@vellumai/assistant 0.6.4 → 0.6.5
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/.prettierignore +5 -0
- package/ARCHITECTURE.md +32 -36
- package/Dockerfile +12 -0
- package/README.md +3 -4
- package/bun.lock +8 -3
- package/docs/architecture/integrations.md +1 -20
- package/docs/architecture/security.md +16 -16
- package/docs/error-handling.md +111 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +2 -1
- package/knip.json +9 -2
- package/node_modules/@vellumai/ces-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
- package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
- package/node_modules/@vellumai/credential-storage/package.json +2 -2
- package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
- package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
- package/node_modules/@vellumai/egress-proxy/package.json +2 -2
- package/openapi.yaml +123 -11
- package/package.json +6 -3
- package/scripts/generate-openapi.ts +50 -11
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
- package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
- package/src/__tests__/agent-loop.test.ts +112 -1
- package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
- package/src/__tests__/anthropic-provider.test.ts +171 -2
- package/src/__tests__/approval-cascade.test.ts +31 -10
- package/src/__tests__/approval-routes-http.test.ts +134 -10
- package/src/__tests__/assistant-attachments.test.ts +44 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
- package/src/__tests__/browser-skill-endstate.test.ts +51 -182
- package/src/__tests__/btw-routes.test.ts +47 -1
- package/src/__tests__/call-controller.test.ts +1 -2
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +27 -4
- package/src/__tests__/channel-approval-routes.test.ts +4 -4
- package/src/__tests__/channel-reply-delivery.test.ts +300 -2
- package/src/__tests__/checker.test.ts +428 -501
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/config-analysis.test.ts +11 -28
- package/src/__tests__/config-loader-backfill.test.ts +174 -0
- package/src/__tests__/config-loader-corrupt.test.ts +183 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +427 -114
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +72 -73
- package/src/__tests__/contacts-write.test.ts +4 -4
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +530 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
- package/src/__tests__/conversation-agent-loop.test.ts +412 -82
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
- package/src/__tests__/conversation-error.test.ts +37 -6
- package/src/__tests__/conversation-history-web-search.test.ts +6 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
- package/src/__tests__/conversation-process-callsite.test.ts +306 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
- package/src/__tests__/conversation-queue.test.ts +41 -26
- package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
- package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
- package/src/__tests__/conversation-skill-tools.test.ts +12 -146
- package/src/__tests__/conversation-slash-queue.test.ts +34 -19
- package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
- package/src/__tests__/conversation-speed-override.test.ts +30 -11
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -2
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
- package/src/__tests__/conversation-unread-route.test.ts +2 -2
- package/src/__tests__/conversation-usage.test.ts +3 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
- package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
- package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
- package/src/__tests__/credential-vault-unit.test.ts +135 -19
- package/src/__tests__/credentials-cli.test.ts +1 -9
- package/src/__tests__/cross-provider-web-search.test.ts +84 -0
- package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
- package/src/__tests__/delete-propagation.test.ts +437 -0
- package/src/__tests__/dm-backfill.test.ts +417 -0
- package/src/__tests__/dm-persistence.test.ts +227 -0
- package/src/__tests__/edit-propagation.test.ts +280 -0
- package/src/__tests__/ephemeral-permissions.test.ts +93 -3
- package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
- package/src/__tests__/estimator-calibration.test.ts +213 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/gemini-provider.test.ts +0 -3
- package/src/__tests__/guardian-grant-minting.test.ts +8 -0
- package/src/__tests__/headless-browser-interactions.test.ts +1 -1
- package/src/__tests__/heartbeat-service.test.ts +96 -15
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/intent-routing.test.ts +1 -40
- package/src/__tests__/llm-catalog-parity.test.ts +174 -0
- package/src/__tests__/llm-context-normalization.test.ts +121 -0
- package/src/__tests__/llm-resolver.test.ts +214 -0
- package/src/__tests__/llm-schema.test.ts +223 -0
- package/src/__tests__/managed-proxy-context.test.ts +6 -2
- package/src/__tests__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-import-from-url.test.ts +684 -0
- package/src/__tests__/model-intents.test.ts +9 -83
- package/src/__tests__/notification-decision-fallback.test.ts +0 -10
- package/src/__tests__/notification-decision-identity.test.ts +0 -9
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
- package/src/__tests__/oauth-store.test.ts +10 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/openai-provider.test.ts +7 -0
- package/src/__tests__/openai-responses-provider.test.ts +396 -0
- package/src/__tests__/openrouter-provider-only.test.ts +135 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +13 -13
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/pricing.test.ts +50 -3
- package/src/__tests__/profiler-routes.test.ts +1 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
- package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
- package/src/__tests__/provider-error-scenarios.test.ts +135 -6
- package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
- package/src/__tests__/provider-registry-ollama.test.ts +1 -2
- package/src/__tests__/proxy-approval-callback.test.ts +0 -1
- package/src/__tests__/reaction-persistence.test.ts +560 -0
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
- package/src/__tests__/risk-classifier-parity.test.ts +230 -0
- package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
- package/src/__tests__/secret-ingress-http.test.ts +28 -0
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
- package/src/__tests__/secret-scanner-executor.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +29 -1
- package/src/__tests__/server-history-render.test.ts +31 -0
- package/src/__tests__/shell-parser-property.test.ts +13 -13
- package/src/__tests__/skill-cache-store.test.ts +182 -0
- package/src/__tests__/skills.test.ts +19 -33
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-skill.test.ts +3 -8
- package/src/__tests__/starter-bundle.test.ts +35 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
- package/src/__tests__/suggestion-routes.test.ts +160 -3
- package/src/__tests__/system-prompt.test.ts +22 -35
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor.test.ts +60 -94
- package/src/__tests__/trust-store.test.ts +442 -109
- package/src/__tests__/update-bulletin-job.test.ts +389 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
- package/src/__tests__/voice-session-bridge.test.ts +39 -0
- package/src/__tests__/volume-security-guard.test.ts +3 -2
- package/src/__tests__/web-search-history.test.ts +337 -0
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +1 -13
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/loop.ts +209 -17
- package/src/avatar/resvg-lazy.test.ts +136 -0
- package/src/avatar/resvg-lazy.ts +82 -9
- package/src/avatar/traits-png-sync.ts +21 -1
- package/src/browser/__tests__/operations.test.ts +163 -0
- package/src/browser/identifiers.ts +51 -0
- package/src/browser/operations.ts +660 -0
- package/src/browser/types.ts +81 -0
- package/src/calls/guardian-question-copy.ts +2 -2
- package/src/calls/telephony-stt-routing.ts +1 -1
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/browser.test.ts +554 -0
- package/src/cli/commands/__tests__/cache.test.ts +623 -0
- package/src/cli/commands/__tests__/email-list.test.ts +6 -0
- package/src/cli/commands/__tests__/email-send.test.ts +93 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
- package/src/cli/commands/__tests__/task.test.ts +913 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
- package/src/cli/commands/__tests__/ui.test.ts +1215 -0
- package/src/cli/commands/__tests__/watchers.test.ts +716 -0
- package/src/cli/commands/attachment.ts +182 -0
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +14 -1
- package/src/cli/commands/email.ts +234 -194
- package/src/cli/commands/image-generation.ts +300 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
- package/src/cli/commands/stt.ts +339 -0
- package/src/cli/commands/task.ts +795 -0
- package/src/cli/commands/trust.ts +50 -19
- package/src/cli/commands/tts.ts +273 -0
- package/src/cli/commands/ui.ts +670 -0
- package/src/cli/commands/watchers.ts +509 -0
- package/src/cli/lib/daemon-credential-client.ts +0 -19
- package/src/cli/program.ts +23 -4
- package/src/cli.ts +0 -37
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-tool-registry.ts +0 -175
- package/src/config/env.ts +7 -2
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/llm-resolver.ts +128 -0
- package/src/config/loader.ts +194 -10
- package/src/config/raw-config-utils.ts +30 -2
- package/src/config/sanitize-for-transfer.ts +35 -0
- package/src/config/schema.ts +30 -41
- package/src/config/schemas/analysis.ts +3 -22
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/filing.ts +2 -7
- package/src/config/schemas/heartbeat.ts +0 -5
- package/src/config/schemas/inference.ts +3 -23
- package/src/config/schemas/llm.ts +318 -0
- package/src/config/schemas/memory-processing.ts +1 -9
- package/src/config/schemas/notifications.ts +4 -11
- package/src/config/schemas/platform.ts +3 -9
- package/src/config/schemas/security.ts +33 -0
- package/src/config/schemas/services.ts +9 -4
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/schemas/tts.ts +53 -0
- package/src/config/schemas/updates.ts +1 -1
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skills.ts +2 -2
- package/src/context/__tests__/compact-prompt.test.ts +45 -0
- package/src/context/__tests__/microcompact.test.ts +805 -0
- package/src/context/estimator-calibration.ts +136 -0
- package/src/context/microcompact.ts +443 -0
- package/src/context/prompts/compact.md +12 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/window-manager.ts +229 -25
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/executable-discovery.ts +19 -8
- package/src/credential-execution/process-manager.test.ts +109 -0
- package/src/credential-execution/process-manager.ts +65 -2
- package/src/daemon/approval-generators.ts +29 -4
- package/src/daemon/assistant-attachments.ts +24 -13
- package/src/daemon/classifier.ts +2 -2
- package/src/daemon/config-watcher.ts +0 -1
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
- package/src/daemon/conversation-agent-loop.ts +462 -80
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +36 -1
- package/src/daemon/conversation-lifecycle.ts +30 -6
- package/src/daemon/conversation-messaging.ts +73 -4
- package/src/daemon/conversation-process.ts +10 -4
- package/src/daemon/conversation-queue-manager.ts +3 -0
- package/src/daemon/conversation-runtime-assembly.ts +760 -29
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +389 -1
- package/src/daemon/conversation-tool-setup.ts +10 -5
- package/src/daemon/conversation-usage.ts +1 -1
- package/src/daemon/conversation.ts +118 -30
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/guardian-action-generators.ts +34 -14
- package/src/daemon/handlers/config-model.test.ts +86 -0
- package/src/daemon/handlers/config-model.ts +54 -12
- package/src/daemon/handlers/conversations.ts +9 -2
- package/src/daemon/handlers/shared.ts +39 -11
- package/src/daemon/handlers/skills.ts +2 -2
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/lifecycle.ts +76 -14
- package/src/daemon/message-types/conversations.ts +14 -0
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/trust.ts +0 -2
- package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
- package/src/daemon/pkb-context-tracker.test.ts +169 -0
- package/src/daemon/pkb-context-tracker.ts +125 -0
- package/src/daemon/pkb-reminder-builder.test.ts +70 -0
- package/src/daemon/pkb-reminder-builder.ts +31 -0
- package/src/daemon/providers-setup.ts +6 -0
- package/src/daemon/server.ts +117 -9
- package/src/daemon/tool-side-effects.ts +0 -9
- package/src/daemon/watch-handler.ts +4 -4
- package/src/daemon/web-search-history.ts +126 -0
- package/src/events/domain-events.ts +0 -1
- package/src/filing/filing-service.ts +9 -10
- package/src/heartbeat/heartbeat-service.ts +76 -28
- package/src/home/__tests__/feed-scheduler.test.ts +39 -11
- package/src/home/__tests__/rollup-producer.test.ts +44 -0
- package/src/home/assistant-feed-authoring.ts +4 -0
- package/src/home/emit-feed-event.ts +4 -0
- package/src/home/feed-scheduler.ts +20 -4
- package/src/home/feed-types.ts +56 -2
- package/src/home/relationship-state-writer.ts +2 -2
- package/src/home/rollup-producer.ts +34 -5
- package/src/home/suggested-prompts.ts +101 -0
- package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
- package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
- package/src/ipc/__tests__/socket-path.test.ts +73 -0
- package/src/ipc/__tests__/task-ipc.test.ts +577 -0
- package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
- package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
- package/src/ipc/cli-client.ts +2 -1
- package/src/ipc/cli-server.ts +26 -8
- package/src/ipc/gateway-client.ts +4 -4
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +61 -0
- package/src/ipc/routes/browser.ts +96 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/index.ts +17 -1
- package/src/ipc/routes/task-queue.ts +226 -0
- package/src/ipc/routes/task.ts +173 -0
- package/src/ipc/routes/ui-request.ts +50 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +100 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
- package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
- package/src/memory/admin.ts +18 -0
- package/src/memory/conversation-analyze-job.ts +14 -13
- package/src/memory/conversation-attention-store.ts +13 -6
- package/src/memory/conversation-crud.ts +103 -3
- package/src/memory/conversation-group-migration.ts +38 -6
- package/src/memory/conversation-title-service.ts +7 -4
- package/src/memory/db-init.ts +2 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/graph/compaction.ts +299 -0
- package/src/memory/graph/consolidation.ts +4 -4
- package/src/memory/graph/conversation-graph-memory.ts +89 -29
- package/src/memory/graph/extraction.test.ts +272 -2
- package/src/memory/graph/extraction.ts +173 -51
- package/src/memory/graph/graph-search.test.ts +92 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.test.ts +459 -0
- package/src/memory/graph/retriever.ts +230 -48
- package/src/memory/graph/store.ts +41 -0
- package/src/memory/graph/tool-handlers.ts +27 -0
- package/src/memory/graph/tools.ts +6 -1
- package/src/memory/indexer.ts +5 -5
- package/src/memory/job-handlers/conversation-starters.ts +23 -20
- package/src/memory/job-handlers/summarization.ts +2 -2
- package/src/memory/job-utils.ts +7 -1
- package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
- package/src/memory/jobs/embed-pkb-file.ts +54 -0
- package/src/memory/jobs-store.ts +44 -3
- package/src/memory/jobs-worker.ts +4 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/pkb/pkb-index.test.ts +368 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +438 -0
- package/src/memory/pkb/pkb-search.ts +137 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.ts +122 -1
- package/src/memory/slack-thread-store.ts +37 -0
- package/src/messaging/providers/gmail/adapter.ts +6 -16
- package/src/messaging/providers/gmail/client.ts +22 -0
- package/src/messaging/providers/gmail/types.ts +7 -0
- package/src/messaging/providers/slack/adapter.ts +14 -2
- package/src/messaging/providers/slack/backfill.test.ts +257 -0
- package/src/messaging/providers/slack/backfill.ts +101 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
- package/src/messaging/providers/slack/message-metadata.ts +123 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
- package/src/messaging/providers/slack/render-transcript.ts +443 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/decision-engine.ts +3 -9
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/oauth/oauth-store.ts +1 -0
- package/src/oauth/platform-connection.test.ts +47 -0
- package/src/oauth/platform-connection.ts +15 -5
- package/src/oauth/seed-providers.ts +4 -2
- package/src/permissions/approval-policy.test.ts +948 -0
- package/src/permissions/approval-policy.ts +257 -0
- package/src/permissions/bash-risk-classifier.test.ts +1208 -0
- package/src/permissions/bash-risk-classifier.ts +707 -0
- package/src/permissions/checker.ts +217 -708
- package/src/permissions/command-registry.test.ts +535 -0
- package/src/permissions/command-registry.ts +825 -0
- package/src/permissions/defaults.ts +26 -78
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/risk-types.ts +205 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/skill-risk-classifier.test.ts +311 -0
- package/src/permissions/skill-risk-classifier.ts +214 -0
- package/src/permissions/trust-client.ts +52 -25
- package/src/permissions/trust-store-interface.ts +1 -6
- package/src/permissions/trust-store.ts +161 -62
- package/src/permissions/types.ts +23 -14
- package/src/permissions/web-risk-classifier.test.ts +170 -0
- package/src/permissions/web-risk-classifier.ts +89 -0
- package/src/permissions/workspace-policy.ts +1 -16
- package/src/platform/client.ts +19 -1
- package/src/prompts/persona-resolver.ts +3 -3
- package/src/prompts/system-prompt.ts +19 -20
- package/src/prompts/templates/SOUL.md +2 -2
- package/src/prompts/update-bulletin-job.ts +190 -0
- package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
- package/src/providers/__tests__/retry-callsite.test.ts +424 -0
- package/src/providers/anthropic/client.ts +183 -14
- package/src/providers/call-site-routing.ts +71 -0
- package/src/providers/gemini/client.ts +65 -2
- package/src/providers/managed-proxy/constants.ts +2 -1
- package/src/providers/model-catalog.ts +501 -33
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/openai/chat-completions-provider.ts +57 -1
- package/src/providers/openai/responses-provider.ts +86 -9
- package/src/providers/openrouter/client.ts +76 -9
- package/src/providers/provider-env-vars.ts +56 -0
- package/src/providers/provider-send-message.ts +22 -5
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/registry.ts +19 -8
- package/src/providers/retry.ts +174 -39
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
- package/src/providers/speech-to-text/provider-catalog.ts +17 -0
- package/src/providers/speech-to-text/resolve.ts +7 -0
- package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
- package/src/providers/speech-to-text/xai-realtime.ts +796 -0
- package/src/providers/speech-to-text/xai.test.ts +155 -0
- package/src/providers/speech-to-text/xai.ts +97 -0
- package/src/providers/types.ts +93 -3
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +43 -2
- package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
- package/src/runtime/agent-wake.ts +63 -22
- package/src/runtime/auth/route-policy.ts +4 -0
- package/src/runtime/btw-sidechain.ts +13 -3
- package/src/runtime/channel-reply-delivery.ts +106 -2
- package/src/runtime/decision-token.ts +116 -0
- package/src/runtime/gateway-client.ts +2 -2
- package/src/runtime/http-router.ts +32 -0
- package/src/runtime/http-server.ts +52 -1
- package/src/runtime/http-types.ts +23 -1
- package/src/runtime/interactive-ui.ts +362 -0
- package/src/runtime/invite-instruction-generator.ts +2 -2
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
- package/src/runtime/migrations/gcs-signed-url.ts +162 -0
- package/src/runtime/migrations/vbundle-importer.ts +154 -9
- package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
- package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
- package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
- package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
- package/src/runtime/migrations/vbundle-validator.ts +15 -6
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
- package/src/runtime/routes/approval-routes.ts +12 -17
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
- package/src/runtime/routes/avatar-routes.ts +20 -4
- package/src/runtime/routes/btw-routes.ts +1 -4
- package/src/runtime/routes/conversation-management-routes.ts +20 -2
- package/src/runtime/routes/conversation-routes.ts +133 -27
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +6 -4
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/guardian-approval-interception.ts +33 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
- package/src/runtime/routes/home-feed-routes.ts +120 -2
- package/src/runtime/routes/inbound-message-handler.ts +912 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
- package/src/runtime/routes/integrations/slack/channel.ts +25 -3
- package/src/runtime/routes/llm-context-normalization.ts +23 -1
- package/src/runtime/routes/migration-routes.ts +720 -124
- package/src/runtime/routes/settings-routes.ts +4 -2
- package/src/runtime/routes/trust-rules-routes.ts +30 -14
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/routes/work-items-routes.ts +3 -2
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
- package/src/runtime/services/analyze-conversation.ts +12 -16
- package/src/runtime/skill-route-registry.ts +28 -6
- package/src/schedule/scheduler.ts +8 -0
- package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
- package/src/security/__tests__/untrusted-content.test.ts +109 -0
- package/src/security/oauth2.ts +98 -35
- package/src/security/secure-keys.ts +7 -8
- package/src/security/token-manager.ts +27 -13
- package/src/security/untrusted-content.ts +102 -0
- package/src/skills/catalog-cache.ts +26 -7
- package/src/skills/catalog-install.ts +31 -3
- package/src/skills/skill-cache-store.ts +97 -0
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
- package/src/stt/daemon-batch-transcriber.ts +33 -0
- package/src/stt/stt-stream-session.ts +8 -1
- package/src/stt/types.ts +5 -1
- package/src/subagent/manager.ts +41 -13
- package/src/tasks/ephemeral-permissions.ts +9 -4
- package/src/telemetry/usage-telemetry-reporter.ts +27 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
- package/src/tools/browser/browser-execution.ts +65 -38
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +9 -4
- package/src/tools/executor.ts +4 -0
- package/src/tools/filesystem/write.ts +52 -0
- package/src/tools/host-terminal/host-shell.ts +45 -5
- package/src/tools/memory/register.test.ts +185 -0
- package/src/tools/memory/register.ts +3 -1
- package/src/tools/network/web-fetch.ts +20 -10
- package/src/tools/network/web-search.ts +19 -4
- package/src/tools/permission-checker.ts +36 -15
- package/src/tools/policy-context.ts +25 -8
- package/src/tools/registry.ts +55 -3
- package/src/tools/side-effects.ts +0 -11
- package/src/tools/skills/execute.ts +2 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/terminal/backends/native.ts +51 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +1 -0
- package/src/tools/tool-manifest.ts +6 -21
- package/src/tools/types.ts +12 -3
- package/src/tools/verification-control-plane-policy.ts +1 -1
- package/src/tts/__tests__/provider-adapters.test.ts +240 -13
- package/src/tts/provider-catalog.ts +18 -0
- package/src/tts/providers/index.ts +2 -0
- package/src/tts/providers/xai-provider.ts +224 -0
- package/src/tts/types.ts +46 -0
- package/src/types/tar-stream.d.ts +66 -0
- package/src/util/json.ts +17 -0
- package/src/util/platform.ts +2 -2
- package/src/util/pricing.ts +15 -5
- package/src/watcher/engine.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +134 -8
- package/src/watcher/providers/outlook-calendar.ts +42 -2
- package/src/workspace/git-service.ts +23 -4
- package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
- package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
- package/src/__tests__/gmail-archive-gate.test.ts +0 -246
- package/src/__tests__/gmail-preferences.test.ts +0 -117
- package/src/__tests__/outlook-attachments.test.ts +0 -301
- package/src/__tests__/outlook-automation-tools.test.ts +0 -425
- package/src/__tests__/outlook-categories.test.ts +0 -212
- package/src/__tests__/outlook-compose-tools.test.ts +0 -325
- package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
- package/src/__tests__/outlook-follow-up.test.ts +0 -196
- package/src/__tests__/outlook-trash.test.ts +0 -77
- package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
- package/src/__tests__/update-bulletin-format.test.ts +0 -181
- package/src/__tests__/update-bulletin-state.test.ts +0 -135
- package/src/__tests__/update-bulletin.test.ts +0 -478
- package/src/__tests__/update-template-contract.test.ts +0 -29
- package/src/cli/commands/doctor.ts +0 -341
- package/src/config/bundled-skills/browser/SKILL.md +0 -88
- package/src/config/bundled-skills/browser/TOOLS.json +0 -516
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
- package/src/config/bundled-skills/gmail/SKILL.md +0 -221
- package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
- package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
- package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
- package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/google-calendar/types.ts +0 -97
- package/src/config/bundled-skills/outlook/SKILL.md +0 -196
- package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
- package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
- package/src/config/bundled-skills/slack/SKILL.md +0 -108
- package/src/config/bundled-skills/tasks/SKILL.md +0 -37
- package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
- package/src/config/bundled-skills/tasks/icon.svg +0 -34
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
- package/src/config/bundled-skills/watcher/SKILL.md +0 -31
- package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
- package/src/prompts/templates/UPDATES.md +0 -50
- package/src/prompts/update-bulletin-format.ts +0 -85
- package/src/prompts/update-bulletin-state.ts +0 -58
- package/src/prompts/update-bulletin-template-path.ts +0 -13
- package/src/prompts/update-bulletin.ts +0 -139
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/tools/watcher/create.ts +0 -86
- package/src/tools/watcher/delete.ts +0 -36
- package/src/tools/watcher/digest.ts +0 -54
- package/src/tools/watcher/list.ts +0 -83
- package/src/tools/watcher/update.ts +0 -71
|
@@ -24,7 +24,7 @@ import type {
|
|
|
24
24
|
} from "../channels/types.js";
|
|
25
25
|
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
26
26
|
import { getConfig } from "../config/loader.js";
|
|
27
|
-
import type { Speed } from "../config/schemas/
|
|
27
|
+
import type { LLMCallSite, Speed } from "../config/schemas/llm.js";
|
|
28
28
|
import {
|
|
29
29
|
ContextWindowManager,
|
|
30
30
|
type ContextWindowResult,
|
|
@@ -47,6 +47,7 @@ import { getHookManager } from "../hooks/manager.js";
|
|
|
47
47
|
import { enqueueAutoAnalysisOnCompaction } from "../memory/auto-analysis-enqueue.js";
|
|
48
48
|
import { resolveCanonicalGuardianRequest } from "../memory/canonical-guardian-store.js";
|
|
49
49
|
import {
|
|
50
|
+
getConversationOriginChannel,
|
|
50
51
|
updateConversationContextWindow,
|
|
51
52
|
updateConversationHostAccess,
|
|
52
53
|
} from "../memory/conversation-crud.js";
|
|
@@ -62,19 +63,22 @@ import {
|
|
|
62
63
|
} from "../permissions/v2-consent-policy.js";
|
|
63
64
|
import { resolvePersonaContext } from "../prompts/persona-resolver.js";
|
|
64
65
|
import { buildSystemPrompt } from "../prompts/system-prompt.js";
|
|
65
|
-
import {
|
|
66
|
-
import type { Message, ModelIntent } from "../providers/types.js";
|
|
66
|
+
import type { Message } from "../providers/types.js";
|
|
67
67
|
import type { Provider } from "../providers/types.js";
|
|
68
68
|
import type { TrustClass } from "../runtime/actor-trust-resolver.js";
|
|
69
69
|
import type { AuthContext } from "../runtime/auth/types.js";
|
|
70
70
|
import * as approvalOverrides from "../runtime/conversation-approval-overrides.js";
|
|
71
|
+
import type { InteractiveUiResult } from "../runtime/interactive-ui.js";
|
|
71
72
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
72
73
|
import { ToolExecutor } from "../tools/executor.js";
|
|
73
74
|
import type { OnboardingContext } from "../types/onboarding-context.js";
|
|
74
75
|
import type { AbortReason } from "../util/abort-reasons.js";
|
|
75
76
|
import { getLogger } from "../util/logger.js";
|
|
76
77
|
import type { AssistantAttachmentDraft } from "./assistant-attachments.js";
|
|
77
|
-
import {
|
|
78
|
+
import {
|
|
79
|
+
runAgentLoopImpl,
|
|
80
|
+
trackCompactionOutcome,
|
|
81
|
+
} from "./conversation-agent-loop.js";
|
|
78
82
|
import type { HistoryConversationContext } from "./conversation-history.js";
|
|
79
83
|
import {
|
|
80
84
|
regenerate as regenerateImpl,
|
|
@@ -190,6 +194,19 @@ export class Conversation {
|
|
|
190
194
|
/** @internal */ contextWindowManager: ContextWindowManager;
|
|
191
195
|
/** @internal */ contextCompactedMessageCount = 0;
|
|
192
196
|
/** @internal */ contextCompactedAt: number | null = null;
|
|
197
|
+
/**
|
|
198
|
+
* Tracks consecutive compaction failures (summary LLM call threw). In-memory
|
|
199
|
+
* only — resets to 0 on process restart, which is the intended "one free
|
|
200
|
+
* retry after restart" behavior. Reset to 0 on any successful compaction.
|
|
201
|
+
*/
|
|
202
|
+
/** @internal */ consecutiveCompactionFailures = 0;
|
|
203
|
+
/**
|
|
204
|
+
* When the circuit breaker is open, this timestamp (ms since epoch) marks
|
|
205
|
+
* when auto-compaction is allowed to resume. Set to `Date.now() + 1h` after
|
|
206
|
+
* 3 consecutive failures; cleared on a successful compaction. User-initiated
|
|
207
|
+
* compaction (`force: true`) bypasses the breaker regardless.
|
|
208
|
+
*/
|
|
209
|
+
/** @internal */ compactionCircuitOpenUntil: number | null = null;
|
|
193
210
|
/** @internal */ currentRequestId?: string;
|
|
194
211
|
/** @internal */ hasNoClient = false;
|
|
195
212
|
/** @internal */ isSubagent = false;
|
|
@@ -238,6 +255,7 @@ export class Conversation {
|
|
|
238
255
|
languageCode?: string;
|
|
239
256
|
};
|
|
240
257
|
/** @internal */ surfaceActionRequestIds = new Set<string>();
|
|
258
|
+
/** @internal */ approvedViaPromptThisTurn = false;
|
|
241
259
|
/** @internal */ pendingSurfaceActions = new Map<
|
|
242
260
|
string,
|
|
243
261
|
{ surfaceType: SurfaceType }
|
|
@@ -265,6 +283,28 @@ export class Conversation {
|
|
|
265
283
|
string,
|
|
266
284
|
Record<string, unknown>
|
|
267
285
|
>();
|
|
286
|
+
/**
|
|
287
|
+
* Pending standalone UI requests keyed by surfaceId.
|
|
288
|
+
* Daemon-driven surfaces that block the caller until user response or timeout.
|
|
289
|
+
* @internal
|
|
290
|
+
*/
|
|
291
|
+
pendingStandaloneSurfaces = new Map<
|
|
292
|
+
string,
|
|
293
|
+
{
|
|
294
|
+
resolve: (result: InteractiveUiResult) => void;
|
|
295
|
+
timer: ReturnType<typeof setTimeout>;
|
|
296
|
+
surfaceType: SurfaceType;
|
|
297
|
+
}
|
|
298
|
+
>();
|
|
299
|
+
/**
|
|
300
|
+
* Short-lived tombstone set of recently-completed standalone surface IDs.
|
|
301
|
+
* Prevents late client actions from falling through to the LLM path.
|
|
302
|
+
* @internal
|
|
303
|
+
*/
|
|
304
|
+
recentlyCompletedStandaloneSurfaces = new Map<
|
|
305
|
+
string,
|
|
306
|
+
ReturnType<typeof setTimeout>
|
|
307
|
+
>();
|
|
268
308
|
/** @internal */ broadcastToAllClients?: (msg: ServerMessage) => void;
|
|
269
309
|
/** @internal */ withSurface = createSurfaceMutex();
|
|
270
310
|
/** @internal */ currentTurnSurfaces: Array<{
|
|
@@ -338,7 +378,6 @@ export class Conversation {
|
|
|
338
378
|
sharedCesClient?: CesClient,
|
|
339
379
|
speedOverride?: Speed,
|
|
340
380
|
cacheTtl?: "5m" | "1h",
|
|
341
|
-
modelIntent?: ModelIntent,
|
|
342
381
|
modelOverride?: string,
|
|
343
382
|
) {
|
|
344
383
|
this.conversationId = conversationId;
|
|
@@ -386,7 +425,10 @@ export class Conversation {
|
|
|
386
425
|
);
|
|
387
426
|
}
|
|
388
427
|
});
|
|
389
|
-
this.secretPrompter = new SecretPrompter(
|
|
428
|
+
this.secretPrompter = new SecretPrompter(
|
|
429
|
+
sendToClient,
|
|
430
|
+
broadcastToAllClients,
|
|
431
|
+
);
|
|
390
432
|
|
|
391
433
|
// Register watch/call notifiers (reads ctx properties lazily)
|
|
392
434
|
registerConversationNotifiers(conversationId, this);
|
|
@@ -424,7 +466,7 @@ export class Conversation {
|
|
|
424
466
|
);
|
|
425
467
|
|
|
426
468
|
const config = getConfig();
|
|
427
|
-
this.streamThinking = config.thinking.streamThinking ?? false;
|
|
469
|
+
this.streamThinking = config.llm.default.thinking.streamThinking ?? false;
|
|
428
470
|
|
|
429
471
|
// CES (Credential Execution Service) — use the shared server-level client.
|
|
430
472
|
// The CES sidecar accepts exactly one bootstrap connection, so the
|
|
@@ -441,13 +483,10 @@ export class Conversation {
|
|
|
441
483
|
const hasSystemPromptOverride = systemPrompt !== buildSystemPrompt();
|
|
442
484
|
this.hasSystemPromptOverride = hasSystemPromptOverride;
|
|
443
485
|
|
|
444
|
-
// If an explicit modelOverride is supplied, use it verbatim. Otherwise
|
|
445
|
-
//
|
|
446
|
-
//
|
|
447
|
-
|
|
448
|
-
const resolvedModel: string | undefined =
|
|
449
|
-
modelOverride ??
|
|
450
|
-
(modelIntent ? resolveModelIntent(provider.name, modelIntent) : undefined);
|
|
486
|
+
// If an explicit modelOverride is supplied, use it verbatim. Otherwise
|
|
487
|
+
// leave the model unset and let `RetryProvider`'s call-site resolver pick
|
|
488
|
+
// it up from `llm.default` / `llm.callSites.<id>` on every turn.
|
|
489
|
+
const resolvedModel: string | undefined = modelOverride;
|
|
451
490
|
|
|
452
491
|
const resolveSystemPromptCallback = (
|
|
453
492
|
_history: import("../providers/types.js").Message[],
|
|
@@ -477,16 +516,17 @@ export class Conversation {
|
|
|
477
516
|
};
|
|
478
517
|
|
|
479
518
|
const fastModeEnabled = isAssistantFeatureFlagEnabled("fast-mode", config);
|
|
480
|
-
const resolvedSpeed = speedOverride ?? config.speed;
|
|
519
|
+
const resolvedSpeed = speedOverride ?? config.llm.default.speed;
|
|
520
|
+
const llmDefault = config.llm.default;
|
|
481
521
|
|
|
482
522
|
this.agentLoop = new AgentLoop(
|
|
483
523
|
provider,
|
|
484
524
|
systemPrompt,
|
|
485
525
|
{
|
|
486
526
|
maxTokens,
|
|
487
|
-
maxInputTokens:
|
|
488
|
-
thinking:
|
|
489
|
-
effort:
|
|
527
|
+
maxInputTokens: llmDefault.contextWindow.maxInputTokens,
|
|
528
|
+
thinking: llmDefault.thinking,
|
|
529
|
+
effort: llmDefault.effort,
|
|
490
530
|
...(fastModeEnabled && resolvedSpeed === "fast"
|
|
491
531
|
? { speed: resolvedSpeed }
|
|
492
532
|
: {}),
|
|
@@ -500,7 +540,7 @@ export class Conversation {
|
|
|
500
540
|
this.contextWindowManager = new ContextWindowManager({
|
|
501
541
|
provider,
|
|
502
542
|
systemPrompt: () => resolveSystemPromptCallback([]).systemPrompt,
|
|
503
|
-
config:
|
|
543
|
+
config: llmDefault.contextWindow,
|
|
504
544
|
toolTokenBudget: this.agentLoop.getToolTokenBudget(),
|
|
505
545
|
});
|
|
506
546
|
|
|
@@ -724,6 +764,35 @@ export class Conversation {
|
|
|
724
764
|
|
|
725
765
|
dispose(): void {
|
|
726
766
|
approvalOverrides.clearMode(this.conversationId);
|
|
767
|
+
// Cancel all pending standalone surfaces so callers get a clean
|
|
768
|
+
// cancellation instead of hanging forever. Emit dismiss notifications
|
|
769
|
+
// to the client so surfaces don't remain visually active if the client
|
|
770
|
+
// reconnects after dispose.
|
|
771
|
+
const emitDispose =
|
|
772
|
+
this.broadcastToAllClients ?? this.sendToClient.bind(this);
|
|
773
|
+
for (const [surfaceId, entry] of this.pendingStandaloneSurfaces) {
|
|
774
|
+
clearTimeout(entry.timer);
|
|
775
|
+
try {
|
|
776
|
+
emitDispose({
|
|
777
|
+
type: "ui_surface_dismiss",
|
|
778
|
+
conversationId: this.conversationId,
|
|
779
|
+
surfaceId,
|
|
780
|
+
});
|
|
781
|
+
} catch {
|
|
782
|
+
// Best-effort: the client may already be disconnected during dispose.
|
|
783
|
+
}
|
|
784
|
+
entry.resolve({
|
|
785
|
+
status: "cancelled",
|
|
786
|
+
surfaceId,
|
|
787
|
+
cancellationReason: "resolver_unavailable",
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
this.pendingStandaloneSurfaces.clear();
|
|
791
|
+
// Clear tombstone timers to prevent dangling references after dispose.
|
|
792
|
+
for (const timer of this.recentlyCompletedStandaloneSurfaces.values()) {
|
|
793
|
+
clearTimeout(timer);
|
|
794
|
+
}
|
|
795
|
+
this.recentlyCompletedStandaloneSurfaces.clear();
|
|
727
796
|
this.hostBashProxy?.dispose();
|
|
728
797
|
this.hostBrowserProxy?.dispose();
|
|
729
798
|
this.hostCuProxy?.dispose();
|
|
@@ -762,6 +831,7 @@ export class Conversation {
|
|
|
762
831
|
options?: { isInteractive?: boolean },
|
|
763
832
|
displayContent?: string,
|
|
764
833
|
transport?: ConversationTransportMetadata,
|
|
834
|
+
clientMessageId?: string,
|
|
765
835
|
): { queued: boolean; requestId: string; rejected?: boolean } {
|
|
766
836
|
return enqueueMessageImpl(
|
|
767
837
|
this,
|
|
@@ -775,6 +845,7 @@ export class Conversation {
|
|
|
775
845
|
options,
|
|
776
846
|
displayContent,
|
|
777
847
|
transport,
|
|
848
|
+
clientMessageId,
|
|
778
849
|
);
|
|
779
850
|
}
|
|
780
851
|
|
|
@@ -927,7 +998,7 @@ export class Conversation {
|
|
|
927
998
|
* confirmations in the same conversation that match the decision.
|
|
928
999
|
*
|
|
929
1000
|
* - allow_10m / allow_conversation → approve ALL pending in conversation
|
|
930
|
-
* - always_allow
|
|
1001
|
+
* - always_allow → approve pattern-matching pending
|
|
931
1002
|
* - always_deny → deny pattern-matching pending
|
|
932
1003
|
* - allow / deny (one-time) → no cascading
|
|
933
1004
|
*/
|
|
@@ -1021,14 +1092,9 @@ export class Conversation {
|
|
|
1021
1092
|
}
|
|
1022
1093
|
|
|
1023
1094
|
// Persistent allow: cascade if the pattern matches any allowlist candidate.
|
|
1024
|
-
// "always_allow" must NOT cascade to high-risk pending confirmations
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
(decision === "always_allow" || decision === "always_allow_high_risk") &&
|
|
1028
|
-
selectedPattern &&
|
|
1029
|
-
details
|
|
1030
|
-
) {
|
|
1031
|
-
if (decision === "always_allow" && details.riskLevel === "high") {
|
|
1095
|
+
// "always_allow" must NOT cascade to high-risk pending confirmations.
|
|
1096
|
+
if (decision === "always_allow" && selectedPattern && details) {
|
|
1097
|
+
if (details.riskLevel === "high") {
|
|
1032
1098
|
return null;
|
|
1033
1099
|
}
|
|
1034
1100
|
for (const option of details.allowlistOptions) {
|
|
@@ -1170,8 +1236,21 @@ export class Conversation {
|
|
|
1170
1236
|
const result = await this.contextWindowManager.maybeCompact(
|
|
1171
1237
|
this.messages,
|
|
1172
1238
|
this.abortController?.signal ?? undefined,
|
|
1173
|
-
{
|
|
1239
|
+
{
|
|
1240
|
+
force: true,
|
|
1241
|
+
lastCompactedAt: this.contextCompactedAt ?? undefined,
|
|
1242
|
+
conversationOriginChannel:
|
|
1243
|
+
getConversationOriginChannel(this.conversationId) ?? undefined,
|
|
1244
|
+
},
|
|
1174
1245
|
);
|
|
1246
|
+
// Track circuit-breaker state for user-initiated `/compact` and other
|
|
1247
|
+
// forced paths so a successful forced compaction clears a stuck counter
|
|
1248
|
+
// and a run of forced failures still trips the breaker. `summaryFailed`
|
|
1249
|
+
// is `undefined` on early-return paths (no eligible messages, disabled,
|
|
1250
|
+
// etc.) — skip those so they don't silently reset the counter.
|
|
1251
|
+
if (result.summaryFailed !== undefined) {
|
|
1252
|
+
trackCompactionOutcome(this, result.summaryFailed, this.sendToClient);
|
|
1253
|
+
}
|
|
1175
1254
|
if (result.compacted) {
|
|
1176
1255
|
this.messages = result.messages;
|
|
1177
1256
|
this.contextCompactedMessageCount += result.compactedPersistedMessages;
|
|
@@ -1194,6 +1273,14 @@ export class Conversation {
|
|
|
1194
1273
|
|
|
1195
1274
|
setChannelCapabilities(caps: ChannelCapabilities | null): void {
|
|
1196
1275
|
this.channelCapabilities = caps ?? undefined;
|
|
1276
|
+
this.secretPrompter.setChannelContext(
|
|
1277
|
+
caps
|
|
1278
|
+
? {
|
|
1279
|
+
channel: caps.channel,
|
|
1280
|
+
supportsDynamicUi: caps.supportsDynamicUi,
|
|
1281
|
+
}
|
|
1282
|
+
: undefined,
|
|
1283
|
+
);
|
|
1197
1284
|
}
|
|
1198
1285
|
|
|
1199
1286
|
setTrustContext(ctx: TrustContext | null): void {
|
|
@@ -1333,6 +1420,7 @@ export class Conversation {
|
|
|
1333
1420
|
isInteractive?: boolean;
|
|
1334
1421
|
isUserMessage?: boolean;
|
|
1335
1422
|
titleText?: string;
|
|
1423
|
+
callSite?: LLMCallSite;
|
|
1336
1424
|
},
|
|
1337
1425
|
): Promise<void> {
|
|
1338
1426
|
return runAgentLoopImpl(this, content, userMessageId, onEvent, options);
|
|
@@ -1349,7 +1437,7 @@ export class Conversation {
|
|
|
1349
1437
|
requestId?: string,
|
|
1350
1438
|
activeSurfaceId?: string,
|
|
1351
1439
|
currentPage?: string,
|
|
1352
|
-
options?: { isInteractive?: boolean },
|
|
1440
|
+
options?: { isInteractive?: boolean; callSite?: LLMCallSite },
|
|
1353
1441
|
displayContent?: string,
|
|
1354
1442
|
): Promise<string> {
|
|
1355
1443
|
return processMessageImpl(
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External skill bootstrap.
|
|
3
|
+
*
|
|
4
|
+
* Loads first-party skills that expose **in-process tools** to the daemon.
|
|
5
|
+
* Importing this module triggers each skill's `register.ts` to run, which
|
|
6
|
+
* in turn calls `registerExternalTools()` on the assistant-side tool
|
|
7
|
+
* registry. The daemon's `initializeTools()` then picks the registered
|
|
8
|
+
* tools up and makes them available to the LLM.
|
|
9
|
+
*
|
|
10
|
+
* ## Why the cross-directory import exists
|
|
11
|
+
*
|
|
12
|
+
* `CLAUDE.md` and `skills/meet-join/AGENTS.md` establish a general rule
|
|
13
|
+
* that `assistant/` must not import from `skills/` via relative paths so
|
|
14
|
+
* that skills stay portable and extractable. For in-process tools this
|
|
15
|
+
* creates a chicken-and-egg problem: skills need their `register.ts` to
|
|
16
|
+
* execute before `initializeTools()` runs, but in a `bun --compile`
|
|
17
|
+
* binary only statically analyzed imports end up in the bundle, and
|
|
18
|
+
* dynamic imports with variable paths fail inside `/$bunfs/`.
|
|
19
|
+
*
|
|
20
|
+
* We resolve the tension by:
|
|
21
|
+
*
|
|
22
|
+
* 1. Keeping this file as the **one** place in `assistant/` that
|
|
23
|
+
* reaches into `skills/`. Every other import direction (skill ->
|
|
24
|
+
* assistant) remains legal and intentional.
|
|
25
|
+
* 2. Limiting entries to **first-party bundled skills** whose source
|
|
26
|
+
* is shipped in the Docker build context and statically compiled
|
|
27
|
+
* into the Bun binary. The repo-root `.dockerignore` is the
|
|
28
|
+
* allowlist that determines which skill files enter the build
|
|
29
|
+
* context; the assistant `Dockerfile` copies `skills/` generically.
|
|
30
|
+
* 3. Keeping the imports as **side-effect only** so the skill owns
|
|
31
|
+
* both the tool list and the feature-flag semantics — this file
|
|
32
|
+
* just wires module evaluation into the startup path.
|
|
33
|
+
*
|
|
34
|
+
* When a new bundled first-party skill wants to expose in-process tools
|
|
35
|
+
* to the LLM, add another side-effect import here and extend the
|
|
36
|
+
* repo-root `.dockerignore` allowlist with the skill's runtime files.
|
|
37
|
+
* Non-bundled skills (workspace-installed, third-party) never belong in
|
|
38
|
+
* this file.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import "../../../skills/meet-join/register.js";
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CallSiteRoutingProvider } from "../providers/call-site-routing.js";
|
|
2
|
+
import { getConfiguredProvider } from "../providers/provider-send-message.js";
|
|
2
3
|
import { getProvider } from "../providers/registry.js";
|
|
4
|
+
import type { Provider } from "../providers/types.js";
|
|
3
5
|
import {
|
|
4
6
|
buildGuardianActionGenerationPrompt,
|
|
5
7
|
getGuardianActionFallbackMessage,
|
|
@@ -18,21 +20,20 @@ import type {
|
|
|
18
20
|
/**
|
|
19
21
|
* Create the daemon-owned guardian action copy generator that resolves
|
|
20
22
|
* providers and calls `provider.sendMessage` to generate guardian action
|
|
21
|
-
* copy text. Uses `
|
|
22
|
-
*
|
|
23
|
+
* copy text. Uses the `guardianQuestionCopy` call site so model selection
|
|
24
|
+
* tracks the unified `llm.callSites` configuration.
|
|
23
25
|
*
|
|
24
26
|
* This keeps all provider awareness in the daemon lifecycle, away from
|
|
25
27
|
* the runtime composer.
|
|
26
28
|
*/
|
|
27
29
|
export function createGuardianActionCopyGenerator(): GuardianActionCopyGenerator {
|
|
28
30
|
return async (context, options = {}) => {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
31
|
+
const baseProvider = await getConfiguredProvider("guardianQuestionCopy");
|
|
32
|
+
if (!baseProvider) return null;
|
|
33
|
+
// Wrap so the per-call `callSite` can route to a different provider
|
|
34
|
+
// transport when `llm.callSites.guardianQuestionCopy.provider` overrides
|
|
35
|
+
// the default. Without this, callSite only affects request metadata.
|
|
36
|
+
const provider = wrapWithCallSiteRouting(baseProvider);
|
|
36
37
|
|
|
37
38
|
const fallbackText =
|
|
38
39
|
options.fallbackText?.trim() || getGuardianActionFallbackMessage(context);
|
|
@@ -52,7 +53,7 @@ export function createGuardianActionCopyGenerator(): GuardianActionCopyGenerator
|
|
|
52
53
|
{
|
|
53
54
|
config: {
|
|
54
55
|
max_tokens: options.maxTokens ?? GUARDIAN_ACTION_COPY_MAX_TOKENS,
|
|
55
|
-
|
|
56
|
+
callSite: "guardianQuestionCopy",
|
|
56
57
|
},
|
|
57
58
|
signal: AbortSignal.timeout(
|
|
58
59
|
options.timeoutMs ?? GUARDIAN_ACTION_COPY_TIMEOUT_MS,
|
|
@@ -130,8 +131,11 @@ const VALID_FOLLOWUP_DISPOSITIONS: ReadonlySet<string> = new Set([
|
|
|
130
131
|
*/
|
|
131
132
|
export function createGuardianFollowUpConversationGenerator(): GuardianFollowUpConversationGenerator {
|
|
132
133
|
return async (context) => {
|
|
133
|
-
const
|
|
134
|
-
|
|
134
|
+
const baseProvider = await getConfiguredProvider("guardianQuestionCopy");
|
|
135
|
+
if (!baseProvider) {
|
|
136
|
+
throw new Error("No configured provider available for follow-up conversation");
|
|
137
|
+
}
|
|
138
|
+
const provider = wrapWithCallSiteRouting(baseProvider);
|
|
135
139
|
|
|
136
140
|
const userPrompt = [
|
|
137
141
|
`Original question from the voice call: "${context.questionText}"`,
|
|
@@ -146,7 +150,7 @@ export function createGuardianFollowUpConversationGenerator(): GuardianFollowUpC
|
|
|
146
150
|
{
|
|
147
151
|
config: {
|
|
148
152
|
max_tokens: FOLLOWUP_CONVERSATION_MAX_TOKENS,
|
|
149
|
-
|
|
153
|
+
callSite: "guardianQuestionCopy",
|
|
150
154
|
},
|
|
151
155
|
signal: AbortSignal.timeout(FOLLOWUP_CONVERSATION_TIMEOUT_MS),
|
|
152
156
|
},
|
|
@@ -188,3 +192,19 @@ export function createGuardianFollowUpConversationGenerator(): GuardianFollowUpC
|
|
|
188
192
|
return result;
|
|
189
193
|
};
|
|
190
194
|
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Wrap a base Provider so per-call `callSite` metadata can route the actual
|
|
198
|
+
* transport to a different provider when `llm.callSites.<id>.provider`
|
|
199
|
+
* differs from the default. Without this wrapper, only request metadata
|
|
200
|
+
* reflects the callSite — the HTTP transport stays bound to the default.
|
|
201
|
+
*/
|
|
202
|
+
function wrapWithCallSiteRouting(base: Provider): Provider {
|
|
203
|
+
return new CallSiteRoutingProvider(base, (name) => {
|
|
204
|
+
try {
|
|
205
|
+
return getProvider(name);
|
|
206
|
+
} catch {
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { PROVIDER_CATALOG } from "../../providers/model-catalog.js";
|
|
4
|
+
import { projectProviderForWire } from "./config-model.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Regression guard for the wire contract declared in
|
|
8
|
+
* `daemon/message-types/conversations.ts#ModelInfo.allProviders`. The
|
|
9
|
+
* daemon's `PROVIDER_CATALOG` carries richer metadata (capability flags,
|
|
10
|
+
* pricing, subtitle, setupMode, setupHint, envVar, credentialsGuide), but
|
|
11
|
+
* clients source that metadata from the bundled `LLMProviderRegistry`
|
|
12
|
+
* JSON, so only the legacy fields belong on the wire. The Swift generated
|
|
13
|
+
* DTO declares the same legacy-only shape and silently discards any
|
|
14
|
+
* extras — this test keeps the daemon honest about what it sends.
|
|
15
|
+
*/
|
|
16
|
+
describe("projectProviderForWire", () => {
|
|
17
|
+
const LEGACY_WIRE_KEYS = new Set([
|
|
18
|
+
"id",
|
|
19
|
+
"displayName",
|
|
20
|
+
"models",
|
|
21
|
+
"defaultModel",
|
|
22
|
+
"apiKeyUrl",
|
|
23
|
+
"apiKeyPlaceholder",
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
test("drops rich catalog fields (subtitle, setupMode, envVar, credentialsGuide, setupHint)", () => {
|
|
27
|
+
for (const entry of PROVIDER_CATALOG) {
|
|
28
|
+
const wire = projectProviderForWire(entry);
|
|
29
|
+
const keys = Object.keys(wire);
|
|
30
|
+
for (const key of keys) {
|
|
31
|
+
expect(LEGACY_WIRE_KEYS.has(key)).toBe(true);
|
|
32
|
+
}
|
|
33
|
+
expect(keys).not.toContain("subtitle");
|
|
34
|
+
expect(keys).not.toContain("setupMode");
|
|
35
|
+
expect(keys).not.toContain("setupHint");
|
|
36
|
+
expect(keys).not.toContain("envVar");
|
|
37
|
+
expect(keys).not.toContain("credentialsGuide");
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("drops rich CatalogModel fields (capability flags, pricing, context windows)", () => {
|
|
42
|
+
for (const entry of PROVIDER_CATALOG) {
|
|
43
|
+
const wire = projectProviderForWire(entry);
|
|
44
|
+
for (const model of wire.models) {
|
|
45
|
+
expect(Object.keys(model).sort()).toEqual(["displayName", "id"]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("preserves legacy wire fields exactly", () => {
|
|
51
|
+
const anthropic = PROVIDER_CATALOG.find((p) => p.id === "anthropic");
|
|
52
|
+
expect(anthropic).toBeDefined();
|
|
53
|
+
const wire = projectProviderForWire(anthropic!);
|
|
54
|
+
expect(wire.id).toBe(anthropic!.id);
|
|
55
|
+
expect(wire.displayName).toBe(anthropic!.displayName);
|
|
56
|
+
expect(wire.defaultModel).toBe(anthropic!.defaultModel);
|
|
57
|
+
expect(wire.apiKeyUrl).toBe(anthropic!.apiKeyUrl);
|
|
58
|
+
expect(wire.apiKeyPlaceholder).toBe(anthropic!.apiKeyPlaceholder);
|
|
59
|
+
expect(wire.models.length).toBe(anthropic!.models.length);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("omits apiKeyUrl/apiKeyPlaceholder when source entry has none (keyless providers)", () => {
|
|
63
|
+
const ollama = PROVIDER_CATALOG.find((p) => p.id === "ollama");
|
|
64
|
+
expect(ollama).toBeDefined();
|
|
65
|
+
// Sanity-check the fixture: ollama is the keyless provider.
|
|
66
|
+
expect(ollama!.apiKeyUrl).toBeUndefined();
|
|
67
|
+
expect(ollama!.apiKeyPlaceholder).toBeUndefined();
|
|
68
|
+
|
|
69
|
+
const wire = projectProviderForWire(ollama!);
|
|
70
|
+
expect("apiKeyUrl" in wire).toBe(false);
|
|
71
|
+
expect("apiKeyPlaceholder" in wire).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("JSON round-trip exposes only the legacy wire keys", () => {
|
|
75
|
+
for (const entry of PROVIDER_CATALOG) {
|
|
76
|
+
const wire = projectProviderForWire(entry);
|
|
77
|
+
const serialized = JSON.parse(JSON.stringify(wire)) as Record<
|
|
78
|
+
string,
|
|
79
|
+
unknown
|
|
80
|
+
>;
|
|
81
|
+
for (const key of Object.keys(serialized)) {
|
|
82
|
+
expect(LEGACY_WIRE_KEYS.has(key)).toBe(true);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -3,7 +3,10 @@ import {
|
|
|
3
3
|
loadRawConfig,
|
|
4
4
|
saveRawConfig,
|
|
5
5
|
} from "../../config/loader.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
setLlmDefaultField,
|
|
8
|
+
setServiceField,
|
|
9
|
+
} from "../../config/raw-config-utils.js";
|
|
7
10
|
import { VALID_INFERENCE_PROVIDERS } from "../../config/schemas/services.js";
|
|
8
11
|
import type { ProviderCatalogEntry } from "../../providers/model-catalog.js";
|
|
9
12
|
import {
|
|
@@ -37,25 +40,64 @@ export const MODEL_TO_PROVIDER: Record<string, string> = Object.fromEntries(
|
|
|
37
40
|
// Shared business logic (transport-agnostic)
|
|
38
41
|
// ---------------------------------------------------------------------------
|
|
39
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Wire-contract shape for a provider entry in `ModelInfo.allProviders`.
|
|
45
|
+
* Mirrors the legacy fields declared in `message-types/conversations.ts` —
|
|
46
|
+
* rich provider metadata (capability flags, pricing, subtitle, setupMode,
|
|
47
|
+
* setupHint, envVar, credentialsGuide) is sourced by clients from the
|
|
48
|
+
* bundled `LLMProviderRegistry` JSON, so there is no reason to double-send
|
|
49
|
+
* it over the wire.
|
|
50
|
+
*/
|
|
51
|
+
export interface WireProviderEntry {
|
|
52
|
+
id: string;
|
|
53
|
+
displayName: string;
|
|
54
|
+
models: Array<{ id: string; displayName: string }>;
|
|
55
|
+
defaultModel: string;
|
|
56
|
+
apiKeyUrl?: string;
|
|
57
|
+
apiKeyPlaceholder?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
40
60
|
export interface ModelInfo {
|
|
41
61
|
model: string;
|
|
42
62
|
provider: string;
|
|
43
63
|
configuredProviders?: string[];
|
|
44
64
|
availableModels?: Array<{ id: string; displayName: string }>;
|
|
45
|
-
allProviders?:
|
|
65
|
+
allProviders?: WireProviderEntry[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Project a rich `ProviderCatalogEntry` to the legacy wire-contract fields.
|
|
70
|
+
* Keeping the wire payload honest avoids contract drift with
|
|
71
|
+
* `message-types/conversations.ts` and the generated Swift DTO.
|
|
72
|
+
*/
|
|
73
|
+
export function projectProviderForWire(
|
|
74
|
+
entry: ProviderCatalogEntry,
|
|
75
|
+
): WireProviderEntry {
|
|
76
|
+
return {
|
|
77
|
+
id: entry.id,
|
|
78
|
+
displayName: entry.displayName,
|
|
79
|
+
models: entry.models.map((m) => ({ id: m.id, displayName: m.displayName })),
|
|
80
|
+
defaultModel: entry.defaultModel,
|
|
81
|
+
...(entry.apiKeyUrl !== undefined && { apiKeyUrl: entry.apiKeyUrl }),
|
|
82
|
+
...(entry.apiKeyPlaceholder !== undefined && {
|
|
83
|
+
apiKeyPlaceholder: entry.apiKeyPlaceholder,
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
46
86
|
}
|
|
47
87
|
|
|
48
88
|
/** Return current model configuration. */
|
|
49
89
|
export async function getModelInfo(): Promise<ModelInfo> {
|
|
50
90
|
const config = getConfig();
|
|
51
|
-
const provider = config.
|
|
91
|
+
const provider = config.llm.default.provider;
|
|
52
92
|
|
|
53
93
|
return {
|
|
54
|
-
model: config.
|
|
94
|
+
model: config.llm.default.model,
|
|
55
95
|
provider,
|
|
56
96
|
configuredProviders: await getConfiguredProviders(),
|
|
57
|
-
availableModels: PROVIDER_CATALOG.find(
|
|
58
|
-
|
|
97
|
+
availableModels: PROVIDER_CATALOG.find(
|
|
98
|
+
(p) => p.id === provider,
|
|
99
|
+
)?.models?.map((m) => ({ id: m.id, displayName: m.displayName })),
|
|
100
|
+
allProviders: PROVIDER_CATALOG.map(projectProviderForWire),
|
|
59
101
|
};
|
|
60
102
|
}
|
|
61
103
|
|
|
@@ -102,12 +144,12 @@ export async function setModel(
|
|
|
102
144
|
const resolvedProvider =
|
|
103
145
|
explicitProvider ??
|
|
104
146
|
MODEL_TO_PROVIDER[modelId] ??
|
|
105
|
-
current.
|
|
147
|
+
current.llm.default.provider;
|
|
106
148
|
|
|
107
149
|
// Auto-reset model when provider changes and current modelId doesn't
|
|
108
150
|
// belong to the new provider's catalog.
|
|
109
151
|
if (
|
|
110
|
-
resolvedProvider !== current.
|
|
152
|
+
resolvedProvider !== current.llm.default.provider &&
|
|
111
153
|
!isModelInCatalog(resolvedProvider, modelId)
|
|
112
154
|
) {
|
|
113
155
|
modelId = getProviderDefaultModel(resolvedProvider);
|
|
@@ -115,8 +157,8 @@ export async function setModel(
|
|
|
115
157
|
|
|
116
158
|
// No-op guard: skip expensive reinitialization when nothing changed
|
|
117
159
|
if (
|
|
118
|
-
modelId === current.
|
|
119
|
-
resolvedProvider === current.
|
|
160
|
+
modelId === current.llm.default.model &&
|
|
161
|
+
resolvedProvider === current.llm.default.provider
|
|
120
162
|
) {
|
|
121
163
|
return await getModelInfo();
|
|
122
164
|
}
|
|
@@ -129,8 +171,8 @@ export async function setModel(
|
|
|
129
171
|
|
|
130
172
|
// Use raw config to avoid persisting env-var API keys to disk
|
|
131
173
|
const raw = loadRawConfig();
|
|
132
|
-
|
|
133
|
-
|
|
174
|
+
setLlmDefaultField(raw, "model", modelId);
|
|
175
|
+
setLlmDefaultField(raw, "provider", resolvedProvider);
|
|
134
176
|
|
|
135
177
|
// Suppress the file watcher callback — setModel already does
|
|
136
178
|
// the full reload sequence; a redundant watcher-triggered reload
|
|
@@ -148,12 +148,19 @@ export function handleConfirmationResponse(
|
|
|
148
148
|
// Route by requestId to the conversation that originated the prompt, not by
|
|
149
149
|
// the current conversation binding which may have changed since the
|
|
150
150
|
// request was issued (e.g. after a conversation switch).
|
|
151
|
+
// Normalize legacy decision: older clients may still send
|
|
152
|
+
// "always_allow_high_risk" via WebSocket for high-risk prompts.
|
|
153
|
+
const decision =
|
|
154
|
+
msg.decision === ("always_allow_high_risk" as typeof msg.decision)
|
|
155
|
+
? "always_allow"
|
|
156
|
+
: msg.decision;
|
|
157
|
+
|
|
151
158
|
for (const [conversationId, conversation] of ctx.conversations) {
|
|
152
159
|
if (conversation.hasPendingConfirmation(msg.requestId)) {
|
|
153
160
|
ctx.touchConversation(conversationId);
|
|
154
161
|
conversation.handleConfirmationResponse(
|
|
155
162
|
msg.requestId,
|
|
156
|
-
|
|
163
|
+
decision,
|
|
157
164
|
msg.selectedPattern,
|
|
158
165
|
msg.selectedScope,
|
|
159
166
|
undefined,
|
|
@@ -435,7 +442,7 @@ export function handleUsageRequest(
|
|
|
435
442
|
totalInputTokens: conversation.totalInputTokens,
|
|
436
443
|
totalOutputTokens: conversation.totalOutputTokens,
|
|
437
444
|
estimatedCost: conversation.totalEstimatedCost,
|
|
438
|
-
model: config.
|
|
445
|
+
model: config.llm.default.model,
|
|
439
446
|
});
|
|
440
447
|
}
|
|
441
448
|
|