@vellumai/assistant 0.7.0 → 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/ARCHITECTURE.md +6 -7
- package/Dockerfile +1 -0
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
- package/bun.lock +3 -0
- package/docs/architecture/security.md +18 -16
- package/knip.json +1 -0
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
- 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 +294 -107
- package/package.json +4 -2
- package/scripts/generate-openapi.ts +16 -111
- package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
- package/src/__tests__/anthropic-provider.test.ts +56 -13
- package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/approval-cascade.test.ts +0 -15
- package/src/__tests__/approval-routes-http.test.ts +6 -17
- 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 +37 -15
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
- package/src/__tests__/background-shell-host-bash.test.ts +34 -43
- package/src/__tests__/call-controller.test.ts +1 -1
- package/src/__tests__/call-site-routing-provider.test.ts +193 -0
- package/src/__tests__/channel-approval-routes.test.ts +10 -296
- package/src/__tests__/channel-approvals.test.ts +25 -17
- package/src/__tests__/channel-guardian.test.ts +100 -146
- package/src/__tests__/checker.test.ts +20 -34
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/config-schema.test.ts +6 -48
- package/src/__tests__/config-watcher.test.ts +12 -0
- package/src/__tests__/connection-policy.test.ts +1 -52
- package/src/__tests__/contacts-write.test.ts +2 -64
- package/src/__tests__/context-image-dimensions.test.ts +1 -1
- package/src/__tests__/context-search-memory-source.test.ts +120 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
- package/src/__tests__/context-search-pkb-source.test.ts +49 -0
- package/src/__tests__/context-search-workspace-source.test.ts +9 -22
- package/src/__tests__/context-window-manager.test.ts +46 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
- package/src/__tests__/conversation-agent-loop.test.ts +980 -13
- package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
- package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
- package/src/__tests__/conversation-history-web-search.test.ts +4 -3
- package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
- package/src/__tests__/conversation-lifecycle.test.ts +4 -4
- package/src/__tests__/conversation-process-callsite.test.ts +79 -2
- package/src/__tests__/conversation-queue.test.ts +3 -8
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
- package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
- package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
- package/src/__tests__/conversation-slash-commands.test.ts +24 -4
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-starter-routes.test.ts +79 -2
- 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 +8 -46
- package/src/__tests__/conversation-usage.test.ts +253 -3
- 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 +1 -5
- package/src/__tests__/credential-token-resolver.test.ts +180 -0
- 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 +4 -1
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
- package/src/__tests__/document-conversations.test.ts +332 -0
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
- package/src/__tests__/emit-event-signal.test.ts +4 -6
- package/src/__tests__/events-client-registration.test.ts +193 -49
- package/src/__tests__/filing-service.test.ts +58 -7
- package/src/__tests__/first-greeting.test.ts +156 -150
- package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
- package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -1
- package/src/__tests__/guardian-grant-minting.test.ts +7 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
- package/src/__tests__/guardian-routing-state.test.ts +1 -1
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
- 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 +289 -7
- package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/host-bash-proxy.test.ts +46 -122
- package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
- package/src/__tests__/host-browser-proxy.test.ts +111 -185
- package/src/__tests__/host-browser-routes.test.ts +45 -75
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
- 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-shell-tool.test.ts +33 -68
- package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
- package/src/__tests__/host-transfer-proxy.test.ts +43 -53
- package/src/__tests__/http-user-message-parity.test.ts +0 -6
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/injector-chain.test.ts +10 -5
- 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 +0 -2
- package/src/__tests__/install-skill-routing.test.ts +1 -13
- 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-resolution.test.ts +180 -0
- package/src/__tests__/llm-resolver.test.ts +80 -12
- package/src/__tests__/llm-usage-store.test.ts +269 -4
- package/src/__tests__/log-export-routes.test.ts +89 -0
- 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__/memory-v2-static-injector.test.ts +95 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
- package/src/__tests__/migration-export-http.test.ts +33 -26
- package/src/__tests__/migration-export-streaming.test.ts +18 -10
- package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
- package/src/__tests__/migration-import-commit-http.test.ts +66 -21
- package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
- package/src/__tests__/migration-import-from-url.test.ts +20 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
- 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 +105 -80
- package/src/__tests__/migration-wizard.test.ts +133 -27
- package/src/__tests__/non-member-access-request.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +19 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
- package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
- package/src/__tests__/pricing.test.ts +68 -4
- package/src/__tests__/process-message-background-slack.test.ts +331 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
- package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
- package/src/__tests__/provider-usage-tracking.test.ts +208 -0
- package/src/__tests__/reaction-persistence.test.ts +9 -6
- package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
- package/src/__tests__/recording-handler.test.ts +64 -81
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
- package/src/__tests__/relay-server.test.ts +18 -13
- package/src/__tests__/require-fresh-approval.test.ts +13 -22
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +3 -12
- 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 +0 -4
- 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 +5 -1
- package/src/__tests__/secret-scanner.test.ts +2 -545
- package/src/__tests__/send-endpoint-busy.test.ts +9 -24
- package/src/__tests__/settings-routes.test.ts +1 -1
- 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-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 -30
- package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
- package/src/__tests__/slack-inbound-verification.test.ts +1 -62
- package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
- package/src/__tests__/subagent-manager-notify.test.ts +70 -70
- package/src/__tests__/subagent-notify-parent.test.ts +80 -83
- package/src/__tests__/system-prompt.test.ts +115 -13
- package/src/__tests__/terminal-tools.test.ts +0 -89
- package/src/__tests__/thread-backfill.test.ts +945 -31
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
- package/src/__tests__/tool-executor.test.ts +12 -19
- package/src/__tests__/tool-metrics-listener.test.ts +0 -35
- 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__/trusted-contact-lifecycle-notifications.test.ts +2 -149
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +16 -5
- package/src/__tests__/usage-attribution.test.ts +247 -0
- 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 +150 -0
- 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 +49 -137
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
- package/src/__tests__/voice-session-bridge.test.ts +5 -5
- 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-memory-v2-init.test.ts +8 -30
- package/src/acp/index.ts +0 -15
- package/src/acp/session-manager.ts +37 -34
- package/src/agent/loop.ts +16 -1
- package/src/approvals/AGENTS.md +4 -0
- package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
- package/src/approvals/guardian-request-resolvers.ts +10 -2
- package/src/backup/__tests__/backup-worker.test.ts +36 -8
- package/src/backup/__tests__/paths.test.ts +2 -2
- package/src/backup/__tests__/restore.test.ts +45 -28
- package/src/backup/backup-worker.ts +36 -2
- package/src/backup/paths.ts +9 -6
- package/src/browser-session/events.ts +0 -9
- package/src/calls/call-store.ts +1 -34
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/relay-server.ts +0 -24
- package/src/calls/twilio-rest.ts +0 -38
- package/src/calls/twilio-routes.ts +1 -1
- package/src/calls/voice-session-bridge.ts +7 -38
- package/src/channels/types.ts +1 -36
- package/src/cli/commands/__tests__/cache.test.ts +152 -5
- package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
- package/src/cli/commands/__tests__/trust.test.ts +21 -387
- package/src/cli/commands/backup.ts +4 -4
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +153 -82
- package/src/cli/commands/clients.ts +63 -5
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +231 -76
- package/src/cli/commands/keys.ts +4 -1
- package/src/cli/commands/memory-v2.ts +24 -52
- package/src/cli/commands/oauth/shared.ts +2 -29
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/skills.ts +77 -35
- package/src/cli/commands/trust.ts +70 -430
- package/src/cli/commands/usage.ts +25 -16
- package/src/cli/lib/daemon-credential-client.ts +14 -0
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
- package/src/config/env-registry.ts +12 -2
- package/src/config/env.ts +3 -14
- package/src/config/feature-flag-registry.json +30 -30
- package/src/config/llm-callsite-catalog.ts +12 -0
- package/src/config/llm-context-resolution.ts +80 -0
- package/src/config/llm-resolver.ts +58 -22
- package/src/config/loader.ts +3 -3
- package/src/config/schema.ts +2 -158
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -5
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/ingress.ts +1 -1
- package/src/config/schemas/llm.ts +31 -3
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-v2.ts +9 -0
- package/src/config/schemas/security.ts +1 -42
- package/src/config/schemas/services.ts +6 -6
- 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 +0 -90
- package/src/config/types.ts +3 -6
- package/src/contacts/contact-store.ts +0 -17
- package/src/contacts/contacts-write.ts +1 -105
- package/src/context/window-manager.ts +44 -5
- package/src/credential-execution/process-manager.ts +34 -10
- package/src/credential-health/credential-health-service.ts +21 -16
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
- package/src/daemon/connection-policy.ts +1 -26
- package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
- package/src/daemon/conversation-agent-loop.ts +277 -36
- package/src/daemon/conversation-history.ts +8 -8
- package/src/daemon/conversation-launch.ts +20 -135
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-process.ts +83 -163
- package/src/daemon/conversation-runtime-assembly.ts +219 -76
- package/src/daemon/conversation-slash.ts +47 -5
- package/src/daemon/conversation-store.ts +7 -31
- package/src/daemon/conversation-surfaces.ts +22 -28
- package/src/daemon/conversation-tool-setup.ts +3 -33
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +117 -233
- package/src/daemon/daemon-control.ts +3 -71
- package/src/daemon/daemon-skill-host.ts +8 -11
- package/src/daemon/dictation-profile-store.ts +2 -26
- package/src/daemon/first-greeting.ts +44 -156
- package/src/daemon/handlers/config-channels.ts +12 -12
- package/src/daemon/handlers/config-ingress.ts +4 -165
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/config-voice.ts +0 -42
- package/src/daemon/handlers/conversations.ts +11 -190
- package/src/daemon/handlers/recording.ts +26 -158
- package/src/daemon/handlers/shared.ts +23 -71
- package/src/daemon/handlers/skills.ts +42 -93
- 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 +84 -46
- package/src/daemon/lifecycle.ts +49 -15
- package/src/daemon/message-types/conversations.ts +7 -0
- 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 +1 -0
- package/src/daemon/message-types/messages.ts +10 -9
- package/src/daemon/message-types/workspace.ts +1 -1
- package/src/daemon/process-message.ts +102 -239
- package/src/daemon/server.ts +13 -462
- package/src/daemon/shutdown-handlers.ts +2 -2
- package/src/daemon/tool-side-effects.ts +125 -107
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +4 -9
- package/src/events/domain-events.ts +0 -8
- package/src/events/tool-audit-listener.ts +3 -1
- package/src/events/tool-domain-event-publisher.ts +0 -10
- package/src/events/tool-metrics-listener.ts +0 -17
- package/src/events/tool-trace-listener.ts +0 -14
- package/src/filing/filing-service.ts +13 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
- package/src/heartbeat/heartbeat-service.ts +23 -5
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
- package/src/home/feed-writer.ts +1 -2
- package/src/home/relationship-state-writer.ts +16 -3
- package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
- package/src/ipc/assistant-server.ts +3 -10
- package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
- package/src/ipc/routes/route-adapter.ts +1 -1
- package/src/ipc/routes/trust-rules.test.ts +0 -95
- package/src/ipc/skill-ipc-types.ts +41 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
- package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
- package/src/ipc/skill-routes/events.ts +12 -23
- package/src/ipc/skill-routes/identity.ts +4 -17
- package/src/ipc/skill-routes/index.ts +1 -1
- package/src/ipc/skill-server.ts +6 -39
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
- package/src/live-voice/protocol.ts +4 -13
- package/src/mcp/manager.ts +0 -5
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
- package/src/memory/app-git-service.ts +0 -32
- package/src/memory/app-store.ts +154 -0
- package/src/memory/attachments-store.ts +6 -0
- package/src/memory/context-search/sources/memory-v2.ts +578 -0
- package/src/memory/context-search/sources/memory.ts +5 -0
- package/src/memory/context-search/sources/pkb.ts +10 -1
- package/src/memory/context-search/sources/workspace.ts +3 -2
- package/src/memory/conversation-crud.ts +29 -4
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +3 -21
- 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/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
- package/src/memory/graph/conversation-graph-memory.ts +35 -13
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/guardian-action-store.ts +0 -83
- package/src/memory/guardian-approvals.ts +0 -48
- package/src/memory/indexer.ts +1 -15
- package/src/memory/job-handlers/conversation-starters.ts +36 -53
- package/src/memory/job-utils.ts +0 -6
- package/src/memory/jobs-store.ts +0 -1
- package/src/memory/jobs-worker.ts +2 -16
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +129 -43
- package/src/memory/memory-v2-activation-log-store.ts +115 -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 +14 -0
- package/src/memory/migrations/registry.ts +24 -0
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/conversations.ts +7 -0
- package/src/memory/schema/infrastructure.ts +25 -0
- package/src/memory/search/semantic.ts +5 -16
- package/src/memory/tool-usage-store.ts +2 -0
- package/src/memory/usage-buckets.ts +40 -1
- package/src/memory/usage-grouped-buckets.ts +127 -0
- package/src/memory/v2/__tests__/activation.test.ts +289 -90
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
- package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
- package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
- package/src/memory/v2/__tests__/injection.test.ts +384 -15
- package/src/memory/v2/__tests__/migration.test.ts +64 -36
- package/src/memory/v2/__tests__/page-store.test.ts +191 -8
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
- package/src/memory/v2/__tests__/static-context.test.ts +153 -0
- package/src/memory/v2/activation.ts +168 -97
- package/src/memory/v2/backfill-jobs.ts +15 -100
- package/src/memory/v2/consolidation-job.ts +14 -12
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +182 -58
- package/src/memory/v2/migration.ts +57 -64
- package/src/memory/v2/now-text.ts +2 -3
- package/src/memory/v2/page-store.ts +168 -31
- package/src/memory/v2/prompts/consolidation.ts +118 -42
- package/src/memory/v2/prompts/sweep.ts +3 -3
- package/src/memory/v2/skill-store.ts +55 -7
- package/src/memory/v2/static-context.ts +62 -0
- package/src/memory/v2/types.ts +10 -20
- 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/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/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 +12 -2
- 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/types.ts +1 -0
- package/src/oauth/connection-resolver.test.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -16
- package/src/oauth/credential-token-resolver.ts +97 -0
- package/src/oauth/manual-token-connection.ts +30 -34
- package/src/oauth/oauth-store.ts +6 -4
- 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 -22
- package/src/permissions/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.ts +4 -1
- package/src/permissions/gateway-threshold-reader.ts +4 -1
- package/src/permissions/prompter.ts +9 -2
- package/src/permissions/secret-prompter.ts +21 -48
- package/src/permissions/types.ts +33 -0
- package/src/permissions/workspace-policy.ts +0 -5
- package/src/platform/sync-identity.ts +0 -8
- package/src/plugins/defaults/injectors.ts +69 -2
- package/src/plugins/defaults/overflow-reduce.ts +3 -2
- package/src/plugins/types.ts +8 -0
- package/src/prompts/system-prompt.ts +34 -70
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/update-bulletin-job.ts +2 -0
- package/src/providers/__tests__/retry-callsite.test.ts +138 -1
- package/src/providers/anthropic/client.ts +72 -33
- package/src/providers/call-site-routing.ts +42 -3
- package/src/providers/gemini/client.ts +18 -2
- package/src/providers/managed-proxy/context.ts +0 -5
- package/src/providers/model-catalog.ts +105 -19
- package/src/providers/openai/chat-completions-provider.ts +6 -0
- package/src/providers/openai/responses-provider.ts +7 -1
- package/src/providers/provider-send-message.ts +45 -2
- package/src/providers/ratelimit.ts +7 -2
- package/src/providers/registry.ts +14 -9
- package/src/providers/retry.ts +96 -8
- package/src/providers/types.ts +13 -0
- package/src/providers/usage-tracking.ts +96 -0
- package/src/runtime/AGENTS.md +10 -6
- package/src/runtime/__tests__/agent-wake.test.ts +89 -0
- package/src/runtime/agent-wake.ts +39 -2
- package/src/runtime/assistant-event-hub.ts +541 -45
- package/src/runtime/assistant-event.ts +1 -6
- package/src/runtime/auth/context.ts +0 -9
- package/src/runtime/auth/middleware.ts +1 -1
- package/src/runtime/auth/route-policy.ts +11 -9
- package/src/runtime/auth/token-service.ts +0 -11
- package/src/runtime/channel-approvals.ts +6 -2
- package/src/runtime/channel-verification-service.ts +3 -5
- package/src/runtime/http-errors.ts +0 -34
- package/src/runtime/http-router.ts +6 -3
- package/src/runtime/http-server.ts +22 -82
- package/src/runtime/http-types.ts +5 -0
- package/src/runtime/interactive-ui.ts +0 -1
- package/src/runtime/middleware/auth.ts +0 -20
- 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 +2 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -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 -79
- package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
- package/src/runtime/migrations/vbundle-importer.ts +7 -7
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
- package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
- package/src/runtime/migrations/vbundle-validator.ts +214 -41
- package/src/runtime/pending-interactions.ts +13 -4
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
- package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
- 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__/user-route-dispatcher.test.ts +7 -7
- package/src/runtime/routes/acp-routes.test.ts +0 -3
- package/src/runtime/routes/acp-routes.ts +3 -7
- package/src/runtime/routes/app-management-routes.ts +18 -9
- package/src/runtime/routes/approval-routes.ts +55 -14
- package/src/runtime/routes/avatar-routes.ts +3 -5
- package/src/runtime/routes/browser-routes.ts +1 -15
- package/src/runtime/routes/channel-guardian-routes.ts +1 -5
- package/src/runtime/routes/channel-readiness-routes.ts +3 -7
- package/src/runtime/routes/channel-route-shared.ts +2 -28
- package/src/runtime/routes/client-routes.ts +45 -12
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/conversation-list-routes.ts +12 -29
- package/src/runtime/routes/conversation-management-routes.ts +14 -51
- package/src/runtime/routes/conversation-query-routes.ts +120 -8
- package/src/runtime/routes/conversation-routes.ts +44 -528
- package/src/runtime/routes/conversation-starter-routes.ts +19 -40
- package/src/runtime/routes/documents-routes.ts +53 -18
- package/src/runtime/routes/events-routes.ts +59 -91
- package/src/runtime/routes/filing-routes.ts +18 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -9
- package/src/runtime/routes/host-bash-routes.ts +3 -2
- package/src/runtime/routes/host-browser-routes.ts +9 -33
- package/src/runtime/routes/host-cu-routes.ts +6 -1
- package/src/runtime/routes/host-file-routes.ts +3 -2
- package/src/runtime/routes/host-transfer-routes.ts +11 -15
- package/src/runtime/routes/identity-routes.ts +78 -6
- package/src/runtime/routes/inbound-message-handler.ts +580 -137
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
- package/src/runtime/routes/index.ts +4 -0
- package/src/runtime/routes/integrations/slack/channel.ts +0 -24
- package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
- package/src/runtime/routes/memory-v2-routes.ts +10 -15
- package/src/runtime/routes/migration-routes.ts +188 -31
- package/src/runtime/routes/playground/guard.ts +1 -1
- package/src/runtime/routes/playground/index.ts +0 -2
- package/src/runtime/routes/recording-routes.ts +4 -24
- package/src/runtime/routes/rename-conversation-routes.ts +2 -6
- package/src/runtime/routes/schedule-routes.ts +3 -6
- package/src/runtime/routes/secret-routes.ts +87 -18
- package/src/runtime/routes/settings-routes.ts +29 -28
- package/src/runtime/routes/skills-routes.ts +12 -31
- package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
- package/src/runtime/routes/task-routes.ts +6 -6
- package/src/runtime/routes/trust-rules-routes.ts +3 -94
- package/src/runtime/routes/types.ts +4 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
- package/src/runtime/routes/usage-routes.ts +87 -10
- package/src/runtime/routes/user-routes.ts +17 -31
- package/src/runtime/routes/work-items-routes.ts +1 -4
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
- package/src/runtime/services/analyze-conversation.ts +7 -17
- package/src/runtime/services/conversation-serializer.ts +2 -4
- package/src/runtime/verification-outbound-actions.ts +1 -1
- package/src/runtime/verification-rate-limiter.ts +1 -1
- package/src/schedule/schedule-store.ts +0 -16
- 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/signals/cancel.ts +16 -25
- package/src/signals/conversation-undo.ts +2 -27
- package/src/signals/emit-event.ts +1 -2
- package/src/signals/user-message.ts +108 -22
- package/src/skills/catalog-install.ts +1 -0
- package/src/skills/clawhub.ts +2 -2
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/subagent/manager.ts +67 -84
- package/src/tasks/task-store.ts +1 -28
- 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/spawn.test.ts +1 -2
- package/src/tools/acp/steer.test.ts +1 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
- package/src/tools/browser/browser-execution.ts +31 -147
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
- package/src/tools/browser/cdp-client/factory.ts +48 -76
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/executor.ts +44 -31
- 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 +45 -42
- package/src/tools/host-filesystem/transfer.ts +4 -3
- package/src/tools/host-filesystem/write.ts +3 -2
- package/src/tools/host-terminal/host-shell.ts +4 -3
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +66 -1
- package/src/tools/skills/sandbox-runner.ts +1 -6
- package/src/tools/skills/skill-tool-factory.ts +32 -0
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/terminal/shell.ts +2 -78
- package/src/tools/types.ts +12 -39
- 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/json.ts +13 -0
- package/src/util/logger.ts +3 -3
- package/src/util/pricing.ts +50 -3
- package/src/work-items/work-item-runner.ts +15 -42
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
- package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
- 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/registry.ts +8 -0
- package/src/workspace/provider-commit-message-generator.ts +3 -3
- 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 -67
- package/src/__tests__/secret-scanner-executor.test.ts +0 -450
- package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
- package/src/__tests__/terminal-sandbox.test.ts +0 -374
- package/src/__tests__/tool-notification-listener.test.ts +0 -65
- package/src/context/__tests__/microcompact.test.ts +0 -805
- package/src/context/microcompact.ts +0 -443
- package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
- package/src/events/tool-notification-listener.ts +0 -17
- package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
- package/src/memory/v2/__tests__/edges.test.ts +0 -435
- package/src/memory/v2/edges.ts +0 -217
- package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
- package/src/runtime/__tests__/client-registry.test.ts +0 -271
- package/src/runtime/chrome-extension-registry.ts +0 -368
- package/src/runtime/client-registry.ts +0 -254
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
- package/src/tools/secret-detection-handler.ts +0 -269
- package/src/tools/terminal/backends/native.ts +0 -327
- package/src/tools/terminal/backends/types.ts +0 -37
- package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
- package/src/tools/terminal/sandbox.ts +0 -40
|
@@ -31,6 +31,7 @@ import { tmpdir } from "node:os";
|
|
|
31
31
|
import { join } from "node:path";
|
|
32
32
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
33
33
|
|
|
34
|
+
import { defaultV1Options } from "../../runtime/migrations/__tests__/v1-test-helpers.js";
|
|
34
35
|
import { buildVBundle } from "../../runtime/migrations/vbundle-builder.js";
|
|
35
36
|
import type { PathResolver } from "../../runtime/migrations/vbundle-import-analyzer.js";
|
|
36
37
|
import type {
|
|
@@ -78,11 +79,13 @@ const NULL_RESOLVER: PathResolver = {
|
|
|
78
79
|
* the file path along with the manifest the builder embedded so tests can
|
|
79
80
|
* compare against it.
|
|
80
81
|
*/
|
|
81
|
-
function writeTinyPlaintextBundle(
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
function writeTinyPlaintextBundle(fileName: string): {
|
|
83
|
+
path: string;
|
|
84
|
+
manifest: ManifestType;
|
|
85
|
+
} {
|
|
84
86
|
const { archive, manifest } = buildVBundle({
|
|
85
87
|
files: [
|
|
88
|
+
{ path: "data/db/assistant.db", data: new Uint8Array() },
|
|
86
89
|
{
|
|
87
90
|
path: "workspace/notes/hello.txt",
|
|
88
91
|
data: new TextEncoder().encode("hello world"),
|
|
@@ -92,8 +95,7 @@ function writeTinyPlaintextBundle(
|
|
|
92
95
|
data: new TextEncoder().encode("a tiny bundle for tests"),
|
|
93
96
|
},
|
|
94
97
|
],
|
|
95
|
-
|
|
96
|
-
description: "tiny bundle for restore.test.ts",
|
|
98
|
+
...defaultV1Options(),
|
|
97
99
|
});
|
|
98
100
|
|
|
99
101
|
const path = join(TEST_DIR, fileName);
|
|
@@ -117,21 +119,35 @@ function makeStubCommitImpl(): {
|
|
|
117
119
|
const calls: RecordedCall[] = [];
|
|
118
120
|
const commitImpl = (options: ImportCommitOptions): ImportCommitResult => {
|
|
119
121
|
calls.push({ options });
|
|
120
|
-
const manifest =
|
|
122
|
+
const manifest: ManifestType =
|
|
121
123
|
options.preValidatedManifest ??
|
|
122
124
|
({
|
|
123
|
-
schema_version:
|
|
125
|
+
schema_version: 1,
|
|
126
|
+
bundle_id: "00000000-0000-4000-8000-000000000000",
|
|
124
127
|
created_at: new Date().toISOString(),
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
assistant: { id: "self", name: "Test", runtime_version: "0.0.0-test" },
|
|
129
|
+
origin: { mode: "self-hosted-local" },
|
|
130
|
+
compatibility: {
|
|
131
|
+
min_runtime_version: "0.0.0-test",
|
|
132
|
+
max_runtime_version: null,
|
|
133
|
+
},
|
|
134
|
+
contents: [],
|
|
135
|
+
checksum:
|
|
136
|
+
"0000000000000000000000000000000000000000000000000000000000000000",
|
|
137
|
+
secrets_redacted: false,
|
|
138
|
+
export_options: {
|
|
139
|
+
include_logs: false,
|
|
140
|
+
include_browser_state: false,
|
|
141
|
+
include_memory_vectors: false,
|
|
142
|
+
},
|
|
143
|
+
} as ManifestType);
|
|
128
144
|
return {
|
|
129
145
|
ok: true,
|
|
130
146
|
report: {
|
|
131
147
|
success: true,
|
|
132
148
|
summary: {
|
|
133
|
-
total_files: manifest.
|
|
134
|
-
files_created: manifest.
|
|
149
|
+
total_files: manifest.contents.length,
|
|
150
|
+
files_created: manifest.contents.length,
|
|
135
151
|
files_overwritten: 0,
|
|
136
152
|
files_skipped: 0,
|
|
137
153
|
backups_created: 0,
|
|
@@ -178,8 +194,9 @@ describe("verifySnapshot", () => {
|
|
|
178
194
|
expect(result.valid).toBe(true);
|
|
179
195
|
expect(result.manifest).toBeDefined();
|
|
180
196
|
expect(result.error).toBeUndefined();
|
|
181
|
-
expect(result.manifest?.
|
|
182
|
-
|
|
197
|
+
expect(result.manifest?.checksum).toBe(manifest.checksum);
|
|
198
|
+
// 3 = synthetic data/db/assistant.db + workspace/notes/hello.txt + workspace/notes/about.txt
|
|
199
|
+
expect(result.manifest?.contents.length).toBe(3);
|
|
183
200
|
});
|
|
184
201
|
|
|
185
202
|
test("encrypted: returns valid:true after decrypting first", async () => {
|
|
@@ -244,11 +261,13 @@ describe("verifySnapshot", () => {
|
|
|
244
261
|
// validateVBundle catches the bad manifest.
|
|
245
262
|
const { archive } = buildVBundle({
|
|
246
263
|
files: [
|
|
264
|
+
{ path: "data/db/assistant.db", data: new Uint8Array() },
|
|
247
265
|
{
|
|
248
266
|
path: "workspace/notes/hello.txt",
|
|
249
267
|
data: new TextEncoder().encode("hello"),
|
|
250
268
|
},
|
|
251
269
|
],
|
|
270
|
+
...defaultV1Options(),
|
|
252
271
|
});
|
|
253
272
|
|
|
254
273
|
// Flip a few bytes in the middle of the gzipped archive — this almost
|
|
@@ -292,21 +311,19 @@ describe("restoreFromSnapshot", () => {
|
|
|
292
311
|
const passed = calls[0].options;
|
|
293
312
|
// The wrapper should pass the pre-validated manifest + entries so
|
|
294
313
|
// commitImport doesn't re-validate.
|
|
295
|
-
expect(passed.preValidatedManifest?.
|
|
296
|
-
manifest.manifest_sha256,
|
|
297
|
-
);
|
|
314
|
+
expect(passed.preValidatedManifest?.checksum).toBe(manifest.checksum);
|
|
298
315
|
expect(passed.preValidatedEntries).toBeDefined();
|
|
299
316
|
expect(passed.preValidatedEntries?.has("manifest.json")).toBe(true);
|
|
300
|
-
expect(
|
|
301
|
-
|
|
302
|
-
)
|
|
317
|
+
expect(passed.preValidatedEntries?.has("workspace/notes/hello.txt")).toBe(
|
|
318
|
+
true,
|
|
319
|
+
);
|
|
303
320
|
// archiveData must be the actual bundle bytes.
|
|
304
321
|
expect(passed.archiveData).toBeInstanceOf(Uint8Array);
|
|
305
322
|
expect(passed.archiveData.length).toBeGreaterThan(0);
|
|
306
323
|
|
|
307
324
|
// Public result is shaped correctly.
|
|
308
|
-
expect(result.manifest.
|
|
309
|
-
expect(result.restoredFiles).toBe(
|
|
325
|
+
expect(result.manifest.checksum).toBe(manifest.checksum);
|
|
326
|
+
expect(result.restoredFiles).toBe(3);
|
|
310
327
|
});
|
|
311
328
|
|
|
312
329
|
test("encrypted round-trip: decrypts then commits, and cleans up the temp file", async () => {
|
|
@@ -327,8 +344,8 @@ describe("restoreFromSnapshot", () => {
|
|
|
327
344
|
const after = listRestoreTempArtifacts();
|
|
328
345
|
|
|
329
346
|
expect(calls.length).toBe(1);
|
|
330
|
-
expect(result.manifest.
|
|
331
|
-
expect(result.restoredFiles).toBe(
|
|
347
|
+
expect(result.manifest.checksum).toBe(manifest.checksum);
|
|
348
|
+
expect(result.restoredFiles).toBe(3);
|
|
332
349
|
|
|
333
350
|
// Decrypted temp file must be cleaned up after the call.
|
|
334
351
|
expect(after.length).toBe(before.length);
|
|
@@ -377,6 +394,7 @@ describe("restoreFromSnapshot", () => {
|
|
|
377
394
|
// the OS keychain / CES and are not part of the backup round trip.
|
|
378
395
|
const { archive, manifest } = buildVBundle({
|
|
379
396
|
files: [
|
|
397
|
+
{ path: "data/db/assistant.db", data: new Uint8Array() },
|
|
380
398
|
{
|
|
381
399
|
path: "workspace/notes/hello.txt",
|
|
382
400
|
data: new TextEncoder().encode("hello"),
|
|
@@ -386,6 +404,7 @@ describe("restoreFromSnapshot", () => {
|
|
|
386
404
|
data: new TextEncoder().encode("sk-test-1234"),
|
|
387
405
|
},
|
|
388
406
|
],
|
|
407
|
+
...defaultV1Options(),
|
|
389
408
|
});
|
|
390
409
|
|
|
391
410
|
const path = join(TEST_DIR, "with-creds.vbundle");
|
|
@@ -399,7 +418,7 @@ describe("restoreFromSnapshot", () => {
|
|
|
399
418
|
|
|
400
419
|
// The restore result must not expose a `credentials` field — the public
|
|
401
420
|
// type only has `manifest` and `restoredFiles`.
|
|
402
|
-
expect(result.manifest.
|
|
421
|
+
expect(result.manifest.checksum).toBe(manifest.checksum);
|
|
403
422
|
expect("credentials" in result).toBe(false);
|
|
404
423
|
});
|
|
405
424
|
|
|
@@ -468,9 +487,7 @@ describe("restoreFromSnapshot", () => {
|
|
|
468
487
|
|
|
469
488
|
// Stub that simulates a write failure (the importer returns this for
|
|
470
489
|
// disk errors like permission denied or partial bundle writes).
|
|
471
|
-
const failingCommit = (
|
|
472
|
-
_opts: ImportCommitOptions,
|
|
473
|
-
): ImportCommitResult => ({
|
|
490
|
+
const failingCommit = (_opts: ImportCommitOptions): ImportCommitResult => ({
|
|
474
491
|
ok: false,
|
|
475
492
|
reason: "write_failed",
|
|
476
493
|
message: "disk full",
|
|
@@ -26,18 +26,24 @@
|
|
|
26
26
|
* surface against temp directories with tiny fake bundles.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
+
import { hostname } from "node:os";
|
|
29
30
|
import { Database } from "bun:sqlite";
|
|
30
31
|
|
|
31
32
|
import { getConfig } from "../config/loader.js";
|
|
32
33
|
import type { BackupConfig } from "../config/schema.js";
|
|
34
|
+
import { getAssistantName } from "../daemon/identity-helpers.js";
|
|
33
35
|
import {
|
|
34
36
|
getMemoryCheckpoint as realGetMemoryCheckpoint,
|
|
35
37
|
setMemoryCheckpoint as realSetMemoryCheckpoint,
|
|
36
38
|
} from "../memory/checkpoints.js";
|
|
39
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
40
|
+
import type { VBundleOriginMode } from "../runtime/migrations/origin-mode.js";
|
|
37
41
|
import type { StreamExportVBundleResult } from "../runtime/migrations/vbundle-builder.js";
|
|
38
42
|
import { streamExportVBundle as realStreamExportVBundle } from "../runtime/migrations/vbundle-builder.js";
|
|
43
|
+
import { getDaemonRuntimeMode } from "../runtime/runtime-mode.js";
|
|
39
44
|
import { getLogger } from "../util/logger.js";
|
|
40
45
|
import { getDbPath, getWorkspaceDir } from "../util/platform.js";
|
|
46
|
+
import { APP_VERSION } from "../version.js";
|
|
41
47
|
import { ensureBackupKey as realEnsureBackupKey } from "./backup-key.js";
|
|
42
48
|
import type { SnapshotEntry } from "./list-snapshots.js";
|
|
43
49
|
import { pruneLocalSnapshots, writeLocalSnapshot } from "./local-writer.js";
|
|
@@ -185,10 +191,38 @@ async function performBackup(
|
|
|
185
191
|
// mirrors the pattern in `handleMigrationExport`: open a fresh Database
|
|
186
192
|
// handle, run PRAGMA wal_checkpoint(TRUNCATE), close it. Any failure is
|
|
187
193
|
// best-effort — the export still proceeds with whatever is on disk.
|
|
194
|
+
//
|
|
195
|
+
// The backup worker bundles credentials by design (its purpose is local
|
|
196
|
+
// recovery), so `secretsRedacted: false`. Backups run locally on the host
|
|
197
|
+
// machine; managed deployments delegate to the platform. Hardcoding to
|
|
198
|
+
// self-hosted ensures the resulting bundle satisfies the v1 schema's
|
|
199
|
+
// refine for managed/secrets_redacted — `getOriginMode()` would return
|
|
200
|
+
// "managed" in a managed deployment, producing a non-restorable bundle.
|
|
201
|
+
const originMode: VBundleOriginMode =
|
|
202
|
+
getDaemonRuntimeMode() === "docker"
|
|
203
|
+
? "self-hosted-remote"
|
|
204
|
+
: "self-hosted-local";
|
|
188
205
|
const result = await streamExport({
|
|
189
206
|
workspaceDir,
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
assistant: {
|
|
208
|
+
id: DAEMON_INTERNAL_ASSISTANT_ID,
|
|
209
|
+
name: getAssistantName() ?? "Assistant",
|
|
210
|
+
runtime_version: APP_VERSION,
|
|
211
|
+
},
|
|
212
|
+
origin: {
|
|
213
|
+
mode: originMode,
|
|
214
|
+
hostname: hostname(),
|
|
215
|
+
},
|
|
216
|
+
compatibility: {
|
|
217
|
+
min_runtime_version: APP_VERSION,
|
|
218
|
+
max_runtime_version: null,
|
|
219
|
+
},
|
|
220
|
+
exportOptions: {
|
|
221
|
+
include_logs: true,
|
|
222
|
+
include_browser_state: false,
|
|
223
|
+
include_memory_vectors: false,
|
|
224
|
+
},
|
|
225
|
+
secretsRedacted: false,
|
|
192
226
|
checkpoint: () => {
|
|
193
227
|
const dbPath = getDbPath();
|
|
194
228
|
try {
|
package/src/backup/paths.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getBackupKeyPathOverride,
|
|
7
7
|
} from "../config/env-registry.js";
|
|
8
8
|
import type { BackupDestination } from "../config/schema.js";
|
|
9
|
-
import {
|
|
9
|
+
import { getWorkspaceDir } from "../util/platform.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Returns the backup root directory. Respects the `VELLUM_BACKUP_DIR`
|
|
@@ -134,13 +134,16 @@ export function resolveOffsiteDestinations(
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
* Returns the path to the backup encryption key file.
|
|
138
|
-
*
|
|
139
|
-
* can override
|
|
140
|
-
* persistent volume.
|
|
137
|
+
* Returns the path to the backup encryption key file.
|
|
138
|
+
*
|
|
139
|
+
* The `VELLUM_BACKUP_KEY_PATH` env var can override this for containerized
|
|
140
|
+
* deployments where the key must live on a persistent volume.
|
|
141
|
+
*
|
|
142
|
+
* TODO: The backup key is a credential and should eventually be managed by the
|
|
143
|
+
* gateway (behind IPC), not stored on the daemon's filesystem.
|
|
141
144
|
*/
|
|
142
145
|
export function getBackupKeyPath(): string {
|
|
143
|
-
return getBackupKeyPathOverride() ?? join(
|
|
146
|
+
return getBackupKeyPathOverride() ?? join(getWorkspaceDir(), ".backup.key");
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
/**
|
|
@@ -132,15 +132,6 @@ export function isTargetInvalidated(targetId: string): boolean {
|
|
|
132
132
|
return invalidatedTargetIds.has(targetId);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
/**
|
|
136
|
-
* Test-only helper: snapshot the current invalidated set without
|
|
137
|
-
* draining it. Exported so unit tests can assert exact set contents
|
|
138
|
-
* across multiple frames; production code must not rely on this.
|
|
139
|
-
*/
|
|
140
|
-
export function __peekInvalidatedTargetIdsForTests(): string[] {
|
|
141
|
-
return Array.from(invalidatedTargetIds);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
135
|
/**
|
|
145
136
|
* Atomically remove and return a target id from the invalidated set.
|
|
146
137
|
* Returns `true` when the id was present (and has now been removed),
|
package/src/calls/call-store.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { and, desc, eq, notInArray, or } from "drizzle-orm";
|
|
|
2
2
|
import { v4 as uuid } from "uuid";
|
|
3
3
|
|
|
4
4
|
import { getDb } from "../memory/db-connection.js";
|
|
5
|
-
import { rawChanges,
|
|
5
|
+
import { rawChanges, rawRun } from "../memory/raw-query.js";
|
|
6
6
|
import {
|
|
7
7
|
callEvents,
|
|
8
8
|
callPendingQuestions,
|
|
@@ -379,39 +379,6 @@ export function buildCallbackDedupeKey(
|
|
|
379
379
|
return `${callSid}:${callStatus}:${discriminator}`;
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
-
/**
|
|
383
|
-
* Check whether a callback dedupe key has already been processed (read-only).
|
|
384
|
-
* Returns true if the key already exists, false otherwise.
|
|
385
|
-
*/
|
|
386
|
-
export function isCallbackProcessed(dedupeKey: string): boolean {
|
|
387
|
-
return (
|
|
388
|
-
rawGet<{ 1: number }>(
|
|
389
|
-
`SELECT 1 FROM processed_callbacks WHERE dedupe_key = ?`,
|
|
390
|
-
dedupeKey,
|
|
391
|
-
) != null
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* Record a callback as processed. Should be called AFTER downstream writes
|
|
397
|
-
* (session updates, event recording) have succeeded so that Twilio retries
|
|
398
|
-
* are not silently dropped if those writes fail.
|
|
399
|
-
*
|
|
400
|
-
* Uses INSERT OR IGNORE so concurrent calls for the same key are safe.
|
|
401
|
-
*/
|
|
402
|
-
export function recordProcessedCallback(
|
|
403
|
-
dedupeKey: string,
|
|
404
|
-
callSessionId: string,
|
|
405
|
-
): void {
|
|
406
|
-
rawRun(
|
|
407
|
-
`INSERT OR IGNORE INTO processed_callbacks (id, dedupe_key, call_session_id, created_at) VALUES (?, ?, ?, ?)`,
|
|
408
|
-
uuid(),
|
|
409
|
-
dedupeKey,
|
|
410
|
-
callSessionId,
|
|
411
|
-
Date.now(),
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
382
|
/**
|
|
416
383
|
* Atomically claim a callback for processing. Returns a unique claim ID
|
|
417
384
|
* (string) if this caller won the claim, or null if another caller already
|
|
@@ -6,18 +6,7 @@
|
|
|
6
6
|
* when the provider is unavailable or generation fails/times out.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
createTimeout,
|
|
11
|
-
extractText,
|
|
12
|
-
resolveConfiguredProvider,
|
|
13
|
-
userMessage,
|
|
14
|
-
} from "../providers/provider-send-message.js";
|
|
15
|
-
import { getLogger } from "../util/logger.js";
|
|
16
|
-
|
|
17
|
-
const log = getLogger("guardian-question-copy");
|
|
18
|
-
|
|
19
9
|
/** Timeout for the generative copy call (ms). */
|
|
20
|
-
const GENERATION_TIMEOUT_MS = 5_000;
|
|
21
10
|
|
|
22
11
|
export interface GuardianCopy {
|
|
23
12
|
conversationTitle: string;
|
|
@@ -39,100 +28,3 @@ export function buildFallbackCopy(questionText: string): GuardianCopy {
|
|
|
39
28
|
].join("\n"),
|
|
40
29
|
};
|
|
41
30
|
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Generate guardian conversation copy (title + initial message) via the configured
|
|
45
|
-
* LLM provider. Returns deterministic fallback when the provider is unavailable,
|
|
46
|
-
* generation times out, or any error occurs.
|
|
47
|
-
*/
|
|
48
|
-
export async function generateGuardianCopy(
|
|
49
|
-
questionText: string,
|
|
50
|
-
requestCode?: string,
|
|
51
|
-
): Promise<GuardianCopy> {
|
|
52
|
-
const fallback = buildFallbackCopy(questionText);
|
|
53
|
-
|
|
54
|
-
// If no provider is configured, return fallback immediately
|
|
55
|
-
const resolved = await resolveConfiguredProvider("guardianQuestionCopy");
|
|
56
|
-
if (!resolved) {
|
|
57
|
-
log.debug(
|
|
58
|
-
"No provider available for guardian copy generation, using fallback",
|
|
59
|
-
);
|
|
60
|
-
return fallback;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const { signal, cleanup } = createTimeout(GENERATION_TIMEOUT_MS);
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const prompt = [
|
|
67
|
-
"Generate a conversation title and initial message for a guardian question during a live phone call.",
|
|
68
|
-
"",
|
|
69
|
-
`Question: ${questionText}`,
|
|
70
|
-
...(requestCode ? [`Reference code: ${requestCode}`] : []),
|
|
71
|
-
"",
|
|
72
|
-
"Requirements:",
|
|
73
|
-
'- TITLE: An emoji-prefixed, attention-oriented, concise title (under 80 characters). Do NOT start with "Guardian question:". Use a relevant warning or alert emoji.',
|
|
74
|
-
"- MESSAGE: A clear initial message that includes the question text, mentions this is a live phone call waiting for the user's input, and asks them to reply with their answer.",
|
|
75
|
-
"",
|
|
76
|
-
"Respond in exactly this format (no extra text):",
|
|
77
|
-
"TITLE: <your title>",
|
|
78
|
-
"MESSAGE: <your message>",
|
|
79
|
-
].join("\n");
|
|
80
|
-
|
|
81
|
-
const response = await resolved.provider.sendMessage(
|
|
82
|
-
[userMessage(prompt)],
|
|
83
|
-
undefined,
|
|
84
|
-
undefined,
|
|
85
|
-
{ signal, config: { callSite: "guardianQuestionCopy" } },
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const text = extractText(response);
|
|
89
|
-
const parsed = parseGeneratedCopy(text);
|
|
90
|
-
|
|
91
|
-
if (parsed) {
|
|
92
|
-
return parsed;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
log.warn(
|
|
96
|
-
{ raw: text },
|
|
97
|
-
"Failed to parse generated guardian copy, using fallback",
|
|
98
|
-
);
|
|
99
|
-
return fallback;
|
|
100
|
-
} catch (err) {
|
|
101
|
-
if (signal.aborted) {
|
|
102
|
-
log.warn("Guardian copy generation timed out, using fallback");
|
|
103
|
-
} else {
|
|
104
|
-
log.warn({ err }, "Guardian copy generation failed, using fallback");
|
|
105
|
-
}
|
|
106
|
-
return fallback;
|
|
107
|
-
} finally {
|
|
108
|
-
cleanup();
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Parse the structured TITLE/MESSAGE response from the model.
|
|
114
|
-
* Returns null if the format is not matched.
|
|
115
|
-
*/
|
|
116
|
-
function parseGeneratedCopy(text: string): GuardianCopy | null {
|
|
117
|
-
const titleMatch = text.match(/^TITLE:\s*(.+)/m);
|
|
118
|
-
const messageMatch = text.match(/^MESSAGE:\s*([\s\S]+)/m);
|
|
119
|
-
|
|
120
|
-
if (!titleMatch || !messageMatch) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const title = titleMatch[1].trim();
|
|
125
|
-
const message = messageMatch[1].trim();
|
|
126
|
-
|
|
127
|
-
// Sanity checks: title must be non-empty and under 80 chars, message must be non-empty
|
|
128
|
-
if (!title || title.length > 80 || !message) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Reject the old static prefix — the model is guided towards better titles but has final say
|
|
133
|
-
if (/^guardian question:/i.test(title)) {
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return { conversationTitle: title, initialMessage: message };
|
|
138
|
-
}
|
|
@@ -15,8 +15,6 @@ import {
|
|
|
15
15
|
listGuardianChannels,
|
|
16
16
|
} from "../contacts/contact-store.js";
|
|
17
17
|
import {
|
|
18
|
-
createGuardianBinding,
|
|
19
|
-
revokeGuardianBinding,
|
|
20
18
|
touchContactInteraction,
|
|
21
19
|
upsertContactChannel,
|
|
22
20
|
} from "../contacts/contacts-write.js";
|
|
@@ -998,28 +996,6 @@ export class RelayConnection {
|
|
|
998
996
|
"Guardian voice verification succeeded",
|
|
999
997
|
);
|
|
1000
998
|
|
|
1001
|
-
// Create the guardian binding now that verification succeeded.
|
|
1002
|
-
if (result.verificationType === "guardian") {
|
|
1003
|
-
if (result.bindingConflict) {
|
|
1004
|
-
log.warn(
|
|
1005
|
-
{
|
|
1006
|
-
callSessionId: this.callSessionId,
|
|
1007
|
-
existingGuardian: result.bindingConflict.existingGuardian,
|
|
1008
|
-
},
|
|
1009
|
-
"Guardian binding conflict: another user already holds the voice binding",
|
|
1010
|
-
);
|
|
1011
|
-
} else {
|
|
1012
|
-
revokeGuardianBinding("phone");
|
|
1013
|
-
createGuardianBinding({
|
|
1014
|
-
channel: "phone",
|
|
1015
|
-
guardianExternalUserId: fromNumber,
|
|
1016
|
-
guardianDeliveryChatId: fromNumber,
|
|
1017
|
-
guardianPrincipalId: result.canonicalPrincipal!,
|
|
1018
|
-
verifiedVia: "challenge",
|
|
1019
|
-
});
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
999
|
if (isOutbound) {
|
|
1024
1000
|
// Keep the pointer message back to the initiating conversation
|
|
1025
1001
|
const successSession = getCallSession(this.callSessionId);
|
package/src/calls/twilio-rest.ts
CHANGED
|
@@ -210,44 +210,6 @@ export async function provisionPhoneNumber(
|
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
/** Fetch the current status of a Twilio message by SID. */
|
|
214
|
-
export async function fetchMessageStatus(
|
|
215
|
-
accountSid: string,
|
|
216
|
-
authToken: string,
|
|
217
|
-
messageSid: string,
|
|
218
|
-
): Promise<{ status: string; errorCode?: string; errorMessage?: string }> {
|
|
219
|
-
const res = await fetch(
|
|
220
|
-
`${twilioBaseUrl(accountSid)}/Messages/${encodeURIComponent(
|
|
221
|
-
messageSid,
|
|
222
|
-
)}.json`,
|
|
223
|
-
{
|
|
224
|
-
method: "GET",
|
|
225
|
-
headers: { Authorization: twilioAuthHeader(accountSid, authToken) },
|
|
226
|
-
},
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
if (!res.ok) {
|
|
230
|
-
const text = await res.text();
|
|
231
|
-
throw new ProviderError(
|
|
232
|
-
`Twilio API error ${res.status}: ${text}`,
|
|
233
|
-
"twilio",
|
|
234
|
-
res.status,
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const data = (await res.json()) as {
|
|
239
|
-
status?: string;
|
|
240
|
-
error_code?: number | null;
|
|
241
|
-
error_message?: string | null;
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
return {
|
|
245
|
-
status: data.status ?? "unknown",
|
|
246
|
-
errorCode: data.error_code != null ? String(data.error_code) : undefined,
|
|
247
|
-
errorMessage: data.error_message ?? undefined,
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
|
|
251
213
|
export interface WebhookUrls {
|
|
252
214
|
voiceUrl: string;
|
|
253
215
|
statusCallbackUrl: string;
|
|
@@ -65,7 +65,7 @@ const log = getLogger("twilio-routes");
|
|
|
65
65
|
* The gateway replaces this with a real JWT before returning TwiML to Twilio.
|
|
66
66
|
* This keeps the signing key out of the daemon for voice webhook responses.
|
|
67
67
|
*/
|
|
68
|
-
|
|
68
|
+
const TWILIO_RELAY_TOKEN_PLACEHOLDER = "__VELLUM_RELAY_TOKEN__";
|
|
69
69
|
|
|
70
70
|
// ── Speech config type ───────────────────────────────────────────────
|
|
71
71
|
|
|
@@ -22,8 +22,7 @@ import type { Conversation } from "../daemon/conversation.js";
|
|
|
22
22
|
import { resolveChannelCapabilities } from "../daemon/conversation-runtime-assembly.js";
|
|
23
23
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
24
24
|
import type { TrustContext } from "../daemon/trust-context.js";
|
|
25
|
-
import {
|
|
26
|
-
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
25
|
+
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
27
26
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
28
27
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
29
28
|
import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
|
|
@@ -418,34 +417,6 @@ export async function startVoiceTurn(
|
|
|
418
417
|
);
|
|
419
418
|
}
|
|
420
419
|
|
|
421
|
-
// Serialized publish chain so hub subscribers observe events in order.
|
|
422
|
-
let hubChain: Promise<void> = Promise.resolve();
|
|
423
|
-
const publishToHub = (msg: ServerMessage): void => {
|
|
424
|
-
// ServerMessage is a large union; conversationId exists on most but not all variants.
|
|
425
|
-
const msgConversationId =
|
|
426
|
-
"conversationId" in msg &&
|
|
427
|
-
typeof (msg as { conversationId?: unknown }).conversationId === "string"
|
|
428
|
-
? (msg as { conversationId: string }).conversationId
|
|
429
|
-
: undefined;
|
|
430
|
-
const resolvedConversationId = msgConversationId ?? opts.conversationId;
|
|
431
|
-
const event = buildAssistantEvent(
|
|
432
|
-
DAEMON_INTERNAL_ASSISTANT_ID,
|
|
433
|
-
msg,
|
|
434
|
-
resolvedConversationId,
|
|
435
|
-
);
|
|
436
|
-
hubChain = (async () => {
|
|
437
|
-
await hubChain;
|
|
438
|
-
try {
|
|
439
|
-
await assistantEventHub.publish(event);
|
|
440
|
-
} catch (err) {
|
|
441
|
-
log.warn(
|
|
442
|
-
{ err },
|
|
443
|
-
"assistant-events hub subscriber threw during voice turn",
|
|
444
|
-
);
|
|
445
|
-
}
|
|
446
|
-
})();
|
|
447
|
-
};
|
|
448
|
-
|
|
449
420
|
// Hook into conversation to intercept confirmation_request and secret_request events.
|
|
450
421
|
// Voice auto-denies/auto-allows/auto-resolves these since there's no interactive UI.
|
|
451
422
|
const autoDeny = !isGuardian;
|
|
@@ -455,7 +426,6 @@ export async function startVoiceTurn(
|
|
|
455
426
|
if (msg.type === "confirmation_request") {
|
|
456
427
|
if (usesLocalInteractiveApprovals) {
|
|
457
428
|
pendingInteractions.register(msg.requestId, {
|
|
458
|
-
conversation,
|
|
459
429
|
conversationId: opts.conversationId,
|
|
460
430
|
kind: "confirmation",
|
|
461
431
|
confirmationDetails: {
|
|
@@ -470,7 +440,7 @@ export async function startVoiceTurn(
|
|
|
470
440
|
acpOptions: msg.acpOptions,
|
|
471
441
|
},
|
|
472
442
|
});
|
|
473
|
-
|
|
443
|
+
broadcastMessage(msg);
|
|
474
444
|
return;
|
|
475
445
|
}
|
|
476
446
|
if (autoDeny) {
|
|
@@ -518,7 +488,7 @@ export async function startVoiceTurn(
|
|
|
518
488
|
undefined,
|
|
519
489
|
`Permission approved for "${msg.toolName}": guardian pre-approved via scoped grant.`,
|
|
520
490
|
);
|
|
521
|
-
|
|
491
|
+
broadcastMessage(msg);
|
|
522
492
|
return;
|
|
523
493
|
}
|
|
524
494
|
} catch (err) {
|
|
@@ -539,7 +509,7 @@ export async function startVoiceTurn(
|
|
|
539
509
|
undefined,
|
|
540
510
|
`Permission denied for "${msg.toolName}": this voice call does not have interactive approval capabilities. Side-effect tools are not available for non-guardian voice callers. In your next assistant reply, explain briefly that this action requires guardian-level access and cannot be performed during this call.`,
|
|
541
511
|
);
|
|
542
|
-
|
|
512
|
+
broadcastMessage(msg);
|
|
543
513
|
return;
|
|
544
514
|
}
|
|
545
515
|
if (autoAllow) {
|
|
@@ -554,7 +524,7 @@ export async function startVoiceTurn(
|
|
|
554
524
|
undefined,
|
|
555
525
|
`Permission approved for "${msg.toolName}": this is a verified guardian voice call.`,
|
|
556
526
|
);
|
|
557
|
-
|
|
527
|
+
broadcastMessage(msg);
|
|
558
528
|
return;
|
|
559
529
|
}
|
|
560
530
|
} else if (msg.type === "secret_request") {
|
|
@@ -564,10 +534,9 @@ export async function startVoiceTurn(
|
|
|
564
534
|
"Auto-resolving secret request for voice turn (no secret-entry UI)",
|
|
565
535
|
);
|
|
566
536
|
conversation.handleSecretResponse(msg.requestId, undefined, "store");
|
|
567
|
-
publishToHub(msg);
|
|
568
537
|
return;
|
|
569
538
|
}
|
|
570
|
-
|
|
539
|
+
broadcastMessage(msg);
|
|
571
540
|
});
|
|
572
541
|
|
|
573
542
|
// Fire-and-forget the agent loop
|
|
@@ -596,7 +565,7 @@ export async function startVoiceTurn(
|
|
|
596
565
|
} else if (msg.type === "conversation_error") {
|
|
597
566
|
lastError = msg.userMessage;
|
|
598
567
|
}
|
|
599
|
-
|
|
568
|
+
broadcastMessage(msg);
|
|
600
569
|
|
|
601
570
|
// Forward voice-relevant events to the real-time event sink
|
|
602
571
|
if (msg.type === "assistant_text_delta") {
|