Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions src/seclab_taskflow_agent/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# from agents.run import DEFAULT_MAX_TURNS # XXX: this is 10, we need more than that
from agents.exceptions import AgentsException, MaxTurnsExceeded
from agents.extensions.handoff_prompt import prompt_with_handoff_instructions
from agents import Tool, RunContextWrapper, TContext, Agent
from openai import BadRequestError, APITimeoutError, RateLimitError, APIStatusError
from agents.mcp import MCPServerSse, MCPServerStdio, MCPServerStreamableHttp, create_static_tool_filter
from dotenv import find_dotenv, load_dotenv
from openai import APITimeoutError, BadRequestError, RateLimitError
Comment on lines +21 to 25
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate imports were introduced: Agent/RunContextWrapper/TContext/Tool are imported twice (line 15 and 21) and OpenAI exception classes are imported twice (line 22 and 25). Consolidate into a single import per module to avoid lint failures and keep imports maintainable.

Suggested change
from agents import Tool, RunContextWrapper, TContext, Agent
from openai import BadRequestError, APITimeoutError, RateLimitError, APIStatusError
from agents.mcp import MCPServerSse, MCPServerStdio, MCPServerStreamableHttp, create_static_tool_filter
from dotenv import find_dotenv, load_dotenv
from openai import APITimeoutError, BadRequestError, RateLimitError
from openai import BadRequestError, APITimeoutError, RateLimitError, APIStatusError
from agents.mcp import MCPServerSse, MCPServerStdio, MCPServerStreamableHttp, create_static_tool_filter
from dotenv import find_dotenv, load_dotenv

Copilot uses AI. Check for mistakes.
Expand Down Expand Up @@ -350,7 +352,16 @@ async def _run_streamed():
return
except APITimeoutError:
if not max_retry:
logging.exception("Max retries for APITimeoutError reached")
logging.error(f"Max API retries reached")
raise
max_retry -= 1
except APIStatusError as e:
# Retry transient “client closed request / upstream cancelled” style errors
if getattr(e, "status_code", None) != 499:
raise # propagate non-499 errors
# 499: retry
if not max_retry:
logging.error(f"Max API retries reached")
raise
max_retry -= 1
Comment on lines +358 to 366
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new APIStatusError exception handler should be added to the outer exception handling block (lines 361-381) to provide consistent error handling and user feedback. Currently, if a non-499 APIStatusError is raised and propagated from the inner try-except block, it won't be caught by any outer handler, potentially resulting in an unhandled exception. Consider adding an exception handler for APIStatusError similar to the existing handlers for BadRequestError and APITimeoutError.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea probably worth adding a handler in the outer scope like APITimeoutError

Comment on lines +358 to 366
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new APIStatusError retry logic for 499 status codes lacks test coverage. Since the repository includes tests for other functionality (test_api_endpoint_config.py, test_cli_parser.py, test_yaml_parser.py), consider adding tests to verify that 499 errors are properly retried and that non-499 APIStatusErrors are propagated correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +358 to 366
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the APIStatusError(499) retry path, the max-retries case logs with logging.error and re-raises without preserving traceback/context. Consider logging with traceback (or include exception details) before raising so repeated 499 failures are diagnosable.

This issue also appears on line 353 of the same file.

Copilot uses AI. Check for mistakes.
except RateLimitError:
Expand All @@ -377,8 +388,15 @@ async def _run_streamed():
await render_model_output(f"** 🤖❗ Request Error: {e}\n", async_task=async_task, task_id=task_id)
logging.exception("Bad Request")
except APITimeoutError as e:
await render_model_output(f"** 🤖❗ Timeout Error: {e}\n", async_task=async_task, task_id=task_id)
logging.exception("Bad Request")
await render_model_output(f"** 🤖❗ Timeout Error: {e}\n",
async_task=async_task,
task_id=task_id)
logging.error(f"Bad Request: {e}")
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The APITimeoutError outer handler logs Bad Request: {e} even though this is a timeout path. This is misleading when debugging and in logs/telemetry; update the log message to reflect a timeout (and consider logging.exception if you want traceback).

Suggested change
logging.error(f"Bad Request: {e}")
logging.exception("Timeout Error")

Copilot uses AI. Check for mistakes.
except APIStatusError as e:
await render_model_output(f"** 🤖❗ API Status Error: {e}\n",
async_task=async_task,
task_id=task_id)
logging.error(f"API Status Error: Status={e.status_code}, Response={e.response}")
Comment on lines +395 to +399
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The APIStatusError exception handler is placed before the more specific exception types (BadRequestError, APITimeoutError, RateLimitError) in the exception hierarchy. Since these specific exceptions inherit from APIStatusError, this catch block will intercept them before they reach their intended handlers above (lines 372-381). The APIStatusError handler should be moved to the end of the exception chain, after all the more specific handlers.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logging.error(f"API Status Error: Status={e.status_code}, Response={e.response}") logs the full response object, which can be very large and may include sensitive payloads. Prefer logging a minimal, stable subset (e.g., status_code + request id / error type/message) to avoid leaking content and to keep logs bounded.

Suggested change
logging.error(f"API Status Error: Status={e.status_code}, Response={e.response}")
logging.error(
"API Status Error: status=%s, message=%s",
getattr(e, "status_code", "unknown"),
getattr(e, "message", str(e)),
)

Copilot uses AI. Check for mistakes.

if async_task:
await flush_async_output(task_id)
Expand Down