@wahack/pi-coding-agent 15.11.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/CHANGELOG.md +10031 -0
- package/README.md +36 -0
- package/examples/README.md +21 -0
- package/examples/custom-tools/README.md +104 -0
- package/examples/custom-tools/hello/index.ts +20 -0
- package/examples/extensions/README.md +142 -0
- package/examples/extensions/api-demo.ts +79 -0
- package/examples/extensions/chalk-logger.ts +25 -0
- package/examples/extensions/hello.ts +31 -0
- package/examples/extensions/pirate.ts +43 -0
- package/examples/extensions/plan-mode.ts +549 -0
- package/examples/extensions/reload-runtime.ts +38 -0
- package/examples/extensions/thinking-note.ts +13 -0
- package/examples/extensions/tools.ts +145 -0
- package/examples/extensions/with-deps/index.ts +36 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +17 -0
- package/examples/hooks/README.md +56 -0
- package/examples/hooks/auto-commit-on-exit.ts +48 -0
- package/examples/hooks/confirm-destructive.ts +58 -0
- package/examples/hooks/custom-compaction.ts +115 -0
- package/examples/hooks/dirty-repo-guard.ts +51 -0
- package/examples/hooks/file-trigger.ts +40 -0
- package/examples/hooks/git-checkpoint.ts +52 -0
- package/examples/hooks/handoff.ts +149 -0
- package/examples/hooks/permission-gate.ts +33 -0
- package/examples/hooks/protected-paths.ts +29 -0
- package/examples/hooks/qna.ts +118 -0
- package/examples/hooks/status-line.ts +39 -0
- package/examples/sdk/01-minimal.ts +21 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +46 -0
- package/examples/sdk/04-skills.ts +43 -0
- package/examples/sdk/06-extensions.ts +82 -0
- package/examples/sdk/06-hooks.ts +61 -0
- package/examples/sdk/07-context-files.ts +35 -0
- package/examples/sdk/08-prompt-templates.ts +41 -0
- package/examples/sdk/08-slash-commands.ts +46 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
- package/examples/sdk/11-sessions.ts +47 -0
- package/examples/sdk/12-redis-sessions.ts +54 -0
- package/examples/sdk/13-sql-sessions.ts +61 -0
- package/examples/sdk/README.md +172 -0
- package/package.json +554 -0
- package/scripts/build-binary.ts +100 -0
- package/scripts/bundle-dist.ts +90 -0
- package/scripts/format-prompts.ts +68 -0
- package/scripts/generate-docs-index.ts +40 -0
- package/scripts/generate-template.ts +33 -0
- package/scripts/omp +42 -0
- package/scripts/omp.ts +19 -0
- package/src/async/index.ts +1 -0
- package/src/async/job-manager.ts +625 -0
- package/src/auto-thinking/classifier.ts +185 -0
- package/src/autoresearch/command-resume.md +14 -0
- package/src/autoresearch/dashboard.ts +436 -0
- package/src/autoresearch/git.ts +319 -0
- package/src/autoresearch/helpers.ts +218 -0
- package/src/autoresearch/index.ts +536 -0
- package/src/autoresearch/prompt-setup.md +43 -0
- package/src/autoresearch/prompt.md +103 -0
- package/src/autoresearch/resume-message.md +10 -0
- package/src/autoresearch/state.ts +273 -0
- package/src/autoresearch/storage.ts +699 -0
- package/src/autoresearch/tools/init-experiment.ts +272 -0
- package/src/autoresearch/tools/log-experiment.ts +524 -0
- package/src/autoresearch/tools/run-experiment.ts +407 -0
- package/src/autoresearch/tools/update-notes.ts +109 -0
- package/src/autoresearch/types.ts +168 -0
- package/src/bun-imports.d.ts +28 -0
- package/src/capability/context-file.ts +44 -0
- package/src/capability/extension-module.ts +34 -0
- package/src/capability/extension.ts +47 -0
- package/src/capability/fs.ts +117 -0
- package/src/capability/hook.ts +40 -0
- package/src/capability/index.ts +436 -0
- package/src/capability/instruction.ts +37 -0
- package/src/capability/mcp.ts +74 -0
- package/src/capability/prompt.ts +35 -0
- package/src/capability/rule-buckets.ts +66 -0
- package/src/capability/rule.ts +261 -0
- package/src/capability/settings.ts +34 -0
- package/src/capability/skill.ts +63 -0
- package/src/capability/slash-command.ts +40 -0
- package/src/capability/ssh.ts +41 -0
- package/src/capability/system-prompt.ts +34 -0
- package/src/capability/tool.ts +38 -0
- package/src/capability/types.ts +168 -0
- package/src/cli/agents-cli.ts +138 -0
- package/src/cli/args.ts +340 -0
- package/src/cli/auth-broker-cli.ts +895 -0
- package/src/cli/auth-gateway-cli.ts +611 -0
- package/src/cli/classify-install-target.ts +76 -0
- package/src/cli/claude-trace-cli.ts +795 -0
- package/src/cli/commands/init-xdg.ts +27 -0
- package/src/cli/completion-gen.ts +550 -0
- package/src/cli/config-cli.ts +418 -0
- package/src/cli/dry-balance-cli.ts +856 -0
- package/src/cli/extension-flags.ts +48 -0
- package/src/cli/file-processor.ts +133 -0
- package/src/cli/gallery-cli.ts +230 -0
- package/src/cli/gallery-fixtures/agentic.ts +407 -0
- package/src/cli/gallery-fixtures/codeintel.ts +187 -0
- package/src/cli/gallery-fixtures/edit.ts +194 -0
- package/src/cli/gallery-fixtures/fs.ts +220 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +49 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +250 -0
- package/src/cli/gallery-fixtures/search.ts +213 -0
- package/src/cli/gallery-fixtures/shell.ts +167 -0
- package/src/cli/gallery-fixtures/types.ts +57 -0
- package/src/cli/gallery-fixtures/web.ts +158 -0
- package/src/cli/gallery-screenshot.ts +279 -0
- package/src/cli/grep-cli.ts +160 -0
- package/src/cli/grievances-cli.ts +256 -0
- package/src/cli/initial-message.ts +58 -0
- package/src/cli/list-models.ts +194 -0
- package/src/cli/plugin-cli.ts +996 -0
- package/src/cli/read-cli.ts +57 -0
- package/src/cli/session-picker.ts +79 -0
- package/src/cli/setup-cli.ts +231 -0
- package/src/cli/shell-cli.ts +176 -0
- package/src/cli/ssh-cli.ts +179 -0
- package/src/cli/startup-cwd.ts +68 -0
- package/src/cli/stats-cli.ts +238 -0
- package/src/cli/tiny-models-cli.ts +127 -0
- package/src/cli/update-cli.ts +611 -0
- package/src/cli/usage-cli.ts +603 -0
- package/src/cli/web-search-cli.ts +132 -0
- package/src/cli/worktree-cli.ts +291 -0
- package/src/cli-commands.ts +79 -0
- package/src/cli.ts +200 -0
- package/src/commands/acp.ts +24 -0
- package/src/commands/agents.ts +57 -0
- package/src/commands/auth-broker.ts +99 -0
- package/src/commands/auth-gateway.ts +69 -0
- package/src/commands/commit.ts +46 -0
- package/src/commands/complete.ts +66 -0
- package/src/commands/completions.ts +60 -0
- package/src/commands/config.ts +51 -0
- package/src/commands/dry-balance.ts +43 -0
- package/src/commands/gallery.ts +52 -0
- package/src/commands/grep.ts +48 -0
- package/src/commands/grievances.ts +51 -0
- package/src/commands/install.ts +107 -0
- package/src/commands/launch.ts +169 -0
- package/src/commands/plugin.ts +78 -0
- package/src/commands/read.ts +38 -0
- package/src/commands/setup.ts +67 -0
- package/src/commands/shell.ts +29 -0
- package/src/commands/ssh.ts +60 -0
- package/src/commands/stats.ts +29 -0
- package/src/commands/tiny-models.ts +36 -0
- package/src/commands/update.ts +21 -0
- package/src/commands/usage.ts +35 -0
- package/src/commands/web-search.ts +42 -0
- package/src/commands/worktree.ts +56 -0
- package/src/commit/agentic/agent.ts +317 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +355 -0
- package/src/commit/agentic/prompts/analyze-file.md +22 -0
- package/src/commit/agentic/prompts/session-user.md +25 -0
- package/src/commit/agentic/prompts/split-confirm.md +1 -0
- package/src/commit/agentic/prompts/system.md +38 -0
- package/src/commit/agentic/state.ts +60 -0
- package/src/commit/agentic/tools/analyze-file.ts +146 -0
- package/src/commit/agentic/tools/git-file-diff.ts +191 -0
- package/src/commit/agentic/tools/git-hunk.ts +50 -0
- package/src/commit/agentic/tools/git-overview.ts +81 -0
- package/src/commit/agentic/tools/index.ts +54 -0
- package/src/commit/agentic/tools/propose-changelog.ts +144 -0
- package/src/commit/agentic/tools/propose-commit.ts +109 -0
- package/src/commit/agentic/tools/recent-commits.ts +81 -0
- package/src/commit/agentic/tools/schemas.ts +23 -0
- package/src/commit/agentic/tools/split-commit.ts +245 -0
- package/src/commit/agentic/topo-sort.ts +44 -0
- package/src/commit/agentic/trivial.ts +51 -0
- package/src/commit/agentic/validation.ts +183 -0
- package/src/commit/analysis/conventional.ts +64 -0
- package/src/commit/analysis/index.ts +4 -0
- package/src/commit/analysis/scope.ts +242 -0
- package/src/commit/analysis/summary.ts +105 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +40 -0
- package/src/commit/changelog/generate.ts +97 -0
- package/src/commit/changelog/index.ts +234 -0
- package/src/commit/changelog/parse.ts +44 -0
- package/src/commit/cli.ts +85 -0
- package/src/commit/git/diff.ts +148 -0
- package/src/commit/index.ts +5 -0
- package/src/commit/map-reduce/index.ts +69 -0
- package/src/commit/map-reduce/map-phase.ts +193 -0
- package/src/commit/map-reduce/reduce-phase.ts +49 -0
- package/src/commit/map-reduce/utils.ts +9 -0
- package/src/commit/message.ts +11 -0
- package/src/commit/model-selection.ts +92 -0
- package/src/commit/pipeline.ts +243 -0
- package/src/commit/prompts/analysis-system.md +148 -0
- package/src/commit/prompts/analysis-user.md +38 -0
- package/src/commit/prompts/changelog-system.md +50 -0
- package/src/commit/prompts/changelog-user.md +18 -0
- package/src/commit/prompts/file-observer-system.md +24 -0
- package/src/commit/prompts/file-observer-user.md +8 -0
- package/src/commit/prompts/reduce-system.md +50 -0
- package/src/commit/prompts/reduce-user.md +17 -0
- package/src/commit/prompts/summary-retry.md +3 -0
- package/src/commit/prompts/summary-system.md +38 -0
- package/src/commit/prompts/summary-user.md +13 -0
- package/src/commit/prompts/types-description.md +2 -0
- package/src/commit/shared-llm.ts +77 -0
- package/src/commit/types.ts +118 -0
- package/src/commit/utils/exclusions.ts +42 -0
- package/src/commit/utils.ts +58 -0
- package/src/config/api-key-resolver.ts +60 -0
- package/src/config/append-only-context-mode.ts +31 -0
- package/src/config/config-file.ts +317 -0
- package/src/config/file-lock.ts +164 -0
- package/src/config/keybindings.ts +628 -0
- package/src/config/mcp-schema.json +230 -0
- package/src/config/model-discovery.ts +554 -0
- package/src/config/model-registry.ts +2090 -0
- package/src/config/model-resolver.ts +1502 -0
- package/src/config/model-roles.ts +74 -0
- package/src/config/models-config-schema.ts +226 -0
- package/src/config/models-config.ts +129 -0
- package/src/config/prompt-templates.ts +185 -0
- package/src/config/resolve-config-value.ts +94 -0
- package/src/config/settings-schema.ts +3530 -0
- package/src/config/settings.ts +1178 -0
- package/src/config.ts +242 -0
- package/src/cursor.ts +340 -0
- package/src/dap/client.ts +760 -0
- package/src/dap/config.ts +189 -0
- package/src/dap/defaults.json +212 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1441 -0
- package/src/dap/types.ts +610 -0
- package/src/debug/index.ts +515 -0
- package/src/debug/log-formatting.ts +58 -0
- package/src/debug/log-viewer.ts +908 -0
- package/src/debug/profiler.ts +162 -0
- package/src/debug/protocol-probe.ts +267 -0
- package/src/debug/raw-sse-buffer.ts +273 -0
- package/src/debug/raw-sse.ts +292 -0
- package/src/debug/report-bundle.ts +374 -0
- package/src/debug/system-info.ts +111 -0
- package/src/debug/terminal-info.ts +124 -0
- package/src/discovery/agents-md.ts +67 -0
- package/src/discovery/agents.ts +230 -0
- package/src/discovery/at-imports.ts +273 -0
- package/src/discovery/builtin-defaults.ts +39 -0
- package/src/discovery/builtin-rules/index.ts +54 -0
- package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
- package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
- package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
- package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
- package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
- package/src/discovery/builtin-rules/rs-result-type.md +19 -0
- package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
- package/src/discovery/builtin-rules/ts-import-type.md +42 -0
- package/src/discovery/builtin-rules/ts-no-any.md +56 -0
- package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
- package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
- package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
- package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
- package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
- package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
- package/src/discovery/builtin-rules/ts-set-map.md +28 -0
- package/src/discovery/builtin.ts +906 -0
- package/src/discovery/claude-plugins.ts +386 -0
- package/src/discovery/claude.ts +584 -0
- package/src/discovery/cline.ts +83 -0
- package/src/discovery/codex.ts +522 -0
- package/src/discovery/cursor.ts +220 -0
- package/src/discovery/gemini.ts +383 -0
- package/src/discovery/github.ts +154 -0
- package/src/discovery/helpers.ts +1016 -0
- package/src/discovery/index.ts +81 -0
- package/src/discovery/mcp-json.ts +171 -0
- package/src/discovery/omp-extension-roots.ts +190 -0
- package/src/discovery/omp-plugins.ts +383 -0
- package/src/discovery/opencode.ts +398 -0
- package/src/discovery/plugin-dir-roots.ts +28 -0
- package/src/discovery/ssh.ts +153 -0
- package/src/discovery/substitute-plugin-root.ts +29 -0
- package/src/discovery/vscode.ts +105 -0
- package/src/discovery/windsurf.ts +147 -0
- package/src/edit/apply-patch/index.ts +87 -0
- package/src/edit/apply-patch/parser.ts +174 -0
- package/src/edit/diff.ts +999 -0
- package/src/edit/file-snapshot-store.ts +91 -0
- package/src/edit/hashline/block-resolver.ts +33 -0
- package/src/edit/hashline/diff.ts +290 -0
- package/src/edit/hashline/execute.ts +242 -0
- package/src/edit/hashline/filesystem.ts +130 -0
- package/src/edit/hashline/index.ts +5 -0
- package/src/edit/hashline/noop-loop-guard.ts +99 -0
- package/src/edit/hashline/params.ts +18 -0
- package/src/edit/index.ts +571 -0
- package/src/edit/modes/apply-patch.lark +19 -0
- package/src/edit/modes/apply-patch.ts +53 -0
- package/src/edit/modes/patch.ts +1891 -0
- package/src/edit/modes/replace.ts +1137 -0
- package/src/edit/normalize.ts +345 -0
- package/src/edit/notebook.ts +242 -0
- package/src/edit/read-file.ts +25 -0
- package/src/edit/renderer.ts +769 -0
- package/src/edit/streaming.ts +517 -0
- package/src/eval/__tests__/agent-bridge.test.ts +708 -0
- package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
- package/src/eval/__tests__/budget-bridge.test.ts +69 -0
- package/src/eval/__tests__/completion-bridge.test.ts +412 -0
- package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
- package/src/eval/__tests__/idle-timeout.test.ts +80 -0
- package/src/eval/__tests__/js-context-manager.test.ts +241 -0
- package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
- package/src/eval/agent-bridge.ts +319 -0
- package/src/eval/backend.ts +71 -0
- package/src/eval/bridge-timeout.ts +44 -0
- package/src/eval/budget-bridge.ts +48 -0
- package/src/eval/completion-bridge.ts +207 -0
- package/src/eval/concurrency-bridge.ts +34 -0
- package/src/eval/idle-timeout.ts +91 -0
- package/src/eval/index.ts +4 -0
- package/src/eval/js/context-manager.ts +502 -0
- package/src/eval/js/executor.ts +173 -0
- package/src/eval/js/index.ts +51 -0
- package/src/eval/js/shared/helpers.ts +283 -0
- package/src/eval/js/shared/indirect-eval.ts +30 -0
- package/src/eval/js/shared/local-module-loader.ts +342 -0
- package/src/eval/js/shared/prelude.ts +2 -0
- package/src/eval/js/shared/prelude.txt +246 -0
- package/src/eval/js/shared/rewrite-imports.ts +532 -0
- package/src/eval/js/shared/runtime.ts +352 -0
- package/src/eval/js/shared/types.ts +18 -0
- package/src/eval/js/tool-bridge.ts +162 -0
- package/src/eval/js/worker-core.ts +132 -0
- package/src/eval/js/worker-entry.ts +30 -0
- package/src/eval/js/worker-protocol.ts +47 -0
- package/src/eval/py/__tests__/prelude.test.ts +19 -0
- package/src/eval/py/display.ts +71 -0
- package/src/eval/py/executor.ts +742 -0
- package/src/eval/py/index.ts +68 -0
- package/src/eval/py/kernel.ts +748 -0
- package/src/eval/py/prelude.py +658 -0
- package/src/eval/py/prelude.ts +3 -0
- package/src/eval/py/runner.py +1133 -0
- package/src/eval/py/runtime.ts +276 -0
- package/src/eval/py/spawn-options.ts +126 -0
- package/src/eval/py/tool-bridge.ts +182 -0
- package/src/eval/session-id.ts +8 -0
- package/src/eval/types.ts +48 -0
- package/src/exa/index.ts +2 -0
- package/src/exa/mcp-client.ts +370 -0
- package/src/exa/types.ts +69 -0
- package/src/exec/bash-executor.ts +419 -0
- package/src/exec/exec.ts +53 -0
- package/src/exec/non-interactive-env.ts +48 -0
- package/src/export/custom-share.ts +65 -0
- package/src/export/html/index.ts +164 -0
- package/src/export/html/template.css +1051 -0
- package/src/export/html/template.generated.ts +2 -0
- package/src/export/html/template.html +46 -0
- package/src/export/html/template.js +2271 -0
- package/src/export/html/template.macro.ts +25 -0
- package/src/export/html/vendor/highlight.min.js +1213 -0
- package/src/export/html/vendor/marked.min.js +6 -0
- package/src/export/ttsr.ts +583 -0
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
- package/src/extensibility/custom-commands/bundled/review/index.ts +489 -0
- package/src/extensibility/custom-commands/index.ts +2 -0
- package/src/extensibility/custom-commands/loader.ts +238 -0
- package/src/extensibility/custom-commands/types.ts +113 -0
- package/src/extensibility/custom-tools/index.ts +7 -0
- package/src/extensibility/custom-tools/loader.ts +269 -0
- package/src/extensibility/custom-tools/types.ts +270 -0
- package/src/extensibility/custom-tools/wrapper.ts +47 -0
- package/src/extensibility/extensions/compact-handler.ts +40 -0
- package/src/extensibility/extensions/get-commands-handler.ts +78 -0
- package/src/extensibility/extensions/index.ts +16 -0
- package/src/extensibility/extensions/loader.ts +572 -0
- package/src/extensibility/extensions/runner.ts +922 -0
- package/src/extensibility/extensions/types.ts +1322 -0
- package/src/extensibility/extensions/wrapper.ts +223 -0
- package/src/extensibility/hooks/index.ts +5 -0
- package/src/extensibility/hooks/loader.ts +257 -0
- package/src/extensibility/hooks/runner.ts +425 -0
- package/src/extensibility/hooks/tool-wrapper.ts +107 -0
- package/src/extensibility/hooks/types.ts +606 -0
- package/src/extensibility/legacy-pi-ai-shim.ts +24 -0
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +15 -0
- package/src/extensibility/plugins/doctor.ts +65 -0
- package/src/extensibility/plugins/git-url.ts +367 -0
- package/src/extensibility/plugins/index.ts +9 -0
- package/src/extensibility/plugins/installer.ts +192 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +682 -0
- package/src/extensibility/plugins/loader.ts +313 -0
- package/src/extensibility/plugins/manager.ts +827 -0
- package/src/extensibility/plugins/marketplace/cache.ts +136 -0
- package/src/extensibility/plugins/marketplace/fetcher.ts +317 -0
- package/src/extensibility/plugins/marketplace/index.ts +6 -0
- package/src/extensibility/plugins/marketplace/manager.ts +770 -0
- package/src/extensibility/plugins/marketplace/registry.ts +196 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
- package/src/extensibility/plugins/marketplace/types.ts +191 -0
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/extensibility/plugins/parser.ts +105 -0
- package/src/extensibility/plugins/types.ts +194 -0
- package/src/extensibility/shared-events.ts +343 -0
- package/src/extensibility/skills.ts +312 -0
- package/src/extensibility/slash-commands.ts +227 -0
- package/src/extensibility/tool-proxy.ts +25 -0
- package/src/extensibility/typebox.ts +418 -0
- package/src/extensibility/utils.ts +44 -0
- package/src/goals/index.ts +3 -0
- package/src/goals/runtime.ts +528 -0
- package/src/goals/state.ts +37 -0
- package/src/goals/tools/goal-tool.ts +251 -0
- package/src/hindsight/backend.ts +354 -0
- package/src/hindsight/bank.ts +156 -0
- package/src/hindsight/client.ts +598 -0
- package/src/hindsight/config.ts +175 -0
- package/src/hindsight/content.ts +210 -0
- package/src/hindsight/index.ts +8 -0
- package/src/hindsight/mental-models.ts +429 -0
- package/src/hindsight/seeds.json +32 -0
- package/src/hindsight/state.ts +488 -0
- package/src/hindsight/transcript.ts +71 -0
- package/src/index.ts +59 -0
- package/src/internal-urls/agent-protocol.ts +146 -0
- package/src/internal-urls/artifact-protocol.ts +107 -0
- package/src/internal-urls/docs-index.generated.ts +106 -0
- package/src/internal-urls/history-protocol.ts +113 -0
- package/src/internal-urls/index.ts +25 -0
- package/src/internal-urls/issue-pr-protocol.ts +584 -0
- package/src/internal-urls/json-query.ts +126 -0
- package/src/internal-urls/local-protocol.ts +287 -0
- package/src/internal-urls/mcp-protocol.ts +151 -0
- package/src/internal-urls/memory-protocol.ts +169 -0
- package/src/internal-urls/omp-protocol.ts +93 -0
- package/src/internal-urls/parse.ts +72 -0
- package/src/internal-urls/registry-helpers.ts +25 -0
- package/src/internal-urls/router.ts +105 -0
- package/src/internal-urls/rule-protocol.ts +45 -0
- package/src/internal-urls/skill-protocol.ts +96 -0
- package/src/internal-urls/types.ts +152 -0
- package/src/internal-urls/vault-protocol.ts +936 -0
- package/src/irc/bus.ts +292 -0
- package/src/lib/xai-http.ts +124 -0
- package/src/lsp/client.ts +1193 -0
- package/src/lsp/clients/biome-client.ts +264 -0
- package/src/lsp/clients/index.ts +50 -0
- package/src/lsp/clients/lsp-linter-client.ts +93 -0
- package/src/lsp/clients/swiftlint-client.ts +120 -0
- package/src/lsp/config.ts +502 -0
- package/src/lsp/defaults.json +493 -0
- package/src/lsp/diagnostics-ledger.ts +51 -0
- package/src/lsp/edits.ts +267 -0
- package/src/lsp/index.ts +2477 -0
- package/src/lsp/lspmux.ts +233 -0
- package/src/lsp/render.ts +694 -0
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +455 -0
- package/src/lsp/utils.ts +718 -0
- package/src/main.ts +1325 -0
- package/src/mcp/client.ts +484 -0
- package/src/mcp/config-writer.ts +225 -0
- package/src/mcp/config.ts +365 -0
- package/src/mcp/index.ts +29 -0
- package/src/mcp/json-rpc.ts +122 -0
- package/src/mcp/loader.ts +124 -0
- package/src/mcp/manager.ts +1275 -0
- package/src/mcp/oauth-discovery.ts +442 -0
- package/src/mcp/oauth-flow.ts +442 -0
- package/src/mcp/render.ts +132 -0
- package/src/mcp/smithery-auth.ts +104 -0
- package/src/mcp/smithery-connect.ts +145 -0
- package/src/mcp/smithery-registry.ts +477 -0
- package/src/mcp/timeout.ts +59 -0
- package/src/mcp/tool-bridge.ts +426 -0
- package/src/mcp/tool-cache.ts +117 -0
- package/src/mcp/transports/http.ts +519 -0
- package/src/mcp/transports/index.ts +6 -0
- package/src/mcp/transports/stdio.ts +528 -0
- package/src/mcp/types.ts +423 -0
- package/src/memories/index.ts +1150 -0
- package/src/memories/storage.ts +577 -0
- package/src/memory-backend/index.ts +18 -0
- package/src/memory-backend/local-backend.ts +39 -0
- package/src/memory-backend/off-backend.ts +25 -0
- package/src/memory-backend/resolve.ts +25 -0
- package/src/memory-backend/runtime.ts +66 -0
- package/src/memory-backend/types.ts +166 -0
- package/src/mnemopi/backend.ts +547 -0
- package/src/mnemopi/config.ts +160 -0
- package/src/mnemopi/index.ts +3 -0
- package/src/mnemopi/state.ts +584 -0
- package/src/modes/acp/acp-agent.ts +2407 -0
- package/src/modes/acp/acp-client-bridge.ts +154 -0
- package/src/modes/acp/acp-event-mapper.ts +929 -0
- package/src/modes/acp/acp-mode.ts +23 -0
- package/src/modes/acp/index.ts +2 -0
- package/src/modes/acp/terminal-auth.ts +37 -0
- package/src/modes/components/agent-dashboard.ts +1206 -0
- package/src/modes/components/agent-hub.ts +1071 -0
- package/src/modes/components/assistant-message.ts +307 -0
- package/src/modes/components/bash-execution.ts +220 -0
- package/src/modes/components/bordered-loader.ts +41 -0
- package/src/modes/components/branch-summary-message.ts +45 -0
- package/src/modes/components/btw-panel.ts +104 -0
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/compaction-summary-message.ts +87 -0
- package/src/modes/components/copy-selector.ts +206 -0
- package/src/modes/components/countdown-timer.ts +75 -0
- package/src/modes/components/custom-editor.ts +398 -0
- package/src/modes/components/custom-message.ts +63 -0
- package/src/modes/components/diff.ts +277 -0
- package/src/modes/components/dynamic-border.ts +34 -0
- package/src/modes/components/error-banner.ts +33 -0
- package/src/modes/components/eval-execution.ts +158 -0
- package/src/modes/components/execution-shared.ts +101 -0
- package/src/modes/components/extensions/extension-dashboard.ts +399 -0
- package/src/modes/components/extensions/extension-list.ts +502 -0
- package/src/modes/components/extensions/index.ts +9 -0
- package/src/modes/components/extensions/inspector-panel.ts +317 -0
- package/src/modes/components/extensions/state-manager.ts +627 -0
- package/src/modes/components/extensions/types.ts +186 -0
- package/src/modes/components/footer.ts +274 -0
- package/src/modes/components/history-search.ts +280 -0
- package/src/modes/components/hook-editor.ts +167 -0
- package/src/modes/components/hook-input.ts +87 -0
- package/src/modes/components/hook-message.ts +66 -0
- package/src/modes/components/hook-selector.ts +660 -0
- package/src/modes/components/index.ts +38 -0
- package/src/modes/components/keybinding-hints.ts +65 -0
- package/src/modes/components/late-diagnostics-message.ts +60 -0
- package/src/modes/components/login-dialog.ts +164 -0
- package/src/modes/components/mcp-add-wizard.ts +1340 -0
- package/src/modes/components/message-frame.ts +88 -0
- package/src/modes/components/model-selector.ts +1271 -0
- package/src/modes/components/oauth-selector.ts +368 -0
- package/src/modes/components/omfg-panel.ts +141 -0
- package/src/modes/components/overlay-box.ts +108 -0
- package/src/modes/components/plan-review-overlay.ts +820 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/plugin-selector.ts +95 -0
- package/src/modes/components/plugin-settings.ts +722 -0
- package/src/modes/components/queue-mode-selector.ts +56 -0
- package/src/modes/components/read-tool-group.ts +670 -0
- package/src/modes/components/segment-track.ts +52 -0
- package/src/modes/components/session-selector.ts +625 -0
- package/src/modes/components/settings-defs.ts +189 -0
- package/src/modes/components/settings-selector.ts +651 -0
- package/src/modes/components/show-images-selector.ts +45 -0
- package/src/modes/components/skill-message.ts +89 -0
- package/src/modes/components/status-line/component.ts +869 -0
- package/src/modes/components/status-line/context-thresholds.ts +79 -0
- package/src/modes/components/status-line/git-utils.ts +42 -0
- package/src/modes/components/status-line/index.ts +5 -0
- package/src/modes/components/status-line/presets.ts +106 -0
- package/src/modes/components/status-line/segments.ts +584 -0
- package/src/modes/components/status-line/separators.ts +55 -0
- package/src/modes/components/status-line/token-rate.ts +66 -0
- package/src/modes/components/status-line/types.ts +108 -0
- package/src/modes/components/theme-selector.ts +63 -0
- package/src/modes/components/thinking-selector.ts +52 -0
- package/src/modes/components/tiny-title-download-progress.ts +90 -0
- package/src/modes/components/tips.txt +19 -0
- package/src/modes/components/todo-reminder.ts +38 -0
- package/src/modes/components/tool-execution.ts +1024 -0
- package/src/modes/components/transcript-container.ts +608 -0
- package/src/modes/components/tree-selector.ts +978 -0
- package/src/modes/components/ttsr-notification.ts +122 -0
- package/src/modes/components/user-message-selector.ts +227 -0
- package/src/modes/components/user-message.ts +66 -0
- package/src/modes/components/visual-truncate.ts +63 -0
- package/src/modes/components/welcome.ts +493 -0
- package/src/modes/controllers/btw-controller.ts +105 -0
- package/src/modes/controllers/command-controller-shared.ts +109 -0
- package/src/modes/controllers/command-controller.ts +1566 -0
- package/src/modes/controllers/event-controller.ts +1054 -0
- package/src/modes/controllers/extension-ui-controller.ts +886 -0
- package/src/modes/controllers/input-controller.ts +1073 -0
- package/src/modes/controllers/mcp-command-controller.ts +2017 -0
- package/src/modes/controllers/omfg-controller.ts +283 -0
- package/src/modes/controllers/omfg-rule.ts +647 -0
- package/src/modes/controllers/selector-controller.ts +1108 -0
- package/src/modes/controllers/ssh-command-controller.ts +384 -0
- package/src/modes/controllers/streaming-reveal.ts +279 -0
- package/src/modes/controllers/tan-command-controller.ts +173 -0
- package/src/modes/controllers/todo-command-controller.ts +485 -0
- package/src/modes/data/emojis.json +1 -0
- package/src/modes/emoji-autocomplete.ts +285 -0
- package/src/modes/gradient-highlight.ts +87 -0
- package/src/modes/image-references.ts +117 -0
- package/src/modes/index.ts +17 -0
- package/src/modes/interactive-mode.ts +3370 -0
- package/src/modes/internal-url-autocomplete.ts +143 -0
- package/src/modes/loop-limit.ts +140 -0
- package/src/modes/magic-keywords.ts +20 -0
- package/src/modes/markdown-prose.ts +247 -0
- package/src/modes/oauth-manual-input.ts +69 -0
- package/src/modes/orchestrate.ts +42 -0
- package/src/modes/print-mode.ts +126 -0
- package/src/modes/prompt-action-autocomplete.ts +260 -0
- package/src/modes/rpc/host-tools.ts +186 -0
- package/src/modes/rpc/host-uris.ts +235 -0
- package/src/modes/rpc/rpc-client.ts +963 -0
- package/src/modes/rpc/rpc-mode.ts +947 -0
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +458 -0
- package/src/modes/runtime-init.ts +116 -0
- package/src/modes/session-observer-registry.ts +146 -0
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +99 -0
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +69 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +205 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +299 -0
- package/src/modes/setup-wizard/scenes/types.ts +48 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +129 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
- package/src/modes/shared.ts +47 -0
- package/src/modes/theme/dark.json +95 -0
- package/src/modes/theme/defaults/alabaster.json +93 -0
- package/src/modes/theme/defaults/amethyst.json +96 -0
- package/src/modes/theme/defaults/anthracite.json +93 -0
- package/src/modes/theme/defaults/basalt.json +91 -0
- package/src/modes/theme/defaults/birch.json +95 -0
- package/src/modes/theme/defaults/dark-abyss.json +91 -0
- package/src/modes/theme/defaults/dark-arctic.json +104 -0
- package/src/modes/theme/defaults/dark-aurora.json +95 -0
- package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
- package/src/modes/theme/defaults/dark-cavern.json +91 -0
- package/src/modes/theme/defaults/dark-copper.json +95 -0
- package/src/modes/theme/defaults/dark-cosmos.json +90 -0
- package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
- package/src/modes/theme/defaults/dark-dracula.json +98 -0
- package/src/modes/theme/defaults/dark-eclipse.json +91 -0
- package/src/modes/theme/defaults/dark-ember.json +95 -0
- package/src/modes/theme/defaults/dark-equinox.json +90 -0
- package/src/modes/theme/defaults/dark-forest.json +96 -0
- package/src/modes/theme/defaults/dark-github.json +105 -0
- package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
- package/src/modes/theme/defaults/dark-lavender.json +95 -0
- package/src/modes/theme/defaults/dark-lunar.json +89 -0
- package/src/modes/theme/defaults/dark-midnight.json +95 -0
- package/src/modes/theme/defaults/dark-monochrome.json +94 -0
- package/src/modes/theme/defaults/dark-monokai.json +98 -0
- package/src/modes/theme/defaults/dark-nebula.json +90 -0
- package/src/modes/theme/defaults/dark-nord.json +97 -0
- package/src/modes/theme/defaults/dark-ocean.json +101 -0
- package/src/modes/theme/defaults/dark-one.json +100 -0
- package/src/modes/theme/defaults/dark-poimandres.json +142 -0
- package/src/modes/theme/defaults/dark-rainforest.json +91 -0
- package/src/modes/theme/defaults/dark-reef.json +91 -0
- package/src/modes/theme/defaults/dark-retro.json +92 -0
- package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
- package/src/modes/theme/defaults/dark-sakura.json +95 -0
- package/src/modes/theme/defaults/dark-slate.json +95 -0
- package/src/modes/theme/defaults/dark-solarized.json +97 -0
- package/src/modes/theme/defaults/dark-solstice.json +90 -0
- package/src/modes/theme/defaults/dark-starfall.json +91 -0
- package/src/modes/theme/defaults/dark-sunset.json +99 -0
- package/src/modes/theme/defaults/dark-swamp.json +90 -0
- package/src/modes/theme/defaults/dark-synthwave.json +103 -0
- package/src/modes/theme/defaults/dark-taiga.json +91 -0
- package/src/modes/theme/defaults/dark-terminal.json +95 -0
- package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
- package/src/modes/theme/defaults/dark-tundra.json +91 -0
- package/src/modes/theme/defaults/dark-twilight.json +91 -0
- package/src/modes/theme/defaults/dark-volcanic.json +91 -0
- package/src/modes/theme/defaults/graphite.json +92 -0
- package/src/modes/theme/defaults/index.ts +199 -0
- package/src/modes/theme/defaults/light-arctic.json +107 -0
- package/src/modes/theme/defaults/light-aurora-day.json +91 -0
- package/src/modes/theme/defaults/light-canyon.json +91 -0
- package/src/modes/theme/defaults/light-catppuccin.json +106 -0
- package/src/modes/theme/defaults/light-cirrus.json +90 -0
- package/src/modes/theme/defaults/light-coral.json +95 -0
- package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
- package/src/modes/theme/defaults/light-dawn.json +90 -0
- package/src/modes/theme/defaults/light-dunes.json +91 -0
- package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
- package/src/modes/theme/defaults/light-forest.json +100 -0
- package/src/modes/theme/defaults/light-frost.json +95 -0
- package/src/modes/theme/defaults/light-github.json +115 -0
- package/src/modes/theme/defaults/light-glacier.json +91 -0
- package/src/modes/theme/defaults/light-gruvbox.json +108 -0
- package/src/modes/theme/defaults/light-haze.json +90 -0
- package/src/modes/theme/defaults/light-honeycomb.json +95 -0
- package/src/modes/theme/defaults/light-lagoon.json +91 -0
- package/src/modes/theme/defaults/light-lavender.json +95 -0
- package/src/modes/theme/defaults/light-meadow.json +91 -0
- package/src/modes/theme/defaults/light-mint.json +95 -0
- package/src/modes/theme/defaults/light-monochrome.json +101 -0
- package/src/modes/theme/defaults/light-ocean.json +99 -0
- package/src/modes/theme/defaults/light-one.json +99 -0
- package/src/modes/theme/defaults/light-opal.json +91 -0
- package/src/modes/theme/defaults/light-orchard.json +91 -0
- package/src/modes/theme/defaults/light-paper.json +95 -0
- package/src/modes/theme/defaults/light-poimandres.json +142 -0
- package/src/modes/theme/defaults/light-prism.json +90 -0
- package/src/modes/theme/defaults/light-retro.json +98 -0
- package/src/modes/theme/defaults/light-sand.json +95 -0
- package/src/modes/theme/defaults/light-savanna.json +91 -0
- package/src/modes/theme/defaults/light-solarized.json +102 -0
- package/src/modes/theme/defaults/light-soleil.json +90 -0
- package/src/modes/theme/defaults/light-sunset.json +99 -0
- package/src/modes/theme/defaults/light-synthwave.json +98 -0
- package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
- package/src/modes/theme/defaults/light-wetland.json +91 -0
- package/src/modes/theme/defaults/light-zenith.json +89 -0
- package/src/modes/theme/defaults/limestone.json +94 -0
- package/src/modes/theme/defaults/mahogany.json +97 -0
- package/src/modes/theme/defaults/marble.json +93 -0
- package/src/modes/theme/defaults/obsidian.json +91 -0
- package/src/modes/theme/defaults/onyx.json +91 -0
- package/src/modes/theme/defaults/pearl.json +93 -0
- package/src/modes/theme/defaults/porcelain.json +91 -0
- package/src/modes/theme/defaults/quartz.json +96 -0
- package/src/modes/theme/defaults/sandstone.json +95 -0
- package/src/modes/theme/defaults/titanium.json +90 -0
- package/src/modes/theme/light.json +93 -0
- package/src/modes/theme/mermaid-cache.ts +29 -0
- package/src/modes/theme/shimmer.ts +235 -0
- package/src/modes/theme/theme-schema.json +459 -0
- package/src/modes/theme/theme.ts +2676 -0
- package/src/modes/turn-budget.ts +31 -0
- package/src/modes/types.ts +359 -0
- package/src/modes/ultrathink.ts +41 -0
- package/src/modes/utils/context-usage.ts +339 -0
- package/src/modes/utils/copy-targets.ts +360 -0
- package/src/modes/utils/hotkeys-markdown.ts +61 -0
- package/src/modes/utils/keybinding-matchers.ts +51 -0
- package/src/modes/utils/tools-markdown.ts +27 -0
- package/src/modes/utils/ui-helpers.ts +801 -0
- package/src/modes/workflow.ts +42 -0
- package/src/plan-mode/approved-plan.ts +186 -0
- package/src/plan-mode/plan-handoff.ts +37 -0
- package/src/plan-mode/plan-protection.ts +31 -0
- package/src/plan-mode/state.ts +6 -0
- package/src/priority.json +41 -0
- package/src/prompts/agents/designer.md +66 -0
- package/src/prompts/agents/explore.md +58 -0
- package/src/prompts/agents/frontmatter.md +11 -0
- package/src/prompts/agents/init.md +33 -0
- package/src/prompts/agents/librarian.md +119 -0
- package/src/prompts/agents/oracle.md +55 -0
- package/src/prompts/agents/plan.md +48 -0
- package/src/prompts/agents/reviewer.md +140 -0
- package/src/prompts/agents/task.md +16 -0
- package/src/prompts/ci-green-request.md +36 -0
- package/src/prompts/dry-balance-bench.md +8 -0
- package/src/prompts/goals/goal-budget-limit.md +16 -0
- package/src/prompts/goals/goal-continuation.md +28 -0
- package/src/prompts/goals/goal-mode-active.md +23 -0
- package/src/prompts/memories/consolidation.md +30 -0
- package/src/prompts/memories/read-path.md +11 -0
- package/src/prompts/memories/stage_one_input.md +6 -0
- package/src/prompts/memories/stage_one_system.md +21 -0
- package/src/prompts/review-custom-request.md +22 -0
- package/src/prompts/review-headless-request.md +16 -0
- package/src/prompts/review-request.md +69 -0
- package/src/prompts/steering/user-interjection.md +10 -0
- package/src/prompts/system/agent-creation-architect.md +50 -0
- package/src/prompts/system/agent-creation-user.md +6 -0
- package/src/prompts/system/auto-continue.md +1 -0
- package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
- package/src/prompts/system/auto-thinking-difficulty.md +12 -0
- package/src/prompts/system/background-tan-dispatch.md +8 -0
- package/src/prompts/system/btw-user.md +8 -0
- package/src/prompts/system/commit-message-system.md +14 -0
- package/src/prompts/system/custom-system-prompt.md +64 -0
- package/src/prompts/system/eager-todo.md +13 -0
- package/src/prompts/system/empty-stop-retry.md +6 -0
- package/src/prompts/system/irc-incoming.md +7 -0
- package/src/prompts/system/manual-continue.md +7 -0
- package/src/prompts/system/memory-consolidation-system.md +8 -0
- package/src/prompts/system/memory-extraction-system.md +26 -0
- package/src/prompts/system/omfg-user.md +50 -0
- package/src/prompts/system/orchestrate-notice.md +40 -0
- package/src/prompts/system/plan-mode-active.md +109 -0
- package/src/prompts/system/plan-mode-approved.md +25 -0
- package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
- package/src/prompts/system/plan-mode-reference.md +11 -0
- package/src/prompts/system/plan-mode-subagent.md +33 -0
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
- package/src/prompts/system/project-prompt.md +52 -0
- package/src/prompts/system/subagent-system-prompt.md +64 -0
- package/src/prompts/system/subagent-user-prompt.md +3 -0
- package/src/prompts/system/subagent-yield-reminder.md +12 -0
- package/src/prompts/system/system-prompt.md +258 -0
- package/src/prompts/system/tiny-title-system.md +8 -0
- package/src/prompts/system/title-system.md +16 -0
- package/src/prompts/system/ttsr-interrupt.md +7 -0
- package/src/prompts/system/ttsr-tool-reminder.md +5 -0
- package/src/prompts/system/ultrathink-notice.md +3 -0
- package/src/prompts/system/web-search.md +25 -0
- package/src/prompts/system/workflow-notice.md +70 -0
- package/src/prompts/tools/apply-patch.md +65 -0
- package/src/prompts/tools/ask.md +30 -0
- package/src/prompts/tools/ast-edit.md +39 -0
- package/src/prompts/tools/ast-grep.md +42 -0
- package/src/prompts/tools/async-result.md +8 -0
- package/src/prompts/tools/bash.md +46 -0
- package/src/prompts/tools/browser.md +73 -0
- package/src/prompts/tools/checkpoint.md +16 -0
- package/src/prompts/tools/debug.md +34 -0
- package/src/prompts/tools/eval.md +92 -0
- package/src/prompts/tools/find.md +36 -0
- package/src/prompts/tools/github.md +21 -0
- package/src/prompts/tools/goal.md +18 -0
- package/src/prompts/tools/image-gen.md +7 -0
- package/src/prompts/tools/inspect-image-system.md +20 -0
- package/src/prompts/tools/inspect-image.md +32 -0
- package/src/prompts/tools/irc.md +59 -0
- package/src/prompts/tools/job.md +19 -0
- package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
- package/src/prompts/tools/lsp.md +42 -0
- package/src/prompts/tools/memory-edit.md +8 -0
- package/src/prompts/tools/patch.md +70 -0
- package/src/prompts/tools/read.md +84 -0
- package/src/prompts/tools/recall.md +5 -0
- package/src/prompts/tools/reflect.md +5 -0
- package/src/prompts/tools/render-mermaid.md +9 -0
- package/src/prompts/tools/replace.md +30 -0
- package/src/prompts/tools/resolve.md +9 -0
- package/src/prompts/tools/retain.md +6 -0
- package/src/prompts/tools/rewind.md +13 -0
- package/src/prompts/tools/search-tool-bm25.md +32 -0
- package/src/prompts/tools/search.md +24 -0
- package/src/prompts/tools/ssh.md +31 -0
- package/src/prompts/tools/task-summary.md +17 -0
- package/src/prompts/tools/task.md +88 -0
- package/src/prompts/tools/todo.md +62 -0
- package/src/prompts/tools/web-search.md +10 -0
- package/src/prompts/tools/write.md +14 -0
- package/src/registry/agent-lifecycle.ts +218 -0
- package/src/registry/agent-registry.ts +151 -0
- package/src/sdk.ts +2558 -0
- package/src/secrets/index.ts +123 -0
- package/src/secrets/obfuscator.ts +298 -0
- package/src/secrets/regex.ts +21 -0
- package/src/session/agent-session.ts +10121 -0
- package/src/session/agent-storage.ts +455 -0
- package/src/session/artifacts.ts +135 -0
- package/src/session/auth-broker-config.ts +131 -0
- package/src/session/auth-storage.ts +29 -0
- package/src/session/blob-store.ts +255 -0
- package/src/session/client-bridge.ts +85 -0
- package/src/session/history-storage.ts +348 -0
- package/src/session/indexed-session-storage.ts +430 -0
- package/src/session/messages.ts +541 -0
- package/src/session/redis-session-storage.ts +170 -0
- package/src/session/session-dump-format.ts +209 -0
- package/src/session/session-history-format.ts +246 -0
- package/src/session/session-manager.ts +3676 -0
- package/src/session/session-storage.ts +529 -0
- package/src/session/shake-types.ts +43 -0
- package/src/session/sql-session-storage.ts +314 -0
- package/src/session/streaming-output.ts +1330 -0
- package/src/session/tool-choice-queue.ts +213 -0
- package/src/session/yield-queue.ts +173 -0
- package/src/slash-commands/acp-builtins.ts +70 -0
- package/src/slash-commands/builtin-registry.ts +1798 -0
- package/src/slash-commands/helpers/context-report.ts +39 -0
- package/src/slash-commands/helpers/format.ts +46 -0
- package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
- package/src/slash-commands/helpers/mcp.ts +532 -0
- package/src/slash-commands/helpers/parse.ts +85 -0
- package/src/slash-commands/helpers/ssh.ts +195 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/slash-commands/helpers/todo.ts +279 -0
- package/src/slash-commands/helpers/usage-report.ts +95 -0
- package/src/slash-commands/marketplace-install-parser.ts +99 -0
- package/src/slash-commands/types.ts +135 -0
- package/src/ssh/config-writer.ts +183 -0
- package/src/ssh/connection-manager.ts +509 -0
- package/src/ssh/ssh-executor.ts +189 -0
- package/src/ssh/sshfs-mount.ts +140 -0
- package/src/ssh/utils.ts +8 -0
- package/src/stt/downloader.ts +71 -0
- package/src/stt/index.ts +3 -0
- package/src/stt/recorder.ts +351 -0
- package/src/stt/setup.ts +52 -0
- package/src/stt/stt-controller.ts +160 -0
- package/src/stt/transcribe.py +70 -0
- package/src/stt/transcriber.ts +91 -0
- package/src/stubs/natives/index.ts +814 -0
- package/src/stubs/natives/package.json +7 -0
- package/src/stubs/tui/index.ts +282 -0
- package/src/stubs/tui/package.json +7 -0
- package/src/system-prompt.ts +611 -0
- package/src/task/agents.ts +167 -0
- package/src/task/commands.ts +132 -0
- package/src/task/discovery.ts +122 -0
- package/src/task/executor.ts +2133 -0
- package/src/task/index.ts +1419 -0
- package/src/task/name-generator.ts +1577 -0
- package/src/task/omp-command.ts +26 -0
- package/src/task/output-manager.ts +88 -0
- package/src/task/parallel.ts +116 -0
- package/src/task/render.ts +1381 -0
- package/src/task/repair-args.ts +129 -0
- package/src/task/subprocess-tool-registry.ts +88 -0
- package/src/task/types.ts +336 -0
- package/src/task/worktree.ts +514 -0
- package/src/telemetry-export.ts +144 -0
- package/src/thinking.ts +167 -0
- package/src/tiny/compiled-runtime.ts +179 -0
- package/src/tiny/device.ts +111 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/models.ts +242 -0
- package/src/tiny/text.ts +165 -0
- package/src/tiny/title-client.ts +543 -0
- package/src/tiny/title-protocol.ts +56 -0
- package/src/tiny/worker.ts +568 -0
- package/src/tool-discovery/mode.ts +24 -0
- package/src/tool-discovery/tool-index.ts +256 -0
- package/src/tools/approval.ts +189 -0
- package/src/tools/archive-reader.ts +721 -0
- package/src/tools/ask.ts +928 -0
- package/src/tools/ast-edit.ts +642 -0
- package/src/tools/ast-grep.ts +452 -0
- package/src/tools/auto-generated-guard.ts +322 -0
- package/src/tools/bash-command-fixup.ts +37 -0
- package/src/tools/bash-interactive.ts +408 -0
- package/src/tools/bash-interceptor.ts +67 -0
- package/src/tools/bash-pty-selection.ts +14 -0
- package/src/tools/bash-skill-urls.ts +248 -0
- package/src/tools/bash.ts +1386 -0
- package/src/tools/browser/attach.ts +175 -0
- package/src/tools/browser/launch.ts +660 -0
- package/src/tools/browser/readable.ts +112 -0
- package/src/tools/browser/registry.ts +197 -0
- package/src/tools/browser/render.ts +216 -0
- package/src/tools/browser/tab-protocol.ts +105 -0
- package/src/tools/browser/tab-supervisor.ts +628 -0
- package/src/tools/browser/tab-worker-entry.ts +21 -0
- package/src/tools/browser/tab-worker.ts +1226 -0
- package/src/tools/browser.ts +343 -0
- package/src/tools/checkpoint.ts +136 -0
- package/src/tools/conflict-detect.ts +718 -0
- package/src/tools/context.ts +39 -0
- package/src/tools/debug.ts +1067 -0
- package/src/tools/eval-backends.ts +27 -0
- package/src/tools/eval-render.ts +752 -0
- package/src/tools/eval.ts +577 -0
- package/src/tools/fetch.ts +1926 -0
- package/src/tools/file-recorder.ts +35 -0
- package/src/tools/find.ts +609 -0
- package/src/tools/fs-cache-invalidation.ts +28 -0
- package/src/tools/gh-cache-invalidation.ts +255 -0
- package/src/tools/gh-format.ts +12 -0
- package/src/tools/gh-renderer.ts +481 -0
- package/src/tools/gh.ts +3720 -0
- package/src/tools/github-cache.ts +637 -0
- package/src/tools/grouped-file-output.ts +210 -0
- package/src/tools/image-gen.ts +1517 -0
- package/src/tools/index.ts +599 -0
- package/src/tools/inspect-image-renderer.ts +132 -0
- package/src/tools/inspect-image.ts +174 -0
- package/src/tools/irc.ts +723 -0
- package/src/tools/job.ts +557 -0
- package/src/tools/json-tree.ts +243 -0
- package/src/tools/jtd-to-json-schema.ts +219 -0
- package/src/tools/jtd-to-typescript.ts +136 -0
- package/src/tools/jtd-utils.ts +102 -0
- package/src/tools/list-limit.ts +40 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/memory-edit.ts +59 -0
- package/src/tools/memory-recall.ts +100 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +202 -0
- package/src/tools/memory-retain.ts +91 -0
- package/src/tools/output-meta.ts +754 -0
- package/src/tools/output-schema-validator.ts +132 -0
- package/src/tools/path-utils.ts +1054 -0
- package/src/tools/plan-mode-guard.ts +108 -0
- package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
- package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
- package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
- package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
- package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
- package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
- package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
- package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
- package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
- package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
- package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
- package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
- package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
- package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
- package/src/tools/read.ts +2929 -0
- package/src/tools/render-mermaid.ts +69 -0
- package/src/tools/render-utils.ts +838 -0
- package/src/tools/renderers.ts +77 -0
- package/src/tools/report-tool-issue.ts +534 -0
- package/src/tools/resolve.ts +276 -0
- package/src/tools/review.ts +253 -0
- package/src/tools/search-tool-bm25.ts +351 -0
- package/src/tools/search.ts +1580 -0
- package/src/tools/sqlite-reader.ts +828 -0
- package/src/tools/ssh.ts +349 -0
- package/src/tools/todo.ts +982 -0
- package/src/tools/tool-errors.ts +62 -0
- package/src/tools/tool-result.ts +94 -0
- package/src/tools/tool-timeouts.ts +30 -0
- package/src/tools/tts.ts +133 -0
- package/src/tools/write.ts +1217 -0
- package/src/tools/yield.ts +269 -0
- package/src/tui/code-cell.ts +216 -0
- package/src/tui/file-list.ts +55 -0
- package/src/tui/hyperlink.ts +175 -0
- package/src/tui/index.ts +12 -0
- package/src/tui/output-block.ts +240 -0
- package/src/tui/status-line.ts +54 -0
- package/src/tui/tree-list.ts +84 -0
- package/src/tui/types.ts +15 -0
- package/src/tui/utils.ts +103 -0
- package/src/utils/block-context.ts +312 -0
- package/src/utils/changelog.ts +132 -0
- package/src/utils/clipboard.ts +193 -0
- package/src/utils/command-args.ts +76 -0
- package/src/utils/commit-message-generator.ts +151 -0
- package/src/utils/edit-mode.ts +41 -0
- package/src/utils/enhanced-paste.ts +230 -0
- package/src/utils/event-bus.ts +33 -0
- package/src/utils/external-editor.ts +65 -0
- package/src/utils/file-display-mode.ts +45 -0
- package/src/utils/file-mentions.ts +281 -0
- package/src/utils/git.ts +1833 -0
- package/src/utils/image-loading.ts +132 -0
- package/src/utils/image-resize.ts +309 -0
- package/src/utils/jj.ts +248 -0
- package/src/utils/lang-from-path.ts +239 -0
- package/src/utils/markit.ts +89 -0
- package/src/utils/open.ts +55 -0
- package/src/utils/session-color.ts +68 -0
- package/src/utils/shell-snapshot.ts +187 -0
- package/src/utils/sixel.ts +69 -0
- package/src/utils/title-generator.ts +373 -0
- package/src/utils/tool-choice.ts +33 -0
- package/src/utils/tools-manager.ts +363 -0
- package/src/web/kagi.ts +305 -0
- package/src/web/parallel.ts +353 -0
- package/src/web/scrapers/artifacthub.ts +207 -0
- package/src/web/scrapers/arxiv.ts +83 -0
- package/src/web/scrapers/aur.ts +162 -0
- package/src/web/scrapers/biorxiv.ts +133 -0
- package/src/web/scrapers/bluesky.ts +262 -0
- package/src/web/scrapers/brew.ts +172 -0
- package/src/web/scrapers/cheatsh.ts +68 -0
- package/src/web/scrapers/chocolatey.ts +196 -0
- package/src/web/scrapers/choosealicense.ts +95 -0
- package/src/web/scrapers/cisa-kev.ts +87 -0
- package/src/web/scrapers/clojars.ts +154 -0
- package/src/web/scrapers/coingecko.ts +177 -0
- package/src/web/scrapers/crates-io.ts +97 -0
- package/src/web/scrapers/crossref.ts +136 -0
- package/src/web/scrapers/devto.ts +147 -0
- package/src/web/scrapers/discogs.ts +306 -0
- package/src/web/scrapers/discourse.ts +197 -0
- package/src/web/scrapers/dockerhub.ts +138 -0
- package/src/web/scrapers/docs-rs.ts +653 -0
- package/src/web/scrapers/fdroid.ts +134 -0
- package/src/web/scrapers/firefox-addons.ts +191 -0
- package/src/web/scrapers/flathub.ts +223 -0
- package/src/web/scrapers/github-gist.ts +58 -0
- package/src/web/scrapers/github.ts +704 -0
- package/src/web/scrapers/gitlab.ts +401 -0
- package/src/web/scrapers/go-pkg.ts +266 -0
- package/src/web/scrapers/hackage.ts +140 -0
- package/src/web/scrapers/hackernews.ts +189 -0
- package/src/web/scrapers/hex.ts +105 -0
- package/src/web/scrapers/huggingface.ts +321 -0
- package/src/web/scrapers/iacr.ts +89 -0
- package/src/web/scrapers/index.ts +252 -0
- package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
- package/src/web/scrapers/lemmy.ts +203 -0
- package/src/web/scrapers/lobsters.ts +175 -0
- package/src/web/scrapers/mastodon.ts +292 -0
- package/src/web/scrapers/maven.ts +138 -0
- package/src/web/scrapers/mdn.ts +173 -0
- package/src/web/scrapers/metacpan.ts +222 -0
- package/src/web/scrapers/musicbrainz.ts +250 -0
- package/src/web/scrapers/npm.ts +98 -0
- package/src/web/scrapers/nuget.ts +183 -0
- package/src/web/scrapers/nvd.ts +222 -0
- package/src/web/scrapers/ollama.ts +239 -0
- package/src/web/scrapers/open-vsx.ts +106 -0
- package/src/web/scrapers/opencorporates.ts +292 -0
- package/src/web/scrapers/openlibrary.ts +336 -0
- package/src/web/scrapers/orcid.ts +286 -0
- package/src/web/scrapers/osv.ts +176 -0
- package/src/web/scrapers/packagist.ts +160 -0
- package/src/web/scrapers/pub-dev.ts +143 -0
- package/src/web/scrapers/pubmed.ts +211 -0
- package/src/web/scrapers/pypi.ts +112 -0
- package/src/web/scrapers/rawg.ts +110 -0
- package/src/web/scrapers/readthedocs.ts +120 -0
- package/src/web/scrapers/reddit.ts +95 -0
- package/src/web/scrapers/repology.ts +251 -0
- package/src/web/scrapers/rfc.ts +201 -0
- package/src/web/scrapers/rubygems.ts +103 -0
- package/src/web/scrapers/searchcode.ts +189 -0
- package/src/web/scrapers/sec-edgar.ts +261 -0
- package/src/web/scrapers/semantic-scholar.ts +171 -0
- package/src/web/scrapers/snapcraft.ts +187 -0
- package/src/web/scrapers/sourcegraph.ts +336 -0
- package/src/web/scrapers/spdx.ts +108 -0
- package/src/web/scrapers/spotify.ts +198 -0
- package/src/web/scrapers/stackoverflow.ts +120 -0
- package/src/web/scrapers/terraform.ts +277 -0
- package/src/web/scrapers/tldr.ts +47 -0
- package/src/web/scrapers/twitter.ts +94 -0
- package/src/web/scrapers/types.ts +397 -0
- package/src/web/scrapers/utils.ts +109 -0
- package/src/web/scrapers/vimeo.ts +133 -0
- package/src/web/scrapers/vscode-marketplace.ts +187 -0
- package/src/web/scrapers/w3c.ts +156 -0
- package/src/web/scrapers/wikidata.ts +344 -0
- package/src/web/scrapers/wikipedia.ts +84 -0
- package/src/web/scrapers/youtube.ts +325 -0
- package/src/web/search/index.ts +292 -0
- package/src/web/search/provider.ts +157 -0
- package/src/web/search/providers/anthropic.ts +318 -0
- package/src/web/search/providers/base.ts +89 -0
- package/src/web/search/providers/brave.ts +152 -0
- package/src/web/search/providers/codex.ts +591 -0
- package/src/web/search/providers/exa.ts +400 -0
- package/src/web/search/providers/gemini.ts +460 -0
- package/src/web/search/providers/jina.ts +111 -0
- package/src/web/search/providers/kagi.ts +86 -0
- package/src/web/search/providers/kimi.ts +196 -0
- package/src/web/search/providers/parallel.ts +225 -0
- package/src/web/search/providers/perplexity.ts +730 -0
- package/src/web/search/providers/searxng.ts +313 -0
- package/src/web/search/providers/synthetic.ts +114 -0
- package/src/web/search/providers/tavily.ts +176 -0
- package/src/web/search/providers/utils.ts +128 -0
- package/src/web/search/providers/zai.ts +333 -0
- package/src/web/search/render.ts +262 -0
- package/src/web/search/types.ts +482 -0
- package/src/web/search/utils.ts +17 -0
- package/src/workspace-tree.ts +286 -0
|
@@ -0,0 +1,1016 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
5
|
+
import { FileType, glob } from './stubs/natives/index.ts';
|
|
6
|
+
import {
|
|
7
|
+
CONFIG_DIR_NAME,
|
|
8
|
+
getConfigDirName,
|
|
9
|
+
getPluginsDir,
|
|
10
|
+
getProjectDir,
|
|
11
|
+
parseFrontmatter,
|
|
12
|
+
tryParseJson,
|
|
13
|
+
} from "@oh-my-pi/pi-utils";
|
|
14
|
+
import type { ExtensionModule } from "../capability/extension-module";
|
|
15
|
+
import { invalidate as invalidateFsCache, readDirEntries, readFile } from "../capability/fs";
|
|
16
|
+
import { parseRuleConditionAndScope, type Rule, type RuleFrontmatter } from "../capability/rule";
|
|
17
|
+
import type { Skill, SkillFrontmatter } from "../capability/skill";
|
|
18
|
+
import type { LoadContext, LoadResult, SourceMeta } from "../capability/types";
|
|
19
|
+
import { parseThinkingLevel } from "../thinking";
|
|
20
|
+
|
|
21
|
+
import { buildPluginDirRoot } from "./plugin-dir-roots";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Standard paths for each config source.
|
|
25
|
+
*/
|
|
26
|
+
export const SOURCE_PATHS = {
|
|
27
|
+
native: {
|
|
28
|
+
get userBase() {
|
|
29
|
+
return getConfigDirName();
|
|
30
|
+
},
|
|
31
|
+
get userAgent() {
|
|
32
|
+
return `${getConfigDirName()}/agent`;
|
|
33
|
+
},
|
|
34
|
+
projectDir: CONFIG_DIR_NAME,
|
|
35
|
+
},
|
|
36
|
+
claude: {
|
|
37
|
+
userBase: ".claude",
|
|
38
|
+
userAgent: ".claude",
|
|
39
|
+
projectDir: ".claude",
|
|
40
|
+
},
|
|
41
|
+
codex: {
|
|
42
|
+
userBase: ".codex",
|
|
43
|
+
userAgent: ".codex",
|
|
44
|
+
projectDir: ".codex",
|
|
45
|
+
},
|
|
46
|
+
gemini: {
|
|
47
|
+
userBase: ".gemini",
|
|
48
|
+
userAgent: ".gemini",
|
|
49
|
+
projectDir: ".gemini",
|
|
50
|
+
},
|
|
51
|
+
opencode: {
|
|
52
|
+
userBase: ".config/opencode",
|
|
53
|
+
userAgent: ".config/opencode",
|
|
54
|
+
projectDir: ".opencode",
|
|
55
|
+
},
|
|
56
|
+
cursor: {
|
|
57
|
+
userBase: ".cursor",
|
|
58
|
+
userAgent: ".cursor",
|
|
59
|
+
projectDir: ".cursor",
|
|
60
|
+
},
|
|
61
|
+
windsurf: {
|
|
62
|
+
userBase: ".codeium/windsurf",
|
|
63
|
+
userAgent: ".codeium/windsurf",
|
|
64
|
+
projectDir: ".windsurf",
|
|
65
|
+
},
|
|
66
|
+
cline: {
|
|
67
|
+
userBase: ".cline",
|
|
68
|
+
userAgent: ".cline",
|
|
69
|
+
projectDir: null, // Cline uses root-level .clinerules
|
|
70
|
+
},
|
|
71
|
+
github: {
|
|
72
|
+
userBase: null,
|
|
73
|
+
userAgent: null,
|
|
74
|
+
projectDir: ".github",
|
|
75
|
+
},
|
|
76
|
+
vscode: {
|
|
77
|
+
userBase: ".vscode",
|
|
78
|
+
userAgent: ".vscode",
|
|
79
|
+
projectDir: ".vscode",
|
|
80
|
+
},
|
|
81
|
+
} as const;
|
|
82
|
+
|
|
83
|
+
export type SourceId = keyof typeof SOURCE_PATHS;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get user-level path for a source.
|
|
87
|
+
*/
|
|
88
|
+
export function getUserPath(ctx: LoadContext, source: SourceId, subpath: string): string | null {
|
|
89
|
+
const paths = SOURCE_PATHS[source];
|
|
90
|
+
if (!paths.userAgent) return null;
|
|
91
|
+
return path.join(ctx.home, paths.userAgent, subpath);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get project-level path for a source (cwd only).
|
|
96
|
+
*/
|
|
97
|
+
export function getProjectPath(ctx: LoadContext, source: SourceId, subpath: string): string | null {
|
|
98
|
+
const paths = SOURCE_PATHS[source];
|
|
99
|
+
if (!paths.projectDir) return null;
|
|
100
|
+
|
|
101
|
+
return path.join(ctx.cwd, paths.projectDir, subpath);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Create source metadata for an item.
|
|
106
|
+
*/
|
|
107
|
+
export function createSourceMeta(provider: string, filePath: string, level: "user" | "project"): SourceMeta {
|
|
108
|
+
return {
|
|
109
|
+
provider,
|
|
110
|
+
providerName: "", // Filled in by registry
|
|
111
|
+
path: path.resolve(filePath),
|
|
112
|
+
level,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function parseBoolean(value: unknown): boolean | undefined {
|
|
117
|
+
if (typeof value === "boolean") return value;
|
|
118
|
+
if (typeof value === "string") {
|
|
119
|
+
const normalized = value.trim().toLowerCase();
|
|
120
|
+
if (normalized === "true") return true;
|
|
121
|
+
if (normalized === "false") return false;
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Parse a comma-separated string into an array of trimmed, non-empty strings.
|
|
128
|
+
*/
|
|
129
|
+
export function parseCSV(value: string): string[] {
|
|
130
|
+
return value
|
|
131
|
+
.split(",")
|
|
132
|
+
.map(s => s.trim())
|
|
133
|
+
.filter(Boolean);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Parse a value that may be an array of strings or a comma-separated string.
|
|
138
|
+
* Returns undefined if the result would be empty.
|
|
139
|
+
*/
|
|
140
|
+
export function parseArrayOrCSV(value: unknown): string[] | undefined {
|
|
141
|
+
if (Array.isArray(value)) {
|
|
142
|
+
const filtered = value.filter((item): item is string => typeof item === "string");
|
|
143
|
+
return filtered.length > 0 ? filtered : undefined;
|
|
144
|
+
}
|
|
145
|
+
if (typeof value === "string") {
|
|
146
|
+
const parsed = parseCSV(value);
|
|
147
|
+
return parsed.length > 0 ? parsed : undefined;
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Build a canonical rule item from a markdown/markdown-frontmatter document.
|
|
154
|
+
*/
|
|
155
|
+
export function buildRuleFromMarkdown(
|
|
156
|
+
name: string,
|
|
157
|
+
content: string,
|
|
158
|
+
filePath: string,
|
|
159
|
+
source: SourceMeta,
|
|
160
|
+
options?: {
|
|
161
|
+
ruleName?: string;
|
|
162
|
+
stripNamePattern?: RegExp;
|
|
163
|
+
},
|
|
164
|
+
): Rule {
|
|
165
|
+
const { frontmatter, body } = parseFrontmatter(content, { source: filePath });
|
|
166
|
+
const { condition, astCondition, scope } = parseRuleConditionAndScope(frontmatter as RuleFrontmatter);
|
|
167
|
+
|
|
168
|
+
let globs: string[] | undefined;
|
|
169
|
+
if (Array.isArray(frontmatter.globs)) {
|
|
170
|
+
globs = frontmatter.globs.filter((item): item is string => typeof item === "string");
|
|
171
|
+
} else if (typeof frontmatter.globs === "string") {
|
|
172
|
+
globs = [frontmatter.globs];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const resolvedName = options?.ruleName ?? name.replace(options?.stripNamePattern ?? /\.(md|mdc)$/, "");
|
|
176
|
+
const rawMode = frontmatter.interruptMode;
|
|
177
|
+
const interruptMode: Rule["interruptMode"] =
|
|
178
|
+
rawMode === "never" || rawMode === "prose-only" || rawMode === "tool-only" || rawMode === "always"
|
|
179
|
+
? rawMode
|
|
180
|
+
: undefined;
|
|
181
|
+
return {
|
|
182
|
+
name: resolvedName,
|
|
183
|
+
path: filePath,
|
|
184
|
+
content: body,
|
|
185
|
+
globs,
|
|
186
|
+
alwaysApply: frontmatter.alwaysApply === true,
|
|
187
|
+
description: typeof frontmatter.description === "string" ? frontmatter.description : undefined,
|
|
188
|
+
condition,
|
|
189
|
+
astCondition,
|
|
190
|
+
scope,
|
|
191
|
+
interruptMode,
|
|
192
|
+
_source: source,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Parse model field into a prioritized list.
|
|
198
|
+
*/
|
|
199
|
+
export function parseModelList(value: unknown): string[] | undefined {
|
|
200
|
+
const parsed = parseArrayOrCSV(value);
|
|
201
|
+
if (!parsed) return undefined;
|
|
202
|
+
const normalized = parsed.map(entry => entry.trim()).filter(Boolean);
|
|
203
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Parsed agent fields from frontmatter (excludes source/filePath/systemPrompt) */
|
|
207
|
+
export interface ParsedAgentFields {
|
|
208
|
+
name: string;
|
|
209
|
+
description: string;
|
|
210
|
+
tools?: string[];
|
|
211
|
+
spawns?: string[] | "*";
|
|
212
|
+
model?: string[];
|
|
213
|
+
output?: unknown;
|
|
214
|
+
thinkingLevel?: ThinkingLevel;
|
|
215
|
+
autoloadSkills?: string[];
|
|
216
|
+
readSummarize?: boolean;
|
|
217
|
+
blocking?: boolean;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Parse agent fields from frontmatter.
|
|
222
|
+
* Returns null if required fields (name, description) are missing.
|
|
223
|
+
*/
|
|
224
|
+
export function parseAgentFields(frontmatter: Record<string, unknown>): ParsedAgentFields | null {
|
|
225
|
+
const name = typeof frontmatter.name === "string" ? frontmatter.name : undefined;
|
|
226
|
+
const description = typeof frontmatter.description === "string" ? frontmatter.description : undefined;
|
|
227
|
+
|
|
228
|
+
if (!name || !description) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let tools = parseArrayOrCSV(frontmatter.tools)?.map(tool => tool.toLowerCase());
|
|
233
|
+
|
|
234
|
+
// Subagents with explicit tool lists always need yield
|
|
235
|
+
if (tools && !tools.includes("yield")) {
|
|
236
|
+
tools = [...tools, "yield"];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Parse spawns field (array, "*", or CSV)
|
|
240
|
+
let spawns: string[] | "*" | undefined;
|
|
241
|
+
if (frontmatter.spawns === "*") {
|
|
242
|
+
spawns = "*";
|
|
243
|
+
} else if (typeof frontmatter.spawns === "string") {
|
|
244
|
+
const trimmed = frontmatter.spawns.trim();
|
|
245
|
+
if (trimmed === "*") {
|
|
246
|
+
spawns = "*";
|
|
247
|
+
} else {
|
|
248
|
+
spawns = parseArrayOrCSV(trimmed);
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
spawns = parseArrayOrCSV(frontmatter.spawns);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Backward compat: infer spawns: "*" when tools includes "task"
|
|
255
|
+
if (spawns === undefined && tools?.includes("task")) {
|
|
256
|
+
spawns = "*";
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const output = frontmatter.output !== undefined ? frontmatter.output : undefined;
|
|
260
|
+
const rawThinkingLevel =
|
|
261
|
+
typeof frontmatter.thinkingLevel === "string"
|
|
262
|
+
? frontmatter.thinkingLevel
|
|
263
|
+
: typeof frontmatter.thinking === "string"
|
|
264
|
+
? frontmatter.thinking
|
|
265
|
+
: undefined;
|
|
266
|
+
|
|
267
|
+
const thinkingLevel = parseThinkingLevel(rawThinkingLevel);
|
|
268
|
+
const model = parseModelList(frontmatter.model);
|
|
269
|
+
const blocking = parseBoolean(frontmatter.blocking);
|
|
270
|
+
const readSummarize = parseBoolean(frontmatter.readSummarize);
|
|
271
|
+
const autoloadSkills = parseArrayOrCSV(frontmatter.autoloadSkills)
|
|
272
|
+
?.map(s => s.trim())
|
|
273
|
+
.filter(Boolean);
|
|
274
|
+
return { name, description, tools, spawns, model, output, thinkingLevel, blocking, autoloadSkills, readSummarize };
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async function globIf(
|
|
278
|
+
dir: string,
|
|
279
|
+
pattern: string,
|
|
280
|
+
fileType: FileType,
|
|
281
|
+
recursive: boolean = true,
|
|
282
|
+
): Promise<Array<{ path: string }>> {
|
|
283
|
+
try {
|
|
284
|
+
const result = await glob({ pattern, path: dir, gitignore: true, hidden: false, fileType, recursive });
|
|
285
|
+
return result.matches;
|
|
286
|
+
} catch {
|
|
287
|
+
return [];
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export interface ScanSkillsFromDirOptions {
|
|
292
|
+
dir: string;
|
|
293
|
+
providerId: string;
|
|
294
|
+
level: "user" | "project";
|
|
295
|
+
requireDescription?: boolean;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Stable ordering used for skill lists in prompts: name (case-insensitive), then name, then path.
|
|
299
|
+
export function compareSkillOrder(aName: string, aPath: string, bName: string, bPath: string): number {
|
|
300
|
+
const cmp = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0);
|
|
301
|
+
const lowerCompare = cmp(aName.toLowerCase(), bName.toLowerCase());
|
|
302
|
+
if (lowerCompare !== 0) return lowerCompare;
|
|
303
|
+
const nameCompare = cmp(aName, bName);
|
|
304
|
+
if (nameCompare !== 0) return nameCompare;
|
|
305
|
+
return cmp(aPath, bPath);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export async function scanSkillsFromDir(
|
|
309
|
+
_ctx: LoadContext,
|
|
310
|
+
options: ScanSkillsFromDirOptions,
|
|
311
|
+
): Promise<LoadResult<Skill>> {
|
|
312
|
+
const items: Skill[] = [];
|
|
313
|
+
const warnings: string[] = [];
|
|
314
|
+
const { dir, level, providerId, requireDescription = false } = options;
|
|
315
|
+
|
|
316
|
+
let entries: fs.Dirent[];
|
|
317
|
+
try {
|
|
318
|
+
entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
319
|
+
} catch (error) {
|
|
320
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
321
|
+
warnings.push(`Failed to read skills directory: ${dir} (${String(error)})`);
|
|
322
|
+
}
|
|
323
|
+
return { items, warnings };
|
|
324
|
+
}
|
|
325
|
+
const loadSkill = async (skillPath: string) => {
|
|
326
|
+
try {
|
|
327
|
+
const content = await readFile(skillPath);
|
|
328
|
+
if (!content) return;
|
|
329
|
+
const { frontmatter, body } = parseFrontmatter(content, { source: skillPath });
|
|
330
|
+
if (frontmatter.enabled === false) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (requireDescription && !frontmatter.description) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const skillDirName = path.basename(path.dirname(skillPath));
|
|
337
|
+
const rawName = frontmatter.name;
|
|
338
|
+
const name = typeof rawName === "string" ? rawName.trim() || skillDirName : skillDirName;
|
|
339
|
+
items.push({
|
|
340
|
+
name,
|
|
341
|
+
path: skillPath,
|
|
342
|
+
content: body,
|
|
343
|
+
frontmatter: frontmatter as SkillFrontmatter,
|
|
344
|
+
level,
|
|
345
|
+
_source: createSourceMeta(providerId, skillPath, level),
|
|
346
|
+
});
|
|
347
|
+
} catch {
|
|
348
|
+
warnings.push(`Failed to read skill file: ${skillPath}`);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const work = [];
|
|
353
|
+
for (const entry of entries) {
|
|
354
|
+
if (entry.name.startsWith(".")) continue;
|
|
355
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
356
|
+
const skillPath = path.join(dir, entry.name, "SKILL.md");
|
|
357
|
+
if (fs.existsSync(skillPath)) {
|
|
358
|
+
work.push(loadSkill(skillPath));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
await Promise.all(work);
|
|
362
|
+
|
|
363
|
+
// Deterministic ordering: async file reads complete nondeterministically, so sort after loading.
|
|
364
|
+
items.sort((a, b) => compareSkillOrder(a.name, a.path, b.name, b.path));
|
|
365
|
+
|
|
366
|
+
return { items, warnings };
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Expand environment variables in a string.
|
|
371
|
+
* Supports ${VAR} and ${VAR:-default} syntax.
|
|
372
|
+
*/
|
|
373
|
+
function expandEnvVars(value: string, extraEnv?: Record<string, string>): string {
|
|
374
|
+
return value.replace(/\$\{([^}:]+)(?::-([^}]*))?\}/g, (_, varName: string, defaultValue?: string) => {
|
|
375
|
+
const envValue = extraEnv?.[varName] ?? Bun.env[varName];
|
|
376
|
+
if (envValue !== undefined) return envValue;
|
|
377
|
+
if (defaultValue !== undefined) return defaultValue;
|
|
378
|
+
return `\${${varName}}`;
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Recursively expand environment variables in an object.
|
|
384
|
+
*/
|
|
385
|
+
export function expandEnvVarsDeep<T>(obj: T, extraEnv?: Record<string, string>): T {
|
|
386
|
+
if (typeof obj === "string") {
|
|
387
|
+
return expandEnvVars(obj, extraEnv) as T;
|
|
388
|
+
}
|
|
389
|
+
if (Array.isArray(obj)) {
|
|
390
|
+
return obj.map(item => expandEnvVarsDeep(item, extraEnv)) as T;
|
|
391
|
+
}
|
|
392
|
+
if (obj !== null && typeof obj === "object") {
|
|
393
|
+
const result: Record<string, unknown> = {};
|
|
394
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
395
|
+
result[key] = expandEnvVarsDeep(value, extraEnv);
|
|
396
|
+
}
|
|
397
|
+
return result as T;
|
|
398
|
+
}
|
|
399
|
+
return obj;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Load files from a directory matching extensions.
|
|
404
|
+
* Uses native glob for fast filesystem scanning with gitignore support.
|
|
405
|
+
*/
|
|
406
|
+
export async function loadFilesFromDir<T>(
|
|
407
|
+
_ctx: LoadContext,
|
|
408
|
+
dir: string,
|
|
409
|
+
provider: string,
|
|
410
|
+
level: "user" | "project",
|
|
411
|
+
options: {
|
|
412
|
+
/** File extensions to match (without dot) */
|
|
413
|
+
extensions?: string[];
|
|
414
|
+
/** Transform file to item (return null to skip) */
|
|
415
|
+
transform: (name: string, content: string, path: string, source: SourceMeta) => T | null;
|
|
416
|
+
/** Whether to recurse into subdirectories (default: false) */
|
|
417
|
+
recursive?: boolean;
|
|
418
|
+
},
|
|
419
|
+
): Promise<LoadResult<T>> {
|
|
420
|
+
const items: T[] = [];
|
|
421
|
+
const warnings: string[] = [];
|
|
422
|
+
// Build glob pattern based on extensions and recursion
|
|
423
|
+
const { extensions, recursive = false } = options;
|
|
424
|
+
|
|
425
|
+
let pattern: string;
|
|
426
|
+
if (extensions && extensions.length > 0) {
|
|
427
|
+
const extPattern = extensions.length === 1 ? extensions[0] : `{${extensions.join(",")}}`;
|
|
428
|
+
pattern = recursive ? `**/*.${extPattern}` : `*.${extPattern}`;
|
|
429
|
+
} else {
|
|
430
|
+
pattern = recursive ? "**/*" : "*";
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Use native glob for fast scanning with gitignore support
|
|
434
|
+
let matches: Array<{ path: string }>;
|
|
435
|
+
try {
|
|
436
|
+
const result = await glob({
|
|
437
|
+
pattern,
|
|
438
|
+
path: dir,
|
|
439
|
+
gitignore: true,
|
|
440
|
+
hidden: false,
|
|
441
|
+
fileType: FileType.File,
|
|
442
|
+
});
|
|
443
|
+
matches = result.matches;
|
|
444
|
+
} catch {
|
|
445
|
+
// Directory doesn't exist or isn't readable
|
|
446
|
+
return { items, warnings };
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Read all matching files in parallel
|
|
450
|
+
const fileResults = await Promise.all(
|
|
451
|
+
matches.map(async match => {
|
|
452
|
+
const filePath = path.join(dir, match.path);
|
|
453
|
+
const content = await readFile(filePath);
|
|
454
|
+
return { filePath, content };
|
|
455
|
+
}),
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
for (const { filePath, content } of fileResults) {
|
|
459
|
+
if (content === null) {
|
|
460
|
+
warnings.push(`Failed to read file: ${filePath}`);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const name = path.basename(filePath);
|
|
465
|
+
const source = createSourceMeta(provider, filePath, level);
|
|
466
|
+
|
|
467
|
+
try {
|
|
468
|
+
const item = options.transform(name, content, filePath, source);
|
|
469
|
+
if (item !== null) {
|
|
470
|
+
items.push(item);
|
|
471
|
+
}
|
|
472
|
+
} catch (err) {
|
|
473
|
+
warnings.push(`Failed to parse ${filePath}: ${err}`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
return { items, warnings };
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Calculate depth of target directory relative to current working directory.
|
|
481
|
+
* Depth is the number of directory levels from cwd to target.
|
|
482
|
+
* - Positive depth: target is above cwd (parent/ancestor)
|
|
483
|
+
* - Zero depth: target is cwd
|
|
484
|
+
* - This uses path splitting to count directory levels
|
|
485
|
+
*/
|
|
486
|
+
export function calculateDepth(cwd: string, targetDir: string, separator: string): number {
|
|
487
|
+
return cwd.split(separator).length - targetDir.split(separator).length;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
interface ExtensionModuleManifest {
|
|
491
|
+
extensions?: string[];
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
async function readExtensionModuleManifest(
|
|
495
|
+
_ctx: LoadContext,
|
|
496
|
+
packageJsonPath: string,
|
|
497
|
+
): Promise<ExtensionModuleManifest | null> {
|
|
498
|
+
const content = await readFile(packageJsonPath);
|
|
499
|
+
if (!content) return null;
|
|
500
|
+
|
|
501
|
+
const pkg = tryParseJson<{ omp?: ExtensionModuleManifest; pi?: ExtensionModuleManifest }>(content);
|
|
502
|
+
const manifest = pkg?.omp ?? pkg?.pi;
|
|
503
|
+
if (manifest && typeof manifest === "object") {
|
|
504
|
+
return manifest;
|
|
505
|
+
}
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Discover extension module entry points in a directory.
|
|
511
|
+
*
|
|
512
|
+
* Discovery rules:
|
|
513
|
+
* 1. Direct files: `extensions/*.ts` or `*.js` → load
|
|
514
|
+
* 2. Subdirectory with index: `extensions/<ext>/index.ts` or `index.js` → load
|
|
515
|
+
* 3. Subdirectory with package.json: `extensions/<ext>/package.json` with "omp"/"pi" field → load declared paths
|
|
516
|
+
*
|
|
517
|
+
* No recursion beyond one level. Complex packages must use package.json manifest.
|
|
518
|
+
* Uses native glob for fast filesystem scanning with gitignore support.
|
|
519
|
+
*/
|
|
520
|
+
export async function discoverExtensionModulePaths(_ctx: LoadContext, dir: string): Promise<string[]> {
|
|
521
|
+
const discovered = new Set<string>();
|
|
522
|
+
// Find all candidate files in parallel using glob
|
|
523
|
+
const [directFiles, indexFiles, packageJsonFiles] = await Promise.all([
|
|
524
|
+
// 1. Direct *.ts or *.js files
|
|
525
|
+
globIf(dir, "*.{ts,js}", FileType.File, false),
|
|
526
|
+
// 2. Subdirectory index files
|
|
527
|
+
globIf(dir, "*/index.{ts,js}", FileType.File, false),
|
|
528
|
+
// 3. Subdirectory package.json files
|
|
529
|
+
globIf(dir, "*/package.json", FileType.File, false),
|
|
530
|
+
]);
|
|
531
|
+
|
|
532
|
+
// Process direct files
|
|
533
|
+
for (const match of directFiles) {
|
|
534
|
+
if (match.path.includes("/")) continue;
|
|
535
|
+
discovered.add(path.join(dir, match.path));
|
|
536
|
+
}
|
|
537
|
+
// Track which subdirectories have package.json manifests with declared extensions
|
|
538
|
+
const subdirsWithDeclaredExtensions = new Set<string>();
|
|
539
|
+
for (const match of packageJsonFiles) {
|
|
540
|
+
const subdir = path.dirname(match.path); // e.g., "my-extension"
|
|
541
|
+
const packageJsonPath = path.join(dir, match.path);
|
|
542
|
+
const manifest = await readExtensionModuleManifest(_ctx, packageJsonPath);
|
|
543
|
+
const declaredExtensions =
|
|
544
|
+
manifest?.extensions?.filter((extPath): extPath is string => typeof extPath === "string") ?? [];
|
|
545
|
+
if (declaredExtensions.length === 0) continue;
|
|
546
|
+
subdirsWithDeclaredExtensions.add(subdir);
|
|
547
|
+
const subdirPath = path.join(dir, subdir);
|
|
548
|
+
for (const extPath of declaredExtensions) {
|
|
549
|
+
let resolvedExtPath = path.resolve(subdirPath, extPath);
|
|
550
|
+
const entries = await readDirEntries(resolvedExtPath);
|
|
551
|
+
if (entries.length !== 0) {
|
|
552
|
+
const pluginFilePath = entries.find(
|
|
553
|
+
e => e.isFile() && (e.name === "index.ts" || e.name === "index.js"),
|
|
554
|
+
)?.name;
|
|
555
|
+
resolvedExtPath = pluginFilePath ? path.join(resolvedExtPath, pluginFilePath) : resolvedExtPath;
|
|
556
|
+
}
|
|
557
|
+
const content = await readFile(resolvedExtPath);
|
|
558
|
+
if (content !== null) {
|
|
559
|
+
discovered.add(resolvedExtPath);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
const preferredIndexBySubdir = new Map<string, string>();
|
|
564
|
+
for (const match of indexFiles) {
|
|
565
|
+
if (match.path.split("/").length !== 2) continue;
|
|
566
|
+
const subdir = path.dirname(match.path);
|
|
567
|
+
if (subdirsWithDeclaredExtensions.has(subdir)) continue;
|
|
568
|
+
const existing = preferredIndexBySubdir.get(subdir);
|
|
569
|
+
if (!existing || (existing.endsWith("index.js") && match.path.endsWith("index.ts"))) {
|
|
570
|
+
preferredIndexBySubdir.set(subdir, match.path);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
for (const preferredPath of preferredIndexBySubdir.values()) {
|
|
574
|
+
discovered.add(path.join(dir, preferredPath));
|
|
575
|
+
}
|
|
576
|
+
return [...discovered];
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Derive a stable extension name from a path.
|
|
581
|
+
*/
|
|
582
|
+
export function getExtensionNameFromPath(extensionPath: string): string {
|
|
583
|
+
const base = extensionPath.replace(/\\/g, "/").split("/").pop() ?? extensionPath;
|
|
584
|
+
|
|
585
|
+
if (base === "index.ts" || base === "index.js") {
|
|
586
|
+
const parts = extensionPath.replace(/\\/g, "/").split("/");
|
|
587
|
+
const parent = parts[parts.length - 2];
|
|
588
|
+
return parent ?? base;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const dot = base.lastIndexOf(".");
|
|
592
|
+
if (dot > 0) {
|
|
593
|
+
return base.slice(0, dot);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
return base;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Build ExtensionModule items from discovered user/project paths.
|
|
601
|
+
* Shared across providers that expose extension modules via user + project dirs.
|
|
602
|
+
*/
|
|
603
|
+
export function buildExtensionModuleItems(
|
|
604
|
+
providerId: string,
|
|
605
|
+
userPaths: string[],
|
|
606
|
+
projectPaths: string[],
|
|
607
|
+
): ExtensionModule[] {
|
|
608
|
+
return [
|
|
609
|
+
...userPaths.map(extPath => ({
|
|
610
|
+
name: getExtensionNameFromPath(extPath),
|
|
611
|
+
path: extPath,
|
|
612
|
+
level: "user" as const,
|
|
613
|
+
_source: createSourceMeta(providerId, extPath, "user"),
|
|
614
|
+
})),
|
|
615
|
+
...projectPaths.map(extPath => ({
|
|
616
|
+
name: getExtensionNameFromPath(extPath),
|
|
617
|
+
path: extPath,
|
|
618
|
+
level: "project" as const,
|
|
619
|
+
_source: createSourceMeta(providerId, extPath, "project"),
|
|
620
|
+
})),
|
|
621
|
+
];
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// =============================================================================
|
|
625
|
+
// Claude Code Plugin Cache Helpers
|
|
626
|
+
// =============================================================================
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Entry for an installed Claude Code plugin.
|
|
630
|
+
*/
|
|
631
|
+
export interface ClaudePluginEntry {
|
|
632
|
+
scope: "user" | "project";
|
|
633
|
+
installPath: string;
|
|
634
|
+
version: string;
|
|
635
|
+
installedAt: string;
|
|
636
|
+
lastUpdated: string;
|
|
637
|
+
gitCommitSha?: string;
|
|
638
|
+
enabled?: boolean;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Claude Code installed_plugins.json registry format.
|
|
643
|
+
*/
|
|
644
|
+
export interface ClaudePluginsRegistry {
|
|
645
|
+
version: number;
|
|
646
|
+
plugins: Record<string, ClaudePluginEntry[]>;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Resolved plugin root for loading.
|
|
651
|
+
*/
|
|
652
|
+
export interface ClaudePluginRoot {
|
|
653
|
+
/** Plugin ID (e.g., "simpleclaude-core@simpleclaude") */
|
|
654
|
+
id: string;
|
|
655
|
+
/** Marketplace name */
|
|
656
|
+
marketplace: string;
|
|
657
|
+
/** Plugin name */
|
|
658
|
+
plugin: string;
|
|
659
|
+
/** Version string */
|
|
660
|
+
version: string;
|
|
661
|
+
/** Absolute path to plugin root */
|
|
662
|
+
path: string;
|
|
663
|
+
/** Whether this is a user or project scope plugin */
|
|
664
|
+
scope: "user" | "project";
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Parse Claude Code installed_plugins.json content.
|
|
669
|
+
*/
|
|
670
|
+
export function parseClaudePluginsRegistry(content: string): ClaudePluginsRegistry | null {
|
|
671
|
+
const data = tryParseJson<ClaudePluginsRegistry>(content);
|
|
672
|
+
if (!data || typeof data !== "object") return null;
|
|
673
|
+
if (
|
|
674
|
+
typeof data.version !== "number" ||
|
|
675
|
+
!data.plugins ||
|
|
676
|
+
typeof data.plugins !== "object" ||
|
|
677
|
+
Array.isArray(data.plugins)
|
|
678
|
+
)
|
|
679
|
+
return null;
|
|
680
|
+
return data;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Resolve the active project registry path by walking up from `cwd`.
|
|
685
|
+
*
|
|
686
|
+
* Walk order:
|
|
687
|
+
* 1. Walk up from `cwd` looking for the nearest directory containing `.omp/`.
|
|
688
|
+
* The first match returns `<dir>/.omp/plugins/installed_plugins.json`.
|
|
689
|
+
* 2. If no `.omp/` is found, rescan from `cwd` upward looking for `.git`.
|
|
690
|
+
* The git root is used as an anchor: `<gitRoot>/.omp/plugins/installed_plugins.json`.
|
|
691
|
+
* 3. If neither is found, return `null` — no project context is active.
|
|
692
|
+
*
|
|
693
|
+
* This is the single source of truth for "active project root" used by install,
|
|
694
|
+
* uninstall, list, upgrade, discovery, and doctor. Deterministic for a given `cwd`.
|
|
695
|
+
*/
|
|
696
|
+
export async function resolveActiveProjectRegistryPath(cwd: string): Promise<string | null> {
|
|
697
|
+
// Pass 1: walk up looking for an existing .omp/ directory (nearest wins).
|
|
698
|
+
// Stop before os.homedir() — ~/.omp/ is the user-level config dir, not a project root.
|
|
699
|
+
const homeDir = os.homedir();
|
|
700
|
+
let dir = path.resolve(cwd);
|
|
701
|
+
while (dir !== homeDir) {
|
|
702
|
+
try {
|
|
703
|
+
const stat = await fs.promises.stat(path.join(dir, getConfigDirName()));
|
|
704
|
+
if (stat.isDirectory()) {
|
|
705
|
+
return path.join(dir, getConfigDirName(), "plugins", "installed_plugins.json");
|
|
706
|
+
}
|
|
707
|
+
} catch {
|
|
708
|
+
// not found at this level — continue up
|
|
709
|
+
}
|
|
710
|
+
const parent = path.dirname(dir);
|
|
711
|
+
if (parent === dir) break; // filesystem root
|
|
712
|
+
dir = parent;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// Pass 2: walk up looking for .git as a fallback anchor.
|
|
716
|
+
dir = path.resolve(cwd);
|
|
717
|
+
while (dir !== homeDir) {
|
|
718
|
+
try {
|
|
719
|
+
await fs.promises.stat(path.join(dir, ".git"));
|
|
720
|
+
return path.join(dir, getConfigDirName(), "plugins", "installed_plugins.json");
|
|
721
|
+
} catch {
|
|
722
|
+
// not found at this level — continue up
|
|
723
|
+
}
|
|
724
|
+
const parent = path.dirname(dir);
|
|
725
|
+
if (parent === dir) break; // filesystem root
|
|
726
|
+
dir = parent;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
return null; // not inside any project
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Like resolveActiveProjectRegistryPath, but falls back to `<cwd>/.omp/plugins/installed_plugins.json`
|
|
734
|
+
* when no project anchor (.omp/ or .git/) is found.
|
|
735
|
+
*
|
|
736
|
+
* Use this when the caller accepts an explicit --scope project so that installing into a freshly
|
|
737
|
+
* bootstrapped directory (no .omp/ or .git/ yet) works: writeInstalledPluginsRegistry auto-creates
|
|
738
|
+
* the directory tree on first write.
|
|
739
|
+
*
|
|
740
|
+
* Returns undefined when cwd is os.homedir() — that path is already the user registry and must
|
|
741
|
+
* never alias as the project registry.
|
|
742
|
+
*/
|
|
743
|
+
export async function resolveOrDefaultProjectRegistryPath(cwd: string): Promise<string | undefined> {
|
|
744
|
+
const resolved = await resolveActiveProjectRegistryPath(cwd);
|
|
745
|
+
if (resolved) return resolved;
|
|
746
|
+
// Home directory must not be treated as a project root: the fallback path would alias
|
|
747
|
+
// getInstalledPluginsRegistryPath(), causing MarketplaceManager to load the same file
|
|
748
|
+
// as both user and project registry and producing duplicates / disambiguation errors.
|
|
749
|
+
if (path.resolve(cwd) === os.homedir()) return undefined;
|
|
750
|
+
return path.join(cwd, getConfigDirName(), "plugins", "installed_plugins.json");
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
const pluginRootsCache = new Map<string, { roots: ClaudePluginRoot[]; warnings: string[] }>();
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* List all installed Claude Code plugin roots from the plugin cache.
|
|
757
|
+
* Reads ~/.claude/plugins/installed_plugins.json and ~/.omp/plugins/installed_plugins.json,
|
|
758
|
+
* and optionally the nearest project-scoped registry resolved from `cwd`.
|
|
759
|
+
*
|
|
760
|
+
* Results are cached per `home:resolvedProjectPath` key to avoid repeated parsing.
|
|
761
|
+
*/
|
|
762
|
+
export async function listClaudePluginRoots(
|
|
763
|
+
home: string,
|
|
764
|
+
cwd?: string,
|
|
765
|
+
): Promise<{ roots: ClaudePluginRoot[]; warnings: string[] }> {
|
|
766
|
+
const resolvedProjectPath = cwd ? await resolveActiveProjectRegistryPath(cwd) : null;
|
|
767
|
+
const cacheKey = `${home}:${resolvedProjectPath ?? ""}`;
|
|
768
|
+
const cached = pluginRootsCache.get(cacheKey);
|
|
769
|
+
if (cached) return cached;
|
|
770
|
+
|
|
771
|
+
const roots: ClaudePluginRoot[] = [];
|
|
772
|
+
const warnings: string[] = [];
|
|
773
|
+
const projectRoots: ClaudePluginRoot[] = [];
|
|
774
|
+
|
|
775
|
+
// ── Claude Code registry ──────────────────────────────────────────────────
|
|
776
|
+
const registryPath = path.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
777
|
+
const content = await readFile(registryPath);
|
|
778
|
+
|
|
779
|
+
if (content) {
|
|
780
|
+
const registry = parseClaudePluginsRegistry(content);
|
|
781
|
+
if (!registry) {
|
|
782
|
+
warnings.push(`Failed to parse Claude Code plugin registry: ${registryPath}`);
|
|
783
|
+
} else {
|
|
784
|
+
for (const [pluginId, entries] of Object.entries(registry.plugins)) {
|
|
785
|
+
if (!Array.isArray(entries) || entries.length === 0) continue;
|
|
786
|
+
|
|
787
|
+
// Parse plugin ID format: "plugin-name@marketplace"
|
|
788
|
+
const atIndex = pluginId.lastIndexOf("@");
|
|
789
|
+
if (atIndex === -1) {
|
|
790
|
+
warnings.push(`Invalid plugin ID format (missing @marketplace): ${pluginId}`);
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
const pluginName = pluginId.slice(0, atIndex);
|
|
795
|
+
const marketplace = pluginId.slice(atIndex + 1);
|
|
796
|
+
|
|
797
|
+
// Process all valid entries, not just the first one.
|
|
798
|
+
// This handles plugins with multiple installs (different scopes/versions).
|
|
799
|
+
for (const entry of entries) {
|
|
800
|
+
if (!entry.installPath || typeof entry.installPath !== "string") {
|
|
801
|
+
warnings.push(`Plugin ${pluginId} entry has no installPath`);
|
|
802
|
+
continue;
|
|
803
|
+
}
|
|
804
|
+
if (entry.enabled === false) continue;
|
|
805
|
+
|
|
806
|
+
roots.push({
|
|
807
|
+
id: pluginId,
|
|
808
|
+
marketplace,
|
|
809
|
+
plugin: pluginName,
|
|
810
|
+
version: entry.version || "unknown",
|
|
811
|
+
path: entry.installPath,
|
|
812
|
+
scope: entry.scope || "user",
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// ── OMP installed plugins registry ───────────────────────────────────────
|
|
820
|
+
// OMP registry is authoritative: its entries replace Claude's entries for the same plugin ID.
|
|
821
|
+
// In production `home` is `os.homedir()`, so `getPluginsDir(home)` resolves to the
|
|
822
|
+
// same XDG-aware path the marketplace writer uses (reads and writes always agree).
|
|
823
|
+
// Tests pass a temp dir, which short-circuits the resolver for deterministic isolation.
|
|
824
|
+
const ompRegistryPath = path.join(getPluginsDir(home), "installed_plugins.json");
|
|
825
|
+
const ompContent = await readFile(ompRegistryPath);
|
|
826
|
+
if (ompContent) {
|
|
827
|
+
const ompRegistry = parseClaudePluginsRegistry(ompContent);
|
|
828
|
+
if (ompRegistry) {
|
|
829
|
+
for (const [pluginId, entries] of Object.entries(ompRegistry.plugins)) {
|
|
830
|
+
if (!Array.isArray(entries) || entries.length === 0) continue;
|
|
831
|
+
|
|
832
|
+
const atIndex = pluginId.lastIndexOf("@");
|
|
833
|
+
if (atIndex === -1) {
|
|
834
|
+
warnings.push(`Invalid plugin ID format (missing @marketplace): ${pluginId}`);
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
const pluginName = pluginId.slice(0, atIndex);
|
|
838
|
+
const marketplace = pluginId.slice(atIndex + 1);
|
|
839
|
+
|
|
840
|
+
// OMP is authoritative: drop all Claude-sourced entries for this plugin ID
|
|
841
|
+
const filtered = roots.filter(r => r.id !== pluginId);
|
|
842
|
+
roots.length = 0;
|
|
843
|
+
roots.push(...filtered);
|
|
844
|
+
|
|
845
|
+
for (const entry of entries) {
|
|
846
|
+
if (!entry.installPath || typeof entry.installPath !== "string") {
|
|
847
|
+
warnings.push(`Plugin ${pluginId} entry has no installPath`);
|
|
848
|
+
continue;
|
|
849
|
+
}
|
|
850
|
+
if (entry.enabled === false) continue;
|
|
851
|
+
// Deduplicate by installPath within same ID
|
|
852
|
+
if (roots.some(r => r.id === pluginId && r.path === entry.installPath)) continue;
|
|
853
|
+
|
|
854
|
+
roots.push({
|
|
855
|
+
id: pluginId,
|
|
856
|
+
marketplace,
|
|
857
|
+
plugin: pluginName,
|
|
858
|
+
version: entry.version || "unknown",
|
|
859
|
+
path: entry.installPath,
|
|
860
|
+
scope: entry.scope || "user",
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
} else {
|
|
865
|
+
warnings.push(`Failed to parse OMP plugin registry: ${ompRegistryPath}`);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// ── Project-scoped OMP registry ────────────────────────────────────────
|
|
870
|
+
// Loaded from the nearest .omp/plugins/installed_plugins.json relative to cwd.
|
|
871
|
+
// Project entries take precedence over user entries for the same plugin ID.
|
|
872
|
+
if (resolvedProjectPath) {
|
|
873
|
+
const projectContent = await readFile(resolvedProjectPath);
|
|
874
|
+
if (projectContent) {
|
|
875
|
+
const projectRegistry = parseClaudePluginsRegistry(projectContent);
|
|
876
|
+
if (projectRegistry) {
|
|
877
|
+
for (const [pluginId, entries] of Object.entries(projectRegistry.plugins)) {
|
|
878
|
+
if (!Array.isArray(entries) || entries.length === 0) continue;
|
|
879
|
+
const atIndex = pluginId.lastIndexOf("@");
|
|
880
|
+
if (atIndex === -1) {
|
|
881
|
+
warnings.push(`Invalid plugin ID format (missing @marketplace): ${pluginId}`);
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
const pluginName = pluginId.slice(0, atIndex);
|
|
885
|
+
const marketplace = pluginId.slice(atIndex + 1);
|
|
886
|
+
for (const entry of entries) {
|
|
887
|
+
if (!entry.installPath || typeof entry.installPath !== "string") {
|
|
888
|
+
warnings.push(`Plugin ${pluginId} entry has no installPath`);
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
if (entry.enabled === false) continue;
|
|
892
|
+
projectRoots.push({
|
|
893
|
+
id: pluginId,
|
|
894
|
+
marketplace,
|
|
895
|
+
plugin: pluginName,
|
|
896
|
+
version: entry.version || "unknown",
|
|
897
|
+
path: entry.installPath,
|
|
898
|
+
scope: "project",
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
} else {
|
|
903
|
+
warnings.push(`Failed to parse project plugin registry: ${resolvedProjectPath}`);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
// Project entries shadow user entries for the same plugin ID.
|
|
909
|
+
if (projectRoots.length > 0) {
|
|
910
|
+
const projectIds = new Set(projectRoots.map(r => r.id));
|
|
911
|
+
const deduped = roots.filter(r => !projectIds.has(r.id));
|
|
912
|
+
roots.length = 0;
|
|
913
|
+
roots.push(...projectRoots, ...deduped);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// Merge --plugin-dir roots (highest precedence) on every fresh load
|
|
917
|
+
if (injectedPluginDirRoots.length > 0) {
|
|
918
|
+
const injectedIds = new Set(injectedPluginDirRoots.map(r => r.id));
|
|
919
|
+
const filtered = roots.filter(r => !injectedIds.has(r.id));
|
|
920
|
+
roots.length = 0;
|
|
921
|
+
roots.push(...injectedPluginDirRoots, ...filtered);
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
const result = { roots, warnings };
|
|
925
|
+
pluginRootsCache.set(cacheKey, result);
|
|
926
|
+
return result;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* Clear the plugin roots cache (useful for testing or when plugins change).
|
|
931
|
+
*/
|
|
932
|
+
export function clearClaudePluginRootsCache(): void {
|
|
933
|
+
pluginRootsCache.clear();
|
|
934
|
+
preloadedPluginRoots = [...injectedPluginDirRoots];
|
|
935
|
+
// Re-warm preloaded roots asynchronously so sync LSP config reads stay valid
|
|
936
|
+
if (lastPreloadHome) {
|
|
937
|
+
void preloadPluginRoots(lastPreloadHome, getProjectDir());
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* Invalidate fs caches for installed-plugin registry files and reset the
|
|
943
|
+
* in-memory plugin roots cache. Used by MarketplaceManager clients after
|
|
944
|
+
* installing/uninstalling/enabling/disabling plugins.
|
|
945
|
+
*/
|
|
946
|
+
export function clearPluginRootsAndCaches(extraPaths?: readonly string[]): void {
|
|
947
|
+
invalidateFsCache(path.join(os.homedir(), ".claude", "plugins", "installed_plugins.json"));
|
|
948
|
+
invalidateFsCache(path.join(getPluginsDir(), "installed_plugins.json"));
|
|
949
|
+
for (const p of extraPaths ?? []) invalidateFsCache(p);
|
|
950
|
+
clearClaudePluginRootsCache();
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
// ── Preloaded plugin roots (for sync consumers like LSP config) ─────────────
|
|
954
|
+
// Populated at startup by preloadPluginRoots(). Read synchronously by
|
|
955
|
+
// getPreloadedPluginRoots(). Safe degradation: empty array if not warmed.
|
|
956
|
+
|
|
957
|
+
let preloadedPluginRoots: ClaudePluginRoot[] = [];
|
|
958
|
+
let injectedPluginDirRoots: ClaudePluginRoot[] = [];
|
|
959
|
+
let lastPreloadHome: string | undefined;
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* Populate the module-level plugin roots cache for sync consumers.
|
|
963
|
+
* Call during session initialization, after dir resolution completes
|
|
964
|
+
* but before any LSP config is read.
|
|
965
|
+
*/
|
|
966
|
+
export async function preloadPluginRoots(home: string, cwd?: string): Promise<void> {
|
|
967
|
+
lastPreloadHome = home;
|
|
968
|
+
const { roots } = await listClaudePluginRoots(home, cwd);
|
|
969
|
+
preloadedPluginRoots = roots;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* Get pre-loaded plugin roots synchronously.
|
|
974
|
+
* Returns empty array if preloadPluginRoots() hasn't been called.
|
|
975
|
+
*/
|
|
976
|
+
export function getPreloadedPluginRoots(): readonly ClaudePluginRoot[] {
|
|
977
|
+
return preloadedPluginRoots;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// ── --plugin-dir injection ──────────────────────────────────────────────────
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* Inject synthetic plugin roots from --plugin-dir paths.
|
|
984
|
+
* These are prepended to the cache with highest precedence (before OMP/Claude entries).
|
|
985
|
+
* Must be called before any listClaudePluginRoots() access.
|
|
986
|
+
*/
|
|
987
|
+
export async function injectPluginDirRoots(home: string, dirs: string[], cwd?: string): Promise<void> {
|
|
988
|
+
const injected: ClaudePluginRoot[] = [];
|
|
989
|
+
for (const dir of dirs) {
|
|
990
|
+
const resolved = path.resolve(dir);
|
|
991
|
+
// Read plugin name from manifest
|
|
992
|
+
let pluginName = path.basename(resolved);
|
|
993
|
+
try {
|
|
994
|
+
const manifestPath = path.join(resolved, ".claude-plugin", "plugin.json");
|
|
995
|
+
const content = await Bun.file(manifestPath).text();
|
|
996
|
+
const manifest = JSON.parse(content);
|
|
997
|
+
if (typeof manifest.name === "string" && manifest.name) {
|
|
998
|
+
pluginName = manifest.name;
|
|
999
|
+
}
|
|
1000
|
+
} catch {
|
|
1001
|
+
// No manifest or invalid — use directory name
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
injected.push(buildPluginDirRoot(resolved, pluginName));
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// Set injected roots BEFORE populating cache so listClaudePluginRoots merges them.
|
|
1008
|
+
injectedPluginDirRoots = injected;
|
|
1009
|
+
lastPreloadHome = home; // ensure cache-clear re-warm fires even when injectPluginDirRoots was the startup path
|
|
1010
|
+
// Clear any stale cache entries (populated before injected roots were set).
|
|
1011
|
+
pluginRootsCache.clear();
|
|
1012
|
+
// Rebuild — cache miss triggers fresh load that includes both user+project registries
|
|
1013
|
+
// and prepends injectedPluginDirRoots at highest precedence.
|
|
1014
|
+
const { roots } = await listClaudePluginRoots(home, cwd);
|
|
1015
|
+
preloadedPluginRoots = roots;
|
|
1016
|
+
}
|