@linzumi/cli 1.0.275 → 1.0.276

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.
Files changed (41) hide show
  1. package/README.md +10 -9
  2. package/dist/{impl-ts/cloud-supervisor.mjs → cloud-supervisor.mjs} +78 -78
  3. package/dist/hosted-coding-account-worker.js +25 -0
  4. package/dist/index.js +1609 -3
  5. package/dist/mcp-server.mjs +174 -168
  6. package/dist/{impl-res/native → native}/darwin/manifest.json +5 -2
  7. package/dist/remote-codex-harness-worker.js +757 -0
  8. package/dist/tcp-tunnel-cli.mjs +25 -69
  9. package/dist/topics-cli.mjs +137 -13
  10. package/package.json +9 -16
  11. package/scripts/build.mjs +33 -356
  12. package/scripts/bump-cli-version.mjs +35 -9
  13. package/scripts/check-package-size-budget.mjs +13 -61
  14. package/dist/impl-res/cloud-supervisor.mjs +0 -281
  15. package/dist/impl-res/index.js +0 -1546
  16. package/dist/impl-res/mcp-server.mjs +0 -461
  17. package/dist/impl-ts/assets/linzumi-logo.svg +0 -1
  18. package/dist/impl-ts/crossHarnessFailover.mjs +0 -14
  19. package/dist/impl-ts/index.js +0 -2617
  20. package/dist/impl-ts/mcp-server.mjs +0 -455
  21. package/dist/impl-ts/native/darwin/manifest.json +0 -21
  22. package/dist/impl-ts/native/darwin/preview-process-identity +0 -0
  23. package/dist/impl-ts/tcp-tunnel-cli.mjs +0 -93
  24. package/scripts/build-differential-entry-impl-res.mjs +0 -64
  25. package/scripts/build-differential-entry.mjs +0 -180
  26. package/scripts/build-onboarding-demo-evidence.mjs +0 -186
  27. package/scripts/build-tui-demo-evidence.mjs +0 -107
  28. package/scripts/diagnose-claude-probe.ts +0 -198
  29. package/scripts/differentialMutations.mjs +0 -114
  30. package/scripts/f5_live_cross_harness_failover_e2e.mjs +0 -239
  31. package/scripts/golden-chaos-harness.mjs +0 -1420
  32. package/scripts/normalize-agent-replay-fixture.ts +0 -281
  33. package/scripts/promote-gstack-claude-smoke-fixture.ts +0 -891
  34. package/scripts/record-agent-replay-fixtures.ts +0 -610
  35. package/scripts/replay-agent-backend-browser.ts +0 -198
  36. package/scripts/replay-agent-backend.ts +0 -1961
  37. package/scripts/replay-agent-fixture.ts +0 -326
  38. package/scripts/typecheck.mjs +0 -42
  39. /package/dist/{impl-res/assets → assets}/linzumi-logo.svg +0 -0
  40. /package/dist/{impl-res/crossHarnessFailover.mjs → crossHarnessFailover.mjs} +0 -0
  41. /package/dist/{impl-res/native → native}/darwin/preview-process-identity +0 -0
