mixdog 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +31 -0
- package/.claude-plugin/plugin.json +20 -0
- package/.gitattributes +34 -0
- package/.mcp.json +14 -0
- package/ARCHITECTURE.md +77 -0
- package/CHANGELOG.md +7 -0
- package/CONTRIBUTING.md +45 -0
- package/DATA-FLOW.md +79 -0
- package/LICENSE +21 -0
- package/README.md +389 -0
- package/SECURITY.md +138 -0
- package/UNINSTALL.md +112 -0
- package/agents/maintenance.md +5 -0
- package/agents/memory-classification.md +30 -0
- package/agents/scheduler-task.md +18 -0
- package/agents/webhook-handler.md +27 -0
- package/agents/worker.md +24 -0
- package/bin/bridge +133 -0
- package/bin/statusline-launcher.mjs +78 -0
- package/bin/statusline-lib.mjs +550 -0
- package/bin/statusline.mjs +607 -0
- package/bun.lock +802 -0
- package/commands/config.md +16 -0
- package/commands/doctor.md +13 -0
- package/commands/setup.md +17 -0
- package/defaults/cycle3-review-prompt.md +90 -0
- package/defaults/hidden-roles.json +65 -0
- package/defaults/memory-chunk-prompt.md +63 -0
- package/defaults/memory-promote-prompt.md +135 -0
- package/defaults/mixdog-config.template.json +27 -0
- package/defaults/user-workflow.json +8 -0
- package/defaults/user-workflow.md +12 -0
- package/hooks/hooks.json +73 -0
- package/hooks/lib/active-instance.cjs +77 -0
- package/hooks/lib/permission-evaluator.cjs +411 -0
- package/hooks/lib/permission-route.cjs +63 -0
- package/hooks/lib/permission-rules.cjs +170 -0
- package/hooks/lib/settings-loader.cjs +116 -0
- package/hooks/post-tool-use.cjs +84 -0
- package/hooks/pre-mcp-sandbox.cjs +158 -0
- package/hooks/pre-tool-subagent.cjs +253 -0
- package/hooks/session-start.cjs +1372 -0
- package/hooks/turn-timer.cjs +82 -0
- package/lib/claude-md-writer.cjs +386 -0
- package/lib/config-cjs.cjs +61 -0
- package/lib/hook-pipe-path.cjs +10 -0
- package/lib/keychain-cjs.cjs +263 -0
- package/lib/plugin-paths.cjs +61 -0
- package/lib/rules-builder.cjs +241 -0
- package/lib/text-utils.cjs +61 -0
- package/native/README.md +117 -0
- package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
- package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
- package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
- package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
- package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
- package/package.json +107 -0
- package/prompts/code-review.txt +16 -0
- package/prompts/security-audit.txt +17 -0
- package/rules/bridge/00-common.md +39 -0
- package/rules/bridge/20-skip-protocol.md +18 -0
- package/rules/bridge/30-explorer.md +33 -0
- package/rules/bridge/40-cycle1-agent.md +52 -0
- package/rules/bridge/41-cycle2-agent.md +62 -0
- package/rules/bridge/42-cycle3-agent.md +44 -0
- package/rules/lead/00-tool-lead.md +61 -0
- package/rules/lead/01-general.md +23 -0
- package/rules/lead/02-channels.md +49 -0
- package/rules/lead/03-team.md +27 -0
- package/rules/lead/04-workflow.md +20 -0
- package/rules/shared/00-language.md +14 -0
- package/rules/shared/01-tool.md +138 -0
- package/scripts/bootstrap.mjs +184 -0
- package/scripts/bridge-unify-smoke.mjs +308 -0
- package/scripts/build-runtime-linux.sh +348 -0
- package/scripts/build-runtime-macos.sh +217 -0
- package/scripts/build-runtime-windows.ps1 +242 -0
- package/scripts/builtin-utils-smoke.mjs +392 -0
- package/scripts/check-json.mjs +45 -0
- package/scripts/check-syntax-changed.mjs +102 -0
- package/scripts/check-syntax.mjs +58 -0
- package/scripts/code-graph-batch.test.mjs +33 -0
- package/scripts/config-preserve-smoke.mjs +180 -0
- package/scripts/doctor.mjs +484 -0
- package/scripts/edit-normalize-fuzz.mjs +130 -0
- package/scripts/edit-normalize-smoke.mjs +401 -0
- package/scripts/edit-operation-smoke.mjs +369 -0
- package/scripts/edit2-smoke.mjs +63 -0
- package/scripts/fuzzy-e2e.mjs +28 -0
- package/scripts/fuzzy-smoke.mjs +26 -0
- package/scripts/generate-runtime-manifest.mjs +166 -0
- package/scripts/guard-smoke.mjs +66 -0
- package/scripts/hidden-role-schema-smoke.mjs +162 -0
- package/scripts/hook-routing-smoke.mjs +29 -0
- package/scripts/inject-input.ps1 +204 -0
- package/scripts/io-complex-smoke.mjs +667 -0
- package/scripts/io-explore-bench.mjs +424 -0
- package/scripts/io-guardrails-smoke.mjs +205 -0
- package/scripts/io-mini-bench-baseline.json +11 -0
- package/scripts/io-mini-bench.mjs +216 -0
- package/scripts/io-route-harness.mjs +933 -0
- package/scripts/io-telemetry-report.mjs +691 -0
- package/scripts/mutation-bench.mjs +564 -0
- package/scripts/mutation-io-smoke.mjs +1081 -0
- package/scripts/native-patch-bridge-smoke.mjs +288 -0
- package/scripts/native-patch-smoke.mjs +304 -0
- package/scripts/patch-interior-context-smoke.mjs +49 -0
- package/scripts/patch-newline-utf8-smoke.mjs +157 -0
- package/scripts/perf-hook-smoke.mjs +71 -0
- package/scripts/permission-eval-smoke.mjs +426 -0
- package/scripts/prep-patch.mjs +53 -0
- package/scripts/prep-shim.mjs +96 -0
- package/scripts/provider-cache-smoke.mjs +687 -0
- package/scripts/report-runtime-health.mjs +132 -0
- package/scripts/run-mcp.mjs +1547 -0
- package/scripts/salvage-v4a-shatter.test.mjs +58 -0
- package/scripts/scoped-cache-io-smoke.mjs +103 -0
- package/scripts/shell-policy-round3-smoke.mjs +46 -0
- package/scripts/smoke-runtime-negative.ps1 +100 -0
- package/scripts/smoke-runtime-negative.sh +95 -0
- package/scripts/stall-policy-smoke.mjs +50 -0
- package/scripts/start-memory-worker.mjs +23 -0
- package/scripts/statusline-launcher-smoke.mjs +82 -0
- package/scripts/stress-atomic-write.mjs +1028 -0
- package/scripts/test-config-rmw-restore.mjs +122 -0
- package/scripts/test-fault-inject.mjs +164 -0
- package/scripts/test-large-file.mjs +174 -0
- package/scripts/tool-edge-smoke.mjs +209 -0
- package/scripts/uninstall.mjs +201 -0
- package/scripts/webhook-selfheal-smoke.mjs +29 -0
- package/scripts/write-overwrite-guard-smoke.mjs +56 -0
- package/server-main.mjs +3055 -0
- package/server.mjs +468 -0
- package/setup/config-merge.mjs +254 -0
- package/setup/install.mjs +120 -0
- package/setup/launch-core.mjs +507 -0
- package/setup/launch.mjs +101 -0
- package/setup/setup-server.mjs +3206 -0
- package/setup/setup.html +3693 -0
- package/skills/retro-skill-proposer/SKILL.md +92 -0
- package/skills/schedule-add/SKILL.md +77 -0
- package/skills/setup/SKILL.md +346 -0
- package/skills/webhook-add/SKILL.md +81 -0
- package/src/agent/bridge-stall-watchdog.mjs +337 -0
- package/src/agent/index.mjs +2138 -0
- package/src/agent/orchestrator/activity-bus.mjs +38 -0
- package/src/agent/orchestrator/ai-wrapped-dispatch.mjs +1010 -0
- package/src/agent/orchestrator/bridge-retry.mjs +220 -0
- package/src/agent/orchestrator/bridge-trace.mjs +583 -0
- package/src/agent/orchestrator/cache-mtime.mjs +58 -0
- package/src/agent/orchestrator/config.mjs +358 -0
- package/src/agent/orchestrator/context/collect.mjs +651 -0
- package/src/agent/orchestrator/dispatch-persist.mjs +549 -0
- package/src/agent/orchestrator/drain-registry.mjs +50 -0
- package/src/agent/orchestrator/explore-validator.mjs +8 -0
- package/src/agent/orchestrator/internal-roles.mjs +118 -0
- package/src/agent/orchestrator/internal-tools.mjs +88 -0
- package/src/agent/orchestrator/jobs.mjs +116 -0
- package/src/agent/orchestrator/mcp/client.mjs +364 -0
- package/src/agent/orchestrator/providers/anthropic-betas.mjs +21 -0
- package/src/agent/orchestrator/providers/anthropic-oauth.mjs +1745 -0
- package/src/agent/orchestrator/providers/anthropic.mjs +437 -0
- package/src/agent/orchestrator/providers/gemini.mjs +1175 -0
- package/src/agent/orchestrator/providers/grok-oauth.mjs +782 -0
- package/src/agent/orchestrator/providers/model-catalog.mjs +241 -0
- package/src/agent/orchestrator/providers/openai-compat.mjs +1467 -0
- package/src/agent/orchestrator/providers/openai-oauth-ws.mjs +1890 -0
- package/src/agent/orchestrator/providers/openai-oauth.mjs +1307 -0
- package/src/agent/orchestrator/providers/openai-ws.mjs +104 -0
- package/src/agent/orchestrator/providers/registry.mjs +192 -0
- package/src/agent/orchestrator/providers/retry-classifier.mjs +325 -0
- package/src/agent/orchestrator/session/abort-lookup.mjs +13 -0
- package/src/agent/orchestrator/session/cache/post-edit-marks.mjs +42 -0
- package/src/agent/orchestrator/session/cache/prefetch-cache.mjs +142 -0
- package/src/agent/orchestrator/session/cache/read-cache.mjs +319 -0
- package/src/agent/orchestrator/session/cache/scoped-cache-outcome.mjs +11 -0
- package/src/agent/orchestrator/session/cache/scoped-cache.mjs +361 -0
- package/src/agent/orchestrator/session/cache/util.mjs +49 -0
- package/src/agent/orchestrator/session/loop.mjs +1478 -0
- package/src/agent/orchestrator/session/manager.mjs +1975 -0
- package/src/agent/orchestrator/session/read-dedup.mjs +6 -0
- package/src/agent/orchestrator/session/result-classification.mjs +65 -0
- package/src/agent/orchestrator/session/save-session-worker.mjs +18 -0
- package/src/agent/orchestrator/session/store.mjs +624 -0
- package/src/agent/orchestrator/session/stream-watchdog.mjs +130 -0
- package/src/agent/orchestrator/session/tool-result-offload.mjs +166 -0
- package/src/agent/orchestrator/session/trim.mjs +491 -0
- package/src/agent/orchestrator/smart-bridge/CACHE-SHARD.md +115 -0
- package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +327 -0
- package/src/agent/orchestrator/smart-bridge/cache-obs.mjs +150 -0
- package/src/agent/orchestrator/smart-bridge/cache-strategy.mjs +228 -0
- package/src/agent/orchestrator/smart-bridge/index.mjs +215 -0
- package/src/agent/orchestrator/smart-bridge/profiles.mjs +37 -0
- package/src/agent/orchestrator/smart-bridge/registry.mjs +348 -0
- package/src/agent/orchestrator/smart-bridge/session-builder.mjs +116 -0
- package/src/agent/orchestrator/stall-policy.mjs +195 -0
- package/src/agent/orchestrator/tool-loop-guard.mjs +75 -0
- package/src/agent/orchestrator/tools/bash-policy-scan.mjs +77 -0
- package/src/agent/orchestrator/tools/bash-session.mjs +721 -0
- package/src/agent/orchestrator/tools/builtin/advisory-lock.mjs +171 -0
- package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +455 -0
- package/src/agent/orchestrator/tools/builtin/atomic-write.mjs +236 -0
- package/src/agent/orchestrator/tools/builtin/bash-tool.mjs +480 -0
- package/src/agent/orchestrator/tools/builtin/binary-file.mjs +76 -0
- package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +256 -0
- package/src/agent/orchestrator/tools/builtin/cache-layers.mjs +386 -0
- package/src/agent/orchestrator/tools/builtin/cwd-utils.mjs +37 -0
- package/src/agent/orchestrator/tools/builtin/device-paths.mjs +154 -0
- package/src/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +292 -0
- package/src/agent/orchestrator/tools/builtin/diff-utils.mjs +109 -0
- package/src/agent/orchestrator/tools/builtin/edit-base-guard.mjs +58 -0
- package/src/agent/orchestrator/tools/builtin/edit-byte-plan.mjs +240 -0
- package/src/agent/orchestrator/tools/builtin/edit-byte-utils.mjs +113 -0
- package/src/agent/orchestrator/tools/builtin/edit-commit.mjs +74 -0
- package/src/agent/orchestrator/tools/builtin/edit-context-utils.mjs +242 -0
- package/src/agent/orchestrator/tools/builtin/edit-diagnostics.mjs +211 -0
- package/src/agent/orchestrator/tools/builtin/edit-engine.mjs +1364 -0
- package/src/agent/orchestrator/tools/builtin/edit-failure-context.mjs +126 -0
- package/src/agent/orchestrator/tools/builtin/edit-hint.mjs +141 -0
- package/src/agent/orchestrator/tools/builtin/edit-match-utils.mjs +194 -0
- package/src/agent/orchestrator/tools/builtin/edit-partial-write.mjs +60 -0
- package/src/agent/orchestrator/tools/builtin/edit-stale-refresh.mjs +168 -0
- package/src/agent/orchestrator/tools/builtin/edit-tool.mjs +173 -0
- package/src/agent/orchestrator/tools/builtin/edit-utf8-guard.mjs +48 -0
- package/src/agent/orchestrator/tools/builtin/fs-reachability.mjs +48 -0
- package/src/agent/orchestrator/tools/builtin/fuzzy-match.mjs +99 -0
- package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +170 -0
- package/src/agent/orchestrator/tools/builtin/grep-formatting.mjs +113 -0
- package/src/agent/orchestrator/tools/builtin/hash-utils.mjs +6 -0
- package/src/agent/orchestrator/tools/builtin/list-formatting.mjs +7 -0
- package/src/agent/orchestrator/tools/builtin/list-tool.mjs +593 -0
- package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +89 -0
- package/src/agent/orchestrator/tools/builtin/notebook-edit-tool.mjs +300 -0
- package/src/agent/orchestrator/tools/builtin/open-config-tool.mjs +26 -0
- package/src/agent/orchestrator/tools/builtin/path-diagnostics.mjs +152 -0
- package/src/agent/orchestrator/tools/builtin/path-locks.mjs +35 -0
- package/src/agent/orchestrator/tools/builtin/path-utils.mjs +201 -0
- package/src/agent/orchestrator/tools/builtin/read-args.mjs +103 -0
- package/src/agent/orchestrator/tools/builtin/read-batch.mjs +172 -0
- package/src/agent/orchestrator/tools/builtin/read-constants.mjs +40 -0
- package/src/agent/orchestrator/tools/builtin/read-formatting.mjs +118 -0
- package/src/agent/orchestrator/tools/builtin/read-image-resize.mjs +189 -0
- package/src/agent/orchestrator/tools/builtin/read-image.mjs +88 -0
- package/src/agent/orchestrator/tools/builtin/read-lines.mjs +12 -0
- package/src/agent/orchestrator/tools/builtin/read-mode-tool.mjs +455 -0
- package/src/agent/orchestrator/tools/builtin/read-open.mjs +190 -0
- package/src/agent/orchestrator/tools/builtin/read-range-index.mjs +271 -0
- package/src/agent/orchestrator/tools/builtin/read-ranges.mjs +26 -0
- package/src/agent/orchestrator/tools/builtin/read-single-tool.mjs +728 -0
- package/src/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +173 -0
- package/src/agent/orchestrator/tools/builtin/read-special-files.mjs +268 -0
- package/src/agent/orchestrator/tools/builtin/read-streaming.mjs +602 -0
- package/src/agent/orchestrator/tools/builtin/read-tool.mjs +530 -0
- package/src/agent/orchestrator/tools/builtin/read-windows.mjs +107 -0
- package/src/agent/orchestrator/tools/builtin/rename-tool.mjs +196 -0
- package/src/agent/orchestrator/tools/builtin/rg-runner.mjs +422 -0
- package/src/agent/orchestrator/tools/builtin/search-builders.mjs +158 -0
- package/src/agent/orchestrator/tools/builtin/search-tool.mjs +869 -0
- package/src/agent/orchestrator/tools/builtin/shell-analysis.mjs +653 -0
- package/src/agent/orchestrator/tools/builtin/shell-jobs.mjs +936 -0
- package/src/agent/orchestrator/tools/builtin/shell-output.mjs +36 -0
- package/src/agent/orchestrator/tools/builtin/shell-runtime.mjs +214 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +143 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-store.mjs +206 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-validation.mjs +98 -0
- package/src/agent/orchestrator/tools/builtin/text-stats.mjs +69 -0
- package/src/agent/orchestrator/tools/builtin/windows-roots.mjs +23 -0
- package/src/agent/orchestrator/tools/builtin/write-tool.mjs +401 -0
- package/src/agent/orchestrator/tools/builtin.mjs +500 -0
- package/src/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +39 -0
- package/src/agent/orchestrator/tools/code-graph-tool-defs.mjs +24 -0
- package/src/agent/orchestrator/tools/code-graph.mjs +4095 -0
- package/src/agent/orchestrator/tools/cwd-tool.mjs +298 -0
- package/src/agent/orchestrator/tools/destructive-warning.mjs +323 -0
- package/src/agent/orchestrator/tools/edit-normalize.mjs +603 -0
- package/src/agent/orchestrator/tools/env-scrub.mjs +100 -0
- package/src/agent/orchestrator/tools/graph-binary-fetcher.mjs +144 -0
- package/src/agent/orchestrator/tools/graph-manifest.json +26 -0
- package/src/agent/orchestrator/tools/host-input.mjs +204 -0
- package/src/agent/orchestrator/tools/mutation-content-cache.mjs +67 -0
- package/src/agent/orchestrator/tools/mutation-planner.mjs +75 -0
- package/src/agent/orchestrator/tools/next-call-utils.mjs +48 -0
- package/src/agent/orchestrator/tools/patch-binary-fetcher.mjs +133 -0
- package/src/agent/orchestrator/tools/patch-manifest.json +26 -0
- package/src/agent/orchestrator/tools/patch-tool-defs.mjs +20 -0
- package/src/agent/orchestrator/tools/patch.mjs +2754 -0
- package/src/agent/orchestrator/tools/progress-message.mjs +118 -0
- package/src/agent/orchestrator/tools/result-compression.mjs +279 -0
- package/src/agent/orchestrator/tools/shell-command.mjs +865 -0
- package/src/agent/orchestrator/tools/shell-exec-policy.mjs +89 -0
- package/src/agent/orchestrator/tools/shell-policy-danger-target.mjs +27 -0
- package/src/agent/orchestrator/tools/shell-policy-imports.mjs +7 -0
- package/src/agent/orchestrator/tools/shell-policy.mjs +345 -0
- package/src/agent/orchestrator/tools/shell-snapshot.mjs +313 -0
- package/src/agent/orchestrator/workflow-store.mjs +93 -0
- package/src/agent/tool-defs.mjs +103 -0
- package/src/channels/backends/discord.mjs +784 -0
- package/src/channels/data/voice-runtime-manifest.json +138 -0
- package/src/channels/index.mjs +3229 -0
- package/src/channels/lib/cli-worker-host.mjs +12 -0
- package/src/channels/lib/config-lock.mjs +13 -0
- package/src/channels/lib/config.mjs +292 -0
- package/src/channels/lib/drop-trace.mjs +71 -0
- package/src/channels/lib/event-pipeline.mjs +81 -0
- package/src/channels/lib/event-queue.mjs +345 -0
- package/src/channels/lib/executor.mjs +168 -0
- package/src/channels/lib/format.mjs +188 -0
- package/src/channels/lib/holidays.mjs +138 -0
- package/src/channels/lib/hook-pipe-server.mjs +802 -0
- package/src/channels/lib/interaction-workflows.mjs +184 -0
- package/src/channels/lib/memory-client.mjs +149 -0
- package/src/channels/lib/output-forwarder.mjs +765 -0
- package/src/channels/lib/runtime-paths.mjs +479 -0
- package/src/channels/lib/scheduler.mjs +723 -0
- package/src/channels/lib/session-control.mjs +36 -0
- package/src/channels/lib/session-discovery.mjs +103 -0
- package/src/channels/lib/settings.mjs +11 -0
- package/src/channels/lib/state-file.mjs +68 -0
- package/src/channels/lib/status-snapshot.mjs +219 -0
- package/src/channels/lib/tool-format.mjs +140 -0
- package/src/channels/lib/transcript-discovery.mjs +195 -0
- package/src/channels/lib/voice-runtime-fetcher.mjs +734 -0
- package/src/channels/lib/webhook.mjs +1179 -0
- package/src/channels/lib/whisper-server.mjs +477 -0
- package/src/channels/tool-defs.mjs +170 -0
- package/src/daemon/host.mjs +118 -0
- package/src/daemon/mcp-transport.mjs +47 -0
- package/src/daemon/session.mjs +100 -0
- package/src/daemon/thin-client.mjs +71 -0
- package/src/daemon/transport.mjs +163 -0
- package/src/memory/data/runtime-manifest.json +40 -0
- package/src/memory/index.mjs +3305 -0
- package/src/memory/lib/agent-ipc.mjs +93 -0
- package/src/memory/lib/bridge-trace-queries.mjs +120 -0
- package/src/memory/lib/core-memory-store.mjs +330 -0
- package/src/memory/lib/embedding-provider.mjs +269 -0
- package/src/memory/lib/embedding-worker.mjs +323 -0
- package/src/memory/lib/llm-worker-host.mjs +17 -0
- package/src/memory/lib/memory-cycle.mjs +11 -0
- package/src/memory/lib/memory-cycle1.mjs +641 -0
- package/src/memory/lib/memory-cycle2.mjs +1284 -0
- package/src/memory/lib/memory-cycle3.mjs +540 -0
- package/src/memory/lib/memory-embed.mjs +299 -0
- package/src/memory/lib/memory-extraction.mjs +5 -0
- package/src/memory/lib/memory-maintenance-store.mjs +32 -0
- package/src/memory/lib/memory-ops-policy.mjs +190 -0
- package/src/memory/lib/memory-recall-id-patch.mjs +15 -0
- package/src/memory/lib/memory-recall-read-query.mjs +7 -0
- package/src/memory/lib/memory-recall-scope-filter.mjs +63 -0
- package/src/memory/lib/memory-recall-store.mjs +621 -0
- package/src/memory/lib/memory-retrievers.mjs +112 -0
- package/src/memory/lib/memory-score.mjs +71 -0
- package/src/memory/lib/memory-text-utils.mjs +58 -0
- package/src/memory/lib/memory.mjs +412 -0
- package/src/memory/lib/model-profile.mjs +85 -0
- package/src/memory/lib/pg/adapter.mjs +308 -0
- package/src/memory/lib/pg/process.mjs +360 -0
- package/src/memory/lib/pg/supervisor.mjs +396 -0
- package/src/memory/lib/project-id-resolver.mjs +86 -0
- package/src/memory/lib/runtime-fetcher.mjs +442 -0
- package/src/memory/lib/trace-store.mjs +728 -0
- package/src/memory/tool-defs.mjs +79 -0
- package/src/search/index.mjs +1173 -0
- package/src/search/lib/backends/anthropic-oauth.mjs +98 -0
- package/src/search/lib/backends/exa.mjs +50 -0
- package/src/search/lib/backends/firecrawl.mjs +61 -0
- package/src/search/lib/backends/gemini-api.mjs +83 -0
- package/src/search/lib/backends/grok-oauth.mjs +86 -0
- package/src/search/lib/backends/index.mjs +150 -0
- package/src/search/lib/backends/openai-api.mjs +144 -0
- package/src/search/lib/backends/openai-oauth.mjs +98 -0
- package/src/search/lib/backends/openai-web-search.mjs +76 -0
- package/src/search/lib/backends/tavily.mjs +55 -0
- package/src/search/lib/backends/xai-api.mjs +113 -0
- package/src/search/lib/cache.mjs +131 -0
- package/src/search/lib/config.mjs +192 -0
- package/src/search/lib/formatter.mjs +115 -0
- package/src/search/lib/provider-usage.mjs +67 -0
- package/src/search/lib/providers.mjs +47 -0
- package/src/search/lib/search-intent.mjs +109 -0
- package/src/search/lib/setup-handler.mjs +261 -0
- package/src/search/lib/state.mjs +201 -0
- package/src/search/lib/web-tools.mjs +1207 -0
- package/src/search/tool-defs.mjs +83 -0
- package/src/setup/defender-exclusion.mjs +183 -0
- package/src/shared/abort-controller.mjs +15 -0
- package/src/shared/atomic-file.mjs +420 -0
- package/src/shared/config.mjs +350 -0
- package/src/shared/daemon-recycle.mjs +108 -0
- package/src/shared/disable-claude-builtins.mjs +88 -0
- package/src/shared/err-text.mjs +12 -0
- package/src/shared/llm/cost.mjs +66 -0
- package/src/shared/llm/http-agent.mjs +123 -0
- package/src/shared/llm/index.mjs +41 -0
- package/src/shared/llm/pid-cleanup.mjs +27 -0
- package/src/shared/llm/usage-log.mjs +47 -0
- package/src/shared/plugin-paths.mjs +58 -0
- package/src/shared/schedules-store.mjs +70 -0
- package/src/shared/seed.mjs +119 -0
- package/src/shared/user-cwd.mjs +213 -0
- package/src/shared/user-data-guard.mjs +238 -0
- package/src/status/aggregator.mjs +584 -0
- package/src/status/server.mjs +413 -0
- package/tools.json +1653 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Shell environment snapshot.
|
|
3
|
+
//
|
|
4
|
+
// Captures the user's interactive shell state (functions, aliases, shell
|
|
5
|
+
// options) by sourcing their config file in a one-shot login shell and
|
|
6
|
+
// dumping the resulting environment to a temp script. Subsequent bash
|
|
7
|
+
// commands prepend `source <snapshot>` so they run with the same nvm /
|
|
8
|
+
// pyenv / mise / asdf / direnv setup the user gets in their interactive
|
|
9
|
+
// terminal — without paying a fresh login-shell startup on every call.
|
|
10
|
+
//
|
|
11
|
+
// Mirrors Claude Code upstream (src/utils/bash/ShellSnapshot.ts:413,
|
|
12
|
+
// createAndSaveSnapshot). Simpler scope: bash and zsh only, no embedded
|
|
13
|
+
// search-tool injection (mixdog ships its own grep/glob helpers).
|
|
14
|
+
|
|
15
|
+
import { spawn } from 'node:child_process';
|
|
16
|
+
import { existsSync, mkdirSync, statSync, readFileSync, readdirSync, unlinkSync } from 'node:fs';
|
|
17
|
+
import { readdir as readdirAsync, stat as statAsync, unlink as unlinkAsync } from 'node:fs/promises';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
import { homedir } from 'node:os';
|
|
20
|
+
import { randomUUID } from 'node:crypto';
|
|
21
|
+
import { getPluginData } from '../config.mjs';
|
|
22
|
+
import { scrubLoaderVars, scrubProviderSecrets } from './env-scrub.mjs';
|
|
23
|
+
|
|
24
|
+
const SNAPSHOT_TIMEOUT_MS = 10_000;
|
|
25
|
+
|
|
26
|
+
// One snapshot per shellPath. Re-snapshot when the cached file is gone;
|
|
27
|
+
// otherwise the cached path is reused for the process lifetime so we
|
|
28
|
+
// don't pay the login-shell cost per call.
|
|
29
|
+
const _cache = new Map();
|
|
30
|
+
|
|
31
|
+
// Negative cache. When snapshot generation fails (timeout, syntax error,
|
|
32
|
+
// missing dump utilities) we mark the shell path so subsequent calls
|
|
33
|
+
// fall through immediately instead of paying another 10 s timeout per
|
|
34
|
+
// command. Cleared on process exit (process-scoped Set).
|
|
35
|
+
const _failedShells = new Set();
|
|
36
|
+
|
|
37
|
+
// Mirrors Claude Code's cleanupRegistry pattern (refs/claude-code/utils/
|
|
38
|
+
// cleanupRegistry.ts + ShellSnapshot.ts:534-545). Snapshot files are
|
|
39
|
+
// session-scoped and must be unlinked on graceful shutdown — otherwise
|
|
40
|
+
// they pile up forever (each rc-file mtime change creates a new file).
|
|
41
|
+
const _activeSnapshots = new Set();
|
|
42
|
+
let _cleanupRegistered = false;
|
|
43
|
+
|
|
44
|
+
export function drainShellSnapshots() {
|
|
45
|
+
for (const p of _activeSnapshots) {
|
|
46
|
+
try { unlinkSync(p); } catch {}
|
|
47
|
+
}
|
|
48
|
+
_activeSnapshots.clear();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Stale-snapshot sweep on module init. _activeSnapshots tracks files this
|
|
52
|
+
// process created; snapshots written by prior mcp child instances (before
|
|
53
|
+
// supervisor restart) sit on disk with no in-memory handle and the bare
|
|
54
|
+
// 'exit' hook can't reach them. Invariant: any snapshot-*.sh older than
|
|
55
|
+
// SNAPSHOT_STALE_MS in shell-snapshots/ belongs to a dead instance. The
|
|
56
|
+
// live process keeps its own files because _cache hits skip generation
|
|
57
|
+
// and the kept files get touched on reuse.
|
|
58
|
+
const SNAPSHOT_STALE_MS = 60 * 60 * 1000;
|
|
59
|
+
async function _sweepStaleSnapshots() {
|
|
60
|
+
const dir = join(getPluginData(), 'shell-snapshots');
|
|
61
|
+
if (!existsSync(dir)) return;
|
|
62
|
+
const cutoff = Date.now() - SNAPSHOT_STALE_MS;
|
|
63
|
+
let names;
|
|
64
|
+
try { names = await readdirAsync(dir); } catch { return; }
|
|
65
|
+
await Promise.all(names.map(async (name) => {
|
|
66
|
+
if (!name.startsWith('snapshot-') || !name.endsWith('.sh')) return;
|
|
67
|
+
const p = join(dir, name);
|
|
68
|
+
try {
|
|
69
|
+
const st = await statAsync(p);
|
|
70
|
+
if (st.mtimeMs < cutoff) await unlinkAsync(p);
|
|
71
|
+
} catch {}
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
// Fire-and-forget. Async dirent iteration keeps the main event loop free
|
|
75
|
+
// while the sweep runs; errors swallowed per-file so a single stat/unlink
|
|
76
|
+
// failure does not abort the rest of the batch.
|
|
77
|
+
_sweepStaleSnapshots();
|
|
78
|
+
|
|
79
|
+
function _registerSnapshotCleanup(snapshotPath) {
|
|
80
|
+
_activeSnapshots.add(snapshotPath);
|
|
81
|
+
if (_cleanupRegistered) return;
|
|
82
|
+
_cleanupRegistered = true;
|
|
83
|
+
// SIGINT/SIGTERM drain runs through drain-registry; bare 'exit' hook stays
|
|
84
|
+
// as an idempotent backup so registry-bypass paths still cleanup snapshots.
|
|
85
|
+
process.once('exit', drainShellSnapshots);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function getConfigFile(shellPath) {
|
|
89
|
+
const lower = shellPath.toLowerCase();
|
|
90
|
+
if (lower.includes('zsh')) return join(homedir(), '.zshrc');
|
|
91
|
+
if (lower.includes('bash')) return join(homedir(), '.bashrc');
|
|
92
|
+
return join(homedir(), '.profile');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// User-state capture script. Functions + aliases + shell options. Writes
|
|
96
|
+
// to $SNAPSHOT_FILE so the parent process can reuse it via `source`.
|
|
97
|
+
//
|
|
98
|
+
// Filtering: completion functions (single-underscore prefix) are dropped
|
|
99
|
+
// since they bloat the snapshot without affecting interactive behaviour.
|
|
100
|
+
// Double-underscore helpers (__pyenv_init etc) are kept.
|
|
101
|
+
function _shellQuote(s) {
|
|
102
|
+
// POSIX single-quote escape: close, escaped quote, reopen.
|
|
103
|
+
return `'${String(s).replace(/'/g, "'\\''")}'`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getSnapshotScript(shellPath, snapshotFilePath, configFileExists) {
|
|
107
|
+
const isZsh = shellPath.toLowerCase().includes('zsh');
|
|
108
|
+
const sourceCfg = configFileExists
|
|
109
|
+
? `source ${_shellQuote(getConfigFile(shellPath))} < /dev/null 2>/dev/null || true`
|
|
110
|
+
: '# no user config file';
|
|
111
|
+
const fnDump = isZsh
|
|
112
|
+
? `
|
|
113
|
+
typeset -f > /dev/null 2>&1
|
|
114
|
+
typeset +f 2>/dev/null | grep -vE '^_[^_]' | while read func; do
|
|
115
|
+
typeset -f "$func" >> "$SNAPSHOT_FILE" 2>/dev/null
|
|
116
|
+
done
|
|
117
|
+
`
|
|
118
|
+
: `
|
|
119
|
+
declare -f > /dev/null 2>&1
|
|
120
|
+
declare -F 2>/dev/null | cut -d' ' -f3 | grep -vE '^_[^_]' | while read func; do
|
|
121
|
+
declare -f "$func" >> "$SNAPSHOT_FILE" 2>/dev/null
|
|
122
|
+
done
|
|
123
|
+
`;
|
|
124
|
+
const optDump = isZsh
|
|
125
|
+
? `setopt 2>/dev/null | sed 's/^/setopt /' | head -n 1000 >> "$SNAPSHOT_FILE"`
|
|
126
|
+
: `
|
|
127
|
+
shopt -p 2>/dev/null | head -n 1000 >> "$SNAPSHOT_FILE"
|
|
128
|
+
set -o 2>/dev/null | grep "on" | awk '{print "set -o " $1}' | head -n 1000 >> "$SNAPSHOT_FILE"
|
|
129
|
+
echo "shopt -s expand_aliases" >> "$SNAPSHOT_FILE"
|
|
130
|
+
`;
|
|
131
|
+
const aliasDump = `
|
|
132
|
+
alias 2>/dev/null | sed 's/^alias //g' | sed 's/^/alias -- /' | head -n 1000 >> "$SNAPSHOT_FILE"
|
|
133
|
+
`;
|
|
134
|
+
return `SNAPSHOT_FILE=${_shellQuote(snapshotFilePath)}
|
|
135
|
+
${sourceCfg}
|
|
136
|
+
echo "# Snapshot" >| "$SNAPSHOT_FILE"
|
|
137
|
+
echo "# Unset all aliases first to avoid frozen-alias issues inside functions" >> "$SNAPSHOT_FILE"
|
|
138
|
+
echo "unalias -a 2>/dev/null || true" >> "$SNAPSHOT_FILE"
|
|
139
|
+
echo "# Functions" >> "$SNAPSHOT_FILE"
|
|
140
|
+
${fnDump}
|
|
141
|
+
echo "# Shell options" >> "$SNAPSHOT_FILE"
|
|
142
|
+
${optDump}
|
|
143
|
+
echo "# Aliases" >> "$SNAPSHOT_FILE"
|
|
144
|
+
${aliasDump}
|
|
145
|
+
# PATH may contain $, backticks, or quotes that would re-expand if we
|
|
146
|
+
# emitted it inside double quotes. Emit a shell-safe single-quoted PATH
|
|
147
|
+
# export line via printf %q-style escaping inside the dump shell.
|
|
148
|
+
printf 'export PATH=' >> "$SNAPSHOT_FILE"
|
|
149
|
+
_q=$(printf %s "$PATH" | sed "s/'/'\\\\''/g")
|
|
150
|
+
printf "'%s'\n" "$_q" >> "$SNAPSHOT_FILE"
|
|
151
|
+
exit 0
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function _runSnapshot(shellPath, snapshotPath, configFileExists) {
|
|
156
|
+
return new Promise((resolve) => {
|
|
157
|
+
const script = getSnapshotScript(shellPath, snapshotPath, configFileExists);
|
|
158
|
+
let stderrBuf = '';
|
|
159
|
+
// Mirror Claude Code (refs/claude-code/utils/bash/ShellSnapshot.ts:458):
|
|
160
|
+
// `-c -l` (login non-interactive). Earlier `-ic` (interactive command)
|
|
161
|
+
// forced bash-completion to load — Git's completion loader spawns `find`
|
|
162
|
+
// in subshells (__git_find_on_cmdline etc.) which detach on Windows when
|
|
163
|
+
// the parent gets SIGTERM at timeout, leaking find.exe processes. Login
|
|
164
|
+
// mode runs .bash_profile / .profile (which typically sources .bashrc)
|
|
165
|
+
// without triggering completion init. The script also explicitly sources
|
|
166
|
+
// the rc file, so the interactive-guard `[[ $- == *i* ]] && return` is
|
|
167
|
+
// accepted as a known tradeoff (matches Claude Code's choice).
|
|
168
|
+
const child = spawn(shellPath, ['-c', '-l', script], {
|
|
169
|
+
// P3 fix: blank prompts so an interactive sourcing in -ic does not
|
|
170
|
+
// print PS1 / PS2 / RPROMPT / PROMPT noise to stderr (which our
|
|
171
|
+
// failure log truncates to 200 chars and tags as "snapshot failed"
|
|
172
|
+
// even when the snapshot itself is fine).
|
|
173
|
+
// R11: scrub loader/execution vars from process.env before
|
|
174
|
+
// handing it to the snapshot shell. This site previously passed
|
|
175
|
+
// raw process.env, bypassing even the R5 secret scrub — the
|
|
176
|
+
// snapshot child sources the user's rc file, so NODE_OPTIONS /
|
|
177
|
+
// LD_PRELOAD / BASH_ENV here would inject into every subsequent
|
|
178
|
+
// bash command that uses this snapshot.
|
|
179
|
+
env: (() => {
|
|
180
|
+
const e = scrubLoaderVars({
|
|
181
|
+
...process.env,
|
|
182
|
+
SHELL: shellPath,
|
|
183
|
+
GIT_EDITOR: 'true',
|
|
184
|
+
CLAUDECODE: '1',
|
|
185
|
+
PS1: '',
|
|
186
|
+
PS2: '',
|
|
187
|
+
PS3: '',
|
|
188
|
+
PS4: '',
|
|
189
|
+
PROMPT: '',
|
|
190
|
+
RPROMPT: '',
|
|
191
|
+
});
|
|
192
|
+
// R5 secret scrub — the rc-sourcing snapshot child runs user code
|
|
193
|
+
// (.bashrc / .zshrc) which can exfil any inherited env. Strip
|
|
194
|
+
// provider/cloud tokens before exposing the env to that script.
|
|
195
|
+
// Shared with bash-session and shell-jobs via env-scrub.mjs.
|
|
196
|
+
scrubProviderSecrets(e);
|
|
197
|
+
return e;
|
|
198
|
+
})(),
|
|
199
|
+
windowsHide: true,
|
|
200
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
201
|
+
});
|
|
202
|
+
child.stderr.setEncoding('utf-8');
|
|
203
|
+
child.stderr.on('data', (s) => {
|
|
204
|
+
stderrBuf += s;
|
|
205
|
+
});
|
|
206
|
+
const timer = setTimeout(() => {
|
|
207
|
+
try {
|
|
208
|
+
child.kill('SIGTERM');
|
|
209
|
+
} catch {}
|
|
210
|
+
}, SNAPSHOT_TIMEOUT_MS);
|
|
211
|
+
if (timer.unref) timer.unref();
|
|
212
|
+
child.once('exit', (code) => {
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
if (code === 0 && existsSync(snapshotPath)) {
|
|
215
|
+
// P3 fix: payload-aware sentinel. Header bytes alone (~80) plus
|
|
216
|
+
// PATH export and `unalias -a` boilerplate can exceed 200 even
|
|
217
|
+
// when no user state was captured. Require at least one of:
|
|
218
|
+
// alias declaration, function definition, or shell-option line.
|
|
219
|
+
let snapContent = '';
|
|
220
|
+
try { snapContent = readFileSync(snapshotPath, 'utf-8'); } catch {}
|
|
221
|
+
const _hasAlias = /^\s*alias\s+--\s/m.test(snapContent);
|
|
222
|
+
const _hasFn = /^\s*[A-Za-z_][\w-]*\s*\(\s*\)\s*\{/m.test(snapContent)
|
|
223
|
+
|| /^\s*function\s+[A-Za-z_]/m.test(snapContent);
|
|
224
|
+
const _hasOpt = /^\s*setopt\b/m.test(snapContent)
|
|
225
|
+
|| /^\s*shopt\s+-s/m.test(snapContent)
|
|
226
|
+
|| /^\s*set\s+-o\s/m.test(snapContent);
|
|
227
|
+
if (!_hasAlias && !_hasFn && !_hasOpt) {
|
|
228
|
+
try {
|
|
229
|
+
process.stderr.write(
|
|
230
|
+
`[shell-snapshot] empty snapshot rejected (no aliases / functions / options captured, size=${snapContent.length})\n`,
|
|
231
|
+
);
|
|
232
|
+
} catch {}
|
|
233
|
+
try { unlinkSync(snapshotPath); } catch {}
|
|
234
|
+
resolve(null);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
_registerSnapshotCleanup(snapshotPath);
|
|
238
|
+
resolve(snapshotPath);
|
|
239
|
+
} else {
|
|
240
|
+
try {
|
|
241
|
+
process.stderr.write(
|
|
242
|
+
`[shell-snapshot] failed exit=${code} stderr=${(stderrBuf || '').slice(0, 200)}\n`,
|
|
243
|
+
);
|
|
244
|
+
} catch {}
|
|
245
|
+
// Failure branch may have left a partially-written file behind.
|
|
246
|
+
try { unlinkSync(snapshotPath); } catch {}
|
|
247
|
+
resolve(null);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
child.once('error', () => {
|
|
251
|
+
clearTimeout(timer);
|
|
252
|
+
resolve(null);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Returns the snapshot file path for the given shell, generating one on
|
|
258
|
+
// first call. Returns null if generation failed (caller falls through to
|
|
259
|
+
// running the command without snapshot prelude).
|
|
260
|
+
async function getOrCreateSnapshot(shellPath) {
|
|
261
|
+
// Cache key includes rc-file mtime/size so editing .bashrc/.zshrc
|
|
262
|
+
// mid-session forces a fresh snapshot on the next call instead of
|
|
263
|
+
// reusing the stale one for the rest of the process lifetime.
|
|
264
|
+
const configFile = getConfigFile(shellPath);
|
|
265
|
+
const configExists = existsSync(configFile);
|
|
266
|
+
let _rcMtime = 0;
|
|
267
|
+
let _rcSize = 0;
|
|
268
|
+
if (configExists) {
|
|
269
|
+
try {
|
|
270
|
+
const _st = statSync(configFile);
|
|
271
|
+
_rcMtime = _st.mtimeMs;
|
|
272
|
+
_rcSize = _st.size;
|
|
273
|
+
} catch {}
|
|
274
|
+
}
|
|
275
|
+
const cacheKey = `${shellPath}|${_rcMtime}|${_rcSize}`;
|
|
276
|
+
if (_failedShells.has(cacheKey)) return null;
|
|
277
|
+
const cached = _cache.get(cacheKey);
|
|
278
|
+
if (cached && existsSync(cached)) return cached;
|
|
279
|
+
const dir = join(getPluginData(), 'shell-snapshots');
|
|
280
|
+
try {
|
|
281
|
+
mkdirSync(dir, { recursive: true });
|
|
282
|
+
} catch {}
|
|
283
|
+
const shellTag = shellPath.toLowerCase().includes('zsh')
|
|
284
|
+
? 'zsh'
|
|
285
|
+
: shellPath.toLowerCase().includes('bash')
|
|
286
|
+
? 'bash'
|
|
287
|
+
: 'sh';
|
|
288
|
+
const snapshotPath = join(
|
|
289
|
+
dir,
|
|
290
|
+
`snapshot-${shellTag}-${Date.now()}-${randomUUID().slice(0, 6)}.sh`,
|
|
291
|
+
);
|
|
292
|
+
const result = await _runSnapshot(shellPath, snapshotPath, configExists);
|
|
293
|
+
if (result) _cache.set(cacheKey, result);
|
|
294
|
+
else _failedShells.add(cacheKey);
|
|
295
|
+
return result;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Wrap a user command so it runs with the captured environment sourced
|
|
299
|
+
// in. Snapshot generation is best-effort — when it fails, the command
|
|
300
|
+
// still runs (without alias / function support).
|
|
301
|
+
export async function wrapCommandWithSnapshot(shellPath, command) {
|
|
302
|
+
if (process.platform === 'win32') return command;
|
|
303
|
+
if (process.env.MIXDOG_BASH_SNAPSHOT === 'off') return command;
|
|
304
|
+
const snapshot = await getOrCreateSnapshot(shellPath).catch(() => null);
|
|
305
|
+
if (!snapshot) return command;
|
|
306
|
+
const escaped = snapshot.replace(/'/g, "'\\''");
|
|
307
|
+
// Source on its own line so the just-loaded aliases are visible to
|
|
308
|
+
// the user command. When alias declarations and the consuming command
|
|
309
|
+
// share a single shell line, alias expansion is skipped on that line
|
|
310
|
+
// (bash POSIX rule) and the user command runs without snapshot
|
|
311
|
+
// aliases applied.
|
|
312
|
+
return `source '${escaped}' 2>/dev/null\n${command}`;
|
|
313
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, existsSync, mkdirSync, copyFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { getPluginData } from './config.mjs';
|
|
4
|
+
|
|
5
|
+
/** Validate workflow name — reject path traversal and invalid characters */
|
|
6
|
+
function isValidName(name) {
|
|
7
|
+
return name && typeof name === 'string' && !/[\/\\]/.test(name) && !name.includes('..')
|
|
8
|
+
&& /^[a-zA-Z0-9._-]+$/.test(name);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Returns the workflows directory path WITHOUT touching the filesystem.
|
|
13
|
+
* Read paths (list/get) use this so they stay strictly side-effect-free
|
|
14
|
+
* under speculative/eager execution; a missing dir is handled by the
|
|
15
|
+
* callers as "no workflows" / not-found.
|
|
16
|
+
*/
|
|
17
|
+
function readWorkflowDir() {
|
|
18
|
+
return join(getPluginData(), 'workflows');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Returns the workflows directory path, creating it if it does not exist.
|
|
23
|
+
* Write paths (seed/save/delete) only.
|
|
24
|
+
*/
|
|
25
|
+
function getWorkflowDir() {
|
|
26
|
+
const dir = readWorkflowDir();
|
|
27
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
28
|
+
return dir;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* List all workflows: [{name, description}].
|
|
33
|
+
* Reads only name + description from each JSON file.
|
|
34
|
+
*/
|
|
35
|
+
export function listWorkflows() {
|
|
36
|
+
const dir = readWorkflowDir();
|
|
37
|
+
const results = [];
|
|
38
|
+
let files;
|
|
39
|
+
try { files = readdirSync(dir); } catch { return results; }
|
|
40
|
+
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
if (!file.endsWith('.json')) continue;
|
|
43
|
+
try {
|
|
44
|
+
const raw = JSON.parse(readFileSync(join(dir, file), 'utf-8'));
|
|
45
|
+
if (raw.name) {
|
|
46
|
+
results.push({ name: raw.name, description: raw.description || '' });
|
|
47
|
+
}
|
|
48
|
+
} catch { /* skip malformed files */ }
|
|
49
|
+
}
|
|
50
|
+
return results;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get a specific workflow by name.
|
|
55
|
+
* Returns the full JSON object or null if not found.
|
|
56
|
+
*/
|
|
57
|
+
export function getWorkflow(name) {
|
|
58
|
+
if (!isValidName(name)) return null;
|
|
59
|
+
const dir = readWorkflowDir();
|
|
60
|
+
const filePath = join(dir, `${name}.json`);
|
|
61
|
+
if (!existsSync(filePath)) return null;
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
64
|
+
} catch { return null; }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Seed default workflows into the user data directory.
|
|
69
|
+
* Only copies when the target directory contains zero .json files,
|
|
70
|
+
* so existing user workflows are never overwritten.
|
|
71
|
+
*/
|
|
72
|
+
export function seedDefaults() {
|
|
73
|
+
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
|
|
74
|
+
if (!pluginRoot) return;
|
|
75
|
+
|
|
76
|
+
const defaultsDir = join(pluginRoot, 'defaults', 'workflows');
|
|
77
|
+
if (!existsSync(defaultsDir)) return;
|
|
78
|
+
|
|
79
|
+
const targetDir = getWorkflowDir();
|
|
80
|
+
|
|
81
|
+
// Check if user already has any workflow files
|
|
82
|
+
let existing;
|
|
83
|
+
try { existing = readdirSync(targetDir).filter(f => f.endsWith('.json')); } catch { existing = []; }
|
|
84
|
+
if (existing.length > 0) return;
|
|
85
|
+
|
|
86
|
+
// Copy all default workflow files
|
|
87
|
+
let defaults;
|
|
88
|
+
try { defaults = readdirSync(defaultsDir).filter(f => f.endsWith('.json')); } catch { return; }
|
|
89
|
+
|
|
90
|
+
for (const file of defaults) {
|
|
91
|
+
copyFileSync(join(defaultsDir, file), join(targetDir, file));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Tool definitions extracted from src/agent/index.mjs for import safety.
|
|
2
|
+
// Pure data: no top-level side effects, no external symbol references.
|
|
3
|
+
//
|
|
4
|
+
// Public entries (advertised in tools.json) come first, then `public:
|
|
5
|
+
// false` entries (reachable through handleToolCall / in-process dispatch
|
|
6
|
+
// only — excluded from build-tools-manifest output so the Lead never
|
|
7
|
+
// sees them).
|
|
8
|
+
export const TOOL_DEFS = [
|
|
9
|
+
{
|
|
10
|
+
name: 'list_models',
|
|
11
|
+
title: 'List Models',
|
|
12
|
+
annotations: { title: 'List Models', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
13
|
+
description: 'List models.',
|
|
14
|
+
inputSchema: { type: 'object', properties: {} },
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: 'explore',
|
|
18
|
+
title: 'Explore',
|
|
19
|
+
aiWrapped: true,
|
|
20
|
+
annotations: { title: 'Explore', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
21
|
+
description: 'Read-only codebase EXPLORATION — fact-finding only: locate/map where and how things are implemented, for open-ended/unknown scope (for a known or partial identifier use code_graph; recall=memory, search=web). NOT a reviewer/auditor: explorers LOCATE and DESCRIBE code, never judge it — bug/quality/risk claims in explore output are UNVERIFIED leads; verify them (reviewer role or direct reads) before acting on or reporting them. Shape every query as a LOCATION/INVENTORY question ("where is X handled", "which files implement Y", "what does Z read/write") — NEVER a verdict question ("is X correct/missing/inconsistent?", "are there gaps/bugs?"); the judgment stays with the caller, applied to the coordinates explore returns. Query shaping (one-line, one topic per item, decompose a multi-part brief) is specified on the query parameter — follow it. Fan-out runs items in parallel; wall-clock = the slowest item. LEAD: default background:true (answer pushed via channel, avoids the 120s sync cap). BRIDGE WORKERS run it sync and SHOULD prefer it for a tree-wide enumeration or broad/unanchored exploration — ONE call offloads the whole sweep into a sub-agent instead of a long grep/code_graph storm; a bounded/known-anchor lookup stays a direct code_graph/grep call.',
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
query: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' }, minItems: 1 }], description: 'Array of independent ONE-LINE questions: each item is ONE short question on ONE topic — do NOT pass a whole brief/context dump as one item; DECOMPOSE a multi-part task into several one-line per-topic questions here. Split by topic; never one broad query. Each item must be location/inventory-shaped (where/which/what), never verdict-shaped (is-it-correct / are-there-problems).' },
|
|
26
|
+
cwd: { type: 'string' },
|
|
27
|
+
background: { type: 'boolean' },
|
|
28
|
+
},
|
|
29
|
+
required: ['query'],
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'get_workflows',
|
|
35
|
+
public: false,
|
|
36
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, bridgeHidden: true },
|
|
37
|
+
description: 'List workflow plans (name + description).',
|
|
38
|
+
inputSchema: { type: 'object', properties: {} },
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'get_workflow',
|
|
42
|
+
public: false,
|
|
43
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, bridgeHidden: true },
|
|
44
|
+
description: 'Get a workflow plan by name. Returns full JSON with steps.',
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
name: { type: 'string', description: 'Workflow name (e.g., "code-review")' },
|
|
49
|
+
},
|
|
50
|
+
required: ['name'],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'set_prompt',
|
|
55
|
+
title: 'Store Prompt',
|
|
56
|
+
annotations: { bridgeHidden: true },
|
|
57
|
+
public: false,
|
|
58
|
+
description: 'Store a long prompt and return a reference key for bridge.ref.',
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: 'object',
|
|
61
|
+
properties: {
|
|
62
|
+
content: { type: 'string', description: 'The prompt content to store' },
|
|
63
|
+
file: { type: 'string', description: 'Read content from this file path instead of content param' },
|
|
64
|
+
key: { type: 'string', description: 'Optional custom key. Auto-generated if omitted.' },
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'bridge',
|
|
70
|
+
title: 'Bridge to External Model',
|
|
71
|
+
annotations: { title: 'Bridge to External Model', readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true, bridgeHidden: true },
|
|
72
|
+
description: 'Unified worker session control. type selects the action (default "spawn"). '
|
|
73
|
+
+ 'spawn: dispatch a detached worker — requires role + message (alias: prompt); optional tag names the session for later send/close (auto "<role><n>" if omitted). '
|
|
74
|
+
+ 'send: resume a worker by tag (or raw sess_ id) — requires tag + message. To CONTINUE the same task on the same files/context — fix rounds, re-reviews, iterative refinement, or any follow-up — PREFER reusing the original tag over a new spawn: it preserves the worker\'s transcript + file context + change history, so it is faster, cheaper (the prompt cache stays warm), and more accurate than re-discovering from scratch. The return\'s respawned flag = false when the live session continued (context kept), true when a closed/cold tag was respawned fresh (context reset). '
|
|
75
|
+
+ 'close: stop a worker — requires tag. '
|
|
76
|
+
+ 'list: enumerate active worker sessions with stage/staleness — no args (optional role/status filter).',
|
|
77
|
+
inputSchema: {
|
|
78
|
+
type: 'object',
|
|
79
|
+
properties: {
|
|
80
|
+
type: { type: 'string', enum: ['spawn', 'send', 'close', 'list'], description: 'Action discriminator. Default "spawn".' },
|
|
81
|
+
role: { type: 'string', description: 'Worker role (from user-workflow). Required for spawn; optional filter for list.' },
|
|
82
|
+
tag: { type: 'string', description: 'Stable session handle. spawn: optional name; send/close: required target (tag or raw sess_ id).' },
|
|
83
|
+
message: { type: 'string', description: 'Brief for spawn / follow-up for send. `prompt` is accepted as an alias on spawn. A spawn brief must state: goal+why, mode (write-code vs research-only), anchor (file:line/symbol/command), and done (output shape + stop condition).' },
|
|
84
|
+
prompt: { type: 'string', description: 'Alias of message for spawn (backward compat).' },
|
|
85
|
+
status: { type: 'string', description: 'list: optional status filter (e.g. running, idle, error).' },
|
|
86
|
+
provider: { type: 'string', description: 'spawn: override the worker provider.' },
|
|
87
|
+
model: { type: 'string', description: 'spawn: override the worker model.' },
|
|
88
|
+
effort: { type: 'string', description: 'spawn: reasoning effort level for the worker.' },
|
|
89
|
+
fast: { type: 'boolean', description: 'spawn: enable fast mode (lower-latency, lighter worker).' },
|
|
90
|
+
preset: { type: 'string', description: 'spawn: profile preset selecting provider/model/effort.' },
|
|
91
|
+
isolation: { type: 'string', enum: ['worktree'], description: 'spawn: run the worker in a dedicated git worktree + branch (opt-in; best-effort — falls back to the plain cwd outside a git repo). Use when parallel workers must edit the same files.' },
|
|
92
|
+
brief: { type: 'boolean', description: 'list: return brief (condensed) session output.' },
|
|
93
|
+
includeClosed: { type: 'boolean', description: 'list: include closed/finished sessions in the listing.' },
|
|
94
|
+
context: { type: 'string' },
|
|
95
|
+
ref: { type: 'string' },
|
|
96
|
+
file: { type: 'string' },
|
|
97
|
+
cwd: { type: 'string' },
|
|
98
|
+
permission_mode: { type: 'string', enum: ['default', 'acceptEdits', 'bypassPermissions', 'plan'] },
|
|
99
|
+
},
|
|
100
|
+
required: [],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
];
|