argsbarg 5.0.1 → 5.0.3
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/CHANGELOG.md +15 -1
- package/docs/distribution-homebrew.md +2 -0
- package/examples/full-example/scripts/formula-shared.ts +1 -0
- package/index.d.ts +10 -5
- package/package.json +1 -1
- package/src/builtins/builtins.test.ts +12 -0
- package/src/builtins/config.test.ts +8 -0
- package/src/cli-tool/cli-smoke.test.ts +5 -0
- package/src/cli-tool/create.test.ts +10 -0
- package/src/cli-tool/full-example-capabilities.test.ts +6 -0
- package/src/cli-tool/main.ts +0 -0
- package/src/config/context.test.ts +7 -0
- package/src/config/file.test.ts +7 -0
- package/src/config/resolve.test.ts +11 -0
- package/src/config/validate.test.ts +5 -0
- package/src/config.integration.test.ts +5 -0
- package/src/configure/configure.test.ts +11 -0
- package/src/configure/index.ts +14 -0
- package/src/configure/prompt.ts +7 -0
- package/src/docs/api-guide.test.ts +6 -0
- package/src/docs/docs.test.ts +7 -0
- package/src/docs/mcp-resources.test.ts +4 -0
- package/src/formats.test.ts +4 -0
- package/src/headless.test.ts +6 -0
- package/src/headless.ts +5 -4
- package/src/hidden-mcpb.test.ts +10 -0
- package/src/install/binary-placement.test.ts +9 -0
- package/src/install/gh-release-update.test.ts +4 -0
- package/src/install/install-validate.test.ts +5 -0
- package/src/install/mcp-codex.test.ts +7 -0
- package/src/install/mcp-openclaw.test.ts +6 -0
- package/src/install/mcp-opencode.test.ts +6 -0
- package/src/install/status.test.ts +9 -0
- package/src/install/targets.test.ts +9 -0
- package/src/invoke.test.ts +7 -0
- package/src/mcp/claude.test.ts +6 -0
- package/src/mcp/env.test.ts +7 -0
- package/src/mcp/zip.test.ts +4 -0
- package/src/mcp.integration.test.ts +17 -0
- package/src/parse.test.ts +43 -0
package/src/parse.test.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from "./test-fixtures.ts";
|
|
32
32
|
import { cliValidateProgram } from "./validate.ts";
|
|
33
33
|
|
|
34
|
+
/** Tests that bundled short presence flags. */
|
|
34
35
|
test("bundled short presence flags", () => {
|
|
35
36
|
const root = testProgram({
|
|
36
37
|
key: "app",
|
|
@@ -64,6 +65,7 @@ test("bundled short presence flags", () => {
|
|
|
64
65
|
expect(pr.opts.b).toBe("1");
|
|
65
66
|
});
|
|
66
67
|
|
|
68
|
+
/** Tests that long option equals. */
|
|
67
69
|
test("long option equals", () => {
|
|
68
70
|
const root = testProgram({
|
|
69
71
|
key: "app",
|
|
@@ -89,6 +91,7 @@ test("long option equals", () => {
|
|
|
89
91
|
expect(pr.opts.name).toBe("pat");
|
|
90
92
|
});
|
|
91
93
|
|
|
94
|
+
/** Tests that fallback missing or unknown root flags. */
|
|
92
95
|
test("fallback missing or unknown root flags", () => {
|
|
93
96
|
const root = testProgram({
|
|
94
97
|
key: "app",
|
|
@@ -141,6 +144,7 @@ test("implicit help empty", () => {
|
|
|
141
144
|
expect(pr.helpExplicit).toBe(false);
|
|
142
145
|
});
|
|
143
146
|
|
|
147
|
+
/** Invalid number post validate. */
|
|
144
148
|
test("invalid number post validate", () => {
|
|
145
149
|
const root = testProgram({
|
|
146
150
|
key: "app",
|
|
@@ -167,6 +171,7 @@ test("invalid number post validate", () => {
|
|
|
167
171
|
expect(pr.errorMsg).toContain("Invalid number");
|
|
168
172
|
});
|
|
169
173
|
|
|
174
|
+
/** Supports scientific notation in numbers. */
|
|
170
175
|
test("supports scientific notation in numbers", () => {
|
|
171
176
|
const root = testProgram({
|
|
172
177
|
key: "app",
|
|
@@ -193,6 +198,7 @@ test("supports scientific notation in numbers", () => {
|
|
|
193
198
|
expect(Number(pr.opts.n)).toBe(12300);
|
|
194
199
|
});
|
|
195
200
|
|
|
201
|
+
/** Completion scripts contain app name. */
|
|
196
202
|
test("completion scripts contain app name", () => {
|
|
197
203
|
const root = testProgram({
|
|
198
204
|
key: "myapp",
|
|
@@ -210,6 +216,7 @@ test("completion scripts contain app name", () => {
|
|
|
210
216
|
expect(zsh).toContain("hello:Say hello.");
|
|
211
217
|
});
|
|
212
218
|
|
|
219
|
+
/** Completion scripts do not emit invalid bash substitutions. */
|
|
213
220
|
test("completion scripts do not emit invalid bash substitutions", () => {
|
|
214
221
|
const root = testProgram({
|
|
215
222
|
key: "app",
|
|
@@ -221,6 +228,7 @@ test("completion scripts do not emit invalid bash substitutions", () => {
|
|
|
221
228
|
expect(bash).not.toContain("${${");
|
|
222
229
|
});
|
|
223
230
|
|
|
231
|
+
/** Completion scripts escape shell-sensitive command text in zsh. */
|
|
224
232
|
test("completion scripts escape shell-sensitive command text in zsh", () => {
|
|
225
233
|
const root = testProgram({
|
|
226
234
|
key: "app",
|
|
@@ -238,6 +246,7 @@ test("completion scripts escape shell-sensitive command text in zsh", () => {
|
|
|
238
246
|
expect(zsh).toContain("quote'\\''cmd:Say '\\''hello'\\'' and keep going.");
|
|
239
247
|
});
|
|
240
248
|
|
|
249
|
+
/** Completion scripts keep dotted app names in registration names. */
|
|
241
250
|
test("completion scripts keep dotted app names in registration names", () => {
|
|
242
251
|
const root = testProgram({
|
|
243
252
|
key: "minimal.ts",
|
|
@@ -253,6 +262,7 @@ test("completion scripts keep dotted app names in registration names", () => {
|
|
|
253
262
|
expect(zsh).toContain("compdef _minimal_ts minimal.ts");
|
|
254
263
|
});
|
|
255
264
|
|
|
265
|
+
/** Tests that trailing options after bounded positionals. */
|
|
256
266
|
test("trailing options after bounded positionals", () => {
|
|
257
267
|
const root = testProgram({
|
|
258
268
|
key: "app",
|
|
@@ -286,6 +296,7 @@ test("trailing options after bounded positionals", () => {
|
|
|
286
296
|
expect(pr.opts.verbose).toBe("1");
|
|
287
297
|
});
|
|
288
298
|
|
|
299
|
+
/** Tests that trailing options include parent-scoped flags. */
|
|
289
300
|
test("trailing options include parent-scoped flags", () => {
|
|
290
301
|
const root = testProgram({
|
|
291
302
|
key: "app",
|
|
@@ -338,6 +349,7 @@ test("trailing options include parent-scoped flags", () => {
|
|
|
338
349
|
expect(pr.opts.json).toBe("1");
|
|
339
350
|
});
|
|
340
351
|
|
|
352
|
+
/** Varargs tail parses trailing options. */
|
|
341
353
|
test("varargs tail parses trailing options", () => {
|
|
342
354
|
const root = testProgram({
|
|
343
355
|
key: "app",
|
|
@@ -373,6 +385,7 @@ test("varargs tail parses trailing options", () => {
|
|
|
373
385
|
expect(pr.opts.json).toBe("1");
|
|
374
386
|
});
|
|
375
387
|
|
|
388
|
+
/** Stops parsing options at --. */
|
|
376
389
|
test("stops parsing options at --", () => {
|
|
377
390
|
const root = testProgram({
|
|
378
391
|
key: "app",
|
|
@@ -411,6 +424,7 @@ test("stops parsing options at --", () => {
|
|
|
411
424
|
expect(pr.args).toEqual(["--name", "bob", "-x"]);
|
|
412
425
|
});
|
|
413
426
|
|
|
427
|
+
/** Missing required option returns error. */
|
|
414
428
|
test("missing required option returns error", () => {
|
|
415
429
|
const root = testProgram({
|
|
416
430
|
key: "app",
|
|
@@ -437,6 +451,7 @@ test("missing required option returns error", () => {
|
|
|
437
451
|
expect(pr.errorMsg).toContain("Missing required option: --req");
|
|
438
452
|
});
|
|
439
453
|
|
|
454
|
+
/** Provided required option parses ok. */
|
|
440
455
|
test("provided required option parses ok", () => {
|
|
441
456
|
const root = testProgram({
|
|
442
457
|
key: "app",
|
|
@@ -463,6 +478,7 @@ test("provided required option parses ok", () => {
|
|
|
463
478
|
expect(pr.opts.req).toBe("val");
|
|
464
479
|
});
|
|
465
480
|
|
|
481
|
+
/** Tests that presence option cannot be required. */
|
|
466
482
|
test("presence option cannot be required", () => {
|
|
467
483
|
const root = testProgram({
|
|
468
484
|
key: "app",
|
|
@@ -499,6 +515,7 @@ test("leaf completion help prints correctly", async () => {
|
|
|
499
515
|
expect(stderr.toString()).toBe("");
|
|
500
516
|
});
|
|
501
517
|
|
|
518
|
+
/** Docs schema exports JSON for nested CLIs. */
|
|
502
519
|
test("docs schema exports JSON for nested CLIs", async () => {
|
|
503
520
|
const { stdout, stderr, exitCode } = await $`bun run examples/nested.ts docs schema`
|
|
504
521
|
.nothrow()
|
|
@@ -517,6 +534,7 @@ test("docs schema exports JSON for nested CLIs", async () => {
|
|
|
517
534
|
expect(lookup.positionals[0].name).toBe("path");
|
|
518
535
|
});
|
|
519
536
|
|
|
537
|
+
/** Docs schema exports JSON for leaf roots. */
|
|
520
538
|
test("docs schema exports JSON for leaf roots", async () => {
|
|
521
539
|
const { stdout, exitCode } = await $`bun run examples/minimal.ts docs schema`.nothrow().quiet();
|
|
522
540
|
expect(exitCode).toBe(0);
|
|
@@ -545,6 +563,7 @@ test("leaf root help omits hidden completion built-in", async () => {
|
|
|
545
563
|
expect(stdout.toString()).toContain("configure");
|
|
546
564
|
});
|
|
547
565
|
|
|
566
|
+
/** Root --schema is no longer a flag. */
|
|
548
567
|
test("root --schema is no longer a flag", () => {
|
|
549
568
|
const root = testProgram({
|
|
550
569
|
key: "app",
|
|
@@ -567,6 +586,7 @@ test("root --schema is no longer a flag", () => {
|
|
|
567
586
|
expect(pr.kind).not.toBe(ParseKind.Ok);
|
|
568
587
|
});
|
|
569
588
|
|
|
589
|
+
/** CliSchemaJson omits handlers and completion built-ins. */
|
|
570
590
|
test("cliSchemaJson omits handlers and completion built-ins", () => {
|
|
571
591
|
const root = testProgram({
|
|
572
592
|
key: "app",
|
|
@@ -597,6 +617,7 @@ test("cliSchemaJson omits handlers and completion built-ins", () => {
|
|
|
597
617
|
expect(schema).not.toHaveProperty("handler");
|
|
598
618
|
});
|
|
599
619
|
|
|
620
|
+
/** CliSchemaExport resolves program key in install notes. */
|
|
600
621
|
test("cliSchemaExport resolves program key in install notes", () => {
|
|
601
622
|
const root = testProgram({
|
|
602
623
|
key: "myapp",
|
|
@@ -616,6 +637,7 @@ test("cliSchemaExport resolves program key in install notes", () => {
|
|
|
616
637
|
expect(json).toContain("brew install");
|
|
617
638
|
});
|
|
618
639
|
|
|
640
|
+
/** CliSchemaExport resolves {argsbarg:program} in consumer notes. */
|
|
619
641
|
test("cliSchemaExport resolves {argsbarg:program} in consumer notes", () => {
|
|
620
642
|
const root = testProgram({
|
|
621
643
|
key: "myapp",
|
|
@@ -635,6 +657,7 @@ test("cliSchemaExport resolves {argsbarg:program} in consumer notes", () => {
|
|
|
635
657
|
expect(schema.commands[0].notes).toBe("Run `myapp run` to start.");
|
|
636
658
|
});
|
|
637
659
|
|
|
660
|
+
/** Docs help lists schema, api, and skill subcommands. */
|
|
638
661
|
test("docs help lists schema, api, and skill subcommands", () => {
|
|
639
662
|
const root = testProgram({
|
|
640
663
|
key: "app",
|
|
@@ -661,6 +684,7 @@ test("docs help lists schema, api, and skill subcommands", () => {
|
|
|
661
684
|
expect(help).toContain("reference agent SKILL");
|
|
662
685
|
});
|
|
663
686
|
|
|
687
|
+
/** Root help omits legacy --schema flag. */
|
|
664
688
|
test("root help omits legacy --schema flag", () => {
|
|
665
689
|
const root = testProgram({
|
|
666
690
|
key: "app",
|
|
@@ -678,6 +702,7 @@ test("root help omits legacy --schema flag", () => {
|
|
|
678
702
|
expect(help).not.toContain("--schema");
|
|
679
703
|
});
|
|
680
704
|
|
|
705
|
+
/** Root help shows agent docs hint when docs enabled. */
|
|
681
706
|
test("root help shows agent docs hint when docs enabled", () => {
|
|
682
707
|
const root = testProgram({
|
|
683
708
|
key: "myapp",
|
|
@@ -706,6 +731,7 @@ test("root help omits agent hint when docs disabled", () => {
|
|
|
706
731
|
expect(help).not.toContain("docs skill");
|
|
707
732
|
});
|
|
708
733
|
|
|
734
|
+
/** Root help includes program notes and agent hint. */
|
|
709
735
|
test("root help includes program notes and agent hint", () => {
|
|
710
736
|
const root = testProgram({
|
|
711
737
|
key: "myapp",
|
|
@@ -750,6 +776,7 @@ test("cliValidateProgram rejects Enum with duplicate choices", () => {
|
|
|
750
776
|
expect(() => cliValidateProgram(root)).toThrow(/choices must be distinct/);
|
|
751
777
|
});
|
|
752
778
|
|
|
779
|
+
/** McpTool.description override wins without env suffix. */
|
|
753
780
|
test("mcpTool.description override wins without env suffix", () => {
|
|
754
781
|
const root = testProgram({
|
|
755
782
|
key: "app",
|
|
@@ -778,6 +805,7 @@ test("cliValidateProgram requires program.appConfig description", () => {
|
|
|
778
805
|
expect(() => cliValidateProgram(root)).toThrow(/description must be a non-empty string/);
|
|
779
806
|
});
|
|
780
807
|
|
|
808
|
+
/** CliValidateProgram rejects duplicate mcpResources URIs. */
|
|
781
809
|
test("cliValidateProgram rejects duplicate mcpResources URIs", () => {
|
|
782
810
|
const root = testProgram({
|
|
783
811
|
key: "app",
|
|
@@ -837,6 +865,7 @@ test("cliValidateProgram rejects resource URI matching default schema URI", () =
|
|
|
837
865
|
expect(() => cliValidateProgram(root)).toThrow(/conflicts with built-in schema resource/);
|
|
838
866
|
});
|
|
839
867
|
|
|
868
|
+
/** CliValidateProgram rejects resource URI matching schemaResourceUri. */
|
|
840
869
|
test("cliValidateProgram rejects resource URI matching schemaResourceUri", () => {
|
|
841
870
|
const root = testProgram({
|
|
842
871
|
key: "app",
|
|
@@ -851,6 +880,7 @@ test("cliValidateProgram rejects resource URI matching schemaResourceUri", () =>
|
|
|
851
880
|
expect(() => cliValidateProgram(root)).toThrow(/conflicts with built-in schema resource/);
|
|
852
881
|
});
|
|
853
882
|
|
|
883
|
+
/** CliValidateProgram rejects resource URI matching auto docs topic. */
|
|
854
884
|
test("cliValidateProgram rejects resource URI matching auto docs topic", () => {
|
|
855
885
|
const root = testProgram({
|
|
856
886
|
key: "app",
|
|
@@ -865,6 +895,7 @@ test("cliValidateProgram rejects resource URI matching auto docs topic", () => {
|
|
|
865
895
|
expect(() => cliValidateProgram(root)).toThrow(/conflicts with auto docs topic resource/);
|
|
866
896
|
});
|
|
867
897
|
|
|
898
|
+
/** AllMcpResources includes custom resources. */
|
|
868
899
|
test("allMcpResources includes custom resources", () => {
|
|
869
900
|
const root = testProgram({
|
|
870
901
|
key: "app",
|
|
@@ -880,6 +911,7 @@ test("allMcpResources includes custom resources", () => {
|
|
|
880
911
|
expect(resources.map((r) => r.uri)).toContain("test://x");
|
|
881
912
|
});
|
|
882
913
|
|
|
914
|
+
/** AllMcpResources includes docs topic resources. */
|
|
883
915
|
test("allMcpResources includes docs topic resources", () => {
|
|
884
916
|
const root = testProgram({
|
|
885
917
|
key: "app",
|
|
@@ -894,6 +926,7 @@ test("allMcpResources includes docs topic resources", () => {
|
|
|
894
926
|
expect(readme?.load()).toBe("# hi\n");
|
|
895
927
|
});
|
|
896
928
|
|
|
929
|
+
/** ApplyShellEnv merges PATH and preserves host vars. */
|
|
897
930
|
test("applyShellEnv merges PATH and preserves host vars", () => {
|
|
898
931
|
const origPath = process.env.PATH ?? "";
|
|
899
932
|
const origHome = process.env.HOME;
|
|
@@ -913,6 +946,7 @@ test("applyShellEnv merges PATH and preserves host vars", () => {
|
|
|
913
946
|
delete process.env.NEWVAR;
|
|
914
947
|
});
|
|
915
948
|
|
|
949
|
+
/** Enum completions list choices in bash script. */
|
|
916
950
|
test("Enum completions list choices in bash script", () => {
|
|
917
951
|
const root = testProgram({
|
|
918
952
|
key: "app",
|
|
@@ -942,6 +976,7 @@ test("nested fallback routes to default when argv exhausted at router", () => {
|
|
|
942
976
|
expect(pr.path).toEqual(["docs", "guide"]);
|
|
943
977
|
});
|
|
944
978
|
|
|
979
|
+
/** Nested fallback MissingOrUnknown routes unknown token to default. */
|
|
945
980
|
test("nested fallback MissingOrUnknown routes unknown token to default", () => {
|
|
946
981
|
const root = testProgram({
|
|
947
982
|
key: "app",
|
|
@@ -991,6 +1026,7 @@ test("nested fallback MissingOnly errors on unknown subcommand", () => {
|
|
|
991
1026
|
expect(pr.errorMsg).toContain("Unknown subcommand");
|
|
992
1027
|
});
|
|
993
1028
|
|
|
1029
|
+
/** CliValidateProgram rejects invalid nested fallbackCommand. */
|
|
994
1030
|
test("cliValidateProgram rejects invalid nested fallbackCommand", () => {
|
|
995
1031
|
const root = testProgram({
|
|
996
1032
|
key: "app",
|
|
@@ -1106,6 +1142,7 @@ test("mcpToolCallToArgv empty array varargs errors when required", () => {
|
|
|
1106
1142
|
|
|
1107
1143
|
// ── Skills ────────────────────────────────────────────────────────────────────
|
|
1108
1144
|
|
|
1145
|
+
/** Configure config on non-root node is rejected. */
|
|
1109
1146
|
test("configure config on non-root node is rejected", () => {
|
|
1110
1147
|
const root = {
|
|
1111
1148
|
key: "app",
|
|
@@ -1134,6 +1171,7 @@ test("configure.prefix is rejected", () => {
|
|
|
1134
1171
|
expect(() => cliValidateProgram(root)).toThrow(/configure\.prefix removed/);
|
|
1135
1172
|
});
|
|
1136
1173
|
|
|
1174
|
+
/** Tests that generateSkillBundle includes frontmatter and compact command index. */
|
|
1137
1175
|
test("generateSkillBundle includes frontmatter and compact command index", () => {
|
|
1138
1176
|
const bundle = generateSkillBundle(nestedMcpFixture, "cursor");
|
|
1139
1177
|
expect(bundle.dirName).toBe("nested_ts");
|
|
@@ -1154,6 +1192,7 @@ test("generateSkillBundle includes frontmatter and compact command index", () =>
|
|
|
1154
1192
|
expect(bundle.referenceMd).not.toContain("```json");
|
|
1155
1193
|
});
|
|
1156
1194
|
|
|
1195
|
+
/** Tests that generatePluginSkillBundle is MCP routing stub without shell catalog. */
|
|
1157
1196
|
test("generatePluginSkillBundle is MCP routing stub without shell catalog", () => {
|
|
1158
1197
|
const bundle = generatePluginSkillBundle(nestedMcpFixture);
|
|
1159
1198
|
expect(bundle.dirName).toBe("nested_ts");
|
|
@@ -1168,6 +1207,7 @@ test("generatePluginSkillBundle is MCP routing stub without shell catalog", () =
|
|
|
1168
1207
|
expect(bundle.skillMd).not.toContain("## Commands");
|
|
1169
1208
|
});
|
|
1170
1209
|
|
|
1210
|
+
/** CliSkillInstall writes project Cursor skill files. */
|
|
1171
1211
|
test("cliSkillInstall writes project Cursor skill files", () => {
|
|
1172
1212
|
const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-"));
|
|
1173
1213
|
const prev = process.cwd();
|
|
@@ -1192,6 +1232,7 @@ test("cliSkillInstall writes project Cursor skill files", () => {
|
|
|
1192
1232
|
}
|
|
1193
1233
|
});
|
|
1194
1234
|
|
|
1235
|
+
/** CliSkillInstall global uses HOME skills directory. */
|
|
1195
1236
|
test("cliSkillInstall global uses HOME skills directory", () => {
|
|
1196
1237
|
const home = mkdtempSync(join(tmpdir(), "argsbarg-home-"));
|
|
1197
1238
|
const prevHome = process.env.HOME;
|
|
@@ -1210,6 +1251,7 @@ test("cliSkillInstall global uses HOME skills directory", () => {
|
|
|
1210
1251
|
}
|
|
1211
1252
|
});
|
|
1212
1253
|
|
|
1254
|
+
/** CliSkillInstall rimraf overwrites existing directory. */
|
|
1213
1255
|
test("cliSkillInstall rimraf overwrites existing directory", () => {
|
|
1214
1256
|
const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-dup-"));
|
|
1215
1257
|
const prev = process.cwd();
|
|
@@ -1228,6 +1270,7 @@ test("cliSkillInstall rimraf overwrites existing directory", () => {
|
|
|
1228
1270
|
}
|
|
1229
1271
|
});
|
|
1230
1272
|
|
|
1273
|
+
/** CliSkillInstall claude target uses .claude/skills. */
|
|
1231
1274
|
test("cliSkillInstall claude target uses .claude/skills", () => {
|
|
1232
1275
|
const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-claude-"));
|
|
1233
1276
|
const prev = process.cwd();
|