@linzumi/cli 1.0.204 → 1.0.205
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/README.md +1 -1
- package/dist/impl-res/cloud-supervisor.mjs +11 -11
- package/dist/impl-res/index.js +190 -163
- package/dist/impl-res/mcp-server.mjs +31 -31
- package/dist/impl-ts/cloud-supervisor.mjs +11 -11
- package/dist/impl-ts/index.js +501 -485
- package/dist/impl-ts/mcp-server.mjs +41 -41
- package/dist/mcp-server.mjs +41 -41
- package/package.json +4 -4
- package/scripts/build-core-fate-ladder-parity-oracle.mjs +62 -2
- package/scripts/build-harness-claude-parity-oracle.mjs +121 -22
- package/scripts/build-queue-parity-oracle.mjs +4 -0
- package/scripts/build.mjs +10 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linzumi/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.205",
|
|
4
4
|
"description": "Linzumi CLI \u2014 point a Codex agent at the real code on your laptop, with your team watching and steering from shared threads.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
"scripts"
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
|
-
"build": "node scripts/build.mjs",
|
|
16
|
+
"build": "rescript build ../linzumi-cli-rescript && node scripts/build.mjs",
|
|
17
17
|
"bump-version": "node scripts/bump-cli-version.mjs",
|
|
18
18
|
"codex:history-table": "node scripts/codex_history_table.mjs",
|
|
19
|
-
"test": "rescript build ../linzumi-cli-rescript && rescript build ../../kandan/server_v2/web/replay_harness && vitest run --config vitest.config.mjs",
|
|
19
|
+
"test": "rescript build ../linzumi-cli-rescript && node --import tsx --test ../linzumi-cli-rescript/src/parity/McpToolCallBoundaryTest.res.mjs && rescript build ../../kandan/server_v2/web/replay_harness && vitest run --config vitest.config.mjs",
|
|
20
20
|
"typecheck": "tsgo --noEmit -p tsconfig.source.json",
|
|
21
21
|
"typecheck:all": "tsgo --noEmit -p tsconfig.json",
|
|
22
22
|
"typecheck:watch": "tsgo --noEmit -w -p tsconfig.source.json",
|
|
23
|
-
"prepack": "node scripts/build.mjs",
|
|
23
|
+
"prepack": "rescript build -q ../linzumi-cli-rescript && node scripts/build.mjs",
|
|
24
24
|
"pack:dry-run": "npm pack --dry-run",
|
|
25
25
|
"record:agent-fixtures": "tsx scripts/record-agent-replay-fixtures.ts",
|
|
26
26
|
"normalize:agent-fixture": "tsx scripts/normalize-agent-replay-fixture.ts",
|
|
@@ -21,12 +21,72 @@
|
|
|
21
21
|
// SECRETS: the oracle only ever sees the conformance suite's synthetic
|
|
22
22
|
// payloads. The output is a local test artifact (.differential/ is
|
|
23
23
|
// gitignored, never published) and stays unminified for debuggability.
|
|
24
|
-
import { mkdir } from 'node:fs/promises';
|
|
24
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
25
25
|
import { dirname, join } from 'node:path';
|
|
26
26
|
import { fileURLToPath } from 'node:url';
|
|
27
27
|
import { build } from 'esbuild';
|
|
28
28
|
|
|
29
29
|
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
30
|
+
const providerSlasPath = join(
|
|
31
|
+
packageRoot,
|
|
32
|
+
'src',
|
|
33
|
+
'fateLadderProviderSlas.json'
|
|
34
|
+
);
|
|
35
|
+
const generatedProviderSlasPath = join(
|
|
36
|
+
packageRoot,
|
|
37
|
+
'..',
|
|
38
|
+
'linzumi-cli-rescript',
|
|
39
|
+
'src',
|
|
40
|
+
'generated',
|
|
41
|
+
'CommanderFateLadderProviderSlas.res'
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
function positiveFiniteNumber(value, label) {
|
|
45
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
|
|
46
|
+
throw new Error(`invalid provider fate SLA ${label}: ${String(value)}`);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const providerSlas = JSON.parse(await readFile(providerSlasPath, 'utf8'));
|
|
52
|
+
const defaultMaxLadderMs = positiveFiniteNumber(
|
|
53
|
+
providerSlas?.default?.maxLadderMs,
|
|
54
|
+
'default.maxLadderMs'
|
|
55
|
+
);
|
|
56
|
+
const waferMaxLadderMs = positiveFiniteNumber(
|
|
57
|
+
providerSlas?.wafer?.maxLadderMs,
|
|
58
|
+
'wafer.maxLadderMs'
|
|
59
|
+
);
|
|
60
|
+
const generatedProviderSlas = `// GENERATED from packages/linzumi-cli/src/fateLadderProviderSlas.json by
|
|
61
|
+
// packages/linzumi-cli/scripts/build-core-fate-ladder-parity-oracle.mjs.
|
|
62
|
+
// Do not edit this file by hand.
|
|
63
|
+
// Spec: plans/2026-08-07-wafer-provider-aware-fate-budget.spec.md
|
|
64
|
+
|
|
65
|
+
let defaultMaxLadderMs = ${defaultMaxLadderMs}.
|
|
66
|
+
let waferMaxLadderMs = ${waferMaxLadderMs}.
|
|
67
|
+
|
|
68
|
+
let maxLadderMsForModelProvider = (modelProvider: option<string>): float =>
|
|
69
|
+
switch modelProvider {
|
|
70
|
+
| Some("wafer") => waferMaxLadderMs
|
|
71
|
+
| Some(_) | None => defaultMaxLadderMs
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
|
|
75
|
+
if (process.argv.includes('--write-provider-slas')) {
|
|
76
|
+
await writeFile(generatedProviderSlasPath, generatedProviderSlas, 'utf8');
|
|
77
|
+
} else {
|
|
78
|
+
const trackedProviderSlas = await readFile(generatedProviderSlasPath, 'utf8');
|
|
79
|
+
if (trackedProviderSlas !== generatedProviderSlas) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
'generated CommanderFateLadderProviderSlas.res is stale; run build-core-fate-ladder-parity-oracle.mjs --write-provider-slas'
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (process.argv.includes('--check-provider-slas-only')) {
|
|
87
|
+
process.stdout.write(generatedProviderSlasPath + '\n');
|
|
88
|
+
process.exit(0);
|
|
89
|
+
}
|
|
30
90
|
|
|
31
91
|
// PARITY SCOPE (owner ruling 2026-07-18, failover becomes a user-decision
|
|
32
92
|
// capability): the compared surface is the SHARED F2 recovery engine only.
|
|
@@ -229,7 +289,7 @@ function runCase(input) {
|
|
|
229
289
|
rateLimitHoldReasonPrefix,
|
|
230
290
|
};
|
|
231
291
|
case 'budgets':
|
|
232
|
-
return fateLadderBudgets(input.env ?? {});
|
|
292
|
+
return fateLadderBudgets(input.env ?? {}, input.modelProvider);
|
|
233
293
|
case 'holdReason':
|
|
234
294
|
return rateLimitHoldReason(input.resetAtMs);
|
|
235
295
|
case 'resetFromNotification':
|
|
@@ -278,31 +278,130 @@ run().then(
|
|
|
278
278
|
);
|
|
279
279
|
`;
|
|
280
280
|
|
|
281
|
+
const questionCardDriverSource = `
|
|
282
|
+
/*
|
|
283
|
+
* Spec: spec/commander-completion-pipeline-rules.md
|
|
284
|
+
* (\`:commander-completion-pipeline/rule-07-claude-events-publish\`).
|
|
285
|
+
* Relationship: Batch driver over the active TS Claude question-card model;
|
|
286
|
+
* it contains no copied approval behavior.
|
|
287
|
+
*/
|
|
288
|
+
import {
|
|
289
|
+
claudeCodeQuestionAnsweredInput,
|
|
290
|
+
claudeCodeToolApprovalRequest,
|
|
291
|
+
claudeCodeUserQuestionStreamKey,
|
|
292
|
+
claudeCodeUserQuestionStructuredMessage,
|
|
293
|
+
parseClaudeCodeUserQuestionRequest,
|
|
294
|
+
} from './src/claudeCodeUserQuestions';
|
|
295
|
+
import type { ClaudeCodeUserQuestionAnswer } from './src/claudeCodeUserQuestions';
|
|
296
|
+
import type { ClaudeCodePermissionRequest } from './src/claudeCodeSession';
|
|
297
|
+
import type { JsonObject } from './src/protocol';
|
|
298
|
+
|
|
299
|
+
type OracleCase = {
|
|
300
|
+
readonly op?: 'approval' | 'question';
|
|
301
|
+
readonly request: ClaudeCodePermissionRequest;
|
|
302
|
+
readonly answers?: readonly ClaudeCodeUserQuestionAnswer[];
|
|
303
|
+
readonly sessionId: string | undefined;
|
|
304
|
+
readonly sourceSeq: number;
|
|
305
|
+
readonly answerState: JsonObject;
|
|
306
|
+
readonly streamState: 'streaming' | 'completed' | 'failed' | 'interrupted';
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
function handle(testCase: OracleCase): JsonObject {
|
|
310
|
+
if (testCase.op === 'question') {
|
|
311
|
+
const parsed = parseClaudeCodeUserQuestionRequest(testCase.request);
|
|
312
|
+
if (parsed.type === 'question' && testCase.answers !== undefined) {
|
|
313
|
+
return {
|
|
314
|
+
parsed,
|
|
315
|
+
answeredInput: claudeCodeQuestionAnsweredInput(
|
|
316
|
+
testCase.request.input,
|
|
317
|
+
parsed.request,
|
|
318
|
+
testCase.answers
|
|
319
|
+
),
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
return { parsed };
|
|
323
|
+
}
|
|
324
|
+
const approval = claudeCodeToolApprovalRequest(testCase.request);
|
|
325
|
+
return {
|
|
326
|
+
approval,
|
|
327
|
+
structured: claudeCodeUserQuestionStructuredMessage({
|
|
328
|
+
request: approval.request,
|
|
329
|
+
sessionId: testCase.sessionId,
|
|
330
|
+
sourceSeq: testCase.sourceSeq,
|
|
331
|
+
answerState: testCase.answerState,
|
|
332
|
+
streamState: testCase.streamState,
|
|
333
|
+
}),
|
|
334
|
+
streamKey: claudeCodeUserQuestionStreamKey(testCase.request.requestId),
|
|
335
|
+
decisions: Object.fromEntries(
|
|
336
|
+
approval.choices.map((choice) => [choice.decision, choice.permissionDecision])
|
|
337
|
+
),
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const chunks: Buffer[] = [];
|
|
342
|
+
for await (const chunk of process.stdin) {
|
|
343
|
+
chunks.push(Buffer.from(chunk));
|
|
344
|
+
}
|
|
345
|
+
const cases = JSON.parse(Buffer.concat(chunks).toString('utf8')) as OracleCase[];
|
|
346
|
+
process.stdout.write(JSON.stringify(cases.map(handle)));
|
|
347
|
+
|
|
348
|
+
`;
|
|
349
|
+
|
|
281
350
|
const outDir = join(packageRoot, '.differential');
|
|
282
351
|
const outPath = join(outDir, 'harness-claude-parity-oracle.mjs');
|
|
352
|
+
const buildQuestionCard = process.argv[2] === 'question-card';
|
|
283
353
|
|
|
284
354
|
await mkdir(outDir, { recursive: true });
|
|
285
355
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
356
|
+
if (!buildQuestionCard) {
|
|
357
|
+
await build({
|
|
358
|
+
stdin: {
|
|
359
|
+
contents: driverSource,
|
|
360
|
+
resolveDir: packageRoot,
|
|
361
|
+
sourcefile: 'harness-claude-parity-driver.ts',
|
|
362
|
+
loader: 'ts',
|
|
363
|
+
},
|
|
364
|
+
bundle: true,
|
|
365
|
+
platform: 'node',
|
|
366
|
+
target: 'node20',
|
|
367
|
+
format: 'esm',
|
|
368
|
+
outfile: outPath,
|
|
369
|
+
minify: false,
|
|
370
|
+
sourcemap: false,
|
|
371
|
+
legalComments: 'none',
|
|
372
|
+
logLevel: 'silent',
|
|
373
|
+
external: ['ws', 'undici', 'blessed'],
|
|
374
|
+
alias: {
|
|
375
|
+
'@anthropic-ai/claude-agent-sdk': stubModulePath,
|
|
376
|
+
},
|
|
377
|
+
});
|
|
378
|
+
}
|
|
307
379
|
|
|
308
|
-
|
|
380
|
+
const questionCardOutPath = join(
|
|
381
|
+
outDir,
|
|
382
|
+
'claude-question-card-parity-oracle.mjs'
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
if (buildQuestionCard) {
|
|
386
|
+
await build({
|
|
387
|
+
stdin: {
|
|
388
|
+
contents: questionCardDriverSource,
|
|
389
|
+
resolveDir: packageRoot,
|
|
390
|
+
sourcefile: 'claude-question-card-parity-driver.ts',
|
|
391
|
+
loader: 'ts',
|
|
392
|
+
},
|
|
393
|
+
bundle: true,
|
|
394
|
+
platform: 'node',
|
|
395
|
+
target: 'node22',
|
|
396
|
+
format: 'esm',
|
|
397
|
+
outfile: questionCardOutPath,
|
|
398
|
+
minify: false,
|
|
399
|
+
sourcemap: 'inline',
|
|
400
|
+
legalComments: 'none',
|
|
401
|
+
logLevel: 'silent',
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
process.stdout.write(
|
|
406
|
+
(buildQuestionCard ? questionCardOutPath : outPath) + '\n'
|
|
407
|
+
);
|
|
@@ -503,6 +503,10 @@ function buildersFromSpec(spec, recordedReplies) {
|
|
|
503
503
|
...(config.timeoutMs === undefined ? {} : { timeoutMs: config.timeoutMs }),
|
|
504
504
|
};
|
|
505
505
|
},
|
|
506
|
+
// Spec: spec/commander-recovery-rules.md. These generic parity entries
|
|
507
|
+
// exercise must_ack/best_effort transport acknowledgement, never the
|
|
508
|
+
// approval-failure consensus protocol.
|
|
509
|
+
replyPolicy: { kind: 'transport_ack' },
|
|
506
510
|
...(config.onReply === 'record'
|
|
507
511
|
? {
|
|
508
512
|
onReply: (data, reply) => {
|
package/scripts/build.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
// Spec: plans/2026-05-17-linzumi-cli-node-toolchain-note.md
|
|
1
|
+
// Spec: plans/2026-05-17-linzumi-cli-node-toolchain-note.md and
|
|
2
|
+
// plans/2026-08-06-hosted-runner-proper-lockfile-boot-incident.md
|
|
2
3
|
// Relationship: Builds the published CLI package with Node-hosted tooling.
|
|
3
4
|
import { copyFile, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
4
5
|
import { dirname, join } from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
7
|
import { build } from 'esbuild';
|
|
7
8
|
|
|
8
9
|
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
@@ -326,3 +327,10 @@ try {
|
|
|
326
327
|
'}\n'
|
|
327
328
|
);
|
|
328
329
|
}
|
|
330
|
+
|
|
331
|
+
// LOAD-SMOKE TOOTH (prod RCA 2026-08-06): parsing alone did not catch a
|
|
332
|
+
// createRequire dependency that was absent from the Nix image. The published
|
|
333
|
+
// package has a separate build recipe, so import its fully installed commander
|
|
334
|
+
// bundle here as well; any eager MODULE_NOT_FOUND or other load-time failure
|
|
335
|
+
// fails the build.
|
|
336
|
+
await import(pathToFileURL(join(packageRoot, 'dist/impl-ts/index.js')).href);
|