argsbarg 7.0.6 → 7.0.7
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 +13 -1
- package/README.md +3 -3
- package/docs/README.md +1 -1
- package/docs/ai-skills.md +14 -62
- package/docs/bundled-docs.md +9 -13
- package/docs/cli-program.md +10 -11
- package/docs/configure.md +9 -11
- package/docs/output-schema.md +0 -1
- package/examples/full-example/AGENTS.md +3 -3
- package/examples/full-example/docs/README.md +1 -1
- package/examples/full-example/justfile +0 -1
- package/examples/full-example/skills/full-example/SKILL.md +0 -2
- package/examples/full-example/src/program.ts +0 -1
- package/examples/full-example-json/AGENTS.md +3 -3
- package/examples/full-example-json/docs/README.md +1 -1
- package/examples/full-example-json/justfile +0 -1
- package/examples/full-example-json/skills/full-example-json/SKILL.md +0 -2
- package/examples/full-example-json/src/program.ts +0 -1
- package/index.d.ts +5 -3
- package/package.json +1 -1
- package/src/builtins/builtins.test.ts +1 -22
- package/src/builtins/configure-copy.ts +4 -11
- package/src/builtins/presentation.ts +2 -5
- package/src/configure/artifacts/status.test.ts +5 -5
- package/src/configure/artifacts/target-effective.ts +1 -2
- package/src/configure/artifacts/target-skill.ts +9 -15
- package/src/configure/artifacts/targets/skill.ts +8 -1
- package/src/configure/artifacts/targets.test.ts +5 -5
- package/src/configure/configure.test.ts +4 -4
- package/src/core/parse.test.ts +1 -112
- package/src/core/types.ts +5 -3
- package/src/core/validate.ts +4 -2
- package/src/docs/builtin.ts +5 -3
- package/src/docs/cli-guide.ts +3 -3
- package/src/docs/docs.test.ts +3 -47
- package/src/docs/resolve.ts +5 -5
- package/src/docs/save.ts +9 -20
- package/src/help.test.ts +6 -7
- package/src/skill/generate.ts +30 -156
- package/src/skill/hint.ts +2 -15
- package/src/skill/install.ts +3 -35
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
This module provides capability-aware labels for the configure built-in and docs copy.
|
|
3
|
+
*/
|
|
2
4
|
|
|
3
5
|
import type { CliProgram } from "../core/types.ts";
|
|
4
6
|
import type { CliCapabilities } from "../runtime/capabilities.ts";
|
|
5
7
|
|
|
6
|
-
type Kind = "
|
|
8
|
+
type Kind = "mcp" | "config";
|
|
7
9
|
|
|
8
10
|
const LABEL: Record<Kind, { prose: string; short: string }> = {
|
|
9
|
-
skills: { prose: "agent skills", short: "skills" },
|
|
10
11
|
mcp: { prose: "MCP config", short: "MCP" },
|
|
11
12
|
config: { prose: "app config", short: "config" },
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
function enabledKinds(program: CliProgram, caps: CliCapabilities): Kind[] {
|
|
15
16
|
const kinds: Kind[] = [];
|
|
16
|
-
if (program.skill?.enabled) kinds.push("skills");
|
|
17
17
|
if (caps.mcp && program.mcpServer?.enabled) kinds.push("mcp");
|
|
18
18
|
if (program.appConfig && Object.keys(program.appConfig.entries).length > 0) kinds.push("config");
|
|
19
19
|
return kinds;
|
|
@@ -39,13 +39,6 @@ export function configureCommandDescription(program: CliProgram, caps: CliCapabi
|
|
|
39
39
|
return `Set up ${prose(program, caps)} for this app (binary via Homebrew).`;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export function docsSkillTopicDescription(_program: CliProgram, caps: CliCapabilities): string {
|
|
43
|
-
if (caps.configure) {
|
|
44
|
-
return "Print a reference agent SKILL; run `configure install` to install an optimized copy.";
|
|
45
|
-
}
|
|
46
|
-
return "Print a reference agent SKILL for AI agents.";
|
|
47
|
-
}
|
|
48
|
-
|
|
49
42
|
export function configureCommandNotes(program: CliProgram, _caps: CliCapabilities): string {
|
|
50
43
|
const app = program.key;
|
|
51
44
|
const lines = [
|
|
@@ -77,15 +77,12 @@ export function cliPresentationRoot(program: CliProgram): CliRouter {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
/** Root help notes
|
|
81
|
-
export function presentationRootNotes(program: CliProgram,
|
|
80
|
+
/** Root help notes from consumer `program.notes`. */
|
|
81
|
+
export function presentationRootNotes(program: CliProgram, _caps: CliCapabilities): string | undefined {
|
|
82
82
|
const parts: string[] = [];
|
|
83
83
|
if ((program.notes ?? "").trim().length > 0) {
|
|
84
84
|
parts.push((program.notes ?? "").trim());
|
|
85
85
|
}
|
|
86
|
-
if (caps.docs) {
|
|
87
|
-
parts.push(`For AI agents: \`${program.key} docs skill\`.`);
|
|
88
|
-
}
|
|
89
86
|
if (parts.length === 0) {
|
|
90
87
|
return undefined;
|
|
91
88
|
}
|
|
@@ -43,7 +43,7 @@ describe("resolveInstallTargetPreview", () => {
|
|
|
43
43
|
expect(preview.skill).toEqual([]);
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
test("skill app
|
|
46
|
+
test("skill app does not include skill in all scope (skill gen removed)", () => {
|
|
47
47
|
const program: CliProgram = {
|
|
48
48
|
key: "cliapp",
|
|
49
49
|
version: "1",
|
|
@@ -53,8 +53,8 @@ describe("resolveInstallTargetPreview", () => {
|
|
|
53
53
|
};
|
|
54
54
|
const paths = resolveInstallPaths(program);
|
|
55
55
|
const preview = resolveInstallTargetPreview(program, paths);
|
|
56
|
-
expect(preview.all).toEqual([
|
|
57
|
-
expect(preview.skill).toEqual([
|
|
56
|
+
expect(preview.all).toEqual([]);
|
|
57
|
+
expect(preview.skill).toEqual([]);
|
|
58
58
|
expect(preview.mcp).toEqual([]);
|
|
59
59
|
});
|
|
60
60
|
});
|
|
@@ -81,8 +81,8 @@ describe("printInstallStatus json", () => {
|
|
|
81
81
|
const parsed = JSON.parse(chunks.join("")) as {
|
|
82
82
|
effective: { all: string[]; mcp: string[]; skill: string[] };
|
|
83
83
|
};
|
|
84
|
-
expect(parsed.effective.all).toEqual(["
|
|
85
|
-
expect(parsed.effective.skill).toEqual([
|
|
84
|
+
expect(parsed.effective.all).toEqual(["agentsMcp"]);
|
|
85
|
+
expect(parsed.effective.skill).toEqual([]);
|
|
86
86
|
expect(parsed.effective.mcp).toEqual(["agentsMcp"]);
|
|
87
87
|
} finally {
|
|
88
88
|
process.stdout.write = orig;
|
|
@@ -32,8 +32,7 @@ function artifactDefaults(
|
|
|
32
32
|
program?: Pick<CliProgram, "mcpServer" | "skill">,
|
|
33
33
|
): { enabled: boolean; includedInAll: boolean } {
|
|
34
34
|
if (key === "skill") {
|
|
35
|
-
|
|
36
|
-
return { enabled: on, includedInAll: on };
|
|
35
|
+
return { enabled: false, includedInAll: false };
|
|
37
36
|
}
|
|
38
37
|
if (key === "agentsMcp") {
|
|
39
38
|
const on = program?.mcpServer?.enabled === true;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Agent shell skill directory install (~/.agents/skills/<key>/).
|
|
3
|
+
Skill generation is removed; skills are authored directly in repositories under skills/<app>/SKILL.md.
|
|
4
|
+
Uninstall cleans up legacy/stale skill directories if present.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import { existsSync } from "node:fs";
|
|
2
8
|
import type { CliProgram } from "../../core/types.ts";
|
|
3
|
-
import { cliSkillInstall } from "../../skill/install.ts";
|
|
4
9
|
import { displayInstallPath, type InstallPaths } from "./paths.ts";
|
|
5
10
|
import { InstallTarget } from "./target-base.ts";
|
|
6
11
|
import type {
|
|
@@ -15,6 +20,7 @@ import type {
|
|
|
15
20
|
} from "./target-types.ts";
|
|
16
21
|
import { uninstallSkillDir } from "./uninstall.ts";
|
|
17
22
|
|
|
23
|
+
/** Specification for an agent skill install target. */
|
|
18
24
|
export interface SkillHostSpec {
|
|
19
25
|
key: CliInstallArtifactKey;
|
|
20
26
|
actionKind: InstallActionKind;
|
|
@@ -71,20 +77,8 @@ export class SkillInstallTarget extends InstallTarget {
|
|
|
71
77
|
return this.spec.skillDir(paths);
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
protected buildInstallActions(
|
|
75
|
-
|
|
76
|
-
const displayDir = `${displayInstallPath(dir)}/`;
|
|
77
|
-
return [
|
|
78
|
-
{
|
|
79
|
-
kind: this.actionKind,
|
|
80
|
-
summary: `${this.spec.label.toLowerCase()}: ${displayDir}`,
|
|
81
|
-
message: `Installing ${this.spec.label.toLowerCase()} to ${displayDir}`,
|
|
82
|
-
run: () => {
|
|
83
|
-
cliSkillInstall(ctx.root, { global: true, rimraf: true, dry: ctx.dry });
|
|
84
|
-
return [];
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
];
|
|
80
|
+
protected buildInstallActions(_ctx: TargetPlanContext): InstallAction[] {
|
|
81
|
+
return [];
|
|
88
82
|
}
|
|
89
83
|
|
|
90
84
|
protected buildUninstallActions(ctx: TargetPlanContext): UninstallAction[] {
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Install target definition for agent skill cleanup and status.
|
|
3
|
+
Skill generation is removed; skills are authored directly in repositories under skills/<app>/SKILL.md.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
1
7
|
import { SkillInstallTarget } from "../target-skill.ts";
|
|
2
8
|
|
|
9
|
+
/** Registered install target for agent skill directory cleanup and detection. */
|
|
3
10
|
export const skillTarget = new SkillInstallTarget({
|
|
4
11
|
key: "skill",
|
|
5
12
|
actionKind: "agent-skill",
|
|
@@ -8,5 +15,5 @@ export const skillTarget = new SkillInstallTarget({
|
|
|
8
15
|
skillDir: (p) => p.agentsSkillDir,
|
|
9
16
|
detectedKey: "skill",
|
|
10
17
|
statusField: "skill",
|
|
11
|
-
isAvailable: (
|
|
18
|
+
isAvailable: (_root, p) => existsSync(p.agentsSkillDir),
|
|
12
19
|
});
|
|
@@ -42,10 +42,10 @@ describe("resolveEffectiveInstallTargets", () => {
|
|
|
42
42
|
expect(t.agentsMcp.includedInAll).toBe(false);
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
test("skill
|
|
45
|
+
test("skill disabled even when program.skill is set (skill gen removed)", () => {
|
|
46
46
|
const t = resolveEffectiveInstallTargets(undefined, { skill: { enabled: true } });
|
|
47
|
-
expect(t.skill.enabled).toBe(
|
|
48
|
-
expect(t.skill.includedInAll).toBe(
|
|
47
|
+
expect(t.skill.enabled).toBe(false);
|
|
48
|
+
expect(t.skill.includedInAll).toBe(false);
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
test("agentsMcp in --all when mcpServer enabled", () => {
|
|
@@ -69,7 +69,7 @@ describe("resolveEffectiveInstallTargets", () => {
|
|
|
69
69
|
expect(isArtifactInScope("agentsMcp", scope, effective, "install-scoped", program)).toBe(true);
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
-
test("scoped --skill
|
|
72
|
+
test("scoped --skill omits skill because skill generation is removed", () => {
|
|
73
73
|
const program: CliProgram = {
|
|
74
74
|
key: "app",
|
|
75
75
|
version: "1",
|
|
@@ -79,6 +79,6 @@ describe("resolveEffectiveInstallTargets", () => {
|
|
|
79
79
|
};
|
|
80
80
|
const effective = resolveEffectiveInstallTargets(program.configure, program);
|
|
81
81
|
const scope = { skill: true };
|
|
82
|
-
expect(isArtifactInScope("skill", scope, effective, "install-scoped", program)).toBe(
|
|
82
|
+
expect(isArtifactInScope("skill", scope, effective, "install-scoped", program)).toBe(false);
|
|
83
83
|
});
|
|
84
84
|
});
|
|
@@ -88,19 +88,19 @@ describe("detect installed", () => {
|
|
|
88
88
|
|
|
89
89
|
/** Tests for install plan. */
|
|
90
90
|
describe("install plan", () => {
|
|
91
|
-
test("buildUpdatePlan greenfield
|
|
91
|
+
test("buildUpdatePlan greenfield omits skill because skill generation is removed", () => {
|
|
92
92
|
const paths = resolveInstallPaths(fixture);
|
|
93
93
|
const plan = buildUpdatePlan(fixture, paths, parseInstallOpts({ reinstall: "1", yes: "1" }));
|
|
94
94
|
expect(plan.length).toBeGreaterThan(0);
|
|
95
|
-
expect(plan.some((a) => a.kind === "agent-skill")).toBe(
|
|
95
|
+
expect(plan.some((a) => a.kind === "agent-skill")).toBe(false);
|
|
96
96
|
expect(plan.some((a) => a.kind === "app")).toBe(false);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
test("buildInstallPlan --all omits app self-install", () => {
|
|
99
|
+
test("buildInstallPlan --all omits app self-install and skill", () => {
|
|
100
100
|
const paths = resolveInstallPaths(fixture);
|
|
101
101
|
const plan = buildInstallPlan(fixture, paths, parseInstallOpts({ all: "1" }));
|
|
102
102
|
expect(plan.some((a) => a.kind === "app")).toBe(false);
|
|
103
|
-
expect(plan.some((a) => a.kind === "agent-skill")).toBe(
|
|
103
|
+
expect(plan.some((a) => a.kind === "agent-skill")).toBe(false);
|
|
104
104
|
expect(plan.some((a) => a.kind === "agents-mcp")).toBe(true);
|
|
105
105
|
});
|
|
106
106
|
|
package/src/core/parse.test.ts
CHANGED
|
@@ -3,9 +3,6 @@ Domain-specific regression tests (split from index.test.ts).
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { expect, test } from "bun:test";
|
|
6
|
-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { tmpdir } from "node:os";
|
|
8
|
-
import { join } from "node:path";
|
|
9
6
|
import { $ } from "bun";
|
|
10
7
|
import { completionBashScript, completionZshScript } from "../builtins/index.ts";
|
|
11
8
|
import { cliPresentationRoot } from "../builtins/presentation.ts";
|
|
@@ -13,8 +10,7 @@ import { cliHelpRender } from "../help.ts";
|
|
|
13
10
|
import { Cli, CliFallbackMode, CliOptionKind, type CliProgram } from "../index.ts";
|
|
14
11
|
import { applyShellEnv } from "../mcp/env.ts";
|
|
15
12
|
import { allMcpResources, collectMcpTools, mcpToolCallToArgv, resolveMcpSchemaUri } from "../mcp/tools.ts";
|
|
16
|
-
import { generatePluginSkillBundle
|
|
17
|
-
import { cliSkillInstall } from "../skill/install.ts";
|
|
13
|
+
import { generatePluginSkillBundle } from "../skill/generate.ts";
|
|
18
14
|
import {
|
|
19
15
|
enumMcpFixture,
|
|
20
16
|
nestedDocsFallbackFixture,
|
|
@@ -1352,31 +1348,6 @@ test("configure.prefix is rejected", () => {
|
|
|
1352
1348
|
expect(() => cliValidateProgram(root)).toThrow(/configure\.prefix removed/);
|
|
1353
1349
|
});
|
|
1354
1350
|
|
|
1355
|
-
/** Tests that generateSkillBundle includes frontmatter and intent-based router. */
|
|
1356
|
-
test("generateSkillBundle includes frontmatter and intent-based router", () => {
|
|
1357
|
-
const bundle = generateSkillBundle(nestedMcpFixture);
|
|
1358
|
-
expect(bundle.dirName).toBe("nested.ts");
|
|
1359
|
-
expect(bundle.skillMd).toMatch(/^---\nid: nested\.ts\nname: nested\.ts\n/);
|
|
1360
|
-
expect(bundle.skillMd).toContain("enabled: true");
|
|
1361
|
-
expect(bundle.skillMd).toContain("dotagentsprotocol.com");
|
|
1362
|
-
expect(bundle.skillMd).toContain("~/.claude/skills/nested.ts");
|
|
1363
|
-
expect(bundle.skillMd).toContain("Options & Help Discovery");
|
|
1364
|
-
expect(bundle.skillMd).toContain("Run `nested.ts <subcommand> --help`");
|
|
1365
|
-
expect(bundle.skillMd).toContain("## Commands");
|
|
1366
|
-
expect(bundle.skillMd).toContain("`nested.ts stat owner lookup <path>`");
|
|
1367
|
-
expect(bundle.skillMd).toContain("Invoke via shell:");
|
|
1368
|
-
expect(bundle.skillMd).toContain("Workflow & Pitfalls");
|
|
1369
|
-
expect(bundle.skillMd).toContain("~/.agents/skills/nested.ts/");
|
|
1370
|
-
expect(bundle.skillMd).not.toContain("reference.md");
|
|
1371
|
-
expect(bundle.skillMd).not.toContain("#### Options");
|
|
1372
|
-
expect(bundle.skillMd).not.toContain("CLI API reference");
|
|
1373
|
-
expect(bundle.skillMd).not.toContain("mcp.json");
|
|
1374
|
-
expect(bundle.skillMd).not.toContain("Prefer MCP");
|
|
1375
|
-
expect(bundle.skillMd).not.toContain("tools/call");
|
|
1376
|
-
expect(bundle.skillMd).not.toContain("Generated by");
|
|
1377
|
-
expect((bundle as unknown as Record<string, unknown>).referenceMd).toBeUndefined();
|
|
1378
|
-
});
|
|
1379
|
-
|
|
1380
1351
|
/** Tests that generatePluginSkillBundle is MCP routing stub without shell catalog. */
|
|
1381
1352
|
test("generatePluginSkillBundle is MCP routing stub without shell catalog", () => {
|
|
1382
1353
|
const bundle = generatePluginSkillBundle(nestedMcpFixture);
|
|
@@ -1391,85 +1362,3 @@ test("generatePluginSkillBundle is MCP routing stub without shell catalog", () =
|
|
|
1391
1362
|
expect(bundle.skillMd).not.toContain("`nested.ts stat owner lookup <path>`");
|
|
1392
1363
|
expect(bundle.skillMd).not.toContain("## Commands");
|
|
1393
1364
|
});
|
|
1394
|
-
|
|
1395
|
-
/** CliSkillInstall writes project agent skill files. */
|
|
1396
|
-
test("cliSkillInstall writes project agent skill files", () => {
|
|
1397
|
-
const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-"));
|
|
1398
|
-
const prev = process.cwd();
|
|
1399
|
-
process.chdir(cwd);
|
|
1400
|
-
try {
|
|
1401
|
-
const files = cliSkillInstall(nestedMcpFixture, { global: false, rimraf: true });
|
|
1402
|
-
expect(files.some((f) => f.includes(".agents/skills/nested.ts/"))).toBe(true);
|
|
1403
|
-
const skillDir = join(cwd, ".agents", "skills", "nested.ts");
|
|
1404
|
-
expect(existsSync(join(skillDir, "SKILL.md"))).toBe(true);
|
|
1405
|
-
expect(existsSync(join(skillDir, "skill.md"))).toBe(true);
|
|
1406
|
-
expect(existsSync(join(skillDir, "reference.md"))).toBe(false);
|
|
1407
|
-
expect(readFileSync(join(skillDir, "SKILL.md"), "utf8")).toContain("## Commands");
|
|
1408
|
-
expect(readFileSync(join(skillDir, "SKILL.md"), "utf8")).toContain("Options & Help Discovery");
|
|
1409
|
-
const skillText = readFileSync(join(skillDir, "SKILL.md"), "utf8");
|
|
1410
|
-
expect(skillText.startsWith("---\n")).toBe(true);
|
|
1411
|
-
const hint = "<!-- Generated by nested.ts configure; do not edit. -->";
|
|
1412
|
-
expect(skillText.indexOf(hint)).toBeGreaterThan(skillText.indexOf("---\n", 4));
|
|
1413
|
-
} finally {
|
|
1414
|
-
process.chdir(prev);
|
|
1415
|
-
rmSync(cwd, { recursive: true, force: true });
|
|
1416
|
-
}
|
|
1417
|
-
});
|
|
1418
|
-
|
|
1419
|
-
/** CliSkillInstall removes legacy reference.md if present. */
|
|
1420
|
-
test("cliSkillInstall removes legacy reference.md if present", () => {
|
|
1421
|
-
const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-legacy-"));
|
|
1422
|
-
const prev = process.cwd();
|
|
1423
|
-
process.chdir(cwd);
|
|
1424
|
-
try {
|
|
1425
|
-
const skillDir = join(cwd, ".agents", "skills", "nested.ts");
|
|
1426
|
-
mkdirSync(skillDir, { recursive: true });
|
|
1427
|
-
writeFileSync(join(skillDir, "reference.md"), "legacy reference content", "utf8");
|
|
1428
|
-
expect(existsSync(join(skillDir, "reference.md"))).toBe(true);
|
|
1429
|
-
|
|
1430
|
-
cliSkillInstall(nestedMcpFixture, { global: false, rimraf: false });
|
|
1431
|
-
expect(existsSync(join(skillDir, "SKILL.md"))).toBe(true);
|
|
1432
|
-
expect(existsSync(join(skillDir, "reference.md"))).toBe(false);
|
|
1433
|
-
} finally {
|
|
1434
|
-
process.chdir(prev);
|
|
1435
|
-
rmSync(cwd, { recursive: true, force: true });
|
|
1436
|
-
}
|
|
1437
|
-
});
|
|
1438
|
-
|
|
1439
|
-
/** CliSkillInstall global uses TEST_USER_HOME agents skills directory. */
|
|
1440
|
-
test("cliSkillInstall global uses TEST_USER_HOME agents skills directory", () => {
|
|
1441
|
-
const home = mkdtempSync(join(tmpdir(), "argsbarg-home-"));
|
|
1442
|
-
const prevTestHome = process.env.TEST_USER_HOME;
|
|
1443
|
-
process.env.TEST_USER_HOME = home;
|
|
1444
|
-
try {
|
|
1445
|
-
const files = cliSkillInstall(nestedMcpFixture, { global: true, rimraf: true });
|
|
1446
|
-
expect(files.some((f) => f.includes(join(home, ".agents", "skills", "nested.ts")))).toBe(true);
|
|
1447
|
-
expect(existsSync(join(home, ".agents", "skills", "nested.ts", "SKILL.md"))).toBe(true);
|
|
1448
|
-
} finally {
|
|
1449
|
-
if (prevTestHome === undefined) {
|
|
1450
|
-
delete process.env.TEST_USER_HOME;
|
|
1451
|
-
} else {
|
|
1452
|
-
process.env.TEST_USER_HOME = prevTestHome;
|
|
1453
|
-
}
|
|
1454
|
-
rmSync(home, { recursive: true, force: true });
|
|
1455
|
-
}
|
|
1456
|
-
});
|
|
1457
|
-
|
|
1458
|
-
/** CliSkillInstall rimraf overwrites existing directory. */
|
|
1459
|
-
test("cliSkillInstall rimraf overwrites existing directory", () => {
|
|
1460
|
-
const cwd = mkdtempSync(join(tmpdir(), "argsbarg-skill-dup-"));
|
|
1461
|
-
const prev = process.cwd();
|
|
1462
|
-
process.chdir(cwd);
|
|
1463
|
-
try {
|
|
1464
|
-
cliSkillInstall(nestedMcpFixture, { global: false, rimraf: true });
|
|
1465
|
-
writeFileSync(join(cwd, ".agents", "skills", "nested.ts", "SKILL.md"), "stale", "utf8");
|
|
1466
|
-
const files = cliSkillInstall(nestedMcpFixture, { global: false, rimraf: true });
|
|
1467
|
-
expect(files.length).toBeGreaterThan(0);
|
|
1468
|
-
expect(readFileSync(join(cwd, ".agents", "skills", "nested.ts", "SKILL.md"), "utf8")).toContain(
|
|
1469
|
-
"stat owner lookup",
|
|
1470
|
-
);
|
|
1471
|
-
} finally {
|
|
1472
|
-
process.chdir(prev);
|
|
1473
|
-
rmSync(cwd, { recursive: true, force: true });
|
|
1474
|
-
}
|
|
1475
|
-
});
|
package/src/core/types.ts
CHANGED
|
@@ -404,9 +404,11 @@ export interface CliCompletionConfig {
|
|
|
404
404
|
enabled?: boolean;
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
-
/**
|
|
407
|
+
/**
|
|
408
|
+
* @deprecated Skill generation was removed; skills are authored directly in repositories under `skills/<app>/SKILL.md`.
|
|
409
|
+
*/
|
|
408
410
|
export interface CliSkillConfig {
|
|
409
|
-
/**
|
|
411
|
+
/** @deprecated Skill generation was removed; this property has no effect. */
|
|
410
412
|
enabled?: boolean;
|
|
411
413
|
}
|
|
412
414
|
|
|
@@ -678,7 +680,7 @@ export type CliProgram = CliNode & {
|
|
|
678
680
|
mcpServer?: CliMcpServerConfig;
|
|
679
681
|
/** Optional readiness probe for HTTP/MCP `GET /health/readiness` only. */
|
|
680
682
|
readiness?: (ctx: ReadinessContext) => boolean | Promise<boolean>;
|
|
681
|
-
/**
|
|
683
|
+
/** @deprecated Skill generation was removed; skills are authored directly in repositories under `skills/<app>/SKILL.md`. */
|
|
682
684
|
skill?: CliSkillConfig;
|
|
683
685
|
/** Program version (printed by the `version` built-in and MCP serverInfo). */
|
|
684
686
|
version: string;
|
package/src/core/validate.ts
CHANGED
|
@@ -105,7 +105,9 @@ function validateConfigureConfig(program: CliProgram): void {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
if ("agentIntegration" in configure) {
|
|
108
|
-
throw new CliSchemaValidationError(
|
|
108
|
+
throw new CliSchemaValidationError(
|
|
109
|
+
"configure.agentIntegration removed; skills are authored under skills/<app>/SKILL.md",
|
|
110
|
+
);
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
if (!configure.targets) return;
|
|
@@ -119,7 +121,7 @@ function validateConfigureConfig(program: CliProgram): void {
|
|
|
119
121
|
for (const key of legacySkillKeys) {
|
|
120
122
|
if (key in targets) {
|
|
121
123
|
throw new CliSchemaValidationError(
|
|
122
|
-
`configure.targets.${key} removed;
|
|
124
|
+
`configure.targets.${key} removed; skills are authored under skills/<app>/SKILL.md`,
|
|
123
125
|
);
|
|
124
126
|
}
|
|
125
127
|
}
|
package/src/docs/builtin.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
This module builds the built-in `docs` command group router.
|
|
3
|
+
It registers bundled documentation topics (CLI guide, schema, MCP, HTTP) as subcommands.
|
|
4
|
+
*/
|
|
5
|
+
|
|
2
6
|
import { type CliLeaf, type CliOption, CliOptionKind, type CliProgram, type CliRouter } from "../core/types.ts";
|
|
3
|
-
import { resolveCapabilities } from "../runtime/capabilities.ts";
|
|
4
7
|
import {
|
|
5
8
|
DOCS_ROUTER_DESCRIPTION,
|
|
6
9
|
docsEnabled,
|
|
@@ -74,7 +77,6 @@ export function cliBuiltinDocsGroup(program: CliProgram): CliRouter {
|
|
|
74
77
|
leaves.push(
|
|
75
78
|
docsLeaf(program, "cli-schema", "Print the full CLI command tree as JSON."),
|
|
76
79
|
docsLeaf(program, "cli", "Print the full command reference as markdown."),
|
|
77
|
-
docsLeaf(program, "skill", docsSkillTopicDescription(program, resolveCapabilities(program))),
|
|
78
80
|
);
|
|
79
81
|
|
|
80
82
|
return {
|
package/src/docs/cli-guide.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { cliPositionalLabel, cliResolveNotes } from "../help.ts";
|
|
|
6
6
|
|
|
7
7
|
/** Options for {@link generateCliGuideBody} and {@link generateCliGuide}. */
|
|
8
8
|
export interface CliGuideBodyOptions {
|
|
9
|
-
/** Omit embedded outputSchema JSON; point to `docs cli-schema` instead
|
|
9
|
+
/** Omit embedded outputSchema JSON; point to `docs cli-schema` instead. */
|
|
10
10
|
compact?: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -72,7 +72,7 @@ function formatNotesBlockquote(notes: string, appKey: string): string {
|
|
|
72
72
|
.join("\n");
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
/** Markdown section for leaf outputSchema (docs cli
|
|
75
|
+
/** Markdown section for leaf outputSchema (docs cli). */
|
|
76
76
|
function formatOutputSchemaSection(schema: Record<string, unknown>): string[] {
|
|
77
77
|
return [
|
|
78
78
|
"#### Output",
|
|
@@ -173,7 +173,7 @@ function renderCommandNode(
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
/** Command-tree markdown
|
|
176
|
+
/** Command-tree markdown for `docs cli` (no API doc header). */
|
|
177
177
|
export function generateCliGuideBody(program: CliProgram, opts: CliGuideBodyOptions = {}): string {
|
|
178
178
|
const schema = cliSchemaExport(program);
|
|
179
179
|
const lines: string[] = [];
|
package/src/docs/docs.test.ts
CHANGED
|
@@ -76,9 +76,6 @@ test("docs rejects reserved topic keys", () => {
|
|
|
76
76
|
docs.topics["cli-schema"] = { text: "nope" };
|
|
77
77
|
expect(() => cliValidateProgram(root)).toThrow(/reserved/);
|
|
78
78
|
delete docs.topics["cli-schema"];
|
|
79
|
-
docs.topics.skill = { text: "nope" };
|
|
80
|
-
expect(() => cliValidateProgram(root)).toThrow(/reserved/);
|
|
81
|
-
delete docs.topics.skill;
|
|
82
79
|
docs.topics.cli = { text: "nope" };
|
|
83
80
|
expect(() => cliValidateProgram(root)).toThrow(/reserved/);
|
|
84
81
|
delete docs.topics.cli;
|
|
@@ -128,9 +125,6 @@ test("built-in docs work without topics", async () => {
|
|
|
128
125
|
const cliRef = await new Cli(root).invoke(["docs", "cli"]);
|
|
129
126
|
expect(cliRef.exitCode).toBe(0);
|
|
130
127
|
expect(cliRef.stdout).toContain("CLI API reference");
|
|
131
|
-
const skill = await new Cli(root).invoke(["docs", "skill"]);
|
|
132
|
-
expect(skill.exitCode).toBe(0);
|
|
133
|
-
expect(skill.stdout).toContain("name: myapp");
|
|
134
128
|
});
|
|
135
129
|
|
|
136
130
|
test("bare docs shows router help", () => {
|
|
@@ -253,41 +247,14 @@ test("skipsRequiredAppConfigExit includes docs and config builtins", () => {
|
|
|
253
247
|
expect(skipsRequiredAppConfigExit(["run"], caps)).toBe(false);
|
|
254
248
|
});
|
|
255
249
|
|
|
256
|
-
test("docs
|
|
257
|
-
const result = await new Cli(docsFixture()).invoke(["docs", "skill"]);
|
|
258
|
-
expect(result.exitCode).toBe(0);
|
|
259
|
-
expect(result.stdout).toContain("---");
|
|
260
|
-
expect(result.stdout).toContain("name: myapp");
|
|
261
|
-
expect(result.stdout).toContain("## Commands");
|
|
262
|
-
expect(result.stdout).toContain("--help");
|
|
263
|
-
expect(result.stdout).not.toContain("reference.md");
|
|
264
|
-
expect(result.stdout).not.toContain("#### Options");
|
|
265
|
-
expect(result.stdout).not.toContain("mcp.json");
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
/** Docs skill help recommends configure. */
|
|
269
|
-
test("docs skill help recommends configure", async () => {
|
|
270
|
-
const presentation = cliPresentationRoot(docsFixture());
|
|
271
|
-
const docsNode = presentation.commands.find((c) => c.key === "docs");
|
|
272
|
-
expect(docsNode && "commands" in docsNode).toBe(true);
|
|
273
|
-
if (docsNode && "commands" in docsNode) {
|
|
274
|
-
const skill = docsNode.commands.find((c) => c.key === "skill");
|
|
275
|
-
expect(skill?.description).toContain("reference agent SKILL");
|
|
276
|
-
expect(skill?.description).toContain("configure");
|
|
277
|
-
expect(skill?.notes).toBeUndefined();
|
|
278
|
-
expect(docsNode.notes).toContain("--save");
|
|
279
|
-
expect(docsNode.notes).not.toContain("install --skill");
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
test("presentation includes docs cli-schema and skill", () => {
|
|
250
|
+
test("presentation includes docs cli-schema and cli without skill", () => {
|
|
284
251
|
const presentation = cliPresentationRoot(docsFixture());
|
|
285
252
|
const docsNode = presentation.commands.find((c) => c.key === "docs");
|
|
286
253
|
expect(docsNode && "commands" in docsNode).toBe(true);
|
|
287
254
|
if (docsNode && "commands" in docsNode) {
|
|
288
255
|
expect(docsNode.commands.some((c) => c.key === "cli-schema")).toBe(true);
|
|
289
256
|
expect(docsNode.commands.some((c) => c.key === "cli")).toBe(true);
|
|
290
|
-
expect(docsNode.commands.some((c) => c.key === "skill")).toBe(
|
|
257
|
+
expect(docsNode.commands.some((c) => c.key === "skill")).toBe(false);
|
|
291
258
|
}
|
|
292
259
|
});
|
|
293
260
|
|
|
@@ -297,7 +264,7 @@ test("completions offer docs subcommands", () => {
|
|
|
297
264
|
expect(bash).toContain("readme) echo");
|
|
298
265
|
expect(bash).toContain("cli-schema) echo");
|
|
299
266
|
expect(bash).toContain("cli) echo");
|
|
300
|
-
expect(bash).toContain("skill) echo");
|
|
267
|
+
expect(bash).not.toContain("skill) echo");
|
|
301
268
|
});
|
|
302
269
|
|
|
303
270
|
test("generateMcpGuide includes schema URI and .agents install", () => {
|
|
@@ -330,17 +297,6 @@ test("docs cli --save prepends generated hint", async () => {
|
|
|
330
297
|
expect(text).toContain("CLI API reference");
|
|
331
298
|
});
|
|
332
299
|
|
|
333
|
-
test("docs skill --save writes skills/<app>/SKILL.md and keeps frontmatter first", async () => {
|
|
334
|
-
const result = await new Cli(docsFixture()).invoke(["docs", "skill", "--save"]);
|
|
335
|
-
expect(result.exitCode).toBe(0);
|
|
336
|
-
expect(result.stdout.trim()).toBe("skills/myapp/SKILL.md");
|
|
337
|
-
const text = readFileSync(join(workDir, "skills/myapp/SKILL.md"), "utf8");
|
|
338
|
-
expect(text.startsWith("---\n")).toBe(true);
|
|
339
|
-
expect(text).toContain("name: myapp");
|
|
340
|
-
const hint = "<!-- Generated by myapp docs skill --save; do not edit. -->";
|
|
341
|
-
expect(text.indexOf(hint)).toBeGreaterThan(text.indexOf("---\n", 4));
|
|
342
|
-
});
|
|
343
|
-
|
|
344
300
|
test("docs cli-schema --save writes JSON file", async () => {
|
|
345
301
|
const result = await new Cli(docsFixture()).invoke(["docs", "cli-schema", "--save"]);
|
|
346
302
|
expect(result.exitCode).toBe(0);
|
package/src/docs/resolve.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This module resolves and prints bundled documentation topics for the `docs` built-in.
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
import { cliSchemaJson } from "../core/schema.ts";
|
|
2
6
|
import type { CliDocsConfig, CliProgram } from "../core/types.ts";
|
|
3
7
|
import { openApiJson } from "../http/openapi.ts";
|
|
4
|
-
import { generateSkillBundle } from "../skill/generate.ts";
|
|
5
8
|
import { generateCliGuide } from "./cli-guide.ts";
|
|
6
9
|
import { generateHttpGuide } from "./http-guide.ts";
|
|
7
10
|
import { generateMcpGuide } from "./mcp-guide.ts";
|
|
8
11
|
|
|
9
12
|
/** Built-in docs subcommand keys not allowed in `docs.topics`. */
|
|
10
|
-
export const DOCS_BUILTIN_TOPIC_KEYS = ["http", "mcp", "all", "cli-schema", "cli", "
|
|
13
|
+
export const DOCS_BUILTIN_TOPIC_KEYS = ["http", "mcp", "all", "cli-schema", "cli", "openapi"] as const;
|
|
11
14
|
|
|
12
15
|
export type DocsBuiltinTopicKey = (typeof DOCS_BUILTIN_TOPIC_KEYS)[number];
|
|
13
16
|
|
|
@@ -98,9 +101,6 @@ export function docsTopicContent(program: CliProgram, topic: string): string {
|
|
|
98
101
|
if (topic === "cli") {
|
|
99
102
|
return generateCliGuide(program);
|
|
100
103
|
}
|
|
101
|
-
if (topic === "skill") {
|
|
102
|
-
return `${generateSkillBundle(program).skillMd}\n`;
|
|
103
|
-
}
|
|
104
104
|
const text = docsTopicText(program, topic);
|
|
105
105
|
return text.endsWith("\n") ? text : `${text}\n`;
|
|
106
106
|
}
|
package/src/docs/save.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
/*
|
|
2
2
|
This module persists bundled documentation topics to disk when `--save` is passed.
|
|
3
|
-
It writes documentation under `./docs
|
|
3
|
+
It writes documentation under `./docs/`.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { dirname, join } from "node:path";
|
|
8
8
|
import type { CliProgram } from "../core/types.ts";
|
|
9
9
|
import { generatedFileHtmlComment, insertGeneratedHint } from "../skill/hint.ts";
|
|
10
|
-
import { skillDirName } from "../skill/naming.ts";
|
|
11
10
|
import { docsTopicContent } from "./resolve.ts";
|
|
12
11
|
|
|
13
12
|
/** Relative output directory for `docs --save`. */
|
|
14
13
|
export const DOCS_SAVE_DIR = "docs";
|
|
15
14
|
|
|
16
15
|
/** Builtin docs topics generated by argsbarg (not consumer `docs.topics`). */
|
|
17
|
-
export const DOCS_GENERATED_SAVE_TOPICS = ["mcp", "cli", "
|
|
16
|
+
export const DOCS_GENERATED_SAVE_TOPICS = ["mcp", "cli", "http"] as const;
|
|
18
17
|
|
|
19
18
|
/** Whether `--save` should prepend a generated-file hint (argsbarg writers only). */
|
|
20
19
|
export function docsTopicIsGeneratedByArgsbarg(
|
|
@@ -34,7 +33,7 @@ export function docsSaveGeneratedHint(
|
|
|
34
33
|
return generatedFileHtmlComment(`${program.key} docs ${topic} --save`);
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
/** Inserts save hint
|
|
36
|
+
/** Inserts save hint into markdown content. */
|
|
38
37
|
export function applySaveGeneratedHint(
|
|
39
38
|
/** Program definition. */
|
|
40
39
|
program: CliProgram,
|
|
@@ -47,7 +46,7 @@ export function applySaveGeneratedHint(
|
|
|
47
46
|
return content;
|
|
48
47
|
}
|
|
49
48
|
const hint = docsSaveGeneratedHint(program, topic);
|
|
50
|
-
return insertGeneratedHint(content, hint
|
|
49
|
+
return insertGeneratedHint(content, hint);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
/** File body for `--save` (hint on argsbarg-generated markdown only). */
|
|
@@ -74,20 +73,17 @@ export function docsSaveFilename(
|
|
|
74
73
|
return `${topic}.md`;
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
/** Relative path under cwd for a saved docs topic
|
|
76
|
+
/** Relative path under cwd for a saved docs topic. */
|
|
78
77
|
export function docsSaveRelativePath(
|
|
79
78
|
/** Topic identifier. */
|
|
80
79
|
topic: string,
|
|
81
|
-
/** Program root for resolving app-specific paths
|
|
82
|
-
|
|
80
|
+
/** Program root for resolving app-specific paths. */
|
|
81
|
+
_program?: CliProgram,
|
|
83
82
|
): string {
|
|
84
|
-
if (topic === "skill" && program) {
|
|
85
|
-
return join("skills", skillDirName(program.key), "SKILL.md");
|
|
86
|
-
}
|
|
87
83
|
return join(DOCS_SAVE_DIR, docsSaveFilename(topic));
|
|
88
84
|
}
|
|
89
85
|
|
|
90
|
-
/** Writes one docs topic under `./docs
|
|
86
|
+
/** Writes one docs topic under `./docs/`; returns relative path written. */
|
|
91
87
|
export function saveDocsTopic(
|
|
92
88
|
/** Program definition root. */
|
|
93
89
|
program: CliProgram,
|
|
@@ -98,13 +94,6 @@ export function saveDocsTopic(
|
|
|
98
94
|
const abs = join(process.cwd(), rel);
|
|
99
95
|
mkdirSync(dirname(abs), { recursive: true });
|
|
100
96
|
|
|
101
|
-
if (topic === "skill") {
|
|
102
|
-
const legacyDoc = join(process.cwd(), DOCS_SAVE_DIR, "skill.md");
|
|
103
|
-
if (existsSync(legacyDoc)) {
|
|
104
|
-
rmSync(legacyDoc, { force: true });
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
97
|
writeFileSync(abs, docsTopicContentForSave(program, topic), "utf8");
|
|
109
98
|
return rel;
|
|
110
99
|
}
|