@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
|
@@ -119,9 +119,19 @@ export interface WakeOptions {
|
|
|
119
119
|
source: string;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Reason a wake returned `invoked: false`. Callers (CLI, update-bulletin
|
|
124
|
+
* job) need to distinguish "conversation doesn't exist" from "conversation
|
|
125
|
+
* exists but stayed busy past the wait-until-idle timeout" — the former is
|
|
126
|
+
* a user-visible error, the latter is an expected transient condition.
|
|
127
|
+
*/
|
|
128
|
+
export type WakeSkipReason = "not_found" | "timeout" | "no_resolver";
|
|
129
|
+
|
|
122
130
|
export interface WakeResult {
|
|
123
131
|
invoked: boolean;
|
|
124
132
|
producedToolCalls: boolean;
|
|
133
|
+
/** Present only when `invoked: false`; identifies why the wake was skipped. */
|
|
134
|
+
reason?: WakeSkipReason;
|
|
125
135
|
}
|
|
126
136
|
|
|
127
137
|
/**
|
|
@@ -223,13 +233,12 @@ async function waitUntilIdle(
|
|
|
223
233
|
target: WakeTarget,
|
|
224
234
|
nowFn: () => number,
|
|
225
235
|
timeoutMs = 30_000,
|
|
226
|
-
): Promise<
|
|
236
|
+
): Promise<boolean> {
|
|
227
237
|
const deadline = nowFn() + timeoutMs;
|
|
228
|
-
// 50ms backoff is fine — wakes are not latency-critical and a user turn
|
|
229
|
-
// typically completes on the order of seconds.
|
|
230
238
|
while (target.isProcessing() && nowFn() < deadline) {
|
|
231
239
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
232
240
|
}
|
|
241
|
+
return !target.isProcessing();
|
|
233
242
|
}
|
|
234
243
|
|
|
235
244
|
/**
|
|
@@ -300,7 +309,7 @@ export async function wakeAgentForOpportunity(
|
|
|
300
309
|
{ conversationId, source },
|
|
301
310
|
"agent-wake: no resolver available (default resolver not registered and no deps passed); skipping",
|
|
302
311
|
);
|
|
303
|
-
return { invoked: false, producedToolCalls: false };
|
|
312
|
+
return { invoked: false, producedToolCalls: false, reason: "no_resolver" };
|
|
304
313
|
}
|
|
305
314
|
const nowFn = deps?.now ?? Date.now;
|
|
306
315
|
const startedAt = nowFn();
|
|
@@ -312,10 +321,17 @@ export async function wakeAgentForOpportunity(
|
|
|
312
321
|
{ conversationId, source },
|
|
313
322
|
"agent-wake: conversation not found; skipping",
|
|
314
323
|
);
|
|
315
|
-
return { invoked: false, producedToolCalls: false };
|
|
324
|
+
return { invoked: false, producedToolCalls: false, reason: "not_found" };
|
|
316
325
|
}
|
|
317
326
|
|
|
318
|
-
await waitUntilIdle(target, nowFn);
|
|
327
|
+
const idle = await waitUntilIdle(target, nowFn);
|
|
328
|
+
if (!idle) {
|
|
329
|
+
log.warn(
|
|
330
|
+
{ conversationId, source },
|
|
331
|
+
"agent-wake: conversation still processing after timeout; skipping",
|
|
332
|
+
);
|
|
333
|
+
return { invoked: false, producedToolCalls: false, reason: "timeout" };
|
|
334
|
+
}
|
|
319
335
|
|
|
320
336
|
const baseline = target.getMessages();
|
|
321
337
|
const hintContent = `[opportunity:${source}] ${hint}`;
|
|
@@ -346,6 +362,7 @@ export async function wakeAgentForOpportunity(
|
|
|
346
362
|
let producedToolCalls = false;
|
|
347
363
|
let toolUseNames: string[] = [];
|
|
348
364
|
let tailMessageCount = 0;
|
|
365
|
+
let drainedInTry = false;
|
|
349
366
|
try {
|
|
350
367
|
let updatedHistory: Message[];
|
|
351
368
|
try {
|
|
@@ -375,8 +392,11 @@ export async function wakeAgentForOpportunity(
|
|
|
375
392
|
// `drainSingleMessage` reads `ctx.messages` mid-tail and writes a
|
|
376
393
|
// DB row that lands out of chronological order (queued user msg
|
|
377
394
|
// before the wake's just-produced assistant outputs).
|
|
378
|
-
const {
|
|
379
|
-
|
|
395
|
+
const {
|
|
396
|
+
tailMessages,
|
|
397
|
+
hasVisibleText,
|
|
398
|
+
toolUseNames: names,
|
|
399
|
+
} = inspectWakeOutput(baseline.length, updatedHistory);
|
|
380
400
|
toolUseNames = names;
|
|
381
401
|
producedToolCalls = names.length > 0;
|
|
382
402
|
const producedOutput = producedToolCalls || hasVisibleText;
|
|
@@ -431,11 +451,12 @@ export async function wakeAgentForOpportunity(
|
|
|
431
451
|
}
|
|
432
452
|
}
|
|
433
453
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
//
|
|
437
|
-
//
|
|
438
|
-
//
|
|
454
|
+
// Drain queued messages AFTER tail is pushed + persisted so the
|
|
455
|
+
// next dequeued user message sees the complete, up-to-date
|
|
456
|
+
// history. markProcessing(false) must come first (the queue only
|
|
457
|
+
// accepts entries while processing === true, and drain expects
|
|
458
|
+
// processing to already be false). The finally block handles the
|
|
459
|
+
// error/early-return paths where no tail was produced.
|
|
439
460
|
try {
|
|
440
461
|
target.markProcessing(false);
|
|
441
462
|
} catch (err) {
|
|
@@ -444,15 +465,6 @@ export async function wakeAgentForOpportunity(
|
|
|
444
465
|
"agent-wake: markProcessing(false) threw; continuing",
|
|
445
466
|
);
|
|
446
467
|
}
|
|
447
|
-
// Drain any messages queued during the wake. Order matters:
|
|
448
|
-
// `enqueueMessage()` only queues when `processing === true`, so
|
|
449
|
-
// late sends arriving while the wake was running landed on the
|
|
450
|
-
// queue. The canonical user-turn finally calls drain after
|
|
451
|
-
// resetting `processing = false` AND after `ctx.messages` has
|
|
452
|
-
// been updated with the new tail; mirror that here so a queued
|
|
453
|
-
// message is picked up against an updated history rather than
|
|
454
|
-
// stranded behind an out-of-order DB row. Wrapped in try/catch
|
|
455
|
-
// so a drain failure can't propagate out of the wake.
|
|
456
468
|
if (target.drainQueue) {
|
|
457
469
|
try {
|
|
458
470
|
await target.drainQueue();
|
|
@@ -463,6 +475,35 @@ export async function wakeAgentForOpportunity(
|
|
|
463
475
|
);
|
|
464
476
|
}
|
|
465
477
|
}
|
|
478
|
+
drainedInTry = true;
|
|
479
|
+
|
|
480
|
+
return { invoked: true, producedToolCalls };
|
|
481
|
+
} finally {
|
|
482
|
+
// The success path (above) already called markProcessing(false)
|
|
483
|
+
// + drainQueue after tail persist. This catch-all handles the
|
|
484
|
+
// error and early-return paths where no tail was produced — those
|
|
485
|
+
// exit the try body before reaching the drain block, so
|
|
486
|
+
// `drainedInTry` is still false.
|
|
487
|
+
if (!drainedInTry) {
|
|
488
|
+
try {
|
|
489
|
+
target.markProcessing(false);
|
|
490
|
+
} catch (err) {
|
|
491
|
+
log.warn(
|
|
492
|
+
{ conversationId, source, err },
|
|
493
|
+
"agent-wake: markProcessing(false) threw; continuing",
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
if (target.drainQueue) {
|
|
497
|
+
try {
|
|
498
|
+
await target.drainQueue();
|
|
499
|
+
} catch (err) {
|
|
500
|
+
log.warn(
|
|
501
|
+
{ conversationId, source, err },
|
|
502
|
+
"agent-wake: drainQueue threw; continuing",
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
466
507
|
|
|
467
508
|
const durationMs = nowFn() - startedAt;
|
|
468
509
|
if (runError) {
|
|
@@ -214,6 +214,10 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
214
214
|
endpoint: "integrations/slack/channel/config:DELETE",
|
|
215
215
|
scopes: ["settings.write"],
|
|
216
216
|
},
|
|
217
|
+
{
|
|
218
|
+
endpoint: "integrations/slack/channel/oauth-install:POST",
|
|
219
|
+
scopes: ["settings.write"],
|
|
220
|
+
},
|
|
217
221
|
{ endpoint: "channel-verification-sessions", scopes: ["settings.write"] },
|
|
218
222
|
{
|
|
219
223
|
endpoint: "channel-verification-sessions:DELETE",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
1
2
|
import { buildToolDefinitions } from "../daemon/conversation-tool-setup.js";
|
|
2
3
|
import { buildSystemPrompt } from "../prompts/system-prompt.js";
|
|
3
4
|
import {
|
|
@@ -7,7 +8,6 @@ import {
|
|
|
7
8
|
} from "../providers/provider-send-message.js";
|
|
8
9
|
import type {
|
|
9
10
|
Message,
|
|
10
|
-
ModelIntent,
|
|
11
11
|
Provider,
|
|
12
12
|
ProviderEvent,
|
|
13
13
|
ProviderResponse,
|
|
@@ -29,7 +29,15 @@ export interface RunBtwSidechainParams {
|
|
|
29
29
|
systemPrompt?: string;
|
|
30
30
|
tools?: ToolDefinition[];
|
|
31
31
|
maxTokens?: number;
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Unified call-site identifier. The provider layer resolves
|
|
34
|
+
* provider/model/maxTokens/effort/speed/temperature/thinking/contextWindow
|
|
35
|
+
* via `resolveCallSiteConfig(callSite, config.llm)`. Defaults to
|
|
36
|
+
* `'identityIntro'` since this side-chain runner was originally introduced
|
|
37
|
+
* for the identity intro generation path; callers (greeting, title, etc.)
|
|
38
|
+
* override it with their own call-site ID.
|
|
39
|
+
*/
|
|
40
|
+
callSite?: LLMCallSite;
|
|
33
41
|
signal?: AbortSignal;
|
|
34
42
|
timeoutMs?: number;
|
|
35
43
|
onEvent?: (event: ProviderEvent) => void;
|
|
@@ -89,7 +97,9 @@ export async function runBtwSidechain(
|
|
|
89
97
|
config: {
|
|
90
98
|
max_tokens: params.maxTokens ?? 1024,
|
|
91
99
|
tool_choice: { type: "none" },
|
|
92
|
-
|
|
100
|
+
// Default call site is "identityIntro" — the original purpose of
|
|
101
|
+
// this side-chain runner. Callers may override per invocation.
|
|
102
|
+
callSite: params.callSite ?? ("identityIntro" as LLMCallSite),
|
|
93
103
|
},
|
|
94
104
|
onEvent: (event) => {
|
|
95
105
|
if (event.type === "text_delta") {
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { renderHistoryContent } from "../daemon/handlers/shared.js";
|
|
2
2
|
import * as attachmentsStore from "../memory/attachments-store.js";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getMessageById,
|
|
5
|
+
getMessages,
|
|
6
|
+
updateMessageMetadata,
|
|
7
|
+
} from "../memory/conversation-crud.js";
|
|
8
|
+
import { readSlackMetadata } from "../messaging/providers/slack/message-metadata.js";
|
|
9
|
+
import { getLogger } from "../util/logger.js";
|
|
4
10
|
import type { ChannelDeliveryResult } from "./gateway-client.js";
|
|
5
11
|
import { deliverChannelReply } from "./gateway-client.js";
|
|
6
12
|
import type { RuntimeAttachmentMetadata } from "./http-types.js";
|
|
@@ -9,6 +15,8 @@ import {
|
|
|
9
15
|
textToSlackBlocks,
|
|
10
16
|
} from "./slack-block-formatting.js";
|
|
11
17
|
|
|
18
|
+
const log = getLogger("channel-reply-delivery");
|
|
19
|
+
|
|
12
20
|
const INTER_SEGMENT_DELAY_MS = 150;
|
|
13
21
|
|
|
14
22
|
type DeliverRenderedReplyParams = {
|
|
@@ -206,6 +214,22 @@ export async function deliverReplyViaCallback(
|
|
|
206
214
|
kind: a.kind,
|
|
207
215
|
}));
|
|
208
216
|
|
|
217
|
+
// Compose an `onMessageTs` that reconciles `slackMeta.channelTs` on the
|
|
218
|
+
// persisted assistant row once Slack returns the authoritative ts. The
|
|
219
|
+
// assistant row was written BEFORE the gateway POST in
|
|
220
|
+
// `handleMessageComplete`, so the partial `slackMeta` it carries is
|
|
221
|
+
// missing `channelTs` and would otherwise be rejected by
|
|
222
|
+
// `readSlackMetadata`, dropping the row out of chronological/thread-tag
|
|
223
|
+
// rendering. We only act on the FIRST ts (top-level segment); any
|
|
224
|
+
// subsequent split segments become independent Slack messages with
|
|
225
|
+
// their own ts and are not represented as separate DB rows.
|
|
226
|
+
const reconcileOnMessageTs = makeChannelTsReconciler(msgs[i].id);
|
|
227
|
+
const callerOnMessageTs = options?.onMessageTs;
|
|
228
|
+
const composedOnMessageTs = (ts: string): void => {
|
|
229
|
+
reconcileOnMessageTs(ts);
|
|
230
|
+
callerOnMessageTs?.(ts);
|
|
231
|
+
};
|
|
232
|
+
|
|
209
233
|
await deliverRenderedReplyViaCallback({
|
|
210
234
|
callbackUrl,
|
|
211
235
|
chatId: externalChatId,
|
|
@@ -219,8 +243,88 @@ export async function deliverReplyViaCallback(
|
|
|
219
243
|
ephemeral: options?.ephemeral,
|
|
220
244
|
user: options?.user,
|
|
221
245
|
messageTs: options?.messageTs,
|
|
222
|
-
onMessageTs:
|
|
246
|
+
onMessageTs: composedOnMessageTs,
|
|
223
247
|
});
|
|
224
248
|
break;
|
|
225
249
|
}
|
|
226
250
|
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Build a one-shot `onMessageTs` handler that reconciles the persisted
|
|
254
|
+
* assistant message's `slackMeta.channelTs` from Slack's authoritative `ts`.
|
|
255
|
+
*
|
|
256
|
+
* Behavior:
|
|
257
|
+
* - Acts only on the first invocation per delivery (subsequent segments
|
|
258
|
+
* correspond to independent Slack messages with their own ts and are not
|
|
259
|
+
* represented as separate DB rows).
|
|
260
|
+
* - No-op when the row was not persisted with a `slackMeta` envelope (the
|
|
261
|
+
* channel was not Slack at write-time, e.g. vellum/telegram outbound).
|
|
262
|
+
* - No-op when the row's existing `slackMeta` already parses cleanly via
|
|
263
|
+
* `readSlackMetadata` (channelTs already present, e.g. from a prior
|
|
264
|
+
* reconciliation).
|
|
265
|
+
* - Failures are logged and swallowed so a transient DB error cannot break
|
|
266
|
+
* the outbound delivery itself.
|
|
267
|
+
*/
|
|
268
|
+
function makeChannelTsReconciler(messageId: string): (ts: string) => void {
|
|
269
|
+
let applied = false;
|
|
270
|
+
return (ts: string): void => {
|
|
271
|
+
if (applied) return;
|
|
272
|
+
applied = true;
|
|
273
|
+
if (!ts) return;
|
|
274
|
+
try {
|
|
275
|
+
// Re-read the row's current metadata so a concurrent edit-propagation
|
|
276
|
+
// write (e.g. `editedAt`) is not clobbered. `updateMessageMetadata`
|
|
277
|
+
// shallow-merges into the top-level envelope, and the slackMeta
|
|
278
|
+
// sub-object is merged manually below so we can preserve fields on
|
|
279
|
+
// the partial pre-send envelope (`mergeSlackMetadata` would call
|
|
280
|
+
// `readSlackMetadata` which rejects the partial form for lacking
|
|
281
|
+
// channelTs — exactly the state we are reconciling).
|
|
282
|
+
const row = getMessageById(messageId);
|
|
283
|
+
if (row === null || row.metadata === null) return;
|
|
284
|
+
let envelope: Record<string, unknown>;
|
|
285
|
+
try {
|
|
286
|
+
envelope = JSON.parse(row.metadata) as Record<string, unknown>;
|
|
287
|
+
} catch {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const slackMetaRaw =
|
|
291
|
+
typeof envelope.slackMeta === "string" ? envelope.slackMeta : null;
|
|
292
|
+
if (slackMetaRaw === null) return;
|
|
293
|
+
// If the existing slackMeta already parses cleanly via the strict
|
|
294
|
+
// reader, channelTs is already present (a prior reconciliation ran,
|
|
295
|
+
// or backfill stamped the field) — nothing to do.
|
|
296
|
+
if (readSlackMetadata(slackMetaRaw) !== null) return;
|
|
297
|
+
// Lenient parse of the partial slackMeta so we can preserve every
|
|
298
|
+
// field already written by `handleMessageComplete` (source,
|
|
299
|
+
// eventKind, channelId, threadTs, ...) while patching channelTs in.
|
|
300
|
+
let existingSlackMeta: Record<string, unknown>;
|
|
301
|
+
try {
|
|
302
|
+
const parsed = JSON.parse(slackMetaRaw) as unknown;
|
|
303
|
+
if (
|
|
304
|
+
parsed === null ||
|
|
305
|
+
typeof parsed !== "object" ||
|
|
306
|
+
Array.isArray(parsed)
|
|
307
|
+
) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
existingSlackMeta = parsed as Record<string, unknown>;
|
|
311
|
+
} catch {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const mergedSlackMeta = JSON.stringify({
|
|
315
|
+
...existingSlackMeta,
|
|
316
|
+
channelTs: ts,
|
|
317
|
+
// Force `source: "slack"` for parity with `mergeSlackMetadata`'s
|
|
318
|
+
// invariant — the reader rejects anything else and we never want a
|
|
319
|
+
// reconciled row to slip through with a stale source.
|
|
320
|
+
source: "slack",
|
|
321
|
+
});
|
|
322
|
+
updateMessageMetadata(messageId, { slackMeta: mergedSlackMeta });
|
|
323
|
+
} catch (err) {
|
|
324
|
+
log.warn(
|
|
325
|
+
{ err, messageId },
|
|
326
|
+
"Failed to reconcile slackMeta.channelTs on outbound assistant row",
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight informational decision token for interactive UI outcomes.
|
|
3
|
+
*
|
|
4
|
+
* Minted when a confirmation-style surface is `submitted`. The token is
|
|
5
|
+
* **non-authoritative** — it carries metadata about the decision for
|
|
6
|
+
* audit and correlation purposes only. It does not grant any capability
|
|
7
|
+
* and must not be used for enforcement or replay protection (that is
|
|
8
|
+
* explicitly out of scope for v1).
|
|
9
|
+
*
|
|
10
|
+
* Format: base64url-encoded JSON payload + `.` + random nonce.
|
|
11
|
+
* The nonce makes tokens unique even for identical payloads; the
|
|
12
|
+
* payload is readable by any consumer without a secret.
|
|
13
|
+
*
|
|
14
|
+
* This module is intentionally decoupled from the existing auth/token
|
|
15
|
+
* infrastructure in `runtime/auth/` — it serves a different purpose
|
|
16
|
+
* and should remain independent.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { randomBytes } from "node:crypto";
|
|
20
|
+
|
|
21
|
+
// ── Token shape ──────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
export interface DecisionTokenPayload {
|
|
24
|
+
/** Conversation the decision belongs to. */
|
|
25
|
+
conversationId: string;
|
|
26
|
+
/** Surface identifier that was displayed. */
|
|
27
|
+
surfaceId: string;
|
|
28
|
+
/** The action ID the user selected (e.g. "confirm"). Only present on affirmative confirmation. */
|
|
29
|
+
action: string;
|
|
30
|
+
/** ISO-8601 timestamp when the decision was recorded. */
|
|
31
|
+
issuedAt: string;
|
|
32
|
+
/** ISO-8601 timestamp after which the token should be considered stale. */
|
|
33
|
+
expiresAt: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Default token lifetime: 5 minutes. */
|
|
37
|
+
const DEFAULT_TTL_MS = 5 * 60 * 1000;
|
|
38
|
+
|
|
39
|
+
// ── Minting ──────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Mint an informational decision token.
|
|
43
|
+
*
|
|
44
|
+
* The returned string is `<base64url-payload>.<random-nonce>`. It is
|
|
45
|
+
* short-lived (default 5 minutes) and non-authoritative.
|
|
46
|
+
*
|
|
47
|
+
* @param opts - Decision metadata.
|
|
48
|
+
* @param opts.conversationId - Conversation scope.
|
|
49
|
+
* @param opts.surfaceId - Surface that was displayed.
|
|
50
|
+
* @param opts.action - Terminal action taken by the user.
|
|
51
|
+
* @param opts.ttlMs - Token lifetime in milliseconds (default 5 min).
|
|
52
|
+
* @returns The minted token string.
|
|
53
|
+
*/
|
|
54
|
+
export function mintDecisionToken(opts: {
|
|
55
|
+
conversationId: string;
|
|
56
|
+
surfaceId: string;
|
|
57
|
+
action: string;
|
|
58
|
+
ttlMs?: number;
|
|
59
|
+
}): string {
|
|
60
|
+
const now = new Date();
|
|
61
|
+
const ttl = opts.ttlMs ?? DEFAULT_TTL_MS;
|
|
62
|
+
const expiresAt = new Date(now.getTime() + ttl);
|
|
63
|
+
|
|
64
|
+
const payload: DecisionTokenPayload = {
|
|
65
|
+
conversationId: opts.conversationId,
|
|
66
|
+
surfaceId: opts.surfaceId,
|
|
67
|
+
action: opts.action,
|
|
68
|
+
issuedAt: now.toISOString(),
|
|
69
|
+
expiresAt: expiresAt.toISOString(),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const encoded = Buffer.from(JSON.stringify(payload)).toString("base64url");
|
|
73
|
+
const nonce = randomBytes(12).toString("hex");
|
|
74
|
+
|
|
75
|
+
return `${encoded}.${nonce}`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── Decoding (informational only) ────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Decode a decision token's payload.
|
|
82
|
+
*
|
|
83
|
+
* This is a pure decoding step — there is no signature verification
|
|
84
|
+
* because the token is non-authoritative. Consumers should treat the
|
|
85
|
+
* payload as informational metadata, not a trust assertion.
|
|
86
|
+
*
|
|
87
|
+
* @param token - The token string produced by {@link mintDecisionToken}.
|
|
88
|
+
* @returns The decoded payload, or `null` if the token is malformed.
|
|
89
|
+
*/
|
|
90
|
+
export function decodeDecisionToken(
|
|
91
|
+
token: string,
|
|
92
|
+
): DecisionTokenPayload | null {
|
|
93
|
+
const dotIdx = token.indexOf(".");
|
|
94
|
+
if (dotIdx < 0) return null;
|
|
95
|
+
|
|
96
|
+
const encodedPayload = token.slice(0, dotIdx);
|
|
97
|
+
try {
|
|
98
|
+
const json = Buffer.from(encodedPayload, "base64url").toString("utf-8");
|
|
99
|
+
const parsed = JSON.parse(json) as Record<string, unknown>;
|
|
100
|
+
|
|
101
|
+
// Minimal structural validation
|
|
102
|
+
if (
|
|
103
|
+
typeof parsed.conversationId !== "string" ||
|
|
104
|
+
typeof parsed.surfaceId !== "string" ||
|
|
105
|
+
typeof parsed.action !== "string" ||
|
|
106
|
+
typeof parsed.issuedAt !== "string" ||
|
|
107
|
+
typeof parsed.expiresAt !== "string"
|
|
108
|
+
) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return parsed as unknown as DecisionTokenPayload;
|
|
113
|
+
} catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -397,8 +397,8 @@ export async function deliverApprovalPrompt(
|
|
|
397
397
|
approval: ApprovalUIMetadata,
|
|
398
398
|
assistantId?: string,
|
|
399
399
|
bearerToken?: string,
|
|
400
|
-
): Promise<
|
|
401
|
-
|
|
400
|
+
): Promise<ChannelDeliveryResult> {
|
|
401
|
+
return deliverChannelReply(
|
|
402
402
|
callbackUrl,
|
|
403
403
|
{ chatId, text, approval, assistantId },
|
|
404
404
|
bearerToken,
|
|
@@ -48,6 +48,29 @@ export interface RouteQueryParam {
|
|
|
48
48
|
* The generate-openapi script converts these to JSON Schema via z.toJSONSchema(). */
|
|
49
49
|
export type RouteBodySchema = z.ZodType;
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Description for a non-200 response variant. Used when an endpoint has
|
|
53
|
+
* meaningful alternate response shapes that clients should handle (e.g.
|
|
54
|
+
* 502 `fetch_failed` on POST /v1/migrations/import when the URL body path
|
|
55
|
+
* can't reach the upstream bundle host).
|
|
56
|
+
*/
|
|
57
|
+
export interface RouteAdditionalResponse {
|
|
58
|
+
description: string;
|
|
59
|
+
/** Zod schema or plain JSON Schema fragment. */
|
|
60
|
+
schema?: RouteBodySchema | Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Request-body variant keyed by Content-Type. Use this when an endpoint
|
|
65
|
+
* accepts multiple body shapes (e.g. `application/octet-stream` OR
|
|
66
|
+
* `application/json`). For the common single-JSON case, use `requestBody`.
|
|
67
|
+
*/
|
|
68
|
+
export interface RouteRequestBodyVariant {
|
|
69
|
+
contentType: string;
|
|
70
|
+
/** Zod schema or plain JSON Schema fragment. Plain objects are embedded verbatim. */
|
|
71
|
+
schema: RouteBodySchema | Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
|
|
51
74
|
/**
|
|
52
75
|
* A single route entry in the declarative table.
|
|
53
76
|
*
|
|
@@ -76,8 +99,17 @@ export interface RouteDefinition {
|
|
|
76
99
|
queryParams?: RouteQueryParam[];
|
|
77
100
|
/** Zod schema for the request body (POST/PUT/PATCH/DELETE). */
|
|
78
101
|
requestBody?: RouteBodySchema;
|
|
102
|
+
/**
|
|
103
|
+
* Alternate request-body variants keyed by Content-Type. When set,
|
|
104
|
+
* overrides `requestBody` in the generated OpenAPI spec — use this for
|
|
105
|
+
* endpoints that accept multiple body shapes on the same URL (e.g.
|
|
106
|
+
* raw bytes OR JSON URL).
|
|
107
|
+
*/
|
|
108
|
+
requestBodies?: RouteRequestBodyVariant[];
|
|
79
109
|
/** Zod schema for the 200 response body. */
|
|
80
110
|
responseBody?: RouteBodySchema;
|
|
111
|
+
/** Additional non-200 responses documented in the generated OpenAPI spec. */
|
|
112
|
+
additionalResponses?: Record<string, RouteAdditionalResponse>;
|
|
81
113
|
}
|
|
82
114
|
|
|
83
115
|
// ---------------------------------------------------------------------------
|
|
@@ -1066,6 +1066,12 @@ export class RuntimeHttpServer {
|
|
|
1066
1066
|
// tokens minted by a session manager).
|
|
1067
1067
|
const skillMatch = matchSkillRoute(path, req.method);
|
|
1068
1068
|
if (skillMatch) {
|
|
1069
|
+
if (skillMatch.kind === "methodMismatch") {
|
|
1070
|
+
return new Response("Method Not Allowed", {
|
|
1071
|
+
status: 405,
|
|
1072
|
+
headers: { Allow: skillMatch.allow.join(", ") },
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1069
1075
|
return await skillMatch.route.handler(req, skillMatch.match);
|
|
1070
1076
|
}
|
|
1071
1077
|
|
|
@@ -1851,6 +1857,21 @@ export class RuntimeHttpServer {
|
|
|
1851
1857
|
404,
|
|
1852
1858
|
);
|
|
1853
1859
|
try {
|
|
1860
|
+
// Snapshot current state to detect whether the seen cursor
|
|
1861
|
+
// actually advances (avoids emitting on no-op signals).
|
|
1862
|
+
// Only consider a conversation "unseen" when a latest assistant
|
|
1863
|
+
// message exists and the seen cursor is behind it — matching
|
|
1864
|
+
// the hasUnseenLatestAssistantMessage logic in buildAssistantAttention.
|
|
1865
|
+
const priorState = getAttentionStateByConversationIds([
|
|
1866
|
+
conversationId,
|
|
1867
|
+
]).get(conversationId);
|
|
1868
|
+
const wasUnseen =
|
|
1869
|
+
priorState != null &&
|
|
1870
|
+
priorState.latestAssistantMessageAt != null &&
|
|
1871
|
+
(priorState.lastSeenAssistantMessageAt == null ||
|
|
1872
|
+
priorState.lastSeenAssistantMessageAt <
|
|
1873
|
+
priorState.latestAssistantMessageAt);
|
|
1874
|
+
|
|
1854
1875
|
recordConversationSeenSignal({
|
|
1855
1876
|
conversationId,
|
|
1856
1877
|
sourceChannel: (body.sourceChannel as string) ?? "vellum",
|
|
@@ -1863,6 +1884,21 @@ export class RuntimeHttpServer {
|
|
|
1863
1884
|
metadata: body.metadata as Record<string, unknown> | undefined,
|
|
1864
1885
|
observedAt: body.observedAt as number | undefined,
|
|
1865
1886
|
});
|
|
1887
|
+
if (wasUnseen) {
|
|
1888
|
+
assistantEventHub
|
|
1889
|
+
.publish(
|
|
1890
|
+
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
1891
|
+
type: "conversation_list_invalidated",
|
|
1892
|
+
reason: "seen_changed",
|
|
1893
|
+
}),
|
|
1894
|
+
)
|
|
1895
|
+
.catch((err) => {
|
|
1896
|
+
log.warn(
|
|
1897
|
+
{ err },
|
|
1898
|
+
"Failed to publish conversation_list_invalidated (seen_changed)",
|
|
1899
|
+
);
|
|
1900
|
+
});
|
|
1901
|
+
}
|
|
1866
1902
|
return Response.json({ ok: true });
|
|
1867
1903
|
} catch (err) {
|
|
1868
1904
|
log.error(
|
|
@@ -1894,7 +1930,22 @@ export class RuntimeHttpServer {
|
|
|
1894
1930
|
404,
|
|
1895
1931
|
);
|
|
1896
1932
|
try {
|
|
1897
|
-
markConversationUnread(conversationId);
|
|
1933
|
+
const changed = markConversationUnread(conversationId);
|
|
1934
|
+
if (changed) {
|
|
1935
|
+
assistantEventHub
|
|
1936
|
+
.publish(
|
|
1937
|
+
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
1938
|
+
type: "conversation_list_invalidated",
|
|
1939
|
+
reason: "seen_changed",
|
|
1940
|
+
}),
|
|
1941
|
+
)
|
|
1942
|
+
.catch((err) => {
|
|
1943
|
+
log.warn(
|
|
1944
|
+
{ err },
|
|
1945
|
+
"Failed to publish conversation_list_invalidated (seen_changed)",
|
|
1946
|
+
);
|
|
1947
|
+
});
|
|
1948
|
+
}
|
|
1898
1949
|
return Response.json({ ok: true });
|
|
1899
1950
|
} catch (err) {
|
|
1900
1951
|
if (err instanceof UserError) {
|
|
@@ -2,10 +2,18 @@
|
|
|
2
2
|
* Shared types for the runtime HTTP server and its route handlers.
|
|
3
3
|
*/
|
|
4
4
|
import type { ChannelId, InterfaceId } from "../channels/types.js";
|
|
5
|
+
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
5
6
|
import type { CesClient } from "../credential-execution/client.js";
|
|
6
7
|
import type { Conversation } from "../daemon/conversation.js";
|
|
7
8
|
import type { TrustContext } from "../daemon/conversation-runtime-assembly.js";
|
|
8
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
ConversationCreateOptions,
|
|
11
|
+
SlackInboundMessageMetadata,
|
|
12
|
+
} from "../daemon/handlers/shared.js";
|
|
13
|
+
|
|
14
|
+
// Re-export so route modules (background-dispatch, etc.) can pull the type
|
|
15
|
+
// from the runtime barrel without reaching into daemon internals.
|
|
16
|
+
export type { SlackInboundMessageMetadata };
|
|
9
17
|
import type { SkillOperationContext } from "../daemon/handlers/skills.js";
|
|
10
18
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
11
19
|
import type {
|
|
@@ -132,6 +140,20 @@ export interface RuntimeMessageConversationOptions {
|
|
|
132
140
|
commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
133
141
|
/** Optional callback to receive real-time agent loop events (text deltas, tool starts, etc.). */
|
|
134
142
|
onEvent?: (msg: ServerMessage) => void;
|
|
143
|
+
/**
|
|
144
|
+
* Optional LLM call-site identifier. Channel ingress and other inbound paths
|
|
145
|
+
* may pass this so the daemon's per-call provider config picks up the right
|
|
146
|
+
* profile via `resolveCallSiteConfig`. PRs 7-11 wire individual call-site
|
|
147
|
+
* literals into specific call paths.
|
|
148
|
+
*/
|
|
149
|
+
callSite?: LLMCallSite;
|
|
150
|
+
/**
|
|
151
|
+
* Slack inbound metadata captured at the channel ingress boundary. When
|
|
152
|
+
* present (and the turn channel resolves to Slack), persistence writes a
|
|
153
|
+
* `slackMeta` sub-object into the message's `metadata` JSON for the
|
|
154
|
+
* chronological renderer to consume.
|
|
155
|
+
*/
|
|
156
|
+
slackInbound?: SlackInboundMessageMetadata;
|
|
135
157
|
}
|
|
136
158
|
|
|
137
159
|
export type MessageProcessor = (
|