@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
|
@@ -31,9 +31,11 @@ const TMP_PATHS = String.raw`^(?:/tmp|/var/tmp|\./|\.\.\/)`;
|
|
|
31
31
|
|
|
32
32
|
export const DEFAULT_COMMAND_REGISTRY = {
|
|
33
33
|
// ── Read-only filesystem commands ──────────────────────────────────────────
|
|
34
|
-
ls: { baseRisk: "low" },
|
|
34
|
+
ls: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
35
35
|
cat: {
|
|
36
36
|
baseRisk: "low",
|
|
37
|
+
sandboxAutoApprove: true,
|
|
38
|
+
argSchema: {},
|
|
37
39
|
argRules: [
|
|
38
40
|
{
|
|
39
41
|
id: "cat:sensitive",
|
|
@@ -43,33 +45,78 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
43
45
|
},
|
|
44
46
|
],
|
|
45
47
|
},
|
|
46
|
-
head: { baseRisk: "low" },
|
|
47
|
-
tail: { baseRisk: "low" },
|
|
48
|
-
less: { baseRisk: "low" },
|
|
49
|
-
more: { baseRisk: "low" },
|
|
50
|
-
wc: { baseRisk: "low" },
|
|
51
|
-
file: { baseRisk: "low" },
|
|
52
|
-
stat: { baseRisk: "low" },
|
|
53
|
-
du: { baseRisk: "low" },
|
|
54
|
-
df: { baseRisk: "low" },
|
|
55
|
-
diff: { baseRisk: "low" },
|
|
56
|
-
tree: { baseRisk: "low" },
|
|
57
|
-
pwd: {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
48
|
+
head: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
49
|
+
tail: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
50
|
+
less: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
51
|
+
more: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
52
|
+
wc: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
53
|
+
file: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
54
|
+
stat: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
55
|
+
du: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
56
|
+
df: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
57
|
+
diff: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
58
|
+
tree: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
59
|
+
pwd: {
|
|
60
|
+
baseRisk: "low",
|
|
61
|
+
sandboxAutoApprove: true,
|
|
62
|
+
argSchema: { positionals: "none" },
|
|
63
|
+
},
|
|
64
|
+
realpath: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
65
|
+
basename: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
66
|
+
dirname: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
67
|
+
readlink: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
61
68
|
|
|
62
69
|
// ── Search / filter / text processing ──────────────────────────────────────
|
|
63
|
-
grep: {
|
|
64
|
-
rg: { baseRisk: "low" },
|
|
65
|
-
ag: { baseRisk: "low" },
|
|
66
|
-
ack: { baseRisk: "low" },
|
|
67
|
-
sort: { baseRisk: "low" },
|
|
68
|
-
uniq: { baseRisk: "low" },
|
|
69
|
-
cut: { baseRisk: "low" },
|
|
70
|
-
tr: { baseRisk: "low" },
|
|
71
|
-
sed: {
|
|
70
|
+
grep: {
|
|
72
71
|
baseRisk: "low",
|
|
72
|
+
sandboxAutoApprove: true,
|
|
73
|
+
argSchema: {
|
|
74
|
+
positionals: [{ role: "pattern" }, { role: "path", rest: true }],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
rg: {
|
|
78
|
+
baseRisk: "low",
|
|
79
|
+
sandboxAutoApprove: true,
|
|
80
|
+
argSchema: {
|
|
81
|
+
positionals: [{ role: "pattern" }, { role: "path", rest: true }],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
ag: {
|
|
85
|
+
baseRisk: "low",
|
|
86
|
+
sandboxAutoApprove: true,
|
|
87
|
+
argSchema: {
|
|
88
|
+
positionals: [{ role: "pattern" }, { role: "path", rest: true }],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
ack: {
|
|
92
|
+
baseRisk: "low",
|
|
93
|
+
sandboxAutoApprove: true,
|
|
94
|
+
argSchema: {
|
|
95
|
+
positionals: [{ role: "pattern" }, { role: "path", rest: true }],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
sort: {
|
|
99
|
+
baseRisk: "low",
|
|
100
|
+
sandboxAutoApprove: true,
|
|
101
|
+
argSchema: {
|
|
102
|
+
valueFlags: ["-o", "--output"],
|
|
103
|
+
pathFlags: { "-o": true, "--output": true },
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
uniq: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
107
|
+
cut: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
108
|
+
tr: {
|
|
109
|
+
baseRisk: "low",
|
|
110
|
+
sandboxAutoApprove: true,
|
|
111
|
+
argSchema: { positionals: "none" },
|
|
112
|
+
},
|
|
113
|
+
sed: {
|
|
114
|
+
baseRisk: "medium",
|
|
115
|
+
reason: "Can write files or execute commands via sed scripts",
|
|
116
|
+
sandboxAutoApprove: true,
|
|
117
|
+
argSchema: {
|
|
118
|
+
positionals: [{ role: "script" }, { role: "path", rest: true }],
|
|
119
|
+
},
|
|
73
120
|
argRules: [
|
|
74
121
|
{
|
|
75
122
|
id: "sed:inplace",
|
|
@@ -81,13 +128,24 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
81
128
|
},
|
|
82
129
|
awk: {
|
|
83
130
|
baseRisk: "medium",
|
|
131
|
+
argSchema: {
|
|
132
|
+
positionals: [{ role: "script" }, { role: "path", rest: true }],
|
|
133
|
+
},
|
|
84
134
|
complexSyntax: true,
|
|
85
135
|
reason: "Can execute shell commands via system()",
|
|
86
136
|
},
|
|
87
137
|
|
|
88
138
|
// ── System information (read-only) ─────────────────────────────────────────
|
|
89
|
-
echo: {
|
|
90
|
-
|
|
139
|
+
echo: {
|
|
140
|
+
baseRisk: "low",
|
|
141
|
+
sandboxAutoApprove: true,
|
|
142
|
+
argSchema: { positionals: "none" },
|
|
143
|
+
},
|
|
144
|
+
printf: {
|
|
145
|
+
baseRisk: "low",
|
|
146
|
+
sandboxAutoApprove: true,
|
|
147
|
+
argSchema: { positionals: "none" },
|
|
148
|
+
},
|
|
91
149
|
whoami: { baseRisk: "low" },
|
|
92
150
|
uname: { baseRisk: "low" },
|
|
93
151
|
uptime: { baseRisk: "low" },
|
|
@@ -113,14 +171,31 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
113
171
|
hexdump: { baseRisk: "low" },
|
|
114
172
|
|
|
115
173
|
// ── Data processing ────────────────────────────────────────────────────────
|
|
116
|
-
jq: { baseRisk: "low" },
|
|
117
|
-
yq: { baseRisk: "low" },
|
|
174
|
+
jq: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
175
|
+
yq: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
118
176
|
|
|
119
177
|
// ── Find ───────────────────────────────────────────────────────────────────
|
|
120
178
|
// DIVERGENCE: checker.ts lists `find` as LOW_RISK unconditionally. Our
|
|
121
179
|
// registry adds arg rules for -exec/-execdir/-delete which escalate to high.
|
|
122
180
|
find: {
|
|
123
181
|
baseRisk: "low",
|
|
182
|
+
argSchema: {
|
|
183
|
+
valueFlags: [
|
|
184
|
+
"-name",
|
|
185
|
+
"-iname",
|
|
186
|
+
"-path",
|
|
187
|
+
"-ipath",
|
|
188
|
+
"-regex",
|
|
189
|
+
"-iregex",
|
|
190
|
+
"-maxdepth",
|
|
191
|
+
"-mindepth",
|
|
192
|
+
"-newer",
|
|
193
|
+
"-user",
|
|
194
|
+
"-group",
|
|
195
|
+
"-printf",
|
|
196
|
+
"-fprintf",
|
|
197
|
+
],
|
|
198
|
+
},
|
|
124
199
|
complexSyntax: true,
|
|
125
200
|
argRules: [
|
|
126
201
|
{
|
|
@@ -137,11 +212,16 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
137
212
|
},
|
|
138
213
|
],
|
|
139
214
|
},
|
|
140
|
-
fd: { baseRisk: "low" },
|
|
215
|
+
fd: { baseRisk: "low", sandboxAutoApprove: true, argSchema: {} },
|
|
141
216
|
|
|
142
217
|
// ── Write commands ─────────────────────────────────────────────────────────
|
|
143
218
|
cp: {
|
|
144
219
|
baseRisk: "medium",
|
|
220
|
+
sandboxAutoApprove: true,
|
|
221
|
+
argSchema: {
|
|
222
|
+
valueFlags: ["-t", "--target-directory"],
|
|
223
|
+
pathFlags: { "-t": true, "--target-directory": true },
|
|
224
|
+
},
|
|
145
225
|
argRules: [
|
|
146
226
|
{
|
|
147
227
|
id: "cp:system",
|
|
@@ -153,6 +233,8 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
153
233
|
},
|
|
154
234
|
mv: {
|
|
155
235
|
baseRisk: "medium",
|
|
236
|
+
sandboxAutoApprove: true,
|
|
237
|
+
argSchema: {},
|
|
156
238
|
argRules: [
|
|
157
239
|
{
|
|
158
240
|
id: "mv:system",
|
|
@@ -162,15 +244,25 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
162
244
|
},
|
|
163
245
|
],
|
|
164
246
|
},
|
|
165
|
-
mkdir: { baseRisk: "medium" },
|
|
166
|
-
touch: { baseRisk: "medium" },
|
|
247
|
+
mkdir: { baseRisk: "medium", sandboxAutoApprove: true, argSchema: {} },
|
|
248
|
+
touch: { baseRisk: "medium", sandboxAutoApprove: true, argSchema: {} },
|
|
249
|
+
ln: {
|
|
250
|
+
baseRisk: "medium",
|
|
251
|
+
sandboxAutoApprove: true,
|
|
252
|
+
argSchema: {
|
|
253
|
+
valueFlags: ["-t", "--target-directory"],
|
|
254
|
+
pathFlags: { "-t": true, "--target-directory": true },
|
|
255
|
+
},
|
|
256
|
+
},
|
|
167
257
|
// DIVERGENCE: checker.ts lists `tee` as LOW_RISK. Our registry classifies
|
|
168
258
|
// it as medium because it writes to files.
|
|
169
|
-
tee: { baseRisk: "medium" },
|
|
259
|
+
tee: { baseRisk: "medium", sandboxAutoApprove: true, argSchema: {} },
|
|
170
260
|
|
|
171
261
|
// ── Delete commands ────────────────────────────────────────────────────────
|
|
172
262
|
rm: {
|
|
173
263
|
baseRisk: "high",
|
|
264
|
+
sandboxAutoApprove: true,
|
|
265
|
+
argSchema: {},
|
|
174
266
|
argRules: [
|
|
175
267
|
{
|
|
176
268
|
id: "rm:recursive-force",
|
|
@@ -204,11 +296,45 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
204
296
|
},
|
|
205
297
|
],
|
|
206
298
|
},
|
|
207
|
-
rmdir: { baseRisk: "high" },
|
|
299
|
+
rmdir: { baseRisk: "high", sandboxAutoApprove: true, argSchema: {} },
|
|
208
300
|
|
|
209
301
|
// ── Network commands ───────────────────────────────────────────────────────
|
|
210
302
|
curl: {
|
|
211
303
|
baseRisk: "medium",
|
|
304
|
+
argSchema: {
|
|
305
|
+
valueFlags: [
|
|
306
|
+
"-d",
|
|
307
|
+
"--data",
|
|
308
|
+
"--data-binary",
|
|
309
|
+
"--data-raw",
|
|
310
|
+
"--data-urlencode",
|
|
311
|
+
"-T",
|
|
312
|
+
"--upload-file",
|
|
313
|
+
"-o",
|
|
314
|
+
"--output",
|
|
315
|
+
"-H",
|
|
316
|
+
"--header",
|
|
317
|
+
"-X",
|
|
318
|
+
"--request",
|
|
319
|
+
"-u",
|
|
320
|
+
"--user",
|
|
321
|
+
"-A",
|
|
322
|
+
"--user-agent",
|
|
323
|
+
"-e",
|
|
324
|
+
"--referer",
|
|
325
|
+
"-b",
|
|
326
|
+
"--cookie",
|
|
327
|
+
"-c",
|
|
328
|
+
"--cookie-jar",
|
|
329
|
+
"--connect-timeout",
|
|
330
|
+
"-m",
|
|
331
|
+
"--max-time",
|
|
332
|
+
"--retry",
|
|
333
|
+
"-w",
|
|
334
|
+
"--write-out",
|
|
335
|
+
],
|
|
336
|
+
positionals: "none", // positionals are URLs, not paths
|
|
337
|
+
},
|
|
212
338
|
argRules: [
|
|
213
339
|
{
|
|
214
340
|
id: "curl:upload-data",
|
|
@@ -254,15 +380,17 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
254
380
|
// Divergences are noted inline.
|
|
255
381
|
git: {
|
|
256
382
|
baseRisk: "medium",
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
383
|
+
argSchema: {
|
|
384
|
+
valueFlags: [
|
|
385
|
+
"-C",
|
|
386
|
+
"-c",
|
|
387
|
+
"--git-dir",
|
|
388
|
+
"--work-tree",
|
|
389
|
+
"--namespace",
|
|
390
|
+
"--super-prefix",
|
|
391
|
+
"--config-env",
|
|
392
|
+
],
|
|
393
|
+
},
|
|
266
394
|
subcommands: {
|
|
267
395
|
// LOW_RISK_GIT_SUBCOMMANDS from checker.ts:
|
|
268
396
|
status: { baseRisk: "low" },
|
|
@@ -357,7 +485,9 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
357
485
|
// they download and execute code, with subcommand-level overrides.
|
|
358
486
|
npm: {
|
|
359
487
|
baseRisk: "medium",
|
|
360
|
-
|
|
488
|
+
argSchema: {
|
|
489
|
+
valueFlags: ["--prefix", "--userconfig", "--globalconfig", "--cache"],
|
|
490
|
+
},
|
|
361
491
|
subcommands: {
|
|
362
492
|
ls: { baseRisk: "low" },
|
|
363
493
|
list: { baseRisk: "low" },
|
|
@@ -531,7 +661,9 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
531
661
|
// ── Docker ─────────────────────────────────────────────────────────────────
|
|
532
662
|
docker: {
|
|
533
663
|
baseRisk: "medium",
|
|
534
|
-
|
|
664
|
+
argSchema: {
|
|
665
|
+
valueFlags: ["--host", "-H", "--config", "--context", "--log-level"],
|
|
666
|
+
},
|
|
535
667
|
subcommands: {
|
|
536
668
|
ps: { baseRisk: "low" },
|
|
537
669
|
images: { baseRisk: "low" },
|
|
@@ -544,6 +676,26 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
544
676
|
push: { baseRisk: "high", reason: "Pushes image to registry" },
|
|
545
677
|
run: {
|
|
546
678
|
baseRisk: "high",
|
|
679
|
+
argSchema: {
|
|
680
|
+
valueFlags: [
|
|
681
|
+
"-v",
|
|
682
|
+
"--volume",
|
|
683
|
+
"-p",
|
|
684
|
+
"--publish",
|
|
685
|
+
"-e",
|
|
686
|
+
"--env",
|
|
687
|
+
"--name",
|
|
688
|
+
"--network",
|
|
689
|
+
"-w",
|
|
690
|
+
"--workdir",
|
|
691
|
+
"--entrypoint",
|
|
692
|
+
"--mount",
|
|
693
|
+
"--cpus",
|
|
694
|
+
"--memory",
|
|
695
|
+
"--user",
|
|
696
|
+
"--platform",
|
|
697
|
+
],
|
|
698
|
+
},
|
|
547
699
|
reason: "Runs arbitrary container",
|
|
548
700
|
argRules: [
|
|
549
701
|
{
|
|
@@ -584,9 +736,24 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
584
736
|
isWrapper: true,
|
|
585
737
|
reason: "Elevates privileges (OpenBSD sudo alternative)",
|
|
586
738
|
},
|
|
587
|
-
chmod: {
|
|
588
|
-
|
|
589
|
-
|
|
739
|
+
chmod: {
|
|
740
|
+
baseRisk: "high",
|
|
741
|
+
sandboxAutoApprove: true,
|
|
742
|
+
argSchema: {},
|
|
743
|
+
reason: "Changes file permissions",
|
|
744
|
+
},
|
|
745
|
+
chown: {
|
|
746
|
+
baseRisk: "high",
|
|
747
|
+
sandboxAutoApprove: true,
|
|
748
|
+
argSchema: {},
|
|
749
|
+
reason: "Changes file ownership",
|
|
750
|
+
},
|
|
751
|
+
chgrp: {
|
|
752
|
+
baseRisk: "high",
|
|
753
|
+
sandboxAutoApprove: true,
|
|
754
|
+
argSchema: {},
|
|
755
|
+
reason: "Changes file group",
|
|
756
|
+
},
|
|
590
757
|
mount: { baseRisk: "high", reason: "Mounts filesystem" },
|
|
591
758
|
umount: { baseRisk: "high", reason: "Unmounts filesystem" },
|
|
592
759
|
systemctl: { baseRisk: "high", reason: "Controls system services" },
|
|
@@ -726,16 +893,29 @@ export const DEFAULT_COMMAND_REGISTRY = {
|
|
|
726
893
|
complexSyntax: true,
|
|
727
894
|
reason: "Executes command with piped arguments",
|
|
728
895
|
},
|
|
729
|
-
tar: {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
896
|
+
tar: {
|
|
897
|
+
baseRisk: "medium",
|
|
898
|
+
sandboxAutoApprove: true,
|
|
899
|
+
argSchema: {
|
|
900
|
+
valueFlags: ["-C", "--directory", "-f", "--file"],
|
|
901
|
+
pathFlags: {
|
|
902
|
+
"-C": true,
|
|
903
|
+
"--directory": true,
|
|
904
|
+
"-f": true,
|
|
905
|
+
"--file": true,
|
|
906
|
+
},
|
|
907
|
+
},
|
|
908
|
+
complexSyntax: true,
|
|
909
|
+
},
|
|
910
|
+
zip: { baseRisk: "medium", sandboxAutoApprove: true, argSchema: {} },
|
|
911
|
+
unzip: { baseRisk: "medium", sandboxAutoApprove: true, argSchema: {} },
|
|
912
|
+
gzip: { baseRisk: "medium", sandboxAutoApprove: true, argSchema: {} },
|
|
913
|
+
gunzip: { baseRisk: "medium", sandboxAutoApprove: true, argSchema: {} },
|
|
734
914
|
|
|
735
915
|
// ── Version control tools ──────────────────────────────────────────────────
|
|
736
916
|
gh: {
|
|
737
917
|
baseRisk: "low",
|
|
738
|
-
|
|
918
|
+
argSchema: { valueFlags: ["--repo", "-R"] },
|
|
739
919
|
subcommands: {
|
|
740
920
|
pr: {
|
|
741
921
|
baseRisk: "low",
|
|
@@ -85,10 +85,11 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
// When running inside a container (IS_CONTAINERIZED=true), bash commands
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
88
|
+
// with sandboxAutoApprove tags auto-allow via the approval policy's
|
|
89
|
+
// sandbox auto-approve check. Non-allowlisted commands matched by the
|
|
90
|
+
// default allow rule below are still auto-allowed at low/medium risk;
|
|
91
|
+
// only high-risk non-allowlisted commands (runtimes, privilege escalation)
|
|
92
|
+
// fall through to be prompted.
|
|
92
93
|
const bashShellRule: DefaultRuleTemplate | null = getIsContainerized()
|
|
93
94
|
? {
|
|
94
95
|
id: "default:allow-bash-global",
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway-backed auto-approve threshold reader.
|
|
3
|
+
*
|
|
4
|
+
* When the `permission-controls-v3` feature flag is enabled, reads
|
|
5
|
+
* thresholds from the gateway via IPC. Falls back to `undefined` (caller
|
|
6
|
+
* uses config-based `resolveThreshold`) when the flag is off or the gateway
|
|
7
|
+
* is unreachable.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
11
|
+
import { getConfig } from "../config/loader.js";
|
|
12
|
+
import { ipcCall } from "../ipc/gateway-client.js";
|
|
13
|
+
import { getLogger } from "../util/logger.js";
|
|
14
|
+
import type { ExecutionContext } from "./approval-policy.js";
|
|
15
|
+
|
|
16
|
+
const log = getLogger("gateway-threshold-reader");
|
|
17
|
+
|
|
18
|
+
// ── Types ────────────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
type Threshold = "none" | "low" | "medium" | "high";
|
|
21
|
+
|
|
22
|
+
interface GlobalThresholds {
|
|
23
|
+
interactive: string;
|
|
24
|
+
background: string;
|
|
25
|
+
headless: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface ConversationThreshold {
|
|
29
|
+
threshold: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ── Global threshold cache (30s TTL) ─────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
let cachedGlobalThresholds: GlobalThresholds | null = null;
|
|
35
|
+
let cachedGlobalTimestamp = 0;
|
|
36
|
+
const GLOBAL_CACHE_TTL_MS = 30_000;
|
|
37
|
+
|
|
38
|
+
// ── Conversation threshold cache (5s TTL) ────────────────────────────────────
|
|
39
|
+
// Shorter TTL than global because the user can change mid-conversation via the
|
|
40
|
+
// picker UI, but still avoids a network roundtrip on every single tool call
|
|
41
|
+
// within a burst.
|
|
42
|
+
|
|
43
|
+
const conversationThresholdCache = new Map<
|
|
44
|
+
string,
|
|
45
|
+
{ threshold: string | null; timestamp: number }
|
|
46
|
+
>();
|
|
47
|
+
const CONVERSATION_CACHE_TTL_MS = 5_000;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Clear the global threshold cache. Exported for testing.
|
|
51
|
+
*/
|
|
52
|
+
export function _clearGlobalCacheForTesting(): void {
|
|
53
|
+
cachedGlobalThresholds = null;
|
|
54
|
+
cachedGlobalTimestamp = 0;
|
|
55
|
+
conversationThresholdCache.clear();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── Hardcoded fallback defaults ──────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
const HARDCODED_DEFAULTS: Record<ExecutionContext, Threshold> = {
|
|
61
|
+
conversation: "low",
|
|
62
|
+
background: "medium",
|
|
63
|
+
headless: "none",
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
function mapExecutionContextToField(
|
|
69
|
+
executionContext: ExecutionContext,
|
|
70
|
+
): keyof GlobalThresholds {
|
|
71
|
+
if (executionContext === "conversation") return "interactive";
|
|
72
|
+
return executionContext;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isValidThreshold(value: string): value is Threshold {
|
|
76
|
+
return (
|
|
77
|
+
value === "none" ||
|
|
78
|
+
value === "low" ||
|
|
79
|
+
value === "medium" ||
|
|
80
|
+
value === "high"
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ── Main export ──────────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Read the auto-approve threshold from the gateway via IPC.
|
|
88
|
+
*
|
|
89
|
+
* Returns `undefined` when the feature flag is off (caller falls back to
|
|
90
|
+
* config-based `resolveThreshold`).
|
|
91
|
+
*
|
|
92
|
+
* For `"conversation"` context with a `conversationId`, checks for a
|
|
93
|
+
* per-conversation override first. Falls through to global defaults when
|
|
94
|
+
* the conversation override is absent.
|
|
95
|
+
*
|
|
96
|
+
* Caches global thresholds for 30 seconds to avoid hammering the gateway.
|
|
97
|
+
* On any IPC error, logs a warning and returns hardcoded defaults.
|
|
98
|
+
*/
|
|
99
|
+
export async function getAutoApproveThreshold(
|
|
100
|
+
conversationId: string | undefined,
|
|
101
|
+
executionContext?: ExecutionContext,
|
|
102
|
+
): Promise<Threshold | undefined> {
|
|
103
|
+
const config = getConfig();
|
|
104
|
+
if (!isAssistantFeatureFlagEnabled("permission-controls-v3", config)) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const ctx: ExecutionContext = executionContext ?? "conversation";
|
|
109
|
+
|
|
110
|
+
// For conversation context with a conversationId, try per-conversation override first
|
|
111
|
+
if (ctx === "conversation" && conversationId) {
|
|
112
|
+
// Check cache first (5s TTL) — includes negative entries (no override)
|
|
113
|
+
const cached = conversationThresholdCache.get(conversationId);
|
|
114
|
+
if (cached && Date.now() - cached.timestamp < CONVERSATION_CACHE_TTL_MS) {
|
|
115
|
+
if (cached.threshold === null) {
|
|
116
|
+
// Negative cache hit — no override exists, fall through to global
|
|
117
|
+
} else if (isValidThreshold(cached.threshold)) {
|
|
118
|
+
return cached.threshold;
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
// ipcCall() returns undefined on transport failure (socket not found,
|
|
122
|
+
// timeout, etc.) and null when the gateway explicitly says "no override".
|
|
123
|
+
// We must distinguish the two: only cache the negative on `null`, and
|
|
124
|
+
// fall back to hardcoded defaults on `undefined` without poisoning the
|
|
125
|
+
// cache — otherwise a transient IPC failure would cause subsequent
|
|
126
|
+
// approval checks to skip a real override for up to 5 seconds.
|
|
127
|
+
const result = (await ipcCall("get_conversation_threshold", {
|
|
128
|
+
conversationId,
|
|
129
|
+
})) as ConversationThreshold | null | undefined;
|
|
130
|
+
|
|
131
|
+
if (result === undefined) {
|
|
132
|
+
log.warn(
|
|
133
|
+
{ conversationId },
|
|
134
|
+
"IPC call failed for conversation threshold override, falling back to defaults",
|
|
135
|
+
);
|
|
136
|
+
return HARDCODED_DEFAULTS[ctx];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (result && isValidThreshold(result.threshold)) {
|
|
140
|
+
conversationThresholdCache.set(conversationId, {
|
|
141
|
+
threshold: result.threshold,
|
|
142
|
+
timestamp: Date.now(),
|
|
143
|
+
});
|
|
144
|
+
return result.threshold;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// result === null (or an unexpected shape) — cache the negative result
|
|
148
|
+
// and fall through to global defaults.
|
|
149
|
+
conversationThresholdCache.set(conversationId, {
|
|
150
|
+
threshold: null,
|
|
151
|
+
timestamp: Date.now(),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Fetch global thresholds (with 30s cache)
|
|
157
|
+
try {
|
|
158
|
+
const global = await fetchGlobalThresholds();
|
|
159
|
+
const field = mapExecutionContextToField(ctx);
|
|
160
|
+
const value = global[field];
|
|
161
|
+
if (isValidThreshold(value)) {
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
// Unexpected value from gateway — fall back to hardcoded
|
|
165
|
+
log.warn({ field, value }, "Gateway returned unexpected threshold value");
|
|
166
|
+
return HARDCODED_DEFAULTS[ctx];
|
|
167
|
+
} catch (err) {
|
|
168
|
+
log.warn(
|
|
169
|
+
{ error: String(err) },
|
|
170
|
+
"Failed to fetch global thresholds, falling back to defaults",
|
|
171
|
+
);
|
|
172
|
+
return HARDCODED_DEFAULTS[ctx];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async function fetchGlobalThresholds(): Promise<GlobalThresholds> {
|
|
177
|
+
const now = Date.now();
|
|
178
|
+
if (
|
|
179
|
+
cachedGlobalThresholds &&
|
|
180
|
+
now - cachedGlobalTimestamp < GLOBAL_CACHE_TTL_MS
|
|
181
|
+
) {
|
|
182
|
+
return cachedGlobalThresholds;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const result = (await ipcCall(
|
|
186
|
+
"get_global_thresholds",
|
|
187
|
+
)) as GlobalThresholds | null;
|
|
188
|
+
|
|
189
|
+
if (!result) {
|
|
190
|
+
throw new Error("Gateway IPC returned no result for global thresholds");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
cachedGlobalThresholds = result;
|
|
194
|
+
cachedGlobalTimestamp = Date.now();
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
@@ -66,6 +66,8 @@ export class PermissionPrompter {
|
|
|
66
66
|
temporaryOptionsAvailable?: Array<"allow_10m" | "allow_conversation">,
|
|
67
67
|
toolUseId?: string,
|
|
68
68
|
hostAccessEnablePrompt?: boolean,
|
|
69
|
+
riskReason?: string,
|
|
70
|
+
isContainerized?: boolean,
|
|
69
71
|
): Promise<{
|
|
70
72
|
decision: UserDecision;
|
|
71
73
|
selectedPattern?: string;
|
|
@@ -116,6 +118,8 @@ export class PermissionPrompter {
|
|
|
116
118
|
toolName,
|
|
117
119
|
input: redactSensitiveFields(input),
|
|
118
120
|
riskLevel,
|
|
121
|
+
riskReason,
|
|
122
|
+
isContainerized,
|
|
119
123
|
allowlistOptions: allowlistOptions.map((o) => ({
|
|
120
124
|
label: o.label,
|
|
121
125
|
description: o.description,
|