@linzumi/cli 0.0.99-beta → 0.0.100-beta

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +118 -70
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -58,7 +58,7 @@ Install the CLI or run it with `npx`:
58
58
  ```bash
59
59
  npm install -g @linzumi/cli@latest
60
60
  npx -y @linzumi/cli@latest signup
61
- npx -y @linzumi/cli@0.0.99-beta --version
61
+ npx -y @linzumi/cli@0.0.100-beta --version
62
62
  linzumi --version
63
63
  ```
64
64
 
package/dist/index.js CHANGED
@@ -19803,7 +19803,7 @@ var linzumiCliVersion, linzumiCliVersionText;
19803
19803
  var init_version = __esm({
19804
19804
  "src/version.ts"() {
19805
19805
  "use strict";
19806
- linzumiCliVersion = "0.0.99-beta";
19806
+ linzumiCliVersion = "0.0.100-beta";
19807
19807
  linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
19808
19808
  }
19809
19809
  });
@@ -22098,6 +22098,37 @@ var init_runnerConsoleReporter = __esm({
22098
22098
  }
22099
22099
  });
22100
22100
 
22101
+ // src/threadRebuildSerializer.ts
22102
+ function createThreadRebuildSerializer() {
22103
+ const chains = /* @__PURE__ */ new Map();
22104
+ return {
22105
+ async run(key, fn) {
22106
+ const prior = chains.get(key) ?? Promise.resolve();
22107
+ const run = prior.then(fn, fn);
22108
+ const tail = run.then(
22109
+ () => void 0,
22110
+ () => void 0
22111
+ );
22112
+ chains.set(key, tail);
22113
+ try {
22114
+ return await run;
22115
+ } finally {
22116
+ if (chains.get(key) === tail) {
22117
+ chains.delete(key);
22118
+ }
22119
+ }
22120
+ },
22121
+ activeKeyCount() {
22122
+ return chains.size;
22123
+ }
22124
+ };
22125
+ }
22126
+ var init_threadRebuildSerializer = __esm({
22127
+ "src/threadRebuildSerializer.ts"() {
22128
+ "use strict";
22129
+ }
22130
+ });
22131
+
22101
22132
  // src/telemetry.ts
22102
22133
  import { mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
22103
22134
  import { dirname as dirname11, basename as basename7, join as join18 } from "node:path";
@@ -24699,6 +24730,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
24699
24730
  );
24700
24731
  threadRunnerProcesses.clear();
24701
24732
  });
24733
+ const threadRebuildSerializer = createThreadRebuildSerializer();
24702
24734
  const evictStaleDynamicChannelSession = async (codexThreadId, expectClient) => {
24703
24735
  const session = dynamicChannelSessions.get(codexThreadId);
24704
24736
  const boundClient = dynamicChannelSessionCodexClients.get(codexThreadId);
@@ -24778,81 +24810,96 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
24778
24810
  );
24779
24811
  }
24780
24812
  const runtimeSettings = startInstanceRuntimeSettings(options, control);
