@vellumai/assistant 0.11.4 → 0.11.5-staging.1
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 +2 -2
- package/ARCHITECTURE.md +29 -4
- package/README.md +1 -1
- package/docs/architecture/memory.md +17 -5
- package/docs/architecture/security.md +96 -152
- package/docs/guardian-request-flow.md +13 -2
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
- package/node_modules/@vellumai/gateway-client/src/http-delivery.ts +7 -14
- package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +29 -31
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/openapi.yaml +193 -3
- package/package.json +1 -1
- package/src/__tests__/anthropic-provider.test.ts +10 -3
- package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
- package/src/__tests__/channel-approval-routes.test.ts +4 -0
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -6
- package/src/__tests__/channel-reply-delivery.test.ts +26 -13
- package/src/__tests__/checker.test.ts +20 -314
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
- package/src/__tests__/client-os-metadata-persistence.test.ts +16 -0
- package/src/__tests__/compactor-retained-image-validation.test.ts +142 -0
- package/src/__tests__/container-cpu-sampler.test.ts +153 -0
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/conversation-attachments.test.ts +0 -1
- package/src/__tests__/conversation-error.test.ts +17 -0
- package/src/__tests__/conversation-lifecycle.test.ts +20 -26
- package/src/__tests__/conversation-pairing.test.ts +186 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +21 -2
- package/src/__tests__/credential-broker-server-use.test.ts +24 -5
- package/src/__tests__/credential-routes.test.ts +22 -3
- package/src/__tests__/credential-security-invariants.test.ts +2 -1
- package/src/__tests__/daemon-credential-client.test.ts +88 -0
- package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
- package/src/__tests__/dm-backfill.test.ts +63 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
- package/src/__tests__/edit-propagation.test.ts +107 -4
- package/src/__tests__/events-client-registration.test.ts +28 -0
- package/src/__tests__/file-write-tool.test.ts +4 -2
- package/src/__tests__/guardian-prompt-notice-privacy.test.ts +133 -0
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +143 -97
- package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
- package/src/__tests__/host-proxy-interface.test.ts +11 -1
- package/src/__tests__/host-shell-tool.test.ts +23 -4
- package/src/__tests__/image-conversion.test.ts +143 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
- package/src/__tests__/input-repairs.test.ts +207 -0
- package/src/__tests__/live-workspace-guard.test.ts +75 -0
- package/src/__tests__/mcp-abort-signal.test.ts +1 -1
- package/src/__tests__/mcp-client-auth.test.ts +1 -1
- package/src/__tests__/mcp-tool-annotations-risk.test.ts +1 -1
- package/src/__tests__/media-resolve-image-validation.test.ts +310 -0
- package/src/__tests__/mtime-cache.test.ts +2 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +124 -1
- package/src/__tests__/openai-provider.test.ts +22 -0
- package/src/__tests__/personal-memory-auth-bypass.test.ts +22 -6
- package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
- package/src/__tests__/platform.test.ts +16 -1
- package/src/__tests__/plugin-api-resolve-credential.test.ts +22 -13
- package/src/__tests__/plugin-api-shim.test.ts +5 -0
- package/src/__tests__/plugin-api-store-credential.test.ts +268 -0
- package/src/__tests__/plugin-config-data-migration.test.ts +8 -1
- package/src/__tests__/plugin-disabled-state.test.ts +2 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
- package/src/__tests__/plugin-execution-context.test.ts +73 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -1
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +0 -1
- package/src/__tests__/reaction-persistence.test.ts +200 -7
- package/src/__tests__/require-fresh-approval.test.ts +0 -4
- package/src/__tests__/resource-pressure-guard.test.ts +428 -0
- package/src/__tests__/resource-pressure-routes.test.ts +113 -0
- package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +27 -1
- package/src/__tests__/secret-routes-platform-proxy.test.ts +7 -0
- package/src/__tests__/skill-tool-factory.test.ts +161 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
- package/src/__tests__/tool-executor.test.ts +63 -38
- package/src/__tests__/tool-policy.test.ts +97 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +7 -4
- package/src/__tests__/user-plugin-loader.test.ts +2 -0
- package/src/__tests__/validate-input.test.ts +243 -7
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/acp/__tests__/acp-claude-oauth.test.ts +97 -29
- package/src/acp/__tests__/prepare-agent-env.test.ts +376 -153
- package/src/acp/acp-claude-oauth.ts +38 -21
- package/src/acp/prepare-agent-env.ts +146 -55
- package/src/agent/loop-tool-dedup.test.ts +161 -0
- package/src/agent/loop.ts +68 -22
- package/src/api/constants/app-tools.ts +34 -0
- package/src/api/events/resource-pressure-status-changed.ts +53 -0
- package/src/api/index.ts +19 -0
- package/src/api/responses/resource-pressure-status.ts +25 -0
- package/src/approvals/guardian-channel-delivery.ts +70 -6
- package/src/approvals/guardian-request-resolvers.ts +32 -66
- package/src/channels/__tests__/message-audience.test.ts +49 -0
- package/src/channels/__tests__/types.test.ts +17 -3
- package/src/channels/message-audience.ts +40 -0
- package/src/channels/types.ts +16 -12
- package/src/cli/__tests__/catalog-search-help.test.ts +50 -0
- package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +31 -0
- package/src/cli/commands/__tests__/conversations-search.test.ts +289 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -0
- package/src/cli/commands/__tests__/inference-providers.test.ts +68 -0
- package/src/cli/commands/__tests__/keys.test.ts +89 -8
- package/src/cli/commands/__tests__/plugins.test.ts +57 -1
- package/src/cli/commands/channel-verification-sessions.help.ts +11 -9
- package/src/cli/commands/channel-verification-sessions.ts +11 -21
- package/src/cli/commands/conversations.help.ts +34 -0
- package/src/cli/commands/conversations.ts +125 -0
- package/src/cli/commands/inference-providers.ts +9 -4
- package/src/cli/commands/inference.help.ts +9 -4
- package/src/cli/commands/keys.help.ts +13 -1
- package/src/cli/commands/keys.ts +26 -15
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
- package/src/cli/commands/memory/index.help.ts +41 -27
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/memory-v2.ts +58 -54
- package/src/cli/commands/memory/memory-validate.ts +18 -0
- package/src/cli/commands/monitoring.ts +1 -0
- package/src/cli/commands/plugins.help.ts +28 -31
- package/src/cli/commands/plugins.ts +10 -0
- package/src/cli/commands/skills.help.ts +13 -16
- package/src/cli/commands/trust.ts +3 -14
- package/src/cli/lib/__tests__/install-from-github.test.ts +38 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +34 -0
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +32 -1
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +2 -1
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +64 -0
- package/src/cli/lib/bundled-marketplace.json +13 -0
- package/src/cli/lib/daemon-credential-client.ts +25 -3
- package/src/cli/lib/install-from-github.ts +35 -24
- package/src/cli/lib/merge-plugin-tree.ts +22 -4
- package/src/cli/lib/plugin-surfaces.ts +27 -0
- package/src/config/feature-flag-registry.json +35 -19
- package/src/config/webhook-routing.ts +8 -0
- package/src/context/compactor.ts +31 -2
- package/src/daemon/__tests__/provider-rejection-log-fields.test.ts +272 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +4 -1
- package/src/daemon/conversation-error.ts +13 -0
- package/src/daemon/conversation-messaging.ts +22 -2
- package/src/daemon/conversation-process.ts +11 -0
- package/src/daemon/conversation-store.ts +10 -0
- package/src/daemon/conversation-surfaces.ts +21 -8
- package/src/daemon/conversation.ts +12 -10
- package/src/daemon/lifecycle.ts +6 -2
- package/src/daemon/message-types/conversations.ts +5 -7
- package/src/daemon/provider-rejection-log-fields.ts +124 -0
- package/src/daemon/resource-pressure-guard-lifecycle.ts +66 -0
- package/src/daemon/resource-pressure-guard.ts +387 -0
- package/src/daemon/shutdown-handlers.ts +2 -0
- package/src/daemon/startup-error.ts +16 -0
- package/src/daemon/trust-context.ts +14 -10
- package/src/daemon/unsendable-image-notice.ts +76 -0
- package/src/hooks/registry.ts +65 -51
- package/src/ipc/__tests__/socket-path.test.ts +15 -7
- package/src/ipc/gateway-client.test.ts +1 -1
- package/src/ipc/gateway-client.ts +14 -21
- package/src/ipc/socket-cleanup.ts +2 -11
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +1 -1
- package/src/messaging/provider-message-metadata.ts +128 -0
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +116 -68
- package/src/messaging/providers/channel-transport.ts +90 -13
- package/src/messaging/providers/discord/send.ts +16 -0
- package/src/messaging/providers/discord/transport.ts +11 -1
- package/src/messaging/providers/index.ts +109 -16
- package/src/messaging/providers/slack/message-metadata.ts +45 -0
- package/src/messaging/providers/slack/render-transcript.ts +1 -4
- package/src/messaging/providers/slack/send.test.ts +6 -9
- package/src/messaging/providers/slack/send.ts +40 -28
- package/src/messaging/providers/slack/transport.ts +22 -26
- package/src/messaging/providers/telegram-bot/send.test.ts +2 -8
- package/src/messaging/providers/telegram-bot/transport.ts +3 -6
- package/src/messaging/read-provider-metadata.test.ts +157 -0
- package/src/messaging/read-provider-metadata.ts +51 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +94 -0
- package/src/notifications/__tests__/edit-notification.test.ts +174 -2
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +536 -4
- package/src/notifications/adapters/macos.ts +55 -0
- package/src/notifications/adapters/slack.ts +10 -5
- package/src/notifications/assistant-reply-producer.ts +37 -4
- package/src/notifications/conversation-pairing.ts +111 -21
- package/src/notifications/edit-notification.ts +38 -8
- package/src/notifications/emit-signal.ts +12 -14
- package/src/notifications/home-feed-side-effect.ts +218 -15
- package/src/notifications/types.ts +5 -0
- package/src/permissions/AGENTS.md +16 -0
- package/src/permissions/checker.test.ts +75 -122
- package/src/permissions/checker.ts +44 -560
- package/src/permissions/confirmation-guardian-request.test.ts +28 -3
- package/src/permissions/confirmation-guardian-request.ts +5 -1
- package/src/persistence/conversation-crud.ts +23 -20
- package/src/persistence/conversation-queries.ts +14 -1
- package/src/persistence/conversation-types.ts +22 -0
- package/src/persistence/delivery-crud.ts +122 -15
- package/src/plugin-api/__tests__/import-graph-partial-mock.test.ts +67 -0
- package/src/plugin-api/conversation-turn.ts +27 -0
- package/src/plugin-api/credential-scope.test.ts +15 -0
- package/src/plugin-api/credential-scope.ts +14 -0
- package/src/plugin-api/index.ts +19 -1
- package/src/plugin-api/resolve-credential.ts +15 -10
- package/src/plugin-api/store-credential.ts +148 -0
- package/src/plugin-api/system-card.ts +36 -0
- package/src/plugin-api/vision-support.test.ts +82 -0
- package/src/plugin-api/vision-support.ts +14 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +361 -110
- package/src/plugins/defaults/image-fallback/__tests__/vision-recovery.test.ts +4 -0
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +58 -0
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +64 -23
- package/src/plugins/defaults/image-recovery/detect.ts +24 -1
- package/src/plugins/defaults/main.ts +15 -0
- package/src/plugins/defaults/memory/AGENTS.md +11 -3
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +9 -12
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +114 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
- package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
- package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
- package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
- package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
- package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +1 -61
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +68 -6
- package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
- package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
- package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
- package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
- package/src/plugins/defaults/memory/substrate/static-context.ts +0 -29
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +3 -1
- package/src/plugins/defaults/memory/v3/card.ts +9 -9
- package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
- package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
- package/src/plugins/defaults/memory/v3/edge.ts +13 -57
- package/src/plugins/mtime-cache.ts +1 -1
- package/src/plugins/pipeline.ts +14 -7
- package/src/plugins/plugin-execution-context.ts +35 -11
- package/src/plugins/plugin-tree-walk.ts +63 -4
- package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
- package/src/providers/anthropic/client.ts +332 -241
- package/src/providers/connection-resolution.ts +2 -1
- package/src/providers/content-blocks.ts +22 -0
- package/src/providers/gemini/client.ts +5 -2
- package/src/providers/inference/__tests__/adapter-factory-litellm.test.ts +47 -1
- package/src/providers/inference/__tests__/adapter-factory-ollama.test.ts +83 -0
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +98 -1
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +38 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +10 -0
- package/src/providers/inference/__tests__/connections-ollama.test.ts +90 -0
- package/src/providers/inference/__tests__/missing-credential-guard.test.ts +117 -0
- package/src/providers/inference/adapter-factory.ts +33 -2
- package/src/providers/inference/auth.ts +13 -2
- package/src/providers/inference/credential-usage.ts +37 -0
- package/src/providers/inference/missing-credential-guard.ts +110 -0
- package/src/providers/inference/resolve-auth.ts +7 -7
- package/src/providers/media-resolve.ts +176 -15
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +576 -46
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
- package/src/providers/openai/chat-completions-provider.ts +322 -42
- package/src/routes/route-host-protocol.ts +7 -0
- package/src/routes/worker.ts +31 -10
- package/src/runtime/AGENTS.md +35 -0
- package/src/runtime/__tests__/runtime-http-port-collision.test.ts +131 -0
- package/src/runtime/__tests__/web-presence.test.ts +234 -0
- package/src/runtime/assistant-event-hub.ts +38 -0
- package/src/runtime/channel-reply-delivery.ts +54 -31
- package/src/runtime/channel-retry-sweep.ts +6 -4
- package/src/runtime/effective-capabilities.test.ts +19 -0
- package/src/runtime/effective-capabilities.ts +25 -0
- package/src/runtime/guardian-reply-router.ts +6 -2
- package/src/runtime/http-errors.ts +1 -0
- package/src/runtime/http-server.ts +20 -5
- package/src/runtime/routes/__tests__/client-routes.test.ts +150 -0
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +133 -0
- package/src/runtime/routes/__tests__/credential-delete-in-use.test.ts +155 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +52 -1
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/pending-interactions-route.test.ts +175 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +88 -35
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
- package/src/runtime/routes/__tests__/system-card-turn-termination.test.ts +107 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +75 -4
- package/src/runtime/routes/approval-routes.ts +37 -4
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +16 -22
- package/src/runtime/routes/canned-message-complete.ts +68 -29
- package/src/runtime/routes/client-routes.ts +113 -0
- package/src/runtime/routes/conversation-list-routes.ts +22 -7
- package/src/runtime/routes/conversation-management-routes.ts +15 -9
- package/src/runtime/routes/conversation-routes.ts +36 -22
- package/src/runtime/routes/credential-in-use.ts +85 -0
- package/src/runtime/routes/credential-routes.ts +55 -85
- package/src/runtime/routes/guardian-approval-interception.ts +22 -22
- package/src/runtime/routes/guardian-approval-reply-helpers.ts +14 -12
- package/src/runtime/routes/identity-routes.ts +5 -121
- package/src/runtime/routes/inbound-message-handler.ts +71 -27
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +16 -17
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +77 -50
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -97
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -77
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +17 -8
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -7
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -70
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +9 -7
- package/src/runtime/routes/monitoring-routes.ts +9 -1
- package/src/runtime/routes/plugins-routes.ts +17 -5
- package/src/runtime/routes/resource-pressure-routes.ts +22 -0
- package/src/runtime/routes/secret-routes.ts +39 -8
- package/src/runtime/routes/settings-routes.ts +6 -6
- package/src/runtime/routes/surface-action-routes.ts +20 -19
- package/src/runtime/routes/user-route-dispatcher.ts +31 -2
- package/src/runtime/routes/user-route-resolution.ts +18 -1
- package/src/runtime/slack-reply-session.test.ts +23 -13
- package/src/runtime/slack-reply-session.ts +38 -55
- package/src/runtime/web-presence.ts +90 -0
- package/src/skills/validate-input.ts +177 -40
- package/src/subagent/__tests__/consult-context-gating.test.ts +6 -10
- package/src/subagent/consult-context.ts +7 -23
- package/src/tools/credentials/broker.ts +24 -79
- package/src/tools/credentials/ref-parse.ts +35 -0
- package/src/tools/credentials/resolve.ts +4 -10
- package/src/tools/credentials/store.ts +168 -0
- package/src/tools/credentials/tool-policy.ts +67 -0
- package/src/tools/executor.ts +53 -15
- package/src/tools/network/__tests__/web-search.test.ts +41 -1
- package/src/tools/network/url-safety.ts +9 -16
- package/src/tools/network/web-search.ts +21 -3
- package/src/tools/permission-checker.ts +43 -52
- package/src/tools/schema-transforms.ts +40 -5
- package/src/tools/shared/input-repairs.ts +160 -0
- package/src/tools/skills/skill-tool-factory.ts +18 -4
- package/src/tools/subagent/spawn.ts +0 -1
- package/src/tools/tool-approval-handler.ts +16 -10
- package/src/tools/tool-types.ts +26 -13
- package/src/tools/types.ts +6 -6
- package/src/util/__tests__/cgroup-memory.test.ts +3 -0
- package/src/util/cgroup-memory.ts +3 -0
- package/src/util/container-cpu-sampler.ts +250 -0
- package/src/util/image-conversion.ts +178 -14
- package/src/util/platform.ts +93 -10
- package/src/permissions/ipc-risk-types.ts +0 -143
- package/src/permissions/risk-types.ts +0 -76
|
@@ -171,9 +171,9 @@ mock.module("../tools/network/url-safety.js", () => ({
|
|
|
171
171
|
// ── ipcClassifyRisk mock ─────────────────────────────────────────────────────
|
|
172
172
|
// This is the core mock — all classification goes through this.
|
|
173
173
|
|
|
174
|
-
import type {
|
|
174
|
+
import type { ClassifyRiskIpcResponse } from "@vellumai/gateway-client";
|
|
175
175
|
|
|
176
|
-
let mockIpcClassifyRiskResult:
|
|
176
|
+
let mockIpcClassifyRiskResult: ClassifyRiskIpcResponse | undefined;
|
|
177
177
|
let lastClassifyRiskParams: Record<string, unknown> | undefined;
|
|
178
178
|
|
|
179
179
|
mock.module("../ipc/gateway-client.js", () => ({
|
|
@@ -204,9 +204,7 @@ import type { Tool, ToolContext } from "../tools/types.js";
|
|
|
204
204
|
import {
|
|
205
205
|
check,
|
|
206
206
|
classifyRisk,
|
|
207
|
-
generateAllowlistOptions,
|
|
208
207
|
generateScopeOptions,
|
|
209
|
-
getCachedAssessment,
|
|
210
208
|
isInstalledStaticSkillLoad,
|
|
211
209
|
} from "./checker.js";
|
|
212
210
|
import { RiskLevel } from "./types.js";
|
|
@@ -352,36 +350,9 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
352
350
|
expect(lastClassifyRiskParams?.resolvedWorkingDir).toBeUndefined();
|
|
353
351
|
});
|
|
354
352
|
|
|
355
|
-
test("
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
reason: "Cached test",
|
|
359
|
-
matchType: "registry",
|
|
360
|
-
scopeOptions: [],
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
// First call
|
|
364
|
-
const result1 = await classifyRisk("file_read", { path: "/tmp/a.txt" });
|
|
365
|
-
expect(result1.level).toBe(RiskLevel.Low);
|
|
366
|
-
|
|
367
|
-
// Change the mock to verify cache is used
|
|
368
|
-
mockIpcClassifyRiskResult = {
|
|
369
|
-
risk: "high",
|
|
370
|
-
reason: "Should not see this",
|
|
371
|
-
matchType: "registry",
|
|
372
|
-
scopeOptions: [],
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
// Second call with same inputs should return cached result
|
|
376
|
-
const result2 = await classifyRisk("file_read", { path: "/tmp/a.txt" });
|
|
377
|
-
expect(result2.level).toBe(RiskLevel.Low);
|
|
378
|
-
expect(result2.reason).toBe("Cached test");
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
test("file-tool cache misses when a symlink target is retargeted", async () => {
|
|
382
|
-
// File risk depends on filesystem state: the cache key folds in the
|
|
383
|
-
// symlink-resolved target, so the same raw input must NOT return a stale
|
|
384
|
-
// cached result after the symlink is pointed somewhere new.
|
|
353
|
+
test("a retargeted symlink is reflected on the next classification of the same raw input", async () => {
|
|
354
|
+
// File risk depends on filesystem state; nothing in the daemon memoises
|
|
355
|
+
// a classification, so re-pointing the symlink changes the answer.
|
|
385
356
|
const dir = mkdtempSync(join(tmpdir(), "risk-cache-symlink-"));
|
|
386
357
|
try {
|
|
387
358
|
const benign = join(dir, "benign.txt");
|
|
@@ -411,7 +382,7 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
411
382
|
scopeOptions: [],
|
|
412
383
|
};
|
|
413
384
|
const second = await classifyRisk("file_read", { path: link });
|
|
414
|
-
//
|
|
385
|
+
// Re-classified against the new target.
|
|
415
386
|
expect(second.level).toBe(RiskLevel.High);
|
|
416
387
|
expect(second.reason).toBe("now sensitive");
|
|
417
388
|
} finally {
|
|
@@ -427,12 +398,8 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
427
398
|
scopeOptions: [],
|
|
428
399
|
commandCandidates: ["ls -la", "action:ls"],
|
|
429
400
|
};
|
|
430
|
-
// Use unique command to avoid cache hits from other tests
|
|
431
401
|
const result = await classifyRisk("bash", { command: "ls -la" });
|
|
432
|
-
expect(
|
|
433
|
-
"ls -la",
|
|
434
|
-
"action:ls",
|
|
435
|
-
]);
|
|
402
|
+
expect(result.commandCandidates).toEqual(["ls -la", "action:ls"]);
|
|
436
403
|
});
|
|
437
404
|
|
|
438
405
|
test("preserves sandboxAutoApprove from gateway response", async () => {
|
|
@@ -443,9 +410,8 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
443
410
|
scopeOptions: [],
|
|
444
411
|
sandboxAutoApprove: true,
|
|
445
412
|
};
|
|
446
|
-
// Use unique command to avoid cache hits
|
|
447
413
|
const result = await classifyRisk("bash", { command: "pwd" });
|
|
448
|
-
expect(
|
|
414
|
+
expect(result.sandboxAutoApprove).toBe(true);
|
|
449
415
|
});
|
|
450
416
|
|
|
451
417
|
test("overrides sandboxAutoApprove when symlink escape detected", async () => {
|
|
@@ -461,7 +427,7 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
461
427
|
const result = await classifyRisk("bash", {
|
|
462
428
|
command: "cat /workspace/escape/passwd",
|
|
463
429
|
});
|
|
464
|
-
expect(
|
|
430
|
+
expect(result.sandboxAutoApprove).toBe(false);
|
|
465
431
|
mockIsPathWithinWorkspaceRoot = true;
|
|
466
432
|
});
|
|
467
433
|
|
|
@@ -478,7 +444,7 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
478
444
|
const result = await classifyRisk("bash", {
|
|
479
445
|
command: "cat /workspace/file.txt",
|
|
480
446
|
});
|
|
481
|
-
expect(
|
|
447
|
+
expect(result.sandboxAutoApprove).toBe(true);
|
|
482
448
|
});
|
|
483
449
|
|
|
484
450
|
test("overrides sandboxAutoApprove when any path arg escapes", async () => {
|
|
@@ -494,7 +460,7 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
494
460
|
const result = await classifyRisk("bash", {
|
|
495
461
|
command: "cat /workspace/safe.txt && cat /workspace/escape/passwd",
|
|
496
462
|
});
|
|
497
|
-
expect(
|
|
463
|
+
expect(result.sandboxAutoApprove).toBe(false);
|
|
498
464
|
mockIsPathWithinWorkspaceRoot = true;
|
|
499
465
|
});
|
|
500
466
|
|
|
@@ -509,11 +475,11 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
509
475
|
// No sandboxPathArgs — e.g. older gateway that doesn't send them
|
|
510
476
|
};
|
|
511
477
|
const result = await classifyRisk("bash", { command: "ls" });
|
|
512
|
-
expect(
|
|
478
|
+
expect(result.sandboxAutoApprove).toBe(true);
|
|
513
479
|
mockIsPathWithinWorkspaceRoot = true;
|
|
514
480
|
});
|
|
515
481
|
|
|
516
|
-
test("
|
|
482
|
+
test("the symlink escape check runs on every classification, so a retargeted symlink revokes sandbox auto-approve", async () => {
|
|
517
483
|
// First call: path args within workspace → sandboxAutoApprove true.
|
|
518
484
|
mockIsPathWithinWorkspaceRoot = true;
|
|
519
485
|
mockIpcClassifyRiskResult = {
|
|
@@ -527,16 +493,15 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
527
493
|
const first = await classifyRisk("bash", {
|
|
528
494
|
command: "cat /workspace/escape/secret42.bin",
|
|
529
495
|
});
|
|
530
|
-
expect(
|
|
496
|
+
expect(first.sandboxAutoApprove).toBe(true);
|
|
531
497
|
|
|
532
|
-
// Second call with the same command:
|
|
533
|
-
//
|
|
534
|
-
// and override sandboxAutoApprove to false.
|
|
498
|
+
// Second call with the same command: the symlink now resolves outside
|
|
499
|
+
// the workspace, so sandboxAutoApprove is revoked.
|
|
535
500
|
mockIsPathWithinWorkspaceRoot = false;
|
|
536
501
|
const second = await classifyRisk("bash", {
|
|
537
502
|
command: "cat /workspace/escape/secret42.bin",
|
|
538
503
|
});
|
|
539
|
-
expect(
|
|
504
|
+
expect(second.sandboxAutoApprove).toBe(false);
|
|
540
505
|
mockIsPathWithinWorkspaceRoot = true;
|
|
541
506
|
});
|
|
542
507
|
|
|
@@ -556,9 +521,8 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
556
521
|
scopeOptions: [],
|
|
557
522
|
allowlistOptions: mockOptions,
|
|
558
523
|
};
|
|
559
|
-
// Use unique command to avoid cache hits
|
|
560
524
|
const result = await classifyRisk("bash", { command: "date" });
|
|
561
|
-
expect(
|
|
525
|
+
expect(result.allowlistOptions).toEqual(mockOptions);
|
|
562
526
|
});
|
|
563
527
|
});
|
|
564
528
|
|
|
@@ -1215,10 +1179,10 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
1215
1179
|
});
|
|
1216
1180
|
});
|
|
1217
1181
|
|
|
1218
|
-
// ──
|
|
1182
|
+
// ── allowlist ladder ──────────────────────────────────────────────────────
|
|
1219
1183
|
|
|
1220
|
-
describe("
|
|
1221
|
-
test("
|
|
1184
|
+
describe("allowlist ladder", () => {
|
|
1185
|
+
test("is the gateway's, carried through unchanged", async () => {
|
|
1222
1186
|
const mockOptions = [
|
|
1223
1187
|
{ label: "wc -l", description: "Exact command", pattern: "wc -l" },
|
|
1224
1188
|
{
|
|
@@ -1235,37 +1199,27 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
1235
1199
|
allowlistOptions: mockOptions,
|
|
1236
1200
|
};
|
|
1237
1201
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
// Then generate options should use cached assessment
|
|
1242
|
-
const options = await generateAllowlistOptions("bash", {
|
|
1243
|
-
command: "wc -l",
|
|
1244
|
-
});
|
|
1245
|
-
expect(options).toEqual(mockOptions);
|
|
1202
|
+
const classification = await classifyRisk("bash", { command: "wc -l" });
|
|
1203
|
+
expect(classification.allowlistOptions).toEqual(mockOptions);
|
|
1246
1204
|
});
|
|
1247
1205
|
|
|
1248
|
-
test("
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
});
|
|
1206
|
+
test("is absent when the classifier produced none", async () => {
|
|
1207
|
+
mockIpcClassifyRiskResult = {
|
|
1208
|
+
risk: "low",
|
|
1209
|
+
reason: "no ladder",
|
|
1210
|
+
matchType: "registry",
|
|
1211
|
+
scopeOptions: [],
|
|
1212
|
+
};
|
|
1256
1213
|
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
expect(options).toEqual([
|
|
1260
|
-
{ label: "*", description: "Everything", pattern: "*" },
|
|
1261
|
-
]);
|
|
1214
|
+
const classification = await classifyRisk("custom_tool", {});
|
|
1215
|
+
expect(classification.allowlistOptions).toBeUndefined();
|
|
1262
1216
|
});
|
|
1263
1217
|
});
|
|
1264
1218
|
|
|
1265
|
-
// ──
|
|
1219
|
+
// ── classifyRisk carries the gateway's assessment fields ──────────────────
|
|
1266
1220
|
|
|
1267
|
-
describe("
|
|
1268
|
-
test("
|
|
1221
|
+
describe("classifyRisk assessment fields", () => {
|
|
1222
|
+
test("carries reason, matchType and allowlistOptions from the gateway result", async () => {
|
|
1269
1223
|
mockIpcClassifyRiskResult = {
|
|
1270
1224
|
risk: "low",
|
|
1271
1225
|
reason: "Test assessment",
|
|
@@ -1276,21 +1230,37 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
1276
1230
|
],
|
|
1277
1231
|
};
|
|
1278
1232
|
|
|
1279
|
-
await classifyRisk("bash", {
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
expect(
|
|
1283
|
-
expect(
|
|
1284
|
-
expect(
|
|
1285
|
-
expect(
|
|
1233
|
+
const classification = await classifyRisk("bash", {
|
|
1234
|
+
command: "echo test",
|
|
1235
|
+
});
|
|
1236
|
+
expect(classification.level).toBe(RiskLevel.Low);
|
|
1237
|
+
expect(classification.reason).toBe("Test assessment");
|
|
1238
|
+
expect(classification.matchType).toBe("registry");
|
|
1239
|
+
expect(classification.allowlistOptions).toHaveLength(1);
|
|
1286
1240
|
});
|
|
1287
1241
|
|
|
1288
|
-
test("
|
|
1289
|
-
|
|
1290
|
-
|
|
1242
|
+
test("is not memoised: a changed gateway answer for the same input is returned", async () => {
|
|
1243
|
+
mockIpcClassifyRiskResult = {
|
|
1244
|
+
risk: "low",
|
|
1245
|
+
reason: "before the rule",
|
|
1246
|
+
matchType: "registry",
|
|
1247
|
+
scopeOptions: [],
|
|
1248
|
+
};
|
|
1249
|
+
const before = await classifyRisk("bash", { command: "curl example" });
|
|
1250
|
+
expect(before.level).toBe(RiskLevel.Low);
|
|
1251
|
+
|
|
1252
|
+
mockIpcClassifyRiskResult = {
|
|
1253
|
+
risk: "high",
|
|
1254
|
+
reason: "after the rule",
|
|
1255
|
+
matchType: "user_rule",
|
|
1256
|
+
scopeOptions: [],
|
|
1257
|
+
};
|
|
1258
|
+
const after = await classifyRisk("bash", { command: "curl example" });
|
|
1259
|
+
expect(after.level).toBe(RiskLevel.High);
|
|
1260
|
+
expect(after.matchType).toBe("user_rule");
|
|
1291
1261
|
});
|
|
1292
1262
|
|
|
1293
|
-
test("preserves scopeOptions from gateway result
|
|
1263
|
+
test("preserves scopeOptions from the gateway result", async () => {
|
|
1294
1264
|
mockIpcClassifyRiskResult = {
|
|
1295
1265
|
risk: "low",
|
|
1296
1266
|
reason: "Registry match",
|
|
@@ -1302,22 +1272,16 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
1302
1272
|
allowlistOptions: [],
|
|
1303
1273
|
};
|
|
1304
1274
|
|
|
1305
|
-
await classifyRisk("bash", {
|
|
1306
|
-
|
|
1307
|
-
const assessment = getCachedAssessment("bash", { command: "echo hello" });
|
|
1308
|
-
expect(assessment).toBeDefined();
|
|
1309
|
-
expect(assessment!.scopeOptions).toHaveLength(2);
|
|
1310
|
-
expect(assessment!.scopeOptions[0]).toEqual({
|
|
1311
|
-
pattern: "echo *",
|
|
1312
|
-
label: "only 'echo' commands",
|
|
1313
|
-
});
|
|
1314
|
-
expect(assessment!.scopeOptions[1]).toEqual({
|
|
1315
|
-
pattern: ".*",
|
|
1316
|
-
label: "everywhere",
|
|
1275
|
+
const classification = await classifyRisk("bash", {
|
|
1276
|
+
command: "echo hello",
|
|
1317
1277
|
});
|
|
1278
|
+
expect(classification.scopeOptions).toEqual([
|
|
1279
|
+
{ pattern: "echo *", label: "only 'echo' commands" },
|
|
1280
|
+
{ pattern: ".*", label: "everywhere" },
|
|
1281
|
+
]);
|
|
1318
1282
|
});
|
|
1319
1283
|
|
|
1320
|
-
test("preserves directoryScopeOptions from gateway result
|
|
1284
|
+
test("preserves directoryScopeOptions from the gateway result", async () => {
|
|
1321
1285
|
mockIpcClassifyRiskResult = {
|
|
1322
1286
|
risk: "medium",
|
|
1323
1287
|
reason: "Filesystem write",
|
|
@@ -1331,25 +1295,14 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
1331
1295
|
],
|
|
1332
1296
|
};
|
|
1333
1297
|
|
|
1334
|
-
await classifyRisk("file_write", {
|
|
1335
|
-
|
|
1336
|
-
const assessment = getCachedAssessment("file_write", {
|
|
1298
|
+
const classification = await classifyRisk("file_write", {
|
|
1337
1299
|
path: "/workspace/scratch/out.txt",
|
|
1338
1300
|
});
|
|
1339
|
-
expect(
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
scope: "
|
|
1343
|
-
|
|
1344
|
-
});
|
|
1345
|
-
expect(assessment!.directoryScopeOptions![1]).toEqual({
|
|
1346
|
-
scope: "/workspace/*",
|
|
1347
|
-
label: "In workspace/",
|
|
1348
|
-
});
|
|
1349
|
-
expect(assessment!.directoryScopeOptions![2]).toEqual({
|
|
1350
|
-
scope: "everywhere",
|
|
1351
|
-
label: "everywhere",
|
|
1352
|
-
});
|
|
1301
|
+
expect(classification.directoryScopeOptions).toEqual([
|
|
1302
|
+
{ scope: "/workspace/scratch/*", label: "In scratch/" },
|
|
1303
|
+
{ scope: "/workspace/*", label: "In workspace/" },
|
|
1304
|
+
{ scope: "everywhere", label: "everywhere" },
|
|
1305
|
+
]);
|
|
1353
1306
|
});
|
|
1354
1307
|
});
|
|
1355
1308
|
|