@vellumai/assistant 0.7.2 → 0.8.0
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/ARCHITECTURE.md +45 -29
- package/Dockerfile +1 -0
- package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
- package/bun.lock +3 -0
- package/docs/architecture/memory.md +5 -2
- package/knip.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
- package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
- package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
- package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -9
- package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
- package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
- package/openapi.yaml +470 -25
- package/package.json +3 -1
- package/src/__tests__/annotate-risk-options.test.ts +291 -0
- package/src/__tests__/app-control-flow.test.ts +21 -11
- package/src/__tests__/approval-cascade.test.ts +8 -16
- package/src/__tests__/approval-routes-http.test.ts +6 -0
- package/src/__tests__/assistant-event-hub.test.ts +48 -0
- package/src/__tests__/assistant-event.test.ts +0 -10
- package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -7
- package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +48 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
- package/src/__tests__/call-constants.test.ts +10 -1
- package/src/__tests__/call-controller.test.ts +127 -0
- package/src/__tests__/call-conversation-messages.test.ts +8 -2
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
- package/src/__tests__/channel-readiness-service.test.ts +4 -2
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +58 -28
- package/src/__tests__/config-loader-backfill.test.ts +379 -0
- package/src/__tests__/config-loader-platform-defaults.test.ts +284 -1
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +18 -9
- package/src/__tests__/config-watcher.test.ts +140 -69
- package/src/__tests__/context-search-agent-runner.test.ts +61 -3
- package/src/__tests__/context-search-conversations-source.test.ts +0 -24
- package/src/__tests__/context-search-fanout.test.ts +0 -1
- package/src/__tests__/context-search-memory-source.test.ts +6 -33
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
- package/src/__tests__/context-search-pkb-source.test.ts +12 -7
- package/src/__tests__/context-search-workspace-source.test.ts +0 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop.test.ts +457 -8
- package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
- package/src/__tests__/conversation-error.test.ts +150 -3
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
- package/src/__tests__/conversation-process-callsite.test.ts +38 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +74 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-store.test.ts +0 -18
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
- package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +476 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +61 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/credentials-cli.test.ts +7 -0
- package/src/__tests__/cu-unified-flow.test.ts +176 -10
- package/src/__tests__/date-context.test.ts +164 -2
- package/src/__tests__/disk-pressure-guard.test.ts +262 -0
- package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
- package/src/__tests__/disk-pressure-policy.test.ts +241 -0
- package/src/__tests__/disk-pressure-routes.test.ts +379 -0
- package/src/__tests__/disk-pressure-tools.test.ts +277 -0
- package/src/__tests__/disk-usage.test.ts +150 -0
- package/src/__tests__/events-client-registration.test.ts +52 -0
- package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
- package/src/__tests__/file-write-tool.test.ts +4 -10
- package/src/__tests__/filing-service.test.ts +2 -20
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -26
- package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
- package/src/__tests__/heartbeat-service.test.ts +260 -11
- package/src/__tests__/host-app-control-proxy.test.ts +195 -25
- package/src/__tests__/host-bash-proxy.test.ts +227 -34
- package/src/__tests__/host-bash-routes.test.ts +178 -13
- package/src/__tests__/host-cu-proxy.test.ts +210 -3
- package/src/__tests__/host-cu-routes-targeted.test.ts +141 -12
- package/src/__tests__/host-file-proxy-targeted.test.ts +48 -9
- package/src/__tests__/host-file-proxy.test.ts +268 -6
- package/src/__tests__/host-file-routes-targeted.test.ts +175 -17
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +408 -59
- package/src/__tests__/host-transfer-routes-targeted.test.ts +232 -17
- package/src/__tests__/http-user-message-parity.test.ts +107 -1
- package/src/__tests__/injector-chain.test.ts +36 -16
- package/src/__tests__/injector-disk-pressure.test.ts +224 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +154 -67
- package/src/__tests__/managed-profile-guard.test.ts +18 -0
- package/src/__tests__/mcp-abort-signal.test.ts +130 -0
- package/src/__tests__/memory-admin-recall.test.ts +3 -11
- package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
- package/src/__tests__/normalize-onboarding.test.ts +180 -0
- package/src/__tests__/notification-decision-fallback.test.ts +91 -0
- package/src/__tests__/notification-decision-strategy.test.ts +22 -0
- package/src/__tests__/oauth-cli.test.ts +121 -0
- package/src/__tests__/oauth-connect-routes.test.ts +316 -0
- package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
- package/src/__tests__/onboarding-persona-write.test.ts +308 -0
- package/src/__tests__/openai-provider.test.ts +45 -8
- package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
- package/src/__tests__/platform-callback-registration.test.ts +21 -4
- package/src/__tests__/platform.test.ts +2 -1
- package/src/__tests__/playbook-execution.test.ts +0 -43
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +214 -27
- package/src/__tests__/provider-tool-name.test.ts +23 -0
- package/src/__tests__/relay-server.test.ts +60 -5
- package/src/__tests__/runtime-events-sse.test.ts +4 -8
- package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
- package/src/__tests__/secret-ingress-http.test.ts +0 -1
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
- package/src/__tests__/secret-response-routing.test.ts +7 -5
- package/src/__tests__/server-history-render.test.ts +82 -0
- package/src/__tests__/skill-include-graph.test.ts +31 -0
- package/src/__tests__/skill-load-tool.test.ts +44 -16
- package/src/__tests__/skills.test.ts +39 -0
- package/src/__tests__/suggestion-routes.test.ts +46 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
- package/src/__tests__/tool-executor.test.ts +155 -0
- package/src/__tests__/twilio-validation.test.ts +2 -2
- package/src/__tests__/voice-session-bridge.test.ts +3 -0
- package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
- package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
- package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +120 -0
- package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
- package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +78 -0
- package/src/agent/loop.ts +11 -0
- package/src/approvals/guardian-request-resolvers.ts +3 -32
- package/src/backup/snapshot-lock.ts +2 -27
- package/src/bundler/compiler-tools.ts +3 -2
- package/src/calls/call-constants.ts +5 -8
- package/src/calls/call-controller.ts +130 -67
- package/src/calls/call-conversation-messages.ts +46 -10
- package/src/calls/relay-server.ts +7 -1
- package/src/calls/voice-session-bridge.ts +1 -1
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -4
- package/src/cli/commands/bash.ts +35 -108
- package/src/cli/commands/contacts.ts +64 -25
- package/src/cli/commands/credentials.ts +56 -0
- package/src/cli/commands/memory-v2.ts +11 -10
- package/src/cli/commands/oauth/__tests__/connect.test.ts +401 -219
- package/src/cli/commands/oauth/connect.ts +124 -40
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +103 -6
- package/src/cli/commands/platform/index.ts +16 -7
- package/src/cli/commands/status.ts +57 -0
- package/src/cli/program.ts +4 -2
- package/src/config/assistant-feature-flags.ts +13 -3
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +13 -7
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
- package/src/config/env.ts +0 -8
- package/src/config/feature-flag-registry.json +13 -5
- package/src/config/loader.ts +199 -27
- package/src/config/schemas/__tests__/memory-v2.test.ts +10 -5
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/channels.ts +0 -5
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +2 -0
- package/src/config/schemas/memory-lifecycle.ts +13 -0
- package/src/config/schemas/memory-v2.ts +76 -12
- package/src/config/schemas/platform.ts +43 -3
- package/src/config/schemas/services.ts +28 -0
- package/src/config/seed-inference-profiles.ts +230 -33
- package/src/contacts/contact-store.ts +0 -25
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +32 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +86 -25
- package/src/daemon/assistant-attachments.ts +4 -4
- package/src/daemon/config-watcher.ts +85 -57
- package/src/daemon/conversation-agent-loop-handlers.ts +38 -0
- package/src/daemon/conversation-agent-loop.ts +183 -43
- package/src/daemon/conversation-error.ts +87 -15
- package/src/daemon/conversation-lifecycle.ts +22 -10
- package/src/daemon/conversation-process.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +26 -0
- package/src/daemon/conversation-store.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +211 -29
- package/src/daemon/conversation-tool-setup.ts +66 -19
- package/src/daemon/conversation.ts +18 -23
- package/src/daemon/date-context.ts +71 -22
- package/src/daemon/disk-pressure-background-gate.ts +73 -0
- package/src/daemon/disk-pressure-guard.ts +343 -0
- package/src/daemon/disk-pressure-policy.ts +163 -0
- package/src/daemon/handlers/shared.ts +26 -1
- package/src/daemon/handlers/skills.ts +3 -4
- package/src/daemon/host-app-control-proxy.ts +137 -41
- package/src/daemon/host-bash-proxy.ts +47 -22
- package/src/daemon/host-browser-proxy.ts +1 -1
- package/src/daemon/host-cu-proxy.ts +50 -4
- package/src/daemon/host-file-proxy.ts +44 -8
- package/src/daemon/host-transfer-proxy.ts +97 -6
- package/src/daemon/lifecycle.ts +167 -101
- package/src/daemon/meet-host-supervisor.ts +4 -4
- package/src/daemon/meet-manifest-loader.ts +0 -1
- package/src/daemon/memory-v2-startup.ts +66 -15
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/conversations.ts +4 -0
- package/src/daemon/message-types/disk-pressure.ts +9 -0
- package/src/daemon/message-types/messages.ts +22 -1
- package/src/daemon/profiler-run-store.ts +5 -5
- package/src/daemon/tool-setup-types.ts +2 -2
- package/src/documents/document-store.ts +119 -0
- package/src/filing/filing-service.ts +29 -5
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +9 -16
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +36 -0
- package/src/heartbeat/heartbeat-run-store.ts +13 -0
- package/src/heartbeat/heartbeat-service.ts +205 -31
- package/src/home/feed-scheduler.ts +18 -0
- package/src/inbound/platform-callback-registration.ts +8 -15
- package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
- package/src/ipc/assistant-server.ts +149 -38
- package/src/ipc/gateway-client.ts +37 -3
- package/src/ipc/skill-server.ts +99 -42
- package/src/live-voice/live-voice-archive.ts +4 -4
- package/src/live-voice/protocol.ts +5 -7
- package/src/media/image-service.ts +1 -7
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +34 -51
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
- package/src/memory/admin.ts +5 -9
- package/src/memory/context-search/agent-runner.ts +19 -2
- package/src/memory/context-search/sources/conversations.ts +2 -11
- package/src/memory/context-search/sources/memory-v2.ts +1 -16
- package/src/memory/context-search/sources/memory.ts +2 -3
- package/src/memory/context-search/sources/pkb.ts +2 -3
- package/src/memory/context-search/types.ts +0 -1
- package/src/memory/conversation-crud.ts +4 -12
- package/src/memory/db-init.ts +2 -0
- package/src/memory/embedding-runtime-manager.ts +119 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +136 -82
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
- package/src/memory/graph/conversation-graph-memory.ts +72 -61
- package/src/memory/graph/extraction.ts +1 -3
- package/src/memory/graph/graph-search.test.ts +11 -67
- package/src/memory/graph/graph-search.ts +4 -24
- package/src/memory/graph/retriever.test.ts +12 -1
- package/src/memory/graph/retriever.ts +10 -15
- package/src/memory/graph/tool-handlers.ts +3 -4
- package/src/memory/graph/tools.ts +4 -4
- package/src/memory/indexer.ts +53 -45
- package/src/memory/job-handlers/backfill.ts +2 -11
- package/src/memory/job-handlers/cleanup.ts +43 -0
- package/src/memory/job-handlers/embedding.ts +6 -8
- package/src/memory/job-handlers/summarization.ts +2 -7
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +116 -0
- package/src/memory/jobs/embed-concept-page.ts +223 -87
- package/src/memory/jobs-store.ts +48 -0
- package/src/memory/jobs-worker.ts +85 -43
- package/src/memory/memory-v2-activation-log-store.ts +32 -14
- package/src/memory/memory-v2-concept-frequency.ts +169 -0
- package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/pkb/pkb-search.test.ts +7 -0
- package/src/memory/pkb/pkb-search.ts +4 -5
- package/src/memory/qdrant-client.ts +3 -13
- package/src/memory/rerank-local.ts +374 -0
- package/src/memory/search/semantic.ts +10 -72
- package/src/memory/trace-event-store.ts +1 -17
- package/src/memory/v2/__tests__/activation.test.ts +346 -255
- package/src/memory/v2/__tests__/consolidation-job.test.ts +61 -40
- package/src/memory/v2/__tests__/injection.test.ts +297 -190
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
- package/src/memory/v2/__tests__/qdrant.test.ts +326 -9
- package/src/memory/v2/__tests__/reranker.test.ts +338 -0
- package/src/memory/v2/__tests__/sim.test.ts +113 -196
- package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
- package/src/memory/v2/__tests__/static-context.test.ts +77 -14
- package/src/memory/v2/__tests__/sweep-job.test.ts +19 -33
- package/src/memory/v2/activation.ts +149 -156
- package/src/memory/v2/consolidation-job.ts +69 -20
- package/src/memory/v2/injection.ts +75 -68
- package/src/memory/v2/page-store.ts +39 -0
- package/src/memory/v2/prompts/consolidation.ts +41 -1
- package/src/memory/v2/qdrant.ts +306 -46
- package/src/memory/v2/reranker.ts +177 -0
- package/src/memory/v2/sim.ts +77 -110
- package/src/memory/v2/skill-content.ts +4 -3
- package/src/memory/v2/skill-store.ts +82 -59
- package/src/memory/v2/static-context.ts +26 -8
- package/src/memory/v2/sweep-job.ts +5 -6
- package/src/memory/v2/types.ts +17 -10
- package/src/notifications/copy-composer.ts +47 -0
- package/src/notifications/decision-engine.ts +46 -0
- package/src/notifications/signal.ts +4 -0
- package/src/oauth/AGENTS.md +3 -1
- package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
- package/src/oauth/connect-orchestrator.ts +2 -0
- package/src/oauth/connection-resolver.test.ts +66 -1
- package/src/oauth/connection-resolver.ts +55 -1
- package/src/oauth/oauth-connect-state.ts +77 -0
- package/src/oauth/seed-providers.ts +58 -1
- package/src/permissions/gateway-threshold-reader.ts +116 -8
- package/src/permissions/prompter.ts +86 -96
- package/src/permissions/secret-prompter.ts +31 -31
- package/src/plugins/defaults/injectors.ts +36 -4
- package/src/plugins/defaults/memory-retrieval.ts +5 -6
- package/src/plugins/types.ts +7 -0
- package/src/proactive-artifact/aux-message-injector.ts +74 -0
- package/src/proactive-artifact/decision.test.ts +226 -0
- package/src/proactive-artifact/decision.ts +165 -0
- package/src/proactive-artifact/index.ts +7 -0
- package/src/proactive-artifact/job.test.ts +914 -0
- package/src/proactive-artifact/job.ts +366 -0
- package/src/proactive-artifact/message-copy.ts +58 -0
- package/src/proactive-artifact/trigger-state.test.ts +277 -0
- package/src/proactive-artifact/trigger-state.ts +119 -0
- package/src/prompts/normalize-onboarding.ts +80 -0
- package/src/prompts/persona-resolver.ts +101 -9
- package/src/prompts/system-prompt.ts +21 -7
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/SOUL.md +13 -28
- package/src/providers/__tests__/retry-callsite.test.ts +222 -1
- package/src/providers/model-intents.ts +7 -0
- package/src/providers/openrouter/client.ts +8 -0
- package/src/providers/retry.ts +50 -0
- package/src/providers/types.ts +1 -0
- package/src/runtime/__tests__/agent-wake.test.ts +456 -3
- package/src/runtime/agent-wake.ts +238 -100
- package/src/runtime/assistant-event-hub.ts +36 -6
- package/src/runtime/assistant-event.ts +0 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
- package/src/runtime/auth/route-policy.ts +15 -1
- package/src/runtime/auth/same-actor.ts +216 -0
- package/src/runtime/channel-approvals.ts +3 -2
- package/src/runtime/channel-retry-sweep.ts +65 -1
- package/src/runtime/local-actor-identity.ts +52 -11
- package/src/runtime/pending-interactions.ts +27 -15
- package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -5
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
- package/src/runtime/routes/approval-routes.ts +7 -3
- package/src/runtime/routes/client-routes.ts +20 -2
- package/src/runtime/routes/consolidation-routes.ts +8 -9
- package/src/runtime/routes/contact-routes.ts +0 -25
- package/src/runtime/routes/conversation-query-routes.ts +44 -1
- package/src/runtime/routes/conversation-routes.ts +35 -26
- package/src/runtime/routes/debug-bash-routes.ts +165 -0
- package/src/runtime/routes/disk-pressure-routes.ts +121 -0
- package/src/runtime/routes/document-pdf-renderer.ts +6 -2
- package/src/runtime/routes/documents-routes.ts +2 -75
- package/src/runtime/routes/events-routes.ts +41 -9
- package/src/runtime/routes/filing-routes.ts +2 -3
- package/src/runtime/routes/host-bash-routes.ts +23 -3
- package/src/runtime/routes/host-cu-routes.ts +33 -6
- package/src/runtime/routes/host-file-routes.ts +32 -6
- package/src/runtime/routes/host-transfer-routes.ts +79 -16
- package/src/runtime/routes/identity-routes.ts +7 -138
- package/src/runtime/routes/inbound-message-handler.ts +77 -12
- package/src/runtime/routes/index.ts +6 -0
- package/src/runtime/routes/memory-item-routes.test.ts +37 -17
- package/src/runtime/routes/memory-item-routes.ts +5 -6
- package/src/runtime/routes/memory-v2-routes.ts +136 -17
- package/src/runtime/routes/oauth-connect-routes.ts +153 -0
- package/src/runtime/verification-outbound-actions.ts +4 -4
- package/src/schedule/run-script.ts +37 -5
- package/src/schedule/scheduler.ts +20 -1
- package/src/security/encrypted-store.ts +2 -0
- package/src/security/secure-keys.ts +55 -0
- package/src/skills/include-graph.ts +35 -13
- package/src/skills/remote-skill-policy.ts +4 -10
- package/src/subagent/index.ts +1 -7
- package/src/subagent/manager.ts +1 -15
- package/src/tasks/task-runner.ts +0 -1
- package/src/tasks/task-store.ts +0 -3
- package/src/tools/background-tool-registry.ts +17 -3
- package/src/tools/document/document-tool.ts +20 -0
- package/src/tools/executor.ts +18 -2
- package/src/tools/host-filesystem/edit.test.ts +151 -0
- package/src/tools/host-filesystem/edit.ts +43 -1
- package/src/tools/host-filesystem/read.test.ts +129 -0
- package/src/tools/host-filesystem/read.ts +43 -1
- package/src/tools/host-filesystem/transfer.test.ts +127 -2
- package/src/tools/host-filesystem/transfer.ts +56 -11
- package/src/tools/host-filesystem/write.test.ts +134 -0
- package/src/tools/host-filesystem/write.ts +43 -1
- package/src/tools/host-terminal/host-shell.ts +13 -6
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/register.test.ts +14 -9
- package/src/tools/memory/register.ts +1 -2
- package/src/tools/permission-checker.ts +15 -0
- package/src/tools/provider-tool-name.ts +28 -0
- package/src/tools/registry.ts +30 -9
- package/src/tools/skills/load.ts +24 -20
- package/src/tools/terminal/shell.ts +9 -1
- package/src/tools/tool-approval-handler.ts +31 -6
- package/src/tools/tool-name-aliases.ts +19 -0
- package/src/tools/types.ts +43 -3
- package/src/tts/provider-catalog.ts +3 -5
- package/src/util/disk-usage.ts +138 -0
- package/src/util/platform.ts +21 -11
- package/src/util/process-liveness.ts +26 -0
- package/src/workspace/heartbeat-service.ts +19 -0
- package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
- package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +14 -0
- package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +28 -0
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
- package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
- package/src/workspace/migrations/registry.ts +14 -0
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
- package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
- package/src/memory/v2/skill-qdrant.ts +0 -404
- package/src/signals/bash.ts +0 -198
|
@@ -179,9 +179,17 @@ class HostShellTool implements Tool {
|
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
181
|
const background = input.background === true;
|
|
182
|
+
if (background && context.diskPressureCleanupModeActive === true) {
|
|
183
|
+
return {
|
|
184
|
+
content:
|
|
185
|
+
"Error: background host shell commands are not available during disk pressure cleanup mode.",
|
|
186
|
+
isError: true,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
182
189
|
|
|
183
190
|
const targetClientId =
|
|
184
|
-
typeof input.target_client_id === "string" &&
|
|
191
|
+
typeof input.target_client_id === "string" &&
|
|
192
|
+
input.target_client_id !== ""
|
|
185
193
|
? input.target_client_id
|
|
186
194
|
: undefined;
|
|
187
195
|
|
|
@@ -236,10 +244,7 @@ class HostShellTool implements Tool {
|
|
|
236
244
|
// guard both targetClientId != null guards above are bypassed, and the
|
|
237
245
|
// code falls through to local daemon execution — silently running commands
|
|
238
246
|
// inside the Docker container instead of on the intended host machine.
|
|
239
|
-
if (
|
|
240
|
-
targetClientId != null &&
|
|
241
|
-
!HostBashProxy.instance.isAvailable()
|
|
242
|
-
) {
|
|
247
|
+
if (targetClientId != null && !HostBashProxy.instance.isAvailable()) {
|
|
243
248
|
return {
|
|
244
249
|
content: `Error: target client "${targetClientId}" is no longer connected. The specified client may have disconnected since the tool was called. Run \`assistant clients list --capability host_bash\` to see currently connected clients.`,
|
|
245
250
|
isError: true,
|
|
@@ -287,6 +292,7 @@ class HostShellTool implements Tool {
|
|
|
287
292
|
},
|
|
288
293
|
context.conversationId,
|
|
289
294
|
abortController.signal,
|
|
295
|
+
context.sourceActorPrincipalId,
|
|
290
296
|
);
|
|
291
297
|
|
|
292
298
|
proxyPromise
|
|
@@ -315,7 +321,7 @@ class HostShellTool implements Tool {
|
|
|
315
321
|
conversationId: context.conversationId,
|
|
316
322
|
command,
|
|
317
323
|
startedAt: Date.now(),
|
|
318
|
-
cancel: () => abortController.abort(),
|
|
324
|
+
cancel: (reason?: string) => abortController.abort(reason),
|
|
319
325
|
});
|
|
320
326
|
|
|
321
327
|
return {
|
|
@@ -334,6 +340,7 @@ class HostShellTool implements Tool {
|
|
|
334
340
|
},
|
|
335
341
|
context.conversationId,
|
|
336
342
|
context.signal,
|
|
343
|
+
context.sourceActorPrincipalId,
|
|
337
344
|
);
|
|
338
345
|
}
|
|
339
346
|
|
|
@@ -2,6 +2,7 @@ import type { McpServerConfig } from "../../config/schemas/mcp.js";
|
|
|
2
2
|
import type { McpServerManager } from "../../mcp/manager.js";
|
|
3
3
|
import { RiskLevel } from "../../permissions/types.js";
|
|
4
4
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
5
|
+
import { toProviderSafeToolName } from "../provider-tool-name.js";
|
|
5
6
|
import { schemaDefinesProperty } from "../schema-transforms.js";
|
|
6
7
|
import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
|
|
7
8
|
|
|
@@ -16,7 +17,7 @@ const riskMap: Record<string, RiskLevel> = {
|
|
|
16
17
|
* and with core/skill tools.
|
|
17
18
|
*/
|
|
18
19
|
function mcpToolName(serverId: string, toolName: string): string {
|
|
19
|
-
return `mcp__${serverId}__${toolName}
|
|
20
|
+
return toProviderSafeToolName(`mcp__${serverId}__${toolName}`);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export interface McpToolMetadata {
|
|
@@ -14,6 +14,14 @@ import {
|
|
|
14
14
|
import { PKB_WORKSPACE_SCOPE } from "../../memory/pkb/types.js";
|
|
15
15
|
import type { ToolContext } from "../types.js";
|
|
16
16
|
|
|
17
|
+
// This test exercises v1 PKB re-index enqueue. `config.memory.v2.enabled`
|
|
18
|
+
// (default `true`) makes the enqueue path skipped — force it off so the
|
|
19
|
+
// v1 PKB index path stays under test.
|
|
20
|
+
mock.module("../../config/loader.js", () => ({
|
|
21
|
+
getConfig: () => ({ memory: { v2: { enabled: false } } }),
|
|
22
|
+
loadConfig: () => ({ memory: { v2: { enabled: false } } }),
|
|
23
|
+
}));
|
|
24
|
+
|
|
17
25
|
let tmpWorkspace: string;
|
|
18
26
|
let previousWorkspaceEnv: string | undefined;
|
|
19
27
|
|
|
@@ -175,7 +183,7 @@ describe("recallTool.execute", () => {
|
|
|
175
183
|
max_results: 4,
|
|
176
184
|
depth: "deep",
|
|
177
185
|
},
|
|
178
|
-
makeContext(
|
|
186
|
+
makeContext(),
|
|
179
187
|
);
|
|
180
188
|
|
|
181
189
|
expect(result).toEqual({
|
|
@@ -196,7 +204,7 @@ describe("recallTool.execute", () => {
|
|
|
196
204
|
|
|
197
205
|
const result = await recallTool.execute(
|
|
198
206
|
{ query: "fallback search", sources: ["workspace"], depth: "fast" },
|
|
199
|
-
makeContext(
|
|
207
|
+
makeContext(),
|
|
200
208
|
);
|
|
201
209
|
|
|
202
210
|
expect(result).toEqual({
|
|
@@ -205,7 +213,7 @@ describe("recallTool.execute", () => {
|
|
|
205
213
|
});
|
|
206
214
|
});
|
|
207
215
|
|
|
208
|
-
test("propagates tool context
|
|
216
|
+
test("propagates tool context", async () => {
|
|
209
217
|
const controller = new AbortController();
|
|
210
218
|
|
|
211
219
|
await recallTool.execute(
|
|
@@ -221,7 +229,6 @@ describe("recallTool.execute", () => {
|
|
|
221
229
|
expect(recallCalls[0]?.context).toEqual({
|
|
222
230
|
workingDir: "/workspace/project",
|
|
223
231
|
conversationId: "conv-context",
|
|
224
|
-
memoryScopeId: "default",
|
|
225
232
|
config: getConfig(),
|
|
226
233
|
signal: controller.signal,
|
|
227
234
|
});
|
|
@@ -275,9 +282,7 @@ describe("rememberTool.execute — PKB re-index enqueue", () => {
|
|
|
275
282
|
test("enqueues re-index jobs for both buffer and daily archive paths", async () => {
|
|
276
283
|
const result = await rememberTool.execute(
|
|
277
284
|
{ content: "index me please" },
|
|
278
|
-
|
|
279
|
-
// enqueue ignores it and pins to PKB_WORKSPACE_SCOPE instead.
|
|
280
|
-
makeContext({ memoryScopeId: "scope-enqueue" }),
|
|
285
|
+
makeContext(),
|
|
281
286
|
);
|
|
282
287
|
expect(result.isError).toBe(false);
|
|
283
288
|
|
|
@@ -308,7 +313,7 @@ describe("rememberTool.execute — PKB re-index enqueue", () => {
|
|
|
308
313
|
test("does not enqueue when content is empty (write was skipped)", async () => {
|
|
309
314
|
const result = await rememberTool.execute(
|
|
310
315
|
{ content: " " },
|
|
311
|
-
makeContext(
|
|
316
|
+
makeContext(),
|
|
312
317
|
);
|
|
313
318
|
expect(result.isError).toBe(true);
|
|
314
319
|
expect(enqueueCalls).toHaveLength(0);
|
|
@@ -319,7 +324,7 @@ describe("rememberTool.execute — PKB re-index enqueue", () => {
|
|
|
319
324
|
|
|
320
325
|
const result = await rememberTool.execute(
|
|
321
326
|
{ content: "enqueue will throw" },
|
|
322
|
-
makeContext(
|
|
327
|
+
makeContext(),
|
|
323
328
|
);
|
|
324
329
|
|
|
325
330
|
// Remember call succeeded despite enqueue throwing for each write.
|
|
@@ -34,7 +34,7 @@ class RememberTool implements Tool {
|
|
|
34
34
|
const result = handleRemember(
|
|
35
35
|
typedInput,
|
|
36
36
|
context.conversationId,
|
|
37
|
-
|
|
37
|
+
"default",
|
|
38
38
|
getConfig(),
|
|
39
39
|
);
|
|
40
40
|
return {
|
|
@@ -73,7 +73,6 @@ class RecallTool implements Tool {
|
|
|
73
73
|
const result = await runAgenticRecall(input as unknown as RecallInput, {
|
|
74
74
|
workingDir: context.workingDir,
|
|
75
75
|
conversationId: context.conversationId,
|
|
76
|
-
memoryScopeId: context.memoryScopeId ?? "default",
|
|
77
76
|
config,
|
|
78
77
|
signal: context.signal,
|
|
79
78
|
});
|
|
@@ -32,6 +32,11 @@ export type PermissionDecision =
|
|
|
32
32
|
riskLevel: string;
|
|
33
33
|
riskReason: string;
|
|
34
34
|
riskScopeOptions: Array<{ pattern: string; label: string }>;
|
|
35
|
+
riskAllowlistOptions?: Array<{
|
|
36
|
+
label: string;
|
|
37
|
+
description: string;
|
|
38
|
+
pattern: string;
|
|
39
|
+
}>;
|
|
35
40
|
riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
|
|
36
41
|
isContainerized?: boolean;
|
|
37
42
|
};
|
|
@@ -51,6 +56,11 @@ export type PermissionDecision =
|
|
|
51
56
|
riskLevel: string;
|
|
52
57
|
riskReason: string;
|
|
53
58
|
riskScopeOptions: Array<{ pattern: string; label: string }>;
|
|
59
|
+
riskAllowlistOptions?: Array<{
|
|
60
|
+
label: string;
|
|
61
|
+
description: string;
|
|
62
|
+
pattern: string;
|
|
63
|
+
}>;
|
|
54
64
|
riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
|
|
55
65
|
isContainerized?: boolean;
|
|
56
66
|
};
|
|
@@ -111,7 +121,12 @@ export class PermissionChecker {
|
|
|
111
121
|
? {
|
|
112
122
|
riskLevel: cachedAssessment.riskLevel,
|
|
113
123
|
riskReason: cachedAssessment.reason,
|
|
124
|
+
// Display ladder (regex patterns — internal only, not for save).
|
|
114
125
|
riskScopeOptions: cachedAssessment.scopeOptions,
|
|
126
|
+
// Save ladder (Minimatch globs — what the gateway matches against).
|
|
127
|
+
// Populated for classifiers that produce allowlist options
|
|
128
|
+
// (bash, file, skill); undefined otherwise.
|
|
129
|
+
riskAllowlistOptions: cachedAssessment.allowlistOptions,
|
|
115
130
|
riskDirectoryScopeOptions: cachedAssessment.directoryScopeOptions,
|
|
116
131
|
isContainerized: getIsContainerized(),
|
|
117
132
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
const PROVIDER_TOOL_NAME_MAX_LENGTH = 64;
|
|
4
|
+
const PROVIDER_TOOL_NAME_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
5
|
+
const HASH_LENGTH = 12;
|
|
6
|
+
|
|
7
|
+
export function isProviderSafeToolName(name: string): boolean {
|
|
8
|
+
return PROVIDER_TOOL_NAME_RE.test(name);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function toProviderSafeToolName(rawName: string): string {
|
|
12
|
+
const trimmed = rawName.trim();
|
|
13
|
+
if (isProviderSafeToolName(rawName)) {
|
|
14
|
+
return rawName;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const hash = createHash("sha256")
|
|
18
|
+
.update(rawName)
|
|
19
|
+
.digest("hex")
|
|
20
|
+
.slice(0, HASH_LENGTH);
|
|
21
|
+
const suffix = `__${hash}`;
|
|
22
|
+
const maxBaseLength = PROVIDER_TOOL_NAME_MAX_LENGTH - suffix.length;
|
|
23
|
+
const sanitized =
|
|
24
|
+
trimmed.replace(/[^a-zA-Z0-9_-]+/g, "_").replace(/^_+|_+$/g, "") || "tool";
|
|
25
|
+
const base = sanitized.slice(0, maxBaseLength).replace(/_+$/g, "") || "tool";
|
|
26
|
+
|
|
27
|
+
return `${base}${suffix}`;
|
|
28
|
+
}
|
package/src/tools/registry.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { hostFileReadTool } from "./host-filesystem/read.js";
|
|
|
8
8
|
import { hostFileTransferTool } from "./host-filesystem/transfer.js";
|
|
9
9
|
import { hostFileWriteTool } from "./host-filesystem/write.js";
|
|
10
10
|
import { hostShellTool } from "./host-terminal/host-shell.js";
|
|
11
|
+
import { toProviderSafeToolName } from "./provider-tool-name.js";
|
|
11
12
|
import { registerSystemTools } from "./system/register.js";
|
|
12
13
|
import type { Tool } from "./types.js";
|
|
13
14
|
import { allUiSurfaceTools } from "./ui-surface/definitions.js";
|
|
@@ -75,6 +76,24 @@ const skillRefCount = new Map<string, number>();
|
|
|
75
76
|
// separate and covers the case of two extensions choosing the same tool name.
|
|
76
77
|
const pluginRefCount = new Map<string, number>();
|
|
77
78
|
|
|
79
|
+
function withProviderSafeToolName(tool: Tool): Tool {
|
|
80
|
+
const safeName = toProviderSafeToolName(tool.name);
|
|
81
|
+
if (safeName === tool.name) {
|
|
82
|
+
return tool;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
...tool,
|
|
87
|
+
name: safeName,
|
|
88
|
+
getDefinition(): ToolDefinition {
|
|
89
|
+
return {
|
|
90
|
+
...tool.getDefinition(),
|
|
91
|
+
name: safeName,
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
78
97
|
export function registerTool(tool: Tool): void {
|
|
79
98
|
const existing = tools.get(tool.name);
|
|
80
99
|
if (existing) {
|
|
@@ -176,15 +195,17 @@ export function registerPluginTools(
|
|
|
176
195
|
pluginName: string,
|
|
177
196
|
newTools: Tool[],
|
|
178
197
|
): Tool[] {
|
|
179
|
-
const stamped: Tool[] = newTools.map((tool) =>
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
198
|
+
const stamped: Tool[] = newTools.map((tool) =>
|
|
199
|
+
withProviderSafeToolName({
|
|
200
|
+
...tool,
|
|
201
|
+
origin: "plugin" as const,
|
|
202
|
+
ownerPluginId: pluginName,
|
|
203
|
+
ownerSkillId: undefined,
|
|
204
|
+
ownerMcpServerId: undefined,
|
|
205
|
+
ownerSkillBundled: undefined,
|
|
206
|
+
ownerSkillVersionHash: undefined,
|
|
207
|
+
}),
|
|
208
|
+
);
|
|
188
209
|
|
|
189
210
|
const accepted: Tool[] = [];
|
|
190
211
|
for (const tool of stamped) {
|
package/src/tools/skills/load.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import {
|
|
20
20
|
collectAllMissing,
|
|
21
21
|
indexCatalogById,
|
|
22
|
-
|
|
22
|
+
validateIncludeCycles,
|
|
23
23
|
} from "../../skills/include-graph.js";
|
|
24
24
|
import { renderInlineCommands } from "../../skills/inline-command-render.js";
|
|
25
25
|
import { parseToolManifestFile } from "../../skills/tool-manifest.js";
|
|
@@ -204,6 +204,7 @@ export class SkillLoadTool implements Tool {
|
|
|
204
204
|
|
|
205
205
|
// Load catalog for include validation and child metadata output
|
|
206
206
|
let catalogIndex: Map<string, SkillSummary> | undefined;
|
|
207
|
+
let missingIncludedSkillIds: string[] = [];
|
|
207
208
|
if (skill.includes && skill.includes.length > 0) {
|
|
208
209
|
let catalog = loadSkillCatalog();
|
|
209
210
|
catalogIndex = indexCatalogById(catalog);
|
|
@@ -260,19 +261,13 @@ export class SkillLoadTool implements Tool {
|
|
|
260
261
|
catalogIndex = indexCatalogById(catalog);
|
|
261
262
|
}
|
|
262
263
|
|
|
263
|
-
|
|
264
|
-
|
|
264
|
+
missingIncludedSkillIds = [...collectAllMissing(skill.id, catalogIndex)];
|
|
265
|
+
|
|
266
|
+
// Validate cycles fail closed. Missing includes are advisory: the parent
|
|
267
|
+
// skill should still load so the assistant can decide whether to search
|
|
268
|
+
// for and install the suggested dependency.
|
|
269
|
+
const validation = validateIncludeCycles(skill.id, catalogIndex);
|
|
265
270
|
if (!validation.ok) {
|
|
266
|
-
if (validation.error === "missing") {
|
|
267
|
-
return {
|
|
268
|
-
content: `Error: skill "${skill.id}" includes "${
|
|
269
|
-
validation.missingChildId
|
|
270
|
-
}" which was not found (referenced by "${
|
|
271
|
-
validation.parentId
|
|
272
|
-
}" via path: ${validation.path.join(" → ")})`,
|
|
273
|
-
isError: true,
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
271
|
if (validation.error === "cycle") {
|
|
277
272
|
return {
|
|
278
273
|
content: `Error: skill "${
|
|
@@ -283,10 +278,6 @@ export class SkillLoadTool implements Tool {
|
|
|
283
278
|
isError: true,
|
|
284
279
|
};
|
|
285
280
|
}
|
|
286
|
-
return {
|
|
287
|
-
content: `Error: skill "${skill.id}" has an invalid include graph`,
|
|
288
|
-
isError: true,
|
|
289
|
-
};
|
|
290
281
|
}
|
|
291
282
|
}
|
|
292
283
|
|
|
@@ -444,13 +435,25 @@ export class SkillLoadTool implements Tool {
|
|
|
444
435
|
}
|
|
445
436
|
}
|
|
446
437
|
}
|
|
447
|
-
immediateChildrenSection =
|
|
448
|
-
|
|
449
|
-
|
|
438
|
+
immediateChildrenSection =
|
|
439
|
+
childLines.length > 0
|
|
440
|
+
? `Included Skills (immediate):\n${childLines.join("\n")}`
|
|
441
|
+
: "Included Skills (immediate): none";
|
|
450
442
|
} else {
|
|
451
443
|
immediateChildrenSection = "Included Skills (immediate): none";
|
|
452
444
|
}
|
|
453
445
|
|
|
446
|
+
const missingIncludesSection =
|
|
447
|
+
missingIncludedSkillIds.length > 0
|
|
448
|
+
? [
|
|
449
|
+
"Suggested Included Skills (not loaded):",
|
|
450
|
+
...missingIncludedSkillIds.map(
|
|
451
|
+
(id) =>
|
|
452
|
+
` - ${id}: not installed or unavailable. If this task needs it, search for and install this skill, then load it.`,
|
|
453
|
+
),
|
|
454
|
+
].join("\n")
|
|
455
|
+
: undefined;
|
|
456
|
+
|
|
454
457
|
let versionHash: string | undefined;
|
|
455
458
|
try {
|
|
456
459
|
versionHash = computeSkillVersionHash(skill.directoryPath);
|
|
@@ -512,6 +515,7 @@ export class SkillLoadTool implements Tool {
|
|
|
512
515
|
: []),
|
|
513
516
|
...includedBodies.flatMap((b) => [b, ""]),
|
|
514
517
|
immediateChildrenSection,
|
|
518
|
+
...(missingIncludesSection ? [missingIncludesSection] : []),
|
|
515
519
|
"",
|
|
516
520
|
`<loaded_skill id="${skill.id}"${versionAttr} />`,
|
|
517
521
|
...includeMarkers,
|
|
@@ -111,6 +111,15 @@ class ShellTool implements Tool {
|
|
|
111
111
|
return { content: "Error: command contains null bytes", isError: true };
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
const background = input.background === true;
|
|
115
|
+
if (background && context.diskPressureCleanupModeActive === true) {
|
|
116
|
+
return {
|
|
117
|
+
content:
|
|
118
|
+
"Error: background shell commands are not available during disk pressure cleanup mode.",
|
|
119
|
+
isError: true,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
114
123
|
const config = getConfig();
|
|
115
124
|
const shellLockdownActive =
|
|
116
125
|
isCesShellLockdownEnabled(config) &&
|
|
@@ -276,7 +285,6 @@ class ShellTool implements Tool {
|
|
|
276
285
|
// Background mode: spawn and return immediately. The process output is
|
|
277
286
|
// delivered to the conversation as a wake when the process exits.
|
|
278
287
|
// -----------------------------------------------------------------------
|
|
279
|
-
const background = input.background === true;
|
|
280
288
|
if (background) {
|
|
281
289
|
// Check the registry limit BEFORE spawning so we never leak an
|
|
282
290
|
// untracked process when the registry is full.
|
|
@@ -13,12 +13,13 @@ import { getLogger } from "../util/logger.js";
|
|
|
13
13
|
import { getAllTools, getTool } from "./registry.js";
|
|
14
14
|
import { isSideEffectTool } from "./side-effects.js";
|
|
15
15
|
import { summarizeToolInput } from "./tool-input-summary.js";
|
|
16
|
-
import
|
|
17
|
-
ExecutionTarget,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
import {
|
|
17
|
+
type ExecutionTarget,
|
|
18
|
+
isDiskPressureCleanupToolName,
|
|
19
|
+
type Tool,
|
|
20
|
+
type ToolContext,
|
|
21
|
+
type ToolExecutionResult,
|
|
22
|
+
type ToolLifecycleEvent,
|
|
22
23
|
} from "./types.js";
|
|
23
24
|
import { enforceVerificationControlPlanePolicy } from "./verification-control-plane-policy.js";
|
|
24
25
|
|
|
@@ -309,6 +310,30 @@ export class ToolApprovalHandler {
|
|
|
309
310
|
};
|
|
310
311
|
}
|
|
311
312
|
|
|
313
|
+
if (
|
|
314
|
+
context.diskPressureCleanupModeActive === true &&
|
|
315
|
+
!isDiskPressureCleanupToolName(name)
|
|
316
|
+
) {
|
|
317
|
+
const msg = `Tool "${name}" is not available during disk pressure cleanup mode.`;
|
|
318
|
+
const durationMs = Date.now() - startTime;
|
|
319
|
+
emitLifecycleEvent({
|
|
320
|
+
type: "error",
|
|
321
|
+
toolName: name,
|
|
322
|
+
executionTarget,
|
|
323
|
+
input,
|
|
324
|
+
workingDir: context.workingDir,
|
|
325
|
+
conversationId: context.conversationId,
|
|
326
|
+
requestId: context.requestId,
|
|
327
|
+
riskLevel,
|
|
328
|
+
decision: "error",
|
|
329
|
+
durationMs,
|
|
330
|
+
errorMessage: msg,
|
|
331
|
+
isExpected: true,
|
|
332
|
+
errorCategory: "tool_failure",
|
|
333
|
+
});
|
|
334
|
+
return { allowed: false, result: { content: msg, isError: true } };
|
|
335
|
+
}
|
|
336
|
+
|
|
312
337
|
// Gate tools not active for the current turn
|
|
313
338
|
if (context.allowedToolNames && !context.allowedToolNames.has(name)) {
|
|
314
339
|
const msg = `Tool "${name}" is not currently active. Load the skill that provides this tool first.`;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const TOOL_NAME_ALIASES = new Map<string, string>([
|
|
2
|
+
["create_app", "app_create"],
|
|
3
|
+
]);
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolve high-confidence compatibility aliases before active-tool gating.
|
|
7
|
+
* Keep this list narrow: aliases should only cover observed model drift where
|
|
8
|
+
* the canonical target is active for the turn.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveToolNameAlias(
|
|
11
|
+
name: string,
|
|
12
|
+
allowedToolNames?: ReadonlySet<string>,
|
|
13
|
+
): string {
|
|
14
|
+
if (allowedToolNames?.has(name)) return name;
|
|
15
|
+
const canonical = TOOL_NAME_ALIASES.get(name);
|
|
16
|
+
if (!canonical) return name;
|
|
17
|
+
if (allowedToolNames && !allowedToolNames.has(canonical)) return name;
|
|
18
|
+
return canonical;
|
|
19
|
+
}
|
package/src/tools/types.ts
CHANGED
|
@@ -18,6 +18,20 @@ import type { SecretPromptResult } from "../permissions/secret-prompter.js";
|
|
|
18
18
|
import type { ContentBlock } from "../providers/types.js";
|
|
19
19
|
import type { TrustClass } from "../runtime/actor-trust-resolver.js";
|
|
20
20
|
|
|
21
|
+
export const DISK_PRESSURE_CLEANUP_TOOL_NAMES: ReadonlySet<string> = new Set([
|
|
22
|
+
"bash",
|
|
23
|
+
"host_bash",
|
|
24
|
+
"file_read",
|
|
25
|
+
"file_list",
|
|
26
|
+
"host_file_read",
|
|
27
|
+
"background_tool_list",
|
|
28
|
+
"background_tool_cancel",
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
export function isDiskPressureCleanupToolName(name: string): boolean {
|
|
32
|
+
return DISK_PRESSURE_CLEANUP_TOOL_NAMES.has(name);
|
|
33
|
+
}
|
|
34
|
+
|
|
21
35
|
// ---------------------------------------------------------------------------
|
|
22
36
|
// Re-exports + concrete overlays for types that live in
|
|
23
37
|
// @vellumai/skill-host-contracts.
|
|
@@ -101,8 +115,26 @@ export interface ToolExecutionResult {
|
|
|
101
115
|
riskThreshold?: string;
|
|
102
116
|
/** Whether the daemon is running in a containerized (Docker) environment. */
|
|
103
117
|
isContainerized?: boolean;
|
|
104
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* Display-only ladder of scope option labels for the rule editor
|
|
120
|
+
* (narrowest to broadest). The `pattern` field here is a regex-style
|
|
121
|
+
* descriptor used internally by the daemon and is NOT a valid trust
|
|
122
|
+
* rule pattern. Use `riskAllowlistOptions` for the pattern that gets
|
|
123
|
+
* saved as a trust rule.
|
|
124
|
+
*/
|
|
105
125
|
riskScopeOptions?: Array<{ pattern: string; label: string }>;
|
|
126
|
+
/**
|
|
127
|
+
* Allowlist options for the rule editor save path (narrowest to
|
|
128
|
+
* broadest). Each `pattern` is a Minimatch-glob compatible string
|
|
129
|
+
* (e.g. raw command for exact match, `action:<program>` for command
|
|
130
|
+
* wildcards) — what the gateway actually matches against. Mirrors
|
|
131
|
+
* the `allowlistOptions` field on `ConfirmationRequest` SSE events.
|
|
132
|
+
*/
|
|
133
|
+
riskAllowlistOptions?: Array<{
|
|
134
|
+
label: string;
|
|
135
|
+
description: string;
|
|
136
|
+
pattern: string;
|
|
137
|
+
}>;
|
|
106
138
|
/** Directory scope ladder for the rule editor (narrowest to broadest). */
|
|
107
139
|
riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
|
|
108
140
|
/**
|
|
@@ -177,6 +209,8 @@ export interface ToolContext {
|
|
|
177
209
|
proxyToolResolver?: ProxyToolResolver;
|
|
178
210
|
/** When set, only tools in this set may execute. Tools outside the set are blocked with an error. */
|
|
179
211
|
allowedToolNames?: Set<string>;
|
|
212
|
+
/** True when this turn is restricted to storage cleanup-safe tools. */
|
|
213
|
+
diskPressureCleanupModeActive?: boolean;
|
|
180
214
|
/** Prompt the user for a secret value via native SecureField UI. */
|
|
181
215
|
requestSecret?: (params: {
|
|
182
216
|
service: string;
|
|
@@ -192,8 +226,6 @@ export interface ToolContext {
|
|
|
192
226
|
sendToClient?: (msg: { type: string; [key: string]: unknown }) => void;
|
|
193
227
|
/** True when an interactive client is connected (not just a no-op callback). */
|
|
194
228
|
isInteractive?: boolean;
|
|
195
|
-
/** Memory scope ID from the conversation's memory policy, so memory tools can target the correct scope. */
|
|
196
|
-
memoryScopeId?: string;
|
|
197
229
|
/** When true, tools with side effects should always prompt for confirmation. */
|
|
198
230
|
forcePromptSideEffects?: boolean;
|
|
199
231
|
/**
|
|
@@ -268,6 +300,14 @@ export interface ToolContext {
|
|
|
268
300
|
* `executeSubagentSpawn` in tools/subagent/spawn.ts.
|
|
269
301
|
*/
|
|
270
302
|
overrideProfile?: string;
|
|
303
|
+
/**
|
|
304
|
+
* Canonical principal ID of the actor on whose behalf this tool invocation
|
|
305
|
+
* is running. Sourced from `conversation.trustContext.guardianPrincipalId`.
|
|
306
|
+
* Used by host proxies to bind cross-client targeted execution to the same
|
|
307
|
+
* authenticated user identity. May be undefined for legacy/internal flows
|
|
308
|
+
* with no resolved actor identity.
|
|
309
|
+
*/
|
|
310
|
+
sourceActorPrincipalId?: string;
|
|
271
311
|
}
|
|
272
312
|
|
|
273
313
|
export interface Tool {
|
|
@@ -13,8 +13,6 @@
|
|
|
13
13
|
|
|
14
14
|
import type { TtsCallMode, TtsProviderId } from "./types.js";
|
|
15
15
|
|
|
16
|
-
export type { TtsCallMode } from "./types.js";
|
|
17
|
-
|
|
18
16
|
// ---------------------------------------------------------------------------
|
|
19
17
|
// Catalog entry model
|
|
20
18
|
// ---------------------------------------------------------------------------
|
|
@@ -22,7 +20,7 @@ export type { TtsCallMode } from "./types.js";
|
|
|
22
20
|
/**
|
|
23
21
|
* Metadata about a secret (API key / credential) required by a provider.
|
|
24
22
|
*/
|
|
25
|
-
|
|
23
|
+
interface TtsProviderSecretRequirement {
|
|
26
24
|
/**
|
|
27
25
|
* The key used to retrieve this secret from the secure credential store.
|
|
28
26
|
*
|
|
@@ -49,7 +47,7 @@ export interface TtsProviderSecretRequirement {
|
|
|
49
47
|
* These describe static, provider-wide traits — they do not change based
|
|
50
48
|
* on runtime configuration or per-request parameters.
|
|
51
49
|
*/
|
|
52
|
-
|
|
50
|
+
interface TtsProviderCatalogCapabilities {
|
|
53
51
|
/** Whether the provider supports chunk-level streaming synthesis. */
|
|
54
52
|
readonly supportsStreaming: boolean;
|
|
55
53
|
|
|
@@ -64,7 +62,7 @@ export interface TtsProviderCatalogCapabilities {
|
|
|
64
62
|
* metadata level — identity, display name, telephony call mode,
|
|
65
63
|
* capabilities, and secret requirements.
|
|
66
64
|
*/
|
|
67
|
-
|
|
65
|
+
interface TtsProviderCatalogEntry {
|
|
68
66
|
/** Unique provider identifier matching {@link TtsProviderId}. */
|
|
69
67
|
readonly id: TtsProviderId;
|
|
70
68
|
|