@vellumai/assistant 0.6.5 → 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/AGENTS.md +9 -1
- package/ARCHITECTURE.md +15 -17
- package/Dockerfile +6 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
- package/docs/architecture/integrations.md +32 -39
- package/docs/architecture/memory.md +25 -30
- package/docs/architecture/security.md +7 -6
- package/docs/browser-use-architecture-phase2.md +63 -20
- package/docs/plugins.md +761 -0
- 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/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
- package/openapi.yaml +212 -68
- package/package.json +1 -1
- package/src/__tests__/app-compiler.test.ts +57 -0
- package/src/__tests__/approval-cascade.test.ts +7 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +1 -0
- package/src/__tests__/avatar-generator.test.ts +4 -2
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/catalog-cache.test.ts +69 -0
- package/src/__tests__/checker.test.ts +459 -171
- package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
- 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__/config-model-image-provider.test.ts +110 -0
- package/src/__tests__/config-schema.test.ts +22 -9
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
- package/src/__tests__/contacts-tools.test.ts +26 -0
- package/src/__tests__/context-overflow-policy.test.ts +7 -7
- package/src/__tests__/context-window-manager.test.ts +355 -4
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +26 -30
- package/src/__tests__/conversation-agent-loop.test.ts +30 -141
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -1
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +2 -16
- package/src/__tests__/conversation-pairing.test.ts +174 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +4 -1
- package/src/__tests__/conversation-process-callsite.test.ts +3 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +16 -7
- package/src/__tests__/conversation-queue.test.ts +29 -14
- package/src/__tests__/conversation-routes-disk-view.test.ts +7 -6
- package/src/__tests__/conversation-runtime-assembly.test.ts +155 -110
- package/src/__tests__/conversation-runtime-workspace.test.ts +23 -38
- package/src/__tests__/conversation-seed-composer.test.ts +2 -2
- package/src/__tests__/conversation-slash-queue.test.ts +7 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +25 -2
- package/src/__tests__/conversation-speed-override.test.ts +6 -1
- package/src/__tests__/conversation-title-service.test.ts +116 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -2
- package/src/__tests__/conversation-usage.test.ts +1 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +4 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +3 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -1
- package/src/__tests__/credential-health-service.test.ts +78 -9
- package/src/__tests__/credential-security-invariants.test.ts +2 -2
- package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
- package/src/__tests__/empty-response-pipeline.test.ts +305 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +3 -3
- package/src/__tests__/first-greeting.test.ts +247 -5
- package/src/__tests__/headless-browser-mode.test.ts +57 -0
- 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__/image-credentials.test.ts +137 -0
- package/src/__tests__/image-service-dispatcher.test.ts +186 -0
- package/src/__tests__/injector-chain.test.ts +526 -0
- package/src/__tests__/intent-routing.test.ts +0 -26
- package/src/__tests__/llm-call-pipeline.test.ts +285 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- 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__/migration-import-from-url.test.ts +5 -68
- package/src/__tests__/model-intents.test.ts +4 -2
- package/src/__tests__/notification-broadcaster.test.ts +3 -3
- 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 +41 -76
- package/src/__tests__/onboarding-template-contract.test.ts +16 -64
- package/src/__tests__/openai-image-service.test.ts +368 -0
- package/src/__tests__/overflow-reduce-pipeline.test.ts +676 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +0 -24
- package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
- package/src/__tests__/persistence-pipeline.test.ts +377 -0
- package/src/__tests__/pipeline-runner.test.ts +565 -0
- 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 +44 -12
- package/src/__tests__/proxy-approval-callback.test.ts +69 -8
- package/src/__tests__/reaction-persistence.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +0 -2
- 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__/shell-identity.test.ts +0 -134
- package/src/__tests__/suggestion-routes.test.ts +103 -4
- package/src/__tests__/task-memory-cleanup.test.ts +1 -0
- package/src/__tests__/task-scheduler.test.ts +3 -15
- package/src/__tests__/test-preload.ts +11 -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 +0 -6
- package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
- package/src/__tests__/tool-executor.test.ts +141 -0
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
- package/src/__tests__/tool-result-truncation.test.ts +0 -110
- package/src/__tests__/user-plugin-loader.test.ts +191 -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-remove-hooks.test.ts +99 -0
- package/src/__tests__/workspace-policy.test.ts +21 -3
- package/src/agent/loop.ts +340 -102
- package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
- package/src/approvals/guardian-request-resolvers.ts +80 -0
- package/src/backup/__tests__/backup-worker.test.ts +2 -13
- package/src/backup/backup-worker.ts +3 -15
- package/src/bundler/app-compiler.ts +84 -1
- package/src/calls/call-state.ts +2 -2
- package/src/channels/__tests__/types.test.ts +3 -3
- package/src/channels/types.ts +6 -4
- package/src/cli/__tests__/notifications.test.ts +87 -211
- package/src/cli/commands/__tests__/backup.test.ts +1 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +255 -35
- package/src/cli/commands/__tests__/inference-send.test.ts +12 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +12 -0
- package/src/cli/commands/backup.ts +2 -2
- package/src/cli/commands/clients.ts +138 -0
- package/src/cli/commands/completions.ts +2 -9
- package/src/cli/commands/conversations.ts +55 -7
- package/src/cli/commands/image-generation.ts +33 -34
- 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/skills.ts +3 -4
- package/src/cli/program.ts +25 -29
- 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/messaging/SKILL.md +3 -3
- 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 +12 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +58 -0
- 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-tool-registry.ts +0 -15
- package/src/config/feature-flag-registry.json +17 -1
- package/src/config/schema.ts +19 -0
- package/src/config/schemas/backup.ts +1 -1
- package/src/config/schemas/conversations.ts +16 -0
- package/src/config/schemas/llm.ts +2 -3
- package/src/config/schemas/security.ts +6 -6
- package/src/config/schemas/tts.ts +11 -0
- package/src/config/skill-state.ts +6 -2
- package/src/config/skills.ts +94 -5
- package/src/context/__tests__/compact-prompt.test.ts +27 -9
- package/src/context/prompts/compact.md +26 -12
- package/src/context/tool-result-truncation.ts +3 -63
- package/src/context/window-manager.ts +190 -16
- 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/config-watcher.ts +0 -2
- package/src/daemon/context-overflow-policy.ts +4 -13
- package/src/daemon/conversation-agent-loop-handlers.ts +83 -22
- package/src/daemon/conversation-agent-loop.ts +984 -683
- package/src/daemon/conversation-history.ts +10 -19
- package/src/daemon/conversation-lifecycle.ts +37 -19
- package/src/daemon/conversation-notifiers.ts +2 -110
- package/src/daemon/conversation-process.ts +14 -7
- package/src/daemon/conversation-runtime-assembly.ts +532 -411
- package/src/daemon/conversation-tool-setup.ts +41 -4
- package/src/daemon/conversation.ts +80 -35
- package/src/daemon/external-plugins-bootstrap.ts +478 -0
- package/src/daemon/first-greeting.ts +191 -14
- package/src/daemon/handlers/config-model.ts +11 -0
- package/src/daemon/handlers/skills.ts +5 -1
- package/src/daemon/lifecycle.ts +33 -68
- package/src/daemon/message-types/computer-use.ts +2 -34
- package/src/daemon/message-types/conversations.ts +49 -0
- package/src/daemon/message-types/messages.ts +12 -0
- package/src/daemon/server.ts +5 -3
- package/src/daemon/shutdown-handlers.ts +2 -12
- package/src/daemon/tool-side-effects.ts +14 -56
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +160 -0
- package/src/heartbeat/heartbeat-service.ts +24 -1
- package/src/home/__tests__/feed-population-integration.test.ts +312 -0
- package/src/home/emit-feed-event.ts +7 -0
- package/src/home/feed-types.ts +41 -2
- package/src/home/rewrite-command-preview.ts +66 -0
- package/src/ipc/__tests__/socket-path.test.ts +11 -50
- package/src/ipc/cli-client.ts +1 -1
- package/src/ipc/cli-server.ts +3 -3
- package/src/ipc/gateway-client.ts +4 -1
- package/src/ipc/routes/browser-context.ts +2 -0
- package/src/ipc/routes/browser.ts +1 -0
- package/src/ipc/routes/get-contact.ts +16 -0
- package/src/ipc/routes/index.ts +14 -0
- 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/upsert-contact.ts +25 -0
- package/src/ipc/socket-path.ts +14 -38
- 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/conversation-crud.ts +48 -18
- package/src/memory/conversation-queries.ts +57 -4
- package/src/memory/conversation-title-service.ts +25 -0
- package/src/memory/db-init.ts +8 -0
- 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/extraction.ts +10 -2
- package/src/memory/graph/graph-search.test.ts +1 -0
- package/src/memory/graph/inspect.ts +2 -2
- package/src/memory/graph/retriever.ts +10 -3
- package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
- package/src/memory/migrations/149-oauth-tables.ts +1 -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 +4 -0
- package/src/memory/pkb/pkb-index.test.ts +1 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +1 -0
- package/src/memory/pkb/pkb-search.test.ts +65 -4
- package/src/memory/pkb/pkb-search.ts +40 -18
- package/src/memory/qdrant-client.test.ts +60 -0
- package/src/memory/qdrant-client.ts +25 -0
- package/src/memory/schema/infrastructure.ts +1 -0
- package/src/memory/schema/oauth.ts +4 -1
- package/src/messaging/providers/slack/render-transcript.test.ts +77 -29
- package/src/messaging/providers/slack/render-transcript.ts +58 -0
- package/src/notifications/conversation-pairing.ts +78 -19
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/emit-signal.ts +1 -1
- 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 +30 -14
- package/src/oauth/provider-serializer.ts +6 -1
- package/src/oauth/seed-providers.ts +56 -108
- package/src/outbound-proxy/http-forwarder.ts +9 -0
- package/src/permissions/approval-policy.test.ts +293 -18
- package/src/permissions/approval-policy.ts +110 -58
- 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 +414 -2
- package/src/permissions/bash-risk-classifier.ts +303 -60
- package/src/permissions/checker.ts +157 -29
- package/src/permissions/command-registry.test.ts +239 -0
- package/src/permissions/command-registry.ts +234 -54
- package/src/permissions/defaults.ts +5 -4
- package/src/permissions/gateway-threshold-reader.ts +196 -0
- package/src/permissions/prompter.ts +4 -0
- package/src/permissions/risk-types.ts +61 -4
- package/src/permissions/schedule-risk-classifier.test.ts +129 -0
- package/src/permissions/schedule-risk-classifier.ts +85 -0
- package/src/permissions/shell-identity.ts +2 -42
- package/src/permissions/types.ts +2 -0
- package/src/permissions/workspace-policy.ts +8 -3
- 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/templates/BOOTSTRAP.md +27 -77
- package/src/providers/model-catalog.ts +52 -29
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openrouter/client.ts +5 -1
- 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/xai-realtime.test.ts +72 -4
- package/src/providers/speech-to-text/xai-realtime.ts +39 -14
- package/src/runtime/AGENTS.md +25 -16
- 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/client-registry.ts +261 -0
- package/src/runtime/http-server.ts +77 -8
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +1 -22
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +51 -31
- package/src/runtime/routes/approval-routes.ts +17 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +27 -8
- package/src/runtime/routes/conversation-routes.ts +223 -116
- package/src/runtime/routes/inbound-message-handler.ts +88 -13
- package/src/runtime/routes/memory-item-routes.test.ts +1 -0
- package/src/runtime/routes/migration-routes.ts +0 -3
- 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/skill-route-registry.ts +75 -15
- package/src/schedule/run-script.ts +68 -0
- package/src/schedule/schedule-store.ts +7 -1
- package/src/schedule/scheduler.ts +48 -8
- package/src/skills/catalog-cache.ts +12 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +189 -0
- package/src/tools/browser/browser-execution.ts +88 -19
- 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/extension-cdp-client.ts +54 -3
- package/src/tools/browser/cdp-client/factory.ts +15 -4
- package/src/tools/executor.ts +126 -74
- package/src/tools/network/script-proxy/session-manager.ts +37 -1
- package/src/tools/permission-checker.ts +98 -49
- package/src/tools/policy-context.ts +4 -0
- package/src/tools/registry.ts +140 -3
- 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/system/avatar-generator.ts +6 -2
- package/src/tools/types.ts +28 -2
- package/src/util/platform.ts +7 -2
- package/src/util/pricing.ts +26 -3
- 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/041-backfill-google-gmail-settings-scope.ts +3 -4
- 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/registry.ts +12 -0
- 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__/compaction-circuit-breaker.test.ts +0 -336
- package/src/__tests__/context-overflow-approval.test.ts +0 -156
- 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__/send-notification-tool.test.ts +0 -83
- package/src/cli/commands/shotgun.ts +0 -266
- 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 -88
- 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/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/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/runtime/gateway-internal-client.ts +0 -94
- package/src/runtime/routes/watch-routes.ts +0 -156
- 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
|
@@ -136,16 +136,16 @@ describe("allow rule", () => {
|
|
|
136
136
|
expect(result.matchedRule).toBeUndefined();
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
test("allow at High risk — containerized bash
|
|
139
|
+
test("allow at High risk — containerized bash without sandboxAutoApprove flag → prompt", () => {
|
|
140
140
|
const result = evaluate({
|
|
141
141
|
riskLevel: RiskLevel.High,
|
|
142
142
|
toolName: "bash",
|
|
143
143
|
matchedRule: allowRule,
|
|
144
144
|
isContainerized: true,
|
|
145
145
|
});
|
|
146
|
-
expect(result.decision).toBe("
|
|
147
|
-
expect(result.reason).toContain("
|
|
148
|
-
expect(result.matchedRule).
|
|
146
|
+
expect(result.decision).toBe("prompt");
|
|
147
|
+
expect(result.reason).toContain("high risk");
|
|
148
|
+
expect(result.matchedRule).toBeUndefined();
|
|
149
149
|
});
|
|
150
150
|
|
|
151
151
|
test("allow at High risk — non-bash tool, containerized → prompt, no matchedRule in decision", () => {
|
|
@@ -175,6 +175,113 @@ describe("allow rule", () => {
|
|
|
175
175
|
});
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
+
// ── Sandbox auto-approve ─────────────────────────────────────────────────────
|
|
179
|
+
|
|
180
|
+
describe("sandbox auto-approve", () => {
|
|
181
|
+
test("bash + hasSandboxAutoApprove + containerized → allow", () => {
|
|
182
|
+
const result = evaluate({
|
|
183
|
+
riskLevel: RiskLevel.High,
|
|
184
|
+
toolName: "bash",
|
|
185
|
+
hasSandboxAutoApprove: true,
|
|
186
|
+
isContainerized: true,
|
|
187
|
+
});
|
|
188
|
+
expect(result.decision).toBe("allow");
|
|
189
|
+
expect(result.reason).toContain("sandbox auto-approve");
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("bash + hasSandboxAutoApprove + not containerized → allow (path resolution is baked in)", () => {
|
|
193
|
+
const result = evaluate({
|
|
194
|
+
riskLevel: RiskLevel.Low,
|
|
195
|
+
toolName: "bash",
|
|
196
|
+
hasSandboxAutoApprove: true,
|
|
197
|
+
isContainerized: false,
|
|
198
|
+
});
|
|
199
|
+
// hasSandboxAutoApprove === true means path resolution already passed upstream.
|
|
200
|
+
// The isContainerized gate was removed — sandbox auto-approve fires regardless.
|
|
201
|
+
expect(result.decision).toBe("allow");
|
|
202
|
+
expect(result.reason).toContain("sandbox auto-approve");
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test("bash + hasSandboxAutoApprove + not containerized + High risk → allow (path resolution validated upstream)", () => {
|
|
206
|
+
const result = evaluate({
|
|
207
|
+
riskLevel: RiskLevel.High,
|
|
208
|
+
toolName: "bash",
|
|
209
|
+
hasSandboxAutoApprove: true,
|
|
210
|
+
isContainerized: false,
|
|
211
|
+
});
|
|
212
|
+
// Even at High risk, hasSandboxAutoApprove === true means the checker already
|
|
213
|
+
// validated that all path arguments are within the workspace root.
|
|
214
|
+
expect(result.decision).toBe("allow");
|
|
215
|
+
expect(result.reason).toContain("sandbox auto-approve");
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test("host_bash + hasSandboxAutoApprove + containerized → falls through", () => {
|
|
219
|
+
const result = evaluate({
|
|
220
|
+
riskLevel: RiskLevel.Low,
|
|
221
|
+
toolName: "host_bash",
|
|
222
|
+
hasSandboxAutoApprove: true,
|
|
223
|
+
isContainerized: true,
|
|
224
|
+
});
|
|
225
|
+
// host_bash is not "bash", so sandbox auto-approve doesn't fire.
|
|
226
|
+
// Falls through to risk-based: Low → allow (within default "low" threshold)
|
|
227
|
+
expect(result.decision).toBe("allow");
|
|
228
|
+
expect(result.reason).toContain("within auto-approve threshold");
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test("bash + no hasSandboxAutoApprove + containerized → falls through", () => {
|
|
232
|
+
const result = evaluate({
|
|
233
|
+
riskLevel: RiskLevel.High,
|
|
234
|
+
toolName: "bash",
|
|
235
|
+
hasSandboxAutoApprove: false,
|
|
236
|
+
isContainerized: true,
|
|
237
|
+
});
|
|
238
|
+
// hasSandboxAutoApprove is false, so sandbox auto-approve doesn't fire.
|
|
239
|
+
// Falls through to risk-based: High → prompt
|
|
240
|
+
expect(result.decision).toBe("prompt");
|
|
241
|
+
expect(result.reason).toContain("high risk");
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test("sandbox auto-approve fires even for High risk commands", () => {
|
|
245
|
+
// e.g. rm -rf in a container — should be auto-approved
|
|
246
|
+
const result = evaluate({
|
|
247
|
+
riskLevel: RiskLevel.High,
|
|
248
|
+
toolName: "bash",
|
|
249
|
+
hasSandboxAutoApprove: true,
|
|
250
|
+
isContainerized: true,
|
|
251
|
+
});
|
|
252
|
+
expect(result.decision).toBe("allow");
|
|
253
|
+
expect(result.reason).toContain("sandbox auto-approve");
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test("deny rule still blocks sandbox auto-approve commands", () => {
|
|
257
|
+
const denyRule = makeRule({ decision: "deny" });
|
|
258
|
+
const result = evaluate({
|
|
259
|
+
riskLevel: RiskLevel.High,
|
|
260
|
+
toolName: "bash",
|
|
261
|
+
hasSandboxAutoApprove: true,
|
|
262
|
+
isContainerized: true,
|
|
263
|
+
matchedRule: denyRule,
|
|
264
|
+
});
|
|
265
|
+
// Deny at step 1 prevents step 3 (sandbox auto-approve)
|
|
266
|
+
expect(result.decision).toBe("deny");
|
|
267
|
+
expect(result.reason).toContain("deny rule");
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test("strict mode blocks sandbox auto-approve", () => {
|
|
271
|
+
const result = evaluate({
|
|
272
|
+
riskLevel: RiskLevel.Low,
|
|
273
|
+
toolName: "bash",
|
|
274
|
+
hasSandboxAutoApprove: true,
|
|
275
|
+
isContainerized: true,
|
|
276
|
+
permissionsMode: "strict",
|
|
277
|
+
});
|
|
278
|
+
// Strict mode requires explicit rules — sandbox auto-approve only
|
|
279
|
+
// fires in workspace mode.
|
|
280
|
+
expect(result.decision).toBe("prompt");
|
|
281
|
+
expect(result.reason).toContain("Strict mode");
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
|
|
178
285
|
// ── No rule: third-party skill tool ──────────────────────────────────────────
|
|
179
286
|
|
|
180
287
|
describe("no rule — third-party skill tool", () => {
|
|
@@ -220,6 +327,44 @@ describe("no rule — third-party skill tool", () => {
|
|
|
220
327
|
// Bundled skill + Low risk + no rule → handled by step 9 or 11
|
|
221
328
|
expect(result.decision).toBe("allow");
|
|
222
329
|
});
|
|
330
|
+
|
|
331
|
+
test("skill origin, not bundled, gateway threshold covers risk → allow", () => {
|
|
332
|
+
const result = evaluate({
|
|
333
|
+
riskLevel: RiskLevel.Low,
|
|
334
|
+
toolName: "custom_tool",
|
|
335
|
+
toolOrigin: "skill",
|
|
336
|
+
isSkillBundled: false,
|
|
337
|
+
autoApproveUpTo: "medium",
|
|
338
|
+
isGatewayThreshold: true,
|
|
339
|
+
});
|
|
340
|
+
expect(result.decision).toBe("allow");
|
|
341
|
+
expect(result.reason).toContain("within auto-approve threshold");
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
test("skill origin, not bundled, gateway threshold does not cover risk → prompt", () => {
|
|
345
|
+
const result = evaluate({
|
|
346
|
+
riskLevel: RiskLevel.High,
|
|
347
|
+
toolName: "custom_tool",
|
|
348
|
+
toolOrigin: "skill",
|
|
349
|
+
isSkillBundled: false,
|
|
350
|
+
autoApproveUpTo: "medium",
|
|
351
|
+
isGatewayThreshold: true,
|
|
352
|
+
});
|
|
353
|
+
expect(result.decision).toBe("prompt");
|
|
354
|
+
expect(result.reason).toContain("Skill tool");
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test("hasManifestOverride, gateway threshold covers risk → allow", () => {
|
|
358
|
+
const result = evaluate({
|
|
359
|
+
riskLevel: RiskLevel.Low,
|
|
360
|
+
toolName: "unknown_tool",
|
|
361
|
+
hasManifestOverride: true,
|
|
362
|
+
autoApproveUpTo: "low",
|
|
363
|
+
isGatewayThreshold: true,
|
|
364
|
+
});
|
|
365
|
+
expect(result.decision).toBe("allow");
|
|
366
|
+
expect(result.reason).toContain("within auto-approve threshold");
|
|
367
|
+
});
|
|
223
368
|
});
|
|
224
369
|
|
|
225
370
|
// ── No rule: strict mode ─────────────────────────────────────────────────────
|
|
@@ -266,6 +411,30 @@ describe("no rule — strict mode", () => {
|
|
|
266
411
|
expect(result.decision).toBe("prompt");
|
|
267
412
|
expect(result.reason).toContain("Strict mode");
|
|
268
413
|
});
|
|
414
|
+
|
|
415
|
+
test("strict mode, gateway threshold covers risk → allow", () => {
|
|
416
|
+
const result = evaluate({
|
|
417
|
+
riskLevel: RiskLevel.Low,
|
|
418
|
+
toolName: "file_read",
|
|
419
|
+
permissionsMode: "strict",
|
|
420
|
+
autoApproveUpTo: "low",
|
|
421
|
+
isGatewayThreshold: true,
|
|
422
|
+
});
|
|
423
|
+
expect(result.decision).toBe("allow");
|
|
424
|
+
expect(result.reason).toContain("within auto-approve threshold");
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
test("strict mode, gateway threshold does not cover risk → prompt", () => {
|
|
428
|
+
const result = evaluate({
|
|
429
|
+
riskLevel: RiskLevel.Medium,
|
|
430
|
+
toolName: "file_read",
|
|
431
|
+
permissionsMode: "strict",
|
|
432
|
+
autoApproveUpTo: "low",
|
|
433
|
+
isGatewayThreshold: true,
|
|
434
|
+
});
|
|
435
|
+
expect(result.decision).toBe("prompt");
|
|
436
|
+
expect(result.reason).toContain("Strict mode");
|
|
437
|
+
});
|
|
269
438
|
});
|
|
270
439
|
|
|
271
440
|
// ── No rule: workspace mode ──────────────────────────────────────────────────
|
|
@@ -305,7 +474,7 @@ describe("no rule — workspace mode", () => {
|
|
|
305
474
|
expect(result.reason).toContain("medium risk");
|
|
306
475
|
});
|
|
307
476
|
|
|
308
|
-
test("workspace mode, bash, NOT containerized, Low risk, workspace-scoped →
|
|
477
|
+
test("workspace mode, bash, NOT containerized, Low risk, workspace-scoped → allow via workspace mode", () => {
|
|
309
478
|
const result = evaluate({
|
|
310
479
|
riskLevel: RiskLevel.Low,
|
|
311
480
|
toolName: "bash",
|
|
@@ -313,10 +482,8 @@ describe("no rule — workspace mode", () => {
|
|
|
313
482
|
isContainerized: false,
|
|
314
483
|
isWorkspaceScoped: true,
|
|
315
484
|
});
|
|
316
|
-
// Non-containerized bash falls through the workspace check.
|
|
317
|
-
// Then hits risk-based: Low → allow (within default "low" threshold)
|
|
318
485
|
expect(result.decision).toBe("allow");
|
|
319
|
-
expect(result.reason).toContain("
|
|
486
|
+
expect(result.reason).toContain("Workspace mode");
|
|
320
487
|
});
|
|
321
488
|
|
|
322
489
|
test("workspace mode, bash, containerized, Low risk, workspace-scoped → allow via workspace mode", () => {
|
|
@@ -474,10 +641,9 @@ describe("edge cases", () => {
|
|
|
474
641
|
expect(result.decision).toBe("allow");
|
|
475
642
|
});
|
|
476
643
|
|
|
477
|
-
test("workspace mode non-containerized bash, Low risk, workspace-scoped →
|
|
478
|
-
//
|
|
479
|
-
//
|
|
480
|
-
// to the risk-based path where Low risk still auto-allows.
|
|
644
|
+
test("workspace mode non-containerized bash, Low risk, workspace-scoped → workspace allow", () => {
|
|
645
|
+
// Non-containerized bash auto-allows via workspace mode like any other
|
|
646
|
+
// workspace-scoped tool when risk is Low.
|
|
481
647
|
const result = evaluate({
|
|
482
648
|
riskLevel: RiskLevel.Low,
|
|
483
649
|
toolName: "bash",
|
|
@@ -486,10 +652,7 @@ describe("edge cases", () => {
|
|
|
486
652
|
isWorkspaceScoped: true,
|
|
487
653
|
});
|
|
488
654
|
expect(result.decision).toBe("allow");
|
|
489
|
-
|
|
490
|
-
// auto-allow was bypassed because bash is on the host.
|
|
491
|
-
expect(result.reason).not.toContain("Workspace mode");
|
|
492
|
-
expect(result.reason).toContain("low risk");
|
|
655
|
+
expect(result.reason).toContain("Workspace mode");
|
|
493
656
|
});
|
|
494
657
|
|
|
495
658
|
test("hasManifestOverride with toolOrigin set to skill — third-party check triggers on origin", () => {
|
|
@@ -618,6 +781,38 @@ describe("autoApproveUpTo threshold", () => {
|
|
|
618
781
|
});
|
|
619
782
|
});
|
|
620
783
|
|
|
784
|
+
describe('autoApproveUpTo: "high" — everything auto-allows', () => {
|
|
785
|
+
test("Low risk → allow", () => {
|
|
786
|
+
const result = evaluate({
|
|
787
|
+
riskLevel: RiskLevel.Low,
|
|
788
|
+
toolName: "some_tool",
|
|
789
|
+
autoApproveUpTo: "high",
|
|
790
|
+
});
|
|
791
|
+
expect(result.decision).toBe("allow");
|
|
792
|
+
expect(result.reason).toContain("within auto-approve threshold");
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
test("Medium risk → allow", () => {
|
|
796
|
+
const result = evaluate({
|
|
797
|
+
riskLevel: RiskLevel.Medium,
|
|
798
|
+
toolName: "some_tool",
|
|
799
|
+
autoApproveUpTo: "high",
|
|
800
|
+
});
|
|
801
|
+
expect(result.decision).toBe("allow");
|
|
802
|
+
expect(result.reason).toContain("within auto-approve threshold");
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
test("High risk → allow", () => {
|
|
806
|
+
const result = evaluate({
|
|
807
|
+
riskLevel: RiskLevel.High,
|
|
808
|
+
toolName: "some_tool",
|
|
809
|
+
autoApproveUpTo: "high",
|
|
810
|
+
});
|
|
811
|
+
expect(result.decision).toBe("allow");
|
|
812
|
+
expect(result.reason).toContain("within auto-approve threshold");
|
|
813
|
+
});
|
|
814
|
+
});
|
|
815
|
+
|
|
621
816
|
describe("threshold interacts correctly with rule-based decisions", () => {
|
|
622
817
|
test("deny rule still denies regardless of threshold", () => {
|
|
623
818
|
const denyRule = makeRule({ decision: "deny" });
|
|
@@ -631,18 +826,60 @@ describe("autoApproveUpTo threshold", () => {
|
|
|
631
826
|
expect(result.matchedRule).toBe(denyRule);
|
|
632
827
|
});
|
|
633
828
|
|
|
634
|
-
test("ask rule still prompts
|
|
829
|
+
test("ask rule still prompts without gateway threshold flag", () => {
|
|
830
|
+
const askRule = makeRule({ decision: "ask" });
|
|
831
|
+
const result = evaluate({
|
|
832
|
+
riskLevel: RiskLevel.Low,
|
|
833
|
+
toolName: "bash",
|
|
834
|
+
matchedRule: askRule,
|
|
835
|
+
autoApproveUpTo: "medium",
|
|
836
|
+
});
|
|
837
|
+
expect(result.decision).toBe("prompt");
|
|
838
|
+
expect(result.matchedRule).toBe(askRule);
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
test("ask rule auto-approves when gateway threshold covers the risk", () => {
|
|
635
842
|
const askRule = makeRule({ decision: "ask" });
|
|
636
843
|
const result = evaluate({
|
|
637
844
|
riskLevel: RiskLevel.Low,
|
|
638
845
|
toolName: "bash",
|
|
639
846
|
matchedRule: askRule,
|
|
640
847
|
autoApproveUpTo: "medium",
|
|
848
|
+
isGatewayThreshold: true,
|
|
849
|
+
});
|
|
850
|
+
expect(result.decision).toBe("allow");
|
|
851
|
+
expect(result.reason).toContain("within auto-approve threshold");
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
test("ask rule still prompts when gateway threshold does not cover the risk", () => {
|
|
855
|
+
const askRule = makeRule({ decision: "ask" });
|
|
856
|
+
const result = evaluate({
|
|
857
|
+
riskLevel: RiskLevel.High,
|
|
858
|
+
toolName: "bash",
|
|
859
|
+
matchedRule: askRule,
|
|
860
|
+
autoApproveUpTo: "medium",
|
|
861
|
+
isGatewayThreshold: true,
|
|
641
862
|
});
|
|
642
863
|
expect(result.decision).toBe("prompt");
|
|
643
864
|
expect(result.matchedRule).toBe(askRule);
|
|
644
865
|
});
|
|
645
866
|
|
|
867
|
+
test("skill_load_dynamic ask rule always prompts even with gateway threshold", () => {
|
|
868
|
+
const dynamicSkillAskRule = makeRule({
|
|
869
|
+
decision: "ask",
|
|
870
|
+
pattern: "skill_load_dynamic:my-skill",
|
|
871
|
+
});
|
|
872
|
+
const result = evaluate({
|
|
873
|
+
riskLevel: RiskLevel.Low,
|
|
874
|
+
toolName: "skill_load",
|
|
875
|
+
matchedRule: dynamicSkillAskRule,
|
|
876
|
+
autoApproveUpTo: "high",
|
|
877
|
+
isGatewayThreshold: true,
|
|
878
|
+
});
|
|
879
|
+
expect(result.decision).toBe("prompt");
|
|
880
|
+
expect(result.matchedRule).toBe(dynamicSkillAskRule);
|
|
881
|
+
});
|
|
882
|
+
|
|
646
883
|
test("allow rule still allows non-High regardless of threshold", () => {
|
|
647
884
|
const allowRule = makeRule({ decision: "allow" });
|
|
648
885
|
const result = evaluate({
|
|
@@ -727,6 +964,12 @@ describe("resolveThreshold", () => {
|
|
|
727
964
|
expect(resolveThreshold("none", "headless")).toBe("none");
|
|
728
965
|
});
|
|
729
966
|
|
|
967
|
+
test("returns high scalar for any context", () => {
|
|
968
|
+
expect(resolveThreshold("high", "conversation")).toBe("high");
|
|
969
|
+
expect(resolveThreshold("high", "background")).toBe("high");
|
|
970
|
+
expect(resolveThreshold("high", "headless")).toBe("high");
|
|
971
|
+
});
|
|
972
|
+
|
|
730
973
|
test("returns scalar when executionContext is omitted", () => {
|
|
731
974
|
expect(resolveThreshold("low")).toBe("low");
|
|
732
975
|
});
|
|
@@ -808,12 +1051,13 @@ describe("guardian threshold-based auto-approve (ordinal comparison)", () => {
|
|
|
808
1051
|
// This is the logic that replaces the old `riskLevel !== RiskLevel.High` check.
|
|
809
1052
|
function isWithinThreshold(
|
|
810
1053
|
riskLevel: RiskLevel,
|
|
811
|
-
bgThreshold: "none" | "low" | "medium",
|
|
1054
|
+
bgThreshold: "none" | "low" | "medium" | "high",
|
|
812
1055
|
): boolean {
|
|
813
1056
|
const thresholdOrdinal: Record<string, number> = {
|
|
814
1057
|
none: -1,
|
|
815
1058
|
low: 0,
|
|
816
1059
|
medium: 1,
|
|
1060
|
+
high: 2,
|
|
817
1061
|
};
|
|
818
1062
|
const riskOrdinal: Record<string, number> = {
|
|
819
1063
|
[RiskLevel.Low]: 0,
|
|
@@ -906,7 +1150,38 @@ describe("guardian threshold-based auto-approve (ordinal comparison)", () => {
|
|
|
906
1150
|
});
|
|
907
1151
|
});
|
|
908
1152
|
|
|
1153
|
+
describe('loosest config (background: "high") — everything auto-approves', () => {
|
|
1154
|
+
test("Low risk → within threshold (auto-approve)", () => {
|
|
1155
|
+
const bgThreshold = resolveThreshold(
|
|
1156
|
+
{ conversation: "low", background: "high", headless: "none" },
|
|
1157
|
+
"background",
|
|
1158
|
+
);
|
|
1159
|
+
expect(bgThreshold).toBe("high");
|
|
1160
|
+
expect(isWithinThreshold(RiskLevel.Low, bgThreshold)).toBe(true);
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
test("Medium risk → within threshold (auto-approve)", () => {
|
|
1164
|
+
const bgThreshold = resolveThreshold(
|
|
1165
|
+
{ conversation: "low", background: "high", headless: "none" },
|
|
1166
|
+
"background",
|
|
1167
|
+
);
|
|
1168
|
+
expect(isWithinThreshold(RiskLevel.Medium, bgThreshold)).toBe(true);
|
|
1169
|
+
});
|
|
1170
|
+
|
|
1171
|
+
test("High risk → within threshold (auto-approve)", () => {
|
|
1172
|
+
const bgThreshold = resolveThreshold(
|
|
1173
|
+
{ conversation: "low", background: "high", headless: "none" },
|
|
1174
|
+
"background",
|
|
1175
|
+
);
|
|
1176
|
+
expect(isWithinThreshold(RiskLevel.High, bgThreshold)).toBe(true);
|
|
1177
|
+
});
|
|
1178
|
+
});
|
|
1179
|
+
|
|
909
1180
|
describe("scalar config form resolves correctly for background context", () => {
|
|
1181
|
+
test('scalar "high" → background resolves to high', () => {
|
|
1182
|
+
expect(resolveThreshold("high", "background")).toBe("high");
|
|
1183
|
+
});
|
|
1184
|
+
|
|
910
1185
|
test('scalar "medium" → background resolves to medium', () => {
|
|
911
1186
|
expect(resolveThreshold("medium", "background")).toBe("medium");
|
|
912
1187
|
});
|