@linzumi/cli 0.0.98-beta → 0.0.99-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 +80 -18
  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.98-beta --version
61
+ npx -y @linzumi/cli@0.0.99-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.98-beta";
19806
+ linzumiCliVersion = "0.0.99-beta";
19807
19807
  linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
19808
19808
  }
19809
19809
  });
@@ -24579,6 +24579,17 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
24579
24579
  }
24580
24580
  const dynamicChannelSessions = /* @__PURE__ */ new Map();
24581
24581
  const dynamicChannelSessionAttachInFlight = /* @__PURE__ */ new Map();
24582
+ const dynamicChannelSessionAttachWaiters = /* @__PURE__ */ new Map();
24583
+ const resolveDynamicChannelSessionAttachWaiters = (codexThreadId, session) => {
24584
+ const waiters = dynamicChannelSessionAttachWaiters.get(codexThreadId);
24585
+ if (waiters === void 0) {
24586
+ return;
24587
+ }
24588
+ dynamicChannelSessionAttachWaiters.delete(codexThreadId);
24589
+ for (const waiter of waiters) {
24590
+ waiter(session);
24591
+ }
24592
+ };
24582
24593
  const dynamicChannelSessionCodexClients = /* @__PURE__ */ new Map();
24583
24594
  const codexTurnFailureGuards = /* @__PURE__ */ new Map();
24584
24595
  const lossReportPushes = [];
@@ -24640,6 +24651,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
24640
24651
  );
24641
24652
  dynamicChannelSessions.clear();
24642
24653
  dynamicChannelSessionCodexClients.clear();
24654
+ dynamicChannelSessionAttachWaiters.clear();
24643
24655
  const claudeSessions = [...activeClaudeCodeSessions.values()];
24644
24656
  for (const session of claudeSessions) {
24645
24657
  try {
@@ -24716,6 +24728,28 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
24716
24728
  }
24717
24729
  return true;
24718
24730
  };
24731
+ const resolveLiveDynamicChannelSession = async (codexThreadId, options2 = {}) => {
24732
+ const existing = dynamicChannelSessions.get(codexThreadId);
24733
+ if (existing !== void 0) {
24734
+ return existing;
24735
+ }
24736
+ const inFlight = dynamicChannelSessionAttachInFlight.get(codexThreadId);
24737
+ if (inFlight !== void 0) {
24738
+ const attached = await inFlight;
24739
+ if (attached !== void 0) {
24740
+ return attached;
24741
+ }
24742
+ }
24743
+ const settled = dynamicChannelSessions.get(codexThreadId);
24744
+ if (settled !== void 0 || options2.waitForSiblingSpawn !== true) {
24745
+ return settled;
24746
+ }
24747
+ return await new Promise((resolve12) => {
24748
+ const waiters = dynamicChannelSessionAttachWaiters.get(codexThreadId) ?? [];
24749
+ waiters.push(resolve12);
24750
+ dynamicChannelSessionAttachWaiters.set(codexThreadId, waiters);
24751
+ });
24752
+ };
24719
24753
  const attachThreadSessionWithCodex = async (args) => {
24720
24754
  const { control, cwd, codexThreadId, sessionCodex } = args;
24721
24755
  const portForwardWatcherRootPid = args.portForwardWatcherRootPid;
@@ -24769,20 +24803,42 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
24769
24803
  ...runtimeSettings.approvalPolicy === void 0 ? {} : { approvalPolicy: runtimeSettings.approvalPolicy },
24770
24804
  ...runtimeSettings.fast === void 0 ? {} : { fast: runtimeSettings.fast }
24771
24805
  };
24772
- const liveSession = dynamicChannelSessions.get(
24773
- rebuildArgs.codexThreadId
24774
- );
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
+ };
24775
24826
  try {
24776
- if (liveSession !== void 0 && rebuilt) {
24777
- await liveSession.startThreadMessageTurn({
24778
- seq: message.seq,
24779
- body: message.body,
24780
- actorSlug: message.actorSlug,
24781
- actorUserId: message.actorUserId,
24782
- boundStartTimeout: true
24783
- });
24827
+ if (rebuilt) {
24828
+ await replayOntoLiveSession({ waitForSiblingSpawn: false });
24784
24829
  } else {
24785
- await startThreadRunnerProcess(reconnectControl, cwd);
24830
+ const startResult = await startThreadRunnerProcess(
24831
+ reconnectControl,
24832
+ cwd
24833
+ );
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
24839
+ });
24840
+ await replayOntoLiveSession({ waitForSiblingSpawn: true });
24841
+ }
24786
24842
  }
24787
24843
  rebuilt = true;
24788
24844
  } catch (error) {
@@ -24854,6 +24910,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
24854
24910
  });
24855
24911
  dynamicChannelSessions.set(codexThreadId, session);
24856
24912
  dynamicChannelSessionCodexClients.set(codexThreadId, sessionCodex);
24913
+ resolveDynamicChannelSessionAttachWaiters(codexThreadId, session);
24857
24914
  threadSessionRegistry.upsert({
24858
24915
  workspace: workspaceSlug,
24859
24916
  channel: channelSlug,
@@ -25973,6 +26030,9 @@ function controlTargetsInstance(control, instanceId) {
25973
26030
  function controlInstanceId(control) {
25974
26031
  return "instanceId" in control ? control.instanceId : void 0;
25975
26032
  }
26033
+ function threadStartDelegatedToSibling(startResult) {
26034
+ return startResult !== void 0 && startResult.delegated === true && startResult.threadProcess === "already_started";
26035
+ }
25976
26036
  function shouldUseThreadProcesses(options) {
25977
26037
  if (options.threadProcess?.role === "thread") {
25978
26038
  return false;
@@ -27119,7 +27179,10 @@ async function applyControl(codex, kandan, topic, instanceId, options, agentProv
27119
27179
  ensureCodexProjectTrusted(cwd.cwd);
27120
27180
  }
27121
27181
  const runtimeSettings = startInstanceRuntimeSettings(options, control);
27122
- const startedThreadSession = onStartedThread === void 0 ? void 0 : await onStartedThread(control, cwd.cwd, codexThreadId);
27182
+ const startedThreadSession = onStartedThread === void 0 ? void 0 : await withCodexStartRequestTimeout(
27183
+ "thread/attach",
27184
+ onStartedThread(control, cwd.cwd, codexThreadId)
27185
+ );
27123
27186
  if (workDescription !== void 0) {
27124
27187
  const rootSeq = integerValue(control.rootSeq);
27125
27188
  const sourceSeq = integerValue(control.sourceSeq) ?? rootSeq;
@@ -27811,10 +27874,9 @@ async function startCodexProviderInstance(args) {
27811
27874
  let startedThreadSession;
27812
27875
  if (codexThreadId !== void 0 && args.onStartedThread !== void 0) {
27813
27876
  args.setStartupStage("binding_kandan_thread");
27814
- startedThreadSession = await args.onStartedThread(
27815
- args.control,
27816
- args.cwd,
27817
- codexThreadId
27877
+ startedThreadSession = await withCodexStartRequestTimeout(
27878
+ "thread/attach",
27879
+ args.onStartedThread(args.control, args.cwd, codexThreadId)
27818
27880
  );
27819
27881
  }
27820
27882
  if (codexThreadId !== void 0 && workDescription !== void 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linzumi/cli",
3
- "version": "0.0.98-beta",
3
+ "version": "0.0.99-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": {