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,620 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { execFile } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { getLogger } from '../util/logger.js';
|
|
6
|
+
|
|
7
|
+
const execFileAsync = promisify(execFile);
|
|
8
|
+
const log = getLogger('workspace-git');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Build a clean env for git subprocesses.
|
|
12
|
+
*
|
|
13
|
+
* Strips all GIT_* env vars (e.g. GIT_DIR, GIT_WORK_TREE) that CI runners
|
|
14
|
+
* or parent processes may set, then adds GIT_CEILING_DIRECTORIES to prevent
|
|
15
|
+
* walking up to a parent repo.
|
|
16
|
+
*/
|
|
17
|
+
function cleanGitEnv(workspaceDir: string): Record<string, string> {
|
|
18
|
+
const env: Record<string, string> = {};
|
|
19
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
20
|
+
if (value !== undefined && !key.startsWith('GIT_')) {
|
|
21
|
+
env[key] = value;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
env.GIT_CEILING_DIRECTORIES = workspaceDir;
|
|
25
|
+
return env;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Patterns excluded from workspace git tracking.
|
|
30
|
+
* These are written to .gitignore on init and appended to existing .gitignore files.
|
|
31
|
+
*/
|
|
32
|
+
const WORKSPACE_GITIGNORE_RULES = [
|
|
33
|
+
'data/db/',
|
|
34
|
+
'data/qdrant/',
|
|
35
|
+
'data/ipc-blobs/',
|
|
36
|
+
'logs/',
|
|
37
|
+
'*.log',
|
|
38
|
+
'*.sock',
|
|
39
|
+
'*.pid',
|
|
40
|
+
'*.sqlite',
|
|
41
|
+
'*.sqlite-journal',
|
|
42
|
+
'*.sqlite-wal',
|
|
43
|
+
'*.sqlite-shm',
|
|
44
|
+
'*.db',
|
|
45
|
+
'*.db-journal',
|
|
46
|
+
'*.db-wal',
|
|
47
|
+
'*.db-shm',
|
|
48
|
+
'vellum.sock',
|
|
49
|
+
'vellum.pid',
|
|
50
|
+
'session-token',
|
|
51
|
+
'http-token',
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Rules that were used in older versions but have been superseded.
|
|
56
|
+
* These are removed from existing .gitignore files during normalization
|
|
57
|
+
* to prevent them from overriding the newer, more selective rules.
|
|
58
|
+
*/
|
|
59
|
+
const DEPRECATED_GITIGNORE_RULES = [
|
|
60
|
+
'data/',
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
/** Properties added by Node's child_process errors. */
|
|
64
|
+
interface ExecError extends Error {
|
|
65
|
+
killed?: boolean;
|
|
66
|
+
signal?: string;
|
|
67
|
+
code?: string | number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Simple mutex implementation for per-workspace git operation serialization.
|
|
72
|
+
* Prevents concurrent git operations from corrupting the repository state.
|
|
73
|
+
*/
|
|
74
|
+
class Mutex {
|
|
75
|
+
private locked = false;
|
|
76
|
+
private waitQueue: Array<() => void> = [];
|
|
77
|
+
|
|
78
|
+
async acquire(): Promise<void> {
|
|
79
|
+
if (!this.locked) {
|
|
80
|
+
this.locked = true;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
// Wait for the lock to be released
|
|
84
|
+
await new Promise<void>((resolve) => {
|
|
85
|
+
this.waitQueue.push(resolve);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
release(): void {
|
|
90
|
+
const next = this.waitQueue.shift();
|
|
91
|
+
if (next) {
|
|
92
|
+
next();
|
|
93
|
+
} else {
|
|
94
|
+
this.locked = false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Execute a function while holding the lock.
|
|
100
|
+
* Automatically releases the lock when done, even if the function throws.
|
|
101
|
+
*/
|
|
102
|
+
async withLock<T>(fn: () => Promise<T>): Promise<T> {
|
|
103
|
+
await this.acquire();
|
|
104
|
+
try {
|
|
105
|
+
return await fn();
|
|
106
|
+
} finally {
|
|
107
|
+
this.release();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface GitCommitMetadata {
|
|
113
|
+
/** Optional metadata to include in the commit message or as git notes */
|
|
114
|
+
[key: string]: unknown;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface GitStatus {
|
|
118
|
+
/** Files staged for commit */
|
|
119
|
+
staged: string[];
|
|
120
|
+
/** Files modified but not staged */
|
|
121
|
+
modified: string[];
|
|
122
|
+
/** Untracked files */
|
|
123
|
+
untracked: string[];
|
|
124
|
+
/** True if the working directory is clean */
|
|
125
|
+
clean: boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Git service for workspace change management.
|
|
130
|
+
*
|
|
131
|
+
* Provides git-backed tracking of workspace state with lazy initialization.
|
|
132
|
+
* Each workspace gets its own git repository initialized on first write.
|
|
133
|
+
*
|
|
134
|
+
* Key features:
|
|
135
|
+
* - Lazy initialization: git repo created only when needed
|
|
136
|
+
* - Mutex-protected operations: prevents concurrent git command conflicts
|
|
137
|
+
* - Handles both new and existing workspaces transparently
|
|
138
|
+
* - Synchronous initial commit within mutex to prevent races
|
|
139
|
+
*/
|
|
140
|
+
export class WorkspaceGitService {
|
|
141
|
+
private readonly workspaceDir: string;
|
|
142
|
+
private readonly mutex: Mutex;
|
|
143
|
+
private initialized = false;
|
|
144
|
+
private initPromise: Promise<void> | null = null;
|
|
145
|
+
|
|
146
|
+
constructor(workspaceDir: string) {
|
|
147
|
+
this.workspaceDir = workspaceDir;
|
|
148
|
+
this.mutex = new Mutex();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Ensure the git repository is initialized.
|
|
153
|
+
* Idempotent: safe to call multiple times.
|
|
154
|
+
*
|
|
155
|
+
* If .git doesn't exist:
|
|
156
|
+
* 1. Run git init -b main
|
|
157
|
+
* 2. Create .gitignore
|
|
158
|
+
* 3. Set git identity
|
|
159
|
+
* 4. Stage all files and create initial commit
|
|
160
|
+
*
|
|
161
|
+
* The initial commit is created synchronously within the mutex lock
|
|
162
|
+
* to prevent races with the first commitChanges() call.
|
|
163
|
+
*/
|
|
164
|
+
async ensureInitialized(): Promise<void> {
|
|
165
|
+
// Fast path: already initialized
|
|
166
|
+
if (this.initialized) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// If initialization is in progress, wait for it
|
|
171
|
+
if (this.initPromise) {
|
|
172
|
+
return this.initPromise;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Start initialization
|
|
176
|
+
this.initPromise = this.mutex.withLock(async () => {
|
|
177
|
+
// Double-check after acquiring lock
|
|
178
|
+
if (this.initialized) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const gitDir = join(this.workspaceDir, '.git');
|
|
183
|
+
|
|
184
|
+
if (existsSync(gitDir)) {
|
|
185
|
+
// Validate existing repo is not corrupted before marking as ready.
|
|
186
|
+
// A corrupted .git directory (e.g. missing HEAD) would cause all
|
|
187
|
+
// subsequent git operations to fail with confusing errors.
|
|
188
|
+
try {
|
|
189
|
+
await this.execGit(['rev-parse', '--git-dir']);
|
|
190
|
+
} catch (err: unknown) {
|
|
191
|
+
// Distinguish transient failures from genuine corruption.
|
|
192
|
+
// Transient errors (timeouts, permissions, missing git binary)
|
|
193
|
+
// should NOT destroy .git — they will resolve on retry via
|
|
194
|
+
// the initPromise clearing logic.
|
|
195
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
196
|
+
const execErr = err as ExecError;
|
|
197
|
+
const isTimeout = execErr.killed === true
|
|
198
|
+
|| execErr.signal === 'SIGTERM'
|
|
199
|
+
|| errMsg.includes('SIGTERM')
|
|
200
|
+
|| errMsg.includes('timed out');
|
|
201
|
+
const isPermission = execErr.code === 'EACCES'
|
|
202
|
+
|| errMsg.includes('EACCES')
|
|
203
|
+
|| errMsg.toLowerCase().includes('permission denied');
|
|
204
|
+
const isMissingBinary = execErr.code === 'ENOENT'
|
|
205
|
+
|| errMsg.includes('ENOENT');
|
|
206
|
+
|
|
207
|
+
if (isTimeout || isPermission || isMissingBinary) {
|
|
208
|
+
// Re-throw so initialization fails gracefully without
|
|
209
|
+
// destroying valid git history.
|
|
210
|
+
throw err;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Genuine corruption (e.g. missing HEAD, broken refs) —
|
|
214
|
+
// remove corrupted .git and fall through to full init below.
|
|
215
|
+
log.warn(
|
|
216
|
+
{ workspaceDir: this.workspaceDir, err: errMsg },
|
|
217
|
+
'Corrupted .git directory detected; reinitializing',
|
|
218
|
+
);
|
|
219
|
+
const { rmSync } = await import('node:fs');
|
|
220
|
+
rmSync(gitDir, { recursive: true, force: true });
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (existsSync(gitDir)) {
|
|
224
|
+
// .git exists and passed the corruption check, but we still
|
|
225
|
+
// need to verify that at least one commit exists. A partial
|
|
226
|
+
// init (e.g. git init succeeded but the initial commit failed)
|
|
227
|
+
// leaves .git present with an undefined HEAD. In that case,
|
|
228
|
+
// fall through to the initial commit logic below.
|
|
229
|
+
let headExists = false;
|
|
230
|
+
try {
|
|
231
|
+
await this.execGit(['rev-parse', 'HEAD']);
|
|
232
|
+
headExists = true;
|
|
233
|
+
} catch (err: unknown) {
|
|
234
|
+
// Distinguish transient failures from genuine "no commits".
|
|
235
|
+
// Transient errors (timeouts, permissions, missing git binary)
|
|
236
|
+
// should NOT fall through to re-initialization — they will
|
|
237
|
+
// resolve on retry via the initPromise clearing logic.
|
|
238
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
239
|
+
const execErr = err as ExecError;
|
|
240
|
+
const isTimeout = execErr.killed === true
|
|
241
|
+
|| execErr.signal === 'SIGTERM'
|
|
242
|
+
|| errMsg.includes('SIGTERM')
|
|
243
|
+
|| errMsg.includes('timed out');
|
|
244
|
+
const isPermission = execErr.code === 'EACCES'
|
|
245
|
+
|| errMsg.includes('EACCES')
|
|
246
|
+
|| errMsg.toLowerCase().includes('permission denied');
|
|
247
|
+
const isMissingBinary = execErr.code === 'ENOENT'
|
|
248
|
+
|| errMsg.includes('ENOENT');
|
|
249
|
+
|
|
250
|
+
if (isTimeout || isPermission || isMissingBinary) {
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
// Genuine "no commits" (unborn HEAD) — fall through to
|
|
254
|
+
// create the initial commit.
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (headExists) {
|
|
258
|
+
// HEAD resolves — repo is fully initialized.
|
|
259
|
+
// Run normalization for existing repos that may have been
|
|
260
|
+
// created before these helpers existed, or by external tools.
|
|
261
|
+
// These calls are OUTSIDE the rev-parse try/catch so that
|
|
262
|
+
// normalization errors are not misclassified as "no commits".
|
|
263
|
+
this.ensureGitignoreRulesLocked();
|
|
264
|
+
await this.ensureCommitIdentityLocked();
|
|
265
|
+
await this.ensureOnMainLocked();
|
|
266
|
+
this.initialized = true;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Otherwise fall through to reinitialize / create initial commit
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Initialize new git repository
|
|
274
|
+
await this.execGit(['init', '-b', 'main']);
|
|
275
|
+
|
|
276
|
+
// Run normalization (gitignore + identity + branch enforcement).
|
|
277
|
+
// For fresh `git init -b main` the branch is already main, but
|
|
278
|
+
// in the corruption-recovery path we fall through here after
|
|
279
|
+
// removing .git, so branch enforcement is still useful.
|
|
280
|
+
this.ensureGitignoreRulesLocked();
|
|
281
|
+
await this.ensureCommitIdentityLocked();
|
|
282
|
+
await this.ensureOnMainLocked();
|
|
283
|
+
|
|
284
|
+
// Create initial commit synchronously within the lock to prevent
|
|
285
|
+
// races with the first commitChanges() call. Without this, the
|
|
286
|
+
// initial commit could run concurrently and consume edits meant
|
|
287
|
+
// for the first user-requested commit.
|
|
288
|
+
const status = await this.getStatusInternal();
|
|
289
|
+
const hasExistingFiles = status.untracked.length > 1 || // More than just .gitignore
|
|
290
|
+
status.untracked.some(f => f !== '.gitignore');
|
|
291
|
+
|
|
292
|
+
await this.execGit(['add', '-A']);
|
|
293
|
+
|
|
294
|
+
const message = hasExistingFiles
|
|
295
|
+
? 'Initial commit: migrated existing workspace'
|
|
296
|
+
: 'Initial commit: new workspace';
|
|
297
|
+
|
|
298
|
+
await this.execGit(['commit', '-m', message, '--allow-empty']);
|
|
299
|
+
|
|
300
|
+
this.initialized = true;
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// If initialization fails, clear the cached promise so subsequent
|
|
304
|
+
// calls can retry instead of permanently returning the rejected promise.
|
|
305
|
+
this.initPromise.catch(() => {
|
|
306
|
+
this.initPromise = null;
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
return this.initPromise;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Commit all changes in the workspace.
|
|
314
|
+
*
|
|
315
|
+
* @param message - Commit message describing the changes
|
|
316
|
+
* @param metadata - Optional metadata (currently stored in commit message)
|
|
317
|
+
*/
|
|
318
|
+
async commitChanges(message: string, metadata?: GitCommitMetadata): Promise<void> {
|
|
319
|
+
await this.ensureInitialized();
|
|
320
|
+
|
|
321
|
+
await this.mutex.withLock(async () => {
|
|
322
|
+
// Stage all changes
|
|
323
|
+
await this.execGit(['add', '-A']);
|
|
324
|
+
|
|
325
|
+
// Build commit message with metadata if provided
|
|
326
|
+
let fullMessage = message;
|
|
327
|
+
if (metadata && Object.keys(metadata).length > 0) {
|
|
328
|
+
fullMessage += '\n\n' + Object.entries(metadata)
|
|
329
|
+
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
|
|
330
|
+
.join('\n');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Commit (will succeed even if no changes)
|
|
334
|
+
await this.execGit(['commit', '-m', fullMessage, '--allow-empty']);
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Atomically check for uncommitted changes and commit if the caller decides to.
|
|
340
|
+
*
|
|
341
|
+
* The status check, staging, and commit all happen within a single mutex lock,
|
|
342
|
+
* eliminating the TOCTOU race that exists when calling getStatus() and
|
|
343
|
+
* commitChanges() separately.
|
|
344
|
+
*
|
|
345
|
+
* @param decide - Called with the current status. Return an object with `message`
|
|
346
|
+
* (and optional `metadata`) to commit, or `null` to skip.
|
|
347
|
+
* @returns Whether a commit was created and the status at check time.
|
|
348
|
+
*/
|
|
349
|
+
async commitIfDirty(
|
|
350
|
+
decide: (status: GitStatus) => { message: string; metadata?: GitCommitMetadata } | null,
|
|
351
|
+
): Promise<{ committed: boolean; status: GitStatus }> {
|
|
352
|
+
await this.ensureInitialized();
|
|
353
|
+
|
|
354
|
+
return this.mutex.withLock(async () => {
|
|
355
|
+
const status = await this.getStatusInternal();
|
|
356
|
+
if (status.clean) {
|
|
357
|
+
return { committed: false, status };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const decision = decide(status);
|
|
361
|
+
if (!decision) {
|
|
362
|
+
return { committed: false, status };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
await this.execGit(['add', '-A']);
|
|
366
|
+
|
|
367
|
+
// Verify something was actually staged. Another service instance
|
|
368
|
+
// (or external process) could have committed between our status
|
|
369
|
+
// check and the add, leaving the index clean.
|
|
370
|
+
try {
|
|
371
|
+
await this.execGit(['diff', '--cached', '--quiet']);
|
|
372
|
+
// Exit code 0 means nothing staged — nothing to commit
|
|
373
|
+
return { committed: false, status };
|
|
374
|
+
} catch {
|
|
375
|
+
// Exit code 1 means there ARE staged changes — proceed
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
let fullMessage = decision.message;
|
|
379
|
+
if (decision.metadata && Object.keys(decision.metadata).length > 0) {
|
|
380
|
+
fullMessage += '\n\n' + Object.entries(decision.metadata)
|
|
381
|
+
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
|
|
382
|
+
.join('\n');
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
await this.execGit(['commit', '-m', fullMessage]);
|
|
386
|
+
return { committed: true, status };
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Get the current git status of the workspace.
|
|
392
|
+
*
|
|
393
|
+
* @returns Status information about staged, modified, and untracked files
|
|
394
|
+
*/
|
|
395
|
+
async getStatus(): Promise<GitStatus> {
|
|
396
|
+
await this.ensureInitialized();
|
|
397
|
+
return this.mutex.withLock(() => this.getStatusInternal());
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Internal status implementation (must be called with lock held).
|
|
402
|
+
*/
|
|
403
|
+
private async getStatusInternal(): Promise<GitStatus> {
|
|
404
|
+
const { stdout } = await this.execGit(['status', '--porcelain']);
|
|
405
|
+
|
|
406
|
+
const staged: string[] = [];
|
|
407
|
+
const modified: string[] = [];
|
|
408
|
+
const untracked: string[] = [];
|
|
409
|
+
|
|
410
|
+
for (const line of stdout.split('\n')) {
|
|
411
|
+
if (!line) continue;
|
|
412
|
+
|
|
413
|
+
const status = line.substring(0, 2);
|
|
414
|
+
const file = line.substring(3);
|
|
415
|
+
|
|
416
|
+
// First character is staged status, second is working tree status
|
|
417
|
+
const stagedStatus = status[0];
|
|
418
|
+
const workingStatus = status[1];
|
|
419
|
+
|
|
420
|
+
if (stagedStatus !== ' ' && stagedStatus !== '?') {
|
|
421
|
+
staged.push(file);
|
|
422
|
+
}
|
|
423
|
+
if (workingStatus === 'M' || workingStatus === 'D') {
|
|
424
|
+
modified.push(file);
|
|
425
|
+
}
|
|
426
|
+
if (status === '??') {
|
|
427
|
+
untracked.push(file);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return {
|
|
432
|
+
staged,
|
|
433
|
+
modified,
|
|
434
|
+
untracked,
|
|
435
|
+
clean: staged.length === 0 && modified.length === 0 && untracked.length === 0,
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Ensure .gitignore contains all required workspace exclusion rules.
|
|
441
|
+
* Idempotent: checks for missing rules and only appends what's needed.
|
|
442
|
+
* Also removes deprecated rules that have been superseded by newer ones.
|
|
443
|
+
* Must be called with the mutex lock held.
|
|
444
|
+
*/
|
|
445
|
+
private ensureGitignoreRulesLocked(): void {
|
|
446
|
+
const gitignorePath = join(this.workspaceDir, '.gitignore');
|
|
447
|
+
if (existsSync(gitignorePath)) {
|
|
448
|
+
let content = readFileSync(gitignorePath, 'utf-8');
|
|
449
|
+
|
|
450
|
+
// Remove deprecated rules (e.g. broad 'data/' replaced by selective 'data/db/' etc.)
|
|
451
|
+
const deprecatedPresent = DEPRECATED_GITIGNORE_RULES.filter(rule => content.includes(rule));
|
|
452
|
+
if (deprecatedPresent.length > 0) {
|
|
453
|
+
const lines = content.split('\n');
|
|
454
|
+
content = lines.filter(line => !DEPRECATED_GITIGNORE_RULES.includes(line.trim())).join('\n');
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const missingRules = WORKSPACE_GITIGNORE_RULES.filter(rule => !content.includes(rule));
|
|
458
|
+
if (missingRules.length > 0 || deprecatedPresent.length > 0) {
|
|
459
|
+
const updated = missingRules.length > 0
|
|
460
|
+
? content + '\n# Vellum runtime state (auto-added)\n' + missingRules.join('\n') + '\n'
|
|
461
|
+
: content;
|
|
462
|
+
writeFileSync(gitignorePath, updated, 'utf-8');
|
|
463
|
+
}
|
|
464
|
+
} else {
|
|
465
|
+
const gitignore = '# Runtime state - excluded from git tracking\n' + WORKSPACE_GITIGNORE_RULES.join('\n') + '\n';
|
|
466
|
+
writeFileSync(gitignorePath, gitignore, 'utf-8');
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Ensure local git identity is configured for automated commits.
|
|
472
|
+
* Idempotent: git config set is a no-op if the value is already correct.
|
|
473
|
+
* Must be called with the mutex lock held.
|
|
474
|
+
*/
|
|
475
|
+
private async ensureCommitIdentityLocked(): Promise<void> {
|
|
476
|
+
await this.execGit(['config', 'user.name', 'Vellum Assistant']);
|
|
477
|
+
await this.execGit(['config', 'user.email', 'assistant@vellum.ai']);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Ensure the workspace repo is on the `main` branch.
|
|
482
|
+
* If on a different branch or in detached HEAD state, switches to main
|
|
483
|
+
* (creating it if it doesn't exist).
|
|
484
|
+
* Must be called with the mutex lock held.
|
|
485
|
+
*/
|
|
486
|
+
private async ensureOnMainLocked(): Promise<void> {
|
|
487
|
+
let currentBranch: string | null = null;
|
|
488
|
+
try {
|
|
489
|
+
const { stdout } = await this.execGit(['symbolic-ref', '--short', 'HEAD']);
|
|
490
|
+
currentBranch = stdout.trim();
|
|
491
|
+
} catch {
|
|
492
|
+
// symbolic-ref fails in detached HEAD state
|
|
493
|
+
currentBranch = null;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (currentBranch === 'main') {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const state = currentBranch === null ? 'detached HEAD' : `branch '${currentBranch}'`;
|
|
501
|
+
log.warn(
|
|
502
|
+
{ workspaceDir: this.workspaceDir, currentBranch },
|
|
503
|
+
`Workspace repo is on ${state}; auto-switching to main`,
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
// Try switching to existing main branch first.
|
|
507
|
+
// If the switch fails, distinguish "main doesn't exist" from
|
|
508
|
+
// "local changes would be overwritten" to pick the right recovery.
|
|
509
|
+
try {
|
|
510
|
+
await this.execGit(['switch', 'main']);
|
|
511
|
+
} catch {
|
|
512
|
+
// Check whether `main` already exists as a branch.
|
|
513
|
+
let mainExists = false;
|
|
514
|
+
try {
|
|
515
|
+
await this.execGit(['rev-parse', '--verify', 'refs/heads/main']);
|
|
516
|
+
mainExists = true;
|
|
517
|
+
} catch {
|
|
518
|
+
// main branch does not exist
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (mainExists) {
|
|
522
|
+
// `main` exists but switch failed — likely due to uncommitted
|
|
523
|
+
// local changes that would be overwritten. Discard them so we
|
|
524
|
+
// can land on main.
|
|
525
|
+
await this.execGit(['switch', 'main', '--discard-changes']);
|
|
526
|
+
} else {
|
|
527
|
+
// `main` doesn't exist yet — create it.
|
|
528
|
+
await this.execGit(['switch', '-c', 'main']);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Execute a git command in the workspace directory.
|
|
535
|
+
* Includes a 30-second timeout to prevent hung operations
|
|
536
|
+
* (e.g. stale git lock files).
|
|
537
|
+
*/
|
|
538
|
+
private async execGit(args: string[]): Promise<{ stdout: string; stderr: string }> {
|
|
539
|
+
try {
|
|
540
|
+
const { stdout, stderr } = await execFileAsync('git', args, {
|
|
541
|
+
cwd: this.workspaceDir,
|
|
542
|
+
encoding: 'utf-8',
|
|
543
|
+
timeout: 30_000,
|
|
544
|
+
env: cleanGitEnv(this.workspaceDir),
|
|
545
|
+
});
|
|
546
|
+
return { stdout, stderr };
|
|
547
|
+
} catch (err) {
|
|
548
|
+
// Enhance error with git command details, preserving properties
|
|
549
|
+
// needed to distinguish transient failures from corruption.
|
|
550
|
+
const gitErr = err as Error & {
|
|
551
|
+
stdout?: string; stderr?: string;
|
|
552
|
+
code?: string; killed?: boolean; signal?: string;
|
|
553
|
+
};
|
|
554
|
+
const isPermissionError = gitErr.code === 'EACCES' || gitErr.stderr?.includes('Permission denied');
|
|
555
|
+
const prefix = isPermissionError ? 'Git permission error' : 'Git command failed';
|
|
556
|
+
const enhanced = new Error(
|
|
557
|
+
`${prefix}: git ${args.join(' ')}\n` +
|
|
558
|
+
`Error: ${gitErr.message}\n` +
|
|
559
|
+
`Stderr: ${gitErr.stderr || ''}`,
|
|
560
|
+
);
|
|
561
|
+
// Preserve properties so callers can detect timeouts, permission
|
|
562
|
+
// errors, and missing-binary failures without parsing the message.
|
|
563
|
+
(enhanced as ExecError).killed = gitErr.killed;
|
|
564
|
+
(enhanced as ExecError).signal = gitErr.signal;
|
|
565
|
+
(enhanced as ExecError).code = gitErr.code;
|
|
566
|
+
throw enhanced;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Check if the workspace has a git repository initialized.
|
|
572
|
+
* This is a non-blocking check that doesn't trigger initialization.
|
|
573
|
+
*/
|
|
574
|
+
isInitialized(): boolean {
|
|
575
|
+
return existsSync(join(this.workspaceDir, '.git'));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Get the workspace directory path.
|
|
580
|
+
*/
|
|
581
|
+
getWorkspaceDir(): string {
|
|
582
|
+
return this.workspaceDir;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Singleton registry for workspace git services.
|
|
588
|
+
* Ensures one service instance per workspace directory.
|
|
589
|
+
*/
|
|
590
|
+
const serviceRegistry = new Map<string, WorkspaceGitService>();
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Get or create a git service for the specified workspace directory.
|
|
594
|
+
*
|
|
595
|
+
* @param workspaceDir - Absolute path to workspace directory
|
|
596
|
+
* @returns WorkspaceGitService instance for the workspace
|
|
597
|
+
*/
|
|
598
|
+
export function getWorkspaceGitService(workspaceDir: string): WorkspaceGitService {
|
|
599
|
+
let service = serviceRegistry.get(workspaceDir);
|
|
600
|
+
if (!service) {
|
|
601
|
+
service = new WorkspaceGitService(workspaceDir);
|
|
602
|
+
serviceRegistry.set(workspaceDir, service);
|
|
603
|
+
}
|
|
604
|
+
return service;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Returns all currently registered WorkspaceGitService instances.
|
|
609
|
+
* Used by the heartbeat service to check all tracked workspaces for uncommitted changes.
|
|
610
|
+
*/
|
|
611
|
+
export function getAllWorkspaceGitServices(): ReadonlyMap<string, WorkspaceGitService> {
|
|
612
|
+
return serviceRegistry;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* @internal Test-only: clear the service registry
|
|
617
|
+
*/
|
|
618
|
+
export function _resetGitServiceRegistry(): void {
|
|
619
|
+
serviceRegistry.clear();
|
|
620
|
+
}
|