@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
|
@@ -18,10 +18,8 @@ import {
|
|
|
18
18
|
createUserMessage,
|
|
19
19
|
} from "../../agent/message-types.js";
|
|
20
20
|
import {
|
|
21
|
-
canServiceRegistryBrowser,
|
|
22
21
|
CHANNEL_IDS,
|
|
23
22
|
INTERFACE_IDS,
|
|
24
|
-
type InterfaceId,
|
|
25
23
|
isInteractiveInterface,
|
|
26
24
|
parseChannelId,
|
|
27
25
|
parseInterfaceId,
|
|
@@ -29,6 +27,7 @@ import {
|
|
|
29
27
|
} from "../../channels/types.js";
|
|
30
28
|
import { isHttpAuthDisabled } from "../../config/env.js";
|
|
31
29
|
import { getConfig } from "../../config/loader.js";
|
|
30
|
+
import { createApprovalConversationGenerator } from "../../daemon/approval-generators.js";
|
|
32
31
|
import type { Conversation } from "../../daemon/conversation.js";
|
|
33
32
|
import {
|
|
34
33
|
buildModelInfoEvent,
|
|
@@ -36,34 +35,34 @@ import {
|
|
|
36
35
|
isModelSlashCommand,
|
|
37
36
|
} from "../../daemon/conversation-process.js";
|
|
38
37
|
import {
|
|
38
|
+
buildSlashContextForContent,
|
|
39
39
|
resolveSlash,
|
|
40
|
-
type SlashContext,
|
|
41
40
|
} from "../../daemon/conversation-slash.js";
|
|
41
|
+
import { getOrCreateConversation as getOrCreateConversationInstance } from "../../daemon/conversation-store.js";
|
|
42
42
|
import {
|
|
43
43
|
getCannedFirstGreeting,
|
|
44
44
|
isWakeUpGreeting,
|
|
45
45
|
} from "../../daemon/first-greeting.js";
|
|
46
46
|
import { renderHistoryContent } from "../../daemon/handlers/shared.js";
|
|
47
|
-
import { HostBashProxy } from "../../daemon/host-bash-proxy.js";
|
|
48
|
-
import { HostBrowserProxy } from "../../daemon/host-browser-proxy.js";
|
|
49
47
|
import { HostCuProxy } from "../../daemon/host-cu-proxy.js";
|
|
50
|
-
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
51
48
|
import type { ServerMessage } from "../../daemon/message-protocol.js";
|
|
52
49
|
import type {
|
|
53
50
|
HostProxyTransportMetadata,
|
|
54
51
|
NonHostProxyTransportMetadata,
|
|
55
52
|
} from "../../daemon/message-types/conversations.js";
|
|
56
|
-
import
|
|
57
|
-
import { emitFeedEvent } from "../../home/emit-feed-event.js";
|
|
53
|
+
import { HeartbeatService } from "../../heartbeat/heartbeat-service.js";
|
|
58
54
|
import {
|
|
59
55
|
writeOnboardingSidecar,
|
|
60
56
|
writeRelationshipState,
|
|
61
57
|
} from "../../home/relationship-state-writer.js";
|
|
62
|
-
import {
|
|
63
|
-
import
|
|
58
|
+
import { ipcCall } from "../../ipc/gateway-client.js";
|
|
59
|
+
import {
|
|
60
|
+
getAttachmentById,
|
|
61
|
+
getAttachmentMetadataForMessage,
|
|
62
|
+
getAttachmentsByIds,
|
|
63
|
+
getSourcePathsForAttachments,
|
|
64
|
+
} from "../../memory/attachments-store.js";
|
|
64
65
|
import {
|
|
65
|
-
createCanonicalGuardianRequest,
|
|
66
|
-
generateCanonicalRequestCode,
|
|
67
66
|
listCanonicalGuardianRequests,
|
|
68
67
|
listPendingRequestsByConversationScope,
|
|
69
68
|
resolveCanonicalGuardianRequest,
|
|
@@ -76,6 +75,7 @@ import {
|
|
|
76
75
|
hasMessages,
|
|
77
76
|
type MessageRow,
|
|
78
77
|
provenanceFromTrustContext,
|
|
78
|
+
setConversationInferenceProfile,
|
|
79
79
|
setConversationOriginChannelIfUnset,
|
|
80
80
|
setConversationOriginInterfaceIfUnset,
|
|
81
81
|
} from "../../memory/conversation-crud.js";
|
|
@@ -87,21 +87,17 @@ import { searchConversations } from "../../memory/conversation-queries.js";
|
|
|
87
87
|
import { getConfiguredProvider } from "../../providers/provider-send-message.js";
|
|
88
88
|
import type { Provider } from "../../providers/types.js";
|
|
89
89
|
import { checkIngressForSecrets } from "../../security/secret-ingress.js";
|
|
90
|
-
import { redactSecrets } from "../../security/secret-scanner.js";
|
|
91
|
-
import { summarizeToolInput } from "../../tools/tool-input-summary.js";
|
|
92
90
|
import { getLogger } from "../../util/logger.js";
|
|
93
|
-
import {
|
|
91
|
+
import {
|
|
92
|
+
getInterfacesDir,
|
|
93
|
+
getWorkspacePromptPath,
|
|
94
|
+
} from "../../util/platform.js";
|
|
94
95
|
import { silentlyWithLog } from "../../util/silently.js";
|
|
95
96
|
import { buildAssistantEvent } from "../assistant-event.js";
|
|
97
|
+
import { assistantEventHub, broadcastMessage } from "../assistant-event-hub.js";
|
|
96
98
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
97
|
-
import type { AuthContext } from "../auth/types.js";
|
|
98
|
-
import { getChromeExtensionRegistry } from "../chrome-extension-registry.js";
|
|
99
|
-
import { getClientRegistry } from "../client-registry.js";
|
|
100
|
-
import { bridgeConfirmationRequestToGuardian } from "../confirmation-request-guardian-bridge.js";
|
|
101
99
|
import { routeGuardianReply } from "../guardian-reply-router.js";
|
|
102
100
|
import { healGuardianBindingDrift } from "../guardian-vellum-migration.js";
|
|
103
|
-
import { httpError } from "../http-errors.js";
|
|
104
|
-
import type { RouteDefinition } from "../http-router.js";
|
|
105
101
|
import type {
|
|
106
102
|
ApprovalConversationGenerator,
|
|
107
103
|
RuntimeAttachmentMetadata,
|
|
@@ -114,6 +110,9 @@ import {
|
|
|
114
110
|
resolveTrustContext,
|
|
115
111
|
withSourceChannel,
|
|
116
112
|
} from "../trust-context-resolver.js";
|
|
113
|
+
import { BadRequestError, InternalError, RouteError } from "./errors.js";
|
|
114
|
+
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
115
|
+
import { RouteResponse } from "./types.js";
|
|
117
116
|
|
|
118
117
|
const log = getLogger("conversation-routes");
|
|
119
118
|
|
|
@@ -121,6 +120,15 @@ const log = getLogger("conversation-routes");
|
|
|
121
120
|
const NO_RESPONSE_INLINE_RE = /<no_response\s*\/?>/g;
|
|
122
121
|
|
|
123
122
|
const SUGGESTION_CACHE_MAX = 100;
|
|
123
|
+
const VALID_RISK_THRESHOLDS = ["none", "low", "medium", "high"] as const;
|
|
124
|
+
type RiskThreshold = (typeof VALID_RISK_THRESHOLDS)[number];
|
|
125
|
+
|
|
126
|
+
function isValidRiskThreshold(value: unknown): value is RiskThreshold {
|
|
127
|
+
return (
|
|
128
|
+
typeof value === "string" &&
|
|
129
|
+
VALID_RISK_THRESHOLDS.includes(value as RiskThreshold)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
124
132
|
|
|
125
133
|
function collectCanonicalGuardianRequestHintIds(
|
|
126
134
|
conversationId: string,
|
|
@@ -333,18 +341,6 @@ async function tryConsumeCanonicalGuardianReply(params: {
|
|
|
333
341
|
return { consumed: true, messageId };
|
|
334
342
|
}
|
|
335
343
|
|
|
336
|
-
function resolveCanonicalRequestSourceType(
|
|
337
|
-
sourceChannel: string | undefined,
|
|
338
|
-
): "desktop" | "channel" | "voice" {
|
|
339
|
-
if (sourceChannel === "phone") {
|
|
340
|
-
return "voice";
|
|
341
|
-
}
|
|
342
|
-
if (sourceChannel === "vellum") {
|
|
343
|
-
return "desktop";
|
|
344
|
-
}
|
|
345
|
-
return "channel";
|
|
346
|
-
}
|
|
347
|
-
|
|
348
344
|
function getInterfaceFilesWithMtimes(
|
|
349
345
|
interfacesDir: string | null,
|
|
350
346
|
): Array<{ path: string; mtimeMs: number }> {
|
|
@@ -368,11 +364,11 @@ function getInterfaceFilesWithMtimes(
|
|
|
368
364
|
}
|
|
369
365
|
|
|
370
366
|
export function handleListMessages(
|
|
371
|
-
|
|
367
|
+
{ queryParams }: RouteHandlerArgs,
|
|
372
368
|
interfacesDir: string | null,
|
|
373
|
-
):
|
|
374
|
-
const conversationId =
|
|
375
|
-
const conversationKey =
|
|
369
|
+
): Record<string, unknown> {
|
|
370
|
+
const conversationId = queryParams?.conversationId;
|
|
371
|
+
const conversationKey = queryParams?.conversationKey;
|
|
376
372
|
|
|
377
373
|
let resolvedConversationId: string | undefined;
|
|
378
374
|
if (conversationId) {
|
|
@@ -381,30 +377,40 @@ export function handleListMessages(
|
|
|
381
377
|
const mapping = getConversationByKey(conversationKey);
|
|
382
378
|
resolvedConversationId = mapping?.conversationId;
|
|
383
379
|
} else {
|
|
384
|
-
|
|
385
|
-
"BAD_REQUEST",
|
|
380
|
+
throw new BadRequestError(
|
|
386
381
|
"conversationKey or conversationId query parameter is required",
|
|
387
|
-
400,
|
|
388
382
|
);
|
|
389
383
|
}
|
|
390
384
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const beforeTimestampRaw = url.searchParams.get("beforeTimestamp");
|
|
396
|
-
const limitRaw = url.searchParams.get("limit");
|
|
385
|
+
const beforeTimestampRaw = queryParams?.beforeTimestamp;
|
|
386
|
+
const limitRaw = queryParams?.limit;
|
|
387
|
+
const pageRaw = queryParams?.page;
|
|
397
388
|
|
|
398
389
|
// Validate: reject NaN values with 400
|
|
399
|
-
if (beforeTimestampRaw
|
|
400
|
-
|
|
401
|
-
"BAD_REQUEST",
|
|
402
|
-
"beforeTimestamp must be a valid number",
|
|
403
|
-
400,
|
|
404
|
-
);
|
|
390
|
+
if (beforeTimestampRaw != null && isNaN(Number(beforeTimestampRaw))) {
|
|
391
|
+
throw new BadRequestError("beforeTimestamp must be a valid number");
|
|
405
392
|
}
|
|
406
|
-
if (limitRaw
|
|
407
|
-
|
|
393
|
+
if (limitRaw != null && isNaN(Number(limitRaw))) {
|
|
394
|
+
throw new BadRequestError("limit must be a valid number");
|
|
395
|
+
}
|
|
396
|
+
if (pageRaw != null && pageRaw !== "latest") {
|
|
397
|
+
throw new BadRequestError("page must be 'latest' when provided");
|
|
398
|
+
}
|
|
399
|
+
const isLatestPage = pageRaw === "latest";
|
|
400
|
+
|
|
401
|
+
if (!resolvedConversationId) {
|
|
402
|
+
// Unresolved conversation keys still need to advertise the stable
|
|
403
|
+
// `page=latest` contract so the web client can rely on metadata fields
|
|
404
|
+
// being present even before any message is persisted.
|
|
405
|
+
if (isLatestPage && beforeTimestampRaw == null) {
|
|
406
|
+
return {
|
|
407
|
+
messages: [],
|
|
408
|
+
hasMore: false,
|
|
409
|
+
oldestTimestamp: null,
|
|
410
|
+
oldestMessageId: null,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
return { messages: [] };
|
|
408
414
|
}
|
|
409
415
|
|
|
410
416
|
const beforeTimestamp = beforeTimestampRaw
|
|
@@ -415,10 +421,12 @@ export function handleListMessages(
|
|
|
415
421
|
? Math.min(Math.max(Math.floor(Number(limitRaw)), 1), 500)
|
|
416
422
|
: undefined;
|
|
417
423
|
|
|
418
|
-
//
|
|
419
|
-
//
|
|
420
|
-
//
|
|
421
|
-
|
|
424
|
+
// Paginate when either `beforeTimestamp` (older-page request) or
|
|
425
|
+
// `page=latest` (initial newest-N request) is set. When both are sent,
|
|
426
|
+
// `beforeTimestamp` wins because the caller is explicitly asking for an
|
|
427
|
+
// older page; `getMessagesPaginated` ignores `beforeTimestamp === undefined`
|
|
428
|
+
// and returns the newest `limit` messages in chronological order.
|
|
429
|
+
const isPaginated = beforeTimestamp != null || isLatestPage;
|
|
422
430
|
|
|
423
431
|
let rawMessages: MessageRow[];
|
|
424
432
|
let hasMore = false;
|
|
@@ -583,12 +591,12 @@ export function handleListMessages(
|
|
|
583
591
|
// aren't lost before DB compaction relinks them.
|
|
584
592
|
const idsToQuery = [m.id, ...(mergedIdMap.get(m.id) ?? [])];
|
|
585
593
|
const linked = idsToQuery.flatMap((id) =>
|
|
586
|
-
|
|
594
|
+
getAttachmentMetadataForMessage(id),
|
|
587
595
|
);
|
|
588
596
|
if (linked.length > 0) {
|
|
589
597
|
msgAttachments = linked.map((a) => {
|
|
590
598
|
if (a.mimeType.startsWith("image/")) {
|
|
591
|
-
const full =
|
|
599
|
+
const full = getAttachmentById(a.id, {
|
|
592
600
|
hydrateFileData: true,
|
|
593
601
|
});
|
|
594
602
|
return {
|
|
@@ -664,15 +672,28 @@ export function handleListMessages(
|
|
|
664
672
|
rawMessages.length > 0 ? rawMessages[0].createdAt : undefined;
|
|
665
673
|
const oldestMessageId =
|
|
666
674
|
rawMessages.length > 0 ? rawMessages[0].id : undefined;
|
|
667
|
-
|
|
675
|
+
// `page=latest` always emits both metadata fields so the web client has
|
|
676
|
+
// a stable contract; emit `null` when the conversation is empty.
|
|
677
|
+
// The existing `beforeTimestamp` branch keeps its conditional shape to
|
|
678
|
+
// avoid disturbing current callers.
|
|
679
|
+
if (isLatestPage && beforeTimestamp == null) {
|
|
680
|
+
return {
|
|
681
|
+
messages,
|
|
682
|
+
hasMore,
|
|
683
|
+
oldestTimestamp: oldestTimestamp ?? null,
|
|
684
|
+
oldestMessageId: oldestMessageId ?? null,
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return {
|
|
668
689
|
messages,
|
|
669
690
|
hasMore,
|
|
670
691
|
...(oldestTimestamp != null ? { oldestTimestamp } : {}),
|
|
671
692
|
...(oldestMessageId != null ? { oldestMessageId } : {}),
|
|
672
|
-
}
|
|
693
|
+
};
|
|
673
694
|
}
|
|
674
695
|
|
|
675
|
-
return
|
|
696
|
+
return { messages };
|
|
676
697
|
}
|
|
677
698
|
|
|
678
699
|
// ── Tool-result merging ─────────────────────────────────────────────
|
|
@@ -973,337 +994,6 @@ function mergeConsecutiveAssistantMessages(messages: MessageRow[]): {
|
|
|
973
994
|
return { messages: result, mergedIdMap };
|
|
974
995
|
}
|
|
975
996
|
|
|
976
|
-
/**
|
|
977
|
-
* Build an `onEvent` callback that publishes every outbound event to the
|
|
978
|
-
* assistant event hub, maintaining ordered delivery through a serial chain.
|
|
979
|
-
*
|
|
980
|
-
* Also registers pending interactions when confirmation_request,
|
|
981
|
-
* secret_request, host_bash_request, host_browser_request, host_file_request,
|
|
982
|
-
* or host_cu_request events flow through, so standalone approval/result
|
|
983
|
-
* endpoints can look up the conversation by requestId.
|
|
984
|
-
*/
|
|
985
|
-
function makeHubPublisher(
|
|
986
|
-
deps: SendMessageDeps,
|
|
987
|
-
conversationId: string,
|
|
988
|
-
conversation: Conversation,
|
|
989
|
-
): (msg: ServerMessage) => void {
|
|
990
|
-
let hubChain: Promise<void> = Promise.resolve();
|
|
991
|
-
return (msg: ServerMessage) => {
|
|
992
|
-
// Register pending interactions for approval events
|
|
993
|
-
if (msg.type === "confirmation_request") {
|
|
994
|
-
pendingInteractions.register(msg.requestId, {
|
|
995
|
-
conversation,
|
|
996
|
-
conversationId,
|
|
997
|
-
kind: "confirmation",
|
|
998
|
-
confirmationDetails: {
|
|
999
|
-
toolName: msg.toolName,
|
|
1000
|
-
input: msg.input,
|
|
1001
|
-
riskLevel: msg.riskLevel,
|
|
1002
|
-
executionTarget: msg.executionTarget,
|
|
1003
|
-
allowlistOptions: msg.allowlistOptions,
|
|
1004
|
-
scopeOptions: msg.scopeOptions,
|
|
1005
|
-
persistentDecisionsAllowed: msg.persistentDecisionsAllowed,
|
|
1006
|
-
temporaryOptionsAvailable: msg.temporaryOptionsAvailable,
|
|
1007
|
-
},
|
|
1008
|
-
});
|
|
1009
|
-
|
|
1010
|
-
const inputRecord = msg.input as Record<string, unknown>;
|
|
1011
|
-
const commandPreview =
|
|
1012
|
-
redactSecrets(summarizeToolInput(msg.toolName, inputRecord)) ||
|
|
1013
|
-
undefined;
|
|
1014
|
-
const technicalTitle = commandPreview
|
|
1015
|
-
? `Requesting permission: ${commandPreview}`
|
|
1016
|
-
: `Requesting approval to use ${msg.toolName}.`;
|
|
1017
|
-
const dedupKey = `tool-approval:${msg.requestId}`;
|
|
1018
|
-
|
|
1019
|
-
// Emit immediately with the technical preview.
|
|
1020
|
-
void emitFeedEvent({
|
|
1021
|
-
source: "assistant",
|
|
1022
|
-
title: technicalTitle,
|
|
1023
|
-
summary: technicalTitle,
|
|
1024
|
-
dedupKey,
|
|
1025
|
-
urgency: msg.riskLevel === "high" ? "high" : "medium",
|
|
1026
|
-
conversationId,
|
|
1027
|
-
}).catch((err) => {
|
|
1028
|
-
log.warn(
|
|
1029
|
-
{ err, requestId: msg.requestId },
|
|
1030
|
-
"Failed to emit tool approval request feed event",
|
|
1031
|
-
);
|
|
1032
|
-
});
|
|
1033
|
-
|
|
1034
|
-
// Background: rewrite into prose and update the feed item.
|
|
1035
|
-
if (commandPreview) {
|
|
1036
|
-
void rewriteCommandPreview(msg.toolName, commandPreview)
|
|
1037
|
-
.then((prose) => {
|
|
1038
|
-
if (prose) {
|
|
1039
|
-
const proseTitle = `Requesting permission: ${prose}`;
|
|
1040
|
-
return emitFeedEvent({
|
|
1041
|
-
source: "assistant",
|
|
1042
|
-
title: proseTitle,
|
|
1043
|
-
summary: proseTitle,
|
|
1044
|
-
dedupKey,
|
|
1045
|
-
urgency: msg.riskLevel === "high" ? "high" : "medium",
|
|
1046
|
-
conversationId,
|
|
1047
|
-
});
|
|
1048
|
-
}
|
|
1049
|
-
})
|
|
1050
|
-
.catch((err) => {
|
|
1051
|
-
log.warn(
|
|
1052
|
-
{ err, requestId: msg.requestId },
|
|
1053
|
-
"Failed to update feed event with prose rewrite",
|
|
1054
|
-
);
|
|
1055
|
-
});
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
// Create a canonical guardian request so HTTP handlers can find it
|
|
1059
|
-
// via applyCanonicalGuardianDecision.
|
|
1060
|
-
try {
|
|
1061
|
-
const trustContext = conversation.trustContext;
|
|
1062
|
-
const sourceChannel = trustContext?.sourceChannel ?? "vellum";
|
|
1063
|
-
const inputRecord = msg.input as Record<string, unknown>;
|
|
1064
|
-
const activityRaw =
|
|
1065
|
-
(typeof inputRecord.activity === "string"
|
|
1066
|
-
? inputRecord.activity
|
|
1067
|
-
: undefined) ??
|
|
1068
|
-
(typeof inputRecord.reason === "string"
|
|
1069
|
-
? inputRecord.reason
|
|
1070
|
-
: undefined);
|
|
1071
|
-
const canonicalRequest = createCanonicalGuardianRequest({
|
|
1072
|
-
id: msg.requestId,
|
|
1073
|
-
kind: "tool_approval",
|
|
1074
|
-
sourceType: resolveCanonicalRequestSourceType(sourceChannel),
|
|
1075
|
-
sourceChannel,
|
|
1076
|
-
conversationId,
|
|
1077
|
-
requesterExternalUserId: trustContext?.requesterExternalUserId,
|
|
1078
|
-
requesterChatId: trustContext?.requesterChatId,
|
|
1079
|
-
guardianExternalUserId: trustContext?.guardianExternalUserId,
|
|
1080
|
-
guardianPrincipalId: trustContext?.guardianPrincipalId ?? undefined,
|
|
1081
|
-
toolName: msg.toolName,
|
|
1082
|
-
commandPreview:
|
|
1083
|
-
redactSecrets(summarizeToolInput(msg.toolName, inputRecord)) ||
|
|
1084
|
-
undefined,
|
|
1085
|
-
riskLevel: msg.riskLevel,
|
|
1086
|
-
activityText: activityRaw ? redactSecrets(activityRaw) : undefined,
|
|
1087
|
-
executionTarget: msg.executionTarget,
|
|
1088
|
-
status: "pending",
|
|
1089
|
-
requestCode: generateCanonicalRequestCode(),
|
|
1090
|
-
expiresAt: Date.now() + 5 * 60 * 1000,
|
|
1091
|
-
});
|
|
1092
|
-
|
|
1093
|
-
// For trusted-contact conversations, bridge to guardian.question so the
|
|
1094
|
-
// guardian gets notified and can approve via callback/request-code.
|
|
1095
|
-
if (trustContext) {
|
|
1096
|
-
bridgeConfirmationRequestToGuardian({
|
|
1097
|
-
canonicalRequest,
|
|
1098
|
-
trustContext,
|
|
1099
|
-
conversationId,
|
|
1100
|
-
toolName: msg.toolName,
|
|
1101
|
-
assistantId:
|
|
1102
|
-
conversation.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID,
|
|
1103
|
-
});
|
|
1104
|
-
}
|
|
1105
|
-
} catch (err) {
|
|
1106
|
-
log.debug(
|
|
1107
|
-
{ err, requestId: msg.requestId, conversationId },
|
|
1108
|
-
"Failed to create canonical request from hub publisher",
|
|
1109
|
-
);
|
|
1110
|
-
}
|
|
1111
|
-
} else if (msg.type === "secret_request") {
|
|
1112
|
-
pendingInteractions.register(msg.requestId, {
|
|
1113
|
-
conversation,
|
|
1114
|
-
conversationId,
|
|
1115
|
-
kind: "secret",
|
|
1116
|
-
});
|
|
1117
|
-
} else {
|
|
1118
|
-
registerHostProxyPendingInteraction(msg, conversation, conversationId);
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
// ServerMessage is a large union; conversationId exists on most but not all variants.
|
|
1122
|
-
const msgConversationId =
|
|
1123
|
-
"conversationId" in msg &&
|
|
1124
|
-
typeof (msg as { conversationId?: unknown }).conversationId === "string"
|
|
1125
|
-
? (msg as { conversationId: string }).conversationId
|
|
1126
|
-
: undefined;
|
|
1127
|
-
// `conversation_list_invalidated` is a list-level system event: it
|
|
1128
|
-
// describes no particular conversation and every connected client
|
|
1129
|
-
// should refresh its sidebar. Publish it unscoped so the SSE hub does
|
|
1130
|
-
// not filter it out by the subscriber's `filter.conversationId`.
|
|
1131
|
-
// Other events (including `conversation_title_updated`) stay scoped to
|
|
1132
|
-
// their conversation — unscoped scoped-events would leak foreign
|
|
1133
|
-
// `conversationId` values to native clients' speculative ID-resolution
|
|
1134
|
-
// path. For `conversation_title_updated` we instead enqueue a matching
|
|
1135
|
-
// unscoped `conversation_list_invalidated` below so other clients'
|
|
1136
|
-
// sidebars can refresh and pick up the new title.
|
|
1137
|
-
const resolvedConversationId =
|
|
1138
|
-
msg.type === "conversation_list_invalidated"
|
|
1139
|
-
? undefined
|
|
1140
|
-
: (msgConversationId ?? conversationId);
|
|
1141
|
-
const event = buildAssistantEvent(
|
|
1142
|
-
DAEMON_INTERNAL_ASSISTANT_ID,
|
|
1143
|
-
msg,
|
|
1144
|
-
resolvedConversationId,
|
|
1145
|
-
);
|
|
1146
|
-
hubChain = (async () => {
|
|
1147
|
-
await hubChain;
|
|
1148
|
-
try {
|
|
1149
|
-
await deps.assistantEventHub.publish(event);
|
|
1150
|
-
} catch (err) {
|
|
1151
|
-
log.warn(
|
|
1152
|
-
{ err },
|
|
1153
|
-
"assistant-events hub subscriber threw during POST /messages",
|
|
1154
|
-
);
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
// When the agent loop auto-generates a conversation title, also
|
|
1158
|
-
// broadcast an unscoped `conversation_list_invalidated` so every
|
|
1159
|
-
// connected client's sidebar can refresh and pick up the new title.
|
|
1160
|
-
// Without this, clients viewing other conversations (or a draft)
|
|
1161
|
-
// would never learn that the title for this conversation changed.
|
|
1162
|
-
// The scoped `conversation_title_updated` above still handles the
|
|
1163
|
-
// in-place update for the client currently viewing this conversation.
|
|
1164
|
-
if (msg.type === "conversation_title_updated") {
|
|
1165
|
-
try {
|
|
1166
|
-
await deps.assistantEventHub.publish(
|
|
1167
|
-
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
1168
|
-
type: "conversation_list_invalidated",
|
|
1169
|
-
reason: "renamed",
|
|
1170
|
-
}),
|
|
1171
|
-
);
|
|
1172
|
-
} catch (err) {
|
|
1173
|
-
log.warn(
|
|
1174
|
-
{ err },
|
|
1175
|
-
"Failed to publish conversation_list_invalidated after title update",
|
|
1176
|
-
);
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
})();
|
|
1180
|
-
};
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
/**
|
|
1184
|
-
* Register pending interactions for host proxy request envelopes so
|
|
1185
|
-
* standalone result endpoints can resolve by requestId.
|
|
1186
|
-
*
|
|
1187
|
-
* Returns the registered requestId when a host proxy request was registered.
|
|
1188
|
-
* Callers that route through non-hub transports (e.g. registry-routed
|
|
1189
|
-
* host_browser sends) can use this to clean up the registration if send fails.
|
|
1190
|
-
*/
|
|
1191
|
-
function registerHostProxyPendingInteraction(
|
|
1192
|
-
msg: ServerMessage,
|
|
1193
|
-
conversation: Conversation,
|
|
1194
|
-
conversationId: string,
|
|
1195
|
-
): string | undefined {
|
|
1196
|
-
if (msg.type === "host_bash_request") {
|
|
1197
|
-
pendingInteractions.register(msg.requestId, {
|
|
1198
|
-
conversation,
|
|
1199
|
-
conversationId,
|
|
1200
|
-
kind: "host_bash",
|
|
1201
|
-
});
|
|
1202
|
-
return msg.requestId;
|
|
1203
|
-
}
|
|
1204
|
-
if (msg.type === "host_browser_request") {
|
|
1205
|
-
pendingInteractions.register(msg.requestId, {
|
|
1206
|
-
conversation,
|
|
1207
|
-
conversationId,
|
|
1208
|
-
kind: "host_browser",
|
|
1209
|
-
});
|
|
1210
|
-
return msg.requestId;
|
|
1211
|
-
}
|
|
1212
|
-
if (msg.type === "host_file_request") {
|
|
1213
|
-
pendingInteractions.register(msg.requestId, {
|
|
1214
|
-
conversation,
|
|
1215
|
-
conversationId,
|
|
1216
|
-
kind: "host_file",
|
|
1217
|
-
});
|
|
1218
|
-
return msg.requestId;
|
|
1219
|
-
}
|
|
1220
|
-
if (msg.type === "host_cu_request") {
|
|
1221
|
-
pendingInteractions.register(msg.requestId, {
|
|
1222
|
-
conversation,
|
|
1223
|
-
conversationId,
|
|
1224
|
-
kind: "host_cu",
|
|
1225
|
-
});
|
|
1226
|
-
return msg.requestId;
|
|
1227
|
-
}
|
|
1228
|
-
return undefined;
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
/**
|
|
1232
|
-
* Resolve the host_browser sender function for a conversation turn.
|
|
1233
|
-
*
|
|
1234
|
-
* When the guardian has an active extension connection in the
|
|
1235
|
-
* ChromeExtensionRegistry, returns a registry-routed sender that forwards
|
|
1236
|
-
* `host_browser_request` / `host_browser_cancel` frames through the
|
|
1237
|
-
* WebSocket to the connected extension. Otherwise returns the SSE hub
|
|
1238
|
-
* emitter (`onEvent`).
|
|
1239
|
-
*
|
|
1240
|
-
* For `chrome-extension` turns the registry sender is **always** returned
|
|
1241
|
-
* regardless of the POST-time connection check. The chrome-extension
|
|
1242
|
-
* interface has no SSE consumer for `host_browser_request` frames, so
|
|
1243
|
-
* falling back to `onEvent` would cause CDP calls to stall until the proxy
|
|
1244
|
-
* timeout (30 s) instead of failing immediately at send time when the
|
|
1245
|
-
* registry throws on a missing connection.
|
|
1246
|
-
*
|
|
1247
|
-
* This helper is interface-agnostic: both chrome-extension and macOS turns
|
|
1248
|
-
* can obtain a registry-routed sender when extension connectivity exists.
|
|
1249
|
-
* The `isRegistryRouted` flag lets the caller decide whether to set
|
|
1250
|
-
* `hostBrowserSenderOverride` and whether to provision a `HostBrowserProxy`
|
|
1251
|
-
* for interfaces that don't statically support host_browser (e.g. macOS).
|
|
1252
|
-
*/
|
|
1253
|
-
function resolveHostBrowserSender(
|
|
1254
|
-
conversation: Conversation,
|
|
1255
|
-
conversationId: string,
|
|
1256
|
-
authContext: AuthContext,
|
|
1257
|
-
onEvent: (msg: ServerMessage) => void,
|
|
1258
|
-
sourceInterface: InterfaceId,
|
|
1259
|
-
): { sender: (msg: ServerMessage) => void; isRegistryRouted: boolean } {
|
|
1260
|
-
// Check whether the guardian has any active extension connection.
|
|
1261
|
-
const guardianId =
|
|
1262
|
-
conversation.trustContext?.guardianPrincipalId ??
|
|
1263
|
-
authContext.actorPrincipalId;
|
|
1264
|
-
const hasExtensionConnection =
|
|
1265
|
-
!!guardianId && !!getChromeExtensionRegistry().get(guardianId);
|
|
1266
|
-
|
|
1267
|
-
// For chrome-extension, always use the registry sender so that send-time
|
|
1268
|
-
// failures produce immediate errors rather than 30-second proxy timeouts.
|
|
1269
|
-
// The SSE hub has no extension consumer, so falling back to onEvent is
|
|
1270
|
-
// never correct for this interface.
|
|
1271
|
-
if (!hasExtensionConnection && sourceInterface !== "chrome-extension") {
|
|
1272
|
-
return { sender: onEvent, isRegistryRouted: false };
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
// Build a registry-routed sender. The guardian principal ID is resolved
|
|
1276
|
-
// at send time rather than captured here so that queue-drain restores
|
|
1277
|
-
// (which re-fire this closure outside the original POST context) follow
|
|
1278
|
-
// the conversation's bound guardian identity rather than a stale
|
|
1279
|
-
// authContext.actorPrincipalId.
|
|
1280
|
-
const registrySender = (msg: ServerMessage): void => {
|
|
1281
|
-
const requestId = registerHostProxyPendingInteraction(
|
|
1282
|
-
msg,
|
|
1283
|
-
conversation,
|
|
1284
|
-
conversationId,
|
|
1285
|
-
);
|
|
1286
|
-
const gid =
|
|
1287
|
-
conversation.trustContext?.guardianPrincipalId ??
|
|
1288
|
-
authContext.actorPrincipalId;
|
|
1289
|
-
if (!gid) {
|
|
1290
|
-
if (requestId) pendingInteractions.resolve(requestId);
|
|
1291
|
-
throw new Error(
|
|
1292
|
-
"host_browser send skipped: no guardianId on AuthContext",
|
|
1293
|
-
);
|
|
1294
|
-
}
|
|
1295
|
-
const ok = getChromeExtensionRegistry().send(gid, msg);
|
|
1296
|
-
if (!ok) {
|
|
1297
|
-
if (requestId) pendingInteractions.resolve(requestId);
|
|
1298
|
-
throw new Error(
|
|
1299
|
-
`host_browser send failed: no active connection for guardian ${gid}`,
|
|
1300
|
-
);
|
|
1301
|
-
}
|
|
1302
|
-
};
|
|
1303
|
-
|
|
1304
|
-
return { sender: registrySender, isRegistryRouted: true };
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
997
|
/**
|
|
1308
998
|
* Persist the pre-chat onboarding payload to disk.
|
|
1309
999
|
*
|
|
@@ -1395,15 +1085,13 @@ export function persistOnboardingArtifacts(onboarding: {
|
|
|
1395
1085
|
}
|
|
1396
1086
|
|
|
1397
1087
|
export async function handleSendMessage(
|
|
1398
|
-
|
|
1088
|
+
{ body: rawBody, headers }: RouteHandlerArgs,
|
|
1399
1089
|
deps: {
|
|
1400
1090
|
sendMessageDeps?: SendMessageDeps;
|
|
1401
1091
|
approvalConversationGenerator?: ApprovalConversationGenerator;
|
|
1402
|
-
heartbeatService?: HeartbeatService;
|
|
1403
1092
|
},
|
|
1404
|
-
|
|
1405
|
-
)
|
|
1406
|
-
const body = (await req.json()) as {
|
|
1093
|
+
): Promise<unknown> {
|
|
1094
|
+
const body = (rawBody ?? {}) as {
|
|
1407
1095
|
conversationKey?: string;
|
|
1408
1096
|
content?: string;
|
|
1409
1097
|
attachmentIds?: string[];
|
|
@@ -1416,6 +1104,8 @@ export async function handleSendMessage(
|
|
|
1416
1104
|
hostUsername?: string;
|
|
1417
1105
|
clientId?: string;
|
|
1418
1106
|
clientMessageId?: string;
|
|
1107
|
+
inferenceProfile?: string | null;
|
|
1108
|
+
riskThreshold?: string;
|
|
1419
1109
|
onboarding?: {
|
|
1420
1110
|
tools: string[];
|
|
1421
1111
|
tasks: string[];
|
|
@@ -1425,35 +1115,70 @@ export async function handleSendMessage(
|
|
|
1425
1115
|
};
|
|
1426
1116
|
};
|
|
1427
1117
|
|
|
1118
|
+
const actorPrincipalId = headers?.["x-vellum-actor-principal-id"];
|
|
1119
|
+
const principalType = headers?.["x-vellum-principal-type"];
|
|
1120
|
+
|
|
1428
1121
|
const { conversationKey, content, attachmentIds } = body;
|
|
1429
1122
|
const clientMessageId =
|
|
1430
1123
|
typeof body.clientMessageId === "string" ? body.clientMessageId : undefined;
|
|
1124
|
+
const requestedInferenceProfile =
|
|
1125
|
+
typeof body.inferenceProfile === "string"
|
|
1126
|
+
? body.inferenceProfile
|
|
1127
|
+
: undefined;
|
|
1128
|
+
const requestedRiskThreshold = body.riskThreshold;
|
|
1129
|
+
if (
|
|
1130
|
+
body.inferenceProfile != null &&
|
|
1131
|
+
typeof body.inferenceProfile !== "string"
|
|
1132
|
+
) {
|
|
1133
|
+
throw new BadRequestError(
|
|
1134
|
+
"inferenceProfile must be a non-empty string or null",
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
if (requestedInferenceProfile === "") {
|
|
1138
|
+
throw new BadRequestError(
|
|
1139
|
+
"inferenceProfile must be a non-empty string or null",
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
if (requestedInferenceProfile !== undefined) {
|
|
1143
|
+
const profiles = getConfig().llm.profiles ?? {};
|
|
1144
|
+
if (
|
|
1145
|
+
!Object.prototype.hasOwnProperty.call(profiles, requestedInferenceProfile)
|
|
1146
|
+
) {
|
|
1147
|
+
throw new BadRequestError(
|
|
1148
|
+
`Profile "${requestedInferenceProfile}" is not defined in llm.profiles`,
|
|
1149
|
+
);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
if (
|
|
1153
|
+
requestedRiskThreshold !== undefined &&
|
|
1154
|
+
!isValidRiskThreshold(requestedRiskThreshold)
|
|
1155
|
+
) {
|
|
1156
|
+
throw new BadRequestError(
|
|
1157
|
+
`riskThreshold must be one of: ${VALID_RISK_THRESHOLDS.join(", ")}`,
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1431
1160
|
if (!body.sourceChannel || typeof body.sourceChannel !== "string") {
|
|
1432
|
-
|
|
1161
|
+
throw new BadRequestError("sourceChannel is required");
|
|
1433
1162
|
}
|
|
1434
1163
|
const sourceChannel = parseChannelId(body.sourceChannel);
|
|
1435
1164
|
|
|
1436
1165
|
if (!sourceChannel) {
|
|
1437
|
-
|
|
1438
|
-
"BAD_REQUEST",
|
|
1166
|
+
throw new BadRequestError(
|
|
1439
1167
|
`Invalid sourceChannel: ${
|
|
1440
1168
|
body.sourceChannel
|
|
1441
1169
|
}. Valid values: ${CHANNEL_IDS.join(", ")}`,
|
|
1442
|
-
400,
|
|
1443
1170
|
);
|
|
1444
1171
|
}
|
|
1445
1172
|
|
|
1446
1173
|
if (!body.interface || typeof body.interface !== "string") {
|
|
1447
|
-
|
|
1174
|
+
throw new BadRequestError("interface is required");
|
|
1448
1175
|
}
|
|
1449
1176
|
const sourceInterface = parseInterfaceId(body.interface);
|
|
1450
1177
|
if (!sourceInterface) {
|
|
1451
|
-
|
|
1452
|
-
"BAD_REQUEST",
|
|
1178
|
+
throw new BadRequestError(
|
|
1453
1179
|
`Invalid interface: ${body.interface}. Valid values: ${INTERFACE_IDS.join(
|
|
1454
1180
|
", ",
|
|
1455
1181
|
)}`,
|
|
1456
|
-
400,
|
|
1457
1182
|
);
|
|
1458
1183
|
}
|
|
1459
1184
|
|
|
@@ -1465,7 +1190,7 @@ export async function handleSendMessage(
|
|
|
1465
1190
|
|
|
1466
1191
|
// Reject non-string content values (numbers, objects, etc.)
|
|
1467
1192
|
if (content != null && typeof content !== "string") {
|
|
1468
|
-
|
|
1193
|
+
throw new BadRequestError("content must be a string");
|
|
1469
1194
|
}
|
|
1470
1195
|
|
|
1471
1196
|
const trimmedContent = typeof content === "string" ? content.trim() : "";
|
|
@@ -1473,23 +1198,17 @@ export async function handleSendMessage(
|
|
|
1473
1198
|
Array.isArray(attachmentIds) && attachmentIds.length > 0;
|
|
1474
1199
|
|
|
1475
1200
|
if (trimmedContent.length === 0 && !hasAttachments) {
|
|
1476
|
-
|
|
1477
|
-
"BAD_REQUEST",
|
|
1478
|
-
"content or attachmentIds is required",
|
|
1479
|
-
400,
|
|
1480
|
-
);
|
|
1201
|
+
throw new BadRequestError("content or attachmentIds is required");
|
|
1481
1202
|
}
|
|
1482
1203
|
|
|
1483
1204
|
// Validate that all attachment IDs resolve
|
|
1484
1205
|
if (hasAttachments) {
|
|
1485
|
-
const resolved =
|
|
1206
|
+
const resolved = getAttachmentsByIds(attachmentIds);
|
|
1486
1207
|
if (resolved.length !== attachmentIds.length) {
|
|
1487
1208
|
const resolvedIds = new Set(resolved.map((a) => a.id));
|
|
1488
1209
|
const missing = attachmentIds.filter((id) => !resolvedIds.has(id));
|
|
1489
|
-
|
|
1490
|
-
"BAD_REQUEST",
|
|
1210
|
+
throw new BadRequestError(
|
|
1491
1211
|
`Attachment IDs not found: ${missing.join(", ")}`,
|
|
1492
|
-
400,
|
|
1493
1212
|
);
|
|
1494
1213
|
}
|
|
1495
1214
|
}
|
|
@@ -1498,36 +1217,52 @@ export async function handleSendMessage(
|
|
|
1498
1217
|
if (trimmedContent.length > 0 && !body.bypassSecretCheck) {
|
|
1499
1218
|
const ingressResult = checkIngressForSecrets(trimmedContent);
|
|
1500
1219
|
if (ingressResult.blocked) {
|
|
1501
|
-
return
|
|
1502
|
-
{
|
|
1220
|
+
return new RouteResponse(
|
|
1221
|
+
JSON.stringify({
|
|
1503
1222
|
accepted: false,
|
|
1504
1223
|
error: "secret_blocked",
|
|
1505
1224
|
message: ingressResult.userNotice,
|
|
1506
1225
|
detectedTypes: ingressResult.detectedTypes,
|
|
1507
|
-
},
|
|
1508
|
-
{
|
|
1226
|
+
}),
|
|
1227
|
+
{ "content-type": "application/json" },
|
|
1228
|
+
422,
|
|
1509
1229
|
);
|
|
1510
1230
|
}
|
|
1511
1231
|
}
|
|
1512
1232
|
|
|
1513
1233
|
if (!deps.sendMessageDeps) {
|
|
1514
|
-
|
|
1515
|
-
"SERVICE_UNAVAILABLE",
|
|
1234
|
+
throw new RouteError(
|
|
1516
1235
|
"Message processing is not available",
|
|
1236
|
+
"SERVICE_UNAVAILABLE",
|
|
1517
1237
|
503,
|
|
1518
1238
|
);
|
|
1519
1239
|
}
|
|
1520
1240
|
|
|
1521
1241
|
// Desktop messages are always from the guardian — reset the heartbeat
|
|
1522
1242
|
// timer so the next heartbeat is a full interval after this interaction.
|
|
1523
|
-
|
|
1243
|
+
HeartbeatService.getInstance()?.resetTimer();
|
|
1524
1244
|
|
|
1525
|
-
const conversationType =
|
|
1526
|
-
body.conversationType === "private" ? ("private" as const) : undefined;
|
|
1527
1245
|
const mapping = getOrCreateConversation(resolvedConversationKey, {
|
|
1528
|
-
conversationType,
|
|
1246
|
+
conversationType: "standard",
|
|
1529
1247
|
});
|
|
1530
1248
|
|
|
1249
|
+
if (requestedRiskThreshold !== undefined) {
|
|
1250
|
+
const result = await ipcCall("set_conversation_threshold", {
|
|
1251
|
+
conversationId: mapping.conversationId,
|
|
1252
|
+
threshold: requestedRiskThreshold,
|
|
1253
|
+
});
|
|
1254
|
+
if (result === undefined) {
|
|
1255
|
+
log.error(
|
|
1256
|
+
{
|
|
1257
|
+
conversationId: mapping.conversationId,
|
|
1258
|
+
threshold: requestedRiskThreshold,
|
|
1259
|
+
},
|
|
1260
|
+
"Failed to set conversation risk threshold override via gateway IPC",
|
|
1261
|
+
);
|
|
1262
|
+
throw new InternalError("Failed to persist risk threshold override");
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1531
1266
|
const smDeps = deps.sendMessageDeps;
|
|
1532
1267
|
|
|
1533
1268
|
// Notify all connected clients that the conversation list changed when
|
|
@@ -1542,7 +1277,7 @@ export async function handleSendMessage(
|
|
|
1542
1277
|
if (!hasMessages(mapping.conversationId)) {
|
|
1543
1278
|
smDeps.assistantEventHub
|
|
1544
1279
|
.publish(
|
|
1545
|
-
buildAssistantEvent(
|
|
1280
|
+
buildAssistantEvent({
|
|
1546
1281
|
type: "conversation_list_invalidated",
|
|
1547
1282
|
reason: "created",
|
|
1548
1283
|
}),
|
|
@@ -1571,27 +1306,18 @@ export async function handleSendMessage(
|
|
|
1571
1306
|
interfaceId: sourceInterface,
|
|
1572
1307
|
} satisfies NonHostProxyTransportMetadata);
|
|
1573
1308
|
|
|
1574
|
-
// Register/refresh the client in the unified client registry so
|
|
1575
|
-
// `assistant clients list` can discover all connected interfaces.
|
|
1576
|
-
// Uses the client-supplied clientId when available (stable per-install
|
|
1577
|
-
// UUID), falling back to a synthetic key derived from interfaceId so
|
|
1578
|
-
// older clients that don't send clientId still appear in the registry.
|
|
1579
|
-
const effectiveClientId =
|
|
1580
|
-
typeof body.clientId === "string" && body.clientId.length > 0
|
|
1581
|
-
? body.clientId
|
|
1582
|
-
: `synthetic:${sourceInterface}`;
|
|
1583
|
-
getClientRegistry().register({
|
|
1584
|
-
clientId: effectiveClientId,
|
|
1585
|
-
interfaceId: sourceInterface,
|
|
1586
|
-
hostHomeDir: body.hostHomeDir,
|
|
1587
|
-
hostUsername: body.hostUsername,
|
|
1588
|
-
});
|
|
1589
|
-
|
|
1590
1309
|
const conversation = await smDeps.getOrCreateConversation(
|
|
1591
1310
|
mapping.conversationId,
|
|
1592
1311
|
{ transport },
|
|
1593
1312
|
);
|
|
1594
1313
|
|
|
1314
|
+
if (requestedInferenceProfile !== undefined) {
|
|
1315
|
+
setConversationInferenceProfile(
|
|
1316
|
+
mapping.conversationId,
|
|
1317
|
+
requestedInferenceProfile,
|
|
1318
|
+
);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1595
1321
|
// Store pre-chat onboarding context on the conversation when this is the
|
|
1596
1322
|
// very first message (no prior messages loaded). Artifact persistence
|
|
1597
1323
|
// (IDENTITY.md, USER.md, sidecar) is deferred: on the canned greeting
|
|
@@ -1607,11 +1333,11 @@ export async function handleSendMessage(
|
|
|
1607
1333
|
// Resolve guardian context from the AuthContext's actorPrincipalId.
|
|
1608
1334
|
// The JWT-verified principal is used as the sender identity through
|
|
1609
1335
|
// the same trust resolution pipeline that channel ingress uses.
|
|
1610
|
-
if (
|
|
1336
|
+
if (actorPrincipalId) {
|
|
1611
1337
|
// Dev bypass (HTTP auth disabled): the synthetic "dev-bypass" principal
|
|
1612
1338
|
// won't match any guardian binding. Resolve from the local guardian
|
|
1613
1339
|
// binding instead, which produces the correct guardian trust context.
|
|
1614
|
-
if (isHttpAuthDisabled() &&
|
|
1340
|
+
if (isHttpAuthDisabled() && actorPrincipalId === "dev-bypass") {
|
|
1615
1341
|
conversation.setTrustContext(resolveLocalTrustContext(sourceChannel));
|
|
1616
1342
|
} else {
|
|
1617
1343
|
const assistantId = DAEMON_INTERNAL_ASSISTANT_ID;
|
|
@@ -1619,24 +1345,24 @@ export async function handleSendMessage(
|
|
|
1619
1345
|
assistantId,
|
|
1620
1346
|
sourceChannel: "vellum",
|
|
1621
1347
|
conversationExternalId: "local",
|
|
1622
|
-
actorExternalId:
|
|
1348
|
+
actorExternalId: actorPrincipalId,
|
|
1623
1349
|
});
|
|
1624
1350
|
if (trustCtx.trustClass === "unknown") {
|
|
1625
1351
|
// Attempt to heal guardian binding drift: after a DB reset the
|
|
1626
1352
|
// guardian binding gets a new vellum-principal-* UUID while the
|
|
1627
1353
|
// client still holds a valid JWT with the old one. The signing
|
|
1628
1354
|
// key survives the reset, so the JWT is authentic — just stale.
|
|
1629
|
-
const healed = healGuardianBindingDrift(
|
|
1355
|
+
const healed = healGuardianBindingDrift(actorPrincipalId);
|
|
1630
1356
|
if (healed) {
|
|
1631
1357
|
trustCtx = resolveTrustContext({
|
|
1632
1358
|
assistantId,
|
|
1633
1359
|
sourceChannel: "vellum",
|
|
1634
1360
|
conversationExternalId: "local",
|
|
1635
|
-
actorExternalId:
|
|
1361
|
+
actorExternalId: actorPrincipalId,
|
|
1636
1362
|
});
|
|
1637
1363
|
log.info(
|
|
1638
1364
|
{
|
|
1639
|
-
actorPrincipalId:
|
|
1365
|
+
actorPrincipalId: actorPrincipalId,
|
|
1640
1366
|
trustClass: trustCtx.trustClass,
|
|
1641
1367
|
},
|
|
1642
1368
|
"Trust re-resolved after guardian binding drift heal",
|
|
@@ -1644,10 +1370,10 @@ export async function handleSendMessage(
|
|
|
1644
1370
|
} else {
|
|
1645
1371
|
log.warn(
|
|
1646
1372
|
{
|
|
1647
|
-
actorPrincipalId:
|
|
1373
|
+
actorPrincipalId: actorPrincipalId,
|
|
1648
1374
|
sourceChannel,
|
|
1649
1375
|
trustClass: trustCtx.trustClass,
|
|
1650
|
-
principalType:
|
|
1376
|
+
principalType: principalType,
|
|
1651
1377
|
},
|
|
1652
1378
|
"JWT-verified actor resolved to unknown trust class — possible guardian binding drift (e.g. DB reset without re-bootstrap)",
|
|
1653
1379
|
);
|
|
@@ -1661,95 +1387,13 @@ export async function handleSendMessage(
|
|
|
1661
1387
|
conversation.setTrustContext({ trustClass: "guardian", sourceChannel });
|
|
1662
1388
|
}
|
|
1663
1389
|
|
|
1664
|
-
const onEvent = makeHubPublisher(
|
|
1665
|
-
smDeps,
|
|
1666
|
-
mapping.conversationId,
|
|
1667
|
-
conversation,
|
|
1668
|
-
);
|
|
1669
1390
|
const isInteractive = isInteractiveInterface(sourceInterface);
|
|
1670
|
-
//
|
|
1671
|
-
//
|
|
1672
|
-
//
|
|
1673
|
-
// fall back to local execution.
|
|
1674
|
-
// Set the proxy BEFORE updateClient so updateClient's call to
|
|
1675
|
-
// hostBashProxy.updateSender targets the correct (new) proxy.
|
|
1676
|
-
if (supportsHostProxy(sourceInterface, "host_bash")) {
|
|
1677
|
-
// Reuse the existing proxy if the conversation is actively processing a
|
|
1678
|
-
// host bash request to avoid orphaning in-flight requests.
|
|
1679
|
-
if (!conversation.isProcessing() || !conversation.hostBashProxy) {
|
|
1680
|
-
const proxy = new HostBashProxy(onEvent, (requestId) => {
|
|
1681
|
-
pendingInteractions.resolve(requestId);
|
|
1682
|
-
});
|
|
1683
|
-
conversation.setHostBashProxy(proxy);
|
|
1684
|
-
}
|
|
1685
|
-
} else if (!conversation.isProcessing()) {
|
|
1686
|
-
conversation.setHostBashProxy(undefined);
|
|
1687
|
-
}
|
|
1688
|
-
// Resolve the host_browser sender — registry-routed when the guardian has
|
|
1689
|
-
// an active extension connection, SSE hub otherwise. This applies to both
|
|
1690
|
-
// chrome-extension and macOS interfaces so that macOS turns can route
|
|
1691
|
-
// browser automation through the user's real Chrome session when available.
|
|
1692
|
-
const { sender: browserProxySendToClient, isRegistryRouted } =
|
|
1693
|
-
resolveHostBrowserSender(
|
|
1694
|
-
conversation,
|
|
1695
|
-
mapping.conversationId,
|
|
1696
|
-
authContext,
|
|
1697
|
-
onEvent,
|
|
1698
|
-
sourceInterface,
|
|
1699
|
-
);
|
|
1700
|
-
|
|
1701
|
-
// Stash the registry-routed sender on the conversation so queue-drain
|
|
1702
|
-
// restores (which run outside of conversation-routes.ts and only have
|
|
1703
|
-
// access to `sendToClient`) can preserve it when calling
|
|
1704
|
-
// `restoreBrowserProxyAvailability()`. The override is set when the
|
|
1705
|
-
// sender is registry-routed (regardless of interface) and cleared when
|
|
1706
|
-
// the SSE hub sender is used, so the drain path always restores the
|
|
1707
|
-
// correct transport.
|
|
1708
|
-
if (isRegistryRouted) {
|
|
1709
|
-
conversation.hostBrowserSenderOverride = browserProxySendToClient;
|
|
1710
|
-
} else {
|
|
1711
|
-
conversation.hostBrowserSenderOverride = undefined;
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
// Provision the host browser proxy. Both macOS and chrome-extension
|
|
1715
|
-
// natively support host_browser. For macOS, the proxy is wired to the
|
|
1716
|
-
// SSE sender by default so `host_browser_request` frames reach the
|
|
1717
|
-
// desktop client directly. When the guardian also has an active extension
|
|
1718
|
-
// connection (isRegistryRouted), the registry-routed sender is used
|
|
1719
|
-
// instead so browser tools route through the user's real Chrome session.
|
|
1720
|
-
// For chrome-extension, the registry sender is always used.
|
|
1721
|
-
const shouldProvisionBrowserProxy =
|
|
1722
|
-
supportsHostProxy(sourceInterface, "host_browser") ||
|
|
1723
|
-
(canServiceRegistryBrowser(sourceInterface) && isRegistryRouted);
|
|
1724
|
-
if (shouldProvisionBrowserProxy) {
|
|
1725
|
-
if (!conversation.isProcessing() || !conversation.hostBrowserProxy) {
|
|
1726
|
-
const browserProxy = new HostBrowserProxy(
|
|
1727
|
-
browserProxySendToClient,
|
|
1728
|
-
(requestId) => {
|
|
1729
|
-
pendingInteractions.resolve(requestId);
|
|
1730
|
-
},
|
|
1731
|
-
);
|
|
1732
|
-
conversation.setHostBrowserProxy(browserProxy);
|
|
1733
|
-
}
|
|
1734
|
-
} else if (!conversation.isProcessing()) {
|
|
1735
|
-
conversation.setHostBrowserProxy(undefined);
|
|
1736
|
-
}
|
|
1737
|
-
if (supportsHostProxy(sourceInterface, "host_file")) {
|
|
1738
|
-
if (!conversation.isProcessing() || !conversation.hostFileProxy) {
|
|
1739
|
-
const fileProxy = new HostFileProxy(onEvent, (requestId) => {
|
|
1740
|
-
pendingInteractions.resolve(requestId);
|
|
1741
|
-
});
|
|
1742
|
-
conversation.setHostFileProxy(fileProxy);
|
|
1743
|
-
}
|
|
1744
|
-
} else if (!conversation.isProcessing()) {
|
|
1745
|
-
conversation.setHostFileProxy(undefined);
|
|
1746
|
-
}
|
|
1391
|
+
// Bash/File/Transfer singletons are globally available via isAvailable() —
|
|
1392
|
+
// no per-conversation gating needed. CU is per-conversation (owns step
|
|
1393
|
+
// count, AX tree history, loop detection).
|
|
1747
1394
|
if (supportsHostProxy(sourceInterface, "host_cu")) {
|
|
1748
1395
|
if (!conversation.isProcessing() || !conversation.hostCuProxy) {
|
|
1749
|
-
|
|
1750
|
-
pendingInteractions.resolve(requestId);
|
|
1751
|
-
});
|
|
1752
|
-
conversation.setHostCuProxy(cuProxy);
|
|
1396
|
+
conversation.setHostCuProxy(new HostCuProxy());
|
|
1753
1397
|
}
|
|
1754
1398
|
// Only preactivate CU when the conversation is idle — if the conversation is
|
|
1755
1399
|
// processing, this message will be queued and preactivation is deferred
|
|
@@ -1761,14 +1405,6 @@ export async function handleSendMessage(
|
|
|
1761
1405
|
conversation.setHostCuProxy(undefined);
|
|
1762
1406
|
}
|
|
1763
1407
|
// Wire sendToClient to the SSE hub so all subsystems can reach the HTTP client.
|
|
1764
|
-
// Called after setHostBashProxy so updateSender targets the current proxy.
|
|
1765
|
-
// When proxies are preserved during an active turn (non-desktop request while
|
|
1766
|
-
// processing), skip updating proxy senders to avoid degrading them. The gate
|
|
1767
|
-
// matches the host_bash capability because the legacy "reject send during
|
|
1768
|
-
// host bash" flow is what this is really protecting.
|
|
1769
|
-
const preservingProxies =
|
|
1770
|
-
conversation.isProcessing() &&
|
|
1771
|
-
!supportsHostProxy(sourceInterface, "host_bash");
|
|
1772
1408
|
// hasNoClient must remain `!isInteractive` so downstream tool gating
|
|
1773
1409
|
// (`isToolActiveForContext` for HOST_TOOL_NAMES, `createToolExecutor`'s
|
|
1774
1410
|
// `isInteractive: !ctx.hasNoClient`) keeps host_bash/host_file/host_cu
|
|
@@ -1776,23 +1412,7 @@ export async function handleSendMessage(
|
|
|
1776
1412
|
// is non-interactive (no SSE prompter UI) but still has a connected client
|
|
1777
1413
|
// that can service host_browser_request events; we restore that single
|
|
1778
1414
|
// proxy explicitly below without relaxing `hasNoClient`.
|
|
1779
|
-
conversation.updateClient(
|
|
1780
|
-
skipProxySenderUpdate: preservingProxies,
|
|
1781
|
-
});
|
|
1782
|
-
// Re-enable the browser proxy for turns that provisioned one. This covers:
|
|
1783
|
-
// - macOS: always provisioned (SSE sender or registry-routed when extension
|
|
1784
|
-
// is connected)
|
|
1785
|
-
// - chrome-extension: natively supports host_browser (non-interactive but
|
|
1786
|
-
// has a connected client for host_browser_request events)
|
|
1787
|
-
//
|
|
1788
|
-
// The helper bypasses the `hasNoClient` gate so chrome-extension turns can
|
|
1789
|
-
// drive the browser via CDP without leaking host_bash/host_file tool
|
|
1790
|
-
// availability. It reads `hostBrowserSenderOverride` (set above when
|
|
1791
|
-
// registry-routed) and applies the correct sender — including after
|
|
1792
|
-
// queue-drain restores run from conversation-process.ts.
|
|
1793
|
-
if (shouldProvisionBrowserProxy) {
|
|
1794
|
-
conversation.restoreBrowserProxyAvailability?.();
|
|
1795
|
-
}
|
|
1415
|
+
conversation.updateClient(broadcastMessage, !isInteractive);
|
|
1796
1416
|
|
|
1797
1417
|
// ── Canned first-greeting fast path ──
|
|
1798
1418
|
// On a completely fresh workspace, skip LLM inference for the macOS
|
|
@@ -1847,21 +1467,26 @@ export async function handleSendMessage(
|
|
|
1847
1467
|
);
|
|
1848
1468
|
conversation.getMessages().push(assistantMsg);
|
|
1849
1469
|
|
|
1850
|
-
const response =
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1470
|
+
const response = {
|
|
1471
|
+
accepted: true,
|
|
1472
|
+
messageId: persisted.id,
|
|
1473
|
+
conversationId,
|
|
1474
|
+
};
|
|
1854
1475
|
|
|
1855
1476
|
setTimeout(() => {
|
|
1856
|
-
|
|
1477
|
+
broadcastMessage({
|
|
1857
1478
|
type: "user_message_echo",
|
|
1858
1479
|
text: rawContent,
|
|
1859
1480
|
conversationId,
|
|
1860
1481
|
messageId: persisted.id,
|
|
1861
1482
|
clientMessageId,
|
|
1862
1483
|
});
|
|
1863
|
-
|
|
1864
|
-
|
|
1484
|
+
broadcastMessage({
|
|
1485
|
+
type: "assistant_text_delta",
|
|
1486
|
+
text: cannedGreeting,
|
|
1487
|
+
conversationId,
|
|
1488
|
+
});
|
|
1489
|
+
broadcastMessage({ type: "message_complete", conversationId });
|
|
1865
1490
|
conversation.processing = false;
|
|
1866
1491
|
silentlyWithLog(
|
|
1867
1492
|
conversation.drainQueue(),
|
|
@@ -1914,7 +1539,7 @@ export async function handleSendMessage(
|
|
|
1914
1539
|
content: content ?? "",
|
|
1915
1540
|
attachments,
|
|
1916
1541
|
conversation,
|
|
1917
|
-
onEvent,
|
|
1542
|
+
onEvent: broadcastMessage,
|
|
1918
1543
|
// Desktop path: disable NL classification to avoid consuming non-decision
|
|
1919
1544
|
// messages while a tool confirmation is pending. Deterministic code-prefix
|
|
1920
1545
|
// and callback parsing remain active. Mirrors conversation-process.ts behavior.
|
|
@@ -1926,16 +1551,13 @@ export async function handleSendMessage(
|
|
|
1926
1551
|
verifiedActorPrincipalId,
|
|
1927
1552
|
});
|
|
1928
1553
|
if (inlineReplyResult.consumed) {
|
|
1929
|
-
return
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
},
|
|
1937
|
-
{ status: 202 },
|
|
1938
|
-
);
|
|
1554
|
+
return {
|
|
1555
|
+
accepted: true,
|
|
1556
|
+
conversationId: mapping.conversationId,
|
|
1557
|
+
...(inlineReplyResult.messageId
|
|
1558
|
+
? { messageId: inlineReplyResult.messageId }
|
|
1559
|
+
: {}),
|
|
1560
|
+
};
|
|
1939
1561
|
}
|
|
1940
1562
|
} catch (err) {
|
|
1941
1563
|
log.warn(
|
|
@@ -1950,7 +1572,7 @@ export async function handleSendMessage(
|
|
|
1950
1572
|
const enqueueResult = conversation.enqueueMessage(
|
|
1951
1573
|
content ?? "",
|
|
1952
1574
|
attachments,
|
|
1953
|
-
|
|
1575
|
+
broadcastMessage,
|
|
1954
1576
|
requestId,
|
|
1955
1577
|
undefined, // activeSurfaceId
|
|
1956
1578
|
undefined, // currentPage
|
|
@@ -1967,9 +1589,10 @@ export async function handleSendMessage(
|
|
|
1967
1589
|
clientMessageId,
|
|
1968
1590
|
);
|
|
1969
1591
|
if (enqueueResult.rejected) {
|
|
1970
|
-
return
|
|
1971
|
-
{ accepted: false, error: "queue_full" },
|
|
1972
|
-
{
|
|
1592
|
+
return new RouteResponse(
|
|
1593
|
+
JSON.stringify({ accepted: false, error: "queue_full" }),
|
|
1594
|
+
{ "content-type": "application/json" },
|
|
1595
|
+
429,
|
|
1973
1596
|
);
|
|
1974
1597
|
}
|
|
1975
1598
|
|
|
@@ -1987,10 +1610,7 @@ export async function handleSendMessage(
|
|
|
1987
1610
|
for (const interaction of pendingInteractions.getByConversation(
|
|
1988
1611
|
mapping.conversationId,
|
|
1989
1612
|
)) {
|
|
1990
|
-
if (
|
|
1991
|
-
interaction.conversation === conversation &&
|
|
1992
|
-
interaction.kind === "confirmation"
|
|
1993
|
-
) {
|
|
1613
|
+
if (interaction.kind === "confirmation") {
|
|
1994
1614
|
conversation.emitConfirmationStateChanged({
|
|
1995
1615
|
conversationId: mapping.conversationId,
|
|
1996
1616
|
requestId: interaction.requestId,
|
|
@@ -2005,7 +1625,7 @@ export async function handleSendMessage(
|
|
|
2005
1625
|
}
|
|
2006
1626
|
}
|
|
2007
1627
|
conversation.denyAllPendingConfirmations();
|
|
2008
|
-
pendingInteractions.removeByConversation(
|
|
1628
|
+
pendingInteractions.removeByConversation(mapping.conversationId);
|
|
2009
1629
|
}
|
|
2010
1630
|
|
|
2011
1631
|
// Expire any orphaned canonical requests that survived without a
|
|
@@ -2018,10 +1638,11 @@ export async function handleSendMessage(
|
|
|
2018
1638
|
);
|
|
2019
1639
|
}
|
|
2020
1640
|
|
|
2021
|
-
return
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
1641
|
+
return {
|
|
1642
|
+
accepted: true,
|
|
1643
|
+
queued: true,
|
|
1644
|
+
conversationId: mapping.conversationId,
|
|
1645
|
+
};
|
|
2025
1646
|
}
|
|
2026
1647
|
|
|
2027
1648
|
// Auto-deny pending confirmations for idle conversations. The legacy
|
|
@@ -2033,10 +1654,7 @@ export async function handleSendMessage(
|
|
|
2033
1654
|
for (const interaction of pendingInteractions.getByConversation(
|
|
2034
1655
|
mapping.conversationId,
|
|
2035
1656
|
)) {
|
|
2036
|
-
if (
|
|
2037
|
-
interaction.conversation === conversation &&
|
|
2038
|
-
interaction.kind === "confirmation"
|
|
2039
|
-
) {
|
|
1657
|
+
if (interaction.kind === "confirmation") {
|
|
2040
1658
|
conversation.emitConfirmationStateChanged({
|
|
2041
1659
|
conversationId: mapping.conversationId,
|
|
2042
1660
|
requestId: interaction.requestId,
|
|
@@ -2051,7 +1669,7 @@ export async function handleSendMessage(
|
|
|
2051
1669
|
}
|
|
2052
1670
|
}
|
|
2053
1671
|
conversation.denyAllPendingConfirmations();
|
|
2054
|
-
pendingInteractions.removeByConversation(
|
|
1672
|
+
pendingInteractions.removeByConversation(mapping.conversationId);
|
|
2055
1673
|
}
|
|
2056
1674
|
|
|
2057
1675
|
// Expire any orphaned canonical requests that survived without a
|
|
@@ -2072,17 +1690,14 @@ export async function handleSendMessage(
|
|
|
2072
1690
|
|
|
2073
1691
|
// Resolve slash commands before persisting or running the agent loop.
|
|
2074
1692
|
const rawContent = content ?? "";
|
|
2075
|
-
const
|
|
2076
|
-
|
|
1693
|
+
const slashContext = buildSlashContextForContent(rawContent, {
|
|
1694
|
+
conversationId: mapping.conversationId,
|
|
2077
1695
|
messageCount: conversation.getMessages().length,
|
|
2078
1696
|
inputTokens: conversation.usageStats.inputTokens,
|
|
2079
1697
|
outputTokens: conversation.usageStats.outputTokens,
|
|
2080
|
-
maxInputTokens: config.llm.default.contextWindow.maxInputTokens,
|
|
2081
|
-
model: config.llm.default.model,
|
|
2082
|
-
provider: config.llm.default.provider,
|
|
2083
1698
|
estimatedCost: conversation.usageStats.estimatedCost,
|
|
2084
1699
|
userMessageInterface: sourceInterface,
|
|
2085
|
-
};
|
|
1700
|
+
});
|
|
2086
1701
|
const slashResult = await resolveSlash(rawContent, slashContext);
|
|
2087
1702
|
|
|
2088
1703
|
if (slashResult.kind === "unknown") {
|
|
@@ -2139,17 +1754,14 @@ export async function handleSendMessage(
|
|
|
2139
1754
|
// Snapshot model info now so the deferred callback cannot observe
|
|
2140
1755
|
// a config change from a concurrent request.
|
|
2141
1756
|
const modelInfoEvent = isModelSlashCommand(rawContent)
|
|
2142
|
-
? await buildModelInfoEvent()
|
|
1757
|
+
? await buildModelInfoEvent(mapping.conversationId)
|
|
2143
1758
|
: null;
|
|
2144
1759
|
|
|
2145
|
-
const response =
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
},
|
|
2151
|
-
{ status: 202 },
|
|
2152
|
-
);
|
|
1760
|
+
const response = {
|
|
1761
|
+
accepted: true,
|
|
1762
|
+
messageId: persisted.id,
|
|
1763
|
+
conversationId: mapping.conversationId,
|
|
1764
|
+
};
|
|
2153
1765
|
|
|
2154
1766
|
// Defer event publishing to next tick so the HTTP response reaches the
|
|
2155
1767
|
// client first. This ensures the client's serverToLocalConversationMap is
|
|
@@ -2162,7 +1774,7 @@ export async function handleSendMessage(
|
|
|
2162
1774
|
const conversationId = mapping.conversationId;
|
|
2163
1775
|
const message = slashResult.message;
|
|
2164
1776
|
setTimeout(() => {
|
|
2165
|
-
|
|
1777
|
+
broadcastMessage({
|
|
2166
1778
|
type: "user_message_echo",
|
|
2167
1779
|
text: rawContent,
|
|
2168
1780
|
conversationId,
|
|
@@ -2170,10 +1782,14 @@ export async function handleSendMessage(
|
|
|
2170
1782
|
clientMessageId,
|
|
2171
1783
|
});
|
|
2172
1784
|
if (modelInfoEvent) {
|
|
2173
|
-
|
|
1785
|
+
broadcastMessage(modelInfoEvent);
|
|
2174
1786
|
}
|
|
2175
|
-
|
|
2176
|
-
|
|
1787
|
+
broadcastMessage({
|
|
1788
|
+
type: "assistant_text_delta",
|
|
1789
|
+
text: message,
|
|
1790
|
+
conversationId,
|
|
1791
|
+
});
|
|
1792
|
+
broadcastMessage({
|
|
2177
1793
|
type: "message_complete",
|
|
2178
1794
|
conversationId: conversationId,
|
|
2179
1795
|
});
|
|
@@ -2219,7 +1835,7 @@ export async function handleSendMessage(
|
|
|
2219
1835
|
// HTTP timeout on large contexts, causing a false "Failed to send".
|
|
2220
1836
|
(async () => {
|
|
2221
1837
|
try {
|
|
2222
|
-
|
|
1838
|
+
broadcastMessage({
|
|
2223
1839
|
type: "user_message_echo",
|
|
2224
1840
|
text: rawContent,
|
|
2225
1841
|
conversationId,
|
|
@@ -2243,11 +1859,15 @@ export async function handleSendMessage(
|
|
|
2243
1859
|
);
|
|
2244
1860
|
conversation.getMessages().push(assistantMsg);
|
|
2245
1861
|
|
|
2246
|
-
|
|
2247
|
-
|
|
1862
|
+
broadcastMessage({
|
|
1863
|
+
type: "assistant_text_delta",
|
|
1864
|
+
text: responseText,
|
|
1865
|
+
conversationId,
|
|
1866
|
+
});
|
|
1867
|
+
broadcastMessage({ type: "message_complete", conversationId });
|
|
2248
1868
|
} catch (err) {
|
|
2249
1869
|
log.error({ err, conversationId }, "Compact command failed");
|
|
2250
|
-
|
|
1870
|
+
broadcastMessage({
|
|
2251
1871
|
type: "conversation_error",
|
|
2252
1872
|
conversationId,
|
|
2253
1873
|
code: "UNKNOWN",
|
|
@@ -2263,14 +1883,11 @@ export async function handleSendMessage(
|
|
|
2263
1883
|
}
|
|
2264
1884
|
})();
|
|
2265
1885
|
|
|
2266
|
-
return
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
},
|
|
2272
|
-
{ status: 202 },
|
|
2273
|
-
);
|
|
1886
|
+
return {
|
|
1887
|
+
accepted: true,
|
|
1888
|
+
messageId: persisted.id,
|
|
1889
|
+
conversationId,
|
|
1890
|
+
};
|
|
2274
1891
|
}
|
|
2275
1892
|
|
|
2276
1893
|
const resolvedContent = slashResult.content;
|
|
@@ -2288,7 +1905,7 @@ export async function handleSendMessage(
|
|
|
2288
1905
|
throw err;
|
|
2289
1906
|
}
|
|
2290
1907
|
|
|
2291
|
-
|
|
1908
|
+
broadcastMessage({
|
|
2292
1909
|
type: "user_message_echo",
|
|
2293
1910
|
text: resolvedContent,
|
|
2294
1911
|
conversationId: mapping.conversationId,
|
|
@@ -2297,9 +1914,9 @@ export async function handleSendMessage(
|
|
|
2297
1914
|
clientMessageId,
|
|
2298
1915
|
});
|
|
2299
1916
|
|
|
2300
|
-
// Fire-and-forget the agent loop; events flow to the hub via
|
|
1917
|
+
// Fire-and-forget the agent loop; events flow to the hub via broadcastMessage.
|
|
2301
1918
|
conversation
|
|
2302
|
-
.runAgentLoop(resolvedContent, messageId,
|
|
1919
|
+
.runAgentLoop(resolvedContent, messageId, broadcastMessage, {
|
|
2303
1920
|
isInteractive,
|
|
2304
1921
|
isUserMessage: true,
|
|
2305
1922
|
})
|
|
@@ -2310,10 +1927,11 @@ export async function handleSendMessage(
|
|
|
2310
1927
|
);
|
|
2311
1928
|
});
|
|
2312
1929
|
|
|
2313
|
-
return
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
1930
|
+
return {
|
|
1931
|
+
accepted: true,
|
|
1932
|
+
messageId,
|
|
1933
|
+
conversationId: mapping.conversationId,
|
|
1934
|
+
};
|
|
2317
1935
|
}
|
|
2318
1936
|
|
|
2319
1937
|
function escapeXmlContent(text: string): string {
|
|
@@ -2400,54 +2018,39 @@ async function generateLlmSuggestion(
|
|
|
2400
2018
|
}
|
|
2401
2019
|
|
|
2402
2020
|
export async function handleGetSuggestion(
|
|
2403
|
-
|
|
2021
|
+
{ queryParams }: RouteHandlerArgs,
|
|
2404
2022
|
deps: {
|
|
2405
2023
|
suggestionCache: Map<string, string>;
|
|
2406
2024
|
suggestionInFlight: Map<string, Promise<string | null>>;
|
|
2407
2025
|
},
|
|
2408
|
-
): Promise<
|
|
2409
|
-
const
|
|
2026
|
+
): Promise<Record<string, unknown>> {
|
|
2027
|
+
const noSuggestion = {
|
|
2028
|
+
suggestion: null,
|
|
2029
|
+
messageId: null,
|
|
2030
|
+
source: "none" as const,
|
|
2031
|
+
};
|
|
2032
|
+
|
|
2033
|
+
const conversationKey = queryParams?.conversationKey;
|
|
2410
2034
|
if (!conversationKey) {
|
|
2411
|
-
|
|
2412
|
-
"BAD_REQUEST",
|
|
2413
|
-
"conversationKey query parameter is required",
|
|
2414
|
-
400,
|
|
2415
|
-
);
|
|
2035
|
+
throw new BadRequestError("conversationKey query parameter is required");
|
|
2416
2036
|
}
|
|
2417
2037
|
|
|
2418
2038
|
const mapping = getConversationByKey(conversationKey);
|
|
2419
|
-
if (!mapping)
|
|
2420
|
-
return Response.json({
|
|
2421
|
-
suggestion: null,
|
|
2422
|
-
messageId: null,
|
|
2423
|
-
source: "none" as const,
|
|
2424
|
-
});
|
|
2425
|
-
}
|
|
2039
|
+
if (!mapping) return noSuggestion;
|
|
2426
2040
|
|
|
2427
2041
|
const rawMessages = getMessages(mapping.conversationId);
|
|
2428
|
-
if (rawMessages.length === 0)
|
|
2429
|
-
return Response.json({
|
|
2430
|
-
suggestion: null,
|
|
2431
|
-
messageId: null,
|
|
2432
|
-
source: "none" as const,
|
|
2433
|
-
});
|
|
2434
|
-
}
|
|
2042
|
+
if (rawMessages.length === 0) return noSuggestion;
|
|
2435
2043
|
|
|
2436
2044
|
// Staleness check: compare requested messageId against the latest
|
|
2437
2045
|
// assistant message BEFORE filtering by text content. This ensures
|
|
2438
2046
|
// that a newer tool-only assistant turn (empty text) still causes
|
|
2439
2047
|
// older messageId requests to be correctly marked as stale.
|
|
2440
|
-
const requestedMessageId =
|
|
2048
|
+
const requestedMessageId = queryParams?.messageId;
|
|
2441
2049
|
if (requestedMessageId) {
|
|
2442
2050
|
for (let i = rawMessages.length - 1; i >= 0; i--) {
|
|
2443
2051
|
if (rawMessages[i].role === "assistant") {
|
|
2444
2052
|
if (rawMessages[i].id !== requestedMessageId) {
|
|
2445
|
-
return
|
|
2446
|
-
suggestion: null,
|
|
2447
|
-
messageId: null,
|
|
2448
|
-
source: "none" as const,
|
|
2449
|
-
stale: true,
|
|
2450
|
-
});
|
|
2053
|
+
return { ...noSuggestion, stale: true };
|
|
2451
2054
|
}
|
|
2452
2055
|
break;
|
|
2453
2056
|
}
|
|
@@ -2475,22 +2078,13 @@ export async function handleGetSuggestion(
|
|
|
2475
2078
|
// If a messageId was requested and the first text-bearing assistant
|
|
2476
2079
|
// message is a *different* message, the request is stale.
|
|
2477
2080
|
if (requestedMessageId && msg.id !== requestedMessageId) {
|
|
2478
|
-
return
|
|
2479
|
-
suggestion: null,
|
|
2480
|
-
messageId: null,
|
|
2481
|
-
source: "none" as const,
|
|
2482
|
-
stale: true,
|
|
2483
|
-
});
|
|
2081
|
+
return { ...noSuggestion, stale: true };
|
|
2484
2082
|
}
|
|
2485
2083
|
|
|
2486
2084
|
// Return cached suggestion if we already generated one for this message
|
|
2487
2085
|
const cached = suggestionCache.get(msg.id);
|
|
2488
2086
|
if (cached !== undefined) {
|
|
2489
|
-
return
|
|
2490
|
-
suggestion: cached,
|
|
2491
|
-
messageId: msg.id,
|
|
2492
|
-
source: "llm" as const,
|
|
2493
|
-
});
|
|
2087
|
+
return { suggestion: cached, messageId: msg.id, source: "llm" as const };
|
|
2494
2088
|
}
|
|
2495
2089
|
|
|
2496
2090
|
// Find the most recent user message preceding this assistant turn so the
|
|
@@ -2534,11 +2128,11 @@ export async function handleGetSuggestion(
|
|
|
2534
2128
|
}
|
|
2535
2129
|
suggestionCache.set(msg.id, llmSuggestion);
|
|
2536
2130
|
|
|
2537
|
-
return
|
|
2131
|
+
return {
|
|
2538
2132
|
suggestion: llmSuggestion,
|
|
2539
2133
|
messageId: msg.id,
|
|
2540
2134
|
source: "llm" as const,
|
|
2541
|
-
}
|
|
2135
|
+
};
|
|
2542
2136
|
}
|
|
2543
2137
|
} catch (err) {
|
|
2544
2138
|
suggestionInFlight.delete(msg.id);
|
|
@@ -2554,18 +2148,10 @@ export async function handleGetSuggestion(
|
|
|
2554
2148
|
);
|
|
2555
2149
|
}
|
|
2556
2150
|
|
|
2557
|
-
return
|
|
2558
|
-
suggestion: null,
|
|
2559
|
-
messageId: null,
|
|
2560
|
-
source: "none" as const,
|
|
2561
|
-
});
|
|
2151
|
+
return noSuggestion;
|
|
2562
2152
|
}
|
|
2563
2153
|
|
|
2564
|
-
return
|
|
2565
|
-
suggestion: null,
|
|
2566
|
-
messageId: null,
|
|
2567
|
-
source: "none" as const,
|
|
2568
|
-
});
|
|
2154
|
+
return noSuggestion;
|
|
2569
2155
|
}
|
|
2570
2156
|
|
|
2571
2157
|
/**
|
|
@@ -2574,19 +2160,17 @@ export async function handleGetSuggestion(
|
|
|
2574
2160
|
* Full-text search across all conversations (message content + titles).
|
|
2575
2161
|
* Returns ranked results grouped by conversation, each with matching message excerpts.
|
|
2576
2162
|
*/
|
|
2577
|
-
function handleSearchConversations(
|
|
2578
|
-
|
|
2163
|
+
function handleSearchConversations({
|
|
2164
|
+
queryParams,
|
|
2165
|
+
}: RouteHandlerArgs): Record<string, unknown> {
|
|
2166
|
+
const query = queryParams?.q ?? "";
|
|
2579
2167
|
if (!query.trim()) {
|
|
2580
|
-
|
|
2168
|
+
throw new BadRequestError("q query parameter is required");
|
|
2581
2169
|
}
|
|
2582
2170
|
|
|
2583
|
-
const limit =
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
const maxMessagesPerConversation = url.searchParams.has(
|
|
2587
|
-
"maxMessagesPerConversation",
|
|
2588
|
-
)
|
|
2589
|
-
? Number(url.searchParams.get("maxMessagesPerConversation"))
|
|
2171
|
+
const limit = queryParams?.limit ? Number(queryParams.limit) : undefined;
|
|
2172
|
+
const maxMessagesPerConversation = queryParams?.maxMessagesPerConversation
|
|
2173
|
+
? Number(queryParams.maxMessagesPerConversation)
|
|
2590
2174
|
: undefined;
|
|
2591
2175
|
|
|
2592
2176
|
const results = searchConversations(query, {
|
|
@@ -2597,105 +2181,125 @@ function handleSearchConversations(url: URL): Response {
|
|
|
2597
2181
|
: {}),
|
|
2598
2182
|
});
|
|
2599
2183
|
|
|
2600
|
-
return
|
|
2184
|
+
return { query, results };
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
// ---------------------------------------------------------------------------
|
|
2188
|
+
// Module-level state
|
|
2189
|
+
// ---------------------------------------------------------------------------
|
|
2190
|
+
|
|
2191
|
+
const suggestionCache = new Map<string, string>();
|
|
2192
|
+
const suggestionInFlight = new Map<string, Promise<string | null>>();
|
|
2193
|
+
|
|
2194
|
+
function resolveAttachments(attachmentIds: string[]) {
|
|
2195
|
+
const resolved = getAttachmentsByIds(attachmentIds, {
|
|
2196
|
+
hydrateFileData: true,
|
|
2197
|
+
});
|
|
2198
|
+
const sourcePaths = getSourcePathsForAttachments(attachmentIds);
|
|
2199
|
+
return resolved.map((a) => ({
|
|
2200
|
+
id: a.id,
|
|
2201
|
+
filename: a.originalFilename,
|
|
2202
|
+
mimeType: a.mimeType,
|
|
2203
|
+
data: a.dataBase64,
|
|
2204
|
+
...(sourcePaths.has(a.id) ? { filePath: sourcePaths.get(a.id) } : {}),
|
|
2205
|
+
}));
|
|
2601
2206
|
}
|
|
2602
2207
|
|
|
2603
2208
|
// ---------------------------------------------------------------------------
|
|
2604
2209
|
// Route definitions
|
|
2605
2210
|
// ---------------------------------------------------------------------------
|
|
2606
2211
|
|
|
2607
|
-
export
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
{
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
"
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
.describe("Whether older messages exist beyond this page"),
|
|
2629
|
-
oldestTimestamp: z
|
|
2630
|
-
.number()
|
|
2631
|
-
.optional()
|
|
2632
|
-
.describe(
|
|
2633
|
-
"Timestamp of the oldest message in this page (ms since epoch)",
|
|
2634
|
-
),
|
|
2635
|
-
oldestMessageId: z
|
|
2636
|
-
.string()
|
|
2637
|
-
.optional()
|
|
2638
|
-
.describe("ID of the oldest message in this page"),
|
|
2639
|
-
}),
|
|
2640
|
-
handler: ({ url }) => handleListMessages(url, deps.interfacesDir),
|
|
2641
|
-
},
|
|
2642
|
-
{
|
|
2643
|
-
endpoint: "messages",
|
|
2644
|
-
method: "POST",
|
|
2645
|
-
summary: "Send a message",
|
|
2646
|
-
description:
|
|
2647
|
-
"Send a user message to a conversation and trigger the assistant response.",
|
|
2648
|
-
tags: ["messages"],
|
|
2649
|
-
requestBody: z.object({
|
|
2650
|
-
conversationKey: z.string().optional(),
|
|
2651
|
-
content: z.string().describe("Message text content"),
|
|
2652
|
-
attachments: z
|
|
2653
|
-
.array(z.unknown())
|
|
2654
|
-
.describe("Optional file attachments")
|
|
2655
|
-
.optional(),
|
|
2656
|
-
conversationType: z.string().optional(),
|
|
2657
|
-
slashCommand: z.string().optional(),
|
|
2658
|
-
}),
|
|
2659
|
-
handler: async ({ req, authContext }) =>
|
|
2660
|
-
handleSendMessage(
|
|
2661
|
-
req,
|
|
2662
|
-
{
|
|
2663
|
-
sendMessageDeps: deps.sendMessageDeps,
|
|
2664
|
-
approvalConversationGenerator: deps.approvalConversationGenerator,
|
|
2665
|
-
heartbeatService: deps.getHeartbeatService?.(),
|
|
2666
|
-
},
|
|
2667
|
-
authContext,
|
|
2212
|
+
export const ROUTES: RouteDefinition[] = [
|
|
2213
|
+
{
|
|
2214
|
+
operationId: "messages_get",
|
|
2215
|
+
endpoint: "messages",
|
|
2216
|
+
method: "GET",
|
|
2217
|
+
summary: "List messages",
|
|
2218
|
+
description:
|
|
2219
|
+
"Return messages for a conversation, including attachments and interface file metadata.",
|
|
2220
|
+
tags: ["messages"],
|
|
2221
|
+
responseBody: z.object({
|
|
2222
|
+
messages: z.array(z.unknown()).describe("Array of message objects"),
|
|
2223
|
+
hasMore: z
|
|
2224
|
+
.boolean()
|
|
2225
|
+
.optional()
|
|
2226
|
+
.describe("Whether older messages exist beyond this page"),
|
|
2227
|
+
oldestTimestamp: z
|
|
2228
|
+
.number()
|
|
2229
|
+
.nullable()
|
|
2230
|
+
.optional()
|
|
2231
|
+
.describe(
|
|
2232
|
+
"Timestamp of the oldest message in this page (ms since epoch). Null when page=latest is used on an empty conversation.",
|
|
2668
2233
|
),
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2234
|
+
oldestMessageId: z
|
|
2235
|
+
.string()
|
|
2236
|
+
.nullable()
|
|
2237
|
+
.optional()
|
|
2238
|
+
.describe("ID of the oldest message in this page"),
|
|
2239
|
+
}),
|
|
2240
|
+
handler: (args) => handleListMessages(args, getInterfacesDir()),
|
|
2241
|
+
},
|
|
2242
|
+
{
|
|
2243
|
+
operationId: "messages_post",
|
|
2244
|
+
endpoint: "messages",
|
|
2245
|
+
method: "POST",
|
|
2246
|
+
summary: "Send a message",
|
|
2247
|
+
description:
|
|
2248
|
+
"Send a user message to a conversation and trigger the assistant response.",
|
|
2249
|
+
tags: ["messages"],
|
|
2250
|
+
responseStatus: "202",
|
|
2251
|
+
requestBody: z.object({
|
|
2252
|
+
conversationKey: z.string().optional(),
|
|
2253
|
+
content: z.string().describe("Message text content"),
|
|
2254
|
+
attachments: z
|
|
2255
|
+
.array(z.unknown())
|
|
2256
|
+
.describe("Optional file attachments")
|
|
2257
|
+
.optional(),
|
|
2258
|
+
conversationType: z.string().optional(),
|
|
2259
|
+
slashCommand: z.string().optional(),
|
|
2260
|
+
inferenceProfile: z.string().nullable().optional(),
|
|
2261
|
+
riskThreshold: z.enum(VALID_RISK_THRESHOLDS).optional(),
|
|
2262
|
+
}),
|
|
2263
|
+
handler: async (args) =>
|
|
2264
|
+
handleSendMessage(args, {
|
|
2265
|
+
sendMessageDeps: {
|
|
2266
|
+
getOrCreateConversation: getOrCreateConversationInstance,
|
|
2267
|
+
assistantEventHub,
|
|
2268
|
+
resolveAttachments,
|
|
2269
|
+
},
|
|
2270
|
+
approvalConversationGenerator: createApprovalConversationGenerator(),
|
|
2679
2271
|
}),
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2272
|
+
},
|
|
2273
|
+
{
|
|
2274
|
+
operationId: "search_get",
|
|
2275
|
+
endpoint: "search",
|
|
2276
|
+
method: "GET",
|
|
2277
|
+
summary: "Search conversations",
|
|
2278
|
+
description: "Full-text search across all conversations.",
|
|
2279
|
+
tags: ["conversations"],
|
|
2280
|
+
responseBody: z.object({
|
|
2281
|
+
query: z.string(),
|
|
2282
|
+
results: z.array(z.unknown()),
|
|
2283
|
+
}),
|
|
2284
|
+
handler: handleSearchConversations,
|
|
2285
|
+
},
|
|
2286
|
+
{
|
|
2287
|
+
operationId: "suggestion_get",
|
|
2288
|
+
endpoint: "suggestion",
|
|
2289
|
+
method: "GET",
|
|
2290
|
+
summary: "Get reply suggestion",
|
|
2291
|
+
description:
|
|
2292
|
+
"Return an LLM-generated follow-up suggestion for the most recent assistant message.",
|
|
2293
|
+
tags: ["messages"],
|
|
2294
|
+
responseBody: z.object({
|
|
2295
|
+
suggestion: z.string(),
|
|
2296
|
+
messageId: z.string(),
|
|
2297
|
+
source: z.string(),
|
|
2298
|
+
}),
|
|
2299
|
+
handler: async (args) =>
|
|
2300
|
+
handleGetSuggestion(args, {
|
|
2301
|
+
suggestionCache,
|
|
2302
|
+
suggestionInFlight,
|
|
2693
2303
|
}),
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
suggestionCache: deps.suggestionCache,
|
|
2697
|
-
suggestionInFlight: deps.suggestionInFlight,
|
|
2698
|
-
}),
|
|
2699
|
-
},
|
|
2700
|
-
];
|
|
2701
|
-
}
|
|
2304
|
+
},
|
|
2305
|
+
];
|