@super-one/cli 0.57.1-alpha → 0.57.3-alpha

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/MANIFEST.json +2 -2
  2. package/lib/cli.mjs +710 -618
  3. package/package.json +1 -1
package/lib/cli.mjs CHANGED
@@ -2990,7 +2990,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
2990
2990
  },
2991
2991
  {
2992
2992
  "name": "browser_act",
2993
- "description": "Submit 1\u201320 page actions as one call: click, hover, type, press, scroll, drag, select, upload. Prefer a CSS selector from snapshot/query; click/hover also accept text or x/y. engine=auto|cdp|synthetic (default auto). description is shown to the user instead of raw selectors. Do not use this to navigate (browser_tabs), wait (browser_wait_for), or run JS (browser_evaluate). Fail-fast: stops at the first error.",
2993
+ "description": "Submit 1\u201320 page actions as one call: click, hover, type, press, scroll, drag, select, upload. Prefer a CSS selector from snapshot/query; click/hover also accept text or x/y. engine=auto|cdp|synthetic (default auto). description is shown to the user instead of raw selectors. Set recording=true to save a short video containing only this action transaction. Optional expect keeps the recording open until an explicit page condition is met. Do not use this to navigate (browser_tabs), wait (browser_wait_for), or run JS (browser_evaluate). Fail-fast: stops at the first error.",
2994
2994
  "inputSchema": {
2995
2995
  "type": "object",
2996
2996
  "properties": {
@@ -3008,7 +3008,19 @@ If the tool returns an error containing "user_locked", the user has manually nam
3008
3008
  "required": ["type"],
3009
3009
  "additionalProperties": true
3010
3010
  }
3011
- }
3011
+ },
3012
+ "recording": { "type": "boolean", "description": "Save a video of only this action transaction. Default false." },
3013
+ "expect": {
3014
+ "type": "object",
3015
+ "properties": {
3016
+ "selector": { "type": "string" },
3017
+ "selectorGone": { "type": "string" },
3018
+ "text": { "type": "string" },
3019
+ "urlIncludes": { "type": "string" }
3020
+ },
3021
+ "additionalProperties": false
3022
+ },
3023
+ "timeoutMs": { "type": "integer", "minimum": 100, "maximum": 6e4 }
3012
3024
  },
3013
3025
  "required": ["actions"],
3014
3026
  "additionalProperties": false
@@ -3277,7 +3289,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
3277
3289
  },
