@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,770 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MarketplaceManager — orchestrates registry, fetcher, resolver, and cache.
|
|
3
|
+
*
|
|
4
|
+
* Constructor takes explicit paths for testability (same pattern as registry.ts).
|
|
5
|
+
* The `clearPluginRootsCache` dependency is injected so callers can provide
|
|
6
|
+
* the real `clearClaudePluginRootsCache` while tests supply a counter stub.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as fs from "node:fs/promises";
|
|
10
|
+
import * as os from "node:os";
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
|
|
13
|
+
import { isEnoent, logger, pathIsWithin } from "@oh-my-pi/pi-utils";
|
|
14
|
+
|
|
15
|
+
import { cachePlugin } from "./cache";
|
|
16
|
+
import { classifySource, fetchMarketplace, parseMarketplaceCatalog, promoteCloneToCache } from "./fetcher";
|
|
17
|
+
import {
|
|
18
|
+
addInstalledPlugin,
|
|
19
|
+
addMarketplaceEntry,
|
|
20
|
+
collectReferencedPaths,
|
|
21
|
+
getInstalledPlugin,
|
|
22
|
+
getMarketplaceEntry,
|
|
23
|
+
readInstalledPluginsRegistry,
|
|
24
|
+
readMarketplacesRegistry,
|
|
25
|
+
removeInstalledPlugin,
|
|
26
|
+
removeMarketplaceEntry,
|
|
27
|
+
writeInstalledPluginsRegistry,
|
|
28
|
+
writeMarketplacesRegistry,
|
|
29
|
+
} from "./registry";
|
|
30
|
+
import { resolvePluginSource } from "./source-resolver";
|
|
31
|
+
import type {
|
|
32
|
+
InstalledPluginEntry,
|
|
33
|
+
InstalledPluginSummary,
|
|
34
|
+
InstalledPluginsRegistry,
|
|
35
|
+
MarketplaceCatalog,
|
|
36
|
+
MarketplacePluginEntry,
|
|
37
|
+
MarketplaceRegistryEntry,
|
|
38
|
+
} from "./types";
|
|
39
|
+
import { buildPluginId, parsePluginId } from "./types";
|
|
40
|
+
|
|
41
|
+
// ── Options ──────────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
export interface MarketplaceManagerOptions {
|
|
44
|
+
marketplacesRegistryPath: string;
|
|
45
|
+
installedRegistryPath: string;
|
|
46
|
+
/**
|
|
47
|
+
* Path to the project-scoped installed_plugins.json.
|
|
48
|
+
* Required when installPlugin / uninstallPlugin is called with scope: "project".
|
|
49
|
+
* Resolved by resolveActiveProjectRegistryPath(cwd) in callers.
|
|
50
|
+
*/
|
|
51
|
+
projectInstalledRegistryPath?: string;
|
|
52
|
+
marketplacesCacheDir: string;
|
|
53
|
+
pluginsCacheDir: string;
|
|
54
|
+
/** Injected for testing; production callers pass clearClaudePluginRootsCache.
|
|
55
|
+
* Receives any additional file paths that should also be invalidated from the fs cache.
|
|
56
|
+
*/
|
|
57
|
+
clearPluginRootsCache?: (extraPaths?: readonly string[]) => void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ── Manager ──────────────────────────────────────────────────────────────────
|
|
61
|
+
|
|
62
|
+
export class MarketplaceManager {
|
|
63
|
+
#opts: MarketplaceManagerOptions;
|
|
64
|
+
|
|
65
|
+
constructor(options: MarketplaceManagerOptions) {
|
|
66
|
+
this.#opts = options;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Invalidate fs caches for all registry paths the manager writes, then clear plugin roots.
|
|
70
|
+
#clearCache(): void {
|
|
71
|
+
const extra = this.#opts.projectInstalledRegistryPath
|
|
72
|
+
? ([this.#opts.projectInstalledRegistryPath] as readonly string[])
|
|
73
|
+
: undefined;
|
|
74
|
+
this.#opts.clearPluginRootsCache?.(extra);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ── Marketplace lifecycle ─────────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
async addMarketplace(source: string): Promise<MarketplaceRegistryEntry> {
|
|
80
|
+
const reg = await readMarketplacesRegistry(this.#opts.marketplacesRegistryPath);
|
|
81
|
+
const existingNames = new Set(reg.marketplaces.map(m => m.name));
|
|
82
|
+
|
|
83
|
+
const { catalog, clonePath } = await fetchMarketplace(source, this.#opts.marketplacesCacheDir);
|
|
84
|
+
|
|
85
|
+
if (existingNames.has(catalog.name)) {
|
|
86
|
+
if (clonePath) {
|
|
87
|
+
await fs.rm(clonePath, { recursive: true, force: true }).catch(() => {});
|
|
88
|
+
}
|
|
89
|
+
throw new Error(`Marketplace "${catalog.name}" already exists`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Promote the temp clone to its final cache location now that we know it's not a duplicate.
|
|
93
|
+
if (clonePath) {
|
|
94
|
+
await promoteCloneToCache(clonePath, this.#opts.marketplacesCacheDir, catalog.name);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const sourceType = classifySource(source);
|
|
98
|
+
const normalizedSource =
|
|
99
|
+
sourceType === "local"
|
|
100
|
+
? path.resolve(source.startsWith("~/") ? path.join(os.homedir(), source.slice(2)) : source)
|
|
101
|
+
: source;
|
|
102
|
+
|
|
103
|
+
const catalogPath = path.join(this.#opts.marketplacesCacheDir, catalog.name, "marketplace.json");
|
|
104
|
+
|
|
105
|
+
// Persist the fetched catalog so subsequent reads don't require re-fetching.
|
|
106
|
+
await Bun.write(catalogPath, `${JSON.stringify(catalog, null, 2)}\n`);
|
|
107
|
+
|
|
108
|
+
const now = new Date().toISOString();
|
|
109
|
+
const entry: MarketplaceRegistryEntry = {
|
|
110
|
+
name: catalog.name,
|
|
111
|
+
sourceType,
|
|
112
|
+
sourceUri: normalizedSource,
|
|
113
|
+
catalogPath,
|
|
114
|
+
addedAt: now,
|
|
115
|
+
updatedAt: now,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const updated = addMarketplaceEntry(reg, entry);
|
|
119
|
+
await writeMarketplacesRegistry(this.#opts.marketplacesRegistryPath, updated);
|
|
120
|
+
|
|
121
|
+
logger.debug("Marketplace added", { name: catalog.name, sourceType });
|
|
122
|
+
return entry;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async removeMarketplace(name: string): Promise<void> {
|
|
126
|
+
const reg = await readMarketplacesRegistry(this.#opts.marketplacesRegistryPath);
|
|
127
|
+
// removeMarketplaceEntry throws if not found — propagate to caller.
|
|
128
|
+
const updated = removeMarketplaceEntry(reg, name);
|
|
129
|
+
await writeMarketplacesRegistry(this.#opts.marketplacesRegistryPath, updated);
|
|
130
|
+
|
|
131
|
+
await fs.rm(path.join(this.#opts.marketplacesCacheDir, name), {
|
|
132
|
+
recursive: true,
|
|
133
|
+
force: true,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
logger.debug("Marketplace removed", { name });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async updateMarketplace(name: string): Promise<MarketplaceRegistryEntry> {
|
|
140
|
+
const reg = await readMarketplacesRegistry(this.#opts.marketplacesRegistryPath);
|
|
141
|
+
const existing = getMarketplaceEntry(reg, name);
|
|
142
|
+
if (!existing) {
|
|
143
|
+
throw new Error(`Marketplace "${name}" not found`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const { catalog, clonePath } = await fetchMarketplace(existing.sourceUri, this.#opts.marketplacesCacheDir);
|
|
147
|
+
|
|
148
|
+
// Guard against upstream catalog silently renaming itself — the registry
|
|
149
|
+
// entry is keyed by name, so a drift would corrupt the entry on next read.
|
|
150
|
+
if (catalog.name !== name) {
|
|
151
|
+
if (clonePath) {
|
|
152
|
+
await fs.rm(clonePath, { recursive: true, force: true }).catch(() => {});
|
|
153
|
+
}
|
|
154
|
+
throw new Error(
|
|
155
|
+
`Marketplace catalog name changed from "${name}" to "${catalog.name}". ` +
|
|
156
|
+
`Remove and re-add the marketplace to update.`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Promote the temp clone to its final cache location now that drift check passed.
|
|
161
|
+
if (clonePath) {
|
|
162
|
+
await promoteCloneToCache(clonePath, this.#opts.marketplacesCacheDir, catalog.name);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Overwrite cached catalog
|
|
166
|
+
await Bun.write(existing.catalogPath, `${JSON.stringify(catalog, null, 2)}\n`);
|
|
167
|
+
|
|
168
|
+
const updatedEntry: MarketplaceRegistryEntry = {
|
|
169
|
+
...existing,
|
|
170
|
+
updatedAt: new Date().toISOString(),
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const updatedReg = {
|
|
174
|
+
...reg,
|
|
175
|
+
marketplaces: reg.marketplaces.map(m => (m.name === name ? updatedEntry : m)),
|
|
176
|
+
};
|
|
177
|
+
await writeMarketplacesRegistry(this.#opts.marketplacesRegistryPath, updatedReg);
|
|
178
|
+
|
|
179
|
+
logger.debug("Marketplace updated", { name });
|
|
180
|
+
return updatedEntry;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async updateAllMarketplaces(): Promise<MarketplaceRegistryEntry[]> {
|
|
184
|
+
const marketplaces = await this.listMarketplaces();
|
|
185
|
+
const results: MarketplaceRegistryEntry[] = [];
|
|
186
|
+
for (const m of marketplaces) {
|
|
187
|
+
const updated = await this.updateMarketplace(m.name);
|
|
188
|
+
results.push(updated);
|
|
189
|
+
}
|
|
190
|
+
return results;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async listMarketplaces(): Promise<MarketplaceRegistryEntry[]> {
|
|
194
|
+
const reg = await readMarketplacesRegistry(this.#opts.marketplacesRegistryPath);
|
|
195
|
+
return reg.marketplaces;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ── Plugin discovery ──────────────────────────────────────────────────────
|
|
199
|
+
|
|
200
|
+
async listAvailablePlugins(marketplace?: string): Promise<MarketplacePluginEntry[]> {
|
|
201
|
+
const reg = await readMarketplacesRegistry(this.#opts.marketplacesRegistryPath);
|
|
202
|
+
|
|
203
|
+
if (marketplace !== undefined) {
|
|
204
|
+
const entry = reg.marketplaces.find(m => m.name === marketplace);
|
|
205
|
+
if (!entry) {
|
|
206
|
+
throw new Error(`Marketplace "${marketplace}" not found`);
|
|
207
|
+
}
|
|
208
|
+
const catalog = await this.#readCatalog(entry);
|
|
209
|
+
return catalog.plugins;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const all: MarketplacePluginEntry[] = [];
|
|
213
|
+
for (const entry of reg.marketplaces) {
|
|
214
|
+
const catalog = await this.#readCatalog(entry);
|
|
215
|
+
all.push(...catalog.plugins);
|
|
216
|
+
}
|
|
217
|
+
return all;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async getPluginInfo(name: string, marketplace: string): Promise<MarketplacePluginEntry | null> {
|
|
221
|
+
const plugins = await this.listAvailablePlugins(marketplace);
|
|
222
|
+
return plugins.find(p => p.name === name) ?? null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ── Install / uninstall ───────────────────────────────────────────────────
|
|
226
|
+
|
|
227
|
+
async installPlugin(
|
|
228
|
+
name: string,
|
|
229
|
+
marketplace: string,
|
|
230
|
+
options?: { force?: boolean; scope?: "user" | "project" },
|
|
231
|
+
): Promise<InstalledPluginEntry> {
|
|
232
|
+
const force = options?.force ?? false;
|
|
233
|
+
const scope = options?.scope ?? "user";
|
|
234
|
+
const registryPath = this.#registryPath(scope);
|
|
235
|
+
|
|
236
|
+
// 1. Find marketplace entry
|
|
237
|
+
const mktReg = await readMarketplacesRegistry(this.#opts.marketplacesRegistryPath);
|
|
238
|
+
const mktEntry = getMarketplaceEntry(mktReg, marketplace);
|
|
239
|
+
if (!mktEntry) {
|
|
240
|
+
throw new Error(`Marketplace "${marketplace}" not found`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// 2. Find plugin in catalog
|
|
244
|
+
const catalog = await this.#readCatalog(mktEntry);
|
|
245
|
+
const pluginEntry = catalog.plugins.find(p => p.name === name);
|
|
246
|
+
if (!pluginEntry) {
|
|
247
|
+
throw new Error(`Plugin "${name}" not found in marketplace "${marketplace}"`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const pluginId = buildPluginId(name, marketplace);
|
|
251
|
+
|
|
252
|
+
// 3. Check if already installed
|
|
253
|
+
const instReg = await readInstalledPluginsRegistry(registryPath);
|
|
254
|
+
const existing = getInstalledPlugin(instReg, pluginId);
|
|
255
|
+
if (existing && existing.length > 0 && !force) {
|
|
256
|
+
throw new Error(`Plugin "${pluginId}" is already installed. Use force option to reinstall.`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 4. Resolve source path.
|
|
260
|
+
// marketplaceClonePath is the marketplace root — the directory containing .claude-plugin/
|
|
261
|
+
// catalogPath is <marketplacesCacheDir>/<name>/marketplace.json, so the root is two levels up.
|
|
262
|
+
// For local sources the content was fetched from a local path; the stored catalog is a copy
|
|
263
|
+
// under marketplacesCacheDir. We need the original source root for resolving relative paths.
|
|
264
|
+
// Use: path.dirname(catalogPath) is <cacheDir>/<name>/, and that IS the stored copy root,
|
|
265
|
+
// so `path.resolve(mktEntry.catalogPath, "../..")` = parent of <name>/ inside cacheDir
|
|
266
|
+
// which is wrong for local sources. Instead, derive from the stored catalog directory:
|
|
267
|
+
// stored at: <marketplacesCacheDir>/<catalogName>/marketplace.json
|
|
268
|
+
// The marketplace root for local sources should be the actual local path, but we only have
|
|
269
|
+
// sourceUri. For local sources, use path.resolve of sourceUri; for others use the cache dir.
|
|
270
|
+
const marketplaceClonePath = this.#resolveMarketplaceRoot(mktEntry);
|
|
271
|
+
|
|
272
|
+
// URL-sourced marketplaces only cache marketplace.json, not the full plugin tree.
|
|
273
|
+
// Relative string sources ("./plugins/foo") cannot be resolved against the cache dir.
|
|
274
|
+
if (mktEntry.sourceType === "url" && typeof pluginEntry.source === "string") {
|
|
275
|
+
throw new Error(
|
|
276
|
+
`Plugin "${name}" uses a relative source path but marketplace "${marketplace}" was added via URL. ` +
|
|
277
|
+
`Relative sources require a git or local marketplace. Re-add the marketplace using its git URL.`,
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const { dir: sourcePath, tempCloneRoot } = await resolvePluginSource(pluginEntry, {
|
|
282
|
+
marketplaceClonePath,
|
|
283
|
+
catalogMetadata: catalog.metadata,
|
|
284
|
+
tmpDir: os.tmpdir(),
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// 5. Determine version: catalog entry > plugin manifest > git SHA > fallback
|
|
288
|
+
let version!: string;
|
|
289
|
+
let cachePath!: string;
|
|
290
|
+
try {
|
|
291
|
+
version = await this.#resolvePluginVersion(pluginEntry, sourcePath);
|
|
292
|
+
cachePath = await cachePlugin(sourcePath, this.#opts.pluginsCacheDir, marketplace, name, version);
|
|
293
|
+
await this.#writeEmbeddedLspConfig(pluginEntry, cachePath);
|
|
294
|
+
} finally {
|
|
295
|
+
// Clean up temp clone dirs created by resolvePluginSource; leave user-supplied local dirs alone
|
|
296
|
+
if (tempCloneRoot) {
|
|
297
|
+
await fs.rm(tempCloneRoot, { recursive: true, force: true }).catch(() => {});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Only now clean up old entries — new cache succeeded, so it is safe to remove old ones.
|
|
302
|
+
if (existing && existing.length > 0) {
|
|
303
|
+
// Remove from scope-appropriate registry first, then cross-check refs before disk deletion.
|
|
304
|
+
const prunedReg = removeInstalledPlugin(await readInstalledPluginsRegistry(registryPath), pluginId);
|
|
305
|
+
await writeInstalledPluginsRegistry(registryPath, prunedReg);
|
|
306
|
+
|
|
307
|
+
// Read both registries AFTER removal — only delete paths no longer referenced by either.
|
|
308
|
+
const [userReg, projectReg] = await Promise.all([
|
|
309
|
+
readInstalledPluginsRegistry(this.#opts.installedRegistryPath),
|
|
310
|
+
this.#opts.projectInstalledRegistryPath
|
|
311
|
+
? readInstalledPluginsRegistry(this.#opts.projectInstalledRegistryPath)
|
|
312
|
+
: Promise.resolve({ version: 2 as const, plugins: {} as Record<string, InstalledPluginEntry[]> }),
|
|
313
|
+
]);
|
|
314
|
+
const referenced = collectReferencedPaths(userReg, projectReg);
|
|
315
|
+
|
|
316
|
+
for (const entry of existing) {
|
|
317
|
+
if (entry.installPath !== cachePath && !referenced.has(entry.installPath)) {
|
|
318
|
+
await fs.rm(entry.installPath, { recursive: true, force: true });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// 6. Build and register the entry, preserving enabled state from previous install
|
|
324
|
+
const now = new Date().toISOString();
|
|
325
|
+
// Carry over enabled flag from existing entry — a disabled plugin must stay disabled after upgrade
|
|
326
|
+
const wasDisabled = existing?.some(e => e.enabled === false);
|
|
327
|
+
const installedEntry: InstalledPluginEntry = {
|
|
328
|
+
scope,
|
|
329
|
+
installPath: cachePath,
|
|
330
|
+
version,
|
|
331
|
+
installedAt: now,
|
|
332
|
+
lastUpdated: now,
|
|
333
|
+
...(wasDisabled ? { enabled: false } : {}),
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const freshInstReg = await readInstalledPluginsRegistry(registryPath);
|
|
337
|
+
const newInstReg = addInstalledPlugin(freshInstReg, pluginId, installedEntry);
|
|
338
|
+
await writeInstalledPluginsRegistry(registryPath, newInstReg);
|
|
339
|
+
|
|
340
|
+
this.#clearCache();
|
|
341
|
+
|
|
342
|
+
logger.debug("Plugin installed", { pluginId, version, cachePath });
|
|
343
|
+
return installedEntry;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
async #writeEmbeddedLspConfig(entry: MarketplacePluginEntry, cachePath: string): Promise<void> {
|
|
347
|
+
const lspServers = entry.lspServers;
|
|
348
|
+
if (!lspServers) return;
|
|
349
|
+
|
|
350
|
+
const targetPath = path.join(cachePath, ".lsp.json");
|
|
351
|
+
if (typeof lspServers === "string") {
|
|
352
|
+
const sourcePath = path.resolve(cachePath, lspServers);
|
|
353
|
+
if (!pathIsWithin(cachePath, sourcePath)) {
|
|
354
|
+
throw new Error(`Plugin "${entry.name}" lspServers path escapes the plugin directory`);
|
|
355
|
+
}
|
|
356
|
+
const content = await Bun.file(sourcePath).text();
|
|
357
|
+
await Bun.write(targetPath, content);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
await Bun.write(targetPath, `${JSON.stringify({ servers: lspServers }, null, 2)}\n`);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Resolve plugin version from multiple sources:
|
|
366
|
+
* 1. Catalog entry version (if set)
|
|
367
|
+
* 2. Plugin manifest (.claude-plugin/plugin.json or package.json)
|
|
368
|
+
* 3. Git SHA from source (truncated to 7 chars)
|
|
369
|
+
* 4. Fallback "0.0.0"
|
|
370
|
+
*/
|
|
371
|
+
async #resolvePluginVersion(entry: MarketplacePluginEntry, sourcePath: string): Promise<string> {
|
|
372
|
+
// 1. Catalog entry version
|
|
373
|
+
if (entry.version) return entry.version;
|
|
374
|
+
|
|
375
|
+
// 2. Plugin manifest
|
|
376
|
+
for (const manifestPath of [
|
|
377
|
+
path.join(sourcePath, ".claude-plugin", "plugin.json"),
|
|
378
|
+
path.join(sourcePath, "package.json"),
|
|
379
|
+
]) {
|
|
380
|
+
try {
|
|
381
|
+
const content = await Bun.file(manifestPath).json();
|
|
382
|
+
if (typeof content?.version === "string" && content.version) {
|
|
383
|
+
return content.version;
|
|
384
|
+
}
|
|
385
|
+
} catch {
|
|
386
|
+
// Missing or invalid — try next
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// 3. Git SHA from source definition
|
|
391
|
+
if (typeof entry.source === "object" && "sha" in entry.source && entry.source.sha) {
|
|
392
|
+
return entry.source.sha.slice(0, 7);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return "0.0.0";
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
async uninstallPlugin(pluginId: string, scope?: "user" | "project"): Promise<void> {
|
|
399
|
+
const parsed = parsePluginId(pluginId);
|
|
400
|
+
if (!parsed) {
|
|
401
|
+
throw new Error(`Invalid plugin ID format: "${pluginId}". Expected "name@marketplace".`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const { userEntries, projectEntries, userReg, projectReg } = await this.#findInBothRegistries(pluginId);
|
|
405
|
+
|
|
406
|
+
const inUser = userEntries && userEntries.length > 0;
|
|
407
|
+
const inProject = projectEntries && projectEntries.length > 0;
|
|
408
|
+
|
|
409
|
+
if (!inUser && !inProject) {
|
|
410
|
+
throw new Error(`Plugin "${pluginId}" is not installed`);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Disambiguation: if installed in both scopes and no explicit scope, require one.
|
|
414
|
+
let targetScope: "user" | "project";
|
|
415
|
+
if (inUser && inProject) {
|
|
416
|
+
if (!scope) {
|
|
417
|
+
throw new Error(
|
|
418
|
+
`Plugin "${pluginId}" is installed in both user and project scope. Use --scope user or --scope project to specify which to remove.`,
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
targetScope = scope;
|
|
422
|
+
} else if (inProject) {
|
|
423
|
+
if (scope === "user") {
|
|
424
|
+
throw new Error(`Plugin "${pluginId}" is not installed in user scope`);
|
|
425
|
+
}
|
|
426
|
+
targetScope = "project";
|
|
427
|
+
} else {
|
|
428
|
+
if (scope === "project") {
|
|
429
|
+
throw new Error(`Plugin "${pluginId}" is not installed in project scope`);
|
|
430
|
+
}
|
|
431
|
+
targetScope = "user";
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const targetEntries = targetScope === "project" ? projectEntries! : userEntries!;
|
|
435
|
+
const targetReg = targetScope === "project" ? projectReg : userReg;
|
|
436
|
+
const registryPath = this.#registryPath(targetScope);
|
|
437
|
+
|
|
438
|
+
const updatedReg = removeInstalledPlugin(targetReg, pluginId);
|
|
439
|
+
await writeInstalledPluginsRegistry(registryPath, updatedReg);
|
|
440
|
+
|
|
441
|
+
// Read both registries AFTER removal — only delete paths no longer referenced by either.
|
|
442
|
+
const [freshUserReg, freshProjectReg] = await Promise.all([
|
|
443
|
+
readInstalledPluginsRegistry(this.#opts.installedRegistryPath),
|
|
444
|
+
this.#opts.projectInstalledRegistryPath
|
|
445
|
+
? readInstalledPluginsRegistry(this.#opts.projectInstalledRegistryPath)
|
|
446
|
+
: Promise.resolve({ version: 2 as const, plugins: {} as Record<string, InstalledPluginEntry[]> }),
|
|
447
|
+
]);
|
|
448
|
+
const referenced = collectReferencedPaths(freshUserReg, freshProjectReg);
|
|
449
|
+
|
|
450
|
+
for (const entry of targetEntries) {
|
|
451
|
+
if (!referenced.has(entry.installPath)) {
|
|
452
|
+
await fs.rm(entry.installPath, { recursive: true, force: true });
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
this.#clearCache();
|
|
457
|
+
|
|
458
|
+
logger.debug("Plugin uninstalled", { pluginId, scope: targetScope });
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// ── Plugin state ──────────────────────────────────────────────────────────
|
|
462
|
+
|
|
463
|
+
async listInstalledPlugins(): Promise<InstalledPluginSummary[]> {
|
|
464
|
+
const userReg = await readInstalledPluginsRegistry(this.#opts.installedRegistryPath);
|
|
465
|
+
const projectReg = this.#opts.projectInstalledRegistryPath
|
|
466
|
+
? await readInstalledPluginsRegistry(this.#opts.projectInstalledRegistryPath)
|
|
467
|
+
: null;
|
|
468
|
+
|
|
469
|
+
// Only enabled project installs shadow user installs — a disabled project copy leaves
|
|
470
|
+
// the user entry as the active one and must not be reported as shadowed.
|
|
471
|
+
const activeProjectIds = new Set(
|
|
472
|
+
projectReg
|
|
473
|
+
? Object.entries(projectReg.plugins)
|
|
474
|
+
.filter(([, entries]) => entries.length > 0 && entries[0].enabled !== false)
|
|
475
|
+
.map(([id]) => id)
|
|
476
|
+
: [],
|
|
477
|
+
);
|
|
478
|
+
const results: InstalledPluginSummary[] = [];
|
|
479
|
+
|
|
480
|
+
// Project entries first
|
|
481
|
+
if (projectReg) {
|
|
482
|
+
for (const [id, entries] of Object.entries(projectReg.plugins)) {
|
|
483
|
+
results.push({ id, scope: "project", entries });
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
// User entries (shadow-marked if overridden by project)
|
|
487
|
+
for (const [id, entries] of Object.entries(userReg.plugins)) {
|
|
488
|
+
results.push({
|
|
489
|
+
id,
|
|
490
|
+
scope: "user",
|
|
491
|
+
entries,
|
|
492
|
+
...(activeProjectIds.has(id) ? { shadowedBy: "project" as const } : {}),
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
return results;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
async setPluginEnabled(pluginId: string, enabled: boolean, scope?: "user" | "project"): Promise<void> {
|
|
499
|
+
const { userEntries, projectEntries, userReg, projectReg } = await this.#findInBothRegistries(pluginId);
|
|
500
|
+
|
|
501
|
+
const inUser = userEntries && userEntries.length > 0;
|
|
502
|
+
const inProject = projectEntries && projectEntries.length > 0;
|
|
503
|
+
|
|
504
|
+
if (!inUser && !inProject) {
|
|
505
|
+
throw new Error(`Plugin "${pluginId}" is not installed`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Disambiguation: if installed in both scopes and no explicit scope, require one.
|
|
509
|
+
let targetScope: "user" | "project";
|
|
510
|
+
if (inUser && inProject) {
|
|
511
|
+
if (!scope) {
|
|
512
|
+
throw new Error(
|
|
513
|
+
`Plugin "${pluginId}" is installed in both user and project scope. Use --scope user or --scope project to specify which to modify.`,
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
targetScope = scope;
|
|
517
|
+
} else if (inProject) {
|
|
518
|
+
if (scope === "user") {
|
|
519
|
+
throw new Error(`Plugin "${pluginId}" is not installed in user scope`);
|
|
520
|
+
}
|
|
521
|
+
targetScope = "project";
|
|
522
|
+
} else {
|
|
523
|
+
if (scope === "project") {
|
|
524
|
+
throw new Error(`Plugin "${pluginId}" is not installed in project scope`);
|
|
525
|
+
}
|
|
526
|
+
targetScope = "user";
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const reg = targetScope === "project" ? projectReg : userReg;
|
|
530
|
+
const entries = targetScope === "project" ? projectEntries! : userEntries!;
|
|
531
|
+
const registryPath = this.#registryPath(targetScope);
|
|
532
|
+
|
|
533
|
+
const updated = {
|
|
534
|
+
...reg,
|
|
535
|
+
plugins: {
|
|
536
|
+
...reg.plugins,
|
|
537
|
+
[pluginId]: entries.map(e => ({ ...e, enabled })),
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
await writeInstalledPluginsRegistry(registryPath, updated);
|
|
541
|
+
|
|
542
|
+
this.#clearCache();
|
|
543
|
+
|
|
544
|
+
logger.debug("Plugin enabled state changed", { pluginId, enabled, scope: targetScope });
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// ── Update / upgrade ─────────────────────────────────────────────────────
|
|
548
|
+
|
|
549
|
+
// Refresh marketplace catalogs that haven't been updated in more than 24 h.
|
|
550
|
+
// Per-marketplace failures are silently swallowed — offline is fine.
|
|
551
|
+
async refreshStaleMarketplaces(): Promise<void> {
|
|
552
|
+
const reg = await readMarketplacesRegistry(this.#opts.marketplacesRegistryPath);
|
|
553
|
+
const staleMs = 24 * 60 * 60 * 1000;
|
|
554
|
+
for (const entry of reg.marketplaces) {
|
|
555
|
+
if (Date.now() - Date.parse(entry.updatedAt) >= staleMs) {
|
|
556
|
+
try {
|
|
557
|
+
await this.updateMarketplace(entry.name);
|
|
558
|
+
} catch {
|
|
559
|
+
// Network or parse failure — leave stale, try next time.
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Compare installed plugin versions against their catalog entries.
|
|
566
|
+
// Returns one entry per (pluginId, scope) pair where the catalog declares a newer version.
|
|
567
|
+
// Catalog entries without a version field are skipped.
|
|
568
|
+
async checkForUpdates(): Promise<Array<{ pluginId: string; scope: "user" | "project"; from: string; to: string }>> {
|
|
569
|
+
const mktReg = await readMarketplacesRegistry(this.#opts.marketplacesRegistryPath);
|
|
570
|
+
const updates: Array<{ pluginId: string; scope: "user" | "project"; from: string; to: string }> = [];
|
|
571
|
+
|
|
572
|
+
// Keyed by (path, scope) so each scope is checked independently.
|
|
573
|
+
// A plugin current in user scope but stale in project scope must still appear.
|
|
574
|
+
const registryEntries: Array<[string, "user" | "project"]> = [[this.#opts.installedRegistryPath, "user"]];
|
|
575
|
+
if (this.#opts.projectInstalledRegistryPath) {
|
|
576
|
+
registryEntries.push([this.#opts.projectInstalledRegistryPath, "project"]);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
for (const [regPath, scope] of registryEntries) {
|
|
580
|
+
const instReg = await readInstalledPluginsRegistry(regPath);
|
|
581
|
+
for (const [pluginId, entries] of Object.entries(instReg.plugins)) {
|
|
582
|
+
const parsed = parsePluginId(pluginId);
|
|
583
|
+
if (!parsed) continue;
|
|
584
|
+
const installed = entries[0];
|
|
585
|
+
if (!installed) continue;
|
|
586
|
+
|
|
587
|
+
const mktEntry = mktReg.marketplaces.find(m => m.name === parsed.marketplace);
|
|
588
|
+
if (!mktEntry) continue;
|
|
589
|
+
|
|
590
|
+
let catalogVersion: string | undefined;
|
|
591
|
+
try {
|
|
592
|
+
const catalog = await this.#readCatalog(mktEntry);
|
|
593
|
+
catalogVersion = catalog.plugins.find(p => p.name === parsed.name)?.version;
|
|
594
|
+
} catch {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (!catalogVersion || catalogVersion === installed.version) continue;
|
|
599
|
+
|
|
600
|
+
// Treat newer semver as an update; fall back to inequality for non-semver tags.
|
|
601
|
+
let isNewer: boolean;
|
|
602
|
+
try {
|
|
603
|
+
isNewer = Bun.semver.order(catalogVersion, installed.version) > 0;
|
|
604
|
+
} catch {
|
|
605
|
+
isNewer = catalogVersion !== installed.version;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
if (isNewer) {
|
|
609
|
+
updates.push({ pluginId, scope, from: installed.version, to: catalogVersion });
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
return updates;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Re-install a specific plugin at the latest catalog version (force-overwrites).
|
|
618
|
+
async upgradePlugin(pluginId: string, scope?: "user" | "project"): Promise<InstalledPluginEntry> {
|
|
619
|
+
const parsed = parsePluginId(pluginId);
|
|
620
|
+
if (!parsed) {
|
|
621
|
+
throw new Error(`Invalid plugin ID: "${pluginId}". Expected "name@marketplace".`);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
const { userEntries, projectEntries } = await this.#findInBothRegistries(pluginId);
|
|
625
|
+
|
|
626
|
+
const inUser = userEntries && userEntries.length > 0;
|
|
627
|
+
const inProject = projectEntries && projectEntries.length > 0;
|
|
628
|
+
|
|
629
|
+
if (!inUser && !inProject) {
|
|
630
|
+
throw new Error(`Plugin "${pluginId}" is not installed`);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
let resolvedScope: "user" | "project";
|
|
634
|
+
if (inUser && inProject) {
|
|
635
|
+
if (!scope) {
|
|
636
|
+
throw new Error(
|
|
637
|
+
`Plugin "${pluginId}" is installed in both user and project scope. Use --scope user or --scope project to specify which to upgrade.`,
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
resolvedScope = scope;
|
|
641
|
+
} else if (inProject) {
|
|
642
|
+
if (scope === "user") throw new Error(`Plugin "${pluginId}" is not installed in user scope`);
|
|
643
|
+
resolvedScope = "project";
|
|
644
|
+
} else {
|
|
645
|
+
if (scope === "project") throw new Error(`Plugin "${pluginId}" is not installed in project scope`);
|
|
646
|
+
resolvedScope = "user";
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return this.installPlugin(parsed.name, parsed.marketplace, { force: true, scope: resolvedScope });
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Upgrade a plugin across all scopes where it is installed.
|
|
653
|
+
// Returns one entry per scope upgraded (0–2 entries).
|
|
654
|
+
async upgradePluginAcrossScopes(pluginId: string): Promise<InstalledPluginEntry[]> {
|
|
655
|
+
const parsed = parsePluginId(pluginId);
|
|
656
|
+
if (!parsed) {
|
|
657
|
+
throw new Error(`Invalid plugin ID: "${pluginId}". Expected "name@marketplace".`);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
const { userEntries, projectEntries } = await this.#findInBothRegistries(pluginId);
|
|
661
|
+
|
|
662
|
+
const inUser = userEntries && userEntries.length > 0;
|
|
663
|
+
const inProject = projectEntries && projectEntries.length > 0;
|
|
664
|
+
|
|
665
|
+
if (!inUser && !inProject) {
|
|
666
|
+
throw new Error(`Plugin "${pluginId}" is not installed`);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const results: InstalledPluginEntry[] = [];
|
|
670
|
+
|
|
671
|
+
if (inProject) {
|
|
672
|
+
const entry = await this.installPlugin(parsed.name, parsed.marketplace, { force: true, scope: "project" });
|
|
673
|
+
results.push(entry);
|
|
674
|
+
}
|
|
675
|
+
if (inUser) {
|
|
676
|
+
const entry = await this.installPlugin(parsed.name, parsed.marketplace, { force: true, scope: "user" });
|
|
677
|
+
results.push(entry);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
return results;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// Upgrade every (pluginId, scope) pair that checkForUpdates reports as outdated.
|
|
684
|
+
// Only stale scopes are touched; a current user install is not re-installed when only
|
|
685
|
+
// the project scope is stale. Per-entry failures are skipped — partial success is returned.
|
|
686
|
+
async upgradeAllPlugins(): Promise<
|
|
687
|
+
Array<{ pluginId: string; scope: "user" | "project"; from: string; to: string }>
|
|
688
|
+
> {
|
|
689
|
+
const updates = await this.checkForUpdates();
|
|
690
|
+
const results: Array<{ pluginId: string; scope: "user" | "project"; from: string; to: string }> = [];
|
|
691
|
+
for (const update of updates) {
|
|
692
|
+
try {
|
|
693
|
+
const entry = await this.upgradePlugin(update.pluginId, update.scope);
|
|
694
|
+
results.push({ pluginId: update.pluginId, scope: update.scope, from: update.from, to: entry.version });
|
|
695
|
+
} catch {
|
|
696
|
+
// Skip this entry; partial upgrades are better than none.
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return results;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// ── Private helpers ───────────────────────────────────────────────────────
|
|
703
|
+
|
|
704
|
+
#registryPath(scope: "user" | "project"): string {
|
|
705
|
+
if (scope === "project") {
|
|
706
|
+
if (!this.#opts.projectInstalledRegistryPath) {
|
|
707
|
+
throw new Error("project-scoped install requires running inside a project directory");
|
|
708
|
+
}
|
|
709
|
+
return this.#opts.projectInstalledRegistryPath;
|
|
710
|
+
}
|
|
711
|
+
return this.#opts.installedRegistryPath;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
async #findInBothRegistries(pluginId: string): Promise<{
|
|
715
|
+
userEntries: InstalledPluginEntry[] | undefined;
|
|
716
|
+
projectEntries: InstalledPluginEntry[] | undefined;
|
|
717
|
+
userReg: InstalledPluginsRegistry;
|
|
718
|
+
projectReg: InstalledPluginsRegistry;
|
|
719
|
+
}> {
|
|
720
|
+
const [userReg, projectReg] = await Promise.all([
|
|
721
|
+
readInstalledPluginsRegistry(this.#opts.installedRegistryPath),
|
|
722
|
+
this.#opts.projectInstalledRegistryPath
|
|
723
|
+
? readInstalledPluginsRegistry(this.#opts.projectInstalledRegistryPath)
|
|
724
|
+
: Promise.resolve({ version: 2 as const, plugins: {} as Record<string, InstalledPluginEntry[]> }),
|
|
725
|
+
]);
|
|
726
|
+
return {
|
|
727
|
+
userEntries: getInstalledPlugin(userReg, pluginId),
|
|
728
|
+
projectEntries: getInstalledPlugin(projectReg, pluginId),
|
|
729
|
+
userReg,
|
|
730
|
+
projectReg,
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
async #readCatalog(entry: MarketplaceRegistryEntry): Promise<MarketplaceCatalog> {
|
|
735
|
+
try {
|
|
736
|
+
const content = await Bun.file(entry.catalogPath).text();
|
|
737
|
+
return parseMarketplaceCatalog(content, entry.catalogPath);
|
|
738
|
+
} catch (err) {
|
|
739
|
+
if (isEnoent(err)) {
|
|
740
|
+
throw new Error(
|
|
741
|
+
`Marketplace catalog not found at ${entry.catalogPath}. Try: /marketplace update ${entry.name}`,
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
throw err;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* Compute the marketplace root directory for source resolution.
|
|
750
|
+
*
|
|
751
|
+
* For local sources: sourceUri IS the local path, so resolve it directly.
|
|
752
|
+
* This gives the directory containing `.claude-plugin/marketplace.json`,
|
|
753
|
+
* which is what resolvePluginSource expects as `marketplaceClonePath`.
|
|
754
|
+
*
|
|
755
|
+
* For remote sources (git/github/url): the catalog was cloned into
|
|
756
|
+
* `<marketplacesCacheDir>/<name>/`, so the root is the parent of catalogPath.
|
|
757
|
+
*/
|
|
758
|
+
#resolveMarketplaceRoot(entry: MarketplaceRegistryEntry): string {
|
|
759
|
+
if (entry.sourceType === "local") {
|
|
760
|
+
// expandHome already happened in fetcher; resolve to ensure absolute.
|
|
761
|
+
const expanded = entry.sourceUri.startsWith("~/")
|
|
762
|
+
? path.join(os.homedir(), entry.sourceUri.slice(2))
|
|
763
|
+
: entry.sourceUri;
|
|
764
|
+
return path.resolve(expanded);
|
|
765
|
+
}
|
|
766
|
+
// For git/github/url sources, the catalog lives at <cloneDir>/marketplace.json
|
|
767
|
+
// under marketplacesCacheDir/<name>/; parent = <marketplacesCacheDir>/<name>/
|
|
768
|
+
return path.dirname(entry.catalogPath);
|
|
769
|
+
}
|
|
770
|
+
}
|