@vellumai/assistant 0.12.2 → 0.12.3-staging.2
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/.env.example +2 -0
- package/AGENTS.md +1 -1
- package/ARCHITECTURE.md +43 -29
- package/Dockerfile +63 -0
- package/docs/architecture/integrations.md +7 -0
- package/docs/architecture/memory.md +17 -2
- package/docs/architecture/security.md +10 -5
- package/docs/architecture/turn-actor.md +2 -0
- package/docs/credential-execution-service.md +1 -1
- package/docs/desktop-browser-cli.md +50 -5
- package/docs/live-voice-task-outcomes.md +100 -0
- package/docs/mode-sessions.md +183 -0
- package/docs/voice-input-diagnostics.md +58 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
- package/node_modules/@vellumai/environments/src/shell.ts +24 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -1
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +38 -7
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +5 -6
- package/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
- package/openapi.yaml +716 -16
- package/package.json +1 -1
- package/scripts/smoke-desktop-browser-cli.ts +11 -26
- package/scripts/smoke-desktop-window-theme.ts +2 -3
- package/scripts/sync-llm-catalog.ts +3 -0
- package/scripts/voice-ttft-spike.ts +2 -2
- package/src/__tests__/agent-loop-output-hooks.test.ts +150 -1
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +87 -19
- package/src/__tests__/agent-loop.test.ts +259 -0
- package/src/__tests__/agent-wake-delegation-prompt.test.ts +64 -2
- package/src/__tests__/annotate-activity-metadata.test.ts +3 -1
- package/src/__tests__/annotate-risk-options.test.ts +2 -0
- package/src/__tests__/answered-question-persistence.test.ts +2 -0
- package/src/__tests__/anthropic-gateway-shared.test.ts +22 -0
- package/src/__tests__/anthropic-provider.test.ts +55 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
- package/src/__tests__/approval-message-composer.test.ts +1 -118
- package/src/__tests__/approval-routes-http.test.ts +3 -0
- package/src/__tests__/assistant-event-hub-connection-history.test.ts +111 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +50 -0
- package/src/__tests__/assistant-event-targeting.test.ts +186 -0
- package/src/__tests__/assistant-stream-state.test.ts +29 -9
- package/src/__tests__/attachments-store.test.ts +22 -3
- package/src/__tests__/browser-fill-credential.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +4 -1
- package/src/__tests__/build-persisted-content.test.ts +1 -1
- package/src/__tests__/call-conversation-messages.test.ts +5 -0
- package/src/__tests__/call-recovery.test.ts +7 -2
- package/src/__tests__/call-routes-http.test.ts +12 -0
- package/src/__tests__/call-store.test.ts +7 -2
- package/src/__tests__/channel-approval.test.ts +9 -14
- package/src/__tests__/channel-reply-delivery.test.ts +56 -0
- package/src/__tests__/channel-retry-sweep.test.ts +9 -0
- package/src/__tests__/chat-credential-redaction.test.ts +23 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +2 -0
- package/src/__tests__/checker.test.ts +11 -3
- package/src/__tests__/client-os-metadata-persistence.test.ts +35 -1
- package/src/__tests__/computer-use-screenshot-attachments.test.ts +411 -0
- package/src/__tests__/computer-use-screenshot-selection.test.ts +50 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -25
- package/src/__tests__/computer-use-tools.test.ts +1 -233
- package/src/__tests__/config-model-image-provider.test.ts +39 -0
- package/src/__tests__/config-schema.test.ts +16 -0
- package/src/__tests__/config-watcher.test.ts +24 -0
- package/src/__tests__/context-search-agent-runner.test.ts +260 -1
- package/src/__tests__/context-search-fanout.test.ts +1 -1
- package/src/__tests__/context-search-types.test.ts +7 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +8 -2
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +797 -16
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
- package/src/__tests__/conversation-attachments.test.ts +106 -0
- package/src/__tests__/conversation-evictor.test.ts +62 -37
- package/src/__tests__/conversation-fork-crud.test.ts +191 -0
- package/src/__tests__/conversation-history-boundary-repair-failure.test.ts +174 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +2 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
- package/src/__tests__/conversation-rendered-delegation-state.test.ts +276 -0
- package/src/__tests__/conversation-retry-route.test.ts +22 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +2 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +2 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +10 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +2 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -0
- package/src/__tests__/conversation-surface-snapshots.test.ts +543 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +151 -0
- package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +63 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +23 -0
- package/src/__tests__/conversation-undo.test.ts +61 -0
- package/src/__tests__/credential-execution-client.test.ts +72 -55
- package/src/__tests__/credential-prompt-route.test.ts +35 -3
- package/src/__tests__/cu-unified-flow.test.ts +82 -1
- package/src/__tests__/db-conversation-tool-surface.test.ts +221 -0
- package/src/__tests__/db-mode-sessions-migration.test.ts +175 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -0
- package/src/__tests__/dm-backfill.test.ts +91 -1
- package/src/__tests__/document-create-route.test.ts +88 -0
- package/src/__tests__/document-sync-tags.test.ts +27 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +142 -2
- package/src/__tests__/events-tail-route.test.ts +58 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +57 -8
- package/src/__tests__/guardian-action-sweep.test.ts +16 -0
- package/src/__tests__/guardian-dispatch.test.ts +13 -0
- package/src/__tests__/headless-browser-interactions.test.ts +64 -20
- package/src/__tests__/heartbeat-service.test.ts +2 -59
- package/src/__tests__/helpers/mock-conversation.ts +21 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +2 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +5 -0
- package/src/__tests__/history-repair.test.ts +53 -0
- package/src/__tests__/host-cu-proxy.test.ts +46 -2
- package/src/__tests__/http-user-message-parity.test.ts +2 -0
- package/src/__tests__/image-credentials.test.ts +49 -0
- package/src/__tests__/image-service-dispatcher.test.ts +45 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +26 -0
- package/src/__tests__/interrupt-on-send.test.ts +57 -43
- package/src/__tests__/interrupt-turn-note.test.ts +5 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +85 -1
- package/src/__tests__/llm-catalog-parity.test.ts +27 -4
- package/src/__tests__/media-generate-image.test.ts +49 -1
- package/src/__tests__/message-provenance-contact-id.test.ts +69 -0
- package/src/__tests__/migration-export-to-gcs.test.ts +142 -0
- package/src/__tests__/mode-session-history.test.ts +245 -0
- package/src/__tests__/mode-session-recovery.test.ts +222 -0
- package/src/__tests__/mode-session-wire.test.ts +141 -0
- package/src/__tests__/notification-guardian-path.test.ts +7 -0
- package/src/__tests__/notification-telegram-adapter.test.ts +2 -2
- package/src/__tests__/notification-vellum-adapter.test.ts +34 -0
- package/src/__tests__/oauth-apps-routes.test.ts +1 -0
- package/src/__tests__/oauth-commands-routes.test.ts +114 -101
- package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +13 -0
- package/src/__tests__/oauth-providers-routes.test.ts +3 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/persist-media-references.test.ts +50 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
- package/src/__tests__/plugin-api-provider.test.ts +5 -0
- package/src/__tests__/plugin-api-resolve-credential.test.ts +97 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +9 -1
- package/src/__tests__/process-message-display-content.test.ts +56 -0
- package/src/__tests__/reaction-persistence.test.ts +5 -0
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +25 -9
- package/src/__tests__/run-conversation-turn-persistence.test.ts +138 -1
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +20 -0
- package/src/__tests__/scheduler-result-notification.test.ts +23 -4
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/scripted-turn-metadata-persistence.test.ts +73 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +86 -31
- package/src/__tests__/secret-routes-scrub.test.ts +22 -27
- package/src/__tests__/secret-scanner.test.ts +20 -0
- package/src/__tests__/secure-keys-managed-failover.test.ts +8 -0
- package/src/__tests__/secure-keys.test.ts +50 -4
- package/src/__tests__/send-endpoint-busy.test.ts +163 -1
- package/src/__tests__/server-history-render.test.ts +91 -1
- package/src/__tests__/server-tool-pairing.test.ts +107 -0
- package/src/__tests__/settings-routes.test.ts +50 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
- package/src/__tests__/skills.test.ts +5 -4
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -2
- package/src/__tests__/subagent-manager-notify.test.ts +1 -2
- package/src/__tests__/subagent-notify-parent.test.ts +146 -39
- package/src/__tests__/subagent-notify-stale-rebuild.test.ts +2 -4
- package/src/__tests__/subagent-tool-gate-mode.test.ts +226 -0
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/thread-backfill.test.ts +53 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
- package/src/__tests__/tool-result-follow-up.test.ts +99 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +66 -1
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/twilio-routes.test.ts +1 -0
- package/src/__tests__/unicode.test.ts +36 -0
- package/src/__tests__/web-search-backend-failure.test.ts +1 -1
- package/src/activation/progress-store.test.ts +12 -7
- package/src/agent/loop.ts +136 -53
- package/src/agent/tool-result-follow-up.ts +70 -0
- package/src/api/attachment-provenance.test.ts +68 -0
- package/src/api/computer-use-tool.test.ts +55 -0
- package/src/api/computer-use-tool.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +3 -0
- package/src/api/events/assistant-turn-start.ts +3 -0
- package/src/api/events/desktop-activity-changed.ts +10 -0
- package/src/api/events/generation-handoff.ts +2 -0
- package/src/api/events/message-complete.ts +2 -0
- package/src/api/events/notification-conversation-created.ts +14 -16
- package/src/api/events/notification-intent.ts +4 -2
- package/src/api/events/question-request.ts +1 -0
- package/src/api/events/tool-result.ts +85 -0
- package/src/api/events/tool-use-start.ts +3 -0
- package/src/api/events/user-message-echo.ts +3 -0
- package/src/api/index.ts +42 -6
- package/src/api/mode-session.test.ts +131 -0
- package/src/api/mode-session.ts +148 -0
- package/src/api/remember-tool.ts +15 -0
- package/src/api/responses/conversation-message.ts +9 -0
- package/src/approvals/AGENTS.md +4 -2
- package/src/approvals/approval-primitive.ts +5 -2
- package/src/approvals/scoped-approval-grants.ts +6 -2
- package/src/browser/__tests__/operations.test.ts +29 -0
- package/src/browser/operation-meta.ts +2 -1
- package/src/browser/operations.ts +29 -0
- package/src/browser/virtual-desktop-target.ts +2 -9
- package/src/bundler/bundle-signer.ts +1 -3
- package/src/calls/__tests__/barge-in-guard.test.ts +3 -0
- package/src/calls/__tests__/call-controller.test.ts +94 -0
- package/src/calls/__tests__/call-funnel-telemetry.test.ts +204 -0
- package/src/calls/__tests__/voice-control-protocol.test.ts +15 -0
- package/src/calls/__tests__/voice-escalation-judge.test.ts +209 -0
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +168 -0
- package/src/{live-voice/__tests__/live-voice-metrics.test.ts → calls/__tests__/voice-metrics.test.ts} +32 -38
- package/src/calls/__tests__/voice-session-bridge.test.ts +576 -122
- package/src/calls/barge-in-guard.ts +5 -0
- package/src/calls/call-controller.ts +196 -1
- package/src/calls/call-domain.ts +4 -0
- package/src/calls/call-store.ts +87 -2
- package/src/calls/guardian-action-sweep.ts +22 -8
- package/src/calls/media-stream-audio-transcode.ts +1 -3
- package/src/calls/typesafe-noul.ts +156 -0
- package/src/calls/voice-control-protocol.ts +6 -0
- package/src/calls/voice-escalation-judge.ts +145 -0
- package/src/calls/voice-escalation-target.ts +10 -0
- package/src/calls/voice-leg-coordinator.ts +121 -3
- package/src/{live-voice/live-voice-metrics.ts → calls/voice-metrics.ts} +94 -87
- package/src/calls/voice-session-bridge.ts +256 -112
- package/src/calls/voice-triage-escalate.ts +7 -0
- package/src/cli/__tests__/roadmap-cli.test.ts +4 -41
- package/src/cli/commands/__tests__/cli-test-harness.ts +21 -3
- package/src/cli/commands/__tests__/notifications.test.ts +35 -10
- package/src/cli/commands/__tests__/plugins.test.ts +20 -1
- package/src/cli/commands/__tests__/schedules.test.ts +14 -0
- package/src/cli/commands/bash.help.ts +4 -3
- package/src/cli/commands/browser.help.ts +9 -6
- package/src/cli/commands/browser.ts +0 -1
- package/src/cli/commands/clients.help.ts +46 -0
- package/src/cli/commands/clients.ts +116 -0
- package/src/cli/commands/credentials.help.ts +9 -4
- package/src/cli/commands/notifications.help.ts +16 -2
- package/src/cli/commands/notifications.ts +30 -8
- package/src/cli/commands/oauth/index.help.ts +10 -0
- package/src/cli/commands/oauth/providers.ts +12 -0
- package/src/cli/commands/oauth/request.test.ts +179 -2
- package/src/cli/commands/oauth/request.ts +41 -10
- package/src/cli/commands/plugins.ts +12 -5
- package/src/cli/commands/roadmap.help.ts +18 -21
- package/src/cli/commands/roadmap.ts +4 -21
- package/src/cli/commands/schedules.ts +2 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +41 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
- package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +133 -51
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +8 -2
- package/src/cli/lib/bundled-marketplace.json +906 -1
- package/src/cli/lib/bundled-plugin-packages.json +783 -1
- package/src/cli/lib/inspect-plugin.ts +11 -4
- package/src/cli/lib/plugin-marketplace.ts +8 -0
- package/src/cli/lib/publish-plugin.ts +1 -2
- package/src/cli/lib/upgrade-plugin.ts +19 -11
- package/src/cli/output.ts +18 -4
- package/src/config/__tests__/default-provider.test.ts +6 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +14 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +1 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +89 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +17 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -11
- package/src/config/bundled-skills/schedule/SKILL.md +6 -6
- package/src/config/bundled-skills/sequences/TOOLS.json +1 -5
- package/src/config/call-site-defaults.ts +9 -0
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/loader.ts +9 -17
- package/src/config/platform-identity.ts +8 -8
- package/src/config/profile-text-generation.test.ts +51 -0
- package/src/config/profile-text-generation.ts +51 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +12 -0
- package/src/config/schemas/__tests__/tools.test.ts +31 -0
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/channels.ts +0 -18
- package/src/config/schemas/llm.ts +9 -2
- package/src/config/schemas/mcp.ts +6 -1
- package/src/config/schemas/memory-retrospective.ts +11 -2
- package/src/config/schemas/memory-v3.ts +12 -0
- package/src/config/schemas/services.ts +15 -6
- package/src/config/schemas/tools.ts +10 -0
- package/src/config/session-groups-gate.ts +21 -0
- package/src/config/skills.ts +2 -6
- package/src/conversations/__tests__/message-consolidation.test.ts +149 -0
- package/src/conversations/message-consolidation.ts +102 -5
- package/src/credential-execution/ces-connect.test.ts +69 -0
- package/src/credential-execution/ces-connect.ts +115 -0
- package/src/credential-execution/ces-runtime.ts +55 -93
- package/src/credential-execution/executable-discovery.ts +34 -142
- package/src/credential-execution/process-manager.test.ts +20 -24
- package/src/credential-execution/process-manager.ts +24 -19
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +43 -0
- package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +36 -0
- package/src/daemon/assistant-attachments.ts +20 -12
- package/src/daemon/browser-mode-session.test.ts +402 -0
- package/src/daemon/browser-mode-session.ts +186 -0
- package/src/daemon/chat-credential-redaction.ts +16 -1
- package/src/daemon/computer-use-mode-session.test.ts +210 -0
- package/src/daemon/computer-use-mode-session.ts +105 -0
- package/src/daemon/config-watcher.ts +10 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +132 -13
- package/src/daemon/conversation-agent-loop.ts +231 -25
- package/src/daemon/conversation-attachments.ts +93 -12
- package/src/daemon/conversation-evictor.ts +5 -24
- package/src/daemon/conversation-history.ts +10 -0
- package/src/daemon/conversation-interrupt-repair.ts +4 -43
- package/src/daemon/conversation-interrupt.ts +7 -11
- package/src/daemon/conversation-messaging.ts +58 -5
- package/src/daemon/conversation-mode-session.test.ts +1667 -0
- package/src/daemon/conversation-mode-session.ts +1008 -0
- package/src/daemon/conversation-process.ts +5 -0
- package/src/daemon/conversation-runtime-assembly.ts +10 -20
- package/src/daemon/conversation-skill-tools.ts +1 -0
- package/src/daemon/conversation-store.ts +4 -4
- package/src/daemon/conversation-surface-snapshots.ts +135 -0
- package/src/daemon/conversation-surfaces.ts +113 -5
- package/src/daemon/conversation-tool-setup.ts +79 -6
- package/src/daemon/conversation-turn-finalize.ts +26 -13
- package/src/daemon/conversation.ts +215 -58
- package/src/daemon/daemon-control.ts +3 -7
- package/src/daemon/handlers/config-model.ts +7 -5
- package/src/daemon/handlers/shared.ts +55 -16
- package/src/daemon/host-cu-proxy.ts +51 -22
- package/src/daemon/lifecycle.ts +30 -13
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/message-protocol.ts +0 -1
- package/src/daemon/message-provenance.ts +28 -4
- package/src/daemon/message-types/shared.ts +1 -0
- package/src/daemon/mode-session-startup-recovery.ts +23 -0
- package/src/daemon/mode-session-tracking.ts +54 -0
- package/src/daemon/orphan-reaper.ts +4 -3
- package/src/daemon/persist-media-references.ts +20 -3
- package/src/daemon/process-message.ts +13 -4
- package/src/daemon/tool-setup-types.ts +6 -0
- package/src/daemon/virtual-desktop-context.ts +21 -0
- package/src/daemon/wake-conversation-ops.ts +50 -15
- package/src/desktop/__tests__/fake-desktop.ts +1 -0
- package/src/desktop/desktop-accessibility-script.ts +88 -0
- package/src/desktop/desktop-accessibility.test.ts +160 -0
- package/src/desktop/desktop-accessibility.ts +169 -0
- package/src/desktop/desktop-automation-lease.test.ts +302 -64
- package/src/desktop/desktop-automation-lease.ts +129 -54
- package/src/desktop/desktop-browser-endpoint.ts +4 -0
- package/src/desktop/desktop-computer-use-routing.test.ts +330 -0
- package/src/desktop/desktop-computer-use.test.ts +449 -0
- package/src/desktop/desktop-computer-use.ts +502 -0
- package/src/desktop/desktop-dependencies.ts +47 -293
- package/src/desktop/desktop-display.ts +2 -2
- package/src/desktop/desktop-help.ts +15 -0
- package/src/desktop/desktop-panel-config.test.ts +13 -3
- package/src/desktop/desktop-panel-config.ts +109 -15
- package/src/desktop/desktop-session-manager.test.ts +69 -21
- package/src/desktop/desktop-session-manager.ts +76 -22
- package/src/desktop/desktop-stream-bridge.test.ts +76 -132
- package/src/desktop/desktop-stream-bridge.ts +9 -11
- package/src/desktop/desktop-wallpaper-renderer.ts +132 -0
- package/src/desktop/desktop-wallpaper-worker.ts +17 -0
- package/src/desktop/desktop-wallpaper.test.ts +48 -7
- package/src/desktop/desktop-wallpaper.ts +34 -102
- package/src/desktop/desktop-window-theme.ts +5 -25
- package/src/desktop/virtual-desktop-feature.ts +53 -3
- package/src/desktop/virtual-desktop-platform.test.ts +5 -9
- package/src/documents/document-store.ts +23 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +22 -26
- package/src/heartbeat/heartbeat-service.ts +5 -33
- package/src/ipc/__tests__/browser-ipc.test.ts +215 -6
- package/src/ipc/assistant-server.ts +2 -0
- package/src/ipc/routes/__tests__/channel-reply-ipc-routes.test.ts +111 -0
- package/src/ipc/routes/channel-reply-ipc-routes.ts +73 -0
- package/src/live-voice/__tests__/continuation-judge.test.ts +151 -0
- package/src/live-voice/__tests__/live-activity-reporter.test.ts +154 -15
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +743 -31
- package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +191 -10
- package/src/live-voice/__tests__/live-voice-session-groups-gate.test.ts +87 -0
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +5 -1
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +41 -0
- package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +1017 -9
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +224 -1
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +101 -0
- package/src/live-voice/__tests__/live-voice-tts.test.ts +44 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +939 -75
- package/src/live-voice/__tests__/microphone-idle-gate.test.ts +87 -0
- package/src/live-voice/__tests__/session-controls.test.ts +23 -0
- package/src/live-voice/__tests__/task-outcomes.test.ts +117 -0
- package/src/live-voice/__tests__/voice-input-diagnostics.test.ts +117 -0
- package/src/live-voice/camera-mode-session.test.ts +265 -0
- package/src/live-voice/camera-mode-session.ts +277 -0
- package/src/live-voice/continuation-judge.ts +123 -0
- package/src/live-voice/live-activity-reporter.ts +115 -6
- package/src/live-voice/live-voice-manager.ts +36 -1
- package/src/live-voice/live-voice-photo.ts +88 -7
- package/src/live-voice/live-voice-session-manager.ts +15 -0
- package/src/live-voice/live-voice-session.ts +1443 -747
- package/src/live-voice/live-voice-tts.ts +22 -4
- package/src/live-voice/microphone-idle-gate.ts +56 -0
- package/src/live-voice/protocol.ts +171 -4
- package/src/live-voice/session-controls.ts +11 -3
- package/src/live-voice/task-outcomes.ts +131 -0
- package/src/live-voice/voice-input-diagnostics.ts +117 -0
- package/src/mcp/__tests__/manager-tool-caps.test.ts +156 -0
- package/src/mcp/__tests__/startup.test.ts +30 -7
- package/src/mcp/__tests__/tool-caps.test.ts +134 -0
- package/src/mcp/manager.ts +171 -101
- package/src/mcp/startup.ts +33 -13
- package/src/mcp/tool-caps.ts +184 -0
- package/src/media/__tests__/image-models.test.ts +58 -0
- package/src/media/image-credentials.ts +5 -0
- package/src/media/image-models.ts +52 -0
- package/src/media/image-service.ts +8 -0
- package/src/media/openrouter-image-service.test.ts +133 -0
- package/src/media/openrouter-image-service.ts +153 -0
- package/src/media/types.ts +1 -1
- package/src/messaging/provider-message-metadata.ts +3 -3
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +65 -11
- package/src/messaging/providers/discord/send.ts +4 -17
- package/src/messaging/providers/discord/transport.ts +2 -2
- package/src/messaging/providers/outlook/client.ts +16 -22
- package/src/messaging/providers/telegram-bot/send.test.ts +236 -1
- package/src/messaging/providers/telegram-bot/send.ts +10 -7
- package/src/messaging/providers/telegram-bot/transport.ts +3 -10
- package/src/messaging/providers/whatsapp/send.test.ts +169 -4
- package/src/monitoring/__tests__/control.test.ts +17 -5
- package/src/monitoring/control.ts +15 -5
- package/src/notifications/AGENTS.md +1 -1
- package/src/notifications/README.md +83 -99
- package/src/notifications/__tests__/broadcaster.test.ts +1 -1
- package/src/notifications/__tests__/channel-allowlist.test.ts +39 -0
- package/src/notifications/__tests__/copy-composer.test.ts +71 -1
- package/src/notifications/__tests__/decision-engine.test.ts +79 -2
- package/src/notifications/__tests__/deterministic-checks.test.ts +10 -10
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +93 -4
- package/src/notifications/__tests__/notification-utils.test.ts +18 -0
- package/src/notifications/adapters/macos.ts +37 -46
- package/src/notifications/broadcaster.ts +5 -6
- package/src/notifications/channel-allowlist.ts +44 -0
- package/src/notifications/copy-composer.ts +11 -26
- package/src/notifications/decision-engine.ts +24 -14
- package/src/notifications/deterministic-checks.ts +1 -1
- package/src/notifications/emit-signal.ts +123 -37
- package/src/notifications/home-feed-side-effect.ts +9 -7
- package/src/notifications/notification-utils.ts +19 -0
- package/src/notifications/schedule-result-producer.ts +4 -6
- package/src/notifications/signal.ts +4 -19
- package/src/notifications/types.ts +15 -0
- package/src/oauth/AGENTS.md +2 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +36 -1
- package/src/oauth/connection-resolver.ts +1 -2
- package/src/oauth/identity-verifier.ts +24 -0
- package/src/oauth/oauth-store.ts +12 -4
- package/src/oauth/provider-serializer.ts +8 -0
- package/src/oauth/seed-providers.ts +42 -0
- package/src/onboarding/onboarding-events-store.ts +99 -12
- package/src/permissions/confirmation-guardian-request.test.ts +16 -0
- package/src/permissions/confirmation-guardian-request.ts +2 -3
- package/src/permissions/question-prompter.test.ts +31 -0
- package/src/permissions/question-prompter.ts +2 -0
- package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
- package/src/persistence/attachments-store.ts +84 -44
- package/src/persistence/client-connection-events-store.ts +377 -0
- package/src/persistence/conversation-crud.ts +166 -26
- package/src/persistence/conversation-mode-sessions.test.ts +424 -0
- package/src/persistence/conversation-mode-sessions.ts +460 -0
- package/src/persistence/conversation-plugin-facade.ts +30 -0
- package/src/persistence/conversation-queries.ts +6 -19
- package/src/persistence/conversation-tool-surface.ts +135 -0
- package/src/persistence/conversation-types.test.ts +32 -0
- package/src/persistence/conversation-types.ts +26 -4
- package/src/persistence/llm-usage-store.ts +3 -9
- package/src/persistence/message-metadata.ts +25 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
- package/src/persistence/migrations/379-oauth-providers-response-ok-field.test.ts +92 -0
- package/src/persistence/migrations/379-oauth-providers-response-ok-field.ts +32 -0
- package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.test.ts +90 -0
- package/src/persistence/migrations/380-conversation-tool-surfaces-delegate-independent-tasks.ts +34 -0
- package/src/persistence/migrations/381-create-conversation-mode-sessions.ts +41 -0
- package/src/persistence/migrations/382-create-client-connection-events.ts +40 -0
- package/src/persistence/migrations/__tests__/382-create-client-connection-events.test.ts +56 -0
- package/src/persistence/schema/conversation-tool-surfaces.ts +32 -0
- package/src/persistence/schema/conversations.ts +67 -0
- package/src/persistence/schema/index.ts +1 -0
- package/src/persistence/schema/infrastructure.ts +29 -0
- package/src/persistence/schema/oauth.ts +1 -0
- package/src/persistence/steps.ts +41 -3
- package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
- package/src/plugin-api/conversation-turn.ts +31 -7
- package/src/plugin-api/effective-context-window.ts +33 -0
- package/src/plugin-api/index.ts +35 -6
- package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
- package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
- package/src/plugin-api/plugin-name-env.ts +125 -0
- package/src/plugin-api/resolve-credential.ts +79 -20
- package/src/plugin-api/vision-support.test.ts +22 -0
- package/src/plugin-api/vision-support.ts +17 -5
- package/src/plugins/__tests__/active-plugin-env.test.ts +136 -0
- package/src/plugins/active-plugin-env.ts +51 -0
- package/src/plugins/defaults/index.ts +24 -0
- package/src/plugins/defaults/memory/AGENTS.md +39 -5
- package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
- package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +365 -0
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
- package/src/plugins/defaults/memory/__tests__/conversation-memory-purge.test.ts +1 -0
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +2 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +74 -0
- package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
- package/src/plugins/defaults/memory/__tests__/relocated-memory-test-rows.ts +10 -0
- package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
- package/src/plugins/defaults/memory/buffer-file.ts +354 -0
- package/src/plugins/defaults/memory/buffer-format.ts +40 -0
- package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +77 -22
- package/src/plugins/defaults/memory/context-search/format.ts +53 -8
- package/src/plugins/defaults/memory/context-search/limits.ts +10 -12
- package/src/plugins/defaults/memory/context-search/recall-input.ts +38 -0
- package/src/plugins/defaults/memory/context-search/search.ts +8 -14
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +1 -0
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +2 -1
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +2 -1
- package/src/plugins/defaults/memory/context-search/types.ts +1 -11
- package/src/plugins/defaults/memory/conversation-memory-purge.ts +4 -0
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
- package/src/plugins/defaults/memory/graph/capability-seed.ts +1 -2
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +13 -63
- package/src/plugins/defaults/memory/graph/tools.ts +35 -64
- package/src/plugins/defaults/memory/host-utils.ts +0 -10
- package/src/plugins/defaults/memory/injectors.ts +4 -3
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +72 -183
- package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
- package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +6 -1
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
- package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +2 -1
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +91 -51
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
- package/src/plugins/defaults/memory/tools.test.ts +124 -9
- package/src/plugins/defaults/memory/tools.ts +38 -11
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +2 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +2 -1
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
- package/src/plugins/defaults/memory/v2/reranker.ts +2 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
- package/src/plugins/defaults/memory/v3/__tests__/plugin-schema.test.ts +12 -0
- package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +332 -15
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +148 -28
- package/src/plugins/defaults/memory/v3/card.ts +2 -1
- package/src/plugins/defaults/memory/v3/injector.ts +212 -178
- package/src/plugins/defaults/memory/v3/orchestrate.ts +159 -32
- package/src/plugins/defaults/memory/v3/plugin-schema.ts +54 -4
- package/src/plugins/defaults/memory/v3/pool-log-store.ts +275 -37
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +47 -5
- package/src/plugins/defaults/memory/v3/pool-select.ts +710 -59
- package/src/plugins/defaults/memory/v3/sections.ts +2 -1
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +41 -14
- package/src/plugins/defaults/memory/worker-control.ts +15 -5
- package/src/plugins/defaults/task-progress/__tests__/registration.test.ts +70 -0
- package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +380 -0
- package/src/plugins/defaults/task-progress/hooks/post-compact.ts +19 -0
- package/src/plugins/defaults/task-progress/hooks/user-prompt-submit.ts +24 -0
- package/src/plugins/defaults/task-progress/package.json +14 -0
- package/src/plugins/defaults/task-progress/src/apply-task-progress-context.ts +93 -0
- package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +67 -0
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +4 -1
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
- package/src/prompts/__tests__/parallel-tasks-section.test.ts +25 -0
- package/src/prompts/delegation-gate.ts +57 -0
- package/src/prompts/system-prompt.ts +14 -32
- package/src/providers/__tests__/context-overflow-error.test.ts +10 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +18 -0
- package/src/providers/anthropic/client.ts +10 -1
- package/src/providers/anthropic-gateway-shared.ts +6 -0
- package/src/providers/fetch-provider-catalog.ts +11 -0
- package/src/providers/gemini/client.ts +25 -8
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/jev/client.test.ts +270 -0
- package/src/providers/jev/client.ts +534 -0
- package/src/providers/model-catalog.ts +59 -3
- package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +94 -1
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +106 -1
- package/src/providers/openai/__tests__/chat-template-flatten.test.ts +24 -0
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +1 -2
- package/src/providers/openai/chat-completions-provider.ts +100 -29
- package/src/providers/openai/google-thought-signature.ts +0 -6
- package/src/providers/openai/responses-provider.ts +23 -1
- package/src/providers/ratelimit.ts +1 -3
- package/src/providers/search-provider-catalog.ts +24 -0
- package/src/providers/server-tool-pairing.ts +16 -7
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +24 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +7 -1
- package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +50 -1
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +11 -0
- package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +13 -0
- package/src/providers/types.ts +5 -0
- package/src/routes/control.ts +7 -5
- package/src/runtime/AGENTS.md +6 -4
- package/src/runtime/__tests__/agent-wake.test.ts +94 -1
- package/src/runtime/actor-trust-resolver.ts +3 -3
- package/src/runtime/agent-wake.ts +32 -5
- package/src/runtime/approval-message-composer.ts +3 -69
- package/src/runtime/assistant-event-hub.ts +73 -75
- package/src/runtime/assistant-event-publish-options.ts +7 -0
- package/src/runtime/assistant-event-targeting.ts +79 -0
- package/src/runtime/assistant-stream-state.ts +13 -100
- package/src/runtime/background-job-runner.ts +5 -5
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/guardian-action-message-composer.ts +8 -161
- package/src/runtime/guardian-action-service.ts +2 -17
- package/src/runtime/guardian-reply-router.ts +29 -40
- package/src/runtime/http-server.ts +2 -2
- package/src/runtime/http-types.ts +6 -0
- package/src/runtime/message-composer-types.ts +3 -61
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +67 -1
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +89 -0
- package/src/runtime/migrations/vbundle-builder.ts +24 -1
- package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +43 -11
- package/src/runtime/migrations/vbundle-importer.ts +4 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +4 -1
- package/src/runtime/migrations/vbundle-validator.ts +1 -0
- package/src/runtime/pending-interactions-mode-session.test.ts +62 -0
- package/src/runtime/pending-interactions.ts +29 -0
- package/src/runtime/routes/__tests__/client-history-routes.test.ts +104 -0
- package/src/runtime/routes/__tests__/image-generation-routes.test.ts +97 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +24 -2
- package/src/runtime/routes/__tests__/roadmap-routes.test.ts +29 -6
- package/src/runtime/routes/browser-context.ts +31 -11
- package/src/runtime/routes/browser-routes.ts +43 -4
- package/src/runtime/routes/btw-routes.ts +9 -4
- package/src/runtime/routes/channel-route-shared.ts +1 -9
- package/src/runtime/routes/client-routes.ts +108 -0
- package/src/runtime/routes/conversation-management-routes.ts +4 -1
- package/src/runtime/routes/conversation-routes.ts +125 -14
- package/src/runtime/routes/credential-prompt-routes.ts +4 -3
- package/src/runtime/routes/credential-routes.ts +1 -2
- package/src/runtime/routes/desktop-setup-routes.test.ts +9 -18
- package/src/runtime/routes/desktop-setup-routes.ts +8 -7
- package/src/runtime/routes/documents-routes.ts +51 -0
- package/src/runtime/routes/email-routes.ts +3 -7
- package/src/runtime/routes/events-routes.ts +75 -54
- package/src/runtime/routes/guardian-approval-interception.ts +24 -0
- package/src/runtime/routes/identity-routes.ts +1 -5
- package/src/runtime/routes/image-generation-routes.ts +8 -14
- package/src/runtime/routes/inbound-message-handler.ts +37 -41
- package/src/runtime/routes/inbound-stages/backfill-sender-provenance.test.ts +168 -0
- package/src/runtime/routes/inbound-stages/backfill-sender-provenance.ts +96 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +39 -10
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +9 -9
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +11 -1
- package/src/runtime/routes/inference-profiles-routes.ts +9 -0
- package/src/runtime/routes/llm-context-normalization.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +73 -2
- package/src/runtime/routes/notification-routes.ts +10 -0
- package/src/runtime/routes/oauth-commands-routes.ts +57 -54
- package/src/runtime/routes/oauth-providers.ts +11 -0
- package/src/runtime/routes/oauth-request-hints.test.ts +246 -0
- package/src/runtime/routes/oauth-request-hints.ts +149 -0
- package/src/runtime/routes/plugins-routes.ts +6 -0
- package/src/runtime/routes/roadmap-routes.ts +47 -8
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/secret-routes.ts +99 -119
- package/src/runtime/routes/settings-routes.ts +10 -4
- package/src/runtime/routes/watcher-routes.ts +1 -3
- package/src/runtime/trust-class.test.ts +7 -6
- package/src/runtime/trust-class.ts +9 -17
- package/src/schedule/__tests__/worker-control.test.ts +36 -5
- package/src/schedule/__tests__/worker-mcp-bootstrap.test.ts +107 -0
- package/src/schedule/__tests__/worker-mcp-readiness.test.ts +173 -0
- package/src/schedule/__tests__/worker-mcp-tools.test.ts +13 -47
- package/src/schedule/run-script.ts +2 -2
- package/src/schedule/scheduler.ts +47 -11
- package/src/schedule/tool-surface-readiness.ts +65 -0
- package/src/schedule/worker-control.ts +15 -5
- package/src/schedule/worker-mcp.ts +85 -0
- package/src/schedule/worker.ts +9 -31
- package/src/security/secure-keys.ts +74 -112
- package/src/skills/clawhub.ts +3 -8
- package/src/skills/managed-store.ts +1 -5
- package/src/stt/types.ts +4 -0
- package/src/subagent/notify.ts +54 -34
- package/src/subagent/parent-notification.ts +6 -0
- package/src/telemetry/__tests__/phone-call-funnel.test.ts +72 -0
- package/src/telemetry/phone-call-funnel.ts +144 -0
- package/src/tools/__tests__/tool-schema-root-combinator-guard.test.ts +81 -0
- package/src/tools/ask-question/ask-question-tool.test.ts +167 -5
- package/src/tools/ask-question/ask-question-tool.ts +120 -22
- package/src/tools/browser/browser-execution.ts +29 -60
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +561 -39
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +435 -39
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +1 -8
- package/src/tools/client-os.ts +15 -0
- package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
- package/src/tools/computer-use/target.ts +42 -0
- package/src/tools/document/document-tool.ts +13 -18
- package/src/tools/execution-target.ts +14 -16
- package/src/tools/host-terminal/host-shell.ts +16 -7
- package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +250 -0
- package/src/tools/network/__tests__/web-search.test.ts +203 -0
- package/src/tools/network/web-fetch.ts +274 -7
- package/src/tools/network/web-search.ts +468 -6
- package/src/tools/permission-checker.ts +3 -3
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +1 -31
- package/src/tools/shared/shell-output.test.ts +10 -0
- package/src/tools/shared/shell-output.ts +14 -2
- package/src/tools/skills/load.ts +2 -1
- package/src/tools/skills/sandbox-runner.ts +24 -4
- package/src/tools/skills/scaffold-managed.ts +2 -1
- package/src/tools/skills/skill-script-runner.ts +7 -0
- package/src/tools/skills/skill-tool-factory.ts +15 -1
- package/src/tools/terminal/__tests__/safe-env.test.ts +44 -4
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -14
- package/src/tools/terminal/safe-env.ts +39 -24
- package/src/tools/terminal/sanitized-bash.ts +15 -2
- package/src/tools/terminal/shell-launch.test.ts +162 -0
- package/src/tools/terminal/shell.test.ts +29 -0
- package/src/tools/terminal/shell.ts +15 -7
- package/src/tools/tool-approval-handler.ts +5 -1
- package/src/tools/tool-types.ts +3 -3
- package/src/tools/types.ts +8 -2
- package/src/util/__tests__/worker-process-command.test.ts +5 -4
- package/src/util/abort-reasons.ts +18 -26
- package/src/util/browser-human-verification.ts +14 -0
- package/src/util/canonicalize-identity.test.ts +21 -0
- package/src/util/canonicalize-identity.ts +16 -0
- package/src/util/errors.ts +13 -3
- package/src/util/host-process.test.ts +17 -1
- package/src/util/host-process.ts +24 -0
- package/src/util/provider-error-patterns.ts +3 -0
- package/src/util/unicode.ts +29 -0
- package/src/util/worker-process.ts +77 -35
- package/src/workspace/migrations/157-add-desktop-files-launcher.ts +94 -0
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +4 -10
- package/src/workspace/migrations/__tests__/157-add-desktop-files-launcher.test.ts +113 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/computer-use-window-schema.test.ts +0 -24
- package/src/api/events/heartbeat-alert.ts +0 -20
- package/src/daemon/message-types/web-activity.ts +0 -65
- package/src/desktop/desktop-dependencies.test.ts +0 -131
- package/src/tools/computer-use/definitions.ts +0 -607
package/src/agent/loop.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { AnsweredQuestion } from "../api/events/question-answered.js";
|
|
2
|
+
import type { ToolActivityMetadata } from "../api/events/tool-result.js";
|
|
3
|
+
import { resolveCallSiteConfig } from "../config/llm-resolver.js";
|
|
4
|
+
import { getConfig } from "../config/loader.js";
|
|
2
5
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
3
6
|
import { SEND_USER_MESSAGE_TOOL_NAME } from "../config/send-user-message-constants.js";
|
|
4
7
|
import { recordEstimate } from "../context/estimator-calibration.js";
|
|
@@ -11,7 +14,6 @@ import {
|
|
|
11
14
|
getCalibrationProviderKey,
|
|
12
15
|
} from "../context/token-estimator.js";
|
|
13
16
|
import { spoolAndStubOversizedToolResults } from "../context/tool-result-spool.js";
|
|
14
|
-
import type { ToolActivityMetadata } from "../daemon/message-types/web-activity.js";
|
|
15
17
|
import { parseActualTokensFromError } from "../daemon/parse-actual-tokens-from-error.js";
|
|
16
18
|
import type { TrustContext } from "../daemon/trust-context-types.js";
|
|
17
19
|
import type {
|
|
@@ -42,6 +44,7 @@ import type {
|
|
|
42
44
|
Provider,
|
|
43
45
|
ProviderResponse,
|
|
44
46
|
SendMessageOptions,
|
|
47
|
+
TextContent,
|
|
45
48
|
ToolDefinition,
|
|
46
49
|
ToolResultContent,
|
|
47
50
|
} from "../providers/types.js";
|
|
@@ -74,6 +77,7 @@ import {
|
|
|
74
77
|
isRepairableOrderingError,
|
|
75
78
|
isUserTerminalHistoryError,
|
|
76
79
|
} from "./history-repair/history-repair.js";
|
|
80
|
+
import { buildToolResultFollowUp } from "./tool-result-follow-up.js";
|
|
77
81
|
|
|
78
82
|
const log = getLogger("agent-loop");
|
|
79
83
|
|
|
@@ -441,25 +445,26 @@ export type AgentEvent =
|
|
|
441
445
|
/**
|
|
442
446
|
* Emitted when the provider call throws — i.e. the provider
|
|
443
447
|
* rejected the request before returning a usable response. Carries
|
|
444
|
-
* the
|
|
445
|
-
* system prompt, provider-agnostic config) plus the thrown error.
|
|
448
|
+
* the wire request we attempted to send plus the thrown error.
|
|
446
449
|
* Consumers (`handleProviderError` in the daemon handlers, the
|
|
447
450
|
* `onEvent` in `agent-wake`) persist these as `llm_request_logs`
|
|
448
451
|
* rows so failed calls are queryable in the LLM inspector instead
|
|
449
452
|
* of only surfacing in pino logs.
|
|
450
453
|
*
|
|
451
|
-
* `rawRequest` is
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
454
|
+
* `rawRequest` is `ProviderError.rawRequest` when the throw carried
|
|
455
|
+
* an inspectable SDK/wire payload (including extra body fields such
|
|
456
|
+
* as `directions`). The loop does not invent a substitute snapshot
|
|
457
|
+
* of messages/tools/systemPrompt; a missing payload stays missing.
|
|
458
|
+
* `actualProvider` echoes `ProviderError.provider` so a routed
|
|
459
|
+
* invocation (e.g. Vellum via a Fireworks default wrapper) is
|
|
460
|
+
* attributed to the transport that actually ran.
|
|
456
461
|
*
|
|
457
462
|
* Re-thrown by the inner LLM-call try/catch after emission so the
|
|
458
463
|
* outer agent-loop catch still handles abort, the existing `error`
|
|
459
464
|
* event, and the loop break.
|
|
460
465
|
*/
|
|
461
466
|
type: "provider_error";
|
|
462
|
-
rawRequest
|
|
467
|
+
rawRequest?: unknown;
|
|
463
468
|
error: Error;
|
|
464
469
|
actualProvider?: string;
|
|
465
470
|
}
|
|
@@ -661,6 +666,18 @@ type AgentLoopContextWindowResolver = () => {
|
|
|
661
666
|
overflowRecovery: { enabled: boolean; safetyMarginRatio: number };
|
|
662
667
|
};
|
|
663
668
|
|
|
669
|
+
/** Final request surface after the pre-model hook has settled. */
|
|
670
|
+
export interface PreparedModelCall {
|
|
671
|
+
callSite?: LLMCallSite;
|
|
672
|
+
overrideProfile?: string;
|
|
673
|
+
forceOverrideProfile: boolean;
|
|
674
|
+
/** Present when the finalized route opts out of prompt caching. */
|
|
675
|
+
disableCache?: true;
|
|
676
|
+
signal?: AbortSignal;
|
|
677
|
+
systemPrompt: string | null;
|
|
678
|
+
tools: ToolDefinition[];
|
|
679
|
+
}
|
|
680
|
+
|
|
664
681
|
interface AgentLoopRunOptionsBase {
|
|
665
682
|
/** Input history the run starts from; the loop appends its output onto a copy. */
|
|
666
683
|
messages: Message[];
|
|
@@ -688,7 +705,10 @@ interface AgentLoopRunOptionsBase {
|
|
|
688
705
|
onCheckpoint?: (
|
|
689
706
|
checkpoint: CheckpointInfo,
|
|
690
707
|
) => CheckpointDecision | Promise<CheckpointDecision>;
|
|
708
|
+
/** Semantic call site exposed to hooks, events, and loop behavior. */
|
|
691
709
|
callSite?: LLMCallSite;
|
|
710
|
+
/** Provider-resolution call site when it differs from turn semantics. */
|
|
711
|
+
inferenceCallSite?: LLMCallSite;
|
|
692
712
|
/**
|
|
693
713
|
* Route this run's user-facing text through the `send_user_message` tool
|
|
694
714
|
* instead of streamed assistant text. The daemon sets it for main-agent runs
|
|
@@ -738,6 +758,8 @@ interface AgentLoopRunOptionsBase {
|
|
|
738
758
|
*/
|
|
739
759
|
forceOverrideProfile?: boolean;
|
|
740
760
|
resolveOverrideProfile?: () => string | undefined;
|
|
761
|
+
/** Observe a finalized model request without delaying provider dispatch. */
|
|
762
|
+
onModelCallPrepared?: (prepared: PreparedModelCall) => void;
|
|
741
763
|
/**
|
|
742
764
|
* When `true`, the loop owns turn-start and mid-loop compaction. The pre-call
|
|
743
765
|
* budget gate runs before the very first provider call — subsuming the
|
|
@@ -1047,6 +1069,17 @@ export interface AgentLoopConstructorOptions {
|
|
|
1047
1069
|
tools?: ToolDefinition[];
|
|
1048
1070
|
toolExecutor?: LoopToolExecutor;
|
|
1049
1071
|
resolveTools?: (history: Message[]) => ToolDefinition[];
|
|
1072
|
+
/**
|
|
1073
|
+
* Observer for the final tool array of each provider call, invoked
|
|
1074
|
+
* immediately before the request leaves with exactly what goes on the wire
|
|
1075
|
+
* (after any provider-native tool is appended, past the inter-call throttle
|
|
1076
|
+
* and the pre-model hooks, and not at all once the run is aborted). This is
|
|
1077
|
+
* the only point that sees the sent array: the dynamic `resolveTools`
|
|
1078
|
+
* callback is also consulted out of band (token counting, compaction
|
|
1079
|
+
* estimates), so a consumer that needs "what the last request sent"
|
|
1080
|
+
* subscribes here rather than wrapping the resolver. Must not throw.
|
|
1081
|
+
*/
|
|
1082
|
+
onToolsSent?: (tools: ToolDefinition[]) => void;
|
|
1050
1083
|
/**
|
|
1051
1084
|
* Conversation this loop drives. Scopes the loop-held compaction circuit
|
|
1052
1085
|
* breaker and is the source of truth the loop's pipeline contexts and
|
|
@@ -1087,6 +1120,7 @@ export class AgentLoop {
|
|
|
1087
1120
|
private config: AgentLoopConfig;
|
|
1088
1121
|
private tools: ToolDefinition[];
|
|
1089
1122
|
private resolveTools: ((history: Message[]) => ToolDefinition[]) | null;
|
|
1123
|
+
private onToolsSent: ((tools: ToolDefinition[]) => void) | null;
|
|
1090
1124
|
private toolExecutor: LoopToolExecutor | null;
|
|
1091
1125
|
|
|
1092
1126
|
/**
|
|
@@ -1122,6 +1156,7 @@ export class AgentLoop {
|
|
|
1122
1156
|
tools,
|
|
1123
1157
|
toolExecutor,
|
|
1124
1158
|
resolveTools,
|
|
1159
|
+
onToolsSent,
|
|
1125
1160
|
conversationId,
|
|
1126
1161
|
resolveConversationDir,
|
|
1127
1162
|
transformCompactedHistory,
|
|
@@ -1131,6 +1166,7 @@ export class AgentLoop {
|
|
|
1131
1166
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
1132
1167
|
this.tools = tools ?? [];
|
|
1133
1168
|
this.resolveTools = resolveTools ?? null;
|
|
1169
|
+
this.onToolsSent = onToolsSent ?? null;
|
|
1134
1170
|
this.toolExecutor = toolExecutor ?? null;
|
|
1135
1171
|
this.conversationId = conversationId;
|
|
1136
1172
|
this.resolveConversationDir = resolveConversationDir ?? null;
|
|
@@ -1413,18 +1449,21 @@ export class AgentLoop {
|
|
|
1413
1449
|
requestId,
|
|
1414
1450
|
onCheckpoint,
|
|
1415
1451
|
callSite,
|
|
1452
|
+
inferenceCallSite,
|
|
1416
1453
|
suppressAssistantText = false,
|
|
1417
1454
|
supportsDynamicUi = true,
|
|
1418
1455
|
trust,
|
|
1419
1456
|
overrideProfile,
|
|
1420
1457
|
forceOverrideProfile = false,
|
|
1421
1458
|
resolveOverrideProfile,
|
|
1459
|
+
onModelCallPrepared,
|
|
1422
1460
|
compactInPlace = false,
|
|
1423
1461
|
isNonInteractive = false,
|
|
1424
1462
|
model: runModel,
|
|
1425
1463
|
latencyTracker,
|
|
1426
1464
|
injectionLedgerResets,
|
|
1427
1465
|
} = options;
|
|
1466
|
+
const providerCallSite = inferenceCallSite ?? callSite;
|
|
1428
1467
|
// Snapshot the system prompt once per run. The instance field is mutable
|
|
1429
1468
|
// (the conversation may update it between turns), but a single run must
|
|
1430
1469
|
// use one consistent prompt — an aborted run left detached after the
|
|
@@ -1544,7 +1583,7 @@ export class AgentLoop {
|
|
|
1544
1583
|
turn: number,
|
|
1545
1584
|
): Promise<{
|
|
1546
1585
|
resultBlocks: ContentBlock[];
|
|
1547
|
-
additionalContextBlocks:
|
|
1586
|
+
additionalContextBlocks: TextContent[];
|
|
1548
1587
|
}> => {
|
|
1549
1588
|
if (conversationDir) {
|
|
1550
1589
|
const toolCallByUseId = new Map(
|
|
@@ -1569,7 +1608,7 @@ export class AgentLoop {
|
|
|
1569
1608
|
180_000;
|
|
1570
1609
|
|
|
1571
1610
|
const resultBlocks: ContentBlock[] = [];
|
|
1572
|
-
const additionalContextBlocks:
|
|
1611
|
+
const additionalContextBlocks: TextContent[] = [];
|
|
1573
1612
|
for (const block of rawBlocks) {
|
|
1574
1613
|
if (block.type !== "tool_result") {
|
|
1575
1614
|
resultBlocks.push(block);
|
|
@@ -1870,7 +1909,7 @@ export class AgentLoop {
|
|
|
1870
1909
|
// unexecutable client tool. The advisor consult's `advisorProfile` can
|
|
1871
1910
|
// route `subagentSpawn` to a provider/model whose native-search support
|
|
1872
1911
|
// differs from the construction-time default, so the gate resolves the
|
|
1873
|
-
// routed target (
|
|
1912
|
+
// routed target (providerCallSite + overrideProfile) via
|
|
1874
1913
|
// `supportsNativeWebSearchFor` rather than the static
|
|
1875
1914
|
// `this.provider.supportsNativeWebSearch` snapshot; providers without
|
|
1876
1915
|
// the routing-aware probe fall back to the static flag. This is a SERVER
|
|
@@ -1882,7 +1921,7 @@ export class AgentLoop {
|
|
|
1882
1921
|
.supportsNativeWebSearchFor
|
|
1883
1922
|
? this.provider.supportsNativeWebSearchFor(
|
|
1884
1923
|
buildNativeWebSearchProbeOptions(
|
|
1885
|
-
|
|
1924
|
+
providerCallSite,
|
|
1886
1925
|
resolveEffectiveOverrideProfile(),
|
|
1887
1926
|
forceOverrideProfile,
|
|
1888
1927
|
this.conversationId,
|
|
@@ -1901,11 +1940,11 @@ export class AgentLoop {
|
|
|
1901
1940
|
// 1. Per-run explicit (`runModel`)
|
|
1902
1941
|
// 2. Call-site resolved values (filled by
|
|
1903
1942
|
// `RetryProvider.normalizeSendMessageOptions` from
|
|
1904
|
-
// `resolveCallSiteConfig(
|
|
1943
|
+
// `resolveCallSiteConfig(providerCallSite, llm)`)
|
|
1905
1944
|
// 3. Conversation defaults (`this.config.*`, from the resolved
|
|
1906
1945
|
// default call-site config)
|
|
1907
1946
|
//
|
|
1908
|
-
// When `
|
|
1947
|
+
// When `providerCallSite` is present we deliberately leave
|
|
1909
1948
|
// `max_tokens`/`thinking`/`effort`/`speed` *unset* in `providerConfig`
|
|
1910
1949
|
// so the normalizer can fill them from the call-site resolution. The
|
|
1911
1950
|
// normalizer only writes these fields when they're undefined; if we
|
|
@@ -1913,10 +1952,10 @@ export class AgentLoop {
|
|
|
1913
1952
|
// for these knobs is silently ignored.
|
|
1914
1953
|
//
|
|
1915
1954
|
// `toolChoice` and `cacheTtl` are not part of the call-site schema, so
|
|
1916
|
-
// they always come from `this.config` regardless of `
|
|
1955
|
+
// they always come from `this.config` regardless of `providerCallSite`.
|
|
1917
1956
|
const providerConfig: Record<string, unknown> = {};
|
|
1918
1957
|
|
|
1919
|
-
if (!
|
|
1958
|
+
if (!providerCallSite) {
|
|
1920
1959
|
providerConfig.max_tokens = this.config.maxTokens;
|
|
1921
1960
|
}
|
|
1922
1961
|
|
|
@@ -1924,7 +1963,7 @@ export class AgentLoop {
|
|
|
1924
1963
|
providerConfig.model = runModel;
|
|
1925
1964
|
}
|
|
1926
1965
|
|
|
1927
|
-
if (!
|
|
1966
|
+
if (!providerCallSite) {
|
|
1928
1967
|
const thinking = normalizeThinkingConfigForWire(this.config.thinking);
|
|
1929
1968
|
if (thinking !== undefined) {
|
|
1930
1969
|
providerConfig.thinking = thinking;
|
|
@@ -1963,9 +2002,9 @@ export class AgentLoop {
|
|
|
1963
2002
|
// defaults when absent).
|
|
1964
2003
|
// User-initiated conversation turns default to `mainAgent` in the
|
|
1965
2004
|
// agent loop's caller; other invocation contexts (heartbeat, filing,
|
|
1966
|
-
// analyze, etc.) pass their own
|
|
1967
|
-
if (
|
|
1968
|
-
providerConfig.callSite =
|
|
2005
|
+
// analyze, etc.) pass their own provider-resolution site.
|
|
2006
|
+
if (providerCallSite) {
|
|
2007
|
+
providerConfig.callSite = providerCallSite;
|
|
1969
2008
|
providerConfig.usageTracking = "manual";
|
|
1970
2009
|
// Per-conversation seed for deterministic `mix`-profile expansion.
|
|
1971
2010
|
// Sourced from the loop's own conversation id so every LLM call in a
|
|
@@ -1993,7 +2032,7 @@ export class AgentLoop {
|
|
|
1993
2032
|
// `activeProfile` and any call-site named profile. Threading it on
|
|
1994
2033
|
// every send (rather than once at construction) keeps subagents that
|
|
1995
2034
|
// share an `AgentLoop` instance but ought to inherit a different
|
|
1996
|
-
// profile correct
|
|
2035
|
+
// profile correct, matching how the provider call site is plumbed.
|
|
1997
2036
|
const effectiveOverrideProfile = resolveEffectiveOverrideProfile();
|
|
1998
2037
|
if (effectiveOverrideProfile) {
|
|
1999
2038
|
providerConfig.overrideProfile = effectiveOverrideProfile;
|
|
@@ -2217,6 +2256,49 @@ export class AgentLoop {
|
|
|
2217
2256
|
);
|
|
2218
2257
|
}
|
|
2219
2258
|
|
|
2259
|
+
if (onModelCallPrepared && !signal?.aborted) {
|
|
2260
|
+
const preparedOverrideProfile =
|
|
2261
|
+
typeof providerConfig.overrideProfile === "string" &&
|
|
2262
|
+
providerConfig.overrideProfile.length > 0
|
|
2263
|
+
? providerConfig.overrideProfile
|
|
2264
|
+
: undefined;
|
|
2265
|
+
try {
|
|
2266
|
+
const preparedForceOverrideProfile =
|
|
2267
|
+
providerConfig.forceOverrideProfile === true;
|
|
2268
|
+
const disableCache =
|
|
2269
|
+
providerCallSite !== undefined &&
|
|
2270
|
+
resolveCallSiteConfig(providerCallSite, getConfig().llm, {
|
|
2271
|
+
...(preparedOverrideProfile !== undefined
|
|
2272
|
+
? { overrideProfile: preparedOverrideProfile }
|
|
2273
|
+
: {}),
|
|
2274
|
+
...(preparedForceOverrideProfile
|
|
2275
|
+
? { forceOverrideProfile: true }
|
|
2276
|
+
: {}),
|
|
2277
|
+
...(this.conversationId !== undefined
|
|
2278
|
+
? { selectionSeed: this.conversationId }
|
|
2279
|
+
: {}),
|
|
2280
|
+
}).disableCache === true;
|
|
2281
|
+
onModelCallPrepared({
|
|
2282
|
+
...(providerCallSite !== undefined
|
|
2283
|
+
? { callSite: providerCallSite }
|
|
2284
|
+
: {}),
|
|
2285
|
+
...(preparedOverrideProfile !== undefined
|
|
2286
|
+
? { overrideProfile: preparedOverrideProfile }
|
|
2287
|
+
: {}),
|
|
2288
|
+
forceOverrideProfile: preparedForceOverrideProfile,
|
|
2289
|
+
...(disableCache ? { disableCache: true as const } : {}),
|
|
2290
|
+
...(signal !== undefined ? { signal } : {}),
|
|
2291
|
+
systemPrompt: providerOptions.systemPrompt ?? null,
|
|
2292
|
+
tools: currentTools,
|
|
2293
|
+
});
|
|
2294
|
+
} catch (preparedError) {
|
|
2295
|
+
rlog.warn(
|
|
2296
|
+
{ err: preparedError },
|
|
2297
|
+
"Prepared model-call observer failed; continuing with provider dispatch",
|
|
2298
|
+
);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2220
2302
|
// Announce the LLM-call boundary so downstream handlers (the
|
|
2221
2303
|
// daemon's persistence pipeline) can reserve an empty assistant row
|
|
2222
2304
|
// and stamp the resulting `messageId` onto every streaming event the
|
|
@@ -2234,13 +2316,18 @@ export class AgentLoop {
|
|
|
2234
2316
|
// turn body (tool execution, plugin pipelines, checkpoints), so
|
|
2235
2317
|
// recording there would risk mis-attributing tool/plugin throws as
|
|
2236
2318
|
// provider rejections. On provider failure we emit `provider_error`
|
|
2237
|
-
// with the
|
|
2238
|
-
// `llm_request_logs` row, then
|
|
2239
|
-
//
|
|
2240
|
-
// break unchanged.
|
|
2319
|
+
// with the inspectable wire request from the throw (when present)
|
|
2320
|
+
// so consumers can persist it as an `llm_request_logs` row, then
|
|
2321
|
+
// re-throw so the existing outer catch continues to handle abort
|
|
2322
|
+
// sync, the `error` event, and the loop break unchanged.
|
|
2241
2323
|
// Latency: the request is about to leave for the provider. The span
|
|
2242
2324
|
// from here to the first streamed token is time-to-first-token.
|
|
2243
2325
|
latencyTracker?.mark("request_sent");
|
|
2326
|
+
// Every await that could cancel the call is behind us; a run aborted
|
|
2327
|
+
// during the throttle or a hook never reports an array it did not send.
|
|
2328
|
+
if (!signal?.aborted) {
|
|
2329
|
+
this.onToolsSent?.(currentTools);
|
|
2330
|
+
}
|
|
2244
2331
|
let response: ProviderResponse;
|
|
2245
2332
|
try {
|
|
2246
2333
|
response = await traceAsyncSection("agent-loop:provider-send", () =>
|
|
@@ -2255,26 +2342,18 @@ export class AgentLoop {
|
|
|
2255
2342
|
llmCallError instanceof Error
|
|
2256
2343
|
? llmCallError
|
|
2257
2344
|
: new Error(String(llmCallError));
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
// misrepresent both.
|
|
2263
|
-
const rawRequest = {
|
|
2264
|
-
provider: this.provider.name,
|
|
2265
|
-
messages: sanitizedHistory,
|
|
2266
|
-
tools: providerOptions.tools,
|
|
2267
|
-
systemPrompt: providerOptions.systemPrompt,
|
|
2268
|
-
config: providerOptions.config,
|
|
2269
|
-
};
|
|
2345
|
+
const invocationProvider =
|
|
2346
|
+
errInstance instanceof ProviderError
|
|
2347
|
+
? errInstance.provider
|
|
2348
|
+
: this.provider.name;
|
|
2270
2349
|
onEvent({
|
|
2271
2350
|
type: "provider_error",
|
|
2272
|
-
|
|
2351
|
+
...(errInstance instanceof ProviderError &&
|
|
2352
|
+
errInstance.rawRequest !== undefined
|
|
2353
|
+
? { rawRequest: errInstance.rawRequest }
|
|
2354
|
+
: {}),
|
|
2273
2355
|
error: errInstance,
|
|
2274
|
-
actualProvider:
|
|
2275
|
-
errInstance instanceof ProviderError
|
|
2276
|
-
? errInstance.provider
|
|
2277
|
-
: this.provider.name,
|
|
2356
|
+
actualProvider: invocationProvider,
|
|
2278
2357
|
});
|
|
2279
2358
|
}
|
|
2280
2359
|
providerCallError = llmCallError;
|
|
@@ -2945,16 +3024,20 @@ export class AgentLoop {
|
|
|
2945
3024
|
|
|
2946
3025
|
toolUseTurns++;
|
|
2947
3026
|
|
|
2948
|
-
//
|
|
2949
|
-
// `additionalContext` (e.g. tool-error retry coaching)
|
|
2950
|
-
//
|
|
2951
|
-
//
|
|
2952
|
-
//
|
|
2953
|
-
// tool's actual result.
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
3027
|
+
// Add the tool results, plus any guidance a post-tool-use hook
|
|
3028
|
+
// surfaced via `additionalContext` (e.g. tool-error retry coaching),
|
|
3029
|
+
// as a user message and continue the loop. The guidance joins the
|
|
3030
|
+
// provider-bound history only: it was not part of the tool_result
|
|
3031
|
+
// events emitted above, so the client-facing and persisted tool
|
|
3032
|
+
// output stay the tool's actual result.
|
|
3033
|
+
history.push({
|
|
3034
|
+
role: "user",
|
|
3035
|
+
content: buildToolResultFollowUp(
|
|
3036
|
+
history,
|
|
3037
|
+
resultBlocks,
|
|
3038
|
+
additionalContextBlocks,
|
|
3039
|
+
),
|
|
3040
|
+
});
|
|
2958
3041
|
|
|
2959
3042
|
// Invoke checkpoint callback after tool results are in history.
|
|
2960
3043
|
// Handoff takes precedence over the budget gate: a handoff decision
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Content of the user message that answers a tool-calling assistant turn:
|
|
2
|
+
// the tool_result blocks plus any guidance a post-tool-use hook surfaced via
|
|
3
|
+
// `additionalContext`.
|
|
4
|
+
|
|
5
|
+
import { analyzeServerToolPairing } from "../providers/server-tool-pairing.js";
|
|
6
|
+
import type {
|
|
7
|
+
ContentBlock,
|
|
8
|
+
Message,
|
|
9
|
+
TextContent,
|
|
10
|
+
ToolResultContent,
|
|
11
|
+
} from "../providers/types.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Hook guidance rides as separate blocks after the results, so the model sees
|
|
15
|
+
* it while each tool_result stays the tool's actual output. The exception is
|
|
16
|
+
* an assistant turn that left a server tool (native web search) deferred: the
|
|
17
|
+
* provider runs a deferred server tool only when the answering message holds
|
|
18
|
+
* tool_result blocks alone, and any block after the results closes the
|
|
19
|
+
* assistant turn, after which the provider rejects the unanswered server tool
|
|
20
|
+
* as unpaired. The guidance is then folded into the content of the last
|
|
21
|
+
* errored tool_result (the last tool_result when none errored), where the
|
|
22
|
+
* model still sees it and the search still runs.
|
|
23
|
+
*/
|
|
24
|
+
export function buildToolResultFollowUp(
|
|
25
|
+
history: ReadonlyArray<Message>,
|
|
26
|
+
resultBlocks: ContentBlock[],
|
|
27
|
+
additionalContextBlocks: ReadonlyArray<TextContent>,
|
|
28
|
+
): ContentBlock[] {
|
|
29
|
+
if (additionalContextBlocks.length === 0) {
|
|
30
|
+
return resultBlocks;
|
|
31
|
+
}
|
|
32
|
+
const targetIndex = foldTargetIndex(resultBlocks);
|
|
33
|
+
const pairing = analyzeServerToolPairing([
|
|
34
|
+
...history,
|
|
35
|
+
{ role: "user", content: resultBlocks },
|
|
36
|
+
]);
|
|
37
|
+
if (pairing.deferredUseIds.size === 0 || targetIndex < 0) {
|
|
38
|
+
return [...resultBlocks, ...additionalContextBlocks];
|
|
39
|
+
}
|
|
40
|
+
const target = resultBlocks[targetIndex] as ToolResultContent;
|
|
41
|
+
const folded: ToolResultContent = {
|
|
42
|
+
...target,
|
|
43
|
+
content: [target.content, ...additionalContextBlocks.map((b) => b.text)]
|
|
44
|
+
.filter((text) => text.length > 0)
|
|
45
|
+
.join("\n\n"),
|
|
46
|
+
};
|
|
47
|
+
return resultBlocks.map((block, index) =>
|
|
48
|
+
index === targetIndex ? folded : block,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Index of the last errored tool_result, else the last tool_result, else -1. */
|
|
53
|
+
function foldTargetIndex(blocks: ReadonlyArray<ContentBlock>): number {
|
|
54
|
+
let lastResult = -1;
|
|
55
|
+
for (let index = blocks.length - 1; index >= 0; index--) {
|
|
56
|
+
const block = blocks[index];
|
|
57
|
+
// guard:allow-tool-result-only: the answering user message carries client
|
|
58
|
+
// tool_result blocks only; server-side results live in assistant messages.
|
|
59
|
+
if (block.type !== "tool_result") {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (block.is_error) {
|
|
63
|
+
return index;
|
|
64
|
+
}
|
|
65
|
+
if (lastResult < 0) {
|
|
66
|
+
lastResult = index;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return lastResult;
|
|
70
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { AssistantOutboundAttachmentSchema } from "./events/assistant-outbound-attachment.js";
|
|
4
|
+
import { ConversationMessageAttachmentSchema } from "./responses/conversation-message.js";
|
|
5
|
+
|
|
6
|
+
const outboundFixture = {
|
|
7
|
+
id: "attachment-1",
|
|
8
|
+
filename: "screenshot.png",
|
|
9
|
+
mimeType: "image/png",
|
|
10
|
+
data: "c2NyZWVuc2hvdA==",
|
|
11
|
+
sourceType: "tool_block" as const,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const historyFixture = {
|
|
15
|
+
id: "attachment-1",
|
|
16
|
+
filename: "screenshot.png",
|
|
17
|
+
mimeType: "image/png",
|
|
18
|
+
sizeBytes: 10,
|
|
19
|
+
kind: "image",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
describe("computer-use screenshot attachment provenance", () => {
|
|
23
|
+
test("new schemas accept the marker and its absence", () => {
|
|
24
|
+
expect(
|
|
25
|
+
AssistantOutboundAttachmentSchema.parse({
|
|
26
|
+
...outboundFixture,
|
|
27
|
+
computerUseScreenshot: true,
|
|
28
|
+
}).computerUseScreenshot,
|
|
29
|
+
).toBe(true);
|
|
30
|
+
expect(
|
|
31
|
+
AssistantOutboundAttachmentSchema.parse(outboundFixture)
|
|
32
|
+
.computerUseScreenshot,
|
|
33
|
+
).toBeUndefined();
|
|
34
|
+
|
|
35
|
+
expect(
|
|
36
|
+
ConversationMessageAttachmentSchema.parse({
|
|
37
|
+
...historyFixture,
|
|
38
|
+
computerUseScreenshot: true,
|
|
39
|
+
}).computerUseScreenshot,
|
|
40
|
+
).toBe(true);
|
|
41
|
+
expect(
|
|
42
|
+
ConversationMessageAttachmentSchema.parse(historyFixture)
|
|
43
|
+
.computerUseScreenshot,
|
|
44
|
+
).toBeUndefined();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("legacy object parsers tolerate and strip the additive marker", () => {
|
|
48
|
+
const legacyOutbound = AssistantOutboundAttachmentSchema.omit({
|
|
49
|
+
computerUseScreenshot: true,
|
|
50
|
+
});
|
|
51
|
+
const legacyHistory = ConversationMessageAttachmentSchema.omit({
|
|
52
|
+
computerUseScreenshot: true,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
expect(
|
|
56
|
+
legacyOutbound.parse({
|
|
57
|
+
...outboundFixture,
|
|
58
|
+
computerUseScreenshot: true,
|
|
59
|
+
}),
|
|
60
|
+
).toEqual(outboundFixture);
|
|
61
|
+
expect(
|
|
62
|
+
legacyHistory.parse({
|
|
63
|
+
...historyFixture,
|
|
64
|
+
computerUseScreenshot: true,
|
|
65
|
+
}),
|
|
66
|
+
).toEqual(historyFixture);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
isComputerUseToolCall,
|
|
5
|
+
resolveComputerUseToolName,
|
|
6
|
+
} from "./computer-use-tool.js";
|
|
7
|
+
|
|
8
|
+
describe("isComputerUseToolCall", () => {
|
|
9
|
+
test("recognizes direct and skill-wrapped computer-use calls", () => {
|
|
10
|
+
expect(isComputerUseToolCall("computer_use_click", {})).toBe(true);
|
|
11
|
+
expect(
|
|
12
|
+
isComputerUseToolCall("skill_execute", { tool: "computer_use_type" }),
|
|
13
|
+
).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("resolves the direct or wrapped computer-use tool name", () => {
|
|
17
|
+
expect(resolveComputerUseToolName("computer_use_click", {})).toBe(
|
|
18
|
+
"computer_use_click",
|
|
19
|
+
);
|
|
20
|
+
expect(
|
|
21
|
+
resolveComputerUseToolName("skill_execute", {
|
|
22
|
+
tool: "computer_use_scroll",
|
|
23
|
+
}),
|
|
24
|
+
).toBe("computer_use_scroll");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("rejects unrelated media tools and malformed skill input", () => {
|
|
28
|
+
expect(isComputerUseToolCall("browser_screenshot", {})).toBe(false);
|
|
29
|
+
expect(isComputerUseToolCall("file_read", {})).toBe(false);
|
|
30
|
+
expect(isComputerUseToolCall("image_generate", {})).toBe(false);
|
|
31
|
+
expect(isComputerUseToolCall("skill_execute", null)).toBe(false);
|
|
32
|
+
expect(isComputerUseToolCall("skill_execute", "computer_use_click")).toBe(
|
|
33
|
+
false,
|
|
34
|
+
);
|
|
35
|
+
expect(isComputerUseToolCall("skill_execute", { tool: 42 })).toBe(false);
|
|
36
|
+
expect(
|
|
37
|
+
isComputerUseToolCall("skill_execute", {
|
|
38
|
+
tool: "browser_screenshot",
|
|
39
|
+
}),
|
|
40
|
+
).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("does not classify raw-only recovered skill input", () => {
|
|
44
|
+
expect(
|
|
45
|
+
isComputerUseToolCall("skill_execute", {
|
|
46
|
+
_raw: '{"tool":"computer_use_click"}',
|
|
47
|
+
}),
|
|
48
|
+
).toBe(false);
|
|
49
|
+
expect(
|
|
50
|
+
resolveComputerUseToolName("skill_execute", {
|
|
51
|
+
_raw: '{"tool":"computer_use_click"}',
|
|
52
|
+
}),
|
|
53
|
+
).toBeUndefined();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the host computer-use tool behind a direct or skill-wrapped call.
|
|
3
|
+
*
|
|
4
|
+
* Skills expose their selected tool in structured input. Calls recovered only
|
|
5
|
+
* from `_raw` retain their legacy behavior because this helper deliberately
|
|
6
|
+
* does not parse a second input representation.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveComputerUseToolName(
|
|
9
|
+
name: string,
|
|
10
|
+
input: unknown,
|
|
11
|
+
): string | undefined {
|
|
12
|
+
if (name.startsWith("computer_use_")) {
|
|
13
|
+
return name;
|
|
14
|
+
}
|
|
15
|
+
if (name !== "skill_execute" || input === null || typeof input !== "object") {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const tool = (input as Record<string, unknown>).tool;
|
|
19
|
+
return typeof tool === "string" && tool.startsWith("computer_use_")
|
|
20
|
+
? tool
|
|
21
|
+
: undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** True when a tool call is backed by the host computer-use capability. */
|
|
25
|
+
export function isComputerUseToolCall(name: string, input: unknown): boolean {
|
|
26
|
+
return resolveComputerUseToolName(name, input) !== undefined;
|
|
27
|
+
}
|
|
@@ -28,6 +28,9 @@ export const AssistantOutboundAttachmentSchema = z.object({
|
|
|
28
28
|
* true and the client should hydrate via the /content endpoint. */
|
|
29
29
|
data: z.string(),
|
|
30
30
|
sourceType: z.enum(["sandbox_file", "host_file", "tool_block"]).optional(),
|
|
31
|
+
/** True when this existing computer-use screenshot was linked to the reply
|
|
32
|
+
* automatically. Missing or false identifies legacy or explicit placement. */
|
|
33
|
+
computerUseScreenshot: z.boolean().optional(),
|
|
31
34
|
/** Original file size in bytes. Present when `data` was omitted to
|
|
32
35
|
* keep payloads small. */
|
|
33
36
|
sizeBytes: z.number().optional(),
|
|
@@ -20,10 +20,13 @@
|
|
|
20
20
|
|
|
21
21
|
import { z } from "zod";
|
|
22
22
|
|
|
23
|
+
import { ModeSessionSchema } from "../mode-session.js";
|
|
24
|
+
|
|
23
25
|
export const AssistantTurnStartEventSchema = z.object({
|
|
24
26
|
type: z.literal("assistant_turn_start"),
|
|
25
27
|
messageId: z.string(),
|
|
26
28
|
conversationId: z.string().optional(),
|
|
29
|
+
modeSession: ModeSessionSchema.optional(),
|
|
27
30
|
});
|
|
28
31
|
|
|
29
32
|
export type AssistantTurnStartEvent = z.infer<
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/** Transient browser activity changed; refetch desktop status. */
|
|
4
|
+
export const DesktopActivityChangedEventSchema = z.object({
|
|
5
|
+
type: z.literal("desktop_activity_changed"),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export type DesktopActivityChangedEvent = z.infer<
|
|
9
|
+
typeof DesktopActivityChangedEventSchema
|
|
10
|
+
>;
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
|
|
21
|
+
import { ModeSessionSchema } from "../mode-session.js";
|
|
21
22
|
import { AssistantOutboundAttachmentSchema } from "./assistant-outbound-attachment.js";
|
|
22
23
|
|
|
23
24
|
export const GenerationHandoffEventSchema = z.object({
|
|
@@ -30,6 +31,7 @@ export const GenerationHandoffEventSchema = z.object({
|
|
|
30
31
|
queuedCount: z.number(),
|
|
31
32
|
/** Database row id of the just-finished assistant turn. */
|
|
32
33
|
messageId: z.string().optional(),
|
|
34
|
+
modeSession: ModeSessionSchema.optional(),
|
|
33
35
|
attachments: z.array(AssistantOutboundAttachmentSchema).optional(),
|
|
34
36
|
attachmentWarnings: z.array(z.string()).optional(),
|
|
35
37
|
});
|