@procedures/mark 0.2.2 → 0.3.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 +79 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +50 -8
- package/dist/cli.js.map +1 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +20 -16
- package/dist/manifest.js.map +1 -1
- package/dist/manifest.json +24335 -8068
- package/dist/server-mode.d.ts.map +1 -1
- package/dist/server-mode.js +19 -2
- package/dist/server-mode.js.map +1 -1
- package/package.json +46 -26
- package/src/cli.ts +43 -7
- package/src/manifest.ts +15 -11
- package/src/server-mode.ts +17 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-mode.d.ts","sourceRoot":"","sources":["../src/server-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"server-mode.d.ts","sourceRoot":"","sources":["../src/server-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA6CD;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+F/E;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED,2CAA2C;AAC3C,eAAO,MAAM,iBAAiB,YAAI,MAAM,EAAE,WAAW,EAAE,MAAM,CAAU,CAAC;AAExE;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAM3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAUzD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAWzD"}
|
package/dist/server-mode.js
CHANGED
|
@@ -9,6 +9,7 @@ import { print } from "./print.js";
|
|
|
9
9
|
import { loadEcosystemRegistry } from "./ecosystem.js";
|
|
10
10
|
import { randomBytes } from "node:crypto";
|
|
11
11
|
import { writeLockfile, removeLockfileForPort, getLockfilePath, currentBuild } from "./lockfile.js";
|
|
12
|
+
import { seconds } from "@procedures/client";
|
|
12
13
|
/**
|
|
13
14
|
* Build transport configuration array
|
|
14
15
|
*/
|
|
@@ -97,11 +98,27 @@ export async function startServerMode(options) {
|
|
|
97
98
|
print.info(` [${endpoint.type}] ${endpoint.address}`);
|
|
98
99
|
}
|
|
99
100
|
print.info("\nPress Ctrl+C to stop.");
|
|
100
|
-
// Handle shutdown
|
|
101
|
+
// Handle shutdown: the peer stops (its requests end and its ports close) before the process
|
|
102
|
+
// exits, with a limit of 10 seconds. A second signal exits at once. Before, the process exited
|
|
103
|
+
// without a stop (roadmap R5).
|
|
104
|
+
let stopping = false;
|
|
101
105
|
const cleanup = async () => {
|
|
106
|
+
if (stopping)
|
|
107
|
+
process.exit(1);
|
|
108
|
+
stopping = true;
|
|
102
109
|
print.info("\nStopping server...");
|
|
103
110
|
removeLockfileForPort(port);
|
|
104
|
-
process.exit(
|
|
111
|
+
const limit = setTimeout(() => process.exit(1), 10_000);
|
|
112
|
+
limit.unref();
|
|
113
|
+
try {
|
|
114
|
+
// The calls in flight have 5 seconds to end (roadmap R14)
|
|
115
|
+
await peer.stop({ grace: seconds(5) });
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
print.error(`The server did not stop cleanly: ${error instanceof Error ? error.message : String(error)}`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
105
122
|
};
|
|
106
123
|
process.on("SIGINT", cleanup);
|
|
107
124
|
process.on("SIGTERM", cleanup);
|
package/dist/server-mode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-mode.js","sourceRoot":"","sources":["../src/server-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"server-mode.js","sourceRoot":"","sources":["../src/server-mode.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@procedures/mark",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "mark: one CLI for every procedure package. It finds the procedures, parses flags by their Zod types, runs local or through a fast warm server, and asks for missing arguments.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"cli",
|
|
@@ -52,39 +52,59 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@clack/prompts": "^0.7.0",
|
|
55
|
-
"@procedures/
|
|
56
|
-
"@procedures/
|
|
57
|
-
"@procedures/lib": "0.
|
|
58
|
-
"@procedures/
|
|
59
|
-
"@procedures/
|
|
60
|
-
"@procedures/
|
|
61
|
-
"@procedures/
|
|
62
|
-
"@procedures/
|
|
55
|
+
"@procedures/cli-run": "0.3.0",
|
|
56
|
+
"@procedures/client": "0.3.0",
|
|
57
|
+
"@procedures/lib": "0.3.0",
|
|
58
|
+
"@procedures/mcp-dev-tools": "0.3.0",
|
|
59
|
+
"@procedures/peer": "0.3.0",
|
|
60
|
+
"@procedures/pnpm": "0.3.0",
|
|
61
|
+
"@procedures/procedure": "0.3.0",
|
|
62
|
+
"@procedures/server": "0.3.0",
|
|
63
|
+
"@procedures/shell": "0.3.0",
|
|
64
|
+
"@procedures/vitest": "0.3.0",
|
|
63
65
|
"chalk": "^5.3.0",
|
|
64
66
|
"cli-table3": "^0.6.5",
|
|
65
67
|
"ora": "^8.0.0",
|
|
66
68
|
"tslib": "^2.8.1",
|
|
67
|
-
"zod": "^4.6.5"
|
|
68
|
-
"@procedures/server": "0.2.2",
|
|
69
|
-
"@procedures/mcp-dev-tools": "0.2.2"
|
|
69
|
+
"zod": "^4.6.5"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@procedures/bundle-dev": "0.2.2",
|
|
73
|
-
"@procedures/bundle-mcp": "0.2.2",
|
|
74
|
-
"@procedures/cue": "0.2.2",
|
|
75
|
-
"@procedures/docker": "0.2.2",
|
|
76
|
-
"@procedures/fs": "0.2.2",
|
|
77
|
-
"@procedures/git": "0.2.2",
|
|
78
|
-
"@procedures/mongo": "0.2.2",
|
|
79
|
-
"@procedures/node": "0.2.2",
|
|
80
|
-
"@procedures/s3": "0.2.2",
|
|
81
|
-
"@procedures/snapshot": "0.2.2",
|
|
82
|
-
"@procedures/splay": "0.2.2",
|
|
83
|
-
"@procedures/sqlite": "0.2.2",
|
|
84
|
-
"@procedures/store": "0.2.2",
|
|
85
|
-
"@procedures/vite": "0.2.2",
|
|
86
72
|
"@mark1russell7/cue": "^1.0.0",
|
|
73
|
+
"@procedures/archive": "0.3.0",
|
|
74
|
+
"@procedures/bundle-assistant": "0.3.0",
|
|
75
|
+
"@procedures/bundle-dev": "0.3.0",
|
|
76
|
+
"@procedures/bundle-mcp": "0.3.0",
|
|
77
|
+
"@procedures/compiler": "0.3.0",
|
|
78
|
+
"@procedures/cue": "0.3.0",
|
|
79
|
+
"@procedures/docker": "0.3.0",
|
|
80
|
+
"@procedures/env": "0.3.0",
|
|
81
|
+
"@procedures/exif": "0.3.0",
|
|
82
|
+
"@procedures/fs": "0.3.0",
|
|
83
|
+
"@procedures/geo": "0.3.0",
|
|
84
|
+
"@procedures/gh": "0.3.0",
|
|
85
|
+
"@procedures/git": "0.3.0",
|
|
86
|
+
"@procedures/http": "0.3.0",
|
|
87
|
+
"@procedures/ics": "0.3.0",
|
|
88
|
+
"@procedures/json": "0.3.0",
|
|
89
|
+
"@procedures/llm": "0.3.0",
|
|
90
|
+
"@procedures/mail": "0.3.0",
|
|
91
|
+
"@procedures/mongo": "0.3.0",
|
|
92
|
+
"@procedures/node": "0.3.0",
|
|
93
|
+
"@procedures/notify": "0.3.0",
|
|
94
|
+
"@procedures/npm": "0.3.0",
|
|
95
|
+
"@procedures/restic": "0.3.0",
|
|
96
|
+
"@procedures/s3": "0.3.0",
|
|
97
|
+
"@procedures/schedule": "0.3.0",
|
|
98
|
+
"@procedures/snapshot": "0.3.0",
|
|
99
|
+
"@procedures/splay": "0.3.0",
|
|
100
|
+
"@procedures/sqlite": "0.3.0",
|
|
101
|
+
"@procedures/store": "0.3.0",
|
|
102
|
+
"@procedures/systems": "0.3.0",
|
|
103
|
+
"@procedures/tailscale": "0.3.0",
|
|
104
|
+
"@procedures/vite": "0.3.0",
|
|
105
|
+
"@procedures/weather": "0.3.0",
|
|
87
106
|
"@types/node": "^22.0.0",
|
|
107
|
+
"fast-check": "^4.10.2",
|
|
88
108
|
"typescript": "^7.0.2",
|
|
89
109
|
"vitest": "^5.0.3"
|
|
90
110
|
},
|
package/src/cli.ts
CHANGED
|
@@ -169,6 +169,21 @@ export interface ExecuteOptions {
|
|
|
169
169
|
ask?: Asker;
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/**
|
|
173
|
+
* A signal that aborts on the first Ctrl+C while a command runs in this process (roadmap R14):
|
|
174
|
+
* the procedure gets the abort (a shell command stops its process tree). A second Ctrl+C exits
|
|
175
|
+
* at once. `release()` removes the listener when the command ends.
|
|
176
|
+
*/
|
|
177
|
+
function interruptSignal(): { signal: AbortSignal; release: () => void } {
|
|
178
|
+
const controller = new AbortController();
|
|
179
|
+
const onInterrupt = (): void => {
|
|
180
|
+
if (controller.signal.aborted) process.exit(130);
|
|
181
|
+
controller.abort();
|
|
182
|
+
};
|
|
183
|
+
process.on("SIGINT", onInterrupt);
|
|
184
|
+
return { signal: controller.signal, release: () => process.off("SIGINT", onInterrupt) };
|
|
185
|
+
}
|
|
186
|
+
|
|
172
187
|
/**
|
|
173
188
|
* Initialize the CLI context (load ecosystem, create client)
|
|
174
189
|
* This is the expensive part (~4s). Call once, reuse many times.
|
|
@@ -269,15 +284,18 @@ export async function executeArgs(
|
|
|
269
284
|
fail('--json needs a procedure reference: an object with "$proc".');
|
|
270
285
|
return;
|
|
271
286
|
}
|
|
287
|
+
const interrupt = interruptSignal();
|
|
272
288
|
try {
|
|
273
289
|
const { client } = await local();
|
|
274
|
-
const result = await client.exec(parsedJson as Parameters<typeof client.exec>[0]);
|
|
290
|
+
const result = await client.exec(parsedJson as Parameters<typeof client.exec>[0], undefined, { signal: interrupt.signal });
|
|
275
291
|
formatOutput(print as unknown as Print, result, "json");
|
|
276
292
|
if (failureOf(result)) {
|
|
277
293
|
process.exitCode = 1;
|
|
278
294
|
}
|
|
279
295
|
} catch (error) {
|
|
280
296
|
fail(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
297
|
+
} finally {
|
|
298
|
+
interrupt.release();
|
|
281
299
|
}
|
|
282
300
|
return;
|
|
283
301
|
}
|
|
@@ -399,10 +417,15 @@ export async function executeArgs(
|
|
|
399
417
|
// A streaming procedure gives many items: print each one when it arrives. A
|
|
400
418
|
// request/response procedure gives one item, so its output does not change.
|
|
401
419
|
let items = 0;
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
420
|
+
const interrupt = interruptSignal();
|
|
421
|
+
try {
|
|
422
|
+
for await (const item of client.stream(method, validated, { signal: interrupt.signal })) {
|
|
423
|
+
if (spinner && items === 0) spinner.stop();
|
|
424
|
+
items++;
|
|
425
|
+
printItem(item);
|
|
426
|
+
}
|
|
427
|
+
} finally {
|
|
428
|
+
interrupt.release();
|
|
406
429
|
}
|
|
407
430
|
|
|
408
431
|
if (spinner) {
|
|
@@ -420,7 +443,8 @@ export async function executeArgs(
|
|
|
420
443
|
|
|
421
444
|
const MCP_HELP = `Usage: mark mcp [options]
|
|
422
445
|
|
|
423
|
-
Start the dev-tools MCP server over stdio (the server of Claude Code's MCP configuration)
|
|
446
|
+
Start the dev-tools MCP server over stdio (the server of Claude Code's MCP configuration), or
|
|
447
|
+
over Streamable HTTP with --http.
|
|
424
448
|
It has a registry of its own, from the modules of its bundles, and the host policy of an MCP
|
|
425
449
|
server: only the tools of the bundles, strict nested calls, and a time limit for each call.
|
|
426
450
|
|
|
@@ -428,6 +452,9 @@ Options:
|
|
|
428
452
|
--bundles <list> Comma-separated bundles (default: MCP_BUNDLES, or @procedures/bundle-mcp)
|
|
429
453
|
--tool-timeout <ms> The time limit of each tool call (default: MCP_TOOL_TIMEOUT_MS, or 600000)
|
|
430
454
|
--read-only Only the tools that change nothing (default: MCP_READ_ONLY)
|
|
455
|
+
--http <port> Serve over Streamable HTTP on this port, not over stdio (MCP_HTTP_PORT)
|
|
456
|
+
--host <host> The address of --http (default: 127.0.0.1, only this computer)
|
|
457
|
+
--token <token> A secret that each HTTP request must send as a bearer token
|
|
431
458
|
--debug Write debug lines to stderr
|
|
432
459
|
-h, --help Show this help
|
|
433
460
|
|
|
@@ -461,6 +488,14 @@ async function startMcp(args: string[]): Promise<void> {
|
|
|
461
488
|
config.toolTimeoutMs = ms;
|
|
462
489
|
} else if (name === "--read-only") {
|
|
463
490
|
config.readOnly = true;
|
|
491
|
+
} else if (name === "--http") {
|
|
492
|
+
const port = Number(value());
|
|
493
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error("--http needs a port number");
|
|
494
|
+
config.http = { ...config.http, port };
|
|
495
|
+
} else if (name === "--host") {
|
|
496
|
+
config.http = { port: config.http?.port ?? 3003, ...config.http, host: value() };
|
|
497
|
+
} else if (name === "--token") {
|
|
498
|
+
config.http = { port: config.http?.port ?? 3003, ...config.http, token: value() };
|
|
464
499
|
} else if (name === "--debug") {
|
|
465
500
|
config.debug = true;
|
|
466
501
|
} else {
|
|
@@ -530,7 +565,8 @@ async function run(argv: string[]): Promise<void> {
|
|
|
530
565
|
await runServer(commandArgs, { resolveFrom: [process.cwd(), markDir] });
|
|
531
566
|
return;
|
|
532
567
|
}
|
|
533
|
-
|
|
568
|
+
// `mark mcp` and `mark mcp --option value`: the server. `mark mcp <procedure>`: an mcp.* command.
|
|
569
|
+
if (command === "mcp" && (commandArgs.length === 0 || commandArgs[0]!.startsWith("-"))) {
|
|
534
570
|
await startMcp(commandArgs);
|
|
535
571
|
return;
|
|
536
572
|
}
|
package/src/manifest.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { createHash } from "node:crypto";
|
|
|
17
17
|
import * as fs from "node:fs";
|
|
18
18
|
import * as path from "node:path";
|
|
19
19
|
import { fileURLToPath } from "node:url";
|
|
20
|
-
import { jsonSchemaOf, type AnyProcedure } from "@procedures/client";
|
|
20
|
+
import { describeProcedureEntry, jsonSchemaOf, type AnyProcedure, type ProcedureEntry } from "@procedures/client";
|
|
21
21
|
import { discoverFromEcosystem, findWorkspaceRoot } from "./ecosystem.js";
|
|
22
22
|
import { extractSchemaFields, resultFieldsOfSchema, type CLIMeta, type SchemaFieldInfo } from "./parse.js";
|
|
23
23
|
|
|
@@ -96,26 +96,30 @@ export function computeFingerprint(root: string | null = findWorkspaceRoot(), ma
|
|
|
96
96
|
return createHash("sha256").update(parts.join("\n")).digest("hex");
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
/**
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
/**
|
|
100
|
+
* The CLI metadata of a procedure: only the fields that mark reads, so the manifest is plain JSON.
|
|
101
|
+
* It comes from the one description of the core (roadmap R17).
|
|
102
|
+
*/
|
|
103
|
+
function cliMetadata(entry: ProcedureEntry): CLIMeta {
|
|
102
104
|
const result: CLIMeta = {};
|
|
103
|
-
if (
|
|
104
|
-
if (
|
|
105
|
-
if (
|
|
106
|
-
if (
|
|
107
|
-
if (
|
|
105
|
+
if (entry.description !== undefined) result.description = entry.description;
|
|
106
|
+
if (entry.cli?.args) result.args = entry.cli.args.filter((arg): arg is string => typeof arg === "string");
|
|
107
|
+
if (entry.cli?.shorts) result.shorts = { ...entry.cli.shorts };
|
|
108
|
+
if (entry.cli?.output !== undefined) result.output = entry.cli.output as NonNullable<CLIMeta["output"]>;
|
|
109
|
+
if (entry.cli?.interactive !== undefined) result.interactive = entry.cli.interactive;
|
|
108
110
|
return result;
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
/** The commands of the manifest, from the procedures of the registry */
|
|
112
114
|
export async function commandsOf(procedures: readonly AnyProcedure[]): Promise<ManifestCommand[]> {
|
|
113
115
|
return procedures.map((procedure) => {
|
|
114
|
-
// One JSON Schema for each command: the fields come from it too (roadmap 2.1)
|
|
116
|
+
// One JSON Schema for each command: the fields come from it too (roadmap 2.1). The schema and
|
|
117
|
+
// the CLI metadata come from the one manifest type of the core (roadmap R17).
|
|
118
|
+
const entry = describeProcedureEntry(procedure, { schemas: false });
|
|
115
119
|
const inputSchema = jsonSchemaOf(procedure.input) ?? {};
|
|
116
120
|
return {
|
|
117
121
|
path: [...procedure.path],
|
|
118
|
-
metadata: cliMetadata(
|
|
122
|
+
metadata: cliMetadata(entry),
|
|
119
123
|
fields: extractSchemaFields(inputSchema),
|
|
120
124
|
inputSchema,
|
|
121
125
|
resultFields: resultFieldsOfSchema(procedure.output),
|
package/src/server-mode.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { print } from "./print.js";
|
|
|
10
10
|
import { loadEcosystemRegistry } from "./ecosystem.js";
|
|
11
11
|
import { randomBytes } from "node:crypto";
|
|
12
12
|
import { writeLockfile, removeLockfileForPort, getLockfilePath, currentBuild } from "./lockfile.js";
|
|
13
|
+
import { seconds } from "@procedures/client";
|
|
13
14
|
|
|
14
15
|
export interface ServerModeOptions {
|
|
15
16
|
port: number;
|
|
@@ -131,11 +132,25 @@ export async function startServerMode(options: ServerModeOptions): Promise<void>
|
|
|
131
132
|
}
|
|
132
133
|
print.info("\nPress Ctrl+C to stop.");
|
|
133
134
|
|
|
134
|
-
// Handle shutdown
|
|
135
|
+
// Handle shutdown: the peer stops (its requests end and its ports close) before the process
|
|
136
|
+
// exits, with a limit of 10 seconds. A second signal exits at once. Before, the process exited
|
|
137
|
+
// without a stop (roadmap R5).
|
|
138
|
+
let stopping = false;
|
|
135
139
|
const cleanup = async () => {
|
|
140
|
+
if (stopping) process.exit(1);
|
|
141
|
+
stopping = true;
|
|
136
142
|
print.info("\nStopping server...");
|
|
137
143
|
removeLockfileForPort(port);
|
|
138
|
-
process.exit(
|
|
144
|
+
const limit = setTimeout(() => process.exit(1), 10_000);
|
|
145
|
+
limit.unref();
|
|
146
|
+
try {
|
|
147
|
+
// The calls in flight have 5 seconds to end (roadmap R14)
|
|
148
|
+
await peer.stop({ grace: seconds(5) });
|
|
149
|
+
process.exit(0);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
print.error(`The server did not stop cleanly: ${error instanceof Error ? error.message : String(error)}`);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
139
154
|
};
|
|
140
155
|
|
|
141
156
|
process.on("SIGINT", cleanup);
|