@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
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the `circuitBreaker` plugin pipeline.
|
|
3
|
+
*
|
|
4
|
+
* The default plugin (`plugins/defaults/circuit-breaker.ts`) replaces the
|
|
5
|
+
* inline compaction circuit-breaker logic that previously lived in
|
|
6
|
+
* `daemon/conversation-agent-loop.ts`. These tests exercise the default
|
|
7
|
+
* plugin through the pipeline runner and assert the threshold (3 consecutive
|
|
8
|
+
* failures) and cooldown (1 hour) exactly match the legacy behavior.
|
|
9
|
+
*
|
|
10
|
+
* Coverage mirrors the eight scenarios the deleted
|
|
11
|
+
* `compaction-circuit-breaker.test.ts` exercised before the wrap:
|
|
12
|
+
* (a) counter increments on each failure outcome
|
|
13
|
+
* (b) circuit opens after exactly 3 consecutive failures
|
|
14
|
+
* (c) successful compaction resets counter and clears the circuit
|
|
15
|
+
* (d) decision.open reflects state and cooldown expiry
|
|
16
|
+
* (d) open circuit admits force:true (exercised at the call site; this
|
|
17
|
+
* file asserts decision.open is true while the breaker is tripped)
|
|
18
|
+
* (e) circuit re-opens after cooldown expiry when 3 more failures
|
|
19
|
+
* accumulate (guards the stale-timestamp regression)
|
|
20
|
+
* (f) callers skip tracking on undefined summaryFailed so early returns
|
|
21
|
+
* don't reset the counter (documented from the caller's perspective)
|
|
22
|
+
* (g) open→closed transition emits `compaction_circuit_closed` exactly once
|
|
23
|
+
* (h) closed→closed transition emits nothing
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
27
|
+
|
|
28
|
+
import type { TrustContext } from "../daemon/conversation-runtime-assembly.js";
|
|
29
|
+
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
30
|
+
import {
|
|
31
|
+
COMPACTION_CIRCUIT_COOLDOWN_MS,
|
|
32
|
+
COMPACTION_CIRCUIT_FAILURE_THRESHOLD,
|
|
33
|
+
defaultCircuitBreakerPlugin,
|
|
34
|
+
} from "../plugins/defaults/circuit-breaker.js";
|
|
35
|
+
import { runPipeline } from "../plugins/pipeline.js";
|
|
36
|
+
import {
|
|
37
|
+
getMiddlewaresFor,
|
|
38
|
+
registerPlugin,
|
|
39
|
+
resetPluginRegistryForTests,
|
|
40
|
+
} from "../plugins/registry.js";
|
|
41
|
+
import type {
|
|
42
|
+
CircuitBreakerArgs,
|
|
43
|
+
CircuitBreakerResult,
|
|
44
|
+
TurnContext,
|
|
45
|
+
} from "../plugins/types.js";
|
|
46
|
+
|
|
47
|
+
// ─── Fixtures ───────────────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
interface BreakerState {
|
|
50
|
+
readonly conversationId: string;
|
|
51
|
+
consecutiveCompactionFailures: number;
|
|
52
|
+
compactionCircuitOpenUntil: number | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function makeState(conversationId = "conv-breaker-test"): BreakerState {
|
|
56
|
+
return {
|
|
57
|
+
conversationId,
|
|
58
|
+
consecutiveCompactionFailures: 0,
|
|
59
|
+
compactionCircuitOpenUntil: null,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function collectEvents(): {
|
|
64
|
+
events: ServerMessage[];
|
|
65
|
+
onEvent: (msg: ServerMessage) => void;
|
|
66
|
+
} {
|
|
67
|
+
const events: ServerMessage[] = [];
|
|
68
|
+
return { events, onEvent: (msg) => events.push(msg) };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const trust: TrustContext = {
|
|
72
|
+
sourceChannel: "vellum",
|
|
73
|
+
trustClass: "guardian",
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
function makeTurnCtx(conversationId = "conv-breaker-test"): TurnContext {
|
|
77
|
+
return {
|
|
78
|
+
requestId: "req-test",
|
|
79
|
+
conversationId,
|
|
80
|
+
turnIndex: 0,
|
|
81
|
+
trust,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Run the `circuitBreaker` pipeline through the registered plugin chain.
|
|
87
|
+
* Mirrors how `conversation-agent-loop.ts` invokes it, with the same
|
|
88
|
+
* terminal fallback used in production.
|
|
89
|
+
*/
|
|
90
|
+
async function runCircuit(
|
|
91
|
+
args: CircuitBreakerArgs,
|
|
92
|
+
ctx: TurnContext = makeTurnCtx(args.state.conversationId),
|
|
93
|
+
): Promise<CircuitBreakerResult> {
|
|
94
|
+
return runPipeline<CircuitBreakerArgs, CircuitBreakerResult>(
|
|
95
|
+
"circuitBreaker",
|
|
96
|
+
getMiddlewaresFor("circuitBreaker"),
|
|
97
|
+
async (terminalArgs) => {
|
|
98
|
+
const openUntil = terminalArgs.state.compactionCircuitOpenUntil;
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
if (openUntil !== null && now < openUntil) {
|
|
101
|
+
return { open: true, cooldownRemainingMs: openUntil - now };
|
|
102
|
+
}
|
|
103
|
+
return { open: false };
|
|
104
|
+
},
|
|
105
|
+
args,
|
|
106
|
+
ctx,
|
|
107
|
+
500,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
describe("circuit-breaker pipeline", () => {
|
|
112
|
+
let originalDateNow: () => number;
|
|
113
|
+
|
|
114
|
+
beforeEach(() => {
|
|
115
|
+
resetPluginRegistryForTests();
|
|
116
|
+
registerPlugin(defaultCircuitBreakerPlugin);
|
|
117
|
+
originalDateNow = Date.now;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
afterEach(() => {
|
|
121
|
+
Date.now = originalDateNow;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("threshold and cooldown match legacy constants exactly", () => {
|
|
125
|
+
// Sanity — the plugin must expose the same constants the legacy inline
|
|
126
|
+
// helpers used. Any drift would silently change user-visible behavior.
|
|
127
|
+
expect(COMPACTION_CIRCUIT_FAILURE_THRESHOLD).toBe(3);
|
|
128
|
+
expect(COMPACTION_CIRCUIT_COOLDOWN_MS).toBe(60 * 60 * 1000);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("(a) counter increments on each failure outcome", async () => {
|
|
132
|
+
const state = makeState();
|
|
133
|
+
const { onEvent, events } = collectEvents();
|
|
134
|
+
|
|
135
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
136
|
+
expect(state.consecutiveCompactionFailures).toBe(1);
|
|
137
|
+
expect(state.compactionCircuitOpenUntil).toBeNull();
|
|
138
|
+
expect(events).toHaveLength(0);
|
|
139
|
+
|
|
140
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
141
|
+
expect(state.consecutiveCompactionFailures).toBe(2);
|
|
142
|
+
expect(state.compactionCircuitOpenUntil).toBeNull();
|
|
143
|
+
expect(events).toHaveLength(0);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("(b) circuit opens after exactly 3 consecutive failures", async () => {
|
|
147
|
+
const fixedNow = 1_700_000_000_000;
|
|
148
|
+
Date.now = () => fixedNow;
|
|
149
|
+
|
|
150
|
+
const state = makeState();
|
|
151
|
+
const { onEvent, events } = collectEvents();
|
|
152
|
+
|
|
153
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
154
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
155
|
+
// Two failures — circuit still closed.
|
|
156
|
+
expect(state.compactionCircuitOpenUntil).toBeNull();
|
|
157
|
+
expect(events).toHaveLength(0);
|
|
158
|
+
|
|
159
|
+
const third = await runCircuit({
|
|
160
|
+
key: "k",
|
|
161
|
+
outcome: "failure",
|
|
162
|
+
state,
|
|
163
|
+
onEvent,
|
|
164
|
+
});
|
|
165
|
+
// Third failure — circuit trips and fires the event exactly once.
|
|
166
|
+
expect(state.consecutiveCompactionFailures).toBe(3);
|
|
167
|
+
expect(state.compactionCircuitOpenUntil).toBe(fixedNow + 60 * 60 * 1000);
|
|
168
|
+
expect(third.open).toBe(true);
|
|
169
|
+
expect(third.cooldownRemainingMs).toBe(60 * 60 * 1000);
|
|
170
|
+
expect(events).toHaveLength(1);
|
|
171
|
+
expect(events[0]).toEqual({
|
|
172
|
+
type: "compaction_circuit_open",
|
|
173
|
+
conversationId: state.conversationId,
|
|
174
|
+
reason: "3_consecutive_failures",
|
|
175
|
+
openUntil: fixedNow + 60 * 60 * 1000,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Further failures do not re-fire the event while the circuit is open.
|
|
179
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
180
|
+
expect(state.consecutiveCompactionFailures).toBe(4);
|
|
181
|
+
expect(events).toHaveLength(1);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("(c) successful outcome resets counter and clears circuit", async () => {
|
|
185
|
+
const fixedNow = 1_700_000_000_000;
|
|
186
|
+
Date.now = () => fixedNow;
|
|
187
|
+
|
|
188
|
+
const state = makeState();
|
|
189
|
+
const { onEvent } = collectEvents();
|
|
190
|
+
|
|
191
|
+
// Trip the breaker.
|
|
192
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
193
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
194
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
195
|
+
expect(state.compactionCircuitOpenUntil).not.toBeNull();
|
|
196
|
+
|
|
197
|
+
// Success resets state.
|
|
198
|
+
await runCircuit({ key: "k", outcome: "success", state, onEvent });
|
|
199
|
+
expect(state.consecutiveCompactionFailures).toBe(0);
|
|
200
|
+
expect(state.compactionCircuitOpenUntil).toBeNull();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test("(d) decision.open reflects state and expiry", async () => {
|
|
204
|
+
const fixedNow = 1_700_000_000_000;
|
|
205
|
+
Date.now = () => fixedNow;
|
|
206
|
+
|
|
207
|
+
const state = makeState();
|
|
208
|
+
const { onEvent } = collectEvents();
|
|
209
|
+
|
|
210
|
+
// Query-only on a fresh state: closed, no cooldown.
|
|
211
|
+
const preQuery = await runCircuit({ key: "k", state, onEvent });
|
|
212
|
+
expect(preQuery.open).toBe(false);
|
|
213
|
+
expect(preQuery.cooldownRemainingMs).toBeUndefined();
|
|
214
|
+
|
|
215
|
+
// Trip the breaker.
|
|
216
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
217
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
218
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
219
|
+
|
|
220
|
+
// Query-only while open: open + non-zero cooldown.
|
|
221
|
+
const openQuery = await runCircuit({ key: "k", state, onEvent });
|
|
222
|
+
expect(openQuery.open).toBe(true);
|
|
223
|
+
expect(openQuery.cooldownRemainingMs).toBe(60 * 60 * 1000);
|
|
224
|
+
|
|
225
|
+
// After cooldown expires the breaker reports closed again, even without
|
|
226
|
+
// an explicit reset — the open-until timestamp is the only source of
|
|
227
|
+
// truth for the gate.
|
|
228
|
+
Date.now = () => fixedNow + 60 * 60 * 1000 + 1;
|
|
229
|
+
const postCooldown = await runCircuit({ key: "k", state, onEvent });
|
|
230
|
+
expect(postCooldown.open).toBe(false);
|
|
231
|
+
expect(postCooldown.cooldownRemainingMs).toBeUndefined();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("(e) circuit re-opens after cooldown expiry when 3 more failures accumulate", async () => {
|
|
235
|
+
// Regression: before the fix in the legacy helper, opening the breaker a
|
|
236
|
+
// second time required `compactionCircuitOpenUntil === null`. Once a
|
|
237
|
+
// cooldown expired, the decision correctly reported "closed" but the
|
|
238
|
+
// stale past-timestamp stayed on the state, so the next 3-strike window
|
|
239
|
+
// couldn't trip a new cooldown. The default plugin must treat any
|
|
240
|
+
// expired timestamp the same as null.
|
|
241
|
+
const t0 = 1_700_000_000_000;
|
|
242
|
+
Date.now = () => t0;
|
|
243
|
+
|
|
244
|
+
const state = makeState();
|
|
245
|
+
const { onEvent, events } = collectEvents();
|
|
246
|
+
|
|
247
|
+
// Trip the breaker the first time.
|
|
248
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
249
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
250
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
251
|
+
expect(state.compactionCircuitOpenUntil).toBe(t0 + 60 * 60 * 1000);
|
|
252
|
+
expect(events).toHaveLength(1);
|
|
253
|
+
|
|
254
|
+
// Advance past the cooldown window. Manually reset the counter — in
|
|
255
|
+
// production this happens when a subsequent `maybeCompact` call succeeds
|
|
256
|
+
// (outcome: "success") after the cooldown elapses, but the bug
|
|
257
|
+
// manifests even when the counter is reset: the stale
|
|
258
|
+
// `compactionCircuitOpenUntil` is what breaks re-opening.
|
|
259
|
+
const t1 = t0 + 60 * 60 * 1000 + 1;
|
|
260
|
+
Date.now = () => t1;
|
|
261
|
+
const postCooldown = await runCircuit({ key: "k", state, onEvent });
|
|
262
|
+
expect(postCooldown.open).toBe(false);
|
|
263
|
+
state.consecutiveCompactionFailures = 0;
|
|
264
|
+
// `compactionCircuitOpenUntil` is deliberately left as the old
|
|
265
|
+
// timestamp to reproduce the bug condition.
|
|
266
|
+
expect(state.compactionCircuitOpenUntil).toBe(t0 + 60 * 60 * 1000);
|
|
267
|
+
|
|
268
|
+
// Three more failures must trip a fresh cooldown even though the old
|
|
269
|
+
// timestamp is still set.
|
|
270
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
271
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
272
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
273
|
+
expect(state.consecutiveCompactionFailures).toBe(3);
|
|
274
|
+
expect(state.compactionCircuitOpenUntil).toBe(t1 + 60 * 60 * 1000);
|
|
275
|
+
expect(events).toHaveLength(2);
|
|
276
|
+
expect(events[1]).toEqual({
|
|
277
|
+
type: "compaction_circuit_open",
|
|
278
|
+
conversationId: state.conversationId,
|
|
279
|
+
reason: "3_consecutive_failures",
|
|
280
|
+
openUntil: t1 + 60 * 60 * 1000,
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("(f) callers must skip tracking on undefined summaryFailed so early returns don't reset the counter", async () => {
|
|
285
|
+
// Regression: `maybeCompact()` returns `summaryFailed: undefined` on
|
|
286
|
+
// early-return paths (no eligible messages, below threshold, cooldown
|
|
287
|
+
// active, truncation-only). Callers guard with `summaryFailed !==
|
|
288
|
+
// undefined` at every call site — this test asserts that a query-only
|
|
289
|
+
// pipeline invocation (no `outcome`) preserves the counter.
|
|
290
|
+
const state = makeState();
|
|
291
|
+
const { onEvent } = collectEvents();
|
|
292
|
+
|
|
293
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
294
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
295
|
+
expect(state.consecutiveCompactionFailures).toBe(2);
|
|
296
|
+
|
|
297
|
+
// Query-only — should NOT touch the counter.
|
|
298
|
+
await runCircuit({ key: "k", state, onEvent });
|
|
299
|
+
expect(state.consecutiveCompactionFailures).toBe(2);
|
|
300
|
+
|
|
301
|
+
// A third real failure then trips the breaker as expected.
|
|
302
|
+
await runCircuit({ key: "k", outcome: "failure", state, onEvent });
|
|
303
|
+
expect(state.consecutiveCompactionFailures).toBe(3);
|
|
304
|
+
expect(state.compactionCircuitOpenUntil).not.toBeNull();
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
test("(g) open→closed transition emits compaction_circuit_closed exactly once", async () => {
|
|
308
|
+
// Regression: before this fix in the legacy helper, the reset branch
|
|
309
|
+
// silently cleared `compactionCircuitOpenUntil` without notifying the
|
|
310
|
+
// client. The Swift banner set from `compaction_circuit_open` would
|
|
311
|
+
// stay visible until the original `openUntil` deadline (up to 1h),
|
|
312
|
+
// misrepresenting the live state. The default plugin emits
|
|
313
|
+
// `compaction_circuit_closed` on the open→closed transition so the
|
|
314
|
+
// banner dismisses immediately.
|
|
315
|
+
const fixedNow = 1_700_000_000_000;
|
|
316
|
+
Date.now = () => fixedNow;
|
|
317
|
+
|
|
318
|
+
const state = makeState();
|
|
319
|
+
const { onEvent, events } = collectEvents();
|
|
320
|
+
|
|
321
|
+
// Force the circuit into the open state directly — the emitted-event
|
|
322
|
+
// transition logic is what we're testing, not the tripping path.
|
|
323
|
+
state.compactionCircuitOpenUntil = fixedNow + 60 * 60 * 1000;
|
|
324
|
+
state.consecutiveCompactionFailures = 3;
|
|
325
|
+
|
|
326
|
+
await runCircuit({ key: "k", outcome: "success", state, onEvent });
|
|
327
|
+
|
|
328
|
+
expect(state.consecutiveCompactionFailures).toBe(0);
|
|
329
|
+
expect(state.compactionCircuitOpenUntil).toBeNull();
|
|
330
|
+
expect(events).toHaveLength(1);
|
|
331
|
+
expect(events[0]).toEqual({
|
|
332
|
+
type: "compaction_circuit_closed",
|
|
333
|
+
conversationId: state.conversationId,
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
test("(h) successful outcome against an already-closed circuit emits no event", async () => {
|
|
338
|
+
// Emitting `compaction_circuit_closed` on every successful compaction
|
|
339
|
+
// would spam the client (the breaker is closed in the common case).
|
|
340
|
+
// Only the open→closed transition is meaningful.
|
|
341
|
+
const state = makeState();
|
|
342
|
+
const { onEvent, events } = collectEvents();
|
|
343
|
+
|
|
344
|
+
expect(state.compactionCircuitOpenUntil).toBeNull();
|
|
345
|
+
await runCircuit({ key: "k", outcome: "success", state, onEvent });
|
|
346
|
+
expect(state.compactionCircuitOpenUntil).toBeNull();
|
|
347
|
+
expect(events).toHaveLength(0);
|
|
348
|
+
|
|
349
|
+
// A second successful outcome while still closed — still no event.
|
|
350
|
+
await runCircuit({ key: "k", outcome: "success", state, onEvent });
|
|
351
|
+
expect(events).toHaveLength(0);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test("omitting onEvent still updates state without emitting", async () => {
|
|
355
|
+
// `onEvent` is optional in `CircuitBreakerArgs`. When omitted the plugin
|
|
356
|
+
// must still mutate the state container correctly — the only missing
|
|
357
|
+
// side effect is the transition notification.
|
|
358
|
+
const state = makeState();
|
|
359
|
+
|
|
360
|
+
for (let i = 0; i < 3; i++) {
|
|
361
|
+
await runCircuit({ key: "k", outcome: "failure", state });
|
|
362
|
+
}
|
|
363
|
+
expect(state.consecutiveCompactionFailures).toBe(3);
|
|
364
|
+
expect(state.compactionCircuitOpenUntil).not.toBeNull();
|
|
365
|
+
|
|
366
|
+
await runCircuit({ key: "k", outcome: "success", state });
|
|
367
|
+
expect(state.consecutiveCompactionFailures).toBe(0);
|
|
368
|
+
expect(state.compactionCircuitOpenUntil).toBeNull();
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
test("pipeline runner applies registered middleware in registration order", async () => {
|
|
372
|
+
// A second plugin registered after the default can observe args/result
|
|
373
|
+
// around the default's behavior. This proves the pipeline composes both
|
|
374
|
+
// middlewares rather than short-circuiting on the default alone.
|
|
375
|
+
const seen: string[] = [];
|
|
376
|
+
registerPlugin({
|
|
377
|
+
manifest: {
|
|
378
|
+
name: "observer",
|
|
379
|
+
version: "0.0.1",
|
|
380
|
+
requires: { pluginRuntime: "v1", circuitBreakerApi: "v1" },
|
|
381
|
+
},
|
|
382
|
+
middleware: {
|
|
383
|
+
circuitBreaker: async (args, next) => {
|
|
384
|
+
seen.push(`before:${args.outcome ?? "query"}`);
|
|
385
|
+
const res = await next(args);
|
|
386
|
+
seen.push(`after:${res.open ? "open" : "closed"}`);
|
|
387
|
+
return res;
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
const state = makeState();
|
|
393
|
+
await runCircuit({ key: "k", outcome: "failure", state });
|
|
394
|
+
await runCircuit({ key: "k", outcome: "failure", state });
|
|
395
|
+
await runCircuit({ key: "k", outcome: "failure", state });
|
|
396
|
+
|
|
397
|
+
expect(seen).toEqual([
|
|
398
|
+
"before:failure",
|
|
399
|
+
"after:closed",
|
|
400
|
+
"before:failure",
|
|
401
|
+
"after:closed",
|
|
402
|
+
"before:failure",
|
|
403
|
+
"after:open",
|
|
404
|
+
]);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
@@ -32,6 +32,7 @@ mock.module("../config/loader.js", () => ({
|
|
|
32
32
|
}));
|
|
33
33
|
|
|
34
34
|
import { buildCliProgram } from "../cli/program.js";
|
|
35
|
+
import type { RiskClassification } from "../permissions/checker.js";
|
|
35
36
|
import { classifyRisk } from "../permissions/checker.js";
|
|
36
37
|
import { RiskLevel } from "../permissions/types.js";
|
|
37
38
|
|
|
@@ -39,17 +40,17 @@ import { RiskLevel } from "../permissions/types.js";
|
|
|
39
40
|
* Assert that a command classifies as Low risk, with a descriptive failure
|
|
40
41
|
* message that guides developers toward the correct fix.
|
|
41
42
|
*/
|
|
42
|
-
function expectLowRisk(command: string, actual:
|
|
43
|
-
if (actual !== RiskLevel.Low) {
|
|
43
|
+
function expectLowRisk(command: string, actual: RiskClassification): void {
|
|
44
|
+
if (actual.level !== RiskLevel.Low) {
|
|
44
45
|
throw new Error(
|
|
45
|
-
`"${command}" classified as ${actual} instead of Low. ` +
|
|
46
|
+
`"${command}" classified as ${actual.level} instead of Low. ` +
|
|
46
47
|
`assistant CLI commands must be Low risk by default — the assistant ` +
|
|
47
48
|
`uses its own CLI during normal operation. If you need risk ` +
|
|
48
49
|
`escalation for specific subcommands, add them to the elevated ` +
|
|
49
50
|
`risk tests in this guard test with justification.`,
|
|
50
51
|
);
|
|
51
52
|
}
|
|
52
|
-
expect(actual).toBe(RiskLevel.Low);
|
|
53
|
+
expect(actual.level).toBe(RiskLevel.Low);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
// Dynamically extract subcommand names from the CLI program definition.
|
|
@@ -84,11 +85,7 @@ describe("CLI command risk guard: assistant commands", () => {
|
|
|
84
85
|
});
|
|
85
86
|
|
|
86
87
|
test("assistant with flags classifies as Low risk", async () => {
|
|
87
|
-
const flagCommands = [
|
|
88
|
-
"assistant --version",
|
|
89
|
-
"assistant --help",
|
|
90
|
-
"assistant doctor --verbose",
|
|
91
|
-
];
|
|
88
|
+
const flagCommands = ["assistant --version", "assistant --help"];
|
|
92
89
|
|
|
93
90
|
for (const command of flagCommands) {
|
|
94
91
|
const risk = await classifyRisk("bash", { command });
|
|
@@ -105,56 +102,56 @@ describe("CLI command risk guard: elevated assistant subcommands", () => {
|
|
|
105
102
|
const risk = await classifyRisk("bash", {
|
|
106
103
|
command: "assistant oauth token",
|
|
107
104
|
});
|
|
108
|
-
expect(risk).toBe(RiskLevel.High);
|
|
105
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
109
106
|
});
|
|
110
107
|
|
|
111
108
|
test("assistant oauth mode --set is High risk (changes auth mode)", async () => {
|
|
112
109
|
const risk = await classifyRisk("bash", {
|
|
113
110
|
command: "assistant oauth mode --set managed",
|
|
114
111
|
});
|
|
115
|
-
expect(risk).toBe(RiskLevel.High);
|
|
112
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
116
113
|
});
|
|
117
114
|
|
|
118
115
|
test("assistant oauth mode --set=value is High risk (equals syntax)", async () => {
|
|
119
116
|
const risk = await classifyRisk("bash", {
|
|
120
117
|
command: "assistant oauth mode google --set=managed",
|
|
121
118
|
});
|
|
122
|
-
expect(risk).toBe(RiskLevel.High);
|
|
119
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
123
120
|
});
|
|
124
121
|
|
|
125
122
|
test("assistant oauth mode without --set is Low risk (read-only)", async () => {
|
|
126
123
|
const risk = await classifyRisk("bash", {
|
|
127
124
|
command: "assistant oauth mode",
|
|
128
125
|
});
|
|
129
|
-
expect(risk).toBe(RiskLevel.Low);
|
|
126
|
+
expect(risk.level).toBe(RiskLevel.Low);
|
|
130
127
|
});
|
|
131
128
|
|
|
132
129
|
test("assistant credentials reveal is High risk (exposes secrets)", async () => {
|
|
133
130
|
const risk = await classifyRisk("bash", {
|
|
134
131
|
command: "assistant credentials reveal",
|
|
135
132
|
});
|
|
136
|
-
expect(risk).toBe(RiskLevel.High);
|
|
133
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
137
134
|
});
|
|
138
135
|
|
|
139
136
|
test("assistant oauth request is Medium risk (initiates OAuth flow)", async () => {
|
|
140
137
|
const risk = await classifyRisk("bash", {
|
|
141
138
|
command: "assistant oauth request",
|
|
142
139
|
});
|
|
143
|
-
expect(risk).toBe(RiskLevel.Medium);
|
|
140
|
+
expect(risk.level).toBe(RiskLevel.Medium);
|
|
144
141
|
});
|
|
145
142
|
|
|
146
143
|
test("assistant oauth connect is Medium risk (modifies OAuth connections)", async () => {
|
|
147
144
|
const risk = await classifyRisk("bash", {
|
|
148
145
|
command: "assistant oauth connect",
|
|
149
146
|
});
|
|
150
|
-
expect(risk).toBe(RiskLevel.Medium);
|
|
147
|
+
expect(risk.level).toBe(RiskLevel.Medium);
|
|
151
148
|
});
|
|
152
149
|
|
|
153
150
|
test("assistant oauth disconnect is Medium risk (removes OAuth connections)", async () => {
|
|
154
151
|
const risk = await classifyRisk("bash", {
|
|
155
152
|
command: "assistant oauth disconnect",
|
|
156
153
|
});
|
|
157
|
-
expect(risk).toBe(RiskLevel.Medium);
|
|
154
|
+
expect(risk.level).toBe(RiskLevel.Medium);
|
|
158
155
|
});
|
|
159
156
|
|
|
160
157
|
test("--help on non-elevated subcommands remains Low risk", async () => {
|
|
@@ -199,12 +196,12 @@ describe("CLI command risk guard: elevated assistant subcommands", () => {
|
|
|
199
196
|
// THEN --help does not bypass the elevated risk level
|
|
200
197
|
for (const command of highRiskWithHelp) {
|
|
201
198
|
const risk = await classifyRisk("bash", { command });
|
|
202
|
-
expect(risk).toBe(RiskLevel.High);
|
|
199
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
203
200
|
}
|
|
204
201
|
|
|
205
202
|
for (const command of mediumRiskWithHelp) {
|
|
206
203
|
const risk = await classifyRisk("bash", { command });
|
|
207
|
-
expect(risk).toBe(RiskLevel.Medium);
|
|
204
|
+
expect(risk.level).toBe(RiskLevel.Medium);
|
|
208
205
|
}
|
|
209
206
|
});
|
|
210
207
|
|
|
@@ -212,14 +209,14 @@ describe("CLI command risk guard: elevated assistant subcommands", () => {
|
|
|
212
209
|
const risk = await classifyRisk("bash", {
|
|
213
210
|
command: "assistant credentials reveal 123 --service --help",
|
|
214
211
|
});
|
|
215
|
-
expect(risk).toBe(RiskLevel.High);
|
|
212
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
216
213
|
});
|
|
217
214
|
|
|
218
215
|
test("-h used as option value does not downgrade oauth mode --set risk", async () => {
|
|
219
216
|
const risk = await classifyRisk("bash", {
|
|
220
217
|
command: "assistant oauth mode --set -h",
|
|
221
218
|
});
|
|
222
|
-
expect(risk).toBe(RiskLevel.High);
|
|
219
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
223
220
|
});
|
|
224
221
|
|
|
225
222
|
test("non-sensitive oauth subcommands remain Low risk", async () => {
|
|
@@ -252,28 +249,28 @@ describe("CLI command risk guard: elevated assistant subcommands", () => {
|
|
|
252
249
|
const risk = await classifyRisk("bash", {
|
|
253
250
|
command: "assistant credentials set",
|
|
254
251
|
});
|
|
255
|
-
expect(risk).toBe(RiskLevel.High);
|
|
252
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
256
253
|
});
|
|
257
254
|
|
|
258
255
|
test("assistant credentials delete is High risk (removes stored credentials)", async () => {
|
|
259
256
|
const risk = await classifyRisk("bash", {
|
|
260
257
|
command: "assistant credentials delete",
|
|
261
258
|
});
|
|
262
|
-
expect(risk).toBe(RiskLevel.High);
|
|
259
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
263
260
|
});
|
|
264
261
|
|
|
265
262
|
test("assistant keys set is High risk (modifies API keys)", async () => {
|
|
266
263
|
const risk = await classifyRisk("bash", {
|
|
267
264
|
command: "assistant keys set anthropic sk-ant-xxx",
|
|
268
265
|
});
|
|
269
|
-
expect(risk).toBe(RiskLevel.High);
|
|
266
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
270
267
|
});
|
|
271
268
|
|
|
272
269
|
test("assistant keys delete is High risk (removes API keys)", async () => {
|
|
273
270
|
const risk = await classifyRisk("bash", {
|
|
274
271
|
command: "assistant keys delete openai",
|
|
275
272
|
});
|
|
276
|
-
expect(risk).toBe(RiskLevel.High);
|
|
273
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
277
274
|
});
|
|
278
275
|
|
|
279
276
|
test("non-sensitive keys subcommands remain Low risk", async () => {
|
|
@@ -289,14 +286,14 @@ describe("CLI command risk guard: elevated assistant subcommands", () => {
|
|
|
289
286
|
const risk = await classifyRisk("bash", {
|
|
290
287
|
command: "assistant trust remove abc123",
|
|
291
288
|
});
|
|
292
|
-
expect(risk).toBe(RiskLevel.High);
|
|
289
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
293
290
|
});
|
|
294
291
|
|
|
295
292
|
test("assistant trust clear is High risk (clears all trust rules)", async () => {
|
|
296
293
|
const risk = await classifyRisk("bash", {
|
|
297
294
|
command: "assistant trust clear",
|
|
298
295
|
});
|
|
299
|
-
expect(risk).toBe(RiskLevel.High);
|
|
296
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
300
297
|
});
|
|
301
298
|
|
|
302
299
|
test("non-sensitive trust subcommands remain Low risk", async () => {
|
|
@@ -314,35 +311,35 @@ describe("CLI command risk guard: wrapper program propagation", () => {
|
|
|
314
311
|
const risk = await classifyRisk("bash", {
|
|
315
312
|
command: "env assistant oauth token",
|
|
316
313
|
});
|
|
317
|
-
expect(risk).toBe(RiskLevel.High);
|
|
314
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
318
315
|
});
|
|
319
316
|
|
|
320
317
|
test("nice assistant credentials reveal is High risk", async () => {
|
|
321
318
|
const risk = await classifyRisk("bash", {
|
|
322
319
|
command: "nice assistant credentials reveal",
|
|
323
320
|
});
|
|
324
|
-
expect(risk).toBe(RiskLevel.High);
|
|
321
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
325
322
|
});
|
|
326
323
|
|
|
327
324
|
test("timeout 30 assistant oauth request is Medium risk", async () => {
|
|
328
325
|
const risk = await classifyRisk("bash", {
|
|
329
326
|
command: "timeout 30 assistant oauth request",
|
|
330
327
|
});
|
|
331
|
-
expect(risk).toBe(RiskLevel.Medium);
|
|
328
|
+
expect(risk.level).toBe(RiskLevel.Medium);
|
|
332
329
|
});
|
|
333
330
|
|
|
334
331
|
test("timeout 30 assistant oauth token is High risk", async () => {
|
|
335
332
|
const risk = await classifyRisk("bash", {
|
|
336
333
|
command: "timeout 30 assistant oauth token",
|
|
337
334
|
});
|
|
338
|
-
expect(risk).toBe(RiskLevel.High);
|
|
335
|
+
expect(risk.level).toBe(RiskLevel.High);
|
|
339
336
|
});
|
|
340
337
|
|
|
341
338
|
test("timeout 30 git push is Medium risk", async () => {
|
|
342
339
|
const risk = await classifyRisk("bash", {
|
|
343
340
|
command: "timeout 30 git push",
|
|
344
341
|
});
|
|
345
|
-
expect(risk).toBe(RiskLevel.Medium);
|
|
342
|
+
expect(risk.level).toBe(RiskLevel.Medium);
|
|
346
343
|
});
|
|
347
344
|
|
|
348
345
|
test("timeout 30 git status is Low risk", async () => {
|
|
@@ -361,7 +358,7 @@ describe("CLI command risk guard: wrapper program propagation", () => {
|
|
|
361
358
|
|
|
362
359
|
test("env git push is Medium risk (not Low)", async () => {
|
|
363
360
|
const risk = await classifyRisk("bash", { command: "env git push" });
|
|
364
|
-
expect(risk).toBe(RiskLevel.Medium);
|
|
361
|
+
expect(risk.level).toBe(RiskLevel.Medium);
|
|
365
362
|
});
|
|
366
363
|
|
|
367
364
|
test("env git status is Low risk", async () => {
|