@oh-my-pi/pi-coding-agent 11.0.3 → 11.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 +199 -49
- package/README.md +1 -1
- package/docs/config-usage.md +3 -4
- package/docs/sdk.md +6 -5
- package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
- package/examples/sdk/README.md +1 -1
- package/package.json +19 -11
- package/src/cli/args.ts +11 -94
- package/src/cli/config-cli.ts +1 -1
- package/src/cli/file-processor.ts +3 -3
- package/src/cli/oclif-help.ts +26 -0
- package/src/cli/web-search-cli.ts +148 -0
- package/src/cli.ts +8 -2
- package/src/commands/commit.ts +36 -0
- package/src/commands/config.ts +51 -0
- package/src/commands/grep.ts +41 -0
- package/src/commands/index/index.ts +136 -0
- package/src/commands/jupyter.ts +32 -0
- package/src/commands/plugin.ts +70 -0
- package/src/commands/setup.ts +39 -0
- package/src/commands/shell.ts +29 -0
- package/src/commands/stats.ts +29 -0
- package/src/commands/update.ts +21 -0
- package/src/commands/web-search.ts +50 -0
- package/src/commit/agentic/index.ts +3 -2
- package/src/commit/agentic/tools/analyze-file.ts +1 -3
- package/src/commit/git/errors.ts +4 -6
- package/src/commit/pipeline.ts +3 -2
- package/src/config/keybindings.ts +1 -3
- package/src/config/model-registry.ts +89 -162
- package/src/config/settings-schema.ts +10 -0
- package/src/config.ts +202 -132
- package/src/exa/mcp-client.ts +8 -41
- package/src/export/html/index.ts +1 -1
- package/src/extensibility/extensions/loader.ts +7 -10
- package/src/extensibility/extensions/runner.ts +5 -15
- package/src/extensibility/extensions/types.ts +1 -1
- package/src/extensibility/hooks/runner.ts +6 -9
- package/src/index.ts +0 -1
- package/src/ipy/kernel.ts +10 -22
- package/src/lsp/clients/biome-client.ts +4 -7
- package/src/lsp/clients/lsp-linter-client.ts +4 -6
- package/src/lsp/index.ts +5 -4
- package/src/lsp/utils.ts +18 -0
- package/src/main.ts +86 -181
- package/src/mcp/json-rpc.ts +2 -2
- package/src/mcp/transports/http.ts +12 -49
- package/src/modes/components/armin.ts +1 -3
- package/src/modes/components/assistant-message.ts +4 -4
- package/src/modes/components/bash-execution.ts +5 -3
- package/src/modes/components/branch-summary-message.ts +1 -3
- package/src/modes/components/compaction-summary-message.ts +1 -3
- package/src/modes/components/custom-message.ts +4 -5
- package/src/modes/components/extensions/extension-dashboard.ts +10 -16
- package/src/modes/components/extensions/extension-list.ts +5 -5
- package/src/modes/components/footer.ts +1 -4
- package/src/modes/components/hook-editor.ts +7 -32
- package/src/modes/components/hook-message.ts +4 -5
- package/src/modes/components/model-selector.ts +2 -2
- package/src/modes/components/plugin-settings.ts +16 -20
- package/src/modes/components/python-execution.ts +5 -5
- package/src/modes/components/session-selector.ts +6 -7
- package/src/modes/components/settings-defs.ts +49 -40
- package/src/modes/components/settings-selector.ts +8 -17
- package/src/modes/components/skill-message.ts +1 -3
- package/src/modes/components/status-line-segment-editor.ts +1 -3
- package/src/modes/components/status-line.ts +1 -3
- package/src/modes/components/todo-reminder.ts +5 -7
- package/src/modes/components/tree-selector.ts +10 -12
- package/src/modes/components/ttsr-notification.ts +1 -3
- package/src/modes/components/user-message-selector.ts +2 -4
- package/src/modes/components/welcome.ts +6 -18
- package/src/modes/controllers/event-controller.ts +1 -0
- package/src/modes/controllers/extension-ui-controller.ts +1 -1
- package/src/modes/controllers/input-controller.ts +7 -34
- package/src/modes/controllers/selector-controller.ts +3 -3
- package/src/modes/interactive-mode.ts +27 -1
- package/src/modes/rpc/rpc-client.ts +2 -5
- package/src/modes/rpc/rpc-mode.ts +2 -2
- package/src/modes/theme/theme.ts +2 -6
- package/src/modes/types.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +6 -1
- package/src/patch/index.ts +1 -4
- package/src/prompts/agents/explore.md +1 -0
- package/src/prompts/agents/frontmatter.md +2 -1
- package/src/prompts/agents/init.md +1 -0
- package/src/prompts/agents/plan.md +1 -0
- package/src/prompts/agents/reviewer.md +1 -0
- package/src/prompts/system/subagent-submit-reminder.md +2 -0
- package/src/prompts/system/subagent-system-prompt.md +2 -0
- package/src/prompts/system/subagent-user-prompt.md +8 -0
- package/src/prompts/system/system-prompt.md +5 -3
- package/src/prompts/system/web-search.md +6 -4
- package/src/prompts/tools/task.md +216 -163
- package/src/sdk.ts +11 -110
- package/src/session/agent-session.ts +117 -83
- package/src/session/auth-storage.ts +10 -51
- package/src/session/messages.ts +17 -3
- package/src/session/session-manager.ts +30 -30
- package/src/session/streaming-output.ts +1 -1
- package/src/ssh/ssh-executor.ts +6 -3
- package/src/task/agents.ts +2 -0
- package/src/task/discovery.ts +1 -1
- package/src/task/executor.ts +5 -10
- package/src/task/index.ts +43 -23
- package/src/task/render.ts +67 -64
- package/src/task/template.ts +17 -34
- package/src/task/types.ts +49 -22
- package/src/tools/ask.ts +1 -3
- package/src/tools/bash.ts +1 -4
- package/src/tools/browser.ts +5 -7
- package/src/tools/exit-plan-mode.ts +1 -4
- package/src/tools/fetch.ts +1 -3
- package/src/tools/find.ts +4 -3
- package/src/tools/gemini-image.ts +24 -55
- package/src/tools/grep.ts +4 -4
- package/src/tools/index.ts +12 -14
- package/src/tools/notebook.ts +1 -5
- package/src/tools/python.ts +4 -3
- package/src/tools/read.ts +2 -4
- package/src/tools/render-utils.ts +23 -0
- package/src/tools/ssh.ts +8 -12
- package/src/tools/todo-write.ts +1 -4
- package/src/tools/tool-errors.ts +1 -4
- package/src/tools/write.ts +1 -3
- package/src/utils/external-editor.ts +59 -0
- package/src/utils/file-mentions.ts +39 -1
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +4 -4
- package/src/web/search/auth.ts +3 -33
- package/src/web/search/index.ts +73 -139
- package/src/web/search/provider.ts +58 -0
- package/src/web/search/providers/anthropic.ts +53 -14
- package/src/web/search/providers/base.ts +22 -0
- package/src/web/search/providers/codex.ts +38 -16
- package/src/web/search/providers/exa.ts +30 -6
- package/src/web/search/providers/gemini.ts +56 -20
- package/src/web/search/providers/jina.ts +28 -5
- package/src/web/search/providers/perplexity.ts +103 -36
- package/src/web/search/render.ts +84 -74
- package/src/web/search/types.ts +285 -59
- package/src/migrations.ts +0 -175
- package/src/session/storage-migration.ts +0 -173
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Root command for the coding agent CLI.
|
|
3
|
+
*/
|
|
4
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
5
|
+
import { parseArgs } from "../../cli/args";
|
|
6
|
+
import { APP_NAME } from "../../config";
|
|
7
|
+
import { runRootCommand } from "../../main";
|
|
8
|
+
|
|
9
|
+
export default class Index extends Command {
|
|
10
|
+
static description = "AI coding assistant";
|
|
11
|
+
static hidden = true;
|
|
12
|
+
|
|
13
|
+
static args = {
|
|
14
|
+
messages: Args.string({
|
|
15
|
+
description: "Messages to send (prefix files with @)",
|
|
16
|
+
required: false,
|
|
17
|
+
multiple: true,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
static flags = {
|
|
22
|
+
model: Flags.string({
|
|
23
|
+
description: 'Model to use (fuzzy match: "opus", "gpt-5.2", or "p-openai/gpt-5.2")',
|
|
24
|
+
}),
|
|
25
|
+
smol: Flags.string({
|
|
26
|
+
description: "Smol/fast model for lightweight tasks (or PI_SMOL_MODEL env)",
|
|
27
|
+
}),
|
|
28
|
+
slow: Flags.string({
|
|
29
|
+
description: "Slow/reasoning model for thorough analysis (or PI_SLOW_MODEL env)",
|
|
30
|
+
}),
|
|
31
|
+
plan: Flags.string({
|
|
32
|
+
description: "Plan model for architectural planning (or PI_PLAN_MODEL env)",
|
|
33
|
+
}),
|
|
34
|
+
provider: Flags.string({
|
|
35
|
+
description: "Provider to use (legacy; prefer --model)",
|
|
36
|
+
}),
|
|
37
|
+
"api-key": Flags.string({
|
|
38
|
+
description: "API key (defaults to env vars)",
|
|
39
|
+
}),
|
|
40
|
+
"system-prompt": Flags.string({
|
|
41
|
+
description: "System prompt (default: coding assistant prompt)",
|
|
42
|
+
}),
|
|
43
|
+
"append-system-prompt": Flags.string({
|
|
44
|
+
description: "Append text or file contents to the system prompt",
|
|
45
|
+
}),
|
|
46
|
+
"allow-home": Flags.boolean({
|
|
47
|
+
description: "Allow starting in ~ without auto-switching to a temp dir",
|
|
48
|
+
}),
|
|
49
|
+
mode: Flags.string({
|
|
50
|
+
description: "Output mode: text (default), json, or rpc",
|
|
51
|
+
options: ["text", "json", "rpc"],
|
|
52
|
+
}),
|
|
53
|
+
print: Flags.boolean({
|
|
54
|
+
char: "p",
|
|
55
|
+
description: "Non-interactive mode: process prompt and exit",
|
|
56
|
+
}),
|
|
57
|
+
continue: Flags.boolean({
|
|
58
|
+
char: "c",
|
|
59
|
+
description: "Continue previous session",
|
|
60
|
+
}),
|
|
61
|
+
resume: Flags.boolean({
|
|
62
|
+
char: "r",
|
|
63
|
+
description: "Select a session to resume",
|
|
64
|
+
}),
|
|
65
|
+
session: Flags.string({
|
|
66
|
+
description: "Use specific session file",
|
|
67
|
+
}),
|
|
68
|
+
"session-dir": Flags.string({
|
|
69
|
+
description: "Directory for session storage and lookup",
|
|
70
|
+
}),
|
|
71
|
+
"no-session": Flags.boolean({
|
|
72
|
+
description: "Don't save session (ephemeral)",
|
|
73
|
+
}),
|
|
74
|
+
models: Flags.string({
|
|
75
|
+
description: "Comma-separated model patterns for Ctrl+P cycling",
|
|
76
|
+
}),
|
|
77
|
+
"no-tools": Flags.boolean({
|
|
78
|
+
description: "Disable all built-in tools",
|
|
79
|
+
}),
|
|
80
|
+
"no-lsp": Flags.boolean({
|
|
81
|
+
description: "Disable LSP tools, formatting, and diagnostics",
|
|
82
|
+
}),
|
|
83
|
+
tools: Flags.string({
|
|
84
|
+
description: "Comma-separated list of tools to enable (default: all)",
|
|
85
|
+
}),
|
|
86
|
+
thinking: Flags.string({
|
|
87
|
+
description: "Set thinking level: off, minimal, low, medium, high, xhigh",
|
|
88
|
+
options: ["off", "minimal", "low", "medium", "high", "xhigh"],
|
|
89
|
+
}),
|
|
90
|
+
hook: Flags.string({
|
|
91
|
+
description: "Load a hook/extension file (can be used multiple times)",
|
|
92
|
+
multiple: true,
|
|
93
|
+
}),
|
|
94
|
+
extension: Flags.string({
|
|
95
|
+
char: "e",
|
|
96
|
+
description: "Load an extension file (can be used multiple times)",
|
|
97
|
+
multiple: true,
|
|
98
|
+
}),
|
|
99
|
+
"no-extensions": Flags.boolean({
|
|
100
|
+
description: "Disable extension discovery (explicit -e paths still work)",
|
|
101
|
+
}),
|
|
102
|
+
"no-skills": Flags.boolean({
|
|
103
|
+
description: "Disable skills discovery and loading",
|
|
104
|
+
}),
|
|
105
|
+
skills: Flags.string({
|
|
106
|
+
description: "Comma-separated glob patterns to filter skills (e.g., git-*,docker)",
|
|
107
|
+
}),
|
|
108
|
+
export: Flags.string({
|
|
109
|
+
description: "Export session file to HTML and exit",
|
|
110
|
+
}),
|
|
111
|
+
"list-models": Flags.string({
|
|
112
|
+
description: "List available models (with optional fuzzy search)",
|
|
113
|
+
}),
|
|
114
|
+
"no-title": Flags.boolean({
|
|
115
|
+
description: "Disable title auto-generation",
|
|
116
|
+
}),
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
static examples = [
|
|
120
|
+
`# Interactive mode\n ${APP_NAME}`,
|
|
121
|
+
`# Interactive mode with initial prompt\n ${APP_NAME} "List all .ts files in src/"`,
|
|
122
|
+
`# Include files in initial message\n ${APP_NAME} @prompt.md @image.png "What color is the sky?"`,
|
|
123
|
+
`# Non-interactive mode (process and exit)\n ${APP_NAME} -p "List all .ts files in src/"`,
|
|
124
|
+
`# Continue previous session\n ${APP_NAME} --continue "What did we discuss?"`,
|
|
125
|
+
`# Use different model (fuzzy matching)\n ${APP_NAME} --model opus "Help me refactor this code"`,
|
|
126
|
+
`# Limit model cycling to specific models\n ${APP_NAME} --models claude-sonnet,claude-haiku,gpt-4o`,
|
|
127
|
+
`# Export a session file to HTML\n ${APP_NAME} --export ~/.omp/agent/sessions/--path--/session.jsonl`,
|
|
128
|
+
];
|
|
129
|
+
|
|
130
|
+
static strict = false;
|
|
131
|
+
|
|
132
|
+
async run(): Promise<void> {
|
|
133
|
+
const parsed = parseArgs(this.argv);
|
|
134
|
+
await runRootCommand(parsed, this.argv);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manage the shared Jupyter gateway.
|
|
3
|
+
*/
|
|
4
|
+
import { Args, Command } from "@oclif/core";
|
|
5
|
+
import { type JupyterAction, type JupyterCommandArgs, runJupyterCommand } from "../cli/jupyter-cli";
|
|
6
|
+
import { initTheme } from "../modes/theme/theme";
|
|
7
|
+
|
|
8
|
+
const ACTIONS: JupyterAction[] = ["kill", "status"];
|
|
9
|
+
|
|
10
|
+
export default class Jupyter extends Command {
|
|
11
|
+
static description = "Manage the shared Jupyter gateway";
|
|
12
|
+
|
|
13
|
+
static args = {
|
|
14
|
+
action: Args.string({
|
|
15
|
+
description: "Jupyter action",
|
|
16
|
+
required: false,
|
|
17
|
+
options: ACTIONS,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
async run(): Promise<void> {
|
|
22
|
+
const { args } = await this.parse(Jupyter);
|
|
23
|
+
const action = (args.action ?? "status") as JupyterAction;
|
|
24
|
+
|
|
25
|
+
const cmd: JupyterCommandArgs = {
|
|
26
|
+
action,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
await initTheme();
|
|
30
|
+
await runJupyterCommand(cmd);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manage plugins (install, uninstall, list, etc.).
|
|
3
|
+
*/
|
|
4
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
5
|
+
import { type PluginAction, type PluginCommandArgs, runPluginCommand } from "../cli/plugin-cli";
|
|
6
|
+
import { initTheme } from "../modes/theme/theme";
|
|
7
|
+
|
|
8
|
+
const ACTIONS: PluginAction[] = [
|
|
9
|
+
"install",
|
|
10
|
+
"uninstall",
|
|
11
|
+
"list",
|
|
12
|
+
"link",
|
|
13
|
+
"doctor",
|
|
14
|
+
"features",
|
|
15
|
+
"config",
|
|
16
|
+
"enable",
|
|
17
|
+
"disable",
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
export default class Plugin extends Command {
|
|
21
|
+
static description = "Manage plugins (install, uninstall, list, etc.)";
|
|
22
|
+
|
|
23
|
+
static args = {
|
|
24
|
+
action: Args.string({
|
|
25
|
+
description: "Plugin action",
|
|
26
|
+
required: false,
|
|
27
|
+
options: ACTIONS,
|
|
28
|
+
}),
|
|
29
|
+
targets: Args.string({
|
|
30
|
+
description: "Packages, paths, or plugin names",
|
|
31
|
+
required: false,
|
|
32
|
+
multiple: true,
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
static flags = {
|
|
37
|
+
json: Flags.boolean({ description: "Output JSON" }),
|
|
38
|
+
fix: Flags.boolean({ description: "Attempt to fix issues (doctor)" }),
|
|
39
|
+
force: Flags.boolean({ description: "Force install" }),
|
|
40
|
+
"dry-run": Flags.boolean({ description: "Show actions without applying changes" }),
|
|
41
|
+
local: Flags.boolean({ char: "l", description: "Operate on local plugin directory" }),
|
|
42
|
+
enable: Flags.string({ description: "Enable a feature" }),
|
|
43
|
+
disable: Flags.string({ description: "Disable a feature" }),
|
|
44
|
+
set: Flags.string({ description: "Set plugin config (key=value)" }),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
async run(): Promise<void> {
|
|
48
|
+
const { args, flags } = await this.parse(Plugin);
|
|
49
|
+
const action = (args.action ?? "list") as PluginAction;
|
|
50
|
+
|
|
51
|
+
const targets = Array.isArray(args.targets) ? args.targets : args.targets ? [args.targets] : [];
|
|
52
|
+
const cmd: PluginCommandArgs = {
|
|
53
|
+
action,
|
|
54
|
+
args: targets,
|
|
55
|
+
flags: {
|
|
56
|
+
json: flags.json,
|
|
57
|
+
fix: flags.fix,
|
|
58
|
+
force: flags.force,
|
|
59
|
+
dryRun: flags["dry-run"],
|
|
60
|
+
local: flags.local,
|
|
61
|
+
enable: flags.enable,
|
|
62
|
+
disable: flags.disable,
|
|
63
|
+
set: flags.set,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
await initTheme();
|
|
68
|
+
await runPluginCommand(cmd);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install dependencies for optional features.
|
|
3
|
+
*/
|
|
4
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
5
|
+
import { runSetupCommand, type SetupCommandArgs, type SetupComponent } from "../cli/setup-cli";
|
|
6
|
+
import { initTheme } from "../modes/theme/theme";
|
|
7
|
+
|
|
8
|
+
const COMPONENTS: SetupComponent[] = ["python"];
|
|
9
|
+
|
|
10
|
+
export default class Setup extends Command {
|
|
11
|
+
static description = "Install dependencies for optional features";
|
|
12
|
+
|
|
13
|
+
static args = {
|
|
14
|
+
component: Args.string({
|
|
15
|
+
description: "Component to install",
|
|
16
|
+
required: true,
|
|
17
|
+
options: COMPONENTS,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
static flags = {
|
|
22
|
+
check: Flags.boolean({ char: "c", description: "Check if dependencies are installed" }),
|
|
23
|
+
json: Flags.boolean({ description: "Output status as JSON" }),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
async run(): Promise<void> {
|
|
27
|
+
const { args, flags } = await this.parse(Setup);
|
|
28
|
+
const cmd: SetupCommandArgs = {
|
|
29
|
+
component: args.component as SetupComponent,
|
|
30
|
+
flags: {
|
|
31
|
+
json: flags.json,
|
|
32
|
+
check: flags.check,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
await initTheme();
|
|
37
|
+
await runSetupCommand(cmd);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive shell console.
|
|
3
|
+
*/
|
|
4
|
+
import { Command, Flags } from "@oclif/core";
|
|
5
|
+
import { runShellCommand, type ShellCommandArgs } from "../cli/shell-cli";
|
|
6
|
+
import { initTheme } from "../modes/theme/theme";
|
|
7
|
+
|
|
8
|
+
export default class Shell extends Command {
|
|
9
|
+
static description = "Interactive shell console";
|
|
10
|
+
|
|
11
|
+
static flags = {
|
|
12
|
+
cwd: Flags.string({ char: "C", description: "Set working directory for commands" }),
|
|
13
|
+
timeout: Flags.integer({ char: "t", description: "Timeout per command in milliseconds" }),
|
|
14
|
+
"no-snapshot": Flags.boolean({ description: "Skip sourcing snapshot from user shell" }),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async run(): Promise<void> {
|
|
18
|
+
const { flags } = await this.parse(Shell);
|
|
19
|
+
|
|
20
|
+
const cmd: ShellCommandArgs = {
|
|
21
|
+
cwd: flags.cwd,
|
|
22
|
+
timeoutMs: flags.timeout,
|
|
23
|
+
noSnapshot: flags["no-snapshot"],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
await initTheme();
|
|
27
|
+
await runShellCommand(cmd);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View usage statistics dashboard.
|
|
3
|
+
*/
|
|
4
|
+
import { Command, Flags } from "@oclif/core";
|
|
5
|
+
import { runStatsCommand, type StatsCommandArgs } from "../cli/stats-cli";
|
|
6
|
+
import { initTheme } from "../modes/theme/theme";
|
|
7
|
+
|
|
8
|
+
export default class Stats extends Command {
|
|
9
|
+
static description = "View usage statistics";
|
|
10
|
+
|
|
11
|
+
static flags = {
|
|
12
|
+
port: Flags.integer({ char: "p", description: "Port for the dashboard server", default: 3847 }),
|
|
13
|
+
json: Flags.boolean({ char: "j", description: "Output stats as JSON" }),
|
|
14
|
+
summary: Flags.boolean({ char: "s", description: "Print summary to console" }),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async run(): Promise<void> {
|
|
18
|
+
const { flags } = await this.parse(Stats);
|
|
19
|
+
|
|
20
|
+
const cmd: StatsCommandArgs = {
|
|
21
|
+
port: flags.port,
|
|
22
|
+
json: flags.json,
|
|
23
|
+
summary: flags.summary,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
await initTheme();
|
|
27
|
+
await runStatsCommand(cmd);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check for and install updates.
|
|
3
|
+
*/
|
|
4
|
+
import { Command, Flags } from "@oclif/core";
|
|
5
|
+
import { runUpdateCommand } from "../cli/update-cli";
|
|
6
|
+
import { initTheme } from "../modes/theme/theme";
|
|
7
|
+
|
|
8
|
+
export default class Update extends Command {
|
|
9
|
+
static description = "Check for and install updates";
|
|
10
|
+
|
|
11
|
+
static flags = {
|
|
12
|
+
force: Flags.boolean({ char: "f", description: "Force update" }),
|
|
13
|
+
check: Flags.boolean({ char: "c", description: "Check for updates without installing" }),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
async run(): Promise<void> {
|
|
17
|
+
const { flags } = await this.parse(Update);
|
|
18
|
+
await initTheme();
|
|
19
|
+
await runUpdateCommand({ force: flags.force, check: flags.check });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test web search providers.
|
|
3
|
+
*/
|
|
4
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
5
|
+
import { runSearchCommand, type SearchCommandArgs } from "../cli/web-search-cli";
|
|
6
|
+
import type { SearchProviderId } from "../web/search/types";
|
|
7
|
+
|
|
8
|
+
const PROVIDERS: Array<SearchProviderId | "auto"> = [
|
|
9
|
+
"auto",
|
|
10
|
+
"anthropic",
|
|
11
|
+
"perplexity",
|
|
12
|
+
"exa",
|
|
13
|
+
"jina",
|
|
14
|
+
"gemini",
|
|
15
|
+
"codex",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const RECENCY: NonNullable<SearchCommandArgs["recency"]>[] = ["day", "week", "month", "year"];
|
|
19
|
+
|
|
20
|
+
export default class Search extends Command {
|
|
21
|
+
static description = "Test web search providers";
|
|
22
|
+
|
|
23
|
+
static aliases = ["q"];
|
|
24
|
+
|
|
25
|
+
static args = {
|
|
26
|
+
query: Args.string({ description: "Search query text", required: false, multiple: true }),
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
static flags = {
|
|
30
|
+
provider: Flags.string({ description: "Search provider", options: PROVIDERS }),
|
|
31
|
+
recency: Flags.string({ description: "Recency filter", options: RECENCY }),
|
|
32
|
+
limit: Flags.integer({ char: "l", description: "Max results to return" }),
|
|
33
|
+
compact: Flags.boolean({ description: "Render condensed output" }),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
async run(): Promise<void> {
|
|
37
|
+
const { args, flags } = await this.parse(Search);
|
|
38
|
+
const query = Array.isArray(args.query) ? args.query.join(" ") : (args.query ?? "");
|
|
39
|
+
|
|
40
|
+
const cmd: SearchCommandArgs = {
|
|
41
|
+
query,
|
|
42
|
+
provider: flags.provider as SearchProviderId | "auto" | undefined,
|
|
43
|
+
recency: flags.recency as SearchCommandArgs["recency"],
|
|
44
|
+
limit: flags.limit,
|
|
45
|
+
expanded: !flags.compact,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
await runSearchCommand(cmd);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -8,9 +8,10 @@ import { ControlledGit } from "../../commit/git";
|
|
|
8
8
|
import { formatCommitMessage } from "../../commit/message";
|
|
9
9
|
import { resolvePrimaryModel, resolveSmolModel } from "../../commit/model-selection";
|
|
10
10
|
import type { CommitCommandArgs, ConventionalAnalysis } from "../../commit/types";
|
|
11
|
+
import { ModelRegistry } from "../../config/model-registry";
|
|
11
12
|
import { renderPromptTemplate } from "../../config/prompt-templates";
|
|
12
13
|
import { Settings } from "../../config/settings";
|
|
13
|
-
import { discoverAuthStorage, discoverContextFiles
|
|
14
|
+
import { discoverAuthStorage, discoverContextFiles } from "../../sdk";
|
|
14
15
|
import { type ExistingChangelogEntries, runCommitAgentSession } from "./agent";
|
|
15
16
|
import { generateFallbackProposal } from "./fallback";
|
|
16
17
|
import splitConfirmPrompt from "./prompts/split-confirm.md" with { type: "text" };
|
|
@@ -31,7 +32,7 @@ export async function runAgenticCommit(args: CommitCommandArgs): Promise<void> {
|
|
|
31
32
|
const settings = settingsInstance;
|
|
32
33
|
|
|
33
34
|
writeStdout("● Resolving model...");
|
|
34
|
-
const modelRegistry =
|
|
35
|
+
const modelRegistry = new ModelRegistry(authStorage);
|
|
35
36
|
const stagedFilesPromise = (async () => {
|
|
36
37
|
let stagedFiles = await git.getStagedFiles();
|
|
37
38
|
if (stagedFiles.length === 0) {
|
|
@@ -62,7 +62,6 @@ export function createAnalyzeFileTool(options: {
|
|
|
62
62
|
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
|
63
63
|
const toolSession = buildToolSession(ctx, options);
|
|
64
64
|
const taskTool = await TaskTool.create(toolSession);
|
|
65
|
-
const context = "{{prompt}}";
|
|
66
65
|
const numstat = options.state.overview?.numstat ?? [];
|
|
67
66
|
const tasks = params.files.map((file, index) => {
|
|
68
67
|
const relatedFiles = formatRelatedFiles(params.files, file, numstat);
|
|
@@ -74,12 +73,11 @@ export function createAnalyzeFileTool(options: {
|
|
|
74
73
|
return {
|
|
75
74
|
id: `AnalyzeFile${index + 1}`,
|
|
76
75
|
description: `Analyze ${file}`,
|
|
77
|
-
|
|
76
|
+
assignment: prompt,
|
|
78
77
|
};
|
|
79
78
|
});
|
|
80
79
|
const taskParams: TaskParams = {
|
|
81
80
|
agent: "quick_task",
|
|
82
|
-
context,
|
|
83
81
|
schema: analyzeFileOutputSchema,
|
|
84
82
|
tasks,
|
|
85
83
|
};
|
package/src/commit/git/errors.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
export class GitError extends Error {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
constructor(
|
|
3
|
+
readonly command: string,
|
|
4
|
+
readonly stderr: string,
|
|
5
|
+
) {
|
|
6
6
|
super(`${command} failed: ${stderr || "unknown error"}`);
|
|
7
|
-
this.command = command;
|
|
8
|
-
this.stderr = stderr;
|
|
9
7
|
this.name = "GitError";
|
|
10
8
|
}
|
|
11
9
|
}
|
package/src/commit/pipeline.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
4
|
+
import { ModelRegistry } from "../config/model-registry";
|
|
4
5
|
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
5
6
|
import { Settings } from "../config/settings";
|
|
6
|
-
import { discoverAuthStorage
|
|
7
|
+
import { discoverAuthStorage } from "../sdk";
|
|
7
8
|
import { loadProjectContextFiles } from "../system-prompt";
|
|
8
9
|
import { runAgenticCommit } from "./agentic";
|
|
9
10
|
import {
|
|
@@ -41,7 +42,7 @@ async function runLegacyCommitCommand(args: CommitCommandArgs): Promise<void> {
|
|
|
41
42
|
const settingsInstance = await Settings.init();
|
|
42
43
|
const commitSettings = settingsInstance.getGroup("commit");
|
|
43
44
|
const authStorage = await discoverAuthStorage();
|
|
44
|
-
const modelRegistry =
|
|
45
|
+
const modelRegistry = new ModelRegistry(authStorage);
|
|
45
46
|
|
|
46
47
|
const { model: primaryModel, apiKey: primaryApiKey } = await resolvePrimaryModel(
|
|
47
48
|
args.model,
|
|
@@ -151,11 +151,9 @@ export function formatKeyHints(keys: KeyId | KeyId[]): string {
|
|
|
151
151
|
* Manages all keybindings (app + editor).
|
|
152
152
|
*/
|
|
153
153
|
export class KeybindingsManager {
|
|
154
|
-
private config: KeybindingsConfig;
|
|
155
154
|
private appActionToKeys: Map<AppAction, KeyId[]>;
|
|
156
155
|
|
|
157
|
-
private constructor(config: KeybindingsConfig) {
|
|
158
|
-
this.config = config;
|
|
156
|
+
private constructor(private readonly config: KeybindingsConfig) {
|
|
159
157
|
this.appActionToKeys = new Map();
|
|
160
158
|
this.buildMaps();
|
|
161
159
|
}
|