overlord-cli 0.2608141841.0 → 0.2608170844.0

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.
package/dist/index.js CHANGED
@@ -278,16 +278,16 @@ function resolveCommandArgs({
278
278
  return parsed;
279
279
  }
280
280
  function normalizeVersion(raw) {
281
- const trimmed7 = raw.trim();
282
- if (!trimmed7) {
281
+ const trimmed8 = raw.trim();
282
+ if (!trimmed8) {
283
283
  throw new CliError({ message: "Received an empty version from npm." });
284
284
  }
285
285
  try {
286
- const parsed = JSON.parse(trimmed7);
286
+ const parsed = JSON.parse(trimmed8);
287
287
  if (typeof parsed === "string" && parsed.trim()) return parsed.trim();
288
288
  } catch {
289
289
  }
290
- return trimmed7.replace(/^"+|"+$/g, "");
290
+ return trimmed8.replace(/^"+|"+$/g, "");
291
291
  }
292
292
  function compareVersions(left, right) {
293
293
  const leftParts = left.split(".").map((part) => Number.parseInt(part, 10));
@@ -1346,11 +1346,11 @@ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, wr
1346
1346
  import os from "node:os";
1347
1347
  import path3 from "node:path";
1348
1348
  function normalizeBackendUrl(value) {
1349
- const trimmed7 = value.trim().replace(/\/+$/, "");
1350
- if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed7)) {
1351
- return trimmed7;
1349
+ const trimmed8 = value.trim().replace(/\/+$/, "");
1350
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed8)) {
1351
+ return trimmed8;
1352
1352
  }
1353
- return `http://${trimmed7}`;
1353
+ return `http://${trimmed8}`;
1354
1354
  }
