@vellumai/assistant 0.3.0
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.
- package/.dockerignore +27 -0
- package/.env.example +22 -0
- package/Dockerfile +99 -0
- package/Dockerfile.sandbox +5 -0
- package/README.md +248 -0
- package/bun.lock +1723 -0
- package/bunfig.toml +2 -0
- package/docs/skills.md +158 -0
- package/drizzle/0000_dizzy_maggott.sql +301 -0
- package/drizzle/meta/0000_snapshot.json +1999 -0
- package/drizzle/meta/_journal.json +13 -0
- package/drizzle.config.ts +7 -0
- package/eslint.config.mjs +17 -0
- package/hook-templates/debug-prompt-logger/hook.json +7 -0
- package/hook-templates/debug-prompt-logger/run.sh +68 -0
- package/knip.json +9 -0
- package/package.json +70 -0
- package/scripts/capture-x-graphql.ts +545 -0
- package/scripts/ipc/check-contract-inventory.ts +104 -0
- package/scripts/ipc/check-swift-decoder-drift.ts +166 -0
- package/scripts/ipc/generate-swift.ts +492 -0
- package/scripts/test-filesystem-tools.sh +48 -0
- package/scripts/test.sh +127 -0
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +2485 -0
- package/src/__tests__/account-registry.test.ts +245 -0
- package/src/__tests__/active-skill-tools.test.ts +378 -0
- package/src/__tests__/agent-heartbeat-service.test.ts +250 -0
- package/src/__tests__/agent-loop-thinking.test.ts +81 -0
- package/src/__tests__/agent-loop.test.ts +1135 -0
- package/src/__tests__/anthropic-provider.test.ts +778 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +290 -0
- package/src/__tests__/app-bundler.test.ts +292 -0
- package/src/__tests__/app-executors.test.ts +613 -0
- package/src/__tests__/app-git-history.test.ts +176 -0
- package/src/__tests__/app-git-service.test.ts +169 -0
- package/src/__tests__/app-open-proxy.test.ts +62 -0
- package/src/__tests__/asset-materialize-tool.test.ts +452 -0
- package/src/__tests__/asset-search-tool.test.ts +477 -0
- package/src/__tests__/assistant-attachment-directive.test.ts +401 -0
- package/src/__tests__/assistant-attachments.test.ts +437 -0
- package/src/__tests__/assistant-event-hub.test.ts +226 -0
- package/src/__tests__/assistant-event.test.ts +123 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +315 -0
- package/src/__tests__/attachments-store.test.ts +476 -0
- package/src/__tests__/attachments.test.ts +134 -0
- package/src/__tests__/audit-log-rotation.test.ts +154 -0
- package/src/__tests__/browser-fill-credential.test.ts +309 -0
- package/src/__tests__/browser-manager.test.ts +203 -0
- package/src/__tests__/browser-runtime-check.test.ts +55 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +68 -0
- package/src/__tests__/browser-skill-endstate.test.ts +195 -0
- package/src/__tests__/bundle-scanner.test.ts +313 -0
- package/src/__tests__/call-bridge.test.ts +517 -0
- package/src/__tests__/call-constants.test.ts +40 -0
- package/src/__tests__/call-domain.test.ts +163 -0
- package/src/__tests__/call-orchestrator.test.ts +625 -0
- package/src/__tests__/call-recovery.test.ts +518 -0
- package/src/__tests__/call-routes-http.test.ts +699 -0
- package/src/__tests__/call-state-machine.test.ts +143 -0
- package/src/__tests__/call-state.test.ts +174 -0
- package/src/__tests__/call-store.test.ts +691 -0
- package/src/__tests__/channel-approval-routes.test.ts +2356 -0
- package/src/__tests__/channel-approval.test.ts +299 -0
- package/src/__tests__/channel-approvals.test.ts +521 -0
- package/src/__tests__/channel-delivery-store.test.ts +447 -0
- package/src/__tests__/channel-guardian.test.ts +1005 -0
- package/src/__tests__/checker.test.ts +3519 -0
- package/src/__tests__/clarification-resolver.test.ts +159 -0
- package/src/__tests__/classifier.test.ts +67 -0
- package/src/__tests__/claude-code-skill-regression.test.ts +127 -0
- package/src/__tests__/claude-code-tool-profiles.test.ts +88 -0
- package/src/__tests__/cli-discover.test.ts +85 -0
- package/src/__tests__/cli.test.ts +26 -0
- package/src/__tests__/clipboard.test.ts +80 -0
- package/src/__tests__/commit-guarantee.test.ts +335 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +550 -0
- package/src/__tests__/compaction.benchmark.test.ts +176 -0
- package/src/__tests__/computer-use-session-compaction.test.ts +132 -0
- package/src/__tests__/computer-use-session-lifecycle.test.ts +293 -0
- package/src/__tests__/computer-use-session-working-dir.test.ts +117 -0
- package/src/__tests__/computer-use-skill-baseline.test.ts +74 -0
- package/src/__tests__/computer-use-skill-endstate.test.ts +89 -0
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +217 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +107 -0
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +54 -0
- package/src/__tests__/computer-use-tools.test.ts +250 -0
- package/src/__tests__/config-schema.test.ts +1462 -0
- package/src/__tests__/conflict-intent-tokenization.test.ts +141 -0
- package/src/__tests__/conflict-policy.test.ts +121 -0
- package/src/__tests__/conflict-store.test.ts +332 -0
- package/src/__tests__/connection-policy.test.ts +102 -0
- package/src/__tests__/contacts-tools.test.ts +331 -0
- package/src/__tests__/context-memory-e2e.test.ts +434 -0
- package/src/__tests__/context-token-estimator.test.ts +135 -0
- package/src/__tests__/context-window-manager.test.ts +376 -0
- package/src/__tests__/contradiction-checker.test.ts +314 -0
- package/src/__tests__/conversation-store.test.ts +612 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +517 -0
- package/src/__tests__/credential-broker-server-use.test.ts +554 -0
- package/src/__tests__/credential-broker.test.ts +167 -0
- package/src/__tests__/credential-host-pattern-match.test.ts +104 -0
- package/src/__tests__/credential-metadata-store.test.ts +779 -0
- package/src/__tests__/credential-policy-validate.test.ts +121 -0
- package/src/__tests__/credential-resolve.test.ts +328 -0
- package/src/__tests__/credential-security-e2e.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +583 -0
- package/src/__tests__/credential-selection.test.ts +354 -0
- package/src/__tests__/credential-vault-unit.test.ts +780 -0
- package/src/__tests__/credential-vault.test.ts +852 -0
- package/src/__tests__/daemon-assistant-events.test.ts +164 -0
- package/src/__tests__/daemon-server-session-init.test.ts +522 -0
- package/src/__tests__/date-context.test.ts +373 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +129 -0
- package/src/__tests__/delete-managed-skill-tool.test.ts +97 -0
- package/src/__tests__/diff.test.ts +121 -0
- package/src/__tests__/domain-normalize.test.ts +112 -0
- package/src/__tests__/domain-policy.test.ts +124 -0
- package/src/__tests__/doordash-client.test.ts +186 -0
- package/src/__tests__/doordash-session.test.ts +152 -0
- package/src/__tests__/dynamic-page-surface.test.ts +91 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +132 -0
- package/src/__tests__/edit-engine.test.ts +180 -0
- package/src/__tests__/elevenlabs-client.test.ts +271 -0
- package/src/__tests__/email-cli.test.ts +283 -0
- package/src/__tests__/encrypted-store.test.ts +332 -0
- package/src/__tests__/entity-extractor.test.ts +190 -0
- package/src/__tests__/ephemeral-permissions.test.ts +362 -0
- package/src/__tests__/evaluate-typescript-tool.test.ts +286 -0
- package/src/__tests__/event-bus.test.ts +222 -0
- package/src/__tests__/file-edit-tool.test.ts +122 -0
- package/src/__tests__/file-ops-service.test.ts +330 -0
- package/src/__tests__/file-read-tool.test.ts +75 -0
- package/src/__tests__/file-write-tool.test.ts +113 -0
- package/src/__tests__/filesystem-tools.test.ts +579 -0
- package/src/__tests__/fixtures/credential-security-fixtures.ts +181 -0
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +126 -0
- package/src/__tests__/fixtures/mock-signup-server.ts +387 -0
- package/src/__tests__/fixtures/proxy-fixtures.ts +147 -0
- package/src/__tests__/followup-tools.test.ts +303 -0
- package/src/__tests__/forbidden-legacy-symbols.test.ts +71 -0
- package/src/__tests__/fuzzy-match-property.test.ts +216 -0
- package/src/__tests__/fuzzy-match.test.ts +138 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +631 -0
- package/src/__tests__/gemini-image-service.test.ts +261 -0
- package/src/__tests__/gemini-provider.test.ts +651 -0
- package/src/__tests__/get-weather.test.ts +318 -0
- package/src/__tests__/gmail-integration.test.ts +73 -0
- package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +202 -0
- package/src/__tests__/handlers-cu-observation-blob.test.ts +352 -0
- package/src/__tests__/handlers-ipc-blob-probe.test.ts +191 -0
- package/src/__tests__/handlers-slack-config.test.ts +200 -0
- package/src/__tests__/handlers-task-submit-slash.test.ts +38 -0
- package/src/__tests__/handlers-telegram-config.test.ts +968 -0
- package/src/__tests__/handlers-twilio-config.test.ts +659 -0
- package/src/__tests__/handlers-twitter-config.test.ts +858 -0
- package/src/__tests__/headless-browser-interactions.test.ts +536 -0
- package/src/__tests__/headless-browser-navigate.test.ts +211 -0
- package/src/__tests__/headless-browser-read-tools.test.ts +261 -0
- package/src/__tests__/headless-browser-snapshot.test.ts +185 -0
- package/src/__tests__/history-repair-observability.test.ts +56 -0
- package/src/__tests__/history-repair.test.ts +510 -0
- package/src/__tests__/home-base-bootstrap.test.ts +82 -0
- package/src/__tests__/hooks-blocking.test.ts +128 -0
- package/src/__tests__/hooks-cli.test.ts +144 -0
- package/src/__tests__/hooks-config.test.ts +93 -0
- package/src/__tests__/hooks-discovery.test.ts +199 -0
- package/src/__tests__/hooks-integration.test.ts +189 -0
- package/src/__tests__/hooks-manager.test.ts +187 -0
- package/src/__tests__/hooks-runner.test.ts +182 -0
- package/src/__tests__/hooks-settings.test.ts +154 -0
- package/src/__tests__/hooks-templates.test.ts +137 -0
- package/src/__tests__/hooks-ts-runner.test.ts +125 -0
- package/src/__tests__/hooks-watch.test.ts +100 -0
- package/src/__tests__/host-file-edit-tool.test.ts +228 -0
- package/src/__tests__/host-file-read-tool.test.ts +123 -0
- package/src/__tests__/host-file-write-tool.test.ts +136 -0
- package/src/__tests__/host-shell-tool.test.ts +562 -0
- package/src/__tests__/ingress-reconcile.test.ts +581 -0
- package/src/__tests__/ingress-url-consistency.test.ts +214 -0
- package/src/__tests__/intent-routing.test.ts +259 -0
- package/src/__tests__/ipc-blob-store.test.ts +315 -0
- package/src/__tests__/ipc-contract-inventory.test.ts +54 -0
- package/src/__tests__/ipc-contract.test.ts +74 -0
- package/src/__tests__/ipc-protocol.test.ts +113 -0
- package/src/__tests__/ipc-roundtrip.benchmark.test.ts +237 -0
- package/src/__tests__/ipc-snapshot.test.ts +1769 -0
- package/src/__tests__/ipc-validate.test.ts +407 -0
- package/src/__tests__/key-migration.test.ts +206 -0
- package/src/__tests__/keychain.test.ts +258 -0
- package/src/__tests__/llm-usage-store.test.ts +221 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +257 -0
- package/src/__tests__/managed-store.test.ts +608 -0
- package/src/__tests__/media-generate-image.test.ts +238 -0
- package/src/__tests__/media-reuse-story.e2e.test.ts +676 -0
- package/src/__tests__/media-visibility-policy.test.ts +141 -0
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +235 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +481 -0
- package/src/__tests__/memory-query-builder.test.ts +59 -0
- package/src/__tests__/memory-recall-quality.test.ts +846 -0
- package/src/__tests__/memory-regressions.experimental.test.ts +538 -0
- package/src/__tests__/memory-regressions.test.ts +4435 -0
- package/src/__tests__/memory-retrieval-budget.test.ts +49 -0
- package/src/__tests__/memory-retrieval.benchmark.test.ts +430 -0
- package/src/__tests__/migration-cli-flows.test.ts +169 -0
- package/src/__tests__/migration-ordering.test.ts +249 -0
- package/src/__tests__/mock-signup-server.test.ts +528 -0
- package/src/__tests__/oauth-callback-registry.test.ts +92 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +285 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +176 -0
- package/src/__tests__/onboarding-template-contract.test.ts +58 -0
- package/src/__tests__/openai-provider.test.ts +753 -0
- package/src/__tests__/parallel-tool.benchmark.test.ts +294 -0
- package/src/__tests__/parser.test.ts +472 -0
- package/src/__tests__/path-classifier.test.ts +73 -0
- package/src/__tests__/path-policy.test.ts +435 -0
- package/src/__tests__/platform-move-helper.test.ts +99 -0
- package/src/__tests__/platform-socket-path.test.ts +52 -0
- package/src/__tests__/platform-workspace-migration.test.ts +1000 -0
- package/src/__tests__/platform.test.ts +131 -0
- package/src/__tests__/playbook-execution.test.ts +502 -0
- package/src/__tests__/playbook-tools.test.ts +340 -0
- package/src/__tests__/prebuilt-home-base-seed.test.ts +75 -0
- package/src/__tests__/pricing.test.ts +256 -0
- package/src/__tests__/profile-compiler.test.ts +374 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +342 -0
- package/src/__tests__/provider-registry-ollama.test.ts +16 -0
- package/src/__tests__/provider-streaming.benchmark.test.ts +773 -0
- package/src/__tests__/proxy-approval-callback.test.ts +601 -0
- package/src/__tests__/public-ingress-urls.test.ts +256 -0
- package/src/__tests__/qdrant-manager.test.ts +267 -0
- package/src/__tests__/ratelimit.test.ts +297 -0
- package/src/__tests__/recurrence-engine-rruleset.test.ts +175 -0
- package/src/__tests__/recurrence-engine.test.ts +78 -0
- package/src/__tests__/recurrence-types.test.ts +79 -0
- package/src/__tests__/registry.test.ts +494 -0
- package/src/__tests__/relay-server.test.ts +688 -0
- package/src/__tests__/reminder-store.test.ts +223 -0
- package/src/__tests__/reminder.test.ts +229 -0
- package/src/__tests__/request-file-tool.test.ts +158 -0
- package/src/__tests__/run-orchestrator-assistant-events.test.ts +227 -0
- package/src/__tests__/run-orchestrator.test.ts +425 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +189 -0
- package/src/__tests__/runtime-events-sse-parity.test.ts +343 -0
- package/src/__tests__/runtime-events-sse.test.ts +162 -0
- package/src/__tests__/runtime-runs-http.test.ts +438 -0
- package/src/__tests__/runtime-runs.test.ts +260 -0
- package/src/__tests__/sandbox-diagnostics.test.ts +408 -0
- package/src/__tests__/sandbox-host-parity.test.ts +950 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +253 -0
- package/src/__tests__/schedule-store.test.ts +484 -0
- package/src/__tests__/schedule-tools.test.ts +783 -0
- package/src/__tests__/scheduler-recurrence.test.ts +430 -0
- package/src/__tests__/script-proxy-certs.test.ts +90 -0
- package/src/__tests__/script-proxy-connect-tunnel.test.ts +177 -0
- package/src/__tests__/script-proxy-decision-trace.test.ts +156 -0
- package/src/__tests__/script-proxy-http-forwarder.test.ts +281 -0
- package/src/__tests__/script-proxy-injection-runtime.test.ts +401 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +407 -0
- package/src/__tests__/script-proxy-policy-runtime.test.ts +287 -0
- package/src/__tests__/script-proxy-policy.test.ts +310 -0
- package/src/__tests__/script-proxy-rewrite-specificity.test.ts +135 -0
- package/src/__tests__/script-proxy-router.test.ts +180 -0
- package/src/__tests__/script-proxy-session-manager.test.ts +382 -0
- package/src/__tests__/script-proxy-session-runtime.test.ts +113 -0
- package/src/__tests__/secret-allowlist.test.ts +230 -0
- package/src/__tests__/secret-ingress-handler.test.ts +110 -0
- package/src/__tests__/secret-onetime-send.test.ts +130 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +106 -0
- package/src/__tests__/secret-response-routing.test.ts +93 -0
- package/src/__tests__/secret-scanner-executor.test.ts +348 -0
- package/src/__tests__/secret-scanner.test.ts +900 -0
- package/src/__tests__/secure-keys.test.ts +323 -0
- package/src/__tests__/server-history-render.test.ts +431 -0
- package/src/__tests__/session-abort-tool-results.test.ts +240 -0
- package/src/__tests__/session-conflict-gate.test.ts +1136 -0
- package/src/__tests__/session-error.test.ts +369 -0
- package/src/__tests__/session-evictor.test.ts +188 -0
- package/src/__tests__/session-init.benchmark.test.ts +465 -0
- package/src/__tests__/session-load-history-repair.test.ts +222 -0
- package/src/__tests__/session-pre-run-repair.test.ts +213 -0
- package/src/__tests__/session-process-bridge.test.ts +242 -0
- package/src/__tests__/session-profile-injection.test.ts +444 -0
- package/src/__tests__/session-provider-retry-repair.test.ts +306 -0
- package/src/__tests__/session-queue.test.ts +1535 -0
- package/src/__tests__/session-runtime-assembly.test.ts +476 -0
- package/src/__tests__/session-runtime-workspace.test.ts +183 -0
- package/src/__tests__/session-skill-tools.test.ts +2431 -0
- package/src/__tests__/session-slash-known.test.ts +368 -0
- package/src/__tests__/session-slash-queue.test.ts +288 -0
- package/src/__tests__/session-slash-unknown.test.ts +271 -0
- package/src/__tests__/session-surfaces-task-progress.test.ts +104 -0
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +473 -0
- package/src/__tests__/session-tool-setup-memory-scope.test.ts +140 -0
- package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +140 -0
- package/src/__tests__/session-undo.test.ts +75 -0
- package/src/__tests__/session-workspace-cache-state.test.ts +246 -0
- package/src/__tests__/session-workspace-injection.test.ts +327 -0
- package/src/__tests__/session-workspace-tool-tracking.test.ts +240 -0
- package/src/__tests__/shared-filesystem-errors.test.ts +78 -0
- package/src/__tests__/shell-credential-ref.test.ts +187 -0
- package/src/__tests__/shell-identity.test.ts +256 -0
- package/src/__tests__/shell-parser-fuzz.test.ts +544 -0
- package/src/__tests__/shell-parser-property.test.ts +433 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +272 -0
- package/src/__tests__/signup-e2e.test.ts +353 -0
- package/src/__tests__/size-guard.test.ts +117 -0
- package/src/__tests__/skill-include-graph.test.ts +303 -0
- package/src/__tests__/skill-load-tool.test.ts +409 -0
- package/src/__tests__/skill-projection.benchmark.test.ts +338 -0
- package/src/__tests__/skill-script-runner-host.test.ts +489 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +349 -0
- package/src/__tests__/skill-script-runner.test.ts +159 -0
- package/src/__tests__/skill-tool-factory.test.ts +252 -0
- package/src/__tests__/skill-tool-manifest.test.ts +658 -0
- package/src/__tests__/skill-version-hash.test.ts +182 -0
- package/src/__tests__/skills.test.ts +680 -0
- package/src/__tests__/slash-commands-catalog.test.ts +86 -0
- package/src/__tests__/slash-commands-parser.test.ts +119 -0
- package/src/__tests__/slash-commands-resolver.test.ts +193 -0
- package/src/__tests__/slash-commands-rewrite.test.ts +39 -0
- package/src/__tests__/speaker-identification.test.ts +52 -0
- package/src/__tests__/starter-bundle.test.ts +136 -0
- package/src/__tests__/starter-task-flow.test.ts +143 -0
- package/src/__tests__/subagent-manager-notify.test.ts +404 -0
- package/src/__tests__/subagent-tools.test.ts +801 -0
- package/src/__tests__/subagent-types.test.ts +78 -0
- package/src/__tests__/swarm-orchestrator.test.ts +428 -0
- package/src/__tests__/swarm-plan-validator.test.ts +330 -0
- package/src/__tests__/swarm-recursion.test.ts +165 -0
- package/src/__tests__/swarm-router-planner.test.ts +208 -0
- package/src/__tests__/swarm-session-integration.test.ts +274 -0
- package/src/__tests__/swarm-tool.test.ts +145 -0
- package/src/__tests__/swarm-worker-backend.test.ts +129 -0
- package/src/__tests__/swarm-worker-runner.test.ts +272 -0
- package/src/__tests__/system-prompt.test.ts +439 -0
- package/src/__tests__/task-compiler.test.ts +284 -0
- package/src/__tests__/task-management-tools.test.ts +936 -0
- package/src/__tests__/task-runner.test.ts +216 -0
- package/src/__tests__/task-scheduler.test.ts +217 -0
- package/src/__tests__/task-tools.test.ts +595 -0
- package/src/__tests__/terminal-sandbox-docker.test.ts +1064 -0
- package/src/__tests__/terminal-sandbox.integration.test.ts +178 -0
- package/src/__tests__/terminal-sandbox.test.ts +202 -0
- package/src/__tests__/terminal-tools.test.ts +840 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +90 -0
- package/src/__tests__/test-support/computer-use-skill-harness.ts +45 -0
- package/src/__tests__/tool-audit-listener.test.ts +113 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +253 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +500 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +516 -0
- package/src/__tests__/tool-executor-redaction.test.ts +289 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +301 -0
- package/src/__tests__/tool-executor.test.ts +1989 -0
- package/src/__tests__/tool-metrics-listener.test.ts +225 -0
- package/src/__tests__/tool-notification-listener.test.ts +49 -0
- package/src/__tests__/tool-permission-simulate-handler.test.ts +336 -0
- package/src/__tests__/tool-policy.test.ts +54 -0
- package/src/__tests__/tool-profiling-listener.test.ts +268 -0
- package/src/__tests__/tool-result-truncation.test.ts +217 -0
- package/src/__tests__/tool-trace-listener.test.ts +226 -0
- package/src/__tests__/top-level-renderer.test.ts +121 -0
- package/src/__tests__/top-level-scanner.test.ts +141 -0
- package/src/__tests__/trace-emitter.test.ts +173 -0
- package/src/__tests__/trust-store.test.ts +1605 -0
- package/src/__tests__/turn-commit.test.ts +554 -0
- package/src/__tests__/twilio-provider.test.ts +329 -0
- package/src/__tests__/twilio-routes-elevenlabs.test.ts +375 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +127 -0
- package/src/__tests__/twilio-routes.test.ts +577 -0
- package/src/__tests__/twitter-auth-handler.test.ts +667 -0
- package/src/__tests__/twitter-cli-error-shaping.test.ts +208 -0
- package/src/__tests__/twitter-cli-routing.test.ts +252 -0
- package/src/__tests__/twitter-oauth-client.test.ts +209 -0
- package/src/__tests__/url-safety.test.ts +418 -0
- package/src/__tests__/view-image-tool.test.ts +217 -0
- package/src/__tests__/weather-skill-regression.test.ts +225 -0
- package/src/__tests__/web-fetch.test.ts +869 -0
- package/src/__tests__/web-search.test.ts +584 -0
- package/src/__tests__/workspace-git-service.test.ts +1153 -0
- package/src/__tests__/workspace-heartbeat-service.test.ts +486 -0
- package/src/__tests__/workspace-lifecycle.test.ts +292 -0
- package/src/__tests__/workspace-policy.test.ts +213 -0
- package/src/agent/attachments.ts +35 -0
- package/src/agent/loop.ts +500 -0
- package/src/agent/message-types.ts +17 -0
- package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
- package/src/autonomy/autonomy-resolver.ts +60 -0
- package/src/autonomy/autonomy-store.ts +122 -0
- package/src/autonomy/disposition-mapper.ts +31 -0
- package/src/autonomy/index.ts +11 -0
- package/src/autonomy/types.ts +39 -0
- package/src/bundler/app-bundler.ts +295 -0
- package/src/bundler/bundle-scanner.ts +535 -0
- package/src/bundler/bundle-signer.ts +124 -0
- package/src/bundler/manifest.ts +21 -0
- package/src/bundler/signature-verifier.ts +184 -0
- package/src/calls/call-bridge.ts +168 -0
- package/src/calls/call-constants.ts +48 -0
- package/src/calls/call-domain.ts +430 -0
- package/src/calls/call-orchestrator.ts +498 -0
- package/src/calls/call-recovery.ts +207 -0
- package/src/calls/call-state-machine.ts +68 -0
- package/src/calls/call-state.ts +87 -0
- package/src/calls/call-store.ts +422 -0
- package/src/calls/elevenlabs-client.ts +97 -0
- package/src/calls/elevenlabs-config.ts +31 -0
- package/src/calls/relay-server.ts +390 -0
- package/src/calls/speaker-identification.ts +213 -0
- package/src/calls/twilio-config.ts +45 -0
- package/src/calls/twilio-provider.ts +263 -0
- package/src/calls/twilio-rest.ts +156 -0
- package/src/calls/twilio-routes.ts +311 -0
- package/src/calls/types.ts +39 -0
- package/src/calls/voice-provider.ts +14 -0
- package/src/calls/voice-quality.ts +114 -0
- package/src/cli/autonomy.ts +188 -0
- package/src/cli/config-commands.ts +334 -0
- package/src/cli/contacts.ts +149 -0
- package/src/cli/core-commands.ts +784 -0
- package/src/cli/doordash.ts +1055 -0
- package/src/cli/email-guardrails.ts +200 -0
- package/src/cli/email.ts +405 -0
- package/src/cli/ipc-client.ts +82 -0
- package/src/cli/main-screen.tsx +53 -0
- package/src/cli/map.ts +270 -0
- package/src/cli/twitter.ts +754 -0
- package/src/cli.ts +918 -0
- package/src/commands/__tests__/cc-command-registry.test.ts +319 -0
- package/src/commands/cc-command-registry.ts +209 -0
- package/src/config/bundled-skills/.gitkeep +0 -0
- package/src/config/bundled-skills/agentmail/SKILL.md +128 -0
- package/src/config/bundled-skills/agentmail/icon.svg +21 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +1404 -0
- package/src/config/bundled-skills/app-builder/TOOLS.json +279 -0
- package/src/config/bundled-skills/app-builder/icon.svg +9 -0
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +15 -0
- package/src/config/bundled-skills/app-builder/tools/app-delete.ts +10 -0
- package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +11 -0
- package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +10 -0
- package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +18 -0
- package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +11 -0
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +10 -0
- package/src/config/bundled-skills/app-builder/tools/app-query.ts +10 -0
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +20 -0
- package/src/config/bundled-skills/browser/SKILL.md +28 -0
- package/src/config/bundled-skills/browser/TOOLS.json +234 -0
- package/src/config/bundled-skills/browser/tools/browser-click.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-close.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-type.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +9 -0
- package/src/config/bundled-skills/claude-code/SKILL.md +50 -0
- package/src/config/bundled-skills/claude-code/TOOLS.json +40 -0
- package/src/config/bundled-skills/claude-code/tools/claude-code.ts +9 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +17 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +326 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +9 -0
- package/src/config/bundled-skills/contacts/SKILL.md +39 -0
- package/src/config/bundled-skills/contacts/TOOLS.json +122 -0
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +57 -0
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +60 -0
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +66 -0
- package/src/config/bundled-skills/document/SKILL.md +26 -0
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-create.ts +9 -0
- package/src/config/bundled-skills/document/tools/document-update.ts +9 -0
- package/src/config/bundled-skills/doordash/SKILL.md +163 -0
- package/src/config/bundled-skills/followups/SKILL.md +32 -0
- package/src/config/bundled-skills/followups/TOOLS.json +100 -0
- package/src/config/bundled-skills/followups/icon.svg +24 -0
- package/src/config/bundled-skills/followups/tools/followup-create.ts +9 -0
- package/src/config/bundled-skills/followups/tools/followup-list.ts +9 -0
- package/src/config/bundled-skills/followups/tools/followup-resolve.ts +9 -0
- package/src/config/bundled-skills/google-calendar/SKILL.md +51 -0
- package/src/config/bundled-skills/google-calendar/TOOLS.json +108 -0
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +165 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +21 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +42 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +13 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +30 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +41 -0
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +18 -0
- package/src/config/bundled-skills/google-calendar/types.ts +97 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +32 -0
- package/src/config/bundled-skills/image-studio/TOOLS.json +42 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +115 -0
- package/src/config/bundled-skills/macos-automation/SKILL.md +66 -0
- package/src/config/bundled-skills/messaging/SKILL.md +153 -0
- package/src/config/bundled-skills/messaging/TOOLS.json +357 -0
- package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +23 -0
- package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +23 -0
- package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +25 -0
- package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +26 -0
- package/src/config/bundled-skills/messaging/tools/gmail-label.ts +25 -0
- package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +23 -0
- package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +84 -0
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +18 -0
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +125 -0
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +16 -0
- package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +49 -0
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +21 -0
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +25 -0
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +28 -0
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +32 -0
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +22 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +31 -0
- package/src/config/bundled-skills/messaging/tools/shared.ts +76 -0
- package/src/config/bundled-skills/messaging/tools/slack-add-reaction.ts +25 -0
- package/src/config/bundled-skills/messaging/tools/slack-leave-channel.ts +23 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +533 -0
- package/src/config/bundled-skills/playbooks/SKILL.md +31 -0
- package/src/config/bundled-skills/playbooks/TOOLS.json +126 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +98 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +54 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +76 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +113 -0
- package/src/config/bundled-skills/public-ingress/SKILL.md +200 -0
- package/src/config/bundled-skills/reminder/SKILL.md +20 -0
- package/src/config/bundled-skills/reminder/TOOLS.json +67 -0
- package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +9 -0
- package/src/config/bundled-skills/reminder/tools/reminder-create.ts +9 -0
- package/src/config/bundled-skills/reminder/tools/reminder-list.ts +9 -0
- package/src/config/bundled-skills/schedule/SKILL.md +74 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +135 -0
- package/src/config/bundled-skills/schedule/tools/schedule-create.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-list.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-update.ts +9 -0
- package/src/config/bundled-skills/self-upgrade/SKILL.md +68 -0
- package/src/config/bundled-skills/start-the-day/SKILL.md +70 -0
- package/src/config/bundled-skills/start-the-day/icon.svg +13 -0
- package/src/config/bundled-skills/subagent/SKILL.md +25 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +107 -0
- package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-message.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-read.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-status.ts +9 -0
- package/src/config/bundled-skills/tasks/SKILL.md +28 -0
- package/src/config/bundled-skills/tasks/TOOLS.json +281 -0
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-run.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-save.ts +9 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +25 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +32 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +370 -0
- package/src/config/bundled-skills/twitter/SKILL.md +220 -0
- package/src/config/bundled-skills/watcher/SKILL.md +27 -0
- package/src/config/bundled-skills/watcher/TOOLS.json +147 -0
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +9 -0
- package/src/config/bundled-skills/weather/SKILL.md +37 -0
- package/src/config/bundled-skills/weather/TOOLS.json +32 -0
- package/src/config/bundled-skills/weather/icon.svg +24 -0
- package/src/config/bundled-skills/weather/tools/get-weather.ts +9 -0
- package/src/config/computer-use-prompt.ts +97 -0
- package/src/config/defaults.ts +263 -0
- package/src/config/loader.ts +339 -0
- package/src/config/schema.ts +1436 -0
- package/src/config/skill-state.ts +95 -0
- package/src/config/skills.ts +972 -0
- package/src/config/system-prompt.ts +675 -0
- package/src/config/templates/BOOTSTRAP.md +70 -0
- package/src/config/templates/IDENTITY.md +25 -0
- package/src/config/templates/LOOKS.md +25 -0
- package/src/config/templates/SOUL.md +37 -0
- package/src/config/templates/USER.md +19 -0
- package/src/config/types.ts +42 -0
- package/src/config/vellum-skills/chatgpt-import/SKILL.md +24 -0
- package/src/config/vellum-skills/chatgpt-import/TOOLS.json +23 -0
- package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +284 -0
- package/src/config/vellum-skills/deploy-fullstack-vercel/SKILL.md +179 -0
- package/src/config/vellum-skills/document-writer/SKILL.md +195 -0
- package/src/config/vellum-skills/google-oauth-setup/SKILL.md +199 -0
- package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +153 -0
- package/src/config/vellum-skills/telegram-setup/SKILL.md +143 -0
- package/src/config/vellum-skills/twilio-setup/SKILL.md +213 -0
- package/src/contacts/contact-store.ts +410 -0
- package/src/contacts/index.ts +11 -0
- package/src/contacts/types.ts +28 -0
- package/src/context/token-estimator.ts +108 -0
- package/src/context/tool-result-truncation.ts +128 -0
- package/src/context/window-manager.ts +531 -0
- package/src/daemon/assistant-attachments.ts +691 -0
- package/src/daemon/classifier.ts +110 -0
- package/src/daemon/computer-use-session.ts +903 -0
- package/src/daemon/connection-policy.ts +41 -0
- package/src/daemon/date-context.ts +136 -0
- package/src/daemon/handlers/apps.ts +530 -0
- package/src/daemon/handlers/browser.ts +54 -0
- package/src/daemon/handlers/computer-use.ts +187 -0
- package/src/daemon/handlers/config.ts +1517 -0
- package/src/daemon/handlers/diagnostics.ts +338 -0
- package/src/daemon/handlers/documents.ts +173 -0
- package/src/daemon/handlers/home-base.ts +78 -0
- package/src/daemon/handlers/identity.ts +127 -0
- package/src/daemon/handlers/index.ts +129 -0
- package/src/daemon/handlers/misc.ts +331 -0
- package/src/daemon/handlers/open-bundle-handler.ts +80 -0
- package/src/daemon/handlers/publish.ts +187 -0
- package/src/daemon/handlers/sessions.ts +555 -0
- package/src/daemon/handlers/shared.ts +570 -0
- package/src/daemon/handlers/signing.ts +37 -0
- package/src/daemon/handlers/skills.ts +486 -0
- package/src/daemon/handlers/subagents.ts +210 -0
- package/src/daemon/handlers/twitter-auth.ts +198 -0
- package/src/daemon/handlers/work-items.ts +632 -0
- package/src/daemon/handlers/workspace-files.ts +75 -0
- package/src/daemon/handlers.ts +17 -0
- package/src/daemon/history-repair.ts +214 -0
- package/src/daemon/ipc-blob-store.ts +231 -0
- package/src/daemon/ipc-contract-inventory.json +495 -0
- package/src/daemon/ipc-contract-inventory.ts +126 -0
- package/src/daemon/ipc-contract.ts +2551 -0
- package/src/daemon/ipc-protocol.ts +75 -0
- package/src/daemon/ipc-validate.ts +188 -0
- package/src/daemon/lifecycle.ts +582 -0
- package/src/daemon/main.ts +21 -0
- package/src/daemon/media-visibility-policy.ts +57 -0
- package/src/daemon/ride-shotgun-handler.ts +309 -0
- package/src/daemon/server.ts +1215 -0
- package/src/daemon/session-agent-loop.ts +922 -0
- package/src/daemon/session-attachments.ts +196 -0
- package/src/daemon/session-conflict-gate.ts +184 -0
- package/src/daemon/session-dynamic-profile.ts +63 -0
- package/src/daemon/session-error.ts +290 -0
- package/src/daemon/session-evictor.ts +196 -0
- package/src/daemon/session-history.ts +437 -0
- package/src/daemon/session-lifecycle.ts +147 -0
- package/src/daemon/session-media-retry.ts +147 -0
- package/src/daemon/session-memory.ts +212 -0
- package/src/daemon/session-messaging.ts +145 -0
- package/src/daemon/session-notifiers.ts +193 -0
- package/src/daemon/session-process.ts +323 -0
- package/src/daemon/session-queue-manager.ts +82 -0
- package/src/daemon/session-runtime-assembly.ts +447 -0
- package/src/daemon/session-skill-tools.ts +356 -0
- package/src/daemon/session-slash.ts +305 -0
- package/src/daemon/session-surfaces.ts +702 -0
- package/src/daemon/session-tool-setup.ts +523 -0
- package/src/daemon/session-usage.ts +72 -0
- package/src/daemon/session-workspace.ts +19 -0
- package/src/daemon/session.ts +400 -0
- package/src/daemon/tls-certs.ts +189 -0
- package/src/daemon/trace-emitter.ts +82 -0
- package/src/daemon/video-thumbnail.ts +62 -0
- package/src/daemon/watch-handler.ts +274 -0
- package/src/doordash/client.ts +999 -0
- package/src/doordash/queries.ts +1311 -0
- package/src/doordash/query-extractor.ts +93 -0
- package/src/doordash/session.ts +82 -0
- package/src/email/provider.ts +117 -0
- package/src/email/providers/agentmail.ts +317 -0
- package/src/email/providers/index.ts +58 -0
- package/src/email/service.ts +303 -0
- package/src/email/types.ts +126 -0
- package/src/events/bus.ts +157 -0
- package/src/events/domain-events.ts +83 -0
- package/src/events/index.ts +18 -0
- package/src/events/tool-audit-listener.ts +80 -0
- package/src/events/tool-domain-event-publisher.ts +111 -0
- package/src/events/tool-metrics-listener.ts +159 -0
- package/src/events/tool-notification-listener.ts +17 -0
- package/src/events/tool-profiling-listener.ts +158 -0
- package/src/events/tool-trace-listener.ts +75 -0
- package/src/export/formatter.ts +98 -0
- package/src/followups/followup-store.ts +168 -0
- package/src/followups/index.ts +10 -0
- package/src/followups/types.ts +29 -0
- package/src/gallery/default-gallery.ts +795 -0
- package/src/gallery/gallery-manifest.ts +24 -0
- package/src/home-base/app-link-store.ts +82 -0
- package/src/home-base/bootstrap.ts +68 -0
- package/src/home-base/prebuilt/index.html +662 -0
- package/src/home-base/prebuilt/seed-metadata.json +21 -0
- package/src/home-base/prebuilt/seed.ts +112 -0
- package/src/home-base/prebuilt-home-base-updater.ts +30 -0
- package/src/hooks/cli.ts +163 -0
- package/src/hooks/config.ts +88 -0
- package/src/hooks/discovery.ts +110 -0
- package/src/hooks/manager.ts +124 -0
- package/src/hooks/runner.ts +123 -0
- package/src/hooks/templates.ts +52 -0
- package/src/hooks/types.ts +72 -0
- package/src/inbound/public-ingress-urls.ts +123 -0
- package/src/index.ts +81 -0
- package/src/instrument.ts +60 -0
- package/src/logfire.ts +99 -0
- package/src/media/gemini-image-service.ts +136 -0
- package/src/memory/account-store.ts +108 -0
- package/src/memory/admin.ts +211 -0
- package/src/memory/app-git-service.ts +295 -0
- package/src/memory/app-store.ts +577 -0
- package/src/memory/attachments-store.ts +397 -0
- package/src/memory/channel-delivery-store.ts +353 -0
- package/src/memory/channel-guardian-store.ts +669 -0
- package/src/memory/checkpoints.ts +52 -0
- package/src/memory/clarification-resolver.ts +298 -0
- package/src/memory/conflict-intent.ts +157 -0
- package/src/memory/conflict-policy.ts +73 -0
- package/src/memory/conflict-store.ts +350 -0
- package/src/memory/contradiction-checker.ts +358 -0
- package/src/memory/conversation-key-store.ts +122 -0
- package/src/memory/conversation-store.ts +470 -0
- package/src/memory/db.ts +1991 -0
- package/src/memory/embedding-backend.ts +229 -0
- package/src/memory/embedding-gemini.ts +52 -0
- package/src/memory/embedding-local.ts +65 -0
- package/src/memory/embedding-ollama.ts +55 -0
- package/src/memory/embedding-openai.ts +25 -0
- package/src/memory/entity-extractor.ts +474 -0
- package/src/memory/external-conversation-store.ts +234 -0
- package/src/memory/fingerprint.ts +20 -0
- package/src/memory/indexer.ts +156 -0
- package/src/memory/items-extractor.ts +461 -0
- package/src/memory/job-handlers/backfill.ts +139 -0
- package/src/memory/job-handlers/cleanup.ts +58 -0
- package/src/memory/job-handlers/conflict.ts +141 -0
- package/src/memory/job-handlers/embedding.ts +61 -0
- package/src/memory/job-handlers/extraction.ts +123 -0
- package/src/memory/job-handlers/index-maintenance.ts +54 -0
- package/src/memory/job-handlers/summarization.ts +286 -0
- package/src/memory/job-utils.ts +170 -0
- package/src/memory/jobs-store.ts +401 -0
- package/src/memory/jobs-worker.ts +313 -0
- package/src/memory/llm-request-log-store.ts +45 -0
- package/src/memory/llm-usage-store.ts +60 -0
- package/src/memory/message-content.ts +54 -0
- package/src/memory/profile-compiler.ts +160 -0
- package/src/memory/published-pages-store.ts +137 -0
- package/src/memory/qdrant-client.ts +366 -0
- package/src/memory/qdrant-manager.ts +242 -0
- package/src/memory/query-builder.ts +45 -0
- package/src/memory/retrieval-budget.ts +30 -0
- package/src/memory/retriever.ts +653 -0
- package/src/memory/runs-store.ts +305 -0
- package/src/memory/schema.ts +677 -0
- package/src/memory/search/entity.ts +298 -0
- package/src/memory/search/formatting.ts +207 -0
- package/src/memory/search/lexical.ts +227 -0
- package/src/memory/search/ranking.ts +401 -0
- package/src/memory/search/semantic.ts +121 -0
- package/src/memory/search/types.ts +137 -0
- package/src/memory/segmenter.ts +68 -0
- package/src/memory/shared-app-links-store.ts +138 -0
- package/src/memory/tool-usage-store.ts +62 -0
- package/src/messaging/activity-analyzer.ts +76 -0
- package/src/messaging/draft-store.ts +88 -0
- package/src/messaging/index.ts +3 -0
- package/src/messaging/provider-types.ts +80 -0
- package/src/messaging/provider.ts +52 -0
- package/src/messaging/providers/gmail/adapter.ts +193 -0
- package/src/messaging/providers/gmail/client.ts +204 -0
- package/src/messaging/providers/gmail/types.ts +90 -0
- package/src/messaging/providers/slack/adapter.ts +202 -0
- package/src/messaging/providers/slack/client.ts +198 -0
- package/src/messaging/providers/slack/types.ts +119 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +162 -0
- package/src/messaging/providers/telegram-bot/client.ts +104 -0
- package/src/messaging/providers/telegram-bot/types.ts +15 -0
- package/src/messaging/registry.ts +35 -0
- package/src/messaging/style-analyzer.ts +159 -0
- package/src/messaging/thread-summarizer.ts +306 -0
- package/src/messaging/triage-engine.ts +323 -0
- package/src/messaging/types.ts +55 -0
- package/src/permissions/checker.ts +640 -0
- package/src/permissions/defaults.ts +254 -0
- package/src/permissions/prompter.ts +98 -0
- package/src/permissions/secret-prompter.ts +114 -0
- package/src/permissions/shell-identity.ts +227 -0
- package/src/permissions/trust-store.ts +607 -0
- package/src/permissions/types.ts +43 -0
- package/src/permissions/workspace-policy.ts +114 -0
- package/src/playbooks/index.ts +2 -0
- package/src/playbooks/playbook-compiler.ts +90 -0
- package/src/playbooks/types.ts +55 -0
- package/src/providers/anthropic/client.ts +751 -0
- package/src/providers/failover.ts +129 -0
- package/src/providers/fireworks/client.ts +20 -0
- package/src/providers/gemini/client.ts +285 -0
- package/src/providers/ollama/client.ts +30 -0
- package/src/providers/openai/client.ts +337 -0
- package/src/providers/openrouter/client.ts +20 -0
- package/src/providers/ratelimit.ts +93 -0
- package/src/providers/registry.ts +146 -0
- package/src/providers/retry.ts +81 -0
- package/src/providers/stream-timeout.ts +38 -0
- package/src/providers/types.ts +109 -0
- package/src/runtime/assistant-event-hub.ts +157 -0
- package/src/runtime/assistant-event.ts +82 -0
- package/src/runtime/channel-approval-parser.ts +60 -0
- package/src/runtime/channel-approval-types.ts +73 -0
- package/src/runtime/channel-approvals.ts +206 -0
- package/src/runtime/channel-guardian-service.ts +212 -0
- package/src/runtime/gateway-client.ts +58 -0
- package/src/runtime/http-server.ts +1076 -0
- package/src/runtime/http-types.ts +66 -0
- package/src/runtime/routes/app-routes.ts +174 -0
- package/src/runtime/routes/attachment-routes.ts +133 -0
- package/src/runtime/routes/call-routes.ts +190 -0
- package/src/runtime/routes/channel-routes.ts +1404 -0
- package/src/runtime/routes/conversation-routes.ts +352 -0
- package/src/runtime/routes/events-routes.ts +148 -0
- package/src/runtime/routes/run-routes.ts +257 -0
- package/src/runtime/routes/secret-routes.ts +76 -0
- package/src/runtime/run-orchestrator.ts +330 -0
- package/src/schedule/recurrence-engine.ts +162 -0
- package/src/schedule/recurrence-types.ts +67 -0
- package/src/schedule/schedule-store.ts +506 -0
- package/src/schedule/scheduler.ts +171 -0
- package/src/security/encrypted-store.ts +238 -0
- package/src/security/keychain.ts +252 -0
- package/src/security/oauth-callback-registry.ts +66 -0
- package/src/security/oauth2.ts +274 -0
- package/src/security/redaction.ts +89 -0
- package/src/security/secret-allowlist.ts +164 -0
- package/src/security/secret-ingress.ts +57 -0
- package/src/security/secret-scanner.ts +550 -0
- package/src/security/secure-keys.ts +180 -0
- package/src/security/token-manager.ts +141 -0
- package/src/services/published-app-updater.ts +69 -0
- package/src/services/vercel-deploy.ts +73 -0
- package/src/skills/active-skill-tools.ts +81 -0
- package/src/skills/clawhub.ts +414 -0
- package/src/skills/include-graph.ts +146 -0
- package/src/skills/managed-store.ts +233 -0
- package/src/skills/path-classifier.ts +128 -0
- package/src/skills/slash-commands.ts +174 -0
- package/src/skills/tool-manifest.ts +165 -0
- package/src/skills/version-hash.ts +110 -0
- package/src/slack/slack-webhook.ts +61 -0
- package/src/subagent/index.ts +19 -0
- package/src/subagent/manager.ts +511 -0
- package/src/subagent/types.ts +69 -0
- package/src/swarm/backend-claude-code.ts +145 -0
- package/src/swarm/index.ts +44 -0
- package/src/swarm/limits.ts +37 -0
- package/src/swarm/orchestrator.ts +279 -0
- package/src/swarm/plan-validator.ts +151 -0
- package/src/swarm/router-planner.ts +100 -0
- package/src/swarm/router-prompts.ts +36 -0
- package/src/swarm/synthesizer.ts +62 -0
- package/src/swarm/types.ts +62 -0
- package/src/swarm/worker-backend.ts +121 -0
- package/src/swarm/worker-prompts.ts +79 -0
- package/src/swarm/worker-runner.ts +164 -0
- package/src/tasks/SPEC.md +139 -0
- package/src/tasks/candidate-store.ts +86 -0
- package/src/tasks/ephemeral-permissions.ts +48 -0
- package/src/tasks/task-compiler.ts +199 -0
- package/src/tasks/task-runner.ts +90 -0
- package/src/tasks/task-scheduler.ts +21 -0
- package/src/tasks/task-store.ts +127 -0
- package/src/tasks/tool-sanitizer.ts +36 -0
- package/src/tools/apps/definitions.ts +59 -0
- package/src/tools/apps/executors.ts +313 -0
- package/src/tools/apps/open-proxy.ts +43 -0
- package/src/tools/apps/registry.ts +16 -0
- package/src/tools/assets/materialize.ts +218 -0
- package/src/tools/assets/search.ts +361 -0
- package/src/tools/browser/__tests__/auth-cache.test.ts +219 -0
- package/src/tools/browser/__tests__/auth-detector.test.ts +362 -0
- package/src/tools/browser/__tests__/jit-auth.test.ts +189 -0
- package/src/tools/browser/api-map.ts +293 -0
- package/src/tools/browser/auth-cache.ts +149 -0
- package/src/tools/browser/auth-detector.ts +347 -0
- package/src/tools/browser/auto-navigate.ts +270 -0
- package/src/tools/browser/browser-execution.ts +980 -0
- package/src/tools/browser/browser-handoff.ts +79 -0
- package/src/tools/browser/browser-manager.ts +715 -0
- package/src/tools/browser/browser-screencast.ts +217 -0
- package/src/tools/browser/headless-browser.ts +450 -0
- package/src/tools/browser/jit-auth.ts +51 -0
- package/src/tools/browser/network-recorder.ts +349 -0
- package/src/tools/browser/network-recording-types.ts +49 -0
- package/src/tools/browser/recording-store.ts +49 -0
- package/src/tools/browser/runtime-check.ts +43 -0
- package/src/tools/browser/x-auto-navigate.ts +207 -0
- package/src/tools/calls/call-end.ts +67 -0
- package/src/tools/calls/call-start.ts +81 -0
- package/src/tools/calls/call-status.ts +81 -0
- package/src/tools/claude-code/claude-code.ts +428 -0
- package/src/tools/computer-use/definitions.ts +443 -0
- package/src/tools/computer-use/registry.ts +22 -0
- package/src/tools/computer-use/request-computer-control.ts +53 -0
- package/src/tools/computer-use/skill-proxy-bridge.ts +28 -0
- package/src/tools/credentials/account-registry.ts +127 -0
- package/src/tools/credentials/broker-types.ts +107 -0
- package/src/tools/credentials/broker.ts +372 -0
- package/src/tools/credentials/domain-policy.ts +51 -0
- package/src/tools/credentials/host-pattern-match.ts +60 -0
- package/src/tools/credentials/metadata-store.ts +335 -0
- package/src/tools/credentials/policy-types.ts +52 -0
- package/src/tools/credentials/policy-validate.ts +80 -0
- package/src/tools/credentials/resolve.ts +122 -0
- package/src/tools/credentials/selection.ts +159 -0
- package/src/tools/credentials/tool-policy.ts +25 -0
- package/src/tools/credentials/vault.ts +657 -0
- package/src/tools/document/document-tool.ts +92 -0
- package/src/tools/document/editor-template.ts +237 -0
- package/src/tools/execution-target.ts +21 -0
- package/src/tools/execution-timeout.ts +49 -0
- package/src/tools/executor.ts +815 -0
- package/src/tools/filesystem/edit.ts +127 -0
- package/src/tools/filesystem/fuzzy-match.ts +202 -0
- package/src/tools/filesystem/read.ts +71 -0
- package/src/tools/filesystem/view-image.ts +199 -0
- package/src/tools/filesystem/write.ts +79 -0
- package/src/tools/followups/followup_create.ts +76 -0
- package/src/tools/followups/followup_list.ts +60 -0
- package/src/tools/followups/followup_resolve.ts +56 -0
- package/src/tools/host-filesystem/edit.ts +125 -0
- package/src/tools/host-filesystem/read.ts +80 -0
- package/src/tools/host-filesystem/write.ts +76 -0
- package/src/tools/host-terminal/cli-discover.ts +180 -0
- package/src/tools/host-terminal/host-shell.ts +191 -0
- package/src/tools/memory/definitions.ts +69 -0
- package/src/tools/memory/handlers.ts +246 -0
- package/src/tools/memory/register.ts +66 -0
- package/src/tools/network/__tests__/web-search.test.ts +427 -0
- package/src/tools/network/domain-normalize.ts +85 -0
- package/src/tools/network/script-proxy/__tests__/logging.test.ts +248 -0
- package/src/tools/network/script-proxy/__tests__/policy.test.ts +234 -0
- package/src/tools/network/script-proxy/__tests__/router.test.ts +76 -0
- package/src/tools/network/script-proxy/certs.ts +237 -0
- package/src/tools/network/script-proxy/connect-tunnel.ts +82 -0
- package/src/tools/network/script-proxy/http-forwarder.ts +151 -0
- package/src/tools/network/script-proxy/index.ts +28 -0
- package/src/tools/network/script-proxy/logging.ts +196 -0
- package/src/tools/network/script-proxy/mitm-handler.ts +269 -0
- package/src/tools/network/script-proxy/policy.ts +152 -0
- package/src/tools/network/script-proxy/router.ts +60 -0
- package/src/tools/network/script-proxy/server.ts +136 -0
- package/src/tools/network/script-proxy/session-manager.ts +534 -0
- package/src/tools/network/script-proxy/types.ts +125 -0
- package/src/tools/network/url-safety.ts +227 -0
- package/src/tools/network/web-fetch.ts +713 -0
- package/src/tools/network/web-search.ts +296 -0
- package/src/tools/policy-context.ts +29 -0
- package/src/tools/registry.ts +295 -0
- package/src/tools/reminder/reminder-store.ts +148 -0
- package/src/tools/reminder/reminder.ts +80 -0
- package/src/tools/schedule/create.ts +81 -0
- package/src/tools/schedule/delete.ts +28 -0
- package/src/tools/schedule/list.ts +69 -0
- package/src/tools/schedule/update.ts +97 -0
- package/src/tools/shared/filesystem/edit-engine.ts +56 -0
- package/src/tools/shared/filesystem/errors.ts +85 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +215 -0
- package/src/tools/shared/filesystem/format-diff.ts +35 -0
- package/src/tools/shared/filesystem/path-policy.ts +125 -0
- package/src/tools/shared/filesystem/size-guard.ts +41 -0
- package/src/tools/shared/filesystem/types.ts +80 -0
- package/src/tools/shared/shell-output.ts +52 -0
- package/src/tools/skills/delete-managed.ts +60 -0
- package/src/tools/skills/load.ts +139 -0
- package/src/tools/skills/sandbox-runner.ts +279 -0
- package/src/tools/skills/scaffold-managed.ts +150 -0
- package/src/tools/skills/script-contract.ts +6 -0
- package/src/tools/skills/skill-script-runner.ts +86 -0
- package/src/tools/skills/skill-tool-factory.ts +64 -0
- package/src/tools/skills/vellum-catalog.ts +217 -0
- package/src/tools/subagent/abort.ts +33 -0
- package/src/tools/subagent/message.ts +39 -0
- package/src/tools/subagent/read.ts +67 -0
- package/src/tools/subagent/spawn.ts +46 -0
- package/src/tools/subagent/status.ts +45 -0
- package/src/tools/swarm/delegate.ts +183 -0
- package/src/tools/system/request-permission.ts +98 -0
- package/src/tools/system/version.ts +43 -0
- package/src/tools/tasks/index.ts +27 -0
- package/src/tools/tasks/task-delete.ts +82 -0
- package/src/tools/tasks/task-list.ts +44 -0
- package/src/tools/tasks/task-run.ts +97 -0
- package/src/tools/tasks/task-save.ts +47 -0
- package/src/tools/tasks/work-item-enqueue.ts +234 -0
- package/src/tools/tasks/work-item-list.ts +55 -0
- package/src/tools/tasks/work-item-remove.ts +60 -0
- package/src/tools/tasks/work-item-run.ts +78 -0
- package/src/tools/tasks/work-item-update.ts +114 -0
- package/src/tools/terminal/backends/docker.ts +372 -0
- package/src/tools/terminal/backends/native.ts +190 -0
- package/src/tools/terminal/backends/types.ts +26 -0
- package/src/tools/terminal/evaluate-typescript.ts +275 -0
- package/src/tools/terminal/parser.ts +413 -0
- package/src/tools/terminal/safe-env.ts +37 -0
- package/src/tools/terminal/sandbox-diagnostics.ts +149 -0
- package/src/tools/terminal/sandbox.ts +44 -0
- package/src/tools/terminal/shell.ts +257 -0
- package/src/tools/tool-manifest.ts +198 -0
- package/src/tools/types.ts +176 -0
- package/src/tools/ui-surface/definitions.ts +244 -0
- package/src/tools/ui-surface/registry.ts +14 -0
- package/src/tools/watch/screen-watch.ts +130 -0
- package/src/tools/watch/watch-state.ts +119 -0
- package/src/tools/watcher/create.ts +64 -0
- package/src/tools/watcher/delete.ts +27 -0
- package/src/tools/watcher/digest.ts +50 -0
- package/src/tools/watcher/list.ts +60 -0
- package/src/tools/watcher/update.ts +56 -0
- package/src/tools/weather/service.ts +551 -0
- package/src/twitter/client.ts +690 -0
- package/src/twitter/oauth-client.ts +102 -0
- package/src/twitter/router.ts +101 -0
- package/src/twitter/session.ts +91 -0
- package/src/usage/actors.ts +24 -0
- package/src/usage/types.ts +37 -0
- package/src/util/clipboard.ts +33 -0
- package/src/util/content-id.ts +16 -0
- package/src/util/debounce.ts +88 -0
- package/src/util/diff.ts +181 -0
- package/src/util/errors.ts +129 -0
- package/src/util/logger.ts +243 -0
- package/src/util/network-info.ts +47 -0
- package/src/util/platform.ts +632 -0
- package/src/util/pricing.ts +150 -0
- package/src/util/promise-guard.ts +37 -0
- package/src/util/retry.ts +98 -0
- package/src/util/spinner.ts +51 -0
- package/src/util/time.ts +16 -0
- package/src/util/truncate.ts +6 -0
- package/src/util/xml.ts +4 -0
- package/src/version.ts +3 -0
- package/src/watcher/constants.ts +11 -0
- package/src/watcher/engine.ts +199 -0
- package/src/watcher/provider-registry.ts +15 -0
- package/src/watcher/provider-types.ts +48 -0
- package/src/watcher/providers/gmail.ts +198 -0
- package/src/watcher/providers/google-calendar.ts +228 -0
- package/src/watcher/providers/slack.ts +129 -0
- package/src/watcher/watcher-store.ts +419 -0
- package/src/work-items/work-item-runner.ts +171 -0
- package/src/work-items/work-item-store.ts +325 -0
- package/src/workspace/commit-message-enrichment-service.ts +284 -0
- package/src/workspace/commit-message-provider.ts +95 -0
- package/src/workspace/git-service.ts +857 -0
- package/src/workspace/heartbeat-service.ts +345 -0
- package/src/workspace/provider-commit-message-generator.ts +285 -0
- package/src/workspace/top-level-renderer.ts +19 -0
- package/src/workspace/top-level-scanner.ts +41 -0
- package/src/workspace/turn-commit.ts +175 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,903 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computer-use session orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Manages the observation -> infer -> action loop for computer-use tasks,
|
|
5
|
+
* bridging the macOS client (which captures screen state and executes actions)
|
|
6
|
+
* with the AgentLoop (which runs inference via the Anthropic API with CU tools).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { v4 as uuid } from 'uuid';
|
|
10
|
+
import type { Provider, Message, ContentBlock, ToolDefinition } from '../providers/types.js';
|
|
11
|
+
import { INTERACTIVE_SURFACE_TYPES } from './ipc-protocol.js';
|
|
12
|
+
import type { ServerMessage, CuObservation, SurfaceType, SurfaceData, FileUploadSurfaceData, UiSurfaceShow } from './ipc-protocol.js';
|
|
13
|
+
import type { Tool, ToolExecutionResult } from '../tools/types.js';
|
|
14
|
+
import { AgentLoop } from '../agent/loop.js';
|
|
15
|
+
import { ToolExecutor } from '../tools/executor.js';
|
|
16
|
+
import { PermissionPrompter } from '../permissions/prompter.js';
|
|
17
|
+
import { SecretPrompter } from '../permissions/secret-prompter.js';
|
|
18
|
+
import type { UserDecision } from '../permissions/types.js';
|
|
19
|
+
import { allUiSurfaceTools } from '../tools/ui-surface/definitions.js';
|
|
20
|
+
import { allComputerUseTools } from '../tools/computer-use/definitions.js';
|
|
21
|
+
import { registerSkillTools } from '../tools/registry.js';
|
|
22
|
+
import { buildComputerUseSystemPrompt } from '../config/computer-use-prompt.js';
|
|
23
|
+
import { getSandboxWorkingDir } from '../util/platform.js';
|
|
24
|
+
import { getConfig } from '../config/loader.js';
|
|
25
|
+
import { projectSkillTools, resetSkillToolProjection, type SkillProjectionCache } from './session-skill-tools.js';
|
|
26
|
+
import { getLogger } from '../util/logger.js';
|
|
27
|
+
|
|
28
|
+
const log = getLogger('computer-use-session');
|
|
29
|
+
|
|
30
|
+
const MAX_STEPS = 50;
|
|
31
|
+
const SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
|
|
32
|
+
const MAX_HISTORY_ENTRIES = 10;
|
|
33
|
+
const LOOP_DETECTION_WINDOW = 3;
|
|
34
|
+
const CONSECUTIVE_UNCHANGED_WARNING_THRESHOLD = 2;
|
|
35
|
+
|
|
36
|
+
/** Number of most-recent AX tree snapshots to keep in conversation history. */
|
|
37
|
+
const MAX_AX_TREES_IN_HISTORY = 2;
|
|
38
|
+
|
|
39
|
+
/** Regex that matches the `<ax-tree>…</ax-tree>` markers injected by buildObservationResultContent. */
|
|
40
|
+
const AX_TREE_PATTERN = /<ax-tree>[\s\S]*?<\/ax-tree>/g;
|
|
41
|
+
const AX_TREE_PLACEHOLDER = '<ax_tree_omitted />';
|
|
42
|
+
|
|
43
|
+
type SessionState = 'idle' | 'awaiting_observation' | 'inferring' | 'complete' | 'error';
|
|
44
|
+
|
|
45
|
+
interface ActionRecord {
|
|
46
|
+
step: number;
|
|
47
|
+
toolName: string;
|
|
48
|
+
input: Record<string, unknown>;
|
|
49
|
+
reasoning?: string;
|
|
50
|
+
result?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class ComputerUseSession {
|
|
54
|
+
private readonly sessionId: string;
|
|
55
|
+
private readonly task: string;
|
|
56
|
+
private readonly screenWidth: number;
|
|
57
|
+
private readonly screenHeight: number;
|
|
58
|
+
private readonly provider: Provider;
|
|
59
|
+
private sendToClient: (msg: ServerMessage) => void;
|
|
60
|
+
private readonly interactionType: 'computer_use' | 'text_qa';
|
|
61
|
+
private readonly onTerminal?: (sessionId: string) => void;
|
|
62
|
+
private readonly preactivatedSkillIds: string[];
|
|
63
|
+
private readonly skillProjectionState = new Map<string, string>();
|
|
64
|
+
private readonly skillProjectionCache: SkillProjectionCache = {};
|
|
65
|
+
|
|
66
|
+
private state: SessionState = 'idle';
|
|
67
|
+
private stepCount = 0;
|
|
68
|
+
private actionHistory: ActionRecord[] = [];
|
|
69
|
+
private previousAXTree: string | undefined;
|
|
70
|
+
private consecutiveUnchangedSteps = 0;
|
|
71
|
+
private abortController: AbortController | null = null;
|
|
72
|
+
private sessionTimer: ReturnType<typeof setTimeout> | null = null;
|
|
73
|
+
|
|
74
|
+
private pendingObservation: {
|
|
75
|
+
resolve: (result: ToolExecutionResult) => void;
|
|
76
|
+
} | null = null;
|
|
77
|
+
|
|
78
|
+
private pendingSurfaceActions = new Map<string, {
|
|
79
|
+
resolve: (result: ToolExecutionResult) => void;
|
|
80
|
+
}>();
|
|
81
|
+
private surfaceState = new Map<string, { surfaceType: SurfaceType; data: SurfaceData }>();
|
|
82
|
+
private terminalNotified = false;
|
|
83
|
+
private prompter: PermissionPrompter | null = null;
|
|
84
|
+
|
|
85
|
+
// Tracks the agent loop promise so callers can await session completion
|
|
86
|
+
private loopPromise: Promise<void> | null = null;
|
|
87
|
+
|
|
88
|
+
constructor(
|
|
89
|
+
sessionId: string,
|
|
90
|
+
task: string,
|
|
91
|
+
screenWidth: number,
|
|
92
|
+
screenHeight: number,
|
|
93
|
+
provider: Provider,
|
|
94
|
+
sendToClient: (msg: ServerMessage) => void,
|
|
95
|
+
interactionType?: 'computer_use' | 'text_qa',
|
|
96
|
+
onTerminal?: (sessionId: string) => void,
|
|
97
|
+
preactivatedSkillIds?: string[],
|
|
98
|
+
) {
|
|
99
|
+
this.sessionId = sessionId;
|
|
100
|
+
this.task = task;
|
|
101
|
+
this.screenWidth = screenWidth;
|
|
102
|
+
this.screenHeight = screenHeight;
|
|
103
|
+
this.provider = provider;
|
|
104
|
+
this.sendToClient = sendToClient;
|
|
105
|
+
this.interactionType = interactionType ?? 'computer_use';
|
|
106
|
+
this.onTerminal = onTerminal;
|
|
107
|
+
this.preactivatedSkillIds = preactivatedSkillIds ?? ['computer-use'];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
// Public API
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
|
|
114
|
+
async handleObservation(obs: CuObservation): Promise<void> {
|
|
115
|
+
if (this.state === 'complete' || this.state === 'error') {
|
|
116
|
+
log.warn({ sessionId: this.sessionId, state: this.state }, 'Observation received after session ended');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Track consecutive unchanged steps
|
|
121
|
+
const hadPreviousAXTree = this.previousAXTree != null;
|
|
122
|
+
if (this.stepCount > 0) {
|
|
123
|
+
if (obs.axDiff == null && hadPreviousAXTree && obs.axTree != null) {
|
|
124
|
+
this.consecutiveUnchangedSteps++;
|
|
125
|
+
} else if (obs.axDiff != null) {
|
|
126
|
+
this.consecutiveUnchangedSteps = 0;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Capture previous AX tree for next turn
|
|
131
|
+
if (obs.axTree != null) {
|
|
132
|
+
this.previousAXTree = obs.axTree;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (this.state === 'awaiting_observation' && this.pendingObservation) {
|
|
136
|
+
// Resolve the pending proxy tool result with updated screen context
|
|
137
|
+
const content = this.buildObservationResultContent(obs, hadPreviousAXTree);
|
|
138
|
+
const result: ToolExecutionResult = obs.executionError
|
|
139
|
+
? { content: `Action failed: ${obs.executionError}\n\n${content}`, isError: true }
|
|
140
|
+
: { content, isError: false };
|
|
141
|
+
this.state = 'inferring';
|
|
142
|
+
this.pendingObservation.resolve(result);
|
|
143
|
+
this.pendingObservation = null;
|
|
144
|
+
// The agent loop continues automatically after resolution
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// First observation — start the agent loop
|
|
149
|
+
this.state = 'inferring';
|
|
150
|
+
this.abortController = new AbortController();
|
|
151
|
+
|
|
152
|
+
// Safety net: abort the session if it runs longer than SESSION_TIMEOUT_MS
|
|
153
|
+
this.sessionTimer = setTimeout(() => {
|
|
154
|
+
log.warn({ sessionId: this.sessionId, timeoutMs: SESSION_TIMEOUT_MS }, 'Session timeout reached, aborting');
|
|
155
|
+
this.abort();
|
|
156
|
+
}, SESSION_TIMEOUT_MS);
|
|
157
|
+
|
|
158
|
+
const messages = this.buildMessages(obs, hadPreviousAXTree);
|
|
159
|
+
this.loopPromise = this.runAgentLoop(messages).catch((err) => {
|
|
160
|
+
// Catches errors from setup code (e.g. skill projection failures) that
|
|
161
|
+
// occur before runAgentLoop's internal try-catch takes over.
|
|
162
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
163
|
+
log.error({ err, sessionId: this.sessionId }, 'Agent loop startup failed');
|
|
164
|
+
if (this.sessionTimer) {
|
|
165
|
+
clearTimeout(this.sessionTimer);
|
|
166
|
+
this.sessionTimer = null;
|
|
167
|
+
}
|
|
168
|
+
if (this.state !== 'complete' && this.state !== 'error') {
|
|
169
|
+
this.state = 'error';
|
|
170
|
+
this.sendToClient({
|
|
171
|
+
type: 'cu_error',
|
|
172
|
+
sessionId: this.sessionId,
|
|
173
|
+
message,
|
|
174
|
+
});
|
|
175
|
+
this.notifyTerminal();
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await this.loopPromise;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
abort(): void {
|
|
183
|
+
if (this.state === 'complete' || this.state === 'error') return;
|
|
184
|
+
|
|
185
|
+
log.info({ sessionId: this.sessionId }, 'Aborting computer-use session');
|
|
186
|
+
if (this.sessionTimer) {
|
|
187
|
+
clearTimeout(this.sessionTimer);
|
|
188
|
+
this.sessionTimer = null;
|
|
189
|
+
}
|
|
190
|
+
this.abortController?.abort();
|
|
191
|
+
|
|
192
|
+
// If waiting for an observation, resolve it as cancelled
|
|
193
|
+
if (this.pendingObservation) {
|
|
194
|
+
this.pendingObservation.resolve({ content: 'Session aborted', isError: true });
|
|
195
|
+
this.pendingObservation = null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Dispose prompter to clear pending permission timers and reject promises
|
|
199
|
+
this.prompter?.dispose();
|
|
200
|
+
|
|
201
|
+
// Resolve any pending surface actions
|
|
202
|
+
for (const [, pending] of this.pendingSurfaceActions) {
|
|
203
|
+
pending.resolve({ content: 'Session aborted', isError: true });
|
|
204
|
+
}
|
|
205
|
+
this.pendingSurfaceActions.clear();
|
|
206
|
+
this.surfaceState.clear();
|
|
207
|
+
|
|
208
|
+
this.state = 'error';
|
|
209
|
+
this.sendToClient({
|
|
210
|
+
type: 'cu_error',
|
|
211
|
+
sessionId: this.sessionId,
|
|
212
|
+
message: 'Session aborted by user',
|
|
213
|
+
});
|
|
214
|
+
this.notifyTerminal();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
isComplete(): boolean {
|
|
218
|
+
return this.state === 'complete';
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
getState(): string {
|
|
222
|
+
return this.state;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Compute CU tool definitions from the bundled computer-use skill via
|
|
227
|
+
* skill projection. Returns null if projection fails so the caller can
|
|
228
|
+
* fall back to legacy hardcoded tool definitions.
|
|
229
|
+
*/
|
|
230
|
+
private getProjectedCuToolDefinitions(): ToolDefinition[] | null {
|
|
231
|
+
if (this.preactivatedSkillIds.length === 0) {
|
|
232
|
+
log.warn('No preactivatedSkillIds configured, falling back to legacy CU tools');
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
const projection = projectSkillTools([], {
|
|
238
|
+
preactivatedSkillIds: this.preactivatedSkillIds,
|
|
239
|
+
previouslyActiveSkillIds: this.skillProjectionState,
|
|
240
|
+
cache: this.skillProjectionCache,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
if (projection.toolDefinitions.length === 0) {
|
|
244
|
+
log.warn(
|
|
245
|
+
{ preactivatedSkillIds: this.preactivatedSkillIds },
|
|
246
|
+
'Skill projection produced no tool definitions, falling back to legacy CU tools',
|
|
247
|
+
);
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return projection.toolDefinitions;
|
|
252
|
+
} catch (err) {
|
|
253
|
+
log.warn({ err }, 'Skill projection failed, falling back to legacy CU tools');
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
handleSurfaceAction(surfaceId: string, actionId: string, data?: Record<string, unknown>): void {
|
|
259
|
+
const pending = this.pendingSurfaceActions.get(surfaceId);
|
|
260
|
+
if (!pending) {
|
|
261
|
+
log.warn({ surfaceId, actionId }, 'No pending surface action found');
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
// selection_changed is a non-terminal state update — don't consume the
|
|
265
|
+
// pending entry. The selection state will be in the action button payload.
|
|
266
|
+
if (actionId === 'selection_changed') {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
this.pendingSurfaceActions.delete(surfaceId);
|
|
270
|
+
pending.resolve({
|
|
271
|
+
content: JSON.stringify({ actionId, data: data ?? {} }),
|
|
272
|
+
isError: false,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// Agent loop execution
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
|
|
280
|
+
private async runAgentLoop(messages: Message[]): Promise<void> {
|
|
281
|
+
const systemPrompt = buildComputerUseSystemPrompt(this.screenWidth, this.screenHeight);
|
|
282
|
+
|
|
283
|
+
let cuToolDefs = this.getProjectedCuToolDefinitions();
|
|
284
|
+
if (!cuToolDefs) {
|
|
285
|
+
// Fallback: register the legacy CU tools as skill-origin tools so
|
|
286
|
+
// ToolExecutor can resolve them via getTool(), but using the same
|
|
287
|
+
// ownerSkillId as the bundled computer-use skill. This avoids
|
|
288
|
+
// core-vs-skill collisions that would permanently block skill
|
|
289
|
+
// projection recovery on subsequent sessions.
|
|
290
|
+
const fallbackSkillId = this.preactivatedSkillIds[0] ?? 'computer-use';
|
|
291
|
+
const fallbackTools: Tool[] = allComputerUseTools.map((t) => ({
|
|
292
|
+
...t,
|
|
293
|
+
origin: 'skill' as const,
|
|
294
|
+
ownerSkillId: fallbackSkillId,
|
|
295
|
+
ownerSkillBundled: true,
|
|
296
|
+
}));
|
|
297
|
+
registerSkillTools(fallbackTools);
|
|
298
|
+
// Track in the session map so resetSkillToolProjection cleans up
|
|
299
|
+
this.skillProjectionState.set(fallbackSkillId, 'fallback');
|
|
300
|
+
cuToolDefs = allComputerUseTools.map((t) => t.getDefinition());
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const toolDefs: ToolDefinition[] = [
|
|
304
|
+
...cuToolDefs,
|
|
305
|
+
...allUiSurfaceTools
|
|
306
|
+
.filter((t) => t.name !== 'request_file')
|
|
307
|
+
.map((t) => t.getDefinition()),
|
|
308
|
+
];
|
|
309
|
+
|
|
310
|
+
this.prompter = new PermissionPrompter(this.sendToClient);
|
|
311
|
+
const prompter = this.prompter;
|
|
312
|
+
const secretPrompter = new SecretPrompter(this.sendToClient);
|
|
313
|
+
const executor = new ToolExecutor(prompter);
|
|
314
|
+
|
|
315
|
+
const proxyResolver = async (
|
|
316
|
+
toolName: string,
|
|
317
|
+
input: Record<string, unknown>,
|
|
318
|
+
): Promise<ToolExecutionResult> => {
|
|
319
|
+
// ── Surface tool proxying ──────────────────────────────────────
|
|
320
|
+
if (toolName === 'ui_show') {
|
|
321
|
+
const surfaceId = uuid();
|
|
322
|
+
const surfaceType = input.surface_type as SurfaceType;
|
|
323
|
+
const title = typeof input.title === 'string' ? input.title : undefined;
|
|
324
|
+
const data = input.data as SurfaceData;
|
|
325
|
+
const actions = input.actions as Array<{ id: string; label: string; style?: string }> | undefined;
|
|
326
|
+
// Interactive surfaces default to awaiting user action.
|
|
327
|
+
// Tables and lists only block when explicit action buttons are provided;
|
|
328
|
+
// selectionMode alone should not gate blocking because selection_changed
|
|
329
|
+
// fires on every click and would immediately resolve multi-select surfaces.
|
|
330
|
+
const hasActions = Array.isArray(actions) && actions.length > 0;
|
|
331
|
+
const isInteractive = surfaceType === 'list'
|
|
332
|
+
? hasActions
|
|
333
|
+
: surfaceType === 'table'
|
|
334
|
+
? hasActions
|
|
335
|
+
: INTERACTIVE_SURFACE_TYPES.includes(surfaceType);
|
|
336
|
+
const awaitAction = (input.await_action as boolean) ?? isInteractive;
|
|
337
|
+
|
|
338
|
+
// Track surface state for ui_update merging
|
|
339
|
+
this.surfaceState.set(surfaceId, { surfaceType, data });
|
|
340
|
+
|
|
341
|
+
this.sendToClient({
|
|
342
|
+
type: 'ui_surface_show',
|
|
343
|
+
sessionId: this.sessionId,
|
|
344
|
+
surfaceId,
|
|
345
|
+
surfaceType,
|
|
346
|
+
title,
|
|
347
|
+
data,
|
|
348
|
+
actions: actions?.map(a => ({ id: a.id, label: a.label, style: (a.style ?? 'secondary') as 'primary' | 'secondary' | 'destructive' })),
|
|
349
|
+
} as unknown as UiSurfaceShow);
|
|
350
|
+
|
|
351
|
+
if (awaitAction) {
|
|
352
|
+
return new Promise<ToolExecutionResult>((resolve) => {
|
|
353
|
+
this.pendingSurfaceActions.set(surfaceId, { resolve });
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
return { content: JSON.stringify({ surfaceId }), isError: false };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (toolName === 'ui_update') {
|
|
360
|
+
const surfaceId = input.surface_id as string;
|
|
361
|
+
const patch = input.data as Record<string, unknown>;
|
|
362
|
+
|
|
363
|
+
// Merge the partial patch into the stored full surface data
|
|
364
|
+
const stored = this.surfaceState.get(surfaceId);
|
|
365
|
+
let mergedData: SurfaceData;
|
|
366
|
+
if (stored) {
|
|
367
|
+
mergedData = { ...stored.data, ...patch } as SurfaceData;
|
|
368
|
+
stored.data = mergedData;
|
|
369
|
+
} else {
|
|
370
|
+
mergedData = patch as unknown as SurfaceData;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
this.sendToClient({
|
|
374
|
+
type: 'ui_surface_update',
|
|
375
|
+
sessionId: this.sessionId,
|
|
376
|
+
surfaceId,
|
|
377
|
+
data: mergedData,
|
|
378
|
+
});
|
|
379
|
+
return { content: 'Surface updated', isError: false };
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (toolName === 'ui_dismiss') {
|
|
383
|
+
const surfaceId = input.surface_id as string;
|
|
384
|
+
this.sendToClient({
|
|
385
|
+
type: 'ui_surface_dismiss',
|
|
386
|
+
sessionId: this.sessionId,
|
|
387
|
+
surfaceId,
|
|
388
|
+
});
|
|
389
|
+
this.pendingSurfaceActions.delete(surfaceId);
|
|
390
|
+
this.surfaceState.delete(surfaceId);
|
|
391
|
+
return { content: 'Surface dismissed', isError: false };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// ── File request proxying ──────────────────────────────────────
|
|
395
|
+
if (toolName === 'request_file') {
|
|
396
|
+
const surfaceId = uuid();
|
|
397
|
+
const prompt = typeof input.prompt === 'string' ? input.prompt : 'Please share a file';
|
|
398
|
+
const acceptedTypes = Array.isArray(input.accepted_types) ? input.accepted_types as string[] : undefined;
|
|
399
|
+
const maxFiles = typeof input.max_files === 'number' ? input.max_files : 1;
|
|
400
|
+
|
|
401
|
+
const data: FileUploadSurfaceData = {
|
|
402
|
+
prompt,
|
|
403
|
+
acceptedTypes,
|
|
404
|
+
maxFiles,
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
this.surfaceState.set(surfaceId, { surfaceType: 'file_upload', data });
|
|
408
|
+
|
|
409
|
+
this.sendToClient({
|
|
410
|
+
type: 'ui_surface_show',
|
|
411
|
+
sessionId: this.sessionId,
|
|
412
|
+
surfaceId,
|
|
413
|
+
surfaceType: 'file_upload',
|
|
414
|
+
title: 'File Request',
|
|
415
|
+
data,
|
|
416
|
+
} as UiSurfaceShow);
|
|
417
|
+
|
|
418
|
+
// Always await — file upload is interactive
|
|
419
|
+
return new Promise<ToolExecutionResult>((resolve) => {
|
|
420
|
+
this.pendingSurfaceActions.set(surfaceId, { resolve });
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// ── Computer-use tool proxying ─────────────────────────────────
|
|
425
|
+
const reasoning = typeof input.reasoning === 'string' ? input.reasoning : undefined;
|
|
426
|
+
|
|
427
|
+
// Record action in history
|
|
428
|
+
this.actionHistory.push({
|
|
429
|
+
step: this.stepCount + 1,
|
|
430
|
+
toolName,
|
|
431
|
+
input,
|
|
432
|
+
reasoning,
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
// Check for terminal tools
|
|
436
|
+
if (toolName === 'computer_use_done' || toolName === 'computer_use_respond') {
|
|
437
|
+
const summary =
|
|
438
|
+
toolName === 'computer_use_done'
|
|
439
|
+
? (typeof input.summary === 'string' ? input.summary : 'Task completed')
|
|
440
|
+
: (typeof input.answer === 'string' ? input.answer : 'No answer provided');
|
|
441
|
+
|
|
442
|
+
this.sendToClient({
|
|
443
|
+
type: 'cu_complete',
|
|
444
|
+
sessionId: this.sessionId,
|
|
445
|
+
summary,
|
|
446
|
+
stepCount: this.stepCount,
|
|
447
|
+
isResponse: toolName === 'computer_use_respond' ? true : undefined,
|
|
448
|
+
});
|
|
449
|
+
this.state = 'complete';
|
|
450
|
+
// Stop AgentLoop immediately so terminal tools cannot trigger extra provider calls.
|
|
451
|
+
this.abortController?.abort();
|
|
452
|
+
this.notifyTerminal();
|
|
453
|
+
return { content: 'Session complete', isError: false };
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
this.stepCount++;
|
|
457
|
+
|
|
458
|
+
// Enforce step limit — abort the loop so toolChoice:'any' can't force another turn
|
|
459
|
+
if (this.stepCount > MAX_STEPS) {
|
|
460
|
+
this.state = 'error';
|
|
461
|
+
this.sendToClient({
|
|
462
|
+
type: 'cu_error',
|
|
463
|
+
sessionId: this.sessionId,
|
|
464
|
+
message: `Step limit (${MAX_STEPS}) exceeded`,
|
|
465
|
+
});
|
|
466
|
+
this.abortController?.abort();
|
|
467
|
+
this.notifyTerminal();
|
|
468
|
+
return { content: `Step limit (${MAX_STEPS}) exceeded`, isError: true };
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Send action to client for execution
|
|
472
|
+
this.sendToClient({
|
|
473
|
+
type: 'cu_action',
|
|
474
|
+
sessionId: this.sessionId,
|
|
475
|
+
toolName,
|
|
476
|
+
input,
|
|
477
|
+
reasoning,
|
|
478
|
+
stepNumber: this.stepCount,
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
// Wait for next observation from client
|
|
482
|
+
this.state = 'awaiting_observation';
|
|
483
|
+
return new Promise<ToolExecutionResult>((resolve) => {
|
|
484
|
+
this.pendingObservation = { resolve };
|
|
485
|
+
});
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// Build a set of tool names the CU session is allowed to execute.
|
|
489
|
+
// This prevents tools registered globally (e.g. computer_use_request_control)
|
|
490
|
+
// but not advertised to the CU model from executing during CU sessions.
|
|
491
|
+
const allowedToolNames = new Set(toolDefs.map((td) => td.name));
|
|
492
|
+
|
|
493
|
+
const toolExecutor = async (
|
|
494
|
+
name: string,
|
|
495
|
+
input: Record<string, unknown>,
|
|
496
|
+
): Promise<ToolExecutionResult> => {
|
|
497
|
+
return executor.execute(name, input, {
|
|
498
|
+
workingDir: getSandboxWorkingDir(),
|
|
499
|
+
sessionId: this.sessionId,
|
|
500
|
+
conversationId: this.sessionId,
|
|
501
|
+
proxyToolResolver: proxyResolver,
|
|
502
|
+
allowedToolNames,
|
|
503
|
+
requestSecret: async (params) => {
|
|
504
|
+
return secretPrompter.prompt(
|
|
505
|
+
params.service, params.field, params.label,
|
|
506
|
+
params.description, params.placeholder,
|
|
507
|
+
this.sessionId,
|
|
508
|
+
params.purpose, params.allowedTools, params.allowedDomains,
|
|
509
|
+
);
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// Wrap the provider so that old AX tree snapshots are stripped from
|
|
515
|
+
// conversation history before each API call, keeping only the most recent
|
|
516
|
+
// MAX_AX_TREES_IN_HISTORY entries. This prevents TTFT from growing
|
|
517
|
+
// linearly with step count.
|
|
518
|
+
const compactingProvider: Provider = {
|
|
519
|
+
name: this.provider.name,
|
|
520
|
+
sendMessage: (msgs, tools, sys, opts) => {
|
|
521
|
+
const compacted = ComputerUseSession.compactHistory(msgs);
|
|
522
|
+
return this.provider.sendMessage(compacted, tools, sys, opts);
|
|
523
|
+
},
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
const cuConfig = getConfig();
|
|
527
|
+
const agentLoop = new AgentLoop(
|
|
528
|
+
compactingProvider,
|
|
529
|
+
systemPrompt,
|
|
530
|
+
{
|
|
531
|
+
maxTokens: 4096,
|
|
532
|
+
maxInputTokens: cuConfig.contextWindow.maxInputTokens,
|
|
533
|
+
toolChoice: { type: 'any' },
|
|
534
|
+
// Allow MAX_STEPS non-terminal actions plus one terminal turn
|
|
535
|
+
// (computer_use_done/computer_use_respond), since AgentLoop caps tool turns globally.
|
|
536
|
+
maxToolUseTurns: MAX_STEPS + 1,
|
|
537
|
+
},
|
|
538
|
+
toolDefs,
|
|
539
|
+
toolExecutor,
|
|
540
|
+
);
|
|
541
|
+
|
|
542
|
+
try {
|
|
543
|
+
await agentLoop.run(
|
|
544
|
+
messages,
|
|
545
|
+
(event) => {
|
|
546
|
+
switch (event.type) {
|
|
547
|
+
case 'error':
|
|
548
|
+
log.error({ err: event.error, sessionId: this.sessionId }, 'Agent loop error');
|
|
549
|
+
if (this.state !== 'complete') {
|
|
550
|
+
this.state = 'error';
|
|
551
|
+
this.sendToClient({
|
|
552
|
+
type: 'cu_error',
|
|
553
|
+
sessionId: this.sessionId,
|
|
554
|
+
message: event.error.message,
|
|
555
|
+
});
|
|
556
|
+
this.notifyTerminal();
|
|
557
|
+
}
|
|
558
|
+
break;
|
|
559
|
+
case 'usage':
|
|
560
|
+
log.info({
|
|
561
|
+
sessionId: this.sessionId,
|
|
562
|
+
inputTokens: event.inputTokens,
|
|
563
|
+
outputTokens: event.outputTokens,
|
|
564
|
+
model: event.model,
|
|
565
|
+
}, 'Usage');
|
|
566
|
+
break;
|
|
567
|
+
// Other events (text_delta, thinking_delta, etc.) are not surfaced to the CU client
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
this.abortController?.signal,
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
// If the loop exits without completing, treat as error
|
|
574
|
+
if (this.state !== 'complete' && this.state !== 'error') {
|
|
575
|
+
this.state = 'error';
|
|
576
|
+
this.sendToClient({
|
|
577
|
+
type: 'cu_error',
|
|
578
|
+
sessionId: this.sessionId,
|
|
579
|
+
message: 'Agent loop ended unexpectedly',
|
|
580
|
+
});
|
|
581
|
+
this.notifyTerminal();
|
|
582
|
+
}
|
|
583
|
+
} catch (err) {
|
|
584
|
+
if (this.abortController?.signal.aborted) {
|
|
585
|
+
log.info({ sessionId: this.sessionId }, 'Agent loop aborted');
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
589
|
+
log.error({ err, sessionId: this.sessionId }, 'Agent loop failed');
|
|
590
|
+
if (this.state !== 'complete') {
|
|
591
|
+
this.state = 'error';
|
|
592
|
+
this.sendToClient({
|
|
593
|
+
type: 'cu_error',
|
|
594
|
+
sessionId: this.sessionId,
|
|
595
|
+
message,
|
|
596
|
+
});
|
|
597
|
+
this.notifyTerminal();
|
|
598
|
+
}
|
|
599
|
+
} finally {
|
|
600
|
+
// Always clean up skill projection state and session timer
|
|
601
|
+
resetSkillToolProjection(this.skillProjectionState);
|
|
602
|
+
if (this.sessionTimer) {
|
|
603
|
+
clearTimeout(this.sessionTimer);
|
|
604
|
+
this.sessionTimer = null;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
private notifyTerminal(): void {
|
|
610
|
+
if (this.terminalNotified) return;
|
|
611
|
+
this.terminalNotified = true;
|
|
612
|
+
resetSkillToolProjection(this.skillProjectionState);
|
|
613
|
+
this.onTerminal?.(this.sessionId);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// ---------------------------------------------------------------------------
|
|
617
|
+
// History compaction — strip old AX tree snapshots from tool results
|
|
618
|
+
// ---------------------------------------------------------------------------
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Returns a shallow copy of `messages` where all but the most recent
|
|
622
|
+
* `MAX_AX_TREES_IN_HISTORY` `<ax-tree>` blocks have been replaced with a
|
|
623
|
+
* short placeholder. This keeps the conversation context small so that
|
|
624
|
+
* TTFT does not grow linearly with step count.
|
|
625
|
+
*/
|
|
626
|
+
static compactHistory(messages: Message[]): Message[] {
|
|
627
|
+
// Collect indices of user messages that contain an <ax-tree> block
|
|
628
|
+
const indicesWithAxTree: number[] = [];
|
|
629
|
+
for (let i = 0; i < messages.length; i++) {
|
|
630
|
+
const msg = messages[i];
|
|
631
|
+
if (msg.role !== 'user') continue;
|
|
632
|
+
for (const block of msg.content) {
|
|
633
|
+
if (
|
|
634
|
+
block.type === 'tool_result' &&
|
|
635
|
+
typeof block.content === 'string' &&
|
|
636
|
+
block.content.includes('<ax-tree>')
|
|
637
|
+
) {
|
|
638
|
+
indicesWithAxTree.push(i);
|
|
639
|
+
break;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (indicesWithAxTree.length <= MAX_AX_TREES_IN_HISTORY) {
|
|
645
|
+
return messages;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const toStrip = new Set(indicesWithAxTree.slice(0, -MAX_AX_TREES_IN_HISTORY));
|
|
649
|
+
|
|
650
|
+
return messages.map((msg, idx) => {
|
|
651
|
+
if (!toStrip.has(idx)) return msg;
|
|
652
|
+
return {
|
|
653
|
+
...msg,
|
|
654
|
+
content: msg.content.map((block) => {
|
|
655
|
+
if (
|
|
656
|
+
block.type === 'tool_result' &&
|
|
657
|
+
typeof block.content === 'string' &&
|
|
658
|
+
block.content.includes('<ax-tree>')
|
|
659
|
+
) {
|
|
660
|
+
return {
|
|
661
|
+
...block,
|
|
662
|
+
content: block.content.replace(AX_TREE_PATTERN, AX_TREE_PLACEHOLDER),
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
return block;
|
|
666
|
+
}),
|
|
667
|
+
};
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Escapes any literal `</ax-tree>` occurrences inside AX tree content so
|
|
673
|
+
* that the non-greedy compaction regex (`AX_TREE_PATTERN`) does not stop
|
|
674
|
+
* prematurely when the user happens to be viewing XML/HTML source that
|
|
675
|
+
* contains the closing tag. The escaped content does not need to be
|
|
676
|
+
* unescaped because compaction replaces the entire block with a placeholder.
|
|
677
|
+
*/
|
|
678
|
+
static escapeAxTreeContent(content: string): string {
|
|
679
|
+
return content.replace(/<\/ax-tree>/gi, '</ax-tree>');
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// ---------------------------------------------------------------------------
|
|
683
|
+
// Build rich tool-result content from an observation so the model sees
|
|
684
|
+
// updated screen state on each turn (not just "Action executed").
|
|
685
|
+
// ---------------------------------------------------------------------------
|
|
686
|
+
|
|
687
|
+
private buildObservationResultContent(obs: CuObservation, hadPreviousAXTree: boolean): string {
|
|
688
|
+
const parts: string[] = [];
|
|
689
|
+
|
|
690
|
+
if (obs.executionResult) {
|
|
691
|
+
parts.push(obs.executionResult);
|
|
692
|
+
parts.push('');
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// AX tree diff
|
|
696
|
+
if (obs.axDiff) {
|
|
697
|
+
parts.push(obs.axDiff);
|
|
698
|
+
parts.push('');
|
|
699
|
+
} else if (hadPreviousAXTree && obs.axTree != null) {
|
|
700
|
+
const lastAction = this.actionHistory[this.actionHistory.length - 1];
|
|
701
|
+
const wasWait = lastAction?.toolName === 'computer_use_wait';
|
|
702
|
+
if (this.consecutiveUnchangedSteps >= CONSECUTIVE_UNCHANGED_WARNING_THRESHOLD) {
|
|
703
|
+
parts.push(
|
|
704
|
+
`WARNING: ${this.consecutiveUnchangedSteps} consecutive actions had NO VISIBLE EFFECT on the UI. You MUST try a completely different approach.`,
|
|
705
|
+
);
|
|
706
|
+
} else if (!wasWait) {
|
|
707
|
+
parts.push('Your last action had NO VISIBLE EFFECT on the UI. Try something different.');
|
|
708
|
+
}
|
|
709
|
+
parts.push('');
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// Current screen state — wrapped in markers so compactHistory can strip old snapshots
|
|
713
|
+
if (obs.axTree) {
|
|
714
|
+
parts.push('<ax-tree>');
|
|
715
|
+
parts.push('CURRENT SCREEN STATE:');
|
|
716
|
+
parts.push(ComputerUseSession.escapeAxTreeContent(obs.axTree));
|
|
717
|
+
parts.push('</ax-tree>');
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const screenshotMetadata = this.formatScreenshotMetadata(obs);
|
|
721
|
+
if (screenshotMetadata.length > 0) {
|
|
722
|
+
parts.push('');
|
|
723
|
+
parts.push(...screenshotMetadata);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return parts.join('\n').trim() || 'Action executed';
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// ---------------------------------------------------------------------------
|
|
730
|
+
// Message building (replicates AnthropicProvider.buildMessages from Swift)
|
|
731
|
+
// ---------------------------------------------------------------------------
|
|
732
|
+
|
|
733
|
+
private buildMessages(obs: CuObservation, hadPreviousAXTree: boolean): Message[] {
|
|
734
|
+
const contentBlocks: ContentBlock[] = [];
|
|
735
|
+
|
|
736
|
+
// Screenshot image block
|
|
737
|
+
if (obs.screenshot) {
|
|
738
|
+
contentBlocks.push({
|
|
739
|
+
type: 'image',
|
|
740
|
+
source: {
|
|
741
|
+
type: 'base64',
|
|
742
|
+
media_type: 'image/jpeg',
|
|
743
|
+
data: obs.screenshot,
|
|
744
|
+
},
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Text block
|
|
749
|
+
const textParts: string[] = [];
|
|
750
|
+
const trimmedTask = this.task.trim();
|
|
751
|
+
if (trimmedTask) {
|
|
752
|
+
textParts.push(`TASK: ${trimmedTask}`);
|
|
753
|
+
} else {
|
|
754
|
+
textParts.push('TASK: No explicit task provided.');
|
|
755
|
+
}
|
|
756
|
+
textParts.push('');
|
|
757
|
+
|
|
758
|
+
// AX tree diff (compact summary of what changed)
|
|
759
|
+
if (obs.axDiff && this.actionHistory.length > 0) {
|
|
760
|
+
textParts.push(obs.axDiff);
|
|
761
|
+
textParts.push('');
|
|
762
|
+
} else if (hadPreviousAXTree && obs.axTree != null && this.actionHistory.length > 0) {
|
|
763
|
+
// AX tree unchanged — tell the model its action had no effect
|
|
764
|
+
const lastAction = this.actionHistory[this.actionHistory.length - 1];
|
|
765
|
+
const wasWait = lastAction?.toolName === 'computer_use_wait';
|
|
766
|
+
textParts.push('CHANGES SINCE LAST ACTION:');
|
|
767
|
+
if (this.consecutiveUnchangedSteps >= CONSECUTIVE_UNCHANGED_WARNING_THRESHOLD) {
|
|
768
|
+
textParts.push(
|
|
769
|
+
`WARNING: ${this.consecutiveUnchangedSteps} consecutive actions had NO VISIBLE EFFECT on the UI. You MUST try a completely different approach — do not repeat any of your recent actions.`,
|
|
770
|
+
);
|
|
771
|
+
} else if (!wasWait) {
|
|
772
|
+
const actionDesc = `${lastAction?.toolName ?? 'unknown'}`;
|
|
773
|
+
textParts.push(
|
|
774
|
+
`Your last action (${actionDesc}) had NO VISIBLE EFFECT on the UI. The screen is identical to the previous step. Do NOT repeat the same action — try something different.`,
|
|
775
|
+
);
|
|
776
|
+
} else {
|
|
777
|
+
textParts.push('No visible changes detected — the UI is identical to the previous step.');
|
|
778
|
+
}
|
|
779
|
+
textParts.push('');
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// Current screen state
|
|
783
|
+
if (obs.axTree) {
|
|
784
|
+
textParts.push('CURRENT SCREEN STATE (accessibility tree of the focused window):');
|
|
785
|
+
textParts.push(obs.axTree);
|
|
786
|
+
textParts.push('');
|
|
787
|
+
textParts.push('Use element_id with the [ID] numbers shown above to target elements.');
|
|
788
|
+
|
|
789
|
+
// Secondary windows for cross-app awareness
|
|
790
|
+
if (obs.secondaryWindows) {
|
|
791
|
+
textParts.push('');
|
|
792
|
+
textParts.push(obs.secondaryWindows);
|
|
793
|
+
textParts.push('');
|
|
794
|
+
textParts.push(
|
|
795
|
+
"Note: The element [ID]s above are from other windows — you can reference them for context but can only interact with the focused window's elements.",
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
if (obs.screenshot) {
|
|
800
|
+
textParts.push('');
|
|
801
|
+
textParts.push(
|
|
802
|
+
'A screenshot of the FULL SCREEN is also attached above. Use it to see content outside the focused window (e.g., reference documents, PDFs, other apps visible behind the current window).',
|
|
803
|
+
);
|
|
804
|
+
const screenshotMetadata = this.formatScreenshotMetadata(obs);
|
|
805
|
+
if (screenshotMetadata.length > 0) {
|
|
806
|
+
textParts.push(...screenshotMetadata);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
} else if (obs.screenshot) {
|
|
810
|
+
textParts.push('CURRENT SCREEN STATE:');
|
|
811
|
+
textParts.push('See the screenshot above. No accessibility tree available — estimate coordinates from the image.');
|
|
812
|
+
const screenshotMetadata = this.formatScreenshotMetadata(obs);
|
|
813
|
+
if (screenshotMetadata.length > 0) {
|
|
814
|
+
textParts.push(...screenshotMetadata);
|
|
815
|
+
}
|
|
816
|
+
} else {
|
|
817
|
+
textParts.push('CURRENT SCREEN STATE:');
|
|
818
|
+
textParts.push('No screen data available.');
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// Action history
|
|
822
|
+
if (this.actionHistory.length > 0) {
|
|
823
|
+
textParts.push('');
|
|
824
|
+
textParts.push('ACTIONS TAKEN SO FAR:');
|
|
825
|
+
let windowedHistory: ActionRecord[];
|
|
826
|
+
if (this.actionHistory.length > MAX_HISTORY_ENTRIES) {
|
|
827
|
+
textParts.push(
|
|
828
|
+
` [... ${this.actionHistory.length - MAX_HISTORY_ENTRIES} earlier actions omitted]`,
|
|
829
|
+
);
|
|
830
|
+
windowedHistory = this.actionHistory.slice(-MAX_HISTORY_ENTRIES);
|
|
831
|
+
} else {
|
|
832
|
+
windowedHistory = this.actionHistory;
|
|
833
|
+
}
|
|
834
|
+
for (const record of windowedHistory) {
|
|
835
|
+
const result = record.result ?? 'executed';
|
|
836
|
+
textParts.push(` ${record.step}. ${record.toolName} → ${result}`);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Loop detection warning
|
|
841
|
+
if (this.actionHistory.length >= LOOP_DETECTION_WINDOW) {
|
|
842
|
+
const recent = this.actionHistory.slice(-LOOP_DETECTION_WINDOW);
|
|
843
|
+
const allIdentical = recent.every(
|
|
844
|
+
(r) =>
|
|
845
|
+
r.toolName === recent[0].toolName &&
|
|
846
|
+
JSON.stringify(r.input) === JSON.stringify(recent[0].input),
|
|
847
|
+
);
|
|
848
|
+
if (allIdentical) {
|
|
849
|
+
textParts.push('');
|
|
850
|
+
textParts.push(
|
|
851
|
+
`WARNING: You have repeated the exact same action (${recent[0].toolName}) ${LOOP_DETECTION_WINDOW} times in a row. You MUST try a completely different approach or call computer_use_done with an explanation of why you are stuck.`,
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// Prompt for next action
|
|
857
|
+
textParts.push('');
|
|
858
|
+
if (this.actionHistory.length === 0) {
|
|
859
|
+
textParts.push('This is the first action. Examine the screen state and decide what to do first.');
|
|
860
|
+
} else {
|
|
861
|
+
textParts.push('Decide the next action to take.');
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
contentBlocks.push({
|
|
865
|
+
type: 'text',
|
|
866
|
+
text: textParts.join('\n'),
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
return [{ role: 'user', content: contentBlocks }];
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
private formatScreenshotMetadata(obs: CuObservation): string[] {
|
|
873
|
+
if (!obs.screenshot) return [];
|
|
874
|
+
|
|
875
|
+
const lines: string[] = [];
|
|
876
|
+
if (obs.screenshotWidthPx != null && obs.screenshotHeightPx != null) {
|
|
877
|
+
lines.push(`Screenshot metadata: ${obs.screenshotWidthPx}x${obs.screenshotHeightPx} px`);
|
|
878
|
+
}
|
|
879
|
+
if (obs.screenWidthPt != null && obs.screenHeightPt != null) {
|
|
880
|
+
lines.push(`Screen metadata: ${obs.screenWidthPt}x${obs.screenHeightPt} pt`);
|
|
881
|
+
}
|
|
882
|
+
if (obs.coordinateOrigin) {
|
|
883
|
+
lines.push(`Coordinate origin: ${obs.coordinateOrigin}`);
|
|
884
|
+
}
|
|
885
|
+
if (obs.captureDisplayId != null) {
|
|
886
|
+
lines.push(`Capture display ID: ${obs.captureDisplayId}`);
|
|
887
|
+
}
|
|
888
|
+
return lines;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
hasPendingConfirmation(requestId: string): boolean {
|
|
892
|
+
return this.prompter?.hasPendingRequest(requestId) ?? false;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
handleConfirmationResponse(
|
|
896
|
+
requestId: string,
|
|
897
|
+
decision: UserDecision,
|
|
898
|
+
selectedPattern?: string,
|
|
899
|
+
selectedScope?: string,
|
|
900
|
+
): void {
|
|
901
|
+
this.prompter?.resolveConfirmation(requestId, decision, selectedPattern, selectedScope);
|
|
902
|
+
}
|
|
903
|
+
}
|