@oh-my-pi/pi-coding-agent 8.1.0 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/docs/session.md +111 -46
- package/examples/custom-tools/hello/index.ts +1 -1
- package/examples/custom-tools/todo/index.ts +3 -4
- package/examples/extensions/api-demo.ts +0 -1
- package/examples/extensions/chalk-logger.ts +2 -3
- package/examples/extensions/hello.ts +0 -1
- package/examples/extensions/pirate.ts +0 -1
- package/examples/extensions/plan-mode.ts +15 -16
- package/examples/extensions/todo.ts +3 -4
- package/examples/extensions/tools.ts +1 -2
- package/examples/extensions/with-deps/index.ts +0 -1
- package/examples/hooks/auto-commit-on-exit.ts +1 -2
- package/examples/hooks/confirm-destructive.ts +0 -1
- package/examples/hooks/custom-compaction.ts +1 -2
- package/examples/hooks/dirty-repo-guard.ts +0 -1
- package/examples/hooks/file-trigger.ts +3 -4
- package/examples/hooks/git-checkpoint.ts +0 -1
- package/examples/hooks/handoff.ts +3 -4
- package/examples/hooks/permission-gate.ts +1 -2
- package/examples/hooks/protected-paths.ts +1 -2
- package/examples/hooks/qna.ts +2 -3
- package/examples/hooks/snake.ts +4 -5
- package/examples/hooks/status-line.ts +0 -1
- package/examples/sdk/01-minimal.ts +2 -3
- package/examples/sdk/02-custom-model.ts +2 -3
- package/examples/sdk/03-custom-prompt.ts +3 -4
- package/examples/sdk/04-skills.ts +2 -3
- package/examples/sdk/06-extensions.ts +1 -2
- package/examples/sdk/06-hooks.ts +6 -7
- package/examples/sdk/07-context-files.ts +0 -1
- package/examples/sdk/08-prompt-templates.ts +0 -1
- package/examples/sdk/08-slash-commands.ts +0 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +0 -1
- package/examples/sdk/10-settings.ts +0 -1
- package/examples/sdk/11-sessions.ts +0 -1
- package/package.json +51 -23
- package/scripts/format-prompts.ts +0 -1
- package/src/capability/context-file.ts +2 -3
- package/src/capability/extension-module.ts +2 -3
- package/src/capability/extension.ts +2 -3
- package/src/capability/fs.ts +20 -21
- package/src/capability/hook.ts +2 -3
- package/src/capability/index.ts +15 -16
- package/src/capability/instruction.ts +2 -3
- package/src/capability/mcp.ts +2 -3
- package/src/capability/prompt.ts +2 -3
- package/src/capability/rule.ts +2 -3
- package/src/capability/settings.ts +1 -2
- package/src/capability/skill.ts +2 -3
- package/src/capability/slash-command.ts +2 -3
- package/src/capability/ssh.ts +2 -3
- package/src/capability/system-prompt.ts +2 -3
- package/src/capability/tool.ts +2 -3
- package/src/cli/args.ts +5 -6
- package/src/cli/config-cli.ts +6 -7
- package/src/cli/file-processor.ts +19 -17
- package/src/cli/jupyter-cli.ts +105 -0
- package/src/cli/list-models.ts +10 -11
- package/src/cli/plugin-cli.ts +20 -21
- package/src/cli/session-picker.ts +2 -3
- package/src/cli/setup-cli.ts +2 -3
- package/src/cli/stats-cli.ts +2 -3
- package/src/cli/update-cli.ts +25 -22
- package/src/commit/agentic/agent.ts +21 -23
- package/src/commit/agentic/fallback.ts +9 -9
- package/src/commit/agentic/index.ts +30 -38
- package/src/commit/agentic/state.ts +1 -6
- package/src/commit/agentic/tools/analyze-file.ts +15 -15
- package/src/commit/agentic/tools/git-file-diff.ts +3 -3
- package/src/commit/agentic/tools/git-hunk.ts +7 -7
- package/src/commit/agentic/tools/git-overview.ts +5 -5
- package/src/commit/agentic/tools/index.ts +14 -14
- package/src/commit/agentic/tools/propose-changelog.ts +6 -6
- package/src/commit/agentic/tools/propose-commit.ts +8 -8
- package/src/commit/agentic/tools/recent-commits.ts +2 -2
- package/src/commit/agentic/tools/split-commit.ts +19 -23
- package/src/commit/agentic/topo-sort.ts +1 -1
- package/src/commit/agentic/trivial.ts +3 -3
- package/src/commit/agentic/validation.ts +12 -12
- package/src/commit/analysis/conventional.ts +7 -11
- package/src/commit/analysis/index.ts +4 -4
- package/src/commit/analysis/scope.ts +4 -4
- package/src/commit/analysis/summary.ts +7 -9
- package/src/commit/analysis/validation.ts +1 -1
- package/src/commit/changelog/detect.ts +6 -6
- package/src/commit/changelog/generate.ts +7 -9
- package/src/commit/changelog/index.ts +13 -13
- package/src/commit/changelog/parse.ts +2 -2
- package/src/commit/cli.ts +1 -1
- package/src/commit/git/diff.ts +3 -3
- package/src/commit/git/index.ts +19 -24
- package/src/commit/index.ts +1 -1
- package/src/commit/map-reduce/index.ts +9 -9
- package/src/commit/map-reduce/map-phase.ts +19 -34
- package/src/commit/map-reduce/reduce-phase.ts +9 -11
- package/src/commit/message.ts +2 -2
- package/src/commit/model-selection.ts +3 -7
- package/src/commit/pipeline.ts +20 -22
- package/src/commit/utils/exclusions.ts +3 -3
- package/src/config/file-lock.ts +17 -7
- package/src/config/keybindings.ts +6 -8
- package/src/config/model-registry.ts +55 -37
- package/src/config/model-resolver.ts +18 -19
- package/src/config/prompt-templates.ts +11 -11
- package/src/config/settings-manager.ts +50 -34
- package/src/config.ts +60 -62
- package/src/cursor.ts +11 -9
- package/src/discovery/agents-md.ts +11 -12
- package/src/discovery/builtin.ts +68 -73
- package/src/discovery/claude.ts +41 -42
- package/src/discovery/cline.ts +11 -12
- package/src/discovery/codex.ts +52 -53
- package/src/discovery/cursor.ts +9 -10
- package/src/discovery/gemini.ts +17 -22
- package/src/discovery/github.ts +13 -14
- package/src/discovery/helpers.ts +35 -34
- package/src/discovery/index.ts +16 -18
- package/src/discovery/mcp-json.ts +8 -9
- package/src/discovery/ssh.ts +8 -9
- package/src/discovery/vscode.ts +4 -5
- package/src/discovery/windsurf.ts +6 -7
- package/src/exa/company.ts +1 -2
- package/src/exa/index.ts +2 -3
- package/src/exa/linkedin.ts +1 -2
- package/src/exa/mcp-client.ts +14 -16
- package/src/exa/render.ts +10 -11
- package/src/exa/researcher.ts +1 -2
- package/src/exa/search.ts +1 -2
- package/src/exa/types.ts +0 -1
- package/src/exa/websets.ts +1 -2
- package/src/exec/bash-executor.ts +3 -4
- package/src/exec/exec.ts +0 -1
- package/src/export/custom-share.ts +5 -6
- package/src/export/html/index.ts +24 -21
- package/src/export/ttsr.ts +2 -3
- package/src/extensibility/custom-commands/bundled/review/index.ts +7 -8
- package/src/extensibility/custom-commands/loader.ts +17 -14
- package/src/extensibility/custom-commands/types.ts +1 -2
- package/src/extensibility/custom-tools/loader.ts +10 -11
- package/src/extensibility/custom-tools/types.ts +6 -7
- package/src/extensibility/custom-tools/wrapper.ts +2 -3
- package/src/extensibility/extensions/loader.ts +75 -53
- package/src/extensibility/extensions/runner.ts +11 -12
- package/src/extensibility/extensions/types.ts +19 -26
- package/src/extensibility/extensions/wrapper.ts +3 -4
- package/src/extensibility/hooks/index.ts +1 -1
- package/src/extensibility/hooks/loader.ts +8 -9
- package/src/extensibility/hooks/runner.ts +7 -8
- package/src/extensibility/hooks/tool-wrapper.ts +0 -1
- package/src/extensibility/hooks/types.ts +10 -17
- package/src/extensibility/plugins/doctor.ts +3 -3
- package/src/extensibility/plugins/installer.ts +27 -27
- package/src/extensibility/plugins/loader.ts +59 -56
- package/src/extensibility/plugins/manager.ts +211 -171
- package/src/extensibility/plugins/parser.ts +1 -1
- package/src/extensibility/plugins/paths.ts +8 -8
- package/src/extensibility/skills.ts +63 -60
- package/src/extensibility/slash-commands.ts +10 -10
- package/src/index.ts +46 -46
- package/src/internal-urls/agent-protocol.ts +21 -11
- package/src/internal-urls/artifact-protocol.ts +17 -13
- package/src/internal-urls/router.ts +1 -2
- package/src/internal-urls/rule-protocol.ts +3 -4
- package/src/internal-urls/skill-protocol.ts +3 -4
- package/src/ipy/executor.ts +14 -10
- package/src/ipy/gateway-coordinator.ts +79 -90
- package/src/ipy/kernel.ts +32 -30
- package/src/ipy/modules.ts +13 -13
- package/src/lsp/client.ts +21 -10
- package/src/lsp/clients/biome-client.ts +1 -2
- package/src/lsp/clients/index.ts +3 -3
- package/src/lsp/clients/lsp-linter-client.ts +4 -5
- package/src/lsp/config.ts +15 -15
- package/src/lsp/edits.ts +4 -5
- package/src/lsp/index.ts +43 -44
- package/src/lsp/lspmux.ts +8 -8
- package/src/lsp/render.ts +10 -16
- package/src/lsp/utils.ts +3 -3
- package/src/main.ts +55 -34
- package/src/mcp/client.ts +2 -3
- package/src/mcp/config.ts +5 -6
- package/src/mcp/json-rpc.ts +0 -1
- package/src/mcp/loader.ts +3 -4
- package/src/mcp/manager.ts +17 -18
- package/src/mcp/tool-bridge.ts +4 -9
- package/src/mcp/tool-cache.ts +2 -3
- package/src/mcp/transports/http.ts +2 -4
- package/src/mcp/transports/stdio.ts +1 -2
- package/src/migrations.ts +60 -49
- package/src/modes/components/armin.ts +4 -5
- package/src/modes/components/assistant-message.ts +6 -6
- package/src/modes/components/bash-execution.ts +7 -8
- package/src/modes/components/bordered-loader.ts +3 -3
- package/src/modes/components/branch-summary-message.ts +3 -3
- package/src/modes/components/compaction-summary-message.ts +3 -3
- package/src/modes/components/countdown-timer.ts +0 -1
- package/src/modes/components/custom-message.ts +5 -5
- package/src/modes/components/diff.ts +1 -1
- package/src/modes/components/dynamic-border.ts +2 -2
- package/src/modes/components/extensions/extension-dashboard.ts +6 -7
- package/src/modes/components/extensions/extension-list.ts +2 -3
- package/src/modes/components/extensions/inspector-panel.ts +3 -4
- package/src/modes/components/extensions/state-manager.ts +25 -26
- package/src/modes/components/extensions/types.ts +1 -2
- package/src/modes/components/footer.ts +47 -43
- package/src/modes/components/history-search.ts +2 -2
- package/src/modes/components/hook-editor.ts +3 -4
- package/src/modes/components/hook-input.ts +2 -3
- package/src/modes/components/hook-message.ts +5 -5
- package/src/modes/components/hook-selector.ts +2 -3
- package/src/modes/components/keybinding-hints.ts +2 -3
- package/src/modes/components/login-dialog.ts +2 -2
- package/src/modes/components/model-selector.ts +12 -12
- package/src/modes/components/oauth-selector.ts +2 -2
- package/src/modes/components/plugin-settings.ts +20 -20
- package/src/modes/components/python-execution.ts +7 -8
- package/src/modes/components/queue-mode-selector.ts +3 -3
- package/src/modes/components/read-tool-group.ts +2 -2
- package/src/modes/components/session-selector.ts +4 -4
- package/src/modes/components/settings-defs.ts +77 -69
- package/src/modes/components/settings-selector.ts +16 -16
- package/src/modes/components/show-images-selector.ts +2 -2
- package/src/modes/components/status-line/segments.ts +4 -4
- package/src/modes/components/status-line/separators.ts +1 -1
- package/src/modes/components/status-line/types.ts +2 -2
- package/src/modes/components/status-line-segment-editor.ts +7 -8
- package/src/modes/components/status-line.ts +12 -12
- package/src/modes/components/theme-selector.ts +8 -7
- package/src/modes/components/thinking-selector.ts +4 -4
- package/src/modes/components/todo-display.ts +2 -2
- package/src/modes/components/todo-reminder.ts +4 -4
- package/src/modes/components/tool-execution.ts +11 -16
- package/src/modes/components/tree-selector.ts +11 -11
- package/src/modes/components/ttsr-notification.ts +5 -5
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +1 -1
- package/src/modes/components/visual-truncate.ts +0 -1
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +46 -47
- package/src/modes/controllers/event-controller.ts +16 -20
- package/src/modes/controllers/extension-ui-controller.ts +40 -46
- package/src/modes/controllers/input-controller.ts +17 -18
- package/src/modes/controllers/selector-controller.ts +103 -91
- package/src/modes/index.ts +3 -3
- package/src/modes/interactive-mode.ts +27 -29
- package/src/modes/print-mode.ts +12 -13
- package/src/modes/rpc/rpc-client.ts +7 -8
- package/src/modes/rpc/rpc-mode.ts +24 -25
- package/src/modes/rpc/rpc-types.ts +3 -4
- package/src/modes/theme/mermaid-cache.ts +2 -2
- package/src/modes/theme/theme.ts +128 -53
- package/src/modes/types.ts +10 -10
- package/src/modes/utils/ui-helpers.ts +17 -17
- package/src/patch/applicator.ts +18 -19
- package/src/patch/diff.ts +1 -2
- package/src/patch/fuzzy.ts +1 -2
- package/src/patch/index.ts +10 -11
- package/src/patch/normalize.ts +4 -4
- package/src/patch/normative.ts +1 -2
- package/src/patch/parser.ts +8 -9
- package/src/patch/shared.ts +12 -13
- package/src/sdk.ts +60 -63
- package/src/session/agent-session.ts +83 -84
- package/src/session/agent-storage.ts +11 -11
- package/src/session/artifacts.ts +8 -9
- package/src/session/auth-storage.ts +25 -29
- package/src/session/compaction/branch-summarization.ts +7 -10
- package/src/session/compaction/compaction.ts +8 -19
- package/src/session/compaction/utils.ts +6 -9
- package/src/session/history-storage.ts +10 -10
- package/src/session/messages.ts +4 -5
- package/src/session/session-manager.ts +76 -65
- package/src/session/session-storage.ts +57 -69
- package/src/session/storage-migration.ts +2 -3
- package/src/session/streaming-output.ts +2 -2
- package/src/ssh/connection-manager.ts +43 -50
- package/src/ssh/ssh-executor.ts +2 -2
- package/src/ssh/sshfs-mount.ts +11 -18
- package/src/system-prompt.ts +27 -34
- package/src/task/agents.ts +45 -30
- package/src/task/commands.ts +6 -7
- package/src/task/discovery.ts +39 -76
- package/src/task/executor.ts +14 -15
- package/src/task/index.ts +33 -36
- package/src/task/output-manager.ts +3 -4
- package/src/task/parallel.ts +0 -1
- package/src/task/render.ts +19 -20
- package/src/task/subprocess-tool-registry.ts +1 -2
- package/src/task/worker-protocol.ts +3 -3
- package/src/task/worker.ts +32 -38
- package/src/task/worktree.ts +19 -19
- package/src/tools/ask.ts +8 -9
- package/src/tools/bash-interceptor.ts +1 -5
- package/src/tools/bash.ts +19 -18
- package/src/tools/calculator.ts +12 -12
- package/src/tools/complete.ts +3 -4
- package/src/tools/context.ts +2 -2
- package/src/tools/fetch.ts +23 -26
- package/src/tools/find.ts +15 -16
- package/src/tools/gemini-image.ts +14 -14
- package/src/tools/grep.ts +27 -27
- package/src/tools/index.ts +78 -56
- package/src/tools/list-limit.ts +1 -1
- package/src/tools/ls.ts +7 -7
- package/src/tools/notebook.ts +5 -5
- package/src/tools/output-meta.ts +3 -4
- package/src/tools/output-utils.ts +1 -1
- package/src/tools/path-utils.ts +5 -5
- package/src/tools/python.ts +36 -37
- package/src/tools/read.ts +23 -23
- package/src/tools/render-utils.ts +8 -9
- package/src/tools/renderers.ts +6 -7
- package/src/tools/review.ts +8 -11
- package/src/tools/ssh.ts +31 -30
- package/src/tools/todo-write.ts +13 -13
- package/src/tools/tool-errors.ts +3 -3
- package/src/tools/tool-result.ts +3 -8
- package/src/tools/write.ts +11 -16
- package/src/tui/code-cell.ts +3 -9
- package/src/tui/file-list.ts +3 -4
- package/src/tui/output-block.ts +1 -2
- package/src/tui/status-line.ts +2 -3
- package/src/tui/tree-list.ts +2 -3
- package/src/tui/types.ts +1 -2
- package/src/tui/utils.ts +2 -3
- package/src/utils/changelog.ts +9 -10
- package/src/utils/clipboard.ts +11 -11
- package/src/utils/file-mentions.ts +4 -10
- package/src/utils/frontmatter.ts +6 -3
- package/src/utils/fuzzy.ts +2 -2
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +1 -1
- package/src/utils/mime.ts +2 -2
- package/src/utils/shell-snapshot.ts +11 -13
- package/src/utils/shell.ts +4 -5
- package/src/utils/title-generator.ts +8 -9
- package/src/utils/tools-manager.ts +23 -23
- package/src/vendor/photon/index.js +1099 -1059
- package/src/vendor/photon/photon_rs_bg.wasm +0 -0
- package/src/web/scrapers/artifacthub.ts +1 -1
- package/src/web/scrapers/arxiv.ts +2 -2
- package/src/web/scrapers/bluesky.ts +2 -2
- package/src/web/scrapers/cheatsh.ts +1 -1
- package/src/web/scrapers/chocolatey.ts +2 -2
- package/src/web/scrapers/choosealicense.ts +5 -5
- package/src/web/scrapers/cisa-kev.ts +1 -1
- package/src/web/scrapers/crossref.ts +2 -2
- package/src/web/scrapers/devto.ts +3 -3
- package/src/web/scrapers/discogs.ts +3 -4
- package/src/web/scrapers/discourse.ts +1 -1
- package/src/web/scrapers/dockerhub.ts +1 -1
- package/src/web/scrapers/fdroid.ts +2 -2
- package/src/web/scrapers/firefox-addons.ts +3 -3
- package/src/web/scrapers/flathub.ts +1 -1
- package/src/web/scrapers/github.ts +3 -3
- package/src/web/scrapers/gitlab.ts +4 -4
- package/src/web/scrapers/hackernews.ts +2 -2
- package/src/web/scrapers/huggingface.ts +1 -1
- package/src/web/scrapers/iacr.ts +2 -2
- package/src/web/scrapers/index.ts +0 -1
- package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
- package/src/web/scrapers/lemmy.ts +2 -2
- package/src/web/scrapers/maven.ts +2 -2
- package/src/web/scrapers/mdn.ts +2 -4
- package/src/web/scrapers/metacpan.ts +2 -2
- package/src/web/scrapers/musicbrainz.ts +1 -2
- package/src/web/scrapers/npm.ts +1 -1
- package/src/web/scrapers/nuget.ts +2 -2
- package/src/web/scrapers/nvd.ts +3 -3
- package/src/web/scrapers/ollama.ts +7 -9
- package/src/web/scrapers/opencorporates.ts +2 -2
- package/src/web/scrapers/openlibrary.ts +6 -6
- package/src/web/scrapers/orcid.ts +0 -1
- package/src/web/scrapers/osv.ts +2 -2
- package/src/web/scrapers/packagist.ts +1 -1
- package/src/web/scrapers/pubmed.ts +1 -2
- package/src/web/scrapers/rawg.ts +2 -2
- package/src/web/scrapers/readthedocs.ts +1 -2
- package/src/web/scrapers/repology.ts +2 -2
- package/src/web/scrapers/rfc.ts +1 -1
- package/src/web/scrapers/searchcode.ts +2 -2
- package/src/web/scrapers/semantic-scholar.ts +1 -1
- package/src/web/scrapers/snapcraft.ts +2 -2
- package/src/web/scrapers/sourcegraph.ts +1 -1
- package/src/web/scrapers/spdx.ts +3 -3
- package/src/web/scrapers/spotify.ts +0 -1
- package/src/web/scrapers/twitter.ts +1 -1
- package/src/web/scrapers/types.ts +1 -2
- package/src/web/scrapers/utils.ts +5 -5
- package/src/web/scrapers/wikidata.ts +3 -3
- package/src/web/scrapers/youtube.ts +9 -14
- package/src/web/search/auth.ts +4 -9
- package/src/web/search/index.ts +11 -21
- package/src/web/search/providers/anthropic.ts +3 -9
- package/src/web/search/providers/exa.ts +6 -10
- package/src/web/search/providers/perplexity.ts +5 -5
- package/src/web/search/render.ts +16 -18
- package/scripts/generate-wasm-b64.ts +0 -24
- package/src/commit/map-reduce/.map-phase.ts.kate-swp +0 -0
- package/src/task/.executor.ts.kate-swp +0 -0
- package/src/vendor/photon/photon_rs_bg.wasm.b64.js +0 -1
package/src/discovery/builtin.ts
CHANGED
|
@@ -4,29 +4,24 @@
|
|
|
4
4
|
* Primary provider for OMP native configs. Supports all capabilities.
|
|
5
5
|
* .pi is an alias for backwards compatibility.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
import { registerProvider } from "
|
|
9
|
-
import { type ContextFile, contextFileCapability } from "
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from "
|
|
15
|
-
import { type
|
|
16
|
-
import {
|
|
17
|
-
import { type
|
|
18
|
-
import { type
|
|
19
|
-
import { type
|
|
20
|
-
import { type
|
|
21
|
-
import { type
|
|
22
|
-
import { type
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { type SystemPrompt, systemPromptCapability } from "@oh-my-pi/pi-coding-agent/capability/system-prompt";
|
|
26
|
-
import { type CustomTool, toolCapability } from "@oh-my-pi/pi-coding-agent/capability/tool";
|
|
27
|
-
import type { LoadContext, LoadResult } from "@oh-my-pi/pi-coding-agent/capability/types";
|
|
28
|
-
import { parseFrontmatter } from "@oh-my-pi/pi-coding-agent/utils/frontmatter";
|
|
29
|
-
import { dirname, isAbsolute, join, resolve } from "path";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import { registerProvider } from "../capability";
|
|
9
|
+
import { type ContextFile, contextFileCapability } from "../capability/context-file";
|
|
10
|
+
import { type Extension, type ExtensionManifest, extensionCapability } from "../capability/extension";
|
|
11
|
+
import { type ExtensionModule, extensionModuleCapability } from "../capability/extension-module";
|
|
12
|
+
import { readDirEntries, readFile } from "../capability/fs";
|
|
13
|
+
import { type Hook, hookCapability } from "../capability/hook";
|
|
14
|
+
import { type Instruction, instructionCapability } from "../capability/instruction";
|
|
15
|
+
import { type MCPServer, mcpCapability } from "../capability/mcp";
|
|
16
|
+
import { type Prompt, promptCapability } from "../capability/prompt";
|
|
17
|
+
import { type Rule, ruleCapability } from "../capability/rule";
|
|
18
|
+
import { type Settings, settingsCapability } from "../capability/settings";
|
|
19
|
+
import { type Skill, skillCapability } from "../capability/skill";
|
|
20
|
+
import { type SlashCommand, slashCommandCapability } from "../capability/slash-command";
|
|
21
|
+
import { type SystemPrompt, systemPromptCapability } from "../capability/system-prompt";
|
|
22
|
+
import { type CustomTool, toolCapability } from "../capability/tool";
|
|
23
|
+
import type { LoadContext, LoadResult } from "../capability/types";
|
|
24
|
+
import { parseFrontmatter } from "../utils/frontmatter";
|
|
30
25
|
import {
|
|
31
26
|
createSourceMeta,
|
|
32
27
|
discoverExtensionModulePaths,
|
|
@@ -51,7 +46,7 @@ async function getConfigDirs(ctx: LoadContext): Promise<Array<{ dir: string; lev
|
|
|
51
46
|
const result: Array<{ dir: string; level: "user" | "project" }> = [];
|
|
52
47
|
|
|
53
48
|
for (const name of PROJECT_DIRS) {
|
|
54
|
-
const projectDir = join(ctx.cwd, name);
|
|
49
|
+
const projectDir = path.join(ctx.cwd, name);
|
|
55
50
|
const entries = await readDirEntries(projectDir);
|
|
56
51
|
if (entries.length > 0) {
|
|
57
52
|
result.push({ dir: projectDir, level: "project" });
|
|
@@ -60,7 +55,7 @@ async function getConfigDirs(ctx: LoadContext): Promise<Array<{ dir: string; lev
|
|
|
60
55
|
}
|
|
61
56
|
|
|
62
57
|
for (const name of USER_DIRS) {
|
|
63
|
-
const userDir = join(ctx.home, name, PATHS.userAgent.replace(`${PATHS.userBase}/`, ""));
|
|
58
|
+
const userDir = path.join(ctx.home, name, PATHS.userAgent.replace(`${PATHS.userBase}/`, ""));
|
|
64
59
|
const entries = await readDirEntries(userDir);
|
|
65
60
|
if (entries.length > 0) {
|
|
66
61
|
result.push({ dir: userDir, level: "user" });
|
|
@@ -99,18 +94,18 @@ async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>>
|
|
|
99
94
|
};
|
|
100
95
|
|
|
101
96
|
const projectDirs = await Promise.all(
|
|
102
|
-
PROJECT_DIRS.map(async
|
|
103
|
-
const dir = join(ctx.cwd, name);
|
|
97
|
+
PROJECT_DIRS.map(async name => {
|
|
98
|
+
const dir = path.join(ctx.cwd, name);
|
|
104
99
|
const entries = await readDirEntries(dir);
|
|
105
100
|
return entries.length > 0 ? dir : null;
|
|
106
101
|
}),
|
|
107
102
|
);
|
|
108
|
-
const userPaths = USER_DIRS.map(
|
|
103
|
+
const userPaths = USER_DIRS.map(name => path.join(ctx.home, name, "mcp.json"));
|
|
109
104
|
|
|
110
|
-
const projectDir = projectDirs.find(
|
|
105
|
+
const projectDir = projectDirs.find(dir => dir !== null);
|
|
111
106
|
if (projectDir) {
|
|
112
|
-
const projectCandidates = ["mcp.json", ".mcp.json"].map(
|
|
113
|
-
const projectContents = await Promise.all(projectCandidates.map(
|
|
107
|
+
const projectCandidates = ["mcp.json", ".mcp.json"].map(filename => path.join(projectDir, filename));
|
|
108
|
+
const projectContents = await Promise.all(projectCandidates.map(path => readFile(path)));
|
|
114
109
|
for (let i = 0; i < projectCandidates.length; i++) {
|
|
115
110
|
const content = projectContents[i];
|
|
116
111
|
if (content) {
|
|
@@ -120,7 +115,7 @@ async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>>
|
|
|
120
115
|
}
|
|
121
116
|
}
|
|
122
117
|
|
|
123
|
-
const userContents = await Promise.all(userPaths.map(
|
|
118
|
+
const userContents = await Promise.all(userPaths.map(path => readFile(path)));
|
|
124
119
|
for (let i = 0; i < userPaths.length; i++) {
|
|
125
120
|
const content = userContents[i];
|
|
126
121
|
if (content) {
|
|
@@ -144,10 +139,10 @@ registerProvider<MCPServer>(mcpCapability.id, {
|
|
|
144
139
|
async function loadSystemPrompt(ctx: LoadContext): Promise<LoadResult<SystemPrompt>> {
|
|
145
140
|
const items: SystemPrompt[] = [];
|
|
146
141
|
|
|
147
|
-
const userPaths = USER_DIRS.map(
|
|
148
|
-
join(ctx.home, name, PATHS.userAgent.replace(`${PATHS.userBase}/`, ""), "SYSTEM.md"),
|
|
142
|
+
const userPaths = USER_DIRS.map(name =>
|
|
143
|
+
path.join(ctx.home, name, PATHS.userAgent.replace(`${PATHS.userBase}/`, ""), "SYSTEM.md"),
|
|
149
144
|
);
|
|
150
|
-
const userContents = await Promise.all(userPaths.map(
|
|
145
|
+
const userContents = await Promise.all(userPaths.map(p => readFile(p)));
|
|
151
146
|
for (let i = 0; i < userPaths.length; i++) {
|
|
152
147
|
const content = userContents[i];
|
|
153
148
|
if (content) {
|
|
@@ -165,18 +160,18 @@ async function loadSystemPrompt(ctx: LoadContext): Promise<LoadResult<SystemProm
|
|
|
165
160
|
let current = ctx.cwd;
|
|
166
161
|
while (true) {
|
|
167
162
|
ancestors.push(current);
|
|
168
|
-
const parent = dirname(current);
|
|
163
|
+
const parent = path.dirname(current);
|
|
169
164
|
if (parent === current) break;
|
|
170
165
|
current = parent;
|
|
171
166
|
}
|
|
172
167
|
|
|
173
168
|
for (const dir of ancestors) {
|
|
174
|
-
const configDirs = PROJECT_DIRS.map(
|
|
175
|
-
const entriesResults = await Promise.all(configDirs.map(
|
|
169
|
+
const configDirs = PROJECT_DIRS.map(name => path.join(dir, name));
|
|
170
|
+
const entriesResults = await Promise.all(configDirs.map(d => readDirEntries(d)));
|
|
176
171
|
const validConfigDir = configDirs.find((_, i) => entriesResults[i].length > 0);
|
|
177
172
|
if (!validConfigDir) continue;
|
|
178
173
|
|
|
179
|
-
const projectPath = join(validConfigDir, "SYSTEM.md");
|
|
174
|
+
const projectPath = path.join(validConfigDir, "SYSTEM.md");
|
|
180
175
|
const content = await readFile(projectPath);
|
|
181
176
|
if (content) {
|
|
182
177
|
items.push({
|
|
@@ -206,7 +201,7 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
206
201
|
const results = await Promise.all(
|
|
207
202
|
configDirs.map(({ dir, level }) =>
|
|
208
203
|
loadSkillsFromDir(ctx, {
|
|
209
|
-
dir: join(dir, "skills"),
|
|
204
|
+
dir: path.join(dir, "skills"),
|
|
210
205
|
providerId: PROVIDER_ID,
|
|
211
206
|
level,
|
|
212
207
|
requireDescription: true,
|
|
@@ -215,8 +210,8 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
215
210
|
);
|
|
216
211
|
|
|
217
212
|
return {
|
|
218
|
-
items: results.flatMap(
|
|
219
|
-
warnings: results.flatMap(
|
|
213
|
+
items: results.flatMap(r => r.items),
|
|
214
|
+
warnings: results.flatMap(r => r.warnings ?? []),
|
|
220
215
|
};
|
|
221
216
|
}
|
|
222
217
|
|
|
@@ -234,7 +229,7 @@ async function loadSlashCommands(ctx: LoadContext): Promise<LoadResult<SlashComm
|
|
|
234
229
|
const warnings: string[] = [];
|
|
235
230
|
|
|
236
231
|
for (const { dir, level } of await getConfigDirs(ctx)) {
|
|
237
|
-
const commandsDir = join(dir, "commands");
|
|
232
|
+
const commandsDir = path.join(dir, "commands");
|
|
238
233
|
const result = await loadFilesFromDir<SlashCommand>(ctx, commandsDir, PROVIDER_ID, level, {
|
|
239
234
|
extensions: ["md"],
|
|
240
235
|
transform: (name, content, path, source) => ({
|
|
@@ -266,7 +261,7 @@ async function loadRules(ctx: LoadContext): Promise<LoadResult<Rule>> {
|
|
|
266
261
|
const warnings: string[] = [];
|
|
267
262
|
|
|
268
263
|
for (const { dir, level } of await getConfigDirs(ctx)) {
|
|
269
|
-
const rulesDir = join(dir, "rules");
|
|
264
|
+
const rulesDir = path.join(dir, "rules");
|
|
270
265
|
const result = await loadFilesFromDir<Rule>(ctx, rulesDir, PROVIDER_ID, level, {
|
|
271
266
|
extensions: ["md", "mdc"],
|
|
272
267
|
transform: (name, content, path, source) => {
|
|
@@ -304,7 +299,7 @@ async function loadPrompts(ctx: LoadContext): Promise<LoadResult<Prompt>> {
|
|
|
304
299
|
const warnings: string[] = [];
|
|
305
300
|
|
|
306
301
|
for (const { dir, level } of await getConfigDirs(ctx)) {
|
|
307
|
-
const promptsDir = join(dir, "prompts");
|
|
302
|
+
const promptsDir = path.join(dir, "prompts");
|
|
308
303
|
const result = await loadFilesFromDir<Prompt>(ctx, promptsDir, PROVIDER_ID, level, {
|
|
309
304
|
extensions: ["md"],
|
|
310
305
|
transform: (name, content, path, source) => ({
|
|
@@ -336,15 +331,15 @@ async function loadExtensionModules(ctx: LoadContext): Promise<LoadResult<Extens
|
|
|
336
331
|
|
|
337
332
|
const resolveExtensionPath = (rawPath: string): string => {
|
|
338
333
|
if (rawPath.startsWith("~/")) {
|
|
339
|
-
return join(ctx.home, rawPath.slice(2));
|
|
334
|
+
return path.join(ctx.home, rawPath.slice(2));
|
|
340
335
|
}
|
|
341
336
|
if (rawPath.startsWith("~")) {
|
|
342
|
-
return join(ctx.home, rawPath.slice(1));
|
|
337
|
+
return path.join(ctx.home, rawPath.slice(1));
|
|
343
338
|
}
|
|
344
|
-
if (isAbsolute(rawPath)) {
|
|
339
|
+
if (path.isAbsolute(rawPath)) {
|
|
345
340
|
return rawPath;
|
|
346
341
|
}
|
|
347
|
-
return resolve(ctx.cwd, rawPath);
|
|
342
|
+
return path.resolve(ctx.cwd, rawPath);
|
|
348
343
|
};
|
|
349
344
|
|
|
350
345
|
const createExtensionModule = (extPath: string, level: "user" | "project"): ExtensionModule => ({
|
|
@@ -357,8 +352,8 @@ async function loadExtensionModules(ctx: LoadContext): Promise<LoadResult<Extens
|
|
|
357
352
|
const configDirs = await getConfigDirs(ctx);
|
|
358
353
|
|
|
359
354
|
const [discoveredResults, settingsResults] = await Promise.all([
|
|
360
|
-
Promise.all(configDirs.map(({ dir }) => discoverExtensionModulePaths(ctx, join(dir, "extensions")))),
|
|
361
|
-
Promise.all(configDirs.map(({ dir }) => readFile(join(dir, "settings.json")))),
|
|
355
|
+
Promise.all(configDirs.map(({ dir }) => discoverExtensionModulePaths(ctx, path.join(dir, "extensions")))),
|
|
356
|
+
Promise.all(configDirs.map(({ dir }) => readFile(path.join(dir, "settings.json")))),
|
|
362
357
|
]);
|
|
363
358
|
|
|
364
359
|
for (let i = 0; i < configDirs.length; i++) {
|
|
@@ -379,7 +374,7 @@ async function loadExtensionModules(ctx: LoadContext): Promise<LoadResult<Extens
|
|
|
379
374
|
const settingsContent = settingsResults[i];
|
|
380
375
|
if (!settingsContent) continue;
|
|
381
376
|
|
|
382
|
-
const settingsPath = join(dir, "settings.json");
|
|
377
|
+
const settingsPath = path.join(dir, "settings.json");
|
|
383
378
|
const settingsData = parseJSON<{ extensions?: unknown }>(settingsContent);
|
|
384
379
|
const extensions = settingsData?.extensions;
|
|
385
380
|
if (!Array.isArray(extensions)) continue;
|
|
@@ -424,7 +419,7 @@ async function loadExtensionModules(ctx: LoadContext): Promise<LoadResult<Extens
|
|
|
424
419
|
}
|
|
425
420
|
}
|
|
426
421
|
|
|
427
|
-
const dirDiscoveryResults = await Promise.all(dirDiscoveryPromises.map(
|
|
422
|
+
const dirDiscoveryResults = await Promise.all(dirDiscoveryPromises.map(d => d.promise));
|
|
428
423
|
for (let i = 0; i < dirDiscoveryPromises.length; i++) {
|
|
429
424
|
const { level } = dirDiscoveryPromises[i];
|
|
430
425
|
for (const extPath of dirDiscoveryResults[i]) {
|
|
@@ -449,7 +444,7 @@ async function loadExtensions(ctx: LoadContext): Promise<LoadResult<Extension>>
|
|
|
449
444
|
const warnings: string[] = [];
|
|
450
445
|
|
|
451
446
|
const configDirs = await getConfigDirs(ctx);
|
|
452
|
-
const entriesResults = await Promise.all(configDirs.map(({ dir }) => readDirEntries(join(dir, "extensions"))));
|
|
447
|
+
const entriesResults = await Promise.all(configDirs.map(({ dir }) => readDirEntries(path.join(dir, "extensions"))));
|
|
453
448
|
|
|
454
449
|
const manifestCandidates: Array<{
|
|
455
450
|
extDir: string;
|
|
@@ -461,16 +456,16 @@ async function loadExtensions(ctx: LoadContext): Promise<LoadResult<Extension>>
|
|
|
461
456
|
for (let i = 0; i < configDirs.length; i++) {
|
|
462
457
|
const { dir, level } = configDirs[i];
|
|
463
458
|
const entries = entriesResults[i];
|
|
464
|
-
const extensionsDir = join(dir, "extensions");
|
|
459
|
+
const extensionsDir = path.join(dir, "extensions");
|
|
465
460
|
|
|
466
461
|
for (const entry of entries) {
|
|
467
462
|
if (entry.name.startsWith(".")) continue;
|
|
468
463
|
if (!entry.isDirectory()) continue;
|
|
469
464
|
|
|
470
|
-
const extDir = join(extensionsDir, entry.name);
|
|
465
|
+
const extDir = path.join(extensionsDir, entry.name);
|
|
471
466
|
manifestCandidates.push({
|
|
472
467
|
extDir,
|
|
473
|
-
manifestPath: join(extDir, "gemini-extension.json"),
|
|
468
|
+
manifestPath: path.join(extDir, "gemini-extension.json"),
|
|
474
469
|
entryName: entry.name,
|
|
475
470
|
level,
|
|
476
471
|
});
|
|
@@ -516,7 +511,7 @@ async function loadInstructions(ctx: LoadContext): Promise<LoadResult<Instructio
|
|
|
516
511
|
const warnings: string[] = [];
|
|
517
512
|
|
|
518
513
|
for (const { dir, level } of await getConfigDirs(ctx)) {
|
|
519
|
-
const instructionsDir = join(dir, "instructions");
|
|
514
|
+
const instructionsDir = path.join(dir, "instructions");
|
|
520
515
|
const result = await loadFilesFromDir<Instruction>(ctx, instructionsDir, PROVIDER_ID, level, {
|
|
521
516
|
extensions: ["md"],
|
|
522
517
|
transform: (name, content, path, source) => {
|
|
@@ -561,7 +556,7 @@ async function loadHooks(ctx: LoadContext): Promise<LoadResult<Hook>> {
|
|
|
561
556
|
for (const { dir, level } of configDirs) {
|
|
562
557
|
for (const hookType of hookTypes) {
|
|
563
558
|
typeDirRequests.push({
|
|
564
|
-
typeDir: join(dir, "hooks", hookType),
|
|
559
|
+
typeDir: path.join(dir, "hooks", hookType),
|
|
565
560
|
hookType,
|
|
566
561
|
level,
|
|
567
562
|
});
|
|
@@ -578,17 +573,17 @@ async function loadHooks(ctx: LoadContext): Promise<LoadResult<Hook>> {
|
|
|
578
573
|
if (entry.name.startsWith(".")) continue;
|
|
579
574
|
if (!entry.isFile()) continue;
|
|
580
575
|
|
|
581
|
-
const
|
|
576
|
+
const hookPath = path.join(typeDir, entry.name);
|
|
582
577
|
const baseName = entry.name.includes(".") ? entry.name.slice(0, entry.name.lastIndexOf(".")) : entry.name;
|
|
583
578
|
const tool = baseName === "*" ? "*" : baseName;
|
|
584
579
|
|
|
585
580
|
items.push({
|
|
586
581
|
name: entry.name,
|
|
587
|
-
path,
|
|
582
|
+
path: hookPath,
|
|
588
583
|
type: hookType,
|
|
589
584
|
tool,
|
|
590
585
|
level,
|
|
591
|
-
_source: createSourceMeta(PROVIDER_ID,
|
|
586
|
+
_source: createSourceMeta(PROVIDER_ID, hookPath, level),
|
|
592
587
|
});
|
|
593
588
|
}
|
|
594
589
|
}
|
|
@@ -610,7 +605,7 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
610
605
|
const warnings: string[] = [];
|
|
611
606
|
|
|
612
607
|
const configDirs = await getConfigDirs(ctx);
|
|
613
|
-
const entriesResults = await Promise.all(configDirs.map(({ dir }) => readDirEntries(join(dir, "tools"))));
|
|
608
|
+
const entriesResults = await Promise.all(configDirs.map(({ dir }) => readDirEntries(path.join(dir, "tools"))));
|
|
614
609
|
|
|
615
610
|
const fileLoadPromises: Array<Promise<{ items: CustomTool[]; warnings?: string[] }>> = [];
|
|
616
611
|
const subDirCandidates: Array<{
|
|
@@ -624,7 +619,7 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
624
619
|
const toolEntries = entriesResults[i];
|
|
625
620
|
if (toolEntries.length === 0) continue;
|
|
626
621
|
|
|
627
|
-
const toolsDir = join(dir, "tools");
|
|
622
|
+
const toolsDir = path.join(dir, "tools");
|
|
628
623
|
|
|
629
624
|
fileLoadPromises.push(
|
|
630
625
|
loadFilesFromDir<CustomTool>(ctx, toolsDir, PROVIDER_ID, level, {
|
|
@@ -657,7 +652,7 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
657
652
|
if (!entry.isDirectory()) continue;
|
|
658
653
|
|
|
659
654
|
subDirCandidates.push({
|
|
660
|
-
indexPath: join(toolsDir, entry.name, "index.ts"),
|
|
655
|
+
indexPath: path.join(toolsDir, entry.name, "index.ts"),
|
|
661
656
|
entryName: entry.name,
|
|
662
657
|
level,
|
|
663
658
|
});
|
|
@@ -705,7 +700,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
705
700
|
const warnings: string[] = [];
|
|
706
701
|
|
|
707
702
|
for (const { dir, level } of await getConfigDirs(ctx)) {
|
|
708
|
-
const settingsPath = join(dir, "settings.json");
|
|
703
|
+
const settingsPath = path.join(dir, "settings.json");
|
|
709
704
|
const content = await readFile(settingsPath);
|
|
710
705
|
if (!content) continue;
|
|
711
706
|
|
|
@@ -739,10 +734,10 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
739
734
|
const items: ContextFile[] = [];
|
|
740
735
|
const warnings: string[] = [];
|
|
741
736
|
|
|
742
|
-
const userPaths = USER_DIRS.map(
|
|
743
|
-
join(ctx.home, name, PATHS.userAgent.replace(`${PATHS.userBase}/`, ""), "AGENTS.md"),
|
|
737
|
+
const userPaths = USER_DIRS.map(name =>
|
|
738
|
+
path.join(ctx.home, name, PATHS.userAgent.replace(`${PATHS.userBase}/`, ""), "AGENTS.md"),
|
|
744
739
|
);
|
|
745
|
-
const userContents = await Promise.all(userPaths.map(
|
|
740
|
+
const userContents = await Promise.all(userPaths.map(p => readFile(p)));
|
|
746
741
|
for (let i = 0; i < userPaths.length; i++) {
|
|
747
742
|
const content = userContents[i];
|
|
748
743
|
if (content) {
|
|
@@ -761,19 +756,19 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
761
756
|
let depth = 0;
|
|
762
757
|
while (true) {
|
|
763
758
|
ancestors.push({ dir: current, depth });
|
|
764
|
-
const parent = dirname(current);
|
|
759
|
+
const parent = path.dirname(current);
|
|
765
760
|
if (parent === current) break;
|
|
766
761
|
current = parent;
|
|
767
762
|
depth++;
|
|
768
763
|
}
|
|
769
764
|
|
|
770
765
|
for (const { dir, depth: ancestorDepth } of ancestors) {
|
|
771
|
-
const configDirs = PROJECT_DIRS.map(
|
|
772
|
-
const entriesResults = await Promise.all(configDirs.map(
|
|
766
|
+
const configDirs = PROJECT_DIRS.map(name => path.join(dir, name));
|
|
767
|
+
const entriesResults = await Promise.all(configDirs.map(d => readDirEntries(d)));
|
|
773
768
|
const validConfigDir = configDirs.find((_, i) => entriesResults[i].length > 0);
|
|
774
769
|
if (!validConfigDir) continue;
|
|
775
770
|
|
|
776
|
-
const projectPath = join(validConfigDir, "AGENTS.md");
|
|
771
|
+
const projectPath = path.join(validConfigDir, "AGENTS.md");
|
|
777
772
|
const content = await readFile(projectPath);
|
|
778
773
|
if (content) {
|
|
779
774
|
items.push({
|
package/src/discovery/claude.ts
CHANGED
|
@@ -4,20 +4,19 @@
|
|
|
4
4
|
* Loads configuration from .claude directories.
|
|
5
5
|
* Priority: 80 (tool-specific, below builtin but above shared standards)
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { type
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { type
|
|
14
|
-
import { type
|
|
15
|
-
import { type
|
|
16
|
-
import { type
|
|
17
|
-
import { type
|
|
18
|
-
import { type
|
|
19
|
-
import {
|
|
20
|
-
import type { LoadContext, LoadResult } from "@oh-my-pi/pi-coding-agent/capability/types";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import { registerProvider } from "../capability";
|
|
9
|
+
import { type ContextFile, contextFileCapability } from "../capability/context-file";
|
|
10
|
+
import { type ExtensionModule, extensionModuleCapability } from "../capability/extension-module";
|
|
11
|
+
import { readFile } from "../capability/fs";
|
|
12
|
+
import { type Hook, hookCapability } from "../capability/hook";
|
|
13
|
+
import { type MCPServer, mcpCapability } from "../capability/mcp";
|
|
14
|
+
import { type Settings, settingsCapability } from "../capability/settings";
|
|
15
|
+
import { type Skill, skillCapability } from "../capability/skill";
|
|
16
|
+
import { type SlashCommand, slashCommandCapability } from "../capability/slash-command";
|
|
17
|
+
import { type SystemPrompt, systemPromptCapability } from "../capability/system-prompt";
|
|
18
|
+
import { type CustomTool, toolCapability } from "../capability/tool";
|
|
19
|
+
import type { LoadContext, LoadResult } from "../capability/types";
|
|
21
20
|
import {
|
|
22
21
|
calculateDepth,
|
|
23
22
|
createSourceMeta,
|
|
@@ -38,14 +37,14 @@ const CONFIG_DIR = ".claude";
|
|
|
38
37
|
* Get user-level .claude path.
|
|
39
38
|
*/
|
|
40
39
|
function getUserClaude(ctx: LoadContext): string {
|
|
41
|
-
return join(ctx.home, CONFIG_DIR);
|
|
40
|
+
return path.join(ctx.home, CONFIG_DIR);
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
/**
|
|
45
44
|
* Get project-level .claude path (cwd only).
|
|
46
45
|
*/
|
|
47
46
|
function getProjectClaude(ctx: LoadContext): string {
|
|
48
|
-
return join(ctx.cwd, CONFIG_DIR);
|
|
47
|
+
return path.join(ctx.cwd, CONFIG_DIR);
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
// =============================================================================
|
|
@@ -57,12 +56,12 @@ async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>>
|
|
|
57
56
|
const warnings: string[] = [];
|
|
58
57
|
|
|
59
58
|
const userBase = getUserClaude(ctx);
|
|
60
|
-
const userClaudeJson = join(ctx.home, ".claude.json");
|
|
61
|
-
const userMcpJson = join(userBase, "mcp.json");
|
|
59
|
+
const userClaudeJson = path.join(ctx.home, ".claude.json");
|
|
60
|
+
const userMcpJson = path.join(userBase, "mcp.json");
|
|
62
61
|
|
|
63
|
-
const projectBase = join(ctx.cwd, CONFIG_DIR);
|
|
64
|
-
const projectMcpJson = join(projectBase, ".mcp.json");
|
|
65
|
-
const projectMcpJsonAlt = join(projectBase, "mcp.json");
|
|
62
|
+
const projectBase = path.join(ctx.cwd, CONFIG_DIR);
|
|
63
|
+
const projectMcpJson = path.join(projectBase, ".mcp.json");
|
|
64
|
+
const projectMcpJsonAlt = path.join(projectBase, "mcp.json");
|
|
66
65
|
|
|
67
66
|
const userPaths = [
|
|
68
67
|
{ path: userClaudeJson, level: "user" as const },
|
|
@@ -126,7 +125,7 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
126
125
|
const warnings: string[] = [];
|
|
127
126
|
|
|
128
127
|
const userBase = getUserClaude(ctx);
|
|
129
|
-
const userClaudeMd = join(userBase, "CLAUDE.md");
|
|
128
|
+
const userClaudeMd = path.join(userBase, "CLAUDE.md");
|
|
130
129
|
|
|
131
130
|
const userContent = await readFile(userClaudeMd);
|
|
132
131
|
if (userContent !== null) {
|
|
@@ -139,10 +138,10 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
const projectBase = getProjectClaude(ctx);
|
|
142
|
-
const projectClaudeMd = join(projectBase, "CLAUDE.md");
|
|
141
|
+
const projectClaudeMd = path.join(projectBase, "CLAUDE.md");
|
|
143
142
|
const projectContent = await readFile(projectClaudeMd);
|
|
144
143
|
if (projectContent !== null) {
|
|
145
|
-
const depth = calculateDepth(ctx.cwd, projectBase, sep);
|
|
144
|
+
const depth = calculateDepth(ctx.cwd, projectBase, path.sep);
|
|
146
145
|
items.push({
|
|
147
146
|
path: projectClaudeMd,
|
|
148
147
|
content: projectContent,
|
|
@@ -160,8 +159,8 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
160
159
|
// =============================================================================
|
|
161
160
|
|
|
162
161
|
async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
163
|
-
const userSkillsDir = join(getUserClaude(ctx), "skills");
|
|
164
|
-
const projectSkillsDir = join(getProjectClaude(ctx), "skills");
|
|
162
|
+
const userSkillsDir = path.join(getUserClaude(ctx), "skills");
|
|
163
|
+
const projectSkillsDir = path.join(getProjectClaude(ctx), "skills");
|
|
165
164
|
|
|
166
165
|
const results = await Promise.all([
|
|
167
166
|
loadSkillsFromDir(ctx, { dir: userSkillsDir, providerId: PROVIDER_ID, level: "user" }),
|
|
@@ -169,8 +168,8 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
169
168
|
]);
|
|
170
169
|
|
|
171
170
|
return {
|
|
172
|
-
items: results.flatMap(
|
|
173
|
-
warnings: results.flatMap(
|
|
171
|
+
items: results.flatMap(r => r.items),
|
|
172
|
+
warnings: results.flatMap(r => r.warnings ?? []),
|
|
174
173
|
};
|
|
175
174
|
}
|
|
176
175
|
|
|
@@ -183,8 +182,8 @@ async function loadExtensionModules(ctx: LoadContext): Promise<LoadResult<Extens
|
|
|
183
182
|
const warnings: string[] = [];
|
|
184
183
|
|
|
185
184
|
const userBase = getUserClaude(ctx);
|
|
186
|
-
const userExtensionsDir = join(userBase, "extensions");
|
|
187
|
-
const projectExtensionsDir = join(ctx.cwd, CONFIG_DIR, "extensions");
|
|
185
|
+
const userExtensionsDir = path.join(userBase, "extensions");
|
|
186
|
+
const projectExtensionsDir = path.join(ctx.cwd, CONFIG_DIR, "extensions");
|
|
188
187
|
|
|
189
188
|
const dirsToDiscover: { dir: string; level: "user" | "project" }[] = [
|
|
190
189
|
{ dir: userExtensionsDir, level: "user" },
|
|
@@ -194,7 +193,7 @@ async function loadExtensionModules(ctx: LoadContext): Promise<LoadResult<Extens
|
|
|
194
193
|
const pathsByLevel = await Promise.all(
|
|
195
194
|
dirsToDiscover.map(async ({ dir, level }) => {
|
|
196
195
|
const paths = await discoverExtensionModulePaths(ctx, dir);
|
|
197
|
-
return paths.map(
|
|
196
|
+
return paths.map(extPath => ({ extPath, level }));
|
|
198
197
|
}),
|
|
199
198
|
);
|
|
200
199
|
|
|
@@ -221,7 +220,7 @@ async function loadSlashCommands(ctx: LoadContext): Promise<LoadResult<SlashComm
|
|
|
221
220
|
const warnings: string[] = [];
|
|
222
221
|
|
|
223
222
|
const userBase = getUserClaude(ctx);
|
|
224
|
-
const userCommandsDir = join(userBase, "commands");
|
|
223
|
+
const userCommandsDir = path.join(userBase, "commands");
|
|
225
224
|
|
|
226
225
|
const userResult = await loadFilesFromDir<SlashCommand>(ctx, userCommandsDir, PROVIDER_ID, "user", {
|
|
227
226
|
extensions: ["md"],
|
|
@@ -240,7 +239,7 @@ async function loadSlashCommands(ctx: LoadContext): Promise<LoadResult<SlashComm
|
|
|
240
239
|
items.push(...userResult.items);
|
|
241
240
|
if (userResult.warnings) warnings.push(...userResult.warnings);
|
|
242
241
|
|
|
243
|
-
const projectCommandsDir = join(ctx.cwd, CONFIG_DIR, "commands");
|
|
242
|
+
const projectCommandsDir = path.join(ctx.cwd, CONFIG_DIR, "commands");
|
|
244
243
|
|
|
245
244
|
const projectResult = await loadFilesFromDir<SlashCommand>(ctx, projectCommandsDir, PROVIDER_ID, "project", {
|
|
246
245
|
extensions: ["md"],
|
|
@@ -271,18 +270,18 @@ async function loadHooks(ctx: LoadContext): Promise<LoadResult<Hook>> {
|
|
|
271
270
|
const warnings: string[] = [];
|
|
272
271
|
|
|
273
272
|
const userBase = getUserClaude(ctx);
|
|
274
|
-
const userHooksDir = join(userBase, "hooks");
|
|
273
|
+
const userHooksDir = path.join(userBase, "hooks");
|
|
275
274
|
const projectBase = getProjectClaude(ctx);
|
|
276
|
-
const projectHooksDir = join(projectBase, "hooks");
|
|
275
|
+
const projectHooksDir = path.join(projectBase, "hooks");
|
|
277
276
|
|
|
278
277
|
const hookTypes = ["pre", "post"] as const;
|
|
279
278
|
|
|
280
279
|
const loadTasks: { dir: string; hookType: "pre" | "post"; level: "user" | "project" }[] = [];
|
|
281
280
|
for (const hookType of hookTypes) {
|
|
282
|
-
loadTasks.push({ dir: join(userHooksDir, hookType), hookType, level: "user" });
|
|
281
|
+
loadTasks.push({ dir: path.join(userHooksDir, hookType), hookType, level: "user" });
|
|
283
282
|
}
|
|
284
283
|
for (const hookType of hookTypes) {
|
|
285
|
-
loadTasks.push({ dir: join(projectHooksDir, hookType), hookType, level: "project" });
|
|
284
|
+
loadTasks.push({ dir: path.join(projectHooksDir, hookType), hookType, level: "project" });
|
|
286
285
|
}
|
|
287
286
|
|
|
288
287
|
const results = await Promise.all(
|
|
@@ -320,7 +319,7 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
320
319
|
const warnings: string[] = [];
|
|
321
320
|
|
|
322
321
|
const userBase = getUserClaude(ctx);
|
|
323
|
-
const userToolsDir = join(userBase, "tools");
|
|
322
|
+
const userToolsDir = path.join(userBase, "tools");
|
|
324
323
|
|
|
325
324
|
const userResult = await loadFilesFromDir<CustomTool>(ctx, userToolsDir, PROVIDER_ID, "user", {
|
|
326
325
|
transform: (name, _content, path, source) => {
|
|
@@ -339,7 +338,7 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
339
338
|
if (userResult.warnings) warnings.push(...userResult.warnings);
|
|
340
339
|
|
|
341
340
|
const projectBase = getProjectClaude(ctx);
|
|
342
|
-
const projectToolsDir = join(projectBase, "tools");
|
|
341
|
+
const projectToolsDir = path.join(projectBase, "tools");
|
|
343
342
|
|
|
344
343
|
const projectResult = await loadFilesFromDir<CustomTool>(ctx, projectToolsDir, PROVIDER_ID, "project", {
|
|
345
344
|
transform: (name, _content, path, source) => {
|
|
@@ -369,7 +368,7 @@ async function loadSystemPrompts(ctx: LoadContext): Promise<LoadResult<SystemPro
|
|
|
369
368
|
const warnings: string[] = [];
|
|
370
369
|
|
|
371
370
|
const userBase = getUserClaude(ctx);
|
|
372
|
-
const userSystemMd = join(userBase, "SYSTEM.md");
|
|
371
|
+
const userSystemMd = path.join(userBase, "SYSTEM.md");
|
|
373
372
|
|
|
374
373
|
const content = await readFile(userSystemMd);
|
|
375
374
|
if (content !== null) {
|
|
@@ -393,7 +392,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
393
392
|
const warnings: string[] = [];
|
|
394
393
|
|
|
395
394
|
const userBase = getUserClaude(ctx);
|
|
396
|
-
const userSettingsJson = join(userBase, "settings.json");
|
|
395
|
+
const userSettingsJson = path.join(userBase, "settings.json");
|
|
397
396
|
|
|
398
397
|
const userContent = await readFile(userSettingsJson);
|
|
399
398
|
if (userContent) {
|
|
@@ -411,7 +410,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
411
410
|
}
|
|
412
411
|
|
|
413
412
|
const projectBase = getProjectClaude(ctx);
|
|
414
|
-
const projectSettingsJson = join(projectBase, "settings.json");
|
|
413
|
+
const projectSettingsJson = path.join(projectBase, "settings.json");
|
|
415
414
|
const projectContent = await readFile(projectSettingsJson);
|
|
416
415
|
if (projectContent) {
|
|
417
416
|
const data = parseJSON<Record<string, unknown>>(projectContent);
|
package/src/discovery/cline.ts
CHANGED
|
@@ -4,14 +4,13 @@
|
|
|
4
4
|
* Loads rules from .clinerules (can be single file or directory with *.md files).
|
|
5
5
|
* Project-only (no user-level config).
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import { parseFrontmatter } from "@oh-my-pi/pi-coding-agent/utils/frontmatter";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import { registerProvider } from "../capability";
|
|
9
|
+
import { readDirEntries, readFile } from "../capability/fs";
|
|
10
|
+
import type { Rule } from "../capability/rule";
|
|
11
|
+
import { ruleCapability } from "../capability/rule";
|
|
12
|
+
import type { LoadContext, LoadResult } from "../capability/types";
|
|
13
|
+
import { parseFrontmatter } from "../utils/frontmatter";
|
|
15
14
|
import { createSourceMeta, loadFilesFromDir } from "./helpers";
|
|
16
15
|
|
|
17
16
|
const PROVIDER_ID = "cline";
|
|
@@ -19,18 +18,18 @@ const DISPLAY_NAME = "Cline";
|
|
|
19
18
|
const PRIORITY = 40;
|
|
20
19
|
|
|
21
20
|
async function findClinerules(startDir: string): Promise<{ path: string; isDir: boolean } | null> {
|
|
22
|
-
let current = resolve(startDir);
|
|
21
|
+
let current = path.resolve(startDir);
|
|
23
22
|
|
|
24
23
|
while (true) {
|
|
25
24
|
const entries = await readDirEntries(current);
|
|
26
|
-
const entry = entries.find(
|
|
25
|
+
const entry = entries.find(e => e.name === ".clinerules");
|
|
27
26
|
if (entry) {
|
|
28
27
|
return {
|
|
29
|
-
path: resolve(current, ".clinerules"),
|
|
28
|
+
path: path.resolve(current, ".clinerules"),
|
|
30
29
|
isDir: entry.isDirectory(),
|
|
31
30
|
};
|
|
32
31
|
}
|
|
33
|
-
const parent = dirname(current);
|
|
32
|
+
const parent = path.dirname(current);
|
|
34
33
|
if (parent === current) return null;
|
|
35
34
|
current = parent;
|
|
36
35
|
}
|