@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
|
@@ -9,10 +9,16 @@ import {
|
|
|
9
9
|
setCesReconnect,
|
|
10
10
|
} from "../security/secure-keys.js";
|
|
11
11
|
import { getLogger } from "../util/logger.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
openCesRpcSession,
|
|
14
|
+
reconnectCesRpcSession,
|
|
15
|
+
} from "./ces-connect.js";
|
|
16
|
+
import {
|
|
17
|
+
type CesClient,
|
|
18
|
+
type CesClientHandshakeOptions,
|
|
19
|
+
} from "./client.js";
|
|
13
20
|
import {
|
|
14
21
|
type CesProcessManager,
|
|
15
|
-
CesUnavailableError,
|
|
16
22
|
createCesProcessManager,
|
|
17
23
|
} from "./process-manager.js";
|
|
18
24
|
import {
|
|
@@ -45,70 +51,69 @@ interface CesStartupResult {
|
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
/**
|
|
48
|
-
*
|
|
49
|
-
* handles to the in-flight initialization
|
|
50
|
-
* for startup to continue.
|
|
54
|
+
* Open the assistant's CES RPC client and perform the handshake. Returns
|
|
55
|
+
* immediately with handles to the in-flight initialization: callers don't
|
|
56
|
+
* need to await this for startup to continue.
|
|
51
57
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
58
|
+
* Claims reconnect ownership before any credential read so boot identity
|
|
59
|
+
* loading cannot open a second, identity-less session through the child
|
|
60
|
+
* entry point. CES serves a multi-connection Unix socket, so child
|
|
61
|
+
* processes in other address spaces still open their own connections.
|
|
54
62
|
*/
|
|
55
63
|
function startCesProcess(config: AssistantConfig): CesStartupResult {
|
|
56
64
|
const pm = createCesProcessManager({ assistantConfig: config });
|
|
57
65
|
const abortController = new AbortController();
|
|
58
66
|
let currentClient: CesClient | undefined;
|
|
67
|
+
let handshake: CesClientHandshakeOptions = {};
|
|
68
|
+
|
|
69
|
+
// Own this process's CES session before resolveManagedProxyContext()
|
|
70
|
+
// reads the API key. That read must not take the child open path.
|
|
71
|
+
setCesReconnect(async () => {
|
|
72
|
+
const client = await reconnectCesRpcSession(pm, handshake);
|
|
73
|
+
if (client) {
|
|
74
|
+
log.info("CES reconnection handshake accepted");
|
|
75
|
+
}
|
|
76
|
+
return client;
|
|
77
|
+
});
|
|
59
78
|
|
|
60
79
|
const handshakePromise = (async (): Promise<CesClient | undefined> => {
|
|
61
80
|
try {
|
|
62
|
-
const transport = await pm.start();
|
|
63
|
-
if (abortController.signal.aborted) {
|
|
64
|
-
throw new Error("CES initialization aborted during shutdown");
|
|
65
|
-
}
|
|
66
|
-
const client = createCesClient(transport);
|
|
67
|
-
currentClient = client;
|
|
68
81
|
// Resolve the assistant API key so CES can use it for platform
|
|
69
82
|
// credential materialisation. In managed mode the key is provisioned
|
|
70
|
-
// after hatch and stored in the credential store
|
|
71
|
-
// the env var, so we pass it via the handshake.
|
|
83
|
+
// after hatch and stored in the credential store. CES can't read
|
|
84
|
+
// the env var, so we pass it via the handshake. Reconnect ownership
|
|
85
|
+
// is already claimed, so this read uses HTTP or the encrypted store,
|
|
86
|
+
// not a second RPC session.
|
|
72
87
|
const proxyCtx = await resolveManagedProxyContext();
|
|
88
|
+
if (abortController.signal.aborted) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
73
91
|
const assistantId = getPlatformAssistantId();
|
|
74
|
-
|
|
92
|
+
handshake = {
|
|
75
93
|
...(proxyCtx.assistantApiKey
|
|
76
94
|
? { assistantApiKey: proxyCtx.assistantApiKey }
|
|
77
95
|
: {}),
|
|
78
96
|
...(assistantId ? { assistantId } : {}),
|
|
97
|
+
};
|
|
98
|
+
const session = await openCesRpcSession({
|
|
99
|
+
processManager: pm,
|
|
100
|
+
signal: abortController.signal,
|
|
101
|
+
handshake,
|
|
79
102
|
});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
throw new Error("CES initialization aborted during shutdown");
|
|
83
|
-
}
|
|
84
|
-
if (accepted) {
|
|
103
|
+
currentClient = session?.client;
|
|
104
|
+
if (session) {
|
|
85
105
|
log.info(
|
|
86
106
|
"CES client initialized and handshake accepted (server-level)",
|
|
87
107
|
);
|
|
88
|
-
return client;
|
|
89
108
|
}
|
|
109
|
+
return session?.client;
|
|
110
|
+
} catch (err) {
|
|
90
111
|
log.warn(
|
|
91
|
-
{
|
|
92
|
-
"
|
|
112
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
113
|
+
"Failed to initialize CES client",
|
|
93
114
|
);
|
|
94
|
-
client.close();
|
|
95
115
|
currentClient = undefined;
|
|
96
|
-
await pm.stop();
|
|
97
|
-
return undefined;
|
|
98
|
-
} catch (err) {
|
|
99
|
-
if (err instanceof CesUnavailableError) {
|
|
100
|
-
log.info(
|
|
101
|
-
{ reason: err.message },
|
|
102
|
-
"CES is not available — CES tools will be unavailable",
|
|
103
|
-
);
|
|
104
|
-
} else {
|
|
105
|
-
log.warn(
|
|
106
|
-
{ error: err instanceof Error ? err.message : String(err) },
|
|
107
|
-
"Failed to initialize CES client — CES tools will be unavailable",
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
116
|
await pm.stop().catch(() => {});
|
|
111
|
-
currentClient = undefined;
|
|
112
117
|
return undefined;
|
|
113
118
|
}
|
|
114
119
|
})();
|
|
@@ -154,11 +159,11 @@ function updateClientRef(client: CesClient | undefined): void {
|
|
|
154
159
|
}
|
|
155
160
|
|
|
156
161
|
/**
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* direct credential store.
|
|
162
|
+
* Open the assistant's CES RPC client: handshake (blocking up to a 20s
|
|
163
|
+
* timeout so credential reads can route through CES before provider init)
|
|
164
|
+
* and keep the live client reference in sync. Reconnect ownership is
|
|
165
|
+
* claimed before the identity read. Non-fatal: on failure the assistant
|
|
166
|
+
* falls back to the direct credential store.
|
|
162
167
|
*/
|
|
163
168
|
export async function startCes(config: AssistantConfig): Promise<void> {
|
|
164
169
|
const cesResult = startCesProcess(config);
|
|
@@ -171,7 +176,7 @@ export async function startCes(config: AssistantConfig): Promise<void> {
|
|
|
171
176
|
timeoutMs: DEFAULT_CES_STARTUP_TIMEOUT_MS,
|
|
172
177
|
onTimeout: () => {
|
|
173
178
|
log.warn(
|
|
174
|
-
"CES handshake timed out after 20s
|
|
179
|
+
"CES handshake timed out after 20s, falling back to direct credential store",
|
|
175
180
|
);
|
|
176
181
|
},
|
|
177
182
|
});
|
|
@@ -193,56 +198,13 @@ export async function startCes(config: AssistantConfig): Promise<void> {
|
|
|
193
198
|
}
|
|
194
199
|
}
|
|
195
200
|
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
//
|
|
201
|
+
// Reconnect ownership is claimed inside startCesProcess before the
|
|
202
|
+
// identity read. Snapshotting the API key there (not here) avoids a
|
|
203
|
+
// second resolveManagedProxyContext() after setCesClient, which would
|
|
204
|
+
// read the key through CES while reconnecting.
|
|
199
205
|
if (cesResult.processManager) {
|
|
200
206
|
const pm = cesResult.processManager;
|
|
201
207
|
|
|
202
|
-
// Snapshot the managed-proxy context and assistant ID at CES startup so the
|
|
203
|
-
// reconnect closure below never calls back into `resolveManagedProxyContext()`.
|
|
204
|
-
// That function reads the assistant API key via `getSecureKeyAsync()`, which
|
|
205
|
-
// — once `setCesClient()` has resolved the backend to CES RPC — routes the
|
|
206
|
-
// read through CES itself. During a reconnect the old transport is dead and
|
|
207
|
-
// a new one is being set up by this very closure, so the nested credential
|
|
208
|
-
// read recursively awaits its own in-flight reconnection and deadlocks until
|
|
209
|
-
// `CREDENTIAL_OP_TIMEOUT_MS` (45s) fires. That 45-second stall delays every
|
|
210
|
-
// CES restart and causes dependent credential reads (e.g. Meet's STT
|
|
211
|
-
// provider resolution) to return `undefined` during the window. API key
|
|
212
|
-
// rotation uses the `updateAssistantApiKey` RPC on the live client, not a
|
|
213
|
-
// reconnect, so caching at startup is safe.
|
|
214
|
-
const startupProxyCtx = await resolveManagedProxyContext();
|
|
215
|
-
const startupAssistantId = getPlatformAssistantId();
|
|
216
|
-
|
|
217
|
-
setCesReconnect(async () => {
|
|
218
|
-
try {
|
|
219
|
-
await pm.stop();
|
|
220
|
-
const transport = await pm.start();
|
|
221
|
-
const newClient = createCesClient(transport);
|
|
222
|
-
const { accepted, reason } = await newClient.handshake({
|
|
223
|
-
...(startupProxyCtx.assistantApiKey
|
|
224
|
-
? { assistantApiKey: startupProxyCtx.assistantApiKey }
|
|
225
|
-
: {}),
|
|
226
|
-
...(startupAssistantId ? { assistantId: startupAssistantId } : {}),
|
|
227
|
-
});
|
|
228
|
-
if (accepted) {
|
|
229
|
-
log.info("CES reconnection handshake accepted");
|
|
230
|
-
return newClient;
|
|
231
|
-
}
|
|
232
|
-
log.warn({ reason }, "CES reconnection handshake rejected");
|
|
233
|
-
newClient.close();
|
|
234
|
-
await pm.stop().catch(() => {});
|
|
235
|
-
return undefined;
|
|
236
|
-
} catch (err) {
|
|
237
|
-
log.warn(
|
|
238
|
-
{ error: err instanceof Error ? err.message : String(err) },
|
|
239
|
-
"CES reconnection attempt failed",
|
|
240
|
-
);
|
|
241
|
-
await pm.stop().catch(() => {});
|
|
242
|
-
return undefined;
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
|
|
246
208
|
// Proactive reconnect: when the transport dies (socket close, process
|
|
247
209
|
// exit), start a retry-with-backoff loop immediately instead of waiting
|
|
248
210
|
// for the next credential operation to trigger the lazy reconnect path.
|
|
@@ -1,196 +1,88 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CES
|
|
2
|
+
* CES socket discovery and transport bootstrap.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Unix socket (`CES_LOCAL_SOCKET`). Used by bare-metal/local instances.
|
|
8
|
-
*
|
|
9
|
-
* 2. **Managed mode** — Locates the bootstrap Unix socket exposed by the CES
|
|
10
|
-
* sidecar container through a shared emptyDir volume, and returns a
|
|
11
|
-
* connected Unix socket transport.
|
|
12
|
-
*
|
|
13
|
-
* Both strategies fail closed: if the socket cannot be found, the discovery
|
|
14
|
-
* returns a structured error rather than falling back to in-process
|
|
15
|
-
* credential handling.
|
|
4
|
+
* Local siblings and managed sidecars share one resolver: `ces.sock` under
|
|
5
|
+
* `CES_BOOTSTRAP_SOCKET_DIR` (default `/run/ces-bootstrap`). Discovery fails
|
|
6
|
+
* closed if the socket cannot be found.
|
|
16
7
|
*/
|
|
17
8
|
|
|
18
9
|
import { existsSync } from "node:fs";
|
|
19
|
-
import { join } from "node:path";
|
|
20
10
|
|
|
21
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
isNamedPipePath,
|
|
13
|
+
resolveIpcEndpoint,
|
|
14
|
+
} from "@vellumai/ipc-server-utils";
|
|
15
|
+
|
|
22
16
|
import { getLogger } from "../util/logger.js";
|
|
23
17
|
|
|
24
18
|
const log = getLogger("ces-discovery");
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
// Well-known paths
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
/** Default directory for the bootstrap socket shared volume. */
|
|
20
|
+
/** Default directory for the CES Unix socket. */
|
|
31
21
|
const DEFAULT_BOOTSTRAP_SOCKET_DIR = "/run/ces-bootstrap";
|
|
32
22
|
|
|
33
|
-
/** Bootstrap socket filename. */
|
|
34
|
-
const BOOTSTRAP_SOCKET_NAME = "ces.sock";
|
|
35
|
-
|
|
36
23
|
/**
|
|
37
|
-
* Resolve the CES
|
|
38
|
-
*
|
|
39
|
-
* Priority:
|
|
40
|
-
* 1. `CES_BOOTSTRAP_SOCKET_DIR` env var (directory) — appends `ces.sock`
|
|
41
|
-
* 2. `CES_BOOTSTRAP_SOCKET` env var (full file path override)
|
|
42
|
-
* 3. Hardcoded default: `/run/ces-bootstrap/ces.sock`
|
|
24
|
+
* Resolve the CES socket path used in every environment.
|
|
43
25
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
26
|
+
* Uses `CES_BOOTSTRAP_SOCKET_DIR` when set, otherwise `/run/ces-bootstrap`.
|
|
27
|
+
* `ces.sock` is resolved through `resolveIpcEndpoint`.
|
|
46
28
|
*/
|
|
47
|
-
function
|
|
48
|
-
const dir =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
return (
|
|
53
|
-
process.env["CES_BOOTSTRAP_SOCKET"] ??
|
|
54
|
-
join(DEFAULT_BOOTSTRAP_SOCKET_DIR, BOOTSTRAP_SOCKET_NAME)
|
|
55
|
-
);
|
|
29
|
+
function getCesSocketPath(): string {
|
|
30
|
+
const dir =
|
|
31
|
+
process.env["CES_BOOTSTRAP_SOCKET_DIR"]?.trim() ||
|
|
32
|
+
DEFAULT_BOOTSTRAP_SOCKET_DIR;
|
|
33
|
+
return resolveIpcEndpoint("ces", { workspaceDir: dir }).path;
|
|
56
34
|
}
|
|
57
35
|
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
// Discovery result types
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
|
|
62
36
|
export interface ManagedDiscoverySuccess {
|
|
63
37
|
mode: "managed";
|
|
64
38
|
socketPath: string;
|
|
65
39
|
}
|
|
66
40
|
|
|
67
|
-
/**
|
|
68
|
-
* A local CES running as an independent sibling process (not spawned by the
|
|
69
|
-
* assistant), reached over a Unix socket. Transport-identical to managed; the
|
|
70
|
-
* distinct mode records that the assistant does not own this process's
|
|
71
|
-
* lifecycle. This is the default topology for bare-metal/local instances.
|
|
72
|
-
*/
|
|
73
|
-
export interface SiblingDiscoverySuccess {
|
|
74
|
-
mode: "sibling";
|
|
75
|
-
socketPath: string;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
41
|
export interface DiscoveryFailure {
|
|
79
42
|
mode: "unavailable";
|
|
80
43
|
reason: string;
|
|
81
44
|
}
|
|
82
45
|
|
|
83
|
-
export type DiscoveryResult =
|
|
84
|
-
| ManagedDiscoverySuccess
|
|
85
|
-
| SiblingDiscoverySuccess
|
|
86
|
-
| DiscoveryFailure;
|
|
87
|
-
|
|
88
|
-
// ---------------------------------------------------------------------------
|
|
89
|
-
// Managed discovery
|
|
90
|
-
// ---------------------------------------------------------------------------
|
|
46
|
+
export type DiscoveryResult = ManagedDiscoverySuccess | DiscoveryFailure;
|
|
91
47
|
|
|
92
48
|
/**
|
|
93
|
-
* Discover
|
|
94
|
-
*
|
|
95
|
-
* Checks that the well-known socket file exists on disk. Does NOT open a
|
|
96
|
-
* connection — the CES sidecar accepts exactly one connection and then
|
|
97
|
-
* unlinks the socket, so a probe would consume the only slot. The actual
|
|
98
|
-
* connection is made later by `CesProcessManager.start()`.
|
|
49
|
+
* Discover CES via the shared bootstrap Unix socket.
|
|
99
50
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
51
|
+
* Checks that the well-known socket exists. Does not open a connection.
|
|
52
|
+
* CES serves a multi-connection listener, so the assistant and its child
|
|
53
|
+
* processes can each connect. The actual connection is made later by
|
|
54
|
+
* `CesProcessManager.start()`.
|
|
102
55
|
*/
|
|
103
|
-
export function
|
|
104
|
-
|
|
105
|
-
| DiscoveryFailure {
|
|
106
|
-
const socketPath = getManagedBootstrapSocketPath();
|
|
56
|
+
export function discoverCes(): DiscoveryResult {
|
|
57
|
+
const socketPath = getCesSocketPath();
|
|
107
58
|
|
|
108
|
-
if (!existsSync(socketPath)) {
|
|
59
|
+
if (!isNamedPipePath(socketPath) && !existsSync(socketPath)) {
|
|
109
60
|
const reason = `CES bootstrap socket not found at ${socketPath}`;
|
|
110
61
|
log.warn(reason);
|
|
111
62
|
return { mode: "unavailable", reason };
|
|
112
63
|
}
|
|
113
64
|
|
|
114
|
-
log.info({ socketPath }, "
|
|
65
|
+
log.info({ socketPath }, "CES bootstrap socket found");
|
|
115
66
|
return { mode: "managed", socketPath };
|
|
116
67
|
}
|
|
117
68
|
|
|
118
|
-
|
|
119
|
-
// Sibling discovery (local bare-metal topology)
|
|
120
|
-
// ---------------------------------------------------------------------------
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Discover a CLI-launched local CES sibling via its Unix socket. The CLI sets
|
|
124
|
-
* `CES_LOCAL_SOCKET` on both the sibling and the daemon so they agree on the
|
|
125
|
-
* path. Does not open a connection — that happens in `CesProcessManager.start()`.
|
|
126
|
-
*/
|
|
127
|
-
export function discoverLocalSiblingCes():
|
|
128
|
-
| SiblingDiscoverySuccess
|
|
129
|
-
| DiscoveryFailure {
|
|
130
|
-
const socketPath = process.env["CES_LOCAL_SOCKET"];
|
|
131
|
-
if (!socketPath) {
|
|
132
|
-
const reason =
|
|
133
|
-
"CES_LOCAL_SOCKET is not set — cannot locate the CES sibling socket. The CLI should set this during wake/hatch.";
|
|
134
|
-
log.warn(reason);
|
|
135
|
-
return { mode: "unavailable", reason };
|
|
136
|
-
}
|
|
137
|
-
if (!existsSync(socketPath)) {
|
|
138
|
-
return {
|
|
139
|
-
mode: "unavailable",
|
|
140
|
-
reason: `CES sibling socket not found at ${socketPath}`,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
log.info({ socketPath }, "Local CES sibling socket found");
|
|
144
|
-
return { mode: "sibling", socketPath };
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// ---------------------------------------------------------------------------
|
|
148
|
-
// Auto-discovery
|
|
149
|
-
// ---------------------------------------------------------------------------
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Automatically discover CES using the appropriate strategy for the
|
|
153
|
-
* current deployment topology.
|
|
154
|
-
*
|
|
155
|
-
* - Containerized environments → managed sidecar discovery
|
|
156
|
-
* - Non-containerized → CLI-launched sibling socket discovery
|
|
157
|
-
*/
|
|
158
|
-
export function discoverCes(): DiscoveryResult {
|
|
159
|
-
if (getIsContainerized()) {
|
|
160
|
-
return discoverManagedCes();
|
|
161
|
-
}
|
|
162
|
-
return discoverLocalSiblingCes();
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/** How long to poll for the managed bootstrap socket before giving up. */
|
|
69
|
+
/** How long to poll for the CES socket before giving up. */
|
|
166
70
|
const MANAGED_DISCOVERY_TIMEOUT_MS = 3_000;
|
|
167
71
|
|
|
168
|
-
/** Delay between
|
|
72
|
+
/** Delay between CES socket discovery attempts. */
|
|
169
73
|
const MANAGED_DISCOVERY_INTERVAL_MS = 100;
|
|
170
74
|
|
|
171
75
|
/**
|
|
172
|
-
* Discover CES, polling for the
|
|
173
|
-
* backoff before failing.
|
|
174
|
-
*
|
|
175
|
-
* The managed CES sidecar re-binds its bootstrap socket after each assistant
|
|
176
|
-
* session ends — it outlives any single assistant and accepts the next
|
|
177
|
-
* connection (see `credential-executor/src/main.ts`). A reconnecting
|
|
178
|
-
* assistant (e.g. after a container restart) can therefore probe during the
|
|
179
|
-
* brief window before the socket is re-bound. A single existence check would
|
|
180
|
-
* race that window and incorrectly report the sidecar as unavailable; polling
|
|
181
|
-
* absorbs the gap.
|
|
76
|
+
* Discover CES, polling for the socket with a short backoff before failing.
|
|
182
77
|
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
78
|
+
* CES binds its socket asynchronously. A reconnecting assistant can probe
|
|
79
|
+
* during the brief window before the socket is re-bound. Polling absorbs
|
|
80
|
+
* that gap.
|
|
185
81
|
*/
|
|
186
82
|
export async function discoverCesWithRetry({
|
|
187
83
|
timeoutMs = MANAGED_DISCOVERY_TIMEOUT_MS,
|
|
188
84
|
intervalMs = MANAGED_DISCOVERY_INTERVAL_MS,
|
|
189
85
|
}: { timeoutMs?: number; intervalMs?: number } = {}): Promise<DiscoveryResult> {
|
|
190
|
-
// Both the managed bootstrap socket and the CLI-launched sibling socket
|
|
191
|
-
// are bound asynchronously, so polling is worthwhile. A missing local
|
|
192
|
-
// binary (the old stdio path) would not appear by waiting, but that path
|
|
193
|
-
// is gone — the sibling is the only local topology now.
|
|
194
86
|
const deadline = Date.now() + timeoutMs;
|
|
195
87
|
let result = discoverCes();
|
|
196
88
|
while (result.mode === "unavailable" && Date.now() < deadline) {
|
|
@@ -3,12 +3,10 @@ import { createServer, type Server } from "node:net";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import {
|
|
6
|
-
afterAll,
|
|
7
6
|
afterEach,
|
|
8
7
|
beforeEach,
|
|
9
8
|
describe,
|
|
10
9
|
expect,
|
|
11
|
-
mock,
|
|
12
10
|
test,
|
|
13
11
|
} from "bun:test";
|
|
14
12
|
|
|
@@ -21,22 +19,18 @@ const untilClosed = (predicate: () => boolean) =>
|
|
|
21
19
|
message: "socket close never propagated to the transport",
|
|
22
20
|
});
|
|
23
21
|
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
// onTransportClose tests
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
|
|
28
|
-
// Mock executable-discovery so start() connects to our test socket.
|
|
29
|
-
const realDiscovery = await import("./executable-discovery.js");
|
|
30
|
-
|
|
31
22
|
let mockSocketPath = "";
|
|
32
23
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
mode: "sibling" as const,
|
|
24
|
+
function discoverTestSocket() {
|
|
25
|
+
return Promise.resolve({
|
|
26
|
+
mode: "managed" as const,
|
|
37
27
|
socketPath: mockSocketPath,
|
|
38
|
-
})
|
|
39
|
-
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// onTransportClose tests
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
40
34
|
|
|
41
35
|
describe("CesProcessManager.onTransportClose", () => {
|
|
42
36
|
let tempDir: string;
|
|
@@ -67,12 +61,8 @@ describe("CesProcessManager.onTransportClose", () => {
|
|
|
67
61
|
rmSync(tempDir, { recursive: true, force: true });
|
|
68
62
|
});
|
|
69
63
|
|
|
70
|
-
afterAll(() => {
|
|
71
|
-
mock.module("./executable-discovery.js", () => realDiscovery);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
64
|
test("fires handler when the transport dies (socket closed)", async () => {
|
|
75
|
-
const pm = createCesProcessManager({});
|
|
65
|
+
const pm = createCesProcessManager({ discover: discoverTestSocket });
|
|
76
66
|
const transport = await pm.start();
|
|
77
67
|
expect(transport.isAlive()).toBe(true);
|
|
78
68
|
|
|
@@ -93,7 +83,7 @@ describe("CesProcessManager.onTransportClose", () => {
|
|
|
93
83
|
});
|
|
94
84
|
|
|
95
85
|
test("does not fire handler before the transport dies", async () => {
|
|
96
|
-
const pm = createCesProcessManager({});
|
|
86
|
+
const pm = createCesProcessManager({ discover: discoverTestSocket });
|
|
97
87
|
await pm.start();
|
|
98
88
|
|
|
99
89
|
let closeFired = false;
|
|
@@ -109,7 +99,7 @@ describe("CesProcessManager.onTransportClose", () => {
|
|
|
109
99
|
});
|
|
110
100
|
|
|
111
101
|
test("fires handler immediately if transport is already dead", async () => {
|
|
112
|
-
const pm = createCesProcessManager({});
|
|
102
|
+
const pm = createCesProcessManager({ discover: discoverTestSocket });
|
|
113
103
|
const transport = await pm.start();
|
|
114
104
|
|
|
115
105
|
// Kill the transport by destroying the server-side socket.
|
|
@@ -186,7 +176,10 @@ describe("CesProcessManager transport-death logging", () => {
|
|
|
186
176
|
|
|
187
177
|
test("logs WARN when the transport dies unexpectedly (remote close)", async () => {
|
|
188
178
|
const { calls, logger } = makeRecordingLogger();
|
|
189
|
-
const pm = createCesProcessManager({
|
|
179
|
+
const pm = createCesProcessManager({
|
|
180
|
+
logger,
|
|
181
|
+
discover: discoverTestSocket,
|
|
182
|
+
});
|
|
190
183
|
const transport = await pm.start();
|
|
191
184
|
|
|
192
185
|
// The remote (server) closes the connection: genuinely-unexpected death.
|
|
@@ -205,7 +198,10 @@ describe("CesProcessManager transport-death logging", () => {
|
|
|
205
198
|
|
|
206
199
|
test("does not log WARN on an intentional stop()", async () => {
|
|
207
200
|
const { calls, logger } = makeRecordingLogger();
|
|
208
|
-
const pm = createCesProcessManager({
|
|
201
|
+
const pm = createCesProcessManager({
|
|
202
|
+
logger,
|
|
203
|
+
discover: discoverTestSocket,
|
|
204
|
+
});
|
|
209
205
|
await pm.start();
|
|
210
206
|
|
|
211
207
|
await pm.stop();
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CES process manager.
|
|
3
3
|
*
|
|
4
|
-
* Creates transport
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Creates a transport connection to the CES process over the shared bootstrap
|
|
5
|
+
* socket. Local CLI siblings and managed sidecars bind the same path under
|
|
6
|
+
* `CES_BOOTSTRAP_SOCKET_DIR`. The process manager owns only the transport
|
|
7
|
+
* connection lifecycle; the CES process itself is managed by the CLI
|
|
8
|
+
* (sibling) or the pod infrastructure (managed).
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
12
|
-
* - /assistant-data-ro
|
|
13
|
-
* - /ces-data
|
|
14
|
-
* - CES_HEALTH_PORT
|
|
10
|
+
* Env contract:
|
|
11
|
+
* - CES_BOOTSTRAP_SOCKET_DIR: directory containing `ces.sock`
|
|
12
|
+
* - /assistant-data-ro: assistant data mounted read-only into CES
|
|
13
|
+
* - /ces-data: CES private data directory (separate PVC)
|
|
14
|
+
* - CES_HEALTH_PORT: health check port exposed by the CES sidecar
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { createConnection, type Socket } from "node:net";
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
discoverCesWithRetry,
|
|
25
25
|
type DiscoveryResult,
|
|
26
26
|
type ManagedDiscoverySuccess,
|
|
27
|
-
type SiblingDiscoverySuccess,
|
|
28
27
|
} from "./executable-discovery.js";
|
|
29
28
|
|
|
30
29
|
const log = getLogger("ces-process-manager");
|
|
@@ -62,6 +61,12 @@ export interface CesProcessManagerConfig {
|
|
|
62
61
|
|
|
63
62
|
/** Logger override. Defaults to the module logger; injected in tests. */
|
|
64
63
|
logger?: PmLogger;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Socket discovery. Defaults to `discoverCesWithRetry`. Tests inject a
|
|
67
|
+
* stub that returns a known socket path.
|
|
68
|
+
*/
|
|
69
|
+
discover?: typeof discoverCesWithRetry;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
// ---------------------------------------------------------------------------
|
|
@@ -70,7 +75,7 @@ export interface CesProcessManagerConfig {
|
|
|
70
75
|
|
|
71
76
|
export interface CesProcessManager {
|
|
72
77
|
/**
|
|
73
|
-
* Connect to the CES
|
|
78
|
+
* Connect to the CES bootstrap socket.
|
|
74
79
|
* Returns a CesTransport ready for use with createCesClient().
|
|
75
80
|
*
|
|
76
81
|
* Throws if CES is unavailable.
|
|
@@ -107,6 +112,7 @@ export function createCesProcessManager(
|
|
|
107
112
|
config: CesProcessManagerConfig,
|
|
108
113
|
): CesProcessManager {
|
|
109
114
|
const pmLog = config.logger ?? log;
|
|
115
|
+
const discover = config.discover ?? discoverCesWithRetry;
|
|
110
116
|
let managedSocket: Socket | null = null;
|
|
111
117
|
let discoveryResult: DiscoveryResult | null = null;
|
|
112
118
|
let running = false;
|
|
@@ -119,16 +125,15 @@ export function createCesProcessManager(
|
|
|
119
125
|
throw new Error("CES process manager is already running");
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
// Poll for the socket with a short backoff.
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
discoveryResult = await
|
|
128
|
+
// Poll for the socket with a short backoff. CES binds
|
|
129
|
+
// asynchronously, so a reconnecting assistant can briefly race
|
|
130
|
+
// the re-bind.
|
|
131
|
+
discoveryResult = await discover();
|
|
126
132
|
|
|
127
133
|
if (discoveryResult.mode === "unavailable") {
|
|
128
134
|
throw new CesUnavailableError(discoveryResult.reason);
|
|
129
135
|
}
|
|
130
136
|
|
|
131
|
-
// managed sidecar or CLI-launched sibling — both connect to a socket.
|
|
132
137
|
const transport = await connectManagedSocket(discoveryResult);
|
|
133
138
|
currentTransport = transport;
|
|
134
139
|
wireTransportClose(transport);
|
|
@@ -200,11 +205,11 @@ export function createCesProcessManager(
|
|
|
200
205
|
}
|
|
201
206
|
|
|
202
207
|
// -------------------------------------------------------------------------
|
|
203
|
-
// Socket connection
|
|
208
|
+
// Socket connection
|
|
204
209
|
// -------------------------------------------------------------------------
|
|
205
210
|
|
|
206
211
|
async function connectManagedSocket(
|
|
207
|
-
discovery: ManagedDiscoverySuccess
|
|
212
|
+
discovery: ManagedDiscoverySuccess,
|
|
208
213
|
): Promise<SocketTransport> {
|
|
209
214
|
pmLog.info(
|
|
210
215
|
{ socketPath: discovery.socketPath, mode: discovery.mode },
|
|
@@ -440,7 +440,12 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
|
|
|
440
440
|
// claimed to eliminate that round-trip; this test enforces it.
|
|
441
441
|
nextKeyStoreResult = { conversationId: "conv-pending-set" };
|
|
442
442
|
|
|
443
|
-
const
|
|
443
|
+
const settleStructuralWait = mock(() => true);
|
|
444
|
+
const ctx = makeContext({
|
|
445
|
+
modeSessions: {
|
|
446
|
+
settleStructuralWait,
|
|
447
|
+
} as unknown as Conversation["modeSessions"],
|
|
448
|
+
});
|
|
444
449
|
registerCardSurface(ctx, "surface-pending");
|
|
445
450
|
// Simulate `ui_show` having stamped a pending entry for this surface
|
|
446
451
|
// (which it does for any interactive card, including persistent ones).
|
|
@@ -473,6 +478,10 @@ describe("handleSurfaceAction — launch_conversation dispatch", () => {
|
|
|
473
478
|
// Pending entry was deleted so subsequent sibling clicks on the same
|
|
474
479
|
// persistent card aren't blocked behind a stale "owes-an-answer" flag.
|
|
475
480
|
expect(ctx.pendingSurfaceActions.has("surface-pending")).toBe(false);
|
|
481
|
+
expect(settleStructuralWait).toHaveBeenCalledWith(
|
|
482
|
+
{ kind: "surface", responseId: "surface-pending" },
|
|
483
|
+
{ status: "completed", endReason: "surface_launch_settled" },
|
|
484
|
+
);
|
|
476
485
|
|
|
477
486
|
await processStartedPromise;
|
|
478
487
|
resolveProcess();
|