@oh-my-pi/pi-coding-agent 2.3.1337 → 3.1.1337
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 +72 -34
- package/README.md +100 -100
- package/docs/compaction.md +8 -8
- package/docs/config-usage.md +113 -0
- package/docs/custom-tools.md +8 -8
- package/docs/extension-loading.md +58 -58
- package/docs/hooks.md +11 -11
- package/docs/rpc.md +4 -4
- package/docs/sdk.md +14 -14
- package/docs/session-tree-plan.md +1 -1
- package/docs/session.md +2 -2
- package/docs/skills.md +16 -16
- package/docs/theme.md +9 -9
- package/docs/tui.md +1 -1
- package/examples/README.md +1 -1
- package/examples/custom-tools/README.md +4 -4
- package/examples/custom-tools/subagent/README.md +13 -13
- package/examples/custom-tools/subagent/agents.ts +2 -2
- package/examples/custom-tools/subagent/index.ts +5 -5
- package/examples/hooks/README.md +3 -3
- package/examples/hooks/auto-commit-on-exit.ts +1 -1
- package/examples/hooks/custom-compaction.ts +1 -1
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/examples/sdk/05-tools.ts +1 -1
- package/examples/sdk/08-slash-commands.ts +1 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
- package/examples/sdk/README.md +2 -2
- package/package.json +13 -11
- package/src/capability/context-file.ts +40 -0
- package/src/capability/extension.ts +48 -0
- package/src/capability/hook.ts +40 -0
- package/src/capability/index.ts +616 -0
- package/src/capability/instruction.ts +37 -0
- package/src/capability/mcp.ts +52 -0
- package/src/capability/prompt.ts +35 -0
- package/src/capability/rule.ts +52 -0
- package/src/capability/settings.ts +35 -0
- package/src/capability/skill.ts +49 -0
- package/src/capability/slash-command.ts +40 -0
- package/src/capability/system-prompt.ts +35 -0
- package/src/capability/tool.ts +38 -0
- package/src/capability/types.ts +166 -0
- package/src/cli/args.ts +2 -2
- package/src/cli/plugin-cli.ts +24 -19
- package/src/cli/update-cli.ts +10 -10
- package/src/config.ts +290 -6
- package/src/core/auth-storage.ts +32 -9
- package/src/core/bash-executor.ts +1 -1
- package/src/core/custom-commands/loader.ts +44 -50
- package/src/core/custom-tools/index.ts +1 -0
- package/src/core/custom-tools/loader.ts +67 -69
- package/src/core/custom-tools/types.ts +10 -1
- package/src/core/hooks/loader.ts +13 -42
- package/src/core/index.ts +0 -1
- package/src/core/logger.ts +7 -7
- package/src/core/mcp/client.ts +1 -1
- package/src/core/mcp/config.ts +94 -146
- package/src/core/mcp/index.ts +0 -4
- package/src/core/mcp/loader.ts +26 -22
- package/src/core/mcp/manager.ts +18 -23
- package/src/core/mcp/tool-bridge.ts +9 -1
- package/src/core/mcp/types.ts +2 -0
- package/src/core/model-registry.ts +25 -8
- package/src/core/plugins/installer.ts +1 -1
- package/src/core/plugins/loader.ts +17 -11
- package/src/core/plugins/manager.ts +2 -2
- package/src/core/plugins/paths.ts +12 -7
- package/src/core/plugins/types.ts +3 -3
- package/src/core/sdk.ts +48 -27
- package/src/core/session-manager.ts +4 -4
- package/src/core/settings-manager.ts +45 -21
- package/src/core/skills.ts +208 -293
- package/src/core/slash-commands.ts +34 -165
- package/src/core/system-prompt.ts +58 -65
- package/src/core/timings.ts +2 -2
- package/src/core/tools/lsp/config.ts +38 -17
- package/src/core/tools/task/agents.ts +21 -0
- package/src/core/tools/task/artifacts.ts +1 -1
- package/src/core/tools/task/bundled-agents/reviewer.md +2 -1
- package/src/core/tools/task/bundled-agents/task.md +1 -0
- package/src/core/tools/task/commands.ts +30 -107
- package/src/core/tools/task/discovery.ts +75 -66
- package/src/core/tools/task/executor.ts +25 -10
- package/src/core/tools/task/index.ts +35 -10
- package/src/core/tools/task/model-resolver.ts +27 -25
- package/src/core/tools/task/types.ts +6 -2
- package/src/core/tools/web-fetch.ts +3 -3
- package/src/core/tools/web-search/auth.ts +40 -34
- package/src/core/tools/web-search/index.ts +1 -1
- package/src/core/tools/web-search/providers/anthropic.ts +1 -1
- package/src/discovery/agents-md.ts +75 -0
- package/src/discovery/builtin.ts +646 -0
- package/src/discovery/claude.ts +623 -0
- package/src/discovery/cline.ts +102 -0
- package/src/discovery/codex.ts +571 -0
- package/src/discovery/cursor.ts +264 -0
- package/src/discovery/gemini.ts +368 -0
- package/src/discovery/github.ts +120 -0
- package/src/discovery/helpers.test.ts +127 -0
- package/src/discovery/helpers.ts +249 -0
- package/src/discovery/index.ts +84 -0
- package/src/discovery/mcp-json.ts +127 -0
- package/src/discovery/vscode.ts +99 -0
- package/src/discovery/windsurf.ts +216 -0
- package/src/main.ts +14 -13
- package/src/migrations.ts +24 -3
- package/src/modes/interactive/components/hook-editor.ts +1 -1
- package/src/modes/interactive/components/plugin-settings.ts +1 -1
- package/src/modes/interactive/components/settings-defs.ts +38 -2
- package/src/modes/interactive/components/settings-selector.ts +1 -0
- package/src/modes/interactive/components/welcome.ts +2 -2
- package/src/modes/interactive/interactive-mode.ts +233 -16
- package/src/modes/interactive/theme/theme-schema.json +1 -1
- package/src/utils/clipboard.ts +1 -1
- package/src/utils/shell-snapshot.ts +2 -2
- package/src/utils/shell.ts +7 -7
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompts Capability
|
|
3
|
+
*
|
|
4
|
+
* Reusable prompt templates (Codex format) available via /prompts: menu.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineCapability } from "./index";
|
|
8
|
+
import type { SourceMeta } from "./types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A reusable prompt template.
|
|
12
|
+
*/
|
|
13
|
+
export interface Prompt {
|
|
14
|
+
/** Prompt name (filename without extension) */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Absolute path to prompt file */
|
|
17
|
+
path: string;
|
|
18
|
+
/** Prompt content (markdown) */
|
|
19
|
+
content: string;
|
|
20
|
+
/** Source metadata */
|
|
21
|
+
_source: SourceMeta;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const promptCapability = defineCapability<Prompt>({
|
|
25
|
+
id: "prompts",
|
|
26
|
+
displayName: "Prompts",
|
|
27
|
+
description: "Reusable prompt templates available via /prompts: menu",
|
|
28
|
+
key: (prompt) => prompt.name,
|
|
29
|
+
validate: (prompt) => {
|
|
30
|
+
if (!prompt.name) return "Missing name";
|
|
31
|
+
if (!prompt.path) return "Missing path";
|
|
32
|
+
if (prompt.content === undefined) return "Missing content";
|
|
33
|
+
return undefined;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rules Capability
|
|
3
|
+
*
|
|
4
|
+
* Project-specific rules from Cursor (.mdc), Windsurf (.md), and Cline formats.
|
|
5
|
+
* Translated to a canonical shape regardless of source format.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { defineCapability } from "./index";
|
|
9
|
+
import type { SourceMeta } from "./types";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Parsed frontmatter from MDC rule files (Cursor format).
|
|
13
|
+
*/
|
|
14
|
+
export interface RuleFrontmatter {
|
|
15
|
+
description?: string;
|
|
16
|
+
globs?: string[];
|
|
17
|
+
alwaysApply?: boolean;
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A rule providing project-specific guidance and constraints.
|
|
23
|
+
*/
|
|
24
|
+
export interface Rule {
|
|
25
|
+
/** Rule name (derived from filename) */
|
|
26
|
+
name: string;
|
|
27
|
+
/** Absolute path to rule file */
|
|
28
|
+
path: string;
|
|
29
|
+
/** Rule content (after frontmatter stripped) */
|
|
30
|
+
content: string;
|
|
31
|
+
/** Globs this rule applies to (if any) */
|
|
32
|
+
globs?: string[];
|
|
33
|
+
/** Whether to always include this rule */
|
|
34
|
+
alwaysApply?: boolean;
|
|
35
|
+
/** Description (for agent-requested rules) */
|
|
36
|
+
description?: string;
|
|
37
|
+
/** Source metadata */
|
|
38
|
+
_source: SourceMeta;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const ruleCapability = defineCapability<Rule>({
|
|
42
|
+
id: "rules",
|
|
43
|
+
displayName: "Rules",
|
|
44
|
+
description: "Project-specific rules and constraints (Cursor MDC, Windsurf, Cline formats)",
|
|
45
|
+
key: (rule) => rule.name,
|
|
46
|
+
validate: (rule) => {
|
|
47
|
+
if (!rule.name) return "Missing rule name";
|
|
48
|
+
if (!rule.path) return "Missing rule path";
|
|
49
|
+
if (!rule.content || typeof rule.content !== "string") return "Rule must have content";
|
|
50
|
+
return undefined;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Capability
|
|
3
|
+
*
|
|
4
|
+
* Configuration settings from various sources (JSON, TOML, etc.)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineCapability } from "./index";
|
|
8
|
+
import type { SourceMeta } from "./types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A settings file.
|
|
12
|
+
*/
|
|
13
|
+
export interface Settings {
|
|
14
|
+
/** Absolute path to settings file */
|
|
15
|
+
path: string;
|
|
16
|
+
/** Parsed settings data */
|
|
17
|
+
data: Record<string, unknown>;
|
|
18
|
+
/** Source level */
|
|
19
|
+
level: "user" | "project";
|
|
20
|
+
/** Source metadata */
|
|
21
|
+
_source: SourceMeta;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const settingsCapability = defineCapability<Settings>({
|
|
25
|
+
id: "settings",
|
|
26
|
+
displayName: "Settings",
|
|
27
|
+
description: "Configuration settings from various sources",
|
|
28
|
+
// Settings are merged, not deduplicated by key
|
|
29
|
+
key: () => undefined,
|
|
30
|
+
validate: (settings) => {
|
|
31
|
+
if (!settings.path) return "Missing path";
|
|
32
|
+
if (!settings.data || typeof settings.data !== "object") return "Missing or invalid data";
|
|
33
|
+
return undefined;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills Capability
|
|
3
|
+
*
|
|
4
|
+
* Skills provide specialized knowledge or workflows that extend agent capabilities.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineCapability } from "./index";
|
|
8
|
+
import type { SourceMeta } from "./types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parsed frontmatter from a skill file.
|
|
12
|
+
*/
|
|
13
|
+
export interface SkillFrontmatter {
|
|
14
|
+
name?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
globs?: string[];
|
|
17
|
+
alwaysApply?: boolean;
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A skill that provides specialized knowledge or workflows.
|
|
23
|
+
*/
|
|
24
|
+
export interface Skill {
|
|
25
|
+
/** Skill name (unique key, derived from filename or frontmatter) */
|
|
26
|
+
name: string;
|
|
27
|
+
/** Absolute path to skill file */
|
|
28
|
+
path: string;
|
|
29
|
+
/** Skill content (markdown) */
|
|
30
|
+
content: string;
|
|
31
|
+
/** Parsed frontmatter */
|
|
32
|
+
frontmatter?: SkillFrontmatter;
|
|
33
|
+
/** Source level */
|
|
34
|
+
level: "user" | "project";
|
|
35
|
+
/** Source metadata */
|
|
36
|
+
_source: SourceMeta;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const skillCapability = defineCapability<Skill>({
|
|
40
|
+
id: "skills",
|
|
41
|
+
displayName: "Skills",
|
|
42
|
+
description: "Specialized knowledge and workflow files that extend agent capabilities",
|
|
43
|
+
key: (skill) => skill.name,
|
|
44
|
+
validate: (skill) => {
|
|
45
|
+
if (!skill.name) return "Missing skill name";
|
|
46
|
+
if (!skill.path) return "Missing skill path";
|
|
47
|
+
return undefined;
|
|
48
|
+
},
|
|
49
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash Commands Capability
|
|
3
|
+
*
|
|
4
|
+
* File-based slash commands defined as markdown files.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineCapability } from "./index";
|
|
8
|
+
import type { SourceMeta } from "./types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A file-based slash command.
|
|
12
|
+
*/
|
|
13
|
+
export interface SlashCommand {
|
|
14
|
+
/** Command name (without leading slash) */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Absolute path to command file */
|
|
17
|
+
path: string;
|
|
18
|
+
/** Command content (markdown template) */
|
|
19
|
+
content: string;
|
|
20
|
+
/** Source level */
|
|
21
|
+
level: "user" | "project" | "native";
|
|
22
|
+
/** Source metadata */
|
|
23
|
+
_source: SourceMeta;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const slashCommandCapability = defineCapability<SlashCommand>({
|
|
27
|
+
id: "slash-commands",
|
|
28
|
+
displayName: "Slash Commands",
|
|
29
|
+
description: "Custom slash commands defined as markdown files",
|
|
30
|
+
key: (cmd) => cmd.name,
|
|
31
|
+
validate: (cmd) => {
|
|
32
|
+
if (!cmd.name) return "Missing name";
|
|
33
|
+
if (!cmd.path) return "Missing path";
|
|
34
|
+
if (cmd.content === undefined) return "Missing content";
|
|
35
|
+
if (cmd.level !== "user" && cmd.level !== "project" && cmd.level !== "native") {
|
|
36
|
+
return "Invalid level: must be 'user', 'project', or 'native'";
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System Prompt Capability
|
|
3
|
+
*
|
|
4
|
+
* Custom system prompt files (SYSTEM.md) that modify the agent's base system prompt.
|
|
5
|
+
* Distinct from context-files which are user instructions shown in conversation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { defineCapability } from "./index";
|
|
9
|
+
import type { SourceMeta } from "./types";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A system prompt customization file.
|
|
13
|
+
*/
|
|
14
|
+
export interface SystemPrompt {
|
|
15
|
+
/** Absolute path to the file */
|
|
16
|
+
path: string;
|
|
17
|
+
/** File content */
|
|
18
|
+
content: string;
|
|
19
|
+
/** Which level this came from */
|
|
20
|
+
level: "user" | "project";
|
|
21
|
+
/** Source metadata */
|
|
22
|
+
_source: SourceMeta;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const systemPromptCapability = defineCapability<SystemPrompt>({
|
|
26
|
+
id: "system-prompt",
|
|
27
|
+
displayName: "System Prompt",
|
|
28
|
+
description: "Custom system prompt files (SYSTEM.md) that modify agent behavior",
|
|
29
|
+
key: (sp) => sp.level,
|
|
30
|
+
validate: (sp) => {
|
|
31
|
+
if (!sp.path) return "Missing path";
|
|
32
|
+
if (sp.content === undefined) return "Missing content";
|
|
33
|
+
return undefined;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Tools Capability
|
|
3
|
+
*
|
|
4
|
+
* User-defined tools that extend agent capabilities.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineCapability } from "./index";
|
|
8
|
+
import type { SourceMeta } from "./types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A custom tool definition.
|
|
12
|
+
*/
|
|
13
|
+
export interface CustomTool {
|
|
14
|
+
/** Tool name (unique key) */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Absolute path to tool definition file */
|
|
17
|
+
path: string;
|
|
18
|
+
/** Tool description */
|
|
19
|
+
description?: string;
|
|
20
|
+
/** Tool implementation (script path or inline) */
|
|
21
|
+
implementation?: string;
|
|
22
|
+
/** Source level */
|
|
23
|
+
level: "user" | "project";
|
|
24
|
+
/** Source metadata */
|
|
25
|
+
_source: SourceMeta;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const toolCapability = defineCapability<CustomTool>({
|
|
29
|
+
id: "tools",
|
|
30
|
+
displayName: "Custom Tools",
|
|
31
|
+
description: "User-defined tools that extend agent capabilities",
|
|
32
|
+
key: (tool) => tool.name,
|
|
33
|
+
validate: (tool) => {
|
|
34
|
+
if (!tool.name) return "Missing name";
|
|
35
|
+
if (!tool.path) return "Missing path";
|
|
36
|
+
return undefined;
|
|
37
|
+
},
|
|
38
|
+
});
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the capability-based config discovery system.
|
|
3
|
+
*
|
|
4
|
+
* This architecture inverts control: instead of callers knowing about paths like
|
|
5
|
+
* `.claude`, `.codex`, `.gemini`, they simply ask for `load("mcps")` and get back
|
|
6
|
+
* a unified array of MCP servers.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Context passed to every provider loader.
|
|
11
|
+
*/
|
|
12
|
+
export interface LoadContext {
|
|
13
|
+
/** Current working directory (project root) */
|
|
14
|
+
cwd: string;
|
|
15
|
+
/** User home directory */
|
|
16
|
+
home: string;
|
|
17
|
+
/** Filesystem helpers (cached) */
|
|
18
|
+
fs: {
|
|
19
|
+
exists(path: string): boolean;
|
|
20
|
+
isDir(path: string): boolean;
|
|
21
|
+
isFile(path: string): boolean;
|
|
22
|
+
readFile(path: string): string | null;
|
|
23
|
+
readDir(path: string): string[];
|
|
24
|
+
/** Walk up from cwd looking for a file/dir, returns first match */
|
|
25
|
+
walkUp(name: string, opts?: { file?: boolean; dir?: boolean }): string | null;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Result from a provider's load function.
|
|
31
|
+
*/
|
|
32
|
+
export interface LoadResult<T> {
|
|
33
|
+
items: T[];
|
|
34
|
+
/** Warnings encountered during loading (parse errors, etc.) */
|
|
35
|
+
warnings?: string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A provider that can load items for a capability.
|
|
40
|
+
*/
|
|
41
|
+
export interface Provider<T> {
|
|
42
|
+
/** Unique provider ID (e.g., "claude", "omp", "mcp-json", "agents-md") */
|
|
43
|
+
id: string;
|
|
44
|
+
|
|
45
|
+
/** Human-readable name for UI display (e.g., "Claude Code", "OpenAI Codex") */
|
|
46
|
+
displayName: string;
|
|
47
|
+
|
|
48
|
+
/** Short description for settings UI (e.g., "Load config from ~/.claude and .claude/") */
|
|
49
|
+
description: string;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Priority (higher = checked first, wins on conflicts).
|
|
53
|
+
* Suggested ranges:
|
|
54
|
+
* 100+ : Primary providers (omp, pi)
|
|
55
|
+
* 50-99: Tool-specific providers (claude, codex, gemini)
|
|
56
|
+
* 1-49 : Shared standards (mcp-json, agents-md)
|
|
57
|
+
*/
|
|
58
|
+
priority: number;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Load items for this capability.
|
|
62
|
+
* Returns items in provider's preferred order (usually project before user).
|
|
63
|
+
*/
|
|
64
|
+
load(ctx: LoadContext): LoadResult<T> | Promise<LoadResult<T>>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Options for loading a capability.
|
|
69
|
+
*/
|
|
70
|
+
export interface LoadOptions {
|
|
71
|
+
/** Only use these providers (by ID). Default: all registered */
|
|
72
|
+
providers?: string[];
|
|
73
|
+
/** Exclude these providers (by ID). Default: none */
|
|
74
|
+
excludeProviders?: string[];
|
|
75
|
+
/** Custom cwd. Default: process.cwd() */
|
|
76
|
+
cwd?: string;
|
|
77
|
+
/** Include items even if they fail validation. Default: false */
|
|
78
|
+
includeInvalid?: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Source metadata attached to every loaded item.
|
|
83
|
+
*/
|
|
84
|
+
export interface SourceMeta {
|
|
85
|
+
/** Provider ID that loaded this item */
|
|
86
|
+
provider: string;
|
|
87
|
+
/** Provider display name (for UI) */
|
|
88
|
+
providerName: string;
|
|
89
|
+
/** Absolute path to the source file */
|
|
90
|
+
path: string;
|
|
91
|
+
/** Whether this came from user-level, project-level, or native config */
|
|
92
|
+
level: "user" | "project" | "native";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Merged result from loading a capability across all providers.
|
|
97
|
+
*/
|
|
98
|
+
export interface CapabilityResult<T> {
|
|
99
|
+
/** Deduplicated items in priority order */
|
|
100
|
+
items: Array<T & { _source: SourceMeta }>;
|
|
101
|
+
/** All items including shadowed duplicates (for diagnostics) */
|
|
102
|
+
all: Array<T & { _source: SourceMeta; _shadowed?: boolean }>;
|
|
103
|
+
/** Warnings from all providers */
|
|
104
|
+
warnings: string[];
|
|
105
|
+
/** Which providers contributed items (IDs) */
|
|
106
|
+
providers: string[];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Definition of a capability.
|
|
111
|
+
*/
|
|
112
|
+
export interface Capability<T> {
|
|
113
|
+
/** Capability ID (e.g., "mcps", "skills", "context-files") */
|
|
114
|
+
id: string;
|
|
115
|
+
|
|
116
|
+
/** Human-readable name for UI display (e.g., "MCP Servers", "Skills") */
|
|
117
|
+
displayName: string;
|
|
118
|
+
|
|
119
|
+
/** Short description for settings/status UI */
|
|
120
|
+
description: string;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Extract a unique key from an item for deduplication.
|
|
124
|
+
* Items with the same key: first one wins (highest priority provider).
|
|
125
|
+
* Return undefined to never deduplicate (all items kept).
|
|
126
|
+
*/
|
|
127
|
+
key(item: T): string | undefined;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Optional validation. Return error message if invalid, undefined if valid.
|
|
131
|
+
*/
|
|
132
|
+
validate?(item: T): string | undefined;
|
|
133
|
+
|
|
134
|
+
/** Registered providers, sorted by priority (highest first) */
|
|
135
|
+
providers: Provider<T>[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Metadata about a capability (for introspection/UI).
|
|
140
|
+
*/
|
|
141
|
+
export interface CapabilityInfo {
|
|
142
|
+
id: string;
|
|
143
|
+
displayName: string;
|
|
144
|
+
description: string;
|
|
145
|
+
providers: Array<{
|
|
146
|
+
id: string;
|
|
147
|
+
displayName: string;
|
|
148
|
+
description: string;
|
|
149
|
+
priority: number;
|
|
150
|
+
enabled: boolean;
|
|
151
|
+
}>;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Metadata about a provider (for introspection/UI).
|
|
156
|
+
*/
|
|
157
|
+
export interface ProviderInfo {
|
|
158
|
+
id: string;
|
|
159
|
+
displayName: string;
|
|
160
|
+
description: string;
|
|
161
|
+
priority: number;
|
|
162
|
+
/** Which capabilities this provider is registered for */
|
|
163
|
+
capabilities: string[];
|
|
164
|
+
/** Whether this provider is currently enabled */
|
|
165
|
+
enabled: boolean;
|
|
166
|
+
}
|
package/src/cli/args.ts
CHANGED
|
@@ -153,8 +153,8 @@ ${chalk.bold("Usage:")}
|
|
|
153
153
|
|
|
154
154
|
${chalk.bold("Options:")}
|
|
155
155
|
--model <pattern> Model to use (fuzzy match: "opus", "gpt-5.2", or "p-openai/gpt-5.2")
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
--smol <id> Smol/fast model for lightweight tasks (or OMP_SMOL_MODEL env)
|
|
157
|
+
--slow <id> Slow/reasoning model for thorough analysis (or OMP_SLOW_MODEL env)
|
|
158
158
|
--api-key <key> API key (defaults to env vars)
|
|
159
159
|
--system-prompt <text> System prompt (default: coding assistant prompt)
|
|
160
160
|
--append-system-prompt <text> Append text or file contents to the system prompt
|
package/src/cli/plugin-cli.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plugin CLI command handlers.
|
|
3
3
|
*
|
|
4
|
-
* Handles `
|
|
4
|
+
* Handles `omp plugin <command>` subcommands for plugin lifecycle management.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import chalk from "chalk";
|
|
8
|
+
import { APP_NAME } from "../config";
|
|
8
9
|
import { PluginManager, parseSettingValue, validateSetting } from "../core/plugins/index";
|
|
9
10
|
|
|
10
11
|
// =============================================================================
|
|
@@ -153,12 +154,12 @@ async function handleInstall(
|
|
|
153
154
|
flags: { json?: boolean; force?: boolean; dryRun?: boolean },
|
|
154
155
|
): Promise<void> {
|
|
155
156
|
if (packages.length === 0) {
|
|
156
|
-
console.error(chalk.red(
|
|
157
|
+
console.error(chalk.red(`Usage: ${APP_NAME} plugin install <package[@version]>[features] ...`));
|
|
157
158
|
console.error(chalk.dim("Examples:"));
|
|
158
|
-
console.error(chalk.dim(
|
|
159
|
-
console.error(chalk.dim(
|
|
160
|
-
console.error(chalk.dim(
|
|
161
|
-
console.error(chalk.dim(
|
|
159
|
+
console.error(chalk.dim(` ${APP_NAME} plugin install @oh-my-pi/exa`));
|
|
160
|
+
console.error(chalk.dim(` ${APP_NAME} plugin install @oh-my-pi/exa[search,websets]`));
|
|
161
|
+
console.error(chalk.dim(` ${APP_NAME} plugin install @oh-my-pi/exa[*] # all features`));
|
|
162
|
+
console.error(chalk.dim(` ${APP_NAME} plugin install @oh-my-pi/exa[] # no optional features`));
|
|
162
163
|
process.exit(1);
|
|
163
164
|
}
|
|
164
165
|
|
|
@@ -190,7 +191,7 @@ async function handleInstall(
|
|
|
190
191
|
|
|
191
192
|
async function handleUninstall(manager: PluginManager, packages: string[], flags: { json?: boolean }): Promise<void> {
|
|
192
193
|
if (packages.length === 0) {
|
|
193
|
-
console.error(chalk.red(
|
|
194
|
+
console.error(chalk.red(`Usage: ${APP_NAME} plugin uninstall <package> ...`));
|
|
194
195
|
process.exit(1);
|
|
195
196
|
}
|
|
196
197
|
|
|
@@ -220,7 +221,7 @@ async function handleList(manager: PluginManager, flags: { json?: boolean }): Pr
|
|
|
220
221
|
|
|
221
222
|
if (plugins.length === 0) {
|
|
222
223
|
console.log(chalk.dim("No plugins installed"));
|
|
223
|
-
console.log(chalk.dim(
|
|
224
|
+
console.log(chalk.dim(`\nInstall plugins with: ${APP_NAME} plugin install <package>`));
|
|
224
225
|
return;
|
|
225
226
|
}
|
|
226
227
|
|
|
@@ -254,7 +255,7 @@ async function handleList(manager: PluginManager, flags: { json?: boolean }): Pr
|
|
|
254
255
|
|
|
255
256
|
async function handleLink(manager: PluginManager, paths: string[], flags: { json?: boolean }): Promise<void> {
|
|
256
257
|
if (paths.length === 0) {
|
|
257
|
-
console.error(chalk.red(
|
|
258
|
+
console.error(chalk.red(`Usage: ${APP_NAME} plugin link <path>`));
|
|
258
259
|
process.exit(1);
|
|
259
260
|
}
|
|
260
261
|
|
|
@@ -313,7 +314,9 @@ async function handleFeatures(
|
|
|
313
314
|
flags: { json?: boolean; enable?: string; disable?: string; set?: string },
|
|
314
315
|
): Promise<void> {
|
|
315
316
|
if (args.length === 0) {
|
|
316
|
-
console.error(
|
|
317
|
+
console.error(
|
|
318
|
+
chalk.red(`Usage: ${APP_NAME} plugin features <plugin> [--enable f1,f2] [--disable f1] [--set f1,f2]`),
|
|
319
|
+
);
|
|
317
320
|
process.exit(1);
|
|
318
321
|
}
|
|
319
322
|
|
|
@@ -404,7 +407,9 @@ async function handleConfig(
|
|
|
404
407
|
flags: { json?: boolean; local?: boolean },
|
|
405
408
|
): Promise<void> {
|
|
406
409
|
if (args.length === 0) {
|
|
407
|
-
console.error(
|
|
410
|
+
console.error(
|
|
411
|
+
chalk.red(`Usage: ${APP_NAME} plugin config <list|get|set|delete|validate> <plugin> [key] [value]`),
|
|
412
|
+
);
|
|
408
413
|
process.exit(1);
|
|
409
414
|
}
|
|
410
415
|
|
|
@@ -560,7 +565,7 @@ async function handleConfigValidate(manager: PluginManager, flags: { json?: bool
|
|
|
560
565
|
|
|
561
566
|
async function handleEnable(manager: PluginManager, plugins: string[], flags: { json?: boolean }): Promise<void> {
|
|
562
567
|
if (plugins.length === 0) {
|
|
563
|
-
console.error(chalk.red(
|
|
568
|
+
console.error(chalk.red(`Usage: ${APP_NAME} plugin enable <plugin> ...`));
|
|
564
569
|
process.exit(1);
|
|
565
570
|
}
|
|
566
571
|
|
|
@@ -582,7 +587,7 @@ async function handleEnable(manager: PluginManager, plugins: string[], flags: {
|
|
|
582
587
|
|
|
583
588
|
async function handleDisable(manager: PluginManager, plugins: string[], flags: { json?: boolean }): Promise<void> {
|
|
584
589
|
if (plugins.length === 0) {
|
|
585
|
-
console.error(chalk.red(
|
|
590
|
+
console.error(chalk.red(`Usage: ${APP_NAME} plugin disable <plugin> ...`));
|
|
586
591
|
process.exit(1);
|
|
587
592
|
}
|
|
588
593
|
|
|
@@ -607,7 +612,7 @@ async function handleDisable(manager: PluginManager, plugins: string[], flags: {
|
|
|
607
612
|
// =============================================================================
|
|
608
613
|
|
|
609
614
|
export function printPluginHelp(): void {
|
|
610
|
-
console.log(`${chalk.bold(
|
|
615
|
+
console.log(`${chalk.bold(`${APP_NAME} plugin`)} - Plugin lifecycle management
|
|
611
616
|
|
|
612
617
|
${chalk.bold("Commands:")}
|
|
613
618
|
install <pkg[@ver]>[features] Install plugins from npm
|
|
@@ -641,10 +646,10 @@ ${chalk.bold("Options:")}
|
|
|
641
646
|
-l, --local Use project-local overrides
|
|
642
647
|
|
|
643
648
|
${chalk.bold("Examples:")}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
+
${APP_NAME} plugin install @oh-my-pi/exa[search]
|
|
650
|
+
${APP_NAME} plugin list --json
|
|
651
|
+
${APP_NAME} plugin features my-plugin --enable search,web
|
|
652
|
+
${APP_NAME} plugin config set my-plugin apiKey sk-xxx
|
|
653
|
+
${APP_NAME} plugin doctor --fix
|
|
649
654
|
`);
|
|
650
655
|
}
|
package/src/cli/update-cli.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Update CLI command handler.
|
|
3
3
|
*
|
|
4
|
-
* Handles `
|
|
4
|
+
* Handles `omp update` to check for and install updates.
|
|
5
5
|
* Uses bun if available, otherwise downloads binary from GitHub releases.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@ import { dirname } from "node:path";
|
|
|
11
11
|
import { Readable } from "node:stream";
|
|
12
12
|
import { pipeline } from "node:stream/promises";
|
|
13
13
|
import chalk from "chalk";
|
|
14
|
-
import { VERSION } from "../config";
|
|
14
|
+
import { APP_NAME, VERSION } from "../config";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Detect if we're running as a Bun compiled binary.
|
|
@@ -129,9 +129,9 @@ function getBinaryName(): string {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
if (os === "windows") {
|
|
132
|
-
return
|
|
132
|
+
return `${APP_NAME}-${os}-${archName}.exe`;
|
|
133
133
|
}
|
|
134
|
-
return
|
|
134
|
+
return `${APP_NAME}-${os}-${archName}`;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/**
|
|
@@ -193,7 +193,7 @@ async function updateViaBinary(release: ReleaseInfo): Promise<void> {
|
|
|
193
193
|
unlinkSync(backupPath);
|
|
194
194
|
|
|
195
195
|
console.log(chalk.green(`\n✓ Updated to ${release.version}`));
|
|
196
|
-
console.log(chalk.dim(
|
|
196
|
+
console.log(chalk.dim(`Restart ${APP_NAME} to use the new version`));
|
|
197
197
|
} catch (err) {
|
|
198
198
|
// Restore from backup if possible
|
|
199
199
|
if (existsSync(backupPath) && !existsSync(execPath)) {
|
|
@@ -256,18 +256,18 @@ export async function runUpdateCommand(opts: { force: boolean; check: boolean })
|
|
|
256
256
|
* Print update command help.
|
|
257
257
|
*/
|
|
258
258
|
export function printUpdateHelp(): void {
|
|
259
|
-
console.log(`${chalk.bold(
|
|
259
|
+
console.log(`${chalk.bold(`${APP_NAME} update`)} - Check for and install updates
|
|
260
260
|
|
|
261
261
|
${chalk.bold("Usage:")}
|
|
262
|
-
|
|
262
|
+
${APP_NAME} update [options]
|
|
263
263
|
|
|
264
264
|
${chalk.bold("Options:")}
|
|
265
265
|
-c, --check Check for updates without installing
|
|
266
266
|
-f, --force Force reinstall even if up to date
|
|
267
267
|
|
|
268
268
|
${chalk.bold("Examples:")}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
${APP_NAME} update Update to latest version
|
|
270
|
+
${APP_NAME} update --check Check if updates are available
|
|
271
|
+
${APP_NAME} update --force Force reinstall
|
|
272
272
|
`);
|
|
273
273
|
}
|