padrone 1.4.0 → 1.5.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 (82) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +105 -284
  3. package/dist/{args-CVDbyyzG.mjs → args-D5PNDyNu.mjs} +41 -18
  4. package/dist/args-D5PNDyNu.mjs.map +1 -0
  5. package/dist/chunk-CjcI7cDX.mjs +15 -0
  6. package/dist/codegen/index.d.mts +28 -3
  7. package/dist/codegen/index.d.mts.map +1 -1
  8. package/dist/codegen/index.mjs +169 -19
  9. package/dist/codegen/index.mjs.map +1 -1
  10. package/dist/command-utils-B1D-HqCd.mjs +1117 -0
  11. package/dist/command-utils-B1D-HqCd.mjs.map +1 -0
  12. package/dist/completion.d.mts +1 -1
  13. package/dist/completion.d.mts.map +1 -1
  14. package/dist/completion.mjs +77 -29
  15. package/dist/completion.mjs.map +1 -1
  16. package/dist/docs/index.d.mts +22 -2
  17. package/dist/docs/index.d.mts.map +1 -1
  18. package/dist/docs/index.mjs +94 -7
  19. package/dist/docs/index.mjs.map +1 -1
  20. package/dist/errors-BiVrBgi6.mjs +114 -0
  21. package/dist/errors-BiVrBgi6.mjs.map +1 -0
  22. package/dist/{formatter-ClUK5hcQ.d.mts → formatter-DtHzbP22.d.mts} +34 -5
  23. package/dist/formatter-DtHzbP22.d.mts.map +1 -0
  24. package/dist/help-bbmu9-qd.mjs +735 -0
  25. package/dist/help-bbmu9-qd.mjs.map +1 -0
  26. package/dist/index.d.mts +32 -3
  27. package/dist/index.d.mts.map +1 -1
  28. package/dist/index.mjs +493 -265
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/mcp-mLWIdUIu.mjs +379 -0
  31. package/dist/mcp-mLWIdUIu.mjs.map +1 -0
  32. package/dist/serve-B0u43DK7.mjs +404 -0
  33. package/dist/serve-B0u43DK7.mjs.map +1 -0
  34. package/dist/stream-BcC146Ud.mjs +56 -0
  35. package/dist/stream-BcC146Ud.mjs.map +1 -0
  36. package/dist/test.d.mts +1 -1
  37. package/dist/test.mjs +4 -15
  38. package/dist/test.mjs.map +1 -1
  39. package/dist/{types-DjIdJN5G.d.mts → types-Ch8Mk6Qb.d.mts} +310 -62
  40. package/dist/types-Ch8Mk6Qb.d.mts.map +1 -0
  41. package/dist/{update-check-EbNDkzyV.mjs → update-check-CFX1FV3v.mjs} +2 -2
  42. package/dist/{update-check-EbNDkzyV.mjs.map → update-check-CFX1FV3v.mjs.map} +1 -1
  43. package/dist/zod.d.mts +32 -0
  44. package/dist/zod.d.mts.map +1 -0
  45. package/dist/zod.mjs +50 -0
  46. package/dist/zod.mjs.map +1 -0
  47. package/package.json +10 -2
  48. package/src/args.ts +68 -40
  49. package/src/cli/docs.ts +1 -7
  50. package/src/cli/doctor.ts +195 -10
  51. package/src/cli/index.ts +1 -1
  52. package/src/cli/init.ts +2 -3
  53. package/src/cli/link.ts +2 -2
  54. package/src/codegen/discovery.ts +80 -28
  55. package/src/codegen/index.ts +2 -1
  56. package/src/codegen/parsers/bash.ts +179 -0
  57. package/src/codegen/schema-to-code.ts +2 -1
  58. package/src/colorizer.ts +126 -13
  59. package/src/command-utils.ts +380 -30
  60. package/src/completion.ts +120 -47
  61. package/src/create.ts +480 -128
  62. package/src/docs/index.ts +122 -8
  63. package/src/formatter.ts +171 -125
  64. package/src/help.ts +45 -12
  65. package/src/index.ts +29 -1
  66. package/src/interactive.ts +45 -4
  67. package/src/mcp.ts +390 -0
  68. package/src/repl-loop.ts +16 -3
  69. package/src/runtime.ts +195 -2
  70. package/src/serve.ts +442 -0
  71. package/src/stream.ts +75 -0
  72. package/src/test.ts +7 -16
  73. package/src/type-utils.ts +28 -4
  74. package/src/types.ts +212 -30
  75. package/src/wrap.ts +23 -25
  76. package/src/zod.ts +50 -0
  77. package/dist/args-CVDbyyzG.mjs.map +0 -1
  78. package/dist/chunk-y_GBKt04.mjs +0 -5
  79. package/dist/formatter-ClUK5hcQ.d.mts.map +0 -1
  80. package/dist/help-CcBe91bV.mjs +0 -1254
  81. package/dist/help-CcBe91bV.mjs.map +0 -1
  82. package/dist/types-DjIdJN5G.d.mts.map +0 -1
