argsbarg 3.4.2 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -1
- package/README.md +24 -8
- package/biome.json +29 -6
- package/bun.lock +22 -0
- package/docs/cli-program.md +75 -1
- package/docs/install.md +1 -1
- package/docs/mcp.md +45 -1
- package/docs/templates/cursor/rules/cli-program.mdc +15 -21
- package/index.d.ts +95 -50
- package/justfile +24 -6
- package/package.json +4 -2
- package/scripts/release.ts +26 -9
- package/src/builtins/builtins.test.ts +9 -4
- package/src/builtins/completion-bash.ts +74 -50
- package/src/builtins/completion-fish.ts +3 -8
- package/src/builtins/completion-group.ts +1 -1
- package/src/builtins/completion-zsh.ts +80 -42
- package/src/builtins/dispatch.ts +20 -16
- package/src/builtins/export.ts +19 -10
- package/src/builtins/index.ts +9 -4
- package/src/builtins/install.ts +10 -10
- package/src/builtins/mcp.ts +1 -1
- package/src/builtins/presentation.ts +8 -8
- package/src/builtins/scopes.ts +1 -1
- package/src/builtins/version.ts +1 -1
- package/src/completion.ts +4 -4
- package/src/context.ts +91 -15
- package/src/docs/api-guide.test.ts +2 -2
- package/src/docs/api-guide.ts +19 -5
- package/src/docs/builtin.ts +27 -8
- package/src/docs/docs.test.ts +18 -11
- package/src/docs/mcp-guide.ts +108 -25
- package/src/docs/resolve.ts +10 -3
- package/src/docs/save.ts +11 -3
- package/src/formats.test.ts +35 -0
- package/src/formats.ts +135 -0
- package/src/headless.test.ts +8 -16
- package/src/help.ts +73 -43
- package/src/hidden-mcpb.test.ts +7 -6
- package/src/hidden.ts +2 -2
- package/src/index.test.ts +120 -96
- package/src/index.ts +36 -24
- package/src/install/binary.ts +12 -5
- package/src/install/completions.ts +7 -3
- package/src/install/detect-installed.ts +29 -4
- package/src/install/gh-release-update.ts +31 -23
- package/src/install/index.ts +69 -19
- package/src/install/install.test.ts +31 -8
- package/src/install/mcp-codex.test.ts +57 -0
- package/src/install/mcp-codex.ts +125 -0
- package/src/install/mcp-config.ts +12 -5
- package/src/install/mcp-opencode.test.ts +98 -0
- package/src/install/mcp-opencode.ts +149 -0
- package/src/install/paths.ts +29 -3
- package/src/install/plan.ts +73 -6
- package/src/install/shell.ts +1 -4
- package/src/install/status.ts +12 -6
- package/src/install/uninstall.ts +38 -4
- package/src/install/update.test.ts +2 -2
- package/src/install/update.ts +3 -1
- package/src/invoke.ts +12 -9
- package/src/mcp/bundle.ts +36 -8
- package/src/mcp/env.ts +7 -13
- package/src/mcp/server.ts +12 -6
- package/src/mcp/tools.ts +83 -18
- package/src/mcp.ts +3 -3
- package/src/parse.ts +129 -27
- package/src/runtime.ts +22 -12
- package/src/schema.ts +11 -5
- package/src/skill/generate.ts +4 -4
- package/src/skill/install.ts +6 -2
- package/src/types.ts +24 -0
- package/src/validate.ts +75 -16
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CliOptionKind, type CliRouter } from "../types.ts";
|
|
2
2
|
import { collectScopes, type ScopeRec } from "./scopes.ts";
|
|
3
3
|
import {
|
|
4
4
|
escShellSingleQuoted,
|
|
@@ -11,22 +11,41 @@ import {
|
|
|
11
11
|
function emitScopeArraysZsh(ident: string, scopes: ScopeRec[]): string {
|
|
12
12
|
let out = "";
|
|
13
13
|
for (const [i, sc] of scopes.entries()) {
|
|
14
|
-
out +=
|
|
15
|
-
out +=
|
|
16
|
-
out +=
|
|
14
|
+
out += `typeset -g A_${ident}_${i}_opts\n`;
|
|
15
|
+
out += `A_${ident}_${i}_opts=(`;
|
|
16
|
+
out +=
|
|
17
|
+
"'" +
|
|
18
|
+
escShellSingleQuoted(kHelpLong) +
|
|
19
|
+
":" +
|
|
20
|
+
escShellSingleQuoted("Show help for this command.") +
|
|
21
|
+
"' '" +
|
|
22
|
+
escShellSingleQuoted(kHelpShort) +
|
|
23
|
+
":" +
|
|
24
|
+
escShellSingleQuoted("Show help for this command.") +
|
|
25
|
+
"'";
|
|
17
26
|
for (const o of sc.opts) {
|
|
18
|
-
out +=
|
|
27
|
+
out +=
|
|
28
|
+
" '" +
|
|
29
|
+
escShellSingleQuoted(`--${o.name}`) +
|
|
30
|
+
":" +
|
|
31
|
+
escShellSingleQuoted(o.description) +
|
|
32
|
+
"'";
|
|
19
33
|
if (o.shortName) {
|
|
20
|
-
out +=
|
|
34
|
+
out +=
|
|
35
|
+
" '" +
|
|
36
|
+
escShellSingleQuoted(`-${o.shortName}`) +
|
|
37
|
+
":" +
|
|
38
|
+
escShellSingleQuoted(o.description) +
|
|
39
|
+
"'";
|
|
21
40
|
}
|
|
22
41
|
}
|
|
23
42
|
out += ")\n";
|
|
24
|
-
out +=
|
|
25
|
-
out +=
|
|
43
|
+
out += `typeset -g A_${ident}_${i}_leaf=${sc.kids.length === 0 ? "1" : "0"}\n`;
|
|
44
|
+
out += `typeset -g A_${ident}_${i}_pos=${sc.wantsFiles ? "1" : "0"}\n`;
|
|
26
45
|
if (sc.kids.length > 0) {
|
|
27
|
-
out +=
|
|
46
|
+
out += `typeset -g A_${ident}_${i}_cmds=(`;
|
|
28
47
|
for (const ch of sc.kids) {
|
|
29
|
-
out +=
|
|
48
|
+
out += ` '${escShellSingleQuoted(ch.key)}:${escShellSingleQuoted(ch.description)}'`;
|
|
30
49
|
}
|
|
31
50
|
out += ")\n";
|
|
32
51
|
}
|
|
@@ -36,19 +55,24 @@ function emitScopeArraysZsh(ident: string, scopes: ScopeRec[]): string {
|
|
|
36
55
|
|
|
37
56
|
function emitConsumeLongZsh(ident: string, scopes: ScopeRec[]): string {
|
|
38
57
|
let o = "_${ident}_nac_consume_long() {\n".replace("${ident}", ident);
|
|
39
|
-
o +=
|
|
58
|
+
o += ' local sid="$1" w="$2" nw="$3"\n';
|
|
40
59
|
o += " case $sid in\n";
|
|
41
60
|
for (const [i, sc] of scopes.entries()) {
|
|
42
|
-
o +=
|
|
61
|
+
o += ` ${i})\n`;
|
|
43
62
|
o += " case $w in\n";
|
|
44
|
-
o +=
|
|
63
|
+
o +=
|
|
64
|
+
" " +
|
|
65
|
+
kHelpLong +
|
|
66
|
+
"|${kHelpLong}=*|${kHelpShort}) echo 1 ;;\n"
|
|
67
|
+
.replace(/\$\{kHelpLong\}/g, kHelpLong)
|
|
68
|
+
.replace(/\$\{kHelpShort\}/g, kHelpShort);
|
|
45
69
|
for (const op of sc.opts) {
|
|
46
|
-
const base =
|
|
70
|
+
const base = `--${op.name}`;
|
|
47
71
|
if (op.kind === "presence") {
|
|
48
|
-
o +=
|
|
72
|
+
o += ` ${base}${"|${base}=*) echo 1 ;;\n".replace(/\$\{base\}/g, base)}`;
|
|
49
73
|
} else {
|
|
50
|
-
o +=
|
|
51
|
-
o +=
|
|
74
|
+
o += ` ${base}=*) echo 1 ;;\n`;
|
|
75
|
+
o += ` ${base}) echo 2 ;;\n`;
|
|
52
76
|
}
|
|
53
77
|
}
|
|
54
78
|
o += " *) echo 0 ;;\n";
|
|
@@ -63,10 +87,10 @@ function emitConsumeLongZsh(ident: string, scopes: ScopeRec[]): string {
|
|
|
63
87
|
|
|
64
88
|
function emitConsumeShortZsh(ident: string, scopes: ScopeRec[]): string {
|
|
65
89
|
let o = "_${ident}_nac_consume_short() {\n".replace("${ident}", ident);
|
|
66
|
-
o +=
|
|
90
|
+
o += ' local sid="$1" w="$2"\n';
|
|
67
91
|
o += " case $sid in\n";
|
|
68
92
|
for (const [i, sc] of scopes.entries()) {
|
|
69
|
-
o +=
|
|
93
|
+
o += ` ${i})\n`;
|
|
70
94
|
o += " local rest=${w#-}\n";
|
|
71
95
|
o += " local ch\n";
|
|
72
96
|
o += " local saw=0\n";
|
|
@@ -78,16 +102,16 @@ function emitConsumeShortZsh(ident: string, scopes: ScopeRec[]): string {
|
|
|
78
102
|
for (const op of sc.opts) {
|
|
79
103
|
if (!op.shortName) continue;
|
|
80
104
|
if (op.kind === "presence") {
|
|
81
|
-
boolChars += op.shortName
|
|
105
|
+
boolChars += `${op.shortName}|`;
|
|
82
106
|
} else {
|
|
83
|
-
o +=
|
|
107
|
+
o += ` ${op.shortName})\n`;
|
|
84
108
|
o += " if [[ $saw -ne 0 || -n $rest ]]; then echo 0; return; fi\n";
|
|
85
109
|
o += " echo 2; return ;;\n";
|
|
86
110
|
}
|
|
87
111
|
}
|
|
88
112
|
if (boolChars.length > 0) {
|
|
89
113
|
boolChars = boolChars.slice(0, -1);
|
|
90
|
-
o +=
|
|
114
|
+
o += ` ${boolChars}) ;;\n`;
|
|
91
115
|
}
|
|
92
116
|
o += " *) echo 0; return ;;\n";
|
|
93
117
|
o += " esac\n";
|
|
@@ -102,18 +126,22 @@ function emitConsumeShortZsh(ident: string, scopes: ScopeRec[]): string {
|
|
|
102
126
|
return o;
|
|
103
127
|
}
|
|
104
128
|
|
|
105
|
-
function emitMatchChildZsh(
|
|
129
|
+
function emitMatchChildZsh(
|
|
130
|
+
ident: string,
|
|
131
|
+
scopes: ScopeRec[],
|
|
132
|
+
pathIndex: Record<string, number>,
|
|
133
|
+
): string {
|
|
106
134
|
let o = "_${ident}_nac_match_child() {\n".replace("${ident}", ident);
|
|
107
|
-
o +=
|
|
135
|
+
o += ' local sid="$1" w="$2"\n';
|
|
108
136
|
o += " case $sid in\n";
|
|
109
137
|
for (const [sid, sc] of scopes.entries()) {
|
|
110
138
|
if (sc.kids.length === 0) continue;
|
|
111
|
-
o +=
|
|
139
|
+
o += ` ${sid})\n`;
|
|
112
140
|
o += " case $w in\n";
|
|
113
141
|
for (const ch of sc.kids) {
|
|
114
|
-
const childPath = sc.path === "" ? ch.key : sc.path
|
|
142
|
+
const childPath = sc.path === "" ? ch.key : `${sc.path}/${ch.key}`;
|
|
115
143
|
const cid = pathIndex[childPath] ?? 0;
|
|
116
|
-
o +=
|
|
144
|
+
o += ` ${ch.key}) echo ${cid}; return 0 ;;\n`;
|
|
117
145
|
}
|
|
118
146
|
o += " esac\n";
|
|
119
147
|
o += " ;;\n";
|
|
@@ -129,11 +157,14 @@ function emitSimulateZsh(ident: string): string {
|
|
|
129
157
|
o += " local i=2 sid=0 w steps next\n";
|
|
130
158
|
o += " while (( i < CURRENT )); do\n";
|
|
131
159
|
o += " w=$words[i]\n";
|
|
132
|
-
o +=
|
|
160
|
+
o += ` if [[ $w == ${kHelpShort} || $w == ${kHelpLong} ]]; then\n`;
|
|
133
161
|
o += " ((i++)); continue\n";
|
|
134
162
|
o += " fi\n";
|
|
135
163
|
o += " if [[ $w == --* ]]; then\n";
|
|
136
|
-
o +=
|
|
164
|
+
o += ' steps=$(_${ident}_nac_consume_long "$sid" "$w" "${words[i+1]}")\n'.replace(
|
|
165
|
+
"${ident}",
|
|
166
|
+
ident,
|
|
167
|
+
);
|
|
137
168
|
o += " case $steps in\n";
|
|
138
169
|
o += " 0) break ;;\n";
|
|
139
170
|
o += " 1) ((i++)) ;;\n";
|
|
@@ -143,7 +174,7 @@ function emitSimulateZsh(ident: string): string {
|
|
|
143
174
|
o += " continue\n";
|
|
144
175
|
o += " fi\n";
|
|
145
176
|
o += " if [[ $w == -* ]]; then\n";
|
|
146
|
-
o +=
|
|
177
|
+
o += ' steps=$(_${ident}_nac_consume_short "$sid" "$w")\n'.replace("${ident}", ident);
|
|
147
178
|
o += " case $steps in\n";
|
|
148
179
|
o += " 0) break ;;\n";
|
|
149
180
|
o += " 1) ((i++)) ;;\n";
|
|
@@ -152,7 +183,7 @@ function emitSimulateZsh(ident: string): string {
|
|
|
152
183
|
o += " esac\n";
|
|
153
184
|
o += " continue\n";
|
|
154
185
|
o += " fi\n";
|
|
155
|
-
o +=
|
|
186
|
+
o += ' next=$(_${ident}_nac_match_child "$sid" "$w") || break\n'.replace("${ident}", ident);
|
|
156
187
|
o += " sid=$next\n";
|
|
157
188
|
o += " ((i++))\n";
|
|
158
189
|
o += " done\n";
|
|
@@ -166,13 +197,15 @@ function emitEnumReplyZsh(ident: string, scopes: ScopeRec[]): string {
|
|
|
166
197
|
o += " local sid=$1 prev=$2\n";
|
|
167
198
|
o += " case $sid in\n";
|
|
168
199
|
for (const [i, sc] of scopes.entries()) {
|
|
169
|
-
const enumOpts = sc.opts.filter(
|
|
200
|
+
const enumOpts = sc.opts.filter(
|
|
201
|
+
(op) => op.kind === CliOptionKind.Enum && (op.choices?.length ?? 0) > 0,
|
|
202
|
+
);
|
|
170
203
|
if (enumOpts.length === 0) continue;
|
|
171
|
-
o +=
|
|
204
|
+
o += ` ${i})\n`;
|
|
172
205
|
o += " case $prev in\n";
|
|
173
206
|
for (const op of enumOpts) {
|
|
174
207
|
const vals = (op.choices ?? []).map((c) => escShellSingleQuoted(c)).join(" ");
|
|
175
|
-
o +=
|
|
208
|
+
o += ` --${op.name}) _values ${vals}; return 0 ;;\n`;
|
|
176
209
|
}
|
|
177
210
|
o += " esac\n";
|
|
178
211
|
o += " ;;\n";
|
|
@@ -186,24 +219,27 @@ function emitEnumReplyZsh(ident: string, scopes: ScopeRec[]): string {
|
|
|
186
219
|
function emitMainBodyZsh(schema: CliRouter, ident: string): string {
|
|
187
220
|
const main = mainName(schema.key);
|
|
188
221
|
let o = "_${main}() {\n".replace("${main}", main);
|
|
189
|
-
o +=
|
|
222
|
+
o += ' local curcontext="$curcontext" ret=1\n';
|
|
190
223
|
o += " _${ident}_nac_simulate\n".replace("${ident}", ident);
|
|
191
224
|
o += " local sid=$REPLY_SID\n";
|
|
192
|
-
o +=
|
|
225
|
+
o += ' if _${ident}_nac_enum_reply "$sid" "$words[CURRENT-1]"; then return 0; fi\n'.replace(
|
|
226
|
+
"${ident}",
|
|
227
|
+
ident,
|
|
228
|
+
);
|
|
193
229
|
o += " if [[ $PREFIX == -* ]]; then\n";
|
|
194
230
|
o += " local -a optsarr\n";
|
|
195
|
-
o +=
|
|
231
|
+
o += ' local oname="A_${ident}_${sid}_opts"\n'.replace("${ident}", ident);
|
|
196
232
|
o += " optsarr=(${(@P)oname})\n";
|
|
197
233
|
o += " _describe -t options 'option' optsarr && ret=0\n";
|
|
198
234
|
o += " else\n";
|
|
199
|
-
o +=
|
|
235
|
+
o += ' local lname="A_${ident}_${sid}_leaf"\n'.replace("${ident}", ident);
|
|
200
236
|
o += " if [[ ${(P)lname} -eq 0 ]]; then\n";
|
|
201
237
|
o += " local -a cmdsarr\n";
|
|
202
|
-
o +=
|
|
238
|
+
o += ' local cname="A_${ident}_${sid}_cmds"\n'.replace("${ident}", ident);
|
|
203
239
|
o += " cmdsarr=(${(@P)cname})\n";
|
|
204
240
|
o += " _describe -t commands 'command' cmdsarr && ret=0\n";
|
|
205
241
|
o += " else\n";
|
|
206
|
-
o +=
|
|
242
|
+
o += ' local pname="A_${ident}_${sid}_pos"\n'.replace("${ident}", ident);
|
|
207
243
|
o += " if [[ ${(P)pname} -eq 1 ]]; then\n";
|
|
208
244
|
o += " _files && ret=0\n";
|
|
209
245
|
o += " fi\n";
|
|
@@ -211,7 +247,9 @@ function emitMainBodyZsh(schema: CliRouter, ident: string): string {
|
|
|
211
247
|
o += " fi\n";
|
|
212
248
|
o += " return ret\n";
|
|
213
249
|
o += "}\n\n";
|
|
214
|
-
o += "compdef _${main} ${schema.key}\n"
|
|
250
|
+
o += "compdef _${main} ${schema.key}\n"
|
|
251
|
+
.replace("${main}", main)
|
|
252
|
+
.replace("${schema.key}", schema.key);
|
|
215
253
|
return o;
|
|
216
254
|
}
|
|
217
255
|
|
|
@@ -224,7 +262,7 @@ export function completionZshScript(schema: CliRouter): string {
|
|
|
224
262
|
pathIndex[s.path] = i;
|
|
225
263
|
}
|
|
226
264
|
|
|
227
|
-
let out =
|
|
265
|
+
let out = `#compdef ${schema.key}\n\n`;
|
|
228
266
|
out += emitScopeArraysZsh(ident, scopes);
|
|
229
267
|
out += emitConsumeLongZsh(ident, scopes);
|
|
230
268
|
out += emitConsumeShortZsh(ident, scopes);
|
package/src/builtins/dispatch.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { resolveCapabilities } from "../capabilities.ts";
|
|
2
|
+
import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
|
|
3
|
+
import { cliInstall } from "../install/index.ts";
|
|
4
|
+
import { runMcpBundle } from "../mcp/bundle.ts";
|
|
5
|
+
import { cliMcpServeStdio } from "../mcp.ts";
|
|
6
|
+
import type { ParseResult } from "../parse.ts";
|
|
7
|
+
import { ParseKind } from "../parse.ts";
|
|
2
8
|
import type { CliNode, CliProgram, CliRouter } from "../types.ts";
|
|
3
|
-
import { isCliLeaf
|
|
9
|
+
import { isCliLeaf } from "../types.ts";
|
|
4
10
|
import { completionBashScript } from "./completion-bash.ts";
|
|
5
11
|
import { completionFishScript } from "./completion-fish.ts";
|
|
12
|
+
import { cliBuiltinCompletionGroup as completionGroup } from "./completion-group.ts";
|
|
6
13
|
import { completionZshScript } from "./completion-zsh.ts";
|
|
7
14
|
import { cliBuiltinInstallCommand } from "./install.ts";
|
|
8
15
|
import { cliBuiltinMcpCommand } from "./mcp.ts";
|
|
9
|
-
import { cliBuiltinVersionCommand } from "./version.ts";
|
|
10
|
-
import { cliBuiltinCompletionGroup as completionGroup } from "./completion-group.ts";
|
|
11
16
|
import { cliPresentationRoot } from "./presentation.ts";
|
|
12
|
-
import {
|
|
13
|
-
import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
|
|
14
|
-
import { cliMcpServeStdio } from "../mcp.ts";
|
|
15
|
-
import { cliInstall } from "../install/index.ts";
|
|
16
|
-
import type { ParseResult } from "../parse.ts";
|
|
17
|
-
import { ParseKind } from "../parse.ts";
|
|
17
|
+
import { cliBuiltinVersionCommand } from "./version.ts";
|
|
18
18
|
|
|
19
19
|
export interface DispatchBuiltinOpts {
|
|
20
20
|
isLeafCompletionIntercept: boolean;
|
|
@@ -61,16 +61,18 @@ export async function dispatchBuiltin(
|
|
|
61
61
|
|
|
62
62
|
if (pr.path[0] === "version") {
|
|
63
63
|
if (pr.path.length !== 1) {
|
|
64
|
-
process.stderr.write(
|
|
64
|
+
process.stderr.write(`Unknown subcommand: version ${pr.path.slice(1).join(" ")}\n`);
|
|
65
65
|
process.exit(1);
|
|
66
66
|
}
|
|
67
|
-
process.stdout.write(program.version
|
|
67
|
+
process.stdout.write(`${program.version}\n`);
|
|
68
68
|
process.exit(0);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
if (pr.path[0] === "mcp") {
|
|
72
72
|
if (!caps.mcp) {
|
|
73
|
-
process.stderr.write(
|
|
73
|
+
process.stderr.write(
|
|
74
|
+
"MCP is not enabled. Set mcpServer: { enabled: true } on the program root.\n",
|
|
75
|
+
);
|
|
74
76
|
process.exit(1);
|
|
75
77
|
}
|
|
76
78
|
const sub = pr.path[1];
|
|
@@ -82,22 +84,24 @@ export async function dispatchBuiltin(
|
|
|
82
84
|
try {
|
|
83
85
|
runMcpBundle(program);
|
|
84
86
|
} catch (err) {
|
|
85
|
-
process.stderr.write(err instanceof Error ? err.message
|
|
87
|
+
process.stderr.write(err instanceof Error ? `${err.message}\n` : "mcp bundle failed.\n");
|
|
86
88
|
process.exit(1);
|
|
87
89
|
}
|
|
88
90
|
process.exit(0);
|
|
89
91
|
}
|
|
90
|
-
process.stderr.write(
|
|
92
|
+
process.stderr.write(`Unknown subcommand: mcp ${pr.path.slice(1).join(" ")}\n`);
|
|
91
93
|
process.exit(1);
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
if (pr.path[0] === "install") {
|
|
95
97
|
if (!caps.install) {
|
|
96
|
-
process.stderr.write(
|
|
98
|
+
process.stderr.write(
|
|
99
|
+
"install is disabled. Remove install.enabled: false from the program root.\n",
|
|
100
|
+
);
|
|
97
101
|
process.exit(1);
|
|
98
102
|
}
|
|
99
103
|
if (pr.path.length !== 1) {
|
|
100
|
-
process.stderr.write(
|
|
104
|
+
process.stderr.write(`Unknown subcommand: install ${pr.path.slice(1).join(" ")}\n`);
|
|
101
105
|
process.exit(1);
|
|
102
106
|
}
|
|
103
107
|
await cliInstall(program, pr.opts);
|
package/src/builtins/export.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type CliCapabilities, resolveCapabilities } from "../capabilities.ts";
|
|
2
|
+
import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
|
|
3
|
+
import { visibleOptions } from "../hidden.ts";
|
|
2
4
|
import type { CliFallbackMode, CliNode, CliOption, CliPositional, CliProgram } from "../types.ts";
|
|
3
5
|
import { isCliRouter } from "../types.ts";
|
|
4
|
-
import { visibleOptions } from "../hidden.ts";
|
|
5
6
|
import { cliBuiltinCompletionGroup } from "./completion-group.ts";
|
|
6
7
|
import { cliBuiltinInstallCommand } from "./install.ts";
|
|
7
8
|
import { cliBuiltinMcpCommand } from "./mcp.ts";
|
|
8
9
|
import { cliBuiltinVersionCommand } from "./version.ts";
|
|
9
|
-
import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
|
|
10
10
|
|
|
11
11
|
/** JSON-safe command node (no handlers). */
|
|
12
12
|
export interface CliSchemaExport {
|
|
@@ -55,22 +55,31 @@ function exportBuiltinNode(cmd: CliNode): CliSchemaExport | null {
|
|
|
55
55
|
return out;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
function pushExportedBuiltin(builtins: CliSchemaExport[], cmd: CliNode): void {
|
|
59
|
+
const node = exportBuiltinNode(cmd);
|
|
60
|
+
if (node) {
|
|
61
|
+
builtins.push(node);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
58
65
|
/** Built-in subtrees matching help visibility for `--schema` export. */
|
|
59
|
-
export function exportPresentationBuiltins(
|
|
66
|
+
export function exportPresentationBuiltins(
|
|
67
|
+
program: CliProgram,
|
|
68
|
+
caps?: CliCapabilities,
|
|
69
|
+
): CliSchemaExport[] {
|
|
60
70
|
const resolved = caps ?? resolveCapabilities(program);
|
|
61
|
-
const builtins: CliSchemaExport[] = [
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
];
|
|
71
|
+
const builtins: CliSchemaExport[] = [];
|
|
72
|
+
pushExportedBuiltin(builtins, cliBuiltinCompletionGroup(program));
|
|
73
|
+
pushExportedBuiltin(builtins, cliBuiltinVersionCommand());
|
|
65
74
|
if (resolved.install) {
|
|
66
|
-
builtins
|
|
75
|
+
pushExportedBuiltin(builtins, cliBuiltinInstallCommand(program));
|
|
67
76
|
}
|
|
68
77
|
const docsGroup = cliBuiltinDocsGroupIfEnabled(program);
|
|
69
78
|
if (docsGroup) {
|
|
70
|
-
builtins
|
|
79
|
+
pushExportedBuiltin(builtins, docsGroup);
|
|
71
80
|
}
|
|
72
81
|
if (resolved.mcp) {
|
|
73
|
-
builtins
|
|
82
|
+
pushExportedBuiltin(builtins, cliBuiltinMcpCommand(program));
|
|
74
83
|
}
|
|
75
84
|
return builtins;
|
|
76
85
|
}
|
package/src/builtins/index.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
export { completionBashScript } from "./completion-bash.ts";
|
|
2
|
-
export { completionZshScript } from "./completion-zsh.ts";
|
|
3
2
|
export { completionFishScript } from "./completion-fish.ts";
|
|
4
3
|
export { cliBuiltinCompletionGroup } from "./completion-group.ts";
|
|
4
|
+
export { completionZshScript } from "./completion-zsh.ts";
|
|
5
|
+
export { builtinInterceptRoot, dispatchBuiltin } from "./dispatch.ts";
|
|
6
|
+
export { type CliSchemaExport, exportPresentationBuiltins } from "./export.ts";
|
|
5
7
|
export { cliBuiltinInstallCommand, installBuiltinOptions } from "./install.ts";
|
|
6
8
|
export { cliBuiltinMcpCommand } from "./mcp.ts";
|
|
7
|
-
export {
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
export {
|
|
10
|
+
cliParseRoot,
|
|
11
|
+
cliPresentationRoot,
|
|
12
|
+
parseBuiltins,
|
|
13
|
+
presentationBuiltins,
|
|
14
|
+
} from "./presentation.ts";
|
|
10
15
|
export { collectScopes, type ScopeRec } from "./scopes.ts";
|
package/src/builtins/install.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveCapabilities } from "../capabilities.ts";
|
|
2
|
-
import {
|
|
2
|
+
import { type CliLeaf, type CliOption, CliOptionKind, type CliProgram } from "../types.ts";
|
|
3
3
|
|
|
4
4
|
/** Install command options (dynamic: `--mcp` only when MCP is enabled). */
|
|
5
5
|
export function installBuiltinOptions(root: CliProgram): CliOption[] {
|
|
@@ -42,12 +42,14 @@ export function installBuiltinOptions(root: CliProgram): CliOption[] {
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
name: "uninstall",
|
|
45
|
-
description:
|
|
45
|
+
description:
|
|
46
|
+
"Remove installed artifacts (use --all or scoped flags; skips targets not on disk).",
|
|
46
47
|
kind: CliOptionKind.Presence,
|
|
47
48
|
},
|
|
48
49
|
{
|
|
49
50
|
name: "prefix",
|
|
50
|
-
description:
|
|
51
|
+
description:
|
|
52
|
+
"Install directory for the binary (default ~/.local/bin; overrides INSTALL_PREFIX).",
|
|
51
53
|
kind: CliOptionKind.String,
|
|
52
54
|
},
|
|
53
55
|
{
|
|
@@ -67,7 +69,8 @@ export function installBuiltinOptions(root: CliProgram): CliOption[] {
|
|
|
67
69
|
},
|
|
68
70
|
{
|
|
69
71
|
name: "quiet",
|
|
70
|
-
description:
|
|
72
|
+
description:
|
|
73
|
+
"Suppress informational output (requires --yes, --json, --reinstall, or --update).",
|
|
71
74
|
kind: CliOptionKind.Presence,
|
|
72
75
|
},
|
|
73
76
|
];
|
|
@@ -103,11 +106,7 @@ export function cliBuiltinInstallCommand(root: CliProgram): CliLeaf {
|
|
|
103
106
|
` ${app} install --reinstall`,
|
|
104
107
|
];
|
|
105
108
|
if (resolveCapabilities(root).update) {
|
|
106
|
-
notesLines.push(
|
|
107
|
-
"",
|
|
108
|
-
"Upgrade to latest release:",
|
|
109
|
-
` ${app} install --update`,
|
|
110
|
-
);
|
|
109
|
+
notesLines.push("", "Upgrade to latest release:", ` ${app} install --update`);
|
|
111
110
|
}
|
|
112
111
|
notesLines.push(
|
|
113
112
|
"",
|
|
@@ -122,7 +121,8 @@ export function cliBuiltinInstallCommand(root: CliProgram): CliLeaf {
|
|
|
122
121
|
);
|
|
123
122
|
return {
|
|
124
123
|
key: "install",
|
|
125
|
-
description:
|
|
124
|
+
description:
|
|
125
|
+
"Install the binary, shell completions, agent skills, and MCP config to your user environment.",
|
|
126
126
|
notes: notesLines.join("\n"),
|
|
127
127
|
options: installBuiltinOptions(root),
|
|
128
128
|
handler: () => {},
|
package/src/builtins/mcp.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveCapabilities } from "../capabilities.ts";
|
|
2
2
|
import { docsEnabled } from "../docs/resolve.ts";
|
|
3
|
-
import { type CliLeaf, type CliProgram, type CliRouter
|
|
3
|
+
import { CliFallbackMode, type CliLeaf, type CliProgram, type CliRouter } from "../types.ts";
|
|
4
4
|
|
|
5
5
|
/** Built-in `mcp` router: bare `myapp mcp` runs stdio (via hidden `serve` fallback); `mcp bundle` packs `.mcpb`. */
|
|
6
6
|
export function cliBuiltinMcpCommand(program: CliProgram): CliRouter {
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import type { CliCapabilities } from "../capabilities.ts";
|
|
2
2
|
import { resolveCapabilities } from "../capabilities.ts";
|
|
3
|
+
import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
|
|
3
4
|
import { presentationNode, visibleOptions } from "../hidden.ts";
|
|
4
5
|
import type { CliLeaf, CliNode, CliProgram, CliRouter } from "../types.ts";
|
|
5
|
-
import { isCliLeaf
|
|
6
|
+
import { isCliLeaf } from "../types.ts";
|
|
6
7
|
import { cliBuiltinCompletionGroup } from "./completion-group.ts";
|
|
7
8
|
import { cliBuiltinInstallCommand } from "./install.ts";
|
|
8
9
|
import { cliBuiltinMcpCommand } from "./mcp.ts";
|
|
9
10
|
import { cliBuiltinVersionCommand } from "./version.ts";
|
|
10
|
-
import { cliBuiltinDocsGroupIfEnabled } from "../docs/builtin.ts";
|
|
11
11
|
|
|
12
12
|
/** All built-in command nodes for argv parsing (includes hidden builtins). */
|
|
13
13
|
export function parseBuiltins(program: CliProgram, caps: CliCapabilities): CliNode[] {
|
|
14
|
-
const builtins: CliNode[] = [
|
|
15
|
-
cliBuiltinCompletionGroup(program),
|
|
16
|
-
cliBuiltinVersionCommand(),
|
|
17
|
-
];
|
|
14
|
+
const builtins: CliNode[] = [cliBuiltinCompletionGroup(program), cliBuiltinVersionCommand()];
|
|
18
15
|
if (caps.install) {
|
|
19
16
|
builtins.push(cliBuiltinInstallCommand(program));
|
|
20
17
|
}
|
|
@@ -98,10 +95,13 @@ export function cliPresentationRoot(program: CliProgram): CliRouter {
|
|
|
98
95
|
}
|
|
99
96
|
|
|
100
97
|
/** Root help notes: consumer `program.notes` plus agent discovery when `docs` is enabled. */
|
|
101
|
-
export function presentationRootNotes(
|
|
98
|
+
export function presentationRootNotes(
|
|
99
|
+
program: CliProgram,
|
|
100
|
+
caps: CliCapabilities,
|
|
101
|
+
): string | undefined {
|
|
102
102
|
const parts: string[] = [];
|
|
103
103
|
if ((program.notes ?? "").trim().length > 0) {
|
|
104
|
-
parts.push(program.notes
|
|
104
|
+
parts.push((program.notes ?? "").trim());
|
|
105
105
|
}
|
|
106
106
|
if (caps.docs) {
|
|
107
107
|
parts.push(`For AI agents: \`${program.key} docs skill\`.`);
|
package/src/builtins/scopes.ts
CHANGED
|
@@ -25,7 +25,7 @@ function walkScopes(cmdPath: string, cmd: CliNode, acc: ScopeRec[]): void {
|
|
|
25
25
|
wantsFiles: hasPositionalArguments(cmd),
|
|
26
26
|
});
|
|
27
27
|
for (const ch of kids) {
|
|
28
|
-
const nextPath = cmdPath === "" ? ch.key : cmdPath
|
|
28
|
+
const nextPath = cmdPath === "" ? ch.key : `${cmdPath}/${ch.key}`;
|
|
29
29
|
walkScopes(nextPath, ch, acc);
|
|
30
30
|
}
|
|
31
31
|
}
|
package/src/builtins/version.ts
CHANGED
package/src/completion.ts
CHANGED
|
@@ -3,11 +3,11 @@ Re-export shim — completion emitters and built-in trees live in ./builtins/.
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
export {
|
|
6
|
-
completionBashScript,
|
|
7
|
-
completionZshScript,
|
|
8
|
-
completionFishScript,
|
|
9
|
-
cliPresentationRoot,
|
|
10
6
|
cliBuiltinCompletionGroup,
|
|
11
7
|
cliBuiltinInstallCommand,
|
|
12
8
|
cliBuiltinMcpCommand,
|
|
9
|
+
cliPresentationRoot,
|
|
10
|
+
completionBashScript,
|
|
11
|
+
completionFishScript,
|
|
12
|
+
completionZshScript,
|
|
13
13
|
} from "./builtins/index.ts";
|