@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
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* HTTP route definitions.
|
|
5
5
|
*
|
|
6
6
|
* Pipeline:
|
|
7
|
-
* 1. Programmatically import
|
|
8
|
-
*
|
|
9
|
-
* 2. Combine with
|
|
10
|
-
* pre-auth / non-v1 routes.
|
|
7
|
+
* 1. Programmatically import every route module under src/runtime/routes/
|
|
8
|
+
* and collect all exported ROUTES arrays — no regex, no source-text parsing.
|
|
9
|
+
* 2. Combine with pre-auth / non-v1 routes.
|
|
11
10
|
* 3. Convert to OpenAPI path items.
|
|
12
11
|
* 4. Write to openapi.yaml.
|
|
13
12
|
*
|
|
@@ -132,40 +131,12 @@ function toJSONSchemaObject(schema: unknown): JSONSchemaObject {
|
|
|
132
131
|
// ---------------------------------------------------------------------------
|
|
133
132
|
|
|
134
133
|
/**
|
|
135
|
-
*
|
|
134
|
+
* Dynamically import every route module under `src/runtime/routes/`
|
|
135
|
+
* and collect all exported `ROUTES` arrays.
|
|
136
136
|
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* properties are read or the value is called as a function.
|
|
141
|
-
*/
|
|
142
|
-
function createDeepStub(): unknown {
|
|
143
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
-
const stub: any = new Proxy(function () {}, {
|
|
145
|
-
get(_target, prop) {
|
|
146
|
-
// Prevent the stub from being treated as a Promise (await-able).
|
|
147
|
-
if (prop === "then") return undefined;
|
|
148
|
-
// Prevent infinite iteration.
|
|
149
|
-
if (prop === Symbol.iterator) return undefined;
|
|
150
|
-
// String coercion.
|
|
151
|
-
if (prop === Symbol.toPrimitive) return () => "";
|
|
152
|
-
return createDeepStub();
|
|
153
|
-
},
|
|
154
|
-
apply() {
|
|
155
|
-
return createDeepStub();
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
return stub;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Dynamically import every route module under `src/runtime/routes/`,
|
|
163
|
-
* find all exported functions whose names end with `RouteDefinitions`,
|
|
164
|
-
* invoke each with a deep stub as its first argument, and collect the
|
|
165
|
-
* `{ endpoint, method }` pairs from the returned arrays.
|
|
166
|
-
*
|
|
167
|
-
* This replaces the previous regex + balanced-brace scanning approach
|
|
168
|
-
* and automatically picks up new route modules without manual updates.
|
|
137
|
+
* Each route module is expected to export a `ROUTES: RouteDefinition[]`
|
|
138
|
+
* constant. The function automatically picks up new route modules
|
|
139
|
+
* without manual updates.
|
|
169
140
|
*/
|
|
170
141
|
async function collectRoutesFromModules(): Promise<RouteEntry[]> {
|
|
171
142
|
const routes: RouteEntry[] = [];
|
|
@@ -191,41 +162,13 @@ async function collectRoutesFromModules(): Promise<RouteEntry[]> {
|
|
|
191
162
|
continue;
|
|
192
163
|
}
|
|
193
164
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (result.success) routes.push(result.data);
|
|
202
|
-
}
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (
|
|
207
|
-
!exportName.endsWith("RouteDefinitions") ||
|
|
208
|
-
typeof exportValue !== "function"
|
|
209
|
-
) {
|
|
210
|
-
continue;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
try {
|
|
214
|
-
const rawDefs = exportValue(createDeepStub());
|
|
215
|
-
if (!Array.isArray(rawDefs)) continue;
|
|
216
|
-
for (const raw of rawDefs) {
|
|
217
|
-
const result = RouteEntrySchema.safeParse({
|
|
218
|
-
...(typeof raw === "object" && raw !== null ? raw : {}),
|
|
219
|
-
sourceModule: file,
|
|
220
|
-
});
|
|
221
|
-
if (result.success) {
|
|
222
|
-
routes.push(result.data);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
} catch (err) {
|
|
226
|
-
console.warn(
|
|
227
|
-
`Warning: ${exportName}() in ${file} threw: ${err instanceof Error ? err.message : err}`,
|
|
228
|
-
);
|
|
165
|
+
if ("ROUTES" in mod && Array.isArray(mod.ROUTES)) {
|
|
166
|
+
for (const raw of mod.ROUTES) {
|
|
167
|
+
const result = RouteEntrySchema.safeParse({
|
|
168
|
+
...(typeof raw === "object" && raw !== null ? raw : {}),
|
|
169
|
+
sourceModule: file,
|
|
170
|
+
});
|
|
171
|
+
if (result.success) routes.push(result.data);
|
|
229
172
|
}
|
|
230
173
|
}
|
|
231
174
|
}
|
|
@@ -233,40 +176,6 @@ async function collectRoutesFromModules(): Promise<RouteEntry[]> {
|
|
|
233
176
|
return routes;
|
|
234
177
|
}
|
|
235
178
|
|
|
236
|
-
/**
|
|
237
|
-
* Routes defined inline in RuntimeHttpServer.buildRouteTable() that are
|
|
238
|
-
* not exported from any route module. These are kept here because they
|
|
239
|
-
* depend on cross-cutting concerns specific to the RuntimeHttpServer
|
|
240
|
-
* instance (see B2 in the improvement plan for the recommendation to
|
|
241
|
-
* extract these into modules).
|
|
242
|
-
*
|
|
243
|
-
* Whenever buildRouteTable() gains or loses an inline route, this list
|
|
244
|
-
* must be updated manually. Note: `--check` only compares the generated
|
|
245
|
-
* YAML against the committed YAML, so it will NOT catch a missing entry
|
|
246
|
-
* here if openapi.yaml is also stale. Plan items B2/C2 address this gap.
|
|
247
|
-
*/
|
|
248
|
-
const INLINE_ROUTES: RouteEntry[] = [
|
|
249
|
-
{ endpoint: "conversations", method: "GET" },
|
|
250
|
-
{ endpoint: "conversations/seen", method: "POST" },
|
|
251
|
-
{ endpoint: "conversations/unread", method: "POST" },
|
|
252
|
-
{ endpoint: "conversations/:id", method: "GET" },
|
|
253
|
-
{ endpoint: "interfaces/:path*", method: "GET" },
|
|
254
|
-
{ endpoint: "internal/twilio/voice-webhook", method: "POST" },
|
|
255
|
-
{ endpoint: "internal/twilio/status", method: "POST" },
|
|
256
|
-
{ endpoint: "internal/twilio/connect-action", method: "POST" },
|
|
257
|
-
{ endpoint: "internal/oauth/callback", method: "POST" },
|
|
258
|
-
];
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Pre-auth routes handled directly in routeRequest() before the router.
|
|
262
|
-
* These are a small, stable set that bypass JWT authentication and are
|
|
263
|
-
* not part of the declarative route table.
|
|
264
|
-
*/
|
|
265
|
-
const PRE_AUTH_ROUTES: RouteEntry[] = [
|
|
266
|
-
{ method: "POST", endpoint: "pairing/request" },
|
|
267
|
-
{ method: "GET", endpoint: "pairing/status" },
|
|
268
|
-
];
|
|
269
|
-
|
|
270
179
|
/**
|
|
271
180
|
* Top-level routes outside the /v1/ namespace.
|
|
272
181
|
* These are added to the spec separately.
|
|
@@ -551,11 +460,7 @@ async function main() {
|
|
|
551
460
|
const moduleRoutes = await collectRoutesFromModules();
|
|
552
461
|
|
|
553
462
|
// Combine all route sources
|
|
554
|
-
const allRoutes: RouteEntry[] =
|
|
555
|
-
...PRE_AUTH_ROUTES,
|
|
556
|
-
...INLINE_ROUTES,
|
|
557
|
-
...moduleRoutes,
|
|
558
|
-
];
|
|
463
|
+
const allRoutes: RouteEntry[] = moduleRoutes;
|
|
559
464
|
|
|
560
465
|
// Build the spec
|
|
561
466
|
const spec = buildSpec(allRoutes, version);
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
* asserts that:
|
|
21
21
|
* 1. The wake forwards `overrideProfile` to `agentLoop.run`.
|
|
22
22
|
* 2. The wake forwards `callSite: "mainAgent"` to `agentLoop.run`.
|
|
23
|
-
* 3.
|
|
23
|
+
* 3. The wake resolves and forwards the effective max input token budget.
|
|
24
|
+
* 4. With both routing keys set, `RetryProvider.normalizeSendMessageOptions` actually
|
|
24
25
|
* invokes the resolver and replaces workspace defaults with the
|
|
25
26
|
* pinned-profile values.
|
|
26
27
|
*/
|
|
@@ -69,6 +70,7 @@ interface RunArgs {
|
|
|
69
70
|
callSite: unknown;
|
|
70
71
|
turnContext: unknown;
|
|
71
72
|
overrideProfile: string | undefined;
|
|
73
|
+
effectiveMaxInputTokens: number | undefined;
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
function makeTarget(): {
|
|
@@ -93,6 +95,7 @@ function makeTarget(): {
|
|
|
93
95
|
callSite?: unknown,
|
|
94
96
|
turnContext?: unknown,
|
|
95
97
|
overrideProfile?: string,
|
|
98
|
+
effectiveMaxInputTokens?: number,
|
|
96
99
|
) => {
|
|
97
100
|
runArgs.push({
|
|
98
101
|
messages: [...messages],
|
|
@@ -102,6 +105,7 @@ function makeTarget(): {
|
|
|
102
105
|
callSite,
|
|
103
106
|
turnContext,
|
|
104
107
|
overrideProfile,
|
|
108
|
+
effectiveMaxInputTokens,
|
|
105
109
|
});
|
|
106
110
|
// Return the input verbatim → silent no-op (no assistant tail).
|
|
107
111
|
return messages;
|
|
@@ -133,6 +137,22 @@ afterEach(() => {
|
|
|
133
137
|
describe("wakeAgentForOpportunity — overrideProfile forwarding", () => {
|
|
134
138
|
test("forwards the conversation's pinned overrideProfile + mainAgent callSite to agentLoop.run", async () => {
|
|
135
139
|
mockOverrideProfile = "frontier";
|
|
140
|
+
mockLlmConfig = LLMSchema.parse({
|
|
141
|
+
default: {
|
|
142
|
+
provider: "anthropic",
|
|
143
|
+
model: "claude-sonnet-4-6",
|
|
144
|
+
maxTokens: 64000,
|
|
145
|
+
contextWindow: { maxInputTokens: 200000 },
|
|
146
|
+
},
|
|
147
|
+
profiles: {
|
|
148
|
+
frontier: {
|
|
149
|
+
contextWindow: { maxInputTokens: 150000 },
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
callSites: {
|
|
153
|
+
mainAgent: {},
|
|
154
|
+
},
|
|
155
|
+
}) as Record<string, unknown>;
|
|
136
156
|
const { target, runArgs } = makeTarget();
|
|
137
157
|
|
|
138
158
|
const result = await wakeAgentForOpportunity(
|
|
@@ -155,6 +175,7 @@ describe("wakeAgentForOpportunity — overrideProfile forwarding", () => {
|
|
|
155
175
|
// short-circuit and silently drop both the call-site config and the
|
|
156
176
|
// pinned override profile.
|
|
157
177
|
expect(runArgs[0]!.callSite).toBe("mainAgent");
|
|
178
|
+
expect(runArgs[0]!.effectiveMaxInputTokens).toBe(150000);
|
|
158
179
|
// Sanity: the wake-source tag still propagates as requestId.
|
|
159
180
|
expect(runArgs[0]!.requestId).toBe("wake:scheduler");
|
|
160
181
|
});
|
|
@@ -179,6 +200,7 @@ describe("wakeAgentForOpportunity — overrideProfile forwarding", () => {
|
|
|
179
200
|
// maxTokens, effort, etc.). Otherwise the wake silently runs under
|
|
180
201
|
// workspace defaults regardless of any per-call-site configuration.
|
|
181
202
|
expect(runArgs[0]!.callSite).toBe("mainAgent");
|
|
203
|
+
expect(runArgs[0]!.effectiveMaxInputTokens).toBeGreaterThan(0);
|
|
182
204
|
});
|
|
183
205
|
});
|
|
184
206
|
|
|
@@ -374,17 +374,53 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
|
|
|
374
374
|
}>;
|
|
375
375
|
|
|
376
376
|
const userMessages = sent.filter((m) => m.role === "user");
|
|
377
|
-
//
|
|
378
|
-
for (const
|
|
379
|
-
|
|
380
|
-
expect(block.cache_control).toBeUndefined();
|
|
381
|
-
}
|
|
377
|
+
// Oldest user message (Turn 1) has no cache_control
|
|
378
|
+
for (const block of userMessages[0].content) {
|
|
379
|
+
expect(block.cache_control).toBeUndefined();
|
|
382
380
|
}
|
|
381
|
+
// Previous-turn anchor (Turn 2) gets 1h cache on its last block to
|
|
382
|
+
// preserve the cached prefix across turn transitions
|
|
383
|
+
const prevTurn = userMessages[userMessages.length - 2];
|
|
384
|
+
const prevTurnLast = prevTurn.content[prevTurn.content.length - 1];
|
|
385
|
+
expect(prevTurnLast.cache_control).toEqual({
|
|
386
|
+
type: "ephemeral",
|
|
387
|
+
ttl: "1h",
|
|
388
|
+
});
|
|
389
|
+
// Current-turn anchor (Turn 3) gets 1h cache on its last block
|
|
383
390
|
const lastUser = userMessages[userMessages.length - 1];
|
|
384
391
|
const lastBlock = lastUser.content[lastUser.content.length - 1];
|
|
385
392
|
expect(lastBlock.cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
|
|
386
393
|
});
|
|
387
394
|
|
|
395
|
+
test("previous-turn anchor is NOT applied during a tool-use loop", async () => {
|
|
396
|
+
// When the request is mid tool-use (last msg is a tool_result), the
|
|
397
|
+
// turn-start anchor already covers the long prefix, so we must not
|
|
398
|
+
// place a second anchor on the prior turn — that would push us over
|
|
399
|
+
// the 4-breakpoint budget without adding cache value.
|
|
400
|
+
const messages: Message[] = [
|
|
401
|
+
userMsg("Turn 1"),
|
|
402
|
+
assistantMsg("Response 1"),
|
|
403
|
+
userMsg("Turn 2"),
|
|
404
|
+
toolUseMsg("tu_1", "bash"),
|
|
405
|
+
toolResultMsg("tu_1", "output"),
|
|
406
|
+
];
|
|
407
|
+
await provider.sendMessage(messages);
|
|
408
|
+
|
|
409
|
+
const sent = lastStreamParams!.messages as Array<{
|
|
410
|
+
role: string;
|
|
411
|
+
content: Array<{
|
|
412
|
+
type: string;
|
|
413
|
+
cache_control?: { type: string; ttl?: string };
|
|
414
|
+
}>;
|
|
415
|
+
}>;
|
|
416
|
+
// Turn 1 user message must have no cache_control (would be the
|
|
417
|
+
// prev-turn-anchor if we applied it, which we shouldn't here)
|
|
418
|
+
const turn1 = sent[0];
|
|
419
|
+
for (const block of turn1.content) {
|
|
420
|
+
expect(block.cache_control).toBeUndefined();
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
|
|
388
424
|
// -----------------------------------------------------------------------
|
|
389
425
|
// Negative: assistant messages never get cache_control
|
|
390
426
|
// -----------------------------------------------------------------------
|
|
@@ -1621,7 +1657,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
|
|
|
1621
1657
|
expect(sent[4].content[0].text).toBe("Follow-up question");
|
|
1622
1658
|
});
|
|
1623
1659
|
|
|
1624
|
-
test("multi-turn with workspace injection:
|
|
1660
|
+
test("multi-turn with workspace injection: prev-turn + last user message get 1h cache", async () => {
|
|
1625
1661
|
const messages: Message[] = [
|
|
1626
1662
|
{
|
|
1627
1663
|
role: "user",
|
|
@@ -1669,14 +1705,21 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
|
|
|
1669
1705
|
const userMsgs = sent.filter((m) => m.role === "user");
|
|
1670
1706
|
expect(userMsgs).toHaveLength(3);
|
|
1671
1707
|
|
|
1672
|
-
//
|
|
1673
|
-
for (const
|
|
1674
|
-
|
|
1675
|
-
expect(block.cache_control).toBeUndefined();
|
|
1676
|
-
}
|
|
1708
|
+
// Oldest user message (turn 1): no cache_control
|
|
1709
|
+
for (const block of userMsgs[0].content) {
|
|
1710
|
+
expect(block.cache_control).toBeUndefined();
|
|
1677
1711
|
}
|
|
1678
1712
|
|
|
1679
|
-
//
|
|
1713
|
+
// Previous-turn anchor (turn 2): 1h cache on last block to preserve the
|
|
1714
|
+
// cached prefix across turn transitions
|
|
1715
|
+
const prevTurn = userMsgs[userMsgs.length - 2];
|
|
1716
|
+
expect(prevTurn.content[0].cache_control).toBeUndefined();
|
|
1717
|
+
expect(prevTurn.content[1].cache_control).toEqual({
|
|
1718
|
+
type: "ephemeral",
|
|
1719
|
+
ttl: "1h",
|
|
1720
|
+
});
|
|
1721
|
+
|
|
1722
|
+
// Current-turn anchor (turn 3): 1h cache on last block
|
|
1680
1723
|
const lastUser = userMsgs[userMsgs.length - 1];
|
|
1681
1724
|
expect(lastUser.content[0].cache_control).toBeUndefined();
|
|
1682
1725
|
expect(lastUser.content[1].cache_control).toEqual({
|
|
@@ -2100,7 +2143,7 @@ describe("AnthropicProvider — Haiku Model Gating", () => {
|
|
|
2100
2143
|
expect(system[0].cache_control).not.toHaveProperty("ttl");
|
|
2101
2144
|
});
|
|
2102
2145
|
|
|
2103
|
-
test("betas array is empty for Haiku (no extended cache TTL
|
|
2146
|
+
test("betas array is empty for Haiku (no extended cache TTL)", async () => {
|
|
2104
2147
|
await provider.sendMessage([userMsg("Hi")], undefined, "You are helpful.");
|
|
2105
2148
|
|
|
2106
2149
|
// When betas is empty, the non-beta stream path is used, so no betas
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { existsSync, rmSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
5
|
+
|
|
6
|
+
mock.module("../util/logger.js", () => ({
|
|
7
|
+
getLogger: () =>
|
|
8
|
+
new Proxy({} as Record<string, unknown>, {
|
|
9
|
+
get: () => () => {},
|
|
10
|
+
}),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
addAppConversationId,
|
|
15
|
+
backfillAppConversationIds,
|
|
16
|
+
createApp,
|
|
17
|
+
getApp,
|
|
18
|
+
} from "../memory/app-store.js";
|
|
19
|
+
import { getDb } from "../memory/db-connection.js";
|
|
20
|
+
import { initializeDb } from "../memory/db-init.js";
|
|
21
|
+
import { rawRun } from "../memory/raw-query.js";
|
|
22
|
+
|
|
23
|
+
// Initialize db once for all tests
|
|
24
|
+
initializeDb();
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Helpers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
let testDataDir: string;
|
|
31
|
+
|
|
32
|
+
function freshTempDir(): string {
|
|
33
|
+
return join(
|
|
34
|
+
tmpdir(),
|
|
35
|
+
`vellum-app-backfill-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function makeAppParams(name: string) {
|
|
40
|
+
return {
|
|
41
|
+
name,
|
|
42
|
+
schemaJson: "{}",
|
|
43
|
+
htmlDefinition: "<h1>Hello</h1>",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Insert a message row with the given conversation_id and content JSON. */
|
|
48
|
+
function insertMessage(
|
|
49
|
+
conversationId: string,
|
|
50
|
+
content: unknown[],
|
|
51
|
+
role = "assistant",
|
|
52
|
+
): void {
|
|
53
|
+
const id = `msg-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
54
|
+
const contentStr = JSON.stringify(content);
|
|
55
|
+
rawRun(
|
|
56
|
+
`INSERT INTO messages (id, conversation_id, role, content, created_at) VALUES (?, ?, ?, ?, ?)`,
|
|
57
|
+
id,
|
|
58
|
+
conversationId,
|
|
59
|
+
role,
|
|
60
|
+
contentStr,
|
|
61
|
+
Date.now(),
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Insert a conversation row so FK constraints are satisfied. */
|
|
66
|
+
function insertConversation(id: string): void {
|
|
67
|
+
const now = Date.now();
|
|
68
|
+
rawRun(
|
|
69
|
+
`INSERT OR IGNORE INTO conversations (id, title, created_at, updated_at) VALUES (?, ?, ?, ?)`,
|
|
70
|
+
id,
|
|
71
|
+
"test",
|
|
72
|
+
now,
|
|
73
|
+
now,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Setup / teardown
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
beforeEach(() => {
|
|
82
|
+
// Clean database tables between tests
|
|
83
|
+
const db = getDb();
|
|
84
|
+
db.run(`DELETE FROM messages`);
|
|
85
|
+
db.run(`DELETE FROM conversations`);
|
|
86
|
+
|
|
87
|
+
// Fresh temp dir for app-store filesystem operations
|
|
88
|
+
testDataDir = freshTempDir();
|
|
89
|
+
process.env.VELLUM_WORKSPACE_DIR = testDataDir;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
afterEach(() => {
|
|
93
|
+
if (existsSync(testDataDir)) {
|
|
94
|
+
rmSync(testDataDir, { recursive: true, force: true });
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// backfillAppConversationIds
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
describe("backfillAppConversationIds", () => {
|
|
103
|
+
test("populates conversationIds from ui_surface blocks in messages", () => {
|
|
104
|
+
const app = createApp(makeAppParams("My App"));
|
|
105
|
+
const convId = "conv-backfill-1";
|
|
106
|
+
insertConversation(convId);
|
|
107
|
+
|
|
108
|
+
// Insert a message with a ui_surface block referencing the app
|
|
109
|
+
insertMessage(convId, [
|
|
110
|
+
{ type: "text", text: "Here is your app" },
|
|
111
|
+
{
|
|
112
|
+
type: "ui_surface",
|
|
113
|
+
surfaceType: "dynamic_page",
|
|
114
|
+
data: { appId: app.id, html: "<h1>App</h1>" },
|
|
115
|
+
},
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
backfillAppConversationIds();
|
|
119
|
+
|
|
120
|
+
const loaded = getApp(app.id);
|
|
121
|
+
expect(loaded?.conversationIds).toEqual([convId]);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("handles multiple apps and conversations", () => {
|
|
125
|
+
const app1 = createApp(makeAppParams("App One"));
|
|
126
|
+
const app2 = createApp(makeAppParams("App Two"));
|
|
127
|
+
const conv1 = "conv-multi-1";
|
|
128
|
+
const conv2 = "conv-multi-2";
|
|
129
|
+
insertConversation(conv1);
|
|
130
|
+
insertConversation(conv2);
|
|
131
|
+
|
|
132
|
+
// app1 referenced in conv1 and conv2
|
|
133
|
+
insertMessage(conv1, [
|
|
134
|
+
{
|
|
135
|
+
type: "ui_surface",
|
|
136
|
+
surfaceType: "dynamic_page",
|
|
137
|
+
data: { appId: app1.id, html: "<h1>A1</h1>" },
|
|
138
|
+
},
|
|
139
|
+
]);
|
|
140
|
+
insertMessage(conv2, [
|
|
141
|
+
{
|
|
142
|
+
type: "ui_surface",
|
|
143
|
+
surfaceType: "dynamic_page",
|
|
144
|
+
data: { appId: app1.id, html: "<h1>A1</h1>" },
|
|
145
|
+
},
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
// app2 referenced only in conv2
|
|
149
|
+
insertMessage(conv2, [
|
|
150
|
+
{
|
|
151
|
+
type: "ui_surface",
|
|
152
|
+
surfaceType: "dynamic_page",
|
|
153
|
+
data: { appId: app2.id, html: "<h1>A2</h1>" },
|
|
154
|
+
},
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
backfillAppConversationIds();
|
|
158
|
+
|
|
159
|
+
const loaded1 = getApp(app1.id);
|
|
160
|
+
expect(loaded1?.conversationIds?.sort()).toEqual([conv1, conv2].sort());
|
|
161
|
+
|
|
162
|
+
const loaded2 = getApp(app2.id);
|
|
163
|
+
expect(loaded2?.conversationIds).toEqual([conv2]);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("is idempotent — running twice does not duplicate associations", () => {
|
|
167
|
+
const app = createApp(makeAppParams("Idempotent App"));
|
|
168
|
+
const convId = "conv-idemp-1";
|
|
169
|
+
insertConversation(convId);
|
|
170
|
+
|
|
171
|
+
insertMessage(convId, [
|
|
172
|
+
{
|
|
173
|
+
type: "ui_surface",
|
|
174
|
+
surfaceType: "dynamic_page",
|
|
175
|
+
data: { appId: app.id, html: "<h1>App</h1>" },
|
|
176
|
+
},
|
|
177
|
+
]);
|
|
178
|
+
|
|
179
|
+
backfillAppConversationIds();
|
|
180
|
+
backfillAppConversationIds();
|
|
181
|
+
|
|
182
|
+
const loaded = getApp(app.id);
|
|
183
|
+
expect(loaded?.conversationIds).toEqual([convId]);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("apps with no message references remain unchanged", () => {
|
|
187
|
+
const app = createApp(makeAppParams("Untouched App"));
|
|
188
|
+
const convId = "conv-unrelated";
|
|
189
|
+
insertConversation(convId);
|
|
190
|
+
|
|
191
|
+
// Insert a message with no ui_surface blocks
|
|
192
|
+
insertMessage(convId, [{ type: "text", text: "Hello world" }]);
|
|
193
|
+
|
|
194
|
+
backfillAppConversationIds();
|
|
195
|
+
|
|
196
|
+
const loaded = getApp(app.id);
|
|
197
|
+
expect(loaded?.conversationIds).toBeUndefined();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("skips malformed message rows without error", () => {
|
|
201
|
+
const app = createApp(makeAppParams("Robust App"));
|
|
202
|
+
const convId = "conv-malformed";
|
|
203
|
+
insertConversation(convId);
|
|
204
|
+
|
|
205
|
+
// Insert a message with invalid JSON that happens to match the LIKE filter
|
|
206
|
+
const msgId = `msg-malformed-${Date.now()}`;
|
|
207
|
+
rawRun(
|
|
208
|
+
`INSERT INTO messages (id, conversation_id, role, content, created_at) VALUES (?, ?, ?, ?, ?)`,
|
|
209
|
+
msgId,
|
|
210
|
+
convId,
|
|
211
|
+
"assistant",
|
|
212
|
+
'not valid json but has "type":"ui_surface" in it',
|
|
213
|
+
Date.now(),
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
// Also insert a valid message referencing the app
|
|
217
|
+
const convId2 = "conv-valid";
|
|
218
|
+
insertConversation(convId2);
|
|
219
|
+
insertMessage(convId2, [
|
|
220
|
+
{
|
|
221
|
+
type: "ui_surface",
|
|
222
|
+
surfaceType: "dynamic_page",
|
|
223
|
+
data: { appId: app.id, html: "<h1>App</h1>" },
|
|
224
|
+
},
|
|
225
|
+
]);
|
|
226
|
+
|
|
227
|
+
// Should not throw, and should still process the valid message
|
|
228
|
+
backfillAppConversationIds();
|
|
229
|
+
|
|
230
|
+
const loaded = getApp(app.id);
|
|
231
|
+
expect(loaded?.conversationIds).toEqual([convId2]);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("skips ui_surface blocks without data.appId", () => {
|
|
235
|
+
const app = createApp(makeAppParams("No AppId App"));
|
|
236
|
+
const convId = "conv-no-appid";
|
|
237
|
+
insertConversation(convId);
|
|
238
|
+
|
|
239
|
+
// ui_surface block without appId in data
|
|
240
|
+
insertMessage(convId, [
|
|
241
|
+
{
|
|
242
|
+
type: "ui_surface",
|
|
243
|
+
surfaceType: "card",
|
|
244
|
+
data: { title: "Hello", body: "World" },
|
|
245
|
+
},
|
|
246
|
+
]);
|
|
247
|
+
|
|
248
|
+
backfillAppConversationIds();
|
|
249
|
+
|
|
250
|
+
const loaded = getApp(app.id);
|
|
251
|
+
expect(loaded?.conversationIds).toBeUndefined();
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test("preserves existing conversationIds added before backfill", () => {
|
|
255
|
+
const app = createApp(makeAppParams("Pre-existing App"));
|
|
256
|
+
const existingConvId = "conv-existing";
|
|
257
|
+
const backfillConvId = "conv-from-backfill";
|
|
258
|
+
insertConversation(existingConvId);
|
|
259
|
+
insertConversation(backfillConvId);
|
|
260
|
+
|
|
261
|
+
// Manually add a conversationId before backfill
|
|
262
|
+
addAppConversationId(app.id, existingConvId);
|
|
263
|
+
|
|
264
|
+
// Insert a message referencing the app from a different conversation
|
|
265
|
+
insertMessage(backfillConvId, [
|
|
266
|
+
{
|
|
267
|
+
type: "ui_surface",
|
|
268
|
+
surfaceType: "dynamic_page",
|
|
269
|
+
data: { appId: app.id, html: "<h1>App</h1>" },
|
|
270
|
+
},
|
|
271
|
+
]);
|
|
272
|
+
|
|
273
|
+
backfillAppConversationIds();
|
|
274
|
+
|
|
275
|
+
const loaded = getApp(app.id);
|
|
276
|
+
expect(loaded?.conversationIds).toEqual([existingConvId, backfillConvId]);
|
|
277
|
+
});
|
|
278
|
+
});
|