@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
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { v4 as uuid } from "uuid";
|
|
2
2
|
|
|
3
3
|
import { getConfig } from "../../config/loader.js";
|
|
4
|
-
import type { Speed } from "../../config/schemas/
|
|
4
|
+
import type { LLMCallSite, Speed } from "../../config/schemas/llm.js";
|
|
5
5
|
import type { HeartbeatService } from "../../heartbeat/heartbeat-service.js";
|
|
6
6
|
import type { SecretPromptResult } from "../../permissions/secret-prompter.js";
|
|
7
|
-
import
|
|
7
|
+
import { isPlaceholderSentinelText } from "../../providers/anthropic/client.js";
|
|
8
8
|
import type { AuthContext } from "../../runtime/auth/types.js";
|
|
9
9
|
import type { DebouncerMap } from "../../util/debounce.js";
|
|
10
10
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -102,6 +102,22 @@ export interface RenderedHistoryContent {
|
|
|
102
102
|
thinkingSegments: string[];
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Slack-specific metadata extracted at the inbound HTTP boundary and threaded
|
|
107
|
+
* through to user-message persistence so the row can be tagged with a
|
|
108
|
+
* `slackMeta` envelope for the chronological renderer.
|
|
109
|
+
*/
|
|
110
|
+
export interface SlackInboundMessageMetadata {
|
|
111
|
+
/** Slack channel id (conversation external id) — recorded as `channelId`. */
|
|
112
|
+
channelId: string;
|
|
113
|
+
/** Slack `ts` for this message — required so persistence can record `channelTs`. */
|
|
114
|
+
channelTs: string;
|
|
115
|
+
/** Parent `thread_ts` when the message lives inside a thread; absent for top-level. */
|
|
116
|
+
threadTs?: string;
|
|
117
|
+
/** Resolved sender label (display name preferred, username fallback). */
|
|
118
|
+
displayName?: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
105
121
|
/**
|
|
106
122
|
* Optional overrides for conversation creation (e.g. interview mode).
|
|
107
123
|
*/
|
|
@@ -128,19 +144,26 @@ export interface ConversationCreateOptions {
|
|
|
128
144
|
commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
129
145
|
/** Optional callback to receive real-time agent loop events (text deltas, tool starts, etc.). */
|
|
130
146
|
onEvent?: (msg: ServerMessage) => void;
|
|
131
|
-
/**
|
|
132
|
-
* Optional model selection strategy for this conversation's agent loop.
|
|
133
|
-
* When set, overrides the provider's default model per-turn. Used by the
|
|
134
|
-
* auto-analyze loop to route the analysis agent to a dedicated model.
|
|
135
|
-
*/
|
|
136
|
-
modelIntent?: ModelIntent;
|
|
137
147
|
/**
|
|
138
148
|
* Optional explicit model override (provider/model string) for this
|
|
139
|
-
* conversation's agent loop.
|
|
140
|
-
*
|
|
141
|
-
* to a specific model.
|
|
149
|
+
* conversation's agent loop. Used by the auto-analyze loop to pin the
|
|
150
|
+
* analysis agent to a specific model.
|
|
142
151
|
*/
|
|
143
152
|
modelOverride?: string;
|
|
153
|
+
/**
|
|
154
|
+
* Optional LLM call-site identifier threaded through to the per-call
|
|
155
|
+
* provider config. Adapter callers (heartbeat, filing, schedule, etc.)
|
|
156
|
+
* pass their call-site here so the agent loop routes through
|
|
157
|
+
* `resolveCallSiteConfig` instead of the global default.
|
|
158
|
+
*/
|
|
159
|
+
callSite?: LLMCallSite;
|
|
160
|
+
/**
|
|
161
|
+
* Slack inbound metadata captured at the channel ingress boundary. When
|
|
162
|
+
* present (and the turn channel resolves to Slack), persistence writes a
|
|
163
|
+
* `slackMeta` sub-object into the message's `metadata` JSON for the
|
|
164
|
+
* chronological renderer to consume.
|
|
165
|
+
*/
|
|
166
|
+
slackInbound?: SlackInboundMessageMetadata;
|
|
144
167
|
}
|
|
145
168
|
|
|
146
169
|
/**
|
|
@@ -329,6 +352,11 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
|
|
|
329
352
|
// path — e.g. empty segments between consecutive tool_use blocks that
|
|
330
353
|
// break tool-call grouping in the UI.
|
|
331
354
|
if (block.text.trim().length === 0) continue;
|
|
355
|
+
// Drop Anthropic provider placeholder sentinels. These are injected
|
|
356
|
+
// into outbound API requests to preserve role alternation and must
|
|
357
|
+
// never be rendered to users. Belt-and-suspenders with the persist-
|
|
358
|
+
// time filter in cleanAssistantContent and migration 222.
|
|
359
|
+
if (isPlaceholderSentinelText(block.text)) continue;
|
|
332
360
|
textParts.push(block.text);
|
|
333
361
|
ensureSegment();
|
|
334
362
|
currentSegmentParts.push(block.text);
|
|
@@ -1517,7 +1517,7 @@ export async function draftSkill(
|
|
|
1517
1517
|
if (missing.length > 0) {
|
|
1518
1518
|
let llmGenerated = false;
|
|
1519
1519
|
try {
|
|
1520
|
-
const provider = await getConfiguredProvider();
|
|
1520
|
+
const provider = await getConfiguredProvider("skillCategoryInference");
|
|
1521
1521
|
if (provider) {
|
|
1522
1522
|
const { signal, cleanup } = createTimeout(LLM_DRAFT_TIMEOUT_MS);
|
|
1523
1523
|
try {
|
|
@@ -1539,7 +1539,7 @@ export async function draftSkill(
|
|
|
1539
1539
|
[],
|
|
1540
1540
|
undefined,
|
|
1541
1541
|
{
|
|
1542
|
-
config: {
|
|
1542
|
+
config: { callSite: "skillCategoryInference", max_tokens: 256 },
|
|
1543
1543
|
signal,
|
|
1544
1544
|
},
|
|
1545
1545
|
);
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs an OAuth2 loopback flow to install the user's Slack app and capture
|
|
3
|
+
* bot + user tokens in a single exchange.
|
|
4
|
+
*
|
|
5
|
+
* Prerequisites: client_id, client_secret, and app_token must already be
|
|
6
|
+
* stored in the credential vault (service: slack_channel).
|
|
7
|
+
*
|
|
8
|
+
* The handler reads client credentials from secure storage, starts a
|
|
9
|
+
* loopback OAuth server on port 17322, opens the browser to Slack's
|
|
10
|
+
* authorize URL, and waits for the user to click "Allow". Slack's
|
|
11
|
+
* oauth.v2.access response contains both the bot token (access_token)
|
|
12
|
+
* and user token (authed_user.access_token). Both are stored via
|
|
13
|
+
* setSlackChannelConfig.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { credentialKey } from "../../security/credential-key.js";
|
|
17
|
+
import { startOAuth2Flow } from "../../security/oauth2.js";
|
|
18
|
+
import { getSecureKeyAsync } from "../../security/secure-keys.js";
|
|
19
|
+
import { openInHostBrowser } from "../../util/browser.js";
|
|
20
|
+
import { getLogger } from "../../util/logger.js";
|
|
21
|
+
import { setSlackChannelConfig } from "./config-slack-channel.js";
|
|
22
|
+
|
|
23
|
+
const log = getLogger("slack-channel-oauth-install");
|
|
24
|
+
|
|
25
|
+
/** Port pre-registered for Slack in seed-providers.ts. */
|
|
26
|
+
const SLACK_LOOPBACK_PORT = 17322;
|
|
27
|
+
|
|
28
|
+
/** Bot scopes matching the manifest in SKILL.md. */
|
|
29
|
+
const BOT_SCOPES = [
|
|
30
|
+
"app_mentions:read",
|
|
31
|
+
"assistant:write",
|
|
32
|
+
"channels:history",
|
|
33
|
+
"channels:join",
|
|
34
|
+
"channels:read",
|
|
35
|
+
"chat:write",
|
|
36
|
+
"files:read",
|
|
37
|
+
"files:write",
|
|
38
|
+
"groups:history",
|
|
39
|
+
"groups:read",
|
|
40
|
+
"im:history",
|
|
41
|
+
"im:read",
|
|
42
|
+
"im:write",
|
|
43
|
+
"mpim:history",
|
|
44
|
+
"mpim:read",
|
|
45
|
+
"reactions:read",
|
|
46
|
+
"reactions:write",
|
|
47
|
+
"users:read",
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
/** User scopes matching the manifest in SKILL.md. */
|
|
51
|
+
const USER_SCOPES = [
|
|
52
|
+
"channels:history",
|
|
53
|
+
"channels:read",
|
|
54
|
+
"groups:history",
|
|
55
|
+
"groups:read",
|
|
56
|
+
"im:history",
|
|
57
|
+
"im:read",
|
|
58
|
+
"mpim:history",
|
|
59
|
+
"mpim:read",
|
|
60
|
+
"users:read",
|
|
61
|
+
"search:read",
|
|
62
|
+
"reactions:read",
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
export interface SlackOAuthInstallResult {
|
|
66
|
+
success: boolean;
|
|
67
|
+
hasBotToken: boolean;
|
|
68
|
+
hasUserToken: boolean;
|
|
69
|
+
error?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function runSlackChannelOAuthInstall(): Promise<SlackOAuthInstallResult> {
|
|
73
|
+
// Read client credentials from secure storage
|
|
74
|
+
const clientId = await getSecureKeyAsync(
|
|
75
|
+
credentialKey("slack_channel", "client_id"),
|
|
76
|
+
);
|
|
77
|
+
if (!clientId) {
|
|
78
|
+
return {
|
|
79
|
+
success: false,
|
|
80
|
+
hasBotToken: false,
|
|
81
|
+
hasUserToken: false,
|
|
82
|
+
error:
|
|
83
|
+
"Client ID not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: client_id).",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const clientSecret = await getSecureKeyAsync(
|
|
88
|
+
credentialKey("slack_channel", "client_secret"),
|
|
89
|
+
);
|
|
90
|
+
if (!clientSecret) {
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
hasBotToken: false,
|
|
94
|
+
hasUserToken: false,
|
|
95
|
+
error:
|
|
96
|
+
"Client Secret not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: client_secret).",
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const appToken = await getSecureKeyAsync(
|
|
101
|
+
credentialKey("slack_channel", "app_token"),
|
|
102
|
+
);
|
|
103
|
+
if (!appToken) {
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
hasBotToken: false,
|
|
107
|
+
hasUserToken: false,
|
|
108
|
+
error:
|
|
109
|
+
"App Token not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: app_token).",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
log.info("Starting Slack OAuth install flow via loopback");
|
|
114
|
+
|
|
115
|
+
let result;
|
|
116
|
+
try {
|
|
117
|
+
result = await startOAuth2Flow(
|
|
118
|
+
{
|
|
119
|
+
authorizeUrl: "https://slack.com/oauth/v2/authorize",
|
|
120
|
+
tokenExchangeUrl: "https://slack.com/api/oauth.v2.access",
|
|
121
|
+
scopes: BOT_SCOPES,
|
|
122
|
+
clientId,
|
|
123
|
+
clientSecret,
|
|
124
|
+
scopeSeparator: ",",
|
|
125
|
+
authorizeParams: {
|
|
126
|
+
user_scope: USER_SCOPES.join(","),
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
openUrl: (url) => openInHostBrowser(url),
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
callbackTransport: "loopback",
|
|
134
|
+
loopbackPort: SLACK_LOOPBACK_PORT,
|
|
135
|
+
},
|
|
136
|
+
);
|
|
137
|
+
} catch (err) {
|
|
138
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
139
|
+
log.error({ err: msg }, "Slack OAuth install flow failed");
|
|
140
|
+
return {
|
|
141
|
+
success: false,
|
|
142
|
+
hasBotToken: false,
|
|
143
|
+
hasUserToken: false,
|
|
144
|
+
error: `OAuth flow failed: ${msg}`,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Slack's oauth.v2.access returns:
|
|
149
|
+
// access_token: "xoxb-..." (bot token)
|
|
150
|
+
// authed_user: { access_token: "xoxp-..." } (user token)
|
|
151
|
+
const raw = result.rawTokenResponse;
|
|
152
|
+
const botToken = raw.access_token as string | undefined;
|
|
153
|
+
const authedUser = raw.authed_user as { access_token?: string } | undefined;
|
|
154
|
+
const userToken = authedUser?.access_token as string | undefined;
|
|
155
|
+
|
|
156
|
+
if (!botToken) {
|
|
157
|
+
log.error(
|
|
158
|
+
{ rawKeys: Object.keys(raw) },
|
|
159
|
+
"Slack OAuth response missing bot access_token",
|
|
160
|
+
);
|
|
161
|
+
return {
|
|
162
|
+
success: false,
|
|
163
|
+
hasBotToken: false,
|
|
164
|
+
hasUserToken: false,
|
|
165
|
+
error:
|
|
166
|
+
"Slack OAuth response did not include a bot token (access_token). The app may not have bot scopes configured.",
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
log.info(
|
|
171
|
+
{ hasBotToken: true, hasUserToken: !!userToken },
|
|
172
|
+
"Slack OAuth tokens received, storing via setSlackChannelConfig",
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
// Store bot token (and user token if present) via the Slack channel handler,
|
|
176
|
+
// which validates tokens and persists workspace metadata.
|
|
177
|
+
const configResult = await setSlackChannelConfig(
|
|
178
|
+
botToken,
|
|
179
|
+
appToken,
|
|
180
|
+
userToken,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
if (!configResult.success) {
|
|
184
|
+
return {
|
|
185
|
+
success: false,
|
|
186
|
+
hasBotToken: false,
|
|
187
|
+
hasUserToken: false,
|
|
188
|
+
error: configResult.error ?? "Failed to store Slack tokens",
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
success: true,
|
|
194
|
+
hasBotToken: true,
|
|
195
|
+
hasUserToken: !!userToken,
|
|
196
|
+
};
|
|
197
|
+
}
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
|
|
1
3
|
import { config as dotenvConfig } from "dotenv";
|
|
2
4
|
|
|
3
5
|
import type { BackupWorkerHandle } from "../backup/backup-worker.js";
|
|
@@ -72,7 +74,6 @@ import {
|
|
|
72
74
|
import { backfillManualTokenConnections } from "../oauth/manual-token-connection.js";
|
|
73
75
|
import { seedOAuthProviders } from "../oauth/seed-providers.js";
|
|
74
76
|
import { ensurePromptFiles } from "../prompts/system-prompt.js";
|
|
75
|
-
import { syncUpdateBulletinOnStartup } from "../prompts/update-bulletin.js";
|
|
76
77
|
import { resolveManagedProxyContext } from "../providers/managed-proxy/context.js";
|
|
77
78
|
import { buildAssistantEvent } from "../runtime/assistant-event.js";
|
|
78
79
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
@@ -89,6 +90,7 @@ import {
|
|
|
89
90
|
} from "../runtime/capability-tokens.js";
|
|
90
91
|
import { ensureVellumGuardianBinding } from "../runtime/guardian-vellum-migration.js";
|
|
91
92
|
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
93
|
+
import { recoverInterruptedImport } from "../runtime/migrations/vbundle-streaming-importer.js";
|
|
92
94
|
import { startScheduler } from "../schedule/scheduler.js";
|
|
93
95
|
import {
|
|
94
96
|
onCesClientChanged,
|
|
@@ -278,6 +280,36 @@ export async function runDaemon(): Promise<void> {
|
|
|
278
280
|
|
|
279
281
|
ensureDataDir();
|
|
280
282
|
|
|
283
|
+
// Recover from any streaming `.vbundle` import that was interrupted by a
|
|
284
|
+
// crash or SIGKILL. If the previous process died between
|
|
285
|
+
// `carryOverPreservedPaths` and the atomic workspace swap, the live
|
|
286
|
+
// workspace may be missing `data/db` / `data/qdrant` / etc. The marker
|
|
287
|
+
// at `<workspaceDir>.import-marker.json` (persisted before any rename
|
|
288
|
+
// runs) tells us where the orphaned preserved paths landed; the
|
|
289
|
+
// recovery helper moves them back into the live workspace and cleans
|
|
290
|
+
// up the temp tree. Running this BEFORE `initializeDb()` ensures the
|
|
291
|
+
// DB singleton opens against the fully-restored `assistant.db`.
|
|
292
|
+
try {
|
|
293
|
+
const recoveryResult = await recoverInterruptedImport(getWorkspaceDir());
|
|
294
|
+
if (!recoveryResult.ok) {
|
|
295
|
+
// Rollback is intentionally unresolved — backup/temp/marker are
|
|
296
|
+
// preserved on disk so an operator (or a later retry) can finish
|
|
297
|
+
// the recovery. Log loudly so ops sees it, but don't block start-up:
|
|
298
|
+
// the daemon still needs to come up for diagnostics. The next
|
|
299
|
+
// `streamCommitImport` will refuse to start a new import until the
|
|
300
|
+
// marker is resolved.
|
|
301
|
+
log.error(
|
|
302
|
+
{ failedCount: recoveryResult.failedCount },
|
|
303
|
+
"Interrupted-import recovery is INCOMPLETE; leftover .pre-import-* / .import-* scratch dirs remain in the workspace. Manual intervention may be required before the next import can run.",
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
} catch (err) {
|
|
307
|
+
log.warn(
|
|
308
|
+
{ err },
|
|
309
|
+
"recoverInterruptedImport threw during daemon startup; continuing",
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
281
313
|
// Load (or generate + persist) the auth signing key so tokens survive
|
|
282
314
|
// daemon restarts.
|
|
283
315
|
const signingKey = resolveSigningKey();
|
|
@@ -543,18 +575,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
543
575
|
log.info("Daemon startup: loading config");
|
|
544
576
|
const config = loadConfig();
|
|
545
577
|
|
|
546
|
-
// Run bulletin sync AFTER the config merge + load so that getConfig()
|
|
547
|
-
// inside syncUpdateBulletinOnStartup() observes the fully merged config.
|
|
548
|
-
// Running it earlier would populate the config cache with pre-merge
|
|
549
|
-
// values, poisoning every downstream getConfig() consumer.
|
|
550
|
-
if (dbReady) {
|
|
551
|
-
try {
|
|
552
|
-
syncUpdateBulletinOnStartup();
|
|
553
|
-
} catch (err) {
|
|
554
|
-
log.warn({ err }, "Bulletin sync failed — continuing startup");
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
578
|
// Seed module-level ingress state from the workspace config so that
|
|
559
579
|
// getIngressPublicBaseUrl() returns the correct value immediately after
|
|
560
580
|
// startup (before any handleIngressConfig("set") call). Without this,
|
|
@@ -655,7 +675,9 @@ export async function runDaemon(): Promise<void> {
|
|
|
655
675
|
...(startupProxyCtx.assistantApiKey
|
|
656
676
|
? { assistantApiKey: startupProxyCtx.assistantApiKey }
|
|
657
677
|
: {}),
|
|
658
|
-
...(startupAssistantId
|
|
678
|
+
...(startupAssistantId
|
|
679
|
+
? { assistantId: startupAssistantId }
|
|
680
|
+
: {}),
|
|
659
681
|
});
|
|
660
682
|
if (accepted) {
|
|
661
683
|
log.info("CES reconnection handshake accepted");
|
|
@@ -690,6 +712,24 @@ export async function runDaemon(): Promise<void> {
|
|
|
690
712
|
await server.start();
|
|
691
713
|
log.info("Daemon startup: DaemonServer started");
|
|
692
714
|
|
|
715
|
+
// Kick off the update bulletin background job AFTER `server.start()`
|
|
716
|
+
// resolves. `server.start()` installs the default wake resolver (via
|
|
717
|
+
// `registerDefaultWakeResolver()`), which the job depends on to actually
|
|
718
|
+
// invoke the agent. Dispatching before that point races the resolver
|
|
719
|
+
// registration and causes `wakeAgentForOpportunity()` to silently return
|
|
720
|
+
// `{invoked: false}`, leaving an orphan background conversation and a
|
|
721
|
+
// wasted LLM title-generation call every startup.
|
|
722
|
+
//
|
|
723
|
+
// Kept fire-and-forget (`void import(...).then(...).catch(...)`) so the
|
|
724
|
+
// daemon never blocks startup on it.
|
|
725
|
+
if (dbReady) {
|
|
726
|
+
void import("../prompts/update-bulletin-job.js")
|
|
727
|
+
.then((m) => m.runUpdateBulletinJobIfNeeded())
|
|
728
|
+
.catch((err) =>
|
|
729
|
+
log.warn({ err }, "Update bulletin job failed — continuing startup"),
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
|
|
693
733
|
// Mutable refs for Qdrant, memory worker, and backup worker so background
|
|
694
734
|
// init can assign them and the shutdown handler always sees the latest value.
|
|
695
735
|
const bgRefs: {
|
|
@@ -774,6 +814,28 @@ export async function runDaemon(): Promise<void> {
|
|
|
774
814
|
"Qdrant client initialization failed — memory features will be degraded",
|
|
775
815
|
);
|
|
776
816
|
}
|
|
817
|
+
|
|
818
|
+
// Reconcile the PKB Qdrant index against the on-disk tree. Kept
|
|
819
|
+
// inside the `qdrantStarted` guard so we don't call
|
|
820
|
+
// `getQdrantClient()` (which throws "not initialized") on every
|
|
821
|
+
// startup when Qdrant is unavailable. Fire-and-forget so enqueued
|
|
822
|
+
// re-index jobs drain in the background and first-turn latency
|
|
823
|
+
// stays unaffected.
|
|
824
|
+
void (async () => {
|
|
825
|
+
try {
|
|
826
|
+
const { reconcilePkbIndex } =
|
|
827
|
+
await import("../memory/pkb/pkb-reconcile.js");
|
|
828
|
+
const { PKB_WORKSPACE_SCOPE } =
|
|
829
|
+
await import("../memory/pkb/types.js");
|
|
830
|
+
const pkbRoot = join(getWorkspaceDir(), "pkb");
|
|
831
|
+
await reconcilePkbIndex(pkbRoot, PKB_WORKSPACE_SCOPE);
|
|
832
|
+
} catch (err) {
|
|
833
|
+
log.warn(
|
|
834
|
+
{ err },
|
|
835
|
+
"PKB index reconciliation failed — continuing startup",
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
})();
|
|
777
839
|
}
|
|
778
840
|
|
|
779
841
|
log.info("Daemon startup: starting memory worker");
|
|
@@ -434,6 +434,19 @@ export interface ContextCompacted {
|
|
|
434
434
|
summaryModel: string;
|
|
435
435
|
}
|
|
436
436
|
|
|
437
|
+
/**
|
|
438
|
+
* Emitted when the compaction circuit breaker trips. After three consecutive
|
|
439
|
+
* summary-LLM failures (with local fallback covering each), auto-compaction is
|
|
440
|
+
* suspended until `openUntil` to avoid repeatedly hammering a broken provider.
|
|
441
|
+
* User-initiated compaction (`/compact`, `force: true`) bypasses the breaker.
|
|
442
|
+
*/
|
|
443
|
+
export interface CompactionCircuitOpen {
|
|
444
|
+
type: "compaction_circuit_open";
|
|
445
|
+
reason: "3_consecutive_failures";
|
|
446
|
+
/** Timestamp (ms since epoch) when the breaker will allow auto-compaction again. */
|
|
447
|
+
openUntil: number;
|
|
448
|
+
}
|
|
449
|
+
|
|
437
450
|
export type ConversationErrorCode =
|
|
438
451
|
| "PROVIDER_NETWORK"
|
|
439
452
|
| "PROVIDER_RATE_LIMIT"
|
|
@@ -531,6 +544,7 @@ export type _ConversationsServerMessages =
|
|
|
531
544
|
| UsageUpdate
|
|
532
545
|
| UsageResponse
|
|
533
546
|
| ContextCompacted
|
|
547
|
+
| CompactionCircuitOpen
|
|
534
548
|
| ConversationErrorMessage
|
|
535
549
|
| ConversationInfo
|
|
536
550
|
| ConversationTitleUpdated
|
|
@@ -23,6 +23,10 @@ export interface UserMessage {
|
|
|
23
23
|
microphonePermissionGranted?: boolean;
|
|
24
24
|
/** Structured command intent — bypasses text parsing when present. */
|
|
25
25
|
commandIntent?: CommandIntent;
|
|
26
|
+
/** Client-generated correlation nonce for echo dedup. See
|
|
27
|
+
* `UserMessageEcho.clientMessageId` — the server echoes this value
|
|
28
|
+
* back on the matching `user_message_echo` event. */
|
|
29
|
+
clientMessageId?: string;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export interface ConfirmationResponse {
|
|
@@ -33,7 +37,6 @@ export interface ConfirmationResponse {
|
|
|
33
37
|
| "allow_10m"
|
|
34
38
|
| "allow_conversation"
|
|
35
39
|
| "always_allow"
|
|
36
|
-
| "always_allow_high_risk"
|
|
37
40
|
| "deny"
|
|
38
41
|
| "always_deny";
|
|
39
42
|
selectedPattern?: string;
|
|
@@ -67,6 +70,11 @@ export interface UserMessageEcho {
|
|
|
67
70
|
/** Server-generated request ID for the send. Allows correlation with
|
|
68
71
|
* `message_queued` / `message_dequeued` events for the same turn. */
|
|
69
72
|
requestId?: string;
|
|
73
|
+
/** Client-generated correlation nonce from the HTTP POST body. Echoed
|
|
74
|
+
* back so the originating client can dedupe its optimistic row even
|
|
75
|
+
* if the SSE echo beats the 202 response. Absent for synthetic echoes
|
|
76
|
+
* (e.g. surface-action prompts) that did not originate from a client POST. */
|
|
77
|
+
clientMessageId?: string;
|
|
70
78
|
}
|
|
71
79
|
|
|
72
80
|
export interface AssistantTextDelta {
|
|
@@ -8,8 +8,6 @@ export interface AddTrustRule {
|
|
|
8
8
|
pattern: string;
|
|
9
9
|
scope: string;
|
|
10
10
|
decision: "allow" | "deny" | "ask";
|
|
11
|
-
/** When true, the rule also covers high-risk invocations. */
|
|
12
|
-
allowHighRisk?: boolean;
|
|
13
11
|
/** Execution target override for this rule. */
|
|
14
12
|
executionTarget?: "host" | "sandbox";
|
|
15
13
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ContextOverflowError } from "../providers/types.js";
|
|
4
|
+
import { parseActualTokensFromError } from "./parse-actual-tokens-from-error.js";
|
|
4
5
|
|
|
5
6
|
describe("parseActualTokensFromError", () => {
|
|
6
7
|
test("returns null for null input", () => {
|
|
@@ -68,4 +69,59 @@ describe("parseActualTokensFromError", () => {
|
|
|
68
69
|
test("returns null when no numeric pattern matches", () => {
|
|
69
70
|
expect(parseActualTokensFromError("context window exceeded")).toBeNull();
|
|
70
71
|
});
|
|
72
|
+
|
|
73
|
+
// ── Typed-error branch ─────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
test("prefers ContextOverflowError.actualTokens over string-regex match", () => {
|
|
76
|
+
// Message would regex-parse to 999999, but typed field wins.
|
|
77
|
+
const err = new ContextOverflowError(
|
|
78
|
+
"Anthropic API error (400): prompt is too long: 999999 tokens > 200000 maximum",
|
|
79
|
+
"anthropic",
|
|
80
|
+
{
|
|
81
|
+
actualTokens: 242201,
|
|
82
|
+
maxTokens: 200000,
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
expect(parseActualTokensFromError(err)).toBe(242201);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("falls back to regex when ContextOverflowError has no actualTokens", () => {
|
|
89
|
+
const err = new ContextOverflowError(
|
|
90
|
+
"OpenAI API error (400): too many input tokens: 150000 > 128000",
|
|
91
|
+
"openai",
|
|
92
|
+
{},
|
|
93
|
+
);
|
|
94
|
+
expect(parseActualTokensFromError(err)).toBe(150000);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("returns null when ContextOverflowError has neither typed field nor matching message", () => {
|
|
98
|
+
const err = new ContextOverflowError("context window exceeded", "openai");
|
|
99
|
+
expect(parseActualTokensFromError(err)).toBeNull();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("typed-error parsing takes precedence over string regex even when both present", () => {
|
|
103
|
+
// String has 999999 tokens > 200000; typed field says 242201.
|
|
104
|
+
// The typed field MUST win — this is the core contract.
|
|
105
|
+
const err = new ContextOverflowError(
|
|
106
|
+
"prompt is too long: 999999 tokens > 200000 maximum",
|
|
107
|
+
"anthropic",
|
|
108
|
+
{ actualTokens: 242201 },
|
|
109
|
+
);
|
|
110
|
+
expect(parseActualTokensFromError(err)).toBe(242201);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("accepts an untyped Error instance and parses its message", () => {
|
|
114
|
+
const err = new Error("prompt is too long: 242201 tokens > 200000 maximum");
|
|
115
|
+
expect(parseActualTokensFromError(err)).toBe(242201);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("ignores non-numeric/invalid actualTokens on typed error", () => {
|
|
119
|
+
// actualTokens of 0 should fall through (typed check requires > 0).
|
|
120
|
+
const err = new ContextOverflowError(
|
|
121
|
+
"prompt is too long: 242201 tokens > 200000 maximum",
|
|
122
|
+
"anthropic",
|
|
123
|
+
{ actualTokens: 0 },
|
|
124
|
+
);
|
|
125
|
+
expect(parseActualTokensFromError(err)).toBe(242201);
|
|
126
|
+
});
|
|
71
127
|
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { isContextOverflowError } from "../providers/types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parse the actual token count reported by the provider for a
|
|
5
|
+
* context-too-large failure.
|
|
6
|
+
*
|
|
7
|
+
* Prefers the typed `ContextOverflowError.actualTokens` field when the
|
|
8
|
+
* thrown error is one. Falls back to regex-parsing the message for patterns
|
|
9
|
+
* like:
|
|
10
|
+
* "prompt is too long: 242201 tokens > 200000 maximum" (Anthropic)
|
|
11
|
+
* "too many input tokens: 242201 > 200000" (OpenAI)
|
|
12
|
+
*
|
|
13
|
+
* The regex path remains a safety net for provider-adapter paths (e.g.
|
|
14
|
+
* managed-proxy rewrappers) that surface untyped errors.
|
|
15
|
+
*
|
|
16
|
+
* Accepts a raw error object, an `Error` instance, or a plain string.
|
|
17
|
+
* Returns the actual token count, or `null` when it cannot be determined.
|
|
18
|
+
*/
|
|
19
|
+
export function parseActualTokensFromError(
|
|
20
|
+
errorOrMessage: unknown,
|
|
21
|
+
): number | null {
|
|
22
|
+
// Typed path — the provider client wrapped a matching upstream error as
|
|
23
|
+
// ContextOverflowError. Use the parsed field directly when available.
|
|
24
|
+
if (isContextOverflowError(errorOrMessage)) {
|
|
25
|
+
const actual = errorOrMessage.actualTokens;
|
|
26
|
+
if (typeof actual === "number" && actual > 0) return actual;
|
|
27
|
+
// Typed error without `actualTokens` — fall through to regex-parse the
|
|
28
|
+
// underlying message in case the upstream body carries it in text form.
|
|
29
|
+
return parseFromMessage(errorOrMessage.message ?? null);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Untyped path — accept either an Error or a string.
|
|
33
|
+
if (errorOrMessage == null) return null;
|
|
34
|
+
if (typeof errorOrMessage === "string") {
|
|
35
|
+
return parseFromMessage(errorOrMessage);
|
|
36
|
+
}
|
|
37
|
+
if (typeof errorOrMessage === "object" && "message" in errorOrMessage) {
|
|
38
|
+
const msg = (errorOrMessage as { message?: unknown }).message;
|
|
39
|
+
if (typeof msg === "string") return parseFromMessage(msg);
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function parseFromMessage(errorMessage: string | null): number | null {
|
|
45
|
+
if (!errorMessage) return null;
|
|
46
|
+
|
|
47
|
+
// Match patterns like "242201 tokens > 200000" or "242201 > 200000 maximum"
|
|
48
|
+
const match = errorMessage.match(
|
|
49
|
+
/(\d[\d,]*)\s*tokens?\s*[>≥]|:\s*(\d[\d,]*)\s*[>≥]/i,
|
|
50
|
+
);
|
|
51
|
+
if (match) {
|
|
52
|
+
const raw = (match[1] || match[2]).replace(/,/g, "");
|
|
53
|
+
const parsed = parseInt(raw, 10);
|
|
54
|
+
if (!isNaN(parsed) && parsed > 0) return parsed;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Fallback: match "too many input tokens: N > M"
|
|
58
|
+
const fallback = errorMessage.match(/(\d[\d,]*)\s*[>≥]\s*\d/);
|
|
59
|
+
if (fallback) {
|
|
60
|
+
const raw = fallback[1].replace(/,/g, "");
|
|
61
|
+
const parsed = parseInt(raw, 10);
|
|
62
|
+
if (!isNaN(parsed) && parsed > 0) return parsed;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return null;
|
|
66
|
+
}
|