unicommand 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +609 -0
- package/dist/index.js +1671 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1671 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { z as z4 } from "zod";
|
|
3
|
+
|
|
4
|
+
// src/command/runtime-metadata.ts
|
|
5
|
+
var commandMetadata = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
var setCommandMetadata = (command, metadata) => {
|
|
7
|
+
commandMetadata.set(command, metadata);
|
|
8
|
+
};
|
|
9
|
+
var getCommandMetadata = (command) => commandMetadata.get(command);
|
|
10
|
+
|
|
11
|
+
// src/cli/completion.ts
|
|
12
|
+
var CompletionShell = /* @__PURE__ */ ((CompletionShell2) => {
|
|
13
|
+
CompletionShell2["Bash"] = "bash";
|
|
14
|
+
CompletionShell2["Fish"] = "fish";
|
|
15
|
+
CompletionShell2["Zsh"] = "zsh";
|
|
16
|
+
return CompletionShell2;
|
|
17
|
+
})(CompletionShell || {});
|
|
18
|
+
var COMPLETION_COMMAND_NAME = "completion";
|
|
19
|
+
var COMPLETION_COMMAND_DESCRIPTION = "Generate shell completion scripts";
|
|
20
|
+
var COMPLETION_SHELL_ARGUMENT = "[shell]";
|
|
21
|
+
var COMPLETION_SHELL_DESCRIPTION = "Shell to generate completion for";
|
|
22
|
+
var EMPTY_DISPLAY_VALUE = "<empty>";
|
|
23
|
+
var completionShells = Object.values(CompletionShell);
|
|
24
|
+
var completionScriptGenerators = {
|
|
25
|
+
["bash" /* Bash */]: getBashCompletionScript,
|
|
26
|
+
["fish" /* Fish */]: getFishCompletionScript,
|
|
27
|
+
["zsh" /* Zsh */]: getZshCompletionScript
|
|
28
|
+
};
|
|
29
|
+
var registerCompletionCommand = (program, config = {}) => {
|
|
30
|
+
program.command(COMPLETION_COMMAND_NAME, COMPLETION_COMMAND_DESCRIPTION).argument(COMPLETION_SHELL_ARGUMENT, COMPLETION_SHELL_DESCRIPTION).strict(false).action(async ({ args, program: program2 }) => {
|
|
31
|
+
const shell = args.shell ? String(args.shell) : "";
|
|
32
|
+
if (isCompletionShell(shell)) {
|
|
33
|
+
console.log(await getCompletionScript(program2, shell, config));
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
console.log(`error: unsupported shell '${shell || EMPTY_DISPLAY_VALUE}'`);
|
|
37
|
+
console.log(`supported: ${completionShells.join(", ")}`);
|
|
38
|
+
return 1;
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
var isCompletionShell = (value) => {
|
|
42
|
+
return completionShells.includes(value);
|
|
43
|
+
};
|
|
44
|
+
var getCompletionScript = async (program, shell, config) => {
|
|
45
|
+
const binName = program.getBin();
|
|
46
|
+
const binNames = uniqueBinNames([binName, ...config.binNames ?? []]);
|
|
47
|
+
const commands = sortCommands(
|
|
48
|
+
(await program.getAllCommands()).filter(
|
|
49
|
+
(command) => command.visible && command.name !== COMPLETION_COMMAND_NAME
|
|
50
|
+
)
|
|
51
|
+
);
|
|
52
|
+
const roots = getRootCommands(commands);
|
|
53
|
+
const subcommands = getSubcommandGroups(commands);
|
|
54
|
+
const options = getCommandOptions(commands);
|
|
55
|
+
return completionScriptGenerators[shell](binNames, roots, subcommands, options, commands);
|
|
56
|
+
};
|
|
57
|
+
function getZshCompletionScript(binNames, roots, subcommands, options, commands) {
|
|
58
|
+
return binNames.map((binName) => formatZshCompletionScript(binName, roots, subcommands, options, commands)).join("\n\n");
|
|
59
|
+
}
|
|
60
|
+
function getBashCompletionScript(binNames, roots, subcommands, options, commands) {
|
|
61
|
+
return binNames.map((binName) => formatBashCompletionScript(binName, roots, subcommands, options, commands)).join("\n\n");
|
|
62
|
+
}
|
|
63
|
+
function formatZshCompletionScript(binName, roots, subcommands, options, commands) {
|
|
64
|
+
const functionName = completionFunctionName(binName);
|
|
65
|
+
return `#compdef ${binName}
|
|
66
|
+
|
|
67
|
+
_${functionName}() {
|
|
68
|
+
local -a commands
|
|
69
|
+
commands=(
|
|
70
|
+
${formatZshItems(roots)}
|
|
71
|
+
)
|
|
72
|
+
${formatSubcommandArrays(subcommands)}
|
|
73
|
+
${formatOptionArrays(options)}
|
|
74
|
+
${formatZshCustomCompletions(binName, commands)}
|
|
75
|
+
|
|
76
|
+
if [[ "$words[$CURRENT]" == -* ]]; then
|
|
77
|
+
local command_key="$words[2]"
|
|
78
|
+
if [[ -n "$words[3]" && "$words[3]" != -* ]]; then
|
|
79
|
+
command_key="$command_key $words[3]"
|
|
80
|
+
fi
|
|
81
|
+
case "$command_key" in
|
|
82
|
+
${formatOptionCases(binName, options)}
|
|
83
|
+
esac
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
_arguments -C \\
|
|
87
|
+
'1:command:->command' \\
|
|
88
|
+
'2:subcommand:->subcommand'
|
|
89
|
+
|
|
90
|
+
case $state in
|
|
91
|
+
command)
|
|
92
|
+
_describe '${binName} commands' commands
|
|
93
|
+
;;
|
|
94
|
+
subcommand)
|
|
95
|
+
case $words[2] in
|
|
96
|
+
${formatZshCustomCases(binName, commands)}
|
|
97
|
+
${formatSubcommandCases(binName, subcommands)}
|
|
98
|
+
esac
|
|
99
|
+
;;
|
|
100
|
+
esac
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
compdef _${functionName} ${binName}`;
|
|
104
|
+
}
|
|
105
|
+
function formatBashCompletionScript(binName, roots, subcommands, options, commands) {
|
|
106
|
+
const functionName = `${completionFunctionName(binName)}_completion`;
|
|
107
|
+
return `_${functionName}() {
|
|
108
|
+
local cur command_key
|
|
109
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
110
|
+
command_key="\${COMP_WORDS[1]}"
|
|
111
|
+
if [[ -n "\${COMP_WORDS[2]}" && "\${COMP_WORDS[2]}" != -* ]]; then
|
|
112
|
+
command_key="\${command_key} \${COMP_WORDS[2]}"
|
|
113
|
+
fi
|
|
114
|
+
COMPREPLY=()
|
|
115
|
+
|
|
116
|
+
if [[ "$cur" == -* ]]; then
|
|
117
|
+
case "$command_key" in
|
|
118
|
+
${formatBashOptionCases(options)}
|
|
119
|
+
esac
|
|
120
|
+
return 0
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
case "$COMP_CWORD" in
|
|
124
|
+
1)
|
|
125
|
+
COMPREPLY=($(compgen -W "${roots.map((item) => item.name).join(" ")}" -- "$cur"))
|
|
126
|
+
;;
|
|
127
|
+
2)
|
|
128
|
+
case "\${COMP_WORDS[1]}" in
|
|
129
|
+
${formatBashCustomCases(binName, commands)}
|
|
130
|
+
${formatBashSubcommandCases(subcommands)}
|
|
131
|
+
esac
|
|
132
|
+
;;
|
|
133
|
+
esac
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
complete -F _${functionName} ${binName}`;
|
|
137
|
+
}
|
|
138
|
+
function getFishCompletionScript(binNames, roots, subcommands, options, commands) {
|
|
139
|
+
const rootNames = roots.map((item) => item.name).join(" ");
|
|
140
|
+
return `${binNames.map((name) => formatFishFunctions(name, rootNames)).join("\n")}
|
|
141
|
+
${binNames.map((name) => formatFishCustomFunctions(name, commands)).join("\n")}
|
|
142
|
+
${binNames.map((name) => `complete -c ${name} -f`).join("\n")}
|
|
143
|
+
${binNames.map((name) => formatFishRootCompletions(name, roots)).join("\n")}
|
|
144
|
+
${binNames.map((name) => formatFishSubcommandCompletions(name, subcommands)).join("\n")}
|
|
145
|
+
${binNames.map((name) => formatFishOptionCompletions(name, options)).join("\n")}
|
|
146
|
+
${binNames.map((name) => formatFishCustomCompletions(name, commands)).join("\n")}`;
|
|
147
|
+
}
|
|
148
|
+
var uniqueBinNames = (binNames) => [...new Set(binNames)];
|
|
149
|
+
var sortCommands = (commands) => {
|
|
150
|
+
return [...commands].sort((left, right) => {
|
|
151
|
+
const leftOrder = getCommandMetadata(left)?.order;
|
|
152
|
+
const rightOrder = getCommandMetadata(right)?.order;
|
|
153
|
+
if (leftOrder !== void 0 || rightOrder !== void 0) {
|
|
154
|
+
return (leftOrder ?? Number.MAX_SAFE_INTEGER) - (rightOrder ?? Number.MAX_SAFE_INTEGER);
|
|
155
|
+
}
|
|
156
|
+
return left.name.localeCompare(right.name);
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
var getRootCommands = (commands) => {
|
|
160
|
+
const roots = /* @__PURE__ */ new Map();
|
|
161
|
+
for (const command of commands) {
|
|
162
|
+
const parts = command.name.split(" ");
|
|
163
|
+
const root = parts[0];
|
|
164
|
+
if (!root || roots.has(root)) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
roots.set(root, {
|
|
168
|
+
name: root,
|
|
169
|
+
description: parts.length === 1 ? command.description : `${root} commands`
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return [...roots.values()];
|
|
173
|
+
};
|
|
174
|
+
var getSubcommandGroups = (commands) => {
|
|
175
|
+
const groups = /* @__PURE__ */ new Map();
|
|
176
|
+
for (const command of commands) {
|
|
177
|
+
const [root, subcommand] = command.name.split(" ");
|
|
178
|
+
if (!root || !subcommand) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const group = groups.get(root) ?? [];
|
|
182
|
+
if (!group.some((item) => item.name === subcommand)) {
|
|
183
|
+
group.push({ name: subcommand, description: command.description });
|
|
184
|
+
}
|
|
185
|
+
groups.set(root, group);
|
|
186
|
+
}
|
|
187
|
+
return groups;
|
|
188
|
+
};
|
|
189
|
+
var getCommandOptions = (commands) => {
|
|
190
|
+
const commandOptions = /* @__PURE__ */ new Map();
|
|
191
|
+
for (const command of commands) {
|
|
192
|
+
const options = command.options.filter((option) => option.visible).flatMap(
|
|
193
|
+
(option) => option.allNotations.map((notation) => ({
|
|
194
|
+
name: notation,
|
|
195
|
+
description: option.description
|
|
196
|
+
}))
|
|
197
|
+
);
|
|
198
|
+
if (options.length > 0) {
|
|
199
|
+
commandOptions.set(command.name, options);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return commandOptions;
|
|
203
|
+
};
|
|
204
|
+
var formatZshItems = (items) => {
|
|
205
|
+
return items.map((item) => ` '${escapeZshItem(item)}'`).join("\n");
|
|
206
|
+
};
|
|
207
|
+
var formatSubcommandArrays = (groups) => {
|
|
208
|
+
return [...groups.entries()].map(
|
|
209
|
+
([root, items]) => `
|
|
210
|
+
local -a ${root}_commands
|
|
211
|
+
${root}_commands=(
|
|
212
|
+
${formatZshItems(items)}
|
|
213
|
+
)`
|
|
214
|
+
).join("\n");
|
|
215
|
+
};
|
|
216
|
+
var formatZshCustomCompletions = (binName, commands) => {
|
|
217
|
+
return commands.flatMap((command) => {
|
|
218
|
+
const functions = getCommandMetadata(command)?.completion?.zsh?.(binName).functions;
|
|
219
|
+
return functions ? [functions] : [];
|
|
220
|
+
}).join("\n");
|
|
221
|
+
};
|
|
222
|
+
var formatZshCustomCases = (binName, commands) => {
|
|
223
|
+
return commands.flatMap((command) => {
|
|
224
|
+
const complete = getCommandMetadata(command)?.completion?.zsh?.(binName).complete;
|
|
225
|
+
return complete ? [
|
|
226
|
+
` ${command.name})
|
|
227
|
+
${complete}
|
|
228
|
+
;;`
|
|
229
|
+
] : [];
|
|
230
|
+
}).join("\n");
|
|
231
|
+
};
|
|
232
|
+
var formatSubcommandCases = (binName, groups) => {
|
|
233
|
+
return [...groups.keys()].map(
|
|
234
|
+
(root) => ` ${root})
|
|
235
|
+
_describe '${binName} ${root} commands' ${root}_commands
|
|
236
|
+
;;`
|
|
237
|
+
).join("\n");
|
|
238
|
+
};
|
|
239
|
+
var formatOptionArrays = (groups) => {
|
|
240
|
+
return [...groups.entries()].map(
|
|
241
|
+
([command, items]) => `
|
|
242
|
+
local -a ${optionVariable(command)}
|
|
243
|
+
${optionVariable(command)}=(
|
|
244
|
+
${formatZshItems(items)}
|
|
245
|
+
)`
|
|
246
|
+
).join("\n");
|
|
247
|
+
};
|
|
248
|
+
var formatOptionCases = (binName, groups) => {
|
|
249
|
+
return [...groups.keys()].map(
|
|
250
|
+
(command) => ` ${JSON.stringify(command)})
|
|
251
|
+
_describe '${binName} ${command} options' ${optionVariable(command)}
|
|
252
|
+
return
|
|
253
|
+
;;`
|
|
254
|
+
).join("\n");
|
|
255
|
+
};
|
|
256
|
+
var formatBashCustomCases = (binName, commands) => {
|
|
257
|
+
return commands.flatMap((command) => {
|
|
258
|
+
const complete = getCommandMetadata(command)?.completion?.bash?.(binName);
|
|
259
|
+
return complete ? [
|
|
260
|
+
` ${command.name})
|
|
261
|
+
${complete}
|
|
262
|
+
;;`
|
|
263
|
+
] : [];
|
|
264
|
+
}).join("\n");
|
|
265
|
+
};
|
|
266
|
+
var formatBashSubcommandCases = (groups) => {
|
|
267
|
+
return [...groups.entries()].map(
|
|
268
|
+
([root, items]) => ` ${root})
|
|
269
|
+
COMPREPLY=($(compgen -W "${items.map((item) => item.name).join(" ")}" -- "$cur"))
|
|
270
|
+
;;`
|
|
271
|
+
).join("\n");
|
|
272
|
+
};
|
|
273
|
+
var formatFishFunctions = (binName, rootNames) => {
|
|
274
|
+
return `function __${binName}_seen_command
|
|
275
|
+
set -l tokens (commandline -opc)
|
|
276
|
+
for token in $tokens[2..-1]
|
|
277
|
+
switch $token
|
|
278
|
+
case ${rootNames}
|
|
279
|
+
return 0
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
return 1
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
function __${binName}_using_command
|
|
286
|
+
set -l tokens (commandline -opc)
|
|
287
|
+
test (count $tokens) -ge 2; and test "$tokens[2]" = "$argv[1]"
|
|
288
|
+
end`;
|
|
289
|
+
};
|
|
290
|
+
var formatFishCustomFunctions = (binName, commands) => {
|
|
291
|
+
return commands.flatMap((command) => {
|
|
292
|
+
const functions = getCommandMetadata(command)?.completion?.fish?.(binName).functions;
|
|
293
|
+
return functions ? [functions] : [];
|
|
294
|
+
}).join("\n");
|
|
295
|
+
};
|
|
296
|
+
var formatFishCustomCompletions = (binName, commands) => {
|
|
297
|
+
return commands.flatMap((command) => {
|
|
298
|
+
const complete = getCommandMetadata(command)?.completion?.fish?.(binName).complete;
|
|
299
|
+
return complete ? [complete] : [];
|
|
300
|
+
}).join("\n");
|
|
301
|
+
};
|
|
302
|
+
var formatFishRootCompletions = (binName, roots) => {
|
|
303
|
+
return roots.map(
|
|
304
|
+
(item) => `complete -c ${binName} -f -n "not __${binName}_seen_command" -a ${quoteFish(item.name)} -d ${quoteFish(item.description ?? "")}`
|
|
305
|
+
).join("\n");
|
|
306
|
+
};
|
|
307
|
+
var formatFishSubcommandCompletions = (binName, groups) => {
|
|
308
|
+
return [...groups.entries()].flatMap(
|
|
309
|
+
([root, items]) => items.map(
|
|
310
|
+
(item) => `complete -c ${binName} -f -n "__${binName}_using_command ${quoteFish(root)}" -a ${quoteFish(item.name)} -d ${quoteFish(item.description ?? "")}`
|
|
311
|
+
)
|
|
312
|
+
).join("\n");
|
|
313
|
+
};
|
|
314
|
+
var formatBashOptionCases = (groups) => {
|
|
315
|
+
return [...groups.entries()].map(
|
|
316
|
+
([command, items]) => ` ${JSON.stringify(command)})
|
|
317
|
+
COMPREPLY=($(compgen -W "${items.map((item) => item.name).join(" ")}" -- "$cur"))
|
|
318
|
+
;;`
|
|
319
|
+
).join("\n");
|
|
320
|
+
};
|
|
321
|
+
var formatFishOptionCompletions = (binName, groups) => {
|
|
322
|
+
return [...groups.entries()].flatMap(
|
|
323
|
+
([command, items]) => items.map((item) => {
|
|
324
|
+
const nameOption = fishOptionName(item.name);
|
|
325
|
+
return `complete -c ${binName} -f -n "__${binName}_using_command ${quoteFish(command)}" ${nameOption} -d ${quoteFish(item.description ?? "")}`;
|
|
326
|
+
})
|
|
327
|
+
).join("\n");
|
|
328
|
+
};
|
|
329
|
+
var fishOptionName = (name) => {
|
|
330
|
+
if (name.startsWith("--")) return `-l ${quoteFish(name.slice(2))}`;
|
|
331
|
+
if (name.startsWith("-")) return `-s ${quoteFish(name.slice(1))}`;
|
|
332
|
+
return `-a ${quoteFish(name)}`;
|
|
333
|
+
};
|
|
334
|
+
var completionFunctionName = (binName) => {
|
|
335
|
+
return binName.replace(/\W/g, "_");
|
|
336
|
+
};
|
|
337
|
+
var optionVariable = (command) => {
|
|
338
|
+
return `${command.replace(/\W/g, "_")}_options`;
|
|
339
|
+
};
|
|
340
|
+
var escapeZshItem = (item) => {
|
|
341
|
+
const text = item.description ? `${item.name}:${item.description}` : item.name;
|
|
342
|
+
return text.replace(/'/g, "'\\''");
|
|
343
|
+
};
|
|
344
|
+
var quoteFish = (value) => {
|
|
345
|
+
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
// src/cli/help.ts
|
|
349
|
+
var programExamples = /* @__PURE__ */ new WeakMap();
|
|
350
|
+
var setProgramExamples = (program, examples) => {
|
|
351
|
+
programExamples.set(program, examples);
|
|
352
|
+
};
|
|
353
|
+
var isGlobalHelpRequest = (args) => args.length === 0 || args.length === 1 && ["--help", "-h"].includes(args[0] ?? "");
|
|
354
|
+
var printProgramHelp = async (program) => {
|
|
355
|
+
const help = cleanHelp(await captureHelp(() => program.run(["--help"])));
|
|
356
|
+
const examples = programExamples.get(program) ?? [];
|
|
357
|
+
console.log([help.trimEnd(), formatExamples(examples)].filter(Boolean).join("\n\n"));
|
|
358
|
+
};
|
|
359
|
+
async function captureHelp(callback) {
|
|
360
|
+
const originalLog = console.log;
|
|
361
|
+
const lines = [];
|
|
362
|
+
console.log = (...args) => {
|
|
363
|
+
lines.push(args.map(String).join(" "));
|
|
364
|
+
};
|
|
365
|
+
try {
|
|
366
|
+
await callback();
|
|
367
|
+
} finally {
|
|
368
|
+
console.log = originalLog;
|
|
369
|
+
}
|
|
370
|
+
return lines.join("\n");
|
|
371
|
+
}
|
|
372
|
+
function cleanHelp(help) {
|
|
373
|
+
return help.replace(
|
|
374
|
+
/COMMANDS\s+—\s+Type '[^']+ help <command>' to get some help about a command/g,
|
|
375
|
+
"COMMANDS"
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
function formatExamples(examples) {
|
|
379
|
+
if (examples.length === 0) return "";
|
|
380
|
+
return [" EXAMPLES", "", ...examples.map((example) => ` ${example}`)].join("\n");
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// src/cli/program.ts
|
|
384
|
+
import { createRequire } from "module";
|
|
385
|
+
import { dirname, join as join2 } from "path";
|
|
386
|
+
import { fileURLToPath } from "url";
|
|
387
|
+
|
|
388
|
+
// src/command/loader.ts
|
|
389
|
+
import { readdir } from "fs/promises";
|
|
390
|
+
import { basename, join } from "path";
|
|
391
|
+
import { pathToFileURL } from "url";
|
|
392
|
+
var COMMAND_FILE_EXTENSION = ".ts";
|
|
393
|
+
var IGNORED_COMMAND_FILES = /* @__PURE__ */ new Set(["index.ts", "options.ts"]);
|
|
394
|
+
var loadCommandModules = async (commandsDir) => {
|
|
395
|
+
return loadCommandModulesFromFiles(await commandFiles(commandsDir));
|
|
396
|
+
};
|
|
397
|
+
var loadCommandModulesFromFiles = async (files) => {
|
|
398
|
+
return Promise.all(
|
|
399
|
+
files.map((file) => import(pathToFileURL(file).href))
|
|
400
|
+
);
|
|
401
|
+
};
|
|
402
|
+
var commandDefinitionsFromModules = (modules) => {
|
|
403
|
+
return modules.flatMap(
|
|
404
|
+
(module) => Object.values(module).flatMap(
|
|
405
|
+
(value) => isCommandAdapterExport(value) && value.metadata ? [value.metadata] : []
|
|
406
|
+
)
|
|
407
|
+
);
|
|
408
|
+
};
|
|
409
|
+
var commandExportsFromModules = (modules, isExport) => {
|
|
410
|
+
return modules.flatMap(
|
|
411
|
+
(module) => Object.entries(module).filter(([name, value]) => isExport(name, value)).map(([, value]) => value)
|
|
412
|
+
);
|
|
413
|
+
};
|
|
414
|
+
var commandFiles = async (dir) => {
|
|
415
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
416
|
+
const nestedFiles = await Promise.all(
|
|
417
|
+
entries.map((entry) => {
|
|
418
|
+
const path = join(dir, entry.name);
|
|
419
|
+
if (entry.isDirectory()) return commandFiles(path);
|
|
420
|
+
if (entry.isFile() && isCommandFile(path)) return [path];
|
|
421
|
+
return [];
|
|
422
|
+
})
|
|
423
|
+
);
|
|
424
|
+
return nestedFiles.flat().sort();
|
|
425
|
+
};
|
|
426
|
+
var isCommandFile = (path) => {
|
|
427
|
+
const fileName = basename(path);
|
|
428
|
+
return path.endsWith(COMMAND_FILE_EXTENSION) && !IGNORED_COMMAND_FILES.has(fileName);
|
|
429
|
+
};
|
|
430
|
+
var isCommandAdapterExport = (value) => {
|
|
431
|
+
if (!value || typeof value !== "object") return false;
|
|
432
|
+
const command = value;
|
|
433
|
+
return typeof command.cli === "function";
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
// src/constants.ts
|
|
437
|
+
var DEFAULT_COMMANDS_DIR = "commands";
|
|
438
|
+
var PROGRAM_NAME_ENV_SUFFIX = "_PROG_NAME";
|
|
439
|
+
|
|
440
|
+
// src/cli/update.ts
|
|
441
|
+
import { exec } from "child_process";
|
|
442
|
+
import { platform } from "os";
|
|
443
|
+
import { promisify } from "util";
|
|
444
|
+
var execAsync = promisify(exec);
|
|
445
|
+
var PackageManager = /* @__PURE__ */ ((PackageManager2) => {
|
|
446
|
+
PackageManager2["Npm"] = "npm";
|
|
447
|
+
PackageManager2["Pnpm"] = "pnpm";
|
|
448
|
+
PackageManager2["Yarn"] = "yarn";
|
|
449
|
+
return PackageManager2;
|
|
450
|
+
})(PackageManager || {});
|
|
451
|
+
var registerUpdateCommand = (program, options) => {
|
|
452
|
+
program.command("update", `Update ${options.packageName} to latest version`).action(async () => {
|
|
453
|
+
if (options.isDevRun) {
|
|
454
|
+
console.log("Skipping update because this is a dev command");
|
|
455
|
+
return 0;
|
|
456
|
+
}
|
|
457
|
+
console.log("Checking current version...");
|
|
458
|
+
const currentVersion = options.version ?? "0.0.0";
|
|
459
|
+
console.log("Checking latest version...");
|
|
460
|
+
const latestVersion = await getLatestVersion(options.packageName);
|
|
461
|
+
if (!latestVersion) {
|
|
462
|
+
console.log("error: could not fetch latest version from npm");
|
|
463
|
+
return 1;
|
|
464
|
+
}
|
|
465
|
+
console.log(`Current version: ${currentVersion}`);
|
|
466
|
+
console.log(`Latest version: ${latestVersion}`);
|
|
467
|
+
if (currentVersion === latestVersion) {
|
|
468
|
+
console.log(`${options.packageName} is already up to date`);
|
|
469
|
+
return 0;
|
|
470
|
+
}
|
|
471
|
+
console.log("Detecting package manager...");
|
|
472
|
+
const packageManager = await detectPackageManager(options.packageName);
|
|
473
|
+
if (!packageManager) {
|
|
474
|
+
console.log(`error: could not detect how ${options.packageName} was installed`);
|
|
475
|
+
console.log("Please update manually using your package manager");
|
|
476
|
+
return 1;
|
|
477
|
+
}
|
|
478
|
+
console.log(`Detected package manager: ${packageManager}`);
|
|
479
|
+
console.log(`Updating ${options.packageName} from ${currentVersion} to ${latestVersion}...`);
|
|
480
|
+
const { stdout, stderr } = await execAsync(updateCommand(packageManager, options.packageName));
|
|
481
|
+
console.log(
|
|
482
|
+
`${options.packageName} updated successfully from ${currentVersion} to ${latestVersion}`
|
|
483
|
+
);
|
|
484
|
+
if (stdout) console.log(stdout.trim());
|
|
485
|
+
if (stderr) console.log(stderr.trim());
|
|
486
|
+
return 0;
|
|
487
|
+
});
|
|
488
|
+
};
|
|
489
|
+
async function detectPackageManager(packageName) {
|
|
490
|
+
const globalBinPath = await getGlobalBinPath(packageName);
|
|
491
|
+
if (!globalBinPath) return await isInstalledWithNpm(packageName) ? "npm" /* Npm */ : null;
|
|
492
|
+
return getPackageManagerFromPath(globalBinPath) ?? "npm" /* Npm */;
|
|
493
|
+
}
|
|
494
|
+
function getPackageManagerFromPath(globalBinPath) {
|
|
495
|
+
const possiblePaths = [
|
|
496
|
+
{ manager: "yarn" /* Yarn */, patterns: ["/yarn/", "\\yarn\\", "/.yarn/", "\\.yarn\\"] },
|
|
497
|
+
{ manager: "pnpm" /* Pnpm */, patterns: ["/pnpm/", "\\pnpm\\", "/.pnpm/", "\\.pnpm\\"] },
|
|
498
|
+
{
|
|
499
|
+
manager: "npm" /* Npm */,
|
|
500
|
+
patterns: ["/npm/", "\\npm\\", "/node/", "\\node\\", "/node_modules/"]
|
|
501
|
+
}
|
|
502
|
+
];
|
|
503
|
+
for (const { manager, patterns } of possiblePaths) {
|
|
504
|
+
if (patterns.some((pattern) => globalBinPath.includes(pattern))) return manager;
|
|
505
|
+
}
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
async function getGlobalBinPath(binName) {
|
|
509
|
+
const isWindows = platform() === "win32";
|
|
510
|
+
try {
|
|
511
|
+
const whereCommand = isWindows ? "where" : "which";
|
|
512
|
+
const { stdout } = await execAsync(`${whereCommand} ${binName}`);
|
|
513
|
+
const execPath = stdout.trim();
|
|
514
|
+
if (!execPath) return null;
|
|
515
|
+
if (isWindows) return execPath;
|
|
516
|
+
try {
|
|
517
|
+
const { stdout: realPath } = await execAsync(`readlink -f "${execPath}"`);
|
|
518
|
+
return realPath.trim() || execPath;
|
|
519
|
+
} catch {
|
|
520
|
+
return execPath;
|
|
521
|
+
}
|
|
522
|
+
} catch {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
async function isInstalledWithNpm(packageName) {
|
|
527
|
+
try {
|
|
528
|
+
const { stdout } = await execAsync(`npm list -g --depth=0 ${packageName}`);
|
|
529
|
+
return stdout.includes(packageName);
|
|
530
|
+
} catch {
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
async function getLatestVersion(packageName) {
|
|
535
|
+
try {
|
|
536
|
+
const { stdout } = await execAsync(`npm view ${packageName} version`);
|
|
537
|
+
return stdout.trim();
|
|
538
|
+
} catch {
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
function updateCommand(packageManager, packageName) {
|
|
543
|
+
return {
|
|
544
|
+
["npm" /* Npm */]: `npm update -g ${packageName}`,
|
|
545
|
+
["pnpm" /* Pnpm */]: `pnpm update -g ${packageName}`,
|
|
546
|
+
["yarn" /* Yarn */]: `yarn global upgrade ${packageName}`
|
|
547
|
+
}[packageManager];
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// src/cli/program.ts
|
|
551
|
+
var VERSION_OPTION = "-v, --version";
|
|
552
|
+
var DISABLED_GLOBAL_OPTIONS = ["--no-color", "--quiet", "--silent", "-v", "-V"];
|
|
553
|
+
var DEFAULT_CLI_VERSION = "0.0.0";
|
|
554
|
+
var createCommandProgram = async ({
|
|
555
|
+
binName,
|
|
556
|
+
binNames,
|
|
557
|
+
commandsDir,
|
|
558
|
+
description,
|
|
559
|
+
getContext,
|
|
560
|
+
importMetaUrl,
|
|
561
|
+
isDevRun = false,
|
|
562
|
+
packageName,
|
|
563
|
+
printVersion = console.log,
|
|
564
|
+
version = DEFAULT_CLI_VERSION
|
|
565
|
+
}) => {
|
|
566
|
+
const program = new (getProgramConstructor())().bin(binName).name(binName).description(description).version(version);
|
|
567
|
+
disableDefaultGlobalOptions(program);
|
|
568
|
+
registerVersionOption(program, version, printVersion);
|
|
569
|
+
const commandDefinitions = await registerCliCommandsFromDirectory({
|
|
570
|
+
binName,
|
|
571
|
+
commandsDir: commandsDir ?? defaultCommandsDir(importMetaUrl),
|
|
572
|
+
getContext,
|
|
573
|
+
program
|
|
574
|
+
});
|
|
575
|
+
registerUpdateCommand(program, { isDevRun, packageName: packageName ?? binName, version });
|
|
576
|
+
registerCompletionCommand(program, { binNames });
|
|
577
|
+
setProgramExamples(
|
|
578
|
+
program,
|
|
579
|
+
commandDefinitions.flatMap((command) => command.examples?.(binName) ?? [])
|
|
580
|
+
);
|
|
581
|
+
return program;
|
|
582
|
+
};
|
|
583
|
+
var registerParentCommandsFromDefinitions = (program, definitions, options = {}) => {
|
|
584
|
+
const description = options.description ?? parentCommandDescription;
|
|
585
|
+
const print = options.print ?? console.log;
|
|
586
|
+
for (const [name, subcommands] of parentCommands(definitions)) {
|
|
587
|
+
program.command(name, description(name)).action(() => {
|
|
588
|
+
print(`Usage: ${program.getBin()} ${name} <command>`);
|
|
589
|
+
print("");
|
|
590
|
+
print(`Available commands: ${subcommands.join(", ")}`);
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
var registerCliCommandsFromDirectory = async ({
|
|
595
|
+
binName,
|
|
596
|
+
commandsDir,
|
|
597
|
+
getContext,
|
|
598
|
+
program
|
|
599
|
+
}) => {
|
|
600
|
+
const modules = await loadCommandModules(commandsDir);
|
|
601
|
+
const definitions = commandDefinitionsFromModules(modules);
|
|
602
|
+
registerParentCommandsFromDefinitions(program, definitions);
|
|
603
|
+
const commands = commandExportsFromModules(
|
|
604
|
+
modules,
|
|
605
|
+
(_name, value) => isCommandAdapterExport(value)
|
|
606
|
+
);
|
|
607
|
+
for (const command of commands.sort(compareCommands)) {
|
|
608
|
+
command.cli(program, { binName, getContext });
|
|
609
|
+
}
|
|
610
|
+
return definitions;
|
|
611
|
+
};
|
|
612
|
+
var getProgramConstructor = () => {
|
|
613
|
+
const require2 = createRequire(import.meta.url);
|
|
614
|
+
const module = require2("@caporal/core");
|
|
615
|
+
return module.Program;
|
|
616
|
+
};
|
|
617
|
+
var disableDefaultGlobalOptions = (program) => {
|
|
618
|
+
for (const option of DISABLED_GLOBAL_OPTIONS) {
|
|
619
|
+
program.disableGlobalOption(option);
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
var registerVersionOption = (program, version, printVersion) => {
|
|
623
|
+
program.option(VERSION_OPTION, "Show version", {
|
|
624
|
+
global: true,
|
|
625
|
+
action: () => {
|
|
626
|
+
printVersion(version);
|
|
627
|
+
return false;
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
};
|
|
631
|
+
var defaultCommandsDir = (importMetaUrl) => join2(dirname(fileURLToPath(importMetaUrl)), DEFAULT_COMMANDS_DIR);
|
|
632
|
+
var compareCommands = (left, right) => {
|
|
633
|
+
const leftName = left.metadata?.name ?? "";
|
|
634
|
+
const rightName = right.metadata?.name ?? "";
|
|
635
|
+
const leftOrder = left.metadata?.order;
|
|
636
|
+
const rightOrder = right.metadata?.order;
|
|
637
|
+
if (leftOrder !== void 0 || rightOrder !== void 0) {
|
|
638
|
+
return (leftOrder ?? Number.MAX_SAFE_INTEGER) - (rightOrder ?? Number.MAX_SAFE_INTEGER);
|
|
639
|
+
}
|
|
640
|
+
return leftName.localeCompare(rightName);
|
|
641
|
+
};
|
|
642
|
+
var parentCommandDescription = (name) => `${name} commands`;
|
|
643
|
+
var parentCommands = (definitions) => {
|
|
644
|
+
const groups = /* @__PURE__ */ new Map();
|
|
645
|
+
const commandNames = new Set(definitions.map((definition) => definition.name));
|
|
646
|
+
for (const definition of definitions) {
|
|
647
|
+
const [parent, subcommand] = definition.name.split(" ");
|
|
648
|
+
const hasGeneratedParentCommand = parent && subcommand && !commandNames.has(parent);
|
|
649
|
+
if (!hasGeneratedParentCommand) continue;
|
|
650
|
+
groups.set(parent, [...groups.get(parent) ?? [], subcommand]);
|
|
651
|
+
}
|
|
652
|
+
return [...groups.entries()].sort(([left], [right]) => left.localeCompare(right));
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
// src/package/json.ts
|
|
656
|
+
import { existsSync, readFileSync } from "fs";
|
|
657
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
658
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
659
|
+
var PACKAGE_JSON_FILE = "package.json";
|
|
660
|
+
var PACKAGE_JSON_ENCODING = "utf8";
|
|
661
|
+
var packageRoot = (importMetaUrl) => {
|
|
662
|
+
const startDir = dirname2(fileURLToPath2(importMetaUrl));
|
|
663
|
+
return findPackageRoot(startDir);
|
|
664
|
+
};
|
|
665
|
+
var readPackageJson = (packageDir) => {
|
|
666
|
+
return JSON.parse(
|
|
667
|
+
readFileSync(join3(packageDir, PACKAGE_JSON_FILE), PACKAGE_JSON_ENCODING)
|
|
668
|
+
);
|
|
669
|
+
};
|
|
670
|
+
var shortPackageName = (name) => {
|
|
671
|
+
const packageName = name?.split("/").at(-1);
|
|
672
|
+
if (!packageName) {
|
|
673
|
+
throw new Error("Missing package name");
|
|
674
|
+
}
|
|
675
|
+
return packageName;
|
|
676
|
+
};
|
|
677
|
+
var packageEnvPrefix = (name) => shortPackageName(name).replaceAll("-", "_").toUpperCase();
|
|
678
|
+
var packageBinEntry = (packageDir, packageJson) => {
|
|
679
|
+
const [commandName, binPath] = Object.entries(packageJson.bin ?? {})[0] ?? [];
|
|
680
|
+
if (!commandName || !binPath) {
|
|
681
|
+
throw new Error(`Missing bin in ${join3(packageDir, PACKAGE_JSON_FILE)}`);
|
|
682
|
+
}
|
|
683
|
+
return { binPath, commandName };
|
|
684
|
+
};
|
|
685
|
+
function findPackageRoot(startDir) {
|
|
686
|
+
const packageJsonPath = join3(startDir, PACKAGE_JSON_FILE);
|
|
687
|
+
if (existsSync(packageJsonPath)) return startDir;
|
|
688
|
+
const parentDir = dirname2(startDir);
|
|
689
|
+
if (parentDir === startDir) throw new Error(`Missing ${PACKAGE_JSON_FILE}`);
|
|
690
|
+
return findPackageRoot(parentDir);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// src/package/metadata.ts
|
|
694
|
+
var packageCommandMetadata = (importMetaUrl, options = {}) => {
|
|
695
|
+
const packageDir = packageRoot(importMetaUrl);
|
|
696
|
+
const packageJson = readPackageJson(packageDir);
|
|
697
|
+
const packageName = shortPackageName(packageJson.name);
|
|
698
|
+
const { commandName } = packageBinEntry(packageDir, packageJson);
|
|
699
|
+
return {
|
|
700
|
+
binName: commandName,
|
|
701
|
+
binNames: Object.keys(packageJson.bin ?? {}),
|
|
702
|
+
description: packageJson.description,
|
|
703
|
+
envBinName: `${packageEnvPrefix(packageName)}${PROGRAM_NAME_ENV_SUFFIX}`,
|
|
704
|
+
mcpPrefix: packageName,
|
|
705
|
+
mcpServerName: mcpServerName(packageName, options.mcpServerPrefix),
|
|
706
|
+
packageDir,
|
|
707
|
+
packageName,
|
|
708
|
+
version: packageJson.version
|
|
709
|
+
};
|
|
710
|
+
};
|
|
711
|
+
var mcpServerName = (packageName, prefix) => prefix ? `${prefix}-${packageName}` : packageName;
|
|
712
|
+
|
|
713
|
+
// src/cli/runtime.ts
|
|
714
|
+
import { realpathSync } from "fs";
|
|
715
|
+
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
|
|
716
|
+
var getProgramBin = (config) => {
|
|
717
|
+
const envBinName = process.env[config.envBinName];
|
|
718
|
+
if (envBinName) {
|
|
719
|
+
return envBinName;
|
|
720
|
+
}
|
|
721
|
+
return config.defaultBinName;
|
|
722
|
+
};
|
|
723
|
+
var isDirectRun = (importMetaUrl) => {
|
|
724
|
+
if (!process.argv[1]) {
|
|
725
|
+
return false;
|
|
726
|
+
}
|
|
727
|
+
try {
|
|
728
|
+
return realpathSync(process.argv[1]) === realpathSync(fileURLToPath3(importMetaUrl));
|
|
729
|
+
} catch {
|
|
730
|
+
return importMetaUrl === pathToFileURL2(process.argv[1]).href;
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
// src/cli/runner.ts
|
|
735
|
+
var createCliRunner = (config) => {
|
|
736
|
+
let programInstance;
|
|
737
|
+
let programInstanceBin;
|
|
738
|
+
const getProgram = async () => {
|
|
739
|
+
const binName = getProgramBin(config);
|
|
740
|
+
const shouldCreateProgram = !programInstance || programInstanceBin !== binName;
|
|
741
|
+
if (shouldCreateProgram) {
|
|
742
|
+
const program = await config.createProgram(binName);
|
|
743
|
+
programInstance = program;
|
|
744
|
+
programInstanceBin = binName;
|
|
745
|
+
return program;
|
|
746
|
+
}
|
|
747
|
+
return programInstance;
|
|
748
|
+
};
|
|
749
|
+
const runCli = async (args = process.argv.slice(2)) => {
|
|
750
|
+
try {
|
|
751
|
+
const program = await getProgram();
|
|
752
|
+
if (isGlobalHelpRequest(args)) {
|
|
753
|
+
await printProgramHelp(program);
|
|
754
|
+
return 0;
|
|
755
|
+
}
|
|
756
|
+
const result = await program.run(args);
|
|
757
|
+
return typeof result === "number" && result > 0 ? result : 0;
|
|
758
|
+
} catch (error) {
|
|
759
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
760
|
+
console.log(`error: ${message}`);
|
|
761
|
+
return 1;
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
return { isDirectRun: () => isDirectRun(config.importMetaUrl), runCli };
|
|
765
|
+
};
|
|
766
|
+
var createPackageCommandCliRunner = ({
|
|
767
|
+
defaultBinName,
|
|
768
|
+
envBinName,
|
|
769
|
+
importMetaUrl,
|
|
770
|
+
...options
|
|
771
|
+
}) => {
|
|
772
|
+
const metadata = packageCommandMetadata(importMetaUrl);
|
|
773
|
+
return createCommandCliRunner({
|
|
774
|
+
...options,
|
|
775
|
+
binNames: options.binNames ?? metadata.binNames,
|
|
776
|
+
defaultBinName: defaultBinName ?? metadata.binName,
|
|
777
|
+
description: options.description ?? metadata.description ?? metadata.packageName,
|
|
778
|
+
envBinName: envBinName ?? metadata.envBinName,
|
|
779
|
+
importMetaUrl,
|
|
780
|
+
isDevRun: process.env[envBinName ?? metadata.envBinName] !== void 0,
|
|
781
|
+
packageName: metadata.packageName,
|
|
782
|
+
version: options.version ?? metadata.version
|
|
783
|
+
});
|
|
784
|
+
};
|
|
785
|
+
var createCommandCliRunner = ({
|
|
786
|
+
binNames,
|
|
787
|
+
commandsDir,
|
|
788
|
+
defaultBinName,
|
|
789
|
+
description,
|
|
790
|
+
envBinName,
|
|
791
|
+
getContext,
|
|
792
|
+
importMetaUrl,
|
|
793
|
+
isDevRun,
|
|
794
|
+
packageName,
|
|
795
|
+
printVersion,
|
|
796
|
+
version
|
|
797
|
+
}) => {
|
|
798
|
+
return createCliRunner({
|
|
799
|
+
createProgram: (binName) => createCommandProgram({
|
|
800
|
+
binName,
|
|
801
|
+
binNames,
|
|
802
|
+
commandsDir,
|
|
803
|
+
description,
|
|
804
|
+
getContext,
|
|
805
|
+
importMetaUrl,
|
|
806
|
+
isDevRun,
|
|
807
|
+
packageName,
|
|
808
|
+
printVersion,
|
|
809
|
+
version
|
|
810
|
+
}),
|
|
811
|
+
defaultBinName,
|
|
812
|
+
envBinName,
|
|
813
|
+
importMetaUrl
|
|
814
|
+
});
|
|
815
|
+
};
|
|
816
|
+
|
|
817
|
+
// src/mcp/router.ts
|
|
818
|
+
import { z as z3 } from "zod";
|
|
819
|
+
|
|
820
|
+
// src/command/metadata.ts
|
|
821
|
+
import { z } from "zod";
|
|
822
|
+
var isCommandMcpToolMetadata = (metadata) => metadata !== void 0 && metadata !== false && metadata.kind === "tool";
|
|
823
|
+
var isCommandMcpResourceMetadata = (metadata) => metadata !== void 0 && metadata !== false && metadata.kind === "resource";
|
|
824
|
+
var defineCommand = (definition) => {
|
|
825
|
+
const command = {
|
|
826
|
+
outputSchema: z.unknown(),
|
|
827
|
+
...definition
|
|
828
|
+
};
|
|
829
|
+
return {
|
|
830
|
+
...command,
|
|
831
|
+
inputSchema: definition.inputSchema ?? commandDefinitionToZodInputSchema(command)
|
|
832
|
+
};
|
|
833
|
+
};
|
|
834
|
+
var registerCommand = (program, definition) => {
|
|
835
|
+
const command = definition.arguments?.reduce(
|
|
836
|
+
(currentCommand, argument) => currentCommand.argument(argument.synopsis, argument.description),
|
|
837
|
+
program.command(definition.name, definition.description, definition.config)
|
|
838
|
+
) ?? program.command(definition.name, definition.description, definition.config);
|
|
839
|
+
const commandWithOptions = definition.options?.reduce(
|
|
840
|
+
(currentCommand, option) => currentCommand.option(commandOptionSynopsis(option), option.description, option.config),
|
|
841
|
+
command
|
|
842
|
+
) ?? command;
|
|
843
|
+
const registeredCommand = definition.aliases?.reduce(
|
|
844
|
+
(currentCommand, alias) => currentCommand.alias(alias),
|
|
845
|
+
commandWithOptions
|
|
846
|
+
) ?? commandWithOptions;
|
|
847
|
+
setCommandMetadata(registeredCommand, definition);
|
|
848
|
+
return registeredCommand;
|
|
849
|
+
};
|
|
850
|
+
var commandInputValue = (args, name) => args[name];
|
|
851
|
+
var commandInputString = (args, name) => {
|
|
852
|
+
const value = commandInputValue(args, name);
|
|
853
|
+
return value === void 0 ? "" : String(value);
|
|
854
|
+
};
|
|
855
|
+
var commandActionInput = (definition, args, options) => normalizeCommandInputAliases(definition, {
|
|
856
|
+
...normalizeArgumentInput(definition, args),
|
|
857
|
+
...options
|
|
858
|
+
});
|
|
859
|
+
var normalizeCommandInputAliases = (definition, input) => ({
|
|
860
|
+
...input,
|
|
861
|
+
...Object.fromEntries(
|
|
862
|
+
(definition.options ?? []).flatMap((option) => {
|
|
863
|
+
const name = optionInputName(option);
|
|
864
|
+
if (input[name] !== void 0) return [];
|
|
865
|
+
const alias = optionAliasInputNames(option).find(
|
|
866
|
+
(candidate) => input[candidate] !== void 0
|
|
867
|
+
);
|
|
868
|
+
return alias ? [[name, input[alias]]] : [];
|
|
869
|
+
})
|
|
870
|
+
)
|
|
871
|
+
});
|
|
872
|
+
var normalizeArgumentInput = (definition, args) => ({
|
|
873
|
+
...args,
|
|
874
|
+
...Object.fromEntries(
|
|
875
|
+
(definition.arguments ?? []).map((argument) => {
|
|
876
|
+
const name = argumentName(argument.synopsis);
|
|
877
|
+
const value = commandInputValue(args, name);
|
|
878
|
+
return value === void 0 ? void 0 : [name, value];
|
|
879
|
+
}).filter((entry) => entry !== void 0)
|
|
880
|
+
)
|
|
881
|
+
});
|
|
882
|
+
var commandDefinitionToZodInputSchema = (definition) => {
|
|
883
|
+
const jsonSchema = commandDefinitionToInputSchema(definition);
|
|
884
|
+
const shape = Object.fromEntries(
|
|
885
|
+
Object.entries(jsonSchema.properties).map(([name, property]) => [
|
|
886
|
+
name,
|
|
887
|
+
zodInputProperty(property, jsonSchema.required.includes(name))
|
|
888
|
+
])
|
|
889
|
+
);
|
|
890
|
+
return z.object(shape);
|
|
891
|
+
};
|
|
892
|
+
var commandDefinitionToInputSchema = (definition) => ({
|
|
893
|
+
type: "object",
|
|
894
|
+
properties: Object.fromEntries([
|
|
895
|
+
...(definition.arguments ?? []).map((argument) => [
|
|
896
|
+
argumentName(argument.synopsis),
|
|
897
|
+
argumentSchema(argument)
|
|
898
|
+
]),
|
|
899
|
+
...(definition.options ?? []).map((option) => [
|
|
900
|
+
optionInputName(option),
|
|
901
|
+
option.schema ?? optionSchema(option)
|
|
902
|
+
])
|
|
903
|
+
]),
|
|
904
|
+
required: [
|
|
905
|
+
...(definition.arguments ?? []).filter((argument) => isRequiredSynopsis(argument.synopsis)).map((argument) => argumentName(argument.synopsis)),
|
|
906
|
+
...(definition.options ?? []).filter((option) => option.config?.required).map(optionInputName)
|
|
907
|
+
],
|
|
908
|
+
additionalProperties: false
|
|
909
|
+
});
|
|
910
|
+
var zodInputProperty = (property, required) => {
|
|
911
|
+
const schema = zodProperty(property);
|
|
912
|
+
const describedSchema = property.description ? schema.describe(property.description) : schema;
|
|
913
|
+
return required ? describedSchema : describedSchema.optional();
|
|
914
|
+
};
|
|
915
|
+
var zodProperty = (property) => {
|
|
916
|
+
if (property.type === "array") return z.array(z.string());
|
|
917
|
+
if (property.type === "boolean") return z.boolean();
|
|
918
|
+
if (property.type === "number") return z.number();
|
|
919
|
+
return z.string();
|
|
920
|
+
};
|
|
921
|
+
var argumentSchema = (argument) => ({
|
|
922
|
+
type: isVariadicSynopsis(argument.synopsis) ? "array" : "string",
|
|
923
|
+
description: argument.description,
|
|
924
|
+
...isVariadicSynopsis(argument.synopsis) ? { items: { type: "string" } } : {}
|
|
925
|
+
});
|
|
926
|
+
var optionSchema = (option) => ({
|
|
927
|
+
type: option.value ? "string" : "boolean",
|
|
928
|
+
description: option.description
|
|
929
|
+
});
|
|
930
|
+
var argumentName = (synopsis) => {
|
|
931
|
+
return kebabToCamel(
|
|
932
|
+
synopsis.replace(/[<>[\].]/g, "").replace(/_([a-z])/g, (_match, letter) => letter.toUpperCase())
|
|
933
|
+
);
|
|
934
|
+
};
|
|
935
|
+
var commandOptionSynopsis = (option) => {
|
|
936
|
+
const longName = `${option.negated ? "--no-" : "--"}${option.name}`;
|
|
937
|
+
const aliases = (option.aliases ?? []).map(
|
|
938
|
+
(alias) => alias.length === 1 ? `-${alias}` : `--${alias}`
|
|
939
|
+
);
|
|
940
|
+
return [...aliases, `${longName}${option.value ? ` ${option.value}` : ""}`].join(", ");
|
|
941
|
+
};
|
|
942
|
+
var optionInputName = (option) => kebabToCamel(option.name);
|
|
943
|
+
var optionAliasInputNames = (option) => (option.aliases ?? []).map(kebabToCamel);
|
|
944
|
+
var kebabToCamel = (value) => value.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
945
|
+
var isRequiredSynopsis = (synopsis) => synopsis.trim().startsWith("<");
|
|
946
|
+
var isVariadicSynopsis = (synopsis) => synopsis.includes("...");
|
|
947
|
+
|
|
948
|
+
// src/mcp/constants.ts
|
|
949
|
+
var DEFAULT_MCP_SERVER_VERSION = "0.0.0";
|
|
950
|
+
var DEFAULT_RESOURCE_MIME_TYPE = "application/json";
|
|
951
|
+
var MCP_PROTOCOL_VERSION = "2024-11-05";
|
|
952
|
+
var JSON_RPC_METHOD_NOT_FOUND = -32601;
|
|
953
|
+
var JSON_RPC_INTERNAL_ERROR = -32603;
|
|
954
|
+
var JSON_RPC_VERSION = "2.0";
|
|
955
|
+
var MCP_STATUS_COMPLETED = "completed";
|
|
956
|
+
var MCP_STATUS_ERROR = "error";
|
|
957
|
+
var MCP_TEXT_CONTENT_TYPE = "text";
|
|
958
|
+
var TOOL_NAME_SEPARATOR = "_";
|
|
959
|
+
var COMMAND_NAME_SEPARATOR = " ";
|
|
960
|
+
var EMPTY_DISPLAY_VALUE2 = "<empty>";
|
|
961
|
+
var RESULT_ENVELOPE_DATA_KEY = "data";
|
|
962
|
+
var RESULT_ENVELOPE_PROGRESS_KEY = "progress";
|
|
963
|
+
var PROGRESS_LIST_KEYS = ["items", "threads", "files", "events", "messages"];
|
|
964
|
+
var CURSOR_KEYS = ["nextCursor", "nextPageToken"];
|
|
965
|
+
var MCP_METHOD_INITIALIZE = "initialize";
|
|
966
|
+
var MCP_METHOD_TOOLS_LIST = "tools/list";
|
|
967
|
+
var MCP_METHOD_TOOLS_CALL = "tools/call";
|
|
968
|
+
var MCP_METHOD_RESOURCES_LIST = "resources/list";
|
|
969
|
+
var MCP_METHOD_RESOURCES_TEMPLATES_LIST = "resources/templates/list";
|
|
970
|
+
var MCP_METHOD_RESOURCES_READ = "resources/read";
|
|
971
|
+
|
|
972
|
+
// src/mcp/errors.ts
|
|
973
|
+
var assertToolName = (expectedName, actualName) => {
|
|
974
|
+
if (actualName !== expectedName) {
|
|
975
|
+
throwUnknownTool(actualName);
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
var throwUnknownTool = (name) => {
|
|
979
|
+
throw new Error(`Unknown tool: ${name ?? EMPTY_DISPLAY_VALUE2}`);
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
// src/mcp/progress.ts
|
|
983
|
+
var toolResult = (result, startedAt) => {
|
|
984
|
+
const envelope = resultEnvelope(result);
|
|
985
|
+
const data = envelope.data;
|
|
986
|
+
const structuredContent = {
|
|
987
|
+
status: MCP_STATUS_COMPLETED,
|
|
988
|
+
progress: progressSummary(data, startedAt, envelope.progress),
|
|
989
|
+
data
|
|
990
|
+
};
|
|
991
|
+
return {
|
|
992
|
+
structuredContent,
|
|
993
|
+
content: [{ type: MCP_TEXT_CONTENT_TYPE, text: JSON.stringify(structuredContent, null, 2) }]
|
|
994
|
+
};
|
|
995
|
+
};
|
|
996
|
+
var toolErrorResult = (caught, startedAt = Date.now()) => {
|
|
997
|
+
const message = caught instanceof Error ? caught.message : String(caught);
|
|
998
|
+
const structuredContent = {
|
|
999
|
+
status: MCP_STATUS_ERROR,
|
|
1000
|
+
progress: { elapsedMs: elapsedMs(startedAt), errors: [message] },
|
|
1001
|
+
error: { message }
|
|
1002
|
+
};
|
|
1003
|
+
return {
|
|
1004
|
+
structuredContent,
|
|
1005
|
+
content: [{ type: MCP_TEXT_CONTENT_TYPE, text: JSON.stringify(structuredContent, null, 2) }]
|
|
1006
|
+
};
|
|
1007
|
+
};
|
|
1008
|
+
var commandProgressSummary = (data, command) => {
|
|
1009
|
+
const mcp = command.mcp;
|
|
1010
|
+
if (!isCommandMcpToolMetadata(mcp) || mcp.readOnly) {
|
|
1011
|
+
return void 0;
|
|
1012
|
+
}
|
|
1013
|
+
const processed = processedOf(data) ?? countOf(data) ?? 1;
|
|
1014
|
+
return { changed: processed, matched: processed, processed, skipped: 0 };
|
|
1015
|
+
};
|
|
1016
|
+
var progressSummary = (data, startedAt, progress) => {
|
|
1017
|
+
const summary = {
|
|
1018
|
+
count: countOf(data),
|
|
1019
|
+
elapsedMs: elapsedMs(startedAt),
|
|
1020
|
+
errors: [],
|
|
1021
|
+
nextCursor: cursorOf(data),
|
|
1022
|
+
processed: processedOf(data),
|
|
1023
|
+
...progress
|
|
1024
|
+
};
|
|
1025
|
+
return Object.fromEntries(Object.entries(summary).filter(([, value]) => value !== void 0));
|
|
1026
|
+
};
|
|
1027
|
+
var resultEnvelope = (result) => {
|
|
1028
|
+
if (isRecord(result) && RESULT_ENVELOPE_DATA_KEY in result && RESULT_ENVELOPE_PROGRESS_KEY in result) {
|
|
1029
|
+
return {
|
|
1030
|
+
data: result[RESULT_ENVELOPE_DATA_KEY],
|
|
1031
|
+
progress: recordOf(result[RESULT_ENVELOPE_PROGRESS_KEY])
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
return { data: result };
|
|
1035
|
+
};
|
|
1036
|
+
var recordOf = (value) => isRecord(value) ? value : void 0;
|
|
1037
|
+
var elapsedMs = (startedAt) => Date.now() - startedAt;
|
|
1038
|
+
var countOf = (data) => {
|
|
1039
|
+
if (!isRecord(data)) return void 0;
|
|
1040
|
+
return typeof data.count === "number" ? data.count : processedOf(data);
|
|
1041
|
+
};
|
|
1042
|
+
var processedOf = (data) => {
|
|
1043
|
+
if (Array.isArray(data)) return data.length;
|
|
1044
|
+
if (!isRecord(data)) return void 0;
|
|
1045
|
+
const list = PROGRESS_LIST_KEYS.map((key) => data[key]).find(Array.isArray);
|
|
1046
|
+
return list ? list.length : void 0;
|
|
1047
|
+
};
|
|
1048
|
+
var cursorOf = (data) => {
|
|
1049
|
+
if (!isRecord(data)) return void 0;
|
|
1050
|
+
const cursor = CURSOR_KEYS.map((key) => data[key]).find((value) => typeof value === "string");
|
|
1051
|
+
return typeof cursor === "string" ? cursor : void 0;
|
|
1052
|
+
};
|
|
1053
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1054
|
+
|
|
1055
|
+
// src/mcp/resources.ts
|
|
1056
|
+
var commandMcpRouteToResourceRoute = (route) => {
|
|
1057
|
+
const mcp = route.command.mcp;
|
|
1058
|
+
if (!isCommandMcpResourceMetadata(mcp)) return [];
|
|
1059
|
+
const inputNames = resourceInputNames(mcp.uriTemplate);
|
|
1060
|
+
return [
|
|
1061
|
+
{
|
|
1062
|
+
command: route.command,
|
|
1063
|
+
handler: route.handler,
|
|
1064
|
+
inputNames,
|
|
1065
|
+
mimeType: mcp.mimeType ?? DEFAULT_RESOURCE_MIME_TYPE,
|
|
1066
|
+
name: route.command.name,
|
|
1067
|
+
uriTemplate: mcp.uriTemplate
|
|
1068
|
+
}
|
|
1069
|
+
];
|
|
1070
|
+
};
|
|
1071
|
+
var commandResourceRouteToResource = (route) => ({
|
|
1072
|
+
uri: route.uriTemplate,
|
|
1073
|
+
name: route.name,
|
|
1074
|
+
description: route.command.description,
|
|
1075
|
+
mimeType: route.mimeType
|
|
1076
|
+
});
|
|
1077
|
+
var commandResourceRouteToResourceTemplate = (route) => ({
|
|
1078
|
+
uriTemplate: route.uriTemplate,
|
|
1079
|
+
name: route.name,
|
|
1080
|
+
description: route.command.description,
|
|
1081
|
+
mimeType: route.mimeType
|
|
1082
|
+
});
|
|
1083
|
+
var commandResourceInput = (route, uri) => {
|
|
1084
|
+
if (!uri) return void 0;
|
|
1085
|
+
const prefix = route.uriTemplate.split("{")[0] ?? "";
|
|
1086
|
+
if (!uri.startsWith(prefix)) return void 0;
|
|
1087
|
+
const values = uri.slice(prefix.length).split("/").filter(Boolean).map(decodeURIComponent);
|
|
1088
|
+
if (values.length !== route.inputNames.length) return void 0;
|
|
1089
|
+
return Object.fromEntries(
|
|
1090
|
+
route.inputNames.map((inputName, index) => [inputName, values[index] ?? ""])
|
|
1091
|
+
);
|
|
1092
|
+
};
|
|
1093
|
+
var isResourceTemplate = (uri) => resourceInputNames(uri).length > 0;
|
|
1094
|
+
var resourceResult = (params, data) => {
|
|
1095
|
+
const resourceRead = params;
|
|
1096
|
+
return {
|
|
1097
|
+
contents: [
|
|
1098
|
+
{
|
|
1099
|
+
uri: resourceRead.uri ?? "",
|
|
1100
|
+
mimeType: DEFAULT_RESOURCE_MIME_TYPE,
|
|
1101
|
+
text: JSON.stringify({ data }, null, 2)
|
|
1102
|
+
}
|
|
1103
|
+
]
|
|
1104
|
+
};
|
|
1105
|
+
};
|
|
1106
|
+
var resourceInputNames = (uriTemplate) => [...uriTemplate.matchAll(/\{([^}]+)\}/g)].flatMap((match) => {
|
|
1107
|
+
const inputName = match[1];
|
|
1108
|
+
return inputName ? [inputName] : [];
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
// src/mcp/schema.ts
|
|
1112
|
+
import { z as z2 } from "zod";
|
|
1113
|
+
var mcpToolOutputSchema = (dataSchema) => ({
|
|
1114
|
+
type: "object",
|
|
1115
|
+
properties: {
|
|
1116
|
+
data: z2.toJSONSchema(dataSchema),
|
|
1117
|
+
progress: {
|
|
1118
|
+
type: "object",
|
|
1119
|
+
properties: {
|
|
1120
|
+
count: { type: "number" },
|
|
1121
|
+
elapsedMs: { type: "number" },
|
|
1122
|
+
changed: { type: "number" },
|
|
1123
|
+
errors: { type: "array", items: { type: "string" } },
|
|
1124
|
+
matched: { type: "number" },
|
|
1125
|
+
nextCursor: { type: "string" },
|
|
1126
|
+
processed: { type: "number" },
|
|
1127
|
+
skipped: { type: "number" }
|
|
1128
|
+
},
|
|
1129
|
+
required: ["elapsedMs", "errors"],
|
|
1130
|
+
additionalProperties: false
|
|
1131
|
+
},
|
|
1132
|
+
status: { type: "string", enum: [MCP_STATUS_COMPLETED, MCP_STATUS_ERROR] }
|
|
1133
|
+
},
|
|
1134
|
+
required: ["data", "progress", "status"],
|
|
1135
|
+
additionalProperties: false
|
|
1136
|
+
});
|
|
1137
|
+
var emptyMcpInputSchema = {
|
|
1138
|
+
type: "object",
|
|
1139
|
+
properties: {},
|
|
1140
|
+
required: [],
|
|
1141
|
+
additionalProperties: false
|
|
1142
|
+
};
|
|
1143
|
+
|
|
1144
|
+
// src/mcp/router.ts
|
|
1145
|
+
var createCommandMcpRoute = ({
|
|
1146
|
+
command,
|
|
1147
|
+
handler,
|
|
1148
|
+
inputSchema,
|
|
1149
|
+
outputSchema
|
|
1150
|
+
}) => ({
|
|
1151
|
+
command,
|
|
1152
|
+
handler,
|
|
1153
|
+
inputSchema,
|
|
1154
|
+
outputSchema
|
|
1155
|
+
});
|
|
1156
|
+
var commandMcpRouteToTool = (route, prefix) => ({
|
|
1157
|
+
name: commandNameToMcpToolName(route.command.name, prefix),
|
|
1158
|
+
description: route.command.description,
|
|
1159
|
+
inputSchema: z3.toJSONSchema(route.inputSchema),
|
|
1160
|
+
outputSchema: mcpToolOutputSchema(route.outputSchema),
|
|
1161
|
+
annotations: commandMcpAnnotations(route.command)
|
|
1162
|
+
});
|
|
1163
|
+
var commandNameToMcpToolName = (name, prefix) => {
|
|
1164
|
+
const baseName = name.replaceAll(COMMAND_NAME_SEPARATOR, TOOL_NAME_SEPARATOR);
|
|
1165
|
+
return prefix ? `${prefix}_${baseName}` : baseName;
|
|
1166
|
+
};
|
|
1167
|
+
var createCommandMcpRouter = ({ prefix, routes }) => {
|
|
1168
|
+
const mcpRoutes = routes.filter((route) => route.command.mcp);
|
|
1169
|
+
const toolRoutes = mcpRoutes.filter((route) => isCommandMcpToolMetadata(route.command.mcp));
|
|
1170
|
+
const resourceRoutes = mcpRoutes.flatMap(commandMcpRouteToResourceRoute);
|
|
1171
|
+
return {
|
|
1172
|
+
tools: toolRoutes.map((route) => commandMcpRouteToTool(route, prefix)),
|
|
1173
|
+
resources: resourceRoutes.filter((route) => !isResourceTemplate(route.uriTemplate)).map(commandResourceRouteToResource),
|
|
1174
|
+
resourceTemplates: resourceRoutes.filter((route) => isResourceTemplate(route.uriTemplate)).map(commandResourceRouteToResourceTemplate),
|
|
1175
|
+
callTool: async (params) => {
|
|
1176
|
+
const toolCall = params;
|
|
1177
|
+
const route = toolRoutes.find(
|
|
1178
|
+
(candidate) => toolCall.name === commandNameToMcpToolName(candidate.command.name, prefix)
|
|
1179
|
+
);
|
|
1180
|
+
if (!route) {
|
|
1181
|
+
return throwUnknownTool(toolCall.name);
|
|
1182
|
+
}
|
|
1183
|
+
const input = route.inputSchema.parse(toolCall.arguments ?? {});
|
|
1184
|
+
const data = route.outputSchema.parse(await route.handler(input));
|
|
1185
|
+
return { data, progress: commandProgressSummary(data, route.command) };
|
|
1186
|
+
},
|
|
1187
|
+
readResource: async (params) => {
|
|
1188
|
+
const resourceRead = params;
|
|
1189
|
+
const routeMatch = resourceRoutes.map((route) => ({ input: commandResourceInput(route, resourceRead.uri), route })).find((candidate) => candidate.input !== void 0);
|
|
1190
|
+
if (!routeMatch?.input) {
|
|
1191
|
+
throw new Error(`Unknown resource: ${resourceRead.uri ?? EMPTY_DISPLAY_VALUE2}`);
|
|
1192
|
+
}
|
|
1193
|
+
return routeMatch.route.command.outputSchema.parse(
|
|
1194
|
+
await routeMatch.route.handler(routeMatch.input)
|
|
1195
|
+
);
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
};
|
|
1199
|
+
var commandMcpAnnotations = (command) => {
|
|
1200
|
+
const mcp = command.mcp;
|
|
1201
|
+
if (!isCommandMcpToolMetadata(mcp)) return void 0;
|
|
1202
|
+
return {
|
|
1203
|
+
readOnlyHint: mcp.readOnly,
|
|
1204
|
+
destructiveHint: mcp.destructive,
|
|
1205
|
+
idempotentHint: mcp.idempotent,
|
|
1206
|
+
openWorldHint: mcp.openWorld,
|
|
1207
|
+
requiresConfirmation: mcp.requiresConfirmation,
|
|
1208
|
+
sideEffects: mcp.sideEffects
|
|
1209
|
+
};
|
|
1210
|
+
};
|
|
1211
|
+
|
|
1212
|
+
// src/command/adapters.ts
|
|
1213
|
+
function createCommandAdapters({
|
|
1214
|
+
handler,
|
|
1215
|
+
metadata,
|
|
1216
|
+
print
|
|
1217
|
+
}) {
|
|
1218
|
+
const parseInput = ({ args, options }) => metadata.inputSchema.parse(commandActionInput(metadata, args, options));
|
|
1219
|
+
const run = async (input, context) => {
|
|
1220
|
+
if (context === void 0) {
|
|
1221
|
+
return handler(input);
|
|
1222
|
+
}
|
|
1223
|
+
return handler(context, input);
|
|
1224
|
+
};
|
|
1225
|
+
return {
|
|
1226
|
+
metadata,
|
|
1227
|
+
cli: (program, context) => {
|
|
1228
|
+
registerCommand(program, metadata).action(async ({ args, options }) => {
|
|
1229
|
+
const input = parseInput({ args, options });
|
|
1230
|
+
const getContext = context?.getContext;
|
|
1231
|
+
const resolvedContext = getContext ? await getContext() : void 0;
|
|
1232
|
+
const output = await run(input, resolvedContext);
|
|
1233
|
+
await print?.(output, input, resolvedContext);
|
|
1234
|
+
return typeof output === "number" ? output : void 0;
|
|
1235
|
+
});
|
|
1236
|
+
},
|
|
1237
|
+
handler,
|
|
1238
|
+
mcp: (getContext) => createCommandMcpRoute({
|
|
1239
|
+
command: metadata,
|
|
1240
|
+
inputSchema: metadata.inputSchema,
|
|
1241
|
+
outputSchema: metadata.outputSchema,
|
|
1242
|
+
handler: async (args) => run(args, getContext ? await getContext() : void 0)
|
|
1243
|
+
})
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// src/docs/readme.ts
|
|
1248
|
+
import { readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
1249
|
+
import { join as join4 } from "path";
|
|
1250
|
+
var generateReadmeCommandDocs = async ({
|
|
1251
|
+
binName,
|
|
1252
|
+
commandDefinitions = [],
|
|
1253
|
+
commandsDir = join4(process.cwd(), "src", "commands"),
|
|
1254
|
+
markerName = "COMMANDS",
|
|
1255
|
+
readmePath = "README.md"
|
|
1256
|
+
}) => {
|
|
1257
|
+
const readme = readFileSync2(readmePath, "utf8");
|
|
1258
|
+
const loadedCommandDefinitions = commandDefinitionsFromModules(
|
|
1259
|
+
await loadCommandModules(commandsDir)
|
|
1260
|
+
);
|
|
1261
|
+
const generated = formatCommandDocs(
|
|
1262
|
+
[...commandDefinitions, ...loadedCommandDefinitions],
|
|
1263
|
+
binName
|
|
1264
|
+
);
|
|
1265
|
+
writeFileSync(readmePath, replaceMarker(readme, markerName, generated), "utf8");
|
|
1266
|
+
};
|
|
1267
|
+
var formatCommandDocs = (commands, binName) => {
|
|
1268
|
+
const visibleCommands = commands.filter(isVisibleCommand).sort(commandSort);
|
|
1269
|
+
const groups = [...parentCommands2(visibleCommands)].map(
|
|
1270
|
+
([parent, subcommands]) => parentCommandDocs(parent, subcommands, binName)
|
|
1271
|
+
);
|
|
1272
|
+
const standaloneCommands = visibleCommands.filter((command) => !command.name.includes(" "));
|
|
1273
|
+
if (standaloneCommands.length > 0) groups.push(otherCommandDocs(standaloneCommands, binName));
|
|
1274
|
+
const lines = groups.flatMap(
|
|
1275
|
+
(commandLines, index) => index === 0 ? commandLines : ["", ...commandLines]
|
|
1276
|
+
);
|
|
1277
|
+
return ["```sh", ...lines, "```"].join("\n");
|
|
1278
|
+
};
|
|
1279
|
+
var isVisibleCommand = (command) => command.config?.visible !== false;
|
|
1280
|
+
var commandSort = (left, right) => (left.order ?? 0) - (right.order ?? 0) || left.name.localeCompare(right.name);
|
|
1281
|
+
var parentCommands2 = (commands) => {
|
|
1282
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1283
|
+
for (const command of commands) {
|
|
1284
|
+
const [parent, subcommand] = command.name.split(" ");
|
|
1285
|
+
if (!parent || !subcommand) continue;
|
|
1286
|
+
groups.set(parent, [...groups.get(parent) ?? [], command]);
|
|
1287
|
+
}
|
|
1288
|
+
return [...groups.entries()].sort(([left], [right]) => left.localeCompare(right));
|
|
1289
|
+
};
|
|
1290
|
+
var parentCommandDocs = (parent, commands, binName) => [`# ${parent} commands`, ...commands.flatMap((command) => commandDocs(command, binName))];
|
|
1291
|
+
var otherCommandDocs = (commands, binName) => [
|
|
1292
|
+
"# other commands",
|
|
1293
|
+
...commands.flatMap((command) => commandDocs(command, binName))
|
|
1294
|
+
];
|
|
1295
|
+
var commandDocs = (command, binName) => [
|
|
1296
|
+
`${binName} ${command.name}${usageSuffix(command)}`
|
|
1297
|
+
];
|
|
1298
|
+
var usageSuffix = (command) => {
|
|
1299
|
+
const args = command.arguments?.map((arg) => arg.synopsis) ?? [];
|
|
1300
|
+
const options = command.options?.map((option) => optionUsage(option)) ?? [];
|
|
1301
|
+
const usage = [...args, ...options];
|
|
1302
|
+
return usage.length > 0 ? ` ${usage.join(" ")}` : "";
|
|
1303
|
+
};
|
|
1304
|
+
var optionUsage = (option) => {
|
|
1305
|
+
const synopsis = option.value ? commandOptionSynopsis(option) : `--${option.name}`;
|
|
1306
|
+
return option.config?.required ? synopsis : `[${synopsis}]`;
|
|
1307
|
+
};
|
|
1308
|
+
var replaceMarker = (source, markerName, replacement) => {
|
|
1309
|
+
const startMarker = `<!-- <DYNFIELD:${markerName}> -->`;
|
|
1310
|
+
const endMarker = `<!-- </DYNFIELD:${markerName}> -->`;
|
|
1311
|
+
const hasOneMarkerPair = countOccurrences(source, startMarker) === 1 && countOccurrences(source, endMarker) === 1;
|
|
1312
|
+
if (!hasOneMarkerPair) throw new Error(`${readmeMarkerError(startMarker, endMarker)}`);
|
|
1313
|
+
const before = source.slice(0, source.indexOf(startMarker) + startMarker.length);
|
|
1314
|
+
const after = source.slice(source.indexOf(endMarker));
|
|
1315
|
+
return `${before}
|
|
1316
|
+
${replacement}
|
|
1317
|
+
${after}`;
|
|
1318
|
+
};
|
|
1319
|
+
var readmeMarkerError = (startMarker, endMarker) => `README must contain one ${startMarker} and one ${endMarker}`;
|
|
1320
|
+
var countOccurrences = (source, value) => source.split(value).length - 1;
|
|
1321
|
+
|
|
1322
|
+
// src/mcp/command-server.ts
|
|
1323
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
1324
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
1325
|
+
|
|
1326
|
+
// src/mcp/server.ts
|
|
1327
|
+
import { createInterface } from "readline";
|
|
1328
|
+
var createSingleToolMcpServer = ({
|
|
1329
|
+
serverName,
|
|
1330
|
+
tool,
|
|
1331
|
+
callTool
|
|
1332
|
+
}) => {
|
|
1333
|
+
return createMcpServer({
|
|
1334
|
+
name: serverName,
|
|
1335
|
+
tools: [tool],
|
|
1336
|
+
callTool: (params) => {
|
|
1337
|
+
const toolCall = params;
|
|
1338
|
+
assertToolName(tool.name, toolCall.name);
|
|
1339
|
+
return callTool(toolCall.arguments ?? {});
|
|
1340
|
+
}
|
|
1341
|
+
});
|
|
1342
|
+
};
|
|
1343
|
+
var createMcpServer = ({
|
|
1344
|
+
name,
|
|
1345
|
+
tools,
|
|
1346
|
+
resources = [],
|
|
1347
|
+
resourceTemplates = [],
|
|
1348
|
+
callTool,
|
|
1349
|
+
readResource
|
|
1350
|
+
}) => {
|
|
1351
|
+
const send = (message) => {
|
|
1352
|
+
process.stdout.write(`${JSON.stringify(message)}
|
|
1353
|
+
`);
|
|
1354
|
+
};
|
|
1355
|
+
const result = (id, value) => {
|
|
1356
|
+
send({ jsonrpc: JSON_RPC_VERSION, id, result: value });
|
|
1357
|
+
};
|
|
1358
|
+
const error = (id, code, message) => {
|
|
1359
|
+
send({ jsonrpc: JSON_RPC_VERSION, id, error: { code, message } });
|
|
1360
|
+
};
|
|
1361
|
+
const handleRequest = async (request) => {
|
|
1362
|
+
if (request.method === MCP_METHOD_INITIALIZE) {
|
|
1363
|
+
result(request.id, {
|
|
1364
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
1365
|
+
capabilities: { resources: {}, tools: {} },
|
|
1366
|
+
serverInfo: { name, version: DEFAULT_MCP_SERVER_VERSION }
|
|
1367
|
+
});
|
|
1368
|
+
return;
|
|
1369
|
+
}
|
|
1370
|
+
if (request.method === MCP_METHOD_TOOLS_LIST) {
|
|
1371
|
+
result(request.id, { tools });
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
if (request.method === MCP_METHOD_RESOURCES_LIST) {
|
|
1375
|
+
result(request.id, { resources });
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
if (request.method === MCP_METHOD_RESOURCES_TEMPLATES_LIST) {
|
|
1379
|
+
result(request.id, { resourceTemplates });
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1382
|
+
if (request.method === MCP_METHOD_RESOURCES_READ) {
|
|
1383
|
+
if (!readResource) {
|
|
1384
|
+
error(
|
|
1385
|
+
request.id,
|
|
1386
|
+
JSON_RPC_METHOD_NOT_FOUND,
|
|
1387
|
+
`Method not found: ${MCP_METHOD_RESOURCES_READ}`
|
|
1388
|
+
);
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
const startedAt = Date.now();
|
|
1392
|
+
try {
|
|
1393
|
+
result(request.id, resourceResult(request.params, await readResource(request.params)));
|
|
1394
|
+
} catch (caught) {
|
|
1395
|
+
result(request.id, toolErrorResult(caught, startedAt));
|
|
1396
|
+
}
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
if (request.method === MCP_METHOD_TOOLS_CALL) {
|
|
1400
|
+
const startedAt = Date.now();
|
|
1401
|
+
try {
|
|
1402
|
+
result(request.id, toolResult(await callTool(request.params), startedAt));
|
|
1403
|
+
} catch (caught) {
|
|
1404
|
+
result(request.id, toolErrorResult(caught, startedAt));
|
|
1405
|
+
}
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
if (request.id !== void 0) {
|
|
1409
|
+
error(
|
|
1410
|
+
request.id,
|
|
1411
|
+
JSON_RPC_METHOD_NOT_FOUND,
|
|
1412
|
+
`Method not found: ${request.method ?? EMPTY_DISPLAY_VALUE2}`
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1415
|
+
};
|
|
1416
|
+
return {
|
|
1417
|
+
start: async () => {
|
|
1418
|
+
const input = createInterface({ input: process.stdin });
|
|
1419
|
+
for await (const line of input) {
|
|
1420
|
+
if (!line.trim()) continue;
|
|
1421
|
+
try {
|
|
1422
|
+
await handleRequest(JSON.parse(line));
|
|
1423
|
+
} catch (caught) {
|
|
1424
|
+
error(
|
|
1425
|
+
void 0,
|
|
1426
|
+
JSON_RPC_INTERNAL_ERROR,
|
|
1427
|
+
caught instanceof Error ? caught.message : String(caught)
|
|
1428
|
+
);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
};
|
|
1434
|
+
|
|
1435
|
+
// src/mcp/command-server.ts
|
|
1436
|
+
var loadCommandMcpRoutes = async (commandsDir, getContext = () => void 0) => {
|
|
1437
|
+
const modules = await loadCommandModules(commandsDir);
|
|
1438
|
+
const factories = commandExportsFromModules(
|
|
1439
|
+
modules,
|
|
1440
|
+
(_name, value) => isCommandAdapterExport(value)
|
|
1441
|
+
).flatMap((command) => command.mcp ? [command.mcp] : []);
|
|
1442
|
+
return factories.map((factory) => factory(getContext)).filter((route) => route.command.mcp);
|
|
1443
|
+
};
|
|
1444
|
+
var createCommandMcpServer = async ({
|
|
1445
|
+
commandsDir,
|
|
1446
|
+
getContext,
|
|
1447
|
+
importMetaUrl,
|
|
1448
|
+
name,
|
|
1449
|
+
prefix
|
|
1450
|
+
}) => {
|
|
1451
|
+
const commandDirectory = commandsDir ?? join5(dirname3(fileURLToPath4(importMetaUrl)), DEFAULT_COMMANDS_DIR);
|
|
1452
|
+
const { tools, resources, resourceTemplates, callTool, readResource } = createCommandMcpRouter({
|
|
1453
|
+
prefix,
|
|
1454
|
+
routes: await loadCommandMcpRoutes(commandDirectory, getContext)
|
|
1455
|
+
});
|
|
1456
|
+
return createMcpServer({ name, tools, resources, resourceTemplates, callTool, readResource });
|
|
1457
|
+
};
|
|
1458
|
+
var startCommandMcpServer = async (options) => {
|
|
1459
|
+
await (await createCommandMcpServer(options)).start();
|
|
1460
|
+
};
|
|
1461
|
+
var startPackageCommandMcpServer = async ({
|
|
1462
|
+
importMetaUrl,
|
|
1463
|
+
mcpServerPrefix,
|
|
1464
|
+
name,
|
|
1465
|
+
prefix,
|
|
1466
|
+
...options
|
|
1467
|
+
}) => {
|
|
1468
|
+
const metadata = packageCommandMetadata(importMetaUrl, { mcpServerPrefix });
|
|
1469
|
+
await startCommandMcpServer({
|
|
1470
|
+
...options,
|
|
1471
|
+
importMetaUrl,
|
|
1472
|
+
name: name ?? metadata.mcpServerName,
|
|
1473
|
+
prefix: prefix ?? metadata.mcpPrefix
|
|
1474
|
+
});
|
|
1475
|
+
};
|
|
1476
|
+
|
|
1477
|
+
// src/scripts/dev-command.ts
|
|
1478
|
+
import { mkdirSync, rmSync as rmSync2 } from "fs";
|
|
1479
|
+
import { join as join7 } from "path";
|
|
1480
|
+
|
|
1481
|
+
// src/scripts/shims.ts
|
|
1482
|
+
import { execFileSync } from "child_process";
|
|
1483
|
+
import { chmodSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1484
|
+
import { homedir } from "os";
|
|
1485
|
+
import { join as join6 } from "path";
|
|
1486
|
+
var POSIX_SHIM_MODE = 493;
|
|
1487
|
+
var WINDOWS_PLATFORM = "win32";
|
|
1488
|
+
var NPM_COMMAND = "npm";
|
|
1489
|
+
var NPM_WINDOWS_COMMAND = "npm.cmd";
|
|
1490
|
+
var NPM_PREFIX_ARGS = ["config", "get", "prefix"];
|
|
1491
|
+
var COMMAND_OUTPUT_ENCODING = "utf8";
|
|
1492
|
+
var WINDOWS_NPM_DIR = ["AppData", "Roaming", "npm"];
|
|
1493
|
+
var NODE_MODULES_BIN = ["node_modules", ".bin"];
|
|
1494
|
+
var TSX_BIN = "tsx";
|
|
1495
|
+
var TSX_WINDOWS_BIN = "tsx.cmd";
|
|
1496
|
+
var installCommandShim = (binDir, config) => {
|
|
1497
|
+
if (process.platform === WINDOWS_PLATFORM) {
|
|
1498
|
+
installWindowsShim(binDir, config);
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
installPosixShim(binDir, config);
|
|
1502
|
+
};
|
|
1503
|
+
var getBinDir = (envName) => {
|
|
1504
|
+
const envValue = process.env[envName];
|
|
1505
|
+
if (envValue) {
|
|
1506
|
+
return envValue;
|
|
1507
|
+
}
|
|
1508
|
+
if (process.platform === WINDOWS_PLATFORM) {
|
|
1509
|
+
return getNpmPrefix() ?? join6(homedir(), ...WINDOWS_NPM_DIR);
|
|
1510
|
+
}
|
|
1511
|
+
return join6(homedir(), ".local", "bin");
|
|
1512
|
+
};
|
|
1513
|
+
var installPosixShim = (binDir, config) => {
|
|
1514
|
+
const target = join6(binDir, config.commandName);
|
|
1515
|
+
rmSync(target, { force: true });
|
|
1516
|
+
writeFileSync2(target, getPosixShim(config));
|
|
1517
|
+
chmodSync(target, POSIX_SHIM_MODE);
|
|
1518
|
+
};
|
|
1519
|
+
var installWindowsShim = (binDir, config) => {
|
|
1520
|
+
const target = join6(binDir, `${config.commandName}.cmd`);
|
|
1521
|
+
rmSync(target, { force: true });
|
|
1522
|
+
writeFileSync2(target, getWindowsShim(config));
|
|
1523
|
+
};
|
|
1524
|
+
var getNpmPrefix = () => {
|
|
1525
|
+
try {
|
|
1526
|
+
return execFileSync(
|
|
1527
|
+
process.platform === WINDOWS_PLATFORM ? NPM_WINDOWS_COMMAND : NPM_COMMAND,
|
|
1528
|
+
NPM_PREFIX_ARGS,
|
|
1529
|
+
{
|
|
1530
|
+
encoding: COMMAND_OUTPUT_ENCODING,
|
|
1531
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1532
|
+
}
|
|
1533
|
+
).trim();
|
|
1534
|
+
} catch {
|
|
1535
|
+
return null;
|
|
1536
|
+
}
|
|
1537
|
+
};
|
|
1538
|
+
var getPosixShim = (config) => {
|
|
1539
|
+
return `#!/usr/bin/env sh
|
|
1540
|
+
set -eu
|
|
1541
|
+
export ${config.programNameEnvName}=${config.commandName}
|
|
1542
|
+
exec ${shellQuote(join6(config.packageDir, ...NODE_MODULES_BIN, TSX_BIN))} ${shellQuote(config.cliPath)} "$@"
|
|
1543
|
+
`;
|
|
1544
|
+
};
|
|
1545
|
+
var getWindowsShim = (config) => {
|
|
1546
|
+
return `@echo off
|
|
1547
|
+
set "${config.programNameEnvName}=${config.commandName}"
|
|
1548
|
+
"${join6(config.packageDir, ...NODE_MODULES_BIN, TSX_WINDOWS_BIN)}" "${config.cliPath}" %*
|
|
1549
|
+
`;
|
|
1550
|
+
};
|
|
1551
|
+
var shellQuote = (value) => {
|
|
1552
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
// src/scripts/dev-command.ts
|
|
1556
|
+
var DEV_BIN_DIR_ENV_SUFFIX = "_DEV_BIN_DIR";
|
|
1557
|
+
var SOURCE_CLI_PATH = "src/cli.ts";
|
|
1558
|
+
var installDevCommand = (config) => {
|
|
1559
|
+
const binDir = getBinDir(config.binDirEnvName);
|
|
1560
|
+
mkdirSync(binDir, { recursive: true });
|
|
1561
|
+
installCommandShim(binDir, config);
|
|
1562
|
+
};
|
|
1563
|
+
var installPackageDevCommand = (importMetaUrl, options) => {
|
|
1564
|
+
installDevCommand(packageDevCommandConfig(importMetaUrl, options));
|
|
1565
|
+
};
|
|
1566
|
+
var installPackageDevCommands = (importMetaUrl, options) => {
|
|
1567
|
+
for (const commandName of options.commandNames) {
|
|
1568
|
+
installPackageDevCommand(importMetaUrl, { commandName });
|
|
1569
|
+
}
|
|
1570
|
+
};
|
|
1571
|
+
var uninstallDevCommand = (config) => {
|
|
1572
|
+
const binDir = getBinDir(config.binDirEnvName);
|
|
1573
|
+
rmSync2(join7(binDir, config.commandName), { force: true });
|
|
1574
|
+
rmSync2(join7(binDir, `${config.commandName}.cmd`), { force: true });
|
|
1575
|
+
};
|
|
1576
|
+
var uninstallPackageDevCommand = (importMetaUrl, options) => {
|
|
1577
|
+
const { binDirEnvName, commandName } = packageDevCommandConfig(importMetaUrl, options);
|
|
1578
|
+
uninstallDevCommand({ binDirEnvName, commandName });
|
|
1579
|
+
};
|
|
1580
|
+
var uninstallPackageDevCommands = (importMetaUrl, options) => {
|
|
1581
|
+
for (const commandName of options.commandNames) {
|
|
1582
|
+
uninstallPackageDevCommand(importMetaUrl, { commandName });
|
|
1583
|
+
}
|
|
1584
|
+
};
|
|
1585
|
+
var packageDevCommandConfig = (importMetaUrl, options) => {
|
|
1586
|
+
const packageDir = packageRoot(importMetaUrl);
|
|
1587
|
+
const packageJson = readPackageJson(packageDir);
|
|
1588
|
+
const appEnvPrefix = packageEnvPrefix(packageJson.name);
|
|
1589
|
+
return {
|
|
1590
|
+
binDirEnvName: `${appEnvPrefix}${DEV_BIN_DIR_ENV_SUFFIX}`,
|
|
1591
|
+
cliPath: join7(packageDir, SOURCE_CLI_PATH),
|
|
1592
|
+
commandName: options.commandName,
|
|
1593
|
+
packageDir,
|
|
1594
|
+
programNameEnvName: `${appEnvPrefix}${PROGRAM_NAME_ENV_SUFFIX}`
|
|
1595
|
+
};
|
|
1596
|
+
};
|
|
1597
|
+
export {
|
|
1598
|
+
DEFAULT_COMMANDS_DIR,
|
|
1599
|
+
PROGRAM_NAME_ENV_SUFFIX,
|
|
1600
|
+
PackageManager,
|
|
1601
|
+
assertToolName,
|
|
1602
|
+
commandActionInput,
|
|
1603
|
+
commandDefinitionToInputSchema,
|
|
1604
|
+
commandDefinitionToZodInputSchema,
|
|
1605
|
+
commandDefinitionsFromModules,
|
|
1606
|
+
commandExportsFromModules,
|
|
1607
|
+
commandInputString,
|
|
1608
|
+
commandInputValue,
|
|
1609
|
+
commandMcpRouteToResourceRoute,
|
|
1610
|
+
commandMcpRouteToTool,
|
|
1611
|
+
commandNameToMcpToolName,
|
|
1612
|
+
commandOptionSynopsis,
|
|
1613
|
+
commandResourceInput,
|
|
1614
|
+
commandResourceRouteToResource,
|
|
1615
|
+
commandResourceRouteToResourceTemplate,
|
|
1616
|
+
createCliRunner,
|
|
1617
|
+
createCommandAdapters,
|
|
1618
|
+
createCommandCliRunner,
|
|
1619
|
+
createCommandMcpRoute,
|
|
1620
|
+
createCommandMcpRouter,
|
|
1621
|
+
createCommandMcpServer,
|
|
1622
|
+
createCommandProgram,
|
|
1623
|
+
createMcpServer,
|
|
1624
|
+
createPackageCommandCliRunner,
|
|
1625
|
+
createSingleToolMcpServer,
|
|
1626
|
+
defineCommand,
|
|
1627
|
+
emptyMcpInputSchema,
|
|
1628
|
+
formatCommandDocs,
|
|
1629
|
+
generateReadmeCommandDocs,
|
|
1630
|
+
getBinDir,
|
|
1631
|
+
getPackageManagerFromPath,
|
|
1632
|
+
getProgramBin,
|
|
1633
|
+
getProgramConstructor,
|
|
1634
|
+
installCommandShim,
|
|
1635
|
+
installDevCommand,
|
|
1636
|
+
installPackageDevCommand,
|
|
1637
|
+
installPackageDevCommands,
|
|
1638
|
+
isCommandAdapterExport,
|
|
1639
|
+
isCommandMcpResourceMetadata,
|
|
1640
|
+
isCommandMcpToolMetadata,
|
|
1641
|
+
isDirectRun,
|
|
1642
|
+
isGlobalHelpRequest,
|
|
1643
|
+
isResourceTemplate,
|
|
1644
|
+
loadCommandMcpRoutes,
|
|
1645
|
+
loadCommandModules,
|
|
1646
|
+
loadCommandModulesFromFiles,
|
|
1647
|
+
mcpToolOutputSchema,
|
|
1648
|
+
normalizeCommandInputAliases,
|
|
1649
|
+
packageBinEntry,
|
|
1650
|
+
packageCommandMetadata,
|
|
1651
|
+
packageEnvPrefix,
|
|
1652
|
+
packageRoot,
|
|
1653
|
+
printProgramHelp,
|
|
1654
|
+
readPackageJson,
|
|
1655
|
+
registerCliCommandsFromDirectory,
|
|
1656
|
+
registerCommand,
|
|
1657
|
+
registerCompletionCommand,
|
|
1658
|
+
registerParentCommandsFromDefinitions,
|
|
1659
|
+
registerUpdateCommand,
|
|
1660
|
+
resourceResult,
|
|
1661
|
+
setProgramExamples,
|
|
1662
|
+
shortPackageName,
|
|
1663
|
+
startCommandMcpServer,
|
|
1664
|
+
startPackageCommandMcpServer,
|
|
1665
|
+
throwUnknownTool,
|
|
1666
|
+
uninstallDevCommand,
|
|
1667
|
+
uninstallPackageDevCommand,
|
|
1668
|
+
uninstallPackageDevCommands,
|
|
1669
|
+
z4 as z
|
|
1670
|
+
};
|
|
1671
|
+
//# sourceMappingURL=index.js.map
|