@linzumi/cli 0.0.89-beta → 0.0.91-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 +1018 -417
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5338,6 +5338,43 @@ var init_itemProjection = __esm({
5338
5338
  function rowStreamStateIsTerminal(state) {
5339
5339
  return state !== void 0 && terminalRowStreamStates.has(state);
5340
5340
  }
5341
+ function codexProtocolFailureReasonFromItems(items) {
5342
+ for (const value of items) {
5343
+ const reason = codexProtocolFailureReasonFromItem(objectValue(value));
5344
+ if (reason !== void 0) {
5345
+ return reason;
5346
+ }
5347
+ }
5348
+ return void 0;
5349
+ }
5350
+ function codexProtocolFailureReasonFromItem(item) {
5351
+ if (item === void 0) {
5352
+ return void 0;
5353
+ }
5354
+ const explicitReason = stringValue(item.codex_protocol_failure_reason) ?? stringValue(item.protocolFailureReason);
5355
+ if (explicitReason !== void 0) {
5356
+ return explicitReason;
5357
+ }
5358
+ const itemType = stringValue(item.type);
5359
+ if (itemType !== "function_call_output" && itemType !== "custom_tool_call_output") {
5360
+ return void 0;
5361
+ }
5362
+ const output = stringValue(item.output) ?? stringValue(item.result) ?? stringValue(item.text) ?? stringValue(item.content);
5363
+ const unsupportedCall = unsupportedCodexCallName(output);
5364
+ return unsupportedCall === void 0 ? void 0 : `${unsupportedCodexToolCallReasonPrefix}: ${unsupportedCall}`;
5365
+ }
5366
+ function unsupportedCodexCallName(output) {
5367
+ const prefix = "unsupported call:";
5368
+ if (output === void 0) {
5369
+ return void 0;
5370
+ }
5371
+ const normalized = output.trim();
5372
+ if (!normalized.toLowerCase().startsWith(prefix)) {
5373
+ return void 0;
5374
+ }
5375
+ const callName = normalized.slice(prefix.length).trim();
5376
+ return callName === "" ? "unknown" : callName;
5377
+ }
5341
5378
  function createInitialLoopState() {
5342
5379
  return {
5343
5380
  phase: "running",
@@ -5433,6 +5470,19 @@ function handleCodexNotification(state, event, deps, effects) {
5433
5470
  failTurn(state, turn, failureOutcome, failureReason(params), effects, deps);
5434
5471
  return;
5435
5472
  }
5473
+ if (method === "error") {
5474
+ const upstreamReason = upstreamErrorReason(params);
5475
+ if (upstreamReason !== void 0) {
5476
+ turn.lastUpstreamErrorReason = upstreamReason;
5477
+ effects.push(
5478
+ log("codex.upstream_error_captured", {
5479
+ turn_id: turn.turnId,
5480
+ reason: upstreamReason
5481
+ })
5482
+ );
5483
+ }
5484
+ return;
5485
+ }
5436
5486
  if (method === "item/completed" || method === "response_item") {
5437
5487
  handleItemCompleted(turn, params, deps, effects);
5438
5488
  return;
@@ -5482,6 +5532,8 @@ function createTurn(state, turnId, sourceSeq) {
5482
5532
  turnId,
5483
5533
  sourceSeq,
5484
5534
  phase: "active",
5535
+ protocolFailureReason: void 0,
5536
+ lastUpstreamErrorReason: void 0,
5485
5537
  items: []
5486
5538
  };
5487
5539
  state.turns.set(turnId, turn);
@@ -5588,6 +5640,10 @@ function handleDelta(turn, signal, deps, effects) {
5588
5640
  emitRowUpdate(turn, item, deltaIndex, streamState, deps, effects);
5589
5641
  }
5590
5642
  function handleItemCompleted(turn, params, deps, effects) {
5643
+ const completedItem = objectValue(params.item);
5644
+ if (completedItem !== void 0) {
5645
+ turn.protocolFailureReason ??= codexProtocolFailureReasonFromItem(completedItem);
5646
+ }
5591
5647
  const completed = completedItemForNotification(params);
5592
5648
  if (completed === void 0) {
5593
5649
  return;
@@ -5757,6 +5813,7 @@ function handleSnapshot(state, turnId, snapshot, deps, effects) {
5757
5813
  return;
5758
5814
  }
5759
5815
  const rawItems = Array.isArray(snapshot.items) ? snapshot.items : [];
5816
+ turn.protocolFailureReason ??= codexProtocolFailureReasonFromItems(rawItems);
5760
5817
  const projected = projectSnapshotItems(rawItems);
5761
5818
  const consumedItemKeys = /* @__PURE__ */ new Set();
5762
5819
  const matches = /* @__PURE__ */ new Map();
@@ -5862,6 +5919,17 @@ function handleSnapshot(state, turnId, snapshot, deps, effects) {
5862
5919
  const assistantResponseSeen = turn.items.some(
5863
5920
  (item) => item.identity.streamKind === "assistant" && item.posted
5864
5921
  ) || projected.some((proj) => proj.streamKind === "assistant");
5922
+ const terminalFailureReason = turn.protocolFailureReason ?? (assistantResponseSeen ? void 0 : turn.lastUpstreamErrorReason ?? completedWithoutAssistantOutputReason);
5923
+ if (turn.protocolFailureReason !== void 0) {
5924
+ effects.push(
5925
+ log("codex.turn_completed_with_protocol_failure", {
5926
+ thread_key: deps.threadKey,
5927
+ turn_id: turn.turnId,
5928
+ source_seq: turn.sourceSeq,
5929
+ reason: turn.protocolFailureReason
5930
+ })
5931
+ );
5932
+ }
5865
5933
  if (!assistantResponseSeen) {
5866
5934
  effects.push(
5867
5935
  log("codex.turn_completed_without_assistant_output", {
@@ -5880,19 +5948,19 @@ function handleSnapshot(state, turnId, snapshot, deps, effects) {
5880
5948
  thread_key: deps.threadKey,
5881
5949
  turn_id: turn.turnId,
5882
5950
  seq: turn.sourceSeq,
5883
- ...assistantResponseSeen ? { status: "processed" } : {
5951
+ ...terminalFailureReason === void 0 ? { status: "processed" } : {
5884
5952
  status: "failed",
5885
- reason: completedWithoutAssistantOutputReason
5953
+ reason: terminalFailureReason
5886
5954
  }
5887
5955
  },
5888
5956
  resolution: "must_ack"
5889
5957
  });
5890
5958
  effects.push(
5891
- assistantResponseSeen ? { type: "turnTerminal", turnId: turn.turnId, outcome: "completed" } : {
5959
+ terminalFailureReason === void 0 ? { type: "turnTerminal", turnId: turn.turnId, outcome: "completed" } : {
5892
5960
  type: "turnTerminal",
5893
5961
  turnId: turn.turnId,
5894
5962
  outcome: "failed",
5895
- reason: completedWithoutAssistantOutputReason
5963
+ reason: terminalFailureReason
5896
5964
  }
5897
5965
  );
5898
5966
  state.turns.delete(turn.turnId);
@@ -5970,10 +6038,29 @@ function nextStreamSnapshotIndex(item) {
5970
6038
  function failureReason(params) {
5971
6039
  return stringValue(params.reason) ?? stringValue(params.message) ?? stringValue(objectValue(params.error)?.message) ?? stringValue(params.error) ?? "codex_turn_aborted";
5972
6040
  }
6041
+ function upstreamErrorReason(params) {
6042
+ const summaryRaw = stringValue(params.diagnostic_summary) ?? stringValue(objectValue(objectValue(params.diagnostic_payload)?.error)?.message);
6043
+ if (summaryRaw === void 0) {
6044
+ return void 0;
6045
+ }
6046
+ const cleaned = summaryRaw.replace(/<[^>]*>/g, " ").replace(/data:[^"' )]+/g, "").replace(/\s+/g, " ").trim().slice(0, 180);
6047
+ if (cleaned.length === 0) {
6048
+ return void 0;
6049
+ }
6050
+ const status = upstreamErrorHttpStatus(params);
6051
+ return status === void 0 ? `Model gateway error: ${cleaned}` : `Model gateway error (HTTP ${status}): ${cleaned}`;
6052
+ }
6053
+ function upstreamErrorHttpStatus(params) {
6054
+ const error = objectValue(objectValue(params.diagnostic_payload)?.error);
6055
+ const info = objectValue(error?.codexErrorInfo);
6056
+ const disconnected = objectValue(info?.responseStreamDisconnected);
6057
+ const code = disconnected?.httpStatusCode;
6058
+ return typeof code === "number" ? code : void 0;
6059
+ }
5973
6060
  function log(event, fields) {
5974
6061
  return { type: "log", event, fields };
5975
6062
  }
5976
- var terminalRowStreamStates, turnMappingReadyMethod, turnMappingFailedMethod, maxTerminalTurnIds, completedWithoutAssistantOutputReason, turnTerminalFailureMethods, handledNotificationMethods;
6063
+ var terminalRowStreamStates, turnMappingReadyMethod, turnMappingFailedMethod, maxTerminalTurnIds, completedWithoutAssistantOutputReason, unsupportedCodexToolCallReasonPrefix, turnTerminalFailureMethods, handledNotificationMethods;
5977
6064
  var init_transition = __esm({
5978
6065
  "src/pipeline/transition.ts"() {
5979
6066
  "use strict";
@@ -5989,6 +6076,7 @@ var init_transition = __esm({
5989
6076
  turnMappingFailedMethod = "pipeline/turnMappingFailed";
5990
6077
  maxTerminalTurnIds = 512;
5991
6078
  completedWithoutAssistantOutputReason = "Codex completed without producing a response.";
6079
+ unsupportedCodexToolCallReasonPrefix = "Codex emitted unsupported tool call";
5992
6080
  turnTerminalFailureMethods = /* @__PURE__ */ new Map([
5993
6081
  ["turn/failed", "failed"],
5994
6082
  ["turn/aborted", "interrupted"],
@@ -6002,6 +6090,7 @@ var init_transition = __esm({
6002
6090
  "turn/aborted",
6003
6091
  "turn/canceled",
6004
6092
  "turn/cancelled",
6093
+ "error",
6005
6094
  "item/agentMessage/delta",
6006
6095
  "item/reasoning/textDelta",
6007
6096
  "item/commandExecution/outputDelta",
@@ -6543,17 +6632,22 @@ function rawItemFromToolCallMessage(message) {
6543
6632
  const structured = message.structured;
6544
6633
  const itemId = /^item-\d+$/.test(message.itemKey) ? void 0 : message.itemKey;
6545
6634
  const idField = itemId === void 0 ? {} : { id: itemId };
6635
+ const output = typeof structured.output === "string" ? structured.output : "";
6546
6636
  switch (stringValue(structured.kind)) {
6547
- case "codex_command_execution":
6637
+ case "codex_command_execution": {
6638
+ const protocolFailureReason = unsupportedToolCallReason(output);
6639
+ const protocolFailureField = protocolFailureReason === void 0 ? {} : { codex_protocol_failure_reason: protocolFailureReason };
6548
6640
  return {
6549
6641
  type: "commandExecution",
6550
6642
  ...idField,
6643
+ ...protocolFailureField,
6551
6644
  command: stringValue(structured.command) ?? "command",
6552
6645
  cwd: stringValue(structured.cwd) ?? "",
6553
6646
  status: stringValue(structured.status) ?? "",
6554
6647
  ...stringValue(structured.process_id) === void 0 || stringValue(structured.process_id) === "" ? {} : { processId: stringValue(structured.process_id) },
6555
- aggregatedOutput: typeof structured.output === "string" ? structured.output : ""
6648
+ aggregatedOutput: output
6556
6649
  };
6650
+ }
6557
6651
  case "codex_file_change":
6558
6652
  return {
6559
6653
  type: "fileChange",
@@ -6566,6 +6660,15 @@ function rawItemFromToolCallMessage(message) {
6566
6660
  return void 0;
6567
6661
  }
6568
6662
  }
6663
+ function unsupportedToolCallReason(output) {
6664
+ const prefix = "unsupported call:";
6665
+ const normalized = output.trim();
6666
+ if (!normalized.toLowerCase().startsWith(prefix)) {
6667
+ return void 0;
6668
+ }
6669
+ const callName = normalized.slice(prefix.length).trim();
6670
+ return `Codex emitted unsupported tool call: ${callName === "" ? "unknown" : callName}`;
6671
+ }
6569
6672
  function mergeSnapshotItems(readItems, sessionItems) {
6570
6673
  if (sessionItems.length === 0) {
6571
6674
  return [...readItems];
@@ -11596,9 +11699,253 @@ var init_channelSession = __esm({
11596
11699
  }
11597
11700
  });
11598
11701
 
11702
+ // src/runnerThreadSessionRegistry.ts
11703
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, renameSync, writeFileSync } from "node:fs";
11704
+ import { createHash as createHash4 } from "node:crypto";
11705
+ import { dirname as dirname3, join as join6 } from "node:path";
11706
+ import { homedir as homedir5 } from "node:os";
11707
+ function runnerThreadSessionRegistryDir() {
11708
+ const override = process.env.LINZUMI_SESSION_REGISTRY_DIR?.trim();
11709
+ if (override !== void 0 && override !== "") {
11710
+ return override;
11711
+ }
11712
+ return join6(homedir5(), ".linzumi", "session-registry");
11713
+ }
11714
+ function runnerThreadSessionRegistryPath(runnerId) {
11715
+ const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
11716
+ const digest = createHash4("sha256").update(runnerId).digest("hex").slice(0, 8);
11717
+ const stem = sanitized === "" ? "runner" : sanitized;
11718
+ return join6(runnerThreadSessionRegistryDir(), `${stem}.${digest}.json`);
11719
+ }
11720
+ function asString(value) {
11721
+ return typeof value === "string" && value !== "" ? value : void 0;
11722
+ }
11723
+ function asAgentProvider(value) {
11724
+ return value === "codex" || value === "claude-code" ? value : void 0;
11725
+ }
11726
+ function parseRecord(value) {
11727
+ if (!isJsonObject(value)) {
11728
+ return void 0;
11729
+ }
11730
+ const workspace = asString(value.workspace);
11731
+ const channel = asString(value.channel);
11732
+ const kandanThreadId = asString(value.kandanThreadId);
11733
+ const codexThreadId = asString(value.codexThreadId);
11734
+ const cwd = asString(value.cwd);
11735
+ const agentProvider = asAgentProvider(value.agentProvider);
11736
+ const control = isJsonObject(value.control) ? value.control : void 0;
11737
+ const updatedAtMs = typeof value.updatedAtMs === "number" && Number.isFinite(value.updatedAtMs) ? value.updatedAtMs : void 0;
11738
+ if (workspace === void 0 || channel === void 0 || kandanThreadId === void 0 || codexThreadId === void 0 || cwd === void 0 || agentProvider === void 0 || control === void 0 || updatedAtMs === void 0) {
11739
+ return void 0;
11740
+ }
11741
+ return {
11742
+ workspace,
11743
+ channel,
11744
+ kandanThreadId,
11745
+ codexThreadId,
11746
+ cwd,
11747
+ agentProvider,
11748
+ control,
11749
+ updatedAtMs
11750
+ };
11751
+ }
11752
+ function readRegistryFile(path2, log2) {
11753
+ const records = /* @__PURE__ */ new Map();
11754
+ let raw;
11755
+ try {
11756
+ raw = readFileSync5(path2, "utf8");
11757
+ } catch (error) {
11758
+ if (error?.code === "ENOENT") {
11759
+ return records;
11760
+ }
11761
+ log2("session_registry.read_failed", {
11762
+ path: path2,
11763
+ message: error instanceof Error ? error.message : String(error)
11764
+ });
11765
+ return records;
11766
+ }
11767
+ let parsed;
11768
+ try {
11769
+ parsed = JSON.parse(raw);
11770
+ } catch (error) {
11771
+ log2("session_registry.parse_failed", {
11772
+ path: path2,
11773
+ message: error instanceof Error ? error.message : String(error)
11774
+ });
11775
+ return records;
11776
+ }
11777
+ if (!isJsonObject(parsed) || parsed.version !== registryFileVersion || !isJsonObject(parsed.sessions)) {
11778
+ return records;
11779
+ }
11780
+ for (const [key, value] of Object.entries(parsed.sessions)) {
11781
+ const record = parseRecord(value);
11782
+ if (record !== void 0 && record.kandanThreadId === key) {
11783
+ records.set(key, record);
11784
+ }
11785
+ }
11786
+ return records;
11787
+ }
11788
+ function createRunnerThreadSessionRegistryStore(path2, log2) {
11789
+ const records = readRegistryFile(path2, log2);
11790
+ const writeNow = () => {
11791
+ const sessions = {};
11792
+ for (const [key, record] of records) {
11793
+ sessions[key] = {
11794
+ workspace: record.workspace,
11795
+ channel: record.channel,
11796
+ kandanThreadId: record.kandanThreadId,
11797
+ codexThreadId: record.codexThreadId,
11798
+ cwd: record.cwd,
11799
+ agentProvider: record.agentProvider,
11800
+ control: record.control,
11801
+ updatedAtMs: record.updatedAtMs
11802
+ };
11803
+ }
11804
+ try {
11805
+ mkdirSync2(dirname3(path2), { recursive: true });
11806
+ const tmpPath = `${path2}.tmp`;
11807
+ writeFileSync(
11808
+ tmpPath,
11809
+ `${JSON.stringify({ version: registryFileVersion, sessions })}
11810
+ `,
11811
+ "utf8"
11812
+ );
11813
+ renameSync(tmpPath, path2);
11814
+ } catch (error) {
11815
+ log2("session_registry.write_failed", {
11816
+ path: path2,
11817
+ message: error instanceof Error ? error.message : String(error)
11818
+ });
11819
+ }
11820
+ };
11821
+ return {
11822
+ list: () => [...records.values()],
11823
+ upsert: (record) => {
11824
+ records.set(record.kandanThreadId, record);
11825
+ writeNow();
11826
+ },
11827
+ remove: (kandanThreadId) => {
11828
+ if (records.delete(kandanThreadId)) {
11829
+ writeNow();
11830
+ }
11831
+ }
11832
+ };
11833
+ }
11834
+ async function rehydrateThreadSessions(args) {
11835
+ let rehydrated = 0;
11836
+ let retiredDrained = 0;
11837
+ let retiredStale = 0;
11838
+ let retiredUnattachable = 0;
11839
+ let failed = 0;
11840
+ for (const record of args.records) {
11841
+ const ageMs = args.nowMs - record.updatedAtMs;
11842
+ if (ageMs > args.maxAgeMs) {
11843
+ args.retire(record);
11844
+ retiredStale += 1;
11845
+ args.log("session_registry.retired_stale", {
11846
+ workspace: record.workspace,
11847
+ channel: record.channel,
11848
+ thread_id: record.kandanThreadId,
11849
+ age_ms: ageMs
11850
+ });
11851
+ continue;
11852
+ }
11853
+ const pendingRows = args.pendingDurableRowCount(record);
11854
+ if (pendingRows <= 0) {
11855
+ args.retire(record);
11856
+ retiredDrained += 1;
11857
+ args.log("session_registry.retired_drained", {
11858
+ workspace: record.workspace,
11859
+ channel: record.channel,
11860
+ thread_id: record.kandanThreadId
11861
+ });
11862
+ continue;
11863
+ }
11864
+ args.log("session_registry.outbox_replay_started", {
11865
+ workspace: record.workspace,
11866
+ channel: record.channel,
11867
+ thread_id: record.kandanThreadId,
11868
+ codex_thread_id: record.codexThreadId,
11869
+ pending_rows: pendingRows
11870
+ });
11871
+ let result;
11872
+ try {
11873
+ result = await args.attach(record);
11874
+ } catch (error) {
11875
+ args.log("session_registry.outbox_replay_failed", {
11876
+ workspace: record.workspace,
11877
+ channel: record.channel,
11878
+ thread_id: record.kandanThreadId,
11879
+ message: error instanceof Error ? error.message : String(error)
11880
+ });
11881
+ failed += 1;
11882
+ continue;
11883
+ }
11884
+ if (result === "attached") {
11885
+ rehydrated += 1;
11886
+ args.log("session_registry.boot_rehydrated", {
11887
+ workspace: record.workspace,
11888
+ channel: record.channel,
11889
+ thread_id: record.kandanThreadId,
11890
+ codex_thread_id: record.codexThreadId,
11891
+ pending_rows: pendingRows
11892
+ });
11893
+ } else if (result === "retire") {
11894
+ args.retire(record);
11895
+ retiredUnattachable += 1;
11896
+ args.log("session_registry.retired_unattachable", {
11897
+ workspace: record.workspace,
11898
+ channel: record.channel,
11899
+ thread_id: record.kandanThreadId
11900
+ });
11901
+ } else {
11902
+ failed += 1;
11903
+ args.log("session_registry.outbox_replay_failed", {
11904
+ workspace: record.workspace,
11905
+ channel: record.channel,
11906
+ thread_id: record.kandanThreadId,
11907
+ message: "attach_failed"
11908
+ });
11909
+ }
11910
+ }
11911
+ return {
11912
+ rehydrated,
11913
+ retiredDrained,
11914
+ retiredStale,
11915
+ retiredUnattachable,
11916
+ failed
11917
+ };
11918
+ }
11919
+ var registryFileVersion, defaultThreadSessionRehydrationMaxAgeMs;
11920
+ var init_runnerThreadSessionRegistry = __esm({
11921
+ "src/runnerThreadSessionRegistry.ts"() {
11922
+ "use strict";
11923
+ init_protocol();
11924
+ registryFileVersion = 1;
11925
+ defaultThreadSessionRehydrationMaxAgeMs = 24 * 60 * 60 * 1e3;
11926
+ }
11927
+ });
11928
+
11599
11929
  // src/claudeCodePipeline.ts
11600
11930
  import { existsSync as existsSync3 } from "node:fs";
11601
11931
  import { isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
11932
+ function claudeIncompleteProgressCompletionReason(body, bodySource) {
11933
+ if (bodySource !== "assistant_aggregate") {
11934
+ return void 0;
11935
+ }
11936
+ const normalized = body.trim().replace(/\s+/g, " ").toLowerCase();
11937
+ if (normalized === "") {
11938
+ return void 0;
11939
+ }
11940
+ const continuationPatterns = [
11941
+ /\blet me\b.*\bbefore\b.*\b(writing|implementing|editing|patching|making|changing|coding|updating)\b/u,
11942
+ /\blet me\b.*\b(check|inspect|confirm|look|verify|investigate|find|review)\b/u,
11943
+ /\bi(?:'|\u2019)ll\b.*\b(check|inspect|confirm|look|verify|investigate|find|review|write|implement|update|edit|patch|run)\b/u,
11944
+ /\bi will\b.*\b(check|inspect|confirm|look|verify|investigate|find|review|write|implement|update|edit|patch|run)\b/u,
11945
+ /\bnext\b.*\b(i(?:'|\u2019)ll|i will|let me)\b/u
11946
+ ];
11947
+ return continuationPatterns.some((pattern) => pattern.test(normalized)) ? incompleteProgressCompletionReason : void 0;
11948
+ }
11602
11949
  function createClaudeCodeSessionPipeline(host) {
11603
11950
  const sourceSeqByTurn = /* @__PURE__ */ new Map();
11604
11951
  const snapshotsByTurn = /* @__PURE__ */ new Map();
@@ -11728,6 +12075,10 @@ function createClaudeCodeSessionPipeline(host) {
11728
12075
  submit("turn/completed", { turnId: turn.turnId });
11729
12076
  activeTurn = void 0;
11730
12077
  };
12078
+ const failTurn2 = (turn, reason) => {
12079
+ submit("turn/failed", { turnId: turn.turnId, reason });
12080
+ activeTurn = void 0;
12081
+ };
11731
12082
  const handleToolResult = (turn, event) => {
11732
12083
  const pending = turn.pendingTools.get(event.itemKey);
11733
12084
  turn.pendingTools.delete(event.itemKey);
@@ -11945,6 +12296,19 @@ function createClaudeCodeSessionPipeline(host) {
11945
12296
  }
11946
12297
  const turn = ensureTurn();
11947
12298
  lastUsage = event.usage ?? lastUsage;
12299
+ const incompleteProgressReason = claudeIncompleteProgressCompletionReason(
12300
+ event.body,
12301
+ event.bodySource
12302
+ );
12303
+ if (incompleteProgressReason !== void 0) {
12304
+ host.log("claude_pipeline.incomplete_progress_completion", {
12305
+ thread_key: host.threadKey,
12306
+ turn_id: turn.turnId,
12307
+ body_source: event.bodySource ?? "unspecified"
12308
+ });
12309
+ failTurn2(turn, incompleteProgressReason);
12310
+ return;
12311
+ }
11948
12312
  finishTurn(turn, event.body);
11949
12313
  return;
11950
12314
  }
@@ -11954,6 +12318,19 @@ function createClaudeCodeSessionPipeline(host) {
11954
12318
  return;
11955
12319
  }
11956
12320
  lastUsage = event.usage ?? lastUsage;
12321
+ const incompleteProgressReason = claudeIncompleteProgressCompletionReason(
12322
+ event.body,
12323
+ event.bodySource
12324
+ );
12325
+ if (incompleteProgressReason !== void 0) {
12326
+ host.log("claude_pipeline.incomplete_progress_completion", {
12327
+ thread_key: host.threadKey,
12328
+ turn_id: activeTurn.turnId,
12329
+ body_source: event.bodySource ?? "unspecified"
12330
+ });
12331
+ failTurn2(activeTurn, incompleteProgressReason);
12332
+ return;
12333
+ }
11957
12334
  finishTurn(activeTurn, event.body);
11958
12335
  return;
11959
12336
  }
@@ -11966,11 +12343,7 @@ function createClaudeCodeSessionPipeline(host) {
11966
12343
  });
11967
12344
  return;
11968
12345
  }
11969
- submit("turn/failed", {
11970
- turnId: activeTurn.turnId,
11971
- reason: event.reason
11972
- });
11973
- activeTurn = void 0;
12346
+ failTurn2(activeTurn, event.reason);
11974
12347
  return;
11975
12348
  }
11976
12349
  }
@@ -12182,12 +12555,13 @@ function claudeToolInputSummary(input) {
12182
12555
  return void 0;
12183
12556
  }
12184
12557
  }
12185
- var maxRetainedSnapshots, todoStatusGlyphs;
12558
+ var incompleteProgressCompletionReason, maxRetainedSnapshots, todoStatusGlyphs;
12186
12559
  var init_claudeCodePipeline = __esm({
12187
12560
  "src/claudeCodePipeline.ts"() {
12188
12561
  "use strict";
12189
12562
  init_json();
12190
12563
  init_integration();
12564
+ incompleteProgressCompletionReason = "Claude Code ended after an incomplete progress response instead of a final answer";
12191
12565
  maxRetainedSnapshots = 8;
12192
12566
  todoStatusGlyphs = {
12193
12567
  completed: "[x]",
@@ -12321,11 +12695,11 @@ var init_claudeCodePlanMirror = __esm({
12321
12695
  // src/runnerLogger.ts
12322
12696
  import { appendFileSync, openSync as openSync2 } from "node:fs";
12323
12697
  import { createWriteStream } from "node:fs";
12324
- import { homedir as homedir5 } from "node:os";
12325
- import { dirname as dirname3, join as join6 } from "node:path";
12326
- import { mkdirSync as mkdirSync2 } from "node:fs";
12698
+ import { homedir as homedir6 } from "node:os";
12699
+ import { dirname as dirname4, join as join7 } from "node:path";
12700
+ import { mkdirSync as mkdirSync3 } from "node:fs";
12327
12701
  function createRunnerLogger(logFile, consoleReporter) {
12328
- mkdirSync2(dirname3(logFile), { recursive: true });
12702
+ mkdirSync3(dirname4(logFile), { recursive: true });
12329
12703
  const fd = openSync2(logFile, "a");
12330
12704
  const stream = createWriteStream("", { fd, flags: "a", autoClose: true });
12331
12705
  const logger = ((event, payload) => {
@@ -12345,7 +12719,7 @@ function createRunnerLogger(logFile, consoleReporter) {
12345
12719
  function writeCliAuditEvent(event, payload, options = {}) {
12346
12720
  const logFile = options.logFile ?? defaultCliAuditLogFile();
12347
12721
  try {
12348
- mkdirSync2(dirname3(logFile), { recursive: true });
12722
+ mkdirSync3(dirname4(logFile), { recursive: true });
12349
12723
  appendFileSync(
12350
12724
  logFile,
12351
12725
  `${JSON.stringify({
@@ -12363,10 +12737,10 @@ function writeCliAuditEvent(event, payload, options = {}) {
12363
12737
  }
12364
12738
  function defaultCliAuditLogFile() {
12365
12739
  const override = process.env.LINZUMI_CLI_AUDIT_LOG?.trim();
12366
- return override === void 0 || override === "" ? join6(homedir5(), ".linzumi", "logs", "command-events.jsonl") : override;
12740
+ return override === void 0 || override === "" ? join7(homedir6(), ".linzumi", "logs", "command-events.jsonl") : override;
12367
12741
  }
12368
12742
  function defaultRunnerLogFile() {
12369
- return join6(homedir5(), ".linzumi", "logs", "linzumi-runner.log");
12743
+ return join7(homedir6(), ".linzumi", "logs", "linzumi-runner.log");
12370
12744
  }
12371
12745
  function redactForCliLog(value) {
12372
12746
  return redactObject(value);
@@ -12642,12 +13016,12 @@ var init_engineChildReaper = __esm({
12642
13016
 
12643
13017
  // src/claudeCodeLiveBashOutput.ts
12644
13018
  import {
12645
- mkdirSync as mkdirSync3,
13019
+ mkdirSync as mkdirSync4,
12646
13020
  rmSync,
12647
- writeFileSync,
13021
+ writeFileSync as writeFileSync2,
12648
13022
  promises as fsPromises
12649
13023
  } from "node:fs";
12650
- import { join as join7 } from "node:path";
13024
+ import { join as join8 } from "node:path";
12651
13025
  import { StringDecoder } from "node:string_decoder";
12652
13026
  function shellSingleQuoted(value) {
12653
13027
  return `'${value.replaceAll("'", `'\\''`)}'`;
@@ -12772,13 +13146,13 @@ function createClaudeCodeLiveBashCapture(host) {
12772
13146
  isClaudeLiveBashWrappedCommand(command)) {
12773
13147
  return void 0;
12774
13148
  }
12775
- const file = join7(
13149
+ const file = join8(
12776
13150
  host.captureDir,
12777
13151
  `${toolUseId.replaceAll(/[^\w-]/g, "_")}.out`
12778
13152
  );
12779
13153
  try {
12780
- mkdirSync3(host.captureDir, { recursive: true });
12781
- writeFileSync(file, "");
13154
+ mkdirSync4(host.captureDir, { recursive: true });
13155
+ writeFileSync2(file, "");
12782
13156
  } catch (error) {
12783
13157
  host.log?.("claude_live_bash.capture_file_failed", {
12784
13158
  tool_use_id: toolUseId,
@@ -12939,9 +13313,9 @@ var init_claudeCodeTurnStallWatchdog = __esm({
12939
13313
  });
12940
13314
 
12941
13315
  // src/claudeCodeSession.ts
12942
- import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
12943
- import { homedir as homedir6 } from "node:os";
12944
- import { join as join8 } from "node:path";
13316
+ import { existsSync as existsSync4, readFileSync as readFileSync6 } from "node:fs";
13317
+ import { homedir as homedir7 } from "node:os";
13318
+ import { join as join9 } from "node:path";
12945
13319
  function claudeCodeSettingSources() {
12946
13320
  return ["user", "project", "local"];
12947
13321
  }
@@ -13085,7 +13459,7 @@ function claudeCodeRateLimitSummaryText(rateLimit, nowMs) {
13085
13459
  async function probeClaudeCodeAvailability(args) {
13086
13460
  if (!hasClaudeCodeAuthHint(process.env, {
13087
13461
  cwd: args.cwd,
13088
- homeDir: homedir6(),
13462
+ homeDir: homedir7(),
13089
13463
  platform: process.platform,
13090
13464
  fileExists: existsSync4,
13091
13465
  readTextFile: readTextFileIfPresent
@@ -13118,7 +13492,7 @@ async function probeClaudeCodeAvailability(args) {
13118
13492
  }
13119
13493
  }
13120
13494
  function hasClaudeCodeAuthHint(env, deps) {
13121
- const configDir = env.CLAUDE_CONFIG_DIR ?? join8(deps.homeDir, ".claude");
13495
+ const configDir = env.CLAUDE_CONFIG_DIR ?? join9(deps.homeDir, ".claude");
13122
13496
  return hasAnthropicCredentialEnv(env) || hasClaudeCloudProviderEnv(env) || hasClaudeCodeFileCredential(configDir, deps) || hasClaudeCodeApiKeyHelper(configDir, deps) || hasMacClaudeCodeKeychainAnchor(deps);
13123
13497
  }
13124
13498
  function claudeCodePolicyDeferHooks() {
@@ -13153,14 +13527,14 @@ function hasClaudeCloudProviderEnv(env) {
13153
13527
  return trueishEnv(env.CLAUDE_CODE_USE_BEDROCK) || trueishEnv(env.CLAUDE_CODE_USE_VERTEX) || trueishEnv(env.CLAUDE_CODE_USE_FOUNDRY) || trueishEnv(env.CLAUDE_CODE_USE_ANTHROPIC_AWS) || trueishEnv(env.CLAUDE_CODE_USE_MANTLE);
13154
13528
  }
13155
13529
  function hasClaudeCodeFileCredential(configDir, deps) {
13156
- return deps.fileExists(join8(configDir, ".credentials.json")) || deps.fileExists(join8(configDir, ".claude.json")) || deps.fileExists(join8(deps.homeDir, ".claude.json"));
13530
+ return deps.fileExists(join9(configDir, ".credentials.json")) || deps.fileExists(join9(configDir, ".claude.json")) || deps.fileExists(join9(deps.homeDir, ".claude.json"));
13157
13531
  }
13158
13532
  function hasClaudeCodeApiKeyHelper(configDir, deps) {
13159
13533
  return [
13160
- join8(configDir, "settings.json"),
13161
- join8(configDir, "settings.local.json"),
13162
- join8(deps.cwd, ".claude", "settings.json"),
13163
- join8(deps.cwd, ".claude", "settings.local.json")
13534
+ join9(configDir, "settings.json"),
13535
+ join9(configDir, "settings.local.json"),
13536
+ join9(deps.cwd, ".claude", "settings.json"),
13537
+ join9(deps.cwd, ".claude", "settings.local.json")
13164
13538
  ].some((path2) => settingsFileHasApiKeyHelper(path2, deps));
13165
13539
  }
13166
13540
  function settingsFileHasApiKeyHelper(path2, deps) {
@@ -13180,14 +13554,14 @@ function hasMacClaudeCodeKeychainAnchor(deps) {
13180
13554
  return false;
13181
13555
  }
13182
13556
  return [
13183
- join8(deps.homeDir, "Library", "Application Support", "claude-cli-nodejs"),
13184
- join8(deps.homeDir, "Library", "Application Support", "Claude"),
13185
- join8(deps.homeDir, "Library", "Preferences", "claude-cli-nodejs")
13557
+ join9(deps.homeDir, "Library", "Application Support", "claude-cli-nodejs"),
13558
+ join9(deps.homeDir, "Library", "Application Support", "Claude"),
13559
+ join9(deps.homeDir, "Library", "Preferences", "claude-cli-nodejs")
13186
13560
  ].some((path2) => deps.fileExists(path2));
13187
13561
  }
13188
13562
  function readTextFileIfPresent(path2) {
13189
13563
  try {
13190
- return readFileSync5(path2, "utf8");
13564
+ return readFileSync6(path2, "utf8");
13191
13565
  } catch (_error) {
13192
13566
  return void 0;
13193
13567
  }
@@ -13322,7 +13696,9 @@ async function startClaudeCodeSession(options) {
13322
13696
  return completeClaudeCodeSession(options, state);
13323
13697
  }
13324
13698
  async function emitClaudeCodeTurnCompleted(options, state) {
13325
- const body = state.resultText ?? nonEmptyText(claudeAssistantAggregateText(state)) ?? "";
13699
+ const aggregateText = nonEmptyText(claudeAssistantAggregateText(state));
13700
+ const body = state.resultText ?? aggregateText ?? "";
13701
+ const bodySource = state.resultText !== void 0 ? "result" : aggregateText !== void 0 ? "assistant_aggregate" : "empty";
13326
13702
  if (state.sessionId === void 0) {
13327
13703
  return;
13328
13704
  }
@@ -13330,12 +13706,17 @@ async function emitClaudeCodeTurnCompleted(options, state) {
13330
13706
  type: "turn_completed",
13331
13707
  sessionId: state.sessionId,
13332
13708
  body,
13709
+ bodySource,
13333
13710
  usage: state.usage
13334
13711
  });
13335
13712
  }
13336
13713
  async function completeClaudeCodeSession(options, state) {
13337
- const body = state.resultText ?? nonEmptyText(claudeAssistantAggregateText(state)) ?? state.lastCompletedTurnBody;
13338
- if (body === void 0) {
13714
+ const aggregateText = nonEmptyText(claudeAssistantAggregateText(state));
13715
+ const completion = state.resultText !== void 0 ? { body: state.resultText, bodySource: "result" } : aggregateText !== void 0 ? { body: aggregateText, bodySource: "assistant_aggregate" } : state.lastCompletedTurnBody !== void 0 ? {
13716
+ body: state.lastCompletedTurnBody,
13717
+ bodySource: "last_completed_turn"
13718
+ } : void 0;
13719
+ if (completion === void 0) {
13339
13720
  return await failClaudeCodeSession(
13340
13721
  options,
13341
13722
  state.sessionId,
@@ -13351,13 +13732,14 @@ async function completeClaudeCodeSession(options, state) {
13351
13732
  }
13352
13733
  const result = {
13353
13734
  sessionId: state.sessionId,
13354
- body,
13735
+ body: completion.body,
13355
13736
  usage: state.usage
13356
13737
  };
13357
13738
  await options.onTranscriptEvent?.({
13358
13739
  type: "session_completed",
13359
13740
  sessionId: result.sessionId,
13360
13741
  body: result.body,
13742
+ bodySource: completion.bodySource,
13361
13743
  usage: result.usage
13362
13744
  });
13363
13745
  return result;
@@ -14093,10 +14475,10 @@ var init_engineParentDeathWatchdog = __esm({
14093
14475
  import {
14094
14476
  spawn as spawn2
14095
14477
  } from "node:child_process";
14096
- import { readFileSync as readFileSync6 } from "node:fs";
14478
+ import { readFileSync as readFileSync7 } from "node:fs";
14097
14479
  import { createServer } from "node:net";
14098
- import { homedir as homedir7 } from "node:os";
14099
- import { join as join9 } from "node:path";
14480
+ import { homedir as homedir8 } from "node:os";
14481
+ import { join as join10 } from "node:path";
14100
14482
  import { WebSocket as NodeWebSocket } from "ws";
14101
14483
  async function chooseLoopbackPort() {
14102
14484
  return new Promise((resolve12, reject) => {
@@ -14346,10 +14728,10 @@ function resolveForwardableOpenAiApiKey(env = process.env) {
14346
14728
  return fromEnv;
14347
14729
  }
14348
14730
  const codexHomeRaw = env.CODEX_HOME?.trim();
14349
- const codexHome = codexHomeRaw !== void 0 && codexHomeRaw !== "" ? codexHomeRaw : join9(homedir7(), ".codex");
14731
+ const codexHome = codexHomeRaw !== void 0 && codexHomeRaw !== "" ? codexHomeRaw : join10(homedir8(), ".codex");
14350
14732
  let raw;
14351
14733
  try {
14352
- raw = readFileSync6(join9(codexHome, "auth.json"), "utf8");
14734
+ raw = readFileSync7(join10(codexHome, "auth.json"), "utf8");
14353
14735
  } catch (_error) {
14354
14736
  return void 0;
14355
14737
  }
@@ -14694,22 +15076,22 @@ var init_codexAppServer = __esm({
14694
15076
  // src/codexProjectTrust.ts
14695
15077
  import {
14696
15078
  existsSync as existsSync5,
14697
- mkdirSync as mkdirSync4,
14698
- readFileSync as readFileSync7,
15079
+ mkdirSync as mkdirSync5,
15080
+ readFileSync as readFileSync8,
14699
15081
  realpathSync,
14700
- writeFileSync as writeFileSync2
15082
+ writeFileSync as writeFileSync3
14701
15083
  } from "node:fs";
14702
- import { homedir as homedir8 } from "node:os";
14703
- import { join as join10, resolve as resolve3 } from "node:path";
15084
+ import { homedir as homedir9 } from "node:os";
15085
+ import { join as join11, resolve as resolve3 } from "node:path";
14704
15086
  function ensureCodexProjectTrusted(projectPath, options = {}) {
14705
15087
  const trustedPath = realpathSync(resolve3(projectPath));
14706
- const configHome = options.configHome ?? process.env.CODEX_HOME ?? join10(homedir8(), ".codex");
14707
- const configPath = join10(configHome, "config.toml");
14708
- const currentConfig = existsSync5(configPath) ? readFileSync7(configPath, "utf8") : "";
15088
+ const configHome = options.configHome ?? process.env.CODEX_HOME ?? join11(homedir9(), ".codex");
15089
+ const configPath = join11(configHome, "config.toml");
15090
+ const currentConfig = existsSync5(configPath) ? readFileSync8(configPath, "utf8") : "";
14709
15091
  const nextConfig = codexConfigWithTrustedProject(currentConfig, trustedPath);
14710
15092
  if (nextConfig !== currentConfig) {
14711
- mkdirSync4(configHome, { recursive: true });
14712
- writeFileSync2(configPath, nextConfig);
15093
+ mkdirSync5(configHome, { recursive: true });
15094
+ writeFileSync3(configPath, nextConfig);
14713
15095
  }
14714
15096
  return trustedPath;
14715
15097
  }
@@ -15054,7 +15436,7 @@ var init_codexNotificationConsoleStats = __esm({
15054
15436
 
15055
15437
  // src/localCapabilities.ts
15056
15438
  import { realpathSync as realpathSync2 } from "node:fs";
15057
- import { homedir as homedir9 } from "node:os";
15439
+ import { homedir as homedir10 } from "node:os";
15058
15440
  import { isAbsolute as isAbsolute3, relative as relative2, resolve as resolve4 } from "node:path";
15059
15441
  function parseAllowedCwdList(value) {
15060
15442
  if (value === void 0) {
@@ -15103,7 +15485,7 @@ function expandUserPath(pathValue) {
15103
15485
  }
15104
15486
  function currentHomeDirectory() {
15105
15487
  const configuredHome = process.env.HOME;
15106
- return configuredHome === void 0 || configuredHome.trim() === "" ? homedir9() : configuredHome;
15488
+ return configuredHome === void 0 || configuredHome.trim() === "" ? homedir10() : configuredHome;
15107
15489
  }
15108
15490
  function resolveAllowedCwd(requestedCwd, allowedRoots) {
15109
15491
  if (requestedCwd === void 0 || requestedCwd.trim() === "") {
@@ -15661,17 +16043,17 @@ import {
15661
16043
  chmodSync,
15662
16044
  existsSync as existsSync6,
15663
16045
  linkSync,
15664
- mkdirSync as mkdirSync5,
15665
- readFileSync as readFileSync8,
16046
+ mkdirSync as mkdirSync6,
16047
+ readFileSync as readFileSync9,
15666
16048
  realpathSync as realpathSync3,
15667
16049
  unlinkSync,
15668
- writeFileSync as writeFileSync3
16050
+ writeFileSync as writeFileSync4
15669
16051
  } from "node:fs";
15670
- import { homedir as homedir10 } from "node:os";
15671
- import { basename as basename5, dirname as dirname4, join as join11, resolve as resolve5 } from "node:path";
16052
+ import { homedir as homedir11 } from "node:os";
16053
+ import { basename as basename5, dirname as dirname5, join as join12, resolve as resolve5 } from "node:path";
15672
16054
  function localConfigPath(env = process.env) {
15673
16055
  const override = env.LINZUMI_CONFIG_FILE;
15674
- return override !== void 0 && override.trim() !== "" ? resolve5(expandUserPath(override)) : resolve5(homedir10(), ".linzumi", "config.json");
16056
+ return override !== void 0 && override.trim() !== "" ? resolve5(expandUserPath(override)) : resolve5(homedir11(), ".linzumi", "config.json");
15675
16057
  }
15676
16058
  function localConfigScopeKey(linzumiUrl) {
15677
16059
  const normalizedUrl = kandanHttpBaseUrl(linzumiUrl);
@@ -15752,21 +16134,21 @@ function ensureLocalRunnerId(path2 = localConfigPath(), createRunnerId = default
15752
16134
  }
15753
16135
  function localMachineIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
15754
16136
  if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
15755
- return join11(
15756
- dirname4(configPath),
16137
+ return join12(
16138
+ dirname5(configPath),
15757
16139
  `${basename5(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.machine-id`
15758
16140
  );
15759
16141
  }
15760
- return join11(dirname4(configPath), `${basename5(configPath)}.machine-id`);
16142
+ return join12(dirname5(configPath), `${basename5(configPath)}.machine-id`);
15761
16143
  }
15762
16144
  function localRunnerIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
15763
16145
  if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
15764
- return join11(
15765
- dirname4(configPath),
16146
+ return join12(
16147
+ dirname5(configPath),
15766
16148
  `${basename5(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.runner-id`
15767
16149
  );
15768
16150
  }
15769
- return join11(dirname4(configPath), `${basename5(configPath)}.runner-id`);
16151
+ return join12(dirname5(configPath), `${basename5(configPath)}.runner-id`);
15770
16152
  }
15771
16153
  function readConfiguredAllowedCwdDetailsForLinzumiUrl(linzumiUrl, path2 = localConfigPath()) {
15772
16154
  return readConfiguredAllowedCwdDetailsFromConfig(
@@ -15896,7 +16278,7 @@ function writeLocalSignupAuth(auth, path2 = localConfigPath()) {
15896
16278
  version: 1,
15897
16279
  signupAuth: nextSignupAuth
15898
16280
  };
15899
- mkdirSync5(dirname4(path2), { recursive: true });
16281
+ mkdirSync6(dirname5(path2), { recursive: true });
15900
16282
  writeLocalConfigJson(path2, next);
15901
16283
  return signupAuthFromJson(nextSignupAuth);
15902
16284
  }
@@ -15904,7 +16286,7 @@ function writeLocalConfigJson(path2, payload) {
15904
16286
  if (existsSync6(path2)) {
15905
16287
  chmodSync(path2, localConfigFileMode);
15906
16288
  }
15907
- writeFileSync3(path2, `${JSON.stringify(payload, null, 2)}
16289
+ writeFileSync4(path2, `${JSON.stringify(payload, null, 2)}
15908
16290
  `, {
15909
16291
  encoding: "utf8",
15910
16292
  mode: localConfigFileMode
@@ -15931,7 +16313,7 @@ function readLocalConfigFile(path2) {
15931
16313
  if (!existsSync6(path2)) {
15932
16314
  return { version: 1, allowedCwds: [] };
15933
16315
  }
15934
- const parsed = JSON.parse(readFileSync8(path2, "utf8"));
16316
+ const parsed = JSON.parse(readFileSync9(path2, "utf8"));
15935
16317
  if (!isConfigPayload(parsed)) {
15936
16318
  throw new Error(`invalid Linzumi config: ${path2}`);
15937
16319
  }
@@ -15960,7 +16342,7 @@ function writeLocalConfigSection(config, path2, linzumiUrl) {
15960
16342
  version: 1,
15961
16343
  [scopeKey]: nextSection
15962
16344
  };
15963
- mkdirSync5(dirname4(path2), { recursive: true });
16345
+ mkdirSync6(dirname5(path2), { recursive: true });
15964
16346
  writeLocalConfigJson(path2, next);
15965
16347
  }
15966
16348
  function isConfigPayload(value) {
@@ -16035,12 +16417,12 @@ function ensureLocalMachineIdSeed(configPath, createMachineId, linzumiUrl) {
16035
16417
  if (!machineIdValid(machineId)) {
16036
16418
  throw new Error(`invalid generated Linzumi machine id: ${machineId}`);
16037
16419
  }
16038
- mkdirSync5(dirname4(seedPath), { recursive: true });
16039
- const tempPath = join11(
16040
- dirname4(seedPath),
16420
+ mkdirSync6(dirname5(seedPath), { recursive: true });
16421
+ const tempPath = join12(
16422
+ dirname5(seedPath),
16041
16423
  `.${basename5(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
16042
16424
  );
16043
- writeFileSync3(tempPath, `${machineId}
16425
+ writeFileSync4(tempPath, `${machineId}
16044
16426
  `, { encoding: "utf8", flag: "wx" });
16045
16427
  try {
16046
16428
  linkSync(tempPath, seedPath);
@@ -16063,12 +16445,12 @@ function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
16063
16445
  if (!runnerIdValid(runnerId)) {
16064
16446
  throw new Error(`invalid generated Linzumi runner id: ${runnerId}`);
16065
16447
  }
16066
- mkdirSync5(dirname4(seedPath), { recursive: true });
16067
- const tempPath = join11(
16068
- dirname4(seedPath),
16448
+ mkdirSync6(dirname5(seedPath), { recursive: true });
16449
+ const tempPath = join12(
16450
+ dirname5(seedPath),
16069
16451
  `.${basename5(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
16070
16452
  );
16071
- writeFileSync3(tempPath, `${runnerId}
16453
+ writeFileSync4(tempPath, `${runnerId}
16072
16454
  `, { encoding: "utf8", flag: "wx" });
16073
16455
  try {
16074
16456
  linkSync(tempPath, seedPath);
@@ -16083,14 +16465,14 @@ function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
16083
16465
  }
16084
16466
  }
16085
16467
  function readMachineIdSeed(seedPath) {
16086
- const machineId = readFileSync8(seedPath, "utf8").trim();
16468
+ const machineId = readFileSync9(seedPath, "utf8").trim();
16087
16469
  if (!machineIdValid(machineId)) {
16088
16470
  throw new Error(`invalid Linzumi machine id seed: ${seedPath}`);
16089
16471
  }
16090
16472
  return machineId;
16091
16473
  }
16092
16474
  function readRunnerIdSeed(seedPath) {
16093
- const runnerId = readFileSync8(seedPath, "utf8").trim();
16475
+ const runnerId = readFileSync9(seedPath, "utf8").trim();
16094
16476
  if (!runnerIdValid(runnerId)) {
16095
16477
  throw new Error(`invalid Linzumi runner id seed: ${seedPath}`);
16096
16478
  }
@@ -16389,8 +16771,8 @@ var init_remoteCodexExecutionContext = __esm({
16389
16771
  });
16390
16772
 
16391
16773
  // src/helloLinzumiProject.ts
16392
- import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync9, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
16393
- import { dirname as dirname5, join as join12, resolve as resolve6 } from "node:path";
16774
+ import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync10, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
16775
+ import { dirname as dirname6, join as join13, resolve as resolve6 } from "node:path";
16394
16776
  import { fileURLToPath as fileURLToPath2 } from "node:url";
16395
16777
  function createHelloLinzumiProject(input = {}) {
16396
16778
  const options = typeof input === "string" ? { rootPath: input } : input;
@@ -16399,9 +16781,9 @@ function createHelloLinzumiProject(input = {}) {
16399
16781
  const host = normalizeHost(options.host);
16400
16782
  assertTcpPort(port);
16401
16783
  assertWritableDemoRoot(root, options.reset === true);
16402
- mkdirSync6(join12(root, "src"), { recursive: true });
16784
+ mkdirSync7(join13(root, "src"), { recursive: true });
16403
16785
  for (const file of demoFiles({ root, port, host })) {
16404
- writeFileSync4(join12(root, file.path), file.content, "utf8");
16786
+ writeFileSync5(join13(root, file.path), file.content, "utf8");
16405
16787
  }
16406
16788
  return {
16407
16789
  root,
@@ -16445,8 +16827,8 @@ function assertWritableDemoRoot(root, reset) {
16445
16827
  if (!existsSync7(root)) {
16446
16828
  return;
16447
16829
  }
16448
- const markerPath = join12(root, markerFile);
16449
- const isDemoRoot = existsSync7(markerPath) && readFileSync9(markerPath, "utf8").trim() === "hello-linzumi";
16830
+ const markerPath = join13(root, markerFile);
16831
+ const isDemoRoot = existsSync7(markerPath) && readFileSync10(markerPath, "utf8").trim() === "hello-linzumi";
16450
16832
  if (isDemoRoot && reset) {
16451
16833
  rmSync2(root, { recursive: true, force: true });
16452
16834
  return;
@@ -16480,8 +16862,8 @@ var init_helloLinzumiProject = __esm({
16480
16862
  defaultHelloLinzumiPort = 8787;
16481
16863
  defaultHelloLinzumiHost = "0.0.0.0";
16482
16864
  markerFile = ".linzumi-demo-project";
16483
- moduleDir = dirname5(fileURLToPath2(import.meta.url));
16484
- linzumiLogoSvg = readFileSync9(join12(moduleDir, "assets", "linzumi-logo.svg"), "utf8");
16865
+ moduleDir = dirname6(fileURLToPath2(import.meta.url));
16866
+ linzumiLogoSvg = readFileSync10(join13(moduleDir, "assets", "linzumi-logo.svg"), "utf8");
16485
16867
  packageJson = `${JSON.stringify(
16486
16868
  {
16487
16869
  name: "hello-linzumi",
@@ -17283,14 +17665,14 @@ import {
17283
17665
  copyFileSync,
17284
17666
  cpSync,
17285
17667
  existsSync as existsSync8,
17286
- mkdirSync as mkdirSync7,
17668
+ mkdirSync as mkdirSync8,
17287
17669
  mkdtempSync,
17288
- readFileSync as readFileSync10,
17670
+ readFileSync as readFileSync11,
17289
17671
  realpathSync as realpathSync4,
17290
- writeFileSync as writeFileSync5
17672
+ writeFileSync as writeFileSync6
17291
17673
  } from "node:fs";
17292
17674
  import { tmpdir } from "node:os";
17293
- import { basename as basename6, delimiter, dirname as dirname6, join as join13 } from "node:path";
17675
+ import { basename as basename6, delimiter, dirname as dirname7, join as join14 } from "node:path";
17294
17676
  function isStartLocalEditorControl(control) {
17295
17677
  return control.type === "start_local_editor";
17296
17678
  }
@@ -17508,24 +17890,24 @@ function codeServerArgs(port, cwd, userDataDir, extensionsDir) {
17508
17890
  }
17509
17891
  function prepareCodeServerProfile(collaboration, editorRuntime) {
17510
17892
  try {
17511
- const userDataDir = mkdtempSync(join13(tmpdir(), "kandan-local-editor-"));
17512
- const extensionsDir = join13(userDataDir, "extensions");
17513
- const collaborationServerDir = join13(userDataDir, "collaboration-server");
17514
- const tempDir = join13(userDataDir, "tmp");
17515
- const userSettingsDir = join13(userDataDir, "User");
17516
- mkdirSync7(userSettingsDir, { recursive: true });
17517
- mkdirSync7(extensionsDir, { recursive: true });
17518
- mkdirSync7(collaborationServerDir, { recursive: true });
17519
- mkdirSync7(tempDir, { recursive: true });
17893
+ const userDataDir = mkdtempSync(join14(tmpdir(), "kandan-local-editor-"));
17894
+ const extensionsDir = join14(userDataDir, "extensions");
17895
+ const collaborationServerDir = join14(userDataDir, "collaboration-server");
17896
+ const tempDir = join14(userDataDir, "tmp");
17897
+ const userSettingsDir = join14(userDataDir, "User");
17898
+ mkdirSync8(userSettingsDir, { recursive: true });
17899
+ mkdirSync8(extensionsDir, { recursive: true });
17900
+ mkdirSync8(collaborationServerDir, { recursive: true });
17901
+ mkdirSync8(tempDir, { recursive: true });
17520
17902
  if (editorRuntime !== void 0) {
17521
17903
  ensureCodeServerBrowserExtensionAssets(editorRuntime);
17522
17904
  installDirectory(
17523
17905
  editorRuntime.assets.documentStateExtensionDir,
17524
- join13(extensionsDir, "kandan.document-state-telemetry")
17906
+ join14(extensionsDir, "kandan.document-state-telemetry")
17525
17907
  );
17526
17908
  }
17527
- writeFileSync5(
17528
- join13(userSettingsDir, "settings.json"),
17909
+ writeFileSync6(
17910
+ join14(userSettingsDir, "settings.json"),
17529
17911
  JSON.stringify(codeServerSettings(collaboration), null, 2)
17530
17912
  );
17531
17913
  return { ok: true, userDataDir, extensionsDir, collaborationServerDir };
@@ -17537,14 +17919,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17537
17919
  const vscodeRoot = codeServerVscodeRoot(runtime);
17538
17920
  const repairs = [
17539
17921
  {
17540
- source: join13(
17922
+ source: join14(
17541
17923
  vscodeRoot,
17542
17924
  "extensions",
17543
17925
  "git-base",
17544
17926
  "dist",
17545
17927
  "extension.js"
17546
17928
  ),
17547
- target: join13(
17929
+ target: join14(
17548
17930
  vscodeRoot,
17549
17931
  "extensions",
17550
17932
  "git-base",
@@ -17555,14 +17937,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17555
17937
  required: true
17556
17938
  },
17557
17939
  {
17558
- source: join13(
17940
+ source: join14(
17559
17941
  vscodeRoot,
17560
17942
  "extensions",
17561
17943
  "git-base",
17562
17944
  "dist",
17563
17945
  "extension.js.map"
17564
17946
  ),
17565
- target: join13(
17947
+ target: join14(
17566
17948
  vscodeRoot,
17567
17949
  "extensions",
17568
17950
  "git-base",
@@ -17573,14 +17955,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17573
17955
  required: false
17574
17956
  },
17575
17957
  {
17576
- source: join13(
17958
+ source: join14(
17577
17959
  vscodeRoot,
17578
17960
  "extensions",
17579
17961
  "merge-conflict",
17580
17962
  "dist",
17581
17963
  "mergeConflictMain.js"
17582
17964
  ),
17583
- target: join13(
17965
+ target: join14(
17584
17966
  vscodeRoot,
17585
17967
  "extensions",
17586
17968
  "merge-conflict",
@@ -17591,14 +17973,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17591
17973
  required: true
17592
17974
  },
17593
17975
  {
17594
- source: join13(
17976
+ source: join14(
17595
17977
  vscodeRoot,
17596
17978
  "extensions",
17597
17979
  "merge-conflict",
17598
17980
  "dist",
17599
17981
  "mergeConflictMain.js.map"
17600
17982
  ),
17601
- target: join13(
17983
+ target: join14(
17602
17984
  vscodeRoot,
17603
17985
  "extensions",
17604
17986
  "merge-conflict",
@@ -17616,7 +17998,7 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17616
17998
  case (!required3 && !existsSync8(source)):
17617
17999
  return;
17618
18000
  default:
17619
- mkdirSync7(dirname6(target), { recursive: true });
18001
+ mkdirSync8(dirname7(target), { recursive: true });
17620
18002
  copyFileSync(source, target);
17621
18003
  return;
17622
18004
  }
@@ -17624,10 +18006,10 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17624
18006
  }
17625
18007
  function codeServerVscodeRoot(runtime) {
17626
18008
  const roots = uniquePaths([
17627
- join13(runtime.root, "lib", "vscode"),
17628
- join13(dirname6(dirname6(runtime.codeServerBin)), "lib", "vscode"),
18009
+ join14(runtime.root, "lib", "vscode"),
18010
+ join14(dirname7(dirname7(runtime.codeServerBin)), "lib", "vscode"),
17629
18011
  ...wrappedCodeServerBin(runtime.codeServerBin).map(
17630
- (codeServerBin) => join13(dirname6(dirname6(codeServerBin)), "lib", "vscode")
18012
+ (codeServerBin) => join14(dirname7(dirname7(codeServerBin)), "lib", "vscode")
17631
18013
  )
17632
18014
  ]);
17633
18015
  const rootWithRequiredAssets = roots.find(
@@ -17643,7 +18025,7 @@ function codeServerVscodeRoot(runtime) {
17643
18025
  }
17644
18026
  function wrappedCodeServerBin(codeServerBin) {
17645
18027
  try {
17646
- const script = readFileSync10(codeServerBin, "utf8");
18028
+ const script = readFileSync11(codeServerBin, "utf8");
17647
18029
  const match = script.match(
17648
18030
  /exec\s+(?:"([^"]+)"|'([^']+)'|([^\s]+))\s+"\$@"/u
17649
18031
  );
@@ -17655,8 +18037,8 @@ function wrappedCodeServerBin(codeServerBin) {
17655
18037
  }
17656
18038
  function codeServerBrowserAssetSources(vscodeRoot) {
17657
18039
  return [
17658
- join13(vscodeRoot, "extensions", "git-base", "dist", "extension.js"),
17659
- join13(
18040
+ join14(vscodeRoot, "extensions", "git-base", "dist", "extension.js"),
18041
+ join14(
17660
18042
  vscodeRoot,
17661
18043
  "extensions",
17662
18044
  "merge-conflict",
@@ -17735,10 +18117,10 @@ function prepareLinuxCodeServerLaunch(options) {
17735
18117
  options.cwd,
17736
18118
  "--setenv",
17737
18119
  "XDG_DATA_HOME",
17738
- join13(options.userDataDir, "data"),
18120
+ join14(options.userDataDir, "data"),
17739
18121
  "--setenv",
17740
18122
  "XDG_CONFIG_HOME",
17741
- join13(options.userDataDir, "config"),
18123
+ join14(options.userDataDir, "config"),
17742
18124
  ...readOnlyRoots.flatMap((path2) => ["--ro-bind-try", path2, path2]),
17743
18125
  "--bind",
17744
18126
  options.cwd,
@@ -17779,12 +18161,12 @@ function resolveCodeServerExecutable(command, envPath) {
17779
18161
  if (directory.trim() === "") {
17780
18162
  continue;
17781
18163
  }
17782
- const candidate = join13(directory, command);
18164
+ const candidate = join14(directory, command);
17783
18165
  if (!existsSync8(candidate)) {
17784
18166
  continue;
17785
18167
  }
17786
18168
  const realpath2 = realpathSync4(candidate);
17787
- return { ok: true, command: realpath2, directory: dirname6(realpath2) };
18169
+ return { ok: true, command: realpath2, directory: dirname7(realpath2) };
17788
18170
  }
17789
18171
  return { ok: false };
17790
18172
  }
@@ -17793,10 +18175,10 @@ function hasPathSeparator(path2) {
17793
18175
  }
17794
18176
  function safeRealpathDir(path2) {
17795
18177
  try {
17796
- const directory = dirname6(realpathSync4(path2));
18178
+ const directory = dirname7(realpathSync4(path2));
17797
18179
  return directory === "/" ? void 0 : directory;
17798
18180
  } catch (_error) {
17799
- const directory = dirname6(path2);
18181
+ const directory = dirname7(path2);
17800
18182
  return directory === "." || directory === "/" ? void 0 : directory;
17801
18183
  }
17802
18184
  }
@@ -17865,7 +18247,7 @@ async function startCollaborationSidecar(collaboration, profile, editorRuntime,
17865
18247
  ]);
17866
18248
  const command = nodeRuntimeExecutable();
17867
18249
  const args = [
17868
- join13(
18250
+ join14(
17869
18251
  profile.collaborationServerDir,
17870
18252
  "open-collaboration-server",
17871
18253
  "bundle",
@@ -17960,11 +18342,11 @@ function nodeRuntimeExecutable(env = process.env, execPath = process.execPath) {
17960
18342
  return basename6(execPath).toLowerCase().includes("bun") ? "node" : execPath;
17961
18343
  }
17962
18344
  async function installLocalTarball(archivePath, destinationDir) {
17963
- mkdirSync7(destinationDir, { recursive: true });
18345
+ mkdirSync8(destinationDir, { recursive: true });
17964
18346
  await runProcess("tar", ["-xzf", archivePath, "-C", destinationDir]);
17965
18347
  }
17966
18348
  function installDirectory(sourceDir, destinationDir) {
17967
- mkdirSync7(dirname6(destinationDir), { recursive: true });
18349
+ mkdirSync8(dirname7(destinationDir), { recursive: true });
17968
18350
  cpSync(sourceDir, destinationDir, { recursive: true });
17969
18351
  }
17970
18352
  function codeServerEnv(env, cwd, userDataDir, collaboration) {
@@ -17982,7 +18364,7 @@ function codeServerEnv(env, cwd, userDataDir, collaboration) {
17982
18364
  KANDAN_EDITOR_COLLABORATION_ENTRY_MODE: "kandan_auto_host_or_join",
17983
18365
  KANDAN_EDITOR_COLLABORATION_ROOM_ID: collaboration.roomId,
17984
18366
  KANDAN_EDITOR_COLLABORATION_SERVER_URL: collaboration.bootstrapServerUrl,
17985
- KANDAN_EDITOR_COLLABORATION_AUTO_HOST_CLAIM_PATH: join13(
18367
+ KANDAN_EDITOR_COLLABORATION_AUTO_HOST_CLAIM_PATH: join14(
17986
18368
  userDataDir,
17987
18369
  "kandan-oct-auto-host.lock"
17988
18370
  )
@@ -18186,20 +18568,20 @@ var init_localEditor = __esm({
18186
18568
 
18187
18569
  // src/localEditorRuntime.ts
18188
18570
  import { spawn as spawn5 } from "node:child_process";
18189
- import { createHash as createHash4 } from "node:crypto";
18571
+ import { createHash as createHash5 } from "node:crypto";
18190
18572
  import {
18191
18573
  createReadStream,
18192
18574
  createWriteStream as createWriteStream2,
18193
18575
  existsSync as existsSync9,
18194
- mkdirSync as mkdirSync8,
18576
+ mkdirSync as mkdirSync9,
18195
18577
  mkdtempSync as mkdtempSync2,
18196
- readFileSync as readFileSync11,
18197
- renameSync,
18578
+ readFileSync as readFileSync12,
18579
+ renameSync as renameSync2,
18198
18580
  rmSync as rmSync3,
18199
- writeFileSync as writeFileSync6
18581
+ writeFileSync as writeFileSync7
18200
18582
  } from "node:fs";
18201
- import { homedir as homedir11 } from "node:os";
18202
- import { dirname as dirname7, join as join14, resolve as resolve7 } from "node:path";
18583
+ import { homedir as homedir12 } from "node:os";
18584
+ import { dirname as dirname8, join as join15, resolve as resolve7 } from "node:path";
18203
18585
  import { Readable } from "node:stream";
18204
18586
  import { pipeline } from "node:stream/promises";
18205
18587
  async function resolveEditorRuntime(options) {
@@ -18390,14 +18772,14 @@ function normalizeRuntimeAssets(value) {
18390
18772
  }
18391
18773
  function installedRuntime(cacheRoot, manifest) {
18392
18774
  const runtimeRoot = runtimeInstallRoot(cacheRoot, manifest);
18393
- const manifestPath = join14(runtimeRoot, manifest.manifestPath);
18394
- const codeServerBin = join14(runtimeRoot, manifest.codeServerBinPath);
18775
+ const manifestPath = join15(runtimeRoot, manifest.manifestPath);
18776
+ const codeServerBin = join15(runtimeRoot, manifest.codeServerBinPath);
18395
18777
  const assets = verifiedRuntimeAssetPaths(runtimeRoot, manifest);
18396
18778
  if (!existsSync9(manifestPath) || !existsSync9(codeServerBin) || assets === void 0) {
18397
18779
  return { ok: false };
18398
18780
  }
18399
18781
  try {
18400
- const installed = JSON.parse(readFileSync11(manifestPath, "utf8"));
18782
+ const installed = JSON.parse(readFileSync12(manifestPath, "utf8"));
18401
18783
  if (isJsonObject(installed) && installed.version === manifest.version && installed.platform === manifest.platform && (installed.archiveSha256 === void 0 || installed.archiveSha256 === manifest.archiveSha256)) {
18402
18784
  return {
18403
18785
  ok: true,
@@ -18415,10 +18797,10 @@ function installedRuntime(cacheRoot, manifest) {
18415
18797
  return { ok: false };
18416
18798
  }
18417
18799
  async function installRuntime(args) {
18418
- mkdirSync8(args.cacheRoot, { recursive: true });
18419
- const tempRoot = mkdtempSync2(join14(args.cacheRoot, ".install-"));
18420
- const archivePath = join14(tempRoot, "runtime.tar.gz");
18421
- const extractRoot = join14(tempRoot, "runtime");
18800
+ mkdirSync9(args.cacheRoot, { recursive: true });
18801
+ const tempRoot = mkdtempSync2(join15(args.cacheRoot, ".install-"));
18802
+ const archivePath = join15(tempRoot, "runtime.tar.gz");
18803
+ const extractRoot = join15(tempRoot, "runtime");
18422
18804
  try {
18423
18805
  const downloaded = await downloadArchive({
18424
18806
  kandanUrl: args.kandanUrl,
@@ -18430,7 +18812,7 @@ async function installRuntime(args) {
18430
18812
  if (!downloaded.ok) {
18431
18813
  return downloaded;
18432
18814
  }
18433
- mkdirSync8(extractRoot, { recursive: true });
18815
+ mkdirSync9(extractRoot, { recursive: true });
18434
18816
  if (!await args.extractArchive(archivePath, extractRoot)) {
18435
18817
  return { ok: false, reason: "archive_extract_failed" };
18436
18818
  }
@@ -18443,14 +18825,14 @@ async function installRuntime(args) {
18443
18825
  if (!assetsInstalled) {
18444
18826
  return { ok: false, reason: "install_failed" };
18445
18827
  }
18446
- const manifestPath = join14(extractRoot, args.manifest.manifestPath);
18447
- const codeServerBin = join14(extractRoot, args.manifest.codeServerBinPath);
18828
+ const manifestPath = join15(extractRoot, args.manifest.manifestPath);
18829
+ const codeServerBin = join15(extractRoot, args.manifest.codeServerBinPath);
18448
18830
  const assets = verifiedRuntimeAssetPaths(extractRoot, args.manifest);
18449
18831
  if (!existsSync9(codeServerBin) || assets === void 0) {
18450
18832
  return { ok: false, reason: "invalid_archive" };
18451
18833
  }
18452
- mkdirSync8(dirname7(manifestPath), { recursive: true });
18453
- writeFileSync6(
18834
+ mkdirSync9(dirname8(manifestPath), { recursive: true });
18835
+ writeFileSync7(
18454
18836
  manifestPath,
18455
18837
  JSON.stringify(
18456
18838
  {
@@ -18468,28 +18850,28 @@ async function installRuntime(args) {
18468
18850
  );
18469
18851
  const targetRoot = runtimeInstallRoot(args.cacheRoot, args.manifest);
18470
18852
  rmSync3(targetRoot, { recursive: true, force: true });
18471
- mkdirSync8(dirname7(targetRoot), { recursive: true });
18472
- renameSync(extractRoot, targetRoot);
18853
+ mkdirSync9(dirname8(targetRoot), { recursive: true });
18854
+ renameSync2(extractRoot, targetRoot);
18473
18855
  return {
18474
18856
  ok: true,
18475
18857
  runtime: {
18476
18858
  mode: "server_managed",
18477
18859
  root: targetRoot,
18478
- codeServerBin: join14(targetRoot, args.manifest.codeServerBinPath),
18860
+ codeServerBin: join15(targetRoot, args.manifest.codeServerBinPath),
18479
18861
  assets: {
18480
- collaborationExtensionTarball: join14(
18862
+ collaborationExtensionTarball: join15(
18481
18863
  targetRoot,
18482
18864
  "kandan",
18483
18865
  "editor_extensions",
18484
18866
  "typefox.open-collaboration-tools.tar.gz"
18485
18867
  ),
18486
- collaborationServerTarball: join14(
18868
+ collaborationServerTarball: join15(
18487
18869
  targetRoot,
18488
18870
  "kandan",
18489
18871
  "editor_servers",
18490
18872
  "open-collaboration-server.tar.gz"
18491
18873
  ),
18492
- documentStateExtensionDir: join14(
18874
+ documentStateExtensionDir: join15(
18493
18875
  targetRoot,
18494
18876
  "kandan",
18495
18877
  "editor_extensions",
@@ -18506,7 +18888,7 @@ async function installRuntime(args) {
18506
18888
  }
18507
18889
  async function materializeRuntimeAssets(args) {
18508
18890
  for (const asset of args.manifest.assets) {
18509
- const targetPath = join14(args.runtimeRoot, asset.path);
18891
+ const targetPath = join15(args.runtimeRoot, asset.path);
18510
18892
  try {
18511
18893
  const bytes = await runtimeAssetBytes({
18512
18894
  kandanUrl: args.kandanUrl,
@@ -18516,8 +18898,8 @@ async function materializeRuntimeAssets(args) {
18516
18898
  if (bytes === void 0) {
18517
18899
  continue;
18518
18900
  }
18519
- mkdirSync8(dirname7(targetPath), { recursive: true });
18520
- writeFileSync6(targetPath, bytes);
18901
+ mkdirSync9(dirname8(targetPath), { recursive: true });
18902
+ writeFileSync7(targetPath, bytes);
18521
18903
  } catch (_error) {
18522
18904
  return false;
18523
18905
  }
@@ -18596,7 +18978,7 @@ function extractTarGz(archivePath, destination) {
18596
18978
  }
18597
18979
  function fileSha256(path2) {
18598
18980
  return new Promise((resolveHash, rejectHash) => {
18599
- const hash = createHash4("sha256");
18981
+ const hash = createHash5("sha256");
18600
18982
  const stream = createReadStream(path2);
18601
18983
  stream.on("error", rejectHash);
18602
18984
  stream.on("data", (chunk) => hash.update(chunk));
@@ -18607,19 +18989,19 @@ function runtimeInstallRoot(cacheRoot, manifest) {
18607
18989
  return resolve7(cacheRoot, manifest.platform, manifest.archiveSha256);
18608
18990
  }
18609
18991
  function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18610
- const collaborationExtensionTarball = join14(
18992
+ const collaborationExtensionTarball = join15(
18611
18993
  runtimeRoot,
18612
18994
  "kandan",
18613
18995
  "editor_extensions",
18614
18996
  "typefox.open-collaboration-tools.tar.gz"
18615
18997
  );
18616
- const collaborationServerTarball = join14(
18998
+ const collaborationServerTarball = join15(
18617
18999
  runtimeRoot,
18618
19000
  "kandan",
18619
19001
  "editor_servers",
18620
19002
  "open-collaboration-server.tar.gz"
18621
19003
  );
18622
- const documentStateExtensionDir = join14(
19004
+ const documentStateExtensionDir = join15(
18623
19005
  runtimeRoot,
18624
19006
  "kandan",
18625
19007
  "editor_extensions",
@@ -18628,7 +19010,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18628
19010
  const codeServerRoot = codeServerRuntimeRoot(manifest.codeServerBinPath);
18629
19011
  const requiredPaths = [
18630
19012
  manifest.codeServerBinPath,
18631
- join14(
19013
+ join15(
18632
19014
  codeServerRoot,
18633
19015
  "lib",
18634
19016
  "vscode",
@@ -18638,7 +19020,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18638
19020
  "web",
18639
19021
  "vsda.js"
18640
19022
  ),
18641
- join14(
19023
+ join15(
18642
19024
  codeServerRoot,
18643
19025
  "lib",
18644
19026
  "vscode",
@@ -18659,7 +19041,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18659
19041
  if (expectedSha256 === void 0 && relativePath !== manifest.codeServerBinPath) {
18660
19042
  return void 0;
18661
19043
  }
18662
- const absolutePath = join14(runtimeRoot, relativePath);
19044
+ const absolutePath = join15(runtimeRoot, relativePath);
18663
19045
  if (!existsSync9(absolutePath)) {
18664
19046
  return void 0;
18665
19047
  }
@@ -18678,7 +19060,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18678
19060
  }
18679
19061
  function codeServerRuntimeRoot(codeServerBinPath) {
18680
19062
  const normalized = codeServerBinPath.replaceAll("\\", "/");
18681
- return normalized === "bin/code-server" ? "." : normalized.endsWith("/bin/code-server") ? normalized.slice(0, -"/bin/code-server".length) || "." : dirname7(normalized);
19063
+ return normalized === "bin/code-server" ? "." : normalized.endsWith("/bin/code-server") ? normalized.slice(0, -"/bin/code-server".length) || "." : dirname8(normalized);
18682
19064
  }
18683
19065
  function manifestAssetChecksums(assets) {
18684
19066
  const checksums = /* @__PURE__ */ new Map();
@@ -18688,10 +19070,10 @@ function manifestAssetChecksums(assets) {
18688
19070
  return checksums;
18689
19071
  }
18690
19072
  function fileSha256Sync(path2) {
18691
- return createHash4("sha256").update(readFileSync11(path2)).digest("hex");
19073
+ return createHash5("sha256").update(readFileSync12(path2)).digest("hex");
18692
19074
  }
18693
19075
  function defaultEditorRuntimeCacheRoot() {
18694
- return join14(homedir11(), ".linzumi", "editor-runtimes");
19076
+ return join15(homedir12(), ".linzumi", "editor-runtimes");
18695
19077
  }
18696
19078
  function nonEmptyString(value) {
18697
19079
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
@@ -18711,7 +19093,7 @@ var init_localEditorRuntime = __esm({
18711
19093
 
18712
19094
  // src/dependencyStatus.ts
18713
19095
  import { spawn as spawn6, spawnSync as spawnSync4 } from "node:child_process";
18714
- import { delimiter as delimiter2, dirname as dirname8, join as join15 } from "node:path";
19096
+ import { delimiter as delimiter2, dirname as dirname9, join as join16 } from "node:path";
18715
19097
  function probeTool(command, cwd) {
18716
19098
  return new Promise((resolve12) => {
18717
19099
  const args = ["--version"];
@@ -18868,8 +19250,8 @@ function voltaCommandCandidates(args) {
18868
19250
  new Set(
18869
19251
  [
18870
19252
  voltaBinBesideCodexShim(args.codexBin),
18871
- env.VOLTA_HOME === void 0 ? void 0 : join15(env.VOLTA_HOME, "bin", "volta"),
18872
- env.HOME === void 0 ? void 0 : join15(env.HOME, ".volta", "bin", "volta"),
19253
+ env.VOLTA_HOME === void 0 ? void 0 : join16(env.VOLTA_HOME, "bin", "volta"),
19254
+ env.HOME === void 0 ? void 0 : join16(env.HOME, ".volta", "bin", "volta"),
18873
19255
  ...pathVoltaCandidates(env.PATH)
18874
19256
  ].filter((candidate) => candidate !== void 0)
18875
19257
  )
@@ -18877,10 +19259,10 @@ function voltaCommandCandidates(args) {
18877
19259
  }
18878
19260
  function voltaBinBesideCodexShim(codexBin) {
18879
19261
  const normalizedCodexBin = codexBin.replaceAll("\\", "/");
18880
- return normalizedCodexBin.endsWith("/.volta/bin/codex") ? join15(dirname8(codexBin), "volta") : void 0;
19262
+ return normalizedCodexBin.endsWith("/.volta/bin/codex") ? join16(dirname9(codexBin), "volta") : void 0;
18881
19263
  }
18882
19264
  function pathVoltaCandidates(pathValue) {
18883
- return pathValue === void 0 ? [] : pathValue.split(delimiter2).filter((entry) => entry !== "").map((entry) => join15(entry, "volta"));
19265
+ return pathValue === void 0 ? [] : pathValue.split(delimiter2).filter((entry) => entry !== "").map((entry) => join16(entry, "volta"));
18884
19266
  }
18885
19267
  function codeServerDependencyStatus(args) {
18886
19268
  switch (args.editorRuntime?.status) {
@@ -18989,7 +19371,7 @@ var linzumiCliVersion, linzumiCliVersionText;
18989
19371
  var init_version = __esm({
18990
19372
  "src/version.ts"() {
18991
19373
  "use strict";
18992
- linzumiCliVersion = "0.0.89-beta";
19374
+ linzumiCliVersion = "0.0.91-beta";
18993
19375
  linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
18994
19376
  }
18995
19377
  });
@@ -18998,21 +19380,21 @@ var init_version = __esm({
18998
19380
  import {
18999
19381
  closeSync as closeSync2,
19000
19382
  existsSync as existsSync10,
19001
- mkdirSync as mkdirSync9,
19383
+ mkdirSync as mkdirSync10,
19002
19384
  openSync as openSync3,
19003
- readFileSync as readFileSync12,
19004
- renameSync as renameSync2,
19385
+ readFileSync as readFileSync13,
19386
+ renameSync as renameSync3,
19005
19387
  unlinkSync as unlinkSync2,
19006
- writeFileSync as writeFileSync7,
19388
+ writeFileSync as writeFileSync8,
19007
19389
  writeSync
19008
19390
  } from "node:fs";
19009
- import { dirname as dirname9, join as join16 } from "node:path";
19391
+ import { dirname as dirname10, join as join17 } from "node:path";
19010
19392
  function isRunnerLockHeldError(error) {
19011
19393
  return error instanceof RunnerLockHeldError || error instanceof Error && error.name === runnerLockHeldErrorName && "lockPath" in error && "heldBy" in error;
19012
19394
  }
19013
19395
  function runnerLockPath(machineId, configPath = localConfigPath(), linzumiUrl) {
19014
19396
  const lockName = linzumiUrl === void 0 ? encodeURIComponent(machineId) : localConfigScopeFileStem(linzumiUrl);
19015
- return join16(dirname9(configPath), "runners", `${lockName}.lock`);
19397
+ return join17(dirname10(configPath), "runners", `${lockName}.lock`);
19016
19398
  }
19017
19399
  function acquireRunnerLock(options) {
19018
19400
  const path2 = runnerLockPath(
@@ -19080,9 +19462,9 @@ function stampRunnerLockHeartbeat(path2, record, now) {
19080
19462
  heartbeatAt: now().toISOString()
19081
19463
  };
19082
19464
  const tmpPath = `${path2}.tmp`;
19083
- writeFileSync7(tmpPath, `${JSON.stringify(next, null, 2)}
19465
+ writeFileSync8(tmpPath, `${JSON.stringify(next, null, 2)}
19084
19466
  `, "utf8");
19085
- renameSync2(tmpPath, path2);
19467
+ renameSync3(tmpPath, path2);
19086
19468
  } catch (_error) {
19087
19469
  }
19088
19470
  }
@@ -19192,7 +19574,7 @@ function writeLockOrHandleExisting(path2, record, isPidAlive, now, killPid, onTa
19192
19574
  });
19193
19575
  }
19194
19576
  function tryCreateLock(path2, record) {
19195
- mkdirSync9(dirname9(path2), { recursive: true });
19577
+ mkdirSync10(dirname10(path2), { recursive: true });
19196
19578
  try {
19197
19579
  const fd = openSync3(path2, "wx");
19198
19580
  try {
@@ -19248,7 +19630,7 @@ function withStaleReplacementLock(path2, isPidAlive, callback) {
19248
19630
  function readReplacementLockPidIfPresent(path2) {
19249
19631
  let value;
19250
19632
  try {
19251
- value = readFileSync12(path2, "utf8").trim();
19633
+ value = readFileSync13(path2, "utf8").trim();
19252
19634
  } catch (error) {
19253
19635
  if (isNodeErrorCode2(error, "ENOENT")) {
19254
19636
  return void 0;
@@ -19291,7 +19673,7 @@ function readRunnerLockIfPresent(path2) {
19291
19673
  }
19292
19674
  }
19293
19675
  function readRunnerLock(path2) {
19294
- const parsed = JSON.parse(readFileSync12(path2, "utf8"));
19676
+ const parsed = JSON.parse(readFileSync13(path2, "utf8"));
19295
19677
  if (!isRunnerLockRecord(parsed)) {
19296
19678
  throw new Error(`invalid Linzumi runner lock: ${path2}`);
19297
19679
  }
@@ -21208,8 +21590,8 @@ var init_runnerConsoleReporter = __esm({
21208
21590
  });
21209
21591
 
21210
21592
  // src/telemetry.ts
21211
- import { mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
21212
- import { dirname as dirname10, basename as basename7, join as join17 } from "node:path";
21593
+ import { mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
21594
+ import { dirname as dirname11, basename as basename7, join as join18 } from "node:path";
21213
21595
  import { randomUUID as randomUUID3 } from "node:crypto";
21214
21596
  function peekFlagValue(args, flags) {
21215
21597
  for (let index = 0; index < args.length; index += 1) {
@@ -21248,12 +21630,12 @@ function telemetryBaseUrl(apiUrl, env = process.env) {
21248
21630
  }
21249
21631
  }
21250
21632
  function telemetryInstallIdPath(env = process.env) {
21251
- return join17(dirname10(localConfigPath(env)), "install-id");
21633
+ return join18(dirname11(localConfigPath(env)), "install-id");
21252
21634
  }
21253
21635
  function ensureTelemetryInstallId(env = process.env) {
21254
21636
  const path2 = telemetryInstallIdPath(env);
21255
21637
  try {
21256
- const existing = readFileSync13(path2, "utf8").trim();
21638
+ const existing = readFileSync14(path2, "utf8").trim();
21257
21639
  if (existing !== "" && existing.length <= 128) {
21258
21640
  return existing;
21259
21641
  }
@@ -21261,8 +21643,8 @@ function ensureTelemetryInstallId(env = process.env) {
21261
21643
  }
21262
21644
  const installId = randomUUID3();
21263
21645
  try {
21264
- mkdirSync10(dirname10(path2), { recursive: true });
21265
- writeFileSync8(path2, `${installId}
21646
+ mkdirSync11(dirname11(path2), { recursive: true });
21647
+ writeFileSync9(path2, `${installId}
21266
21648
  `, { mode: 384 });
21267
21649
  } catch {
21268
21650
  }
@@ -21455,17 +21837,17 @@ var init_linzumiApiClient = __esm({
21455
21837
  });
21456
21838
 
21457
21839
  // src/authCache.ts
21458
- import { existsSync as existsSync11, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
21459
- import { homedir as homedir12 } from "node:os";
21460
- import { dirname as dirname11, join as join18 } from "node:path";
21840
+ import { existsSync as existsSync11, mkdirSync as mkdirSync12, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "node:fs";
21841
+ import { homedir as homedir13 } from "node:os";
21842
+ import { dirname as dirname12, join as join19 } from "node:path";
21461
21843
  function defaultAuthFilePath() {
21462
- return join18(homedir12(), ".linzumi", "auth.json");
21844
+ return join19(homedir13(), ".linzumi", "auth.json");
21463
21845
  }
21464
21846
  function readCachedLocalRunnerToken(kandanUrl, authFilePath = defaultAuthFilePath()) {
21465
21847
  if (!existsSync11(authFilePath)) {
21466
21848
  return void 0;
21467
21849
  }
21468
- const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
21850
+ const authFile = parseAuthFile(readFileSync15(authFilePath, "utf8"));
21469
21851
  const kandanBaseUrl = kandanHttpBaseUrl(kandanUrl);
21470
21852
  const entry = authFile.local_codex_runner?.[kandanBaseUrl];
21471
21853
  if (entry === void 0 || entry.access_token.trim() === "") {
@@ -21487,7 +21869,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
21487
21869
  `missing personal-agent delegation auth file: ${authFilePath}`
21488
21870
  );
21489
21871
  }
21490
- const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
21872
+ const authFile = parseAuthFile(readFileSync15(authFilePath, "utf8"));
21491
21873
  const entry = authFile.personal_agent_delegation;
21492
21874
  if (entry === void 0 || entry.access_token.trim() === "") {
21493
21875
  throw new Error(
@@ -21505,7 +21887,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
21505
21887
  }
21506
21888
  function writeCachedLocalRunnerToken(args) {
21507
21889
  const authFilePath = args.authFilePath ?? defaultAuthFilePath();
21508
- const existing = existsSync11(authFilePath) ? parseAuthFile(readFileSync14(authFilePath, "utf8")) : { version: 1 };
21890
+ const existing = existsSync11(authFilePath) ? parseAuthFile(readFileSync15(authFilePath, "utf8")) : { version: 1 };
21509
21891
  const kandanBaseUrl = kandanHttpBaseUrl(args.kandanUrl);
21510
21892
  const issuedAt = /* @__PURE__ */ new Date();
21511
21893
  const expiresAt = args.expiresInSeconds === void 0 ? void 0 : new Date(
@@ -21523,8 +21905,8 @@ function writeCachedLocalRunnerToken(args) {
21523
21905
  }
21524
21906
  }
21525
21907
  };
21526
- mkdirSync11(dirname11(authFilePath), { recursive: true });
21527
- writeFileSync9(authFilePath, `${JSON.stringify(next, null, 2)}
21908
+ mkdirSync12(dirname12(authFilePath), { recursive: true });
21909
+ writeFileSync10(authFilePath, `${JSON.stringify(next, null, 2)}
21528
21910
  `, "utf8");
21529
21911
  return {
21530
21912
  accessToken: args.accessToken,
@@ -21969,9 +22351,9 @@ var init_threadCodexWorkerIpc = __esm({
21969
22351
 
21970
22352
  // src/signupTaskSuggestions.ts
21971
22353
  import { spawn as spawn7 } from "node:child_process";
21972
- import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync15, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
22354
+ import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "node:fs";
21973
22355
  import { tmpdir as tmpdir2 } from "node:os";
21974
- import { join as join19 } from "node:path";
22356
+ import { join as join20 } from "node:path";
21975
22357
  async function suggestSignupTasksWithCodex(args) {
21976
22358
  const attempts = 2;
21977
22359
  let previousResponse;
@@ -21993,11 +22375,11 @@ async function suggestSignupTasksWithCodex(args) {
21993
22375
  );
21994
22376
  }
21995
22377
  async function runCodexTaskSuggestion(args) {
21996
- const tempRoot = mkdtempSync3(join19(tmpdir2(), "linzumi-signup-codex-tasks-"));
21997
- const schemaPath = join19(tempRoot, "task-suggestions.schema.json");
21998
- const outputPath = join19(tempRoot, "task-suggestions.json");
22378
+ const tempRoot = mkdtempSync3(join20(tmpdir2(), "linzumi-signup-codex-tasks-"));
22379
+ const schemaPath = join20(tempRoot, "task-suggestions.schema.json");
22380
+ const outputPath = join20(tempRoot, "task-suggestions.json");
21999
22381
  const prompt = taskSuggestionPrompt(args.previousResponse);
22000
- writeFileSync10(
22382
+ writeFileSync11(
22001
22383
  schemaPath,
22002
22384
  `${JSON.stringify(taskSuggestionJsonSchema(), null, 2)}
22003
22385
  `,
@@ -22014,7 +22396,7 @@ async function runCodexTaskSuggestion(args) {
22014
22396
  prompt
22015
22397
  })
22016
22398
  );
22017
- return readFileSync15(outputPath, "utf8");
22399
+ return readFileSync16(outputPath, "utf8");
22018
22400
  } finally {
22019
22401
  rmSync4(tempRoot, { recursive: true, force: true });
22020
22402
  }
@@ -22187,7 +22569,7 @@ var init_signupTaskSuggestions = __esm({
22187
22569
  // src/remoteCodexSandboxRunner.ts
22188
22570
  import { spawn as spawn8 } from "node:child_process";
22189
22571
  import { existsSync as existsSync12, realpathSync as realpathSync5 } from "node:fs";
22190
- import { dirname as dirname12, isAbsolute as isAbsolute4 } from "node:path";
22572
+ import { dirname as dirname13, isAbsolute as isAbsolute4 } from "node:path";
22191
22573
  function createConfiguredRemoteCodexSandboxRunner(args) {
22192
22574
  const kind = normalizedSandboxKind(args.env.LINZUMI_REMOTE_CODEX_SANDBOX);
22193
22575
  if (kind === void 0) {
@@ -22302,8 +22684,8 @@ function bubblewrapArgs(sandboxBin, request, exists) {
22302
22684
  ]);
22303
22685
  const readOnlyBindArgs = uniqueStrings3([
22304
22686
  ...linuxReadOnlyRoots,
22305
- ...isAbsolute4(request.command) ? [dirname12(request.command)] : [],
22306
- dirname12(sandboxBin)
22687
+ ...isAbsolute4(request.command) ? [dirname13(request.command)] : [],
22688
+ dirname13(sandboxBin)
22307
22689
  ]).flatMap((path2) => exists(path2) ? ["--ro-bind", path2, path2] : []);
22308
22690
  const cwdParentDirs = parentDirs(request.cwd).flatMap((path2) => [
22309
22691
  "--dir",
@@ -22336,7 +22718,7 @@ function bubblewrapArgs(sandboxBin, request, exists) {
22336
22718
  function macosSeatbeltProfile(request, exists) {
22337
22719
  const readableRoots = uniqueStrings3([
22338
22720
  ...macosReadOnlyRoots,
22339
- ...isAbsolute4(request.command) ? [dirname12(request.command)] : []
22721
+ ...isAbsolute4(request.command) ? [dirname13(request.command)] : []
22340
22722
  ]).filter(exists);
22341
22723
  const readableRules = readableRoots.map((path2) => `(allow file-read* (subpath ${sandboxString(path2)}))`).join("\n");
22342
22724
  const writableTempRules = macosWritableTempRoots.filter(exists).flatMap((path2) => [
@@ -22459,31 +22841,31 @@ var init_remoteCodexSandboxRunner = __esm({
22459
22841
 
22460
22842
  // src/runner.ts
22461
22843
  import { spawn as spawn9, spawnSync as spawnSync5 } from "node:child_process";
22462
- import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
22844
+ import { createHash as createHash6, randomUUID as randomUUID4 } from "node:crypto";
22463
22845
  import {
22464
22846
  chmodSync as chmodSync2,
22465
22847
  existsSync as existsSync13,
22466
22848
  lstatSync,
22467
- mkdirSync as mkdirSync12,
22849
+ mkdirSync as mkdirSync13,
22468
22850
  mkdtempSync as mkdtempSync4,
22469
22851
  readdirSync as readdirSync4,
22470
- readFileSync as readFileSync16,
22852
+ readFileSync as readFileSync17,
22471
22853
  realpathSync as realpathSync6,
22472
- renameSync as renameSync3,
22854
+ renameSync as renameSync4,
22473
22855
  rmSync as rmSync5,
22474
22856
  statSync as statSync3,
22475
- writeFileSync as writeFileSync11
22857
+ writeFileSync as writeFileSync12
22476
22858
  } from "node:fs";
22477
22859
  import { readFile as readFile2 } from "node:fs/promises";
22478
22860
  import { createServer as createServer3 } from "node:http";
22479
- import { homedir as homedir13, hostname as hostname2, tmpdir as tmpdir3 } from "node:os";
22861
+ import { homedir as homedir14, hostname as hostname2, tmpdir as tmpdir3 } from "node:os";
22480
22862
  import { createInterface } from "node:readline";
22481
22863
  import {
22482
22864
  basename as basename8,
22483
- dirname as dirname13,
22865
+ dirname as dirname14,
22484
22866
  extname as extname2,
22485
22867
  isAbsolute as isAbsolute5,
22486
- join as join20,
22868
+ join as join21,
22487
22869
  resolve as resolve8
22488
22870
  } from "node:path";
22489
22871
  async function runLocalCodexRunner(options) {
@@ -22762,6 +23144,10 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
22762
23144
  { discardSeqsOnFirstEpochAdoption: true }
22763
23145
  );
22764
23146
  cleanup.actions.push(() => appliedStartTurnStore.flush());
23147
+ const threadSessionRegistry = createRunnerThreadSessionRegistryStore(
23148
+ runnerThreadSessionRegistryPath(options.runnerId),
23149
+ log2
23150
+ );
22765
23151
  const controlEpochStore = createRunnerControlEpochStore(
22766
23152
  controlCursorStore,
22767
23153
  appliedStartTurnStore,
@@ -23644,6 +24030,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23644
24030
  kandan.onReconnect(() => channelSession.handleKandanReconnect());
23645
24031
  }
23646
24032
  const dynamicChannelSessions = /* @__PURE__ */ new Map();
24033
+ const dynamicChannelSessionAttachInFlight = /* @__PURE__ */ new Map();
23647
24034
  const dynamicChannelSessionCodexClients = /* @__PURE__ */ new Map();
23648
24035
  const codexTurnFailureGuards = /* @__PURE__ */ new Map();
23649
24036
  const lossReportPushes = [];
@@ -23765,90 +24152,120 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23765
24152
  if (existingSession !== void 0) {
23766
24153
  return existingSession;
23767
24154
  }
23768
- const listenUser = options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
23769
- if (listenUser === void 0) {
23770
- throw new Error(
23771
- "missing listen user for Commander-started Codex session"
23772
- );
24155
+ const alreadyAttaching = dynamicChannelSessionAttachInFlight.get(codexThreadId);
24156
+ if (alreadyAttaching !== void 0) {
24157
+ return await alreadyAttaching;
23773
24158
  }
23774
- const runtimeSettings = startInstanceRuntimeSettings(options, control);
23775
- const session = await attachChannelSession({
23776
- kandan,
23777
- codex: sessionCodex,
23778
- topic,
23779
- instanceId,
23780
- options: {
23781
- kandanUrl: options.kandanUrl,
23782
- token: options.token,
23783
- runnerId: options.runnerId,
23784
- cwd,
23785
- codexBin: options.codexBin,
23786
- fetch: options.fetch,
23787
- fast: control.fast ?? options.fast,
23788
- launchTui: false,
23789
- pipelinePersistDir: commanderOutboxPersistDir(),
23790
- enablePortForwardWatch: true,
23791
- initialForwardPorts: allowedForwardPorts,
23792
- portForwardWatcher: channelSessionPortForwardWatcherOptions({
23793
- rootPid: portForwardWatcherRootPid,
23794
- start: options.portForwardWatcher,
23795
- commanderBoundPids: args.commanderBoundPids,
23796
- commanderBoundPorts: args.commanderBoundPorts
23797
- }),
23798
- suppressedForwardPorts,
23799
- onForwardPortApproved: (port, attribution) => {
23800
- liveForwardPorts.add(port);
23801
- setForwardPortAttribution(port, {
23802
- ...attribution,
23803
- agentProvider: "codex"
23804
- });
23805
- return capabilitiesPayload();
23806
- },
23807
- onForwardPortRevoked: (port) => {
23808
- liveForwardPorts.delete(port);
23809
- clearForwardPortAttribution(port);
23810
- return capabilitiesPayload();
24159
+ const attachPromise = (async () => {
24160
+ const listenUser = options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
24161
+ if (listenUser === void 0) {
24162
+ throw new Error(
24163
+ "missing listen user for Commander-started Codex session"
24164
+ );
24165
+ }
24166
+ const runtimeSettings = startInstanceRuntimeSettings(options, control);
24167
+ const session = await attachChannelSession({
24168
+ kandan,
24169
+ codex: sessionCodex,
24170
+ topic,
24171
+ instanceId,
24172
+ options: {
24173
+ kandanUrl: options.kandanUrl,
24174
+ token: options.token,
24175
+ runnerId: options.runnerId,
24176
+ cwd,
24177
+ codexBin: options.codexBin,
24178
+ fetch: options.fetch,
24179
+ fast: control.fast ?? options.fast,
24180
+ launchTui: false,
24181
+ pipelinePersistDir: commanderOutboxPersistDir(),
24182
+ enablePortForwardWatch: true,
24183
+ initialForwardPorts: allowedForwardPorts,
24184
+ portForwardWatcher: channelSessionPortForwardWatcherOptions({
24185
+ rootPid: portForwardWatcherRootPid,
24186
+ start: options.portForwardWatcher,
24187
+ commanderBoundPids: args.commanderBoundPids,
24188
+ commanderBoundPorts: args.commanderBoundPorts
24189
+ }),
24190
+ suppressedForwardPorts,
24191
+ onForwardPortApproved: (port, attribution) => {
24192
+ liveForwardPorts.add(port);
24193
+ setForwardPortAttribution(port, {
24194
+ ...attribution,
24195
+ agentProvider: "codex"
24196
+ });
24197
+ return capabilitiesPayload();
24198
+ },
24199
+ onForwardPortRevoked: (port) => {
24200
+ liveForwardPorts.delete(port);
24201
+ clearForwardPortAttribution(port);
24202
+ return capabilitiesPayload();
24203
+ },
24204
+ channelSession: {
24205
+ workspaceSlug,
24206
+ channelSlug,
24207
+ kandanThreadId,
24208
+ rootSeq: integerValue(control.rootSeq),
24209
+ codexThreadId,
24210
+ linzumiContext: control.linzumiContext,
24211
+ listenUser,
24212
+ model: runtimeSettings.model,
24213
+ reasoningEffort: runtimeSettings.reasoningEffort,
24214
+ sandbox: runtimeSettings.sandbox,
24215
+ approvalPolicy: runtimeSettings.approvalPolicy,
24216
+ allowPortForwardingByDefault: runtimeSettings.allowPortForwardingByDefault
24217
+ }
23811
24218
  },
23812
- channelSession: {
24219
+ log: log2
24220
+ });
24221
+ dynamicChannelSessions.set(codexThreadId, session);
24222
+ dynamicChannelSessionCodexClients.set(codexThreadId, sessionCodex);
24223
+ threadSessionRegistry.upsert({
24224
+ workspace: workspaceSlug,
24225
+ channel: channelSlug,
24226
+ kandanThreadId,
24227
+ codexThreadId,
24228
+ cwd,
24229
+ agentProvider: "codex",
24230
+ control: rehydrationControlSnapshot({
23813
24231
  workspaceSlug,
23814
24232
  channelSlug,
23815
24233
  kandanThreadId,
23816
- rootSeq: integerValue(control.rootSeq),
23817
24234
  codexThreadId,
23818
- linzumiContext: control.linzumiContext,
23819
- listenUser,
23820
- model: runtimeSettings.model,
23821
- reasoningEffort: runtimeSettings.reasoningEffort,
23822
- sandbox: runtimeSettings.sandbox,
23823
- approvalPolicy: runtimeSettings.approvalPolicy,
23824
- allowPortForwardingByDefault: runtimeSettings.allowPortForwardingByDefault
23825
- }
23826
- },
23827
- log: log2
23828
- });
23829
- dynamicChannelSessions.set(codexThreadId, session);
23830
- dynamicChannelSessionCodexClients.set(codexThreadId, sessionCodex);
23831
- if (sessionCodex !== codex) {
23832
- sessionCodex.onNotification((notification) => {
23833
- seq.value += 1;
23834
- const params = notification.params ?? {};
23835
- log2(
23836
- "codex.notification",
23837
- codexNotificationConsoleLogPayload(notification.method, params)
23838
- );
23839
- codexTurnFailureGuardFor(sessionCodex).observeNotification(
23840
- notification.method,
23841
- params
23842
- );
23843
- dispatchCodexNotificationToSession(
23844
- session,
23845
- notification.method,
23846
- params,
23847
- log2
23848
- );
24235
+ cwd,
24236
+ rootSeq: integerValue(control.rootSeq),
24237
+ runtimeSettings
24238
+ }),
24239
+ updatedAtMs: Date.now()
23849
24240
  });
24241
+ if (sessionCodex !== codex) {
24242
+ sessionCodex.onNotification((notification) => {
24243
+ seq.value += 1;
24244
+ const params = notification.params ?? {};
24245
+ log2(
24246
+ "codex.notification",
24247
+ codexNotificationConsoleLogPayload(notification.method, params)
24248
+ );
24249
+ codexTurnFailureGuardFor(sessionCodex).observeNotification(
24250
+ notification.method,
24251
+ params
24252
+ );
24253
+ dispatchCodexNotificationToSession(
24254
+ session,
24255
+ notification.method,
24256
+ params,
24257
+ log2
24258
+ );
24259
+ });
24260
+ }
24261
+ return session;
24262
+ })();
24263
+ dynamicChannelSessionAttachInFlight.set(codexThreadId, attachPromise);
24264
+ try {
24265
+ return await attachPromise;
24266
+ } finally {
24267
+ dynamicChannelSessionAttachInFlight.delete(codexThreadId);
23850
24268
  }
23851
- return session;
23852
24269
  };
23853
24270
  const attachThreadSession = async (control, cwd, codexThreadId) => {
23854
24271
  return await attachThreadSessionWithCodex({
@@ -23859,6 +24276,69 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23859
24276
  portForwardWatcherRootPid: started?.process.pid
23860
24277
  });
23861
24278
  };
24279
+ const rehydrateThreadSessionsOnBoot = async () => {
24280
+ const records = threadSessionRegistry.list();
24281
+ if (records.length === 0) {
24282
+ return;
24283
+ }
24284
+ const summary = await rehydrateThreadSessions({
24285
+ records,
24286
+ nowMs: Date.now(),
24287
+ maxAgeMs: defaultThreadSessionRehydrationMaxAgeMs,
24288
+ pendingDurableRowCount: (record) => recoverOutboxJournal(
24289
+ outboxJournalPath(
24290
+ commanderOutboxPersistDir(),
24291
+ channelSessionPipelineThreadKey(
24292
+ { workspaceSlug: record.workspace, channelSlug: record.channel },
24293
+ record.kandanThreadId,
24294
+ instanceId
24295
+ )
24296
+ ),
24297
+ log2
24298
+ ).pendingEntries.length,
24299
+ attach: async (record) => {
24300
+ if (cleanup.closePromise !== void 0) {
24301
+ log2("session_registry.rehydrate_aborted_shutdown", {
24302
+ thread_id: record.kandanThreadId
24303
+ });
24304
+ return "failed";
24305
+ }
24306
+ const cwd = resolveAllowedCwd(record.cwd, allowedCwds.value);
24307
+ if (!cwd.ok) {
24308
+ log2("session_registry.rehydrate_cwd_rejected", {
24309
+ thread_id: record.kandanThreadId,
24310
+ cwd: record.cwd,
24311
+ reason: cwd.reason
24312
+ });
24313
+ return "retire";
24314
+ }
24315
+ const session = await attachThreadSession(
24316
+ rehydrationReconnectControl(record),
24317
+ cwd.cwd,
24318
+ record.codexThreadId
24319
+ );
24320
+ return session !== void 0 ? "attached" : "failed";
24321
+ },
24322
+ retire: (record) => threadSessionRegistry.remove(record.kandanThreadId),
24323
+ log: log2
24324
+ });
24325
+ log2("session_registry.rehydrate_complete", {
24326
+ records: records.length,
24327
+ rehydrated: summary.rehydrated,
24328
+ retired_drained: summary.retiredDrained,
24329
+ retired_stale: summary.retiredStale,
24330
+ retired_unattachable: summary.retiredUnattachable,
24331
+ failed: summary.failed
24332
+ });
24333
+ };
24334
+ const threadSessionRehydration = rehydrateThreadSessionsOnBoot().catch(
24335
+ (error) => {
24336
+ log2("session_registry.rehydrate_failed", {
24337
+ message: error instanceof Error ? error.message : String(error)
24338
+ });
24339
+ }
24340
+ );
24341
+ cleanup.actions.push(() => threadSessionRehydration);
23862
24342
  const startThreadRunnerProcess = async (control, cwd) => {
23863
24343
  if (options.threadProcess?.role === "thread") {
23864
24344
  return void 0;
@@ -24523,14 +25003,14 @@ function commanderOutboxPersistDir() {
24523
25003
  if (override !== void 0 && override !== "") {
24524
25004
  return override;
24525
25005
  }
24526
- return join20(homedir13(), ".linzumi", "commander-outbox");
25006
+ return join21(homedir14(), ".linzumi", "commander-outbox");
24527
25007
  }
24528
25008
  function controlCursorStorePath(runnerId) {
24529
25009
  const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
24530
- const digest = createHash5("sha256").update(runnerId).digest("hex").slice(0, 8);
25010
+ const digest = createHash6("sha256").update(runnerId).digest("hex").slice(0, 8);
24531
25011
  const stem = sanitized === "" ? "runner" : sanitized;
24532
- return join20(
24533
- homedir13(),
25012
+ return join21(
25013
+ homedir14(),
24534
25014
  ".linzumi",
24535
25015
  "control-cursors",
24536
25016
  `${stem}.${digest}.json`
@@ -24538,10 +25018,10 @@ function controlCursorStorePath(runnerId) {
24538
25018
  }
24539
25019
  function appliedStartTurnStorePath(runnerId) {
24540
25020
  const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
24541
- const digest = createHash5("sha256").update(runnerId).digest("hex").slice(0, 8);
25021
+ const digest = createHash6("sha256").update(runnerId).digest("hex").slice(0, 8);
24542
25022
  const stem = sanitized === "" ? "runner" : sanitized;
24543
- return join20(
24544
- homedir13(),
25023
+ return join21(
25024
+ homedir14(),
24545
25025
  ".linzumi",
24546
25026
  "control-cursors",
24547
25027
  `${stem}.${digest}.start-turn.json`
@@ -24663,9 +25143,9 @@ function createControlCursorFileStore(path2, log2, options) {
24663
25143
  }
24664
25144
  dirty = false;
24665
25145
  try {
24666
- mkdirSync12(dirname13(path2), { recursive: true });
25146
+ mkdirSync13(dirname14(path2), { recursive: true });
24667
25147
  const tmpPath = `${path2}.tmp`;
24668
- writeFileSync11(
25148
+ writeFileSync12(
24669
25149
  tmpPath,
24670
25150
  `${JSON.stringify({
24671
25151
  ...epoch === void 0 ? {} : { [controlCursorEpochKey]: epoch },
@@ -24674,7 +25154,7 @@ function createControlCursorFileStore(path2, log2, options) {
24674
25154
  `,
24675
25155
  "utf8"
24676
25156
  );
24677
- renameSync3(tmpPath, path2);
25157
+ renameSync4(tmpPath, path2);
24678
25158
  } catch (error) {
24679
25159
  log2("control_cursor_store.write_failed", {
24680
25160
  path: path2,
@@ -24773,7 +25253,7 @@ function readControlCursorFile(path2, log2) {
24773
25253
  const cursors = /* @__PURE__ */ new Map();
24774
25254
  let raw;
24775
25255
  try {
24776
- raw = readFileSync16(path2, "utf8");
25256
+ raw = readFileSync17(path2, "utf8");
24777
25257
  } catch (error) {
24778
25258
  if (!isErrnoCode2(error, "ENOENT")) {
24779
25259
  log2("control_cursor_store.read_failed", {
@@ -27067,7 +27547,7 @@ async function startClaudeCodeProviderInstance(args) {
27067
27547
  log: args.log
27068
27548
  });
27069
27549
  const liveBashCapture = args.options.claudeCodeRunner === void 0 && claudeLiveBashCaptureEnabled(process.env) ? createClaudeCodeLiveBashCapture({
27070
- captureDir: join20(
27550
+ captureDir: join21(
27071
27551
  tmpdir3(),
27072
27552
  `linzumi-claude-live-bash-${args.instanceId}`
27073
27553
  ),
@@ -27258,6 +27738,7 @@ async function startClaudeCodeProviderInstance(args) {
27258
27738
  args.log("claude_code.turn_completed", {
27259
27739
  linzumi_thread_id: threadId,
27260
27740
  claude_session_id: event.sessionId,
27741
+ body_source: event.bodySource ?? null,
27261
27742
  body_preview: claudeConsoleBodyPreview(event.body)
27262
27743
  });
27263
27744
  settleFirstTurn();
@@ -27659,6 +28140,7 @@ function claudeSessionStoreEntryPayload(args, event) {
27659
28140
  case "session_completed":
27660
28141
  return {
27661
28142
  body: event.body,
28143
+ bodySource: event.bodySource ?? null,
27662
28144
  usage: event.usage ?? null
27663
28145
  };
27664
28146
  case "turn_interrupted":
@@ -27897,6 +28379,48 @@ function startInstanceRuntimeSettings(options, control) {
27897
28379
  allowPortForwardingByDefault: true
27898
28380
  };
27899
28381
  }
28382
+ function rehydrationControlSnapshot(args) {
28383
+ const { runtimeSettings } = args;
28384
+ return {
28385
+ type: "reconnect_thread",
28386
+ workspace: args.workspaceSlug,
28387
+ channel: args.channelSlug,
28388
+ threadId: args.kandanThreadId,
28389
+ codexThreadId: args.codexThreadId,
28390
+ cwd: args.cwd,
28391
+ agentProvider: "codex",
28392
+ ...args.rootSeq === void 0 ? {} : { rootSeq: args.rootSeq },
28393
+ ...runtimeSettings.model === void 0 ? {} : { model: runtimeSettings.model },
28394
+ ...runtimeSettings.reasoningEffort === void 0 ? {} : { reasoningEffort: runtimeSettings.reasoningEffort },
28395
+ ...runtimeSettings.sandbox === void 0 ? {} : { sandbox: runtimeSettings.sandbox },
28396
+ ...runtimeSettings.approvalPolicy === void 0 ? {} : { approvalPolicy: runtimeSettings.approvalPolicy },
28397
+ ...runtimeSettings.fast === void 0 ? {} : { fast: runtimeSettings.fast }
28398
+ };
28399
+ }
28400
+ function rehydrationReconnectControl(record) {
28401
+ const snapshot = record.control;
28402
+ const rootSeq = integerValue(snapshot.rootSeq);
28403
+ const model = stringValue(snapshot.model);
28404
+ const reasoningEffort = stringValue(snapshot.reasoningEffort);
28405
+ const sandbox = stringValue(snapshot.sandbox);
28406
+ const approvalPolicy = stringValue(snapshot.approvalPolicy);
28407
+ const fast = typeof snapshot.fast === "boolean" ? snapshot.fast : void 0;
28408
+ return {
28409
+ type: "reconnect_thread",
28410
+ workspace: record.workspace,
28411
+ channel: record.channel,
28412
+ threadId: record.kandanThreadId,
28413
+ codexThreadId: record.codexThreadId,
28414
+ cwd: record.cwd,
28415
+ agentProvider: "codex",
28416
+ ...rootSeq === void 0 ? {} : { rootSeq },
28417
+ ...model === void 0 ? {} : { model },
28418
+ ...reasoningEffort === void 0 ? {} : { reasoningEffort },
28419
+ ...sandbox === void 0 ? {} : { sandbox },
28420
+ ...approvalPolicy === void 0 ? {} : { approvalPolicy },
28421
+ ...fast === void 0 ? {} : { fast }
28422
+ };
28423
+ }
27900
28424
  function channelSessionPortForwardWatcherOptions(args) {
27901
28425
  if (args.rootPid === void 0 && args.start === void 0) {
27902
28426
  return void 0;
@@ -28870,8 +29394,8 @@ function onboardingConversationOfficeImport(response) {
28870
29394
  return objectValue(metadata?.office_channel_import);
28871
29395
  }
28872
29396
  function onboardingConversationImportClientMessageId(importKey, itemKey) {
28873
- const importHash = createHash5("sha256").update(importKey).digest("hex");
28874
- const itemHash = createHash5("sha256").update(itemKey).digest("hex");
29397
+ const importHash = createHash6("sha256").update(importKey).digest("hex");
29398
+ const itemHash = createHash6("sha256").update(itemKey).digest("hex");
28875
29399
  return `onboarding-import:${importHash.slice(0, 32)}:${itemHash.slice(0, 24)}`;
28876
29400
  }
28877
29401
  async function uploadLocalConversationAttachments(args) {
@@ -28969,7 +29493,7 @@ async function localConversationAttachmentFile(candidatePath, attachment) {
28969
29493
  };
28970
29494
  }
28971
29495
  case "path": {
28972
- const path2 = isAbsolute5(attachment.path) ? attachment.path : resolve8(dirname13(candidatePath), attachment.path);
29496
+ const path2 = isAbsolute5(attachment.path) ? attachment.path : resolve8(dirname14(candidatePath), attachment.path);
28973
29497
  try {
28974
29498
  const bytes = await readFile2(path2);
28975
29499
  return {
@@ -29359,9 +29883,9 @@ function mcpOwnerUsername(options) {
29359
29883
  return options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
29360
29884
  }
29361
29885
  function writeEphemeralMcpAuthFile(options) {
29362
- const directory = mkdtempSync4(join20(tmpdir3(), "linzumi-mcp-auth-"));
29886
+ const directory = mkdtempSync4(join21(tmpdir3(), "linzumi-mcp-auth-"));
29363
29887
  chmodSync2(directory, 448);
29364
- const path2 = join20(directory, "auth.json");
29888
+ const path2 = join21(directory, "auth.json");
29365
29889
  writeCachedLocalRunnerToken({
29366
29890
  kandanUrl: options.kandanUrl,
29367
29891
  accessToken: options.token,
@@ -29437,7 +29961,7 @@ function configuredAllowedCwds(values, options = {}) {
29437
29961
  const absolutePath = resolve8(expandUserPath(value));
29438
29962
  try {
29439
29963
  if (options.createMissing === true) {
29440
- mkdirSync12(absolutePath, { recursive: true });
29964
+ mkdirSync13(absolutePath, { recursive: true });
29441
29965
  }
29442
29966
  const realPath = realpathSync6(absolutePath);
29443
29967
  allowedCwds.push(
@@ -29474,7 +29998,7 @@ function allowedCwdProjects(allowedCwds) {
29474
29998
  });
29475
29999
  }
29476
30000
  function isGitProjectDirectory(cwd) {
29477
- const gitPath = join20(cwd, ".git");
30001
+ const gitPath = join21(cwd, ".git");
29478
30002
  try {
29479
30003
  const gitPathStats = statSync3(gitPath);
29480
30004
  return gitPathStats.isDirectory() || gitPathStats.isFile();
@@ -29497,9 +30021,9 @@ function browseRunnerDirectory(control, options) {
29497
30021
  error: "not_directory"
29498
30022
  };
29499
30023
  }
29500
- const parent = dirname13(currentPath);
30024
+ const parent = dirname14(currentPath);
29501
30025
  const entries = readdirSync4(currentPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => visibleRunnerDirectoryEntryName(entry.name)).map((entry) => {
29502
- const path2 = join20(currentPath, entry.name);
30026
+ const path2 = join21(currentPath, entry.name);
29503
30027
  return {
29504
30028
  name: entry.name,
29505
30029
  path: path2,
@@ -29540,7 +30064,7 @@ function projectDirectoryName(name) {
29540
30064
  function availableProjectDirectoryName(projectsRoot, baseName, suffix = 0) {
29541
30065
  for (let nextSuffix = suffix; ; nextSuffix += 1) {
29542
30066
  const candidate = nextSuffix === 0 ? baseName : `${baseName}-${nextSuffix}`;
29543
- if (!projectPathExists(join20(projectsRoot, candidate))) {
30067
+ if (!projectPathExists(join21(projectsRoot, candidate))) {
29544
30068
  return candidate;
29545
30069
  }
29546
30070
  }
@@ -29568,9 +30092,9 @@ function createRunnerProject(control, options, allowedCwds) {
29568
30092
  error: "invalid_project_template"
29569
30093
  };
29570
30094
  }
29571
- const projectsRoot = join20(currentHomeDirectory(), "linzumi");
30095
+ const projectsRoot = join21(currentHomeDirectory(), "linzumi");
29572
30096
  const resolvedProjectDirName = template === "hello_linzumi_demo" ? availableProjectDirectoryName(projectsRoot, projectDirName) : projectDirName;
29573
- const projectPath = join20(projectsRoot, resolvedProjectDirName);
30097
+ const projectPath = join21(projectsRoot, resolvedProjectDirName);
29574
30098
  let createdProjectPath = false;
29575
30099
  try {
29576
30100
  if (template !== "hello_linzumi_demo" && projectPathExists(projectPath)) {
@@ -29582,7 +30106,7 @@ function createRunnerProject(control, options, allowedCwds) {
29582
30106
  error: "project_directory_exists"
29583
30107
  };
29584
30108
  }
29585
- mkdirSync12(projectsRoot, { recursive: true });
30109
+ mkdirSync13(projectsRoot, { recursive: true });
29586
30110
  if (template === "hello_linzumi_demo") {
29587
30111
  createdProjectPath = true;
29588
30112
  createHelloLinzumiProject({
@@ -29590,7 +30114,7 @@ function createRunnerProject(control, options, allowedCwds) {
29590
30114
  name: resolvedProjectDirName
29591
30115
  });
29592
30116
  } else {
29593
- mkdirSync12(projectPath, { recursive: false });
30117
+ mkdirSync13(projectPath, { recursive: false });
29594
30118
  createdProjectPath = true;
29595
30119
  }
29596
30120
  const git = spawnSync5("git", ["init"], {
@@ -29708,6 +30232,8 @@ var init_runner = __esm({
29708
30232
  "src/runner.ts"() {
29709
30233
  "use strict";
29710
30234
  init_channelSession();
30235
+ init_runnerThreadSessionRegistry();
30236
+ init_outboxJournal();
29711
30237
  init_channelSessionSupport();
29712
30238
  init_commanderAttachments();
29713
30239
  init_claudeCodePipeline();
@@ -29778,7 +30304,7 @@ var init_runner = __esm({
29778
30304
  });
29779
30305
 
29780
30306
  // src/kandanTls.ts
29781
- import { existsSync as existsSync14, readFileSync as readFileSync17 } from "node:fs";
30307
+ import { existsSync as existsSync14, readFileSync as readFileSync18 } from "node:fs";
29782
30308
  import { Agent } from "undici";
29783
30309
  import WsWebSocket from "ws";
29784
30310
  function kandanTlsTrustFromEnv() {
@@ -29792,7 +30318,7 @@ function kandanTlsTrustFromCaFile(caFile) {
29792
30318
  if (!existsSync14(trimmed)) {
29793
30319
  throw new Error(`KANDAN_TLS_CA_FILE does not exist: ${trimmed}`);
29794
30320
  }
29795
- const ca = readFileSync17(trimmed, "utf8");
30321
+ const ca = readFileSync18(trimmed, "utf8");
29796
30322
  return {
29797
30323
  caFile: trimmed,
29798
30324
  ca,
@@ -48576,7 +49102,7 @@ var init_RemoveFileError = __esm({
48576
49102
 
48577
49103
  // ../../node_modules/@inquirer/external-editor/dist/esm/index.js
48578
49104
  import { spawn as spawn11, spawnSync as spawnSync6 } from "child_process";
48579
- import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync14 } from "fs";
49105
+ import { readFileSync as readFileSync21, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "fs";
48580
49106
  import path from "node:path";
48581
49107
  import os from "node:os";
48582
49108
  import { randomUUID as randomUUID5 } from "node:crypto";
@@ -48693,14 +49219,14 @@ var init_esm5 = __esm({
48693
49219
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
48694
49220
  opt.mode = this.fileOptions.mode;
48695
49221
  }
48696
- writeFileSync14(this.tempFile, this.text, opt);
49222
+ writeFileSync15(this.tempFile, this.text, opt);
48697
49223
  } catch (createFileError) {
48698
49224
  throw new CreateFileError(createFileError);
48699
49225
  }
48700
49226
  }
48701
49227
  readTemporaryFile() {
48702
49228
  try {
48703
- const tempFileBuffer = readFileSync20(this.tempFile);
49229
+ const tempFileBuffer = readFileSync21(this.tempFile);
48704
49230
  if (tempFileBuffer.length === 0) {
48705
49231
  this.text = "";
48706
49232
  } else {
@@ -50069,17 +50595,17 @@ import { spawn as spawn12, spawnSync as spawnSync7 } from "node:child_process";
50069
50595
  import {
50070
50596
  existsSync as existsSync17,
50071
50597
  constants as fsConstants,
50072
- mkdirSync as mkdirSync15,
50073
- mkdtempSync as mkdtempSync5,
50074
- readFileSync as readFileSync21,
50598
+ mkdirSync as mkdirSync16,
50599
+ mkdtempSync as mkdtempSync6,
50600
+ readFileSync as readFileSync22,
50075
50601
  readdirSync as readdirSync5,
50076
- rmSync as rmSync6,
50602
+ rmSync as rmSync7,
50077
50603
  statSync as statSync4,
50078
- writeFileSync as writeFileSync15
50604
+ writeFileSync as writeFileSync16
50079
50605
  } from "node:fs";
50080
50606
  import { access } from "node:fs/promises";
50081
- import { homedir as homedir16, tmpdir as tmpdir4 } from "node:os";
50082
- import { delimiter as delimiter3, dirname as dirname16, join as join23, resolve as resolve10 } from "node:path";
50607
+ import { homedir as homedir17, tmpdir as tmpdir5 } from "node:os";
50608
+ import { delimiter as delimiter3, dirname as dirname18, join as join25, resolve as resolve10 } from "node:path";
50083
50609
  import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
50084
50610
  import { emitKeypressEvents } from "node:readline";
50085
50611
  function signupHelpText() {
@@ -50200,7 +50726,7 @@ function defaultSignupDraftStore(serviceUrl) {
50200
50726
  }
50201
50727
  let parsed;
50202
50728
  try {
50203
- parsed = JSON.parse(readFileSync21(path2, "utf8"));
50729
+ parsed = JSON.parse(readFileSync22(path2, "utf8"));
50204
50730
  } catch (_error) {
50205
50731
  return void 0;
50206
50732
  }
@@ -50210,21 +50736,21 @@ function defaultSignupDraftStore(serviceUrl) {
50210
50736
  return comparableServiceUrl(parsed.serviceUrl) === comparableServiceUrl(serviceUrl) ? parsed : void 0;
50211
50737
  },
50212
50738
  write: (draft) => {
50213
- mkdirSync15(dirname16(path2), { recursive: true });
50214
- writeFileSync15(path2, `${JSON.stringify(draft, null, 2)}
50739
+ mkdirSync16(dirname18(path2), { recursive: true });
50740
+ writeFileSync16(path2, `${JSON.stringify(draft, null, 2)}
50215
50741
  `, {
50216
50742
  encoding: "utf8",
50217
50743
  mode: 384
50218
50744
  });
50219
50745
  },
50220
50746
  clear: () => {
50221
- rmSync6(path2, { force: true });
50747
+ rmSync7(path2, { force: true });
50222
50748
  }
50223
50749
  };
50224
50750
  }
50225
50751
  function defaultSignupDraftPath(serviceUrl) {
50226
- return join23(
50227
- dirname16(localConfigPath()),
50752
+ return join25(
50753
+ dirname18(localConfigPath()),
50228
50754
  `signup-draft.${localConfigScopeFileStem(serviceUrl)}.json`
50229
50755
  );
50230
50756
  }
@@ -50258,8 +50784,8 @@ function defaultSignupTaskCacheStore(serviceUrl) {
50258
50784
  }
50259
50785
  }
50260
50786
  };
50261
- mkdirSync15(dirname16(path2), { recursive: true });
50262
- writeFileSync15(path2, `${JSON.stringify(next, null, 2)}
50787
+ mkdirSync16(dirname18(path2), { recursive: true });
50788
+ writeFileSync16(path2, `${JSON.stringify(next, null, 2)}
50263
50789
  `, {
50264
50790
  encoding: "utf8",
50265
50791
  mode: 384
@@ -50268,8 +50794,8 @@ function defaultSignupTaskCacheStore(serviceUrl) {
50268
50794
  };
50269
50795
  }
50270
50796
  function defaultSignupTaskCachePath(serviceUrl) {
50271
- return join23(
50272
- dirname16(localConfigPath()),
50797
+ return join25(
50798
+ dirname18(localConfigPath()),
50273
50799
  `signup-task-cache.${localConfigScopeFileStem(serviceUrl)}.json`
50274
50800
  );
50275
50801
  }
@@ -50279,7 +50805,7 @@ function readSignupTaskCache(path2) {
50279
50805
  }
50280
50806
  let parsed;
50281
50807
  try {
50282
- parsed = JSON.parse(readFileSync21(path2, "utf8"));
50808
+ parsed = JSON.parse(readFileSync22(path2, "utf8"));
50283
50809
  } catch (_error) {
50284
50810
  return { version: 1, entries: {} };
50285
50811
  }
@@ -52164,7 +52690,7 @@ function autocompletePathSuggestions(pathInput) {
52164
52690
  try {
52165
52691
  const showHidden = prefix.startsWith(".");
52166
52692
  const currentPath = directoryExists(normalizedInput) ? [normalizedInput.replace(/\/$/, "") || "/"] : [];
52167
- const childPaths = readdirSync5(directoryPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => showHidden || !entry.name.startsWith(".")).map((entry) => join23(directoryPath, entry.name)).map((path2) => ({
52693
+ const childPaths = readdirSync5(directoryPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => showHidden || !entry.name.startsWith(".")).map((entry) => join25(directoryPath, entry.name)).map((path2) => ({
52168
52694
  path: path2,
52169
52695
  score: fuzzyPathSegmentScore(path2.split("/").at(-1) ?? path2, prefix)
52170
52696
  })).filter((candidate) => candidate.score !== void 0).sort((left, right) => {
@@ -52410,7 +52936,7 @@ async function runSignupPreflights(runtime) {
52410
52936
  function defaultPreflightRuntime() {
52411
52937
  return {
52412
52938
  cwd: process.cwd(),
52413
- homeDir: homedir16(),
52939
+ homeDir: homedir17(),
52414
52940
  probeTool,
52415
52941
  readGitEmail,
52416
52942
  discoverCodeRoots,
@@ -52555,13 +53081,13 @@ async function suggestTasksWithCodex(projectPath, retryPolicy) {
52555
53081
  );
52556
53082
  }
52557
53083
  async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolicy) {
52558
- const tempRoot = mkdtempSync5(join23(tmpdir4(), "linzumi-signup-codex-tasks-"));
52559
- const schemaPath = join23(tempRoot, "task-suggestions.schema.json");
52560
- const outputPath = join23(tempRoot, "task-suggestions.json");
53084
+ const tempRoot = mkdtempSync6(join25(tmpdir5(), "linzumi-signup-codex-tasks-"));
53085
+ const schemaPath = join25(tempRoot, "task-suggestions.schema.json");
53086
+ const outputPath = join25(tempRoot, "task-suggestions.json");
52561
53087
  const model = process.env.LINZUMI_SIGNUP_TASK_MODEL ?? "gpt-5.4-mini";
52562
53088
  const prompt = taskSuggestionPrompt2(previousResponse);
52563
53089
  const codexCommand = await resolveSignupCodexCommand();
52564
- writeFileSync15(
53090
+ writeFileSync16(
52565
53091
  schemaPath,
52566
53092
  `${JSON.stringify(taskSuggestionJsonSchema2(), null, 2)}
52567
53093
  `,
@@ -52582,9 +53108,9 @@ async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolic
52582
53108
  ),
52583
53109
  retryPolicy
52584
53110
  );
52585
- return readFileSync21(outputPath, "utf8");
53111
+ return readFileSync22(outputPath, "utf8");
52586
53112
  } finally {
52587
- rmSync6(tempRoot, { recursive: true, force: true });
53113
+ rmSync7(tempRoot, { recursive: true, force: true });
52588
53114
  }
52589
53115
  }
52590
53116
  function codexTaskSuggestionProcess2(args) {
@@ -52619,7 +53145,7 @@ function codexTaskSuggestionProcess2(args) {
52619
53145
  function signupCodexTaskSuggestionProcessForTest(args) {
52620
53146
  return codexTaskSuggestionProcess2(args);
52621
53147
  }
52622
- async function resolveSignupCodexCommand(env = process.env, homeDir = homedir16(), executableExists = fileIsExecutable) {
53148
+ async function resolveSignupCodexCommand(env = process.env, homeDir = homedir17(), executableExists = fileIsExecutable) {
52623
53149
  const override = firstConfiguredValue([
52624
53150
  env.LINZUMI_SIGNUP_CODEX_BIN,
52625
53151
  env.LINZUMI_CODEX_BIN
@@ -52674,7 +53200,7 @@ function resolveHomePath(path2, homeDir) {
52674
53200
  return homeDir;
52675
53201
  }
52676
53202
  if (path2.startsWith("~/")) {
52677
- return join23(homeDir, path2.slice(2));
53203
+ return join25(homeDir, path2.slice(2));
52678
53204
  }
52679
53205
  return resolve10(path2);
52680
53206
  }
@@ -52687,9 +53213,9 @@ function commandLooksPathLike(command) {
52687
53213
  }
52688
53214
  function homeManagedCodexCandidates(homeDir) {
52689
53215
  return [
52690
- join23(homeDir, ".volta", "bin", "codex"),
52691
- join23(homeDir, ".local", "bin", "codex"),
52692
- join23(homeDir, "bin", "codex")
53216
+ join25(homeDir, ".volta", "bin", "codex"),
53217
+ join25(homeDir, ".local", "bin", "codex"),
53218
+ join25(homeDir, "bin", "codex")
52693
53219
  ];
52694
53220
  }
52695
53221
  async function firstExecutablePath(paths, executableExists) {
@@ -52704,7 +53230,7 @@ function commandPathCandidates(path2) {
52704
53230
  if (path2 === void 0 || path2.trim() === "") {
52705
53231
  return [];
52706
53232
  }
52707
- return path2.split(delimiter3).filter((entry) => entry.trim() !== "").map((entry) => join23(entry, "codex"));
53233
+ return path2.split(delimiter3).filter((entry) => entry.trim() !== "").map((entry) => join25(entry, "codex"));
52708
53234
  }
52709
53235
  async function fileIsExecutable(path2) {
52710
53236
  try {
@@ -52937,11 +53463,11 @@ function codexPreflightLocation(command, homeDir) {
52937
53463
  switch (command) {
52938
53464
  case "codex":
52939
53465
  return "on PATH";
52940
- case join23(homeDir, ".volta", "bin", "codex"):
53466
+ case join25(homeDir, ".volta", "bin", "codex"):
52941
53467
  return "via Volta";
52942
- case join23(homeDir, ".local", "bin", "codex"):
53468
+ case join25(homeDir, ".local", "bin", "codex"):
52943
53469
  return "via ~/.local/bin";
52944
- case join23(homeDir, "bin", "codex"):
53470
+ case join25(homeDir, "bin", "codex"):
52945
53471
  return "via ~/bin";
52946
53472
  default:
52947
53473
  return "from configured path";
@@ -53100,7 +53626,7 @@ function probeToolWithArgs(command, args, cwd) {
53100
53626
  }
53101
53627
  async function discoverCodeRoots(homeDir) {
53102
53628
  const candidates = ["src", "code", "projects"].map(
53103
- (name) => join23(homeDir, name)
53629
+ (name) => join25(homeDir, name)
53104
53630
  );
53105
53631
  return candidates.filter((path2) => existsSync17(path2)).flatMap((path2) => discoveredProjectNames(path2));
53106
53632
  }
@@ -53154,7 +53680,7 @@ function discoverProjectsFromCurrentDirectory(cwd) {
53154
53680
  }
53155
53681
  function discoverProjectsFromGuessedRoots(homeDir) {
53156
53682
  const guessedRoots = ["src", "code", "projects"].map(
53157
- (name) => join23(homeDir, name)
53683
+ (name) => join25(homeDir, name)
53158
53684
  );
53159
53685
  const projects = guessedRoots.flatMap(
53160
53686
  (root) => discoverProjectsUnderRoot(root)
@@ -53206,25 +53732,25 @@ function looksLikeProject(path2) {
53206
53732
  "pnpm-lock.yaml",
53207
53733
  "yarn.lock",
53208
53734
  "package-lock.json"
53209
- ].some((name) => existsSync17(join23(path2, name)));
53735
+ ].some((name) => existsSync17(join25(path2, name)));
53210
53736
  }
53211
53737
  function detectProjectLanguage(path2) {
53212
- if (existsSync17(join23(path2, "pyproject.toml")) || existsSync17(join23(path2, "requirements.txt"))) {
53738
+ if (existsSync17(join25(path2, "pyproject.toml")) || existsSync17(join25(path2, "requirements.txt"))) {
53213
53739
  return "Python";
53214
53740
  }
53215
- if (existsSync17(join23(path2, "Cargo.toml"))) {
53741
+ if (existsSync17(join25(path2, "Cargo.toml"))) {
53216
53742
  return "Rust";
53217
53743
  }
53218
- if (existsSync17(join23(path2, "go.mod"))) {
53744
+ if (existsSync17(join25(path2, "go.mod"))) {
53219
53745
  return "Go";
53220
53746
  }
53221
- if (existsSync17(join23(path2, "mix.exs"))) {
53747
+ if (existsSync17(join25(path2, "mix.exs"))) {
53222
53748
  return "Elixir";
53223
53749
  }
53224
- if (existsSync17(join23(path2, "tsconfig.json")) || packageJsonMentionsTypeScript(path2)) {
53750
+ if (existsSync17(join25(path2, "tsconfig.json")) || packageJsonMentionsTypeScript(path2)) {
53225
53751
  return "TypeScript";
53226
53752
  }
53227
- if (existsSync17(join23(path2, "package.json"))) {
53753
+ if (existsSync17(join25(path2, "package.json"))) {
53228
53754
  return "JavaScript";
53229
53755
  }
53230
53756
  return "Project";
@@ -53232,7 +53758,7 @@ function detectProjectLanguage(path2) {
53232
53758
  function packageJsonMentionsTypeScript(path2) {
53233
53759
  try {
53234
53760
  const packageJson2 = JSON.parse(
53235
- readFileSync21(join23(path2, "package.json"), "utf8")
53761
+ readFileSync22(join25(path2, "package.json"), "utf8")
53236
53762
  );
53237
53763
  return packageJson2.dependencies?.typescript !== void 0 || packageJson2.devDependencies?.typescript !== void 0;
53238
53764
  } catch {
@@ -53240,11 +53766,11 @@ function packageJsonMentionsTypeScript(path2) {
53240
53766
  }
53241
53767
  }
53242
53768
  function hasGitMetadata(path2) {
53243
- return existsSync17(join23(path2, ".git"));
53769
+ return existsSync17(join25(path2, ".git"));
53244
53770
  }
53245
53771
  function childDirectories(root) {
53246
53772
  try {
53247
- return readdirSync5(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join23(root, entry.name));
53773
+ return readdirSync5(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join25(root, entry.name));
53248
53774
  } catch {
53249
53775
  return [];
53250
53776
  }
@@ -53270,10 +53796,10 @@ function directoryExists(path2) {
53270
53796
  }
53271
53797
  function expandHomePath(path2) {
53272
53798
  if (path2 === "~") {
53273
- return homedir16();
53799
+ return homedir17();
53274
53800
  }
53275
53801
  if (path2.startsWith("~/")) {
53276
- return join23(homedir16(), path2.slice(2));
53802
+ return join25(homedir17(), path2.slice(2));
53277
53803
  }
53278
53804
  return resolve10(path2);
53279
53805
  }
@@ -53364,8 +53890,8 @@ init_runner();
53364
53890
  init_runnerLockTakeover();
53365
53891
  init_claudeCodeSession();
53366
53892
  init_authCache();
53367
- import { existsSync as existsSync18, readFileSync as readFileSync22, realpathSync as realpathSync7 } from "node:fs";
53368
- import { homedir as homedir17 } from "node:os";
53893
+ import { existsSync as existsSync18, readFileSync as readFileSync23, realpathSync as realpathSync7 } from "node:fs";
53894
+ import { homedir as homedir18 } from "node:os";
53369
53895
  import { resolve as resolve11 } from "node:path";
53370
53896
  import { fileURLToPath as fileURLToPath4 } from "node:url";
53371
53897
 
@@ -53460,9 +53986,9 @@ init_kandanTls();
53460
53986
  init_protocol();
53461
53987
  init_json();
53462
53988
  init_defaultUrls();
53463
- import { existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync18, writeFileSync as writeFileSync12 } from "node:fs";
53464
- import { dirname as dirname14, join as join21 } from "node:path";
53465
- import { homedir as homedir14 } from "node:os";
53989
+ import { existsSync as existsSync15, mkdirSync as mkdirSync14, readFileSync as readFileSync19, writeFileSync as writeFileSync13 } from "node:fs";
53990
+ import { dirname as dirname15, join as join22 } from "node:path";
53991
+ import { homedir as homedir15 } from "node:os";
53466
53992
  async function runAgentCliCommand(args, deps = {
53467
53993
  fetchImpl: fetch,
53468
53994
  stdout: process.stdout,
@@ -54170,7 +54696,7 @@ function agentTokenFile(flags) {
54170
54696
  return flags.get("agent-token-file") ?? defaultAgentTokenFilePath();
54171
54697
  }
54172
54698
  function defaultAgentTokenFilePath() {
54173
- return join21(homedir14(), ".linzumi", "agent-token.json");
54699
+ return join22(homedir15(), ".linzumi", "agent-token.json");
54174
54700
  }
54175
54701
  function normalizedApiUrl(apiUrl) {
54176
54702
  return apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`;
@@ -54179,11 +54705,11 @@ function authorizationHeaders(token) {
54179
54705
  return { authorization: `Bearer ${token}` };
54180
54706
  }
54181
54707
  function readOptionalTextFile(path2) {
54182
- return existsSync15(path2) ? readFileSync18(path2, "utf8") : void 0;
54708
+ return existsSync15(path2) ? readFileSync19(path2, "utf8") : void 0;
54183
54709
  }
54184
54710
  function writeTextFile(path2, content) {
54185
- mkdirSync13(dirname14(path2), { recursive: true });
54186
- writeFileSync12(path2, content);
54711
+ mkdirSync14(dirname15(path2), { recursive: true });
54712
+ writeFileSync13(path2, content);
54187
54713
  }
54188
54714
  function readStoredAgentTokenFile(path2, readTextFile = readOptionalTextFile) {
54189
54715
  const content = readTextFile(path2);
@@ -54272,25 +54798,25 @@ init_runnerLogger();
54272
54798
  import {
54273
54799
  existsSync as existsSync16,
54274
54800
  closeSync as closeSync3,
54275
- mkdirSync as mkdirSync14,
54801
+ mkdirSync as mkdirSync15,
54276
54802
  openSync as openSync4,
54277
- readFileSync as readFileSync19,
54803
+ readFileSync as readFileSync20,
54278
54804
  watch,
54279
- writeFileSync as writeFileSync13
54805
+ writeFileSync as writeFileSync14
54280
54806
  } from "node:fs";
54281
- import { homedir as homedir15 } from "node:os";
54282
- import { dirname as dirname15, join as join22, resolve as resolve9 } from "node:path";
54807
+ import { homedir as homedir16 } from "node:os";
54808
+ import { dirname as dirname16, join as join23, resolve as resolve9 } from "node:path";
54283
54809
  import { execFileSync, spawn as spawn10 } from "node:child_process";
54284
54810
  import { fileURLToPath as fileURLToPath3 } from "node:url";
54285
54811
  var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
54286
54812
  function commanderStatusDir() {
54287
- return join22(homedir15(), ".linzumi", "commanders");
54813
+ return join23(homedir16(), ".linzumi", "commanders");
54288
54814
  }
54289
54815
  function commanderStatusFile(runnerId, statusDir = commanderStatusDir()) {
54290
- return join22(statusDir, `${safeRunnerId(runnerId)}.json`);
54816
+ return join23(statusDir, `${safeRunnerId(runnerId)}.json`);
54291
54817
  }
54292
54818
  function defaultCommanderLogFile(runnerId) {
54293
- return join22(homedir15(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
54819
+ return join23(homedir16(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
54294
54820
  }
54295
54821
  function commanderLogIsConnected(log2) {
54296
54822
  return connectedMarkers.some((marker) => log2.includes(marker));
@@ -54311,8 +54837,8 @@ function startCommanderDaemon(options) {
54311
54837
  "--log-file",
54312
54838
  logFile
54313
54839
  ];
54314
- mkdirSync14(statusDir, { recursive: true });
54315
- mkdirSync14(dirname15(logFile), { recursive: true });
54840
+ mkdirSync15(statusDir, { recursive: true });
54841
+ mkdirSync15(dirname16(logFile), { recursive: true });
54316
54842
  const out = openSync4(logFile, "a");
54317
54843
  const err = openSync4(logFile, "a");
54318
54844
  writeCliAuditEvent(
@@ -54358,7 +54884,7 @@ function startCommanderDaemon(options) {
54358
54884
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
54359
54885
  command: [nodeBin, ...command]
54360
54886
  };
54361
- writeFileSync13(statusFile, `${JSON.stringify(record, null, 2)}
54887
+ writeFileSync14(statusFile, `${JSON.stringify(record, null, 2)}
54362
54888
  `);
54363
54889
  return record;
54364
54890
  }
@@ -54367,12 +54893,12 @@ function commanderDaemonStatus(runnerId, statusDir = commanderStatusDir(), proce
54367
54893
  if (!existsSync16(statusFile)) {
54368
54894
  return { status: "missing", runnerId, statusFile };
54369
54895
  }
54370
- const record = parseRecord(readFileSync19(statusFile, "utf8"));
54896
+ const record = parseRecord2(readFileSync20(statusFile, "utf8"));
54371
54897
  return processIsRunning(record.pid) && processMatchesRecord(record, processIdentityReader) ? { status: "running", record } : { status: "stopped", record };
54372
54898
  }
54373
54899
  async function waitForCommanderDaemon(options) {
54374
54900
  const now = options.now ?? (() => Date.now());
54375
- const readTextFile = options.readTextFile ?? ((path2) => existsSync16(path2) ? readFileSync19(path2, "utf8") : void 0);
54901
+ const readTextFile = options.readTextFile ?? ((path2) => existsSync16(path2) ? readFileSync20(path2, "utf8") : void 0);
54376
54902
  const statusImpl = options.statusImpl ?? commanderDaemonStatus;
54377
54903
  const deadline = now() + options.timeoutMs;
54378
54904
  while (now() <= deadline) {
@@ -54436,7 +54962,7 @@ function currentEntrypoint() {
54436
54962
  }
54437
54963
  return fileURLToPath3(import.meta.url);
54438
54964
  }
54439
- function parseRecord(content) {
54965
+ function parseRecord2(content) {
54440
54966
  const parsed = JSON.parse(content);
54441
54967
  const record = typeof parsed === "object" && parsed !== null ? parsed : {};
54442
54968
  const pid = typeof record.pid === "number" ? record.pid : void 0;
@@ -67254,13 +67780,18 @@ function required(values, key) {
67254
67780
  }
67255
67781
 
67256
67782
  // src/remoteCodexHarnessWorker.ts
67783
+ init_authCache();
67257
67784
  init_channelSession();
67258
67785
  init_codexAppServer();
67259
67786
  init_localCapabilities();
67787
+ init_mcpConfig();
67260
67788
  init_phoenix();
67261
67789
  init_runnerLogger();
67262
67790
  init_userFacingErrors();
67263
67791
  init_version();
67792
+ import { chmodSync as chmodSync3, mkdtempSync as mkdtempSync5, rmSync as rmSync6 } from "node:fs";
67793
+ import { tmpdir as tmpdir4 } from "node:os";
67794
+ import { basename as basename9, dirname as dirname17, join as join24 } from "node:path";
67264
67795
  var configEnvKey = "LINZUMI_REMOTE_CODEX_HARNESS_CONFIG_B64";
67265
67796
  var remoteHarnessEnvironmentId = "linzumi-remote-codex-harness";
67266
67797
  async function runRemoteCodexHarnessWorkerFromEnv(env = process.env) {
@@ -67277,17 +67808,42 @@ async function runRemoteCodexHarnessWorker(config, deps = {}) {
67277
67808
  log: writeCliAuditEvent,
67278
67809
  ...deps
67279
67810
  };
67280
- const started = await resolvedDeps.startCodexAppServer(
67281
- config.codexBin,
67282
- config.workerCwd,
67283
- {
67284
- model: config.model,
67285
- reasoningEffort: config.reasoningEffort,
67286
- fast: config.fast,
67287
- inheritEnv: false,
67288
- env: remoteHarnessCodexEnv(process.env, config.execServerUrl)
67289
- }
67811
+ const mcpAuth = writeEphemeralMcpAuthFile2(config);
67812
+ const mcpCommand = linzumiMcpCommandForProcess(
67813
+ process.execPath,
67814
+ resolveLinzumiCliEntrypoint(process.argv[1]),
67815
+ process.execArgv
67290
67816
  );
67817
+ let started;
67818
+ try {
67819
+ started = await resolvedDeps.startCodexAppServer(
67820
+ config.codexBin,
67821
+ config.workerCwd,
67822
+ {
67823
+ model: config.model,
67824
+ reasoningEffort: config.reasoningEffort,
67825
+ fast: config.fast,
67826
+ inheritEnv: false,
67827
+ env: remoteHarnessCodexEnv(process.env, config.execServerUrl),
67828
+ mcpServers: [
67829
+ linzumiMcpServerConfig({
67830
+ command: mcpCommand.command,
67831
+ argsPrefix: mcpCommand.argsPrefix,
67832
+ kandanUrl: config.kandanUrl,
67833
+ authFilePath: mcpAuth.path,
67834
+ ownerUsername: config.listenUser,
67835
+ operatingMode: "text",
67836
+ cwd: config.cwd,
67837
+ threadId: config.kandanThreadId
67838
+ })
67839
+ ]
67840
+ }
67841
+ );
67842
+ } catch (error) {
67843
+ mcpAuth.cleanup();
67844
+ throw error;
67845
+ }
67846
+ started.process.once("exit", () => mcpAuth.cleanup());
67291
67847
  let kandan;
67292
67848
  let codex;
67293
67849
  let session;
@@ -67296,6 +67852,7 @@ async function runRemoteCodexHarnessWorker(config, deps = {}) {
67296
67852
  codex?.close();
67297
67853
  kandan?.close();
67298
67854
  started.stop();
67855
+ mcpAuth.cleanup();
67299
67856
  };
67300
67857
  const cleanupOnce = onceAsync(cleanup);
67301
67858
  try {
@@ -67458,6 +68015,50 @@ function assertJsonRpcOk(response, method) {
67458
68015
  throw new Error(`${method} failed: ${response.error.message}`);
67459
68016
  }
67460
68017
  }
68018
+ function resolveLinzumiCliEntrypoint(entrypoint) {
68019
+ if (entrypoint === void 0 || entrypoint.trim() === "") {
68020
+ return entrypoint;
68021
+ }
68022
+ const base = basename9(entrypoint);
68023
+ switch (base) {
68024
+ case "remote-codex-harness-worker.js":
68025
+ case "remote-codex-harness-worker.mjs":
68026
+ case "remote-codex-harness-worker.cjs":
68027
+ return join24(dirname17(entrypoint), "linzumi.js");
68028
+ case "remoteCodexHarnessWorkerEntrypoint.ts":
68029
+ case "remoteCodexHarnessWorkerEntrypoint.js":
68030
+ return join24(dirname17(entrypoint), "index.ts");
68031
+ default:
68032
+ return entrypoint;
68033
+ }
68034
+ }
68035
+ function writeEphemeralMcpAuthFile2(options) {
68036
+ const directory = mkdtempSync5(join24(tmpdir4(), "linzumi-mcp-auth-"));
68037
+ chmodSync3(directory, 448);
68038
+ const path2 = join24(directory, "auth.json");
68039
+ try {
68040
+ writeCachedLocalRunnerToken({
68041
+ kandanUrl: options.kandanUrl,
68042
+ accessToken: options.token,
68043
+ authFilePath: path2
68044
+ });
68045
+ chmodSync3(path2, 384);
68046
+ } catch (error) {
68047
+ rmSync6(directory, { recursive: true, force: true });
68048
+ throw error;
68049
+ }
68050
+ let cleaned = false;
68051
+ return {
68052
+ path: path2,
68053
+ cleanup: () => {
68054
+ if (cleaned) {
68055
+ return;
68056
+ }
68057
+ cleaned = true;
68058
+ rmSync6(directory, { recursive: true, force: true });
68059
+ }
68060
+ };
68061
+ }
67461
68062
  function remoteHarnessCodexEnv(sourceEnv, execServerUrl) {
67462
68063
  const env = {
67463
68064
  CODEX_EXEC_SERVER_URL: execServerUrl,
@@ -68381,7 +68982,7 @@ async function parseAgentRunnerArgs(args, deps = {
68381
68982
  };
68382
68983
  }
68383
68984
  function readAgentTokenTextFile(path2) {
68384
- return existsSync18(path2) ? readFileSync22(path2, "utf8") : void 0;
68985
+ return existsSync18(path2) ? readFileSync23(path2, "utf8") : void 0;
68385
68986
  }
68386
68987
  function rejectAgentRunnerTargetingFlags(values) {
68387
68988
  const unsupportedFlags = [
@@ -68695,10 +69296,10 @@ function rejectStartTargetingFlags(values) {
68695
69296
  }
68696
69297
  function resolveUserPath(pathValue) {
68697
69298
  if (pathValue === "~") {
68698
- return homedir17();
69299
+ return homedir18();
68699
69300
  }
68700
69301
  if (pathValue.startsWith("~/")) {
68701
- return resolve11(homedir17(), pathValue.slice(2));
69302
+ return resolve11(homedir18(), pathValue.slice(2));
68702
69303
  }
68703
69304
  return resolve11(pathValue);
68704
69305
  }