@procedures/mark 0.0.0-stage → 0.2.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 +36 -0
- package/LICENSE +21 -0
- package/README.md +799 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/args.d.ts +77 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +351 -0
- package/dist/args.js.map +1 -0
- package/dist/ask.d.ts +48 -0
- package/dist/ask.d.ts.map +1 -0
- package/dist/ask.js +91 -0
- package/dist/ask.js.map +1 -0
- package/dist/bin.d.ts +9 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +10 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +61 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +535 -0
- package/dist/cli.js.map +1 -0
- package/dist/client-mode.d.ts +21 -0
- package/dist/client-mode.d.ts.map +1 -0
- package/dist/client-mode.js +75 -0
- package/dist/client-mode.js.map +1 -0
- package/dist/ecosystem.d.ts +67 -0
- package/dist/ecosystem.d.ts.map +1 -0
- package/dist/ecosystem.js +212 -0
- package/dist/ecosystem.js.map +1 -0
- package/dist/failure.d.ts +16 -0
- package/dist/failure.d.ts.map +1 -0
- package/dist/failure.js +47 -0
- package/dist/failure.js.map +1 -0
- package/dist/format.d.ts +30 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +125 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/lockfile.d.ts +26 -0
- package/dist/lockfile.d.ts.map +1 -0
- package/dist/lockfile.js +68 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/manifest-build.d.ts +7 -0
- package/dist/manifest-build.d.ts.map +1 -0
- package/dist/manifest-build.js +11 -0
- package/dist/manifest-build.js.map +1 -0
- package/dist/manifest.d.ts +57 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +140 -0
- package/dist/manifest.js.map +1 -0
- package/dist/manifest.json +20960 -0
- package/dist/parse.d.ts +143 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +509 -0
- package/dist/parse.js.map +1 -0
- package/dist/print.d.ts +42 -0
- package/dist/print.d.ts.map +1 -0
- package/dist/print.js +80 -0
- package/dist/print.js.map +1 -0
- package/dist/prompts.d.ts +58 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +124 -0
- package/dist/prompts.js.map +1 -0
- package/dist/repl.d.ts +34 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/repl.js +101 -0
- package/dist/repl.js.map +1 -0
- package/dist/server-mode.d.ts +37 -0
- package/dist/server-mode.d.ts.map +1 -0
- package/dist/server-mode.js +167 -0
- package/dist/server-mode.js.map +1 -0
- package/package.json +97 -3
- package/src/args.ts +440 -0
- package/src/ask.ts +119 -0
- package/src/bin.ts +11 -0
- package/src/cli.ts +600 -0
- package/src/client-mode.ts +90 -0
- package/src/ecosystem.ts +260 -0
- package/src/failure.ts +47 -0
- package/src/format.ts +177 -0
- package/src/index.ts +31 -0
- package/src/lockfile.ts +85 -0
- package/src/manifest-build.ts +12 -0
- package/src/manifest.ts +162 -0
- package/src/parse.ts +670 -0
- package/src/print.ts +108 -0
- package/src/prompts.ts +181 -0
- package/src/repl.ts +121 -0
- package/src/server-mode.ts +205 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Mark CLI
|
|
4
|
+
*
|
|
5
|
+
* A generic CLI that reflects registered procedures.
|
|
6
|
+
* Uses custom procedure-based routing with modern terminal utilities.
|
|
7
|
+
*/
|
|
8
|
+
import { print } from "./print.js";
|
|
9
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
10
|
+
import { dirname } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { fieldsOf, generateHelp, resultFieldsOf } from "./parse.js";
|
|
13
|
+
import { readFreshManifest, writeManifest } from "./manifest.js";
|
|
14
|
+
import { askMissing, canAsk, missingFields, processTerminal, terminalAsker } from "./ask.js";
|
|
15
|
+
import { formatOutput } from "./format.js";
|
|
16
|
+
import { loadEcosystemRegistry } from "./ecosystem.js";
|
|
17
|
+
import { startServerMode, parsePort, parseTransport } from "./server-mode.js";
|
|
18
|
+
import { tryClientMode } from "./client-mode.js";
|
|
19
|
+
import { startRepl } from "./repl.js";
|
|
20
|
+
import { findChildren, findProcedure, parseCommandLine, parseLeadingGlobals } from "./args.js";
|
|
21
|
+
import { failureOf } from "./failure.js";
|
|
22
|
+
/** The version of this package. This file is `dist/cli.js` (or `src/cli.ts` in the tests): the package.json is one folder up. */
|
|
23
|
+
const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
24
|
+
/**
|
|
25
|
+
* Convert procedure path to transport method. The core mapping is the one of every host: the
|
|
26
|
+
* last segment is the operation (deep dive architecture review 3.3). The core loads only for a
|
|
27
|
+
* run in this process: the help and a call to the CLI server do not need it.
|
|
28
|
+
*/
|
|
29
|
+
async function pathToMethod(path) {
|
|
30
|
+
const { pathToMethod: corePathToMethod } = await import("@procedures/client");
|
|
31
|
+
return corePathToMethod(path);
|
|
32
|
+
}
|
|
33
|
+
const OUTPUT_FORMATS = ["text", "json", "table", "streaming"];
|
|
34
|
+
/**
|
|
35
|
+
* Report a problem of the command line or of the command: print it and set exit code 1
|
|
36
|
+
*/
|
|
37
|
+
function fail(message, hint) {
|
|
38
|
+
print.error(message);
|
|
39
|
+
if (hint) {
|
|
40
|
+
print.info(hint);
|
|
41
|
+
}
|
|
42
|
+
process.exitCode = 1;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The message of a validation error: one line for each issue of a Zod error
|
|
46
|
+
*/
|
|
47
|
+
function validationMessage(error) {
|
|
48
|
+
const issues = error.issues;
|
|
49
|
+
if (Array.isArray(issues) && issues.length > 0) {
|
|
50
|
+
return issues
|
|
51
|
+
.map((issue) => `${(issue.path ?? []).join(".") || "input"}: ${issue.message ?? "invalid"}`)
|
|
52
|
+
.join("\n ");
|
|
53
|
+
}
|
|
54
|
+
return error instanceof Error ? error.message : String(error);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Show help for a path (either a command or a group). Returns false for an unknown path.
|
|
58
|
+
*/
|
|
59
|
+
function showHelp(procedures, path) {
|
|
60
|
+
const proc = findProcedure(procedures, path);
|
|
61
|
+
if (proc) {
|
|
62
|
+
// Show help for specific command with schema introspection (or the fields of the manifest)
|
|
63
|
+
const meta = (proc.metadata ?? {});
|
|
64
|
+
print.info(generateHelp(path, meta, fieldsOf(proc), resultFieldsOf(proc)));
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
// Show help for group
|
|
68
|
+
const children = findChildren(procedures, path);
|
|
69
|
+
if (children.length > 0) {
|
|
70
|
+
const groupName = path.join(" ");
|
|
71
|
+
print.info(`${groupName} commands:\n`);
|
|
72
|
+
// Direct children only
|
|
73
|
+
const directChildren = children.filter((p) => p.path.length === path.length + 1);
|
|
74
|
+
for (const child of directChildren) {
|
|
75
|
+
const meta = (child.metadata ?? {});
|
|
76
|
+
const cmdName = child.path[child.path.length - 1] ?? "";
|
|
77
|
+
const desc = meta.description ?? "";
|
|
78
|
+
print.info(` mark ${groupName} ${cmdName} ${desc}`);
|
|
79
|
+
}
|
|
80
|
+
// Child groups
|
|
81
|
+
const childGroups = new Set();
|
|
82
|
+
for (const child of children) {
|
|
83
|
+
if (child.path.length > path.length + 1) {
|
|
84
|
+
const groupSeg = child.path[path.length];
|
|
85
|
+
if (groupSeg)
|
|
86
|
+
childGroups.add(groupSeg);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const group of childGroups) {
|
|
90
|
+
print.info(` mark ${groupName} ${group} ${group} commands`);
|
|
91
|
+
}
|
|
92
|
+
print.info(`\nRun 'mark ${groupName} <command> --help' for more info.`);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
// Unknown command
|
|
96
|
+
fail(`Unknown command: mark ${path.join(" ")}`, "Run 'mark --help' for available commands.");
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Show root help
|
|
101
|
+
*/
|
|
102
|
+
function showRootHelp(procedures) {
|
|
103
|
+
print.info(`mark v${VERSION} - Development workflow automation\n`);
|
|
104
|
+
print.info("Commands:\n");
|
|
105
|
+
// Group by first path segment
|
|
106
|
+
const groups = new Map();
|
|
107
|
+
for (const proc of procedures) {
|
|
108
|
+
const group = proc.path[0] ?? "other";
|
|
109
|
+
if (!groups.has(group)) {
|
|
110
|
+
groups.set(group, []);
|
|
111
|
+
}
|
|
112
|
+
groups.get(group).push(proc);
|
|
113
|
+
}
|
|
114
|
+
for (const [group, procs] of groups) {
|
|
115
|
+
print.info(` ${group}`);
|
|
116
|
+
for (const proc of procs) {
|
|
117
|
+
const meta = (proc.metadata ?? {});
|
|
118
|
+
const cmdPath = proc.path.join(" ");
|
|
119
|
+
const desc = meta.description ?? "";
|
|
120
|
+
print.info(` mark ${cmdPath} ${desc}`);
|
|
121
|
+
}
|
|
122
|
+
print.info("");
|
|
123
|
+
}
|
|
124
|
+
print.info("Run 'mark <command> --help' for more information.");
|
|
125
|
+
print.info("Hosts: 'mark serve [--procedures pkgs] [--port N] [--expose patterns]' (the procedure server),");
|
|
126
|
+
print.info(" 'mark mcp' (the dev-tools MCP server over stdio).");
|
|
127
|
+
print.info("Modes: 'mark --server [--port N] [--host H] [--transport http|websocket|both]' and 'mark -i' (the REPL).");
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Initialize the CLI context (load ecosystem, create client)
|
|
131
|
+
* This is the expensive part (~4s). Call once, reuse many times.
|
|
132
|
+
*/
|
|
133
|
+
export async function initCli(verbose = false) {
|
|
134
|
+
const clientModule = await import("@procedures/client");
|
|
135
|
+
const { Client, LocalTransport } = clientModule;
|
|
136
|
+
// A registry of its own, from the module of each package (roadmap 3.1): not the global one
|
|
137
|
+
const { registry } = await loadEcosystemRegistry(verbose);
|
|
138
|
+
// The transport runs each procedure of the registry through invokeProcedure() (ARCHITECTURE-PROPOSALS P1).
|
|
139
|
+
// useRegistry(): exec() of a program (--json) uses the same registry.
|
|
140
|
+
const transport = new LocalTransport({ registry });
|
|
141
|
+
const client = new Client({ transport }).useRegistry(registry);
|
|
142
|
+
const procedures = registry.getAll();
|
|
143
|
+
return { client, procedures, verbose };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Execute a single command given argv tokens.
|
|
147
|
+
* Reusable by both CLI entry point and REPL.
|
|
148
|
+
*
|
|
149
|
+
* The exit code is 1 for an unknown command, a problem of the command line, invalid input, a
|
|
150
|
+
* thrown error, and a result that reports a failure (`success: false`, or an `exitCode` that is
|
|
151
|
+
* not 0: see failure.ts). Before, all of these exited with 0 (deep dive CLI-8).
|
|
152
|
+
*
|
|
153
|
+
* With a ManifestContext, the help and a call to the CLI server need no procedures: they load
|
|
154
|
+
* only when the command runs in this process (roadmap 1.3).
|
|
155
|
+
*/
|
|
156
|
+
export async function executeArgs(argv, ctx, options = {}) {
|
|
157
|
+
const procedures = "procedures" in ctx ? ctx.procedures : ctx.commands;
|
|
158
|
+
let loaded = "procedures" in ctx ? ctx : undefined;
|
|
159
|
+
const local = async () => (loaded ??= await ctx.load());
|
|
160
|
+
// Global flags, path and procedure input, converted by the field types (deep dive CLI-7, 9, 10, 11)
|
|
161
|
+
const parsed = parseCommandLine(argv, procedures);
|
|
162
|
+
const { path, procedure, globals } = parsed;
|
|
163
|
+
// An unknown command is the first problem to report
|
|
164
|
+
if (path.length > 0 && !procedure) {
|
|
165
|
+
const isGroup = findChildren(procedures, path).length > 0;
|
|
166
|
+
if (!isGroup || parsed.extraArguments.length > 0) {
|
|
167
|
+
const words = [...path, ...parsed.extraArguments.slice(0, 1)];
|
|
168
|
+
fail(`Unknown command: mark ${words.join(" ")}`, "Run 'mark --help' for available commands.");
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (parsed.errors.length > 0) {
|
|
173
|
+
for (const error of parsed.errors) {
|
|
174
|
+
print.error(error);
|
|
175
|
+
}
|
|
176
|
+
const helpPath = path.length > 0 ? `mark ${path.join(" ")} --help` : "mark --help";
|
|
177
|
+
print.info(`Run '${helpPath}' for the options.`);
|
|
178
|
+
process.exitCode = 1;
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// The modes start before the procedures load: here they are misplaced
|
|
182
|
+
if (globals.server || globals.interactive) {
|
|
183
|
+
fail("--server and -i start a mode of mark: give them alone, before any command.");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (globals.port !== undefined || globals.host !== undefined || globals.transport !== undefined) {
|
|
187
|
+
fail("--port, --host and --transport are options of --server.");
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (globals.version) {
|
|
191
|
+
print.info(`mark v${VERSION}`);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
// Output format: --format/-f, unless the procedure declares a flag of that name
|
|
195
|
+
const formatOverride = globals.format === undefined ? undefined : String(globals.format);
|
|
196
|
+
if (formatOverride !== undefined && !OUTPUT_FORMATS.includes(formatOverride)) {
|
|
197
|
+
fail(`Invalid format: ${formatOverride}. Valid formats: ${OUTPUT_FORMATS.join(", ")}`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// Handle --json flag for raw procedure reference execution
|
|
201
|
+
if (globals.json !== undefined) {
|
|
202
|
+
let parsedJson;
|
|
203
|
+
try {
|
|
204
|
+
parsedJson = JSON.parse(String(globals.json));
|
|
205
|
+
}
|
|
206
|
+
catch (e) {
|
|
207
|
+
fail(`Failed to parse --json input: ${e instanceof Error ? e.message : String(e)}`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (!parsedJson || typeof parsedJson !== "object" || !("$proc" in parsedJson)) {
|
|
211
|
+
fail('--json needs a procedure reference: an object with "$proc".');
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const { client } = await local();
|
|
216
|
+
const result = await client.exec(parsedJson);
|
|
217
|
+
formatOutput(print, result, "json");
|
|
218
|
+
if (failureOf(result)) {
|
|
219
|
+
process.exitCode = 1;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
fail(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
224
|
+
}
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Handle root help
|
|
228
|
+
if (path.length === 0) {
|
|
229
|
+
showRootHelp(procedures);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// Help for a command or a group (a group without a command shows its help too)
|
|
233
|
+
if (globals.help || !procedure) {
|
|
234
|
+
showHelp(procedures, path);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const meta = (procedure.metadata ?? {});
|
|
238
|
+
const outputFormat = (formatOverride ?? meta.output ?? "text");
|
|
239
|
+
// A required argument that is missing: in a terminal, mark asks for it (see ask.ts)
|
|
240
|
+
let input = parsed.input;
|
|
241
|
+
const missing = missingFields(fieldsOf(procedure), input);
|
|
242
|
+
if (missing.length > 0 && canAsk(globals["no-input"] === true, meta, options.terminal ?? processTerminal())) {
|
|
243
|
+
const asked = await askMissing(missing, input, options.ask ?? terminalAsker);
|
|
244
|
+
if (!asked.ok) {
|
|
245
|
+
fail(asked.cancelled ? "Cancelled" : `Invalid input for mark ${path.join(" ")}:\n ${asked.error}`);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
input = asked.input;
|
|
249
|
+
}
|
|
250
|
+
// A procedure of the registry validates the input here. A command of the manifest has no
|
|
251
|
+
// schema: the CLI server validates, or this process after the procedures load.
|
|
252
|
+
let validated = input;
|
|
253
|
+
let checked = false;
|
|
254
|
+
const validate = (target) => {
|
|
255
|
+
const schema = target.input;
|
|
256
|
+
try {
|
|
257
|
+
if (typeof schema?.parse === "function") {
|
|
258
|
+
validated = schema.parse(input);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
fail(`Invalid input for mark ${path.join(" ")}:\n ${validationMessage(error)}`, `Run 'mark ${path.join(" ")} --help' for the options.`);
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
checked = true;
|
|
266
|
+
return true;
|
|
267
|
+
};
|
|
268
|
+
if (loaded) {
|
|
269
|
+
if (!validate(procedure)) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
const stillMissing = missingFields(fieldsOf(procedure), input);
|
|
275
|
+
if (stillMissing.length > 0) {
|
|
276
|
+
const names = stillMissing.map((field) => `${field.name}: Required`).join("\n ");
|
|
277
|
+
fail(`Invalid input for mark ${path.join(" ")}:\n ${names}`, `Run 'mark ${path.join(" ")} --help' for the options.`);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// Each item prints when it arrives. A failed item makes the command fail.
|
|
282
|
+
let failure;
|
|
283
|
+
const printItem = (item) => {
|
|
284
|
+
formatOutput(print, item, outputFormat);
|
|
285
|
+
failure ??= failureOf(item);
|
|
286
|
+
};
|
|
287
|
+
const reportFailure = () => {
|
|
288
|
+
if (failure !== undefined) {
|
|
289
|
+
fail(`mark ${path.join(" ")} failed: ${failure}`);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
// Try client mode: connect to running server if available (unless --local)
|
|
293
|
+
if (!globals.local) {
|
|
294
|
+
const clientResult = await tryClientMode(path, validated, printItem);
|
|
295
|
+
if (clientResult !== null) {
|
|
296
|
+
if (clientResult.success) {
|
|
297
|
+
if (!clientResult.printed) {
|
|
298
|
+
printItem(clientResult.result);
|
|
299
|
+
}
|
|
300
|
+
reportFailure();
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
// The server ran (or started to run) the command and it failed. Running it again
|
|
304
|
+
// locally could repeat its side effects, so report the error instead.
|
|
305
|
+
fail(clientResult.error ?? "The command failed on the CLI server.");
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// The command runs in this process: the procedures load now (a ManifestContext)
|
|
310
|
+
let runtime;
|
|
311
|
+
try {
|
|
312
|
+
runtime = await local();
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
fail(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
const target = findProcedure(runtime.procedures, path);
|
|
319
|
+
if (!target) {
|
|
320
|
+
fail(`Unknown command: mark ${path.join(" ")}`, "Run 'mark --help' for available commands.");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (!checked && !validate(target)) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
let spinner;
|
|
328
|
+
if (outputFormat === "streaming") {
|
|
329
|
+
spinner = print.spin(`Running ${path.join(" ")}...`);
|
|
330
|
+
}
|
|
331
|
+
const method = await pathToMethod(path);
|
|
332
|
+
const { client } = runtime;
|
|
333
|
+
// A streaming procedure gives many items: print each one when it arrives. A
|
|
334
|
+
// request/response procedure gives one item, so its output does not change.
|
|
335
|
+
let items = 0;
|
|
336
|
+
for await (const item of client.stream(method, validated)) {
|
|
337
|
+
if (spinner && items === 0)
|
|
338
|
+
spinner.stop();
|
|
339
|
+
items++;
|
|
340
|
+
printItem(item);
|
|
341
|
+
}
|
|
342
|
+
if (spinner) {
|
|
343
|
+
if (failure === undefined) {
|
|
344
|
+
spinner.succeed(`${path.join(" ")} complete`);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
spinner.fail(`${path.join(" ")} failed`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
reportFailure();
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
fail(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const MCP_HELP = `Usage: mark mcp [options]
|
|
357
|
+
|
|
358
|
+
Start the dev-tools MCP server over stdio (the server of Claude Code's MCP configuration).
|
|
359
|
+
It has a registry of its own, from the modules of its bundles, and the host policy of an MCP
|
|
360
|
+
server: only the tools of the bundles, strict nested calls, and a time limit for each call.
|
|
361
|
+
|
|
362
|
+
Options:
|
|
363
|
+
--bundles <list> Comma-separated bundles (default: MCP_BUNDLES, or @procedures/bundle-mcp)
|
|
364
|
+
--tool-timeout <ms> The time limit of each tool call (default: MCP_TOOL_TIMEOUT_MS, or 600000)
|
|
365
|
+
--read-only Only the tools that change nothing (default: MCP_READ_ONLY)
|
|
366
|
+
--debug Write debug lines to stderr
|
|
367
|
+
-h, --help Show this help
|
|
368
|
+
|
|
369
|
+
\`mark mcp <procedure>\` runs an mcp.* procedure instead (mark mcp serve, mark mcp listTools).`;
|
|
370
|
+
/**
|
|
371
|
+
* Start the dev-tools MCP server (`mark mcp`). stdout carries the protocol: this function
|
|
372
|
+
* writes nothing to stdout, and the server sends console.log to stderr.
|
|
373
|
+
*/
|
|
374
|
+
async function startMcp(args) {
|
|
375
|
+
const { loadConfig, startDevToolsServer } = await import("@procedures/mcp-dev-tools");
|
|
376
|
+
const config = loadConfig();
|
|
377
|
+
for (let i = 0; i < args.length; i++) {
|
|
378
|
+
const arg = args[i];
|
|
379
|
+
const eq = arg.indexOf("=");
|
|
380
|
+
const name = eq === -1 ? arg : arg.slice(0, eq);
|
|
381
|
+
const value = () => {
|
|
382
|
+
if (eq !== -1)
|
|
383
|
+
return arg.slice(eq + 1);
|
|
384
|
+
const next = args[++i];
|
|
385
|
+
if (next === undefined)
|
|
386
|
+
throw new Error(`${name} needs a value`);
|
|
387
|
+
return next;
|
|
388
|
+
};
|
|
389
|
+
if (name === "-h" || name === "--help") {
|
|
390
|
+
process.stderr.write(`${MCP_HELP}\n`);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
else if (name === "--bundles") {
|
|
394
|
+
config.bundles = value().split(",").map((bundle) => bundle.trim()).filter(Boolean);
|
|
395
|
+
}
|
|
396
|
+
else if (name === "--tool-timeout") {
|
|
397
|
+
const ms = Number(value());
|
|
398
|
+
if (!Number.isFinite(ms) || ms < 0)
|
|
399
|
+
throw new Error(`--tool-timeout needs a number of milliseconds`);
|
|
400
|
+
config.toolTimeoutMs = ms;
|
|
401
|
+
}
|
|
402
|
+
else if (name === "--read-only") {
|
|
403
|
+
config.readOnly = true;
|
|
404
|
+
}
|
|
405
|
+
else if (name === "--debug") {
|
|
406
|
+
config.debug = true;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
throw new Error(`Unknown option of mark mcp: ${arg}. Run 'mark mcp --help'.`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
// The server reads stdin until the client closes it: the process stays alive until then
|
|
413
|
+
await startDevToolsServer(config);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Run the CLI
|
|
417
|
+
*/
|
|
418
|
+
async function run(argv) {
|
|
419
|
+
// The global flags before the command: read without loading the procedures
|
|
420
|
+
const leading = parseLeadingGlobals(argv);
|
|
421
|
+
if (leading.errors.length > 0) {
|
|
422
|
+
for (const error of leading.errors) {
|
|
423
|
+
print.error(error);
|
|
424
|
+
}
|
|
425
|
+
print.info("Run 'mark --help' for the options.");
|
|
426
|
+
process.exitCode = 1;
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const globals = leading.globals;
|
|
430
|
+
const verbose = globals.verbose === true;
|
|
431
|
+
// Handle --version early (no imports needed)
|
|
432
|
+
if (globals.version) {
|
|
433
|
+
print.info(`mark v${VERSION}`);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
// Handle --server flag: start server mode
|
|
437
|
+
if (globals.server) {
|
|
438
|
+
if (leading.rest.length > 0) {
|
|
439
|
+
fail(`--server takes no command: ${leading.rest.join(" ")}`);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
const port = globals.port === undefined ? 3000 : parsePort(String(globals.port));
|
|
443
|
+
// Loopback unless --host says otherwise (deep dive CLI-1)
|
|
444
|
+
const host = globals.host === undefined ? "127.0.0.1" : String(globals.host);
|
|
445
|
+
const transport = globals.transport === undefined ? "http" : parseTransport(String(globals.transport));
|
|
446
|
+
await startServerMode({ port, host, transport, verbose });
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
// Handle -i / --interactive flag: start REPL
|
|
450
|
+
if (globals.interactive) {
|
|
451
|
+
if (leading.rest.length > 0) {
|
|
452
|
+
fail(`-i takes no command: ${leading.rest.join(" ")}`);
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
await startRepl({ verbose });
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
// The front door (roadmap 2.3): `mark serve` starts the procedure server (the `server` CLI),
|
|
459
|
+
// and `mark mcp` starts the dev-tools MCP server over stdio (the server of impl-mcp-dev).
|
|
460
|
+
// `mark mcp <procedure>` still runs an mcp.* procedure (`mark mcp serve`, `mark mcp listTools`).
|
|
461
|
+
const [command, ...commandArgs] = leading.rest;
|
|
462
|
+
if (command === "serve") {
|
|
463
|
+
const { runServer } = await import("@procedures/server");
|
|
464
|
+
// A --procedures package resolves from the current folder, then from mark, which depends on
|
|
465
|
+
// every procedure package of the workspace
|
|
466
|
+
const markDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
467
|
+
await runServer(commandArgs, { resolveFrom: [process.cwd(), markDir] });
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
if (command === "mcp" && commandArgs.every((arg) => arg.startsWith("-"))) {
|
|
471
|
+
await startMcp(commandArgs);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
// The manifest gives the commands without the procedures: the help and a call to the CLI
|
|
475
|
+
// server do not load them (roadmap 1.3)
|
|
476
|
+
const manifest = readFreshManifest();
|
|
477
|
+
if (manifest) {
|
|
478
|
+
await executeArgs(argv, { commands: manifest.commands, verbose, load: () => initCli(verbose) });
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
// No manifest, or a stale one (a package was built again): load the procedures as before, and
|
|
482
|
+
// write the manifest for the next run. A failure to write costs only time.
|
|
483
|
+
const ctx = await initCli(verbose);
|
|
484
|
+
try {
|
|
485
|
+
await writeManifest(ctx.procedures);
|
|
486
|
+
}
|
|
487
|
+
catch (error) {
|
|
488
|
+
if (verbose) {
|
|
489
|
+
print.warning(`mark: the manifest was not written: ${error instanceof Error ? error.message : String(error)}`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
await executeArgs(argv, ctx);
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Run the CLI and report an error that escapes it as one line, with exit code 1. With
|
|
496
|
+
* `--verbose`, the stack follows. (Before, an error such as an invalid port showed only an
|
|
497
|
+
* unhandled-rejection stack: deep dive CLI-16.)
|
|
498
|
+
*/
|
|
499
|
+
export async function main(argv) {
|
|
500
|
+
try {
|
|
501
|
+
await run([...argv]);
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
print.error(error instanceof Error ? error.message : String(error));
|
|
505
|
+
if ((argv.includes("--verbose") || argv.includes("-V")) && error instanceof Error && error.stack) {
|
|
506
|
+
print.muted(error.stack);
|
|
507
|
+
}
|
|
508
|
+
process.exitCode = 1;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* True when Node runs this file itself (`node dist/cli.js`), and false when a module imports it.
|
|
513
|
+
* The `mark` bin is `dist/bin.js`. `dist/cli.js` stays runnable for the documented commands
|
|
514
|
+
* (`node packages/mark/dist/cli.js lib new <name>`).
|
|
515
|
+
*/
|
|
516
|
+
function isEntryPoint() {
|
|
517
|
+
const entry = process.argv[1];
|
|
518
|
+
if (!entry) {
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
try {
|
|
522
|
+
const self = fileURLToPath(import.meta.url);
|
|
523
|
+
const target = realpathSync(entry);
|
|
524
|
+
return process.platform === "win32" ? self.toLowerCase() === target.toLowerCase() : self === target;
|
|
525
|
+
}
|
|
526
|
+
catch {
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
// Importing @procedures/mark does not run the CLI (deep dive CLI-17)
|
|
531
|
+
if (isEntryPoint()) {
|
|
532
|
+
await main(process.argv.slice(2));
|
|
533
|
+
}
|
|
534
|
+
export { run };
|
|
535
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Client Mode
|
|
3
|
+
*
|
|
4
|
+
* Connects to a running CLI server and executes commands remotely.
|
|
5
|
+
* Falls back to local execution if no server is available.
|
|
6
|
+
*/
|
|
7
|
+
interface ClientModeResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
result?: unknown;
|
|
10
|
+
error?: string;
|
|
11
|
+
/** The onItem callback printed each item already */
|
|
12
|
+
printed?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Try to execute command via running server. The input is the procedure input that the CLI
|
|
16
|
+
* parsed and validated already.
|
|
17
|
+
* Returns null if no server available (should fall back to local)
|
|
18
|
+
*/
|
|
19
|
+
export declare function tryClientMode(path: string[], input: unknown, onItem?: (item: unknown) => void): Promise<ClientModeResult | null>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=client-mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-mode.d.ts","sourceRoot":"","sources":["../src/client-mode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,OAAO,EACd,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAC/B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA+DlC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Client Mode
|
|
3
|
+
*
|
|
4
|
+
* Connects to a running CLI server and executes commands remotely.
|
|
5
|
+
* Falls back to local execution if no server is available.
|
|
6
|
+
*/
|
|
7
|
+
import { currentBuild, findServer } from "./lockfile.js";
|
|
8
|
+
/**
|
|
9
|
+
* Try to execute command via running server. The input is the procedure input that the CLI
|
|
10
|
+
* parsed and validated already.
|
|
11
|
+
* Returns null if no server available (should fall back to local)
|
|
12
|
+
*/
|
|
13
|
+
export async function tryClientMode(path, input, onItem) {
|
|
14
|
+
// A running server of this build, started in this folder, that answers as the peer of its
|
|
15
|
+
// lockfile and has a token. Otherwise the CLI runs the command itself. (Before, any server
|
|
16
|
+
// with a live PID was used: relative paths resolved in the server's folder, an old build ran
|
|
17
|
+
// after a rebuild, and a reused PID broke every command: deep dive CLI-3, CLI-4, CLI-14.)
|
|
18
|
+
// server.* manages the servers themselves: it always runs here. (Through the server,
|
|
19
|
+
// `mark server stop` ran server.stop inside the server it stopped: no answer, no cleanup.)
|
|
20
|
+
if (path[0] === "server") {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const lockfile = await findServer({ cwd: process.cwd(), build: currentBuild() });
|
|
24
|
+
// mark sends its commands over HTTP: a WebSocket-only server cannot take them
|
|
25
|
+
if (!lockfile?.token || lockfile.transport === "websocket") {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
let client;
|
|
29
|
+
let method;
|
|
30
|
+
try {
|
|
31
|
+
// Dynamic import client
|
|
32
|
+
const clientModule = await import("@procedures/client");
|
|
33
|
+
const { Client, HttpTransport } = clientModule;
|
|
34
|
+
// Connect to server
|
|
35
|
+
const transport = new HttpTransport({
|
|
36
|
+
baseUrl: lockfile.endpoint,
|
|
37
|
+
defaultHeaders: { Authorization: `Bearer ${lockfile.token}` },
|
|
38
|
+
});
|
|
39
|
+
client = new Client({ transport });
|
|
40
|
+
// The method of the path as ProcedureServer registers it: the last segment is the operation.
|
|
41
|
+
// (Before, the first segment was the service, so a path of three segments - docker compose up -
|
|
42
|
+
// was not found on the server.)
|
|
43
|
+
method = { service: path.slice(0, -1).join("."), operation: path[path.length - 1] };
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Nothing was sent to the server yet - fall back to local execution
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
// Execute remotely. From here on, do not fall back to local execution: the server may
|
|
50
|
+
// have run (part of) the command, and running it again would repeat its side effects.
|
|
51
|
+
try {
|
|
52
|
+
// Each item of the response as it arrives (a streaming procedure gives many). The result
|
|
53
|
+
// is the last item.
|
|
54
|
+
let last;
|
|
55
|
+
for await (const item of client.stream(method, input)) {
|
|
56
|
+
last = { value: item };
|
|
57
|
+
onItem?.(item);
|
|
58
|
+
}
|
|
59
|
+
if (!last) {
|
|
60
|
+
throw new Error("No response received from the CLI server");
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
result: last.value,
|
|
65
|
+
printed: onItem !== undefined,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: error instanceof Error ? error.message : String(error),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=client-mode.js.map
|