1355
1355
  function isLoopbackBackendUrl(backendUrl) {
1356
1356
  try {
@@ -2412,12 +2412,12 @@ function parseConnectorManifestYaml(text) {
2412
2412
  };
2413
2413
  for (const rawLine of text.split("\n")) {
2414
2414
  const line = rawLine.replace(/\r$/, "");
2415
- const trimmed7 = line.trim();
2416
- if (trimmed7 === "" || trimmed7.startsWith("#")) continue;
2415
+ const trimmed8 = line.trim();
2416
+ if (trimmed8 === "" || trimmed8.startsWith("#")) continue;
2417
2417
  const indent = line.length - line.trimStart().length;
2418
2418
  if (pending) {
2419
2419
  if (indent > pending.indent) {
2420
- const container = trimmed7.startsWith("- ") ? [] : {};
2420
+ const container = trimmed8.startsWith("- ") ? [] : {};
2421
2421
  pending.parent[pending.key] = container;
2422
2422
  stack.push({ indent, container });
2423
2423
  pending = null;
@@ -2430,16 +2430,16 @@ function parseConnectorManifestYaml(text) {
2430
2430
  stack.pop();
2431
2431
  }
2432
2432
  const frame = stack[stack.length - 1];
2433
- if (trimmed7.startsWith("- ")) {
2433
+ if (trimmed8.startsWith("- ")) {
2434
2434
  if (Array.isArray(frame.container)) {
2435
- frame.container.push(parseScalar(trimmed7.slice(2)));
2435
+ frame.container.push(parseScalar(trimmed8.slice(2)));
2436
2436
  }
2437
2437
  continue;
2438
2438
  }
2439
- const colon = trimmed7.indexOf(":");
2439
+ const colon = trimmed8.indexOf(":");
2440
2440
  if (colon < 0 || Array.isArray(frame.container)) continue;
2441
- const key = trimmed7.slice(0, colon).trim();
2442
- const rest = trimmed7.slice(colon + 1).trim();
2441
+ const key = trimmed8.slice(0, colon).trim();
2442
+ const rest = trimmed8.slice(colon + 1).trim();
2443
2443
  if (rest === "") {
2444
2444
  pending = { parent: frame.container, key, indent };
2445
2445
  } else {
@@ -2633,10 +2633,10 @@ ${managedBlock}
2633
2633
 
2634
2634
  ${after}`;
2635
2635
  }
2636
- const trimmed7 = existingContent.trimEnd();
2637
- if (!trimmed7) return `${managedBlock}
2636
+ const trimmed8 = existingContent.trimEnd();
2637
+ if (!trimmed8) return `${managedBlock}
2638
2638
  `;
2639
- return `${trimmed7}
2639
+ return `${trimmed8}
2640
2640
 
2641
2641
  ${managedBlock}
2642
2642
  `;
@@ -5566,8 +5566,8 @@ function resolveNativeSessionId({
5566
5566
  env = process.env
5567
5567
  }) {
5568
5568
  if (explicit !== void 0) {
5569
- const trimmed7 = explicit.trim();
5570
- return trimmed7 === "null" ? null : trimmed7 || void 0;
5569
+ const trimmed8 = explicit.trim();
5570
+ return trimmed8 === "null" ? null : trimmed8 || void 0;
5571
5571
  }
5572
5572
  const normalizedAgent = agent.toLowerCase();
5573
5573
  if (normalizedAgent === "codex") {
@@ -16335,22 +16335,22 @@ var init_contract = __esm({
16335
16335
 
16336
16336
  // ../packages/contract/dist/agent-launch-flags.js
16337
16337
  function parseAgentLaunchFlagText(text) {
16338
- const trimmed7 = text.trim();
16339
- if (!trimmed7)
16338
+ const trimmed8 = text.trim();
16339
+ if (!trimmed8)
16340
16340
  return null;
16341
- const eqIndex = trimmed7.indexOf("=");
16342
- if (eqIndex > 0 && trimmed7.startsWith("--")) {
16343
- const name = trimmed7.slice(0, eqIndex).trim();
16344
- const value = trimmed7.slice(eqIndex + 1).trim();
16341
+ const eqIndex = trimmed8.indexOf("=");
16342
+ if (eqIndex > 0 && trimmed8.startsWith("--")) {
16343
+ const name = trimmed8.slice(0, eqIndex).trim();
16344
+ const value = trimmed8.slice(eqIndex + 1).trim();
16345
16345
  return name ? { name, value: value.length > 0 ? value : null } : null;
16346
16346
  }
16347
- const spaceIndex = trimmed7.indexOf(" ");
16348
- if (spaceIndex > 0 && trimmed7.startsWith("--")) {
16349
- const name = trimmed7.slice(0, spaceIndex).trim();
16350
- const value = trimmed7.slice(spaceIndex + 1).trim();
16347
+ const spaceIndex = trimmed8.indexOf(" ");
16348
+ if (spaceIndex > 0 && trimmed8.startsWith("--")) {
16349
+ const name = trimmed8.slice(0, spaceIndex).trim();
16350
+ const value = trimmed8.slice(spaceIndex + 1).trim();
16351
16351
  return name ? { name, value: value.length > 0 ? value : null } : null;
16352
16352
  }
16353
- return { name: trimmed7 };
16353
+ return { name: trimmed8 };
16354
16354
  }
16355
16355
  function normalizeAgentLaunchFlags(input) {
16356
16356
  if (!Array.isArray(input))
@@ -16501,11 +16501,11 @@ function accessModeToResourcePathPermission({ accessMode, isPrimary = false }) {
16501
16501
  return accessMode === "read" ? "ro" : "rw";
16502
16502
  }
16503
16503
  function formatResourcePathWithPermission({ path: path34, accessMode, isPrimary = false }) {
16504
- const trimmed7 = path34.trim();
16505
- if (!trimmed7)
16504
+ const trimmed8 = path34.trim();
16505
+ if (!trimmed8)
16506
16506
  return "";
16507
16507
  const permission = accessModeToResourcePathPermission({ accessMode, isPrimary });
16508
- return `${trimmed7}:${permission}`;
16508
+ return `${trimmed8}:${permission}`;
16509
16509
  }
16510
16510
  function formatProjectResourcePathsFromManifest(projectResources) {
16511
16511
  if (!Array.isArray(projectResources))
@@ -16643,12 +16643,304 @@ var init_terminal_profile_types2 = __esm({
16643
16643
  }
16644
16644
  });
16645
16645
 
16646
- // ../packages/core/dist/service/latch-launch.js
16646
+ // ../packages/core/dist/service/latch-discovery.js
16647
+ import { execFileSync } from "node:child_process";
16648
+ import { existsSync as existsSync15, mkdirSync as mkdirSync8, readFileSync as readFileSync14, statSync as statSync4, writeFileSync as writeFileSync7 } from "node:fs";
16649
+ import os3 from "node:os";
16650
+ import path15 from "node:path";
16651
+ function defaultLatchDiscoveryCachePath() {
16652
+ const home = process.env.OVLD_HOME?.trim() || path15.join(os3.homedir(), ".ovld");
16653
+ return path15.join(home, LATCH_DISCOVERY_CACHE_FILENAME);
16654
+ }
16647
16655
  function trimmed2(value) {
16648
16656
  return typeof value === "string" && value.trim() ? value.trim() : null;
16649
16657
  }
16658
+ function asBoolean(value) {
16659
+ return value === true;
16660
+ }
16661
+ function asStringArray(value) {
16662
+ if (!Array.isArray(value))
16663
+ return [];
16664
+ return value.filter((entry) => typeof entry === "string");
16665
+ }
16666
+ function parseLatchCapabilitiesReport(raw) {
16667
+ const text = raw.trim();
16668
+ if (!text)
16669
+ return null;
16670
+ let parsed;
16671
+ try {
16672
+ parsed = JSON.parse(text);
16673
+ } catch {
16674
+ return null;
16675
+ }
16676
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
16677
+ return null;
16678
+ const cast = parsed;
16679
+ const protocolVersion = typeof cast.protocolVersion === "number" && Number.isFinite(cast.protocolVersion) ? Math.trunc(cast.protocolVersion) : null;
16680
+ const productVersion = trimmed2(cast.productVersion);
16681
+ if (protocolVersion === null || !productVersion)
16682
+ return null;
16683
+ if (!cast.capabilities || typeof cast.capabilities !== "object" || Array.isArray(cast.capabilities)) {
16684
+ return null;
16685
+ }
16686
+ const caps = cast.capabilities;
16687
+ return {
16688
+ protocolVersion,
16689
+ productVersion,
16690
+ capabilities: {
16691
+ create: asBoolean(caps.create),
16692
+ openViewer: asBoolean(caps.openViewer),
16693
+ localAttach: asBoolean(caps.localAttach),
16694
+ cloudAttach: asBoolean(caps.cloudAttach),
16695
+ selfUpdate: asBoolean(caps.selfUpdate),
16696
+ extensions: asStringArray(caps.extensions)
16697
+ }
16698
+ };
16699
+ }
16700
+ function evaluateLatchCapabilities({ report, executable, resolvedPath, checkedAt = (/* @__PURE__ */ new Date()).toISOString() }) {
16701
+ if (report.protocolVersion !== SUPPORTED_LATCH_PROTOCOL_VERSION) {
16702
+ return {
16703
+ state: "incompatible",
16704
+ executable,
16705
+ resolvedPath,
16706
+ protocolVersion: report.protocolVersion,
16707
+ productVersion: report.productVersion,
16708
+ missingCapability: "protocolVersion",
16709
+ detail: `Latch protocolVersion ${report.protocolVersion} is not supported (need ${SUPPORTED_LATCH_PROTOCOL_VERSION}).`,
16710
+ checkedAt,
16711
+ latchSelectable: false,
16712
+ directSelectable: true
16713
+ };
16714
+ }
16715
+ for (const required of REQUIRED_LATCH_CAPABILITIES) {
16716
+ if (!report.capabilities[required]) {
16717
+ return {
16718
+ state: "incompatible",
16719
+ executable,
16720
+ resolvedPath,
16721
+ protocolVersion: report.protocolVersion,
16722
+ productVersion: report.productVersion,
16723
+ missingCapability: required,
16724
+ detail: `Latch is missing required capability \`${required}\`.`,
16725
+ checkedAt,
16726
+ latchSelectable: false,
16727
+ directSelectable: true
16728
+ };
16729
+ }
16730
+ }
16731
+ return {
16732
+ state: "found",
16733
+ executable,
16734
+ resolvedPath,
16735
+ protocolVersion: report.protocolVersion,
16736
+ productVersion: report.productVersion,
16737
+ capabilities: report.capabilities,
16738
+ checkedAt,
16739
+ latchSelectable: true,
16740
+ directSelectable: true
16741
+ };
16742
+ }
16743
+ function resolveLatchExecutableOnPath(executable) {
16744
+ try {
16745
+ const found = execFileSync("which", [executable], {
16746
+ encoding: "utf8",
16747
+ stdio: ["ignore", "pipe", "ignore"]
16748
+ }).trim();
16749
+ return found || null;
16750
+ } catch {
16751
+ return null;
16752
+ }
16753
+ }
16754
+ function resolveLatchExecutablePathFromEnvironment({ executable, homeDirectory = os3.homedir(), platform: platform2 = process.platform, resolveOnPath = resolveLatchExecutableOnPath, fileExists = existsSync15 }) {
16755
+ const name = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
16756
+ if (path15.isAbsolute(name) || name.includes("/") || name.includes("\\")) {
16757
+ return fileExists(name) ? path15.resolve(name) : null;
16758
+ }
16759
+ const resolvedOnPath = resolveOnPath(name);
16760
+ if (resolvedOnPath)
16761
+ return resolvedOnPath;
16762
+ const fallbacks = [
16763
+ path15.join(homeDirectory, ".local", "bin", name),
16764
+ ...platform2 === "darwin" ? [`/opt/homebrew/bin/${name}`, `/usr/local/bin/${name}`] : []
16765
+ ];
16766
+ const fallback = fallbacks.find(fileExists);
16767
+ return fallback ? path15.resolve(fallback) : null;
16768
+ }
16769
+ function resolveLatchExecutablePath(executable) {
16770
+ return resolveLatchExecutablePathFromEnvironment({ executable });
16771
+ }
16772
+ function notInstalledResult({ executable, checkedAt }) {
16773
+ return {
16774
+ state: "not_installed",
16775
+ executable,
16776
+ installCommand: LATCH_STANDALONE_INSTALL_COMMAND,
16777
+ checkedAt,
16778
+ latchSelectable: false,
16779
+ directSelectable: true
16780
+ };
16781
+ }
16782
+ function probeLatchCapabilities({ executable = DEFAULT_LATCH_EXECUTABLE, resolvePath = resolveLatchExecutablePath, runCommand: runCommand2 = defaultCommandRunner, now = () => (/* @__PURE__ */ new Date()).toISOString() } = {}) {
16783
+ const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
16784
+ const checkedAt = now();
16785
+ const resolvedPath = resolvePath(exe);
16786
+ if (!resolvedPath) {
16787
+ return notInstalledResult({ executable: exe, checkedAt });
16788
+ }
16789
+ const ran = runCommand2({ executable: resolvedPath, argv: ["capabilities", "--json"] });
16790
+ if (ran.status === null && ran.stderr === "ENOENT") {
16791
+ return notInstalledResult({ executable: exe, checkedAt });
16792
+ }
16793
+ const report = parseLatchCapabilitiesReport(ran.stdout);
16794
+ if (!report) {
16795
+ return {
16796
+ state: "incompatible",
16797
+ executable: exe,
16798
+ resolvedPath,
16799
+ protocolVersion: null,
16800
+ productVersion: null,
16801
+ missingCapability: "capabilities",
16802
+ detail: ran.status === 0 ? "Latch capabilities output was not valid JSON in the expected shape." : `Latch capabilities failed (exit ${ran.status ?? "null"}).`,
16803
+ checkedAt,
16804
+ latchSelectable: false,
16805
+ directSelectable: true
16806
+ };
16807
+ }
16808
+ return evaluateLatchCapabilities({ report, executable: exe, resolvedPath, checkedAt });
16809
+ }
16810
+ function latchDiscoveryCacheKey({ executionTargetId, executable }) {
16811
+ const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
16812
+ return `${executionTargetId}::${exe}`;
16813
+ }
16814
+ function readBinaryMtimeMs(resolvedPath) {
16815
+ if (!resolvedPath)
16816
+ return null;
16817
+ try {
16818
+ return statSync4(resolvedPath).mtimeMs;
16819
+ } catch {
16820
+ return null;
16821
+ }
16822
+ }
16823
+ function isLatchDiscoveryCacheFresh({ entry, resolvePath = resolveLatchExecutablePath }) {
16824
+ const { result } = entry;
16825
+ if (result.state === "not_installed") {
16826
+ return resolvePath(result.executable) === null;
16827
+ }
16828
+ const pathStill = result.resolvedPath;
16829
+ if (!pathStill || !existsSync15(pathStill))
16830
+ return false;
16831
+ const mtime = readBinaryMtimeMs(pathStill);
16832
+ if (mtime === null || entry.binaryMtimeMs === null)
16833
+ return false;
16834
+ return mtime === entry.binaryMtimeMs;
16835
+ }
16836
+ function readLatchDiscoveryCacheFile(filePath) {
16837
+ if (!existsSync15(filePath))
16838
+ return { version: 1, entries: {} };
16839
+ try {
16840
+ const parsed = JSON.parse(readFileSync14(filePath, "utf8"));
16841
+ if (parsed.version !== 1 || !parsed.entries || typeof parsed.entries !== "object") {
16842
+ return { version: 1, entries: {} };
16843
+ }
16844
+ return { version: 1, entries: parsed.entries };
16845
+ } catch {
16846
+ return { version: 1, entries: {} };
16847
+ }
16848
+ }
16849
+ function writeLatchDiscoveryCacheFile({ filePath, cache: cache2 }) {
16850
+ mkdirSync8(path15.dirname(filePath), { recursive: true });
16851
+ writeFileSync7(filePath, `${JSON.stringify(cache2, null, 2)}
16852
+ `, { mode: 384 });
16853
+ }
16854
+ function discoverLatchForExecutionTarget({ executionTargetId, executable = DEFAULT_LATCH_EXECUTABLE, cacheFilePath, force = false, resolvePath = resolveLatchExecutablePath, runCommand: runCommand2 = defaultCommandRunner, now = () => (/* @__PURE__ */ new Date()).toISOString() }) {
16855
+ const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
16856
+ const key = latchDiscoveryCacheKey({ executionTargetId, executable: exe });
16857
+ const cache2 = readLatchDiscoveryCacheFile(cacheFilePath);
16858
+ const existing = cache2.entries[key];
16859
+ if (!force && existing && isLatchDiscoveryCacheFresh({ entry: existing, resolvePath })) {
16860
+ return { ...existing.result, checkedAt: existing.result.checkedAt, directSelectable: true };
16861
+ }
16862
+ const result = probeLatchCapabilities({ executable: exe, resolvePath, runCommand: runCommand2, now });
16863
+ const binaryMtimeMs = result.state === "not_installed" ? null : readBinaryMtimeMs(result.resolvedPath);
16864
+ cache2.entries[key] = {
16865
+ result,
16866
+ binaryMtimeMs,
16867
+ cachedAt: result.checkedAt
16868
+ };
16869
+ writeLatchDiscoveryCacheFile({ filePath: cacheFilePath, cache: cache2 });
16870
+ return result;
16871
+ }
16872
+ var SUPPORTED_LATCH_PROTOCOL_VERSION, REQUIRED_LATCH_CAPABILITIES, LATCH_STANDALONE_INSTALL_COMMAND, LATCH_DISCOVERY_CACHE_FILENAME, defaultCommandRunner;
16873
+ var init_latch_discovery = __esm({
16874
+ "../packages/core/dist/service/latch-discovery.js"() {
16875
+ "use strict";
16876
+ init_latch_environment();
16877
+ init_terminal_profile_types2();
16878
+ SUPPORTED_LATCH_PROTOCOL_VERSION = 1;
16879
+ REQUIRED_LATCH_CAPABILITIES = ["create"];
16880
+ LATCH_STANDALONE_INSTALL_COMMAND = "curl -fsSL https://raw.githubusercontent.com/jchaselubitz/Latch/main/scripts/install-cli.sh | bash";
16881
+ LATCH_DISCOVERY_CACHE_FILENAME = "latch-discovery.json";
16882
+ defaultCommandRunner = ({ executable, argv }) => {
16883
+ try {
16884
+ const stdout = execFileSync(executable, argv, {
16885
+ encoding: "utf8",
16886
+ stdio: ["ignore", "pipe", "pipe"],
16887
+ timeout: 5e3,
16888
+ env: latchChildEnvironment()
16889
+ });
16890
+ return { status: 0, stdout: String(stdout), stderr: "" };
16891
+ } catch (error) {
16892
+ const err = error;
16893
+ if (err.code === "ENOENT") {
16894
+ return { status: null, stdout: "", stderr: "ENOENT" };
16895
+ }
16896
+ return {
16897
+ status: typeof err.status === "number" ? err.status : 1,
16898
+ stdout: err.stdout ? String(err.stdout) : "",
16899
+ stderr: err.stderr ? String(err.stderr) : String(error)
16900
+ };
16901
+ }
16902
+ };
16903
+ }
16904
+ });
16905
+
16906
+ // ../packages/core/dist/service/latch-binary.js
16907
+ import { existsSync as existsSync16 } from "node:fs";
16908
+ function trimmed3(value) {
16909
+ return typeof value === "string" && value.trim() ? value.trim() : null;
16910
+ }
16911
+ function resolveLatchBinaryPath(executable, resolve = resolveLatchExecutablePath) {
16912
+ const name = trimmed3(executable) ?? DEFAULT_LATCH_EXECUTABLE;
16913
+ const cached = cache.get(name);
16914
+ if (cached) {
16915
+ if (existsSync16(cached))
16916
+ return cached;
16917
+ cache.delete(name);
16918
+ }
16919
+ const resolved = resolve(name);
16920
+ if (resolved)
16921
+ cache.set(name, resolved);
16922
+ return resolved;
16923
+ }
16924
+ function latchBinaryMissingMessage(executable) {
16925
+ const name = trimmed3(executable) ?? DEFAULT_LATCH_EXECUTABLE;
16926
+ return `Latch executable "${name}" was not found on this device (checked PATH, ~/.local/bin, and the Homebrew prefixes).`;
16927
+ }
16928
+ var cache;
16929
+ var init_latch_binary = __esm({
16930
+ "../packages/core/dist/service/latch-binary.js"() {
16931
+ "use strict";
16932
+ init_latch_discovery();
16933
+ init_terminal_profile_types2();
16934
+ cache = /* @__PURE__ */ new Map();
16935
+ }
16936
+ });
16937
+
16938
+ // ../packages/core/dist/service/latch-launch.js
16939
+ function trimmed4(value) {
16940
+ return typeof value === "string" && value.trim() ? value.trim() : null;
16941
+ }
16650
16942
  function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.trim() || "/bin/bash", cwd, env, size = DEFAULT_LATCH_TERMINAL_SIZE, title, name, commandLabel, externalRunId }) {
16651
- const shellPath = trimmed2(shell) ?? "/bin/bash";
16943
+ const shellPath = trimmed4(shell) ?? "/bin/bash";
16652
16944
  const cleanedEnv = {};
16653
16945
  for (const [key, value] of Object.entries(env)) {
16654
16946
  if (key.trim() && typeof value === "string")
@@ -16657,15 +16949,15 @@ function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.tr
16657
16949
  const display = {
16658
16950
  source: {
16659
16951
  kind: "overlord",
16660
- ...trimmed2(externalRunId) ? { external_run_id: trimmed2(externalRunId) } : {}
16952
+ ...trimmed4(externalRunId) ? { external_run_id: trimmed4(externalRunId) } : {}
16661
16953
  }
16662
16954
  };
16663
- if (trimmed2(title))
16664
- display.title = trimmed2(title);
16665
- if (trimmed2(name))
16666
- display.name = trimmed2(name);
16667
- if (trimmed2(commandLabel))
16668
- display.command_label = trimmed2(commandLabel);
16955
+ if (trimmed4(title))
16956
+ display.title = trimmed4(title);
16957
+ if (trimmed4(name))
16958
+ display.name = trimmed4(name);
16959
+ if (trimmed4(commandLabel))
16960
+ display.command_label = trimmed4(commandLabel);
16669
16961
  return {
16670
16962
  format_version: LATCH_MANIFEST_FORMAT_VERSION,
16671
16963
  launch: {
@@ -16684,7 +16976,7 @@ function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.tr
16684
16976
  function parseLatchCreateReport(raw) {
16685
16977
  try {
16686
16978
  const parsed = JSON.parse(raw);
16687
- const id = trimmed2(parsed.session?.id);
16979
+ const id = trimmed4(parsed.session?.id);
16688
16980
  if (!id)
16689
16981
  return null;
16690
16982
  const protocolVersion = typeof parsed.protocolVersion === "number" && Number.isFinite(parsed.protocolVersion) ? parsed.protocolVersion : LATCH_MANIFEST_FORMAT_VERSION;
@@ -16692,9 +16984,9 @@ function parseLatchCreateReport(raw) {
16692
16984
  protocolVersion,
16693
16985
  session: {
16694
16986
  id,
16695
- name: trimmed2(parsed.session?.name) ?? id,
16696
- state: trimmed2(parsed.session?.state) ?? "running",
16697
- createdAt: trimmed2(parsed.session?.createdAt) ?? (/* @__PURE__ */ new Date()).toISOString()
16987
+ name: trimmed4(parsed.session?.name) ?? id,
16988
+ state: trimmed4(parsed.session?.state) ?? "running",
16989
+ createdAt: trimmed4(parsed.session?.createdAt) ?? (/* @__PURE__ */ new Date()).toISOString()
16698
16990
  }
16699
16991
  };
16700
16992
  } catch {
@@ -16706,28 +16998,28 @@ function toExecutionProviderSession({ createReport, executionTargetId, createdAt
16706
16998
  provider: "latch",
16707
16999
  providerSessionId: createReport.session.id,
16708
17000
  sessionName: createReport.session.name,
16709
- executionTargetId: trimmed2(executionTargetId),
17001
+ executionTargetId: trimmed4(executionTargetId),
16710
17002
  agentSessionId: null,
16711
17003
  createdAt: createdAt ?? createReport.session.createdAt,
16712
17004
  lastObservedState: createReport.session.state
16713
17005
  };
16714
17006
  }
16715
17007
  function existingLatchProviderSession({ latchSessionId, executionTargetId, createdAt = (/* @__PURE__ */ new Date()).toISOString() }) {
16716
- const providerSessionId = trimmed2(latchSessionId);
17008
+ const providerSessionId = trimmed4(latchSessionId);
16717
17009
  if (!providerSessionId)
16718
17010
  return null;
16719
17011
  return {
16720
17012
  provider: "latch",
16721
17013
  providerSessionId,
16722
17014
  sessionName: null,
16723
- executionTargetId: trimmed2(executionTargetId),
17015
+ executionTargetId: trimmed4(executionTargetId),
16724
17016
  agentSessionId: null,
16725
17017
  createdAt,
16726
17018
  lastObservedState: "running"
16727
17019
  };
16728
17020
  }
16729
17021
  function latchViewerFlagForKind(kind) {
16730
- switch (trimmed2(kind)?.toLowerCase()) {
17022
+ switch (trimmed4(kind)?.toLowerCase()) {
16731
17023
  case "iterm":
16732
17024
  case "iterm2":
16733
17025
  return "iterm";
@@ -16751,7 +17043,7 @@ function compareLatchProductVersions(a, b) {
16751
17043
  return 0;
16752
17044
  }
16753
17045
  function latchSupportsOpenAs(productVersion) {
16754
- const version = trimmed2(productVersion);
17046
+ const version = trimmed4(productVersion);
16755
17047
  if (!version)
16756
17048
  return false;
16757
17049
  return compareLatchProductVersions(version, LATCH_OPEN_AS_MIN_PRODUCT_VERSION) >= 0;
@@ -16765,10 +17057,10 @@ function buildLatchOpenArgs({ providerSessionId, viewer, openAs, productVersion
16765
17057
  return args;
16766
17058
  }
16767
17059
  function latchAttachCommand({ executable = "latch", providerSessionId }) {
16768
- return `${trimmed2(executable) ?? "latch"} attach ${providerSessionId}`;
17060
+ return `${trimmed4(executable) ?? "latch"} attach ${providerSessionId}`;
16769
17061
  }
16770
17062
  function shouldUseLatchProvider({ providerKind, latchSelectable }) {
16771
- return trimmed2(providerKind)?.toLowerCase() === "latch" && latchSelectable === true;
17063
+ return trimmed4(providerKind)?.toLowerCase() === "latch" && latchSelectable === true;
16772
17064
  }
16773
17065
  var LATCH_MANIFEST_FORMAT_VERSION, DEFAULT_LATCH_TERMINAL_SIZE, LATCH_OPEN_AS_MIN_PRODUCT_VERSION;
16774
17066
  var init_latch_launch = __esm({
@@ -16783,11 +17075,11 @@ var init_latch_launch = __esm({
16783
17075
 
16784
17076
  // ../packages/core/dist/service/latch-session.js
16785
17077
  import { spawnSync as spawnSync2 } from "node:child_process";
16786
- function trimmed3(value) {
17078
+ function trimmed5(value) {
16787
17079
  return typeof value === "string" && value.trim() ? value.trim() : null;
16788
17080
  }
16789
17081
  function parseState(value) {
16790
- switch (trimmed3(value)) {
17082
+ switch (trimmed5(value)) {
16791
17083
  case "running":
16792
17084
  return "running";
16793
17085
  case "exited":
@@ -16801,7 +17093,10 @@ function parseState(value) {
16801
17093
  }
16802
17094
  }
16803
17095
  function runLatchJson({ executable, args }) {
16804
- const result = spawnSync2(executable, args, {
17096
+ const binary = resolveLatchBinaryPath(executable);
17097
+ if (!binary)
17098
+ throw new LatchSessionCommandError(latchBinaryMissingMessage(executable));
17099
+ const result = spawnSync2(binary, args, {
16805
17100
  encoding: "utf8",
16806
17101
  shell: false,
16807
17102
  timeout: 1e4,
@@ -16826,11 +17121,11 @@ function runLatchJson({ executable, args }) {
16826
17121
  }
16827
17122
  }
16828
17123
  function inspectLatchSession({ executable = "latch", providerSessionId }) {
16829
- const sessionId = trimmed3(providerSessionId);
17124
+ const sessionId = trimmed5(providerSessionId);
16830
17125
  if (!sessionId)
16831
17126
  throw new LatchSessionCommandError("A Latch session id is required.");
16832
17127
  const report = runLatchJson({
16833
- executable: trimmed3(executable) ?? "latch",
17128
+ executable: trimmed5(executable) ?? "latch",
16834
17129
  args: ["inspect", sessionId, "--json"]
16835
17130
  });
16836
17131
  const state = parseState(report.state);
@@ -16838,8 +17133,8 @@ function inspectLatchSession({ executable = "latch", providerSessionId }) {
16838
17133
  throw new LatchSessionCommandError("Latch returned an unsupported session state.");
16839
17134
  const exit = report.exit && typeof report.exit === "object" && !Array.isArray(report.exit) ? report.exit : null;
16840
17135
  return {
16841
- providerSessionId: trimmed3(report.id) ?? sessionId,
16842
- name: trimmed3(report.name) ?? sessionId,
17136
+ providerSessionId: trimmed5(report.id) ?? sessionId,
17137
+ name: trimmed5(report.name) ?? sessionId,
16843
17138
  state,
16844
17139
  exitCode: typeof exit?.code === "number" && Number.isFinite(exit.code) ? exit.code : null,
16845
17140
  inspectedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -16847,20 +17142,20 @@ function inspectLatchSession({ executable = "latch", providerSessionId }) {
16847
17142
  }
16848
17143
  function readLatchProductVersion(executable) {
16849
17144
  try {
16850
- return trimmed3(runLatchJson({ executable, args: ["capabilities", "--json"] }).productVersion);
17145
+ return trimmed5(runLatchJson({ executable, args: ["capabilities", "--json"] }).productVersion);
16851
17146
  } catch {
16852
17147
  return null;
16853
17148
  }
16854
17149
  }
16855
17150
  function openLatchSession({ executable = "latch", providerSessionId, viewerKind, openAs }) {
16856
- const sessionId = trimmed3(providerSessionId);
17151
+ const sessionId = trimmed5(providerSessionId);
16857
17152
  if (!sessionId)
16858
17153
  throw new LatchSessionCommandError("A Latch session id is required.");
16859
17154
  const viewer = latchViewerFlagForKind(viewerKind);
16860
17155
  if (!viewer) {
16861
17156
  throw new LatchSessionCommandError(`Latch cannot open the configured viewer "${viewerKind}".`);
16862
17157
  }
16863
- const exe = trimmed3(executable) ?? "latch";
17158
+ const exe = trimmed5(executable) ?? "latch";
16864
17159
  const report = runLatchJson({
16865
17160
  executable: exe,
16866
17161
  args: buildLatchOpenArgs({
@@ -16874,25 +17169,25 @@ function openLatchSession({ executable = "latch", providerSessionId, viewerKind,
16874
17169
  throw new LatchSessionCommandError(`Latch did not open the ${viewer} viewer.`);
16875
17170
  }
16876
17171
  return {
16877
- providerSessionId: trimmed3(report.id) ?? sessionId,
16878
- viewer: trimmed3(report.viewer) ?? viewer,
17172
+ providerSessionId: trimmed5(report.id) ?? sessionId,
17173
+ viewer: trimmed5(report.viewer) ?? viewer,
16879
17174
  opened: true,
16880
- behavior: trimmed3(report.behavior) ? parseViewerOpenAs(report.behavior) : null
17175
+ behavior: trimmed5(report.behavior) ? parseViewerOpenAs(report.behavior) : null
16881
17176
  };
16882
17177
  }
16883
17178
  function stopLatchSession({ executable = "latch", providerSessionId }) {
16884
- const sessionId = trimmed3(providerSessionId);
17179
+ const sessionId = trimmed5(providerSessionId);
16885
17180
  if (!sessionId)
16886
17181
  throw new LatchSessionCommandError("A Latch session id is required.");
16887
17182
  const report = runLatchJson({
16888
- executable: trimmed3(executable) ?? "latch",
17183
+ executable: trimmed5(executable) ?? "latch",
16889
17184
  args: ["stop", sessionId, "--json"]
16890
17185
  });
16891
17186
  const state = parseState(report.state);
16892
17187
  if (!state)
16893
17188
  throw new LatchSessionCommandError("Latch returned an unsupported session state.");
16894
17189
  return {
16895
- providerSessionId: trimmed3(report.id) ?? sessionId,
17190
+ providerSessionId: trimmed5(report.id) ?? sessionId,
16896
17191
  state
16897
17192
  };
16898
17193
  }
@@ -16900,6 +17195,7 @@ var LatchSessionCommandError;
16900
17195
  var init_latch_session = __esm({
16901
17196
  "../packages/core/dist/service/latch-session.js"() {
16902
17197
  "use strict";
17198
+ init_latch_binary();
16903
17199
  init_latch_environment();
16904
17200
  init_latch_launch();
16905
17201
  init_terminal_profile_types2();
@@ -16914,17 +17210,17 @@ var init_latch_session = __esm({
16914
17210
 
16915
17211
  // ../packages/core/dist/service/latch-events.js
16916
17212
  import { spawn as spawn3 } from "node:child_process";
16917
- function trimmed4(value) {
17213
+ function trimmed6(value) {
16918
17214
  return typeof value === "string" && value.trim() ? value.trim() : null;
16919
17215
  }
16920
17216
  function parseHarnessEvent(value) {
16921
17217
  if (!value || typeof value !== "object" || Array.isArray(value))
16922
17218
  return null;
16923
17219
  const row = value;
16924
- const type = trimmed4(row.type);
16925
- const sessionId = trimmed4(row.sessionId);
16926
- const at = trimmed4(row.at);
16927
- const harnessVersion = trimmed4(row.harnessVersion);
17220
+ const type = trimmed6(row.type);
17221
+ const sessionId = trimmed6(row.sessionId);
17222
+ const at = trimmed6(row.at);
17223
+ const harnessVersion = trimmed6(row.harnessVersion);
16928
17224
  const connectorEpoch = typeof row.connectorEpoch === "number" && Number.isFinite(row.connectorEpoch) ? row.connectorEpoch : null;
16929
17225
  if (!type || !HARNESS_EVENT_TYPES.has(type) || !sessionId || !at || !harnessVersion)
16930
17226
  return null;
@@ -16935,26 +17231,26 @@ function parseHarnessEvent(value) {
16935
17231
  case "user_message":
16936
17232
  case "assistant_delta":
16937
17233
  case "assistant_message": {
16938
- const text = trimmed4(row.text);
17234
+ const text = trimmed6(row.text);
16939
17235
  if (!text)
16940
17236
  return null;
16941
17237
  return { ...base, type, text };
16942
17238
  }
16943
17239
  case "tool_started": {
16944
- const tool = trimmed4(row.tool);
17240
+ const tool = trimmed6(row.tool);
16945
17241
  if (!tool)
16946
17242
  return null;
16947
17243
  return { ...base, type, tool, input: row.input };
16948
17244
  }
16949
17245
  case "tool_finished": {
16950
- const tool = trimmed4(row.tool);
17246
+ const tool = trimmed6(row.tool);
16951
17247
  if (!tool)
16952
17248
  return null;
16953
17249
  return { ...base, type, tool, output: row.output };
16954
17250
  }
16955
17251
  case "awaiting_input": {
16956
- const requestId = trimmed4(row.requestId);
16957
- const kind = trimmed4(row.kind);
17252
+ const requestId = trimmed6(row.requestId);
17253
+ const kind = trimmed6(row.kind);
16958
17254
  const prompt = typeof row.prompt === "string" ? row.prompt : null;
16959
17255
  if (!requestId || kind !== "permission" && kind !== "question" || prompt === null) {
16960
17256
  return null;
@@ -16970,7 +17266,7 @@ function parseHarnessEvent(value) {
16970
17266
  };
16971
17267
  }
16972
17268
  case "status": {
16973
- const status = trimmed4(row.status);
17269
+ const status = trimmed6(row.status);
16974
17270
  if (!status)
16975
17271
  return null;
16976
17272
  return { ...base, type, status };
@@ -16995,11 +17291,13 @@ function parseHarnessEventNdjson(raw) {
16995
17291
  return events;
16996
17292
  }
16997
17293
  async function collectLatchEvents({ executable = "latch", providerSessionId, from = 0, idleMs = 250, timeoutMs = 8e3 }) {
16998
- const sessionId = trimmed4(providerSessionId);
17294
+ const sessionId = trimmed6(providerSessionId);
16999
17295
  if (!sessionId)
17000
17296
  throw new LatchSessionCommandError("A Latch session id is required.");
17001
17297
  const fromCursor = Number.isFinite(from) && from > 0 ? Math.floor(from) : 0;
17002
- const bin = trimmed4(executable) ?? "latch";
17298
+ const bin = resolveLatchBinaryPath(executable);
17299
+ if (!bin)
17300
+ throw new LatchSessionCommandError(latchBinaryMissingMessage(executable));
17003
17301
  return new Promise((resolve, reject) => {
17004
17302
  const child = spawn3(bin, ["events", sessionId, "--json", "--from", String(fromCursor)], {
17005
17303
  stdio: ["ignore", "pipe", "pipe"],
@@ -17067,6 +17365,7 @@ var HARNESS_EVENT_TYPES;
17067
17365
  var init_latch_events = __esm({
17068
17366
  "../packages/core/dist/service/latch-events.js"() {
17069
17367
  "use strict";
17368
+ init_latch_binary();
17070
17369
  init_latch_environment();
17071
17370
  init_latch_session();
17072
17371
  HARNESS_EVENT_TYPES = /* @__PURE__ */ new Set([
@@ -17096,12 +17395,12 @@ var init_util2 = __esm({
17096
17395
  });
17097
17396
 
17098
17397
  // ../packages/core/dist/service/local-target/project-metadata.js
17099
- import { execFileSync } from "node:child_process";
17100
- import { existsSync as existsSync15, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "node:fs";
17101
- import path15 from "node:path";
17398
+ import { execFileSync as execFileSync2 } from "node:child_process";
17399
+ import { existsSync as existsSync17, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
17400
+ import path16 from "node:path";
17102
17401
  function writeIfChanged(filePath, content) {
17103
- if (!existsSync15(filePath) || readFileSync14(filePath, "utf8") !== content) {
17104
- writeFileSync7(filePath, content);
17402
+ if (!existsSync17(filePath) || readFileSync15(filePath, "utf8") !== content) {
17403
+ writeFileSync8(filePath, content);
17105
17404
  }
17106
17405
  }
17107
17406
  function replaceManagedBlock(content, block) {
@@ -17112,25 +17411,25 @@ function replaceManagedBlock(content, block) {
17112
17411
  }
17113
17412
  function ensureAgentInstructions(checkoutPath) {
17114
17413
  for (const filename of ["AGENTS.md", "CLAUDE.md"]) {
17115
- const instructionPath = path15.join(checkoutPath, filename);
17116
- const existing = existsSync15(instructionPath) ? readFileSync14(instructionPath, "utf8") : "";
17414
+ const instructionPath = path16.join(checkoutPath, filename);
17415
+ const existing = existsSync17(instructionPath) ? readFileSync15(instructionPath, "utf8") : "";
17117
17416
  writeIfChanged(instructionPath, replaceManagedBlock(existing, PROJECT_METADATA_INSTRUCTION));
17118
17417
  }
17119
17418
  }
17120
17419
  function ensureGitignore(checkoutPath) {
17121
- const gitignorePath = path15.join(checkoutPath, ".gitignore");
17122
- const existing = existsSync15(gitignorePath) ? readFileSync14(gitignorePath, "utf8") : "";
17420
+ const gitignorePath = path16.join(checkoutPath, ".gitignore");
17421
+ const existing = existsSync17(gitignorePath) ? readFileSync15(gitignorePath, "utf8") : "";
17123
17422
  const existingPatterns = new Set(existing.split(/\r?\n/).map((line) => line.trim().replace(/^\//, "")).filter(Boolean));
17124
17423
  const additions = [".overlord/tmp/", ".overlord/logs/"].filter((pattern) => !existingPatterns.has(pattern));
17125
17424
  if (additions.length === 0)
17126
17425
  return;
17127
17426
  const separator = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
17128
- writeFileSync7(gitignorePath, `${existing}${separator}${additions.join("\n")}
17427
+ writeFileSync8(gitignorePath, `${existing}${separator}${additions.join("\n")}
17129
17428
  `);
17130
17429
  }
17131
17430
  function resolveGitRoot(directoryPath) {
17132
17431
  try {
17133
- return execFileSync("git", ["-C", directoryPath, "rev-parse", "--show-toplevel"], {
17432
+ return execFileSync2("git", ["-C", directoryPath, "rev-parse", "--show-toplevel"], {
17134
17433
  encoding: "utf8",
17135
17434
  stdio: ["ignore", "pipe", "ignore"]
17136
17435
  }).trim();
@@ -17187,9 +17486,9 @@ function selectPrimaryProjectEntry(projects) {
17187
17486
  return latestLinkedAt(projects);
17188
17487
  }
17189
17488
  function parseProjectJson(projectJsonPath) {
17190
- if (!existsSync15(projectJsonPath))
17489
+ if (!existsSync17(projectJsonPath))
17191
17490
  return null;
17192
- const parsed = JSON.parse(readFileSync14(projectJsonPath, "utf8"));
17491
+ const parsed = JSON.parse(readFileSync15(projectJsonPath, "utf8"));
17193
17492
  const fromArray = Array.isArray(parsed.projects) ? parsed.projects.map((entry) => parseProjectEntry(entry)).filter((entry) => entry !== null) : [];
17194
17493
  const fromTopLevel = parseProjectEntry(parsed);
17195
17494
  const projects = fromArray.length > 0 ? fromArray : fromTopLevel ? [fromTopLevel] : [];
@@ -17256,12 +17555,12 @@ function serializeProjectEntry(entry) {
17256
17555
  };
17257
17556
  }
17258
17557
  function writeProjectJson({ directoryPath, projectId, projectName, resourceId, resourceKey, executionTargetId, isPrimary }) {
17259
- const overlordDir = path15.join(directoryPath, ".overlord");
17260
- mkdirSync8(overlordDir, { recursive: true });
17261
- mkdirSync8(path15.join(overlordDir, "tmp"), { recursive: true });
17262
- mkdirSync8(path15.join(overlordDir, "logs"), { recursive: true });
17558
+ const overlordDir = path16.join(directoryPath, ".overlord");
17559
+ mkdirSync9(overlordDir, { recursive: true });
17560
+ mkdirSync9(path16.join(overlordDir, "tmp"), { recursive: true });
17561
+ mkdirSync9(path16.join(overlordDir, "logs"), { recursive: true });
17263
17562
  protectProjectMetadata(directoryPath);
17264
- const projectJsonPath = path15.join(overlordDir, "project.json");
17563
+ const projectJsonPath = path16.join(overlordDir, "project.json");
17265
17564
  const existing = parseProjectJson(projectJsonPath);
17266
17565
  const existingProjects = existing?.projects ?? [];
17267
17566
  const existingEntry = existingProjects.find((entry) => entry.projectId === projectId);
@@ -17288,7 +17587,7 @@ function writeProjectJson({ directoryPath, projectId, projectName, resourceId, r
17288
17587
  ];
17289
17588
  const primary = selectPrimaryProjectEntry(projects) ?? nextEntry;
17290
17589
  const primaryResourceIds = primary.resourceIdsByExecutionTarget ?? {};
17291
- writeFileSync7(projectJsonPath, `${JSON.stringify({
17590
+ writeFileSync8(projectJsonPath, `${JSON.stringify({
17292
17591
  _warning: PROJECT_JSON_WARNING,
17293
17592
  version: PROJECT_JSON_VERSION,
17294
17593
  projectId: primary.projectId,
@@ -17323,11 +17622,11 @@ ${INSTRUCTION_BLOCK_END}`;
17323
17622
  });
17324
17623
 
17325
17624
  // ../packages/core/dist/repository/git-tree.js
17326
- import { execFileSync as execFileSync2 } from "node:child_process";
17327
- import path16 from "node:path";
17625
+ import { execFileSync as execFileSync3 } from "node:child_process";
17626
+ import path17 from "node:path";
17328
17627
  function runGit(cwd, args) {
17329
17628
  try {
17330
- return execFileSync2("git", args, {
17629
+ return execFileSync3("git", args, {
17331
17630
  cwd,
17332
17631
  encoding: "utf8",
17333
17632
  maxBuffer: 10 * 1024 * 1024,
@@ -17347,17 +17646,17 @@ function gitPath(cwd, args) {
17347
17646
  }
17348
17647
  }
17349
17648
  function addDirectoryAncestors(paths, filePath) {
17350
- let parent = path16.posix.dirname(filePath);
17649
+ let parent = path17.posix.dirname(filePath);
17351
17650
  while (parent !== "." && parent !== "/") {
17352
17651
  paths.add(parent);
17353
- parent = path16.posix.dirname(parent);
17652
+ parent = path17.posix.dirname(parent);
17354
17653
  }
17355
17654
  }
17356
17655
  function toEntry(entryPath, type) {
17357
- const parentPath = path16.posix.dirname(entryPath);
17656
+ const parentPath = path17.posix.dirname(entryPath);
17358
17657
  return {
17359
17658
  path: entryPath,
17360
- name: path16.posix.basename(entryPath),
17659
+ name: path17.posix.basename(entryPath),
17361
17660
  type,
17362
17661
  parentPath: parentPath === "." ? null : parentPath,
17363
17662
  depth: entryPath.split("/").length - 1
@@ -17369,7 +17668,7 @@ function compareEntries(a, b) {
17369
17668
  return a.path < b.path ? -1 : 1;
17370
17669
  }
17371
17670
  function readRepositoryTree(rootPath, options = {}) {
17372
- const resolvedRoot = path16.resolve(rootPath);
17671
+ const resolvedRoot = path17.resolve(rootPath);
17373
17672
  const gitRoot = gitPath(resolvedRoot, ["rev-parse", "--show-toplevel"]);
17374
17673
  if (!gitRoot) {
17375
17674
  throw new RepositoryReadError("not_git_repository", `${resolvedRoot} is not inside a git repository.`);
@@ -17392,7 +17691,7 @@ function readRepositoryTree(rootPath, options = {}) {
17392
17691
  const truncated = entries.length > maxEntries;
17393
17692
  return {
17394
17693
  rootPath: resolvedRoot,
17395
- gitRoot: path16.resolve(gitRoot),
17694
+ gitRoot: path17.resolve(gitRoot),
17396
17695
  branch: gitPath(gitRoot, ["branch", "--show-current"]),
17397
17696
  commit: gitPath(gitRoot, ["rev-parse", "--short", "HEAD"]),
17398
17697
  entries: truncated ? entries.slice(0, maxEntries) : entries,
@@ -17414,274 +17713,14 @@ var init_git_tree = __esm({
17414
17713
  }
17415
17714
  });
17416
17715
 
17417
- // ../packages/core/dist/service/latch-discovery.js
17418
- import { execFileSync as execFileSync3 } from "node:child_process";
17419
- import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync15, statSync as statSync4, writeFileSync as writeFileSync8 } from "node:fs";
17420
- import os3 from "node:os";
17421
- import path17 from "node:path";
17422
- function defaultLatchDiscoveryCachePath() {
17423
- const home = process.env.OVLD_HOME?.trim() || path17.join(os3.homedir(), ".ovld");
17424
- return path17.join(home, LATCH_DISCOVERY_CACHE_FILENAME);
17425
- }
17426
- function trimmed5(value) {
17427
- return typeof value === "string" && value.trim() ? value.trim() : null;
17428
- }
17429
- function asBoolean(value) {
17430
- return value === true;
17431
- }
17432
- function asStringArray(value) {
17433
- if (!Array.isArray(value))
17434
- return [];
17435
- return value.filter((entry) => typeof entry === "string");
17436
- }
17437
- function parseLatchCapabilitiesReport(raw) {
17438
- const text = raw.trim();
17439
- if (!text)
17440
- return null;
17441
- let parsed;
17442
- try {
17443
- parsed = JSON.parse(text);
17444
- } catch {
17445
- return null;
17446
- }
17447
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
17448
- return null;
17449
- const cast = parsed;
17450
- const protocolVersion = typeof cast.protocolVersion === "number" && Number.isFinite(cast.protocolVersion) ? Math.trunc(cast.protocolVersion) : null;
17451
- const productVersion = trimmed5(cast.productVersion);
17452
- if (protocolVersion === null || !productVersion)
17453
- return null;
17454
- if (!cast.capabilities || typeof cast.capabilities !== "object" || Array.isArray(cast.capabilities)) {
17455
- return null;
17456
- }
17457
- const caps = cast.capabilities;
17458
- return {
17459
- protocolVersion,
17460
- productVersion,
17461
- capabilities: {
17462
- create: asBoolean(caps.create),
17463
- openViewer: asBoolean(caps.openViewer),
17464
- localAttach: asBoolean(caps.localAttach),
17465
- cloudAttach: asBoolean(caps.cloudAttach),
17466
- selfUpdate: asBoolean(caps.selfUpdate),
17467
- extensions: asStringArray(caps.extensions)
17468
- }
17469
- };
17470
- }
17471
- function evaluateLatchCapabilities({ report, executable, resolvedPath, checkedAt = (/* @__PURE__ */ new Date()).toISOString() }) {
17472
- if (report.protocolVersion !== SUPPORTED_LATCH_PROTOCOL_VERSION) {
17473
- return {
17474
- state: "incompatible",
17475
- executable,
17476
- resolvedPath,
17477
- protocolVersion: report.protocolVersion,
17478
- productVersion: report.productVersion,
17479
- missingCapability: "protocolVersion",
17480
- detail: `Latch protocolVersion ${report.protocolVersion} is not supported (need ${SUPPORTED_LATCH_PROTOCOL_VERSION}).`,
17481
- checkedAt,
17482
- latchSelectable: false,
17483
- directSelectable: true
17484
- };
17485
- }
17486
- for (const required of REQUIRED_LATCH_CAPABILITIES) {
17487
- if (!report.capabilities[required]) {
17488
- return {
17489
- state: "incompatible",
17490
- executable,
17491
- resolvedPath,
17492
- protocolVersion: report.protocolVersion,
17493
- productVersion: report.productVersion,
17494
- missingCapability: required,
17495
- detail: `Latch is missing required capability \`${required}\`.`,
17496
- checkedAt,
17497
- latchSelectable: false,
17498
- directSelectable: true
17499
- };
17500
- }
17501
- }
17502
- return {
17503
- state: "found",
17504
- executable,
17505
- resolvedPath,
17506
- protocolVersion: report.protocolVersion,
17507
- productVersion: report.productVersion,
17508
- capabilities: report.capabilities,
17509
- checkedAt,
17510
- latchSelectable: true,
17511
- directSelectable: true
17512
- };
17513
- }
17514
- function resolveLatchExecutableOnPath(executable) {
17515
- try {
17516
- const found = execFileSync3("which", [executable], {
17517
- encoding: "utf8",
17518
- stdio: ["ignore", "pipe", "ignore"]
17519
- }).trim();
17520
- return found || null;
17521
- } catch {
17522
- return null;
17523
- }
17524
- }
17525
- function resolveLatchExecutablePathFromEnvironment({ executable, homeDirectory = os3.homedir(), platform: platform2 = process.platform, resolveOnPath = resolveLatchExecutableOnPath, fileExists = existsSync16 }) {
17526
- const name = trimmed5(executable) ?? DEFAULT_LATCH_EXECUTABLE;
17527
- if (path17.isAbsolute(name) || name.includes("/") || name.includes("\\")) {
17528
- return fileExists(name) ? path17.resolve(name) : null;
17529
- }
17530
- const resolvedOnPath = resolveOnPath(name);
17531
- if (resolvedOnPath)
17532
- return resolvedOnPath;
17533
- const fallbacks = [
17534
- path17.join(homeDirectory, ".local", "bin", name),
17535
- ...platform2 === "darwin" ? [`/opt/homebrew/bin/${name}`, `/usr/local/bin/${name}`] : []
17536
- ];
17537
- const fallback = fallbacks.find(fileExists);
17538
- return fallback ? path17.resolve(fallback) : null;
17539
- }
17540
- function resolveLatchExecutablePath(executable) {
17541
- return resolveLatchExecutablePathFromEnvironment({ executable });
17542
- }
17543
- function notInstalledResult({ executable, checkedAt }) {
17544
- return {
17545
- state: "not_installed",
17546
- executable,
17547
- installCommand: LATCH_STANDALONE_INSTALL_COMMAND,
17548
- checkedAt,
17549
- latchSelectable: false,
17550
- directSelectable: true
17551
- };
17552
- }
17553
- function probeLatchCapabilities({ executable = DEFAULT_LATCH_EXECUTABLE, resolvePath = resolveLatchExecutablePath, runCommand: runCommand2 = defaultCommandRunner, now = () => (/* @__PURE__ */ new Date()).toISOString() } = {}) {
17554
- const exe = trimmed5(executable) ?? DEFAULT_LATCH_EXECUTABLE;
17555
- const checkedAt = now();
17556
- const resolvedPath = resolvePath(exe);
17557
- if (!resolvedPath) {
17558
- return notInstalledResult({ executable: exe, checkedAt });
17559
- }
17560
- const ran = runCommand2({ executable: resolvedPath, argv: ["capabilities", "--json"] });
17561
- if (ran.status === null && ran.stderr === "ENOENT") {
17562
- return notInstalledResult({ executable: exe, checkedAt });
17563
- }
17564
- const report = parseLatchCapabilitiesReport(ran.stdout);
17565
- if (!report) {
17566
- return {
17567
- state: "incompatible",
17568
- executable: exe,
17569
- resolvedPath,
17570
- protocolVersion: null,
17571
- productVersion: null,
17572
- missingCapability: "capabilities",
17573
- detail: ran.status === 0 ? "Latch capabilities output was not valid JSON in the expected shape." : `Latch capabilities failed (exit ${ran.status ?? "null"}).`,
17574
- checkedAt,
17575
- latchSelectable: false,
17576
- directSelectable: true
17577
- };
17578
- }
17579
- return evaluateLatchCapabilities({ report, executable: exe, resolvedPath, checkedAt });
17580
- }
17581
- function latchDiscoveryCacheKey({ executionTargetId, executable }) {
17582
- const exe = trimmed5(executable) ?? DEFAULT_LATCH_EXECUTABLE;
17583
- return `${executionTargetId}::${exe}`;
17584
- }
17585
- function readBinaryMtimeMs(resolvedPath) {
17586
- if (!resolvedPath)
17587
- return null;
17588
- try {
17589
- return statSync4(resolvedPath).mtimeMs;
17590
- } catch {
17591
- return null;
17592
- }
17593
- }
17594
- function isLatchDiscoveryCacheFresh({ entry, resolvePath = resolveLatchExecutablePath }) {
17595
- const { result } = entry;
17596
- if (result.state === "not_installed") {
17597
- return resolvePath(result.executable) === null;
17598
- }
17599
- const pathStill = result.resolvedPath;
17600
- if (!pathStill || !existsSync16(pathStill))
17601
- return false;
17602
- const mtime = readBinaryMtimeMs(pathStill);
17603
- if (mtime === null || entry.binaryMtimeMs === null)
17604
- return false;
17605
- return mtime === entry.binaryMtimeMs;
17606
- }
17607
- function readLatchDiscoveryCacheFile(filePath) {
17608
- if (!existsSync16(filePath))
17609
- return { version: 1, entries: {} };
17610
- try {
17611
- const parsed = JSON.parse(readFileSync15(filePath, "utf8"));
17612
- if (parsed.version !== 1 || !parsed.entries || typeof parsed.entries !== "object") {
17613
- return { version: 1, entries: {} };
17614
- }
17615
- return { version: 1, entries: parsed.entries };
17616
- } catch {
17617
- return { version: 1, entries: {} };
17618
- }
17619
- }
17620
- function writeLatchDiscoveryCacheFile({ filePath, cache }) {
17621
- mkdirSync9(path17.dirname(filePath), { recursive: true });
17622
- writeFileSync8(filePath, `${JSON.stringify(cache, null, 2)}
17623
- `, { mode: 384 });
17624
- }
17625
- function discoverLatchForExecutionTarget({ executionTargetId, executable = DEFAULT_LATCH_EXECUTABLE, cacheFilePath, force = false, resolvePath = resolveLatchExecutablePath, runCommand: runCommand2 = defaultCommandRunner, now = () => (/* @__PURE__ */ new Date()).toISOString() }) {
17626
- const exe = trimmed5(executable) ?? DEFAULT_LATCH_EXECUTABLE;
17627
- const key = latchDiscoveryCacheKey({ executionTargetId, executable: exe });
17628
- const cache = readLatchDiscoveryCacheFile(cacheFilePath);
17629
- const existing = cache.entries[key];
17630
- if (!force && existing && isLatchDiscoveryCacheFresh({ entry: existing, resolvePath })) {
17631
- return { ...existing.result, checkedAt: existing.result.checkedAt, directSelectable: true };
17632
- }
17633
- const result = probeLatchCapabilities({ executable: exe, resolvePath, runCommand: runCommand2, now });
17634
- const binaryMtimeMs = result.state === "not_installed" ? null : readBinaryMtimeMs(result.resolvedPath);
17635
- cache.entries[key] = {
17636
- result,
17637
- binaryMtimeMs,
17638
- cachedAt: result.checkedAt
17639
- };
17640
- writeLatchDiscoveryCacheFile({ filePath: cacheFilePath, cache });
17641
- return result;
17642
- }
17643
- var SUPPORTED_LATCH_PROTOCOL_VERSION, REQUIRED_LATCH_CAPABILITIES, LATCH_STANDALONE_INSTALL_COMMAND, LATCH_DISCOVERY_CACHE_FILENAME, defaultCommandRunner;
17644
- var init_latch_discovery = __esm({
17645
- "../packages/core/dist/service/latch-discovery.js"() {
17646
- "use strict";
17647
- init_latch_environment();
17648
- init_terminal_profile_types2();
17649
- SUPPORTED_LATCH_PROTOCOL_VERSION = 1;
17650
- REQUIRED_LATCH_CAPABILITIES = ["create"];
17651
- LATCH_STANDALONE_INSTALL_COMMAND = "curl -fsSL https://raw.githubusercontent.com/jchaselubitz/Latch/main/scripts/install-cli.sh | bash";
17652
- LATCH_DISCOVERY_CACHE_FILENAME = "latch-discovery.json";
17653
- defaultCommandRunner = ({ executable, argv }) => {
17654
- try {
17655
- const stdout = execFileSync3(executable, argv, {
17656
- encoding: "utf8",
17657
- stdio: ["ignore", "pipe", "pipe"],
17658
- timeout: 5e3,
17659
- env: latchChildEnvironment()
17660
- });
17661
- return { status: 0, stdout: String(stdout), stderr: "" };
17662
- } catch (error) {
17663
- const err = error;
17664
- if (err.code === "ENOENT") {
17665
- return { status: null, stdout: "", stderr: "ENOENT" };
17666
- }
17667
- return {
17668
- status: typeof err.status === "number" ? err.status : 1,
17669
- stdout: err.stdout ? String(err.stdout) : "",
17670
- stderr: err.stderr ? String(err.stderr) : String(error)
17671
- };
17672
- }
17673
- };
17674
- }
17675
- });
17676
-
17677
17716
  // ../packages/core/dist/service/latch-send.js
17678
17717
  import { spawnSync as spawnSync3 } from "node:child_process";
17679
- function trimmed6(value) {
17718
+ function trimmed7(value) {
17680
17719
  return typeof value === "string" && value.trim() ? value.trim() : null;
17681
17720
  }
17682
17721
  function probeLatchInteractionCapabilities({ executable = "latch", providerSessionId }) {
17683
- const sessionId = trimmed6(providerSessionId);
17684
- const bin = trimmed6(executable) ?? "latch";
17722
+ const sessionId = trimmed7(providerSessionId);
17723
+ const bin = resolveLatchBinaryPath(executable);
17685
17724
  if (!sessionId) {
17686
17725
  return {
17687
17726
  sendMessage: false,
@@ -17690,6 +17729,14 @@ function probeLatchInteractionCapabilities({ executable = "latch", providerSessi
17690
17729
  canSend: { ok: false, reason: "A Latch session id is required." }
17691
17730
  };
17692
17731
  }
17732
+ if (!bin) {
17733
+ return {
17734
+ sendMessage: false,
17735
+ sendKeys: false,
17736
+ resolve: false,
17737
+ canSend: { ok: false, reason: latchBinaryMissingMessage(executable) }
17738
+ };
17739
+ }
17693
17740
  const help = spawnSync3(bin, ["send", "--help"], {
17694
17741
  encoding: "utf8",
17695
17742
  shell: false,
@@ -17716,9 +17763,9 @@ ${help.stderr}`),
17716
17763
  };
17717
17764
  }
17718
17765
  function resolveLatchInput({ executable = "latch", providerSessionId, requestId, choice }) {
17719
- const sessionId = trimmed6(providerSessionId);
17720
- const id = trimmed6(requestId);
17721
- const selected = trimmed6(choice);
17766
+ const sessionId = trimmed7(providerSessionId);
17767
+ const id = trimmed7(requestId);
17768
+ const selected = trimmed7(choice);
17722
17769
  if (!sessionId)
17723
17770
  throw new LatchSessionCommandError("A Latch session id is required.");
17724
17771
  if (!id)
@@ -17732,7 +17779,9 @@ function resolveLatchInput({ executable = "latch", providerSessionId, requestId,
17732
17779
  if (!capabilities.resolve || !capabilities.canSend.ok) {
17733
17780
  throw new LatchSessionCommandError(capabilities.canSend.reason || "This Latch session cannot resolve a pending prompt.");
17734
17781
  }
17735
- const bin = trimmed6(executable) ?? "latch";
17782
+ const bin = resolveLatchBinaryPath(executable);
17783
+ if (!bin)
17784
+ throw new LatchSessionCommandError(latchBinaryMissingMessage(executable));
17736
17785
  const result = spawnSync3(bin, ["send", sessionId, "--resolve", `${id}=${selected}`, "--json"], {
17737
17786
  encoding: "utf8",
17738
17787
  shell: false,
@@ -17756,6 +17805,7 @@ function resolveLatchInput({ executable = "latch", providerSessionId, requestId,
17756
17805
  var init_latch_send = __esm({
17757
17806
  "../packages/core/dist/service/latch-send.js"() {
17758
17807
  "use strict";
17808
+ init_latch_binary();
17759
17809
  init_latch_environment();
17760
17810
  init_latch_session();
17761
17811
  }
@@ -17800,7 +17850,7 @@ var init_git_run = __esm({
17800
17850
  });
17801
17851
 
17802
17852
  // ../packages/core/dist/service/local-target/worktree-git.js
17803
- import { existsSync as existsSync17, realpathSync as realpathSync2 } from "node:fs";
17853
+ import { existsSync as existsSync18, realpathSync as realpathSync2 } from "node:fs";
17804
17854
  import path18 from "node:path";
17805
17855
  function resolveRealPath(targetPath) {
17806
17856
  try {
@@ -17836,7 +17886,7 @@ function removeGitWorktree({ primaryRepoPath, worktreePath, force }) {
17836
17886
  args.push(worktreePath);
17837
17887
  runGitResult(primaryRepoPath, args);
17838
17888
  runGitResult(primaryRepoPath, ["worktree", "prune"]);
17839
- return !existsSync17(worktreePath);
17889
+ return !existsSync18(worktreePath);
17840
17890
  }
17841
17891
  function collectManagedWorktrees({ worktreeRoot, projects }) {
17842
17892
  const resolvedRoot = resolveRealPath(worktreeRoot);
@@ -17844,7 +17894,7 @@ function collectManagedWorktrees({ worktreeRoot, projects }) {
17844
17894
  const seen = /* @__PURE__ */ new Set();
17845
17895
  for (const project of projects) {
17846
17896
  const repoPath = project.primaryRepoPath;
17847
- if (!repoPath || !existsSync17(repoPath))
17897
+ if (!repoPath || !existsSync18(repoPath))
17848
17898
  continue;
17849
17899
  const out = runGitResult(repoPath, ["worktree", "list", "--porcelain"]);
17850
17900
  if (!out.ok)
@@ -17922,10 +17972,10 @@ var init_worktree_git = __esm({
17922
17972
  });
17923
17973
 
17924
17974
  // ../packages/core/dist/service/local-target/branch-actions-git.js
17925
- import { existsSync as existsSync18 } from "node:fs";
17975
+ import { existsSync as existsSync19 } from "node:fs";
17926
17976
  function integrateBranch(input) {
17927
17977
  const { branchName, baseBranch, worktreePath, primaryRepoPath } = input;
17928
- if (!existsSync18(worktreePath)) {
17978
+ if (!existsSync19(worktreePath)) {
17929
17979
  return {
17930
17980
  ok: false,
17931
17981
  code: "BRANCH_NO_WORKTREE",
@@ -17999,15 +18049,15 @@ function integrateBranch(input) {
17999
18049
  }
18000
18050
  function commitBranch(input) {
18001
18051
  const { branchName, worktreePath } = input;
18002
- const trimmed7 = (input.message ?? "").trim();
18003
- if (!trimmed7) {
18052
+ const trimmed8 = (input.message ?? "").trim();
18053
+ if (!trimmed8) {
18004
18054
  return {
18005
18055
  ok: false,
18006
18056
  code: "BRANCH_COMMIT_MESSAGE_REQUIRED",
18007
18057
  message: "A commit message is required."
18008
18058
  };
18009
18059
  }
18010
- if (!existsSync18(worktreePath)) {
18060
+ if (!existsSync19(worktreePath)) {
18011
18061
  return {
18012
18062
  ok: false,
18013
18063
  code: "BRANCH_NO_WORKTREE",
@@ -18039,7 +18089,7 @@ function commitBranch(input) {
18039
18089
  detail: staged.stderr || staged.stdout
18040
18090
  };
18041
18091
  }
18042
- const commit = runGitResult(worktreePath, ["commit", "-m", trimmed7]);
18092
+ const commit = runGitResult(worktreePath, ["commit", "-m", trimmed8]);
18043
18093
  if (!commit.ok) {
18044
18094
  return {
18045
18095
  ok: false,
@@ -18063,7 +18113,7 @@ function pushParent(input) {
18063
18113
  };
18064
18114
  }
18065
18115
  let summary = `Pushed ${baseBranch} to origin.`;
18066
- if (existsSync18(worktreePath) && !worktreeIsDirty(worktreePath)) {
18116
+ if (existsSync19(worktreePath) && !worktreeIsDirty(worktreePath)) {
18067
18117
  if (removeGitWorktree({ primaryRepoPath, worktreePath, force: false })) {
18068
18118
  summary += ` Removed the merged worktree for ${branchName}.`;
18069
18119
  }
@@ -18072,7 +18122,7 @@ function pushParent(input) {
18072
18122
  }
18073
18123
  function publishBranch(input) {
18074
18124
  const { branchName, worktreePath, primaryRepoPath } = input;
18075
- const repo = existsSync18(worktreePath) ? worktreePath : primaryRepoPath;
18125
+ const repo = existsSync19(worktreePath) ? worktreePath : primaryRepoPath;
18076
18126
  const push = runGitResult(repo, ["push", "-u", "origin", branchName]);
18077
18127
  if (!push.ok) {
18078
18128
  return {
@@ -18122,7 +18172,7 @@ var init_branch_status_git = __esm({
18122
18172
  });
18123
18173
 
18124
18174
  // ../packages/core/dist/service/local-target/commit-message-diff-git.js
18125
- import { existsSync as existsSync19 } from "node:fs";
18175
+ import { existsSync as existsSync20 } from "node:fs";
18126
18176
  function collectWorktreeChanges(worktreePath) {
18127
18177
  const status = runGitResult(worktreePath, ["status", "--porcelain"]);
18128
18178
  const diff = runGitResult(worktreePath, ["diff", "HEAD"]);
@@ -18138,7 +18188,7 @@ ${diff.stdout}`);
18138
18188
  return sections.join("\n\n");
18139
18189
  }
18140
18190
  function gatherCommitMessageDiff(worktreePath) {
18141
- if (!existsSync19(worktreePath)) {
18191
+ if (!existsSync20(worktreePath)) {
18142
18192
  return {
18143
18193
  ok: false,
18144
18194
  code: "BRANCH_NO_WORKTREE",
@@ -18199,7 +18249,7 @@ var init_result = __esm({
18199
18249
  });
18200
18250
 
18201
18251
  // ../packages/core/dist/service/local-target/in-process-provider.js
18202
- import { existsSync as existsSync20 } from "node:fs";
18252
+ import { existsSync as existsSync21 } from "node:fs";
18203
18253
  var InProcessProvider;
18204
18254
  var init_in_process_provider = __esm({
18205
18255
  "../packages/core/dist/service/local-target/in-process-provider.js"() {
@@ -18232,7 +18282,7 @@ var init_in_process_provider = __esm({
18232
18282
  */
18233
18283
  async observeResource(input) {
18234
18284
  const observedAt = (/* @__PURE__ */ new Date()).toISOString();
18235
- const state = existsSync20(input.path) ? "available" : "missing";
18285
+ const state = existsSync21(input.path) ? "available" : "missing";
18236
18286
  return ok(this.target, { state, observedAt });
18237
18287
  }
18238
18288
  /**
@@ -18679,7 +18729,7 @@ var init_branch_planning = __esm({
18679
18729
 
18680
18730
  // src/branch-preparation.ts
18681
18731
  import { execFileSync as execFileSync6 } from "node:child_process";
18682
- import { existsSync as existsSync21, mkdirSync as mkdirSync10, statSync as statSync5 } from "node:fs";
18732
+ import { existsSync as existsSync22, mkdirSync as mkdirSync10, statSync as statSync5 } from "node:fs";
18683
18733
  import os4 from "node:os";
18684
18734
  import path21 from "node:path";
18685
18735
  function runGit3(cwd, args, options = {}) {
@@ -18851,7 +18901,7 @@ function ensureBranchRef(gitRoot, decision) {
18851
18901
  function ensureWorktree(gitRoot, decision) {
18852
18902
  ensureBranchRef(gitRoot, decision);
18853
18903
  mkdirSync10(path21.dirname(decision.worktreePath), { recursive: true });
18854
- if (existsSync21(decision.worktreePath)) {
18904
+ if (existsSync22(decision.worktreePath)) {
18855
18905
  if (!statSync5(decision.worktreePath).isDirectory()) {
18856
18906
  throw new Error(`Worktree path exists and is not a directory: ${decision.worktreePath}`);
18857
18907
  }
@@ -19026,16 +19076,16 @@ async function resolveProjectByIdOrName({
19026
19076
  backend,
19027
19077
  projectRef
19028
19078
  }) {
19029
- const trimmed7 = projectRef.trim();
19079
+ const trimmed8 = projectRef.trim();
19030
19080
  try {
19031
- return await backend.get(`/api/projects/${encodeURIComponent(trimmed7)}`);
19081
+ return await backend.get(`/api/projects/${encodeURIComponent(trimmed8)}`);
19032
19082
  } catch (error) {
19033
19083
  if (!(error instanceof CliError) || !/project not found/i.test(error.message)) throw error;
19034
19084
  }
19035
19085
  const projects = await listAccessibleProjects({ backend });
19036
- const match = projects.find((project) => project.name === trimmed7) ?? projects.find((project) => project.slug === trimmed7);
19086
+ const match = projects.find((project) => project.name === trimmed8) ?? projects.find((project) => project.slug === trimmed8);
19037
19087
  if (!match) {
19038
- throw new CliError({ message: `Project not found: ${trimmed7}` });
19088
+ throw new CliError({ message: `Project not found: ${trimmed8}` });
19039
19089
  }
19040
19090
  return match;
19041
19091
  }
@@ -20119,7 +20169,7 @@ var init_launch = __esm({
20119
20169
  });
20120
20170
 
20121
20171
  // src/launch-bootstrap.ts
20122
- import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
20172
+ import { existsSync as existsSync23, readdirSync as readdirSync4, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
20123
20173
  import path25 from "node:path";
20124
20174
  function firstCapture(match) {
20125
20175
  if (!match) return null;
@@ -20141,7 +20191,7 @@ function recoverLaunchBootstrapFromProjectTmp({
20141
20191
  const trimmedMission = missionId.trim();
20142
20192
  if (!trimmedMission) return empty;
20143
20193
  const tmpDir = projectTmpDir(workingDirectory);
20144
- if (!existsSync22(tmpDir)) return empty;
20194
+ if (!existsSync23(tmpDir)) return empty;
20145
20195
  const prefix = `launch-${safeMissionPart(trimmedMission)}-`;
20146
20196
  let newest = null;
20147
20197
  try {
@@ -20199,8 +20249,8 @@ function promptText({
20199
20249
  return new Promise((resolve) => {
20200
20250
  rl.question(`${question}${suffix}: `, (answer) => {
20201
20251
  rl.close();
20202
- const trimmed7 = answer.trim();
20203
- resolve(trimmed7 || defaultValue || "");
20252
+ const trimmed8 = answer.trim();
20253
+ resolve(trimmed8 || defaultValue || "");
20204
20254
  });
20205
20255
  });
20206
20256
  }
@@ -20789,7 +20839,7 @@ var init_protocol_help = __esm({
20789
20839
 
20790
20840
  // src/vcs-sessions.ts
20791
20841
  import { createHash as createHash8 } from "node:crypto";
20792
- import { existsSync as existsSync23, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "node:fs";
20842
+ import { existsSync as existsSync24, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "node:fs";
20793
20843
  import path27 from "node:path";
20794
20844
  function manifestPath2(workingDirectory) {
20795
20845
  const key = createHash8("sha256").update(path27.resolve(workingDirectory)).digest("hex");
@@ -20798,7 +20848,7 @@ function manifestPath2(workingDirectory) {
20798
20848
  function readEntries(workingDirectory) {
20799
20849
  try {
20800
20850
  const target = manifestPath2(workingDirectory);
20801
- if (!existsSync23(target)) return [];
20851
+ if (!existsSync24(target)) return [];
20802
20852
  const raw = JSON.parse(readFileSync18(target, "utf8"));
20803
20853
  if (!Array.isArray(raw.entries)) return [];
20804
20854
  const now = Date.now();
@@ -20872,7 +20922,7 @@ var init_vcs_sessions = __esm({
20872
20922
  import { execFileSync as execFileSync7 } from "node:child_process";
20873
20923
  import { createHash as createHash9 } from "node:crypto";
20874
20924
  import {
20875
- existsSync as existsSync24,
20925
+ existsSync as existsSync25,
20876
20926
  mkdirSync as mkdirSync12,
20877
20927
  readdirSync as readdirSync5,
20878
20928
  readFileSync as readFileSync19,
@@ -20984,7 +21034,7 @@ function readBashSnapshot({
20984
21034
  }) {
20985
21035
  try {
20986
21036
  const target = bashSnapshotPath({ workingDirectory, missionId });
20987
- if (!existsSync24(target)) return /* @__PURE__ */ new Map();
21037
+ if (!existsSync25(target)) return /* @__PURE__ */ new Map();
20988
21038
  const raw = JSON.parse(readFileSync19(target, "utf8"));
20989
21039
  const byPath = /* @__PURE__ */ new Map();
20990
21040
  if (Array.isArray(raw.files)) {
@@ -21076,7 +21126,7 @@ function resetTouchedFiles({
21076
21126
  touchedFilesPath({ workingDirectory, missionId }),
21077
21127
  bashSnapshotPath({ workingDirectory, missionId })
21078
21128
  ]) {
21079
- if (existsSync24(target)) rmSync5(target);
21129
+ if (existsSync25(target)) rmSync5(target);
21080
21130
  }
21081
21131
  } catch {
21082
21132
  }
@@ -21087,14 +21137,14 @@ function resetRationaleNotes({
21087
21137
  }) {
21088
21138
  try {
21089
21139
  const target = rationaleNotesPath({ workingDirectory, missionId });
21090
- if (existsSync24(target)) rmSync5(target);
21140
+ if (existsSync25(target)) rmSync5(target);
21091
21141
  } catch {
21092
21142
  }
21093
21143
  }
21094
21144
  function truncateNoteText(value, max = 500) {
21095
- const trimmed7 = (value ?? "").replace(/\s+/g, " ").trim();
21096
- if (!trimmed7) return null;
21097
- return trimmed7.length > max ? `${trimmed7.slice(0, max - 1)}...` : trimmed7;
21145
+ const trimmed8 = (value ?? "").replace(/\s+/g, " ").trim();
21146
+ if (!trimmed8) return null;
21147
+ return trimmed8.length > max ? `${trimmed8.slice(0, max - 1)}...` : trimmed8;
21098
21148
  }
21099
21149
  function readRationaleNotes({
21100
21150
  workingDirectory,
@@ -21102,7 +21152,7 @@ function readRationaleNotes({
21102
21152
  }) {
21103
21153
  try {
21104
21154
  const target = rationaleNotesPath({ workingDirectory, missionId });
21105
- if (!existsSync24(target)) return [];
21155
+ if (!existsSync25(target)) return [];
21106
21156
  const raw = JSON.parse(readFileSync19(target, "utf8"));
21107
21157
  if (!Array.isArray(raw.notes)) return [];
21108
21158
  return raw.notes.flatMap((note) => {
@@ -21190,7 +21240,7 @@ function hasTouchedFilesLog({
21190
21240
  workingDirectory,
21191
21241
  missionId
21192
21242
  }) {
21193
- return existsSync24(touchedFilesPath({ workingDirectory, missionId }));
21243
+ return existsSync25(touchedFilesPath({ workingDirectory, missionId }));
21194
21244
  }
21195
21245
  function readTouchedLog({
21196
21246
  workingDirectory,
@@ -21198,7 +21248,7 @@ function readTouchedLog({
21198
21248
  }) {
21199
21249
  try {
21200
21250
  const target = touchedFilesPath({ workingDirectory, missionId });
21201
- if (!existsSync24(target)) return null;
21251
+ if (!existsSync25(target)) return null;
21202
21252
  const raw = JSON.parse(readFileSync19(target, "utf8"));
21203
21253
  const result = /* @__PURE__ */ new Set();
21204
21254
  if (Array.isArray(raw.paths)) {
@@ -21252,7 +21302,7 @@ function readPeerTouchedClaims({
21252
21302
  );
21253
21303
  if (activeMissionIds.size === 0) return [];
21254
21304
  const directory = path28.join(resolveGlobalDataDir(), "vcs-touched");
21255
- if (!existsSync24(directory)) return [];
21305
+ if (!existsSync25(directory)) return [];
21256
21306
  const claims = [];
21257
21307
  for (const name of readdirSync5(directory)) {
21258
21308
  if (!name.endsWith(".json") || name.endsWith(".bash-snapshot.json")) continue;
@@ -21282,7 +21332,7 @@ function readBaselineSnapshot({
21282
21332
  }) {
21283
21333
  try {
21284
21334
  const target = baselineFilePath({ workingDirectory, missionId });
21285
- if (!existsSync24(target)) return /* @__PURE__ */ new Map();
21335
+ if (!existsSync25(target)) return /* @__PURE__ */ new Map();
21286
21336
  const raw = JSON.parse(readFileSync19(target, "utf8"));
21287
21337
  if (Array.isArray(raw.files)) {
21288
21338
  const byPath = /* @__PURE__ */ new Map();
@@ -21378,7 +21428,7 @@ function compileIgnorePattern(rawPattern) {
21378
21428
  function loadIgnoreRules(repoRoot) {
21379
21429
  try {
21380
21430
  const target = path28.join(repoRoot, OVERLORD_IGNORE_FILENAME);
21381
- if (!existsSync24(target)) return [];
21431
+ if (!existsSync25(target)) return [];
21382
21432
  const rules = [];
21383
21433
  for (const rawLine of readFileSync19(target, "utf8").split("\n")) {
21384
21434
  const line = rawLine.replace(/\r$/, "").trim();
@@ -21512,18 +21562,18 @@ import { readFileSync as readFileSync20 } from "node:fs";
21512
21562
  import path29 from "node:path";
21513
21563
  function firstNonEmptyString(value) {
21514
21564
  if (typeof value !== "string") return null;
21515
- const trimmed7 = value.trim();
21516
- return trimmed7 ? trimmed7 : null;
21565
+ const trimmed8 = value.trim();
21566
+ return trimmed8 ? trimmed8 : null;
21517
21567
  }
21518
21568
  function collectCandidates(toolInput) {
21519
21569
  const counts = /* @__PURE__ */ new Map();
21520
21570
  const order = [];
21521
21571
  const bump = (raw, amount) => {
21522
21572
  if (typeof raw !== "string") return;
21523
- const trimmed7 = raw.trim();
21524
- if (!trimmed7) return;
21525
- if (!counts.has(trimmed7)) order.push(trimmed7);
21526
- counts.set(trimmed7, (counts.get(trimmed7) ?? 0) + amount);
21573
+ const trimmed8 = raw.trim();
21574
+ if (!trimmed8) return;
21575
+ if (!counts.has(trimmed8)) order.push(trimmed8);
21576
+ counts.set(trimmed8, (counts.get(trimmed8) ?? 0) + amount);
21527
21577
  };
21528
21578
  bump(toolInput.file_path, 1);
21529
21579
  bump(toolInput.filePath, 1);
@@ -21747,7 +21797,7 @@ var init_resource_observations = __esm({
21747
21797
 
21748
21798
  // src/runner-identity.ts
21749
21799
  import { randomUUID } from "node:crypto";
21750
- import { existsSync as existsSync25, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync12 } from "node:fs";
21800
+ import { existsSync as existsSync26, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync12 } from "node:fs";
21751
21801
  import { hostname as hostname4 } from "node:os";
21752
21802
  import path30 from "node:path";
21753
21803
  function envValue(name) {
@@ -21761,7 +21811,7 @@ function resolveRunnerInstanceId(dataDir = resolveGlobalDataDir()) {
21761
21811
  const pinned = envValue("OVERLORD_RUNNER_INSTANCE_ID");
21762
21812
  if (pinned) return pinned;
21763
21813
  const statePath = runnerInstanceStatePath(dataDir);
21764
- if (existsSync25(statePath)) {
21814
+ if (existsSync26(statePath)) {
21765
21815
  try {
21766
21816
  const parsed = JSON.parse(readFileSync21(statePath, "utf8"));
21767
21817
  if (typeof parsed.runnerInstanceId === "string" && parsed.runnerInstanceId.trim()) {
@@ -21817,7 +21867,7 @@ var init_runner_identity = __esm({
21817
21867
  import { execFile } from "node:child_process";
21818
21868
  import {
21819
21869
  chmodSync as chmodSync5,
21820
- existsSync as existsSync26,
21870
+ existsSync as existsSync27,
21821
21871
  mkdirSync as mkdirSync14,
21822
21872
  readFileSync as readFileSync22,
21823
21873
  rmSync as rmSync6,
@@ -21883,7 +21933,7 @@ function runnerServiceStatePath(dataDir = resolveGlobalDataDir()) {
21883
21933
  }
21884
21934
  function readRunnerServiceState(dataDir = resolveGlobalDataDir()) {
21885
21935
  const filePath = runnerServiceStatePath(dataDir);
21886
- if (!existsSync26(filePath)) return emptyRunnerServiceState();
21936
+ if (!existsSync27(filePath)) return emptyRunnerServiceState();
21887
21937
  try {
21888
21938
  const parsed = JSON.parse(readFileSync22(filePath, "utf8"));
21889
21939
  return { ...emptyRunnerServiceState(), ...parsed };
@@ -21908,7 +21958,7 @@ function applyPollJitter(intervalMs, random = Math.random) {
21908
21958
  function resolveOverlordAppInvocation({
21909
21959
  platform: platform2 = process.platform,
21910
21960
  homedir: homedir2 = os5.homedir(),
21911
- exists = existsSync26
21961
+ exists = existsSync27
21912
21962
  } = {}) {
21913
21963
  if (platform2 !== "darwin") return null;
21914
21964
  const appDirs = [
@@ -22131,10 +22181,10 @@ var init_runner_service = __esm({
22131
22181
  `launchctl still reports ${LAUNCHD_LABEL} as loaded after bootout; left ${this.unitPath()} in place so the service can be repaired with \`ovld runner service restart\`.`
22132
22182
  );
22133
22183
  }
22134
- if (existsSync26(this.unitPath())) rmSync6(this.unitPath());
22184
+ if (existsSync27(this.unitPath())) rmSync6(this.unitPath());
22135
22185
  }
22136
22186
  async status() {
22137
- const installed = existsSync26(this.unitPath());
22187
+ const installed = existsSync27(this.unitPath());
22138
22188
  try {
22139
22189
  const { stdout } = await this.exec(["list"]);
22140
22190
  const line = stdout.split("\n").find((row) => row.includes(LAUNCHD_LABEL));
@@ -22177,14 +22227,14 @@ var init_runner_service = __esm({
22177
22227
  await runCommand("systemctl", ["--user", "disable", this.identifier]);
22178
22228
  } catch {
22179
22229
  }
22180
- if (existsSync26(this.unitPath())) rmSync6(this.unitPath());
22230
+ if (existsSync27(this.unitPath())) rmSync6(this.unitPath());
22181
22231
  try {
22182
22232
  await runCommand("systemctl", ["--user", "daemon-reload"]);
22183
22233
  } catch {
22184
22234
  }
22185
22235
  }
22186
22236
  async status() {
22187
- const installed = existsSync26(this.unitPath());
22237
+ const installed = existsSync27(this.unitPath());
22188
22238
  try {
22189
22239
  const { stdout } = await runCommand("systemctl", ["--user", "is-active", this.identifier]);
22190
22240
  return { installed, running: stdout.trim() === "active" ? "running" : "stopped" };
@@ -22199,9 +22249,9 @@ var init_runner_service = __esm({
22199
22249
  // src/select-prompt.ts
22200
22250
  import { createInterface as createInterface4 } from "node:readline";
22201
22251
  function parseNumberedSelection(answer, count) {
22202
- const trimmed7 = answer.trim();
22203
- if (!/^\d+$/.test(trimmed7)) return null;
22204
- const value = Number.parseInt(trimmed7, 10);
22252
+ const trimmed8 = answer.trim();
22253
+ if (!/^\d+$/.test(trimmed8)) return null;
22254
+ const value = Number.parseInt(trimmed8, 10);
22205
22255
  if (!Number.isInteger(value) || value < 1 || value > count) return null;
22206
22256
  return value - 1;
22207
22257
  }
@@ -22251,7 +22301,7 @@ var init_select_prompt = __esm({
22251
22301
 
22252
22302
  // src/session-key.ts
22253
22303
  import { createHash as createHash10 } from "node:crypto";
22254
- import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync23, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "node:fs";
22304
+ import { existsSync as existsSync28, mkdirSync as mkdirSync15, readFileSync as readFileSync23, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "node:fs";
22255
22305
  import path32 from "node:path";
22256
22306
  function sessionKeyCachePath({
22257
22307
  missionId,
@@ -22266,7 +22316,7 @@ function readCachedSessionKey({
22266
22316
  }) {
22267
22317
  try {
22268
22318
  const filePath = sessionKeyCachePath({ missionId, workingDirectory });
22269
- if (!existsSync27(filePath)) return void 0;
22319
+ if (!existsSync28(filePath)) return void 0;
22270
22320
  const raw = JSON.parse(readFileSync23(filePath, "utf8"));
22271
22321
  return typeof raw.sessionKey === "string" && raw.sessionKey.trim() ? raw.sessionKey.trim() : void 0;
22272
22322
  } catch {
@@ -22279,13 +22329,13 @@ function writeCachedSessionKey({
22279
22329
  sessionKey
22280
22330
  }) {
22281
22331
  try {
22282
- const trimmed7 = sessionKey.trim();
22283
- if (!trimmed7) return;
22332
+ const trimmed8 = sessionKey.trim();
22333
+ if (!trimmed8) return;
22284
22334
  const filePath = sessionKeyCachePath({ missionId, workingDirectory });
22285
22335
  mkdirSync15(path32.dirname(filePath), { recursive: true });
22286
22336
  writeFileSync14(
22287
22337
  filePath,
22288
- JSON.stringify({ sessionKey: trimmed7, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }),
22338
+ JSON.stringify({ sessionKey: trimmed8, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }),
22289
22339
  { mode: 384 }
22290
22340
  );
22291
22341
  } catch {
@@ -22297,7 +22347,7 @@ function clearCachedSessionKey({
22297
22347
  }) {
22298
22348
  try {
22299
22349
  const filePath = sessionKeyCachePath({ missionId, workingDirectory });
22300
- if (existsSync27(filePath)) rmSync7(filePath);
22350
+ if (existsSync28(filePath)) rmSync7(filePath);
22301
22351
  } catch {
22302
22352
  }
22303
22353
  }
@@ -22316,7 +22366,7 @@ __export(commands_exports, {
22316
22366
  runProtocolCommand: () => runProtocolCommand,
22317
22367
  runRunnerOnce: () => runRunnerOnce
22318
22368
  });
22319
- import { existsSync as existsSync28, readFileSync as readFileSync24 } from "node:fs";
22369
+ import { existsSync as existsSync29, readFileSync as readFileSync24 } from "node:fs";
22320
22370
  import os6 from "node:os";
22321
22371
  import path33 from "node:path";
22322
22372
  function resourceAccessModeBody(value) {
@@ -22946,7 +22996,7 @@ async function runProtocolCommand({
22946
22996
  clearCachedSessionKey({ missionId, workingDirectory });
22947
22997
  removeActiveSession({ workingDirectory, missionId });
22948
22998
  clearActiveMissionPointer(workingDirectory);
22949
- const connectorInstallsEditHook = existsSync28(path33.join(os6.homedir(), ".claude")) || existsSync28(
22999
+ const connectorInstallsEditHook = existsSync29(path33.join(os6.homedir(), ".claude")) || existsSync29(
22950
23000
  path33.join(
22951
23001
  os6.homedir(),
22952
23002
  ".cursor",