argsbarg 6.1.2 → 6.1.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 +65 -1
- package/README.md +17 -19
- package/bin/argsbarg +10 -0
- package/docs/README.md +4 -3
- package/docs/ai-skills.md +4 -2
- package/docs/bundled-docs.md +50 -25
- package/docs/cli-program.md +52 -10
- package/docs/config-schema.md +10 -11
- package/docs/configure.md +2 -0
- package/docs/decisions.md +40 -0
- package/docs/developing.md +43 -5
- package/docs/http-server.md +171 -0
- package/docs/json-schema-subset.md +51 -0
- package/docs/mcp.md +4 -2
- package/docs/output-schema.md +55 -62
- package/examples/formats.ts +6 -6
- package/examples/full-example/Formula/full-example.rb +35 -0
- package/examples/full-example/README.md +20 -21
- package/examples/full-example/docs/README.md +1 -1
- package/examples/full-example/docs/cli-schema.json +1790 -98
- package/examples/full-example/docs/cli.md +1990 -0
- package/examples/full-example/docs/http.md +28 -29
- package/examples/full-example/docs/mcp.md +8 -22
- package/examples/full-example/docs/openapi.json +783 -50
- package/examples/full-example/docs/skill.md +10 -10
- package/examples/full-example/justfile +11 -1
- package/examples/full-example/src/commands/render-json/__generated__/RenderJsonInputSchema.json +15 -0
- package/examples/full-example/src/commands/render-json/__generated__/index.ts +5 -0
- package/examples/full-example/src/commands/render-json/command.test.ts +46 -0
- package/examples/full-example/src/commands/render-json/command.ts +30 -0
- package/examples/full-example/src/commands/render-json/types.ts +9 -0
- package/examples/full-example/src/commands/status/__generated__/StatusJsonOutputSchema.json +15 -0
- package/examples/full-example/src/commands/status/__generated__/index.ts +2 -2
- package/examples/full-example/src/commands/status/command.ts +5 -13
- package/examples/full-example/src/commands/status/types.ts +1 -14
- package/examples/full-example/src/commands/workspaces/__generated__/WorkspaceNameInputSchema.json +15 -0
- package/examples/full-example/src/commands/workspaces/__generated__/index.ts +5 -0
- package/examples/full-example/src/commands/workspaces/command.test.ts +58 -0
- package/examples/full-example/src/commands/workspaces/command.ts +94 -0
- package/examples/full-example/src/commands/workspaces/types.ts +6 -0
- package/examples/full-example/src/db/index.test.ts +86 -0
- package/examples/full-example/src/db/index.ts +101 -0
- package/examples/full-example/src/db/migrate.test.ts +35 -0
- package/examples/full-example/src/db/migrate.ts +69 -0
- package/examples/full-example/src/db/migrations/001_workspaces.sql +6 -0
- package/examples/full-example/src/db/tables/workspaces.ts +66 -0
- package/examples/full-example/src/program.ts +11 -36
- package/examples/full-example/src/types/argsbarg.d.ts +11 -0
- package/examples/full-example/src/types/md.d.ts +4 -0
- package/examples/full-example/tsconfig.json +5 -2
- package/examples/mcp-test.ts +1 -2
- package/examples/minimal.ts +1 -7
- package/examples/nested.ts +1 -2
- package/examples/option-required.ts +1 -1
- package/examples/servers.ts +4 -5
- package/index.d.ts +431 -136
- package/package.json +19 -2
- package/src/builtins/builtins.test.ts +7 -7
- package/src/builtins/completion-bash.ts +1 -1
- package/src/builtins/completion-fish.ts +1 -1
- package/src/builtins/completion-group.ts +4 -4
- package/src/builtins/completion-simulate-shared.ts +9 -0
- package/src/builtins/completion-zsh.ts +1 -1
- package/src/builtins/config.test.ts +3 -3
- package/src/builtins/config.ts +9 -9
- package/src/builtins/configure-copy.ts +2 -2
- package/src/builtins/configure.ts +4 -4
- package/src/builtins/dispatch.ts +19 -18
- package/src/builtins/export.ts +7 -5
- package/src/builtins/http.ts +68 -0
- package/src/builtins/mcp.ts +28 -4
- package/src/builtins/presentation.ts +6 -6
- package/src/builtins/registry.ts +6 -6
- package/src/builtins/scopes.ts +2 -2
- package/src/builtins/version.ts +1 -1
- package/src/cli-tool/full-example-capabilities.test.ts +10 -15
- package/src/cli-tool/main.ts +1 -1
- package/src/cli-tool/program.ts +3 -2
- package/src/cli-tool/prompt.ts +1 -1
- package/src/cli-tool/run-schemagen.ts +1 -3
- package/src/cli-tool/schemagen/cleanup.ts +6 -7
- package/src/cli-tool/schemagen/discover-schema-roots.ts +66 -120
- package/src/cli-tool/schemagen/index.ts +2 -2
- package/src/cli-tool/schemagen/names.ts +8 -13
- package/src/cli-tool/schemagen/run.ts +21 -28
- package/src/cli-tool/schemagen/schemagen.test.ts +136 -46
- package/src/config/bindings.test.ts +1 -1
- package/src/config/bindings.ts +1 -1
- package/src/config/bootstrap.test.ts +1 -1
- package/src/config/bootstrap.ts +36 -4
- package/src/config/context.test.ts +1 -1
- package/src/config/context.ts +1 -1
- package/src/config/entry.ts +1 -1
- package/src/config/file.test.ts +1 -1
- package/src/config/file.ts +3 -3
- package/src/config/manifest.ts +1 -1
- package/src/config/resolve.test.ts +1 -1
- package/src/config/resolve.ts +1 -1
- package/src/config/schema.ts +1 -1
- package/src/config/validate.ts +1 -1
- package/src/{install → configure/artifacts}/binary-placement.test.ts +1 -1
- package/src/{install → configure/artifacts}/binary-placement.ts +1 -1
- package/src/{install → configure/artifacts}/gh-release-update.ts +1 -1
- package/src/{install → configure/artifacts}/install-validate.test.ts +3 -3
- package/src/{install → configure/artifacts}/mcp-config.ts +1 -1
- package/src/{install → configure/artifacts}/mcp-opencode.test.ts +1 -1
- package/src/{install → configure/artifacts}/mcp-opencode.ts +1 -1
- package/src/{install → configure/artifacts}/paths.ts +5 -5
- package/src/configure/artifacts/plan.ts +24 -0
- package/src/{install → configure/artifacts}/status.test.ts +1 -1
- package/src/{install → configure/artifacts}/status.ts +2 -2
- package/src/{install → configure/artifacts}/target-base.ts +1 -1
- package/src/{install → configure/artifacts}/target-detect.ts +1 -1
- package/src/{install → configure/artifacts}/target-effective.ts +3 -9
- package/src/{install → configure/artifacts}/target-mcp-cli.ts +1 -1
- package/src/{install → configure/artifacts}/target-mcp-json.ts +1 -1
- package/src/{install → configure/artifacts}/target-plan-build.ts +2 -2
- package/src/{install → configure/artifacts}/target-registry.ts +2 -2
- package/src/{install → configure/artifacts}/target-scope.ts +3 -3
- package/src/{install → configure/artifacts}/target-skill.ts +1 -1
- package/src/{install → configure/artifacts}/target-types.ts +2 -2
- package/src/{install → configure/artifacts}/targets/app.ts +5 -5
- package/src/{install → configure/artifacts}/targets/chatgpt-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-code-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-desktop-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/codex-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/codex-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/configure.ts +5 -5
- package/src/{install → configure/artifacts}/targets/cursor-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/cursor-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/index.ts +1 -1
- package/src/{install → configure/artifacts}/targets/openclaw-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/openclaw-skill.ts +3 -3
- package/src/{install → configure/artifacts}/targets/opencode-mcp.ts +5 -5
- package/src/{install → configure/artifacts}/targets/opencode-skill.ts +3 -3
- package/src/{install → configure/artifacts}/targets.test.ts +1 -1
- package/src/{install → configure/artifacts}/uninstall.ts +1 -1
- package/src/configure/configure.test.ts +11 -11
- package/src/configure/index.ts +14 -14
- package/src/configure/prompt.ts +2 -2
- package/src/{context.ts → core/context.ts} +26 -20
- package/src/{json-leaf.test.ts → core/json-leaf.test.ts} +4 -4
- package/src/{leaf-inputs.test.ts → core/leaf-inputs.test.ts} +7 -7
- package/src/{leaf-inputs.ts → core/leaf-inputs.ts} +16 -12
- package/src/{parse.test.ts → core/parse.test.ts} +97 -109
- package/src/{parse.ts → core/parse.ts} +129 -31
- package/src/{schema.ts → core/schema.ts} +25 -13
- package/src/{types.ts → core/types.ts} +225 -35
- package/src/{validate.ts → core/validate.ts} +39 -29
- package/src/docs/builtin.ts +8 -19
- package/src/docs/{api-guide.test.ts → cli-guide.test.ts} +21 -21
- package/src/docs/{api-guide.ts → cli-guide.ts} +45 -16
- package/src/docs/docs.test.ts +76 -41
- package/src/docs/http-guide.ts +37 -34
- package/src/docs/mcp-guide.ts +12 -14
- package/src/docs/mcp-resources.test.ts +2 -3
- package/src/docs/mcp-resources.ts +6 -11
- package/src/docs/resolve.ts +22 -30
- package/src/docs/save.ts +3 -3
- package/src/exports/cli.ts +47 -0
- package/src/exports/headless.ts +13 -0
- package/src/exports/http.ts +6 -0
- package/src/exports/mcp.ts +6 -0
- package/src/{headless.test.ts → headless/routing.test.ts} +3 -3
- package/src/{headless.ts → headless/routing.ts} +3 -3
- package/src/headless/tool-call.ts +114 -46
- package/src/help.test.ts +152 -0
- package/src/help.ts +3 -3
- package/src/hooks/builtin.ts +20 -0
- package/src/hooks/run.ts +142 -0
- package/src/http/openapi.ts +182 -0
- package/src/http/readiness.ts +78 -0
- package/src/{api → http}/result.ts +16 -5
- package/src/http/routes.ts +329 -0
- package/src/http/server.ts +225 -0
- package/src/index.ts +36 -25
- package/src/log/ecs.test.ts +43 -0
- package/src/log/ecs.ts +59 -0
- package/src/log/emitter.ts +166 -0
- package/src/mcp/bundle.ts +2 -2
- package/src/mcp/claude.test.ts +1 -1
- package/src/mcp/claude.ts +4 -4
- package/src/{hidden-mcpb.test.ts → mcp/hidden-mcpb.test.ts} +10 -9
- package/src/mcp/result.ts +2 -2
- package/src/mcp/server.ts +54 -6
- package/src/mcp/tools.ts +9 -20
- package/src/{capabilities.ts → runtime/capabilities.ts} +11 -11
- package/src/{cli-errors.ts → runtime/cli-errors.ts} +4 -4
- package/src/{cli.ts → runtime/cli.ts} +159 -49
- package/src/runtime/exposure.ts +102 -0
- package/src/{invoke.test.ts → runtime/invoke.test.ts} +31 -7
- package/src/server/context.ts +25 -0
- package/src/server/overrides.ts +112 -0
- package/src/skill/generate.ts +8 -8
- package/src/skill/hint.ts +1 -1
- package/src/skill/install.ts +2 -2
- package/src/skill/naming.ts +1 -1
- package/src/{test-fixtures.ts → test/fixtures.ts} +3 -2
- package/src/{config.integration.test.ts → test/integration/config.test.ts} +8 -8
- package/src/{api.integration.test.ts → test/integration/http.test.ts} +170 -67
- package/src/{mcp.integration.test.ts → test/integration/mcp.test.ts} +11 -57
- package/docs/api-server.md +0 -141
- package/examples/full-example/docs/api.md +0 -511
- package/examples/full-example/src/commands/status/__generated__/outputSchema.json +0 -28
- package/examples/full-example/src/config/__generated__/configSchema.json +0 -40
- package/examples/full-example/src/config/__generated__/index.ts +0 -5
- package/examples/full-example/src/config/types.ts +0 -24
- package/src/api/openapi.ts +0 -117
- package/src/api/server.ts +0 -120
- package/src/builtins/api.ts +0 -38
- package/src/hidden.ts +0 -30
- package/src/install/plan.ts +0 -53
- /package/src/{install → configure/artifacts}/detect-installed.ts +0 -0
- /package/src/{install → configure/artifacts}/gh-release-update.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-codex.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-codex.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-openclaw.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-openclaw.ts +0 -0
- /package/src/{install → configure/artifacts}/normalize-uninstall.ts +0 -0
- /package/src/{install → configure/artifacts}/normalize.ts +0 -0
- /package/src/{install → configure/artifacts}/opts.ts +0 -0
- /package/src/{install → configure/artifacts}/shell.ts +0 -0
- /package/src/{formats.test.ts → core/formats.test.ts} +0 -0
- /package/src/{formats.ts → core/formats.ts} +0 -0
- /package/src/{respond.ts → core/respond.ts} +0 -0
- /package/src/{types.test.ts → core/types.test.ts} +0 -0
- /package/src/{api → http}/schema-deref.test.ts +0 -0
- /package/src/{api → http}/schema-deref.ts +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Tests for docs/
|
|
2
|
+
Tests for docs/cli-guide module behavior.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { expect, test } from "bun:test";
|
|
6
|
-
import { cliSchemaExport } from "
|
|
7
|
-
import type { CliProgram } from "
|
|
8
|
-
import { CliOptionKind } from "
|
|
9
|
-
import {
|
|
6
|
+
import { cliSchemaExport } from "~/core/schema.ts";
|
|
7
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
8
|
+
import { CliOptionKind } from "~/core/types.ts";
|
|
9
|
+
import { generateCliGuide, generateCliGuideBody } from "./cli-guide.ts";
|
|
10
10
|
|
|
11
11
|
const nestedFixture: CliProgram = {
|
|
12
12
|
key: "nested.ts",
|
|
13
13
|
version: "1.0.0",
|
|
14
14
|
description: "Nested groups demo.",
|
|
15
|
-
docs: {
|
|
15
|
+
docs: { topics: { readme: { text: "# readme\n" } } },
|
|
16
16
|
commands: [
|
|
17
17
|
{
|
|
18
18
|
key: "stat",
|
|
@@ -49,16 +49,16 @@ const nestedFixture: CliProgram = {
|
|
|
49
49
|
],
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
test("
|
|
53
|
-
const body =
|
|
54
|
-
const full =
|
|
52
|
+
test("generateCliGuideBody matches command section of full API guide", () => {
|
|
53
|
+
const body = generateCliGuideBody(nestedFixture);
|
|
54
|
+
const full = generateCliGuide(nestedFixture);
|
|
55
55
|
expect(full).toContain(body.trimEnd());
|
|
56
56
|
expect(body).toContain("## `nested.ts stat`");
|
|
57
57
|
expect(body).not.toContain("CLI API reference");
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
test("
|
|
61
|
-
const md =
|
|
60
|
+
test("generateCliGuide covers the same command keys as cliSchemaExport", () => {
|
|
61
|
+
const md = generateCliGuide(nestedFixture);
|
|
62
62
|
const schema = cliSchemaExport(nestedFixture);
|
|
63
63
|
expect(md).toContain("`nested.ts stat owner lookup`");
|
|
64
64
|
expect(md).toContain("`--user-name` (`-u`)");
|
|
@@ -66,34 +66,34 @@ test("generateApiGuide covers the same command keys as cliSchemaExport", () => {
|
|
|
66
66
|
expect(schema.commands?.map((c) => c.key)).toEqual(["stat"]);
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
test("
|
|
69
|
+
test("generateCliGuide configure notes point to README not brew install", () => {
|
|
70
70
|
const fixture: CliProgram = {
|
|
71
71
|
key: "myapp",
|
|
72
72
|
version: "1.0.0",
|
|
73
73
|
description: "Demo app.",
|
|
74
74
|
commands: [{ key: "run", description: "Run.", handler: () => {} }],
|
|
75
75
|
};
|
|
76
|
-
const md =
|
|
76
|
+
const md = generateCliGuide(fixture);
|
|
77
77
|
expect(md).not.toContain("{argsbarg:program}");
|
|
78
78
|
expect(md).toContain("README");
|
|
79
79
|
expect(md).not.toContain("brew install <tap>");
|
|
80
80
|
expect(md).not.toContain("Upgrade to latest release");
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
test("
|
|
83
|
+
test("generateCliGuide mentions Homebrew upgrade", () => {
|
|
84
84
|
const fixture: CliProgram = {
|
|
85
85
|
key: "myapp",
|
|
86
86
|
version: "1.0.0",
|
|
87
87
|
description: "Demo app.",
|
|
88
88
|
commands: [{ key: "run", description: "Run.", handler: () => {} }],
|
|
89
89
|
};
|
|
90
|
-
const md =
|
|
90
|
+
const md = generateCliGuide(fixture);
|
|
91
91
|
expect(md).toContain("brew upgrade");
|
|
92
92
|
expect(md).not.toContain("install --update");
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
/** Tests that
|
|
96
|
-
test("
|
|
95
|
+
/** Tests that generateCliGuide resolves {argsbarg:program} in consumer notes. */
|
|
96
|
+
test("generateCliGuide resolves {argsbarg:program} in consumer notes", () => {
|
|
97
97
|
const fixture: CliProgram = {
|
|
98
98
|
key: "myapp",
|
|
99
99
|
version: "1.0.0",
|
|
@@ -107,12 +107,12 @@ test("generateApiGuide resolves {argsbarg:program} in consumer notes", () => {
|
|
|
107
107
|
},
|
|
108
108
|
],
|
|
109
109
|
};
|
|
110
|
-
const md =
|
|
110
|
+
const md = generateCliGuide(fixture);
|
|
111
111
|
expect(md).toContain("Invoke `myapp run`.");
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
/** Tests that
|
|
115
|
-
test("
|
|
114
|
+
/** Tests that generateCliGuide and cliSchemaExport include leaf outputSchema. */
|
|
115
|
+
test("generateCliGuide and cliSchemaExport include leaf outputSchema", () => {
|
|
116
116
|
const fixture: CliProgram = {
|
|
117
117
|
key: "myapp",
|
|
118
118
|
version: "1.0.0",
|
|
@@ -136,7 +136,7 @@ test("generateApiGuide and cliSchemaExport include leaf outputSchema", () => {
|
|
|
136
136
|
properties: { id: { type: "string" } },
|
|
137
137
|
required: ["id"],
|
|
138
138
|
});
|
|
139
|
-
const md =
|
|
139
|
+
const md = generateCliGuide(fixture);
|
|
140
140
|
expect(md).toContain("#### Output");
|
|
141
141
|
expect(md).toContain('"id"');
|
|
142
142
|
expect(md).toContain('"type": "string"');
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import type { CliSchemaExport } from "
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
1
|
+
import type { CliSchemaExport } from "~/builtins/export.ts";
|
|
2
|
+
import { cliSchemaExport } from "~/core/schema.ts";
|
|
3
|
+
import type { CliOption, CliPositional, CliProgram } from "~/core/types.ts";
|
|
4
|
+
import { CliFallbackMode, CliOptionKind } from "~/core/types.ts";
|
|
5
|
+
import { cliPositionalLabel, cliResolveNotes } from "~/help.ts";
|
|
6
|
+
|
|
7
|
+
/** Options for {@link generateCliGuideBody} and {@link generateCliGuide}. */
|
|
8
|
+
export interface CliGuideBodyOptions {
|
|
9
|
+
/** Omit embedded outputSchema JSON; point to `docs cli-schema` instead (skill reference). */
|
|
10
|
+
compact?: boolean;
|
|
11
|
+
}
|
|
6
12
|
|
|
7
13
|
/** CLI invocation path as a single string (`myapp stat owner lookup`). */
|
|
8
14
|
function commandPath(rootKey: string, path: string[]): string {
|
|
@@ -66,7 +72,7 @@ function formatNotesBlockquote(notes: string, appKey: string): string {
|
|
|
66
72
|
.join("\n");
|
|
67
73
|
}
|
|
68
74
|
|
|
69
|
-
/** Markdown section for leaf outputSchema (docs
|
|
75
|
+
/** Markdown section for leaf outputSchema (docs cli / skill reference). */
|
|
70
76
|
function formatOutputSchemaSection(schema: Record<string, unknown>): string[] {
|
|
71
77
|
return [
|
|
72
78
|
"#### Output",
|
|
@@ -89,8 +95,19 @@ function fallbackLine(node: CliSchemaExport): string | null {
|
|
|
89
95
|
return `**Default subcommand:** \`${node.fallbackCommand}\` (\`${mode}\`)`;
|
|
90
96
|
}
|
|
91
97
|
|
|
98
|
+
/** Compact outputSchema pointer instead of inlined JSON. */
|
|
99
|
+
function formatOutputSchemaPointer(rootKey: string): string[] {
|
|
100
|
+
return ["#### Output", "", `See \`${rootKey} docs cli-schema\` for outputSchema when set.`, ""];
|
|
101
|
+
}
|
|
102
|
+
|
|
92
103
|
/** Renders one command node and recurses into subcommands. */
|
|
93
|
-
function renderCommandNode(
|
|
104
|
+
function renderCommandNode(
|
|
105
|
+
rootKey: string,
|
|
106
|
+
path: string[],
|
|
107
|
+
node: CliSchemaExport,
|
|
108
|
+
lines: string[],
|
|
109
|
+
opts: CliGuideBodyOptions,
|
|
110
|
+
): void {
|
|
94
111
|
const level = Math.min(path.length + 2, 6);
|
|
95
112
|
const heading = "#".repeat(level);
|
|
96
113
|
const cmd = commandPath(rootKey, path);
|
|
@@ -106,7 +123,15 @@ function renderCommandNode(rootKey: string, path: string[], node: CliSchemaExpor
|
|
|
106
123
|
lines.push(fb, "");
|
|
107
124
|
}
|
|
108
125
|
|
|
109
|
-
|
|
126
|
+
const isJsonStyleLeaf =
|
|
127
|
+
opts.compact &&
|
|
128
|
+
(node.options ?? []).length === 0 &&
|
|
129
|
+
(node.positionals ?? []).length === 0 &&
|
|
130
|
+
!node.commands?.length;
|
|
131
|
+
|
|
132
|
+
if (isJsonStyleLeaf) {
|
|
133
|
+
lines.push(`Input shape: see \`${rootKey} docs cli-schema\`.`, "");
|
|
134
|
+
} else if ((node.options ?? []).length > 0) {
|
|
110
135
|
lines.push("#### Options", "");
|
|
111
136
|
lines.push("| Option | Type | Required | Format / default | Description |");
|
|
112
137
|
lines.push("| --- | --- | --- | --- | --- |");
|
|
@@ -127,7 +152,11 @@ function renderCommandNode(rootKey: string, path: string[], node: CliSchemaExpor
|
|
|
127
152
|
}
|
|
128
153
|
|
|
129
154
|
if (node.outputSchema !== undefined) {
|
|
130
|
-
|
|
155
|
+
if (opts.compact) {
|
|
156
|
+
lines.push(...formatOutputSchemaPointer(rootKey));
|
|
157
|
+
} else {
|
|
158
|
+
lines.push(...formatOutputSchemaSection(node.outputSchema));
|
|
159
|
+
}
|
|
131
160
|
}
|
|
132
161
|
|
|
133
162
|
const children = node.commands ?? [];
|
|
@@ -140,20 +169,20 @@ function renderCommandNode(rootKey: string, path: string[], node: CliSchemaExpor
|
|
|
140
169
|
}
|
|
141
170
|
|
|
142
171
|
for (const child of children) {
|
|
143
|
-
renderCommandNode(rootKey, [...path, child.key], child, lines);
|
|
172
|
+
renderCommandNode(rootKey, [...path, child.key], child, lines, opts);
|
|
144
173
|
}
|
|
145
174
|
}
|
|
146
175
|
|
|
147
|
-
/** Command-tree markdown shared by `docs
|
|
148
|
-
export function
|
|
176
|
+
/** Command-tree markdown shared by `docs cli` and generated agent skills (no API doc header). */
|
|
177
|
+
export function generateCliGuideBody(program: CliProgram, opts: CliGuideBodyOptions = {}): string {
|
|
149
178
|
const schema = cliSchemaExport(program);
|
|
150
179
|
const lines: string[] = [];
|
|
151
|
-
renderCommandNode(program.key, [], schema, lines);
|
|
180
|
+
renderCommandNode(program.key, [], schema, lines, opts);
|
|
152
181
|
return `${lines.join("\n").trimEnd()}\n`;
|
|
153
182
|
}
|
|
154
183
|
|
|
155
|
-
/** Generates markdown
|
|
156
|
-
export function
|
|
184
|
+
/** Generates markdown CLI reference from the same export as `docs cli-schema`. */
|
|
185
|
+
export function generateCliGuide(program: CliProgram, opts: CliGuideBodyOptions = {}): string {
|
|
157
186
|
const schema = cliSchemaExport(program);
|
|
158
187
|
const lines: string[] = [
|
|
159
188
|
`# ${program.key} — CLI API reference`,
|
|
@@ -168,6 +197,6 @@ export function generateApiGuide(program: CliProgram): string {
|
|
|
168
197
|
lines.push(formatNotesBlockquote(schema.notes, program.key), "");
|
|
169
198
|
}
|
|
170
199
|
|
|
171
|
-
lines.push(
|
|
200
|
+
lines.push(generateCliGuideBody(program, opts).trimEnd(), "");
|
|
172
201
|
return `${lines.join("\n").trimEnd()}\n`;
|
|
173
202
|
}
|
package/src/docs/docs.test.ts
CHANGED
|
@@ -6,14 +6,15 @@ import { afterEach, beforeEach, expect, test } from "bun:test";
|
|
|
6
6
|
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import { completionBashScript } from "
|
|
10
|
-
import { cliPresentationRoot } from "
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
9
|
+
import { completionBashScript } from "~/builtins";
|
|
10
|
+
import { cliPresentationRoot } from "~/builtins/presentation.ts";
|
|
11
|
+
import { ParseKind, parse } from "~/core/parse.ts";
|
|
12
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
13
|
+
import { cliValidateProgram } from "~/core/validate.ts";
|
|
14
|
+
import { cliHelpRender } from "~/help.ts";
|
|
15
|
+
import { Cli } from "~/index";
|
|
16
|
+
import { resolveCapabilities, skipsRequiredAppConfigExit } from "~/runtime/capabilities.ts";
|
|
15
17
|
import { generateMcpGuide } from "./mcp-guide.ts";
|
|
16
|
-
import { docsEffectiveDefaultTopic } from "./resolve.ts";
|
|
17
18
|
import { saveDocsTopic } from "./save.ts";
|
|
18
19
|
|
|
19
20
|
let workDir: string;
|
|
@@ -37,7 +38,6 @@ function docsFixture(mcp = true): CliProgram {
|
|
|
37
38
|
description: "Demo app.",
|
|
38
39
|
mcpServer: mcp ? { enabled: true } : undefined,
|
|
39
40
|
docs: {
|
|
40
|
-
enabled: true,
|
|
41
41
|
topics: {
|
|
42
42
|
readme: { text: "# Hello README\n" },
|
|
43
43
|
arch: { text: "# Architecture\n", description: "Contributor notes." },
|
|
@@ -72,16 +72,16 @@ test("docs reserved when enabled", () => {
|
|
|
72
72
|
test("docs rejects reserved topic keys", () => {
|
|
73
73
|
const root = docsFixture();
|
|
74
74
|
const docs = root.docs;
|
|
75
|
-
if (!docs) throw new Error("expected docs fixture");
|
|
75
|
+
if (!docs?.topics) throw new Error("expected docs fixture");
|
|
76
76
|
docs.topics["cli-schema"] = { text: "nope" };
|
|
77
77
|
expect(() => cliValidateProgram(root)).toThrow(/reserved/);
|
|
78
78
|
delete docs.topics["cli-schema"];
|
|
79
79
|
docs.topics.skill = { text: "nope" };
|
|
80
80
|
expect(() => cliValidateProgram(root)).toThrow(/reserved/);
|
|
81
81
|
delete docs.topics.skill;
|
|
82
|
-
docs.topics.
|
|
82
|
+
docs.topics.cli = { text: "nope" };
|
|
83
83
|
expect(() => cliValidateProgram(root)).toThrow(/reserved/);
|
|
84
|
-
delete docs.topics.
|
|
84
|
+
delete docs.topics.cli;
|
|
85
85
|
docs.topics.openapi = { text: "nope" };
|
|
86
86
|
expect(() => cliValidateProgram(root)).toThrow(/reserved/);
|
|
87
87
|
delete docs.topics.openapi;
|
|
@@ -89,14 +89,57 @@ test("docs rejects reserved topic keys", () => {
|
|
|
89
89
|
expect(() => cliValidateProgram(root)).toThrow(/reserved/);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
test("
|
|
93
|
-
|
|
92
|
+
test("docs enabled by default without docs block", () => {
|
|
93
|
+
const root: CliProgram = {
|
|
94
|
+
key: "myapp",
|
|
95
|
+
version: "1.0.0",
|
|
96
|
+
description: "Demo.",
|
|
97
|
+
commands: [{ key: "run", description: "Run.", handler: () => {} }],
|
|
98
|
+
};
|
|
99
|
+
expect(resolveCapabilities(root).docs).toBe(true);
|
|
100
|
+
cliValidateProgram(root);
|
|
94
101
|
});
|
|
95
102
|
|
|
96
|
-
test("
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
test("docs opt-out allows user command named docs", () => {
|
|
104
|
+
const root: CliProgram = {
|
|
105
|
+
key: "myapp",
|
|
106
|
+
version: "1.0.0",
|
|
107
|
+
description: "Demo.",
|
|
108
|
+
docs: { enabled: false },
|
|
109
|
+
commands: [
|
|
110
|
+
{
|
|
111
|
+
key: "docs",
|
|
112
|
+
description: "Custom docs.",
|
|
113
|
+
handler: () => {},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
expect(resolveCapabilities(root).docs).toBe(false);
|
|
118
|
+
cliValidateProgram(root);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("built-in docs work without topics", async () => {
|
|
122
|
+
const root: CliProgram = {
|
|
123
|
+
key: "myapp",
|
|
124
|
+
version: "1.0.0",
|
|
125
|
+
description: "Demo.",
|
|
126
|
+
commands: [{ key: "run", description: "Run.", handler: () => {} }],
|
|
127
|
+
};
|
|
128
|
+
const cliRef = await new Cli(root).invoke(["docs", "cli"]);
|
|
129
|
+
expect(cliRef.exitCode).toBe(0);
|
|
130
|
+
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
|
+
});
|
|
135
|
+
|
|
136
|
+
test("bare docs shows router help", () => {
|
|
137
|
+
const root = cliPresentationRoot(docsFixture());
|
|
138
|
+
const pr = parse(root, ["docs"]);
|
|
139
|
+
expect(pr.kind).toBe(ParseKind.Help);
|
|
140
|
+
const help = cliHelpRender(root, pr.helpPath, false);
|
|
141
|
+
expect(help).toContain("cli");
|
|
142
|
+
expect(help).not.toContain("Hello README");
|
|
100
143
|
});
|
|
101
144
|
|
|
102
145
|
test("docs readme prints bundled text", async () => {
|
|
@@ -104,14 +147,6 @@ test("docs readme prints bundled text", async () => {
|
|
|
104
147
|
expect(result.exitCode).toBe(0);
|
|
105
148
|
expect(result.stdout).toContain("Hello README");
|
|
106
149
|
});
|
|
107
|
-
|
|
108
|
-
test("docs defaultTopic override", async () => {
|
|
109
|
-
const root = docsFixture();
|
|
110
|
-
root.docs!.defaultTopic = "arch";
|
|
111
|
-
const result = await new Cli(root).invoke(["docs"]);
|
|
112
|
-
expect(result.stdout).toContain("Architecture");
|
|
113
|
-
});
|
|
114
|
-
|
|
115
150
|
test("docs mcp when MCP enabled", async () => {
|
|
116
151
|
const result = await new Cli(docsFixture(true)).invoke(["docs", "mcp"]);
|
|
117
152
|
expect(result.exitCode).toBe(0);
|
|
@@ -140,7 +175,7 @@ test("docs mcp absent from router when MCP disabled", async () => {
|
|
|
140
175
|
|
|
141
176
|
test("docs http when API enabled", async () => {
|
|
142
177
|
const root = docsFixture(true);
|
|
143
|
-
root.
|
|
178
|
+
root.httpServer = { enabled: true };
|
|
144
179
|
cliValidateProgram(root);
|
|
145
180
|
const result = await new Cli(root).invoke(["docs", "http"]);
|
|
146
181
|
expect(result.exitCode).toBe(0);
|
|
@@ -163,7 +198,7 @@ test("docs http absent from router when API disabled", async () => {
|
|
|
163
198
|
|
|
164
199
|
test("docs openapi when API enabled", async () => {
|
|
165
200
|
const root = docsFixture(true);
|
|
166
|
-
root.
|
|
201
|
+
root.httpServer = { enabled: true };
|
|
167
202
|
cliValidateProgram(root);
|
|
168
203
|
const result = await new Cli(root).invoke(["docs", "openapi"]);
|
|
169
204
|
expect(result.exitCode).toBe(0);
|
|
@@ -193,8 +228,8 @@ test("docs cli-schema prints JSON", async () => {
|
|
|
193
228
|
expect(schema.commands.some((c: { key: string }) => c.key === "run")).toBe(true);
|
|
194
229
|
});
|
|
195
230
|
|
|
196
|
-
test("docs
|
|
197
|
-
const result = await new Cli(docsFixture()).invoke(["docs", "
|
|
231
|
+
test("docs cli prints markdown reference", async () => {
|
|
232
|
+
const result = await new Cli(docsFixture()).invoke(["docs", "cli"]);
|
|
198
233
|
expect(result.exitCode).toBe(0);
|
|
199
234
|
expect(result.stdout).toContain("# myapp — CLI API reference");
|
|
200
235
|
expect(result.stdout).toContain("## `myapp run`");
|
|
@@ -210,7 +245,7 @@ test("skipsRequiredAppConfigExit includes docs and config builtins", () => {
|
|
|
210
245
|
},
|
|
211
246
|
};
|
|
212
247
|
const caps = resolveCapabilities(program);
|
|
213
|
-
expect(skipsRequiredAppConfigExit(["docs", "
|
|
248
|
+
expect(skipsRequiredAppConfigExit(["docs", "cli"], caps)).toBe(true);
|
|
214
249
|
expect(skipsRequiredAppConfigExit(["configure", "get"], caps)).toBe(true);
|
|
215
250
|
expect(skipsRequiredAppConfigExit(["run"], caps)).toBe(false);
|
|
216
251
|
});
|
|
@@ -247,7 +282,7 @@ test("presentation includes docs cli-schema and skill", () => {
|
|
|
247
282
|
expect(docsNode && "commands" in docsNode).toBe(true);
|
|
248
283
|
if (docsNode && "commands" in docsNode) {
|
|
249
284
|
expect(docsNode.commands.some((c) => c.key === "cli-schema")).toBe(true);
|
|
250
|
-
expect(docsNode.commands.some((c) => c.key === "
|
|
285
|
+
expect(docsNode.commands.some((c) => c.key === "cli")).toBe(true);
|
|
251
286
|
expect(docsNode.commands.some((c) => c.key === "skill")).toBe(true);
|
|
252
287
|
}
|
|
253
288
|
});
|
|
@@ -257,7 +292,7 @@ test("completions offer docs subcommands", () => {
|
|
|
257
292
|
expect(bash).toContain("docs) echo");
|
|
258
293
|
expect(bash).toContain("readme) echo");
|
|
259
294
|
expect(bash).toContain("cli-schema) echo");
|
|
260
|
-
expect(bash).toContain("
|
|
295
|
+
expect(bash).toContain("cli) echo");
|
|
261
296
|
expect(bash).toContain("skill) echo");
|
|
262
297
|
});
|
|
263
298
|
|
|
@@ -283,11 +318,11 @@ test("docs --save writes topic file", async () => {
|
|
|
283
318
|
expect(text).not.toContain("Generated by");
|
|
284
319
|
});
|
|
285
320
|
|
|
286
|
-
test("docs
|
|
287
|
-
const result = await new Cli(docsFixture()).invoke(["docs", "
|
|
321
|
+
test("docs cli --save prepends generated hint", async () => {
|
|
322
|
+
const result = await new Cli(docsFixture()).invoke(["docs", "cli", "--save"]);
|
|
288
323
|
expect(result.exitCode).toBe(0);
|
|
289
|
-
const text = readFileSync(join(workDir, "docs/
|
|
290
|
-
expect(text.startsWith("<!-- Generated by myapp docs
|
|
324
|
+
const text = readFileSync(join(workDir, "docs/cli.md"), "utf8");
|
|
325
|
+
expect(text.startsWith("<!-- Generated by myapp docs cli --save; do not edit. -->\n\n")).toBe(true);
|
|
291
326
|
expect(text).toContain("CLI API reference");
|
|
292
327
|
});
|
|
293
328
|
|
|
@@ -313,7 +348,7 @@ test("docs cli-schema --save writes JSON file", async () => {
|
|
|
313
348
|
|
|
314
349
|
test("docs openapi --save writes JSON file", async () => {
|
|
315
350
|
const root = docsFixture(true);
|
|
316
|
-
root.
|
|
351
|
+
root.httpServer = { enabled: true };
|
|
317
352
|
const result = await new Cli(root).invoke(["docs", "openapi", "--save"]);
|
|
318
353
|
expect(result.exitCode).toBe(0);
|
|
319
354
|
expect(result.stdout.trim()).toBe("docs/openapi.json");
|
|
@@ -324,9 +359,9 @@ test("docs openapi --save writes JSON file", async () => {
|
|
|
324
359
|
});
|
|
325
360
|
|
|
326
361
|
test("saveDocsTopic returns relative path", () => {
|
|
327
|
-
const path = saveDocsTopic(docsFixture(), "
|
|
328
|
-
expect(path).toBe("docs/
|
|
329
|
-
const text = readFileSync(join(workDir, "docs/
|
|
330
|
-
expect(text).toContain("<!-- Generated by myapp docs
|
|
362
|
+
const path = saveDocsTopic(docsFixture(), "cli");
|
|
363
|
+
expect(path).toBe("docs/cli.md");
|
|
364
|
+
const text = readFileSync(join(workDir, "docs/cli.md"), "utf8");
|
|
365
|
+
expect(text).toContain("<!-- Generated by myapp docs cli --save; do not edit. -->");
|
|
331
366
|
expect(text).toContain("CLI API reference");
|
|
332
367
|
});
|
package/src/docs/http-guide.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { defaultConfigEntryTitle } from "~/config/entry.ts";
|
|
2
|
+
import { displayAppConfigPath } from "~/config/file.ts";
|
|
3
|
+
import { collectOptionDefs } from "~/core/parse.ts";
|
|
4
|
+
import { CliOptionKind, type CliProgram } from "~/core/types.ts";
|
|
5
|
+
import { collectHttpRoutes } from "~/http/routes.ts";
|
|
6
|
+
import { resolveHttpListenAddress } from "~/http/server.ts";
|
|
7
7
|
|
|
8
|
-
/** Formats one
|
|
9
|
-
function
|
|
10
|
-
const cliPath =
|
|
11
|
-
let line = `- \`${
|
|
12
|
-
const opts = collectOptionDefs(root,
|
|
8
|
+
/** Formats one HTTP route for the auto-generated HTTP guide. */
|
|
9
|
+
function formatRouteLine(root: CliProgram, route: ReturnType<typeof collectHttpRoutes>[number]): string {
|
|
10
|
+
const cliPath = route.commandPath.join(" ");
|
|
11
|
+
let line = `- \`${route.method} ${route.openApiPath}\` (CLI: \`${root.key} ${cliPath}\`) — ${route.leaf.description}`;
|
|
12
|
+
const opts = collectOptionDefs(root, route.commandPath);
|
|
13
13
|
const flags = opts.filter((o) => o.kind === CliOptionKind.Presence).map((o) => `--${o.name}`);
|
|
14
14
|
if (flags.length > 0) {
|
|
15
15
|
line += ` (flags: ${flags.join(", ")})`;
|
|
@@ -19,27 +19,27 @@ function formatToolLine(root: CliProgram, tool: McpToolDef): string {
|
|
|
19
19
|
|
|
20
20
|
/** Generates the auto `docs http` markdown guide from schema and API config. */
|
|
21
21
|
export function generateHttpGuide(root: CliProgram): string {
|
|
22
|
-
const api = root.
|
|
22
|
+
const api = root.httpServer;
|
|
23
23
|
if (!api) {
|
|
24
24
|
throw new Error("HTTP API server not enabled");
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const
|
|
28
|
-
const { hostname, port } =
|
|
27
|
+
const routes = collectHttpRoutes(root);
|
|
28
|
+
const { hostname, port } = resolveHttpListenAddress(root);
|
|
29
29
|
const baseUrl = `http://${hostname}:${port}`;
|
|
30
30
|
|
|
31
31
|
const lines: string[] = [
|
|
32
32
|
`# HTTP API (${root.key})`,
|
|
33
33
|
"",
|
|
34
|
-
`${root.key} exposes
|
|
34
|
+
`${root.key} exposes user commands over HTTP REST routes derived from the CLI tree.`,
|
|
35
35
|
"",
|
|
36
36
|
"## Running",
|
|
37
37
|
"",
|
|
38
38
|
"```bash",
|
|
39
|
-
`${root.key}
|
|
39
|
+
`${root.key} http`,
|
|
40
40
|
"```",
|
|
41
41
|
"",
|
|
42
|
-
`Listens on **${baseUrl}** by default (\`
|
|
42
|
+
`Listens on **${baseUrl}** by default (\`httpServer.host\` / \`httpServer.port\`).`,
|
|
43
43
|
"",
|
|
44
44
|
"Bind is localhost-only in v0 — use a reverse proxy for remote access.",
|
|
45
45
|
"",
|
|
@@ -47,27 +47,30 @@ export function generateHttpGuide(root: CliProgram): string {
|
|
|
47
47
|
"",
|
|
48
48
|
"| Method | Path | Purpose |",
|
|
49
49
|
"| --- | --- | --- |",
|
|
50
|
-
"| `GET` | `/health` | Liveness check |",
|
|
51
|
-
"| `GET` | `/
|
|
50
|
+
"| `GET` | `/health` or `/health/live` | Liveness check |",
|
|
51
|
+
"| `GET` | `/health/ready` | Readiness (config + `program.readiness`) |",
|
|
52
|
+
"| `GET` | `/openapi.json` | OpenAPI 3.1 REST paths |",
|
|
52
53
|
"| `GET` | `/openapi-browser` | Interactive Scalar API reference |",
|
|
53
|
-
"|
|
|
54
|
+
"| `*` | `/api/...` | Invoke user commands (method per route) |",
|
|
54
55
|
"| `OPTIONS` | `*` | CORS preflight |",
|
|
55
56
|
"",
|
|
56
|
-
"
|
|
57
|
+
"Discover paths from `openapi.json` (`/api/...`). Query binds options; POST/PUT/PATCH body binds options and `inputSchema` fields.",
|
|
57
58
|
"",
|
|
58
59
|
"## Examples",
|
|
59
60
|
"",
|
|
60
61
|
"```bash",
|
|
61
62
|
`curl -s ${baseUrl}/health`,
|
|
63
|
+
`curl -s ${baseUrl}/health/ready`,
|
|
62
64
|
`curl -s ${baseUrl}/openapi.json`,
|
|
63
|
-
`curl -s
|
|
65
|
+
`curl -s ${baseUrl}/api/workspaces`,
|
|
66
|
+
`curl -s -X POST ${baseUrl}/api/workspaces \\`,
|
|
64
67
|
' -H "content-type: application/json" \\',
|
|
65
|
-
|
|
68
|
+
` -d '{"name":"qa2"}'`,
|
|
66
69
|
"```",
|
|
67
70
|
"",
|
|
68
71
|
"## Responses",
|
|
69
72
|
"",
|
|
70
|
-
"Success
|
|
73
|
+
"Success: status from handler → `http.successStatus` → method default (GET 200, POST 201, DELETE 204).",
|
|
71
74
|
"",
|
|
72
75
|
"Handlers must use `ctx.respond()` or return a value for API/MCP tool calls.",
|
|
73
76
|
"",
|
|
@@ -92,29 +95,29 @@ export function generateHttpGuide(root: CliProgram): string {
|
|
|
92
95
|
lines.push("");
|
|
93
96
|
}
|
|
94
97
|
|
|
95
|
-
lines.push("##
|
|
98
|
+
lines.push("## REST routes", "");
|
|
96
99
|
|
|
97
|
-
if (
|
|
98
|
-
lines.push("(No
|
|
100
|
+
if (routes.length === 0) {
|
|
101
|
+
lines.push("(No routes exposed.)", "");
|
|
99
102
|
} else {
|
|
100
|
-
for (const
|
|
101
|
-
lines.push(
|
|
103
|
+
for (const route of routes) {
|
|
104
|
+
lines.push(formatRouteLine(root, route));
|
|
102
105
|
}
|
|
103
106
|
lines.push("");
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
lines.push(
|
|
107
|
-
"##
|
|
110
|
+
"## Request bodies",
|
|
108
111
|
"",
|
|
109
|
-
"POST bodies are a flat JSON object keyed by long option and positional names (hyphenated option names are valid keys).",
|
|
112
|
+
"POST/PUT/PATCH bodies are a flat JSON object keyed by long option and positional names (hyphenated option names are valid keys).",
|
|
110
113
|
"",
|
|
111
|
-
`For HTTP clients, use **\`GET /openapi.json\`** (or **\`GET /openapi-browser\`**) for per-
|
|
114
|
+
`For HTTP clients, use **\`GET /openapi.json\`** (or **\`GET /openapi-browser\`**) for per-route request shapes.`,
|
|
112
115
|
"",
|
|
113
116
|
"Varargs positionals accept a JSON array of strings (not a comma-separated string).",
|
|
114
117
|
"Options with `format: comma-list` accept a comma-separated string or JSON array.",
|
|
115
118
|
"Options with a schema `default` are applied when omitted.",
|
|
116
119
|
"",
|
|
117
|
-
`Shell invocation reference: \`${root.key} docs
|
|
120
|
+
`Shell invocation reference: \`${root.key} docs cli\`. Full CLI tree JSON: \`${root.key} docs cli-schema\`.`,
|
|
118
121
|
"",
|
|
119
122
|
"## OpenAPI",
|
|
120
123
|
"",
|
|
@@ -124,7 +127,7 @@ export function generateHttpGuide(root: CliProgram): string {
|
|
|
124
127
|
`- **Fetch** — \`curl -s ${baseUrl}/openapi.json\``,
|
|
125
128
|
`- **Save offline** — \`${root.key} docs openapi --save\` → \`./docs/openapi.json\` (or \`just docgen\` in app repos)`,
|
|
126
129
|
"",
|
|
127
|
-
"Use the spec to discover
|
|
130
|
+
"Use the spec to discover REST paths and request/response shapes before calling `/api/...`.",
|
|
128
131
|
"",
|
|
129
132
|
);
|
|
130
133
|
|
package/src/docs/mcp-guide.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { defaultConfigEntryTitle } from "~/config/entry.ts";
|
|
2
|
+
import { displayAppConfigPath } from "~/config/file.ts";
|
|
3
|
+
import { expectedOpenCodeMcpEntry, OPENCODE_CONFIG_SCHEMA } from "~/configure/artifacts/mcp-opencode.ts";
|
|
4
|
+
import { collectOptionDefs } from "~/core/parse.ts";
|
|
5
|
+
import { CliOptionKind, type CliProgram } from "~/core/types.ts";
|
|
6
|
+
import { collectMcpTools, type McpToolDef, mcpServerId, resolveMcpSchemaUri } from "~/mcp/tools.ts";
|
|
7
|
+
import { resolveCapabilities } from "~/runtime/capabilities.ts";
|
|
8
8
|
import { resolveDocsTopicResourceUri } from "./mcp-resources.ts";
|
|
9
|
-
import { docsEnabled, docsUserTopicKeys } from "./resolve.ts";
|
|
9
|
+
import { docsEnabled, docsUserTopicKeys, resolveDocsConfig } from "./resolve.ts";
|
|
10
10
|
|
|
11
11
|
/** Extra host notes for generated `docs mcp` (manual fallbacks and ChatGPT Connectors). */
|
|
12
12
|
function appendManualHostSetup(lines: string[], root: CliProgram, serverId: string): void {
|
|
@@ -205,12 +205,10 @@ export function generateMcpGuide(root: CliProgram): string {
|
|
|
205
205
|
`| Schema resource | \`${schemaUri}\` — same JSON as \`${root.key} docs cli-schema\` |`,
|
|
206
206
|
);
|
|
207
207
|
if (docsEnabled(root)) {
|
|
208
|
-
const docs = root
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
lines.push(`| Docs topic \`${key}\` | \`${uri}\` — same markdown as \`${root.key} docs ${key}\` |`);
|
|
213
|
-
}
|
|
208
|
+
const docs = resolveDocsConfig(root);
|
|
209
|
+
for (const key of docsUserTopicKeys(docs)) {
|
|
210
|
+
const uri = resolveDocsTopicResourceUri(root, key);
|
|
211
|
+
lines.push(`| Docs topic \`${key}\` | \`${uri}\` — same markdown as \`${root.key} docs ${key}\` |`);
|
|
214
212
|
}
|
|
215
213
|
}
|
|
216
214
|
lines.push("", "## Exposed tools", "");
|