argsbarg 1.4.3 → 2.0.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 (57) hide show
  1. package/.cursor/plans/cliprogram_capabilities_refactor_081e1737.plan.md +224 -0
  2. package/.private/scratch.md +1 -1
  3. package/CHANGELOG.md +39 -1
  4. package/README.md +29 -21
  5. package/docs/ai-skills.md +24 -52
  6. package/docs/install.md +84 -0
  7. package/docs/mcp.md +8 -8
  8. package/examples/mcp-test.ts +3 -3
  9. package/examples/minimal.ts +3 -3
  10. package/examples/nested.ts +3 -3
  11. package/examples/option-required.ts +3 -3
  12. package/index.d.ts +44 -50
  13. package/package.json +1 -1
  14. package/src/builtins/builtins.test.ts +101 -0
  15. package/src/builtins/completion-bash.ts +240 -0
  16. package/src/builtins/completion-fish.ts +73 -0
  17. package/src/builtins/completion-group.ts +50 -0
  18. package/src/builtins/completion-zsh.ts +244 -0
  19. package/src/builtins/dispatch.ts +138 -0
  20. package/src/builtins/export.ts +53 -0
  21. package/src/builtins/index.ts +10 -0
  22. package/src/builtins/install.ts +99 -0
  23. package/src/builtins/mcp.ts +13 -0
  24. package/src/builtins/presentation.ts +50 -0
  25. package/src/builtins/scopes.ts +46 -0
  26. package/src/builtins/shell-helpers.ts +24 -0
  27. package/src/capabilities.ts +32 -0
  28. package/src/completion.ts +10 -693
  29. package/src/context.ts +21 -6
  30. package/src/help.ts +21 -9
  31. package/src/index.test.ts +114 -118
  32. package/src/index.ts +2 -1
  33. package/src/install/binary.ts +82 -0
  34. package/src/install/compiled.ts +15 -0
  35. package/src/install/completions.ts +52 -0
  36. package/src/install/detect-installed.ts +67 -0
  37. package/src/install/index.ts +196 -0
  38. package/src/install/install.test.ts +124 -0
  39. package/src/install/mcp-config.ts +70 -0
  40. package/src/install/paths.ts +69 -0
  41. package/src/install/plan.ts +183 -0
  42. package/src/install/shell.ts +56 -0
  43. package/src/install/status.ts +63 -0
  44. package/src/install/uninstall.ts +111 -0
  45. package/src/invoke.ts +14 -5
  46. package/src/mcp/server.ts +3 -3
  47. package/src/mcp/tools.ts +17 -17
  48. package/src/mcp.ts +2 -2
  49. package/src/parse.ts +55 -27
  50. package/src/runtime.ts +47 -100
  51. package/src/schema.ts +10 -52
  52. package/src/skill/generate.ts +10 -10
  53. package/src/skill/install.ts +21 -19
  54. package/src/types.test.ts +40 -0
  55. package/src/types.ts +59 -49
  56. package/src/validate.ts +89 -83
  57. package/src/ai.ts +0 -7
package/src/context.ts CHANGED
@@ -7,7 +7,8 @@ It keeps handlers small with a typed read API for flags, strings, numbers, and c
7
7
  parsed values.
8
8
  */
9
9
 
10
- import type { CliCommand, CliInvocation } from "./types.ts";
10
+ import type { CliInvocation, CliNode, CliProgram } from "./types.ts";
11
+ import { isCliLeaf, isCliRouter } from "./types.ts";
11
12
  import { strictParseDouble } from "./utils.ts";
12
13
 
