overlord-cli 0.2608221603.0 → 0.2608240740.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/connectors/VERSION +1 -1
- package/dist/connectors/adapters/antigravity/conformance-manifest.yaml +1 -1
- package/dist/connectors/adapters/antigravity/plugin.json +1 -1
- package/dist/connectors/adapters/claude/.claude-plugin/plugin.json +1 -1
- package/dist/connectors/adapters/claude/conformance-manifest.yaml +1 -1
- package/dist/connectors/adapters/codex/.codex-plugin/plugin.json +1 -1
- package/dist/connectors/adapters/codex/conformance-manifest.yaml +1 -1
- package/dist/connectors/adapters/cursor/.cursor-plugin/plugin.json +1 -1
- package/dist/connectors/adapters/cursor/codec/cursor.codec.yaml +4 -0
- package/dist/connectors/adapters/cursor/conformance-manifest.yaml +1 -1
- package/dist/connectors/adapters/opencode/conformance-manifest.yaml +1 -1
- package/dist/connectors/adapters/pi/conformance-manifest.yaml +1 -1
- package/dist/connectors/core/scripts/overlord-mcp.mjs +1 -1
- package/dist/index.js +280 -22
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/connectors/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.3.
|
|
1
|
+
0.3.36
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://antigravity.google/schemas/v1/plugin.json",
|
|
3
3
|
"name": "overlord",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.36",
|
|
5
5
|
"description": "Chat-driven access to Overlord mission protocol workflows through skills and MCP.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Cooperativ",
|
|
@@ -69,5 +69,9 @@ events:
|
|
|
69
69
|
inputPath: tool_input
|
|
70
70
|
callIdPath: call_id
|
|
71
71
|
fileEditKind: file.edited
|
|
72
|
+
# Live Cursor Write payloads use file_path; path/filePath match the write
|
|
73
|
+
# formatter's key order so an alternate Cursor dialect still captures.
|
|
72
74
|
filePathPaths:
|
|
73
75
|
- file_path
|
|
76
|
+
- filePath
|
|
77
|
+
- path
|
|
@@ -1091,7 +1091,7 @@ process.stdin.on('data', async chunk => {
|
|
|
1091
1091
|
result: {
|
|
1092
1092
|
protocolVersion: PROTOCOL_VERSION,
|
|
1093
1093
|
capabilities: { tools: { listChanged: false } },
|
|
1094
|
-
serverInfo: { name: 'overlord-__OVERLORD_ADAPTER_KEY__', version: '0.3.
|
|
1094
|
+
serverInfo: { name: 'overlord-__OVERLORD_ADAPTER_KEY__', version: '0.3.36' }
|
|
1095
1095
|
}
|
|
1096
1096
|
});
|
|
1097
1097
|
continue;
|
package/dist/index.js
CHANGED
|
@@ -67,7 +67,44 @@ function isUnlinkableExecutionRequestError(error) {
|
|
|
67
67
|
const message = error instanceof Error ? error.message : String(error);
|
|
68
68
|
return message.includes("invalid_execution_request_transition");
|
|
69
69
|
}
|
|
70
|
+
function trimmedStringField({
|
|
71
|
+
record,
|
|
72
|
+
key
|
|
73
|
+
}) {
|
|
74
|
+
const value = record[key];
|
|
75
|
+
return typeof value === "string" ? value.trim() : "";
|
|
76
|
+
}
|
|
77
|
+
function looksLikeAlreadyLinkedExecutionRequest({ text }) {
|
|
78
|
+
return text.includes(EXECUTION_REQUEST_ALREADY_LINKED_CODE) || /already linked to another(?: mission)? session/i.test(text);
|
|
79
|
+
}
|
|
80
|
+
function isExecutionRequestAlreadyLinkedPayload(payload) {
|
|
81
|
+
if (!payload || typeof payload !== "object") return false;
|
|
82
|
+
const record = payload;
|
|
83
|
+
if (trimmedStringField({ record, key: "code" }) === EXECUTION_REQUEST_ALREADY_LINKED_CODE) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
const text = [
|
|
87
|
+
trimmedStringField({ record, key: "error" }),
|
|
88
|
+
trimmedStringField({ record, key: "message" }),
|
|
89
|
+
trimmedStringField({ record, key: "detail" })
|
|
90
|
+
].join(" ");
|
|
91
|
+
return looksLikeAlreadyLinkedExecutionRequest({ text });
|
|
92
|
+
}
|
|
93
|
+
function isExecutionRequestAlreadyLinkedError(error) {
|
|
94
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
95
|
+
return looksLikeAlreadyLinkedExecutionRequest({ text: message });
|
|
96
|
+
}
|
|
97
|
+
function formatExecutionRequestAlreadyLinkedDiagnostic() {
|
|
98
|
+
return [
|
|
99
|
+
"Attach was rejected because this execution request is already linked to another mission session (`execution_request_already_linked`).",
|
|
100
|
+
"This is a stale mission-session binding, not a user authentication failure. Do not run `ovld auth login` or `ovld auth repair`.",
|
|
101
|
+
"Recovery: retry `ovld protocol attach` without `--execution-request-id` (unset OVERLORD_EXECUTION_REQUEST_ID). The existing session remains bound to the request; a new attach can continue the objective without relinking it."
|
|
102
|
+
].join("\n");
|
|
103
|
+
}
|
|
70
104
|
function formatCliError(error) {
|
|
105
|
+
if (isExecutionRequestAlreadyLinkedError(error)) {
|
|
106
|
+
return redactSecrets(formatExecutionRequestAlreadyLinkedDiagnostic());
|
|
107
|
+
}
|
|
71
108
|
if (error instanceof CliError) {
|
|
72
109
|
return redactSecrets(error.message);
|
|
73
110
|
}
|
|
@@ -76,7 +113,7 @@ function formatCliError(error) {
|
|
|
76
113
|
}
|
|
77
114
|
return redactSecrets(String(error));
|
|
78
115
|
}
|
|
79
|
-
var CliError;
|
|
116
|
+
var CliError, EXECUTION_REQUEST_ALREADY_LINKED_CODE;
|
|
80
117
|
var init_errors = __esm({
|
|
81
118
|
"src/errors.ts"() {
|
|
82
119
|
"use strict";
|
|
@@ -89,6 +126,7 @@ var init_errors = __esm({
|
|
|
89
126
|
this.exitCode = exitCode;
|
|
90
127
|
}
|
|
91
128
|
};
|
|
129
|
+
EXECUTION_REQUEST_ALREADY_LINKED_CODE = "execution_request_already_linked";
|
|
92
130
|
}
|
|
93
131
|
});
|
|
94
132
|
|
|
@@ -2593,7 +2631,7 @@ function configureCursorHarness({
|
|
|
2593
2631
|
event: "postToolUse",
|
|
2594
2632
|
command: CURSOR_HOOK_COMMANDS.postToolUse,
|
|
2595
2633
|
marker: "overlord-post-tool-use",
|
|
2596
|
-
extra: { matcher: "Shell|Write|Edit|MultiEdit|NotebookEdit" }
|
|
2634
|
+
extra: { matcher: "Shell|Write|Edit|MultiEdit|NotebookEdit|StrReplace" }
|
|
2597
2635
|
}) && "postToolUse",
|
|
2598
2636
|
mergeHook({
|
|
2599
2637
|
event: "stop",
|
|
@@ -3186,6 +3224,9 @@ Start the Desktop/local backend or run \`ovld config set cloud <url>\`.
|
|
|
3186
3224
|
}
|
|
3187
3225
|
const payload = await readResponseJson2(response);
|
|
3188
3226
|
if (!response.ok) {
|
|
3227
|
+
if (isExecutionRequestAlreadyLinkedPayload(payload)) {
|
|
3228
|
+
throw new CliError({ message: formatExecutionRequestAlreadyLinkedDiagnostic() });
|
|
3229
|
+
}
|
|
3189
3230
|
if (response.status === 401 && auth.headers.Authorization) {
|
|
3190
3231
|
const detail = errorMessageFromJson2(payload) ?? `Backend request failed: ${method} ${path36} (${response.status})`;
|
|
3191
3232
|
throw new CliError({
|
|
@@ -7492,6 +7533,8 @@ var init_tool_normalize = __esm({
|
|
|
7492
7533
|
editfile: "edit",
|
|
7493
7534
|
edit_file: "edit",
|
|
7494
7535
|
str_replace: "edit",
|
|
7536
|
+
// Cursor/IDE lowercases StrReplace → "strreplace" (no underscore).
|
|
7537
|
+
strreplace: "edit",
|
|
7495
7538
|
str_replace_editor: "edit",
|
|
7496
7539
|
apply_patch: "edit",
|
|
7497
7540
|
applypatch: "edit",
|
|
@@ -8074,7 +8117,9 @@ var init_codec_registry_generated = __esm({
|
|
|
8074
8117
|
"callIdPath": "call_id",
|
|
8075
8118
|
"fileEditKind": "file.edited",
|
|
8076
8119
|
"filePathPaths": [
|
|
8077
|
-
"file_path"
|
|
8120
|
+
"file_path",
|
|
8121
|
+
"filePath",
|
|
8122
|
+
"path"
|
|
8078
8123
|
]
|
|
8079
8124
|
}
|
|
8080
8125
|
]
|
|
@@ -19366,7 +19411,7 @@ var init_change_ledger = __esm({
|
|
|
19366
19411
|
|
|
19367
19412
|
// src/active-objective-sessions.ts
|
|
19368
19413
|
import { createHash as createHash9 } from "node:crypto";
|
|
19369
|
-
import { existsSync as existsSync24 } from "node:fs";
|
|
19414
|
+
import { existsSync as existsSync24, readdirSync as readdirSync4 } from "node:fs";
|
|
19370
19415
|
import path22 from "node:path";
|
|
19371
19416
|
function normalizeIdentifier(value) {
|
|
19372
19417
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -19529,6 +19574,63 @@ function readObjectiveSessions({
|
|
|
19529
19574
|
const aliases = entries.filter((entry) => entry.objectiveAliases.includes(requested));
|
|
19530
19575
|
return new Set(aliases.map((entry) => entry.objectiveId)).size === 1 ? aliases : [];
|
|
19531
19576
|
}
|
|
19577
|
+
function pathIsUnderWorkingDirectory({
|
|
19578
|
+
absolutePath,
|
|
19579
|
+
workingDirectory
|
|
19580
|
+
}) {
|
|
19581
|
+
const root = canonicalDirectory(workingDirectory);
|
|
19582
|
+
const resolved = path22.resolve(absolutePath);
|
|
19583
|
+
return resolved === root || resolved.startsWith(`${root}${path22.sep}`);
|
|
19584
|
+
}
|
|
19585
|
+
function resolveWorkingDirectoryForObjective({
|
|
19586
|
+
objectiveId,
|
|
19587
|
+
candidateWorkingDirectory,
|
|
19588
|
+
pathHints = []
|
|
19589
|
+
}) {
|
|
19590
|
+
const requested = normalizeIdentifier(objectiveId);
|
|
19591
|
+
if (!isValidIdentifier(requested)) return null;
|
|
19592
|
+
const candidate = path22.resolve(candidateWorkingDirectory);
|
|
19593
|
+
const local = readManifest2(candidate);
|
|
19594
|
+
if (local && resolveEntry(local.entries, requested)) {
|
|
19595
|
+
return local.workingDirectory;
|
|
19596
|
+
}
|
|
19597
|
+
const matches = [];
|
|
19598
|
+
const root = path22.join(resolveGlobalDataDir(), "active-objective-sessions");
|
|
19599
|
+
try {
|
|
19600
|
+
if (!existsSync24(root)) return null;
|
|
19601
|
+
for (const name of readdirSync4(root).slice(0, MAX_ACTIVE_SESSION_MANIFEST_FILES)) {
|
|
19602
|
+
if (!name.endsWith(".json")) continue;
|
|
19603
|
+
try {
|
|
19604
|
+
const raw = readBoundedUtf8File(path22.join(root, name), MAX_ACTIVE_SESSION_MANIFEST_BYTES);
|
|
19605
|
+
if (raw === null) continue;
|
|
19606
|
+
const value = JSON.parse(raw);
|
|
19607
|
+
if (value.schemaVersion !== 3 || typeof value.workingDirectory !== "string" || !Array.isArray(value.entries)) {
|
|
19608
|
+
continue;
|
|
19609
|
+
}
|
|
19610
|
+
const entries = value.entries.flatMap((entry) => {
|
|
19611
|
+
const normalized = normalizeEntry(entry);
|
|
19612
|
+
return normalized ? [normalized] : [];
|
|
19613
|
+
});
|
|
19614
|
+
if (!resolveEntry(entries, requested)) continue;
|
|
19615
|
+
const workingDirectory = canonicalDirectory(value.workingDirectory);
|
|
19616
|
+
if (!matches.includes(workingDirectory)) matches.push(workingDirectory);
|
|
19617
|
+
} catch {
|
|
19618
|
+
}
|
|
19619
|
+
}
|
|
19620
|
+
} catch {
|
|
19621
|
+
return null;
|
|
19622
|
+
}
|
|
19623
|
+
if (matches.length === 0) return null;
|
|
19624
|
+
if (matches.length === 1) return matches[0] ?? null;
|
|
19625
|
+
const absoluteHints = pathHints.filter((hint) => typeof hint === "string" && path22.isAbsolute(hint)).map((hint) => path22.resolve(hint));
|
|
19626
|
+
if (absoluteHints.length === 0) return null;
|
|
19627
|
+
const hinted = matches.filter(
|
|
19628
|
+
(workingDirectory) => absoluteHints.some(
|
|
19629
|
+
(absolutePath) => pathIsUnderWorkingDirectory({ absolutePath, workingDirectory })
|
|
19630
|
+
)
|
|
19631
|
+
);
|
|
19632
|
+
return hinted.length === 1 ? hinted[0] ?? null : null;
|
|
19633
|
+
}
|
|
19532
19634
|
function withActiveObjectiveSession({
|
|
19533
19635
|
workingDirectory,
|
|
19534
19636
|
objectiveId,
|
|
@@ -19591,7 +19693,7 @@ function finalizeActiveSession({
|
|
|
19591
19693
|
return false;
|
|
19592
19694
|
}
|
|
19593
19695
|
}
|
|
19594
|
-
var MAX_ACTIVE_OBJECTIVE_SESSION_BINDINGS, MAX_OBJECTIVE_ALIASES, MAX_ID_LENGTH, MAX_ACTIVE_SESSION_MANIFEST_BYTES;
|
|
19696
|
+
var MAX_ACTIVE_OBJECTIVE_SESSION_BINDINGS, MAX_OBJECTIVE_ALIASES, MAX_ID_LENGTH, MAX_ACTIVE_SESSION_MANIFEST_BYTES, MAX_ACTIVE_SESSION_MANIFEST_FILES;
|
|
19595
19697
|
var init_active_objective_sessions = __esm({
|
|
19596
19698
|
"src/active-objective-sessions.ts"() {
|
|
19597
19699
|
"use strict";
|
|
@@ -19602,6 +19704,7 @@ var init_active_objective_sessions = __esm({
|
|
|
19602
19704
|
MAX_OBJECTIVE_ALIASES = 16;
|
|
19603
19705
|
MAX_ID_LENGTH = 200;
|
|
19604
19706
|
MAX_ACTIVE_SESSION_MANIFEST_BYTES = 512 * 1024;
|
|
19707
|
+
MAX_ACTIVE_SESSION_MANIFEST_FILES = 256;
|
|
19605
19708
|
}
|
|
19606
19709
|
});
|
|
19607
19710
|
|
|
@@ -20156,6 +20259,42 @@ function resolveHookWorkingDirectory({
|
|
|
20156
20259
|
}
|
|
20157
20260
|
return path26.resolve(fallbackCwd);
|
|
20158
20261
|
}
|
|
20262
|
+
function withProjectRootFallback({
|
|
20263
|
+
payload,
|
|
20264
|
+
projectRootPaths,
|
|
20265
|
+
workingDirectory
|
|
20266
|
+
}) {
|
|
20267
|
+
const rootKey = projectRootPaths?.[0];
|
|
20268
|
+
if (!rootKey || rootKey.includes(".") || !payload || typeof payload !== "object") {
|
|
20269
|
+
return payload;
|
|
20270
|
+
}
|
|
20271
|
+
if (Array.isArray(payload)) return payload;
|
|
20272
|
+
const record = payload;
|
|
20273
|
+
if (exactProjectDirectory(record[rootKey])) return payload;
|
|
20274
|
+
return { ...record, [rootKey]: workingDirectory };
|
|
20275
|
+
}
|
|
20276
|
+
function collectAbsolutePathHints(payload) {
|
|
20277
|
+
const hints = [];
|
|
20278
|
+
const visit = (value, depth) => {
|
|
20279
|
+
if (hints.length >= MAX_PATH_HINTS || depth > 4) return;
|
|
20280
|
+
if (typeof value === "string") {
|
|
20281
|
+
if (path26.isAbsolute(value) && value.length <= 4096 && !hasControlCharacters(value)) {
|
|
20282
|
+
hints.push(path26.resolve(value));
|
|
20283
|
+
}
|
|
20284
|
+
return;
|
|
20285
|
+
}
|
|
20286
|
+
if (!value || typeof value !== "object") return;
|
|
20287
|
+
if (Array.isArray(value)) {
|
|
20288
|
+
for (const entry of value.slice(0, 8)) visit(entry, depth + 1);
|
|
20289
|
+
return;
|
|
20290
|
+
}
|
|
20291
|
+
for (const entry of Object.values(value).slice(0, 16)) {
|
|
20292
|
+
visit(entry, depth + 1);
|
|
20293
|
+
}
|
|
20294
|
+
};
|
|
20295
|
+
visit(payload, 0);
|
|
20296
|
+
return hints;
|
|
20297
|
+
}
|
|
20159
20298
|
function captureChangeFromPayload({
|
|
20160
20299
|
agent,
|
|
20161
20300
|
rawPayload,
|
|
@@ -20185,12 +20324,22 @@ function captureChangeFromPayload({
|
|
|
20185
20324
|
payloadFailure = "invalid JSON payload";
|
|
20186
20325
|
}
|
|
20187
20326
|
}
|
|
20188
|
-
const
|
|
20327
|
+
const candidateWorkingDirectory = resolveHookWorkingDirectory({
|
|
20189
20328
|
payload: nativePayload,
|
|
20190
20329
|
projectRootPaths: codec.projectRootPaths,
|
|
20191
20330
|
fallbackCwd
|
|
20192
20331
|
});
|
|
20193
|
-
const
|
|
20332
|
+
const workingDirectory = resolveWorkingDirectoryForObjective({
|
|
20333
|
+
objectiveId,
|
|
20334
|
+
candidateWorkingDirectory,
|
|
20335
|
+
pathHints: collectAbsolutePathHints(nativePayload)
|
|
20336
|
+
}) ?? candidateWorkingDirectory;
|
|
20337
|
+
const payloadForNormalize = withProjectRootFallback({
|
|
20338
|
+
payload: nativePayload,
|
|
20339
|
+
projectRootPaths: codec.projectRootPaths,
|
|
20340
|
+
workingDirectory
|
|
20341
|
+
});
|
|
20342
|
+
const normalized = payloadFailure ? null : normalizeForAdapter({ codec, payload: payloadForNormalize });
|
|
20194
20343
|
const directPaths = normalized?.kind === "file.edited" && Array.isArray(normalized.payload.paths) ? normalized.payload.paths.filter((value) => typeof value === "string") : [];
|
|
20195
20344
|
const confidentlyNonMutating = normalized?.kind === "tool.completed" && (normalized.payload.tool === "read" || normalized.payload.tool === "search" || normalized.payload.tool === "fetch");
|
|
20196
20345
|
return withActiveObjectiveSession({
|
|
@@ -20239,6 +20388,7 @@ function captureChangeFromPayload({
|
|
|
20239
20388
|
}
|
|
20240
20389
|
});
|
|
20241
20390
|
}
|
|
20391
|
+
var MAX_PATH_HINTS;
|
|
20242
20392
|
var init_capture_change = __esm({
|
|
20243
20393
|
"src/capture-change.ts"() {
|
|
20244
20394
|
"use strict";
|
|
@@ -20248,6 +20398,7 @@ var init_capture_change = __esm({
|
|
|
20248
20398
|
init_event();
|
|
20249
20399
|
init_active_objective_sessions();
|
|
20250
20400
|
init_change_ledger();
|
|
20401
|
+
MAX_PATH_HINTS = 16;
|
|
20251
20402
|
}
|
|
20252
20403
|
});
|
|
20253
20404
|
|
|
@@ -20658,6 +20809,9 @@ var init_pre_launch = __esm({
|
|
|
20658
20809
|
});
|
|
20659
20810
|
|
|
20660
20811
|
// src/terminal-launcher.ts
|
|
20812
|
+
function terminalOpenSpawnTimeoutMs(execution) {
|
|
20813
|
+
return execution.terminal ? TERMINAL_OPEN_SPAWN_TIMEOUT_MS : void 0;
|
|
20814
|
+
}
|
|
20661
20815
|
function shellQuote2(value) {
|
|
20662
20816
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
20663
20817
|
}
|
|
@@ -20975,11 +21129,14 @@ function resolveLaunchExecution({
|
|
|
20975
21129
|
});
|
|
20976
21130
|
return { command: full, args: [], useShell: true, terminal: launcher, display: full };
|
|
20977
21131
|
}
|
|
21132
|
+
var TERMINAL_OPEN_SPAWN_TIMEOUT_MS, TERMINAL_OPEN_SPAWN_KILL_SIGNAL;
|
|
20978
21133
|
var init_terminal_launcher = __esm({
|
|
20979
21134
|
"src/terminal-launcher.ts"() {
|
|
20980
21135
|
"use strict";
|
|
20981
21136
|
init_project_tmp();
|
|
20982
21137
|
init_terminal_launch_chord();
|
|
21138
|
+
TERMINAL_OPEN_SPAWN_TIMEOUT_MS = 45e3;
|
|
21139
|
+
TERMINAL_OPEN_SPAWN_KILL_SIGNAL = "SIGKILL";
|
|
20983
21140
|
}
|
|
20984
21141
|
});
|
|
20985
21142
|
|
|
@@ -20991,6 +21148,40 @@ function interactiveLoginShellInvocation(command, configuredShell = process.env.
|
|
|
20991
21148
|
const shell = configuredShell?.trim() || "/bin/bash";
|
|
20992
21149
|
return { command: shell, args: ["-ilc", command] };
|
|
20993
21150
|
}
|
|
21151
|
+
function spawnSyncOptionsForLaunch({
|
|
21152
|
+
cwd,
|
|
21153
|
+
env,
|
|
21154
|
+
timeoutMs
|
|
21155
|
+
}) {
|
|
21156
|
+
return {
|
|
21157
|
+
cwd,
|
|
21158
|
+
env,
|
|
21159
|
+
stdio: "inherit",
|
|
21160
|
+
...timeoutMs === void 0 ? {} : { timeout: timeoutMs, killSignal: TERMINAL_OPEN_SPAWN_KILL_SIGNAL }
|
|
21161
|
+
};
|
|
21162
|
+
}
|
|
21163
|
+
function isSpawnSyncTimedOut(result) {
|
|
21164
|
+
return result.error?.code === "ETIMEDOUT";
|
|
21165
|
+
}
|
|
21166
|
+
function terminalOpenTimeoutMessage({
|
|
21167
|
+
terminal,
|
|
21168
|
+
timeoutMs
|
|
21169
|
+
}) {
|
|
21170
|
+
const seconds = Math.round(timeoutMs / 1e3);
|
|
21171
|
+
return `osascript/Apple Event timed out after ${seconds}s while opening ${terminal}. The execution request failed so the runner can keep claiming. ${terminal} may still open after this timeout (orphan window).`;
|
|
21172
|
+
}
|
|
21173
|
+
function throwIfTerminalOpenTimedOut({
|
|
21174
|
+
result,
|
|
21175
|
+
execution
|
|
21176
|
+
}) {
|
|
21177
|
+
if (!execution.terminal || !isSpawnSyncTimedOut(result)) return;
|
|
21178
|
+
throw new Error(
|
|
21179
|
+
terminalOpenTimeoutMessage({
|
|
21180
|
+
terminal: execution.terminal,
|
|
21181
|
+
timeoutMs: TERMINAL_OPEN_SPAWN_TIMEOUT_MS
|
|
21182
|
+
})
|
|
21183
|
+
);
|
|
21184
|
+
}
|
|
20994
21185
|
function overlordLaunchEnv({
|
|
20995
21186
|
backendUrl,
|
|
20996
21187
|
missionId,
|
|
@@ -21422,16 +21613,15 @@ async function launchAgent({
|
|
|
21422
21613
|
};
|
|
21423
21614
|
}
|
|
21424
21615
|
const { execution } = plan;
|
|
21425
|
-
const
|
|
21426
|
-
const
|
|
21427
|
-
cwd: options.workingDirectory,
|
|
21428
|
-
env,
|
|
21429
|
-
stdio: "inherit"
|
|
21430
|
-
}) : spawnSync3(execution.command, execution.args, {
|
|
21616
|
+
const timeoutMs = terminalOpenSpawnTimeoutMs(execution);
|
|
21617
|
+
const spawnOptions = spawnSyncOptionsForLaunch({
|
|
21431
21618
|
cwd: options.workingDirectory,
|
|
21432
21619
|
env,
|
|
21433
|
-
|
|
21620
|
+
timeoutMs
|
|
21434
21621
|
});
|
|
21622
|
+
const shellInvocation = execution.useShell ? interactiveLoginShellInvocation(execution.command) : null;
|
|
21623
|
+
const result = shellInvocation ? spawnSync3(shellInvocation.command, shellInvocation.args, spawnOptions) : spawnSync3(execution.command, execution.args, spawnOptions);
|
|
21624
|
+
throwIfTerminalOpenTimedOut({ result, execution });
|
|
21435
21625
|
return {
|
|
21436
21626
|
plan,
|
|
21437
21627
|
status: result.status,
|
|
@@ -21464,7 +21654,7 @@ var init_launch = __esm({
|
|
|
21464
21654
|
});
|
|
21465
21655
|
|
|
21466
21656
|
// src/launch-bootstrap.ts
|
|
21467
|
-
import { existsSync as existsSync26, readdirSync as
|
|
21657
|
+
import { existsSync as existsSync26, readdirSync as readdirSync5, readFileSync as readFileSync16, statSync as statSync7 } from "node:fs";
|
|
21468
21658
|
import path30 from "node:path";
|
|
21469
21659
|
function firstCapture(match) {
|
|
21470
21660
|
if (!match) return null;
|
|
@@ -21491,7 +21681,7 @@ function recoverLaunchBootstrapFromProjectTmp({
|
|
|
21491
21681
|
const prefix = `launch-${safeMissionPart(trimmedMission)}-`;
|
|
21492
21682
|
let newest = null;
|
|
21493
21683
|
try {
|
|
21494
|
-
for (const name of
|
|
21684
|
+
for (const name of readdirSync5(tmpDir)) {
|
|
21495
21685
|
if (!name.startsWith(prefix) || !name.endsWith(".sh")) continue;
|
|
21496
21686
|
const filePath = path30.join(tmpDir, name);
|
|
21497
21687
|
try {
|
|
@@ -22644,13 +22834,66 @@ function resolveOvldInvocation(argv = process.argv, execPath = process.execPath)
|
|
|
22644
22834
|
}
|
|
22645
22835
|
return { program: execPath, args: ["runner", "supervise"] };
|
|
22646
22836
|
}
|
|
22837
|
+
function composeRunnerServicePath({
|
|
22838
|
+
homeDir = os5.homedir()
|
|
22839
|
+
} = {}) {
|
|
22840
|
+
const localBin = path33.join(homeDir, ".local", "bin");
|
|
22841
|
+
const dirs = [...RUNNER_SERVICE_PATH_PREFIX_DIRS, localBin, ...RUNNER_SERVICE_SYSTEM_PATH_DIRS];
|
|
22842
|
+
return [...new Set(dirs)].join(":");
|
|
22843
|
+
}
|
|
22844
|
+
function parseLaunchdProcessType(plist) {
|
|
22845
|
+
const match = /<key>ProcessType<\/key>\s*<string>([^<]*)<\/string>/.exec(plist);
|
|
22846
|
+
return match?.[1] ?? null;
|
|
22847
|
+
}
|
|
22848
|
+
function parseLaunchdEnvPath(plist) {
|
|
22849
|
+
const match = /<key>PATH<\/key>\s*<string>([^<]*)<\/string>/.exec(plist);
|
|
22850
|
+
return match?.[1] ?? null;
|
|
22851
|
+
}
|
|
22852
|
+
function inspectInstalledLaunchdPlist(plistPath) {
|
|
22853
|
+
if (!existsSync28(plistPath)) return { processType: null, path: null };
|
|
22854
|
+
try {
|
|
22855
|
+
const plist = readFileSync19(plistPath, "utf8");
|
|
22856
|
+
return {
|
|
22857
|
+
processType: parseLaunchdProcessType(plist),
|
|
22858
|
+
path: parseLaunchdEnvPath(plist)
|
|
22859
|
+
};
|
|
22860
|
+
} catch {
|
|
22861
|
+
return { processType: null, path: null };
|
|
22862
|
+
}
|
|
22863
|
+
}
|
|
22864
|
+
function runnerServiceReinstallHint({
|
|
22865
|
+
installed,
|
|
22866
|
+
publisher,
|
|
22867
|
+
processType,
|
|
22868
|
+
path: path36
|
|
22869
|
+
}) {
|
|
22870
|
+
if (!installed) return null;
|
|
22871
|
+
const hints = [];
|
|
22872
|
+
if (publisher === "node") {
|
|
22873
|
+
hints.push(
|
|
22874
|
+
'This service is registered under "Node.js Foundation" because it runs the plain node binary. Reinstall it from the Overlord desktop app (or with the desktop app present) to re-register it under "Overlord".'
|
|
22875
|
+
);
|
|
22876
|
+
}
|
|
22877
|
+
if (processType && processType !== LAUNCHD_PROCESS_TYPE) {
|
|
22878
|
+
hints.push(
|
|
22879
|
+
`This LaunchAgent is ProcessType=${processType}. App auto-update respawns the supervisor but does not rewrite ProcessType, so Apple Events to Terminal/iTerm stay App-Napped. Reinstall with \`ovld runner service install\` (or Desktop \u2192 Reinstall service) to switch to ${LAUNCHD_PROCESS_TYPE}.`
|
|
22880
|
+
);
|
|
22881
|
+
}
|
|
22882
|
+
if (path36 !== void 0 && path36 !== composeRunnerServicePath()) {
|
|
22883
|
+
hints.push(
|
|
22884
|
+
"This LaunchAgent PATH is not the deterministic prefix (`/opt/homebrew/bin:/usr/local/bin:$HOME/.local/bin` plus system dirs). App auto-update respawns the supervisor but does not rewrite PATH, so Latch/`open`/agent binaries spawned by the service may be missing. Reinstall with `ovld runner service install` (or Desktop \u2192 Reinstall service) to apply it."
|
|
22885
|
+
);
|
|
22886
|
+
}
|
|
22887
|
+
return hints.length > 0 ? hints.join(" ") : null;
|
|
22888
|
+
}
|
|
22647
22889
|
function buildRunnerServiceEnv({
|
|
22648
22890
|
backendUrl,
|
|
22649
22891
|
overlordHome,
|
|
22650
|
-
runAsElectronNode
|
|
22892
|
+
runAsElectronNode,
|
|
22893
|
+
homeDir
|
|
22651
22894
|
}) {
|
|
22652
22895
|
const env = {
|
|
22653
|
-
PATH:
|
|
22896
|
+
PATH: composeRunnerServicePath({ homeDir })
|
|
22654
22897
|
};
|
|
22655
22898
|
if (!isLoopbackBackendUrl(backendUrl)) env.OVERLORD_BACKEND_URL = backendUrl;
|
|
22656
22899
|
const home = overlordHome?.trim() || process.env.OVLD_HOME?.trim();
|
|
@@ -22697,7 +22940,7 @@ ${envEntries}
|
|
|
22697
22940
|
<key>StandardErrorPath</key>
|
|
22698
22941
|
<string>${xmlEscape(path33.join(logDir, "runner-service.err.log"))}</string>
|
|
22699
22942
|
<key>ProcessType</key>
|
|
22700
|
-
<string
|
|
22943
|
+
<string>${LAUNCHD_PROCESS_TYPE}</string>
|
|
22701
22944
|
</dict>
|
|
22702
22945
|
</plist>
|
|
22703
22946
|
`;
|
|
@@ -22762,7 +23005,7 @@ function resolveServiceManager(platform2 = process.platform) {
|
|
|
22762
23005
|
if (platform2 === "linux") return new SystemdUserManager();
|
|
22763
23006
|
return null;
|
|
22764
23007
|
}
|
|
22765
|
-
var execFileAsync, RUNNER_SERVICE_STATE_FILENAME, LAUNCHD_LABEL, SYSTEMD_UNIT_NAME, FALLBACK_POLL_INTERVAL_MS, LaunchdManager, SystemdUserManager;
|
|
23008
|
+
var execFileAsync, RUNNER_SERVICE_STATE_FILENAME, LAUNCHD_LABEL, SYSTEMD_UNIT_NAME, FALLBACK_POLL_INTERVAL_MS, LAUNCHD_PROCESS_TYPE, RUNNER_SERVICE_SYSTEM_PATH_DIRS, RUNNER_SERVICE_PATH_PREFIX_DIRS, LaunchdManager, SystemdUserManager;
|
|
22766
23009
|
var init_runner_service = __esm({
|
|
22767
23010
|
"src/runner-service.ts"() {
|
|
22768
23011
|
"use strict";
|
|
@@ -22772,6 +23015,9 @@ var init_runner_service = __esm({
|
|
|
22772
23015
|
LAUNCHD_LABEL = "io.overlord.runner";
|
|
22773
23016
|
SYSTEMD_UNIT_NAME = "overlord-runner";
|
|
22774
23017
|
FALLBACK_POLL_INTERVAL_MS = 5e3;
|
|
23018
|
+
LAUNCHD_PROCESS_TYPE = "Interactive";
|
|
23019
|
+
RUNNER_SERVICE_SYSTEM_PATH_DIRS = ["/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
23020
|
+
RUNNER_SERVICE_PATH_PREFIX_DIRS = ["/opt/homebrew/bin", "/usr/local/bin"];
|
|
22775
23021
|
LaunchdManager = class {
|
|
22776
23022
|
kind = "launchd";
|
|
22777
23023
|
identifier = LAUNCHD_LABEL;
|
|
@@ -23655,6 +23901,8 @@ async function runProtocolCommand({
|
|
|
23655
23901
|
path: protocolPath,
|
|
23656
23902
|
body: { ...protocolBody, flags }
|
|
23657
23903
|
});
|
|
23904
|
+
} else if (isExecutionRequestAlreadyLinkedError(error)) {
|
|
23905
|
+
throw new CliError({ message: formatExecutionRequestAlreadyLinkedDiagnostic() });
|
|
23658
23906
|
} else {
|
|
23659
23907
|
throw error;
|
|
23660
23908
|
}
|
|
@@ -24668,7 +24916,14 @@ async function runRunnerServiceCommand({
|
|
|
24668
24916
|
const runState = await manager.status();
|
|
24669
24917
|
const state = readRunnerServiceState();
|
|
24670
24918
|
const publisher = process.platform !== "darwin" || !state.execProgram ? "unknown" : state.execProgram.includes(".app/Contents/MacOS/") ? "overlord" : "node";
|
|
24671
|
-
const
|
|
24919
|
+
const inspected = manager.kind === "launchd" && runState.installed ? inspectInstalledLaunchdPlist(manager.unitPath()) : null;
|
|
24920
|
+
const processType = inspected?.processType ?? null;
|
|
24921
|
+
const reinstallHint = runnerServiceReinstallHint({
|
|
24922
|
+
installed: runState.installed,
|
|
24923
|
+
publisher,
|
|
24924
|
+
processType,
|
|
24925
|
+
...inspected ? { path: inspected.path } : {}
|
|
24926
|
+
});
|
|
24672
24927
|
const payload = {
|
|
24673
24928
|
supported: true,
|
|
24674
24929
|
kind: manager.kind,
|
|
@@ -24684,6 +24939,8 @@ async function runRunnerServiceCommand({
|
|
|
24684
24939
|
lastError: state.lastError,
|
|
24685
24940
|
currentPollIntervalMs: state.currentPollIntervalMs,
|
|
24686
24941
|
publisher,
|
|
24942
|
+
processType,
|
|
24943
|
+
path: inspected?.path ?? null,
|
|
24687
24944
|
reinstallHint
|
|
24688
24945
|
};
|
|
24689
24946
|
if (json) printJson(payload);
|
|
@@ -24693,6 +24950,7 @@ async function runRunnerServiceCommand({
|
|
|
24693
24950
|
Installed: runState.installed ? "yes" : "no",
|
|
24694
24951
|
Running: runState.running,
|
|
24695
24952
|
Publisher: publisher === "unknown" ? "(unknown)" : publisher,
|
|
24953
|
+
...processType ? { "Process type": processType } : {},
|
|
24696
24954
|
Backend: state.backendUrl ?? "(unknown)",
|
|
24697
24955
|
"Last heartbeat": state.lastHeartbeatAt ?? "(never)",
|
|
24698
24956
|
"Last launched": state.lastLaunchedAt ?? "(never)",
|
|
@@ -24728,7 +24986,7 @@ Note: ${reinstallHint}`);
|
|
|
24728
24986
|
if (json) printJson({ started: autoStart, ...runState });
|
|
24729
24987
|
else
|
|
24730
24988
|
console.log(
|
|
24731
|
-
`Persistent runner installed (${manager.kind}) and ${autoStart ? "started" : "not started"}.`
|
|
24989
|
+
`Persistent runner installed (${manager.kind}) and ${autoStart ? "started" : "not started"}.` + (manager.kind === "launchd" ? " Re-running install rewrites the LaunchAgent (ProcessType Interactive and PATH prefix); app auto-update respawns the process but does not rewrite the plist." : "")
|
|
24732
24990
|
);
|
|
24733
24991
|
return;
|
|
24734
24992
|
}
|