@vellumai/assistant 0.3.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/.dockerignore +27 -0
- package/.env.example +22 -0
- package/Dockerfile +99 -0
- package/Dockerfile.sandbox +5 -0
- package/README.md +248 -0
- package/bun.lock +1723 -0
- package/bunfig.toml +2 -0
- package/docs/skills.md +158 -0
- package/drizzle/0000_dizzy_maggott.sql +301 -0
- package/drizzle/meta/0000_snapshot.json +1999 -0
- package/drizzle/meta/_journal.json +13 -0
- package/drizzle.config.ts +7 -0
- package/eslint.config.mjs +17 -0
- package/hook-templates/debug-prompt-logger/hook.json +7 -0
- package/hook-templates/debug-prompt-logger/run.sh +68 -0
- package/knip.json +9 -0
- package/package.json +70 -0
- package/scripts/capture-x-graphql.ts +545 -0
- package/scripts/ipc/check-contract-inventory.ts +104 -0
- package/scripts/ipc/check-swift-decoder-drift.ts +166 -0
- package/scripts/ipc/generate-swift.ts +492 -0
- package/scripts/test-filesystem-tools.sh +48 -0
- package/scripts/test.sh +127 -0
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +2485 -0
- package/src/__tests__/account-registry.test.ts +245 -0
- package/src/__tests__/active-skill-tools.test.ts +378 -0
- package/src/__tests__/agent-heartbeat-service.test.ts +250 -0
- package/src/__tests__/agent-loop-thinking.test.ts +81 -0
- package/src/__tests__/agent-loop.test.ts +1135 -0
- package/src/__tests__/anthropic-provider.test.ts +778 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +290 -0
- package/src/__tests__/app-bundler.test.ts +292 -0
- package/src/__tests__/app-executors.test.ts +613 -0
- package/src/__tests__/app-git-history.test.ts +176 -0
- package/src/__tests__/app-git-service.test.ts +169 -0
- package/src/__tests__/app-open-proxy.test.ts +62 -0
- package/src/__tests__/asset-materialize-tool.test.ts +452 -0
- package/src/__tests__/asset-search-tool.test.ts +477 -0
- package/src/__tests__/assistant-attachment-directive.test.ts +401 -0
- package/src/__tests__/assistant-attachments.test.ts +437 -0
- package/src/__tests__/assistant-event-hub.test.ts +226 -0
- package/src/__tests__/assistant-event.test.ts +123 -0
- package/src/__tests__/assistant-events-sse-hardening.test.ts +315 -0
- package/src/__tests__/attachments-store.test.ts +476 -0
- package/src/__tests__/attachments.test.ts +134 -0
- package/src/__tests__/audit-log-rotation.test.ts +154 -0
- package/src/__tests__/browser-fill-credential.test.ts +309 -0
- package/src/__tests__/browser-manager.test.ts +203 -0
- package/src/__tests__/browser-runtime-check.test.ts +55 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +68 -0
- package/src/__tests__/browser-skill-endstate.test.ts +195 -0
- package/src/__tests__/bundle-scanner.test.ts +313 -0
- package/src/__tests__/call-bridge.test.ts +517 -0
- package/src/__tests__/call-constants.test.ts +40 -0
- package/src/__tests__/call-domain.test.ts +163 -0
- package/src/__tests__/call-orchestrator.test.ts +625 -0
- package/src/__tests__/call-recovery.test.ts +518 -0
- package/src/__tests__/call-routes-http.test.ts +699 -0
- package/src/__tests__/call-state-machine.test.ts +143 -0
- package/src/__tests__/call-state.test.ts +174 -0
- package/src/__tests__/call-store.test.ts +691 -0
- package/src/__tests__/channel-approval-routes.test.ts +2356 -0
- package/src/__tests__/channel-approval.test.ts +299 -0
- package/src/__tests__/channel-approvals.test.ts +521 -0
- package/src/__tests__/channel-delivery-store.test.ts +447 -0
- package/src/__tests__/channel-guardian.test.ts +1005 -0
- package/src/__tests__/checker.test.ts +3519 -0
- package/src/__tests__/clarification-resolver.test.ts +159 -0
- package/src/__tests__/classifier.test.ts +67 -0
- package/src/__tests__/claude-code-skill-regression.test.ts +127 -0
- package/src/__tests__/claude-code-tool-profiles.test.ts +88 -0
- package/src/__tests__/cli-discover.test.ts +85 -0
- package/src/__tests__/cli.test.ts +26 -0
- package/src/__tests__/clipboard.test.ts +80 -0
- package/src/__tests__/commit-guarantee.test.ts +335 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +550 -0
- package/src/__tests__/compaction.benchmark.test.ts +176 -0
- package/src/__tests__/computer-use-session-compaction.test.ts +132 -0
- package/src/__tests__/computer-use-session-lifecycle.test.ts +293 -0
- package/src/__tests__/computer-use-session-working-dir.test.ts +117 -0
- package/src/__tests__/computer-use-skill-baseline.test.ts +74 -0
- package/src/__tests__/computer-use-skill-endstate.test.ts +89 -0
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +217 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +107 -0
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +54 -0
- package/src/__tests__/computer-use-tools.test.ts +250 -0
- package/src/__tests__/config-schema.test.ts +1462 -0
- package/src/__tests__/conflict-intent-tokenization.test.ts +141 -0
- package/src/__tests__/conflict-policy.test.ts +121 -0
- package/src/__tests__/conflict-store.test.ts +332 -0
- package/src/__tests__/connection-policy.test.ts +102 -0
- package/src/__tests__/contacts-tools.test.ts +331 -0
- package/src/__tests__/context-memory-e2e.test.ts +434 -0
- package/src/__tests__/context-token-estimator.test.ts +135 -0
- package/src/__tests__/context-window-manager.test.ts +376 -0
- package/src/__tests__/contradiction-checker.test.ts +314 -0
- package/src/__tests__/conversation-store.test.ts +612 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +517 -0
- package/src/__tests__/credential-broker-server-use.test.ts +554 -0
- package/src/__tests__/credential-broker.test.ts +167 -0
- package/src/__tests__/credential-host-pattern-match.test.ts +104 -0
- package/src/__tests__/credential-metadata-store.test.ts +779 -0
- package/src/__tests__/credential-policy-validate.test.ts +121 -0
- package/src/__tests__/credential-resolve.test.ts +328 -0
- package/src/__tests__/credential-security-e2e.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +583 -0
- package/src/__tests__/credential-selection.test.ts +354 -0
- package/src/__tests__/credential-vault-unit.test.ts +780 -0
- package/src/__tests__/credential-vault.test.ts +852 -0
- package/src/__tests__/daemon-assistant-events.test.ts +164 -0
- package/src/__tests__/daemon-server-session-init.test.ts +522 -0
- package/src/__tests__/date-context.test.ts +373 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +129 -0
- package/src/__tests__/delete-managed-skill-tool.test.ts +97 -0
- package/src/__tests__/diff.test.ts +121 -0
- package/src/__tests__/domain-normalize.test.ts +112 -0
- package/src/__tests__/domain-policy.test.ts +124 -0
- package/src/__tests__/doordash-client.test.ts +186 -0
- package/src/__tests__/doordash-session.test.ts +152 -0
- package/src/__tests__/dynamic-page-surface.test.ts +91 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +132 -0
- package/src/__tests__/edit-engine.test.ts +180 -0
- package/src/__tests__/elevenlabs-client.test.ts +271 -0
- package/src/__tests__/email-cli.test.ts +283 -0
- package/src/__tests__/encrypted-store.test.ts +332 -0
- package/src/__tests__/entity-extractor.test.ts +190 -0
- package/src/__tests__/ephemeral-permissions.test.ts +362 -0
- package/src/__tests__/evaluate-typescript-tool.test.ts +286 -0
- package/src/__tests__/event-bus.test.ts +222 -0
- package/src/__tests__/file-edit-tool.test.ts +122 -0
- package/src/__tests__/file-ops-service.test.ts +330 -0
- package/src/__tests__/file-read-tool.test.ts +75 -0
- package/src/__tests__/file-write-tool.test.ts +113 -0
- package/src/__tests__/filesystem-tools.test.ts +579 -0
- package/src/__tests__/fixtures/credential-security-fixtures.ts +181 -0
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +126 -0
- package/src/__tests__/fixtures/mock-signup-server.ts +387 -0
- package/src/__tests__/fixtures/proxy-fixtures.ts +147 -0
- package/src/__tests__/followup-tools.test.ts +303 -0
- package/src/__tests__/forbidden-legacy-symbols.test.ts +71 -0
- package/src/__tests__/fuzzy-match-property.test.ts +216 -0
- package/src/__tests__/fuzzy-match.test.ts +138 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +631 -0
- package/src/__tests__/gemini-image-service.test.ts +261 -0
- package/src/__tests__/gemini-provider.test.ts +651 -0
- package/src/__tests__/get-weather.test.ts +318 -0
- package/src/__tests__/gmail-integration.test.ts +73 -0
- package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +202 -0
- package/src/__tests__/handlers-cu-observation-blob.test.ts +352 -0
- package/src/__tests__/handlers-ipc-blob-probe.test.ts +191 -0
- package/src/__tests__/handlers-slack-config.test.ts +200 -0
- package/src/__tests__/handlers-task-submit-slash.test.ts +38 -0
- package/src/__tests__/handlers-telegram-config.test.ts +968 -0
- package/src/__tests__/handlers-twilio-config.test.ts +659 -0
- package/src/__tests__/handlers-twitter-config.test.ts +858 -0
- package/src/__tests__/headless-browser-interactions.test.ts +536 -0
- package/src/__tests__/headless-browser-navigate.test.ts +211 -0
- package/src/__tests__/headless-browser-read-tools.test.ts +261 -0
- package/src/__tests__/headless-browser-snapshot.test.ts +185 -0
- package/src/__tests__/history-repair-observability.test.ts +56 -0
- package/src/__tests__/history-repair.test.ts +510 -0
- package/src/__tests__/home-base-bootstrap.test.ts +82 -0
- package/src/__tests__/hooks-blocking.test.ts +128 -0
- package/src/__tests__/hooks-cli.test.ts +144 -0
- package/src/__tests__/hooks-config.test.ts +93 -0
- package/src/__tests__/hooks-discovery.test.ts +199 -0
- package/src/__tests__/hooks-integration.test.ts +189 -0
- package/src/__tests__/hooks-manager.test.ts +187 -0
- package/src/__tests__/hooks-runner.test.ts +182 -0
- package/src/__tests__/hooks-settings.test.ts +154 -0
- package/src/__tests__/hooks-templates.test.ts +137 -0
- package/src/__tests__/hooks-ts-runner.test.ts +125 -0
- package/src/__tests__/hooks-watch.test.ts +100 -0
- package/src/__tests__/host-file-edit-tool.test.ts +228 -0
- package/src/__tests__/host-file-read-tool.test.ts +123 -0
- package/src/__tests__/host-file-write-tool.test.ts +136 -0
- package/src/__tests__/host-shell-tool.test.ts +562 -0
- package/src/__tests__/ingress-reconcile.test.ts +581 -0
- package/src/__tests__/ingress-url-consistency.test.ts +214 -0
- package/src/__tests__/intent-routing.test.ts +259 -0
- package/src/__tests__/ipc-blob-store.test.ts +315 -0
- package/src/__tests__/ipc-contract-inventory.test.ts +54 -0
- package/src/__tests__/ipc-contract.test.ts +74 -0
- package/src/__tests__/ipc-protocol.test.ts +113 -0
- package/src/__tests__/ipc-roundtrip.benchmark.test.ts +237 -0
- package/src/__tests__/ipc-snapshot.test.ts +1769 -0
- package/src/__tests__/ipc-validate.test.ts +407 -0
- package/src/__tests__/key-migration.test.ts +206 -0
- package/src/__tests__/keychain.test.ts +258 -0
- package/src/__tests__/llm-usage-store.test.ts +221 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +257 -0
- package/src/__tests__/managed-store.test.ts +608 -0
- package/src/__tests__/media-generate-image.test.ts +238 -0
- package/src/__tests__/media-reuse-story.e2e.test.ts +676 -0
- package/src/__tests__/media-visibility-policy.test.ts +141 -0
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +235 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +481 -0
- package/src/__tests__/memory-query-builder.test.ts +59 -0
- package/src/__tests__/memory-recall-quality.test.ts +846 -0
- package/src/__tests__/memory-regressions.experimental.test.ts +538 -0
- package/src/__tests__/memory-regressions.test.ts +4435 -0
- package/src/__tests__/memory-retrieval-budget.test.ts +49 -0
- package/src/__tests__/memory-retrieval.benchmark.test.ts +430 -0
- package/src/__tests__/migration-cli-flows.test.ts +169 -0
- package/src/__tests__/migration-ordering.test.ts +249 -0
- package/src/__tests__/mock-signup-server.test.ts +528 -0
- package/src/__tests__/oauth-callback-registry.test.ts +92 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +285 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +176 -0
- package/src/__tests__/onboarding-template-contract.test.ts +58 -0
- package/src/__tests__/openai-provider.test.ts +753 -0
- package/src/__tests__/parallel-tool.benchmark.test.ts +294 -0
- package/src/__tests__/parser.test.ts +472 -0
- package/src/__tests__/path-classifier.test.ts +73 -0
- package/src/__tests__/path-policy.test.ts +435 -0
- package/src/__tests__/platform-move-helper.test.ts +99 -0
- package/src/__tests__/platform-socket-path.test.ts +52 -0
- package/src/__tests__/platform-workspace-migration.test.ts +1000 -0
- package/src/__tests__/platform.test.ts +131 -0
- package/src/__tests__/playbook-execution.test.ts +502 -0
- package/src/__tests__/playbook-tools.test.ts +340 -0
- package/src/__tests__/prebuilt-home-base-seed.test.ts +75 -0
- package/src/__tests__/pricing.test.ts +256 -0
- package/src/__tests__/profile-compiler.test.ts +374 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +342 -0
- package/src/__tests__/provider-registry-ollama.test.ts +16 -0
- package/src/__tests__/provider-streaming.benchmark.test.ts +773 -0
- package/src/__tests__/proxy-approval-callback.test.ts +601 -0
- package/src/__tests__/public-ingress-urls.test.ts +256 -0
- package/src/__tests__/qdrant-manager.test.ts +267 -0
- package/src/__tests__/ratelimit.test.ts +297 -0
- package/src/__tests__/recurrence-engine-rruleset.test.ts +175 -0
- package/src/__tests__/recurrence-engine.test.ts +78 -0
- package/src/__tests__/recurrence-types.test.ts +79 -0
- package/src/__tests__/registry.test.ts +494 -0
- package/src/__tests__/relay-server.test.ts +688 -0
- package/src/__tests__/reminder-store.test.ts +223 -0
- package/src/__tests__/reminder.test.ts +229 -0
- package/src/__tests__/request-file-tool.test.ts +158 -0
- package/src/__tests__/run-orchestrator-assistant-events.test.ts +227 -0
- package/src/__tests__/run-orchestrator.test.ts +425 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +189 -0
- package/src/__tests__/runtime-events-sse-parity.test.ts +343 -0
- package/src/__tests__/runtime-events-sse.test.ts +162 -0
- package/src/__tests__/runtime-runs-http.test.ts +438 -0
- package/src/__tests__/runtime-runs.test.ts +260 -0
- package/src/__tests__/sandbox-diagnostics.test.ts +408 -0
- package/src/__tests__/sandbox-host-parity.test.ts +950 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +253 -0
- package/src/__tests__/schedule-store.test.ts +484 -0
- package/src/__tests__/schedule-tools.test.ts +783 -0
- package/src/__tests__/scheduler-recurrence.test.ts +430 -0
- package/src/__tests__/script-proxy-certs.test.ts +90 -0
- package/src/__tests__/script-proxy-connect-tunnel.test.ts +177 -0
- package/src/__tests__/script-proxy-decision-trace.test.ts +156 -0
- package/src/__tests__/script-proxy-http-forwarder.test.ts +281 -0
- package/src/__tests__/script-proxy-injection-runtime.test.ts +401 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +407 -0
- package/src/__tests__/script-proxy-policy-runtime.test.ts +287 -0
- package/src/__tests__/script-proxy-policy.test.ts +310 -0
- package/src/__tests__/script-proxy-rewrite-specificity.test.ts +135 -0
- package/src/__tests__/script-proxy-router.test.ts +180 -0
- package/src/__tests__/script-proxy-session-manager.test.ts +382 -0
- package/src/__tests__/script-proxy-session-runtime.test.ts +113 -0
- package/src/__tests__/secret-allowlist.test.ts +230 -0
- package/src/__tests__/secret-ingress-handler.test.ts +110 -0
- package/src/__tests__/secret-onetime-send.test.ts +130 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +106 -0
- package/src/__tests__/secret-response-routing.test.ts +93 -0
- package/src/__tests__/secret-scanner-executor.test.ts +348 -0
- package/src/__tests__/secret-scanner.test.ts +900 -0
- package/src/__tests__/secure-keys.test.ts +323 -0
- package/src/__tests__/server-history-render.test.ts +431 -0
- package/src/__tests__/session-abort-tool-results.test.ts +240 -0
- package/src/__tests__/session-conflict-gate.test.ts +1136 -0
- package/src/__tests__/session-error.test.ts +369 -0
- package/src/__tests__/session-evictor.test.ts +188 -0
- package/src/__tests__/session-init.benchmark.test.ts +465 -0
- package/src/__tests__/session-load-history-repair.test.ts +222 -0
- package/src/__tests__/session-pre-run-repair.test.ts +213 -0
- package/src/__tests__/session-process-bridge.test.ts +242 -0
- package/src/__tests__/session-profile-injection.test.ts +444 -0
- package/src/__tests__/session-provider-retry-repair.test.ts +306 -0
- package/src/__tests__/session-queue.test.ts +1535 -0
- package/src/__tests__/session-runtime-assembly.test.ts +476 -0
- package/src/__tests__/session-runtime-workspace.test.ts +183 -0
- package/src/__tests__/session-skill-tools.test.ts +2431 -0
- package/src/__tests__/session-slash-known.test.ts +368 -0
- package/src/__tests__/session-slash-queue.test.ts +288 -0
- package/src/__tests__/session-slash-unknown.test.ts +271 -0
- package/src/__tests__/session-surfaces-task-progress.test.ts +104 -0
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +473 -0
- package/src/__tests__/session-tool-setup-memory-scope.test.ts +140 -0
- package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +140 -0
- package/src/__tests__/session-undo.test.ts +75 -0
- package/src/__tests__/session-workspace-cache-state.test.ts +246 -0
- package/src/__tests__/session-workspace-injection.test.ts +327 -0
- package/src/__tests__/session-workspace-tool-tracking.test.ts +240 -0
- package/src/__tests__/shared-filesystem-errors.test.ts +78 -0
- package/src/__tests__/shell-credential-ref.test.ts +187 -0
- package/src/__tests__/shell-identity.test.ts +256 -0
- package/src/__tests__/shell-parser-fuzz.test.ts +544 -0
- package/src/__tests__/shell-parser-property.test.ts +433 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +272 -0
- package/src/__tests__/signup-e2e.test.ts +353 -0
- package/src/__tests__/size-guard.test.ts +117 -0
- package/src/__tests__/skill-include-graph.test.ts +303 -0
- package/src/__tests__/skill-load-tool.test.ts +409 -0
- package/src/__tests__/skill-projection.benchmark.test.ts +338 -0
- package/src/__tests__/skill-script-runner-host.test.ts +489 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +349 -0
- package/src/__tests__/skill-script-runner.test.ts +159 -0
- package/src/__tests__/skill-tool-factory.test.ts +252 -0
- package/src/__tests__/skill-tool-manifest.test.ts +658 -0
- package/src/__tests__/skill-version-hash.test.ts +182 -0
- package/src/__tests__/skills.test.ts +680 -0
- package/src/__tests__/slash-commands-catalog.test.ts +86 -0
- package/src/__tests__/slash-commands-parser.test.ts +119 -0
- package/src/__tests__/slash-commands-resolver.test.ts +193 -0
- package/src/__tests__/slash-commands-rewrite.test.ts +39 -0
- package/src/__tests__/speaker-identification.test.ts +52 -0
- package/src/__tests__/starter-bundle.test.ts +136 -0
- package/src/__tests__/starter-task-flow.test.ts +143 -0
- package/src/__tests__/subagent-manager-notify.test.ts +404 -0
- package/src/__tests__/subagent-tools.test.ts +801 -0
- package/src/__tests__/subagent-types.test.ts +78 -0
- package/src/__tests__/swarm-orchestrator.test.ts +428 -0
- package/src/__tests__/swarm-plan-validator.test.ts +330 -0
- package/src/__tests__/swarm-recursion.test.ts +165 -0
- package/src/__tests__/swarm-router-planner.test.ts +208 -0
- package/src/__tests__/swarm-session-integration.test.ts +274 -0
- package/src/__tests__/swarm-tool.test.ts +145 -0
- package/src/__tests__/swarm-worker-backend.test.ts +129 -0
- package/src/__tests__/swarm-worker-runner.test.ts +272 -0
- package/src/__tests__/system-prompt.test.ts +439 -0
- package/src/__tests__/task-compiler.test.ts +284 -0
- package/src/__tests__/task-management-tools.test.ts +936 -0
- package/src/__tests__/task-runner.test.ts +216 -0
- package/src/__tests__/task-scheduler.test.ts +217 -0
- package/src/__tests__/task-tools.test.ts +595 -0
- package/src/__tests__/terminal-sandbox-docker.test.ts +1064 -0
- package/src/__tests__/terminal-sandbox.integration.test.ts +178 -0
- package/src/__tests__/terminal-sandbox.test.ts +202 -0
- package/src/__tests__/terminal-tools.test.ts +840 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +90 -0
- package/src/__tests__/test-support/computer-use-skill-harness.ts +45 -0
- package/src/__tests__/tool-audit-listener.test.ts +113 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +253 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +500 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +516 -0
- package/src/__tests__/tool-executor-redaction.test.ts +289 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +301 -0
- package/src/__tests__/tool-executor.test.ts +1989 -0
- package/src/__tests__/tool-metrics-listener.test.ts +225 -0
- package/src/__tests__/tool-notification-listener.test.ts +49 -0
- package/src/__tests__/tool-permission-simulate-handler.test.ts +336 -0
- package/src/__tests__/tool-policy.test.ts +54 -0
- package/src/__tests__/tool-profiling-listener.test.ts +268 -0
- package/src/__tests__/tool-result-truncation.test.ts +217 -0
- package/src/__tests__/tool-trace-listener.test.ts +226 -0
- package/src/__tests__/top-level-renderer.test.ts +121 -0
- package/src/__tests__/top-level-scanner.test.ts +141 -0
- package/src/__tests__/trace-emitter.test.ts +173 -0
- package/src/__tests__/trust-store.test.ts +1605 -0
- package/src/__tests__/turn-commit.test.ts +554 -0
- package/src/__tests__/twilio-provider.test.ts +329 -0
- package/src/__tests__/twilio-routes-elevenlabs.test.ts +375 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +127 -0
- package/src/__tests__/twilio-routes.test.ts +577 -0
- package/src/__tests__/twitter-auth-handler.test.ts +667 -0
- package/src/__tests__/twitter-cli-error-shaping.test.ts +208 -0
- package/src/__tests__/twitter-cli-routing.test.ts +252 -0
- package/src/__tests__/twitter-oauth-client.test.ts +209 -0
- package/src/__tests__/url-safety.test.ts +418 -0
- package/src/__tests__/view-image-tool.test.ts +217 -0
- package/src/__tests__/weather-skill-regression.test.ts +225 -0
- package/src/__tests__/web-fetch.test.ts +869 -0
- package/src/__tests__/web-search.test.ts +584 -0
- package/src/__tests__/workspace-git-service.test.ts +1153 -0
- package/src/__tests__/workspace-heartbeat-service.test.ts +486 -0
- package/src/__tests__/workspace-lifecycle.test.ts +292 -0
- package/src/__tests__/workspace-policy.test.ts +213 -0
- package/src/agent/attachments.ts +35 -0
- package/src/agent/loop.ts +500 -0
- package/src/agent/message-types.ts +17 -0
- package/src/agent-heartbeat/agent-heartbeat-service.ts +155 -0
- package/src/autonomy/autonomy-resolver.ts +60 -0
- package/src/autonomy/autonomy-store.ts +122 -0
- package/src/autonomy/disposition-mapper.ts +31 -0
- package/src/autonomy/index.ts +11 -0
- package/src/autonomy/types.ts +39 -0
- package/src/bundler/app-bundler.ts +295 -0
- package/src/bundler/bundle-scanner.ts +535 -0
- package/src/bundler/bundle-signer.ts +124 -0
- package/src/bundler/manifest.ts +21 -0
- package/src/bundler/signature-verifier.ts +184 -0
- package/src/calls/call-bridge.ts +168 -0
- package/src/calls/call-constants.ts +48 -0
- package/src/calls/call-domain.ts +430 -0
- package/src/calls/call-orchestrator.ts +498 -0
- package/src/calls/call-recovery.ts +207 -0
- package/src/calls/call-state-machine.ts +68 -0
- package/src/calls/call-state.ts +87 -0
- package/src/calls/call-store.ts +422 -0
- package/src/calls/elevenlabs-client.ts +97 -0
- package/src/calls/elevenlabs-config.ts +31 -0
- package/src/calls/relay-server.ts +390 -0
- package/src/calls/speaker-identification.ts +213 -0
- package/src/calls/twilio-config.ts +45 -0
- package/src/calls/twilio-provider.ts +263 -0
- package/src/calls/twilio-rest.ts +156 -0
- package/src/calls/twilio-routes.ts +311 -0
- package/src/calls/types.ts +39 -0
- package/src/calls/voice-provider.ts +14 -0
- package/src/calls/voice-quality.ts +114 -0
- package/src/cli/autonomy.ts +188 -0
- package/src/cli/config-commands.ts +334 -0
- package/src/cli/contacts.ts +149 -0
- package/src/cli/core-commands.ts +784 -0
- package/src/cli/doordash.ts +1055 -0
- package/src/cli/email-guardrails.ts +200 -0
- package/src/cli/email.ts +405 -0
- package/src/cli/ipc-client.ts +82 -0
- package/src/cli/main-screen.tsx +53 -0
- package/src/cli/map.ts +270 -0
- package/src/cli/twitter.ts +754 -0
- package/src/cli.ts +918 -0
- package/src/commands/__tests__/cc-command-registry.test.ts +319 -0
- package/src/commands/cc-command-registry.ts +209 -0
- package/src/config/bundled-skills/.gitkeep +0 -0
- package/src/config/bundled-skills/agentmail/SKILL.md +128 -0
- package/src/config/bundled-skills/agentmail/icon.svg +21 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +1404 -0
- package/src/config/bundled-skills/app-builder/TOOLS.json +279 -0
- package/src/config/bundled-skills/app-builder/icon.svg +9 -0
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +15 -0
- package/src/config/bundled-skills/app-builder/tools/app-delete.ts +10 -0
- package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +11 -0
- package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +10 -0
- package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +18 -0
- package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +11 -0
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +10 -0
- package/src/config/bundled-skills/app-builder/tools/app-query.ts +10 -0
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +20 -0
- package/src/config/bundled-skills/browser/SKILL.md +28 -0
- package/src/config/bundled-skills/browser/TOOLS.json +234 -0
- package/src/config/bundled-skills/browser/tools/browser-click.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-close.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-type.ts +9 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +9 -0
- package/src/config/bundled-skills/claude-code/SKILL.md +50 -0
- package/src/config/bundled-skills/claude-code/TOOLS.json +40 -0
- package/src/config/bundled-skills/claude-code/tools/claude-code.ts +9 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +17 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +326 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +9 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +9 -0
- package/src/config/bundled-skills/contacts/SKILL.md +39 -0
- package/src/config/bundled-skills/contacts/TOOLS.json +122 -0
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +57 -0
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +60 -0
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +66 -0
- package/src/config/bundled-skills/document/SKILL.md +26 -0
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-create.ts +9 -0
- package/src/config/bundled-skills/document/tools/document-update.ts +9 -0
- package/src/config/bundled-skills/doordash/SKILL.md +163 -0
- package/src/config/bundled-skills/followups/SKILL.md +32 -0
- package/src/config/bundled-skills/followups/TOOLS.json +100 -0
- package/src/config/bundled-skills/followups/icon.svg +24 -0
- package/src/config/bundled-skills/followups/tools/followup-create.ts +9 -0
- package/src/config/bundled-skills/followups/tools/followup-list.ts +9 -0
- package/src/config/bundled-skills/followups/tools/followup-resolve.ts +9 -0
- package/src/config/bundled-skills/google-calendar/SKILL.md +51 -0
- package/src/config/bundled-skills/google-calendar/TOOLS.json +108 -0
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +165 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +21 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +42 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +13 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +30 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +41 -0
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +18 -0
- package/src/config/bundled-skills/google-calendar/types.ts +97 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +32 -0
- package/src/config/bundled-skills/image-studio/TOOLS.json +42 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +115 -0
- package/src/config/bundled-skills/macos-automation/SKILL.md +66 -0
- package/src/config/bundled-skills/messaging/SKILL.md +153 -0
- package/src/config/bundled-skills/messaging/TOOLS.json +357 -0
- package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +23 -0
- package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +23 -0
- package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +25 -0
- package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +26 -0
- package/src/config/bundled-skills/messaging/tools/gmail-label.ts +25 -0
- package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +23 -0
- package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +84 -0
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +18 -0
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +125 -0
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +16 -0
- package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +49 -0
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +21 -0
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +25 -0
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +28 -0
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +32 -0
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +22 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +31 -0
- package/src/config/bundled-skills/messaging/tools/shared.ts +76 -0
- package/src/config/bundled-skills/messaging/tools/slack-add-reaction.ts +25 -0
- package/src/config/bundled-skills/messaging/tools/slack-leave-channel.ts +23 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +533 -0
- package/src/config/bundled-skills/playbooks/SKILL.md +31 -0
- package/src/config/bundled-skills/playbooks/TOOLS.json +126 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +98 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +54 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +76 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +113 -0
- package/src/config/bundled-skills/public-ingress/SKILL.md +200 -0
- package/src/config/bundled-skills/reminder/SKILL.md +20 -0
- package/src/config/bundled-skills/reminder/TOOLS.json +67 -0
- package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +9 -0
- package/src/config/bundled-skills/reminder/tools/reminder-create.ts +9 -0
- package/src/config/bundled-skills/reminder/tools/reminder-list.ts +9 -0
- package/src/config/bundled-skills/schedule/SKILL.md +74 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +135 -0
- package/src/config/bundled-skills/schedule/tools/schedule-create.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-list.ts +9 -0
- package/src/config/bundled-skills/schedule/tools/schedule-update.ts +9 -0
- package/src/config/bundled-skills/self-upgrade/SKILL.md +68 -0
- package/src/config/bundled-skills/start-the-day/SKILL.md +70 -0
- package/src/config/bundled-skills/start-the-day/icon.svg +13 -0
- package/src/config/bundled-skills/subagent/SKILL.md +25 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +107 -0
- package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-message.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-read.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +9 -0
- package/src/config/bundled-skills/subagent/tools/subagent-status.ts +9 -0
- package/src/config/bundled-skills/tasks/SKILL.md +28 -0
- package/src/config/bundled-skills/tasks/TOOLS.json +281 -0
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-list.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-run.ts +9 -0
- package/src/config/bundled-skills/tasks/tools/task-save.ts +9 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +25 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +32 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +370 -0
- package/src/config/bundled-skills/twitter/SKILL.md +220 -0
- package/src/config/bundled-skills/watcher/SKILL.md +27 -0
- package/src/config/bundled-skills/watcher/TOOLS.json +147 -0
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +9 -0
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +9 -0
- package/src/config/bundled-skills/weather/SKILL.md +37 -0
- package/src/config/bundled-skills/weather/TOOLS.json +32 -0
- package/src/config/bundled-skills/weather/icon.svg +24 -0
- package/src/config/bundled-skills/weather/tools/get-weather.ts +9 -0
- package/src/config/computer-use-prompt.ts +97 -0
- package/src/config/defaults.ts +263 -0
- package/src/config/loader.ts +339 -0
- package/src/config/schema.ts +1436 -0
- package/src/config/skill-state.ts +95 -0
- package/src/config/skills.ts +972 -0
- package/src/config/system-prompt.ts +675 -0
- package/src/config/templates/BOOTSTRAP.md +70 -0
- package/src/config/templates/IDENTITY.md +25 -0
- package/src/config/templates/LOOKS.md +25 -0
- package/src/config/templates/SOUL.md +37 -0
- package/src/config/templates/USER.md +19 -0
- package/src/config/types.ts +42 -0
- package/src/config/vellum-skills/chatgpt-import/SKILL.md +24 -0
- package/src/config/vellum-skills/chatgpt-import/TOOLS.json +23 -0
- package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +284 -0
- package/src/config/vellum-skills/deploy-fullstack-vercel/SKILL.md +179 -0
- package/src/config/vellum-skills/document-writer/SKILL.md +195 -0
- package/src/config/vellum-skills/google-oauth-setup/SKILL.md +199 -0
- package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +153 -0
- package/src/config/vellum-skills/telegram-setup/SKILL.md +143 -0
- package/src/config/vellum-skills/twilio-setup/SKILL.md +213 -0
- package/src/contacts/contact-store.ts +410 -0
- package/src/contacts/index.ts +11 -0
- package/src/contacts/types.ts +28 -0
- package/src/context/token-estimator.ts +108 -0
- package/src/context/tool-result-truncation.ts +128 -0
- package/src/context/window-manager.ts +531 -0
- package/src/daemon/assistant-attachments.ts +691 -0
- package/src/daemon/classifier.ts +110 -0
- package/src/daemon/computer-use-session.ts +903 -0
- package/src/daemon/connection-policy.ts +41 -0
- package/src/daemon/date-context.ts +136 -0
- package/src/daemon/handlers/apps.ts +530 -0
- package/src/daemon/handlers/browser.ts +54 -0
- package/src/daemon/handlers/computer-use.ts +187 -0
- package/src/daemon/handlers/config.ts +1517 -0
- package/src/daemon/handlers/diagnostics.ts +338 -0
- package/src/daemon/handlers/documents.ts +173 -0
- package/src/daemon/handlers/home-base.ts +78 -0
- package/src/daemon/handlers/identity.ts +127 -0
- package/src/daemon/handlers/index.ts +129 -0
- package/src/daemon/handlers/misc.ts +331 -0
- package/src/daemon/handlers/open-bundle-handler.ts +80 -0
- package/src/daemon/handlers/publish.ts +187 -0
- package/src/daemon/handlers/sessions.ts +555 -0
- package/src/daemon/handlers/shared.ts +570 -0
- package/src/daemon/handlers/signing.ts +37 -0
- package/src/daemon/handlers/skills.ts +486 -0
- package/src/daemon/handlers/subagents.ts +210 -0
- package/src/daemon/handlers/twitter-auth.ts +198 -0
- package/src/daemon/handlers/work-items.ts +632 -0
- package/src/daemon/handlers/workspace-files.ts +75 -0
- package/src/daemon/handlers.ts +17 -0
- package/src/daemon/history-repair.ts +214 -0
- package/src/daemon/ipc-blob-store.ts +231 -0
- package/src/daemon/ipc-contract-inventory.json +495 -0
- package/src/daemon/ipc-contract-inventory.ts +126 -0
- package/src/daemon/ipc-contract.ts +2551 -0
- package/src/daemon/ipc-protocol.ts +75 -0
- package/src/daemon/ipc-validate.ts +188 -0
- package/src/daemon/lifecycle.ts +582 -0
- package/src/daemon/main.ts +21 -0
- package/src/daemon/media-visibility-policy.ts +57 -0
- package/src/daemon/ride-shotgun-handler.ts +309 -0
- package/src/daemon/server.ts +1215 -0
- package/src/daemon/session-agent-loop.ts +922 -0
- package/src/daemon/session-attachments.ts +196 -0
- package/src/daemon/session-conflict-gate.ts +184 -0
- package/src/daemon/session-dynamic-profile.ts +63 -0
- package/src/daemon/session-error.ts +290 -0
- package/src/daemon/session-evictor.ts +196 -0
- package/src/daemon/session-history.ts +437 -0
- package/src/daemon/session-lifecycle.ts +147 -0
- package/src/daemon/session-media-retry.ts +147 -0
- package/src/daemon/session-memory.ts +212 -0
- package/src/daemon/session-messaging.ts +145 -0
- package/src/daemon/session-notifiers.ts +193 -0
- package/src/daemon/session-process.ts +323 -0
- package/src/daemon/session-queue-manager.ts +82 -0
- package/src/daemon/session-runtime-assembly.ts +447 -0
- package/src/daemon/session-skill-tools.ts +356 -0
- package/src/daemon/session-slash.ts +305 -0
- package/src/daemon/session-surfaces.ts +702 -0
- package/src/daemon/session-tool-setup.ts +523 -0
- package/src/daemon/session-usage.ts +72 -0
- package/src/daemon/session-workspace.ts +19 -0
- package/src/daemon/session.ts +400 -0
- package/src/daemon/tls-certs.ts +189 -0
- package/src/daemon/trace-emitter.ts +82 -0
- package/src/daemon/video-thumbnail.ts +62 -0
- package/src/daemon/watch-handler.ts +274 -0
- package/src/doordash/client.ts +999 -0
- package/src/doordash/queries.ts +1311 -0
- package/src/doordash/query-extractor.ts +93 -0
- package/src/doordash/session.ts +82 -0
- package/src/email/provider.ts +117 -0
- package/src/email/providers/agentmail.ts +317 -0
- package/src/email/providers/index.ts +58 -0
- package/src/email/service.ts +303 -0
- package/src/email/types.ts +126 -0
- package/src/events/bus.ts +157 -0
- package/src/events/domain-events.ts +83 -0
- package/src/events/index.ts +18 -0
- package/src/events/tool-audit-listener.ts +80 -0
- package/src/events/tool-domain-event-publisher.ts +111 -0
- package/src/events/tool-metrics-listener.ts +159 -0
- package/src/events/tool-notification-listener.ts +17 -0
- package/src/events/tool-profiling-listener.ts +158 -0
- package/src/events/tool-trace-listener.ts +75 -0
- package/src/export/formatter.ts +98 -0
- package/src/followups/followup-store.ts +168 -0
- package/src/followups/index.ts +10 -0
- package/src/followups/types.ts +29 -0
- package/src/gallery/default-gallery.ts +795 -0
- package/src/gallery/gallery-manifest.ts +24 -0
- package/src/home-base/app-link-store.ts +82 -0
- package/src/home-base/bootstrap.ts +68 -0
- package/src/home-base/prebuilt/index.html +662 -0
- package/src/home-base/prebuilt/seed-metadata.json +21 -0
- package/src/home-base/prebuilt/seed.ts +112 -0
- package/src/home-base/prebuilt-home-base-updater.ts +30 -0
- package/src/hooks/cli.ts +163 -0
- package/src/hooks/config.ts +88 -0
- package/src/hooks/discovery.ts +110 -0
- package/src/hooks/manager.ts +124 -0
- package/src/hooks/runner.ts +123 -0
- package/src/hooks/templates.ts +52 -0
- package/src/hooks/types.ts +72 -0
- package/src/inbound/public-ingress-urls.ts +123 -0
- package/src/index.ts +81 -0
- package/src/instrument.ts +60 -0
- package/src/logfire.ts +99 -0
- package/src/media/gemini-image-service.ts +136 -0
- package/src/memory/account-store.ts +108 -0
- package/src/memory/admin.ts +211 -0
- package/src/memory/app-git-service.ts +295 -0
- package/src/memory/app-store.ts +577 -0
- package/src/memory/attachments-store.ts +397 -0
- package/src/memory/channel-delivery-store.ts +353 -0
- package/src/memory/channel-guardian-store.ts +669 -0
- package/src/memory/checkpoints.ts +52 -0
- package/src/memory/clarification-resolver.ts +298 -0
- package/src/memory/conflict-intent.ts +157 -0
- package/src/memory/conflict-policy.ts +73 -0
- package/src/memory/conflict-store.ts +350 -0
- package/src/memory/contradiction-checker.ts +358 -0
- package/src/memory/conversation-key-store.ts +122 -0
- package/src/memory/conversation-store.ts +470 -0
- package/src/memory/db.ts +1991 -0
- package/src/memory/embedding-backend.ts +229 -0
- package/src/memory/embedding-gemini.ts +52 -0
- package/src/memory/embedding-local.ts +65 -0
- package/src/memory/embedding-ollama.ts +55 -0
- package/src/memory/embedding-openai.ts +25 -0
- package/src/memory/entity-extractor.ts +474 -0
- package/src/memory/external-conversation-store.ts +234 -0
- package/src/memory/fingerprint.ts +20 -0
- package/src/memory/indexer.ts +156 -0
- package/src/memory/items-extractor.ts +461 -0
- package/src/memory/job-handlers/backfill.ts +139 -0
- package/src/memory/job-handlers/cleanup.ts +58 -0
- package/src/memory/job-handlers/conflict.ts +141 -0
- package/src/memory/job-handlers/embedding.ts +61 -0
- package/src/memory/job-handlers/extraction.ts +123 -0
- package/src/memory/job-handlers/index-maintenance.ts +54 -0
- package/src/memory/job-handlers/summarization.ts +286 -0
- package/src/memory/job-utils.ts +170 -0
- package/src/memory/jobs-store.ts +401 -0
- package/src/memory/jobs-worker.ts +313 -0
- package/src/memory/llm-request-log-store.ts +45 -0
- package/src/memory/llm-usage-store.ts +60 -0
- package/src/memory/message-content.ts +54 -0
- package/src/memory/profile-compiler.ts +160 -0
- package/src/memory/published-pages-store.ts +137 -0
- package/src/memory/qdrant-client.ts +366 -0
- package/src/memory/qdrant-manager.ts +242 -0
- package/src/memory/query-builder.ts +45 -0
- package/src/memory/retrieval-budget.ts +30 -0
- package/src/memory/retriever.ts +653 -0
- package/src/memory/runs-store.ts +305 -0
- package/src/memory/schema.ts +677 -0
- package/src/memory/search/entity.ts +298 -0
- package/src/memory/search/formatting.ts +207 -0
- package/src/memory/search/lexical.ts +227 -0
- package/src/memory/search/ranking.ts +401 -0
- package/src/memory/search/semantic.ts +121 -0
- package/src/memory/search/types.ts +137 -0
- package/src/memory/segmenter.ts +68 -0
- package/src/memory/shared-app-links-store.ts +138 -0
- package/src/memory/tool-usage-store.ts +62 -0
- package/src/messaging/activity-analyzer.ts +76 -0
- package/src/messaging/draft-store.ts +88 -0
- package/src/messaging/index.ts +3 -0
- package/src/messaging/provider-types.ts +80 -0
- package/src/messaging/provider.ts +52 -0
- package/src/messaging/providers/gmail/adapter.ts +193 -0
- package/src/messaging/providers/gmail/client.ts +204 -0
- package/src/messaging/providers/gmail/types.ts +90 -0
- package/src/messaging/providers/slack/adapter.ts +202 -0
- package/src/messaging/providers/slack/client.ts +198 -0
- package/src/messaging/providers/slack/types.ts +119 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +162 -0
- package/src/messaging/providers/telegram-bot/client.ts +104 -0
- package/src/messaging/providers/telegram-bot/types.ts +15 -0
- package/src/messaging/registry.ts +35 -0
- package/src/messaging/style-analyzer.ts +159 -0
- package/src/messaging/thread-summarizer.ts +306 -0
- package/src/messaging/triage-engine.ts +323 -0
- package/src/messaging/types.ts +55 -0
- package/src/permissions/checker.ts +640 -0
- package/src/permissions/defaults.ts +254 -0
- package/src/permissions/prompter.ts +98 -0
- package/src/permissions/secret-prompter.ts +114 -0
- package/src/permissions/shell-identity.ts +227 -0
- package/src/permissions/trust-store.ts +607 -0
- package/src/permissions/types.ts +43 -0
- package/src/permissions/workspace-policy.ts +114 -0
- package/src/playbooks/index.ts +2 -0
- package/src/playbooks/playbook-compiler.ts +90 -0
- package/src/playbooks/types.ts +55 -0
- package/src/providers/anthropic/client.ts +751 -0
- package/src/providers/failover.ts +129 -0
- package/src/providers/fireworks/client.ts +20 -0
- package/src/providers/gemini/client.ts +285 -0
- package/src/providers/ollama/client.ts +30 -0
- package/src/providers/openai/client.ts +337 -0
- package/src/providers/openrouter/client.ts +20 -0
- package/src/providers/ratelimit.ts +93 -0
- package/src/providers/registry.ts +146 -0
- package/src/providers/retry.ts +81 -0
- package/src/providers/stream-timeout.ts +38 -0
- package/src/providers/types.ts +109 -0
- package/src/runtime/assistant-event-hub.ts +157 -0
- package/src/runtime/assistant-event.ts +82 -0
- package/src/runtime/channel-approval-parser.ts +60 -0
- package/src/runtime/channel-approval-types.ts +73 -0
- package/src/runtime/channel-approvals.ts +206 -0
- package/src/runtime/channel-guardian-service.ts +212 -0
- package/src/runtime/gateway-client.ts +58 -0
- package/src/runtime/http-server.ts +1076 -0
- package/src/runtime/http-types.ts +66 -0
- package/src/runtime/routes/app-routes.ts +174 -0
- package/src/runtime/routes/attachment-routes.ts +133 -0
- package/src/runtime/routes/call-routes.ts +190 -0
- package/src/runtime/routes/channel-routes.ts +1404 -0
- package/src/runtime/routes/conversation-routes.ts +352 -0
- package/src/runtime/routes/events-routes.ts +148 -0
- package/src/runtime/routes/run-routes.ts +257 -0
- package/src/runtime/routes/secret-routes.ts +76 -0
- package/src/runtime/run-orchestrator.ts +330 -0
- package/src/schedule/recurrence-engine.ts +162 -0
- package/src/schedule/recurrence-types.ts +67 -0
- package/src/schedule/schedule-store.ts +506 -0
- package/src/schedule/scheduler.ts +171 -0
- package/src/security/encrypted-store.ts +238 -0
- package/src/security/keychain.ts +252 -0
- package/src/security/oauth-callback-registry.ts +66 -0
- package/src/security/oauth2.ts +274 -0
- package/src/security/redaction.ts +89 -0
- package/src/security/secret-allowlist.ts +164 -0
- package/src/security/secret-ingress.ts +57 -0
- package/src/security/secret-scanner.ts +550 -0
- package/src/security/secure-keys.ts +180 -0
- package/src/security/token-manager.ts +141 -0
- package/src/services/published-app-updater.ts +69 -0
- package/src/services/vercel-deploy.ts +73 -0
- package/src/skills/active-skill-tools.ts +81 -0
- package/src/skills/clawhub.ts +414 -0
- package/src/skills/include-graph.ts +146 -0
- package/src/skills/managed-store.ts +233 -0
- package/src/skills/path-classifier.ts +128 -0
- package/src/skills/slash-commands.ts +174 -0
- package/src/skills/tool-manifest.ts +165 -0
- package/src/skills/version-hash.ts +110 -0
- package/src/slack/slack-webhook.ts +61 -0
- package/src/subagent/index.ts +19 -0
- package/src/subagent/manager.ts +511 -0
- package/src/subagent/types.ts +69 -0
- package/src/swarm/backend-claude-code.ts +145 -0
- package/src/swarm/index.ts +44 -0
- package/src/swarm/limits.ts +37 -0
- package/src/swarm/orchestrator.ts +279 -0
- package/src/swarm/plan-validator.ts +151 -0
- package/src/swarm/router-planner.ts +100 -0
- package/src/swarm/router-prompts.ts +36 -0
- package/src/swarm/synthesizer.ts +62 -0
- package/src/swarm/types.ts +62 -0
- package/src/swarm/worker-backend.ts +121 -0
- package/src/swarm/worker-prompts.ts +79 -0
- package/src/swarm/worker-runner.ts +164 -0
- package/src/tasks/SPEC.md +139 -0
- package/src/tasks/candidate-store.ts +86 -0
- package/src/tasks/ephemeral-permissions.ts +48 -0
- package/src/tasks/task-compiler.ts +199 -0
- package/src/tasks/task-runner.ts +90 -0
- package/src/tasks/task-scheduler.ts +21 -0
- package/src/tasks/task-store.ts +127 -0
- package/src/tasks/tool-sanitizer.ts +36 -0
- package/src/tools/apps/definitions.ts +59 -0
- package/src/tools/apps/executors.ts +313 -0
- package/src/tools/apps/open-proxy.ts +43 -0
- package/src/tools/apps/registry.ts +16 -0
- package/src/tools/assets/materialize.ts +218 -0
- package/src/tools/assets/search.ts +361 -0
- package/src/tools/browser/__tests__/auth-cache.test.ts +219 -0
- package/src/tools/browser/__tests__/auth-detector.test.ts +362 -0
- package/src/tools/browser/__tests__/jit-auth.test.ts +189 -0
- package/src/tools/browser/api-map.ts +293 -0
- package/src/tools/browser/auth-cache.ts +149 -0
- package/src/tools/browser/auth-detector.ts +347 -0
- package/src/tools/browser/auto-navigate.ts +270 -0
- package/src/tools/browser/browser-execution.ts +980 -0
- package/src/tools/browser/browser-handoff.ts +79 -0
- package/src/tools/browser/browser-manager.ts +715 -0
- package/src/tools/browser/browser-screencast.ts +217 -0
- package/src/tools/browser/headless-browser.ts +450 -0
- package/src/tools/browser/jit-auth.ts +51 -0
- package/src/tools/browser/network-recorder.ts +349 -0
- package/src/tools/browser/network-recording-types.ts +49 -0
- package/src/tools/browser/recording-store.ts +49 -0
- package/src/tools/browser/runtime-check.ts +43 -0
- package/src/tools/browser/x-auto-navigate.ts +207 -0
- package/src/tools/calls/call-end.ts +67 -0
- package/src/tools/calls/call-start.ts +81 -0
- package/src/tools/calls/call-status.ts +81 -0
- package/src/tools/claude-code/claude-code.ts +428 -0
- package/src/tools/computer-use/definitions.ts +443 -0
- package/src/tools/computer-use/registry.ts +22 -0
- package/src/tools/computer-use/request-computer-control.ts +53 -0
- package/src/tools/computer-use/skill-proxy-bridge.ts +28 -0
- package/src/tools/credentials/account-registry.ts +127 -0
- package/src/tools/credentials/broker-types.ts +107 -0
- package/src/tools/credentials/broker.ts +372 -0
- package/src/tools/credentials/domain-policy.ts +51 -0
- package/src/tools/credentials/host-pattern-match.ts +60 -0
- package/src/tools/credentials/metadata-store.ts +335 -0
- package/src/tools/credentials/policy-types.ts +52 -0
- package/src/tools/credentials/policy-validate.ts +80 -0
- package/src/tools/credentials/resolve.ts +122 -0
- package/src/tools/credentials/selection.ts +159 -0
- package/src/tools/credentials/tool-policy.ts +25 -0
- package/src/tools/credentials/vault.ts +657 -0
- package/src/tools/document/document-tool.ts +92 -0
- package/src/tools/document/editor-template.ts +237 -0
- package/src/tools/execution-target.ts +21 -0
- package/src/tools/execution-timeout.ts +49 -0
- package/src/tools/executor.ts +815 -0
- package/src/tools/filesystem/edit.ts +127 -0
- package/src/tools/filesystem/fuzzy-match.ts +202 -0
- package/src/tools/filesystem/read.ts +71 -0
- package/src/tools/filesystem/view-image.ts +199 -0
- package/src/tools/filesystem/write.ts +79 -0
- package/src/tools/followups/followup_create.ts +76 -0
- package/src/tools/followups/followup_list.ts +60 -0
- package/src/tools/followups/followup_resolve.ts +56 -0
- package/src/tools/host-filesystem/edit.ts +125 -0
- package/src/tools/host-filesystem/read.ts +80 -0
- package/src/tools/host-filesystem/write.ts +76 -0
- package/src/tools/host-terminal/cli-discover.ts +180 -0
- package/src/tools/host-terminal/host-shell.ts +191 -0
- package/src/tools/memory/definitions.ts +69 -0
- package/src/tools/memory/handlers.ts +246 -0
- package/src/tools/memory/register.ts +66 -0
- package/src/tools/network/__tests__/web-search.test.ts +427 -0
- package/src/tools/network/domain-normalize.ts +85 -0
- package/src/tools/network/script-proxy/__tests__/logging.test.ts +248 -0
- package/src/tools/network/script-proxy/__tests__/policy.test.ts +234 -0
- package/src/tools/network/script-proxy/__tests__/router.test.ts +76 -0
- package/src/tools/network/script-proxy/certs.ts +237 -0
- package/src/tools/network/script-proxy/connect-tunnel.ts +82 -0
- package/src/tools/network/script-proxy/http-forwarder.ts +151 -0
- package/src/tools/network/script-proxy/index.ts +28 -0
- package/src/tools/network/script-proxy/logging.ts +196 -0
- package/src/tools/network/script-proxy/mitm-handler.ts +269 -0
- package/src/tools/network/script-proxy/policy.ts +152 -0
- package/src/tools/network/script-proxy/router.ts +60 -0
- package/src/tools/network/script-proxy/server.ts +136 -0
- package/src/tools/network/script-proxy/session-manager.ts +534 -0
- package/src/tools/network/script-proxy/types.ts +125 -0
- package/src/tools/network/url-safety.ts +227 -0
- package/src/tools/network/web-fetch.ts +713 -0
- package/src/tools/network/web-search.ts +296 -0
- package/src/tools/policy-context.ts +29 -0
- package/src/tools/registry.ts +295 -0
- package/src/tools/reminder/reminder-store.ts +148 -0
- package/src/tools/reminder/reminder.ts +80 -0
- package/src/tools/schedule/create.ts +81 -0
- package/src/tools/schedule/delete.ts +28 -0
- package/src/tools/schedule/list.ts +69 -0
- package/src/tools/schedule/update.ts +97 -0
- package/src/tools/shared/filesystem/edit-engine.ts +56 -0
- package/src/tools/shared/filesystem/errors.ts +85 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +215 -0
- package/src/tools/shared/filesystem/format-diff.ts +35 -0
- package/src/tools/shared/filesystem/path-policy.ts +125 -0
- package/src/tools/shared/filesystem/size-guard.ts +41 -0
- package/src/tools/shared/filesystem/types.ts +80 -0
- package/src/tools/shared/shell-output.ts +52 -0
- package/src/tools/skills/delete-managed.ts +60 -0
- package/src/tools/skills/load.ts +139 -0
- package/src/tools/skills/sandbox-runner.ts +279 -0
- package/src/tools/skills/scaffold-managed.ts +150 -0
- package/src/tools/skills/script-contract.ts +6 -0
- package/src/tools/skills/skill-script-runner.ts +86 -0
- package/src/tools/skills/skill-tool-factory.ts +64 -0
- package/src/tools/skills/vellum-catalog.ts +217 -0
- package/src/tools/subagent/abort.ts +33 -0
- package/src/tools/subagent/message.ts +39 -0
- package/src/tools/subagent/read.ts +67 -0
- package/src/tools/subagent/spawn.ts +46 -0
- package/src/tools/subagent/status.ts +45 -0
- package/src/tools/swarm/delegate.ts +183 -0
- package/src/tools/system/request-permission.ts +98 -0
- package/src/tools/system/version.ts +43 -0
- package/src/tools/tasks/index.ts +27 -0
- package/src/tools/tasks/task-delete.ts +82 -0
- package/src/tools/tasks/task-list.ts +44 -0
- package/src/tools/tasks/task-run.ts +97 -0
- package/src/tools/tasks/task-save.ts +47 -0
- package/src/tools/tasks/work-item-enqueue.ts +234 -0
- package/src/tools/tasks/work-item-list.ts +55 -0
- package/src/tools/tasks/work-item-remove.ts +60 -0
- package/src/tools/tasks/work-item-run.ts +78 -0
- package/src/tools/tasks/work-item-update.ts +114 -0
- package/src/tools/terminal/backends/docker.ts +372 -0
- package/src/tools/terminal/backends/native.ts +190 -0
- package/src/tools/terminal/backends/types.ts +26 -0
- package/src/tools/terminal/evaluate-typescript.ts +275 -0
- package/src/tools/terminal/parser.ts +413 -0
- package/src/tools/terminal/safe-env.ts +37 -0
- package/src/tools/terminal/sandbox-diagnostics.ts +149 -0
- package/src/tools/terminal/sandbox.ts +44 -0
- package/src/tools/terminal/shell.ts +257 -0
- package/src/tools/tool-manifest.ts +198 -0
- package/src/tools/types.ts +176 -0
- package/src/tools/ui-surface/definitions.ts +244 -0
- package/src/tools/ui-surface/registry.ts +14 -0
- package/src/tools/watch/screen-watch.ts +130 -0
- package/src/tools/watch/watch-state.ts +119 -0
- package/src/tools/watcher/create.ts +64 -0
- package/src/tools/watcher/delete.ts +27 -0
- package/src/tools/watcher/digest.ts +50 -0
- package/src/tools/watcher/list.ts +60 -0
- package/src/tools/watcher/update.ts +56 -0
- package/src/tools/weather/service.ts +551 -0
- package/src/twitter/client.ts +690 -0
- package/src/twitter/oauth-client.ts +102 -0
- package/src/twitter/router.ts +101 -0
- package/src/twitter/session.ts +91 -0
- package/src/usage/actors.ts +24 -0
- package/src/usage/types.ts +37 -0
- package/src/util/clipboard.ts +33 -0
- package/src/util/content-id.ts +16 -0
- package/src/util/debounce.ts +88 -0
- package/src/util/diff.ts +181 -0
- package/src/util/errors.ts +129 -0
- package/src/util/logger.ts +243 -0
- package/src/util/network-info.ts +47 -0
- package/src/util/platform.ts +632 -0
- package/src/util/pricing.ts +150 -0
- package/src/util/promise-guard.ts +37 -0
- package/src/util/retry.ts +98 -0
- package/src/util/spinner.ts +51 -0
- package/src/util/time.ts +16 -0
- package/src/util/truncate.ts +6 -0
- package/src/util/xml.ts +4 -0
- package/src/version.ts +3 -0
- package/src/watcher/constants.ts +11 -0
- package/src/watcher/engine.ts +199 -0
- package/src/watcher/provider-registry.ts +15 -0
- package/src/watcher/provider-types.ts +48 -0
- package/src/watcher/providers/gmail.ts +198 -0
- package/src/watcher/providers/google-calendar.ts +228 -0
- package/src/watcher/providers/slack.ts +129 -0
- package/src/watcher/watcher-store.ts +419 -0
- package/src/work-items/work-item-runner.ts +171 -0
- package/src/work-items/work-item-store.ts +325 -0
- package/src/workspace/commit-message-enrichment-service.ts +284 -0
- package/src/workspace/commit-message-provider.ts +95 -0
- package/src/workspace/git-service.ts +857 -0
- package/src/workspace/heartbeat-service.ts +345 -0
- package/src/workspace/provider-commit-message-generator.ts +285 -0
- package/src/workspace/top-level-renderer.ts +19 -0
- package/src/workspace/top-level-scanner.ts +41 -0
- package/src/workspace/turn-commit.ts +175 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../types.js';
|
|
2
|
+
import { listWorkItems, type WorkItem, type WorkItemStatus } from '../../work-items/work-item-store.js';
|
|
3
|
+
|
|
4
|
+
const PRIORITY_LABELS: Record<number, string> = { 0: 'High', 1: 'Medium', 2: 'Low' };
|
|
5
|
+
|
|
6
|
+
function formatTaskList(items: WorkItem[]): string {
|
|
7
|
+
const lines: string[] = [];
|
|
8
|
+
for (const item of items) {
|
|
9
|
+
const priority = PRIORITY_LABELS[item.priorityTier] ?? 'Medium';
|
|
10
|
+
const status = item.status.replace(/_/g, ' ');
|
|
11
|
+
lines.push(`- [${priority}] ${item.title} (${status})`);
|
|
12
|
+
}
|
|
13
|
+
return lines.join('\n');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function executeTaskListShow(
|
|
17
|
+
input: Record<string, unknown>,
|
|
18
|
+
_context: ToolContext,
|
|
19
|
+
): Promise<ToolExecutionResult> {
|
|
20
|
+
try {
|
|
21
|
+
const statusFilter = input.status as string | string[] | undefined;
|
|
22
|
+
|
|
23
|
+
let items;
|
|
24
|
+
if (typeof statusFilter === 'string') {
|
|
25
|
+
items = listWorkItems({ status: statusFilter as WorkItemStatus });
|
|
26
|
+
} else if (Array.isArray(statusFilter)) {
|
|
27
|
+
// listWorkItems only supports a single status filter, so we fetch all
|
|
28
|
+
// and filter client-side when an array is provided
|
|
29
|
+
const allItems = listWorkItems();
|
|
30
|
+
const allowed = new Set(statusFilter);
|
|
31
|
+
items = allItems.filter((item) => allowed.has(item.status));
|
|
32
|
+
} else {
|
|
33
|
+
items = listWorkItems();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const count = items.length;
|
|
37
|
+
const filtered = statusFilter !== undefined;
|
|
38
|
+
|
|
39
|
+
if (count === 0) {
|
|
40
|
+
const suffix = filtered ? 'no items matching filter.' : 'no tasks queued.';
|
|
41
|
+
return { content: `Opened Tasks window \u2014 ${suffix}`, isError: false };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const label = filtered
|
|
45
|
+
? `${count} ${Array.isArray(statusFilter) ? 'matching' : statusFilter} item${count === 1 ? '' : 's'}`
|
|
46
|
+
: `${count} item${count === 1 ? '' : 's'}`;
|
|
47
|
+
|
|
48
|
+
const taskList = formatTaskList(items);
|
|
49
|
+
|
|
50
|
+
return { content: `Opened Tasks window (${label}).\n\nCurrent tasks:\n${taskList}`, isError: false };
|
|
51
|
+
} catch (err) {
|
|
52
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
53
|
+
return { content: `Error: ${msg}`, isError: true };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../types.js';
|
|
2
|
+
import { resolveWorkItem, removeWorkItemFromQueue, identifyEntityById, buildTaskTemplateMismatchError, type WorkItemStatus } from '../../work-items/work-item-store.js';
|
|
3
|
+
import { getLogger } from '../../util/logger.js';
|
|
4
|
+
|
|
5
|
+
const log = getLogger('task-list-remove');
|
|
6
|
+
|
|
7
|
+
export async function executeTaskListRemove(
|
|
8
|
+
input: Record<string, unknown>,
|
|
9
|
+
_context: ToolContext,
|
|
10
|
+
): Promise<ToolExecutionResult> {
|
|
11
|
+
const selectorType = input.work_item_id ? 'work_item_id' : input.task_id ? 'task_id' : input.task_name ? 'task_name' : input.title ? 'title' : 'none';
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const selector = {
|
|
15
|
+
workItemId: input.work_item_id as string | undefined,
|
|
16
|
+
taskId: input.task_id as string | undefined,
|
|
17
|
+
title: (input.task_name ?? input.title) as string | undefined,
|
|
18
|
+
priorityTier: input.priority_tier as number | undefined,
|
|
19
|
+
status: input.status as WorkItemStatus | undefined,
|
|
20
|
+
createdOrder: input.created_order as number | undefined,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const resolveResult = resolveWorkItem(selector);
|
|
24
|
+
|
|
25
|
+
if (resolveResult.status === 'not_found') {
|
|
26
|
+
// When the model passes an ID directly, check if it's a task template
|
|
27
|
+
if (selector.workItemId) {
|
|
28
|
+
const entity = identifyEntityById(selector.workItemId);
|
|
29
|
+
if (entity.type === 'task_template') {
|
|
30
|
+
log.warn({ selectorType, inputId: selector.workItemId }, 'task template ID passed as work_item_id');
|
|
31
|
+
return {
|
|
32
|
+
content: `Error: ${buildTaskTemplateMismatchError(selector.workItemId, entity.title!, 'task_delete to delete task templates')}`,
|
|
33
|
+
isError: true,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
log.warn({ selectorType, error: resolveResult.message }, 'work item not found for removal');
|
|
38
|
+
return { content: `Error: ${resolveResult.message}`, isError: true };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (resolveResult.status === 'ambiguous') {
|
|
42
|
+
log.warn({ selectorType, matchCount: resolveResult.matches.length }, 'ambiguous selector for removal');
|
|
43
|
+
return { content: `Error: ${resolveResult.message}`, isError: true };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const item = resolveResult.workItem;
|
|
47
|
+
|
|
48
|
+
log.info({ selectorType, selectorValue: input[selectorType], resolvedWorkItemId: item.id, title: item.title }, 'resolved work item for removal');
|
|
49
|
+
|
|
50
|
+
const removeResult = removeWorkItemFromQueue(item.id);
|
|
51
|
+
|
|
52
|
+
log.info({ resolvedWorkItemId: item.id, deletedCount: 1 }, 'work item removed');
|
|
53
|
+
|
|
54
|
+
return { content: removeResult.message, isError: false };
|
|
55
|
+
} catch (err) {
|
|
56
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
57
|
+
log.error({ selectorType, error: msg }, 'remove failed');
|
|
58
|
+
return { content: `Error: ${msg}`, isError: true };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../types.js';
|
|
2
|
+
import { getWorkItem, listWorkItems, identifyEntityById } from '../../work-items/work-item-store.js';
|
|
3
|
+
import { runWorkItemInBackground } from '../../work-items/work-item-runner.js';
|
|
4
|
+
import { getTask } from '../../tasks/task-store.js';
|
|
5
|
+
|
|
6
|
+
export async function executeTaskQueueRun(
|
|
7
|
+
input: Record<string, unknown>,
|
|
8
|
+
_context: ToolContext,
|
|
9
|
+
): Promise<ToolExecutionResult> {
|
|
10
|
+
const workItemId = input.work_item_id as string | undefined;
|
|
11
|
+
const taskName = input.task_name as string | undefined;
|
|
12
|
+
const title = input.title as string | undefined;
|
|
13
|
+
|
|
14
|
+
if (!workItemId && !taskName && !title) {
|
|
15
|
+
return {
|
|
16
|
+
content: 'Error: Provide work_item_id, task_name, or title to identify the task to run.',
|
|
17
|
+
isError: true,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
let resolvedId: string | undefined;
|
|
23
|
+
|
|
24
|
+
if (workItemId) {
|
|
25
|
+
const item = getWorkItem(workItemId);
|
|
26
|
+
if (!item) {
|
|
27
|
+
const entity = identifyEntityById(workItemId);
|
|
28
|
+
if (entity.type === 'task_template') {
|
|
29
|
+
return {
|
|
30
|
+
content: `Error: "${workItemId}" is a task template ID, not a work item. Use task_list_show to find the work item ID.`,
|
|
31
|
+
isError: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return { content: `Error: No work item found with ID "${workItemId}".`, isError: true };
|
|
35
|
+
}
|
|
36
|
+
resolvedId = item.id;
|
|
37
|
+
} else {
|
|
38
|
+
// Search by task_name or title among active work items
|
|
39
|
+
const needle = (taskName ?? title)!.toLowerCase();
|
|
40
|
+
const allItems = listWorkItems();
|
|
41
|
+
const activeItems = allItems.filter((i) => !['archived', 'done'].includes(i.status));
|
|
42
|
+
const matches = activeItems.filter((i) => i.title.toLowerCase().includes(needle));
|
|
43
|
+
|
|
44
|
+
if (matches.length === 0) {
|
|
45
|
+
return {
|
|
46
|
+
content: `Error: No active work item matching "${taskName ?? title}". Use task_list_show to see your task queue.`,
|
|
47
|
+
isError: true,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (matches.length > 1) {
|
|
52
|
+
const lines = [`Multiple work items match "${taskName ?? title}". Please specify by ID:`, ''];
|
|
53
|
+
for (const m of matches) {
|
|
54
|
+
lines.push(`- ${m.title} (ID: ${m.id}, status: ${m.status})`);
|
|
55
|
+
}
|
|
56
|
+
return { content: lines.join('\n'), isError: true };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
resolvedId = matches[0].id;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const result = runWorkItemInBackground(resolvedId);
|
|
63
|
+
|
|
64
|
+
if (!result.success) {
|
|
65
|
+
return { content: `Error: ${result.error}`, isError: true };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const item = getWorkItem(resolvedId)!;
|
|
69
|
+
const task = getTask(item.taskId);
|
|
70
|
+
return {
|
|
71
|
+
content: `Started running task "${item.title}"${task ? ` (template: ${task.title})` : ''}. It will execute in the background. Use task_list_show to check progress.`,
|
|
72
|
+
isError: false,
|
|
73
|
+
};
|
|
74
|
+
} catch (err) {
|
|
75
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
76
|
+
return { content: `Error: ${msg}`, isError: true };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { ToolContext, ToolExecutionResult } from '../types.js';
|
|
2
|
+
import { resolveWorkItem, updateWorkItem, identifyEntityById, buildTaskTemplateMismatchError, type WorkItemStatus } from '../../work-items/work-item-store.js';
|
|
3
|
+
import { getLogger } from '../../util/logger.js';
|
|
4
|
+
|
|
5
|
+
const log = getLogger('task-list-update');
|
|
6
|
+
|
|
7
|
+
const PRIORITY_LABELS: Record<number, string> = {
|
|
8
|
+
0: 'high',
|
|
9
|
+
1: 'medium',
|
|
10
|
+
2: 'low',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function executeTaskListUpdate(
|
|
14
|
+
input: Record<string, unknown>,
|
|
15
|
+
_context: ToolContext,
|
|
16
|
+
): Promise<ToolExecutionResult> {
|
|
17
|
+
const selectorType = input.work_item_id ? 'work_item_id' : input.task_id ? 'task_id' : input.task_name ? 'task_name' : input.title ? 'title' : 'none';
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
// Build selector from whichever identifier was provided
|
|
21
|
+
const selector = {
|
|
22
|
+
workItemId: input.work_item_id as string | undefined,
|
|
23
|
+
taskId: input.task_id as string | undefined,
|
|
24
|
+
title: (input.task_name ?? input.title) as string | undefined,
|
|
25
|
+
priorityTier: input.filter_priority_tier as number | undefined,
|
|
26
|
+
status: input.filter_status as WorkItemStatus | undefined,
|
|
27
|
+
createdOrder: input.created_order as number | undefined,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Resolve the target work item
|
|
31
|
+
const result = resolveWorkItem(selector);
|
|
32
|
+
|
|
33
|
+
if (result.status === 'not_found') {
|
|
34
|
+
// When the model passes an ID directly, check if it's a task template
|
|
35
|
+
if (selector.workItemId) {
|
|
36
|
+
const entity = identifyEntityById(selector.workItemId);
|
|
37
|
+
if (entity.type === 'task_template') {
|
|
38
|
+
log.warn({ selectorType, inputId: selector.workItemId }, 'task template ID passed as work_item_id');
|
|
39
|
+
return {
|
|
40
|
+
content: `Error: ${buildTaskTemplateMismatchError(selector.workItemId, entity.title!, 'task_delete to remove task templates, or task_list to view them')}`,
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
log.warn({ selectorType, error: result.message }, 'work item not found for update');
|
|
46
|
+
return { content: `Error: ${result.message}`, isError: true };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (result.status === 'ambiguous') {
|
|
50
|
+
log.warn({ selectorType, matchCount: result.matches.length }, 'ambiguous selector for update');
|
|
51
|
+
return { content: `Error: ${result.message}`, isError: true };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const item = result.workItem;
|
|
55
|
+
|
|
56
|
+
// Block direct transitions to 'done' — the only path to done is
|
|
57
|
+
// through the Review action (handleWorkItemComplete in the daemon).
|
|
58
|
+
if (input.status === 'done') {
|
|
59
|
+
log.warn({ selectorType, resolvedWorkItemId: item.id }, 'rejected attempt to set status to done directly');
|
|
60
|
+
return {
|
|
61
|
+
content: 'Error: Cannot set status to \'done\' directly. Use the Review action in the Tasks window.',
|
|
62
|
+
isError: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
log.info({ selectorType, selectorValue: input[selectorType], resolvedWorkItemId: item.id }, 'resolved work item for update');
|
|
67
|
+
|
|
68
|
+
// Build updates from provided fields
|
|
69
|
+
const updates: Partial<{
|
|
70
|
+
priorityTier: number;
|
|
71
|
+
notes: string;
|
|
72
|
+
status: WorkItemStatus;
|
|
73
|
+
sortIndex: number;
|
|
74
|
+
}> = {};
|
|
75
|
+
if (input.priority_tier !== undefined) updates.priorityTier = input.priority_tier as number;
|
|
76
|
+
if (input.notes !== undefined) updates.notes = input.notes as string;
|
|
77
|
+
if (input.status !== undefined) updates.status = input.status as WorkItemStatus;
|
|
78
|
+
if (input.sort_index !== undefined) updates.sortIndex = input.sort_index as number;
|
|
79
|
+
|
|
80
|
+
if (Object.keys(updates).length === 0) {
|
|
81
|
+
log.warn({ selectorType, resolvedWorkItemId: item.id }, 'update called with no fields to update');
|
|
82
|
+
return {
|
|
83
|
+
content: 'No updates specified. Provide at least one field to update (priority_tier, notes, status, sort_index).',
|
|
84
|
+
isError: true,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const updated = updateWorkItem(item.id, updates);
|
|
89
|
+
if (!updated) {
|
|
90
|
+
log.error({ selectorType, resolvedWorkItemId: item.id, updates }, 'updateWorkItem returned null');
|
|
91
|
+
return {
|
|
92
|
+
content: `Error: Failed to update work item "${item.title}".`,
|
|
93
|
+
isError: true,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
log.info({ resolvedWorkItemId: item.id, updatedFields: Object.keys(updates) }, 'work item updated');
|
|
98
|
+
|
|
99
|
+
// Build confirmation message
|
|
100
|
+
const parts: string[] = [`Updated "${updated.title}"`];
|
|
101
|
+
if (input.priority_tier !== undefined) {
|
|
102
|
+
parts.push(`priority → ${PRIORITY_LABELS[updated.priorityTier] ?? updated.priorityTier}`);
|
|
103
|
+
}
|
|
104
|
+
if (input.notes !== undefined) parts.push('notes updated');
|
|
105
|
+
if (input.status !== undefined) parts.push(`status → ${updated.status}`);
|
|
106
|
+
if (input.sort_index !== undefined) parts.push(`sort index → ${updated.sortIndex}`);
|
|
107
|
+
|
|
108
|
+
return { content: parts.join(', ') + '.', isError: false };
|
|
109
|
+
} catch (err) {
|
|
110
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
111
|
+
log.error({ selectorType, error: msg }, 'update failed');
|
|
112
|
+
return { content: `Error: ${msg}`, isError: true };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
3
|
+
import { dirname, resolve, relative, posix } from 'node:path';
|
|
4
|
+
import { ToolError } from '../../../util/errors.js';
|
|
5
|
+
import { getLogger } from '../../../util/logger.js';
|
|
6
|
+
import type { DockerConfig } from '../../../config/types.js';
|
|
7
|
+
import type { SandboxBackend, SandboxResult, WrapOptions } from './types.js';
|
|
8
|
+
|
|
9
|
+
const log = getLogger('docker-sandbox');
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_SANDBOX_IMAGE = 'vellum-sandbox:latest';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Fallback defaults when DockerBackend is constructed without explicit config.
|
|
15
|
+
* Must stay in sync with DockerConfigSchema defaults in config/schema.ts.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULTS: Required<DockerConfig> = {
|
|
18
|
+
image: DEFAULT_SANDBOX_IMAGE,
|
|
19
|
+
shell: 'bash',
|
|
20
|
+
cpus: 1,
|
|
21
|
+
memoryMb: 512,
|
|
22
|
+
pidsLimit: 256,
|
|
23
|
+
network: 'none',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Characters that are dangerous in Docker mount arguments or shell commands.
|
|
28
|
+
* Commas are included because Docker's --mount flag uses them as field
|
|
29
|
+
* delimiters — a path containing a comma could inject extra key=value pairs
|
|
30
|
+
* (e.g. overriding dst= or src=) into the mount specification.
|
|
31
|
+
*/
|
|
32
|
+
const UNSAFE_PATH_CHARS = /[\x00\n\r,]/;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Cache positive preflight results only, matching the bwrap pattern in native.ts.
|
|
36
|
+
* Negative results are not cached so that installing/starting Docker after the
|
|
37
|
+
* daemon starts takes effect without a restart.
|
|
38
|
+
*/
|
|
39
|
+
let dockerCliAvailable = false;
|
|
40
|
+
let dockerDaemonReachable = false;
|
|
41
|
+
const imageAvailableCache = new Set<string>();
|
|
42
|
+
const mountProbeCache = new Set<string>();
|
|
43
|
+
/** Maps image → resolved shell path (e.g. 'bash' → 'bash', or fell back to 'sh'). */
|
|
44
|
+
const shellResolvedCache = new Map<string, string>();
|
|
45
|
+
|
|
46
|
+
/** Exported for tests to reset cached state between runs. */
|
|
47
|
+
export function _resetDockerChecks(): void {
|
|
48
|
+
dockerCliAvailable = false;
|
|
49
|
+
dockerDaemonReachable = false;
|
|
50
|
+
imageAvailableCache.clear();
|
|
51
|
+
mountProbeCache.clear();
|
|
52
|
+
shellResolvedCache.clear();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function checkDockerCli(): void {
|
|
56
|
+
if (dockerCliAvailable) return;
|
|
57
|
+
try {
|
|
58
|
+
execFileSync('docker', ['--version'], { stdio: 'ignore', timeout: 5000 });
|
|
59
|
+
dockerCliAvailable = true;
|
|
60
|
+
} catch {
|
|
61
|
+
throw new ToolError(
|
|
62
|
+
'Docker CLI is not installed or not in PATH. Install Docker: https://docs.docker.com/get-docker/',
|
|
63
|
+
'bash',
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function checkDockerDaemon(): void {
|
|
69
|
+
if (dockerDaemonReachable) return;
|
|
70
|
+
try {
|
|
71
|
+
execFileSync('docker', ['info'], { stdio: 'ignore', timeout: 10000 });
|
|
72
|
+
dockerDaemonReachable = true;
|
|
73
|
+
} catch {
|
|
74
|
+
throw new ToolError(
|
|
75
|
+
'Docker daemon is not running. Start Docker Desktop or run "sudo systemctl start docker".',
|
|
76
|
+
'bash',
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Resolve the path to Dockerfile.sandbox relative to this source file.
|
|
83
|
+
* Works in both development (source layout) and bundled environments.
|
|
84
|
+
*
|
|
85
|
+
* In compiled Bun binaries, import.meta.dirname resolves into the virtual
|
|
86
|
+
* $bunfs filesystem, so the Dockerfile won't exist there. Fall back to
|
|
87
|
+
* looking next to the compiled binary (process.execPath) in that case.
|
|
88
|
+
*/
|
|
89
|
+
function getSandboxDockerfilePath(): string {
|
|
90
|
+
const dir = import.meta.dirname ?? __dirname;
|
|
91
|
+
const sourcePath = resolve(dir, '../../../../Dockerfile.sandbox');
|
|
92
|
+
|
|
93
|
+
// In compiled Bun binaries, dir points into /$bunfs/ which is virtual.
|
|
94
|
+
// Fall back to looking next to the compiled binary itself.
|
|
95
|
+
if (!existsSync(sourcePath) && dir.startsWith('/$bunfs/')) {
|
|
96
|
+
return resolve(dirname(process.execPath), 'Dockerfile.sandbox');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return sourcePath;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function checkImageAvailable(image: string): void {
|
|
103
|
+
if (imageAvailableCache.has(image)) return;
|
|
104
|
+
try {
|
|
105
|
+
// Use execFileSync to avoid shell interpolation of the image name.
|
|
106
|
+
execFileSync('docker', ['image', 'inspect', image], { stdio: 'ignore', timeout: 10000 });
|
|
107
|
+
imageAvailableCache.add(image);
|
|
108
|
+
return;
|
|
109
|
+
} catch {
|
|
110
|
+
// Image not available locally — try to build or pull it.
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// For the default sandbox image, build from Dockerfile.sandbox instead of pulling.
|
|
114
|
+
if (image === DEFAULT_SANDBOX_IMAGE) {
|
|
115
|
+
const dockerfile = getSandboxDockerfilePath();
|
|
116
|
+
if (existsSync(dockerfile)) {
|
|
117
|
+
log.info(`Building sandbox image "${image}" from ${dockerfile}...`);
|
|
118
|
+
try {
|
|
119
|
+
// --no-cache avoids stale apt-get layers with expired GPG signatures.
|
|
120
|
+
execFileSync('docker', ['build', '--no-cache', '-t', image, '-f', dockerfile, '.'], {
|
|
121
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
122
|
+
timeout: 120000,
|
|
123
|
+
cwd: resolve(dockerfile, '..'),
|
|
124
|
+
});
|
|
125
|
+
imageAvailableCache.add(image);
|
|
126
|
+
return;
|
|
127
|
+
} catch (err: unknown) {
|
|
128
|
+
const stderr = err instanceof Error && 'stderr' in err
|
|
129
|
+
? String((err as { stderr: unknown }).stderr).trim()
|
|
130
|
+
: '';
|
|
131
|
+
const detail = stderr ? `\n\nBuild output:\n${stderr}` : '';
|
|
132
|
+
throw new ToolError(
|
|
133
|
+
`Failed to build sandbox image "${image}" from ${dockerfile}. ` +
|
|
134
|
+
'Check Docker is running and try building manually: ' +
|
|
135
|
+
`docker build --no-cache -t ${image} -f ${dockerfile} ${resolve(dockerfile, '..')}` +
|
|
136
|
+
detail,
|
|
137
|
+
'bash',
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Dockerfile not found — can't build the local-only image and pulling won't work.
|
|
143
|
+
throw new ToolError(
|
|
144
|
+
`Cannot find Dockerfile.sandbox to build "${image}". ` +
|
|
145
|
+
'This image is built locally and is not available from a registry. ' +
|
|
146
|
+
'If you have the Vellum source tree, build it manually:\n' +
|
|
147
|
+
' docker build --no-cache -t vellum-sandbox:latest -f assistant/Dockerfile.sandbox assistant\n' +
|
|
148
|
+
'Or set sandbox.docker.image to a different image in your config.',
|
|
149
|
+
'bash',
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
log.info(`Docker image "${image}" not found locally, pulling...`);
|
|
154
|
+
try {
|
|
155
|
+
execFileSync('docker', ['pull', image], { stdio: 'ignore', timeout: 120000 });
|
|
156
|
+
imageAvailableCache.add(image);
|
|
157
|
+
} catch {
|
|
158
|
+
throw new ToolError(
|
|
159
|
+
`Failed to pull Docker image "${image}". Check your network connection or pull it manually: docker pull ${image}`,
|
|
160
|
+
'bash',
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function checkMountProbe(sandboxRoot: string, image: string): void {
|
|
166
|
+
const cacheKey = `${sandboxRoot}\0${image}`;
|
|
167
|
+
if (mountProbeCache.has(cacheKey)) return;
|
|
168
|
+
try {
|
|
169
|
+
execFileSync(
|
|
170
|
+
'docker',
|
|
171
|
+
[
|
|
172
|
+
'run', '--rm',
|
|
173
|
+
'--mount', `type=bind,src=${sandboxRoot},dst=/workspace`,
|
|
174
|
+
image, 'test', '-w', '/workspace',
|
|
175
|
+
],
|
|
176
|
+
{ stdio: 'ignore', timeout: 15000 },
|
|
177
|
+
);
|
|
178
|
+
mountProbeCache.add(cacheKey);
|
|
179
|
+
} catch {
|
|
180
|
+
throw new ToolError(
|
|
181
|
+
'Cannot bind-mount the sandbox root into a Docker container or /workspace is not writable. ' +
|
|
182
|
+
'If using Docker Desktop, enable file sharing for this path in Settings > Resources > File Sharing.',
|
|
183
|
+
'bash',
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Verify the configured shell exists in the image. If the requested shell
|
|
190
|
+
* (e.g. 'bash') is missing, fall back to 'sh' which is available on virtually
|
|
191
|
+
* every Linux image. If neither exists the image is too minimal to use.
|
|
192
|
+
*/
|
|
193
|
+
function resolveShell(image: string, shell: string): string {
|
|
194
|
+
const cacheKey = `${image}\0${shell}`;
|
|
195
|
+
const cached = shellResolvedCache.get(cacheKey);
|
|
196
|
+
if (cached) return cached;
|
|
197
|
+
|
|
198
|
+
// Try the configured shell first.
|
|
199
|
+
try {
|
|
200
|
+
execFileSync('docker', ['run', '--rm', image, shell, '-c', 'true'], {
|
|
201
|
+
stdio: 'ignore',
|
|
202
|
+
timeout: 15000,
|
|
203
|
+
});
|
|
204
|
+
shellResolvedCache.set(cacheKey, shell);
|
|
205
|
+
return shell;
|
|
206
|
+
} catch {
|
|
207
|
+
// configured shell not available — try sh fallback
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (shell === 'sh') {
|
|
211
|
+
throw new ToolError(
|
|
212
|
+
`Shell "sh" is not available in Docker image "${image}". The image may be too minimal for sandbox use.`,
|
|
213
|
+
'bash',
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
execFileSync('docker', ['run', '--rm', image, 'sh', '-c', 'true'], {
|
|
219
|
+
stdio: 'ignore',
|
|
220
|
+
timeout: 15000,
|
|
221
|
+
});
|
|
222
|
+
log.warn(`Shell "${shell}" not found in image "${image}", falling back to "sh"`);
|
|
223
|
+
shellResolvedCache.set(cacheKey, 'sh');
|
|
224
|
+
return 'sh';
|
|
225
|
+
} catch {
|
|
226
|
+
throw new ToolError(
|
|
227
|
+
`Neither "${shell}" nor "sh" is available in Docker image "${image}". ` +
|
|
228
|
+
'Choose a different image or set sandbox.docker.shell to a shell that exists in the image.',
|
|
229
|
+
'bash',
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Validate that a path is safe to use in Docker mount arguments.
|
|
236
|
+
* Rejects paths containing null bytes, newlines, or carriage returns which
|
|
237
|
+
* could cause argument injection or parsing issues.
|
|
238
|
+
*/
|
|
239
|
+
function validatePathSafety(path: string, label: string): void {
|
|
240
|
+
if (UNSAFE_PATH_CHARS.test(path)) {
|
|
241
|
+
throw new ToolError(
|
|
242
|
+
`${label} contains characters that are unsafe for Docker mount arguments. ` +
|
|
243
|
+
'Refusing to execute. Remove null bytes, newlines, carriage returns, or commas from the path.',
|
|
244
|
+
'bash',
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Docker sandbox backend that wraps commands in ephemeral containers.
|
|
251
|
+
*
|
|
252
|
+
* Each invocation produces a single `docker run --rm` command — no long-lived
|
|
253
|
+
* container state. The sandbox filesystem root is bind-mounted to /workspace
|
|
254
|
+
* and the host UID:GID is forwarded to prevent permission drift.
|
|
255
|
+
*
|
|
256
|
+
* On first use, runs preflight checks (CLI, daemon, image, mount probe) and
|
|
257
|
+
* fails closed with actionable error messages if any check fails.
|
|
258
|
+
*/
|
|
259
|
+
export class DockerBackend implements SandboxBackend {
|
|
260
|
+
private readonly sandboxRoot: string;
|
|
261
|
+
private readonly config: Required<DockerConfig>;
|
|
262
|
+
private readonly uid: number;
|
|
263
|
+
private readonly gid: number;
|
|
264
|
+
|
|
265
|
+
constructor(
|
|
266
|
+
sandboxRoot: string,
|
|
267
|
+
config?: Partial<Required<DockerConfig>>,
|
|
268
|
+
uid?: number,
|
|
269
|
+
gid?: number,
|
|
270
|
+
) {
|
|
271
|
+
// Resolve to an absolute path first, then follow symlinks.
|
|
272
|
+
// This prevents path traversal via ../.. or symlink tricks.
|
|
273
|
+
const resolved = resolve(sandboxRoot);
|
|
274
|
+
this.sandboxRoot = realpathSync(resolved);
|
|
275
|
+
validatePathSafety(this.sandboxRoot, 'Sandbox root');
|
|
276
|
+
this.config = { ...DEFAULTS, ...config };
|
|
277
|
+
if (uid != null) {
|
|
278
|
+
this.uid = uid;
|
|
279
|
+
} else if (process.getuid) {
|
|
280
|
+
this.uid = process.getuid();
|
|
281
|
+
} else {
|
|
282
|
+
throw new ToolError(
|
|
283
|
+
'Docker sandbox requires POSIX UID/GID APIs (process.getuid/getgid) which are not available on this platform.',
|
|
284
|
+
'bash',
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
this.gid = gid ?? (process.getgid ? process.getgid() : this.uid);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Run preflight checks in dependency order. Each check is cached
|
|
292
|
+
* on success; failures re-check on every call. Returns the resolved
|
|
293
|
+
* shell (may differ from config if the configured shell is missing).
|
|
294
|
+
*/
|
|
295
|
+
preflight(): string {
|
|
296
|
+
checkDockerCli();
|
|
297
|
+
checkDockerDaemon();
|
|
298
|
+
checkImageAvailable(this.config.image);
|
|
299
|
+
checkMountProbe(this.sandboxRoot, this.config.image);
|
|
300
|
+
return resolveShell(this.config.image, this.config.shell);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
wrap(command: string, workingDir: string, options?: WrapOptions): SandboxResult {
|
|
304
|
+
// Preflight: fail closed if Docker is not usable.
|
|
305
|
+
const shell = this.preflight();
|
|
306
|
+
|
|
307
|
+
// Resolve + follow symlinks for the working directory.
|
|
308
|
+
const resolved = resolve(workingDir);
|
|
309
|
+
const realWorkDir = realpathSync(resolved);
|
|
310
|
+
const realRoot = this.sandboxRoot;
|
|
311
|
+
|
|
312
|
+
// Validate path safety for mount/workdir args.
|
|
313
|
+
validatePathSafety(realWorkDir, 'Working directory');
|
|
314
|
+
|
|
315
|
+
// Fail closed: working dir must be inside sandbox root.
|
|
316
|
+
if (!realWorkDir.startsWith(realRoot + '/') && realWorkDir !== realRoot) {
|
|
317
|
+
log.error(
|
|
318
|
+
'Working directory is outside sandbox root — refusing to execute',
|
|
319
|
+
);
|
|
320
|
+
throw new ToolError(
|
|
321
|
+
'Working directory is outside the sandbox root. Refusing to execute.',
|
|
322
|
+
'bash',
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Map host working dir to container path under /workspace.
|
|
327
|
+
const relPath = relative(realRoot, realWorkDir);
|
|
328
|
+
const containerWorkDir =
|
|
329
|
+
relPath === '' ? '/workspace' : posix.join('/workspace', relPath);
|
|
330
|
+
|
|
331
|
+
const { image, cpus, memoryMb, pidsLimit, network } = this.config;
|
|
332
|
+
|
|
333
|
+
// Per-invocation network override: proxied mode needs bridge networking
|
|
334
|
+
// so the container can reach the proxy on the host. Default ('off' or
|
|
335
|
+
// undefined) preserves the config-level network setting.
|
|
336
|
+
const effectiveNetwork =
|
|
337
|
+
options?.networkMode === 'proxied' ? 'bridge' : network;
|
|
338
|
+
|
|
339
|
+
// Every flag is a separate argv segment — no shell interpolation occurs.
|
|
340
|
+
const args: string[] = [
|
|
341
|
+
'run',
|
|
342
|
+
'--rm',
|
|
343
|
+
`--network=${effectiveNetwork}`,
|
|
344
|
+
// When proxied, map host.docker.internal to the host machine so the
|
|
345
|
+
// container can reach the proxy daemon listening on the host loopback.
|
|
346
|
+
...(options?.networkMode === 'proxied'
|
|
347
|
+
? ['--add-host=host.docker.internal:host-gateway']
|
|
348
|
+
: []),
|
|
349
|
+
`--cpus=${cpus}`,
|
|
350
|
+
`--memory=${memoryMb}m`,
|
|
351
|
+
`--pids-limit=${pidsLimit}`,
|
|
352
|
+
'--cap-drop=ALL',
|
|
353
|
+
'--security-opt=no-new-privileges',
|
|
354
|
+
// Read-only container root prevents writes outside explicit mounts.
|
|
355
|
+
'--read-only',
|
|
356
|
+
// Writable tmpfs for /tmp — required for shell behavior, temp files, etc.
|
|
357
|
+
'--tmpfs', '/tmp:rw,nosuid,nodev,noexec',
|
|
358
|
+
'--mount',
|
|
359
|
+
`type=bind,src=${realRoot},dst=/workspace`,
|
|
360
|
+
'--workdir',
|
|
361
|
+
containerWorkDir,
|
|
362
|
+
'--user',
|
|
363
|
+
`${this.uid}:${this.gid}`,
|
|
364
|
+
image,
|
|
365
|
+
shell,
|
|
366
|
+
'-c',
|
|
367
|
+
command,
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
return { command: 'docker', args, sandboxed: true };
|
|
371
|
+
}
|
|
372
|
+
}
|