package/src/completion.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { extractSchemaMetadata } from './args.ts';
1
+ import { extractSchemaMetadata, JSON_SCHEMA_OPTS } from './args.ts';
2
2
  import { detectShell, getRcFile, type ShellType, writeToRcFile } from './shell-utils.ts';
3
3
  import type { AnyPadroneCommand } from './types.ts';
4
4
 
@@ -22,11 +22,19 @@ function collectAllCommands(cmd: AnyPadroneCommand): AnyPadroneCommand[] {
22
22
  return result;
23
23
  }
24
24
 
25
+ interface ExtractedArg {
26
+ name: string;
27
+ alias?: string;
28
+ isBoolean: boolean;
29
+ enum?: string[];
30
+ description?: string;
31
+ }
32
+
25
33
  /**
26
34
  * Extracts all argument names from a command's schema.
27
35
  */
28
- function extractArguments(cmd: AnyPadroneCommand): { name: string; alias?: string; isBoolean: boolean }[] {
29
- const argList: { name: string; alias?: string; isBoolean: boolean }[] = [];
36
+ function extractArguments(cmd: AnyPadroneCommand): ExtractedArg[] {
37
+ const argList: ExtractedArg[] = [];
30
38
 
31
39
  if (!cmd.argsSchema) return argList;
32
40
 
@@ -34,21 +42,24 @@ function extractArguments(cmd: AnyPadroneCommand): { name: string; alias?: strin
34
42
  const argsMeta = cmd.meta?.fields;
35
43
  const { aliases } = extractSchemaMetadata(cmd.argsSchema, argsMeta, cmd.meta?.autoAlias);
36
44
 
37
- // Reverse aliases map (alias -> arg name)
38
- const aliasToArgument: Record<string, string> = {};
39
- for (const [arg, alias] of Object.entries(aliases)) {
40
- aliasToArgument[alias] = arg;
45
+ // Build reverse map: argName aliasName
46
+ const argToAlias: Record<string, string> = {};
47
+ for (const [aliasName, argName] of Object.entries(aliases)) {
48
+ if (!argToAlias[argName]) argToAlias[argName] = aliasName;
41
49
  }
42
50
 
43
- const jsonSchema = cmd.argsSchema['~standard'].jsonSchema.input({ target: 'draft-2020-12' }) as Record<string, any>;
51
+ const jsonSchema = cmd.argsSchema['~standard'].jsonSchema.input(JSON_SCHEMA_OPTS) as Record<string, any>;
44
52
 
45
53
  if (jsonSchema.type === 'object' && jsonSchema.properties) {
46
54
  for (const [key, prop] of Object.entries(jsonSchema.properties as Record<string, any>)) {
47
- const alias = Object.entries(aliases).find(([arg]) => arg === key)?.[1];
55
+ const enumValues = (prop.enum ?? prop.items?.enum) as string[] | undefined;
56
+ const optMeta = argsMeta?.[key];
48
57
  argList.push({
49
58
  name: key,
50
- alias: alias,
59
+ alias: argToAlias[key],
51
60
  isBoolean: prop?.type === 'boolean',
61
+ enum: enumValues,
62
+ description: optMeta?.description ?? prop.description,
52
63
  });
53
64
  }
54
65
  }
@@ -59,6 +70,23 @@ function extractArguments(cmd: AnyPadroneCommand): { name: string; alias?: strin
59
70
  return argList;
60
71
  }
61
72
 
73
+ /**
74
+ * Collects unique args across all commands, preserving first-seen enum values.
75
+ */
76
+ function collectUniqueArgs(program: AnyPadroneCommand, commands: AnyPadroneCommand[]): Map<string, ExtractedArg> {
77
+ const seen = new Map<string, ExtractedArg>();
78
+
79
+ for (const cmd of [program, ...commands]) {
80
+ for (const arg of extractArguments(cmd)) {
81
+ if (!seen.has(arg.name)) {
82
+ seen.set(arg.name, arg);
83
+ }
84
+ }
85
+ }
86
+
87
+ return seen;
88
+ }
89
+
62
90
  /**
63
91
  * Generates a Bash completion script for the program.
64
92
  */
@@ -66,21 +94,41 @@ export function generateBashCompletion(program: AnyPadroneCommand): string {
66
94
  const programName = program.name;
67
95
  const commands = collectAllCommands(program);
68
96
  const commandNames = commands.map((c) => c.name).join(' ');
97
+ const uniqueArgs = collectUniqueArgs(program, commands);
69
98
 
70
- // Collect all args from all commands
99
+ // Collect all option names
71
100
  const allArguments = new Set<string>();
72
101
  allArguments.add('--help');
73
102
  allArguments.add('--version');
74
103
 
75
- for (const cmd of [program, ...commands]) {
76
- for (const arg of extractArguments(cmd)) {
77
- allArguments.add(`--${arg.name}`);
78
- if (arg.alias) allArguments.add(`-${arg.alias}`);
79
- }
104
+ for (const arg of uniqueArgs.values()) {
105
+ allArguments.add(`--${arg.name}`);
106
+ if (arg.alias) allArguments.add(`--${arg.alias}`);
80
107
  }
81
108
 
82
109
  const argsList = Array.from(allArguments).join(' ');
83
110
 
111
+ // Build case branches for options with enum values
112
+ const enumCases: string[] = [];
113
+ for (const arg of uniqueArgs.values()) {
114
+ if (!arg.enum || arg.enum.length === 0) continue;
115
+ const values = arg.enum.join(' ');
116
+ const patterns = [`--${arg.name}`];
117
+ if (arg.alias) patterns.push(`--${arg.alias}`);
118
+ enumCases.push(` ${patterns.join('|')}) COMPREPLY=($(compgen -W "${values}" -- "$cur")); return 0 ;;`);
119
+ }
120
+
121
+ const enumBlock =
122
+ enumCases.length > 0
123
+ ? `
124
+ # Complete option values
125
+ case "$prev" in
126
+ ${enumCases.join('\n')}
127
+ esac
128
+
129
+ `
130
+ : '\n';
131
+
84
132
  return `###-begin-${programName}-completion-###
85
133
  #
86
134
  # ${programName} command completion script
@@ -104,8 +152,7 @@ if type complete &>/dev/null; then
104
152
 
105
153
  local commands="${commandNames}"
106
154
  local args="${argsList}"
107
-
108
- # Complete args when current word starts with -
155
+ ${enumBlock} # Complete args when current word starts with -
109
156
  if [[ "$cur" == -* ]]; then
110
157
  COMPREPLY=($(compgen -W "$args" -- "$cur"))
111
158
  return 0
@@ -161,26 +208,24 @@ export function generateZshCompletion(program: AnyPadroneCommand): string {
161
208
  })
162
209
  .join('\n');
163
210
 
164
- // Collect all args with descriptions
211
+ // Collect all args with descriptions and enum values
165
212
  const argumentCompletions: string[] = [];
166
213
  argumentCompletions.push(" '--help[Show help information]'");
167
214
  argumentCompletions.push(" '--version[Show version number]'");
168
215
 
169
- const seenArgs = new Set<string>(['help', 'version']);
216
+ const uniqueArgs = collectUniqueArgs(program, commands);
170
217
 
171
- for (const cmd of [program, ...commands]) {
172
- for (const arg of extractArguments(cmd)) {
173
- if (seenArgs.has(arg.name)) continue;
174
- seenArgs.add(arg.name);
218
+ for (const arg of uniqueArgs.values()) {
219
+ const desc = arg.description || '';
220
+ const escapedDesc = desc.replace(/'/g, "'\\''").replace(/\[/g, '\\[').replace(/\]/g, '\\]');
175
221
 
176
- const desc = cmd.meta?.fields?.[arg.name]?.description || '';
177
- const escapedDesc = desc.replace(/'/g, "'\\''").replace(/\[/g, '\\[').replace(/\]/g, '\\]');
222
+ // Zsh action spec for enum values: :label:(val1 val2 val3)
223
+ const valueAction = arg.enum?.length ? `: :(${arg.enum.join(' ')})` : '';
178
224
 
179
- if (arg.alias) {
180
- argumentCompletions.push(` {-${arg.alias},--${arg.name}}'[${escapedDesc}]'`);
181
- } else {
182
- argumentCompletions.push(` '--${arg.name}[${escapedDesc}]'`);
183
- }
225
+ if (arg.alias) {
226
+ argumentCompletions.push(` {--${arg.alias},--${arg.name}}'[${escapedDesc}]${valueAction}'`);
227
+ } else {
228
+ argumentCompletions.push(` '--${arg.name}[${escapedDesc}]${valueAction}'`);
184
229
  }
185
230
  }
186
231
 
@@ -253,21 +298,18 @@ export function generateFishCompletion(program: AnyPadroneCommand): string {
253
298
  lines.push(`complete -c ${programName} -l help -d 'Show help information'`);
254
299
  lines.push(`complete -c ${programName} -l version -d 'Show version number'`);
255
300
 
256
- const seenArgs = new Set<string>(['help', 'version']);
301
+ const uniqueArgs = collectUniqueArgs(program, commands);
257
302
 
258
- for (const cmd of [program, ...commands]) {
259
- for (const arg of extractArguments(cmd)) {
260
- if (seenArgs.has(arg.name)) continue;
261
- seenArgs.add(arg.name);
262
-
263
- const desc = cmd.meta?.fields?.[arg.name]?.description || '';
264
- const escapedDesc = desc.replace(/'/g, "\\'");
303
+ for (const arg of uniqueArgs.values()) {
304
+ const desc = arg.description || '';
305
+ const escapedDesc = desc.replace(/'/g, "\\'");
306
+ // Fish: -xa 'val1 val2' provides exclusive value completions
307
+ const valueFlag = arg.enum?.length ? ` -xa '${arg.enum.join(' ')}'` : '';
265
308
 
266
- if (arg.alias) {
267
- lines.push(`complete -c ${programName} -s ${arg.alias} -l ${arg.name} -d '${escapedDesc}'`);
268
- } else {
269
- lines.push(`complete -c ${programName} -l ${arg.name} -d '${escapedDesc}'`);
270
- }
309
+ if (arg.alias) {
310
+ lines.push(`complete -c ${programName} -l ${arg.name} -s ${arg.alias} -d '${escapedDesc}'${valueFlag}`);
311
+ } else {
312
+ lines.push(`complete -c ${programName} -l ${arg.name} -d '${escapedDesc}'${valueFlag}`);
271
313
  }
272
314
  }
273
315
 
@@ -282,9 +324,41 @@ export function generateFishCompletion(program: AnyPadroneCommand): string {
282
324
  export function generatePowerShellCompletion(program: AnyPadroneCommand): string {
283
325
  const programName = program.name;
284
326
  const commands = collectAllCommands(program);
327
+ const uniqueArgs = collectUniqueArgs(program, commands);
285
328
 
286
329
  const commandNames = commands.map((c) => `'${c.name}'`).join(', ');
287
330
 
331
+ // Collect all option names
332
+ const argNames: string[] = ["'--help'", "'--version'"];
333
+ for (const arg of uniqueArgs.values()) {
334
+ argNames.push(`'--${arg.name}'`);
335
+ if (arg.alias) argNames.push(`'--${arg.alias}'`);
336
+ }
337
+
338
+ // Build switch cases for option value completion
339
+ const enumCases: string[] = [];
340
+ for (const arg of uniqueArgs.values()) {
341
+ if (!arg.enum || arg.enum.length === 0) continue;
342
+ const values = arg.enum.map((v) => `'${v}'`).join(', ');
343
+ const patterns = [`'--${arg.name}'`];
344
+ if (arg.alias) patterns.push(`'--${arg.alias}'`);
345
+ enumCases.push(` ${patterns.join(', ')} { @(${values}) | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
346
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
347
+ }; return }`);
348
+ }
349
+
350
+ const enumBlock =
351
+ enumCases.length > 0
352
+ ? `
353
+ # Complete option values
354
+ $prevWord = $commandAst.CommandElements | Select-Object -Last 2 | Select-Object -First 1
355
+ switch ($prevWord) {
356
+ ${enumCases.join('\n')}
357
+ }
358
+
359
+ `
360
+ : '\n';
361
+
288
362
  return `###-begin-${programName}-completion-###
289
363
  #
290
364
  # ${programName} command completion script for PowerShell
@@ -296,9 +370,8 @@ Register-ArgumentCompleter -Native -CommandName ${programName} -ScriptBlock {
296
370
  param($wordToComplete, $commandAst, $cursorPosition)
297
371
 
298
372
  $commands = @(${commandNames})
299
- $args = @('--help', '--version')
300
-
301
- if ($wordToComplete -like '-*') {
373
+ $args = @(${argNames.join(', ')})
374
+ ${enumBlock} if ($wordToComplete -like '-*') {
302
375
  $args | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
303
376
  [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
304
377
  }