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 +495 -445
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -278,16 +278,16 @@ function resolveCommandArgs({
|
|
|
278
278
|
return parsed;
|
|
279
279
|
}
|
|
280
280
|
function normalizeVersion(raw) {
|
|
281
|
-
const
|
|
282
|
-
if (!
|
|
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(
|
|
286
|
+
const parsed = JSON.parse(trimmed8);
|
|
287
287
|
if (typeof parsed === "string" && parsed.trim()) return parsed.trim();
|
|
288
288
|
} catch {
|
|
289
289
|
}
|
|
290
|
-
return
|
|
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
|
|
1350
|
-
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(
|
|
1351
|
-
return
|
|
1349
|
+
const trimmed8 = value.trim().replace(/\/+$/, "");
|
|
1350
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed8)) {
|
|
1351
|
+
return trimmed8;
|
|
1352
1352
|
}
|
|
1353
|
-
return `http://${
|
|
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
|
|
2416
|
-
if (
|
|
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 =
|
|
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 (
|
|
2433
|
+
if (trimmed8.startsWith("- ")) {
|
|
2434
2434
|
if (Array.isArray(frame.container)) {
|
|
2435
|
-
frame.container.push(parseScalar(
|
|
2435
|
+
frame.container.push(parseScalar(trimmed8.slice(2)));
|
|
2436
2436
|
}
|
|
2437
2437
|
continue;
|
|
2438
2438
|
}
|
|
2439
|
-
const colon =
|
|
2439
|
+
const colon = trimmed8.indexOf(":");
|
|
2440
2440
|
if (colon < 0 || Array.isArray(frame.container)) continue;
|
|
2441
|
-
const key =
|
|
2442
|
-
const rest =
|
|
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
|
|
2637
|
-
if (!
|
|
2636
|
+
const trimmed8 = existingContent.trimEnd();
|
|
2637
|
+
if (!trimmed8) return `${managedBlock}
|
|
2638
2638
|
`;
|
|
2639
|
-
return `${
|
|
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
|
|
5570
|
-
return
|
|
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
|
|
16339
|
-
if (!
|
|
16338
|
+
const trimmed8 = text.trim();
|
|
16339
|
+
if (!trimmed8)
|
|
16340
16340
|
return null;
|
|
16341
|
-
const eqIndex =
|
|
16342
|
-
if (eqIndex > 0 &&
|
|
16343
|
-
const name =
|
|
16344
|
-
const value =
|
|
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 =
|
|
16348
|
-
if (spaceIndex > 0 &&
|
|
16349
|
-
const name =
|
|
16350
|
-
const value =
|
|
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:
|
|
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
|
|
16505
|
-
if (!
|
|
16504
|
+
const trimmed8 = path34.trim();
|
|
16505
|
+
if (!trimmed8)
|
|
16506
16506
|
return "";
|
|
16507
16507
|
const permission = accessModeToResourcePathPermission({ accessMode, isPrimary });
|
|
16508
|
-
return `${
|
|
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-
|
|
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 =
|
|
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
|
-
...
|
|
16952
|
+
...trimmed4(externalRunId) ? { external_run_id: trimmed4(externalRunId) } : {}
|
|
16661
16953
|
}
|
|
16662
16954
|
};
|
|
16663
|
-
if (
|
|
16664
|
-
display.title =
|
|
16665
|
-
if (
|
|
16666
|
-
display.name =
|
|
16667
|
-
if (
|
|
16668
|
-
display.command_label =
|
|
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 =
|
|
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:
|
|
16696
|
-
state:
|
|
16697
|
-
createdAt:
|
|
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:
|
|
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 =
|
|
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:
|
|
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 (
|
|
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 =
|
|
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 `${
|
|
17060
|
+
return `${trimmed4(executable) ?? "latch"} attach ${providerSessionId}`;
|
|
16769
17061
|
}
|
|
16770
17062
|
function shouldUseLatchProvider({ providerKind, latchSelectable }) {
|
|
16771
|
-
return
|
|
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
|
|
17078
|
+
function trimmed5(value) {
|
|
16787
17079
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
16788
17080
|
}
|
|
16789
17081
|
function parseState(value) {
|
|
16790
|
-
switch (
|
|
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
|
|
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 =
|
|
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:
|
|
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:
|
|
16842
|
-
name:
|
|
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
|
|
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 =
|
|
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 =
|
|
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:
|
|
16878
|
-
viewer:
|
|
17172
|
+
providerSessionId: trimmed5(report.id) ?? sessionId,
|
|
17173
|
+
viewer: trimmed5(report.viewer) ?? viewer,
|
|
16879
17174
|
opened: true,
|
|
16880
|
-
behavior:
|
|
17175
|
+
behavior: trimmed5(report.behavior) ? parseViewerOpenAs(report.behavior) : null
|
|
16881
17176
|
};
|
|
16882
17177
|
}
|
|
16883
17178
|
function stopLatchSession({ executable = "latch", providerSessionId }) {
|
|
16884
|
-
const sessionId =
|
|
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:
|
|
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:
|
|
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
|
|
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 =
|
|
16925
|
-
const sessionId =
|
|
16926
|
-
const at =
|
|
16927
|
-
const 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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
16957
|
-
const 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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
17101
|
-
import
|
|
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 (!
|
|
17104
|
-
|
|
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 =
|
|
17116
|
-
const existing =
|
|
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 =
|
|
17122
|
-
const existing =
|
|
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
|
-
|
|
17427
|
+
writeFileSync8(gitignorePath, `${existing}${separator}${additions.join("\n")}
|
|
17129
17428
|
`);
|
|
17130
17429
|
}
|
|
17131
17430
|
function resolveGitRoot(directoryPath) {
|
|
17132
17431
|
try {
|
|
17133
|
-
return
|
|
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 (!
|
|
17489
|
+
if (!existsSync17(projectJsonPath))
|
|
17191
17490
|
return null;
|
|
17192
|
-
const parsed = JSON.parse(
|
|
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 =
|
|
17260
|
-
|
|
17261
|
-
|
|
17262
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
17327
|
-
import
|
|
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
|
|
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 =
|
|
17649
|
+
let parent = path17.posix.dirname(filePath);
|
|
17351
17650
|
while (parent !== "." && parent !== "/") {
|
|
17352
17651
|
paths.add(parent);
|
|
17353
|
-
parent =
|
|
17652
|
+
parent = path17.posix.dirname(parent);
|
|
17354
17653
|
}
|
|
17355
17654
|
}
|
|
17356
17655
|
function toEntry(entryPath, type) {
|
|
17357
|
-
const parentPath =
|
|
17656
|
+
const parentPath = path17.posix.dirname(entryPath);
|
|
17358
17657
|
return {
|
|
17359
17658
|
path: entryPath,
|
|
17360
|
-
name:
|
|
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 =
|
|
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:
|
|
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
|
|
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 =
|
|
17684
|
-
const bin =
|
|
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 =
|
|
17720
|
-
const id =
|
|
17721
|
-
const selected =
|
|
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 =
|
|
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
|
|
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 !
|
|
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 || !
|
|
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
|
|
17975
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
17926
17976
|
function integrateBranch(input) {
|
|
17927
17977
|
const { branchName, baseBranch, worktreePath, primaryRepoPath } = input;
|
|
17928
|
-
if (!
|
|
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
|
|
18003
|
-
if (!
|
|
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 (!
|
|
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",
|
|
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 (
|
|
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 =
|
|
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
|
|
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 (!
|
|
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
|
|
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 =
|
|
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
|
|
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 (
|
|
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
|
|
19079
|
+
const trimmed8 = projectRef.trim();
|
|
19030
19080
|
try {
|
|
19031
|
-
return await backend.get(`/api/projects/${encodeURIComponent(
|
|
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 ===
|
|
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: ${
|
|
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
|
|
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 (!
|
|
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
|
|
20203
|
-
resolve(
|
|
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
|
|
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 (!
|
|
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
|
|
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 (!
|
|
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 (
|
|
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 (
|
|
21140
|
+
if (existsSync25(target)) rmSync5(target);
|
|
21091
21141
|
} catch {
|
|
21092
21142
|
}
|
|
21093
21143
|
}
|
|
21094
21144
|
function truncateNoteText(value, max = 500) {
|
|
21095
|
-
const
|
|
21096
|
-
if (!
|
|
21097
|
-
return
|
|
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 (!
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
|
21516
|
-
return
|
|
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
|
|
21524
|
-
if (!
|
|
21525
|
-
if (!counts.has(
|
|
21526
|
-
counts.set(
|
|
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
|
|
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 (
|
|
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
|
|
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 (!
|
|
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 =
|
|
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 (
|
|
22184
|
+
if (existsSync27(this.unitPath())) rmSync6(this.unitPath());
|
|
22135
22185
|
}
|
|
22136
22186
|
async status() {
|
|
22137
|
-
const installed =
|
|
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 (
|
|
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 =
|
|
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
|
|
22203
|
-
if (!/^\d+$/.test(
|
|
22204
|
-
const value = Number.parseInt(
|
|
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
|
|
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 (!
|
|
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
|
|
22283
|
-
if (!
|
|
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:
|
|
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 (
|
|
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
|
|
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 =
|
|
22999
|
+
const connectorInstallsEditHook = existsSync29(path33.join(os6.homedir(), ".claude")) || existsSync29(
|
|
22950
23000
|
path33.join(
|
|
22951
23001
|
os6.homedir(),
|
|
22952
23002
|
".cursor",
|