@linzumi/cli 0.0.90-beta → 0.0.92-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 +885 -402
  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) => {
@@ -14423,6 +14684,7 @@ function codexAppServerArgs(listenUrl, options = {}) {
14423
14684
  }
14424
14685
  function codexConfigArgs(options) {
14425
14686
  return [
14687
+ ...codexDisableAppsConfigArgs,
14426
14688
  ...options.model === void 0 ? [] : ["-c", `model=${JSON.stringify(options.model)}`],
14427
14689
  ...options.reasoningEffort === void 0 ? [] : [
14428
14690
  "-c",
@@ -14467,10 +14729,10 @@ function resolveForwardableOpenAiApiKey(env = process.env) {
14467
14729
  return fromEnv;
14468
14730
  }
14469
14731
  const codexHomeRaw = env.CODEX_HOME?.trim();
14470
- const codexHome = codexHomeRaw !== void 0 && codexHomeRaw !== "" ? codexHomeRaw : join9(homedir7(), ".codex");
14732
+ const codexHome = codexHomeRaw !== void 0 && codexHomeRaw !== "" ? codexHomeRaw : join10(homedir8(), ".codex");
14471
14733
  let raw;
14472
14734
  try {
14473
- raw = readFileSync6(join9(codexHome, "auth.json"), "utf8");
14735
+ raw = readFileSync7(join10(codexHome, "auth.json"), "utf8");
14474
14736
  } catch (_error) {
14475
14737
  return void 0;
14476
14738
  }
@@ -14795,7 +15057,7 @@ function readyzUrlForWebsocket(websocketUrl) {
14795
15057
  parsed.hash = "";
14796
15058
  return parsed.toString();
14797
15059
  }
14798
- var codexAppServerWatchdogPollMs, blockedCodexAppServerEnvKeys;
15060
+ var codexAppServerWatchdogPollMs, blockedCodexAppServerEnvKeys, codexDisableAppsConfigArgs;
14799
15061
  var init_codexAppServer = __esm({
14800
15062
  "src/codexAppServer.ts"() {
14801
15063
  "use strict";
@@ -14809,28 +15071,32 @@ var init_codexAppServer = __esm({
14809
15071
  "LINZUMI_MCP_ACCESS_TOKEN",
14810
15072
  "LINZUMI_MCP_OWNER_USERNAME"
14811
15073
  ];
15074
+ codexDisableAppsConfigArgs = [
15075
+ "-c",
15076
+ "features.apps=false"
15077
+ ];
14812
15078
  }
14813
15079
  });
14814
15080
 
14815
15081
  // src/codexProjectTrust.ts
14816
15082
  import {
14817
15083
  existsSync as existsSync5,
14818
- mkdirSync as mkdirSync4,
14819
- readFileSync as readFileSync7,
15084
+ mkdirSync as mkdirSync5,
15085
+ readFileSync as readFileSync8,
14820
15086
  realpathSync,
14821
- writeFileSync as writeFileSync2
15087
+ writeFileSync as writeFileSync3
14822
15088
  } from "node:fs";
14823
- import { homedir as homedir8 } from "node:os";
14824
- import { join as join10, resolve as resolve3 } from "node:path";
15089
+ import { homedir as homedir9 } from "node:os";
15090
+ import { join as join11, resolve as resolve3 } from "node:path";
14825
15091
  function ensureCodexProjectTrusted(projectPath, options = {}) {
14826
15092
  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") : "";
15093
+ const configHome = options.configHome ?? process.env.CODEX_HOME ?? join11(homedir9(), ".codex");
15094
+ const configPath = join11(configHome, "config.toml");
15095
+ const currentConfig = existsSync5(configPath) ? readFileSync8(configPath, "utf8") : "";
14830
15096
  const nextConfig = codexConfigWithTrustedProject(currentConfig, trustedPath);
14831
15097
  if (nextConfig !== currentConfig) {
14832
- mkdirSync4(configHome, { recursive: true });
14833
- writeFileSync2(configPath, nextConfig);
15098
+ mkdirSync5(configHome, { recursive: true });
15099
+ writeFileSync3(configPath, nextConfig);
14834
15100
  }
14835
15101
  return trustedPath;
14836
15102
  }
@@ -15175,7 +15441,7 @@ var init_codexNotificationConsoleStats = __esm({
15175
15441
 
15176
15442
  // src/localCapabilities.ts
15177
15443
  import { realpathSync as realpathSync2 } from "node:fs";
15178
- import { homedir as homedir9 } from "node:os";
15444
+ import { homedir as homedir10 } from "node:os";
15179
15445
  import { isAbsolute as isAbsolute3, relative as relative2, resolve as resolve4 } from "node:path";
15180
15446
  function parseAllowedCwdList(value) {
15181
15447
  if (value === void 0) {
@@ -15224,7 +15490,7 @@ function expandUserPath(pathValue) {
15224
15490
  }
15225
15491
  function currentHomeDirectory() {
15226
15492
  const configuredHome = process.env.HOME;
15227
- return configuredHome === void 0 || configuredHome.trim() === "" ? homedir9() : configuredHome;
15493
+ return configuredHome === void 0 || configuredHome.trim() === "" ? homedir10() : configuredHome;
15228
15494
  }
15229
15495
  function resolveAllowedCwd(requestedCwd, allowedRoots) {
15230
15496
  if (requestedCwd === void 0 || requestedCwd.trim() === "") {
@@ -15782,17 +16048,17 @@ import {
15782
16048
  chmodSync,
15783
16049
  existsSync as existsSync6,
15784
16050
  linkSync,
15785
- mkdirSync as mkdirSync5,
15786
- readFileSync as readFileSync8,
16051
+ mkdirSync as mkdirSync6,
16052
+ readFileSync as readFileSync9,
15787
16053
  realpathSync as realpathSync3,
15788
16054
  unlinkSync,
15789
- writeFileSync as writeFileSync3
16055
+ writeFileSync as writeFileSync4
15790
16056
  } 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";
16057
+ import { homedir as homedir11 } from "node:os";
16058
+ import { basename as basename5, dirname as dirname5, join as join12, resolve as resolve5 } from "node:path";
15793
16059
  function localConfigPath(env = process.env) {
15794
16060
  const override = env.LINZUMI_CONFIG_FILE;
15795
- return override !== void 0 && override.trim() !== "" ? resolve5(expandUserPath(override)) : resolve5(homedir10(), ".linzumi", "config.json");
16061
+ return override !== void 0 && override.trim() !== "" ? resolve5(expandUserPath(override)) : resolve5(homedir11(), ".linzumi", "config.json");
15796
16062
  }
15797
16063
  function localConfigScopeKey(linzumiUrl) {
15798
16064
  const normalizedUrl = kandanHttpBaseUrl(linzumiUrl);
@@ -15873,21 +16139,21 @@ function ensureLocalRunnerId(path2 = localConfigPath(), createRunnerId = default
15873
16139
  }
15874
16140
  function localMachineIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
15875
16141
  if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
15876
- return join11(
15877
- dirname4(configPath),
16142
+ return join12(
16143
+ dirname5(configPath),
15878
16144
  `${basename5(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.machine-id`
15879
16145
  );
15880
16146
  }
15881
- return join11(dirname4(configPath), `${basename5(configPath)}.machine-id`);
16147
+ return join12(dirname5(configPath), `${basename5(configPath)}.machine-id`);
15882
16148
  }
15883
16149
  function localRunnerIdSeedPath(configPath = localConfigPath(), linzumiUrl) {
15884
16150
  if (linzumiUrl !== void 0 && localConfigScopeKey(linzumiUrl) !== prodConfigScope) {
15885
- return join11(
15886
- dirname4(configPath),
16151
+ return join12(
16152
+ dirname5(configPath),
15887
16153
  `${basename5(configPath)}.${localConfigScopeFileStem(linzumiUrl)}.runner-id`
15888
16154
  );
15889
16155
  }
15890
- return join11(dirname4(configPath), `${basename5(configPath)}.runner-id`);
16156
+ return join12(dirname5(configPath), `${basename5(configPath)}.runner-id`);
15891
16157
  }
15892
16158
  function readConfiguredAllowedCwdDetailsForLinzumiUrl(linzumiUrl, path2 = localConfigPath()) {
15893
16159
  return readConfiguredAllowedCwdDetailsFromConfig(
@@ -16017,7 +16283,7 @@ function writeLocalSignupAuth(auth, path2 = localConfigPath()) {
16017
16283
  version: 1,
16018
16284
  signupAuth: nextSignupAuth
16019
16285
  };
16020
- mkdirSync5(dirname4(path2), { recursive: true });
16286
+ mkdirSync6(dirname5(path2), { recursive: true });
16021
16287
  writeLocalConfigJson(path2, next);
16022
16288
  return signupAuthFromJson(nextSignupAuth);
16023
16289
  }
@@ -16025,7 +16291,7 @@ function writeLocalConfigJson(path2, payload) {
16025
16291
  if (existsSync6(path2)) {
16026
16292
  chmodSync(path2, localConfigFileMode);
16027
16293
  }
16028
- writeFileSync3(path2, `${JSON.stringify(payload, null, 2)}
16294
+ writeFileSync4(path2, `${JSON.stringify(payload, null, 2)}
16029
16295
  `, {
16030
16296
  encoding: "utf8",
16031
16297
  mode: localConfigFileMode
@@ -16052,7 +16318,7 @@ function readLocalConfigFile(path2) {
16052
16318
  if (!existsSync6(path2)) {
16053
16319
  return { version: 1, allowedCwds: [] };
16054
16320
  }
16055
- const parsed = JSON.parse(readFileSync8(path2, "utf8"));
16321
+ const parsed = JSON.parse(readFileSync9(path2, "utf8"));
16056
16322
  if (!isConfigPayload(parsed)) {
16057
16323
  throw new Error(`invalid Linzumi config: ${path2}`);
16058
16324
  }
@@ -16081,7 +16347,7 @@ function writeLocalConfigSection(config, path2, linzumiUrl) {
16081
16347
  version: 1,
16082
16348
  [scopeKey]: nextSection
16083
16349
  };
16084
- mkdirSync5(dirname4(path2), { recursive: true });
16350
+ mkdirSync6(dirname5(path2), { recursive: true });
16085
16351
  writeLocalConfigJson(path2, next);
16086
16352
  }
16087
16353
  function isConfigPayload(value) {
@@ -16156,12 +16422,12 @@ function ensureLocalMachineIdSeed(configPath, createMachineId, linzumiUrl) {
16156
16422
  if (!machineIdValid(machineId)) {
16157
16423
  throw new Error(`invalid generated Linzumi machine id: ${machineId}`);
16158
16424
  }
16159
- mkdirSync5(dirname4(seedPath), { recursive: true });
16160
- const tempPath = join11(
16161
- dirname4(seedPath),
16425
+ mkdirSync6(dirname5(seedPath), { recursive: true });
16426
+ const tempPath = join12(
16427
+ dirname5(seedPath),
16162
16428
  `.${basename5(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
16163
16429
  );
16164
- writeFileSync3(tempPath, `${machineId}
16430
+ writeFileSync4(tempPath, `${machineId}
16165
16431
  `, { encoding: "utf8", flag: "wx" });
16166
16432
  try {
16167
16433
  linkSync(tempPath, seedPath);
@@ -16184,12 +16450,12 @@ function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
16184
16450
  if (!runnerIdValid(runnerId)) {
16185
16451
  throw new Error(`invalid generated Linzumi runner id: ${runnerId}`);
16186
16452
  }
16187
- mkdirSync5(dirname4(seedPath), { recursive: true });
16188
- const tempPath = join11(
16189
- dirname4(seedPath),
16453
+ mkdirSync6(dirname5(seedPath), { recursive: true });
16454
+ const tempPath = join12(
16455
+ dirname5(seedPath),
16190
16456
  `.${basename5(seedPath)}.${process.pid}.${randomUUID2()}.tmp`
16191
16457
  );
16192
- writeFileSync3(tempPath, `${runnerId}
16458
+ writeFileSync4(tempPath, `${runnerId}
16193
16459
  `, { encoding: "utf8", flag: "wx" });
16194
16460
  try {
16195
16461
  linkSync(tempPath, seedPath);
@@ -16204,14 +16470,14 @@ function ensureLocalRunnerIdSeed(configPath, createRunnerId, linzumiUrl) {
16204
16470
  }
16205
16471
  }
16206
16472
  function readMachineIdSeed(seedPath) {
16207
- const machineId = readFileSync8(seedPath, "utf8").trim();
16473
+ const machineId = readFileSync9(seedPath, "utf8").trim();
16208
16474
  if (!machineIdValid(machineId)) {
16209
16475
  throw new Error(`invalid Linzumi machine id seed: ${seedPath}`);
16210
16476
  }
16211
16477
  return machineId;
16212
16478
  }
16213
16479
  function readRunnerIdSeed(seedPath) {
16214
- const runnerId = readFileSync8(seedPath, "utf8").trim();
16480
+ const runnerId = readFileSync9(seedPath, "utf8").trim();
16215
16481
  if (!runnerIdValid(runnerId)) {
16216
16482
  throw new Error(`invalid Linzumi runner id seed: ${seedPath}`);
16217
16483
  }
@@ -16510,8 +16776,8 @@ var init_remoteCodexExecutionContext = __esm({
16510
16776
  });
16511
16777
 
16512
16778
  // 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";
16779
+ import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync10, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
16780
+ import { dirname as dirname6, join as join13, resolve as resolve6 } from "node:path";
16515
16781
  import { fileURLToPath as fileURLToPath2 } from "node:url";
16516
16782
  function createHelloLinzumiProject(input = {}) {
16517
16783
  const options = typeof input === "string" ? { rootPath: input } : input;
@@ -16520,9 +16786,9 @@ function createHelloLinzumiProject(input = {}) {
16520
16786
  const host = normalizeHost(options.host);
16521
16787
  assertTcpPort(port);
16522
16788
  assertWritableDemoRoot(root, options.reset === true);
16523
- mkdirSync6(join12(root, "src"), { recursive: true });
16789
+ mkdirSync7(join13(root, "src"), { recursive: true });
16524
16790
  for (const file of demoFiles({ root, port, host })) {
16525
- writeFileSync4(join12(root, file.path), file.content, "utf8");
16791
+ writeFileSync5(join13(root, file.path), file.content, "utf8");
16526
16792
  }
16527
16793
  return {
16528
16794
  root,
@@ -16566,8 +16832,8 @@ function assertWritableDemoRoot(root, reset) {
16566
16832
  if (!existsSync7(root)) {
16567
16833
  return;
16568
16834
  }
16569
- const markerPath = join12(root, markerFile);
16570
- const isDemoRoot = existsSync7(markerPath) && readFileSync9(markerPath, "utf8").trim() === "hello-linzumi";
16835
+ const markerPath = join13(root, markerFile);
16836
+ const isDemoRoot = existsSync7(markerPath) && readFileSync10(markerPath, "utf8").trim() === "hello-linzumi";
16571
16837
  if (isDemoRoot && reset) {
16572
16838
  rmSync2(root, { recursive: true, force: true });
16573
16839
  return;
@@ -16601,8 +16867,8 @@ var init_helloLinzumiProject = __esm({
16601
16867
  defaultHelloLinzumiPort = 8787;
16602
16868
  defaultHelloLinzumiHost = "0.0.0.0";
16603
16869
  markerFile = ".linzumi-demo-project";
16604
- moduleDir = dirname5(fileURLToPath2(import.meta.url));
16605
- linzumiLogoSvg = readFileSync9(join12(moduleDir, "assets", "linzumi-logo.svg"), "utf8");
16870
+ moduleDir = dirname6(fileURLToPath2(import.meta.url));
16871
+ linzumiLogoSvg = readFileSync10(join13(moduleDir, "assets", "linzumi-logo.svg"), "utf8");
16606
16872
  packageJson = `${JSON.stringify(
16607
16873
  {
16608
16874
  name: "hello-linzumi",
@@ -17404,14 +17670,14 @@ import {
17404
17670
  copyFileSync,
17405
17671
  cpSync,
17406
17672
  existsSync as existsSync8,
17407
- mkdirSync as mkdirSync7,
17673
+ mkdirSync as mkdirSync8,
17408
17674
  mkdtempSync,
17409
- readFileSync as readFileSync10,
17675
+ readFileSync as readFileSync11,
17410
17676
  realpathSync as realpathSync4,
17411
- writeFileSync as writeFileSync5
17677
+ writeFileSync as writeFileSync6
17412
17678
  } from "node:fs";
17413
17679
  import { tmpdir } from "node:os";
17414
- import { basename as basename6, delimiter, dirname as dirname6, join as join13 } from "node:path";
17680
+ import { basename as basename6, delimiter, dirname as dirname7, join as join14 } from "node:path";
17415
17681
  function isStartLocalEditorControl(control) {
17416
17682
  return control.type === "start_local_editor";
17417
17683
  }
@@ -17629,24 +17895,24 @@ function codeServerArgs(port, cwd, userDataDir, extensionsDir) {
17629
17895
  }
17630
17896
  function prepareCodeServerProfile(collaboration, editorRuntime) {
17631
17897
  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 });
17898
+ const userDataDir = mkdtempSync(join14(tmpdir(), "kandan-local-editor-"));
17899
+ const extensionsDir = join14(userDataDir, "extensions");
17900
+ const collaborationServerDir = join14(userDataDir, "collaboration-server");
17901
+ const tempDir = join14(userDataDir, "tmp");
17902
+ const userSettingsDir = join14(userDataDir, "User");
17903
+ mkdirSync8(userSettingsDir, { recursive: true });
17904
+ mkdirSync8(extensionsDir, { recursive: true });
17905
+ mkdirSync8(collaborationServerDir, { recursive: true });
17906
+ mkdirSync8(tempDir, { recursive: true });
17641
17907
  if (editorRuntime !== void 0) {
17642
17908
  ensureCodeServerBrowserExtensionAssets(editorRuntime);
17643
17909
  installDirectory(
17644
17910
  editorRuntime.assets.documentStateExtensionDir,
17645
- join13(extensionsDir, "kandan.document-state-telemetry")
17911
+ join14(extensionsDir, "kandan.document-state-telemetry")
17646
17912
  );
17647
17913
  }
17648
- writeFileSync5(
17649
- join13(userSettingsDir, "settings.json"),
17914
+ writeFileSync6(
17915
+ join14(userSettingsDir, "settings.json"),
17650
17916
  JSON.stringify(codeServerSettings(collaboration), null, 2)
17651
17917
  );
17652
17918
  return { ok: true, userDataDir, extensionsDir, collaborationServerDir };
@@ -17658,14 +17924,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17658
17924
  const vscodeRoot = codeServerVscodeRoot(runtime);
17659
17925
  const repairs = [
17660
17926
  {
17661
- source: join13(
17927
+ source: join14(
17662
17928
  vscodeRoot,
17663
17929
  "extensions",
17664
17930
  "git-base",
17665
17931
  "dist",
17666
17932
  "extension.js"
17667
17933
  ),
17668
- target: join13(
17934
+ target: join14(
17669
17935
  vscodeRoot,
17670
17936
  "extensions",
17671
17937
  "git-base",
@@ -17676,14 +17942,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17676
17942
  required: true
17677
17943
  },
17678
17944
  {
17679
- source: join13(
17945
+ source: join14(
17680
17946
  vscodeRoot,
17681
17947
  "extensions",
17682
17948
  "git-base",
17683
17949
  "dist",
17684
17950
  "extension.js.map"
17685
17951
  ),
17686
- target: join13(
17952
+ target: join14(
17687
17953
  vscodeRoot,
17688
17954
  "extensions",
17689
17955
  "git-base",
@@ -17694,14 +17960,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17694
17960
  required: false
17695
17961
  },
17696
17962
  {
17697
- source: join13(
17963
+ source: join14(
17698
17964
  vscodeRoot,
17699
17965
  "extensions",
17700
17966
  "merge-conflict",
17701
17967
  "dist",
17702
17968
  "mergeConflictMain.js"
17703
17969
  ),
17704
- target: join13(
17970
+ target: join14(
17705
17971
  vscodeRoot,
17706
17972
  "extensions",
17707
17973
  "merge-conflict",
@@ -17712,14 +17978,14 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17712
17978
  required: true
17713
17979
  },
17714
17980
  {
17715
- source: join13(
17981
+ source: join14(
17716
17982
  vscodeRoot,
17717
17983
  "extensions",
17718
17984
  "merge-conflict",
17719
17985
  "dist",
17720
17986
  "mergeConflictMain.js.map"
17721
17987
  ),
17722
- target: join13(
17988
+ target: join14(
17723
17989
  vscodeRoot,
17724
17990
  "extensions",
17725
17991
  "merge-conflict",
@@ -17737,7 +18003,7 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17737
18003
  case (!required3 && !existsSync8(source)):
17738
18004
  return;
17739
18005
  default:
17740
- mkdirSync7(dirname6(target), { recursive: true });
18006
+ mkdirSync8(dirname7(target), { recursive: true });
17741
18007
  copyFileSync(source, target);
17742
18008
  return;
17743
18009
  }
@@ -17745,10 +18011,10 @@ function ensureCodeServerBrowserExtensionAssets(runtime) {
17745
18011
  }
17746
18012
  function codeServerVscodeRoot(runtime) {
17747
18013
  const roots = uniquePaths([
17748
- join13(runtime.root, "lib", "vscode"),
17749
- join13(dirname6(dirname6(runtime.codeServerBin)), "lib", "vscode"),
18014
+ join14(runtime.root, "lib", "vscode"),
18015
+ join14(dirname7(dirname7(runtime.codeServerBin)), "lib", "vscode"),
17750
18016
  ...wrappedCodeServerBin(runtime.codeServerBin).map(
17751
- (codeServerBin) => join13(dirname6(dirname6(codeServerBin)), "lib", "vscode")
18017
+ (codeServerBin) => join14(dirname7(dirname7(codeServerBin)), "lib", "vscode")
17752
18018
  )
17753
18019
  ]);
17754
18020
  const rootWithRequiredAssets = roots.find(
@@ -17764,7 +18030,7 @@ function codeServerVscodeRoot(runtime) {
17764
18030
  }
17765
18031
  function wrappedCodeServerBin(codeServerBin) {
17766
18032
  try {
17767
- const script = readFileSync10(codeServerBin, "utf8");
18033
+ const script = readFileSync11(codeServerBin, "utf8");
17768
18034
  const match = script.match(
17769
18035
  /exec\s+(?:"([^"]+)"|'([^']+)'|([^\s]+))\s+"\$@"/u
17770
18036
  );
@@ -17776,8 +18042,8 @@ function wrappedCodeServerBin(codeServerBin) {
17776
18042
  }
17777
18043
  function codeServerBrowserAssetSources(vscodeRoot) {
17778
18044
  return [
17779
- join13(vscodeRoot, "extensions", "git-base", "dist", "extension.js"),
17780
- join13(
18045
+ join14(vscodeRoot, "extensions", "git-base", "dist", "extension.js"),
18046
+ join14(
17781
18047
  vscodeRoot,
17782
18048
  "extensions",
17783
18049
  "merge-conflict",
@@ -17856,10 +18122,10 @@ function prepareLinuxCodeServerLaunch(options) {
17856
18122
  options.cwd,
17857
18123
  "--setenv",
17858
18124
  "XDG_DATA_HOME",
17859
- join13(options.userDataDir, "data"),
18125
+ join14(options.userDataDir, "data"),
17860
18126
  "--setenv",
17861
18127
  "XDG_CONFIG_HOME",
17862
- join13(options.userDataDir, "config"),
18128
+ join14(options.userDataDir, "config"),
17863
18129
  ...readOnlyRoots.flatMap((path2) => ["--ro-bind-try", path2, path2]),
17864
18130
  "--bind",
17865
18131
  options.cwd,
@@ -17900,12 +18166,12 @@ function resolveCodeServerExecutable(command, envPath) {
17900
18166
  if (directory.trim() === "") {
17901
18167
  continue;
17902
18168
  }
17903
- const candidate = join13(directory, command);
18169
+ const candidate = join14(directory, command);
17904
18170
  if (!existsSync8(candidate)) {
17905
18171
  continue;
17906
18172
  }
17907
18173
  const realpath2 = realpathSync4(candidate);
17908
- return { ok: true, command: realpath2, directory: dirname6(realpath2) };
18174
+ return { ok: true, command: realpath2, directory: dirname7(realpath2) };
17909
18175
  }
17910
18176
  return { ok: false };
17911
18177
  }
@@ -17914,10 +18180,10 @@ function hasPathSeparator(path2) {
17914
18180
  }
17915
18181
  function safeRealpathDir(path2) {
17916
18182
  try {
17917
- const directory = dirname6(realpathSync4(path2));
18183
+ const directory = dirname7(realpathSync4(path2));
17918
18184
  return directory === "/" ? void 0 : directory;
17919
18185
  } catch (_error) {
17920
- const directory = dirname6(path2);
18186
+ const directory = dirname7(path2);
17921
18187
  return directory === "." || directory === "/" ? void 0 : directory;
17922
18188
  }
17923
18189
  }
@@ -17986,7 +18252,7 @@ async function startCollaborationSidecar(collaboration, profile, editorRuntime,
17986
18252
  ]);
17987
18253
  const command = nodeRuntimeExecutable();
17988
18254
  const args = [
17989
- join13(
18255
+ join14(
17990
18256
  profile.collaborationServerDir,
17991
18257
  "open-collaboration-server",
17992
18258
  "bundle",
@@ -18081,11 +18347,11 @@ function nodeRuntimeExecutable(env = process.env, execPath = process.execPath) {
18081
18347
  return basename6(execPath).toLowerCase().includes("bun") ? "node" : execPath;
18082
18348
  }
18083
18349
  async function installLocalTarball(archivePath, destinationDir) {
18084
- mkdirSync7(destinationDir, { recursive: true });
18350
+ mkdirSync8(destinationDir, { recursive: true });
18085
18351
  await runProcess("tar", ["-xzf", archivePath, "-C", destinationDir]);
18086
18352
  }
18087
18353
  function installDirectory(sourceDir, destinationDir) {
18088
- mkdirSync7(dirname6(destinationDir), { recursive: true });
18354
+ mkdirSync8(dirname7(destinationDir), { recursive: true });
18089
18355
  cpSync(sourceDir, destinationDir, { recursive: true });
18090
18356
  }
18091
18357
  function codeServerEnv(env, cwd, userDataDir, collaboration) {
@@ -18103,7 +18369,7 @@ function codeServerEnv(env, cwd, userDataDir, collaboration) {
18103
18369
  KANDAN_EDITOR_COLLABORATION_ENTRY_MODE: "kandan_auto_host_or_join",
18104
18370
  KANDAN_EDITOR_COLLABORATION_ROOM_ID: collaboration.roomId,
18105
18371
  KANDAN_EDITOR_COLLABORATION_SERVER_URL: collaboration.bootstrapServerUrl,
18106
- KANDAN_EDITOR_COLLABORATION_AUTO_HOST_CLAIM_PATH: join13(
18372
+ KANDAN_EDITOR_COLLABORATION_AUTO_HOST_CLAIM_PATH: join14(
18107
18373
  userDataDir,
18108
18374
  "kandan-oct-auto-host.lock"
18109
18375
  )
@@ -18307,20 +18573,20 @@ var init_localEditor = __esm({
18307
18573
 
18308
18574
  // src/localEditorRuntime.ts
18309
18575
  import { spawn as spawn5 } from "node:child_process";
18310
- import { createHash as createHash4 } from "node:crypto";
18576
+ import { createHash as createHash5 } from "node:crypto";
18311
18577
  import {
18312
18578
  createReadStream,
18313
18579
  createWriteStream as createWriteStream2,
18314
18580
  existsSync as existsSync9,
18315
- mkdirSync as mkdirSync8,
18581
+ mkdirSync as mkdirSync9,
18316
18582
  mkdtempSync as mkdtempSync2,
18317
- readFileSync as readFileSync11,
18318
- renameSync,
18583
+ readFileSync as readFileSync12,
18584
+ renameSync as renameSync2,
18319
18585
  rmSync as rmSync3,
18320
- writeFileSync as writeFileSync6
18586
+ writeFileSync as writeFileSync7
18321
18587
  } 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";
18588
+ import { homedir as homedir12 } from "node:os";
18589
+ import { dirname as dirname8, join as join15, resolve as resolve7 } from "node:path";
18324
18590
  import { Readable } from "node:stream";
18325
18591
  import { pipeline } from "node:stream/promises";
18326
18592
  async function resolveEditorRuntime(options) {
@@ -18511,14 +18777,14 @@ function normalizeRuntimeAssets(value) {
18511
18777
  }
18512
18778
  function installedRuntime(cacheRoot, manifest) {
18513
18779
  const runtimeRoot = runtimeInstallRoot(cacheRoot, manifest);
18514
- const manifestPath = join14(runtimeRoot, manifest.manifestPath);
18515
- const codeServerBin = join14(runtimeRoot, manifest.codeServerBinPath);
18780
+ const manifestPath = join15(runtimeRoot, manifest.manifestPath);
18781
+ const codeServerBin = join15(runtimeRoot, manifest.codeServerBinPath);
18516
18782
  const assets = verifiedRuntimeAssetPaths(runtimeRoot, manifest);
18517
18783
  if (!existsSync9(manifestPath) || !existsSync9(codeServerBin) || assets === void 0) {
18518
18784
  return { ok: false };
18519
18785
  }
18520
18786
  try {
18521
- const installed = JSON.parse(readFileSync11(manifestPath, "utf8"));
18787
+ const installed = JSON.parse(readFileSync12(manifestPath, "utf8"));
18522
18788
  if (isJsonObject(installed) && installed.version === manifest.version && installed.platform === manifest.platform && (installed.archiveSha256 === void 0 || installed.archiveSha256 === manifest.archiveSha256)) {
18523
18789
  return {
18524
18790
  ok: true,
@@ -18536,10 +18802,10 @@ function installedRuntime(cacheRoot, manifest) {
18536
18802
  return { ok: false };
18537
18803
  }
18538
18804
  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");
18805
+ mkdirSync9(args.cacheRoot, { recursive: true });
18806
+ const tempRoot = mkdtempSync2(join15(args.cacheRoot, ".install-"));
18807
+ const archivePath = join15(tempRoot, "runtime.tar.gz");
18808
+ const extractRoot = join15(tempRoot, "runtime");
18543
18809
  try {
18544
18810
  const downloaded = await downloadArchive({
18545
18811
  kandanUrl: args.kandanUrl,
@@ -18551,7 +18817,7 @@ async function installRuntime(args) {
18551
18817
  if (!downloaded.ok) {
18552
18818
  return downloaded;
18553
18819
  }
18554
- mkdirSync8(extractRoot, { recursive: true });
18820
+ mkdirSync9(extractRoot, { recursive: true });
18555
18821
  if (!await args.extractArchive(archivePath, extractRoot)) {
18556
18822
  return { ok: false, reason: "archive_extract_failed" };
18557
18823
  }
@@ -18564,14 +18830,14 @@ async function installRuntime(args) {
18564
18830
  if (!assetsInstalled) {
18565
18831
  return { ok: false, reason: "install_failed" };
18566
18832
  }
18567
- const manifestPath = join14(extractRoot, args.manifest.manifestPath);
18568
- const codeServerBin = join14(extractRoot, args.manifest.codeServerBinPath);
18833
+ const manifestPath = join15(extractRoot, args.manifest.manifestPath);
18834
+ const codeServerBin = join15(extractRoot, args.manifest.codeServerBinPath);
18569
18835
  const assets = verifiedRuntimeAssetPaths(extractRoot, args.manifest);
18570
18836
  if (!existsSync9(codeServerBin) || assets === void 0) {
18571
18837
  return { ok: false, reason: "invalid_archive" };
18572
18838
  }
18573
- mkdirSync8(dirname7(manifestPath), { recursive: true });
18574
- writeFileSync6(
18839
+ mkdirSync9(dirname8(manifestPath), { recursive: true });
18840
+ writeFileSync7(
18575
18841
  manifestPath,
18576
18842
  JSON.stringify(
18577
18843
  {
@@ -18589,28 +18855,28 @@ async function installRuntime(args) {
18589
18855
  );
18590
18856
  const targetRoot = runtimeInstallRoot(args.cacheRoot, args.manifest);
18591
18857
  rmSync3(targetRoot, { recursive: true, force: true });
18592
- mkdirSync8(dirname7(targetRoot), { recursive: true });
18593
- renameSync(extractRoot, targetRoot);
18858
+ mkdirSync9(dirname8(targetRoot), { recursive: true });
18859
+ renameSync2(extractRoot, targetRoot);
18594
18860
  return {
18595
18861
  ok: true,
18596
18862
  runtime: {
18597
18863
  mode: "server_managed",
18598
18864
  root: targetRoot,
18599
- codeServerBin: join14(targetRoot, args.manifest.codeServerBinPath),
18865
+ codeServerBin: join15(targetRoot, args.manifest.codeServerBinPath),
18600
18866
  assets: {
18601
- collaborationExtensionTarball: join14(
18867
+ collaborationExtensionTarball: join15(
18602
18868
  targetRoot,
18603
18869
  "kandan",
18604
18870
  "editor_extensions",
18605
18871
  "typefox.open-collaboration-tools.tar.gz"
18606
18872
  ),
18607
- collaborationServerTarball: join14(
18873
+ collaborationServerTarball: join15(
18608
18874
  targetRoot,
18609
18875
  "kandan",
18610
18876
  "editor_servers",
18611
18877
  "open-collaboration-server.tar.gz"
18612
18878
  ),
18613
- documentStateExtensionDir: join14(
18879
+ documentStateExtensionDir: join15(
18614
18880
  targetRoot,
18615
18881
  "kandan",
18616
18882
  "editor_extensions",
@@ -18627,7 +18893,7 @@ async function installRuntime(args) {
18627
18893
  }
18628
18894
  async function materializeRuntimeAssets(args) {
18629
18895
  for (const asset of args.manifest.assets) {
18630
- const targetPath = join14(args.runtimeRoot, asset.path);
18896
+ const targetPath = join15(args.runtimeRoot, asset.path);
18631
18897
  try {
18632
18898
  const bytes = await runtimeAssetBytes({
18633
18899
  kandanUrl: args.kandanUrl,
@@ -18637,8 +18903,8 @@ async function materializeRuntimeAssets(args) {
18637
18903
  if (bytes === void 0) {
18638
18904
  continue;
18639
18905
  }
18640
- mkdirSync8(dirname7(targetPath), { recursive: true });
18641
- writeFileSync6(targetPath, bytes);
18906
+ mkdirSync9(dirname8(targetPath), { recursive: true });
18907
+ writeFileSync7(targetPath, bytes);
18642
18908
  } catch (_error) {
18643
18909
  return false;
18644
18910
  }
@@ -18717,7 +18983,7 @@ function extractTarGz(archivePath, destination) {
18717
18983
  }
18718
18984
  function fileSha256(path2) {
18719
18985
  return new Promise((resolveHash, rejectHash) => {
18720
- const hash = createHash4("sha256");
18986
+ const hash = createHash5("sha256");
18721
18987
  const stream = createReadStream(path2);
18722
18988
  stream.on("error", rejectHash);
18723
18989
  stream.on("data", (chunk) => hash.update(chunk));
@@ -18728,19 +18994,19 @@ function runtimeInstallRoot(cacheRoot, manifest) {
18728
18994
  return resolve7(cacheRoot, manifest.platform, manifest.archiveSha256);
18729
18995
  }
18730
18996
  function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18731
- const collaborationExtensionTarball = join14(
18997
+ const collaborationExtensionTarball = join15(
18732
18998
  runtimeRoot,
18733
18999
  "kandan",
18734
19000
  "editor_extensions",
18735
19001
  "typefox.open-collaboration-tools.tar.gz"
18736
19002
  );
18737
- const collaborationServerTarball = join14(
19003
+ const collaborationServerTarball = join15(
18738
19004
  runtimeRoot,
18739
19005
  "kandan",
18740
19006
  "editor_servers",
18741
19007
  "open-collaboration-server.tar.gz"
18742
19008
  );
18743
- const documentStateExtensionDir = join14(
19009
+ const documentStateExtensionDir = join15(
18744
19010
  runtimeRoot,
18745
19011
  "kandan",
18746
19012
  "editor_extensions",
@@ -18749,7 +19015,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18749
19015
  const codeServerRoot = codeServerRuntimeRoot(manifest.codeServerBinPath);
18750
19016
  const requiredPaths = [
18751
19017
  manifest.codeServerBinPath,
18752
- join14(
19018
+ join15(
18753
19019
  codeServerRoot,
18754
19020
  "lib",
18755
19021
  "vscode",
@@ -18759,7 +19025,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18759
19025
  "web",
18760
19026
  "vsda.js"
18761
19027
  ),
18762
- join14(
19028
+ join15(
18763
19029
  codeServerRoot,
18764
19030
  "lib",
18765
19031
  "vscode",
@@ -18780,7 +19046,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18780
19046
  if (expectedSha256 === void 0 && relativePath !== manifest.codeServerBinPath) {
18781
19047
  return void 0;
18782
19048
  }
18783
- const absolutePath = join14(runtimeRoot, relativePath);
19049
+ const absolutePath = join15(runtimeRoot, relativePath);
18784
19050
  if (!existsSync9(absolutePath)) {
18785
19051
  return void 0;
18786
19052
  }
@@ -18799,7 +19065,7 @@ function verifiedRuntimeAssetPaths(runtimeRoot, manifest) {
18799
19065
  }
18800
19066
  function codeServerRuntimeRoot(codeServerBinPath) {
18801
19067
  const normalized = codeServerBinPath.replaceAll("\\", "/");
18802
- return normalized === "bin/code-server" ? "." : normalized.endsWith("/bin/code-server") ? normalized.slice(0, -"/bin/code-server".length) || "." : dirname7(normalized);
19068
+ return normalized === "bin/code-server" ? "." : normalized.endsWith("/bin/code-server") ? normalized.slice(0, -"/bin/code-server".length) || "." : dirname8(normalized);
18803
19069
  }
18804
19070
  function manifestAssetChecksums(assets) {
18805
19071
  const checksums = /* @__PURE__ */ new Map();
@@ -18809,10 +19075,10 @@ function manifestAssetChecksums(assets) {
18809
19075
  return checksums;
18810
19076
  }
18811
19077
  function fileSha256Sync(path2) {
18812
- return createHash4("sha256").update(readFileSync11(path2)).digest("hex");
19078
+ return createHash5("sha256").update(readFileSync12(path2)).digest("hex");
18813
19079
  }
18814
19080
  function defaultEditorRuntimeCacheRoot() {
18815
- return join14(homedir11(), ".linzumi", "editor-runtimes");
19081
+ return join15(homedir12(), ".linzumi", "editor-runtimes");
18816
19082
  }
18817
19083
  function nonEmptyString(value) {
18818
19084
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
@@ -18832,7 +19098,7 @@ var init_localEditorRuntime = __esm({
18832
19098
 
18833
19099
  // src/dependencyStatus.ts
18834
19100
  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";
19101
+ import { delimiter as delimiter2, dirname as dirname9, join as join16 } from "node:path";
18836
19102
  function probeTool(command, cwd) {
18837
19103
  return new Promise((resolve12) => {
18838
19104
  const args = ["--version"];
@@ -18989,8 +19255,8 @@ function voltaCommandCandidates(args) {
18989
19255
  new Set(
18990
19256
  [
18991
19257
  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"),
19258
+ env.VOLTA_HOME === void 0 ? void 0 : join16(env.VOLTA_HOME, "bin", "volta"),
19259
+ env.HOME === void 0 ? void 0 : join16(env.HOME, ".volta", "bin", "volta"),
18994
19260
  ...pathVoltaCandidates(env.PATH)
18995
19261
  ].filter((candidate) => candidate !== void 0)
18996
19262
  )
@@ -18998,10 +19264,10 @@ function voltaCommandCandidates(args) {
18998
19264
  }
18999
19265
  function voltaBinBesideCodexShim(codexBin) {
19000
19266
  const normalizedCodexBin = codexBin.replaceAll("\\", "/");
19001
- return normalizedCodexBin.endsWith("/.volta/bin/codex") ? join15(dirname8(codexBin), "volta") : void 0;
19267
+ return normalizedCodexBin.endsWith("/.volta/bin/codex") ? join16(dirname9(codexBin), "volta") : void 0;
19002
19268
  }
19003
19269
  function pathVoltaCandidates(pathValue) {
19004
- return pathValue === void 0 ? [] : pathValue.split(delimiter2).filter((entry) => entry !== "").map((entry) => join15(entry, "volta"));
19270
+ return pathValue === void 0 ? [] : pathValue.split(delimiter2).filter((entry) => entry !== "").map((entry) => join16(entry, "volta"));
19005
19271
  }
19006
19272
  function codeServerDependencyStatus(args) {
19007
19273
  switch (args.editorRuntime?.status) {
@@ -19110,7 +19376,7 @@ var linzumiCliVersion, linzumiCliVersionText;
19110
19376
  var init_version = __esm({
19111
19377
  "src/version.ts"() {
19112
19378
  "use strict";
19113
- linzumiCliVersion = "0.0.90-beta";
19379
+ linzumiCliVersion = "0.0.92-beta";
19114
19380
  linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
19115
19381
  }
19116
19382
  });
@@ -19119,21 +19385,21 @@ var init_version = __esm({
19119
19385
  import {
19120
19386
  closeSync as closeSync2,
19121
19387
  existsSync as existsSync10,
19122
- mkdirSync as mkdirSync9,
19388
+ mkdirSync as mkdirSync10,
19123
19389
  openSync as openSync3,
19124
- readFileSync as readFileSync12,
19125
- renameSync as renameSync2,
19390
+ readFileSync as readFileSync13,
19391
+ renameSync as renameSync3,
19126
19392
  unlinkSync as unlinkSync2,
19127
- writeFileSync as writeFileSync7,
19393
+ writeFileSync as writeFileSync8,
19128
19394
  writeSync
19129
19395
  } from "node:fs";
19130
- import { dirname as dirname9, join as join16 } from "node:path";
19396
+ import { dirname as dirname10, join as join17 } from "node:path";
19131
19397
  function isRunnerLockHeldError(error) {
19132
19398
  return error instanceof RunnerLockHeldError || error instanceof Error && error.name === runnerLockHeldErrorName && "lockPath" in error && "heldBy" in error;
19133
19399
  }
19134
19400
  function runnerLockPath(machineId, configPath = localConfigPath(), linzumiUrl) {
19135
19401
  const lockName = linzumiUrl === void 0 ? encodeURIComponent(machineId) : localConfigScopeFileStem(linzumiUrl);
19136
- return join16(dirname9(configPath), "runners", `${lockName}.lock`);
19402
+ return join17(dirname10(configPath), "runners", `${lockName}.lock`);
19137
19403
  }
19138
19404
  function acquireRunnerLock(options) {
19139
19405
  const path2 = runnerLockPath(
@@ -19201,9 +19467,9 @@ function stampRunnerLockHeartbeat(path2, record, now) {
19201
19467
  heartbeatAt: now().toISOString()
19202
19468
  };
19203
19469
  const tmpPath = `${path2}.tmp`;
19204
- writeFileSync7(tmpPath, `${JSON.stringify(next, null, 2)}
19470
+ writeFileSync8(tmpPath, `${JSON.stringify(next, null, 2)}
19205
19471
  `, "utf8");
19206
- renameSync2(tmpPath, path2);
19472
+ renameSync3(tmpPath, path2);
19207
19473
  } catch (_error) {
19208
19474
  }
19209
19475
  }
@@ -19313,7 +19579,7 @@ function writeLockOrHandleExisting(path2, record, isPidAlive, now, killPid, onTa
19313
19579
  });
19314
19580
  }
19315
19581
  function tryCreateLock(path2, record) {
19316
- mkdirSync9(dirname9(path2), { recursive: true });
19582
+ mkdirSync10(dirname10(path2), { recursive: true });
19317
19583
  try {
19318
19584
  const fd = openSync3(path2, "wx");
19319
19585
  try {
@@ -19369,7 +19635,7 @@ function withStaleReplacementLock(path2, isPidAlive, callback) {
19369
19635
  function readReplacementLockPidIfPresent(path2) {
19370
19636
  let value;
19371
19637
  try {
19372
- value = readFileSync12(path2, "utf8").trim();
19638
+ value = readFileSync13(path2, "utf8").trim();
19373
19639
  } catch (error) {
19374
19640
  if (isNodeErrorCode2(error, "ENOENT")) {
19375
19641
  return void 0;
@@ -19412,7 +19678,7 @@ function readRunnerLockIfPresent(path2) {
19412
19678
  }
19413
19679
  }
19414
19680
  function readRunnerLock(path2) {
19415
- const parsed = JSON.parse(readFileSync12(path2, "utf8"));
19681
+ const parsed = JSON.parse(readFileSync13(path2, "utf8"));
19416
19682
  if (!isRunnerLockRecord(parsed)) {
19417
19683
  throw new Error(`invalid Linzumi runner lock: ${path2}`);
19418
19684
  }
@@ -21329,8 +21595,8 @@ var init_runnerConsoleReporter = __esm({
21329
21595
  });
21330
21596
 
21331
21597
  // 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";
21598
+ import { mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "node:fs";
21599
+ import { dirname as dirname11, basename as basename7, join as join18 } from "node:path";
21334
21600
  import { randomUUID as randomUUID3 } from "node:crypto";
21335
21601
  function peekFlagValue(args, flags) {
21336
21602
  for (let index = 0; index < args.length; index += 1) {
@@ -21369,12 +21635,12 @@ function telemetryBaseUrl(apiUrl, env = process.env) {
21369
21635
  }
21370
21636
  }
21371
21637
  function telemetryInstallIdPath(env = process.env) {
21372
- return join17(dirname10(localConfigPath(env)), "install-id");
21638
+ return join18(dirname11(localConfigPath(env)), "install-id");
21373
21639
  }
21374
21640
  function ensureTelemetryInstallId(env = process.env) {
21375
21641
  const path2 = telemetryInstallIdPath(env);
21376
21642
  try {
21377
- const existing = readFileSync13(path2, "utf8").trim();
21643
+ const existing = readFileSync14(path2, "utf8").trim();
21378
21644
  if (existing !== "" && existing.length <= 128) {
21379
21645
  return existing;
21380
21646
  }
@@ -21382,8 +21648,8 @@ function ensureTelemetryInstallId(env = process.env) {
21382
21648
  }
21383
21649
  const installId = randomUUID3();
21384
21650
  try {
21385
- mkdirSync10(dirname10(path2), { recursive: true });
21386
- writeFileSync8(path2, `${installId}
21651
+ mkdirSync11(dirname11(path2), { recursive: true });
21652
+ writeFileSync9(path2, `${installId}
21387
21653
  `, { mode: 384 });
21388
21654
  } catch {
21389
21655
  }
@@ -21576,17 +21842,17 @@ var init_linzumiApiClient = __esm({
21576
21842
  });
21577
21843
 
21578
21844
  // 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";
21845
+ import { existsSync as existsSync11, mkdirSync as mkdirSync12, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "node:fs";
21846
+ import { homedir as homedir13 } from "node:os";
21847
+ import { dirname as dirname12, join as join19 } from "node:path";
21582
21848
  function defaultAuthFilePath() {
21583
- return join18(homedir12(), ".linzumi", "auth.json");
21849
+ return join19(homedir13(), ".linzumi", "auth.json");
21584
21850
  }
21585
21851
  function readCachedLocalRunnerToken(kandanUrl, authFilePath = defaultAuthFilePath()) {
21586
21852
  if (!existsSync11(authFilePath)) {
21587
21853
  return void 0;
21588
21854
  }
21589
- const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
21855
+ const authFile = parseAuthFile(readFileSync15(authFilePath, "utf8"));
21590
21856
  const kandanBaseUrl = kandanHttpBaseUrl(kandanUrl);
21591
21857
  const entry = authFile.local_codex_runner?.[kandanBaseUrl];
21592
21858
  if (entry === void 0 || entry.access_token.trim() === "") {
@@ -21608,7 +21874,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
21608
21874
  `missing personal-agent delegation auth file: ${authFilePath}`
21609
21875
  );
21610
21876
  }
21611
- const authFile = parseAuthFile(readFileSync14(authFilePath, "utf8"));
21877
+ const authFile = parseAuthFile(readFileSync15(authFilePath, "utf8"));
21612
21878
  const entry = authFile.personal_agent_delegation;
21613
21879
  if (entry === void 0 || entry.access_token.trim() === "") {
21614
21880
  throw new Error(
@@ -21626,7 +21892,7 @@ function readPersonalAgentDelegationToken(authFilePath) {
21626
21892
  }
21627
21893
  function writeCachedLocalRunnerToken(args) {
21628
21894
  const authFilePath = args.authFilePath ?? defaultAuthFilePath();
21629
- const existing = existsSync11(authFilePath) ? parseAuthFile(readFileSync14(authFilePath, "utf8")) : { version: 1 };
21895
+ const existing = existsSync11(authFilePath) ? parseAuthFile(readFileSync15(authFilePath, "utf8")) : { version: 1 };
21630
21896
  const kandanBaseUrl = kandanHttpBaseUrl(args.kandanUrl);
21631
21897
  const issuedAt = /* @__PURE__ */ new Date();
21632
21898
  const expiresAt = args.expiresInSeconds === void 0 ? void 0 : new Date(
@@ -21644,8 +21910,8 @@ function writeCachedLocalRunnerToken(args) {
21644
21910
  }
21645
21911
  }
21646
21912
  };
21647
- mkdirSync11(dirname11(authFilePath), { recursive: true });
21648
- writeFileSync9(authFilePath, `${JSON.stringify(next, null, 2)}
21913
+ mkdirSync12(dirname12(authFilePath), { recursive: true });
21914
+ writeFileSync10(authFilePath, `${JSON.stringify(next, null, 2)}
21649
21915
  `, "utf8");
21650
21916
  return {
21651
21917
  accessToken: args.accessToken,
@@ -22090,9 +22356,9 @@ var init_threadCodexWorkerIpc = __esm({
22090
22356
 
22091
22357
  // src/signupTaskSuggestions.ts
22092
22358
  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";
22359
+ import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "node:fs";
22094
22360
  import { tmpdir as tmpdir2 } from "node:os";
22095
- import { join as join19 } from "node:path";
22361
+ import { join as join20 } from "node:path";
22096
22362
  async function suggestSignupTasksWithCodex(args) {
22097
22363
  const attempts = 2;
22098
22364
  let previousResponse;
@@ -22114,11 +22380,11 @@ async function suggestSignupTasksWithCodex(args) {
22114
22380
  );
22115
22381
  }
22116
22382
  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");
22383
+ const tempRoot = mkdtempSync3(join20(tmpdir2(), "linzumi-signup-codex-tasks-"));
22384
+ const schemaPath = join20(tempRoot, "task-suggestions.schema.json");
22385
+ const outputPath = join20(tempRoot, "task-suggestions.json");
22120
22386
  const prompt = taskSuggestionPrompt(args.previousResponse);
22121
- writeFileSync10(
22387
+ writeFileSync11(
22122
22388
  schemaPath,
22123
22389
  `${JSON.stringify(taskSuggestionJsonSchema(), null, 2)}
22124
22390
  `,
@@ -22135,7 +22401,7 @@ async function runCodexTaskSuggestion(args) {
22135
22401
  prompt
22136
22402
  })
22137
22403
  );
22138
- return readFileSync15(outputPath, "utf8");
22404
+ return readFileSync16(outputPath, "utf8");
22139
22405
  } finally {
22140
22406
  rmSync4(tempRoot, { recursive: true, force: true });
22141
22407
  }
@@ -22308,7 +22574,7 @@ var init_signupTaskSuggestions = __esm({
22308
22574
  // src/remoteCodexSandboxRunner.ts
22309
22575
  import { spawn as spawn8 } from "node:child_process";
22310
22576
  import { existsSync as existsSync12, realpathSync as realpathSync5 } from "node:fs";
22311
- import { dirname as dirname12, isAbsolute as isAbsolute4 } from "node:path";
22577
+ import { dirname as dirname13, isAbsolute as isAbsolute4 } from "node:path";
22312
22578
  function createConfiguredRemoteCodexSandboxRunner(args) {
22313
22579
  const kind = normalizedSandboxKind(args.env.LINZUMI_REMOTE_CODEX_SANDBOX);
22314
22580
  if (kind === void 0) {
@@ -22423,8 +22689,8 @@ function bubblewrapArgs(sandboxBin, request, exists) {
22423
22689
  ]);
22424
22690
  const readOnlyBindArgs = uniqueStrings3([
22425
22691
  ...linuxReadOnlyRoots,
22426
- ...isAbsolute4(request.command) ? [dirname12(request.command)] : [],
22427
- dirname12(sandboxBin)
22692
+ ...isAbsolute4(request.command) ? [dirname13(request.command)] : [],
22693
+ dirname13(sandboxBin)
22428
22694
  ]).flatMap((path2) => exists(path2) ? ["--ro-bind", path2, path2] : []);
22429
22695
  const cwdParentDirs = parentDirs(request.cwd).flatMap((path2) => [
22430
22696
  "--dir",
@@ -22457,7 +22723,7 @@ function bubblewrapArgs(sandboxBin, request, exists) {
22457
22723
  function macosSeatbeltProfile(request, exists) {
22458
22724
  const readableRoots = uniqueStrings3([
22459
22725
  ...macosReadOnlyRoots,
22460
- ...isAbsolute4(request.command) ? [dirname12(request.command)] : []
22726
+ ...isAbsolute4(request.command) ? [dirname13(request.command)] : []
22461
22727
  ]).filter(exists);
22462
22728
  const readableRules = readableRoots.map((path2) => `(allow file-read* (subpath ${sandboxString(path2)}))`).join("\n");
22463
22729
  const writableTempRules = macosWritableTempRoots.filter(exists).flatMap((path2) => [
@@ -22580,31 +22846,31 @@ var init_remoteCodexSandboxRunner = __esm({
22580
22846
 
22581
22847
  // src/runner.ts
22582
22848
  import { spawn as spawn9, spawnSync as spawnSync5 } from "node:child_process";
22583
- import { createHash as createHash5, randomUUID as randomUUID4 } from "node:crypto";
22849
+ import { createHash as createHash6, randomUUID as randomUUID4 } from "node:crypto";
22584
22850
  import {
22585
22851
  chmodSync as chmodSync2,
22586
22852
  existsSync as existsSync13,
22587
22853
  lstatSync,
22588
- mkdirSync as mkdirSync12,
22854
+ mkdirSync as mkdirSync13,
22589
22855
  mkdtempSync as mkdtempSync4,
22590
22856
  readdirSync as readdirSync4,
22591
- readFileSync as readFileSync16,
22857
+ readFileSync as readFileSync17,
22592
22858
  realpathSync as realpathSync6,
22593
- renameSync as renameSync3,
22859
+ renameSync as renameSync4,
22594
22860
  rmSync as rmSync5,
22595
22861
  statSync as statSync3,
22596
- writeFileSync as writeFileSync11
22862
+ writeFileSync as writeFileSync12
22597
22863
  } from "node:fs";
22598
22864
  import { readFile as readFile2 } from "node:fs/promises";
22599
22865
  import { createServer as createServer3 } from "node:http";
22600
- import { homedir as homedir13, hostname as hostname2, tmpdir as tmpdir3 } from "node:os";
22866
+ import { homedir as homedir14, hostname as hostname2, tmpdir as tmpdir3 } from "node:os";
22601
22867
  import { createInterface } from "node:readline";
22602
22868
  import {
22603
22869
  basename as basename8,
22604
- dirname as dirname13,
22870
+ dirname as dirname14,
22605
22871
  extname as extname2,
22606
22872
  isAbsolute as isAbsolute5,
22607
- join as join20,
22873
+ join as join21,
22608
22874
  resolve as resolve8
22609
22875
  } from "node:path";
22610
22876
  async function runLocalCodexRunner(options) {
@@ -22883,6 +23149,10 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
22883
23149
  { discardSeqsOnFirstEpochAdoption: true }
22884
23150
  );
22885
23151
  cleanup.actions.push(() => appliedStartTurnStore.flush());
23152
+ const threadSessionRegistry = createRunnerThreadSessionRegistryStore(
23153
+ runnerThreadSessionRegistryPath(options.runnerId),
23154
+ log2
23155
+ );
22886
23156
  const controlEpochStore = createRunnerControlEpochStore(
22887
23157
  controlCursorStore,
22888
23158
  appliedStartTurnStore,
@@ -23765,6 +24035,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23765
24035
  kandan.onReconnect(() => channelSession.handleKandanReconnect());
23766
24036
  }
23767
24037
  const dynamicChannelSessions = /* @__PURE__ */ new Map();
24038
+ const dynamicChannelSessionAttachInFlight = /* @__PURE__ */ new Map();
23768
24039
  const dynamicChannelSessionCodexClients = /* @__PURE__ */ new Map();
23769
24040
  const codexTurnFailureGuards = /* @__PURE__ */ new Map();
23770
24041
  const lossReportPushes = [];
@@ -23886,90 +24157,120 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23886
24157
  if (existingSession !== void 0) {
23887
24158
  return existingSession;
23888
24159
  }
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
- );
24160
+ const alreadyAttaching = dynamicChannelSessionAttachInFlight.get(codexThreadId);
24161
+ if (alreadyAttaching !== void 0) {
24162
+ return await alreadyAttaching;
23894
24163
  }
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();
24164
+ const attachPromise = (async () => {
24165
+ const listenUser = options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
24166
+ if (listenUser === void 0) {
24167
+ throw new Error(
24168
+ "missing listen user for Commander-started Codex session"
24169
+ );
24170
+ }
24171
+ const runtimeSettings = startInstanceRuntimeSettings(options, control);
24172
+ const session = await attachChannelSession({
24173
+ kandan,
24174
+ codex: sessionCodex,
24175
+ topic,
24176
+ instanceId,
24177
+ options: {
24178
+ kandanUrl: options.kandanUrl,
24179
+ token: options.token,
24180
+ runnerId: options.runnerId,
24181
+ cwd,
24182
+ codexBin: options.codexBin,
24183
+ fetch: options.fetch,
24184
+ fast: control.fast ?? options.fast,
24185
+ launchTui: false,
24186
+ pipelinePersistDir: commanderOutboxPersistDir(),
24187
+ enablePortForwardWatch: true,
24188
+ initialForwardPorts: allowedForwardPorts,
24189
+ portForwardWatcher: channelSessionPortForwardWatcherOptions({
24190
+ rootPid: portForwardWatcherRootPid,
24191
+ start: options.portForwardWatcher,
24192
+ commanderBoundPids: args.commanderBoundPids,
24193
+ commanderBoundPorts: args.commanderBoundPorts
24194
+ }),
24195
+ suppressedForwardPorts,
24196
+ onForwardPortApproved: (port, attribution) => {
24197
+ liveForwardPorts.add(port);
24198
+ setForwardPortAttribution(port, {
24199
+ ...attribution,
24200
+ agentProvider: "codex"
24201
+ });
24202
+ return capabilitiesPayload();
24203
+ },
24204
+ onForwardPortRevoked: (port) => {
24205
+ liveForwardPorts.delete(port);
24206
+ clearForwardPortAttribution(port);
24207
+ return capabilitiesPayload();
24208
+ },
24209
+ channelSession: {
24210
+ workspaceSlug,
24211
+ channelSlug,
24212
+ kandanThreadId,
24213
+ rootSeq: integerValue(control.rootSeq),
24214
+ codexThreadId,
24215
+ linzumiContext: control.linzumiContext,
24216
+ listenUser,
24217
+ model: runtimeSettings.model,
24218
+ reasoningEffort: runtimeSettings.reasoningEffort,
24219
+ sandbox: runtimeSettings.sandbox,
24220
+ approvalPolicy: runtimeSettings.approvalPolicy,
24221
+ allowPortForwardingByDefault: runtimeSettings.allowPortForwardingByDefault
24222
+ }
23932
24223
  },
23933
- channelSession: {
24224
+ log: log2
24225
+ });
24226
+ dynamicChannelSessions.set(codexThreadId, session);
24227
+ dynamicChannelSessionCodexClients.set(codexThreadId, sessionCodex);
24228
+ threadSessionRegistry.upsert({
24229
+ workspace: workspaceSlug,
24230
+ channel: channelSlug,
24231
+ kandanThreadId,
24232
+ codexThreadId,
24233
+ cwd,
24234
+ agentProvider: "codex",
24235
+ control: rehydrationControlSnapshot({
23934
24236
  workspaceSlug,
23935
24237
  channelSlug,
23936
24238
  kandanThreadId,
23937
- rootSeq: integerValue(control.rootSeq),
23938
24239
  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
- );
24240
+ cwd,
24241
+ rootSeq: integerValue(control.rootSeq),
24242
+ runtimeSettings
24243
+ }),
24244
+ updatedAtMs: Date.now()
23970
24245
  });
24246
+ if (sessionCodex !== codex) {
24247
+ sessionCodex.onNotification((notification) => {
24248
+ seq.value += 1;
24249
+ const params = notification.params ?? {};
24250
+ log2(
24251
+ "codex.notification",
24252
+ codexNotificationConsoleLogPayload(notification.method, params)
24253
+ );
24254
+ codexTurnFailureGuardFor(sessionCodex).observeNotification(
24255
+ notification.method,
24256
+ params
24257
+ );
24258
+ dispatchCodexNotificationToSession(
24259
+ session,
24260
+ notification.method,
24261
+ params,
24262
+ log2
24263
+ );
24264
+ });
24265
+ }
24266
+ return session;
24267
+ })();
24268
+ dynamicChannelSessionAttachInFlight.set(codexThreadId, attachPromise);
24269
+ try {
24270
+ return await attachPromise;
24271
+ } finally {
24272
+ dynamicChannelSessionAttachInFlight.delete(codexThreadId);
23971
24273
  }
23972
- return session;
23973
24274
  };
23974
24275
  const attachThreadSession = async (control, cwd, codexThreadId) => {
23975
24276
  return await attachThreadSessionWithCodex({
@@ -23980,6 +24281,69 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
23980
24281
  portForwardWatcherRootPid: started?.process.pid
23981
24282
  });
23982
24283
  };
24284
+ const rehydrateThreadSessionsOnBoot = async () => {
24285
+ const records = threadSessionRegistry.list();
24286
+ if (records.length === 0) {
24287
+ return;
24288
+ }
24289
+ const summary = await rehydrateThreadSessions({
24290
+ records,
24291
+ nowMs: Date.now(),
24292
+ maxAgeMs: defaultThreadSessionRehydrationMaxAgeMs,
24293
+ pendingDurableRowCount: (record) => recoverOutboxJournal(
24294
+ outboxJournalPath(
24295
+ commanderOutboxPersistDir(),
24296
+ channelSessionPipelineThreadKey(
24297
+ { workspaceSlug: record.workspace, channelSlug: record.channel },
24298
+ record.kandanThreadId,
24299
+ instanceId
24300
+ )
24301
+ ),
24302
+ log2
24303
+ ).pendingEntries.length,
24304
+ attach: async (record) => {
24305
+ if (cleanup.closePromise !== void 0) {
24306
+ log2("session_registry.rehydrate_aborted_shutdown", {
24307
+ thread_id: record.kandanThreadId
24308
+ });
24309
+ return "failed";
24310
+ }
24311
+ const cwd = resolveAllowedCwd(record.cwd, allowedCwds.value);
24312
+ if (!cwd.ok) {
24313
+ log2("session_registry.rehydrate_cwd_rejected", {
24314
+ thread_id: record.kandanThreadId,
24315
+ cwd: record.cwd,
24316
+ reason: cwd.reason
24317
+ });
24318
+ return "retire";
24319
+ }
24320
+ const session = await attachThreadSession(
24321
+ rehydrationReconnectControl(record),
24322
+ cwd.cwd,
24323
+ record.codexThreadId
24324
+ );
24325
+ return session !== void 0 ? "attached" : "failed";
24326
+ },
24327
+ retire: (record) => threadSessionRegistry.remove(record.kandanThreadId),
24328
+ log: log2
24329
+ });
24330
+ log2("session_registry.rehydrate_complete", {
24331
+ records: records.length,
24332
+ rehydrated: summary.rehydrated,
24333
+ retired_drained: summary.retiredDrained,
24334
+ retired_stale: summary.retiredStale,
24335
+ retired_unattachable: summary.retiredUnattachable,
24336
+ failed: summary.failed
24337
+ });
24338
+ };
24339
+ const threadSessionRehydration = rehydrateThreadSessionsOnBoot().catch(
24340
+ (error) => {
24341
+ log2("session_registry.rehydrate_failed", {
24342
+ message: error instanceof Error ? error.message : String(error)
24343
+ });
24344
+ }
24345
+ );
24346
+ cleanup.actions.push(() => threadSessionRehydration);
23983
24347
  const startThreadRunnerProcess = async (control, cwd) => {
23984
24348
  if (options.threadProcess?.role === "thread") {
23985
24349
  return void 0;
@@ -24644,14 +25008,14 @@ function commanderOutboxPersistDir() {
24644
25008
  if (override !== void 0 && override !== "") {
24645
25009
  return override;
24646
25010
  }
24647
- return join20(homedir13(), ".linzumi", "commander-outbox");
25011
+ return join21(homedir14(), ".linzumi", "commander-outbox");
24648
25012
  }
24649
25013
  function controlCursorStorePath(runnerId) {
24650
25014
  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);
25015
+ const digest = createHash6("sha256").update(runnerId).digest("hex").slice(0, 8);
24652
25016
  const stem = sanitized === "" ? "runner" : sanitized;
24653
- return join20(
24654
- homedir13(),
25017
+ return join21(
25018
+ homedir14(),
24655
25019
  ".linzumi",
24656
25020
  "control-cursors",
24657
25021
  `${stem}.${digest}.json`
@@ -24659,10 +25023,10 @@ function controlCursorStorePath(runnerId) {
24659
25023
  }
24660
25024
  function appliedStartTurnStorePath(runnerId) {
24661
25025
  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);
25026
+ const digest = createHash6("sha256").update(runnerId).digest("hex").slice(0, 8);
24663
25027
  const stem = sanitized === "" ? "runner" : sanitized;
24664
- return join20(
24665
- homedir13(),
25028
+ return join21(
25029
+ homedir14(),
24666
25030
  ".linzumi",
24667
25031
  "control-cursors",
24668
25032
  `${stem}.${digest}.start-turn.json`
@@ -24784,9 +25148,9 @@ function createControlCursorFileStore(path2, log2, options) {
24784
25148
  }
24785
25149
  dirty = false;
24786
25150
  try {
24787
- mkdirSync12(dirname13(path2), { recursive: true });
25151
+ mkdirSync13(dirname14(path2), { recursive: true });
24788
25152
  const tmpPath = `${path2}.tmp`;
24789
- writeFileSync11(
25153
+ writeFileSync12(
24790
25154
  tmpPath,
24791
25155
  `${JSON.stringify({
24792
25156
  ...epoch === void 0 ? {} : { [controlCursorEpochKey]: epoch },
@@ -24795,7 +25159,7 @@ function createControlCursorFileStore(path2, log2, options) {
24795
25159
  `,
24796
25160
  "utf8"
24797
25161
  );
24798
- renameSync3(tmpPath, path2);
25162
+ renameSync4(tmpPath, path2);
24799
25163
  } catch (error) {
24800
25164
  log2("control_cursor_store.write_failed", {
24801
25165
  path: path2,
@@ -24894,7 +25258,7 @@ function readControlCursorFile(path2, log2) {
24894
25258
  const cursors = /* @__PURE__ */ new Map();
24895
25259
  let raw;
24896
25260
  try {
24897
- raw = readFileSync16(path2, "utf8");
25261
+ raw = readFileSync17(path2, "utf8");
24898
25262
  } catch (error) {
24899
25263
  if (!isErrnoCode2(error, "ENOENT")) {
24900
25264
  log2("control_cursor_store.read_failed", {
@@ -27188,7 +27552,7 @@ async function startClaudeCodeProviderInstance(args) {
27188
27552
  log: args.log
27189
27553
  });
27190
27554
  const liveBashCapture = args.options.claudeCodeRunner === void 0 && claudeLiveBashCaptureEnabled(process.env) ? createClaudeCodeLiveBashCapture({
27191
- captureDir: join20(
27555
+ captureDir: join21(
27192
27556
  tmpdir3(),
27193
27557
  `linzumi-claude-live-bash-${args.instanceId}`
27194
27558
  ),
@@ -28020,6 +28384,48 @@ function startInstanceRuntimeSettings(options, control) {
28020
28384
  allowPortForwardingByDefault: true
28021
28385
  };
28022
28386
  }
28387
+ function rehydrationControlSnapshot(args) {
28388
+ const { runtimeSettings } = args;
28389
+ return {
28390
+ type: "reconnect_thread",
28391
+ workspace: args.workspaceSlug,
28392
+ channel: args.channelSlug,
28393
+ threadId: args.kandanThreadId,
28394
+ codexThreadId: args.codexThreadId,
28395
+ cwd: args.cwd,
28396
+ agentProvider: "codex",
28397
+ ...args.rootSeq === void 0 ? {} : { rootSeq: args.rootSeq },
28398
+ ...runtimeSettings.model === void 0 ? {} : { model: runtimeSettings.model },
28399
+ ...runtimeSettings.reasoningEffort === void 0 ? {} : { reasoningEffort: runtimeSettings.reasoningEffort },
28400
+ ...runtimeSettings.sandbox === void 0 ? {} : { sandbox: runtimeSettings.sandbox },
28401
+ ...runtimeSettings.approvalPolicy === void 0 ? {} : { approvalPolicy: runtimeSettings.approvalPolicy },
28402
+ ...runtimeSettings.fast === void 0 ? {} : { fast: runtimeSettings.fast }
28403
+ };
28404
+ }
28405
+ function rehydrationReconnectControl(record) {
28406
+ const snapshot = record.control;
28407
+ const rootSeq = integerValue(snapshot.rootSeq);
28408
+ const model = stringValue(snapshot.model);
28409
+ const reasoningEffort = stringValue(snapshot.reasoningEffort);
28410
+ const sandbox = stringValue(snapshot.sandbox);
28411
+ const approvalPolicy = stringValue(snapshot.approvalPolicy);
28412
+ const fast = typeof snapshot.fast === "boolean" ? snapshot.fast : void 0;
28413
+ return {
28414
+ type: "reconnect_thread",
28415
+ workspace: record.workspace,
28416
+ channel: record.channel,
28417
+ threadId: record.kandanThreadId,
28418
+ codexThreadId: record.codexThreadId,
28419
+ cwd: record.cwd,
28420
+ agentProvider: "codex",
28421
+ ...rootSeq === void 0 ? {} : { rootSeq },
28422
+ ...model === void 0 ? {} : { model },
28423
+ ...reasoningEffort === void 0 ? {} : { reasoningEffort },
28424
+ ...sandbox === void 0 ? {} : { sandbox },
28425
+ ...approvalPolicy === void 0 ? {} : { approvalPolicy },
28426
+ ...fast === void 0 ? {} : { fast }
28427
+ };
28428
+ }
28023
28429
  function channelSessionPortForwardWatcherOptions(args) {
28024
28430
  if (args.rootPid === void 0 && args.start === void 0) {
28025
28431
  return void 0;
@@ -28993,8 +29399,8 @@ function onboardingConversationOfficeImport(response) {
28993
29399
  return objectValue(metadata?.office_channel_import);
28994
29400
  }
28995
29401
  function onboardingConversationImportClientMessageId(importKey, itemKey) {
28996
- const importHash = createHash5("sha256").update(importKey).digest("hex");
28997
- const itemHash = createHash5("sha256").update(itemKey).digest("hex");
29402
+ const importHash = createHash6("sha256").update(importKey).digest("hex");
29403
+ const itemHash = createHash6("sha256").update(itemKey).digest("hex");
28998
29404
  return `onboarding-import:${importHash.slice(0, 32)}:${itemHash.slice(0, 24)}`;
28999
29405
  }
29000
29406
  async function uploadLocalConversationAttachments(args) {
@@ -29092,7 +29498,7 @@ async function localConversationAttachmentFile(candidatePath, attachment) {
29092
29498
  };
29093
29499
  }
29094
29500
  case "path": {
29095
- const path2 = isAbsolute5(attachment.path) ? attachment.path : resolve8(dirname13(candidatePath), attachment.path);
29501
+ const path2 = isAbsolute5(attachment.path) ? attachment.path : resolve8(dirname14(candidatePath), attachment.path);
29096
29502
  try {
29097
29503
  const bytes = await readFile2(path2);
29098
29504
  return {
@@ -29482,9 +29888,9 @@ function mcpOwnerUsername(options) {
29482
29888
  return options.channelSession?.listenUser ?? identityFromAccessToken(options.token).actorUsername;
29483
29889
  }
29484
29890
  function writeEphemeralMcpAuthFile(options) {
29485
- const directory = mkdtempSync4(join20(tmpdir3(), "linzumi-mcp-auth-"));
29891
+ const directory = mkdtempSync4(join21(tmpdir3(), "linzumi-mcp-auth-"));
29486
29892
  chmodSync2(directory, 448);
29487
- const path2 = join20(directory, "auth.json");
29893
+ const path2 = join21(directory, "auth.json");
29488
29894
  writeCachedLocalRunnerToken({
29489
29895
  kandanUrl: options.kandanUrl,
29490
29896
  accessToken: options.token,
@@ -29560,7 +29966,7 @@ function configuredAllowedCwds(values, options = {}) {
29560
29966
  const absolutePath = resolve8(expandUserPath(value));
29561
29967
  try {
29562
29968
  if (options.createMissing === true) {
29563
- mkdirSync12(absolutePath, { recursive: true });
29969
+ mkdirSync13(absolutePath, { recursive: true });
29564
29970
  }
29565
29971
  const realPath = realpathSync6(absolutePath);
29566
29972
  allowedCwds.push(
@@ -29597,7 +30003,7 @@ function allowedCwdProjects(allowedCwds) {
29597
30003
  });
29598
30004
  }
29599
30005
  function isGitProjectDirectory(cwd) {
29600
- const gitPath = join20(cwd, ".git");
30006
+ const gitPath = join21(cwd, ".git");
29601
30007
  try {
29602
30008
  const gitPathStats = statSync3(gitPath);
29603
30009
  return gitPathStats.isDirectory() || gitPathStats.isFile();
@@ -29620,9 +30026,9 @@ function browseRunnerDirectory(control, options) {
29620
30026
  error: "not_directory"
29621
30027
  };
29622
30028
  }
29623
- const parent = dirname13(currentPath);
30029
+ const parent = dirname14(currentPath);
29624
30030
  const entries = readdirSync4(currentPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).filter((entry) => visibleRunnerDirectoryEntryName(entry.name)).map((entry) => {
29625
- const path2 = join20(currentPath, entry.name);
30031
+ const path2 = join21(currentPath, entry.name);
29626
30032
  return {
29627
30033
  name: entry.name,
29628
30034
  path: path2,
@@ -29663,7 +30069,7 @@ function projectDirectoryName(name) {
29663
30069
  function availableProjectDirectoryName(projectsRoot, baseName, suffix = 0) {
29664
30070
  for (let nextSuffix = suffix; ; nextSuffix += 1) {
29665
30071
  const candidate = nextSuffix === 0 ? baseName : `${baseName}-${nextSuffix}`;
29666
- if (!projectPathExists(join20(projectsRoot, candidate))) {
30072
+ if (!projectPathExists(join21(projectsRoot, candidate))) {
29667
30073
  return candidate;
29668
30074
  }
29669
30075
  }
@@ -29691,9 +30097,9 @@ function createRunnerProject(control, options, allowedCwds) {
29691
30097
  error: "invalid_project_template"
29692
30098
  };
29693
30099
  }
29694
- const projectsRoot = join20(currentHomeDirectory(), "linzumi");
30100
+ const projectsRoot = join21(currentHomeDirectory(), "linzumi");
29695
30101
  const resolvedProjectDirName = template === "hello_linzumi_demo" ? availableProjectDirectoryName(projectsRoot, projectDirName) : projectDirName;
29696
- const projectPath = join20(projectsRoot, resolvedProjectDirName);
30102
+ const projectPath = join21(projectsRoot, resolvedProjectDirName);
29697
30103
  let createdProjectPath = false;
29698
30104
  try {
29699
30105
  if (template !== "hello_linzumi_demo" && projectPathExists(projectPath)) {
@@ -29705,7 +30111,7 @@ function createRunnerProject(control, options, allowedCwds) {
29705
30111
  error: "project_directory_exists"
29706
30112
  };
29707
30113
  }
29708
- mkdirSync12(projectsRoot, { recursive: true });
30114
+ mkdirSync13(projectsRoot, { recursive: true });
29709
30115
  if (template === "hello_linzumi_demo") {
29710
30116
  createdProjectPath = true;
29711
30117
  createHelloLinzumiProject({
@@ -29713,7 +30119,7 @@ function createRunnerProject(control, options, allowedCwds) {
29713
30119
  name: resolvedProjectDirName
29714
30120
  });
29715
30121
  } else {
29716
- mkdirSync12(projectPath, { recursive: false });
30122
+ mkdirSync13(projectPath, { recursive: false });
29717
30123
  createdProjectPath = true;
29718
30124
  }
29719
30125
  const git = spawnSync5("git", ["init"], {
@@ -29831,6 +30237,8 @@ var init_runner = __esm({
29831
30237
  "src/runner.ts"() {
29832
30238
  "use strict";
29833
30239
  init_channelSession();
30240
+ init_runnerThreadSessionRegistry();
30241
+ init_outboxJournal();
29834
30242
  init_channelSessionSupport();
29835
30243
  init_commanderAttachments();
29836
30244
  init_claudeCodePipeline();
@@ -29901,7 +30309,7 @@ var init_runner = __esm({
29901
30309
  });
29902
30310
 
29903
30311
  // src/kandanTls.ts
29904
- import { existsSync as existsSync14, readFileSync as readFileSync17 } from "node:fs";
30312
+ import { existsSync as existsSync14, readFileSync as readFileSync18 } from "node:fs";
29905
30313
  import { Agent } from "undici";
29906
30314
  import WsWebSocket from "ws";
29907
30315
  function kandanTlsTrustFromEnv() {
@@ -29915,7 +30323,7 @@ function kandanTlsTrustFromCaFile(caFile) {
29915
30323
  if (!existsSync14(trimmed)) {
29916
30324
  throw new Error(`KANDAN_TLS_CA_FILE does not exist: ${trimmed}`);
29917
30325
  }
29918
- const ca = readFileSync17(trimmed, "utf8");
30326
+ const ca = readFileSync18(trimmed, "utf8");
29919
30327
  return {
29920
30328
  caFile: trimmed,
29921
30329
  ca,
@@ -48699,7 +49107,7 @@ var init_RemoveFileError = __esm({
48699
49107
 
48700
49108
  // ../../node_modules/@inquirer/external-editor/dist/esm/index.js
48701
49109
  import { spawn as spawn11, spawnSync as spawnSync6 } from "child_process";
48702
- import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync14 } from "fs";
49110
+ import { readFileSync as readFileSync21, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "fs";
48703
49111
  import path from "node:path";
48704
49112
  import os from "node:os";
48705
49113
  import { randomUUID as randomUUID5 } from "node:crypto";
@@ -48816,14 +49224,14 @@ var init_esm5 = __esm({
48816
49224
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
48817
49225
  opt.mode = this.fileOptions.mode;
48818
49226
  }
48819
- writeFileSync14(this.tempFile, this.text, opt);
49227
+ writeFileSync15(this.tempFile, this.text, opt);
48820
49228
  } catch (createFileError) {
48821
49229
  throw new CreateFileError(createFileError);
48822
49230
  }
48823
49231
  }
48824
49232
  readTemporaryFile() {
48825
49233
  try {
48826
- const tempFileBuffer = readFileSync20(this.tempFile);
49234
+ const tempFileBuffer = readFileSync21(this.tempFile);
48827
49235
  if (tempFileBuffer.length === 0) {
48828
49236
  this.text = "";
48829
49237
  } else {
@@ -50192,17 +50600,17 @@ import { spawn as spawn12, spawnSync as spawnSync7 } from "node:child_process";
50192
50600
  import {
50193
50601
  existsSync as existsSync17,
50194
50602
  constants as fsConstants,
50195
- mkdirSync as mkdirSync15,
50196
- mkdtempSync as mkdtempSync5,
50197
- readFileSync as readFileSync21,
50603
+ mkdirSync as mkdirSync16,
50604
+ mkdtempSync as mkdtempSync6,
50605
+ readFileSync as readFileSync22,
50198
50606
  readdirSync as readdirSync5,
50199
- rmSync as rmSync6,
50607
+ rmSync as rmSync7,
50200
50608
  statSync as statSync4,
50201
- writeFileSync as writeFileSync15
50609
+ writeFileSync as writeFileSync16
50202
50610
  } from "node:fs";
50203
50611
  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";
50612
+ import { homedir as homedir17, tmpdir as tmpdir5 } from "node:os";
50613
+ import { delimiter as delimiter3, dirname as dirname18, join as join25, resolve as resolve10 } from "node:path";
50206
50614
  import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
50207
50615
  import { emitKeypressEvents } from "node:readline";
50208
50616
  function signupHelpText() {
@@ -50323,7 +50731,7 @@ function defaultSignupDraftStore(serviceUrl) {
50323
50731
  }
50324
50732
  let parsed;
50325
50733
  try {
50326
- parsed = JSON.parse(readFileSync21(path2, "utf8"));
50734
+ parsed = JSON.parse(readFileSync22(path2, "utf8"));
50327
50735
  } catch (_error) {
50328
50736
  return void 0;
50329
50737
  }
@@ -50333,21 +50741,21 @@ function defaultSignupDraftStore(serviceUrl) {
50333
50741
  return comparableServiceUrl(parsed.serviceUrl) === comparableServiceUrl(serviceUrl) ? parsed : void 0;
50334
50742
  },
50335
50743
  write: (draft) => {
50336
- mkdirSync15(dirname16(path2), { recursive: true });
50337
- writeFileSync15(path2, `${JSON.stringify(draft, null, 2)}
50744
+ mkdirSync16(dirname18(path2), { recursive: true });
50745
+ writeFileSync16(path2, `${JSON.stringify(draft, null, 2)}
50338
50746
  `, {
50339
50747
  encoding: "utf8",
50340
50748
  mode: 384
50341
50749
  });
50342
50750
  },
50343
50751
  clear: () => {
50344
- rmSync6(path2, { force: true });
50752
+ rmSync7(path2, { force: true });
50345
50753
  }
50346
50754
  };
50347
50755
  }
50348
50756
  function defaultSignupDraftPath(serviceUrl) {
50349
- return join23(
50350
- dirname16(localConfigPath()),
50757
+ return join25(
50758
+ dirname18(localConfigPath()),
50351
50759
  `signup-draft.${localConfigScopeFileStem(serviceUrl)}.json`
50352
50760
  );
50353
50761
  }
@@ -50381,8 +50789,8 @@ function defaultSignupTaskCacheStore(serviceUrl) {
50381
50789
  }
50382
50790
  }
50383
50791
  };
50384
- mkdirSync15(dirname16(path2), { recursive: true });
50385
- writeFileSync15(path2, `${JSON.stringify(next, null, 2)}
50792
+ mkdirSync16(dirname18(path2), { recursive: true });
50793
+ writeFileSync16(path2, `${JSON.stringify(next, null, 2)}
50386
50794
  `, {
50387
50795
  encoding: "utf8",
50388
50796
  mode: 384
@@ -50391,8 +50799,8 @@ function defaultSignupTaskCacheStore(serviceUrl) {
50391
50799
  };
50392
50800
  }
50393
50801
  function defaultSignupTaskCachePath(serviceUrl) {
50394
- return join23(
50395
- dirname16(localConfigPath()),
50802
+ return join25(
50803
+ dirname18(localConfigPath()),
50396
50804
  `signup-task-cache.${localConfigScopeFileStem(serviceUrl)}.json`
50397
50805
  );
50398
50806
  }
@@ -50402,7 +50810,7 @@ function readSignupTaskCache(path2) {
50402
50810
  }
50403
50811
  let parsed;
50404
50812
  try {
50405
- parsed = JSON.parse(readFileSync21(path2, "utf8"));
50813
+ parsed = JSON.parse(readFileSync22(path2, "utf8"));
50406
50814
  } catch (_error) {
50407
50815
  return { version: 1, entries: {} };
50408
50816
  }
@@ -52287,7 +52695,7 @@ function autocompletePathSuggestions(pathInput) {
52287
52695
  try {
52288
52696
  const showHidden = prefix.startsWith(".");
52289
52697
  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) => ({
52698
+ 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
52699
  path: path2,
52292
52700
  score: fuzzyPathSegmentScore(path2.split("/").at(-1) ?? path2, prefix)
52293
52701
  })).filter((candidate) => candidate.score !== void 0).sort((left, right) => {
@@ -52533,7 +52941,7 @@ async function runSignupPreflights(runtime) {
52533
52941
  function defaultPreflightRuntime() {
52534
52942
  return {
52535
52943
  cwd: process.cwd(),
52536
- homeDir: homedir16(),
52944
+ homeDir: homedir17(),
52537
52945
  probeTool,
52538
52946
  readGitEmail,
52539
52947
  discoverCodeRoots,
@@ -52678,13 +53086,13 @@ async function suggestTasksWithCodex(projectPath, retryPolicy) {
52678
53086
  );
52679
53087
  }
52680
53088
  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");
53089
+ const tempRoot = mkdtempSync6(join25(tmpdir5(), "linzumi-signup-codex-tasks-"));
53090
+ const schemaPath = join25(tempRoot, "task-suggestions.schema.json");
53091
+ const outputPath = join25(tempRoot, "task-suggestions.json");
52684
53092
  const model = process.env.LINZUMI_SIGNUP_TASK_MODEL ?? "gpt-5.4-mini";
52685
53093
  const prompt = taskSuggestionPrompt2(previousResponse);
52686
53094
  const codexCommand = await resolveSignupCodexCommand();
52687
- writeFileSync15(
53095
+ writeFileSync16(
52688
53096
  schemaPath,
52689
53097
  `${JSON.stringify(taskSuggestionJsonSchema2(), null, 2)}
52690
53098
  `,
@@ -52705,9 +53113,9 @@ async function runCodexTaskSuggestion2(projectPath, previousResponse, retryPolic
52705
53113
  ),
52706
53114
  retryPolicy
52707
53115
  );
52708
- return readFileSync21(outputPath, "utf8");
53116
+ return readFileSync22(outputPath, "utf8");
52709
53117
  } finally {
52710
- rmSync6(tempRoot, { recursive: true, force: true });
53118
+ rmSync7(tempRoot, { recursive: true, force: true });
52711
53119
  }
52712
53120
  }
52713
53121
  function codexTaskSuggestionProcess2(args) {
@@ -52742,7 +53150,7 @@ function codexTaskSuggestionProcess2(args) {
52742
53150
  function signupCodexTaskSuggestionProcessForTest(args) {
52743
53151
  return codexTaskSuggestionProcess2(args);
52744
53152
  }
52745
- async function resolveSignupCodexCommand(env = process.env, homeDir = homedir16(), executableExists = fileIsExecutable) {
53153
+ async function resolveSignupCodexCommand(env = process.env, homeDir = homedir17(), executableExists = fileIsExecutable) {
52746
53154
  const override = firstConfiguredValue([
52747
53155
  env.LINZUMI_SIGNUP_CODEX_BIN,
52748
53156
  env.LINZUMI_CODEX_BIN
@@ -52797,7 +53205,7 @@ function resolveHomePath(path2, homeDir) {
52797
53205
  return homeDir;
52798
53206
  }
52799
53207
  if (path2.startsWith("~/")) {
52800
- return join23(homeDir, path2.slice(2));
53208
+ return join25(homeDir, path2.slice(2));
52801
53209
  }
52802
53210
  return resolve10(path2);
52803
53211
  }
@@ -52810,9 +53218,9 @@ function commandLooksPathLike(command) {
52810
53218
  }
52811
53219
  function homeManagedCodexCandidates(homeDir) {
52812
53220
  return [
52813
- join23(homeDir, ".volta", "bin", "codex"),
52814
- join23(homeDir, ".local", "bin", "codex"),
52815
- join23(homeDir, "bin", "codex")
53221
+ join25(homeDir, ".volta", "bin", "codex"),
53222
+ join25(homeDir, ".local", "bin", "codex"),
53223
+ join25(homeDir, "bin", "codex")
52816
53224
  ];
52817
53225
  }
52818
53226
  async function firstExecutablePath(paths, executableExists) {
@@ -52827,7 +53235,7 @@ function commandPathCandidates(path2) {
52827
53235
  if (path2 === void 0 || path2.trim() === "") {
52828
53236
  return [];
52829
53237
  }
52830
- return path2.split(delimiter3).filter((entry) => entry.trim() !== "").map((entry) => join23(entry, "codex"));
53238
+ return path2.split(delimiter3).filter((entry) => entry.trim() !== "").map((entry) => join25(entry, "codex"));
52831
53239
  }
52832
53240
  async function fileIsExecutable(path2) {
52833
53241
  try {
@@ -53060,11 +53468,11 @@ function codexPreflightLocation(command, homeDir) {
53060
53468
  switch (command) {
53061
53469
  case "codex":
53062
53470
  return "on PATH";
53063
- case join23(homeDir, ".volta", "bin", "codex"):
53471
+ case join25(homeDir, ".volta", "bin", "codex"):
53064
53472
  return "via Volta";
53065
- case join23(homeDir, ".local", "bin", "codex"):
53473
+ case join25(homeDir, ".local", "bin", "codex"):
53066
53474
  return "via ~/.local/bin";
53067
- case join23(homeDir, "bin", "codex"):
53475
+ case join25(homeDir, "bin", "codex"):
53068
53476
  return "via ~/bin";
53069
53477
  default:
53070
53478
  return "from configured path";
@@ -53223,7 +53631,7 @@ function probeToolWithArgs(command, args, cwd) {
53223
53631
  }
53224
53632
  async function discoverCodeRoots(homeDir) {
53225
53633
  const candidates = ["src", "code", "projects"].map(
53226
- (name) => join23(homeDir, name)
53634
+ (name) => join25(homeDir, name)
53227
53635
  );
53228
53636
  return candidates.filter((path2) => existsSync17(path2)).flatMap((path2) => discoveredProjectNames(path2));
53229
53637
  }
@@ -53277,7 +53685,7 @@ function discoverProjectsFromCurrentDirectory(cwd) {
53277
53685
  }
53278
53686
  function discoverProjectsFromGuessedRoots(homeDir) {
53279
53687
  const guessedRoots = ["src", "code", "projects"].map(
53280
- (name) => join23(homeDir, name)
53688
+ (name) => join25(homeDir, name)
53281
53689
  );
53282
53690
  const projects = guessedRoots.flatMap(
53283
53691
  (root) => discoverProjectsUnderRoot(root)
@@ -53329,25 +53737,25 @@ function looksLikeProject(path2) {
53329
53737
  "pnpm-lock.yaml",
53330
53738
  "yarn.lock",
53331
53739
  "package-lock.json"
53332
- ].some((name) => existsSync17(join23(path2, name)));
53740
+ ].some((name) => existsSync17(join25(path2, name)));
53333
53741
  }
53334
53742
  function detectProjectLanguage(path2) {
53335
- if (existsSync17(join23(path2, "pyproject.toml")) || existsSync17(join23(path2, "requirements.txt"))) {
53743
+ if (existsSync17(join25(path2, "pyproject.toml")) || existsSync17(join25(path2, "requirements.txt"))) {
53336
53744
  return "Python";
53337
53745
  }
53338
- if (existsSync17(join23(path2, "Cargo.toml"))) {
53746
+ if (existsSync17(join25(path2, "Cargo.toml"))) {
53339
53747
  return "Rust";
53340
53748
  }
53341
- if (existsSync17(join23(path2, "go.mod"))) {
53749
+ if (existsSync17(join25(path2, "go.mod"))) {
53342
53750
  return "Go";
53343
53751
  }
53344
- if (existsSync17(join23(path2, "mix.exs"))) {
53752
+ if (existsSync17(join25(path2, "mix.exs"))) {
53345
53753
  return "Elixir";
53346
53754
  }
53347
- if (existsSync17(join23(path2, "tsconfig.json")) || packageJsonMentionsTypeScript(path2)) {
53755
+ if (existsSync17(join25(path2, "tsconfig.json")) || packageJsonMentionsTypeScript(path2)) {
53348
53756
  return "TypeScript";
53349
53757
  }
53350
- if (existsSync17(join23(path2, "package.json"))) {
53758
+ if (existsSync17(join25(path2, "package.json"))) {
53351
53759
  return "JavaScript";
53352
53760
  }
53353
53761
  return "Project";
@@ -53355,7 +53763,7 @@ function detectProjectLanguage(path2) {
53355
53763
  function packageJsonMentionsTypeScript(path2) {
53356
53764
  try {
53357
53765
  const packageJson2 = JSON.parse(
53358
- readFileSync21(join23(path2, "package.json"), "utf8")
53766
+ readFileSync22(join25(path2, "package.json"), "utf8")
53359
53767
  );
53360
53768
  return packageJson2.dependencies?.typescript !== void 0 || packageJson2.devDependencies?.typescript !== void 0;
53361
53769
  } catch {
@@ -53363,11 +53771,11 @@ function packageJsonMentionsTypeScript(path2) {
53363
53771
  }
53364
53772
  }
53365
53773
  function hasGitMetadata(path2) {
53366
- return existsSync17(join23(path2, ".git"));
53774
+ return existsSync17(join25(path2, ".git"));
53367
53775
  }
53368
53776
  function childDirectories(root) {
53369
53777
  try {
53370
- return readdirSync5(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join23(root, entry.name));
53778
+ return readdirSync5(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join25(root, entry.name));
53371
53779
  } catch {
53372
53780
  return [];
53373
53781
  }
@@ -53393,10 +53801,10 @@ function directoryExists(path2) {
53393
53801
  }
53394
53802
  function expandHomePath(path2) {
53395
53803
  if (path2 === "~") {
53396
- return homedir16();
53804
+ return homedir17();
53397
53805
  }
53398
53806
  if (path2.startsWith("~/")) {
53399
- return join23(homedir16(), path2.slice(2));
53807
+ return join25(homedir17(), path2.slice(2));
53400
53808
  }
53401
53809
  return resolve10(path2);
53402
53810
  }
@@ -53487,8 +53895,8 @@ init_runner();
53487
53895
  init_runnerLockTakeover();
53488
53896
  init_claudeCodeSession();
53489
53897
  init_authCache();
53490
- import { existsSync as existsSync18, readFileSync as readFileSync22, realpathSync as realpathSync7 } from "node:fs";
53491
- import { homedir as homedir17 } from "node:os";
53898
+ import { existsSync as existsSync18, readFileSync as readFileSync23, realpathSync as realpathSync7 } from "node:fs";
53899
+ import { homedir as homedir18 } from "node:os";
53492
53900
  import { resolve as resolve11 } from "node:path";
53493
53901
  import { fileURLToPath as fileURLToPath4 } from "node:url";
53494
53902
 
@@ -53583,9 +53991,9 @@ init_kandanTls();
53583
53991
  init_protocol();
53584
53992
  init_json();
53585
53993
  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";
53994
+ import { existsSync as existsSync15, mkdirSync as mkdirSync14, readFileSync as readFileSync19, writeFileSync as writeFileSync13 } from "node:fs";
53995
+ import { dirname as dirname15, join as join22 } from "node:path";
53996
+ import { homedir as homedir15 } from "node:os";
53589
53997
  async function runAgentCliCommand(args, deps = {
53590
53998
  fetchImpl: fetch,
53591
53999
  stdout: process.stdout,
@@ -54293,7 +54701,7 @@ function agentTokenFile(flags) {
54293
54701
  return flags.get("agent-token-file") ?? defaultAgentTokenFilePath();
54294
54702
  }
54295
54703
  function defaultAgentTokenFilePath() {
54296
- return join21(homedir14(), ".linzumi", "agent-token.json");
54704
+ return join22(homedir15(), ".linzumi", "agent-token.json");
54297
54705
  }
54298
54706
  function normalizedApiUrl(apiUrl) {
54299
54707
  return apiUrl.endsWith("/") ? apiUrl : `${apiUrl}/`;
@@ -54302,11 +54710,11 @@ function authorizationHeaders(token) {
54302
54710
  return { authorization: `Bearer ${token}` };
54303
54711
  }
54304
54712
  function readOptionalTextFile(path2) {
54305
- return existsSync15(path2) ? readFileSync18(path2, "utf8") : void 0;
54713
+ return existsSync15(path2) ? readFileSync19(path2, "utf8") : void 0;
54306
54714
  }
54307
54715
  function writeTextFile(path2, content) {
54308
- mkdirSync13(dirname14(path2), { recursive: true });
54309
- writeFileSync12(path2, content);
54716
+ mkdirSync14(dirname15(path2), { recursive: true });
54717
+ writeFileSync13(path2, content);
54310
54718
  }
54311
54719
  function readStoredAgentTokenFile(path2, readTextFile = readOptionalTextFile) {
54312
54720
  const content = readTextFile(path2);
@@ -54395,25 +54803,25 @@ init_runnerLogger();
54395
54803
  import {
54396
54804
  existsSync as existsSync16,
54397
54805
  closeSync as closeSync3,
54398
- mkdirSync as mkdirSync14,
54806
+ mkdirSync as mkdirSync15,
54399
54807
  openSync as openSync4,
54400
- readFileSync as readFileSync19,
54808
+ readFileSync as readFileSync20,
54401
54809
  watch,
54402
- writeFileSync as writeFileSync13
54810
+ writeFileSync as writeFileSync14
54403
54811
  } 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";
54812
+ import { homedir as homedir16 } from "node:os";
54813
+ import { dirname as dirname16, join as join23, resolve as resolve9 } from "node:path";
54406
54814
  import { execFileSync, spawn as spawn10 } from "node:child_process";
54407
54815
  import { fileURLToPath as fileURLToPath3 } from "node:url";
54408
54816
  var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
54409
54817
  function commanderStatusDir() {
54410
- return join22(homedir15(), ".linzumi", "commanders");
54818
+ return join23(homedir16(), ".linzumi", "commanders");
54411
54819
  }
54412
54820
  function commanderStatusFile(runnerId, statusDir = commanderStatusDir()) {
54413
- return join22(statusDir, `${safeRunnerId(runnerId)}.json`);
54821
+ return join23(statusDir, `${safeRunnerId(runnerId)}.json`);
54414
54822
  }
54415
54823
  function defaultCommanderLogFile(runnerId) {
54416
- return join22(homedir15(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
54824
+ return join23(homedir16(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
54417
54825
  }
54418
54826
  function commanderLogIsConnected(log2) {
54419
54827
  return connectedMarkers.some((marker) => log2.includes(marker));
@@ -54434,8 +54842,8 @@ function startCommanderDaemon(options) {
54434
54842
  "--log-file",
54435
54843
  logFile
54436
54844
  ];
54437
- mkdirSync14(statusDir, { recursive: true });
54438
- mkdirSync14(dirname15(logFile), { recursive: true });
54845
+ mkdirSync15(statusDir, { recursive: true });
54846
+ mkdirSync15(dirname16(logFile), { recursive: true });
54439
54847
  const out = openSync4(logFile, "a");
54440
54848
  const err = openSync4(logFile, "a");
54441
54849
  writeCliAuditEvent(
@@ -54481,7 +54889,7 @@ function startCommanderDaemon(options) {
54481
54889
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
54482
54890
  command: [nodeBin, ...command]
54483
54891
  };
54484
- writeFileSync13(statusFile, `${JSON.stringify(record, null, 2)}
54892
+ writeFileSync14(statusFile, `${JSON.stringify(record, null, 2)}
54485
54893
  `);
54486
54894
  return record;
54487
54895
  }
@@ -54490,12 +54898,12 @@ function commanderDaemonStatus(runnerId, statusDir = commanderStatusDir(), proce
54490
54898
  if (!existsSync16(statusFile)) {
54491
54899
  return { status: "missing", runnerId, statusFile };
54492
54900
  }
54493
- const record = parseRecord(readFileSync19(statusFile, "utf8"));
54901
+ const record = parseRecord2(readFileSync20(statusFile, "utf8"));
54494
54902
  return processIsRunning(record.pid) && processMatchesRecord(record, processIdentityReader) ? { status: "running", record } : { status: "stopped", record };
54495
54903
  }
54496
54904
  async function waitForCommanderDaemon(options) {
54497
54905
  const now = options.now ?? (() => Date.now());
54498
- const readTextFile = options.readTextFile ?? ((path2) => existsSync16(path2) ? readFileSync19(path2, "utf8") : void 0);
54906
+ const readTextFile = options.readTextFile ?? ((path2) => existsSync16(path2) ? readFileSync20(path2, "utf8") : void 0);
54499
54907
  const statusImpl = options.statusImpl ?? commanderDaemonStatus;
54500
54908
  const deadline = now() + options.timeoutMs;
54501
54909
  while (now() <= deadline) {
@@ -54559,7 +54967,7 @@ function currentEntrypoint() {
54559
54967
  }
54560
54968
  return fileURLToPath3(import.meta.url);
54561
54969
  }
54562
- function parseRecord(content) {
54970
+ function parseRecord2(content) {
54563
54971
  const parsed = JSON.parse(content);
54564
54972
  const record = typeof parsed === "object" && parsed !== null ? parsed : {};
54565
54973
  const pid = typeof record.pid === "number" ? record.pid : void 0;
@@ -67377,13 +67785,18 @@ function required(values, key) {
67377
67785
  }
67378
67786
 
67379
67787
  // src/remoteCodexHarnessWorker.ts
67788
+ init_authCache();
67380
67789
  init_channelSession();
67381
67790
  init_codexAppServer();
67382
67791
  init_localCapabilities();
67792
+ init_mcpConfig();
67383
67793
  init_phoenix();
67384
67794
  init_runnerLogger();
67385
67795
  init_userFacingErrors();
67386
67796
  init_version();
67797
+ import { chmodSync as chmodSync3, mkdtempSync as mkdtempSync5, rmSync as rmSync6 } from "node:fs";
67798
+ import { tmpdir as tmpdir4 } from "node:os";
67799
+ import { basename as basename9, dirname as dirname17, join as join24 } from "node:path";
67387
67800
  var configEnvKey = "LINZUMI_REMOTE_CODEX_HARNESS_CONFIG_B64";
67388
67801
  var remoteHarnessEnvironmentId = "linzumi-remote-codex-harness";
67389
67802
  async function runRemoteCodexHarnessWorkerFromEnv(env = process.env) {
@@ -67400,17 +67813,42 @@ async function runRemoteCodexHarnessWorker(config, deps = {}) {
67400
67813
  log: writeCliAuditEvent,
67401
67814
  ...deps
67402
67815
  };
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
- }
67816
+ const mcpAuth = writeEphemeralMcpAuthFile2(config);
67817
+ const mcpCommand = linzumiMcpCommandForProcess(
67818
+ process.execPath,
67819
+ resolveLinzumiCliEntrypoint(process.argv[1]),
67820
+ process.execArgv
67413
67821
  );
67822
+ let started;
67823
+ try {
67824
+ started = await resolvedDeps.startCodexAppServer(
67825
+ config.codexBin,
67826
+ config.workerCwd,
67827
+ {
67828
+ model: config.model,
67829
+ reasoningEffort: config.reasoningEffort,
67830
+ fast: config.fast,
67831
+ inheritEnv: false,
67832
+ env: remoteHarnessCodexEnv(process.env, config.execServerUrl),
67833
+ mcpServers: [
67834
+ linzumiMcpServerConfig({
67835
+ command: mcpCommand.command,
67836
+ argsPrefix: mcpCommand.argsPrefix,
67837
+ kandanUrl: config.kandanUrl,
67838
+ authFilePath: mcpAuth.path,
67839
+ ownerUsername: config.listenUser,
67840
+ operatingMode: "text",
67841
+ cwd: config.cwd,
67842
+ threadId: config.kandanThreadId
67843
+ })
67844
+ ]
67845
+ }
67846
+ );
67847
+ } catch (error) {
67848
+ mcpAuth.cleanup();
67849
+ throw error;
67850
+ }
67851
+ started.process.once("exit", () => mcpAuth.cleanup());
67414
67852
  let kandan;
67415
67853
  let codex;
67416
67854
  let session;
@@ -67419,6 +67857,7 @@ async function runRemoteCodexHarnessWorker(config, deps = {}) {
67419
67857
  codex?.close();
67420
67858
  kandan?.close();
67421
67859
  started.stop();
67860
+ mcpAuth.cleanup();
67422
67861
  };
67423
67862
  const cleanupOnce = onceAsync(cleanup);
67424
67863
  try {
@@ -67581,6 +68020,50 @@ function assertJsonRpcOk(response, method) {
67581
68020
  throw new Error(`${method} failed: ${response.error.message}`);
67582
68021
  }
67583
68022
  }
68023
+ function resolveLinzumiCliEntrypoint(entrypoint) {
68024
+ if (entrypoint === void 0 || entrypoint.trim() === "") {
68025
+ return entrypoint;
68026
+ }
68027
+ const base = basename9(entrypoint);
68028
+ switch (base) {
68029
+ case "remote-codex-harness-worker.js":
68030
+ case "remote-codex-harness-worker.mjs":
68031
+ case "remote-codex-harness-worker.cjs":
68032
+ return join24(dirname17(entrypoint), "linzumi.js");
68033
+ case "remoteCodexHarnessWorkerEntrypoint.ts":
68034
+ case "remoteCodexHarnessWorkerEntrypoint.js":
68035
+ return join24(dirname17(entrypoint), "index.ts");
68036
+ default:
68037
+ return entrypoint;
68038
+ }
68039
+ }
68040
+ function writeEphemeralMcpAuthFile2(options) {
68041
+ const directory = mkdtempSync5(join24(tmpdir4(), "linzumi-mcp-auth-"));
68042
+ chmodSync3(directory, 448);
68043
+ const path2 = join24(directory, "auth.json");
68044
+ try {
68045
+ writeCachedLocalRunnerToken({
68046
+ kandanUrl: options.kandanUrl,
68047
+ accessToken: options.token,
68048
+ authFilePath: path2
68049
+ });
68050
+ chmodSync3(path2, 384);
68051
+ } catch (error) {
68052
+ rmSync6(directory, { recursive: true, force: true });
68053
+ throw error;
68054
+ }
68055
+ let cleaned = false;
68056
+ return {
68057
+ path: path2,
68058
+ cleanup: () => {
68059
+ if (cleaned) {
68060
+ return;
68061
+ }
68062
+ cleaned = true;
68063
+ rmSync6(directory, { recursive: true, force: true });
68064
+ }
68065
+ };
68066
+ }
67584
68067
  function remoteHarnessCodexEnv(sourceEnv, execServerUrl) {
67585
68068
  const env = {
67586
68069
  CODEX_EXEC_SERVER_URL: execServerUrl,
@@ -68504,7 +68987,7 @@ async function parseAgentRunnerArgs(args, deps = {
68504
68987
  };
68505
68988
  }
68506
68989
  function readAgentTokenTextFile(path2) {
68507
- return existsSync18(path2) ? readFileSync22(path2, "utf8") : void 0;
68990
+ return existsSync18(path2) ? readFileSync23(path2, "utf8") : void 0;
68508
68991
  }
68509
68992
  function rejectAgentRunnerTargetingFlags(values) {
68510
68993
  const unsupportedFlags = [
@@ -68818,10 +69301,10 @@ function rejectStartTargetingFlags(values) {
68818
69301
  }
68819
69302
  function resolveUserPath(pathValue) {
68820
69303
  if (pathValue === "~") {
68821
- return homedir17();
69304
+ return homedir18();
68822
69305
  }
68823
69306
  if (pathValue.startsWith("~/")) {
68824
- return resolve11(homedir17(), pathValue.slice(2));
69307
+ return resolve11(homedir18(), pathValue.slice(2));
68825
69308
  }
68826
69309
  return resolve11(pathValue);
68827
69310
  }