@oh-my-pi/cli 0.1.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.
Files changed (89) hide show
  1. package/.github/workflows/ci.yml +32 -0
  2. package/.github/workflows/publish.yml +42 -0
  3. package/CHECK.md +352 -0
  4. package/README.md +224 -0
  5. package/biome.json +29 -0
  6. package/bun.lock +50 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +3941 -0
  10. package/dist/commands/create.d.ts +9 -0
  11. package/dist/commands/create.d.ts.map +1 -0
  12. package/dist/commands/doctor.d.ts +10 -0
  13. package/dist/commands/doctor.d.ts.map +1 -0
  14. package/dist/commands/enable.d.ts +13 -0
  15. package/dist/commands/enable.d.ts.map +1 -0
  16. package/dist/commands/info.d.ts +9 -0
  17. package/dist/commands/info.d.ts.map +1 -0
  18. package/dist/commands/init.d.ts +8 -0
  19. package/dist/commands/init.d.ts.map +1 -0
  20. package/dist/commands/install.d.ts +13 -0
  21. package/dist/commands/install.d.ts.map +1 -0
  22. package/dist/commands/link.d.ts +10 -0
  23. package/dist/commands/link.d.ts.map +1 -0
  24. package/dist/commands/list.d.ts +9 -0
  25. package/dist/commands/list.d.ts.map +1 -0
  26. package/dist/commands/outdated.d.ts +9 -0
  27. package/dist/commands/outdated.d.ts.map +1 -0
  28. package/dist/commands/search.d.ts +9 -0
  29. package/dist/commands/search.d.ts.map +1 -0
  30. package/dist/commands/uninstall.d.ts +9 -0
  31. package/dist/commands/uninstall.d.ts.map +1 -0
  32. package/dist/commands/update.d.ts +9 -0
  33. package/dist/commands/update.d.ts.map +1 -0
  34. package/dist/commands/why.d.ts +9 -0
  35. package/dist/commands/why.d.ts.map +1 -0
  36. package/dist/conflicts.d.ts +21 -0
  37. package/dist/conflicts.d.ts.map +1 -0
  38. package/dist/index.d.ts +20 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/manifest.d.ts +81 -0
  41. package/dist/manifest.d.ts.map +1 -0
  42. package/dist/migrate.d.ts +9 -0
  43. package/dist/migrate.d.ts.map +1 -0
  44. package/dist/npm.d.ts +77 -0
  45. package/dist/npm.d.ts.map +1 -0
  46. package/dist/paths.d.ts +27 -0
  47. package/dist/paths.d.ts.map +1 -0
  48. package/dist/symlinks.d.ts +33 -0
  49. package/dist/symlinks.d.ts.map +1 -0
  50. package/package.json +36 -0
  51. package/plugins/metal-theme/README.md +13 -0
  52. package/plugins/metal-theme/omp.json +8 -0
  53. package/plugins/metal-theme/package.json +14 -0
  54. package/plugins/metal-theme/themes/metal.json +79 -0
  55. package/plugins/subagents/README.md +25 -0
  56. package/plugins/subagents/agents/explore.md +71 -0
  57. package/plugins/subagents/agents/planner.md +51 -0
  58. package/plugins/subagents/agents/reviewer.md +53 -0
  59. package/plugins/subagents/agents/task.md +46 -0
  60. package/plugins/subagents/commands/architect-plan.md +9 -0
  61. package/plugins/subagents/commands/implement-with-critic.md +10 -0
  62. package/plugins/subagents/commands/implement.md +10 -0
  63. package/plugins/subagents/omp.json +15 -0
  64. package/plugins/subagents/package.json +21 -0
  65. package/plugins/subagents/tools/task/index.ts +1019 -0
  66. package/scripts/bump-version.sh +52 -0
  67. package/scripts/publish.sh +35 -0
  68. package/src/cli.ts +167 -0
  69. package/src/commands/create.ts +153 -0
  70. package/src/commands/doctor.ts +217 -0
  71. package/src/commands/enable.ts +105 -0
  72. package/src/commands/info.ts +84 -0
  73. package/src/commands/init.ts +42 -0
  74. package/src/commands/install.ts +327 -0
  75. package/src/commands/link.ts +108 -0
  76. package/src/commands/list.ts +71 -0
  77. package/src/commands/outdated.ts +76 -0
  78. package/src/commands/search.ts +60 -0
  79. package/src/commands/uninstall.ts +73 -0
  80. package/src/commands/update.ts +112 -0
  81. package/src/commands/why.ts +105 -0
  82. package/src/conflicts.ts +84 -0
  83. package/src/index.ts +53 -0
  84. package/src/manifest.ts +212 -0
  85. package/src/migrate.ts +181 -0
  86. package/src/npm.ts +150 -0
  87. package/src/paths.ts +72 -0
  88. package/src/symlinks.ts +199 -0
  89. package/tsconfig.json +24 -0