3278
3290
  {
3279
3291
  "name": "computer_act",
3280
- "description": "Submit 1\u201320 related UI actions as a checked transaction against a stateId. Delivery policy (pick explicitly when possible): (1) Prefer delivery=semantic whenever actions use @eN refs and the action is press/setText/click(ref)/typeText(ref) \u2014 pure AX, most reliable for labeled controls. (2) Use delivery=app-directed (runtime default if omitted) for coordinate click/type/scroll/drag/keypress or when no usable AX ref exists \u2014 posts CGEvent to the target app PID in the background without stealing frontmost. (3) Use delivery=physical only when app-directed fails and global HID is required (requires frontmost; disruptive). Actions: click, typeText, keypress, scroll(dx,dy[,x,y|ref]), drag(path\u22652 points), moveMouse, press/setText (AX). scroll: positive dy scrolls content down; aim with x,y (capture space) or ref center; else window/outline center. drag: path is capture-space points; virtual cursor animates along the path. Returns outcome worked|didnt|unknown based on re-observation (not API success codes): worked when AX readback, expect, typed text, or a meaningful successor outline diff confirms effect; unknown only when applied but unprovable; didnt on hard failure or failed expect. When the successor has pixels, successorImage.path contains the fresh screenshot. Stale stateId (UI changed since snapshot) is rejected before side effects. delivery=semantic never silently upgrades to app-directed/physical input.",
3292
+ "description": "Submit 1\u201320 related UI actions as a checked transaction against a stateId. Delivery policy (pick explicitly when possible): (1) Prefer delivery=semantic whenever actions use @eN refs and the action is press/setText/click(ref)/typeText(ref) \u2014 pure AX, most reliable for labeled controls. (2) Use delivery=app-directed (runtime default if omitted) for coordinate click/type/scroll/drag/keypress or when no usable AX ref exists \u2014 posts CGEvent to the target app PID in the background without stealing frontmost. (3) Use delivery=physical only when app-directed fails and global HID is required (requires frontmost; disruptive). Actions: click, typeText, keypress, scroll(dx,dy[,x,y|ref]), drag(path\u22652 points), moveMouse, press/setText (AX). scroll: positive dy scrolls content down; aim with x,y (capture space) or ref center; else window/outline center. drag: path is capture-space points; virtual cursor animates along the path. Returns outcome worked|didnt|unknown based on re-observation (not API success codes): worked when AX readback, expect, typed text, or a meaningful successor outline diff confirms effect; unknown only when applied but unprovable; didnt on hard failure or failed expect. When the successor has pixels, successorImage.path contains the fresh screenshot. Set recording=true to save a short video containing only this action transaction. Stale stateId (UI changed since snapshot) is rejected before side effects. delivery=semantic never silently upgrades to app-directed/physical input.",
3281
3293
  "inputSchema": {
3282
3294
  "type": "object",
3283
3295
  "properties": {
@@ -3396,6 +3408,16 @@ If the tool returns an error containing "user_locked", the user has manually nam
3396
3408
  ],
3397
3409
  "additionalProperties": false
3398
3410
  },
3411
+ "recording": {
3412
+ "description": "Save a video of only this action transaction. Default false.",
3413
+ "type": "boolean"
3414
+ },
3415
+ "timeoutMs": {
3416
+ "description": "Maximum wait for expect before the action is judged. Default 5000.",
3417
+ "type": "integer",
3418
+ "minimum": 100,
3419
+ "maximum": 6e4
3420
+ },
3399
3421
  "delivery": {
3400
3422
  "description": "Prefer semantic when actions target @eN refs (press/setText/click/typeText). Omit or app-directed = background postToPid (default). physical = global HID + frontmost only as last resort.",
3401
3423
  "type": "string",
@@ -3800,7 +3822,7 @@ If the tool returns an error containing "user_locked", the user has manually nam
3800
3822
  },
3801
3823
  {
3802
3824
  "name": "device_act",
3803
- "description": "Run 1-10 touch actions against a snapshot, then re-observe to judge if they worked. Actions: tap, doubleTap, longPress, swipe(direction|toX/toY), pinch(scale), press(ref), type, key, rotate, keyboard. Prefer press for a ref-backed control; it goes through accessibility, immune to animation, rotation and scale (not on a source=ocr snapshot \u2014 tap there). Aim touch actions at refs too; raw x/y is a last resort. The whole batch, stale stateId included, is validated up front. rotate ends the snapshot it is in: put it last, then re-snapshot \u2014 a later ref or coordinate is refused. Returns worked|didnt|unknown; unknown means input landed but nothing visibly changed. Pass expect to define success.",
3825
+ "description": "Run 1-10 touch actions against a snapshot, then re-observe to judge if they worked. Actions: tap, doubleTap, longPress, swipe(direction|toX/toY), pinch(scale), press(ref), type, key, rotate, keyboard. Prefer refs; press uses accessibility and is resilient to animation (use tap for source=ocr). Raw x/y is a last resort. The batch and stale stateId are validated before side effects. rotate must be last; re-snapshot afterwards. Set recording=true to save a short video containing only this action transaction. Returns worked|didnt|unknown. Pass expect to define and wait for success.",
3804
3826
  "inputSchema": {
3805
3827
  "type": "object",
3806
3828
  "properties": {
@@ -3808,7 +3830,9 @@ If the tool returns an error containing "user_locked", the user has manually nam
3808
3830
  "device": deviceTargetProperty,
3809
3831
  "stateId": { "type": "string" },
3810
3832
  "actions": { "minItems": 1, "maxItems": 10, "type": "array", "items": deviceActionSchema },
3811
- "expect": { "description": "Postcondition checked after the actions run.", ...deviceConditionSchema }
3833
+ "expect": { "description": "Postcondition checked after the actions run.", ...deviceConditionSchema },
3834
+ "timeoutMs": { "description": "Maximum wait for expect before the action is judged. Default 5000.", "type": "integer", "minimum": 100, "maximum": 6e4 },
3835
+ "recording": { "description": "Save a video of only this action transaction. Default false.", "type": "boolean" }
3812
3836
  },
3813
3837
  "required": ["description", "stateId", "actions"],
3814
3838
  "additionalProperties": false
@@ -4548,9 +4572,9 @@ var require_node_gyp_build = __commonJS({
4548
4572
  var debug = getFirst(path.join(dir, "build/Debug"), matchBuild);
4549
4573
  if (debug) return debug;
4550
4574
  }
4551
- var prebuild = resolve14(dir);
4575
+ var prebuild = resolve15(dir);
4552
4576
  if (prebuild) return prebuild;
4553
- var nearby = resolve14(path.dirname(process.execPath));
4577
+ var nearby = resolve15(path.dirname(process.execPath));
4554
4578
  if (nearby) return nearby;
4555
4579
  var target = [
4556
4580
  "platform=" + platform2,
@@ -4566,7 +4590,7 @@ var require_node_gyp_build = __commonJS({
4566
4590
  // eslint-disable-line
4567
4591
  ].filter(Boolean).join(" ");
4568
4592
  throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
4569
- function resolve14(dir2) {
4593
+ function resolve15(dir2) {
4570
4594
  var tuples = readdirSync12(path.join(dir2, "prebuilds")).map(parseTuple);
4571
4595
  var tuple2 = tuples.filter(matchTuple(platform2, arch2)).sort(compareTuples)[0];
4572
4596
  if (!tuple2) return;
@@ -18701,139 +18725,16 @@ var init_hooks_config = __esm({
18701
18725
  }
18702
18726
  });
18703
18727
 
18704
- // ../../packages/runtime/src/fs/additional-dirs-config.ts
18705
- import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
18728
+ // ../../packages/runtime/src/fs/agents-discover.ts
18729
+ import { existsSync as existsSync14, readdirSync as readdirSync5, readFileSync as readFileSync12 } from "node:fs";
18730
+ import { join as join15 } from "node:path";
18706
18731
  import { homedir as osHomedir7 } from "node:os";
18707
- import { dirname as dirname12, join as join15 } from "node:path";
18708
18732
  function homeOf7(opts) {
18709
18733
  return opts?.homeDir ?? osHomedir7();
18710
18734
  }
18711
- function codexHomeOf3(opts) {
18712
- if (opts?.codexHome) return opts.codexHome;
18713
- return process.env.CODEX_HOME?.trim() || join15(homeOf7(opts), ".codex");
18714
- }
18715
- function readJson3(filePath) {
18716
- if (!existsSync14(filePath)) return null;
18717
- try {
18718
- return JSON.parse(readFileSync12(filePath, "utf8"));
18719
- } catch {
18720
- return null;
18721
- }
18722
- }
18723
- function readToml(filePath) {
18724
- if (!existsSync14(filePath)) return null;
18725
- try {
18726
- return parse(readFileSync12(filePath, "utf8"));
18727
- } catch {
18728
- return null;
18729
- }
18730
- }
18731
- function cleanDirs(value) {
18732
- if (!Array.isArray(value)) return [];
18733
- return Array.from(new Set(value.filter((dir) => typeof dir === "string" && dir.trim().length > 0)));
18734
- }
18735
- function claudeDirs(data) {
18736
- if (!data) return [];
18737
- const permissions = data.permissions;
18738
- const nested = permissions && typeof permissions === "object" && !Array.isArray(permissions) ? permissions.additionalDirectories : void 0;
18739
- return Array.from(/* @__PURE__ */ new Set([
18740
- ...cleanDirs(data.additionalDirectories),
18741
- ...cleanDirs(nested)
18742
- ]));
18743
- }
18744
- function codexDirs(data) {
18745
- if (!data) return [];
18746
- const workspaceWrite = data.sandbox_workspace_write;
18747
- if (!workspaceWrite || typeof workspaceWrite !== "object" || Array.isArray(workspaceWrite)) return [];
18748
- return cleanDirs(workspaceWrite.writable_roots);
18749
- }
18750
- function readScopedAdditionalDirs(provider, cwd, opts) {
18751
- if (provider === "codex") {
18752
- return {
18753
- user: codexDirs(readToml(join15(codexHomeOf3(opts), "config.toml"))),
18754
- projectShared: [],
18755
- projectLocal: codexDirs(readToml(join15(cwd, ".codex", "config.toml")))
18756
- };
18757
- }
18758
- return {
18759
- user: claudeDirs(readJson3(join15(homeOf7(opts), ".claude", "settings.json"))),
18760
- projectShared: claudeDirs(readJson3(join15(cwd, ".claude", "settings.json"))),
18761
- projectLocal: claudeDirs(readJson3(join15(cwd, ".claude", "settings.local.json")))
18762
- };
18763
- }
18764
- function addProjectAdditionalDir(provider, cwd, dir, opts) {
18765
- if (provider === "codex") {
18766
- const filePath2 = join15(cwd, ".codex", "config.toml");
18767
- const data2 = readToml(filePath2) ?? {};
18768
- const current2 = data2.sandbox_workspace_write;
18769
- const workspaceWrite = current2 && typeof current2 === "object" && !Array.isArray(current2) ? current2 : {};
18770
- const existing2 = cleanDirs(workspaceWrite.writable_roots);
18771
- if (existing2.includes(dir)) return;
18772
- workspaceWrite.writable_roots = [...existing2, dir];
18773
- data2.sandbox_workspace_write = workspaceWrite;
18774
- mkdirSync11(dirname12(filePath2), { recursive: true });
18775
- writeFileSync9(filePath2, stringify(data2), "utf8");
18776
- return;
18777
- }
18778
- const filePath = join15(cwd, ".claude", "settings.local.json");
18779
- const data = readJson3(filePath) ?? {};
18780
- const current = data.permissions;
18781
- const permissions = current && typeof current === "object" && !Array.isArray(current) ? current : {};
18782
- const existing = cleanDirs(permissions.additionalDirectories);
18783
- if (existing.includes(dir)) return;
18784
- permissions.additionalDirectories = [...existing, dir];
18785
- data.permissions = permissions;
18786
- mkdirSync11(dirname12(filePath), { recursive: true });
18787
- writeFileSync9(filePath, `${JSON.stringify(data, null, 2)}
18788
- `, "utf8");
18789
- }
18790
- function removeProjectAdditionalDir(provider, cwd, dir) {
18791
- if (provider === "codex") {
18792
- const filePath2 = join15(cwd, ".codex", "config.toml");
18793
- const data2 = readToml(filePath2);
18794
- if (!data2) return;
18795
- const current2 = data2.sandbox_workspace_write;
18796
- if (!current2 || typeof current2 !== "object" || Array.isArray(current2)) return;
18797
- const workspaceWrite = current2;
18798
- const existing2 = cleanDirs(workspaceWrite.writable_roots);
18799
- const filtered2 = existing2.filter((root) => root !== dir);
18800
- if (filtered2.length === existing2.length) return;
18801
- if (filtered2.length > 0) workspaceWrite.writable_roots = filtered2;
18802
- else delete workspaceWrite.writable_roots;
18803
- if (Object.keys(workspaceWrite).length === 0) delete data2.sandbox_workspace_write;
18804
- writeFileSync9(filePath2, stringify(data2), "utf8");
18805
- return;
18806
- }
18807
- const filePath = join15(cwd, ".claude", "settings.local.json");
18808
- const data = readJson3(filePath);
18809
- if (!data) return;
18810
- const current = data.permissions;
18811
- if (!current || typeof current !== "object" || Array.isArray(current)) return;
18812
- const permissions = current;
18813
- const existing = cleanDirs(permissions.additionalDirectories);
18814
- const filtered = existing.filter((root) => root !== dir);
18815
- if (filtered.length === existing.length) return;
18816
- permissions.additionalDirectories = filtered;
18817
- writeFileSync9(filePath, `${JSON.stringify(data, null, 2)}
18818
- `, "utf8");
18819
- }
18820
- var init_additional_dirs_config = __esm({
18821
- "../../packages/runtime/src/fs/additional-dirs-config.ts"() {
18822
- "use strict";
18823
- init_dist();
18824
- }
18825
- });
18826
-
18827
- // ../../packages/runtime/src/fs/agents-discover.ts
18828
- import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync13 } from "node:fs";
18829
- import { join as join16 } from "node:path";
18830
- import { homedir as osHomedir8 } from "node:os";
18831
- function homeOf8(opts) {
18832
- return opts?.homeDir ?? osHomedir8();
18833
- }
18834
18735
  function safeRead(path) {
18835
18736
  try {
18836
- return readFileSync13(path, "utf-8");
18737
+ return readFileSync12(path, "utf-8");
18837
18738
  } catch {
18838
18739
  return "";
18839
18740
  }
@@ -18880,10 +18781,10 @@ function parseFrontmatter(content) {
18880
18781
  return result;
18881
18782
  }
18882
18783
  function readPlugins(opts) {
18883
- const pluginsFile = join16(homeOf8(opts), ".claude", "plugins", "installed_plugins.json");
18884
- if (!existsSync15(pluginsFile)) return {};
18784
+ const pluginsFile = join15(homeOf7(opts), ".claude", "plugins", "installed_plugins.json");
18785
+ if (!existsSync14(pluginsFile)) return {};
18885
18786
  try {
18886
- const data = JSON.parse(readFileSync13(pluginsFile, "utf-8"));
18787
+ const data = JSON.parse(readFileSync12(pluginsFile, "utf-8"));
18887
18788
  return data.plugins ?? {};
18888
18789
  } catch {
18889
18790
  return {};
@@ -18904,12 +18805,12 @@ function forEachPluginScope(filter, callback, opts) {
18904
18805
  }
18905
18806
  }
18906
18807
  function scanAgentDir(dir, source, namePrefix = "") {
18907
- if (!existsSync15(dir)) return [];
18808
+ if (!existsSync14(dir)) return [];
18908
18809
  const agents = [];
18909
18810
  for (const entry of readdirSync5(dir, { withFileTypes: true })) {
18910
18811
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
18911
18812
  const name = namePrefix + entry.name.replace(/\.md$/, "");
18912
- const content = safeRead(join16(dir, entry.name));
18813
+ const content = safeRead(join15(dir, entry.name));
18913
18814
  const fm = parseFrontmatter(content);
18914
18815
  agents.push({
18915
18816
  name,
@@ -18922,23 +18823,23 @@ function scanAgentDir(dir, source, namePrefix = "") {
18922
18823
  }
18923
18824
  function discoverUserAgents(opts) {
18924
18825
  const agents = [
18925
- ...scanAgentDir(join16(homeOf8(opts), ".claude", "agents"), "user")
18826
+ ...scanAgentDir(join15(homeOf7(opts), ".claude", "agents"), "user")
18926
18827
  ];
18927
18828
  forEachPluginScope(
18928
18829
  isUserScoped,
18929
18830
  (installPath, pluginName) => {
18930
- agents.push(...scanAgentDir(join16(installPath, "agents"), "plugin", `${pluginName}:`));
18831
+ agents.push(...scanAgentDir(join15(installPath, "agents"), "plugin", `${pluginName}:`));
18931
18832
  },
18932
18833
  opts
18933
18834
  );
18934
18835
  return agents;
18935
18836
  }
18936
18837
  function discoverProjectAgents(cwd, opts) {
18937
- const agents = [...scanAgentDir(join16(cwd, ".claude", "agents"), "project")];
18838
+ const agents = [...scanAgentDir(join15(cwd, ".claude", "agents"), "project")];
18938
18839
  forEachPluginScope(
18939
18840
  (e) => isProjectScoped(e, cwd),
18940
18841
  (installPath, pluginName) => {
18941
- agents.push(...scanAgentDir(join16(installPath, "agents"), "plugin", `${pluginName}:`));
18842
+ agents.push(...scanAgentDir(join15(installPath, "agents"), "plugin", `${pluginName}:`));
18942
18843
  },
18943
18844
  opts
18944
18845
  );
@@ -18961,10 +18862,10 @@ function discoverAllAgents(cwd, opts) {
18961
18862
  }
18962
18863
  function readAgentFile(cwd, name, opts) {
18963
18864
  const baseName = name.includes(":") ? name.split(":").pop() : name;
18964
- const projectPath = join16(cwd, ".claude", "agents", `${baseName}.md`);
18965
- if (existsSync15(projectPath)) return safeRead(projectPath) || null;
18966
- const userPath = join16(homeOf8(opts), ".claude", "agents", `${baseName}.md`);
18967
- if (existsSync15(userPath)) return safeRead(userPath) || null;
18865
+ const projectPath = join15(cwd, ".claude", "agents", `${baseName}.md`);
18866
+ if (existsSync14(projectPath)) return safeRead(projectPath) || null;
18867
+ const userPath = join15(homeOf7(opts), ".claude", "agents", `${baseName}.md`);
18868
+ if (existsSync14(userPath)) return safeRead(userPath) || null;
18968
18869
  const plugins = readPlugins(opts);
18969
18870
  for (const [pluginKey, entries] of Object.entries(plugins)) {
18970
18871
  const pluginName = pluginKey.split("@")[0] ?? pluginKey;
@@ -18972,8 +18873,8 @@ function readAgentFile(cwd, name, opts) {
18972
18873
  if (!entry.installPath) continue;
18973
18874
  const prefix = `${pluginName}:`;
18974
18875
  const agentBaseName = name.startsWith(prefix) ? name.slice(prefix.length) : baseName;
18975
- const pluginAgentPath = join16(entry.installPath, "agents", `${agentBaseName}.md`);
18976
- if (existsSync15(pluginAgentPath)) return safeRead(pluginAgentPath) || null;
18876
+ const pluginAgentPath = join15(entry.installPath, "agents", `${agentBaseName}.md`);
18877
+ if (existsSync14(pluginAgentPath)) return safeRead(pluginAgentPath) || null;
18977
18878
  }
18978
18879
  }
18979
18880
  return null;
@@ -18998,7 +18899,6 @@ var init_fs = __esm({
18998
18899
  init_fuzzy();
18999
18900
  init_plugins_manage();
19000
18901
  init_hooks_config();
19001
- init_additional_dirs_config();
19002
18902
  init_agents_discover();
19003
18903
  }
19004
18904
  });
@@ -20010,12 +19910,12 @@ var init_agent_event_mapper = __esm({
20010
19910
  // ../../packages/codex/src/app-server-client.ts
20011
19911
  import { spawn } from "node:child_process";
20012
19912
  import { createInterface } from "node:readline";
20013
- import { existsSync as existsSync16 } from "node:fs";
19913
+ import { existsSync as existsSync15 } from "node:fs";
20014
19914
  async function openCodexAppServer(opts) {
20015
19915
  if (opts.signal?.aborted) {
20016
19916
  throw new Error("Codex app-server launch interrupted");
20017
19917
  }
20018
- if (!opts.binaryPath || !existsSync16(opts.binaryPath)) {
19918
+ if (!opts.binaryPath || !existsSync15(opts.binaryPath)) {
20019
19919
  throw new Error(`Codex binary not found: ${opts.binaryPath || "(empty)"}`);
20020
19920
  }
20021
19921
  const spawnFn = opts.spawnFn ?? defaultSpawn;
@@ -20079,21 +19979,21 @@ async function openCodexAppServer(opts) {
20079
19979
  const terminateChild = async () => {
20080
19980
  if (processExited) return;
20081
19981
  const killTimeoutMs = opts.killTimeoutMs ?? 2e3;
20082
- await new Promise((resolve14) => {
19982
+ await new Promise((resolve15) => {
20083
19983
  if (processExited) {
20084
- resolve14();
19984
+ resolve15();
20085
19985
  return;
20086
19986
  }
20087
19987
  const onExit = () => {
20088
19988
  clearTimeout(t);
20089
- resolve14();
19989
+ resolve15();
20090
19990
  };
20091
19991
  child.once("exit", onExit);
20092
19992
  try {
20093
19993
  child.kill("SIGTERM");
20094
19994
  } catch {
20095
19995
  child.removeListener("exit", onExit);
20096
- resolve14();
19996
+ resolve15();
20097
19997
  return;
20098
19998
  }
20099
19999
  const t = setTimeout(() => {
@@ -20105,7 +20005,7 @@ async function openCodexAppServer(opts) {
20105
20005
  }
20106
20006
  setTimeout(() => {
20107
20007
  child.removeListener("exit", onExit);
20108
- resolve14();
20008
+ resolve15();
20109
20009
  }, 500);
20110
20010
  }, killTimeoutMs);
20111
20011
  });
@@ -20185,7 +20085,7 @@ async function openCodexAppServer(opts) {
20185
20085
  failAll(safePublicError("Codex app-server read failed", readLoopError));
20186
20086
  }
20187
20087
  })();
20188
- const request = (method, params, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) => new Promise((resolve14, reject) => {
20088
+ const request = (method, params, timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) => new Promise((resolve15, reject) => {
20189
20089
  if (closed) {
20190
20090
  reject(new Error("Codex app-server connection closed"));
20191
20091
  return;
@@ -20203,7 +20103,7 @@ async function openCodexAppServer(opts) {
20203
20103
  pending.delete(id);
20204
20104
  reject(new Error(`Codex app-server ${method} timed out after ${timeoutMs}ms`));
20205
20105
  }, timeoutMs);
20206
- pending.set(id, { resolve: resolve14, reject, timer });
20106
+ pending.set(id, { resolve: resolve15, reject, timer });
20207
20107
  try {
20208
20108
  writeLine({ jsonrpc: "2.0", id, method, params: params ?? {} });
20209
20109
  } catch (err) {
@@ -20215,9 +20115,9 @@ async function openCodexAppServer(opts) {
20215
20115
  const notify = async (method, params) => {
20216
20116
  writeLine({ jsonrpc: "2.0", method, params: params ?? {} });
20217
20117
  };
20218
- const nextNotification = (timeoutMs = 3e4) => new Promise((resolve14, reject) => {
20118
+ const nextNotification = (timeoutMs = 3e4) => new Promise((resolve15, reject) => {
20219
20119
  if (notificationQueue.length) {
20220
- resolve14(notificationQueue.shift());
20120
+ resolve15(notificationQueue.shift());
20221
20121
  return;
20222
20122
  }
20223
20123
  if (readLoopError) {
@@ -20225,16 +20125,16 @@ async function openCodexAppServer(opts) {
20225
20125
  return;
20226
20126
  }
20227
20127
  if (closed) {
20228
- resolve14(null);
20128
+ resolve15(null);
20229
20129
  return;
20230
20130
  }
20231
20131
  const timer = setTimeout(() => {
20232
20132
  const idx = notificationWaiters.findIndex((w2) => w2.timer === timer);
20233
20133
  if (idx >= 0) notificationWaiters.splice(idx, 1);
20234
20134
  if (readLoopError) reject(readLoopError);
20235
- else resolve14(null);
20135
+ else resolve15(null);
20236
20136
  }, timeoutMs);
20237
- notificationWaiters.push({ resolve: resolve14, reject, timer });
20137
+ notificationWaiters.push({ resolve: resolve15, reject, timer });
20238
20138
  });
20239
20139
  child.stdin.on("error", (err) => {
20240
20140
  const publicErr = safePublicError("Codex app-server stdin error", err);
@@ -22071,7 +21971,7 @@ var init_agent_event_mapper2 = __esm({
22071
21971
 
22072
21972
  // ../../packages/claude/src/resolve-sdk-binary.ts
22073
21973
  import { createRequire } from "node:module";
22074
- import { existsSync as existsSync17 } from "node:fs";
21974
+ import { existsSync as existsSync16 } from "node:fs";
22075
21975
  function resolveSdkClaudeBinary() {
22076
21976
  if (cached !== void 0) return cached;
22077
21977
  try {
@@ -22086,7 +21986,7 @@ function resolveSdkClaudeBinary() {
22086
21986
  let p2 = req.resolve(c);
22087
21987
  if (p2.includes("/app.asar/")) p2 = p2.replace("/app.asar/", "/app.asar.unpacked/");
22088
21988
  if (p2.includes("\\app.asar\\")) p2 = p2.replace("\\app.asar\\", "\\app.asar.unpacked\\");
22089
- if (existsSync17(p2)) {
21989
+ if (existsSync16(p2)) {
22090
21990
  cached = p2;
22091
21991
  return p2;
22092
21992
  }
@@ -22299,8 +22199,8 @@ var init_message_bridge = __esm({
22299
22199
  if (this.closed) {
22300
22200
  return Promise.resolve({ value: void 0, done: true });
22301
22201
  }
22302
- return new Promise((resolve14) => {
22303
- this.waiter = { resolve: resolve14 };
22202
+ return new Promise((resolve15) => {
22203
+ this.waiter = { resolve: resolve15 };
22304
22204
  });
22305
22205
  }
22306
22206
  };
@@ -22310,7 +22210,7 @@ var init_message_bridge = __esm({
22310
22210
  });
22311
22211
 
22312
22212
  // ../../packages/claude/src/claude-live-session.ts
22313
- import { existsSync as existsSync18 } from "node:fs";
22213
+ import { existsSync as existsSync17 } from "node:fs";
22314
22214
  import { randomUUID as randomUUID2 } from "node:crypto";
22315
22215
  import { query as sdkQuery2 } from "@anthropic-ai/claude-agent-sdk";
22316
22216
  function buildLiveOptions(opts, onPermission, onQuestion, onPlan, signal, timing, turn) {
@@ -22370,7 +22270,7 @@ function buildLiveOptions(opts, onPermission, onQuestion, onPlan, signal, timing
22370
22270
  if (decision === "allow") return { behavior: "allow" };
22371
22271
  return { behavior: "deny", message: "Permission denied by SuperOne node" };
22372
22272
  };
22373
- const binaryPath = (opts.binaryPath && existsSync18(opts.binaryPath) ? opts.binaryPath : null) ?? resolveSdkClaudeBinary() ?? void 0;
22273
+ const binaryPath = (opts.binaryPath && existsSync17(opts.binaryPath) ? opts.binaryPath : null) ?? resolveSdkClaudeBinary() ?? void 0;
22374
22274
  const effort = opts.effort === "low" || opts.effort === "medium" || opts.effort === "high" || opts.effort === "xhigh" || opts.effort === "max" ? opts.effort : void 0;
22375
22275
  const env = opts.env ? { ...process.env, ...opts.env } : void 0;
22376
22276
  const sandbox = opts.sandboxMode === "on" || opts.sandboxMode === "auto" ? {
@@ -22487,8 +22387,8 @@ var init_claude_live_session = __esm({
22487
22387
  planHandler;
22488
22388
  timing = { pausedMs: 0 };
22489
22389
  static open(opts) {
22490
- const binary = (opts.binaryPath && existsSync18(opts.binaryPath) ? opts.binaryPath : null) ?? resolveSdkClaudeBinary();
22491
- if (opts.binaryPath && !existsSync18(opts.binaryPath)) {
22390
+ const binary = (opts.binaryPath && existsSync17(opts.binaryPath) ? opts.binaryPath : null) ?? resolveSdkClaudeBinary();
22391
+ if (opts.binaryPath && !existsSync17(opts.binaryPath)) {
22492
22392
  throw new Error(`Claude binary not found: ${opts.binaryPath}`);
22493
22393
  }
22494
22394
  if (!binary && !opts.queryFn) {
@@ -22518,7 +22418,7 @@ var init_claude_live_session = __esm({
22518
22418
  const sessionId = this.sdkSessionId || "";
22519
22419
  const priorityNext = input.priorityNext !== false && this.active != null;
22520
22420
  const msg = toUserMessage(input.content, sessionId, priorityNext);
22521
- return new Promise((resolve14, reject) => {
22421
+ return new Promise((resolve15, reject) => {
22522
22422
  if (input.signal?.aborted) {
22523
22423
  reject(new Error("Claude turn interrupted"));
22524
22424
  return;
@@ -22539,10 +22439,10 @@ var init_claude_live_session = __esm({
22539
22439
  };
22540
22440
  input.signal?.addEventListener("abort", onAbort, { once: true });
22541
22441
  if (this.active) {
22542
- this.pending.push({ tag, msg, input, resolve: resolve14, reject });
22442
+ this.pending.push({ tag, msg, input, resolve: resolve15, reject });
22543
22443
  return;
22544
22444
  }
22545
- this.startTurn({ tag, msg, input, resolve: resolve14, reject });
22445
+ this.startTurn({ tag, msg, input, resolve: resolve15, reject });
22546
22446
  });
22547
22447
  }
22548
22448
  async dispose() {
@@ -22742,12 +22642,12 @@ async function fetchClaudeModels(opts) {
22742
22642
  }
22743
22643
  }
22744
22644
  function withTimeout(promise2, ms) {
22745
- return new Promise((resolve14, reject) => {
22645
+ return new Promise((resolve15, reject) => {
22746
22646
  const timer = setTimeout(() => reject(new Error(`claude model probe timed out after ${ms}ms`)), ms);
22747
22647
  promise2.then(
22748
22648
  (v2) => {
22749
22649
  clearTimeout(timer);
22750
- resolve14(v2);
22650
+ resolve15(v2);
22751
22651
  },
22752
22652
  (e) => {
22753
22653
  clearTimeout(timer);
@@ -22768,16 +22668,16 @@ var init_fetch_models = __esm({
22768
22668
  });
22769
22669
 
22770
22670
  // ../../packages/claude/src/fork-session.ts
22771
- import { existsSync as existsSync19, mkdirSync as mkdirSync12, readdirSync as readdirSync6, realpathSync as realpathSync2, renameSync } from "node:fs";
22671
+ import { existsSync as existsSync18, mkdirSync as mkdirSync11, readdirSync as readdirSync6, realpathSync as realpathSync2, renameSync } from "node:fs";
22772
22672
  import { homedir as homedir3 } from "node:os";
22773
- import { join as join17 } from "node:path";
22673
+ import { join as join16 } from "node:path";
22774
22674
  import { forkSession as defaultSdkForkSession } from "@anthropic-ai/claude-agent-sdk";
22775
22675
  function claudeProjectSlug(p2) {
22776
22676
  return p2.replace(/[^a-zA-Z0-9]/g, "-");
22777
22677
  }
22778
22678
  function claudeProjectsDir(configDir) {
22779
- const root = configDir || process.env.CLAUDE_CONFIG_DIR || join17(homedir3(), ".claude");
22780
- return join17(root, "projects");
22679
+ const root = configDir || process.env.CLAUDE_CONFIG_DIR || join16(homedir3(), ".claude");
22680
+ return join16(root, "projects");
22781
22681
  }
22782
22682
  async function forkClaudeTranscript(input) {
22783
22683
  const providerSessionId = input.providerSessionId?.trim();
@@ -22797,13 +22697,13 @@ async function forkClaudeTranscript(input) {
22797
22697
  throw new Error("Claude forkSession did not return a session id");
22798
22698
  }
22799
22699
  const projectsDir = input.projectsDir ?? claudeProjectsDir();
22800
- if (!existsSync19(projectsDir)) {
22700
+ if (!existsSync18(projectsDir)) {
22801
22701
  throw new Error(`Claude projects dir not found: ${projectsDir}`);
22802
22702
  }
22803
22703
  let forkedFile = null;
22804
22704
  for (const dir of readdirSync6(projectsDir)) {
22805
- const candidate = join17(projectsDir, dir, `${newSdkId}.jsonl`);
22806
- if (existsSync19(candidate)) {
22705
+ const candidate = join16(projectsDir, dir, `${newSdkId}.jsonl`);
22706
+ if (existsSync18(candidate)) {
22807
22707
  forkedFile = candidate;
22808
22708
  break;
22809
22709
  }
@@ -22811,9 +22711,9 @@ async function forkClaudeTranscript(input) {
22811
22711
  if (!forkedFile) {
22812
22712
  throw new Error(`forked transcript ${newSdkId}.jsonl not found under ${projectsDir}`);
22813
22713
  }
22814
- const destDir = join17(projectsDir, claudeProjectSlug(realpathSync2(targetCwd)));
22815
- mkdirSync12(destDir, { recursive: true });
22816
- const dest = join17(destDir, `${newSdkId}.jsonl`);
22714
+ const destDir = join16(projectsDir, claudeProjectSlug(realpathSync2(targetCwd)));
22715
+ mkdirSync11(destDir, { recursive: true });
22716
+ const dest = join16(destDir, `${newSdkId}.jsonl`);
22817
22717
  if (dest !== forkedFile) {
22818
22718
  renameSync(forkedFile, dest);
22819
22719
  }
@@ -24566,6 +24466,23 @@ var init_types = __esm({
24566
24466
  }
24567
24467
  });
24568
24468
 
24469
+ // ../../packages/runtime/src/session/runtime-policy.ts
24470
+ function getRuntimeIdleTimeoutMs(activeRuntimeCount) {
24471
+ if (activeRuntimeCount <= 4) return TWENTY_MINUTES_MS;
24472
+ if (activeRuntimeCount <= 8) return TEN_MINUTES_MS;
24473
+ return FIVE_MINUTES_MS;
24474
+ }
24475
+ var SESSION_RUNTIME_REAPER_INTERVAL_MS, TWENTY_MINUTES_MS, TEN_MINUTES_MS, FIVE_MINUTES_MS;
24476
+ var init_runtime_policy = __esm({
24477
+ "../../packages/runtime/src/session/runtime-policy.ts"() {
24478
+ "use strict";
24479
+ SESSION_RUNTIME_REAPER_INTERVAL_MS = 3e4;
24480
+ TWENTY_MINUTES_MS = 20 * 60 * 1e3;
24481
+ TEN_MINUTES_MS = 10 * 60 * 1e3;
24482
+ FIVE_MINUTES_MS = 5 * 60 * 1e3;
24483
+ }
24484
+ });
24485
+
24569
24486
  // ../../packages/runtime/src/session/session-runtime.ts
24570
24487
  import { randomUUID as randomUUID4 } from "node:crypto";
24571
24488
  function redactTaskNotificationForDisplay(content) {
@@ -24674,6 +24591,7 @@ var init_session_runtime = __esm({
24674
24591
  init_miniapp_prompt_tags();
24675
24592
  init_host_action_store();
24676
24593
  init_types();
24594
+ init_runtime_policy();
24677
24595
  init_types();
24678
24596
  DEFAULT_AGENTS_CONFIRM_TIMEOUT_MS = 10 * 6e4;
24679
24597
  SessionRuntime = class {
@@ -24688,6 +24606,13 @@ var init_session_runtime = __esm({
24688
24606
  this.hostActions = opts?.hostActions ?? null;
24689
24607
  this.hydrateFromStore();
24690
24608
  this.reconcileAfterRestart();
24609
+ const runtimeReaperIntervalMs = opts?.runtimeReaperIntervalMs ?? SESSION_RUNTIME_REAPER_INTERVAL_MS;
24610
+ if (runtimeReaperIntervalMs > 0 && this.turnRunner.listActiveRuntimes && this.turnRunner.disposeSession) {
24611
+ this.runtimeReaperTimer = setInterval(() => {
24612
+ void this.reapIdleRuntimes();
24613
+ }, runtimeReaperIntervalMs);
24614
+ this.runtimeReaperTimer.unref?.();
24615
+ }
24691
24616
  if (this.hostActions) {
24692
24617
  this.hostActions.subscribe(() => this.wakeHostActionPollers());
24693
24618
  this.hostActionExpiryTimer = setInterval(() => {
@@ -24720,6 +24645,8 @@ var init_session_runtime = __esm({
24720
24645
  /** Long-poll waiters woken on host action change. */
24721
24646
  hostActionPollWaiters = /* @__PURE__ */ new Set();
24722
24647
  hostActionExpiryTimer = null;
24648
+ runtimeReaperTimer = null;
24649
+ runtimeReleases = /* @__PURE__ */ new Set();
24723
24650
  /**
24724
24651
  * Per-session FIFO of turns accepted while status is streaming for harnesses
24725
24652
  * without a live inject channel (e.g. Codex). Claude uses concurrent
@@ -24737,6 +24664,36 @@ var init_session_runtime = __esm({
24737
24664
  isDisposing() {
24738
24665
  return this.disposing;
24739
24666
  }
24667
+ /** Release idle long-lived harness processes without ending resumable sessions. */
24668
+ async reapIdleRuntimes(now = Date.now()) {
24669
+ if (this.disposing) return;
24670
+ const listActiveRuntimes = this.turnRunner.listActiveRuntimes;
24671
+ const disposeSession = this.turnRunner.disposeSession;
24672
+ if (!listActiveRuntimes || !disposeSession) return;
24673
+ const bySession = /* @__PURE__ */ new Map();
24674
+ for (const entry of listActiveRuntimes()) {
24675
+ const previous = bySession.get(entry.sessionId);
24676
+ bySession.set(entry.sessionId, previous ? {
24677
+ sessionId: entry.sessionId,
24678
+ lastActivityAt: Math.max(previous.lastActivityAt, entry.lastActivityAt),
24679
+ busy: previous.busy || entry.busy
24680
+ } : entry);
24681
+ }
24682
+ if (bySession.size === 0) return;
24683
+ const timeoutMs = getRuntimeIdleTimeoutMs(bySession.size);
24684
+ const releases = [];
24685
+ for (const entry of bySession.values()) {
24686
+ if (entry.busy || now - entry.lastActivityAt < timeoutMs) continue;
24687
+ if (this.runtimeReleases.has(entry.sessionId)) continue;
24688
+ const session = this.live.get(entry.sessionId);
24689
+ if (session?.status === "streaming" || session?.pendingInteraction != null || (this.activeTurnCounts.get(entry.sessionId) ?? 0) > 0) continue;
24690
+ this.runtimeReleases.add(entry.sessionId);
24691
+ releases.push(
24692
+ Promise.resolve().then(() => disposeSession(entry.sessionId)).catch(() => void 0).finally(() => this.runtimeReleases.delete(entry.sessionId))
24693
+ );
24694
+ }
24695
+ await Promise.all(releases);
24696
+ }
24740
24697
  hydrateFromStore() {
24741
24698
  for (const session of this.store.loadAll()) {
24742
24699
  this.live.set(session.sessionId, session);
@@ -25624,7 +25581,7 @@ var init_session_runtime = __esm({
25624
25581
  eventType: SESSION_DURABLE_EVENT.hostActionRequested,
25625
25582
  payload: { actionId: row.actionId }
25626
25583
  });
25627
- return new Promise((resolve14) => {
25584
+ return new Promise((resolve15) => {
25628
25585
  const remaining = Math.max(0, row.deadline - Date.now());
25629
25586
  const timer = setTimeout(() => {
25630
25587
  this.cancelHostActionInternal(row.actionId, "deadline_exceeded");
@@ -25651,7 +25608,7 @@ var init_session_runtime = __esm({
25651
25608
  clearTimeout(timer);
25652
25609
  for (const c of abortCleanups) c();
25653
25610
  this.hostActionWaiters.delete(row.actionId);
25654
- resolve14(result);
25611
+ resolve15(result);
25655
25612
  },
25656
25613
  timer
25657
25614
  });
@@ -25692,14 +25649,14 @@ var init_session_runtime = __esm({
25692
25649
  cursor: existing.length ? existing[existing.length - 1].sequence : this.hostActions.headSequence()
25693
25650
  };
25694
25651
  }
25695
- await new Promise((resolve14) => {
25652
+ await new Promise((resolve15) => {
25696
25653
  let settled = false;
25697
25654
  const done = () => {
25698
25655
  if (settled) return;
25699
25656
  settled = true;
25700
25657
  this.hostActionPollWaiters.delete(done);
25701
25658
  clearTimeout(timer);
25702
- resolve14();
25659
+ resolve15();
25703
25660
  };
25704
25661
  const timer = setTimeout(done, waitMs);
25705
25662
  this.hostActionPollWaiters.add(done);
@@ -25949,7 +25906,7 @@ var init_session_runtime = __esm({
25949
25906
  profiles: input.profiles
25950
25907
  }
25951
25908
  };
25952
- return new Promise((resolve14) => {
25909
+ return new Promise((resolve15) => {
25953
25910
  let settled = false;
25954
25911
  session.pendingInteraction = interaction;
25955
25912
  session.updatedAt = Date.now();
@@ -25983,14 +25940,14 @@ var init_session_runtime = __esm({
25983
25940
  action: result.action
25984
25941
  }
25985
25942
  });
25986
- resolve14({ action: result.action, content: result.content });
25943
+ resolve15({ action: result.action, content: result.content });
25987
25944
  } else {
25988
25945
  this.events.appendSession({
25989
25946
  sessionId: session.sessionId,
25990
25947
  eventType: result.reason === "timeout" ? SESSION_DURABLE_EVENT.permissionTimeout : SESSION_DURABLE_EVENT.permissionAborted,
25991
25948
  payload: { interactionId: interaction.interactionId, decision: "deny" }
25992
25949
  });
25993
- resolve14({ action: "cancel" });
25950
+ resolve15({ action: "cancel" });
25994
25951
  }
25995
25952
  };
25996
25953
  const timer = setTimeout(() => {
@@ -26063,7 +26020,7 @@ var init_session_runtime = __esm({
26063
26020
  if (session.pendingInteraction) {
26064
26021
  this.rejectPendingPermission(session, "aborted");
26065
26022
  }
26066
- return new Promise((resolve14) => {
26023
+ return new Promise((resolve15) => {
26067
26024
  let settled = false;
26068
26025
  session.pendingInteraction = interaction;
26069
26026
  session.updatedAt = Date.now();
@@ -26109,7 +26066,7 @@ var init_session_runtime = __esm({
26109
26066
  payload: { interactionId: interaction.interactionId, decision: "deny" }
26110
26067
  });
26111
26068
  }
26112
- resolve14(result.decision);
26069
+ resolve15(result.decision);
26113
26070
  };
26114
26071
  const timer = setTimeout(() => {
26115
26072
  settle({ decision: "deny", reason: "timeout" });
@@ -26166,7 +26123,7 @@ var init_session_runtime = __esm({
26166
26123
  this.rejectPendingPermission(session, "aborted");
26167
26124
  }
26168
26125
  const pending = { ...interaction, kind: "question" };
26169
- return new Promise((resolve14) => {
26126
+ return new Promise((resolve15) => {
26170
26127
  let settled = false;
26171
26128
  session.pendingInteraction = pending;
26172
26129
  session.updatedAt = Date.now();
@@ -26209,7 +26166,7 @@ var init_session_runtime = __esm({
26209
26166
  payload: { interactionId: pending.interactionId }
26210
26167
  });
26211
26168
  }
26212
- resolve14(result.answers);
26169
+ resolve15(result.answers);
26213
26170
  };
26214
26171
  const timer = setTimeout(() => {
26215
26172
  settle({ answers: {}, reason: "timeout" });
@@ -26237,7 +26194,7 @@ var init_session_runtime = __esm({
26237
26194
  this.rejectPendingPermission(session, "aborted");
26238
26195
  }
26239
26196
  const pending = { ...interaction, kind: "plan" };
26240
- return new Promise((resolve14) => {
26197
+ return new Promise((resolve15) => {
26241
26198
  let settled = false;
26242
26199
  session.pendingInteraction = pending;
26243
26200
  session.updatedAt = Date.now();
@@ -26284,7 +26241,7 @@ var init_session_runtime = __esm({
26284
26241
  payload: { interactionId: pending.interactionId, decision: "reject" }
26285
26242
  });
26286
26243
  }
26287
- resolve14({ decision: result.decision, options: result.options });
26244
+ resolve15({ decision: result.decision, options: result.options });
26288
26245
  };
26289
26246
  const timer = setTimeout(() => {
26290
26247
  settle({ decision: "reject", reason: "timeout" });
@@ -26341,6 +26298,10 @@ var init_session_runtime = __esm({
26341
26298
  */
26342
26299
  async dispose(timeoutMs = 5e3) {
26343
26300
  this.disposing = true;
26301
+ if (this.runtimeReaperTimer) {
26302
+ clearInterval(this.runtimeReaperTimer);
26303
+ this.runtimeReaperTimer = null;
26304
+ }
26344
26305
  if (this.hostActionExpiryTimer) {
26345
26306
  clearInterval(this.hostActionExpiryTimer);
26346
26307
  this.hostActionExpiryTimer = null;
@@ -26366,7 +26327,7 @@ var init_session_runtime = __esm({
26366
26327
  Promise.allSettled(batch).then(() => {
26367
26328
  settled = true;
26368
26329
  }),
26369
- new Promise((resolve14) => setTimeout(resolve14, remaining))
26330
+ new Promise((resolve15) => setTimeout(resolve15, remaining))
26370
26331
  ]);
26371
26332
  if (!settled && Date.now() >= deadline) break;
26372
26333
  }
@@ -26871,9 +26832,9 @@ var init_session_provider_store = __esm({
26871
26832
  });
26872
26833
 
26873
26834
  // ../../packages/runtime/src/session/harness-resources.ts
26874
- import { existsSync as existsSync20, readdirSync as readdirSync7, readFileSync as readFileSync14 } from "node:fs";
26875
- import { join as join18 } from "node:path";
26876
- import { homedir as osHomedir9 } from "node:os";
26835
+ import { existsSync as existsSync19, readdirSync as readdirSync7, readFileSync as readFileSync13 } from "node:fs";
26836
+ import { join as join17 } from "node:path";
26837
+ import { homedir as osHomedir8 } from "node:os";
26877
26838
  function emptyClaude() {
26878
26839
  return {
26879
26840
  models: [],
@@ -26896,15 +26857,15 @@ function emptyAcp() {
26896
26857
  }
26897
26858
  function safeRead2(path) {
26898
26859
  try {
26899
- return readFileSync14(path, "utf-8");
26860
+ return readFileSync13(path, "utf-8");
26900
26861
  } catch {
26901
26862
  return "";
26902
26863
  }
26903
26864
  }
26904
26865
  function discoverCodexUserPrompts(opts) {
26905
- const home = opts?.homeDir ?? osHomedir9();
26906
- const dir = join18(home, ".codex", "prompts");
26907
- if (!existsSync20(dir)) return [];
26866
+ const home = opts?.homeDir ?? osHomedir8();
26867
+ const dir = join17(home, ".codex", "prompts");
26868
+ if (!existsSync19(dir)) return [];
26908
26869
  let ents;
26909
26870
  try {
26910
26871
  ents = readdirSync7(dir, { withFileTypes: true });
@@ -26915,7 +26876,7 @@ function discoverCodexUserPrompts(opts) {
26915
26876
  for (const ent of ents) {
26916
26877
  if (!ent.isFile() || !ent.name.endsWith(".md")) continue;
26917
26878
  const name = ent.name.replace(/\.md$/, "");
26918
- const content = safeRead2(join18(dir, ent.name));
26879
+ const content = safeRead2(join17(dir, ent.name));
26919
26880
  const fm = parseSimpleFrontmatter(content);
26920
26881
  out.push({
26921
26882
  name,
@@ -27030,6 +26991,7 @@ var init_session = __esm({
27030
26991
  "../../packages/runtime/src/session/index.ts"() {
27031
26992
  "use strict";
27032
26993
  init_session_runtime();
26994
+ init_runtime_policy();
27033
26995
  init_event_log();
27034
26996
  init_message_catalog();
27035
26997
  init_sqlite_session_store();
@@ -30851,7 +30813,7 @@ function requireInboundAuth(req, res) {
30851
30813
  return false;
30852
30814
  }
30853
30815
  function readBody(req) {
30854
- return new Promise((resolve14, reject) => {
30816
+ return new Promise((resolve15, reject) => {
30855
30817
  const chunks = [];
30856
30818
  let total = 0;
30857
30819
  req.on("data", (chunk) => {
@@ -30863,7 +30825,7 @@ function readBody(req) {
30863
30825
  }
30864
30826
  chunks.push(chunk);
30865
30827
  });
30866
- req.on("end", () => resolve14(Buffer.concat(chunks)));
30828
+ req.on("end", () => resolve15(Buffer.concat(chunks)));
30867
30829
  req.on("error", reject);
30868
30830
  });
30869
30831
  }
@@ -30893,7 +30855,7 @@ async function writeWebResponse(res, web) {
30893
30855
  if (done) break;
30894
30856
  if (value) {
30895
30857
  if (!res.write(Buffer.from(value))) {
30896
- await new Promise((resolve14) => res.once("drain", resolve14));
30858
+ await new Promise((resolve15) => res.once("drain", resolve15));
30897
30859
  }
30898
30860
  }
30899
30861
  }
@@ -30971,15 +30933,15 @@ async function startLlmProxyServer(upstream, port) {
30971
30933
  }
30972
30934
  }
30973
30935
  });
30974
- await new Promise((resolve14, reject) => {
30936
+ await new Promise((resolve15, reject) => {
30975
30937
  server.once("error", reject);
30976
- server.listen(port, "127.0.0.1", () => resolve14());
30938
+ server.listen(port, "127.0.0.1", () => resolve15());
30977
30939
  });
30978
30940
  return {
30979
30941
  port,
30980
30942
  url: `http://127.0.0.1:${port}`,
30981
- close: () => new Promise((resolve14, reject) => {
30982
- server.close((err) => err ? reject(err) : resolve14());
30943
+ close: () => new Promise((resolve15, reject) => {
30944
+ server.close((err) => err ? reject(err) : resolve15());
30983
30945
  })
30984
30946
  };
30985
30947
  }
@@ -31001,7 +30963,7 @@ function upstreamKey(u) {
31001
30963
  return createHash3("sha256").update(JSON.stringify(u)).digest("hex").slice(0, 16);
31002
30964
  }
31003
30965
  async function getFreePort() {
31004
- return new Promise((resolve14, reject) => {
30966
+ return new Promise((resolve15, reject) => {
31005
30967
  const server = net.createServer();
31006
30968
  server.unref();
31007
30969
  server.on("error", reject);
@@ -31009,7 +30971,7 @@ async function getFreePort() {
31009
30971
  const addr = server.address();
31010
30972
  if (typeof addr === "object" && addr) {
31011
30973
  const { port } = addr;
31012
- server.close(() => resolve14(port));
30974
+ server.close(() => resolve15(port));
31013
30975
  } else {
31014
30976
  server.close(() => reject(new Error("no address")));
31015
30977
  }
@@ -31282,14 +31244,14 @@ var init_resolve_service = __esm({
31282
31244
  });
31283
31245
 
31284
31246
  // ../../packages/shared/src/attachment-store.ts
31285
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync10 } from "node:fs";
31247
+ import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync9 } from "node:fs";
31286
31248
  import { tmpdir } from "node:os";
31287
- import { join as join19 } from "node:path";
31249
+ import { join as join18 } from "node:path";
31288
31250
  import { randomUUID as randomUUID7 } from "node:crypto";
31289
31251
  function resolveAttachmentsDir() {
31290
31252
  const override = process.env.SUPERONE_ATTACHMENTS_DIR?.trim();
31291
31253
  if (override) return override;
31292
- return join19(tmpdir(), SUPERONE_ATTACHMENTS_DIR_NAME);
31254
+ return join18(tmpdir(), SUPERONE_ATTACHMENTS_DIR_NAME);
31293
31255
  }
31294
31256
  function extForAttachmentMime(mimeType) {
31295
31257
  const m2 = mimeType.toLowerCase();
@@ -31324,10 +31286,10 @@ function persistAttachment(base643, mimeType, opts) {
31324
31286
  if (!buf) return null;
31325
31287
  try {
31326
31288
  const dir = resolveAttachmentsDir();
31327
- mkdirSync13(dir, { recursive: true });
31289
+ mkdirSync12(dir, { recursive: true });
31328
31290
  const fileName = `${randomUUID7()}-${safeFileBase(opts?.name, mimeType)}`;
31329
- const filePath = join19(dir, fileName);
31330
- writeFileSync10(filePath, buf);
31291
+ const filePath = join18(dir, fileName);
31292
+ writeFileSync9(filePath, buf);
31331
31293
  return filePath;
31332
31294
  } catch {
31333
31295
  return null;
@@ -31409,11 +31371,11 @@ var init_turn_attachments = __esm({
31409
31371
  });
31410
31372
 
31411
31373
  // src/session/claude-turn-runner.ts
31412
- import { existsSync as existsSync21 } from "node:fs";
31374
+ import { existsSync as existsSync20 } from "node:fs";
31413
31375
  function resolveClaudeBinaryPath(opts) {
31414
- if (opts.binaryPath && existsSync21(opts.binaryPath)) return opts.binaryPath;
31376
+ if (opts.binaryPath && existsSync20(opts.binaryPath)) return opts.binaryPath;
31415
31377
  const status = opts.harnesses?.get("claude");
31416
- if (status?.enabled && (status.state === "ready" || status.state === "needs_auth") && status.command && existsSync21(status.command)) {
31378
+ if (status?.enabled && (status.state === "ready" || status.state === "needs_auth") && status.command && existsSync20(status.command)) {
31417
31379
  return status.command;
31418
31380
  }
31419
31381
  if (!opts.skipSdkBinary) {
@@ -31421,7 +31383,7 @@ function resolveClaudeBinaryPath(opts) {
31421
31383
  if (sdk) return sdk;
31422
31384
  }
31423
31385
  const fromEnv = process.env.SUPERONE_CLAUDE_BINARY?.trim();
31424
- if (fromEnv && existsSync21(fromEnv)) return fromEnv;
31386
+ if (fromEnv && existsSync20(fromEnv)) return fromEnv;
31425
31387
  return null;
31426
31388
  }
31427
31389
  function isClaudeRuntimeRunnable() {
@@ -31467,6 +31429,7 @@ function createNodeClaudeTurnRunner(opts) {
31467
31429
  await entry.hostActionDispose?.().catch(() => void 0);
31468
31430
  };
31469
31431
  const mcpDiskKeyOf = (diskNames) => [...diskNames].sort().join("\0");
31432
+ const additionalDirsKeyOf = (dirs) => [...new Set(dirs ?? [])].sort().join("\0");
31470
31433
  const runner = async (input) => {
31471
31434
  const harnessId = input.session.harnessId || "claude";
31472
31435
  if (harnessId !== "claude") {
@@ -31520,8 +31483,9 @@ function createNodeClaudeTurnRunner(opts) {
31520
31483
  homeDir: opts.homeDir
31521
31484
  });
31522
31485
  const nextMcpDiskKey = mcpDiskKeyOf(mergedProbe.diskNames);
31486
+ const nextAdditionalDirsKey = additionalDirsKeyOf(input.additionalDirectories?.filter(Boolean));
31523
31487
  let entry = lives.get(sessionKey);
31524
- if (entry && (entry.cwd !== cwd || entry.mcpDiskKey !== nextMcpDiskKey)) {
31488
+ if (entry && (entry.cwd !== cwd || entry.mcpDiskKey !== nextMcpDiskKey || entry.additionalDirsKey !== nextAdditionalDirsKey)) {
31525
31489
  await entry.live.dispose().catch(() => void 0);
31526
31490
  await entry.hostActionDispose?.().catch(() => void 0);
31527
31491
  lives.delete(sessionKey);
@@ -31561,14 +31525,20 @@ function createNodeClaudeTurnRunner(opts) {
31561
31525
  live,
31562
31526
  hostActionDispose: hostActionMcp ? () => hostActionMcp.dispose() : null,
31563
31527
  cwd,
31564
- mcpDiskKey: mcpDiskKeyOf(merged.diskNames)
31528
+ mcpDiskKey: mcpDiskKeyOf(merged.diskNames),
31529
+ additionalDirsKey: additionalDirsKeyOf(input.additionalDirectories?.filter(Boolean)),
31530
+ busyCount: 0,
31531
+ lastActivityAt: Date.now()
31565
31532
  };
31566
31533
  lives.set(sessionKey, entry);
31567
31534
  }
31568
31535
  const prepared = prepareTurnPrompt(input.text, cwd, input.images);
31569
31536
  const content = prepared.kind === "text" ? prepared.text : prepared.content;
31537
+ const activeEntry = entry;
31538
+ activeEntry.busyCount += 1;
31539
+ activeEntry.lastActivityAt = Date.now();
31570
31540
  try {
31571
- const result = await entry.live.sendTurn({
31541
+ const result = await activeEntry.live.sendTurn({
31572
31542
  content,
31573
31543
  messageId: input.messageId,
31574
31544
  clientMessageId: input.messageId,
@@ -31613,6 +31583,9 @@ function createNodeClaudeTurnRunner(opts) {
31613
31583
  } catch (err) {
31614
31584
  await disposeEntry(sessionKey);
31615
31585
  throw err;
31586
+ } finally {
31587
+ activeEntry.busyCount = Math.max(0, activeEntry.busyCount - 1);
31588
+ activeEntry.lastActivityAt = Date.now();
31616
31589
  }
31617
31590
  };
31618
31591
  runner.disposeSession = async (sessionId) => {
@@ -31622,6 +31595,11 @@ function createNodeClaudeTurnRunner(opts) {
31622
31595
  const keys = [...lives.keys()];
31623
31596
  await Promise.all(keys.map((id) => disposeEntry(id)));
31624
31597
  };
31598
+ runner.listActiveRuntimes = () => [...lives.entries()].map(([sessionId, entry]) => ({
31599
+ sessionId,
31600
+ lastActivityAt: entry.lastActivityAt,
31601
+ busy: entry.busyCount > 0
31602
+ }));
31625
31603
  return runner;
31626
31604
  }
31627
31605
  var CLAUDE_SESSION_RESUME_PREFIX;
@@ -48894,11 +48872,11 @@ var init_jsonrpc = __esm({
48894
48872
  const id = this.nextRequestId++;
48895
48873
  let cancel = () => {
48896
48874
  };
48897
- const response = new Promise((resolve14, reject) => {
48875
+ const response = new Promise((resolve15, reject) => {
48898
48876
  const pendingResponse = {
48899
48877
  resolve: (value) => {
48900
48878
  try {
48901
- resolve14(mapResponse ? mapResponse(value) : value);
48879
+ resolve15(mapResponse ? mapResponse(value) : value);
48902
48880
  } catch (error51) {
48903
48881
  reject(error51);
48904
48882
  }
@@ -48955,8 +48933,8 @@ var init_jsonrpc = __esm({
48955
48933
  this.stream = stream;
48956
48934
  this.staticHandlers = handlers;
48957
48935
  this.allowBatches = options?.allowBatches ?? true;
48958
- this.closedPromise = new Promise((resolve14) => {
48959
- this.abortController.signal.addEventListener("abort", () => resolve14());
48936
+ this.closedPromise = new Promise((resolve15) => {
48937
+ this.abortController.signal.addEventListener("abort", () => resolve15());
48960
48938
  });
48961
48939
  void this.receive();
48962
48940
  }
@@ -49960,8 +49938,8 @@ var init_acp = __esm({
49960
49938
  if (this.failed) {
49961
49939
  return Promise.reject(this.failure);
49962
49940
  }
49963
- return new Promise((resolve14, reject) => {
49964
- this.waiters.push({ resolve: resolve14, reject });
49941
+ return new Promise((resolve15, reject) => {
49942
+ this.waiters.push({ resolve: resolve15, reject });
49965
49943
  });
49966
49944
  }
49967
49945
  };
@@ -51603,6 +51581,30 @@ var init_session_archive_result_shape = __esm({
51603
51581
  }
51604
51582
  });
51605
51583
 
51584
+ // ../../packages/shared/src/computer-use-result-shape.ts
51585
+ function isComputerUseToolName(toolName) {
51586
+ if (!toolName) return false;
51587
+ return /(?:^|__)computer_(?:snapshot|observe|query|act|apps|zoom|wait_for)$/.test(toolName);
51588
+ }
51589
+ function isComputerUseRoot(value) {
51590
+ if (typeof value !== "object" || value === null) return false;
51591
+ const root = value;
51592
+ return typeof root.app === "string" && typeof root.bundleId === "string";
51593
+ }
51594
+ function looksLikeComputerUseResult(obj) {
51595
+ const stateId = typeof obj.stateId === "string" ? obj.stateId : obj.successorStateId;
51596
+ if (typeof stateId !== "string") return false;
51597
+ return typeof obj.outline === "string" || typeof obj.subtree === "string" || typeof obj.element === "string" || Array.isArray(obj.matches) || isComputerUseRoot(obj.root) || isComputerUseRoot(obj.successorRoot);
51598
+ }
51599
+ function looksLikeComputerUseOutline(summary) {
51600
+ return /outline\[\d+\]\{ref,depth/.test(summary);
51601
+ }
51602
+ var init_computer_use_result_shape = __esm({
51603
+ "../../packages/shared/src/computer-use-result-shape.ts"() {
51604
+ "use strict";
51605
+ }
51606
+ });
51607
+
51606
51608
  // ../../packages/acp/src/tool-result-map.ts
51607
51609
  function formatAcpRawOutput(raw) {
51608
51610
  return formatAgentToolOutput(raw);
@@ -51706,11 +51708,13 @@ function shouldKeepFullToolResult(summary, toolName) {
51706
51708
  if (isCollabToolName(toolName)) return true;
51707
51709
  if (isSessionArchiveToolName(toolName)) return true;
51708
51710
  if (looksLikeSessionArchiveToon(summary)) return true;
51711
+ if (isComputerUseToolName(toolName)) return true;
51712
+ if (looksLikeComputerUseOutline(summary)) return true;
51709
51713
  const trimmed = summary.trim();
51710
51714
  if (!trimmed.startsWith("{")) return false;
51711
51715
  try {
51712
51716
  const obj = JSON.parse(trimmed);
51713
- return typeof obj.widget_code === "string" && obj.widget_code.length > 0 || looksLikeCollabResult(obj) || looksLikeSessionArchiveJson(obj);
51717
+ return typeof obj.widget_code === "string" && obj.widget_code.length > 0 || looksLikeCollabResult(obj) || looksLikeSessionArchiveJson(obj) || looksLikeComputerUseResult(obj);
51714
51718
  } catch {
51715
51719
  return false;
51716
51720
  }
@@ -51723,6 +51727,7 @@ var init_tool_result_map = __esm({
51723
51727
  "use strict";
51724
51728
  init_capability_prompt_tags();
51725
51729
  init_session_archive_result_shape();
51730
+ init_computer_use_result_shape();
51726
51731
  init_tool_ui();
51727
51732
  init_tool_normalization();
51728
51733
  }
@@ -51763,7 +51768,7 @@ var init_acp_goal = __esm({
51763
51768
 
51764
51769
  // ../../packages/acp/src/xai-state.ts
51765
51770
  import { homedir as homedir4 } from "node:os";
51766
- import { join as join20 } from "node:path";
51771
+ import { join as join19 } from "node:path";
51767
51772
  function skipEventSeqDedup(kind) {
51768
51773
  return kind === "workflow_updated" || !!kind && SUBAGENT_LIFECYCLE.has(kind);
51769
51774
  }
@@ -51799,7 +51804,7 @@ function resetTurnTokens(state) {
51799
51804
  }
51800
51805
  function resolveGrokChildChatHistoryPath(cwd, childSessionId) {
51801
51806
  if (!cwd || !childSessionId) return void 0;
51802
- return join20(homedir4(), ".grok", "sessions", encodeURIComponent(cwd), childSessionId, "chat_history.jsonl");
51807
+ return join19(homedir4(), ".grok", "sessions", encodeURIComponent(cwd), childSessionId, "chat_history.jsonl");
51803
51808
  }
51804
51809
  function noteSubagentOutputFile(state, subagentId, childSessionId) {
51805
51810
  const existing = state.subagentOutputById.get(subagentId);
@@ -53467,7 +53472,7 @@ async function stopProcess(child, closed) {
53467
53472
  signalProcess(child, "SIGTERM");
53468
53473
  const stopped = await Promise.race([
53469
53474
  closed.then(() => true),
53470
- new Promise((resolve14) => setTimeout(() => resolve14(false), KILL_ESCALATE_MS))
53475
+ new Promise((resolve15) => setTimeout(() => resolve15(false), KILL_ESCALATE_MS))
53471
53476
  ]);
53472
53477
  if (stopped) return;
53473
53478
  signalProcess(child, "SIGKILL");
@@ -53499,9 +53504,9 @@ function spawnAcpProcess(launch2) {
53499
53504
  const output = Writable.toWeb(stdin);
53500
53505
  const input = Readable.toWeb(stdout);
53501
53506
  const stream = ndJsonStream2(output, input);
53502
- const closed = new Promise((resolve14) => {
53507
+ const closed = new Promise((resolve15) => {
53503
53508
  child.once("exit", (code, signal) => {
53504
- resolve14({ code, signal, stderr: stderrChunks.join("") });
53509
+ resolve15({ code, signal, stderr: stderrChunks.join("") });
53505
53510
  });
53506
53511
  });
53507
53512
  let killPromise = null;
@@ -53684,7 +53689,7 @@ var init_run_turn = __esm({
53684
53689
  });
53685
53690
 
53686
53691
  // ../../packages/acp/src/simulated-runner.ts
53687
- import { existsSync as existsSync22 } from "node:fs";
53692
+ import { existsSync as existsSync21 } from "node:fs";
53688
53693
  function createSimulatedAcpTurnRunner(opts) {
53689
53694
  return createSimulatedTurnRunner({
53690
53695
  delayMs: opts?.delayMs ?? 15,
@@ -53698,7 +53703,7 @@ function resolveLaunch(opts) {
53698
53703
  const fromEnv = process.env.SUPERONE_ACP_BINARY?.trim() || process.env.SUPERONE_ACP_COMMAND?.trim() || opts.binaryPath?.trim();
53699
53704
  if (!fromEnv) return null;
53700
53705
  if (fromEnv.includes("/") || fromEnv.includes("\\")) {
53701
- if (!existsSync22(fromEnv)) return null;
53706
+ if (!existsSync21(fromEnv)) return null;
53702
53707
  }
53703
53708
  return {
53704
53709
  command: fromEnv,
@@ -53762,7 +53767,7 @@ var init_serverSentEvents_gen = __esm({
53762
53767
  "../../node_modules/@opencode-ai/sdk/dist/v2/gen/core/serverSentEvents.gen.js"() {
53763
53768
  createSseClient = ({ onRequest, onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url: url2, ...options }) => {
53764
53769
  let lastEventId;
53765
- const sleep = sseSleepFn ?? ((ms) => new Promise((resolve14) => setTimeout(resolve14, ms)));
53770
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve15) => setTimeout(resolve15, ms)));
53766
53771
  const createStream = async function* () {
53767
53772
  let retryDelay = sseDefaultRetryDelay ?? 3e3;
53768
53773
  let attempt = 0;
@@ -59340,12 +59345,12 @@ var require_isexe = __commonJS({
59340
59345
  if (typeof Promise !== "function") {
59341
59346
  throw new TypeError("callback not provided");
59342
59347
  }
59343
- return new Promise(function(resolve14, reject) {
59348
+ return new Promise(function(resolve15, reject) {
59344
59349
  isexe(path, options || {}, function(er, is) {
59345
59350
  if (er) {
59346
59351
  reject(er);
59347
59352
  } else {
59348
- resolve14(is);
59353
+ resolve15(is);
59349
59354
  }
59350
59355
  });
59351
59356
  });
@@ -59411,27 +59416,27 @@ var require_which = __commonJS({
59411
59416
  opt = {};
59412
59417
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
59413
59418
  const found = [];
59414
- const step = (i) => new Promise((resolve14, reject) => {
59419
+ const step = (i) => new Promise((resolve15, reject) => {
59415
59420
  if (i === pathEnv.length)
59416
- return opt.all && found.length ? resolve14(found) : reject(getNotFoundError(cmd));
59421
+ return opt.all && found.length ? resolve15(found) : reject(getNotFoundError(cmd));
59417
59422
  const ppRaw = pathEnv[i];
59418
59423
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
59419
59424
  const pCmd = path.join(pathPart, cmd);
59420
59425
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
59421
- resolve14(subStep(p2, i, 0));
59426
+ resolve15(subStep(p2, i, 0));
59422
59427
  });
59423
- const subStep = (p2, i, ii) => new Promise((resolve14, reject) => {
59428
+ const subStep = (p2, i, ii) => new Promise((resolve15, reject) => {
59424
59429
  if (ii === pathExt.length)
59425
- return resolve14(step(i + 1));
59430
+ return resolve15(step(i + 1));
59426
59431
  const ext = pathExt[ii];
59427
59432
  isexe(p2 + ext, { pathExt: pathExtExe }, (er, is) => {
59428
59433
  if (!er && is) {
59429
59434
  if (opt.all)
59430
59435
  found.push(p2 + ext);
59431
59436
  else
59432
- return resolve14(p2 + ext);
59437
+ return resolve15(p2 + ext);
59433
59438
  }
59434
- return resolve14(subStep(p2, i, ii + 1));
59439
+ return resolve15(subStep(p2, i, ii + 1));
59435
59440
  });
59436
59441
  });
59437
59442
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -60140,24 +60145,24 @@ var init_parse4 = __esm({
60140
60145
 
60141
60146
  // ../../packages/opencode/src/server.ts
60142
60147
  import { spawn as spawn3 } from "node:child_process";
60143
- import { existsSync as existsSync23 } from "node:fs";
60148
+ import { existsSync as existsSync22 } from "node:fs";
60144
60149
  import { homedir as homedir5 } from "node:os";
60145
- import { delimiter, join as join21 } from "node:path";
60150
+ import { delimiter, join as join20 } from "node:path";
60146
60151
  function appendOutput(current, chunk) {
60147
60152
  const next = current + chunk.toString();
60148
60153
  return next.length <= maxServerOutput ? next : next.slice(-maxServerOutput);
60149
60154
  }
60150
60155
  function defaultOpenCodeBinaryPath() {
60151
60156
  const filename = process.platform === "win32" ? "opencode.exe" : "opencode";
60152
- const installed = join21(homedir5(), ".opencode", "bin", filename);
60153
- return existsSync23(installed) ? installed : filename;
60157
+ const installed = join20(homedir5(), ".opencode", "bin", filename);
60158
+ return existsSync22(installed) ? installed : filename;
60154
60159
  }
60155
60160
  function openCodePath(pathEnv) {
60156
60161
  const home = homedir5();
60157
60162
  const paths = [
60158
- join21(home, ".opencode", "bin"),
60159
- join21(home, ".local", "bin"),
60160
- join21(home, ".bun", "bin"),
60163
+ join20(home, ".opencode", "bin"),
60164
+ join20(home, ".local", "bin"),
60165
+ join20(home, ".bun", "bin"),
60161
60166
  "/opt/homebrew/bin",
60162
60167
  "/usr/local/bin",
60163
60168
  ...(pathEnv ?? "").split(delimiter)
@@ -60182,7 +60187,7 @@ async function stopChild(child, exited) {
60182
60187
  signalChild(child, "SIGTERM");
60183
60188
  const stopped = await Promise.race([
60184
60189
  exited.then(() => true),
60185
- new Promise((resolve14) => setTimeout(() => resolve14(false), 1500))
60190
+ new Promise((resolve15) => setTimeout(() => resolve15(false), 1500))
60186
60191
  ]);
60187
60192
  if (stopped) return;
60188
60193
  signalChild(child, "SIGKILL");
@@ -60190,7 +60195,7 @@ async function stopChild(child, exited) {
60190
60195
  }
60191
60196
  async function waitForServer(child, exited, timeoutMs, signal) {
60192
60197
  let output = "";
60193
- return new Promise((resolve14, reject) => {
60198
+ return new Promise((resolve15, reject) => {
60194
60199
  let settled = false;
60195
60200
  const finish = (error51, url2) => {
60196
60201
  if (settled) return;
@@ -60200,7 +60205,7 @@ async function waitForServer(child, exited, timeoutMs, signal) {
60200
60205
  child.stderr.off("data", onData);
60201
60206
  signal?.removeEventListener("abort", onAbort);
60202
60207
  if (error51) reject(error51);
60203
- else resolve14(url2);
60208
+ else resolve15(url2);
60204
60209
  };
60205
60210
  const onData = (chunk) => {
60206
60211
  output = appendOutput(output, chunk);
@@ -60236,12 +60241,12 @@ async function startOpenCodeServer(opts) {
60236
60241
  env: buildOpenCodeServeEnv(opts.env),
60237
60242
  stdio: "pipe"
60238
60243
  });
60239
- const exited = new Promise((resolve14) => {
60244
+ const exited = new Promise((resolve15) => {
60240
60245
  let settled = false;
60241
60246
  const finish = (code, signal) => {
60242
60247
  if (settled) return;
60243
60248
  settled = true;
60244
- resolve14({ code, signal });
60249
+ resolve15({ code, signal });
60245
60250
  };
60246
60251
  child.once("exit", finish);
60247
60252
  child.once("close", finish);
@@ -60266,7 +60271,7 @@ function isOpenCodeBinaryRunnable(binaryPath) {
60266
60271
  const fromEnv = process.env.SUPERONE_OPENCODE_BINARY?.trim();
60267
60272
  const candidate = binaryPath?.trim() || fromEnv;
60268
60273
  if (!candidate) return false;
60269
- return existsSync23(candidate);
60274
+ return existsSync22(candidate);
60270
60275
  }
60271
60276
  var OPENCODE_SERVE_ARGS, maxServerOutput;
60272
60277
  var init_server3 = __esm({
@@ -60617,9 +60622,9 @@ var init_cursor_sdk_available = __esm({
60617
60622
  });
60618
60623
 
60619
60624
  // ../../packages/cursor/src/cursor-platform-binaries.ts
60620
- import { existsSync as existsSync24, statSync as statSync5 } from "node:fs";
60625
+ import { existsSync as existsSync23, statSync as statSync5 } from "node:fs";
60621
60626
  import { createRequire as createRequire3 } from "node:module";
60622
- import { dirname as dirname13, join as join22 } from "node:path";
60627
+ import { dirname as dirname12, join as join21 } from "node:path";
60623
60628
  function cursorPlatformPackageName(platform2 = process.platform, arch2 = process.arch) {
60624
60629
  return `@cursor/sdk-${platform2}-${arch2}`;
60625
60630
  }
@@ -60648,7 +60653,7 @@ function resolveCursorPlatformRoot() {
60648
60653
  const req = cursorSdkRequire();
60649
60654
  try {
60650
60655
  const pkgJson = toUnpackedAsarPath(req.resolve(`${name}/package.json`));
60651
- return existsSync24(pkgJson) ? dirname13(pkgJson) : null;
60656
+ return existsSync23(pkgJson) ? dirname12(pkgJson) : null;
60652
60657
  } catch {
60653
60658
  return null;
60654
60659
  }
@@ -60659,20 +60664,20 @@ function platformBinName(base) {
60659
60664
  function resolveCursorSandboxBinary() {
60660
60665
  const root = resolveCursorPlatformRoot();
60661
60666
  if (!root) return null;
60662
- const bin = join22(root, "bin", platformBinName("cursorsandbox"));
60667
+ const bin = join21(root, "bin", platformBinName("cursorsandbox"));
60663
60668
  return isExecutableFile(bin) ? bin : null;
60664
60669
  }
60665
60670
  function resolveCursorRipgrepBinary() {
60666
60671
  const root = resolveCursorPlatformRoot();
60667
60672
  if (!root) return null;
60668
- const bin = join22(root, "bin", platformBinName("rg"));
60673
+ const bin = join21(root, "bin", platformBinName("rg"));
60669
60674
  return isExecutableFile(bin) ? bin : null;
60670
60675
  }
60671
60676
  function resolveCursorTreeSitterVendorDir() {
60672
60677
  const root = resolveCursorPlatformRoot();
60673
60678
  if (!root) return null;
60674
- const vendor = join22(root, "vendor");
60675
- return existsSync24(join22(vendor, "tree-sitter", "index.js")) ? vendor : null;
60679
+ const vendor = join21(root, "vendor");
60680
+ return existsSync23(join21(vendor, "tree-sitter", "index.js")) ? vendor : null;
60676
60681
  }
60677
60682
  function sandboxExecAvailable() {
60678
60683
  try {
@@ -60714,7 +60719,7 @@ function beginPlatformLookup() {
60714
60719
  if (lookupDepth === 0) {
60715
60720
  savedArgv1 = process.argv[1];
60716
60721
  const root = resolveCursorPlatformRoot();
60717
- if (root) process.argv[1] = join22(root, "package.json");
60722
+ if (root) process.argv[1] = join21(root, "package.json");
60718
60723
  primeHelperEnv();
60719
60724
  }
60720
60725
  lookupDepth += 1;
@@ -61361,9 +61366,9 @@ var init_cursor_event_map = __esm({
61361
61366
 
61362
61367
  // ../../packages/cursor/src/cursor-store.ts
61363
61368
  import Database2 from "better-sqlite3";
61364
- import { mkdirSync as mkdirSync14 } from "node:fs";
61369
+ import { mkdirSync as mkdirSync13 } from "node:fs";
61365
61370
  import { createHash as createHash4 } from "node:crypto";
61366
- import { join as join23 } from "node:path";
61371
+ import { join as join22 } from "node:path";
61367
61372
  function workspaceHash(workspaceRef) {
61368
61373
  return createHash4("md5").update(workspaceRef).digest("hex");
61369
61374
  }
@@ -61406,7 +61411,7 @@ var init_cursor_store = __esm({
61406
61411
  runEvents;
61407
61412
  db;
61408
61413
  constructor(dbPath) {
61409
- mkdirSync14(join23(dbPath, ".."), { recursive: true });
61414
+ mkdirSync13(join22(dbPath, ".."), { recursive: true });
61410
61415
  this.db = new Database2(dbPath);
61411
61416
  this.db.pragma("journal_mode = WAL");
61412
61417
  this.migrate();
@@ -61416,9 +61421,9 @@ var init_cursor_store = __esm({
61416
61421
  this.runEvents = this.createRunEvents();
61417
61422
  }
61418
61423
  static openForWorkspace(userDataRoot, workspaceRef) {
61419
- const dir = join23(userDataRoot, "cursor-sdk", workspaceHash(workspaceRef));
61420
- mkdirSync14(dir, { recursive: true });
61421
- return new _BetterSqliteLocalAgentStore(join23(dir, "agent-store.db"));
61424
+ const dir = join22(userDataRoot, "cursor-sdk", workspaceHash(workspaceRef));
61425
+ mkdirSync13(dir, { recursive: true });
61426
+ return new _BetterSqliteLocalAgentStore(join22(dir, "agent-store.db"));
61422
61427
  }
61423
61428
  dispose() {
61424
61429
  this.db.close();
@@ -61941,8 +61946,8 @@ function isCursorRetryableNetworkError(error51) {
61941
61946
  return Boolean(error51.isRetryable);
61942
61947
  }
61943
61948
  function defaultSleep(ms) {
61944
- return new Promise((resolve14) => {
61945
- setTimeout(resolve14, ms);
61949
+ return new Promise((resolve15) => {
61950
+ setTimeout(resolve15, ms);
61946
61951
  });
61947
61952
  }
61948
61953
  async function withCursorNetworkRetries(fn, opts) {
@@ -62858,7 +62863,7 @@ var init_codex_live_turn = __esm({
62858
62863
  });
62859
62864
 
62860
62865
  // src/session/codex-turn-runner.ts
62861
- import { existsSync as existsSync25 } from "node:fs";
62866
+ import { existsSync as existsSync24 } from "node:fs";
62862
62867
  function mapCodexReasoningEffort(effort) {
62863
62868
  if (!effort) return void 0;
62864
62869
  const e = effort.trim().toLowerCase();
@@ -62868,18 +62873,18 @@ function mapCodexReasoningEffort(effort) {
62868
62873
  return void 0;
62869
62874
  }
62870
62875
  function resolveCodexBinaryPath(opts) {
62871
- if (opts.binaryPath && existsSync25(opts.binaryPath)) return opts.binaryPath;
62876
+ if (opts.binaryPath && existsSync24(opts.binaryPath)) return opts.binaryPath;
62872
62877
  const fromEnv = process.env.SUPERONE_CODEX_BINARY?.trim();
62873
- if (fromEnv && existsSync25(fromEnv)) return fromEnv;
62878
+ if (fromEnv && existsSync24(fromEnv)) return fromEnv;
62874
62879
  const status = opts.harnesses?.get("codex");
62875
- if (status?.enabled && (status.state === "ready" || status.state === "needs_auth") && status.command && existsSync25(status.command)) {
62880
+ if (status?.enabled && (status.state === "ready" || status.state === "needs_auth") && status.command && existsSync24(status.command)) {
62876
62881
  return status.command;
62877
62882
  }
62878
62883
  return null;
62879
62884
  }
62880
62885
  function isCodexBinaryOverrideRunnable() {
62881
62886
  const fromEnv = process.env.SUPERONE_CODEX_BINARY?.trim();
62882
- return Boolean(fromEnv && existsSync25(fromEnv));
62887
+ return Boolean(fromEnv && existsSync24(fromEnv));
62883
62888
  }
62884
62889
  function providerEnvKeyOf(env) {
62885
62890
  return [
@@ -62923,7 +62928,9 @@ function createNodeCodexTurnRunner(opts) {
62923
62928
  activeTurnId: null,
62924
62929
  cwd,
62925
62930
  providerEnvKey,
62926
- chain: Promise.resolve()
62931
+ chain: Promise.resolve(),
62932
+ busyCount: 0,
62933
+ lastActivityAt: Date.now()
62927
62934
  };
62928
62935
  liveBySession.set(sessionId, live);
62929
62936
  return live;
@@ -62978,21 +62985,28 @@ function createNodeCodexTurnRunner(opts) {
62978
62985
  if (!live2?.threadId || !live2.activeTurnId) {
62979
62986
  throw new Error("No active Codex turn to steer");
62980
62987
  }
62981
- const result = await runCodexAppServerTurn({
62982
- client: live2.client,
62983
- prompt,
62984
- cwd: live2.cwd,
62985
- threadId: live2.threadId,
62986
- turnKind: "steer",
62987
- expectedTurnId: live2.activeTurnId,
62988
- skipThreadSetup: true,
62989
- signal: input.signal
62990
- });
62991
- return {
62992
- finalText: result.finalText,
62993
- providerResume: result.threadId ? `thread:${result.threadId}` : null,
62994
- skipAssistantTranscript: true
62995
- };
62988
+ live2.busyCount += 1;
62989
+ live2.lastActivityAt = Date.now();
62990
+ try {
62991
+ const result = await runCodexAppServerTurn({
62992
+ client: live2.client,
62993
+ prompt,
62994
+ cwd: live2.cwd,
62995
+ threadId: live2.threadId,
62996
+ turnKind: "steer",
62997
+ expectedTurnId: live2.activeTurnId,
62998
+ skipThreadSetup: true,
62999
+ signal: input.signal
63000
+ });
63001
+ return {
63002
+ finalText: result.finalText,
63003
+ providerResume: result.threadId ? `thread:${result.threadId}` : null,
63004
+ skipAssistantTranscript: true
63005
+ };
63006
+ } finally {
63007
+ live2.busyCount = Math.max(0, live2.busyCount - 1);
63008
+ live2.lastActivityAt = Date.now();
63009
+ }
62996
63010
  }
62997
63011
  const live = await openLive(sessionId, binary, authEnv, cwd);
62998
63012
  const fullTurn = async () => {
@@ -63067,12 +63081,18 @@ function createNodeCodexTurnRunner(opts) {
63067
63081
  throw err;
63068
63082
  }
63069
63083
  };
63084
+ live.busyCount += 1;
63085
+ live.lastActivityAt = Date.now();
63070
63086
  const next = live.chain.then(fullTurn, fullTurn);
63071
- live.chain = next.then(
63087
+ const tracked = next.finally(() => {
63088
+ live.busyCount = Math.max(0, live.busyCount - 1);
63089
+ live.lastActivityAt = Date.now();
63090
+ });
63091
+ live.chain = tracked.then(
63072
63092
  () => void 0,
63073
63093
  () => void 0
63074
63094
  );
63075
- return next;
63095
+ return tracked;
63076
63096
  };
63077
63097
  runner.disposeSession = async (sessionId) => {
63078
63098
  await disposeLive(sessionId);
@@ -63081,6 +63101,11 @@ function createNodeCodexTurnRunner(opts) {
63081
63101
  const ids = [...liveBySession.keys()];
63082
63102
  await Promise.all(ids.map((id) => disposeLive(id)));
63083
63103
  };
63104
+ runner.listActiveRuntimes = () => [...liveBySession.entries()].map(([sessionId, live]) => ({
63105
+ sessionId,
63106
+ lastActivityAt: live.lastActivityAt,
63107
+ busy: live.busyCount > 0
63108
+ }));
63084
63109
  return runner;
63085
63110
  }
63086
63111
  function createProductionTurnRunner(opts) {
@@ -63132,6 +63157,10 @@ function createProductionTurnRunner(opts) {
63132
63157
  runner.disposeAll = async () => {
63133
63158
  await Promise.all([claude.disposeAll?.(), codex.disposeAll?.()]);
63134
63159
  };
63160
+ runner.listActiveRuntimes = () => [
63161
+ ...claude.listActiveRuntimes?.() ?? [],
63162
+ ...codex.listActiveRuntimes?.() ?? []
63163
+ ];
63135
63164
  return runner;
63136
63165
  }
63137
63166
  var init_codex_turn_runner = __esm({
@@ -66588,7 +66617,7 @@ var require_compile = __commonJS({
66588
66617
  const schOrFunc = root.refs[ref];
66589
66618
  if (schOrFunc)
66590
66619
  return schOrFunc;
66591
- let _sch = resolve14.call(this, root, ref);
66620
+ let _sch = resolve15.call(this, root, ref);
66592
66621
  if (_sch === void 0) {
66593
66622
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
66594
66623
  const { schemaId } = this.opts;
@@ -66615,7 +66644,7 @@ var require_compile = __commonJS({
66615
66644
  function sameSchemaEnv(s1, s2) {
66616
66645
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
66617
66646
  }
66618
- function resolve14(root, ref) {
66647
+ function resolve15(root, ref) {
66619
66648
  let sch;
66620
66649
  while (typeof (sch = this.refs[ref]) == "string")
66621
66650
  ref = sch;
@@ -67246,7 +67275,7 @@ var require_fast_uri = __commonJS({
67246
67275
  }
67247
67276
  return uri;
67248
67277
  }
67249
- function resolve14(baseURI, relativeURI, options) {
67278
+ function resolve15(baseURI, relativeURI, options) {
67250
67279
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
67251
67280
  const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed } = parseWithStatus(baseURI, schemelessOptions);
67252
67281
  const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
@@ -67530,7 +67559,7 @@ var require_fast_uri = __commonJS({
67530
67559
  var fastUri = {
67531
67560
  SCHEMES,
67532
67561
  normalize: normalize2,
67533
- resolve: resolve14,
67562
+ resolve: resolve15,
67534
67563
  resolveComponent,
67535
67564
  equal,
67536
67565
  serialize,
@@ -70521,7 +70550,7 @@ var require_dist2 = __commonJS({
70521
70550
 
70522
70551
  // src/cli.ts
70523
70552
  import { homedir as homedir10 } from "node:os";
70524
- import { resolve as resolve13 } from "node:path";
70553
+ import { resolve as resolve14 } from "node:path";
70525
70554
 
70526
70555
  // src/config.ts
70527
70556
  import { homedir } from "node:os";
@@ -70562,8 +70591,8 @@ import { fileURLToPath } from "node:url";
70562
70591
  function resolveCliReleaseVersion() {
70563
70592
  const fromEnv = process.env.SUPERONE_CLI_VERSION?.trim();
70564
70593
  if (fromEnv) return fromEnv;
70565
- if ("0.57.1-alpha".trim()) {
70566
- return "0.57.1-alpha".trim();
70594
+ if ("0.57.3-alpha".trim()) {
70595
+ return "0.57.3-alpha".trim();
70567
70596
  }
70568
70597
  const fromDist = readDistManifestVersion();
70569
70598
  if (fromDist) return fromDist;
@@ -71432,9 +71461,9 @@ async function startNodeServer(opts) {
71432
71461
  }
71433
71462
  });
71434
71463
  });
71435
- await new Promise((resolve14, reject) => {
71464
+ await new Promise((resolve15, reject) => {
71436
71465
  httpServer.once("error", reject);
71437
- httpServer.listen(opts.bindPort, opts.bindHost, () => resolve14());
71466
+ httpServer.listen(opts.bindPort, opts.bindHost, () => resolve15());
71438
71467
  });
71439
71468
  const address = httpServer.address();
71440
71469
  const port = typeof address === "object" && address ? address.port : opts.bindPort;
@@ -71447,9 +71476,9 @@ async function startNodeServer(opts) {
71447
71476
  async close() {
71448
71477
  for (const ws of activeSockets.keys()) ws.close();
71449
71478
  activeSockets.clear();
71450
- await new Promise((resolve14) => wss.close(() => resolve14()));
71451
- await new Promise((resolve14, reject) => {
71452
- httpServer.close((err) => err ? reject(err) : resolve14());
71479
+ await new Promise((resolve15) => wss.close(() => resolve15()));
71480
+ await new Promise((resolve15, reject) => {
71481
+ httpServer.close((err) => err ? reject(err) : resolve15());
71453
71482
  });
71454
71483
  }
71455
71484
  };
@@ -71559,7 +71588,7 @@ async function handleHttp(req, res, opts) {
71559
71588
  }
71560
71589
 
71561
71590
  // src/runtime.ts
71562
- import { existsSync as existsSync42, readFileSync as readFileSync21, writeFileSync as writeFileSync19 } from "node:fs";
71591
+ import { existsSync as existsSync41, readFileSync as readFileSync20, writeFileSync as writeFileSync18 } from "node:fs";
71563
71592
 
71564
71593
  // ../../packages/runtime/src/db/database.ts
71565
71594
  import Database from "better-sqlite3";
@@ -71662,7 +71691,8 @@ CREATE TABLE IF NOT EXISTS projects (
71662
71691
  name TEXT NOT NULL,
71663
71692
  repo_identity TEXT,
71664
71693
  opened_at INTEGER,
71665
- last_active_at INTEGER
71694
+ last_active_at INTEGER,
71695
+ extra_dirs_json TEXT NOT NULL DEFAULT '[]'
71666
71696
  );
71667
71697
 
71668
71698
  CREATE TABLE IF NOT EXISTS sessions (
@@ -71855,6 +71885,7 @@ function openNodeDatabase(dbPath) {
71855
71885
  ensureCollaborationTables(db);
71856
71886
  ensureAutomationsSupport(db);
71857
71887
  ensureSessionTagsColumn(db);
71888
+ ensureProjectExtraDirsColumn(db);
71858
71889
  ensureSessionProvidersSupport(db);
71859
71890
  const row = db.prepare("SELECT value FROM meta WHERE key = ?").get("schema_generation");
71860
71891
  if (!row) {
@@ -71885,6 +71916,12 @@ function ensureSessionUiColumns(db) {
71885
71916
  db.exec(`ALTER TABLE sessions ADD COLUMN is_user_renamed INTEGER NOT NULL DEFAULT 0`);
71886
71917
  }
71887
71918
  }
71919
+ function ensureProjectExtraDirsColumn(db) {
71920
+ const cols = db.prepare(`PRAGMA table_info(projects)`).all();
71921
+ if (!cols.some((c) => c.name === "extra_dirs_json")) {
71922
+ db.exec(`ALTER TABLE projects ADD COLUMN extra_dirs_json TEXT NOT NULL DEFAULT '[]'`);
71923
+ }
71924
+ }
71888
71925
  function ensureHarnessInstallationsTable(db) {
71889
71926
  db.exec(`
71890
71927
  CREATE TABLE IF NOT EXISTS harness_installations (
@@ -72590,7 +72627,7 @@ async function cloneRepository(input) {
72590
72627
  }
72591
72628
 
72592
72629
  // src/rpc/handlers.ts
72593
- import { existsSync as existsSync26, mkdirSync as mkdirSync15, readdirSync as readdirSync8, statSync as statSync6 } from "node:fs";
72630
+ import { existsSync as existsSync25, mkdirSync as mkdirSync14, readdirSync as readdirSync8, statSync as statSync6 } from "node:fs";
72594
72631
  import { join as pathJoin, resolve as pathResolve } from "node:path";
72595
72632
  import { arch, cpus, freemem, homedir as homedir6, hostname as hostname4, platform, totalmem, uptime } from "node:os";
72596
72633
 
@@ -72797,57 +72834,6 @@ function handleMcpList(payload, ctx) {
72797
72834
  return mapThrown(err);
72798
72835
  }
72799
72836
  }
72800
- function handleAdditionalDirsList(payload, ctx) {
72801
- const denied = requireScopes(ctx.client, OPERATION_SCOPES.readWorkspace);
72802
- if (denied) return denied;
72803
- const p2 = asRecord13(payload);
72804
- try {
72805
- const projectId = String(p2.projectId ?? "");
72806
- const cwd = projectRoot(ctx.projects, projectId);
72807
- const provider = parseProviderStrict(p2.provider);
72808
- if (!provider) return { error: { code: "invalid_argument", message: "provider must be claude or codex" } };
72809
- ctx.projects.touch(projectId);
72810
- return { result: readScopedAdditionalDirs(provider, cwd, manageOpts(ctx)) };
72811
- } catch (err) {
72812
- return mapThrown(err);
72813
- }
72814
- }
72815
- function handleAdditionalDirsAdd(payload, ctx) {
72816
- const denied = requireScopes(ctx.client, OPERATION_SCOPES.writeWorkspace);
72817
- if (denied) return denied;
72818
- const p2 = asRecord13(payload);
72819
- try {
72820
- const projectId = String(p2.projectId ?? "");
72821
- const cwd = projectRoot(ctx.projects, projectId);
72822
- const provider = parseProviderStrict(p2.provider);
72823
- if (!provider) return { error: { code: "invalid_argument", message: "provider must be claude or codex" } };
72824
- const dir = typeof p2.dir === "string" ? p2.dir.trim() : "";
72825
- if (!dir) return { error: { code: "invalid_argument", message: "dir is required" } };
72826
- addProjectAdditionalDir(provider, cwd, dir, manageOpts(ctx));
72827
- ctx.projects.touch(projectId);
72828
- return { result: { ok: true } };
72829
- } catch (err) {
72830
- return mapThrown(err);
72831
- }
72832
- }
72833
- function handleAdditionalDirsRemove(payload, ctx) {
72834
- const denied = requireScopes(ctx.client, OPERATION_SCOPES.writeWorkspace);
72835
- if (denied) return denied;
72836
- const p2 = asRecord13(payload);
72837
- try {
72838
- const projectId = String(p2.projectId ?? "");
72839
- const cwd = projectRoot(ctx.projects, projectId);
72840
- const provider = parseProviderStrict(p2.provider);
72841
- if (!provider) return { error: { code: "invalid_argument", message: "provider must be claude or codex" } };
72842
- const dir = typeof p2.dir === "string" ? p2.dir.trim() : "";
72843
- if (!dir) return { error: { code: "invalid_argument", message: "dir is required" } };
72844
- removeProjectAdditionalDir(provider, cwd, dir);
72845
- ctx.projects.touch(projectId);
72846
- return { result: { ok: true } };
72847
- } catch (err) {
72848
- return mapThrown(err);
72849
- }
72850
- }
72851
72837
  function parseMcpWriteConfig(raw) {
72852
72838
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
72853
72839
  return {
@@ -73459,12 +73445,6 @@ function dispatchResourceRpc(method, payload, ctx) {
73459
73445
  return handleMcpToggle(payload, ctx);
73460
73446
  case "mcp.delete":
73461
73447
  return handleMcpDelete(payload, ctx);
73462
- case "additionalDirs.list":
73463
- return handleAdditionalDirsList(payload, ctx);
73464
- case "additionalDirs.add":
73465
- return handleAdditionalDirsAdd(payload, ctx);
73466
- case "additionalDirs.remove":
73467
- return handleAdditionalDirsRemove(payload, ctx);
73468
73448
  case "plugins.list":
73469
73449
  return handlePluginsList(payload, ctx);
73470
73450
  case "plugins.get":
@@ -74642,12 +74622,14 @@ function clearWatchBuffersForClient(clientSessionId) {
74642
74622
  watchBuffers.delete(watchId);
74643
74623
  }
74644
74624
  }
74625
+ var MAX_TURN_ADDITIONAL_DIRS = 64;
74645
74626
  var MUTATING_METHODS = /* @__PURE__ */ new Set([
74646
74627
  "terminal.create",
74647
74628
  "terminal.write",
74648
74629
  "terminal.resize",
74649
74630
  "terminal.kill",
74650
74631
  "project.open",
74632
+ "project.update",
74651
74633
  "project.remove",
74652
74634
  "workspace.writeFile",
74653
74635
  "workspace.rename",
@@ -74842,6 +74824,8 @@ async function dispatchRpcInner(method, payload, ctx) {
74842
74824
  return handleProjectGet(payload, ctx);
74843
74825
  case "project.open":
74844
74826
  return handleProjectOpen(payload, ctx);
74827
+ case "project.update":
74828
+ return handleProjectUpdate(payload, ctx);
74845
74829
  case "project.remove":
74846
74830
  return handleProjectRemove(payload, ctx);
74847
74831
  case "fs.listDir":
@@ -75526,14 +75510,42 @@ function handleProjectOpen(payload, ctx) {
75526
75510
  }
75527
75511
  const name = typeof p2.name === "string" ? p2.name : void 0;
75528
75512
  try {
75529
- if (p2.createIfMissing === true && !existsSync26(path)) {
75530
- mkdirSync15(path, { recursive: true });
75513
+ if (p2.createIfMissing === true && !existsSync25(path)) {
75514
+ mkdirSync14(path, { recursive: true });
75531
75515
  }
75532
75516
  return { result: ctx.projects.open(path, name) };
75533
75517
  } catch (err) {
75534
75518
  return mapThrown7(err);
75535
75519
  }
75536
75520
  }
75521
+ function handleProjectUpdate(payload, ctx) {
75522
+ const denied = requireScopes7(ctx.client, OPERATION_SCOPES.manageProject);
75523
+ if (denied) return denied;
75524
+ const p2 = asRecord19(payload);
75525
+ const projectId = typeof p2.projectId === "string" && p2.projectId ? p2.projectId : void 0;
75526
+ const pathRaw = typeof p2.path === "string" && p2.path ? expandHostPath(p2.path) : void 0;
75527
+ if (!projectId && !pathRaw) {
75528
+ return { error: { code: "invalid_argument", message: "projectId or path is required" } };
75529
+ }
75530
+ const name = typeof p2.name === "string" ? p2.name : void 0;
75531
+ const hostDirs = (raw) => Array.isArray(raw) ? raw.filter((d) => typeof d === "string" && d.trim().length > 0).map((d) => expandHostPath(d.trim())) : void 0;
75532
+ try {
75533
+ const updated = ctx.projects.update({
75534
+ projectId,
75535
+ path: pathRaw,
75536
+ name,
75537
+ extraDirs: hostDirs(p2.extraDirs),
75538
+ addExtraDirs: hostDirs(p2.addExtraDirs),
75539
+ removeExtraDirs: hostDirs(p2.removeExtraDirs)
75540
+ });
75541
+ if (!updated) {
75542
+ return { error: { code: "not_found", message: "project not found" } };
75543
+ }
75544
+ return { result: updated };
75545
+ } catch (err) {
75546
+ return mapThrown7(err);
75547
+ }
75548
+ }
75537
75549
  function handleProjectRemove(payload, ctx) {
75538
75550
  const denied = requireScopes7(ctx.client, OPERATION_SCOPES.manageProject);
75539
75551
  if (denied) return denied;
@@ -75563,7 +75575,7 @@ function handleFsListDir(payload, ctx) {
75563
75575
  }
75564
75576
  try {
75565
75577
  const resolved = expandHostPath(raw);
75566
- if (!existsSync26(resolved)) {
75578
+ if (!existsSync25(resolved)) {
75567
75579
  return { error: { code: "not_found", message: "path not found" } };
75568
75580
  }
75569
75581
  if (!statSync6(resolved).isDirectory()) {
@@ -76509,7 +76521,7 @@ async function handleSessionSend(payload, ctx) {
76509
76521
  const permissionModeFromClient = typeof options.permissionMode === "string" && options.permissionMode.trim() ? options.permissionMode.trim() : typeof p2.permissionMode === "string" && p2.permissionMode.trim() ? p2.permissionMode.trim() : null;
76510
76522
  const sandboxModeFromClient = typeof options.sandboxMode === "string" && options.sandboxMode.trim() ? options.sandboxMode.trim() : typeof p2.sandboxMode === "string" && p2.sandboxMode.trim() ? p2.sandboxMode.trim() : null;
76511
76523
  const rawAdditionalDirs = Array.isArray(options.additionalDirectories) ? options.additionalDirectories : Array.isArray(p2.additionalDirectories) ? p2.additionalDirectories : [];
76512
- const additionalDirectories = rawAdditionalDirs.filter((d) => typeof d === "string" && d.trim().length > 0).map((d) => d.trim()).slice(0, 32);
76524
+ const clientAdditionalDirectories = rawAdditionalDirs.filter((d) => typeof d === "string" && d.trim().length > 0).map((d) => d.trim());
76513
76525
  const rawEnabledSkills = Array.isArray(options.enabledSkills) ? options.enabledSkills : Array.isArray(p2.enabledSkills) ? p2.enabledSkills : [];
76514
76526
  const enabledSkills = rawEnabledSkills.filter((s2) => typeof s2 === "string" && s2.trim().length > 0).map((s2) => s2.trim()).slice(0, 200);
76515
76527
  const rawDisabledSkills = Array.isArray(options.disabledSkills) ? options.disabledSkills : Array.isArray(p2.disabledSkills) ? p2.disabledSkills : null;
@@ -76534,6 +76546,10 @@ async function handleSessionSend(payload, ctx) {
76534
76546
  const reviewTarget = options.reviewTarget !== void 0 ? options.reviewTarget : p2.reviewTarget !== void 0 ? p2.reviewTarget : void 0;
76535
76547
  const existing = ctx.sessions.get(String(p2.sessionId ?? ""));
76536
76548
  const harnessId = existing?.harnessId || "claude";
76549
+ const projectExtraDirs = existing ? ctx.projects.get(existing.projectId)?.extraDirs ?? [] : [];
76550
+ const additionalDirectories = [
76551
+ .../* @__PURE__ */ new Set([...projectExtraDirs, ...clientAdditionalDirectories])
76552
+ ].slice(0, MAX_TURN_ADDITIONAL_DIRS);
76537
76553
  const agentDefaults = resolveAgentTurnDefaults(
76538
76554
  loadNodeAgentSettings(ctx.settingsConfigPath),
76539
76555
  harnessId
@@ -77144,11 +77160,11 @@ function parseState(raw) {
77144
77160
 
77145
77161
  // ../../packages/runtime/src/harness/home-path.ts
77146
77162
  import { homedir as homedir7 } from "node:os";
77147
- import { join as join24 } from "node:path";
77163
+ import { join as join23 } from "node:path";
77148
77164
  var HARNESS_HOME_DIRNAME = "harness";
77149
77165
  var SUPERONE_DIRNAME = ".superone";
77150
77166
  function defaultHarnessHomeRoot(userHome = homedir7()) {
77151
- return join24(userHome, SUPERONE_DIRNAME, HARNESS_HOME_DIRNAME);
77167
+ return join23(userHome, SUPERONE_DIRNAME, HARNESS_HOME_DIRNAME);
77152
77168
  }
77153
77169
  function resolveHarnessHomeRoot(opts = {}) {
77154
77170
  const explicit = opts.override?.trim();
@@ -77162,16 +77178,16 @@ function resolveHarnessHomeRoot(opts = {}) {
77162
77178
 
77163
77179
  // ../../packages/runtime/src/harness/managed-layout.ts
77164
77180
  import {
77165
- existsSync as existsSync27,
77166
- mkdirSync as mkdirSync16,
77181
+ existsSync as existsSync26,
77182
+ mkdirSync as mkdirSync15,
77167
77183
  readdirSync as readdirSync9,
77168
- readFileSync as readFileSync15,
77184
+ readFileSync as readFileSync14,
77169
77185
  renameSync as renameSync2,
77170
77186
  rmSync as rmSync2,
77171
77187
  statSync as statSync7,
77172
- writeFileSync as writeFileSync11
77188
+ writeFileSync as writeFileSync10
77173
77189
  } from "node:fs";
77174
- import { join as join25 } from "node:path";
77190
+ import { join as join24 } from "node:path";
77175
77191
  import { randomBytes as randomBytes3 } from "node:crypto";
77176
77192
  var MANAGED_VERSIONS_DIRNAME = "versions";
77177
77193
  var MANAGED_CURRENT_BASENAME = "current";
@@ -77188,19 +77204,19 @@ function sanitizeRuntimeVersionForPath(runtimeVersion) {
77188
77204
  return v2;
77189
77205
  }
77190
77206
  function managedVersionsDir(prefix) {
77191
- return join25(prefix, MANAGED_VERSIONS_DIRNAME);
77207
+ return join24(prefix, MANAGED_VERSIONS_DIRNAME);
77192
77208
  }
77193
77209
  function managedVersionDir(prefix, runtimeVersion) {
77194
- return join25(managedVersionsDir(prefix), sanitizeRuntimeVersionForPath(runtimeVersion));
77210
+ return join24(managedVersionsDir(prefix), sanitizeRuntimeVersionForPath(runtimeVersion));
77195
77211
  }
77196
77212
  function managedCurrentPath(prefix) {
77197
- return join25(prefix, MANAGED_CURRENT_BASENAME);
77213
+ return join24(prefix, MANAGED_CURRENT_BASENAME);
77198
77214
  }
77199
77215
  function readCurrentPointer(prefix) {
77200
77216
  const path = managedCurrentPath(prefix);
77201
- if (!existsSync27(path)) return null;
77217
+ if (!existsSync26(path)) return null;
77202
77218
  try {
77203
- const raw = JSON.parse(readFileSync15(path, "utf8"));
77219
+ const raw = JSON.parse(readFileSync14(path, "utf8"));
77204
77220
  if (typeof raw.runtimeVersion !== "string" || !raw.runtimeVersion.trim()) return null;
77205
77221
  return {
77206
77222
  runtimeVersion: raw.runtimeVersion.trim(),
@@ -77213,7 +77229,7 @@ function readCurrentPointer(prefix) {
77213
77229
  }
77214
77230
  function writeCurrentPointer(prefix, runtimeVersion, extras) {
77215
77231
  const ver = sanitizeRuntimeVersionForPath(runtimeVersion);
77216
- mkdirSync16(prefix, { recursive: true });
77232
+ mkdirSync15(prefix, { recursive: true });
77217
77233
  const path = managedCurrentPath(prefix);
77218
77234
  const body = JSON.stringify(
77219
77235
  {
@@ -77224,19 +77240,19 @@ function writeCurrentPointer(prefix, runtimeVersion, extras) {
77224
77240
  null,
77225
77241
  2
77226
77242
  );
77227
- const tmp = join25(
77243
+ const tmp = join24(
77228
77244
  prefix,
77229
77245
  `.${MANAGED_CURRENT_BASENAME}.${process.pid}.${randomBytes3(6).toString("hex")}.tmp`
77230
77246
  );
77231
- writeFileSync11(tmp, body);
77247
+ writeFileSync10(tmp, body);
77232
77248
  try {
77233
77249
  renameSync2(tmp, path);
77234
77250
  } catch {
77235
77251
  try {
77236
- if (existsSync27(path)) rmSync2(path, { force: true });
77252
+ if (existsSync26(path)) rmSync2(path, { force: true });
77237
77253
  renameSync2(tmp, path);
77238
77254
  } catch {
77239
- writeFileSync11(path, body);
77255
+ writeFileSync10(path, body);
77240
77256
  try {
77241
77257
  rmSync2(tmp, { force: true });
77242
77258
  } catch {
@@ -77245,26 +77261,26 @@ function writeCurrentPointer(prefix, runtimeVersion, extras) {
77245
77261
  }
77246
77262
  }
77247
77263
  function resolveActiveInstallRoot(prefix) {
77248
- if (!prefix || !existsSync27(prefix)) return null;
77264
+ if (!prefix || !existsSync26(prefix)) return null;
77249
77265
  const pointer = readCurrentPointer(prefix);
77250
77266
  if (pointer) {
77251
- if (pointer.installRoot && existsSync27(pointer.installRoot) && statSync7(pointer.installRoot).isDirectory()) {
77267
+ if (pointer.installRoot && existsSync26(pointer.installRoot) && statSync7(pointer.installRoot).isDirectory()) {
77252
77268
  return pointer.installRoot;
77253
77269
  }
77254
77270
  const dir = managedVersionDir(prefix, pointer.runtimeVersion);
77255
- if (existsSync27(dir) && statSync7(dir).isDirectory()) return dir;
77271
+ if (existsSync26(dir) && statSync7(dir).isDirectory()) return dir;
77256
77272
  }
77257
77273
  const versionsRoot = managedVersionsDir(prefix);
77258
- if (existsSync27(versionsRoot)) {
77274
+ if (existsSync26(versionsRoot)) {
77259
77275
  try {
77260
77276
  const kids = readdirSync9(versionsRoot).filter((n) => {
77261
77277
  try {
77262
- return statSync7(join25(versionsRoot, n)).isDirectory();
77278
+ return statSync7(join24(versionsRoot, n)).isDirectory();
77263
77279
  } catch {
77264
77280
  return false;
77265
77281
  }
77266
77282
  });
77267
- if (kids.length === 1) return join25(versionsRoot, kids[0]);
77283
+ if (kids.length === 1) return join24(versionsRoot, kids[0]);
77268
77284
  } catch {
77269
77285
  }
77270
77286
  }
@@ -77272,7 +77288,7 @@ function resolveActiveInstallRoot(prefix) {
77272
77288
  }
77273
77289
  function pruneManagedVersions(prefix, keep, maxKeep = MANAGED_VERSION_KEEP) {
77274
77290
  const versionsRoot = managedVersionsDir(prefix);
77275
- if (!existsSync27(versionsRoot)) return;
77291
+ if (!existsSync26(versionsRoot)) return;
77276
77292
  const keepSet = new Set(
77277
77293
  keep.filter(Boolean).map((v2) => {
77278
77294
  try {
@@ -77286,7 +77302,7 @@ function pruneManagedVersions(prefix, keep, maxKeep = MANAGED_VERSION_KEEP) {
77286
77302
  try {
77287
77303
  entries = readdirSync9(versionsRoot).map((name) => {
77288
77304
  try {
77289
- const st = statSync7(join25(versionsRoot, name));
77305
+ const st = statSync7(join24(versionsRoot, name));
77290
77306
  if (!st.isDirectory()) return null;
77291
77307
  return { name, mtime: st.mtimeMs };
77292
77308
  } catch {
@@ -77305,7 +77321,7 @@ function pruneManagedVersions(prefix, keep, maxKeep = MANAGED_VERSION_KEEP) {
77305
77321
  }
77306
77322
  for (const e of entries) {
77307
77323
  if (retain.has(e.name)) continue;
77308
- const dir = join25(versionsRoot, e.name);
77324
+ const dir = join24(versionsRoot, e.name);
77309
77325
  try {
77310
77326
  rmSync2(dir, { recursive: true, force: true });
77311
77327
  } catch {
@@ -77317,17 +77333,17 @@ function pruneManagedVersions(prefix, keep, maxKeep = MANAGED_VERSION_KEEP) {
77317
77333
  import {
77318
77334
  copyFileSync,
77319
77335
  createReadStream,
77320
- existsSync as existsSync28,
77321
- mkdirSync as mkdirSync17,
77336
+ existsSync as existsSync27,
77337
+ mkdirSync as mkdirSync16,
77322
77338
  mkdtempSync,
77323
- readFileSync as readFileSync16,
77339
+ readFileSync as readFileSync15,
77324
77340
  renameSync as renameSync3,
77325
77341
  rmSync as rmSync3,
77326
77342
  statSync as statSync8,
77327
- writeFileSync as writeFileSync12
77343
+ writeFileSync as writeFileSync11
77328
77344
  } from "node:fs";
77329
77345
  import { createHash as createHash5, randomBytes as randomBytes4 } from "node:crypto";
77330
- import { dirname as dirname14, join as join26, relative, resolve as resolve6, sep as sep3 } from "node:path";
77346
+ import { dirname as dirname13, join as join25, relative, resolve as resolve6, sep as sep3 } from "node:path";
77331
77347
  import { arch as osArch, platform as osPlatform } from "node:os";
77332
77348
  var releaseVersionProvider = null;
77333
77349
  function setHarnessReleaseVersionProvider(fn) {
@@ -77471,14 +77487,14 @@ function parseManagedHarnessPin(id, raw) {
77471
77487
  function loadHarnessReleaseManifest(nodeHome) {
77472
77488
  const fromEnv = process.env.SUPERONE_HARNESS_MANIFEST;
77473
77489
  if (fromEnv) {
77474
- if (!existsSync28(fromEnv)) {
77490
+ if (!existsSync27(fromEnv)) {
77475
77491
  throw new Error(`SUPERONE_HARNESS_MANIFEST not found: ${fromEnv}`);
77476
77492
  }
77477
- return parseHarnessReleaseManifest(JSON.parse(readFileSync16(fromEnv, "utf8")));
77493
+ return parseHarnessReleaseManifest(JSON.parse(readFileSync15(fromEnv, "utf8")));
77478
77494
  }
77479
- const local = join26(nodeHome, "release-manifest.json");
77480
- if (existsSync28(local)) {
77481
- return parseHarnessReleaseManifest(JSON.parse(readFileSync16(local, "utf8")));
77495
+ const local = join25(nodeHome, "release-manifest.json");
77496
+ if (existsSync27(local)) {
77497
+ return parseHarnessReleaseManifest(JSON.parse(readFileSync15(local, "utf8")));
77482
77498
  }
77483
77499
  return null;
77484
77500
  }
@@ -77546,7 +77562,7 @@ async function installManagedArtifactFromFile(opts) {
77546
77562
  throw new Error(`release manifest does not pin managed harness ${opts.harnessId}`);
77547
77563
  }
77548
77564
  const art = selectArtifactPin(pin);
77549
- if (!existsSync28(opts.artifactPath)) {
77565
+ if (!existsSync27(opts.artifactPath)) {
77550
77566
  throw new Error(`artifact not found: ${opts.artifactPath}`);
77551
77567
  }
77552
77568
  if (!statSync8(opts.artifactPath).isFile()) {
@@ -77564,8 +77580,8 @@ async function installManagedArtifactFromFile(opts) {
77564
77580
  opts.harnessId,
77565
77581
  pin.artifactVersion
77566
77582
  );
77567
- const finalFile = join26(destDir, MANAGED_PAYLOAD_BASENAME);
77568
- const metaPath = join26(destDir, MANAGED_META_BASENAME);
77583
+ const finalFile = join25(destDir, MANAGED_PAYLOAD_BASENAME);
77584
+ const metaPath = join25(destDir, MANAGED_META_BASENAME);
77569
77585
  assertStrictChild(finalFile, destDir, "payload path");
77570
77586
  assertStrictChild(metaPath, destDir, "meta path");
77571
77587
  const metaBody = JSON.stringify(
@@ -77584,8 +77600,8 @@ async function installManagedArtifactFromFile(opts) {
77584
77600
  2
77585
77601
  );
77586
77602
  let reusedExisting = false;
77587
- if (existsSync28(destDir)) {
77588
- const payloadOk = existsSync28(finalFile) && statSync8(finalFile).isFile() && await sha256File(finalFile) === art.digestSha256;
77603
+ if (existsSync27(destDir)) {
77604
+ const payloadOk = existsSync27(finalFile) && statSync8(finalFile).isFile() && await sha256File(finalFile) === art.digestSha256;
77589
77605
  if (payloadOk) {
77590
77606
  reusedExisting = true;
77591
77607
  } else if (mode === "repair") {
@@ -77604,26 +77620,26 @@ async function installManagedArtifactFromFile(opts) {
77604
77620
  );
77605
77621
  }
77606
77622
  } else {
77607
- const harnessRoot2 = dirname14(destDir);
77608
- mkdirSync17(harnessRoot2, { recursive: true });
77623
+ const harnessRoot2 = dirname13(destDir);
77624
+ mkdirSync16(harnessRoot2, { recursive: true });
77609
77625
  assertPathInside(destDir, harnessRoot2, "version dir");
77610
77626
  const stagingDir = mkdtempSync(
77611
- join26(harnessRoot2, `.staging-${opts.harnessId}-${randomBytes4(8).toString("hex")}-`)
77627
+ join25(harnessRoot2, `.staging-${opts.harnessId}-${randomBytes4(8).toString("hex")}-`)
77612
77628
  );
77613
77629
  assertPathInside(stagingDir, harnessRoot2, "staging dir");
77614
- const stagingFile = join26(stagingDir, MANAGED_PAYLOAD_BASENAME);
77615
- const stagingMeta = join26(stagingDir, MANAGED_META_BASENAME);
77630
+ const stagingFile = join25(stagingDir, MANAGED_PAYLOAD_BASENAME);
77631
+ const stagingMeta = join25(stagingDir, MANAGED_META_BASENAME);
77616
77632
  try {
77617
77633
  copyFileSync(opts.artifactPath, stagingFile);
77618
77634
  const stagedDigest = await sha256File(stagingFile);
77619
77635
  if (stagedDigest !== art.digestSha256) {
77620
77636
  throw new Error(`staged artifact digest mismatch for ${opts.harnessId}`);
77621
77637
  }
77622
- writeFileSync12(stagingMeta, metaBody, "utf8");
77638
+ writeFileSync11(stagingMeta, metaBody, "utf8");
77623
77639
  renameSync3(stagingDir, destDir);
77624
77640
  } catch (err) {
77625
77641
  rmSync3(stagingDir, { recursive: true, force: true });
77626
- if (existsSync28(destDir) && existsSync28(finalFile)) {
77642
+ if (existsSync27(destDir) && existsSync27(finalFile)) {
77627
77643
  const existingDigest = await sha256File(finalFile);
77628
77644
  if (existingDigest === art.digestSha256) {
77629
77645
  reusedExisting = true;
@@ -77648,22 +77664,22 @@ async function installManagedArtifactFromFile(opts) {
77648
77664
  if (finalDigest !== art.digestSha256) {
77649
77665
  throw new Error(`final payload digest mismatch for ${opts.harnessId}`);
77650
77666
  }
77651
- const harnessRoot = join26(
77667
+ const harnessRoot = join25(
77652
77668
  releasesRoot(opts.nodeHome),
77653
77669
  opts.manifest.cliVersion,
77654
77670
  "harnesses",
77655
77671
  opts.harnessId
77656
77672
  );
77657
77673
  assertPathInside(harnessRoot, releasesRoot(opts.nodeHome), "harness root");
77658
- mkdirSync17(harnessRoot, { recursive: true });
77659
- const currentPath = join26(harnessRoot, MANAGED_CURRENT_BASENAME2);
77660
- const currentTmp = join26(
77674
+ mkdirSync16(harnessRoot, { recursive: true });
77675
+ const currentPath = join25(harnessRoot, MANAGED_CURRENT_BASENAME2);
77676
+ const currentTmp = join25(
77661
77677
  harnessRoot,
77662
77678
  `.${MANAGED_CURRENT_BASENAME2}.${process.pid}.${randomBytes4(6).toString("hex")}.tmp`
77663
77679
  );
77664
77680
  assertStrictChild(currentTmp, harnessRoot, "current pointer temp");
77665
77681
  try {
77666
- writeFileSync12(
77682
+ writeFileSync11(
77667
77683
  currentTmp,
77668
77684
  JSON.stringify(
77669
77685
  {
@@ -77694,10 +77710,10 @@ async function installManagedArtifactFromFile(opts) {
77694
77710
  };
77695
77711
  }
77696
77712
  async function replacePayloadAtomically(opts) {
77697
- mkdirSync17(opts.destDir, { recursive: true });
77713
+ mkdirSync16(opts.destDir, { recursive: true });
77698
77714
  const nonce = randomBytes4(8).toString("hex");
77699
- const payloadTmp = join26(opts.destDir, `.${MANAGED_PAYLOAD_BASENAME}.${nonce}.tmp`);
77700
- const metaTmp = join26(opts.destDir, `.${MANAGED_META_BASENAME}.${nonce}.tmp`);
77715
+ const payloadTmp = join25(opts.destDir, `.${MANAGED_PAYLOAD_BASENAME}.${nonce}.tmp`);
77716
+ const metaTmp = join25(opts.destDir, `.${MANAGED_META_BASENAME}.${nonce}.tmp`);
77701
77717
  assertStrictChild(payloadTmp, opts.destDir, "payload temp");
77702
77718
  assertStrictChild(metaTmp, opts.destDir, "meta temp");
77703
77719
  try {
@@ -77706,7 +77722,7 @@ async function replacePayloadAtomically(opts) {
77706
77722
  if (d !== opts.expectedDigest) {
77707
77723
  throw new Error(`repair staged digest mismatch: expected ${opts.expectedDigest}, got ${d}`);
77708
77724
  }
77709
- writeFileSync12(metaTmp, opts.metaBody, "utf8");
77725
+ writeFileSync11(metaTmp, opts.metaBody, "utf8");
77710
77726
  renameSync3(payloadTmp, opts.finalFile);
77711
77727
  renameSync3(metaTmp, opts.metaPath);
77712
77728
  } catch (err) {
@@ -77731,9 +77747,9 @@ function requiredRuntimeVersion(harnessId, manifest) {
77731
77747
  }
77732
77748
 
77733
77749
  // ../../packages/runtime/src/harness/managed-official.ts
77734
- import { existsSync as existsSync29, mkdirSync as mkdirSync18, readFileSync as readFileSync17, readdirSync as readdirSync10, statSync as statSync9, writeFileSync as writeFileSync13 } from "node:fs";
77750
+ import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync9, writeFileSync as writeFileSync12 } from "node:fs";
77735
77751
  import { arch as osArch2, platform as osPlatform2 } from "node:os";
77736
- import { join as join27, resolve as resolve7 } from "node:path";
77752
+ import { join as join26, resolve as resolve7 } from "node:path";
77737
77753
  var OFFICIAL_CLAUDE_SDK_VERSION = "0.3.238";
77738
77754
  var OFFICIAL_CODEX_NPM_VERSION = "0.149.0";
77739
77755
  var OFFICIAL_CODEX_PACKAGE = "@openai/codex";
@@ -77777,7 +77793,7 @@ function claudePlatformPackageName() {
77777
77793
  }
77778
77794
  function isMuslLinux() {
77779
77795
  try {
77780
- if (existsSync29("/etc/alpine-release")) return true;
77796
+ if (existsSync28("/etc/alpine-release")) return true;
77781
77797
  const lib = readdirSync10("/lib").some((n) => n.startsWith("ld-musl"));
77782
77798
  if (lib) return true;
77783
77799
  } catch {
@@ -77785,44 +77801,44 @@ function isMuslLinux() {
77785
77801
  return false;
77786
77802
  }
77787
77803
  function resolveOfficialInstallBinaryInRoot(harnessId, installRoot) {
77788
- if (!installRoot || !existsSync29(installRoot)) return null;
77804
+ if (!installRoot || !existsSync28(installRoot)) return null;
77789
77805
  if (harnessId === "codex") {
77790
77806
  const triple = codexTargetTriple();
77791
77807
  const nativeName = process.platform === "win32" ? "codex.exe" : "codex";
77792
77808
  const candidates = [
77793
- join27(installRoot, "bin", "codex"),
77794
- join27(installRoot, "bin", "codex.cmd"),
77795
- join27(installRoot, "lib", "node_modules", "@openai", "codex", "bin", "codex.js"),
77796
- join27(installRoot, "node_modules", "@openai", "codex", "bin", "codex.js"),
77809
+ join26(installRoot, "bin", "codex"),
77810
+ join26(installRoot, "bin", "codex.cmd"),
77811
+ join26(installRoot, "lib", "node_modules", "@openai", "codex", "bin", "codex.js"),
77812
+ join26(installRoot, "node_modules", "@openai", "codex", "bin", "codex.js"),
77797
77813
  ...triple ? [
77798
- join27(installRoot, "lib", "node_modules", "@openai", "codex", "vendor", triple, "bin", nativeName),
77799
- join27(installRoot, "node_modules", "@openai", "codex", "vendor", triple, "bin", nativeName)
77814
+ join26(installRoot, "lib", "node_modules", "@openai", "codex", "vendor", triple, "bin", nativeName),
77815
+ join26(installRoot, "node_modules", "@openai", "codex", "vendor", triple, "bin", nativeName)
77800
77816
  ] : []
77801
77817
  ];
77802
77818
  for (const c of candidates) {
77803
- if (existsSync29(c) && (c.endsWith(".js") || isExecutableFile2(c))) return c;
77819
+ if (existsSync28(c) && (c.endsWith(".js") || isExecutableFile2(c))) return c;
77804
77820
  }
77805
77821
  return null;
77806
77822
  }
77807
- const nm = join27(installRoot, "lib", "node_modules");
77808
- const scoped = join27(nm, "@anthropic-ai");
77823
+ const nm = join26(installRoot, "lib", "node_modules");
77824
+ const scoped = join26(nm, "@anthropic-ai");
77809
77825
  try {
77810
- if (existsSync29(scoped)) {
77826
+ if (existsSync28(scoped)) {
77811
77827
  const names = readdirSync10(scoped).filter((n) => n.startsWith("claude-agent-sdk-"));
77812
77828
  for (const n of names) {
77813
77829
  const ext = process.platform === "win32" ? ".exe" : "";
77814
- const bin = join27(scoped, n, `claude${ext}`);
77815
- if (existsSync29(bin)) return bin;
77830
+ const bin = join26(scoped, n, `claude${ext}`);
77831
+ if (existsSync28(bin)) return bin;
77816
77832
  }
77817
77833
  }
77818
77834
  } catch {
77819
77835
  }
77820
- const direct = join27(
77836
+ const direct = join26(
77821
77837
  nm,
77822
77838
  ...claudePlatformPackageName().split("/"),
77823
77839
  process.platform === "win32" ? "claude.exe" : "claude"
77824
77840
  );
77825
- if (existsSync29(direct)) return direct;
77841
+ if (existsSync28(direct)) return direct;
77826
77842
  return null;
77827
77843
  }
77828
77844
  function isExecutableFile2(path) {
@@ -77837,7 +77853,7 @@ function isExecutableFile2(path) {
77837
77853
  }
77838
77854
 
77839
77855
  // ../../packages/runtime/src/harness/tarball-fetch.ts
77840
- import { existsSync as existsSync30, rmSync as rmSync4 } from "node:fs";
77856
+ import { existsSync as existsSync29, rmSync as rmSync4 } from "node:fs";
77841
77857
  var NPM_REGISTRY = "https://registry.npmjs.org";
77842
77858
  function assertSha256(actualHex, expectedHex) {
77843
77859
  if (actualHex !== expectedHex.toLowerCase()) {
@@ -77855,7 +77871,7 @@ function assertSha512Integrity(actualBase64, integrity) {
77855
77871
  }
77856
77872
  function discardPartial(destPath) {
77857
77873
  try {
77858
- if (existsSync30(destPath)) rmSync4(destPath, { force: true });
77874
+ if (existsSync29(destPath)) rmSync4(destPath, { force: true });
77859
77875
  } catch {
77860
77876
  }
77861
77877
  }
@@ -77936,13 +77952,13 @@ import {
77936
77952
  appendFileSync,
77937
77953
  createReadStream as createReadStream2,
77938
77954
  createWriteStream,
77939
- existsSync as existsSync31,
77940
- mkdirSync as mkdirSync19,
77955
+ existsSync as existsSync30,
77956
+ mkdirSync as mkdirSync18,
77941
77957
  rmSync as rmSync5,
77942
77958
  statSync as statSync10,
77943
- writeFileSync as writeFileSync14
77959
+ writeFileSync as writeFileSync13
77944
77960
  } from "node:fs";
77945
- import { dirname as dirname15 } from "node:path";
77961
+ import { dirname as dirname14 } from "node:path";
77946
77962
  import { pipeline } from "node:stream/promises";
77947
77963
  import { Readable as Readable2, Transform } from "node:stream";
77948
77964
  var HARNESS_PROGRESS_THROTTLE_MS = 200;
@@ -77973,7 +77989,7 @@ async function seedHashesFromFile(path) {
77973
77989
  const sha512 = createHash6("sha512");
77974
77990
  const size = statSync10(path).size;
77975
77991
  if (size === 0) return { sha256, sha512, size };
77976
- await new Promise((resolve14, reject) => {
77992
+ await new Promise((resolve15, reject) => {
77977
77993
  const stream = createReadStream2(path);
77978
77994
  stream.on("data", (chunk) => {
77979
77995
  const buf = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
@@ -77981,7 +77997,7 @@ async function seedHashesFromFile(path) {
77981
77997
  sha512.update(buf);
77982
77998
  });
77983
77999
  stream.on("error", reject);
77984
- stream.on("end", () => resolve14());
78000
+ stream.on("end", () => resolve15());
77985
78001
  });
77986
78002
  return { sha256, sha512, size };
77987
78003
  }
@@ -78003,7 +78019,7 @@ async function streamResponseToFile(res, destPath, onProgress, opts = {}) {
78003
78019
  const keepPartial = opts.keepPartialOnError !== false;
78004
78020
  const contentLen = Number(res.headers.get("content-length") ?? 0);
78005
78021
  const total = opts.totalBytes && opts.totalBytes > 0 ? opts.totalBytes : append ? resumeFrom + contentLen : contentLen;
78006
- mkdirSync19(dirname15(destPath), { recursive: true });
78022
+ mkdirSync18(dirname14(destPath), { recursive: true });
78007
78023
  const emit = createThrottledProgress(onProgress, opts.progressThrottleMs);
78008
78024
  let sha256;
78009
78025
  let sha512;
@@ -78029,7 +78045,7 @@ async function streamResponseToFile(res, destPath, onProgress, opts = {}) {
78029
78045
  if (append) {
78030
78046
  appendFileSync(destPath, buf);
78031
78047
  } else {
78032
- writeFileSync14(destPath, buf);
78048
+ writeFileSync13(destPath, buf);
78033
78049
  }
78034
78050
  sha256.update(buf);
78035
78051
  sha512.update(buf);
@@ -78061,7 +78077,7 @@ async function streamResponseToFile(res, destPath, onProgress, opts = {}) {
78061
78077
  } catch (err) {
78062
78078
  if (!keepPartial) {
78063
78079
  try {
78064
- if (existsSync31(destPath)) rmSync5(destPath, { force: true });
78080
+ if (existsSync30(destPath)) rmSync5(destPath, { force: true });
78065
78081
  } catch {
78066
78082
  }
78067
78083
  }
@@ -78078,8 +78094,8 @@ var destPathLocks = /* @__PURE__ */ new Map();
78078
78094
  async function withDestPathLock(destPath, fn) {
78079
78095
  const prev = destPathLocks.get(destPath) ?? Promise.resolve();
78080
78096
  let release;
78081
- const gate = new Promise((resolve14) => {
78082
- release = resolve14;
78097
+ const gate = new Promise((resolve15) => {
78098
+ release = resolve15;
78083
78099
  });
78084
78100
  const held = prev.then(() => gate);
78085
78101
  destPathLocks.set(
@@ -78105,14 +78121,14 @@ async function downloadResumableToFile(httpFetch, url2, destPath, onProgress, lo
78105
78121
  );
78106
78122
  }
78107
78123
  async function downloadResumableToFileUnlocked(httpFetch, url2, destPath, onProgress, log2) {
78108
- mkdirSync19(dirname15(destPath), { recursive: true });
78109
- let existing = existsSync31(destPath) ? statSync10(destPath).size : 0;
78124
+ mkdirSync18(dirname14(destPath), { recursive: true });
78125
+ let existing = existsSync30(destPath) ? statSync10(destPath).size : 0;
78110
78126
  if (existing > 0 && existing < 64) {
78111
78127
  rmSync5(destPath, { force: true });
78112
78128
  existing = 0;
78113
78129
  }
78114
78130
  const tryOnce = async (from) => {
78115
- const diskNow = existsSync31(destPath) ? statSync10(destPath).size : 0;
78131
+ const diskNow = existsSync30(destPath) ? statSync10(destPath).size : 0;
78116
78132
  const start = from > 0 ? diskNow : 0;
78117
78133
  if (from > 0 && diskNow !== from) {
78118
78134
  log2?.warn?.(
@@ -78194,17 +78210,17 @@ function createResumableDownloadToFile(httpFetch, log2) {
78194
78210
 
78195
78211
  // ../../packages/runtime/src/harness/managed-tarball-installer.ts
78196
78212
  import {
78197
- existsSync as existsSync32,
78198
- mkdirSync as mkdirSync20,
78213
+ existsSync as existsSync31,
78214
+ mkdirSync as mkdirSync19,
78199
78215
  mkdtempSync as mkdtempSync2,
78200
- readFileSync as readFileSync18,
78216
+ readFileSync as readFileSync17,
78201
78217
  renameSync as renameSync4,
78202
78218
  rmSync as rmSync6,
78203
78219
  statSync as statSync11,
78204
- writeFileSync as writeFileSync15
78220
+ writeFileSync as writeFileSync14
78205
78221
  } from "node:fs";
78206
78222
  import { tmpdir as tmpdir2 } from "node:os";
78207
- import { dirname as dirname16, join as join28 } from "node:path";
78223
+ import { dirname as dirname15, join as join27 } from "node:path";
78208
78224
  import { spawn as spawn4 } from "node:child_process";
78209
78225
 
78210
78226
  // ../../packages/shared/src/update-channels.ts
@@ -78284,7 +78300,7 @@ function resolveHarnessManifestChannel(explicit, releaseVersion) {
78284
78300
  return "alpha";
78285
78301
  }
78286
78302
  function harnessDownloadDir(homeRoot) {
78287
- return join28(homeRoot, ".download");
78303
+ return join27(homeRoot, ".download");
78288
78304
  }
78289
78305
  function harnessArtifactDownloadKey(opts) {
78290
78306
  const digest = opts.digestSha256?.trim().toLowerCase();
@@ -78298,11 +78314,11 @@ function harnessPartialPath(homeRoot, key) {
78298
78314
  if (!key || key.includes("..") || key.includes("/") || key.includes("\\")) {
78299
78315
  throw new Error(`unsafe download key: ${key}`);
78300
78316
  }
78301
- return join28(harnessDownloadDir(homeRoot), `${key}.partial`);
78317
+ return join27(harnessDownloadDir(homeRoot), `${key}.partial`);
78302
78318
  }
78303
78319
  function extractTgzWithSystemTar(tgzPath, destDir) {
78304
- return new Promise((resolve14, reject) => {
78305
- mkdirSync20(destDir, { recursive: true });
78320
+ return new Promise((resolve15, reject) => {
78321
+ mkdirSync19(destDir, { recursive: true });
78306
78322
  const child = spawn4("tar", ["-xzf", tgzPath, "-C", destDir], {
78307
78323
  stdio: ["ignore", "ignore", "pipe"]
78308
78324
  });
@@ -78312,19 +78328,19 @@ function extractTgzWithSystemTar(tgzPath, destDir) {
78312
78328
  });
78313
78329
  child.on("error", (err) => reject(new Error(`tar spawn failed: ${err.message}`)));
78314
78330
  child.on("close", (code) => {
78315
- if (code === 0) resolve14();
78331
+ if (code === 0) resolve15();
78316
78332
  else reject(new Error(`tar extract failed (exit ${code}): ${stderr.slice(-500)}`));
78317
78333
  });
78318
78334
  });
78319
78335
  }
78320
78336
  function installPackageDir(packageDir, prefix, nodeModulesRel) {
78321
- const dest = join28(prefix, "lib", "node_modules", ...nodeModulesRel.split("/"));
78322
- const parent = dirname16(dest);
78323
- mkdirSync20(parent, { recursive: true });
78324
- if (existsSync32(dest)) {
78337
+ const dest = join27(prefix, "lib", "node_modules", ...nodeModulesRel.split("/"));
78338
+ const parent = dirname15(dest);
78339
+ mkdirSync19(parent, { recursive: true });
78340
+ if (existsSync31(dest)) {
78325
78341
  rmSync6(dest, { recursive: true, force: true });
78326
78342
  }
78327
- const staging = join28(
78343
+ const staging = join27(
78328
78344
  parent,
78329
78345
  `.staging-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
78330
78346
  );
@@ -78332,7 +78348,7 @@ function installPackageDir(packageDir, prefix, nodeModulesRel) {
78332
78348
  renameSync4(packageDir, staging);
78333
78349
  renameSync4(staging, dest);
78334
78350
  } catch (err) {
78335
- if (existsSync32(staging)) rmSync6(staging, { recursive: true, force: true });
78351
+ if (existsSync31(staging)) rmSync6(staging, { recursive: true, force: true });
78336
78352
  throw err instanceof Error ? err : new Error(`failed to place package into ${dest}: ${String(err)}`);
78337
78353
  }
78338
78354
  return dest;
@@ -78354,8 +78370,8 @@ function resolveCodexNativeUnderPrefix(prefix) {
78354
78370
  if (!triple) return null;
78355
78371
  const binaryName = process.platform === "win32" ? "codex.exe" : "codex";
78356
78372
  const candidates = [
78357
- join28(prefix, "lib", "node_modules", "@openai", "codex", "vendor", triple, "bin", binaryName),
78358
- join28(
78373
+ join27(prefix, "lib", "node_modules", "@openai", "codex", "vendor", triple, "bin", binaryName),
78374
+ join27(
78359
78375
  prefix,
78360
78376
  "lib",
78361
78377
  "node_modules",
@@ -78368,7 +78384,7 @@ function resolveCodexNativeUnderPrefix(prefix) {
78368
78384
  )
78369
78385
  ];
78370
78386
  for (const c of candidates) {
78371
- if (existsSync32(c) && statSync11(c).isFile()) return c;
78387
+ if (existsSync31(c) && statSync11(c).isFile()) return c;
78372
78388
  }
78373
78389
  return null;
78374
78390
  }
@@ -78378,17 +78394,17 @@ function resolveManagedTarballBinary(id, installRoot) {
78378
78394
  }
78379
78395
  function readRuntimeVersionFromRoot(id, installRoot) {
78380
78396
  try {
78381
- const metaPath = join28(installRoot, "install-meta.json");
78382
- if (existsSync32(metaPath)) {
78383
- const raw = JSON.parse(readFileSync18(metaPath, "utf8"));
78397
+ const metaPath = join27(installRoot, "install-meta.json");
78398
+ if (existsSync31(metaPath)) {
78399
+ const raw = JSON.parse(readFileSync17(metaPath, "utf8"));
78384
78400
  if (raw.runtimeVersion) return raw.runtimeVersion;
78385
78401
  }
78386
78402
  } catch {
78387
78403
  }
78388
78404
  try {
78389
- const pkgPath = id === "claude" ? null : join28(installRoot, "lib", "node_modules", "@openai", "codex", "package.json");
78390
- if (pkgPath && existsSync32(pkgPath)) {
78391
- const raw = JSON.parse(readFileSync18(pkgPath, "utf8"));
78405
+ const pkgPath = id === "claude" ? null : join27(installRoot, "lib", "node_modules", "@openai", "codex", "package.json");
78406
+ if (pkgPath && existsSync31(pkgPath)) {
78407
+ const raw = JSON.parse(readFileSync17(pkgPath, "utf8"));
78392
78408
  const v2 = raw.version?.trim();
78393
78409
  if (!v2) return null;
78394
78410
  return v2.replace(/-(darwin|linux|win32)-(arm64|x64)$/, "");
@@ -78423,7 +78439,7 @@ function createManagedTarballInstaller(opts = {}) {
78423
78439
  return {
78424
78440
  async install(id, home, onProgress) {
78425
78441
  const prefix = managedHarnessPrefix(home.root, id);
78426
- mkdirSync20(prefix, { recursive: true });
78442
+ mkdirSync19(prefix, { recursive: true });
78427
78443
  const pins = managedPackagePins(id);
78428
78444
  const versionDir = managedVersionDir(prefix, pins.runtimeVersion);
78429
78445
  const previousPointer = readCurrentPointer(prefix)?.runtimeVersion ?? null;
@@ -78465,7 +78481,7 @@ function createManagedTarballInstaller(opts = {}) {
78465
78481
  const artifactPin = await resolveArtifactPin(id, channel, opts, fetchJson);
78466
78482
  let packageSpec = "";
78467
78483
  let source = "npm-tarball";
78468
- mkdirSync20(versionDir, { recursive: true });
78484
+ mkdirSync19(versionDir, { recursive: true });
78469
78485
  for (const pkg of pins.packages) {
78470
78486
  const npmName = artifactPin?.npmName ?? pkg.name;
78471
78487
  const npmVersion = artifactPin?.npmVersion ?? pkg.version;
@@ -78477,7 +78493,7 @@ function createManagedTarballInstaller(opts = {}) {
78477
78493
  npmVersion
78478
78494
  });
78479
78495
  const partialPath = harnessPartialPath(home.root, downloadKey);
78480
- const work = mkdtempSync2(join28(tmpdir2(), `superone-harness-${id}-`));
78496
+ const work = mkdtempSync2(join27(tmpdir2(), `superone-harness-${id}-`));
78481
78497
  try {
78482
78498
  const { from } = await fetchTarballWithFallback({
78483
78499
  destPath: partialPath,
@@ -78491,23 +78507,23 @@ function createManagedTarballInstaller(opts = {}) {
78491
78507
  log: log2
78492
78508
  });
78493
78509
  source = from;
78494
- const extractRoot = join28(work, "out");
78510
+ const extractRoot = join27(work, "out");
78495
78511
  await extractTgz(partialPath, extractRoot);
78496
- const packageDir = join28(extractRoot, "package");
78497
- if (!existsSync32(packageDir) || !statSync11(packageDir).isDirectory()) {
78512
+ const packageDir = join27(extractRoot, "package");
78513
+ if (!existsSync31(packageDir) || !statSync11(packageDir).isDirectory()) {
78498
78514
  throw new Error(`tarball for ${packageSpec} has no package/ directory`);
78499
78515
  }
78500
78516
  installPackageDir(packageDir, versionDir, npmName);
78501
78517
  try {
78502
- if (existsSync32(partialPath)) rmSync6(partialPath, { force: true });
78518
+ if (existsSync31(partialPath)) rmSync6(partialPath, { force: true });
78503
78519
  } catch {
78504
78520
  }
78505
78521
  } finally {
78506
78522
  rmSync6(work, { recursive: true, force: true });
78507
78523
  }
78508
78524
  }
78509
- writeFileSync15(
78510
- join28(versionDir, "install-meta.json"),
78525
+ writeFileSync14(
78526
+ join27(versionDir, "install-meta.json"),
78511
78527
  JSON.stringify(
78512
78528
  {
78513
78529
  harnessId: id,
@@ -78739,7 +78755,7 @@ function isAuthSatisfied(id, deps) {
78739
78755
 
78740
78756
  // ../../packages/runtime/src/harness/enable.ts
78741
78757
  init_environment();
78742
- import { accessSync, constants, existsSync as existsSync33, realpathSync as realpathSync3, statSync as statSync12 } from "node:fs";
78758
+ import { accessSync, constants, existsSync as existsSync32, realpathSync as realpathSync3, statSync as statSync12 } from "node:fs";
78743
78759
  import { isAbsolute as isAbsolute4, resolve as resolve8 } from "node:path";
78744
78760
  async function enableHarness(manager, input, deps) {
78745
78761
  const id = input.harnessId;
@@ -78958,7 +78974,7 @@ function requireRegularReadableFile(path) {
78958
78974
  throw new Error(`path must be absolute: ${path}`);
78959
78975
  }
78960
78976
  const abs = resolve8(path);
78961
- if (!existsSync33(abs) || !statSync12(abs).isFile()) {
78977
+ if (!existsSync32(abs) || !statSync12(abs).isFile()) {
78962
78978
  throw new Error(`not a regular file: ${abs}`);
78963
78979
  }
78964
78980
  accessSync(abs, constants.R_OK);
@@ -78967,7 +78983,7 @@ function requireRegularReadableFile(path) {
78967
78983
  function resolveExternalCommand(explicit, searchNames) {
78968
78984
  if (explicit) {
78969
78985
  const abs = isAbsolute4(explicit) ? explicit : resolve8(explicit);
78970
- if (!existsSync33(abs)) return null;
78986
+ if (!existsSync32(abs)) return null;
78971
78987
  try {
78972
78988
  if (!statSync12(abs).isFile()) return null;
78973
78989
  accessSync(abs, constants.X_OK);
@@ -78982,7 +78998,7 @@ function resolveExternalCommand(explicit, searchNames) {
78982
78998
  for (const dir of dirs) {
78983
78999
  if (!dir) continue;
78984
79000
  const candidate = resolve8(dir, name);
78985
- if (!existsSync33(candidate)) continue;
79001
+ if (!existsSync32(candidate)) continue;
78986
79002
  try {
78987
79003
  if (!statSync12(candidate).isFile()) continue;
78988
79004
  accessSync(candidate, constants.X_OK);
@@ -79037,7 +79053,7 @@ function looksLikeSecretArg(value) {
79037
79053
  }
79038
79054
 
79039
79055
  // src/session/harness-host.ts
79040
- import { existsSync as existsSync34 } from "node:fs";
79056
+ import { existsSync as existsSync33 } from "node:fs";
79041
79057
  init_src2();
79042
79058
  init_claude_turn_runner();
79043
79059
  init_codex_turn_runner();
@@ -79045,7 +79061,7 @@ init_resolve_service();
79045
79061
  setHarnessReleaseVersionProvider(resolveCliReleaseVersion);
79046
79062
  function envBinaryExists(envName) {
79047
79063
  const v2 = process.env[envName]?.trim();
79048
- return Boolean(v2 && existsSync34(v2));
79064
+ return Boolean(v2 && existsSync33(v2));
79049
79065
  }
79050
79066
  var cliHarnessResolver = {
79051
79067
  resolveBinary(id, harnesses) {
@@ -79055,7 +79071,7 @@ var cliHarnessResolver = {
79055
79071
  return null;
79056
79072
  }
79057
79073
  const command = harnesses.get(id).command;
79058
- return command && existsSync34(command) ? command : null;
79074
+ return command && existsSync33(command) ? command : null;
79059
79075
  },
79060
79076
  isRunnableWithoutCatalog(id) {
79061
79077
  if (id === "claude") return isClaudeRuntimeRunnable();
@@ -79068,7 +79084,7 @@ var cliHarnessResolver = {
79068
79084
  autoRuntime(id) {
79069
79085
  if (id === "claude") {
79070
79086
  const sdk = resolveSdkClaudeBinary();
79071
- if (sdk && existsSync34(sdk)) return { command: sdk, source: "agent-sdk-optional" };
79087
+ if (sdk && existsSync33(sdk)) return { command: sdk, source: "agent-sdk-optional" };
79072
79088
  return null;
79073
79089
  }
79074
79090
  const fromEnv = resolveCodexBinaryPath({});
@@ -79210,7 +79226,7 @@ async function startNodeServer2(opts) {
79210
79226
 
79211
79227
  // src/terminal/manager.ts
79212
79228
  import { createRequire as createRequire5 } from "node:module";
79213
- import { existsSync as existsSync35 } from "node:fs";
79229
+ import { existsSync as existsSync34 } from "node:fs";
79214
79230
  var nodeRequire = createRequire5(import.meta.url);
79215
79231
  var { spawn: spawn5 } = nodeRequire("node-pty");
79216
79232
  var SNAPSHOT_SOFT_LIMIT = 64 * 1024;
@@ -79225,7 +79241,7 @@ var NodeTerminalManager = class {
79225
79241
  }
79226
79242
  byId = /* @__PURE__ */ new Map();
79227
79243
  create(opts) {
79228
- if (!existsSync35(opts.cwd)) {
79244
+ if (!existsSync34(opts.cwd)) {
79229
79245
  throw Object.assign(new Error(`cwd does not exist: ${opts.cwd}`), { code: "invalid_argument" });
79230
79246
  }
79231
79247
  const terminalId = crypto.randomUUID();
@@ -79365,38 +79381,83 @@ var NodeTerminalManager = class {
79365
79381
  };
79366
79382
 
79367
79383
  // ../../packages/runtime/src/workspace/project-registry.ts
79368
- import { basename as basename2, resolve as resolve9 } from "node:path";
79369
- import { existsSync as existsSync36, realpathSync as realpathSync4, statSync as statSync13 } from "node:fs";
79384
+ import { basename as basename2, resolve as resolve10 } from "node:path";
79385
+ import { existsSync as existsSync35, realpathSync as realpathSync4, statSync as statSync13 } from "node:fs";
79370
79386
  import { createHash as createHash7 } from "node:crypto";
79371
79387
  import { execFileSync as execFileSync2 } from "node:child_process";
79388
+
79389
+ // ../../packages/shared/src/project-extra-dirs.ts
79390
+ var MAX_PROJECT_EXTRA_DIRS = 16;
79391
+ function parseProjectExtraDirs(raw) {
79392
+ if (typeof raw !== "string" || !raw.trim()) return [];
79393
+ try {
79394
+ const parsed = JSON.parse(raw);
79395
+ if (!Array.isArray(parsed)) return [];
79396
+ return dedupeDirs(parsed.filter((d) => typeof d === "string" && d.trim().length > 0));
79397
+ } catch {
79398
+ return [];
79399
+ }
79400
+ }
79401
+ function dedupeDirs(dirs) {
79402
+ return [...new Set(dirs)];
79403
+ }
79404
+ function resolveProjectExtraDirs(current, patch) {
79405
+ if (patch.extraDirs !== void 0) return [...patch.extraDirs];
79406
+ if (patch.addExtraDirs === void 0 && patch.removeExtraDirs === void 0) return null;
79407
+ const removed = new Set(patch.removeExtraDirs ?? []);
79408
+ return [...current.filter((d) => !removed.has(d)), ...patch.addExtraDirs ?? []];
79409
+ }
79410
+
79411
+ // ../../packages/shared/src/project-extra-dirs-node.ts
79412
+ import { resolve as resolve9 } from "node:path";
79413
+ function normalizeProjectExtraDirs(dirs, projectPath) {
79414
+ const root = resolve9(projectPath);
79415
+ const normalized = dirs.filter((d) => typeof d === "string" && d.trim().length > 0).map((d) => resolve9(d.trim())).filter((d) => d !== root);
79416
+ return dedupeDirs(normalized).slice(0, MAX_PROJECT_EXTRA_DIRS);
79417
+ }
79418
+
79419
+ // ../../packages/runtime/src/workspace/project-registry.ts
79372
79420
  var ProjectRegistry = class {
79373
79421
  constructor(db) {
79374
79422
  this.db = db;
79375
79423
  }
79376
79424
  list() {
79377
79425
  const rows = this.db.prepare(
79378
- `SELECT project_id, path, name, repo_identity, opened_at, last_active_at FROM projects ORDER BY last_active_at DESC`
79426
+ `SELECT project_id, path, name, repo_identity, opened_at, last_active_at, extra_dirs_json FROM projects ORDER BY last_active_at DESC`
79379
79427
  ).all();
79380
79428
  return rows.map((r) => this.toSnapshot(r));
79381
79429
  }
79382
79430
  get(projectId) {
79383
79431
  const r = this.db.prepare(
79384
- `SELECT project_id, path, name, repo_identity, opened_at, last_active_at FROM projects WHERE project_id = ?`
79432
+ `SELECT project_id, path, name, repo_identity, opened_at, last_active_at, extra_dirs_json FROM projects WHERE project_id = ?`
79385
79433
  ).get(projectId);
79386
79434
  if (!r) return null;
79387
79435
  return this.toSnapshot(r);
79388
79436
  }
79437
+ /**
79438
+ * `open()` stores the realpath, so a caller handing back the path the user
79439
+ * typed must be canonicalized the same way or it misses whenever a parent is
79440
+ * a symlink (`/var` on macOS). Belongs here rather than at each call site:
79441
+ * `update({ path })` and `remove({ path })` both take user-facing spellings.
79442
+ */
79389
79443
  getByPath(path) {
79390
- const abs = resolve9(path);
79444
+ const abs = resolve10(path);
79391
79445
  const r = this.db.prepare(
79392
- `SELECT project_id, path, name, repo_identity, opened_at, last_active_at FROM projects WHERE path = ?`
79446
+ `SELECT project_id, path, name, repo_identity, opened_at, last_active_at, extra_dirs_json FROM projects WHERE path = ?`
79393
79447
  ).get(abs);
79394
- if (!r) return null;
79395
- return this.toSnapshot(r);
79448
+ if (r) return this.toSnapshot(r);
79449
+ let real;
79450
+ try {
79451
+ real = realpathSync4(abs);
79452
+ } catch {
79453
+ return null;
79454
+ }
79455
+ if (real === abs) return null;
79456
+ return this.getByPath(real);
79396
79457
  }
79397
79458
  open(path, name) {
79398
- let abs = resolve9(path);
79399
- if (!existsSync36(abs) || !statSync13(abs).isDirectory()) {
79459
+ let abs = resolve10(path);
79460
+ if (!existsSync35(abs) || !statSync13(abs).isDirectory()) {
79400
79461
  throw Object.assign(new Error(`project path is not a directory: ${abs}`), {
79401
79462
  code: "invalid_argument"
79402
79463
  });
@@ -79419,6 +79480,36 @@ var ProjectRegistry = class {
79419
79480
  ).run(projectId, abs, name || basename2(abs), repoIdentity, now, now);
79420
79481
  return this.get(projectId);
79421
79482
  }
79483
+ /**
79484
+ * Apply an Edit Project submission or an `/add-dir` delta.
79485
+ *
79486
+ * Both fields are optional and independent so one patch covers whatever the
79487
+ * user actually touched. Unlike `open()`, a name given here is authoritative:
79488
+ * it is an explicit rename, not a basename refresh.
79489
+ */
79490
+ update(input) {
79491
+ const existing = input.projectId ? this.get(input.projectId) : input.path ? this.getByPath(input.path) : null;
79492
+ if (!existing) return null;
79493
+ let nextName = null;
79494
+ if (input.name !== void 0) {
79495
+ const trimmed = input.name.trim();
79496
+ if (!trimmed) {
79497
+ throw Object.assign(new Error("project name cannot be empty"), {
79498
+ code: "invalid_argument"
79499
+ });
79500
+ }
79501
+ nextName = trimmed.slice(0, 200);
79502
+ }
79503
+ const resolved = resolveProjectExtraDirs(existing.extraDirs ?? [], input);
79504
+ const nextExtraDirs = resolved === null ? null : JSON.stringify(normalizeProjectExtraDirs(resolved, existing.path));
79505
+ this.db.prepare(
79506
+ `UPDATE projects
79507
+ SET name = COALESCE(?, name),
79508
+ extra_dirs_json = COALESCE(?, extra_dirs_json)
79509
+ WHERE project_id = ?`
79510
+ ).run(nextName, nextExtraDirs, existing.projectId);
79511
+ return this.get(existing.projectId);
79512
+ }
79422
79513
  touch(projectId) {
79423
79514
  this.db.prepare(`UPDATE projects SET last_active_at = ? WHERE project_id = ?`).run(Date.now(), projectId);
79424
79515
  }
@@ -79449,6 +79540,7 @@ var ProjectRegistry = class {
79449
79540
  path: r.path,
79450
79541
  name: r.name,
79451
79542
  ...missing ? { missing: true } : {},
79543
+ extraDirs: parseProjectExtraDirs(r.extra_dirs_json),
79452
79544
  repoIdentity: r.repo_identity,
79453
79545
  openedAt: r.opened_at ?? void 0,
79454
79546
  lastActiveAt: r.last_active_at ?? void 0
@@ -79470,7 +79562,7 @@ function detectRepoIdentity(abs) {
79470
79562
  if (remote) return `git:${remote}`;
79471
79563
  } catch {
79472
79564
  }
79473
- return `gitdir:${resolve9(abs, out)}`;
79565
+ return `gitdir:${resolve10(abs, out)}`;
79474
79566
  } catch {
79475
79567
  return null;
79476
79568
  }
@@ -79480,20 +79572,20 @@ function detectRepoIdentity(abs) {
79480
79572
  init_fs();
79481
79573
  import {
79482
79574
  closeSync,
79483
- existsSync as existsSync37,
79575
+ existsSync as existsSync36,
79484
79576
  fstatSync,
79485
- mkdirSync as mkdirSync21,
79577
+ mkdirSync as mkdirSync20,
79486
79578
  openSync,
79487
79579
  readSync,
79488
79580
  readdirSync as readdirSync11,
79489
- readFileSync as readFileSync19,
79581
+ readFileSync as readFileSync18,
79490
79582
  renameSync as renameSync5,
79491
79583
  rmSync as rmSync7,
79492
79584
  statSync as statSync14,
79493
79585
  unlinkSync,
79494
- writeFileSync as writeFileSync16
79586
+ writeFileSync as writeFileSync15
79495
79587
  } from "node:fs";
79496
- import { dirname as dirname17, join as join29, relative as relative2 } from "node:path";
79588
+ import { dirname as dirname16, join as join28, relative as relative2 } from "node:path";
79497
79589
  import { createHash as createHash8 } from "node:crypto";
79498
79590
  function normalizeRel(path) {
79499
79591
  return path.replace(/\\/g, "/").replace(/\/+$/, "") || ".";
@@ -79539,7 +79631,7 @@ var WorkspaceFsService = class {
79539
79631
  if (!resolved.ok) {
79540
79632
  throw Object.assign(new Error(resolved.reason), { code: "invalid_argument" });
79541
79633
  }
79542
- if (!existsSync37(resolved.absolutePath)) {
79634
+ if (!existsSync36(resolved.absolutePath)) {
79543
79635
  throw Object.assign(new Error("path not found"), { code: "not_found" });
79544
79636
  }
79545
79637
  const st = statSync14(resolved.absolutePath);
@@ -79549,7 +79641,7 @@ var WorkspaceFsService = class {
79549
79641
  this.projects.touch(projectId);
79550
79642
  const ents = readdirSync11(resolved.absolutePath, { withFileTypes: true });
79551
79643
  return ents.map((ent) => {
79552
- const abs = join29(resolved.absolutePath, ent.name);
79644
+ const abs = join28(resolved.absolutePath, ent.name);
79553
79645
  let size;
79554
79646
  let mtimeMs;
79555
79647
  try {
@@ -79574,7 +79666,7 @@ var WorkspaceFsService = class {
79574
79666
  if (!resolved.ok) {
79575
79667
  throw Object.assign(new Error(resolved.reason), { code: "invalid_argument" });
79576
79668
  }
79577
- if (!existsSync37(resolved.absolutePath)) {
79669
+ if (!existsSync36(resolved.absolutePath)) {
79578
79670
  throw Object.assign(new Error("file not found"), { code: "not_found" });
79579
79671
  }
79580
79672
  const st = statSync14(resolved.absolutePath);
@@ -79613,7 +79705,7 @@ var WorkspaceFsService = class {
79613
79705
  if (!resolved.ok) {
79614
79706
  throw Object.assign(new Error(resolved.reason), { code: "invalid_argument" });
79615
79707
  }
79616
- if (existsSync37(resolved.absolutePath) && expectedHash) {
79708
+ if (existsSync36(resolved.absolutePath) && expectedHash) {
79617
79709
  const st = statSync14(resolved.absolutePath);
79618
79710
  if (st.size > MAX_READ_BYTES) {
79619
79711
  throw Object.assign(
@@ -79626,13 +79718,13 @@ var WorkspaceFsService = class {
79626
79718
  throw Object.assign(new Error("content hash mismatch"), { code: "conflict" });
79627
79719
  }
79628
79720
  }
79629
- mkdirSync21(dirname17(resolved.absolutePath), { recursive: true });
79721
+ mkdirSync20(dirname16(resolved.absolutePath), { recursive: true });
79630
79722
  const data = typeof content === "string" ? Buffer.from(content, "utf8") : Buffer.from(content);
79631
79723
  if (data.length > MAX_READ_BYTES) {
79632
79724
  throw Object.assign(new Error("write payload too large"), { code: "invalid_argument" });
79633
79725
  }
79634
79726
  let mode = 384;
79635
- if (existsSync37(resolved.absolutePath)) {
79727
+ if (existsSync36(resolved.absolutePath)) {
79636
79728
  try {
79637
79729
  mode = statSync14(resolved.absolutePath).mode & 511;
79638
79730
  } catch {
@@ -79641,7 +79733,7 @@ var WorkspaceFsService = class {
79641
79733
  const tmp = `${resolved.absolutePath}.tmp-${crypto.randomUUID()}`;
79642
79734
  let renamed = false;
79643
79735
  try {
79644
- writeFileSync16(tmp, data, { mode });
79736
+ writeFileSync15(tmp, data, { mode });
79645
79737
  const again = resolveProjectPath(root, relativePath);
79646
79738
  if (!again.ok || again.absolutePath !== resolved.absolutePath) {
79647
79739
  throw Object.assign(new Error("path changed during write"), { code: "failed_precondition" });
@@ -79702,7 +79794,7 @@ var WorkspaceFsService = class {
79702
79794
  for (const ent of ents) {
79703
79795
  if (hits.length >= MAX_SEARCH_HITS) return;
79704
79796
  if (ent.name === ".git" || ent.name === "node_modules") continue;
79705
- const abs = join29(dir, ent.name);
79797
+ const abs = join28(dir, ent.name);
79706
79798
  const rel = relative2(root, abs).split("\\").join("/");
79707
79799
  const check2 = resolveProjectPath(root, rel);
79708
79800
  if (!check2.ok) continue;
@@ -79714,7 +79806,7 @@ var WorkspaceFsService = class {
79714
79806
  try {
79715
79807
  const st = statSync14(abs);
79716
79808
  if (st.size > MAX_SEARCH_FILE_BYTES) continue;
79717
- const text = readFileSync19(abs, "utf8");
79809
+ const text = readFileSync18(abs, "utf8");
79718
79810
  const lines = text.split(/\r?\n/);
79719
79811
  for (let i = 0; i < lines.length; i++) {
79720
79812
  if (lines[i].includes(query)) {
@@ -79776,7 +79868,7 @@ var WorkspaceFsService = class {
79776
79868
  if (!resolved.ok) {
79777
79869
  throw Object.assign(new Error(resolved.reason), { code: "invalid_argument" });
79778
79870
  }
79779
- if (existsSync37(resolved.absolutePath)) {
79871
+ if (existsSync36(resolved.absolutePath)) {
79780
79872
  const st = statSync14(resolved.absolutePath);
79781
79873
  if (!st.isDirectory()) {
79782
79874
  throw Object.assign(new Error("path exists and is not a directory"), { code: "conflict" });
@@ -79784,7 +79876,7 @@ var WorkspaceFsService = class {
79784
79876
  this.projects.touch(projectId);
79785
79877
  return { path: rel };
79786
79878
  }
79787
- mkdirSync21(resolved.absolutePath, { recursive: true });
79879
+ mkdirSync20(resolved.absolutePath, { recursive: true });
79788
79880
  this.projects.touch(projectId);
79789
79881
  return { path: rel };
79790
79882
  }
@@ -79799,7 +79891,7 @@ var WorkspaceFsService = class {
79799
79891
  if (!resolved.ok) {
79800
79892
  throw Object.assign(new Error(resolved.reason), { code: "invalid_argument" });
79801
79893
  }
79802
- if (!existsSync37(resolved.absolutePath)) {
79894
+ if (!existsSync36(resolved.absolutePath)) {
79803
79895
  throw Object.assign(new Error("path not found"), { code: "not_found" });
79804
79896
  }
79805
79897
  if (resolved.absolutePath === root) {
@@ -79823,19 +79915,19 @@ var WorkspaceFsService = class {
79823
79915
  if (!from.ok) {
79824
79916
  throw Object.assign(new Error(from.reason), { code: "invalid_argument" });
79825
79917
  }
79826
- if (!existsSync37(from.absolutePath)) {
79918
+ if (!existsSync36(from.absolutePath)) {
79827
79919
  throw Object.assign(new Error("source not found"), { code: "not_found" });
79828
79920
  }
79829
79921
  const to = resolveProjectPath(root, toN);
79830
79922
  if (!to.ok) {
79831
79923
  throw Object.assign(new Error(to.reason), { code: "invalid_argument" });
79832
79924
  }
79833
- if (existsSync37(to.absolutePath)) {
79925
+ if (existsSync36(to.absolutePath)) {
79834
79926
  throw Object.assign(new Error(`target already exists: ${baseNameRel(toN)}`), {
79835
79927
  code: "conflict"
79836
79928
  });
79837
79929
  }
79838
- mkdirSync21(dirname17(to.absolutePath), { recursive: true });
79930
+ mkdirSync20(dirname16(to.absolutePath), { recursive: true });
79839
79931
  renameSync5(from.absolutePath, to.absolutePath);
79840
79932
  this.projects.touch(projectId);
79841
79933
  return { from: fromN, to: toN };
@@ -79860,8 +79952,8 @@ function hashFileBounded(absolutePath, size) {
79860
79952
  }
79861
79953
 
79862
79954
  // src/workspace/git-service.ts
79863
- import { existsSync as existsSync38, mkdirSync as mkdirSync22, realpathSync as realpathSync5, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "node:fs";
79864
- import { join as join31, resolve as resolve11 } from "node:path";
79955
+ import { existsSync as existsSync37, mkdirSync as mkdirSync21, realpathSync as realpathSync5, rmSync as rmSync8, writeFileSync as writeFileSync16 } from "node:fs";
79956
+ import { join as join30, resolve as resolve12 } from "node:path";
79865
79957
  import { tmpdir as tmpdir3 } from "node:os";
79866
79958
  import { randomUUID as randomUUID8 } from "node:crypto";
79867
79959
 
@@ -79938,19 +80030,19 @@ function gitRunSync(folderPath, args, env) {
79938
80030
  }
79939
80031
 
79940
80032
  // ../../packages/runtime/src/git/worktree-plan.ts
79941
- import { basename as basename3, dirname as dirname18, join as join30, resolve as resolve10, sep as sep4 } from "node:path";
80033
+ import { basename as basename3, dirname as dirname17, join as join29, resolve as resolve11, sep as sep4 } from "node:path";
79942
80034
  import { homedir as homedir8 } from "node:os";
79943
80035
  function resolveMainDirFromCommonDir(folderPath, gitCommonDir) {
79944
- const repoRoot = resolve10(folderPath, gitCommonDir.trim());
79945
- return repoRoot.endsWith(`${sep4}.git`) || repoRoot.endsWith("/.git") ? dirname18(repoRoot) : repoRoot;
80036
+ const repoRoot = resolve11(folderPath, gitCommonDir.trim());
80037
+ return repoRoot.endsWith(`${sep4}.git`) || repoRoot.endsWith("/.git") ? dirname17(repoRoot) : repoRoot;
79946
80038
  }
79947
80039
  function planNewWorktreePaths(input) {
79948
80040
  const home = input.homeDir ?? homedir8();
79949
80041
  const repoName = basename3(input.mainDir);
79950
80042
  const epoch = Math.floor((input.nowMs ?? Date.now()) / 1e3).toString(36);
79951
80043
  const short = input.shortHash.slice(0, 7);
79952
- const wtDir = join30(home, ".worktrees", repoName);
79953
- const wtPath = join30(wtDir, `${epoch}-${short}`);
80044
+ const wtDir = join29(home, ".worktrees", repoName);
80045
+ const wtPath = join29(wtDir, `${epoch}-${short}`);
79954
80046
  return { wtDir, wtPath };
79955
80047
  }
79956
80048
  function worktreeAddArgs(mode, wtPath, baseRef, branchName) {
@@ -80009,11 +80101,11 @@ function resolveMainWorktreeDir(folderPath) {
80009
80101
  }
80010
80102
  function samePath(a, b2) {
80011
80103
  try {
80012
- const ra = existsSync38(a) ? realpathSync5(a) : resolve11(a);
80013
- const rb = existsSync38(b2) ? realpathSync5(b2) : resolve11(b2);
80104
+ const ra = existsSync37(a) ? realpathSync5(a) : resolve12(a);
80105
+ const rb = existsSync37(b2) ? realpathSync5(b2) : resolve12(b2);
80014
80106
  return ra === rb;
80015
80107
  } catch {
80016
- return resolve11(a) === resolve11(b2);
80108
+ return resolve12(a) === resolve12(b2);
80017
80109
  }
80018
80110
  }
80019
80111
  var WorkspaceGitService = class {
@@ -80042,7 +80134,7 @@ var WorkspaceGitService = class {
80042
80134
  * --ignored walks the whole tree of ignored paths and dominates remote latency.
80043
80135
  */
80044
80136
  statusForCwd(cwd) {
80045
- if (!existsSync38(join31(cwd, ".git")) && !isGitWorktree(cwd)) {
80137
+ if (!existsSync37(join30(cwd, ".git")) && !isGitWorktree(cwd)) {
80046
80138
  return { isRepo: false, branch: null, dirty: false, ahead: 0, behind: 0, porcelain: "" };
80047
80139
  }
80048
80140
  try {
@@ -80149,19 +80241,19 @@ var WorkspaceGitService = class {
80149
80241
  if (worktreePath.includes("\0") || worktreePath.includes("..")) {
80150
80242
  throw Object.assign(new Error("invalid worktree path"), { code: "invalid_argument" });
80151
80243
  }
80152
- const abs = resolve11(worktreePath);
80153
- const main2 = resolve11(this.root(projectId));
80154
- if (samePath(abs, main2)) return existsSync38(abs) ? realpathSync5(abs) : abs;
80244
+ const abs = resolve12(worktreePath);
80245
+ const main2 = resolve12(this.root(projectId));
80246
+ if (samePath(abs, main2)) return existsSync37(abs) ? realpathSync5(abs) : abs;
80155
80247
  const listed = this.worktrees(projectId);
80156
80248
  for (const wt of listed) {
80157
80249
  if (samePath(abs, wt.path)) {
80158
- return existsSync38(abs) ? realpathSync5(abs) : resolve11(wt.path);
80250
+ return existsSync37(abs) ? realpathSync5(abs) : resolve12(wt.path);
80159
80251
  }
80160
80252
  }
80161
80253
  try {
80162
- if (existsSync38(abs) && isGitWorktree(abs)) {
80163
- const commonA = resolve11(abs, git(abs, ["rev-parse", "--git-common-dir"]).trim());
80164
- const commonB = resolve11(main2, git(main2, ["rev-parse", "--git-common-dir"]).trim());
80254
+ if (existsSync37(abs) && isGitWorktree(abs)) {
80255
+ const commonA = resolve12(abs, git(abs, ["rev-parse", "--git-common-dir"]).trim());
80256
+ const commonB = resolve12(main2, git(main2, ["rev-parse", "--git-common-dir"]).trim());
80165
80257
  if (samePath(commonA, commonB)) {
80166
80258
  return realpathSync5(abs);
80167
80259
  }
@@ -80201,7 +80293,7 @@ var WorkspaceGitService = class {
80201
80293
  mainDir,
80202
80294
  shortHash: commitHash.slice(0, 7)
80203
80295
  });
80204
- if (!existsSync38(wtDir)) mkdirSync22(wtDir, { recursive: true });
80296
+ if (!existsSync37(wtDir)) mkdirSync21(wtDir, { recursive: true });
80205
80297
  try {
80206
80298
  const addArgs = worktreeAddArgs(mode, wtPath, baseBranch, safeBranchName);
80207
80299
  git(folderPath, ["worktree", ...addArgs]);
@@ -80297,8 +80389,8 @@ var WorkspaceGitService = class {
80297
80389
  const mainStatus = git(diff.mainDir, ["status", "--porcelain"]).trim();
80298
80390
  if (mainStatus) return { ok: false, reason: "main-dirty" };
80299
80391
  const patch = git(diff.worktreePath, ["diff", "--binary", diff.base, diff.tree]);
80300
- const patchFile = join31(tmpdir3(), `s1-handoff-${randomUUID8()}.patch`);
80301
- writeFileSync17(patchFile, `${patch}
80392
+ const patchFile = join30(tmpdir3(), `s1-handoff-${randomUUID8()}.patch`);
80393
+ writeFileSync16(patchFile, `${patch}
80302
80394
  `);
80303
80395
  if (git(diff.mainDir, ["status", "--porcelain"]).trim()) {
80304
80396
  rmSync8(patchFile, { force: true });
@@ -80359,7 +80451,7 @@ var WorkspaceGitService = class {
80359
80451
  };
80360
80452
  }
80361
80453
  writeWorkingTree(worktreePath) {
80362
- const tmpIndex = join31(tmpdir3(), `s1-handoff-${randomUUID8()}.index`);
80454
+ const tmpIndex = join30(tmpdir3(), `s1-handoff-${randomUUID8()}.index`);
80363
80455
  const env = { GIT_INDEX_FILE: tmpIndex };
80364
80456
  try {
80365
80457
  git(worktreePath, ["read-tree", "HEAD"], env);
@@ -80555,7 +80647,7 @@ init_codex_turn_runner();
80555
80647
  init_agent_types();
80556
80648
  init_environment();
80557
80649
  import { createHash as createHash9, randomBytes as randomBytes5, randomUUID as randomUUID10 } from "node:crypto";
80558
- import { existsSync as existsSync39, statSync as statSync15 } from "node:fs";
80650
+ import { existsSync as existsSync38, statSync as statSync15 } from "node:fs";
80559
80651
  import { resolve as pathResolve2 } from "node:path";
80560
80652
 
80561
80653
  // ../../packages/shared/src/harness/acp-brand.ts
@@ -81551,7 +81643,7 @@ var CollaborationService = class {
81551
81643
  const project = this.deps.projects.get(projectId);
81552
81644
  const fallback = parentCwd || project?.path || process.cwd();
81553
81645
  const cwd = pathResolve2(config2.cwd || fallback);
81554
- if (!existsSync39(cwd) || !statSync15(cwd).isDirectory()) {
81646
+ if (!existsSync38(cwd) || !statSync15(cwd).isDirectory()) {
81555
81647
  throw Object.assign(new Error(`Working directory does not exist: ${cwd}`), {
81556
81648
  code: "invalid_argument"
81557
81649
  });
@@ -81703,8 +81795,8 @@ var CollaborationService = class {
81703
81795
  };
81704
81796
 
81705
81797
  // src/provider/secret-crypto.ts
81706
- import { existsSync as existsSync40, mkdirSync as mkdirSync23, readFileSync as readFileSync20, writeFileSync as writeFileSync18, chmodSync as chmodSync2 } from "node:fs";
81707
- import { dirname as dirname19 } from "node:path";
81798
+ import { existsSync as existsSync39, mkdirSync as mkdirSync22, readFileSync as readFileSync19, writeFileSync as writeFileSync17, chmodSync as chmodSync2 } from "node:fs";
81799
+ import { dirname as dirname18 } from "node:path";
81708
81800
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes6 } from "node:crypto";
81709
81801
  var ENC_PREFIX2 = "enc:v1:";
81710
81802
  var KEY_BYTES = 32;
@@ -81712,13 +81804,13 @@ function isEncryptedSecret(value) {
81712
81804
  return typeof value === "string" && value.startsWith(ENC_PREFIX2);
81713
81805
  }
81714
81806
  function ensureKeyFile(keyPath) {
81715
- if (existsSync40(keyPath)) {
81716
- const raw = readFileSync20(keyPath);
81807
+ if (existsSync39(keyPath)) {
81808
+ const raw = readFileSync19(keyPath);
81717
81809
  if (raw.length === KEY_BYTES) return raw;
81718
81810
  }
81719
- mkdirSync23(dirname19(keyPath), { recursive: true, mode: 448 });
81811
+ mkdirSync22(dirname18(keyPath), { recursive: true, mode: 448 });
81720
81812
  const key = randomBytes6(KEY_BYTES);
81721
- writeFileSync18(keyPath, key, { mode: 384 });
81813
+ writeFileSync17(keyPath, key, { mode: 384 });
81722
81814
  try {
81723
81815
  chmodSync2(keyPath, 384);
81724
81816
  } catch {
@@ -81800,9 +81892,9 @@ var WorkspaceWatchService = class {
81800
81892
  try {
81801
81893
  while (!closed) {
81802
81894
  if (queue.length === 0) {
81803
- await new Promise((resolve14) => {
81804
- wake = resolve14;
81805
- setTimeout(() => resolve14(), 100);
81895
+ await new Promise((resolve15) => {
81896
+ wake = resolve15;
81897
+ setTimeout(() => resolve15(), 100);
81806
81898
  });
81807
81899
  wake = null;
81808
81900
  continue;
@@ -81860,7 +81952,7 @@ var WorkspaceWatchService = class {
81860
81952
 
81861
81953
  // src/workspace/tail-watch-service.ts
81862
81954
  init_fs();
81863
- import { existsSync as existsSync41, fstatSync as fstatSync2, openSync as openSync2, closeSync as closeSync2, statSync as statSync16, readSync as readSync2, realpathSync as realpathSync6 } from "node:fs";
81955
+ import { existsSync as existsSync40, fstatSync as fstatSync2, openSync as openSync2, closeSync as closeSync2, statSync as statSync16, readSync as readSync2, realpathSync as realpathSync6 } from "node:fs";
81864
81956
  var MAX_POLL_BYTES = 10 * 1024 * 1024;
81865
81957
  var WorkspaceTailWatchService = class {
81866
81958
  constructor(projects, fs) {
@@ -81882,7 +81974,7 @@ var WorkspaceTailWatchService = class {
81882
81974
  );
81883
81975
  }
81884
81976
  try {
81885
- resolvedAbs = existsSync41(absolutePath) ? realpathSync6(absolutePath) : absolutePath;
81977
+ resolvedAbs = existsSync40(absolutePath) ? realpathSync6(absolutePath) : absolutePath;
81886
81978
  } catch {
81887
81979
  resolvedAbs = absolutePath;
81888
81980
  }
@@ -81913,7 +82005,7 @@ var WorkspaceTailWatchService = class {
81913
82005
  code: "invalid_argument"
81914
82006
  });
81915
82007
  }
81916
- if (existsSync41(resolvedAbs)) {
82008
+ if (existsSync40(resolvedAbs)) {
81917
82009
  try {
81918
82010
  const st = statSync16(resolvedAbs);
81919
82011
  if (!st.isFile()) {
@@ -81964,7 +82056,7 @@ var WorkspaceTailWatchService = class {
81964
82056
  { code: "invalid_argument" }
81965
82057
  );
81966
82058
  }
81967
- if (!existsSync41(absolutePath)) {
82059
+ if (!existsSync40(absolutePath)) {
81968
82060
  return {
81969
82061
  content: "",
81970
82062
  encoding: "base64",
@@ -82810,7 +82902,7 @@ var readBodyDirect = (request) => {
82810
82902
  request[bodyBufferKey] = buffered;
82811
82903
  return Promise.resolve(buffered);
82812
82904
  }
82813
- const promise2 = new Promise((resolve14, reject) => {
82905
+ const promise2 = new Promise((resolve15, reject) => {
82814
82906
  const chunks = [];
82815
82907
  let settled = false;
82816
82908
  const finish = (callback) => {
@@ -82828,7 +82920,7 @@ var readBodyDirect = (request) => {
82828
82920
  else if (recovered === void 0) reject(error51 ?? normalizeAbortError(request, incoming));
82829
82921
  else {
82830
82922
  request[bodyBufferKey] = recovered;
82831
- resolve14(recovered);
82923
+ resolve15(recovered);
82832
82924
  }
82833
82925
  });
82834
82926
  return true;
@@ -82840,7 +82932,7 @@ var readBodyDirect = (request) => {
82840
82932
  finish(() => {
82841
82933
  const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
82842
82934
  request[bodyBufferKey] = buffer;
82843
- resolve14(buffer);
82935
+ resolve15(buffer);
82844
82936
  });
82845
82937
  };
82846
82938
  const onError = (error51) => {
@@ -83365,7 +83457,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
83365
83457
  });
83366
83458
  if (!chunk) {
83367
83459
  if (i === 1) {
83368
- await new Promise((resolve14) => setTimeout(resolve14));
83460
+ await new Promise((resolve15) => setTimeout(resolve15));
83369
83461
  maxReadCount = 3;
83370
83462
  continue;
83371
83463
  }
@@ -85579,9 +85671,9 @@ data:
85579
85671
  const initRequest = messages.find((m2) => isInitializeRequest(m2));
85580
85672
  const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
85581
85673
  if (this._enableJsonResponse) {
85582
- return new Promise((resolve14) => {
85674
+ return new Promise((resolve15) => {
85583
85675
  this._streamMapping.set(streamId, {
85584
- resolveJson: resolve14,
85676
+ resolveJson: resolve15,
85585
85677
  cleanup: () => {
85586
85678
  this._streamMapping.delete(streamId);
85587
85679
  }
@@ -91898,7 +91990,7 @@ var Protocol = class {
91898
91990
  return;
91899
91991
  }
91900
91992
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
91901
- await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
91993
+ await new Promise((resolve15) => setTimeout(resolve15, pollInterval));
91902
91994
  options?.signal?.throwIfAborted();
91903
91995
  }
91904
91996
  } catch (error51) {
@@ -91915,7 +92007,7 @@ var Protocol = class {
91915
92007
  */
91916
92008
  request(request, resultSchema, options) {
91917
92009
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
91918
- return new Promise((resolve14, reject) => {
92010
+ return new Promise((resolve15, reject) => {
91919
92011
  const earlyReject = (error51) => {
91920
92012
  reject(error51);
91921
92013
  };
@@ -91993,7 +92085,7 @@ var Protocol = class {
91993
92085
  if (!parseResult.success) {
91994
92086
  reject(parseResult.error);
91995
92087
  } else {
91996
- resolve14(parseResult.data);
92088
+ resolve15(parseResult.data);
91997
92089
  }
91998
92090
  } catch (error51) {
91999
92091
  reject(error51);
@@ -92254,12 +92346,12 @@ var Protocol = class {
92254
92346
  }
92255
92347
  } catch {
92256
92348
  }
92257
- return new Promise((resolve14, reject) => {
92349
+ return new Promise((resolve15, reject) => {
92258
92350
  if (signal.aborted) {
92259
92351
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
92260
92352
  return;
92261
92353
  }
92262
- const timeoutId = setTimeout(resolve14, interval);
92354
+ const timeoutId = setTimeout(resolve15, interval);
92263
92355
  signal.addEventListener("abort", () => {
92264
92356
  clearTimeout(timeoutId);
92265
92357
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -93354,7 +93446,7 @@ var McpServer = class {
93354
93446
  let task = createTaskResult.task;
93355
93447
  const pollInterval = task.pollInterval ?? 5e3;
93356
93448
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
93357
- await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
93449
+ await new Promise((resolve15) => setTimeout(resolve15, pollInterval));
93358
93450
  const updatedTask = await extra.taskStore.getTask(taskId);
93359
93451
  if (!updatedTask) {
93360
93452
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -94370,11 +94462,11 @@ async function startHostActionMcpServer(opts) {
94370
94462
  writeHttpError(res, 500, err instanceof Error ? err.message : "Internal MCP server error");
94371
94463
  }
94372
94464
  }
94373
- await new Promise((resolve14, reject) => {
94465
+ await new Promise((resolve15, reject) => {
94374
94466
  httpServer.once("error", reject);
94375
94467
  httpServer.listen(0, "127.0.0.1", () => {
94376
94468
  httpServer.off("error", reject);
94377
- resolve14();
94469
+ resolve15();
94378
94470
  });
94379
94471
  });
94380
94472
  const address = httpServer.address();
@@ -94427,8 +94519,8 @@ async function startHostActionMcpServer(opts) {
94427
94519
  }
94428
94520
  httpSessions.clear();
94429
94521
  httpSessionsBySuperone.clear();
94430
- await new Promise((resolve14) => {
94431
- httpServer.close(() => resolve14());
94522
+ await new Promise((resolve15) => {
94523
+ httpServer.close(() => resolve15());
94432
94524
  });
94433
94525
  }
94434
94526
  };
@@ -95759,7 +95851,7 @@ async function startNodeRuntime(partial2 = {}) {
95759
95851
  startedAt,
95760
95852
  simulatedHarness
95761
95853
  });
95762
- writeFileSync19(
95854
+ writeFileSync18(
95763
95855
  paths.runtimeJson,
95764
95856
  JSON.stringify(
95765
95857
  {
@@ -95834,9 +95926,9 @@ function createLocalPairingToken(nodeHome) {
95834
95926
  }
95835
95927
  function readRuntimeStatus(nodeHome) {
95836
95928
  const paths = nodePaths(resolveRuntimeConfig({ nodeHome }).nodeHome);
95837
- if (!existsSync42(paths.runtimeJson)) return null;
95929
+ if (!existsSync41(paths.runtimeJson)) return null;
95838
95930
  try {
95839
- return JSON.parse(readFileSync21(paths.runtimeJson, "utf8"));
95931
+ return JSON.parse(readFileSync20(paths.runtimeJson, "utf8"));
95840
95932
  } catch {
95841
95933
  return null;
95842
95934
  }
@@ -95844,8 +95936,8 @@ function readRuntimeStatus(nodeHome) {
95844
95936
 
95845
95937
  // src/systemd/install.ts
95846
95938
  import { spawnSync as spawnSync2 } from "node:child_process";
95847
- import { chmodSync as chmodSync3, existsSync as existsSync43, mkdirSync as mkdirSync24, unlinkSync as unlinkSync2, writeFileSync as writeFileSync20 } from "node:fs";
95848
- import { dirname as dirname20 } from "node:path";
95939
+ import { chmodSync as chmodSync3, existsSync as existsSync42, mkdirSync as mkdirSync23, unlinkSync as unlinkSync2, writeFileSync as writeFileSync19 } from "node:fs";
95940
+ import { dirname as dirname19 } from "node:path";
95849
95941
 
95850
95942
  // src/systemd/unit.ts
95851
95943
  function renderSystemdUserUnit(opts) {
@@ -95902,8 +95994,8 @@ function checkLinger(user) {
95902
95994
  return { enabled: null, raw };
95903
95995
  }
95904
95996
  function writeSystemdUserUnit(opts, unitPath = systemdUserUnitPath()) {
95905
- mkdirSync24(dirname20(unitPath), { recursive: true });
95906
- writeFileSync20(unitPath, renderSystemdUserUnit(opts), { encoding: "utf8", mode: 420 });
95997
+ mkdirSync23(dirname19(unitPath), { recursive: true });
95998
+ writeFileSync19(unitPath, renderSystemdUserUnit(opts), { encoding: "utf8", mode: 420 });
95907
95999
  try {
95908
96000
  chmodSync3(unitPath, 420);
95909
96001
  } catch {
@@ -95956,7 +96048,7 @@ function uninstallSystemdUserService(removeUnitFile = true) {
95956
96048
  }
95957
96049
  if (removeUnitFile) {
95958
96050
  const path = systemdUserUnitPath();
95959
- if (existsSync43(path)) {
96051
+ if (existsSync42(path)) {
95960
96052
  try {
95961
96053
  unlinkSync2(path);
95962
96054
  } catch (err) {
@@ -95979,8 +96071,8 @@ function systemdUserStatus() {
95979
96071
 
95980
96072
  // src/session/harness-cli.ts
95981
96073
  init_environment();
95982
- import { accessSync as accessSync2, constants as constants3, existsSync as existsSync44, realpathSync as realpathSync7, statSync as statSync17 } from "node:fs";
95983
- import { isAbsolute as isAbsolute5, resolve as resolve12 } from "node:path";
96074
+ import { accessSync as accessSync2, constants as constants3, existsSync as existsSync43, realpathSync as realpathSync7, statSync as statSync17 } from "node:fs";
96075
+ import { isAbsolute as isAbsolute5, resolve as resolve13 } from "node:path";
95984
96076
  import { homedir as homedir9 } from "node:os";
95985
96077
  var DEFERRED_FLAGS = /* @__PURE__ */ new Set([
95986
96078
  "--env-file",
@@ -96520,7 +96612,7 @@ function resolveExternalCommand2(explicit, pathCandidates) {
96520
96612
  ];
96521
96613
  for (const name of pathCandidates) {
96522
96614
  for (const dir of [...dirs, ...extra]) {
96523
- const candidate = resolve12(dir, name);
96615
+ const candidate = resolve13(dir, name);
96524
96616
  const ok = isUsableExecutable(candidate);
96525
96617
  if (ok) return ok;
96526
96618
  }
@@ -96528,7 +96620,7 @@ function resolveExternalCommand2(explicit, pathCandidates) {
96528
96620
  return null;
96529
96621
  }
96530
96622
  function isUsableExecutable(path) {
96531
- if (!existsSync44(path)) return null;
96623
+ if (!existsSync43(path)) return null;
96532
96624
  let st;
96533
96625
  try {
96534
96626
  st = statSync17(path);
@@ -96548,7 +96640,7 @@ function isUsableExecutable(path) {
96548
96640
  }
96549
96641
  }
96550
96642
  function probeExecutableIssues(path) {
96551
- if (!existsSync44(path)) return ["command_missing"];
96643
+ if (!existsSync43(path)) return ["command_missing"];
96552
96644
  let st;
96553
96645
  try {
96554
96646
  st = statSync17(path);
@@ -96564,7 +96656,7 @@ function probeExecutableIssues(path) {
96564
96656
  return [];
96565
96657
  }
96566
96658
  function probeReadableFileIssues(path) {
96567
- if (!existsSync44(path)) return ["artifact_missing"];
96659
+ if (!existsSync43(path)) return ["artifact_missing"];
96568
96660
  try {
96569
96661
  if (!statSync17(path).isFile()) return ["artifact_not_file"];
96570
96662
  } catch {
@@ -96904,7 +96996,7 @@ async function main() {
96904
96996
  }
96905
96997
  if (cmd === "install-systemd") {
96906
96998
  const nodeHome = resolveNodeHome(argValue(rest, "--home"));
96907
- const execStart = argValue(rest, "--exec") || resolve13(process.argv[1] || "superone");
96999
+ const execStart = argValue(rest, "--exec") || resolve14(process.argv[1] || "superone");
96908
97000
  const host = argValue(rest, "--host") || DEFAULT_BIND_HOST;
96909
97001
  const port = Number(argValue(rest, "--port") || DEFAULT_BIND_PORT);
96910
97002
  const result = installSystemdUserService({