overlord-cli 0.2608120914.0 → 0.2608121828.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 +1228 -372
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -262,16 +262,16 @@ function resolveCommandArgs({
|
|
|
262
262
|
return parsed;
|
|
263
263
|
}
|
|
264
264
|
function normalizeVersion(raw) {
|
|
265
|
-
const
|
|
266
|
-
if (!
|
|
265
|
+
const trimmed5 = raw.trim();
|
|
266
|
+
if (!trimmed5) {
|
|
267
267
|
throw new CliError({ message: "Received an empty version from npm." });
|
|
268
268
|
}
|
|
269
269
|
try {
|
|
270
|
-
const parsed = JSON.parse(
|
|
270
|
+
const parsed = JSON.parse(trimmed5);
|
|
271
271
|
if (typeof parsed === "string" && parsed.trim()) return parsed.trim();
|
|
272
272
|
} catch {
|
|
273
273
|
}
|
|
274
|
-
return
|
|
274
|
+
return trimmed5.replace(/^"+|"+$/g, "");
|
|
275
275
|
}
|
|
276
276
|
function compareVersions(left, right) {
|
|
277
277
|
const leftParts = left.split(".").map((part) => Number.parseInt(part, 10));
|
|
@@ -1330,11 +1330,11 @@ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, wr
|
|
|
1330
1330
|
import os from "node:os";
|
|
1331
1331
|
import path3 from "node:path";
|
|
1332
1332
|
function normalizeBackendUrl(value) {
|
|
1333
|
-
const
|
|
1334
|
-
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(
|
|
1335
|
-
return
|
|
1333
|
+
const trimmed5 = value.trim().replace(/\/+$/, "");
|
|
1334
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed5)) {
|
|
1335
|
+
return trimmed5;
|
|
1336
1336
|
}
|
|
1337
|
-
return `http://${
|
|
1337
|
+
return `http://${trimmed5}`;
|
|
1338
1338
|
}
|
|
1339
1339
|
function isLoopbackBackendUrl(backendUrl) {
|
|
1340
1340
|
try {
|
|
@@ -2396,12 +2396,12 @@ function parseConnectorManifestYaml(text) {
|
|
|
2396
2396
|
};
|
|
2397
2397
|
for (const rawLine of text.split("\n")) {
|
|
2398
2398
|
const line = rawLine.replace(/\r$/, "");
|
|
2399
|
-
const
|
|
2400
|
-
if (
|
|
2399
|
+
const trimmed5 = line.trim();
|
|
2400
|
+
if (trimmed5 === "" || trimmed5.startsWith("#")) continue;
|
|
2401
2401
|
const indent = line.length - line.trimStart().length;
|
|
2402
2402
|
if (pending) {
|
|
2403
2403
|
if (indent > pending.indent) {
|
|
2404
|
-
const container =
|
|
2404
|
+
const container = trimmed5.startsWith("- ") ? [] : {};
|
|
2405
2405
|
pending.parent[pending.key] = container;
|
|
2406
2406
|
stack.push({ indent, container });
|
|
2407
2407
|
pending = null;
|
|
@@ -2414,16 +2414,16 @@ function parseConnectorManifestYaml(text) {
|
|
|
2414
2414
|
stack.pop();
|
|
2415
2415
|
}
|
|
2416
2416
|
const frame = stack[stack.length - 1];
|
|
2417
|
-
if (
|
|
2417
|
+
if (trimmed5.startsWith("- ")) {
|
|
2418
2418
|
if (Array.isArray(frame.container)) {
|
|
2419
|
-
frame.container.push(parseScalar(
|
|
2419
|
+
frame.container.push(parseScalar(trimmed5.slice(2)));
|
|
2420
2420
|
}
|
|
2421
2421
|
continue;
|
|
2422
2422
|
}
|
|
2423
|
-
const colon =
|
|
2423
|
+
const colon = trimmed5.indexOf(":");
|
|
2424
2424
|
if (colon < 0 || Array.isArray(frame.container)) continue;
|
|
2425
|
-
const key =
|
|
2426
|
-
const rest =
|
|
2425
|
+
const key = trimmed5.slice(0, colon).trim();
|
|
2426
|
+
const rest = trimmed5.slice(colon + 1).trim();
|
|
2427
2427
|
if (rest === "") {
|
|
2428
2428
|
pending = { parent: frame.container, key, indent };
|
|
2429
2429
|
} else {
|
|
@@ -2645,10 +2645,10 @@ ${managedBlock}
|
|
|
2645
2645
|
|
|
2646
2646
|
${after}`;
|
|
2647
2647
|
}
|
|
2648
|
-
const
|
|
2649
|
-
if (!
|
|
2648
|
+
const trimmed5 = existingContent.trimEnd();
|
|
2649
|
+
if (!trimmed5) return `${managedBlock}
|
|
2650
2650
|
`;
|
|
2651
|
-
return `${
|
|
2651
|
+
return `${trimmed5}
|
|
2652
2652
|
|
|
2653
2653
|
${managedBlock}
|
|
2654
2654
|
`;
|
|
@@ -3158,12 +3158,12 @@ function createBackendClient() {
|
|
|
3158
3158
|
const clientDevice = clientDeviceIdentity();
|
|
3159
3159
|
async function request({
|
|
3160
3160
|
method,
|
|
3161
|
-
path:
|
|
3161
|
+
path: path34,
|
|
3162
3162
|
body,
|
|
3163
3163
|
extraHeaders,
|
|
3164
3164
|
rawBody
|
|
3165
3165
|
}) {
|
|
3166
|
-
const url = `${baseUrl}${
|
|
3166
|
+
const url = `${baseUrl}${path34.startsWith("/") ? path34 : `/${path34}`}`;
|
|
3167
3167
|
const auth = resolveAuthHeaders({ baseUrl });
|
|
3168
3168
|
let response;
|
|
3169
3169
|
try {
|
|
@@ -3190,14 +3190,14 @@ Start the Desktop/local backend or run \`ovld config set cloud <url>\`.
|
|
|
3190
3190
|
const payload = await readResponseJson2(response);
|
|
3191
3191
|
if (!response.ok) {
|
|
3192
3192
|
if (response.status === 401 && auth.headers.Authorization) {
|
|
3193
|
-
const detail = errorMessageFromJson2(payload) ?? `Backend request failed: ${method} ${
|
|
3193
|
+
const detail = errorMessageFromJson2(payload) ?? `Backend request failed: ${method} ${path34} (${response.status})`;
|
|
3194
3194
|
throw new CliError({
|
|
3195
3195
|
message: `${detail}
|
|
3196
3196
|
` + (auth.fromStored ? "Your saved credentials were rejected. Run `ovld auth login` to sign in again." : "Run `ovld auth login` or refresh your USER_TOKEN environment variable.")
|
|
3197
3197
|
});
|
|
3198
3198
|
}
|
|
3199
3199
|
throw new CliError({
|
|
3200
|
-
message: errorMessageFromJson2(payload) ?? `Backend request failed: ${method} ${
|
|
3200
|
+
message: errorMessageFromJson2(payload) ?? `Backend request failed: ${method} ${path34} (${response.status})`
|
|
3201
3201
|
});
|
|
3202
3202
|
}
|
|
3203
3203
|
return payload;
|
|
@@ -3205,13 +3205,13 @@ Start the Desktop/local backend or run \`ovld config set cloud <url>\`.
|
|
|
3205
3205
|
return {
|
|
3206
3206
|
baseUrl,
|
|
3207
3207
|
health: () => request({ method: "GET", path: "/api/health" }),
|
|
3208
|
-
get: (
|
|
3209
|
-
post: ({ path:
|
|
3210
|
-
patch: ({ path:
|
|
3211
|
-
delete: (
|
|
3212
|
-
postRaw: ({ path:
|
|
3208
|
+
get: (path34) => request({ method: "GET", path: path34 }),
|
|
3209
|
+
post: ({ path: path34, body }) => request({ method: "POST", path: path34, body }),
|
|
3210
|
+
patch: ({ path: path34, body }) => request({ method: "PATCH", path: path34, body }),
|
|
3211
|
+
delete: (path34) => request({ method: "DELETE", path: path34 }),
|
|
3212
|
+
postRaw: ({ path: path34, body, contentType, filename }) => request({
|
|
3213
3213
|
method: "POST",
|
|
3214
|
-
path:
|
|
3214
|
+
path: path34,
|
|
3215
3215
|
rawBody: body,
|
|
3216
3216
|
extraHeaders: {
|
|
3217
3217
|
"Content-Type": contentType || "application/octet-stream",
|
|
@@ -5574,8 +5574,8 @@ function resolveNativeSessionId({
|
|
|
5574
5574
|
env = process.env
|
|
5575
5575
|
}) {
|
|
5576
5576
|
if (explicit !== void 0) {
|
|
5577
|
-
const
|
|
5578
|
-
return
|
|
5577
|
+
const trimmed5 = explicit.trim();
|
|
5578
|
+
return trimmed5 === "null" ? null : trimmed5 || void 0;
|
|
5579
5579
|
}
|
|
5580
5580
|
const normalizedAgent = agent.toLowerCase();
|
|
5581
5581
|
if (normalizedAgent === "codex") {
|
|
@@ -6443,11 +6443,11 @@ function createChannelClient({
|
|
|
6443
6443
|
token
|
|
6444
6444
|
}) {
|
|
6445
6445
|
const root = `${baseUrl.replace(/\/+$/, "")}/api/agent-session-channels/v1`;
|
|
6446
|
-
async function request(method,
|
|
6446
|
+
async function request(method, path34, body, timeoutMs) {
|
|
6447
6447
|
const controller = new AbortController();
|
|
6448
6448
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
6449
6449
|
try {
|
|
6450
|
-
const response = await fetch(`${root}${
|
|
6450
|
+
const response = await fetch(`${root}${path34}`, {
|
|
6451
6451
|
method,
|
|
6452
6452
|
// The credential travels here and only here: an Authorization header on a request the
|
|
6453
6453
|
// CLI itself constructs. Not in the URL, which lands in access logs; not in the body,
|
|
@@ -6473,8 +6473,8 @@ function createChannelClient({
|
|
|
6473
6473
|
}
|
|
6474
6474
|
}
|
|
6475
6475
|
return {
|
|
6476
|
-
post: (
|
|
6477
|
-
get: (
|
|
6476
|
+
post: (path34, body, options) => request("POST", path34, body ?? {}, options?.timeoutMs ?? DEFAULT_TIMEOUT_MS),
|
|
6477
|
+
get: (path34, options) => request("GET", path34, void 0, options?.timeoutMs ?? DEFAULT_TIMEOUT_MS)
|
|
6478
6478
|
};
|
|
6479
6479
|
}
|
|
6480
6480
|
var DEFAULT_TIMEOUT_MS;
|
|
@@ -6573,9 +6573,9 @@ function reduceUrl(rawUrl) {
|
|
|
6573
6573
|
try {
|
|
6574
6574
|
const url = new URL(raw);
|
|
6575
6575
|
const hadQuery = url.search !== "" || url.hash !== "";
|
|
6576
|
-
const
|
|
6576
|
+
const path34 = url.pathname === "/" ? "" : url.pathname;
|
|
6577
6577
|
return {
|
|
6578
|
-
display: safeText(`${url.protocol}//${url.host}${
|
|
6578
|
+
display: safeText(`${url.protocol}//${url.host}${path34}`).text,
|
|
6579
6579
|
host: url.host || null,
|
|
6580
6580
|
scheme: url.protocol.replace(/:$/, ""),
|
|
6581
6581
|
hadQuery
|
|
@@ -6740,17 +6740,17 @@ var init_mcp = __esm({
|
|
|
6740
6740
|
function describeRead({ input, projectRoot }) {
|
|
6741
6741
|
const record = input && typeof input === "object" ? input : {};
|
|
6742
6742
|
const raw = typeof record.file_path === "string" && record.file_path || typeof record.filePath === "string" && record.filePath || typeof record.path === "string" && record.path || typeof record.notebook_path === "string" && record.notebook_path || null;
|
|
6743
|
-
const
|
|
6743
|
+
const path34 = reducePath(raw, projectRoot);
|
|
6744
6744
|
const markers = [
|
|
6745
|
-
|
|
6746
|
-
|
|
6745
|
+
path34?.outsideProject && "outside-project-directory",
|
|
6746
|
+
path34?.nonAscii && "non-ascii-path"
|
|
6747
6747
|
];
|
|
6748
|
-
if (
|
|
6748
|
+
if (path34 && /(^|\/)(\.env|\.npmrc|\.netrc|id_rsa|id_ed25519|credentials)(\.|$)/.test(path34.display)) {
|
|
6749
6749
|
markers.push("secret-adjacent");
|
|
6750
6750
|
}
|
|
6751
6751
|
return {
|
|
6752
6752
|
action: "Read a file",
|
|
6753
|
-
subject:
|
|
6753
|
+
subject: path34?.display ?? null,
|
|
6754
6754
|
detail: null,
|
|
6755
6755
|
riskMarkers: normalizeMarkers(markers)
|
|
6756
6756
|
};
|
|
@@ -6892,21 +6892,21 @@ function isOverwrite(record) {
|
|
|
6892
6892
|
}
|
|
6893
6893
|
function describeWrite({ input, projectRoot }) {
|
|
6894
6894
|
const record = input && typeof input === "object" ? input : {};
|
|
6895
|
-
const
|
|
6895
|
+
const path34 = reducePath(readPath(record), projectRoot);
|
|
6896
6896
|
const overwrite = isOverwrite(record);
|
|
6897
6897
|
const bytes = byteLength(readContent(record));
|
|
6898
6898
|
const markers = [
|
|
6899
6899
|
overwrite && "overwrites-existing",
|
|
6900
|
-
|
|
6901
|
-
|
|
6900
|
+
path34?.outsideProject && "outside-project-directory",
|
|
6901
|
+
path34?.nonAscii && "non-ascii-path"
|
|
6902
6902
|
];
|
|
6903
|
-
if (
|
|
6903
|
+
if (path34 && /(^|\/)(\.env|\.npmrc|\.netrc|id_rsa|id_ed25519|credentials)(\.|$)/.test(path34.display)) {
|
|
6904
6904
|
markers.push("secret-adjacent");
|
|
6905
6905
|
}
|
|
6906
6906
|
const detail = bytes === null ? overwrite ? "replacing existing text" : null : `${bytes} byte${bytes === 1 ? "" : "s"}${overwrite ? ", replacing existing text" : ""}`;
|
|
6907
6907
|
return {
|
|
6908
6908
|
action: overwrite ? "Overwrite a file" : "Write a file",
|
|
6909
|
-
subject:
|
|
6909
|
+
subject: path34?.display ?? null,
|
|
6910
6910
|
detail,
|
|
6911
6911
|
riskMarkers: normalizeMarkers(markers)
|
|
6912
6912
|
};
|
|
@@ -7107,8 +7107,8 @@ function readPath2(source, dotted) {
|
|
|
7107
7107
|
return current;
|
|
7108
7108
|
}
|
|
7109
7109
|
function firstString(source, paths) {
|
|
7110
|
-
for (const
|
|
7111
|
-
const value = readPath2(source,
|
|
7110
|
+
for (const path34 of paths ?? []) {
|
|
7111
|
+
const value = readPath2(source, path34);
|
|
7112
7112
|
if (typeof value === "string" && value.trim() !== "")
|
|
7113
7113
|
return value.trim();
|
|
7114
7114
|
}
|
|
@@ -7187,9 +7187,9 @@ function normalizeNativeEvent({ codec, payload, nativeEventName, nativeSessionId
|
|
|
7187
7187
|
sealedInput.formatterVersion = FORMATTER_VERSION;
|
|
7188
7188
|
if (rule.fileEditKind && (tool === "write" || tool === "edit")) {
|
|
7189
7189
|
kind = rule.fileEditKind;
|
|
7190
|
-
const
|
|
7191
|
-
if (
|
|
7192
|
-
sealedInput.paths = [
|
|
7190
|
+
const path34 = reducePath(readPath2(input, "file_path") ?? readPath2(input, "filePath") ?? readPath2(input, "path") ?? readPath2(input, "notebook_path"), projectRoot);
|
|
7191
|
+
if (path34)
|
|
7192
|
+
sealedInput.paths = [path34.display];
|
|
7193
7193
|
}
|
|
7194
7194
|
idParts.push(tool, description.subject ?? "", description.detail ?? "");
|
|
7195
7195
|
}
|
|
@@ -7619,8 +7619,8 @@ async function runAgentSessionInbox({
|
|
|
7619
7619
|
const scope = resolveAgentSessionScope({ agent, env });
|
|
7620
7620
|
if (!scope) return emptyResult("Empty");
|
|
7621
7621
|
const payload = payloadRaw === void 0 ? parseNativePayload(readBoundedStdin()) : parseNativePayload(payloadRaw);
|
|
7622
|
-
const
|
|
7623
|
-
if (
|
|
7622
|
+
const path34 = resolveInjectPath({ agent, payload });
|
|
7623
|
+
if (path34 === "unsupported") return emptyResult("Unsupported");
|
|
7624
7624
|
const baseUrl = env.OVERLORD_BACKEND_URL?.trim();
|
|
7625
7625
|
if (!baseUrl && !injectedClient) return emptyResult("Empty");
|
|
7626
7626
|
const client = injectedClient ?? createChannelClient({ baseUrl, channelId: scope.channelId, token: scope.token });
|
|
@@ -7634,15 +7634,15 @@ async function runAgentSessionInbox({
|
|
|
7634
7634
|
);
|
|
7635
7635
|
if (!claimed.ok || !claimed.value.input) return emptyResult("Empty");
|
|
7636
7636
|
const input = claimed.value.input;
|
|
7637
|
-
return await emitClaimedInput({ agent, path:
|
|
7637
|
+
return await emitClaimedInput({ agent, path: path34, input, client });
|
|
7638
7638
|
}
|
|
7639
7639
|
async function emitClaimedInput({
|
|
7640
7640
|
agent,
|
|
7641
|
-
path:
|
|
7641
|
+
path: path34,
|
|
7642
7642
|
input,
|
|
7643
7643
|
client
|
|
7644
7644
|
}) {
|
|
7645
|
-
if (
|
|
7645
|
+
if (path34 === "claude-mid-turn") {
|
|
7646
7646
|
const emitted = await client.post(`/inputs/${input.id}/emitted`, {
|
|
7647
7647
|
leaseId: input.leaseId,
|
|
7648
7648
|
deliveryOutcome: "delivered"
|
|
@@ -7657,7 +7657,7 @@ async function emitClaimedInput({
|
|
|
7657
7657
|
inputId: input.id
|
|
7658
7658
|
};
|
|
7659
7659
|
}
|
|
7660
|
-
if (
|
|
7660
|
+
if (path34 === "claude-turn-boundary") {
|
|
7661
7661
|
const emitted = await client.post(`/inputs/${input.id}/emitted`, {
|
|
7662
7662
|
leaseId: input.leaseId,
|
|
7663
7663
|
deliveryOutcome: "delivered"
|
|
@@ -7672,7 +7672,7 @@ async function emitClaimedInput({
|
|
|
7672
7672
|
inputId: input.id
|
|
7673
7673
|
};
|
|
7674
7674
|
}
|
|
7675
|
-
if (
|
|
7675
|
+
if (path34 === "cursor-turn-boundary") {
|
|
7676
7676
|
const emitted = await client.post(`/inputs/${input.id}/emitted`, {
|
|
7677
7677
|
leaseId: input.leaseId,
|
|
7678
7678
|
deliveryOutcome: "queued_turn_boundary"
|
|
@@ -7686,7 +7686,7 @@ async function emitClaimedInput({
|
|
|
7686
7686
|
inputId: input.id
|
|
7687
7687
|
};
|
|
7688
7688
|
}
|
|
7689
|
-
if (
|
|
7689
|
+
if (path34 === "codex-turn-boundary") {
|
|
7690
7690
|
const emitted = await client.post(`/inputs/${input.id}/emitted`, {
|
|
7691
7691
|
leaseId: input.leaseId,
|
|
7692
7692
|
deliveryOutcome: "delivered"
|
|
@@ -7701,7 +7701,7 @@ async function emitClaimedInput({
|
|
|
7701
7701
|
inputId: input.id
|
|
7702
7702
|
};
|
|
7703
7703
|
}
|
|
7704
|
-
if (
|
|
7704
|
+
if (path34 === "pi-mid-turn") {
|
|
7705
7705
|
return {
|
|
7706
7706
|
report: "Empty",
|
|
7707
7707
|
exitCode: 0,
|
|
@@ -7806,8 +7806,8 @@ var init_inbox = __esm({
|
|
|
7806
7806
|
|
|
7807
7807
|
// ../packages/core/dist/service/agent-session/pure/decision.js
|
|
7808
7808
|
function firstValue(source, paths) {
|
|
7809
|
-
for (const
|
|
7810
|
-
const value = readPath2(source,
|
|
7809
|
+
for (const path34 of paths ?? []) {
|
|
7810
|
+
const value = readPath2(source, path34);
|
|
7811
7811
|
if (value !== void 0 && value !== null)
|
|
7812
7812
|
return value;
|
|
7813
7813
|
}
|
|
@@ -8397,10 +8397,10 @@ async function reconcileState({
|
|
|
8397
8397
|
}) {
|
|
8398
8398
|
let posted = 0;
|
|
8399
8399
|
let duplicates = 0;
|
|
8400
|
-
for (const
|
|
8400
|
+
for (const path34 of ["/permission", "/question"]) {
|
|
8401
8401
|
let entries;
|
|
8402
8402
|
try {
|
|
8403
|
-
const response = await doFetch(`${controlPlaneBaseUrl(port)}${
|
|
8403
|
+
const response = await doFetch(`${controlPlaneBaseUrl(port)}${path34}`, {
|
|
8404
8404
|
headers: authHeaders(password)
|
|
8405
8405
|
});
|
|
8406
8406
|
if (!response.ok) continue;
|
|
@@ -8410,7 +8410,7 @@ async function reconcileState({
|
|
|
8410
8410
|
continue;
|
|
8411
8411
|
}
|
|
8412
8412
|
for (const entry of entries) {
|
|
8413
|
-
if (
|
|
8413
|
+
if (path34 === "/permission") {
|
|
8414
8414
|
await syncOpenCodePermission({
|
|
8415
8415
|
client,
|
|
8416
8416
|
frame: { event: "permission.updated", data: JSON.stringify(entry) },
|
|
@@ -8933,17 +8933,17 @@ var require_visit = __commonJS({
|
|
|
8933
8933
|
visit.BREAK = BREAK;
|
|
8934
8934
|
visit.SKIP = SKIP;
|
|
8935
8935
|
visit.REMOVE = REMOVE;
|
|
8936
|
-
function visit_(key, node, visitor,
|
|
8937
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
8936
|
+
function visit_(key, node, visitor, path34) {
|
|
8937
|
+
const ctrl = callVisitor(key, node, visitor, path34);
|
|
8938
8938
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
8939
|
-
replaceNode(key,
|
|
8940
|
-
return visit_(key, ctrl, visitor,
|
|
8939
|
+
replaceNode(key, path34, ctrl);
|
|
8940
|
+
return visit_(key, ctrl, visitor, path34);
|
|
8941
8941
|
}
|
|
8942
8942
|
if (typeof ctrl !== "symbol") {
|
|
8943
8943
|
if (identity.isCollection(node)) {
|
|
8944
|
-
|
|
8944
|
+
path34 = Object.freeze(path34.concat(node));
|
|
8945
8945
|
for (let i = 0; i < node.items.length; ++i) {
|
|
8946
|
-
const ci = visit_(i, node.items[i], visitor,
|
|
8946
|
+
const ci = visit_(i, node.items[i], visitor, path34);
|
|
8947
8947
|
if (typeof ci === "number")
|
|
8948
8948
|
i = ci - 1;
|
|
8949
8949
|
else if (ci === BREAK)
|
|
@@ -8954,13 +8954,13 @@ var require_visit = __commonJS({
|
|
|
8954
8954
|
}
|
|
8955
8955
|
}
|
|
8956
8956
|
} else if (identity.isPair(node)) {
|
|
8957
|
-
|
|
8958
|
-
const ck = visit_("key", node.key, visitor,
|
|
8957
|
+
path34 = Object.freeze(path34.concat(node));
|
|
8958
|
+
const ck = visit_("key", node.key, visitor, path34);
|
|
8959
8959
|
if (ck === BREAK)
|
|
8960
8960
|
return BREAK;
|
|
8961
8961
|
else if (ck === REMOVE)
|
|
8962
8962
|
node.key = null;
|
|
8963
|
-
const cv = visit_("value", node.value, visitor,
|
|
8963
|
+
const cv = visit_("value", node.value, visitor, path34);
|
|
8964
8964
|
if (cv === BREAK)
|
|
8965
8965
|
return BREAK;
|
|
8966
8966
|
else if (cv === REMOVE)
|
|
@@ -8981,17 +8981,17 @@ var require_visit = __commonJS({
|
|
|
8981
8981
|
visitAsync.BREAK = BREAK;
|
|
8982
8982
|
visitAsync.SKIP = SKIP;
|
|
8983
8983
|
visitAsync.REMOVE = REMOVE;
|
|
8984
|
-
async function visitAsync_(key, node, visitor,
|
|
8985
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
8984
|
+
async function visitAsync_(key, node, visitor, path34) {
|
|
8985
|
+
const ctrl = await callVisitor(key, node, visitor, path34);
|
|
8986
8986
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
8987
|
-
replaceNode(key,
|
|
8988
|
-
return visitAsync_(key, ctrl, visitor,
|
|
8987
|
+
replaceNode(key, path34, ctrl);
|
|
8988
|
+
return visitAsync_(key, ctrl, visitor, path34);
|
|
8989
8989
|
}
|
|
8990
8990
|
if (typeof ctrl !== "symbol") {
|
|
8991
8991
|
if (identity.isCollection(node)) {
|
|
8992
|
-
|
|
8992
|
+
path34 = Object.freeze(path34.concat(node));
|
|
8993
8993
|
for (let i = 0; i < node.items.length; ++i) {
|
|
8994
|
-
const ci = await visitAsync_(i, node.items[i], visitor,
|
|
8994
|
+
const ci = await visitAsync_(i, node.items[i], visitor, path34);
|
|
8995
8995
|
if (typeof ci === "number")
|
|
8996
8996
|
i = ci - 1;
|
|
8997
8997
|
else if (ci === BREAK)
|
|
@@ -9002,13 +9002,13 @@ var require_visit = __commonJS({
|
|
|
9002
9002
|
}
|
|
9003
9003
|
}
|
|
9004
9004
|
} else if (identity.isPair(node)) {
|
|
9005
|
-
|
|
9006
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
9005
|
+
path34 = Object.freeze(path34.concat(node));
|
|
9006
|
+
const ck = await visitAsync_("key", node.key, visitor, path34);
|
|
9007
9007
|
if (ck === BREAK)
|
|
9008
9008
|
return BREAK;
|
|
9009
9009
|
else if (ck === REMOVE)
|
|
9010
9010
|
node.key = null;
|
|
9011
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
9011
|
+
const cv = await visitAsync_("value", node.value, visitor, path34);
|
|
9012
9012
|
if (cv === BREAK)
|
|
9013
9013
|
return BREAK;
|
|
9014
9014
|
else if (cv === REMOVE)
|
|
@@ -9035,23 +9035,23 @@ var require_visit = __commonJS({
|
|
|
9035
9035
|
}
|
|
9036
9036
|
return visitor;
|
|
9037
9037
|
}
|
|
9038
|
-
function callVisitor(key, node, visitor,
|
|
9038
|
+
function callVisitor(key, node, visitor, path34) {
|
|
9039
9039
|
if (typeof visitor === "function")
|
|
9040
|
-
return visitor(key, node,
|
|
9040
|
+
return visitor(key, node, path34);
|
|
9041
9041
|
if (identity.isMap(node))
|
|
9042
|
-
return visitor.Map?.(key, node,
|
|
9042
|
+
return visitor.Map?.(key, node, path34);
|
|
9043
9043
|
if (identity.isSeq(node))
|
|
9044
|
-
return visitor.Seq?.(key, node,
|
|
9044
|
+
return visitor.Seq?.(key, node, path34);
|
|
9045
9045
|
if (identity.isPair(node))
|
|
9046
|
-
return visitor.Pair?.(key, node,
|
|
9046
|
+
return visitor.Pair?.(key, node, path34);
|
|
9047
9047
|
if (identity.isScalar(node))
|
|
9048
|
-
return visitor.Scalar?.(key, node,
|
|
9048
|
+
return visitor.Scalar?.(key, node, path34);
|
|
9049
9049
|
if (identity.isAlias(node))
|
|
9050
|
-
return visitor.Alias?.(key, node,
|
|
9050
|
+
return visitor.Alias?.(key, node, path34);
|
|
9051
9051
|
return void 0;
|
|
9052
9052
|
}
|
|
9053
|
-
function replaceNode(key,
|
|
9054
|
-
const parent =
|
|
9053
|
+
function replaceNode(key, path34, node) {
|
|
9054
|
+
const parent = path34[path34.length - 1];
|
|
9055
9055
|
if (identity.isCollection(parent)) {
|
|
9056
9056
|
parent.items[key] = node;
|
|
9057
9057
|
} else if (identity.isPair(parent)) {
|
|
@@ -9661,10 +9661,10 @@ var require_Collection = __commonJS({
|
|
|
9661
9661
|
var createNode = require_createNode();
|
|
9662
9662
|
var identity = require_identity();
|
|
9663
9663
|
var Node = require_Node();
|
|
9664
|
-
function collectionFromPath(schema,
|
|
9664
|
+
function collectionFromPath(schema, path34, value) {
|
|
9665
9665
|
let v = value;
|
|
9666
|
-
for (let i =
|
|
9667
|
-
const k =
|
|
9666
|
+
for (let i = path34.length - 1; i >= 0; --i) {
|
|
9667
|
+
const k = path34[i];
|
|
9668
9668
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
9669
9669
|
const a = [];
|
|
9670
9670
|
a[k] = v;
|
|
@@ -9683,7 +9683,7 @@ var require_Collection = __commonJS({
|
|
|
9683
9683
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
9684
9684
|
});
|
|
9685
9685
|
}
|
|
9686
|
-
var isEmptyPath = (
|
|
9686
|
+
var isEmptyPath = (path34) => path34 == null || typeof path34 === "object" && !!path34[Symbol.iterator]().next().done;
|
|
9687
9687
|
var Collection = class extends Node.NodeBase {
|
|
9688
9688
|
constructor(type, schema) {
|
|
9689
9689
|
super(type);
|
|
@@ -9713,11 +9713,11 @@ var require_Collection = __commonJS({
|
|
|
9713
9713
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
9714
9714
|
* that already exists in the map.
|
|
9715
9715
|
*/
|
|
9716
|
-
addIn(
|
|
9717
|
-
if (isEmptyPath(
|
|
9716
|
+
addIn(path34, value) {
|
|
9717
|
+
if (isEmptyPath(path34))
|
|
9718
9718
|
this.add(value);
|
|
9719
9719
|
else {
|
|
9720
|
-
const [key, ...rest] =
|
|
9720
|
+
const [key, ...rest] = path34;
|
|
9721
9721
|
const node = this.get(key, true);
|
|
9722
9722
|
if (identity.isCollection(node))
|
|
9723
9723
|
node.addIn(rest, value);
|
|
@@ -9731,8 +9731,8 @@ var require_Collection = __commonJS({
|
|
|
9731
9731
|
* Removes a value from the collection.
|
|
9732
9732
|
* @returns `true` if the item was found and removed.
|
|
9733
9733
|
*/
|
|
9734
|
-
deleteIn(
|
|
9735
|
-
const [key, ...rest] =
|
|
9734
|
+
deleteIn(path34) {
|
|
9735
|
+
const [key, ...rest] = path34;
|
|
9736
9736
|
if (rest.length === 0)
|
|
9737
9737
|
return this.delete(key);
|
|
9738
9738
|
const node = this.get(key, true);
|
|
@@ -9746,8 +9746,8 @@ var require_Collection = __commonJS({
|
|
|
9746
9746
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
9747
9747
|
* `true` (collections are always returned intact).
|
|
9748
9748
|
*/
|
|
9749
|
-
getIn(
|
|
9750
|
-
const [key, ...rest] =
|
|
9749
|
+
getIn(path34, keepScalar) {
|
|
9750
|
+
const [key, ...rest] = path34;
|
|
9751
9751
|
const node = this.get(key, true);
|
|
9752
9752
|
if (rest.length === 0)
|
|
9753
9753
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -9765,8 +9765,8 @@ var require_Collection = __commonJS({
|
|
|
9765
9765
|
/**
|
|
9766
9766
|
* Checks if the collection includes a value with the key `key`.
|
|
9767
9767
|
*/
|
|
9768
|
-
hasIn(
|
|
9769
|
-
const [key, ...rest] =
|
|
9768
|
+
hasIn(path34) {
|
|
9769
|
+
const [key, ...rest] = path34;
|
|
9770
9770
|
if (rest.length === 0)
|
|
9771
9771
|
return this.has(key);
|
|
9772
9772
|
const node = this.get(key, true);
|
|
@@ -9776,8 +9776,8 @@ var require_Collection = __commonJS({
|
|
|
9776
9776
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
9777
9777
|
* boolean to add/remove the item from the set.
|
|
9778
9778
|
*/
|
|
9779
|
-
setIn(
|
|
9780
|
-
const [key, ...rest] =
|
|
9779
|
+
setIn(path34, value) {
|
|
9780
|
+
const [key, ...rest] = path34;
|
|
9781
9781
|
if (rest.length === 0) {
|
|
9782
9782
|
this.set(key, value);
|
|
9783
9783
|
} else {
|
|
@@ -12292,9 +12292,9 @@ var require_Document = __commonJS({
|
|
|
12292
12292
|
this.contents.add(value);
|
|
12293
12293
|
}
|
|
12294
12294
|
/** Adds a value to the document. */
|
|
12295
|
-
addIn(
|
|
12295
|
+
addIn(path34, value) {
|
|
12296
12296
|
if (assertCollection(this.contents))
|
|
12297
|
-
this.contents.addIn(
|
|
12297
|
+
this.contents.addIn(path34, value);
|
|
12298
12298
|
}
|
|
12299
12299
|
/**
|
|
12300
12300
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -12369,14 +12369,14 @@ var require_Document = __commonJS({
|
|
|
12369
12369
|
* Removes a value from the document.
|
|
12370
12370
|
* @returns `true` if the item was found and removed.
|
|
12371
12371
|
*/
|
|
12372
|
-
deleteIn(
|
|
12373
|
-
if (Collection.isEmptyPath(
|
|
12372
|
+
deleteIn(path34) {
|
|
12373
|
+
if (Collection.isEmptyPath(path34)) {
|
|
12374
12374
|
if (this.contents == null)
|
|
12375
12375
|
return false;
|
|
12376
12376
|
this.contents = null;
|
|
12377
12377
|
return true;
|
|
12378
12378
|
}
|
|
12379
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
12379
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path34) : false;
|
|
12380
12380
|
}
|
|
12381
12381
|
/**
|
|
12382
12382
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -12391,10 +12391,10 @@ var require_Document = __commonJS({
|
|
|
12391
12391
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
12392
12392
|
* `true` (collections are always returned intact).
|
|
12393
12393
|
*/
|
|
12394
|
-
getIn(
|
|
12395
|
-
if (Collection.isEmptyPath(
|
|
12394
|
+
getIn(path34, keepScalar) {
|
|
12395
|
+
if (Collection.isEmptyPath(path34))
|
|
12396
12396
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
12397
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
12397
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path34, keepScalar) : void 0;
|
|
12398
12398
|
}
|
|
12399
12399
|
/**
|
|
12400
12400
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -12405,10 +12405,10 @@ var require_Document = __commonJS({
|
|
|
12405
12405
|
/**
|
|
12406
12406
|
* Checks if the document includes a value at `path`.
|
|
12407
12407
|
*/
|
|
12408
|
-
hasIn(
|
|
12409
|
-
if (Collection.isEmptyPath(
|
|
12408
|
+
hasIn(path34) {
|
|
12409
|
+
if (Collection.isEmptyPath(path34))
|
|
12410
12410
|
return this.contents !== void 0;
|
|
12411
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
12411
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path34) : false;
|
|
12412
12412
|
}
|
|
12413
12413
|
/**
|
|
12414
12414
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -12425,13 +12425,13 @@ var require_Document = __commonJS({
|
|
|
12425
12425
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
12426
12426
|
* boolean to add/remove the item from the set.
|
|
12427
12427
|
*/
|
|
12428
|
-
setIn(
|
|
12429
|
-
if (Collection.isEmptyPath(
|
|
12428
|
+
setIn(path34, value) {
|
|
12429
|
+
if (Collection.isEmptyPath(path34)) {
|
|
12430
12430
|
this.contents = value;
|
|
12431
12431
|
} else if (this.contents == null) {
|
|
12432
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
12432
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path34), value);
|
|
12433
12433
|
} else if (assertCollection(this.contents)) {
|
|
12434
|
-
this.contents.setIn(
|
|
12434
|
+
this.contents.setIn(path34, value);
|
|
12435
12435
|
}
|
|
12436
12436
|
}
|
|
12437
12437
|
/**
|
|
@@ -14391,9 +14391,9 @@ var require_cst_visit = __commonJS({
|
|
|
14391
14391
|
visit.BREAK = BREAK;
|
|
14392
14392
|
visit.SKIP = SKIP;
|
|
14393
14393
|
visit.REMOVE = REMOVE;
|
|
14394
|
-
visit.itemAtPath = (cst,
|
|
14394
|
+
visit.itemAtPath = (cst, path34) => {
|
|
14395
14395
|
let item = cst;
|
|
14396
|
-
for (const [field, index] of
|
|
14396
|
+
for (const [field, index] of path34) {
|
|
14397
14397
|
const tok = item?.[field];
|
|
14398
14398
|
if (tok && "items" in tok) {
|
|
14399
14399
|
item = tok.items[index];
|
|
@@ -14402,23 +14402,23 @@ var require_cst_visit = __commonJS({
|
|
|
14402
14402
|
}
|
|
14403
14403
|
return item;
|
|
14404
14404
|
};
|
|
14405
|
-
visit.parentCollection = (cst,
|
|
14406
|
-
const parent = visit.itemAtPath(cst,
|
|
14407
|
-
const field =
|
|
14405
|
+
visit.parentCollection = (cst, path34) => {
|
|
14406
|
+
const parent = visit.itemAtPath(cst, path34.slice(0, -1));
|
|
14407
|
+
const field = path34[path34.length - 1][0];
|
|
14408
14408
|
const coll = parent?.[field];
|
|
14409
14409
|
if (coll && "items" in coll)
|
|
14410
14410
|
return coll;
|
|
14411
14411
|
throw new Error("Parent collection not found");
|
|
14412
14412
|
};
|
|
14413
|
-
function _visit(
|
|
14414
|
-
let ctrl = visitor(item,
|
|
14413
|
+
function _visit(path34, item, visitor) {
|
|
14414
|
+
let ctrl = visitor(item, path34);
|
|
14415
14415
|
if (typeof ctrl === "symbol")
|
|
14416
14416
|
return ctrl;
|
|
14417
14417
|
for (const field of ["key", "value"]) {
|
|
14418
14418
|
const token = item[field];
|
|
14419
14419
|
if (token && "items" in token) {
|
|
14420
14420
|
for (let i = 0; i < token.items.length; ++i) {
|
|
14421
|
-
const ci = _visit(Object.freeze(
|
|
14421
|
+
const ci = _visit(Object.freeze(path34.concat([[field, i]])), token.items[i], visitor);
|
|
14422
14422
|
if (typeof ci === "number")
|
|
14423
14423
|
i = ci - 1;
|
|
14424
14424
|
else if (ci === BREAK)
|
|
@@ -14429,10 +14429,10 @@ var require_cst_visit = __commonJS({
|
|
|
14429
14429
|
}
|
|
14430
14430
|
}
|
|
14431
14431
|
if (typeof ctrl === "function" && field === "key")
|
|
14432
|
-
ctrl = ctrl(item,
|
|
14432
|
+
ctrl = ctrl(item, path34);
|
|
14433
14433
|
}
|
|
14434
14434
|
}
|
|
14435
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
14435
|
+
return typeof ctrl === "function" ? ctrl(item, path34) : ctrl;
|
|
14436
14436
|
}
|
|
14437
14437
|
exports.visit = visit;
|
|
14438
14438
|
}
|
|
@@ -16343,22 +16343,22 @@ var init_contract = __esm({
|
|
|
16343
16343
|
|
|
16344
16344
|
// ../packages/contract/dist/agent-launch-flags.js
|
|
16345
16345
|
function parseAgentLaunchFlagText(text) {
|
|
16346
|
-
const
|
|
16347
|
-
if (!
|
|
16346
|
+
const trimmed5 = text.trim();
|
|
16347
|
+
if (!trimmed5)
|
|
16348
16348
|
return null;
|
|
16349
|
-
const eqIndex =
|
|
16350
|
-
if (eqIndex > 0 &&
|
|
16351
|
-
const name =
|
|
16352
|
-
const value =
|
|
16349
|
+
const eqIndex = trimmed5.indexOf("=");
|
|
16350
|
+
if (eqIndex > 0 && trimmed5.startsWith("--")) {
|
|
16351
|
+
const name = trimmed5.slice(0, eqIndex).trim();
|
|
16352
|
+
const value = trimmed5.slice(eqIndex + 1).trim();
|
|
16353
16353
|
return name ? { name, value: value.length > 0 ? value : null } : null;
|
|
16354
16354
|
}
|
|
16355
|
-
const spaceIndex =
|
|
16356
|
-
if (spaceIndex > 0 &&
|
|
16357
|
-
const name =
|
|
16358
|
-
const value =
|
|
16355
|
+
const spaceIndex = trimmed5.indexOf(" ");
|
|
16356
|
+
if (spaceIndex > 0 && trimmed5.startsWith("--")) {
|
|
16357
|
+
const name = trimmed5.slice(0, spaceIndex).trim();
|
|
16358
|
+
const value = trimmed5.slice(spaceIndex + 1).trim();
|
|
16359
16359
|
return name ? { name, value: value.length > 0 ? value : null } : null;
|
|
16360
16360
|
}
|
|
16361
|
-
return { name:
|
|
16361
|
+
return { name: trimmed5 };
|
|
16362
16362
|
}
|
|
16363
16363
|
function normalizeAgentLaunchFlags(input) {
|
|
16364
16364
|
if (!Array.isArray(input))
|
|
@@ -16508,12 +16508,12 @@ function accessModeToResourcePathPermission({ accessMode, isPrimary = false }) {
|
|
|
16508
16508
|
return "rw";
|
|
16509
16509
|
return accessMode === "read" ? "ro" : "rw";
|
|
16510
16510
|
}
|
|
16511
|
-
function formatResourcePathWithPermission({ path:
|
|
16512
|
-
const
|
|
16513
|
-
if (!
|
|
16511
|
+
function formatResourcePathWithPermission({ path: path34, accessMode, isPrimary = false }) {
|
|
16512
|
+
const trimmed5 = path34.trim();
|
|
16513
|
+
if (!trimmed5)
|
|
16514
16514
|
return "";
|
|
16515
16515
|
const permission = accessModeToResourcePathPermission({ accessMode, isPrimary });
|
|
16516
|
-
return `${
|
|
16516
|
+
return `${trimmed5}:${permission}`;
|
|
16517
16517
|
}
|
|
16518
16518
|
function formatProjectResourcePathsFromManifest(projectResources) {
|
|
16519
16519
|
if (!Array.isArray(projectResources))
|
|
@@ -16523,11 +16523,11 @@ function formatProjectResourcePathsFromManifest(projectResources) {
|
|
|
16523
16523
|
if (!entry || typeof entry !== "object")
|
|
16524
16524
|
continue;
|
|
16525
16525
|
const record = entry;
|
|
16526
|
-
const
|
|
16527
|
-
if (!
|
|
16526
|
+
const path34 = typeof record.path === "string" ? record.path.trim() : "";
|
|
16527
|
+
if (!path34)
|
|
16528
16528
|
continue;
|
|
16529
16529
|
paths.push(formatResourcePathWithPermission({
|
|
16530
|
-
path:
|
|
16530
|
+
path: path34,
|
|
16531
16531
|
accessMode: typeof record.accessMode === "string" ? record.accessMode : null,
|
|
16532
16532
|
isPrimary: record.isPrimary === true
|
|
16533
16533
|
}));
|
|
@@ -16784,11 +16784,545 @@ var init_git_tree = __esm({
|
|
|
16784
16784
|
}
|
|
16785
16785
|
});
|
|
16786
16786
|
|
|
16787
|
-
// ../packages/core/dist/service/
|
|
16787
|
+
// ../packages/core/dist/service/terminal-profile-types.js
|
|
16788
|
+
function trimmed(value) {
|
|
16789
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
16790
|
+
}
|
|
16791
|
+
function viewerKindForLauncher(launcher) {
|
|
16792
|
+
const value = trimmed(launcher);
|
|
16793
|
+
if (!value)
|
|
16794
|
+
return "inline";
|
|
16795
|
+
const lowered = value.toLowerCase();
|
|
16796
|
+
if (lowered === "iterm2" || lowered === "iterm")
|
|
16797
|
+
return "iterm";
|
|
16798
|
+
if (lowered === "terminal")
|
|
16799
|
+
return "terminal";
|
|
16800
|
+
return "custom";
|
|
16801
|
+
}
|
|
16802
|
+
function normalizeExecutionProvider(value) {
|
|
16803
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16804
|
+
return null;
|
|
16805
|
+
const cast = value;
|
|
16806
|
+
const kind = trimmed(cast.kind)?.toLowerCase() === "latch" ? "latch" : "direct";
|
|
16807
|
+
return {
|
|
16808
|
+
kind,
|
|
16809
|
+
executable: trimmed(cast.executable) ?? DEFAULT_LATCH_EXECUTABLE
|
|
16810
|
+
};
|
|
16811
|
+
}
|
|
16812
|
+
function launchSessionSnapshotFromMetadata(metadata) {
|
|
16813
|
+
const raw = metadata?.[LAUNCH_SESSION_METADATA_KEY];
|
|
16814
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
16815
|
+
return null;
|
|
16816
|
+
const cast = raw;
|
|
16817
|
+
if (cast.version !== TERMINAL_PROFILE_VERSION)
|
|
16818
|
+
return null;
|
|
16819
|
+
const viewer = cast.viewer && typeof cast.viewer === "object" && !Array.isArray(cast.viewer) ? cast.viewer : null;
|
|
16820
|
+
const launcher = trimmed(viewer?.launcher);
|
|
16821
|
+
const source = (value) => trimmed(value) === "target" ? "target" : "user_default";
|
|
16822
|
+
return {
|
|
16823
|
+
version: TERMINAL_PROFILE_VERSION,
|
|
16824
|
+
executionProvider: normalizeExecutionProvider(cast.executionProvider) ?? {
|
|
16825
|
+
...DEFAULT_EXECUTION_PROVIDER
|
|
16826
|
+
},
|
|
16827
|
+
viewer: {
|
|
16828
|
+
kind: trimmed(viewer?.kind) ? trimmed(viewer?.kind) : viewerKindForLauncher(launcher),
|
|
16829
|
+
launcher,
|
|
16830
|
+
openOnLaunch: viewer?.openOnLaunch !== false
|
|
16831
|
+
},
|
|
16832
|
+
executionProviderSource: source(cast.executionProviderSource),
|
|
16833
|
+
viewerOpenSource: source(cast.viewerOpenSource),
|
|
16834
|
+
resolvedAt: trimmed(cast.resolvedAt) ?? ""
|
|
16835
|
+
};
|
|
16836
|
+
}
|
|
16837
|
+
var TERMINAL_PROFILE_VERSION, DEFAULT_LATCH_EXECUTABLE, DEFAULT_EXECUTION_PROVIDER, DEFAULT_OPEN_VIEWER_ON_LAUNCH, DEFAULT_LAUNCH_SESSION_DEFAULTS, LAUNCH_SESSION_METADATA_KEY;
|
|
16838
|
+
var init_terminal_profile_types2 = __esm({
|
|
16839
|
+
"../packages/core/dist/service/terminal-profile-types.js"() {
|
|
16840
|
+
"use strict";
|
|
16841
|
+
TERMINAL_PROFILE_VERSION = 1;
|
|
16842
|
+
DEFAULT_LATCH_EXECUTABLE = "latch";
|
|
16843
|
+
DEFAULT_EXECUTION_PROVIDER = {
|
|
16844
|
+
kind: "direct",
|
|
16845
|
+
executable: DEFAULT_LATCH_EXECUTABLE
|
|
16846
|
+
};
|
|
16847
|
+
DEFAULT_OPEN_VIEWER_ON_LAUNCH = true;
|
|
16848
|
+
DEFAULT_LAUNCH_SESSION_DEFAULTS = {
|
|
16849
|
+
executionProvider: { ...DEFAULT_EXECUTION_PROVIDER },
|
|
16850
|
+
openViewerOnLaunch: DEFAULT_OPEN_VIEWER_ON_LAUNCH
|
|
16851
|
+
};
|
|
16852
|
+
LAUNCH_SESSION_METADATA_KEY = "launchSession";
|
|
16853
|
+
}
|
|
16854
|
+
});
|
|
16855
|
+
|
|
16856
|
+
// ../packages/core/dist/service/latch-discovery.js
|
|
16788
16857
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
16858
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync15, statSync as statSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
16859
|
+
import os3 from "node:os";
|
|
16860
|
+
import path17 from "node:path";
|
|
16861
|
+
function defaultLatchDiscoveryCachePath() {
|
|
16862
|
+
const home = process.env.OVLD_HOME?.trim() || path17.join(os3.homedir(), ".ovld");
|
|
16863
|
+
return path17.join(home, LATCH_DISCOVERY_CACHE_FILENAME);
|
|
16864
|
+
}
|
|
16865
|
+
function trimmed2(value) {
|
|
16866
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
16867
|
+
}
|
|
16868
|
+
function asBoolean(value) {
|
|
16869
|
+
return value === true;
|
|
16870
|
+
}
|
|
16871
|
+
function asStringArray(value) {
|
|
16872
|
+
if (!Array.isArray(value))
|
|
16873
|
+
return [];
|
|
16874
|
+
return value.filter((entry) => typeof entry === "string");
|
|
16875
|
+
}
|
|
16876
|
+
function parseLatchCapabilitiesReport(raw) {
|
|
16877
|
+
const text = raw.trim();
|
|
16878
|
+
if (!text)
|
|
16879
|
+
return null;
|
|
16880
|
+
let parsed;
|
|
16881
|
+
try {
|
|
16882
|
+
parsed = JSON.parse(text);
|
|
16883
|
+
} catch {
|
|
16884
|
+
return null;
|
|
16885
|
+
}
|
|
16886
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
16887
|
+
return null;
|
|
16888
|
+
const cast = parsed;
|
|
16889
|
+
const protocolVersion = typeof cast.protocolVersion === "number" && Number.isFinite(cast.protocolVersion) ? Math.trunc(cast.protocolVersion) : null;
|
|
16890
|
+
const productVersion = trimmed2(cast.productVersion);
|
|
16891
|
+
if (protocolVersion === null || !productVersion)
|
|
16892
|
+
return null;
|
|
16893
|
+
if (!cast.capabilities || typeof cast.capabilities !== "object" || Array.isArray(cast.capabilities)) {
|
|
16894
|
+
return null;
|
|
16895
|
+
}
|
|
16896
|
+
const caps = cast.capabilities;
|
|
16897
|
+
return {
|
|
16898
|
+
protocolVersion,
|
|
16899
|
+
productVersion,
|
|
16900
|
+
capabilities: {
|
|
16901
|
+
create: asBoolean(caps.create),
|
|
16902
|
+
openViewer: asBoolean(caps.openViewer),
|
|
16903
|
+
localAttach: asBoolean(caps.localAttach),
|
|
16904
|
+
cloudAttach: asBoolean(caps.cloudAttach),
|
|
16905
|
+
selfUpdate: asBoolean(caps.selfUpdate),
|
|
16906
|
+
extensions: asStringArray(caps.extensions)
|
|
16907
|
+
}
|
|
16908
|
+
};
|
|
16909
|
+
}
|
|
16910
|
+
function evaluateLatchCapabilities({ report, executable, resolvedPath, checkedAt = (/* @__PURE__ */ new Date()).toISOString() }) {
|
|
16911
|
+
if (report.protocolVersion !== SUPPORTED_LATCH_PROTOCOL_VERSION) {
|
|
16912
|
+
return {
|
|
16913
|
+
state: "incompatible",
|
|
16914
|
+
executable,
|
|
16915
|
+
resolvedPath,
|
|
16916
|
+
protocolVersion: report.protocolVersion,
|
|
16917
|
+
productVersion: report.productVersion,
|
|
16918
|
+
missingCapability: "protocolVersion",
|
|
16919
|
+
detail: `Latch protocolVersion ${report.protocolVersion} is not supported (need ${SUPPORTED_LATCH_PROTOCOL_VERSION}).`,
|
|
16920
|
+
checkedAt,
|
|
16921
|
+
latchSelectable: false,
|
|
16922
|
+
directSelectable: true
|
|
16923
|
+
};
|
|
16924
|
+
}
|
|
16925
|
+
for (const required of REQUIRED_LATCH_CAPABILITIES) {
|
|
16926
|
+
if (!report.capabilities[required]) {
|
|
16927
|
+
return {
|
|
16928
|
+
state: "incompatible",
|
|
16929
|
+
executable,
|
|
16930
|
+
resolvedPath,
|
|
16931
|
+
protocolVersion: report.protocolVersion,
|
|
16932
|
+
productVersion: report.productVersion,
|
|
16933
|
+
missingCapability: required,
|
|
16934
|
+
detail: `Latch is missing required capability \`${required}\`.`,
|
|
16935
|
+
checkedAt,
|
|
16936
|
+
latchSelectable: false,
|
|
16937
|
+
directSelectable: true
|
|
16938
|
+
};
|
|
16939
|
+
}
|
|
16940
|
+
}
|
|
16941
|
+
return {
|
|
16942
|
+
state: "found",
|
|
16943
|
+
executable,
|
|
16944
|
+
resolvedPath,
|
|
16945
|
+
protocolVersion: report.protocolVersion,
|
|
16946
|
+
productVersion: report.productVersion,
|
|
16947
|
+
capabilities: report.capabilities,
|
|
16948
|
+
checkedAt,
|
|
16949
|
+
latchSelectable: true,
|
|
16950
|
+
directSelectable: true
|
|
16951
|
+
};
|
|
16952
|
+
}
|
|
16953
|
+
function resolveLatchExecutablePath(executable) {
|
|
16954
|
+
const name = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
|
|
16955
|
+
if (path17.isAbsolute(name) || name.includes("/") || name.includes("\\")) {
|
|
16956
|
+
return existsSync16(name) ? path17.resolve(name) : null;
|
|
16957
|
+
}
|
|
16958
|
+
try {
|
|
16959
|
+
const found = execFileSync3("which", [name], {
|
|
16960
|
+
encoding: "utf8",
|
|
16961
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
16962
|
+
}).trim();
|
|
16963
|
+
return found || null;
|
|
16964
|
+
} catch {
|
|
16965
|
+
return null;
|
|
16966
|
+
}
|
|
16967
|
+
}
|
|
16968
|
+
function notInstalledResult({ executable, checkedAt }) {
|
|
16969
|
+
return {
|
|
16970
|
+
state: "not_installed",
|
|
16971
|
+
executable,
|
|
16972
|
+
installCommand: LATCH_STANDALONE_INSTALL_COMMAND,
|
|
16973
|
+
checkedAt,
|
|
16974
|
+
latchSelectable: false,
|
|
16975
|
+
directSelectable: true
|
|
16976
|
+
};
|
|
16977
|
+
}
|
|
16978
|
+
function probeLatchCapabilities({ executable = DEFAULT_LATCH_EXECUTABLE, resolvePath = resolveLatchExecutablePath, runCommand: runCommand2 = defaultCommandRunner, now = () => (/* @__PURE__ */ new Date()).toISOString() } = {}) {
|
|
16979
|
+
const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
|
|
16980
|
+
const checkedAt = now();
|
|
16981
|
+
const resolvedPath = resolvePath(exe);
|
|
16982
|
+
if (!resolvedPath) {
|
|
16983
|
+
return notInstalledResult({ executable: exe, checkedAt });
|
|
16984
|
+
}
|
|
16985
|
+
const ran = runCommand2({ executable: resolvedPath, argv: ["capabilities", "--json"] });
|
|
16986
|
+
if (ran.status === null && ran.stderr === "ENOENT") {
|
|
16987
|
+
return notInstalledResult({ executable: exe, checkedAt });
|
|
16988
|
+
}
|
|
16989
|
+
const report = parseLatchCapabilitiesReport(ran.stdout);
|
|
16990
|
+
if (!report) {
|
|
16991
|
+
return {
|
|
16992
|
+
state: "incompatible",
|
|
16993
|
+
executable: exe,
|
|
16994
|
+
resolvedPath,
|
|
16995
|
+
protocolVersion: null,
|
|
16996
|
+
productVersion: null,
|
|
16997
|
+
missingCapability: "capabilities",
|
|
16998
|
+
detail: ran.status === 0 ? "Latch capabilities output was not valid JSON in the expected shape." : `Latch capabilities failed (exit ${ran.status ?? "null"}).`,
|
|
16999
|
+
checkedAt,
|
|
17000
|
+
latchSelectable: false,
|
|
17001
|
+
directSelectable: true
|
|
17002
|
+
};
|
|
17003
|
+
}
|
|
17004
|
+
return evaluateLatchCapabilities({ report, executable: exe, resolvedPath, checkedAt });
|
|
17005
|
+
}
|
|
17006
|
+
function latchDiscoveryCacheKey({ executionTargetId, executable }) {
|
|
17007
|
+
const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
|
|
17008
|
+
return `${executionTargetId}::${exe}`;
|
|
17009
|
+
}
|
|
17010
|
+
function readBinaryMtimeMs(resolvedPath) {
|
|
17011
|
+
if (!resolvedPath)
|
|
17012
|
+
return null;
|
|
17013
|
+
try {
|
|
17014
|
+
return statSync4(resolvedPath).mtimeMs;
|
|
17015
|
+
} catch {
|
|
17016
|
+
return null;
|
|
17017
|
+
}
|
|
17018
|
+
}
|
|
17019
|
+
function isLatchDiscoveryCacheFresh({ entry, resolvePath = resolveLatchExecutablePath }) {
|
|
17020
|
+
const { result } = entry;
|
|
17021
|
+
if (result.state === "not_installed") {
|
|
17022
|
+
return resolvePath(result.executable) === null;
|
|
17023
|
+
}
|
|
17024
|
+
const pathStill = result.resolvedPath;
|
|
17025
|
+
if (!pathStill || !existsSync16(pathStill))
|
|
17026
|
+
return false;
|
|
17027
|
+
const mtime = readBinaryMtimeMs(pathStill);
|
|
17028
|
+
if (mtime === null || entry.binaryMtimeMs === null)
|
|
17029
|
+
return false;
|
|
17030
|
+
return mtime === entry.binaryMtimeMs;
|
|
17031
|
+
}
|
|
17032
|
+
function readLatchDiscoveryCacheFile(filePath) {
|
|
17033
|
+
if (!existsSync16(filePath))
|
|
17034
|
+
return { version: 1, entries: {} };
|
|
17035
|
+
try {
|
|
17036
|
+
const parsed = JSON.parse(readFileSync15(filePath, "utf8"));
|
|
17037
|
+
if (parsed.version !== 1 || !parsed.entries || typeof parsed.entries !== "object") {
|
|
17038
|
+
return { version: 1, entries: {} };
|
|
17039
|
+
}
|
|
17040
|
+
return { version: 1, entries: parsed.entries };
|
|
17041
|
+
} catch {
|
|
17042
|
+
return { version: 1, entries: {} };
|
|
17043
|
+
}
|
|
17044
|
+
}
|
|
17045
|
+
function writeLatchDiscoveryCacheFile({ filePath, cache }) {
|
|
17046
|
+
mkdirSync9(path17.dirname(filePath), { recursive: true });
|
|
17047
|
+
writeFileSync8(filePath, `${JSON.stringify(cache, null, 2)}
|
|
17048
|
+
`, { mode: 384 });
|
|
17049
|
+
}
|
|
17050
|
+
function discoverLatchForExecutionTarget({ executionTargetId, executable = DEFAULT_LATCH_EXECUTABLE, cacheFilePath, force = false, resolvePath = resolveLatchExecutablePath, runCommand: runCommand2 = defaultCommandRunner, now = () => (/* @__PURE__ */ new Date()).toISOString() }) {
|
|
17051
|
+
const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
|
|
17052
|
+
const key = latchDiscoveryCacheKey({ executionTargetId, executable: exe });
|
|
17053
|
+
const cache = readLatchDiscoveryCacheFile(cacheFilePath);
|
|
17054
|
+
const existing = cache.entries[key];
|
|
17055
|
+
if (!force && existing && isLatchDiscoveryCacheFresh({ entry: existing, resolvePath })) {
|
|
17056
|
+
return { ...existing.result, checkedAt: existing.result.checkedAt, directSelectable: true };
|
|
17057
|
+
}
|
|
17058
|
+
const result = probeLatchCapabilities({ executable: exe, resolvePath, runCommand: runCommand2, now });
|
|
17059
|
+
const binaryMtimeMs = result.state === "not_installed" ? null : readBinaryMtimeMs(result.resolvedPath);
|
|
17060
|
+
cache.entries[key] = {
|
|
17061
|
+
result,
|
|
17062
|
+
binaryMtimeMs,
|
|
17063
|
+
cachedAt: result.checkedAt
|
|
17064
|
+
};
|
|
17065
|
+
writeLatchDiscoveryCacheFile({ filePath: cacheFilePath, cache });
|
|
17066
|
+
return result;
|
|
17067
|
+
}
|
|
17068
|
+
var SUPPORTED_LATCH_PROTOCOL_VERSION, REQUIRED_LATCH_CAPABILITIES, LATCH_STANDALONE_INSTALL_COMMAND, LATCH_DISCOVERY_CACHE_FILENAME, defaultCommandRunner;
|
|
17069
|
+
var init_latch_discovery = __esm({
|
|
17070
|
+
"../packages/core/dist/service/latch-discovery.js"() {
|
|
17071
|
+
"use strict";
|
|
17072
|
+
init_terminal_profile_types2();
|
|
17073
|
+
SUPPORTED_LATCH_PROTOCOL_VERSION = 1;
|
|
17074
|
+
REQUIRED_LATCH_CAPABILITIES = ["create"];
|
|
17075
|
+
LATCH_STANDALONE_INSTALL_COMMAND = "curl -fsSL https://raw.githubusercontent.com/jchaselubitz/Latch/main/scripts/install-cli.sh | bash";
|
|
17076
|
+
LATCH_DISCOVERY_CACHE_FILENAME = "latch-discovery.json";
|
|
17077
|
+
defaultCommandRunner = ({ executable, argv }) => {
|
|
17078
|
+
try {
|
|
17079
|
+
const stdout = execFileSync3(executable, argv, {
|
|
17080
|
+
encoding: "utf8",
|
|
17081
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
17082
|
+
timeout: 5e3
|
|
17083
|
+
});
|
|
17084
|
+
return { status: 0, stdout: String(stdout), stderr: "" };
|
|
17085
|
+
} catch (error) {
|
|
17086
|
+
const err = error;
|
|
17087
|
+
if (err.code === "ENOENT") {
|
|
17088
|
+
return { status: null, stdout: "", stderr: "ENOENT" };
|
|
17089
|
+
}
|
|
17090
|
+
return {
|
|
17091
|
+
status: typeof err.status === "number" ? err.status : 1,
|
|
17092
|
+
stdout: err.stdout ? String(err.stdout) : "",
|
|
17093
|
+
stderr: err.stderr ? String(err.stderr) : String(error)
|
|
17094
|
+
};
|
|
17095
|
+
}
|
|
17096
|
+
};
|
|
17097
|
+
}
|
|
17098
|
+
});
|
|
17099
|
+
|
|
17100
|
+
// ../packages/core/dist/service/latch-launch.js
|
|
17101
|
+
function trimmed3(value) {
|
|
17102
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
17103
|
+
}
|
|
17104
|
+
function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.trim() || "/bin/bash", cwd, env, size = DEFAULT_LATCH_TERMINAL_SIZE, title, name, commandLabel, externalRunId }) {
|
|
17105
|
+
const shellPath = trimmed3(shell) ?? "/bin/bash";
|
|
17106
|
+
const cleanedEnv = {};
|
|
17107
|
+
for (const [key, value] of Object.entries(env)) {
|
|
17108
|
+
if (key.trim() && typeof value === "string")
|
|
17109
|
+
cleanedEnv[key] = value;
|
|
17110
|
+
}
|
|
17111
|
+
const display = {
|
|
17112
|
+
source: {
|
|
17113
|
+
kind: "overlord",
|
|
17114
|
+
...trimmed3(externalRunId) ? { external_run_id: trimmed3(externalRunId) } : {}
|
|
17115
|
+
}
|
|
17116
|
+
};
|
|
17117
|
+
if (trimmed3(title))
|
|
17118
|
+
display.title = trimmed3(title);
|
|
17119
|
+
if (trimmed3(name))
|
|
17120
|
+
display.name = trimmed3(name);
|
|
17121
|
+
if (trimmed3(commandLabel))
|
|
17122
|
+
display.command_label = trimmed3(commandLabel);
|
|
17123
|
+
return {
|
|
17124
|
+
format_version: LATCH_MANIFEST_FORMAT_VERSION,
|
|
17125
|
+
launch: {
|
|
17126
|
+
argv: [shellPath, "-lc", commandString],
|
|
17127
|
+
cwd,
|
|
17128
|
+
env: cleanedEnv,
|
|
17129
|
+
inherit_env: true,
|
|
17130
|
+
size: {
|
|
17131
|
+
cols: Math.max(1, Math.floor(size.cols) || DEFAULT_LATCH_TERMINAL_SIZE.cols),
|
|
17132
|
+
rows: Math.max(1, Math.floor(size.rows) || DEFAULT_LATCH_TERMINAL_SIZE.rows)
|
|
17133
|
+
}
|
|
17134
|
+
},
|
|
17135
|
+
display
|
|
17136
|
+
};
|
|
17137
|
+
}
|
|
17138
|
+
function parseLatchCreateReport(raw) {
|
|
17139
|
+
try {
|
|
17140
|
+
const parsed = JSON.parse(raw);
|
|
17141
|
+
const id = trimmed3(parsed.session?.id);
|
|
17142
|
+
if (!id)
|
|
17143
|
+
return null;
|
|
17144
|
+
const protocolVersion = typeof parsed.protocolVersion === "number" && Number.isFinite(parsed.protocolVersion) ? parsed.protocolVersion : LATCH_MANIFEST_FORMAT_VERSION;
|
|
17145
|
+
return {
|
|
17146
|
+
protocolVersion,
|
|
17147
|
+
session: {
|
|
17148
|
+
id,
|
|
17149
|
+
name: trimmed3(parsed.session?.name) ?? id,
|
|
17150
|
+
state: trimmed3(parsed.session?.state) ?? "running",
|
|
17151
|
+
createdAt: trimmed3(parsed.session?.createdAt) ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
17152
|
+
}
|
|
17153
|
+
};
|
|
17154
|
+
} catch {
|
|
17155
|
+
return null;
|
|
17156
|
+
}
|
|
17157
|
+
}
|
|
17158
|
+
function toExecutionProviderSession({ createReport, executionTargetId, createdAt }) {
|
|
17159
|
+
return {
|
|
17160
|
+
provider: "latch",
|
|
17161
|
+
providerSessionId: createReport.session.id,
|
|
17162
|
+
sessionName: createReport.session.name,
|
|
17163
|
+
executionTargetId: trimmed3(executionTargetId),
|
|
17164
|
+
agentSessionId: null,
|
|
17165
|
+
createdAt: createdAt ?? createReport.session.createdAt,
|
|
17166
|
+
lastObservedState: createReport.session.state
|
|
17167
|
+
};
|
|
17168
|
+
}
|
|
17169
|
+
function existingLatchProviderSession({ latchSessionId, executionTargetId, createdAt = (/* @__PURE__ */ new Date()).toISOString() }) {
|
|
17170
|
+
const providerSessionId = trimmed3(latchSessionId);
|
|
17171
|
+
if (!providerSessionId)
|
|
17172
|
+
return null;
|
|
17173
|
+
return {
|
|
17174
|
+
provider: "latch",
|
|
17175
|
+
providerSessionId,
|
|
17176
|
+
sessionName: null,
|
|
17177
|
+
executionTargetId: trimmed3(executionTargetId),
|
|
17178
|
+
agentSessionId: null,
|
|
17179
|
+
createdAt,
|
|
17180
|
+
lastObservedState: "running"
|
|
17181
|
+
};
|
|
17182
|
+
}
|
|
17183
|
+
function latchViewerFlagForKind(kind) {
|
|
17184
|
+
switch (trimmed3(kind)?.toLowerCase()) {
|
|
17185
|
+
case "iterm":
|
|
17186
|
+
case "iterm2":
|
|
17187
|
+
return "iterm";
|
|
17188
|
+
default:
|
|
17189
|
+
return null;
|
|
17190
|
+
}
|
|
17191
|
+
}
|
|
17192
|
+
function latchAttachCommand({ executable = "latch", providerSessionId }) {
|
|
17193
|
+
return `${trimmed3(executable) ?? "latch"} attach ${providerSessionId}`;
|
|
17194
|
+
}
|
|
17195
|
+
function shouldUseLatchProvider({ providerKind, latchSelectable }) {
|
|
17196
|
+
return trimmed3(providerKind)?.toLowerCase() === "latch" && latchSelectable === true;
|
|
17197
|
+
}
|
|
17198
|
+
var LATCH_MANIFEST_FORMAT_VERSION, DEFAULT_LATCH_TERMINAL_SIZE;
|
|
17199
|
+
var init_latch_launch = __esm({
|
|
17200
|
+
"../packages/core/dist/service/latch-launch.js"() {
|
|
17201
|
+
"use strict";
|
|
17202
|
+
LATCH_MANIFEST_FORMAT_VERSION = 1;
|
|
17203
|
+
DEFAULT_LATCH_TERMINAL_SIZE = { cols: 120, rows: 36 };
|
|
17204
|
+
}
|
|
17205
|
+
});
|
|
17206
|
+
|
|
17207
|
+
// ../packages/core/dist/service/latch-session.js
|
|
17208
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
17209
|
+
function trimmed4(value) {
|
|
17210
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
17211
|
+
}
|
|
17212
|
+
function parseState(value) {
|
|
17213
|
+
switch (trimmed4(value)) {
|
|
17214
|
+
case "running":
|
|
17215
|
+
return "running";
|
|
17216
|
+
case "exited":
|
|
17217
|
+
return "exited";
|
|
17218
|
+
case "stopping":
|
|
17219
|
+
return "stopping";
|
|
17220
|
+
case "lost":
|
|
17221
|
+
return "lost";
|
|
17222
|
+
default:
|
|
17223
|
+
return null;
|
|
17224
|
+
}
|
|
17225
|
+
}
|
|
17226
|
+
function runLatchJson({ executable, args }) {
|
|
17227
|
+
const result = spawnSync2(executable, args, {
|
|
17228
|
+
encoding: "utf8",
|
|
17229
|
+
shell: false,
|
|
17230
|
+
timeout: 1e4,
|
|
17231
|
+
maxBuffer: 1024 * 1024
|
|
17232
|
+
});
|
|
17233
|
+
if (result.error) {
|
|
17234
|
+
throw new LatchSessionCommandError(result.error.message);
|
|
17235
|
+
}
|
|
17236
|
+
if (result.status !== 0) {
|
|
17237
|
+
const detail = (result.stderr || result.stdout || `exit ${result.status ?? "unknown"}`).trim().slice(0, 500);
|
|
17238
|
+
throw new LatchSessionCommandError(detail || "Latch command failed.");
|
|
17239
|
+
}
|
|
17240
|
+
try {
|
|
17241
|
+
const parsed = JSON.parse(result.stdout);
|
|
17242
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
17243
|
+
throw new Error("not an object");
|
|
17244
|
+
}
|
|
17245
|
+
return parsed;
|
|
17246
|
+
} catch {
|
|
17247
|
+
throw new LatchSessionCommandError("Latch returned an invalid JSON response.");
|
|
17248
|
+
}
|
|
17249
|
+
}
|
|
17250
|
+
function inspectLatchSession({ executable = "latch", providerSessionId }) {
|
|
17251
|
+
const sessionId = trimmed4(providerSessionId);
|
|
17252
|
+
if (!sessionId)
|
|
17253
|
+
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
17254
|
+
const report = runLatchJson({
|
|
17255
|
+
executable: trimmed4(executable) ?? "latch",
|
|
17256
|
+
args: ["inspect", sessionId, "--json"]
|
|
17257
|
+
});
|
|
17258
|
+
const state = parseState(report.state);
|
|
17259
|
+
if (!state)
|
|
17260
|
+
throw new LatchSessionCommandError("Latch returned an unsupported session state.");
|
|
17261
|
+
const exit = report.exit && typeof report.exit === "object" && !Array.isArray(report.exit) ? report.exit : null;
|
|
17262
|
+
return {
|
|
17263
|
+
providerSessionId: trimmed4(report.id) ?? sessionId,
|
|
17264
|
+
name: trimmed4(report.name) ?? sessionId,
|
|
17265
|
+
state,
|
|
17266
|
+
exitCode: typeof exit?.code === "number" && Number.isFinite(exit.code) ? exit.code : null,
|
|
17267
|
+
inspectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
17268
|
+
};
|
|
17269
|
+
}
|
|
17270
|
+
function openLatchSession({ executable = "latch", providerSessionId, viewerKind }) {
|
|
17271
|
+
const sessionId = trimmed4(providerSessionId);
|
|
17272
|
+
if (!sessionId)
|
|
17273
|
+
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
17274
|
+
const viewer = latchViewerFlagForKind(viewerKind);
|
|
17275
|
+
if (!viewer) {
|
|
17276
|
+
throw new LatchSessionCommandError(`Latch cannot open the configured viewer "${viewerKind}".`);
|
|
17277
|
+
}
|
|
17278
|
+
const report = runLatchJson({
|
|
17279
|
+
executable: trimmed4(executable) ?? "latch",
|
|
17280
|
+
args: ["open", sessionId, "--with", viewer, "--json"]
|
|
17281
|
+
});
|
|
17282
|
+
if (report.opened !== true) {
|
|
17283
|
+
throw new LatchSessionCommandError(`Latch did not open the ${viewer} viewer.`);
|
|
17284
|
+
}
|
|
17285
|
+
return {
|
|
17286
|
+
providerSessionId: trimmed4(report.id) ?? sessionId,
|
|
17287
|
+
viewer: trimmed4(report.viewer) ?? viewer,
|
|
17288
|
+
opened: true
|
|
17289
|
+
};
|
|
17290
|
+
}
|
|
17291
|
+
function stopLatchSession({ executable = "latch", providerSessionId }) {
|
|
17292
|
+
const sessionId = trimmed4(providerSessionId);
|
|
17293
|
+
if (!sessionId)
|
|
17294
|
+
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
17295
|
+
const report = runLatchJson({
|
|
17296
|
+
executable: trimmed4(executable) ?? "latch",
|
|
17297
|
+
args: ["stop", sessionId, "--json"]
|
|
17298
|
+
});
|
|
17299
|
+
const state = parseState(report.state);
|
|
17300
|
+
if (!state)
|
|
17301
|
+
throw new LatchSessionCommandError("Latch returned an unsupported session state.");
|
|
17302
|
+
return {
|
|
17303
|
+
providerSessionId: trimmed4(report.id) ?? sessionId,
|
|
17304
|
+
state
|
|
17305
|
+
};
|
|
17306
|
+
}
|
|
17307
|
+
var LatchSessionCommandError;
|
|
17308
|
+
var init_latch_session = __esm({
|
|
17309
|
+
"../packages/core/dist/service/latch-session.js"() {
|
|
17310
|
+
"use strict";
|
|
17311
|
+
init_latch_launch();
|
|
17312
|
+
LatchSessionCommandError = class extends Error {
|
|
17313
|
+
constructor(message) {
|
|
17314
|
+
super(message);
|
|
17315
|
+
this.name = "LatchSessionCommandError";
|
|
17316
|
+
}
|
|
17317
|
+
};
|
|
17318
|
+
}
|
|
17319
|
+
});
|
|
17320
|
+
|
|
17321
|
+
// ../packages/core/dist/service/local-target/git-run.js
|
|
17322
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
16789
17323
|
function runGit2(cwd, args) {
|
|
16790
17324
|
try {
|
|
16791
|
-
return
|
|
17325
|
+
return execFileSync4("git", args, {
|
|
16792
17326
|
cwd,
|
|
16793
17327
|
encoding: "utf8",
|
|
16794
17328
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -16800,7 +17334,7 @@ function runGit2(cwd, args) {
|
|
|
16800
17334
|
}
|
|
16801
17335
|
function runGitResult(cwd, args) {
|
|
16802
17336
|
try {
|
|
16803
|
-
const stdout =
|
|
17337
|
+
const stdout = execFileSync4("git", args, {
|
|
16804
17338
|
cwd,
|
|
16805
17339
|
encoding: "utf8",
|
|
16806
17340
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -16823,13 +17357,13 @@ var init_git_run = __esm({
|
|
|
16823
17357
|
});
|
|
16824
17358
|
|
|
16825
17359
|
// ../packages/core/dist/service/local-target/worktree-git.js
|
|
16826
|
-
import { existsSync as
|
|
16827
|
-
import
|
|
17360
|
+
import { existsSync as existsSync17, realpathSync as realpathSync2 } from "node:fs";
|
|
17361
|
+
import path18 from "node:path";
|
|
16828
17362
|
function resolveRealPath(targetPath) {
|
|
16829
17363
|
try {
|
|
16830
17364
|
return realpathSync2.native(targetPath);
|
|
16831
17365
|
} catch {
|
|
16832
|
-
return
|
|
17366
|
+
return path18.resolve(targetPath);
|
|
16833
17367
|
}
|
|
16834
17368
|
}
|
|
16835
17369
|
function worktreeIsDirty(worktreePath) {
|
|
@@ -16859,7 +17393,7 @@ function removeGitWorktree({ primaryRepoPath, worktreePath, force }) {
|
|
|
16859
17393
|
args.push(worktreePath);
|
|
16860
17394
|
runGitResult(primaryRepoPath, args);
|
|
16861
17395
|
runGitResult(primaryRepoPath, ["worktree", "prune"]);
|
|
16862
|
-
return !
|
|
17396
|
+
return !existsSync17(worktreePath);
|
|
16863
17397
|
}
|
|
16864
17398
|
function collectManagedWorktrees({ worktreeRoot, projects }) {
|
|
16865
17399
|
const resolvedRoot = resolveRealPath(worktreeRoot);
|
|
@@ -16867,7 +17401,7 @@ function collectManagedWorktrees({ worktreeRoot, projects }) {
|
|
|
16867
17401
|
const seen = /* @__PURE__ */ new Set();
|
|
16868
17402
|
for (const project of projects) {
|
|
16869
17403
|
const repoPath = project.primaryRepoPath;
|
|
16870
|
-
if (!repoPath || !
|
|
17404
|
+
if (!repoPath || !existsSync17(repoPath))
|
|
16871
17405
|
continue;
|
|
16872
17406
|
const out = runGitResult(repoPath, ["worktree", "list", "--porcelain"]);
|
|
16873
17407
|
if (!out.ok)
|
|
@@ -16878,7 +17412,7 @@ function collectManagedWorktrees({ worktreeRoot, projects }) {
|
|
|
16878
17412
|
if (!currentPath)
|
|
16879
17413
|
return;
|
|
16880
17414
|
const resolved = resolveRealPath(currentPath);
|
|
16881
|
-
const underRoot = resolved === resolvedRoot || resolved.startsWith(resolvedRoot +
|
|
17415
|
+
const underRoot = resolved === resolvedRoot || resolved.startsWith(resolvedRoot + path18.sep);
|
|
16882
17416
|
if (underRoot && !seen.has(resolved)) {
|
|
16883
17417
|
seen.add(resolved);
|
|
16884
17418
|
entries.push({
|
|
@@ -16906,7 +17440,7 @@ function collectManagedWorktrees({ worktreeRoot, projects }) {
|
|
|
16906
17440
|
return entries;
|
|
16907
17441
|
}
|
|
16908
17442
|
function removeManagedWorktree({ path: worktreePath, primaryRepoPath, force }) {
|
|
16909
|
-
const target =
|
|
17443
|
+
const target = path18.resolve(worktreePath);
|
|
16910
17444
|
if (!force && worktreeIsDirty(target)) {
|
|
16911
17445
|
return {
|
|
16912
17446
|
removed: [],
|
|
@@ -16920,7 +17454,7 @@ function purgeManagedWorktrees({ entries }) {
|
|
|
16920
17454
|
const removed = [];
|
|
16921
17455
|
const skipped = [];
|
|
16922
17456
|
for (const entry of entries) {
|
|
16923
|
-
const target =
|
|
17457
|
+
const target = path18.resolve(entry.path);
|
|
16924
17458
|
if (worktreeIsDirty(target)) {
|
|
16925
17459
|
skipped.push({ path: target, reason: "uncommitted changes" });
|
|
16926
17460
|
continue;
|
|
@@ -16945,10 +17479,10 @@ var init_worktree_git = __esm({
|
|
|
16945
17479
|
});
|
|
16946
17480
|
|
|
16947
17481
|
// ../packages/core/dist/service/local-target/branch-actions-git.js
|
|
16948
|
-
import { existsSync as
|
|
17482
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
16949
17483
|
function integrateBranch(input) {
|
|
16950
17484
|
const { branchName, baseBranch, worktreePath, primaryRepoPath } = input;
|
|
16951
|
-
if (!
|
|
17485
|
+
if (!existsSync18(worktreePath)) {
|
|
16952
17486
|
return {
|
|
16953
17487
|
ok: false,
|
|
16954
17488
|
code: "BRANCH_NO_WORKTREE",
|
|
@@ -17022,15 +17556,15 @@ function integrateBranch(input) {
|
|
|
17022
17556
|
}
|
|
17023
17557
|
function commitBranch(input) {
|
|
17024
17558
|
const { branchName, worktreePath } = input;
|
|
17025
|
-
const
|
|
17026
|
-
if (!
|
|
17559
|
+
const trimmed5 = (input.message ?? "").trim();
|
|
17560
|
+
if (!trimmed5) {
|
|
17027
17561
|
return {
|
|
17028
17562
|
ok: false,
|
|
17029
17563
|
code: "BRANCH_COMMIT_MESSAGE_REQUIRED",
|
|
17030
17564
|
message: "A commit message is required."
|
|
17031
17565
|
};
|
|
17032
17566
|
}
|
|
17033
|
-
if (!
|
|
17567
|
+
if (!existsSync18(worktreePath)) {
|
|
17034
17568
|
return {
|
|
17035
17569
|
ok: false,
|
|
17036
17570
|
code: "BRANCH_NO_WORKTREE",
|
|
@@ -17062,7 +17596,7 @@ function commitBranch(input) {
|
|
|
17062
17596
|
detail: staged.stderr || staged.stdout
|
|
17063
17597
|
};
|
|
17064
17598
|
}
|
|
17065
|
-
const commit = runGitResult(worktreePath, ["commit", "-m",
|
|
17599
|
+
const commit = runGitResult(worktreePath, ["commit", "-m", trimmed5]);
|
|
17066
17600
|
if (!commit.ok) {
|
|
17067
17601
|
return {
|
|
17068
17602
|
ok: false,
|
|
@@ -17086,7 +17620,7 @@ function pushParent(input) {
|
|
|
17086
17620
|
};
|
|
17087
17621
|
}
|
|
17088
17622
|
let summary = `Pushed ${baseBranch} to origin.`;
|
|
17089
|
-
if (
|
|
17623
|
+
if (existsSync18(worktreePath) && !worktreeIsDirty(worktreePath)) {
|
|
17090
17624
|
if (removeGitWorktree({ primaryRepoPath, worktreePath, force: false })) {
|
|
17091
17625
|
summary += ` Removed the merged worktree for ${branchName}.`;
|
|
17092
17626
|
}
|
|
@@ -17095,7 +17629,7 @@ function pushParent(input) {
|
|
|
17095
17629
|
}
|
|
17096
17630
|
function publishBranch(input) {
|
|
17097
17631
|
const { branchName, worktreePath, primaryRepoPath } = input;
|
|
17098
|
-
const repo =
|
|
17632
|
+
const repo = existsSync18(worktreePath) ? worktreePath : primaryRepoPath;
|
|
17099
17633
|
const push = runGitResult(repo, ["push", "-u", "origin", branchName]);
|
|
17100
17634
|
if (!push.ok) {
|
|
17101
17635
|
return {
|
|
@@ -17145,7 +17679,7 @@ var init_branch_status_git = __esm({
|
|
|
17145
17679
|
});
|
|
17146
17680
|
|
|
17147
17681
|
// ../packages/core/dist/service/local-target/commit-message-diff-git.js
|
|
17148
|
-
import { existsSync as
|
|
17682
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
17149
17683
|
function collectWorktreeChanges(worktreePath) {
|
|
17150
17684
|
const status = runGitResult(worktreePath, ["status", "--porcelain"]);
|
|
17151
17685
|
const diff = runGitResult(worktreePath, ["diff", "HEAD"]);
|
|
@@ -17161,7 +17695,7 @@ ${diff.stdout}`);
|
|
|
17161
17695
|
return sections.join("\n\n");
|
|
17162
17696
|
}
|
|
17163
17697
|
function gatherCommitMessageDiff(worktreePath) {
|
|
17164
|
-
if (!
|
|
17698
|
+
if (!existsSync19(worktreePath)) {
|
|
17165
17699
|
return {
|
|
17166
17700
|
ok: false,
|
|
17167
17701
|
code: "BRANCH_NO_WORKTREE",
|
|
@@ -17187,10 +17721,10 @@ var init_commit_message_diff_git = __esm({
|
|
|
17187
17721
|
});
|
|
17188
17722
|
|
|
17189
17723
|
// ../packages/core/dist/service/local-target/doctor-checks.js
|
|
17190
|
-
import { execFileSync as
|
|
17724
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
17191
17725
|
function commandOnPath(command, args) {
|
|
17192
17726
|
try {
|
|
17193
|
-
const detail =
|
|
17727
|
+
const detail = execFileSync5(command, args, {
|
|
17194
17728
|
encoding: "utf8",
|
|
17195
17729
|
stdio: ["ignore", "pipe", "ignore"]
|
|
17196
17730
|
}).trim();
|
|
@@ -17222,12 +17756,15 @@ var init_result = __esm({
|
|
|
17222
17756
|
});
|
|
17223
17757
|
|
|
17224
17758
|
// ../packages/core/dist/service/local-target/in-process-provider.js
|
|
17225
|
-
import { existsSync as
|
|
17759
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
17226
17760
|
var InProcessProvider;
|
|
17227
17761
|
var init_in_process_provider = __esm({
|
|
17228
17762
|
"../packages/core/dist/service/local-target/in-process-provider.js"() {
|
|
17229
17763
|
"use strict";
|
|
17230
17764
|
init_git_tree();
|
|
17765
|
+
init_latch_discovery();
|
|
17766
|
+
init_latch_session();
|
|
17767
|
+
init_terminal_profile_types2();
|
|
17231
17768
|
init_branch_actions_git();
|
|
17232
17769
|
init_branch_status_git();
|
|
17233
17770
|
init_commit_message_diff_git();
|
|
@@ -17250,7 +17787,7 @@ var init_in_process_provider = __esm({
|
|
|
17250
17787
|
*/
|
|
17251
17788
|
async observeResource(input) {
|
|
17252
17789
|
const observedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
17253
|
-
const state =
|
|
17790
|
+
const state = existsSync20(input.path) ? "available" : "missing";
|
|
17254
17791
|
return ok(this.target, { state, observedAt });
|
|
17255
17792
|
}
|
|
17256
17793
|
/**
|
|
@@ -17357,6 +17894,50 @@ var init_in_process_provider = __esm({
|
|
|
17357
17894
|
async launchAgent(_input) {
|
|
17358
17895
|
return fail(this.target, "CAPABILITY_NOT_IMPLEMENTED", "Agent launch is owned by the CLI runner (`ovld runner` / `ovld launch`).");
|
|
17359
17896
|
}
|
|
17897
|
+
// ---- routed (coo:702) ------------------------------------------------
|
|
17898
|
+
/**
|
|
17899
|
+
* Read-only Latch probe on this machine. In-process is the transport that can
|
|
17900
|
+
* honestly answer it: the provider only exists here when the caller device is
|
|
17901
|
+
* the execution target, so the probe runs where the agent process would run.
|
|
17902
|
+
*/
|
|
17903
|
+
async discoverLatch(input) {
|
|
17904
|
+
const executable = input.executable?.trim() || DEFAULT_LATCH_EXECUTABLE;
|
|
17905
|
+
try {
|
|
17906
|
+
const result = discoverLatchForExecutionTarget({
|
|
17907
|
+
// A resolved provider carries the target id; the desktop bridge and dev
|
|
17908
|
+
// proxy do not, so they pass the caller's id to share one cache entry
|
|
17909
|
+
// with the runner probe on the same device.
|
|
17910
|
+
executionTargetId: this.target.executionTargetId ?? (input.executionTargetId?.trim() || "local"),
|
|
17911
|
+
executable,
|
|
17912
|
+
cacheFilePath: defaultLatchDiscoveryCachePath(),
|
|
17913
|
+
force: input.force === true
|
|
17914
|
+
});
|
|
17915
|
+
return ok(this.target, result);
|
|
17916
|
+
} catch (error) {
|
|
17917
|
+
return fail(this.target, "TARGET_OPERATION_FAILED", error instanceof Error ? error.message : "Latch discovery failed on this device.");
|
|
17918
|
+
}
|
|
17919
|
+
}
|
|
17920
|
+
async inspectLatchSession(input) {
|
|
17921
|
+
try {
|
|
17922
|
+
return ok(this.target, inspectLatchSession(input));
|
|
17923
|
+
} catch (error) {
|
|
17924
|
+
return fail(this.target, "TARGET_OPERATION_FAILED", error instanceof Error ? error.message : "Could not inspect the Latch session.");
|
|
17925
|
+
}
|
|
17926
|
+
}
|
|
17927
|
+
async openLatchSession(input) {
|
|
17928
|
+
try {
|
|
17929
|
+
return ok(this.target, openLatchSession(input));
|
|
17930
|
+
} catch (error) {
|
|
17931
|
+
return fail(this.target, "TARGET_OPERATION_FAILED", error instanceof Error ? error.message : "Could not open the Latch session.");
|
|
17932
|
+
}
|
|
17933
|
+
}
|
|
17934
|
+
async stopLatchSession(input) {
|
|
17935
|
+
try {
|
|
17936
|
+
return ok(this.target, stopLatchSession(input));
|
|
17937
|
+
} catch (error) {
|
|
17938
|
+
return fail(this.target, "TARGET_OPERATION_FAILED", error instanceof Error ? error.message : "Could not stop the Latch session.");
|
|
17939
|
+
}
|
|
17940
|
+
}
|
|
17360
17941
|
async doctor() {
|
|
17361
17942
|
return ok(this.target, { checks: runLocalTargetDoctorChecks() });
|
|
17362
17943
|
}
|
|
@@ -17497,7 +18078,7 @@ var init_local_target_mutation_runner = __esm({
|
|
|
17497
18078
|
});
|
|
17498
18079
|
|
|
17499
18080
|
// ../packages/core/dist/service/project-resource-key.js
|
|
17500
|
-
import
|
|
18081
|
+
import path19 from "node:path";
|
|
17501
18082
|
function deriveProjectResourceKey({ resourceKey, label, directoryPath }) {
|
|
17502
18083
|
const explicit = resourceKey?.trim();
|
|
17503
18084
|
if (explicit)
|
|
@@ -17505,7 +18086,7 @@ function deriveProjectResourceKey({ resourceKey, label, directoryPath }) {
|
|
|
17505
18086
|
const labelKey = label?.trim();
|
|
17506
18087
|
if (labelKey)
|
|
17507
18088
|
return slugify(labelKey);
|
|
17508
|
-
return slugify(
|
|
18089
|
+
return slugify(path19.basename(path19.resolve(directoryPath)));
|
|
17509
18090
|
}
|
|
17510
18091
|
var init_project_resource_key = __esm({
|
|
17511
18092
|
"../packages/core/dist/service/project-resource-key.js"() {
|
|
@@ -17515,7 +18096,7 @@ var init_project_resource_key = __esm({
|
|
|
17515
18096
|
});
|
|
17516
18097
|
|
|
17517
18098
|
// src/branch-planning.ts
|
|
17518
|
-
import
|
|
18099
|
+
import path20 from "node:path";
|
|
17519
18100
|
function stripCombiningMarks(value) {
|
|
17520
18101
|
return value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
|
|
17521
18102
|
}
|
|
@@ -17548,7 +18129,7 @@ function missionWorktreePath({
|
|
|
17548
18129
|
branch
|
|
17549
18130
|
}) {
|
|
17550
18131
|
const key = resourceKey.trim() || "project";
|
|
17551
|
-
return
|
|
18132
|
+
return path20.join(worktreeRoot, projectSlug || "project", key, branchLeaf(branch));
|
|
17552
18133
|
}
|
|
17553
18134
|
function normalizeRemoteRef(ref) {
|
|
17554
18135
|
return ref.replace(/^origin\//, "").replace(/^refs\/heads\//, "").replace(/^refs\/remotes\/origin\//, "");
|
|
@@ -17622,13 +18203,13 @@ var init_branch_planning = __esm({
|
|
|
17622
18203
|
});
|
|
17623
18204
|
|
|
17624
18205
|
// src/branch-preparation.ts
|
|
17625
|
-
import { execFileSync as
|
|
17626
|
-
import { existsSync as
|
|
17627
|
-
import
|
|
17628
|
-
import
|
|
18206
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
18207
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync10, statSync as statSync5 } from "node:fs";
|
|
18208
|
+
import os4 from "node:os";
|
|
18209
|
+
import path21 from "node:path";
|
|
17629
18210
|
function runGit3(cwd, args, options = {}) {
|
|
17630
18211
|
try {
|
|
17631
|
-
return
|
|
18212
|
+
return execFileSync6("git", args, {
|
|
17632
18213
|
cwd,
|
|
17633
18214
|
encoding: "utf8",
|
|
17634
18215
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -17646,7 +18227,7 @@ function lines(value) {
|
|
|
17646
18227
|
function resolveGitRoot2(workingDirectory) {
|
|
17647
18228
|
const root = runGit3(workingDirectory, ["rev-parse", "--show-toplevel"]);
|
|
17648
18229
|
if (!root) throw new Error(`${workingDirectory} is not inside a git repository.`);
|
|
17649
|
-
return
|
|
18230
|
+
return path21.resolve(root);
|
|
17650
18231
|
}
|
|
17651
18232
|
function repoDefaultBranch(gitRoot) {
|
|
17652
18233
|
const symbolic = runGit3(gitRoot, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"], {
|
|
@@ -17781,9 +18362,9 @@ function missionSequence(mission, missionId) {
|
|
|
17781
18362
|
}
|
|
17782
18363
|
function resolveWorktreeRoot() {
|
|
17783
18364
|
const override = process.env.OVERLORD_WORKTREE_ROOT?.trim();
|
|
17784
|
-
if (override) return
|
|
18365
|
+
if (override) return path21.resolve(override);
|
|
17785
18366
|
const home = process.env.OVLD_HOME?.trim() || process.env.OVERLORD_HOME?.trim();
|
|
17786
|
-
return
|
|
18367
|
+
return path21.join(home ? path21.resolve(home) : path21.join(os4.homedir(), ".ovld"), "worktrees");
|
|
17787
18368
|
}
|
|
17788
18369
|
function ensureBranchRef(gitRoot, decision) {
|
|
17789
18370
|
if (decision.action === "reuse") return;
|
|
@@ -17794,9 +18375,9 @@ function ensureBranchRef(gitRoot, decision) {
|
|
|
17794
18375
|
}
|
|
17795
18376
|
function ensureWorktree(gitRoot, decision) {
|
|
17796
18377
|
ensureBranchRef(gitRoot, decision);
|
|
17797
|
-
|
|
17798
|
-
if (
|
|
17799
|
-
if (!
|
|
18378
|
+
mkdirSync10(path21.dirname(decision.worktreePath), { recursive: true });
|
|
18379
|
+
if (existsSync21(decision.worktreePath)) {
|
|
18380
|
+
if (!statSync5(decision.worktreePath).isDirectory()) {
|
|
17800
18381
|
throw new Error(`Worktree path exists and is not a directory: ${decision.worktreePath}`);
|
|
17801
18382
|
}
|
|
17802
18383
|
const existingBranch = worktreeBranch(decision.worktreePath);
|
|
@@ -17936,7 +18517,7 @@ var init_branch_preparation = __esm({
|
|
|
17936
18517
|
});
|
|
17937
18518
|
|
|
17938
18519
|
// src/discover-project-local.ts
|
|
17939
|
-
import
|
|
18520
|
+
import path22 from "node:path";
|
|
17940
18521
|
async function resolvePreferredExecutionTargetId({
|
|
17941
18522
|
backend
|
|
17942
18523
|
}) {
|
|
@@ -17953,9 +18534,9 @@ function discoverProjectJsonFromFilesystem({
|
|
|
17953
18534
|
workingDirectory,
|
|
17954
18535
|
preferredExecutionTargetId
|
|
17955
18536
|
}) {
|
|
17956
|
-
let current =
|
|
18537
|
+
let current = path22.resolve(workingDirectory);
|
|
17957
18538
|
while (true) {
|
|
17958
|
-
const projectJsonPath =
|
|
18539
|
+
const projectJsonPath = path22.join(current, ".overlord", "project.json");
|
|
17959
18540
|
const raw = readProjectJsonLink(projectJsonPath, { preferredExecutionTargetId });
|
|
17960
18541
|
if (raw) {
|
|
17961
18542
|
return {
|
|
@@ -17965,7 +18546,7 @@ function discoverProjectJsonFromFilesystem({
|
|
|
17965
18546
|
isPrimary: raw.isPrimary
|
|
17966
18547
|
};
|
|
17967
18548
|
}
|
|
17968
|
-
const parent =
|
|
18549
|
+
const parent = path22.dirname(current);
|
|
17969
18550
|
if (parent === current) break;
|
|
17970
18551
|
current = parent;
|
|
17971
18552
|
}
|
|
@@ -17975,16 +18556,16 @@ async function resolveProjectByIdOrName({
|
|
|
17975
18556
|
backend,
|
|
17976
18557
|
projectRef
|
|
17977
18558
|
}) {
|
|
17978
|
-
const
|
|
18559
|
+
const trimmed5 = projectRef.trim();
|
|
17979
18560
|
try {
|
|
17980
|
-
return await backend.get(`/api/projects/${encodeURIComponent(
|
|
18561
|
+
return await backend.get(`/api/projects/${encodeURIComponent(trimmed5)}`);
|
|
17981
18562
|
} catch (error) {
|
|
17982
18563
|
if (!(error instanceof CliError) || !/project not found/i.test(error.message)) throw error;
|
|
17983
18564
|
}
|
|
17984
18565
|
const projects = await listAccessibleProjects({ backend });
|
|
17985
|
-
const match = projects.find((project) => project.name ===
|
|
18566
|
+
const match = projects.find((project) => project.name === trimmed5) ?? projects.find((project) => project.slug === trimmed5);
|
|
17986
18567
|
if (!match) {
|
|
17987
|
-
throw new CliError({ message: `Project not found: ${
|
|
18568
|
+
throw new CliError({ message: `Project not found: ${trimmed5}` });
|
|
17988
18569
|
}
|
|
17989
18570
|
return match;
|
|
17990
18571
|
}
|
|
@@ -18025,7 +18606,7 @@ async function discoverProjectOnClient({
|
|
|
18025
18606
|
const resolvedLocal = localWithTarget ?? local;
|
|
18026
18607
|
if (!resolvedLocal) {
|
|
18027
18608
|
throw new CliError({
|
|
18028
|
-
message: `No linked Overlord project found for ${
|
|
18609
|
+
message: `No linked Overlord project found for ${path22.resolve(workingDirectory)}. Run \`ovld add-cwd\` or \`ovld create-project\`.`
|
|
18029
18610
|
});
|
|
18030
18611
|
}
|
|
18031
18612
|
const project = await resolveProjectByIdOrName({ backend, projectRef: resolvedLocal.projectId });
|
|
@@ -18045,6 +18626,134 @@ var init_discover_project_local = __esm({
|
|
|
18045
18626
|
}
|
|
18046
18627
|
});
|
|
18047
18628
|
|
|
18629
|
+
// src/latch-discovery.ts
|
|
18630
|
+
import path23 from "node:path";
|
|
18631
|
+
function latchDiscoveryCachePath(dataDir = resolveGlobalDataDir()) {
|
|
18632
|
+
return path23.join(dataDir, LATCH_DISCOVERY_CACHE_FILENAME);
|
|
18633
|
+
}
|
|
18634
|
+
function discoverLatchOnThisDevice({
|
|
18635
|
+
executionTargetId,
|
|
18636
|
+
executable = DEFAULT_LATCH_EXECUTABLE,
|
|
18637
|
+
force = false
|
|
18638
|
+
}) {
|
|
18639
|
+
return discoverLatchForExecutionTarget({
|
|
18640
|
+
executionTargetId,
|
|
18641
|
+
executable,
|
|
18642
|
+
cacheFilePath: latchDiscoveryCachePath(),
|
|
18643
|
+
force
|
|
18644
|
+
});
|
|
18645
|
+
}
|
|
18646
|
+
var init_latch_discovery2 = __esm({
|
|
18647
|
+
"src/latch-discovery.ts"() {
|
|
18648
|
+
"use strict";
|
|
18649
|
+
init_latch_discovery();
|
|
18650
|
+
init_terminal_profile_types2();
|
|
18651
|
+
init_config();
|
|
18652
|
+
}
|
|
18653
|
+
});
|
|
18654
|
+
|
|
18655
|
+
// src/latch-launch.ts
|
|
18656
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
18657
|
+
function spawnLatchJson({
|
|
18658
|
+
executable,
|
|
18659
|
+
args,
|
|
18660
|
+
stdin
|
|
18661
|
+
}) {
|
|
18662
|
+
const result = spawnSync3(executable, args, {
|
|
18663
|
+
encoding: "utf8",
|
|
18664
|
+
input: stdin,
|
|
18665
|
+
env: process.env,
|
|
18666
|
+
maxBuffer: 2 * 1024 * 1024
|
|
18667
|
+
});
|
|
18668
|
+
return {
|
|
18669
|
+
status: result.status,
|
|
18670
|
+
stdout: result.stdout ?? "",
|
|
18671
|
+
stderr: result.stderr ?? ""
|
|
18672
|
+
};
|
|
18673
|
+
}
|
|
18674
|
+
function createLatchSession({
|
|
18675
|
+
executable = DEFAULT_LATCH_EXECUTABLE,
|
|
18676
|
+
commandString,
|
|
18677
|
+
cwd,
|
|
18678
|
+
env,
|
|
18679
|
+
title,
|
|
18680
|
+
name,
|
|
18681
|
+
commandLabel,
|
|
18682
|
+
externalRunId,
|
|
18683
|
+
executionTargetId,
|
|
18684
|
+
shell = process.env.SHELL?.trim() || "/bin/bash"
|
|
18685
|
+
}) {
|
|
18686
|
+
const manifest = buildLatchCreateManifest({
|
|
18687
|
+
commandString,
|
|
18688
|
+
shell,
|
|
18689
|
+
cwd,
|
|
18690
|
+
env,
|
|
18691
|
+
title,
|
|
18692
|
+
name,
|
|
18693
|
+
commandLabel,
|
|
18694
|
+
externalRunId
|
|
18695
|
+
});
|
|
18696
|
+
const result = spawnLatchJson({
|
|
18697
|
+
executable,
|
|
18698
|
+
args: ["create", "--manifest-file", "-", "--json"],
|
|
18699
|
+
stdin: `${JSON.stringify(manifest)}
|
|
18700
|
+
`
|
|
18701
|
+
});
|
|
18702
|
+
if (result.status !== 0) {
|
|
18703
|
+
const detail = (result.stderr || result.stdout || `exit ${result.status ?? "null"}`).trim();
|
|
18704
|
+
throw new Error(`latch create failed: ${detail}`);
|
|
18705
|
+
}
|
|
18706
|
+
const report = parseLatchCreateReport(result.stdout);
|
|
18707
|
+
if (!report) {
|
|
18708
|
+
throw new Error(
|
|
18709
|
+
`latch create returned unusable JSON: ${(result.stdout || result.stderr).trim() || "(empty)"}`
|
|
18710
|
+
);
|
|
18711
|
+
}
|
|
18712
|
+
return {
|
|
18713
|
+
report,
|
|
18714
|
+
providerSession: toExecutionProviderSession({
|
|
18715
|
+
createReport: report,
|
|
18716
|
+
executionTargetId
|
|
18717
|
+
}),
|
|
18718
|
+
executable
|
|
18719
|
+
};
|
|
18720
|
+
}
|
|
18721
|
+
function openLatchViewer({
|
|
18722
|
+
executable = DEFAULT_LATCH_EXECUTABLE,
|
|
18723
|
+
providerSessionId,
|
|
18724
|
+
viewerKind
|
|
18725
|
+
}) {
|
|
18726
|
+
const viewer = latchViewerFlagForKind(viewerKind);
|
|
18727
|
+
const attachCommand = latchAttachCommand({ executable, providerSessionId });
|
|
18728
|
+
if (!viewer) {
|
|
18729
|
+
return {
|
|
18730
|
+
ok: false,
|
|
18731
|
+
warning: `Latch has no viewer for kind "${viewerKind ?? "unknown"}"; session is running \u2014 attach with: ${attachCommand}`,
|
|
18732
|
+
attachCommand
|
|
18733
|
+
};
|
|
18734
|
+
}
|
|
18735
|
+
const result = spawnLatchJson({
|
|
18736
|
+
executable,
|
|
18737
|
+
args: ["open", providerSessionId, "--with", viewer, "--json"]
|
|
18738
|
+
});
|
|
18739
|
+
if (result.status !== 0) {
|
|
18740
|
+
const detail = (result.stderr || result.stdout || `exit ${result.status ?? "null"}`).trim();
|
|
18741
|
+
return {
|
|
18742
|
+
ok: false,
|
|
18743
|
+
warning: `latch open failed (${detail}); session is running \u2014 attach with: ${attachCommand}`,
|
|
18744
|
+
attachCommand
|
|
18745
|
+
};
|
|
18746
|
+
}
|
|
18747
|
+
return { ok: true, viewer };
|
|
18748
|
+
}
|
|
18749
|
+
var init_latch_launch2 = __esm({
|
|
18750
|
+
"src/latch-launch.ts"() {
|
|
18751
|
+
"use strict";
|
|
18752
|
+
init_latch_launch();
|
|
18753
|
+
init_terminal_profile_types2();
|
|
18754
|
+
}
|
|
18755
|
+
});
|
|
18756
|
+
|
|
18048
18757
|
// src/pre-launch.ts
|
|
18049
18758
|
function substitutePreLaunchVariables(commands, variables) {
|
|
18050
18759
|
return commands.map(
|
|
@@ -18072,10 +18781,10 @@ function primaryResourcePath(projectResources) {
|
|
|
18072
18781
|
for (const entry of projectResources) {
|
|
18073
18782
|
if (!entry || typeof entry !== "object") continue;
|
|
18074
18783
|
const record = entry;
|
|
18075
|
-
const
|
|
18076
|
-
if (!
|
|
18077
|
-
if (record.isPrimary === true) return
|
|
18078
|
-
if (record.isCurrent === true && !currentPath) currentPath =
|
|
18784
|
+
const path34 = typeof record.path === "string" ? record.path.trim() : "";
|
|
18785
|
+
if (!path34) continue;
|
|
18786
|
+
if (record.isPrimary === true) return path34;
|
|
18787
|
+
if (record.isCurrent === true && !currentPath) currentPath = path34;
|
|
18079
18788
|
}
|
|
18080
18789
|
return currentPath;
|
|
18081
18790
|
}
|
|
@@ -18175,7 +18884,7 @@ function terminalInnerCommand({
|
|
|
18175
18884
|
const invocation = withPreLaunchCommands(agentCommand, preLaunchCommands);
|
|
18176
18885
|
return `cd ${shellQuote2(workingDirectory)} && ${exports}; ${invocation}`;
|
|
18177
18886
|
}
|
|
18178
|
-
function
|
|
18887
|
+
function composeAgentTerminalCommand({
|
|
18179
18888
|
command,
|
|
18180
18889
|
args,
|
|
18181
18890
|
workingDirectory,
|
|
@@ -18184,8 +18893,25 @@ function terminalLaunchScriptContent({
|
|
|
18184
18893
|
preLaunchCommands
|
|
18185
18894
|
}) {
|
|
18186
18895
|
const agentCommand = agentShellCommand({ command, args, preCommand });
|
|
18896
|
+
return terminalInnerCommand({ workingDirectory, agentCommand, extraEnv, preLaunchCommands });
|
|
18897
|
+
}
|
|
18898
|
+
function terminalLaunchScriptContent({
|
|
18899
|
+
command,
|
|
18900
|
+
args,
|
|
18901
|
+
workingDirectory,
|
|
18902
|
+
preCommand,
|
|
18903
|
+
extraEnv = {},
|
|
18904
|
+
preLaunchCommands
|
|
18905
|
+
}) {
|
|
18187
18906
|
return `#!/usr/bin/env bash
|
|
18188
|
-
${
|
|
18907
|
+
${composeAgentTerminalCommand({
|
|
18908
|
+
command,
|
|
18909
|
+
args,
|
|
18910
|
+
workingDirectory,
|
|
18911
|
+
preCommand,
|
|
18912
|
+
extraEnv,
|
|
18913
|
+
preLaunchCommands
|
|
18914
|
+
})}
|
|
18189
18915
|
`;
|
|
18190
18916
|
}
|
|
18191
18917
|
function terminalScriptCommand(scriptPath) {
|
|
@@ -18426,9 +19152,9 @@ var init_terminal_launcher = __esm({
|
|
|
18426
19152
|
});
|
|
18427
19153
|
|
|
18428
19154
|
// src/launch.ts
|
|
18429
|
-
import { spawnSync as
|
|
18430
|
-
import { chmodSync as chmodSync4, writeFileSync as
|
|
18431
|
-
import
|
|
19155
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
19156
|
+
import { chmodSync as chmodSync4, writeFileSync as writeFileSync9 } from "node:fs";
|
|
19157
|
+
import path24 from "node:path";
|
|
18432
19158
|
function overlordLaunchEnv({
|
|
18433
19159
|
backendUrl,
|
|
18434
19160
|
missionId,
|
|
@@ -18594,7 +19320,7 @@ function launchScriptPath({
|
|
|
18594
19320
|
executionRequestId
|
|
18595
19321
|
}) {
|
|
18596
19322
|
const requestPart = executionRequestId ? safeLaunchScriptPart(executionRequestId) : `${process.pid}`;
|
|
18597
|
-
return
|
|
19323
|
+
return path24.join(tmpDir, `launch-${safeLaunchScriptPart(displayId)}-${requestPart}.sh`);
|
|
18598
19324
|
}
|
|
18599
19325
|
async function buildLaunchPlan({
|
|
18600
19326
|
runtime,
|
|
@@ -18603,12 +19329,12 @@ async function buildLaunchPlan({
|
|
|
18603
19329
|
const context = await loadMissionContext({ runtime, missionId: options.missionId });
|
|
18604
19330
|
pruneStaleProjectTmp({ workingDirectory: options.workingDirectory, create: true });
|
|
18605
19331
|
const tmpDir = ensureProjectTmpDir(options.workingDirectory);
|
|
18606
|
-
const contextFile =
|
|
19332
|
+
const contextFile = path24.join(
|
|
18607
19333
|
tmpDir,
|
|
18608
19334
|
`mission-${context.displayId.replace(/[^a-zA-Z0-9_-]/g, "-")}.md`
|
|
18609
19335
|
);
|
|
18610
19336
|
const launchContext = context.launchContext;
|
|
18611
|
-
|
|
19337
|
+
writeFileSync9(contextFile, `${launchContext}
|
|
18612
19338
|
`);
|
|
18613
19339
|
const projectResources = await loadProjectResourcesForLaunch({
|
|
18614
19340
|
runtime,
|
|
@@ -18653,13 +19379,21 @@ async function buildLaunchPlan({
|
|
|
18653
19379
|
contextFile,
|
|
18654
19380
|
launchMessage: `Attach to ovld mission ${context.displayId}, then immediately execute ${context.title}. Do not wait for more instructions.`
|
|
18655
19381
|
});
|
|
19382
|
+
const latchCommandString = composeAgentTerminalCommand({
|
|
19383
|
+
command: command.command,
|
|
19384
|
+
args: command.args,
|
|
19385
|
+
workingDirectory: options.workingDirectory,
|
|
19386
|
+
preCommand: options.preCommand,
|
|
19387
|
+
extraEnv: exportedEnv,
|
|
19388
|
+
preLaunchCommands
|
|
19389
|
+
});
|
|
18656
19390
|
const terminalScriptPath = options.terminalLauncher?.trim() ? launchScriptPath({
|
|
18657
19391
|
tmpDir,
|
|
18658
19392
|
displayId: context.displayId,
|
|
18659
19393
|
executionRequestId: options.executionRequestId
|
|
18660
19394
|
}) : null;
|
|
18661
19395
|
if (terminalScriptPath) {
|
|
18662
|
-
|
|
19396
|
+
writeFileSync9(
|
|
18663
19397
|
terminalScriptPath,
|
|
18664
19398
|
terminalLaunchScriptContent({
|
|
18665
19399
|
command: command.command,
|
|
@@ -18691,7 +19425,11 @@ async function buildLaunchPlan({
|
|
|
18691
19425
|
contextFile,
|
|
18692
19426
|
workingDirectory: options.workingDirectory,
|
|
18693
19427
|
execution,
|
|
18694
|
-
env: exportedEnv
|
|
19428
|
+
env: exportedEnv,
|
|
19429
|
+
latchCommandString,
|
|
19430
|
+
launchSession: options.launchSession ?? null,
|
|
19431
|
+
missionTitle: options.missionTitle ?? context.title,
|
|
19432
|
+
missionDisplayId: options.missionDisplayId ?? context.displayId
|
|
18695
19433
|
};
|
|
18696
19434
|
}
|
|
18697
19435
|
async function launchAgent({
|
|
@@ -18707,26 +19445,126 @@ async function launchAgent({
|
|
|
18707
19445
|
...tmpEnvFor(options.workingDirectory),
|
|
18708
19446
|
...plan.env
|
|
18709
19447
|
};
|
|
19448
|
+
const snapshot = options.launchSession ?? plan.launchSession ?? null;
|
|
19449
|
+
const providerKind = snapshot?.executionProvider.kind ?? "direct";
|
|
19450
|
+
const executable = snapshot?.executionProvider.executable ?? "latch";
|
|
19451
|
+
let providerFallbackWarning = null;
|
|
19452
|
+
let useLatch = false;
|
|
19453
|
+
const existingProviderSession = providerKind === "latch" ? existingLatchProviderSession({
|
|
19454
|
+
latchSessionId: process.env.LATCH_SESSION_ID,
|
|
19455
|
+
executionTargetId: options.executionTargetId
|
|
19456
|
+
}) : null;
|
|
19457
|
+
if (existingProviderSession && plan.latchCommandString) {
|
|
19458
|
+
const shell = process.env.SHELL?.trim() || "/bin/bash";
|
|
19459
|
+
const result2 = spawnSync4(shell, ["-lc", plan.latchCommandString], {
|
|
19460
|
+
cwd: options.workingDirectory,
|
|
19461
|
+
env,
|
|
19462
|
+
stdio: "inherit"
|
|
19463
|
+
});
|
|
19464
|
+
return {
|
|
19465
|
+
plan: {
|
|
19466
|
+
...plan,
|
|
19467
|
+
execution: {
|
|
19468
|
+
command: shell,
|
|
19469
|
+
args: ["-lc", plan.latchCommandString],
|
|
19470
|
+
useShell: false,
|
|
19471
|
+
terminal: null,
|
|
19472
|
+
display: `Latch session ${existingProviderSession.providerSessionId} (inline) \u203A ${plan.latchCommandString}`
|
|
19473
|
+
}
|
|
19474
|
+
},
|
|
19475
|
+
status: result2.status,
|
|
19476
|
+
signal: result2.signal,
|
|
19477
|
+
providerSession: existingProviderSession,
|
|
19478
|
+
viewerOpen: null,
|
|
19479
|
+
providerFallbackWarning
|
|
19480
|
+
};
|
|
19481
|
+
}
|
|
19482
|
+
if (providerKind === "latch") {
|
|
19483
|
+
if (!options.executionTargetId) {
|
|
19484
|
+
providerFallbackWarning = "Latch provider selected but no execution target id is available; falling back to direct launch.";
|
|
19485
|
+
} else {
|
|
19486
|
+
const discovery = discoverLatchOnThisDevice({
|
|
19487
|
+
executionTargetId: options.executionTargetId,
|
|
19488
|
+
executable
|
|
19489
|
+
});
|
|
19490
|
+
useLatch = shouldUseLatchProvider({
|
|
19491
|
+
providerKind,
|
|
19492
|
+
latchSelectable: discovery.latchSelectable
|
|
19493
|
+
});
|
|
19494
|
+
if (!useLatch) {
|
|
19495
|
+
providerFallbackWarning = discovery.state === "not_installed" ? `Latch is not installed on this execution target (${discovery.installCommand}); falling back to direct launch.` : discovery.state === "incompatible" ? `Latch is incompatible (${discovery.missingCapability}: ${discovery.detail}); falling back to direct launch.` : "Latch is unavailable; falling back to direct launch.";
|
|
19496
|
+
}
|
|
19497
|
+
}
|
|
19498
|
+
}
|
|
19499
|
+
if (useLatch && plan.latchCommandString) {
|
|
19500
|
+
const created = createLatchSession({
|
|
19501
|
+
executable,
|
|
19502
|
+
commandString: plan.latchCommandString,
|
|
19503
|
+
cwd: options.workingDirectory,
|
|
19504
|
+
env: plan.env,
|
|
19505
|
+
title: plan.missionTitle,
|
|
19506
|
+
name: plan.missionDisplayId,
|
|
19507
|
+
commandLabel: options.agent,
|
|
19508
|
+
externalRunId: options.executionRequestId,
|
|
19509
|
+
executionTargetId: options.executionTargetId
|
|
19510
|
+
});
|
|
19511
|
+
let viewerOpen = null;
|
|
19512
|
+
const openOnLaunch = snapshot?.viewer.openOnLaunch !== false;
|
|
19513
|
+
if (openOnLaunch) {
|
|
19514
|
+
viewerOpen = openLatchViewer({
|
|
19515
|
+
executable,
|
|
19516
|
+
providerSessionId: created.providerSession.providerSessionId,
|
|
19517
|
+
viewerKind: snapshot?.viewer.kind ?? "iterm"
|
|
19518
|
+
});
|
|
19519
|
+
}
|
|
19520
|
+
return {
|
|
19521
|
+
plan: {
|
|
19522
|
+
...plan,
|
|
19523
|
+
execution: {
|
|
19524
|
+
command: executable,
|
|
19525
|
+
args: ["create", "--manifest-file", "-", "--json"],
|
|
19526
|
+
useShell: false,
|
|
19527
|
+
terminal: snapshot?.viewer.launcher ?? null,
|
|
19528
|
+
display: `latch create \u203A ${plan.latchCommandString}`
|
|
19529
|
+
}
|
|
19530
|
+
},
|
|
19531
|
+
status: 0,
|
|
19532
|
+
signal: null,
|
|
19533
|
+
providerSession: created.providerSession,
|
|
19534
|
+
viewerOpen,
|
|
19535
|
+
providerFallbackWarning
|
|
19536
|
+
};
|
|
19537
|
+
}
|
|
18710
19538
|
const { execution } = plan;
|
|
18711
|
-
const result = execution.useShell ?
|
|
19539
|
+
const result = execution.useShell ? spawnSync4(execution.command, {
|
|
18712
19540
|
cwd: options.workingDirectory,
|
|
18713
19541
|
env,
|
|
18714
19542
|
shell: true,
|
|
18715
19543
|
stdio: "inherit"
|
|
18716
|
-
}) :
|
|
19544
|
+
}) : spawnSync4(execution.command, execution.args, {
|
|
18717
19545
|
cwd: options.workingDirectory,
|
|
18718
19546
|
env,
|
|
18719
19547
|
stdio: "inherit"
|
|
18720
19548
|
});
|
|
18721
|
-
return {
|
|
19549
|
+
return {
|
|
19550
|
+
plan,
|
|
19551
|
+
status: result.status,
|
|
19552
|
+
signal: result.signal,
|
|
19553
|
+
providerSession: null,
|
|
19554
|
+
viewerOpen: null,
|
|
19555
|
+
providerFallbackWarning
|
|
19556
|
+
};
|
|
18722
19557
|
}
|
|
18723
19558
|
var AGENT_HISTORY_EXCLUDED_EVENT_TYPES, EXECUTION_DIRECTIVE;
|
|
18724
19559
|
var init_launch = __esm({
|
|
18725
19560
|
"src/launch.ts"() {
|
|
18726
19561
|
"use strict";
|
|
18727
19562
|
init_dist2();
|
|
19563
|
+
init_latch_launch();
|
|
18728
19564
|
init_channel();
|
|
18729
19565
|
init_agent_binaries();
|
|
19566
|
+
init_latch_discovery2();
|
|
19567
|
+
init_latch_launch2();
|
|
18730
19568
|
init_pre_launch();
|
|
18731
19569
|
init_project_tmp();
|
|
18732
19570
|
init_terminal_launcher();
|
|
@@ -18740,8 +19578,8 @@ var init_launch = __esm({
|
|
|
18740
19578
|
});
|
|
18741
19579
|
|
|
18742
19580
|
// src/launch-bootstrap.ts
|
|
18743
|
-
import { existsSync as
|
|
18744
|
-
import
|
|
19581
|
+
import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
|
|
19582
|
+
import path25 from "node:path";
|
|
18745
19583
|
function firstCapture(match) {
|
|
18746
19584
|
if (!match) return null;
|
|
18747
19585
|
const value = match[1] ?? match[2] ?? match[3] ?? null;
|
|
@@ -18762,15 +19600,15 @@ function recoverLaunchBootstrapFromProjectTmp({
|
|
|
18762
19600
|
const trimmedMission = missionId.trim();
|
|
18763
19601
|
if (!trimmedMission) return empty;
|
|
18764
19602
|
const tmpDir = projectTmpDir(workingDirectory);
|
|
18765
|
-
if (!
|
|
19603
|
+
if (!existsSync22(tmpDir)) return empty;
|
|
18766
19604
|
const prefix = `launch-${safeMissionPart(trimmedMission)}-`;
|
|
18767
19605
|
let newest = null;
|
|
18768
19606
|
try {
|
|
18769
19607
|
for (const name of readdirSync4(tmpDir)) {
|
|
18770
19608
|
if (!name.startsWith(prefix) || !name.endsWith(".sh")) continue;
|
|
18771
|
-
const filePath =
|
|
19609
|
+
const filePath = path25.join(tmpDir, name);
|
|
18772
19610
|
try {
|
|
18773
|
-
const mtimeMs =
|
|
19611
|
+
const mtimeMs = statSync6(filePath).mtimeMs;
|
|
18774
19612
|
if (!newest || mtimeMs > newest.mtimeMs) {
|
|
18775
19613
|
newest = { path: filePath, mtimeMs };
|
|
18776
19614
|
}
|
|
@@ -18783,7 +19621,7 @@ function recoverLaunchBootstrapFromProjectTmp({
|
|
|
18783
19621
|
if (!newest) return empty;
|
|
18784
19622
|
let contents = "";
|
|
18785
19623
|
try {
|
|
18786
|
-
contents =
|
|
19624
|
+
contents = readFileSync16(newest.path, "utf8");
|
|
18787
19625
|
} catch {
|
|
18788
19626
|
return empty;
|
|
18789
19627
|
}
|
|
@@ -18804,8 +19642,8 @@ var init_launch_bootstrap = __esm({
|
|
|
18804
19642
|
});
|
|
18805
19643
|
|
|
18806
19644
|
// src/org-setup.ts
|
|
18807
|
-
import { readFileSync as
|
|
18808
|
-
import
|
|
19645
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
19646
|
+
import path26 from "node:path";
|
|
18809
19647
|
import { createInterface as createInterface3 } from "node:readline";
|
|
18810
19648
|
function suggestSlug(name) {
|
|
18811
19649
|
const cleaned = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -18820,8 +19658,8 @@ function promptText({
|
|
|
18820
19658
|
return new Promise((resolve) => {
|
|
18821
19659
|
rl.question(`${question}${suffix}: `, (answer) => {
|
|
18822
19660
|
rl.close();
|
|
18823
|
-
const
|
|
18824
|
-
resolve(
|
|
19661
|
+
const trimmed5 = answer.trim();
|
|
19662
|
+
resolve(trimmed5 || defaultValue || "");
|
|
18825
19663
|
});
|
|
18826
19664
|
});
|
|
18827
19665
|
}
|
|
@@ -18884,12 +19722,12 @@ async function runOrgSetupCommand({
|
|
|
18884
19722
|
let logoWarning = null;
|
|
18885
19723
|
if (logoPath) {
|
|
18886
19724
|
try {
|
|
18887
|
-
const resolvedPath =
|
|
18888
|
-
const bytes =
|
|
19725
|
+
const resolvedPath = path26.resolve(logoPath);
|
|
19726
|
+
const bytes = readFileSync17(resolvedPath);
|
|
18889
19727
|
const stored = await runtime.backend.postRaw({
|
|
18890
19728
|
path: "/api/uploads/organization-images",
|
|
18891
19729
|
body: bytes,
|
|
18892
|
-
filename:
|
|
19730
|
+
filename: path26.basename(resolvedPath)
|
|
18893
19731
|
});
|
|
18894
19732
|
await runtime.backend.patch({
|
|
18895
19733
|
path: `/api/organizations/${encodeURIComponent(organization.id)}`,
|
|
@@ -19384,17 +20222,17 @@ var init_protocol_help = __esm({
|
|
|
19384
20222
|
|
|
19385
20223
|
// src/vcs-sessions.ts
|
|
19386
20224
|
import { createHash as createHash8 } from "node:crypto";
|
|
19387
|
-
import { existsSync as
|
|
19388
|
-
import
|
|
20225
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "node:fs";
|
|
20226
|
+
import path27 from "node:path";
|
|
19389
20227
|
function manifestPath2(workingDirectory) {
|
|
19390
|
-
const key = createHash8("sha256").update(
|
|
19391
|
-
return
|
|
20228
|
+
const key = createHash8("sha256").update(path27.resolve(workingDirectory)).digest("hex");
|
|
20229
|
+
return path27.join(resolveGlobalDataDir(), "vcs-sessions", `${key}.json`);
|
|
19392
20230
|
}
|
|
19393
20231
|
function readEntries(workingDirectory) {
|
|
19394
20232
|
try {
|
|
19395
20233
|
const target = manifestPath2(workingDirectory);
|
|
19396
|
-
if (!
|
|
19397
|
-
const raw = JSON.parse(
|
|
20234
|
+
if (!existsSync23(target)) return [];
|
|
20235
|
+
const raw = JSON.parse(readFileSync18(target, "utf8"));
|
|
19398
20236
|
if (!Array.isArray(raw.entries)) return [];
|
|
19399
20237
|
const now = Date.now();
|
|
19400
20238
|
return raw.entries.flatMap((entry) => {
|
|
@@ -19413,8 +20251,8 @@ function readEntries(workingDirectory) {
|
|
|
19413
20251
|
function writeEntries(workingDirectory, entries) {
|
|
19414
20252
|
try {
|
|
19415
20253
|
const target = manifestPath2(workingDirectory);
|
|
19416
|
-
|
|
19417
|
-
|
|
20254
|
+
mkdirSync11(path27.dirname(target), { recursive: true });
|
|
20255
|
+
writeFileSync10(target, JSON.stringify({ entries }));
|
|
19418
20256
|
} catch {
|
|
19419
20257
|
}
|
|
19420
20258
|
}
|
|
@@ -19464,23 +20302,23 @@ var init_vcs_sessions = __esm({
|
|
|
19464
20302
|
});
|
|
19465
20303
|
|
|
19466
20304
|
// src/vcs.ts
|
|
19467
|
-
import { execFileSync as
|
|
20305
|
+
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
19468
20306
|
import { createHash as createHash9 } from "node:crypto";
|
|
19469
20307
|
import {
|
|
19470
|
-
existsSync as
|
|
19471
|
-
mkdirSync as
|
|
20308
|
+
existsSync as existsSync24,
|
|
20309
|
+
mkdirSync as mkdirSync12,
|
|
19472
20310
|
readdirSync as readdirSync5,
|
|
19473
|
-
readFileSync as
|
|
20311
|
+
readFileSync as readFileSync19,
|
|
19474
20312
|
realpathSync as realpathSync3,
|
|
19475
20313
|
rmSync as rmSync5,
|
|
19476
|
-
writeFileSync as
|
|
20314
|
+
writeFileSync as writeFileSync11
|
|
19477
20315
|
} from "node:fs";
|
|
19478
|
-
import
|
|
20316
|
+
import path28 from "node:path";
|
|
19479
20317
|
function normalizePath(filePath) {
|
|
19480
20318
|
return filePath.replace(/\\/g, "/").trim();
|
|
19481
20319
|
}
|
|
19482
20320
|
function sameWorkingDirectory(left, right) {
|
|
19483
|
-
return typeof left === "string" &&
|
|
20321
|
+
return typeof left === "string" && path28.resolve(left) === path28.resolve(right);
|
|
19484
20322
|
}
|
|
19485
20323
|
function parsePorcelainLine(line) {
|
|
19486
20324
|
const trimmedEnd = line.replace(/\s+$/, "");
|
|
@@ -19500,7 +20338,7 @@ function hashWorktreeFile({
|
|
|
19500
20338
|
filePath
|
|
19501
20339
|
}) {
|
|
19502
20340
|
try {
|
|
19503
|
-
return
|
|
20341
|
+
return execFileSync7("git", ["hash-object", filePath], {
|
|
19504
20342
|
cwd: workingDirectory,
|
|
19505
20343
|
encoding: "utf8",
|
|
19506
20344
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -19511,7 +20349,7 @@ function hashWorktreeFile({
|
|
|
19511
20349
|
}
|
|
19512
20350
|
function readChangedFiles(workingDirectory) {
|
|
19513
20351
|
try {
|
|
19514
|
-
const output =
|
|
20352
|
+
const output = execFileSync7("git", ["status", "--porcelain"], {
|
|
19515
20353
|
cwd: workingDirectory,
|
|
19516
20354
|
encoding: "utf8",
|
|
19517
20355
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -19531,13 +20369,13 @@ function sessionKeyHash({
|
|
|
19531
20369
|
workingDirectory,
|
|
19532
20370
|
missionId
|
|
19533
20371
|
}) {
|
|
19534
|
-
return createHash9("sha256").update(`${
|
|
20372
|
+
return createHash9("sha256").update(`${path28.resolve(workingDirectory)}\0${missionId}`).digest("hex");
|
|
19535
20373
|
}
|
|
19536
20374
|
function baselineFilePath({
|
|
19537
20375
|
workingDirectory,
|
|
19538
20376
|
missionId
|
|
19539
20377
|
}) {
|
|
19540
|
-
return
|
|
20378
|
+
return path28.join(
|
|
19541
20379
|
resolveGlobalDataDir(),
|
|
19542
20380
|
"vcs-baselines",
|
|
19543
20381
|
`${sessionKeyHash({ workingDirectory, missionId })}.json`
|
|
@@ -19547,7 +20385,7 @@ function touchedFilesPath({
|
|
|
19547
20385
|
workingDirectory,
|
|
19548
20386
|
missionId
|
|
19549
20387
|
}) {
|
|
19550
|
-
return
|
|
20388
|
+
return path28.join(
|
|
19551
20389
|
resolveGlobalDataDir(),
|
|
19552
20390
|
"vcs-touched",
|
|
19553
20391
|
`${sessionKeyHash({ workingDirectory, missionId })}.json`
|
|
@@ -19557,7 +20395,7 @@ function rationaleNotesPath({
|
|
|
19557
20395
|
workingDirectory,
|
|
19558
20396
|
missionId
|
|
19559
20397
|
}) {
|
|
19560
|
-
return
|
|
20398
|
+
return path28.join(
|
|
19561
20399
|
resolveGlobalDataDir(),
|
|
19562
20400
|
"vcs-rationale-notes",
|
|
19563
20401
|
`${sessionKeyHash({ workingDirectory, missionId })}.json`
|
|
@@ -19567,7 +20405,7 @@ function bashSnapshotPath({
|
|
|
19567
20405
|
workingDirectory,
|
|
19568
20406
|
missionId
|
|
19569
20407
|
}) {
|
|
19570
|
-
return
|
|
20408
|
+
return path28.join(
|
|
19571
20409
|
resolveGlobalDataDir(),
|
|
19572
20410
|
"vcs-touched",
|
|
19573
20411
|
`${sessionKeyHash({ workingDirectory, missionId })}.bash-snapshot.json`
|
|
@@ -19579,8 +20417,8 @@ function readBashSnapshot({
|
|
|
19579
20417
|
}) {
|
|
19580
20418
|
try {
|
|
19581
20419
|
const target = bashSnapshotPath({ workingDirectory, missionId });
|
|
19582
|
-
if (!
|
|
19583
|
-
const raw = JSON.parse(
|
|
20420
|
+
if (!existsSync24(target)) return /* @__PURE__ */ new Map();
|
|
20421
|
+
const raw = JSON.parse(readFileSync19(target, "utf8"));
|
|
19584
20422
|
const byPath = /* @__PURE__ */ new Map();
|
|
19585
20423
|
if (Array.isArray(raw.files)) {
|
|
19586
20424
|
for (const entry of raw.files) {
|
|
@@ -19605,8 +20443,8 @@ function writeBashSnapshot({
|
|
|
19605
20443
|
}) {
|
|
19606
20444
|
try {
|
|
19607
20445
|
const target = bashSnapshotPath({ workingDirectory, missionId });
|
|
19608
|
-
|
|
19609
|
-
|
|
20446
|
+
mkdirSync12(path28.dirname(target), { recursive: true });
|
|
20447
|
+
writeFileSync11(target, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString(), files }));
|
|
19610
20448
|
} catch {
|
|
19611
20449
|
}
|
|
19612
20450
|
}
|
|
@@ -19639,12 +20477,12 @@ function recordBashObservedChanges({
|
|
|
19639
20477
|
}
|
|
19640
20478
|
}
|
|
19641
20479
|
function normalizeAbsolute(filePath) {
|
|
19642
|
-
const resolved =
|
|
20480
|
+
const resolved = path28.resolve(filePath);
|
|
19643
20481
|
try {
|
|
19644
20482
|
return realpathSync3(resolved).replace(/\\/g, "/");
|
|
19645
20483
|
} catch {
|
|
19646
20484
|
try {
|
|
19647
|
-
return
|
|
20485
|
+
return path28.join(realpathSync3(path28.dirname(resolved)), path28.basename(resolved)).replace(/\\/g, "/");
|
|
19648
20486
|
} catch {
|
|
19649
20487
|
return resolved.replace(/\\/g, "/");
|
|
19650
20488
|
}
|
|
@@ -19652,7 +20490,7 @@ function normalizeAbsolute(filePath) {
|
|
|
19652
20490
|
}
|
|
19653
20491
|
function gitRepoRoot(workingDirectory) {
|
|
19654
20492
|
try {
|
|
19655
|
-
const root =
|
|
20493
|
+
const root = execFileSync7("git", ["rev-parse", "--show-toplevel"], {
|
|
19656
20494
|
cwd: workingDirectory,
|
|
19657
20495
|
encoding: "utf8",
|
|
19658
20496
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -19671,7 +20509,7 @@ function resetTouchedFiles({
|
|
|
19671
20509
|
touchedFilesPath({ workingDirectory, missionId }),
|
|
19672
20510
|
bashSnapshotPath({ workingDirectory, missionId })
|
|
19673
20511
|
]) {
|
|
19674
|
-
if (
|
|
20512
|
+
if (existsSync24(target)) rmSync5(target);
|
|
19675
20513
|
}
|
|
19676
20514
|
} catch {
|
|
19677
20515
|
}
|
|
@@ -19682,14 +20520,14 @@ function resetRationaleNotes({
|
|
|
19682
20520
|
}) {
|
|
19683
20521
|
try {
|
|
19684
20522
|
const target = rationaleNotesPath({ workingDirectory, missionId });
|
|
19685
|
-
if (
|
|
20523
|
+
if (existsSync24(target)) rmSync5(target);
|
|
19686
20524
|
} catch {
|
|
19687
20525
|
}
|
|
19688
20526
|
}
|
|
19689
20527
|
function truncateNoteText(value, max = 500) {
|
|
19690
|
-
const
|
|
19691
|
-
if (!
|
|
19692
|
-
return
|
|
20528
|
+
const trimmed5 = (value ?? "").replace(/\s+/g, " ").trim();
|
|
20529
|
+
if (!trimmed5) return null;
|
|
20530
|
+
return trimmed5.length > max ? `${trimmed5.slice(0, max - 1)}...` : trimmed5;
|
|
19693
20531
|
}
|
|
19694
20532
|
function readRationaleNotes({
|
|
19695
20533
|
workingDirectory,
|
|
@@ -19697,8 +20535,8 @@ function readRationaleNotes({
|
|
|
19697
20535
|
}) {
|
|
19698
20536
|
try {
|
|
19699
20537
|
const target = rationaleNotesPath({ workingDirectory, missionId });
|
|
19700
|
-
if (!
|
|
19701
|
-
const raw = JSON.parse(
|
|
20538
|
+
if (!existsSync24(target)) return [];
|
|
20539
|
+
const raw = JSON.parse(readFileSync19(target, "utf8"));
|
|
19702
20540
|
if (!Array.isArray(raw.notes)) return [];
|
|
19703
20541
|
return raw.notes.flatMap((note) => {
|
|
19704
20542
|
if (typeof note !== "object" || note === null || typeof note.filePath !== "string") {
|
|
@@ -19732,7 +20570,7 @@ function recordRationaleNotes({
|
|
|
19732
20570
|
intent: truncateNoteText(note.intent),
|
|
19733
20571
|
transcriptContext: truncateNoteText(note.transcriptContext)
|
|
19734
20572
|
})).filter((note) => note.filePath).map((note) => {
|
|
19735
|
-
const absolute = normalizeAbsolute(
|
|
20573
|
+
const absolute = normalizeAbsolute(path28.resolve(workingDirectory, note.filePath));
|
|
19736
20574
|
return {
|
|
19737
20575
|
filePath: absolute,
|
|
19738
20576
|
toolName: note.toolName,
|
|
@@ -19740,17 +20578,17 @@ function recordRationaleNotes({
|
|
|
19740
20578
|
transcriptContext: note.transcriptContext,
|
|
19741
20579
|
contentHash: hashWorktreeFile({
|
|
19742
20580
|
workingDirectory,
|
|
19743
|
-
filePath:
|
|
20581
|
+
filePath: path28.relative(workingDirectory, absolute)
|
|
19744
20582
|
}),
|
|
19745
20583
|
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
19746
20584
|
};
|
|
19747
20585
|
});
|
|
19748
20586
|
if (additions.length === 0) return;
|
|
19749
20587
|
const target = rationaleNotesPath({ workingDirectory, missionId });
|
|
19750
|
-
|
|
20588
|
+
mkdirSync12(path28.dirname(target), { recursive: true });
|
|
19751
20589
|
const prior = readRationaleNotes({ workingDirectory, missionId });
|
|
19752
20590
|
const notesToKeep = [...prior, ...additions].slice(-200);
|
|
19753
|
-
|
|
20591
|
+
writeFileSync11(
|
|
19754
20592
|
target,
|
|
19755
20593
|
JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString(), notes: notesToKeep })
|
|
19756
20594
|
);
|
|
@@ -19763,16 +20601,16 @@ function recordTouchedFiles({
|
|
|
19763
20601
|
files
|
|
19764
20602
|
}) {
|
|
19765
20603
|
try {
|
|
19766
|
-
const additions = files.map((filePath) => (filePath ?? "").trim()).filter(Boolean).map((filePath) => normalizeAbsolute(
|
|
20604
|
+
const additions = files.map((filePath) => (filePath ?? "").trim()).filter(Boolean).map((filePath) => normalizeAbsolute(path28.resolve(workingDirectory, filePath)));
|
|
19767
20605
|
if (additions.length === 0) return;
|
|
19768
20606
|
const target = touchedFilesPath({ workingDirectory, missionId });
|
|
19769
|
-
|
|
20607
|
+
mkdirSync12(path28.dirname(target), { recursive: true });
|
|
19770
20608
|
const existing = readTouchedLog({ workingDirectory, missionId })?.paths ?? /* @__PURE__ */ new Set();
|
|
19771
20609
|
for (const filePath of additions) existing.add(filePath);
|
|
19772
|
-
|
|
20610
|
+
writeFileSync11(
|
|
19773
20611
|
target,
|
|
19774
20612
|
JSON.stringify({
|
|
19775
|
-
workingDirectory:
|
|
20613
|
+
workingDirectory: path28.resolve(workingDirectory),
|
|
19776
20614
|
missionId,
|
|
19777
20615
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19778
20616
|
paths: Array.from(existing)
|
|
@@ -19785,7 +20623,7 @@ function hasTouchedFilesLog({
|
|
|
19785
20623
|
workingDirectory,
|
|
19786
20624
|
missionId
|
|
19787
20625
|
}) {
|
|
19788
|
-
return
|
|
20626
|
+
return existsSync24(touchedFilesPath({ workingDirectory, missionId }));
|
|
19789
20627
|
}
|
|
19790
20628
|
function readTouchedLog({
|
|
19791
20629
|
workingDirectory,
|
|
@@ -19793,8 +20631,8 @@ function readTouchedLog({
|
|
|
19793
20631
|
}) {
|
|
19794
20632
|
try {
|
|
19795
20633
|
const target = touchedFilesPath({ workingDirectory, missionId });
|
|
19796
|
-
if (!
|
|
19797
|
-
const raw = JSON.parse(
|
|
20634
|
+
if (!existsSync24(target)) return null;
|
|
20635
|
+
const raw = JSON.parse(readFileSync19(target, "utf8"));
|
|
19798
20636
|
const result = /* @__PURE__ */ new Set();
|
|
19799
20637
|
if (Array.isArray(raw.paths)) {
|
|
19800
20638
|
for (const entry of raw.paths) {
|
|
@@ -19827,14 +20665,14 @@ function writeBaseline({
|
|
|
19827
20665
|
}) {
|
|
19828
20666
|
try {
|
|
19829
20667
|
const target = baselineFilePath({ workingDirectory, missionId });
|
|
19830
|
-
|
|
20668
|
+
mkdirSync12(path28.dirname(target), { recursive: true });
|
|
19831
20669
|
const snapshot = {
|
|
19832
|
-
workingDirectory:
|
|
20670
|
+
workingDirectory: path28.resolve(workingDirectory),
|
|
19833
20671
|
missionId,
|
|
19834
20672
|
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19835
20673
|
files: snapshotBaselineFiles({ workingDirectory, files })
|
|
19836
20674
|
};
|
|
19837
|
-
|
|
20675
|
+
writeFileSync11(target, JSON.stringify(snapshot));
|
|
19838
20676
|
} catch {
|
|
19839
20677
|
}
|
|
19840
20678
|
}
|
|
@@ -19846,13 +20684,13 @@ function readPeerTouchedClaims({
|
|
|
19846
20684
|
readActiveSessions(workingDirectory).map((entry) => entry.missionId.trim()).filter(Boolean)
|
|
19847
20685
|
);
|
|
19848
20686
|
if (activeMissionIds.size === 0) return [];
|
|
19849
|
-
const directory =
|
|
19850
|
-
if (!
|
|
20687
|
+
const directory = path28.join(resolveGlobalDataDir(), "vcs-touched");
|
|
20688
|
+
if (!existsSync24(directory)) return [];
|
|
19851
20689
|
const claims = [];
|
|
19852
20690
|
for (const name of readdirSync5(directory)) {
|
|
19853
20691
|
if (!name.endsWith(".json") || name.endsWith(".bash-snapshot.json")) continue;
|
|
19854
20692
|
try {
|
|
19855
|
-
const raw = JSON.parse(
|
|
20693
|
+
const raw = JSON.parse(readFileSync19(path28.join(directory, name), "utf8"));
|
|
19856
20694
|
const candidateMissionId = typeof raw.missionId === "string" && raw.missionId.trim() ? raw.missionId.trim() : null;
|
|
19857
20695
|
if (!candidateMissionId || candidateMissionId === missionId) continue;
|
|
19858
20696
|
if (!activeMissionIds.has(candidateMissionId)) continue;
|
|
@@ -19877,8 +20715,8 @@ function readBaselineSnapshot({
|
|
|
19877
20715
|
}) {
|
|
19878
20716
|
try {
|
|
19879
20717
|
const target = baselineFilePath({ workingDirectory, missionId });
|
|
19880
|
-
if (!
|
|
19881
|
-
const raw = JSON.parse(
|
|
20718
|
+
if (!existsSync24(target)) return /* @__PURE__ */ new Map();
|
|
20719
|
+
const raw = JSON.parse(readFileSync19(target, "utf8"));
|
|
19882
20720
|
if (Array.isArray(raw.files)) {
|
|
19883
20721
|
const byPath = /* @__PURE__ */ new Map();
|
|
19884
20722
|
for (const entry of raw.files) {
|
|
@@ -19972,10 +20810,10 @@ function compileIgnorePattern(rawPattern) {
|
|
|
19972
20810
|
}
|
|
19973
20811
|
function loadIgnoreRules(repoRoot) {
|
|
19974
20812
|
try {
|
|
19975
|
-
const target =
|
|
19976
|
-
if (!
|
|
20813
|
+
const target = path28.join(repoRoot, OVERLORD_IGNORE_FILENAME);
|
|
20814
|
+
if (!existsSync24(target)) return [];
|
|
19977
20815
|
const rules = [];
|
|
19978
|
-
for (const rawLine of
|
|
20816
|
+
for (const rawLine of readFileSync19(target, "utf8").split("\n")) {
|
|
19979
20817
|
const line = rawLine.replace(/\r$/, "").trim();
|
|
19980
20818
|
if (!line || line.startsWith("#")) continue;
|
|
19981
20819
|
const rule = compileIgnorePattern(line);
|
|
@@ -20009,7 +20847,7 @@ function filterRunAttributableChanges({
|
|
|
20009
20847
|
return [];
|
|
20010
20848
|
}
|
|
20011
20849
|
if (!touched) return [{ filePath: entry.filePath, vcsStatus: entry.vcsStatus }];
|
|
20012
|
-
const absolute = normalizeAbsolute(
|
|
20850
|
+
const absolute = normalizeAbsolute(path28.resolve(repoRoot, entry.filePath));
|
|
20013
20851
|
if (touched.paths.has(absolute)) {
|
|
20014
20852
|
return [
|
|
20015
20853
|
{
|
|
@@ -20040,7 +20878,7 @@ function filterRunAttributableChanges({
|
|
|
20040
20878
|
});
|
|
20041
20879
|
}
|
|
20042
20880
|
function titleFromPath(filePath) {
|
|
20043
|
-
const base =
|
|
20881
|
+
const base = path28.basename(filePath).replace(/\.[^.]+$/, "");
|
|
20044
20882
|
const words = base.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").trim();
|
|
20045
20883
|
if (!words) return `Update ${filePath}`;
|
|
20046
20884
|
return `Update ${words.replace(/\b\w/g, (char) => char.toUpperCase())}`;
|
|
@@ -20063,7 +20901,7 @@ function draftChangeRationalesFromNotes({
|
|
|
20063
20901
|
if (notes.length === 0 || files.length === 0) return [];
|
|
20064
20902
|
const repoRoot = gitRepoRoot(workingDirectory) ?? workingDirectory;
|
|
20065
20903
|
return files.flatMap((file) => {
|
|
20066
|
-
const absolute = normalizeAbsolute(
|
|
20904
|
+
const absolute = normalizeAbsolute(path28.resolve(repoRoot, file.filePath));
|
|
20067
20905
|
const currentHash = hashWorktreeFile({ workingDirectory, filePath: file.filePath });
|
|
20068
20906
|
const note = latestRelevantNote({ notes, filePath: absolute, currentHash });
|
|
20069
20907
|
if (!note) return [];
|
|
@@ -20103,17 +20941,17 @@ var init_vcs = __esm({
|
|
|
20103
20941
|
});
|
|
20104
20942
|
|
|
20105
20943
|
// src/record-touched.ts
|
|
20106
|
-
import { readFileSync as
|
|
20107
|
-
import
|
|
20944
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
20945
|
+
import path29 from "node:path";
|
|
20108
20946
|
function collectCandidates(toolInput) {
|
|
20109
20947
|
const counts = /* @__PURE__ */ new Map();
|
|
20110
20948
|
const order = [];
|
|
20111
20949
|
const bump = (raw, amount) => {
|
|
20112
20950
|
if (typeof raw !== "string") return;
|
|
20113
|
-
const
|
|
20114
|
-
if (!
|
|
20115
|
-
if (!counts.has(
|
|
20116
|
-
counts.set(
|
|
20951
|
+
const trimmed5 = raw.trim();
|
|
20952
|
+
if (!trimmed5) return;
|
|
20953
|
+
if (!counts.has(trimmed5)) order.push(trimmed5);
|
|
20954
|
+
counts.set(trimmed5, (counts.get(trimmed5) ?? 0) + amount);
|
|
20117
20955
|
};
|
|
20118
20956
|
bump(toolInput.file_path, 1);
|
|
20119
20957
|
bump(toolInput.notebook_path, 1);
|
|
@@ -20153,7 +20991,7 @@ function editIntent({
|
|
|
20153
20991
|
function recentAssistantContext(transcriptPath) {
|
|
20154
20992
|
if (typeof transcriptPath !== "string" || !transcriptPath.trim()) return null;
|
|
20155
20993
|
try {
|
|
20156
|
-
const lines2 =
|
|
20994
|
+
const lines2 = readFileSync20(transcriptPath, "utf8").split("\n").slice(-200);
|
|
20157
20995
|
for (let index = lines2.length - 1; index >= 0; index -= 1) {
|
|
20158
20996
|
const line = lines2[index]?.trim();
|
|
20159
20997
|
if (!line) continue;
|
|
@@ -20203,7 +21041,7 @@ function recordTouchedFromPayload({
|
|
|
20203
21041
|
const toolInput = toolInputRaw && typeof toolInputRaw === "object" ? toolInputRaw : {};
|
|
20204
21042
|
const toolName = typeof payload.tool_name === "string" && payload.tool_name.trim() ? payload.tool_name.trim() : "file edit";
|
|
20205
21043
|
const cwd = typeof payload.cwd === "string" && payload.cwd.trim() ? payload.cwd.trim() : fallbackCwd;
|
|
20206
|
-
const workingDirectory =
|
|
21044
|
+
const workingDirectory = path29.resolve(cwd);
|
|
20207
21045
|
const trimmedOverride = missionOverride?.trim();
|
|
20208
21046
|
let missionId;
|
|
20209
21047
|
let ambiguous = false;
|
|
@@ -20307,23 +21145,23 @@ var init_resource_observations = __esm({
|
|
|
20307
21145
|
|
|
20308
21146
|
// src/runner-identity.ts
|
|
20309
21147
|
import { randomUUID } from "node:crypto";
|
|
20310
|
-
import { existsSync as
|
|
21148
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync12 } from "node:fs";
|
|
20311
21149
|
import { hostname as hostname4 } from "node:os";
|
|
20312
|
-
import
|
|
21150
|
+
import path30 from "node:path";
|
|
20313
21151
|
function envValue(name) {
|
|
20314
21152
|
const value = process.env[name]?.trim();
|
|
20315
21153
|
return value && value.length > 0 ? value : null;
|
|
20316
21154
|
}
|
|
20317
21155
|
function runnerInstanceStatePath(dataDir = resolveGlobalDataDir()) {
|
|
20318
|
-
return
|
|
21156
|
+
return path30.join(dataDir, RUNNER_INSTANCE_STATE_FILENAME);
|
|
20319
21157
|
}
|
|
20320
21158
|
function resolveRunnerInstanceId(dataDir = resolveGlobalDataDir()) {
|
|
20321
21159
|
const pinned = envValue("OVERLORD_RUNNER_INSTANCE_ID");
|
|
20322
21160
|
if (pinned) return pinned;
|
|
20323
21161
|
const statePath = runnerInstanceStatePath(dataDir);
|
|
20324
|
-
if (
|
|
21162
|
+
if (existsSync25(statePath)) {
|
|
20325
21163
|
try {
|
|
20326
|
-
const parsed = JSON.parse(
|
|
21164
|
+
const parsed = JSON.parse(readFileSync21(statePath, "utf8"));
|
|
20327
21165
|
if (typeof parsed.runnerInstanceId === "string" && parsed.runnerInstanceId.trim()) {
|
|
20328
21166
|
return parsed.runnerInstanceId.trim();
|
|
20329
21167
|
}
|
|
@@ -20332,8 +21170,8 @@ function resolveRunnerInstanceId(dataDir = resolveGlobalDataDir()) {
|
|
|
20332
21170
|
}
|
|
20333
21171
|
const runnerInstanceId = randomUUID();
|
|
20334
21172
|
try {
|
|
20335
|
-
|
|
20336
|
-
|
|
21173
|
+
mkdirSync13(path30.dirname(statePath), { recursive: true });
|
|
21174
|
+
writeFileSync12(statePath, `${JSON.stringify({ runnerInstanceId }, null, 2)}
|
|
20337
21175
|
`, { mode: 384 });
|
|
20338
21176
|
} catch {
|
|
20339
21177
|
}
|
|
@@ -20375,12 +21213,12 @@ var init_runner_identity = __esm({
|
|
|
20375
21213
|
|
|
20376
21214
|
// src/runner-service.ts
|
|
20377
21215
|
import { execFile } from "node:child_process";
|
|
20378
|
-
import { chmodSync as chmodSync5, existsSync as
|
|
20379
|
-
import
|
|
20380
|
-
import
|
|
21216
|
+
import { chmodSync as chmodSync5, existsSync as existsSync26, mkdirSync as mkdirSync14, readFileSync as readFileSync22, rmSync as rmSync6, writeFileSync as writeFileSync13 } from "node:fs";
|
|
21217
|
+
import os5 from "node:os";
|
|
21218
|
+
import path31 from "node:path";
|
|
20381
21219
|
import { promisify } from "node:util";
|
|
20382
21220
|
function writeServiceFile(filePath, contents) {
|
|
20383
|
-
|
|
21221
|
+
writeFileSync13(filePath, contents, { mode: 384 });
|
|
20384
21222
|
chmodSync5(filePath, 384);
|
|
20385
21223
|
}
|
|
20386
21224
|
function emptyRunnerServiceState() {
|
|
@@ -20399,21 +21237,21 @@ function emptyRunnerServiceState() {
|
|
|
20399
21237
|
};
|
|
20400
21238
|
}
|
|
20401
21239
|
function runnerServiceStatePath(dataDir = resolveGlobalDataDir()) {
|
|
20402
|
-
return
|
|
21240
|
+
return path31.join(dataDir, RUNNER_SERVICE_STATE_FILENAME);
|
|
20403
21241
|
}
|
|
20404
21242
|
function readRunnerServiceState(dataDir = resolveGlobalDataDir()) {
|
|
20405
21243
|
const filePath = runnerServiceStatePath(dataDir);
|
|
20406
|
-
if (!
|
|
21244
|
+
if (!existsSync26(filePath)) return emptyRunnerServiceState();
|
|
20407
21245
|
try {
|
|
20408
|
-
const parsed = JSON.parse(
|
|
21246
|
+
const parsed = JSON.parse(readFileSync22(filePath, "utf8"));
|
|
20409
21247
|
return { ...emptyRunnerServiceState(), ...parsed };
|
|
20410
21248
|
} catch {
|
|
20411
21249
|
return emptyRunnerServiceState();
|
|
20412
21250
|
}
|
|
20413
21251
|
}
|
|
20414
21252
|
function writeRunnerServiceState(state, dataDir = resolveGlobalDataDir()) {
|
|
20415
|
-
|
|
20416
|
-
|
|
21253
|
+
mkdirSync14(dataDir, { recursive: true });
|
|
21254
|
+
writeFileSync13(runnerServiceStatePath(dataDir), `${JSON.stringify(state, null, 2)}
|
|
20417
21255
|
`, "utf8");
|
|
20418
21256
|
}
|
|
20419
21257
|
function patchRunnerServiceState(patch, dataDir = resolveGlobalDataDir()) {
|
|
@@ -20422,13 +21260,13 @@ function patchRunnerServiceState(patch, dataDir = resolveGlobalDataDir()) {
|
|
|
20422
21260
|
return next;
|
|
20423
21261
|
}
|
|
20424
21262
|
function runnerFocusStatePath(dataDir = resolveGlobalDataDir()) {
|
|
20425
|
-
return
|
|
21263
|
+
return path31.join(dataDir, RUNNER_FOCUS_STATE_FILENAME);
|
|
20426
21264
|
}
|
|
20427
21265
|
function readDesktopFocusState(dataDir = resolveGlobalDataDir()) {
|
|
20428
21266
|
const filePath = runnerFocusStatePath(dataDir);
|
|
20429
|
-
if (!
|
|
21267
|
+
if (!existsSync26(filePath)) return { lastFocusedAt: null };
|
|
20430
21268
|
try {
|
|
20431
|
-
const parsed = JSON.parse(
|
|
21269
|
+
const parsed = JSON.parse(readFileSync22(filePath, "utf8"));
|
|
20432
21270
|
return { lastFocusedAt: parsed.lastFocusedAt ?? null };
|
|
20433
21271
|
} catch {
|
|
20434
21272
|
return { lastFocusedAt: null };
|
|
@@ -20458,17 +21296,17 @@ function nextRunnerLastError(pollError) {
|
|
|
20458
21296
|
}
|
|
20459
21297
|
function resolveOverlordAppInvocation({
|
|
20460
21298
|
platform: platform2 = process.platform,
|
|
20461
|
-
homedir: homedir2 =
|
|
20462
|
-
exists =
|
|
21299
|
+
homedir: homedir2 = os5.homedir(),
|
|
21300
|
+
exists = existsSync26
|
|
20463
21301
|
} = {}) {
|
|
20464
21302
|
if (platform2 !== "darwin") return null;
|
|
20465
21303
|
const appDirs = [
|
|
20466
21304
|
"/Applications/Overlord.app",
|
|
20467
|
-
|
|
21305
|
+
path31.join(homedir2, "Applications", "Overlord.app")
|
|
20468
21306
|
];
|
|
20469
21307
|
for (const appDir of appDirs) {
|
|
20470
|
-
const program =
|
|
20471
|
-
const script =
|
|
21308
|
+
const program = path31.join(appDir, "Contents", "MacOS", "Overlord");
|
|
21309
|
+
const script = path31.join(appDir, "Contents", "Resources", "cli", "bin", "ovld.mjs");
|
|
20472
21310
|
if (exists(program) && exists(script)) {
|
|
20473
21311
|
return { program, args: [script, "runner", "supervise"], runAsElectronNode: true };
|
|
20474
21312
|
}
|
|
@@ -20480,7 +21318,7 @@ function resolveOvldInvocation(argv = process.argv, execPath = process.execPath)
|
|
|
20480
21318
|
if (override) {
|
|
20481
21319
|
return { program: override, args: ["runner", "supervise"] };
|
|
20482
21320
|
}
|
|
20483
|
-
const scriptPath = argv[1] ?
|
|
21321
|
+
const scriptPath = argv[1] ? path31.resolve(argv[1]) : "";
|
|
20484
21322
|
if (process.env.ELECTRON_RUN_AS_NODE) {
|
|
20485
21323
|
return scriptPath ? { program: execPath, args: [scriptPath, "runner", "supervise"], runAsElectronNode: true } : { program: execPath, args: ["runner", "supervise"], runAsElectronNode: true };
|
|
20486
21324
|
}
|
|
@@ -20513,7 +21351,7 @@ function buildRunnerServiceEnv({
|
|
|
20513
21351
|
PATH: process.env.PATH?.trim() || "/usr/local/bin:/usr/bin:/bin"
|
|
20514
21352
|
};
|
|
20515
21353
|
const home = overlordHome?.trim() || process.env.OVLD_HOME?.trim();
|
|
20516
|
-
if (home) env.OVLD_HOME =
|
|
21354
|
+
if (home) env.OVLD_HOME = path31.resolve(home);
|
|
20517
21355
|
const token = process.env.OVERLORD_USER_TOKEN?.trim() || process.env.OVLD_USER_TOKEN?.trim();
|
|
20518
21356
|
if (token) env.OVERLORD_USER_TOKEN = token;
|
|
20519
21357
|
if (runAsElectronNode || process.env.ELECTRON_RUN_AS_NODE) env.ELECTRON_RUN_AS_NODE = "1";
|
|
@@ -20552,9 +21390,9 @@ ${envEntries}
|
|
|
20552
21390
|
<key>KeepAlive</key>
|
|
20553
21391
|
<true/>
|
|
20554
21392
|
<key>StandardOutPath</key>
|
|
20555
|
-
<string>${xmlEscape(
|
|
21393
|
+
<string>${xmlEscape(path31.join(logDir, "runner-service.out.log"))}</string>
|
|
20556
21394
|
<key>StandardErrorPath</key>
|
|
20557
|
-
<string>${xmlEscape(
|
|
21395
|
+
<string>${xmlEscape(path31.join(logDir, "runner-service.err.log"))}</string>
|
|
20558
21396
|
<key>ProcessType</key>
|
|
20559
21397
|
<string>Background</string>
|
|
20560
21398
|
</dict>
|
|
@@ -20585,12 +21423,12 @@ WantedBy=default.target
|
|
|
20585
21423
|
`;
|
|
20586
21424
|
}
|
|
20587
21425
|
function launchAgentsDir() {
|
|
20588
|
-
return
|
|
21426
|
+
return path31.join(os5.homedir(), "Library", "LaunchAgents");
|
|
20589
21427
|
}
|
|
20590
21428
|
function systemdUserDir() {
|
|
20591
21429
|
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
20592
|
-
const base = xdg ?
|
|
20593
|
-
return
|
|
21430
|
+
const base = xdg ? path31.resolve(xdg) : path31.join(os5.homedir(), ".config");
|
|
21431
|
+
return path31.join(base, "systemd", "user");
|
|
20594
21432
|
}
|
|
20595
21433
|
async function runCommand(program, args) {
|
|
20596
21434
|
const { stdout } = await execFileAsync(program, args);
|
|
@@ -20619,19 +21457,19 @@ var init_runner_service = __esm({
|
|
|
20619
21457
|
kind = "launchd";
|
|
20620
21458
|
identifier = LAUNCHD_LABEL;
|
|
20621
21459
|
unitPath() {
|
|
20622
|
-
return
|
|
21460
|
+
return path31.join(launchAgentsDir(), `${LAUNCHD_LABEL}.plist`);
|
|
20623
21461
|
}
|
|
20624
21462
|
render(opts) {
|
|
20625
21463
|
return renderLaunchdPlist({
|
|
20626
21464
|
label: LAUNCHD_LABEL,
|
|
20627
21465
|
invocation: opts.invocation,
|
|
20628
21466
|
env: opts.env,
|
|
20629
|
-
logDir:
|
|
21467
|
+
logDir: path31.join(resolveGlobalDataDir(), "logs")
|
|
20630
21468
|
});
|
|
20631
21469
|
}
|
|
20632
21470
|
async install(opts) {
|
|
20633
|
-
|
|
20634
|
-
|
|
21471
|
+
mkdirSync14(launchAgentsDir(), { recursive: true });
|
|
21472
|
+
mkdirSync14(path31.join(resolveGlobalDataDir(), "logs"), { recursive: true });
|
|
20635
21473
|
writeServiceFile(this.unitPath(), this.render(opts));
|
|
20636
21474
|
if (opts.autoStart) await this.start();
|
|
20637
21475
|
}
|
|
@@ -20661,10 +21499,10 @@ var init_runner_service = __esm({
|
|
|
20661
21499
|
await this.stop();
|
|
20662
21500
|
} catch {
|
|
20663
21501
|
}
|
|
20664
|
-
if (
|
|
21502
|
+
if (existsSync26(this.unitPath())) rmSync6(this.unitPath());
|
|
20665
21503
|
}
|
|
20666
21504
|
async status() {
|
|
20667
|
-
const installed =
|
|
21505
|
+
const installed = existsSync26(this.unitPath());
|
|
20668
21506
|
try {
|
|
20669
21507
|
const { stdout } = await runCommand("launchctl", ["list"]);
|
|
20670
21508
|
const line = stdout.split("\n").find((row) => row.includes(LAUNCHD_LABEL));
|
|
@@ -20680,13 +21518,13 @@ var init_runner_service = __esm({
|
|
|
20680
21518
|
kind = "systemd";
|
|
20681
21519
|
identifier = `${SYSTEMD_UNIT_NAME}.service`;
|
|
20682
21520
|
unitPath() {
|
|
20683
|
-
return
|
|
21521
|
+
return path31.join(systemdUserDir(), `${SYSTEMD_UNIT_NAME}.service`);
|
|
20684
21522
|
}
|
|
20685
21523
|
render(opts) {
|
|
20686
21524
|
return renderSystemdUnit(opts);
|
|
20687
21525
|
}
|
|
20688
21526
|
async install(opts) {
|
|
20689
|
-
|
|
21527
|
+
mkdirSync14(systemdUserDir(), { recursive: true });
|
|
20690
21528
|
writeServiceFile(this.unitPath(), this.render(opts));
|
|
20691
21529
|
await runCommand("systemctl", ["--user", "daemon-reload"]);
|
|
20692
21530
|
await runCommand("systemctl", ["--user", "enable", this.identifier]);
|
|
@@ -20707,14 +21545,14 @@ var init_runner_service = __esm({
|
|
|
20707
21545
|
await runCommand("systemctl", ["--user", "disable", this.identifier]);
|
|
20708
21546
|
} catch {
|
|
20709
21547
|
}
|
|
20710
|
-
if (
|
|
21548
|
+
if (existsSync26(this.unitPath())) rmSync6(this.unitPath());
|
|
20711
21549
|
try {
|
|
20712
21550
|
await runCommand("systemctl", ["--user", "daemon-reload"]);
|
|
20713
21551
|
} catch {
|
|
20714
21552
|
}
|
|
20715
21553
|
}
|
|
20716
21554
|
async status() {
|
|
20717
|
-
const installed =
|
|
21555
|
+
const installed = existsSync26(this.unitPath());
|
|
20718
21556
|
try {
|
|
20719
21557
|
const { stdout } = await runCommand("systemctl", ["--user", "is-active", this.identifier]);
|
|
20720
21558
|
return { installed, running: stdout.trim() === "active" ? "running" : "stopped" };
|
|
@@ -20729,9 +21567,9 @@ var init_runner_service = __esm({
|
|
|
20729
21567
|
// src/select-prompt.ts
|
|
20730
21568
|
import { createInterface as createInterface4 } from "node:readline";
|
|
20731
21569
|
function parseNumberedSelection(answer, count) {
|
|
20732
|
-
const
|
|
20733
|
-
if (!/^\d+$/.test(
|
|
20734
|
-
const value = Number.parseInt(
|
|
21570
|
+
const trimmed5 = answer.trim();
|
|
21571
|
+
if (!/^\d+$/.test(trimmed5)) return null;
|
|
21572
|
+
const value = Number.parseInt(trimmed5, 10);
|
|
20735
21573
|
if (!Number.isInteger(value) || value < 1 || value > count) return null;
|
|
20736
21574
|
return value - 1;
|
|
20737
21575
|
}
|
|
@@ -20781,14 +21619,14 @@ var init_select_prompt = __esm({
|
|
|
20781
21619
|
|
|
20782
21620
|
// src/session-key.ts
|
|
20783
21621
|
import { createHash as createHash10 } from "node:crypto";
|
|
20784
|
-
import { existsSync as
|
|
20785
|
-
import
|
|
21622
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync23, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "node:fs";
|
|
21623
|
+
import path32 from "node:path";
|
|
20786
21624
|
function sessionKeyCachePath({
|
|
20787
21625
|
missionId,
|
|
20788
21626
|
workingDirectory
|
|
20789
21627
|
}) {
|
|
20790
|
-
const key = createHash10("sha256").update(`${
|
|
20791
|
-
return
|
|
21628
|
+
const key = createHash10("sha256").update(`${path32.resolve(workingDirectory)}\0${missionId}`).digest("hex");
|
|
21629
|
+
return path32.join(resolveGlobalDataDir(), "protocol-session-keys", key);
|
|
20792
21630
|
}
|
|
20793
21631
|
function readCachedSessionKey({
|
|
20794
21632
|
missionId,
|
|
@@ -20796,8 +21634,8 @@ function readCachedSessionKey({
|
|
|
20796
21634
|
}) {
|
|
20797
21635
|
try {
|
|
20798
21636
|
const filePath = sessionKeyCachePath({ missionId, workingDirectory });
|
|
20799
|
-
if (!
|
|
20800
|
-
const raw = JSON.parse(
|
|
21637
|
+
if (!existsSync27(filePath)) return void 0;
|
|
21638
|
+
const raw = JSON.parse(readFileSync23(filePath, "utf8"));
|
|
20801
21639
|
return typeof raw.sessionKey === "string" && raw.sessionKey.trim() ? raw.sessionKey.trim() : void 0;
|
|
20802
21640
|
} catch {
|
|
20803
21641
|
return void 0;
|
|
@@ -20809,13 +21647,13 @@ function writeCachedSessionKey({
|
|
|
20809
21647
|
sessionKey
|
|
20810
21648
|
}) {
|
|
20811
21649
|
try {
|
|
20812
|
-
const
|
|
20813
|
-
if (!
|
|
21650
|
+
const trimmed5 = sessionKey.trim();
|
|
21651
|
+
if (!trimmed5) return;
|
|
20814
21652
|
const filePath = sessionKeyCachePath({ missionId, workingDirectory });
|
|
20815
|
-
|
|
20816
|
-
|
|
21653
|
+
mkdirSync15(path32.dirname(filePath), { recursive: true });
|
|
21654
|
+
writeFileSync14(
|
|
20817
21655
|
filePath,
|
|
20818
|
-
JSON.stringify({ sessionKey:
|
|
21656
|
+
JSON.stringify({ sessionKey: trimmed5, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
20819
21657
|
{ mode: 384 }
|
|
20820
21658
|
);
|
|
20821
21659
|
} catch {
|
|
@@ -20827,7 +21665,7 @@ function clearCachedSessionKey({
|
|
|
20827
21665
|
}) {
|
|
20828
21666
|
try {
|
|
20829
21667
|
const filePath = sessionKeyCachePath({ missionId, workingDirectory });
|
|
20830
|
-
if (
|
|
21668
|
+
if (existsSync27(filePath)) rmSync7(filePath);
|
|
20831
21669
|
} catch {
|
|
20832
21670
|
}
|
|
20833
21671
|
}
|
|
@@ -20845,9 +21683,9 @@ __export(commands_exports, {
|
|
|
20845
21683
|
runManagementCommand: () => runManagementCommand,
|
|
20846
21684
|
runProtocolCommand: () => runProtocolCommand
|
|
20847
21685
|
});
|
|
20848
|
-
import { existsSync as
|
|
20849
|
-
import
|
|
20850
|
-
import
|
|
21686
|
+
import { existsSync as existsSync28, readFileSync as readFileSync24 } from "node:fs";
|
|
21687
|
+
import os6 from "node:os";
|
|
21688
|
+
import path33 from "node:path";
|
|
20851
21689
|
function resourceAccessModeBody(value) {
|
|
20852
21690
|
if (typeof value !== "string") return {};
|
|
20853
21691
|
const normalized = value.trim().toLowerCase();
|
|
@@ -20893,7 +21731,7 @@ function readChangedFilesFromFlags(flags, stdin) {
|
|
|
20893
21731
|
if (typeof fileFlag === "string") {
|
|
20894
21732
|
const raw = fileFlag === "-" ? stdin ?? "" : (() => {
|
|
20895
21733
|
try {
|
|
20896
|
-
return
|
|
21734
|
+
return readFileSync24(fileFlag, "utf8");
|
|
20897
21735
|
} catch {
|
|
20898
21736
|
return "";
|
|
20899
21737
|
}
|
|
@@ -20945,7 +21783,7 @@ function readJsonFlagContent({
|
|
|
20945
21783
|
if (typeof filePath === "string") {
|
|
20946
21784
|
if (fileInputs[fileFlag] !== void 0) return fileInputs[fileFlag];
|
|
20947
21785
|
try {
|
|
20948
|
-
return
|
|
21786
|
+
return readFileSync24(filePath, "utf8");
|
|
20949
21787
|
} catch {
|
|
20950
21788
|
return void 0;
|
|
20951
21789
|
}
|
|
@@ -21249,7 +22087,7 @@ async function resolveProtocolFileInputs({
|
|
|
21249
22087
|
} else if (process.stdin.isTTY) {
|
|
21250
22088
|
stdinContent = "";
|
|
21251
22089
|
} else {
|
|
21252
|
-
stdinContent =
|
|
22090
|
+
stdinContent = readFileSync24(0, "utf8");
|
|
21253
22091
|
}
|
|
21254
22092
|
return stdinContent;
|
|
21255
22093
|
};
|
|
@@ -21263,7 +22101,7 @@ async function resolveProtocolFileInputs({
|
|
|
21263
22101
|
fileInputs[flagName] = content;
|
|
21264
22102
|
stdinPayload = content;
|
|
21265
22103
|
} else {
|
|
21266
|
-
fileInputs[flagName] =
|
|
22104
|
+
fileInputs[flagName] = readFileSync24(filePath, "utf8");
|
|
21267
22105
|
}
|
|
21268
22106
|
}
|
|
21269
22107
|
if (stdinPayload === void 0 && stdin !== void 0 && Object.keys(fileInputs).length === 0) {
|
|
@@ -21328,7 +22166,7 @@ async function runProtocolCommand({
|
|
|
21328
22166
|
});
|
|
21329
22167
|
if (subcommand === "record-touched") {
|
|
21330
22168
|
const missionOverride = flagValue(parsed.flags, "--mission-id") ?? process.env.MISSION_ID ?? process.env.OVERLORD_MISSION_ID;
|
|
21331
|
-
const rawPayload = stdin ?? (process.stdin.isTTY ? "" :
|
|
22169
|
+
const rawPayload = stdin ?? (process.stdin.isTTY ? "" : readFileSync24(0, "utf8"));
|
|
21332
22170
|
const result2 = recordTouchedFromPayload({
|
|
21333
22171
|
rawPayload,
|
|
21334
22172
|
missionOverride,
|
|
@@ -21459,9 +22297,9 @@ async function runProtocolCommand({
|
|
|
21459
22297
|
clearCachedSessionKey({ missionId, workingDirectory });
|
|
21460
22298
|
removeActiveSession({ workingDirectory, missionId });
|
|
21461
22299
|
clearActiveMissionPointer(workingDirectory);
|
|
21462
|
-
const connectorInstallsEditHook =
|
|
21463
|
-
|
|
21464
|
-
|
|
22300
|
+
const connectorInstallsEditHook = existsSync28(path33.join(os6.homedir(), ".claude")) || existsSync28(
|
|
22301
|
+
path33.join(
|
|
22302
|
+
os6.homedir(),
|
|
21465
22303
|
".cursor",
|
|
21466
22304
|
"plugins",
|
|
21467
22305
|
"local",
|
|
@@ -21560,7 +22398,7 @@ async function runManagementCommand({
|
|
|
21560
22398
|
case "add-cwd": {
|
|
21561
22399
|
const directory = flagValue(parsed.flags, "--directory") ?? process.cwd();
|
|
21562
22400
|
const existingProjectJson = readProjectJsonLink(
|
|
21563
|
-
|
|
22401
|
+
path33.join(directory, ".overlord", "project.json")
|
|
21564
22402
|
);
|
|
21565
22403
|
const resourceKey = flagValue(parsed.flags, "--key") ?? existingProjectJson?.resourceKey;
|
|
21566
22404
|
let projectId = flagValue(parsed.flags, "--project-id");
|
|
@@ -21951,13 +22789,13 @@ async function runManagementCommand({
|
|
|
21951
22789
|
rationales: `/api/missions/${encodeURIComponent(missionId)}/file-changes`,
|
|
21952
22790
|
deliveries: `/api/missions/${encodeURIComponent(missionId)}/deliveries`
|
|
21953
22791
|
};
|
|
21954
|
-
const
|
|
21955
|
-
if (!
|
|
22792
|
+
const path34 = sub ? pathBySub[sub] : void 0;
|
|
22793
|
+
if (!path34) {
|
|
21956
22794
|
throw new CliError({
|
|
21957
22795
|
message: "Usage: ovld mission context|events|deliveries|artifacts|rationales <missionId> [--json]"
|
|
21958
22796
|
});
|
|
21959
22797
|
}
|
|
21960
|
-
const result = await runtime.backend.get(
|
|
22798
|
+
const result = await runtime.backend.get(path34);
|
|
21961
22799
|
if (json || sub === "context") printJson(result);
|
|
21962
22800
|
else if (Array.isArray(result)) for (const row of result) console.log(JSON.stringify(row));
|
|
21963
22801
|
else printJson(result);
|
|
@@ -22127,16 +22965,33 @@ The runner will not register a target for you \u2014 declare this machine first,
|
|
|
22127
22965
|
sessionChannelId: typeof sessionChannel.channelId === "string" ? sessionChannel.channelId : void 0,
|
|
22128
22966
|
sessionChannelToken: typeof sessionChannel.token === "string" ? sessionChannel.token : void 0,
|
|
22129
22967
|
sessionChannelLaunchKind: typeof sessionChannel.launchKind === "string" ? sessionChannel.launchKind : void 0,
|
|
22968
|
+
launchSession: launchSessionSnapshotFromMetadata(asRecord5(requestRecord.metadata)),
|
|
22130
22969
|
...terminal,
|
|
22131
22970
|
dryRun
|
|
22132
22971
|
}
|
|
22133
22972
|
});
|
|
22973
|
+
if (result.providerFallbackWarning) {
|
|
22974
|
+
console.error(`[overlord] ${result.providerFallbackWarning}`);
|
|
22975
|
+
}
|
|
22976
|
+
if (result.viewerOpen && result.viewerOpen.ok === false) {
|
|
22977
|
+
console.error(`[overlord] ${result.viewerOpen.warning}`);
|
|
22978
|
+
}
|
|
22134
22979
|
if (result.status && result.status !== 0) {
|
|
22135
22980
|
throw new CliError({ message: `Launch command exited with status ${result.status}` });
|
|
22136
22981
|
}
|
|
22137
|
-
await runtime.backend.post({
|
|
22982
|
+
await runtime.backend.post({
|
|
22983
|
+
path: `/api/runner/requests/${requestId}/launched`,
|
|
22984
|
+
body: result.providerSession ? { providerSession: result.providerSession } : {}
|
|
22985
|
+
});
|
|
22138
22986
|
if (json || dryRun) {
|
|
22139
|
-
printJson({
|
|
22987
|
+
printJson({
|
|
22988
|
+
request,
|
|
22989
|
+
plan: result.plan,
|
|
22990
|
+
status: result.status,
|
|
22991
|
+
providerSession: result.providerSession ?? null,
|
|
22992
|
+
viewerOpen: result.viewerOpen ?? null,
|
|
22993
|
+
providerFallbackWarning: result.providerFallbackWarning ?? null
|
|
22994
|
+
});
|
|
22140
22995
|
} else {
|
|
22141
22996
|
console.log(`Launched ${requestedAgent} for ${requestRecord.missionId}`);
|
|
22142
22997
|
}
|
|
@@ -22318,6 +23173,7 @@ var init_commands = __esm({
|
|
|
22318
23173
|
init_dist2();
|
|
22319
23174
|
init_project_metadata();
|
|
22320
23175
|
init_local_target_mutation_runner();
|
|
23176
|
+
init_terminal_profile_types2();
|
|
22321
23177
|
init_active_mission();
|
|
22322
23178
|
init_args();
|
|
22323
23179
|
init_branch_preparation();
|