@@ -1,64 +0,0 @@
1
- // Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md (M3 cluster 15)
2
- // Relationship: Builds the ReScript-impl differential entry
3
- // (packages/linzumi-cli-rescript/src/entry/CommanderDifferentialMain.res,
4
- // compiled by `rescript` to .res.mjs) into a single runnable bundle at
5
- // .differential/impl-res.mjs - the peer of scripts/build-differential-entry.mjs's
6
- // impl-ts bundle, with the SAME platform/target/format/externals/banner so the
7
- // differential harness compares the two impls under one bundling reality.
8
- //
9
- // Version injection: the ReScript package ships no version literal (repo
10
- // rule); the CLI version is esbuild-`define`d into the bundle as
11
- // process.env.LINZUMI_CLI_VERSION (read via CommanderEntryVersion.res), so the
12
- // hello `version` equals the TS impl's linzumiCliVersion (== package.json
13
- // version) and the min-version refusal transcripts stay byte-identical.
14
- //
15
- // FAIL LOUDLY when the compiled ReScript artifacts are missing: the
16
- // differential harness must never silently fall back to a stub.
17
- import { existsSync } from 'node:fs';
18
- import { readFile } from 'node:fs/promises';
19
- import { dirname, join } from 'node:path';
20
- import { fileURLToPath } from 'node:url';
21
- import { build } from 'esbuild';
22
-
23
- const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
24
-
25
- const entryPoint = join(
26
- packageRoot,
27
- '../linzumi-cli-rescript/src/entry/CommanderDifferentialMain.res.mjs'
28
- );
29
-
30
- if (!existsSync(entryPoint)) {
31
- console.error(
32
- `impl-res differential entry artifact missing: ${entryPoint}\n` +
33
- 'run `pnpm build` in packages/linzumi-cli-rescript first (rescript compiles src/**.res -> .res.mjs in-source)'
34
- );
35
- process.exit(1);
36
- }
37
-
38
- const packageJson = JSON.parse(
39
- await readFile(join(packageRoot, 'package.json'), 'utf8')
40
- );
41
-
42
- // Renamed banner import, mirroring scripts/build-differential-entry.mjs: this
43
- // bundle keeps source-level identifiers and the sources may import
44
- // createRequire themselves - the published banner's bare name would collide.
45
- const banner = {
46
- js: "import { createRequire as __differentialCreateRequire } from 'node:module';\nconst require = __differentialCreateRequire(import.meta.url);",
47
- };
48
-
49
- await build({
50
- entryPoints: [entryPoint],
51
- bundle: true,
52
- platform: 'node',
53
- target: 'node20',
54
- format: 'esm',
55
- outfile: join(packageRoot, '.differential/impl-res.mjs'),
56
- minify: false,
57
- sourcemap: false,
58
- legalComments: 'none',
59
- external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
60
- banner,
61
- define: {
62
- 'process.env.LINZUMI_CLI_VERSION': JSON.stringify(packageJson.version),
63
- },
64
- });
@@ -1,180 +0,0 @@
1
- // Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md (M2.5 + M2.6)
2
- // Relationship: Builds the TS-impl differential entry
3
- // (src/differentialCommanderEntry.ts) into a single runnable bundle at
4
- // .differential/impl-ts.mjs, mirroring the published dist/index.js build
5
- // configuration (same platform/target/format/externals/banner) so the
6
- // differential harness exercises the SAME bundling reality the shipped CLI
7
- // has - this is the M3 packaging seam's dist/impl-ts precursor: the M3
8
- // chooser design ships dist/impl-ts/ + dist/impl-res/ side by side, and the
9
- // M2.5 differential runner's impl parameter selects between them (the
10
- // impl-res twin is scripts/build-differential-entry-impl-res.mjs).
11
- //
12
- // M2.6 mutation mode (`--mutation <name>`): applies ONE seeded behavior
13
- // delta from scripts/differentialMutations.mjs as a build-time source patch
14
- // and emits .differential/impl-ts.mutant-<name>.mjs instead. The harness's
15
- // anti-false-green mutation check builds each mutant and asserts the
16
- // differential suite goes RED on it. Every patch anchor must match the
17
- // current source EXACTLY ONCE - zero or multiple matches fail the build
18
- // loudly, so a commander refactor can never silently no-op a mutation.
19
- //
20
- // Unminified deliberately: the bundle is a local test artifact
21
- // (.differential/ is gitignored, never published), and readable output makes
22
- // differential findings debuggable.
23
- import { copyFile, mkdir, readFile } from 'node:fs/promises';
24
- import { dirname, join } from 'node:path';
25
- import { fileURLToPath } from 'node:url';
26
- import { build } from 'esbuild';
27
- import { differentialMutations } from './differentialMutations.mjs';
28
-
29
- const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
30
-
31
- function parseArgs(argv) {
32
- if (argv.length === 0) {
33
- return { mutation: undefined };
34
- }
35
- if (argv[0] === '--mutation' && argv.length === 2) {
36
- const mutation = differentialMutations.find(
37
- (entry) => entry.name === argv[1]
38
- );
39
- if (mutation === undefined) {
40
- const known = differentialMutations.map((entry) => entry.name);
41
- throw new Error(
42
- `unknown differential mutation ${JSON.stringify(argv[1])}; known mutations: ${known.join(', ')}`
43
- );
44
- }
45
- return { mutation };
46
- }
47
- throw new Error(
48
- 'usage: node scripts/build-differential-entry.mjs [--mutation <name>]'
49
- );
50
- }
51
-
52
- const { mutation } = parseArgs(process.argv.slice(2));
53
-
54
- // Count non-overlapping occurrences of `needle` in `haystack`. An empty
55
- // needle is a registry authoring error, refused loudly (indexOf('') matches
56
- // at every position, which would both loop forever here and make the
57
- // exactly-once rule meaningless); the harness registry conformance pins the
58
- // same rule at rest (Greptile finding on #3115).
59
- function occurrences(haystack, needle) {
60
- if (needle.length === 0) {
61
- throw new Error('mutation patch `find` must be a non-empty string');
62
- }
63
- let count = 0;
64
- let from = 0;
65
- for (;;) {
66
- const at = haystack.indexOf(needle, from);
67
- if (at === -1) {
68
- return count;
69
- }
70
- count += 1;
71
- from = at + needle.length;
72
- }
73
- }
74
-
75
- // esbuild onLoad plugin: apply the mutation's patches to their target
76
- // sources, enforcing the exactly-once anchor rule per patch. Also asserts
77
- // every patch was actually loaded by the bundle (a patched-but-unbundled
78
- // file would be a silent no-op mutation).
79
- function mutationPlugin(activeMutation) {
80
- const patchesByFile = new Map();
81
- for (const patch of activeMutation.patches) {
82
- const absolute = join(packageRoot, patch.file);
83
- const existing = patchesByFile.get(absolute) ?? [];
84
- existing.push(patch);
85
- patchesByFile.set(absolute, existing);
86
- }
87
- const applied = new Set();
88
-
89
- return {
90
- plugin: {
91
- name: 'differential-mutation',
92
- setup(pluginBuild) {
93
- pluginBuild.onLoad({ filter: /\.ts$/ }, async (args) => {
94
- const patches = patchesByFile.get(args.path);
95
- if (patches === undefined) {
96
- return undefined;
97
- }
98
- let contents = await readFile(args.path, 'utf8');
99
- for (const patch of patches) {
100
- const found = occurrences(contents, patch.find);
101
- if (found !== 1) {
102
- throw new Error(
103
- `mutation ${activeMutation.name}: anchor in ${patch.file} matched ${found} times (must match exactly once); the commander source moved - re-anchor the patch in scripts/differentialMutations.mjs`
104
- );
105
- }
106
- contents = contents.replace(patch.find, patch.replace);
107
- applied.add(`${patch.file}:${patch.find.slice(0, 40)}`);
108
- }
109
- return { contents, loader: 'ts' };
110
- });
111
- },
112
- },
113
- assertAllApplied() {
114
- const expected = activeMutation.patches.length;
115
- if (applied.size !== expected) {
116
- throw new Error(
117
- `mutation ${activeMutation.name}: only ${applied.size} of ${expected} patches were loaded into the bundle - a patched file is not part of the differential entry`
118
- );
119
- }
120
- },
121
- };
122
- }
123
-
124
- // Renamed banner import: unlike the minified dist build, this bundle keeps
125
- // source-level identifiers, and the commander sources themselves import
126
- // createRequire - the published banner's bare name would collide.
127
- const banner = {
128
- js: "import { createRequire as __differentialCreateRequire } from 'node:module';\nconst require = __differentialCreateRequire(import.meta.url);",
129
- };
130
-
131
- const outfile =
132
- mutation === undefined
133
- ? join(packageRoot, '.differential/impl-ts.mjs')
134
- : join(packageRoot, `.differential/impl-ts.mutant-${mutation.name}.mjs`);
135
-
136
- const mutationHooks =
137
- mutation === undefined ? undefined : mutationPlugin(mutation);
138
-
139
- await build({
140
- entryPoints: [join(packageRoot, 'src/differentialCommanderEntry.ts')],
141
- bundle: true,
142
- platform: 'node',
143
- target: 'node20',
144
- format: 'esm',
145
- outfile,
146
- minify: false,
147
- sourcemap: false,
148
- legalComments: 'none',
149
- external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
150
- banner,
151
- plugins: mutationHooks === undefined ? [] : [mutationHooks.plugin],
152
- });
153
-
154
- mutationHooks?.assertAllApplied();
155
-
156
- // The runtime resolves assets/ relative to the bundle (same as dist/).
157
- await mkdir(join(packageRoot, '.differential/assets'), { recursive: true });
158
- await copyFile(
159
- join(packageRoot, 'src/assets/linzumi-logo.svg'),
160
- join(packageRoot, '.differential/assets/linzumi-logo.svg')
161
- );
162
-
163
- // F5: the cross-harness failover bridge rides next to the bundle exactly as
164
- // it does in dist/ (the runner dynamic-imports ./crossHarnessFailover.mjs
165
- // relative to import.meta.url), bundled with the compiled ReScript
166
- // transpiler artifacts resolved at build time. Unlike the dist build there
167
- // is NO stub fallback here: the differential harness must exercise the REAL
168
- // transpile leg, so missing artifacts fail this build loudly.
169
- await build({
170
- entryPoints: [join(packageRoot, 'src/crossHarnessFailover.mjs')],
171
- bundle: true,
172
- platform: 'node',
173
- target: 'node20',
174
- format: 'esm',
175
- outfile: join(packageRoot, '.differential/crossHarnessFailover.mjs'),
176
- minify: false,
177
- sourcemap: false,
178
- legalComments: 'none',
179
- banner,
180
- });
@@ -1,186 +0,0 @@
1
- // Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md
2
- // (M3 cluster 13, onboarding - visual evidence).
3
- // Relationship: Builds the TS TWIN of the onboarding demo entrypoint
4
- // (packages/linzumi-cli-rescript/src/onboarding/CommanderOnboardingDemoMain.res):
5
- // the REAL runSignupFlow mounted on the live terminal - real
6
- // @inquirer/prompts rendering, the real raw-keypress project picker, the
7
- // REAL createSignupServerClient speaking HTTP to the SAME in-process
8
- // ScriptedAuthServer (imported from the ReScript package's compiled
9
- // module - one server implementation, zero drift), replaying the SAME
10
- // commanderOnboardingDemoScenario.json. scripts/onboarding_evidence_
11
- // capture.sh drives both entrypoints with the same tmux key schedule and
12
- // byte-compares the captures.
13
- //
14
- // Determinism: the scenario is dummy data; the only wall-clock effects
15
- // (config-file timestamps) never reach the terminal (the demo runs with
16
- // debugLaunchPayload off unless --debug-signup is passed for ad-hoc use).
17
- import { mkdir, readFile } from 'node:fs/promises';
18
- import { dirname, join } from 'node:path';
19
- import { fileURLToPath } from 'node:url';
20
- import { build } from 'esbuild';
21
-
22
- const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
23
-
24
- const driverSource = `
25
- import { readFileSync } from 'node:fs';
26
- import { join } from 'node:path';
27
- import { runSignupFlow, signupSuggestTasksForProjectForTest, signupPromptCancelMessage } from './src/signupFlow';
28
- import { createSignupServerClient } from './src/signupServerClient';
29
- // The ONE scripted-server implementation: the ReScript package's cluster 3
30
- // double, imported as plain ESM.
31
- import * as ScriptedAuthServer from '../linzumi-cli-rescript/src/parity/ScriptedAuthServer.res.mjs';
32
-
33
- const scenarioPath = join(
34
- '${packageRoot}',
35
- '..',
36
- 'linzumi-cli-rescript',
37
- 'src',
38
- 'onboarding',
39
- 'commanderOnboardingDemoScenario.json'
40
- );
41
- const scenario = JSON.parse(readFileSync(scenarioPath, 'utf8'));
42
-
43
- function reviveProjects(projects) {
44
- return (projects ?? []).map((project) => ({
45
- path: project.path,
46
- language: project.language,
47
- source: project.source,
48
- ...(project.gitHead === undefined || project.gitHead === null
49
- ? {}
50
- : { gitHead: project.gitHead }),
51
- }));
52
- }
53
-
54
- const jsonResponse = (value) =>
55
- ScriptedAuthServer.jsonResponse(200, JSON.stringify(value ?? {}));
56
-
57
- async function main() {
58
- const args = process.argv.slice(2);
59
- const mock = args.includes('--mock');
60
- const handle = await ScriptedAuthServer.start({
61
- routes: [
62
- {
63
- method: 'POST',
64
- path: '/api/v2/signup/email-code/start',
65
- responses: [jsonResponse(scenario.server.emailCodeStart)],
66
- },
67
- {
68
- method: 'POST',
69
- path: '/api/v2/signup/email-code/verify',
70
- responses: [jsonResponse(scenario.server.emailCodeVerify)],
71
- },
72
- {
73
- method: 'POST',
74
- path: '/api/v2/signup/mission-control/complete',
75
- responses: [jsonResponse(scenario.server.missionControlComplete)],
76
- },
77
- {
78
- method: 'POST',
79
- path: '/api/v2/signup/mission-control/start-tasks',
80
- responses: [jsonResponse(scenario.server.missionControlStartTasks)],
81
- },
82
- ],
83
- });
84
- const serviceUrl = handle.baseUrl;
85
- const preflight = scenario.preflight ?? {};
86
- const tools = preflight.tools ?? {};
87
- const demoHome = process.env.LINZUMI_ONBOARDING_DEMO_HOME ?? process.env.HOME ?? '/tmp';
88
- const noopCacheStore = { read: () => undefined, write: () => {} };
89
- try {
90
- await runSignupFlow({
91
- // Real stdio: the prompts default to the REAL inquirer surface and
92
- // the raw-keypress picker (deps.prompts stays undefined).
93
- input: process.stdin,
94
- output: process.stdout,
95
- preflight: {
96
- cwd: demoHome,
97
- homeDir: demoHome,
98
- probeTool: async (command) => {
99
- const tool = tools[command];
100
- if (tool === undefined) {
101
- return { command, available: false };
102
- }
103
- return { command, available: tool.available, version: tool.version ?? undefined };
104
- },
105
- readGitEmail: async () => preflight.gitEmail ?? undefined,
106
- discoverCodeRoots: async () => preflight.codeRoots ?? [],
107
- checkBrowserHandoff: async () => preflight.browserHandoff !== false,
108
- },
109
- projectDiscovery: {
110
- discoverProjects: async () => reviveProjects(scenario.projects),
111
- },
112
- taskSuggestion: {
113
- suggestTasks: (project, output) =>
114
- signupSuggestTasksForProjectForTest({
115
- project,
116
- output,
117
- taskCacheStore: noopCacheStore,
118
- codexTaskRunner: async () => scenario.suggestedTasks ?? [],
119
- }),
120
- },
121
- forceSignup: args.includes('--force-signup'),
122
- serviceUrl,
123
- openBrowser: false,
124
- debugLaunchPayload: args.includes('--debug-signup'),
125
- signupServerClient: mock ? false : createSignupServerClient({ serviceUrl }),
126
- commanderLauncher: async () => ({
127
- status: 'started',
128
- runnerId: scenario.launch?.runnerId ?? 'demo-commander',
129
- restartCommand:
130
- scenario.launch?.restartCommand ?? 'npx -y @linzumi/cli@latest connect',
131
- instanceId: 'demo-instance',
132
- }),
133
- });
134
- await handle.stop();
135
- process.exit(0);
136
- } catch (error) {
137
- await handle.stop();
138
- const message = error instanceof Error ? error.message : String(error);
139
- process.stdout.write((signupPromptCancelMessage(error) ?? message) + '\\n');
140
- process.exit(1);
141
- }
142
- }
143
-
144
- main();
145
- `;
146
-
147
- await mkdir(join(packageRoot, '.differential'), { recursive: true });
148
-
149
- // The build-auth-parity-oracle.mjs banner convention (inquirer's CJS deps
150
- // require node builtins at module scope).
151
- const banner = {
152
- js: "import { createRequire as __onboardingDemoCreateRequire } from 'node:module';\nconst require = __onboardingDemoCreateRequire(import.meta.url);",
153
- };
154
-
155
- await build({
156
- banner,
157
- stdin: {
158
- contents: driverSource,
159
- resolveDir: packageRoot,
160
- sourcefile: 'onboarding-demo-evidence-driver.ts',
161
- loader: 'ts',
162
- },
163
- bundle: true,
164
- platform: 'node',
165
- target: 'node20',
166
- format: 'esm',
167
- outfile: join(packageRoot, '.differential/onboarding-demo-evidence.mjs'),
168
- minify: false,
169
- sourcemap: false,
170
- legalComments: 'none',
171
- external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
172
- });
173
-
174
- // Keep the scenario honest: fail the build loudly if the shared file is
175
- // missing (the twin reads it at RUNTIME from the sibling package).
176
- await readFile(
177
- join(
178
- packageRoot,
179
- '..',
180
- 'linzumi-cli-rescript',
181
- 'src',
182
- 'onboarding',
183
- 'commanderOnboardingDemoScenario.json'
184
- ),
185
- 'utf8'
186
- );
@@ -1,107 +0,0 @@
1
- // Spec: kandan/plans/2026-07-10-compute-nodes-rescript-commander-zero-ts-program.md
2
- // (M3 cluster 11, the TUI - visual evidence).
3
- // Relationship: Builds the TS-side VISUAL-EVIDENCE demo driver: a bundle
4
- // that mounts the REAL TS commander console TUI (reportRunnerConsoleEvent
5
- // on a live TTY) and replays the SAME dummy-event feed the ReScript demo
6
- // entrypoint replays
7
- // (packages/linzumi-cli-rescript/src/tui/commanderTuiDemoFeed.json), so
8
- // the cluster's before/after terminal captures compare the two
9
- // implementations on identical input.
10
- //
11
- // Run (inside a real terminal / tmux pane):
12
- // node scripts/build-tui-demo-evidence.mjs
13
- // LINZUMI_TUI_DEMO_FIXED_NOW=<ms> node .differential/tui-demo.mjs
14
- //
15
- // Env knobs (mirroring the ReScript demo):
16
- // LINZUMI_TUI_DEMO_FIXED_NOW pin Date.now() (and therefore every
17
- // time-ago cell + the render ticker clock)
18
- // so captures are deterministic.
19
- //
20
- // The output is a local evidence artifact (.differential/ is gitignored,
21
- // never published).
22
- import { mkdir } from 'node:fs/promises';
23
- import { dirname, join } from 'node:path';
24
- import { fileURLToPath } from 'node:url';
25
- import { build } from 'esbuild';
26
-
27
- const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
28
-
29
- const driverSource = `
30
- import { readFileSync } from 'node:fs';
31
- import { join } from 'node:path';
32
- import { reportRunnerConsoleEvent } from './src/runnerConsoleReporter';
33
-
34
- const fixedNowRaw = process.env.LINZUMI_TUI_DEMO_FIXED_NOW;
35
- const fixedNow = fixedNowRaw === undefined ? undefined : Number(fixedNowRaw);
36
- if (fixedNow !== undefined && Number.isFinite(fixedNow)) {
37
- const RealDate = Date;
38
- class FixedDate extends RealDate {
39
- constructor(...args) {
40
- if (args.length === 0) {
41
- super(fixedNow);
42
- } else {
43
- super(...args);
44
- }
45
- }
46
- static now() {
47
- return fixedNow;
48
- }
49
- }
50
- globalThis.Date = FixedDate;
51
- }
52
-
53
- const now = Date.now();
54
-
55
- // Resolve *_offset timestamp fields against the demo clock (the ReScript
56
- // demo performs the same resolution).
57
- function resolveOffsets(value) {
58
- if (Array.isArray(value)) {
59
- return value.map(resolveOffsets);
60
- }
61
- if (value !== null && typeof value === 'object') {
62
- const out = {};
63
- for (const [key, entry] of Object.entries(value)) {
64
- if (key.endsWith('_offset') && typeof entry === 'number') {
65
- out[key.slice(0, -'_offset'.length)] = now + entry;
66
- } else {
67
- out[key] = resolveOffsets(entry);
68
- }
69
- }
70
- return out;
71
- }
72
- return value;
73
- }
74
-
75
- const feedPath = join(
76
- process.cwd(),
77
- '../linzumi-cli-rescript/src/tui/commanderTuiDemoFeed.json'
78
- );
79
- const feed = JSON.parse(readFileSync(feedPath, 'utf8'));
80
- for (const entry of feed.events) {
81
- reportRunnerConsoleEvent(entry.event, resolveOffsets(entry.payload));
82
- }
83
-
84
- // Keep the process (and the TUI) alive for interactive navigation; the
85
- // TUI's own C-c binding exits.
86
- setInterval(() => {}, 1000);
87
- `;
88
-
89
- await mkdir(join(packageRoot, '.differential'), { recursive: true });
90
-
91
- await build({
92
- stdin: {
93
- contents: driverSource,
94
- resolveDir: packageRoot,
95
- sourcefile: 'tui-demo-driver.ts',
96
- loader: 'ts',
97
- },
98
- bundle: true,
99
- platform: 'node',
100
- target: 'node20',
101
- format: 'esm',
102
- outfile: join(packageRoot, '.differential/tui-demo.mjs'),
103
- minify: false,
104
- sourcemap: false,
105
- legalComments: 'none',
106
- external: ['ws', 'undici', 'blessed', '@anthropic-ai/claude-agent-sdk'],
107
- });