vellum 0.0.16 → 0.2.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 +150 -3
- package/bun.lock +1768 -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 +60 -10
- package/scripts/ipc/check-contract-inventory.ts +104 -0
- package/scripts/ipc/check-swift-decoder-drift.ts +163 -0
- package/scripts/ipc/generate-swift.ts +492 -0
- package/scripts/test-filesystem-tools.sh +48 -0
- package/scripts/test.sh +122 -0
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +2079 -0
- package/src/__tests__/account-registry.test.ts +244 -0
- package/src/__tests__/active-skill-tools.test.ts +378 -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 +313 -0
- package/src/__tests__/app-executors.test.ts +613 -0
- package/src/__tests__/app-open-proxy.test.ts +62 -0
- package/src/__tests__/asset-materialize-tool.test.ts +451 -0
- package/src/__tests__/asset-search-tool.test.ts +476 -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__/attachments-store.test.ts +547 -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 +67 -0
- package/src/__tests__/browser-skill-endstate.test.ts +198 -0
- package/src/__tests__/bundle-scanner.test.ts +313 -0
- package/src/__tests__/checker.test.ts +3856 -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 +81 -0
- package/src/__tests__/clipboard.test.ts +80 -0
- package/src/__tests__/commit-guarantee.test.ts +335 -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__/config-schema.test.ts +720 -0
- package/src/__tests__/conflict-store.test.ts +329 -0
- package/src/__tests__/connection-policy.test.ts +102 -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 +216 -0
- package/src/__tests__/conversation-store.test.ts +614 -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 +563 -0
- package/src/__tests__/credential-selection.test.ts +354 -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__/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 +143 -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__/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 +312 -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__/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__/fuzzy-match-property.test.ts +216 -0
- package/src/__tests__/fuzzy-match.test.ts +138 -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-cu-observation-blob.test.ts +351 -0
- package/src/__tests__/handlers-ipc-blob-probe.test.ts +190 -0
- package/src/__tests__/handlers-slack-config.test.ts +199 -0
- package/src/__tests__/handlers-task-submit-slash.test.ts +38 -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 +77 -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 +178 -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 +104 -0
- package/src/__tests__/host-file-read-tool.test.ts +61 -0
- package/src/__tests__/host-file-write-tool.test.ts +77 -0
- package/src/__tests__/host-shell-tool.test.ts +311 -0
- package/src/__tests__/intent-routing.test.ts +255 -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-snapshot.test.ts +1560 -0
- package/src/__tests__/ipc-validate.test.ts +357 -0
- package/src/__tests__/key-migration.test.ts +183 -0
- package/src/__tests__/keychain.test.ts +258 -0
- package/src/__tests__/llm-usage-store.test.ts +226 -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.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 +4238 -0
- package/src/__tests__/memory-retrieval-budget.test.ts +49 -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__/onboarding-starter-tasks.test.ts +166 -0
- package/src/__tests__/onboarding-template-contract.test.ts +58 -0
- package/src/__tests__/openai-provider.test.ts +753 -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__/prebuilt-home-base-seed.test.ts +71 -0
- package/src/__tests__/pricing.test.ts +256 -0
- package/src/__tests__/profile-compiler.test.ts +373 -0
- package/src/__tests__/provider-registry-ollama.test.ts +16 -0
- package/src/__tests__/proxy-approval-callback.test.ts +601 -0
- package/src/__tests__/ratelimit.test.ts +297 -0
- package/src/__tests__/registry.test.ts +487 -0
- package/src/__tests__/reminder-store.test.ts +220 -0
- package/src/__tests__/reminder.test.ts +263 -0
- package/src/__tests__/request-file-tool.test.ts +158 -0
- package/src/__tests__/run-orchestrator.test.ts +200 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +190 -0
- package/src/__tests__/runtime-runs-http.test.ts +451 -0
- package/src/__tests__/runtime-runs.test.ts +273 -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__/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 +229 -0
- package/src/__tests__/secret-ingress-handler.test.ts +99 -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 +857 -0
- package/src/__tests__/secure-keys.test.ts +323 -0
- package/src/__tests__/server-history-render.test.ts +430 -0
- package/src/__tests__/session-abort-tool-results.test.ts +240 -0
- package/src/__tests__/session-conflict-gate.test.ts +697 -0
- package/src/__tests__/session-error.test.ts +341 -0
- package/src/__tests__/session-evictor.test.ts +188 -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-profile-injection.test.ts +444 -0
- package/src/__tests__/session-provider-retry-repair.test.ts +306 -0
- package/src/__tests__/session-queue.test.ts +1462 -0
- package/src/__tests__/session-runtime-assembly.test.ts +315 -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-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-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 +352 -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-script-runner-host.test.ts +489 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +349 -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 +597 -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__/starter-bundle.test.ts +136 -0
- package/src/__tests__/starter-task-flow.test.ts +143 -0
- package/src/__tests__/subagent-manager-notify.test.ts +372 -0
- package/src/__tests__/subagent-tools.test.ts +118 -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 +461 -0
- package/src/__tests__/task-compiler.test.ts +283 -0
- package/src/__tests__/task-runner.test.ts +215 -0
- package/src/__tests__/task-scheduler.test.ts +216 -0
- package/src/__tests__/task-tools.test.ts +602 -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__/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 +112 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +251 -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.test.ts +1971 -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-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 +2030 -0
- package/src/__tests__/turn-commit.test.ts +219 -0
- package/src/__tests__/url-safety.test.ts +418 -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 +750 -0
- package/src/__tests__/workspace-heartbeat-service.test.ts +347 -0
- package/src/__tests__/workspace-lifecycle.test.ts +292 -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/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 +274 -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/cli/autonomy.ts +188 -0
- package/src/cli/contacts.ts +149 -0
- package/src/cli/doordash.ts +824 -0
- package/src/cli/email-guardrails.ts +200 -0
- package/src/cli/email.ts +405 -0
- package/src/cli/main-screen.tsx +155 -0
- package/src/cli.ts +935 -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 +1348 -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/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 +137 -0
- package/src/config/bundled-skills/messaging/SKILL.md +126 -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 +124 -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 +29 -0
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +22 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +27 -0
- package/src/config/bundled-skills/messaging/tools/shared.ts +71 -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/self-upgrade/SKILL.md +74 -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/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 +186 -0
- package/src/config/loader.ts +336 -0
- package/src/config/schema.ts +1004 -0
- package/src/config/skill-state.ts +95 -0
- package/src/config/skills.ts +972 -0
- package/src/config/system-prompt.ts +927 -0
- package/src/config/templates/BOOTSTRAP.md +70 -0
- package/src/config/templates/IDENTITY.md +18 -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 +32 -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 +194 -0
- package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +147 -0
- package/src/config/vellum-skills/telegram-setup/SKILL.md +105 -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 +679 -0
- package/src/daemon/classifier.ts +108 -0
- package/src/daemon/computer-use-session.ts +900 -0
- package/src/daemon/connection-policy.ts +41 -0
- package/src/daemon/handlers/apps.ts +446 -0
- package/src/daemon/handlers/computer-use.ts +181 -0
- package/src/daemon/handlers/config.ts +434 -0
- package/src/daemon/handlers/diagnostics.ts +334 -0
- package/src/daemon/handlers/documents.ts +184 -0
- package/src/daemon/handlers/home-base.ts +73 -0
- package/src/daemon/handlers/index.ts +355 -0
- package/src/daemon/handlers/misc.ts +323 -0
- package/src/daemon/handlers/open-bundle-handler.ts +80 -0
- package/src/daemon/handlers/publish.ts +182 -0
- package/src/daemon/handlers/sessions.ts +486 -0
- package/src/daemon/handlers/shared.ts +533 -0
- package/src/daemon/handlers/skills.ts +487 -0
- package/src/daemon/handlers/subagents.ts +122 -0
- package/src/daemon/handlers/work-items.ts +176 -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 +407 -0
- package/src/daemon/ipc-contract-inventory.ts +126 -0
- package/src/daemon/ipc-contract.ts +2102 -0
- package/src/daemon/ipc-protocol.ts +70 -0
- package/src/daemon/ipc-validate.ts +171 -0
- package/src/daemon/lifecycle.ts +503 -0
- package/src/daemon/main.ts +15 -0
- package/src/daemon/media-visibility-policy.ts +57 -0
- package/src/daemon/ride-shotgun-handler.ts +244 -0
- package/src/daemon/server.ts +1085 -0
- package/src/daemon/session-attachments.ts +173 -0
- package/src/daemon/session-conflict-gate.ts +219 -0
- package/src/daemon/session-dynamic-profile.ts +63 -0
- package/src/daemon/session-error.ts +269 -0
- package/src/daemon/session-evictor.ts +196 -0
- package/src/daemon/session-history.ts +437 -0
- package/src/daemon/session-memory.ts +212 -0
- package/src/daemon/session-process.ts +264 -0
- package/src/daemon/session-queue-manager.ts +81 -0
- package/src/daemon/session-runtime-assembly.ts +395 -0
- package/src/daemon/session-skill-tools.ts +237 -0
- package/src/daemon/session-slash.ts +302 -0
- package/src/daemon/session-surfaces.ts +624 -0
- package/src/daemon/session-tool-setup.ts +286 -0
- package/src/daemon/session-usage.ts +74 -0
- package/src/daemon/session-workspace.ts +19 -0
- package/src/daemon/session.ts +1651 -0
- package/src/daemon/trace-emitter.ts +82 -0
- package/src/daemon/watch-handler.ts +274 -0
- package/src/doordash/client.ts +905 -0
- package/src/doordash/queries.ts +1312 -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 +96 -0
- package/src/followups/followup-store.ts +166 -0
- package/src/followups/index.ts +10 -0
- package/src/followups/types.ts +23 -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 +66 -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 +101 -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 +128 -0
- package/src/hooks/runner.ts +123 -0
- package/src/hooks/templates.ts +52 -0
- package/src/hooks/types.ts +72 -0
- package/src/index.ts +1194 -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-store.ts +556 -0
- package/src/memory/attachments-store.ts +453 -0
- package/src/memory/channel-delivery-store.ts +368 -0
- package/src/memory/checkpoints.ts +52 -0
- package/src/memory/clarification-resolver.ts +297 -0
- package/src/memory/conflict-store.ts +342 -0
- package/src/memory/contradiction-checker.ts +329 -0
- package/src/memory/conversation-key-store.ts +127 -0
- package/src/memory/conversation-store.ts +469 -0
- package/src/memory/db.ts +1105 -0
- package/src/memory/embedding-backend.ts +229 -0
- package/src/memory/embedding-gemini.ts +52 -0
- package/src/memory/embedding-local.ts +75 -0
- package/src/memory/embedding-ollama.ts +55 -0
- package/src/memory/embedding-openai.ts +25 -0
- package/src/memory/entity-extractor.ts +471 -0
- package/src/memory/fingerprint.ts +20 -0
- package/src/memory/indexer.ts +156 -0
- package/src/memory/items-extractor.ts +460 -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 +99 -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 +400 -0
- package/src/memory/jobs-worker.ts +274 -0
- package/src/memory/llm-request-log-store.ts +45 -0
- package/src/memory/llm-usage-store.ts +62 -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 +211 -0
- package/src/memory/schema.ts +529 -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 +43 -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/registry.ts +34 -0
- package/src/messaging/style-analyzer.ts +158 -0
- package/src/messaging/thread-summarizer.ts +310 -0
- package/src/messaging/triage-engine.ts +321 -0
- package/src/messaging/types.ts +55 -0
- package/src/permissions/checker.ts +636 -0
- package/src/permissions/defaults.ts +243 -0
- package/src/permissions/prompter.ts +102 -0
- package/src/permissions/secret-prompter.ts +114 -0
- package/src/permissions/trust-store.ts +584 -0
- package/src/permissions/types.ts +62 -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/ratelimit.ts +93 -0
- package/src/providers/registry.ts +138 -0
- package/src/providers/retry.ts +106 -0
- package/src/providers/stream-timeout.ts +38 -0
- package/src/providers/types.ts +109 -0
- package/src/runtime/assistant-event-hub.ts +120 -0
- package/src/runtime/assistant-event.ts +82 -0
- package/src/runtime/http-server.ts +478 -0
- package/src/runtime/http-types.ts +68 -0
- package/src/runtime/routes/app-routes.ts +174 -0
- package/src/runtime/routes/attachment-routes.ts +134 -0
- package/src/runtime/routes/channel-routes.ts +342 -0
- package/src/runtime/routes/conversation-routes.ts +349 -0
- package/src/runtime/routes/run-routes.ts +223 -0
- package/src/runtime/routes/secret-routes.ts +76 -0
- package/src/runtime/run-orchestrator.ts +206 -0
- package/src/schedule/schedule-store.ts +452 -0
- package/src/schedule/scheduler.ts +168 -0
- package/src/security/encrypted-store.ts +238 -0
- package/src/security/keychain.ts +252 -0
- package/src/security/oauth2.ts +241 -0
- package/src/security/redaction.ts +89 -0
- package/src/security/secret-allowlist.ts +118 -0
- package/src/security/secret-ingress.ts +57 -0
- package/src/security/secret-scanner.ts +543 -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 +477 -0
- package/src/subagent/types.ts +69 -0
- package/src/swarm/backend-claude-code.ts +90 -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 +78 -0
- package/src/swarm/worker-runner.ts +164 -0
- package/src/tasks/SPEC.md +133 -0
- package/src/tasks/candidate-store.ts +86 -0
- package/src/tasks/ephemeral-permissions.ts +41 -0
- package/src/tasks/task-compiler.ts +198 -0
- package/src/tasks/task-runner.ts +85 -0
- package/src/tasks/task-scheduler.ts +20 -0
- package/src/tasks/task-store.ts +127 -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 +396 -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/auth-cache.ts +149 -0
- package/src/tools/browser/auth-detector.ts +347 -0
- package/src/tools/browser/browser-execution.ts +979 -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 +348 -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/claude-code/claude-code.ts +232 -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/contacts/contact-merge.ts +87 -0
- package/src/tools/contacts/contact-search.ts +102 -0
- package/src/tools/contacts/contact-upsert.ts +137 -0
- package/src/tools/contacts/index.ts +4 -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 +641 -0
- package/src/tools/document/document-tool.ts +165 -0
- package/src/tools/document/editor-template.ts +237 -0
- package/src/tools/document/index.ts +5 -0
- package/src/tools/executor.ts +825 -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 +118 -0
- package/src/tools/followups/followup_list.ts +100 -0
- package/src/tools/followups/followup_resolve.ts +91 -0
- package/src/tools/followups/index.ts +3 -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 +179 -0
- package/src/tools/host-terminal/host-shell.ts +181 -0
- package/src/tools/memory/definitions.ts +69 -0
- package/src/tools/memory/handlers.ts +245 -0
- package/src/tools/memory/register.ts +66 -0
- package/src/tools/network/domain-normalize.ts +85 -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 +701 -0
- package/src/tools/network/web-search.ts +319 -0
- package/src/tools/playbooks/index.ts +5 -0
- package/src/tools/playbooks/playbook-create.ts +140 -0
- package/src/tools/playbooks/playbook-delete.ts +76 -0
- package/src/tools/playbooks/playbook-list.ts +101 -0
- package/src/tools/playbooks/playbook-update.ts +159 -0
- package/src/tools/registry.ts +297 -0
- package/src/tools/reminder/reminder-store.ts +148 -0
- package/src/tools/reminder/reminder.ts +153 -0
- package/src/tools/schedule/create.ts +86 -0
- package/src/tools/schedule/delete.ts +54 -0
- package/src/tools/schedule/list.ts +88 -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 +62 -0
- package/src/tools/subagent/index.ts +5 -0
- package/src/tools/subagent/message.ts +72 -0
- package/src/tools/subagent/read.ts +98 -0
- package/src/tools/subagent/spawn.ts +85 -0
- package/src/tools/subagent/status.ts +74 -0
- package/src/tools/swarm/delegate.ts +182 -0
- package/src/tools/system/request-permission.ts +98 -0
- package/src/tools/tasks/index.ts +25 -0
- package/src/tools/tasks/task-delete.ts +69 -0
- package/src/tools/tasks/task-list.ts +65 -0
- package/src/tools/tasks/task-run.ts +125 -0
- package/src/tools/tasks/task-save.ts +79 -0
- package/src/tools/tasks/work-item-enqueue.ts +176 -0
- package/src/tools/tasks/work-item-list.ts +86 -0
- package/src/tools/terminal/backends/docker.ts +372 -0
- package/src/tools/terminal/backends/native.ts +188 -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 +393 -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 +250 -0
- package/src/tools/types.ts +177 -0
- package/src/tools/ui-surface/definitions.ts +232 -0
- package/src/tools/ui-surface/registry.ts +14 -0
- package/src/tools/watch/screen-watch.ts +128 -0
- package/src/tools/watch/watch-state.ts +119 -0
- package/src/tools/watcher/create.ts +110 -0
- package/src/tools/watcher/delete.ts +53 -0
- package/src/tools/watcher/digest.ts +84 -0
- package/src/tools/watcher/list.ts +90 -0
- package/src/tools/watcher/update.ts +102 -0
- package/src/tools/weather/service.ts +551 -0
- package/src/usage/actors.ts +24 -0
- package/src/usage/types.ts +38 -0
- package/src/util/clipboard.ts +33 -0
- package/src/util/content-id.ts +16 -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/platform.ts +607 -0
- package/src/util/pricing.ts +150 -0
- package/src/util/spinner.ts +51 -0
- package/src/util/time.ts +16 -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 +128 -0
- package/src/watcher/watcher-store.ts +418 -0
- package/src/work-items/work-item-store.ts +91 -0
- package/src/workspace/git-service.ts +620 -0
- package/src/workspace/heartbeat-service.ts +288 -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 +122 -0
- package/tsconfig.json +21 -0
- package/LICENSE +0 -674
- package/dist/cli.js +0 -569
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import * as net from 'node:net';
|
|
2
|
+
import type {
|
|
3
|
+
WorkItemsListRequest,
|
|
4
|
+
WorkItemGetRequest,
|
|
5
|
+
WorkItemCreateRequest,
|
|
6
|
+
WorkItemUpdateRequest,
|
|
7
|
+
WorkItemCompleteRequest,
|
|
8
|
+
WorkItemRunTaskRequest,
|
|
9
|
+
} from '../ipc-protocol.js';
|
|
10
|
+
import { log, type HandlerContext } from './shared.js';
|
|
11
|
+
import {
|
|
12
|
+
createWorkItem,
|
|
13
|
+
getWorkItem,
|
|
14
|
+
listWorkItems,
|
|
15
|
+
updateWorkItem,
|
|
16
|
+
type WorkItemStatus,
|
|
17
|
+
} from '../../work-items/work-item-store.js';
|
|
18
|
+
import { getTask } from '../../tasks/task-store.js';
|
|
19
|
+
import { runTask } from '../../tasks/task-runner.js';
|
|
20
|
+
|
|
21
|
+
export function handleWorkItemsList(
|
|
22
|
+
msg: WorkItemsListRequest,
|
|
23
|
+
socket: net.Socket,
|
|
24
|
+
ctx: HandlerContext,
|
|
25
|
+
): void {
|
|
26
|
+
const items = listWorkItems(msg.status ? { status: msg.status as WorkItemStatus } : undefined);
|
|
27
|
+
ctx.send(socket, { type: 'work_items_list_response', items });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function handleWorkItemGet(
|
|
31
|
+
msg: WorkItemGetRequest,
|
|
32
|
+
socket: net.Socket,
|
|
33
|
+
ctx: HandlerContext,
|
|
34
|
+
): void {
|
|
35
|
+
const item = getWorkItem(msg.id) ?? null;
|
|
36
|
+
ctx.send(socket, { type: 'work_item_get_response', item });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function handleWorkItemCreate(
|
|
40
|
+
msg: WorkItemCreateRequest,
|
|
41
|
+
socket: net.Socket,
|
|
42
|
+
ctx: HandlerContext,
|
|
43
|
+
): void {
|
|
44
|
+
const task = getTask(msg.taskId);
|
|
45
|
+
if (!task) {
|
|
46
|
+
ctx.send(socket, { type: 'error', message: `Task not found: ${msg.taskId}` });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const item = createWorkItem({
|
|
50
|
+
taskId: msg.taskId,
|
|
51
|
+
title: msg.title ?? task.title,
|
|
52
|
+
notes: msg.notes,
|
|
53
|
+
priorityTier: msg.priorityTier,
|
|
54
|
+
sortIndex: msg.sortIndex,
|
|
55
|
+
});
|
|
56
|
+
ctx.send(socket, { type: 'work_item_create_response', item });
|
|
57
|
+
|
|
58
|
+
// Notify all connected clients so open Task Queue views refresh immediately
|
|
59
|
+
broadcastWorkItemStatus(ctx, item.id);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function handleWorkItemUpdate(
|
|
63
|
+
msg: WorkItemUpdateRequest,
|
|
64
|
+
socket: net.Socket,
|
|
65
|
+
ctx: HandlerContext,
|
|
66
|
+
): void {
|
|
67
|
+
const updates: Record<string, unknown> = {};
|
|
68
|
+
if (msg.title !== undefined) updates.title = msg.title;
|
|
69
|
+
if (msg.notes !== undefined) updates.notes = msg.notes;
|
|
70
|
+
if (msg.status !== undefined) updates.status = msg.status;
|
|
71
|
+
if (msg.priorityTier !== undefined) updates.priorityTier = msg.priorityTier;
|
|
72
|
+
if (msg.sortIndex !== undefined) updates.sortIndex = msg.sortIndex;
|
|
73
|
+
|
|
74
|
+
const item = updateWorkItem(msg.id, updates as Parameters<typeof updateWorkItem>[1]) ?? null;
|
|
75
|
+
ctx.send(socket, { type: 'work_item_update_response', item });
|
|
76
|
+
|
|
77
|
+
// Broadcast to all clients so other open task views stay in sync
|
|
78
|
+
// (e.g. priority/sort changes made by one client are reflected everywhere)
|
|
79
|
+
if (item) {
|
|
80
|
+
broadcastWorkItemStatus(ctx, item.id);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function handleWorkItemComplete(
|
|
85
|
+
msg: WorkItemCompleteRequest,
|
|
86
|
+
socket: net.Socket,
|
|
87
|
+
ctx: HandlerContext,
|
|
88
|
+
): void {
|
|
89
|
+
const item = updateWorkItem(msg.id, { status: 'done' }) ?? null;
|
|
90
|
+
ctx.send(socket, { type: 'work_item_update_response', item });
|
|
91
|
+
if (item) {
|
|
92
|
+
ctx.broadcast({
|
|
93
|
+
type: 'work_item_status_changed',
|
|
94
|
+
item: {
|
|
95
|
+
id: item.id,
|
|
96
|
+
taskId: item.taskId,
|
|
97
|
+
title: item.title,
|
|
98
|
+
status: item.status,
|
|
99
|
+
lastRunId: item.lastRunId,
|
|
100
|
+
lastRunConversationId: item.lastRunConversationId,
|
|
101
|
+
lastRunStatus: item.lastRunStatus,
|
|
102
|
+
updatedAt: item.updatedAt,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function broadcastWorkItemStatus(ctx: HandlerContext, id: string): void {
|
|
109
|
+
const item = getWorkItem(id);
|
|
110
|
+
if (item) {
|
|
111
|
+
ctx.broadcast({
|
|
112
|
+
type: 'work_item_status_changed',
|
|
113
|
+
item: {
|
|
114
|
+
id: item.id,
|
|
115
|
+
taskId: item.taskId,
|
|
116
|
+
title: item.title,
|
|
117
|
+
status: item.status,
|
|
118
|
+
lastRunId: item.lastRunId,
|
|
119
|
+
lastRunConversationId: item.lastRunConversationId,
|
|
120
|
+
lastRunStatus: item.lastRunStatus,
|
|
121
|
+
updatedAt: item.updatedAt,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function handleWorkItemRunTask(
|
|
128
|
+
msg: WorkItemRunTaskRequest,
|
|
129
|
+
socket: net.Socket,
|
|
130
|
+
ctx: HandlerContext,
|
|
131
|
+
): Promise<void> {
|
|
132
|
+
const workItem = getWorkItem(msg.id);
|
|
133
|
+
if (!workItem) {
|
|
134
|
+
ctx.send(socket, { type: 'work_item_run_task_response', id: msg.id, lastRunId: '', success: false, error: 'Work item not found' });
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Set status to running
|
|
139
|
+
updateWorkItem(msg.id, { status: 'running' });
|
|
140
|
+
|
|
141
|
+
// Return immediately with acknowledgment
|
|
142
|
+
ctx.send(socket, { type: 'work_item_run_task_response', id: msg.id, lastRunId: '', success: true });
|
|
143
|
+
|
|
144
|
+
// Broadcast the running state
|
|
145
|
+
broadcastWorkItemStatus(ctx, msg.id);
|
|
146
|
+
|
|
147
|
+
// Execute task asynchronously — create a session and wire processMessage
|
|
148
|
+
try {
|
|
149
|
+
const session = await ctx.getOrCreateSession(crypto.randomUUID());
|
|
150
|
+
const result = await runTask(
|
|
151
|
+
{ taskId: workItem.taskId, workingDir: process.cwd() },
|
|
152
|
+
async (_conversationId, message) => {
|
|
153
|
+
await session.processMessage(message, [], (event) => {
|
|
154
|
+
ctx.broadcast(event);
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const finalStatus: WorkItemStatus = result.status === 'completed' ? 'awaiting_review' : 'failed';
|
|
160
|
+
updateWorkItem(msg.id, {
|
|
161
|
+
status: finalStatus,
|
|
162
|
+
lastRunId: result.taskRunId,
|
|
163
|
+
lastRunConversationId: result.conversationId,
|
|
164
|
+
lastRunStatus: result.status,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
broadcastWorkItemStatus(ctx, msg.id);
|
|
168
|
+
} catch (err) {
|
|
169
|
+
log.error({ err, workItemId: msg.id }, 'work_item_run_task failed');
|
|
170
|
+
updateWorkItem(msg.id, {
|
|
171
|
+
status: 'failed',
|
|
172
|
+
lastRunStatus: 'failed',
|
|
173
|
+
});
|
|
174
|
+
broadcastWorkItemStatus(ctx, msg.id);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Re-export everything from the decomposed handler modules.
|
|
2
|
+
// This file exists for backwards compatibility — all imports from
|
|
3
|
+
// './handlers.js' continue to work without changes.
|
|
4
|
+
export {
|
|
5
|
+
handleMessage,
|
|
6
|
+
renderHistoryContent,
|
|
7
|
+
mergeToolResults,
|
|
8
|
+
} from './handlers/index.js';
|
|
9
|
+
|
|
10
|
+
export type {
|
|
11
|
+
HandlerContext,
|
|
12
|
+
SessionCreateOptions,
|
|
13
|
+
HistoryToolCall,
|
|
14
|
+
HistorySurface,
|
|
15
|
+
RenderedHistoryContent,
|
|
16
|
+
ParsedHistoryMessage,
|
|
17
|
+
} from './handlers/index.js';
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Message,
|
|
3
|
+
ContentBlock,
|
|
4
|
+
ToolUseContent,
|
|
5
|
+
ToolResultContent,
|
|
6
|
+
} from '../providers/types.js';
|
|
7
|
+
|
|
8
|
+
export interface RepairStats {
|
|
9
|
+
assistantToolResultsMigrated: number;
|
|
10
|
+
missingToolResultsInserted: number;
|
|
11
|
+
orphanToolResultsDowngraded: number;
|
|
12
|
+
consecutiveSameRoleMerged: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface RepairResult {
|
|
16
|
+
messages: Message[];
|
|
17
|
+
stats: RepairStats;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const SYNTHETIC_RESULT = '<synthesized_result>tool result missing from history</synthesized_result>';
|
|
21
|
+
|
|
22
|
+
export function repairHistory(messages: Message[]): RepairResult {
|
|
23
|
+
const stats: RepairStats = {
|
|
24
|
+
assistantToolResultsMigrated: 0,
|
|
25
|
+
missingToolResultsInserted: 0,
|
|
26
|
+
orphanToolResultsDowngraded: 0,
|
|
27
|
+
consecutiveSameRoleMerged: 0,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const result: Message[] = [];
|
|
31
|
+
let pendingToolUseIds = new Set<string>();
|
|
32
|
+
// tool_result blocks stripped from assistant messages, keyed by tool_use_id
|
|
33
|
+
let recoveredResults = new Map<string, ToolResultContent>();
|
|
34
|
+
|
|
35
|
+
for (const msg of messages) {
|
|
36
|
+
if (msg.role === 'assistant') {
|
|
37
|
+
// If previous assistant had unfulfilled tool_use, inject user message
|
|
38
|
+
// using recovered results where available, synthetic for the rest
|
|
39
|
+
if (pendingToolUseIds.size > 0) {
|
|
40
|
+
result.push(
|
|
41
|
+
buildResultMessage(pendingToolUseIds, recoveredResults, stats),
|
|
42
|
+
);
|
|
43
|
+
pendingToolUseIds = new Set();
|
|
44
|
+
recoveredResults = new Map();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Strip tool_result blocks from assistant messages, preserving them
|
|
48
|
+
// so they can be migrated to the correct user message position
|
|
49
|
+
const cleanedContent: ContentBlock[] = [];
|
|
50
|
+
const newRecovered = new Map<string, ToolResultContent>();
|
|
51
|
+
for (const block of msg.content) {
|
|
52
|
+
if (block.type === 'tool_result') {
|
|
53
|
+
const tr = block as ToolResultContent;
|
|
54
|
+
newRecovered.set(tr.tool_use_id, tr);
|
|
55
|
+
stats.assistantToolResultsMigrated++;
|
|
56
|
+
} else {
|
|
57
|
+
cleanedContent.push(block);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
result.push({ role: 'assistant', content: cleanedContent });
|
|
62
|
+
|
|
63
|
+
// Collect tool_use IDs from this assistant message
|
|
64
|
+
pendingToolUseIds = new Set(
|
|
65
|
+
cleanedContent
|
|
66
|
+
.filter((b): b is ToolUseContent => b.type === 'tool_use')
|
|
67
|
+
.map((b) => b.id),
|
|
68
|
+
);
|
|
69
|
+
recoveredResults = newRecovered;
|
|
70
|
+
} else {
|
|
71
|
+
// User message
|
|
72
|
+
if (pendingToolUseIds.size > 0) {
|
|
73
|
+
const matchedIds = new Set<string>();
|
|
74
|
+
const newContent: ContentBlock[] = [];
|
|
75
|
+
|
|
76
|
+
for (const block of msg.content) {
|
|
77
|
+
if (block.type === 'tool_result') {
|
|
78
|
+
const tr = block as ToolResultContent;
|
|
79
|
+
if (pendingToolUseIds.has(tr.tool_use_id)) {
|
|
80
|
+
matchedIds.add(tr.tool_use_id);
|
|
81
|
+
newContent.push(block);
|
|
82
|
+
} else {
|
|
83
|
+
stats.orphanToolResultsDowngraded++;
|
|
84
|
+
newContent.push(downgradeToolResult(tr));
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
newContent.push(block);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Fill unmatched IDs: use recovered results if available, otherwise synthesize
|
|
92
|
+
for (const id of pendingToolUseIds) {
|
|
93
|
+
if (!matchedIds.has(id)) {
|
|
94
|
+
const recovered = recoveredResults.get(id);
|
|
95
|
+
if (recovered) {
|
|
96
|
+
newContent.push(recovered);
|
|
97
|
+
// Already counted in assistantToolResultsMigrated
|
|
98
|
+
} else {
|
|
99
|
+
stats.missingToolResultsInserted++;
|
|
100
|
+
newContent.push({
|
|
101
|
+
type: 'tool_result',
|
|
102
|
+
tool_use_id: id,
|
|
103
|
+
content: SYNTHETIC_RESULT,
|
|
104
|
+
is_error: true,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
result.push({ role: 'user', content: newContent });
|
|
111
|
+
pendingToolUseIds = new Set();
|
|
112
|
+
recoveredResults = new Map();
|
|
113
|
+
} else {
|
|
114
|
+
// No pending tool_use — any tool_result here is orphaned
|
|
115
|
+
const newContent: ContentBlock[] = msg.content.map((block) => {
|
|
116
|
+
if (block.type === 'tool_result') {
|
|
117
|
+
stats.orphanToolResultsDowngraded++;
|
|
118
|
+
return downgradeToolResult(block as ToolResultContent);
|
|
119
|
+
}
|
|
120
|
+
return block;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
result.push({ role: 'user', content: newContent });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Trailing unfulfilled tool_use at end of history
|
|
129
|
+
if (pendingToolUseIds.size > 0) {
|
|
130
|
+
result.push(buildResultMessage(pendingToolUseIds, recoveredResults, stats));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Merge consecutive same-role messages. This can occur after a checkpoint
|
|
134
|
+
// handoff where a user(tool_result) message is followed by a user(new_message),
|
|
135
|
+
// or from other history reconstruction artifacts. The Anthropic API requires
|
|
136
|
+
// strict user/assistant alternation, so consecutive same-role messages must
|
|
137
|
+
// always be merged. Undo semantics for mixed tool_result+text messages are
|
|
138
|
+
// handled by isUndoableUserMessage in session.ts.
|
|
139
|
+
const merged: Message[] = [];
|
|
140
|
+
for (const msg of result) {
|
|
141
|
+
const prev = merged[merged.length - 1];
|
|
142
|
+
if (prev && prev.role === msg.role) {
|
|
143
|
+
prev.content = [...prev.content, ...msg.content];
|
|
144
|
+
stats.consecutiveSameRoleMerged++;
|
|
145
|
+
} else {
|
|
146
|
+
merged.push({ role: msg.role, content: [...msg.content] });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return { messages: merged, stats };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function buildResultMessage(
|
|
154
|
+
ids: Set<string>,
|
|
155
|
+
recovered: Map<string, ToolResultContent>,
|
|
156
|
+
stats: RepairStats,
|
|
157
|
+
): Message {
|
|
158
|
+
return {
|
|
159
|
+
role: 'user',
|
|
160
|
+
content: Array.from(ids).map((id) => {
|
|
161
|
+
const rec = recovered.get(id);
|
|
162
|
+
if (rec) {
|
|
163
|
+
// Already counted in assistantToolResultsMigrated
|
|
164
|
+
return rec;
|
|
165
|
+
}
|
|
166
|
+
stats.missingToolResultsInserted++;
|
|
167
|
+
return {
|
|
168
|
+
type: 'tool_result' as const,
|
|
169
|
+
tool_use_id: id,
|
|
170
|
+
content: SYNTHETIC_RESULT,
|
|
171
|
+
is_error: true,
|
|
172
|
+
};
|
|
173
|
+
}),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Aggressive repair pass that handles edge cases beyond repairHistory:
|
|
179
|
+
* - Removes empty messages
|
|
180
|
+
* - Ensures the first message is from the user
|
|
181
|
+
* - Merges consecutive same-role messages (before tool-use/result repair)
|
|
182
|
+
* Then applies the standard repairHistory on top (which also merges any
|
|
183
|
+
* consecutive same-role messages introduced by tool-use/result repair).
|
|
184
|
+
*/
|
|
185
|
+
export function deepRepairHistory(messages: Message[]): RepairResult {
|
|
186
|
+
// 1. Remove messages with no content blocks
|
|
187
|
+
let cleaned = messages.filter((m) => m.content.length > 0);
|
|
188
|
+
|
|
189
|
+
// 2. Strip leading assistant messages (provider requires user-first)
|
|
190
|
+
while (cleaned.length > 0 && cleaned[0].role === 'assistant') {
|
|
191
|
+
cleaned = cleaned.slice(1);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 3. Merge consecutive same-role messages
|
|
195
|
+
const merged: Message[] = [];
|
|
196
|
+
for (const msg of cleaned) {
|
|
197
|
+
const prev = merged[merged.length - 1];
|
|
198
|
+
if (prev && prev.role === msg.role) {
|
|
199
|
+
prev.content = [...prev.content, ...msg.content];
|
|
200
|
+
} else {
|
|
201
|
+
merged.push({ role: msg.role, content: [...msg.content] });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// 4. Apply standard tool-use/tool-result repair on top
|
|
206
|
+
return repairHistory(merged);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function downgradeToolResult(tr: ToolResultContent): ContentBlock {
|
|
210
|
+
return {
|
|
211
|
+
type: 'text',
|
|
212
|
+
text: `[orphaned tool_result for ${tr.tool_use_id}]: ${tr.content}`,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { getIpcBlobDir } from '../util/platform.js';
|
|
2
|
+
import { getLogger } from '../util/logger.js';
|
|
3
|
+
import type { IpcBlobRef } from './ipc-contract.js';
|
|
4
|
+
import {
|
|
5
|
+
mkdirSync,
|
|
6
|
+
existsSync,
|
|
7
|
+
unlinkSync,
|
|
8
|
+
lstatSync,
|
|
9
|
+
realpathSync,
|
|
10
|
+
} from 'node:fs';
|
|
11
|
+
import { readFile, readdir, lstat, realpath, unlink } from 'node:fs/promises';
|
|
12
|
+
import { join, resolve, relative, sep } from 'node:path';
|
|
13
|
+
import { createHash } from 'node:crypto';
|
|
14
|
+
|
|
15
|
+
const log = getLogger('ipc-blob-store');
|
|
16
|
+
|
|
17
|
+
const BLOB_ID_REGEX = /^[0-9a-fA-F-]{36}$/;
|
|
18
|
+
const MAX_SCREENSHOT_BLOB_SIZE = 10 * 1024 * 1024; // 10 MB
|
|
19
|
+
const MAX_AX_BLOB_SIZE = 2 * 1024 * 1024; // 2 MB
|
|
20
|
+
const BLOB_EXTENSION = '.blob';
|
|
21
|
+
|
|
22
|
+
/** Ensure the blob directory exists. Call at daemon startup. */
|
|
23
|
+
export function ensureBlobDir(): void {
|
|
24
|
+
const dir = getIpcBlobDir();
|
|
25
|
+
if (!existsSync(dir)) {
|
|
26
|
+
mkdirSync(dir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Validate a blob ID matches UUID format. */
|
|
31
|
+
export function isValidBlobId(id: string): boolean {
|
|
32
|
+
return BLOB_ID_REGEX.test(id);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Resolve a blob ID to its absolute file path.
|
|
37
|
+
* Throws if the ID is invalid or the resolved path escapes the blob directory.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveBlobPath(id: string): string {
|
|
40
|
+
if (!isValidBlobId(id)) {
|
|
41
|
+
throw new Error(`Invalid blob ID: ${id}`);
|
|
42
|
+
}
|
|
43
|
+
const blobDir = getIpcBlobDir();
|
|
44
|
+
const candidate = resolve(join(blobDir, `${id}${BLOB_EXTENSION}`));
|
|
45
|
+
|
|
46
|
+
// Symlink protection: verify the resolved path stays within the blob dir.
|
|
47
|
+
// Use relative() for separator-agnostic containment check.
|
|
48
|
+
const normalizedBlobDir = resolve(blobDir);
|
|
49
|
+
const rel = relative(normalizedBlobDir, candidate);
|
|
50
|
+
if (rel.startsWith('..') || rel.startsWith(sep + sep) || rel === '') {
|
|
51
|
+
throw new Error(`Blob path escapes blob directory: ${id}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return candidate;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Verify that a blob file at the given path is a regular file (not a symlink)
|
|
59
|
+
* and that its realpath stays within the blob directory.
|
|
60
|
+
* Throws if the file is a symlink or escapes the blob directory.
|
|
61
|
+
*/
|
|
62
|
+
async function assertRegularFileInBlobDir(filePath: string): Promise<void> {
|
|
63
|
+
const fileLstat = await lstat(filePath);
|
|
64
|
+
if (fileLstat.isSymbolicLink()) {
|
|
65
|
+
throw new Error(`Blob file is a symlink: ${filePath}`);
|
|
66
|
+
}
|
|
67
|
+
const real = await realpath(filePath);
|
|
68
|
+
// Realpath both the file and the blob dir so macOS /var → /private/var is handled
|
|
69
|
+
const realBlobDir = await realpath(getIpcBlobDir());
|
|
70
|
+
const realRel = relative(realBlobDir, real);
|
|
71
|
+
if (realRel.startsWith('..') || realRel.startsWith(sep + sep) || realRel === '') {
|
|
72
|
+
throw new Error(`Blob realpath escapes blob directory: ${real}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Synchronous variant for use in deleteBlob.
|
|
78
|
+
*/
|
|
79
|
+
function assertRegularFileInBlobDirSync(filePath: string): void {
|
|
80
|
+
const fileLstat = lstatSync(filePath);
|
|
81
|
+
if (fileLstat.isSymbolicLink()) {
|
|
82
|
+
throw new Error(`Blob file is a symlink: ${filePath}`);
|
|
83
|
+
}
|
|
84
|
+
const real = realpathSync(filePath);
|
|
85
|
+
const realBlobDir = realpathSync(getIpcBlobDir());
|
|
86
|
+
const realRel = relative(realBlobDir, real);
|
|
87
|
+
if (realRel.startsWith('..') || realRel.startsWith(sep + sep) || realRel === '') {
|
|
88
|
+
throw new Error(`Blob realpath escapes blob directory: ${real}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Expected kind and encoding for each blob field. */
|
|
93
|
+
export const EXPECTED_BLOB_FIELD_METADATA = {
|
|
94
|
+
axTreeBlob: { kind: 'ax_tree' as const, encoding: 'utf8' as const },
|
|
95
|
+
screenshotBlob: { kind: 'screenshot_jpeg' as const, encoding: 'binary' as const },
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Validate that a blob ref's kind and encoding match expectations for a given field.
|
|
100
|
+
* Throws with a descriptive message if they don't match.
|
|
101
|
+
*/
|
|
102
|
+
export function validateBlobKindEncoding(
|
|
103
|
+
ref: IpcBlobRef,
|
|
104
|
+
field: keyof typeof EXPECTED_BLOB_FIELD_METADATA,
|
|
105
|
+
): void {
|
|
106
|
+
const expected = EXPECTED_BLOB_FIELD_METADATA[field];
|
|
107
|
+
if (ref.kind !== expected.kind) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`Blob kind mismatch for ${field}: expected "${expected.kind}", got "${ref.kind}"`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
if (ref.encoding !== expected.encoding) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`Blob encoding mismatch for ${field}: expected "${expected.encoding}", got "${ref.encoding}"`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Read a blob file and validate it against the ref metadata.
|
|
121
|
+
* Verifies the file is a regular file (not a symlink) and its realpath
|
|
122
|
+
* stays within the blob directory before reading.
|
|
123
|
+
* Returns the raw bytes.
|
|
124
|
+
*/
|
|
125
|
+
export async function readBlob(ref: IpcBlobRef): Promise<Buffer> {
|
|
126
|
+
const filePath = resolveBlobPath(ref.id);
|
|
127
|
+
|
|
128
|
+
// Enforce hard size limits by kind against declared byteLength before any I/O
|
|
129
|
+
const maxSize = ref.kind === 'screenshot_jpeg' ? MAX_SCREENSHOT_BLOB_SIZE : MAX_AX_BLOB_SIZE;
|
|
130
|
+
if (ref.byteLength > maxSize) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`Blob ${ref.id} declared size exceeds limit for kind "${ref.kind}": ${ref.byteLength} > ${maxSize}`,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Symlink-safe: verify the file is a regular file with realpath inside blob dir.
|
|
137
|
+
// assertRegularFileInBlobDir also lstat()s, giving us symlink detection.
|
|
138
|
+
await assertRegularFileInBlobDir(filePath);
|
|
139
|
+
|
|
140
|
+
const buf = await readFile(filePath);
|
|
141
|
+
|
|
142
|
+
// Validate actual size matches declared byteLength
|
|
143
|
+
if (buf.byteLength !== ref.byteLength) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
`Blob size mismatch for ${ref.id}: expected ${ref.byteLength} bytes, got ${buf.byteLength}`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Double-check actual size against limit (in case byteLength was spoofed to be small)
|
|
150
|
+
if (buf.byteLength > maxSize) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`Blob ${ref.id} exceeds size limit for kind "${ref.kind}": ${buf.byteLength} > ${maxSize}`,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Verify SHA-256 if provided
|
|
157
|
+
if (ref.sha256) {
|
|
158
|
+
const hash = createHash('sha256').update(buf).digest('hex');
|
|
159
|
+
if (hash !== ref.sha256) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Blob SHA-256 mismatch for ${ref.id}: expected ${ref.sha256}, got ${hash}`,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return buf;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Delete a blob file by ID. Best-effort, logs warning on failure. */
|
|
170
|
+
export function deleteBlob(id: string): void {
|
|
171
|
+
try {
|
|
172
|
+
const filePath = resolveBlobPath(id);
|
|
173
|
+
// Symlink-safe: verify the file is a regular file before deleting
|
|
174
|
+
assertRegularFileInBlobDirSync(filePath);
|
|
175
|
+
unlinkSync(filePath);
|
|
176
|
+
} catch (err) {
|
|
177
|
+
// ENOENT is expected when the blob was already cleaned up
|
|
178
|
+
if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
|
|
179
|
+
log.warn({ err, blobId: id }, 'Failed to delete blob');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Sweep stale blob files older than maxAgeMs. Returns count of deleted files. */
|
|
185
|
+
export async function sweepStaleBlobs(maxAgeMs: number): Promise<number> {
|
|
186
|
+
const blobDir = getIpcBlobDir();
|
|
187
|
+
let entries: string[];
|
|
188
|
+
try {
|
|
189
|
+
entries = await readdir(blobDir);
|
|
190
|
+
} catch (err) {
|
|
191
|
+
// Directory may not exist yet if no blobs have been written
|
|
192
|
+
if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
193
|
+
return 0;
|
|
194
|
+
}
|
|
195
|
+
log.warn({ err }, 'Failed to read blob directory for sweep');
|
|
196
|
+
return 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const now = Date.now();
|
|
200
|
+
let deleted = 0;
|
|
201
|
+
|
|
202
|
+
for (const entry of entries) {
|
|
203
|
+
if (!entry.endsWith(BLOB_EXTENSION)) continue;
|
|
204
|
+
|
|
205
|
+
const filePath = join(blobDir, entry);
|
|
206
|
+
try {
|
|
207
|
+
// Use lstat (not stat) to detect symlinks without following them
|
|
208
|
+
const fileLstat = await lstat(filePath);
|
|
209
|
+
if (fileLstat.isSymbolicLink()) {
|
|
210
|
+
log.warn({ filePath }, 'Skipping symlink during blob sweep');
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const ageMs = now - fileLstat.mtimeMs;
|
|
214
|
+
if (ageMs > maxAgeMs) {
|
|
215
|
+
await unlink(filePath);
|
|
216
|
+
deleted++;
|
|
217
|
+
}
|
|
218
|
+
} catch (err) {
|
|
219
|
+
// File may have been deleted between readdir and stat/unlink
|
|
220
|
+
if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
|
|
221
|
+
log.warn({ err, filePath }, 'Failed to stat/delete blob during sweep');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (deleted > 0) {
|
|
227
|
+
log.info({ deleted, total: entries.length }, 'Swept stale blobs');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return deleted;
|
|
231
|
+
}
|