24781
- const rebuildOnDeadCodexWorker = shouldUseThreadProcesses(options) ? async (rebuildArgs) => {
24782
- await evictStaleDynamicChannelSession(rebuildArgs.codexThreadId);
24783
- let rebuilt = false;
24784
- for (const message of rebuildArgs.pendingMessages) {
24785
- const reconnectControl = {
24786
- type: "reconnect_thread",
24787
- workspace: workspaceSlug,
24788
- channel: channelSlug,
24789
- threadId: rebuildArgs.kandanThreadId,
24790
- codexThreadId: rebuildArgs.codexThreadId,
24791
- cwd,
24792
- // Carry the conversation context through the rebuild-replay so
24793
- // the respawned worker's developer instructions match what the
24794
- // server would have replayed (parity with the live reconnect
24795
- // control built above at channelSession.linzumiContext).
24796
- ...control.linzumiContext === void 0 ? {} : { linzumiContext: control.linzumiContext },
24797
- ...integerValue(control.rootSeq) === void 0 ? {} : { rootSeq: integerValue(control.rootSeq) },
24798
- sourceSeq: message.seq,
24799
- workDescription: message.body,
24800
- ...runtimeSettings.model === void 0 ? {} : { model: runtimeSettings.model },
24801
- ...runtimeSettings.reasoningEffort === void 0 ? {} : { reasoningEffort: runtimeSettings.reasoningEffort },
24802
- ...runtimeSettings.sandbox === void 0 ? {} : { sandbox: runtimeSettings.sandbox },
24803
- ...runtimeSettings.approvalPolicy === void 0 ? {} : { approvalPolicy: runtimeSettings.approvalPolicy },
24804
- ...runtimeSettings.fast === void 0 ? {} : { fast: runtimeSettings.fast }
24805
- };
24806
- const replayOntoLiveSession = async (options2) => {
24807
- const liveSession = await withCodexStartRequestTimeout(
24808
- "thread/attach",
24809
- resolveLiveDynamicChannelSession(rebuildArgs.codexThreadId, {
24810
- waitForSiblingSpawn: options2.waitForSiblingSpawn
24811
- })
24812
- );
24813
- if (liveSession === void 0) {
24814
- throw new Error(
24815
- `dead-worker rebuild could not resolve a live session for codex thread ${rebuildArgs.codexThreadId}`
24816
- );
24817
- }
24818
- await liveSession.startThreadMessageTurn({
24819
- seq: message.seq,
24820
- body: message.body,
24821
- actorSlug: message.actorSlug,
24822
- actorUserId: message.actorUserId,
24823
- boundStartTimeout: true
24824
- });
24825
- };
24826
- try {
24827
- if (rebuilt) {
24828
- await replayOntoLiveSession({ waitForSiblingSpawn: false });
24829
- } else {
24830
- const startResult = await startThreadRunnerProcess(
24831
- reconnectControl,
24832
- cwd
24813
+ const rebuildOnDeadCodexWorker = shouldUseThreadProcesses(options) ? async (rebuildArgs) => threadRebuildSerializer.run(
24814
+ rebuildArgs.kandanThreadId,
24815
+ async () => {
24816
+ await evictStaleDynamicChannelSession(
24817
+ rebuildArgs.codexThreadId
24818
+ );
24819
+ let rebuilt = false;
24820
+ for (const message of rebuildArgs.pendingMessages) {
24821
+ const reconnectControl = {
24822
+ type: "reconnect_thread",
24823
+ workspace: workspaceSlug,
24824
+ channel: channelSlug,
24825
+ threadId: rebuildArgs.kandanThreadId,
24826
+ codexThreadId: rebuildArgs.codexThreadId,
24827
+ cwd,
24828
+ // Carry the conversation context through the rebuild-replay so
24829
+ // the respawned worker's developer instructions match what the
24830
+ // server would have replayed (parity with the live reconnect
24831
+ // control built above at channelSession.linzumiContext).
24832
+ ...control.linzumiContext === void 0 ? {} : { linzumiContext: control.linzumiContext },
24833
+ ...integerValue(control.rootSeq) === void 0 ? {} : { rootSeq: integerValue(control.rootSeq) },
24834
+ sourceSeq: message.seq,
24835
+ workDescription: message.body,
24836
+ ...runtimeSettings.model === void 0 ? {} : { model: runtimeSettings.model },
24837
+ ...runtimeSettings.reasoningEffort === void 0 ? {} : { reasoningEffort: runtimeSettings.reasoningEffort },
24838
+ ...runtimeSettings.sandbox === void 0 ? {} : { sandbox: runtimeSettings.sandbox },
24839
+ ...runtimeSettings.approvalPolicy === void 0 ? {} : { approvalPolicy: runtimeSettings.approvalPolicy },
24840
+ ...runtimeSettings.fast === void 0 ? {} : { fast: runtimeSettings.fast }
24841
+ };
24842
+ const replayOntoLiveSession = async (options2) => {
24843
+ const liveSession = await withCodexStartRequestTimeout(
24844
+ "thread/attach",
24845
+ resolveLiveDynamicChannelSession(
24846
+ rebuildArgs.codexThreadId,
24847
+ {
24848
+ waitForSiblingSpawn: options2.waitForSiblingSpawn
24849
+ }
24850
+ )
24833
24851
  );
24834
- if (threadStartDelegatedToSibling(startResult)) {
24835
- log2("runner.thread_dead_worker_rebuild_replay_on_sibling", {
24836
- codex_thread_id: rebuildArgs.codexThreadId,
24837
- kandan_thread_id: rebuildArgs.kandanThreadId,
24838
- seq: message.seq
24852
+ if (liveSession === void 0) {
24853
+ throw new Error(
24854
+ `dead-worker rebuild could not resolve a live session for codex thread ${rebuildArgs.codexThreadId}`
24855
+ );
24856
+ }
24857
+ await liveSession.startThreadMessageTurn({
24858
+ seq: message.seq,
24859
+ body: message.body,
24860
+ actorSlug: message.actorSlug,
24861
+ actorUserId: message.actorUserId,
24862
+ boundStartTimeout: true
24863
+ });
24864
+ };
24865
+ try {
24866
+ if (rebuilt) {
24867
+ await replayOntoLiveSession({
24868
+ waitForSiblingSpawn: false
24839
24869
  });
24840
- await replayOntoLiveSession({ waitForSiblingSpawn: true });
24870
+ } else {
24871
+ const startResult = await startThreadRunnerProcess(
24872
+ reconnectControl,
24873
+ cwd
24874
+ );
24875
+ if (threadStartDelegatedToSibling(startResult)) {
24876
+ log2(
24877
+ "runner.thread_dead_worker_rebuild_replay_on_sibling",
24878
+ {
24879
+ codex_thread_id: rebuildArgs.codexThreadId,
24880
+ kandan_thread_id: rebuildArgs.kandanThreadId,
24881
+ seq: message.seq
24882
+ }
24883
+ );
24884
+ await replayOntoLiveSession({
24885
+ waitForSiblingSpawn: true
24886
+ });
24887
+ }
24841
24888
  }
24889
+ rebuilt = true;
24890
+ } catch (error) {
24891
+ log2("runner.thread_dead_worker_rebuild_failed", {
24892
+ codex_thread_id: rebuildArgs.codexThreadId,
24893
+ kandan_thread_id: rebuildArgs.kandanThreadId,
24894
+ seq: message.seq,
24895
+ message: error instanceof Error ? error.message : String(error)
24896
+ });
24897
+ return false;
24842
24898
  }
24843
- rebuilt = true;
24844
- } catch (error) {
24845
- log2("runner.thread_dead_worker_rebuild_failed", {
24846
- codex_thread_id: rebuildArgs.codexThreadId,
24847
- kandan_thread_id: rebuildArgs.kandanThreadId,
24848
- seq: message.seq,
24849
- message: error instanceof Error ? error.message : String(error)
24850
- });
24851
- return false;
24852
24899
  }
24900
+ return rebuilt;
24853
24901
  }
24854
- return rebuilt;
24855
- } : void 0;
24902
+ ) : void 0;
24856
24903
  const session = await attachChannelSession({
24857
24904
  kandan,
24858
24905
  codex: sessionCodex,
@@ -31192,6 +31239,7 @@ var init_runner = __esm({
31192
31239
  init_runnerLockTakeover();
31193
31240
  init_runnerConsoleReporter();
31194
31241
  init_version();
31242
+ init_threadRebuildSerializer();
31195
31243
  init_telemetry();
31196
31244
  init_mcpConfig();
31197
31245
  init_linzumiApiClient();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linzumi/cli",
3
- "version": "0.0.99-beta",
3
+ "version": "0.0.100-beta",
4
4
  "description": "Linzumi CLI — 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": {