@oh-my-pi/cli 0.1.0 → 0.3.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/.github/icon.png +0 -0
- package/.github/logo.png +0 -0
- package/.github/workflows/publish.yml +1 -1
- package/LICENSE +21 -0
- package/README.md +243 -138
- package/biome.json +1 -1
- package/bun.lock +59 -0
- package/dist/cli.js +6311 -2900
- package/dist/commands/config.d.ts +32 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/enable.d.ts +1 -0
- package/dist/commands/enable.d.ts.map +1 -1
- package/dist/commands/env.d.ts +14 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/features.d.ts +25 -0
- package/dist/commands/features.d.ts.map +1 -0
- package/dist/commands/info.d.ts +1 -0
- package/dist/commands/info.d.ts.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/install.d.ts +37 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/link.d.ts +2 -0
- package/dist/commands/link.d.ts.map +1 -1
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/outdated.d.ts +1 -0
- package/dist/commands/outdated.d.ts.map +1 -1
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/uninstall.d.ts +1 -0
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/why.d.ts +1 -0
- package/dist/commands/why.d.ts.map +1 -1
- package/dist/conflicts.d.ts +9 -1
- package/dist/conflicts.d.ts.map +1 -1
- package/dist/errors.d.ts +8 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +18 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/lock.d.ts +3 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lockfile.d.ts +52 -0
- package/dist/lockfile.d.ts.map +1 -0
- package/dist/manifest.d.ts +60 -25
- package/dist/manifest.d.ts.map +1 -1
- package/dist/npm.d.ts +14 -2
- package/dist/npm.d.ts.map +1 -1
- package/dist/paths.d.ts +34 -3
- package/dist/paths.d.ts.map +1 -1
- package/dist/runtime.d.ts +14 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/symlinks.d.ts +43 -7
- package/dist/symlinks.d.ts.map +1 -1
- package/package.json +11 -5
- package/plugins/exa/README.md +153 -0
- package/plugins/exa/package.json +56 -0
- package/plugins/exa/tools/exa/company.ts +35 -0
- package/plugins/exa/tools/exa/index.ts +66 -0
- package/plugins/exa/tools/exa/linkedin.ts +35 -0
- package/plugins/exa/tools/exa/researcher.ts +40 -0
- package/plugins/exa/tools/exa/runtime.json +4 -0
- package/plugins/exa/tools/exa/search.ts +46 -0
- package/plugins/exa/tools/exa/shared.ts +230 -0
- package/plugins/exa/tools/exa/websets.ts +62 -0
- package/plugins/metal-theme/package.json +7 -2
- package/plugins/subagents/package.json +7 -2
- package/plugins/user-prompt/README.md +130 -0
- package/plugins/user-prompt/package.json +19 -0
- package/plugins/user-prompt/tools/user-prompt/index.ts +235 -0
- package/src/cli.ts +133 -58
- package/src/commands/config.ts +384 -0
- package/src/commands/create.ts +51 -1
- package/src/commands/doctor.ts +95 -7
- package/src/commands/enable.ts +25 -8
- package/src/commands/env.ts +38 -0
- package/src/commands/features.ts +295 -0
- package/src/commands/info.ts +41 -5
- package/src/commands/init.ts +20 -2
- package/src/commands/install.ts +453 -80
- package/src/commands/link.ts +60 -9
- package/src/commands/list.ts +122 -7
- package/src/commands/outdated.ts +17 -6
- package/src/commands/search.ts +20 -3
- package/src/commands/uninstall.ts +57 -6
- package/src/commands/update.ts +67 -9
- package/src/commands/why.ts +47 -16
- package/src/conflicts.ts +33 -1
- package/src/errors.ts +22 -0
- package/src/index.ts +18 -25
- package/src/lock.ts +46 -0
- package/src/lockfile.ts +132 -0
- package/src/manifest.ts +219 -71
- package/src/npm.ts +74 -18
- package/src/paths.ts +77 -12
- package/src/runtime.ts +116 -0
- package/src/symlinks.ts +291 -35
- package/tsconfig.json +7 -3
- package/CHECK.md +0 -352
- package/dist/migrate.d.ts +0 -9
- package/dist/migrate.d.ts.map +0 -1
- package/src/migrate.ts +0 -181
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Prompt Tool - Ask questions to the user during execution
|
|
3
|
+
*
|
|
4
|
+
* Use this tool when you need to ask the user questions during execution.
|
|
5
|
+
* This allows you to:
|
|
6
|
+
* 1. Gather user preferences or requirements
|
|
7
|
+
* 2. Clarify ambiguous instructions
|
|
8
|
+
* 3. Get decisions on implementation choices as you work
|
|
9
|
+
* 4. Offer choices to the user about what direction to take
|
|
10
|
+
*
|
|
11
|
+
* Usage notes:
|
|
12
|
+
* - Users will always be able to select "Other" to provide custom text input
|
|
13
|
+
* - Use multi: true to allow multiple answers to be selected for a question
|
|
14
|
+
* - If you recommend a specific option, make that the first option in the list
|
|
15
|
+
* and add "(Recommended)" at the end of the label
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { Type } from "@sinclair/typebox";
|
|
19
|
+
import { Text } from "@mariozechner/pi-tui";
|
|
20
|
+
import type { CustomAgentTool, CustomToolFactory, ToolAPI } from "@mariozechner/pi-coding-agent";
|
|
21
|
+
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// Tool Definition
|
|
24
|
+
// =============================================================================
|
|
25
|
+
|
|
26
|
+
const OTHER_OPTION = "Other (type your own)";
|
|
27
|
+
|
|
28
|
+
const OptionItem = Type.Object({
|
|
29
|
+
label: Type.String({ description: "Display label for this option" }),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const UserPromptParams = Type.Object({
|
|
33
|
+
question: Type.String({ description: "The question to ask the user" }),
|
|
34
|
+
options: Type.Array(OptionItem, {
|
|
35
|
+
description: "Available options for the user to choose from.",
|
|
36
|
+
minItems: 1,
|
|
37
|
+
}),
|
|
38
|
+
multi: Type.Optional(Type.Boolean({
|
|
39
|
+
description: "Allow multiple options to be selected (default: false)",
|
|
40
|
+
default: false,
|
|
41
|
+
})),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
interface UserPromptDetails {
|
|
45
|
+
question: string;
|
|
46
|
+
options: string[];
|
|
47
|
+
multi: boolean;
|
|
48
|
+
selectedOptions: string[];
|
|
49
|
+
customInput?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const DESCRIPTION = `Use this tool when you need to ask the user questions during execution. This allows you to:
|
|
53
|
+
1. Gather user preferences or requirements
|
|
54
|
+
2. Clarify ambiguous instructions
|
|
55
|
+
3. Get decisions on implementation choices as you work
|
|
56
|
+
4. Offer choices to the user about what direction to take.
|
|
57
|
+
|
|
58
|
+
Usage notes:
|
|
59
|
+
- Users will always be able to select "Other" to provide custom text input
|
|
60
|
+
- Use multi: true to allow multiple answers to be selected for a question
|
|
61
|
+
- If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
|
|
62
|
+
|
|
63
|
+
Example usage:
|
|
64
|
+
|
|
65
|
+
<example>
|
|
66
|
+
assistant: Let me ask which features you want to include.
|
|
67
|
+
assistant: Uses the user_prompt tool:
|
|
68
|
+
{
|
|
69
|
+
"question": "Which features should I implement?",
|
|
70
|
+
"options": [
|
|
71
|
+
{"label": "Authentication"},
|
|
72
|
+
{"label": "API endpoints"},
|
|
73
|
+
{"label": "Database models"},
|
|
74
|
+
{"label": "Unit tests"},
|
|
75
|
+
{"label": "Documentation"}
|
|
76
|
+
],
|
|
77
|
+
"multi": true
|
|
78
|
+
}
|
|
79
|
+
</example>`;
|
|
80
|
+
|
|
81
|
+
const factory: CustomToolFactory = (pi: ToolAPI) => {
|
|
82
|
+
const tool: CustomAgentTool<typeof UserPromptParams, UserPromptDetails> = {
|
|
83
|
+
name: "user_prompt",
|
|
84
|
+
label: "User Prompt",
|
|
85
|
+
description: DESCRIPTION,
|
|
86
|
+
parameters: UserPromptParams,
|
|
87
|
+
|
|
88
|
+
async execute(_toolCallId, params, _signal, _onUpdate) {
|
|
89
|
+
const { question, options, multi = false } = params;
|
|
90
|
+
const optionLabels = options.map((o) => o.label);
|
|
91
|
+
|
|
92
|
+
if (!pi.hasUI) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: "text", text: "Error: User prompt requires interactive mode" }],
|
|
95
|
+
details: { question, options: optionLabels, multi, selectedOptions: [] },
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let selectedOptions: string[] = [];
|
|
100
|
+
let customInput: string | undefined;
|
|
101
|
+
|
|
102
|
+
if (multi) {
|
|
103
|
+
// Multi-select: show checkboxes in the label to indicate selection state
|
|
104
|
+
const DONE = "✓ Done selecting";
|
|
105
|
+
const selected = new Set<string>();
|
|
106
|
+
|
|
107
|
+
while (true) {
|
|
108
|
+
// Build options with checkbox indicators
|
|
109
|
+
const opts: string[] = [];
|
|
110
|
+
|
|
111
|
+
// Add "Done" option if any selected
|
|
112
|
+
if (selected.size > 0) {
|
|
113
|
+
opts.push(DONE);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Add all options with [X] or [ ] prefix
|
|
117
|
+
for (const opt of optionLabels) {
|
|
118
|
+
const checkbox = selected.has(opt) ? "[X]" : "[ ]";
|
|
119
|
+
opts.push(`${checkbox} ${opt}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Add "Other" option
|
|
123
|
+
opts.push(OTHER_OPTION);
|
|
124
|
+
|
|
125
|
+
const prefix = selected.size > 0 ? `(${selected.size} selected) ` : "";
|
|
126
|
+
const choice = await pi.ui.select(`${prefix}${question}`, opts);
|
|
127
|
+
|
|
128
|
+
if (choice === null || choice === DONE) break;
|
|
129
|
+
|
|
130
|
+
if (choice === OTHER_OPTION) {
|
|
131
|
+
const input = await pi.ui.input("Enter your response:");
|
|
132
|
+
if (input) customInput = input;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Toggle selection - extract the actual option name
|
|
137
|
+
const optMatch = choice.match(/^\[.\] (.+)$/);
|
|
138
|
+
if (optMatch) {
|
|
139
|
+
const opt = optMatch[1];
|
|
140
|
+
if (selected.has(opt)) {
|
|
141
|
+
selected.delete(opt);
|
|
142
|
+
} else {
|
|
143
|
+
selected.add(opt);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
selectedOptions = Array.from(selected);
|
|
148
|
+
} else {
|
|
149
|
+
// Single select with "Other" option
|
|
150
|
+
const choice = await pi.ui.select(question, [...optionLabels, OTHER_OPTION]);
|
|
151
|
+
if (choice === OTHER_OPTION) {
|
|
152
|
+
const input = await pi.ui.input("Enter your response:");
|
|
153
|
+
if (input) customInput = input;
|
|
154
|
+
} else if (choice) {
|
|
155
|
+
selectedOptions = [choice];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const details: UserPromptDetails = {
|
|
160
|
+
question,
|
|
161
|
+
options: optionLabels,
|
|
162
|
+
multi,
|
|
163
|
+
selectedOptions,
|
|
164
|
+
customInput,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
let responseText: string;
|
|
168
|
+
if (customInput) {
|
|
169
|
+
responseText = `User provided custom input: ${customInput}`;
|
|
170
|
+
} else if (selectedOptions.length > 0) {
|
|
171
|
+
responseText = multi
|
|
172
|
+
? `User selected: ${selectedOptions.join(", ")}`
|
|
173
|
+
: `User selected: ${selectedOptions[0]}`;
|
|
174
|
+
} else {
|
|
175
|
+
responseText = "User cancelled the selection";
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return { content: [{ type: "text", text: responseText }], details };
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
renderCall(args, t) {
|
|
182
|
+
if (!args.question) {
|
|
183
|
+
return new Text(t.fg("error", "user_prompt: no question provided"), 0, 0);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const multiTag = args.multi ? t.fg("muted", " [multi-select]") : "";
|
|
187
|
+
let text = t.fg("toolTitle", "? ") + t.fg("accent", args.question) + multiTag;
|
|
188
|
+
|
|
189
|
+
if (args.options?.length) {
|
|
190
|
+
for (const opt of args.options) {
|
|
191
|
+
text += "\n" + t.fg("dim", " ○ ") + t.fg("muted", opt.label);
|
|
192
|
+
}
|
|
193
|
+
text += "\n" + t.fg("dim", " ○ ") + t.fg("muted", "Other (custom input)");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return new Text(text, 0, 0);
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
renderResult(result, { expanded }, t) {
|
|
200
|
+
const { details } = result;
|
|
201
|
+
if (!details) {
|
|
202
|
+
const txt = result.content[0];
|
|
203
|
+
return new Text(txt?.type === "text" ? txt.text : "", 0, 0);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let text = t.fg("toolTitle", "? ") + t.fg("accent", details.question);
|
|
207
|
+
|
|
208
|
+
if (details.customInput) {
|
|
209
|
+
// Custom input provided
|
|
210
|
+
text += "\n" + t.fg("dim", " ⎿ ") + t.fg("success", details.customInput);
|
|
211
|
+
} else if (details.selectedOptions.length > 0) {
|
|
212
|
+
// Show only selected options
|
|
213
|
+
const selected = details.selectedOptions;
|
|
214
|
+
if (selected.length === 1) {
|
|
215
|
+
text += "\n" + t.fg("dim", " ⎿ ") + t.fg("success", selected[0]);
|
|
216
|
+
} else {
|
|
217
|
+
// Multiple selections
|
|
218
|
+
for (let i = 0; i < selected.length; i++) {
|
|
219
|
+
const isLast = i === selected.length - 1;
|
|
220
|
+
const branch = isLast ? "└─" : "├─";
|
|
221
|
+
text += "\n" + t.fg("dim", ` ${branch} `) + t.fg("success", selected[i]);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
} else {
|
|
225
|
+
text += "\n" + t.fg("dim", " ⎿ ") + t.fg("warning", "Cancelled");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return new Text(text, 0, 0);
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
return tool;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export default factory;
|
package/src/cli.ts
CHANGED
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
+
import { configCommand } from "@omp/commands/config";
|
|
4
|
+
import { createPlugin } from "@omp/commands/create";
|
|
5
|
+
import { runDoctor } from "@omp/commands/doctor";
|
|
6
|
+
import { disablePlugin, enablePlugin } from "@omp/commands/enable";
|
|
7
|
+
import { envCommand } from "@omp/commands/env";
|
|
8
|
+
import { featuresCommand } from "@omp/commands/features";
|
|
9
|
+
import { showInfo } from "@omp/commands/info";
|
|
10
|
+
import { initProject } from "@omp/commands/init";
|
|
11
|
+
import { installPlugin } from "@omp/commands/install";
|
|
12
|
+
import { linkPlugin } from "@omp/commands/link";
|
|
13
|
+
import { listPlugins } from "@omp/commands/list";
|
|
14
|
+
import { showOutdated } from "@omp/commands/outdated";
|
|
15
|
+
import { searchPlugins } from "@omp/commands/search";
|
|
16
|
+
import { uninstallPlugin } from "@omp/commands/uninstall";
|
|
17
|
+
import { updatePlugin } from "@omp/commands/update";
|
|
18
|
+
import { whyFile } from "@omp/commands/why";
|
|
19
|
+
import { withErrorHandling } from "@omp/errors";
|
|
20
|
+
import { checkNpmAvailable } from "@omp/npm";
|
|
21
|
+
import chalk from "chalk";
|
|
3
22
|
import { program } from "commander";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { searchPlugins } from "./commands/search.js";
|
|
14
|
-
import { uninstallPlugin } from "./commands/uninstall.js";
|
|
15
|
-
import { updatePlugin } from "./commands/update.js";
|
|
16
|
-
import { whyFile } from "./commands/why.js";
|
|
17
|
-
import { checkMigration, migrateToNpm } from "./migrate.js";
|
|
18
|
-
|
|
19
|
-
program.name("omp").description("Oh My Pi - Plugin manager for pi configuration").version("0.1.0");
|
|
20
|
-
|
|
21
|
-
// Check for migration on startup (only for commands that need it)
|
|
22
|
-
program.hook("preAction", async (thisCommand) => {
|
|
23
|
-
const migratingCommands = ["install", "uninstall", "update", "list", "link"];
|
|
24
|
-
if (migratingCommands.includes(thisCommand.name())) {
|
|
25
|
-
await checkMigration();
|
|
26
|
-
}
|
|
27
|
-
});
|
|
23
|
+
|
|
24
|
+
// Check npm availability at startup
|
|
25
|
+
const npmCheck = checkNpmAvailable();
|
|
26
|
+
if (!npmCheck.available) {
|
|
27
|
+
console.log(chalk.red(npmCheck.error));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
program.name("omp").description("Oh My Pi - Plugin manager for pi configuration").version("0.2.0");
|
|
28
32
|
|
|
29
33
|
// ============================================================================
|
|
30
34
|
// Core Commands
|
|
@@ -38,43 +42,50 @@ program
|
|
|
38
42
|
"after",
|
|
39
43
|
`
|
|
40
44
|
Examples:
|
|
41
|
-
$ omp install @oh-my-pi/subagents
|
|
42
|
-
$ omp install @oh-my-pi/
|
|
43
|
-
$ omp install @
|
|
44
|
-
$ omp install
|
|
45
|
-
$ omp install
|
|
45
|
+
$ omp install @oh-my-pi/subagents # Install from npm (all features)
|
|
46
|
+
$ omp install @oh-my-pi/exa[search] # Install with specific features
|
|
47
|
+
$ omp install @oh-my-pi/exa[search,websets] # Multiple features
|
|
48
|
+
$ omp install @oh-my-pi/exa[*] # Explicitly all features
|
|
49
|
+
$ omp install @oh-my-pi/exa[] # No optional features (core only)
|
|
50
|
+
$ omp install @oh-my-pi/subagents@^2.0.0 # Specific version range
|
|
51
|
+
$ omp install ./local/path # Local directory (copies)
|
|
52
|
+
$ omp install # Install all from plugins.json
|
|
46
53
|
`,
|
|
47
54
|
)
|
|
48
|
-
.option("-g, --global", "Install globally to ~/.pi
|
|
55
|
+
.option("-g, --global", "Install globally to ~/.pi")
|
|
56
|
+
.option("-l, --local", "Install to project-local .pi/")
|
|
49
57
|
.option("-S, --save", "Add to plugins.json")
|
|
50
58
|
.option("-D, --save-dev", "Add as dev dependency")
|
|
51
59
|
.option("--force", "Overwrite conflicts without prompting")
|
|
52
60
|
.option("--json", "Output as JSON")
|
|
53
|
-
.action(installPlugin);
|
|
61
|
+
.action(withErrorHandling(installPlugin));
|
|
54
62
|
|
|
55
63
|
program
|
|
56
64
|
.command("uninstall <name>")
|
|
57
65
|
.alias("rm")
|
|
58
66
|
.description("Remove plugin and its symlinks")
|
|
59
|
-
.option("-g, --global", "Uninstall from ~/.pi
|
|
67
|
+
.option("-g, --global", "Uninstall from ~/.pi")
|
|
68
|
+
.option("-l, --local", "Uninstall from project-local .pi/")
|
|
60
69
|
.option("--json", "Output as JSON")
|
|
61
|
-
.action(uninstallPlugin);
|
|
70
|
+
.action(withErrorHandling(uninstallPlugin));
|
|
62
71
|
|
|
63
72
|
program
|
|
64
73
|
.command("update [name]")
|
|
65
74
|
.alias("up")
|
|
66
75
|
.description("Update to latest within semver range")
|
|
67
|
-
.option("-g, --global", "Update global plugins
|
|
76
|
+
.option("-g, --global", "Update global plugins")
|
|
77
|
+
.option("-l, --local", "Update project-local plugins")
|
|
68
78
|
.option("--json", "Output as JSON")
|
|
69
|
-
.action(updatePlugin);
|
|
79
|
+
.action(withErrorHandling(updatePlugin));
|
|
70
80
|
|
|
71
81
|
program
|
|
72
82
|
.command("list")
|
|
73
83
|
.alias("ls")
|
|
74
84
|
.description("Show installed plugins")
|
|
75
|
-
.option("-g, --global", "List global plugins
|
|
85
|
+
.option("-g, --global", "List global plugins")
|
|
86
|
+
.option("-l, --local", "List project-local plugins")
|
|
76
87
|
.option("--json", "Output as JSON")
|
|
77
|
-
.action(listPlugins);
|
|
88
|
+
.action(withErrorHandling(listPlugins));
|
|
78
89
|
|
|
79
90
|
program
|
|
80
91
|
.command("link <path>")
|
|
@@ -87,8 +98,10 @@ so changes are reflected immediately without reinstalling.
|
|
|
87
98
|
`,
|
|
88
99
|
)
|
|
89
100
|
.option("-n, --name <name>", "Custom name for the plugin")
|
|
90
|
-
.option("-g, --global", "Link globally
|
|
91
|
-
.
|
|
101
|
+
.option("-g, --global", "Link globally")
|
|
102
|
+
.option("-l, --local", "Link to project-local .pi/")
|
|
103
|
+
.option("--force", "Overwrite existing npm-installed plugin")
|
|
104
|
+
.action(withErrorHandling(linkPlugin));
|
|
92
105
|
|
|
93
106
|
// ============================================================================
|
|
94
107
|
// New Commands
|
|
@@ -98,70 +111,132 @@ program
|
|
|
98
111
|
.command("init")
|
|
99
112
|
.description("Create .pi/plugins.json in current project")
|
|
100
113
|
.option("--force", "Overwrite existing plugins.json")
|
|
101
|
-
.action(initProject);
|
|
114
|
+
.action(withErrorHandling(initProject));
|
|
102
115
|
|
|
103
116
|
program
|
|
104
117
|
.command("search <query>")
|
|
105
118
|
.description("Search npm for omp-plugin keyword")
|
|
106
119
|
.option("--json", "Output as JSON")
|
|
107
120
|
.option("--limit <n>", "Maximum results to show", "20")
|
|
108
|
-
.action(
|
|
121
|
+
.action(
|
|
122
|
+
withErrorHandling((query, options) => searchPlugins(query, { ...options, limit: parseInt(options.limit, 10) })),
|
|
123
|
+
);
|
|
109
124
|
|
|
110
125
|
program
|
|
111
126
|
.command("info <package>")
|
|
112
127
|
.description("Show plugin details before install")
|
|
113
128
|
.option("--json", "Output as JSON")
|
|
114
129
|
.option("--versions", "Show available versions")
|
|
115
|
-
.
|
|
130
|
+
.option("--all-versions", "Show all published versions")
|
|
131
|
+
.action(withErrorHandling(showInfo));
|
|
116
132
|
|
|
117
133
|
program
|
|
118
134
|
.command("outdated")
|
|
119
135
|
.description("List plugins with newer versions")
|
|
120
|
-
.option("-g, --global", "Check global plugins
|
|
136
|
+
.option("-g, --global", "Check global plugins")
|
|
137
|
+
.option("-l, --local", "Check project-local plugins")
|
|
121
138
|
.option("--json", "Output as JSON")
|
|
122
|
-
.action(showOutdated);
|
|
139
|
+
.action(withErrorHandling(showOutdated));
|
|
123
140
|
|
|
124
141
|
program
|
|
125
142
|
.command("doctor")
|
|
126
143
|
.description("Check for broken symlinks, conflicts")
|
|
127
|
-
.option("-g, --global", "Check global plugins
|
|
144
|
+
.option("-g, --global", "Check global plugins")
|
|
145
|
+
.option("-l, --local", "Check project-local plugins")
|
|
128
146
|
.option("--fix", "Attempt to fix issues")
|
|
129
147
|
.option("--json", "Output as JSON")
|
|
130
|
-
.action(runDoctor);
|
|
148
|
+
.action(withErrorHandling(runDoctor));
|
|
131
149
|
|
|
132
150
|
program
|
|
133
151
|
.command("create <name>")
|
|
134
152
|
.description("Scaffold new plugin from template")
|
|
135
153
|
.option("-d, --description <desc>", "Plugin description")
|
|
136
154
|
.option("-a, --author <author>", "Plugin author")
|
|
137
|
-
.action(createPlugin);
|
|
155
|
+
.action(withErrorHandling(createPlugin));
|
|
138
156
|
|
|
139
157
|
program
|
|
140
158
|
.command("why <file>")
|
|
141
159
|
.description("Show which plugin installed a file")
|
|
142
|
-
.option("-g, --global", "Check global plugins
|
|
160
|
+
.option("-g, --global", "Check global plugins")
|
|
161
|
+
.option("-l, --local", "Check project-local plugins")
|
|
143
162
|
.option("--json", "Output as JSON")
|
|
144
|
-
.action(whyFile);
|
|
163
|
+
.action(withErrorHandling(whyFile));
|
|
145
164
|
|
|
146
165
|
program
|
|
147
166
|
.command("enable <name>")
|
|
148
167
|
.description("Enable a disabled plugin")
|
|
149
|
-
.option("-g, --global", "Target global plugins
|
|
168
|
+
.option("-g, --global", "Target global plugins")
|
|
169
|
+
.option("-l, --local", "Target project-local plugins")
|
|
150
170
|
.option("--json", "Output as JSON")
|
|
151
|
-
.action(enablePlugin);
|
|
171
|
+
.action(withErrorHandling(enablePlugin));
|
|
152
172
|
|
|
153
173
|
program
|
|
154
174
|
.command("disable <name>")
|
|
155
175
|
.description("Disable plugin without uninstalling")
|
|
156
|
-
.option("-g, --global", "Target global plugins
|
|
176
|
+
.option("-g, --global", "Target global plugins")
|
|
177
|
+
.option("-l, --local", "Target project-local plugins")
|
|
178
|
+
.option("--json", "Output as JSON")
|
|
179
|
+
.action(withErrorHandling(disablePlugin));
|
|
180
|
+
|
|
181
|
+
program
|
|
182
|
+
.command("features <name>")
|
|
183
|
+
.description("List or configure plugin features")
|
|
184
|
+
.addHelpText(
|
|
185
|
+
"after",
|
|
186
|
+
`
|
|
187
|
+
Examples:
|
|
188
|
+
$ omp features @oh-my-pi/exa # List available features
|
|
189
|
+
$ omp features @oh-my-pi/exa --enable websets # Enable a feature
|
|
190
|
+
$ omp features @oh-my-pi/exa --disable search # Disable a feature
|
|
191
|
+
$ omp features @oh-my-pi/exa --set search,websets # Set exact features
|
|
192
|
+
$ omp features @oh-my-pi/exa --set '*' # Enable all features
|
|
193
|
+
$ omp features @oh-my-pi/exa --set '' # Disable all optional features
|
|
194
|
+
`,
|
|
195
|
+
)
|
|
196
|
+
.option("-g, --global", "Target global plugins")
|
|
197
|
+
.option("-l, --local", "Target project-local plugins")
|
|
198
|
+
.option("--enable <features...>", "Enable specific features")
|
|
199
|
+
.option("--disable <features...>", "Disable specific features")
|
|
200
|
+
.option("--set <features>", "Set exact feature list (comma-separated, '*' for all, '' for none)")
|
|
157
201
|
.option("--json", "Output as JSON")
|
|
158
|
-
.action(
|
|
202
|
+
.action(withErrorHandling(featuresCommand));
|
|
159
203
|
|
|
160
204
|
program
|
|
161
|
-
.command("
|
|
162
|
-
.description("
|
|
163
|
-
.
|
|
164
|
-
|
|
165
|
-
|
|
205
|
+
.command("config <name> [key] [value]")
|
|
206
|
+
.description("Get or set plugin configuration variables")
|
|
207
|
+
.addHelpText(
|
|
208
|
+
"after",
|
|
209
|
+
`
|
|
210
|
+
Examples:
|
|
211
|
+
$ omp config @oh-my-pi/exa # List all variables
|
|
212
|
+
$ omp config @oh-my-pi/exa apiKey # Get value of apiKey
|
|
213
|
+
$ omp config @oh-my-pi/exa apiKey sk-xxx # Set apiKey to sk-xxx
|
|
214
|
+
$ omp config @oh-my-pi/exa apiKey --delete # Reset apiKey to default
|
|
215
|
+
`,
|
|
216
|
+
)
|
|
217
|
+
.option("-g, --global", "Target global plugins")
|
|
218
|
+
.option("-l, --local", "Target project-local plugins")
|
|
219
|
+
.option("--delete", "Delete/reset the variable to its default")
|
|
220
|
+
.option("--json", "Output as JSON")
|
|
221
|
+
.action(withErrorHandling(configCommand));
|
|
222
|
+
|
|
223
|
+
program
|
|
224
|
+
.command("env")
|
|
225
|
+
.description("Print plugin environment variables for shell eval")
|
|
226
|
+
.addHelpText(
|
|
227
|
+
"after",
|
|
228
|
+
`
|
|
229
|
+
Examples:
|
|
230
|
+
$ eval "$(omp env)" # Load env vars in current shell
|
|
231
|
+
$ omp env >> ~/.bashrc # Persist to shell config
|
|
232
|
+
$ omp env --fish | source # Fish shell syntax
|
|
233
|
+
$ omp env --json # JSON format for scripts
|
|
234
|
+
`,
|
|
235
|
+
)
|
|
236
|
+
.option("-g, --global", "Target global plugins")
|
|
237
|
+
.option("-l, --local", "Target project-local plugins")
|
|
238
|
+
.option("--fish", "Output fish shell syntax instead of POSIX")
|
|
239
|
+
.option("--json", "Output as JSON")
|
|
240
|
+
.action(withErrorHandling(envCommand));
|
|
166
241
|
|
|
167
242
|
program.parse();
|