@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
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schedule-worker MCP bootstrap and reload.
|
|
3
|
+
*
|
|
4
|
+
* The worker hosts execute/wake/workflow turns in its own process, so it
|
|
5
|
+
* has to connect MCP servers itself. Tool-backed schedules must not fire
|
|
6
|
+
* until that pass has settled: a 20s grace lets notify/script start, and
|
|
7
|
+
* the readiness latch defers the rest until registration finishes or
|
|
8
|
+
* fails closed.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
restartConfiguredMcpServers,
|
|
13
|
+
startConfiguredMcpServers,
|
|
14
|
+
} from "../mcp/startup.js";
|
|
15
|
+
import {
|
|
16
|
+
EMPTY_MCP_STARTUP_SNAPSHOT,
|
|
17
|
+
type McpStartupSnapshot,
|
|
18
|
+
} from "../mcp/tool-caps.js";
|
|
19
|
+
import { getLogger } from "../util/logger.js";
|
|
20
|
+
import {
|
|
21
|
+
markScheduleToolSurfaceReady,
|
|
22
|
+
markScheduleToolSurfaceReloading,
|
|
23
|
+
markScheduleToolSurfaceStarting,
|
|
24
|
+
} from "./tool-surface-readiness.js";
|
|
25
|
+
|
|
26
|
+
export { MCP_NOT_READY_DEFER_MS } from "./tool-surface-readiness.js";
|
|
27
|
+
|
|
28
|
+
const log = getLogger("schedule-worker-mcp");
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* How long startup waits before arming notify/script ticks.
|
|
32
|
+
*
|
|
33
|
+
* Connecting is worth waiting for. It is not worth waiting for without
|
|
34
|
+
* limit: each server may take 30s to connect and 30s to list tools. Past
|
|
35
|
+
* this deadline those ticks start. Tool-backed schedules stay deferred
|
|
36
|
+
* until {@link markScheduleToolSurfaceReady}.
|
|
37
|
+
*/
|
|
38
|
+
export const MCP_STARTUP_GRACE_MS = 20_000;
|
|
39
|
+
|
|
40
|
+
export async function bootstrapScheduleWorkerMcp(options?: {
|
|
41
|
+
start?: () => Promise<McpStartupSnapshot>;
|
|
42
|
+
graceMs?: number;
|
|
43
|
+
}): Promise<void> {
|
|
44
|
+
const start = options?.start ?? startConfiguredMcpServers;
|
|
45
|
+
const graceMs = options?.graceMs ?? MCP_STARTUP_GRACE_MS;
|
|
46
|
+
markScheduleToolSurfaceStarting();
|
|
47
|
+
const startup = start()
|
|
48
|
+
.then((snapshot) => {
|
|
49
|
+
markScheduleToolSurfaceReady(snapshot);
|
|
50
|
+
log.info(snapshot, "MCP tool surface ready in schedule worker");
|
|
51
|
+
return snapshot;
|
|
52
|
+
})
|
|
53
|
+
.catch((err: unknown) => {
|
|
54
|
+
markScheduleToolSurfaceReady(EMPTY_MCP_STARTUP_SNAPSHOT);
|
|
55
|
+
log.error(
|
|
56
|
+
{ err },
|
|
57
|
+
"MCP tool surface failed in schedule worker; continuing without MCP tools",
|
|
58
|
+
);
|
|
59
|
+
return EMPTY_MCP_STARTUP_SNAPSHOT;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
await Promise.race([
|
|
63
|
+
startup,
|
|
64
|
+
new Promise<void>((resolve) => {
|
|
65
|
+
setTimeout(resolve, graceMs).unref();
|
|
66
|
+
}),
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function reloadScheduleWorkerMcp(options?: {
|
|
71
|
+
restart?: () => Promise<McpStartupSnapshot>;
|
|
72
|
+
}): Promise<McpStartupSnapshot> {
|
|
73
|
+
const restart = options?.restart ?? restartConfiguredMcpServers;
|
|
74
|
+
markScheduleToolSurfaceReloading();
|
|
75
|
+
try {
|
|
76
|
+
const snapshot = await restart();
|
|
77
|
+
markScheduleToolSurfaceReady(snapshot);
|
|
78
|
+
log.info(snapshot, "MCP servers reloaded in schedule worker");
|
|
79
|
+
return snapshot;
|
|
80
|
+
} catch (err) {
|
|
81
|
+
markScheduleToolSurfaceReady(EMPTY_MCP_STARTUP_SNAPSHOT);
|
|
82
|
+
log.warn({ err }, "MCP reload failed in schedule worker");
|
|
83
|
+
throw err;
|
|
84
|
+
}
|
|
85
|
+
}
|
package/src/schedule/worker.ts
CHANGED
|
@@ -22,10 +22,6 @@ import { rehydratePlatformCredentials } from "../config/platform-rehydration.js"
|
|
|
22
22
|
import { startConversationEvictor } from "../daemon/conversation-evictor.js";
|
|
23
23
|
import { stopMcpServerManager } from "../mcp/manager.js";
|
|
24
24
|
import { MCP_RELOAD_SIGNAL_FILE } from "../mcp/reload-signal.js";
|
|
25
|
-
import {
|
|
26
|
-
restartConfiguredMcpServers,
|
|
27
|
-
startConfiguredMcpServers,
|
|
28
|
-
} from "../mcp/startup.js";
|
|
29
25
|
import { resetDb } from "../persistence/db-connection.js";
|
|
30
26
|
import { registerWorkerPluginSurface } from "../plugins/worker-plugin-surface.js";
|
|
31
27
|
import { disableStreamSeqStamping } from "../runtime/assistant-stream-state.js";
|
|
@@ -37,6 +33,10 @@ import {
|
|
|
37
33
|
startWorkerPidFileGuard,
|
|
38
34
|
} from "../util/worker-process.js";
|
|
39
35
|
import { runDueSchedulesOnce } from "./scheduler.js";
|
|
36
|
+
import {
|
|
37
|
+
bootstrapScheduleWorkerMcp,
|
|
38
|
+
reloadScheduleWorkerMcp,
|
|
39
|
+
} from "./worker-mcp.js";
|
|
40
40
|
|
|
41
41
|
const log = getLogger("schedule-worker-process");
|
|
42
42
|
|
|
@@ -46,19 +46,6 @@ const TICK_INTERVAL_MS = 15_000;
|
|
|
46
46
|
/** How often this process re-reads flag overrides from the gateway. */
|
|
47
47
|
const FLAG_REFRESH_INTERVAL_MS = 60_000;
|
|
48
48
|
|
|
49
|
-
/**
|
|
50
|
-
* How long startup waits for MCP servers before arming the tick.
|
|
51
|
-
*
|
|
52
|
-
* Connecting is worth waiting for: a schedule that fires first would fail its
|
|
53
|
-
* `mcp__*` calls as unknown tools. It is not worth waiting for without limit.
|
|
54
|
-
* `McpServerManager.start()` walks servers one at a time and allows each 30s to
|
|
55
|
-
* connect and 30s more to list its tools, so a handful of unreachable ones can
|
|
56
|
-
* hold the first tick for minutes, including the notify and script schedules
|
|
57
|
-
* that never touch MCP. Past this deadline the connect continues in the
|
|
58
|
-
* background and the tick starts without it.
|
|
59
|
-
*/
|
|
60
|
-
const MCP_STARTUP_GRACE_MS = 20_000;
|
|
61
|
-
|
|
62
49
|
/**
|
|
63
50
|
* Rebuild this process's MCP connections whenever the daemon reports a reload.
|
|
64
51
|
*
|
|
@@ -85,10 +72,7 @@ function watchForMcpReload(): void {
|
|
|
85
72
|
restartQueued = true;
|
|
86
73
|
return;
|
|
87
74
|
}
|
|
88
|
-
restarting =
|
|
89
|
-
.then((toolCount) => {
|
|
90
|
-
log.info({ toolCount }, "MCP servers reloaded in schedule worker");
|
|
91
|
-
})
|
|
75
|
+
restarting = reloadScheduleWorkerMcp()
|
|
92
76
|
.catch((err: unknown) => {
|
|
93
77
|
log.warn({ err }, "MCP reload failed in schedule worker");
|
|
94
78
|
})
|
|
@@ -193,16 +177,10 @@ async function main(): Promise<void> {
|
|
|
193
177
|
// keeps this process independent of the daemon's event loop, which is the
|
|
194
178
|
// reason it is a separate process at all.
|
|
195
179
|
//
|
|
196
|
-
// Bounded by MCP_STARTUP_GRACE_MS
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
await
|
|
200
|
-
mcpStartup,
|
|
201
|
-
// Unref'd so a connect that beats the deadline leaves nothing pending.
|
|
202
|
-
new Promise((resolve) => {
|
|
203
|
-
setTimeout(resolve, MCP_STARTUP_GRACE_MS).unref();
|
|
204
|
-
}),
|
|
205
|
-
]);
|
|
180
|
+
// Bounded by MCP_STARTUP_GRACE_MS so notify/script can fire. Execute, wake,
|
|
181
|
+
// and workflow schedules stay deferred until the connect settles and the
|
|
182
|
+
// tool surface is marked ready.
|
|
183
|
+
await bootstrapScheduleWorkerMcp();
|
|
206
184
|
|
|
207
185
|
// React to an MCP reload in the daemon. The server set belongs to the config
|
|
208
186
|
// and the daemon owns the watcher that notices it change; this process holds
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Unified secure key storage
|
|
2
|
+
* Unified secure key storage: single-backend routing through CredentialBackend
|
|
3
3
|
* adapters.
|
|
4
4
|
*
|
|
5
5
|
* Backend selection (`resolveBackendAsync`) is the single async decision point:
|
|
6
|
-
* 1. CES RPC (primary)
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* cached. On failure, falls through to the encrypted file store.
|
|
17
|
-
* 4. Encrypted file store (fallback) — used when CES is unavailable.
|
|
6
|
+
* 1. CES RPC (primary) - connect to the CES bootstrap socket and talk RPC.
|
|
7
|
+
* `openCesRpcSession` is the one client constructor. The assistant
|
|
8
|
+
* claims session ownership at boot (`startCes`) and hands CES the
|
|
9
|
+
* assistant API key. Child processes open a session on first credential
|
|
10
|
+
* read only when this process has no client and no reconnect owner.
|
|
11
|
+
* 2. CES HTTP - containerized failover when IPC is unavailable
|
|
12
|
+
* (`IS_CONTAINERIZED` + `CES_CREDENTIAL_URL`). Used if the assistant's
|
|
13
|
+
* bootstrap RPC transport is down, or if a process with HTTP env could
|
|
14
|
+
* not open the socket.
|
|
15
|
+
* 3. Encrypted file store (fallback) - used when CES is unavailable locally.
|
|
18
16
|
*
|
|
19
17
|
* All operations (reads, writes, lists, deletes) go to exactly one backend.
|
|
20
18
|
* There are no cross-store fallbacks or merges. The only transport failover is
|
|
21
|
-
* CES RPC
|
|
19
|
+
* CES RPC to CES HTTP in managed mode; both backends target the same CES
|
|
22
20
|
* sidecar and credential data.
|
|
23
21
|
*/
|
|
24
22
|
|
|
@@ -33,13 +31,11 @@ import type {
|
|
|
33
31
|
|
|
34
32
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
35
33
|
import {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
} from "../credential-execution/
|
|
39
|
-
import {
|
|
40
|
-
|
|
41
|
-
createCesProcessManager,
|
|
42
|
-
} from "../credential-execution/process-manager.js";
|
|
34
|
+
openCesRpcSession,
|
|
35
|
+
reconnectCesRpcSession,
|
|
36
|
+
} from "../credential-execution/ces-connect.js";
|
|
37
|
+
import { type CesClient } from "../credential-execution/client.js";
|
|
38
|
+
import { discoverCes } from "../credential-execution/executable-discovery.js";
|
|
43
39
|
import { getAnyProviderEnvVar } from "../providers/provider-env-vars.js";
|
|
44
40
|
import { getLogger } from "../util/logger.js";
|
|
45
41
|
import { getProtectedDir } from "../util/platform.js";
|
|
@@ -82,13 +78,13 @@ let _resolvedBackend: CredentialBackend | undefined;
|
|
|
82
78
|
let _resolvePromise: Promise<CredentialBackend> | undefined;
|
|
83
79
|
|
|
84
80
|
/**
|
|
85
|
-
* In-flight
|
|
81
|
+
* In-flight CES RPC session promise for processes that did not call startCes().
|
|
86
82
|
*
|
|
87
|
-
* Workers and CLI subprocesses
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
83
|
+
* Workers and CLI subprocesses never call startCes(). When they hit
|
|
84
|
+
* resolveBackendAsync() with no _cesClient and no _cesReconnect
|
|
85
|
+
* (assistant-boot only), this promise memoizes `openCesRpcSession` so
|
|
86
|
+
* concurrent credential reads in the same process share a single
|
|
87
|
+
* connect+handshake rather than racing.
|
|
92
88
|
*/
|
|
93
89
|
let _lazyConnectPromise: Promise<CesClient | undefined> | undefined;
|
|
94
90
|
|
|
@@ -203,14 +199,14 @@ function getEncryptedStoreBackend(): CredentialBackend {
|
|
|
203
199
|
* Resolve the primary credential backend for this process (async).
|
|
204
200
|
*
|
|
205
201
|
* Priority:
|
|
206
|
-
* 1. CES RPC client
|
|
207
|
-
* 2. Containerized + CES_CREDENTIAL_URL
|
|
208
|
-
* 3. Encrypted file store
|
|
202
|
+
* 1. CES RPC: live client, or open one via `openCesRpcSession`.
|
|
203
|
+
* 2. Containerized + CES_CREDENTIAL_URL: CES HTTP, only if IPC is down.
|
|
204
|
+
* 3. Encrypted file store: local fallback when CES is unavailable.
|
|
209
205
|
*
|
|
210
206
|
* Once resolved, the backend is cached. If it becomes unavailable (e.g. the
|
|
211
207
|
* CES transport dies), we attempt to reconnect via `_cesReconnect` rather
|
|
212
208
|
* than falling back to a different backend. In managed cloud mode CES is the
|
|
213
|
-
* primary credential source
|
|
209
|
+
* primary credential source. Falling back to the encrypted file store would
|
|
214
210
|
* silently serve stale or empty data.
|
|
215
211
|
*
|
|
216
212
|
* In managed mode, if the CES bootstrap RPC transport dies, we first fail
|
|
@@ -411,17 +407,19 @@ export async function attemptCesReconnection(
|
|
|
411
407
|
}
|
|
412
408
|
|
|
413
409
|
/**
|
|
414
|
-
*
|
|
410
|
+
* Open a CES RPC session from a process that did not call startCes().
|
|
415
411
|
*
|
|
416
|
-
* Workers and CLI subprocesses
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
412
|
+
* Workers and CLI subprocesses never call startCes(). This function
|
|
413
|
+
* opens the same `openCesRpcSession` path the assistant uses at boot,
|
|
414
|
+
* memoizing the in-flight promise so concurrent callers share a single
|
|
415
|
+
* connect+handshake. Discovery uses the shared CES bootstrap socket; a
|
|
416
|
+
* missing socket fails immediately so callers can fall through without
|
|
417
|
+
* polling.
|
|
420
418
|
*
|
|
421
419
|
* On success, the client is injected via setCesClient() so subsequent
|
|
422
|
-
* resolveBackendAsync() calls take the
|
|
423
|
-
*
|
|
424
|
-
*
|
|
420
|
+
* resolveBackendAsync() calls take the live CES RPC path. A reconnect
|
|
421
|
+
* callback is also registered so the session can heal if the transport
|
|
422
|
+
* drops mid-process.
|
|
425
423
|
*
|
|
426
424
|
* Returns undefined on any failure (socket not found, handshake rejected,
|
|
427
425
|
* timeout) so the caller falls through to the encrypted file store.
|
|
@@ -432,62 +430,30 @@ async function tryLazyCesConnect(): Promise<CesClient | undefined> {
|
|
|
432
430
|
}
|
|
433
431
|
|
|
434
432
|
_lazyConnectPromise = (async () => {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
const transport = await pm.start();
|
|
438
|
-
const client = createCesClient(transport);
|
|
439
|
-
const { accepted, reason } = await client.handshake();
|
|
440
|
-
if (!accepted) {
|
|
441
|
-
log.warn(
|
|
442
|
-
{ reason },
|
|
443
|
-
"Lazy CES connection handshake rejected — falling back to encrypted file store",
|
|
444
|
-
);
|
|
445
|
-
client.close();
|
|
446
|
-
await pm.stop().catch(() => {});
|
|
447
|
-
return undefined;
|
|
448
|
-
}
|
|
433
|
+
const discovery = discoverCes();
|
|
434
|
+
if (discovery.mode === "unavailable") {
|
|
449
435
|
log.info(
|
|
450
|
-
|
|
436
|
+
{ reason: discovery.reason },
|
|
437
|
+
"CES socket not reachable for lazy connect, falling back to encrypted file store",
|
|
451
438
|
);
|
|
452
|
-
setCesClient(client);
|
|
453
|
-
// Register a reconnect callback so the lazy connection self-heals
|
|
454
|
-
// if the transport drops, mirroring the daemon's proactive reconnect.
|
|
455
|
-
setCesReconnect(async () => {
|
|
456
|
-
try {
|
|
457
|
-
await pm.stop();
|
|
458
|
-
const newTransport = await pm.start();
|
|
459
|
-
const newClient = createCesClient(newTransport);
|
|
460
|
-
const { accepted: ok } = await newClient.handshake();
|
|
461
|
-
if (ok) {
|
|
462
|
-
log.info("Lazy CES reconnection successful");
|
|
463
|
-
return newClient;
|
|
464
|
-
}
|
|
465
|
-
newClient.close();
|
|
466
|
-
await pm.stop().catch(() => {});
|
|
467
|
-
return undefined;
|
|
468
|
-
} catch (err) {
|
|
469
|
-
log.warn(
|
|
470
|
-
{ error: err instanceof Error ? err.message : String(err) },
|
|
471
|
-
"Lazy CES reconnection failed",
|
|
472
|
-
);
|
|
473
|
-
return undefined;
|
|
474
|
-
}
|
|
475
|
-
});
|
|
476
|
-
return client;
|
|
477
|
-
} catch (err) {
|
|
478
|
-
if (err instanceof CesUnavailableError) {
|
|
479
|
-
log.info(
|
|
480
|
-
{ reason: err.message },
|
|
481
|
-
"CES socket not reachable for lazy connect — falling back to encrypted file store",
|
|
482
|
-
);
|
|
483
|
-
} else {
|
|
484
|
-
log.warn(
|
|
485
|
-
{ error: err instanceof Error ? err.message : String(err) },
|
|
486
|
-
"Lazy CES connection failed — falling back to encrypted file store",
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
439
|
return undefined;
|
|
490
440
|
}
|
|
441
|
+
const session = await openCesRpcSession();
|
|
442
|
+
if (!session) {
|
|
443
|
+
return undefined;
|
|
444
|
+
}
|
|
445
|
+
log.info(
|
|
446
|
+
"CES RPC session established; credential operations route through CES RPC",
|
|
447
|
+
);
|
|
448
|
+
setCesClient(session.client);
|
|
449
|
+
setCesReconnect(async () => {
|
|
450
|
+
const client = await reconnectCesRpcSession(session.processManager);
|
|
451
|
+
if (client) {
|
|
452
|
+
log.info("CES RPC reconnection successful");
|
|
453
|
+
}
|
|
454
|
+
return client;
|
|
455
|
+
});
|
|
456
|
+
return session.client;
|
|
491
457
|
})();
|
|
492
458
|
|
|
493
459
|
try {
|
|
@@ -498,7 +464,10 @@ async function tryLazyCesConnect(): Promise<CesClient | undefined> {
|
|
|
498
464
|
}
|
|
499
465
|
|
|
500
466
|
async function doResolveBackend(): Promise<CredentialBackend> {
|
|
501
|
-
// 1. CES RPC
|
|
467
|
+
// 1. CES RPC. Primary credential backend in every environment. Boot
|
|
468
|
+
// claims reconnect ownership before it reads handshake identity, so
|
|
469
|
+
// that read cannot open a second session. Children open here only
|
|
470
|
+
// when this process has no client and no reconnect owner.
|
|
502
471
|
if (_cesClient) {
|
|
503
472
|
const cesRpc = new CesRpcCredentialBackend(_cesClient);
|
|
504
473
|
if (cesRpc.isAvailable()) {
|
|
@@ -511,7 +480,19 @@ async function doResolveBackend(): Promise<CredentialBackend> {
|
|
|
511
480
|
);
|
|
512
481
|
}
|
|
513
482
|
|
|
514
|
-
|
|
483
|
+
if (!_cesClient && !_cesReconnect) {
|
|
484
|
+
const client = await tryLazyCesConnect();
|
|
485
|
+
if (client) {
|
|
486
|
+
const cesRpc = new CesRpcCredentialBackend(client);
|
|
487
|
+
if (cesRpc.isAvailable()) {
|
|
488
|
+
_resolvedBackend = cesRpc;
|
|
489
|
+
log.info("Resolved credential backend: ces-rpc");
|
|
490
|
+
return cesRpc;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// 2. CES HTTP. Managed failover when IPC is unavailable.
|
|
515
496
|
if (getIsContainerized() && process.env.CES_CREDENTIAL_URL) {
|
|
516
497
|
const ces = createCesCredentialBackend();
|
|
517
498
|
if (ces.isAvailable()) {
|
|
@@ -525,25 +506,6 @@ async function doResolveBackend(): Promise<CredentialBackend> {
|
|
|
525
506
|
);
|
|
526
507
|
}
|
|
527
508
|
|
|
528
|
-
// 2.5. Lazy CES RPC connect — non-daemon processes (workers, CLI
|
|
529
|
-
// subprocesses) inherit CES_LOCAL_SOCKET but never call startCes().
|
|
530
|
-
// When the daemon's setCesReconnect() is NOT registered, attempt a
|
|
531
|
-
// direct connection to the CES sibling socket. On success, inject
|
|
532
|
-
// the client via setCesClient() and re-resolve through the CES RPC
|
|
533
|
-
// path. On failure, fall through to the encrypted file store.
|
|
534
|
-
if (!_cesClient && !_cesReconnect && process.env.CES_LOCAL_SOCKET) {
|
|
535
|
-
const lazyClient = await tryLazyCesConnect();
|
|
536
|
-
if (lazyClient) {
|
|
537
|
-
const cesRpc = new CesRpcCredentialBackend(lazyClient);
|
|
538
|
-
if (cesRpc.isAvailable()) {
|
|
539
|
-
_resolvedBackend = cesRpc;
|
|
540
|
-
log.info("Resolved credential backend: ces-rpc (lazy connect)");
|
|
541
|
-
return cesRpc;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
// Lazy connect failed; fall through.
|
|
545
|
-
}
|
|
546
|
-
|
|
547
509
|
// 3. On a containerized pod the local encrypted store does not exist and CES
|
|
548
510
|
// owns credentials. Never resolve to the encrypted store here; it would
|
|
549
511
|
// report a provisioned credential as absent. Return an unreachable backend
|
package/src/skills/clawhub.ts
CHANGED
|
@@ -11,11 +11,6 @@ import {
|
|
|
11
11
|
|
|
12
12
|
const log = getLogger("clawhub");
|
|
13
13
|
|
|
14
|
-
// Managed skills directory — where installed skill folders live
|
|
15
|
-
function getManagedSkillsDir(): string {
|
|
16
|
-
return getWorkspaceSkillsDir();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
14
|
// ClaWHub project root — clawhub creates a `skills/` subdir inside its cwd,
|
|
20
15
|
// so we use the parent of the managed skills dir as the project root.
|
|
21
16
|
function getClawhubProjectRoot(): string {
|
|
@@ -39,7 +34,7 @@ interface IntegrityRecord {
|
|
|
39
34
|
type IntegrityManifest = Record<string, IntegrityRecord>;
|
|
40
35
|
|
|
41
36
|
function getIntegrityPath(): string {
|
|
42
|
-
return join(
|
|
37
|
+
return join(getWorkspaceSkillsDir(), ".integrity.json");
|
|
43
38
|
}
|
|
44
39
|
|
|
45
40
|
function loadIntegrityManifest(): IntegrityManifest {
|
|
@@ -66,7 +61,7 @@ function loadIntegrityManifest(): IntegrityManifest {
|
|
|
66
61
|
* from skills that haven't been migrated yet.
|
|
67
62
|
*/
|
|
68
63
|
export function verifyAndRecordSkillHash(slug: string): void {
|
|
69
|
-
const skillDir = join(
|
|
64
|
+
const skillDir = join(getWorkspaceSkillsDir(), slug);
|
|
70
65
|
const hash = computeSkillHash(skillDir);
|
|
71
66
|
if (!hash) {
|
|
72
67
|
log.warn({ slug }, "Could not compute content hash for installed skill");
|
|
@@ -232,7 +227,7 @@ function getSkillNameFromSlug(slug: string): string {
|
|
|
232
227
|
}
|
|
233
228
|
|
|
234
229
|
function getClawhubSkillsDir(projectRoot?: string): string {
|
|
235
|
-
return projectRoot ? join(projectRoot, "skills") :
|
|
230
|
+
return projectRoot ? join(projectRoot, "skills") : getWorkspaceSkillsDir();
|
|
236
231
|
}
|
|
237
232
|
|
|
238
233
|
function hasRootSkillFile(skillDir: string): boolean {
|
|
@@ -44,13 +44,9 @@ export function validateManagedSkillId(id: string): string | null {
|
|
|
44
44
|
|
|
45
45
|
// ─── Path helpers ────────────────────────────────────────────────────────────
|
|
46
46
|
|
|
47
|
-
function getManagedSkillsDir(): string {
|
|
48
|
-
return getWorkspaceSkillsDir();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
47
|
/** Absolute path of a managed skill's directory (whether or not it exists). */
|
|
52
48
|
export function getManagedSkillDir(id: string): string {
|
|
53
|
-
return join(
|
|
49
|
+
return join(getWorkspaceSkillsDir(), id);
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
interface ResolvedCompanionPath {
|
package/src/stt/types.ts
CHANGED
|
@@ -436,6 +436,10 @@ export interface SttStreamServerTurnEndEvent {
|
|
|
436
436
|
* provider does not surface a score.
|
|
437
437
|
*/
|
|
438
438
|
readonly confidence?: number;
|
|
439
|
+
/** Provider-reported cause of the turn boundary, when available. */
|
|
440
|
+
readonly trigger?: "model" | "manual" | "timeout";
|
|
441
|
+
/** End of the decoded audio window, in seconds from stream start. */
|
|
442
|
+
readonly audioWindowEndSeconds?: number;
|
|
439
443
|
/**
|
|
440
444
|
* Provider's index for the turn being closed, matching the
|
|
441
445
|
* {@link SttStreamServerTurnStartEvent} that opened it. A consumer can
|
package/src/subagent/notify.ts
CHANGED
|
@@ -8,16 +8,20 @@
|
|
|
8
8
|
* manager out of the import graph lets tool modules import these helpers without
|
|
9
9
|
* pulling in the conversation/agent-loop core.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* stale idle parent is rebuilt through `getOrCreateConversation` first so
|
|
14
|
-
* injected turn uses the current provider, prompt, and credentials.
|
|
11
|
+
* An active live-voice session owns delivery for its conversation. Otherwise,
|
|
12
|
+
* delivery targets the parent's in-process `Conversation` via the registry.
|
|
13
|
+
* A stale idle parent is rebuilt through `getOrCreateConversation` first so
|
|
14
|
+
* the injected turn uses the current provider, prompt, and credentials.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { getConfig } from "../config/loader.js";
|
|
18
|
+
import { resolveTurnCommitWaitMs } from "../daemon/abort-watchdog.js";
|
|
17
19
|
import {
|
|
18
20
|
findConversation,
|
|
19
21
|
findConversationOrSubagent,
|
|
20
22
|
} from "../daemon/conversation-registry.js";
|
|
23
|
+
import { startAfterTurnFinalization } from "../daemon/turn-finalization.js";
|
|
24
|
+
import { deliverSubagentNotificationToLiveVoice } from "../live-voice/live-voice-manager.js";
|
|
21
25
|
import { getSubagentRecordByConversationId } from "../persistence/subagent-store.js";
|
|
22
26
|
import { getLogger } from "../util/logger.js";
|
|
23
27
|
import { type SubagentStatus, TERMINAL_STATUSES } from "./types.js";
|
|
@@ -25,9 +29,9 @@ import { type SubagentStatus, TERMINAL_STATUSES } from "./types.js";
|
|
|
25
29
|
const log = getLogger("subagent-notify");
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
32
|
+
* Deliver task updates through the parent's live voice session when present,
|
|
33
|
+
* otherwise enqueue a parent turn. No-op with a warning
|
|
34
|
+
* when neither the session nor the parent conversation is live here.
|
|
31
35
|
*
|
|
32
36
|
* Shared by the child-triggered {@link notifyParentFromChild} and the
|
|
33
37
|
* manager's terminal/abort injections so every subagent → parent turn lands
|
|
@@ -37,8 +41,30 @@ export function injectMessageIntoParent(
|
|
|
37
41
|
parentConversationId: string,
|
|
38
42
|
message: string,
|
|
39
43
|
metadata?: Record<string, unknown>,
|
|
40
|
-
opts?: { cronRunId?: string | null },
|
|
44
|
+
opts?: { cronRunId?: string | null; bypassLiveVoice?: boolean },
|
|
41
45
|
): void {
|
|
46
|
+
const notification = metadata?.subagentNotification;
|
|
47
|
+
// The live child's conversation ID is stable even if its cosmetic record changes.
|
|
48
|
+
if (
|
|
49
|
+
!opts?.bypassLiveVoice &&
|
|
50
|
+
notification !== null &&
|
|
51
|
+
typeof notification === "object" &&
|
|
52
|
+
"subagentId" in notification &&
|
|
53
|
+
typeof notification.subagentId === "string" &&
|
|
54
|
+
metadata !== undefined &&
|
|
55
|
+
deliverSubagentNotificationToLiveVoice(parentConversationId, {
|
|
56
|
+
taskId:
|
|
57
|
+
"conversationId" in notification &&
|
|
58
|
+
typeof notification.conversationId === "string"
|
|
59
|
+
? notification.conversationId
|
|
60
|
+
: notification.subagentId,
|
|
61
|
+
message,
|
|
62
|
+
metadata,
|
|
63
|
+
cronRunId: opts?.cronRunId,
|
|
64
|
+
})
|
|
65
|
+
) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
42
68
|
const existing = findConversation(parentConversationId);
|
|
43
69
|
if (!existing) {
|
|
44
70
|
log.warn(
|
|
@@ -76,17 +102,10 @@ function deliverToParent(
|
|
|
76
102
|
content: string;
|
|
77
103
|
metadata?: Record<string, unknown>;
|
|
78
104
|
isInteractive: boolean;
|
|
105
|
+
queueWhenIdle: boolean;
|
|
79
106
|
cronRunId?: string | null;
|
|
80
107
|
}) => { queued: boolean; rejected?: boolean };
|
|
81
|
-
|
|
82
|
-
content: string;
|
|
83
|
-
metadata?: Record<string, unknown>;
|
|
84
|
-
}) => Promise<{ id: string }>;
|
|
85
|
-
runAgentLoop: (
|
|
86
|
-
message: string,
|
|
87
|
-
messageId: string,
|
|
88
|
-
options: { isInteractive: boolean; cronRunId?: string | null },
|
|
89
|
-
) => Promise<unknown>;
|
|
108
|
+
kickDrainQueue: (reason: "loop_complete", origin: string) => Promise<void>;
|
|
90
109
|
},
|
|
91
110
|
parentConversationId: string,
|
|
92
111
|
message: string,
|
|
@@ -95,33 +114,34 @@ function deliverToParent(
|
|
|
95
114
|
): void {
|
|
96
115
|
// The continuation this notification starts is still the scheduled firing's
|
|
97
116
|
// work, so it carries the same run id as the child whose result triggered it.
|
|
98
|
-
//
|
|
99
|
-
// has ended, so the id has to travel on the message.
|
|
117
|
+
// The queue drains after the enqueuing turn, so the id travels on the message.
|
|
100
118
|
const cronRunId = opts?.cronRunId ?? null;
|
|
101
119
|
// Machine-injected with no human asserted present, so the notification
|
|
102
120
|
// turn runs non-interactive; it still streams to whoever is watching
|
|
103
121
|
// through the parent's sink.
|
|
104
122
|
const enqueueResult = parentConversation.enqueueMessage({
|
|
105
123
|
content: message,
|
|
106
|
-
metadata,
|
|
124
|
+
metadata: { ...metadata, scripted: true },
|
|
107
125
|
isInteractive: false,
|
|
126
|
+
queueWhenIdle: true,
|
|
108
127
|
...(cronRunId ? { cronRunId } : {}),
|
|
109
128
|
});
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
119
|
-
.catch((err) => {
|
|
120
|
-
log.error(
|
|
121
|
-
{ parentConversationId, err },
|
|
122
|
-
"Failed to process subagent notification in parent",
|
|
129
|
+
if (enqueueResult.queued) {
|
|
130
|
+
startAfterTurnFinalization(
|
|
131
|
+
parentConversationId,
|
|
132
|
+
resolveTurnCommitWaitMs(getConfig().workspaceGit?.turnCommitMaxWaitMs),
|
|
133
|
+
() => {
|
|
134
|
+
void parentConversation.kickDrainQueue(
|
|
135
|
+
"loop_complete",
|
|
136
|
+
"subagent_notification",
|
|
123
137
|
);
|
|
124
|
-
}
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
} else {
|
|
141
|
+
log.error(
|
|
142
|
+
{ parentConversationId },
|
|
143
|
+
"Parent queue rejected subagent notification",
|
|
144
|
+
);
|
|
125
145
|
}
|
|
126
146
|
}
|
|
127
147
|
|