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)