From 9e86dec579a4bc360f89ce418261cfcdbd6b01da Mon Sep 17 00:00:00 2001 From: Ramon Nogueira Date: Tue, 7 Jul 2026 19:47:24 -0400 Subject: [PATCH] feat: add platform issue reporting tool (#1685) Adapted from upstream langchain-ai/open-swe #1685 to the fork's direct-import tool registry. Adds the report_platform_issue tool (stdlib-only: returns a locally generated UUIDv7 report id, no external network call) and wires it into get_agent's curated tool list. Dropped upstream's test_task_retry_wraps_inside_tool_error_middleware assertion, which references ToolRetryMiddleware that this fork does not wire into the middleware stack. (cherry picked from commit 88b62322b44103335773002d0745704cd96e9160) --- agent/server.py | 2 ++ agent/tools/__init__.py | 2 ++ agent/tools/report_platform_issue.py | 16 ++++++++++++++++ tests/test_agent_assembly_context.py | 10 ++++++++++ tests/test_report_platform_issue_tool.py | 20 ++++++++++++++++++++ 5 files changed, 50 insertions(+) create mode 100644 agent/tools/report_platform_issue.py create mode 100644 tests/test_report_platform_issue_tool.py diff --git a/agent/server.py b/agent/server.py index adbdd484..33298a49 100644 --- a/agent/server.py +++ b/agent/server.py @@ -83,6 +83,7 @@ from .tools import ( linear_list_teams, linear_update_issue, open_pull_request, + report_platform_issue, request_pr_review, save_plan, schedule_thread_wakeup, @@ -957,6 +958,7 @@ async def get_agent(config: RunnableConfig) -> Pregel: linear_update_issue, open_pull_request, request_pr_review, + report_platform_issue, schedule_thread_wakeup, slack_read_thread_messages, slack_thread_reply, diff --git a/agent/tools/__init__.py b/agent/tools/__init__.py index ef411c17..2c973847 100644 --- a/agent/tools/__init__.py +++ b/agent/tools/__init__.py @@ -15,6 +15,7 @@ from .open_pull_request import open_pull_request from .publish_review import publish_review from .read_repo_file import read_repo_file from .reply_to_finding_thread import reply_to_finding_thread +from .report_platform_issue import report_platform_issue from .request_pr_review import request_pr_review from .resolve_finding_thread import resolve_finding_thread from .save_plan import save_plan @@ -42,6 +43,7 @@ __all__ = [ "open_pull_request", "publish_review", "read_repo_file", + "report_platform_issue", "request_pr_review", "reply_to_finding_thread", "resolve_finding_thread", diff --git a/agent/tools/report_platform_issue.py b/agent/tools/report_platform_issue.py new file mode 100644 index 00000000..8d5afee9 --- /dev/null +++ b/agent/tools/report_platform_issue.py @@ -0,0 +1,16 @@ +import secrets +import time +import uuid + + +def _uuid7() -> str: + timestamp_ms = (time.time_ns() // 1_000_000) & ((1 << 48) - 1) + rand_a = secrets.randbits(12) + rand_b = secrets.randbits(62) + uuid_int = (timestamp_ms << 80) | (0x7 << 76) | (rand_a << 64) | (0b10 << 62) | rand_b + return str(uuid.UUID(int=uuid_int)) + + +async def report_platform_issue() -> dict[str, str]: + """Report an issue with the sandbox or execution environment.""" + return {"report_id": _uuid7()} diff --git a/tests/test_agent_assembly_context.py b/tests/test_agent_assembly_context.py index 9461ba7b..43668bf5 100644 --- a/tests/test_agent_assembly_context.py +++ b/tests/test_agent_assembly_context.py @@ -111,3 +111,13 @@ async def test_agent_keeps_message_queue_and_step_limit_middleware() -> None: present = {type(m).__name__ for m in middleware} assert "check_message_queue_before_model" in present assert "notify_step_limit_reached" in present + + +@pytest.mark.asyncio +async def test_agent_includes_report_platform_issue_tool() -> None: + from agent.tools import report_platform_issue + + captured = await _capture_create_deep_agent_kwargs() + tools = captured["tools"] + assert isinstance(tools, list) + assert report_platform_issue in tools diff --git a/tests/test_report_platform_issue_tool.py b/tests/test_report_platform_issue_tool.py new file mode 100644 index 00000000..0422ecd3 --- /dev/null +++ b/tests/test_report_platform_issue_tool.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +import uuid + + +async def test_report_platform_issue_returns_uuid7_report_id() -> None: + from agent.tools.report_platform_issue import report_platform_issue + + result = await report_platform_issue() + + assert set(result) == {"report_id"} + report_id = uuid.UUID(result["report_id"]) + assert report_id.version == 7 + assert report_id.variant == uuid.RFC_4122 + + +def test_report_platform_issue_exported() -> None: + from agent.tools import report_platform_issue + + assert callable(report_platform_issue)