package/dist/cli.js ADDED
@@ -0,0 +1,3941 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __toESM = (mod, isNodeMode, target) => {
9
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
10
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
+ for (let key of __getOwnPropNames(mod))
12
+ if (!__hasOwnProp.call(to, key))
13
+ __defProp(to, key, {
14
+ get: () => mod[key],
15
+ enumerable: true
16
+ });
17
+ return to;
18
+ };
19
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
20
+ var __require = import.meta.require;
21
+
22
+ // node_modules/commander/lib/error.js
23
+ var require_error = __commonJS((exports) => {
24
+ class CommanderError extends Error {
25
+ constructor(exitCode, code, message) {
26
+ super(message);
27
+ Error.captureStackTrace(this, this.constructor);
28
+ this.name = this.constructor.name;
29
+ this.code = code;
30
+ this.exitCode = exitCode;
31
+ this.nestedError = undefined;
32
+ }
33
+ }
34
+
35
+ class InvalidArgumentError extends CommanderError {
36
+ constructor(message) {
37
+ super(1, "commander.invalidArgument", message);
38
+ Error.captureStackTrace(this, this.constructor);
39
+ this.name = this.constructor.name;
40
+ }
41
+ }
42
+ exports.CommanderError = CommanderError;
43
+ exports.InvalidArgumentError = InvalidArgumentError;
44
+ });
45
+
46
+ // node_modules/commander/lib/argument.js
47
+ var require_argument = __commonJS((exports) => {
48
+ var { InvalidArgumentError } = require_error();
49
+
50
+ class Argument {
51
+ constructor(name, description) {
52
+ this.description = description || "";
53
+ this.variadic = false;
54
+ this.parseArg = undefined;
55
+ this.defaultValue = undefined;
56
+ this.defaultValueDescription = undefined;
57
+ this.argChoices = undefined;
58
+ switch (name[0]) {
59
+ case "<":
60
+ this.required = true;
61
+ this._name = name.slice(1, -1);
62
+ break;
63
+ case "[":
64
+ this.required = false;
65
+ this._name = name.slice(1, -1);
66
+ break;
67
+ default:
68
+ this.required = true;
69
+ this._name = name;
70
+ break;
71
+ }
72
+ if (this._name.length > 3 && this._name.slice(-3) === "...") {
73
+ this.variadic = true;
74
+ this._name = this._name.slice(0, -3);
75
+ }
76
+ }
77
+ name() {
78
+ return this._name;
79
+ }
80
+ _concatValue(value, previous) {
81
+ if (previous === this.defaultValue || !Array.isArray(previous)) {
82
+ return [value];
83
+ }
84
+ return previous.concat(value);
85
+ }
86
+ default(value, description) {
87
+ this.defaultValue = value;
88
+ this.defaultValueDescription = description;
89
+ return this;
90
+ }
91
+ argParser(fn) {
92
+ this.parseArg = fn;
93
+ return this;
94
+ }
95
+ choices(values) {
96
+ this.argChoices = values.slice();
97
+ this.parseArg = (arg, previous) => {
98
+ if (!this.argChoices.includes(arg)) {
99
+ throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(", ")}.`);
100
+ }
101
+ if (this.variadic) {
102
+ return this._concatValue(arg, previous);
103
+ }
104
+ return arg;
105
+ };
106
+ return this;
107
+ }
108
+ argRequired() {
109
+ this.required = true;
110
+ return this;
111
+ }
112
+ argOptional() {
113
+ this.required = false;
114
+ return this;
115
+ }
116
+ }
117
+ function humanReadableArgName(arg) {
118
+ const nameOutput = arg.name() + (arg.variadic === true ? "..." : "");
119
+ return arg.required ? "<" + nameOutput + ">" : "[" + nameOutput + "]";
120
+ }
121
+ exports.Argument = Argument;
122
+ exports.humanReadableArgName = humanReadableArgName;
123
+ });
124
+
125
+ // node_modules/commander/lib/help.js
126
+ var require_help = __commonJS((exports) => {
127
+ var { humanReadableArgName } = require_argument();
128
+
129
+ class Help {
130
+ constructor() {
131
+ this.helpWidth = undefined;
132
+ this.sortSubcommands = false;
133
+ this.sortOptions = false;
134
+ this.showGlobalOptions = false;
135
+ }
136
+ visibleCommands(cmd) {
137
+ const visibleCommands = cmd.commands.filter((cmd2) => !cmd2._hidden);
138
+ const helpCommand = cmd._getHelpCommand();
139
+ if (helpCommand && !helpCommand._hidden) {
140
+ visibleCommands.push(helpCommand);
141
+ }
142
+ if (this.sortSubcommands) {
143
+ visibleCommands.sort((a, b) => {
144
+ return a.name().localeCompare(b.name());
145
+ });
146
+ }
147
+ return visibleCommands;
148
+ }
149
+ compareOptions(a, b) {
150
+ const getSortKey = (option) => {
151
+ return option.short ? option.short.replace(/^-/, "") : option.long.replace(/^--/, "");
152
+ };
153
+ return getSortKey(a).localeCompare(getSortKey(b));
154
+ }
155
+ visibleOptions(cmd) {
156
+ const visibleOptions = cmd.options.filter((option) => !option.hidden);
157
+ const helpOption = cmd._getHelpOption();
158
+ if (helpOption && !helpOption.hidden) {
159
+ const removeShort = helpOption.short && cmd._findOption(helpOption.short);
160
+ const removeLong = helpOption.long && cmd._findOption(helpOption.long);
161
+ if (!removeShort && !removeLong) {
162
+ visibleOptions.push(helpOption);
163
+ } else if (helpOption.long && !removeLong) {
164
+ visibleOptions.push(cmd.createOption(helpOption.long, helpOption.description));
165
+ } else if (helpOption.short && !removeShort) {
166
+ visibleOptions.push(cmd.createOption(helpOption.short, helpOption.description));
167
+ }
168
+ }
169
+ if (this.sortOptions) {
170
+ visibleOptions.sort(this.compareOptions);
171
+ }
172
+ return visibleOptions;
173
+ }
174
+ visibleGlobalOptions(cmd) {
175
+ if (!this.showGlobalOptions)
176
+ return [];
177
+ const globalOptions = [];
178
+ for (let ancestorCmd = cmd.parent;ancestorCmd; ancestorCmd = ancestorCmd.parent) {
179
+ const visibleOptions = ancestorCmd.options.filter((option) => !option.hidden);
180
+ globalOptions.push(...visibleOptions);
181
+ }
182
+ if (this.sortOptions) {
183
+ globalOptions.sort(this.compareOptions);
184
+ }
185
+ return globalOptions;
186
+ }
187
+ visibleArguments(cmd) {
188
+ if (cmd._argsDescription) {
189
+ cmd.registeredArguments.forEach((argument) => {
190
+ argument.description = argument.description || cmd._argsDescription[argument.name()] || "";
191
+ });
192
+ }
193
+ if (cmd.registeredArguments.find((argument) => argument.description)) {
194
+ return cmd.registeredArguments;
195
+ }
196
+ return [];
197
+ }
198
+ subcommandTerm(cmd) {
199
+ const args = cmd.registeredArguments.map((arg) => humanReadableArgName(arg)).join(" ");
200
+ return cmd._name + (cmd._aliases[0] ? "|" + cmd._aliases[0] : "") + (cmd.options.length ? " [options]" : "") + (args ? " " + args : "");
201
+ }
202
+ optionTerm(option) {
203
+ return option.flags;
204
+ }
205
+ argumentTerm(argument) {
206
+ return argument.name();
207
+ }
208
+ longestSubcommandTermLength(cmd, helper) {
209
+ return helper.visibleCommands(cmd).reduce((max, command) => {
210
+ return Math.max(max, helper.subcommandTerm(command).length);
211
+ }, 0);
212
+ }
213
+ longestOptionTermLength(cmd, helper) {
214
+ return helper.visibleOptions(cmd).reduce((max, option) => {
215
+ return Math.max(max, helper.optionTerm(option).length);
216
+ }, 0);
217
+ }
218
+ longestGlobalOptionTermLength(cmd, helper) {
219
+ return helper.visibleGlobalOptions(cmd).reduce((max, option) => {
220
+ return Math.max(max, helper.optionTerm(option).length);
221
+ }, 0);
222
+ }
223
+ longestArgumentTermLength(cmd, helper) {
224
+ return helper.visibleArguments(cmd).reduce((max, argument) => {
225
+ return Math.max(max, helper.argumentTerm(argument).length);
226
+ }, 0);
227
+ }
228
+ commandUsage(cmd) {
229
+ let cmdName = cmd._name;
230
+ if (cmd._aliases[0]) {
231
+ cmdName = cmdName + "|" + cmd._aliases[0];
232
+ }
233
+ let ancestorCmdNames = "";
234
+ for (let ancestorCmd = cmd.parent;ancestorCmd; ancestorCmd = ancestorCmd.parent) {
235
+ ancestorCmdNames = ancestorCmd.name() + " " + ancestorCmdNames;
236
+ }
237
+ return ancestorCmdNames + cmdName + " " + cmd.usage();
238
+ }
239
+ commandDescription(cmd) {
240
+ return cmd.description();
241
+ }
242
+ subcommandDescription(cmd) {
243
+ return cmd.summary() || cmd.description();
244
+ }
245
+ optionDescription(option) {
246
+ const extraInfo = [];
247
+ if (option.argChoices) {
248
+ extraInfo.push(`choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`);
249
+ }
250
+ if (option.defaultValue !== undefined) {
251
+ const showDefault = option.required || option.optional || option.isBoolean() && typeof option.defaultValue === "boolean";
252
+ if (showDefault) {
253
+ extraInfo.push(`default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`);
254
+ }
255
+ }
256
+ if (option.presetArg !== undefined && option.optional) {
257
+ extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);
258
+ }
259
+ if (option.envVar !== undefined) {
260
+ extraInfo.push(`env: ${option.envVar}`);
261
+ }
262
+ if (extraInfo.length > 0) {
263
+ return `${option.description} (${extraInfo.join(", ")})`;
264
+ }
265
+ return option.description;
266
+ }
267
+ argumentDescription(argument) {
268
+ const extraInfo = [];
269
+ if (argument.argChoices) {
270
+ extraInfo.push(`choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`);
271
+ }
272
+ if (argument.defaultValue !== undefined) {
273
+ extraInfo.push(`default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`);
274
+ }
275
+ if (extraInfo.length > 0) {
276
+ const extraDescripton = `(${extraInfo.join(", ")})`;
277
+ if (argument.description) {
278
+ return `${argument.description} ${extraDescripton}`;
279
+ }
280
+ return extraDescripton;
281
+ }
282
+ return argument.description;
283
+ }
284
+ formatHelp(cmd, helper) {
285
+ const termWidth = helper.padWidth(cmd, helper);
286
+ const helpWidth = helper.helpWidth || 80;
287
+ const itemIndentWidth = 2;
288
+ const itemSeparatorWidth = 2;
289
+ function formatItem(term, description) {
290
+ if (description) {
291
+ const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`;
292
+ return helper.wrap(fullText, helpWidth - itemIndentWidth, termWidth + itemSeparatorWidth);
293
+ }
294
+ return term;
295
+ }
296
+ function formatList(textArray) {
297
+ return textArray.join(`
298
+ `).replace(/^/gm, " ".repeat(itemIndentWidth));
299
+ }
300
+ let output = [`Usage: ${helper.commandUsage(cmd)}`, ""];
301
+ const commandDescription = helper.commandDescription(cmd);
302
+ if (commandDescription.length > 0) {
303
+ output = output.concat([
304
+ helper.wrap(commandDescription, helpWidth, 0),
305
+ ""
306
+ ]);
307
+ }
308
+ const argumentList = helper.visibleArguments(cmd).map((argument) => {
309
+ return formatItem(helper.argumentTerm(argument), helper.argumentDescription(argument));
310
+ });
311
+ if (argumentList.length > 0) {
312
+ output = output.concat(["Arguments:", formatList(argumentList), ""]);
313
+ }
314
+ const optionList = helper.visibleOptions(cmd).map((option) => {
315
+ return formatItem(helper.optionTerm(option), helper.optionDescription(option));
316
+ });
317
+ if (optionList.length > 0) {
318
+ output = output.concat(["Options:", formatList(optionList), ""]);
319
+ }
320
+ if (this.showGlobalOptions) {
321
+ const globalOptionList = helper.visibleGlobalOptions(cmd).map((option) => {
322
+ return formatItem(helper.optionTerm(option), helper.optionDescription(option));
323
+ });
324
+ if (globalOptionList.length > 0) {
325
+ output = output.concat([
326
+ "Global Options:",
327
+ formatList(globalOptionList),
328
+ ""
329
+ ]);
330
+ }
331
+ }
332
+ const commandList = helper.visibleCommands(cmd).map((cmd2) => {
333
+ return formatItem(helper.subcommandTerm(cmd2), helper.subcommandDescription(cmd2));
334
+ });
335
+ if (commandList.length > 0) {
336
+ output = output.concat(["Commands:", formatList(commandList), ""]);
337
+ }
338
+ return output.join(`
339
+ `);
340
+ }
341
+ padWidth(cmd, helper) {
342
+ return Math.max(helper.longestOptionTermLength(cmd, helper), helper.longestGlobalOptionTermLength(cmd, helper), helper.longestSubcommandTermLength(cmd, helper), helper.longestArgumentTermLength(cmd, helper));
343
+ }
344
+ wrap(str, width, indent, minColumnWidth = 40) {
345
+ const indents = " \\f\\t\\v\xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF";
346
+ const manualIndent = new RegExp(`[\\n][${indents}]+`);
347
+ if (str.match(manualIndent))
348
+ return str;
349
+ const columnWidth = width - indent;
350
+ if (columnWidth < minColumnWidth)
351
+ return str;
352
+ const leadingStr = str.slice(0, indent);
353
+ const columnText = str.slice(indent).replace(`\r
354
+ `, `
355
+ `);
356
+ const indentString = " ".repeat(indent);
357
+ const zeroWidthSpace = "\u200B";
358
+ const breaks = `\\s${zeroWidthSpace}`;
359
+ const regex = new RegExp(`
360
+ |.{1,${columnWidth - 1}}([${breaks}]|$)|[^${breaks}]+?([${breaks}]|$)`, "g");
361
+ const lines = columnText.match(regex) || [];
362
+ return leadingStr + lines.map((line, i) => {
363
+ if (line === `
364
+ `)
365
+ return "";
366
+ return (i > 0 ? indentString : "") + line.trimEnd();
367
+ }).join(`
368
+ `);
369
+ }
370
+ }
371
+ exports.Help = Help;
372
+ });
373
+
374
+ // node_modules/commander/lib/option.js
375
+ var require_option = __commonJS((exports) => {
376
+ var { InvalidArgumentError } = require_error();
377
+
378
+ class Option {
379
+ constructor(flags, description) {
380
+ this.flags = flags;
381
+ this.description = description || "";
382
+ this.required = flags.includes("<");
383
+ this.optional = flags.includes("[");
384
+ this.variadic = /\w\.\.\.[>\]]$/.test(flags);
385
+ this.mandatory = false;
386
+ const optionFlags = splitOptionFlags(flags);
387
+ this.short = optionFlags.shortFlag;
388
+ this.long = optionFlags.longFlag;
389
+ this.negate = false;
390
+ if (this.long) {
391
+ this.negate = this.long.startsWith("--no-");
392
+ }
393
+ this.defaultValue = undefined;
394
+ this.defaultValueDescription = undefined;
395
+ this.presetArg = undefined;
396
+ this.envVar = undefined;
397
+ this.parseArg = undefined;
398
+ this.hidden = false;
399
+ this.argChoices = undefined;
400
+ this.conflictsWith = [];
401
+ this.implied = undefined;
402
+ }
403
+ default(value, description) {
404
+ this.defaultValue = value;
405
+ this.defaultValueDescription = description;
406
+ return this;
407
+ }
408
+ preset(arg) {
409
+ this.presetArg = arg;
410
+ return this;
411
+ }
412
+ conflicts(names) {
413
+ this.conflictsWith = this.conflictsWith.concat(names);
414
+ return this;
415
+ }
416
+ implies(impliedOptionValues) {
417
+ let newImplied = impliedOptionValues;
418
+ if (typeof impliedOptionValues === "string") {
419
+ newImplied = { [impliedOptionValues]: true };
420
+ }
421
+ this.implied = Object.assign(this.implied || {}, newImplied);
422
+ return this;
423
+ }
424
+ env(name) {
425
+ this.envVar = name;
426
+ return this;
427
+ }
428
+ argParser(fn) {
429
+ this.parseArg = fn;
430
+ return this;
431
+ }
432
+ makeOptionMandatory(mandatory = true) {
433
+ this.mandatory = !!mandatory;
434
+ return this;
435
+ }
436
+ hideHelp(hide = true) {
437
+ this.hidden = !!hide;
438
+ return this;
439
+ }
440
+ _concatValue(value, previous) {
441
+ if (previous === this.defaultValue || !Array.isArray(previous)) {
442
+ return [value];
443
+ }
444
+ return previous.concat(value);
445
+ }
446
+ choices(values) {
447
+ this.argChoices = values.slice();
448
+ this.parseArg = (arg, previous) => {
449
+ if (!this.argChoices.includes(arg)) {
450
+ throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(", ")}.`);
451
+ }
452
+ if (this.variadic) {
453
+ return this._concatValue(arg, previous);
454
+ }
455
+ return arg;
456
+ };
457
+ return this;
458
+ }
459
+ name() {
460
+ if (this.long) {
461
+ return this.long.replace(/^--/, "");
462
+ }
463
+ return this.short.replace(/^-/, "");
464
+ }
465
+ attributeName() {
466
+ return camelcase(this.name().replace(/^no-/, ""));
467
+ }
468
+ is(arg) {
469
+ return this.short === arg || this.long === arg;
470
+ }
471
+ isBoolean() {
472
+ return !this.required && !this.optional && !this.negate;
473
+ }
474
+ }
475
+
476
+ class DualOptions {
477
+ constructor(options) {
478
+ this.positiveOptions = new Map;
479
+ this.negativeOptions = new Map;
480
+ this.dualOptions = new Set;
481
+ options.forEach((option) => {
482
+ if (option.negate) {
483
+ this.negativeOptions.set(option.attributeName(), option);
484
+ } else {
485
+ this.positiveOptions.set(option.attributeName(), option);
486
+ }
487
+ });
488
+ this.negativeOptions.forEach((value, key) => {
489
+ if (this.positiveOptions.has(key)) {
490
+ this.dualOptions.add(key);
491
+ }
492
+ });
493
+ }
494
+ valueFromOption(value, option) {
495
+ const optionKey = option.attributeName();
496
+ if (!this.dualOptions.has(optionKey))
497
+ return true;
498
+ const preset = this.negativeOptions.get(optionKey).presetArg;
499
+ const negativeValue = preset !== undefined ? preset : false;
500
+ return option.negate === (negativeValue === value);
501
+ }
502
+ }
503
+ function camelcase(str) {
504
+ return str.split("-").reduce((str2, word) => {
505
+ return str2 + word[0].toUpperCase() + word.slice(1);
506
+ });
507
+ }
508
+ function splitOptionFlags(flags) {
509
+ let shortFlag;
510
+ let longFlag;
511
+ const flagParts = flags.split(/[ |,]+/);
512
+ if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1]))
513
+ shortFlag = flagParts.shift();
514
+ longFlag = flagParts.shift();
515
+ if (!shortFlag && /^-[^-]$/.test(longFlag)) {
516
+ shortFlag = longFlag;
517
+ longFlag = undefined;
518
+ }
519
+ return { shortFlag, longFlag };
520
+ }
521
+ exports.Option = Option;
522
+ exports.DualOptions = DualOptions;
523
+ });
524
+
525
+ // node_modules/commander/lib/suggestSimilar.js
526
+ var require_suggestSimilar = __commonJS((exports) => {
527
+ var maxDistance = 3;
528
+ function editDistance(a, b) {
529
+ if (Math.abs(a.length - b.length) > maxDistance)
530
+ return Math.max(a.length, b.length);
531
+ const d = [];
532
+ for (let i = 0;i <= a.length; i++) {
533
+ d[i] = [i];
534
+ }
535
+ for (let j = 0;j <= b.length; j++) {
536
+ d[0][j] = j;
537
+ }
538
+ for (let j = 1;j <= b.length; j++) {
539
+ for (let i = 1;i <= a.length; i++) {
540
+ let cost = 1;
541
+ if (a[i - 1] === b[j - 1]) {
542
+ cost = 0;
543
+ } else {
544
+ cost = 1;
545
+ }
546
+ d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
547
+ if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
548
+ d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);
549
+ }
550
+ }
551
+ }
552
+ return d[a.length][b.length];
553
+ }
554
+ function suggestSimilar(word, candidates) {
555
+ if (!candidates || candidates.length === 0)
556
+ return "";
557
+ candidates = Array.from(new Set(candidates));
558
+ const searchingOptions = word.startsWith("--");
559
+ if (searchingOptions) {
560
+ word = word.slice(2);
561
+ candidates = candidates.map((candidate) => candidate.slice(2));
562
+ }
563
+ let similar = [];
564
+ let bestDistance = maxDistance;
565
+ const minSimilarity = 0.4;
566
+ candidates.forEach((candidate) => {
567
+ if (candidate.length <= 1)
568
+ return;
569
+ const distance = editDistance(word, candidate);
570
+ const length = Math.max(word.length, candidate.length);
571
+ const similarity = (length - distance) / length;
572
+ if (similarity > minSimilarity) {
573
+ if (distance < bestDistance) {
574
+ bestDistance = distance;
575
+ similar = [candidate];
576
+ } else if (distance === bestDistance) {
577
+ similar.push(candidate);
578
+ }
579
+ }
580
+ });
581
+ similar.sort((a, b) => a.localeCompare(b));
582
+ if (searchingOptions) {
583
+ similar = similar.map((candidate) => `--${candidate}`);
584
+ }
585
+ if (similar.length > 1) {
586
+ return `
587
+ (Did you mean one of ${similar.join(", ")}?)`;
588
+ }
589
+ if (similar.length === 1) {
590
+ return `
591
+ (Did you mean ${similar[0]}?)`;
592
+ }
593
+ return "";
594
+ }
595
+ exports.suggestSimilar = suggestSimilar;
596
+ });
597
+
598
+ // node_modules/commander/lib/command.js
599
+ var require_command = __commonJS((exports) => {
600
+ var EventEmitter = __require("events").EventEmitter;
601
+ var childProcess = __require("child_process");
602
+ var path = __require("path");
603
+ var fs = __require("fs");
604
+ var process2 = __require("process");
605
+ var { Argument, humanReadableArgName } = require_argument();
606
+ var { CommanderError } = require_error();
607
+ var { Help } = require_help();
608
+ var { Option, DualOptions } = require_option();
609
+ var { suggestSimilar } = require_suggestSimilar();
610
+
611
+ class Command extends EventEmitter {
612
+ constructor(name) {
613
+ super();
614
+ this.commands = [];
615
+ this.options = [];
616
+ this.parent = null;
617
+ this._allowUnknownOption = false;
618
+ this._allowExcessArguments = true;
619
+ this.registeredArguments = [];
620
+ this._args = this.registeredArguments;
621
+ this.args = [];
622
+ this.rawArgs = [];
623
+ this.processedArgs = [];
624
+ this._scriptPath = null;
625
+ this._name = name || "";
626
+ this._optionValues = {};
627
+ this._optionValueSources = {};
628
+ this._storeOptionsAsProperties = false;
629
+ this._actionHandler = null;
630
+ this._executableHandler = false;
631
+ this._executableFile = null;
632
+ this._executableDir = null;
633
+ this._defaultCommandName = null;
634
+ this._exitCallback = null;
635
+ this._aliases = [];
636
+ this._combineFlagAndOptionalValue = true;
637
+ this._description = "";
638
+ this._summary = "";
639
+ this._argsDescription = undefined;
640
+ this._enablePositionalOptions = false;
641
+ this._passThroughOptions = false;
642
+ this._lifeCycleHooks = {};
643
+ this._showHelpAfterError = false;
644
+ this._showSuggestionAfterError = true;
645
+ this._outputConfiguration = {
646
+ writeOut: (str) => process2.stdout.write(str),
647
+ writeErr: (str) => process2.stderr.write(str),
648
+ getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : undefined,
649
+ getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : undefined,
650
+ outputError: (str, write) => write(str)
651
+ };
652
+ this._hidden = false;
653
+ this._helpOption = undefined;
654
+ this._addImplicitHelpCommand = undefined;
655
+ this._helpCommand = undefined;
656
+ this._helpConfiguration = {};
657
+ }
658
+ copyInheritedSettings(sourceCommand) {
659
+ this._outputConfiguration = sourceCommand._outputConfiguration;
660
+ this._helpOption = sourceCommand._helpOption;
661
+ this._helpCommand = sourceCommand._helpCommand;
662
+ this._helpConfiguration = sourceCommand._helpConfiguration;
663
+ this._exitCallback = sourceCommand._exitCallback;
664
+ this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties;
665
+ this._combineFlagAndOptionalValue = sourceCommand._combineFlagAndOptionalValue;
666
+ this._allowExcessArguments = sourceCommand._allowExcessArguments;
667
+ this._enablePositionalOptions = sourceCommand._enablePositionalOptions;
668
+ this._showHelpAfterError = sourceCommand._showHelpAfterError;
669
+ this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError;
670
+ return this;
671
+ }
672
+ _getCommandAndAncestors() {
673
+ const result = [];
674
+ for (let command = this;command; command = command.parent) {
675
+ result.push(command);
676
+ }
677
+ return result;
678
+ }
679
+ command(nameAndArgs, actionOptsOrExecDesc, execOpts) {
680
+ let desc = actionOptsOrExecDesc;
681
+ let opts = execOpts;
682
+ if (typeof desc === "object" && desc !== null) {
683
+ opts = desc;
684
+ desc = null;
685
+ }
686
+ opts = opts || {};
687
+ const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);
688
+ const cmd = this.createCommand(name);
689
+ if (desc) {
690
+ cmd.description(desc);
691
+ cmd._executableHandler = true;
692
+ }
693
+ if (opts.isDefault)
694
+ this._defaultCommandName = cmd._name;
695
+ cmd._hidden = !!(opts.noHelp || opts.hidden);
696
+ cmd._executableFile = opts.executableFile || null;
697
+ if (args)
698
+ cmd.arguments(args);
699
+ this._registerCommand(cmd);
700
+ cmd.parent = this;
701
+ cmd.copyInheritedSettings(this);
702
+ if (desc)
703
+ return this;
704
+ return cmd;
705
+ }
706
+ createCommand(name) {
707
+ return new Command(name);
708
+ }
709
+ createHelp() {
710
+ return Object.assign(new Help, this.configureHelp());
711
+ }
712
+ configureHelp(configuration) {
713
+ if (configuration === undefined)
714
+ return this._helpConfiguration;
715
+ this._helpConfiguration = configuration;
716
+ return this;
717
+ }
718
+ configureOutput(configuration) {
719
+ if (configuration === undefined)
720
+ return this._outputConfiguration;
721
+ Object.assign(this._outputConfiguration, configuration);
722
+ return this;
723
+ }
724
+ showHelpAfterError(displayHelp = true) {
725
+ if (typeof displayHelp !== "string")
726
+ displayHelp = !!displayHelp;
727
+ this._showHelpAfterError = displayHelp;
728
+ return this;
729
+ }
730
+ showSuggestionAfterError(displaySuggestion = true) {
731
+ this._showSuggestionAfterError = !!displaySuggestion;
732
+ return this;
733
+ }
734
+ addCommand(cmd, opts) {
735
+ if (!cmd._name) {
736
+ throw new Error(`Command passed to .addCommand() must have a name
737
+ - specify the name in Command constructor or using .name()`);
738
+ }
739
+ opts = opts || {};
740
+ if (opts.isDefault)
741
+ this._defaultCommandName = cmd._name;
742
+ if (opts.noHelp || opts.hidden)
743
+ cmd._hidden = true;
744
+ this._registerCommand(cmd);
745
+ cmd.parent = this;
746
+ cmd._checkForBrokenPassThrough();
747
+ return this;
748
+ }
749
+ createArgument(name, description) {
750
+ return new Argument(name, description);
751
+ }
752
+ argument(name, description, fn, defaultValue) {
753
+ const argument = this.createArgument(name, description);
754
+ if (typeof fn === "function") {
755
+ argument.default(defaultValue).argParser(fn);
756
+ } else {
757
+ argument.default(fn);
758
+ }
759
+ this.addArgument(argument);
760
+ return this;
761
+ }
762
+ arguments(names) {
763
+ names.trim().split(/ +/).forEach((detail) => {
764
+ this.argument(detail);
765
+ });
766
+ return this;
767
+ }
768
+ addArgument(argument) {
769
+ const previousArgument = this.registeredArguments.slice(-1)[0];
770
+ if (previousArgument && previousArgument.variadic) {
771
+ throw new Error(`only the last argument can be variadic '${previousArgument.name()}'`);
772
+ }
773
+ if (argument.required && argument.defaultValue !== undefined && argument.parseArg === undefined) {
774
+ throw new Error(`a default value for a required argument is never used: '${argument.name()}'`);
775
+ }
776
+ this.registeredArguments.push(argument);
777
+ return this;
778
+ }
779
+ helpCommand(enableOrNameAndArgs, description) {
780
+ if (typeof enableOrNameAndArgs === "boolean") {
781
+ this._addImplicitHelpCommand = enableOrNameAndArgs;
782
+ return this;
783
+ }
784
+ enableOrNameAndArgs = enableOrNameAndArgs ?? "help [command]";
785
+ const [, helpName, helpArgs] = enableOrNameAndArgs.match(/([^ ]+) *(.*)/);
786
+ const helpDescription = description ?? "display help for command";
787
+ const helpCommand = this.createCommand(helpName);
788
+ helpCommand.helpOption(false);
789
+ if (helpArgs)
790
+ helpCommand.arguments(helpArgs);
791
+ if (helpDescription)
792
+ helpCommand.description(helpDescription);
793
+ this._addImplicitHelpCommand = true;
794
+ this._helpCommand = helpCommand;
795
+ return this;
796
+ }
797
+ addHelpCommand(helpCommand, deprecatedDescription) {
798
+ if (typeof helpCommand !== "object") {
799
+ this.helpCommand(helpCommand, deprecatedDescription);
800
+ return this;
801
+ }
802
+ this._addImplicitHelpCommand = true;
803
+ this._helpCommand = helpCommand;
804
+ return this;
805
+ }
806
+ _getHelpCommand() {
807
+ const hasImplicitHelpCommand = this._addImplicitHelpCommand ?? (this.commands.length && !this._actionHandler && !this._findCommand("help"));
808
+ if (hasImplicitHelpCommand) {
809
+ if (this._helpCommand === undefined) {
810
+ this.helpCommand(undefined, undefined);
811
+ }
812
+ return this._helpCommand;
813
+ }
814
+ return null;
815
+ }
816
+ hook(event, listener) {
817
+ const allowedValues = ["preSubcommand", "preAction", "postAction"];
818
+ if (!allowedValues.includes(event)) {
819
+ throw new Error(`Unexpected value for event passed to hook : '${event}'.
820
+ Expecting one of '${allowedValues.join("', '")}'`);
821
+ }
822
+ if (this._lifeCycleHooks[event]) {
823
+ this._lifeCycleHooks[event].push(listener);
824
+ } else {
825
+ this._lifeCycleHooks[event] = [listener];
826
+ }
827
+ return this;
828
+ }
829
+ exitOverride(fn) {
830
+ if (fn) {
831
+ this._exitCallback = fn;
832
+ } else {
833
+ this._exitCallback = (err) => {
834
+ if (err.code !== "commander.executeSubCommandAsync") {
835
+ throw err;
836
+ } else {}
837
+ };
838
+ }
839
+ return this;
840
+ }
841
+ _exit(exitCode, code, message) {
842
+ if (this._exitCallback) {
843
+ this._exitCallback(new CommanderError(exitCode, code, message));
844
+ }
845
+ process2.exit(exitCode);
846
+ }
847
+ action(fn) {
848
+ const listener = (args) => {
849
+ const expectedArgsCount = this.registeredArguments.length;
850
+ const actionArgs = args.slice(0, expectedArgsCount);
851
+ if (this._storeOptionsAsProperties) {
852
+ actionArgs[expectedArgsCount] = this;
853
+ } else {
854
+ actionArgs[expectedArgsCount] = this.opts();
855
+ }
856
+ actionArgs.push(this);
857
+ return fn.apply(this, actionArgs);
858
+ };
859
+ this._actionHandler = listener;
860
+ return this;
861
+ }
862
+ createOption(flags, description) {
863
+ return new Option(flags, description);
864
+ }
865
+ _callParseArg(target, value, previous, invalidArgumentMessage) {
866
+ try {
867
+ return target.parseArg(value, previous);
868
+ } catch (err) {
869
+ if (err.code === "commander.invalidArgument") {
870
+ const message = `${invalidArgumentMessage} ${err.message}`;
871
+ this.error(message, { exitCode: err.exitCode, code: err.code });
872
+ }
873
+ throw err;
874
+ }
875
+ }
876
+ _registerOption(option) {
877
+ const matchingOption = option.short && this._findOption(option.short) || option.long && this._findOption(option.long);
878
+ if (matchingOption) {
879
+ const matchingFlag = option.long && this._findOption(option.long) ? option.long : option.short;
880
+ throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'
881
+ - already used by option '${matchingOption.flags}'`);
882
+ }
883
+ this.options.push(option);
884
+ }
885
+ _registerCommand(command) {
886
+ const knownBy = (cmd) => {
887
+ return [cmd.name()].concat(cmd.aliases());
888
+ };
889
+ const alreadyUsed = knownBy(command).find((name) => this._findCommand(name));
890
+ if (alreadyUsed) {
891
+ const existingCmd = knownBy(this._findCommand(alreadyUsed)).join("|");
892
+ const newCmd = knownBy(command).join("|");
893
+ throw new Error(`cannot add command '${newCmd}' as already have command '${existingCmd}'`);
894
+ }
895
+ this.commands.push(command);
896
+ }
897
+ addOption(option) {
898
+ this._registerOption(option);
899
+ const oname = option.name();
900
+ const name = option.attributeName();
901
+ if (option.negate) {
902
+ const positiveLongFlag = option.long.replace(/^--no-/, "--");
903
+ if (!this._findOption(positiveLongFlag)) {
904
+ this.setOptionValueWithSource(name, option.defaultValue === undefined ? true : option.defaultValue, "default");
905
+ }
906
+ } else if (option.defaultValue !== undefined) {
907
+ this.setOptionValueWithSource(name, option.defaultValue, "default");
908
+ }
909
+ const handleOptionValue = (val, invalidValueMessage, valueSource) => {
910
+ if (val == null && option.presetArg !== undefined) {
911
+ val = option.presetArg;
912
+ }
913
+ const oldValue = this.getOptionValue(name);
914
+ if (val !== null && option.parseArg) {
915
+ val = this._callParseArg(option, val, oldValue, invalidValueMessage);
916
+ } else if (val !== null && option.variadic) {
917
+ val = option._concatValue(val, oldValue);
918
+ }
919
+ if (val == null) {
920
+ if (option.negate) {
921
+ val = false;
922
+ } else if (option.isBoolean() || option.optional) {
923
+ val = true;
924
+ } else {
925
+ val = "";
926
+ }
927
+ }
928
+ this.setOptionValueWithSource(name, val, valueSource);
929
+ };
930
+ this.on("option:" + oname, (val) => {
931
+ const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;
932
+ handleOptionValue(val, invalidValueMessage, "cli");
933
+ });
934
+ if (option.envVar) {
935
+ this.on("optionEnv:" + oname, (val) => {
936
+ const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;
937
+ handleOptionValue(val, invalidValueMessage, "env");
938
+ });
939
+ }
940
+ return this;
941
+ }
942
+ _optionEx(config, flags, description, fn, defaultValue) {
943
+ if (typeof flags === "object" && flags instanceof Option) {
944
+ throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");
945
+ }
946
+ const option = this.createOption(flags, description);
947
+ option.makeOptionMandatory(!!config.mandatory);
948
+ if (typeof fn === "function") {
949
+ option.default(defaultValue).argParser(fn);
950
+ } else if (fn instanceof RegExp) {
951
+ const regex = fn;
952
+ fn = (val, def) => {
953
+ const m = regex.exec(val);
954
+ return m ? m[0] : def;
955
+ };
956
+ option.default(defaultValue).argParser(fn);
957
+ } else {
958
+ option.default(fn);
959
+ }
960
+ return this.addOption(option);
961
+ }
962
+ option(flags, description, parseArg, defaultValue) {
963
+ return this._optionEx({}, flags, description, parseArg, defaultValue);
964
+ }
965
+ requiredOption(flags, description, parseArg, defaultValue) {
966
+ return this._optionEx({ mandatory: true }, flags, description, parseArg, defaultValue);
967
+ }
968
+ combineFlagAndOptionalValue(combine = true) {
969
+ this._combineFlagAndOptionalValue = !!combine;
970
+ return this;
971
+ }
972
+ allowUnknownOption(allowUnknown = true) {
973
+ this._allowUnknownOption = !!allowUnknown;
974
+ return this;
975
+ }
976
+ allowExcessArguments(allowExcess = true) {
977
+ this._allowExcessArguments = !!allowExcess;
978
+ return this;
979
+ }
980
+ enablePositionalOptions(positional = true) {
981
+ this._enablePositionalOptions = !!positional;
982
+ return this;
983
+ }
984
+ passThroughOptions(passThrough = true) {
985
+ this._passThroughOptions = !!passThrough;
986
+ this._checkForBrokenPassThrough();
987
+ return this;
988
+ }
989
+ _checkForBrokenPassThrough() {
990
+ if (this.parent && this._passThroughOptions && !this.parent._enablePositionalOptions) {
991
+ throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`);
992
+ }
993
+ }
994
+ storeOptionsAsProperties(storeAsProperties = true) {
995
+ if (this.options.length) {
996
+ throw new Error("call .storeOptionsAsProperties() before adding options");
997
+ }
998
+ if (Object.keys(this._optionValues).length) {
999
+ throw new Error("call .storeOptionsAsProperties() before setting option values");
1000
+ }
1001
+ this._storeOptionsAsProperties = !!storeAsProperties;
1002
+ return this;
1003
+ }
1004
+ getOptionValue(key) {
1005
+ if (this._storeOptionsAsProperties) {
1006
+ return this[key];
1007
+ }
1008
+ return this._optionValues[key];
1009
+ }
1010
+ setOptionValue(key, value) {
1011
+ return this.setOptionValueWithSource(key, value, undefined);
1012
+ }
1013
+ setOptionValueWithSource(key, value, source) {
1014
+ if (this._storeOptionsAsProperties) {
1015
+ this[key] = value;
1016
+ } else {
1017
+ this._optionValues[key] = value;
1018
+ }
1019
+ this._optionValueSources[key] = source;
1020
+ return this;
1021
+ }
1022
+ getOptionValueSource(key) {
1023
+ return this._optionValueSources[key];
1024
+ }
1025
+ getOptionValueSourceWithGlobals(key) {
1026
+ let source;
1027
+ this._getCommandAndAncestors().forEach((cmd) => {
1028
+ if (cmd.getOptionValueSource(key) !== undefined) {
1029
+ source = cmd.getOptionValueSource(key);
1030
+ }
1031
+ });
1032
+ return source;
1033
+ }
1034
+ _prepareUserArgs(argv, parseOptions) {
1035
+ if (argv !== undefined && !Array.isArray(argv)) {
1036
+ throw new Error("first parameter to parse must be array or undefined");
1037
+ }
1038
+ parseOptions = parseOptions || {};
1039
+ if (argv === undefined && parseOptions.from === undefined) {
1040
+ if (process2.versions?.electron) {
1041
+ parseOptions.from = "electron";
1042
+ }
1043
+ const execArgv = process2.execArgv ?? [];
1044
+ if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
1045
+ parseOptions.from = "eval";
1046
+ }
1047
+ }
1048
+ if (argv === undefined) {
1049
+ argv = process2.argv;
1050
+ }
1051
+ this.rawArgs = argv.slice();
1052
+ let userArgs;
1053
+ switch (parseOptions.from) {
1054
+ case undefined:
1055
+ case "node":
1056
+ this._scriptPath = argv[1];
1057
+ userArgs = argv.slice(2);
1058
+ break;
1059
+ case "electron":
1060
+ if (process2.defaultApp) {
1061
+ this._scriptPath = argv[1];
1062
+ userArgs = argv.slice(2);
1063
+ } else {
1064
+ userArgs = argv.slice(1);
1065
+ }
1066
+ break;
1067
+ case "user":
1068
+ userArgs = argv.slice(0);
1069
+ break;
1070
+ case "eval":
1071
+ userArgs = argv.slice(1);
1072
+ break;
1073
+ default:
1074
+ throw new Error(`unexpected parse option { from: '${parseOptions.from}' }`);
1075
+ }
1076
+ if (!this._name && this._scriptPath)
1077
+ this.nameFromFilename(this._scriptPath);
1078
+ this._name = this._name || "program";
1079
+ return userArgs;
1080
+ }
1081
+ parse(argv, parseOptions) {
1082
+ const userArgs = this._prepareUserArgs(argv, parseOptions);
1083
+ this._parseCommand([], userArgs);
1084
+ return this;
1085
+ }
1086
+ async parseAsync(argv, parseOptions) {
1087
+ const userArgs = this._prepareUserArgs(argv, parseOptions);
1088
+ await this._parseCommand([], userArgs);
1089
+ return this;
1090
+ }
1091
+ _executeSubCommand(subcommand, args) {
1092
+ args = args.slice();
1093
+ let launchWithNode = false;
1094
+ const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1095
+ function findFile(baseDir, baseName) {
1096
+ const localBin = path.resolve(baseDir, baseName);
1097
+ if (fs.existsSync(localBin))
1098
+ return localBin;
1099
+ if (sourceExt.includes(path.extname(baseName)))
1100
+ return;
1101
+ const foundExt = sourceExt.find((ext) => fs.existsSync(`${localBin}${ext}`));
1102
+ if (foundExt)
1103
+ return `${localBin}${foundExt}`;
1104
+ return;
1105
+ }
1106
+ this._checkForMissingMandatoryOptions();
1107
+ this._checkForConflictingOptions();
1108
+ let executableFile = subcommand._executableFile || `${this._name}-${subcommand._name}`;
1109
+ let executableDir = this._executableDir || "";
1110
+ if (this._scriptPath) {
1111
+ let resolvedScriptPath;
1112
+ try {
1113
+ resolvedScriptPath = fs.realpathSync(this._scriptPath);
1114
+ } catch (err) {
1115
+ resolvedScriptPath = this._scriptPath;
1116
+ }
1117
+ executableDir = path.resolve(path.dirname(resolvedScriptPath), executableDir);
1118
+ }
1119
+ if (executableDir) {
1120
+ let localFile = findFile(executableDir, executableFile);
1121
+ if (!localFile && !subcommand._executableFile && this._scriptPath) {
1122
+ const legacyName = path.basename(this._scriptPath, path.extname(this._scriptPath));
1123
+ if (legacyName !== this._name) {
1124
+ localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
1125
+ }
1126
+ }
1127
+ executableFile = localFile || executableFile;
1128
+ }
1129
+ launchWithNode = sourceExt.includes(path.extname(executableFile));
1130
+ let proc;
1131
+ if (process2.platform !== "win32") {
1132
+ if (launchWithNode) {
1133
+ args.unshift(executableFile);
1134
+ args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1135
+ proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" });
1136
+ } else {
1137
+ proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
1138
+ }
1139
+ } else {
1140
+ args.unshift(executableFile);
1141
+ args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1142
+ proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" });
1143
+ }
1144
+ if (!proc.killed) {
1145
+ const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
1146
+ signals.forEach((signal) => {
1147
+ process2.on(signal, () => {
1148
+ if (proc.killed === false && proc.exitCode === null) {
1149
+ proc.kill(signal);
1150
+ }
1151
+ });
1152
+ });
1153
+ }
1154
+ const exitCallback = this._exitCallback;
1155
+ proc.on("close", (code) => {
1156
+ code = code ?? 1;
1157
+ if (!exitCallback) {
1158
+ process2.exit(code);
1159
+ } else {
1160
+ exitCallback(new CommanderError(code, "commander.executeSubCommandAsync", "(close)"));
1161
+ }
1162
+ });
1163
+ proc.on("error", (err) => {
1164
+ if (err.code === "ENOENT") {
1165
+ const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
1166
+ const executableMissing = `'${executableFile}' does not exist
1167
+ - if '${subcommand._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
1168
+ - if the default executable name is not suitable, use the executableFile option to supply a custom name or path
1169
+ - ${executableDirMessage}`;
1170
+ throw new Error(executableMissing);
1171
+ } else if (err.code === "EACCES") {
1172
+ throw new Error(`'${executableFile}' not executable`);
1173
+ }
1174
+ if (!exitCallback) {
1175
+ process2.exit(1);
1176
+ } else {
1177
+ const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
1178
+ wrappedError.nestedError = err;
1179
+ exitCallback(wrappedError);
1180
+ }
1181
+ });
1182
+ this.runningCommand = proc;
1183
+ }
1184
+ _dispatchSubcommand(commandName, operands, unknown) {
1185
+ const subCommand = this._findCommand(commandName);
1186
+ if (!subCommand)
1187
+ this.help({ error: true });
1188
+ let promiseChain;
1189
+ promiseChain = this._chainOrCallSubCommandHook(promiseChain, subCommand, "preSubcommand");
1190
+ promiseChain = this._chainOrCall(promiseChain, () => {
1191
+ if (subCommand._executableHandler) {
1192
+ this._executeSubCommand(subCommand, operands.concat(unknown));
1193
+ } else {
1194
+ return subCommand._parseCommand(operands, unknown);
1195
+ }
1196
+ });
1197
+ return promiseChain;
1198
+ }
1199
+ _dispatchHelpCommand(subcommandName) {
1200
+ if (!subcommandName) {
1201
+ this.help();
1202
+ }
1203
+ const subCommand = this._findCommand(subcommandName);
1204
+ if (subCommand && !subCommand._executableHandler) {
1205
+ subCommand.help();
1206
+ }
1207
+ return this._dispatchSubcommand(subcommandName, [], [this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? "--help"]);
1208
+ }
1209
+ _checkNumberOfArguments() {
1210
+ this.registeredArguments.forEach((arg, i) => {
1211
+ if (arg.required && this.args[i] == null) {
1212
+ this.missingArgument(arg.name());
1213
+ }
1214
+ });
1215
+ if (this.registeredArguments.length > 0 && this.registeredArguments[this.registeredArguments.length - 1].variadic) {
1216
+ return;
1217
+ }
1218
+ if (this.args.length > this.registeredArguments.length) {
1219
+ this._excessArguments(this.args);
1220
+ }
1221
+ }
1222
+ _processArguments() {
1223
+ const myParseArg = (argument, value, previous) => {
1224
+ let parsedValue = value;
1225
+ if (value !== null && argument.parseArg) {
1226
+ const invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;
1227
+ parsedValue = this._callParseArg(argument, value, previous, invalidValueMessage);
1228
+ }
1229
+ return parsedValue;
1230
+ };
1231
+ this._checkNumberOfArguments();
1232
+ const processedArgs = [];
1233
+ this.registeredArguments.forEach((declaredArg, index) => {
1234
+ let value = declaredArg.defaultValue;
1235
+ if (declaredArg.variadic) {
1236
+ if (index < this.args.length) {
1237
+ value = this.args.slice(index);
1238
+ if (declaredArg.parseArg) {
1239
+ value = value.reduce((processed, v) => {
1240
+ return myParseArg(declaredArg, v, processed);
1241
+ }, declaredArg.defaultValue);
1242
+ }
1243
+ } else if (value === undefined) {
1244
+ value = [];
1245
+ }
1246
+ } else if (index < this.args.length) {
1247
+ value = this.args[index];
1248
+ if (declaredArg.parseArg) {
1249
+ value = myParseArg(declaredArg, value, declaredArg.defaultValue);
1250
+ }
1251
+ }
1252
+ processedArgs[index] = value;
1253
+ });
1254
+ this.processedArgs = processedArgs;
1255
+ }
1256
+ _chainOrCall(promise, fn) {
1257
+ if (promise && promise.then && typeof promise.then === "function") {
1258
+ return promise.then(() => fn());
1259
+ }
1260
+ return fn();
1261
+ }
1262
+ _chainOrCallHooks(promise, event) {
1263
+ let result = promise;
1264
+ const hooks = [];
1265
+ this._getCommandAndAncestors().reverse().filter((cmd) => cmd._lifeCycleHooks[event] !== undefined).forEach((hookedCommand) => {
1266
+ hookedCommand._lifeCycleHooks[event].forEach((callback) => {
1267
+ hooks.push({ hookedCommand, callback });
1268
+ });
1269
+ });
1270
+ if (event === "postAction") {
1271
+ hooks.reverse();
1272
+ }
1273
+ hooks.forEach((hookDetail) => {
1274
+ result = this._chainOrCall(result, () => {
1275
+ return hookDetail.callback(hookDetail.hookedCommand, this);
1276
+ });
1277
+ });
1278
+ return result;
1279
+ }
1280
+ _chainOrCallSubCommandHook(promise, subCommand, event) {
1281
+ let result = promise;
1282
+ if (this._lifeCycleHooks[event] !== undefined) {
1283
+ this._lifeCycleHooks[event].forEach((hook) => {
1284
+ result = this._chainOrCall(result, () => {
1285
+ return hook(this, subCommand);
1286
+ });
1287
+ });
1288
+ }
1289
+ return result;
1290
+ }
1291
+ _parseCommand(operands, unknown) {
1292
+ const parsed = this.parseOptions(unknown);
1293
+ this._parseOptionsEnv();
1294
+ this._parseOptionsImplied();
1295
+ operands = operands.concat(parsed.operands);
1296
+ unknown = parsed.unknown;
1297
+ this.args = operands.concat(unknown);
1298
+ if (operands && this._findCommand(operands[0])) {
1299
+ return this._dispatchSubcommand(operands[0], operands.slice(1), unknown);
1300
+ }
1301
+ if (this._getHelpCommand() && operands[0] === this._getHelpCommand().name()) {
1302
+ return this._dispatchHelpCommand(operands[1]);
1303
+ }
1304
+ if (this._defaultCommandName) {
1305
+ this._outputHelpIfRequested(unknown);
1306
+ return this._dispatchSubcommand(this._defaultCommandName, operands, unknown);
1307
+ }
1308
+ if (this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName) {
1309
+ this.help({ error: true });
1310
+ }
1311
+ this._outputHelpIfRequested(parsed.unknown);
1312
+ this._checkForMissingMandatoryOptions();
1313
+ this._checkForConflictingOptions();
1314
+ const checkForUnknownOptions = () => {
1315
+ if (parsed.unknown.length > 0) {
1316
+ this.unknownOption(parsed.unknown[0]);
1317
+ }
1318
+ };
1319
+ const commandEvent = `command:${this.name()}`;
1320
+ if (this._actionHandler) {
1321
+ checkForUnknownOptions();
1322
+ this._processArguments();
1323
+ let promiseChain;
1324
+ promiseChain = this._chainOrCallHooks(promiseChain, "preAction");
1325
+ promiseChain = this._chainOrCall(promiseChain, () => this._actionHandler(this.processedArgs));
1326
+ if (this.parent) {
1327
+ promiseChain = this._chainOrCall(promiseChain, () => {
1328
+ this.parent.emit(commandEvent, operands, unknown);
1329
+ });
1330
+ }
1331
+ promiseChain = this._chainOrCallHooks(promiseChain, "postAction");
1332
+ return promiseChain;
1333
+ }
1334
+ if (this.parent && this.parent.listenerCount(commandEvent)) {
1335
+ checkForUnknownOptions();
1336
+ this._processArguments();
1337
+ this.parent.emit(commandEvent, operands, unknown);
1338
+ } else if (operands.length) {
1339
+ if (this._findCommand("*")) {
1340
+ return this._dispatchSubcommand("*", operands, unknown);
1341
+ }
1342
+ if (this.listenerCount("command:*")) {
1343
+ this.emit("command:*", operands, unknown);
1344
+ } else if (this.commands.length) {
1345
+ this.unknownCommand();
1346
+ } else {
1347
+ checkForUnknownOptions();
1348
+ this._processArguments();
1349
+ }
1350
+ } else if (this.commands.length) {
1351
+ checkForUnknownOptions();
1352
+ this.help({ error: true });
1353
+ } else {
1354
+ checkForUnknownOptions();
1355
+ this._processArguments();
1356
+ }
1357
+ }
1358
+ _findCommand(name) {
1359
+ if (!name)
1360
+ return;
1361
+ return this.commands.find((cmd) => cmd._name === name || cmd._aliases.includes(name));
1362
+ }
1363
+ _findOption(arg) {
1364
+ return this.options.find((option) => option.is(arg));
1365
+ }
1366
+ _checkForMissingMandatoryOptions() {
1367
+ this._getCommandAndAncestors().forEach((cmd) => {
1368
+ cmd.options.forEach((anOption) => {
1369
+ if (anOption.mandatory && cmd.getOptionValue(anOption.attributeName()) === undefined) {
1370
+ cmd.missingMandatoryOptionValue(anOption);
1371
+ }
1372
+ });
1373
+ });
1374
+ }
1375
+ _checkForConflictingLocalOptions() {
1376
+ const definedNonDefaultOptions = this.options.filter((option) => {
1377
+ const optionKey = option.attributeName();
1378
+ if (this.getOptionValue(optionKey) === undefined) {
1379
+ return false;
1380
+ }
1381
+ return this.getOptionValueSource(optionKey) !== "default";
1382
+ });
1383
+ const optionsWithConflicting = definedNonDefaultOptions.filter((option) => option.conflictsWith.length > 0);
1384
+ optionsWithConflicting.forEach((option) => {
1385
+ const conflictingAndDefined = definedNonDefaultOptions.find((defined) => option.conflictsWith.includes(defined.attributeName()));
1386
+ if (conflictingAndDefined) {
1387
+ this._conflictingOption(option, conflictingAndDefined);
1388
+ }
1389
+ });
1390
+ }
1391
+ _checkForConflictingOptions() {
1392
+ this._getCommandAndAncestors().forEach((cmd) => {
1393
+ cmd._checkForConflictingLocalOptions();
1394
+ });
1395
+ }
1396
+ parseOptions(argv) {
1397
+ const operands = [];
1398
+ const unknown = [];
1399
+ let dest = operands;
1400
+ const args = argv.slice();
1401
+ function maybeOption(arg) {
1402
+ return arg.length > 1 && arg[0] === "-";
1403
+ }
1404
+ let activeVariadicOption = null;
1405
+ while (args.length) {
1406
+ const arg = args.shift();
1407
+ if (arg === "--") {
1408
+ if (dest === unknown)
1409
+ dest.push(arg);
1410
+ dest.push(...args);
1411
+ break;
1412
+ }
1413
+ if (activeVariadicOption && !maybeOption(arg)) {
1414
+ this.emit(`option:${activeVariadicOption.name()}`, arg);
1415
+ continue;
1416
+ }
1417
+ activeVariadicOption = null;
1418
+ if (maybeOption(arg)) {
1419
+ const option = this._findOption(arg);
1420
+ if (option) {
1421
+ if (option.required) {
1422
+ const value = args.shift();
1423
+ if (value === undefined)
1424
+ this.optionMissingArgument(option);
1425
+ this.emit(`option:${option.name()}`, value);
1426
+ } else if (option.optional) {
1427
+ let value = null;
1428
+ if (args.length > 0 && !maybeOption(args[0])) {
1429
+ value = args.shift();
1430
+ }
1431
+ this.emit(`option:${option.name()}`, value);
1432
+ } else {
1433
+ this.emit(`option:${option.name()}`);
1434
+ }
1435
+ activeVariadicOption = option.variadic ? option : null;
1436
+ continue;
1437
+ }
1438
+ }
1439
+ if (arg.length > 2 && arg[0] === "-" && arg[1] !== "-") {
1440
+ const option = this._findOption(`-${arg[1]}`);
1441
+ if (option) {
1442
+ if (option.required || option.optional && this._combineFlagAndOptionalValue) {
1443
+ this.emit(`option:${option.name()}`, arg.slice(2));
1444
+ } else {
1445
+ this.emit(`option:${option.name()}`);
1446
+ args.unshift(`-${arg.slice(2)}`);
1447
+ }
1448
+ continue;
1449
+ }
1450
+ }
1451
+ if (/^--[^=]+=/.test(arg)) {
1452
+ const index = arg.indexOf("=");
1453
+ const option = this._findOption(arg.slice(0, index));
1454
+ if (option && (option.required || option.optional)) {
1455
+ this.emit(`option:${option.name()}`, arg.slice(index + 1));
1456
+ continue;
1457
+ }
1458
+ }
1459
+ if (maybeOption(arg)) {
1460
+ dest = unknown;
1461
+ }
1462
+ if ((this._enablePositionalOptions || this._passThroughOptions) && operands.length === 0 && unknown.length === 0) {
1463
+ if (this._findCommand(arg)) {
1464
+ operands.push(arg);
1465
+ if (args.length > 0)
1466
+ unknown.push(...args);
1467
+ break;
1468
+ } else if (this._getHelpCommand() && arg === this._getHelpCommand().name()) {
1469
+ operands.push(arg);
1470
+ if (args.length > 0)
1471
+ operands.push(...args);
1472
+ break;
1473
+ } else if (this._defaultCommandName) {
1474
+ unknown.push(arg);
1475
+ if (args.length > 0)
1476
+ unknown.push(...args);
1477
+ break;
1478
+ }
1479
+ }
1480
+ if (this._passThroughOptions) {
1481
+ dest.push(arg);
1482
+ if (args.length > 0)
1483
+ dest.push(...args);
1484
+ break;
1485
+ }
1486
+ dest.push(arg);
1487
+ }
1488
+ return { operands, unknown };
1489
+ }
1490
+ opts() {
1491
+ if (this._storeOptionsAsProperties) {
1492
+ const result = {};
1493
+ const len = this.options.length;
1494
+ for (let i = 0;i < len; i++) {
1495
+ const key = this.options[i].attributeName();
1496
+ result[key] = key === this._versionOptionName ? this._version : this[key];
1497
+ }
1498
+ return result;
1499
+ }
1500
+ return this._optionValues;
1501
+ }
1502
+ optsWithGlobals() {
1503
+ return this._getCommandAndAncestors().reduce((combinedOptions, cmd) => Object.assign(combinedOptions, cmd.opts()), {});
1504
+ }
1505
+ error(message, errorOptions) {
1506
+ this._outputConfiguration.outputError(`${message}
1507
+ `, this._outputConfiguration.writeErr);
1508
+ if (typeof this._showHelpAfterError === "string") {
1509
+ this._outputConfiguration.writeErr(`${this._showHelpAfterError}
1510
+ `);
1511
+ } else if (this._showHelpAfterError) {
1512
+ this._outputConfiguration.writeErr(`
1513
+ `);
1514
+ this.outputHelp({ error: true });
1515
+ }
1516
+ const config = errorOptions || {};
1517
+ const exitCode = config.exitCode || 1;
1518
+ const code = config.code || "commander.error";
1519
+ this._exit(exitCode, code, message);
1520
+ }
1521
+ _parseOptionsEnv() {
1522
+ this.options.forEach((option) => {
1523
+ if (option.envVar && option.envVar in process2.env) {
1524
+ const optionKey = option.attributeName();
1525
+ if (this.getOptionValue(optionKey) === undefined || ["default", "config", "env"].includes(this.getOptionValueSource(optionKey))) {
1526
+ if (option.required || option.optional) {
1527
+ this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
1528
+ } else {
1529
+ this.emit(`optionEnv:${option.name()}`);
1530
+ }
1531
+ }
1532
+ }
1533
+ });
1534
+ }
1535
+ _parseOptionsImplied() {
1536
+ const dualHelper = new DualOptions(this.options);
1537
+ const hasCustomOptionValue = (optionKey) => {
1538
+ return this.getOptionValue(optionKey) !== undefined && !["default", "implied"].includes(this.getOptionValueSource(optionKey));
1539
+ };
1540
+ this.options.filter((option) => option.implied !== undefined && hasCustomOptionValue(option.attributeName()) && dualHelper.valueFromOption(this.getOptionValue(option.attributeName()), option)).forEach((option) => {
1541
+ Object.keys(option.implied).filter((impliedKey) => !hasCustomOptionValue(impliedKey)).forEach((impliedKey) => {
1542
+ this.setOptionValueWithSource(impliedKey, option.implied[impliedKey], "implied");
1543
+ });
1544
+ });
1545
+ }
1546
+ missingArgument(name) {
1547
+ const message = `error: missing required argument '${name}'`;
1548
+ this.error(message, { code: "commander.missingArgument" });
1549
+ }
1550
+ optionMissingArgument(option) {
1551
+ const message = `error: option '${option.flags}' argument missing`;
1552
+ this.error(message, { code: "commander.optionMissingArgument" });
1553
+ }
1554
+ missingMandatoryOptionValue(option) {
1555
+ const message = `error: required option '${option.flags}' not specified`;
1556
+ this.error(message, { code: "commander.missingMandatoryOptionValue" });
1557
+ }
1558
+ _conflictingOption(option, conflictingOption) {
1559
+ const findBestOptionFromValue = (option2) => {
1560
+ const optionKey = option2.attributeName();
1561
+ const optionValue = this.getOptionValue(optionKey);
1562
+ const negativeOption = this.options.find((target) => target.negate && optionKey === target.attributeName());
1563
+ const positiveOption = this.options.find((target) => !target.negate && optionKey === target.attributeName());
1564
+ if (negativeOption && (negativeOption.presetArg === undefined && optionValue === false || negativeOption.presetArg !== undefined && optionValue === negativeOption.presetArg)) {
1565
+ return negativeOption;
1566
+ }
1567
+ return positiveOption || option2;
1568
+ };
1569
+ const getErrorMessage = (option2) => {
1570
+ const bestOption = findBestOptionFromValue(option2);
1571
+ const optionKey = bestOption.attributeName();
1572
+ const source = this.getOptionValueSource(optionKey);
1573
+ if (source === "env") {
1574
+ return `environment variable '${bestOption.envVar}'`;
1575
+ }
1576
+ return `option '${bestOption.flags}'`;
1577
+ };
1578
+ const message = `error: ${getErrorMessage(option)} cannot be used with ${getErrorMessage(conflictingOption)}`;
1579
+ this.error(message, { code: "commander.conflictingOption" });
1580
+ }
1581
+ unknownOption(flag) {
1582
+ if (this._allowUnknownOption)
1583
+ return;
1584
+ let suggestion = "";
1585
+ if (flag.startsWith("--") && this._showSuggestionAfterError) {
1586
+ let candidateFlags = [];
1587
+ let command = this;
1588
+ do {
1589
+ const moreFlags = command.createHelp().visibleOptions(command).filter((option) => option.long).map((option) => option.long);
1590
+ candidateFlags = candidateFlags.concat(moreFlags);
1591
+ command = command.parent;
1592
+ } while (command && !command._enablePositionalOptions);
1593
+ suggestion = suggestSimilar(flag, candidateFlags);
1594
+ }
1595
+ const message = `error: unknown option '${flag}'${suggestion}`;
1596
+ this.error(message, { code: "commander.unknownOption" });
1597
+ }
1598
+ _excessArguments(receivedArgs) {
1599
+ if (this._allowExcessArguments)
1600
+ return;
1601
+ const expected = this.registeredArguments.length;
1602
+ const s = expected === 1 ? "" : "s";
1603
+ const forSubcommand = this.parent ? ` for '${this.name()}'` : "";
1604
+ const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${receivedArgs.length}.`;
1605
+ this.error(message, { code: "commander.excessArguments" });
1606
+ }
1607
+ unknownCommand() {
1608
+ const unknownName = this.args[0];
1609
+ let suggestion = "";
1610
+ if (this._showSuggestionAfterError) {
1611
+ const candidateNames = [];
1612
+ this.createHelp().visibleCommands(this).forEach((command) => {
1613
+ candidateNames.push(command.name());
1614
+ if (command.alias())
1615
+ candidateNames.push(command.alias());
1616
+ });
1617
+ suggestion = suggestSimilar(unknownName, candidateNames);
1618
+ }
1619
+ const message = `error: unknown command '${unknownName}'${suggestion}`;
1620
+ this.error(message, { code: "commander.unknownCommand" });
1621
+ }
1622
+ version(str, flags, description) {
1623
+ if (str === undefined)
1624
+ return this._version;
1625
+ this._version = str;
1626
+ flags = flags || "-V, --version";
1627
+ description = description || "output the version number";
1628
+ const versionOption = this.createOption(flags, description);
1629
+ this._versionOptionName = versionOption.attributeName();
1630
+ this._registerOption(versionOption);
1631
+ this.on("option:" + versionOption.name(), () => {
1632
+ this._outputConfiguration.writeOut(`${str}
1633
+ `);
1634
+ this._exit(0, "commander.version", str);
1635
+ });
1636
+ return this;
1637
+ }
1638
+ description(str, argsDescription) {
1639
+ if (str === undefined && argsDescription === undefined)
1640
+ return this._description;
1641
+ this._description = str;
1642
+ if (argsDescription) {
1643
+ this._argsDescription = argsDescription;
1644
+ }
1645
+ return this;
1646
+ }
1647
+ summary(str) {
1648
+ if (str === undefined)
1649
+ return this._summary;
1650
+ this._summary = str;
1651
+ return this;
1652
+ }
1653
+ alias(alias) {
1654
+ if (alias === undefined)
1655
+ return this._aliases[0];
1656
+ let command = this;
1657
+ if (this.commands.length !== 0 && this.commands[this.commands.length - 1]._executableHandler) {
1658
+ command = this.commands[this.commands.length - 1];
1659
+ }
1660
+ if (alias === command._name)
1661
+ throw new Error("Command alias can't be the same as its name");
1662
+ const matchingCommand = this.parent?._findCommand(alias);
1663
+ if (matchingCommand) {
1664
+ const existingCmd = [matchingCommand.name()].concat(matchingCommand.aliases()).join("|");
1665
+ throw new Error(`cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`);
1666
+ }
1667
+ command._aliases.push(alias);
1668
+ return this;
1669
+ }
1670
+ aliases(aliases) {
1671
+ if (aliases === undefined)
1672
+ return this._aliases;
1673
+ aliases.forEach((alias) => this.alias(alias));
1674
+ return this;
1675
+ }
1676
+ usage(str) {
1677
+ if (str === undefined) {
1678
+ if (this._usage)
1679
+ return this._usage;
1680
+ const args = this.registeredArguments.map((arg) => {
1681
+ return humanReadableArgName(arg);
1682
+ });
1683
+ return [].concat(this.options.length || this._helpOption !== null ? "[options]" : [], this.commands.length ? "[command]" : [], this.registeredArguments.length ? args : []).join(" ");
1684
+ }
1685
+ this._usage = str;
1686
+ return this;
1687
+ }
1688
+ name(str) {
1689
+ if (str === undefined)
1690
+ return this._name;
1691
+ this._name = str;
1692
+ return this;
1693
+ }
1694
+ nameFromFilename(filename) {
1695
+ this._name = path.basename(filename, path.extname(filename));
1696
+ return this;
1697
+ }
1698
+ executableDir(path2) {
1699
+ if (path2 === undefined)
1700
+ return this._executableDir;
1701
+ this._executableDir = path2;
1702
+ return this;
1703
+ }
1704
+ helpInformation(contextOptions) {
1705
+ const helper = this.createHelp();
1706
+ if (helper.helpWidth === undefined) {
1707
+ helper.helpWidth = contextOptions && contextOptions.error ? this._outputConfiguration.getErrHelpWidth() : this._outputConfiguration.getOutHelpWidth();
1708
+ }
1709
+ return helper.formatHelp(this, helper);
1710
+ }
1711
+ _getHelpContext(contextOptions) {
1712
+ contextOptions = contextOptions || {};
1713
+ const context = { error: !!contextOptions.error };
1714
+ let write;
1715
+ if (context.error) {
1716
+ write = (arg) => this._outputConfiguration.writeErr(arg);
1717
+ } else {
1718
+ write = (arg) => this._outputConfiguration.writeOut(arg);
1719
+ }
1720
+ context.write = contextOptions.write || write;
1721
+ context.command = this;
1722
+ return context;
1723
+ }
1724
+ outputHelp(contextOptions) {
1725
+ let deprecatedCallback;
1726
+ if (typeof contextOptions === "function") {
1727
+ deprecatedCallback = contextOptions;
1728
+ contextOptions = undefined;
1729
+ }
1730
+ const context = this._getHelpContext(contextOptions);
1731
+ this._getCommandAndAncestors().reverse().forEach((command) => command.emit("beforeAllHelp", context));
1732
+ this.emit("beforeHelp", context);
1733
+ let helpInformation = this.helpInformation(context);
1734
+ if (deprecatedCallback) {
1735
+ helpInformation = deprecatedCallback(helpInformation);
1736
+ if (typeof helpInformation !== "string" && !Buffer.isBuffer(helpInformation)) {
1737
+ throw new Error("outputHelp callback must return a string or a Buffer");
1738
+ }
1739
+ }
1740
+ context.write(helpInformation);
1741
+ if (this._getHelpOption()?.long) {
1742
+ this.emit(this._getHelpOption().long);
1743
+ }
1744
+ this.emit("afterHelp", context);
1745
+ this._getCommandAndAncestors().forEach((command) => command.emit("afterAllHelp", context));
1746
+ }
1747
+ helpOption(flags, description) {
1748
+ if (typeof flags === "boolean") {
1749
+ if (flags) {
1750
+ this._helpOption = this._helpOption ?? undefined;
1751
+ } else {
1752
+ this._helpOption = null;
1753
+ }
1754
+ return this;
1755
+ }
1756
+ flags = flags ?? "-h, --help";
1757
+ description = description ?? "display help for command";
1758
+ this._helpOption = this.createOption(flags, description);
1759
+ return this;
1760
+ }
1761
+ _getHelpOption() {
1762
+ if (this._helpOption === undefined) {
1763
+ this.helpOption(undefined, undefined);
1764
+ }
1765
+ return this._helpOption;
1766
+ }
1767
+ addHelpOption(option) {
1768
+ this._helpOption = option;
1769
+ return this;
1770
+ }
1771
+ help(contextOptions) {
1772
+ this.outputHelp(contextOptions);
1773
+ let exitCode = process2.exitCode || 0;
1774
+ if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
1775
+ exitCode = 1;
1776
+ }
1777
+ this._exit(exitCode, "commander.help", "(outputHelp)");
1778
+ }
1779
+ addHelpText(position, text) {
1780
+ const allowedValues = ["beforeAll", "before", "after", "afterAll"];
1781
+ if (!allowedValues.includes(position)) {
1782
+ throw new Error(`Unexpected value for position to addHelpText.
1783
+ Expecting one of '${allowedValues.join("', '")}'`);
1784
+ }
1785
+ const helpEvent = `${position}Help`;
1786
+ this.on(helpEvent, (context) => {
1787
+ let helpStr;
1788
+ if (typeof text === "function") {
1789
+ helpStr = text({ error: context.error, command: context.command });
1790
+ } else {
1791
+ helpStr = text;
1792
+ }
1793
+ if (helpStr) {
1794
+ context.write(`${helpStr}
1795
+ `);
1796
+ }
1797
+ });
1798
+ return this;
1799
+ }
1800
+ _outputHelpIfRequested(args) {
1801
+ const helpOption = this._getHelpOption();
1802
+ const helpRequested = helpOption && args.find((arg) => helpOption.is(arg));
1803
+ if (helpRequested) {
1804
+ this.outputHelp();
1805
+ this._exit(0, "commander.helpDisplayed", "(outputHelp)");
1806
+ }
1807
+ }
1808
+ }
1809
+ function incrementNodeInspectorPort(args) {
1810
+ return args.map((arg) => {
1811
+ if (!arg.startsWith("--inspect")) {
1812
+ return arg;
1813
+ }
1814
+ let debugOption;
1815
+ let debugHost = "127.0.0.1";
1816
+ let debugPort = "9229";
1817
+ let match;
1818
+ if ((match = arg.match(/^(--inspect(-brk)?)$/)) !== null) {
1819
+ debugOption = match[1];
1820
+ } else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null) {
1821
+ debugOption = match[1];
1822
+ if (/^\d+$/.test(match[3])) {
1823
+ debugPort = match[3];
1824
+ } else {
1825
+ debugHost = match[3];
1826
+ }
1827
+ } else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/)) !== null) {
1828
+ debugOption = match[1];
1829
+ debugHost = match[3];
1830
+ debugPort = match[4];
1831
+ }
1832
+ if (debugOption && debugPort !== "0") {
1833
+ return `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;
1834
+ }
1835
+ return arg;
1836
+ });
1837
+ }
1838
+ exports.Command = Command;
1839
+ });
1840
+
1841
+ // node_modules/commander/index.js
1842
+ var require_commander = __commonJS((exports) => {
1843
+ var { Argument } = require_argument();
1844
+ var { Command } = require_command();
1845
+ var { CommanderError, InvalidArgumentError } = require_error();
1846
+ var { Help } = require_help();
1847
+ var { Option } = require_option();
1848
+ exports.program = new Command;
1849
+ exports.createCommand = (name) => new Command(name);
1850
+ exports.createOption = (flags, description) => new Option(flags, description);
1851
+ exports.createArgument = (name, description) => new Argument(name, description);
1852
+ exports.Command = Command;
1853
+ exports.Option = Option;
1854
+ exports.Argument = Argument;
1855
+ exports.Help = Help;
1856
+ exports.CommanderError = CommanderError;
1857
+ exports.InvalidArgumentError = InvalidArgumentError;
1858
+ exports.InvalidOptionArgumentError = InvalidArgumentError;
1859
+ });
1860
+
1861
+ // node_modules/commander/esm.mjs
1862
+ var import__ = __toESM(require_commander(), 1);
1863
+ var {
1864
+ program,
1865
+ createCommand,
1866
+ createArgument,
1867
+ createOption,
1868
+ CommanderError,
1869
+ InvalidArgumentError,
1870
+ InvalidOptionArgumentError,
1871
+ Command,
1872
+ Argument,
1873
+ Option,
1874
+ Help
1875
+ } = import__.default;
1876
+
1877
+ // src/commands/create.ts
1878
+ import { existsSync } from "fs";
1879
+ import { mkdir, writeFile } from "fs/promises";
1880
+ import { join } from "path";
1881
+
1882
+ // node_modules/chalk/source/vendor/ansi-styles/index.js
1883
+ var ANSI_BACKGROUND_OFFSET = 10;
1884
+ var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
1885
+ var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
1886
+ var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
1887
+ var styles = {
1888
+ modifier: {
1889
+ reset: [0, 0],
1890
+ bold: [1, 22],
1891
+ dim: [2, 22],
1892
+ italic: [3, 23],
1893
+ underline: [4, 24],
1894
+ overline: [53, 55],
1895
+ inverse: [7, 27],
1896
+ hidden: [8, 28],
1897
+ strikethrough: [9, 29]
1898
+ },
1899
+ color: {
1900
+ black: [30, 39],
1901
+ red: [31, 39],
1902
+ green: [32, 39],
1903
+ yellow: [33, 39],
1904
+ blue: [34, 39],
1905
+ magenta: [35, 39],
1906
+ cyan: [36, 39],
1907
+ white: [37, 39],
1908
+ blackBright: [90, 39],
1909
+ gray: [90, 39],
1910
+ grey: [90, 39],
1911
+ redBright: [91, 39],
1912
+ greenBright: [92, 39],
1913
+ yellowBright: [93, 39],
1914
+ blueBright: [94, 39],
1915
+ magentaBright: [95, 39],
1916
+ cyanBright: [96, 39],
1917
+ whiteBright: [97, 39]
1918
+ },
1919
+ bgColor: {
1920
+ bgBlack: [40, 49],
1921
+ bgRed: [41, 49],
1922
+ bgGreen: [42, 49],
1923
+ bgYellow: [43, 49],
1924
+ bgBlue: [44, 49],
1925
+ bgMagenta: [45, 49],
1926
+ bgCyan: [46, 49],
1927
+ bgWhite: [47, 49],
1928
+ bgBlackBright: [100, 49],
1929
+ bgGray: [100, 49],
1930
+ bgGrey: [100, 49],
1931
+ bgRedBright: [101, 49],
1932
+ bgGreenBright: [102, 49],
1933
+ bgYellowBright: [103, 49],
1934
+ bgBlueBright: [104, 49],
1935
+ bgMagentaBright: [105, 49],
1936
+ bgCyanBright: [106, 49],
1937
+ bgWhiteBright: [107, 49]
1938
+ }
1939
+ };
1940
+ var modifierNames = Object.keys(styles.modifier);
1941
+ var foregroundColorNames = Object.keys(styles.color);
1942
+ var backgroundColorNames = Object.keys(styles.bgColor);
1943
+ var colorNames = [...foregroundColorNames, ...backgroundColorNames];
1944
+ function assembleStyles() {
1945
+ const codes = new Map;
1946
+ for (const [groupName, group] of Object.entries(styles)) {
1947
+ for (const [styleName, style] of Object.entries(group)) {
1948
+ styles[styleName] = {
1949
+ open: `\x1B[${style[0]}m`,
1950
+ close: `\x1B[${style[1]}m`
1951
+ };
1952
+ group[styleName] = styles[styleName];
1953
+ codes.set(style[0], style[1]);
1954
+ }
1955
+ Object.defineProperty(styles, groupName, {
1956
+ value: group,
1957
+ enumerable: false
1958
+ });
1959
+ }
1960
+ Object.defineProperty(styles, "codes", {
1961
+ value: codes,
1962
+ enumerable: false
1963
+ });
1964
+ styles.color.close = "\x1B[39m";
1965
+ styles.bgColor.close = "\x1B[49m";
1966
+ styles.color.ansi = wrapAnsi16();
1967
+ styles.color.ansi256 = wrapAnsi256();
1968
+ styles.color.ansi16m = wrapAnsi16m();
1969
+ styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
1970
+ styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
1971
+ styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
1972
+ Object.defineProperties(styles, {
1973
+ rgbToAnsi256: {
1974
+ value(red, green, blue) {
1975
+ if (red === green && green === blue) {
1976
+ if (red < 8) {
1977
+ return 16;
1978
+ }
1979
+ if (red > 248) {
1980
+ return 231;
1981
+ }
1982
+ return Math.round((red - 8) / 247 * 24) + 232;
1983
+ }
1984
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
1985
+ },
1986
+ enumerable: false
1987
+ },
1988
+ hexToRgb: {
1989
+ value(hex) {
1990
+ const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
1991
+ if (!matches) {
1992
+ return [0, 0, 0];
1993
+ }
1994
+ let [colorString] = matches;
1995
+ if (colorString.length === 3) {
1996
+ colorString = [...colorString].map((character) => character + character).join("");
1997
+ }
1998
+ const integer = Number.parseInt(colorString, 16);
1999
+ return [
2000
+ integer >> 16 & 255,
2001
+ integer >> 8 & 255,
2002
+ integer & 255
2003
+ ];
2004
+ },
2005
+ enumerable: false
2006
+ },
2007
+ hexToAnsi256: {
2008
+ value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
2009
+ enumerable: false
2010
+ },
2011
+ ansi256ToAnsi: {
2012
+ value(code) {
2013
+ if (code < 8) {
2014
+ return 30 + code;
2015
+ }
2016
+ if (code < 16) {
2017
+ return 90 + (code - 8);
2018
+ }
2019
+ let red;
2020
+ let green;
2021
+ let blue;
2022
+ if (code >= 232) {
2023
+ red = ((code - 232) * 10 + 8) / 255;
2024
+ green = red;
2025
+ blue = red;
2026
+ } else {
2027
+ code -= 16;
2028
+ const remainder = code % 36;
2029
+ red = Math.floor(code / 36) / 5;
2030
+ green = Math.floor(remainder / 6) / 5;
2031
+ blue = remainder % 6 / 5;
2032
+ }
2033
+ const value = Math.max(red, green, blue) * 2;
2034
+ if (value === 0) {
2035
+ return 30;
2036
+ }
2037
+ let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
2038
+ if (value === 2) {
2039
+ result += 60;
2040
+ }
2041
+ return result;
2042
+ },
2043
+ enumerable: false
2044
+ },
2045
+ rgbToAnsi: {
2046
+ value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
2047
+ enumerable: false
2048
+ },
2049
+ hexToAnsi: {
2050
+ value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
2051
+ enumerable: false
2052
+ }
2053
+ });
2054
+ return styles;
2055
+ }
2056
+ var ansiStyles = assembleStyles();
2057
+ var ansi_styles_default = ansiStyles;
2058
+
2059
+ // node_modules/chalk/source/vendor/supports-color/index.js
2060
+ import process2 from "process";
2061
+ import os from "os";
2062
+ import tty from "tty";
2063
+ function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
2064
+ const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
2065
+ const position = argv.indexOf(prefix + flag);
2066
+ const terminatorPosition = argv.indexOf("--");
2067
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
2068
+ }
2069
+ var { env } = process2;
2070
+ var flagForceColor;
2071
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
2072
+ flagForceColor = 0;
2073
+ } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
2074
+ flagForceColor = 1;
2075
+ }
2076
+ function envForceColor() {
2077
+ if ("FORCE_COLOR" in env) {
2078
+ if (env.FORCE_COLOR === "true") {
2079
+ return 1;
2080
+ }
2081
+ if (env.FORCE_COLOR === "false") {
2082
+ return 0;
2083
+ }
2084
+ return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
2085
+ }
2086
+ }
2087
+ function translateLevel(level) {
2088
+ if (level === 0) {
2089
+ return false;
2090
+ }
2091
+ return {
2092
+ level,
2093
+ hasBasic: true,
2094
+ has256: level >= 2,
2095
+ has16m: level >= 3
2096
+ };
2097
+ }
2098
+ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
2099
+ const noFlagForceColor = envForceColor();
2100
+ if (noFlagForceColor !== undefined) {
2101
+ flagForceColor = noFlagForceColor;
2102
+ }
2103
+ const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
2104
+ if (forceColor === 0) {
2105
+ return 0;
2106
+ }
2107
+ if (sniffFlags) {
2108
+ if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
2109
+ return 3;
2110
+ }
2111
+ if (hasFlag("color=256")) {
2112
+ return 2;
2113
+ }
2114
+ }
2115
+ if ("TF_BUILD" in env && "AGENT_NAME" in env) {
2116
+ return 1;
2117
+ }
2118
+ if (haveStream && !streamIsTTY && forceColor === undefined) {
2119
+ return 0;
2120
+ }
2121
+ const min = forceColor || 0;
2122
+ if (env.TERM === "dumb") {
2123
+ return min;
2124
+ }
2125
+ if (process2.platform === "win32") {
2126
+ const osRelease = os.release().split(".");
2127
+ if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
2128
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
2129
+ }
2130
+ return 1;
2131
+ }
2132
+ if ("CI" in env) {
2133
+ if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => (key in env))) {
2134
+ return 3;
2135
+ }
2136
+ if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => (sign in env)) || env.CI_NAME === "codeship") {
2137
+ return 1;
2138
+ }
2139
+ return min;
2140
+ }
2141
+ if ("TEAMCITY_VERSION" in env) {
2142
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
2143
+ }
2144
+ if (env.COLORTERM === "truecolor") {
2145
+ return 3;
2146
+ }
2147
+ if (env.TERM === "xterm-kitty") {
2148
+ return 3;
2149
+ }
2150
+ if (env.TERM === "xterm-ghostty") {
2151
+ return 3;
2152
+ }
2153
+ if (env.TERM === "wezterm") {
2154
+ return 3;
2155
+ }
2156
+ if ("TERM_PROGRAM" in env) {
2157
+ const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
2158
+ switch (env.TERM_PROGRAM) {
2159
+ case "iTerm.app": {
2160
+ return version >= 3 ? 3 : 2;
2161
+ }
2162
+ case "Apple_Terminal": {
2163
+ return 2;
2164
+ }
2165
+ }
2166
+ }
2167
+ if (/-256(color)?$/i.test(env.TERM)) {
2168
+ return 2;
2169
+ }
2170
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
2171
+ return 1;
2172
+ }
2173
+ if ("COLORTERM" in env) {
2174
+ return 1;
2175
+ }
2176
+ return min;
2177
+ }
2178
+ function createSupportsColor(stream, options = {}) {
2179
+ const level = _supportsColor(stream, {
2180
+ streamIsTTY: stream && stream.isTTY,
2181
+ ...options
2182
+ });
2183
+ return translateLevel(level);
2184
+ }
2185
+ var supportsColor = {
2186
+ stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
2187
+ stderr: createSupportsColor({ isTTY: tty.isatty(2) })
2188
+ };
2189
+ var supports_color_default = supportsColor;
2190
+
2191
+ // node_modules/chalk/source/utilities.js
2192
+ function stringReplaceAll(string, substring, replacer) {
2193
+ let index = string.indexOf(substring);
2194
+ if (index === -1) {
2195
+ return string;
2196
+ }
2197
+ const substringLength = substring.length;
2198
+ let endIndex = 0;
2199
+ let returnValue = "";
2200
+ do {
2201
+ returnValue += string.slice(endIndex, index) + substring + replacer;
2202
+ endIndex = index + substringLength;
2203
+ index = string.indexOf(substring, endIndex);
2204
+ } while (index !== -1);
2205
+ returnValue += string.slice(endIndex);
2206
+ return returnValue;
2207
+ }
2208
+ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
2209
+ let endIndex = 0;
2210
+ let returnValue = "";
2211
+ do {
2212
+ const gotCR = string[index - 1] === "\r";
2213
+ returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? `\r
2214
+ ` : `
2215
+ `) + postfix;
2216
+ endIndex = index + 1;
2217
+ index = string.indexOf(`
2218
+ `, endIndex);
2219
+ } while (index !== -1);
2220
+ returnValue += string.slice(endIndex);
2221
+ return returnValue;
2222
+ }
2223
+
2224
+ // node_modules/chalk/source/index.js
2225
+ var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
2226
+ var GENERATOR = Symbol("GENERATOR");
2227
+ var STYLER = Symbol("STYLER");
2228
+ var IS_EMPTY = Symbol("IS_EMPTY");
2229
+ var levelMapping = [
2230
+ "ansi",
2231
+ "ansi",
2232
+ "ansi256",
2233
+ "ansi16m"
2234
+ ];
2235
+ var styles2 = Object.create(null);
2236
+ var applyOptions = (object, options = {}) => {
2237
+ if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
2238
+ throw new Error("The `level` option should be an integer from 0 to 3");
2239
+ }
2240
+ const colorLevel = stdoutColor ? stdoutColor.level : 0;
2241
+ object.level = options.level === undefined ? colorLevel : options.level;
2242
+ };
2243
+ var chalkFactory = (options) => {
2244
+ const chalk = (...strings) => strings.join(" ");
2245
+ applyOptions(chalk, options);
2246
+ Object.setPrototypeOf(chalk, createChalk.prototype);
2247
+ return chalk;
2248
+ };
2249
+ function createChalk(options) {
2250
+ return chalkFactory(options);
2251
+ }
2252
+ Object.setPrototypeOf(createChalk.prototype, Function.prototype);
2253
+ for (const [styleName, style] of Object.entries(ansi_styles_default)) {
2254
+ styles2[styleName] = {
2255
+ get() {
2256
+ const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
2257
+ Object.defineProperty(this, styleName, { value: builder });
2258
+ return builder;
2259
+ }
2260
+ };
2261
+ }
2262
+ styles2.visible = {
2263
+ get() {
2264
+ const builder = createBuilder(this, this[STYLER], true);
2265
+ Object.defineProperty(this, "visible", { value: builder });
2266
+ return builder;
2267
+ }
2268
+ };
2269
+ var getModelAnsi = (model, level, type, ...arguments_) => {
2270
+ if (model === "rgb") {
2271
+ if (level === "ansi16m") {
2272
+ return ansi_styles_default[type].ansi16m(...arguments_);
2273
+ }
2274
+ if (level === "ansi256") {
2275
+ return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
2276
+ }
2277
+ return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
2278
+ }
2279
+ if (model === "hex") {
2280
+ return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
2281
+ }
2282
+ return ansi_styles_default[type][model](...arguments_);
2283
+ };
2284
+ var usedModels = ["rgb", "hex", "ansi256"];
2285
+ for (const model of usedModels) {
2286
+ styles2[model] = {
2287
+ get() {
2288
+ const { level } = this;
2289
+ return function(...arguments_) {
2290
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
2291
+ return createBuilder(this, styler, this[IS_EMPTY]);
2292
+ };
2293
+ }
2294
+ };
2295
+ const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
2296
+ styles2[bgModel] = {
2297
+ get() {
2298
+ const { level } = this;
2299
+ return function(...arguments_) {
2300
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
2301
+ return createBuilder(this, styler, this[IS_EMPTY]);
2302
+ };
2303
+ }
2304
+ };
2305
+ }
2306
+ var proto = Object.defineProperties(() => {}, {
2307
+ ...styles2,
2308
+ level: {
2309
+ enumerable: true,
2310
+ get() {
2311
+ return this[GENERATOR].level;
2312
+ },
2313
+ set(level) {
2314
+ this[GENERATOR].level = level;
2315
+ }
2316
+ }
2317
+ });
2318
+ var createStyler = (open, close, parent) => {
2319
+ let openAll;
2320
+ let closeAll;
2321
+ if (parent === undefined) {
2322
+ openAll = open;
2323
+ closeAll = close;
2324
+ } else {
2325
+ openAll = parent.openAll + open;
2326
+ closeAll = close + parent.closeAll;
2327
+ }
2328
+ return {
2329
+ open,
2330
+ close,
2331
+ openAll,
2332
+ closeAll,
2333
+ parent
2334
+ };
2335
+ };
2336
+ var createBuilder = (self, _styler, _isEmpty) => {
2337
+ const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
2338
+ Object.setPrototypeOf(builder, proto);
2339
+ builder[GENERATOR] = self;
2340
+ builder[STYLER] = _styler;
2341
+ builder[IS_EMPTY] = _isEmpty;
2342
+ return builder;
2343
+ };
2344
+ var applyStyle = (self, string) => {
2345
+ if (self.level <= 0 || !string) {
2346
+ return self[IS_EMPTY] ? "" : string;
2347
+ }
2348
+ let styler = self[STYLER];
2349
+ if (styler === undefined) {
2350
+ return string;
2351
+ }
2352
+ const { openAll, closeAll } = styler;
2353
+ if (string.includes("\x1B")) {
2354
+ while (styler !== undefined) {
2355
+ string = stringReplaceAll(string, styler.close, styler.open);
2356
+ styler = styler.parent;
2357
+ }
2358
+ }
2359
+ const lfIndex = string.indexOf(`
2360
+ `);
2361
+ if (lfIndex !== -1) {
2362
+ string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
2363
+ }
2364
+ return openAll + string + closeAll;
2365
+ };
2366
+ Object.defineProperties(createChalk.prototype, styles2);
2367
+ var chalk = createChalk();
2368
+ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
2369
+ var source_default = chalk;
2370
+
2371
+ // src/commands/create.ts
2372
+ async function createPlugin(name, options = {}) {
2373
+ const pluginName = name.startsWith("omp-") ? name : `omp-${name}`;
2374
+ const pluginDir = pluginName;
2375
+ if (existsSync(pluginDir)) {
2376
+ console.log(source_default.red(`Error: Directory ${pluginDir} already exists`));
2377
+ return;
2378
+ }
2379
+ console.log(source_default.blue(`Creating plugin: ${pluginName}...`));
2380
+ try {
2381
+ await mkdir(pluginDir, { recursive: true });
2382
+ await mkdir(join(pluginDir, "agents"), { recursive: true });
2383
+ await mkdir(join(pluginDir, "tools"), { recursive: true });
2384
+ await mkdir(join(pluginDir, "themes"), { recursive: true });
2385
+ await mkdir(join(pluginDir, "commands"), { recursive: true });
2386
+ const packageJson = {
2387
+ name: pluginName,
2388
+ version: "0.1.0",
2389
+ description: options.description || `A pi plugin`,
2390
+ keywords: ["omp-plugin"],
2391
+ author: options.author || "",
2392
+ license: "MIT",
2393
+ omp: {
2394
+ install: []
2395
+ },
2396
+ files: ["agents", "tools", "themes", "commands"]
2397
+ };
2398
+ await writeFile(join(pluginDir, "package.json"), JSON.stringify(packageJson, null, 2));
2399
+ const readme = `# ${pluginName}
2400
+
2401
+ ${options.description || "A pi plugin."}
2402
+
2403
+ ## Installation
2404
+
2405
+ \`\`\`bash
2406
+ omp install ${pluginName}
2407
+ \`\`\`
2408
+
2409
+ ## Contents
2410
+
2411
+ ### Agents
2412
+
2413
+ Add agent markdown files to \`agents/\` directory.
2414
+
2415
+ ### Tools
2416
+
2417
+ Add tool implementations to \`tools/\` directory.
2418
+
2419
+ ### Themes
2420
+
2421
+ Add theme JSON files to \`themes/\` directory.
2422
+
2423
+ ### Commands
2424
+
2425
+ Add command markdown files to \`commands/\` directory.
2426
+
2427
+ ## Configuration
2428
+
2429
+ Edit \`package.json\` to configure which files are installed:
2430
+
2431
+ \`\`\`json
2432
+ {
2433
+ "omp": {
2434
+ "install": [
2435
+ { "src": "agents/my-agent.md", "dest": "agent/agents/my-agent.md" },
2436
+ { "src": "tools/my-tool/", "dest": "agent/tools/my-tool/" }
2437
+ ]
2438
+ }
2439
+ }
2440
+ \`\`\`
2441
+
2442
+ ## Publishing
2443
+
2444
+ 1. Update version in package.json
2445
+ 2. Run \`npm publish\`
2446
+
2447
+ Users can then install with: \`omp install ${pluginName}\`
2448
+
2449
+ ## License
2450
+
2451
+ MIT
2452
+ `;
2453
+ await writeFile(join(pluginDir, "README.md"), readme);
2454
+ const exampleAgent = `# Example Agent
2455
+
2456
+ This is an example agent for ${pluginName}.
2457
+
2458
+ ## Description
2459
+
2460
+ Describe what this agent does.
2461
+
2462
+ ## Instructions
2463
+
2464
+ Provide instructions for the agent here.
2465
+ `;
2466
+ await writeFile(join(pluginDir, "agents", "example.md"), exampleAgent);
2467
+ const gitignore = `node_modules/
2468
+ .DS_Store
2469
+ *.log
2470
+ `;
2471
+ await writeFile(join(pluginDir, ".gitignore"), gitignore);
2472
+ console.log(source_default.green(`
2473
+ \u2713 Created plugin at ${pluginDir}/`));
2474
+ console.log();
2475
+ console.log(source_default.dim("Directory structure:"));
2476
+ console.log(source_default.dim(` ${pluginDir}/`));
2477
+ console.log(source_default.dim(" \u251C\u2500\u2500 package.json"));
2478
+ console.log(source_default.dim(" \u251C\u2500\u2500 README.md"));
2479
+ console.log(source_default.dim(" \u251C\u2500\u2500 .gitignore"));
2480
+ console.log(source_default.dim(" \u251C\u2500\u2500 agents/"));
2481
+ console.log(source_default.dim(" \u2502 \u2514\u2500\u2500 example.md"));
2482
+ console.log(source_default.dim(" \u251C\u2500\u2500 tools/"));
2483
+ console.log(source_default.dim(" \u251C\u2500\u2500 themes/"));
2484
+ console.log(source_default.dim(" \u2514\u2500\u2500 commands/"));
2485
+ console.log();
2486
+ console.log(source_default.dim("Next steps:"));
2487
+ console.log(source_default.dim(` 1. cd ${pluginDir}`));
2488
+ console.log(source_default.dim(" 2. Add your agents, tools, themes, or commands"));
2489
+ console.log(source_default.dim(" 3. Update omp.install in package.json"));
2490
+ console.log(source_default.dim(" 4. Test locally: omp link ."));
2491
+ console.log(source_default.dim(" 5. Publish: npm publish"));
2492
+ } catch (err) {
2493
+ console.log(source_default.red(`Error creating plugin: ${err.message}`));
2494
+ }
2495
+ }
2496
+
2497
+ // src/commands/doctor.ts
2498
+ import { existsSync as existsSync4 } from "fs";
2499
+
2500
+ // src/conflicts.ts
2501
+ function detectConflicts(newPluginName, newPkgJson, existingPlugins) {
2502
+ const conflicts = [];
2503
+ if (!newPkgJson.omp?.install?.length) {
2504
+ return conflicts;
2505
+ }
2506
+ const destMap = new Map;
2507
+ for (const [name, pkgJson] of existingPlugins) {
2508
+ if (pkgJson.omp?.install) {
2509
+ for (const entry of pkgJson.omp.install) {
2510
+ const existing = destMap.get(entry.dest) || [];
2511
+ existing.push({ name, src: entry.src });
2512
+ destMap.set(entry.dest, existing);
2513
+ }
2514
+ }
2515
+ }
2516
+ for (const entry of newPkgJson.omp.install) {
2517
+ const existing = destMap.get(entry.dest);
2518
+ if (existing && existing.length > 0) {
2519
+ conflicts.push({
2520
+ dest: entry.dest,
2521
+ plugins: [...existing, { name: newPluginName, src: entry.src }]
2522
+ });
2523
+ }
2524
+ }
2525
+ return conflicts;
2526
+ }
2527
+ function detectAllConflicts(plugins) {
2528
+ const conflicts = [];
2529
+ const destMap = new Map;
2530
+ for (const [name, pkgJson] of plugins) {
2531
+ if (pkgJson.omp?.install) {
2532
+ for (const entry of pkgJson.omp.install) {
2533
+ const existing = destMap.get(entry.dest) || [];
2534
+ existing.push({ name, src: entry.src });
2535
+ destMap.set(entry.dest, existing);
2536
+ }
2537
+ }
2538
+ }
2539
+ for (const [dest, sources] of destMap) {
2540
+ if (sources.length > 1) {
2541
+ conflicts.push({ dest, plugins: sources });
2542
+ }
2543
+ }
2544
+ return conflicts;
2545
+ }
2546
+ function formatConflicts(conflicts) {
2547
+ return conflicts.map((conflict) => {
2548
+ const plugins = conflict.plugins.map((p) => p.name).join(" and ");
2549
+ return `${plugins} both install ${conflict.dest}`;
2550
+ });
2551
+ }
2552
+
2553
+ // src/manifest.ts
2554
+ import { existsSync as existsSync2 } from "fs";
2555
+ import { mkdir as mkdir2, readFile, writeFile as writeFile2 } from "fs/promises";
2556
+ import { dirname, join as join3 } from "path";
2557
+
2558
+ // src/paths.ts
2559
+ import { homedir } from "os";
2560
+ import { join as join2 } from "path";
2561
+ var PI_CONFIG_DIR = join2(homedir(), ".pi");
2562
+ var PLUGINS_DIR = join2(PI_CONFIG_DIR, "plugins");
2563
+ var NODE_MODULES_DIR = join2(PLUGINS_DIR, "node_modules");
2564
+ var GLOBAL_PACKAGE_JSON = join2(PLUGINS_DIR, "package.json");
2565
+ var GLOBAL_LOCK_FILE = join2(PLUGINS_DIR, "package-lock.json");
2566
+ var LEGACY_MANIFEST_PATH = join2(PLUGINS_DIR, "manifest.json");
2567
+ var PROJECT_PI_DIR = ".pi";
2568
+ var PROJECT_PLUGINS_JSON = join2(PROJECT_PI_DIR, "plugins.json");
2569
+ var PROJECT_PLUGINS_LOCK = join2(PROJECT_PI_DIR, "plugins-lock.json");
2570
+ var PROJECT_NODE_MODULES = join2(PROJECT_PI_DIR, "node_modules");
2571
+
2572
+ // src/manifest.ts
2573
+ async function initGlobalPlugins() {
2574
+ await mkdir2(PLUGINS_DIR, { recursive: true });
2575
+ if (!existsSync2(GLOBAL_PACKAGE_JSON)) {
2576
+ const packageJson = {
2577
+ name: "pi-plugins",
2578
+ version: "1.0.0",
2579
+ private: true,
2580
+ description: "Global pi plugins managed by omp",
2581
+ dependencies: {}
2582
+ };
2583
+ await writeFile2(GLOBAL_PACKAGE_JSON, JSON.stringify(packageJson, null, 2));
2584
+ }
2585
+ }
2586
+ async function loadPluginsJson(global = true) {
2587
+ const path = global ? GLOBAL_PACKAGE_JSON : PROJECT_PLUGINS_JSON;
2588
+ try {
2589
+ const data = await readFile(path, "utf-8");
2590
+ const parsed = JSON.parse(data);
2591
+ if (global) {
2592
+ return {
2593
+ plugins: parsed.dependencies || {},
2594
+ disabled: parsed.omp?.disabled || []
2595
+ };
2596
+ }
2597
+ return {
2598
+ plugins: parsed.plugins || {},
2599
+ disabled: parsed.disabled || []
2600
+ };
2601
+ } catch (err) {
2602
+ if (err.code === "ENOENT") {
2603
+ return { plugins: {}, disabled: [] };
2604
+ }
2605
+ throw err;
2606
+ }
2607
+ }
2608
+ async function savePluginsJson(data, global = true) {
2609
+ const path = global ? GLOBAL_PACKAGE_JSON : PROJECT_PLUGINS_JSON;
2610
+ await mkdir2(dirname(path), { recursive: true });
2611
+ if (global) {
2612
+ let existing = {};
2613
+ try {
2614
+ existing = JSON.parse(await readFile(path, "utf-8"));
2615
+ } catch {
2616
+ existing = {
2617
+ name: "pi-plugins",
2618
+ version: "1.0.0",
2619
+ private: true,
2620
+ description: "Global pi plugins managed by omp"
2621
+ };
2622
+ }
2623
+ existing.dependencies = data.plugins;
2624
+ if (data.disabled?.length) {
2625
+ existing.omp = { ...existing.omp || {}, disabled: data.disabled };
2626
+ }
2627
+ await writeFile2(path, JSON.stringify(existing, null, 2));
2628
+ } else {
2629
+ await writeFile2(path, JSON.stringify(data, null, 2));
2630
+ }
2631
+ }
2632
+ async function readPluginPackageJson(pluginName, global = true) {
2633
+ const nodeModules = global ? NODE_MODULES_DIR : ".pi/node_modules";
2634
+ let pkgPath;
2635
+ if (pluginName.startsWith("@")) {
2636
+ pkgPath = join3(nodeModules, pluginName, "package.json");
2637
+ } else {
2638
+ pkgPath = join3(nodeModules, pluginName, "package.json");
2639
+ }
2640
+ try {
2641
+ const data = await readFile(pkgPath, "utf-8");
2642
+ return JSON.parse(data);
2643
+ } catch {
2644
+ return null;
2645
+ }
2646
+ }
2647
+ function getPluginSourceDir(pluginName, global = true) {
2648
+ const nodeModules = global ? NODE_MODULES_DIR : ".pi/node_modules";
2649
+ return join3(nodeModules, pluginName);
2650
+ }
2651
+ function hasLegacyManifest() {
2652
+ return existsSync2(LEGACY_MANIFEST_PATH);
2653
+ }
2654
+ async function loadLegacyManifest() {
2655
+ try {
2656
+ const data = await readFile(LEGACY_MANIFEST_PATH, "utf-8");
2657
+ return JSON.parse(data);
2658
+ } catch {
2659
+ return { plugins: {} };
2660
+ }
2661
+ }
2662
+ async function getInstalledPlugins(global = true) {
2663
+ const pluginsJson = await loadPluginsJson(global);
2664
+ const plugins = new Map;
2665
+ for (const name of Object.keys(pluginsJson.plugins)) {
2666
+ const pkgJson = await readPluginPackageJson(name, global);
2667
+ if (pkgJson) {
2668
+ plugins.set(name, pkgJson);
2669
+ }
2670
+ }
2671
+ return plugins;
2672
+ }
2673
+
2674
+ // src/symlinks.ts
2675
+ import { existsSync as existsSync3, lstatSync } from "fs";
2676
+ import { mkdir as mkdir3, readlink, rm, symlink } from "fs/promises";
2677
+ import { dirname as dirname2, join as join4 } from "path";
2678
+ async function createPluginSymlinks(pluginName, pkgJson, global = true, verbose = true) {
2679
+ const result = { created: [], errors: [] };
2680
+ const sourceDir = getPluginSourceDir(pluginName, global);
2681
+ if (!pkgJson.omp?.install?.length) {
2682
+ if (verbose) {
2683
+ console.log(source_default.dim(" No omp.install entries found"));
2684
+ }
2685
+ return result;
2686
+ }
2687
+ for (const entry of pkgJson.omp.install) {
2688
+ try {
2689
+ const src = join4(sourceDir, entry.src);
2690
+ const dest = join4(PI_CONFIG_DIR, entry.dest);
2691
+ if (!existsSync3(src)) {
2692
+ result.errors.push(`Source not found: ${entry.src}`);
2693
+ if (verbose) {
2694
+ console.log(source_default.yellow(` \u26A0 Source not found: ${entry.src}`));
2695
+ }
2696
+ continue;
2697
+ }
2698
+ await mkdir3(dirname2(dest), { recursive: true });
2699
+ try {
2700
+ await rm(dest, { force: true, recursive: true });
2701
+ } catch {}
2702
+ await symlink(src, dest);
2703
+ result.created.push(entry.dest);
2704
+ if (verbose) {
2705
+ console.log(source_default.dim(` Linked: ${entry.dest} \u2192 ${entry.src}`));
2706
+ }
2707
+ } catch (err) {
2708
+ const msg = `Failed to link ${entry.dest}: ${err.message}`;
2709
+ result.errors.push(msg);
2710
+ if (verbose) {
2711
+ console.log(source_default.red(` \u2717 ${msg}`));
2712
+ }
2713
+ }
2714
+ }
2715
+ return result;
2716
+ }
2717
+ async function removePluginSymlinks(_pluginName, pkgJson, verbose = true) {
2718
+ const result = { created: [], errors: [] };
2719
+ if (!pkgJson.omp?.install?.length) {
2720
+ return result;
2721
+ }
2722
+ for (const entry of pkgJson.omp.install) {
2723
+ const dest = join4(PI_CONFIG_DIR, entry.dest);
2724
+ try {
2725
+ if (existsSync3(dest)) {
2726
+ await rm(dest, { force: true, recursive: true });
2727
+ result.created.push(entry.dest);
2728
+ if (verbose) {
2729
+ console.log(source_default.dim(` Removed: ${entry.dest}`));
2730
+ }
2731
+ }
2732
+ } catch (err) {
2733
+ const msg = `Failed to remove ${entry.dest}: ${err.message}`;
2734
+ result.errors.push(msg);
2735
+ if (verbose) {
2736
+ console.log(source_default.yellow(` \u26A0 ${msg}`));
2737
+ }
2738
+ }
2739
+ }
2740
+ return result;
2741
+ }
2742
+ async function checkPluginSymlinks(pluginName, pkgJson, global = true) {
2743
+ const result = { valid: [], broken: [], missing: [] };
2744
+ const sourceDir = getPluginSourceDir(pluginName, global);
2745
+ if (!pkgJson.omp?.install?.length) {
2746
+ return result;
2747
+ }
2748
+ for (const entry of pkgJson.omp.install) {
2749
+ const src = join4(sourceDir, entry.src);
2750
+ const dest = join4(PI_CONFIG_DIR, entry.dest);
2751
+ if (!existsSync3(dest)) {
2752
+ result.missing.push(entry.dest);
2753
+ continue;
2754
+ }
2755
+ try {
2756
+ const stats = lstatSync(dest);
2757
+ if (stats.isSymbolicLink()) {
2758
+ const _target = await readlink(dest);
2759
+ if (existsSync3(src)) {
2760
+ result.valid.push(entry.dest);
2761
+ } else {
2762
+ result.broken.push(entry.dest);
2763
+ }
2764
+ } else {
2765
+ result.broken.push(entry.dest);
2766
+ }
2767
+ } catch {
2768
+ result.broken.push(entry.dest);
2769
+ }
2770
+ }
2771
+ return result;
2772
+ }
2773
+ async function traceInstalledFile(filePath, installedPlugins) {
2774
+ let relativePath = filePath;
2775
+ if (filePath.startsWith(PI_CONFIG_DIR)) {
2776
+ relativePath = filePath.slice(PI_CONFIG_DIR.length + 1);
2777
+ }
2778
+ for (const [name, pkgJson] of installedPlugins) {
2779
+ if (pkgJson.omp?.install) {
2780
+ for (const entry of pkgJson.omp.install) {
2781
+ if (entry.dest === relativePath) {
2782
+ return { plugin: name, entry };
2783
+ }
2784
+ }
2785
+ }
2786
+ }
2787
+ return null;
2788
+ }
2789
+
2790
+ // src/commands/doctor.ts
2791
+ async function runDoctor(options = {}) {
2792
+ const isGlobal = options.global !== false;
2793
+ const results = [];
2794
+ console.log(source_default.blue(`Running health checks...
2795
+ `));
2796
+ const pluginsDir = isGlobal ? PLUGINS_DIR : ".pi";
2797
+ if (!existsSync4(pluginsDir)) {
2798
+ results.push({
2799
+ check: "Plugins directory",
2800
+ status: "warning",
2801
+ message: `${pluginsDir} does not exist`,
2802
+ fix: "Run: omp install <package>"
2803
+ });
2804
+ } else {
2805
+ results.push({
2806
+ check: "Plugins directory",
2807
+ status: "ok",
2808
+ message: pluginsDir
2809
+ });
2810
+ }
2811
+ const packageJsonPath = isGlobal ? GLOBAL_PACKAGE_JSON : ".pi/plugins.json";
2812
+ if (!existsSync4(packageJsonPath)) {
2813
+ results.push({
2814
+ check: "Package manifest",
2815
+ status: "warning",
2816
+ message: `${packageJsonPath} does not exist`,
2817
+ fix: isGlobal ? "Run: omp install <package>" : "Run: omp init"
2818
+ });
2819
+ } else {
2820
+ results.push({
2821
+ check: "Package manifest",
2822
+ status: "ok",
2823
+ message: packageJsonPath
2824
+ });
2825
+ }
2826
+ const nodeModules = isGlobal ? NODE_MODULES_DIR : ".pi/node_modules";
2827
+ if (!existsSync4(nodeModules)) {
2828
+ results.push({
2829
+ check: "Node modules",
2830
+ status: "warning",
2831
+ message: `${nodeModules} does not exist`
2832
+ });
2833
+ } else {
2834
+ results.push({
2835
+ check: "Node modules",
2836
+ status: "ok",
2837
+ message: nodeModules
2838
+ });
2839
+ }
2840
+ const installedPlugins = await getInstalledPlugins(isGlobal);
2841
+ const brokenSymlinks = [];
2842
+ const missingSymlinks = [];
2843
+ for (const [name, pkgJson] of installedPlugins) {
2844
+ const symlinkStatus = await checkPluginSymlinks(name, pkgJson, isGlobal);
2845
+ if (symlinkStatus.broken.length > 0) {
2846
+ brokenSymlinks.push(...symlinkStatus.broken.map((s) => `${name}: ${s}`));
2847
+ }
2848
+ if (symlinkStatus.missing.length > 0) {
2849
+ missingSymlinks.push(...symlinkStatus.missing.map((s) => `${name}: ${s}`));
2850
+ }
2851
+ }
2852
+ if (brokenSymlinks.length > 0) {
2853
+ results.push({
2854
+ check: "Broken symlinks",
2855
+ status: "error",
2856
+ message: `${brokenSymlinks.length} broken symlink(s)`,
2857
+ fix: "Run: omp update <plugin> to re-create symlinks"
2858
+ });
2859
+ } else {
2860
+ results.push({
2861
+ check: "Symlinks",
2862
+ status: "ok",
2863
+ message: "All symlinks valid"
2864
+ });
2865
+ }
2866
+ if (missingSymlinks.length > 0) {
2867
+ results.push({
2868
+ check: "Missing symlinks",
2869
+ status: "warning",
2870
+ message: `${missingSymlinks.length} expected symlink(s) not found`,
2871
+ fix: "Run: omp update <plugin> to re-create symlinks"
2872
+ });
2873
+ }
2874
+ const conflicts = detectAllConflicts(installedPlugins);
2875
+ if (conflicts.length > 0) {
2876
+ results.push({
2877
+ check: "Conflicts",
2878
+ status: "warning",
2879
+ message: formatConflicts(conflicts).join("; ")
2880
+ });
2881
+ } else {
2882
+ results.push({
2883
+ check: "Conflicts",
2884
+ status: "ok",
2885
+ message: "No conflicts detected"
2886
+ });
2887
+ }
2888
+ const pluginsJson = await loadPluginsJson(isGlobal);
2889
+ const orphaned = [];
2890
+ for (const name of Object.keys(pluginsJson.plugins)) {
2891
+ const pkgJson = await readPluginPackageJson(name, isGlobal);
2892
+ if (!pkgJson) {
2893
+ orphaned.push(name);
2894
+ }
2895
+ }
2896
+ if (orphaned.length > 0) {
2897
+ results.push({
2898
+ check: "Orphaned entries",
2899
+ status: "warning",
2900
+ message: `${orphaned.length} plugin(s) in manifest but not in node_modules: ${orphaned.join(", ")}`,
2901
+ fix: "Run: omp install (to reinstall) or remove from manifest"
2902
+ });
2903
+ }
2904
+ if (options.json) {
2905
+ console.log(JSON.stringify({ results }, null, 2));
2906
+ return;
2907
+ }
2908
+ for (const result of results) {
2909
+ let icon;
2910
+ let color;
2911
+ switch (result.status) {
2912
+ case "ok":
2913
+ icon = "\u2713";
2914
+ color = source_default.green;
2915
+ break;
2916
+ case "warning":
2917
+ icon = "\u26A0";
2918
+ color = source_default.yellow;
2919
+ break;
2920
+ case "error":
2921
+ icon = "\u2717";
2922
+ color = source_default.red;
2923
+ break;
2924
+ }
2925
+ console.log(color(`${icon} ${result.check}: `) + result.message);
2926
+ if (result.fix && result.status !== "ok") {
2927
+ console.log(source_default.dim(` ${result.fix}`));
2928
+ }
2929
+ }
2930
+ const errors = results.filter((r) => r.status === "error");
2931
+ const warnings = results.filter((r) => r.status === "warning");
2932
+ console.log();
2933
+ if (errors.length === 0 && warnings.length === 0) {
2934
+ console.log(source_default.green("\u2713 All checks passed!"));
2935
+ } else {
2936
+ if (errors.length > 0) {
2937
+ console.log(source_default.red(`${errors.length} error(s) found`));
2938
+ }
2939
+ if (warnings.length > 0) {
2940
+ console.log(source_default.yellow(`${warnings.length} warning(s) found`));
2941
+ }
2942
+ }
2943
+ if (brokenSymlinks.length > 0) {
2944
+ console.log(source_default.red(`
2945
+ Broken symlinks:`));
2946
+ for (const s of brokenSymlinks) {
2947
+ console.log(source_default.dim(` - ${s}`));
2948
+ }
2949
+ }
2950
+ if (missingSymlinks.length > 0) {
2951
+ console.log(source_default.yellow(`
2952
+ Missing symlinks:`));
2953
+ for (const s of missingSymlinks) {
2954
+ console.log(source_default.dim(` - ${s}`));
2955
+ }
2956
+ }
2957
+ }
2958
+
2959
+ // src/commands/enable.ts
2960
+ async function enablePlugin(name, options = {}) {
2961
+ const isGlobal = options.global !== false;
2962
+ const pluginsJson = await loadPluginsJson(isGlobal);
2963
+ if (!pluginsJson.plugins[name]) {
2964
+ console.log(source_default.yellow(`Plugin "${name}" is not installed.`));
2965
+ return;
2966
+ }
2967
+ if (!pluginsJson.disabled?.includes(name)) {
2968
+ console.log(source_default.yellow(`Plugin "${name}" is already enabled.`));
2969
+ return;
2970
+ }
2971
+ try {
2972
+ const pkgJson = await readPluginPackageJson(name, isGlobal);
2973
+ if (!pkgJson) {
2974
+ console.log(source_default.red(`Could not read package.json for ${name}`));
2975
+ return;
2976
+ }
2977
+ console.log(source_default.blue(`Enabling ${name}...`));
2978
+ await createPluginSymlinks(name, pkgJson, isGlobal);
2979
+ pluginsJson.disabled = pluginsJson.disabled.filter((n) => n !== name);
2980
+ await savePluginsJson(pluginsJson, isGlobal);
2981
+ console.log(source_default.green(`\u2713 Enabled "${name}"`));
2982
+ if (options.json) {
2983
+ console.log(JSON.stringify({ name, enabled: true }, null, 2));
2984
+ }
2985
+ } catch (err) {
2986
+ console.log(source_default.red(`Error enabling plugin: ${err.message}`));
2987
+ }
2988
+ }
2989
+ async function disablePlugin(name, options = {}) {
2990
+ const isGlobal = options.global !== false;
2991
+ const pluginsJson = await loadPluginsJson(isGlobal);
2992
+ if (!pluginsJson.plugins[name]) {
2993
+ console.log(source_default.yellow(`Plugin "${name}" is not installed.`));
2994
+ return;
2995
+ }
2996
+ if (pluginsJson.disabled?.includes(name)) {
2997
+ console.log(source_default.yellow(`Plugin "${name}" is already disabled.`));
2998
+ return;
2999
+ }
3000
+ try {
3001
+ const pkgJson = await readPluginPackageJson(name, isGlobal);
3002
+ if (!pkgJson) {
3003
+ console.log(source_default.red(`Could not read package.json for ${name}`));
3004
+ return;
3005
+ }
3006
+ console.log(source_default.blue(`Disabling ${name}...`));
3007
+ await removePluginSymlinks(name, pkgJson);
3008
+ if (!pluginsJson.disabled) {
3009
+ pluginsJson.disabled = [];
3010
+ }
3011
+ pluginsJson.disabled.push(name);
3012
+ await savePluginsJson(pluginsJson, isGlobal);
3013
+ console.log(source_default.green(`\u2713 Disabled "${name}"`));
3014
+ console.log(source_default.dim(" Plugin is still installed, symlinks removed"));
3015
+ console.log(source_default.dim(` Re-enable with: omp enable ${name}`));
3016
+ if (options.json) {
3017
+ console.log(JSON.stringify({ name, enabled: false }, null, 2));
3018
+ }
3019
+ } catch (err) {
3020
+ console.log(source_default.red(`Error disabling plugin: ${err.message}`));
3021
+ }
3022
+ }
3023
+
3024
+ // src/npm.ts
3025
+ import { execSync } from "child_process";
3026
+ function npmExec(args, cwd) {
3027
+ const cmd = `npm ${args.join(" ")}`;
3028
+ return execSync(cmd, {
3029
+ cwd,
3030
+ stdio: ["pipe", "pipe", "pipe"],
3031
+ encoding: "utf-8"
3032
+ });
3033
+ }
3034
+ function npmExecWithPrefix(args, prefix) {
3035
+ return npmExec(["--prefix", prefix, ...args]);
3036
+ }
3037
+ async function npmInstall(packages, prefix, options = {}) {
3038
+ const args = ["install"];
3039
+ if (options.save) {
3040
+ args.push("--save");
3041
+ } else if (options.saveDev) {
3042
+ args.push("--save-dev");
3043
+ }
3044
+ args.push(...packages);
3045
+ npmExecWithPrefix(args, prefix);
3046
+ }
3047
+ async function npmUninstall(packages, prefix) {
3048
+ npmExecWithPrefix(["uninstall", ...packages], prefix);
3049
+ }
3050
+ async function npmInfo(packageName) {
3051
+ try {
3052
+ const output = npmExec(["info", packageName, "--json"]);
3053
+ return JSON.parse(output);
3054
+ } catch {
3055
+ return null;
3056
+ }
3057
+ }
3058
+ async function npmSearch(query, keyword = "omp-plugin") {
3059
+ try {
3060
+ const searchTerm = keyword ? `keywords:${keyword} ${query}` : query;
3061
+ const output = npmExec(["search", searchTerm, "--json"]);
3062
+ return JSON.parse(output);
3063
+ } catch {
3064
+ return [];
3065
+ }
3066
+ }
3067
+ async function npmOutdated(prefix) {
3068
+ try {
3069
+ const output = npmExecWithPrefix(["outdated", "--json"], prefix);
3070
+ return JSON.parse(output);
3071
+ } catch (err) {
3072
+ const error = err;
3073
+ if (error.stdout) {
3074
+ try {
3075
+ return JSON.parse(error.stdout);
3076
+ } catch {
3077
+ return {};
3078
+ }
3079
+ }
3080
+ return {};
3081
+ }
3082
+ }
3083
+ async function npmUpdate(packages, prefix) {
3084
+ const args = ["update"];
3085
+ if (packages.length > 0) {
3086
+ args.push(...packages);
3087
+ }
3088
+ npmExecWithPrefix(args, prefix);
3089
+ }
3090
+
3091
+ // src/commands/info.ts
3092
+ async function showInfo(packageName, options = {}) {
3093
+ console.log(source_default.blue(`Fetching info for ${packageName}...`));
3094
+ try {
3095
+ const info = await npmInfo(packageName);
3096
+ if (!info) {
3097
+ console.log(source_default.red(`Package not found: ${packageName}`));
3098
+ return;
3099
+ }
3100
+ if (options.json) {
3101
+ console.log(JSON.stringify(info, null, 2));
3102
+ return;
3103
+ }
3104
+ console.log();
3105
+ console.log(source_default.bold.green(info.name) + source_default.dim(` v${info.version}`));
3106
+ console.log();
3107
+ if (info.description) {
3108
+ console.log(source_default.white(info.description));
3109
+ console.log();
3110
+ }
3111
+ if (info.author) {
3112
+ const authorStr = typeof info.author === "string" ? info.author : `${info.author.name}${info.author.email ? ` <${info.author.email}>` : ""}`;
3113
+ console.log(source_default.dim("author: ") + authorStr);
3114
+ }
3115
+ if (info.homepage) {
3116
+ console.log(source_default.dim("homepage: ") + info.homepage);
3117
+ }
3118
+ if (info.repository) {
3119
+ const repoUrl = typeof info.repository === "string" ? info.repository : info.repository.url;
3120
+ console.log(source_default.dim("repo: ") + repoUrl);
3121
+ }
3122
+ if (info.keywords?.length) {
3123
+ console.log(source_default.dim("keywords: ") + info.keywords.join(", "));
3124
+ }
3125
+ const isOmpPlugin = info.keywords?.includes("omp-plugin");
3126
+ if (isOmpPlugin) {
3127
+ console.log(source_default.green(`
3128
+ \u2713 This is an omp plugin`));
3129
+ } else {
3130
+ console.log(source_default.yellow(`
3131
+ \u26A0 This package does not have the omp-plugin keyword`));
3132
+ console.log(source_default.dim(" It may work, but might not have omp.install configuration"));
3133
+ }
3134
+ if (options.versions && info["dist-tags"]) {
3135
+ console.log(source_default.dim(`
3136
+ dist-tags:`));
3137
+ for (const [tag, version] of Object.entries(info["dist-tags"])) {
3138
+ console.log(source_default.dim(` ${tag}: `) + version);
3139
+ }
3140
+ }
3141
+ console.log();
3142
+ console.log(source_default.dim(`Install with: omp install ${packageName}`));
3143
+ } catch (err) {
3144
+ console.log(source_default.red(`Error fetching info: ${err.message}`));
3145
+ }
3146
+ }
3147
+
3148
+ // src/commands/init.ts
3149
+ import { existsSync as existsSync5 } from "fs";
3150
+ import { mkdir as mkdir4, writeFile as writeFile3 } from "fs/promises";
3151
+ async function initProject(options = {}) {
3152
+ if (existsSync5(PROJECT_PLUGINS_JSON) && !options.force) {
3153
+ console.log(source_default.yellow(`${PROJECT_PLUGINS_JSON} already exists.`));
3154
+ console.log(source_default.dim("Use --force to overwrite"));
3155
+ return;
3156
+ }
3157
+ try {
3158
+ await mkdir4(PROJECT_PI_DIR, { recursive: true });
3159
+ const pluginsJson = {
3160
+ plugins: {},
3161
+ disabled: []
3162
+ };
3163
+ await writeFile3(PROJECT_PLUGINS_JSON, JSON.stringify(pluginsJson, null, 2));
3164
+ console.log(source_default.green(`\u2713 Created ${PROJECT_PLUGINS_JSON}`));
3165
+ console.log();
3166
+ console.log(source_default.dim("Next steps:"));
3167
+ console.log(source_default.dim(" 1. Add plugins: omp install <package> --save"));
3168
+ console.log(source_default.dim(" 2. Or edit plugins.json directly"));
3169
+ console.log(source_default.dim(" 3. Run: omp install (to install all)"));
3170
+ } catch (err) {
3171
+ console.log(source_default.red(`Error initializing project: ${err.message}`));
3172
+ }
3173
+ }
3174
+
3175
+ // src/commands/install.ts
3176
+ import { execSync as execSync2 } from "child_process";
3177
+ import { existsSync as existsSync6 } from "fs";
3178
+ import { cp, mkdir as mkdir5, readFile as readFile2, rm as rm2 } from "fs/promises";
3179
+ import { basename, join as join5, resolve } from "path";
3180
+ import { createInterface } from "readline";
3181
+ async function promptConflictResolution(conflict) {
3182
+ const rl = createInterface({
3183
+ input: process.stdin,
3184
+ output: process.stdout
3185
+ });
3186
+ return new Promise((resolve2) => {
3187
+ console.log(source_default.yellow(`
3188
+ \u26A0 Conflict: ${formatConflicts([conflict])[0]}`));
3189
+ conflict.plugins.forEach((p, i) => {
3190
+ console.log(` [${i + 1}] ${p.name}`);
3191
+ });
3192
+ console.log(` [${conflict.plugins.length + 1}] abort`);
3193
+ rl.question(" Choose: ", (answer) => {
3194
+ rl.close();
3195
+ const choice = parseInt(answer, 10);
3196
+ if (choice > 0 && choice <= conflict.plugins.length) {
3197
+ resolve2(choice - 1);
3198
+ } else {
3199
+ resolve2(null);
3200
+ }
3201
+ });
3202
+ });
3203
+ }
3204
+ function parsePackageSpec(spec) {
3205
+ if (spec.startsWith("@")) {
3206
+ const lastAt = spec.lastIndexOf("@");
3207
+ if (lastAt > 0) {
3208
+ return {
3209
+ name: spec.slice(0, lastAt),
3210
+ version: spec.slice(lastAt + 1)
3211
+ };
3212
+ }
3213
+ return { name: spec, version: "latest" };
3214
+ }
3215
+ const atIndex = spec.indexOf("@");
3216
+ if (atIndex > 0) {
3217
+ return {
3218
+ name: spec.slice(0, atIndex),
3219
+ version: spec.slice(atIndex + 1)
3220
+ };
3221
+ }
3222
+ return { name: spec, version: "latest" };
3223
+ }
3224
+ function isLocalPath(spec) {
3225
+ return spec.startsWith("/") || spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("~");
3226
+ }
3227
+ async function installPlugin(packages, options = {}) {
3228
+ const isGlobal = options.global !== false;
3229
+ const prefix = isGlobal ? PLUGINS_DIR : ".pi";
3230
+ const _nodeModules = isGlobal ? NODE_MODULES_DIR : PROJECT_NODE_MODULES;
3231
+ if (isGlobal) {
3232
+ await initGlobalPlugins();
3233
+ } else {
3234
+ await mkdir5(prefix, { recursive: true });
3235
+ if (!existsSync6(PROJECT_PLUGINS_JSON)) {
3236
+ await savePluginsJson({ plugins: {} }, false);
3237
+ }
3238
+ }
3239
+ if (!packages || packages.length === 0) {
3240
+ const pluginsJson = await loadPluginsJson(isGlobal);
3241
+ packages = Object.entries(pluginsJson.plugins).map(([name, version]) => `${name}@${version}`);
3242
+ if (packages.length === 0) {
3243
+ console.log(source_default.yellow("No plugins to install."));
3244
+ console.log(source_default.dim(isGlobal ? "Add plugins with: omp install <package>" : "Add plugins to .pi/plugins.json"));
3245
+ return;
3246
+ }
3247
+ console.log(source_default.blue(`Installing ${packages.length} plugin(s) from ${isGlobal ? "package.json" : "plugins.json"}...`));
3248
+ }
3249
+ const existingPlugins = await getInstalledPlugins(isGlobal);
3250
+ const results = [];
3251
+ for (const spec of packages) {
3252
+ if (isLocalPath(spec)) {
3253
+ const result = await installLocalPlugin(spec, isGlobal, options);
3254
+ results.push(result);
3255
+ continue;
3256
+ }
3257
+ const { name, version } = parsePackageSpec(spec);
3258
+ const pkgSpec = version === "latest" ? name : `${name}@${version}`;
3259
+ try {
3260
+ console.log(source_default.blue(`
3261
+ Installing ${pkgSpec}...`));
3262
+ const info = await npmInfo(pkgSpec);
3263
+ if (!info) {
3264
+ console.log(source_default.red(` \u2717 Package not found: ${name}`));
3265
+ results.push({ name, version, success: false, error: "Package not found" });
3266
+ continue;
3267
+ }
3268
+ console.log(source_default.dim(` Fetching from npm...`));
3269
+ await npmInstall([pkgSpec], prefix, { save: options.save || isGlobal });
3270
+ const pkgJson = await readPluginPackageJson(name, isGlobal);
3271
+ if (!pkgJson) {
3272
+ console.log(source_default.yellow(` \u26A0 Installed but no package.json found`));
3273
+ results.push({ name, version: info.version, success: true });
3274
+ continue;
3275
+ }
3276
+ const conflicts = detectConflicts(name, pkgJson, existingPlugins);
3277
+ if (conflicts.length > 0 && !options.force) {
3278
+ let abort = false;
3279
+ for (const conflict of conflicts) {
3280
+ const choice = await promptConflictResolution(conflict);
3281
+ if (choice === null) {
3282
+ abort = true;
3283
+ break;
3284
+ }
3285
+ }
3286
+ if (abort) {
3287
+ console.log(source_default.yellow(` Aborted due to conflicts`));
3288
+ execSync2(`npm uninstall --prefix ${prefix} ${name}`, { stdio: "pipe" });
3289
+ results.push({ name, version: info.version, success: false, error: "Conflicts" });
3290
+ continue;
3291
+ }
3292
+ }
3293
+ const _symlinkResult = await createPluginSymlinks(name, pkgJson, isGlobal);
3294
+ if (pkgJson.dependencies) {
3295
+ for (const depName of Object.keys(pkgJson.dependencies)) {
3296
+ const depPkgJson = await readPluginPackageJson(depName, isGlobal);
3297
+ if (depPkgJson?.omp?.install) {
3298
+ console.log(source_default.dim(` Processing dependency: ${depName}`));
3299
+ await createPluginSymlinks(depName, depPkgJson, isGlobal);
3300
+ }
3301
+ }
3302
+ }
3303
+ existingPlugins.set(name, pkgJson);
3304
+ console.log(source_default.green(`\u2713 Installed ${name}@${info.version}`));
3305
+ results.push({ name, version: info.version, success: true });
3306
+ } catch (err) {
3307
+ const errorMsg = err.message;
3308
+ console.log(source_default.red(` \u2717 Failed to install ${name}: ${errorMsg}`));
3309
+ results.push({ name, version, success: false, error: errorMsg });
3310
+ }
3311
+ }
3312
+ const successful = results.filter((r) => r.success);
3313
+ const failed = results.filter((r) => !r.success);
3314
+ console.log();
3315
+ if (successful.length > 0) {
3316
+ console.log(source_default.green(`\u2713 Installed ${successful.length} plugin(s)`));
3317
+ }
3318
+ if (failed.length > 0) {
3319
+ console.log(source_default.red(`\u2717 Failed to install ${failed.length} plugin(s)`));
3320
+ }
3321
+ if (options.json) {
3322
+ console.log(JSON.stringify({ results }, null, 2));
3323
+ }
3324
+ }
3325
+ async function installLocalPlugin(localPath, isGlobal, _options) {
3326
+ if (localPath.startsWith("~")) {
3327
+ localPath = join5(process.env.HOME || "", localPath.slice(1));
3328
+ }
3329
+ localPath = resolve(localPath);
3330
+ if (!existsSync6(localPath)) {
3331
+ console.log(source_default.red(`Error: Path does not exist: ${localPath}`));
3332
+ return { name: basename(localPath), version: "local", success: false, error: "Path not found" };
3333
+ }
3334
+ const _prefix = isGlobal ? PLUGINS_DIR : ".pi";
3335
+ const nodeModules = isGlobal ? NODE_MODULES_DIR : PROJECT_NODE_MODULES;
3336
+ try {
3337
+ const localPkgJsonPath = join5(localPath, "package.json");
3338
+ let pkgJson;
3339
+ if (existsSync6(localPkgJsonPath)) {
3340
+ pkgJson = JSON.parse(await readFile2(localPkgJsonPath, "utf-8"));
3341
+ } else {
3342
+ const ompJsonPath = join5(localPath, "omp.json");
3343
+ if (existsSync6(ompJsonPath)) {
3344
+ const ompJson = JSON.parse(await readFile2(ompJsonPath, "utf-8"));
3345
+ pkgJson = {
3346
+ name: ompJson.name || basename(localPath),
3347
+ version: ompJson.version || "0.0.0",
3348
+ description: ompJson.description,
3349
+ keywords: ["omp-plugin"],
3350
+ omp: {
3351
+ install: ompJson.install
3352
+ }
3353
+ };
3354
+ } else {
3355
+ pkgJson = {
3356
+ name: basename(localPath),
3357
+ version: "0.0.0",
3358
+ keywords: ["omp-plugin"]
3359
+ };
3360
+ }
3361
+ }
3362
+ const pluginName = pkgJson.name;
3363
+ const pluginDir = join5(nodeModules, pluginName);
3364
+ console.log(source_default.blue(`
3365
+ Installing ${pluginName} from ${localPath}...`));
3366
+ await mkdir5(nodeModules, { recursive: true });
3367
+ if (existsSync6(pluginDir)) {
3368
+ await rm2(pluginDir, { recursive: true, force: true });
3369
+ }
3370
+ await cp(localPath, pluginDir, { recursive: true });
3371
+ console.log(source_default.dim(` Copied to ${pluginDir}`));
3372
+ const pluginsJson = await loadPluginsJson(isGlobal);
3373
+ pluginsJson.plugins[pluginName] = `file:${localPath}`;
3374
+ await savePluginsJson(pluginsJson, isGlobal);
3375
+ await createPluginSymlinks(pluginName, pkgJson, isGlobal);
3376
+ console.log(source_default.green(`\u2713 Installed ${pluginName}@${pkgJson.version}`));
3377
+ return { name: pluginName, version: pkgJson.version, success: true };
3378
+ } catch (err) {
3379
+ const errorMsg = err.message;
3380
+ console.log(source_default.red(` \u2717 Failed: ${errorMsg}`));
3381
+ return { name: basename(localPath), version: "local", success: false, error: errorMsg };
3382
+ }
3383
+ }
3384
+
3385
+ // src/commands/link.ts
3386
+ import { existsSync as existsSync7 } from "fs";
3387
+ import { mkdir as mkdir6, readFile as readFile3, rm as rm3, symlink as symlink2 } from "fs/promises";
3388
+ import { basename as basename2, dirname as dirname3, join as join6, resolve as resolve2 } from "path";
3389
+ async function linkPlugin(localPath, options = {}) {
3390
+ const isGlobal = options.global !== false;
3391
+ const nodeModules = isGlobal ? NODE_MODULES_DIR : PROJECT_NODE_MODULES;
3392
+ if (localPath.startsWith("~")) {
3393
+ localPath = join6(process.env.HOME || "", localPath.slice(1));
3394
+ }
3395
+ localPath = resolve2(localPath);
3396
+ if (!existsSync7(localPath)) {
3397
+ console.log(source_default.red(`Error: Path does not exist: ${localPath}`));
3398
+ return;
3399
+ }
3400
+ let pkgJson;
3401
+ const localPkgJsonPath = join6(localPath, "package.json");
3402
+ const localOmpJsonPath = join6(localPath, "omp.json");
3403
+ if (existsSync7(localPkgJsonPath)) {
3404
+ pkgJson = JSON.parse(await readFile3(localPkgJsonPath, "utf-8"));
3405
+ } else if (existsSync7(localOmpJsonPath)) {
3406
+ const ompJson = JSON.parse(await readFile3(localOmpJsonPath, "utf-8"));
3407
+ pkgJson = {
3408
+ name: ompJson.name || options.name || basename2(localPath),
3409
+ version: ompJson.version || "0.0.0-dev",
3410
+ description: ompJson.description,
3411
+ keywords: ["omp-plugin"],
3412
+ omp: {
3413
+ install: ompJson.install
3414
+ }
3415
+ };
3416
+ } else {
3417
+ pkgJson = {
3418
+ name: options.name || basename2(localPath),
3419
+ version: "0.0.0-dev",
3420
+ keywords: ["omp-plugin"]
3421
+ };
3422
+ console.log(source_default.yellow(" Warning: No package.json or omp.json found"));
3423
+ }
3424
+ const pluginName = options.name || pkgJson.name;
3425
+ const pluginDir = join6(nodeModules, pluginName);
3426
+ const pluginsJson = await loadPluginsJson(isGlobal);
3427
+ if (pluginsJson.plugins[pluginName]) {
3428
+ console.log(source_default.yellow(`Plugin "${pluginName}" is already installed.`));
3429
+ console.log(source_default.dim("Use omp uninstall first, or specify a different name with -n"));
3430
+ return;
3431
+ }
3432
+ try {
3433
+ console.log(source_default.blue(`Linking ${localPath}...`));
3434
+ await mkdir6(dirname3(pluginDir), { recursive: true });
3435
+ if (existsSync7(pluginDir)) {
3436
+ await rm3(pluginDir, { force: true, recursive: true });
3437
+ }
3438
+ await symlink2(localPath, pluginDir);
3439
+ console.log(source_default.dim(` Symlinked: ${pluginDir} \u2192 ${localPath}`));
3440
+ pluginsJson.plugins[pluginName] = `file:${localPath}`;
3441
+ await savePluginsJson(pluginsJson, isGlobal);
3442
+ if (pkgJson.omp?.install?.length) {
3443
+ await createPluginSymlinks(pluginName, pkgJson, isGlobal);
3444
+ }
3445
+ console.log(source_default.green(`
3446
+ \u2713 Linked "${pluginName}"${pkgJson.version ? ` v${pkgJson.version}` : ""} (development mode)`));
3447
+ console.log(source_default.dim(" Changes to the source will be reflected immediately"));
3448
+ } catch (err) {
3449
+ console.log(source_default.red(`Error linking plugin: ${err.message}`));
3450
+ try {
3451
+ await rm3(pluginDir, { force: true });
3452
+ } catch {}
3453
+ }
3454
+ }
3455
+
3456
+ // src/commands/list.ts
3457
+ async function listPlugins(options = {}) {
3458
+ const isGlobal = options.global !== false;
3459
+ const pluginsJson = await loadPluginsJson(isGlobal);
3460
+ const pluginNames = Object.keys(pluginsJson.plugins);
3461
+ if (pluginNames.length === 0) {
3462
+ console.log(source_default.yellow("No plugins installed."));
3463
+ console.log(source_default.dim("Install one with: omp install <package>"));
3464
+ return;
3465
+ }
3466
+ if (options.json) {
3467
+ const plugins = {};
3468
+ for (const name of pluginNames) {
3469
+ const pkgJson = await readPluginPackageJson(name, isGlobal);
3470
+ const disabled = pluginsJson.disabled?.includes(name) || false;
3471
+ plugins[name] = {
3472
+ version: pkgJson?.version || pluginsJson.plugins[name],
3473
+ description: pkgJson?.description,
3474
+ disabled,
3475
+ files: pkgJson?.omp?.install?.map((e) => e.dest) || []
3476
+ };
3477
+ }
3478
+ console.log(JSON.stringify({ plugins }, null, 2));
3479
+ return;
3480
+ }
3481
+ const location = isGlobal ? "~/.pi/plugins" : ".pi";
3482
+ console.log(source_default.bold(`Installed plugins (${pluginNames.length}) [${location}]:
3483
+ `));
3484
+ for (const name of pluginNames.sort()) {
3485
+ const pkgJson = await readPluginPackageJson(name, isGlobal);
3486
+ const specifier = pluginsJson.plugins[name];
3487
+ const isLocal = specifier.startsWith("file:");
3488
+ const disabled = pluginsJson.disabled?.includes(name);
3489
+ const version = pkgJson?.version ? source_default.dim(` v${pkgJson.version}`) : "";
3490
+ const localBadge = isLocal ? source_default.cyan(" (local)") : "";
3491
+ const disabledBadge = disabled ? source_default.yellow(" (disabled)") : "";
3492
+ const icon = disabled ? source_default.gray("\u25CB") : source_default.green("\u25C6");
3493
+ console.log(`${icon} ${source_default.bold(name)}${version}${localBadge}${disabledBadge}`);
3494
+ if (pkgJson?.description) {
3495
+ console.log(source_default.dim(` ${pkgJson.description}`));
3496
+ }
3497
+ if (isLocal) {
3498
+ const localPath = specifier.replace("file:", "");
3499
+ console.log(source_default.dim(` path: ${localPath}`));
3500
+ }
3501
+ if (pkgJson?.omp?.install?.length) {
3502
+ const files = pkgJson.omp.install.map((e) => e.dest);
3503
+ console.log(source_default.dim(` files: ${files.join(", ")}`));
3504
+ }
3505
+ console.log();
3506
+ }
3507
+ }
3508
+
3509
+ // src/commands/outdated.ts
3510
+ async function showOutdated(options = {}) {
3511
+ const isGlobal = options.global !== false;
3512
+ const prefix = isGlobal ? PLUGINS_DIR : ".pi";
3513
+ console.log(source_default.blue("Checking for outdated plugins..."));
3514
+ try {
3515
+ const outdated = await npmOutdated(prefix);
3516
+ const pluginsJson = await loadPluginsJson(isGlobal);
3517
+ const managedOutdated = Object.entries(outdated).filter(([name]) => {
3518
+ return pluginsJson.plugins[name] !== undefined;
3519
+ });
3520
+ if (managedOutdated.length === 0) {
3521
+ console.log(source_default.green(`
3522
+ \u2713 All plugins are up to date!`));
3523
+ return;
3524
+ }
3525
+ if (options.json) {
3526
+ const result = Object.fromEntries(managedOutdated);
3527
+ console.log(JSON.stringify({ outdated: result }, null, 2));
3528
+ return;
3529
+ }
3530
+ console.log(source_default.bold(`
3531
+ Outdated plugins (${managedOutdated.length}):
3532
+ `));
3533
+ console.log(source_default.dim(" Package".padEnd(30)) + source_default.dim("Current".padEnd(15)) + source_default.dim("Wanted".padEnd(15)) + source_default.dim("Latest"));
3534
+ for (const [name, versions] of managedOutdated) {
3535
+ const current = versions.current || "?";
3536
+ const wanted = versions.wanted || "?";
3537
+ const latest = versions.latest || "?";
3538
+ const hasMinorUpdate = wanted !== current;
3539
+ const hasMajorUpdate = latest !== wanted;
3540
+ const wantedColor = hasMinorUpdate ? source_default.yellow : source_default.dim;
3541
+ const latestColor = hasMajorUpdate ? source_default.red : wantedColor;
3542
+ console.log(` ${source_default.white(name.padEnd(28))}` + `${source_default.dim(current.padEnd(15))}` + `${wantedColor(wanted.padEnd(15))}` + `${latestColor(latest)}`);
3543
+ }
3544
+ console.log();
3545
+ console.log(source_default.dim("Update with: omp update [package]"));
3546
+ console.log(source_default.dim(" - 'wanted' = latest within semver range"));
3547
+ console.log(source_default.dim(" - 'latest' = latest available version"));
3548
+ } catch (err) {
3549
+ console.log(source_default.red(`Error checking outdated: ${err.message}`));
3550
+ }
3551
+ }
3552
+
3553
+ // src/commands/search.ts
3554
+ async function searchPlugins(query, options = {}) {
3555
+ console.log(source_default.blue(`Searching npm for "${query}" with omp-plugin keyword...`));
3556
+ try {
3557
+ const results = await npmSearch(query, "omp-plugin");
3558
+ if (results.length === 0) {
3559
+ console.log(source_default.yellow(`
3560
+ No plugins found.`));
3561
+ console.log(source_default.dim("Try a different search term, or search without keyword:"));
3562
+ console.log(source_default.dim(" npm search omp-plugin"));
3563
+ return;
3564
+ }
3565
+ const limit = options.limit || 20;
3566
+ const displayResults = results.slice(0, limit);
3567
+ if (options.json) {
3568
+ console.log(JSON.stringify({ results: displayResults }, null, 2));
3569
+ return;
3570
+ }
3571
+ console.log(source_default.bold(`
3572
+ Found ${results.length} plugin(s):
3573
+ `));
3574
+ for (const result of displayResults) {
3575
+ console.log(source_default.green("\u25C6 ") + source_default.bold(result.name) + source_default.dim(` v${result.version}`));
3576
+ if (result.description) {
3577
+ console.log(source_default.dim(` ${result.description}`));
3578
+ }
3579
+ if (result.keywords?.length) {
3580
+ const otherKeywords = result.keywords.filter((k) => k !== "omp-plugin");
3581
+ if (otherKeywords.length > 0) {
3582
+ console.log(source_default.dim(` tags: ${otherKeywords.join(", ")}`));
3583
+ }
3584
+ }
3585
+ console.log();
3586
+ }
3587
+ if (results.length > limit) {
3588
+ console.log(source_default.dim(`... and ${results.length - limit} more. Use --limit to see more.`));
3589
+ }
3590
+ console.log(source_default.dim("Install with: omp install <package-name>"));
3591
+ } catch (err) {
3592
+ console.log(source_default.red(`Error searching: ${err.message}`));
3593
+ }
3594
+ }
3595
+
3596
+ // src/commands/uninstall.ts
3597
+ import { existsSync as existsSync8 } from "fs";
3598
+ import { rm as rm4 } from "fs/promises";
3599
+ import { join as join7 } from "path";
3600
+ async function uninstallPlugin(name, options = {}) {
3601
+ const isGlobal = options.global !== false;
3602
+ const prefix = isGlobal ? PLUGINS_DIR : ".pi";
3603
+ const nodeModules = isGlobal ? NODE_MODULES_DIR : PROJECT_NODE_MODULES;
3604
+ const pluginsJson = await loadPluginsJson(isGlobal);
3605
+ if (!pluginsJson.plugins[name]) {
3606
+ console.log(source_default.yellow(`Plugin "${name}" is not installed.`));
3607
+ return;
3608
+ }
3609
+ try {
3610
+ console.log(source_default.blue(`Uninstalling ${name}...`));
3611
+ const pkgJson = await readPluginPackageJson(name, isGlobal);
3612
+ if (pkgJson) {
3613
+ await removePluginSymlinks(name, pkgJson);
3614
+ }
3615
+ try {
3616
+ await npmUninstall([name], prefix);
3617
+ } catch (_err) {
3618
+ const pluginDir = join7(nodeModules, name);
3619
+ if (existsSync8(pluginDir)) {
3620
+ await rm4(pluginDir, { recursive: true, force: true });
3621
+ }
3622
+ }
3623
+ delete pluginsJson.plugins[name];
3624
+ if (pluginsJson.disabled) {
3625
+ pluginsJson.disabled = pluginsJson.disabled.filter((n) => n !== name);
3626
+ }
3627
+ await savePluginsJson(pluginsJson, isGlobal);
3628
+ console.log(source_default.green(`\u2713 Uninstalled "${name}"`));
3629
+ if (options.json) {
3630
+ console.log(JSON.stringify({ name, success: true }, null, 2));
3631
+ }
3632
+ } catch (err) {
3633
+ console.log(source_default.red(`Error uninstalling plugin: ${err.message}`));
3634
+ if (options.json) {
3635
+ console.log(JSON.stringify({ name, success: false, error: err.message }, null, 2));
3636
+ }
3637
+ }
3638
+ }
3639
+
3640
+ // src/commands/update.ts
3641
+ async function updatePlugin(name, options = {}) {
3642
+ const isGlobal = options.global !== false;
3643
+ const prefix = isGlobal ? PLUGINS_DIR : ".pi";
3644
+ const _nodeModules = isGlobal ? NODE_MODULES_DIR : PROJECT_NODE_MODULES;
3645
+ const pluginsJson = await loadPluginsJson(isGlobal);
3646
+ const pluginNames = Object.keys(pluginsJson.plugins);
3647
+ if (pluginNames.length === 0) {
3648
+ console.log(source_default.yellow("No plugins installed."));
3649
+ return;
3650
+ }
3651
+ if (name && !pluginsJson.plugins[name]) {
3652
+ console.log(source_default.yellow(`Plugin "${name}" is not installed.`));
3653
+ return;
3654
+ }
3655
+ const toUpdate = name ? [name] : pluginNames;
3656
+ const npmPlugins = toUpdate.filter((n) => {
3657
+ const version = pluginsJson.plugins[n];
3658
+ return !version.startsWith("file:");
3659
+ });
3660
+ const localPlugins = toUpdate.filter((n) => {
3661
+ const version = pluginsJson.plugins[n];
3662
+ return version.startsWith("file:");
3663
+ });
3664
+ if (localPlugins.length > 0) {
3665
+ console.log(source_default.dim(`Skipping ${localPlugins.length} local plugin(s): ${localPlugins.join(", ")}`));
3666
+ }
3667
+ if (npmPlugins.length === 0) {
3668
+ console.log(source_default.yellow("No npm plugins to update."));
3669
+ return;
3670
+ }
3671
+ console.log(source_default.blue(`Updating ${npmPlugins.length} plugin(s)...`));
3672
+ const results = [];
3673
+ try {
3674
+ const beforeVersions = {};
3675
+ for (const pluginName of npmPlugins) {
3676
+ const pkgJson = await readPluginPackageJson(pluginName, isGlobal);
3677
+ if (pkgJson) {
3678
+ beforeVersions[pluginName] = pkgJson.version;
3679
+ await removePluginSymlinks(pluginName, pkgJson, false);
3680
+ }
3681
+ }
3682
+ await npmUpdate(npmPlugins, prefix);
3683
+ for (const pluginName of npmPlugins) {
3684
+ const pkgJson = await readPluginPackageJson(pluginName, isGlobal);
3685
+ if (pkgJson) {
3686
+ const beforeVersion = beforeVersions[pluginName] || "unknown";
3687
+ const afterVersion = pkgJson.version;
3688
+ await createPluginSymlinks(pluginName, pkgJson, isGlobal);
3689
+ const changed = beforeVersion !== afterVersion;
3690
+ if (changed) {
3691
+ console.log(source_default.green(` \u2713 ${pluginName}: ${beforeVersion} \u2192 ${afterVersion}`));
3692
+ } else {
3693
+ console.log(source_default.dim(` \xB7 ${pluginName}: ${afterVersion} (already latest)`));
3694
+ }
3695
+ results.push({
3696
+ name: pluginName,
3697
+ from: beforeVersion,
3698
+ to: afterVersion,
3699
+ success: true
3700
+ });
3701
+ }
3702
+ }
3703
+ const updated = results.filter((r) => r.from !== r.to);
3704
+ console.log();
3705
+ console.log(source_default.dim(`Updated: ${updated.length}, Already latest: ${results.length - updated.length}`));
3706
+ if (options.json) {
3707
+ console.log(JSON.stringify({ results }, null, 2));
3708
+ }
3709
+ } catch (err) {
3710
+ console.log(source_default.red(`Error updating plugins: ${err.message}`));
3711
+ }
3712
+ }
3713
+
3714
+ // src/commands/why.ts
3715
+ import { existsSync as existsSync9, lstatSync as lstatSync2 } from "fs";
3716
+ import { readlink as readlink2 } from "fs/promises";
3717
+ import { join as join8, relative } from "path";
3718
+ async function whyFile(filePath, options = {}) {
3719
+ const isGlobal = options.global !== false;
3720
+ let relativePath = filePath;
3721
+ if (filePath.startsWith(PI_CONFIG_DIR)) {
3722
+ relativePath = relative(PI_CONFIG_DIR, filePath);
3723
+ } else if (filePath.startsWith("~/.pi/")) {
3724
+ relativePath = filePath.slice(6);
3725
+ }
3726
+ if (!relativePath.startsWith("agent/")) {
3727
+ const withAgent = `agent/${relativePath}`;
3728
+ const fullWithAgent = join8(PI_CONFIG_DIR, withAgent);
3729
+ if (existsSync9(fullWithAgent)) {
3730
+ relativePath = withAgent;
3731
+ }
3732
+ }
3733
+ const fullPath = join8(PI_CONFIG_DIR, relativePath);
3734
+ if (!existsSync9(fullPath)) {
3735
+ console.log(source_default.yellow(`File not found: ${fullPath}`));
3736
+ return;
3737
+ }
3738
+ const stats = lstatSync2(fullPath);
3739
+ const isSymlink = stats.isSymbolicLink();
3740
+ let target = null;
3741
+ if (isSymlink) {
3742
+ target = await readlink2(fullPath);
3743
+ }
3744
+ const installedPlugins = await getInstalledPlugins(isGlobal);
3745
+ const result = await traceInstalledFile(relativePath, installedPlugins);
3746
+ if (options.json) {
3747
+ console.log(JSON.stringify({
3748
+ path: relativePath,
3749
+ fullPath,
3750
+ isSymlink,
3751
+ target,
3752
+ plugin: result?.plugin || null,
3753
+ source: result?.entry.src || null
3754
+ }, null, 2));
3755
+ return;
3756
+ }
3757
+ console.log(source_default.bold(`File: ${relativePath}`));
3758
+ console.log(source_default.dim(`Full path: ${fullPath}`));
3759
+ console.log();
3760
+ if (isSymlink && target) {
3761
+ console.log(`${source_default.dim("Type: ")}symlink`);
3762
+ console.log(source_default.dim("Target: ") + target);
3763
+ console.log();
3764
+ }
3765
+ if (result) {
3766
+ console.log(source_default.green(`\u2713 Installed by: ${result.plugin}`));
3767
+ console.log(source_default.dim(` Source: ${result.entry.src}`));
3768
+ console.log(source_default.dim(` Dest: ${result.entry.dest}`));
3769
+ const pkgJson = await readPluginPackageJson(result.plugin, isGlobal);
3770
+ if (pkgJson) {
3771
+ console.log();
3772
+ console.log(source_default.dim(`Plugin version: ${pkgJson.version}`));
3773
+ if (pkgJson.description) {
3774
+ console.log(source_default.dim(`Description: ${pkgJson.description}`));
3775
+ }
3776
+ }
3777
+ } else {
3778
+ console.log(source_default.yellow("\u26A0 Not installed by any tracked plugin"));
3779
+ console.log(source_default.dim(" This file may have been created manually or by a plugin that was uninstalled."));
3780
+ }
3781
+ }
3782
+
3783
+ // src/migrate.ts
3784
+ import { existsSync as existsSync10 } from "fs";
3785
+ import { mkdir as mkdir7, readFile as readFile4, rename, rm as rm5, symlink as symlink3, writeFile as writeFile4 } from "fs/promises";
3786
+ import { basename as basename3, join as join9 } from "path";
3787
+ import { createInterface as createInterface2 } from "readline";
3788
+ async function promptMigration() {
3789
+ const rl = createInterface2({
3790
+ input: process.stdin,
3791
+ output: process.stdout
3792
+ });
3793
+ return new Promise((resolve3) => {
3794
+ rl.question(source_default.yellow("Migrate to npm-native format? [y/N] "), (answer) => {
3795
+ rl.close();
3796
+ resolve3(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
3797
+ });
3798
+ });
3799
+ }
3800
+ async function checkMigration(auto = false) {
3801
+ if (!hasLegacyManifest()) {
3802
+ return false;
3803
+ }
3804
+ console.log(source_default.yellow(`
3805
+ \u26A0 Legacy manifest.json detected`));
3806
+ console.log(source_default.dim(" oh-my-pi has been updated to use npm-native plugin management."));
3807
+ console.log();
3808
+ if (!auto) {
3809
+ const shouldMigrate = await promptMigration();
3810
+ if (!shouldMigrate) {
3811
+ console.log(source_default.dim(" Migration skipped. Use 'omp migrate' to migrate later."));
3812
+ return false;
3813
+ }
3814
+ }
3815
+ return await migrateToNpm();
3816
+ }
3817
+ async function migrateToNpm() {
3818
+ console.log(source_default.blue(`
3819
+ Migrating to npm-native format...`));
3820
+ try {
3821
+ const legacyManifest = await loadLegacyManifest();
3822
+ const plugins = Object.entries(legacyManifest.plugins);
3823
+ if (plugins.length === 0) {
3824
+ console.log(source_default.dim(" No plugins to migrate"));
3825
+ await archiveLegacyManifest();
3826
+ return true;
3827
+ }
3828
+ await mkdir7(NODE_MODULES_DIR, { recursive: true });
3829
+ const newPluginsJson = { plugins: {} };
3830
+ const migrated = [];
3831
+ const failed = [];
3832
+ for (const [name, info] of plugins) {
3833
+ try {
3834
+ console.log(source_default.dim(` Migrating ${name}...`));
3835
+ await migratePlugin(name, info);
3836
+ if (info.type === "npm" && info.package) {
3837
+ newPluginsJson.plugins[info.package] = info.version ? `^${info.version}` : "latest";
3838
+ } else if (info.type === "local" && info.path) {
3839
+ newPluginsJson.plugins[name] = `file:${info.path}`;
3840
+ } else if (info.type === "github" && info.repo) {
3841
+ newPluginsJson.plugins[name] = `file:${join9(NODE_MODULES_DIR, name)}`;
3842
+ }
3843
+ migrated.push(name);
3844
+ } catch (err) {
3845
+ console.log(source_default.yellow(` \u26A0 Failed to migrate ${name}: ${err.message}`));
3846
+ failed.push(name);
3847
+ }
3848
+ }
3849
+ await savePluginsJson(newPluginsJson, true);
3850
+ await archiveLegacyManifest();
3851
+ console.log();
3852
+ console.log(source_default.green(`\u2713 Migrated ${migrated.length} plugin(s)`));
3853
+ if (failed.length > 0) {
3854
+ console.log(source_default.yellow(`\u26A0 Failed to migrate ${failed.length} plugin(s): ${failed.join(", ")}`));
3855
+ }
3856
+ return true;
3857
+ } catch (err) {
3858
+ console.log(source_default.red(`Error during migration: ${err.message}`));
3859
+ return false;
3860
+ }
3861
+ }
3862
+ async function migratePlugin(name, info) {
3863
+ const oldPluginDir = join9(PLUGINS_DIR, name);
3864
+ const newPluginDir = join9(NODE_MODULES_DIR, name);
3865
+ if (!existsSync10(oldPluginDir)) {
3866
+ throw new Error(`Plugin directory not found: ${oldPluginDir}`);
3867
+ }
3868
+ if (info.linked && info.path) {
3869
+ await mkdir7(NODE_MODULES_DIR, { recursive: true });
3870
+ if (existsSync10(newPluginDir)) {
3871
+ await rm5(newPluginDir, { force: true, recursive: true });
3872
+ }
3873
+ await symlink3(info.path, newPluginDir);
3874
+ await rm5(oldPluginDir, { force: true });
3875
+ return;
3876
+ }
3877
+ if (existsSync10(newPluginDir)) {
3878
+ await rm5(newPluginDir, { force: true, recursive: true });
3879
+ }
3880
+ await rename(oldPluginDir, newPluginDir);
3881
+ const pkgJsonPath = join9(newPluginDir, "package.json");
3882
+ const ompJsonPath = join9(newPluginDir, "omp.json");
3883
+ if (!existsSync10(pkgJsonPath) && existsSync10(ompJsonPath)) {
3884
+ const ompJson = JSON.parse(await readFile4(ompJsonPath, "utf-8"));
3885
+ const pkgJson = {
3886
+ name: ompJson.name || name,
3887
+ version: ompJson.version || info.version || "0.0.0",
3888
+ description: ompJson.description,
3889
+ keywords: ["omp-plugin"],
3890
+ omp: {
3891
+ install: ompJson.install
3892
+ }
3893
+ };
3894
+ await writeFile4(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
3895
+ }
3896
+ }
3897
+ async function archiveLegacyManifest() {
3898
+ if (!existsSync10(LEGACY_MANIFEST_PATH)) {
3899
+ return;
3900
+ }
3901
+ const archivePath = join9(PLUGINS_DIR, `manifest.json.bak.${Date.now()}`);
3902
+ await rename(LEGACY_MANIFEST_PATH, archivePath);
3903
+ console.log(source_default.dim(` Archived old manifest to ${basename3(archivePath)}`));
3904
+ }
3905
+
3906
+ // src/cli.ts
3907
+ program.name("omp").description("Oh My Pi - Plugin manager for pi configuration").version("0.1.0");
3908
+ program.hook("preAction", async (thisCommand) => {
3909
+ const migratingCommands = ["install", "uninstall", "update", "list", "link"];
3910
+ if (migratingCommands.includes(thisCommand.name())) {
3911
+ await checkMigration();
3912
+ }
3913
+ });
3914
+ program.command("install [packages...]").alias("i").description("Install plugin(s). No args = install from plugins.json").addHelpText("after", `
3915
+ Examples:
3916
+ $ omp install @oh-my-pi/subagents # Install from npm
3917
+ $ omp install @oh-my-pi/subagents@^2.0.0 # Specific version range
3918
+ $ omp install @myorg/cool-theme # Scoped package
3919
+ $ omp install ./local/path # Local directory (copies)
3920
+ $ omp install # Install all from plugins.json
3921
+ `).option("-g, --global", "Install globally to ~/.pi (default)").option("-S, --save", "Add to plugins.json").option("-D, --save-dev", "Add as dev dependency").option("--force", "Overwrite conflicts without prompting").option("--json", "Output as JSON").action(installPlugin);
3922
+ program.command("uninstall <name>").alias("rm").description("Remove plugin and its symlinks").option("-g, --global", "Uninstall from ~/.pi (default)").option("--json", "Output as JSON").action(uninstallPlugin);
3923
+ program.command("update [name]").alias("up").description("Update to latest within semver range").option("-g, --global", "Update global plugins (default)").option("--json", "Output as JSON").action(updatePlugin);
3924
+ program.command("list").alias("ls").description("Show installed plugins").option("-g, --global", "List global plugins (default)").option("--json", "Output as JSON").action(listPlugins);
3925
+ program.command("link <path>").description("Symlink local plugin (dev mode)").addHelpText("after", `
3926
+ Unlike install, link creates a symlink to the original directory,
3927
+ so changes are reflected immediately without reinstalling.
3928
+ `).option("-n, --name <name>", "Custom name for the plugin").option("-g, --global", "Link globally (default)").action(linkPlugin);
3929
+ program.command("init").description("Create .pi/plugins.json in current project").option("--force", "Overwrite existing plugins.json").action(initProject);
3930
+ program.command("search <query>").description("Search npm for omp-plugin keyword").option("--json", "Output as JSON").option("--limit <n>", "Maximum results to show", "20").action((query, options) => searchPlugins(query, { ...options, limit: parseInt(options.limit, 10) }));
3931
+ program.command("info <package>").description("Show plugin details before install").option("--json", "Output as JSON").option("--versions", "Show available versions").action(showInfo);
3932
+ program.command("outdated").description("List plugins with newer versions").option("-g, --global", "Check global plugins (default)").option("--json", "Output as JSON").action(showOutdated);
3933
+ program.command("doctor").description("Check for broken symlinks, conflicts").option("-g, --global", "Check global plugins (default)").option("--fix", "Attempt to fix issues").option("--json", "Output as JSON").action(runDoctor);
3934
+ program.command("create <name>").description("Scaffold new plugin from template").option("-d, --description <desc>", "Plugin description").option("-a, --author <author>", "Plugin author").action(createPlugin);
3935
+ program.command("why <file>").description("Show which plugin installed a file").option("-g, --global", "Check global plugins (default)").option("--json", "Output as JSON").action(whyFile);
3936
+ program.command("enable <name>").description("Enable a disabled plugin").option("-g, --global", "Target global plugins (default)").option("--json", "Output as JSON").action(enablePlugin);
3937
+ program.command("disable <name>").description("Disable plugin without uninstalling").option("-g, --global", "Target global plugins (default)").option("--json", "Output as JSON").action(disablePlugin);
3938
+ program.command("migrate").description("Migrate from legacy manifest.json to npm-native format").action(async () => {
3939
+ await migrateToNpm();
3940
+ });
3941
+ program.parse();