@linzumi/cli 0.0.90-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 +879 -401
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5470,6 +5470,19 @@ function handleCodexNotification(state, event, deps, effects) {
5470
5470
  failTurn(state, turn, failureOutcome, failureReason(params), effects, deps);
5471
5471
  return;
5472
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
+ }
5473
5486
  if (method === "item/completed" || method === "response_item") {
5474
5487
  handleItemCompleted(turn, params, deps, effects);
5475
5488
  return;
@@ -5520,6 +5533,7 @@ function createTurn(state, turnId, sourceSeq) {
5520
5533
  sourceSeq,
5521
5534
  phase: "active",
5522
5535
  protocolFailureReason: void 0,
5536
+ lastUpstreamErrorReason: void 0,
5523
5537
  items: []
5524
5538
  };
5525
5539
  state.turns.set(turnId, turn);
@@ -5905,7 +5919,7 @@ function handleSnapshot(state, turnId, snapshot, deps, effects) {
5905
5919
  const assistantResponseSeen = turn.items.some(
5906
5920
  (item) => item.identity.streamKind === "assistant" && item.posted
5907
5921
  ) || projected.some((proj) => proj.streamKind === "assistant");
5908
- const terminalFailureReason = turn.protocolFailureReason ?? (assistantResponseSeen ? void 0 : completedWithoutAssistantOutputReason);
5922
+ const terminalFailureReason = turn.protocolFailureReason ?? (assistantResponseSeen ? void 0 : turn.lastUpstreamErrorReason ?? completedWithoutAssistantOutputReason);
5909
5923
  if (turn.protocolFailureReason !== void 0) {
5910
5924
  effects.push(
5911
5925
  log("codex.turn_completed_with_protocol_failure", {
@@ -6024,6 +6038,25 @@ function nextStreamSnapshotIndex(item) {
6024
6038
  function failureReason(params) {
6025
6039
  return stringValue(params.reason) ?? stringValue(params.message) ?? stringValue(objectValue(params.error)?.message) ?? stringValue(params.error) ?? "codex_turn_aborted";
6026
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
+ }
6027
6060
  function log(event, fields) {
6028
6061
  return { type: "log", event, fields };
6029
6062
  }
@@ -6057,6 +6090,7 @@ var init_transition = __esm({
6057
6090
  "turn/aborted",
6058
6091
  "turn/canceled",
6059
6092
  "turn/cancelled",
6093
+ "error",
6060
6094
  "item/agentMessage/delta",
6061
6095
  "item/reasoning/textDelta",
6062
6096
  "item/commandExecution/outputDelta",
@@ -11665,6 +11699,233 @@ var init_channelSession = __esm({
11665
11699
  }
11666
11700
  });
11667
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
+
11668
11929
  // src/claudeCodePipeline.ts
11669
11930
  import { existsSync as existsSync3 } from "node:fs";
11670
11931
  import { isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
@@ -12434,11 +12695,11 @@ var init_claudeCodePlanMirror = __esm({
12434
12695
  // src/runnerLogger.ts
12435
12696
  import { appendFileSync, openSync as openSync2 } from "node:fs";
12436
12697
  import { createWriteStream } from "node:fs";
12437
- import { homedir as homedir5 } from "node:os";
12438
- import { dirname as dirname3, join as join6 } from "node:path";
12439
- 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";
12440
12701
  function createRunnerLogger(logFile, consoleReporter) {
12441
- mkdirSync2(dirname3(logFile), { recursive: true });
12702
+ mkdirSync3(dirname4(logFile), { recursive: true });
12442
12703
  const fd = openSync2(logFile, "a");
12443
12704
  const stream = createWriteStream("", { fd, flags: "a", autoClose: true });
12444
12705
  const logger = ((event, payload) => {
@@ -12458,7 +12719,7 @@ function createRunnerLogger(logFile, consoleReporter) {
12458
12719
  function writeCliAuditEvent(event, payload, options = {}) {
12459
12720
  const logFile = options.logFile ?? defaultCliAuditLogFile();
12460
12721
  try {
12461
- mkdirSync2(dirname3(logFile), { recursive: true });
12722
+ mkdirSync3(dirname4(logFile), { recursive: true });
12462
12723
  appendFileSync(
12463
12724
  logFile,
12464
12725
  `${JSON.stringify({
@@ -12476,10 +12737,10 @@ function writeCliAuditEvent(event, payload, options = {}) {
12476
12737
  }
12477
12738
  function defaultCliAuditLogFile() {
12478
12739
  const override = process.env.LINZUMI_CLI_AUDIT_LOG?.trim();
12479
- 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;
12480
12741
  }
12481
12742
  function defaultRunnerLogFile() {
12482
- return join6(homedir5(), ".linzumi", "logs", "linzumi-runner.log");
12743
+ return join7(homedir6(), ".linzumi", "logs", "linzumi-runner.log");
12483
12744
  }
12484
12745
  function redactForCliLog(value) {
12485
12746
  return redactObject(value);
@@ -12755,12 +13016,12 @@ var init_engineChildReaper = __esm({
12755
13016
 
12756
13017
  // src/claudeCodeLiveBashOutput.ts
12757
13018
  import {
12758
- mkdirSync as mkdirSync3,
13019
+ mkdirSync as mkdirSync4,
12759
13020
  rmSync,
12760
- writeFileSync,
13021
+ writeFileSync as writeFileSync2,
12761
13022
  promises as fsPromises
12762
13023
  } from "node:fs";
12763
- import { join as join7 } from "node:path";
13024
+ import { join as join8 } from "node:path";
12764
13025
  import { StringDecoder } from "node:string_decoder";
12765
13026
  function shellSingleQuoted(value) {
12766
13027
  return `'${value.replaceAll("'", `'\\''`)}'`;
@@ -12885,13 +13146,13 @@ function createClaudeCodeLiveBashCapture(host) {
12885
13146
  isClaudeLiveBashWrappedCommand(command)) {
12886
13147
  return void 0;
12887
13148
  }
12888
- const file = join7(
13149
+ const file = join8(
12889
13150
  host.captureDir,
12890
13151
  `${toolUseId.replaceAll(/[^\w-]/g, "_")}.out`
12891
13152
  );
12892
13153
  try {
12893
- mkdirSync3(host.captureDir, { recursive: true });
12894
- writeFileSync(file, "");
13154
+ mkdirSync4(host.captureDir, { recursive: true });
13155
+ writeFileSync2(file, "");
12895
13156
  } catch (error) {
12896
13157
  host.log?.("claude_live_bash.capture_file_failed", {
12897
13158
  tool_use_id: toolUseId,
@@ -13052,9 +13313,9 @@ var init_claudeCodeTurnStallWatchdog = __esm({
13052
13313
  });
13053
13314
 
13054
13315
  // src/claudeCodeSession.ts
13055
- import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
13056
- import { homedir as homedir6 } from "node:os";
13057
- 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";
13058
13319
  function claudeCodeSettingSources() {
13059
13320
  return ["user", "project", "local"];
13060
13321
  }
@@ -13198,7 +13459,7 @@ function claudeCodeRateLimitSummaryText(rateLimit, nowMs) {
13198
13459
  async function probeClaudeCodeAvailability(args) {
13199
13460
  if (!hasClaudeCodeAuthHint(process.env, {
13200
13461
  cwd: args.cwd,
13201
- homeDir: homedir6(),
13462
+ homeDir: homedir7(),
13202
13463
  platform: process.platform,
13203
13464
  fileExists: existsSync4,
13204
13465
  readTextFile: readTextFileIfPresent
@@ -13231,7 +13492,7 @@ async function probeClaudeCodeAvailability(args) {
13231
13492
  }
13232
13493
  }
13233
13494
  function hasClaudeCodeAuthHint(env, deps) {
13234
- const configDir = env.CLAUDE_CONFIG_DIR ?? join8(deps.homeDir, ".claude");
13495
+ const configDir = env.CLAUDE_CONFIG_DIR ?? join9(deps.homeDir, ".claude");
13235
13496
  return hasAnthropicCredentialEnv(env) || hasClaudeCloudProviderEnv(env) || hasClaudeCodeFileCredential(configDir, deps) || hasClaudeCodeApiKeyHelper(configDir, deps) || hasMacClaudeCodeKeychainAnchor(deps);
13236
13497
  }
13237
13498
  function claudeCodePolicyDeferHooks() {
@@ -13266,14 +13527,14 @@ function hasClaudeCloudProviderEnv(env) {
13266
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);
13267
13528
  }
13268
13529
  function hasClaudeCodeFileCredential(configDir, deps) {
13269
- 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"));
13270
13531
  }
13271
13532
  function hasClaudeCodeApiKeyHelper(configDir, deps) {
13272
13533
  return [
13273
- join8(configDir, "settings.json"),
13274
- join8(configDir, "settings.local.json"),
13275
- join8(deps.cwd, ".claude", "settings.json"),
13276
- 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")
13277
13538
  ].some((path2) => settingsFileHasApiKeyHelper(path2, deps));
13278
13539
  }
13279
13540
  function settingsFileHasApiKeyHelper(path2, deps) {
@@ -13293,14 +13554,14 @@ function hasMacClaudeCodeKeychainAnchor(deps) {
13293
13554
  return false;
13294
13555
  }
13295
13556
  return [
13296
- join8(deps.homeDir, "Library", "Application Support", "claude-cli-nodejs"),
13297
- join8(deps.homeDir, "Library", "Application Support", "Claude"),
13298
- 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")
13299
13560
  ].some((path2) => deps.fileExists(path2));
13300
13561
  }
13301
13562
  function readTextFileIfPresent(path2) {
13302
13563
  try {
13303
- return readFileSync5(path2, "utf8");
13564
+ return readFileSync6(path2, "utf8");
13304
13565
  } catch (_error) {
13305
13566
  return void 0;
13306
13567
  }
@@ -14214,10 +14475,10 @@ var init_engineParentDeathWatchdog = __esm({
14214
14475
  import {
14215
14476
  spawn as spawn2
14216
14477
  } from "node:child_process";
14217
- import { readFileSync as readFileSync6 } from "node:fs";
14478
+ import { readFileSync as readFileSync7 } from "node:fs";
14218
14479
  import { createServer } from "node:net";
14219
- import { homedir as homedir7 } from "node:os";
14220
- import { join as join9 } from "node:path";
14480
+ import { homedir as homedir8 } from "node:os";
14481
+ import { join as join10 } from "node:path";
14221
14482
  import { WebSocket as NodeWebSocket } from "ws";
14222
14483
  async function chooseLoopbackPort() {
14223
14484
  return new Promise((resolve12, reject) => {
@@ -14467,10 +14728,10 @@ function resolveForwardableOpenAiApiKey(env = process.env) {
14467
14728
  return fromEnv;
14468
14729
  }
14469
14730
  const codexHomeRaw = env.CODEX_HOME?.trim();
14470
- const codexHome = codexHomeRaw !== void 0 && codexHomeRaw !== "" ? codexHomeRaw : join9(homedir7(), ".codex");
14731
+ const codexHome = codexHomeRaw !== void 0 && codexHomeRaw !== "" ? codexHomeRaw : join10(homedir8(), ".codex");
14471
14732
  let raw;
14472
14733
  try {
14473
- raw = readFileSync6(join9(codexHome, "auth.json"), "utf8");
14734
+ raw = readFileSync7(join10(codexHome, "auth.json"), "utf8");
14474
14735
  } catch (_error) {
14475
14736
  return void 0;
14476
14737
  }
@@ -14815,22 +15076,22 @@ var init_codexAppServer = __esm({
14815
15076
  // src/codexProjectTrust.ts
14816
15077
  import {
14817
15078
  existsSync as existsSync5,
14818
- mkdirSync as mkdirSync4,
14819
- readFileSync as readFileSync7,
15079
+ mkdirSync as mkdirSync5,
15080
+ readFileSync as readFileSync8,
14820
15081
  realpathSync,
14821
- writeFileSync as writeFileSync2
15082
+ writeFileSync as writeFileSync3
14822
15083
  } from "node:fs";
14823
- import { homedir as homedir8 } from "node:os";
14824
- 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";
14825
15086
  function ensureCodexProjectTrusted(projectPath, options = {}) {
14826
15087
  const trustedPath = realpathSync(resolve3(projectPath));
14827
- const configHome = options.configHome ?? process.env.CODEX_HOME ?? join10(homedir8(), ".codex");
14828
- const configPath = join10(configHome, "config.toml");
14829
- 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") : "";
14830
15091
  const nextConfig = codexConfigWithTrustedProject(currentConfig, trustedPath);
14831
15092
  if (nextConfig !== currentConfig) {
14832
- mkdirSync4(configHome, { recursive: true });
14833
- writeFileSync2(configPath, nextConfig);
15093
+ mkdirSync5(configHome, { recursive: true });
15094
+ writeFileSync3(configPath, nextConfig);
14834
15095
  }
14835
15096
  return trustedPath;
14836
15097
  }
@@ -15175,7 +15436,7 @@ var init_codexNotificationConsoleStats = __esm({
15175
15436
 
15176
15437
  // src/localCapabilities.ts
15177
15438
  import { realpathSync as realpathSync2 } from "node:fs";
15178
- import { homedir as homedir9 } from "node:os";
15439
+ import { homedir as homedir10 } from "node:os";
15179
15440
  import { isAbsolute as isAbsolute3, relative as relative2, resolve as resolve4 } from "node:path";
15180
15441
  function parseAllowedCwdList(value) {
15181
15442
  if (value === void 0) {
@@ -15224,7 +15485,7 @@ function expandUserPath(pathValue) {
15224
15485
  }
15225
15486
  function currentHomeDirectory() {
15226
15487
  const configuredHome = process.env.HOME;
15227
- return configuredHome === void 0 || configuredHome.trim() === "" ? homedir9() : configuredHome;
15488
+ return configuredHome === void 0 || configuredHome.trim() === "" ? homedir10() : configuredHome;
15228
15489
  }
15229
15490
  function resolveAllowedCwd(requestedCwd, allowedRoots) {
15230
15491
  if (requestedCwd === void 0 || requestedCwd.trim() === "") {
@@ -15782,17 +16043,17 @@ import {
15782
16043
  chmodSync,
15783
16044
  existsSync as existsSync6,
15784
16045
  linkSync,
15785
- mkdirSync as mkdirSync5,
15786
- readFileSync as readFileSync8,
16046
+ mkdirSync as mkdirSync6,
16047
+ readFileSync as readFileSync9,
15787
16048
  realpathSync as realpathSync3,
15788
16049
  unlinkSync,
15789
- writeFileSync as writeFileSync3
16050
+ writeFileSync as writeFileSync4
15790
16051
  } from "node:fs";
15791
- import { homedir as homedir10 } from "node:os";
15792
- 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";
15793
16054
  function localConfigPath(env = process.env) {
15794
16055
  const override = env.LINZUMI_CONFIG_FILE;
15795
- 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");
15796
16057
  }
15797
16058
  function localConfigScopeKey(linzumiUrl) {
15798
16059
  const normalizedUrl = kandanHttpBaseUrl(linzumiUrl);
@@ -15873,21 +16134,21 @@ function ensureLocalRunnerId(path2 = localConfigPath(), createRunnerId = default
15873
16134
  }
15874
16135
  function localMachineIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
15875
16136
  if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
15876
- return join11(
15877
- dirname4(configPath),
16137
+ return join12(
16138
+ dirname5(configPath),
15878
16139
  `${basename5(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.machine-id`
15879
16140
  );
15880
16141
  }
15881
- return join11(dirname4(configPath), `${basename5(configPath)}.machine-id`);
16142
+ return join12(dirname5(configPath), `${basename5(configPath)}.machine-id`);
15882
16143
  }
15883
16144
  function localRunnerIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
15884
16145
  if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
15885
- return join11(
15886
- dirname4(configPath),
16146
+ return join12(
16147
+ dirname5(configPath),
15887
16148
  `${basename5(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.runner-id`
15888
16149
  );
15889
16150
  }
15890
- return join11(dirname4(configPath), `${basename5(configPath)}.runner-id`);
16151
+ return join12(dirname5(configPath), `${basename5(configPath)}.runner-id`);
15891
16152
  }
15892
16153
  function readConfiguredAllowedCwdDetailsForLinzumiUrl(linzumiUrl, path2 = localConfigPath()) {
15893
16154
  return readConfiguredAllowedCwdDetailsFromConfig(
@@ -16017,7 +16278,7 @@ function writeLocalSignupAuth(auth, path2 = localConfigPath()) {
16017
16278
  version: 1,
16018
16279
  signupAuth: nextSignupAuth
16019
16280
  };
16020
- mkdirSync5(dirname4(path2), { recursive: true });
16281
+ mkdirSync6(dirname5(path2), { recursive: true });
16021
16282
  writeLocalConfigJson(path2, next);
16022
16283
  return signupAuthFromJson(nextSignupAuth);
16023
16284
  }
@@ -16025,7 +16286,7 @@ function writeLocalConfigJson(path2, payload) {
16025
16286
  if (existsSync6(path2)) {
16026
16287
  chmodSync(path2, localConfigFileMode);
16027
16288
  }
16028
- writeFileSync3(path2, `${JSON.stringify(payload, null, 2)}
16289
+ writeFileSync4(path2, `${JSON.stringify(payload, null, 2)}
16029
16290
  `, {
16030
16291
  encoding: "utf8",
16031
16292
  mode: localConfigFileMode
@@ -16052,7 +16313,7 @@ function readLocalConfigFile(path2) {
16052
16313
  if (!existsSync6(path2)) {
16053
16314
  return { version: 1, allowedCwds: [] };
16054
16315
  }
16055
- const parsed = JSON.parse(readFileSync8(path2, "utf8"));
16316
+ const parsed = JSON.parse(readFileSync9(path2, "utf8"));
16056
16317
  if (!isConfigPayload(parsed)) {
16057
16318
  throw new Error(`invalid Linzumi config: ${path2}`);
16058
16319
  }
@@ -16081,7 +16342,7 @@ function writeLocalConfigSection(config, path2, linzumiUrl) {
16081
16342
  version: 1,
16082
16343
  [scopeKey]: nextSection
16083
16344
  };
16084
- mkdirSync5(dirname4(path2), { recursive: true });
16345
+ mkdirSync6(dirname5(path2), { recursive: true });
16085
16346
  writeLocalConfigJson(path2, next);
16086
16347
  }
16087
16348
  function isConfigPayload(value) {
@@ -16156,12 +16417,12 @@ function ensureLocalMachineIdSeed(configPath, createMachineId, linzumiUrl) {
16156
16417
  if (!machineIdValid(machineId)) {
16157
16418
  throw new Error(`invalid generated Linzumi machine id: ${machineId}`);
16158
16419
  }
16159
- mkdirSync5(dirname4(seedPath), { recursive: true });
16160
- const tempPath = join11(
16161
- dirname4(seedPath),
16420
+ mkdirSync6(dirname5(seedPath), { recursive: true });
16421
+ const tempPath = join12(
16422
+ dirname5(seedPath),
16162
16423
  `.${basename5(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
16163
16424
  );
16164
- writeFileSync3(tempPath, `${machineId}
16425
+ writeFileSync4(tempPath, `${machineId}
16165
16426
  `, { encoding: "utf8", flag: "wx" });
16166
16427
  try {
16167
16428
  linkSync(tempPath, seedPath);
@@ -16184,12 +16445,12 @@ function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
16184
16445
  if (!runnerIdValid(runnerId)) {
16185
16446
  throw new Error(`invalid generated Linzumi runner id: ${runnerId}`);
16186
16447
  }
16187
- mkdirSync5(dirname4(seedPath), { recursive: true });
16188
- const tempPath = join11(
16189
- dirname4(seedPath),
16448
+ mkdirSync6(dirname5(seedPath), { recursive: true });
16449
+ const tempPath = join12(
16450
+ dirname5(seedPath),
16190
16451
  `.${basename5(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
16191
16452
  );
16192
- writeFileSync3(tempPath, `${runnerId}
16453
+ writeFileSync4(tempPath, `${runnerId}
16193
16454
  `, { encoding: "utf8", flag: "wx" });
16194
16455
  try {
16195
16456
  linkSync(tempPath, seedPath);
@@ -16204,14 +16465,14 @@ function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
16204
16465
  }
16205
16466
  }
16206
16467
  function readMachineIdSeed(seedPath) {
16207
- const machineId = readFileSync8(seedPath, "utf8").trim();
16468
+ const machineId = readFileSync9(seedPath, "utf8").trim();
16208
16469
  if (!machineIdValid(machineId)) {
16209
16470
  throw new Error(`invalid Linzumi machine id seed: ${seedPath}`);
16210
16471
  }
16211
16472
  return machineId;
16212
16473
  }
16213
16474
  function readRunnerIdSeed(seedPath) {
16214
- const runnerId = readFileSync8(seedPath, "utf8").trim();
16475
+ const runnerId = readFileSync9(seedPath, "utf8").trim();
16215
16476
  if (!runnerIdValid(runnerId)) {
16216
16477
  throw new Error(`invalid Linzumi runner id seed: ${seedPath}`);
16217
16478
  }
@@ -16510,8 +16771,8 @@ var init_remoteCodexExecutionContext = __esm({
16510
16771
  });
16511
16772
 
16512
16773
  // src/helloLinzumiProject.ts
16513
- import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync9, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
16514
- 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";
16515
16776
  import { fileURLToPath as fileURLToPath2 } from "node:url";
16516
16777
  function createHelloLinzumiProject(input = {}) {
16517
16778
  const options = typeof input === "string" ? { rootPath: input } : input;
@@ -16520,9 +16781,9 @@ function createHelloLinzumiProject(input = {}) {
16520
16781
  const host = normalizeHost(options.host);
16521
16782
  assertTcpPort(port);
16522
16783
  assertWritableDemoRoot(root, options.reset === true);
16523
- mkdirSync6(join12(root, "src"), { recursive: true });
16784
+ mkdirSync7(join13(root, "src"), { recursive: true });
16524
16785
  for (const file of demoFiles({ root, port, host })) {
16525
- writeFileSync4(join12(root, file.path), file.content, "utf8");
16786
+ writeFileSync5(join13(root, file.path), file.content, "utf8");
16526
16787
  }
16527
16788
  return {
16528
16789
  root,
@@ -16566,8 +16827,8 @@ function assertWritableDemoRoot(root, reset) {
16566
16827
  if (!existsSync7(root)) {
16567
16828
  return;
16568
16829
  }
16569
- const markerPath = join12(root, markerFile);
16570
- 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";
16571
16832
  if (isDemoRoot && reset) {
16572
16833
  rmSync2(root, { recursive: true, force: true });
16573
16834
  return;
@@ -16601,8 +16862,8 @@ var init_helloLinzumiProject = __esm({
16601
16862
  defaultHelloLinzumiPort = 8787;
16602
16863
  defaultHelloLinzumiHost = "0.0.0.0";
16603
16864
  markerFile = ".linzumi-demo-project";
16604
- moduleDir = dirname5(fileURLToPath2(import.meta.url));
16605
- 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");
16606
16867
  packageJson = `${JSON.stringify(
16607
16868
  {
16608
16869
  name: "hello-linzumi",
@@ -17404,14 +17665,14 @@ import {
17404
17665
  copyFileSync,
17405
17666
  cpSync,
17406
17667
  existsSync as existsSync8,
17407
- mkdirSync as mkdirSync7,
17668
+ mkdirSync as mkdirSync8,
17408
17669
  mkdtempSync,
17409
- readFileSync as readFileSync10,
17670
+ readFileSync as readFileSync11,
17410
17671
  realpathSync as realpathSync4,
17411
- writeFileSync as writeFileSync5
17672
+ writeFileSync as writeFileSync6
17412
17673
  } from "node:fs";
17413
17674
  import { tmpdir } from "node:os";
17414
- 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";
17415
17676
  function isStartLocalEditorControl(control) {
17416
17677
  return control.type === "start_local_editor";
17417
17678
  }
@@ -17629,24 +17890,24 @@ function codeServerArgs(port, cwd, userDataDir, extensionsDir) {
17629
17890
  }
17630
17891
  function prepareCodeServerProfile(collaboration, editorRuntime) {
17631
17892
  try {
17632
- const userDataDir = mkdtempSync(join13(tmpdir(), "kandan-local-editor-"));
17633
- const extensionsDir = join13(userDataDir, "extensions");
17634
- const collaborationServerDir = join13(userDataDir, "collaboration-server");
17635
- const tempDir = join13(userDataDir, "tmp");
17636
- const userSettingsDir = join13(userDataDir, "User");
17637
- mkdirSync7(userSettingsDir, { recursive: true });
17638
- mkdirSync7(extensionsDir, { recursive: true });
17639
- mkdirSync7(collaborationServerDir, { recursive: true });
17640
- 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 });
17641
17902
  if (editorRuntime !== void 0) {
17642
17903
  ensureCodeServerBrowserExtensionAssets(editorRuntime);
17643
17904
  installDirectory(
17644
17905
  editorRuntime.assets.documentStateExtensionDir,
17645
- join13(extensionsDir, "kandan.document-state-telemetry")
17906
+ join14(extensionsDir, "kandan.document-state-telemetry")
17646
17907
  );
17647
17908
  }
17648
- writeFileSync5(
17649
- join13(userSettingsDir, "settings.json"),
17909
+ writeFileSync6(
17910
+ join14(userSettingsDir, "settings.json"),
17650
17911
  JSON.stringify(codeServerSettings(collaboration), null, 2)
17651
17912
  );
17652
17913
  return { ok: true, userDataDir, extensionsDir, collaborationServerDir };
@@ -17658,14 +17919,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17658
17919
  const vscodeRoot = codeServerVscodeRoot(runtime);
17659
17920
  const repairs = [
17660
17921
  {
17661
- source: join13(
17922
+ source: join14(
17662
17923
  vscodeRoot,
17663
17924
  "extensions",
17664
17925
  "git-base",
17665
17926
  "dist",
17666
17927
  "extension.js"
17667
17928
  ),
17668
- target: join13(
17929
+ target: join14(
17669
17930
  vscodeRoot,
17670
17931
  "extensions",
17671
17932
  "git-base",
@@ -17676,14 +17937,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17676
17937
  required: true
17677
17938
  },
17678
17939
  {
17679
- source: join13(
17940
+ source: join14(
17680
17941
  vscodeRoot,
17681
17942
  "extensions",
17682
17943
  "git-base",
17683
17944
  "dist",
17684
17945
  "extension.js.map"
17685
17946
  ),
17686
- target: join13(
17947
+ target: join14(
17687
17948
  vscodeRoot,
17688
17949
  "extensions",
17689
17950
  "git-base",
@@ -17694,14 +17955,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17694
17955
  required: false
17695
17956
  },
17696
17957
  {
17697
- source: join13(
17958
+ source: join14(
17698
17959
  vscodeRoot,
17699
17960
  "extensions",
17700
17961
  "merge-conflict",
17701
17962
  "dist",
17702
17963
  "mergeConflictMain.js"
17703
17964
  ),
17704
- target: join13(
17965
+ target: join14(
17705
17966
  vscodeRoot,
17706
17967
  "extensions",
17707
17968
  "merge-conflict",
@@ -17712,14 +17973,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17712
17973
  required: true
17713
17974
  },
17714
17975
  {
17715
- source: join13(
17976
+ source: join14(
17716
17977
  vscodeRoot,
17717
17978
  "extensions",
17718
17979
  "merge-conflict",
17719
17980
  "dist",
17720
17981
  "mergeConflictMain.js.map"
17721
17982
  ),
17722
- target: join13(
17983
+ target: join14(
17723
17984
  vscodeRoot,
17724
17985
  "extensions",
17725
17986
  "merge-conflict",
@@ -17737,7 +17998,7 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17737
17998
  case (!required3 && !existsSync8(source)):
17738
17999
  return;
17739
18000
  default:
17740
- mkdirSync7(dirname6(target), { recursive: true });
18001
+ mkdirSync8(dirname7(target), { recursive: true });
17741
18002
  copyFileSync(source, target);
17742
18003
  return;
17743
18004
  }
@@ -17745,10 +18006,10 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17745
18006
  }
17746
18007
  function codeServerVscodeRoot(runtime) {
17747
18008
  const roots = uniquePaths([
17748
- join13(runtime.root, "lib", "vscode"),
17749
- join13(dirname6(dirname6(runtime.codeServerBin)), "lib", "vscode"),
18009
+ join14(runtime.root, "lib", "vscode"),
18010
+ join14(dirname7(dirname7(runtime.codeServerBin)), "lib", "vscode"),
17750
18011
  ...wrappedCodeServerBin(runtime.codeServerBin).map(
17751
- (codeServerBin) => join13(dirname6(dirname6(codeServerBin)), "lib", "vscode")
18012
+ (codeServerBin) => join14(dirname7(dirname7(codeServerBin)), "lib", "vscode")
17752
18013
  )
17753
18014
  ]);
17754
18015
  const rootWithRequiredAssets = roots.find(
@@ -17764,7 +18025,7 @@ function codeServerVscodeRoot(runtime) {
17764
18025
  }
17765
18026
  function wrappedCodeServerBin(codeServerBin) {
17766
18027
  try {
17767
- const script = readFileSync10(codeServerBin, "utf8");
18028
+ const script = readFileSync11(codeServerBin, "utf8");
17768
18029
  const match = script.match(
17769
18030
  /exec\s+(?:"([^"]+)"|'([^']+)'|([^\s]+))\s+"\$@"/u
17770
18031
  );
@@ -17776,8 +18037,8 @@ function wrappedCodeServerBin(codeServerBin) {
17776
18037
  }
17777
18038
  function codeServerBrowserAssetSources(vscodeRoot) {
17778
18039
  return [
17779
- join13(vscodeRoot, "extensions", "git-base", "dist", "extension.js"),
17780
- join13(
18040
+ join14(vscodeRoot, "extensions", "git-base", "dist", "extension.js"),
18041
+ join14(
17781
18042
  vscodeRoot,
17782
18043
  "extensions",
17783
18044
  "merge-conflict",
@@ -17856,10 +18117,10 @@ function prepareLinuxCodeServerLaunch(options) {
17856
18117
  options.cwd,
17857
18118
  "--setenv",
17858
18119
  "XDG_DATA_HOME",
17859
- join13(options.userDataDir, "data"),
18120
+ join14(options.userDataDir, "data"),
17860
18121
  "--setenv",
17861
18122
  "XDG_CONFIG_HOME",
17862
- join13(options.userDataDir, "config"),
18123
+ join14(options.userDataDir, "config"),
17863
18124
  ...readOnlyRoots.flatMap((path2) => ["--ro-bind-try", path2, path2]),
17864
18125
  "--bind",
17865
18126
  options.cwd,
@@ -17900,12 +18161,12 @@ function resolveCodeServerExecutable(command, envPath) {
17900
18161
  if (directory.trim() === "") {
17901
18162
  continue;
17902
18163
  }
17903
- const candidate = join13(directory, command);
18164
+ const candidate = join14(directory, command);
17904
18165
  if (!existsSync8(candidate)) {
17905
18166
  continue;
17906
18167
  }
17907
18168
  const realpath2 = realpathSync4(candidate);
17908
- return { ok: true, command: realpath2, directory: dirname6(realpath2) };
18169
+ return { ok: true, command: realpath2, directory: dirname7(realpath2) };
17909
18170
  }
17910
18171
  return { ok: false };
17911
18172
  }
@@ -17914,10 +18175,10 @@ function hasPathSeparator(path2) {
17914
18175
  }
17915
18176
  function safeRealpathDir(path2) {
17916
18177
  try {
17917
- const directory = dirname6(realpathSync4(path2));
18178
+ const directory = dirname7(realpathSync4(path2));
17918
18179
  return directory === "/" ? void 0 : directory;
17919
18180
  } catch (_error) {
17920
- const directory = dirname6(path2);
18181
+ const directory = dirname7(path2);
17921
18182
  return directory === "." || directory === "/" ? void 0 : directory;
17922
18183
  }
17923
18184
  }
@@ -17986,7 +18247,7 @@ async function startCollaborationSidecar(collaboration, profile, editorRuntime,
17986
18247
  ]);
17987
18248
  const command = nodeRuntimeExecutable();
17988
18249
  const args = [
17989
- join13(
18250
+ join14(
17990
18251
  profile.collaborationServerDir,
17991
18252
  "open-collaboration-server",
17992
18253
  "bundle",
@@ -18081,11 +18342,11 @@ function nodeRuntimeExecutable(env = process.env, execPath = process.execPath) {
18081
18342
  return basename6(execPath).toLowerCase().includes("bun") ? "node" : execPath;
18082
18343
  }
18083
18344
  async function installLocalTarball(archivePath, destinationDir) {
18084
- mkdirSync7(destinationDir, { recursive: true });
18345
+ mkdirSync8(destinationDir, { recursive: true });
18085
18346
  await runProcess("tar", ["-xzf", archivePath, "-C", destinationDir]);
18086
18347
  }
18087
18348
  function installDirectory(sourceDir, destinationDir) {
18088
- mkdirSync7(dirname6(destinationDir), { recursive: true });
18349
+ mkdirSync8(dirname7(destinationDir), { recursive: true });
18089
18350
  cpSync(sourceDir, destinationDir, { recursive: true });
18090
18351
  }
18091
18352
  function codeServerEnv(env, cwd, userDataDir, collaboration) {
@@ -18103,7 +18364,7 @@ function codeServerEnv(env, cwd, userDataDir, collaboration) {
18103
18364
  KANDAN_EDITOR_COLLABORATION_ENTRY_MODE: "kandan_auto_host_or_join",
18104
18365
  KANDAN_EDITOR_COLLABORATION_ROOM_ID: collaboration.roomId,
18105
18366
  KANDAN_EDITOR_COLLABORATION_SERVER_URL: collaboration.bootstrapServerUrl,
18106
- KANDAN_EDITOR_COLLABORATION_AUTO_HOST_CLAIM_PATH: join13(
18367
+ KANDAN_EDITOR_COLLABORATION_AUTO_HOST_CLAIM_PATH: join14(
18107
18368
  userDataDir,
18108
18369
  "kandan-oct-auto-host.lock"
18109
18370
  )
@@ -18307,20 +18568,20 @@ var init_localEditor = __esm({
18307
18568
 
18308
18569
  // src/localEditorRuntime.ts
18309
18570
  import { spawn as spawn5 } from "node:child_process";
18310
- import { createHash as createHash4 } from "node:crypto";
18571
+ import { createHash as createHash5 } from "node:crypto";
18311
18572
  import {
18312
18573
  createReadStream,
18313
18574
  createWriteStream as createWriteStream2,
18314
18575
  existsSync as existsSync9,
18315
- mkdirSync as mkdirSync8,
18576
+ mkdirSync as mkdirSync9,
18316
18577
  mkdtempSync as mkdtempSync2,
18317
- readFileSync as readFileSync11,
18318
- renameSync,
18578
+ readFileSync as readFileSync12,
18579
+ renameSync as renameSync2,
18319
18580
  rmSync as rmSync3,
18320
- writeFileSync as writeFileSync6
18581
+ writeFileSync as writeFileSync7
18321
18582
  } from "node:fs";
18322
- import { homedir as homedir11 } from "node:os";
18323
- 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";
18324
18585
  import { Readable } from "node:stream";
18325
18586
  import { pipeline } from "node:stream/promises";
18326
18587
  async function resolveEditorRuntime(options) {
@@ -18511,14 +18772,14 @@ function normalizeRuntimeAssets(value) {
18511
18772
  }
18512
18773
  function installedRuntime(cacheRoot, manifest) {
18513
18774
  const runtimeRoot = runtimeInstallRoot(cacheRoot, manifest);
18514
- const manifestPath = join14(runtimeRoot, manifest.manifestPath);
18515
- const codeServerBin = join14(runtimeRoot, manifest.codeServerBinPath);
18775
+ const manifestPath = join15(runtimeRoot, manifest.manifestPath);
18776
+ const codeServerBin = join15(runtimeRoot, manifest.codeServerBinPath);
18516
18777
  const assets = verifiedRuntimeAssetPaths(runtimeRoot, manifest);
18517
18778
  if (!existsSync9(manifestPath) || !existsSync9(codeServerBin) || assets === void 0) {
18518
18779
  return { ok: false };
18519
18780
  }
18520
18781
  try {
18521
- const installed = JSON.parse(readFileSync11(manifestPath, "utf8"));
18782
+ const installed = JSON.parse(readFileSync12(manifestPath, "utf8"));
18522
18783
  if (isJsonObject(installed) && installed.version === manifest.version && installed.platform === manifest.platform && (installed.archiveSha256 === void 0 || installed.archiveSha256 === manifest.archiveSha256)) {
18523
18784
  return {
18524
18785
  ok: true,
@@ -18536,10 +18797,10 @@ function installedRuntime(cacheRoot, manifest) {
18536
18797
  return { ok: false };
18537
18798
  }
18538
18799
  async function installRuntime(args) {
18539
- mkdirSync8(args.cacheRoot, { recursive: true });
18540
- const tempRoot = mkdtempSync2(join14(args.cacheRoot, ".install-"));
18541
- const archivePath = join14(tempRoot, "runtime.tar.gz");
18542
- 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");
18543
18804
  try {
18544
18805
  const downloaded = await downloadArchive({
18545
18806
  kandanUrl: args.kandanUrl,
@@ -18551,7 +18812,7 @@ async function installRuntime(args) {
18551
18812
  if (!downloaded.ok) {
18552
18813
  return downloaded;
18553
18814
  }
18554
- mkdirSync8(extractRoot, { recursive: true });
18815
+ mkdirSync9(extractRoot, { recursive: true });
18555
18816
  if (!await args.extractArchive(archivePath, extractRoot)) {
18556
18817
  return { ok: false, reason: "archive_extract_failed" };
18557
18818
  }
@@ -18564,14 +18825,14 @@ async function installRuntime(args) {
18564
18825
  if (!assetsInstalled) {
18565
18826
  return { ok: false, reason: "install_failed" };
18566
18827
  }
18567
- const manifestPath = join14(extractRoot, args.manifest.manifestPath);
18568
- const codeServerBin = join14(extractRoot, args.manifest.codeServerBinPath);
18828
+ const manifestPath = join15(extractRoot, args.manifest.manifestPath);
18829
+ const codeServerBin = join15(extractRoot, args.manifest.codeServerBinPath);
18569
18830
  const assets = verifiedRuntimeAssetPaths(extractRoot, args.manifest);
18570
18831
  if (!existsSync9(codeServerBin) || assets === void 0) {
18571
18832
  return { ok: false, reason: "invalid_archive" };
18572
18833
  }
18573
- mkdirSync8(dirname7(manifestPath), { recursive: true });
18574
- writeFileSync6(
18834
+ mkdirSync9(dirname8(manifestPath), { recursive: true });
18835
+ writeFileSync7(
18575
18836
  manifestPath,
18576
18837
  JSON.stringify(
18577
18838
  {
@@ -18589,28 +18850,28 @@ async function installRuntime(args) {
18589
18850
  );
18590
18851
  const targetRoot = runtimeInstallRoot(args.cacheRoot, args.manifest);
18591
18852
  rmSync3(targetRoot, { recursive: true, force: true });
18592
- mkdirSync8(dirname7(targetRoot), { recursive: true });
18593
- renameSync(extractRoot, targetRoot);
18853
+ mkdirSync9(dirname8(targetRoot), { recursive: true });
18854
+ renameSync2(extractRoot, targetRoot);
18594
18855
  return {
18595
18856
  ok: true,
18596
18857
  runtime: {
18597
18858
  mode: "server_managed",
18598
18859
  root: targetRoot,
18599
- codeServerBin: join14(targetRoot, args.manifest.codeServerBinPath),
18860
+ codeServerBin: join15(targetRoot, args.manifest.codeServerBinPath),
18600
18861
  assets: {
18601
- collaborationExtensionTarball: join14(
18862
+ collaborationExtensionTarball: join15(
18602
18863
  targetRoot,
18603
18864
  "kandan",
18604
18865
  "editor_extensions",
18605
18866
  "typefox.open-collaboration-tools.tar.gz"
18606
18867
  ),
18607
- collaborationServerTarball: join14(
18868
+ collaborationServerTarball: join15(
18608
18869
  targetRoot,
18609
18870
  "kandan",
18610
18871
  "editor_servers",
18611
18872
  "open-collaboration-server.tar.gz"
18612
18873
  ),
18613
- documentStateExtensionDir: join14(
18874
+ documentStateExtensionDir: join15(
18614
18875
  targetRoot,
18615
18876
  "kandan",
18616
18877
  "editor_extensions",
@@ -18627,7 +18888,7 @@ async function installRuntime(args) {
18627
18888
  }
18628
18889
  async function materializeRuntimeAssets(args) {
18629
18890
  for (const asset of args.manifest.assets) {
18630
- const targetPath = join14(args.runtimeRoot, asset.path);
18891
+ const targetPath = join15(args.runtimeRoot, asset.path);
18631
18892
  try {
18632
18893
  const bytes = await runtimeAssetBytes({
18633
18894
  kandanUrl: args.kandanUrl,
@@ -18637,8 +18898,8 @@ async function materializeRuntimeAssets(args) {
18637
18898
  if (bytes === void 0) {
18638
18899
  continue;
18639
18900
  }
18640
- mkdirSync8(dirname7(targetPath), { recursive: true });
18641
- writeFileSync6(targetPath, bytes);
18901
+ mkdirSync9(dirname8(targetPath), { recursive: true });
18902
+ writeFileSync7(targetPath, bytes);
18642
18903
  } catch (_error) {
18643
18904
  return false;
18644
18905
  }
@@ -18717,7 +18978,7 @@ function extractTarGz(archivePath, destination) {
18717
18978
  }
18718
18979
  function fileSha256(path2) {
18719
18980
  return new Promise((resolveHash, rejectHash) => {
18720
- const hash = createHash4("sha256");
18981
+ const hash = createHash5("sha256");
18721
18982
  const stream = createReadStream(path2);
18722
18983
  stream.on("error", rejectHash);
18723
18984
  stream.on("data", (chunk) => hash.update(chunk));
@@ -18728,19 +18989,19 @@ function runtimeInstallRoot(cacheRoot, manifest) {
18728
18989
  return resolve7(cacheRoot, manifest.platform, manifest.archiveSha256);
18729
18990
  }
18730
18991
  function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18731
- const collaborationExtensionTarball = join14(
18992
+ const collaborationExtensionTarball = join15(
18732
18993
  runtimeRoot,
18733
18994
  "kandan",
18734
18995
  "editor_extensions",
18735
18996
  "typefox.open-collaboration-tools.tar.gz"
18736
18997
  );
18737
- const collaborationServerTarball = join14(
18998
+ const collaborationServerTarball = join15(
18738
18999
  runtimeRoot,
18739
19000
  "kandan",
18740
19001
  "editor_servers",
18741
19002
  "open-collaboration-server.tar.gz"
18742
19003
  );
18743
- const documentStateExtensionDir = join14(
19004
+ const documentStateExtensionDir = join15(
18744
19005
  runtimeRoot,
18745
19006
  "kandan",
18746
19007
  "editor_extensions",
@@ -18749,7 +19010,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18749
19010
  const codeServerRoot = codeServerRuntimeRoot(manifest.codeServerBinPath);
18750
19011
  const requiredPaths = [
18751
19012
  manifest.codeServerBinPath,
18752
- join14(
19013
+ join15(
18753
19014
  codeServerRoot,
18754
19015
  "lib",
18755
19016
  "vscode",
@@ -18759,7 +19020,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18759
19020
  "web",
18760
19021
  "vsda.js"
18761
19022
  ),
18762
- join14(
19023
+ join15(
18763
19024
  codeServerRoot,
18764
19025
  "lib",
18765
19026
  "vscode",
@@ -18780,7 +19041,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18780
19041
  if (expectedSha256 === void 0 && relativePath !== manifest.codeServerBinPath) {
18781
19042
  return void 0;
18782
19043
  }
18783
- const absolutePath = join14(runtimeRoot, relativePath);
19044
+ const absolutePath = join15(runtimeRoot, relativePath);
18784
19045
  if (!existsSync9(absolutePath)) {
18785
19046
  return void 0;
18786
19047
  }
@@ -18799,7 +19060,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18799
19060
  }
18800
19061
  function codeServerRuntimeRoot(codeServerBinPath) {
18801
19062
  const normalized = codeServerBinPath.replaceAll("\\", "/");
18802
- 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);
18803
19064
  }
18804
19065
  function manifestAssetChecksums(assets) {
18805
19066
  const checksums = /* @__PURE__ */ new Map();
@@ -18809,10 +19070,10 @@ function manifestAssetChecksums(assets) {
18809
19070
  return checksums;
18810
19071
  }
18811
19072
  function fileSha256Sync(path2) {
18812
- return createHash4("sha256").update(readFileSync11(path2)).digest("hex");
19073
+ return createHash5("sha256").update(readFileSync12(path2)).digest("hex");
18813
19074
  }
18814
19075
  function defaultEditorRuntimeCacheRoot() {
18815
- return join14(homedir11(), ".linzumi", "editor-runtimes");
19076
+ return join15(homedir12(), ".linzumi", "editor-runtimes");
18816
19077
  }
18817
19078
  function nonEmptyString(value) {
18818
19079
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
@@ -18832,7 +19093,7 @@ var init_localEditorRuntime = __esm({
18832
19093
 
18833
19094
  // src/dependencyStatus.ts
18834
19095
  import { spawn as spawn6, spawnSync as spawnSync4 } from "node:child_process";
18835
- 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";
18836
19097
  function probeTool(command, cwd) {
18837
19098
  return new Promise((resolve12) => {
18838
19099
  const args = ["--version"];
@@ -18989,8 +19250,8 @@ function voltaCommandCandidates(args) {
18989
19250
  new Set(
18990
19251
  [
18991
19252
  voltaBinBesideCodexShim(args.codexBin),
18992
- env.VOLTA_HOME === void 0 ? void 0 : join15(env.VOLTA_HOME, "bin", "volta"),
18993
- 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"),
18994
19255
  ...pathVoltaCandidates(env.PATH)
18995
19256
  ].filter((candidate) => candidate !== void 0)
18996
19257
  )
@@ -18998,10 +19259,10 @@ function voltaCommandCandidates(args) {
18998
19259
  }
18999
19260
  function voltaBinBesideCodexShim(codexBin) {
19000
19261
  const normalizedCodexBin = codexBin.replaceAll("\\", "/");
19001
- 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;
19002
19263
  }
19003
19264
  function pathVoltaCandidates(pathValue) {
19004
- 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"));
19005
19266
  }
19006
19267
  function codeServerDependencyStatus(args) {
19007
19268
  switch (args.editorRuntime?.status) {
@@ -19110,7 +19371,7 @@ var linzumiCliVersion, linzumiCliVersionText;
19110
19371
  var init_version = __esm({
19111
19372
  "src/version.ts"() {
19112
19373
  "use strict";
19113
- linzumiCliVersion = "0.0.90-beta";
19374
+ linzumiCliVersion = "0.0.91-beta";
19114
19375
  linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
19115
19376
  }
19116
19377
  });
@@ -19119,21 +19380,21 @@ var init_version = __esm({
19119
19380
  import {
19120
19381
  closeSync as closeSync2,
19121
19382
  existsSync as existsSync10,
19122
- mkdirSync as mkdirSync9,
19383
+ mkdirSync as mkdirSync10,
19123
19384
  openSync as openSync3,
19124
- readFileSync as readFileSync12,
19125
- renameSync as renameSync2,
19385
+ readFileSync as readFileSync13,
19386
+ renameSync as renameSync3,
19126
19387
  unlinkSync as unlinkSync2,
19127
- writeFileSync as writeFileSync7,
19388
+ writeFileSync as writeFileSync8,
19128
19389
  writeSync
19129
19390
  } from "node:fs";
19130
- import { dirname as dirname9, join as join16 } from "node:path";
19391
+ import { dirname as dirname10, join as join17 } from "node:path";
19131
19392
  function isRunnerLockHeldError(error) {
19132
19393
  return error instanceof RunnerLockHeldError || error instanceof Error && error.name === runnerLockHeldErrorName && "lockPath" in error && "heldBy" in error;
19133
19394
  }
19134
19395
  function runnerLockPath(machineId, configPath = localConfigPath(), linzumiUrl) {
19135
19396
  const lockName = linzumiUrl === void 0 ? encodeURIComponent(machineId) : localConfigScopeFileStem(linzumiUrl);
19136
- return join16(dirname9(configPath), "runners", `${lockName}.lock`);
19397
+ return join17(dirname10(configPath), "runners", `${lockName}.lock`);
19137
19398
  }
19138
19399
  function acquireRunnerLock(options) {
19139
19400
  const path2 = runnerLockPath(
@@ -19201,9 +19462,9 @@ function stampRunnerLockHeartbeat(path2, record, now) {
19201
19462
  heartbeatAt: now().toISOString()
19202
19463
  };
19203
19464
  const tmpPath = `${path2}.tmp`;
19204
- writeFileSync7(tmpPath, `${JSON.stringify(next, null, 2)}
19465
+ writeFileSync8(tmpPath, `${JSON.stringify(next, null, 2)}
19205
19466
  `, "utf8");
19206
- renameSync2(tmpPath, path2);
19467
+ renameSync3(tmpPath, path2);
19207
19468
  } catch (_error) {
19208
19469
  }
19209
19470
  }
@@ -19313,7 +19574,7 @@ function writeLockOrHandleExisting(path2, record, isPidAlive, now, killPid, onTa
19313
19574
  });
19314
19575
  }
19315
19576
  function tryCreateLock(path2, record) {
19316
- mkdirSync9(dirname9(path2), { recursive: true });
19577
+ mkdirSync10(dirname10(path2), { recursive: true });
19317
19578
  try {
19318
19579
  const fd = openSync3(path2, "wx");
19319
19580
  try {
@@ -19369,7 +19630,7 @@ function withStaleReplacementLock(path2, isPidAlive, callback) {
19369
19630
  function readReplacementLockPidIfPresent(path2) {
19370
19631
  let value;
19371
19632
  try {
19372
- value = readFileSync12(path2, "utf8").trim();
19633
+ value = readFileSync13(path2, "utf8").trim();
19373
19634
  } catch (error) {
19374
19635
  if (isNodeErrorCode2(error, "ENOENT")) {
19375
19636
  return void 0;
@@ -19412,7 +19673,7 @@ function readRunnerLockIfPresent(path2) {
19412
19673
  }
19413
19674
  }
19414
19675
  function readRunnerLock(path2) {
19415
- const parsed = JSON.parse(readFileSync12(path2, "utf8"));
19676
+ const parsed = JSON.parse(readFileSync13(path2, "utf8"));
19416
19677
  if (!isRunnerLockRecord(parsed)) {
19417
19678
  throw new Error(`invalid Linzumi runner lock: ${path2}`);
19418
19679
  }
@@ -21329,8 +21590,8 @@ var init_runnerConsoleReporter = __esm({
21329
21590
  });
21330
21591
 
21331
21592
  // src/telemetry.ts
21332
- import { mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
21333
- 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";
21334
21595
  import { randomUUID as randomUUID3 } from "node:crypto";
21335
21596
  function peekFlagValue(args, flags) {
21336
21597
  for (let index = 0; index < args.length; index += 1) {
@@ -21369,12 +21630,12 @@ function telemetryBaseUrl(apiUrl, env = process.env) {
21369
21630
  }
21370
21631
  }
21371
21632
  function telemetryInstallIdPath(env = process.env) {
21372
- return join17(dirname10(localConfigPath(env)), "install-id");
21633
+ return join18(dirname11(localConfigPath(env)), "install-id");
21373
21634
  }
21374
21635
  function ensureTelemetryInstallId(env = process.env) {
21375
21636
  const path2 = telemetryInstallIdPath(env);
21376
21637
  try {
21377
- const existing = readFileSync13(path2, "utf8").trim();
21638
+ const existing = readFileSync14(path2, "utf8").trim();
21378
21639
  if (existing !== "" && existing.length <= 128) {
21379
21640
  return existing;
21380
21641
  }
@@ -21382,8 +21643,8 @@ function ensureTelemetryInstallId(env = process.env) {
21382
21643
  }
21383
21644
  const installId = randomUUID3();
21384
21645
  try {
21385
- mkdirSync10(dirname10(path2), { recursive: true });
21386
- writeFileSync8(path2, `${installId}
21646
+ mkdirSync11(dirname11(path2), { recursive: true });
21647
+ writeFileSync9(path2, `${installId}
21387
21648
  `, { mode: 384 });
21388
21649
  } catch {
21389
21650
  }
@@ -21576,17 +21837,17 @@ var init_linzumiApiClient = __esm({
21576
21837
  });
21577
21838
 
21578
21839
  // src/authCache.ts
21579
- import { existsSync as existsSync11, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
21580
- import { homedir as homedir12 } from "node:os";
21581
- 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";
21582
21843
  function defaultAuthFilePath() {
21583
- return join18(homedir12(), ".linzumi", "auth.json");
21844
+ return join19(homedir13(), ".linzumi", "auth.json");
21584
21845
  }
21585
21846
  function readCachedLocalRunnerToken(kandanUrl, authFilePath = defaultAuthFilePath()) {
21586
21847
  if (!existsSync11(authFilePath)) {
21587
21848
  return void 0;
21588
21849
  }
21589
- const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
21850
+ const authFile = parseAuthFile(readFileSync15(authFilePath, "utf8"));
21590
21851
  const kandanBaseUrl = kandanHttpBaseUrl(kandanUrl);
21591
21852
  const entry = authFile.local_codex_runner?.[kandanBaseUrl];
21592
21853
  if (entry === void 0 || entry.access_token.trim() === "") {
@@ -21608,7 +21869,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
21608
21869
  `missing personal-agent delegation auth file: ${authFilePath}`
21609
21870
  );
21610
21871
  }
21611
- const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
21872
+ const authFile = parseAuthFile(readFileSync15(authFilePath, "utf8"));
21612
21873
  const entry = authFile.personal_agent_delegation;
21613
21874
  if (entry === void 0 || entry.access_token.trim() === "") {
21614
21875
  throw new Error(
@@ -21626,7 +21887,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
21626
21887
  }
21627
21888
  function writeCachedLocalRunnerToken(args) {
21628
21889
  const authFilePath = args.authFilePath ?? defaultAuthFilePath();
21629
- const existing = existsSync11(authFilePath) ? parseAuthFile(readFileSync14(authFilePath, "utf8")) : { version: 1 };
21890
+ const existing = existsSync11(authFilePath) ? parseAuthFile(readFileSync15(authFilePath, "utf8")) : { version: 1 };
21630
21891
  const kandanBaseUrl = kandanHttpBaseUrl(args.kandanUrl);
21631
21892
  const issuedAt = /* @__PURE__ */ new Date();
21632
21893
  const expiresAt = args.expiresInSeconds === void 0 ? void 0 : new Date(
@@ -21644,8 +21905,8 @@ function writeCachedLocalRunnerToken(args) {
21644
21905
  }
21645
21906
  }
21646
21907
  };
21647
- mkdirSync11(dirname11(authFilePath), { recursive: true });
21648
- writeFileSync9(authFilePath, `${JSON.stringify(next, null, 2)}
21908
+ mkdirSync12(dirname12(authFilePath), { recursive: true });
21909
+ writeFileSync10(authFilePath, `${JSON.stringify(next, null, 2)}
21649
21910
  `, "utf8");
21650
21911
  return {
21651
21912
  accessToken: args.accessToken,
@@ -22090,9 +22351,9 @@ var init_threadCodexWorkerIpc = __esm({
22090
22351
 
22091
22352
  // src/signupTaskSuggestions.ts
22092
22353
  import { spawn as spawn7 } from "node:child_process";
22093
- 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";
22094
22355
  import { tmpdir as tmpdir2 } from "node:os";
22095
- import { join as join19 } from "node:path";
22356
+ import { join as join20 } from "node:path";
22096
22357
  async function suggestSignupTasksWithCodex(args) {
22097
22358
  const attempts = 2;
22098
22359
  let previousResponse;
@@ -22114,11 +22375,11 @@ async function suggestSignupTasksWithCodex(args) {
22114
22375
  );
22115
22376
  }
22116
22377
  async function runCodexTaskSuggestion(args) {
22117
- const tempRoot = mkdtempSync3(join19(tmpdir2(), "linzumi-signup-codex-tasks-"));
22118
- const schemaPath = join19(tempRoot, "task-suggestions.schema.json");
22119
- 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");
22120
22381
  const prompt = taskSuggestionPrompt(args.previousResponse);
22121
- writeFileSync10(
22382
+ writeFileSync11(
22122
22383
  schemaPath,
22123
22384
  `${JSON.stringify(taskSuggestionJsonSchema(), null, 2)}
22124
22385
  `,
@@ -22135,7 +22396,7 @@ async function runCodexTaskSuggestion(args) {
22135
22396
  prompt
22136
22397
  })
22137
22398
  );
22138
- return readFileSync15(outputPath, "utf8");
22399
+ return readFileSync16(outputPath, "utf8");
22139
22400
  } finally {
22140
22401
  rmSync4(tempRoot, { recursive: true, force: true });
22141
22402
  }
@@ -22308,7 +22569,7 @@ var init_signupTaskSuggestions = __esm({
22308
22569
  // src/remoteCodexSandboxRunner.ts
22309
22570
  import { spawn as spawn8 } from "node:child_process";
22310
22571
  import { existsSync as existsSync12, realpathSync as realpathSync5 } from "node:fs";
22311
- import { dirname as dirname12, isAbsolute as isAbsolute4 } from "node:path";
22572
+ import { dirname as dirname13, isAbsolute as isAbsolute4 } from "node:path";
22312
22573
  function createConfiguredRemoteCodexSandboxRunner(args) {
22313
22574
  const kind = normalizedSandboxKind(args.env.LINZUMI_REMOTE_CODEX_SANDBOX);
22314
22575
  if (kind === void 0) {
@@ -22423,8 +22684,8 @@ function bubblewrapArgs(sandboxBin, request, exists) {
22423
22684
  ]);
22424
22685
  const readOnlyBindArgs = uniqueStrings3([
22425
22686
  ...linuxReadOnlyRoots,
22426
- ...isAbsolute4(request.command) ? [dirname12(request.command)] : [],
22427
- dirname12(sandboxBin)
22687
+ ...isAbsolute4(request.command) ? [dirname13(request.command)] : [],
22688
+ dirname13(sandboxBin)
22428
22689
  ]).flatMap((path2) => exists(path2) ? ["--ro-bind", path2, path2] : []);
22429
22690
  const cwdParentDirs = parentDirs(request.cwd).flatMap((path2) => [
22430
22691
  "--dir",
@@ -22457,7 +22718,7 @@ function bubblewrapArgs(sandboxBin, request, exists) {
22457
22718
  function macosSeatbeltProfile(request, exists) {
22458
22719
  const readableRoots = uniqueStrings3([
22459
22720
  ...macosReadOnlyRoots,
22460
- ...isAbsolute4(request.command) ? [dirname12(request.command)] : []
22721
+ ...isAbsolute4(request.command) ? [dirname13(request.command)] : []
22461
22722
  ]).filter(exists);
22462
22723
  const readableRules = readableRoots.map((path2) => `(allow file-read* (subpath ${sandboxString(path2)}))`).join("\n");
22463
22724
  const writableTempRules = macosWritableTempRoots.filter(exists).flatMap((path2) => [
@@ -22580,31 +22841,31 @@ var init_remoteCodexSandboxRunner = __esm({
22580
22841
 
22581
22842
  // src/runner.ts
22582
22843
  import { spawn as spawn9, spawnSync as spawnSync5 } from "node:child_process";
22583
- import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
22844
+ import { createHash as createHash6, randomUUID as randomUUID4 } from "node:crypto";
22584
22845
  import {
22585
22846
  chmodSync as chmodSync2,
22586
22847
  existsSync as existsSync13,
22587
22848
  lstatSync,
22588
- mkdirSync as mkdirSync12,
22849
+ mkdirSync as mkdirSync13,
22589
22850
  mkdtempSync as mkdtempSync4,
22590
22851
  readdirSync as readdirSync4,
22591
- readFileSync as readFileSync16,
22852
+ readFileSync as readFileSync17,
22592
22853
  realpathSync as realpathSync6,
22593
- renameSync as renameSync3,
22854
+ renameSync as renameSync4,
22594
22855
  rmSync as rmSync5,
22595
22856
  statSync as statSync3,
22596
- writeFileSync as writeFileSync11
22857
+ writeFileSync as writeFileSync12
22597
22858
  } from "node:fs";
22598
22859
  import { readFile as readFile2 } from "node:fs/promises";
22599
22860
  import { createServer as createServer3 } from "node:http";
22600
- 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";
22601
22862
  import { createInterface } from "node:readline";
22602
22863
  import {
22603
22864
  basename as basename8,
22604
- dirname as dirname13,
22865
+ dirname as dirname14,
22605
22866
  extname as extname2,
22606
22867
  isAbsolute as isAbsolute5,
22607
- join as join20,
22868
+ join as join21,
22608
22869
  resolve as resolve8
22609
22870
  } from "node:path";
22610
22871
  async function runLocalCodexRunner(options) {
@@ -22883,6 +23144,10 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
22883
23144
  { discardSeqsOnFirstEpochAdoption: true }
22884
23145
  );
22885
23146
  cleanup.actions.push(() => appliedStartTurnStore.flush());
23147
+ const threadSessionRegistry = createRunnerThreadSessionRegistryStore(
23148
+ runnerThreadSessionRegistryPath(options.runnerId),
23149
+ log2
23150
+ );
22886
23151
  const controlEpochStore = createRunnerControlEpochStore(
22887
23152
  controlCursorStore,
22888
23153
  appliedStartTurnStore,
@@ -23765,6 +24030,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23765
24030
  kandan.onReconnect(() => channelSession.handleKandanReconnect());
23766
24031
  }
23767
24032
  const dynamicChannelSessions = /* @__PURE__ */ new Map();
24033
+ const dynamicChannelSessionAttachInFlight = /* @__PURE__ */ new Map();
23768
24034
  const dynamicChannelSessionCodexClients = /* @__PURE__ */ new Map();
23769
24035
  const codexTurnFailureGuards = /* @__PURE__ */ new Map();
23770
24036
  const lossReportPushes = [];
@@ -23886,90 +24152,120 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23886
24152
  if (existingSession !== void 0) {
23887
24153
  return existingSession;
23888
24154
  }
23889
- const listenUser = options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
23890
- if (listenUser === void 0) {
23891
- throw new Error(
23892
- "missing listen user for Commander-started Codex session"
23893
- );
24155
+ const alreadyAttaching = dynamicChannelSessionAttachInFlight.get(codexThreadId);
24156
+ if (alreadyAttaching !== void 0) {
24157
+ return await alreadyAttaching;
23894
24158
  }
23895
- const runtimeSettings = startInstanceRuntimeSettings(options, control);
23896
- const session = await attachChannelSession({
23897
- kandan,
23898
- codex: sessionCodex,
23899
- topic,
23900
- instanceId,
23901
- options: {
23902
- kandanUrl: options.kandanUrl,
23903
- token: options.token,
23904
- runnerId: options.runnerId,
23905
- cwd,
23906
- codexBin: options.codexBin,
23907
- fetch: options.fetch,
23908
- fast: control.fast ?? options.fast,
23909
- launchTui: false,
23910
- pipelinePersistDir: commanderOutboxPersistDir(),
23911
- enablePortForwardWatch: true,
23912
- initialForwardPorts: allowedForwardPorts,
23913
- portForwardWatcher: channelSessionPortForwardWatcherOptions({
23914
- rootPid: portForwardWatcherRootPid,
23915
- start: options.portForwardWatcher,
23916
- commanderBoundPids: args.commanderBoundPids,
23917
- commanderBoundPorts: args.commanderBoundPorts
23918
- }),
23919
- suppressedForwardPorts,
23920
- onForwardPortApproved: (port, attribution) => {
23921
- liveForwardPorts.add(port);
23922
- setForwardPortAttribution(port, {
23923
- ...attribution,
23924
- agentProvider: "codex"
23925
- });
23926
- return capabilitiesPayload();
23927
- },
23928
- onForwardPortRevoked: (port) => {
23929
- liveForwardPorts.delete(port);
23930
- clearForwardPortAttribution(port);
23931
- 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
+ }
23932
24218
  },
23933
- 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({
23934
24231
  workspaceSlug,
23935
24232
  channelSlug,
23936
24233
  kandanThreadId,
23937
- rootSeq: integerValue(control.rootSeq),
23938
24234
  codexThreadId,
23939
- linzumiContext: control.linzumiContext,
23940
- listenUser,
23941
- model: runtimeSettings.model,
23942
- reasoningEffort: runtimeSettings.reasoningEffort,
23943
- sandbox: runtimeSettings.sandbox,
23944
- approvalPolicy: runtimeSettings.approvalPolicy,
23945
- allowPortForwardingByDefault: runtimeSettings.allowPortForwardingByDefault
23946
- }
23947
- },
23948
- log: log2
23949
- });
23950
- dynamicChannelSessions.set(codexThreadId, session);
23951
- dynamicChannelSessionCodexClients.set(codexThreadId, sessionCodex);
23952
- if (sessionCodex !== codex) {
23953
- sessionCodex.onNotification((notification) => {
23954
- seq.value += 1;
23955
- const params = notification.params ?? {};
23956
- log2(
23957
- "codex.notification",
23958
- codexNotificationConsoleLogPayload(notification.method, params)
23959
- );
23960
- codexTurnFailureGuardFor(sessionCodex).observeNotification(
23961
- notification.method,
23962
- params
23963
- );
23964
- dispatchCodexNotificationToSession(
23965
- session,
23966
- notification.method,
23967
- params,
23968
- log2
23969
- );
24235
+ cwd,
24236
+ rootSeq: integerValue(control.rootSeq),
24237
+ runtimeSettings
24238
+ }),
24239
+ updatedAtMs: Date.now()
23970
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);
23971
24268
  }
23972
- return session;
23973
24269
  };
23974
24270
  const attachThreadSession = async (control, cwd, codexThreadId) => {
23975
24271
  return await attachThreadSessionWithCodex({
@@ -23980,6 +24276,69 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23980
24276
  portForwardWatcherRootPid: started?.process.pid
23981
24277
  });
23982
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);
23983
24342
  const startThreadRunnerProcess = async (control, cwd) => {
23984
24343
  if (options.threadProcess?.role === "thread") {
23985
24344
  return void 0;
@@ -24644,14 +25003,14 @@ function commanderOutboxPersistDir() {
24644
25003
  if (override !== void 0 && override !== "") {
24645
25004
  return override;
24646
25005
  }
24647
- return join20(homedir13(), ".linzumi", "commander-outbox");
25006
+ return join21(homedir14(), ".linzumi", "commander-outbox");
24648
25007
  }
24649
25008
  function controlCursorStorePath(runnerId) {
24650
25009
  const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
24651
- const digest = createHash5("sha256").update(runnerId).digest("hex").slice(0, 8);
25010
+ const digest = createHash6("sha256").update(runnerId).digest("hex").slice(0, 8);
24652
25011
  const stem = sanitized === "" ? "runner" : sanitized;
24653
- return join20(
24654
- homedir13(),
25012
+ return join21(
25013
+ homedir14(),
24655
25014
  ".linzumi",
24656
25015
  "control-cursors",
24657
25016
  `${stem}.${digest}.json`
@@ -24659,10 +25018,10 @@ function controlCursorStorePath(runnerId) {
24659
25018
  }
24660
25019
  function appliedStartTurnStorePath(runnerId) {
24661
25020
  const sanitized = runnerId.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
24662
- const digest = createHash5("sha256").update(runnerId).digest("hex").slice(0, 8);
25021
+ const digest = createHash6("sha256").update(runnerId).digest("hex").slice(0, 8);
24663
25022
  const stem = sanitized === "" ? "runner" : sanitized;
24664
- return join20(
24665
- homedir13(),
25023
+ return join21(
25024
+ homedir14(),
24666
25025
  ".linzumi",
24667
25026
  "control-cursors",
24668
25027
  `${stem}.${digest}.start-turn.json`
@@ -24784,9 +25143,9 @@ function createControlCursorFileStore(path2, log2, options) {
24784
25143
  }
24785
25144
  dirty = false;
24786
25145
  try {
24787
- mkdirSync12(dirname13(path2), { recursive: true });
25146
+ mkdirSync13(dirname14(path2), { recursive: true });
24788
25147
  const tmpPath = `${path2}.tmp`;
24789
- writeFileSync11(
25148
+ writeFileSync12(
24790
25149
  tmpPath,
24791
25150
  `${JSON.stringify({
24792
25151
  ...epoch === void 0 ? {} : { [controlCursorEpochKey]: epoch },
@@ -24795,7 +25154,7 @@ function createControlCursorFileStore(path2, log2, options) {
24795
25154
  `,
24796
25155
  "utf8"
24797
25156
  );
24798
- renameSync3(tmpPath, path2);
25157
+ renameSync4(tmpPath, path2);
24799
25158
  } catch (error) {
24800
25159
  log2("control_cursor_store.write_failed", {
24801
25160
  path: path2,
@@ -24894,7 +25253,7 @@ function readControlCursorFile(path2, log2) {
24894
25253
  const cursors = /* @__PURE__ */ new Map();
24895
25254
  let raw;
24896
25255
  try {
24897
- raw = readFileSync16(path2, "utf8");
25256
+ raw = readFileSync17(path2, "utf8");
24898
25257
  } catch (error) {
24899
25258
  if (!isErrnoCode2(error, "ENOENT")) {
24900
25259
  log2("control_cursor_store.read_failed", {
@@ -27188,7 +27547,7 @@ async function startClaudeCodeProviderInstance(args) {
27188
27547
  log: args.log
27189
27548
  });
27190
27549
  const liveBashCapture = args.options.claudeCodeRunner === void 0 && claudeLiveBashCaptureEnabled(process.env) ? createClaudeCodeLiveBashCapture({
27191
- captureDir: join20(
27550
+ captureDir: join21(
27192
27551
  tmpdir3(),
27193
27552
  `linzumi-claude-live-bash-${args.instanceId}`
27194
27553
  ),
@@ -28020,6 +28379,48 @@ function startInstanceRuntimeSettings(options, control) {
28020
28379
  allowPortForwardingByDefault: true
28021
28380
  };
28022
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
+ }
28023
28424
  function channelSessionPortForwardWatcherOptions(args) {
28024
28425
  if (args.rootPid === void 0 && args.start === void 0) {
28025
28426
  return void 0;
@@ -28993,8 +29394,8 @@ function onboardingConversationOfficeImport(response) {
28993
29394
  return objectValue(metadata?.office_channel_import);
28994
29395
  }
28995
29396
  function onboardingConversationImportClientMessageId(importKey, itemKey) {
28996
- const importHash = createHash5("sha256").update(importKey).digest("hex");
28997
- 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");
28998
29399
  return `onboarding-import:${importHash.slice(0, 32)}:${itemHash.slice(0, 24)}`;
28999
29400
  }
29000
29401
  async function uploadLocalConversationAttachments(args) {
@@ -29092,7 +29493,7 @@ async function localConversationAttachmentFile(candidatePath, attachment) {
29092
29493
  };
29093
29494
  }
29094
29495
  case "path": {
29095
- 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);
29096
29497
  try {
29097
29498
  const bytes = await readFile2(path2);
29098
29499
  return {
@@ -29482,9 +29883,9 @@ function mcpOwnerUsername(options) {
29482
29883
  return options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
29483
29884
  }
29484
29885
  function writeEphemeralMcpAuthFile(options) {
29485
- const directory = mkdtempSync4(join20(tmpdir3(), "linzumi-mcp-auth-"));
29886
+ const directory = mkdtempSync4(join21(tmpdir3(), "linzumi-mcp-auth-"));
29486
29887
  chmodSync2(directory, 448);
29487
- const path2 = join20(directory, "auth.json");
29888
+ const path2 = join21(directory, "auth.json");
29488
29889
  writeCachedLocalRunnerToken({
29489
29890
  kandanUrl: options.kandanUrl,
29490
29891
  accessToken: options.token,
@@ -29560,7 +29961,7 @@ function configuredAllowedCwds(values, options = {}) {
29560
29961
  const absolutePath = resolve8(expandUserPath(value));
29561
29962
  try {
29562
29963
  if (options.createMissing === true) {
29563
- mkdirSync12(absolutePath, { recursive: true });
29964
+ mkdirSync13(absolutePath, { recursive: true });
29564
29965
  }
29565
29966
  const realPath = realpathSync6(absolutePath);
29566
29967
  allowedCwds.push(
@@ -29597,7 +29998,7 @@ function allowedCwdProjects(allowedCwds) {
29597
29998
  });
29598
29999
  }
29599
30000
  function isGitProjectDirectory(cwd) {
29600
- const gitPath = join20(cwd, ".git");
30001
+ const gitPath = join21(cwd, ".git");
29601
30002
  try {
29602
30003
  const gitPathStats = statSync3(gitPath);
29603
30004
  return gitPathStats.isDirectory() || gitPathStats.isFile();
@@ -29620,9 +30021,9 @@ function browseRunnerDirectory(control, options) {
29620
30021
  error: "not_directory"
29621
30022
  };
29622
30023
  }
29623
- const parent = dirname13(currentPath);
30024
+ const parent = dirname14(currentPath);
29624
30025
  const entries = readdirSync4(currentPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => visibleRunnerDirectoryEntryName(entry.name)).map((entry) => {
29625
- const path2 = join20(currentPath, entry.name);
30026
+ const path2 = join21(currentPath, entry.name);
29626
30027
  return {
29627
30028
  name: entry.name,
29628
30029
  path: path2,
@@ -29663,7 +30064,7 @@ function projectDirectoryName(name) {
29663
30064
  function availableProjectDirectoryName(projectsRoot, baseName, suffix = 0) {
29664
30065
  for (let nextSuffix = suffix; ; nextSuffix += 1) {
29665
30066
  const candidate = nextSuffix === 0 ? baseName : `${baseName}-${nextSuffix}`;
29666
- if (!projectPathExists(join20(projectsRoot, candidate))) {
30067
+ if (!projectPathExists(join21(projectsRoot, candidate))) {
29667
30068
  return candidate;
29668
30069
  }
29669
30070
  }
@@ -29691,9 +30092,9 @@ function createRunnerProject(control, options, allowedCwds) {
29691
30092
  error: "invalid_project_template"
29692
30093
  };
29693
30094
  }
29694
- const projectsRoot = join20(currentHomeDirectory(), "linzumi");
30095
+ const projectsRoot = join21(currentHomeDirectory(), "linzumi");
29695
30096
  const resolvedProjectDirName = template === "hello_linzumi_demo" ? availableProjectDirectoryName(projectsRoot, projectDirName) : projectDirName;
29696
- const projectPath = join20(projectsRoot, resolvedProjectDirName);
30097
+ const projectPath = join21(projectsRoot, resolvedProjectDirName);
29697
30098
  let createdProjectPath = false;
29698
30099
  try {
29699
30100
  if (template !== "hello_linzumi_demo" && projectPathExists(projectPath)) {
@@ -29705,7 +30106,7 @@ function createRunnerProject(control, options, allowedCwds) {
29705
30106
  error: "project_directory_exists"
29706
30107
  };
29707
30108
  }
29708
- mkdirSync12(projectsRoot, { recursive: true });
30109
+ mkdirSync13(projectsRoot, { recursive: true });
29709
30110
  if (template === "hello_linzumi_demo") {
29710
30111
  createdProjectPath = true;
29711
30112
  createHelloLinzumiProject({
@@ -29713,7 +30114,7 @@ function createRunnerProject(control, options, allowedCwds) {
29713
30114
  name: resolvedProjectDirName
29714
30115
  });
29715
30116
  } else {
29716
- mkdirSync12(projectPath, { recursive: false });
30117
+ mkdirSync13(projectPath, { recursive: false });
29717
30118
  createdProjectPath = true;
29718
30119
  }
29719
30120
  const git = spawnSync5("git", ["init"], {
@@ -29831,6 +30232,8 @@ var init_runner = __esm({
29831
30232
  "src/runner.ts"() {
29832
30233
  "use strict";
29833
30234
  init_channelSession();
30235
+ init_runnerThreadSessionRegistry();
30236
+ init_outboxJournal();
29834
30237
  init_channelSessionSupport();
29835
30238
  init_commanderAttachments();
29836
30239
  init_claudeCodePipeline();
@@ -29901,7 +30304,7 @@ var init_runner = __esm({
29901
30304
  });
29902
30305
 
29903
30306
  // src/kandanTls.ts
29904
- import { existsSync as existsSync14, readFileSync as readFileSync17 } from "node:fs";
30307
+ import { existsSync as existsSync14, readFileSync as readFileSync18 } from "node:fs";
29905
30308
  import { Agent } from "undici";
29906
30309
  import WsWebSocket from "ws";
29907
30310
  function kandanTlsTrustFromEnv() {
@@ -29915,7 +30318,7 @@ function kandanTlsTrustFromCaFile(caFile) {
29915
30318
  if (!existsSync14(trimmed)) {
29916
30319
  throw new Error(`KANDAN_TLS_CA_FILE does not exist: ${trimmed}`);
29917
30320
  }
29918
- const ca = readFileSync17(trimmed, "utf8");
30321
+ const ca = readFileSync18(trimmed, "utf8");
29919
30322
  return {
29920
30323
  caFile: trimmed,
29921
30324
  ca,
@@ -48699,7 +49102,7 @@ var init_RemoveFileError = __esm({
48699
49102
 
48700
49103
  // ../../node_modules/@inquirer/external-editor/dist/esm/index.js
48701
49104
  import { spawn as spawn11, spawnSync as spawnSync6 } from "child_process";
48702
- 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";
48703
49106
  import path from "node:path";
48704
49107
  import os from "node:os";
48705
49108
  import { randomUUID as randomUUID5 } from "node:crypto";
@@ -48816,14 +49219,14 @@ var init_esm5 = __esm({
48816
49219
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
48817
49220
  opt.mode = this.fileOptions.mode;
48818
49221
  }
48819
- writeFileSync14(this.tempFile, this.text, opt);
49222
+ writeFileSync15(this.tempFile, this.text, opt);
48820
49223
  } catch (createFileError) {
48821
49224
  throw new CreateFileError(createFileError);
48822
49225
  }
48823
49226
  }
48824
49227
  readTemporaryFile() {
48825
49228
  try {
48826
- const tempFileBuffer = readFileSync20(this.tempFile);
49229
+ const tempFileBuffer = readFileSync21(this.tempFile);
48827
49230
  if (tempFileBuffer.length === 0) {
48828
49231
  this.text = "";
48829
49232
  } else {
@@ -50192,17 +50595,17 @@ import { spawn as spawn12, spawnSync as spawnSync7 } from "node:child_process";
50192
50595
  import {
50193
50596
  existsSync as existsSync17,
50194
50597
  constants as fsConstants,
50195
- mkdirSync as mkdirSync15,
50196
- mkdtempSync as mkdtempSync5,
50197
- readFileSync as readFileSync21,
50598
+ mkdirSync as mkdirSync16,
50599
+ mkdtempSync as mkdtempSync6,
50600
+ readFileSync as readFileSync22,
50198
50601
  readdirSync as readdirSync5,
50199
- rmSync as rmSync6,
50602
+ rmSync as rmSync7,
50200
50603
  statSync as statSync4,
50201
- writeFileSync as writeFileSync15
50604
+ writeFileSync as writeFileSync16
50202
50605
  } from "node:fs";
50203
50606
  import { access } from "node:fs/promises";
50204
- import { homedir as homedir16, tmpdir as tmpdir4 } from "node:os";
50205
- 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";
50206
50609
  import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
50207
50610
  import { emitKeypressEvents } from "node:readline";
50208
50611
  function signupHelpText() {
@@ -50323,7 +50726,7 @@ function defaultSignupDraftStore(serviceUrl) {
50323
50726
  }
50324
50727
  let parsed;
50325
50728
  try {
50326
- parsed = JSON.parse(readFileSync21(path2, "utf8"));
50729
+ parsed = JSON.parse(readFileSync22(path2, "utf8"));
50327
50730
  } catch (_error) {
50328
50731
  return void 0;
50329
50732
  }
@@ -50333,21 +50736,21 @@ function defaultSignupDraftStore(serviceUrl) {
50333
50736
  return comparableServiceUrl(parsed.serviceUrl) === comparableServiceUrl(serviceUrl) ? parsed : void 0;
50334
50737
  },
50335
50738
  write: (draft) => {
50336
- mkdirSync15(dirname16(path2), { recursive: true });
50337
- writeFileSync15(path2, `${JSON.stringify(draft, null, 2)}
50739
+ mkdirSync16(dirname18(path2), { recursive: true });
50740
+ writeFileSync16(path2, `${JSON.stringify(draft, null, 2)}
50338
50741
  `, {
50339
50742
  encoding: "utf8",
50340
50743
  mode: 384
50341
50744
  });
50342
50745
  },
50343
50746
  clear: () => {
50344
- rmSync6(path2, { force: true });
50747
+ rmSync7(path2, { force: true });
50345
50748
  }
50346
50749
  };
50347
50750
  }
50348
50751
  function defaultSignupDraftPath(serviceUrl) {
50349
- return join23(
50350
- dirname16(localConfigPath()),
50752
+ return join25(
50753
+ dirname18(localConfigPath()),
50351
50754
  `signup-draft.${localConfigScopeFileStem(serviceUrl)}.json`
50352
50755
  );
50353
50756
  }
@@ -50381,8 +50784,8 @@ function defaultSignupTaskCacheStore(serviceUrl) {
50381
50784
  }
50382
50785
  }
50383
50786
  };
50384
- mkdirSync15(dirname16(path2), { recursive: true });
50385
- writeFileSync15(path2, `${JSON.stringify(next, null, 2)}
50787
+ mkdirSync16(dirname18(path2), { recursive: true });
50788
+ writeFileSync16(path2, `${JSON.stringify(next, null, 2)}
50386
50789
  `, {
50387
50790
  encoding: "utf8",
50388
50791
  mode: 384
@@ -50391,8 +50794,8 @@ function defaultSignupTaskCacheStore(serviceUrl) {
50391
50794
  };
50392
50795
  }
50393
50796
  function defaultSignupTaskCachePath(serviceUrl) {
50394
- return join23(
50395
- dirname16(localConfigPath()),
50797
+ return join25(
50798
+ dirname18(localConfigPath()),
50396
50799
  `signup-task-cache.${localConfigScopeFileStem(serviceUrl)}.json`
50397
50800
  );
50398
50801
  }
@@ -50402,7 +50805,7 @@ function readSignupTaskCache(path2) {
50402
50805
  }
50403
50806
  let parsed;
50404
50807
  try {
50405
- parsed = JSON.parse(readFileSync21(path2, "utf8"));
50808
+ parsed = JSON.parse(readFileSync22(path2, "utf8"));
50406
50809
  } catch (_error) {
50407
50810
  return { version: 1, entries: {} };
50408
50811
  }
@@ -52287,7 +52690,7 @@ function autocompletePathSuggestions(pathInput) {
52287
52690
  try {
52288
52691
  const showHidden = prefix.startsWith(".");
52289
52692
  const currentPath = directoryExists(normalizedInput) ? [normalizedInput.replace(/\/$/, "") || "/"] : [];
52290
- 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) => ({
52291
52694
  path: path2,
52292
52695
  score: fuzzyPathSegmentScore(path2.split("/").at(-1) ?? path2, prefix)
52293
52696
  })).filter((candidate) => candidate.score !== void 0).sort((left, right) => {
@@ -52533,7 +52936,7 @@ async function runSignupPreflights(runtime) {
52533
52936
  function defaultPreflightRuntime() {
52534
52937
  return {
52535
52938
  cwd: process.cwd(),
52536
- homeDir: homedir16(),
52939
+ homeDir: homedir17(),
52537
52940
  probeTool,
52538
52941
  readGitEmail,
52539
52942
  discoverCodeRoots,
@@ -52678,13 +53081,13 @@ async function suggestTasksWithCodex(projectPath, retryPolicy) {
52678
53081
  );
52679
53082
  }
52680
53083
  async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolicy) {
52681
- const tempRoot = mkdtempSync5(join23(tmpdir4(), "linzumi-signup-codex-tasks-"));
52682
- const schemaPath = join23(tempRoot, "task-suggestions.schema.json");
52683
- 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");
52684
53087
  const model = process.env.LINZUMI_SIGNUP_TASK_MODEL ?? "gpt-5.4-mini";
52685
53088
  const prompt = taskSuggestionPrompt2(previousResponse);
52686
53089
  const codexCommand = await resolveSignupCodexCommand();
52687
- writeFileSync15(
53090
+ writeFileSync16(
52688
53091
  schemaPath,
52689
53092
  `${JSON.stringify(taskSuggestionJsonSchema2(), null, 2)}
52690
53093
  `,
@@ -52705,9 +53108,9 @@ async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolic
52705
53108
  ),
52706
53109
  retryPolicy
52707
53110
  );
52708
- return readFileSync21(outputPath, "utf8");
53111
+ return readFileSync22(outputPath, "utf8");
52709
53112
  } finally {
52710
- rmSync6(tempRoot, { recursive: true, force: true });
53113
+ rmSync7(tempRoot, { recursive: true, force: true });
52711
53114
  }
52712
53115
  }
52713
53116
  function codexTaskSuggestionProcess2(args) {
@@ -52742,7 +53145,7 @@ function codexTaskSuggestionProcess2(args) {
52742
53145
  function signupCodexTaskSuggestionProcessForTest(args) {
52743
53146
  return codexTaskSuggestionProcess2(args);
52744
53147
  }
52745
- async function resolveSignupCodexCommand(env = process.env, homeDir = homedir16(), executableExists = fileIsExecutable) {
53148
+ async function resolveSignupCodexCommand(env = process.env, homeDir = homedir17(), executableExists = fileIsExecutable) {
52746
53149
  const override = firstConfiguredValue([
52747
53150
  env.LINZUMI_SIGNUP_CODEX_BIN,
52748
53151
  env.LINZUMI_CODEX_BIN
@@ -52797,7 +53200,7 @@ function resolveHomePath(path2, homeDir) {
52797
53200
  return homeDir;
52798
53201
  }
52799
53202
  if (path2.startsWith("~/")) {
52800
- return join23(homeDir, path2.slice(2));
53203
+ return join25(homeDir, path2.slice(2));
52801
53204
  }
52802
53205
  return resolve10(path2);
52803
53206
  }
@@ -52810,9 +53213,9 @@ function commandLooksPathLike(command) {
52810
53213
  }
52811
53214
  function homeManagedCodexCandidates(homeDir) {
52812
53215
  return [
52813
- join23(homeDir, ".volta", "bin", "codex"),
52814
- join23(homeDir, ".local", "bin", "codex"),
52815
- join23(homeDir, "bin", "codex")
53216
+ join25(homeDir, ".volta", "bin", "codex"),
53217
+ join25(homeDir, ".local", "bin", "codex"),
53218
+ join25(homeDir, "bin", "codex")
52816
53219
  ];
52817
53220
  }
52818
53221
  async function firstExecutablePath(paths, executableExists) {
@@ -52827,7 +53230,7 @@ function commandPathCandidates(path2) {
52827
53230
  if (path2 === void 0 || path2.trim() === "") {
52828
53231
  return [];
52829
53232
  }
52830
- 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"));
52831
53234
  }
52832
53235
  async function fileIsExecutable(path2) {
52833
53236
  try {
@@ -53060,11 +53463,11 @@ function codexPreflightLocation(command, homeDir) {
53060
53463
  switch (command) {
53061
53464
  case "codex":
53062
53465
  return "on PATH";
53063
- case join23(homeDir, ".volta", "bin", "codex"):
53466
+ case join25(homeDir, ".volta", "bin", "codex"):
53064
53467
  return "via Volta";
53065
- case join23(homeDir, ".local", "bin", "codex"):
53468
+ case join25(homeDir, ".local", "bin", "codex"):
53066
53469
  return "via ~/.local/bin";
53067
- case join23(homeDir, "bin", "codex"):
53470
+ case join25(homeDir, "bin", "codex"):
53068
53471
  return "via ~/bin";
53069
53472
  default:
53070
53473
  return "from configured path";
@@ -53223,7 +53626,7 @@ function probeToolWithArgs(command, args, cwd) {
53223
53626
  }
53224
53627
  async function discoverCodeRoots(homeDir) {
53225
53628
  const candidates = ["src", "code", "projects"].map(
53226
- (name) => join23(homeDir, name)
53629
+ (name) => join25(homeDir, name)
53227
53630
  );
53228
53631
  return candidates.filter((path2) => existsSync17(path2)).flatMap((path2) => discoveredProjectNames(path2));
53229
53632
  }
@@ -53277,7 +53680,7 @@ function discoverProjectsFromCurrentDirectory(cwd) {
53277
53680
  }
53278
53681
  function discoverProjectsFromGuessedRoots(homeDir) {
53279
53682
  const guessedRoots = ["src", "code", "projects"].map(
53280
- (name) => join23(homeDir, name)
53683
+ (name) => join25(homeDir, name)
53281
53684
  );
53282
53685
  const projects = guessedRoots.flatMap(
53283
53686
  (root) => discoverProjectsUnderRoot(root)
@@ -53329,25 +53732,25 @@ function looksLikeProject(path2) {
53329
53732
  "pnpm-lock.yaml",
53330
53733
  "yarn.lock",
53331
53734
  "package-lock.json"
53332
- ].some((name) => existsSync17(join23(path2, name)));
53735
+ ].some((name) => existsSync17(join25(path2, name)));
53333
53736
  }
53334
53737
  function detectProjectLanguage(path2) {
53335
- if (existsSync17(join23(path2, "pyproject.toml")) || existsSync17(join23(path2, "requirements.txt"))) {
53738
+ if (existsSync17(join25(path2, "pyproject.toml")) || existsSync17(join25(path2, "requirements.txt"))) {
53336
53739
  return "Python";
53337
53740
  }
53338
- if (existsSync17(join23(path2, "Cargo.toml"))) {
53741
+ if (existsSync17(join25(path2, "Cargo.toml"))) {
53339
53742
  return "Rust";
53340
53743
  }
53341
- if (existsSync17(join23(path2, "go.mod"))) {
53744
+ if (existsSync17(join25(path2, "go.mod"))) {
53342
53745
  return "Go";
53343
53746
  }
53344
- if (existsSync17(join23(path2, "mix.exs"))) {
53747
+ if (existsSync17(join25(path2, "mix.exs"))) {
53345
53748
  return "Elixir";
53346
53749
  }
53347
- if (existsSync17(join23(path2, "tsconfig.json")) || packageJsonMentionsTypeScript(path2)) {
53750
+ if (existsSync17(join25(path2, "tsconfig.json")) || packageJsonMentionsTypeScript(path2)) {
53348
53751
  return "TypeScript";
53349
53752
  }
53350
- if (existsSync17(join23(path2, "package.json"))) {
53753
+ if (existsSync17(join25(path2, "package.json"))) {
53351
53754
  return "JavaScript";
53352
53755
  }
53353
53756
  return "Project";
@@ -53355,7 +53758,7 @@ function detectProjectLanguage(path2) {
53355
53758
  function packageJsonMentionsTypeScript(path2) {
53356
53759
  try {
53357
53760
  const packageJson2 = JSON.parse(
53358
- readFileSync21(join23(path2, "package.json"), "utf8")
53761
+ readFileSync22(join25(path2, "package.json"), "utf8")
53359
53762
  );
53360
53763
  return packageJson2.dependencies?.typescript !== void 0 || packageJson2.devDependencies?.typescript !== void 0;
53361
53764
  } catch {
@@ -53363,11 +53766,11 @@ function packageJsonMentionsTypeScript(path2) {
53363
53766
  }
53364
53767
  }
53365
53768
  function hasGitMetadata(path2) {
53366
- return existsSync17(join23(path2, ".git"));
53769
+ return existsSync17(join25(path2, ".git"));
53367
53770
  }
53368
53771
  function childDirectories(root) {
53369
53772
  try {
53370
- 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));
53371
53774
  } catch {
53372
53775
  return [];
53373
53776
  }
@@ -53393,10 +53796,10 @@ function directoryExists(path2) {
53393
53796
  }
53394
53797
  function expandHomePath(path2) {
53395
53798
  if (path2 === "~") {
53396
- return homedir16();
53799
+ return homedir17();
53397
53800
  }
53398
53801
  if (path2.startsWith("~/")) {
53399
- return join23(homedir16(), path2.slice(2));
53802
+ return join25(homedir17(), path2.slice(2));
53400
53803
  }
53401
53804
  return resolve10(path2);
53402
53805
  }
@@ -53487,8 +53890,8 @@ init_runner();
53487
53890
  init_runnerLockTakeover();
53488
53891
  init_claudeCodeSession();
53489
53892
  init_authCache();
53490
- import { existsSync as existsSync18, readFileSync as readFileSync22, realpathSync as realpathSync7 } from "node:fs";
53491
- 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";
53492
53895
  import { resolve as resolve11 } from "node:path";
53493
53896
  import { fileURLToPath as fileURLToPath4 } from "node:url";
53494
53897
 
@@ -53583,9 +53986,9 @@ init_kandanTls();
53583
53986
  init_protocol();
53584
53987
  init_json();
53585
53988
  init_defaultUrls();
53586
- import { existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync18, writeFileSync as writeFileSync12 } from "node:fs";
53587
- import { dirname as dirname14, join as join21 } from "node:path";
53588
- 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";
53589
53992
  async function runAgentCliCommand(args, deps = {
53590
53993
  fetchImpl: fetch,
53591
53994
  stdout: process.stdout,
@@ -54293,7 +54696,7 @@ function agentTokenFile(flags) {
54293
54696
  return flags.get("agent-token-file") ?? defaultAgentTokenFilePath();
54294
54697
  }
54295
54698
  function defaultAgentTokenFilePath() {
54296
- return join21(homedir14(), ".linzumi", "agent-token.json");
54699
+ return join22(homedir15(), ".linzumi", "agent-token.json");
54297
54700
  }
54298
54701
  function normalizedApiUrl(apiUrl) {
54299
54702
  return apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`;
@@ -54302,11 +54705,11 @@ function authorizationHeaders(token) {
54302
54705
  return { authorization: `Bearer ${token}` };
54303
54706
  }
54304
54707
  function readOptionalTextFile(path2) {
54305
- return existsSync15(path2) ? readFileSync18(path2, "utf8") : void 0;
54708
+ return existsSync15(path2) ? readFileSync19(path2, "utf8") : void 0;
54306
54709
  }
54307
54710
  function writeTextFile(path2, content) {
54308
- mkdirSync13(dirname14(path2), { recursive: true });
54309
- writeFileSync12(path2, content);
54711
+ mkdirSync14(dirname15(path2), { recursive: true });
54712
+ writeFileSync13(path2, content);
54310
54713
  }
54311
54714
  function readStoredAgentTokenFile(path2, readTextFile = readOptionalTextFile) {
54312
54715
  const content = readTextFile(path2);
@@ -54395,25 +54798,25 @@ init_runnerLogger();
54395
54798
  import {
54396
54799
  existsSync as existsSync16,
54397
54800
  closeSync as closeSync3,
54398
- mkdirSync as mkdirSync14,
54801
+ mkdirSync as mkdirSync15,
54399
54802
  openSync as openSync4,
54400
- readFileSync as readFileSync19,
54803
+ readFileSync as readFileSync20,
54401
54804
  watch,
54402
- writeFileSync as writeFileSync13
54805
+ writeFileSync as writeFileSync14
54403
54806
  } from "node:fs";
54404
- import { homedir as homedir15 } from "node:os";
54405
- 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";
54406
54809
  import { execFileSync, spawn as spawn10 } from "node:child_process";
54407
54810
  import { fileURLToPath as fileURLToPath3 } from "node:url";
54408
54811
  var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
54409
54812
  function commanderStatusDir() {
54410
- return join22(homedir15(), ".linzumi", "commanders");
54813
+ return join23(homedir16(), ".linzumi", "commanders");
54411
54814
  }
54412
54815
  function commanderStatusFile(runnerId, statusDir = commanderStatusDir()) {
54413
- return join22(statusDir, `${safeRunnerId(runnerId)}.json`);
54816
+ return join23(statusDir, `${safeRunnerId(runnerId)}.json`);
54414
54817
  }
54415
54818
  function defaultCommanderLogFile(runnerId) {
54416
- return join22(homedir15(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
54819
+ return join23(homedir16(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
54417
54820
  }
54418
54821
  function commanderLogIsConnected(log2) {
54419
54822
  return connectedMarkers.some((marker) => log2.includes(marker));
@@ -54434,8 +54837,8 @@ function startCommanderDaemon(options) {
54434
54837
  "--log-file",
54435
54838
  logFile
54436
54839
  ];
54437
- mkdirSync14(statusDir, { recursive: true });
54438
- mkdirSync14(dirname15(logFile), { recursive: true });
54840
+ mkdirSync15(statusDir, { recursive: true });
54841
+ mkdirSync15(dirname16(logFile), { recursive: true });
54439
54842
  const out = openSync4(logFile, "a");
54440
54843
  const err = openSync4(logFile, "a");
54441
54844
  writeCliAuditEvent(
@@ -54481,7 +54884,7 @@ function startCommanderDaemon(options) {
54481
54884
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
54482
54885
  command: [nodeBin, ...command]
54483
54886
  };
54484
- writeFileSync13(statusFile, `${JSON.stringify(record, null, 2)}
54887
+ writeFileSync14(statusFile, `${JSON.stringify(record, null, 2)}
54485
54888
  `);
54486
54889
  return record;
54487
54890
  }
@@ -54490,12 +54893,12 @@ function commanderDaemonStatus(runnerId, statusDir = commanderStatusDir(), proce
54490
54893
  if (!existsSync16(statusFile)) {
54491
54894
  return { status: "missing", runnerId, statusFile };
54492
54895
  }
54493
- const record = parseRecord(readFileSync19(statusFile, "utf8"));
54896
+ const record = parseRecord2(readFileSync20(statusFile, "utf8"));
54494
54897
  return processIsRunning(record.pid) && processMatchesRecord(record, processIdentityReader) ? { status: "running", record } : { status: "stopped", record };
54495
54898
  }
54496
54899
  async function waitForCommanderDaemon(options) {
54497
54900
  const now = options.now ?? (() => Date.now());
54498
- 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);
54499
54902
  const statusImpl = options.statusImpl ?? commanderDaemonStatus;
54500
54903
  const deadline = now() + options.timeoutMs;
54501
54904
  while (now() <= deadline) {
@@ -54559,7 +54962,7 @@ function currentEntrypoint() {
54559
54962
  }
54560
54963
  return fileURLToPath3(import.meta.url);
54561
54964
  }
54562
- function parseRecord(content) {
54965
+ function parseRecord2(content) {
54563
54966
  const parsed = JSON.parse(content);
54564
54967
  const record = typeof parsed === "object" && parsed !== null ? parsed : {};
54565
54968
  const pid = typeof record.pid === "number" ? record.pid : void 0;
@@ -67377,13 +67780,18 @@ function required(values, key) {
67377
67780
  }
67378
67781
 
67379
67782
  // src/remoteCodexHarnessWorker.ts
67783
+ init_authCache();
67380
67784
  init_channelSession();
67381
67785
  init_codexAppServer();
67382
67786
  init_localCapabilities();
67787
+ init_mcpConfig();
67383
67788
  init_phoenix();
67384
67789
  init_runnerLogger();
67385
67790
  init_userFacingErrors();
67386
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";
67387
67795
  var configEnvKey = "LINZUMI_REMOTE_CODEX_HARNESS_CONFIG_B64";
67388
67796
  var remoteHarnessEnvironmentId = "linzumi-remote-codex-harness";
67389
67797
  async function runRemoteCodexHarnessWorkerFromEnv(env = process.env) {
@@ -67400,17 +67808,42 @@ async function runRemoteCodexHarnessWorker(config, deps = {}) {
67400
67808
  log: writeCliAuditEvent,
67401
67809
  ...deps
67402
67810
  };
67403
- const started = await resolvedDeps.startCodexAppServer(
67404
- config.codexBin,
67405
- config.workerCwd,
67406
- {
67407
- model: config.model,
67408
- reasoningEffort: config.reasoningEffort,
67409
- fast: config.fast,
67410
- inheritEnv: false,
67411
- env: remoteHarnessCodexEnv(process.env, config.execServerUrl)
67412
- }
67811
+ const mcpAuth = writeEphemeralMcpAuthFile2(config);
67812
+ const mcpCommand = linzumiMcpCommandForProcess(
67813
+ process.execPath,
67814
+ resolveLinzumiCliEntrypoint(process.argv[1]),
67815
+ process.execArgv
67413
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());
67414
67847
  let kandan;
67415
67848
  let codex;
67416
67849
  let session;
@@ -67419,6 +67852,7 @@ async function runRemoteCodexHarnessWorker(config, deps = {}) {
67419
67852
  codex?.close();
67420
67853
  kandan?.close();
67421
67854
  started.stop();
67855
+ mcpAuth.cleanup();
67422
67856
  };
67423
67857
  const cleanupOnce = onceAsync(cleanup);
67424
67858
  try {
@@ -67581,6 +68015,50 @@ function assertJsonRpcOk(response, method) {
67581
68015
  throw new Error(`${method} failed: ${response.error.message}`);
67582
68016
  }
67583
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
+ }
67584
68062
  function remoteHarnessCodexEnv(sourceEnv, execServerUrl) {
67585
68063
  const env = {
67586
68064
  CODEX_EXEC_SERVER_URL: execServerUrl,
@@ -68504,7 +68982,7 @@ async function parseAgentRunnerArgs(args, deps = {
68504
68982
  };
68505
68983
  }
68506
68984
  function readAgentTokenTextFile(path2) {
68507
- return existsSync18(path2) ? readFileSync22(path2, "utf8") : void 0;
68985
+ return existsSync18(path2) ? readFileSync23(path2, "utf8") : void 0;
68508
68986
  }
68509
68987
  function rejectAgentRunnerTargetingFlags(values) {
68510
68988
  const unsupportedFlags = [
@@ -68818,10 +69296,10 @@ function rejectStartTargetingFlags(values) {
68818
69296
  }
68819
69297
  function resolveUserPath(pathValue) {
68820
69298
  if (pathValue === "~") {
68821
- return homedir17();
69299
+ return homedir18();
68822
69300
  }
68823
69301
  if (pathValue.startsWith("~/")) {
68824
- return resolve11(homedir17(), pathValue.slice(2));
69302
+ return resolve11(homedir18(), pathValue.slice(2));
68825
69303
  }
68826
69304
  return resolve11(pathValue);
68827
69305
  }