@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
package/src/daemon/server.ts
CHANGED
|
@@ -1,122 +1,47 @@
|
|
|
1
|
-
import { existsSync, readFileSync
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
disposeAcpSessionManager,
|
|
6
|
-
getAcpSessionManager,
|
|
7
|
-
setBroadcastToAllClients,
|
|
8
|
-
} from "../acp/index.js";
|
|
9
|
-
import { enrichMessageWithSourcePaths } from "../agent/attachments.js";
|
|
10
|
-
import type { AgentEvent } from "../agent/loop.js";
|
|
11
|
-
import {
|
|
12
|
-
createAssistantMessage,
|
|
13
|
-
createUserMessage,
|
|
14
|
-
} from "../agent/message-types.js";
|
|
4
|
+
import { disposeAcpSessionManager } from "../acp/index.js";
|
|
15
5
|
import { compileApp } from "../bundler/app-compiler.js";
|
|
16
|
-
import {
|
|
17
|
-
type ChannelId,
|
|
18
|
-
type InterfaceId,
|
|
19
|
-
parseChannelId,
|
|
20
|
-
parseInterfaceId,
|
|
21
|
-
supportsHostProxy,
|
|
22
|
-
} from "../channels/types.js";
|
|
23
6
|
import { getConfig } from "../config/loader.js";
|
|
24
7
|
import { onContactChange } from "../contacts/contact-events.js";
|
|
25
8
|
import type { CesClient } from "../credential-execution/client.js";
|
|
26
9
|
import type { CesProcessManager } from "../credential-execution/process-manager.js";
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import { CliIpcServer } from "../ipc/cli-server.js";
|
|
30
|
-
import { registerBrowserIpcContextResolver } from "../ipc/routes/browser-context.js";
|
|
10
|
+
import { AssistantIpcServer } from "../ipc/assistant-server.js";
|
|
11
|
+
import { SkillIpcServer } from "../ipc/skill-server.js";
|
|
31
12
|
import { getApp, getAppDirPath, isMultifileApp } from "../memory/app-store.js";
|
|
32
|
-
import * as attachmentsStore from "../memory/attachments-store.js";
|
|
33
|
-
import {
|
|
34
|
-
createCanonicalGuardianRequest,
|
|
35
|
-
generateCanonicalRequestCode,
|
|
36
|
-
} from "../memory/canonical-guardian-store.js";
|
|
37
|
-
import {
|
|
38
|
-
addMessage,
|
|
39
|
-
getConversation,
|
|
40
|
-
getConversationMemoryScopeId,
|
|
41
|
-
getConversationType,
|
|
42
|
-
provenanceFromTrustContext,
|
|
43
|
-
setConversationOriginChannelIfUnset,
|
|
44
|
-
setConversationOriginInterfaceIfUnset,
|
|
45
|
-
} from "../memory/conversation-crud.js";
|
|
46
|
-
import {
|
|
47
|
-
syncMessageToDisk,
|
|
48
|
-
updateMetaFile,
|
|
49
|
-
} from "../memory/conversation-disk-view.js";
|
|
50
|
-
import { getOrCreateConversation } from "../memory/conversation-key-store.js";
|
|
51
13
|
import { syncIdentityNameToPlatform } from "../platform/sync-identity.js";
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
import { RateLimitProvider } from "../providers/ratelimit.js";
|
|
55
|
-
import { getProvider, initializeProviders } from "../providers/registry.js";
|
|
56
|
-
import {
|
|
57
|
-
registerDefaultWakeResolver,
|
|
58
|
-
type WakeTarget,
|
|
59
|
-
} from "../runtime/agent-wake.js";
|
|
60
|
-
import { buildAssistantEvent } from "../runtime/assistant-event.js";
|
|
61
|
-
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
62
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
14
|
+
import { initializeProviders } from "../providers/registry.js";
|
|
15
|
+
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
63
16
|
import { getSigningKeyFingerprint } from "../runtime/auth/token-service.js";
|
|
64
|
-
import { bridgeConfirmationRequestToGuardian } from "../runtime/confirmation-request-guardian-bridge.js";
|
|
65
|
-
import { registerInteractiveUiResolver } from "../runtime/interactive-ui.js";
|
|
66
|
-
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
67
|
-
import { checkIngressForSecrets } from "../security/secret-ingress.js";
|
|
68
|
-
import { redactSecrets } from "../security/secret-scanner.js";
|
|
69
17
|
import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
|
|
70
|
-
import { registerCancelCallback } from "../signals/cancel.js";
|
|
71
|
-
import { registerConversationUndoCallback } from "../signals/conversation-undo.js";
|
|
72
|
-
import { appendEventToStream } from "../signals/event-stream.js";
|
|
73
|
-
import { registerUserMessageCallback } from "../signals/user-message.js";
|
|
74
18
|
import { getSubagentManager } from "../subagent/index.js";
|
|
75
|
-
import { summarizeToolInput } from "../tools/tool-input-summary.js";
|
|
76
|
-
import { createAbortReason } from "../util/abort-reasons.js";
|
|
77
19
|
import { getLogger } from "../util/logger.js";
|
|
78
20
|
import {
|
|
79
21
|
getAvatarImagePath,
|
|
80
|
-
getSandboxWorkingDir,
|
|
81
22
|
getWorkspacePromptPath,
|
|
82
23
|
} from "../util/platform.js";
|
|
83
|
-
import { registerDaemonCallbacks } from "../work-items/work-item-runner.js";
|
|
84
24
|
import {
|
|
85
25
|
AppSourceWatcher,
|
|
86
26
|
setEnsureAppSourceWatcher,
|
|
87
27
|
} from "./app-source-watcher.js";
|
|
88
|
-
import {
|
|
89
|
-
import {
|
|
90
|
-
Conversation,
|
|
91
|
-
type ConversationMemoryPolicy,
|
|
92
|
-
DEFAULT_MEMORY_POLICY,
|
|
93
|
-
} from "./conversation.js";
|
|
28
|
+
import { getConfigWatcher } from "./config-watcher.js";
|
|
29
|
+
import { Conversation } from "./conversation.js";
|
|
94
30
|
import { ConversationEvictor } from "./conversation-evictor.js";
|
|
95
|
-
import { registerLaunchConversationDeps } from "./conversation-launch.js";
|
|
96
|
-
import { buildSlackMetaForPersistence } from "./conversation-messaging.js";
|
|
97
|
-
import { formatCompactResult } from "./conversation-process.js";
|
|
98
|
-
import { resolveChannelCapabilities } from "./conversation-runtime-assembly.js";
|
|
99
|
-
import { resolveSlash, type SlashContext } from "./conversation-slash.js";
|
|
100
31
|
import {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
32
|
+
allConversations,
|
|
33
|
+
clearConversations,
|
|
34
|
+
conversationEntries,
|
|
35
|
+
deleteConversation,
|
|
36
|
+
getConversationMap,
|
|
37
|
+
getOrCreateConversation as getOrCreateActiveConversation,
|
|
38
|
+
initConversationLifecycle,
|
|
39
|
+
setCesClientPromise,
|
|
40
|
+
} from "./conversation-store.js";
|
|
41
|
+
import { refreshSurfacesForApp } from "./conversation-surfaces.js";
|
|
105
42
|
import { parseIdentityFields } from "./handlers/identity.js";
|
|
106
|
-
import type {
|
|
107
|
-
|
|
108
|
-
HandlerContext,
|
|
109
|
-
} from "./handlers/shared.js";
|
|
110
|
-
import type { SkillOperationContext } from "./handlers/skills.js";
|
|
111
|
-
import { HostBashProxy } from "./host-bash-proxy.js";
|
|
112
|
-
import { HostBrowserProxy } from "./host-browser-proxy.js";
|
|
113
|
-
import { HostCuProxy } from "./host-cu-proxy.js";
|
|
114
|
-
import { HostFileProxy } from "./host-file-proxy.js";
|
|
115
|
-
import type {
|
|
116
|
-
ServerMessage,
|
|
117
|
-
UserMessageAttachment,
|
|
118
|
-
} from "./message-protocol.js";
|
|
119
|
-
import { buildTransportHints } from "./transport-hints.js";
|
|
43
|
+
import type { ConversationCreateOptions } from "./handlers/shared.js";
|
|
44
|
+
import { setGlobalSkillIpcSender } from "./meet-host-supervisor.js";
|
|
120
45
|
|
|
121
46
|
const log = getLogger("server");
|
|
122
47
|
|
|
@@ -134,181 +59,16 @@ function readPackageVersion(): string | undefined {
|
|
|
134
59
|
|
|
135
60
|
const daemonVersion = readPackageVersion();
|
|
136
61
|
|
|
137
|
-
function resolveTurnChannel(
|
|
138
|
-
sourceChannel?: string,
|
|
139
|
-
transportChannelId?: string,
|
|
140
|
-
): ChannelId {
|
|
141
|
-
if (sourceChannel != null) {
|
|
142
|
-
const parsed = parseChannelId(sourceChannel);
|
|
143
|
-
if (!parsed) {
|
|
144
|
-
throw new Error(`Invalid sourceChannel: ${sourceChannel}`);
|
|
145
|
-
}
|
|
146
|
-
return parsed;
|
|
147
|
-
}
|
|
148
|
-
if (transportChannelId != null) {
|
|
149
|
-
const parsed = parseChannelId(transportChannelId);
|
|
150
|
-
if (!parsed) {
|
|
151
|
-
throw new Error(`Invalid transport.channelId: ${transportChannelId}`);
|
|
152
|
-
}
|
|
153
|
-
return parsed;
|
|
154
|
-
}
|
|
155
|
-
return "vellum";
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function resolveTurnInterface(sourceInterface?: string): InterfaceId {
|
|
159
|
-
if (sourceInterface != null) {
|
|
160
|
-
const parsed = parseInterfaceId(sourceInterface);
|
|
161
|
-
if (!parsed) {
|
|
162
|
-
throw new Error(`Invalid sourceInterface: ${sourceInterface}`);
|
|
163
|
-
}
|
|
164
|
-
return parsed;
|
|
165
|
-
}
|
|
166
|
-
// Interface and channel are orthogonal dimensions; default explicitly
|
|
167
|
-
// instead of deriving interface from channel.
|
|
168
|
-
return "vellum";
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function resolveCanonicalRequestSourceType(
|
|
172
|
-
sourceChannel: string | undefined,
|
|
173
|
-
): "desktop" | "channel" | "voice" {
|
|
174
|
-
if (sourceChannel === "phone") {
|
|
175
|
-
return "voice";
|
|
176
|
-
}
|
|
177
|
-
if (sourceChannel === "vellum") {
|
|
178
|
-
return "desktop";
|
|
179
|
-
}
|
|
180
|
-
return "channel";
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Build an onEvent callback that registers pending interactions when the agent
|
|
185
|
-
* loop emits confirmation_request, secret_request, host_bash_request,
|
|
186
|
-
* host_browser_request, host_file_request, or host_cu_request events. This
|
|
187
|
-
* ensures that channel approval interception can look up the conversation by
|
|
188
|
-
* requestId.
|
|
189
|
-
*/
|
|
190
|
-
function makePendingInteractionRegistrar(
|
|
191
|
-
conversation: Conversation,
|
|
192
|
-
conversationId: string,
|
|
193
|
-
): (msg: ServerMessage) => void {
|
|
194
|
-
return (msg: ServerMessage) => {
|
|
195
|
-
if (msg.type === "confirmation_request") {
|
|
196
|
-
pendingInteractions.register(msg.requestId, {
|
|
197
|
-
conversation,
|
|
198
|
-
conversationId,
|
|
199
|
-
kind: "confirmation",
|
|
200
|
-
confirmationDetails: {
|
|
201
|
-
toolName: msg.toolName,
|
|
202
|
-
input: msg.input,
|
|
203
|
-
riskLevel: msg.riskLevel,
|
|
204
|
-
executionTarget: msg.executionTarget,
|
|
205
|
-
allowlistOptions: msg.allowlistOptions,
|
|
206
|
-
scopeOptions: msg.scopeOptions,
|
|
207
|
-
persistentDecisionsAllowed: msg.persistentDecisionsAllowed,
|
|
208
|
-
temporaryOptionsAvailable: msg.temporaryOptionsAvailable,
|
|
209
|
-
},
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// Create a canonical guardian request so HTTP handlers can find it
|
|
213
|
-
// via applyCanonicalGuardianDecision.
|
|
214
|
-
try {
|
|
215
|
-
const trustContext = conversation.trustContext;
|
|
216
|
-
const sourceChannel = trustContext?.sourceChannel ?? "vellum";
|
|
217
|
-
const inputRecord = msg.input as Record<string, unknown>;
|
|
218
|
-
const activityRaw =
|
|
219
|
-
(typeof inputRecord.activity === "string"
|
|
220
|
-
? inputRecord.activity
|
|
221
|
-
: undefined) ??
|
|
222
|
-
(typeof inputRecord.reason === "string"
|
|
223
|
-
? inputRecord.reason
|
|
224
|
-
: undefined);
|
|
225
|
-
const canonicalRequest = createCanonicalGuardianRequest({
|
|
226
|
-
id: msg.requestId,
|
|
227
|
-
kind: "tool_approval",
|
|
228
|
-
sourceType: resolveCanonicalRequestSourceType(sourceChannel),
|
|
229
|
-
sourceChannel,
|
|
230
|
-
conversationId,
|
|
231
|
-
requesterExternalUserId: trustContext?.requesterExternalUserId,
|
|
232
|
-
requesterChatId: trustContext?.requesterChatId,
|
|
233
|
-
guardianExternalUserId: trustContext?.guardianExternalUserId,
|
|
234
|
-
guardianPrincipalId: trustContext?.guardianPrincipalId ?? undefined,
|
|
235
|
-
toolName: msg.toolName,
|
|
236
|
-
commandPreview:
|
|
237
|
-
redactSecrets(summarizeToolInput(msg.toolName, inputRecord)) ||
|
|
238
|
-
undefined,
|
|
239
|
-
riskLevel: msg.riskLevel,
|
|
240
|
-
activityText: activityRaw ? redactSecrets(activityRaw) : undefined,
|
|
241
|
-
executionTarget: msg.executionTarget,
|
|
242
|
-
status: "pending",
|
|
243
|
-
requestCode: generateCanonicalRequestCode(),
|
|
244
|
-
expiresAt: Date.now() + 5 * 60 * 1000,
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// For trusted-contact sessions, bridge to guardian.question so the
|
|
248
|
-
// guardian gets notified and can approve via callback/request-code.
|
|
249
|
-
if (trustContext) {
|
|
250
|
-
bridgeConfirmationRequestToGuardian({
|
|
251
|
-
canonicalRequest,
|
|
252
|
-
trustContext,
|
|
253
|
-
conversationId,
|
|
254
|
-
toolName: msg.toolName,
|
|
255
|
-
assistantId:
|
|
256
|
-
conversation.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
} catch (err) {
|
|
260
|
-
log.debug(
|
|
261
|
-
{ err, requestId: msg.requestId, conversationId },
|
|
262
|
-
"Failed to create canonical request from pending interaction registrar",
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
} else if (msg.type === "secret_request") {
|
|
266
|
-
pendingInteractions.register(msg.requestId, {
|
|
267
|
-
conversation,
|
|
268
|
-
conversationId,
|
|
269
|
-
kind: "secret",
|
|
270
|
-
});
|
|
271
|
-
} else if (msg.type === "host_bash_request") {
|
|
272
|
-
pendingInteractions.register(msg.requestId, {
|
|
273
|
-
conversation,
|
|
274
|
-
conversationId,
|
|
275
|
-
kind: "host_bash",
|
|
276
|
-
});
|
|
277
|
-
} else if (msg.type === "host_browser_request") {
|
|
278
|
-
pendingInteractions.register(msg.requestId, {
|
|
279
|
-
conversation,
|
|
280
|
-
conversationId,
|
|
281
|
-
kind: "host_browser",
|
|
282
|
-
});
|
|
283
|
-
} else if (msg.type === "host_file_request") {
|
|
284
|
-
pendingInteractions.register(msg.requestId, {
|
|
285
|
-
conversation,
|
|
286
|
-
conversationId,
|
|
287
|
-
kind: "host_file",
|
|
288
|
-
});
|
|
289
|
-
} else if (msg.type === "host_cu_request") {
|
|
290
|
-
pendingInteractions.register(msg.requestId, {
|
|
291
|
-
conversation,
|
|
292
|
-
conversationId,
|
|
293
|
-
kind: "host_cu",
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
62
|
export class DaemonServer {
|
|
300
|
-
private conversations = new Map<string, Conversation>();
|
|
301
|
-
private conversationOptions = new Map<string, ConversationCreateOptions>();
|
|
302
|
-
private conversationCreating = new Map<string, Promise<Conversation>>();
|
|
303
63
|
private sharedRequestTimestamps: number[] = [];
|
|
304
64
|
private unsubscribeContactChange: (() => void) | null = null;
|
|
305
65
|
private evictor: ConversationEvictor;
|
|
306
|
-
private _hubChain: Promise<void> = Promise.resolve();
|
|
307
66
|
|
|
308
67
|
// Composed subsystems
|
|
309
|
-
private configWatcher =
|
|
68
|
+
private configWatcher = getConfigWatcher();
|
|
310
69
|
private appSourceWatcher = new AppSourceWatcher();
|
|
311
|
-
private cliIpc = new
|
|
70
|
+
private cliIpc = new AssistantIpcServer();
|
|
71
|
+
private skillIpc = new SkillIpcServer();
|
|
312
72
|
|
|
313
73
|
// CES (Credential Execution Service) — process-level singleton.
|
|
314
74
|
// Lifecycle is managed by startCesProcess() in lifecycle.ts; the server
|
|
@@ -320,11 +80,6 @@ export class DaemonServer {
|
|
|
320
80
|
/** Monotonically increasing counter to detect stale client updates. */
|
|
321
81
|
private cesClientGeneration = 0;
|
|
322
82
|
|
|
323
|
-
/**
|
|
324
|
-
* Logical assistant identifier used when publishing to the assistant-events hub.
|
|
325
|
-
*/
|
|
326
|
-
assistantId: string = DAEMON_INTERNAL_ASSISTANT_ID;
|
|
327
|
-
|
|
328
83
|
/**
|
|
329
84
|
* Inject the CES client and process manager from the caller (lifecycle.ts).
|
|
330
85
|
* Must be called before start().
|
|
@@ -352,6 +107,7 @@ export class DaemonServer {
|
|
|
352
107
|
}
|
|
353
108
|
return client;
|
|
354
109
|
});
|
|
110
|
+
setCesClientPromise(this.cesClientPromise);
|
|
355
111
|
}
|
|
356
112
|
}
|
|
357
113
|
|
|
@@ -374,68 +130,22 @@ export class DaemonServer {
|
|
|
374
130
|
this.cesClientRef = client;
|
|
375
131
|
}
|
|
376
132
|
|
|
377
|
-
/** Optional heartbeat service reference for "Run Now" from the UI. */
|
|
378
|
-
private _heartbeatService?: HeartbeatService;
|
|
379
|
-
|
|
380
|
-
setHeartbeatService(service: HeartbeatService): void {
|
|
381
|
-
this._heartbeatService = service;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
getHeartbeatService(): HeartbeatService | undefined {
|
|
385
|
-
return this._heartbeatService;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/** Optional filing service reference for "Run Now" from the UI. */
|
|
389
|
-
private _filingService?: FilingService;
|
|
390
|
-
|
|
391
|
-
setFilingService(service: FilingService): void {
|
|
392
|
-
this._filingService = service;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
getFilingService(): FilingService | undefined {
|
|
396
|
-
return this._filingService;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
private deriveMemoryPolicy(conversationId: string): ConversationMemoryPolicy {
|
|
400
|
-
const conversationType = getConversationType(conversationId);
|
|
401
|
-
if (conversationType === "private") {
|
|
402
|
-
return {
|
|
403
|
-
scopeId: getConversationMemoryScopeId(conversationId),
|
|
404
|
-
includeDefaultFallback: true,
|
|
405
|
-
strictSideEffects: true,
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
return DEFAULT_MEMORY_POLICY;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
private applyTransportMetadata(
|
|
412
|
-
conversation: Conversation,
|
|
413
|
-
options: ConversationCreateOptions | undefined,
|
|
414
|
-
): void {
|
|
415
|
-
const transport = options?.transport;
|
|
416
|
-
if (!transport) return;
|
|
417
|
-
log.debug(
|
|
418
|
-
{ channelId: transport.channelId },
|
|
419
|
-
"Transport metadata received",
|
|
420
|
-
);
|
|
421
|
-
conversation.setTransportHints(buildTransportHints(transport));
|
|
422
|
-
// Route client-reported host env through the capability-gated setter on
|
|
423
|
-
// Conversation so both the create/reuse path here and the queue-drain
|
|
424
|
-
// path in conversation-process share one implementation. The method
|
|
425
|
-
// gates on `supportsHostProxy` (not a specific interface name), so any
|
|
426
|
-
// new host-capable client added to `HostProxyInterfaceId` will flow its
|
|
427
|
-
// host env through automatically.
|
|
428
|
-
conversation.applyHostEnvFromTransport(transport);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
133
|
constructor() {
|
|
432
|
-
this.evictor = new ConversationEvictor(
|
|
134
|
+
this.evictor = new ConversationEvictor(getConversationMap());
|
|
433
135
|
getSubagentManager().sharedRequestTimestamps = this.sharedRequestTimestamps;
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
this.
|
|
437
|
-
|
|
136
|
+
|
|
137
|
+
initConversationLifecycle({
|
|
138
|
+
evictor: this.evictor,
|
|
139
|
+
sharedRequestTimestamps: this.sharedRequestTimestamps,
|
|
140
|
+
});
|
|
141
|
+
|
|
438
142
|
setEnsureAppSourceWatcher(() => this.appSourceWatcher.ensureStarted());
|
|
143
|
+
// Wire the skill IPC server into the meet-host supervisor's lazy
|
|
144
|
+
// dispatch path. The supervisor is constructed in
|
|
145
|
+
// `initializeProvidersAndTools()` (via `startMeetHost`), which can run
|
|
146
|
+
// before or after this DaemonServer instance, so the sender flows
|
|
147
|
+
// through a module-level global rather than constructor injection.
|
|
148
|
+
setGlobalSkillIpcSender(this.skillIpc);
|
|
439
149
|
this.evictor.onEvict = (conversationId: string) => {
|
|
440
150
|
getSubagentManager().abortAllForParent(conversationId);
|
|
441
151
|
};
|
|
@@ -445,121 +155,6 @@ export class DaemonServer {
|
|
|
445
155
|
(c) => c.status === "running" || c.status === "pending",
|
|
446
156
|
);
|
|
447
157
|
};
|
|
448
|
-
getSubagentManager().onSubagentFinished = async (
|
|
449
|
-
parentConversationId,
|
|
450
|
-
message,
|
|
451
|
-
sendToClient,
|
|
452
|
-
notification,
|
|
453
|
-
) => {
|
|
454
|
-
const parentConversation = this.conversations.get(parentConversationId);
|
|
455
|
-
if (!parentConversation) {
|
|
456
|
-
log.warn(
|
|
457
|
-
{ parentConversationId },
|
|
458
|
-
"Subagent finished but parent conversation not found",
|
|
459
|
-
);
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
const requestId = `subagent-notify-${Date.now()}`;
|
|
463
|
-
const metadata = { subagentNotification: notification };
|
|
464
|
-
const enqueueResult = parentConversation.enqueueMessage(
|
|
465
|
-
message,
|
|
466
|
-
[],
|
|
467
|
-
sendToClient,
|
|
468
|
-
requestId,
|
|
469
|
-
undefined,
|
|
470
|
-
undefined,
|
|
471
|
-
metadata,
|
|
472
|
-
);
|
|
473
|
-
if (!enqueueResult.queued && !enqueueResult.rejected) {
|
|
474
|
-
const messageId = await parentConversation.persistUserMessage(
|
|
475
|
-
message,
|
|
476
|
-
[],
|
|
477
|
-
undefined,
|
|
478
|
-
metadata,
|
|
479
|
-
);
|
|
480
|
-
parentConversation
|
|
481
|
-
.runAgentLoop(message, messageId, sendToClient)
|
|
482
|
-
.catch((err) => {
|
|
483
|
-
log.error(
|
|
484
|
-
{ parentConversationId, err },
|
|
485
|
-
"Failed to process subagent notification in parent",
|
|
486
|
-
);
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
};
|
|
490
|
-
getAcpSessionManager().onAcpSessionFinished = async (
|
|
491
|
-
parentConversationId,
|
|
492
|
-
message,
|
|
493
|
-
sendToClient,
|
|
494
|
-
) => {
|
|
495
|
-
const parentConversation = this.conversations.get(parentConversationId);
|
|
496
|
-
if (!parentConversation) {
|
|
497
|
-
log.warn(
|
|
498
|
-
{ parentConversationId },
|
|
499
|
-
"ACP agent finished but parent conversation not found",
|
|
500
|
-
);
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
const requestId = `acp-notify-${Date.now()}`;
|
|
504
|
-
const enqueueResult = parentConversation.enqueueMessage(
|
|
505
|
-
message,
|
|
506
|
-
[],
|
|
507
|
-
sendToClient,
|
|
508
|
-
requestId,
|
|
509
|
-
);
|
|
510
|
-
if (!enqueueResult.queued && !enqueueResult.rejected) {
|
|
511
|
-
const messageId = await parentConversation.persistUserMessage(
|
|
512
|
-
message,
|
|
513
|
-
[],
|
|
514
|
-
);
|
|
515
|
-
parentConversation
|
|
516
|
-
.runAgentLoop(message, messageId, sendToClient)
|
|
517
|
-
.catch((err: unknown) => {
|
|
518
|
-
log.error(
|
|
519
|
-
{ parentConversationId, err },
|
|
520
|
-
"Failed to process ACP notification in parent",
|
|
521
|
-
);
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
// ── Broadcast / Event publishing ──────────────────────────────────
|
|
528
|
-
|
|
529
|
-
/**
|
|
530
|
-
* Publish `msg` as an `AssistantEvent` to the process-level hub.
|
|
531
|
-
* Publications are serialized via a promise chain so subscribers
|
|
532
|
-
* always observe events in send order.
|
|
533
|
-
*/
|
|
534
|
-
private publishAssistantEvent(
|
|
535
|
-
msg: ServerMessage,
|
|
536
|
-
conversationId?: string,
|
|
537
|
-
): void {
|
|
538
|
-
const id = this.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID;
|
|
539
|
-
const event = buildAssistantEvent(id, msg, conversationId);
|
|
540
|
-
this._hubChain = this._hubChain
|
|
541
|
-
.then(() => assistantEventHub.publish(event))
|
|
542
|
-
.catch((err: unknown) => {
|
|
543
|
-
log.warn(
|
|
544
|
-
{ err },
|
|
545
|
-
"assistant-events hub subscriber threw during broadcast",
|
|
546
|
-
);
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
// Dual-write to file-based stream for cross-process consumers.
|
|
550
|
-
// No-op when no subscriber files exist for this conversation.
|
|
551
|
-
if (conversationId) {
|
|
552
|
-
try {
|
|
553
|
-
appendEventToStream(conversationId, event);
|
|
554
|
-
} catch {
|
|
555
|
-
// Best-effort; file I/O failures must not block the hub chain.
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
broadcast(msg: ServerMessage): void {
|
|
561
|
-
const conversationId = extractConversationId(msg);
|
|
562
|
-
this.publishAssistantEvent(msg, conversationId);
|
|
563
158
|
}
|
|
564
159
|
|
|
565
160
|
private broadcastIdentityChanged(): void {
|
|
@@ -569,7 +164,7 @@ export class DaemonServer {
|
|
|
569
164
|
? readFileSync(identityPath, "utf-8")
|
|
570
165
|
: "";
|
|
571
166
|
const fields = parseIdentityFields(content);
|
|
572
|
-
|
|
167
|
+
broadcastMessage({
|
|
573
168
|
type: "identity_changed",
|
|
574
169
|
name: fields.name,
|
|
575
170
|
role: fields.role,
|
|
@@ -604,19 +199,15 @@ export class DaemonServer {
|
|
|
604
199
|
}
|
|
605
200
|
|
|
606
201
|
private broadcastConfigChanged(): void {
|
|
607
|
-
|
|
202
|
+
broadcastMessage({ type: "config_changed" });
|
|
608
203
|
}
|
|
609
204
|
|
|
610
205
|
private broadcastSoundsConfigUpdated(): void {
|
|
611
|
-
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
private broadcastFeatureFlagsChanged(): void {
|
|
615
|
-
this.broadcast({ type: "feature_flags_changed" });
|
|
206
|
+
broadcastMessage({ type: "sounds_config_updated" });
|
|
616
207
|
}
|
|
617
208
|
|
|
618
209
|
private broadcastAvatarUpdated(): void {
|
|
619
|
-
|
|
210
|
+
broadcastMessage({
|
|
620
211
|
type: "avatar_updated",
|
|
621
212
|
avatarPath: getAvatarImagePath(),
|
|
622
213
|
});
|
|
@@ -631,10 +222,10 @@ export class DaemonServer {
|
|
|
631
222
|
if (!app) return;
|
|
632
223
|
|
|
633
224
|
const doRefresh = () => {
|
|
634
|
-
for (const conversation of
|
|
225
|
+
for (const conversation of allConversations()) {
|
|
635
226
|
refreshSurfacesForApp(conversation, appId, { fileChange: true });
|
|
636
227
|
}
|
|
637
|
-
|
|
228
|
+
broadcastMessage({ type: "app_files_changed", appId });
|
|
638
229
|
void updatePublishedAppDeployment(appId);
|
|
639
230
|
};
|
|
640
231
|
|
|
@@ -669,257 +260,13 @@ export class DaemonServer {
|
|
|
669
260
|
|
|
670
261
|
this.evictor.start();
|
|
671
262
|
|
|
672
|
-
|
|
673
|
-
getOrCreateConversation: (conversationId) =>
|
|
674
|
-
this.getOrCreateConversation(conversationId),
|
|
675
|
-
broadcast: (msg) => this.broadcast(msg),
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
registerCancelCallback((conversationId) => {
|
|
679
|
-
const conversation = this.conversations.get(conversationId);
|
|
680
|
-
if (!conversation) return false;
|
|
681
|
-
this.evictor.touch(conversationId);
|
|
682
|
-
conversation.abort(
|
|
683
|
-
createAbortReason(
|
|
684
|
-
"signal_cancel",
|
|
685
|
-
"registerCancelCallback",
|
|
686
|
-
conversationId,
|
|
687
|
-
),
|
|
688
|
-
);
|
|
689
|
-
getSubagentManager().abortAllForParent(conversationId);
|
|
690
|
-
return true;
|
|
691
|
-
});
|
|
692
|
-
|
|
693
|
-
registerConversationUndoCallback((conversationId) =>
|
|
694
|
-
undoLastMessage(conversationId, this.handlerContext()),
|
|
695
|
-
);
|
|
696
|
-
|
|
697
|
-
registerUserMessageCallback(async (params) => {
|
|
698
|
-
// Block messages containing known-format secrets before persistence
|
|
699
|
-
if (!params.bypassSecretCheck) {
|
|
700
|
-
const ingressResult = checkIngressForSecrets(params.content);
|
|
701
|
-
if (ingressResult.blocked) {
|
|
702
|
-
return {
|
|
703
|
-
accepted: false,
|
|
704
|
-
error: "secret_blocked" as const,
|
|
705
|
-
message: ingressResult.userNotice,
|
|
706
|
-
};
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
const { conversationId } = getOrCreateConversation(
|
|
711
|
-
params.conversationKey,
|
|
712
|
-
);
|
|
713
|
-
const conversation = await this.getOrCreateConversation(conversationId);
|
|
714
|
-
|
|
715
|
-
// Register file-backed attachments so they flow through the send
|
|
716
|
-
// pipeline as images the LLM can see directly.
|
|
717
|
-
const attachmentIds: string[] = [];
|
|
718
|
-
const resolvedAttachments: UserMessageAttachment[] = [];
|
|
719
|
-
if (params.attachments && params.attachments.length > 0) {
|
|
720
|
-
for (const a of params.attachments) {
|
|
721
|
-
try {
|
|
722
|
-
const validation = attachmentsStore.validateAttachmentUpload(
|
|
723
|
-
a.filename,
|
|
724
|
-
a.mimeType,
|
|
725
|
-
);
|
|
726
|
-
if (!validation.ok) {
|
|
727
|
-
log.warn(
|
|
728
|
-
{ error: validation.error, path: a.path },
|
|
729
|
-
"Signal attachment rejected by validation",
|
|
730
|
-
);
|
|
731
|
-
continue;
|
|
732
|
-
}
|
|
733
|
-
const size = statSync(a.path).size;
|
|
734
|
-
const stored = attachmentsStore.uploadFileBackedAttachment(
|
|
735
|
-
a.filename,
|
|
736
|
-
a.mimeType,
|
|
737
|
-
a.path,
|
|
738
|
-
size,
|
|
739
|
-
);
|
|
740
|
-
attachmentIds.push(stored.id);
|
|
741
|
-
resolvedAttachments.push({
|
|
742
|
-
id: stored.id,
|
|
743
|
-
filename: a.filename,
|
|
744
|
-
mimeType: a.mimeType,
|
|
745
|
-
data: "",
|
|
746
|
-
filePath: a.path,
|
|
747
|
-
});
|
|
748
|
-
} catch (err) {
|
|
749
|
-
log.warn(
|
|
750
|
-
{ err, path: a.path },
|
|
751
|
-
"Failed to register signal attachment",
|
|
752
|
-
);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// Build a hub-publishing sender so events reach SSE clients.
|
|
758
|
-
const hubSender = (msg: ServerMessage) => {
|
|
759
|
-
const msgConversationId =
|
|
760
|
-
"conversationId" in msg &&
|
|
761
|
-
typeof (msg as { conversationId?: unknown }).conversationId ===
|
|
762
|
-
"string"
|
|
763
|
-
? (msg as { conversationId: string }).conversationId
|
|
764
|
-
: undefined;
|
|
765
|
-
this.publishAssistantEvent(msg, msgConversationId ?? conversationId);
|
|
766
|
-
};
|
|
263
|
+
await this.cliIpc.start();
|
|
767
264
|
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
if (att.filePath && !att.data) {
|
|
774
|
-
try {
|
|
775
|
-
att.data = readFileSync(att.filePath).toString("base64");
|
|
776
|
-
} catch (err) {
|
|
777
|
-
log.warn(
|
|
778
|
-
{ err, path: att.filePath },
|
|
779
|
-
"Failed to read queued signal attachment, skipping",
|
|
780
|
-
);
|
|
781
|
-
resolvedAttachments.splice(i, 1);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
const requestId = crypto.randomUUID();
|
|
786
|
-
const resolvedChannel = resolveTurnChannel(params.sourceChannel);
|
|
787
|
-
const resolvedInterface = resolveTurnInterface(params.sourceInterface);
|
|
788
|
-
const result = conversation.enqueueMessage(
|
|
789
|
-
params.content,
|
|
790
|
-
resolvedAttachments,
|
|
791
|
-
hubSender,
|
|
792
|
-
requestId,
|
|
793
|
-
undefined,
|
|
794
|
-
undefined,
|
|
795
|
-
{
|
|
796
|
-
userMessageChannel: resolvedChannel,
|
|
797
|
-
assistantMessageChannel: resolvedChannel,
|
|
798
|
-
userMessageInterface: resolvedInterface,
|
|
799
|
-
assistantMessageInterface: resolvedInterface,
|
|
800
|
-
},
|
|
801
|
-
);
|
|
802
|
-
return { accepted: !result.rejected };
|
|
803
|
-
}
|
|
804
|
-
await this.persistAndProcessMessage(
|
|
805
|
-
conversationId,
|
|
806
|
-
params.content,
|
|
807
|
-
attachmentIds.length > 0 ? attachmentIds : undefined,
|
|
808
|
-
{ onEvent: hubSender },
|
|
809
|
-
params.sourceChannel,
|
|
810
|
-
params.sourceInterface,
|
|
811
|
-
);
|
|
812
|
-
return { accepted: true };
|
|
813
|
-
});
|
|
814
|
-
|
|
815
|
-
// Install the default resolver for `wakeAgentForOpportunity()` so
|
|
816
|
-
// internal subsystems (e.g. the Meet chat-opportunity detector wired
|
|
817
|
-
// up in `MeetSessionManager`) can invoke it without having to build
|
|
818
|
-
// a `WakeTarget` adapter themselves. The adapter wraps a live
|
|
819
|
-
// `Conversation` fetched from the in-memory map / hydrated from the
|
|
820
|
-
// DB, exposing only the narrow surface the wake helper needs.
|
|
821
|
-
registerDefaultWakeResolver(async (conversationId) => {
|
|
822
|
-
try {
|
|
823
|
-
// Only resolve existing conversations — don't create ghost
|
|
824
|
-
// conversations for stale targets (e.g. meetings that ended
|
|
825
|
-
// but a delayed opportunity callback still fires).
|
|
826
|
-
const existing = getConversation(conversationId);
|
|
827
|
-
if (!existing) return null;
|
|
828
|
-
const conversation = await this.getOrCreateConversation(conversationId);
|
|
829
|
-
return conversationToWakeTarget(conversation);
|
|
830
|
-
} catch (err) {
|
|
831
|
-
log.warn(
|
|
832
|
-
{ err, conversationId },
|
|
833
|
-
"agent-wake default resolver: failed to hydrate conversation",
|
|
834
|
-
);
|
|
835
|
-
return null;
|
|
836
|
-
}
|
|
837
|
-
});
|
|
838
|
-
|
|
839
|
-
// Install the interactive UI resolver so skills and IPC handlers can
|
|
840
|
-
// present ad-hoc UI surfaces (confirmations, forms) to the user via
|
|
841
|
-
// `requestInteractiveUi()`. Interactive UI requires a client to be
|
|
842
|
-
// actively connected to the conversation (via SSE), which means the
|
|
843
|
-
// conversation must be in the in-memory map. If the conversation was
|
|
844
|
-
// evicted from memory the client is definitely disconnected, so
|
|
845
|
-
// hydration from persistent storage is pointless — the hydrated
|
|
846
|
-
// conversation would have hasNoClient=true, causing
|
|
847
|
-
// canShowInteractiveUi() to return false and the surface to be
|
|
848
|
-
// cancelled with no_interactive_surface. We skip that wasted work
|
|
849
|
-
// and return conversation_not_found directly.
|
|
850
|
-
registerInteractiveUiResolver(async (request) => {
|
|
851
|
-
const conversation = this.conversations.get(request.conversationId);
|
|
852
|
-
|
|
853
|
-
if (!conversation) {
|
|
854
|
-
log.warn(
|
|
855
|
-
{
|
|
856
|
-
conversationId: request.conversationId,
|
|
857
|
-
surfaceType: request.surfaceType,
|
|
858
|
-
},
|
|
859
|
-
"interactive-ui resolver: conversation not in memory (client not connected); failing closed",
|
|
860
|
-
);
|
|
861
|
-
return {
|
|
862
|
-
status: "cancelled" as const,
|
|
863
|
-
surfaceId: `ui-resolver-${Date.now()}`,
|
|
864
|
-
cancellationReason: "conversation_not_found" as const,
|
|
865
|
-
};
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
// Generate a unique surface ID and delegate to the conversation's
|
|
869
|
-
// standalone surface lifecycle. The returned Promise blocks until
|
|
870
|
-
// the user submits, cancels, or the timeout elapses.
|
|
871
|
-
const surfaceId = `ui-standalone-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
872
|
-
return showStandaloneSurface(conversation, request, surfaceId);
|
|
873
|
-
});
|
|
874
|
-
|
|
875
|
-
// Allow `browser_execute` IPC calls to reuse live conversation browser
|
|
876
|
-
// proxy wiring (when a caller passes a conversationId from
|
|
877
|
-
// __CONVERSATION_ID / __SKILL_CONTEXT_JSON). This keeps nested
|
|
878
|
-
// `assistant browser status` checks consistent with the parent turn's
|
|
879
|
-
// extension connectivity instead of always falling back to a synthetic
|
|
880
|
-
// browser-cli session that has no hostBrowserProxy.
|
|
881
|
-
registerBrowserIpcContextResolver((conversationId) => {
|
|
882
|
-
const conversation = this.conversations.get(conversationId);
|
|
883
|
-
if (!conversation) return null;
|
|
884
|
-
return {
|
|
885
|
-
conversationId,
|
|
886
|
-
trustClass: conversation.trustContext?.trustClass ?? "guardian",
|
|
887
|
-
hostBrowserProxy: conversation.hostBrowserProxy,
|
|
888
|
-
transportInterface: conversation.transportInterface,
|
|
889
|
-
hostBrowserRegistryRouted: !!conversation.hostBrowserSenderOverride,
|
|
890
|
-
};
|
|
891
|
-
});
|
|
892
|
-
|
|
893
|
-
// Start the CLI IPC server. Built-in methods (wake_conversation) are
|
|
894
|
-
// registered by the constructor; CLI commands connect to this socket to
|
|
895
|
-
// invoke daemon-side operations that require in-process state.
|
|
896
|
-
this.cliIpc.start();
|
|
897
|
-
|
|
898
|
-
// Wire the launchConversation helper to daemon-side state so
|
|
899
|
-
// handleSurfaceAction can spawn conversations through it.
|
|
900
|
-
registerLaunchConversationDeps({
|
|
901
|
-
getOrCreateConversation: (id, options) =>
|
|
902
|
-
this.getOrCreateConversation(id, options),
|
|
903
|
-
persistAndProcessMessage: (
|
|
904
|
-
conversationId,
|
|
905
|
-
content,
|
|
906
|
-
attachmentIds,
|
|
907
|
-
options,
|
|
908
|
-
sourceChannel,
|
|
909
|
-
sourceInterface,
|
|
910
|
-
) =>
|
|
911
|
-
this.persistAndProcessMessage(
|
|
912
|
-
conversationId,
|
|
913
|
-
content,
|
|
914
|
-
attachmentIds,
|
|
915
|
-
options,
|
|
916
|
-
sourceChannel,
|
|
917
|
-
sourceInterface,
|
|
918
|
-
),
|
|
919
|
-
publishAssistantEvent: (msg, conversationId) =>
|
|
920
|
-
this.publishAssistantEvent(msg, conversationId),
|
|
921
|
-
getAssistantId: () => this.assistantId,
|
|
922
|
-
});
|
|
265
|
+
// Start the skill IPC server. First-party skill processes connect to this
|
|
266
|
+
// socket to access host capabilities (host.log, host.config.*,
|
|
267
|
+
// host.events.*, host.registries.*). Route registry is populated by
|
|
268
|
+
// subsequent PRs in the skill-isolation plan.
|
|
269
|
+
await this.skillIpc.start();
|
|
923
270
|
|
|
924
271
|
this.configWatcher.start(
|
|
925
272
|
() => this.evictConversationsForReload(),
|
|
@@ -927,7 +274,6 @@ export class DaemonServer {
|
|
|
927
274
|
() => this.broadcastSoundsConfigUpdated(),
|
|
928
275
|
() => this.broadcastAvatarUpdated(),
|
|
929
276
|
() => this.broadcastConfigChanged(),
|
|
930
|
-
() => this.broadcastFeatureFlagsChanged(),
|
|
931
277
|
);
|
|
932
278
|
|
|
933
279
|
this.syncIdentityToPlatform();
|
|
@@ -936,7 +282,7 @@ export class DaemonServer {
|
|
|
936
282
|
|
|
937
283
|
// Broadcast contacts_changed to all clients when any contact mutation occurs.
|
|
938
284
|
this.unsubscribeContactChange = onContactChange(() => {
|
|
939
|
-
|
|
285
|
+
broadcastMessage({ type: "contacts_changed" });
|
|
940
286
|
});
|
|
941
287
|
|
|
942
288
|
log.info("DaemonServer started (HTTP-only mode)");
|
|
@@ -949,15 +295,16 @@ export class DaemonServer {
|
|
|
949
295
|
this.configWatcher.stop();
|
|
950
296
|
this.appSourceWatcher.stop();
|
|
951
297
|
this.cliIpc.stop();
|
|
298
|
+
this.skillIpc.stop();
|
|
952
299
|
if (this.unsubscribeContactChange) {
|
|
953
300
|
this.unsubscribeContactChange();
|
|
954
301
|
this.unsubscribeContactChange = null;
|
|
955
302
|
}
|
|
956
303
|
|
|
957
|
-
for (const conversation of
|
|
304
|
+
for (const conversation of allConversations()) {
|
|
958
305
|
conversation.dispose();
|
|
959
306
|
}
|
|
960
|
-
|
|
307
|
+
clearConversations();
|
|
961
308
|
|
|
962
309
|
// Abort any in-flight CES initialization so it fails fast instead of
|
|
963
310
|
// blocking shutdown for up to ~15s (socket connect + handshake timeouts).
|
|
@@ -982,6 +329,7 @@ export class DaemonServer {
|
|
|
982
329
|
if (this.cesClientPromise) {
|
|
983
330
|
await this.cesClientPromise.catch(() => undefined);
|
|
984
331
|
this.cesClientPromise = undefined;
|
|
332
|
+
setCesClientPromise(undefined);
|
|
985
333
|
}
|
|
986
334
|
if (this.cesProcessManager) {
|
|
987
335
|
this.cesProcessManager = undefined;
|
|
@@ -993,49 +341,20 @@ export class DaemonServer {
|
|
|
993
341
|
// ── Conversation management ──────────────────────────────────────────────
|
|
994
342
|
|
|
995
343
|
broadcastStatus(): void {
|
|
996
|
-
|
|
344
|
+
broadcastMessage({
|
|
997
345
|
type: "assistant_status",
|
|
998
346
|
version: daemonVersion,
|
|
999
347
|
keyFingerprint: getSigningKeyFingerprint(),
|
|
1000
348
|
});
|
|
1001
349
|
}
|
|
1002
350
|
|
|
1003
|
-
clearAllConversations(): number {
|
|
1004
|
-
const count = this.conversations.size;
|
|
1005
|
-
const subagentManager = getSubagentManager();
|
|
1006
|
-
for (const id of this.conversations.keys()) {
|
|
1007
|
-
this.evictor.remove(id);
|
|
1008
|
-
subagentManager.abortAllForParent(id);
|
|
1009
|
-
}
|
|
1010
|
-
for (const conversation of this.conversations.values()) {
|
|
1011
|
-
conversation.dispose();
|
|
1012
|
-
}
|
|
1013
|
-
this.conversations.clear();
|
|
1014
|
-
this.conversationOptions.clear();
|
|
1015
|
-
return count;
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
/**
|
|
1019
|
-
* Abort and dispose a single in-memory conversation, removing it from the
|
|
1020
|
-
* conversation map. No-op if no conversation exists for the given ID.
|
|
1021
|
-
*/
|
|
1022
|
-
destroyConversation(conversationId: string): void {
|
|
1023
|
-
const conversation = this.conversations.get(conversationId);
|
|
1024
|
-
if (!conversation) return;
|
|
1025
|
-
this.evictor.remove(conversationId);
|
|
1026
|
-
getSubagentManager().abortAllForParent(conversationId);
|
|
1027
|
-
conversation.dispose();
|
|
1028
|
-
this.conversations.delete(conversationId);
|
|
1029
|
-
this.conversationOptions.delete(conversationId);
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
351
|
private evictConversationsForReload(): void {
|
|
1033
352
|
const subagentManager = getSubagentManager();
|
|
1034
|
-
for (const [id, conversation] of
|
|
353
|
+
for (const [id, conversation] of conversationEntries()) {
|
|
1035
354
|
if (!conversation.isProcessing()) {
|
|
1036
355
|
subagentManager.abortAllForParent(id);
|
|
1037
356
|
conversation.dispose();
|
|
1038
|
-
|
|
357
|
+
deleteConversation(id);
|
|
1039
358
|
this.evictor.remove(id);
|
|
1040
359
|
} else {
|
|
1041
360
|
conversation.markStale();
|
|
@@ -1065,687 +384,6 @@ export class DaemonServer {
|
|
|
1065
384
|
this.evictConversationsForReload();
|
|
1066
385
|
}
|
|
1067
386
|
|
|
1068
|
-
private async getOrCreateConversation(
|
|
1069
|
-
conversationId: string,
|
|
1070
|
-
options?: ConversationCreateOptions,
|
|
1071
|
-
): Promise<Conversation> {
|
|
1072
|
-
let conversation = this.conversations.get(conversationId);
|
|
1073
|
-
const sendToClient = () => {};
|
|
1074
|
-
|
|
1075
|
-
const { taskRunId: _taskRunId, ...persistentOptions } = options ?? {};
|
|
1076
|
-
if (Object.values(persistentOptions).some((v) => v !== undefined)) {
|
|
1077
|
-
this.conversationOptions.set(conversationId, {
|
|
1078
|
-
...this.conversationOptions.get(conversationId),
|
|
1079
|
-
...persistentOptions,
|
|
1080
|
-
});
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
if (
|
|
1084
|
-
!conversation ||
|
|
1085
|
-
(conversation.isStale() && !conversation.isProcessing())
|
|
1086
|
-
) {
|
|
1087
|
-
if (conversation) {
|
|
1088
|
-
getSubagentManager().abortAllForParent(conversationId);
|
|
1089
|
-
conversation.dispose();
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
const pending = this.conversationCreating.get(conversationId);
|
|
1093
|
-
if (pending) {
|
|
1094
|
-
conversation = await pending;
|
|
1095
|
-
return conversation;
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
const storedOptions = this.conversationOptions.get(conversationId);
|
|
1099
|
-
|
|
1100
|
-
const createPromise = (async () => {
|
|
1101
|
-
const config = getConfig();
|
|
1102
|
-
let provider = getProvider(config.llm.default.provider);
|
|
1103
|
-
// Per-call `options.config.callSite` can resolve to a provider name
|
|
1104
|
-
// that differs from `llm.default.provider`. Wrap the default
|
|
1105
|
-
// provider so the actual transport routes correctly per call,
|
|
1106
|
-
// rather than only forwarding metadata to the default's HTTP
|
|
1107
|
-
// client. See `providers/call-site-routing.ts`.
|
|
1108
|
-
provider = new CallSiteRoutingProvider(provider, (name) => {
|
|
1109
|
-
try {
|
|
1110
|
-
return getProvider(name);
|
|
1111
|
-
} catch {
|
|
1112
|
-
return undefined;
|
|
1113
|
-
}
|
|
1114
|
-
});
|
|
1115
|
-
const { rateLimit } = config;
|
|
1116
|
-
if (rateLimit.maxRequestsPerMinute > 0) {
|
|
1117
|
-
provider = new RateLimitProvider(
|
|
1118
|
-
provider,
|
|
1119
|
-
rateLimit,
|
|
1120
|
-
this.sharedRequestTimestamps,
|
|
1121
|
-
);
|
|
1122
|
-
}
|
|
1123
|
-
const workingDir = getSandboxWorkingDir();
|
|
1124
|
-
|
|
1125
|
-
const systemPrompt =
|
|
1126
|
-
storedOptions?.systemPromptOverride ?? buildSystemPrompt();
|
|
1127
|
-
const maxTokens =
|
|
1128
|
-
storedOptions?.maxResponseTokens ?? config.llm.default.maxTokens;
|
|
1129
|
-
|
|
1130
|
-
const memoryPolicy = this.deriveMemoryPolicy(conversationId);
|
|
1131
|
-
// Resolve the shared CES client (may still be initializing).
|
|
1132
|
-
const sharedCesClient = this.cesClientPromise
|
|
1133
|
-
? await this.cesClientPromise
|
|
1134
|
-
: undefined;
|
|
1135
|
-
const newConversation = new Conversation(
|
|
1136
|
-
conversationId,
|
|
1137
|
-
provider,
|
|
1138
|
-
systemPrompt,
|
|
1139
|
-
maxTokens,
|
|
1140
|
-
sendToClient,
|
|
1141
|
-
workingDir,
|
|
1142
|
-
(msg) => this.broadcast(msg),
|
|
1143
|
-
memoryPolicy,
|
|
1144
|
-
sharedCesClient,
|
|
1145
|
-
storedOptions?.speed,
|
|
1146
|
-
undefined,
|
|
1147
|
-
storedOptions?.modelOverride,
|
|
1148
|
-
);
|
|
1149
|
-
newConversation.updateClient(sendToClient, true);
|
|
1150
|
-
await newConversation.loadFromDb();
|
|
1151
|
-
// Restore trust/auth context and assistant ID from stored options so
|
|
1152
|
-
// that evicted sessions rehydrated by undo/regenerate don't run with
|
|
1153
|
-
// unscoped history. Without this, an untrusted actor could operate
|
|
1154
|
-
// on the full conversation after eviction.
|
|
1155
|
-
if (storedOptions?.assistantId) {
|
|
1156
|
-
newConversation.setAssistantId(storedOptions.assistantId);
|
|
1157
|
-
}
|
|
1158
|
-
if (storedOptions?.trustContext) {
|
|
1159
|
-
newConversation.setTrustContext(storedOptions.trustContext);
|
|
1160
|
-
}
|
|
1161
|
-
if (storedOptions?.authContext) {
|
|
1162
|
-
newConversation.setAuthContext(storedOptions.authContext);
|
|
1163
|
-
}
|
|
1164
|
-
if (storedOptions?.trustContext || storedOptions?.authContext) {
|
|
1165
|
-
await newConversation.ensureActorScopedHistory();
|
|
1166
|
-
}
|
|
1167
|
-
this.applyTransportMetadata(newConversation, storedOptions);
|
|
1168
|
-
this.conversations.set(conversationId, newConversation);
|
|
1169
|
-
return newConversation;
|
|
1170
|
-
})();
|
|
1171
|
-
|
|
1172
|
-
this.conversationCreating.set(conversationId, createPromise);
|
|
1173
|
-
try {
|
|
1174
|
-
conversation = await createPromise;
|
|
1175
|
-
} finally {
|
|
1176
|
-
this.conversationCreating.delete(conversationId);
|
|
1177
|
-
}
|
|
1178
|
-
this.evictor.touch(conversationId);
|
|
1179
|
-
} else {
|
|
1180
|
-
// Only apply transport metadata when the conversation is idle.
|
|
1181
|
-
// When processing, the hints are stored on the queued message and
|
|
1182
|
-
// will be applied at dequeue time — applying them here would
|
|
1183
|
-
// overwrite the in-flight conversation's transportHints.
|
|
1184
|
-
if (!conversation.isProcessing()) {
|
|
1185
|
-
this.applyTransportMetadata(conversation, options);
|
|
1186
|
-
// trustContext is reapplied here only when the conversation is idle,
|
|
1187
|
-
// so concurrent requests cannot overwrite an in-flight turn's guardian
|
|
1188
|
-
// scope. Direct callers (e.g. schedule-routes run-now) that invoke
|
|
1189
|
-
// processMessage without going through prepareConversationForMessage
|
|
1190
|
-
// rely on this to pick up the trustContext passed in options.
|
|
1191
|
-
// prepareConversationForMessage also reapplies after its own idle check.
|
|
1192
|
-
if (options?.trustContext !== undefined) {
|
|
1193
|
-
conversation.setTrustContext(options.trustContext);
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
this.evictor.touch(conversationId);
|
|
1197
|
-
}
|
|
1198
|
-
return conversation;
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
// ── Handler context ────────────────────────────────────────────────
|
|
1202
|
-
|
|
1203
|
-
private handlerContext(): HandlerContext {
|
|
1204
|
-
return {
|
|
1205
|
-
conversations: this.conversations,
|
|
1206
|
-
sharedRequestTimestamps: this.sharedRequestTimestamps,
|
|
1207
|
-
debounceTimers: this.configWatcher.timers,
|
|
1208
|
-
suppressConfigReload: this.configWatcher.suppressConfigReload,
|
|
1209
|
-
setSuppressConfigReload: (value: boolean) => {
|
|
1210
|
-
this.configWatcher.suppressConfigReload = value;
|
|
1211
|
-
},
|
|
1212
|
-
updateConfigFingerprint: () => {
|
|
1213
|
-
this.configWatcher.updateFingerprint();
|
|
1214
|
-
},
|
|
1215
|
-
send: (msg) => this.broadcast(msg),
|
|
1216
|
-
broadcast: (msg) => this.broadcast(msg),
|
|
1217
|
-
clearAllConversations: () => this.clearAllConversations(),
|
|
1218
|
-
getOrCreateConversation: (id, options?) =>
|
|
1219
|
-
this.getOrCreateConversation(id, options),
|
|
1220
|
-
touchConversation: (id) => this.evictor.touch(id),
|
|
1221
|
-
heartbeatService: this._heartbeatService,
|
|
1222
|
-
};
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
/** Public subset of handler context for skill management HTTP routes. */
|
|
1226
|
-
getSkillContext(): SkillOperationContext {
|
|
1227
|
-
return {
|
|
1228
|
-
debounceTimers: this.configWatcher.timers,
|
|
1229
|
-
setSuppressConfigReload: (value: boolean) => {
|
|
1230
|
-
this.configWatcher.suppressConfigReload = value;
|
|
1231
|
-
},
|
|
1232
|
-
updateConfigFingerprint: () => {
|
|
1233
|
-
this.configWatcher.updateFingerprint();
|
|
1234
|
-
},
|
|
1235
|
-
broadcast: (msg) => this.broadcast(msg),
|
|
1236
|
-
};
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
// ── HTTP message processing ─────────────────────────────────────────
|
|
1240
|
-
|
|
1241
|
-
private async prepareConversationForMessage(
|
|
1242
|
-
conversationId: string,
|
|
1243
|
-
content: string,
|
|
1244
|
-
attachmentIds: string[] | undefined,
|
|
1245
|
-
options: ConversationCreateOptions | undefined,
|
|
1246
|
-
sourceChannel: string | undefined,
|
|
1247
|
-
sourceInterface: string | undefined,
|
|
1248
|
-
): Promise<{
|
|
1249
|
-
conversation: Conversation;
|
|
1250
|
-
attachments: {
|
|
1251
|
-
id: string;
|
|
1252
|
-
filename: string;
|
|
1253
|
-
mimeType: string;
|
|
1254
|
-
data: string;
|
|
1255
|
-
filePath?: string;
|
|
1256
|
-
}[];
|
|
1257
|
-
}> {
|
|
1258
|
-
const conversation = await this.getOrCreateConversation(
|
|
1259
|
-
conversationId,
|
|
1260
|
-
options,
|
|
1261
|
-
);
|
|
1262
|
-
|
|
1263
|
-
if (conversation.isProcessing()) {
|
|
1264
|
-
throw new Error("Conversation is already processing a message");
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
const resolvedChannel = resolveTurnChannel(
|
|
1268
|
-
sourceChannel,
|
|
1269
|
-
options?.transport?.channelId,
|
|
1270
|
-
);
|
|
1271
|
-
const resolvedInterface = resolveTurnInterface(sourceInterface);
|
|
1272
|
-
conversation.setAssistantId(
|
|
1273
|
-
options?.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
|
|
1274
|
-
);
|
|
1275
|
-
conversation.taskRunId = options?.taskRunId;
|
|
1276
|
-
// Only overwrite trust/auth context when explicitly provided. Callers that
|
|
1277
|
-
// don't supply a trust context (e.g. signal-injected messages) should
|
|
1278
|
-
// inherit whatever the conversation already has from a prior session.
|
|
1279
|
-
if (options?.trustContext !== undefined) {
|
|
1280
|
-
conversation.setTrustContext(options.trustContext);
|
|
1281
|
-
}
|
|
1282
|
-
if (options?.authContext !== undefined) {
|
|
1283
|
-
conversation.setAuthContext(options.authContext);
|
|
1284
|
-
}
|
|
1285
|
-
await conversation.ensureActorScopedHistory();
|
|
1286
|
-
|
|
1287
|
-
// Persist the conversation's current trust/auth context so it survives
|
|
1288
|
-
// eviction and recreation. The restore path in getOrCreateConversation
|
|
1289
|
-
// reads from storedOptions.trustContext / storedOptions.authContext.
|
|
1290
|
-
// Always write — including null — so explicit clearing isn't lost.
|
|
1291
|
-
this.conversationOptions.set(conversationId, {
|
|
1292
|
-
...this.conversationOptions.get(conversationId),
|
|
1293
|
-
trustContext: conversation.trustContext,
|
|
1294
|
-
authContext: conversation.authContext,
|
|
1295
|
-
});
|
|
1296
|
-
conversation.setChannelCapabilities(
|
|
1297
|
-
resolveChannelCapabilities(
|
|
1298
|
-
sourceChannel,
|
|
1299
|
-
sourceInterface,
|
|
1300
|
-
options?.transport?.chatType,
|
|
1301
|
-
),
|
|
1302
|
-
);
|
|
1303
|
-
// Chrome-extension host_browser wiring is intentionally not supported
|
|
1304
|
-
// through this entry point. `prepareConversationForMessage` constructs
|
|
1305
|
-
// host_browser proxies that capture `conversation.getCurrentSender()`
|
|
1306
|
-
// directly, which routes browser frames through the daemon SSE channel.
|
|
1307
|
-
// This is correct for macOS (SSE-based host proxy), but chrome-extension
|
|
1308
|
-
// requires the `ChromeExtensionRegistry` WebSocket transport instead.
|
|
1309
|
-
// Chrome-extension flows reach host_browser exclusively through the
|
|
1310
|
-
// `/v1/messages` flow in `conversation-routes.ts`, which wires a
|
|
1311
|
-
// registry-aware sender and sets `hostBrowserSenderOverride`.
|
|
1312
|
-
//
|
|
1313
|
-
// Fail loudly rather than silently returning a mis-wired proxy so that
|
|
1314
|
-
// any future caller that tries to route chrome-extension through this
|
|
1315
|
-
// path discovers the gap immediately. When the time comes, factor the
|
|
1316
|
-
// wiring in conversation-routes.ts (registry lookup + override) into a
|
|
1317
|
-
// shared helper and call it from both sites.
|
|
1318
|
-
if (resolvedInterface === "chrome-extension") {
|
|
1319
|
-
throw new Error(
|
|
1320
|
-
"prepareConversationForMessage does not yet support chrome-extension transport — " +
|
|
1321
|
-
"use the conversation-routes.ts /v1/messages flow which routes host_browser through " +
|
|
1322
|
-
"the ChromeExtensionRegistry. If you need chrome-extension here, factor out the " +
|
|
1323
|
-
"wiring in conversation-routes.ts into a shared helper.",
|
|
1324
|
-
);
|
|
1325
|
-
}
|
|
1326
|
-
// Only create each host proxy for interfaces that support the matching
|
|
1327
|
-
// capability. macOS supports all four; the chrome-extension interface only
|
|
1328
|
-
// supports host_browser. Non-desktop conversations (CLI, channels, headless)
|
|
1329
|
-
// fall back to local execution.
|
|
1330
|
-
// Guard: don't replace an active proxy during concurrent turn races —
|
|
1331
|
-
// another request may have started processing between the isProcessing()
|
|
1332
|
-
// check above and the await on ensureActorScopedHistory().
|
|
1333
|
-
if (supportsHostProxy(resolvedInterface, "host_bash")) {
|
|
1334
|
-
if (!conversation.isProcessing() || !conversation.hostBashProxy) {
|
|
1335
|
-
conversation.setHostBashProxy(
|
|
1336
|
-
new HostBashProxy(conversation.getCurrentSender(), (requestId) => {
|
|
1337
|
-
pendingInteractions.resolve(requestId);
|
|
1338
|
-
}),
|
|
1339
|
-
);
|
|
1340
|
-
}
|
|
1341
|
-
} else if (!conversation.isProcessing()) {
|
|
1342
|
-
conversation.setHostBashProxy(undefined);
|
|
1343
|
-
}
|
|
1344
|
-
if (supportsHostProxy(resolvedInterface, "host_browser")) {
|
|
1345
|
-
if (!conversation.isProcessing() || !conversation.hostBrowserProxy) {
|
|
1346
|
-
conversation.setHostBrowserProxy(
|
|
1347
|
-
new HostBrowserProxy(conversation.getCurrentSender(), (requestId) => {
|
|
1348
|
-
pendingInteractions.resolve(requestId);
|
|
1349
|
-
}),
|
|
1350
|
-
);
|
|
1351
|
-
}
|
|
1352
|
-
} else if (!conversation.isProcessing()) {
|
|
1353
|
-
conversation.setHostBrowserProxy(undefined);
|
|
1354
|
-
}
|
|
1355
|
-
if (supportsHostProxy(resolvedInterface, "host_file")) {
|
|
1356
|
-
if (!conversation.isProcessing() || !conversation.hostFileProxy) {
|
|
1357
|
-
conversation.setHostFileProxy(
|
|
1358
|
-
new HostFileProxy(conversation.getCurrentSender(), (requestId) => {
|
|
1359
|
-
pendingInteractions.resolve(requestId);
|
|
1360
|
-
}),
|
|
1361
|
-
);
|
|
1362
|
-
}
|
|
1363
|
-
} else if (!conversation.isProcessing()) {
|
|
1364
|
-
conversation.setHostFileProxy(undefined);
|
|
1365
|
-
}
|
|
1366
|
-
if (supportsHostProxy(resolvedInterface, "host_cu")) {
|
|
1367
|
-
if (!conversation.isProcessing() || !conversation.hostCuProxy) {
|
|
1368
|
-
conversation.setHostCuProxy(
|
|
1369
|
-
new HostCuProxy(conversation.getCurrentSender(), (requestId) => {
|
|
1370
|
-
pendingInteractions.resolve(requestId);
|
|
1371
|
-
}),
|
|
1372
|
-
);
|
|
1373
|
-
}
|
|
1374
|
-
conversation.addPreactivatedSkillId("computer-use");
|
|
1375
|
-
} else if (!conversation.isProcessing()) {
|
|
1376
|
-
conversation.setHostCuProxy(undefined);
|
|
1377
|
-
}
|
|
1378
|
-
conversation.setCommandIntent(options?.commandIntent ?? null);
|
|
1379
|
-
conversation.setTurnChannelContext({
|
|
1380
|
-
userMessageChannel: resolvedChannel,
|
|
1381
|
-
assistantMessageChannel: resolvedChannel,
|
|
1382
|
-
});
|
|
1383
|
-
conversation.setTurnInterfaceContext({
|
|
1384
|
-
userMessageInterface: resolvedInterface,
|
|
1385
|
-
assistantMessageInterface: resolvedInterface,
|
|
1386
|
-
});
|
|
1387
|
-
|
|
1388
|
-
const attachments = attachmentIds
|
|
1389
|
-
? (() => {
|
|
1390
|
-
const resolved = attachmentsStore.getAttachmentsByIds(attachmentIds, {
|
|
1391
|
-
hydrateFileData: true,
|
|
1392
|
-
});
|
|
1393
|
-
const sourcePaths =
|
|
1394
|
-
attachmentsStore.getSourcePathsForAttachments(attachmentIds);
|
|
1395
|
-
return resolved.map((a) => ({
|
|
1396
|
-
id: a.id,
|
|
1397
|
-
filename: a.originalFilename,
|
|
1398
|
-
mimeType: a.mimeType,
|
|
1399
|
-
data: a.dataBase64,
|
|
1400
|
-
...(sourcePaths.has(a.id)
|
|
1401
|
-
? { filePath: sourcePaths.get(a.id) }
|
|
1402
|
-
: {}),
|
|
1403
|
-
}));
|
|
1404
|
-
})()
|
|
1405
|
-
: [];
|
|
1406
|
-
|
|
1407
|
-
return { conversation, attachments };
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
async persistAndProcessMessage(
|
|
1411
|
-
conversationId: string,
|
|
1412
|
-
content: string,
|
|
1413
|
-
attachmentIds?: string[],
|
|
1414
|
-
options?: ConversationCreateOptions,
|
|
1415
|
-
sourceChannel?: string,
|
|
1416
|
-
sourceInterface?: string,
|
|
1417
|
-
): Promise<{ messageId: string }> {
|
|
1418
|
-
const { conversation, attachments } =
|
|
1419
|
-
await this.prepareConversationForMessage(
|
|
1420
|
-
conversationId,
|
|
1421
|
-
content,
|
|
1422
|
-
attachmentIds,
|
|
1423
|
-
options,
|
|
1424
|
-
sourceChannel,
|
|
1425
|
-
sourceInterface,
|
|
1426
|
-
);
|
|
1427
|
-
|
|
1428
|
-
const requestId = crypto.randomUUID();
|
|
1429
|
-
const messageId = await conversation.persistUserMessage(
|
|
1430
|
-
content,
|
|
1431
|
-
attachments,
|
|
1432
|
-
requestId,
|
|
1433
|
-
);
|
|
1434
|
-
|
|
1435
|
-
// Register pending interactions so channel approval interception can
|
|
1436
|
-
// find the conversation by requestId when confirmation/secret events fire.
|
|
1437
|
-
const registrar = makePendingInteractionRegistrar(
|
|
1438
|
-
conversation,
|
|
1439
|
-
conversationId,
|
|
1440
|
-
);
|
|
1441
|
-
const onEvent = options?.onEvent
|
|
1442
|
-
? (msg: ServerMessage) => {
|
|
1443
|
-
registrar(msg);
|
|
1444
|
-
try {
|
|
1445
|
-
options.onEvent!(msg);
|
|
1446
|
-
} catch (err) {
|
|
1447
|
-
log.error(
|
|
1448
|
-
{ err, conversationId },
|
|
1449
|
-
"onEvent callback failed; continuing agent loop",
|
|
1450
|
-
);
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
: registrar;
|
|
1454
|
-
// Non-interactive interfaces that still have a connected client capable
|
|
1455
|
-
// of handling host_browser_request events (e.g. chrome-extension) need
|
|
1456
|
-
// their hostBrowserProxy explicitly marked connected. The proxy
|
|
1457
|
-
// constructor defaults clientConnected = false, so without an explicit
|
|
1458
|
-
// sender update the chrome-extension proxy would be created and
|
|
1459
|
-
// immediately unavailable. We do NOT call updateClient(onEvent, false)
|
|
1460
|
-
// for that case, because flipping hasNoClient false would also enable
|
|
1461
|
-
// host_bash/host_file/host_cu tool gating for an interface that can't
|
|
1462
|
-
// service them. Instead, provision just the browser proxy's sender.
|
|
1463
|
-
const persistInterfaceCtx = conversation.getTurnInterfaceContext();
|
|
1464
|
-
const persistInterface = persistInterfaceCtx?.userMessageInterface;
|
|
1465
|
-
if (options?.isInteractive === true) {
|
|
1466
|
-
conversation.updateClient(onEvent, false);
|
|
1467
|
-
} else if (
|
|
1468
|
-
persistInterface &&
|
|
1469
|
-
!supportsHostProxy(persistInterface) &&
|
|
1470
|
-
supportsHostProxy(persistInterface, "host_browser")
|
|
1471
|
-
) {
|
|
1472
|
-
conversation.hostBrowserProxy?.updateSender(onEvent, true);
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
conversation
|
|
1476
|
-
.runAgentLoop(content, messageId, onEvent, {
|
|
1477
|
-
isInteractive: options?.isInteractive ?? false,
|
|
1478
|
-
isUserMessage: true,
|
|
1479
|
-
...(options?.callSite ? { callSite: options.callSite } : {}),
|
|
1480
|
-
})
|
|
1481
|
-
.finally(() => {
|
|
1482
|
-
if (
|
|
1483
|
-
options?.isInteractive === true &&
|
|
1484
|
-
conversation.getCurrentSender() === onEvent
|
|
1485
|
-
) {
|
|
1486
|
-
conversation.updateClient(() => {}, true);
|
|
1487
|
-
}
|
|
1488
|
-
})
|
|
1489
|
-
.catch((err) => {
|
|
1490
|
-
log.error({ err, conversationId }, "Background agent loop failed");
|
|
1491
|
-
});
|
|
1492
|
-
|
|
1493
|
-
return { messageId };
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
async processMessage(
|
|
1497
|
-
conversationId: string,
|
|
1498
|
-
content: string,
|
|
1499
|
-
attachmentIds?: string[],
|
|
1500
|
-
options?: ConversationCreateOptions,
|
|
1501
|
-
sourceChannel?: string,
|
|
1502
|
-
sourceInterface?: string,
|
|
1503
|
-
): Promise<{ messageId: string }> {
|
|
1504
|
-
const { conversation, attachments } =
|
|
1505
|
-
await this.prepareConversationForMessage(
|
|
1506
|
-
conversationId,
|
|
1507
|
-
content,
|
|
1508
|
-
attachmentIds,
|
|
1509
|
-
options,
|
|
1510
|
-
sourceChannel,
|
|
1511
|
-
sourceInterface,
|
|
1512
|
-
);
|
|
1513
|
-
|
|
1514
|
-
const config = getConfig();
|
|
1515
|
-
const serverInterfaceCtx = conversation.getTurnInterfaceContext();
|
|
1516
|
-
const slashContext: SlashContext = {
|
|
1517
|
-
messageCount: conversation.getMessages().length,
|
|
1518
|
-
inputTokens: conversation.usageStats.inputTokens,
|
|
1519
|
-
outputTokens: conversation.usageStats.outputTokens,
|
|
1520
|
-
maxInputTokens: config.llm.default.contextWindow.maxInputTokens,
|
|
1521
|
-
model: config.llm.default.model,
|
|
1522
|
-
provider: config.llm.default.provider,
|
|
1523
|
-
estimatedCost: conversation.usageStats.estimatedCost,
|
|
1524
|
-
userMessageInterface: serverInterfaceCtx?.userMessageInterface,
|
|
1525
|
-
};
|
|
1526
|
-
const slashResult = await resolveSlash(content, slashContext);
|
|
1527
|
-
|
|
1528
|
-
// Slack inbound metadata is materialized once here for the slash-command
|
|
1529
|
-
// bypass paths (unknown-slash and /compact), which persist the user row
|
|
1530
|
-
// directly via `addMessage` and would otherwise drop the envelope. The
|
|
1531
|
-
// agent-loop path does not consume this variable — it forwards
|
|
1532
|
-
// `options.slackInbound` through `persistMetadata` and the envelope is
|
|
1533
|
-
// built internally by `buildSlackMetaForPersistence` inside
|
|
1534
|
-
// `persistQueuedMessageBody`.
|
|
1535
|
-
const slackMeta = buildSlackMetaForPersistence({
|
|
1536
|
-
slackInbound: options?.slackInbound,
|
|
1537
|
-
turnChannel: conversation.getTurnChannelContext()?.userMessageChannel,
|
|
1538
|
-
});
|
|
1539
|
-
|
|
1540
|
-
if (slashResult.kind === "unknown") {
|
|
1541
|
-
const serverTurnCtx = conversation.getTurnChannelContext();
|
|
1542
|
-
const serverProvenance = provenanceFromTrustContext(
|
|
1543
|
-
conversation.trustContext,
|
|
1544
|
-
);
|
|
1545
|
-
const imageSourcePaths: Record<string, string> = {};
|
|
1546
|
-
for (let i = 0; i < attachments.length; i++) {
|
|
1547
|
-
const a = attachments[i];
|
|
1548
|
-
if (a.filePath && a.mimeType.toLowerCase().startsWith("image/")) {
|
|
1549
|
-
imageSourcePaths[`${i}:${a.filename}`] = a.filePath;
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
const serverChannelMeta = {
|
|
1553
|
-
...serverProvenance,
|
|
1554
|
-
...(serverTurnCtx
|
|
1555
|
-
? {
|
|
1556
|
-
userMessageChannel: serverTurnCtx.userMessageChannel,
|
|
1557
|
-
assistantMessageChannel: serverTurnCtx.assistantMessageChannel,
|
|
1558
|
-
}
|
|
1559
|
-
: {}),
|
|
1560
|
-
...(serverInterfaceCtx
|
|
1561
|
-
? {
|
|
1562
|
-
userMessageInterface: serverInterfaceCtx.userMessageInterface,
|
|
1563
|
-
assistantMessageInterface:
|
|
1564
|
-
serverInterfaceCtx.assistantMessageInterface,
|
|
1565
|
-
}
|
|
1566
|
-
: {}),
|
|
1567
|
-
...(Object.keys(imageSourcePaths).length > 0
|
|
1568
|
-
? { imageSourcePaths }
|
|
1569
|
-
: {}),
|
|
1570
|
-
};
|
|
1571
|
-
// slackMeta encodes the inbound user message's ts/thread — it attaches
|
|
1572
|
-
// to the user row only. The assistant's slash-command response does not
|
|
1573
|
-
// originate from Slack and must not inherit the user's channelTs, which
|
|
1574
|
-
// would break ordering in the chronological renderer.
|
|
1575
|
-
const userMetaWithSlack = slackMeta
|
|
1576
|
-
? { ...serverChannelMeta, slackMeta }
|
|
1577
|
-
: serverChannelMeta;
|
|
1578
|
-
const cleanMsg = createUserMessage(content, attachments);
|
|
1579
|
-
const llmMsg = enrichMessageWithSourcePaths(cleanMsg, attachments);
|
|
1580
|
-
const persisted = await addMessage(
|
|
1581
|
-
conversationId,
|
|
1582
|
-
"user",
|
|
1583
|
-
JSON.stringify(cleanMsg.content),
|
|
1584
|
-
userMetaWithSlack,
|
|
1585
|
-
);
|
|
1586
|
-
conversation.getMessages().push(llmMsg);
|
|
1587
|
-
|
|
1588
|
-
if (serverTurnCtx) {
|
|
1589
|
-
try {
|
|
1590
|
-
setConversationOriginChannelIfUnset(
|
|
1591
|
-
conversationId,
|
|
1592
|
-
serverTurnCtx.userMessageChannel,
|
|
1593
|
-
);
|
|
1594
|
-
} catch (err) {
|
|
1595
|
-
log.warn(
|
|
1596
|
-
{ err, conversationId },
|
|
1597
|
-
"Failed to set origin channel (best-effort)",
|
|
1598
|
-
);
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
if (serverInterfaceCtx) {
|
|
1602
|
-
try {
|
|
1603
|
-
setConversationOriginInterfaceIfUnset(
|
|
1604
|
-
conversationId,
|
|
1605
|
-
serverInterfaceCtx.userMessageInterface,
|
|
1606
|
-
);
|
|
1607
|
-
} catch (err) {
|
|
1608
|
-
log.warn(
|
|
1609
|
-
{ err, conversationId },
|
|
1610
|
-
"Failed to set origin interface (best-effort)",
|
|
1611
|
-
);
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
// Rewrite meta.json so the on-disk metadata reflects the origin channel
|
|
1616
|
-
if (serverTurnCtx || serverInterfaceCtx) {
|
|
1617
|
-
try {
|
|
1618
|
-
const convForMeta = getConversation(conversationId);
|
|
1619
|
-
if (convForMeta) {
|
|
1620
|
-
updateMetaFile(convForMeta);
|
|
1621
|
-
}
|
|
1622
|
-
} catch (err) {
|
|
1623
|
-
log.warn(
|
|
1624
|
-
{ err, conversationId },
|
|
1625
|
-
"Failed to update disk meta (best-effort)",
|
|
1626
|
-
);
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
const assistantMsg = createAssistantMessage(slashResult.message);
|
|
1631
|
-
await addMessage(
|
|
1632
|
-
conversationId,
|
|
1633
|
-
"assistant",
|
|
1634
|
-
JSON.stringify(assistantMsg.content),
|
|
1635
|
-
serverChannelMeta,
|
|
1636
|
-
);
|
|
1637
|
-
conversation.getMessages().push(assistantMsg);
|
|
1638
|
-
return { messageId: persisted.id };
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
if (slashResult.kind === "compact") {
|
|
1642
|
-
const serverTurnCtx = conversation.getTurnChannelContext();
|
|
1643
|
-
const serverProvenance = provenanceFromTrustContext(
|
|
1644
|
-
conversation.trustContext,
|
|
1645
|
-
);
|
|
1646
|
-
const compactChannelMeta = {
|
|
1647
|
-
...serverProvenance,
|
|
1648
|
-
...(serverTurnCtx
|
|
1649
|
-
? {
|
|
1650
|
-
userMessageChannel: serverTurnCtx.userMessageChannel,
|
|
1651
|
-
assistantMessageChannel: serverTurnCtx.assistantMessageChannel,
|
|
1652
|
-
}
|
|
1653
|
-
: {}),
|
|
1654
|
-
...(serverInterfaceCtx
|
|
1655
|
-
? {
|
|
1656
|
-
userMessageInterface: serverInterfaceCtx.userMessageInterface,
|
|
1657
|
-
assistantMessageInterface:
|
|
1658
|
-
serverInterfaceCtx.assistantMessageInterface,
|
|
1659
|
-
}
|
|
1660
|
-
: {}),
|
|
1661
|
-
};
|
|
1662
|
-
const compactUserMeta = slackMeta
|
|
1663
|
-
? { ...compactChannelMeta, slackMeta }
|
|
1664
|
-
: compactChannelMeta;
|
|
1665
|
-
const cleanMsg = createUserMessage(content, attachments);
|
|
1666
|
-
const persisted = await addMessage(
|
|
1667
|
-
conversationId,
|
|
1668
|
-
"user",
|
|
1669
|
-
JSON.stringify(cleanMsg.content),
|
|
1670
|
-
compactUserMeta,
|
|
1671
|
-
);
|
|
1672
|
-
conversation.getMessages().push(cleanMsg);
|
|
1673
|
-
|
|
1674
|
-
conversation.emitActivityState(
|
|
1675
|
-
"thinking",
|
|
1676
|
-
"context_compacting",
|
|
1677
|
-
"assistant_turn",
|
|
1678
|
-
);
|
|
1679
|
-
const result = await conversation.forceCompact();
|
|
1680
|
-
const responseText = formatCompactResult(result);
|
|
1681
|
-
const assistantMsg = createAssistantMessage(responseText);
|
|
1682
|
-
await addMessage(
|
|
1683
|
-
conversationId,
|
|
1684
|
-
"assistant",
|
|
1685
|
-
JSON.stringify(assistantMsg.content),
|
|
1686
|
-
compactChannelMeta,
|
|
1687
|
-
);
|
|
1688
|
-
conversation.getMessages().push(assistantMsg);
|
|
1689
|
-
return { messageId: persisted.id };
|
|
1690
|
-
}
|
|
1691
|
-
|
|
1692
|
-
const resolvedContent = slashResult.content;
|
|
1693
|
-
|
|
1694
|
-
const requestId = crypto.randomUUID();
|
|
1695
|
-
// Slack inbound metadata captured at the channel ingress boundary is
|
|
1696
|
-
// forwarded into the persistence call so `persistQueuedMessageBody` can
|
|
1697
|
-
// emit a `slackMeta` envelope on the row's metadata column.
|
|
1698
|
-
const persistMetadata = options?.slackInbound
|
|
1699
|
-
? { slackInbound: options.slackInbound }
|
|
1700
|
-
: undefined;
|
|
1701
|
-
const messageId = await conversation.persistUserMessage(
|
|
1702
|
-
resolvedContent,
|
|
1703
|
-
attachments,
|
|
1704
|
-
requestId,
|
|
1705
|
-
persistMetadata,
|
|
1706
|
-
);
|
|
1707
|
-
|
|
1708
|
-
// Register pending interactions so channel approval interception can
|
|
1709
|
-
// find the conversation by requestId when confirmation/secret events fire.
|
|
1710
|
-
const registrar = makePendingInteractionRegistrar(
|
|
1711
|
-
conversation,
|
|
1712
|
-
conversationId,
|
|
1713
|
-
);
|
|
1714
|
-
const onEvent = options?.onEvent
|
|
1715
|
-
? (msg: ServerMessage) => {
|
|
1716
|
-
registrar(msg);
|
|
1717
|
-
try {
|
|
1718
|
-
options.onEvent!(msg);
|
|
1719
|
-
} catch (err) {
|
|
1720
|
-
log.error(
|
|
1721
|
-
{ err, conversationId },
|
|
1722
|
-
"onEvent callback failed; continuing agent loop",
|
|
1723
|
-
);
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
: registrar;
|
|
1727
|
-
if (options?.isInteractive === true) {
|
|
1728
|
-
conversation.updateClient(onEvent, false);
|
|
1729
|
-
}
|
|
1730
|
-
|
|
1731
|
-
try {
|
|
1732
|
-
await conversation.runAgentLoop(resolvedContent, messageId, onEvent, {
|
|
1733
|
-
isInteractive: options?.isInteractive ?? false,
|
|
1734
|
-
isUserMessage: true,
|
|
1735
|
-
...(options?.callSite ? { callSite: options.callSite } : {}),
|
|
1736
|
-
});
|
|
1737
|
-
} finally {
|
|
1738
|
-
if (
|
|
1739
|
-
options?.isInteractive === true &&
|
|
1740
|
-
conversation.getCurrentSender() === onEvent
|
|
1741
|
-
) {
|
|
1742
|
-
conversation.updateClient(() => {}, true);
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
|
|
1746
|
-
return { messageId };
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
387
|
/**
|
|
1750
388
|
* Expose conversation lookup for the POST /v1/messages handler.
|
|
1751
389
|
* The handler manages busy-state checking and queueing itself.
|
|
@@ -1754,288 +392,6 @@ export class DaemonServer {
|
|
|
1754
392
|
conversationId: string,
|
|
1755
393
|
options?: ConversationCreateOptions,
|
|
1756
394
|
): Promise<Conversation> {
|
|
1757
|
-
return
|
|
395
|
+
return getOrCreateActiveConversation(conversationId, options);
|
|
1758
396
|
}
|
|
1759
|
-
|
|
1760
|
-
/**
|
|
1761
|
-
* Look up an active conversation by ID without creating one.
|
|
1762
|
-
*/
|
|
1763
|
-
findConversation(conversationId: string): Conversation | undefined {
|
|
1764
|
-
return this.conversations.get(conversationId);
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
/**
|
|
1768
|
-
* Look up an active conversation that owns a given surfaceId.
|
|
1769
|
-
*/
|
|
1770
|
-
findConversationBySurfaceId(surfaceId: string): Conversation | undefined {
|
|
1771
|
-
// Fast path: exact surfaceId match in surfaceState
|
|
1772
|
-
for (const c of this.conversations.values()) {
|
|
1773
|
-
if (c.surfaceState.has(surfaceId)) return c;
|
|
1774
|
-
}
|
|
1775
|
-
|
|
1776
|
-
// Fallback: standalone app surfaces use "app-open-{appId}" IDs that
|
|
1777
|
-
// were never part of any conversation. Extract the appId and find
|
|
1778
|
-
// a conversation whose surfaceState has a surface for that app.
|
|
1779
|
-
const appOpenPrefix = "app-open-";
|
|
1780
|
-
if (surfaceId.startsWith(appOpenPrefix)) {
|
|
1781
|
-
const appId = surfaceId.slice(appOpenPrefix.length);
|
|
1782
|
-
for (const c of this.conversations.values()) {
|
|
1783
|
-
for (const [, state] of c.surfaceState.entries()) {
|
|
1784
|
-
const data = state.data as unknown as Record<string, unknown>;
|
|
1785
|
-
if (data?.appId === appId) {
|
|
1786
|
-
// Register this surfaceId so subsequent lookups are O(1)
|
|
1787
|
-
c.surfaceState.set(surfaceId, state);
|
|
1788
|
-
return c;
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
|
|
1794
|
-
return undefined;
|
|
1795
|
-
}
|
|
1796
|
-
|
|
1797
|
-
/**
|
|
1798
|
-
* Expose the handler context for use by conversation management HTTP routes.
|
|
1799
|
-
* The context is built on-the-fly so it always reflects the current server state.
|
|
1800
|
-
*/
|
|
1801
|
-
getHandlerContext(): HandlerContext {
|
|
1802
|
-
return this.handlerContext();
|
|
1803
|
-
}
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
/** Extract conversationId from a ServerMessage if present. */
|
|
1807
|
-
function extractConversationId(msg: ServerMessage): string | undefined {
|
|
1808
|
-
const record = msg as unknown as Record<string, unknown>;
|
|
1809
|
-
if ("conversationId" in msg && typeof record.conversationId === "string") {
|
|
1810
|
-
return record.conversationId as string;
|
|
1811
|
-
}
|
|
1812
|
-
return undefined;
|
|
1813
|
-
}
|
|
1814
|
-
|
|
1815
|
-
/**
|
|
1816
|
-
* Translate a raw {@link AgentEvent} from the agent loop into the
|
|
1817
|
-
* corresponding {@link ServerMessage} wire frame. The normal user-turn
|
|
1818
|
-
* path does this via the full state-aware handler in
|
|
1819
|
-
* `conversation-agent-loop-handlers.ts`; the wake path has no tool
|
|
1820
|
-
* accounting, title generation, or activity-state tracking to worry
|
|
1821
|
-
* about, so we only need the subset that produces client-visible
|
|
1822
|
-
* frames. Events that have no client-visible wire shape (usage, error,
|
|
1823
|
-
* preview/input-json deltas, etc.) are dropped — they produce no UI.
|
|
1824
|
-
*
|
|
1825
|
-
* Keeping this translator co-located with the wake adapter preserves
|
|
1826
|
-
* the runtime/daemon layering: `runtime/agent-wake.ts` never imports
|
|
1827
|
-
* `message-protocol.ts` or wire shapes, and the daemon owns all
|
|
1828
|
-
* translation from agent-loop semantics to client frames.
|
|
1829
|
-
*/
|
|
1830
|
-
function translateAgentEventToServerMessage(
|
|
1831
|
-
event: AgentEvent,
|
|
1832
|
-
conversationId: string,
|
|
1833
|
-
): ServerMessage | null {
|
|
1834
|
-
switch (event.type) {
|
|
1835
|
-
case "text_delta":
|
|
1836
|
-
return {
|
|
1837
|
-
type: "assistant_text_delta",
|
|
1838
|
-
text: event.text,
|
|
1839
|
-
conversationId,
|
|
1840
|
-
};
|
|
1841
|
-
case "thinking_delta":
|
|
1842
|
-
return {
|
|
1843
|
-
type: "assistant_thinking_delta",
|
|
1844
|
-
thinking: event.thinking,
|
|
1845
|
-
conversationId,
|
|
1846
|
-
};
|
|
1847
|
-
case "tool_use":
|
|
1848
|
-
return {
|
|
1849
|
-
type: "tool_use_start",
|
|
1850
|
-
toolName: event.name,
|
|
1851
|
-
input: event.input,
|
|
1852
|
-
conversationId,
|
|
1853
|
-
toolUseId: event.id,
|
|
1854
|
-
};
|
|
1855
|
-
case "tool_use_preview_start":
|
|
1856
|
-
return {
|
|
1857
|
-
type: "tool_use_preview_start",
|
|
1858
|
-
toolUseId: event.toolUseId,
|
|
1859
|
-
toolName: event.toolName,
|
|
1860
|
-
conversationId,
|
|
1861
|
-
};
|
|
1862
|
-
case "tool_output_chunk":
|
|
1863
|
-
return {
|
|
1864
|
-
type: "tool_output_chunk",
|
|
1865
|
-
chunk: event.chunk,
|
|
1866
|
-
conversationId,
|
|
1867
|
-
toolUseId: event.toolUseId,
|
|
1868
|
-
};
|
|
1869
|
-
case "tool_result": {
|
|
1870
|
-
const imageBlocks = event.contentBlocks?.filter(
|
|
1871
|
-
(b): b is Extract<typeof b, { type: "image" }> => b.type === "image",
|
|
1872
|
-
);
|
|
1873
|
-
const imageDataList = imageBlocks?.length
|
|
1874
|
-
? imageBlocks.map((b) => b.source.data)
|
|
1875
|
-
: undefined;
|
|
1876
|
-
return {
|
|
1877
|
-
type: "tool_result",
|
|
1878
|
-
toolName: "",
|
|
1879
|
-
result: event.content,
|
|
1880
|
-
isError: event.isError,
|
|
1881
|
-
diff: event.diff,
|
|
1882
|
-
status: event.status,
|
|
1883
|
-
conversationId,
|
|
1884
|
-
imageData: imageDataList?.[0],
|
|
1885
|
-
imageDataList,
|
|
1886
|
-
toolUseId: event.toolUseId,
|
|
1887
|
-
};
|
|
1888
|
-
}
|
|
1889
|
-
case "server_tool_start":
|
|
1890
|
-
return {
|
|
1891
|
-
type: "tool_use_start",
|
|
1892
|
-
toolName: event.name,
|
|
1893
|
-
input: event.input,
|
|
1894
|
-
conversationId,
|
|
1895
|
-
toolUseId: event.toolUseId,
|
|
1896
|
-
};
|
|
1897
|
-
case "server_tool_complete": {
|
|
1898
|
-
let resultText = "";
|
|
1899
|
-
if (Array.isArray(event.content) && event.content.length > 0) {
|
|
1900
|
-
resultText = (event.content as unknown[])
|
|
1901
|
-
.filter(
|
|
1902
|
-
(r): r is { type: string; title: string; url: string } =>
|
|
1903
|
-
typeof r === "object" &&
|
|
1904
|
-
r != null &&
|
|
1905
|
-
(r as { type?: string }).type === "web_search_result",
|
|
1906
|
-
)
|
|
1907
|
-
.map((r) => `${r.title}\n${r.url}`)
|
|
1908
|
-
.join("\n\n");
|
|
1909
|
-
}
|
|
1910
|
-
return {
|
|
1911
|
-
type: "tool_result",
|
|
1912
|
-
toolName: "web_search",
|
|
1913
|
-
result: resultText,
|
|
1914
|
-
isError: event.isError,
|
|
1915
|
-
conversationId,
|
|
1916
|
-
toolUseId: event.toolUseId,
|
|
1917
|
-
};
|
|
1918
|
-
}
|
|
1919
|
-
case "message_complete":
|
|
1920
|
-
return {
|
|
1921
|
-
type: "message_complete",
|
|
1922
|
-
conversationId,
|
|
1923
|
-
};
|
|
1924
|
-
// No wire frame for these — usage/error/input_json_delta are either
|
|
1925
|
-
// server-internal (accounting/classification) or app-only debug
|
|
1926
|
-
// streams the client doesn't surface for wake-originated turns.
|
|
1927
|
-
case "input_json_delta":
|
|
1928
|
-
case "usage":
|
|
1929
|
-
case "error":
|
|
1930
|
-
return null;
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
/**
|
|
1935
|
-
* Adapt a live {@link Conversation} to the narrow {@link WakeTarget}
|
|
1936
|
-
* surface expected by `wakeAgentForOpportunity()`. Kept here so the
|
|
1937
|
-
* runtime-level wake helper stays decoupled from the heavyweight
|
|
1938
|
-
* conversation class (see `registerDefaultWakeResolver` above).
|
|
1939
|
-
*
|
|
1940
|
-
* Routing notes:
|
|
1941
|
-
* - `emitAgentEvent` dispatches via `broadcastToAllClients` rather
|
|
1942
|
-
* than `sendToClient`. Several signal-injected paths reset
|
|
1943
|
-
* `sendToClient` to a no-op in their `finally` blocks (see the
|
|
1944
|
-
* `updateClient(() => {}, true)` calls in `persistAndProcessMessage`
|
|
1945
|
-
* / `processMessage`), so a wake fired on such a conversation would
|
|
1946
|
-
* find a silent sink. `broadcastToAllClients` is wired to
|
|
1947
|
-
* `this.broadcast(msg)` at construction time and always reaches the
|
|
1948
|
-
* hub, regardless of which sender the most-recent user turn left
|
|
1949
|
-
* behind.
|
|
1950
|
-
* - `persistTailMessage` mirrors the canonical user-turn handlers
|
|
1951
|
-
* (`handleMessageComplete` / the tool-result block in
|
|
1952
|
-
* `conversation-agent-loop-handlers.ts`): builds channel/interface
|
|
1953
|
-
* metadata via `provenanceFromTrustContext` plus the live turn
|
|
1954
|
-
* channel/interface contexts, persists with metadata, and syncs the
|
|
1955
|
-
* resulting row to the disk view so wake-produced messages appear
|
|
1956
|
-
* in the on-disk transcript and carry provenance tags.
|
|
1957
|
-
* - `drainQueue` delegates to the conversation so any user messages
|
|
1958
|
-
* queued while the wake was running are processed. The wake helper
|
|
1959
|
-
* calls this in its finally AFTER `markProcessing(false)`; the
|
|
1960
|
-
* order matters because `enqueueMessage` only queues when
|
|
1961
|
-
* `processing === true`.
|
|
1962
|
-
*/
|
|
1963
|
-
function conversationToWakeTarget(conversation: Conversation): WakeTarget {
|
|
1964
|
-
return {
|
|
1965
|
-
conversationId: conversation.conversationId,
|
|
1966
|
-
agentLoop: conversation.agentLoop,
|
|
1967
|
-
getMessages: () => conversation.getMessages(),
|
|
1968
|
-
pushMessage: (msg) => {
|
|
1969
|
-
conversation.messages.push(msg);
|
|
1970
|
-
},
|
|
1971
|
-
emitAgentEvent: (event) => {
|
|
1972
|
-
const frame = translateAgentEventToServerMessage(
|
|
1973
|
-
event,
|
|
1974
|
-
conversation.conversationId,
|
|
1975
|
-
);
|
|
1976
|
-
if (!frame) return;
|
|
1977
|
-
// Prefer `broadcastToAllClients` (wired to the hub at construction
|
|
1978
|
-
// time and always live) over `sendToClient` (which several
|
|
1979
|
-
// signal-injected paths reset to `() => {}` in their finally
|
|
1980
|
-
// blocks). Fall back to `sendToClient` when the broadcaster is
|
|
1981
|
-
// missing (e.g. in tests that construct a Conversation directly).
|
|
1982
|
-
if (conversation.broadcastToAllClients) {
|
|
1983
|
-
conversation.broadcastToAllClients(frame);
|
|
1984
|
-
} else {
|
|
1985
|
-
conversation.sendToClient(frame);
|
|
1986
|
-
}
|
|
1987
|
-
},
|
|
1988
|
-
isProcessing: () => conversation.isProcessing(),
|
|
1989
|
-
markProcessing: (on) => {
|
|
1990
|
-
conversation.processing = on;
|
|
1991
|
-
},
|
|
1992
|
-
persistTailMessage: async (message) => {
|
|
1993
|
-
// Build metadata that mirrors the canonical handlers in
|
|
1994
|
-
// `conversation-agent-loop-handlers.ts`. If the live turn channel
|
|
1995
|
-
// / interface contexts are missing (a wake can fire on a
|
|
1996
|
-
// conversation that has never run a user turn), fall back to the
|
|
1997
|
-
// conversation's origin channel/interface defaults (`"vellum"`)
|
|
1998
|
-
// so persisted rows still carry valid channel/interface ids.
|
|
1999
|
-
const turnChannelCtx = conversation.getTurnChannelContext();
|
|
2000
|
-
const turnInterfaceCtx = conversation.getTurnInterfaceContext();
|
|
2001
|
-
const metadata: Record<string, unknown> = {
|
|
2002
|
-
...provenanceFromTrustContext(conversation.trustContext),
|
|
2003
|
-
userMessageChannel: turnChannelCtx?.userMessageChannel ?? "vellum",
|
|
2004
|
-
assistantMessageChannel:
|
|
2005
|
-
turnChannelCtx?.assistantMessageChannel ?? "vellum",
|
|
2006
|
-
userMessageInterface:
|
|
2007
|
-
turnInterfaceCtx?.userMessageInterface ?? "vellum",
|
|
2008
|
-
assistantMessageInterface:
|
|
2009
|
-
turnInterfaceCtx?.assistantMessageInterface ?? "vellum",
|
|
2010
|
-
};
|
|
2011
|
-
const persisted = await addMessage(
|
|
2012
|
-
conversation.conversationId,
|
|
2013
|
-
message.role,
|
|
2014
|
-
JSON.stringify(message.content),
|
|
2015
|
-
metadata,
|
|
2016
|
-
);
|
|
2017
|
-
// Sync the persisted row to the disk view so wake-produced
|
|
2018
|
-
// messages appear in the on-disk transcript and tools that read
|
|
2019
|
-
// from disk (e.g. `messages.jsonl`-based diagnostics) see them.
|
|
2020
|
-
// Mirrors the `syncMessageToDisk(...)` calls in the canonical
|
|
2021
|
-
// handlers — best-effort because a sync failure must not strand
|
|
2022
|
-
// the in-memory tail.
|
|
2023
|
-
try {
|
|
2024
|
-
const convRow = getConversation(conversation.conversationId);
|
|
2025
|
-
if (convRow) {
|
|
2026
|
-
syncMessageToDisk(
|
|
2027
|
-
conversation.conversationId,
|
|
2028
|
-
persisted.id,
|
|
2029
|
-
convRow.createdAt,
|
|
2030
|
-
);
|
|
2031
|
-
}
|
|
2032
|
-
} catch (err) {
|
|
2033
|
-
log.warn(
|
|
2034
|
-
{ err, conversationId: conversation.conversationId },
|
|
2035
|
-
"wake adapter: syncMessageToDisk failed (non-fatal)",
|
|
2036
|
-
);
|
|
2037
|
-
}
|
|
2038
|
-
},
|
|
2039
|
-
drainQueue: () => conversation.drainQueue(),
|
|
2040
|
-
};
|
|
2041
397
|
}
|