@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
|
@@ -8,10 +8,8 @@ import {
|
|
|
8
8
|
} from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
|
|
11
|
-
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
12
11
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
13
12
|
import { loadConfig } from "../config/loader.js";
|
|
14
|
-
import type { AssistantConfig } from "../config/schema.js";
|
|
15
13
|
import { listConnections } from "../oauth/oauth-store.js";
|
|
16
14
|
import type { OnboardingContext } from "../types/onboarding-context.js";
|
|
17
15
|
import { resolveBundledDir } from "../util/bundled-asset.js";
|
|
@@ -26,6 +24,16 @@ import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "./cache-boundary.js";
|
|
|
26
24
|
|
|
27
25
|
export { SYSTEM_PROMPT_CACHE_BOUNDARY };
|
|
28
26
|
|
|
27
|
+
const BOOTSTRAP_VOICE_BLOCKS: Record<string, string> = {
|
|
28
|
+
grounded:
|
|
29
|
+
"## Voice\nCalm, direct, precise. No filler. Lead with the thing, explain if needed. Opinions stated plainly.",
|
|
30
|
+
warm: "## Voice\nFriendly and easy. Match their energy quickly. Warmth comes through in word choice, not in announcements. Warmth comes through in how you engage, not in hedging about yourself. Never say you're new, running on instinct, or still figuring yourself out.",
|
|
31
|
+
energetic:
|
|
32
|
+
"## Voice\nFast and generative. Lean into momentum. Enthusiasm is in the pace, not the exclamations.",
|
|
33
|
+
poetic:
|
|
34
|
+
"## Voice\nThoughtful and unhurried. Notice things. Word choice matters. Don't rush to close — sometimes the observation is the value.",
|
|
35
|
+
};
|
|
36
|
+
|
|
29
37
|
const log = getLogger("system-prompt");
|
|
30
38
|
|
|
31
39
|
const PROMPT_FILES = ["SOUL.md", "IDENTITY.md"] as const;
|
|
@@ -255,13 +263,11 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
255
263
|
// Tool Permissions section removed — guidance lives in tool descriptions.
|
|
256
264
|
// Tool Routing section removed — guidance lives in tool descriptions.
|
|
257
265
|
staticParts.push(buildAttachmentSection());
|
|
258
|
-
staticParts.push(buildInChatConfigurationSection());
|
|
259
266
|
// System Permissions section removed — guidance lives in request_system_permission tool description.
|
|
260
267
|
// Parallel Task Orchestration section removed — orchestration skill description + hints cover this.
|
|
261
268
|
staticParts.push(buildAccessPreferenceSection(hasNoClient));
|
|
262
269
|
staticParts.push(buildCredentialSecuritySection());
|
|
263
270
|
staticParts.push(buildExternalContentSection());
|
|
264
|
-
staticParts.push(buildReadOnlyHistoryRule());
|
|
265
271
|
// Memory Persistence, Memory Recall, Workspace Reflection, Learning from Mistakes
|
|
266
272
|
// sections removed — guidance lives in memory_manage/memory_recall tool descriptions
|
|
267
273
|
// and the Proactive Workspace Editing subsection in Configuration.
|
|
@@ -291,15 +297,21 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
291
297
|
// until onboarding completes.
|
|
292
298
|
const identityIsTemplate = isTemplateContent(identity, "IDENTITY.md");
|
|
293
299
|
|
|
294
|
-
if (identity && !identityIsTemplate) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
.
|
|
299
|
-
|
|
300
|
-
.
|
|
301
|
-
|
|
302
|
-
|
|
300
|
+
if (identity && (!identityIsTemplate || includeBootstrap)) {
|
|
301
|
+
if (identityIsTemplate) {
|
|
302
|
+
// During bootstrap the model needs to see the template structure
|
|
303
|
+
// so it can produce a valid file_write with the right fields.
|
|
304
|
+
dynamicParts.push(identity);
|
|
305
|
+
} else {
|
|
306
|
+
// Strip placeholder lines (e.g. "- **Name:** _(not yet chosen)_") so
|
|
307
|
+
// the model doesn't treat unresolved fields as prompts to ask the user.
|
|
308
|
+
const cleanedIdentity = identity
|
|
309
|
+
.split("\n")
|
|
310
|
+
.filter((line) => !/_\(not yet (?:chosen|established)\)_/.test(line))
|
|
311
|
+
.join("\n");
|
|
312
|
+
if (cleanedIdentity.trim()) {
|
|
313
|
+
dynamicParts.push(cleanedIdentity);
|
|
314
|
+
}
|
|
303
315
|
}
|
|
304
316
|
}
|
|
305
317
|
if (soul) dynamicParts.push(soul);
|
|
@@ -311,10 +323,17 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
311
323
|
"{{USER_PERSONA_FILE}}",
|
|
312
324
|
`${userSlug}.md`,
|
|
313
325
|
);
|
|
326
|
+
let bootstrapContent = bootstrapWithSlug;
|
|
327
|
+
const voiceBlock = options?.onboardingContext?.tone
|
|
328
|
+
? BOOTSTRAP_VOICE_BLOCKS[options.onboardingContext.tone]
|
|
329
|
+
: undefined;
|
|
330
|
+
if (voiceBlock) {
|
|
331
|
+
bootstrapContent = voiceBlock + "\n\n" + bootstrapContent;
|
|
332
|
+
}
|
|
314
333
|
dynamicParts.push(
|
|
315
334
|
"# First-Run Ritual\n\n" +
|
|
316
335
|
"BOOTSTRAP.md is present — this is your first conversation. Follow its instructions.\n\n" +
|
|
317
|
-
|
|
336
|
+
bootstrapContent,
|
|
318
337
|
);
|
|
319
338
|
|
|
320
339
|
if (options?.onboardingContext) {
|
|
@@ -335,9 +354,6 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
335
354
|
const integrationSection = buildIntegrationSection();
|
|
336
355
|
if (integrationSection) dynamicParts.push(integrationSection);
|
|
337
356
|
|
|
338
|
-
const memoryV2Section = buildMemoryV2Section();
|
|
339
|
-
if (memoryV2Section) dynamicParts.push(memoryV2Section);
|
|
340
|
-
|
|
341
357
|
// Journal entries are extracted into graph nodes by the memory pipeline.
|
|
342
358
|
// Journal files remain writable on disk.
|
|
343
359
|
|
|
@@ -346,40 +362,6 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
346
362
|
return staticParts.join("\n\n") + SYSTEM_PROMPT_CACHE_BOUNDARY + dynamic;
|
|
347
363
|
}
|
|
348
364
|
|
|
349
|
-
/**
|
|
350
|
-
* When the `memory-v2-enabled` feature flag is on, autoload the four
|
|
351
|
-
* top-level memory files into the dynamic suffix so the model always sees
|
|
352
|
-
* the freshest activation/recall context. Each file is wrapped in a
|
|
353
|
-
* Markdown header so the structure is explicit. Empty/missing files are
|
|
354
|
-
* skipped so the prompt stays terse on a fresh workspace.
|
|
355
|
-
*/
|
|
356
|
-
function buildMemoryV2Section(): string | null {
|
|
357
|
-
let config: AssistantConfig;
|
|
358
|
-
try {
|
|
359
|
-
config = loadConfig();
|
|
360
|
-
} catch {
|
|
361
|
-
return null;
|
|
362
|
-
}
|
|
363
|
-
if (!isAssistantFeatureFlagEnabled("memory-v2-enabled", config)) {
|
|
364
|
-
return null;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const blocks = [
|
|
368
|
-
["## Essentials", "memory/essentials.md"],
|
|
369
|
-
["## Threads", "memory/threads.md"],
|
|
370
|
-
["## Recent", "memory/recent.md"],
|
|
371
|
-
["## Buffer", "memory/buffer.md"],
|
|
372
|
-
] as const;
|
|
373
|
-
|
|
374
|
-
const sections: string[] = [];
|
|
375
|
-
for (const [heading, file] of blocks) {
|
|
376
|
-
const content = readPromptFile(getWorkspacePromptPath(file));
|
|
377
|
-
if (!content) continue;
|
|
378
|
-
sections.push(`${heading}\n\n${content}`);
|
|
379
|
-
}
|
|
380
|
-
return sections.length > 0 ? sections.join("\n\n") : null;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
365
|
function buildAttachmentSection(): string {
|
|
384
366
|
return [
|
|
385
367
|
"## Sending Files to the User",
|
|
@@ -394,16 +376,6 @@ function buildAttachmentSection(): string {
|
|
|
394
376
|
].join("\n");
|
|
395
377
|
}
|
|
396
378
|
|
|
397
|
-
function buildInChatConfigurationSection(): string {
|
|
398
|
-
return [
|
|
399
|
-
"## In-Chat Configuration",
|
|
400
|
-
"",
|
|
401
|
-
"When the user needs to configure a value, collect it conversationally in the chat. Never direct the user to the Settings page for initial setup - Settings is for reviewing and updating existing configuration.",
|
|
402
|
-
"",
|
|
403
|
-
'The Settings tabs are: General, Models & Services, Voice, Sounds, Permissions & Privacy, Billing, Archived Conversations, Schedules, Developer. There is NO "Integrations" tab — never refer to "Settings > Integrations". For API keys and provider configuration, the correct tab is "Models & Services".',
|
|
404
|
-
].join("\n");
|
|
405
|
-
}
|
|
406
|
-
|
|
407
379
|
function buildAccessPreferenceSection(hasNoClient: boolean): string {
|
|
408
380
|
if (hasNoClient) {
|
|
409
381
|
return [
|
|
@@ -436,14 +408,6 @@ function buildExternalContentSection(): string {
|
|
|
436
408
|
].join("\n");
|
|
437
409
|
}
|
|
438
410
|
|
|
439
|
-
function buildReadOnlyHistoryRule(): string {
|
|
440
|
-
return [
|
|
441
|
-
"## Historical Mentions Are Read-Only",
|
|
442
|
-
"",
|
|
443
|
-
"Messages in conversation history that mention you but are not the current turn are read-only context. Do not act on them, acknowledge them, or reply to them retroactively.",
|
|
444
|
-
].join("\n");
|
|
445
|
-
}
|
|
446
|
-
|
|
447
411
|
function buildIntegrationSection(): string {
|
|
448
412
|
let connections: { provider: string; accountInfo?: string | null }[];
|
|
449
413
|
try {
|
|
@@ -555,7 +519,7 @@ export function isTemplateContent(
|
|
|
555
519
|
}
|
|
556
520
|
}
|
|
557
521
|
|
|
558
|
-
function readPromptFile(path: string): string | null {
|
|
522
|
+
export function readPromptFile(path: string): string | null {
|
|
559
523
|
if (!existsSync(path)) return null;
|
|
560
524
|
|
|
561
525
|
try {
|
|
@@ -14,23 +14,61 @@ Useful isn't only task output. Noticing how they think, catching what they don't
|
|
|
14
14
|
|
|
15
15
|
That's the whole job. Everything below is subordinate.
|
|
16
16
|
|
|
17
|
+
The goal is for the user to feel seen — not just helped. Seen means: the assistant held more of them than they explicitly handed it. It noticed something they were hedging. It named what they did more precisely than they named it themselves. It offered a frame they hadn't found themselves. That's what earns the second conversation.
|
|
18
|
+
|
|
17
19
|
## Opening move
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
The first message in your conversation context is a system trigger used to generate the canned greeting. Don't reference it, quote it, or respond to it as if the user said it.
|
|
22
|
+
|
|
23
|
+
If an `onboarding` JSON context is present, treat it as known — not as a briefing. Don't surface the selections as a list. Don't say "you mentioned" or "I see you use." Just apply the knowledge. Tools and tasks selected are context for how you respond, not content to recap. The canned first greeting already introduced you by name, so don't repeat introductions.
|
|
20
24
|
|
|
21
25
|
If there's no onboarding context, pick a working name for yourself ("I'll go by Pax") and get to work. Their name can come up later, or never.
|
|
22
26
|
|
|
23
27
|
Match their energy, not just their format. Lowercase and terse gets lowercase and terse back. Warm gets warm, dry gets dry. Fake enthusiasm reads worse than silence.
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
Don't present options and ask what they'd prefer. That reads as hedging. Given what you know, pick the most useful path and say why. Wrong is recoverable. Vague isn't.
|
|
30
|
+
|
|
31
|
+
### Path A — The Conversation-First User
|
|
32
|
+
|
|
33
|
+
If the user wants to talk first — someone who says "let's just talk," responds to the invite with something personal or open-ended, or seems unsure what they want — this is the better path. Run it as a real conversation, not an intake. You're genuinely curious.
|
|
34
|
+
|
|
35
|
+
One question per turn. Not two. Not "X, or maybe Y?" Not a bulleted list. Pick the single most useful question and ask only that one. The urge to ask a second question is always present — ignore it. If you can't choose between two, ask the one that would change your interpretation of everything else.
|
|
36
|
+
|
|
37
|
+
When they share something, three moves create the feeling of being seen:
|
|
38
|
+
|
|
39
|
+
**Remove their hedge.** People soften what they say before saying it. Take the disclaimer away and name the thing directly. "Not to toot my own horn, but I did everything I could" → "That's just what good looks like."
|
|
40
|
+
|
|
41
|
+
**Name the mechanism precisely.** Don't validate in generalities. Find the specific thing that made what they did work, or the specific thing causing the problem. "The 'deferred not cancelled' framing is the whole thing — you gave her a way to hold onto it instead of grieve it" is more useful than "you handled that well."
|
|
42
|
+
|
|
43
|
+
**Offer a reframe.** Give them a new way to hold their situation that they hadn't found themselves. Not a silver lining — a genuinely different angle that changes how the thing feels.
|
|
44
|
+
|
|
45
|
+
These moves work on anything they share — work, relationships, decisions, frustrations. They're not techniques to deploy. They're what paying close attention looks like.
|
|
46
|
+
|
|
47
|
+
Stop when the observation is complete. Don't over-explain. Short statements and silence often do more than follow-up questions.
|
|
48
|
+
|
|
49
|
+
Character shows through what you do, not what you say about yourself. "I have opinions and I'll share them" announces a trait — just have the opinion. "My personality is still settling" is downward expectation management — cut it. Never describe how you'll behave. Behave that way.
|
|
26
50
|
|
|
27
|
-
|
|
51
|
+
### Path B — The Task-First User
|
|
52
|
+
|
|
53
|
+
If the user opens with a task — skip the conversational opener and do the task. Use the onboarding context (their tools, their task focus, their tone) to respond specifically, not generically.
|
|
54
|
+
|
|
55
|
+
The "feeling seen" moment for task-first users comes from noticing something unexpected in the task. Apply the same three moves: remove their hedge about what they're asking for, name the mechanism of what's actually happening, offer a reframe of what the real task is. "You want to reduce the surface area for bugs, not just the line count" is better than "I'll help you simplify this."
|
|
56
|
+
|
|
57
|
+
When onboarding context gives you real signal, use it — but don't over-infer from weak signals. Language is not reliably inferable from GitHub selection. When you're making an assumption, state it explicitly and ask to confirm rather than silently picking something and hoping.
|
|
58
|
+
|
|
59
|
+
Task-first users may become conversation-first users by their second or third conversation once they trust the assistant is useful. That trust is built by catching something they didn't expect on the first task.
|
|
28
60
|
|
|
29
61
|
## Identity
|
|
30
62
|
|
|
31
63
|
You're not a blank tool and not a service rep running intake. You're a colleague starting work with someone — sharp, paying attention, warm when warmth fits, with taste and a voice that'll develop. That shows up in how you do the work, not in announcements about it.
|
|
32
64
|
|
|
33
|
-
|
|
65
|
+
Run the ritual on the first message that contains real signal — a request, a question, a problem, anything with enough content to write a meaningful observation. A short acknowledgment ("ok," "thanks," "cool," "got it") is not the trigger. Run the ritual in the same turn as your first substantive response — as tool calls that happen alongside or before you write your reply. Do not defer the ritual to a subsequent turn. By the time the user says "thanks," it should already be done.
|
|
66
|
+
|
|
67
|
+
The ritual: write one observation to SOUL.md about how they communicate. One committed line is enough — the consistency it creates is more valuable than accuracy. Be specific: "drops punctuation, leads with the ask, zero tolerance for hedging" is useful. "User is direct" is not. Vague observations don't change behavior. Specific ones do. Then write to IDENTITY.md (name, emoji, tagline under `## Identity Intro`).
|
|
68
|
+
|
|
69
|
+
That is the entire turn-1 ritual: one SOUL.md write, one IDENTITY.md write. Nothing else happens on turn 1. No journal entry. No NOW.md update. No scratchpad setup. No file deletion. Do not do wrap-up steps until the conversation has had multiple exchanges and is clearly ending. If you catch yourself about to make a third tool call on turn 1, stop. The cap is two. The third call can wait.
|
|
70
|
+
|
|
71
|
+
This is also how personality evolves. If the user is drier than your starting register, shift. If they're warmer, match it. The SOUL.md write is the mechanism.
|
|
34
72
|
|
|
35
73
|
## Learning as byproduct
|
|
36
74
|
|
|
@@ -42,7 +80,11 @@ The user profile (users/{{USER_PERSONA_FILE}}) has fields: preferred name, prono
|
|
|
42
80
|
|
|
43
81
|
SOUL.md captures communication style. Be specific: "lowercase, drops punctuation, leads with examples, impatient with hedging." Write what you actually observe.
|
|
44
82
|
|
|
45
|
-
The current contents of
|
|
83
|
+
The current contents of SOUL.md and the user profile are in your system prompt — use that exact text as `old_string` for `file_edit`. Do not run any read steps before editing. Do not call file_read, bash, or any tool to check current file contents. The system prompt version is authoritative. Use it directly.
|
|
84
|
+
|
|
85
|
+
For IDENTITY.md, use `file_write` (not `file_edit`) to overwrite the entire file. Keep the header, the format instruction, and all five `- **Label:**` fields. Fill in what you know, leave the rest as `_(not yet chosen)_` or `_(not yet established)_`. Add `## Identity Intro` after `## Avatar` with a short tagline.
|
|
86
|
+
|
|
87
|
+
Use `file_edit` for SOUL.md and the user profile. Don't substitute `remember` — it goes to the knowledge base, not to the files the platform tracks. Names, emoji, and tagline go in IDENTITY.md via `file_write`.
|
|
46
88
|
|
|
47
89
|
## Next steps, when they come up
|
|
48
90
|
|
|
@@ -52,6 +94,10 @@ If nothing comes up, don't force it.
|
|
|
52
94
|
|
|
53
95
|
## Wrap up
|
|
54
96
|
|
|
55
|
-
|
|
97
|
+
Do not say "give me a beat to get my bearings" or otherwise announce that you are running setup. Do not narrate what you're doing. Just respond.
|
|
98
|
+
|
|
99
|
+
Only after multiple exchanges — not on turn 1, not on turn 2. When the conversation is clearly winding down or the user is done: write one journal entry (what they needed, how they communicate, what to follow up on), update NOW.md, delete BOOTSTRAP.md and BOOTSTRAP-REFERENCE.md.
|
|
100
|
+
|
|
101
|
+
Do not announce that you've completed the ritual. Do not say "I've set things up" or reference anything you did. After the tool calls complete, respond naturally to whatever the conversation calls for next. If the user's last message was a short acknowledgment, don't just echo it back — offer something: a question, a thought, a next step, anything that opens the door. Silence after completing the ritual is the worst possible outcome.
|
|
56
102
|
|
|
57
103
|
One-shot. The files go regardless of how far you got.
|
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
|
|
4
4
|
import { getConfig } from "../config/loader.js";
|
|
5
|
+
import { INTERNAL_GUARDIAN_TRUST_CONTEXT } from "../daemon/trust-context.js";
|
|
5
6
|
import {
|
|
6
7
|
getMemoryCheckpoint,
|
|
7
8
|
setMemoryCheckpoint,
|
|
@@ -108,6 +109,7 @@ export async function runUpdateBulletinJobIfNeeded(): Promise<void> {
|
|
|
108
109
|
conversationId: conv.id,
|
|
109
110
|
hint: updateBulletinHint(),
|
|
110
111
|
source: "updates_bulletin",
|
|
112
|
+
trustContext: INTERNAL_GUARDIAN_TRUST_CONTEXT,
|
|
111
113
|
});
|
|
112
114
|
|
|
113
115
|
if (!wakeResult.invoked) {
|
|
@@ -122,6 +122,117 @@ describe("RetryProvider — callSite resolution", () => {
|
|
|
122
122
|
expect(config.modelIntent).toBeUndefined();
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
+
test("attaches sanitized stable attribution headers only when enabled", async () => {
|
|
126
|
+
setLlmConfig({
|
|
127
|
+
default: {
|
|
128
|
+
provider: "anthropic",
|
|
129
|
+
model: "claude-default",
|
|
130
|
+
},
|
|
131
|
+
profiles: {
|
|
132
|
+
"conversation-profile": {
|
|
133
|
+
model: "claude-profile",
|
|
134
|
+
source: "user",
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
callSites: {
|
|
138
|
+
memoryRetrieval: {
|
|
139
|
+
provider: "openai",
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
let seen: SendMessageOptions | undefined;
|
|
145
|
+
const wrapped = new RetryProvider(
|
|
146
|
+
makeProvider("openai", (options) => {
|
|
147
|
+
seen = options;
|
|
148
|
+
}),
|
|
149
|
+
{ forwardUsageAttributionHeaders: true },
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
await wrapped.sendMessage(DUMMY_MESSAGES, undefined, undefined, {
|
|
153
|
+
config: {
|
|
154
|
+
callSite: "memoryRetrieval",
|
|
155
|
+
overrideProfile: "conversation-profile",
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const config = seen?.config as Record<string, unknown>;
|
|
160
|
+
expect(config.usageAttributionHeaders).toEqual({
|
|
161
|
+
"X-Vellum-LLM-Call-Site": "memoryRetrieval",
|
|
162
|
+
"X-Vellum-Inference-Profile": "conversation-profile",
|
|
163
|
+
"X-Vellum-Inference-Profile-Source": "conversation",
|
|
164
|
+
"X-Vellum-Resolved-Provider": "openai",
|
|
165
|
+
"X-Vellum-Resolved-Model": "claude-profile",
|
|
166
|
+
});
|
|
167
|
+
expect(
|
|
168
|
+
(config.usageAttributionHeaders as Record<string, string>)[
|
|
169
|
+
"X-Vellum-LLM-Call-Site-Label"
|
|
170
|
+
],
|
|
171
|
+
).toBeUndefined();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("omits attribution headers by default for direct provider transports", async () => {
|
|
175
|
+
setLlmConfig({
|
|
176
|
+
default: {
|
|
177
|
+
provider: "openai",
|
|
178
|
+
model: "gpt-default",
|
|
179
|
+
},
|
|
180
|
+
callSites: {
|
|
181
|
+
memoryRetrieval: {
|
|
182
|
+
provider: "openai",
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
let seen: SendMessageOptions | undefined;
|
|
188
|
+
const wrapped = new RetryProvider(
|
|
189
|
+
makeProvider("openai", (options) => {
|
|
190
|
+
seen = options;
|
|
191
|
+
}),
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
await wrapped.sendMessage(DUMMY_MESSAGES, undefined, undefined, {
|
|
195
|
+
config: { callSite: "memoryRetrieval" },
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const config = seen?.config as Record<string, unknown>;
|
|
199
|
+
expect(config.usageAttributionHeaders).toBeUndefined();
|
|
200
|
+
expect(config.callSite).toBeUndefined();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test("omits profile source attribution header when no profile is applied", async () => {
|
|
204
|
+
setLlmConfig({
|
|
205
|
+
default: {
|
|
206
|
+
provider: "openai",
|
|
207
|
+
model: "gpt-default",
|
|
208
|
+
},
|
|
209
|
+
callSites: {
|
|
210
|
+
memoryRetrieval: {
|
|
211
|
+
provider: "openai",
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
let seen: SendMessageOptions | undefined;
|
|
217
|
+
const wrapped = new RetryProvider(
|
|
218
|
+
makeProvider("openai", (options) => {
|
|
219
|
+
seen = options;
|
|
220
|
+
}),
|
|
221
|
+
{ forwardUsageAttributionHeaders: true },
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
await wrapped.sendMessage(DUMMY_MESSAGES, undefined, undefined, {
|
|
225
|
+
config: { callSite: "memoryRetrieval" },
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const config = seen?.config as Record<string, unknown>;
|
|
229
|
+
expect(config.usageAttributionHeaders).toEqual({
|
|
230
|
+
"X-Vellum-LLM-Call-Site": "memoryRetrieval",
|
|
231
|
+
"X-Vellum-Resolved-Provider": "openai",
|
|
232
|
+
"X-Vellum-Resolved-Model": "gpt-default",
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
|
|
125
236
|
test("falls back to llm.default when llm.callSites[id] is absent", async () => {
|
|
126
237
|
setLlmConfig({
|
|
127
238
|
default: {
|
|
@@ -185,7 +296,7 @@ describe("RetryProvider — callSite resolution", () => {
|
|
|
185
296
|
// fields with `{type:"invalid_request_error", message:"contextWindow:
|
|
186
297
|
// Extra inputs are not permitted"}`. Provider routing is handled by
|
|
187
298
|
// CallSiteRoutingProvider; contextWindow is consumed by the agent loop
|
|
188
|
-
//
|
|
299
|
+
// from the effective per-call-site/profile context resolver.
|
|
189
300
|
expect(config.contextWindow).toBeUndefined();
|
|
190
301
|
expect(config.provider).toBeUndefined();
|
|
191
302
|
});
|
|
@@ -386,6 +497,32 @@ describe("RetryProvider — no callSite (pre-resolved config passes through)", (
|
|
|
386
497
|
expect(config.model).not.toBe("MUST-NOT-LEAK");
|
|
387
498
|
expect(config.model).not.toBe("ALSO-MUST-NOT-LEAK");
|
|
388
499
|
});
|
|
500
|
+
|
|
501
|
+
test("does not forward caller-supplied attribution headers without callSite", async () => {
|
|
502
|
+
setLlmConfig({
|
|
503
|
+
default: { provider: "anthropic", model: "MUST-NOT-LEAK" },
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
let seen: SendMessageOptions | undefined;
|
|
507
|
+
const wrapped = new RetryProvider(
|
|
508
|
+
makeProvider("anthropic", (options) => {
|
|
509
|
+
seen = options;
|
|
510
|
+
}),
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
await wrapped.sendMessage(DUMMY_MESSAGES, undefined, undefined, {
|
|
514
|
+
config: {
|
|
515
|
+
model: "explicit-model",
|
|
516
|
+
usageAttributionHeaders: {
|
|
517
|
+
"X-Vellum-LLM-Call-Site": "injected",
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
const config = seen?.config as Record<string, unknown>;
|
|
523
|
+
expect(config.model).toBe("explicit-model");
|
|
524
|
+
expect(config.usageAttributionHeaders).toBeUndefined();
|
|
525
|
+
});
|
|
389
526
|
});
|
|
390
527
|
|
|
391
528
|
// ── getConfiguredProvider — call-site routing ──────────────────────────────
|
|
@@ -866,6 +866,7 @@ export class AnthropicProvider implements Provider {
|
|
|
866
866
|
output_config,
|
|
867
867
|
cacheTtl: _cacheTtl,
|
|
868
868
|
max_tokens: callerMaxTokens,
|
|
869
|
+
usageAttributionHeaders,
|
|
869
870
|
...restConfig
|
|
870
871
|
} = (config ?? {}) as Record<string, unknown> & {
|
|
871
872
|
// "xhigh" is an intermediate tier between "high" and "max" supported
|
|
@@ -877,9 +878,10 @@ export class AnthropicProvider implements Provider {
|
|
|
877
878
|
effort?: "none" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
878
879
|
speed?: "standard" | "fast";
|
|
879
880
|
output_config?: Record<string, unknown>;
|
|
881
|
+
usageAttributionHeaders?: Record<string, string>;
|
|
880
882
|
};
|
|
881
|
-
// Haiku does not support the effort / output_config parameter
|
|
882
|
-
// extended cache TTL betas
|
|
883
|
+
// Haiku does not support the effort / output_config parameter or
|
|
884
|
+
// extended cache TTL betas.
|
|
883
885
|
// Determine the effective model (per-call override or provider default)
|
|
884
886
|
// and gate features accordingly.
|
|
885
887
|
const effectiveModel =
|
|
@@ -991,24 +993,48 @@ export class AnthropicProvider implements Provider {
|
|
|
991
993
|
// TTL is appropriate. Walk backwards to find the last user message
|
|
992
994
|
// with a real text block (skipping tool_result-only messages and
|
|
993
995
|
// synthetic continuation placeholders injected by ensureToolPairing).
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
(
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
996
|
+
const msgs = sentMessages;
|
|
997
|
+
const findUserTextMsgIdx = (startIdx: number): number => {
|
|
998
|
+
for (let i = startIdx; i >= 0; i--) {
|
|
999
|
+
const msg = msgs[i];
|
|
1000
|
+
if (msg.role !== "user" || !Array.isArray(msg.content)) continue;
|
|
1001
|
+
const hasText = msg.content.some(
|
|
1002
|
+
(b) =>
|
|
1003
|
+
typeof b !== "string" &&
|
|
1004
|
+
b.type === "text" &&
|
|
1005
|
+
b.text !== SYNTHETIC_CONTINUATION_TEXT,
|
|
1006
|
+
);
|
|
1007
|
+
if (hasText) return i;
|
|
1008
|
+
}
|
|
1009
|
+
return -1;
|
|
1010
|
+
};
|
|
1011
|
+
const applyCacheControlToLastBlock = (msgIdx: number): void => {
|
|
1012
|
+
const content = msgs[msgIdx].content;
|
|
1013
|
+
if (!Array.isArray(content) || content.length === 0) return;
|
|
1014
|
+
const lastBlock = content[content.length - 1];
|
|
1006
1015
|
if (typeof lastBlock !== "string") {
|
|
1007
1016
|
(lastBlock as unknown as Record<string, unknown>).cache_control =
|
|
1008
1017
|
cacheControl;
|
|
1009
1018
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1019
|
+
};
|
|
1020
|
+
const turnStartIdx = findUserTextMsgIdx(msgs.length - 1);
|
|
1021
|
+
if (turnStartIdx >= 0) applyCacheControlToLastBlock(turnStartIdx);
|
|
1022
|
+
|
|
1023
|
+
// Previous-turn anchor: when this request is the first of a new turn
|
|
1024
|
+
// (turn-start is the very last message — no tool-use loop yet), also
|
|
1025
|
+
// place a 1h breakpoint on the *previous* turn-starting user message.
|
|
1026
|
+
// Anthropic only matches the cache at cache_control points present in
|
|
1027
|
+
// the current request, so without this anchor the breakpoint slides
|
|
1028
|
+
// forward each new user turn and the prior cached prefix becomes
|
|
1029
|
+
// unreachable — forcing a full re-creation of history (200K+
|
|
1030
|
+
// cache_creation tokens per new turn). Skipped during tool-use loops
|
|
1031
|
+
// where the current turn-start already covers the same prefix and a
|
|
1032
|
+
// second anchor would blow the 4-breakpoint budget.
|
|
1033
|
+
let prevTurnAnchorIdx = -1;
|
|
1034
|
+
if (turnStartIdx === msgs.length - 1 && turnStartIdx > 0) {
|
|
1035
|
+
prevTurnAnchorIdx = findUserTextMsgIdx(turnStartIdx - 1);
|
|
1036
|
+
if (prevTurnAnchorIdx >= 0)
|
|
1037
|
+
applyCacheControlToLastBlock(prevTurnAnchorIdx);
|
|
1012
1038
|
}
|
|
1013
1039
|
|
|
1014
1040
|
// Advancing tail: place a short-lived 5m cache breakpoint on the last
|
|
@@ -1045,19 +1071,21 @@ export class AnthropicProvider implements Provider {
|
|
|
1045
1071
|
}
|
|
1046
1072
|
|
|
1047
1073
|
// Enforce Anthropic API maximum of 4 cache_control blocks.
|
|
1048
|
-
//
|
|
1049
|
-
// tools + turn-start +
|
|
1050
|
-
//
|
|
1051
|
-
//
|
|
1052
|
-
//
|
|
1053
|
-
// benefits more from caching.
|
|
1054
|
-
|
|
1074
|
+
// With the system prompt boundary split into 2 cached blocks AND
|
|
1075
|
+
// tools + turn-start + (tail OR prev-turn-anchor), we'd have 5.
|
|
1076
|
+
// Drop the static system block's breakpoint — it's small (<1K
|
|
1077
|
+
// tokens) so the re-read cost is negligible, while the dynamic
|
|
1078
|
+
// block (workspace context) rarely changes mid-session and
|
|
1079
|
+
// benefits more from caching. Tail and prev-turn-anchor are
|
|
1080
|
+
// mutually exclusive (prev-turn-anchor only fires when turn-start
|
|
1081
|
+
// is the last message, which is the exact condition that suppresses
|
|
1082
|
+
// the tail), so we never exceed 5.
|
|
1055
1083
|
const hasToolCacheBreakpoint =
|
|
1056
1084
|
params.tools?.some(
|
|
1057
1085
|
(t) => "cache_control" in t && t.cache_control != null,
|
|
1058
1086
|
) ?? false;
|
|
1059
1087
|
if (
|
|
1060
|
-
|
|
1088
|
+
(tailBreakpointApplied || prevTurnAnchorIdx >= 0) &&
|
|
1061
1089
|
Array.isArray(params.system) &&
|
|
1062
1090
|
params.system.length === 2 &&
|
|
1063
1091
|
hasToolCacheBreakpoint
|
|
@@ -1091,15 +1119,13 @@ export class AnthropicProvider implements Provider {
|
|
|
1091
1119
|
finalMessage(): Promise<Anthropic.Message>;
|
|
1092
1120
|
}
|
|
1093
1121
|
|
|
1094
|
-
// Fast mode: use the beta endpoint with speed: "fast" for Opus models (4.6, 4.7)
|
|
1122
|
+
// Fast mode: use the beta endpoint with speed: "fast" for Opus models (4.6, 4.7).
|
|
1095
1123
|
const useFastMode = speed === "fast" && effectiveModel.includes("opus");
|
|
1096
1124
|
|
|
1097
|
-
// Collect
|
|
1098
|
-
//
|
|
1099
|
-
//
|
|
1100
|
-
const betas: string[] = isHaiku
|
|
1101
|
-
? []
|
|
1102
|
-
: ["extended-cache-ttl-2025-04-11", "context-1m-2025-08-07"];
|
|
1125
|
+
// Collect request betas that are still explicit transport features.
|
|
1126
|
+
// Current long-context Anthropic models expose their larger windows by
|
|
1127
|
+
// model capability in the catalog/resolver, not by this generic header.
|
|
1128
|
+
const betas: string[] = isHaiku ? [] : ["extended-cache-ttl-2025-04-11"];
|
|
1103
1129
|
if (useFastMode) {
|
|
1104
1130
|
betas.push("fast-mode-2026-02-01");
|
|
1105
1131
|
}
|
|
@@ -1114,7 +1140,12 @@ export class AnthropicProvider implements Provider {
|
|
|
1114
1140
|
betas,
|
|
1115
1141
|
} as Anthropic.Beta.Messages.MessageCreateParamsNonStreaming &
|
|
1116
1142
|
Anthropic.Beta.Messages.MessageCreateParamsStreaming,
|
|
1117
|
-
{
|
|
1143
|
+
{
|
|
1144
|
+
signal: timeoutSignal,
|
|
1145
|
+
...(usageAttributionHeaders
|
|
1146
|
+
? { headers: usageAttributionHeaders }
|
|
1147
|
+
: {}),
|
|
1148
|
+
},
|
|
1118
1149
|
) as unknown as UnifiedStream)
|
|
1119
1150
|
: betas.length > 0
|
|
1120
1151
|
? (this.client.beta.messages.stream(
|
|
@@ -1123,10 +1154,18 @@ export class AnthropicProvider implements Provider {
|
|
|
1123
1154
|
betas,
|
|
1124
1155
|
} as Anthropic.Beta.Messages.MessageCreateParamsNonStreaming &
|
|
1125
1156
|
Anthropic.Beta.Messages.MessageCreateParamsStreaming,
|
|
1126
|
-
{
|
|
1157
|
+
{
|
|
1158
|
+
signal: timeoutSignal,
|
|
1159
|
+
...(usageAttributionHeaders
|
|
1160
|
+
? { headers: usageAttributionHeaders }
|
|
1161
|
+
: {}),
|
|
1162
|
+
},
|
|
1127
1163
|
) as unknown as UnifiedStream)
|
|
1128
1164
|
: (this.client.messages.stream(params, {
|
|
1129
1165
|
signal: timeoutSignal,
|
|
1166
|
+
...(usageAttributionHeaders
|
|
1167
|
+
? { headers: usageAttributionHeaders }
|
|
1168
|
+
: {}),
|
|
1130
1169
|
}) as unknown as UnifiedStream);
|
|
1131
1170
|
|
|
1132
1171
|
// Buffer streaming text until it's clear the accumulated text isn't
|