@oh-my-pi/pi-coding-agent 13.1.2 → 13.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/package.json +7 -7
- package/scripts/format-prompts.ts +33 -14
- package/src/async/job-manager.ts +43 -1
- package/src/capability/index.ts +1 -2
- package/src/capability/tool.ts +1 -1
- package/src/cli/args.ts +1 -2
- package/src/cli/config-cli.ts +1 -1
- package/src/cli/file-processor.ts +1 -2
- package/src/cli/grep-cli.ts +1 -1
- package/src/cli/jupyter-cli.ts +1 -1
- package/src/cli/plugin-cli.ts +1 -1
- package/src/cli/setup-cli.ts +1 -1
- package/src/cli/shell-cli.ts +1 -1
- package/src/cli/ssh-cli.ts +1 -1
- package/src/cli/stats-cli.ts +1 -2
- package/src/cli/update-cli.ts +1 -2
- package/src/cli/web-search-cli.ts +1 -1
- package/src/cli.ts +1 -1
- package/src/commands/launch.ts +2 -1
- package/src/commit/agentic/agent.ts +2 -1
- package/src/commit/agentic/index.ts +1 -2
- package/src/commit/agentic/prompts/system.md +3 -3
- package/src/commit/agentic/tools/propose-changelog.ts +30 -19
- package/src/commit/changelog/generate.ts +16 -6
- package/src/commit/changelog/index.ts +2 -1
- package/src/commit/pipeline.ts +1 -2
- package/src/commit/prompts/reduce-system.md +1 -1
- package/src/commit/types.ts +10 -1
- package/src/config/keybindings.ts +1 -2
- package/src/config/model-registry.ts +1 -1
- package/src/config/prompt-templates.ts +14 -2
- package/src/config/settings-schema.ts +10 -0
- package/src/config/settings.ts +25 -2
- package/src/config.ts +1 -2
- package/src/debug/index.ts +1 -1
- package/src/debug/report-bundle.ts +1 -2
- package/src/debug/system-info.ts +1 -2
- package/src/discovery/agents.ts +2 -2
- package/src/discovery/builtin.ts +24 -14
- package/src/discovery/claude-plugins.ts +3 -2
- package/src/discovery/claude.ts +9 -9
- package/src/discovery/codex.ts +3 -3
- package/src/discovery/cursor.ts +5 -4
- package/src/discovery/gemini.ts +5 -5
- package/src/discovery/helpers.ts +47 -69
- package/src/discovery/mcp-json.ts +3 -3
- package/src/discovery/opencode.ts +7 -8
- package/src/discovery/ssh.ts +3 -3
- package/src/discovery/vscode.ts +3 -2
- package/src/discovery/windsurf.ts +3 -2
- package/src/exa/company.ts +1 -1
- package/src/exa/factory.ts +1 -6
- package/src/exa/linkedin.ts +1 -1
- package/src/exa/mcp-client.ts +19 -8
- package/src/exa/search.ts +2 -2
- package/src/exa/types.ts +3 -3
- package/src/exec/bash-executor.ts +2 -1
- package/src/exec/non-interactive-env.ts +43 -0
- package/src/export/custom-share.ts +1 -1
- package/src/export/html/index.ts +1 -2
- package/src/extensibility/custom-commands/loader.ts +1 -2
- package/src/extensibility/plugins/installer.ts +1 -2
- package/src/extensibility/plugins/loader.ts +1 -2
- package/src/extensibility/plugins/manager.ts +3 -2
- package/src/extensibility/skills.ts +59 -115
- package/src/index.ts +1 -3
- package/src/internal-urls/docs-index.generated.ts +1 -1
- package/src/ipy/executor.ts +1 -2
- package/src/ipy/gateway-coordinator.ts +1 -2
- package/src/ipy/modules.ts +1 -1
- package/src/ipy/runtime.ts +1 -3
- package/src/main.ts +1 -2
- package/src/mcp/config.ts +1 -1
- package/src/mcp/transports/stdio.ts +1 -2
- package/src/memories/index.ts +1 -2
- package/src/modes/components/diff.ts +49 -19
- package/src/modes/components/extensions/extension-dashboard.ts +1 -1
- package/src/modes/components/extensions/inspector-panel.ts +8 -2
- package/src/modes/components/footer.ts +1 -2
- package/src/modes/components/status-line/segments.ts +1 -2
- package/src/modes/components/tool-execution.ts +3 -10
- package/src/modes/components/welcome.ts +1 -1
- package/src/modes/controllers/command-controller.ts +1 -2
- package/src/modes/controllers/mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/controllers/ssh-command-controller.ts +1 -1
- package/src/modes/interactive-mode.ts +2 -3
- package/src/modes/shared.ts +1 -2
- package/src/modes/theme/theme.ts +1 -2
- package/src/patch/index.ts +1 -25
- package/src/prompts/agents/designer.md +7 -10
- package/src/prompts/agents/explore.md +15 -23
- package/src/prompts/agents/init.md +23 -23
- package/src/prompts/agents/plan.md +14 -77
- package/src/prompts/agents/reviewer.md +6 -5
- package/src/prompts/agents/task.md +13 -11
- package/src/prompts/compaction/branch-summary.md +3 -3
- package/src/prompts/compaction/compaction-short-summary.md +7 -7
- package/src/prompts/compaction/compaction-summary-context.md +1 -1
- package/src/prompts/compaction/compaction-summary.md +5 -5
- package/src/prompts/compaction/compaction-turn-prefix.md +3 -3
- package/src/prompts/compaction/compaction-update-summary.md +11 -11
- package/src/prompts/memories/consolidation.md +5 -5
- package/src/prompts/memories/read-path.md +6 -6
- package/src/prompts/memories/stage_one_input.md +1 -1
- package/src/prompts/memories/stage_one_system.md +5 -5
- package/src/prompts/review-request.md +4 -4
- package/src/prompts/system/agent-creation-architect.md +17 -17
- package/src/prompts/system/agent-creation-user.md +2 -2
- package/src/prompts/system/custom-system-prompt.md +4 -4
- package/src/prompts/system/plan-mode-active.md +20 -20
- package/src/prompts/system/plan-mode-approved.md +7 -7
- package/src/prompts/system/plan-mode-reference.md +2 -2
- package/src/prompts/system/plan-mode-subagent.md +8 -8
- package/src/prompts/system/subagent-submit-reminder.md +5 -5
- package/src/prompts/system/subagent-system-prompt.md +29 -22
- package/src/prompts/system/subagent-user-prompt.md +7 -3
- package/src/prompts/system/summarization-system.md +1 -1
- package/src/prompts/system/system-prompt.md +201 -226
- package/src/prompts/system/title-system.md +2 -2
- package/src/prompts/system/ttsr-interrupt.md +1 -1
- package/src/prompts/system/web-search.md +16 -16
- package/src/prompts/tools/ask.md +1 -3
- package/src/prompts/tools/await.md +2 -4
- package/src/prompts/tools/bash.md +5 -7
- package/src/prompts/tools/browser.md +4 -6
- package/src/prompts/tools/calculator.md +1 -3
- package/src/prompts/tools/cancel-job.md +2 -4
- package/src/prompts/tools/exit-plan-mode.md +7 -7
- package/src/prompts/tools/fetch.md +0 -2
- package/src/prompts/tools/find.md +3 -5
- package/src/prompts/tools/gemini-image.md +6 -22
- package/src/prompts/tools/grep.md +4 -6
- package/src/prompts/tools/hashline.md +12 -15
- package/src/prompts/tools/lsp.md +1 -3
- package/src/prompts/tools/patch.md +7 -9
- package/src/prompts/tools/python.md +10 -14
- package/src/prompts/tools/read.md +0 -2
- package/src/prompts/tools/replace.md +5 -7
- package/src/prompts/tools/ssh.md +3 -5
- package/src/prompts/tools/task.md +6 -8
- package/src/prompts/tools/todo-write.md +7 -9
- package/src/prompts/tools/web-search.md +3 -5
- package/src/prompts/tools/write.md +3 -5
- package/src/sdk.ts +1 -2
- package/src/session/agent-session.ts +10 -26
- package/src/session/agent-storage.ts +1 -2
- package/src/session/history-storage.ts +1 -2
- package/src/session/session-manager.ts +10 -2
- package/src/ssh/connection-manager.ts +11 -2
- package/src/ssh/sshfs-mount.ts +7 -1
- package/src/system-prompt.ts +25 -103
- package/src/task/agents.ts +1 -1
- package/src/task/worktree.ts +1 -2
- package/src/tools/ask.ts +0 -1
- package/src/tools/await-tool.ts +6 -3
- package/src/tools/bash-interactive.ts +2 -45
- package/src/tools/bash.ts +5 -5
- package/src/tools/browser.ts +1 -2
- package/src/tools/gemini-image.ts +8 -28
- package/src/tools/json-tree.ts +2 -1
- package/src/tools/python.ts +1 -1
- package/src/tools/read.ts +1 -2
- package/src/tools/render-utils.ts +5 -2
- package/src/tools/todo-write.ts +11 -9
- package/src/utils/tools-manager.ts +1 -2
- package/src/web/scrapers/artifacthub.ts +2 -1
- package/src/web/scrapers/aur.ts +2 -1
- package/src/web/scrapers/biorxiv.ts +2 -1
- package/src/web/scrapers/bluesky.ts +2 -1
- package/src/web/scrapers/chocolatey.ts +2 -1
- package/src/web/scrapers/cisa-kev.ts +2 -1
- package/src/web/scrapers/clojars.ts +2 -1
- package/src/web/scrapers/coingecko.ts +2 -1
- package/src/web/scrapers/crates-io.ts +2 -1
- package/src/web/scrapers/crossref.ts +2 -1
- package/src/web/scrapers/discogs.ts +3 -1
- package/src/web/scrapers/discourse.ts +2 -1
- package/src/web/scrapers/dockerhub.ts +2 -1
- package/src/web/scrapers/fdroid.ts +2 -1
- package/src/web/scrapers/firefox-addons.ts +2 -1
- package/src/web/scrapers/flathub.ts +2 -1
- package/src/web/scrapers/gitlab.ts +1 -1
- package/src/web/scrapers/go-pkg.ts +2 -1
- package/src/web/scrapers/hackage.ts +2 -1
- package/src/web/scrapers/hackernews.ts +2 -1
- package/src/web/scrapers/hex.ts +2 -1
- package/src/web/scrapers/huggingface.ts +2 -1
- package/src/web/scrapers/jetbrains-marketplace.ts +2 -1
- package/src/web/scrapers/lemmy.ts +2 -1
- package/src/web/scrapers/lobsters.ts +2 -1
- package/src/web/scrapers/mastodon.ts +2 -1
- package/src/web/scrapers/maven.ts +2 -1
- package/src/web/scrapers/mdn.ts +2 -1
- package/src/web/scrapers/metacpan.ts +2 -1
- package/src/web/scrapers/musicbrainz.ts +3 -1
- package/src/web/scrapers/npm.ts +2 -1
- package/src/web/scrapers/nuget.ts +2 -1
- package/src/web/scrapers/nvd.ts +2 -1
- package/src/web/scrapers/ollama.ts +2 -1
- package/src/web/scrapers/open-vsx.ts +2 -1
- package/src/web/scrapers/opencorporates.ts +2 -1
- package/src/web/scrapers/openlibrary.ts +2 -1
- package/src/web/scrapers/orcid.ts +3 -1
- package/src/web/scrapers/osv.ts +2 -1
- package/src/web/scrapers/packagist.ts +2 -1
- package/src/web/scrapers/pub-dev.ts +2 -1
- package/src/web/scrapers/pubmed.ts +2 -1
- package/src/web/scrapers/pypi.ts +2 -1
- package/src/web/scrapers/rawg.ts +2 -8
- package/src/web/scrapers/reddit.ts +2 -1
- package/src/web/scrapers/repology.ts +2 -1
- package/src/web/scrapers/rfc.ts +2 -1
- package/src/web/scrapers/rubygems.ts +2 -1
- package/src/web/scrapers/searchcode.ts +2 -1
- package/src/web/scrapers/sec-edgar.ts +2 -1
- package/src/web/scrapers/semantic-scholar.ts +2 -1
- package/src/web/scrapers/snapcraft.ts +2 -1
- package/src/web/scrapers/sourcegraph.ts +2 -1
- package/src/web/scrapers/spdx.ts +2 -1
- package/src/web/scrapers/stackoverflow.ts +2 -1
- package/src/web/scrapers/terraform.ts +2 -1
- package/src/web/scrapers/types.ts +0 -11
- package/src/web/scrapers/vimeo.ts +2 -1
- package/src/web/scrapers/vscode-marketplace.ts +2 -1
- package/src/web/scrapers/w3c.ts +2 -1
- package/src/web/scrapers/wikidata.ts +2 -1
- package/src/web/search/index.ts +10 -14
- package/src/web/search/provider.ts +2 -2
- package/src/web/search/providers/codex.ts +1 -2
- package/src/web/search/providers/exa.ts +1 -6
- package/src/web/search/providers/gemini.ts +1 -1
- package/src/web/search/providers/perplexity.ts +1 -2
- package/src/web/search/providers/utils.ts +1 -1
|
@@ -10,7 +10,7 @@ Determine:
|
|
|
10
10
|
4. CHANGELOG: Metadata for user-visible changes
|
|
11
11
|
</instructions>
|
|
12
12
|
<scope-rules>
|
|
13
|
-
- Component name if
|
|
13
|
+
- Component name if ≥60% changes target it
|
|
14
14
|
- null if spread across multiple components
|
|
15
15
|
- scope_candidates as primary source
|
|
16
16
|
- Valid: specific component names (api, parser, config, etc.)
|
package/src/commit/types.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Types for the omp commit pipeline.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
4
|
export type CommitType =
|
|
6
5
|
| "feat"
|
|
7
6
|
| "fix"
|
|
@@ -24,6 +23,16 @@ export type ChangelogCategory =
|
|
|
24
23
|
| "Fixed"
|
|
25
24
|
| "Security";
|
|
26
25
|
|
|
26
|
+
export const CHANGELOG_CATEGORIES: ChangelogCategory[] = [
|
|
27
|
+
"Breaking Changes",
|
|
28
|
+
"Added",
|
|
29
|
+
"Changed",
|
|
30
|
+
"Deprecated",
|
|
31
|
+
"Removed",
|
|
32
|
+
"Fixed",
|
|
33
|
+
"Security",
|
|
34
|
+
];
|
|
35
|
+
|
|
27
36
|
export interface CommitCommandArgs {
|
|
28
37
|
/** Push after commit */
|
|
29
38
|
push: boolean;
|
|
@@ -8,8 +8,7 @@ import {
|
|
|
8
8
|
matchesKey,
|
|
9
9
|
setEditorKeybindings,
|
|
10
10
|
} from "@oh-my-pi/pi-tui";
|
|
11
|
-
import { isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
12
|
-
import { getAgentDir } from "@oh-my-pi/pi-utils/dirs";
|
|
11
|
+
import { getAgentDir, isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* Application-level actions (coding agent specific).
|
|
@@ -47,7 +47,7 @@ export const MODEL_ROLES: Record<ModelRole, ModelRoleInfo> = {
|
|
|
47
47
|
smol: { tag: "SMOL", name: "Fast", color: "warning" },
|
|
48
48
|
slow: { tag: "SLOW", name: "Thinking", color: "accent" },
|
|
49
49
|
plan: { tag: "PLAN", name: "Architect", color: "muted" },
|
|
50
|
-
commit: { name: "Commit" },
|
|
50
|
+
commit: { tag: "COMMIT", name: "Commit", color: "dim" },
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
export const MODEL_ROLE_IDS: ModelRole[] = ["default", "smol", "slow", "plan", "commit"];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { logger } from "@oh-my-pi/pi-utils";
|
|
4
|
-
import { getProjectDir, getProjectPromptsDir, getPromptsDir } from "@oh-my-pi/pi-utils/dirs";
|
|
3
|
+
import { getProjectDir, getProjectPromptsDir, getPromptsDir, logger } from "@oh-my-pi/pi-utils";
|
|
5
4
|
import Handlebars from "handlebars";
|
|
6
5
|
import { computeLineHash } from "../patch/hashline";
|
|
7
6
|
import { jtdToTypeScript } from "../tools/jtd-to-typescript";
|
|
@@ -230,6 +229,19 @@ handlebars.registerHelper("jtdToTypeScript", (schema: unknown): string => jtdToT
|
|
|
230
229
|
|
|
231
230
|
handlebars.registerHelper("jsonStringify", (value: unknown): string => JSON.stringify(value));
|
|
232
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Renders a section separator:
|
|
234
|
+
*
|
|
235
|
+
* ═══════════════════════════════
|
|
236
|
+
* Name
|
|
237
|
+
* ═══════════════════════════════
|
|
238
|
+
*/
|
|
239
|
+
export function sectionSeparator(name: string): string {
|
|
240
|
+
return `\n\n═══════════${name}═══════════\n`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
handlebars.registerHelper("SECTION_SEPERATOR", (name: unknown): string => sectionSeparator(String(name)));
|
|
244
|
+
|
|
233
245
|
/**
|
|
234
246
|
* {{hlineref lineNum "content"}} — compute a real hashline ref for prompt examples.
|
|
235
247
|
* Returns `"lineNum#hash"` using the actual hash algorithm.
|
|
@@ -176,6 +176,16 @@ export const SETTINGS_SCHEMA = {
|
|
|
176
176
|
description: "Use blue instead of green for diff additions",
|
|
177
177
|
},
|
|
178
178
|
},
|
|
179
|
+
"display.tabWidth": {
|
|
180
|
+
type: "number",
|
|
181
|
+
default: 3,
|
|
182
|
+
ui: {
|
|
183
|
+
tab: "display",
|
|
184
|
+
label: "Tab width",
|
|
185
|
+
description: "Default number of spaces used when rendering tab characters",
|
|
186
|
+
submenu: true,
|
|
187
|
+
},
|
|
188
|
+
},
|
|
179
189
|
defaultThinkingLevel: {
|
|
180
190
|
type: "enum",
|
|
181
191
|
values: ["off", "minimal", "low", "medium", "high", "xhigh"] as const,
|
package/src/config/settings.ts
CHANGED
|
@@ -13,8 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
import * as fs from "node:fs";
|
|
15
15
|
import * as path from "node:path";
|
|
16
|
-
import {
|
|
17
|
-
|
|
16
|
+
import {
|
|
17
|
+
getAgentDbPath,
|
|
18
|
+
getAgentDir,
|
|
19
|
+
getProjectDir,
|
|
20
|
+
isEnoent,
|
|
21
|
+
logger,
|
|
22
|
+
procmgr,
|
|
23
|
+
setDefaultTabWidth,
|
|
24
|
+
} from "@oh-my-pi/pi-utils";
|
|
18
25
|
import { YAML } from "bun";
|
|
19
26
|
import { type Settings as SettingsCapabilityItem, settingsCapability } from "../capability/settings";
|
|
20
27
|
import type { ModelRole } from "../config/model-registry";
|
|
@@ -438,6 +445,7 @@ export class Settings {
|
|
|
438
445
|
|
|
439
446
|
// Build merged view
|
|
440
447
|
this.#rebuildMerged();
|
|
448
|
+
this.#fireAllHooks();
|
|
441
449
|
return this;
|
|
442
450
|
}
|
|
443
451
|
|
|
@@ -610,6 +618,16 @@ export class Settings {
|
|
|
610
618
|
this.#merged = this.#deepMerge(this.#merged, this.#overrides);
|
|
611
619
|
}
|
|
612
620
|
|
|
621
|
+
#fireAllHooks(): void {
|
|
622
|
+
for (const key of Object.keys(SETTING_HOOKS) as SettingPath[]) {
|
|
623
|
+
const hook = SETTING_HOOKS[key];
|
|
624
|
+
if (hook) {
|
|
625
|
+
const value = this.get(key);
|
|
626
|
+
hook(value, value);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
613
631
|
#deepMerge(base: RawSettings, overrides: RawSettings): RawSettings {
|
|
614
632
|
const result = { ...base };
|
|
615
633
|
for (const key of Object.keys(overrides)) {
|
|
@@ -666,6 +684,11 @@ const SETTING_HOOKS: Partial<Record<SettingPath, SettingHook<any>>> = {
|
|
|
666
684
|
});
|
|
667
685
|
}
|
|
668
686
|
},
|
|
687
|
+
"display.tabWidth": value => {
|
|
688
|
+
if (typeof value === "number") {
|
|
689
|
+
setDefaultTabWidth(value);
|
|
690
|
+
}
|
|
691
|
+
},
|
|
669
692
|
};
|
|
670
693
|
|
|
671
694
|
// ═══════════════════════════════════════════════════════════════════════════
|
package/src/config.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as os from "node:os";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
5
|
-
import { CONFIG_DIR_NAME, getAgentDir, getProjectDir } from "@oh-my-pi/pi-utils/dirs";
|
|
4
|
+
import { CONFIG_DIR_NAME, getAgentDir, getProjectDir, isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
6
5
|
import type { TSchema } from "@sinclair/typebox";
|
|
7
6
|
import { Value } from "@sinclair/typebox/value";
|
|
8
7
|
import { Ajv, type ErrorObject, type ValidateFunction } from "ajv";
|
package/src/debug/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ import * as fs from "node:fs/promises";
|
|
|
7
7
|
import * as url from "node:url";
|
|
8
8
|
import { getWorkProfile } from "@oh-my-pi/pi-natives";
|
|
9
9
|
import { Container, Loader, type SelectItem, SelectList, Spacer, Text } from "@oh-my-pi/pi-tui";
|
|
10
|
-
import { getSessionsDir } from "@oh-my-pi/pi-utils
|
|
10
|
+
import { getSessionsDir } from "@oh-my-pi/pi-utils";
|
|
11
11
|
import { DynamicBorder } from "../modes/components/dynamic-border";
|
|
12
12
|
import { getSelectListTheme, getSymbolTheme, theme } from "../modes/theme/theme";
|
|
13
13
|
import type { InteractiveModeContext } from "../modes/types";
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
import * as fs from "node:fs/promises";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import type { WorkProfile } from "@oh-my-pi/pi-natives";
|
|
9
|
-
import { isEnoent } from "@oh-my-pi/pi-utils";
|
|
10
|
-
import { APP_NAME, getLogPath, getLogsDir, getReportsDir } from "@oh-my-pi/pi-utils/dirs";
|
|
9
|
+
import { APP_NAME, getLogPath, getLogsDir, getReportsDir, isEnoent } from "@oh-my-pi/pi-utils";
|
|
11
10
|
import type { CpuProfile, HeapSnapshot } from "./profiler";
|
|
12
11
|
import { collectSystemInfo, sanitizeEnv } from "./system-info";
|
|
13
12
|
|
package/src/debug/system-info.ts
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import * as os from "node:os";
|
|
6
|
-
import { formatBytes } from "@oh-my-pi/pi-utils";
|
|
7
|
-
import { getProjectDir, VERSION } from "@oh-my-pi/pi-utils/dirs";
|
|
6
|
+
import { formatBytes, getProjectDir, VERSION } from "@oh-my-pi/pi-utils";
|
|
8
7
|
|
|
9
8
|
export interface SystemInfo {
|
|
10
9
|
os: string;
|
package/src/discovery/agents.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { type Skill, skillCapability } from "../capability/skill";
|
|
|
13
13
|
import { type SlashCommand, slashCommandCapability } from "../capability/slash-command";
|
|
14
14
|
import { type SystemPrompt, systemPromptCapability } from "../capability/system-prompt";
|
|
15
15
|
import type { LoadContext, LoadResult } from "../capability/types";
|
|
16
|
-
import { buildRuleFromMarkdown, createSourceMeta, loadFilesFromDir,
|
|
16
|
+
import { buildRuleFromMarkdown, createSourceMeta, loadFilesFromDir, scanSkillsFromDir } from "./helpers";
|
|
17
17
|
|
|
18
18
|
const PROVIDER_ID = "agents";
|
|
19
19
|
const DISPLAY_NAME = "Agents (standard)";
|
|
@@ -28,7 +28,7 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
28
28
|
const items: Skill[] = [];
|
|
29
29
|
const warnings: string[] = [];
|
|
30
30
|
for (const userSkillsDir of getUserAgentPathCandidates(ctx, "skills")) {
|
|
31
|
-
const result = await
|
|
31
|
+
const result = await scanSkillsFromDir(ctx, {
|
|
32
32
|
dir: userSkillsDir,
|
|
33
33
|
providerId: PROVIDER_ID,
|
|
34
34
|
level: "user",
|
package/src/discovery/builtin.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Primary provider for OMP native configs. Supports all capabilities.
|
|
5
5
|
*/
|
|
6
6
|
import * as path from "node:path";
|
|
7
|
-
import { logger } from "@oh-my-pi/pi-utils";
|
|
7
|
+
import { logger, tryParseJson } from "@oh-my-pi/pi-utils";
|
|
8
8
|
import { registerProvider } from "../capability";
|
|
9
9
|
import { type ContextFile, contextFileCapability } from "../capability/context-file";
|
|
10
10
|
import { type Extension, type ExtensionManifest, extensionCapability } from "../capability/extension";
|
|
@@ -30,9 +30,8 @@ import {
|
|
|
30
30
|
expandEnvVarsDeep,
|
|
31
31
|
getExtensionNameFromPath,
|
|
32
32
|
loadFilesFromDir,
|
|
33
|
-
loadSkillsFromDir,
|
|
34
|
-
parseJSON,
|
|
35
33
|
SOURCE_PATHS,
|
|
34
|
+
scanSkillsFromDir,
|
|
36
35
|
} from "./helpers";
|
|
37
36
|
|
|
38
37
|
const PROVIDER_ID = "native";
|
|
@@ -98,7 +97,7 @@ async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>>
|
|
|
98
97
|
|
|
99
98
|
const parseMcpServers = (content: string, path: string, level: "user" | "project"): MCPServer[] => {
|
|
100
99
|
const result: MCPServer[] = [];
|
|
101
|
-
const data =
|
|
100
|
+
const data = tryParseJson<{ mcpServers?: Record<string, unknown> }>(content);
|
|
102
101
|
if (!data?.mcpServers) return result;
|
|
103
102
|
|
|
104
103
|
const expanded = expandEnvVarsDeep(data.mcpServers);
|
|
@@ -245,7 +244,7 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
245
244
|
const configDirs = await getConfigDirs(ctx);
|
|
246
245
|
const results = await Promise.all(
|
|
247
246
|
configDirs.map(({ dir, level }) =>
|
|
248
|
-
|
|
247
|
+
scanSkillsFromDir(ctx, {
|
|
249
248
|
dir: path.join(dir, "skills"),
|
|
250
249
|
providerId: PROVIDER_ID,
|
|
251
250
|
level,
|
|
@@ -404,7 +403,7 @@ async function loadExtensionModules(ctx: LoadContext): Promise<LoadResult<Extens
|
|
|
404
403
|
if (!settingsContent) continue;
|
|
405
404
|
|
|
406
405
|
const settingsPath = path.join(dir, "settings.json");
|
|
407
|
-
const settingsData =
|
|
406
|
+
const settingsData = tryParseJson<{ extensions?: unknown }>(settingsContent);
|
|
408
407
|
const extensions = settingsData?.extensions;
|
|
409
408
|
if (!Array.isArray(extensions)) continue;
|
|
410
409
|
|
|
@@ -508,7 +507,7 @@ async function loadExtensions(ctx: LoadContext): Promise<LoadResult<Extension>>
|
|
|
508
507
|
if (!content) continue;
|
|
509
508
|
|
|
510
509
|
const { extDir, manifestPath, entryName, level } = manifestCandidates[i];
|
|
511
|
-
const manifest =
|
|
510
|
+
const manifest = tryParseJson<ExtensionManifest>(content);
|
|
512
511
|
if (!manifest) {
|
|
513
512
|
warnings.push(`Failed to parse ${manifestPath}`);
|
|
514
513
|
continue;
|
|
@@ -655,21 +654,31 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
655
654
|
extensions: ["json", "md", "ts", "js", "sh", "bash", "py"],
|
|
656
655
|
transform: (name, content, path, source) => {
|
|
657
656
|
if (name.endsWith(".json")) {
|
|
658
|
-
const data =
|
|
657
|
+
const data = tryParseJson<{ name?: string; description?: string }>(content);
|
|
658
|
+
const toolName = data?.name || name.replace(/\.json$/, "");
|
|
659
|
+
const description =
|
|
660
|
+
typeof data?.description === "string" && data.description.trim()
|
|
661
|
+
? data.description
|
|
662
|
+
: `${toolName} custom tool`;
|
|
659
663
|
return {
|
|
660
|
-
name:
|
|
664
|
+
name: toolName,
|
|
661
665
|
path,
|
|
662
|
-
description
|
|
666
|
+
description,
|
|
663
667
|
level,
|
|
664
668
|
_source: source,
|
|
665
669
|
};
|
|
666
670
|
}
|
|
667
671
|
if (name.endsWith(".md")) {
|
|
668
672
|
const { frontmatter } = parseFrontmatter(content, { source: path });
|
|
673
|
+
const toolName = (frontmatter.name as string) || name.replace(/\.md$/, "");
|
|
674
|
+
const description =
|
|
675
|
+
typeof frontmatter.description === "string" && frontmatter.description.trim()
|
|
676
|
+
? String(frontmatter.description)
|
|
677
|
+
: `${toolName} custom tool`;
|
|
669
678
|
return {
|
|
670
|
-
name:
|
|
679
|
+
name: toolName,
|
|
671
680
|
path,
|
|
672
|
-
description
|
|
681
|
+
description,
|
|
673
682
|
level,
|
|
674
683
|
_source: source,
|
|
675
684
|
};
|
|
@@ -679,6 +688,7 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
679
688
|
return {
|
|
680
689
|
name: toolName,
|
|
681
690
|
path,
|
|
691
|
+
description: `${toolName} custom tool`,
|
|
682
692
|
level,
|
|
683
693
|
_source: source,
|
|
684
694
|
};
|
|
@@ -715,7 +725,7 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
715
725
|
items.push({
|
|
716
726
|
name: entryName,
|
|
717
727
|
path: indexPath,
|
|
718
|
-
description:
|
|
728
|
+
description: `${entryName} custom tool`,
|
|
719
729
|
level,
|
|
720
730
|
_source: createSourceMeta(PROVIDER_ID, indexPath, level),
|
|
721
731
|
});
|
|
@@ -743,7 +753,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
743
753
|
const content = await readFile(settingsPath);
|
|
744
754
|
if (!content) continue;
|
|
745
755
|
|
|
746
|
-
const data =
|
|
756
|
+
const data = tryParseJson<Record<string, unknown>>(content);
|
|
747
757
|
if (!data) {
|
|
748
758
|
warnings.push(`Failed to parse ${settingsPath}`);
|
|
749
759
|
continue;
|
|
@@ -11,7 +11,7 @@ import { type Skill, skillCapability } from "../capability/skill";
|
|
|
11
11
|
import { type SlashCommand, slashCommandCapability } from "../capability/slash-command";
|
|
12
12
|
import { type CustomTool, toolCapability } from "../capability/tool";
|
|
13
13
|
import type { LoadContext, LoadResult } from "../capability/types";
|
|
14
|
-
import { type ClaudePluginRoot, listClaudePluginRoots, loadFilesFromDir,
|
|
14
|
+
import { type ClaudePluginRoot, listClaudePluginRoots, loadFilesFromDir, scanSkillsFromDir } from "./helpers";
|
|
15
15
|
|
|
16
16
|
const PROVIDER_ID = "claude-plugins";
|
|
17
17
|
const DISPLAY_NAME = "Claude Code Marketplace";
|
|
@@ -31,7 +31,7 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
31
31
|
const results = await Promise.all(
|
|
32
32
|
roots.map(async root => {
|
|
33
33
|
const skillsDir = path.join(root.path, "skills");
|
|
34
|
-
return
|
|
34
|
+
return scanSkillsFromDir(ctx, {
|
|
35
35
|
dir: skillsDir,
|
|
36
36
|
providerId: PROVIDER_ID,
|
|
37
37
|
level: root.scope,
|
|
@@ -152,6 +152,7 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
152
152
|
return {
|
|
153
153
|
name: toolName,
|
|
154
154
|
path: filePath,
|
|
155
|
+
description: `${toolName} custom tool`,
|
|
155
156
|
level: root.scope,
|
|
156
157
|
_source: source,
|
|
157
158
|
};
|
package/src/discovery/claude.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Priority: 80 (tool-specific, below builtin but above shared standards)
|
|
6
6
|
*/
|
|
7
7
|
import * as path from "node:path";
|
|
8
|
+
import { tryParseJson } from "@oh-my-pi/pi-utils";
|
|
8
9
|
import { registerProvider } from "../capability";
|
|
9
10
|
import { type ContextFile, contextFileCapability } from "../capability/context-file";
|
|
10
11
|
import { type ExtensionModule, extensionModuleCapability } from "../capability/extension-module";
|
|
@@ -24,8 +25,7 @@ import {
|
|
|
24
25
|
expandEnvVarsDeep,
|
|
25
26
|
getExtensionNameFromPath,
|
|
26
27
|
loadFilesFromDir,
|
|
27
|
-
|
|
28
|
-
parseJSON,
|
|
28
|
+
scanSkillsFromDir,
|
|
29
29
|
} from "./helpers";
|
|
30
30
|
|
|
31
31
|
const PROVIDER_ID = "claude";
|
|
@@ -77,7 +77,7 @@ async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>>
|
|
|
77
77
|
|
|
78
78
|
const parseMcpServers = (content: string | null, path: string, level: "user" | "project"): MCPServer[] => {
|
|
79
79
|
if (!content) return [];
|
|
80
|
-
const json =
|
|
80
|
+
const json = tryParseJson<{ mcpServers?: Record<string, unknown> }>(content);
|
|
81
81
|
if (!json?.mcpServers) return [];
|
|
82
82
|
|
|
83
83
|
const mcpServers = expandEnvVarsDeep(json.mcpServers);
|
|
@@ -163,8 +163,8 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
163
163
|
const projectSkillsDir = path.join(getProjectClaude(ctx), "skills");
|
|
164
164
|
|
|
165
165
|
const results = await Promise.all([
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
scanSkillsFromDir(ctx, { dir: userSkillsDir, providerId: PROVIDER_ID, level: "user" }),
|
|
167
|
+
scanSkillsFromDir(ctx, { dir: projectSkillsDir, providerId: PROVIDER_ID, level: "project" }),
|
|
168
168
|
]);
|
|
169
169
|
|
|
170
170
|
return {
|
|
@@ -324,10 +324,10 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
324
324
|
const userResult = await loadFilesFromDir<CustomTool>(ctx, userToolsDir, PROVIDER_ID, "user", {
|
|
325
325
|
transform: (name, _content, path, source) => {
|
|
326
326
|
const toolName = name.replace(/\.(ts|js|sh|bash|py)$/, "");
|
|
327
|
-
|
|
328
327
|
return {
|
|
329
328
|
name: toolName,
|
|
330
329
|
path,
|
|
330
|
+
description: `${toolName} custom tool`,
|
|
331
331
|
level: "user",
|
|
332
332
|
_source: source,
|
|
333
333
|
};
|
|
@@ -343,10 +343,10 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
343
343
|
const projectResult = await loadFilesFromDir<CustomTool>(ctx, projectToolsDir, PROVIDER_ID, "project", {
|
|
344
344
|
transform: (name, _content, path, source) => {
|
|
345
345
|
const toolName = name.replace(/\.(ts|js|sh|bash|py)$/, "");
|
|
346
|
-
|
|
347
346
|
return {
|
|
348
347
|
name: toolName,
|
|
349
348
|
path,
|
|
349
|
+
description: `${toolName} custom tool`,
|
|
350
350
|
level: "project",
|
|
351
351
|
_source: source,
|
|
352
352
|
};
|
|
@@ -396,7 +396,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
396
396
|
|
|
397
397
|
const userContent = await readFile(userSettingsJson);
|
|
398
398
|
if (userContent) {
|
|
399
|
-
const data =
|
|
399
|
+
const data = tryParseJson<Record<string, unknown>>(userContent);
|
|
400
400
|
if (data) {
|
|
401
401
|
items.push({
|
|
402
402
|
path: userSettingsJson,
|
|
@@ -413,7 +413,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
413
413
|
const projectSettingsJson = path.join(projectBase, "settings.json");
|
|
414
414
|
const projectContent = await readFile(projectSettingsJson);
|
|
415
415
|
if (projectContent) {
|
|
416
|
-
const data =
|
|
416
|
+
const data = tryParseJson<Record<string, unknown>>(projectContent);
|
|
417
417
|
if (data) {
|
|
418
418
|
items.push({
|
|
419
419
|
path: projectSettingsJson,
|
package/src/discovery/codex.ts
CHANGED
|
@@ -35,8 +35,8 @@ import {
|
|
|
35
35
|
discoverExtensionModulePaths,
|
|
36
36
|
getExtensionNameFromPath,
|
|
37
37
|
loadFilesFromDir,
|
|
38
|
-
loadSkillsFromDir,
|
|
39
38
|
SOURCE_PATHS,
|
|
39
|
+
scanSkillsFromDir,
|
|
40
40
|
} from "./helpers";
|
|
41
41
|
|
|
42
42
|
const PROVIDER_ID = "codex";
|
|
@@ -214,12 +214,12 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
214
214
|
const projectSkillsDir = path.join(codexDir, "skills");
|
|
215
215
|
|
|
216
216
|
const results = await Promise.all([
|
|
217
|
-
|
|
217
|
+
scanSkillsFromDir(ctx, {
|
|
218
218
|
dir: userSkillsDir,
|
|
219
219
|
providerId: PROVIDER_ID,
|
|
220
220
|
level: "user",
|
|
221
221
|
}),
|
|
222
|
-
|
|
222
|
+
scanSkillsFromDir(ctx, {
|
|
223
223
|
dir: projectSkillsDir,
|
|
224
224
|
providerId: PROVIDER_ID,
|
|
225
225
|
level: "project",
|
package/src/discovery/cursor.ts
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* - rules: From rules/*.mdc files with MDC frontmatter (description, globs, alwaysApply)
|
|
14
14
|
* - settings: From settings.json if present
|
|
15
15
|
*/
|
|
16
|
+
|
|
17
|
+
import { tryParseJson } from "@oh-my-pi/pi-utils";
|
|
16
18
|
import { registerProvider } from "../capability";
|
|
17
19
|
import { readFile } from "../capability/fs";
|
|
18
20
|
import { type MCPServer, mcpCapability } from "../capability/mcp";
|
|
@@ -28,7 +30,6 @@ import {
|
|
|
28
30
|
getProjectPath,
|
|
29
31
|
getUserPath,
|
|
30
32
|
loadFilesFromDir,
|
|
31
|
-
parseJSON,
|
|
32
33
|
} from "./helpers";
|
|
33
34
|
|
|
34
35
|
const PROVIDER_ID = "cursor";
|
|
@@ -46,7 +47,7 @@ function parseMCPServers(
|
|
|
46
47
|
): { items: MCPServer[]; warning?: string } {
|
|
47
48
|
const items: MCPServer[] = [];
|
|
48
49
|
|
|
49
|
-
const parsed =
|
|
50
|
+
const parsed = tryParseJson<{ mcpServers?: Record<string, unknown> }>(content);
|
|
50
51
|
if (!parsed?.mcpServers) {
|
|
51
52
|
return { items, warning: `${path}: missing or invalid 'mcpServers' key` };
|
|
52
53
|
}
|
|
@@ -158,7 +159,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
158
159
|
const projectContentPromise = projectPath ? readFile(projectPath) : Promise.resolve(null);
|
|
159
160
|
|
|
160
161
|
if (userContent && userPath) {
|
|
161
|
-
const parsed =
|
|
162
|
+
const parsed = tryParseJson<Record<string, unknown>>(userContent);
|
|
162
163
|
if (parsed) {
|
|
163
164
|
items.push({
|
|
164
165
|
path: userPath,
|
|
@@ -173,7 +174,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
173
174
|
|
|
174
175
|
const projectContent = await projectContentPromise;
|
|
175
176
|
if (projectContent && projectPath) {
|
|
176
|
-
const parsed =
|
|
177
|
+
const parsed = tryParseJson<Record<string, unknown>>(projectContent);
|
|
177
178
|
if (parsed) {
|
|
178
179
|
items.push({
|
|
179
180
|
path: projectPath,
|
package/src/discovery/gemini.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* - settings: From settings.json
|
|
17
17
|
*/
|
|
18
18
|
import * as path from "node:path";
|
|
19
|
+
import { tryParseJson } from "@oh-my-pi/pi-utils";
|
|
19
20
|
import { registerProvider } from "../capability";
|
|
20
21
|
import { type ContextFile, contextFileCapability } from "../capability/context-file";
|
|
21
22
|
import { type Extension, type ExtensionManifest, extensionCapability } from "../capability/extension";
|
|
@@ -33,7 +34,6 @@ import {
|
|
|
33
34
|
getExtensionNameFromPath,
|
|
34
35
|
getProjectPath,
|
|
35
36
|
getUserPath,
|
|
36
|
-
parseJSON,
|
|
37
37
|
} from "./helpers";
|
|
38
38
|
|
|
39
39
|
const PROVIDER_ID = "gemini";
|
|
@@ -80,7 +80,7 @@ async function loadMCPFromSettings(
|
|
|
80
80
|
return { items, warnings };
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
const parsed =
|
|
83
|
+
const parsed = tryParseJson<{ mcpServers?: Record<string, unknown> }>(content);
|
|
84
84
|
if (!parsed) {
|
|
85
85
|
warnings.push(`Invalid JSON in ${path}`);
|
|
86
86
|
return { items, warnings };
|
|
@@ -206,7 +206,7 @@ async function loadExtensionsFromDir(extensionsDir: string, level: "user" | "pro
|
|
|
206
206
|
for (const { entry, extPath, manifestPath, content } of results) {
|
|
207
207
|
if (!content) continue;
|
|
208
208
|
|
|
209
|
-
const manifest =
|
|
209
|
+
const manifest = tryParseJson<ExtensionManifest>(content);
|
|
210
210
|
if (!manifest) {
|
|
211
211
|
warnings.push(`Invalid JSON in ${manifestPath}`);
|
|
212
212
|
continue;
|
|
@@ -268,7 +268,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
268
268
|
if (userPath) {
|
|
269
269
|
const content = await readFile(userPath);
|
|
270
270
|
if (content) {
|
|
271
|
-
const parsed =
|
|
271
|
+
const parsed = tryParseJson<Record<string, unknown>>(content);
|
|
272
272
|
if (parsed) {
|
|
273
273
|
items.push({
|
|
274
274
|
path: userPath,
|
|
@@ -287,7 +287,7 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
287
287
|
if (projectPath) {
|
|
288
288
|
const content = await readFile(projectPath);
|
|
289
289
|
if (content) {
|
|
290
|
-
const parsed =
|
|
290
|
+
const parsed = tryParseJson<Record<string, unknown>>(content);
|
|
291
291
|
if (parsed) {
|
|
292
292
|
items.push({
|
|
293
293
|
path: projectPath,
|