overlord-cli 0.2608120914.0 → 0.2608121927.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 +1246 -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,559 @@ 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 resolveLatchExecutableOnPath(executable) {
|
|
16954
|
+
try {
|
|
16955
|
+
const found = execFileSync3("which", [executable], {
|
|
16956
|
+
encoding: "utf8",
|
|
16957
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
16958
|
+
}).trim();
|
|
16959
|
+
return found || null;
|
|
16960
|
+
} catch {
|
|
16961
|
+
return null;
|
|
16962
|
+
}
|
|
16963
|
+
}
|
|
16964
|
+
function resolveLatchExecutablePathFromEnvironment({ executable, homeDirectory = os3.homedir(), platform: platform2 = process.platform, resolveOnPath = resolveLatchExecutableOnPath, fileExists = existsSync16 }) {
|
|
16965
|
+
const name = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
|
|
16966
|
+
if (path17.isAbsolute(name) || name.includes("/") || name.includes("\\")) {
|
|
16967
|
+
return fileExists(name) ? path17.resolve(name) : null;
|
|
16968
|
+
}
|
|
16969
|
+
const resolvedOnPath = resolveOnPath(name);
|
|
16970
|
+
if (resolvedOnPath)
|
|
16971
|
+
return resolvedOnPath;
|
|
16972
|
+
const fallbacks = [
|
|
16973
|
+
path17.join(homeDirectory, ".local", "bin", name),
|
|
16974
|
+
...platform2 === "darwin" ? [`/opt/homebrew/bin/${name}`, `/usr/local/bin/${name}`] : []
|
|
16975
|
+
];
|
|
16976
|
+
const fallback = fallbacks.find(fileExists);
|
|
16977
|
+
return fallback ? path17.resolve(fallback) : null;
|
|
16978
|
+
}
|
|
16979
|
+
function resolveLatchExecutablePath(executable) {
|
|
16980
|
+
return resolveLatchExecutablePathFromEnvironment({ executable });
|
|
16981
|
+
}
|
|
16982
|
+
function notInstalledResult({ executable, checkedAt }) {
|
|
16983
|
+
return {
|
|
16984
|
+
state: "not_installed",
|
|
16985
|
+
executable,
|
|
16986
|
+
installCommand: LATCH_STANDALONE_INSTALL_COMMAND,
|
|
16987
|
+
checkedAt,
|
|
16988
|
+
latchSelectable: false,
|
|
16989
|
+
directSelectable: true
|
|
16990
|
+
};
|
|
16991
|
+
}
|
|
16992
|
+
function probeLatchCapabilities({ executable = DEFAULT_LATCH_EXECUTABLE, resolvePath = resolveLatchExecutablePath, runCommand: runCommand2 = defaultCommandRunner, now = () => (/* @__PURE__ */ new Date()).toISOString() } = {}) {
|
|
16993
|
+
const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
|
|
16994
|
+
const checkedAt = now();
|
|
16995
|
+
const resolvedPath = resolvePath(exe);
|
|
16996
|
+
if (!resolvedPath) {
|
|
16997
|
+
return notInstalledResult({ executable: exe, checkedAt });
|
|
16998
|
+
}
|
|
16999
|
+
const ran = runCommand2({ executable: resolvedPath, argv: ["capabilities", "--json"] });
|
|
17000
|
+
if (ran.status === null && ran.stderr === "ENOENT") {
|
|
17001
|
+
return notInstalledResult({ executable: exe, checkedAt });
|
|
17002
|
+
}
|
|
17003
|
+
const report = parseLatchCapabilitiesReport(ran.stdout);
|
|
17004
|
+
if (!report) {
|
|
17005
|
+
return {
|
|
17006
|
+
state: "incompatible",
|
|
17007
|
+
executable: exe,
|
|
17008
|
+
resolvedPath,
|
|
17009
|
+
protocolVersion: null,
|
|
17010
|
+
productVersion: null,
|
|
17011
|
+
missingCapability: "capabilities",
|
|
17012
|
+
detail: ran.status === 0 ? "Latch capabilities output was not valid JSON in the expected shape." : `Latch capabilities failed (exit ${ran.status ?? "null"}).`,
|
|
17013
|
+
checkedAt,
|
|
17014
|
+
latchSelectable: false,
|
|
17015
|
+
directSelectable: true
|
|
17016
|
+
};
|
|
17017
|
+
}
|
|
17018
|
+
return evaluateLatchCapabilities({ report, executable: exe, resolvedPath, checkedAt });
|
|
17019
|
+
}
|
|
17020
|
+
function latchDiscoveryCacheKey({ executionTargetId, executable }) {
|
|
17021
|
+
const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
|
|
17022
|
+
return `${executionTargetId}::${exe}`;
|
|
17023
|
+
}
|
|
17024
|
+
function readBinaryMtimeMs(resolvedPath) {
|
|
17025
|
+
if (!resolvedPath)
|
|
17026
|
+
return null;
|
|
17027
|
+
try {
|
|
17028
|
+
return statSync4(resolvedPath).mtimeMs;
|
|
17029
|
+
} catch {
|
|
17030
|
+
return null;
|
|
17031
|
+
}
|
|
17032
|
+
}
|
|
17033
|
+
function isLatchDiscoveryCacheFresh({ entry, resolvePath = resolveLatchExecutablePath }) {
|
|
17034
|
+
const { result } = entry;
|
|
17035
|
+
if (result.state === "not_installed") {
|
|
17036
|
+
return resolvePath(result.executable) === null;
|
|
17037
|
+
}
|
|
17038
|
+
const pathStill = result.resolvedPath;
|
|
17039
|
+
if (!pathStill || !existsSync16(pathStill))
|
|
17040
|
+
return false;
|
|
17041
|
+
const mtime = readBinaryMtimeMs(pathStill);
|
|
17042
|
+
if (mtime === null || entry.binaryMtimeMs === null)
|
|
17043
|
+
return false;
|
|
17044
|
+
return mtime === entry.binaryMtimeMs;
|
|
17045
|
+
}
|
|
17046
|
+
function readLatchDiscoveryCacheFile(filePath) {
|
|
17047
|
+
if (!existsSync16(filePath))
|
|
17048
|
+
return { version: 1, entries: {} };
|
|
17049
|
+
try {
|
|
17050
|
+
const parsed = JSON.parse(readFileSync15(filePath, "utf8"));
|
|
17051
|
+
if (parsed.version !== 1 || !parsed.entries || typeof parsed.entries !== "object") {
|
|
17052
|
+
return { version: 1, entries: {} };
|
|
17053
|
+
}
|
|
17054
|
+
return { version: 1, entries: parsed.entries };
|
|
17055
|
+
} catch {
|
|
17056
|
+
return { version: 1, entries: {} };
|
|
17057
|
+
}
|
|
17058
|
+
}
|
|
17059
|
+
function writeLatchDiscoveryCacheFile({ filePath, cache }) {
|
|
17060
|
+
mkdirSync9(path17.dirname(filePath), { recursive: true });
|
|
17061
|
+
writeFileSync8(filePath, `${JSON.stringify(cache, null, 2)}
|
|
17062
|
+
`, { mode: 384 });
|
|
17063
|
+
}
|
|
17064
|
+
function discoverLatchForExecutionTarget({ executionTargetId, executable = DEFAULT_LATCH_EXECUTABLE, cacheFilePath, force = false, resolvePath = resolveLatchExecutablePath, runCommand: runCommand2 = defaultCommandRunner, now = () => (/* @__PURE__ */ new Date()).toISOString() }) {
|
|
17065
|
+
const exe = trimmed2(executable) ?? DEFAULT_LATCH_EXECUTABLE;
|
|
17066
|
+
const key = latchDiscoveryCacheKey({ executionTargetId, executable: exe });
|
|
17067
|
+
const cache = readLatchDiscoveryCacheFile(cacheFilePath);
|
|
17068
|
+
const existing = cache.entries[key];
|
|
17069
|
+
if (!force && existing && isLatchDiscoveryCacheFresh({ entry: existing, resolvePath })) {
|
|
17070
|
+
return { ...existing.result, checkedAt: existing.result.checkedAt, directSelectable: true };
|
|
17071
|
+
}
|
|
17072
|
+
const result = probeLatchCapabilities({ executable: exe, resolvePath, runCommand: runCommand2, now });
|
|
17073
|
+
const binaryMtimeMs = result.state === "not_installed" ? null : readBinaryMtimeMs(result.resolvedPath);
|
|
17074
|
+
cache.entries[key] = {
|
|
17075
|
+
result,
|
|
17076
|
+
binaryMtimeMs,
|
|
17077
|
+
cachedAt: result.checkedAt
|
|
17078
|
+
};
|
|
17079
|
+
writeLatchDiscoveryCacheFile({ filePath: cacheFilePath, cache });
|
|
17080
|
+
return result;
|
|
17081
|
+
}
|
|
17082
|
+
var SUPPORTED_LATCH_PROTOCOL_VERSION, REQUIRED_LATCH_CAPABILITIES, LATCH_STANDALONE_INSTALL_COMMAND, LATCH_DISCOVERY_CACHE_FILENAME, defaultCommandRunner;
|
|
17083
|
+
var init_latch_discovery = __esm({
|
|
17084
|
+
"../packages/core/dist/service/latch-discovery.js"() {
|
|
17085
|
+
"use strict";
|
|
17086
|
+
init_terminal_profile_types2();
|
|
17087
|
+
SUPPORTED_LATCH_PROTOCOL_VERSION = 1;
|
|
17088
|
+
REQUIRED_LATCH_CAPABILITIES = ["create"];
|
|
17089
|
+
LATCH_STANDALONE_INSTALL_COMMAND = "curl -fsSL https://raw.githubusercontent.com/jchaselubitz/Latch/main/scripts/install-cli.sh | bash";
|
|
17090
|
+
LATCH_DISCOVERY_CACHE_FILENAME = "latch-discovery.json";
|
|
17091
|
+
defaultCommandRunner = ({ executable, argv }) => {
|
|
17092
|
+
try {
|
|
17093
|
+
const stdout = execFileSync3(executable, argv, {
|
|
17094
|
+
encoding: "utf8",
|
|
17095
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
17096
|
+
timeout: 5e3
|
|
17097
|
+
});
|
|
17098
|
+
return { status: 0, stdout: String(stdout), stderr: "" };
|
|
17099
|
+
} catch (error) {
|
|
17100
|
+
const err = error;
|
|
17101
|
+
if (err.code === "ENOENT") {
|
|
17102
|
+
return { status: null, stdout: "", stderr: "ENOENT" };
|
|
17103
|
+
}
|
|
17104
|
+
return {
|
|
17105
|
+
status: typeof err.status === "number" ? err.status : 1,
|
|
17106
|
+
stdout: err.stdout ? String(err.stdout) : "",
|
|
17107
|
+
stderr: err.stderr ? String(err.stderr) : String(error)
|
|
17108
|
+
};
|
|
17109
|
+
}
|
|
17110
|
+
};
|
|
17111
|
+
}
|
|
17112
|
+
});
|
|
17113
|
+
|
|
17114
|
+
// ../packages/core/dist/service/latch-launch.js
|
|
17115
|
+
function trimmed3(value) {
|
|
17116
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
17117
|
+
}
|
|
17118
|
+
function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.trim() || "/bin/bash", cwd, env, size = DEFAULT_LATCH_TERMINAL_SIZE, title, name, commandLabel, externalRunId }) {
|
|
17119
|
+
const shellPath = trimmed3(shell) ?? "/bin/bash";
|
|
17120
|
+
const cleanedEnv = {};
|
|
17121
|
+
for (const [key, value] of Object.entries(env)) {
|
|
17122
|
+
if (key.trim() && typeof value === "string")
|
|
17123
|
+
cleanedEnv[key] = value;
|
|
17124
|
+
}
|
|
17125
|
+
const display = {
|
|
17126
|
+
source: {
|
|
17127
|
+
kind: "overlord",
|
|
17128
|
+
...trimmed3(externalRunId) ? { external_run_id: trimmed3(externalRunId) } : {}
|
|
17129
|
+
}
|
|
17130
|
+
};
|
|
17131
|
+
if (trimmed3(title))
|
|
17132
|
+
display.title = trimmed3(title);
|
|
17133
|
+
if (trimmed3(name))
|
|
17134
|
+
display.name = trimmed3(name);
|
|
17135
|
+
if (trimmed3(commandLabel))
|
|
17136
|
+
display.command_label = trimmed3(commandLabel);
|
|
17137
|
+
return {
|
|
17138
|
+
format_version: LATCH_MANIFEST_FORMAT_VERSION,
|
|
17139
|
+
launch: {
|
|
17140
|
+
argv: [shellPath, "-lc", commandString],
|
|
17141
|
+
cwd,
|
|
17142
|
+
env: cleanedEnv,
|
|
17143
|
+
inherit_env: true,
|
|
17144
|
+
size: {
|
|
17145
|
+
cols: Math.max(1, Math.floor(size.cols) || DEFAULT_LATCH_TERMINAL_SIZE.cols),
|
|
17146
|
+
rows: Math.max(1, Math.floor(size.rows) || DEFAULT_LATCH_TERMINAL_SIZE.rows)
|
|
17147
|
+
}
|
|
17148
|
+
},
|
|
17149
|
+
display
|
|
17150
|
+
};
|
|
17151
|
+
}
|
|
17152
|
+
function parseLatchCreateReport(raw) {
|
|
17153
|
+
try {
|
|
17154
|
+
const parsed = JSON.parse(raw);
|
|
17155
|
+
const id = trimmed3(parsed.session?.id);
|
|
17156
|
+
if (!id)
|
|
17157
|
+
return null;
|
|
17158
|
+
const protocolVersion = typeof parsed.protocolVersion === "number" && Number.isFinite(parsed.protocolVersion) ? parsed.protocolVersion : LATCH_MANIFEST_FORMAT_VERSION;
|
|
17159
|
+
return {
|
|
17160
|
+
protocolVersion,
|
|
17161
|
+
session: {
|
|
17162
|
+
id,
|
|
17163
|
+
name: trimmed3(parsed.session?.name) ?? id,
|
|
17164
|
+
state: trimmed3(parsed.session?.state) ?? "running",
|
|
17165
|
+
createdAt: trimmed3(parsed.session?.createdAt) ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
17166
|
+
}
|
|
17167
|
+
};
|
|
17168
|
+
} catch {
|
|
17169
|
+
return null;
|
|
17170
|
+
}
|
|
17171
|
+
}
|
|
17172
|
+
function toExecutionProviderSession({ createReport, executionTargetId, createdAt }) {
|
|
17173
|
+
return {
|
|
17174
|
+
provider: "latch",
|
|
17175
|
+
providerSessionId: createReport.session.id,
|
|
17176
|
+
sessionName: createReport.session.name,
|
|
17177
|
+
executionTargetId: trimmed3(executionTargetId),
|
|
17178
|
+
agentSessionId: null,
|
|
17179
|
+
createdAt: createdAt ?? createReport.session.createdAt,
|
|
17180
|
+
lastObservedState: createReport.session.state
|
|
17181
|
+
};
|
|
17182
|
+
}
|
|
17183
|
+
function existingLatchProviderSession({ latchSessionId, executionTargetId, createdAt = (/* @__PURE__ */ new Date()).toISOString() }) {
|
|
17184
|
+
const providerSessionId = trimmed3(latchSessionId);
|
|
17185
|
+
if (!providerSessionId)
|
|
17186
|
+
return null;
|
|
17187
|
+
return {
|
|
17188
|
+
provider: "latch",
|
|
17189
|
+
providerSessionId,
|
|
17190
|
+
sessionName: null,
|
|
17191
|
+
executionTargetId: trimmed3(executionTargetId),
|
|
17192
|
+
agentSessionId: null,
|
|
17193
|
+
createdAt,
|
|
17194
|
+
lastObservedState: "running"
|
|
17195
|
+
};
|
|
17196
|
+
}
|
|
17197
|
+
function latchViewerFlagForKind(kind) {
|
|
17198
|
+
switch (trimmed3(kind)?.toLowerCase()) {
|
|
17199
|
+
case "iterm":
|
|
17200
|
+
case "iterm2":
|
|
17201
|
+
return "iterm";
|
|
17202
|
+
default:
|
|
17203
|
+
return null;
|
|
17204
|
+
}
|
|
17205
|
+
}
|
|
17206
|
+
function latchAttachCommand({ executable = "latch", providerSessionId }) {
|
|
17207
|
+
return `${trimmed3(executable) ?? "latch"} attach ${providerSessionId}`;
|
|
17208
|
+
}
|
|
17209
|
+
function shouldUseLatchProvider({ providerKind, latchSelectable }) {
|
|
17210
|
+
return trimmed3(providerKind)?.toLowerCase() === "latch" && latchSelectable === true;
|
|
17211
|
+
}
|
|
17212
|
+
var LATCH_MANIFEST_FORMAT_VERSION, DEFAULT_LATCH_TERMINAL_SIZE;
|
|
17213
|
+
var init_latch_launch = __esm({
|
|
17214
|
+
"../packages/core/dist/service/latch-launch.js"() {
|
|
17215
|
+
"use strict";
|
|
17216
|
+
LATCH_MANIFEST_FORMAT_VERSION = 1;
|
|
17217
|
+
DEFAULT_LATCH_TERMINAL_SIZE = { cols: 120, rows: 36 };
|
|
17218
|
+
}
|
|
17219
|
+
});
|
|
17220
|
+
|
|
17221
|
+
// ../packages/core/dist/service/latch-session.js
|
|
17222
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
17223
|
+
function trimmed4(value) {
|
|
17224
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
17225
|
+
}
|
|
17226
|
+
function parseState(value) {
|
|
17227
|
+
switch (trimmed4(value)) {
|
|
17228
|
+
case "running":
|
|
17229
|
+
return "running";
|
|
17230
|
+
case "exited":
|
|
17231
|
+
return "exited";
|
|
17232
|
+
case "stopping":
|
|
17233
|
+
return "stopping";
|
|
17234
|
+
case "lost":
|
|
17235
|
+
return "lost";
|
|
17236
|
+
default:
|
|
17237
|
+
return null;
|
|
17238
|
+
}
|
|
17239
|
+
}
|
|
17240
|
+
function runLatchJson({ executable, args }) {
|
|
17241
|
+
const result = spawnSync2(executable, args, {
|
|
17242
|
+
encoding: "utf8",
|
|
17243
|
+
shell: false,
|
|
17244
|
+
timeout: 1e4,
|
|
17245
|
+
maxBuffer: 1024 * 1024
|
|
17246
|
+
});
|
|
17247
|
+
if (result.error) {
|
|
17248
|
+
throw new LatchSessionCommandError(result.error.message);
|
|
17249
|
+
}
|
|
17250
|
+
if (result.status !== 0) {
|
|
17251
|
+
const detail = (result.stderr || result.stdout || `exit ${result.status ?? "unknown"}`).trim().slice(0, 500);
|
|
17252
|
+
throw new LatchSessionCommandError(detail || "Latch command failed.");
|
|
17253
|
+
}
|
|
17254
|
+
try {
|
|
17255
|
+
const parsed = JSON.parse(result.stdout);
|
|
17256
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
17257
|
+
throw new Error("not an object");
|
|
17258
|
+
}
|
|
17259
|
+
return parsed;
|
|
17260
|
+
} catch {
|
|
17261
|
+
throw new LatchSessionCommandError("Latch returned an invalid JSON response.");
|
|
17262
|
+
}
|
|
17263
|
+
}
|
|
17264
|
+
function inspectLatchSession({ executable = "latch", providerSessionId }) {
|
|
17265
|
+
const sessionId = trimmed4(providerSessionId);
|
|
17266
|
+
if (!sessionId)
|
|
17267
|
+
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
17268
|
+
const report = runLatchJson({
|
|
17269
|
+
executable: trimmed4(executable) ?? "latch",
|
|
17270
|
+
args: ["inspect", sessionId, "--json"]
|
|
17271
|
+
});
|
|
17272
|
+
const state = parseState(report.state);
|
|
17273
|
+
if (!state)
|
|
17274
|
+
throw new LatchSessionCommandError("Latch returned an unsupported session state.");
|
|
17275
|
+
const exit = report.exit && typeof report.exit === "object" && !Array.isArray(report.exit) ? report.exit : null;
|
|
17276
|
+
return {
|
|
17277
|
+
providerSessionId: trimmed4(report.id) ?? sessionId,
|
|
17278
|
+
name: trimmed4(report.name) ?? sessionId,
|
|
17279
|
+
state,
|
|
17280
|
+
exitCode: typeof exit?.code === "number" && Number.isFinite(exit.code) ? exit.code : null,
|
|
17281
|
+
inspectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
17282
|
+
};
|
|
17283
|
+
}
|
|
17284
|
+
function openLatchSession({ executable = "latch", providerSessionId, viewerKind }) {
|
|
17285
|
+
const sessionId = trimmed4(providerSessionId);
|
|
17286
|
+
if (!sessionId)
|
|
17287
|
+
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
17288
|
+
const viewer = latchViewerFlagForKind(viewerKind);
|
|
17289
|
+
if (!viewer) {
|
|
17290
|
+
throw new LatchSessionCommandError(`Latch cannot open the configured viewer "${viewerKind}".`);
|
|
17291
|
+
}
|
|
17292
|
+
const report = runLatchJson({
|
|
17293
|
+
executable: trimmed4(executable) ?? "latch",
|
|
17294
|
+
args: ["open", sessionId, "--with", viewer, "--json"]
|
|
17295
|
+
});
|
|
17296
|
+
if (report.opened !== true) {
|
|
17297
|
+
throw new LatchSessionCommandError(`Latch did not open the ${viewer} viewer.`);
|
|
17298
|
+
}
|
|
17299
|
+
return {
|
|
17300
|
+
providerSessionId: trimmed4(report.id) ?? sessionId,
|
|
17301
|
+
viewer: trimmed4(report.viewer) ?? viewer,
|
|
17302
|
+
opened: true
|
|
17303
|
+
};
|
|
17304
|
+
}
|
|
17305
|
+
function stopLatchSession({ executable = "latch", providerSessionId }) {
|
|
17306
|
+
const sessionId = trimmed4(providerSessionId);
|
|
17307
|
+
if (!sessionId)
|
|
17308
|
+
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
17309
|
+
const report = runLatchJson({
|
|
17310
|
+
executable: trimmed4(executable) ?? "latch",
|
|
17311
|
+
args: ["stop", sessionId, "--json"]
|
|
17312
|
+
});
|
|
17313
|
+
const state = parseState(report.state);
|
|
17314
|
+
if (!state)
|
|
17315
|
+
throw new LatchSessionCommandError("Latch returned an unsupported session state.");
|
|
17316
|
+
return {
|
|
17317
|
+
providerSessionId: trimmed4(report.id) ?? sessionId,
|
|
17318
|
+
state
|
|
17319
|
+
};
|
|
17320
|
+
}
|
|
17321
|
+
var LatchSessionCommandError;
|
|
17322
|
+
var init_latch_session = __esm({
|
|
17323
|
+
"../packages/core/dist/service/latch-session.js"() {
|
|
17324
|
+
"use strict";
|
|
17325
|
+
init_latch_launch();
|
|
17326
|
+
LatchSessionCommandError = class extends Error {
|
|
17327
|
+
constructor(message) {
|
|
17328
|
+
super(message);
|
|
17329
|
+
this.name = "LatchSessionCommandError";
|
|
17330
|
+
}
|
|
17331
|
+
};
|
|
17332
|
+
}
|
|
17333
|
+
});
|
|
17334
|
+
|
|
17335
|
+
// ../packages/core/dist/service/local-target/git-run.js
|
|
17336
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
16789
17337
|
function runGit2(cwd, args) {
|
|
16790
17338
|
try {
|
|
16791
|
-
return
|
|
17339
|
+
return execFileSync4("git", args, {
|
|
16792
17340
|
cwd,
|
|
16793
17341
|
encoding: "utf8",
|
|
16794
17342
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -16800,7 +17348,7 @@ function runGit2(cwd, args) {
|
|
|
16800
17348
|
}
|
|
16801
17349
|
function runGitResult(cwd, args) {
|
|
16802
17350
|
try {
|
|
16803
|
-
const stdout =
|
|
17351
|
+
const stdout = execFileSync4("git", args, {
|
|
16804
17352
|
cwd,
|
|
16805
17353
|
encoding: "utf8",
|
|
16806
17354
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -16823,13 +17371,13 @@ var init_git_run = __esm({
|
|
|
16823
17371
|
});
|
|
16824
17372
|
|
|
16825
17373
|
// ../packages/core/dist/service/local-target/worktree-git.js
|
|
16826
|
-
import { existsSync as
|
|
16827
|
-
import
|
|
17374
|
+
import { existsSync as existsSync17, realpathSync as realpathSync2 } from "node:fs";
|
|
17375
|
+
import path18 from "node:path";
|
|
16828
17376
|
function resolveRealPath(targetPath) {
|
|
16829
17377
|
try {
|
|
16830
17378
|
return realpathSync2.native(targetPath);
|
|
16831
17379
|
} catch {
|
|
16832
|
-
return
|
|
17380
|
+
return path18.resolve(targetPath);
|
|
16833
17381
|
}
|
|
16834
17382
|
}
|
|
16835
17383
|
function worktreeIsDirty(worktreePath) {
|
|
@@ -16859,7 +17407,7 @@ function removeGitWorktree({ primaryRepoPath, worktreePath, force }) {
|
|
|
16859
17407
|
args.push(worktreePath);
|
|
16860
17408
|
runGitResult(primaryRepoPath, args);
|
|
16861
17409
|
runGitResult(primaryRepoPath, ["worktree", "prune"]);
|
|
16862
|
-
return !
|
|
17410
|
+
return !existsSync17(worktreePath);
|
|
16863
17411
|
}
|
|
16864
17412
|
function collectManagedWorktrees({ worktreeRoot, projects }) {
|
|
16865
17413
|
const resolvedRoot = resolveRealPath(worktreeRoot);
|
|
@@ -16867,7 +17415,7 @@ function collectManagedWorktrees({ worktreeRoot, projects }) {
|
|
|
16867
17415
|
const seen = /* @__PURE__ */ new Set();
|
|
16868
17416
|
for (const project of projects) {
|
|
16869
17417
|
const repoPath = project.primaryRepoPath;
|
|
16870
|
-
if (!repoPath || !
|
|
17418
|
+
if (!repoPath || !existsSync17(repoPath))
|
|
16871
17419
|
continue;
|
|
16872
17420
|
const out = runGitResult(repoPath, ["worktree", "list", "--porcelain"]);
|
|
16873
17421
|
if (!out.ok)
|
|
@@ -16878,7 +17426,7 @@ function collectManagedWorktrees({ worktreeRoot, projects }) {
|
|
|
16878
17426
|
if (!currentPath)
|
|
16879
17427
|
return;
|
|
16880
17428
|
const resolved = resolveRealPath(currentPath);
|
|
16881
|
-
const underRoot = resolved === resolvedRoot || resolved.startsWith(resolvedRoot +
|
|
17429
|
+
const underRoot = resolved === resolvedRoot || resolved.startsWith(resolvedRoot + path18.sep);
|
|
16882
17430
|
if (underRoot && !seen.has(resolved)) {
|
|
16883
17431
|
seen.add(resolved);
|
|
16884
17432
|
entries.push({
|
|
@@ -16906,7 +17454,7 @@ function collectManagedWorktrees({ worktreeRoot, projects }) {
|
|
|
16906
17454
|
return entries;
|
|
16907
17455
|
}
|
|
16908
17456
|
function removeManagedWorktree({ path: worktreePath, primaryRepoPath, force }) {
|
|
16909
|
-
const target =
|
|
17457
|
+
const target = path18.resolve(worktreePath);
|
|
16910
17458
|
if (!force && worktreeIsDirty(target)) {
|
|
16911
17459
|
return {
|
|
16912
17460
|
removed: [],
|
|
@@ -16920,7 +17468,7 @@ function purgeManagedWorktrees({ entries }) {
|
|
|
16920
17468
|
const removed = [];
|
|
16921
17469
|
const skipped = [];
|
|
16922
17470
|
for (const entry of entries) {
|
|
16923
|
-
const target =
|
|
17471
|
+
const target = path18.resolve(entry.path);
|
|
16924
17472
|
if (worktreeIsDirty(target)) {
|
|
16925
17473
|
skipped.push({ path: target, reason: "uncommitted changes" });
|
|
16926
17474
|
continue;
|
|
@@ -16945,10 +17493,10 @@ var init_worktree_git = __esm({
|
|
|
16945
17493
|
});
|
|
16946
17494
|
|
|
16947
17495
|
// ../packages/core/dist/service/local-target/branch-actions-git.js
|
|
16948
|
-
import { existsSync as
|
|
17496
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
16949
17497
|
function integrateBranch(input) {
|
|
16950
17498
|
const { branchName, baseBranch, worktreePath, primaryRepoPath } = input;
|
|
16951
|
-
if (!
|
|
17499
|
+
if (!existsSync18(worktreePath)) {
|
|
16952
17500
|
return {
|
|
16953
17501
|
ok: false,
|
|
16954
17502
|
code: "BRANCH_NO_WORKTREE",
|
|
@@ -17022,15 +17570,15 @@ function integrateBranch(input) {
|
|
|
17022
17570
|
}
|
|
17023
17571
|
function commitBranch(input) {
|
|
17024
17572
|
const { branchName, worktreePath } = input;
|
|
17025
|
-
const
|
|
17026
|
-
if (!
|
|
17573
|
+
const trimmed5 = (input.message ?? "").trim();
|
|
17574
|
+
if (!trimmed5) {
|
|
17027
17575
|
return {
|
|
17028
17576
|
ok: false,
|
|
17029
17577
|
code: "BRANCH_COMMIT_MESSAGE_REQUIRED",
|
|
17030
17578
|
message: "A commit message is required."
|
|
17031
17579
|
};
|
|
17032
17580
|
}
|
|
17033
|
-
if (!
|
|
17581
|
+
if (!existsSync18(worktreePath)) {
|
|
17034
17582
|
return {
|
|
17035
17583
|
ok: false,
|
|
17036
17584
|
code: "BRANCH_NO_WORKTREE",
|
|
@@ -17062,7 +17610,7 @@ function commitBranch(input) {
|
|
|
17062
17610
|
detail: staged.stderr || staged.stdout
|
|
17063
17611
|
};
|
|
17064
17612
|
}
|
|
17065
|
-
const commit = runGitResult(worktreePath, ["commit", "-m",
|
|
17613
|
+
const commit = runGitResult(worktreePath, ["commit", "-m", trimmed5]);
|
|
17066
17614
|
if (!commit.ok) {
|
|
17067
17615
|
return {
|
|
17068
17616
|
ok: false,
|
|
@@ -17086,7 +17634,7 @@ function pushParent(input) {
|
|
|
17086
17634
|
};
|
|
17087
17635
|
}
|
|
17088
17636
|
let summary = `Pushed ${baseBranch} to origin.`;
|
|
17089
|
-
if (
|
|
17637
|
+
if (existsSync18(worktreePath) && !worktreeIsDirty(worktreePath)) {
|
|
17090
17638
|
if (removeGitWorktree({ primaryRepoPath, worktreePath, force: false })) {
|
|
17091
17639
|
summary += ` Removed the merged worktree for ${branchName}.`;
|
|
17092
17640
|
}
|
|
@@ -17095,7 +17643,7 @@ function pushParent(input) {
|
|
|
17095
17643
|
}
|
|
17096
17644
|
function publishBranch(input) {
|
|
17097
17645
|
const { branchName, worktreePath, primaryRepoPath } = input;
|
|
17098
|
-
const repo =
|
|
17646
|
+
const repo = existsSync18(worktreePath) ? worktreePath : primaryRepoPath;
|
|
17099
17647
|
const push = runGitResult(repo, ["push", "-u", "origin", branchName]);
|
|
17100
17648
|
if (!push.ok) {
|
|
17101
17649
|
return {
|
|
@@ -17145,7 +17693,7 @@ var init_branch_status_git = __esm({
|
|
|
17145
17693
|
});
|
|
17146
17694
|
|
|
17147
17695
|
// ../packages/core/dist/service/local-target/commit-message-diff-git.js
|
|
17148
|
-
import { existsSync as
|
|
17696
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
17149
17697
|
function collectWorktreeChanges(worktreePath) {
|
|
17150
17698
|
const status = runGitResult(worktreePath, ["status", "--porcelain"]);
|
|
17151
17699
|
const diff = runGitResult(worktreePath, ["diff", "HEAD"]);
|
|
@@ -17161,7 +17709,7 @@ ${diff.stdout}`);
|
|
|
17161
17709
|
return sections.join("\n\n");
|
|
17162
17710
|
}
|
|
17163
17711
|
function gatherCommitMessageDiff(worktreePath) {
|
|
17164
|
-
if (!
|
|
17712
|
+
if (!existsSync19(worktreePath)) {
|
|
17165
17713
|
return {
|
|
17166
17714
|
ok: false,
|
|
17167
17715
|
code: "BRANCH_NO_WORKTREE",
|
|
@@ -17187,10 +17735,10 @@ var init_commit_message_diff_git = __esm({
|
|
|
17187
17735
|
});
|
|
17188
17736
|
|
|
17189
17737
|
// ../packages/core/dist/service/local-target/doctor-checks.js
|
|
17190
|
-
import { execFileSync as
|
|
17738
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
17191
17739
|
function commandOnPath(command, args) {
|
|
17192
17740
|
try {
|
|
17193
|
-
const detail =
|
|
17741
|
+
const detail = execFileSync5(command, args, {
|
|
17194
17742
|
encoding: "utf8",
|
|
17195
17743
|
stdio: ["ignore", "pipe", "ignore"]
|
|
17196
17744
|
}).trim();
|
|
@@ -17222,12 +17770,15 @@ var init_result = __esm({
|
|
|
17222
17770
|
});
|
|
17223
17771
|
|
|
17224
17772
|
// ../packages/core/dist/service/local-target/in-process-provider.js
|
|
17225
|
-
import { existsSync as
|
|
17773
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
17226
17774
|
var InProcessProvider;
|
|
17227
17775
|
var init_in_process_provider = __esm({
|
|
17228
17776
|
"../packages/core/dist/service/local-target/in-process-provider.js"() {
|
|
17229
17777
|
"use strict";
|
|
17230
17778
|
init_git_tree();
|
|
17779
|
+
init_latch_discovery();
|
|
17780
|
+
init_latch_session();
|
|
17781
|
+
init_terminal_profile_types2();
|
|
17231
17782
|
init_branch_actions_git();
|
|
17232
17783
|
init_branch_status_git();
|
|
17233
17784
|
init_commit_message_diff_git();
|
|
@@ -17250,7 +17801,7 @@ var init_in_process_provider = __esm({
|
|
|
17250
17801
|
*/
|
|
17251
17802
|
async observeResource(input) {
|
|
17252
17803
|
const observedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
17253
|
-
const state =
|
|
17804
|
+
const state = existsSync20(input.path) ? "available" : "missing";
|
|
17254
17805
|
return ok(this.target, { state, observedAt });
|
|
17255
17806
|
}
|
|
17256
17807
|
/**
|
|
@@ -17357,6 +17908,50 @@ var init_in_process_provider = __esm({
|
|
|
17357
17908
|
async launchAgent(_input) {
|
|
17358
17909
|
return fail(this.target, "CAPABILITY_NOT_IMPLEMENTED", "Agent launch is owned by the CLI runner (`ovld runner` / `ovld launch`).");
|
|
17359
17910
|
}
|
|
17911
|
+
// ---- routed (coo:702) ------------------------------------------------
|
|
17912
|
+
/**
|
|
17913
|
+
* Read-only Latch probe on this machine. In-process is the transport that can
|
|
17914
|
+
* honestly answer it: the provider only exists here when the caller device is
|
|
17915
|
+
* the execution target, so the probe runs where the agent process would run.
|
|
17916
|
+
*/
|
|
17917
|
+
async discoverLatch(input) {
|
|
17918
|
+
const executable = input.executable?.trim() || DEFAULT_LATCH_EXECUTABLE;
|
|
17919
|
+
try {
|
|
17920
|
+
const result = discoverLatchForExecutionTarget({
|
|
17921
|
+
// A resolved provider carries the target id; the desktop bridge and dev
|
|
17922
|
+
// proxy do not, so they pass the caller's id to share one cache entry
|
|
17923
|
+
// with the runner probe on the same device.
|
|
17924
|
+
executionTargetId: this.target.executionTargetId ?? (input.executionTargetId?.trim() || "local"),
|
|
17925
|
+
executable,
|
|
17926
|
+
cacheFilePath: defaultLatchDiscoveryCachePath(),
|
|
17927
|
+
force: input.force === true
|
|
17928
|
+
});
|
|
17929
|
+
return ok(this.target, result);
|
|
17930
|
+
} catch (error) {
|
|
17931
|
+
return fail(this.target, "TARGET_OPERATION_FAILED", error instanceof Error ? error.message : "Latch discovery failed on this device.");
|
|
17932
|
+
}
|
|
17933
|
+
}
|
|
17934
|
+
async inspectLatchSession(input) {
|
|
17935
|
+
try {
|
|
17936
|
+
return ok(this.target, inspectLatchSession(input));
|
|
17937
|
+
} catch (error) {
|
|
17938
|
+
return fail(this.target, "TARGET_OPERATION_FAILED", error instanceof Error ? error.message : "Could not inspect the Latch session.");
|
|
17939
|
+
}
|
|
17940
|
+
}
|
|
17941
|
+
async openLatchSession(input) {
|
|
17942
|
+
try {
|
|
17943
|
+
return ok(this.target, openLatchSession(input));
|
|
17944
|
+
} catch (error) {
|
|
17945
|
+
return fail(this.target, "TARGET_OPERATION_FAILED", error instanceof Error ? error.message : "Could not open the Latch session.");
|
|
17946
|
+
}
|
|
17947
|
+
}
|
|
17948
|
+
async stopLatchSession(input) {
|
|
17949
|
+
try {
|
|
17950
|
+
return ok(this.target, stopLatchSession(input));
|
|
17951
|
+
} catch (error) {
|
|
17952
|
+
return fail(this.target, "TARGET_OPERATION_FAILED", error instanceof Error ? error.message : "Could not stop the Latch session.");
|
|
17953
|
+
}
|
|
17954
|
+
}
|
|
17360
17955
|
async doctor() {
|
|
17361
17956
|
return ok(this.target, { checks: runLocalTargetDoctorChecks() });
|
|
17362
17957
|
}
|
|
@@ -17497,7 +18092,7 @@ var init_local_target_mutation_runner = __esm({
|
|
|
17497
18092
|
});
|
|
17498
18093
|
|
|
17499
18094
|
// ../packages/core/dist/service/project-resource-key.js
|
|
17500
|
-
import
|
|
18095
|
+
import path19 from "node:path";
|
|
17501
18096
|
function deriveProjectResourceKey({ resourceKey, label, directoryPath }) {
|
|
17502
18097
|
const explicit = resourceKey?.trim();
|
|
17503
18098
|
if (explicit)
|
|
@@ -17505,7 +18100,7 @@ function deriveProjectResourceKey({ resourceKey, label, directoryPath }) {
|
|
|
17505
18100
|
const labelKey = label?.trim();
|
|
17506
18101
|
if (labelKey)
|
|
17507
18102
|
return slugify(labelKey);
|
|
17508
|
-
return slugify(
|
|
18103
|
+
return slugify(path19.basename(path19.resolve(directoryPath)));
|
|
17509
18104
|
}
|
|
17510
18105
|
var init_project_resource_key = __esm({
|
|
17511
18106
|
"../packages/core/dist/service/project-resource-key.js"() {
|
|
@@ -17515,7 +18110,7 @@ var init_project_resource_key = __esm({
|
|
|
17515
18110
|
});
|
|
17516
18111
|
|
|
17517
18112
|
// src/branch-planning.ts
|
|
17518
|
-
import
|
|
18113
|
+
import path20 from "node:path";
|
|
17519
18114
|
function stripCombiningMarks(value) {
|
|
17520
18115
|
return value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
|
|
17521
18116
|
}
|
|
@@ -17548,7 +18143,7 @@ function missionWorktreePath({
|
|
|
17548
18143
|
branch
|
|
17549
18144
|
}) {
|
|
17550
18145
|
const key = resourceKey.trim() || "project";
|
|
17551
|
-
return
|
|
18146
|
+
return path20.join(worktreeRoot, projectSlug || "project", key, branchLeaf(branch));
|
|
17552
18147
|
}
|
|
17553
18148
|
function normalizeRemoteRef(ref) {
|
|
17554
18149
|
return ref.replace(/^origin\//, "").replace(/^refs\/heads\//, "").replace(/^refs\/remotes\/origin\//, "");
|
|
@@ -17622,13 +18217,13 @@ var init_branch_planning = __esm({
|
|
|
17622
18217
|
});
|
|
17623
18218
|
|
|
17624
18219
|
// src/branch-preparation.ts
|
|
17625
|
-
import { execFileSync as
|
|
17626
|
-
import { existsSync as
|
|
17627
|
-
import
|
|
17628
|
-
import
|
|
18220
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
18221
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync10, statSync as statSync5 } from "node:fs";
|
|
18222
|
+
import os4 from "node:os";
|
|
18223
|
+
import path21 from "node:path";
|
|
17629
18224
|
function runGit3(cwd, args, options = {}) {
|
|
17630
18225
|
try {
|
|
17631
|
-
return
|
|
18226
|
+
return execFileSync6("git", args, {
|
|
17632
18227
|
cwd,
|
|
17633
18228
|
encoding: "utf8",
|
|
17634
18229
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -17646,7 +18241,7 @@ function lines(value) {
|
|
|
17646
18241
|
function resolveGitRoot2(workingDirectory) {
|
|
17647
18242
|
const root = runGit3(workingDirectory, ["rev-parse", "--show-toplevel"]);
|
|
17648
18243
|
if (!root) throw new Error(`${workingDirectory} is not inside a git repository.`);
|
|
17649
|
-
return
|
|
18244
|
+
return path21.resolve(root);
|
|
17650
18245
|
}
|
|
17651
18246
|
function repoDefaultBranch(gitRoot) {
|
|
17652
18247
|
const symbolic = runGit3(gitRoot, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"], {
|
|
@@ -17781,9 +18376,9 @@ function missionSequence(mission, missionId) {
|
|
|
17781
18376
|
}
|
|
17782
18377
|
function resolveWorktreeRoot() {
|
|
17783
18378
|
const override = process.env.OVERLORD_WORKTREE_ROOT?.trim();
|
|
17784
|
-
if (override) return
|
|
18379
|
+
if (override) return path21.resolve(override);
|
|
17785
18380
|
const home = process.env.OVLD_HOME?.trim() || process.env.OVERLORD_HOME?.trim();
|
|
17786
|
-
return
|
|
18381
|
+
return path21.join(home ? path21.resolve(home) : path21.join(os4.homedir(), ".ovld"), "worktrees");
|
|
17787
18382
|
}
|
|
17788
18383
|
function ensureBranchRef(gitRoot, decision) {
|
|
17789
18384
|
if (decision.action === "reuse") return;
|
|
@@ -17794,9 +18389,9 @@ function ensureBranchRef(gitRoot, decision) {
|
|
|
17794
18389
|
}
|
|
17795
18390
|
function ensureWorktree(gitRoot, decision) {
|
|
17796
18391
|
ensureBranchRef(gitRoot, decision);
|
|
17797
|
-
|
|
17798
|
-
if (
|
|
17799
|
-
if (!
|
|
18392
|
+
mkdirSync10(path21.dirname(decision.worktreePath), { recursive: true });
|
|
18393
|
+
if (existsSync21(decision.worktreePath)) {
|
|
18394
|
+
if (!statSync5(decision.worktreePath).isDirectory()) {
|
|
17800
18395
|
throw new Error(`Worktree path exists and is not a directory: ${decision.worktreePath}`);
|
|
17801
18396
|
}
|
|
17802
18397
|
const existingBranch = worktreeBranch(decision.worktreePath);
|
|
@@ -17936,7 +18531,7 @@ var init_branch_preparation = __esm({
|
|
|
17936
18531
|
});
|
|
17937
18532
|
|
|
17938
18533
|
// src/discover-project-local.ts
|
|
17939
|
-
import
|
|
18534
|
+
import path22 from "node:path";
|
|
17940
18535
|
async function resolvePreferredExecutionTargetId({
|
|
17941
18536
|
backend
|
|
17942
18537
|
}) {
|
|
@@ -17953,9 +18548,9 @@ function discoverProjectJsonFromFilesystem({
|
|
|
17953
18548
|
workingDirectory,
|
|
17954
18549
|
preferredExecutionTargetId
|
|
17955
18550
|
}) {
|
|
17956
|
-
let current =
|
|
18551
|
+
let current = path22.resolve(workingDirectory);
|
|
17957
18552
|
while (true) {
|
|
17958
|
-
const projectJsonPath =
|
|
18553
|
+
const projectJsonPath = path22.join(current, ".overlord", "project.json");
|
|
17959
18554
|
const raw = readProjectJsonLink(projectJsonPath, { preferredExecutionTargetId });
|
|
17960
18555
|
if (raw) {
|
|
17961
18556
|
return {
|
|
@@ -17965,7 +18560,7 @@ function discoverProjectJsonFromFilesystem({
|
|
|
17965
18560
|
isPrimary: raw.isPrimary
|
|
17966
18561
|
};
|
|
17967
18562
|
}
|
|
17968
|
-
const parent =
|
|
18563
|
+
const parent = path22.dirname(current);
|
|
17969
18564
|
if (parent === current) break;
|
|
17970
18565
|
current = parent;
|
|
17971
18566
|
}
|
|
@@ -17975,16 +18570,16 @@ async function resolveProjectByIdOrName({
|
|
|
17975
18570
|
backend,
|
|
17976
18571
|
projectRef
|
|
17977
18572
|
}) {
|
|
17978
|
-
const
|
|
18573
|
+
const trimmed5 = projectRef.trim();
|
|
17979
18574
|
try {
|
|
17980
|
-
return await backend.get(`/api/projects/${encodeURIComponent(
|
|
18575
|
+
return await backend.get(`/api/projects/${encodeURIComponent(trimmed5)}`);
|
|
17981
18576
|
} catch (error) {
|
|
17982
18577
|
if (!(error instanceof CliError) || !/project not found/i.test(error.message)) throw error;
|
|
17983
18578
|
}
|
|
17984
18579
|
const projects = await listAccessibleProjects({ backend });
|
|
17985
|
-
const match = projects.find((project) => project.name ===
|
|
18580
|
+
const match = projects.find((project) => project.name === trimmed5) ?? projects.find((project) => project.slug === trimmed5);
|
|
17986
18581
|
if (!match) {
|
|
17987
|
-
throw new CliError({ message: `Project not found: ${
|
|
18582
|
+
throw new CliError({ message: `Project not found: ${trimmed5}` });
|
|
17988
18583
|
}
|
|
17989
18584
|
return match;
|
|
17990
18585
|
}
|
|
@@ -18025,7 +18620,7 @@ async function discoverProjectOnClient({
|
|
|
18025
18620
|
const resolvedLocal = localWithTarget ?? local;
|
|
18026
18621
|
if (!resolvedLocal) {
|
|
18027
18622
|
throw new CliError({
|
|
18028
|
-
message: `No linked Overlord project found for ${
|
|
18623
|
+
message: `No linked Overlord project found for ${path22.resolve(workingDirectory)}. Run \`ovld add-cwd\` or \`ovld create-project\`.`
|
|
18029
18624
|
});
|
|
18030
18625
|
}
|
|
18031
18626
|
const project = await resolveProjectByIdOrName({ backend, projectRef: resolvedLocal.projectId });
|
|
@@ -18045,6 +18640,134 @@ var init_discover_project_local = __esm({
|
|
|
18045
18640
|
}
|
|
18046
18641
|
});
|
|
18047
18642
|
|
|
18643
|
+
// src/latch-discovery.ts
|
|
18644
|
+
import path23 from "node:path";
|
|
18645
|
+
function latchDiscoveryCachePath(dataDir = resolveGlobalDataDir()) {
|
|
18646
|
+
return path23.join(dataDir, LATCH_DISCOVERY_CACHE_FILENAME);
|
|
18647
|
+
}
|
|
18648
|
+
function discoverLatchOnThisDevice({
|
|
18649
|
+
executionTargetId,
|
|
18650
|
+
executable = DEFAULT_LATCH_EXECUTABLE,
|
|
18651
|
+
force = false
|
|
18652
|
+
}) {
|
|
18653
|
+
return discoverLatchForExecutionTarget({
|
|
18654
|
+
executionTargetId,
|
|
18655
|
+
executable,
|
|
18656
|
+
cacheFilePath: latchDiscoveryCachePath(),
|
|
18657
|
+
force
|
|
18658
|
+
});
|
|
18659
|
+
}
|
|
18660
|
+
var init_latch_discovery2 = __esm({
|
|
18661
|
+
"src/latch-discovery.ts"() {
|
|
18662
|
+
"use strict";
|
|
18663
|
+
init_latch_discovery();
|
|
18664
|
+
init_terminal_profile_types2();
|
|
18665
|
+
init_config();
|
|
18666
|
+
}
|
|
18667
|
+
});
|
|
18668
|
+
|
|
18669
|
+
// src/latch-launch.ts
|
|
18670
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
18671
|
+
function spawnLatchJson({
|
|
18672
|
+
executable,
|
|
18673
|
+
args,
|
|
18674
|
+
stdin
|
|
18675
|
+
}) {
|
|
18676
|
+
const result = spawnSync3(executable, args, {
|
|
18677
|
+
encoding: "utf8",
|
|
18678
|
+
input: stdin,
|
|
18679
|
+
env: process.env,
|
|
18680
|
+
maxBuffer: 2 * 1024 * 1024
|
|
18681
|
+
});
|
|
18682
|
+
return {
|
|
18683
|
+
status: result.status,
|
|
18684
|
+
stdout: result.stdout ?? "",
|
|
18685
|
+
stderr: result.stderr ?? ""
|
|
18686
|
+
};
|
|
18687
|
+
}
|
|
18688
|
+
function createLatchSession({
|
|
18689
|
+
executable = DEFAULT_LATCH_EXECUTABLE,
|
|
18690
|
+
commandString,
|
|
18691
|
+
cwd,
|
|
18692
|
+
env,
|
|
18693
|
+
title,
|
|
18694
|
+
name,
|
|
18695
|
+
commandLabel,
|
|
18696
|
+
externalRunId,
|
|
18697
|
+
executionTargetId,
|
|
18698
|
+
shell = process.env.SHELL?.trim() || "/bin/bash"
|
|
18699
|
+
}) {
|
|
18700
|
+
const manifest = buildLatchCreateManifest({
|
|
18701
|
+
commandString,
|
|
18702
|
+
shell,
|
|
18703
|
+
cwd,
|
|
18704
|
+
env,
|
|
18705
|
+
title,
|
|
18706
|
+
name,
|
|
18707
|
+
commandLabel,
|
|
18708
|
+
externalRunId
|
|
18709
|
+
});
|
|
18710
|
+
const result = spawnLatchJson({
|
|
18711
|
+
executable,
|
|
18712
|
+
args: ["create", "--manifest-file", "-", "--json"],
|
|
18713
|
+
stdin: `${JSON.stringify(manifest)}
|
|
18714
|
+
`
|
|
18715
|
+
});
|
|
18716
|
+
if (result.status !== 0) {
|
|
18717
|
+
const detail = (result.stderr || result.stdout || `exit ${result.status ?? "null"}`).trim();
|
|
18718
|
+
throw new Error(`latch create failed: ${detail}`);
|
|
18719
|
+
}
|
|
18720
|
+
const report = parseLatchCreateReport(result.stdout);
|
|
18721
|
+
if (!report) {
|
|
18722
|
+
throw new Error(
|
|
18723
|
+
`latch create returned unusable JSON: ${(result.stdout || result.stderr).trim() || "(empty)"}`
|
|
18724
|
+
);
|
|
18725
|
+
}
|
|
18726
|
+
return {
|
|
18727
|
+
report,
|
|
18728
|
+
providerSession: toExecutionProviderSession({
|
|
18729
|
+
createReport: report,
|
|
18730
|
+
executionTargetId
|
|
18731
|
+
}),
|
|
18732
|
+
executable
|
|
18733
|
+
};
|
|
18734
|
+
}
|
|
18735
|
+
function openLatchViewer({
|
|
18736
|
+
executable = DEFAULT_LATCH_EXECUTABLE,
|
|
18737
|
+
providerSessionId,
|
|
18738
|
+
viewerKind
|
|
18739
|
+
}) {
|
|
18740
|
+
const viewer = latchViewerFlagForKind(viewerKind);
|
|
18741
|
+
const attachCommand = latchAttachCommand({ executable, providerSessionId });
|
|
18742
|
+
if (!viewer) {
|
|
18743
|
+
return {
|
|
18744
|
+
ok: false,
|
|
18745
|
+
warning: `Latch has no viewer for kind "${viewerKind ?? "unknown"}"; session is running \u2014 attach with: ${attachCommand}`,
|
|
18746
|
+
attachCommand
|
|
18747
|
+
};
|
|
18748
|
+
}
|
|
18749
|
+
const result = spawnLatchJson({
|
|
18750
|
+
executable,
|
|
18751
|
+
args: ["open", providerSessionId, "--with", viewer, "--json"]
|
|
18752
|
+
});
|
|
18753
|
+
if (result.status !== 0) {
|
|
18754
|
+
const detail = (result.stderr || result.stdout || `exit ${result.status ?? "null"}`).trim();
|
|
18755
|
+
return {
|
|
18756
|
+
ok: false,
|
|
18757
|
+
warning: `latch open failed (${detail}); session is running \u2014 attach with: ${attachCommand}`,
|
|
18758
|
+
attachCommand
|
|
18759
|
+
};
|
|
18760
|
+
}
|
|
18761
|
+
return { ok: true, viewer };
|
|
18762
|
+
}
|
|
18763
|
+
var init_latch_launch2 = __esm({
|
|
18764
|
+
"src/latch-launch.ts"() {
|
|
18765
|
+
"use strict";
|
|
18766
|
+
init_latch_launch();
|
|
18767
|
+
init_terminal_profile_types2();
|
|
18768
|
+
}
|
|
18769
|
+
});
|
|
18770
|
+
|
|
18048
18771
|
// src/pre-launch.ts
|
|
18049
18772
|
function substitutePreLaunchVariables(commands, variables) {
|
|
18050
18773
|
return commands.map(
|
|
@@ -18072,10 +18795,10 @@ function primaryResourcePath(projectResources) {
|
|
|
18072
18795
|
for (const entry of projectResources) {
|
|
18073
18796
|
if (!entry || typeof entry !== "object") continue;
|
|
18074
18797
|
const record = entry;
|
|
18075
|
-
const
|
|
18076
|
-
if (!
|
|
18077
|
-
if (record.isPrimary === true) return
|
|
18078
|
-
if (record.isCurrent === true && !currentPath) currentPath =
|
|
18798
|
+
const path34 = typeof record.path === "string" ? record.path.trim() : "";
|
|
18799
|
+
if (!path34) continue;
|
|
18800
|
+
if (record.isPrimary === true) return path34;
|
|
18801
|
+
if (record.isCurrent === true && !currentPath) currentPath = path34;
|
|
18079
18802
|
}
|
|
18080
18803
|
return currentPath;
|
|
18081
18804
|
}
|
|
@@ -18175,7 +18898,7 @@ function terminalInnerCommand({
|
|
|
18175
18898
|
const invocation = withPreLaunchCommands(agentCommand, preLaunchCommands);
|
|
18176
18899
|
return `cd ${shellQuote2(workingDirectory)} && ${exports}; ${invocation}`;
|
|
18177
18900
|
}
|
|
18178
|
-
function
|
|
18901
|
+
function composeAgentTerminalCommand({
|
|
18179
18902
|
command,
|
|
18180
18903
|
args,
|
|
18181
18904
|
workingDirectory,
|
|
@@ -18184,8 +18907,25 @@ function terminalLaunchScriptContent({
|
|
|
18184
18907
|
preLaunchCommands
|
|
18185
18908
|
}) {
|
|
18186
18909
|
const agentCommand = agentShellCommand({ command, args, preCommand });
|
|
18910
|
+
return terminalInnerCommand({ workingDirectory, agentCommand, extraEnv, preLaunchCommands });
|
|
18911
|
+
}
|
|
18912
|
+
function terminalLaunchScriptContent({
|
|
18913
|
+
command,
|
|
18914
|
+
args,
|
|
18915
|
+
workingDirectory,
|
|
18916
|
+
preCommand,
|
|
18917
|
+
extraEnv = {},
|
|
18918
|
+
preLaunchCommands
|
|
18919
|
+
}) {
|
|
18187
18920
|
return `#!/usr/bin/env bash
|
|
18188
|
-
${
|
|
18921
|
+
${composeAgentTerminalCommand({
|
|
18922
|
+
command,
|
|
18923
|
+
args,
|
|
18924
|
+
workingDirectory,
|
|
18925
|
+
preCommand,
|
|
18926
|
+
extraEnv,
|
|
18927
|
+
preLaunchCommands
|
|
18928
|
+
})}
|
|
18189
18929
|
`;
|
|
18190
18930
|
}
|
|
18191
18931
|
function terminalScriptCommand(scriptPath) {
|
|
@@ -18426,9 +19166,9 @@ var init_terminal_launcher = __esm({
|
|
|
18426
19166
|
});
|
|
18427
19167
|
|
|
18428
19168
|
// src/launch.ts
|
|
18429
|
-
import { spawnSync as
|
|
18430
|
-
import { chmodSync as chmodSync4, writeFileSync as
|
|
18431
|
-
import
|
|
19169
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
19170
|
+
import { chmodSync as chmodSync4, writeFileSync as writeFileSync9 } from "node:fs";
|
|
19171
|
+
import path24 from "node:path";
|
|
18432
19172
|
function overlordLaunchEnv({
|
|
18433
19173
|
backendUrl,
|
|
18434
19174
|
missionId,
|
|
@@ -18594,7 +19334,7 @@ function launchScriptPath({
|
|
|
18594
19334
|
executionRequestId
|
|
18595
19335
|
}) {
|
|
18596
19336
|
const requestPart = executionRequestId ? safeLaunchScriptPart(executionRequestId) : `${process.pid}`;
|
|
18597
|
-
return
|
|
19337
|
+
return path24.join(tmpDir, `launch-${safeLaunchScriptPart(displayId)}-${requestPart}.sh`);
|
|
18598
19338
|
}
|
|
18599
19339
|
async function buildLaunchPlan({
|
|
18600
19340
|
runtime,
|
|
@@ -18603,12 +19343,12 @@ async function buildLaunchPlan({
|
|
|
18603
19343
|
const context = await loadMissionContext({ runtime, missionId: options.missionId });
|
|
18604
19344
|
pruneStaleProjectTmp({ workingDirectory: options.workingDirectory, create: true });
|
|
18605
19345
|
const tmpDir = ensureProjectTmpDir(options.workingDirectory);
|
|
18606
|
-
const contextFile =
|
|
19346
|
+
const contextFile = path24.join(
|
|
18607
19347
|
tmpDir,
|
|
18608
19348
|
`mission-${context.displayId.replace(/[^a-zA-Z0-9_-]/g, "-")}.md`
|
|
18609
19349
|
);
|
|
18610
19350
|
const launchContext = context.launchContext;
|
|
18611
|
-
|
|
19351
|
+
writeFileSync9(contextFile, `${launchContext}
|
|
18612
19352
|
`);
|
|
18613
19353
|
const projectResources = await loadProjectResourcesForLaunch({
|
|
18614
19354
|
runtime,
|
|
@@ -18653,13 +19393,21 @@ async function buildLaunchPlan({
|
|
|
18653
19393
|
contextFile,
|
|
18654
19394
|
launchMessage: `Attach to ovld mission ${context.displayId}, then immediately execute ${context.title}. Do not wait for more instructions.`
|
|
18655
19395
|
});
|
|
19396
|
+
const latchCommandString = composeAgentTerminalCommand({
|
|
19397
|
+
command: command.command,
|
|
19398
|
+
args: command.args,
|
|
19399
|
+
workingDirectory: options.workingDirectory,
|
|
19400
|
+
preCommand: options.preCommand,
|
|
19401
|
+
extraEnv: exportedEnv,
|
|
19402
|
+
preLaunchCommands
|
|
19403
|
+
});
|
|
18656
19404
|
const terminalScriptPath = options.terminalLauncher?.trim() ? launchScriptPath({
|
|
18657
19405
|
tmpDir,
|
|
18658
19406
|
displayId: context.displayId,
|
|
18659
19407
|
executionRequestId: options.executionRequestId
|
|
18660
19408
|
}) : null;
|
|
18661
19409
|
if (terminalScriptPath) {
|
|
18662
|
-
|
|
19410
|
+
writeFileSync9(
|
|
18663
19411
|
terminalScriptPath,
|
|
18664
19412
|
terminalLaunchScriptContent({
|
|
18665
19413
|
command: command.command,
|
|
@@ -18691,7 +19439,11 @@ async function buildLaunchPlan({
|
|
|
18691
19439
|
contextFile,
|
|
18692
19440
|
workingDirectory: options.workingDirectory,
|
|
18693
19441
|
execution,
|
|
18694
|
-
env: exportedEnv
|
|
19442
|
+
env: exportedEnv,
|
|
19443
|
+
latchCommandString,
|
|
19444
|
+
launchSession: options.launchSession ?? null,
|
|
19445
|
+
missionTitle: options.missionTitle ?? context.title,
|
|
19446
|
+
missionDisplayId: options.missionDisplayId ?? context.displayId
|
|
18695
19447
|
};
|
|
18696
19448
|
}
|
|
18697
19449
|
async function launchAgent({
|
|
@@ -18707,26 +19459,130 @@ async function launchAgent({
|
|
|
18707
19459
|
...tmpEnvFor(options.workingDirectory),
|
|
18708
19460
|
...plan.env
|
|
18709
19461
|
};
|
|
19462
|
+
const snapshot = options.launchSession ?? plan.launchSession ?? null;
|
|
19463
|
+
const providerKind = snapshot?.executionProvider.kind ?? "direct";
|
|
19464
|
+
const executable = snapshot?.executionProvider.executable ?? "latch";
|
|
19465
|
+
let providerFallbackWarning = null;
|
|
19466
|
+
let useLatch = false;
|
|
19467
|
+
let resolvedLatchExecutable = executable;
|
|
19468
|
+
const existingProviderSession = providerKind === "latch" ? existingLatchProviderSession({
|
|
19469
|
+
latchSessionId: process.env.LATCH_SESSION_ID,
|
|
19470
|
+
executionTargetId: options.executionTargetId
|
|
19471
|
+
}) : null;
|
|
19472
|
+
if (existingProviderSession && plan.latchCommandString) {
|
|
19473
|
+
const shell = process.env.SHELL?.trim() || "/bin/bash";
|
|
19474
|
+
const result2 = spawnSync4(shell, ["-lc", plan.latchCommandString], {
|
|
19475
|
+
cwd: options.workingDirectory,
|
|
19476
|
+
env,
|
|
19477
|
+
stdio: "inherit"
|
|
19478
|
+
});
|
|
19479
|
+
return {
|
|
19480
|
+
plan: {
|
|
19481
|
+
...plan,
|
|
19482
|
+
execution: {
|
|
19483
|
+
command: shell,
|
|
19484
|
+
args: ["-lc", plan.latchCommandString],
|
|
19485
|
+
useShell: false,
|
|
19486
|
+
terminal: null,
|
|
19487
|
+
display: `Latch session ${existingProviderSession.providerSessionId} (inline) \u203A ${plan.latchCommandString}`
|
|
19488
|
+
}
|
|
19489
|
+
},
|
|
19490
|
+
status: result2.status,
|
|
19491
|
+
signal: result2.signal,
|
|
19492
|
+
providerSession: existingProviderSession,
|
|
19493
|
+
viewerOpen: null,
|
|
19494
|
+
providerFallbackWarning
|
|
19495
|
+
};
|
|
19496
|
+
}
|
|
19497
|
+
if (providerKind === "latch") {
|
|
19498
|
+
if (!options.executionTargetId) {
|
|
19499
|
+
providerFallbackWarning = "Latch provider selected but no execution target id is available; falling back to direct launch.";
|
|
19500
|
+
} else {
|
|
19501
|
+
const discovery = discoverLatchOnThisDevice({
|
|
19502
|
+
executionTargetId: options.executionTargetId,
|
|
19503
|
+
executable
|
|
19504
|
+
});
|
|
19505
|
+
useLatch = shouldUseLatchProvider({
|
|
19506
|
+
providerKind,
|
|
19507
|
+
latchSelectable: discovery.latchSelectable
|
|
19508
|
+
});
|
|
19509
|
+
if (useLatch && discovery.state === "found") {
|
|
19510
|
+
resolvedLatchExecutable = discovery.resolvedPath;
|
|
19511
|
+
}
|
|
19512
|
+
if (!useLatch) {
|
|
19513
|
+
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.";
|
|
19514
|
+
}
|
|
19515
|
+
}
|
|
19516
|
+
}
|
|
19517
|
+
if (useLatch && plan.latchCommandString) {
|
|
19518
|
+
const created = createLatchSession({
|
|
19519
|
+
executable: resolvedLatchExecutable,
|
|
19520
|
+
commandString: plan.latchCommandString,
|
|
19521
|
+
cwd: options.workingDirectory,
|
|
19522
|
+
env: plan.env,
|
|
19523
|
+
title: plan.missionTitle,
|
|
19524
|
+
name: plan.missionDisplayId,
|
|
19525
|
+
commandLabel: options.agent,
|
|
19526
|
+
externalRunId: options.executionRequestId,
|
|
19527
|
+
executionTargetId: options.executionTargetId
|
|
19528
|
+
});
|
|
19529
|
+
let viewerOpen = null;
|
|
19530
|
+
const openOnLaunch = snapshot?.viewer.openOnLaunch !== false;
|
|
19531
|
+
if (openOnLaunch) {
|
|
19532
|
+
viewerOpen = openLatchViewer({
|
|
19533
|
+
executable: resolvedLatchExecutable,
|
|
19534
|
+
providerSessionId: created.providerSession.providerSessionId,
|
|
19535
|
+
viewerKind: snapshot?.viewer.kind ?? "iterm"
|
|
19536
|
+
});
|
|
19537
|
+
}
|
|
19538
|
+
return {
|
|
19539
|
+
plan: {
|
|
19540
|
+
...plan,
|
|
19541
|
+
execution: {
|
|
19542
|
+
command: resolvedLatchExecutable,
|
|
19543
|
+
args: ["create", "--manifest-file", "-", "--json"],
|
|
19544
|
+
useShell: false,
|
|
19545
|
+
terminal: snapshot?.viewer.launcher ?? null,
|
|
19546
|
+
display: `latch create \u203A ${plan.latchCommandString}`
|
|
19547
|
+
}
|
|
19548
|
+
},
|
|
19549
|
+
status: 0,
|
|
19550
|
+
signal: null,
|
|
19551
|
+
providerSession: created.providerSession,
|
|
19552
|
+
viewerOpen,
|
|
19553
|
+
providerFallbackWarning
|
|
19554
|
+
};
|
|
19555
|
+
}
|
|
18710
19556
|
const { execution } = plan;
|
|
18711
|
-
const result = execution.useShell ?
|
|
19557
|
+
const result = execution.useShell ? spawnSync4(execution.command, {
|
|
18712
19558
|
cwd: options.workingDirectory,
|
|
18713
19559
|
env,
|
|
18714
19560
|
shell: true,
|
|
18715
19561
|
stdio: "inherit"
|
|
18716
|
-
}) :
|
|
19562
|
+
}) : spawnSync4(execution.command, execution.args, {
|
|
18717
19563
|
cwd: options.workingDirectory,
|
|
18718
19564
|
env,
|
|
18719
19565
|
stdio: "inherit"
|
|
18720
19566
|
});
|
|
18721
|
-
return {
|
|
19567
|
+
return {
|
|
19568
|
+
plan,
|
|
19569
|
+
status: result.status,
|
|
19570
|
+
signal: result.signal,
|
|
19571
|
+
providerSession: null,
|
|
19572
|
+
viewerOpen: null,
|
|
19573
|
+
providerFallbackWarning
|
|
19574
|
+
};
|
|
18722
19575
|
}
|
|
18723
19576
|
var AGENT_HISTORY_EXCLUDED_EVENT_TYPES, EXECUTION_DIRECTIVE;
|
|
18724
19577
|
var init_launch = __esm({
|
|
18725
19578
|
"src/launch.ts"() {
|
|
18726
19579
|
"use strict";
|
|
18727
19580
|
init_dist2();
|
|
19581
|
+
init_latch_launch();
|
|
18728
19582
|
init_channel();
|
|
18729
19583
|
init_agent_binaries();
|
|
19584
|
+
init_latch_discovery2();
|
|
19585
|
+
init_latch_launch2();
|
|
18730
19586
|
init_pre_launch();
|
|
18731
19587
|
init_project_tmp();
|
|
18732
19588
|
init_terminal_launcher();
|
|
@@ -18740,8 +19596,8 @@ var init_launch = __esm({
|
|
|
18740
19596
|
});
|
|
18741
19597
|
|
|
18742
19598
|
// src/launch-bootstrap.ts
|
|
18743
|
-
import { existsSync as
|
|
18744
|
-
import
|
|
19599
|
+
import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
|
|
19600
|
+
import path25 from "node:path";
|
|
18745
19601
|
function firstCapture(match) {
|
|
18746
19602
|
if (!match) return null;
|
|
18747
19603
|
const value = match[1] ?? match[2] ?? match[3] ?? null;
|
|
@@ -18762,15 +19618,15 @@ function recoverLaunchBootstrapFromProjectTmp({
|
|
|
18762
19618
|
const trimmedMission = missionId.trim();
|
|
18763
19619
|
if (!trimmedMission) return empty;
|
|
18764
19620
|
const tmpDir = projectTmpDir(workingDirectory);
|
|
18765
|
-
if (!
|
|
19621
|
+
if (!existsSync22(tmpDir)) return empty;
|
|
18766
19622
|
const prefix = `launch-${safeMissionPart(trimmedMission)}-`;
|
|
18767
19623
|
let newest = null;
|
|
18768
19624
|
try {
|
|
18769
19625
|
for (const name of readdirSync4(tmpDir)) {
|
|
18770
19626
|
if (!name.startsWith(prefix) || !name.endsWith(".sh")) continue;
|
|
18771
|
-
const filePath =
|
|
19627
|
+
const filePath = path25.join(tmpDir, name);
|
|
18772
19628
|
try {
|
|
18773
|
-
const mtimeMs =
|
|
19629
|
+
const mtimeMs = statSync6(filePath).mtimeMs;
|
|
18774
19630
|
if (!newest || mtimeMs > newest.mtimeMs) {
|
|
18775
19631
|
newest = { path: filePath, mtimeMs };
|
|
18776
19632
|
}
|
|
@@ -18783,7 +19639,7 @@ function recoverLaunchBootstrapFromProjectTmp({
|
|
|
18783
19639
|
if (!newest) return empty;
|
|
18784
19640
|
let contents = "";
|
|
18785
19641
|
try {
|
|
18786
|
-
contents =
|
|
19642
|
+
contents = readFileSync16(newest.path, "utf8");
|
|
18787
19643
|
} catch {
|
|
18788
19644
|
return empty;
|
|
18789
19645
|
}
|
|
@@ -18804,8 +19660,8 @@ var init_launch_bootstrap = __esm({
|
|
|
18804
19660
|
});
|
|
18805
19661
|
|
|
18806
19662
|
// src/org-setup.ts
|
|
18807
|
-
import { readFileSync as
|
|
18808
|
-
import
|
|
19663
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
19664
|
+
import path26 from "node:path";
|
|
18809
19665
|
import { createInterface as createInterface3 } from "node:readline";
|
|
18810
19666
|
function suggestSlug(name) {
|
|
18811
19667
|
const cleaned = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -18820,8 +19676,8 @@ function promptText({
|
|
|
18820
19676
|
return new Promise((resolve) => {
|
|
18821
19677
|
rl.question(`${question}${suffix}: `, (answer) => {
|
|
18822
19678
|
rl.close();
|
|
18823
|
-
const
|
|
18824
|
-
resolve(
|
|
19679
|
+
const trimmed5 = answer.trim();
|
|
19680
|
+
resolve(trimmed5 || defaultValue || "");
|
|
18825
19681
|
});
|
|
18826
19682
|
});
|
|
18827
19683
|
}
|
|
@@ -18884,12 +19740,12 @@ async function runOrgSetupCommand({
|
|
|
18884
19740
|
let logoWarning = null;
|
|
18885
19741
|
if (logoPath) {
|
|
18886
19742
|
try {
|
|
18887
|
-
const resolvedPath =
|
|
18888
|
-
const bytes =
|
|
19743
|
+
const resolvedPath = path26.resolve(logoPath);
|
|
19744
|
+
const bytes = readFileSync17(resolvedPath);
|
|
18889
19745
|
const stored = await runtime.backend.postRaw({
|
|
18890
19746
|
path: "/api/uploads/organization-images",
|
|
18891
19747
|
body: bytes,
|
|
18892
|
-
filename:
|
|
19748
|
+
filename: path26.basename(resolvedPath)
|
|
18893
19749
|
});
|
|
18894
19750
|
await runtime.backend.patch({
|
|
18895
19751
|
path: `/api/organizations/${encodeURIComponent(organization.id)}`,
|
|
@@ -19384,17 +20240,17 @@ var init_protocol_help = __esm({
|
|
|
19384
20240
|
|
|
19385
20241
|
// src/vcs-sessions.ts
|
|
19386
20242
|
import { createHash as createHash8 } from "node:crypto";
|
|
19387
|
-
import { existsSync as
|
|
19388
|
-
import
|
|
20243
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync10 } from "node:fs";
|
|
20244
|
+
import path27 from "node:path";
|
|
19389
20245
|
function manifestPath2(workingDirectory) {
|
|
19390
|
-
const key = createHash8("sha256").update(
|
|
19391
|
-
return
|
|
20246
|
+
const key = createHash8("sha256").update(path27.resolve(workingDirectory)).digest("hex");
|
|
20247
|
+
return path27.join(resolveGlobalDataDir(), "vcs-sessions", `${key}.json`);
|
|
19392
20248
|
}
|
|
19393
20249
|
function readEntries(workingDirectory) {
|
|
19394
20250
|
try {
|
|
19395
20251
|
const target = manifestPath2(workingDirectory);
|
|
19396
|
-
if (!
|
|
19397
|
-
const raw = JSON.parse(
|
|
20252
|
+
if (!existsSync23(target)) return [];
|
|
20253
|
+
const raw = JSON.parse(readFileSync18(target, "utf8"));
|
|
19398
20254
|
if (!Array.isArray(raw.entries)) return [];
|
|
19399
20255
|
const now = Date.now();
|
|
19400
20256
|
return raw.entries.flatMap((entry) => {
|
|
@@ -19413,8 +20269,8 @@ function readEntries(workingDirectory) {
|
|
|
19413
20269
|
function writeEntries(workingDirectory, entries) {
|
|
19414
20270
|
try {
|
|
19415
20271
|
const target = manifestPath2(workingDirectory);
|
|
19416
|
-
|
|
19417
|
-
|
|
20272
|
+
mkdirSync11(path27.dirname(target), { recursive: true });
|
|
20273
|
+
writeFileSync10(target, JSON.stringify({ entries }));
|
|
19418
20274
|
} catch {
|
|
19419
20275
|
}
|
|
19420
20276
|
}
|
|
@@ -19464,23 +20320,23 @@ var init_vcs_sessions = __esm({
|
|
|
19464
20320
|
});
|
|
19465
20321
|
|
|
19466
20322
|
// src/vcs.ts
|
|
19467
|
-
import { execFileSync as
|
|
20323
|
+
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
19468
20324
|
import { createHash as createHash9 } from "node:crypto";
|
|
19469
20325
|
import {
|
|
19470
|
-
existsSync as
|
|
19471
|
-
mkdirSync as
|
|
20326
|
+
existsSync as existsSync24,
|
|
20327
|
+
mkdirSync as mkdirSync12,
|
|
19472
20328
|
readdirSync as readdirSync5,
|
|
19473
|
-
readFileSync as
|
|
20329
|
+
readFileSync as readFileSync19,
|
|
19474
20330
|
realpathSync as realpathSync3,
|
|
19475
20331
|
rmSync as rmSync5,
|
|
19476
|
-
writeFileSync as
|
|
20332
|
+
writeFileSync as writeFileSync11
|
|
19477
20333
|
} from "node:fs";
|
|
19478
|
-
import
|
|
20334
|
+
import path28 from "node:path";
|
|
19479
20335
|
function normalizePath(filePath) {
|
|
19480
20336
|
return filePath.replace(/\\/g, "/").trim();
|
|
19481
20337
|
}
|
|
19482
20338
|
function sameWorkingDirectory(left, right) {
|
|
19483
|
-
return typeof left === "string" &&
|
|
20339
|
+
return typeof left === "string" && path28.resolve(left) === path28.resolve(right);
|
|
19484
20340
|
}
|
|
19485
20341
|
function parsePorcelainLine(line) {
|
|
19486
20342
|
const trimmedEnd = line.replace(/\s+$/, "");
|
|
@@ -19500,7 +20356,7 @@ function hashWorktreeFile({
|
|
|
19500
20356
|
filePath
|
|
19501
20357
|
}) {
|
|
19502
20358
|
try {
|
|
19503
|
-
return
|
|
20359
|
+
return execFileSync7("git", ["hash-object", filePath], {
|
|
19504
20360
|
cwd: workingDirectory,
|
|
19505
20361
|
encoding: "utf8",
|
|
19506
20362
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -19511,7 +20367,7 @@ function hashWorktreeFile({
|
|
|
19511
20367
|
}
|
|
19512
20368
|
function readChangedFiles(workingDirectory) {
|
|
19513
20369
|
try {
|
|
19514
|
-
const output =
|
|
20370
|
+
const output = execFileSync7("git", ["status", "--porcelain"], {
|
|
19515
20371
|
cwd: workingDirectory,
|
|
19516
20372
|
encoding: "utf8",
|
|
19517
20373
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -19531,13 +20387,13 @@ function sessionKeyHash({
|
|
|
19531
20387
|
workingDirectory,
|
|
19532
20388
|
missionId
|
|
19533
20389
|
}) {
|
|
19534
|
-
return createHash9("sha256").update(`${
|
|
20390
|
+
return createHash9("sha256").update(`${path28.resolve(workingDirectory)}\0${missionId}`).digest("hex");
|
|
19535
20391
|
}
|
|
19536
20392
|
function baselineFilePath({
|
|
19537
20393
|
workingDirectory,
|
|
19538
20394
|
missionId
|
|
19539
20395
|
}) {
|
|
19540
|
-
return
|
|
20396
|
+
return path28.join(
|
|
19541
20397
|
resolveGlobalDataDir(),
|
|
19542
20398
|
"vcs-baselines",
|
|
19543
20399
|
`${sessionKeyHash({ workingDirectory, missionId })}.json`
|
|
@@ -19547,7 +20403,7 @@ function touchedFilesPath({
|
|
|
19547
20403
|
workingDirectory,
|
|
19548
20404
|
missionId
|
|
19549
20405
|
}) {
|
|
19550
|
-
return
|
|
20406
|
+
return path28.join(
|
|
19551
20407
|
resolveGlobalDataDir(),
|
|
19552
20408
|
"vcs-touched",
|
|
19553
20409
|
`${sessionKeyHash({ workingDirectory, missionId })}.json`
|
|
@@ -19557,7 +20413,7 @@ function rationaleNotesPath({
|
|
|
19557
20413
|
workingDirectory,
|
|
19558
20414
|
missionId
|
|
19559
20415
|
}) {
|
|
19560
|
-
return
|
|
20416
|
+
return path28.join(
|
|
19561
20417
|
resolveGlobalDataDir(),
|
|
19562
20418
|
"vcs-rationale-notes",
|
|
19563
20419
|
`${sessionKeyHash({ workingDirectory, missionId })}.json`
|
|
@@ -19567,7 +20423,7 @@ function bashSnapshotPath({
|
|
|
19567
20423
|
workingDirectory,
|
|
19568
20424
|
missionId
|
|
19569
20425
|
}) {
|
|
19570
|
-
return
|
|
20426
|
+
return path28.join(
|
|
19571
20427
|
resolveGlobalDataDir(),
|
|
19572
20428
|
"vcs-touched",
|
|
19573
20429
|
`${sessionKeyHash({ workingDirectory, missionId })}.bash-snapshot.json`
|
|
@@ -19579,8 +20435,8 @@ function readBashSnapshot({
|
|
|
19579
20435
|
}) {
|
|
19580
20436
|
try {
|
|
19581
20437
|
const target = bashSnapshotPath({ workingDirectory, missionId });
|
|
19582
|
-
if (!
|
|
19583
|
-
const raw = JSON.parse(
|
|
20438
|
+
if (!existsSync24(target)) return /* @__PURE__ */ new Map();
|
|
20439
|
+
const raw = JSON.parse(readFileSync19(target, "utf8"));
|
|
19584
20440
|
const byPath = /* @__PURE__ */ new Map();
|
|
19585
20441
|
if (Array.isArray(raw.files)) {
|
|
19586
20442
|
for (const entry of raw.files) {
|
|
@@ -19605,8 +20461,8 @@ function writeBashSnapshot({
|
|
|
19605
20461
|
}) {
|
|
19606
20462
|
try {
|
|
19607
20463
|
const target = bashSnapshotPath({ workingDirectory, missionId });
|
|
19608
|
-
|
|
19609
|
-
|
|
20464
|
+
mkdirSync12(path28.dirname(target), { recursive: true });
|
|
20465
|
+
writeFileSync11(target, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString(), files }));
|
|
19610
20466
|
} catch {
|
|
19611
20467
|
}
|
|
19612
20468
|
}
|
|
@@ -19639,12 +20495,12 @@ function recordBashObservedChanges({
|
|
|
19639
20495
|
}
|
|
19640
20496
|
}
|
|
19641
20497
|
function normalizeAbsolute(filePath) {
|
|
19642
|
-
const resolved =
|
|
20498
|
+
const resolved = path28.resolve(filePath);
|
|
19643
20499
|
try {
|
|
19644
20500
|
return realpathSync3(resolved).replace(/\\/g, "/");
|
|
19645
20501
|
} catch {
|
|
19646
20502
|
try {
|
|
19647
|
-
return
|
|
20503
|
+
return path28.join(realpathSync3(path28.dirname(resolved)), path28.basename(resolved)).replace(/\\/g, "/");
|
|
19648
20504
|
} catch {
|
|
19649
20505
|
return resolved.replace(/\\/g, "/");
|
|
19650
20506
|
}
|
|
@@ -19652,7 +20508,7 @@ function normalizeAbsolute(filePath) {
|
|
|
19652
20508
|
}
|
|
19653
20509
|
function gitRepoRoot(workingDirectory) {
|
|
19654
20510
|
try {
|
|
19655
|
-
const root =
|
|
20511
|
+
const root = execFileSync7("git", ["rev-parse", "--show-toplevel"], {
|
|
19656
20512
|
cwd: workingDirectory,
|
|
19657
20513
|
encoding: "utf8",
|
|
19658
20514
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -19671,7 +20527,7 @@ function resetTouchedFiles({
|
|
|
19671
20527
|
touchedFilesPath({ workingDirectory, missionId }),
|
|
19672
20528
|
bashSnapshotPath({ workingDirectory, missionId })
|
|
19673
20529
|
]) {
|
|
19674
|
-
if (
|
|
20530
|
+
if (existsSync24(target)) rmSync5(target);
|
|
19675
20531
|
}
|
|
19676
20532
|
} catch {
|
|
19677
20533
|
}
|
|
@@ -19682,14 +20538,14 @@ function resetRationaleNotes({
|
|
|
19682
20538
|
}) {
|
|
19683
20539
|
try {
|
|
19684
20540
|
const target = rationaleNotesPath({ workingDirectory, missionId });
|
|
19685
|
-
if (
|
|
20541
|
+
if (existsSync24(target)) rmSync5(target);
|
|
19686
20542
|
} catch {
|
|
19687
20543
|
}
|
|
19688
20544
|
}
|
|
19689
20545
|
function truncateNoteText(value, max = 500) {
|
|
19690
|
-
const
|
|
19691
|
-
if (!
|
|
19692
|
-
return
|
|
20546
|
+
const trimmed5 = (value ?? "").replace(/\s+/g, " ").trim();
|
|
20547
|
+
if (!trimmed5) return null;
|
|
20548
|
+
return trimmed5.length > max ? `${trimmed5.slice(0, max - 1)}...` : trimmed5;
|
|
19693
20549
|
}
|
|
19694
20550
|
function readRationaleNotes({
|
|
19695
20551
|
workingDirectory,
|
|
@@ -19697,8 +20553,8 @@ function readRationaleNotes({
|
|
|
19697
20553
|
}) {
|
|
19698
20554
|
try {
|
|
19699
20555
|
const target = rationaleNotesPath({ workingDirectory, missionId });
|
|
19700
|
-
if (!
|
|
19701
|
-
const raw = JSON.parse(
|
|
20556
|
+
if (!existsSync24(target)) return [];
|
|
20557
|
+
const raw = JSON.parse(readFileSync19(target, "utf8"));
|
|
19702
20558
|
if (!Array.isArray(raw.notes)) return [];
|
|
19703
20559
|
return raw.notes.flatMap((note) => {
|
|
19704
20560
|
if (typeof note !== "object" || note === null || typeof note.filePath !== "string") {
|
|
@@ -19732,7 +20588,7 @@ function recordRationaleNotes({
|
|
|
19732
20588
|
intent: truncateNoteText(note.intent),
|
|
19733
20589
|
transcriptContext: truncateNoteText(note.transcriptContext)
|
|
19734
20590
|
})).filter((note) => note.filePath).map((note) => {
|
|
19735
|
-
const absolute = normalizeAbsolute(
|
|
20591
|
+
const absolute = normalizeAbsolute(path28.resolve(workingDirectory, note.filePath));
|
|
19736
20592
|
return {
|
|
19737
20593
|
filePath: absolute,
|
|
19738
20594
|
toolName: note.toolName,
|
|
@@ -19740,17 +20596,17 @@ function recordRationaleNotes({
|
|
|
19740
20596
|
transcriptContext: note.transcriptContext,
|
|
19741
20597
|
contentHash: hashWorktreeFile({
|
|
19742
20598
|
workingDirectory,
|
|
19743
|
-
filePath:
|
|
20599
|
+
filePath: path28.relative(workingDirectory, absolute)
|
|
19744
20600
|
}),
|
|
19745
20601
|
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
19746
20602
|
};
|
|
19747
20603
|
});
|
|
19748
20604
|
if (additions.length === 0) return;
|
|
19749
20605
|
const target = rationaleNotesPath({ workingDirectory, missionId });
|
|
19750
|
-
|
|
20606
|
+
mkdirSync12(path28.dirname(target), { recursive: true });
|
|
19751
20607
|
const prior = readRationaleNotes({ workingDirectory, missionId });
|
|
19752
20608
|
const notesToKeep = [...prior, ...additions].slice(-200);
|
|
19753
|
-
|
|
20609
|
+
writeFileSync11(
|
|
19754
20610
|
target,
|
|
19755
20611
|
JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString(), notes: notesToKeep })
|
|
19756
20612
|
);
|
|
@@ -19763,16 +20619,16 @@ function recordTouchedFiles({
|
|
|
19763
20619
|
files
|
|
19764
20620
|
}) {
|
|
19765
20621
|
try {
|
|
19766
|
-
const additions = files.map((filePath) => (filePath ?? "").trim()).filter(Boolean).map((filePath) => normalizeAbsolute(
|
|
20622
|
+
const additions = files.map((filePath) => (filePath ?? "").trim()).filter(Boolean).map((filePath) => normalizeAbsolute(path28.resolve(workingDirectory, filePath)));
|
|
19767
20623
|
if (additions.length === 0) return;
|
|
19768
20624
|
const target = touchedFilesPath({ workingDirectory, missionId });
|
|
19769
|
-
|
|
20625
|
+
mkdirSync12(path28.dirname(target), { recursive: true });
|
|
19770
20626
|
const existing = readTouchedLog({ workingDirectory, missionId })?.paths ?? /* @__PURE__ */ new Set();
|
|
19771
20627
|
for (const filePath of additions) existing.add(filePath);
|
|
19772
|
-
|
|
20628
|
+
writeFileSync11(
|
|
19773
20629
|
target,
|
|
19774
20630
|
JSON.stringify({
|
|
19775
|
-
workingDirectory:
|
|
20631
|
+
workingDirectory: path28.resolve(workingDirectory),
|
|
19776
20632
|
missionId,
|
|
19777
20633
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19778
20634
|
paths: Array.from(existing)
|
|
@@ -19785,7 +20641,7 @@ function hasTouchedFilesLog({
|
|
|
19785
20641
|
workingDirectory,
|
|
19786
20642
|
missionId
|
|
19787
20643
|
}) {
|
|
19788
|
-
return
|
|
20644
|
+
return existsSync24(touchedFilesPath({ workingDirectory, missionId }));
|
|
19789
20645
|
}
|
|
19790
20646
|
function readTouchedLog({
|
|
19791
20647
|
workingDirectory,
|
|
@@ -19793,8 +20649,8 @@ function readTouchedLog({
|
|
|
19793
20649
|
}) {
|
|
19794
20650
|
try {
|
|
19795
20651
|
const target = touchedFilesPath({ workingDirectory, missionId });
|
|
19796
|
-
if (!
|
|
19797
|
-
const raw = JSON.parse(
|
|
20652
|
+
if (!existsSync24(target)) return null;
|
|
20653
|
+
const raw = JSON.parse(readFileSync19(target, "utf8"));
|
|
19798
20654
|
const result = /* @__PURE__ */ new Set();
|
|
19799
20655
|
if (Array.isArray(raw.paths)) {
|
|
19800
20656
|
for (const entry of raw.paths) {
|
|
@@ -19827,14 +20683,14 @@ function writeBaseline({
|
|
|
19827
20683
|
}) {
|
|
19828
20684
|
try {
|
|
19829
20685
|
const target = baselineFilePath({ workingDirectory, missionId });
|
|
19830
|
-
|
|
20686
|
+
mkdirSync12(path28.dirname(target), { recursive: true });
|
|
19831
20687
|
const snapshot = {
|
|
19832
|
-
workingDirectory:
|
|
20688
|
+
workingDirectory: path28.resolve(workingDirectory),
|
|
19833
20689
|
missionId,
|
|
19834
20690
|
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19835
20691
|
files: snapshotBaselineFiles({ workingDirectory, files })
|
|
19836
20692
|
};
|
|
19837
|
-
|
|
20693
|
+
writeFileSync11(target, JSON.stringify(snapshot));
|
|
19838
20694
|
} catch {
|
|
19839
20695
|
}
|
|
19840
20696
|
}
|
|
@@ -19846,13 +20702,13 @@ function readPeerTouchedClaims({
|
|
|
19846
20702
|
readActiveSessions(workingDirectory).map((entry) => entry.missionId.trim()).filter(Boolean)
|
|
19847
20703
|
);
|
|
19848
20704
|
if (activeMissionIds.size === 0) return [];
|
|
19849
|
-
const directory =
|
|
19850
|
-
if (!
|
|
20705
|
+
const directory = path28.join(resolveGlobalDataDir(), "vcs-touched");
|
|
20706
|
+
if (!existsSync24(directory)) return [];
|
|
19851
20707
|
const claims = [];
|
|
19852
20708
|
for (const name of readdirSync5(directory)) {
|
|
19853
20709
|
if (!name.endsWith(".json") || name.endsWith(".bash-snapshot.json")) continue;
|
|
19854
20710
|
try {
|
|
19855
|
-
const raw = JSON.parse(
|
|
20711
|
+
const raw = JSON.parse(readFileSync19(path28.join(directory, name), "utf8"));
|
|
19856
20712
|
const candidateMissionId = typeof raw.missionId === "string" && raw.missionId.trim() ? raw.missionId.trim() : null;
|
|
19857
20713
|
if (!candidateMissionId || candidateMissionId === missionId) continue;
|
|
19858
20714
|
if (!activeMissionIds.has(candidateMissionId)) continue;
|
|
@@ -19877,8 +20733,8 @@ function readBaselineSnapshot({
|
|
|
19877
20733
|
}) {
|
|
19878
20734
|
try {
|
|
19879
20735
|
const target = baselineFilePath({ workingDirectory, missionId });
|
|
19880
|
-
if (!
|
|
19881
|
-
const raw = JSON.parse(
|
|
20736
|
+
if (!existsSync24(target)) return /* @__PURE__ */ new Map();
|
|
20737
|
+
const raw = JSON.parse(readFileSync19(target, "utf8"));
|
|
19882
20738
|
if (Array.isArray(raw.files)) {
|
|
19883
20739
|
const byPath = /* @__PURE__ */ new Map();
|
|
19884
20740
|
for (const entry of raw.files) {
|
|
@@ -19972,10 +20828,10 @@ function compileIgnorePattern(rawPattern) {
|
|
|
19972
20828
|
}
|
|
19973
20829
|
function loadIgnoreRules(repoRoot) {
|
|
19974
20830
|
try {
|
|
19975
|
-
const target =
|
|
19976
|
-
if (!
|
|
20831
|
+
const target = path28.join(repoRoot, OVERLORD_IGNORE_FILENAME);
|
|
20832
|
+
if (!existsSync24(target)) return [];
|
|
19977
20833
|
const rules = [];
|
|
19978
|
-
for (const rawLine of
|
|
20834
|
+
for (const rawLine of readFileSync19(target, "utf8").split("\n")) {
|
|
19979
20835
|
const line = rawLine.replace(/\r$/, "").trim();
|
|
19980
20836
|
if (!line || line.startsWith("#")) continue;
|
|
19981
20837
|
const rule = compileIgnorePattern(line);
|
|
@@ -20009,7 +20865,7 @@ function filterRunAttributableChanges({
|
|
|
20009
20865
|
return [];
|
|
20010
20866
|
}
|
|
20011
20867
|
if (!touched) return [{ filePath: entry.filePath, vcsStatus: entry.vcsStatus }];
|
|
20012
|
-
const absolute = normalizeAbsolute(
|
|
20868
|
+
const absolute = normalizeAbsolute(path28.resolve(repoRoot, entry.filePath));
|
|
20013
20869
|
if (touched.paths.has(absolute)) {
|
|
20014
20870
|
return [
|
|
20015
20871
|
{
|
|
@@ -20040,7 +20896,7 @@ function filterRunAttributableChanges({
|
|
|
20040
20896
|
});
|
|
20041
20897
|
}
|
|
20042
20898
|
function titleFromPath(filePath) {
|
|
20043
|
-
const base =
|
|
20899
|
+
const base = path28.basename(filePath).replace(/\.[^.]+$/, "");
|
|
20044
20900
|
const words = base.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").trim();
|
|
20045
20901
|
if (!words) return `Update ${filePath}`;
|
|
20046
20902
|
return `Update ${words.replace(/\b\w/g, (char) => char.toUpperCase())}`;
|
|
@@ -20063,7 +20919,7 @@ function draftChangeRationalesFromNotes({
|
|
|
20063
20919
|
if (notes.length === 0 || files.length === 0) return [];
|
|
20064
20920
|
const repoRoot = gitRepoRoot(workingDirectory) ?? workingDirectory;
|
|
20065
20921
|
return files.flatMap((file) => {
|
|
20066
|
-
const absolute = normalizeAbsolute(
|
|
20922
|
+
const absolute = normalizeAbsolute(path28.resolve(repoRoot, file.filePath));
|
|
20067
20923
|
const currentHash = hashWorktreeFile({ workingDirectory, filePath: file.filePath });
|
|
20068
20924
|
const note = latestRelevantNote({ notes, filePath: absolute, currentHash });
|
|
20069
20925
|
if (!note) return [];
|
|
@@ -20103,17 +20959,17 @@ var init_vcs = __esm({
|
|
|
20103
20959
|
});
|
|
20104
20960
|
|
|
20105
20961
|
// src/record-touched.ts
|
|
20106
|
-
import { readFileSync as
|
|
20107
|
-
import
|
|
20962
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
20963
|
+
import path29 from "node:path";
|
|
20108
20964
|
function collectCandidates(toolInput) {
|
|
20109
20965
|
const counts = /* @__PURE__ */ new Map();
|
|
20110
20966
|
const order = [];
|
|
20111
20967
|
const bump = (raw, amount) => {
|
|
20112
20968
|
if (typeof raw !== "string") return;
|
|
20113
|
-
const
|
|
20114
|
-
if (!
|
|
20115
|
-
if (!counts.has(
|
|
20116
|
-
counts.set(
|
|
20969
|
+
const trimmed5 = raw.trim();
|
|
20970
|
+
if (!trimmed5) return;
|
|
20971
|
+
if (!counts.has(trimmed5)) order.push(trimmed5);
|
|
20972
|
+
counts.set(trimmed5, (counts.get(trimmed5) ?? 0) + amount);
|
|
20117
20973
|
};
|
|
20118
20974
|
bump(toolInput.file_path, 1);
|
|
20119
20975
|
bump(toolInput.notebook_path, 1);
|
|
@@ -20153,7 +21009,7 @@ function editIntent({
|
|
|
20153
21009
|
function recentAssistantContext(transcriptPath) {
|
|
20154
21010
|
if (typeof transcriptPath !== "string" || !transcriptPath.trim()) return null;
|
|
20155
21011
|
try {
|
|
20156
|
-
const lines2 =
|
|
21012
|
+
const lines2 = readFileSync20(transcriptPath, "utf8").split("\n").slice(-200);
|
|
20157
21013
|
for (let index = lines2.length - 1; index >= 0; index -= 1) {
|
|
20158
21014
|
const line = lines2[index]?.trim();
|
|
20159
21015
|
if (!line) continue;
|
|
@@ -20203,7 +21059,7 @@ function recordTouchedFromPayload({
|
|
|
20203
21059
|
const toolInput = toolInputRaw && typeof toolInputRaw === "object" ? toolInputRaw : {};
|
|
20204
21060
|
const toolName = typeof payload.tool_name === "string" && payload.tool_name.trim() ? payload.tool_name.trim() : "file edit";
|
|
20205
21061
|
const cwd = typeof payload.cwd === "string" && payload.cwd.trim() ? payload.cwd.trim() : fallbackCwd;
|
|
20206
|
-
const workingDirectory =
|
|
21062
|
+
const workingDirectory = path29.resolve(cwd);
|
|
20207
21063
|
const trimmedOverride = missionOverride?.trim();
|
|
20208
21064
|
let missionId;
|
|
20209
21065
|
let ambiguous = false;
|
|
@@ -20307,23 +21163,23 @@ var init_resource_observations = __esm({
|
|
|
20307
21163
|
|
|
20308
21164
|
// src/runner-identity.ts
|
|
20309
21165
|
import { randomUUID } from "node:crypto";
|
|
20310
|
-
import { existsSync as
|
|
21166
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync12 } from "node:fs";
|
|
20311
21167
|
import { hostname as hostname4 } from "node:os";
|
|
20312
|
-
import
|
|
21168
|
+
import path30 from "node:path";
|
|
20313
21169
|
function envValue(name) {
|
|
20314
21170
|
const value = process.env[name]?.trim();
|
|
20315
21171
|
return value && value.length > 0 ? value : null;
|
|
20316
21172
|
}
|
|
20317
21173
|
function runnerInstanceStatePath(dataDir = resolveGlobalDataDir()) {
|
|
20318
|
-
return
|
|
21174
|
+
return path30.join(dataDir, RUNNER_INSTANCE_STATE_FILENAME);
|
|
20319
21175
|
}
|
|
20320
21176
|
function resolveRunnerInstanceId(dataDir = resolveGlobalDataDir()) {
|
|
20321
21177
|
const pinned = envValue("OVERLORD_RUNNER_INSTANCE_ID");
|
|
20322
21178
|
if (pinned) return pinned;
|
|
20323
21179
|
const statePath = runnerInstanceStatePath(dataDir);
|
|
20324
|
-
if (
|
|
21180
|
+
if (existsSync25(statePath)) {
|
|
20325
21181
|
try {
|
|
20326
|
-
const parsed = JSON.parse(
|
|
21182
|
+
const parsed = JSON.parse(readFileSync21(statePath, "utf8"));
|
|
20327
21183
|
if (typeof parsed.runnerInstanceId === "string" && parsed.runnerInstanceId.trim()) {
|
|
20328
21184
|
return parsed.runnerInstanceId.trim();
|
|
20329
21185
|
}
|
|
@@ -20332,8 +21188,8 @@ function resolveRunnerInstanceId(dataDir = resolveGlobalDataDir()) {
|
|
|
20332
21188
|
}
|
|
20333
21189
|
const runnerInstanceId = randomUUID();
|
|
20334
21190
|
try {
|
|
20335
|
-
|
|
20336
|
-
|
|
21191
|
+
mkdirSync13(path30.dirname(statePath), { recursive: true });
|
|
21192
|
+
writeFileSync12(statePath, `${JSON.stringify({ runnerInstanceId }, null, 2)}
|
|
20337
21193
|
`, { mode: 384 });
|
|
20338
21194
|
} catch {
|
|
20339
21195
|
}
|
|
@@ -20375,12 +21231,12 @@ var init_runner_identity = __esm({
|
|
|
20375
21231
|
|
|
20376
21232
|
// src/runner-service.ts
|
|
20377
21233
|
import { execFile } from "node:child_process";
|
|
20378
|
-
import { chmodSync as chmodSync5, existsSync as
|
|
20379
|
-
import
|
|
20380
|
-
import
|
|
21234
|
+
import { chmodSync as chmodSync5, existsSync as existsSync26, mkdirSync as mkdirSync14, readFileSync as readFileSync22, rmSync as rmSync6, writeFileSync as writeFileSync13 } from "node:fs";
|
|
21235
|
+
import os5 from "node:os";
|
|
21236
|
+
import path31 from "node:path";
|
|
20381
21237
|
import { promisify } from "node:util";
|
|
20382
21238
|
function writeServiceFile(filePath, contents) {
|
|
20383
|
-
|
|
21239
|
+
writeFileSync13(filePath, contents, { mode: 384 });
|
|
20384
21240
|
chmodSync5(filePath, 384);
|
|
20385
21241
|
}
|
|
20386
21242
|
function emptyRunnerServiceState() {
|
|
@@ -20399,21 +21255,21 @@ function emptyRunnerServiceState() {
|
|
|
20399
21255
|
};
|
|
20400
21256
|
}
|
|
20401
21257
|
function runnerServiceStatePath(dataDir = resolveGlobalDataDir()) {
|
|
20402
|
-
return
|
|
21258
|
+
return path31.join(dataDir, RUNNER_SERVICE_STATE_FILENAME);
|
|
20403
21259
|
}
|
|
20404
21260
|
function readRunnerServiceState(dataDir = resolveGlobalDataDir()) {
|
|
20405
21261
|
const filePath = runnerServiceStatePath(dataDir);
|
|
20406
|
-
if (!
|
|
21262
|
+
if (!existsSync26(filePath)) return emptyRunnerServiceState();
|
|
20407
21263
|
try {
|
|
20408
|
-
const parsed = JSON.parse(
|
|
21264
|
+
const parsed = JSON.parse(readFileSync22(filePath, "utf8"));
|
|
20409
21265
|
return { ...emptyRunnerServiceState(), ...parsed };
|
|
20410
21266
|
} catch {
|
|
20411
21267
|
return emptyRunnerServiceState();
|
|
20412
21268
|
}
|
|
20413
21269
|
}
|
|
20414
21270
|
function writeRunnerServiceState(state, dataDir = resolveGlobalDataDir()) {
|
|
20415
|
-
|
|
20416
|
-
|
|
21271
|
+
mkdirSync14(dataDir, { recursive: true });
|
|
21272
|
+
writeFileSync13(runnerServiceStatePath(dataDir), `${JSON.stringify(state, null, 2)}
|
|
20417
21273
|
`, "utf8");
|
|
20418
21274
|
}
|
|
20419
21275
|
function patchRunnerServiceState(patch, dataDir = resolveGlobalDataDir()) {
|
|
@@ -20422,13 +21278,13 @@ function patchRunnerServiceState(patch, dataDir = resolveGlobalDataDir()) {
|
|
|
20422
21278
|
return next;
|
|
20423
21279
|
}
|
|
20424
21280
|
function runnerFocusStatePath(dataDir = resolveGlobalDataDir()) {
|
|
20425
|
-
return
|
|
21281
|
+
return path31.join(dataDir, RUNNER_FOCUS_STATE_FILENAME);
|
|
20426
21282
|
}
|
|
20427
21283
|
function readDesktopFocusState(dataDir = resolveGlobalDataDir()) {
|
|
20428
21284
|
const filePath = runnerFocusStatePath(dataDir);
|
|
20429
|
-
if (!
|
|
21285
|
+
if (!existsSync26(filePath)) return { lastFocusedAt: null };
|
|
20430
21286
|
try {
|
|
20431
|
-
const parsed = JSON.parse(
|
|
21287
|
+
const parsed = JSON.parse(readFileSync22(filePath, "utf8"));
|
|
20432
21288
|
return { lastFocusedAt: parsed.lastFocusedAt ?? null };
|
|
20433
21289
|
} catch {
|
|
20434
21290
|
return { lastFocusedAt: null };
|
|
@@ -20458,17 +21314,17 @@ function nextRunnerLastError(pollError) {
|
|
|
20458
21314
|
}
|
|
20459
21315
|
function resolveOverlordAppInvocation({
|
|
20460
21316
|
platform: platform2 = process.platform,
|
|
20461
|
-
homedir: homedir2 =
|
|
20462
|
-
exists =
|
|
21317
|
+
homedir: homedir2 = os5.homedir(),
|
|
21318
|
+
exists = existsSync26
|
|
20463
21319
|
} = {}) {
|
|
20464
21320
|
if (platform2 !== "darwin") return null;
|
|
20465
21321
|
const appDirs = [
|
|
20466
21322
|
"/Applications/Overlord.app",
|
|
20467
|
-
|
|
21323
|
+
path31.join(homedir2, "Applications", "Overlord.app")
|
|
20468
21324
|
];
|
|
20469
21325
|
for (const appDir of appDirs) {
|
|
20470
|
-
const program =
|
|
20471
|
-
const script =
|
|
21326
|
+
const program = path31.join(appDir, "Contents", "MacOS", "Overlord");
|
|
21327
|
+
const script = path31.join(appDir, "Contents", "Resources", "cli", "bin", "ovld.mjs");
|
|
20472
21328
|
if (exists(program) && exists(script)) {
|
|
20473
21329
|
return { program, args: [script, "runner", "supervise"], runAsElectronNode: true };
|
|
20474
21330
|
}
|
|
@@ -20480,7 +21336,7 @@ function resolveOvldInvocation(argv = process.argv, execPath = process.execPath)
|
|
|
20480
21336
|
if (override) {
|
|
20481
21337
|
return { program: override, args: ["runner", "supervise"] };
|
|
20482
21338
|
}
|
|
20483
|
-
const scriptPath = argv[1] ?
|
|
21339
|
+
const scriptPath = argv[1] ? path31.resolve(argv[1]) : "";
|
|
20484
21340
|
if (process.env.ELECTRON_RUN_AS_NODE) {
|
|
20485
21341
|
return scriptPath ? { program: execPath, args: [scriptPath, "runner", "supervise"], runAsElectronNode: true } : { program: execPath, args: ["runner", "supervise"], runAsElectronNode: true };
|
|
20486
21342
|
}
|
|
@@ -20513,7 +21369,7 @@ function buildRunnerServiceEnv({
|
|
|
20513
21369
|
PATH: process.env.PATH?.trim() || "/usr/local/bin:/usr/bin:/bin"
|
|
20514
21370
|
};
|
|
20515
21371
|
const home = overlordHome?.trim() || process.env.OVLD_HOME?.trim();
|
|
20516
|
-
if (home) env.OVLD_HOME =
|
|
21372
|
+
if (home) env.OVLD_HOME = path31.resolve(home);
|
|
20517
21373
|
const token = process.env.OVERLORD_USER_TOKEN?.trim() || process.env.OVLD_USER_TOKEN?.trim();
|
|
20518
21374
|
if (token) env.OVERLORD_USER_TOKEN = token;
|
|
20519
21375
|
if (runAsElectronNode || process.env.ELECTRON_RUN_AS_NODE) env.ELECTRON_RUN_AS_NODE = "1";
|
|
@@ -20552,9 +21408,9 @@ ${envEntries}
|
|
|
20552
21408
|
<key>KeepAlive</key>
|
|
20553
21409
|
<true/>
|
|
20554
21410
|
<key>StandardOutPath</key>
|
|
20555
|
-
<string>${xmlEscape(
|
|
21411
|
+
<string>${xmlEscape(path31.join(logDir, "runner-service.out.log"))}</string>
|
|
20556
21412
|
<key>StandardErrorPath</key>
|
|
20557
|
-
<string>${xmlEscape(
|
|
21413
|
+
<string>${xmlEscape(path31.join(logDir, "runner-service.err.log"))}</string>
|
|
20558
21414
|
<key>ProcessType</key>
|
|
20559
21415
|
<string>Background</string>
|
|
20560
21416
|
</dict>
|
|
@@ -20585,12 +21441,12 @@ WantedBy=default.target
|
|
|
20585
21441
|
`;
|
|
20586
21442
|
}
|
|
20587
21443
|
function launchAgentsDir() {
|
|
20588
|
-
return
|
|
21444
|
+
return path31.join(os5.homedir(), "Library", "LaunchAgents");
|
|
20589
21445
|
}
|
|
20590
21446
|
function systemdUserDir() {
|
|
20591
21447
|
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
20592
|
-
const base = xdg ?
|
|
20593
|
-
return
|
|
21448
|
+
const base = xdg ? path31.resolve(xdg) : path31.join(os5.homedir(), ".config");
|
|
21449
|
+
return path31.join(base, "systemd", "user");
|
|
20594
21450
|
}
|
|
20595
21451
|
async function runCommand(program, args) {
|
|
20596
21452
|
const { stdout } = await execFileAsync(program, args);
|
|
@@ -20619,19 +21475,19 @@ var init_runner_service = __esm({
|
|
|
20619
21475
|
kind = "launchd";
|
|
20620
21476
|
identifier = LAUNCHD_LABEL;
|
|
20621
21477
|
unitPath() {
|
|
20622
|
-
return
|
|
21478
|
+
return path31.join(launchAgentsDir(), `${LAUNCHD_LABEL}.plist`);
|
|
20623
21479
|
}
|
|
20624
21480
|
render(opts) {
|
|
20625
21481
|
return renderLaunchdPlist({
|
|
20626
21482
|
label: LAUNCHD_LABEL,
|
|
20627
21483
|
invocation: opts.invocation,
|
|
20628
21484
|
env: opts.env,
|
|
20629
|
-
logDir:
|
|
21485
|
+
logDir: path31.join(resolveGlobalDataDir(), "logs")
|
|
20630
21486
|
});
|
|
20631
21487
|
}
|
|
20632
21488
|
async install(opts) {
|
|
20633
|
-
|
|
20634
|
-
|
|
21489
|
+
mkdirSync14(launchAgentsDir(), { recursive: true });
|
|
21490
|
+
mkdirSync14(path31.join(resolveGlobalDataDir(), "logs"), { recursive: true });
|
|
20635
21491
|
writeServiceFile(this.unitPath(), this.render(opts));
|
|
20636
21492
|
if (opts.autoStart) await this.start();
|
|
20637
21493
|
}
|
|
@@ -20661,10 +21517,10 @@ var init_runner_service = __esm({
|
|
|
20661
21517
|
await this.stop();
|
|
20662
21518
|
} catch {
|
|
20663
21519
|
}
|
|
20664
|
-
if (
|
|
21520
|
+
if (existsSync26(this.unitPath())) rmSync6(this.unitPath());
|
|
20665
21521
|
}
|
|
20666
21522
|
async status() {
|
|
20667
|
-
const installed =
|
|
21523
|
+
const installed = existsSync26(this.unitPath());
|
|
20668
21524
|
try {
|
|
20669
21525
|
const { stdout } = await runCommand("launchctl", ["list"]);
|
|
20670
21526
|
const line = stdout.split("\n").find((row) => row.includes(LAUNCHD_LABEL));
|
|
@@ -20680,13 +21536,13 @@ var init_runner_service = __esm({
|
|
|
20680
21536
|
kind = "systemd";
|
|
20681
21537
|
identifier = `${SYSTEMD_UNIT_NAME}.service`;
|
|
20682
21538
|
unitPath() {
|
|
20683
|
-
return
|
|
21539
|
+
return path31.join(systemdUserDir(), `${SYSTEMD_UNIT_NAME}.service`);
|
|
20684
21540
|
}
|
|
20685
21541
|
render(opts) {
|
|
20686
21542
|
return renderSystemdUnit(opts);
|
|
20687
21543
|
}
|
|
20688
21544
|
async install(opts) {
|
|
20689
|
-
|
|
21545
|
+
mkdirSync14(systemdUserDir(), { recursive: true });
|
|
20690
21546
|
writeServiceFile(this.unitPath(), this.render(opts));
|
|
20691
21547
|
await runCommand("systemctl", ["--user", "daemon-reload"]);
|
|
20692
21548
|
await runCommand("systemctl", ["--user", "enable", this.identifier]);
|
|
@@ -20707,14 +21563,14 @@ var init_runner_service = __esm({
|
|
|
20707
21563
|
await runCommand("systemctl", ["--user", "disable", this.identifier]);
|
|
20708
21564
|
} catch {
|
|
20709
21565
|
}
|
|
20710
|
-
if (
|
|
21566
|
+
if (existsSync26(this.unitPath())) rmSync6(this.unitPath());
|
|
20711
21567
|
try {
|
|
20712
21568
|
await runCommand("systemctl", ["--user", "daemon-reload"]);
|
|
20713
21569
|
} catch {
|
|
20714
21570
|
}
|
|
20715
21571
|
}
|
|
20716
21572
|
async status() {
|
|
20717
|
-
const installed =
|
|
21573
|
+
const installed = existsSync26(this.unitPath());
|
|
20718
21574
|
try {
|
|
20719
21575
|
const { stdout } = await runCommand("systemctl", ["--user", "is-active", this.identifier]);
|
|
20720
21576
|
return { installed, running: stdout.trim() === "active" ? "running" : "stopped" };
|
|
@@ -20729,9 +21585,9 @@ var init_runner_service = __esm({
|
|
|
20729
21585
|
// src/select-prompt.ts
|
|
20730
21586
|
import { createInterface as createInterface4 } from "node:readline";
|
|
20731
21587
|
function parseNumberedSelection(answer, count) {
|
|
20732
|
-
const
|
|
20733
|
-
if (!/^\d+$/.test(
|
|
20734
|
-
const value = Number.parseInt(
|
|
21588
|
+
const trimmed5 = answer.trim();
|
|
21589
|
+
if (!/^\d+$/.test(trimmed5)) return null;
|
|
21590
|
+
const value = Number.parseInt(trimmed5, 10);
|
|
20735
21591
|
if (!Number.isInteger(value) || value < 1 || value > count) return null;
|
|
20736
21592
|
return value - 1;
|
|
20737
21593
|
}
|
|
@@ -20781,14 +21637,14 @@ var init_select_prompt = __esm({
|
|
|
20781
21637
|
|
|
20782
21638
|
// src/session-key.ts
|
|
20783
21639
|
import { createHash as createHash10 } from "node:crypto";
|
|
20784
|
-
import { existsSync as
|
|
20785
|
-
import
|
|
21640
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync23, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "node:fs";
|
|
21641
|
+
import path32 from "node:path";
|
|
20786
21642
|
function sessionKeyCachePath({
|
|
20787
21643
|
missionId,
|
|
20788
21644
|
workingDirectory
|
|
20789
21645
|
}) {
|
|
20790
|
-
const key = createHash10("sha256").update(`${
|
|
20791
|
-
return
|
|
21646
|
+
const key = createHash10("sha256").update(`${path32.resolve(workingDirectory)}\0${missionId}`).digest("hex");
|
|
21647
|
+
return path32.join(resolveGlobalDataDir(), "protocol-session-keys", key);
|
|
20792
21648
|
}
|
|
20793
21649
|
function readCachedSessionKey({
|
|
20794
21650
|
missionId,
|
|
@@ -20796,8 +21652,8 @@ function readCachedSessionKey({
|
|
|
20796
21652
|
}) {
|
|
20797
21653
|
try {
|
|
20798
21654
|
const filePath = sessionKeyCachePath({ missionId, workingDirectory });
|
|
20799
|
-
if (!
|
|
20800
|
-
const raw = JSON.parse(
|
|
21655
|
+
if (!existsSync27(filePath)) return void 0;
|
|
21656
|
+
const raw = JSON.parse(readFileSync23(filePath, "utf8"));
|
|
20801
21657
|
return typeof raw.sessionKey === "string" && raw.sessionKey.trim() ? raw.sessionKey.trim() : void 0;
|
|
20802
21658
|
} catch {
|
|
20803
21659
|
return void 0;
|
|
@@ -20809,13 +21665,13 @@ function writeCachedSessionKey({
|
|
|
20809
21665
|
sessionKey
|
|
20810
21666
|
}) {
|
|
20811
21667
|
try {
|
|
20812
|
-
const
|
|
20813
|
-
if (!
|
|
21668
|
+
const trimmed5 = sessionKey.trim();
|
|
21669
|
+
if (!trimmed5) return;
|
|
20814
21670
|
const filePath = sessionKeyCachePath({ missionId, workingDirectory });
|
|
20815
|
-
|
|
20816
|
-
|
|
21671
|
+
mkdirSync15(path32.dirname(filePath), { recursive: true });
|
|
21672
|
+
writeFileSync14(
|
|
20817
21673
|
filePath,
|
|
20818
|
-
JSON.stringify({ sessionKey:
|
|
21674
|
+
JSON.stringify({ sessionKey: trimmed5, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
20819
21675
|
{ mode: 384 }
|
|
20820
21676
|
);
|
|
20821
21677
|
} catch {
|
|
@@ -20827,7 +21683,7 @@ function clearCachedSessionKey({
|
|
|
20827
21683
|
}) {
|
|
20828
21684
|
try {
|
|
20829
21685
|
const filePath = sessionKeyCachePath({ missionId, workingDirectory });
|
|
20830
|
-
if (
|
|
21686
|
+
if (existsSync27(filePath)) rmSync7(filePath);
|
|
20831
21687
|
} catch {
|
|
20832
21688
|
}
|
|
20833
21689
|
}
|
|
@@ -20845,9 +21701,9 @@ __export(commands_exports, {
|
|
|
20845
21701
|
runManagementCommand: () => runManagementCommand,
|
|
20846
21702
|
runProtocolCommand: () => runProtocolCommand
|
|
20847
21703
|
});
|
|
20848
|
-
import { existsSync as
|
|
20849
|
-
import
|
|
20850
|
-
import
|
|
21704
|
+
import { existsSync as existsSync28, readFileSync as readFileSync24 } from "node:fs";
|
|
21705
|
+
import os6 from "node:os";
|
|
21706
|
+
import path33 from "node:path";
|
|
20851
21707
|
function resourceAccessModeBody(value) {
|
|
20852
21708
|
if (typeof value !== "string") return {};
|
|
20853
21709
|
const normalized = value.trim().toLowerCase();
|
|
@@ -20893,7 +21749,7 @@ function readChangedFilesFromFlags(flags, stdin) {
|
|
|
20893
21749
|
if (typeof fileFlag === "string") {
|
|
20894
21750
|
const raw = fileFlag === "-" ? stdin ?? "" : (() => {
|
|
20895
21751
|
try {
|
|
20896
|
-
return
|
|
21752
|
+
return readFileSync24(fileFlag, "utf8");
|
|
20897
21753
|
} catch {
|
|
20898
21754
|
return "";
|
|
20899
21755
|
}
|
|
@@ -20945,7 +21801,7 @@ function readJsonFlagContent({
|
|
|
20945
21801
|
if (typeof filePath === "string") {
|
|
20946
21802
|
if (fileInputs[fileFlag] !== void 0) return fileInputs[fileFlag];
|
|
20947
21803
|
try {
|
|
20948
|
-
return
|
|
21804
|
+
return readFileSync24(filePath, "utf8");
|
|
20949
21805
|
} catch {
|
|
20950
21806
|
return void 0;
|
|
20951
21807
|
}
|
|
@@ -21249,7 +22105,7 @@ async function resolveProtocolFileInputs({
|
|
|
21249
22105
|
} else if (process.stdin.isTTY) {
|
|
21250
22106
|
stdinContent = "";
|
|
21251
22107
|
} else {
|
|
21252
|
-
stdinContent =
|
|
22108
|
+
stdinContent = readFileSync24(0, "utf8");
|
|
21253
22109
|
}
|
|
21254
22110
|
return stdinContent;
|
|
21255
22111
|
};
|
|
@@ -21263,7 +22119,7 @@ async function resolveProtocolFileInputs({
|
|
|
21263
22119
|
fileInputs[flagName] = content;
|
|
21264
22120
|
stdinPayload = content;
|
|
21265
22121
|
} else {
|
|
21266
|
-
fileInputs[flagName] =
|
|
22122
|
+
fileInputs[flagName] = readFileSync24(filePath, "utf8");
|
|
21267
22123
|
}
|
|
21268
22124
|
}
|
|
21269
22125
|
if (stdinPayload === void 0 && stdin !== void 0 && Object.keys(fileInputs).length === 0) {
|
|
@@ -21328,7 +22184,7 @@ async function runProtocolCommand({
|
|
|
21328
22184
|
});
|
|
21329
22185
|
if (subcommand === "record-touched") {
|
|
21330
22186
|
const missionOverride = flagValue(parsed.flags, "--mission-id") ?? process.env.MISSION_ID ?? process.env.OVERLORD_MISSION_ID;
|
|
21331
|
-
const rawPayload = stdin ?? (process.stdin.isTTY ? "" :
|
|
22187
|
+
const rawPayload = stdin ?? (process.stdin.isTTY ? "" : readFileSync24(0, "utf8"));
|
|
21332
22188
|
const result2 = recordTouchedFromPayload({
|
|
21333
22189
|
rawPayload,
|
|
21334
22190
|
missionOverride,
|
|
@@ -21459,9 +22315,9 @@ async function runProtocolCommand({
|
|
|
21459
22315
|
clearCachedSessionKey({ missionId, workingDirectory });
|
|
21460
22316
|
removeActiveSession({ workingDirectory, missionId });
|
|
21461
22317
|
clearActiveMissionPointer(workingDirectory);
|
|
21462
|
-
const connectorInstallsEditHook =
|
|
21463
|
-
|
|
21464
|
-
|
|
22318
|
+
const connectorInstallsEditHook = existsSync28(path33.join(os6.homedir(), ".claude")) || existsSync28(
|
|
22319
|
+
path33.join(
|
|
22320
|
+
os6.homedir(),
|
|
21465
22321
|
".cursor",
|
|
21466
22322
|
"plugins",
|
|
21467
22323
|
"local",
|
|
@@ -21560,7 +22416,7 @@ async function runManagementCommand({
|
|
|
21560
22416
|
case "add-cwd": {
|
|
21561
22417
|
const directory = flagValue(parsed.flags, "--directory") ?? process.cwd();
|
|
21562
22418
|
const existingProjectJson = readProjectJsonLink(
|
|
21563
|
-
|
|
22419
|
+
path33.join(directory, ".overlord", "project.json")
|
|
21564
22420
|
);
|
|
21565
22421
|
const resourceKey = flagValue(parsed.flags, "--key") ?? existingProjectJson?.resourceKey;
|
|
21566
22422
|
let projectId = flagValue(parsed.flags, "--project-id");
|
|
@@ -21951,13 +22807,13 @@ async function runManagementCommand({
|
|
|
21951
22807
|
rationales: `/api/missions/${encodeURIComponent(missionId)}/file-changes`,
|
|
21952
22808
|
deliveries: `/api/missions/${encodeURIComponent(missionId)}/deliveries`
|
|
21953
22809
|
};
|
|
21954
|
-
const
|
|
21955
|
-
if (!
|
|
22810
|
+
const path34 = sub ? pathBySub[sub] : void 0;
|
|
22811
|
+
if (!path34) {
|
|
21956
22812
|
throw new CliError({
|
|
21957
22813
|
message: "Usage: ovld mission context|events|deliveries|artifacts|rationales <missionId> [--json]"
|
|
21958
22814
|
});
|
|
21959
22815
|
}
|
|
21960
|
-
const result = await runtime.backend.get(
|
|
22816
|
+
const result = await runtime.backend.get(path34);
|
|
21961
22817
|
if (json || sub === "context") printJson(result);
|
|
21962
22818
|
else if (Array.isArray(result)) for (const row of result) console.log(JSON.stringify(row));
|
|
21963
22819
|
else printJson(result);
|
|
@@ -22127,16 +22983,33 @@ The runner will not register a target for you \u2014 declare this machine first,
|
|
|
22127
22983
|
sessionChannelId: typeof sessionChannel.channelId === "string" ? sessionChannel.channelId : void 0,
|
|
22128
22984
|
sessionChannelToken: typeof sessionChannel.token === "string" ? sessionChannel.token : void 0,
|
|
22129
22985
|
sessionChannelLaunchKind: typeof sessionChannel.launchKind === "string" ? sessionChannel.launchKind : void 0,
|
|
22986
|
+
launchSession: launchSessionSnapshotFromMetadata(asRecord5(requestRecord.metadata)),
|
|
22130
22987
|
...terminal,
|
|
22131
22988
|
dryRun
|
|
22132
22989
|
}
|
|
22133
22990
|
});
|
|
22991
|
+
if (result.providerFallbackWarning) {
|
|
22992
|
+
console.error(`[overlord] ${result.providerFallbackWarning}`);
|
|
22993
|
+
}
|
|
22994
|
+
if (result.viewerOpen && result.viewerOpen.ok === false) {
|
|
22995
|
+
console.error(`[overlord] ${result.viewerOpen.warning}`);
|
|
22996
|
+
}
|
|
22134
22997
|
if (result.status && result.status !== 0) {
|
|
22135
22998
|
throw new CliError({ message: `Launch command exited with status ${result.status}` });
|
|
22136
22999
|
}
|
|
22137
|
-
await runtime.backend.post({
|
|
23000
|
+
await runtime.backend.post({
|
|
23001
|
+
path: `/api/runner/requests/${requestId}/launched`,
|
|
23002
|
+
body: result.providerSession ? { providerSession: result.providerSession } : {}
|
|
23003
|
+
});
|
|
22138
23004
|
if (json || dryRun) {
|
|
22139
|
-
printJson({
|
|
23005
|
+
printJson({
|
|
23006
|
+
request,
|
|
23007
|
+
plan: result.plan,
|
|
23008
|
+
status: result.status,
|
|
23009
|
+
providerSession: result.providerSession ?? null,
|
|
23010
|
+
viewerOpen: result.viewerOpen ?? null,
|
|
23011
|
+
providerFallbackWarning: result.providerFallbackWarning ?? null
|
|
23012
|
+
});
|
|
22140
23013
|
} else {
|
|
22141
23014
|
console.log(`Launched ${requestedAgent} for ${requestRecord.missionId}`);
|
|
22142
23015
|
}
|
|
@@ -22318,6 +23191,7 @@ var init_commands = __esm({
|
|
|
22318
23191
|
init_dist2();
|
|
22319
23192
|
init_project_metadata();
|
|
22320
23193
|
init_local_target_mutation_runner();
|
|
23194
|
+
init_terminal_profile_types2();
|
|
22321
23195
|
init_active_mission();
|
|
22322
23196
|
init_args();
|
|
22323
23197
|
init_branch_preparation();
|