@vellumai/assistant 0.6.4 → 0.6.6
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/AGENTS.md +9 -1
- package/ARCHITECTURE.md +43 -49
- package/Dockerfile +17 -3
- package/README.md +3 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
- package/bun.lock +8 -3
- package/docs/architecture/integrations.md +33 -59
- package/docs/architecture/memory.md +25 -30
- package/docs/architecture/security.md +19 -18
- package/docs/browser-use-architecture-phase2.md +63 -20
- package/docs/error-handling.md +111 -0
- package/docs/plugins.md +761 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +2 -1
- package/examples/plugins/echo/README.md +132 -0
- package/examples/plugins/echo/package.json +17 -0
- package/examples/plugins/echo/register.ts +187 -0
- 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/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
- package/openapi.yaml +334 -78
- 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__/app-compiler.test.ts +57 -0
- package/src/__tests__/approval-cascade.test.ts +36 -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__/auto-analysis-end-to-end.test.ts +1 -0
- package/src/__tests__/avatar-generator.test.ts +4 -2
- 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__/bundled-asset.test.ts +6 -6
- 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 +96 -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 +870 -655
- package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/compaction-events.test.ts +501 -0
- package/src/__tests__/compaction-pipeline.test.ts +210 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
- package/src/__tests__/compaction-timeout-recovery.test.ts +262 -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-model-image-provider.test.ts +110 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +440 -114
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +72 -73
- package/src/__tests__/contacts-tools.test.ts +26 -0
- package/src/__tests__/contacts-write.test.ts +4 -4
- package/src/__tests__/context-overflow-policy.test.ts +7 -7
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +883 -4
- package/src/__tests__/conversation-abort-tool-results.test.ts +32 -15
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +86 -46
- package/src/__tests__/conversation-agent-loop.test.ts +435 -216
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +36 -10
- package/src/__tests__/conversation-error.test.ts +37 -6
- package/src/__tests__/conversation-history-web-search.test.ts +7 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +34 -12
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pairing.test.ts +174 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +32 -15
- package/src/__tests__/conversation-process-callsite.test.ts +309 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +44 -21
- package/src/__tests__/conversation-queue.test.ts +68 -38
- package/src/__tests__/conversation-routes-disk-view.test.ts +36 -7
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2877 -152
- package/src/__tests__/conversation-runtime-workspace.test.ts +35 -50
- package/src/__tests__/conversation-seed-composer.test.ts +2 -2
- package/src/__tests__/conversation-skill-tools.test.ts +12 -146
- package/src/__tests__/conversation-slash-queue.test.ts +39 -19
- package/src/__tests__/conversation-slash-unknown.test.ts +53 -16
- package/src/__tests__/conversation-speed-override.test.ts +36 -12
- 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 +118 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -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 +4 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +33 -9
- package/src/__tests__/conversation-workspace-injection.test.ts +46 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +46 -15
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-health-service.test.ts +78 -9
- package/src/__tests__/credential-security-invariants.test.ts +5 -2
- 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__/db-schedule-syntax-migration.test.ts +1 -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__/empty-response-pipeline.test.ts +305 -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 +29 -10
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/first-greeting.test.ts +247 -5
- 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__/headless-browser-mode.test.ts +57 -0
- package/src/__tests__/heartbeat-service.test.ts +96 -15
- package/src/__tests__/history-repair-pipeline.test.ts +399 -0
- package/src/__tests__/host-browser-e2e-cloud.test.ts +307 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +3 -3
- package/src/__tests__/host-proxy-interface.test.ts +36 -2
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/image-credentials.test.ts +137 -0
- package/src/__tests__/image-service-dispatcher.test.ts +186 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/injector-chain.test.ts +526 -0
- package/src/__tests__/intent-routing.test.ts +1 -66
- package/src/__tests__/llm-call-pipeline.test.ts +285 -0
- 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__/media-generate-image.test.ts +119 -13
- package/src/__tests__/memory-retrieval-pipeline.test.ts +401 -0
- package/src/__tests__/memory-upsert-concurrency.test.ts +1 -0
- package/src/__tests__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-import-from-url.test.ts +621 -0
- package/src/__tests__/model-intents.test.ts +11 -83
- package/src/__tests__/notification-broadcaster.test.ts +3 -3
- 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__/notification-decision-strategy.test.ts +0 -11
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +108 -0
- package/src/__tests__/oauth-apps-routes.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +14 -12
- package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
- package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
- package/src/__tests__/oauth-provider-visibility.test.ts +3 -5
- package/src/__tests__/oauth-providers-routes.test.ts +3 -2
- package/src/__tests__/oauth-store.test.ts +46 -78
- package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/onboarding-template-contract.test.ts +16 -64
- package/src/__tests__/openai-image-service.test.ts +368 -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__/overflow-reduce-pipeline.test.ts +676 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -25
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
- package/src/__tests__/persistence-pipeline.test.ts +377 -0
- package/src/__tests__/persona-resolver.test.ts +13 -13
- package/src/__tests__/pipeline-runner.test.ts +565 -0
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/platform.test.ts +5 -2
- package/src/__tests__/plugin-bootstrap.test.ts +483 -0
- package/src/__tests__/plugin-registry.test.ts +273 -0
- package/src/__tests__/plugin-route-contribution.test.ts +288 -0
- package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +286 -0
- package/src/__tests__/plugin-types.test.ts +320 -0
- package/src/__tests__/pricing.test.ts +93 -14
- 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 +69 -9
- package/src/__tests__/reaction-persistence.test.ts +561 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +0 -2
- 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__/schedule-routes.test.ts +131 -1
- package/src/__tests__/scheduler-recurrence.test.ts +14 -70
- package/src/__tests__/scheduler-reuse-conversation.test.ts +10 -50
- package/src/__tests__/secret-detection-handler.test.ts +0 -10
- 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-identity.test.ts +0 -134
- 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 +259 -3
- package/src/__tests__/system-prompt.test.ts +22 -35
- package/src/__tests__/task-memory-cleanup.test.ts +1 -0
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/task-scheduler.test.ts +3 -15
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-preload.ts +11 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/title-generate-pipeline.test.ts +224 -0
- package/src/__tests__/token-estimate-pipeline.test.ts +431 -0
- package/src/__tests__/tool-error-pipeline.test.ts +244 -0
- package/src/__tests__/tool-execute-pipeline.test.ts +431 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -8
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
- package/src/__tests__/tool-executor.test.ts +201 -94
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -110
- 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__/user-plugin-loader.test.ts +191 -0
- 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-046-seed-conversation-starters-callsite.test.ts +185 -0
- package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
- package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
- package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +22 -16
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/loop.ts +545 -115
- package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
- package/src/approvals/guardian-request-resolvers.ts +80 -0
- 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/backup/__tests__/backup-worker.test.ts +2 -13
- package/src/backup/backup-worker.ts +3 -15
- 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/bundler/app-compiler.ts +84 -1
- package/src/calls/call-state.ts +2 -2
- 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/channels/__tests__/types.test.ts +3 -3
- package/src/channels/types.ts +6 -4
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/__tests__/notifications.test.ts +87 -211
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/backup.test.ts +1 -1
- 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 +886 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +463 -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 +606 -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/backup.ts +2 -2
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/clients.ts +138 -0
- package/src/cli/commands/completions.ts +2 -12
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +69 -8
- package/src/cli/commands/email.ts +234 -194
- package/src/cli/commands/image-generation.ts +299 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/notifications.ts +68 -103
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/connect.ts +2 -2
- package/src/cli/commands/oauth/providers.ts +176 -8
- package/src/cli/commands/oauth/status.ts +46 -36
- 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/skills.ts +3 -4
- 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 +39 -24
- package/src/cli.ts +0 -37
- package/src/config/__tests__/backup-schema.test.ts +7 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +28 -51
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +22 -40
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +20 -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 +69 -12
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
- package/src/config/bundled-skills/schedule/SKILL.md +8 -3
- package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
- package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-tool-registry.ts +0 -190
- package/src/config/env.ts +7 -2
- package/src/config/feature-flag-registry.json +42 -10
- 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 +49 -41
- package/src/config/schemas/analysis.ts +3 -22
- package/src/config/schemas/backup.ts +1 -1
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/conversations.ts +16 -0
- 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 +317 -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 +64 -0
- package/src/config/schemas/updates.ts +1 -1
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skill-state.ts +6 -2
- package/src/config/skills.ts +96 -7
- package/src/context/__tests__/compact-prompt.test.ts +63 -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 +26 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/tool-result-truncation.ts +3 -63
- package/src/context/window-manager.ts +417 -39
- 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/credential-health/credential-health-service.ts +19 -6
- package/src/daemon/__tests__/conversation-feed-event.test.ts +317 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
- 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 -3
- package/src/daemon/context-overflow-policy.ts +4 -13
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +162 -34
- package/src/daemon/conversation-agent-loop.ts +1282 -599
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +36 -1
- package/src/daemon/conversation-history.ts +10 -19
- package/src/daemon/conversation-lifecycle.ts +59 -17
- package/src/daemon/conversation-messaging.ts +73 -4
- package/src/daemon/conversation-notifiers.ts +2 -110
- package/src/daemon/conversation-process.ts +24 -11
- package/src/daemon/conversation-queue-manager.ts +3 -0
- package/src/daemon/conversation-runtime-assembly.ts +1063 -211
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +389 -1
- package/src/daemon/conversation-tool-setup.ts +51 -9
- package/src/daemon/conversation-usage.ts +1 -1
- package/src/daemon/conversation.ts +197 -64
- package/src/daemon/external-plugins-bootstrap.ts +478 -0
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/first-greeting.ts +191 -14
- 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 +65 -12
- package/src/daemon/handlers/conversations.ts +9 -2
- package/src/daemon/handlers/shared.ts +39 -11
- package/src/daemon/handlers/skills.ts +7 -3
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/lifecycle.ts +109 -82
- package/src/daemon/message-types/computer-use.ts +2 -34
- package/src/daemon/message-types/conversations.ts +63 -0
- package/src/daemon/message-types/messages.ts +21 -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 +122 -12
- package/src/daemon/shutdown-handlers.ts +2 -12
- package/src/daemon/tool-side-effects.ts +14 -65
- 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/__tests__/heartbeat-feed-event.test.ts +160 -0
- package/src/heartbeat/heartbeat-service.ts +99 -28
- package/src/home/__tests__/feed-population-integration.test.ts +312 -0
- 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 +11 -0
- package/src/home/feed-scheduler.ts +20 -4
- package/src/home/feed-types.ts +97 -4
- package/src/home/relationship-state-writer.ts +2 -2
- package/src/home/rewrite-command-preview.ts +66 -0
- 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 +34 -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 +6 -3
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +63 -0
- package/src/ipc/routes/browser.ts +97 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/get-contact.ts +16 -0
- package/src/ipc/routes/index.ts +31 -1
- package/src/ipc/routes/list-clients.ts +31 -0
- package/src/ipc/routes/merge-contacts.ts +17 -0
- package/src/ipc/routes/notification.ts +133 -0
- package/src/ipc/routes/rename-conversation.ts +59 -0
- package/src/ipc/routes/search-contacts.ts +19 -0
- 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/upsert-contact.ts +25 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +76 -0
- package/src/media/app-icon-generator.ts +23 -46
- package/src/media/avatar-router.ts +26 -41
- package/src/media/gemini-image-service.ts +8 -41
- package/src/media/image-credentials.ts +73 -0
- package/src/media/image-service.ts +85 -0
- package/src/media/openai-image-service.ts +131 -0
- package/src/media/types.ts +46 -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 +133 -3
- package/src/memory/conversation-group-migration.ts +38 -6
- package/src/memory/conversation-queries.ts +57 -4
- package/src/memory/conversation-title-service.ts +32 -4
- package/src/memory/db-init.ts +10 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/embedding-gemini.test.ts +41 -2
- package/src/memory/embedding-gemini.ts +6 -1
- package/src/memory/graph/bootstrap.test.ts +282 -0
- package/src/memory/graph/bootstrap.ts +8 -5
- 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 +183 -53
- package/src/memory/graph/graph-search.test.ts +93 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/inspect.ts +2 -2
- 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 +237 -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/041-approval-prompt-ts-tracker.ts +26 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- package/src/memory/migrations/149-oauth-tables.ts +1 -0
- 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/223-schedule-script-column.ts +11 -0
- package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
- package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/pkb/pkb-index.test.ts +369 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +252 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +499 -0
- package/src/memory/pkb/pkb-search.ts +159 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.test.ts +60 -0
- package/src/memory/qdrant-client.ts +147 -1
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/schema/oauth.ts +4 -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 +1421 -0
- package/src/messaging/providers/slack/render-transcript.ts +501 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/conversation-pairing.ts +78 -19
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/decision-engine.ts +3 -9
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/notifications/signal.ts +1 -2
- package/src/oauth/AGENTS.md +1 -1
- package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
- package/src/oauth/connect-orchestrator.ts +8 -34
- package/src/oauth/connect-types.ts +6 -10
- package/src/oauth/manual-token-connection.ts +23 -0
- package/src/oauth/oauth-store.ts +31 -14
- package/src/oauth/platform-connection.test.ts +47 -0
- package/src/oauth/platform-connection.ts +15 -5
- package/src/oauth/provider-serializer.ts +6 -1
- package/src/oauth/seed-providers.ts +56 -106
- package/src/outbound-proxy/http-forwarder.ts +9 -0
- package/src/permissions/approval-policy.test.ts +1223 -0
- package/src/permissions/approval-policy.ts +309 -0
- package/src/permissions/arg-parser.test.ts +161 -0
- package/src/permissions/arg-parser.ts +141 -0
- package/src/permissions/bash-risk-classifier.test.ts +1620 -0
- package/src/permissions/bash-risk-classifier.ts +950 -0
- package/src/permissions/checker.ts +348 -711
- package/src/permissions/command-registry.test.ts +774 -0
- package/src/permissions/command-registry.ts +1005 -0
- package/src/permissions/defaults.ts +28 -79
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/gateway-threshold-reader.ts +196 -0
- package/src/permissions/prompter.ts +4 -0
- package/src/permissions/risk-types.ts +262 -0
- package/src/permissions/schedule-risk-classifier.test.ts +129 -0
- package/src/permissions/schedule-risk-classifier.ts +85 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/shell-identity.ts +2 -42
- 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 +25 -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 +9 -19
- package/src/platform/client.ts +19 -1
- package/src/plugins/defaults/circuit-breaker.ts +146 -0
- package/src/plugins/defaults/compaction.ts +145 -0
- package/src/plugins/defaults/empty-response.ts +126 -0
- package/src/plugins/defaults/history-repair.ts +85 -0
- package/src/plugins/defaults/index.ts +116 -0
- package/src/plugins/defaults/injectors.ts +491 -0
- package/src/plugins/defaults/llm-call.ts +82 -0
- package/src/plugins/defaults/memory-retrieval.ts +226 -0
- package/src/plugins/defaults/overflow-reduce.ts +181 -0
- package/src/plugins/defaults/persistence.ts +129 -0
- package/src/plugins/defaults/title-generate.ts +95 -0
- package/src/plugins/defaults/token-estimate.ts +104 -0
- package/src/plugins/defaults/tool-error.ts +126 -0
- package/src/plugins/defaults/tool-execute.ts +89 -0
- package/src/plugins/defaults/tool-result-truncate.ts +88 -0
- package/src/plugins/pipeline.ts +316 -0
- package/src/plugins/plugin-skill-contributions.ts +292 -0
- package/src/plugins/registry.ts +241 -0
- package/src/plugins/types.ts +1134 -0
- package/src/plugins/user-loader.ts +177 -0
- package/src/prompts/persona-resolver.ts +3 -3
- package/src/prompts/system-prompt.ts +19 -20
- package/src/prompts/templates/BOOTSTRAP.md +27 -77
- 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 +524 -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 +80 -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/deepgram-realtime.test.ts +61 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +57 -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 +646 -0
- package/src/providers/speech-to-text/xai-realtime.ts +821 -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 +27 -18
- package/src/runtime/__tests__/agent-wake.test.ts +43 -2
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +3 -3
- package/src/runtime/__tests__/client-registry.test.ts +293 -0
- 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/client-registry.ts +261 -0
- 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 +129 -9
- package/src/runtime/http-types.ts +23 -3
- 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-builder.ts +1 -22
- 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 +78 -0
- package/src/runtime/routes/approval-routes.ts +29 -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/browser-extension-pair-routes.ts +27 -8
- 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 +351 -138
- 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 +987 -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/memory-item-routes.test.ts +1 -0
- package/src/runtime/routes/migration-routes.ts +720 -127
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +284 -0
- package/src/runtime/routes/playground/__tests__/guard.test.ts +80 -0
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +294 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +271 -0
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +202 -0
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +309 -0
- package/src/runtime/routes/playground/__tests__/state.test.ts +224 -0
- package/src/runtime/routes/playground/conversation-not-found.ts +29 -0
- package/src/runtime/routes/playground/deps.ts +56 -0
- package/src/runtime/routes/playground/force-compact.ts +73 -0
- package/src/runtime/routes/playground/guard.ts +37 -0
- package/src/runtime/routes/playground/index.ts +28 -0
- package/src/runtime/routes/playground/inject-failures.ts +159 -0
- package/src/runtime/routes/playground/reset-circuit.ts +115 -0
- package/src/runtime/routes/playground/seed-conversation.ts +139 -0
- package/src/runtime/routes/playground/seeded-conversations.ts +78 -0
- package/src/runtime/routes/playground/state.ts +78 -0
- package/src/runtime/routes/schedule-routes.ts +89 -8
- 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 +97 -15
- package/src/schedule/run-script.ts +68 -0
- package/src/schedule/schedule-store.ts +7 -1
- package/src/schedule/scheduler.ts +56 -8
- 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 +35 -9
- 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 +234 -2
- package/src/tools/browser/browser-execution.ts +150 -54
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
- package/src/tools/browser/cdp-client/factory.ts +15 -4
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +9 -4
- package/src/tools/executor.ts +129 -73
- 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/script-proxy/session-manager.ts +37 -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 +116 -46
- package/src/tools/policy-context.ts +29 -8
- package/src/tools/registry.ts +195 -6
- package/src/tools/schedule/create.ts +23 -8
- package/src/tools/schedule/update.ts +3 -1
- package/src/tools/secret-detection-handler.ts +0 -51
- 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/system/avatar-generator.ts +6 -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 +40 -5
- 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 +9 -4
- package/src/util/pricing.ts +41 -8
- 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/006-services-config.ts +2 -4
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
- 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 +56 -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/046-seed-conversation-starters-callsite.ts +108 -0
- package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
- package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +28 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/tsconfig.json +1 -1
- package/hook-templates/debug-prompt-logger/hook.json +0 -7
- package/hook-templates/debug-prompt-logger/run.sh +0 -66
- package/src/__tests__/context-overflow-approval.test.ts +0 -156
- 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__/hooks-blocking.test.ts +0 -178
- package/src/__tests__/hooks-cli.test.ts +0 -182
- package/src/__tests__/hooks-config.test.ts +0 -108
- package/src/__tests__/hooks-discovery.test.ts +0 -211
- package/src/__tests__/hooks-integration.test.ts +0 -196
- package/src/__tests__/hooks-manager.test.ts +0 -226
- package/src/__tests__/hooks-runner.test.ts +0 -175
- package/src/__tests__/hooks-settings.test.ts +0 -160
- package/src/__tests__/hooks-templates.test.ts +0 -169
- package/src/__tests__/hooks-ts-runner.test.ts +0 -170
- package/src/__tests__/hooks-watch.test.ts +0 -112
- package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
- package/src/__tests__/oauth-scope-policy.test.ts +0 -180
- 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__/send-notification-tool.test.ts +0 -83
- 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/cli/commands/shotgun.ts +0 -266
- 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/conversations/SKILL.md +0 -20
- package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -66
- 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/heartbeat/SKILL.md +0 -43
- package/src/config/bundled-skills/notifications/SKILL.md +0 -40
- package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
- package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
- 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/screen-watch/SKILL.md +0 -27
- package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
- package/src/config/bundled-skills/screen-watch/tools/start-screen-watch.ts +0 -12
- package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
- 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/daemon/context-overflow-approval.ts +0 -52
- package/src/daemon/watch-handler.ts +0 -399
- package/src/hooks/cli.ts +0 -253
- package/src/hooks/config.ts +0 -100
- package/src/hooks/discovery.ts +0 -135
- package/src/hooks/manager.ts +0 -179
- package/src/hooks/runner.ts +0 -117
- package/src/hooks/templates.ts +0 -77
- package/src/hooks/types.ts +0 -75
- package/src/oauth/scope-policy.ts +0 -89
- 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/runtime/gateway-internal-client.ts +0 -94
- package/src/runtime/routes/watch-routes.ts +0 -156
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/signals/shotgun.ts +0 -203
- package/src/tools/watch/screen-watch.ts +0 -144
- package/src/tools/watch/watch-state.ts +0 -142
- 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
|
@@ -8,6 +8,7 @@ import { z } from "zod";
|
|
|
8
8
|
|
|
9
9
|
import { bootstrapConversation } from "../../memory/conversation-bootstrap.js";
|
|
10
10
|
import { getConversation } from "../../memory/conversation-crud.js";
|
|
11
|
+
import { runScript } from "../../schedule/run-script.js";
|
|
11
12
|
import {
|
|
12
13
|
cancelSchedule,
|
|
13
14
|
completeScheduleRun,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
describeCronExpression,
|
|
17
18
|
getLastScheduleConversationId,
|
|
18
19
|
getSchedule,
|
|
20
|
+
getScheduleRuns,
|
|
19
21
|
listSchedules,
|
|
20
22
|
updateSchedule,
|
|
21
23
|
} from "../../schedule/schedule-store.js";
|
|
@@ -46,6 +48,7 @@ function handleListSchedules(): Response {
|
|
|
46
48
|
cronExpression: j.cronExpression,
|
|
47
49
|
timezone: j.timezone,
|
|
48
50
|
message: j.message,
|
|
51
|
+
script: j.script,
|
|
49
52
|
nextRunAt: j.nextRunAt,
|
|
50
53
|
lastRunAt: j.lastRunAt,
|
|
51
54
|
lastStatus: j.lastStatus,
|
|
@@ -108,7 +111,7 @@ function handleCancelSchedule(id: string): Response {
|
|
|
108
111
|
return handleListSchedules();
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
const VALID_MODES = ["notify", "execute"] as const;
|
|
114
|
+
const VALID_MODES = ["notify", "execute", "script"] as const;
|
|
112
115
|
const VALID_ROUTING_INTENTS = [
|
|
113
116
|
"single_channel",
|
|
114
117
|
"multi_channel",
|
|
@@ -149,6 +152,7 @@ function handleUpdateSchedule(
|
|
|
149
152
|
"expression",
|
|
150
153
|
"timezone",
|
|
151
154
|
"message",
|
|
155
|
+
"script",
|
|
152
156
|
"mode",
|
|
153
157
|
"routingIntent",
|
|
154
158
|
"quiet",
|
|
@@ -178,6 +182,28 @@ function handleUpdateSchedule(
|
|
|
178
182
|
return handleListSchedules();
|
|
179
183
|
}
|
|
180
184
|
|
|
185
|
+
function handleListScheduleRuns(id: string, limit: number): Response {
|
|
186
|
+
const schedule = getSchedule(id);
|
|
187
|
+
if (!schedule) {
|
|
188
|
+
return httpError("NOT_FOUND", "Schedule not found", 404);
|
|
189
|
+
}
|
|
190
|
+
const runs = getScheduleRuns(id, limit);
|
|
191
|
+
return Response.json({
|
|
192
|
+
runs: runs.map((r) => ({
|
|
193
|
+
id: r.id,
|
|
194
|
+
jobId: r.jobId,
|
|
195
|
+
status: r.status,
|
|
196
|
+
startedAt: r.startedAt,
|
|
197
|
+
finishedAt: r.finishedAt,
|
|
198
|
+
durationMs: r.durationMs,
|
|
199
|
+
output: r.output,
|
|
200
|
+
error: r.error,
|
|
201
|
+
conversationId: r.conversationId,
|
|
202
|
+
createdAt: r.createdAt,
|
|
203
|
+
})),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
181
207
|
async function handleRunScheduleNow(
|
|
182
208
|
id: string,
|
|
183
209
|
sendMessageDeps?: SendMessageDeps,
|
|
@@ -187,6 +213,38 @@ async function handleRunScheduleNow(
|
|
|
187
213
|
return httpError("NOT_FOUND", "Schedule not found", 404);
|
|
188
214
|
}
|
|
189
215
|
|
|
216
|
+
// ── Script mode (shell command, no LLM) ──────────────────────────
|
|
217
|
+
if (schedule.mode === "script") {
|
|
218
|
+
if (!schedule.script) {
|
|
219
|
+
return httpError(
|
|
220
|
+
"BAD_REQUEST",
|
|
221
|
+
"Script schedule has no script command",
|
|
222
|
+
400,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
const runId = createScheduleRun(schedule.id, `script:${schedule.id}`);
|
|
226
|
+
try {
|
|
227
|
+
log.info(
|
|
228
|
+
{ jobId: schedule.id, name: schedule.name },
|
|
229
|
+
"Executing script schedule manually via HTTP (run now)",
|
|
230
|
+
);
|
|
231
|
+
const result = await runScript(schedule.script);
|
|
232
|
+
completeScheduleRun(runId, {
|
|
233
|
+
status: result.exitCode === 0 ? "ok" : "error",
|
|
234
|
+
output: result.stdout || undefined,
|
|
235
|
+
error: result.stderr || undefined,
|
|
236
|
+
});
|
|
237
|
+
} catch (err) {
|
|
238
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
239
|
+
log.warn(
|
|
240
|
+
{ err, jobId: schedule.id, name: schedule.name },
|
|
241
|
+
"Manual script schedule execution failed",
|
|
242
|
+
);
|
|
243
|
+
completeScheduleRun(runId, { status: "error", error: errorMsg });
|
|
244
|
+
}
|
|
245
|
+
return handleListSchedules();
|
|
246
|
+
}
|
|
247
|
+
|
|
190
248
|
// Check if message is a task invocation (run_task:<task_id>)
|
|
191
249
|
const taskMatch = schedule.message.match(/^run_task:(\S+)$/);
|
|
192
250
|
if (taskMatch) {
|
|
@@ -205,10 +263,12 @@ async function handleRunScheduleNow(
|
|
|
205
263
|
"sendMessageDeps not available for schedule execution",
|
|
206
264
|
);
|
|
207
265
|
}
|
|
208
|
-
const conversation =
|
|
209
|
-
|
|
266
|
+
const conversation = await sendMessageDeps.getOrCreateConversation(
|
|
267
|
+
conversationId,
|
|
268
|
+
{
|
|
210
269
|
trustContext: SCHEDULE_GUARDIAN_TRUST_CONTEXT,
|
|
211
|
-
}
|
|
270
|
+
},
|
|
271
|
+
);
|
|
212
272
|
conversation.taskRunId = taskRunId;
|
|
213
273
|
try {
|
|
214
274
|
await conversation.processMessage(
|
|
@@ -285,10 +345,12 @@ async function handleRunScheduleNow(
|
|
|
285
345
|
if (!sendMessageDeps) {
|
|
286
346
|
throw new Error("sendMessageDeps not available for schedule execution");
|
|
287
347
|
}
|
|
288
|
-
const activeConversation =
|
|
289
|
-
|
|
348
|
+
const activeConversation = await sendMessageDeps.getOrCreateConversation(
|
|
349
|
+
conversationId,
|
|
350
|
+
{
|
|
290
351
|
trustContext: SCHEDULE_GUARDIAN_TRUST_CONTEXT,
|
|
291
|
-
}
|
|
352
|
+
},
|
|
353
|
+
);
|
|
292
354
|
activeConversation.taskRunId = undefined;
|
|
293
355
|
await activeConversation.processMessage(
|
|
294
356
|
schedule.message,
|
|
@@ -331,6 +393,24 @@ export function scheduleRouteDefinitions(deps: {
|
|
|
331
393
|
}),
|
|
332
394
|
handler: () => handleListSchedules(),
|
|
333
395
|
},
|
|
396
|
+
{
|
|
397
|
+
endpoint: "schedules/:id/runs",
|
|
398
|
+
method: "GET",
|
|
399
|
+
policyKey: "schedules",
|
|
400
|
+
summary: "List schedule runs",
|
|
401
|
+
description: "Return recent invocation history for a schedule.",
|
|
402
|
+
tags: ["schedules"],
|
|
403
|
+
responseBody: z.object({
|
|
404
|
+
runs: z.array(z.unknown()).describe("Schedule run objects"),
|
|
405
|
+
}),
|
|
406
|
+
handler: ({ params, url }) => {
|
|
407
|
+
const rawLimit = Number(url.searchParams.get("limit") ?? 10);
|
|
408
|
+
const limit = Number.isFinite(rawLimit)
|
|
409
|
+
? Math.min(Math.max(Math.floor(rawLimit), 1), 100)
|
|
410
|
+
: 10;
|
|
411
|
+
return handleListScheduleRuns(params.id, limit);
|
|
412
|
+
},
|
|
413
|
+
},
|
|
334
414
|
{
|
|
335
415
|
endpoint: "schedules/:id/toggle",
|
|
336
416
|
method: "POST",
|
|
@@ -376,7 +456,8 @@ export function scheduleRouteDefinitions(deps: {
|
|
|
376
456
|
expression: z.string(),
|
|
377
457
|
timezone: z.string(),
|
|
378
458
|
message: z.string(),
|
|
379
|
-
|
|
459
|
+
script: z.string().nullable().describe("Shell command for script mode"),
|
|
460
|
+
mode: z.string().describe("notify, execute, or script"),
|
|
380
461
|
routingIntent: z
|
|
381
462
|
.string()
|
|
382
463
|
.describe("single_channel, multi_channel, or all_channels"),
|
|
@@ -477,9 +477,11 @@ async function handleToolPermissionSimulate(body: {
|
|
|
477
477
|
body.toolName,
|
|
478
478
|
manifestOverride,
|
|
479
479
|
);
|
|
480
|
-
const
|
|
480
|
+
const executionContext =
|
|
481
|
+
body.isInteractive === false ? "headless" : "conversation";
|
|
482
|
+
const policyContext = { executionTarget, executionContext } as const;
|
|
481
483
|
|
|
482
|
-
const riskLevel = await classifyRisk(
|
|
484
|
+
const { level: riskLevel } = await classifyRisk(
|
|
483
485
|
body.toolName,
|
|
484
486
|
body.input,
|
|
485
487
|
workingDir,
|
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
* These endpoints manage persistent trust rules independently of
|
|
5
5
|
* the approval-flow trust-rule endpoint in approval-routes.ts.
|
|
6
6
|
* All endpoints are bearer-token authenticated (standard runtime auth).
|
|
7
|
+
*
|
|
8
|
+
* Canonicalization is handled centrally inside `addRule`/`updateRule` in
|
|
9
|
+
* trust-store.ts: legacy clients can keep sending current shapes without
|
|
10
|
+
* 4xx regressions, but fields invalid for a tool's family (e.g.
|
|
11
|
+
* `executionTarget` on a URL-tool rule) are silently stripped.
|
|
7
12
|
*/
|
|
13
|
+
import { SCOPED_TOOLS } from "@vellumai/ces-contracts";
|
|
8
14
|
import { z } from "zod";
|
|
9
15
|
|
|
10
16
|
import {
|
|
@@ -17,6 +23,9 @@ import { getLogger } from "../../util/logger.js";
|
|
|
17
23
|
import { httpError } from "../http-errors.js";
|
|
18
24
|
import type { RouteDefinition } from "../http-router.js";
|
|
19
25
|
|
|
26
|
+
/** O(1) lookup set for scoped tool names. */
|
|
27
|
+
const SCOPED_TOOLS_SET: ReadonlySet<string> = new Set(SCOPED_TOOLS);
|
|
28
|
+
|
|
20
29
|
const log = getLogger("trust-rules-routes");
|
|
21
30
|
|
|
22
31
|
/**
|
|
@@ -30,7 +39,11 @@ function handleListTrustRules(): Response {
|
|
|
30
39
|
/**
|
|
31
40
|
* POST /v1/trust-rules/manage — add a trust rule (standalone, not approval-flow).
|
|
32
41
|
*
|
|
33
|
-
* Body: { toolName, pattern, scope, decision,
|
|
42
|
+
* Body: { toolName, pattern, scope, decision, executionTarget? }
|
|
43
|
+
*
|
|
44
|
+
* Legacy payloads that include fields invalid for the tool's family (e.g.
|
|
45
|
+
* `executionTarget` on a `web_fetch` rule) are accepted but canonicalized:
|
|
46
|
+
* the invalid fields are stripped before persistence.
|
|
34
47
|
*/
|
|
35
48
|
export async function handleAddTrustRuleManage(
|
|
36
49
|
req: Request,
|
|
@@ -40,12 +53,10 @@ export async function handleAddTrustRuleManage(
|
|
|
40
53
|
pattern?: string;
|
|
41
54
|
scope?: string;
|
|
42
55
|
decision?: string;
|
|
43
|
-
allowHighRisk?: boolean;
|
|
44
56
|
executionTarget?: string;
|
|
45
57
|
};
|
|
46
58
|
|
|
47
|
-
const { toolName, pattern, scope, decision,
|
|
48
|
-
body;
|
|
59
|
+
const { toolName, pattern, scope, decision, executionTarget } = body;
|
|
49
60
|
|
|
50
61
|
if (!toolName || typeof toolName !== "string") {
|
|
51
62
|
return httpError("BAD_REQUEST", "toolName is required", 400);
|
|
@@ -60,8 +71,10 @@ export async function handleAddTrustRuleManage(
|
|
|
60
71
|
if (!pattern || typeof pattern !== "string") {
|
|
61
72
|
return httpError("BAD_REQUEST", "pattern is required", 400);
|
|
62
73
|
}
|
|
63
|
-
|
|
64
|
-
|
|
74
|
+
// Scope is only required for scoped tools. Non-scoped tools ignore scope.
|
|
75
|
+
const isScoped = SCOPED_TOOLS_SET.has(toolName);
|
|
76
|
+
if (isScoped && (!scope || typeof scope !== "string")) {
|
|
77
|
+
return httpError("BAD_REQUEST", "scope is required for scoped tools", 400);
|
|
65
78
|
}
|
|
66
79
|
const validDecisions = ["allow", "deny", "ask"] as const;
|
|
67
80
|
if (
|
|
@@ -76,14 +89,18 @@ export async function handleAddTrustRuleManage(
|
|
|
76
89
|
}
|
|
77
90
|
|
|
78
91
|
try {
|
|
79
|
-
|
|
92
|
+
// Canonicalization is handled inside addRule — no need to pre-parse here.
|
|
93
|
+
// Legacy callers that send e.g. executionTarget on a URL-tool rule won't
|
|
94
|
+
// get a 4xx — the field is simply dropped during normalization in addRule.
|
|
80
95
|
addRule(
|
|
81
96
|
toolName,
|
|
82
97
|
pattern,
|
|
83
|
-
scope,
|
|
98
|
+
isScoped ? scope! : "everywhere",
|
|
84
99
|
decision as "allow" | "deny" | "ask",
|
|
85
100
|
undefined,
|
|
86
|
-
|
|
101
|
+
{
|
|
102
|
+
...(executionTarget != null ? { executionTarget } : {}),
|
|
103
|
+
},
|
|
87
104
|
);
|
|
88
105
|
log.info(
|
|
89
106
|
{ toolName, pattern, scope, decision },
|
|
@@ -197,12 +214,11 @@ export function trustRulesRouteDefinitions(): RouteDefinition[] {
|
|
|
197
214
|
requestBody: z.object({
|
|
198
215
|
toolName: z.string().describe("Tool name"),
|
|
199
216
|
pattern: z.string().describe("Allowlist pattern"),
|
|
200
|
-
scope: z
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
.boolean()
|
|
204
|
-
.describe("Allow high-risk invocations")
|
|
217
|
+
scope: z
|
|
218
|
+
.string()
|
|
219
|
+
.describe("Scope (required for scoped tools, ignored for others)")
|
|
205
220
|
.optional(),
|
|
221
|
+
decision: z.string().describe("allow, deny, or ask"),
|
|
206
222
|
executionTarget: z.string().describe("Execution target").optional(),
|
|
207
223
|
}),
|
|
208
224
|
responseBody: z.object({
|
|
@@ -16,7 +16,7 @@ mock.module("../../util/logger.js", () => ({
|
|
|
16
16
|
|
|
17
17
|
mock.module("../../permissions/checker.js", () => ({
|
|
18
18
|
check: async () => ({ decision: "prompt" }),
|
|
19
|
-
classifyRisk: async () => "high",
|
|
19
|
+
classifyRisk: async () => ({ level: "high" }),
|
|
20
20
|
}));
|
|
21
21
|
|
|
22
22
|
import { initializeDb } from "../../memory/db.js";
|
|
@@ -354,10 +354,11 @@ export async function preflightWorkItem(
|
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
const workingDir = process.cwd();
|
|
357
|
+
const policyContext = { executionContext: "headless" as const };
|
|
357
358
|
const permissions = await Promise.all(
|
|
358
359
|
requiredTools.map(async (tool) => {
|
|
359
|
-
const risk = await classifyRisk(tool, {}, workingDir);
|
|
360
|
-
const result = await check(tool, {}, workingDir);
|
|
360
|
+
const { level: risk } = await classifyRisk(tool, {}, workingDir);
|
|
361
|
+
const result = await check(tool, {}, workingDir, policyContext);
|
|
361
362
|
return {
|
|
362
363
|
tool,
|
|
363
364
|
description: getToolDescription(tool),
|
|
@@ -50,23 +50,6 @@ mock.module("../../../export/transcript-formatter.js", () => ({
|
|
|
50
50
|
buildAnalysisTranscript: () => "user: hi",
|
|
51
51
|
}));
|
|
52
52
|
|
|
53
|
-
// Default config stub — individual tests can override via mockGetConfig.
|
|
54
|
-
interface AnalysisConfigStub {
|
|
55
|
-
analysis: {
|
|
56
|
-
modelIntent?: string;
|
|
57
|
-
modelOverride?: string;
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
const mockGetConfig = mock(
|
|
61
|
-
(): AnalysisConfigStub => ({
|
|
62
|
-
analysis: {},
|
|
63
|
-
}),
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
mock.module("../../../config/loader.js", () => ({
|
|
67
|
-
getConfig: mockGetConfig,
|
|
68
|
-
}));
|
|
69
|
-
|
|
70
53
|
import { AssistantEventHub } from "../../assistant-event-hub.js";
|
|
71
54
|
import type { SendMessageDeps } from "../../http-types.js";
|
|
72
55
|
import { analyzeConversation } from "../analyze-conversation.js";
|
|
@@ -90,8 +73,6 @@ beforeEach(() => {
|
|
|
90
73
|
mockFindAnalysisConversationFor.mockImplementation(() => null);
|
|
91
74
|
mockGetConversationSource.mockReset();
|
|
92
75
|
mockGetConversationSource.mockImplementation(() => null);
|
|
93
|
-
mockGetConfig.mockReset();
|
|
94
|
-
mockGetConfig.mockImplementation(() => ({ analysis: {} }));
|
|
95
76
|
});
|
|
96
77
|
|
|
97
78
|
function makeConversation() {
|
|
@@ -221,12 +202,17 @@ describe("analyzeConversation", () => {
|
|
|
221
202
|
expect(allowedTools).toBeInstanceOf(Set);
|
|
222
203
|
expect(allowedTools?.size).toBe(0);
|
|
223
204
|
|
|
224
|
-
// Fires the agent loop
|
|
205
|
+
// Fires the agent loop with the analyzeConversation call-site so the
|
|
206
|
+
// per-call provider config flows through `resolveCallSiteConfig`.
|
|
225
207
|
expect(conversation.runAgentLoop).toHaveBeenCalledWith(
|
|
226
208
|
expect.any(String),
|
|
227
209
|
"msg-1",
|
|
228
210
|
expect.any(Function),
|
|
229
|
-
expect.objectContaining({
|
|
211
|
+
expect.objectContaining({
|
|
212
|
+
isInteractive: false,
|
|
213
|
+
isUserMessage: true,
|
|
214
|
+
callSite: "analyzeConversation",
|
|
215
|
+
}),
|
|
230
216
|
);
|
|
231
217
|
});
|
|
232
218
|
|
|
@@ -405,40 +391,36 @@ describe("analyzeConversation", () => {
|
|
|
405
391
|
expect(mockAddMessage).not.toHaveBeenCalled();
|
|
406
392
|
});
|
|
407
393
|
|
|
408
|
-
test("auto:
|
|
409
|
-
mockGetConfig.mockImplementation(() => ({
|
|
410
|
-
analysis: {
|
|
411
|
-
modelIntent: "quality-optimized",
|
|
412
|
-
modelOverride: "claude-opus-4-6",
|
|
413
|
-
},
|
|
414
|
-
}));
|
|
394
|
+
test("auto: routes the agent loop through callSite: 'analyzeConversation'", async () => {
|
|
415
395
|
const conversation = makeConversation();
|
|
416
396
|
const deps = makeDeps(conversation);
|
|
417
397
|
|
|
418
398
|
await analyzeConversation("conv-1", deps, { trigger: "auto" });
|
|
419
399
|
|
|
420
|
-
expect(
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}),
|
|
400
|
+
expect(conversation.runAgentLoop).toHaveBeenCalledWith(
|
|
401
|
+
expect.any(String),
|
|
402
|
+
"msg-1",
|
|
403
|
+
expect.any(Function),
|
|
404
|
+
expect.objectContaining({ callSite: "analyzeConversation" }),
|
|
426
405
|
);
|
|
427
406
|
});
|
|
428
407
|
|
|
429
|
-
test("
|
|
408
|
+
test("does not thread modelIntent/modelOverride into getOrCreateConversation", async () => {
|
|
409
|
+
// Per-call model selection now happens via the call-site resolver against
|
|
410
|
+
// `llm.callSites.analyzeConversation`, not via legacy modelIntent/
|
|
411
|
+
// modelOverride keys on the conversation create options.
|
|
430
412
|
const conversation = makeConversation();
|
|
431
413
|
const deps = makeDeps(conversation);
|
|
432
414
|
|
|
433
415
|
await analyzeConversation("conv-1", deps, { trigger: "auto" });
|
|
434
416
|
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
417
|
+
const calls = deps.getOrCreateConversation.mock
|
|
418
|
+
.calls as unknown as Array<[string, Record<string, unknown> | undefined]>;
|
|
419
|
+
expect(calls.length).toBe(1);
|
|
420
|
+
const passedOpts = calls[0]?.[1];
|
|
421
|
+
if (passedOpts !== undefined) {
|
|
422
|
+
expect("modelIntent" in passedOpts).toBe(false);
|
|
423
|
+
expect("modelOverride" in passedOpts).toBe(false);
|
|
424
|
+
}
|
|
443
425
|
});
|
|
444
426
|
});
|
|
@@ -8,15 +8,18 @@
|
|
|
8
8
|
* Two triggers are supported:
|
|
9
9
|
* - **manual**: user-initiated analysis. Creates a fresh conversation each
|
|
10
10
|
* invocation, runs with `trustClass: "unknown"`, and strips the tool
|
|
11
|
-
* surface.
|
|
11
|
+
* surface.
|
|
12
12
|
* - **auto**: called by the auto-analyze job when a source conversation
|
|
13
13
|
* reaches a natural pause. Reuses a rolling analysis conversation per
|
|
14
14
|
* parent (creating one if none exists), runs with `trustClass:
|
|
15
15
|
* "guardian"`, and keeps the full tool surface so the analysis agent can
|
|
16
|
-
* write memory and skills directly.
|
|
17
|
-
*
|
|
16
|
+
* write memory and skills directly.
|
|
17
|
+
*
|
|
18
|
+
* Both triggers route the agent loop through `callSite: 'analyzeConversation'`
|
|
19
|
+
* so per-call provider/model selection flows through `resolveCallSiteConfig`
|
|
20
|
+
* against `llm.callSites.analyzeConversation` (falling back to `llm.default`
|
|
21
|
+
* when no override is set).
|
|
18
22
|
*/
|
|
19
|
-
import { getConfig } from "../../config/loader.js";
|
|
20
23
|
import type { ServerMessage } from "../../daemon/message-protocol.js";
|
|
21
24
|
import {
|
|
22
25
|
AUTO_ANALYSIS_GROUP_ID,
|
|
@@ -31,7 +34,6 @@ import {
|
|
|
31
34
|
getMessages,
|
|
32
35
|
} from "../../memory/conversation-crud.js";
|
|
33
36
|
import { resolveConversationId } from "../../memory/conversation-key-store.js";
|
|
34
|
-
import type { ModelIntent } from "../../providers/types.js";
|
|
35
37
|
import { getLogger } from "../../util/logger.js";
|
|
36
38
|
import { buildAssistantEvent } from "../assistant-event.js";
|
|
37
39
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
@@ -173,8 +175,6 @@ export async function analyzeConversation(
|
|
|
173
175
|
let prompt: string;
|
|
174
176
|
let trustClass: "unknown" | "guardian";
|
|
175
177
|
let stripTools: boolean;
|
|
176
|
-
let modelIntent: ModelIntent | undefined;
|
|
177
|
-
let modelOverride: string | undefined;
|
|
178
178
|
|
|
179
179
|
if (opts.trigger === "manual") {
|
|
180
180
|
const newConv = createConversation({
|
|
@@ -205,10 +205,6 @@ export async function analyzeConversation(
|
|
|
205
205
|
prompt = buildAutoAnalysisPrompt(transcript);
|
|
206
206
|
trustClass = "guardian";
|
|
207
207
|
stripTools = false;
|
|
208
|
-
|
|
209
|
-
const analysisConfig = getConfig().analysis;
|
|
210
|
-
modelIntent = analysisConfig.modelIntent;
|
|
211
|
-
modelOverride = analysisConfig.modelOverride;
|
|
212
208
|
}
|
|
213
209
|
|
|
214
210
|
// h. Load the conversation into memory with the appropriate trust
|
|
@@ -219,13 +215,10 @@ export async function analyzeConversation(
|
|
|
219
215
|
// Hoisted ahead of message persistence so the auto branch can detect a
|
|
220
216
|
// still-running prior agent loop on the rolling conversation and bail out
|
|
221
217
|
// before mutating any state. See concurrency guard below.
|
|
218
|
+
//
|
|
222
219
|
const analysisConversation =
|
|
223
220
|
await deps.sendMessageDeps.getOrCreateConversation(
|
|
224
221
|
analysisConversationId,
|
|
225
|
-
{
|
|
226
|
-
...(modelIntent !== undefined ? { modelIntent } : {}),
|
|
227
|
-
...(modelOverride !== undefined ? { modelOverride } : {}),
|
|
228
|
-
},
|
|
229
222
|
);
|
|
230
223
|
|
|
231
224
|
// h.1. Concurrency guard (auto trigger only). The rolling analysis
|
|
@@ -298,11 +291,14 @@ export async function analyzeConversation(
|
|
|
298
291
|
analysisConversation.abortController = new AbortController();
|
|
299
292
|
analysisConversation.currentRequestId = crypto.randomUUID();
|
|
300
293
|
|
|
301
|
-
// l. Fire-and-forget the agent loop
|
|
294
|
+
// l. Fire-and-forget the agent loop. `callSite: 'analyzeConversation'`
|
|
295
|
+
// routes the per-call provider config through `resolveCallSiteConfig`
|
|
296
|
+
// against `llm.callSites.analyzeConversation`.
|
|
302
297
|
analysisConversation
|
|
303
298
|
.runAgentLoop(prompt, messageId, onEvent, {
|
|
304
299
|
isInteractive: false,
|
|
305
300
|
isUserMessage: true,
|
|
301
|
+
callSite: "analyzeConversation",
|
|
306
302
|
})
|
|
307
303
|
.catch((err) => {
|
|
308
304
|
log.error(
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Registry for skill-provided HTTP route handlers.
|
|
3
3
|
*
|
|
4
|
-
* Skills register route matchers + handlers at initialization
|
|
5
|
-
* runtime HTTP server checks the registry for each inbound request
|
|
6
|
-
* falling through to its own route table.
|
|
4
|
+
* Skills and plugins register route matchers + handlers at initialization
|
|
5
|
+
* time. The runtime HTTP server checks the registry for each inbound request
|
|
6
|
+
* before falling through to its own route table.
|
|
7
|
+
*
|
|
8
|
+
* Registrations are identified by an opaque {@link SkillRouteHandle} returned
|
|
9
|
+
* from {@link registerSkillRoute}. Callers must pass that exact handle back
|
|
10
|
+
* to {@link unregisterSkillRoute} to remove the registration — pattern text
|
|
11
|
+
* is intentionally not a stable key, because two owners can legitimately
|
|
12
|
+
* register the same regex, and keying on `source + flags` would let one
|
|
13
|
+
* owner's teardown silently drop another owner's route.
|
|
7
14
|
*/
|
|
8
15
|
|
|
9
16
|
import { getLogger } from "../util/logger.js";
|
|
@@ -19,31 +26,106 @@ export interface SkillRoute {
|
|
|
19
26
|
handler: (req: Request, match: RegExpMatchArray) => Promise<Response>;
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
|
|
29
|
+
export type SkillRouteMatch =
|
|
30
|
+
| { kind: "match"; route: SkillRoute; match: RegExpMatchArray }
|
|
31
|
+
| { kind: "methodMismatch"; allow: string[] };
|
|
23
32
|
|
|
24
33
|
/**
|
|
25
|
-
*
|
|
34
|
+
* Opaque token returned from {@link registerSkillRoute}. The token has no
|
|
35
|
+
* observable fields — callers must treat it as a black box whose only valid
|
|
36
|
+
* use is to pass it to {@link unregisterSkillRoute}. Identity comparison on
|
|
37
|
+
* the token is what the registry keys against, so every call to
|
|
38
|
+
* `registerSkillRoute` returns a fresh handle even when the route's
|
|
39
|
+
* `pattern`/`methods`/`handler` are deep-equal to an existing entry.
|
|
26
40
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
declare const skillRouteHandleBrand: unique symbol;
|
|
42
|
+
export interface SkillRouteHandle {
|
|
43
|
+
readonly [skillRouteHandleBrand]: true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface RegisteredRoute {
|
|
47
|
+
readonly handle: SkillRouteHandle;
|
|
48
|
+
readonly route: SkillRoute;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const routes: RegisteredRoute[] = [];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Register a skill- or plugin-provided HTTP route. Called at initialization
|
|
55
|
+
* time. Returns an opaque handle the caller must retain and pass back to
|
|
56
|
+
* {@link unregisterSkillRoute} at teardown time. Do not attempt to derive
|
|
57
|
+
* the handle from the route's pattern — identity is the only stable key.
|
|
58
|
+
*/
|
|
59
|
+
export function registerSkillRoute(route: SkillRoute): SkillRouteHandle {
|
|
60
|
+
const handle = Object.freeze({}) as SkillRouteHandle;
|
|
61
|
+
routes.push({ handle, route });
|
|
29
62
|
log.info(
|
|
30
63
|
{ pattern: route.pattern.source, methods: route.methods },
|
|
31
64
|
"Skill route registered",
|
|
32
65
|
);
|
|
66
|
+
return handle;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Unregister a previously-registered skill route by handle.
|
|
71
|
+
*
|
|
72
|
+
* Returns `true` if a route was removed, `false` otherwise. Not finding a
|
|
73
|
+
* match is not an error: the plugin-shutdown path calls this best-effort for
|
|
74
|
+
* every handle a plugin retained, and a stale handle (e.g. the registry was
|
|
75
|
+
* cleared externally) should not crash shutdown.
|
|
76
|
+
*/
|
|
77
|
+
export function unregisterSkillRoute(handle: SkillRouteHandle): boolean {
|
|
78
|
+
const index = routes.findIndex((entry) => entry.handle === handle);
|
|
79
|
+
if (index === -1) {
|
|
80
|
+
log.warn({}, "unregisterSkillRoute: no matching route found for handle");
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const [removed] = routes.splice(index, 1);
|
|
84
|
+
log.info(
|
|
85
|
+
{ pattern: removed!.route.pattern.source },
|
|
86
|
+
"Skill route unregistered",
|
|
87
|
+
);
|
|
88
|
+
return true;
|
|
33
89
|
}
|
|
34
90
|
|
|
35
91
|
/**
|
|
36
|
-
* Try to match an inbound request against registered skill routes.
|
|
37
|
-
*
|
|
92
|
+
* Try to match an inbound request path + method against registered skill routes.
|
|
93
|
+
*
|
|
94
|
+
* - Returns `{ kind: "match", ... }` when a route matches both path and method.
|
|
95
|
+
* - Returns `{ kind: "methodMismatch", allow }` when one or more routes match
|
|
96
|
+
* the path but none accept the method — the caller should respond with 405
|
|
97
|
+
* and an `Allow` header listing the accepted methods.
|
|
98
|
+
* - Returns `null` when no route matches the path at all; the request then
|
|
99
|
+
* falls through to JWT auth and the normal route table.
|
|
100
|
+
*
|
|
101
|
+
* Method gating lives here so unauthenticated requests with the wrong method
|
|
102
|
+
* cannot reach skill handlers, and so same-path/different-method route pairs
|
|
103
|
+
* dispatch to the correct handler.
|
|
38
104
|
*/
|
|
39
105
|
export function matchSkillRoute(
|
|
40
106
|
path: string,
|
|
41
107
|
method: string,
|
|
42
|
-
):
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const match = path.match(route.pattern);
|
|
46
|
-
if (match)
|
|
108
|
+
): SkillRouteMatch | null {
|
|
109
|
+
const pathMatches: SkillRoute[] = [];
|
|
110
|
+
for (const entry of routes) {
|
|
111
|
+
const match = path.match(entry.route.pattern);
|
|
112
|
+
if (!match) continue;
|
|
113
|
+
if (entry.route.methods.includes(method)) {
|
|
114
|
+
return { kind: "match", route: entry.route, match };
|
|
115
|
+
}
|
|
116
|
+
pathMatches.push(entry.route);
|
|
47
117
|
}
|
|
48
|
-
return null;
|
|
118
|
+
if (pathMatches.length === 0) return null;
|
|
119
|
+
const allow = Array.from(new Set(pathMatches.flatMap((r) => r.methods)));
|
|
120
|
+
return { kind: "methodMismatch", allow };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Test-only helper — drops every registered route. Production code has no
|
|
125
|
+
* legitimate need for this; a real shutdown walks the handles each owner
|
|
126
|
+
* retained. Exported so tests that bypass the normal shutdown path (e.g.
|
|
127
|
+
* those that crash mid-bootstrap) can reset registry state between cases.
|
|
128
|
+
*/
|
|
129
|
+
export function resetSkillRoutesForTests(): void {
|
|
130
|
+
routes.length = 0;
|
|
49
131
|
}
|