@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
|
@@ -160,6 +160,14 @@ mock.module("node:fs", () => {
|
|
|
160
160
|
};
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
+
// Capture broadcastMessage calls
|
|
164
|
+
const broadcastedMessages: Array<{ type: string; [k: string]: unknown }> = [];
|
|
165
|
+
mock.module("../runtime/assistant-event-hub.js", () => ({
|
|
166
|
+
broadcastMessage: (msg: unknown) => {
|
|
167
|
+
broadcastedMessages.push(msg as { type: string; [k: string]: unknown });
|
|
168
|
+
},
|
|
169
|
+
}));
|
|
170
|
+
|
|
163
171
|
// ─── Imports (after mocks) ──────────────────────────────────────────────────
|
|
164
172
|
|
|
165
173
|
import {
|
|
@@ -168,38 +176,13 @@ import {
|
|
|
168
176
|
handleRecordingStatusCore,
|
|
169
177
|
handleRecordingStop,
|
|
170
178
|
} from "../daemon/handlers/recording.js";
|
|
171
|
-
import type { HandlerContext } from "../daemon/handlers/shared.js";
|
|
172
179
|
import type { RecordingStatus } from "../daemon/message-types/computer-use.js";
|
|
173
|
-
import { DebouncerMap } from "../util/debounce.js";
|
|
174
180
|
|
|
175
181
|
// ─── Test helpers ───────────────────────────────────────────────────────────
|
|
176
182
|
|
|
177
|
-
function
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
} {
|
|
181
|
-
const sent: Array<{ type: string; [k: string]: unknown }> = [];
|
|
182
|
-
|
|
183
|
-
const ctx: HandlerContext = {
|
|
184
|
-
sharedRequestTimestamps: [],
|
|
185
|
-
debounceTimers: new DebouncerMap({ defaultDelayMs: 200 }),
|
|
186
|
-
suppressConfigReload: false,
|
|
187
|
-
setSuppressConfigReload: noop,
|
|
188
|
-
updateConfigFingerprint: noop,
|
|
189
|
-
send: (msg) => {
|
|
190
|
-
sent.push(msg as { type: string; [k: string]: unknown });
|
|
191
|
-
},
|
|
192
|
-
broadcast: (msg) => {
|
|
193
|
-
sent.push(msg as { type: string; [k: string]: unknown });
|
|
194
|
-
},
|
|
195
|
-
clearAllConversations: () => 0,
|
|
196
|
-
getOrCreateConversation: () => {
|
|
197
|
-
throw new Error("not implemented");
|
|
198
|
-
},
|
|
199
|
-
touchConversation: noop,
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
return { ctx, sent };
|
|
183
|
+
function createSent(): Array<{ type: string; [k: string]: unknown }> {
|
|
184
|
+
broadcastedMessages.length = 0;
|
|
185
|
+
return broadcastedMessages;
|
|
203
186
|
}
|
|
204
187
|
|
|
205
188
|
// ─── Tests ──────────────────────────────────────────────────────────────────
|
|
@@ -216,10 +199,10 @@ describe("handleRecordingStart", () => {
|
|
|
216
199
|
});
|
|
217
200
|
|
|
218
201
|
test("sends recording_start event and returns a UUID", () => {
|
|
219
|
-
const
|
|
202
|
+
const sent = createSent();
|
|
220
203
|
const conversationId = "conv-1";
|
|
221
204
|
|
|
222
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
205
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
223
206
|
|
|
224
207
|
expect(recordingId).not.toBeNull();
|
|
225
208
|
// UUID v4 format
|
|
@@ -234,21 +217,21 @@ describe("handleRecordingStart", () => {
|
|
|
234
217
|
});
|
|
235
218
|
|
|
236
219
|
test("passes recording options through", () => {
|
|
237
|
-
const
|
|
220
|
+
const sent = createSent();
|
|
238
221
|
const options = { captureScope: "window" as const, includeAudio: true };
|
|
239
222
|
|
|
240
|
-
handleRecordingStart("conv-2", options
|
|
223
|
+
handleRecordingStart("conv-2", options);
|
|
241
224
|
|
|
242
225
|
expect(sent[0].options).toEqual(options);
|
|
243
226
|
});
|
|
244
227
|
|
|
245
228
|
test("returns null when recording already active and sends no messages", () => {
|
|
246
|
-
const
|
|
229
|
+
const sent = createSent();
|
|
247
230
|
|
|
248
|
-
const id1 = handleRecordingStart("conv-3", undefined
|
|
231
|
+
const id1 = handleRecordingStart("conv-3", undefined);
|
|
249
232
|
expect(id1).toBeTruthy();
|
|
250
233
|
|
|
251
|
-
const id2 = handleRecordingStart("conv-3", undefined
|
|
234
|
+
const id2 = handleRecordingStart("conv-3", undefined);
|
|
252
235
|
|
|
253
236
|
// Should return null (callers handle messaging)
|
|
254
237
|
expect(id2).toBeNull();
|
|
@@ -259,13 +242,13 @@ describe("handleRecordingStart", () => {
|
|
|
259
242
|
});
|
|
260
243
|
|
|
261
244
|
test("returns null when a different conversation already has an active recording (global guard)", () => {
|
|
262
|
-
const
|
|
245
|
+
const sent = createSent();
|
|
263
246
|
|
|
264
|
-
const id1 = handleRecordingStart("conv-global-a", undefined
|
|
247
|
+
const id1 = handleRecordingStart("conv-global-a", undefined);
|
|
265
248
|
expect(id1).toBeTruthy();
|
|
266
249
|
|
|
267
250
|
// A second start from a different conversation should be rejected
|
|
268
|
-
const id2 = handleRecordingStart("conv-global-b", undefined
|
|
251
|
+
const id2 = handleRecordingStart("conv-global-b", undefined);
|
|
269
252
|
expect(id2).toBeNull();
|
|
270
253
|
|
|
271
254
|
// Only the first call sends recording_start
|
|
@@ -287,15 +270,15 @@ describe("handleRecordingStop", () => {
|
|
|
287
270
|
});
|
|
288
271
|
|
|
289
272
|
test("sends recording_stop for an active recording", () => {
|
|
290
|
-
const
|
|
273
|
+
const sent = createSent();
|
|
291
274
|
const conversationId = "conv-stop-1";
|
|
292
275
|
|
|
293
276
|
// Start a recording first
|
|
294
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
277
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
295
278
|
expect(recordingId).not.toBeNull();
|
|
296
279
|
sent.length = 0; // Clear the start message
|
|
297
280
|
|
|
298
|
-
const result = handleRecordingStop(conversationId
|
|
281
|
+
const result = handleRecordingStop(conversationId);
|
|
299
282
|
|
|
300
283
|
expect(result).toBe(recordingId!);
|
|
301
284
|
expect(sent).toHaveLength(1);
|
|
@@ -304,27 +287,27 @@ describe("handleRecordingStop", () => {
|
|
|
304
287
|
});
|
|
305
288
|
|
|
306
289
|
test("returns undefined when no active recording exists", () => {
|
|
307
|
-
|
|
290
|
+
createSent();
|
|
308
291
|
|
|
309
|
-
const result = handleRecordingStop("conv-no-recording"
|
|
292
|
+
const result = handleRecordingStop("conv-no-recording");
|
|
310
293
|
|
|
311
294
|
expect(result).toBeUndefined();
|
|
312
295
|
});
|
|
313
296
|
|
|
314
297
|
test("resolves to globally active recording from a different conversation", () => {
|
|
315
|
-
const
|
|
298
|
+
const sent = createSent();
|
|
316
299
|
const convA = "conv-owner";
|
|
317
300
|
const convB = "conv-stopper";
|
|
318
301
|
|
|
319
302
|
// Bind socket to conv-A (the owning conversation)
|
|
320
303
|
|
|
321
304
|
// Start a recording on conv-A
|
|
322
|
-
const recordingId = handleRecordingStart(convA, undefined
|
|
305
|
+
const recordingId = handleRecordingStart(convA, undefined);
|
|
323
306
|
expect(recordingId).not.toBeNull();
|
|
324
307
|
sent.length = 0;
|
|
325
308
|
|
|
326
309
|
// Stop from conv-B — should resolve to the globally active recording on conv-A
|
|
327
|
-
const result = handleRecordingStop(convB
|
|
310
|
+
const result = handleRecordingStop(convB);
|
|
328
311
|
|
|
329
312
|
expect(result).toBe(recordingId!);
|
|
330
313
|
expect(sent).toHaveLength(1);
|
|
@@ -333,13 +316,13 @@ describe("handleRecordingStop", () => {
|
|
|
333
316
|
});
|
|
334
317
|
|
|
335
318
|
test("returns recordingId when stopped via broadcast", () => {
|
|
336
|
-
|
|
319
|
+
createSent();
|
|
337
320
|
const conversationId = "conv-broadcast-stop";
|
|
338
321
|
|
|
339
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
322
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
340
323
|
expect(recordingId).not.toBeNull();
|
|
341
324
|
|
|
342
|
-
const result = handleRecordingStop(conversationId
|
|
325
|
+
const result = handleRecordingStop(conversationId);
|
|
343
326
|
|
|
344
327
|
// Broadcast-based stop always returns the recordingId
|
|
345
328
|
expect(result).toBe(recordingId!);
|
|
@@ -358,10 +341,10 @@ describe("handleRecordingStatusCore", () => {
|
|
|
358
341
|
});
|
|
359
342
|
|
|
360
343
|
test("handles started status without errors", async () => {
|
|
361
|
-
|
|
344
|
+
createSent();
|
|
362
345
|
const conversationId = "conv-status-1";
|
|
363
346
|
|
|
364
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
347
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
365
348
|
expect(recordingId).not.toBeNull();
|
|
366
349
|
|
|
367
350
|
const statusMsg: RecordingStatus = {
|
|
@@ -371,16 +354,16 @@ describe("handleRecordingStatusCore", () => {
|
|
|
371
354
|
};
|
|
372
355
|
|
|
373
356
|
// Should not throw
|
|
374
|
-
await handleRecordingStatusCore(statusMsg
|
|
357
|
+
await handleRecordingStatusCore(statusMsg);
|
|
375
358
|
});
|
|
376
359
|
|
|
377
360
|
test("handles stopped status with file — creates attachment and notifies client", async () => {
|
|
378
|
-
const
|
|
361
|
+
const sent = createSent();
|
|
379
362
|
const conversationId = "conv-status-stopped";
|
|
380
363
|
|
|
381
364
|
// Bind socket
|
|
382
365
|
|
|
383
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
366
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
384
367
|
expect(recordingId).not.toBeNull();
|
|
385
368
|
sent.length = 0;
|
|
386
369
|
|
|
@@ -399,7 +382,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
399
382
|
durationMs: 5000,
|
|
400
383
|
};
|
|
401
384
|
|
|
402
|
-
await handleRecordingStatusCore(statusMsg
|
|
385
|
+
await handleRecordingStatusCore(statusMsg);
|
|
403
386
|
|
|
404
387
|
// Should have sent assistant_text_delta and message_complete
|
|
405
388
|
const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
|
|
@@ -424,10 +407,10 @@ describe("handleRecordingStatusCore", () => {
|
|
|
424
407
|
});
|
|
425
408
|
|
|
426
409
|
test("handles stopped status and creates assistant message when none exists", async () => {
|
|
427
|
-
const
|
|
410
|
+
const sent = createSent();
|
|
428
411
|
const conversationId = "conv-status-no-msg";
|
|
429
412
|
|
|
430
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
413
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
431
414
|
expect(recordingId).not.toBeNull();
|
|
432
415
|
sent.length = 0;
|
|
433
416
|
|
|
@@ -441,7 +424,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
441
424
|
durationMs: 3000,
|
|
442
425
|
};
|
|
443
426
|
|
|
444
|
-
await handleRecordingStatusCore(statusMsg
|
|
427
|
+
await handleRecordingStatusCore(statusMsg);
|
|
445
428
|
|
|
446
429
|
// An assistant message should have been created via addMessage mock
|
|
447
430
|
expect(mockMessages.length).toBeGreaterThanOrEqual(1);
|
|
@@ -450,12 +433,12 @@ describe("handleRecordingStatusCore", () => {
|
|
|
450
433
|
});
|
|
451
434
|
|
|
452
435
|
test("handles stopped status when file does not exist — notifies client", async () => {
|
|
453
|
-
const
|
|
436
|
+
const sent = createSent();
|
|
454
437
|
const conversationId = "conv-status-no-file";
|
|
455
438
|
|
|
456
439
|
mockFileExists = false;
|
|
457
440
|
|
|
458
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
441
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
459
442
|
expect(recordingId).not.toBeNull();
|
|
460
443
|
sent.length = 0;
|
|
461
444
|
|
|
@@ -468,7 +451,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
468
451
|
};
|
|
469
452
|
|
|
470
453
|
// Should not throw — the handler logs the error and notifies the client
|
|
471
|
-
await handleRecordingStatusCore(statusMsg
|
|
454
|
+
await handleRecordingStatusCore(statusMsg);
|
|
472
455
|
|
|
473
456
|
// No attachment should have been created
|
|
474
457
|
expect(mockAttachments.length).toBe(0);
|
|
@@ -484,13 +467,13 @@ describe("handleRecordingStatusCore", () => {
|
|
|
484
467
|
});
|
|
485
468
|
|
|
486
469
|
test("handles stopped status with zero-length file — treated as failure", async () => {
|
|
487
|
-
const
|
|
470
|
+
const sent = createSent();
|
|
488
471
|
const conversationId = "conv-status-zero-file";
|
|
489
472
|
|
|
490
473
|
mockFileExists = true;
|
|
491
474
|
mockFileSize = 0;
|
|
492
475
|
|
|
493
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
476
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
494
477
|
expect(recordingId).not.toBeNull();
|
|
495
478
|
sent.length = 0;
|
|
496
479
|
|
|
@@ -502,7 +485,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
502
485
|
durationMs: 2000,
|
|
503
486
|
};
|
|
504
487
|
|
|
505
|
-
await handleRecordingStatusCore(statusMsg
|
|
488
|
+
await handleRecordingStatusCore(statusMsg);
|
|
506
489
|
|
|
507
490
|
// No attachment should have been created for a zero-length file
|
|
508
491
|
expect(mockAttachments.length).toBe(0);
|
|
@@ -525,13 +508,13 @@ describe("handleRecordingStatusCore", () => {
|
|
|
525
508
|
});
|
|
526
509
|
|
|
527
510
|
test("successful finalization — attachment created and success message sent", async () => {
|
|
528
|
-
const
|
|
511
|
+
const sent = createSent();
|
|
529
512
|
const conversationId = "conv-status-success";
|
|
530
513
|
|
|
531
514
|
mockFileExists = true;
|
|
532
515
|
mockFileSize = 4096;
|
|
533
516
|
|
|
534
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
517
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
535
518
|
expect(recordingId).not.toBeNull();
|
|
536
519
|
sent.length = 0;
|
|
537
520
|
|
|
@@ -543,7 +526,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
543
526
|
durationMs: 5000,
|
|
544
527
|
};
|
|
545
528
|
|
|
546
|
-
await handleRecordingStatusCore(statusMsg
|
|
529
|
+
await handleRecordingStatusCore(statusMsg);
|
|
547
530
|
|
|
548
531
|
// Attachment should have been created
|
|
549
532
|
expect(mockAttachments.length).toBe(1);
|
|
@@ -562,13 +545,13 @@ describe("handleRecordingStatusCore", () => {
|
|
|
562
545
|
});
|
|
563
546
|
|
|
564
547
|
test("rejects file path outside allowed directory", async () => {
|
|
565
|
-
const
|
|
548
|
+
const sent = createSent();
|
|
566
549
|
const conversationId = "conv-status-outside-dir";
|
|
567
550
|
|
|
568
551
|
mockFileExists = true;
|
|
569
552
|
mockFileSize = 4096;
|
|
570
553
|
|
|
571
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
554
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
572
555
|
expect(recordingId).not.toBeNull();
|
|
573
556
|
sent.length = 0;
|
|
574
557
|
|
|
@@ -580,7 +563,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
580
563
|
durationMs: 5000,
|
|
581
564
|
};
|
|
582
565
|
|
|
583
|
-
await handleRecordingStatusCore(statusMsg
|
|
566
|
+
await handleRecordingStatusCore(statusMsg);
|
|
584
567
|
|
|
585
568
|
// No attachment should have been created — path is outside allowlist
|
|
586
569
|
expect(mockAttachments.length).toBe(0);
|
|
@@ -598,10 +581,10 @@ describe("handleRecordingStatusCore", () => {
|
|
|
598
581
|
});
|
|
599
582
|
|
|
600
583
|
test("failed finalization — failure status sent and no success message", async () => {
|
|
601
|
-
const
|
|
584
|
+
const sent = createSent();
|
|
602
585
|
const conversationId = "conv-status-fail-final";
|
|
603
586
|
|
|
604
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
587
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
605
588
|
expect(recordingId).not.toBeNull();
|
|
606
589
|
sent.length = 0;
|
|
607
590
|
|
|
@@ -613,7 +596,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
613
596
|
error: "Video writer finished with non-completed status 3",
|
|
614
597
|
};
|
|
615
598
|
|
|
616
|
-
await handleRecordingStatusCore(statusMsg
|
|
599
|
+
await handleRecordingStatusCore(statusMsg);
|
|
617
600
|
|
|
618
601
|
// No attachment should have been created
|
|
619
602
|
expect(mockAttachments.length).toBe(0);
|
|
@@ -632,10 +615,10 @@ describe("handleRecordingStatusCore", () => {
|
|
|
632
615
|
});
|
|
633
616
|
|
|
634
617
|
test("handles failed status and notifies client", async () => {
|
|
635
|
-
const
|
|
618
|
+
const sent = createSent();
|
|
636
619
|
const conversationId = "conv-status-failed";
|
|
637
620
|
|
|
638
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
621
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
639
622
|
expect(recordingId).not.toBeNull();
|
|
640
623
|
sent.length = 0;
|
|
641
624
|
|
|
@@ -646,7 +629,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
646
629
|
error: "Permission denied",
|
|
647
630
|
};
|
|
648
631
|
|
|
649
|
-
await handleRecordingStatusCore(statusMsg
|
|
632
|
+
await handleRecordingStatusCore(statusMsg);
|
|
650
633
|
|
|
651
634
|
// Should send error notification
|
|
652
635
|
const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
|
|
@@ -659,10 +642,10 @@ describe("handleRecordingStatusCore", () => {
|
|
|
659
642
|
});
|
|
660
643
|
|
|
661
644
|
test("handles failed status with no error message", async () => {
|
|
662
|
-
const
|
|
645
|
+
const sent = createSent();
|
|
663
646
|
const conversationId = "conv-status-failed-no-err";
|
|
664
647
|
|
|
665
|
-
const recordingId = handleRecordingStart(conversationId, undefined
|
|
648
|
+
const recordingId = handleRecordingStart(conversationId, undefined);
|
|
666
649
|
expect(recordingId).not.toBeNull();
|
|
667
650
|
sent.length = 0;
|
|
668
651
|
|
|
@@ -672,7 +655,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
672
655
|
status: "failed",
|
|
673
656
|
};
|
|
674
657
|
|
|
675
|
-
await handleRecordingStatusCore(statusMsg
|
|
658
|
+
await handleRecordingStatusCore(statusMsg);
|
|
676
659
|
|
|
677
660
|
const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
|
|
678
661
|
expect(textDeltas.length).toBeGreaterThanOrEqual(1);
|
|
@@ -680,7 +663,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
680
663
|
});
|
|
681
664
|
|
|
682
665
|
test("handles status with attachToConversationId fallback", async () => {
|
|
683
|
-
const
|
|
666
|
+
const sent = createSent();
|
|
684
667
|
const conversationId = "conv-fallback";
|
|
685
668
|
|
|
686
669
|
// Send a recording_status directly with attachToConversationId
|
|
@@ -694,7 +677,7 @@ describe("handleRecordingStatusCore", () => {
|
|
|
694
677
|
};
|
|
695
678
|
|
|
696
679
|
// Should not throw — uses attachToConversationId as fallback
|
|
697
|
-
await handleRecordingStatusCore(statusMsg
|
|
680
|
+
await handleRecordingStatusCore(statusMsg);
|
|
698
681
|
|
|
699
682
|
const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
|
|
700
683
|
expect(textDeltas.length).toBeGreaterThanOrEqual(1);
|
|
@@ -117,6 +117,7 @@ function buildContext(
|
|
|
117
117
|
traceEvents.push({ event, body, options });
|
|
118
118
|
},
|
|
119
119
|
} as unknown as HistoryConversationContext["traceEmitter"],
|
|
120
|
+
sendToClient: () => {},
|
|
120
121
|
messages,
|
|
121
122
|
processing: false,
|
|
122
123
|
abortController: null,
|
|
@@ -139,7 +140,7 @@ describe("regenerate fire-and-forget error path", () => {
|
|
|
139
140
|
},
|
|
140
141
|
});
|
|
141
142
|
|
|
142
|
-
await regenerate(session,
|
|
143
|
+
await regenerate(session, "req-123");
|
|
143
144
|
|
|
144
145
|
// Give the fire-and-forget .catch() a tick to run.
|
|
145
146
|
await new Promise((resolve) => setImmediate(resolve));
|
|
@@ -167,7 +168,7 @@ describe("regenerate fire-and-forget error path", () => {
|
|
|
167
168
|
},
|
|
168
169
|
});
|
|
169
170
|
|
|
170
|
-
await regenerate(session
|
|
171
|
+
await regenerate(session);
|
|
171
172
|
|
|
172
173
|
await new Promise((resolve) => setImmediate(resolve));
|
|
173
174
|
|
|
@@ -185,7 +186,7 @@ describe("regenerate fire-and-forget error path", () => {
|
|
|
185
186
|
runAgentLoop: async () => {},
|
|
186
187
|
});
|
|
187
188
|
|
|
188
|
-
await regenerate(session,
|
|
189
|
+
await regenerate(session, "req-ok");
|
|
189
190
|
|
|
190
191
|
await new Promise((resolve) => setImmediate(resolve));
|
|
191
192
|
|
|
@@ -215,10 +215,7 @@ import {
|
|
|
215
215
|
} from "../calls/relay-server.js";
|
|
216
216
|
import { setVoiceBridgeDeps } from "../calls/voice-session-bridge.js";
|
|
217
217
|
import { upsertContact } from "../contacts/contact-store.js";
|
|
218
|
-
import {
|
|
219
|
-
createGuardianBinding,
|
|
220
|
-
upsertContactChannel,
|
|
221
|
-
} from "../contacts/contacts-write.js";
|
|
218
|
+
import { upsertContactChannel } from "../contacts/contacts-write.js";
|
|
222
219
|
import {
|
|
223
220
|
listCanonicalGuardianRequests,
|
|
224
221
|
resolveCanonicalGuardianRequest,
|
|
@@ -238,6 +235,7 @@ import {
|
|
|
238
235
|
getGuardianBinding,
|
|
239
236
|
} from "../runtime/channel-verification-service.js";
|
|
240
237
|
import { generateVoiceCode, hashVoiceCode } from "../util/voice-code.js";
|
|
238
|
+
import { createGuardianBinding } from "./helpers/create-guardian-binding.js";
|
|
241
239
|
|
|
242
240
|
initializeDb();
|
|
243
241
|
|
|
@@ -1419,9 +1417,11 @@ describe("relay-server", () => {
|
|
|
1419
1417
|
expect(relay.isVerificationSessionActive()).toBe(false);
|
|
1420
1418
|
expect(relay.getConnectionState()).toBe("connected");
|
|
1421
1419
|
|
|
1422
|
-
// Guardian binding
|
|
1420
|
+
// Guardian binding is NOT created by the assistant — the gateway owns
|
|
1421
|
+
// binding creation for inbound voice verification. The assistant only
|
|
1422
|
+
// transitions to connected state and starts the normal call flow.
|
|
1423
1423
|
const binding = getGuardianBinding("self", "phone");
|
|
1424
|
-
expect(binding).
|
|
1424
|
+
expect(binding).toBeNull();
|
|
1425
1425
|
|
|
1426
1426
|
// Orchestrator greeting should have fired
|
|
1427
1427
|
const textMessages = ws.sentMessages
|
|
@@ -1490,9 +1490,9 @@ describe("relay-server", () => {
|
|
|
1490
1490
|
expect(relay.isVerificationSessionActive()).toBe(false);
|
|
1491
1491
|
expect(relay.getConnectionState()).toBe("connected");
|
|
1492
1492
|
|
|
1493
|
-
// Binding created
|
|
1493
|
+
// Binding is NOT created by the assistant — gateway owns this.
|
|
1494
1494
|
const binding = getGuardianBinding("self", "phone");
|
|
1495
|
-
expect(binding).
|
|
1495
|
+
expect(binding).toBeNull();
|
|
1496
1496
|
|
|
1497
1497
|
// Greeting should have started
|
|
1498
1498
|
const textMessages = ws.sentMessages
|
|
@@ -1746,18 +1746,23 @@ describe("relay-server", () => {
|
|
|
1746
1746
|
|
|
1747
1747
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1748
1748
|
|
|
1749
|
+
// The gateway creates the guardian binding before the ConversationRelay
|
|
1750
|
+
// WebSocket is established, so resolveActorTrust() would find it in
|
|
1751
|
+
// production. Without a gateway in this test, trust reflects the
|
|
1752
|
+
// resolved state without a binding.
|
|
1749
1753
|
const postVerify = (
|
|
1750
1754
|
relay.getController() as unknown as {
|
|
1751
1755
|
trustContext?: {
|
|
1752
1756
|
sourceChannel?: string;
|
|
1753
1757
|
trustClass?: string;
|
|
1754
|
-
guardianExternalUserId?: string;
|
|
1755
1758
|
};
|
|
1756
1759
|
}
|
|
1757
1760
|
)?.trustContext;
|
|
1758
1761
|
expect(postVerify?.sourceChannel).toBe("phone");
|
|
1759
|
-
|
|
1760
|
-
|
|
1762
|
+
// Trust class is 'unknown' because the gateway creates the binding
|
|
1763
|
+
// before the relay is established. Without a gateway in this test,
|
|
1764
|
+
// resolveActorTrust finds no guardian binding.
|
|
1765
|
+
expect(postVerify?.trustClass).toBe("unknown");
|
|
1761
1766
|
|
|
1762
1767
|
relay.destroy();
|
|
1763
1768
|
});
|
|
@@ -4034,9 +4039,9 @@ describe("relay-server", () => {
|
|
|
4034
4039
|
expect(relay.isVerificationSessionActive()).toBe(false);
|
|
4035
4040
|
expect(relay.getConnectionState()).toBe("connected");
|
|
4036
4041
|
|
|
4037
|
-
// Guardian binding
|
|
4042
|
+
// Guardian binding is NOT created by the assistant — gateway owns this.
|
|
4038
4043
|
const binding = getGuardianBinding("self", "phone");
|
|
4039
|
-
expect(binding).
|
|
4044
|
+
expect(binding).toBeNull();
|
|
4040
4045
|
|
|
4041
4046
|
// Normal greeting should fire (from mockSendMessage), not the handoff copy
|
|
4042
4047
|
const textMessages = ws.sentMessages
|
|
@@ -54,8 +54,6 @@ const mockConfig = {
|
|
|
54
54
|
rateLimit: { maxRequestsPerMinute: 0 },
|
|
55
55
|
secretDetection: {
|
|
56
56
|
enabled: false,
|
|
57
|
-
action: "warn" as const,
|
|
58
|
-
entropyThreshold: 4.0,
|
|
59
57
|
},
|
|
60
58
|
};
|
|
61
59
|
|
|
@@ -136,10 +134,6 @@ mock.module("../tools/shared/filesystem/path-policy.js", () => ({
|
|
|
136
134
|
hostPolicy: () => ({ ok: false }),
|
|
137
135
|
}));
|
|
138
136
|
|
|
139
|
-
mock.module("../tools/terminal/sandbox.js", () => ({
|
|
140
|
-
wrapCommand: () => ({ command: "", sandboxed: false }),
|
|
141
|
-
}));
|
|
142
|
-
|
|
143
137
|
import { PermissionPrompter } from "../permissions/prompter.js";
|
|
144
138
|
import { ToolExecutor } from "../tools/executor.js";
|
|
145
139
|
import type { ToolContext as TC } from "../tools/types.js";
|
|
@@ -231,7 +225,11 @@ describe("requireFreshApproval: non-interactive guardian denial", () => {
|
|
|
231
225
|
const result = await executor.execute(
|
|
232
226
|
"bash",
|
|
233
227
|
{ command: "echo hello" },
|
|
234
|
-
makeContext({
|
|
228
|
+
makeContext({
|
|
229
|
+
isInteractive: false,
|
|
230
|
+
trustClass: "guardian",
|
|
231
|
+
requireFreshApproval: true,
|
|
232
|
+
}),
|
|
235
233
|
);
|
|
236
234
|
|
|
237
235
|
expect(result.isError).toBe(true);
|
|
@@ -283,7 +281,11 @@ describe("requireFreshApproval: non-interactive guardian denial", () => {
|
|
|
283
281
|
const result = await executor.execute(
|
|
284
282
|
"gmail_send_draft",
|
|
285
283
|
{ draft_id: "draft-123", confidence: 0.99 },
|
|
286
|
-
makeContext({
|
|
284
|
+
makeContext({
|
|
285
|
+
isInteractive: false,
|
|
286
|
+
trustClass: "guardian",
|
|
287
|
+
requireFreshApproval: true,
|
|
288
|
+
}),
|
|
287
289
|
);
|
|
288
290
|
|
|
289
291
|
expect(result.isError).toBe(true);
|
|
@@ -318,12 +320,9 @@ describe("requireFreshApproval: persistent decisions disabled", () => {
|
|
|
318
320
|
checkResultOverride = undefined;
|
|
319
321
|
scopeOptionsOverride = undefined;
|
|
320
322
|
riskOverride = "high";
|
|
321
|
-
|
|
322
323
|
});
|
|
323
324
|
|
|
324
|
-
afterEach(() => {
|
|
325
|
-
|
|
326
|
-
});
|
|
325
|
+
afterEach(() => {});
|
|
327
326
|
|
|
328
327
|
test("manage_secure_command_tool prompt does not offer persistent decisions", async () => {
|
|
329
328
|
checkResultOverride = { decision: "allow", reason: "Matched trust rule" };
|
|
@@ -372,8 +371,6 @@ describe("requireFreshApproval: persistent decisions disabled", () => {
|
|
|
372
371
|
expect(promptEvent).toBeDefined();
|
|
373
372
|
expect(promptEvent!.persistentDecisionsAllowed).toBe(false);
|
|
374
373
|
});
|
|
375
|
-
|
|
376
|
-
|
|
377
374
|
});
|
|
378
375
|
|
|
379
376
|
// ---------------------------------------------------------------------------
|
|
@@ -386,12 +383,9 @@ describe("requireFreshApproval: grant-consumed does not skip permission check",
|
|
|
386
383
|
checkResultOverride = undefined;
|
|
387
384
|
scopeOptionsOverride = undefined;
|
|
388
385
|
riskOverride = "high";
|
|
389
|
-
|
|
390
386
|
});
|
|
391
387
|
|
|
392
|
-
afterEach(() => {
|
|
393
|
-
|
|
394
|
-
});
|
|
388
|
+
afterEach(() => {});
|
|
395
389
|
|
|
396
390
|
test("manage_secure_command_tool is prompted even when executor sets requireFreshApproval and grantConsumed would normally short-circuit", async () => {
|
|
397
391
|
// This test verifies the code path in executor.ts where the
|
|
@@ -441,12 +435,9 @@ describe("requireFreshApproval: context flag propagation", () => {
|
|
|
441
435
|
checkResultOverride = undefined;
|
|
442
436
|
scopeOptionsOverride = undefined;
|
|
443
437
|
riskOverride = "high";
|
|
444
|
-
|
|
445
438
|
});
|
|
446
439
|
|
|
447
|
-
afterEach(() => {
|
|
448
|
-
|
|
449
|
-
});
|
|
440
|
+
afterEach(() => {});
|
|
450
441
|
|
|
451
442
|
test("manage_secure_command_tool sets both forcePromptSideEffects and requireFreshApproval", async () => {
|
|
452
443
|
checkResultOverride = { decision: "allow", reason: "Matched trust rule" };
|
|
@@ -34,9 +34,9 @@ mock.module("../config/loader.js", () => ({
|
|
|
34
34
|
mock.module("../daemon/process-message.js", () => ({
|
|
35
35
|
resolveTurnChannel: () => "whatsapp",
|
|
36
36
|
resolveTurnInterface: () => "whatsapp",
|
|
37
|
-
makePendingInteractionRegistrar: () => () => {},
|
|
38
37
|
prepareConversationForMessage: async () => ({}),
|
|
39
38
|
processMessage: async () => ({ messageId: `mock-msg-${Date.now()}` }),
|
|
39
|
+
processMessageInBackground: async () => ({ messageId: "mock-bg" }),
|
|
40
40
|
}));
|
|
41
41
|
|
|
42
42
|
mock.module("../daemon/approval-generators.js", () => ({
|
|
@@ -72,7 +72,7 @@ async function publishAndReadFrame(
|
|
|
72
72
|
abortSignal: ac.signal,
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
const event = buildAssistantEvent(
|
|
75
|
+
const event = buildAssistantEvent(message, conversationId);
|
|
76
76
|
await assistantEventHub.publish(event);
|
|
77
77
|
|
|
78
78
|
const reader = stream.getReader();
|
|
@@ -322,7 +322,7 @@ describe("SSE HTTP parity — streaming/delta message types", () => {
|
|
|
322
322
|
|
|
323
323
|
// ── Envelope integrity ───────────────────────────────────────────────────
|
|
324
324
|
|
|
325
|
-
test("SSE envelope preserves
|
|
325
|
+
test("SSE envelope preserves conversationId across all event types", async () => {
|
|
326
326
|
const conversationKey = "parity-envelope-check";
|
|
327
327
|
const { conversationId } = getOrCreateConversation(conversationKey);
|
|
328
328
|
|
|
@@ -338,7 +338,7 @@ describe("SSE HTTP parity — streaming/delta message types", () => {
|
|
|
338
338
|
type: "assistant_text_delta" as const,
|
|
339
339
|
text: "envelope test",
|
|
340
340
|
};
|
|
341
|
-
const published = buildAssistantEvent(
|
|
341
|
+
const published = buildAssistantEvent(msg, conversationId);
|
|
342
342
|
await assistantEventHub.publish(published);
|
|
343
343
|
|
|
344
344
|
const reader = stream.getReader();
|
|
@@ -358,7 +358,6 @@ describe("SSE HTTP parity — streaming/delta message types", () => {
|
|
|
358
358
|
|
|
359
359
|
// Envelope fields
|
|
360
360
|
expect(received.id).toBe(published.id);
|
|
361
|
-
expect(received.assistantId).toBe("self");
|
|
362
361
|
expect(received.conversationId).toBe(conversationId);
|
|
363
362
|
expect(received.emittedAt).toBe(published.emittedAt);
|
|
364
363
|
// SSE frame fields
|