@vellumai/assistant 0.6.6 → 0.7.1
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/AGENTS.md +20 -0
- package/ARCHITECTURE.md +46 -38
- package/Dockerfile +27 -6
- package/README.md +9 -11
- package/__tests__/permissions/gateway-threshold-reader.test.ts +83 -149
- package/bun.lock +309 -119
- package/docs/architecture/memory.md +1 -90
- package/docs/architecture/security.md +28 -41
- package/docs/credential-execution-service.md +7 -5
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +17 -45
- package/examples/plugins/echo/bun.lock +25 -0
- package/knip.json +9 -22
- package/node_modules/@vellumai/ces-client/bun.lock +33 -0
- package/node_modules/@vellumai/ces-client/package.json +25 -0
- package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +631 -0
- package/node_modules/@vellumai/ces-client/src/__tests__/package-boundary.test.ts +138 -0
- package/node_modules/@vellumai/ces-client/src/credential-rpc.ts +13 -0
- package/node_modules/@vellumai/ces-client/src/http-credentials.ts +296 -0
- package/node_modules/@vellumai/ces-client/src/http-log-export.ts +111 -0
- package/node_modules/@vellumai/ces-client/src/index.ts +43 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +445 -0
- package/node_modules/@vellumai/credential-storage/src/__tests__/package-boundary.test.ts +32 -6
- package/node_modules/@vellumai/egress-proxy/src/__tests__/package-boundary.test.ts +32 -1
- package/node_modules/@vellumai/gateway-client/bun.lock +39 -0
- package/node_modules/@vellumai/gateway-client/package.json +23 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/gateway-client.test.ts +343 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/package-boundary.test.ts +140 -0
- package/node_modules/@vellumai/gateway-client/src/http-delivery.ts +422 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +35 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +331 -0
- package/node_modules/@vellumai/gateway-client/src/types.ts +131 -0
- package/node_modules/@vellumai/gateway-client/tsconfig.json +20 -0
- package/node_modules/@vellumai/{ces-contracts → service-contracts}/bun.lock +1 -1
- package/node_modules/@vellumai/{ces-contracts → service-contracts}/package.json +4 -2
- package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/__tests__/contracts.test.ts +5 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +155 -0
- package/node_modules/@vellumai/service-contracts/src/credential-rpc.ts +23 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +25 -0
- package/node_modules/@vellumai/{ces-contracts/src/index.ts → service-contracts/src/transport.ts} +6 -28
- package/node_modules/@vellumai/service-contracts/src/trust-rules.ts +116 -0
- package/node_modules/@vellumai/service-contracts/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +887 -0
- package/node_modules/@vellumai/skill-host-contracts/bun.lock +24 -0
- package/node_modules/@vellumai/skill-host-contracts/package.json +18 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +86 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +1342 -0
- package/node_modules/@vellumai/skill-host-contracts/src/index.ts +6 -0
- package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +11 -0
- package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +32 -0
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +325 -0
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +444 -0
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +12 -0
- package/node_modules/@vellumai/slack-text/bun.lock +24 -0
- package/node_modules/@vellumai/slack-text/package.json +18 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
- package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
- package/openapi.yaml +3136 -650
- package/package.json +15 -7
- package/scripts/check-circular-deps.ts +80 -0
- package/scripts/generate-openapi.ts +29 -107
- package/{src/memory/graph/inspect.ts → scripts/memory-inspect.ts} +27 -27
- package/src/__tests__/access-request-decision.test.ts +2 -11
- package/src/__tests__/acp-session.test.ts +4 -150
- package/src/__tests__/actor-token-service.test.ts +17 -678
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +2 -6
- package/src/__tests__/agent-loop-override-profile.test.ts +404 -0
- package/src/__tests__/agent-loop-thinking.test.ts +4 -4
- package/src/__tests__/agent-wake-override-profile.test.ts +283 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -1
- package/src/__tests__/anthropic-provider.test.ts +183 -28
- package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/app-routes-csp.test.ts +106 -55
- package/src/__tests__/approval-cascade.test.ts +3 -370
- package/src/__tests__/approval-conversation-turn.test.ts +3 -8
- package/src/__tests__/approval-hardcoded-copy-guard.test.ts +1 -1
- package/src/__tests__/approval-primitive.test.ts +2 -1
- package/src/__tests__/approval-routes-http.test.ts +36 -464
- package/src/__tests__/assistant-event-hub.test.ts +126 -77
- package/src/__tests__/assistant-event.test.ts +0 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +107 -92
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -3
- package/src/__tests__/attachment-upload-trusted-source.test.ts +139 -0
- package/src/__tests__/attachments-store.test.ts +46 -1
- package/src/__tests__/audit-log-rotation.test.ts +2 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +8 -20
- package/src/__tests__/background-shell-bash.test.ts +227 -0
- package/src/__tests__/background-shell-host-bash.test.ts +465 -0
- package/src/__tests__/background-tool-registry.test.ts +145 -0
- package/src/__tests__/background-tool-routes.test.ts +175 -0
- package/src/__tests__/btw-routes.test.ts +147 -183
- package/src/__tests__/call-controller.test.ts +15 -2
- package/src/__tests__/call-conversation-messages.test.ts +2 -1
- package/src/__tests__/call-domain.test.ts +2 -2
- package/src/__tests__/call-pointer-messages.test.ts +11 -13
- package/src/__tests__/call-recovery.test.ts +2 -1
- package/src/__tests__/call-routes-http.test.ts +3 -14
- package/src/__tests__/call-site-routing-provider.test.ts +193 -0
- package/src/__tests__/call-store.test.ts +2 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +31 -62
- package/src/__tests__/canonical-guardian-store.test.ts +2 -2
- package/src/__tests__/catalog-files.test.ts +0 -26
- package/src/__tests__/ces-rpc-credential-backend.test.ts +1 -1
- package/src/__tests__/channel-approval-routes.test.ts +88 -344
- package/src/__tests__/channel-approval.test.ts +9 -7
- package/src/__tests__/channel-approvals.test.ts +34 -197
- package/src/__tests__/channel-delivery-store.test.ts +11 -10
- package/src/__tests__/channel-guardian.test.ts +114 -171
- package/src/__tests__/channel-readiness-service.test.ts +8 -6
- package/src/__tests__/channel-reply-delivery.test.ts +3 -19
- package/src/__tests__/channel-retry-sweep.test.ts +2 -5
- package/src/__tests__/checker.test.ts +272 -3933
- package/src/__tests__/circuit-breaker-pipeline.test.ts +1 -1
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +208 -0
- package/src/__tests__/cli.test.ts +1 -38
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
- package/src/__tests__/compaction-events.test.ts +2 -1
- package/src/__tests__/compaction-pipeline.test.ts +1 -1
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +2 -2
- package/src/__tests__/compaction-timeout-recovery.test.ts +1 -1
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -7
- package/src/__tests__/config-model-image-provider.test.ts +0 -1
- package/src/__tests__/config-schema-cmd.test.ts +1 -1
- package/src/__tests__/config-schema.test.ts +36 -269
- package/src/__tests__/config-watcher.test.ts +12 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +4 -25
- package/src/__tests__/connection-policy.test.ts +1 -52
- package/src/__tests__/contact-store-user-file.test.ts +2 -1
- package/src/__tests__/contacts-tools.test.ts +56 -29
- package/src/__tests__/contacts-write.test.ts +8 -125
- package/src/__tests__/context-image-dimensions.test.ts +1 -1
- package/src/__tests__/context-search-agent-protocol.test.ts +230 -0
- package/src/__tests__/context-search-agent-runner.test.ts +998 -0
- package/src/__tests__/context-search-conversations-source.test.ts +320 -0
- package/src/__tests__/context-search-fanout.test.ts +380 -0
- package/src/__tests__/context-search-memory-source.test.ts +430 -0
- package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
- package/src/__tests__/context-search-pkb-source.test.ts +493 -0
- package/src/__tests__/context-search-types.test.ts +95 -0
- package/src/__tests__/context-search-workspace-source.test.ts +532 -0
- package/src/__tests__/context-window-manager.test.ts +71 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +10 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +633 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +117 -31
- package/src/__tests__/conversation-agent-loop.test.ts +1004 -15
- package/src/__tests__/conversation-analysis-routes.test.ts +68 -88
- package/src/__tests__/conversation-attachments.test.ts +9 -20
- package/src/__tests__/conversation-attention-store.test.ts +2 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +15 -5
- package/src/__tests__/conversation-clear-safety.test.ts +53 -95
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -330
- package/src/__tests__/conversation-crud-inference-profile.test.ts +54 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +63 -157
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-disk-view.test.ts +5 -4
- package/src/__tests__/conversation-fork-crud.test.ts +26 -55
- package/src/__tests__/conversation-fork-route.test.ts +5 -74
- package/src/__tests__/conversation-history-web-search.test.ts +4 -3
- package/src/__tests__/conversation-inference-profile-list.test.ts +128 -0
- package/src/__tests__/conversation-inference-profile-route.test.ts +205 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +4 -81
- package/src/__tests__/conversation-key-store-disk-view.test.ts +2 -1
- package/src/__tests__/conversation-lifecycle.test.ts +4 -5
- package/src/__tests__/conversation-list-source.test.ts +2 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +0 -1
- package/src/__tests__/conversation-pairing.test.ts +0 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +137 -297
- package/src/__tests__/conversation-process-callsite.test.ts +79 -3
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -1
- package/src/__tests__/conversation-queue.test.ts +4 -41
- package/src/__tests__/conversation-routes-disk-view.test.ts +55 -188
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +64 -71
- package/src/__tests__/conversation-routes-slash-commands.test.ts +144 -64
- package/src/__tests__/conversation-runtime-assembly.test.ts +295 -84
- package/src/__tests__/conversation-slash-commands.test.ts +30 -47
- package/src/__tests__/conversation-slash-queue.test.ts +2 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
- package/src/__tests__/conversation-speed-override.test.ts +0 -4
- package/src/__tests__/conversation-starter-routes.test.ts +254 -55
- package/src/__tests__/conversation-starters-cadence.test.ts +2 -2
- package/src/__tests__/conversation-store.test.ts +2 -375
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
- package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -47
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +6 -6
- package/src/__tests__/conversation-unread-route.test.ts +1 -1
- package/src/__tests__/conversation-usage.test.ts +255 -4
- package/src/__tests__/conversation-wipe.test.ts +2 -103
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
- package/src/__tests__/conversations-defer-cli.test.ts +150 -0
- package/src/__tests__/credential-execution-admin-cli.test.ts +1 -1
- package/src/__tests__/credential-execution-api-key-propagation.test.ts +2 -2
- package/src/__tests__/credential-execution-approval-bridge.test.ts +22 -289
- package/src/__tests__/credential-execution-client.test.ts +1 -1
- package/src/__tests__/credential-execution-managed-contract.test.ts +1 -1
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
- package/src/__tests__/credential-health-service.test.ts +68 -0
- package/src/__tests__/credential-security-e2e.test.ts +4 -3
- package/src/__tests__/credential-security-invariants.test.ts +15 -5
- package/src/__tests__/credential-token-resolver.test.ts +180 -0
- package/src/__tests__/credentials-cli.test.ts +45 -21
- package/src/__tests__/cu-unified-flow.test.ts +33 -16
- package/src/__tests__/daemon-assistant-events.test.ts +34 -21
- package/src/__tests__/daemon-credential-client.test.ts +26 -108
- package/src/__tests__/db-acp-history.test.ts +284 -0
- package/src/__tests__/db-activation-state.test.ts +240 -0
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +2 -1
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +248 -0
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +2 -1
- package/src/__tests__/db-memory-graph-event-date-repair.test.ts +116 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-rename-inference-profile-snake-case-migration.test.ts +132 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
- package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
- package/src/__tests__/delete-propagation.test.ts +3 -2
- package/src/__tests__/deterministic-verification-control-plane.test.ts +38 -104
- package/src/__tests__/dm-backfill.test.ts +3 -2
- package/src/__tests__/document-conversations.test.ts +332 -0
- package/src/__tests__/edit-propagation.test.ts +5 -7
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +3 -3
- package/src/__tests__/emit-event-signal.test.ts +4 -6
- package/src/__tests__/empty-response-pipeline.test.ts +1 -1
- package/src/__tests__/events-client-registration.test.ts +441 -0
- package/src/__tests__/file-write-tool.test.ts +2 -4
- package/src/__tests__/filing-service.test.ts +197 -19
- package/src/__tests__/first-greeting.test.ts +156 -150
- package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
- package/src/__tests__/followup-tools.test.ts +2 -1
- package/src/__tests__/gateway-client-managed-outbound.test.ts +8 -12
- package/src/__tests__/gateway-only-enforcement.test.ts +2 -6
- package/src/__tests__/gateway-only-guard.test.ts +4 -3
- package/src/__tests__/gemini-provider.test.ts +276 -10
- package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
- package/src/__tests__/graph-extraction-event-date.test.ts +30 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -1
- package/src/__tests__/guardian-action-followup-executor.test.ts +2 -2
- package/src/__tests__/guardian-action-followup-store.test.ts +2 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +9 -9
- package/src/__tests__/guardian-action-late-reply.test.ts +2 -1
- package/src/__tests__/guardian-action-store.test.ts +2 -1
- package/src/__tests__/guardian-action-sweep.test.ts +9 -8
- package/src/__tests__/guardian-binding-drift-heal.test.ts +3 -2
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +21 -118
- package/src/__tests__/guardian-dispatch.test.ts +14 -11
- package/src/__tests__/guardian-grant-minting.test.ts +16 -17
- package/src/__tests__/guardian-outbound-http.test.ts +71 -106
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +41 -92
- package/src/__tests__/guardian-routing-state.test.ts +15 -23
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +274 -0
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +10 -87
- package/src/__tests__/headless-browser-mode.test.ts +4 -9
- package/src/__tests__/headless-browser-navigate.test.ts +21 -20
- package/src/__tests__/heartbeat-service.test.ts +325 -25
- package/src/__tests__/helpers/call-route-handler.ts +72 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +161 -0
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/helpers/gateway-classify-mock.ts +67 -0
- package/src/__tests__/helpers/mock-logger.ts +36 -0
- package/src/__tests__/history-repair-pipeline.test.ts +1 -1
- package/src/__tests__/home-state-routes.test.ts +10 -31
- package/src/__tests__/host-bash-proxy.test.ts +46 -122
- package/src/__tests__/host-browser-e2e-cloud.test.ts +38 -498
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +35 -95
- package/src/__tests__/host-browser-proxy.test.ts +111 -185
- package/src/__tests__/host-browser-routes.test.ts +68 -153
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +35 -31
- package/src/__tests__/host-cu-proxy.test.ts +56 -111
- package/src/__tests__/host-file-proxy.test.ts +44 -98
- package/src/__tests__/host-file-read-tool.test.ts +42 -21
- package/src/__tests__/host-proxy-interface.test.ts +3 -3
- package/src/__tests__/host-shell-tool.test.ts +35 -72
- package/src/__tests__/host-transfer-pending-interactions.test.ts +144 -0
- package/src/__tests__/host-transfer-proxy.test.ts +723 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +18 -15
- package/src/__tests__/inbound-invite-redemption.test.ts +3 -2
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/injector-chain.test.ts +25 -21
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -66
- package/src/__tests__/inline-skill-load-permissions.test.ts +41 -208
- package/src/__tests__/install-skill-routing.test.ts +2 -14
- package/src/__tests__/invite-redemption-service.test.ts +2 -1
- package/src/__tests__/invite-routes-http.test.ts +80 -12
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +2 -1
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +2 -1
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +157 -0
- package/src/__tests__/list-messages-attachments.test.ts +52 -55
- package/src/__tests__/list-messages-page-latest.test.ts +283 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +16 -17
- package/src/__tests__/llm-call-pipeline.test.ts +7 -8
- package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
- package/src/__tests__/llm-catalog-parity.test.ts +90 -0
- package/src/__tests__/llm-context-normalization.test.ts +69 -4
- package/src/__tests__/llm-context-resolution.test.ts +180 -0
- package/src/__tests__/llm-context-route-provider.test.ts +39 -113
- package/src/__tests__/llm-request-log-turn-query.test.ts +2 -1
- package/src/__tests__/llm-resolver.test.ts +279 -0
- package/src/__tests__/llm-schema.test.ts +57 -1
- package/src/__tests__/llm-usage-store.test.ts +271 -5
- package/src/__tests__/log-export-routes.test.ts +89 -0
- package/src/__tests__/log-export-workspace.test.ts +28 -17
- package/src/__tests__/managed-profile-guard.test.ts +225 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
- package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
- package/src/__tests__/mcp-abort-signal.test.ts +2 -3
- package/src/__tests__/mcp-client-auth.test.ts +2 -3
- package/src/__tests__/memory-admin-recall.test.ts +221 -0
- package/src/__tests__/memory-recall-log-store.test.ts +2 -1
- package/src/__tests__/memory-retrieval-pipeline.test.ts +6 -8
- package/src/__tests__/memory-upsert-concurrency.test.ts +2 -1
- package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +209 -302
- package/src/__tests__/migration-export-http.test.ts +50 -43
- package/src/__tests__/migration-export-streaming.test.ts +18 -10
- package/src/__tests__/migration-export-to-gcs.test.ts +531 -0
- package/src/__tests__/migration-import-commit-http.test.ts +82 -37
- package/src/__tests__/migration-import-from-gcs.test.ts +574 -0
- package/src/__tests__/migration-import-from-url.test.ts +34 -27
- package/src/__tests__/migration-import-preflight-http.test.ts +108 -108
- package/src/__tests__/migration-jobs-status.test.ts +164 -0
- package/src/__tests__/migration-parity-persistence.test.ts +62 -25
- package/src/__tests__/migration-transport.test.ts +115 -23
- package/src/__tests__/migration-validate-http.test.ts +149 -159
- package/src/__tests__/migration-wizard.test.ts +133 -27
- package/src/__tests__/mock-gateway-ipc.ts +32 -62
- package/src/__tests__/model-intents.test.ts +15 -2
- package/src/__tests__/nl-approval-parser.test.ts +13 -17
- package/src/__tests__/non-member-access-request.test.ts +14 -6
- package/src/__tests__/notification-guardian-path.test.ts +15 -8
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +2 -1
- package/src/__tests__/notification-telegram-adapter.test.ts +57 -55
- package/src/__tests__/oauth-apps-routes.test.ts +76 -122
- package/src/__tests__/oauth-cli.test.ts +14 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +3 -1
- package/src/__tests__/oauth-providers-routes.test.ts +78 -101
- package/src/__tests__/oauth-store.test.ts +22 -1
- package/src/__tests__/oauth2-gateway-transport.test.ts +6 -3
- package/src/__tests__/openai-provider.test.ts +105 -6
- package/src/__tests__/openai-responses-provider.test.ts +146 -4
- package/src/__tests__/openrouter-provider-only.test.ts +22 -4
- package/src/__tests__/overflow-reduce-pipeline.test.ts +4 -9
- package/src/__tests__/permission-types.test.ts +3 -18
- package/src/__tests__/persistence-pipeline.test.ts +3 -2
- package/src/__tests__/pipeline-runner.test.ts +1 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +44 -28
- package/src/__tests__/platform.test.ts +11 -63
- package/src/__tests__/playbook-execution.test.ts +2 -1
- package/src/__tests__/playbook-tools.test.ts +2 -1
- package/src/__tests__/plugin-bootstrap.test.ts +51 -5
- package/src/__tests__/plugin-registry.test.ts +30 -0
- package/src/__tests__/plugin-route-contribution.test.ts +17 -11
- package/src/__tests__/plugin-skill-contribution.test.ts +3 -3
- package/src/__tests__/plugin-tool-contribution.test.ts +10 -4
- package/src/__tests__/plugin-types.test.ts +1 -1
- package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
- package/src/__tests__/pricing.test.ts +218 -5
- package/src/__tests__/process-message-background-slack.test.ts +331 -0
- package/src/__tests__/profiler-routes.test.ts +112 -177
- package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
- package/src/__tests__/provider-send-message-override-profile.test.ts +273 -0
- package/src/__tests__/provider-usage-tracking.test.ts +208 -0
- package/src/__tests__/proxy-approval-callback.test.ts +6 -554
- package/src/__tests__/qdrant-collection-migration.test.ts +7 -7
- package/src/__tests__/reaction-persistence.test.ts +12 -8
- package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
- package/src/__tests__/recording-handler.test.ts +64 -83
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
- package/src/__tests__/registry.test.ts +1 -0
- package/src/__tests__/relay-server.test.ts +37 -17
- package/src/__tests__/require-fresh-approval.test.ts +24 -182
- package/src/__tests__/resolve-trust-class.test.ts +2 -1
- package/src/__tests__/retry-thinking-tool-choice.test.ts +19 -7
- package/src/__tests__/retry-verbosity-normalization.test.ts +139 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +26 -6
- package/src/__tests__/runtime-events-sse-parity.test.ts +15 -17
- package/src/__tests__/runtime-events-sse.test.ts +16 -33
- package/src/__tests__/schedule-routes.test.ts +226 -129
- package/src/__tests__/schedule-store.test.ts +119 -1
- package/src/__tests__/schedule-tools.test.ts +2 -1
- package/src/__tests__/scheduler-recurrence.test.ts +2 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +2 -1
- package/src/__tests__/scheduler-wake.test.ts +356 -0
- package/src/__tests__/scoped-approval-grants.test.ts +2 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -1
- package/src/__tests__/search-skills-unified.test.ts +9 -15
- package/src/__tests__/secret-ingress-cli.test.ts +2 -5
- package/src/__tests__/secret-ingress-http.test.ts +36 -23
- package/src/__tests__/secret-onetime-send.test.ts +4 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
- package/src/__tests__/secret-response-routing.test.ts +29 -15
- package/src/__tests__/secret-routes-managed-proxy.test.ts +51 -103
- package/src/__tests__/secret-scanner.test.ts +2 -545
- package/src/__tests__/send-endpoint-busy.test.ts +36 -38
- package/src/__tests__/sequence-store.test.ts +2 -1
- package/src/__tests__/server-history-render.test.ts +2 -2
- package/src/__tests__/service-contracts-import-guard.test.ts +185 -0
- package/src/__tests__/set-permission-mode.test.ts +0 -10
- package/src/__tests__/settings-routes.test.ts +36 -69
- package/src/__tests__/shell-credential-ref.test.ts +0 -8
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
- package/src/__tests__/skill-boundary-guard.test.ts +105 -0
- package/src/__tests__/skill-load-inline-command.test.ts +2 -2
- package/src/__tests__/skill-load-inline-includes.test.ts +2 -2
- package/src/__tests__/skill-runtime-path.test.ts +64 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
- package/src/__tests__/skill-tool-factory.test.ts +97 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -32
- package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
- package/src/__tests__/slack-inbound-verification.test.ts +12 -64
- package/src/__tests__/slack-messaging-token-resolution.test.ts +1 -3
- package/src/__tests__/slack-reaction-approvals.test.ts +4 -4
- package/src/__tests__/slack-share-routes.test.ts +37 -72
- package/src/__tests__/subagent-call-site-routing.test.ts +79 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
- package/src/__tests__/subagent-fork-spawn.test.ts +20 -28
- package/src/__tests__/subagent-manager-notify.test.ts +70 -70
- package/src/__tests__/subagent-notify-parent.test.ts +83 -109
- package/src/__tests__/subagent-role-registry.test.ts +3 -3
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +52 -104
- package/src/__tests__/subagent-tools.test.ts +0 -1
- package/src/__tests__/suggestion-routes.test.ts +55 -62
- package/src/__tests__/system-prompt.test.ts +115 -13
- package/src/__tests__/task-compiler.test.ts +2 -1
- package/src/__tests__/task-management-tools.test.ts +2 -1
- package/src/__tests__/task-memory-cleanup.test.ts +2 -1
- package/src/__tests__/task-scheduler.test.ts +2 -1
- package/src/__tests__/telegram-config.test.ts +0 -1
- package/src/__tests__/terminal-tools.test.ts +3 -401
- package/src/__tests__/test-preload.ts +0 -11
- package/src/__tests__/thread-backfill.test.ts +947 -32
- package/src/__tests__/token-estimate-pipeline.test.ts +68 -15
- package/src/__tests__/tool-approval-handler.test.ts +21 -63
- package/src/__tests__/tool-audit-listener.test.ts +3 -3
- package/src/__tests__/tool-domain-event-publisher.test.ts +3 -39
- package/src/__tests__/tool-error-pipeline.test.ts +6 -6
- package/src/__tests__/tool-execute-pipeline.test.ts +6 -14
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +69 -16
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +31 -62
- package/src/__tests__/tool-executor.test.ts +336 -1654
- package/src/__tests__/tool-grant-request-escalation.test.ts +90 -311
- package/src/__tests__/tool-metrics-listener.test.ts +0 -35
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +1 -1
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-trace-listener.test.ts +0 -17
- package/src/__tests__/transfer-progress-screen.test.ts +63 -26
- package/src/__tests__/trust-context-guards.test.ts +1 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +7 -15
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +178 -354
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +5 -151
- package/src/__tests__/trusted-contact-multichannel.test.ts +5 -6
- package/src/__tests__/trusted-contact-verification.test.ts +3 -2
- package/src/__tests__/tts-catalog-parity.test.ts +16 -5
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -1
- package/src/__tests__/twilio-routes.test.ts +25 -66
- package/src/__tests__/usage-attribution.test.ts +247 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -7
- package/src/__tests__/usage-cli.test.ts +143 -0
- package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
- package/src/__tests__/usage-routes.test.ts +223 -90
- package/src/__tests__/user-plugin-loader.test.ts +54 -12
- package/src/__tests__/validation-results-screen.test.ts +39 -16
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +51 -139
- package/src/__tests__/verification-control-plane-policy.test.ts +97 -19
- package/src/__tests__/voice-ingress-preflight.test.ts +5 -5
- package/src/__tests__/voice-invite-redemption.test.ts +2 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +3 -3
- package/src/__tests__/voice-session-bridge.test.ts +285 -106
- package/src/__tests__/volume-security-guard.test.ts +0 -2
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +3 -1
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +2 -1
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +1 -1
- package/src/__tests__/workspace-migration-052-seed-default-inference-profiles.test.ts +260 -0
- package/src/__tests__/workspace-migration-053-release-notes-acp-codex.test.ts +225 -0
- package/src/__tests__/workspace-migration-054-seed-recall-callsite.test.ts +235 -0
- package/src/__tests__/workspace-migration-055-release-notes-agentic-recall.test.ts +128 -0
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +232 -0
- package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
- package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
- package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
- package/src/__tests__/workspace-migration-acp-sessions-ui.test.ts +144 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +1 -1
- package/src/__tests__/workspace-migration-memory-v2-init.test.ts +252 -0
- package/src/acp/__tests__/client-handler.test.ts +64 -0
- package/src/acp/__tests__/helpers/acp-config-stub.ts +62 -0
- package/src/acp/__tests__/helpers/which-stub.ts +45 -0
- package/src/acp/__tests__/session-manager-persistence.test.ts +366 -0
- package/src/acp/__tests__/session-manager-startup.test.ts +159 -0
- package/src/acp/__tests__/session-manager.test.ts +83 -0
- package/src/acp/client-handler.ts +23 -139
- package/src/acp/index.ts +0 -15
- package/src/acp/resolve-agent.test.ts +291 -0
- package/src/acp/resolve-agent.ts +176 -0
- package/src/acp/session-manager.ts +193 -31
- package/src/acp/types.ts +2 -50
- package/src/agent/loop.ts +53 -15
- package/src/agent/message-types.ts +0 -2
- package/src/approvals/AGENTS.md +5 -1
- package/src/approvals/__tests__/guardian-feed-event.test.ts +11 -12
- package/src/approvals/approval-primitive.ts +3 -20
- package/src/approvals/guardian-decision-primitive.ts +37 -68
- package/src/approvals/guardian-request-resolvers.ts +38 -104
- package/src/avatar/character-components.ts +6 -6
- package/src/{config/bundled-skills/settings/tools → avatar}/identity-avatar.ts +1 -1
- package/src/backup/__tests__/backup-worker.test.ts +36 -10
- package/src/backup/__tests__/paths.test.ts +5 -4
- package/src/backup/__tests__/restore.test.ts +45 -28
- package/src/backup/backup-worker.ts +37 -12
- package/src/backup/paths.ts +11 -24
- package/src/backup/restore.ts +7 -11
- package/src/browser/__tests__/operations.test.ts +0 -35
- package/src/browser/operations.ts +1 -47
- package/src/browser-session/events.ts +0 -9
- package/src/bundler/package-resolver.ts +2 -6
- package/src/calls/active-call-lease.ts +1 -1
- package/src/calls/call-constants.ts +1 -1
- package/src/calls/call-controller.ts +1 -5
- package/src/calls/call-domain.ts +14 -14
- package/src/calls/call-pointer-messages.ts +4 -9
- package/src/calls/call-store.ts +2 -34
- package/src/calls/guardian-action-sweep.ts +9 -25
- package/src/calls/guardian-dispatch.ts +1 -20
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/media-stream-audio-transcode.ts +2 -41
- package/src/calls/media-stream-server.ts +2 -3
- package/src/calls/media-stream-stt-session.ts +1 -3
- package/src/calls/relay-access-wait.ts +5 -8
- package/src/calls/relay-server.ts +15 -42
- package/src/calls/relay-setup-router.ts +2 -2
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/twilio-rest.ts +1 -39
- package/src/calls/twilio-routes.ts +160 -78
- package/src/calls/voice-control-protocol.ts +10 -10
- package/src/calls/voice-ingress-preflight.ts +2 -2
- package/src/calls/voice-session-bridge.ts +141 -77
- package/src/channels/__tests__/types.test.ts +25 -3
- package/src/channels/permission-profiles.ts +2 -72
- package/src/channels/types.ts +25 -44
- package/src/cli/AGENTS.md +1 -0
- package/src/cli/__tests__/notifications.test.ts +12 -10
- package/src/cli/commands/__tests__/attachment.test.ts +14 -8
- package/src/cli/commands/__tests__/backup.test.ts +3 -14
- package/src/cli/commands/__tests__/browser.test.ts +36 -31
- package/src/cli/commands/__tests__/cache.test.ts +175 -23
- package/src/cli/commands/__tests__/memory-v2.test.ts +382 -0
- package/src/cli/commands/__tests__/task.test.ts +36 -35
- package/src/cli/commands/__tests__/trust.test.ts +236 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +14 -14
- package/src/cli/commands/__tests__/ui.test.ts +17 -17
- package/src/cli/commands/__tests__/watchers.test.ts +29 -29
- package/src/cli/commands/__tests__/webhooks.test.ts +544 -0
- package/src/cli/commands/attachment.ts +12 -8
- package/src/cli/commands/auth.ts +1 -1
- package/src/cli/commands/avatar.ts +192 -9
- package/src/cli/commands/backup.ts +18 -48
- package/src/cli/commands/browser.ts +52 -4
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +157 -84
- package/src/cli/commands/channel-verification-sessions.ts +6 -6
- package/src/cli/commands/clients.ts +74 -17
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +241 -86
- package/src/cli/commands/conversations-defer.ts +364 -0
- package/src/cli/commands/conversations-import.ts +2 -3
- package/src/cli/commands/conversations.ts +63 -53
- package/src/cli/commands/credential-execution.ts +1 -1
- package/src/cli/commands/credentials.ts +139 -5
- package/src/cli/commands/default-action.ts +1 -1
- package/src/cli/commands/domain.ts +2 -2
- package/src/cli/commands/email.ts +7 -7
- package/src/cli/commands/image-generation.ts +1 -1
- package/src/cli/commands/keys.ts +5 -2
- package/src/cli/commands/mcp.ts +1 -1
- package/src/cli/commands/memory-v2.ts +315 -0
- package/src/cli/commands/memory.ts +8 -8
- package/src/cli/commands/notifications.ts +21 -20
- package/src/cli/commands/oauth/__tests__/connect.test.ts +23 -5
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/mode.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/token.test.ts +1 -1
- package/src/cli/commands/oauth/connect.ts +2 -2
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -6
- package/src/cli/commands/platform/__tests__/connect.test.ts +23 -11
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +22 -10
- package/src/cli/commands/platform/__tests__/status.test.ts +22 -10
- package/src/cli/commands/platform/connect.ts +3 -3
- package/src/cli/commands/platform/disconnect.ts +4 -6
- package/src/cli/commands/platform/index.ts +12 -10
- package/src/cli/commands/routes.ts +7 -1
- package/src/cli/commands/sequence.ts +7 -7
- package/src/cli/commands/skills.ts +264 -116
- package/src/cli/commands/task.ts +12 -10
- package/src/cli/commands/trust.ts +105 -167
- package/src/cli/commands/ui.ts +3 -3
- package/src/cli/commands/usage.ts +29 -15
- package/src/cli/commands/watchers.ts +8 -8
- package/src/cli/commands/webhooks.ts +270 -0
- package/src/cli/lib/daemon-avatar-client.ts +37 -0
- package/src/cli/lib/daemon-credential-client.ts +41 -189
- package/src/cli/lib/ipc-params.ts +22 -0
- package/src/cli/program.ts +6 -0
- package/src/cli.ts +1 -82
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/acp-defaults.test.ts +57 -0
- package/src/config/acp-defaults.ts +40 -0
- package/src/config/acp-schema.ts +1 -1
- package/src/config/assistant-feature-flags.ts +18 -142
- package/src/config/bundled-skills/acp/SKILL.md +44 -16
- package/src/config/bundled-skills/acp/TOOLS.json +45 -1
- package/src/config/bundled-skills/acp/tools/acp-list-agents.ts +12 -0
- package/src/config/bundled-skills/acp/tools/acp-steer.ts +12 -0
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +14 -14
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -4
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +11 -6
- package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +6 -6
- package/src/config/bundled-skills/media-processing/services/reduce.ts +0 -13
- package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
- package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +1 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -1
- package/src/config/bundled-skills/settings/SKILL.md +2 -17
- package/src/config/bundled-skills/settings/TOOLS.json +0 -56
- package/src/config/bundled-skills/subagent/SKILL.md +2 -0
- package/src/config/bundled-tool-registry.ts +4 -6
- package/src/config/env-registry.ts +12 -2
- package/src/config/env.ts +10 -22
- package/src/config/feature-flag-registry.json +38 -46
- package/src/config/llm-callsite-catalog.ts +12 -0
- package/src/config/llm-context-resolution.ts +80 -0
- package/src/config/llm-resolver.ts +90 -36
- package/src/config/loader.ts +9 -12
- package/src/config/schema.ts +5 -228
- package/src/config/schemas/__tests__/filing.test.ts +58 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +187 -0
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -5
- package/src/config/schemas/filing.ts +12 -0
- package/src/config/schemas/host-browser.ts +2 -2
- package/src/config/schemas/inference.ts +1 -3
- package/src/config/schemas/ingress.ts +2 -2
- package/src/config/schemas/llm.ts +82 -12
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-storage.ts +1 -1
- package/src/config/schemas/memory-v2.ts +185 -0
- package/src/config/schemas/memory.ts +2 -0
- package/src/config/schemas/security.ts +1 -102
- package/src/config/schemas/services.ts +52 -13
- package/src/config/schemas/skills.ts +5 -5
- package/src/config/schemas/tts.ts +1 -1
- package/src/config/seed-inference-profiles.ts +117 -0
- package/src/config/skills.ts +1 -91
- package/src/config/types.ts +3 -47
- package/src/contacts/contact-store.ts +2 -19
- package/src/contacts/contacts-write.ts +1 -143
- package/src/contacts/types.ts +8 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/context/tool-result-truncation.ts +1 -1
- package/src/context/window-manager.ts +45 -6
- package/src/credential-execution/approval-bridge.ts +7 -69
- package/src/credential-execution/client.ts +17 -422
- package/src/credential-execution/feature-gates.ts +1 -2
- package/src/credential-execution/managed-catalog.ts +1 -1
- package/src/credential-execution/process-manager.ts +34 -10
- package/src/credential-health/credential-health-service.ts +22 -17
- package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -13
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +76 -83
- package/src/daemon/__tests__/daemon-skill-host.test.ts +265 -0
- package/src/daemon/__tests__/meet-host-supervisor.test.ts +587 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +463 -0
- package/src/daemon/approval-generators.ts +2 -14
- package/src/daemon/classifier.ts +0 -106
- package/src/daemon/config-watcher.ts +14 -54
- package/src/daemon/connection-policy.ts +1 -40
- package/src/daemon/conversation-agent-loop-handlers.ts +89 -9
- package/src/daemon/conversation-agent-loop.ts +440 -88
- package/src/daemon/conversation-attachments.ts +5 -81
- package/src/daemon/conversation-error.ts +9 -5
- package/src/daemon/conversation-history.ts +9 -9
- package/src/daemon/conversation-launch.ts +21 -136
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-messaging.ts +2 -1
- package/src/daemon/conversation-notifiers.ts +1 -1
- package/src/daemon/conversation-process.ts +90 -174
- package/src/daemon/conversation-runtime-assembly.ts +245 -164
- package/src/daemon/conversation-slash.ts +50 -164
- package/src/daemon/conversation-store.ts +344 -0
- package/src/daemon/conversation-surfaces.ts +27 -32
- package/src/daemon/conversation-tool-setup.ts +23 -202
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +129 -381
- package/src/daemon/daemon-control.ts +4 -72
- package/src/daemon/daemon-skill-host.ts +259 -0
- package/src/daemon/dictation-profile-store.ts +2 -26
- package/src/daemon/external-plugins-bootstrap.ts +67 -13
- package/src/daemon/first-greeting.ts +44 -156
- package/src/daemon/handlers/config-channels.ts +14 -14
- package/src/daemon/handlers/config-embeddings.ts +1 -1
- package/src/daemon/handlers/config-ingress.ts +27 -166
- package/src/daemon/handlers/config-model.test.ts +17 -0
- package/src/daemon/handlers/config-model.ts +8 -53
- package/src/daemon/handlers/config-telegram.ts +6 -53
- package/src/daemon/handlers/config-voice.ts +0 -42
- package/src/daemon/handlers/conversations.ts +32 -345
- package/src/daemon/handlers/recording.ts +27 -159
- package/src/daemon/handlers/shared.ts +50 -99
- package/src/daemon/handlers/skills.ts +55 -114
- package/src/daemon/host-bash-proxy.ts +67 -45
- package/src/daemon/host-browser-proxy.ts +65 -27
- package/src/daemon/host-cu-proxy.ts +40 -39
- package/src/daemon/host-file-proxy.ts +58 -37
- package/src/daemon/host-transfer-proxy.ts +538 -0
- package/src/daemon/lifecycle.ts +71 -272
- package/src/daemon/meet-host-startup.ts +51 -0
- package/src/daemon/meet-host-supervisor.ts +781 -0
- package/src/daemon/meet-manifest-loader.ts +410 -0
- package/src/daemon/memory-v2-startup.ts +35 -0
- package/src/daemon/message-protocol.ts +4 -7
- package/src/daemon/message-types/acp.ts +1 -0
- package/src/daemon/message-types/conversations.ts +23 -2
- package/src/daemon/message-types/host-bash.ts +1 -0
- package/src/daemon/message-types/host-cu.ts +1 -0
- package/src/daemon/message-types/host-file.ts +1 -0
- package/src/daemon/message-types/host-transfer.ts +42 -0
- package/src/daemon/message-types/integrations.ts +6 -0
- package/src/daemon/message-types/messages.ts +24 -23
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/settings.ts +0 -6
- package/src/daemon/message-types/shared.ts +5 -2
- package/src/daemon/message-types/subagents.ts +2 -1
- package/src/daemon/message-types/workspace.ts +1 -3
- package/src/daemon/pkb-reminder-builder.test.ts +13 -12
- package/src/daemon/pkb-reminder-builder.ts +8 -16
- package/src/daemon/process-message.ts +479 -0
- package/src/daemon/providers-setup.ts +14 -6
- package/src/daemon/server.ts +58 -1702
- package/src/daemon/shutdown-handlers.ts +3 -3
- package/src/daemon/startup-error.ts +1 -1
- package/src/daemon/tool-side-effects.ts +125 -107
- package/src/daemon/trust-context.ts +45 -0
- package/src/daemon/wake-target-adapter.ts +218 -0
- package/src/email/feature-gate.ts +1 -1
- package/src/events/domain-events.ts +1 -16
- package/src/events/tool-audit-listener.ts +5 -9
- package/src/events/tool-domain-event-publisher.ts +0 -10
- package/src/events/tool-metrics-listener.ts +1 -21
- package/src/events/tool-trace-listener.ts +0 -14
- package/src/filing/filing-service.ts +207 -55
- package/src/followups/followup-store.ts +3 -71
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +93 -21
- package/src/heartbeat/heartbeat-service.ts +55 -16
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/phase5-exit-criteria.test.ts +18 -1
- package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
- package/src/home/__tests__/rollup-producer.test.ts +67 -2
- package/src/home/assistant-feed-authoring.ts +8 -1
- package/src/home/feed-types.ts +1 -1
- package/src/home/feed-writer.ts +1 -2
- package/src/home/relationship-state-writer.ts +17 -4
- package/src/home/rewrite-feed-title.ts +58 -0
- package/src/home/rollup-producer.ts +16 -3
- package/src/inbound/platform-callback-registration.ts +1 -17
- package/src/ipc/__tests__/attachment-ipc.test.ts +128 -66
- package/src/ipc/__tests__/browser-ipc.test.ts +72 -58
- package/src/ipc/__tests__/cache-ipc.test.ts +52 -107
- package/src/ipc/__tests__/cli-ipc.test.ts +9 -6
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +253 -0
- package/src/ipc/__tests__/skill-server.test.ts +182 -0
- package/src/ipc/__tests__/socket-path.test.ts +69 -23
- package/src/ipc/__tests__/ui-request-route.test.ts +241 -216
- package/src/ipc/__tests__/watcher-ipc.test.ts +33 -33
- package/src/ipc/assistant-server.ts +443 -0
- package/src/ipc/cli-client.ts +3 -3
- package/src/ipc/gateway-client.test.ts +131 -0
- package/src/ipc/gateway-client.ts +98 -123
- package/src/ipc/ipc-framing.ts +281 -0
- package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +171 -0
- package/src/ipc/routes/db-proxy.ts +73 -0
- package/src/ipc/routes/route-adapter.ts +32 -0
- package/src/ipc/routes/trust-rules.test.ts +123 -0
- package/src/ipc/skill-ipc-types.ts +54 -0
- package/src/ipc/skill-routes/__tests__/config.test.ts +146 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +388 -0
- package/src/ipc/skill-routes/__tests__/identity.test.ts +62 -0
- package/src/ipc/skill-routes/__tests__/log.test.ts +133 -0
- package/src/ipc/skill-routes/__tests__/memory.test.ts +178 -0
- package/src/ipc/skill-routes/__tests__/platform.test.ts +111 -0
- package/src/ipc/skill-routes/__tests__/providers.test.ts +265 -0
- package/src/ipc/skill-routes/__tests__/registries.test.ts +361 -0
- package/src/ipc/skill-routes/config.ts +47 -0
- package/src/ipc/skill-routes/events.ts +120 -0
- package/src/ipc/skill-routes/identity.ts +21 -0
- package/src/ipc/skill-routes/index.ts +37 -0
- package/src/ipc/skill-routes/log.ts +40 -0
- package/src/ipc/skill-routes/memory.ts +76 -0
- package/src/ipc/skill-routes/platform.ts +39 -0
- package/src/ipc/skill-routes/providers.ts +163 -0
- package/src/ipc/skill-routes/registries.ts +393 -0
- package/src/ipc/skill-server.ts +738 -0
- package/src/ipc/skill-socket-path.ts +20 -0
- package/src/ipc/socket-cleanup.ts +92 -0
- package/src/ipc/socket-path.ts +63 -32
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +374 -0
- package/src/live-voice/__tests__/live-voice-archive.test.ts +525 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +473 -0
- package/src/live-voice/__tests__/live-voice-integration.test.ts +359 -0
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +179 -0
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +349 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +244 -0
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +337 -0
- package/src/live-voice/__tests__/live-voice-tts.test.ts +337 -0
- package/src/live-voice/__tests__/protocol.test.ts +295 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +413 -0
- package/src/live-voice/live-voice-archive.ts +758 -0
- package/src/live-voice/live-voice-metrics.ts +472 -0
- package/src/live-voice/live-voice-session-manager.ts +222 -0
- package/src/live-voice/live-voice-session.ts +1144 -0
- package/src/live-voice/live-voice-tts.ts +260 -0
- package/src/live-voice/protocol.ts +515 -0
- package/src/mcp/client.ts +2 -2
- package/src/mcp/manager.ts +0 -5
- package/src/media/types.ts +4 -4
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +4 -28
- package/src/memory/__tests__/auto-analysis-guard.test.ts +2 -2
- package/src/memory/__tests__/conversation-analyze-job.test.ts +7 -62
- package/src/memory/__tests__/conversation-group-migration.test.ts +2 -2
- package/src/memory/__tests__/find-analysis-conversation.test.ts +2 -1
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +235 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
- package/src/memory/admin.ts +65 -7
- package/src/memory/app-git-service.ts +0 -46
- package/src/memory/app-store.ts +154 -0
- package/src/memory/attachments-store.ts +20 -16
- package/src/memory/auto-analysis-enqueue.ts +2 -17
- package/src/memory/canonical-guardian-store.ts +2 -1
- package/src/memory/channel-verification-sessions.ts +1 -1
- package/src/memory/checkpoints.ts +1 -1
- package/src/memory/context-search/agent-protocol.ts +424 -0
- package/src/memory/context-search/agent-runner.ts +1295 -0
- package/src/memory/context-search/format.ts +160 -0
- package/src/memory/context-search/limits.ts +106 -0
- package/src/memory/context-search/search.ts +387 -0
- package/src/memory/context-search/sources/conversations.ts +278 -0
- package/src/memory/context-search/sources/memory-v2.ts +578 -0
- package/src/memory/context-search/sources/memory.ts +95 -0
- package/src/memory/context-search/sources/pkb.ts +477 -0
- package/src/memory/context-search/sources/workspace.ts +1256 -0
- package/src/memory/context-search/types.ts +49 -0
- package/src/memory/conversation-analyze-job.ts +3 -24
- package/src/memory/conversation-attention-store.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +1 -1
- package/src/memory/conversation-crud.ts +86 -119
- package/src/memory/conversation-directories.ts +1 -11
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-display-order-migration.ts +11 -2
- package/src/memory/conversation-group-migration.ts +20 -4
- package/src/memory/conversation-key-store.ts +3 -4
- package/src/memory/conversation-queries.ts +13 -26
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/conversation-starter-validation.ts +88 -0
- package/src/memory/conversation-starters-cadence.ts +1 -1
- package/src/memory/conversation-title-service.ts +2 -1
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +28 -4
- package/src/memory/db-maintenance.ts +1 -1
- package/src/memory/delivery-channels.ts +1 -14
- package/src/memory/delivery-crud.ts +2 -32
- package/src/memory/delivery-status.ts +1 -1
- package/src/memory/embedding-backend.ts +3 -21
- package/src/memory/embedding-gemini.test.ts +4 -4
- package/src/memory/embedding-gemini.ts +0 -2
- package/src/memory/embedding-local.ts +6 -6
- package/src/memory/embedding-ollama.ts +6 -6
- package/src/memory/embedding-openai.ts +6 -6
- package/src/memory/embedding-types.ts +21 -0
- package/src/memory/external-conversation-store.ts +1 -1
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +408 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +225 -0
- package/src/memory/graph/bootstrap.test.ts +2 -7
- package/src/memory/graph/bootstrap.ts +2 -1
- package/src/memory/graph/capability-seed.ts +3 -3
- package/src/memory/graph/compaction.ts +1 -1
- package/src/memory/graph/consolidation.ts +13 -10
- package/src/memory/graph/conversation-graph-memory.ts +184 -12
- package/src/memory/graph/decay.ts +1 -1
- package/src/memory/graph/extraction.ts +53 -21
- package/src/memory/graph/graph-memory-state-store.ts +1 -1
- package/src/memory/graph/graph-search.test.ts +94 -2
- package/src/memory/graph/graph-search.ts +22 -7
- package/src/memory/graph/image-ref-utils.ts +1 -1
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/graph/retriever.test.ts +158 -4
- package/src/memory/graph/retriever.ts +17 -5
- package/src/memory/graph/store.test.ts +2 -1
- package/src/memory/graph/store.ts +1 -1
- package/src/memory/graph/tool-handlers.ts +73 -247
- package/src/memory/graph/tools.ts +35 -53
- package/src/memory/group-crud.ts +1 -2
- package/src/memory/guardian-action-store.ts +2 -84
- package/src/memory/guardian-approvals.ts +1 -49
- package/src/memory/guardian-rate-limits.ts +1 -1
- package/src/memory/indexer.ts +44 -32
- package/src/memory/invite-store.ts +1 -1
- package/src/memory/job-handlers/backfill.ts +1 -1
- package/src/memory/job-handlers/cleanup.ts +2 -1
- package/src/memory/job-handlers/conversation-starters.ts +54 -63
- package/src/memory/job-handlers/embedding.test.ts +2 -1
- package/src/memory/job-handlers/embedding.ts +1 -1
- package/src/memory/job-handlers/index-maintenance.ts +1 -1
- package/src/memory/job-handlers/summarization.ts +3 -3
- package/src/memory/job-utils.ts +3 -9
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +362 -0
- package/src/memory/jobs/embed-concept-page.ts +210 -0
- package/src/memory/jobs/embed-pkb-file.test.ts +2 -1
- package/src/memory/jobs-store.ts +9 -2
- package/src/memory/jobs-worker.ts +56 -17
- package/src/memory/lifecycle-events-store.ts +1 -1
- package/src/memory/llm-request-log-store.ts +1 -42
- package/src/memory/llm-usage-store.ts +130 -44
- package/src/memory/media-store.ts +1 -1
- package/src/memory/memory-recall-log-store.ts +1 -1
- package/src/memory/memory-v2-activation-log-store.ts +115 -0
- package/src/memory/migrations/038-actor-token-records.ts +3 -0
- package/src/memory/migrations/039-actor-refresh-token-records.ts +3 -0
- package/src/memory/migrations/226-schedule-wake-conversation-id.ts +11 -0
- package/src/memory/migrations/227-add-conversation-inference-profile.ts +18 -0
- package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +27 -0
- package/src/memory/migrations/229-delete-private-conversations.test.ts +1087 -0
- package/src/memory/migrations/229-delete-private-conversations.ts +210 -0
- package/src/memory/migrations/230-acp-session-history.ts +41 -0
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +128 -0
- package/src/memory/migrations/232-activation-state.ts +38 -0
- package/src/memory/migrations/233-document-conversations.ts +54 -0
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
- package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
- package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
- package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
- package/src/memory/migrations/index.ts +24 -0
- package/src/memory/migrations/registry.ts +31 -0
- package/src/memory/pkb/pkb-index.test.ts +4 -5
- package/src/memory/pkb/pkb-reconcile.test.ts +4 -5
- package/src/memory/pkb/pkb-search.test.ts +83 -3
- package/src/memory/pkb/pkb-search.ts +27 -14
- package/src/memory/published-pages-store.ts +1 -1
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/acp.ts +30 -0
- package/src/memory/schema/conversations.ts +8 -1
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/infrastructure.ts +26 -32
- package/src/memory/schema/memory-graph.ts +36 -14
- package/src/memory/scoped-approval-grants.ts +2 -1
- package/src/memory/search/semantic.ts +7 -18
- package/src/memory/shared-app-links-store.ts +2 -1
- package/src/memory/tool-usage-store.ts +3 -1
- package/src/memory/trace-event-store.ts +2 -1
- package/src/memory/turn-events-store.ts +1 -1
- package/src/memory/usage-buckets.ts +40 -1
- package/src/memory/usage-grouped-buckets.ts +127 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +202 -0
- package/src/memory/v2/__tests__/activation.test.ts +1155 -0
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +483 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +412 -0
- package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
- package/src/memory/v2/__tests__/injection.test.ts +1161 -0
- package/src/memory/v2/__tests__/migration.test.ts +840 -0
- package/src/memory/v2/__tests__/page-store.test.ts +517 -0
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +438 -0
- package/src/memory/v2/__tests__/sim.test.ts +549 -0
- package/src/memory/v2/__tests__/skill-content.test.ts +85 -0
- package/src/memory/v2/__tests__/skill-qdrant.test.ts +657 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +463 -0
- package/src/memory/v2/__tests__/static-context.test.ts +153 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +441 -0
- package/src/memory/v2/activation-store.ts +109 -0
- package/src/memory/v2/activation.ts +561 -0
- package/src/memory/v2/backfill-jobs.ts +357 -0
- package/src/memory/v2/consolidation-job.ts +306 -0
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +431 -0
- package/src/memory/v2/migration.ts +647 -0
- package/src/memory/v2/now-text.ts +37 -0
- package/src/memory/v2/page-store.ts +382 -0
- package/src/memory/v2/prompts/consolidation.ts +261 -0
- package/src/memory/v2/prompts/sweep.ts +56 -0
- package/src/memory/v2/qdrant.ts +342 -0
- package/src/memory/v2/sim.ts +206 -0
- package/src/memory/v2/skill-content.ts +42 -0
- package/src/memory/v2/skill-qdrant.ts +395 -0
- package/src/memory/v2/skill-store.ts +176 -0
- package/src/memory/v2/static-context.ts +62 -0
- package/src/memory/v2/sweep-job.ts +298 -0
- package/src/memory/v2/types.ts +106 -0
- package/src/memory/validation.ts +0 -11
- package/src/messaging/draft-store.ts +0 -6
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/client.ts +1 -121
- package/src/messaging/providers/index.ts +262 -0
- package/src/messaging/providers/outlook/client.ts +0 -73
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
- package/src/messaging/providers/slack/adapter.ts +122 -21
- package/src/messaging/providers/slack/api.ts +242 -0
- package/src/messaging/providers/slack/backfill.test.ts +95 -6
- package/src/messaging/providers/slack/backfill.ts +89 -11
- package/src/messaging/providers/slack/client.ts +10 -124
- package/src/messaging/providers/slack/message-metadata.ts +13 -3
- package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
- package/src/messaging/providers/slack/render-transcript.ts +126 -25
- package/src/messaging/providers/slack/send.ts +383 -0
- package/src/messaging/providers/slack/types.ts +1 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +4 -42
- package/src/messaging/providers/telegram-bot/api.ts +253 -0
- package/src/messaging/providers/telegram-bot/client.ts +17 -58
- package/src/messaging/providers/telegram-bot/send.ts +232 -0
- package/src/messaging/providers/whatsapp/adapter.ts +4 -36
- package/src/messaging/providers/whatsapp/api.ts +319 -0
- package/src/messaging/providers/whatsapp/client.ts +4 -48
- package/src/messaging/providers/whatsapp/send.ts +209 -0
- package/src/notifications/adapters/slack.ts +5 -23
- package/src/notifications/adapters/telegram.ts +8 -29
- package/src/notifications/conversation-candidates.ts +1 -1
- package/src/notifications/conversation-seed-composer.ts +12 -6
- package/src/notifications/copy-composer.ts +1 -1
- package/src/notifications/decision-engine.ts +1 -1
- package/src/notifications/decisions-store.ts +1 -1
- package/src/notifications/deliveries-store.ts +2 -1
- package/src/notifications/deterministic-checks.ts +1 -1
- package/src/notifications/events-store.ts +1 -13
- package/src/notifications/preferences-store.ts +1 -1
- package/src/notifications/signal.ts +0 -9
- package/src/oauth/connection-resolver.test.ts +8 -0
- package/src/oauth/connection-resolver.ts +6 -5
- package/src/oauth/credential-token-resolver.ts +97 -0
- package/src/oauth/manual-token-connection.ts +30 -34
- package/src/oauth/oauth-store.ts +8 -5
- package/src/outbound-proxy/certs.ts +0 -7
- package/src/outbound-proxy/config.ts +0 -74
- package/src/outbound-proxy/health.ts +0 -44
- package/src/outbound-proxy/index.ts +0 -23
- package/src/permissions/approval-policy.test.ts +149 -132
- package/src/permissions/approval-policy.ts +65 -91
- package/src/permissions/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.test.ts +632 -0
- package/src/permissions/checker.ts +270 -460
- package/src/permissions/gateway-threshold-reader.ts +31 -47
- package/src/permissions/ipc-risk-types.ts +95 -0
- package/src/permissions/prompter.ts +13 -11
- package/src/permissions/risk-types.ts +24 -210
- package/src/permissions/secret-prompter.ts +21 -48
- package/src/permissions/types.ts +49 -46
- package/src/permissions/workspace-policy.ts +1 -8
- package/src/platform/sync-identity.ts +0 -8
- package/src/playbooks/playbook-compiler.ts +1 -1
- package/src/plugins/defaults/index.ts +1 -1
- package/src/plugins/defaults/injectors.ts +87 -23
- package/src/plugins/defaults/llm-call.ts +6 -9
- package/src/plugins/defaults/memory-retrieval.ts +1 -6
- package/src/plugins/defaults/overflow-reduce.ts +12 -7
- package/src/plugins/defaults/token-estimate.ts +2 -3
- package/src/plugins/registry.ts +61 -1
- package/src/plugins/types.ts +14 -7
- package/src/plugins/user-loader.ts +36 -10
- package/src/prompts/persona-resolver.ts +2 -4
- package/src/prompts/system-prompt.ts +34 -31
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/templates/SOUL.md +3 -1
- package/src/prompts/update-bulletin-job.ts +2 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +0 -21
- package/src/providers/__tests__/retry-callsite.test.ts +141 -7
- package/src/providers/anthropic/client.ts +143 -52
- package/src/providers/call-site-routing.ts +49 -6
- package/src/providers/fireworks/client.ts +3 -0
- package/src/providers/gemini/client.ts +113 -23
- package/src/providers/managed-proxy/context.ts +0 -17
- package/src/providers/model-catalog.ts +188 -27
- package/src/providers/model-intents.ts +7 -8
- package/src/providers/openai/chat-completions-provider.ts +43 -7
- package/src/providers/openai/responses-provider.ts +46 -5
- package/src/providers/openrouter/client.ts +4 -5
- package/src/providers/provider-env-vars.ts +4 -12
- package/src/providers/provider-send-message.ts +61 -13
- package/src/providers/ratelimit.ts +7 -2
- package/src/providers/registry.ts +15 -10
- package/src/providers/retry.ts +148 -31
- package/src/providers/speech-to-text/openai-whisper-stream.ts +1 -1
- package/src/providers/speech-to-text/openai-whisper.ts +3 -6
- package/src/providers/speech-to-text/provider-catalog.ts +75 -0
- package/src/providers/speech-to-text/xai.ts +5 -5
- package/src/providers/thinking-config.ts +34 -0
- package/src/providers/types.ts +35 -10
- package/src/providers/usage-tracking.ts +96 -0
- package/src/runtime/AGENTS.md +16 -11
- package/src/runtime/__tests__/agent-wake.test.ts +122 -9
- package/src/runtime/__tests__/interactive-ui.test.ts +157 -246
- package/src/runtime/access-request-helper.ts +9 -20
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/agent-wake.ts +211 -68
- package/src/runtime/approval-conversation-turn.ts +2 -15
- package/src/runtime/approval-message-composer.ts +11 -60
- package/src/runtime/assistant-event-hub.ts +541 -45
- package/src/runtime/assistant-event.ts +16 -69
- package/src/runtime/auth/__tests__/guard-tests.test.ts +6 -30
- package/src/runtime/auth/__tests__/middleware.test.ts +10 -10
- package/src/runtime/auth/__tests__/route-policy.test.ts +0 -8
- package/src/runtime/auth/middleware.ts +5 -5
- package/src/runtime/auth/route-policy.ts +205 -12
- package/src/runtime/auth/token-service.ts +1 -111
- package/src/runtime/capability-tokens.ts +89 -313
- package/src/runtime/channel-approval-types.ts +1 -6
- package/src/runtime/channel-approvals.ts +13 -81
- package/src/runtime/channel-readiness-service.ts +2 -2
- package/src/runtime/channel-reply-delivery.ts +2 -8
- package/src/runtime/channel-retry-sweep.ts +20 -17
- package/src/runtime/channel-verification-service.ts +3 -5
- package/src/runtime/confirmation-request-guardian-bridge.ts +2 -7
- package/src/runtime/gateway-client.ts +37 -378
- package/src/runtime/guardian-action-grant-minter.ts +2 -3
- package/src/runtime/guardian-action-message-composer.ts +11 -52
- package/src/runtime/guardian-action-service.ts +19 -7
- package/src/runtime/guardian-decision-types.ts +4 -65
- package/src/runtime/guardian-reply-router.ts +10 -19
- package/src/runtime/guardian-vellum-migration.ts +5 -64
- package/src/runtime/http-errors.ts +1 -32
- package/src/runtime/http-router.ts +54 -8
- package/src/runtime/http-server.ts +362 -1187
- package/src/runtime/http-types.ts +20 -98
- package/src/runtime/interactive-ui-types.ts +145 -0
- package/src/runtime/interactive-ui.ts +37 -196
- package/src/runtime/invite-redemption-service.ts +1 -1
- package/src/runtime/invite-redemption-templates.ts +1 -1
- package/src/runtime/local-actor-identity.ts +13 -43
- package/src/runtime/message-composer-types.ts +134 -0
- package/src/runtime/middleware/auth.ts +0 -20
- package/src/runtime/middleware/rate-limiter.ts +1 -1
- package/src/runtime/middleware/request-logger.ts +5 -2
- package/src/runtime/migrations/__tests__/job-registry.test.ts +346 -0
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +18 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
- package/src/runtime/migrations/job-registry.ts +281 -0
- package/src/runtime/migrations/migration-transport.ts +46 -13
- package/src/runtime/migrations/migration-wizard.ts +2 -2
- package/src/runtime/migrations/origin-mode.ts +40 -0
- package/src/runtime/migrations/vbundle-builder.ts +133 -80
- package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
- package/src/runtime/migrations/vbundle-importer.ts +8 -8
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -16
- package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
- package/src/runtime/migrations/vbundle-tar-stream.ts +11 -3
- package/src/runtime/migrations/vbundle-validator.ts +214 -41
- package/src/runtime/nl-approval-parser.ts +16 -21
- package/src/runtime/pending-interactions.ts +42 -16
- package/src/runtime/routes/__tests__/acp-routes.test.ts +394 -0
- package/src/runtime/routes/__tests__/backup-routes.test.ts +232 -339
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +72 -4
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
- package/src/runtime/routes/__tests__/stt-routes.test.ts +182 -223
- package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +230 -0
- package/src/{ipc/__tests__/task-ipc.test.ts → runtime/routes/__tests__/task-routes.test.ts} +116 -96
- package/src/runtime/routes/__tests__/tts-routes.test.ts +185 -289
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
- package/src/runtime/routes/access-request-decision.ts +25 -50
- package/src/runtime/routes/acp-routes.test.ts +368 -0
- package/src/runtime/routes/acp-routes.ts +392 -170
- package/src/runtime/routes/app-management-routes.ts +475 -662
- package/src/runtime/routes/app-routes.ts +192 -177
- package/src/runtime/routes/approval-routes.ts +163 -440
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +24 -84
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +3 -10
- package/src/runtime/routes/attachment-routes.ts +409 -253
- package/src/runtime/routes/audio-routes.ts +51 -18
- package/src/runtime/routes/avatar-routes.ts +81 -76
- package/src/runtime/routes/background-tool-routes.ts +94 -0
- package/src/runtime/routes/backup-routes.ts +154 -336
- package/src/runtime/routes/brain-graph-routes.ts +83 -110
- package/src/runtime/routes/browser-routes.ts +127 -0
- package/src/runtime/routes/btw-routes.ts +62 -106
- package/src/runtime/routes/cache-routes.ts +96 -0
- package/src/runtime/routes/call-routes.ts +208 -247
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +1 -1
- package/src/runtime/routes/channel-delivery-routes.ts +25 -27
- package/src/runtime/routes/channel-guardian-routes.ts +1 -5
- package/src/runtime/routes/channel-readiness-routes.ts +79 -120
- package/src/runtime/routes/channel-route-definitions.ts +62 -0
- package/src/runtime/routes/channel-route-shared.ts +15 -45
- package/src/runtime/routes/channel-verification-routes.ts +207 -187
- package/src/runtime/routes/client-routes.ts +81 -0
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/contact-routes.ts +533 -407
- package/src/runtime/routes/conversation-analysis-routes.ts +48 -49
- package/src/runtime/routes/conversation-attention-routes.ts +55 -67
- package/src/runtime/routes/conversation-list-routes.ts +248 -0
- package/src/runtime/routes/conversation-management-routes.ts +591 -717
- package/src/runtime/routes/conversation-query-routes.ts +621 -459
- package/src/runtime/routes/conversation-routes.ts +396 -792
- package/src/runtime/routes/conversation-starter-routes.ts +137 -108
- package/src/runtime/routes/credential-prompt-routes.ts +124 -0
- package/src/runtime/routes/debug-routes.ts +34 -39
- package/src/runtime/routes/defer-routes.ts +230 -0
- package/src/runtime/routes/diagnostics-routes.ts +79 -70
- package/src/runtime/routes/documents-routes.ts +163 -117
- package/src/runtime/routes/errors.ts +132 -0
- package/src/runtime/routes/events-routes.ts +126 -119
- package/src/runtime/routes/filing-routes.ts +80 -76
- package/src/runtime/routes/global-search-routes.ts +51 -57
- package/src/runtime/routes/group-routes.ts +199 -181
- package/src/runtime/routes/guardian-action-routes.ts +100 -171
- package/src/runtime/routes/guardian-approval-interception.ts +27 -58
- package/src/runtime/routes/guardian-approval-prompt.ts +10 -21
- package/src/runtime/routes/guardian-approval-reply-helpers.ts +2 -6
- package/src/runtime/routes/guardian-expiry-sweep.ts +19 -36
- package/src/runtime/routes/heartbeat-routes.ts +194 -209
- package/src/runtime/routes/home-feed-routes.ts +85 -187
- package/src/runtime/routes/home-state-routes.ts +27 -24
- package/src/runtime/routes/host-bash-routes.ts +45 -54
- package/src/runtime/routes/host-browser-routes.ts +44 -99
- package/src/runtime/routes/host-cu-routes.ts +80 -71
- package/src/runtime/routes/host-file-routes.ts +53 -62
- package/src/runtime/routes/host-transfer-routes.ts +216 -0
- package/src/runtime/routes/http-adapter.ts +172 -0
- package/src/runtime/routes/identity-routes.ts +161 -85
- package/src/runtime/routes/inbound-conversation.ts +11 -18
- package/src/runtime/routes/inbound-message-handler.ts +639 -232
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +81 -226
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +2 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -90
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +25 -50
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +5 -5
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +5 -6
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -24
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -10
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -4
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +3 -3
- package/src/runtime/routes/index.ts +201 -0
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +25 -32
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +22 -31
- package/src/runtime/routes/integrations/slack/channel.ts +50 -71
- package/src/runtime/routes/integrations/slack/share.ts +49 -58
- package/src/runtime/routes/integrations/telegram.ts +91 -74
- package/src/runtime/routes/integrations/twilio.ts +163 -240
- package/src/runtime/routes/integrations/vercel.ts +57 -54
- package/src/runtime/routes/interface-routes.ts +43 -0
- package/src/runtime/routes/internal-oauth-routes.ts +56 -0
- package/src/runtime/routes/internal-twilio-routes.ts +46 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
- package/src/runtime/routes/llm-context-normalization.ts +4 -2
- package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
- package/src/runtime/routes/log-export-routes.ts +90 -100
- package/src/runtime/routes/memory-item-routes.test.ts +152 -175
- package/src/runtime/routes/memory-item-routes.ts +243 -323
- package/src/runtime/routes/memory-v2-routes.ts +188 -0
- package/src/runtime/routes/migration-rollback-routes.ts +167 -212
- package/src/runtime/routes/migration-routes.ts +1037 -377
- package/src/runtime/routes/notification-routes.ts +199 -70
- package/src/runtime/routes/oauth-apps.ts +254 -251
- package/src/runtime/routes/oauth-providers.ts +66 -57
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +60 -120
- package/src/runtime/routes/playground/__tests__/guard.test.ts +34 -54
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +107 -151
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +41 -117
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +95 -138
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +115 -217
- package/src/runtime/routes/playground/__tests__/state.test.ts +41 -90
- package/src/runtime/routes/playground/conversation-not-found.ts +9 -11
- package/src/runtime/routes/playground/force-compact.ts +41 -54
- package/src/runtime/routes/playground/guard.ts +18 -19
- package/src/runtime/routes/playground/helpers.ts +103 -0
- package/src/runtime/routes/playground/index.ts +15 -27
- package/src/runtime/routes/playground/inject-failures.ts +48 -64
- package/src/runtime/routes/playground/reset-circuit.ts +31 -57
- package/src/runtime/routes/playground/seed-conversation.ts +66 -92
- package/src/runtime/routes/playground/seeded-conversations.ts +60 -64
- package/src/runtime/routes/playground/state.ts +23 -24
- package/src/runtime/routes/profiler-routes.ts +132 -167
- package/src/runtime/routes/ps-routes.ts +120 -0
- package/src/runtime/routes/recording-routes.ts +189 -270
- package/src/runtime/routes/rename-conversation-routes.ts +85 -0
- package/src/runtime/routes/schedule-routes.ts +239 -246
- package/src/runtime/routes/secret-routes.ts +305 -282
- package/src/runtime/routes/secrets-deps.ts +24 -0
- package/src/runtime/routes/settings-routes.ts +370 -449
- package/src/runtime/routes/skills-routes.ts +417 -471
- package/src/runtime/routes/stt-routes.ts +196 -206
- package/src/runtime/routes/subagents-routes.ts +125 -141
- package/src/runtime/routes/suggest-trust-rule-routes.ts +275 -0
- package/src/runtime/routes/surface-action-routes.ts +135 -190
- package/src/runtime/routes/surface-content-routes.ts +84 -118
- package/src/runtime/routes/task-routes.ts +354 -0
- package/src/runtime/routes/telemetry-routes.ts +33 -49
- package/src/runtime/routes/trace-event-routes.ts +55 -74
- package/src/runtime/routes/trust-rules-routes.ts +61 -244
- package/src/runtime/routes/tts-routes.ts +187 -169
- package/src/runtime/routes/types.ts +139 -0
- package/src/{ipc/routes/ui-request.ts → runtime/routes/ui-request-routes.ts} +23 -17
- package/src/runtime/routes/upgrade-broadcast-routes.ts +150 -198
- package/src/runtime/routes/usage-routes.ts +222 -171
- package/src/runtime/routes/user-routes.ts +88 -18
- package/src/runtime/routes/wake-conversation-routes.ts +49 -0
- package/src/{ipc/routes/watcher.ts → runtime/routes/watcher-routes.ts} +84 -39
- package/src/runtime/routes/wipe-conversation-routes.ts +89 -0
- package/src/runtime/routes/work-items-routes.test.ts +10 -20
- package/src/runtime/routes/work-items-routes.ts +419 -437
- package/src/runtime/routes/workspace-commit-routes.ts +30 -61
- package/src/runtime/routes/workspace-routes.test.ts +254 -381
- package/src/runtime/routes/workspace-routes.ts +238 -246
- package/src/runtime/runtime-mode.ts +8 -1
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +82 -120
- package/src/runtime/services/analyze-conversation.ts +18 -55
- package/src/runtime/services/conversation-serializer.ts +179 -0
- package/src/runtime/trust-context-resolver.ts +3 -2
- package/src/runtime/verification-outbound-actions.ts +14 -50
- package/src/runtime/verification-rate-limiter.ts +1 -1
- package/src/schedule/schedule-store.ts +64 -18
- package/src/schedule/scheduler.ts +101 -0
- package/src/security/ces-credential-client.ts +32 -169
- package/src/security/ces-rpc-credential-backend.ts +1 -1
- package/src/security/credential-backend.ts +6 -6
- package/src/security/oauth-completion-page.ts +1 -1
- package/src/security/oauth2.ts +3 -6
- package/src/security/secret-scanner.ts +14 -547
- package/src/security/secure-keys.ts +31 -11
- package/src/security/token-manager.ts +7 -3
- package/src/sequence/analytics.ts +1 -1
- package/src/sequence/guardrails.ts +3 -3
- package/src/sequence/store.ts +2 -1
- package/src/signals/bash.ts +1 -1
- package/src/signals/cancel.ts +16 -25
- package/src/signals/conversation-undo.ts +2 -27
- package/src/signals/emit-event.ts +1 -2
- package/src/signals/event-stream.ts +1 -1
- package/src/signals/user-message.ts +108 -22
- package/src/skills/catalog-cache.ts +7 -0
- package/src/skills/catalog-files.ts +0 -5
- package/src/skills/catalog-install.ts +29 -18
- package/src/skills/category-inference.ts +0 -11
- package/src/skills/clawhub.ts +4 -4
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/skills/managed-store.ts +2 -2
- package/src/skills/remote-skill-policy.ts +6 -7
- package/src/subagent/index.ts +2 -6
- package/src/subagent/manager.ts +94 -107
- package/src/subagent/types.ts +9 -0
- package/src/tasks/SPEC.md +2 -2
- package/src/tasks/task-compiler.ts +1 -1
- package/src/tasks/task-runner.ts +2 -22
- package/src/tasks/task-store.ts +2 -29
- package/src/telemetry/types.ts +6 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
- package/src/telemetry/usage-telemetry-reporter.ts +3 -5
- package/src/tools/acp/list-agents.test.ts +115 -0
- package/src/tools/acp/list-agents.ts +31 -0
- package/src/tools/acp/spawn.test.ts +378 -0
- package/src/tools/acp/spawn.ts +142 -62
- package/src/tools/acp/steer.test.ts +100 -0
- package/src/tools/acp/steer.ts +38 -0
- package/src/tools/background-tool-registry.ts +98 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
- package/src/tools/browser/browser-execution.ts +38 -127
- package/src/tools/browser/browser-manager.ts +1 -8
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +1 -1
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +3 -1
- package/src/tools/browser/cdp-client/factory.ts +48 -76
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/browser/cdp-client/types.ts +4 -1
- package/src/tools/computer-use/definitions.ts +1 -1
- package/src/tools/credential-execution/make-authenticated-request.ts +2 -2
- package/src/tools/credential-execution/manage-secure-command-tool.ts +1 -1
- package/src/tools/credential-execution/run-authenticated-command.ts +2 -2
- package/src/tools/credentials/broker-types.ts +2 -1
- package/src/tools/document/editor-template.ts +1 -1
- package/src/tools/execution-timeout.ts +1 -1
- package/src/tools/executor.ts +53 -45
- package/src/tools/host-filesystem/edit.ts +3 -2
- package/src/tools/host-filesystem/read.ts +3 -2
- package/src/tools/host-filesystem/transfer.test.ts +271 -0
- package/src/tools/host-filesystem/transfer.ts +235 -0
- package/src/tools/host-filesystem/write.ts +3 -2
- package/src/tools/host-terminal/host-shell.ts +192 -13
- package/src/tools/mcp/mcp-tool-factory.ts +1 -1
- package/src/tools/memory/register.test.ts +161 -1
- package/src/tools/memory/register.ts +19 -34
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +84 -220
- package/src/tools/policy-context.ts +1 -8
- package/src/tools/registry.ts +16 -1
- package/src/tools/shared/shell-output.ts +4 -1
- package/src/tools/side-effects.ts +2 -2
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/sandbox-runner.ts +1 -6
- package/src/tools/skills/skill-tool-factory.ts +32 -0
- package/src/tools/subagent/spawn.ts +35 -11
- package/src/tools/terminal/safe-env.ts +10 -1
- package/src/tools/terminal/shell.ts +142 -88
- package/src/tools/tool-approval-handler.ts +4 -70
- package/src/tools/tool-input-summary.ts +10 -0
- package/src/tools/types.ts +136 -183
- package/src/tools/ui-surface/definitions.ts +2 -2
- package/src/tts/__tests__/provider-catalog.test.ts +2 -2
- package/src/tts/provider-catalog.ts +1 -1
- package/src/usage/actors.ts +2 -1
- package/src/usage/attribution.ts +185 -0
- package/src/usage/pricing.ts +166 -0
- package/src/usage/types.ts +14 -0
- package/src/util/debounce.ts +0 -21
- package/src/util/errors.ts +0 -8
- package/src/util/json.ts +13 -0
- package/src/util/log-redact.ts +0 -1
- package/src/util/logger.ts +3 -3
- package/src/util/platform.ts +85 -124
- package/src/util/pricing.ts +158 -8
- package/src/watcher/engine.ts +42 -20
- package/src/watcher/watcher-store.ts +2 -1
- package/src/work-items/work-item-runner.ts +15 -42
- package/src/work-items/work-item-store.ts +1 -1
- package/src/workspace/git-service.ts +1 -6
- package/src/workspace/migrations/006-services-config.ts +10 -1
- package/src/workspace/migrations/017-seed-persona-dirs.ts +1 -1
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +1 -1
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +1 -1
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +3 -4
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +150 -0
- package/src/workspace/migrations/053-release-notes-acp-codex.ts +107 -0
- package/src/workspace/migrations/054-seed-recall-callsite.ts +102 -0
- package/src/workspace/migrations/055-release-notes-agentic-recall.ts +63 -0
- package/src/workspace/migrations/056-release-notes-inference-profile-reordering.ts +65 -0
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +98 -0
- package/src/workspace/migrations/058-release-notes-acp-sessions-ui.ts +71 -0
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +53 -0
- package/src/workspace/migrations/060-memory-v2-init.ts +37 -0
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
- package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
- package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
- package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
- package/src/workspace/migrations/rebuild-conversation-disk-view.ts +1 -1
- package/src/workspace/migrations/registry.ts +26 -0
- package/src/workspace/migrations/runner.ts +2 -2
- package/src/workspace/provider-commit-message-generator.ts +4 -4
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +0 -471
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +0 -436
- package/src/__tests__/cli-command-risk-guard.test.ts +0 -368
- package/src/__tests__/config-watcher-feature-flags.test.ts +0 -211
- package/src/__tests__/conversation-approval-overrides.test.ts +0 -207
- package/src/__tests__/conversation-host-access-routes.test.ts +0 -229
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +0 -226
- package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +0 -167
- package/src/__tests__/ephemeral-permissions.test.ts +0 -474
- package/src/__tests__/extension-id-sync-guard.test.ts +0 -241
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +0 -374
- package/src/__tests__/native-host-marker-sync-guard.test.ts +0 -157
- package/src/__tests__/pairing-concurrent.test.ts +0 -84
- package/src/__tests__/pairing-routes.test.ts +0 -181
- package/src/__tests__/parser.test.ts +0 -595
- package/src/__tests__/permission-checker-host-gate.test.ts +0 -488
- package/src/__tests__/permission-controls-v2-flag.test.ts +0 -55
- package/src/__tests__/permission-mode.test.ts +0 -89
- package/src/__tests__/provider-env-vars-scope.test.ts +0 -52
- package/src/__tests__/risk-classifier-parity.test.ts +0 -230
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
- package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
- package/src/__tests__/secret-detection-handler.test.ts +0 -74
- package/src/__tests__/secret-scanner-executor.test.ts +0 -451
- package/src/__tests__/shell-identity.test.ts +0 -236
- package/src/__tests__/shell-parser-fuzz.test.ts +0 -629
- package/src/__tests__/shell-parser-property.test.ts +0 -936
- package/src/__tests__/starter-bundle.test.ts +0 -173
- package/src/__tests__/stt-catalog-parity.test.ts +0 -282
- package/src/__tests__/task-runner.test.ts +0 -224
- package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
- package/src/__tests__/terminal-sandbox.test.ts +0 -374
- package/src/__tests__/tool-executor-shell-integration.test.ts +0 -354
- package/src/__tests__/tool-notification-listener.test.ts +0 -65
- package/src/__tests__/trust-store-pattern-matches.test.ts +0 -29
- package/src/__tests__/trust-store.test.ts +0 -2013
- package/src/__tests__/v2-consent-policy.test.ts +0 -103
- package/src/browser/identifiers.ts +0 -51
- package/src/cli/db.ts +0 -1
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +0 -40
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +0 -64
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +0 -88
- package/src/context/__tests__/microcompact.test.ts +0 -805
- package/src/context/microcompact.ts +0 -443
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +0 -127
- package/src/daemon/approved-devices-store.ts +0 -110
- package/src/daemon/external-skills-bootstrap.ts +0 -41
- package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
- package/src/daemon/message-types/trust.ts +0 -71
- package/src/daemon/pairing-store.ts +0 -229
- package/src/events/tool-notification-listener.ts +0 -17
- package/src/ipc/cli-server.ts +0 -252
- package/src/ipc/routes/attachment.ts +0 -114
- package/src/ipc/routes/browser-context.ts +0 -63
- package/src/ipc/routes/browser.ts +0 -97
- package/src/ipc/routes/cache.ts +0 -96
- package/src/ipc/routes/get-contact.ts +0 -16
- package/src/ipc/routes/index.ts +0 -35
- package/src/ipc/routes/list-clients.ts +0 -31
- package/src/ipc/routes/merge-contacts.ts +0 -17
- package/src/ipc/routes/notification.ts +0 -133
- package/src/ipc/routes/rename-conversation.ts +0 -59
- package/src/ipc/routes/search-contacts.ts +0 -19
- package/src/ipc/routes/task-queue.ts +0 -226
- package/src/ipc/routes/task.ts +0 -173
- package/src/ipc/routes/upsert-contact.ts +0 -25
- package/src/ipc/routes/wake-conversation.ts +0 -19
- package/src/memory/db.ts +0 -23
- package/src/permissions/arg-parser.test.ts +0 -161
- package/src/permissions/arg-parser.ts +0 -141
- package/src/permissions/bash-risk-classifier.test.ts +0 -1620
- package/src/permissions/bash-risk-classifier.ts +0 -950
- package/src/permissions/command-registry.test.ts +0 -774
- package/src/permissions/command-registry.ts +0 -1005
- package/src/permissions/defaults.ts +0 -314
- package/src/permissions/file-risk-classifier.test.ts +0 -535
- package/src/permissions/file-risk-classifier.ts +0 -274
- package/src/permissions/permission-mode.ts +0 -24
- package/src/permissions/schedule-risk-classifier.test.ts +0 -129
- package/src/permissions/schedule-risk-classifier.ts +0 -85
- package/src/permissions/shell-identity.ts +0 -297
- package/src/permissions/skill-risk-classifier.test.ts +0 -311
- package/src/permissions/skill-risk-classifier.ts +0 -214
- package/src/permissions/trust-client.ts +0 -359
- package/src/permissions/trust-store-interface.ts +0 -100
- package/src/permissions/trust-store.ts +0 -1330
- package/src/permissions/v2-consent-policy.ts +0 -87
- package/src/permissions/web-risk-classifier.test.ts +0 -170
- package/src/permissions/web-risk-classifier.ts +0 -89
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +0 -715
- package/src/runtime/__tests__/capability-tokens.test.ts +0 -258
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
- package/src/runtime/__tests__/client-registry.test.ts +0 -293
- package/src/runtime/actor-refresh-token-store.ts +0 -156
- package/src/runtime/actor-token-store.ts +0 -207
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -264
- package/src/runtime/auth/credential-service.ts +0 -352
- package/src/runtime/chrome-extension-registry.ts +0 -368
- package/src/runtime/client-registry.ts +0 -261
- package/src/runtime/conversation-approval-overrides.ts +0 -86
- package/src/runtime/routes/browser-extension-pair-routes.ts +0 -575
- package/src/runtime/routes/channel-routes.ts +0 -112
- package/src/runtime/routes/contact-routes.test.ts +0 -298
- package/src/runtime/routes/guardian-bootstrap-routes.ts +0 -175
- package/src/runtime/routes/guardian-refresh-routes.ts +0 -79
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -336
- package/src/runtime/routes/invite-routes.ts +0 -280
- package/src/runtime/routes/pairing-routes.ts +0 -431
- package/src/runtime/routes/playground/deps.ts +0 -56
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +0 -67
- package/src/runtime/services/analyze-deps-singleton.ts +0 -32
- package/src/tasks/ephemeral-permissions.ts +0 -55
- package/src/tools/secret-detection-handler.ts +0 -359
- package/src/tools/terminal/backends/native.ts +0 -327
- package/src/tools/terminal/backends/types.ts +0 -37
- package/src/tools/terminal/parser.ts +0 -623
- package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
- package/src/tools/terminal/sandbox.ts +0 -40
- package/src/types/qrcode.d.ts +0 -13
- package/src/util/network-info.ts +0 -55
- /package/node_modules/@vellumai/{ces-contracts → ces-client}/tsconfig.json +0 -0
- /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/__tests__/grants.test.ts +0 -0
- /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/error.ts +0 -0
- /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/grants.ts +0 -0
- /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/handles.ts +0 -0
- /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/rendering.ts +0 -0
- /package/node_modules/@vellumai/{ces-contracts → service-contracts}/src/rpc.ts +0 -0
|
@@ -5,16 +5,6 @@
|
|
|
5
5
|
* configured port (default: 7821).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
existsSync,
|
|
10
|
-
mkdirSync,
|
|
11
|
-
readFileSync,
|
|
12
|
-
renameSync,
|
|
13
|
-
unlinkSync,
|
|
14
|
-
writeFileSync,
|
|
15
|
-
} from "node:fs";
|
|
16
|
-
import { dirname, resolve } from "node:path";
|
|
17
|
-
|
|
18
8
|
import type { ServerWebSocket } from "bun";
|
|
19
9
|
|
|
20
10
|
import {
|
|
@@ -35,75 +25,36 @@ import {
|
|
|
35
25
|
handleStatusCallback,
|
|
36
26
|
handleVoiceWebhook,
|
|
37
27
|
} from "../calls/twilio-routes.js";
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
getGatewayInternalBaseUrl,
|
|
42
|
-
hasUngatedHttpAuthDisabled,
|
|
43
|
-
isHttpAuthDisabled,
|
|
44
|
-
} from "../config/env.js";
|
|
28
|
+
import { isHttpAuthDisabled } from "../config/env.js";
|
|
29
|
+
import { getIsPlatform } from "../config/env-registry.js";
|
|
45
30
|
import { getConfig } from "../config/loader.js";
|
|
46
|
-
import
|
|
47
|
-
import {
|
|
31
|
+
import { processMessage } from "../daemon/process-message.js";
|
|
32
|
+
import { createLiveVoiceSession } from "../live-voice/live-voice-session.js";
|
|
33
|
+
import { LiveVoiceSessionManager } from "../live-voice/live-voice-session-manager.js";
|
|
48
34
|
import {
|
|
49
|
-
type
|
|
50
|
-
type
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
} from "../
|
|
56
|
-
import {
|
|
57
|
-
addMessage,
|
|
58
|
-
type ConversationRow,
|
|
59
|
-
createConversation,
|
|
60
|
-
deleteConversation,
|
|
61
|
-
forkConversation as forkConversationInStore,
|
|
62
|
-
getConversation,
|
|
63
|
-
getDisplayMetaForConversations,
|
|
64
|
-
} from "../memory/conversation-crud.js";
|
|
65
|
-
import { resolveConversationId } from "../memory/conversation-key-store.js";
|
|
66
|
-
import {
|
|
67
|
-
countConversations,
|
|
68
|
-
listConversations,
|
|
69
|
-
listConversationsByTitlePrefix,
|
|
70
|
-
listPinnedConversations,
|
|
71
|
-
} from "../memory/conversation-queries.js";
|
|
72
|
-
import type { ExternalConversationBinding } from "../memory/external-conversation-store.js";
|
|
73
|
-
import * as externalConversationStore from "../memory/external-conversation-store.js";
|
|
74
|
-
import { listGroups } from "../memory/group-crud.js";
|
|
75
|
-
import { enqueueMemoryJob } from "../memory/jobs-store.js";
|
|
35
|
+
type LiveVoiceClientFrame,
|
|
36
|
+
type LiveVoiceProtocolError,
|
|
37
|
+
LiveVoiceProtocolErrorCode,
|
|
38
|
+
type LiveVoiceServerFrame,
|
|
39
|
+
parseLiveVoiceBinaryAudioFrame,
|
|
40
|
+
parseLiveVoiceClientTextFrame,
|
|
41
|
+
} from "../live-voice/protocol.js";
|
|
76
42
|
import { resolveStreamingTranscriber } from "../providers/speech-to-text/resolve.js";
|
|
77
|
-
import {
|
|
78
|
-
consumeCallback,
|
|
79
|
-
consumeCallbackError,
|
|
80
|
-
} from "../security/oauth-callback-registry.js";
|
|
81
43
|
import {
|
|
82
44
|
activeSttStreamSessions,
|
|
83
45
|
SttStreamSession,
|
|
84
46
|
} from "../stt/stt-stream-session.js";
|
|
85
|
-
import { UserError } from "../util/errors.js";
|
|
86
47
|
import { getLogger } from "../util/logger.js";
|
|
87
|
-
import { getRuntimePortFilePath } from "../util/platform.js";
|
|
88
|
-
import { buildAssistantEvent } from "./assistant-event.js";
|
|
89
|
-
import { assistantEventHub } from "./assistant-event-hub.js";
|
|
90
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "./assistant-scope.js";
|
|
91
48
|
// Auth
|
|
92
49
|
import {
|
|
93
50
|
authenticateHostBrowserResultRequest,
|
|
94
51
|
authenticateRequest,
|
|
95
52
|
} from "./auth/middleware.js";
|
|
96
53
|
import { parseSub } from "./auth/subject.js";
|
|
97
|
-
import {
|
|
98
|
-
mintDaemonDeliveryToken,
|
|
99
|
-
mintUiPageToken,
|
|
100
|
-
verifyToken,
|
|
101
|
-
} from "./auth/token-service.js";
|
|
54
|
+
import { verifyToken } from "./auth/token-service.js";
|
|
102
55
|
import { verifyHostBrowserCapability } from "./capability-tokens.js";
|
|
103
56
|
import { sweepFailedEvents } from "./channel-retry-sweep.js";
|
|
104
|
-
import {
|
|
105
|
-
import { httpError } from "./http-errors.js";
|
|
106
|
-
import type { RouteDefinition } from "./http-router.js";
|
|
57
|
+
import { httpError, type HttpErrorCode } from "./http-errors.js";
|
|
107
58
|
import { HttpRouter } from "./http-router.js";
|
|
108
59
|
// Middleware
|
|
109
60
|
import {
|
|
@@ -129,111 +80,23 @@ import {
|
|
|
129
80
|
TWILIO_WEBHOOK_RE,
|
|
130
81
|
validateTwilioWebhook,
|
|
131
82
|
} from "./middleware/twilio-validation.js";
|
|
132
|
-
import {
|
|
133
|
-
import {
|
|
134
|
-
import { handleServePage } from "./routes/app-routes.js";
|
|
135
|
-
import { appRouteDefinitions } from "./routes/app-routes.js";
|
|
136
|
-
import { approvalRouteDefinitions } from "./routes/approval-routes.js";
|
|
137
|
-
import { attachmentRouteDefinitions } from "./routes/attachment-routes.js";
|
|
138
|
-
import { handleGetAudio } from "./routes/audio-routes.js";
|
|
139
|
-
import { avatarRouteDefinitions } from "./routes/avatar-routes.js";
|
|
140
|
-
import { backupRouteDefinitions } from "./routes/backup-routes.js";
|
|
141
|
-
import { brainGraphRouteDefinitions } from "./routes/brain-graph-routes.js";
|
|
142
|
-
import { handleBrowserExtensionPair } from "./routes/browser-extension-pair-routes.js";
|
|
143
|
-
import { btwRouteDefinitions } from "./routes/btw-routes.js";
|
|
144
|
-
import { callRouteDefinitions } from "./routes/call-routes.js";
|
|
83
|
+
import { ROUTES as APP_ROUTES } from "./routes/app-routes.js";
|
|
84
|
+
import { ROUTES as AUDIO_ROUTES } from "./routes/audio-routes.js";
|
|
145
85
|
import {
|
|
146
86
|
startCanonicalGuardianExpirySweep,
|
|
147
87
|
stopCanonicalGuardianExpirySweep,
|
|
148
88
|
} from "./routes/canonical-guardian-expiry-sweep.js";
|
|
149
|
-
import { channelReadinessRouteDefinitions } from "./routes/channel-readiness-routes.js";
|
|
150
89
|
import {
|
|
151
|
-
channelRouteDefinitions,
|
|
152
90
|
startGuardianExpirySweep,
|
|
153
91
|
stopGuardianExpirySweep,
|
|
154
|
-
} from "./routes/channel-routes.js";
|
|
155
|
-
import {
|
|
156
|
-
import {
|
|
157
|
-
contactCatchAllRouteDefinitions,
|
|
158
|
-
contactRouteDefinitions,
|
|
159
|
-
} from "./routes/contact-routes.js";
|
|
160
|
-
import { conversationAnalysisRouteDefinitions } from "./routes/conversation-analysis-routes.js";
|
|
161
|
-
import { conversationAttentionRouteDefinitions } from "./routes/conversation-attention-routes.js";
|
|
162
|
-
import {
|
|
163
|
-
type ConversationManagementDeps,
|
|
164
|
-
conversationManagementRouteDefinitions,
|
|
165
|
-
} from "./routes/conversation-management-routes.js";
|
|
166
|
-
import { conversationQueryRouteDefinitions } from "./routes/conversation-query-routes.js";
|
|
167
|
-
import { conversationRouteDefinitions } from "./routes/conversation-routes.js";
|
|
168
|
-
import { conversationStarterRouteDefinitions } from "./routes/conversation-starter-routes.js";
|
|
169
|
-
import { debugRouteDefinitions } from "./routes/debug-routes.js";
|
|
170
|
-
import { diagnosticsRouteDefinitions } from "./routes/diagnostics-routes.js";
|
|
171
|
-
import { documentRouteDefinitions } from "./routes/documents-routes.js";
|
|
172
|
-
import { eventsRouteDefinitions } from "./routes/events-routes.js";
|
|
173
|
-
import { filingRouteDefinitions } from "./routes/filing-routes.js";
|
|
174
|
-
import { globalSearchRouteDefinitions } from "./routes/global-search-routes.js";
|
|
175
|
-
import { groupRouteDefinitions } from "./routes/group-routes.js";
|
|
176
|
-
import { guardianActionRouteDefinitions } from "./routes/guardian-action-routes.js";
|
|
177
|
-
import { handleGuardianBootstrap } from "./routes/guardian-bootstrap-routes.js";
|
|
178
|
-
import { handleGuardianRefresh } from "./routes/guardian-refresh-routes.js";
|
|
179
|
-
import { heartbeatRouteDefinitions } from "./routes/heartbeat-routes.js";
|
|
180
|
-
import { homeFeedRouteDefinitions } from "./routes/home-feed-routes.js";
|
|
181
|
-
import { homeStateRouteDefinitions } from "./routes/home-state-routes.js";
|
|
182
|
-
import { hostBashRouteDefinitions } from "./routes/host-bash-routes.js";
|
|
92
|
+
} from "./routes/channel-guardian-routes.js";
|
|
93
|
+
import { RouteError } from "./routes/errors.js";
|
|
183
94
|
import {
|
|
184
|
-
hostBrowserRouteDefinitions,
|
|
185
95
|
resolveHostBrowserEvent,
|
|
186
96
|
resolveHostBrowserResultByRequestId,
|
|
187
97
|
resolveHostBrowserSessionInvalidated,
|
|
188
98
|
} from "./routes/host-browser-routes.js";
|
|
189
|
-
import {
|
|
190
|
-
import { hostFileRouteDefinitions } from "./routes/host-file-routes.js";
|
|
191
|
-
import {
|
|
192
|
-
handleHealth,
|
|
193
|
-
handleReadyz,
|
|
194
|
-
identityRouteDefinitions,
|
|
195
|
-
} from "./routes/identity-routes.js";
|
|
196
|
-
import { slackChannelRouteDefinitions } from "./routes/integrations/slack/channel.js";
|
|
197
|
-
import { slackShareRouteDefinitions } from "./routes/integrations/slack/share.js";
|
|
198
|
-
import { telegramRouteDefinitions } from "./routes/integrations/telegram.js";
|
|
199
|
-
import { twilioRouteDefinitions } from "./routes/integrations/twilio.js";
|
|
200
|
-
import { vercelRouteDefinitions } from "./routes/integrations/vercel.js";
|
|
201
|
-
import { inviteRouteDefinitions } from "./routes/invite-routes.js";
|
|
202
|
-
import { logExportRouteDefinitions } from "./routes/log-export-routes.js";
|
|
203
|
-
import { memoryItemRouteDefinitions } from "./routes/memory-item-routes.js";
|
|
204
|
-
import { migrationRollbackRouteDefinitions } from "./routes/migration-rollback-routes.js";
|
|
205
|
-
import { migrationRouteDefinitions } from "./routes/migration-routes.js";
|
|
206
|
-
import { notificationRouteDefinitions } from "./routes/notification-routes.js";
|
|
207
|
-
import { oauthAppsRouteDefinitions } from "./routes/oauth-apps.js";
|
|
208
|
-
import { oauthProvidersRouteDefinitions } from "./routes/oauth-providers.js";
|
|
209
|
-
import type { PairingHandlerContext } from "./routes/pairing-routes.js";
|
|
210
|
-
import {
|
|
211
|
-
handlePairingRequest,
|
|
212
|
-
handlePairingStatus,
|
|
213
|
-
pairingRouteDefinitions,
|
|
214
|
-
} from "./routes/pairing-routes.js";
|
|
215
|
-
import { playgroundRouteDefinitions } from "./routes/playground/index.js";
|
|
216
|
-
import { profilerRouteDefinitions } from "./routes/profiler-routes.js";
|
|
217
|
-
import { recordingRouteDefinitions } from "./routes/recording-routes.js";
|
|
218
|
-
import { scheduleRouteDefinitions } from "./routes/schedule-routes.js";
|
|
219
|
-
import { secretRouteDefinitions } from "./routes/secret-routes.js";
|
|
220
|
-
import { settingsRouteDefinitions } from "./routes/settings-routes.js";
|
|
221
|
-
import { skillRouteDefinitions } from "./routes/skills-routes.js";
|
|
222
|
-
import { sttRouteDefinitions } from "./routes/stt-routes.js";
|
|
223
|
-
import { subagentRouteDefinitions } from "./routes/subagents-routes.js";
|
|
224
|
-
import { surfaceActionRouteDefinitions } from "./routes/surface-action-routes.js";
|
|
225
|
-
import { surfaceContentRouteDefinitions } from "./routes/surface-content-routes.js";
|
|
226
|
-
import { telemetryRouteDefinitions } from "./routes/telemetry-routes.js";
|
|
227
|
-
import { traceEventRouteDefinitions } from "./routes/trace-event-routes.js";
|
|
228
|
-
import { trustRulesRouteDefinitions } from "./routes/trust-rules-routes.js";
|
|
229
|
-
import { ttsRouteDefinitions } from "./routes/tts-routes.js";
|
|
230
|
-
import { upgradeBroadcastRouteDefinitions } from "./routes/upgrade-broadcast-routes.js";
|
|
231
|
-
import { usageRouteDefinitions } from "./routes/usage-routes.js";
|
|
232
|
-
import { userRouteDefinitions } from "./routes/user-routes.js";
|
|
233
|
-
import { workItemRouteDefinitions } from "./routes/work-items-routes.js";
|
|
234
|
-
import { workspaceCommitRouteDefinitions } from "./routes/workspace-commit-routes.js";
|
|
235
|
-
import { workspaceRouteDefinitions } from "./routes/workspace-routes.js";
|
|
236
|
-
import { setAnalysisDeps } from "./services/analyze-deps-singleton.js";
|
|
99
|
+
import { handleHealth, handleReadyz } from "./routes/identity-routes.js";
|
|
237
100
|
import { matchSkillRoute } from "./skill-route-registry.js";
|
|
238
101
|
|
|
239
102
|
// Re-export for consumers
|
|
@@ -249,7 +112,6 @@ export type {
|
|
|
249
112
|
RuntimeAttachmentMetadata,
|
|
250
113
|
RuntimeHttpServerOptions,
|
|
251
114
|
RuntimeMessageConversationOptions,
|
|
252
|
-
SendMessageDeps,
|
|
253
115
|
} from "./http-types.js";
|
|
254
116
|
|
|
255
117
|
import type {
|
|
@@ -257,9 +119,7 @@ import type {
|
|
|
257
119
|
ApprovalCopyGenerator,
|
|
258
120
|
GuardianActionCopyGenerator,
|
|
259
121
|
GuardianFollowUpConversationGenerator,
|
|
260
|
-
MessageProcessor,
|
|
261
122
|
RuntimeHttpServerOptions,
|
|
262
|
-
SendMessageDeps,
|
|
263
123
|
} from "./http-types.js";
|
|
264
124
|
|
|
265
125
|
const log = getLogger("runtime-http");
|
|
@@ -273,9 +133,8 @@ const MAX_REQUEST_BODY_BYTES = 512 * 1024 * 1024;
|
|
|
273
133
|
/**
|
|
274
134
|
* WebSocket data attached to `/v1/browser-relay` connections. The route
|
|
275
135
|
* is used exclusively by the chrome-extension CDP proxy — outbound
|
|
276
|
-
* `host_browser_request` frames are pushed through the
|
|
277
|
-
*
|
|
278
|
-
* frames are dispatched through
|
|
136
|
+
* `host_browser_request` frames are pushed through the assistant event
|
|
137
|
+
* hub, and inbound `host_browser_result` frames are dispatched through
|
|
279
138
|
* `resolveHostBrowserResultByRequestId`. The extension may also submit
|
|
280
139
|
* results via `POST /v1/host-browser-result` (both transports resolve
|
|
281
140
|
* through the same core function).
|
|
@@ -285,21 +144,16 @@ interface BrowserRelayWebSocketData {
|
|
|
285
144
|
connectionId: string;
|
|
286
145
|
/**
|
|
287
146
|
* Guardian identity derived from the JWT claims at WebSocket upgrade
|
|
288
|
-
* time.
|
|
289
|
-
*
|
|
290
|
-
* HTTP auth is disabled (dev bypass) or when the token's sub cannot be
|
|
291
|
-
* parsed into an actor principal.
|
|
147
|
+
* time. Undefined when HTTP auth is disabled (dev bypass) or when the
|
|
148
|
+
* token's sub cannot be parsed into an actor principal.
|
|
292
149
|
*/
|
|
293
150
|
guardianId?: string;
|
|
294
151
|
/**
|
|
295
152
|
* Stable per-extension-install identifier supplied by the client on
|
|
296
153
|
* the WebSocket handshake (via the `clientInstanceId` query param or
|
|
297
|
-
* the `x-client-instance-id` header).
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* other on register/unregister. Undefined on older extension builds
|
|
301
|
-
* — the registry synthesizes a connection-scoped fallback key in
|
|
302
|
-
* that case for backwards-compatible single-instance semantics.
|
|
154
|
+
* the `x-client-instance-id` header). Allows multiple parallel installs
|
|
155
|
+
* for the same guardian (e.g. two Chrome profiles, two desktops) to
|
|
156
|
+
* coexist. Undefined on older extension builds.
|
|
303
157
|
*/
|
|
304
158
|
clientInstanceId?: string;
|
|
305
159
|
}
|
|
@@ -338,60 +192,45 @@ interface SttStreamWebSocketData {
|
|
|
338
192
|
session?: SttStreamSession;
|
|
339
193
|
}
|
|
340
194
|
|
|
195
|
+
/**
|
|
196
|
+
* WebSocket data attached to `/v1/live-voice` connections. The `wsType`
|
|
197
|
+
* discriminator routes frames to the live voice protocol shell instead of
|
|
198
|
+
* the other WebSocket handlers.
|
|
199
|
+
*/
|
|
200
|
+
interface LiveVoiceWebSocketData {
|
|
201
|
+
wsType: "live-voice";
|
|
202
|
+
sessionId?: string;
|
|
203
|
+
lastSeq: number;
|
|
204
|
+
}
|
|
205
|
+
|
|
341
206
|
export class RuntimeHttpServer {
|
|
342
207
|
private server: ReturnType<typeof Bun.serve> | null = null;
|
|
343
208
|
private port: number;
|
|
344
209
|
private hostname: string;
|
|
345
|
-
|
|
346
|
-
private bearerToken: string | undefined;
|
|
347
|
-
private processMessage?: MessageProcessor;
|
|
210
|
+
|
|
348
211
|
private approvalCopyGenerator?: ApprovalCopyGenerator;
|
|
349
212
|
private approvalConversationGenerator?: ApprovalConversationGenerator;
|
|
350
213
|
private guardianActionCopyGenerator?: GuardianActionCopyGenerator;
|
|
351
214
|
private guardianFollowUpConversationGenerator?: GuardianFollowUpConversationGenerator;
|
|
352
|
-
private interfacesDir: string | null;
|
|
353
|
-
private suggestionCache = new Map<string, string>();
|
|
354
|
-
private suggestionInFlight = new Map<string, Promise<string | null>>();
|
|
355
215
|
private retrySweepTimer: ReturnType<typeof setInterval> | null = null;
|
|
356
216
|
private sweepInProgress = false;
|
|
357
|
-
|
|
358
|
-
private
|
|
359
|
-
private sendMessageDeps?: SendMessageDeps;
|
|
360
|
-
private findConversation?: RuntimeHttpServerOptions["findConversation"];
|
|
361
|
-
private findConversationBySurfaceId?: RuntimeHttpServerOptions["findConversationBySurfaceId"];
|
|
362
|
-
private getSkillContext?: RuntimeHttpServerOptions["getSkillContext"];
|
|
363
|
-
private conversationManagementDeps?: RuntimeHttpServerOptions["conversationManagementDeps"];
|
|
364
|
-
private getModelSetContext?: RuntimeHttpServerOptions["getModelSetContext"];
|
|
365
|
-
private getRecordingDeps?: RuntimeHttpServerOptions["getRecordingDeps"];
|
|
366
|
-
private getCesClient?: RuntimeHttpServerOptions["getCesClient"];
|
|
367
|
-
private onProviderCredentialsChanged?: RuntimeHttpServerOptions["onProviderCredentialsChanged"];
|
|
368
|
-
private getHeartbeatService?: RuntimeHttpServerOptions["getHeartbeatService"];
|
|
369
|
-
private getFilingService?: RuntimeHttpServerOptions["getFilingService"];
|
|
217
|
+
|
|
218
|
+
private readonly liveVoiceSessionManager: LiveVoiceSessionManager;
|
|
370
219
|
private router: HttpRouter;
|
|
371
220
|
|
|
372
221
|
constructor(options: RuntimeHttpServerOptions = {}) {
|
|
373
222
|
this.port = options.port ?? DEFAULT_PORT;
|
|
374
223
|
this.hostname = options.hostname ?? DEFAULT_HOSTNAME;
|
|
375
|
-
|
|
376
|
-
this.processMessage = options.processMessage;
|
|
224
|
+
|
|
377
225
|
this.approvalCopyGenerator = options.approvalCopyGenerator;
|
|
378
226
|
this.approvalConversationGenerator = options.approvalConversationGenerator;
|
|
379
227
|
this.guardianActionCopyGenerator = options.guardianActionCopyGenerator;
|
|
380
228
|
this.guardianFollowUpConversationGenerator =
|
|
381
229
|
options.guardianFollowUpConversationGenerator;
|
|
382
|
-
this.
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
this.
|
|
386
|
-
this.getSkillContext = options.getSkillContext;
|
|
387
|
-
this.conversationManagementDeps = options.conversationManagementDeps;
|
|
388
|
-
this.getModelSetContext = options.getModelSetContext;
|
|
389
|
-
this.getRecordingDeps = options.getRecordingDeps;
|
|
390
|
-
this.getCesClient = options.getCesClient;
|
|
391
|
-
this.onProviderCredentialsChanged = options.onProviderCredentialsChanged;
|
|
392
|
-
this.getHeartbeatService = options.getHeartbeatService;
|
|
393
|
-
this.getFilingService = options.getFilingService;
|
|
394
|
-
this.router = new HttpRouter(this.buildRouteTable());
|
|
230
|
+
this.liveVoiceSessionManager = new LiveVoiceSessionManager({
|
|
231
|
+
createSession: (context) => createLiveVoiceSession(context),
|
|
232
|
+
});
|
|
233
|
+
this.router = new HttpRouter();
|
|
395
234
|
}
|
|
396
235
|
|
|
397
236
|
/** The port the server is actually listening on (resolved after start). */
|
|
@@ -399,40 +238,13 @@ export class RuntimeHttpServer {
|
|
|
399
238
|
return this.server?.port ?? this.port;
|
|
400
239
|
}
|
|
401
240
|
|
|
402
|
-
/** Expose the pairing store so the daemon server can wire HTTP handlers. */
|
|
403
|
-
getPairingStore(): PairingStore {
|
|
404
|
-
return this.pairingStore;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/** Set a callback for broadcasting server messages (wired by daemon server). */
|
|
408
|
-
setPairingBroadcast(fn: (msg: ServerMessage) => void): void {
|
|
409
|
-
this.pairingBroadcast = fn;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
private get pairingContext(): PairingHandlerContext {
|
|
413
|
-
const broadcast = this.pairingBroadcast;
|
|
414
|
-
return {
|
|
415
|
-
pairingStore: this.pairingStore,
|
|
416
|
-
bearerToken: this.bearerToken,
|
|
417
|
-
pairingBroadcast: broadcast
|
|
418
|
-
? (msg) => {
|
|
419
|
-
// Broadcast to all clients via the event hub so HTTP/SSE clients
|
|
420
|
-
// (e.g. macOS app) receive pairing approval requests.
|
|
421
|
-
broadcast(msg);
|
|
422
|
-
void assistantEventHub.publish(
|
|
423
|
-
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, msg),
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
: undefined,
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
|
|
430
241
|
async start(): Promise<void> {
|
|
431
242
|
type AllWebSocketData =
|
|
432
243
|
| RelayWebSocketData
|
|
433
244
|
| BrowserRelayWebSocketData
|
|
434
245
|
| MediaStreamWebSocketData
|
|
435
|
-
| SttStreamWebSocketData
|
|
246
|
+
| SttStreamWebSocketData
|
|
247
|
+
| LiveVoiceWebSocketData;
|
|
436
248
|
this.server = Bun.serve<AllWebSocketData>({
|
|
437
249
|
port: this.port,
|
|
438
250
|
hostname: this.hostname,
|
|
@@ -440,25 +252,8 @@ export class RuntimeHttpServer {
|
|
|
440
252
|
maxRequestBodySize: MAX_REQUEST_BODY_BYTES,
|
|
441
253
|
fetch: (req, server) => this.handleRequest(req, server),
|
|
442
254
|
websocket: {
|
|
443
|
-
open(ws) {
|
|
255
|
+
open: (ws) => {
|
|
444
256
|
const data = ws.data as AllWebSocketData;
|
|
445
|
-
if ("wsType" in data && data.wsType === "browser-relay") {
|
|
446
|
-
// When the JWT sub resolved to a guardian principal at upgrade
|
|
447
|
-
// time, register this connection with the chrome-extension
|
|
448
|
-
// registry so host_browser_request frames can be routed to it.
|
|
449
|
-
if (data.guardianId) {
|
|
450
|
-
const now = Date.now();
|
|
451
|
-
getChromeExtensionRegistry().register({
|
|
452
|
-
id: data.connectionId,
|
|
453
|
-
guardianId: data.guardianId,
|
|
454
|
-
clientInstanceId: data.clientInstanceId,
|
|
455
|
-
ws,
|
|
456
|
-
connectedAt: now,
|
|
457
|
-
lastActiveAt: now,
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
257
|
if ("wsType" in data && data.wsType === "media-stream") {
|
|
463
258
|
const msData = data as MediaStreamWebSocketData;
|
|
464
259
|
log.info(
|
|
@@ -547,6 +342,10 @@ export class RuntimeHttpServer {
|
|
|
547
342
|
);
|
|
548
343
|
return;
|
|
549
344
|
}
|
|
345
|
+
if ("wsType" in data && data.wsType === "live-voice") {
|
|
346
|
+
log.info("Live voice WebSocket opened");
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
550
349
|
const callSessionId = (data as RelayWebSocketData).callSessionId;
|
|
551
350
|
log.info({ callSessionId }, "ConversationRelay WebSocket opened");
|
|
552
351
|
if (callSessionId) {
|
|
@@ -557,7 +356,7 @@ export class RuntimeHttpServer {
|
|
|
557
356
|
activeRelayConnections.set(callSessionId, connection);
|
|
558
357
|
}
|
|
559
358
|
},
|
|
560
|
-
message(ws, message) {
|
|
359
|
+
message: (ws, message) => {
|
|
561
360
|
const data = ws.data as AllWebSocketData;
|
|
562
361
|
const raw =
|
|
563
362
|
typeof message === "string"
|
|
@@ -670,11 +469,7 @@ export class RuntimeHttpServer {
|
|
|
670
469
|
return;
|
|
671
470
|
}
|
|
672
471
|
case "keepalive": {
|
|
673
|
-
// Extension keepalive
|
|
674
|
-
// activity timestamp without producing log noise or
|
|
675
|
-
// altering routing semantics. Unknown extra keys on
|
|
676
|
-
// the frame are silently ignored (lenient validation).
|
|
677
|
-
getChromeExtensionRegistry().touch(data.connectionId);
|
|
472
|
+
// Extension keepalive — acknowledged, no action needed.
|
|
678
473
|
return;
|
|
679
474
|
}
|
|
680
475
|
default: {
|
|
@@ -708,23 +503,33 @@ export class RuntimeHttpServer {
|
|
|
708
503
|
}
|
|
709
504
|
return;
|
|
710
505
|
}
|
|
506
|
+
if ("wsType" in data && data.wsType === "live-voice") {
|
|
507
|
+
void this.handleLiveVoiceMessage(
|
|
508
|
+
ws as ServerWebSocket<LiveVoiceWebSocketData>,
|
|
509
|
+
message,
|
|
510
|
+
).catch((err) => {
|
|
511
|
+
log.warn(
|
|
512
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
513
|
+
"Live voice WebSocket message handler failed",
|
|
514
|
+
);
|
|
515
|
+
this.sendLiveVoiceError(
|
|
516
|
+
ws as ServerWebSocket<LiveVoiceWebSocketData>,
|
|
517
|
+
{
|
|
518
|
+
code: LiveVoiceProtocolErrorCode.InvalidFrame,
|
|
519
|
+
message: "Live voice frame handling failed",
|
|
520
|
+
},
|
|
521
|
+
);
|
|
522
|
+
});
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
711
525
|
const callSessionId = (data as RelayWebSocketData).callSessionId;
|
|
712
526
|
if (callSessionId) {
|
|
713
527
|
const connection = activeRelayConnections.get(callSessionId);
|
|
714
528
|
connection?.handleMessage(raw);
|
|
715
529
|
}
|
|
716
530
|
},
|
|
717
|
-
close(ws, code, reason) {
|
|
531
|
+
close: (ws, code, reason) => {
|
|
718
532
|
const data = ws.data as AllWebSocketData;
|
|
719
|
-
if ("wsType" in data && data.wsType === "browser-relay") {
|
|
720
|
-
// Always attempt to unregister — the registry uses connectionId
|
|
721
|
-
// as the key and no-ops if the entry is absent (e.g. when the
|
|
722
|
-
// connection was never registered because guardianId was
|
|
723
|
-
// undefined, or when it was superseded by a newer registration
|
|
724
|
-
// for the same guardian).
|
|
725
|
-
getChromeExtensionRegistry().unregister(data.connectionId);
|
|
726
|
-
return;
|
|
727
|
-
}
|
|
728
533
|
if ("wsType" in data && data.wsType === "media-stream") {
|
|
729
534
|
const msData = data as MediaStreamWebSocketData;
|
|
730
535
|
log.info(
|
|
@@ -775,6 +580,18 @@ export class RuntimeHttpServer {
|
|
|
775
580
|
}
|
|
776
581
|
return;
|
|
777
582
|
}
|
|
583
|
+
if ("wsType" in data && data.wsType === "live-voice") {
|
|
584
|
+
log.info(
|
|
585
|
+
{
|
|
586
|
+
sessionId: data.sessionId,
|
|
587
|
+
code,
|
|
588
|
+
reason: reason?.toString(),
|
|
589
|
+
},
|
|
590
|
+
"Live voice WebSocket closed",
|
|
591
|
+
);
|
|
592
|
+
this.releaseLiveVoiceSession(data, "websocket_close");
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
778
595
|
const callSessionId = (data as RelayWebSocketData).callSessionId;
|
|
779
596
|
log.info(
|
|
780
597
|
{ callSessionId, code, reason: reason?.toString() },
|
|
@@ -801,31 +618,25 @@ export class RuntimeHttpServer {
|
|
|
801
618
|
);
|
|
802
619
|
}
|
|
803
620
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
621
|
+
if (isHttpAuthDisabled()) {
|
|
622
|
+
if (getIsPlatform()) {
|
|
623
|
+
log.info(
|
|
624
|
+
"DISABLE_HTTP_AUTH is set — HTTP auth disabled (expected: platform handles auth)",
|
|
625
|
+
);
|
|
626
|
+
} else {
|
|
627
|
+
log.warn(
|
|
628
|
+
"DISABLE_HTTP_AUTH is set — HTTP API authentication is DISABLED. All API endpoints are accessible without a bearer token.",
|
|
629
|
+
);
|
|
630
|
+
}
|
|
814
631
|
}
|
|
815
632
|
|
|
816
633
|
log.info(
|
|
817
634
|
{
|
|
818
635
|
port: this.actualPort,
|
|
819
636
|
hostname: this.hostname,
|
|
820
|
-
auth: !!this.bearerToken,
|
|
821
637
|
},
|
|
822
638
|
"Runtime HTTP server listening",
|
|
823
639
|
);
|
|
824
|
-
|
|
825
|
-
// Advertise the actual port to thin helpers that need to reach the
|
|
826
|
-
// runtime without inheriting the daemon's environment (e.g. the
|
|
827
|
-
// chrome-extension native messaging helper, spawned by Chrome).
|
|
828
|
-
this.writeRuntimePortFile(this.actualPort);
|
|
829
640
|
}
|
|
830
641
|
|
|
831
642
|
/**
|
|
@@ -834,108 +645,27 @@ export class RuntimeHttpServer {
|
|
|
834
645
|
* Extracted from start() to allow future callers to defer sweep startup.
|
|
835
646
|
*/
|
|
836
647
|
private startBackgroundSweeps(): void {
|
|
837
|
-
if (
|
|
838
|
-
const pm = this.processMessage;
|
|
839
|
-
const mintBt = () => mintDaemonDeliveryToken();
|
|
648
|
+
if (!this.retrySweepTimer) {
|
|
840
649
|
this.retrySweepTimer = setInterval(() => {
|
|
841
650
|
if (this.sweepInProgress) return;
|
|
842
651
|
this.sweepInProgress = true;
|
|
843
|
-
sweepFailedEvents(
|
|
652
|
+
sweepFailedEvents(processMessage).finally(() => {
|
|
844
653
|
this.sweepInProgress = false;
|
|
845
654
|
});
|
|
846
655
|
}, 30_000);
|
|
847
656
|
}
|
|
848
657
|
|
|
849
|
-
startGuardianExpirySweep(
|
|
850
|
-
getGatewayInternalBaseUrl(),
|
|
851
|
-
() => mintDaemonDeliveryToken(),
|
|
852
|
-
this.approvalCopyGenerator,
|
|
853
|
-
);
|
|
658
|
+
startGuardianExpirySweep(this.approvalCopyGenerator);
|
|
854
659
|
log.info("Guardian approval expiry sweep started");
|
|
855
660
|
|
|
856
|
-
startGuardianActionSweep(
|
|
857
|
-
getGatewayInternalBaseUrl(),
|
|
858
|
-
() => mintDaemonDeliveryToken(),
|
|
859
|
-
this.guardianActionCopyGenerator,
|
|
860
|
-
);
|
|
661
|
+
startGuardianActionSweep(this.guardianActionCopyGenerator);
|
|
861
662
|
log.info("Guardian action expiry sweep started");
|
|
862
663
|
|
|
863
664
|
startCanonicalGuardianExpirySweep();
|
|
864
665
|
log.info("Canonical guardian request expiry sweep started");
|
|
865
666
|
}
|
|
866
667
|
|
|
867
|
-
/**
|
|
868
|
-
* Atomically publish the runtime HTTP port to ~/.vellum/runtime-port so
|
|
869
|
-
* external helpers can locate a non-default `RUNTIME_HTTP_PORT` without
|
|
870
|
-
* any manifest changes. Best-effort — write failures never block
|
|
871
|
-
* daemon startup (see assistant/AGENTS.md "Daemon startup philosophy").
|
|
872
|
-
*/
|
|
873
|
-
private writeRuntimePortFile(actualPort: number): void {
|
|
874
|
-
try {
|
|
875
|
-
const portFile = getRuntimePortFilePath();
|
|
876
|
-
const dir = dirname(portFile);
|
|
877
|
-
if (!existsSync(dir)) {
|
|
878
|
-
mkdirSync(dir, { recursive: true });
|
|
879
|
-
}
|
|
880
|
-
const tmpPath = `${portFile}.tmp.${process.pid}`;
|
|
881
|
-
writeFileSync(tmpPath, String(actualPort), { mode: 0o644 });
|
|
882
|
-
renameSync(tmpPath, portFile);
|
|
883
|
-
log.info({ portFile, actualPort }, "Wrote runtime port file");
|
|
884
|
-
} catch (err) {
|
|
885
|
-
log.warn(
|
|
886
|
-
{ err },
|
|
887
|
-
"Failed to write runtime port file; non-default assistant ports may require --assistant-port on thin helpers",
|
|
888
|
-
);
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
/**
|
|
893
|
-
* Remove the runtime port file written by `writeRuntimePortFile`.
|
|
894
|
-
* Called from `stop()` on clean shutdown so a stale file does not
|
|
895
|
-
* point thin helpers (e.g. the chrome-extension native messaging
|
|
896
|
-
* helper) at a dead port until the next daemon start overwrites it.
|
|
897
|
-
* Best-effort — unlink failures never block shutdown.
|
|
898
|
-
*
|
|
899
|
-
* The unlink is conditional: we only remove the file if its current
|
|
900
|
-
* contents still match this server's port. The runtime-port file
|
|
901
|
-
* lives at the user-home level (`~/.vellum/runtime-port`) and is
|
|
902
|
-
* therefore shared across multiple daemon instances running on
|
|
903
|
-
* different `RUNTIME_HTTP_PORT`s. If a sibling instance has already
|
|
904
|
-
* rewritten the file with its own port, deleting it would strand
|
|
905
|
-
* thin helpers on the default port `7821` and break their ability
|
|
906
|
-
* to reach the still-running sibling.
|
|
907
|
-
*
|
|
908
|
-
* Note: this only runs on graceful shutdown. A crash leaves the
|
|
909
|
-
* file in place; the next successful startup overwrites it.
|
|
910
|
-
*/
|
|
911
|
-
private removeRuntimePortFile(): void {
|
|
912
|
-
try {
|
|
913
|
-
const portFile = getRuntimePortFilePath();
|
|
914
|
-
if (!existsSync(portFile)) return;
|
|
915
|
-
// Read-then-compare-then-unlink. Race-safe enough: the worst case
|
|
916
|
-
// is that another instance writes the file between our read and
|
|
917
|
-
// our unlink, in which case we erroneously delete its mapping.
|
|
918
|
-
// That window is short (a few microseconds) and a sibling startup
|
|
919
|
-
// will rewrite the file on its next port-publish call. The much
|
|
920
|
-
// more common multi-instance race — sibling already overwrote
|
|
921
|
-
// before our stop() runs — is correctly handled here as a no-op.
|
|
922
|
-
const current = readFileSync(portFile, "utf-8").trim();
|
|
923
|
-
if (current !== String(this.actualPort)) {
|
|
924
|
-
log.info(
|
|
925
|
-
{ portFile, current, actualPort: this.actualPort },
|
|
926
|
-
"Leaving runtime port file alone — owned by another instance",
|
|
927
|
-
);
|
|
928
|
-
return;
|
|
929
|
-
}
|
|
930
|
-
unlinkSync(portFile);
|
|
931
|
-
log.info({ portFile }, "Removed runtime port file");
|
|
932
|
-
} catch (err) {
|
|
933
|
-
log.warn({ err }, "Failed to remove runtime port file");
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
|
|
937
668
|
async stop(): Promise<void> {
|
|
938
|
-
this.pairingStore.stop();
|
|
939
669
|
stopGuardianExpirySweep();
|
|
940
670
|
stopGuardianActionSweep();
|
|
941
671
|
stopCanonicalGuardianExpirySweep();
|
|
@@ -952,12 +682,19 @@ export class RuntimeHttpServer {
|
|
|
952
682
|
activeSttStreamSessions.delete(sessionId);
|
|
953
683
|
}
|
|
954
684
|
|
|
685
|
+
const liveVoiceSessionId = this.liveVoiceSessionManager.activeSessionId;
|
|
686
|
+
if (liveVoiceSessionId) {
|
|
687
|
+
await this.liveVoiceSessionManager.releaseSession(
|
|
688
|
+
liveVoiceSessionId,
|
|
689
|
+
"manager_shutdown",
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
|
|
955
693
|
if (this.server) {
|
|
956
694
|
this.server.stop(true);
|
|
957
695
|
this.server = null;
|
|
958
696
|
log.info("Runtime HTTP server stopped");
|
|
959
697
|
}
|
|
960
|
-
this.removeRuntimePortFile();
|
|
961
698
|
}
|
|
962
699
|
|
|
963
700
|
private async handleRequest(
|
|
@@ -1026,43 +763,48 @@ export class RuntimeHttpServer {
|
|
|
1026
763
|
return this.handleSttStreamUpgrade(req, server);
|
|
1027
764
|
}
|
|
1028
765
|
|
|
766
|
+
// WebSocket upgrade for live voice — same private-network restrictions
|
|
767
|
+
// and gateway-service token verification as STT streaming.
|
|
768
|
+
if (
|
|
769
|
+
path === "/v1/live-voice" &&
|
|
770
|
+
req.headers.get("upgrade")?.toLowerCase() === "websocket"
|
|
771
|
+
) {
|
|
772
|
+
return this.handleLiveVoiceUpgrade(req, server);
|
|
773
|
+
}
|
|
774
|
+
|
|
1029
775
|
// Twilio webhook endpoints — before auth check because Twilio
|
|
1030
776
|
// webhook POSTs don't include bearer tokens.
|
|
1031
777
|
const twilioResponse = await this.handleTwilioWebhook(req, path);
|
|
1032
778
|
if (twilioResponse) return twilioResponse;
|
|
1033
779
|
|
|
1034
780
|
// Audio serving endpoint — before auth check because Twilio
|
|
1035
|
-
// fetches these URLs directly
|
|
781
|
+
// fetches these URLs directly (isPublic route, ATL-314).
|
|
1036
782
|
const audioMatch = path.match(/^\/v1\/audio\/([^/]+)$/);
|
|
1037
783
|
if (audioMatch && req.method === "GET") {
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
return await handleGuardianBootstrap(req, server);
|
|
1063
|
-
}
|
|
1064
|
-
if (path === "/v1/guardian/refresh" && req.method === "POST") {
|
|
1065
|
-
return await handleGuardianRefresh(req);
|
|
784
|
+
const audioDef = AUDIO_ROUTES.find((r) => r.operationId === "audio_get")!;
|
|
785
|
+
const args = { pathParams: { audioId: audioMatch[1] } };
|
|
786
|
+
try {
|
|
787
|
+
const result = await audioDef.handler(args);
|
|
788
|
+
const headers =
|
|
789
|
+
typeof audioDef.responseHeaders === "function"
|
|
790
|
+
? audioDef.responseHeaders(args)
|
|
791
|
+
: audioDef.responseHeaders;
|
|
792
|
+
if (result instanceof ReadableStream) {
|
|
793
|
+
return new Response(result as ReadableStream<Uint8Array>, {
|
|
794
|
+
headers,
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
return new Response(result as BodyInit, { headers });
|
|
798
|
+
} catch (err) {
|
|
799
|
+
if (err instanceof RouteError) {
|
|
800
|
+
return httpError(
|
|
801
|
+
err.code as HttpErrorCode,
|
|
802
|
+
err.message,
|
|
803
|
+
err.statusCode,
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
throw err;
|
|
807
|
+
}
|
|
1066
808
|
}
|
|
1067
809
|
|
|
1068
810
|
// Skill-registered routes (e.g. meet-bot event ingress). Handled before
|
|
@@ -1092,7 +834,7 @@ export class RuntimeHttpServer {
|
|
|
1092
834
|
const normalizedPath = path.endsWith("/") ? path.slice(0, -1) : path;
|
|
1093
835
|
const authResult =
|
|
1094
836
|
normalizedPath === "/v1/host-browser-result" && req.method === "POST"
|
|
1095
|
-
? authenticateHostBrowserResultRequest(req)
|
|
837
|
+
? await authenticateHostBrowserResultRequest(req)
|
|
1096
838
|
: authenticateRequest(req);
|
|
1097
839
|
if (!authResult.ok) {
|
|
1098
840
|
return authResult.response;
|
|
@@ -1102,9 +844,18 @@ export class RuntimeHttpServer {
|
|
|
1102
844
|
// Serve shareable app pages (outside /v1/ namespace, no rate limiting)
|
|
1103
845
|
const pagesMatch = path.match(/^\/pages\/([^/]+)$/);
|
|
1104
846
|
if (pagesMatch && req.method === "GET") {
|
|
1105
|
-
return withErrorHandling("pages", async () =>
|
|
1106
|
-
|
|
1107
|
-
|
|
847
|
+
return withErrorHandling("pages", async () => {
|
|
848
|
+
const pageDef = APP_ROUTES.find(
|
|
849
|
+
(r) => r.operationId === "pages_serve",
|
|
850
|
+
)!;
|
|
851
|
+
const args = { pathParams: { appId: pagesMatch[1] } };
|
|
852
|
+
const body = pageDef.handler(args) as string;
|
|
853
|
+
const headers =
|
|
854
|
+
typeof pageDef.responseHeaders === "function"
|
|
855
|
+
? pageDef.responseHeaders(args)
|
|
856
|
+
: pageDef.responseHeaders;
|
|
857
|
+
return new Response(body, { headers });
|
|
858
|
+
});
|
|
1108
859
|
}
|
|
1109
860
|
|
|
1110
861
|
// Per-client-IP rate limiting for /v1/* endpoints. Authenticated requests
|
|
@@ -1166,10 +917,10 @@ export class RuntimeHttpServer {
|
|
|
1166
917
|
return routerResponse ?? httpError("NOT_FOUND", "Not found", 404);
|
|
1167
918
|
}
|
|
1168
919
|
|
|
1169
|
-
private handleBrowserRelayUpgrade(
|
|
920
|
+
private async handleBrowserRelayUpgrade(
|
|
1170
921
|
req: Request,
|
|
1171
922
|
server: ReturnType<typeof Bun.serve>,
|
|
1172
|
-
): Response {
|
|
923
|
+
): Promise<Response> {
|
|
1173
924
|
if (
|
|
1174
925
|
!isLoopbackHost(new URL(req.url).hostname) &&
|
|
1175
926
|
!isPrivateNetworkPeer(server, req)
|
|
@@ -1185,8 +936,8 @@ export class RuntimeHttpServer {
|
|
|
1185
936
|
// `/v1/browser-relay` handshake:
|
|
1186
937
|
//
|
|
1187
938
|
// 1. **Capability token** — a signed `host_browser_command`
|
|
1188
|
-
// capability minted by
|
|
1189
|
-
//
|
|
939
|
+
// capability minted by the gateway and handed to the chrome
|
|
940
|
+
// extension by the native-messaging pair flow
|
|
1190
941
|
// (`/v1/browser-extension-pair`). This is the preferred,
|
|
1191
942
|
// self-hosted default: the extension never has to touch a
|
|
1192
943
|
// gateway JWT.
|
|
@@ -1235,7 +986,7 @@ export class RuntimeHttpServer {
|
|
|
1235
986
|
// messaging pair flow. We derive `guardianId` from the
|
|
1236
987
|
// capability claims directly — the claims are HMAC-signed by
|
|
1237
988
|
// the same daemon so there is no cross-tenant risk.
|
|
1238
|
-
const capabilityClaims = verifyHostBrowserCapability(token);
|
|
989
|
+
const capabilityClaims = await verifyHostBrowserCapability(token);
|
|
1239
990
|
if (capabilityClaims) {
|
|
1240
991
|
guardianId = capabilityClaims.guardianId;
|
|
1241
992
|
} else {
|
|
@@ -1266,9 +1017,7 @@ export class RuntimeHttpServer {
|
|
|
1266
1017
|
guardianId = fallbackGuardianId;
|
|
1267
1018
|
} else {
|
|
1268
1019
|
// Fail closed: a service-token relay upgrade without a
|
|
1269
|
-
// guardian context cannot be routed safely.
|
|
1270
|
-
// upgrade to proceed creates an unscoped socket that never
|
|
1271
|
-
// registers in the ChromeExtensionRegistry.
|
|
1020
|
+
// guardian context cannot be routed safely.
|
|
1272
1021
|
log.warn(
|
|
1273
1022
|
{
|
|
1274
1023
|
principalType: subResult.ok
|
|
@@ -1304,6 +1053,28 @@ export class RuntimeHttpServer {
|
|
|
1304
1053
|
return undefined!;
|
|
1305
1054
|
}
|
|
1306
1055
|
|
|
1056
|
+
private verifyGatewayServiceToken(req: Request): Response | null {
|
|
1057
|
+
if (isHttpAuthDisabled()) return null;
|
|
1058
|
+
|
|
1059
|
+
const wsUrl = new URL(req.url);
|
|
1060
|
+
const token = wsUrl.searchParams.get("token");
|
|
1061
|
+
if (!token) {
|
|
1062
|
+
return httpError("UNAUTHORIZED", "Unauthorized", 401);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
const jwtResult = verifyToken(token, "vellum-daemon");
|
|
1066
|
+
if (!jwtResult.ok) {
|
|
1067
|
+
return httpError("UNAUTHORIZED", "Unauthorized", 401);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
const subResult = parseSub(jwtResult.claims.sub);
|
|
1071
|
+
if (!subResult.ok || subResult.principalType !== "svc_gateway") {
|
|
1072
|
+
return httpError("UNAUTHORIZED", "Unauthorized", 401);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
return null;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1307
1078
|
private handleRelayUpgrade(
|
|
1308
1079
|
req: Request,
|
|
1309
1080
|
server: ReturnType<typeof Bun.serve>,
|
|
@@ -1316,6 +1087,10 @@ export class RuntimeHttpServer {
|
|
|
1316
1087
|
);
|
|
1317
1088
|
}
|
|
1318
1089
|
|
|
1090
|
+
// Verify the gateway service token before accepting the upgrade.
|
|
1091
|
+
const tokenError = this.verifyGatewayServiceToken(req);
|
|
1092
|
+
if (tokenError) return tokenError;
|
|
1093
|
+
|
|
1319
1094
|
const wsUrl = new URL(req.url);
|
|
1320
1095
|
const callSessionId = wsUrl.searchParams.get("callSessionId");
|
|
1321
1096
|
if (!callSessionId) {
|
|
@@ -1341,6 +1116,10 @@ export class RuntimeHttpServer {
|
|
|
1341
1116
|
);
|
|
1342
1117
|
}
|
|
1343
1118
|
|
|
1119
|
+
// Verify the gateway service token before accepting the upgrade.
|
|
1120
|
+
const tokenError = this.verifyGatewayServiceToken(req);
|
|
1121
|
+
if (tokenError) return tokenError;
|
|
1122
|
+
|
|
1344
1123
|
const wsUrl = new URL(req.url);
|
|
1345
1124
|
const callSessionId = wsUrl.searchParams.get("callSessionId");
|
|
1346
1125
|
if (!callSessionId) {
|
|
@@ -1382,23 +1161,8 @@ export class RuntimeHttpServer {
|
|
|
1382
1161
|
}
|
|
1383
1162
|
|
|
1384
1163
|
// Verify the gateway service token before accepting the upgrade.
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
const token = wsUrl.searchParams.get("token");
|
|
1388
|
-
if (!token) {
|
|
1389
|
-
return httpError("UNAUTHORIZED", "Unauthorized", 401);
|
|
1390
|
-
}
|
|
1391
|
-
const jwtResult = verifyToken(token, "vellum-daemon");
|
|
1392
|
-
if (!jwtResult.ok) {
|
|
1393
|
-
return httpError("UNAUTHORIZED", "Unauthorized", 401);
|
|
1394
|
-
}
|
|
1395
|
-
// Accept gateway service tokens (svc:gateway:*) — these are the
|
|
1396
|
-
// only tokens the gateway mints for upstream connections.
|
|
1397
|
-
const subResult = parseSub(jwtResult.claims.sub);
|
|
1398
|
-
if (!subResult.ok || subResult.principalType !== "svc_gateway") {
|
|
1399
|
-
return httpError("UNAUTHORIZED", "Unauthorized", 401);
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1164
|
+
const tokenError = this.verifyGatewayServiceToken(req);
|
|
1165
|
+
if (tokenError) return tokenError;
|
|
1402
1166
|
|
|
1403
1167
|
const wsUrl = new URL(req.url);
|
|
1404
1168
|
// provider is optional compatibility metadata — the runtime resolves
|
|
@@ -1431,6 +1195,175 @@ export class RuntimeHttpServer {
|
|
|
1431
1195
|
return undefined!;
|
|
1432
1196
|
}
|
|
1433
1197
|
|
|
1198
|
+
/**
|
|
1199
|
+
* Handle WebSocket upgrade for `/v1/live-voice`.
|
|
1200
|
+
*
|
|
1201
|
+
* The gateway owns downstream client auth and forwards this upstream with
|
|
1202
|
+
* a short-lived gateway service token. The runtime accepts only private
|
|
1203
|
+
* network peers/origins so the shell is not publicly reachable.
|
|
1204
|
+
*/
|
|
1205
|
+
private handleLiveVoiceUpgrade(
|
|
1206
|
+
req: Request,
|
|
1207
|
+
server: ReturnType<typeof Bun.serve>,
|
|
1208
|
+
): Response {
|
|
1209
|
+
if (!isPrivateNetworkPeer(server, req) || !isPrivateNetworkOrigin(req)) {
|
|
1210
|
+
return httpError(
|
|
1211
|
+
"FORBIDDEN",
|
|
1212
|
+
"Direct live voice access disabled — only private network peers allowed",
|
|
1213
|
+
403,
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
const tokenError = this.verifyGatewayServiceToken(req);
|
|
1218
|
+
if (tokenError) return tokenError;
|
|
1219
|
+
|
|
1220
|
+
const upgraded = server.upgrade(req, {
|
|
1221
|
+
data: {
|
|
1222
|
+
wsType: "live-voice",
|
|
1223
|
+
lastSeq: 0,
|
|
1224
|
+
} satisfies LiveVoiceWebSocketData,
|
|
1225
|
+
});
|
|
1226
|
+
if (!upgraded) {
|
|
1227
|
+
return new Response("WebSocket upgrade failed", { status: 500 });
|
|
1228
|
+
}
|
|
1229
|
+
return undefined!;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
private async handleLiveVoiceMessage(
|
|
1233
|
+
ws: ServerWebSocket<LiveVoiceWebSocketData>,
|
|
1234
|
+
message: string | ArrayBuffer | ArrayBufferView,
|
|
1235
|
+
): Promise<void> {
|
|
1236
|
+
if (typeof message === "string") {
|
|
1237
|
+
const result = parseLiveVoiceClientTextFrame(message);
|
|
1238
|
+
if (!result.ok) {
|
|
1239
|
+
this.sendLiveVoiceError(ws, result.error);
|
|
1240
|
+
return;
|
|
1241
|
+
}
|
|
1242
|
+
await this.dispatchLiveVoiceClientFrame(ws, result.frame);
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
const result = parseLiveVoiceBinaryAudioFrame(message);
|
|
1247
|
+
if (!result.ok) {
|
|
1248
|
+
this.sendLiveVoiceError(ws, result.error);
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
const sessionId = ws.data.sessionId;
|
|
1253
|
+
if (!sessionId) {
|
|
1254
|
+
this.sendLiveVoiceStateError(
|
|
1255
|
+
ws,
|
|
1256
|
+
"Live voice binary audio received before start",
|
|
1257
|
+
);
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
const handled = await this.liveVoiceSessionManager.handleBinaryAudio(
|
|
1262
|
+
sessionId,
|
|
1263
|
+
result.frame.data,
|
|
1264
|
+
);
|
|
1265
|
+
if (handled.status === "not_found") {
|
|
1266
|
+
ws.data.sessionId = undefined;
|
|
1267
|
+
this.sendLiveVoiceStateError(ws, "Live voice session is not active");
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
private async dispatchLiveVoiceClientFrame(
|
|
1272
|
+
ws: ServerWebSocket<LiveVoiceWebSocketData>,
|
|
1273
|
+
frame: LiveVoiceClientFrame,
|
|
1274
|
+
): Promise<void> {
|
|
1275
|
+
if (frame.type === "start") {
|
|
1276
|
+
if (ws.data.sessionId) {
|
|
1277
|
+
this.sendLiveVoiceStateError(ws, "Live voice session already started");
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
const result = await this.liveVoiceSessionManager.startSession(frame, {
|
|
1282
|
+
sendFrame: async (serverFrame) => {
|
|
1283
|
+
this.sendLiveVoiceFrame(ws, serverFrame);
|
|
1284
|
+
},
|
|
1285
|
+
});
|
|
1286
|
+
if (result.status === "accepted") {
|
|
1287
|
+
ws.data.sessionId = result.sessionId;
|
|
1288
|
+
}
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
const sessionId = ws.data.sessionId;
|
|
1293
|
+
if (!sessionId) {
|
|
1294
|
+
this.sendLiveVoiceStateError(
|
|
1295
|
+
ws,
|
|
1296
|
+
`Live voice ${frame.type} frame received before start`,
|
|
1297
|
+
);
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
const handled = await this.liveVoiceSessionManager.handleClientFrame(
|
|
1302
|
+
sessionId,
|
|
1303
|
+
frame,
|
|
1304
|
+
);
|
|
1305
|
+
if (handled.status === "not_found") {
|
|
1306
|
+
ws.data.sessionId = undefined;
|
|
1307
|
+
this.sendLiveVoiceStateError(ws, "Live voice session is not active");
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
if (frame.type === "end") {
|
|
1312
|
+
ws.data.sessionId = undefined;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
private sendLiveVoiceStateError(
|
|
1317
|
+
ws: ServerWebSocket<LiveVoiceWebSocketData>,
|
|
1318
|
+
message: string,
|
|
1319
|
+
): void {
|
|
1320
|
+
this.sendLiveVoiceError(ws, {
|
|
1321
|
+
code: LiveVoiceProtocolErrorCode.InvalidFrame,
|
|
1322
|
+
message,
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
private sendLiveVoiceError(
|
|
1327
|
+
ws: ServerWebSocket<LiveVoiceWebSocketData>,
|
|
1328
|
+
error: Pick<LiveVoiceProtocolError, "code" | "message">,
|
|
1329
|
+
): void {
|
|
1330
|
+
this.sendLiveVoiceFrame(ws, {
|
|
1331
|
+
type: "error",
|
|
1332
|
+
seq: ws.data.lastSeq + 1,
|
|
1333
|
+
code: error.code,
|
|
1334
|
+
message: error.message,
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
private sendLiveVoiceFrame(
|
|
1339
|
+
ws: ServerWebSocket<LiveVoiceWebSocketData>,
|
|
1340
|
+
frame: LiveVoiceServerFrame,
|
|
1341
|
+
): void {
|
|
1342
|
+
ws.data.lastSeq = Math.max(ws.data.lastSeq, frame.seq);
|
|
1343
|
+
ws.send(JSON.stringify(frame));
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
private releaseLiveVoiceSession(
|
|
1347
|
+
data: LiveVoiceWebSocketData,
|
|
1348
|
+
reason: "websocket_close",
|
|
1349
|
+
): void {
|
|
1350
|
+
const sessionId = data.sessionId;
|
|
1351
|
+
data.sessionId = undefined;
|
|
1352
|
+
if (!sessionId) return;
|
|
1353
|
+
|
|
1354
|
+
void this.liveVoiceSessionManager
|
|
1355
|
+
.releaseSession(sessionId, reason)
|
|
1356
|
+
.catch((err) => {
|
|
1357
|
+
log.warn(
|
|
1358
|
+
{
|
|
1359
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1360
|
+
sessionId,
|
|
1361
|
+
},
|
|
1362
|
+
"Failed to release live voice session",
|
|
1363
|
+
);
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1434
1367
|
private async handleTwilioWebhook(
|
|
1435
1368
|
req: Request,
|
|
1436
1369
|
path: string,
|
|
@@ -1470,762 +1403,4 @@ export class RuntimeHttpServer {
|
|
|
1470
1403
|
|
|
1471
1404
|
return null;
|
|
1472
1405
|
}
|
|
1473
|
-
|
|
1474
|
-
private handleGetInterface(interfacePath: string): Response {
|
|
1475
|
-
if (!this.interfacesDir) {
|
|
1476
|
-
return httpError("NOT_FOUND", "Interface not found", 404);
|
|
1477
|
-
}
|
|
1478
|
-
const fullPath = resolve(this.interfacesDir, interfacePath);
|
|
1479
|
-
if (
|
|
1480
|
-
(fullPath !== this.interfacesDir &&
|
|
1481
|
-
!fullPath.startsWith(this.interfacesDir + "/")) ||
|
|
1482
|
-
!existsSync(fullPath)
|
|
1483
|
-
) {
|
|
1484
|
-
return httpError("NOT_FOUND", "Interface not found", 404);
|
|
1485
|
-
}
|
|
1486
|
-
const source = readFileSync(fullPath, "utf-8");
|
|
1487
|
-
return new Response(source, {
|
|
1488
|
-
headers: { "Content-Type": "text/plain; charset=utf-8" },
|
|
1489
|
-
});
|
|
1490
|
-
}
|
|
1491
|
-
|
|
1492
|
-
private buildAssistantAttention(attentionState: AttentionState | undefined):
|
|
1493
|
-
| {
|
|
1494
|
-
hasUnseenLatestAssistantMessage: boolean;
|
|
1495
|
-
latestAssistantMessageAt?: number;
|
|
1496
|
-
lastSeenAssistantMessageAt?: number;
|
|
1497
|
-
lastSeenConfidence?: Confidence;
|
|
1498
|
-
lastSeenSignalType?: SignalType;
|
|
1499
|
-
}
|
|
1500
|
-
| undefined {
|
|
1501
|
-
if (!attentionState) return undefined;
|
|
1502
|
-
|
|
1503
|
-
return {
|
|
1504
|
-
hasUnseenLatestAssistantMessage:
|
|
1505
|
-
attentionState.latestAssistantMessageAt != null &&
|
|
1506
|
-
(attentionState.lastSeenAssistantMessageAt == null ||
|
|
1507
|
-
attentionState.lastSeenAssistantMessageAt <
|
|
1508
|
-
attentionState.latestAssistantMessageAt),
|
|
1509
|
-
...(attentionState.latestAssistantMessageAt != null
|
|
1510
|
-
? {
|
|
1511
|
-
latestAssistantMessageAt: attentionState.latestAssistantMessageAt,
|
|
1512
|
-
}
|
|
1513
|
-
: {}),
|
|
1514
|
-
...(attentionState.lastSeenAssistantMessageAt != null
|
|
1515
|
-
? {
|
|
1516
|
-
lastSeenAssistantMessageAt:
|
|
1517
|
-
attentionState.lastSeenAssistantMessageAt,
|
|
1518
|
-
}
|
|
1519
|
-
: {}),
|
|
1520
|
-
...(attentionState.lastSeenConfidence != null
|
|
1521
|
-
? { lastSeenConfidence: attentionState.lastSeenConfidence }
|
|
1522
|
-
: {}),
|
|
1523
|
-
...(attentionState.lastSeenSignalType != null
|
|
1524
|
-
? { lastSeenSignalType: attentionState.lastSeenSignalType }
|
|
1525
|
-
: {}),
|
|
1526
|
-
};
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
private buildForkParent(
|
|
1530
|
-
conversation: ConversationRow,
|
|
1531
|
-
parentCache: Map<string, ConversationRow | null>,
|
|
1532
|
-
): { conversationId: string; messageId: string; title: string } | undefined {
|
|
1533
|
-
const parentConversationId = conversation.forkParentConversationId;
|
|
1534
|
-
const parentMessageId = conversation.forkParentMessageId;
|
|
1535
|
-
if (!parentConversationId || !parentMessageId) return undefined;
|
|
1536
|
-
|
|
1537
|
-
let parentConversation: ConversationRow | null | undefined =
|
|
1538
|
-
parentCache.get(parentConversationId);
|
|
1539
|
-
if (parentConversation === undefined) {
|
|
1540
|
-
parentConversation = getConversation(parentConversationId);
|
|
1541
|
-
parentCache.set(parentConversationId, parentConversation);
|
|
1542
|
-
}
|
|
1543
|
-
if (
|
|
1544
|
-
!parentConversation ||
|
|
1545
|
-
parentConversation.conversationType === "private"
|
|
1546
|
-
) {
|
|
1547
|
-
return undefined;
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
|
-
return {
|
|
1551
|
-
conversationId: parentConversationId,
|
|
1552
|
-
messageId: parentMessageId,
|
|
1553
|
-
title: parentConversation.title ?? "Untitled",
|
|
1554
|
-
};
|
|
1555
|
-
}
|
|
1556
|
-
|
|
1557
|
-
private serializeConversationSummary(params: {
|
|
1558
|
-
conversation: ConversationRow;
|
|
1559
|
-
binding?: ExternalConversationBinding | null;
|
|
1560
|
-
attentionState?: AttentionState;
|
|
1561
|
-
displayMeta?: {
|
|
1562
|
-
displayOrder: number | null;
|
|
1563
|
-
isPinned: boolean;
|
|
1564
|
-
groupId: string | null;
|
|
1565
|
-
};
|
|
1566
|
-
parentCache: Map<string, ConversationRow | null>;
|
|
1567
|
-
}) {
|
|
1568
|
-
const { conversation, binding, attentionState, displayMeta, parentCache } =
|
|
1569
|
-
params;
|
|
1570
|
-
const originChannel = parseChannelId(conversation.originChannel);
|
|
1571
|
-
const assistantAttention = this.buildAssistantAttention(attentionState);
|
|
1572
|
-
const forkParent = this.buildForkParent(conversation, parentCache);
|
|
1573
|
-
|
|
1574
|
-
return {
|
|
1575
|
-
id: conversation.id,
|
|
1576
|
-
title: conversation.title ?? "Untitled",
|
|
1577
|
-
createdAt: conversation.createdAt,
|
|
1578
|
-
updatedAt: conversation.updatedAt,
|
|
1579
|
-
lastMessageAt: conversation.lastMessageAt,
|
|
1580
|
-
conversationType: conversation.conversationType ?? "standard",
|
|
1581
|
-
source: conversation.source ?? "user",
|
|
1582
|
-
hostAccess: conversation.hostAccess === 1,
|
|
1583
|
-
...(conversation.scheduleJobId
|
|
1584
|
-
? { scheduleJobId: conversation.scheduleJobId }
|
|
1585
|
-
: {}),
|
|
1586
|
-
...(binding
|
|
1587
|
-
? {
|
|
1588
|
-
channelBinding: {
|
|
1589
|
-
sourceChannel: binding.sourceChannel,
|
|
1590
|
-
externalChatId: binding.externalChatId,
|
|
1591
|
-
externalUserId: binding.externalUserId,
|
|
1592
|
-
displayName: binding.displayName,
|
|
1593
|
-
username: binding.username,
|
|
1594
|
-
},
|
|
1595
|
-
}
|
|
1596
|
-
: {}),
|
|
1597
|
-
...(originChannel ? { conversationOriginChannel: originChannel } : {}),
|
|
1598
|
-
...(assistantAttention ? { assistantAttention } : {}),
|
|
1599
|
-
...(displayMeta?.isPinned
|
|
1600
|
-
? {
|
|
1601
|
-
isPinned: true as const,
|
|
1602
|
-
displayOrder: displayMeta.displayOrder,
|
|
1603
|
-
}
|
|
1604
|
-
: displayMeta?.displayOrder != null
|
|
1605
|
-
? {
|
|
1606
|
-
displayOrder: displayMeta.displayOrder,
|
|
1607
|
-
}
|
|
1608
|
-
: {}),
|
|
1609
|
-
groupId: displayMeta?.groupId ?? null,
|
|
1610
|
-
...(forkParent ? { forkParent } : {}),
|
|
1611
|
-
...(conversation.archivedAt != null
|
|
1612
|
-
? { archivedAt: conversation.archivedAt }
|
|
1613
|
-
: {}),
|
|
1614
|
-
};
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
private buildConversationDetailResponse(conversationId: string) {
|
|
1618
|
-
const conversation = getConversation(conversationId);
|
|
1619
|
-
if (!conversation) {
|
|
1620
|
-
return null;
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
const bindings = externalConversationStore.getBindingsForConversations([
|
|
1624
|
-
conversation.id,
|
|
1625
|
-
]);
|
|
1626
|
-
const attentionStates = getAttentionStateByConversationIds([
|
|
1627
|
-
conversation.id,
|
|
1628
|
-
]);
|
|
1629
|
-
const displayMeta = getDisplayMetaForConversations([conversation.id]);
|
|
1630
|
-
const parentCache = new Map<string, ConversationRow | null>();
|
|
1631
|
-
|
|
1632
|
-
return {
|
|
1633
|
-
conversation: this.serializeConversationSummary({
|
|
1634
|
-
conversation,
|
|
1635
|
-
binding: bindings.get(conversation.id),
|
|
1636
|
-
attentionState: attentionStates.get(conversation.id),
|
|
1637
|
-
displayMeta: displayMeta.get(conversation.id),
|
|
1638
|
-
parentCache,
|
|
1639
|
-
}),
|
|
1640
|
-
};
|
|
1641
|
-
}
|
|
1642
|
-
|
|
1643
|
-
private getConversationManagementRouteDeps(): ConversationManagementDeps | null {
|
|
1644
|
-
if (!this.conversationManagementDeps) {
|
|
1645
|
-
return null;
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
return {
|
|
1649
|
-
...this.conversationManagementDeps,
|
|
1650
|
-
forkConversation:
|
|
1651
|
-
this.conversationManagementDeps.forkConversation ??
|
|
1652
|
-
(async ({ conversationId, throughMessageId }) => {
|
|
1653
|
-
const forkedConversation = forkConversationInStore({
|
|
1654
|
-
conversationId,
|
|
1655
|
-
throughMessageId,
|
|
1656
|
-
});
|
|
1657
|
-
const detail = this.buildConversationDetailResponse(
|
|
1658
|
-
forkedConversation.id,
|
|
1659
|
-
);
|
|
1660
|
-
if (!detail) {
|
|
1661
|
-
throw new Error(
|
|
1662
|
-
`Forked conversation ${forkedConversation.id} could not be loaded`,
|
|
1663
|
-
);
|
|
1664
|
-
}
|
|
1665
|
-
return detail.conversation;
|
|
1666
|
-
}),
|
|
1667
|
-
};
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
|
-
// ---------------------------------------------------------------------------
|
|
1671
|
-
// Declarative route table
|
|
1672
|
-
// ---------------------------------------------------------------------------
|
|
1673
|
-
|
|
1674
|
-
/**
|
|
1675
|
-
* Build the full set of route definitions. Routes are matched in order,
|
|
1676
|
-
* so more specific patterns (e.g. `calls/:id/cancel`) must precede
|
|
1677
|
-
* more general ones (e.g. `calls/:id`).
|
|
1678
|
-
*
|
|
1679
|
-
* Each domain's routes are defined in their own module under
|
|
1680
|
-
* `./routes/` and composed here via spread. The composition order
|
|
1681
|
-
* preserves the original top-to-bottom matching semantics.
|
|
1682
|
-
*/
|
|
1683
|
-
private buildRouteTable(): RouteDefinition[] {
|
|
1684
|
-
const assistantId = DAEMON_INTERNAL_ASSISTANT_ID;
|
|
1685
|
-
const conversationManagementDeps =
|
|
1686
|
-
this.getConversationManagementRouteDeps();
|
|
1687
|
-
|
|
1688
|
-
return [
|
|
1689
|
-
...pairingRouteDefinitions({
|
|
1690
|
-
getPairingContext: () => this.pairingContext,
|
|
1691
|
-
}),
|
|
1692
|
-
...appRouteDefinitions(),
|
|
1693
|
-
...appManagementRouteDefinitions(),
|
|
1694
|
-
...secretRouteDefinitions({
|
|
1695
|
-
getCesClient: this.getCesClient,
|
|
1696
|
-
onProviderCredentialsChanged: this.onProviderCredentialsChanged,
|
|
1697
|
-
}),
|
|
1698
|
-
...identityRouteDefinitions(),
|
|
1699
|
-
...upgradeBroadcastRouteDefinitions(),
|
|
1700
|
-
...workspaceCommitRouteDefinitions(),
|
|
1701
|
-
...migrationRollbackRouteDefinitions(),
|
|
1702
|
-
...debugRouteDefinitions(),
|
|
1703
|
-
...usageRouteDefinitions(),
|
|
1704
|
-
...telemetryRouteDefinitions(),
|
|
1705
|
-
...workspaceRouteDefinitions(),
|
|
1706
|
-
...memoryItemRouteDefinitions(),
|
|
1707
|
-
...conversationStarterRouteDefinitions(),
|
|
1708
|
-
...settingsRouteDefinitions(),
|
|
1709
|
-
...avatarRouteDefinitions(),
|
|
1710
|
-
...scheduleRouteDefinitions({
|
|
1711
|
-
sendMessageDeps: this.sendMessageDeps,
|
|
1712
|
-
}),
|
|
1713
|
-
...heartbeatRouteDefinitions({
|
|
1714
|
-
getHeartbeatService: this.getHeartbeatService,
|
|
1715
|
-
}),
|
|
1716
|
-
...filingRouteDefinitions({
|
|
1717
|
-
getFilingService: this.getFilingService,
|
|
1718
|
-
}),
|
|
1719
|
-
...homeStateRouteDefinitions(),
|
|
1720
|
-
...homeFeedRouteDefinitions(),
|
|
1721
|
-
...notificationRouteDefinitions(),
|
|
1722
|
-
...diagnosticsRouteDefinitions(),
|
|
1723
|
-
...logExportRouteDefinitions(),
|
|
1724
|
-
...profilerRouteDefinitions(),
|
|
1725
|
-
...documentRouteDefinitions(),
|
|
1726
|
-
...workItemRouteDefinitions(
|
|
1727
|
-
this.sendMessageDeps
|
|
1728
|
-
? {
|
|
1729
|
-
getOrCreateConversation: (conversationId) =>
|
|
1730
|
-
this.sendMessageDeps!.getOrCreateConversation(conversationId),
|
|
1731
|
-
findConversation: this.findConversation
|
|
1732
|
-
? (conversationId) => {
|
|
1733
|
-
const s = this.findConversation!(conversationId);
|
|
1734
|
-
if (!s || !("abort" in s)) return undefined;
|
|
1735
|
-
return s as import("../daemon/conversation.js").Conversation;
|
|
1736
|
-
}
|
|
1737
|
-
: undefined,
|
|
1738
|
-
}
|
|
1739
|
-
: undefined,
|
|
1740
|
-
),
|
|
1741
|
-
...acpRouteDefinitions(),
|
|
1742
|
-
...subagentRouteDefinitions(),
|
|
1743
|
-
...conversationQueryRouteDefinitions({
|
|
1744
|
-
getModelSetContext: this.getModelSetContext,
|
|
1745
|
-
findConversationForQueue: this.findConversation
|
|
1746
|
-
? (id) => {
|
|
1747
|
-
const s = this.findConversation!(id);
|
|
1748
|
-
if (!s?.removeQueuedMessage) return undefined;
|
|
1749
|
-
return { removeQueuedMessage: s.removeQueuedMessage.bind(s) };
|
|
1750
|
-
}
|
|
1751
|
-
: undefined,
|
|
1752
|
-
}),
|
|
1753
|
-
...ttsRouteDefinitions(),
|
|
1754
|
-
...sttRouteDefinitions(),
|
|
1755
|
-
|
|
1756
|
-
// Conversation list and seen signal — kept inline because they
|
|
1757
|
-
// depend on multiple cross-cutting stores that aren't grouped
|
|
1758
|
-
// into a single domain module.
|
|
1759
|
-
{
|
|
1760
|
-
endpoint: "conversations",
|
|
1761
|
-
method: "GET",
|
|
1762
|
-
handler: ({ url }) => {
|
|
1763
|
-
const limit = Number(url.searchParams.get("limit") ?? 50);
|
|
1764
|
-
const offset = Number(url.searchParams.get("offset") ?? 0);
|
|
1765
|
-
const backgroundOnly =
|
|
1766
|
-
url.searchParams.get("conversationType") === "background";
|
|
1767
|
-
let rows = listConversations(limit, backgroundOnly, offset);
|
|
1768
|
-
const totalCount = countConversations(backgroundOnly);
|
|
1769
|
-
// On the first page, ensure all pinned conversations are included
|
|
1770
|
-
// even if they fall outside the paginated window.
|
|
1771
|
-
if (offset === 0 && !backgroundOnly) {
|
|
1772
|
-
const pinned = listPinnedConversations();
|
|
1773
|
-
const seen = new Set(rows.map((c) => c.id));
|
|
1774
|
-
const missing = pinned.filter((c) => !seen.has(c.id));
|
|
1775
|
-
if (missing.length > 0) {
|
|
1776
|
-
rows = [...rows, ...missing];
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
const conversationIds = rows.map((c) => c.id);
|
|
1780
|
-
const displayMeta = getDisplayMetaForConversations(conversationIds);
|
|
1781
|
-
const bindings =
|
|
1782
|
-
externalConversationStore.getBindingsForConversations(
|
|
1783
|
-
conversationIds,
|
|
1784
|
-
);
|
|
1785
|
-
const attentionStates =
|
|
1786
|
-
getAttentionStateByConversationIds(conversationIds);
|
|
1787
|
-
const parentCache = new Map<string, ConversationRow | null>();
|
|
1788
|
-
const nextOffset = offset + limit;
|
|
1789
|
-
const response: Record<string, unknown> = {
|
|
1790
|
-
conversations: rows.map((conversation) =>
|
|
1791
|
-
this.serializeConversationSummary({
|
|
1792
|
-
conversation,
|
|
1793
|
-
binding: bindings.get(conversation.id),
|
|
1794
|
-
attentionState: attentionStates.get(conversation.id),
|
|
1795
|
-
displayMeta: displayMeta.get(conversation.id),
|
|
1796
|
-
parentCache,
|
|
1797
|
-
}),
|
|
1798
|
-
),
|
|
1799
|
-
nextOffset,
|
|
1800
|
-
hasMore: nextOffset < totalCount,
|
|
1801
|
-
};
|
|
1802
|
-
// Include groups array on first page only
|
|
1803
|
-
if (offset === 0) {
|
|
1804
|
-
const groups = listGroups();
|
|
1805
|
-
response.groups = groups.map((g) => ({
|
|
1806
|
-
id: g.id,
|
|
1807
|
-
name: g.name,
|
|
1808
|
-
sortPosition: g.sortPosition,
|
|
1809
|
-
isSystemGroup: g.isSystemGroup,
|
|
1810
|
-
}));
|
|
1811
|
-
}
|
|
1812
|
-
return Response.json(response);
|
|
1813
|
-
},
|
|
1814
|
-
},
|
|
1815
|
-
...conversationAttentionRouteDefinitions(),
|
|
1816
|
-
|
|
1817
|
-
...(conversationManagementDeps
|
|
1818
|
-
? conversationManagementRouteDefinitions(conversationManagementDeps)
|
|
1819
|
-
: []),
|
|
1820
|
-
|
|
1821
|
-
...((): RouteDefinition[] => {
|
|
1822
|
-
const sendMessageDeps = this.sendMessageDeps;
|
|
1823
|
-
if (!sendMessageDeps) return [];
|
|
1824
|
-
const analysisDeps = {
|
|
1825
|
-
sendMessageDeps,
|
|
1826
|
-
buildConversationDetailResponse: (id: string) =>
|
|
1827
|
-
this.buildConversationDetailResponse(id),
|
|
1828
|
-
};
|
|
1829
|
-
// Also expose via the module singleton so background callers
|
|
1830
|
-
// (e.g. job handlers) can invoke analyzeConversation() without
|
|
1831
|
-
// HTTP-layer wiring. Daemon startup must never block, so failures
|
|
1832
|
-
// to register the singleton are logged and swallowed.
|
|
1833
|
-
try {
|
|
1834
|
-
setAnalysisDeps(analysisDeps);
|
|
1835
|
-
} catch (err) {
|
|
1836
|
-
log.warn(
|
|
1837
|
-
{ err },
|
|
1838
|
-
"Failed to register analysis deps singleton; background analysis jobs will be skipped",
|
|
1839
|
-
);
|
|
1840
|
-
}
|
|
1841
|
-
return conversationAnalysisRouteDefinitions(analysisDeps);
|
|
1842
|
-
})(),
|
|
1843
|
-
|
|
1844
|
-
...groupRouteDefinitions(),
|
|
1845
|
-
|
|
1846
|
-
{
|
|
1847
|
-
endpoint: "conversations/seen",
|
|
1848
|
-
method: "POST",
|
|
1849
|
-
handler: async ({ req }) => {
|
|
1850
|
-
const body = (await req.json()) as Record<string, unknown>;
|
|
1851
|
-
const rawConversationId = body.conversationId as string | undefined;
|
|
1852
|
-
if (!rawConversationId)
|
|
1853
|
-
return httpError("BAD_REQUEST", "Missing conversationId", 400);
|
|
1854
|
-
// The client may send a conversation key rather than the internal
|
|
1855
|
-
// conversation ID. Resolve to the internal ID to satisfy FK constraints.
|
|
1856
|
-
const conversationId = resolveConversationId(rawConversationId);
|
|
1857
|
-
if (!conversationId)
|
|
1858
|
-
return httpError(
|
|
1859
|
-
"NOT_FOUND",
|
|
1860
|
-
`Unknown conversation: ${rawConversationId}`,
|
|
1861
|
-
404,
|
|
1862
|
-
);
|
|
1863
|
-
try {
|
|
1864
|
-
// Snapshot current state to detect whether the seen cursor
|
|
1865
|
-
// actually advances (avoids emitting on no-op signals).
|
|
1866
|
-
// Only consider a conversation "unseen" when a latest assistant
|
|
1867
|
-
// message exists and the seen cursor is behind it — matching
|
|
1868
|
-
// the hasUnseenLatestAssistantMessage logic in buildAssistantAttention.
|
|
1869
|
-
const priorState = getAttentionStateByConversationIds([
|
|
1870
|
-
conversationId,
|
|
1871
|
-
]).get(conversationId);
|
|
1872
|
-
const wasUnseen =
|
|
1873
|
-
priorState != null &&
|
|
1874
|
-
priorState.latestAssistantMessageAt != null &&
|
|
1875
|
-
(priorState.lastSeenAssistantMessageAt == null ||
|
|
1876
|
-
priorState.lastSeenAssistantMessageAt <
|
|
1877
|
-
priorState.latestAssistantMessageAt);
|
|
1878
|
-
|
|
1879
|
-
recordConversationSeenSignal({
|
|
1880
|
-
conversationId,
|
|
1881
|
-
sourceChannel: (body.sourceChannel as string) ?? "vellum",
|
|
1882
|
-
signalType: ((body.signalType as string) ??
|
|
1883
|
-
"macos_conversation_opened") as SignalType,
|
|
1884
|
-
confidence: ((body.confidence as string) ??
|
|
1885
|
-
"explicit") as Confidence,
|
|
1886
|
-
source: (body.source as string) ?? "http-api",
|
|
1887
|
-
evidenceText: body.evidenceText as string | undefined,
|
|
1888
|
-
metadata: body.metadata as Record<string, unknown> | undefined,
|
|
1889
|
-
observedAt: body.observedAt as number | undefined,
|
|
1890
|
-
});
|
|
1891
|
-
if (wasUnseen) {
|
|
1892
|
-
assistantEventHub
|
|
1893
|
-
.publish(
|
|
1894
|
-
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
1895
|
-
type: "conversation_list_invalidated",
|
|
1896
|
-
reason: "seen_changed",
|
|
1897
|
-
}),
|
|
1898
|
-
)
|
|
1899
|
-
.catch((err) => {
|
|
1900
|
-
log.warn(
|
|
1901
|
-
{ err },
|
|
1902
|
-
"Failed to publish conversation_list_invalidated (seen_changed)",
|
|
1903
|
-
);
|
|
1904
|
-
});
|
|
1905
|
-
}
|
|
1906
|
-
return Response.json({ ok: true });
|
|
1907
|
-
} catch (err) {
|
|
1908
|
-
log.error(
|
|
1909
|
-
{ err, conversationId },
|
|
1910
|
-
"POST /v1/conversations/seen: failed",
|
|
1911
|
-
);
|
|
1912
|
-
return httpError(
|
|
1913
|
-
"INTERNAL_ERROR",
|
|
1914
|
-
"Failed to record seen signal",
|
|
1915
|
-
500,
|
|
1916
|
-
);
|
|
1917
|
-
}
|
|
1918
|
-
},
|
|
1919
|
-
},
|
|
1920
|
-
|
|
1921
|
-
{
|
|
1922
|
-
endpoint: "conversations/unread",
|
|
1923
|
-
method: "POST",
|
|
1924
|
-
handler: async ({ req }) => {
|
|
1925
|
-
const body = (await req.json()) as Record<string, unknown>;
|
|
1926
|
-
const rawConversationId = body.conversationId as string | undefined;
|
|
1927
|
-
if (!rawConversationId)
|
|
1928
|
-
return httpError("BAD_REQUEST", "Missing conversationId", 400);
|
|
1929
|
-
const conversationId = resolveConversationId(rawConversationId);
|
|
1930
|
-
if (!conversationId)
|
|
1931
|
-
return httpError(
|
|
1932
|
-
"NOT_FOUND",
|
|
1933
|
-
`Unknown conversation: ${rawConversationId}`,
|
|
1934
|
-
404,
|
|
1935
|
-
);
|
|
1936
|
-
try {
|
|
1937
|
-
const changed = markConversationUnread(conversationId);
|
|
1938
|
-
if (changed) {
|
|
1939
|
-
assistantEventHub
|
|
1940
|
-
.publish(
|
|
1941
|
-
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
1942
|
-
type: "conversation_list_invalidated",
|
|
1943
|
-
reason: "seen_changed",
|
|
1944
|
-
}),
|
|
1945
|
-
)
|
|
1946
|
-
.catch((err) => {
|
|
1947
|
-
log.warn(
|
|
1948
|
-
{ err },
|
|
1949
|
-
"Failed to publish conversation_list_invalidated (seen_changed)",
|
|
1950
|
-
);
|
|
1951
|
-
});
|
|
1952
|
-
}
|
|
1953
|
-
return Response.json({ ok: true });
|
|
1954
|
-
} catch (err) {
|
|
1955
|
-
if (err instanceof UserError) {
|
|
1956
|
-
return httpError("UNPROCESSABLE_ENTITY", err.message, 422);
|
|
1957
|
-
}
|
|
1958
|
-
log.error(
|
|
1959
|
-
{ err, conversationId },
|
|
1960
|
-
"POST /v1/conversations/unread: failed",
|
|
1961
|
-
);
|
|
1962
|
-
return httpError(
|
|
1963
|
-
"INTERNAL_ERROR",
|
|
1964
|
-
"Failed to mark conversation unread",
|
|
1965
|
-
500,
|
|
1966
|
-
);
|
|
1967
|
-
}
|
|
1968
|
-
},
|
|
1969
|
-
},
|
|
1970
|
-
|
|
1971
|
-
// conversations/:id must be registered AFTER all literal conversations/<word>
|
|
1972
|
-
// routes above (attention, seen, unread) so the parameterized :id does not
|
|
1973
|
-
// shadow them.
|
|
1974
|
-
{
|
|
1975
|
-
endpoint: "conversations/:id",
|
|
1976
|
-
method: "GET",
|
|
1977
|
-
handler: ({ params }) => {
|
|
1978
|
-
const detail = this.buildConversationDetailResponse(params.id);
|
|
1979
|
-
if (!detail) {
|
|
1980
|
-
return httpError(
|
|
1981
|
-
"NOT_FOUND",
|
|
1982
|
-
`Conversation ${params.id} not found`,
|
|
1983
|
-
404,
|
|
1984
|
-
);
|
|
1985
|
-
}
|
|
1986
|
-
return Response.json(detail);
|
|
1987
|
-
},
|
|
1988
|
-
},
|
|
1989
|
-
|
|
1990
|
-
...btwRouteDefinitions({
|
|
1991
|
-
sendMessageDeps: this.sendMessageDeps,
|
|
1992
|
-
}),
|
|
1993
|
-
|
|
1994
|
-
...conversationRouteDefinitions({
|
|
1995
|
-
interfacesDir: this.interfacesDir,
|
|
1996
|
-
sendMessageDeps: this.sendMessageDeps,
|
|
1997
|
-
approvalConversationGenerator: this.approvalConversationGenerator,
|
|
1998
|
-
suggestionCache: this.suggestionCache,
|
|
1999
|
-
suggestionInFlight: this.suggestionInFlight,
|
|
2000
|
-
getHeartbeatService: this.getHeartbeatService,
|
|
2001
|
-
}),
|
|
2002
|
-
...playgroundRouteDefinitions({
|
|
2003
|
-
getConversationById: async (id) => {
|
|
2004
|
-
// Gate on DB existence first so genuinely-missing IDs return
|
|
2005
|
-
// `undefined` (preserving the route handlers' 404 path) rather
|
|
2006
|
-
// than triggering `getOrCreateConversation`'s create branch and
|
|
2007
|
-
// masking the not-found case. For existing-but-not-loaded rows
|
|
2008
|
-
// (e.g. freshly seeded by `POST /playground/seed-conversation`),
|
|
2009
|
-
// hydrate the in-memory `Conversation` on demand so conv-scoped
|
|
2010
|
-
// playground routes work without first opening the conversation
|
|
2011
|
-
// in the main window.
|
|
2012
|
-
if (!getConversation(id)) return undefined;
|
|
2013
|
-
const sendDeps = this.sendMessageDeps;
|
|
2014
|
-
if (!sendDeps) {
|
|
2015
|
-
// Fall back to the in-memory active map when the daemon hasn't
|
|
2016
|
-
// wired the hydration-capable accessor (e.g. unit tests).
|
|
2017
|
-
const s = this.findConversation?.(id);
|
|
2018
|
-
if (!s || !("abort" in s)) return undefined;
|
|
2019
|
-
return s as import("../daemon/conversation.js").Conversation;
|
|
2020
|
-
}
|
|
2021
|
-
return sendDeps.getOrCreateConversation(id);
|
|
2022
|
-
},
|
|
2023
|
-
isPlaygroundEnabled: () =>
|
|
2024
|
-
isAssistantFeatureFlagEnabled("compaction-playground", getConfig()),
|
|
2025
|
-
listConversationsByTitlePrefix: (prefix) =>
|
|
2026
|
-
listConversationsByTitlePrefix(prefix),
|
|
2027
|
-
deleteConversationById: (id) => {
|
|
2028
|
-
// Existence check first so we can report `false` for missing rows
|
|
2029
|
-
// — `deleteConversation` always returns a result object even when
|
|
2030
|
-
// no row matched.
|
|
2031
|
-
if (!getConversation(id)) return false;
|
|
2032
|
-
// Mirror the canonical DELETE /v1/conversations/:id handler in
|
|
2033
|
-
// conversation-management-routes.ts: tear down the in-memory
|
|
2034
|
-
// Conversation first (so a running agent loop can't write to a
|
|
2035
|
-
// deleted row and trip FK constraints), then drop the DB row,
|
|
2036
|
-
// then enqueue Qdrant vector cleanup for the returned segment
|
|
2037
|
-
// and summary IDs. Without this, seeded-then-deleted playground
|
|
2038
|
-
// conversations leak vectors and zombie Conversation objects.
|
|
2039
|
-
if (this.findConversation?.(id)) {
|
|
2040
|
-
this.conversationManagementDeps?.destroyConversation(id);
|
|
2041
|
-
}
|
|
2042
|
-
const deleted = deleteConversation(id);
|
|
2043
|
-
for (const segId of deleted.segmentIds) {
|
|
2044
|
-
enqueueMemoryJob("delete_qdrant_vectors", {
|
|
2045
|
-
targetType: "segment",
|
|
2046
|
-
targetId: segId,
|
|
2047
|
-
});
|
|
2048
|
-
}
|
|
2049
|
-
for (const summaryId of deleted.deletedSummaryIds) {
|
|
2050
|
-
enqueueMemoryJob("delete_qdrant_vectors", {
|
|
2051
|
-
targetType: "summary",
|
|
2052
|
-
targetId: summaryId,
|
|
2053
|
-
});
|
|
2054
|
-
}
|
|
2055
|
-
return true;
|
|
2056
|
-
},
|
|
2057
|
-
createConversation: async (title) => {
|
|
2058
|
-
const row = createConversation({ title });
|
|
2059
|
-
return { id: row.id };
|
|
2060
|
-
},
|
|
2061
|
-
addMessage: async (conversationId, role, contentJson, options) => {
|
|
2062
|
-
const persisted = await addMessage(
|
|
2063
|
-
conversationId,
|
|
2064
|
-
role,
|
|
2065
|
-
contentJson,
|
|
2066
|
-
undefined,
|
|
2067
|
-
options,
|
|
2068
|
-
);
|
|
2069
|
-
return { id: persisted.id };
|
|
2070
|
-
},
|
|
2071
|
-
}),
|
|
2072
|
-
...globalSearchRouteDefinitions(),
|
|
2073
|
-
...approvalRouteDefinitions(),
|
|
2074
|
-
...hostBashRouteDefinitions(),
|
|
2075
|
-
...hostBrowserRouteDefinitions(),
|
|
2076
|
-
...hostCuRouteDefinitions(),
|
|
2077
|
-
...hostFileRouteDefinitions(),
|
|
2078
|
-
...(this.getSkillContext
|
|
2079
|
-
? skillRouteDefinitions({
|
|
2080
|
-
getSkillContext: this.getSkillContext,
|
|
2081
|
-
})
|
|
2082
|
-
: []),
|
|
2083
|
-
...trustRulesRouteDefinitions(),
|
|
2084
|
-
...surfaceActionRouteDefinitions({
|
|
2085
|
-
findConversation: this.findConversation,
|
|
2086
|
-
findConversationBySurfaceId: this.findConversationBySurfaceId,
|
|
2087
|
-
}),
|
|
2088
|
-
...surfaceContentRouteDefinitions({
|
|
2089
|
-
findConversation: this.findConversation,
|
|
2090
|
-
}),
|
|
2091
|
-
...guardianActionRouteDefinitions(),
|
|
2092
|
-
|
|
2093
|
-
...contactRouteDefinitions(),
|
|
2094
|
-
...inviteRouteDefinitions(),
|
|
2095
|
-
// contacts/:id catch-all must follow invite routes to avoid shadowing
|
|
2096
|
-
...contactCatchAllRouteDefinitions(),
|
|
2097
|
-
|
|
2098
|
-
...telegramRouteDefinitions(),
|
|
2099
|
-
...channelVerificationRouteDefinitions(),
|
|
2100
|
-
...slackChannelRouteDefinitions(),
|
|
2101
|
-
...slackShareRouteDefinitions(),
|
|
2102
|
-
...twilioRouteDefinitions(),
|
|
2103
|
-
...vercelRouteDefinitions(),
|
|
2104
|
-
...channelReadinessRouteDefinitions(),
|
|
2105
|
-
...oauthProvidersRouteDefinitions(),
|
|
2106
|
-
...oauthAppsRouteDefinitions(),
|
|
2107
|
-
...attachmentRouteDefinitions(),
|
|
2108
|
-
|
|
2109
|
-
...(this.getRecordingDeps
|
|
2110
|
-
? recordingRouteDefinitions({
|
|
2111
|
-
getRecordingDeps: this.getRecordingDeps,
|
|
2112
|
-
})
|
|
2113
|
-
: []),
|
|
2114
|
-
|
|
2115
|
-
{
|
|
2116
|
-
endpoint: "interfaces/:path*",
|
|
2117
|
-
method: "GET",
|
|
2118
|
-
policyKey: "interfaces",
|
|
2119
|
-
handler: ({ params }) => this.handleGetInterface(params.path),
|
|
2120
|
-
},
|
|
2121
|
-
|
|
2122
|
-
...channelRouteDefinitions({
|
|
2123
|
-
assistantId,
|
|
2124
|
-
processMessage: this.processMessage,
|
|
2125
|
-
approvalCopyGenerator: this.approvalCopyGenerator,
|
|
2126
|
-
approvalConversationGenerator: this.approvalConversationGenerator,
|
|
2127
|
-
guardianActionCopyGenerator: this.guardianActionCopyGenerator,
|
|
2128
|
-
guardianFollowUpConversationGenerator:
|
|
2129
|
-
this.guardianFollowUpConversationGenerator,
|
|
2130
|
-
getHeartbeatService: this.getHeartbeatService,
|
|
2131
|
-
}),
|
|
2132
|
-
...callRouteDefinitions({ assistantId }),
|
|
2133
|
-
|
|
2134
|
-
// Internal Twilio forwarding (gateway -> runtime) — kept inline
|
|
2135
|
-
// because these reconstruct fake form-encoded requests from JSON,
|
|
2136
|
-
// a pattern specific to the gateway-to-daemon bridge.
|
|
2137
|
-
{
|
|
2138
|
-
endpoint: "internal/twilio/voice-webhook",
|
|
2139
|
-
method: "POST",
|
|
2140
|
-
handler: async ({ req }) => {
|
|
2141
|
-
const json = (await req.json()) as {
|
|
2142
|
-
params: Record<string, string>;
|
|
2143
|
-
originalUrl?: string;
|
|
2144
|
-
};
|
|
2145
|
-
const formBody = new URLSearchParams(json.params).toString();
|
|
2146
|
-
const reconstructedUrl = json.originalUrl ?? req.url;
|
|
2147
|
-
const fakeReq = new Request(reconstructedUrl, {
|
|
2148
|
-
method: "POST",
|
|
2149
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
2150
|
-
body: formBody,
|
|
2151
|
-
});
|
|
2152
|
-
return handleVoiceWebhook(fakeReq);
|
|
2153
|
-
},
|
|
2154
|
-
},
|
|
2155
|
-
{
|
|
2156
|
-
endpoint: "internal/twilio/status",
|
|
2157
|
-
method: "POST",
|
|
2158
|
-
handler: async ({ req }) => {
|
|
2159
|
-
const json = (await req.json()) as {
|
|
2160
|
-
params: Record<string, string>;
|
|
2161
|
-
};
|
|
2162
|
-
const formBody = new URLSearchParams(json.params).toString();
|
|
2163
|
-
const fakeReq = new Request(req.url, {
|
|
2164
|
-
method: "POST",
|
|
2165
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
2166
|
-
body: formBody,
|
|
2167
|
-
});
|
|
2168
|
-
return handleStatusCallback(fakeReq);
|
|
2169
|
-
},
|
|
2170
|
-
},
|
|
2171
|
-
{
|
|
2172
|
-
endpoint: "internal/twilio/connect-action",
|
|
2173
|
-
method: "POST",
|
|
2174
|
-
handler: async ({ req }) => {
|
|
2175
|
-
const json = (await req.json()) as {
|
|
2176
|
-
params: Record<string, string>;
|
|
2177
|
-
};
|
|
2178
|
-
const formBody = new URLSearchParams(json.params).toString();
|
|
2179
|
-
const fakeReq = new Request(req.url, {
|
|
2180
|
-
method: "POST",
|
|
2181
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
2182
|
-
body: formBody,
|
|
2183
|
-
});
|
|
2184
|
-
return handleConnectAction(fakeReq);
|
|
2185
|
-
},
|
|
2186
|
-
},
|
|
2187
|
-
|
|
2188
|
-
...brainGraphRouteDefinitions({ mintUiPageToken }),
|
|
2189
|
-
...eventsRouteDefinitions(),
|
|
2190
|
-
...traceEventRouteDefinitions(),
|
|
2191
|
-
...migrationRouteDefinitions(),
|
|
2192
|
-
...backupRouteDefinitions(),
|
|
2193
|
-
|
|
2194
|
-
// User-defined routes under /x/* — must be LAST so built-in routes
|
|
2195
|
-
// always take priority.
|
|
2196
|
-
...userRouteDefinitions(),
|
|
2197
|
-
|
|
2198
|
-
// Internal OAuth callback (gateway -> runtime)
|
|
2199
|
-
{
|
|
2200
|
-
endpoint: "internal/oauth/callback",
|
|
2201
|
-
method: "POST",
|
|
2202
|
-
handler: async ({ req }) => {
|
|
2203
|
-
const json = (await req.json()) as {
|
|
2204
|
-
state: string;
|
|
2205
|
-
code?: string;
|
|
2206
|
-
error?: string;
|
|
2207
|
-
};
|
|
2208
|
-
if (!json.state)
|
|
2209
|
-
return httpError("BAD_REQUEST", "Missing state parameter", 400);
|
|
2210
|
-
if (json.error) {
|
|
2211
|
-
const consumed = consumeCallbackError(json.state, json.error);
|
|
2212
|
-
return consumed
|
|
2213
|
-
? Response.json({ ok: true })
|
|
2214
|
-
: httpError("NOT_FOUND", "Unknown state", 404);
|
|
2215
|
-
}
|
|
2216
|
-
if (json.code) {
|
|
2217
|
-
const consumed = consumeCallback(json.state, json.code);
|
|
2218
|
-
return consumed
|
|
2219
|
-
? Response.json({ ok: true })
|
|
2220
|
-
: httpError("NOT_FOUND", "Unknown state", 404);
|
|
2221
|
-
}
|
|
2222
|
-
return httpError(
|
|
2223
|
-
"BAD_REQUEST",
|
|
2224
|
-
"Missing code or error parameter",
|
|
2225
|
-
400,
|
|
2226
|
-
);
|
|
2227
|
-
},
|
|
2228
|
-
},
|
|
2229
|
-
];
|
|
2230
|
-
}
|
|
2231
1406
|
}
|