13
14
  /**
@@ -17,17 +18,22 @@ export class CliContext {
17
18
  readonly appName: string;
18
19
  readonly commandPath: string[];
19
20
  readonly args: string[];
20
- readonly schema: CliCommand;
21
+ readonly schema: CliProgram;
21
22
  readonly opts: Record<string, string>;
22
23
  readonly invocation: CliInvocation;
23
24
 
24
- /** Captures the merged program root, routed path, positional words, and option map for a leaf handler. */
25
+ /** Program root schema (same as {@link schema}). */
26
+ get program(): CliProgram {
27
+ return this.schema;
28
+ }
29
+
30
+ /** Captures the program root, routed path, positional words, and option map for a leaf handler. */
25
31
  constructor(
26
32
  appName: string,
27
33
  commandPath: string[],
28
34
  args: string[],
29
35
  opts: Record<string, string>,
30
- schema: CliCommand,
36
+ schema: CliProgram,
31
37
  invocation: CliInvocation = "cli",
32
38
  ) {
33
39
  this.appName = appName;
@@ -79,9 +85,13 @@ export class CliContext {
79
85
  private _positionalMap(): Record<string, string | string[]> {
80
86
  if (this._posMap) return this._posMap;
81
87
 
82
- let node: CliCommand = this.schema;
88
+ let node: CliNode = this.schema;
83
89
  for (const seg of this.commandPath) {
84
- const child = (node.commands ?? []).find((c) => c.key === seg);
90
+ if (!isCliRouter(node)) {
91
+ this._posMap = {};
92
+ return {};
93
+ }
94
+ const child = node.commands.find((c) => c.key === seg);
85
95
  if (!child) {
86
96
  this._posMap = {};
87
97
  return {};
@@ -89,6 +99,11 @@ export class CliContext {
89
99
  node = child;
90
100
  }
91
101
 
102
+ if (!isCliLeaf(node)) {
103
+ this._posMap = {};
104
+ return {};
105
+ }
106
+
92
107
  const map: Record<string, string | string[]> = {};
93
108
  let argIdx = 0;
94
109
  for (const p of node.positionals ?? []) {
package/src/help.ts CHANGED
@@ -7,7 +7,7 @@ It keeps help formatting shared across help and error paths so users see one con
7
7
  style no matter how help is reached.
8
8
  */
9
9
 
10
- import { CliCommand, CliOption, CliOptionKind, CliPositional } from "./types.ts";
10
+ import { CliNode, CliOption, CliOptionKind, CliPositional, CliRouter, isCliLeaf, isCliRouter } from "./types.ts";
11
11
 
12
12
  // ── ANSI Style Helpers ────────────────────────────────────────────────────────
13
13
 
@@ -369,7 +369,7 @@ function rowsForPositionals(defs: CliPositional[], color: boolean): HelpRow[] {
369
369
  }
370
370
 
371
371
  /** Table rows for subcommands, sorted by key. */
372
- function rowsForSubcommands(cmds: CliCommand[]): HelpRow[] {
372
+ function rowsForSubcommands(cmds: CliNode[]): HelpRow[] {
373
373
  return cmds
374
374
  .sort((a, b) => a.key.localeCompare(b.key))
375
375
  .map((c) => ({ label: c.key, description: c.description }));
@@ -381,7 +381,7 @@ function rowsForSubcommands(cmds: CliCommand[]): HelpRow[] {
381
381
  * Renders full help for the app root or a nested command, following `helpPath` from the root key.
382
382
  * `useStderr` is reserved for call-site consistency; width and color use stdout TTY.
383
383
  */
384
- export function cliHelpRender(schema: CliCommand, helpPath: string[], useStderr: boolean): string {
384
+ export function cliHelpRender(schema: CliRouter, helpPath: string[], useStderr: boolean): string {
385
385
  const hw = getHelpWidth();
386
386
  const color = isStdoutTTY();
387
387
 
@@ -416,14 +416,14 @@ export function cliHelpRender(schema: CliCommand, helpPath: string[], useStderr:
416
416
  }
417
417
 
418
418
  let layer = schema.commands ?? [];
419
- let node: CliCommand | undefined;
419
+ let node: CliNode | undefined;
420
420
  for (const seg of helpPath) {
421
- const ch = layer.find((c) => c.key === seg);
421
+ const ch = layer.find((c: CliNode) => c.key === seg);
422
422
  if (!ch) {
423
423
  return (color ? style.red("Unknown help path.") : "Unknown help path.") + "\n";
424
424
  }
425
425
  node = ch;
426
- layer = ch.commands ?? [];
426
+ layer = isCliRouter(ch) ? ch.commands : [];
427
427
  }
428
428
  if (!node) {
429
429
  return (color ? style.red("Unknown help path.") : "Unknown help path.") + "\n";
@@ -438,7 +438,13 @@ export function cliHelpRender(schema: CliCommand, helpPath: string[], useStderr:
438
438
  lines.push(
439
439
  renderTextBox(
440
440
  "Usage",
441
- usageLines(schema.key, helpPath, (node.commands ?? []).length > 0, (node.positionals ?? []).length > 0, color),
441
+ usageLines(
442
+ schema.key,
443
+ helpPath,
444
+ isCliRouter(node) && node.commands.length > 0,
445
+ isCliLeaf(node) && (node.positionals ?? []).length > 0,
446
+ color,
447
+ ),
442
448
  hw,
443
449
  color,
444
450
  ).join("\n"),
@@ -450,13 +456,19 @@ export function cliHelpRender(schema: CliCommand, helpPath: string[], useStderr:
450
456
  lines.push(optBox.join("\n"));
451
457
  }
452
458
 
453
- const posBox = renderTableBox("Arguments", rowsForPositionals(node.positionals ?? [], color), hw, color);
459
+ const posBox = renderTableBox(
460
+ "Arguments",
461
+ rowsForPositionals(isCliLeaf(node) ? (node.positionals ?? []) : [], color),
462
+ hw,
463
+ color,
464
+ );
454
465
  if (posBox.length > 0) {
455
466
  lines.push("");
456
467
  lines.push(posBox.join("\n"));
457
468
  }
458
469
 
459
- const subBox = renderTableBox("Subcommands", rowsForSubcommands(node.commands ?? []), hw, color);
470
+ const subcmds = isCliRouter(node) ? node.commands : [];
471
+ const subBox = renderTableBox("Subcommands", rowsForSubcommands(subcmds), hw, color);
460
472
  if (subBox.length > 0) {
461
473
  lines.push("");
462
474
  lines.push(subBox.join("\n"));