argsbarg 1.3.1 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/plans/mcp_v1.1_polish_e9656029.plan.md +260 -0
- package/.cursor/plans/mcp_v1.2_invocation_and_extensions_a4f82c1e.plan.md +647 -0
- package/CHANGELOG.md +30 -1
- package/README.md +21 -5
- package/docs/mcp.md +300 -0
- package/examples/mcp-test.ts +66 -0
- package/examples/nested.ts +1 -0
- package/index.d.ts +120 -23
- package/package.json +1 -1
- package/src/completion.ts +76 -4
- package/src/context.ts +4 -1
- package/src/help.ts +12 -2
- package/src/index.test.ts +692 -1
- package/src/index.ts +12 -1
- package/src/invoke.ts +192 -0
- package/src/mcp/env.ts +99 -0
- package/src/mcp/result.ts +57 -0
- package/src/mcp/server.ts +238 -0
- package/src/mcp/tools.ts +254 -0
- package/src/mcp.ts +28 -0
- package/src/parse.ts +17 -2
- package/src/runtime.ts +26 -2
- package/src/types.ts +81 -1
- package/src/validate.ts +54 -1
package/src/completion.ts
CHANGED
|
@@ -8,7 +8,7 @@ It keeps completion aligned with the runtime schema so the generated commands,
|
|
|
8
8
|
options, and descriptions stay in sync with the CLI definition.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { CliCommand, CliOption } from "./types.ts";
|
|
11
|
+
import { CliCommand, CliOption, CliOptionKind } from "./types.ts";
|
|
12
12
|
|
|
13
13
|
// ── Shared Types ───────────────────────────────────────────────────────────────
|
|
14
14
|
|
|
@@ -216,6 +216,31 @@ function emitSimulate(ident: string): string {
|
|
|
216
216
|
return o;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
/** Emits bash helper to complete Enum option values when previous token is --name. */
|
|
220
|
+
function emitEnumReplyBash(ident: string, scopes: ScopeRec[]): string {
|
|
221
|
+
let o = "_${ident}_nac_enum_reply() {\n".replace("${ident}", ident);
|
|
222
|
+
o += " local sid=\"$1\" prev=\"$2\" cur=\"$3\"\n";
|
|
223
|
+
o += " case $sid in\n";
|
|
224
|
+
for (const [i, sc] of scopes.entries()) {
|
|
225
|
+
const enumOpts = sc.opts.filter((op) => op.kind === CliOptionKind.Enum && (op.choices?.length ?? 0) > 0);
|
|
226
|
+
if (enumOpts.length === 0) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
o += " " + i + ")\n";
|
|
230
|
+
o += " case $prev in\n";
|
|
231
|
+
for (const op of enumOpts) {
|
|
232
|
+
const words = (op.choices ?? []).map((c) => escShellSingleQuoted(c)).join(" ");
|
|
233
|
+
o += " --" + op.name + ") COMPREPLY=( $(compgen -W '" + words + "' -- \"$cur\") ); return 0 ;;\n";
|
|
234
|
+
}
|
|
235
|
+
o += " esac\n";
|
|
236
|
+
o += " ;;\n";
|
|
237
|
+
}
|
|
238
|
+
o += " esac\n";
|
|
239
|
+
o += " return 1\n";
|
|
240
|
+
o += "}\n";
|
|
241
|
+
return o;
|
|
242
|
+
}
|
|
243
|
+
|
|
219
244
|
/** Emits the main `COMPREPLY` driver and `complete -F` registration for bash. */
|
|
220
245
|
function emitMainBodyBash(schema: CliCommand, ident: string): string {
|
|
221
246
|
const main = mainName(schema.key);
|
|
@@ -224,6 +249,7 @@ function emitMainBodyBash(schema: CliCommand, ident: string): string {
|
|
|
224
249
|
o += " local prev=\"${COMP_WORDS[COMP_CWORD-1]:-}\"\n";
|
|
225
250
|
o += " _${ident}_nac_simulate\n".replace("${ident}", ident);
|
|
226
251
|
o += " local sid=$REPLY_SID\n";
|
|
252
|
+
o += " if _${ident}_nac_enum_reply \"$sid\" \"$prev\" \"$cur\"; then return; fi\n".replace("${ident}", ident);
|
|
227
253
|
o += " if [[ $cur == -* ]]; then\n";
|
|
228
254
|
o += " local oname=\"A_${ident}_${sid}_opts\"\n".replace("${ident}", ident);
|
|
229
255
|
o += " local -a optsarr\n";
|
|
@@ -289,6 +315,7 @@ export function completionBashScript(schema: CliCommand): string {
|
|
|
289
315
|
out += emitConsumeShort(ident, scopes);
|
|
290
316
|
out += emitMatchChild(ident, scopes, pathIndex);
|
|
291
317
|
out += emitSimulate(ident);
|
|
318
|
+
out += emitEnumReplyBash(ident, scopes);
|
|
292
319
|
out += emitMainBodyBash(schema, ident);
|
|
293
320
|
|
|
294
321
|
return out;
|
|
@@ -470,6 +497,31 @@ function emitSimulateZsh(ident: string): string {
|
|
|
470
497
|
return o;
|
|
471
498
|
}
|
|
472
499
|
|
|
500
|
+
/** Emits zsh helper to complete Enum option values when previous token is --name. */
|
|
501
|
+
function emitEnumReplyZsh(ident: string, scopes: ScopeRec[]): string {
|
|
502
|
+
let o = "_${ident}_nac_enum_reply() {\n".replace("${ident}", ident);
|
|
503
|
+
o += " local sid=$1 prev=$2\n";
|
|
504
|
+
o += " case $sid in\n";
|
|
505
|
+
for (const [i, sc] of scopes.entries()) {
|
|
506
|
+
const enumOpts = sc.opts.filter((op) => op.kind === CliOptionKind.Enum && (op.choices?.length ?? 0) > 0);
|
|
507
|
+
if (enumOpts.length === 0) {
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
o += " " + i + ")\n";
|
|
511
|
+
o += " case $prev in\n";
|
|
512
|
+
for (const op of enumOpts) {
|
|
513
|
+
const vals = (op.choices ?? []).map((c) => escShellSingleQuoted(c)).join(" ");
|
|
514
|
+
o += " --" + op.name + ") _values " + vals + "; return 0 ;;\n";
|
|
515
|
+
}
|
|
516
|
+
o += " esac\n";
|
|
517
|
+
o += " ;;\n";
|
|
518
|
+
}
|
|
519
|
+
o += " esac\n";
|
|
520
|
+
o += " return 1\n";
|
|
521
|
+
o += "}\n";
|
|
522
|
+
return o;
|
|
523
|
+
}
|
|
524
|
+
|
|
473
525
|
/** Zsh: `_main` completer and `compdef` registration. */
|
|
474
526
|
function emitMainBodyZsh(schema: CliCommand, ident: string): string {
|
|
475
527
|
const main = mainName(schema.key);
|
|
@@ -477,6 +529,7 @@ function emitMainBodyZsh(schema: CliCommand, ident: string): string {
|
|
|
477
529
|
o += " local curcontext=\"$curcontext\" ret=1\n";
|
|
478
530
|
o += " _${ident}_nac_simulate\n".replace("${ident}", ident);
|
|
479
531
|
o += " local sid=$REPLY_SID\n";
|
|
532
|
+
o += " if _${ident}_nac_enum_reply \"$sid\" \"$words[CURRENT-1]\"; then return 0; fi\n".replace("${ident}", ident);
|
|
480
533
|
o += " if [[ $PREFIX == -* ]]; then\n";
|
|
481
534
|
o += " local -a optsarr\n";
|
|
482
535
|
o += " local oname=\"A_${ident}_${sid}_opts\"\n".replace("${ident}", ident);
|
|
@@ -517,12 +570,13 @@ export function completionZshScript(schema: CliCommand): string {
|
|
|
517
570
|
out += emitConsumeShortZsh(ident, scopes);
|
|
518
571
|
out += emitMatchChildZsh(ident, scopes, pathIndex);
|
|
519
572
|
out += emitSimulateZsh(ident);
|
|
573
|
+
out += emitEnumReplyZsh(ident, scopes);
|
|
520
574
|
out += emitMainBodyZsh(schema, ident);
|
|
521
575
|
return out;
|
|
522
576
|
}
|
|
523
577
|
|
|
524
578
|
/**
|
|
525
|
-
* Returns a schema suitable for help display, including
|
|
579
|
+
* Returns a schema suitable for help display, including reserved built-in subtrees.
|
|
526
580
|
* Routing roots get `completion` merged; leaf roots are wrapped as a tiny router.
|
|
527
581
|
*/
|
|
528
582
|
export function cliPresentationRoot(root: CliCommand): CliCommand {
|
|
@@ -534,15 +588,33 @@ export function cliPresentationRoot(root: CliCommand): CliCommand {
|
|
|
534
588
|
key: root.key,
|
|
535
589
|
description: root.description,
|
|
536
590
|
options: root.options,
|
|
537
|
-
commands:
|
|
591
|
+
commands: presentationBuiltins(root),
|
|
538
592
|
} as CliCommand;
|
|
539
593
|
}
|
|
540
594
|
return {
|
|
541
595
|
...root,
|
|
542
|
-
commands: [...(root.commands ?? []),
|
|
596
|
+
commands: [...(root.commands ?? []), ...presentationBuiltins(root)],
|
|
543
597
|
} as CliCommand;
|
|
544
598
|
}
|
|
545
599
|
|
|
600
|
+
/** Built-in commands shown in help and merged for routing CLIs. */
|
|
601
|
+
function presentationBuiltins(root: CliCommand): CliCommand[] {
|
|
602
|
+
const cmds: CliCommand[] = [cliBuiltinCompletionGroup(root.key)];
|
|
603
|
+
if (root.mcpServer !== undefined) {
|
|
604
|
+
cmds.push(cliBuiltinMcpCommand());
|
|
605
|
+
}
|
|
606
|
+
return cmds;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/** Builds the static `mcp` leaf command (merged when `root.mcpServer` is set). */
|
|
610
|
+
export function cliBuiltinMcpCommand(): CliCommand {
|
|
611
|
+
return {
|
|
612
|
+
key: "mcp",
|
|
613
|
+
description: "Run as an MCP server over stdio (for AI agents).",
|
|
614
|
+
handler: () => {},
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
|
|
546
618
|
/**
|
|
547
619
|
* Builds the static `completion` / `bash` / `zsh` command subtree (merged into the program root at runtime).
|
|
548
620
|
*/
|
package/src/context.ts
CHANGED
|
@@ -7,7 +7,7 @@ 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 } from "./types.ts";
|
|
10
|
+
import type { CliCommand, CliInvocation } from "./types.ts";
|
|
11
11
|
import { strictParseDouble } from "./utils.ts";
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -19,6 +19,7 @@ export class CliContext {
|
|
|
19
19
|
readonly args: string[];
|
|
20
20
|
readonly schema: CliCommand;
|
|
21
21
|
readonly opts: Record<string, string>;
|
|
22
|
+
readonly invocation: CliInvocation;
|
|
22
23
|
|
|
23
24
|
/** Captures the merged program root, routed path, positional words, and option map for a leaf handler. */
|
|
24
25
|
constructor(
|
|
@@ -27,12 +28,14 @@ export class CliContext {
|
|
|
27
28
|
args: string[],
|
|
28
29
|
opts: Record<string, string>,
|
|
29
30
|
schema: CliCommand,
|
|
31
|
+
invocation: CliInvocation = "cli",
|
|
30
32
|
) {
|
|
31
33
|
this.appName = appName;
|
|
32
34
|
this.commandPath = commandPath;
|
|
33
35
|
this.args = args;
|
|
34
36
|
this.opts = opts;
|
|
35
37
|
this.schema = schema;
|
|
38
|
+
this.invocation = invocation;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/** Returns whether a presence flag was set (including implicit "1" for boolean options). */
|
package/src/help.ts
CHANGED
|
@@ -151,7 +151,7 @@ function wrapText(text: string, width: number): string[] {
|
|
|
151
151
|
// ── Option Label Formatting ───────────────────────────────────────────────────
|
|
152
152
|
|
|
153
153
|
/** Suffix for `--name` in usage (e.g. ` <string>`) based on value kind. */
|
|
154
|
-
function optKindLabel(k: CliOptionKind): string {
|
|
154
|
+
function optKindLabel(k: CliOptionKind, o?: CliOption): string {
|
|
155
155
|
switch (k) {
|
|
156
156
|
case CliOptionKind.Presence:
|
|
157
157
|
return "";
|
|
@@ -159,12 +159,22 @@ function optKindLabel(k: CliOptionKind): string {
|
|
|
159
159
|
return " <number>";
|
|
160
160
|
case CliOptionKind.String:
|
|
161
161
|
return " <string>";
|
|
162
|
+
case CliOptionKind.Enum: {
|
|
163
|
+
const choices = o?.choices ?? [];
|
|
164
|
+
if (choices.length === 0) {
|
|
165
|
+
return " <choice>";
|
|
166
|
+
}
|
|
167
|
+
if (choices.length <= 4) {
|
|
168
|
+
return " <" + choices.join("|") + ">";
|
|
169
|
+
}
|
|
170
|
+
return " <" + choices.slice(0, 3).join("|") + "|…>";
|
|
171
|
+
}
|
|
162
172
|
}
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
/** Formats a flag/value option for help tables: `--name`, optional short, optional kind hint. */
|
|
166
176
|
export function cliOptionLabel(o: CliOption, color: boolean): string {
|
|
167
|
-
let r = "--" + o.name + optKindLabel(o.kind);
|
|
177
|
+
let r = "--" + o.name + optKindLabel(o.kind, o);
|
|
168
178
|
if (o.shortName) r += ", -" + o.shortName;
|
|
169
179
|
if (!color) return r;
|
|
170
180
|
|