monkeybot 3.2.0__tar.gz → 3.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {monkeybot-3.2.0 → monkeybot-3.3.0}/CHANGELOG.md +24 -1
- {monkeybot-3.2.0 → monkeybot-3.3.0}/PKG-INFO +2 -2
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/browser-mcp.md +33 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/features.md +19 -14
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/pyproject.toml +1 -1
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/app.py +8 -9
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/backend.py +33 -2
- monkeybot-3.3.0/integrations/browser-mcp/src/browser_mcp/chat_scope.py +139 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/in_app_cdp.py +5 -0
- monkeybot-3.3.0/integrations/browser-mcp/tests/test_chat_scope.py +276 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/uv.lock +1 -1
- {monkeybot-3.2.0 → monkeybot-3.3.0}/pyproject.toml +2 -2
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/computer/safety.py +35 -7
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/computer/tools.py +8 -1
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/bootstrap.py +9 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/config/runtime_env.py +4 -3
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/config/snapshot.py +2 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/context/__init__.py +30 -2
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/layout.py +23 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/mcp/mcp_client.py +4 -1
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/mcp/ports_mcp.py +2 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/prompts/harness_prompt.py +7 -3
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/realtime_loop.py +10 -2
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/tool_dispatch.py +12 -2
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/subagents/subagent_worker.py +12 -1
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/core_tool_executor.py +115 -64
- monkeybot-3.3.0/src/monkeybot/core/tools/fs_isolation.py +695 -0
- monkeybot-3.3.0/src/monkeybot/core/tools/grant_store.py +259 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/inspector.py +124 -23
- monkeybot-3.3.0/src/monkeybot/core/tools/path_grant_inspector.py +115 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/sandbox_executor.py +39 -6
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/terminal.py +140 -42
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/workspace_service.py +173 -28
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/app.py +1 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/deps.py +2 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/routes.py +2 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/app.py +17 -1
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/computer/test_path_policy.py +16 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_core_tool_executor.py +264 -3
- monkeybot-3.3.0/tests/core/test_fs_isolation.py +650 -0
- monkeybot-3.3.0/tests/core/test_grant_store.py +183 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_inspector.py +32 -2
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_loop.py +106 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_mcp_client.py +12 -1
- monkeybot-3.3.0/tests/core/test_path_grant_inspector.py +230 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_realtime_loop.py +65 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_run_command_parse.py +1 -1
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_terminal.py +183 -0
- monkeybot-3.3.0/tests/core/test_workspace_extra_read_roots.py +253 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/test_deps.py +2 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/sse/test_gateway_runtime.py +1 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/uv.lock +3 -3
- monkeybot-3.2.0/src/monkeybot/core/tools/fs_isolation.py +0 -316
- monkeybot-3.2.0/tests/core/test_fs_isolation.py +0 -242
- {monkeybot-3.2.0 → monkeybot-3.3.0}/.dockerignore +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/.github/workflows/ci.yml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/.github/workflows/live-eval-smoke.yml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/.github/workflows/prepare-release.yml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/.github/workflows/publish-release.yml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/.gitignore +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/.pre-commit-config.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/BACKLOG.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/CONTRIBUTING.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/LICENSE +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/README.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/pyproject.toml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/skills/monkeybot/SKILL.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/skills/monkeybot/references/config-sections.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_file_index.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_local_shell.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_renderer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_session.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_status_bar.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_theme.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_tool_display.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_tui.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/chat_tui_widgets.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/chat.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/doctor.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/loop.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/new.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/refresh.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/run_cmd.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/talk.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/commands/validate.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/compat.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/config_resolve.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/exit_commands.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/extras_catalog.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/gateway_health.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/main.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/opensandbox_lifecycle.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/output.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/process_tree.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/providers.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/audio_io.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/client.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/gateway_manager.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/push_to_talk.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/session.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/session_controller.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/talk_ui.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/realtime/wire_encode.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/runtime_python.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/AGENT.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/Dockerfile +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/browser/SKILL.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/command_allowlist.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/dockerignore +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/env.example +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/image-generator/SKILL.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/image-generator/generate_image.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/loop/SKILL.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/mcp.json +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/monkeybot.example.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/opensandbox.docker.toml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/otel-collector.example.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/scaffold_defaults/permissions.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/session_controller.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/src/monkeybot_cli/terminal_markdown.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_continue.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_e2e.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_errors.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_file_index.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_grounding.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_local_shell.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_renderer_parity.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_session.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_status_bar.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_theme.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_tool_display.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_chat_tui.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_cli.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_config_resolve.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_doctor.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_extras_catalog.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_gateway_health.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_opensandbox_lifecycle.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_realtime_session_controller.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_run_cmd.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_runtime_python.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_scaffold.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/tests/test_terminal_markdown.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/cli/uv.lock +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docker/Dockerfile +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docker/demo-model.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docker/demo.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docker/docker-compose.sandbox.yml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docker/opensandbox.docker.toml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docker/sandbox.Dockerfile +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docker-compose.yml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/agent-layout.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/assets/logo.png +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/browser-mcp-perf-baseline.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/browser-mcp-performance-plan.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/cloud-deployment-design.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/deploy-aws-agentcore.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/deploy-pattern-a-container.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/deploy-pattern-b-serverless.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/deploy-pattern-c-agent-platform.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/deploy-pattern-d-realtime.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/getting-started.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/knowledge-layer-fixes.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/live-evals.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/mcp.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/memory-graph-split-plan.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/migrations/agent-scope-namespacing.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/migrations/memory-outbox.sql +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/observability-runbook.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/ollama-local.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/otel-collector.example.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/progressive-loop-tools.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/progressive-mcp-tools.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/skills.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/spill-dynamic-design.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/sse-gateway-ui.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/verifier-agent-design.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/docs/workspace-index-design.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/TEST_COVERAGE.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/assertions.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/baselines/smoke.json +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/baselines/smoke.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/diff.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/eval_config.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/models.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/persistence.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/report.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/runner.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenario_loader.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/context/summarization_trigger.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/drift/declares_done.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/drift/path_constraint.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/drift/preempt.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/drift/repeat_correction.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/drift/supersession.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/mcp/get_prompt.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/mcp/list_resources.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/mcp/tool_invoke.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/memory/recall_cross_session.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/memory/recall_single_session.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/multi_turn/task_tracking.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/skills/skill_invocation.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/subagents/dispatch_complete.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/tools/core_read.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/tools/core_read_error.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/tools/core_run_command.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/tools/core_run_command_sandbox.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scenarios/tools/core_write.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/scorer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/.env.example +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/.gitignore +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/fixture_mcp_server.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/monkeybot_config/AGENT.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/monkeybot_config/command_allowlist.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/monkeybot_config/mcp.json +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/monkeybot_config/monkeybot.verifier-on.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/monkeybot_config/monkeybot.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/monkeybot_config/permissions.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/pyproject.toml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/skills/browser/SKILL.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/uv.lock +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/workspace/.gitkeep +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/smoke_agent/workspace/skills/browser/playbooks/.gitkeep +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/suites/drift.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/suites/smoke.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/test_assertions.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/test_diff.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/test_judge.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/test_report.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/test_runner_sse.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/evals/test_scorer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/README.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/agentcore/handler.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/agentcore/runtime_app.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/agentengine/handler.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/cloud-functions/main.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/lambda/handler.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/ollama/PrefixStable.Modelfile +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/skills/browser/SKILL.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/skills/browser/playbooks/.gitkeep +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/skills/diagnostics/README.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/skills/diagnostics/SKILL.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/skills/diagnostics/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/skills/diagnostics/diagnostics.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/skills/image-generator/SKILL.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/examples/skills/image-generator/generate_image.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/scripts/agentcore_smoke.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/scripts/dump_tool_surface.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/scripts/perf_bench.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/actions.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/agentcore.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/assets/NOTICE.md +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/assets/dom_tree.js +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/assets/pa_driver.js +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/dom_indexing.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/login.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/observe.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/perf.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/playbooks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/playwright_helpers.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/results.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/screenshots.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/server.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tab_ops.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tabs.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tools/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tools/batch.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tools/capture.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tools/interact.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tools/navigate.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tools/playbook.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tools/read.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/src/browser_mcp/tools/tab_control.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/fixtures/api.json +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/fixtures/article.html +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/fixtures/cards.html +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/fixtures/form.html +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/fixtures/long_list.html +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/fixtures/spa.html +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/fixtures/tool_surface.json +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/integration/conftest.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/integration/test_act_observe.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/integration/test_driver_persist.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/integration/test_intent_tools.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/integration/test_multi_tab.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/integration/test_observation.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/integration/test_run_playbook.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/integration/test_wait_for.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_act.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_agentcore.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_dom_indexing.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_fill_form.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_in_app_cdp.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_indexed_tools.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_observe.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_observe_after.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_perf.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_playbook_flows.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_playbooks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_playwright_helpers.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_screenshots.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_server_shutdown.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_tabs.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_tool_surface.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/integrations/browser-mcp/tests/test_wait_tools.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/pytest.ini +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/scripts/create_schema.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/scripts/precommit-pytest.sh +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/scripts/release.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/scripts/smoke_global_cli.sh +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/cli/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/cli/__main__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/cli/audio_io.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/cli/gateway_manager.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/cli/main.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/cli/push_to_talk.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/cli/realtime_client.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/computer/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/computer/approvals.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/computer/permissions.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/attachments/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/attachments/catalog.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/attachments/config.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/attachments/freeze.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/attachments/resolve.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/attachments/store.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/attachments/text.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/attachments/tools.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/config/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/config/realtime_config.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/config/settings.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/config/validation.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/config/yaml_loader.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/context/campaign_context.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/context/common.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/context/epoch.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/context/secret_egress.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/context/tool_output_policy.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/context/tool_result_ingress.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/context/tool_shapers.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/hooks/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/captions.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/chunking.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/config.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/embeddings/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/embeddings/base.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/embeddings/factory.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/embeddings/gemini.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/embeddings/nvidia.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/embeddings/openai_compat.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/embeddings/sanitize.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/evidence_guard.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/extractors.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/fusion.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/hook.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/indexer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/links.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/salience.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/sqlite_index.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/subsystem.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/tool.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/knowledge/types.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/llm/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/llm/provider.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/llm/realtime_provider.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/llm/usage.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/lockfile_names.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/logging_utils.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/mcp/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/config.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/hook.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/ids.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/ingest.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/migrate_layout.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/observability.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/outbox.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/palace.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/subsystem.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/uri.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/memory/writer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/messages/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/messages/convert_provider.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/messages/tool_integrity.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/messages/transform_context.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/path_safety.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/backends.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/db.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/durable_runs.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/errors.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/firestore.indexes.json +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/firestore.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/firestore_scheduled_loops.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/goal_ledger.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/history.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/postgres.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/runs.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/scheduled_loops.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/session_turn_locks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/sqlite.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/sqlite_backend.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/sqlite_vector.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/thread_summary.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/transcript.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/usage.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/persistence/usage_buckets.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/prompts/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/prompts/headings.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/prompts/prompt.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/context_budget.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/doom_loop.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/events.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/history_compaction.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/input_admission.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/loop.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/loop_hooks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/loop_messages.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/loop_ports.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/loop_usage.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/provider_stream_mapper.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/tool_batch.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/turn_loop.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/runtime/utterance_buffer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/subagents/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/subagents/progress_publish.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/subagents/subagent_proto.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/subagents/worker_pool.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/subprocess_groups.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/testing/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/testing/mocks_provider.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/testing/mocks_realtime_provider.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/loop_inspector.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/patch.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/permission.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/spill_inventory.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/text_normalize.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/tool_hint.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/tool_kind.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/tools/types.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/types/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/types/content_blocks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/types/interfaces.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/types/types_tools.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/actuator.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/classify.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/inspector.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/judge.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/ledger.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/mailbox.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/match.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/port.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/severity.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/verifier/tracker.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/workspace/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/workspace/factory.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/workspace/gcs.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/workspace/local.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/workspace/protocol.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/workspace/s3.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/core/workspace_layout.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/bootstrap.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/main.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/pending_response_bus.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/errors.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/guardrails.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/manager.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/metrics.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/session.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime/wire.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/realtime_main.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/loop_port.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/models.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/reload.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/reply_body.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/routes.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/scheduler_routes.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/scheduler_wiring.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/session_bus.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/sse.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/gateway/sse/workspace_layout.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/observability/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/observability/_state.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/observability/instrumentation.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/observability/propagation.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/observability/spans.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/observability/sqlite_exporter.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/_bedrock_converse.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/_openai_compat.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/_utils.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/bedrock.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/claude.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/gemini.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/gemini_live.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/huggingface.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/model_capabilities.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/nvidia.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/ollama.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/openai.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/openrouter.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/pricing.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/sampling.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/providers/vertex_claude.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/scaffold/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/scheduler/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/scheduler/__main__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/scheduler/engine.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/scheduler/http_invoker.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/scheduler/interval.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/scheduler/tick_result.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/scheduler/worker.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/subagents/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/subagents/worker/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/subagents/worker/__main__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/todo_list/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/todo_list/store.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/todo_list/tool.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/web_search/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/web_search/backends/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/web_search/backends/duckduckgo.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/web_search/backends/firecrawl.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/web_search/backends/tavily.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/web_search/protocol.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/src/monkeybot/web_search/tool.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/acceptance/test_observability_acceptance.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/cli/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/cli/test_gateway_manager.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/cli/test_main.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/cli/test_push_to_talk.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/cli/test_realtime_client.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/computer/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/computer/test_approvals.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/computer/test_computer_tools.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/computer/test_package_init.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/computer/test_permissions.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/computer/test_subagent_exclusion.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/computer/test_wiring.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/conftest.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/fixtures/bitbucket_dc_style_pr.diff +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/memory/helpers.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/memory/in_memory_palace.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/memory/test_mempalace.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/memory/test_review_fixes.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_agent_layout.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_attachment_freeze.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_attachment_store.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_bootstrap.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_config_extensions.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_content_blocks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_context.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_context_budget.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_context_epoch.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_doom_loop.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_durable_events.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_durable_runs.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_empty_completion.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_env_map_grep_gates.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_events.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_evidence_guard.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_firestore_history.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_firestore_scheduled_loops.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_firestore_usage.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_gemini_history_replay.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_goal_ledger.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_harness_prompt.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_history.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_history_compaction_split.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_hooks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_input_admission.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_chunking.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_chunking_rank.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_config.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_embeddings.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_fts.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_fusion.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_fusion_ann.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_hook.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_indexer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_links.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_media.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_salience.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_single_writer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_subsystem.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_knowledge_vectors.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_layout.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_logging_utils.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_loop_hooks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_loop_observability.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_loop_transcript.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_memory_layout_migrate.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_message_pipeline.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_mocks_realtime_provider.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_patch.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_path_safety.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_permission.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_pricing.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_progress_publish.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_progress_tracker.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_prompt.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_provider_contract.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_provider_stream_mapper.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_replace_fuzzy.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_runs.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_runtime_config_snapshot.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_runtime_env.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_sandbox_executor.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_scheduled_loops.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_secret_egress.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_session_turn_locks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_settlement.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_spill_dynamic.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_spill_inventory.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_storage_backends.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_subagent_proto.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_subagent_trace_propagation.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_subagent_worker_paths.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_thread_summary_wire.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_tool_def_schema.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_tool_integrity.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_tool_result_ingress.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_tool_shapers.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_transcript.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_truncated_tool_batch.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_usage.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_usage_migration.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_utterance_buffer.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_verifier_inspector.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_verifier_judge.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_worker_pool.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_workspace_layout.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_workspace_symlinks.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/test_workspace_write_scope.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/workspace/test_factory.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/workspace/test_local_storage.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/core/workspace/test_protocol_contract.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/eval_hook.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenario_runner.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/memory_wake_up_large.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/memory_write_inject.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/subagent_roundtrip.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_glob_grep.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_load_file.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_loops.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_read.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_replace_apply_patch.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_run_command.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_search_knowledge.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_search_memory.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_todo_list.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_web_search.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/tool_write.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/scenarios/turn_completion.yaml +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/test_agent_behavior.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/test_memory_knowledge_routing.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/evals/test_verifier_port.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/test_app.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/test_guardrails.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/test_manager.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/test_metrics.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/test_routes_client_text.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/test_session.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/realtime/test_wire.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/sse/test_attachments.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/sse/test_config_reload.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/sse/test_create_session_model.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/sse/test_routes.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/sse/test_scheduler_routes.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/sse/test_session_bus.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/sse/test_transcript_wiring.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/test_otel_fastapi.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/test_otel_lifespan.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/test_pending_response_endpoints.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/test_realtime_main.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/test_resolve_provider.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/test_sse_events.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/gateway/test_subagent_event_publisher.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/integration/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/integration/test_mb_e2e_simple_reply.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/integration/test_observability_integration.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/integration/test_prompt_caching_integration.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/conftest.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_init.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_instrumentation.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_loop_hook_spans.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_propagation.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_span_contract.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_spans.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_sqlite_exporter.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_truncate.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/observability/test_turn_complete_trace.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/conftest.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_anthropic_cache.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_anthropic_history.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_bedrock_converse.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_bedrock_estimate.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_gemini_history.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_gemini_live.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_gemini_usage.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_huggingface.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_model_capabilities.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_nvidia.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_ollama.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_openai_compat_usage.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_openai_history.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_pricing.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_safe_parse_tool_args.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_sampling.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_sonnet5_sampling.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_source_grep_gates.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/providers/test_vertex_claude_history.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/scheduler/test_engine.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/scheduler/test_interval.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/skills/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/skills/test_generate_image_script.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/test_cold_start.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/test_packaging_config.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/test_release_script.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/todo_list/test_todo_list.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/web_search/__init__.py +0 -0
- {monkeybot-3.2.0 → monkeybot-3.3.0}/tests/web_search/test_web_search.py +0 -0
|
@@ -6,7 +6,30 @@ the project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## [browser v0.7.0] - 2026-09-10
|
|
10
|
+
|
|
11
|
+
#### Added
|
|
12
|
+
|
|
13
|
+
- Announces the chat it is acting for to the Spaces in-app bridge (`Monkeybot.setChatScope`) so tabs stay attached to their chat; silently no-op on older apps.
|
|
14
|
+
|
|
15
|
+
#### Fixed
|
|
16
|
+
|
|
17
|
+
- Chat-switch tab drop now fires on real tool calls (`browser_harness()` reuse no longer forgets the last scoped chat).
|
|
18
|
+
|
|
19
|
+
## [core v3.3.0] - 2026-09-11
|
|
20
|
+
|
|
21
|
+
### Breaking
|
|
22
|
+
|
|
23
|
+
- `run_command` now runs inside a deny-by-default OS filesystem jail (macOS `sandbox-exec`; Linux mount-namespace, unvalidated on a real host as part of this change) on top of the existing binary/path allowlist. The user's home directory is denied by default; the workspace, artifacts, memory palace, and OS temp dirs stay read+write, and skills/the interpreter prefix/granted folders stay read-only, including when they sit inside the denied home directory (the normal case for a desktop app). This closes a real gap: the old argv-string path screen never caught indirect path expressions a shell or interpreter builds at runtime (`bash -c 'cp "$HOME/Desktop/x" .'`, or a Python `os.path.expanduser(...)` call), so a command that depended on reading/writing somewhere under `$HOME` outside the workspace — by accident or on purpose — will now fail where it previously succeeded. `git` keeps working via a narrow, explicit `~/.gitconfig`/`~/.config/git/ignore` read carve-out (needed even for `--version`); `gh` does not — its own auth config is credential-adjacent and is not carved out, matching the credential-path denylist already established for `computer_*` tools. If the OS jail mechanism itself is unavailable on a host (older kernels without unprivileged user namespaces, some hardened/CI Linux configs), `run_command` falls back to running **unconfined** (logged once, not per call) rather than refusing every command — a deliberate difference from the existing memory-off hide mechanism, which still fails closed, since this is default-on hardening for every deployment rather than a narrow, deliberate opt-out.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- MCP tool calls now carry `_meta.monkeybot` (`thread_id`, `request_id`, `run_id`) so servers can attribute work to a chat. Requires `mcp>=1.27.1` so `ClientSession.call_tool(meta=)` is always available.
|
|
28
|
+
- **Command grants:** an unlisted `run_command` binary now surfaces a "Needs your OK" approval card (`Decision.grant_key`/`grant_kind` on `CommandTierInspector`) instead of silently falling through to a hard `SecurityError` at the executor. "Allow once" covers the rest of the turn; "Always allow" writes a durable rule to a new home-level store, `grants.json` (`core/tools/grant_store.py`), shared by every agent on the machine — deliberately separate from the per-agent, `computer_*`-only `approvals.json`. Same on-disk contract (JSON, `0600`, atomic replace, cross-process exclusive-create locking matched with the Electron side).
|
|
29
|
+
- **Folder read grants:** `read_file`/`load_file`/`glob`/`grep` on an absolute path outside the workspace now ask via a new `PathGrantInspector` rather than rejecting outright — denying credential paths and anything outside `$HOME` hard, never promotable. An approved folder is read in place through `WorkspaceFileService.extra_read_roots` (symlink-escape-protected, read-only — never widens what `write_file`/`replace_in_file` can touch); the same granted folders feed the `run_command` jail's read-only set so the shell tool and the file tools agree on what's reachable. Fixes the failure mode where the model, unable to read a file outside its workspace and told only "use a relative path," would narrate copying the file into the workspace to route around the boundary — tool descriptions, the harness prompt, and the `workspace_error_envelope` hint for this case now say to ask for access instead, explicitly calling relocating-to-route-around-the-boundary a policy violation.
|
|
30
|
+
- Settings → Privacy & access gained **Allowed commands** and **Folder access** sections listing/revoking these new grants, alongside the existing per-agent `computer_*` rules.
|
|
31
|
+
|
|
32
|
+
## [browser v0.6.0] - 2026-09-07
|
|
10
33
|
|
|
11
34
|
#### Added
|
|
12
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: monkeybot
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: monkeybot agent harness — FastAPI SSE gateway, owned loop, SQLite, and MCP.
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -9,7 +9,7 @@ Requires-Dist: aiosqlite>=0.20.0
|
|
|
9
9
|
Requires-Dist: fastapi>=0.115.0
|
|
10
10
|
Requires-Dist: google-genai>=1.0.0
|
|
11
11
|
Requires-Dist: httpx>=0.27.0
|
|
12
|
-
Requires-Dist: mcp<2,>=1.
|
|
12
|
+
Requires-Dist: mcp<2,>=1.27.1
|
|
13
13
|
Requires-Dist: numpy<2.5,>=1.26.0
|
|
14
14
|
Requires-Dist: pydantic>=2.10.0
|
|
15
15
|
Requires-Dist: python-dotenv>=1.0.0
|
|
@@ -189,6 +189,39 @@ other ephemeral-workspace targets they reset when the instance is recycled. Use
|
|
|
189
189
|
the memory storage contract for durable knowledge rather than adding a workspace
|
|
190
190
|
synchronization layer.
|
|
191
191
|
|
|
192
|
+
## In-app bridge extensions
|
|
193
|
+
|
|
194
|
+
When the Spaces in-app browser is bound, each tool call may announce which chat
|
|
195
|
+
it is acting for so new tabs stay attached to that chat. AgentCore and Browser
|
|
196
|
+
Use Cloud backends never send this.
|
|
197
|
+
|
|
198
|
+
### MCP request meta
|
|
199
|
+
|
|
200
|
+
The gateway includes `_meta` on every `call_tool`:
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{ "monkeybot": { "thread_id": "<gateway thread id>", "request_id": "<turn request id>", "run_id": "<MONKEYBOT_RUN_ID or null>" } }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Servers that ignore `_meta` are unaffected. Older gateways send nothing; this
|
|
207
|
+
server then announces `chatKey` as `null`.
|
|
208
|
+
|
|
209
|
+
### `Monkeybot.setChatScope`
|
|
210
|
+
|
|
211
|
+
On every in-app tool call, after the harness binds and before other CDP
|
|
212
|
+
commands, the backend sends:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{ "id": 7, "method": "Monkeybot.setChatScope", "params": { "chatKey": "<thread_id or null>" } }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
`chatKey` is the gateway `thread_id` from `_meta.monkeybot`, which equals the
|
|
219
|
+
app's session ID. The bridge stores it on the WebSocket client until changed. An
|
|
220
|
+
older app replies with an error; this server treats that as unsupported, stops
|
|
221
|
+
sending the method for the rest of the connection, and continues normally.
|
|
222
|
+
Rebinding the in-app daemon (including after Spaces `warmBrowserOnLaunch`)
|
|
223
|
+
clears that disabled flag so a newer app gets a fresh attempt.
|
|
224
|
+
|
|
192
225
|
## Tools
|
|
193
226
|
|
|
194
227
|
Navigation, interaction, screenshots, tabs, waits, playbooks (`browser_list_playbooks`, `browser_read_playbook`, `browser_write_playbook`, `browser_run_playbook`), `browser_login` for Spaces-saved passwords (returns `{ok, loggedIn, origin, mfa?, mode?}` — never the password), and `browser_stop` for daemon cleanup.
|
|
@@ -259,20 +259,20 @@ Each section follows: **Purpose** · **Key files** · **How it works** · **Depe
|
|
|
259
259
|
|
|
260
260
|
**Purpose:** Default `ToolExecutorPort` — built-ins, MCP, custom tools, subagents.
|
|
261
261
|
|
|
262
|
-
**Key files:** `core/tools/core_tool_executor.py`, `terminal.py`, `workspace_service.py`, `patch.py`, `sandbox_executor.py`, `spill_inventory.py`
|
|
262
|
+
**Key files:** `core/tools/core_tool_executor.py`, `terminal.py`, `workspace_service.py`, `patch.py`, `sandbox_executor.py`, `spill_inventory.py`, `fs_isolation.py`, `grant_store.py`
|
|
263
263
|
|
|
264
264
|
**Built-in tools** (from `context._core_tool_defs`):
|
|
265
265
|
|
|
266
266
|
| Tool | Role |
|
|
267
267
|
|------|------|
|
|
268
|
-
| `read_file` / `write_file` | `skills/...` read-only or workspace-relative paths |
|
|
268
|
+
| `read_file` / `write_file` | `skills/...` read-only or workspace-relative paths; `read_file`/`load_file` also accept an absolute path outside the workspace once the user grants that folder (see §5) — read in place, never copied in |
|
|
269
269
|
| `replace_in_file` | Unique (or `replace_all`) substring edit; exact then light fuzzy match |
|
|
270
|
-
| `glob` / `grep` | Path discovery / content regex search (prefer over shell) |
|
|
270
|
+
| `glob` / `grep` | Path discovery / content regex search (prefer over shell); `root` accepts a granted external folder the same way `read_file` does |
|
|
271
271
|
| `apply_patch` | Multi-file Codex-style Add/Update/Delete/Move; fail-closed before any write |
|
|
272
272
|
| `search_memory` | Keyword search in memory tree |
|
|
273
273
|
| `search` / `recall` | Local knowledge index (workspace + notes); **parallel-safe**. Gateway owns writes; subagents open the index **read-only**. Harness-as-library (Pattern B/C) callers can opt into read-only via `MONKEYBOT_KNOWLEDGE_READ_ONLY=1`; the gateway always ignores this flag and stays the writer |
|
|
274
274
|
| `list_skills` | Skill discovery |
|
|
275
|
-
| `run_command` | Allowlisted shell (host or OpenSandbox) |
|
|
275
|
+
| `run_command` | Allowlisted **and OS-confined** shell (host or OpenSandbox) — see the workspace jail below |
|
|
276
276
|
| `task` | Subagent subprocess (parent only) |
|
|
277
277
|
| `enable_mcp` / `disable_mcp` | Catalog connect / disconnect (success includes status) |
|
|
278
278
|
| `enable_loops` | Progressive advertise scheduled-loop tools |
|
|
@@ -296,6 +296,8 @@ Each section follows: **Purpose** · **Key files** · **How it works** · **Depe
|
|
|
296
296
|
- Nested `task` disabled inside subagents.
|
|
297
297
|
- Custom tools must not collide with core or MCP names.
|
|
298
298
|
- `MONKEYBOT_KNOWLEDGE_READ_ONLY` (default off) opens the knowledge index read-only for `create_harness_deps` (Pattern B/C) callers; subagent workers are always read-only regardless of the flag. The gateway SSE app is the sole writer per workspace and ignores this flag, logging a warning if it is set.
|
|
299
|
+
- **The workspace jail:** `run_command` runs under a deny-by-default OS filesystem policy (`fs_isolation.py::JailRoots`/`jailed_argv`), not just the `allowed_path_prefixes` argv screen (which a shell or interpreter defeats trivially — `bash -c 'cp "$HOME/Desktop/x" .'` never contains a literal `~`/`/` token an argv scanner can catch). The jail denies the user's home directory by default, then allows the workspace/artifacts/memory-palace/OS-temp-dirs back on top (read+write) and skills/interpreter-prefix/granted folders (read-only) — including when those sit inside the denied home directory, the normal case for a desktop app. Implemented for macOS `sandbox-exec`; the Linux mount-namespace path follows the same structure but is unvalidated on a real Linux host — both fail *closed* (refuse to run) if the OS mechanism can't be established, except that the jail itself (unlike the older memory-hide mechanism) fails *open*, once, with a logged warning, if neither OS mechanism is available at all — a default-on hardening that must not turn into "run_command stops working" on unsupported hosts.
|
|
300
|
+
- **Folder read grants:** `read_file`/`load_file`/`glob`/`grep` on an absolute path outside the workspace ask via `PathGrantInspector` (§5) rather than dead-ending; an approved folder is read in place through `WorkspaceFileService.extra_read_roots` — nothing is copied into the workspace, and the same granted folders feed the jail's read-only set above so `run_command` and the file tools agree on what's reachable.
|
|
299
301
|
|
|
300
302
|
---
|
|
301
303
|
|
|
@@ -303,13 +305,14 @@ Each section follows: **Purpose** · **Key files** · **How it works** · **Depe
|
|
|
303
305
|
|
|
304
306
|
**Purpose:** Pre-flight policy gates; supports user confirmation via SSE.
|
|
305
307
|
|
|
306
|
-
**Key files:** `core/tools/inspector.py`, `core/tools/permission.py`, `core/tools/loop_inspector.py`
|
|
308
|
+
**Key files:** `core/tools/inspector.py`, `core/tools/permission.py`, `core/tools/loop_inspector.py`, `core/tools/path_grant_inspector.py`, `core/tools/grant_store.py`
|
|
307
309
|
|
|
308
310
|
**Inspectors wired at gateway startup (order matters — first deny/confirm wins):**
|
|
309
|
-
1. `CommandTierInspector` — `command_allowlist.yaml` deny-regex preflight
|
|
310
|
-
2. `
|
|
311
|
-
3. `
|
|
312
|
-
4. `
|
|
311
|
+
1. `CommandTierInspector` — `command_allowlist.yaml` deny-regex preflight (hard, never promotable), then a binary allow/ask gate: a binary already on the static allowlist, in `grants.json`, or granted "Allow once" earlier this turn is allowed and the chain continues (`permissions.yaml` can still ask/deny a finer-grained pattern on top, unchanged); any other binary asks (`confirm`, carrying `grant_key`=the binary) instead of silently falling through to a hard rejection at the executor
|
|
312
|
+
2. `PathGrantInspector` — for `read_file`/`load_file`/`glob`/`grep`, an absolute/`~` path inside the workspace is a no-op (allow); on the credential denylist or outside `$HOME` it's a hard deny; already covered by a `grants.json`/turn-scoped folder grant it's allow; otherwise it asks (`confirm`, `grant_key`=the containing folder, `grant_kind="path"`)
|
|
313
|
+
3. `RulesInspector` — `MONKEYBOT_TOOL_DENIED_PATTERNS` substring deny list (backward compat)
|
|
314
|
+
4. `PermissionInspector` — `permissions.yaml` last-match-wins `allow` / `ask` / `deny` ruleset (`PERMISSION_CONFIG`)
|
|
315
|
+
5. `LoopStartInspector` — `start_loop` always asks for confirmation (rich plan preview)
|
|
313
316
|
|
|
314
317
|
**Permission ruleset (`permissions.yaml`):**
|
|
315
318
|
- Rules are ordered; **last match wins** (OpenCode-style).
|
|
@@ -318,15 +321,17 @@ Each section follows: **Purpose** · **Key files** · **How it works** · **Depe
|
|
|
318
321
|
- `default:` applies when nothing matches (shipped default: `allow`).
|
|
319
322
|
- Session approvals: POST tool-confirmation with `{approved: true, always: true}` remembers tool+resource for the rest of the session (`SessionBus.session_approvals`).
|
|
320
323
|
|
|
321
|
-
**Decision kinds:** `allow` | `deny` | `confirm` (requires `ctx.sse_bus` for pending UI response).
|
|
324
|
+
**Decision kinds:** `allow` | `deny` | `confirm` (requires `ctx.sse_bus` for pending UI response). A `confirm` may carry `grant_key`/`grant_kind` (`"command"` | `"path"`) — what an "Allow once"/"Always allow" click actually remembers (a binary name or a folder, never the full resource string `resource_for_call()` would otherwise use, which would make a durable rule cover exactly one invocation). `tool_dispatch.py` routes an "always" approval to `ctx.grants_persist` (writing `grants.json`, shared by every agent) when `grant_kind` is set, instead of the `computer_*`-only `ctx.approvals_persist`; either way, "Allow once" also records the grant on `ctx.turn_command_grants`/`ctx.turn_path_grants` so a repeat call later in the same turn does not ask again even without a durable write.
|
|
322
325
|
|
|
323
|
-
|
|
326
|
+
**`grants.json`** (`core/tools/grant_store.py`) is a home-level store — one file shared by every agent on the machine, deliberately distinct from the per-agent, `computer_*`-only `approvals.json` (§21). Same on-disk contract: JSON, mode `0600`, atomic replace, cross-process exclusive-create locking matched byte-for-byte with the Electron side (`electron/main/grants.ts`).
|
|
327
|
+
|
|
328
|
+
**Hard constraints underneath soft asks:** `allowed_commands` / `allowed_path_prefixes` + sandbox still enforce at execution time — permission `ask`/`allow` cannot bypass them. Beyond the argv allowlist, `run_command` additionally runs inside a deny-by-default OS filesystem jail (§4) that a shell/interpreter cannot argue its way around by rewriting a path.
|
|
324
329
|
|
|
325
330
|
**Invariants:**
|
|
326
331
|
- Missing allowlist file → tier inspector skipped (logged); executor falls back to code defaults.
|
|
327
332
|
- Missing `permissions.yaml` → soft ruleset disabled (logged).
|
|
328
|
-
- Default deny patterns block package installs (`pip install`, `npm install`, etc.).
|
|
329
|
-
- Confirm without `sse_bus` → deny.
|
|
333
|
+
- Default deny patterns block package installs (`pip install`, `npm install`, etc.) and are never promotable to a confirm by any grant.
|
|
334
|
+
- Confirm without `sse_bus` → deny (this is why a subagent, which has no interactive session, can use an already-durably-granted command/folder transparently but can never ask for a new one).
|
|
330
335
|
|
|
331
336
|
---
|
|
332
337
|
|
|
@@ -652,7 +657,7 @@ Before spawning the gateway, the CLI probes that interpreter for MonkeyBot `>=3.
|
|
|
652
657
|
|
|
653
658
|
**How it works:**
|
|
654
659
|
- Off by default, macOS-only: `computer.enabled: true` in `monkeybot.yaml` → `MONKEYBOT_COMPUTER_TOOLS` env, combined with a hard `sys.platform == "darwin"` check (`should_enable_computer_tools()`). The desktop app sets the env var when it spawns a gateway with the feature turned on in Settings; no other deployment should ever set it.
|
|
655
|
-
- **Hard security boundary lives in the tool bodies, not in `permissions.yaml`** (`safety.py`): every path is resolved and validated against the user's home directory after following symlinks; a fixed denylist blocks credential directories (`.ssh`, `.aws`, keychains, browser profiles, the app's own config) both at their canonical location *and* by directory-name anywhere in the tree; filenames matching credential patterns (`.env`, `*.pem`, `id_rsa*`, …) are always refused; `computer_open` refuses any path/app that would make `open` execute code (`.command`, `.app`, `.sh`, Terminal, script editors, …); trash never hard-deletes. `permissions.yaml` is fail-open (a broken file silently disables it), so none of this can depend on it.
|
|
660
|
+
- **Hard security boundary lives in the tool bodies, not in `permissions.yaml`** (`safety.py`): every path is resolved and validated against the user's home directory after following symlinks; a fixed denylist blocks credential directories (`.ssh`, `.aws`, keychains, browser profiles, the app's own config) both at their canonical location *and* by directory-name anywhere in the tree; filenames matching credential patterns (`.env`, `*.pem`, `id_rsa*`, …) are always refused; `computer_open` refuses any path/app that would make `open` execute code (`.command`, `.app`, `.sh`, Terminal, script editors, …); trash never hard-deletes. `permissions.yaml` is fail-open (a broken file silently disables it), so none of this can depend on it. `_denied_dirs()` also always includes `MONKEYBOT_WORKSPACE_ROOT` (not only under `MONKEYBOT_APP_HOME`, which only the desktop app sets) — a CLI-scaffolded agent's workspace can sit anywhere under `$HOME` the user chose, and `computer_move`/`computer_trash` must not be able to relocate a file straight into or out of it, one click away from smuggling exactly what the workspace boundary (§4) exists to prevent. `computer_move`'s own description now says so, so the model doesn't reach for it as a `read_file`/`run_command` workaround.
|
|
656
661
|
- **Every `computer_*` call asks by default**, via a built-in baseline rule (`COMPUTER_BASELINE_RULES` in `permissions.py`) — not a line in `permissions.yaml`, so it can't be silently defeated by a missing/broken config file. `ComputerAwarePermissionInspector` layers, last-match-wins: baseline `ask` < durable approvals overlay `allow` < the user's `permissions.yaml` (highest authority — a hand-written `deny` always wins).
|
|
657
662
|
- **"Always allow" is durable and narrow**: `monkeybot_config/approvals.json` (machine-written, JSON — deliberately *not* appended into `permissions.yaml`, which is a comment-heavy file the app's Advanced settings save wholesale) stores one exact `(tool, resource)` pair per rule. Mutating tools (`computer_move`, `computer_trash`) are excluded from `ALWAYS_SCOPE` — their resource is the *source* path only, so an "always" rule would cover any destination — every call to them asks. The inspector re-`stat`s the overlay file on every check and reloads on change; on a genuine change it also clears the session-level approval cache, so a revoke in the app's Settings takes effect immediately rather than waiting for a gateway restart.
|
|
658
663
|
- Registered via the standard `extra_tools` extension point in both the SSE (`gateway/sse/app.py`) and realtime (`gateway/realtime/routes.py`) gateways — same mechanism as `web_search`/`todo_list`. Never registered for subagents (`subagent_worker.py` builds its own `extra_tools` independently and never imports this package).
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "monkeybot-browser-mcp"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.0"
|
|
8
8
|
description = "monkeybot MCP server wrapping browser-harness for real-browser control and site playbooks."
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
dependencies = [
|
|
@@ -93,15 +93,14 @@ def _public_tool(fn: Callable[_P, str]) -> Callable[_P, str]:
|
|
|
93
93
|
|
|
94
94
|
@functools.wraps(fn)
|
|
95
95
|
def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> str:
|
|
96
|
-
with _TOOL_LOCK:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
in_app_cdp._reraise_public_harness_error(exc)
|
|
96
|
+
with _TOOL_LOCK, perf.timed_tool(fn.__name__) as rec:
|
|
97
|
+
try:
|
|
98
|
+
result = fn(*args, **kwargs)
|
|
99
|
+
rec.observe(result)
|
|
100
|
+
return result
|
|
101
|
+
except Exception as exc:
|
|
102
|
+
rec.fail()
|
|
103
|
+
in_app_cdp._reraise_public_harness_error(exc)
|
|
105
104
|
|
|
106
105
|
# FastMCP copies fn.__doc__ as-is (not inspect.getdoc), so without this the
|
|
107
106
|
# model sees the 4-space body indent from the source. @mcp.tool() wraps
|
|
@@ -6,7 +6,7 @@ import contextlib
|
|
|
6
6
|
import logging
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
-
from browser_mcp import agentcore, dom_indexing, in_app_cdp, perf, tabs
|
|
9
|
+
from browser_mcp import agentcore, chat_scope, dom_indexing, in_app_cdp, perf, tabs
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
@@ -23,6 +23,24 @@ def mark_unbound() -> None:
|
|
|
23
23
|
_bound_cdp = None
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def in_app_backend_active() -> bool:
|
|
27
|
+
"""True when the live binding is Monkeyapp's in-app CDP bridge."""
|
|
28
|
+
return (
|
|
29
|
+
_bh is not None
|
|
30
|
+
and _bound_cdp not in (None, "agentcore")
|
|
31
|
+
and in_app_cdp._env_set_from_in_app_file
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def in_app_helpers() -> Any | None:
|
|
36
|
+
"""Return in-app CDP helpers when the in-app backend is bound, else None."""
|
|
37
|
+
if not in_app_backend_active():
|
|
38
|
+
return None
|
|
39
|
+
assert _bh is not None
|
|
40
|
+
helpers, _ = _bh
|
|
41
|
+
return helpers
|
|
42
|
+
|
|
43
|
+
|
|
26
44
|
def teardown_bound_backend() -> None:
|
|
27
45
|
"""Tear down whatever backend _bh is currently bound to, if any.
|
|
28
46
|
|
|
@@ -42,6 +60,7 @@ def teardown_bound_backend() -> None:
|
|
|
42
60
|
tabs.registry().detach_all(helpers)
|
|
43
61
|
_bh = None
|
|
44
62
|
dom_indexing.clear_registered_targets()
|
|
63
|
+
chat_scope.reset()
|
|
45
64
|
if is_agentcore:
|
|
46
65
|
admin.stop_session()
|
|
47
66
|
from browser_mcp import playwright_helpers
|
|
@@ -58,6 +77,12 @@ def _with_perf_helpers(bh: tuple[Any, Any]) -> tuple[Any, Any]:
|
|
|
58
77
|
return perf.wrap_helpers(helpers), admin
|
|
59
78
|
|
|
60
79
|
|
|
80
|
+
def _announce_in_app(helpers: Any) -> None:
|
|
81
|
+
"""Scope the in-app bridge after bind. Playbook/login skip this by not binding."""
|
|
82
|
+
if in_app_cdp._env_set_from_in_app_file:
|
|
83
|
+
chat_scope.announce_current(helpers)
|
|
84
|
+
|
|
85
|
+
|
|
61
86
|
def _reconnect_agentcore() -> tuple[str, dict[str, str]]:
|
|
62
87
|
"""Force a fresh AgentCore session (stop + restart) and return new ws creds.
|
|
63
88
|
|
|
@@ -105,7 +130,9 @@ def browser_harness() -> tuple[Any, Any]:
|
|
|
105
130
|
return _with_perf_helpers(_agentcore_browser_harness())
|
|
106
131
|
|
|
107
132
|
if _bh is not None and cdp == _bound_cdp:
|
|
108
|
-
|
|
133
|
+
wrapped = _with_perf_helpers(_bh)
|
|
134
|
+
_announce_in_app(wrapped[0])
|
|
135
|
+
return wrapped
|
|
109
136
|
|
|
110
137
|
if _bound_cdp == "agentcore":
|
|
111
138
|
teardown_bound_backend()
|
|
@@ -126,6 +153,9 @@ def browser_harness() -> tuple[Any, Any]:
|
|
|
126
153
|
admin.ensure_daemon()
|
|
127
154
|
_bh = (helpers, admin)
|
|
128
155
|
_bound_cdp = cdp
|
|
156
|
+
if in_app_cdp._env_set_from_in_app_file:
|
|
157
|
+
chat_scope.reset()
|
|
158
|
+
_announce_in_app(helpers)
|
|
129
159
|
return _with_perf_helpers(_bh)
|
|
130
160
|
|
|
131
161
|
|
|
@@ -153,6 +183,7 @@ def stop_active_backend_best_effort() -> None:
|
|
|
153
183
|
with contextlib.suppress(Exception):
|
|
154
184
|
tab_ops._close_agent_opened_tabs(helpers)
|
|
155
185
|
_bh = None
|
|
186
|
+
chat_scope.reset()
|
|
156
187
|
from browser_harness import admin
|
|
157
188
|
|
|
158
189
|
admin.restart_daemon()
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Chat identity for the Spaces in-app CDP bridge.
|
|
2
|
+
|
|
3
|
+
The gateway may pass ``_meta.monkeybot.thread_id`` on each MCP tool call.
|
|
4
|
+
When driving the in-app browser, we announce that id as ``Monkeybot.setChatScope``
|
|
5
|
+
before other CDP commands so new tabs attach to the right chat.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
import re
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
# JSON-RPC "Method not found" — Chrome's reply when the app has no setChatScope.
|
|
17
|
+
_JSONRPC_METHOD_NOT_FOUND = -32601
|
|
18
|
+
_CDP_ERROR_CODE_RE = re.compile(r"""['"]code['"]\s*:\s*(-?\d+)""")
|
|
19
|
+
|
|
20
|
+
_UNSET: object = object()
|
|
21
|
+
_last_chat: object = _UNSET
|
|
22
|
+
_unsupported: bool = False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def reset() -> None:
|
|
26
|
+
"""Clear last-chat / unsupported flags after a daemon (re)bind."""
|
|
27
|
+
global _last_chat, _unsupported
|
|
28
|
+
_last_chat = _UNSET
|
|
29
|
+
_unsupported = False
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def current_thread_id() -> str | None:
|
|
33
|
+
"""Return the gateway thread id from this request's ``_meta``, if any.
|
|
34
|
+
|
|
35
|
+
Never raises. Returns ``None`` outside a request or when the extra is absent.
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
from browser_mcp.app import mcp
|
|
39
|
+
|
|
40
|
+
ctx = mcp.get_context()
|
|
41
|
+
meta = getattr(getattr(ctx, "request_context", None), "meta", None)
|
|
42
|
+
return _thread_id_from_meta(meta)
|
|
43
|
+
except LookupError:
|
|
44
|
+
return None
|
|
45
|
+
except Exception:
|
|
46
|
+
logger.debug("browser-mcp: current_thread_id failed", exc_info=True)
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _thread_id_from_meta(meta: object) -> str | None:
|
|
51
|
+
"""Read ``monkeybot.thread_id`` from FastMCP's pydantic ``RequestParams.Meta``."""
|
|
52
|
+
if meta is None:
|
|
53
|
+
return None
|
|
54
|
+
monkeybot: Any = getattr(meta, "monkeybot", None)
|
|
55
|
+
if not isinstance(monkeybot, dict):
|
|
56
|
+
return None
|
|
57
|
+
thread_id = monkeybot.get("thread_id")
|
|
58
|
+
if thread_id is None:
|
|
59
|
+
return None
|
|
60
|
+
text = str(thread_id).strip()
|
|
61
|
+
return text or None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _forget_other_chat_tabs() -> None:
|
|
65
|
+
"""Drop this process's tab registry: those targets belong to the chat we left.
|
|
66
|
+
|
|
67
|
+
Spaces owns the previous chat's tabs and keeps them in that chat's panel.
|
|
68
|
+
Forgetting ``opened_by_agent`` here is intentional: ``browser_stop`` in the
|
|
69
|
+
new chat must not close the previous chat's tabs.
|
|
70
|
+
"""
|
|
71
|
+
from browser_mcp import tabs
|
|
72
|
+
|
|
73
|
+
tabs.reset_registry()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _cdp_error_code(exc: BaseException) -> int | None:
|
|
77
|
+
"""Best-effort CDP/JSON-RPC error code from a harness ``RuntimeError``."""
|
|
78
|
+
payload = exc.args[0] if exc.args else None
|
|
79
|
+
if isinstance(payload, dict):
|
|
80
|
+
code = payload.get("code")
|
|
81
|
+
if isinstance(code, int):
|
|
82
|
+
return code
|
|
83
|
+
match = _CDP_ERROR_CODE_RE.search(str(exc))
|
|
84
|
+
if match:
|
|
85
|
+
return int(match.group(1))
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _looks_like_unknown_method(exc: BaseException) -> bool:
|
|
90
|
+
if _cdp_error_code(exc) == _JSONRPC_METHOD_NOT_FOUND:
|
|
91
|
+
return True
|
|
92
|
+
text = str(exc).lower()
|
|
93
|
+
return "unknown method" in text or "method not found" in text
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def announce_current(helpers: object) -> None:
|
|
97
|
+
"""Announce this request's thread id. Never raises."""
|
|
98
|
+
announce(helpers, current_thread_id())
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def announce(helpers: object, thread_id: str | None) -> None:
|
|
102
|
+
"""Send ``Monkeybot.setChatScope`` for this request. Never raises.
|
|
103
|
+
|
|
104
|
+
CDP is sent on every call (idempotent) so a reconnected WebSocket still gets
|
|
105
|
+
``chatKey``. The tab registry is dropped only when the non-None thread id
|
|
106
|
+
changes. ``_last_chat`` is updated even when the app does not support the
|
|
107
|
+
method, so a chat switch still drops tabs owned by the previous chat.
|
|
108
|
+
"""
|
|
109
|
+
global _last_chat, _unsupported
|
|
110
|
+
previous = _last_chat
|
|
111
|
+
switched = (
|
|
112
|
+
thread_id is not None and previous is not _UNSET and previous != thread_id
|
|
113
|
+
)
|
|
114
|
+
if thread_id is not None:
|
|
115
|
+
_last_chat = thread_id
|
|
116
|
+
if switched:
|
|
117
|
+
_forget_other_chat_tabs()
|
|
118
|
+
logger.info(
|
|
119
|
+
"browser-mcp: chat scope changed %s -> %s; dropping tabs",
|
|
120
|
+
previous,
|
|
121
|
+
thread_id,
|
|
122
|
+
)
|
|
123
|
+
if _unsupported:
|
|
124
|
+
return
|
|
125
|
+
cdp = getattr(helpers, "cdp", None)
|
|
126
|
+
if not callable(cdp):
|
|
127
|
+
_unsupported = True
|
|
128
|
+
logger.warning("browser-mcp: helpers have no cdp(); disabling setChatScope")
|
|
129
|
+
return
|
|
130
|
+
try:
|
|
131
|
+
cdp("Monkeybot.setChatScope", chatKey=thread_id)
|
|
132
|
+
except Exception as exc:
|
|
133
|
+
if _looks_like_unknown_method(exc):
|
|
134
|
+
_unsupported = True
|
|
135
|
+
logger.warning(
|
|
136
|
+
"browser-mcp: Monkeybot.setChatScope unsupported; disabling for this connection"
|
|
137
|
+
)
|
|
138
|
+
else:
|
|
139
|
+
logger.warning("browser-mcp: Monkeybot.setChatScope failed", exc_info=True)
|
|
@@ -9,6 +9,8 @@ from pathlib import Path
|
|
|
9
9
|
from typing import NoReturn
|
|
10
10
|
from urllib.parse import parse_qsl, urlencode, urlparse, urlunparse
|
|
11
11
|
|
|
12
|
+
from browser_mcp import chat_scope
|
|
13
|
+
|
|
12
14
|
logger = logging.getLogger(__name__)
|
|
13
15
|
|
|
14
16
|
# Written by Monkeyapp when the in-app Electron CDP bridge is live. Prefer this over
|
|
@@ -150,9 +152,12 @@ def _redact_cdp_token(message: str) -> str:
|
|
|
150
152
|
def _bind_in_app_endpoint(url: str, token: str | None) -> str:
|
|
151
153
|
global _env_set_from_in_app_file
|
|
152
154
|
endpoint = _in_app_ws_url(url, token)
|
|
155
|
+
prev = os.environ.get("BU_CDP_WS")
|
|
153
156
|
os.environ["BU_CDP_WS"] = endpoint
|
|
154
157
|
os.environ.pop("BU_CDP_URL", None)
|
|
155
158
|
_env_set_from_in_app_file = True
|
|
159
|
+
if prev != endpoint:
|
|
160
|
+
chat_scope.reset()
|
|
156
161
|
return endpoint
|
|
157
162
|
|
|
158
163
|
|