overlord-cli 0.2608132027.0 → 0.2608141841.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 +479 -367
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3073,16 +3073,21 @@ function normalizeBaseUrl4(value) {
|
|
|
3073
3073
|
function resolveAuthHeaders({ baseUrl }) {
|
|
3074
3074
|
const fromEnv = process.env.OVERLORD_USER_TOKEN?.trim() || process.env.OVLD_USER_TOKEN?.trim() || process.env.USER_TOKEN?.trim();
|
|
3075
3075
|
if (fromEnv) {
|
|
3076
|
-
return {
|
|
3076
|
+
return {
|
|
3077
|
+
headers: { Authorization: `Bearer ${fromEnv}` },
|
|
3078
|
+
fromStored: false,
|
|
3079
|
+
storedCredentialBackendUrl: null
|
|
3080
|
+
};
|
|
3077
3081
|
}
|
|
3078
3082
|
const stored = readStoredAuthCredentials();
|
|
3079
|
-
if (!stored) return { headers: {}, fromStored: false };
|
|
3083
|
+
if (!stored) return { headers: {}, fromStored: false, storedCredentialBackendUrl: null };
|
|
3080
3084
|
if (normalizeBaseUrl4(stored.backendUrl) !== normalizeBaseUrl4(baseUrl)) {
|
|
3081
|
-
return { headers: {}, fromStored: false };
|
|
3085
|
+
return { headers: {}, fromStored: false, storedCredentialBackendUrl: stored.backendUrl };
|
|
3082
3086
|
}
|
|
3083
3087
|
return {
|
|
3084
3088
|
headers: { Authorization: `Bearer ${stored.token}` },
|
|
3085
|
-
fromStored: true
|
|
3089
|
+
fromStored: true,
|
|
3090
|
+
storedCredentialBackendUrl: null
|
|
3086
3091
|
};
|
|
3087
3092
|
}
|
|
3088
3093
|
async function readResponseJson2(response) {
|
|
@@ -3146,6 +3151,12 @@ function createBackendClient() {
|
|
|
3146
3151
|
}) {
|
|
3147
3152
|
const url = `${baseUrl}${path34.startsWith("/") ? path34 : `/${path34}`}`;
|
|
3148
3153
|
const auth = resolveAuthHeaders({ baseUrl });
|
|
3154
|
+
if (auth.storedCredentialBackendUrl) {
|
|
3155
|
+
throw new CliError({
|
|
3156
|
+
message: `Saved credentials are for ${normalizeBaseUrl4(auth.storedCredentialBackendUrl)}, but this CLI is configured for ${baseUrl}.
|
|
3157
|
+
The backend URL may have changed. Run \`ovld auth login\` to sign in to the current backend.`
|
|
3158
|
+
});
|
|
3159
|
+
}
|
|
3149
3160
|
let response;
|
|
3150
3161
|
try {
|
|
3151
3162
|
response = await fetch(url, {
|
|
@@ -16556,12 +16567,88 @@ var init_latch_environment = __esm({
|
|
|
16556
16567
|
}
|
|
16557
16568
|
});
|
|
16558
16569
|
|
|
16559
|
-
// ../packages/core/dist/service/
|
|
16570
|
+
// ../packages/core/dist/service/terminal-profile-types.js
|
|
16571
|
+
function parseViewerOpenAs(value) {
|
|
16572
|
+
return typeof value === "string" && value.trim().toLowerCase() === "tab" ? "tab" : DEFAULT_VIEWER_OPEN_AS;
|
|
16573
|
+
}
|
|
16560
16574
|
function trimmed(value) {
|
|
16561
16575
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
16562
16576
|
}
|
|
16577
|
+
function viewerKindForLauncher(launcher) {
|
|
16578
|
+
const value = trimmed(launcher);
|
|
16579
|
+
if (!value)
|
|
16580
|
+
return "inline";
|
|
16581
|
+
const lowered = value.toLowerCase();
|
|
16582
|
+
if (lowered === "iterm2" || lowered === "iterm")
|
|
16583
|
+
return "iterm";
|
|
16584
|
+
if (lowered === "terminal")
|
|
16585
|
+
return "terminal";
|
|
16586
|
+
return "custom";
|
|
16587
|
+
}
|
|
16588
|
+
function normalizeExecutionProvider(value) {
|
|
16589
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16590
|
+
return null;
|
|
16591
|
+
const cast = value;
|
|
16592
|
+
const kind = trimmed(cast.kind)?.toLowerCase() === "latch" ? "latch" : "direct";
|
|
16593
|
+
return {
|
|
16594
|
+
kind,
|
|
16595
|
+
executable: trimmed(cast.executable) ?? DEFAULT_LATCH_EXECUTABLE
|
|
16596
|
+
};
|
|
16597
|
+
}
|
|
16598
|
+
function launchSessionSnapshotFromMetadata(metadata) {
|
|
16599
|
+
const raw = metadata?.[LAUNCH_SESSION_METADATA_KEY];
|
|
16600
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
16601
|
+
return null;
|
|
16602
|
+
const cast = raw;
|
|
16603
|
+
if (cast.version !== TERMINAL_PROFILE_VERSION)
|
|
16604
|
+
return null;
|
|
16605
|
+
const viewer = cast.viewer && typeof cast.viewer === "object" && !Array.isArray(cast.viewer) ? cast.viewer : null;
|
|
16606
|
+
const launcher = trimmed(viewer?.launcher);
|
|
16607
|
+
const source = (value) => trimmed(value) === "target" ? "target" : "user_default";
|
|
16608
|
+
return {
|
|
16609
|
+
version: TERMINAL_PROFILE_VERSION,
|
|
16610
|
+
executionProvider: normalizeExecutionProvider(cast.executionProvider) ?? {
|
|
16611
|
+
...DEFAULT_EXECUTION_PROVIDER
|
|
16612
|
+
},
|
|
16613
|
+
viewer: {
|
|
16614
|
+
kind: trimmed(viewer?.kind) ? trimmed(viewer?.kind) : viewerKindForLauncher(launcher),
|
|
16615
|
+
launcher,
|
|
16616
|
+
openOnLaunch: viewer?.openOnLaunch !== false,
|
|
16617
|
+
// A snapshot frozen before `openAs` existed carries none; `window` is what
|
|
16618
|
+
// those runs actually did, so the absent case must not become `tab`.
|
|
16619
|
+
openAs: parseViewerOpenAs(viewer?.openAs)
|
|
16620
|
+
},
|
|
16621
|
+
executionProviderSource: source(cast.executionProviderSource),
|
|
16622
|
+
viewerOpenSource: source(cast.viewerOpenSource),
|
|
16623
|
+
resolvedAt: trimmed(cast.resolvedAt) ?? ""
|
|
16624
|
+
};
|
|
16625
|
+
}
|
|
16626
|
+
var DEFAULT_VIEWER_OPEN_AS, TERMINAL_PROFILE_VERSION, DEFAULT_LATCH_EXECUTABLE, DEFAULT_EXECUTION_PROVIDER, DEFAULT_OPEN_VIEWER_ON_LAUNCH, DEFAULT_LAUNCH_SESSION_DEFAULTS, LAUNCH_SESSION_METADATA_KEY;
|
|
16627
|
+
var init_terminal_profile_types2 = __esm({
|
|
16628
|
+
"../packages/core/dist/service/terminal-profile-types.js"() {
|
|
16629
|
+
"use strict";
|
|
16630
|
+
DEFAULT_VIEWER_OPEN_AS = "window";
|
|
16631
|
+
TERMINAL_PROFILE_VERSION = 1;
|
|
16632
|
+
DEFAULT_LATCH_EXECUTABLE = "latch";
|
|
16633
|
+
DEFAULT_EXECUTION_PROVIDER = {
|
|
16634
|
+
kind: "direct",
|
|
16635
|
+
executable: DEFAULT_LATCH_EXECUTABLE
|
|
16636
|
+
};
|
|
16637
|
+
DEFAULT_OPEN_VIEWER_ON_LAUNCH = true;
|
|
16638
|
+
DEFAULT_LAUNCH_SESSION_DEFAULTS = {
|
|
16639
|
+
executionProvider: { ...DEFAULT_EXECUTION_PROVIDER },
|
|
16640
|
+
openViewerOnLaunch: DEFAULT_OPEN_VIEWER_ON_LAUNCH
|
|
16641
|
+
};
|
|
16642
|
+
LAUNCH_SESSION_METADATA_KEY = "launchSession";
|
|
16643
|
+
}
|
|
16644
|
+
});
|
|
16645
|
+
|
|
16646
|
+
// ../packages/core/dist/service/latch-launch.js
|
|
16647
|
+
function trimmed2(value) {
|
|
16648
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
16649
|
+
}
|
|
16563
16650
|
function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.trim() || "/bin/bash", cwd, env, size = DEFAULT_LATCH_TERMINAL_SIZE, title, name, commandLabel, externalRunId }) {
|
|
16564
|
-
const shellPath =
|
|
16651
|
+
const shellPath = trimmed2(shell) ?? "/bin/bash";
|
|
16565
16652
|
const cleanedEnv = {};
|
|
16566
16653
|
for (const [key, value] of Object.entries(env)) {
|
|
16567
16654
|
if (key.trim() && typeof value === "string")
|
|
@@ -16570,15 +16657,15 @@ function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.tr
|
|
|
16570
16657
|
const display = {
|
|
16571
16658
|
source: {
|
|
16572
16659
|
kind: "overlord",
|
|
16573
|
-
...
|
|
16660
|
+
...trimmed2(externalRunId) ? { external_run_id: trimmed2(externalRunId) } : {}
|
|
16574
16661
|
}
|
|
16575
16662
|
};
|
|
16576
|
-
if (
|
|
16577
|
-
display.title =
|
|
16578
|
-
if (
|
|
16579
|
-
display.name =
|
|
16580
|
-
if (
|
|
16581
|
-
display.command_label =
|
|
16663
|
+
if (trimmed2(title))
|
|
16664
|
+
display.title = trimmed2(title);
|
|
16665
|
+
if (trimmed2(name))
|
|
16666
|
+
display.name = trimmed2(name);
|
|
16667
|
+
if (trimmed2(commandLabel))
|
|
16668
|
+
display.command_label = trimmed2(commandLabel);
|
|
16582
16669
|
return {
|
|
16583
16670
|
format_version: LATCH_MANIFEST_FORMAT_VERSION,
|
|
16584
16671
|
launch: {
|
|
@@ -16597,7 +16684,7 @@ function buildLatchCreateManifest({ commandString, shell = process.env.SHELL?.tr
|
|
|
16597
16684
|
function parseLatchCreateReport(raw) {
|
|
16598
16685
|
try {
|
|
16599
16686
|
const parsed = JSON.parse(raw);
|
|
16600
|
-
const id =
|
|
16687
|
+
const id = trimmed2(parsed.session?.id);
|
|
16601
16688
|
if (!id)
|
|
16602
16689
|
return null;
|
|
16603
16690
|
const protocolVersion = typeof parsed.protocolVersion === "number" && Number.isFinite(parsed.protocolVersion) ? parsed.protocolVersion : LATCH_MANIFEST_FORMAT_VERSION;
|
|
@@ -16605,9 +16692,9 @@ function parseLatchCreateReport(raw) {
|
|
|
16605
16692
|
protocolVersion,
|
|
16606
16693
|
session: {
|
|
16607
16694
|
id,
|
|
16608
|
-
name:
|
|
16609
|
-
state:
|
|
16610
|
-
createdAt:
|
|
16695
|
+
name: trimmed2(parsed.session?.name) ?? id,
|
|
16696
|
+
state: trimmed2(parsed.session?.state) ?? "running",
|
|
16697
|
+
createdAt: trimmed2(parsed.session?.createdAt) ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
16611
16698
|
}
|
|
16612
16699
|
};
|
|
16613
16700
|
} catch {
|
|
@@ -16619,28 +16706,28 @@ function toExecutionProviderSession({ createReport, executionTargetId, createdAt
|
|
|
16619
16706
|
provider: "latch",
|
|
16620
16707
|
providerSessionId: createReport.session.id,
|
|
16621
16708
|
sessionName: createReport.session.name,
|
|
16622
|
-
executionTargetId:
|
|
16709
|
+
executionTargetId: trimmed2(executionTargetId),
|
|
16623
16710
|
agentSessionId: null,
|
|
16624
16711
|
createdAt: createdAt ?? createReport.session.createdAt,
|
|
16625
16712
|
lastObservedState: createReport.session.state
|
|
16626
16713
|
};
|
|
16627
16714
|
}
|
|
16628
16715
|
function existingLatchProviderSession({ latchSessionId, executionTargetId, createdAt = (/* @__PURE__ */ new Date()).toISOString() }) {
|
|
16629
|
-
const providerSessionId =
|
|
16716
|
+
const providerSessionId = trimmed2(latchSessionId);
|
|
16630
16717
|
if (!providerSessionId)
|
|
16631
16718
|
return null;
|
|
16632
16719
|
return {
|
|
16633
16720
|
provider: "latch",
|
|
16634
16721
|
providerSessionId,
|
|
16635
16722
|
sessionName: null,
|
|
16636
|
-
executionTargetId:
|
|
16723
|
+
executionTargetId: trimmed2(executionTargetId),
|
|
16637
16724
|
agentSessionId: null,
|
|
16638
16725
|
createdAt,
|
|
16639
16726
|
lastObservedState: "running"
|
|
16640
16727
|
};
|
|
16641
16728
|
}
|
|
16642
16729
|
function latchViewerFlagForKind(kind) {
|
|
16643
|
-
switch (
|
|
16730
|
+
switch (trimmed2(kind)?.toLowerCase()) {
|
|
16644
16731
|
case "iterm":
|
|
16645
16732
|
case "iterm2":
|
|
16646
16733
|
return "iterm";
|
|
@@ -16648,28 +16735,59 @@ function latchViewerFlagForKind(kind) {
|
|
|
16648
16735
|
return null;
|
|
16649
16736
|
}
|
|
16650
16737
|
}
|
|
16738
|
+
function compareLatchProductVersions(a, b) {
|
|
16739
|
+
const parts = (value) => value.trim().split(".").map((segment) => {
|
|
16740
|
+
const parsed = Number.parseInt(segment, 10);
|
|
16741
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
16742
|
+
});
|
|
16743
|
+
const left = parts(a);
|
|
16744
|
+
const right = parts(b);
|
|
16745
|
+
const length = Math.max(left.length, right.length);
|
|
16746
|
+
for (let index = 0; index < length; index += 1) {
|
|
16747
|
+
const diff = (left[index] ?? 0) - (right[index] ?? 0);
|
|
16748
|
+
if (diff !== 0)
|
|
16749
|
+
return diff;
|
|
16750
|
+
}
|
|
16751
|
+
return 0;
|
|
16752
|
+
}
|
|
16753
|
+
function latchSupportsOpenAs(productVersion) {
|
|
16754
|
+
const version = trimmed2(productVersion);
|
|
16755
|
+
if (!version)
|
|
16756
|
+
return false;
|
|
16757
|
+
return compareLatchProductVersions(version, LATCH_OPEN_AS_MIN_PRODUCT_VERSION) >= 0;
|
|
16758
|
+
}
|
|
16759
|
+
function buildLatchOpenArgs({ providerSessionId, viewer, openAs, productVersion }) {
|
|
16760
|
+
const args = ["open", providerSessionId, "--with", viewer];
|
|
16761
|
+
if (openAs && latchSupportsOpenAs(productVersion)) {
|
|
16762
|
+
args.push("--as", parseViewerOpenAs(openAs));
|
|
16763
|
+
}
|
|
16764
|
+
args.push("--json");
|
|
16765
|
+
return args;
|
|
16766
|
+
}
|
|
16651
16767
|
function latchAttachCommand({ executable = "latch", providerSessionId }) {
|
|
16652
|
-
return `${
|
|
16768
|
+
return `${trimmed2(executable) ?? "latch"} attach ${providerSessionId}`;
|
|
16653
16769
|
}
|
|
16654
16770
|
function shouldUseLatchProvider({ providerKind, latchSelectable }) {
|
|
16655
|
-
return
|
|
16771
|
+
return trimmed2(providerKind)?.toLowerCase() === "latch" && latchSelectable === true;
|
|
16656
16772
|
}
|
|
16657
|
-
var LATCH_MANIFEST_FORMAT_VERSION, DEFAULT_LATCH_TERMINAL_SIZE;
|
|
16773
|
+
var LATCH_MANIFEST_FORMAT_VERSION, DEFAULT_LATCH_TERMINAL_SIZE, LATCH_OPEN_AS_MIN_PRODUCT_VERSION;
|
|
16658
16774
|
var init_latch_launch = __esm({
|
|
16659
16775
|
"../packages/core/dist/service/latch-launch.js"() {
|
|
16660
16776
|
"use strict";
|
|
16777
|
+
init_terminal_profile_types2();
|
|
16661
16778
|
LATCH_MANIFEST_FORMAT_VERSION = 1;
|
|
16662
16779
|
DEFAULT_LATCH_TERMINAL_SIZE = { cols: 120, rows: 36 };
|
|
16780
|
+
LATCH_OPEN_AS_MIN_PRODUCT_VERSION = "0.2608140931.0";
|
|
16663
16781
|
}
|
|
16664
16782
|
});
|
|
16665
16783
|
|
|
16666
16784
|
// ../packages/core/dist/service/latch-session.js
|
|
16667
16785
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
16668
|
-
function
|
|
16786
|
+
function trimmed3(value) {
|
|
16669
16787
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
16670
16788
|
}
|
|
16671
16789
|
function parseState(value) {
|
|
16672
|
-
switch (
|
|
16790
|
+
switch (trimmed3(value)) {
|
|
16673
16791
|
case "running":
|
|
16674
16792
|
return "running";
|
|
16675
16793
|
case "exited":
|
|
@@ -16708,11 +16826,11 @@ function runLatchJson({ executable, args }) {
|
|
|
16708
16826
|
}
|
|
16709
16827
|
}
|
|
16710
16828
|
function inspectLatchSession({ executable = "latch", providerSessionId }) {
|
|
16711
|
-
const sessionId =
|
|
16829
|
+
const sessionId = trimmed3(providerSessionId);
|
|
16712
16830
|
if (!sessionId)
|
|
16713
16831
|
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
16714
16832
|
const report = runLatchJson({
|
|
16715
|
-
executable:
|
|
16833
|
+
executable: trimmed3(executable) ?? "latch",
|
|
16716
16834
|
args: ["inspect", sessionId, "--json"]
|
|
16717
16835
|
});
|
|
16718
16836
|
const state = parseState(report.state);
|
|
@@ -16720,47 +16838,61 @@ function inspectLatchSession({ executable = "latch", providerSessionId }) {
|
|
|
16720
16838
|
throw new LatchSessionCommandError("Latch returned an unsupported session state.");
|
|
16721
16839
|
const exit = report.exit && typeof report.exit === "object" && !Array.isArray(report.exit) ? report.exit : null;
|
|
16722
16840
|
return {
|
|
16723
|
-
providerSessionId:
|
|
16724
|
-
name:
|
|
16841
|
+
providerSessionId: trimmed3(report.id) ?? sessionId,
|
|
16842
|
+
name: trimmed3(report.name) ?? sessionId,
|
|
16725
16843
|
state,
|
|
16726
16844
|
exitCode: typeof exit?.code === "number" && Number.isFinite(exit.code) ? exit.code : null,
|
|
16727
16845
|
inspectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
16728
16846
|
};
|
|
16729
16847
|
}
|
|
16730
|
-
function
|
|
16731
|
-
|
|
16848
|
+
function readLatchProductVersion(executable) {
|
|
16849
|
+
try {
|
|
16850
|
+
return trimmed3(runLatchJson({ executable, args: ["capabilities", "--json"] }).productVersion);
|
|
16851
|
+
} catch {
|
|
16852
|
+
return null;
|
|
16853
|
+
}
|
|
16854
|
+
}
|
|
16855
|
+
function openLatchSession({ executable = "latch", providerSessionId, viewerKind, openAs }) {
|
|
16856
|
+
const sessionId = trimmed3(providerSessionId);
|
|
16732
16857
|
if (!sessionId)
|
|
16733
16858
|
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
16734
16859
|
const viewer = latchViewerFlagForKind(viewerKind);
|
|
16735
16860
|
if (!viewer) {
|
|
16736
16861
|
throw new LatchSessionCommandError(`Latch cannot open the configured viewer "${viewerKind}".`);
|
|
16737
16862
|
}
|
|
16863
|
+
const exe = trimmed3(executable) ?? "latch";
|
|
16738
16864
|
const report = runLatchJson({
|
|
16739
|
-
executable:
|
|
16740
|
-
args:
|
|
16865
|
+
executable: exe,
|
|
16866
|
+
args: buildLatchOpenArgs({
|
|
16867
|
+
providerSessionId: sessionId,
|
|
16868
|
+
viewer,
|
|
16869
|
+
openAs,
|
|
16870
|
+
productVersion: openAs ? readLatchProductVersion(exe) : null
|
|
16871
|
+
})
|
|
16741
16872
|
});
|
|
16742
16873
|
if (report.opened !== true) {
|
|
16743
16874
|
throw new LatchSessionCommandError(`Latch did not open the ${viewer} viewer.`);
|
|
16744
16875
|
}
|
|
16745
16876
|
return {
|
|
16746
|
-
providerSessionId:
|
|
16747
|
-
viewer:
|
|
16748
|
-
opened: true
|
|
16877
|
+
providerSessionId: trimmed3(report.id) ?? sessionId,
|
|
16878
|
+
viewer: trimmed3(report.viewer) ?? viewer,
|
|
16879
|
+
opened: true,
|
|
16880
|
+
behavior: trimmed3(report.behavior) ? parseViewerOpenAs(report.behavior) : null
|
|
16749
16881
|
};
|
|
16750
16882
|
}
|
|
16751
16883
|
function stopLatchSession({ executable = "latch", providerSessionId }) {
|
|
16752
|
-
const sessionId =
|
|
16884
|
+
const sessionId = trimmed3(providerSessionId);
|
|
16753
16885
|
if (!sessionId)
|
|
16754
16886
|
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
16755
16887
|
const report = runLatchJson({
|
|
16756
|
-
executable:
|
|
16888
|
+
executable: trimmed3(executable) ?? "latch",
|
|
16757
16889
|
args: ["stop", sessionId, "--json"]
|
|
16758
16890
|
});
|
|
16759
16891
|
const state = parseState(report.state);
|
|
16760
16892
|
if (!state)
|
|
16761
16893
|
throw new LatchSessionCommandError("Latch returned an unsupported session state.");
|
|
16762
16894
|
return {
|
|
16763
|
-
providerSessionId:
|
|
16895
|
+
providerSessionId: trimmed3(report.id) ?? sessionId,
|
|
16764
16896
|
state
|
|
16765
16897
|
};
|
|
16766
16898
|
}
|
|
@@ -16770,6 +16902,7 @@ var init_latch_session = __esm({
|
|
|
16770
16902
|
"use strict";
|
|
16771
16903
|
init_latch_environment();
|
|
16772
16904
|
init_latch_launch();
|
|
16905
|
+
init_terminal_profile_types2();
|
|
16773
16906
|
LatchSessionCommandError = class extends Error {
|
|
16774
16907
|
constructor(message) {
|
|
16775
16908
|
super(message);
|
|
@@ -16781,17 +16914,17 @@ var init_latch_session = __esm({
|
|
|
16781
16914
|
|
|
16782
16915
|
// ../packages/core/dist/service/latch-events.js
|
|
16783
16916
|
import { spawn as spawn3 } from "node:child_process";
|
|
16784
|
-
function
|
|
16917
|
+
function trimmed4(value) {
|
|
16785
16918
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
16786
16919
|
}
|
|
16787
16920
|
function parseHarnessEvent(value) {
|
|
16788
16921
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16789
16922
|
return null;
|
|
16790
16923
|
const row = value;
|
|
16791
|
-
const type =
|
|
16792
|
-
const sessionId =
|
|
16793
|
-
const at =
|
|
16794
|
-
const harnessVersion =
|
|
16924
|
+
const type = trimmed4(row.type);
|
|
16925
|
+
const sessionId = trimmed4(row.sessionId);
|
|
16926
|
+
const at = trimmed4(row.at);
|
|
16927
|
+
const harnessVersion = trimmed4(row.harnessVersion);
|
|
16795
16928
|
const connectorEpoch = typeof row.connectorEpoch === "number" && Number.isFinite(row.connectorEpoch) ? row.connectorEpoch : null;
|
|
16796
16929
|
if (!type || !HARNESS_EVENT_TYPES.has(type) || !sessionId || !at || !harnessVersion)
|
|
16797
16930
|
return null;
|
|
@@ -16802,26 +16935,26 @@ function parseHarnessEvent(value) {
|
|
|
16802
16935
|
case "user_message":
|
|
16803
16936
|
case "assistant_delta":
|
|
16804
16937
|
case "assistant_message": {
|
|
16805
|
-
const text =
|
|
16938
|
+
const text = trimmed4(row.text);
|
|
16806
16939
|
if (!text)
|
|
16807
16940
|
return null;
|
|
16808
16941
|
return { ...base, type, text };
|
|
16809
16942
|
}
|
|
16810
16943
|
case "tool_started": {
|
|
16811
|
-
const tool =
|
|
16944
|
+
const tool = trimmed4(row.tool);
|
|
16812
16945
|
if (!tool)
|
|
16813
16946
|
return null;
|
|
16814
16947
|
return { ...base, type, tool, input: row.input };
|
|
16815
16948
|
}
|
|
16816
16949
|
case "tool_finished": {
|
|
16817
|
-
const tool =
|
|
16950
|
+
const tool = trimmed4(row.tool);
|
|
16818
16951
|
if (!tool)
|
|
16819
16952
|
return null;
|
|
16820
16953
|
return { ...base, type, tool, output: row.output };
|
|
16821
16954
|
}
|
|
16822
16955
|
case "awaiting_input": {
|
|
16823
|
-
const requestId =
|
|
16824
|
-
const kind =
|
|
16956
|
+
const requestId = trimmed4(row.requestId);
|
|
16957
|
+
const kind = trimmed4(row.kind);
|
|
16825
16958
|
const prompt = typeof row.prompt === "string" ? row.prompt : null;
|
|
16826
16959
|
if (!requestId || kind !== "permission" && kind !== "question" || prompt === null) {
|
|
16827
16960
|
return null;
|
|
@@ -16837,7 +16970,7 @@ function parseHarnessEvent(value) {
|
|
|
16837
16970
|
};
|
|
16838
16971
|
}
|
|
16839
16972
|
case "status": {
|
|
16840
|
-
const status =
|
|
16973
|
+
const status = trimmed4(row.status);
|
|
16841
16974
|
if (!status)
|
|
16842
16975
|
return null;
|
|
16843
16976
|
return { ...base, type, status };
|
|
@@ -16862,11 +16995,11 @@ function parseHarnessEventNdjson(raw) {
|
|
|
16862
16995
|
return events;
|
|
16863
16996
|
}
|
|
16864
16997
|
async function collectLatchEvents({ executable = "latch", providerSessionId, from = 0, idleMs = 250, timeoutMs = 8e3 }) {
|
|
16865
|
-
const sessionId =
|
|
16998
|
+
const sessionId = trimmed4(providerSessionId);
|
|
16866
16999
|
if (!sessionId)
|
|
16867
17000
|
throw new LatchSessionCommandError("A Latch session id is required.");
|
|
16868
17001
|
const fromCursor = Number.isFinite(from) && from > 0 ? Math.floor(from) : 0;
|
|
16869
|
-
const bin =
|
|
17002
|
+
const bin = trimmed4(executable) ?? "latch";
|
|
16870
17003
|
return new Promise((resolve, reject) => {
|
|
16871
17004
|
const child = spawn3(bin, ["events", sessionId, "--json", "--from", String(fromCursor)], {
|
|
16872
17005
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -17281,75 +17414,6 @@ var init_git_tree = __esm({
|
|
|
17281
17414
|
}
|
|
17282
17415
|
});
|
|
17283
17416
|
|
|
17284
|
-
// ../packages/core/dist/service/terminal-profile-types.js
|
|
17285
|
-
function trimmed4(value) {
|
|
17286
|
-
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
17287
|
-
}
|
|
17288
|
-
function viewerKindForLauncher(launcher) {
|
|
17289
|
-
const value = trimmed4(launcher);
|
|
17290
|
-
if (!value)
|
|
17291
|
-
return "inline";
|
|
17292
|
-
const lowered = value.toLowerCase();
|
|
17293
|
-
if (lowered === "iterm2" || lowered === "iterm")
|
|
17294
|
-
return "iterm";
|
|
17295
|
-
if (lowered === "terminal")
|
|
17296
|
-
return "terminal";
|
|
17297
|
-
return "custom";
|
|
17298
|
-
}
|
|
17299
|
-
function normalizeExecutionProvider(value) {
|
|
17300
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
17301
|
-
return null;
|
|
17302
|
-
const cast = value;
|
|
17303
|
-
const kind = trimmed4(cast.kind)?.toLowerCase() === "latch" ? "latch" : "direct";
|
|
17304
|
-
return {
|
|
17305
|
-
kind,
|
|
17306
|
-
executable: trimmed4(cast.executable) ?? DEFAULT_LATCH_EXECUTABLE
|
|
17307
|
-
};
|
|
17308
|
-
}
|
|
17309
|
-
function launchSessionSnapshotFromMetadata(metadata) {
|
|
17310
|
-
const raw = metadata?.[LAUNCH_SESSION_METADATA_KEY];
|
|
17311
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
17312
|
-
return null;
|
|
17313
|
-
const cast = raw;
|
|
17314
|
-
if (cast.version !== TERMINAL_PROFILE_VERSION)
|
|
17315
|
-
return null;
|
|
17316
|
-
const viewer = cast.viewer && typeof cast.viewer === "object" && !Array.isArray(cast.viewer) ? cast.viewer : null;
|
|
17317
|
-
const launcher = trimmed4(viewer?.launcher);
|
|
17318
|
-
const source = (value) => trimmed4(value) === "target" ? "target" : "user_default";
|
|
17319
|
-
return {
|
|
17320
|
-
version: TERMINAL_PROFILE_VERSION,
|
|
17321
|
-
executionProvider: normalizeExecutionProvider(cast.executionProvider) ?? {
|
|
17322
|
-
...DEFAULT_EXECUTION_PROVIDER
|
|
17323
|
-
},
|
|
17324
|
-
viewer: {
|
|
17325
|
-
kind: trimmed4(viewer?.kind) ? trimmed4(viewer?.kind) : viewerKindForLauncher(launcher),
|
|
17326
|
-
launcher,
|
|
17327
|
-
openOnLaunch: viewer?.openOnLaunch !== false
|
|
17328
|
-
},
|
|
17329
|
-
executionProviderSource: source(cast.executionProviderSource),
|
|
17330
|
-
viewerOpenSource: source(cast.viewerOpenSource),
|
|
17331
|
-
resolvedAt: trimmed4(cast.resolvedAt) ?? ""
|
|
17332
|
-
};
|
|
17333
|
-
}
|
|
17334
|
-
var TERMINAL_PROFILE_VERSION, DEFAULT_LATCH_EXECUTABLE, DEFAULT_EXECUTION_PROVIDER, DEFAULT_OPEN_VIEWER_ON_LAUNCH, DEFAULT_LAUNCH_SESSION_DEFAULTS, LAUNCH_SESSION_METADATA_KEY;
|
|
17335
|
-
var init_terminal_profile_types2 = __esm({
|
|
17336
|
-
"../packages/core/dist/service/terminal-profile-types.js"() {
|
|
17337
|
-
"use strict";
|
|
17338
|
-
TERMINAL_PROFILE_VERSION = 1;
|
|
17339
|
-
DEFAULT_LATCH_EXECUTABLE = "latch";
|
|
17340
|
-
DEFAULT_EXECUTION_PROVIDER = {
|
|
17341
|
-
kind: "direct",
|
|
17342
|
-
executable: DEFAULT_LATCH_EXECUTABLE
|
|
17343
|
-
};
|
|
17344
|
-
DEFAULT_OPEN_VIEWER_ON_LAUNCH = true;
|
|
17345
|
-
DEFAULT_LAUNCH_SESSION_DEFAULTS = {
|
|
17346
|
-
executionProvider: { ...DEFAULT_EXECUTION_PROVIDER },
|
|
17347
|
-
openViewerOnLaunch: DEFAULT_OPEN_VIEWER_ON_LAUNCH
|
|
17348
|
-
};
|
|
17349
|
-
LAUNCH_SESSION_METADATA_KEY = "launchSession";
|
|
17350
|
-
}
|
|
17351
|
-
});
|
|
17352
|
-
|
|
17353
17417
|
// ../packages/core/dist/service/latch-discovery.js
|
|
17354
17418
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
17355
17419
|
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync15, statSync as statSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
@@ -19186,7 +19250,9 @@ function createLatchSession({
|
|
|
19186
19250
|
function openLatchViewer({
|
|
19187
19251
|
executable = DEFAULT_LATCH_EXECUTABLE,
|
|
19188
19252
|
providerSessionId,
|
|
19189
|
-
viewerKind
|
|
19253
|
+
viewerKind,
|
|
19254
|
+
openAs,
|
|
19255
|
+
productVersion
|
|
19190
19256
|
}) {
|
|
19191
19257
|
const viewer = latchViewerFlagForKind(viewerKind);
|
|
19192
19258
|
const attachCommand = latchAttachCommand({ executable, providerSessionId });
|
|
@@ -19197,9 +19263,10 @@ function openLatchViewer({
|
|
|
19197
19263
|
attachCommand
|
|
19198
19264
|
};
|
|
19199
19265
|
}
|
|
19266
|
+
const sendsOpenAs = Boolean(openAs) && latchSupportsOpenAs(productVersion);
|
|
19200
19267
|
const result = spawnLatchJson({
|
|
19201
19268
|
executable,
|
|
19202
|
-
args:
|
|
19269
|
+
args: buildLatchOpenArgs({ providerSessionId, viewer, openAs, productVersion })
|
|
19203
19270
|
});
|
|
19204
19271
|
if (result.status !== 0) {
|
|
19205
19272
|
const detail = (result.stderr || result.stdout || `exit ${result.status ?? "null"}`).trim();
|
|
@@ -19209,7 +19276,7 @@ function openLatchViewer({
|
|
|
19209
19276
|
attachCommand
|
|
19210
19277
|
};
|
|
19211
19278
|
}
|
|
19212
|
-
return { ok: true, viewer };
|
|
19279
|
+
return { ok: true, viewer, openAs: sendsOpenAs ? parseViewerOpenAs(openAs) : null };
|
|
19213
19280
|
}
|
|
19214
19281
|
var init_latch_launch2 = __esm({
|
|
19215
19282
|
"src/latch-launch.ts"() {
|
|
@@ -19917,6 +19984,7 @@ async function launchAgent({
|
|
|
19917
19984
|
let providerFallbackWarning = null;
|
|
19918
19985
|
let useLatch = false;
|
|
19919
19986
|
let resolvedLatchExecutable = executable;
|
|
19987
|
+
let latchProductVersion = null;
|
|
19920
19988
|
const existingProviderSession = providerKind === "latch" ? existingLatchProviderSession({
|
|
19921
19989
|
latchSessionId: process.env.LATCH_SESSION_ID,
|
|
19922
19990
|
executionTargetId: options.executionTargetId
|
|
@@ -19960,6 +20028,7 @@ async function launchAgent({
|
|
|
19960
20028
|
});
|
|
19961
20029
|
if (useLatch && discovery.state === "found") {
|
|
19962
20030
|
resolvedLatchExecutable = discovery.resolvedPath;
|
|
20031
|
+
latchProductVersion = discovery.productVersion;
|
|
19963
20032
|
}
|
|
19964
20033
|
if (!useLatch) {
|
|
19965
20034
|
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.";
|
|
@@ -19984,7 +20053,9 @@ async function launchAgent({
|
|
|
19984
20053
|
viewerOpen = openLatchViewer({
|
|
19985
20054
|
executable: resolvedLatchExecutable,
|
|
19986
20055
|
providerSessionId: created.providerSession.providerSessionId,
|
|
19987
|
-
viewerKind: snapshot?.viewer.kind ?? "iterm"
|
|
20056
|
+
viewerKind: snapshot?.viewer.kind ?? "iterm",
|
|
20057
|
+
openAs: snapshot?.viewer.openAs ?? null,
|
|
20058
|
+
productVersion: latchProductVersion
|
|
19988
20059
|
});
|
|
19989
20060
|
}
|
|
19990
20061
|
return {
|
|
@@ -21744,7 +21815,15 @@ var init_runner_identity = __esm({
|
|
|
21744
21815
|
|
|
21745
21816
|
// src/runner-service.ts
|
|
21746
21817
|
import { execFile } from "node:child_process";
|
|
21747
|
-
import {
|
|
21818
|
+
import {
|
|
21819
|
+
chmodSync as chmodSync5,
|
|
21820
|
+
existsSync as existsSync26,
|
|
21821
|
+
mkdirSync as mkdirSync14,
|
|
21822
|
+
readFileSync as readFileSync22,
|
|
21823
|
+
rmSync as rmSync6,
|
|
21824
|
+
statSync as statSync7,
|
|
21825
|
+
writeFileSync as writeFileSync13
|
|
21826
|
+
} from "node:fs";
|
|
21748
21827
|
import os5 from "node:os";
|
|
21749
21828
|
import path31 from "node:path";
|
|
21750
21829
|
import { promisify } from "node:util";
|
|
@@ -21752,6 +21831,38 @@ function writeServiceFile(filePath, contents) {
|
|
|
21752
21831
|
writeFileSync13(filePath, contents, { mode: 384 });
|
|
21753
21832
|
chmodSync5(filePath, 384);
|
|
21754
21833
|
}
|
|
21834
|
+
function resolveRunnerEntryScript(argv = process.argv) {
|
|
21835
|
+
return argv[1] ? path31.resolve(argv[1]) : null;
|
|
21836
|
+
}
|
|
21837
|
+
function readRunnerExecutableFileIdentity(filePath, stat = statSync7) {
|
|
21838
|
+
try {
|
|
21839
|
+
const metadata = stat(filePath);
|
|
21840
|
+
return { dev: metadata.dev, ino: metadata.ino, mtimeMs: metadata.mtimeMs };
|
|
21841
|
+
} catch (error) {
|
|
21842
|
+
return error.code === "ENOENT" ? null : void 0;
|
|
21843
|
+
}
|
|
21844
|
+
}
|
|
21845
|
+
function captureRunnerSupervisorIdentity({
|
|
21846
|
+
execPath = process.execPath,
|
|
21847
|
+
entryScript = resolveRunnerEntryScript(),
|
|
21848
|
+
stat = statSync7
|
|
21849
|
+
} = {}) {
|
|
21850
|
+
return {
|
|
21851
|
+
program: readRunnerExecutableFileIdentity(execPath, stat),
|
|
21852
|
+
entryScript: entryScript ? readRunnerExecutableFileIdentity(entryScript, stat) : void 0
|
|
21853
|
+
};
|
|
21854
|
+
}
|
|
21855
|
+
function executableIdentityChanged(initial, current) {
|
|
21856
|
+
if (current === null) return true;
|
|
21857
|
+
if (!initial || !current) return false;
|
|
21858
|
+
return initial.dev !== current.dev || initial.ino !== current.ino || initial.mtimeMs !== current.mtimeMs;
|
|
21859
|
+
}
|
|
21860
|
+
function shouldRestartRunnerSupervisor({
|
|
21861
|
+
initial,
|
|
21862
|
+
current
|
|
21863
|
+
}) {
|
|
21864
|
+
return executableIdentityChanged(initial.program, current.program) || executableIdentityChanged(initial.entryScript, current.entryScript);
|
|
21865
|
+
}
|
|
21755
21866
|
function emptyRunnerServiceState() {
|
|
21756
21867
|
return {
|
|
21757
21868
|
serviceKind: null,
|
|
@@ -21790,41 +21901,10 @@ function patchRunnerServiceState(patch, dataDir = resolveGlobalDataDir()) {
|
|
|
21790
21901
|
writeRunnerServiceState(next, dataDir);
|
|
21791
21902
|
return next;
|
|
21792
21903
|
}
|
|
21793
|
-
function runnerFocusStatePath(dataDir = resolveGlobalDataDir()) {
|
|
21794
|
-
return path31.join(dataDir, RUNNER_FOCUS_STATE_FILENAME);
|
|
21795
|
-
}
|
|
21796
|
-
function readDesktopFocusState(dataDir = resolveGlobalDataDir()) {
|
|
21797
|
-
const filePath = runnerFocusStatePath(dataDir);
|
|
21798
|
-
if (!existsSync26(filePath)) return { lastFocusedAt: null };
|
|
21799
|
-
try {
|
|
21800
|
-
const parsed = JSON.parse(readFileSync22(filePath, "utf8"));
|
|
21801
|
-
return { lastFocusedAt: parsed.lastFocusedAt ?? null };
|
|
21802
|
-
} catch {
|
|
21803
|
-
return { lastFocusedAt: null };
|
|
21804
|
-
}
|
|
21805
|
-
}
|
|
21806
|
-
function withinWindow(timestamp, now, windowMs) {
|
|
21807
|
-
if (!timestamp) return false;
|
|
21808
|
-
const ms = Date.parse(timestamp);
|
|
21809
|
-
if (Number.isNaN(ms)) return false;
|
|
21810
|
-
return now - ms <= windowMs;
|
|
21811
|
-
}
|
|
21812
|
-
function selectBasePollIntervalMs({
|
|
21813
|
-
lastLaunchedAt,
|
|
21814
|
-
lastDesktopFocusAt = null,
|
|
21815
|
-
now
|
|
21816
|
-
}) {
|
|
21817
|
-
const jobActive = withinWindow(lastLaunchedAt, now, IDLE_BACKOFF_MS);
|
|
21818
|
-
const focusActive = withinWindow(lastDesktopFocusAt, now, DESKTOP_FOCUS_WINDOW_MS);
|
|
21819
|
-
return jobActive || focusActive ? FAST_POLL_INTERVAL_MS : SLOW_POLL_INTERVAL_MS;
|
|
21820
|
-
}
|
|
21821
21904
|
function applyPollJitter(intervalMs, random = Math.random) {
|
|
21822
21905
|
const spread = intervalMs * 0.1;
|
|
21823
21906
|
return Math.round(intervalMs + (random() * 2 - 1) * spread);
|
|
21824
21907
|
}
|
|
21825
|
-
function nextRunnerLastError(pollError) {
|
|
21826
|
-
return pollError;
|
|
21827
|
-
}
|
|
21828
21908
|
function resolveOverlordAppInvocation({
|
|
21829
21909
|
platform: platform2 = process.platform,
|
|
21830
21910
|
homedir: homedir2 = os5.homedir(),
|
|
@@ -21860,27 +21940,15 @@ function resolveOvldInvocation(argv = process.argv, execPath = process.execPath)
|
|
|
21860
21940
|
}
|
|
21861
21941
|
return { program: execPath, args: ["runner", "supervise"] };
|
|
21862
21942
|
}
|
|
21863
|
-
function describeServicePublisher({
|
|
21864
|
-
execProgram,
|
|
21865
|
-
platform: platform2 = process.platform
|
|
21866
|
-
}) {
|
|
21867
|
-
if (platform2 !== "darwin" || !execProgram) {
|
|
21868
|
-
return { publisher: "unknown", needsReinstallForOverlord: false };
|
|
21869
|
-
}
|
|
21870
|
-
if (execProgram.includes(".app/Contents/MacOS/")) {
|
|
21871
|
-
return { publisher: "overlord", needsReinstallForOverlord: false };
|
|
21872
|
-
}
|
|
21873
|
-
return { publisher: "node", needsReinstallForOverlord: true };
|
|
21874
|
-
}
|
|
21875
21943
|
function buildRunnerServiceEnv({
|
|
21876
21944
|
backendUrl,
|
|
21877
21945
|
overlordHome,
|
|
21878
21946
|
runAsElectronNode
|
|
21879
21947
|
}) {
|
|
21880
21948
|
const env = {
|
|
21881
|
-
OVERLORD_BACKEND_URL: backendUrl,
|
|
21882
21949
|
PATH: process.env.PATH?.trim() || "/usr/local/bin:/usr/bin:/bin"
|
|
21883
21950
|
};
|
|
21951
|
+
if (!isLoopbackBackendUrl(backendUrl)) env.OVERLORD_BACKEND_URL = backendUrl;
|
|
21884
21952
|
const home = overlordHome?.trim() || process.env.OVLD_HOME?.trim();
|
|
21885
21953
|
if (home) env.OVLD_HOME = path31.resolve(home);
|
|
21886
21954
|
const token = process.env.OVERLORD_USER_TOKEN?.trim() || process.env.OVLD_USER_TOKEN?.trim();
|
|
@@ -21965,31 +22033,72 @@ async function runCommand(program, args) {
|
|
|
21965
22033
|
const { stdout } = await execFileAsync(program, args);
|
|
21966
22034
|
return { stdout: stdout.toString() };
|
|
21967
22035
|
}
|
|
22036
|
+
function launchdDomainTarget(uid) {
|
|
22037
|
+
return `gui/${uid}`;
|
|
22038
|
+
}
|
|
22039
|
+
function launchdServiceTarget(uid) {
|
|
22040
|
+
return `${launchdDomainTarget(uid)}/${LAUNCHD_LABEL}`;
|
|
22041
|
+
}
|
|
22042
|
+
function planLaunchdUnloadCommands(opts) {
|
|
22043
|
+
return [{ args: ["bootout", launchdServiceTarget(opts.uid)], tolerateFailure: true }];
|
|
22044
|
+
}
|
|
22045
|
+
function planLaunchdLoadCommands(opts) {
|
|
22046
|
+
const service = launchdServiceTarget(opts.uid);
|
|
22047
|
+
return [
|
|
22048
|
+
{ args: ["enable", service], tolerateFailure: true },
|
|
22049
|
+
{
|
|
22050
|
+
args: ["bootstrap", launchdDomainTarget(opts.uid), opts.plistPath],
|
|
22051
|
+
tolerateFailure: true
|
|
22052
|
+
},
|
|
22053
|
+
{ args: ["kickstart", service], tolerateFailure: false }
|
|
22054
|
+
];
|
|
22055
|
+
}
|
|
21968
22056
|
function resolveServiceManager(platform2 = process.platform) {
|
|
21969
22057
|
if (platform2 === "darwin") return new LaunchdManager();
|
|
21970
22058
|
if (platform2 === "linux") return new SystemdUserManager();
|
|
21971
22059
|
return null;
|
|
21972
22060
|
}
|
|
21973
|
-
var execFileAsync, RUNNER_SERVICE_STATE_FILENAME,
|
|
22061
|
+
var execFileAsync, RUNNER_SERVICE_STATE_FILENAME, LAUNCHD_LABEL, SYSTEMD_UNIT_NAME, FALLBACK_POLL_INTERVAL_MS, LaunchdManager, SystemdUserManager;
|
|
21974
22062
|
var init_runner_service = __esm({
|
|
21975
22063
|
"src/runner-service.ts"() {
|
|
21976
22064
|
"use strict";
|
|
21977
22065
|
init_config();
|
|
21978
22066
|
execFileAsync = promisify(execFile);
|
|
21979
22067
|
RUNNER_SERVICE_STATE_FILENAME = "runner-service.json";
|
|
21980
|
-
RUNNER_FOCUS_STATE_FILENAME = "runner-focus.json";
|
|
21981
22068
|
LAUNCHD_LABEL = "io.overlord.runner";
|
|
21982
22069
|
SYSTEMD_UNIT_NAME = "overlord-runner";
|
|
21983
|
-
|
|
21984
|
-
SLOW_POLL_INTERVAL_MS = 5e3;
|
|
21985
|
-
IDLE_BACKOFF_MS = 2 * 60 * 60 * 1e3;
|
|
21986
|
-
DESKTOP_FOCUS_WINDOW_MS = 30 * 60 * 1e3;
|
|
22070
|
+
FALLBACK_POLL_INTERVAL_MS = 5e3;
|
|
21987
22071
|
LaunchdManager = class {
|
|
21988
22072
|
kind = "launchd";
|
|
21989
22073
|
identifier = LAUNCHD_LABEL;
|
|
22074
|
+
exec;
|
|
22075
|
+
constructor(exec) {
|
|
22076
|
+
this.exec = exec ?? ((args) => runCommand("launchctl", args));
|
|
22077
|
+
}
|
|
21990
22078
|
unitPath() {
|
|
21991
22079
|
return path31.join(launchAgentsDir(), `${LAUNCHD_LABEL}.plist`);
|
|
21992
22080
|
}
|
|
22081
|
+
uid() {
|
|
22082
|
+
return process.getuid?.() ?? "";
|
|
22083
|
+
}
|
|
22084
|
+
async runSteps(steps) {
|
|
22085
|
+
for (const step of steps) {
|
|
22086
|
+
try {
|
|
22087
|
+
await this.exec(step.args);
|
|
22088
|
+
} catch (error) {
|
|
22089
|
+
if (!step.tolerateFailure) throw error;
|
|
22090
|
+
}
|
|
22091
|
+
}
|
|
22092
|
+
}
|
|
22093
|
+
/** True when launchd still has the label registered, whatever its run state. */
|
|
22094
|
+
async isLoaded() {
|
|
22095
|
+
try {
|
|
22096
|
+
await this.exec(["list", LAUNCHD_LABEL]);
|
|
22097
|
+
return true;
|
|
22098
|
+
} catch {
|
|
22099
|
+
return false;
|
|
22100
|
+
}
|
|
22101
|
+
}
|
|
21993
22102
|
render(opts) {
|
|
21994
22103
|
return renderLaunchdPlist({
|
|
21995
22104
|
label: LAUNCHD_LABEL,
|
|
@@ -22001,41 +22110,33 @@ var init_runner_service = __esm({
|
|
|
22001
22110
|
async install(opts) {
|
|
22002
22111
|
mkdirSync14(launchAgentsDir(), { recursive: true });
|
|
22003
22112
|
mkdirSync14(path31.join(resolveGlobalDataDir(), "logs"), { recursive: true });
|
|
22113
|
+
await this.runSteps(planLaunchdUnloadCommands({ uid: this.uid() }));
|
|
22004
22114
|
writeServiceFile(this.unitPath(), this.render(opts));
|
|
22005
22115
|
if (opts.autoStart) await this.start();
|
|
22006
22116
|
}
|
|
22007
22117
|
async start() {
|
|
22008
|
-
|
|
22009
|
-
await runCommand("launchctl", ["load", "-w", this.unitPath()]);
|
|
22010
|
-
} catch {
|
|
22011
|
-
await runCommand("launchctl", [
|
|
22012
|
-
"kickstart",
|
|
22013
|
-
"-k",
|
|
22014
|
-
`gui/${process.getuid?.() ?? ""}/${LAUNCHD_LABEL}`
|
|
22015
|
-
]);
|
|
22016
|
-
}
|
|
22118
|
+
await this.runSteps(planLaunchdLoadCommands({ uid: this.uid(), plistPath: this.unitPath() }));
|
|
22017
22119
|
}
|
|
22018
22120
|
async stop() {
|
|
22019
|
-
await
|
|
22121
|
+
await this.runSteps(planLaunchdUnloadCommands({ uid: this.uid() }));
|
|
22020
22122
|
}
|
|
22021
22123
|
async restart() {
|
|
22022
|
-
|
|
22023
|
-
await this.stop();
|
|
22024
|
-
} catch {
|
|
22025
|
-
}
|
|
22124
|
+
await this.stop();
|
|
22026
22125
|
await this.start();
|
|
22027
22126
|
}
|
|
22028
22127
|
async uninstall() {
|
|
22029
|
-
|
|
22030
|
-
|
|
22031
|
-
|
|
22128
|
+
await this.runSteps(planLaunchdUnloadCommands({ uid: this.uid() }));
|
|
22129
|
+
if (await this.isLoaded()) {
|
|
22130
|
+
throw new Error(
|
|
22131
|
+
`launchctl still reports ${LAUNCHD_LABEL} as loaded after bootout; left ${this.unitPath()} in place so the service can be repaired with \`ovld runner service restart\`.`
|
|
22132
|
+
);
|
|
22032
22133
|
}
|
|
22033
22134
|
if (existsSync26(this.unitPath())) rmSync6(this.unitPath());
|
|
22034
22135
|
}
|
|
22035
22136
|
async status() {
|
|
22036
22137
|
const installed = existsSync26(this.unitPath());
|
|
22037
22138
|
try {
|
|
22038
|
-
const { stdout } = await
|
|
22139
|
+
const { stdout } = await this.exec(["list"]);
|
|
22039
22140
|
const line = stdout.split("\n").find((row) => row.includes(LAUNCHD_LABEL));
|
|
22040
22141
|
if (!line) return { installed, running: installed ? "stopped" : "unknown" };
|
|
22041
22142
|
const pid = line.trim().split(/\s+/)[0];
|
|
@@ -22212,7 +22313,8 @@ var commands_exports = {};
|
|
|
22212
22313
|
__export(commands_exports, {
|
|
22213
22314
|
resolveProtocolFileInputs: () => resolveProtocolFileInputs,
|
|
22214
22315
|
runManagementCommand: () => runManagementCommand,
|
|
22215
|
-
runProtocolCommand: () => runProtocolCommand
|
|
22316
|
+
runProtocolCommand: () => runProtocolCommand,
|
|
22317
|
+
runRunnerOnce: () => runRunnerOnce
|
|
22216
22318
|
});
|
|
22217
22319
|
import { existsSync as existsSync28, readFileSync as readFileSync24 } from "node:fs";
|
|
22218
22320
|
import os6 from "node:os";
|
|
@@ -23375,6 +23477,165 @@ function isNoExecutionTargetRegisteredError(error) {
|
|
|
23375
23477
|
const message = error instanceof Error ? error.message : String(error);
|
|
23376
23478
|
return message.includes("(no_execution_target_registered)");
|
|
23377
23479
|
}
|
|
23480
|
+
async function runRunnerOnce({
|
|
23481
|
+
runtime,
|
|
23482
|
+
parsed,
|
|
23483
|
+
json
|
|
23484
|
+
}) {
|
|
23485
|
+
let claim;
|
|
23486
|
+
try {
|
|
23487
|
+
claim = await runtime.backend.post({
|
|
23488
|
+
path: "/api/runner/claim",
|
|
23489
|
+
body: {
|
|
23490
|
+
projectId: flagValue(parsed.flags, "--project-id"),
|
|
23491
|
+
...clientDeviceIdentity(),
|
|
23492
|
+
// Contract v40: the claim poll doubles as this runner instance's
|
|
23493
|
+
// heartbeat, so local target liveness reflects a runner that can
|
|
23494
|
+
// actually take work rather than any CLI traffic from the machine.
|
|
23495
|
+
...runnerRegistrationPayload()
|
|
23496
|
+
}
|
|
23497
|
+
});
|
|
23498
|
+
} catch (error) {
|
|
23499
|
+
if (isNoExecutionTargetRegisteredError(error)) {
|
|
23500
|
+
throw new CliError({
|
|
23501
|
+
message: `${error instanceof Error ? error.message : String(error)}
|
|
23502
|
+
The runner will not register a target for you \u2014 declare this machine first, then start it again.`
|
|
23503
|
+
});
|
|
23504
|
+
}
|
|
23505
|
+
throw error;
|
|
23506
|
+
}
|
|
23507
|
+
const request = asRecord5(claim).request;
|
|
23508
|
+
const longPoll = asRecord5(claim).longPoll === true;
|
|
23509
|
+
if (!request) return { launched: false, longPoll };
|
|
23510
|
+
const requestRecord = asRecord5(request);
|
|
23511
|
+
const requestId = String(requestRecord.id);
|
|
23512
|
+
const projectId = String(requestRecord.projectId ?? "");
|
|
23513
|
+
const executionTargetId = typeof requestRecord.executionTargetId === "string" ? requestRecord.executionTargetId.trim() : "";
|
|
23514
|
+
if (projectId && executionTargetId) {
|
|
23515
|
+
try {
|
|
23516
|
+
await reportRunnerResourceObservations({
|
|
23517
|
+
backend: runtime.backend,
|
|
23518
|
+
projectId,
|
|
23519
|
+
executionTargetId
|
|
23520
|
+
});
|
|
23521
|
+
} catch {
|
|
23522
|
+
}
|
|
23523
|
+
}
|
|
23524
|
+
try {
|
|
23525
|
+
await runtime.backend.post({ path: `/api/runner/requests/${requestId}/launching` });
|
|
23526
|
+
const mutation = parseMutationFromMetadata(requestRecord.metadata);
|
|
23527
|
+
if (mutation) {
|
|
23528
|
+
const mutationResult = await executeLocalTargetMutation({ mutation });
|
|
23529
|
+
if (!mutationResult.ok) {
|
|
23530
|
+
await runtime.backend.post({
|
|
23531
|
+
path: `/api/runner/requests/${requestId}/failed`,
|
|
23532
|
+
body: { error: mutationResult.message }
|
|
23533
|
+
});
|
|
23534
|
+
throw new CliError({ message: mutationResult.message });
|
|
23535
|
+
}
|
|
23536
|
+
await runtime.backend.post({
|
|
23537
|
+
path: `/api/runner/requests/${requestId}/completed`,
|
|
23538
|
+
body: { mutationResult }
|
|
23539
|
+
});
|
|
23540
|
+
if (json) printJson({ request, mutationResult });
|
|
23541
|
+
else console.log(`Completed ${mutation.kind} for ${requestRecord.missionId}`);
|
|
23542
|
+
return { launched: true, longPoll };
|
|
23543
|
+
}
|
|
23544
|
+
const requestedAgent = typeof requestRecord.requestedAgent === "string" ? requestRecord.requestedAgent.trim() : "";
|
|
23545
|
+
if (!requestedAgent) {
|
|
23546
|
+
throw new CliError({
|
|
23547
|
+
message: `Execution request ${requestId} has no agent; the objective must specify one before it can be launched.`
|
|
23548
|
+
});
|
|
23549
|
+
}
|
|
23550
|
+
const launchConfig = asRecord5(requestRecord.launchConfig);
|
|
23551
|
+
const terminal = await resolveTerminalLaunchSettings({ runtime, flags: parsed.flags });
|
|
23552
|
+
const missionId = String(requestRecord.missionId);
|
|
23553
|
+
const dryRun = flagBoolean(parsed.flags, "--dry-run");
|
|
23554
|
+
const prepared = await prepareMissionBranch({
|
|
23555
|
+
runtime,
|
|
23556
|
+
options: {
|
|
23557
|
+
missionId,
|
|
23558
|
+
workingDirectory: String(requestRecord.workingDirectory ?? process.cwd()),
|
|
23559
|
+
objectiveId: String(requestRecord.objectiveId ?? ""),
|
|
23560
|
+
workspaceAutomationEnabled: await readWorktreeBranchAutomationEnabled(runtime),
|
|
23561
|
+
dryRun,
|
|
23562
|
+
overrideBranch: flagValue(parsed.flags, "--branch"),
|
|
23563
|
+
noWorktree: flagBoolean(parsed.flags, "--no-worktree")
|
|
23564
|
+
}
|
|
23565
|
+
});
|
|
23566
|
+
await recordBranchPrepared({
|
|
23567
|
+
runtime,
|
|
23568
|
+
missionId,
|
|
23569
|
+
requestId,
|
|
23570
|
+
branchAutomation: prepared.branchAutomation
|
|
23571
|
+
});
|
|
23572
|
+
const launchSession = launchSessionSnapshotFromMetadata(asRecord5(requestRecord.metadata));
|
|
23573
|
+
const result = await launchAgent({
|
|
23574
|
+
runtime,
|
|
23575
|
+
options: {
|
|
23576
|
+
agent: requestedAgent,
|
|
23577
|
+
missionId,
|
|
23578
|
+
workingDirectory: prepared.workingDirectory,
|
|
23579
|
+
model: typeof requestRecord.requestedModel === "string" ? requestRecord.requestedModel : void 0,
|
|
23580
|
+
thinking: typeof requestRecord.requestedReasoningEffort === "string" ? requestRecord.requestedReasoningEffort : void 0,
|
|
23581
|
+
flags: normalizeAgentLaunchFlags(launchConfig.flags),
|
|
23582
|
+
preCommand: typeof launchConfig.preCommand === "string" ? launchConfig.preCommand : void 0,
|
|
23583
|
+
preLaunchCommands: Array.isArray(requestRecord.preLaunchCommands) ? requestRecord.preLaunchCommands.filter(
|
|
23584
|
+
(value) => typeof value === "string"
|
|
23585
|
+
) : void 0,
|
|
23586
|
+
launchEnvVars: parseLaunchEnvVarsValue(requestRecord.launchEnvVars),
|
|
23587
|
+
executionRequestId: requestId,
|
|
23588
|
+
executionTargetId: executionTargetId || void 0,
|
|
23589
|
+
launchSession,
|
|
23590
|
+
...terminal,
|
|
23591
|
+
dryRun
|
|
23592
|
+
}
|
|
23593
|
+
});
|
|
23594
|
+
if (result.providerFallbackWarning) {
|
|
23595
|
+
console.error(`[overlord] ${result.providerFallbackWarning}`);
|
|
23596
|
+
}
|
|
23597
|
+
if (result.viewerOpen && result.viewerOpen.ok === false) {
|
|
23598
|
+
console.error(`[overlord] ${result.viewerOpen.warning}`);
|
|
23599
|
+
}
|
|
23600
|
+
if (result.status && result.status !== 0) {
|
|
23601
|
+
throw new CliError({ message: `Launch command exited with status ${result.status}` });
|
|
23602
|
+
}
|
|
23603
|
+
await runtime.backend.post({
|
|
23604
|
+
path: `/api/runner/requests/${requestId}/launched`,
|
|
23605
|
+
body: result.providerSession ? { providerSession: result.providerSession } : {}
|
|
23606
|
+
});
|
|
23607
|
+
if (result.providerSession && !dryRun) {
|
|
23608
|
+
void postLatchHarnessEventsAfterLaunch({
|
|
23609
|
+
backend: runtime.backend,
|
|
23610
|
+
requestId,
|
|
23611
|
+
providerSessionId: result.providerSession.providerSessionId,
|
|
23612
|
+
executable: launchSession?.executionProvider.kind === "latch" ? launchSession.executionProvider.executable : void 0
|
|
23613
|
+
});
|
|
23614
|
+
}
|
|
23615
|
+
if (json || dryRun) {
|
|
23616
|
+
printJson({
|
|
23617
|
+
request,
|
|
23618
|
+
plan: result.plan,
|
|
23619
|
+
status: result.status,
|
|
23620
|
+
providerSession: result.providerSession ?? null,
|
|
23621
|
+
viewerOpen: result.viewerOpen ?? null,
|
|
23622
|
+
providerFallbackWarning: result.providerFallbackWarning ?? null
|
|
23623
|
+
});
|
|
23624
|
+
} else {
|
|
23625
|
+
console.log(`Launched ${requestedAgent} for ${requestRecord.missionId}`);
|
|
23626
|
+
}
|
|
23627
|
+
return { launched: true, longPoll };
|
|
23628
|
+
} catch (error) {
|
|
23629
|
+
try {
|
|
23630
|
+
await runtime.backend.post({
|
|
23631
|
+
path: `/api/runner/requests/${requestId}/failed`,
|
|
23632
|
+
body: { error: error instanceof Error ? error.message : String(error) }
|
|
23633
|
+
});
|
|
23634
|
+
} catch {
|
|
23635
|
+
}
|
|
23636
|
+
throw error;
|
|
23637
|
+
}
|
|
23638
|
+
}
|
|
23378
23639
|
async function runRunnerCommand({
|
|
23379
23640
|
runtime,
|
|
23380
23641
|
parsed,
|
|
@@ -23408,161 +23669,7 @@ async function runRunnerCommand({
|
|
|
23408
23669
|
message: "Usage: ovld runner once|start|supervise|status|clear <objective_id>|clear-all|service <install|start|stop|restart|status|uninstall>"
|
|
23409
23670
|
});
|
|
23410
23671
|
}
|
|
23411
|
-
const runOnce =
|
|
23412
|
-
let claim;
|
|
23413
|
-
try {
|
|
23414
|
-
claim = await runtime.backend.post({
|
|
23415
|
-
path: "/api/runner/claim",
|
|
23416
|
-
body: {
|
|
23417
|
-
projectId: flagValue(parsed.flags, "--project-id"),
|
|
23418
|
-
...clientDeviceIdentity(),
|
|
23419
|
-
// Contract v40: the claim poll doubles as this runner instance's
|
|
23420
|
-
// heartbeat, so local target liveness reflects a runner that can
|
|
23421
|
-
// actually take work rather than any CLI traffic from the machine.
|
|
23422
|
-
...runnerRegistrationPayload()
|
|
23423
|
-
}
|
|
23424
|
-
});
|
|
23425
|
-
} catch (error) {
|
|
23426
|
-
if (isNoExecutionTargetRegisteredError(error)) {
|
|
23427
|
-
throw new CliError({
|
|
23428
|
-
message: `${error instanceof Error ? error.message : String(error)}
|
|
23429
|
-
The runner will not register a target for you \u2014 declare this machine first, then start it again.`
|
|
23430
|
-
});
|
|
23431
|
-
}
|
|
23432
|
-
throw error;
|
|
23433
|
-
}
|
|
23434
|
-
const request = asRecord5(claim).request;
|
|
23435
|
-
const longPoll = asRecord5(claim).longPoll === true;
|
|
23436
|
-
if (!request) return { launched: false, longPoll };
|
|
23437
|
-
const requestRecord = asRecord5(request);
|
|
23438
|
-
const requestId = String(requestRecord.id);
|
|
23439
|
-
const projectId = String(requestRecord.projectId ?? "");
|
|
23440
|
-
const executionTargetId = typeof requestRecord.executionTargetId === "string" ? requestRecord.executionTargetId.trim() : "";
|
|
23441
|
-
if (projectId && executionTargetId) {
|
|
23442
|
-
try {
|
|
23443
|
-
await reportRunnerResourceObservations({
|
|
23444
|
-
backend: runtime.backend,
|
|
23445
|
-
projectId,
|
|
23446
|
-
executionTargetId
|
|
23447
|
-
});
|
|
23448
|
-
} catch {
|
|
23449
|
-
}
|
|
23450
|
-
}
|
|
23451
|
-
try {
|
|
23452
|
-
await runtime.backend.post({ path: `/api/runner/requests/${requestId}/launching` });
|
|
23453
|
-
const mutation = parseMutationFromMetadata(requestRecord.metadata);
|
|
23454
|
-
if (mutation) {
|
|
23455
|
-
const mutationResult = await executeLocalTargetMutation({ mutation });
|
|
23456
|
-
if (!mutationResult.ok) {
|
|
23457
|
-
await runtime.backend.post({
|
|
23458
|
-
path: `/api/runner/requests/${requestId}/failed`,
|
|
23459
|
-
body: { error: mutationResult.message }
|
|
23460
|
-
});
|
|
23461
|
-
throw new CliError({ message: mutationResult.message });
|
|
23462
|
-
}
|
|
23463
|
-
await runtime.backend.post({
|
|
23464
|
-
path: `/api/runner/requests/${requestId}/completed`,
|
|
23465
|
-
body: { mutationResult }
|
|
23466
|
-
});
|
|
23467
|
-
if (json) printJson({ request, mutationResult });
|
|
23468
|
-
else console.log(`Completed ${mutation.kind} for ${requestRecord.missionId}`);
|
|
23469
|
-
return { launched: true, longPoll };
|
|
23470
|
-
}
|
|
23471
|
-
const requestedAgent = typeof requestRecord.requestedAgent === "string" ? requestRecord.requestedAgent.trim() : "";
|
|
23472
|
-
if (!requestedAgent) {
|
|
23473
|
-
throw new CliError({
|
|
23474
|
-
message: `Execution request ${requestId} has no agent; the objective must specify one before it can be launched.`
|
|
23475
|
-
});
|
|
23476
|
-
}
|
|
23477
|
-
const launchConfig = asRecord5(requestRecord.launchConfig);
|
|
23478
|
-
const terminal = await resolveTerminalLaunchSettings({ runtime, flags: parsed.flags });
|
|
23479
|
-
const missionId = String(requestRecord.missionId);
|
|
23480
|
-
const dryRun = flagBoolean(parsed.flags, "--dry-run");
|
|
23481
|
-
const prepared = await prepareMissionBranch({
|
|
23482
|
-
runtime,
|
|
23483
|
-
options: {
|
|
23484
|
-
missionId,
|
|
23485
|
-
workingDirectory: String(requestRecord.workingDirectory ?? process.cwd()),
|
|
23486
|
-
objectiveId: String(requestRecord.objectiveId ?? ""),
|
|
23487
|
-
workspaceAutomationEnabled: await readWorktreeBranchAutomationEnabled(runtime),
|
|
23488
|
-
dryRun,
|
|
23489
|
-
overrideBranch: flagValue(parsed.flags, "--branch"),
|
|
23490
|
-
noWorktree: flagBoolean(parsed.flags, "--no-worktree")
|
|
23491
|
-
}
|
|
23492
|
-
});
|
|
23493
|
-
await recordBranchPrepared({
|
|
23494
|
-
runtime,
|
|
23495
|
-
missionId,
|
|
23496
|
-
requestId,
|
|
23497
|
-
branchAutomation: prepared.branchAutomation
|
|
23498
|
-
});
|
|
23499
|
-
const launchSession = launchSessionSnapshotFromMetadata(asRecord5(requestRecord.metadata));
|
|
23500
|
-
const result = await launchAgent({
|
|
23501
|
-
runtime,
|
|
23502
|
-
options: {
|
|
23503
|
-
agent: requestedAgent,
|
|
23504
|
-
missionId,
|
|
23505
|
-
workingDirectory: prepared.workingDirectory,
|
|
23506
|
-
model: typeof requestRecord.requestedModel === "string" ? requestRecord.requestedModel : void 0,
|
|
23507
|
-
thinking: typeof requestRecord.requestedReasoningEffort === "string" ? requestRecord.requestedReasoningEffort : void 0,
|
|
23508
|
-
flags: normalizeAgentLaunchFlags(launchConfig.flags),
|
|
23509
|
-
preCommand: typeof launchConfig.preCommand === "string" ? launchConfig.preCommand : void 0,
|
|
23510
|
-
preLaunchCommands: Array.isArray(requestRecord.preLaunchCommands) ? requestRecord.preLaunchCommands.filter(
|
|
23511
|
-
(value) => typeof value === "string"
|
|
23512
|
-
) : void 0,
|
|
23513
|
-
launchEnvVars: parseLaunchEnvVarsValue(requestRecord.launchEnvVars),
|
|
23514
|
-
executionRequestId: requestId,
|
|
23515
|
-
executionTargetId: executionTargetId || void 0,
|
|
23516
|
-
launchSession,
|
|
23517
|
-
...terminal,
|
|
23518
|
-
dryRun
|
|
23519
|
-
}
|
|
23520
|
-
});
|
|
23521
|
-
if (result.providerFallbackWarning) {
|
|
23522
|
-
console.error(`[overlord] ${result.providerFallbackWarning}`);
|
|
23523
|
-
}
|
|
23524
|
-
if (result.viewerOpen && result.viewerOpen.ok === false) {
|
|
23525
|
-
console.error(`[overlord] ${result.viewerOpen.warning}`);
|
|
23526
|
-
}
|
|
23527
|
-
if (result.status && result.status !== 0) {
|
|
23528
|
-
throw new CliError({ message: `Launch command exited with status ${result.status}` });
|
|
23529
|
-
}
|
|
23530
|
-
await runtime.backend.post({
|
|
23531
|
-
path: `/api/runner/requests/${requestId}/launched`,
|
|
23532
|
-
body: result.providerSession ? { providerSession: result.providerSession } : {}
|
|
23533
|
-
});
|
|
23534
|
-
if (result.providerSession && !dryRun) {
|
|
23535
|
-
void postLatchHarnessEventsAfterLaunch({
|
|
23536
|
-
backend: runtime.backend,
|
|
23537
|
-
requestId,
|
|
23538
|
-
providerSessionId: result.providerSession.providerSessionId,
|
|
23539
|
-
executable: launchSession?.executionProvider.kind === "latch" ? launchSession.executionProvider.executable : void 0
|
|
23540
|
-
});
|
|
23541
|
-
}
|
|
23542
|
-
if (json || dryRun) {
|
|
23543
|
-
printJson({
|
|
23544
|
-
request,
|
|
23545
|
-
plan: result.plan,
|
|
23546
|
-
status: result.status,
|
|
23547
|
-
providerSession: result.providerSession ?? null,
|
|
23548
|
-
viewerOpen: result.viewerOpen ?? null,
|
|
23549
|
-
providerFallbackWarning: result.providerFallbackWarning ?? null
|
|
23550
|
-
});
|
|
23551
|
-
} else {
|
|
23552
|
-
console.log(`Launched ${requestedAgent} for ${requestRecord.missionId}`);
|
|
23553
|
-
}
|
|
23554
|
-
return { launched: true, longPoll };
|
|
23555
|
-
} catch (error) {
|
|
23556
|
-
try {
|
|
23557
|
-
await runtime.backend.post({
|
|
23558
|
-
path: `/api/runner/requests/${requestId}/failed`,
|
|
23559
|
-
body: { error: error instanceof Error ? error.message : String(error) }
|
|
23560
|
-
});
|
|
23561
|
-
} catch {
|
|
23562
|
-
}
|
|
23563
|
-
throw error;
|
|
23564
|
-
}
|
|
23565
|
-
};
|
|
23672
|
+
const runOnce = () => runRunnerOnce({ runtime, parsed, json });
|
|
23566
23673
|
if (sub === "once") {
|
|
23567
23674
|
const result = await runOnce();
|
|
23568
23675
|
if (!result.launched) {
|
|
@@ -23586,8 +23693,18 @@ async function runRunnerSupervisor({
|
|
|
23586
23693
|
runOnce,
|
|
23587
23694
|
json
|
|
23588
23695
|
}) {
|
|
23589
|
-
if (!json) console.log("Runner supervisor started.
|
|
23696
|
+
if (!json) console.log("Runner supervisor started. Polling for execution requests.");
|
|
23697
|
+
const initialExecutableIdentity = captureRunnerSupervisorIdentity();
|
|
23590
23698
|
for (; ; ) {
|
|
23699
|
+
if (shouldRestartRunnerSupervisor({
|
|
23700
|
+
initial: initialExecutableIdentity,
|
|
23701
|
+
current: captureRunnerSupervisorIdentity()
|
|
23702
|
+
})) {
|
|
23703
|
+
console.error(
|
|
23704
|
+
"Runner supervisor executable was replaced or removed; exiting cleanly so the service manager restarts the installed build."
|
|
23705
|
+
);
|
|
23706
|
+
process.exit(0);
|
|
23707
|
+
}
|
|
23591
23708
|
const now = /* @__PURE__ */ new Date();
|
|
23592
23709
|
let result = { launched: false, longPoll: false };
|
|
23593
23710
|
let lastError = null;
|
|
@@ -23596,25 +23713,22 @@ async function runRunnerSupervisor({
|
|
|
23596
23713
|
} catch (error) {
|
|
23597
23714
|
if (isNoExecutionTargetRegisteredError(error)) throw error;
|
|
23598
23715
|
lastError = error instanceof Error ? error.message : String(error);
|
|
23716
|
+
console.error(`[overlord] Runner poll failed: ${lastError}`);
|
|
23599
23717
|
}
|
|
23600
23718
|
const state = readRunnerServiceState();
|
|
23601
|
-
const focus = readDesktopFocusState();
|
|
23602
|
-
const base = selectBasePollIntervalMs({
|
|
23603
|
-
lastLaunchedAt: result.launched ? now.toISOString() : state.lastLaunchedAt,
|
|
23604
|
-
lastDesktopFocusAt: focus.lastFocusedAt,
|
|
23605
|
-
now: now.getTime()
|
|
23606
|
-
});
|
|
23607
23719
|
patchRunnerServiceState({
|
|
23608
23720
|
lastHeartbeatAt: now.toISOString(),
|
|
23609
23721
|
lastClaimedAt: result.launched ? now.toISOString() : state.lastClaimedAt,
|
|
23610
23722
|
lastLaunchedAt: result.launched ? now.toISOString() : state.lastLaunchedAt,
|
|
23611
|
-
// Reflect the latest poll's outcome
|
|
23612
|
-
//
|
|
23613
|
-
|
|
23614
|
-
|
|
23723
|
+
// Reflect the latest poll's outcome rather than falling back to the stored
|
|
23724
|
+
// value. A successful poll must clear a resolved failure (for example, an
|
|
23725
|
+
// auth error from before login) instead of leaving the desktop status box
|
|
23726
|
+
// stuck on "Runner error"; persistent failures recur on every poll.
|
|
23727
|
+
lastError,
|
|
23728
|
+
currentPollIntervalMs: FALLBACK_POLL_INTERVAL_MS
|
|
23615
23729
|
});
|
|
23616
23730
|
if (!result.longPoll) {
|
|
23617
|
-
await new Promise((resolve) => setTimeout(resolve, applyPollJitter(
|
|
23731
|
+
await new Promise((resolve) => setTimeout(resolve, applyPollJitter(FALLBACK_POLL_INTERVAL_MS)));
|
|
23618
23732
|
}
|
|
23619
23733
|
}
|
|
23620
23734
|
}
|
|
@@ -23632,10 +23746,8 @@ async function runRunnerServiceCommand({
|
|
|
23632
23746
|
if (action === "status") {
|
|
23633
23747
|
const runState = await manager.status();
|
|
23634
23748
|
const state = readRunnerServiceState();
|
|
23635
|
-
const
|
|
23636
|
-
|
|
23637
|
-
});
|
|
23638
|
-
const reinstallHint = runState.installed && needsReinstallForOverlord ? '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".' : null;
|
|
23749
|
+
const publisher = process.platform !== "darwin" || !state.execProgram ? "unknown" : state.execProgram.includes(".app/Contents/MacOS/") ? "overlord" : "node";
|
|
23750
|
+
const reinstallHint = runState.installed && publisher === "node" ? '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".' : null;
|
|
23639
23751
|
const payload = {
|
|
23640
23752
|
supported: true,
|
|
23641
23753
|
kind: manager.kind,
|