overlord-cli 0.2608131824.0 → 0.2608132027.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
@@ -63,6 +63,10 @@ var init_redact_secrets = __esm({
63
63
  });
64
64
 
65
65
  // src/errors.ts
66
+ function isUnlinkableExecutionRequestError(error) {
67
+ const message = error instanceof Error ? error.message : String(error);
68
+ return message.includes("invalid_execution_request_transition");
69
+ }
66
70
  function formatCliError(error) {
67
71
  if (error instanceof CliError) {
68
72
  return redactSecrets(error.message);
@@ -16527,6 +16531,31 @@ var init_dist2 = __esm({
16527
16531
  }
16528
16532
  });
16529
16533
 
16534
+ // ../packages/core/dist/service/latch-environment.js
16535
+ function isUtf8Locale(value) {
16536
+ return typeof value === "string" && UTF8_LOCALE_PATTERN.test(value);
16537
+ }
16538
+ function latchChildEnvironment({ baseEnv = process.env, platform: platform2 = process.platform } = {}) {
16539
+ const effective = baseEnv.LC_ALL ?? baseEnv.LC_CTYPE ?? baseEnv.LANG;
16540
+ if (isUtf8Locale(effective))
16541
+ return { ...baseEnv };
16542
+ const env = {
16543
+ ...baseEnv,
16544
+ // macOS ships the bare `UTF-8` locale; glibc systems ship `C.UTF-8`.
16545
+ LC_CTYPE: platform2 === "darwin" ? "UTF-8" : "C.UTF-8"
16546
+ };
16547
+ if (env.LC_ALL !== void 0 && !isUtf8Locale(env.LC_ALL))
16548
+ delete env.LC_ALL;
16549
+ return env;
16550
+ }
16551
+ var UTF8_LOCALE_PATTERN;
16552
+ var init_latch_environment = __esm({
16553
+ "../packages/core/dist/service/latch-environment.js"() {
16554
+ "use strict";
16555
+ UTF8_LOCALE_PATTERN = /utf-?8/i;
16556
+ }
16557
+ });
16558
+
16530
16559
  // ../packages/core/dist/service/latch-launch.js
16531
16560
  function trimmed(value) {
16532
16561
  return typeof value === "string" && value.trim() ? value.trim() : null;
@@ -16553,7 +16582,7 @@ function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.tr
16553
16582
  return {
16554
16583
  format_version: LATCH_MANIFEST_FORMAT_VERSION,
16555
16584
  launch: {
16556
- argv: [shellPath, "-lc", commandString],
16585
+ argv: [shellPath, "-ilc", commandString],
16557
16586
  cwd,
16558
16587
  env: cleanedEnv,
16559
16588
  inherit_env: true,
@@ -16658,7 +16687,8 @@ function runLatchJson({ executable, args }) {
16658
16687
  encoding: "utf8",
16659
16688
  shell: false,
16660
16689
  timeout: 1e4,
16661
- maxBuffer: 1024 * 1024
16690
+ maxBuffer: 1024 * 1024,
16691
+ env: latchChildEnvironment()
16662
16692
  });
16663
16693
  if (result.error) {
16664
16694
  throw new LatchSessionCommandError(result.error.message);
@@ -16738,6 +16768,7 @@ var LatchSessionCommandError;
16738
16768
  var init_latch_session = __esm({
16739
16769
  "../packages/core/dist/service/latch-session.js"() {
16740
16770
  "use strict";
16771
+ init_latch_environment();
16741
16772
  init_latch_launch();
16742
16773
  LatchSessionCommandError = class extends Error {
16743
16774
  constructor(message) {
@@ -16838,7 +16869,8 @@ async function collectLatchEvents({ executable = "latch", providerSessionId, fro
16838
16869
  const bin = trimmed3(executable) ?? "latch";
16839
16870
  return new Promise((resolve, reject) => {
16840
16871
  const child = spawn3(bin, ["events", sessionId, "--json", "--from", String(fromCursor)], {
16841
- stdio: ["ignore", "pipe", "pipe"]
16872
+ stdio: ["ignore", "pipe", "pipe"],
16873
+ env: latchChildEnvironment()
16842
16874
  });
16843
16875
  let stdout = "";
16844
16876
  let stderr = "";
@@ -16894,7 +16926,7 @@ async function collectLatchEvents({ executable = "latch", providerSessionId, fro
16894
16926
  finish({ ended: true, error: new LatchSessionCommandError(detail) });
16895
16927
  return;
16896
16928
  }
16897
- finish({ ended: signal == null && (code === 0 || code === null) });
16929
+ finish({ ended: signal === null && (code === 0 || code === null) });
16898
16930
  });
16899
16931
  });
16900
16932
  }
@@ -16902,6 +16934,7 @@ var HARNESS_EVENT_TYPES;
16902
16934
  var init_latch_events = __esm({
16903
16935
  "../packages/core/dist/service/latch-events.js"() {
16904
16936
  "use strict";
16937
+ init_latch_environment();
16905
16938
  init_latch_session();
16906
16939
  HARNESS_EVENT_TYPES = /* @__PURE__ */ new Set([
16907
16940
  "user_message",
@@ -17547,6 +17580,7 @@ var SUPPORTED_LATCH_PROTOCOL_VERSION, REQUIRED_LATCH_CAPABILITIES, LATCH_STANDAL
17547
17580
  var init_latch_discovery = __esm({
17548
17581
  "../packages/core/dist/service/latch-discovery.js"() {
17549
17582
  "use strict";
17583
+ init_latch_environment();
17550
17584
  init_terminal_profile_types2();
17551
17585
  SUPPORTED_LATCH_PROTOCOL_VERSION = 1;
17552
17586
  REQUIRED_LATCH_CAPABILITIES = ["create"];
@@ -17557,7 +17591,8 @@ var init_latch_discovery = __esm({
17557
17591
  const stdout = execFileSync3(executable, argv, {
17558
17592
  encoding: "utf8",
17559
17593
  stdio: ["ignore", "pipe", "pipe"],
17560
- timeout: 5e3
17594
+ timeout: 5e3,
17595
+ env: latchChildEnvironment()
17561
17596
  });
17562
17597
  return { status: 0, stdout: String(stdout), stderr: "" };
17563
17598
  } catch (error) {
@@ -17594,7 +17629,8 @@ function probeLatchInteractionCapabilities({ executable = "latch", providerSessi
17594
17629
  const help = spawnSync3(bin, ["send", "--help"], {
17595
17630
  encoding: "utf8",
17596
17631
  shell: false,
17597
- timeout: 5e3
17632
+ timeout: 5e3,
17633
+ env: latchChildEnvironment()
17598
17634
  });
17599
17635
  if (help.error || help.status !== 0) {
17600
17636
  const detail = (help.stderr || help.stdout || help.error?.message || "latch send is unavailable").trim().slice(0, 200);
@@ -17637,7 +17673,8 @@ function resolveLatchInput({ executable = "latch", providerSessionId, requestId,
17637
17673
  encoding: "utf8",
17638
17674
  shell: false,
17639
17675
  timeout: 1e4,
17640
- maxBuffer: 1024 * 1024
17676
+ maxBuffer: 1024 * 1024,
17677
+ env: latchChildEnvironment()
17641
17678
  });
17642
17679
  if (result.error)
17643
17680
  throw new LatchSessionCommandError(result.error.message);
@@ -17655,6 +17692,7 @@ function resolveLatchInput({ executable = "latch", providerSessionId, requestId,
17655
17692
  var init_latch_send = __esm({
17656
17693
  "../packages/core/dist/service/latch-send.js"() {
17657
17694
  "use strict";
17695
+ init_latch_environment();
17658
17696
  init_latch_session();
17659
17697
  }
17660
17698
  });
@@ -19089,7 +19127,7 @@ function spawnLatchJson({
19089
19127
  const result = spawnSync4(executable, args, {
19090
19128
  encoding: "utf8",
19091
19129
  input: stdin,
19092
- env: process.env,
19130
+ env: latchChildEnvironment(),
19093
19131
  maxBuffer: 2 * 1024 * 1024
19094
19132
  });
19095
19133
  return {
@@ -19176,6 +19214,7 @@ function openLatchViewer({
19176
19214
  var init_latch_launch2 = __esm({
19177
19215
  "src/latch-launch.ts"() {
19178
19216
  "use strict";
19217
+ init_latch_environment();
19179
19218
  init_latch_launch();
19180
19219
  init_terminal_profile_types2();
19181
19220
  }
@@ -19884,7 +19923,7 @@ async function launchAgent({
19884
19923
  }) : null;
19885
19924
  if (existingProviderSession && plan.latchCommandString) {
19886
19925
  const shell = process.env.SHELL?.trim() || "/bin/bash";
19887
- const result2 = spawnSync5(shell, ["-lc", plan.latchCommandString], {
19926
+ const result2 = spawnSync5(shell, ["-ilc", plan.latchCommandString], {
19888
19927
  cwd: options.workingDirectory,
19889
19928
  env,
19890
19929
  stdio: "inherit"
@@ -19894,7 +19933,7 @@ async function launchAgent({
19894
19933
  ...plan,
19895
19934
  execution: {
19896
19935
  command: shell,
19897
- args: ["-lc", plan.latchCommandString],
19936
+ args: ["-ilc", plan.latchCommandString],
19898
19937
  useShell: false,
19899
19938
  terminal: null,
19900
19939
  display: `Latch session ${existingProviderSession.providerSessionId} (inline) \u203A ${plan.latchCommandString}`
@@ -21400,6 +21439,11 @@ var init_vcs = __esm({
21400
21439
  // src/record-touched.ts
21401
21440
  import { readFileSync as readFileSync20 } from "node:fs";
21402
21441
  import path29 from "node:path";
21442
+ function firstNonEmptyString(value) {
21443
+ if (typeof value !== "string") return null;
21444
+ const trimmed7 = value.trim();
21445
+ return trimmed7 ? trimmed7 : null;
21446
+ }
21403
21447
  function collectCandidates(toolInput) {
21404
21448
  const counts = /* @__PURE__ */ new Map();
21405
21449
  const order = [];
@@ -21411,22 +21455,43 @@ function collectCandidates(toolInput) {
21411
21455
  counts.set(trimmed7, (counts.get(trimmed7) ?? 0) + amount);
21412
21456
  };
21413
21457
  bump(toolInput.file_path, 1);
21458
+ bump(toolInput.filePath, 1);
21459
+ bump(toolInput.path, 1);
21414
21460
  bump(toolInput.notebook_path, 1);
21415
21461
  const edits = toolInput.edits;
21416
21462
  if (Array.isArray(edits)) {
21417
- const topLevelPath = toolInput.file_path;
21418
- if (typeof topLevelPath === "string" && topLevelPath.trim()) {
21419
- counts.set(topLevelPath.trim(), (counts.get(topLevelPath.trim()) ?? 0) - 1);
21463
+ const topLevelPath = firstNonEmptyString(toolInput.file_path) ?? firstNonEmptyString(toolInput.filePath) ?? firstNonEmptyString(toolInput.path);
21464
+ if (topLevelPath) {
21465
+ counts.set(topLevelPath, (counts.get(topLevelPath) ?? 0) - 1);
21420
21466
  }
21421
21467
  for (const edit of edits) {
21422
21468
  if (edit && typeof edit === "object") {
21423
- const value = edit.file_path ?? topLevelPath;
21469
+ const record = edit;
21470
+ const value = record.file_path ?? record.filePath ?? record.path ?? topLevelPath;
21424
21471
  bump(value, 1);
21425
21472
  }
21426
21473
  }
21427
21474
  }
21428
21475
  return order.map((filePath) => ({ filePath, editCount: Math.max(counts.get(filePath) ?? 1, 1) }));
21429
21476
  }
21477
+ function resolveHookWorkingDirectory({
21478
+ payload,
21479
+ fallbackCwd,
21480
+ env
21481
+ }) {
21482
+ const fromCwd = firstNonEmptyString(payload.cwd);
21483
+ if (fromCwd) return path29.resolve(fromCwd);
21484
+ const roots = payload.workspace_roots;
21485
+ if (Array.isArray(roots)) {
21486
+ const fromRoots = firstNonEmptyString(roots[0]);
21487
+ if (fromRoots) return path29.resolve(fromRoots);
21488
+ }
21489
+ for (const key of PROJECT_DIR_ENV_KEYS) {
21490
+ const fromEnv = firstNonEmptyString(env[key]);
21491
+ if (fromEnv) return path29.resolve(fromEnv);
21492
+ }
21493
+ return path29.resolve(fallbackCwd);
21494
+ }
21430
21495
  function compact(value, limit = 500) {
21431
21496
  if (typeof value !== "string") return null;
21432
21497
  const text = value.split(/\s+/).filter(Boolean).join(" ");
@@ -21486,7 +21551,8 @@ function recentAssistantContext(transcriptPath) {
21486
21551
  function recordTouchedFromPayload({
21487
21552
  rawPayload,
21488
21553
  missionOverride,
21489
- fallbackCwd
21554
+ fallbackCwd,
21555
+ env = process.env
21490
21556
  }) {
21491
21557
  let payload;
21492
21558
  try {
@@ -21497,8 +21563,7 @@ function recordTouchedFromPayload({
21497
21563
  const toolInputRaw = payload.tool_input;
21498
21564
  const toolInput = toolInputRaw && typeof toolInputRaw === "object" ? toolInputRaw : {};
21499
21565
  const toolName = typeof payload.tool_name === "string" && payload.tool_name.trim() ? payload.tool_name.trim() : "file edit";
21500
- const cwd = typeof payload.cwd === "string" && payload.cwd.trim() ? payload.cwd.trim() : fallbackCwd;
21501
- const workingDirectory = path29.resolve(cwd);
21566
+ const workingDirectory = resolveHookWorkingDirectory({ payload, fallbackCwd, env });
21502
21567
  const trimmedOverride = missionOverride?.trim();
21503
21568
  let missionId;
21504
21569
  let ambiguous = false;
@@ -21507,7 +21572,10 @@ function recordTouchedFromPayload({
21507
21572
  } else {
21508
21573
  const resolved = resolveActiveMissionForCwd(workingDirectory);
21509
21574
  if (!resolved) {
21510
- return { recorded: false, reason: "no active session manifest entry for this cwd" };
21575
+ return {
21576
+ recorded: false,
21577
+ reason: `no active session manifest entry for this cwd (${workingDirectory})`
21578
+ };
21511
21579
  }
21512
21580
  missionId = resolved.missionId;
21513
21581
  ambiguous = resolved.ambiguous;
@@ -21538,11 +21606,17 @@ function recordTouchedFromPayload({
21538
21606
  });
21539
21607
  return { recorded: true, missionId, ambiguous, files: candidates.length };
21540
21608
  }
21609
+ var PROJECT_DIR_ENV_KEYS;
21541
21610
  var init_record_touched = __esm({
21542
21611
  "src/record-touched.ts"() {
21543
21612
  "use strict";
21544
21613
  init_vcs();
21545
21614
  init_vcs_sessions();
21615
+ PROJECT_DIR_ENV_KEYS = [
21616
+ "CURSOR_PROJECT_DIR",
21617
+ "CLAUDE_PROJECT_DIR",
21618
+ "CLAUDE_PROJECT_ROOT"
21619
+ ];
21546
21620
  }
21547
21621
  });
21548
21622
 
@@ -22711,10 +22785,24 @@ async function runProtocolCommand({
22711
22785
  workingDirectory
22712
22786
  })
22713
22787
  };
22714
- const result = await runtime.backend.post({
22715
- path: `/api/protocol/${encodeURIComponent(subcommand)}`,
22716
- body: protocolBody
22717
- });
22788
+ const protocolPath = `/api/protocol/${encodeURIComponent(subcommand)}`;
22789
+ let result;
22790
+ try {
22791
+ result = await runtime.backend.post({
22792
+ path: protocolPath,
22793
+ body: protocolBody
22794
+ });
22795
+ } catch (error) {
22796
+ if (subcommand === "attach" && typeof flags["--execution-request-id"] === "string" && isUnlinkableExecutionRequestError(error)) {
22797
+ delete flags["--execution-request-id"];
22798
+ result = await runtime.backend.post({
22799
+ path: protocolPath,
22800
+ body: { ...protocolBody, flags }
22801
+ });
22802
+ } else {
22803
+ throw error;
22804
+ }
22805
+ }
22718
22806
  if ((subcommand === "attach" || subcommand === "resume-follow-up") && missionId) {
22719
22807
  writeBaseline({
22720
22808
  workingDirectory,
@@ -22768,7 +22856,7 @@ async function runProtocolCommand({
22768
22856
  )
22769
22857
  );
22770
22858
  if (connectorInstallsEditHook && !hasTouchedFilesLog({ workingDirectory, missionId }) && readChangedFiles(workingDirectory).length > 0) {
22771
- const warning = `[overlord] warning: no touched-files log found at deliver for mission ${missionId} in ${workingDirectory}, even though this connector installs a PostToolUse edit hook. Deliver is falling back to baseline-only attribution, which can misattribute concurrent sessions' edits. Check ~/.ovld/logs/post-tool-use-hook.log for why the hook did not record any touched files.`;
22859
+ const warning = `[overlord] warning: no touched-files log found at deliver for mission ${missionId} in ${workingDirectory}, even though this connector installs a PostToolUse edit hook. Deliver is falling back to baseline-only attribution, which can misattribute concurrent sessions' edits. Check ~/.ovld/logs/cursor-post-tool-use-hook.log and ~/.ovld/logs/post-tool-use-hook.log for why the hook did not record any touched files.`;
22772
22860
  console.error(warning);
22773
22861
  const sessionKeyForAlert = typeof flags["--session-key"] === "string" ? flags["--session-key"] : void 0;
22774
22862
  if (sessionKeyForAlert) {