@openscout/scout 0.2.73 → 0.2.75
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/bin/scoutd +0 -0
- package/dist/build-manifest.json +9 -0
- package/dist/client/assets/{RepoDiffViewer-D8gg36W3.js → RepoDiffViewer-CTXJvjIL.js} +1 -1
- package/dist/client/assets/{addon-fit-D4KdY-pj.js → addon-fit-3IrvLm2n.js} +1 -1
- package/dist/client/assets/{addon-webgl-Bo_tmKBp.js → addon-webgl-BgxIDUI-.js} +1 -1
- package/dist/client/assets/{arc.es-D0gujIKy.js → arc.es-Bh8P_xre.js} +1 -1
- package/dist/client/assets/c-BIGW1oBm.js +1 -0
- package/dist/client/assets/cpp-DIPi6g--.js +1 -0
- package/dist/client/assets/css-CLj8gQPS.js +1 -0
- package/dist/client/assets/dart-bE4Kk8sk.js +1 -0
- package/dist/client/assets/docker-BcOcwvcX.js +1 -0
- package/dist/client/assets/{embed-entry-CUVNwyB_.js → embed-entry-wAEtYUEM.js} +1 -1
- package/dist/client/assets/go-C27-OAKa.js +1 -0
- package/dist/client/assets/html-pp8916En.js +1 -0
- package/dist/client/assets/index-BK3mRYyN.js +272 -0
- package/dist/client/assets/index-Dm1ZQS9G.css +1 -0
- package/dist/client/assets/java-CylS5w8V.js +1 -0
- package/dist/client/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/client/assets/json-Cp-IABpG.js +1 -0
- package/dist/client/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/client/assets/kotlin-BdnUsdx6.js +1 -0
- package/dist/client/assets/make-CHLpvVh8.js +1 -0
- package/dist/client/assets/markdown-Cvjx9yec.js +1 -0
- package/dist/client/assets/objective-c-DXmwc3jG.js +1 -0
- package/dist/client/assets/proto-C7zT0LnQ.js +1 -0
- package/dist/client/assets/python-B6aJPvgy.js +1 -0
- package/dist/client/assets/ruby-B13GW9FM.js +1 -0
- package/dist/client/assets/rust-B1yitclQ.js +1 -0
- package/dist/client/assets/scss-D5BDwBP9.js +1 -0
- package/dist/client/assets/shellscript-Yzrsuije.js +1 -0
- package/dist/client/assets/sql-CRqJ_cUM.js +1 -0
- package/dist/client/assets/swift-D82vCrfD.js +1 -0
- package/dist/client/assets/toml-vGWfd6FD.js +1 -0
- package/dist/client/assets/tsx-COt5Ahok.js +1 -0
- package/dist/client/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/client/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/client/assets/xml-sdJ4AIDG.js +1 -0
- package/dist/client/assets/{xterm-RfflDFod.js → xterm-CoGJTxj9.js} +1 -1
- package/dist/client/assets/yaml-Buea-lGh.js +1 -0
- package/dist/client/index.html +2 -2
- package/dist/main.mjs +887 -584
- package/dist/node/main.mjs +115 -1
- package/dist/pairing-runtime-controller.mjs +2525 -895
- package/dist/runtime/base-daemon.mjs +77 -20
- package/dist/runtime/broker-daemon.mjs +1403 -705
- package/dist/runtime/broker-process-manager.mjs +29 -0
- package/dist/runtime/mesh-discover.mjs +29 -0
- package/dist/scout-control-plane-web.mjs +2970 -1116
- package/dist/scout-web-server.mjs +2970 -1116
- package/package.json +1 -1
- package/dist/client/assets/index-CRkjiso5.js +0 -257
- package/dist/client/assets/index-D_RX2cRb.css +0 -1
|
@@ -16,12 +16,12 @@ var __export = (target, all) => {
|
|
|
16
16
|
var __require = import.meta.require;
|
|
17
17
|
|
|
18
18
|
// packages/runtime/src/broker-daemon.ts
|
|
19
|
-
import { createHash as
|
|
19
|
+
import { createHash as createHash5, randomUUID as randomUUID5 } from "crypto";
|
|
20
20
|
import { createServer } from "http";
|
|
21
21
|
import { mkdir as mkdir11, readFile as readFile12, rename, stat as stat7, unlink as unlink2, writeFile as writeFile10 } from "fs/promises";
|
|
22
22
|
import { createRequire as createRequire2 } from "module";
|
|
23
23
|
import { hostname as hostname4 } from "os";
|
|
24
|
-
import { basename as
|
|
24
|
+
import { basename as basename23, dirname as dirname26, join as join42, resolve as resolve20 } from "path";
|
|
25
25
|
|
|
26
26
|
// node_modules/.bun/@trpc+server@11.16.0+1fb4c65d43e298b9/node_modules/@trpc/server/dist/codes-DagpWZLc.mjs
|
|
27
27
|
function mergeWithoutOverrides(obj1, ...objs) {
|
|
@@ -17392,6 +17392,7 @@ var DEFAULT_HOT_DISCOVERY_LIMIT = 64;
|
|
|
17392
17392
|
var DEFAULT_SHALLOW_DISCOVERY_LIMIT = 160;
|
|
17393
17393
|
var DEFAULT_DEEP_DISCOVERY_LIMIT = 160;
|
|
17394
17394
|
var HEAD_READ_BYTES = 256 * 1024;
|
|
17395
|
+
var TAIL_READ_BYTES = 512 * 1024;
|
|
17395
17396
|
var METADATA_CACHE_LIMIT = 512;
|
|
17396
17397
|
var metadataCache = new Map;
|
|
17397
17398
|
function rememberMetadata(file2, metadata) {
|
|
@@ -17452,6 +17453,27 @@ function readFileHead(filePath) {
|
|
|
17452
17453
|
}
|
|
17453
17454
|
}
|
|
17454
17455
|
}
|
|
17456
|
+
function readFileTail(file2) {
|
|
17457
|
+
let fd = null;
|
|
17458
|
+
try {
|
|
17459
|
+
fd = openSync(file2.path, "r");
|
|
17460
|
+
const start = Math.max(0, file2.size - TAIL_READ_BYTES);
|
|
17461
|
+
const buffer = new Uint8Array(Math.min(file2.size, TAIL_READ_BYTES));
|
|
17462
|
+
const bytesRead = readSync(fd, buffer, 0, buffer.length, start);
|
|
17463
|
+
return {
|
|
17464
|
+
content: Buffer.from(buffer.subarray(0, bytesRead)).toString("utf8"),
|
|
17465
|
+
startsAtBeginning: start === 0
|
|
17466
|
+
};
|
|
17467
|
+
} catch {
|
|
17468
|
+
return { content: "", startsAtBeginning: false };
|
|
17469
|
+
} finally {
|
|
17470
|
+
if (fd != null) {
|
|
17471
|
+
try {
|
|
17472
|
+
closeSync(fd);
|
|
17473
|
+
} catch {}
|
|
17474
|
+
}
|
|
17475
|
+
}
|
|
17476
|
+
}
|
|
17455
17477
|
function parseJsonRecord(line) {
|
|
17456
17478
|
try {
|
|
17457
17479
|
const value = JSON.parse(line);
|
|
@@ -17463,7 +17485,11 @@ function parseJsonRecord(line) {
|
|
|
17463
17485
|
function readClaudeMetadata(file2) {
|
|
17464
17486
|
const cached2 = metadataCache.get(file2.path);
|
|
17465
17487
|
if (cached2 && cached2.mtimeMs === file2.mtimeMs && cached2.size === file2.size) {
|
|
17466
|
-
return {
|
|
17488
|
+
return {
|
|
17489
|
+
cwd: cached2.cwd,
|
|
17490
|
+
sessionId: cached2.sessionId,
|
|
17491
|
+
lastEventAt: cached2.lastEventAt
|
|
17492
|
+
};
|
|
17467
17493
|
}
|
|
17468
17494
|
const head = readFileHead(file2.path);
|
|
17469
17495
|
let cwd = null;
|
|
@@ -17474,11 +17500,23 @@ function readClaudeMetadata(file2) {
|
|
|
17474
17500
|
continue;
|
|
17475
17501
|
cwd ??= typeof record2.cwd === "string" && record2.cwd.trim() ? record2.cwd : null;
|
|
17476
17502
|
sessionId ??= typeof record2.sessionId === "string" && record2.sessionId.trim() ? record2.sessionId : typeof record2.session_id === "string" && record2.session_id.trim() ? record2.session_id : null;
|
|
17477
|
-
if (cwd && sessionId)
|
|
17478
|
-
|
|
17479
|
-
}
|
|
17503
|
+
if (cwd && sessionId)
|
|
17504
|
+
break;
|
|
17480
17505
|
}
|
|
17481
|
-
|
|
17506
|
+
const tail = readFileTail(file2);
|
|
17507
|
+
const tailLines = tail.content.split(/\r?\n/);
|
|
17508
|
+
if (!tail.startsAtBeginning)
|
|
17509
|
+
tailLines.shift();
|
|
17510
|
+
let lastEventAt = null;
|
|
17511
|
+
for (let index = tailLines.length - 1;index >= 0; index -= 1) {
|
|
17512
|
+
const record2 = parseJsonRecord(tailLines[index]?.trim() ?? "");
|
|
17513
|
+
if (!record2)
|
|
17514
|
+
continue;
|
|
17515
|
+
lastEventAt = pickTimestamp(record2);
|
|
17516
|
+
if (lastEventAt != null)
|
|
17517
|
+
break;
|
|
17518
|
+
}
|
|
17519
|
+
return rememberMetadata(file2, { cwd, sessionId, lastEventAt });
|
|
17482
17520
|
}
|
|
17483
17521
|
function decodeProjectDir(dirName) {
|
|
17484
17522
|
if (!dirName.startsWith("-"))
|
|
@@ -17705,6 +17743,7 @@ var ClaudeSource = {
|
|
|
17705
17743
|
cwd,
|
|
17706
17744
|
project: cwd ? basename(cwd) : projectDirNameForPath(file2.path) ?? "(unknown)",
|
|
17707
17745
|
harness: "unattributed",
|
|
17746
|
+
lastEventAt: meta3.lastEventAt,
|
|
17708
17747
|
mtimeMs: file2.mtimeMs,
|
|
17709
17748
|
size: file2.size
|
|
17710
17749
|
};
|
|
@@ -18818,20 +18857,32 @@ var GrokSource = {
|
|
|
18818
18857
|
}
|
|
18819
18858
|
};
|
|
18820
18859
|
|
|
18821
|
-
// packages/runtime/src/tail/
|
|
18822
|
-
import {
|
|
18860
|
+
// packages/runtime/src/tail/kimi-source.ts
|
|
18861
|
+
import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync2, statSync as statSync5 } from "fs";
|
|
18823
18862
|
import { homedir as homedir6 } from "os";
|
|
18824
|
-
import { basename as basename5, join as join6
|
|
18825
|
-
var SOURCE_NAME5 = "
|
|
18863
|
+
import { basename as basename5, dirname as dirname2, join as join6 } from "path";
|
|
18864
|
+
var SOURCE_NAME5 = "kimi";
|
|
18826
18865
|
var MAX_SUMMARY_LEN5 = 200;
|
|
18827
18866
|
var DEFAULT_HOT_DISCOVERY_WINDOW_MS5 = 10 * 60 * 1000;
|
|
18828
18867
|
var DEFAULT_SHALLOW_DISCOVERY_WINDOW_MS5 = 24 * 60 * 60 * 1000;
|
|
18829
18868
|
var DEFAULT_DEEP_DISCOVERY_WINDOW_MS5 = 24 * 60 * 60 * 1000;
|
|
18830
|
-
var DEFAULT_HOT_DISCOVERY_LIMIT5 =
|
|
18831
|
-
var DEFAULT_SHALLOW_DISCOVERY_LIMIT5 =
|
|
18832
|
-
var DEFAULT_DEEP_DISCOVERY_LIMIT5 =
|
|
18833
|
-
var
|
|
18834
|
-
var
|
|
18869
|
+
var DEFAULT_HOT_DISCOVERY_LIMIT5 = 96;
|
|
18870
|
+
var DEFAULT_SHALLOW_DISCOVERY_LIMIT5 = 256;
|
|
18871
|
+
var DEFAULT_DEEP_DISCOVERY_LIMIT5 = 256;
|
|
18872
|
+
var METADATA_CACHE_LIMIT4 = 512;
|
|
18873
|
+
var TOOL_CALL_STATE_KEY2 = "kimiToolCallSummaries";
|
|
18874
|
+
var TOOL_CALL_STATE_LIMIT2 = 512;
|
|
18875
|
+
var metadataCache4 = new Map;
|
|
18876
|
+
function recordValue(value) {
|
|
18877
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
18878
|
+
}
|
|
18879
|
+
function parseJsonRecord5(line) {
|
|
18880
|
+
try {
|
|
18881
|
+
return recordValue(JSON.parse(line));
|
|
18882
|
+
} catch {
|
|
18883
|
+
return null;
|
|
18884
|
+
}
|
|
18885
|
+
}
|
|
18835
18886
|
function readPositiveIntEnv5(names, fallback) {
|
|
18836
18887
|
for (const name of names) {
|
|
18837
18888
|
const raw = Number.parseInt(process.env[name] ?? "", 10);
|
|
@@ -18842,22 +18893,336 @@ function readPositiveIntEnv5(names, fallback) {
|
|
|
18842
18893
|
}
|
|
18843
18894
|
function discoveryWindowMs5(scope) {
|
|
18844
18895
|
const fallback = scope === "hot" ? DEFAULT_HOT_DISCOVERY_WINDOW_MS5 : scope === "deep" ? DEFAULT_DEEP_DISCOVERY_WINDOW_MS5 : DEFAULT_SHALLOW_DISCOVERY_WINDOW_MS5;
|
|
18845
|
-
|
|
18846
|
-
|
|
18896
|
+
return readPositiveIntEnv5([
|
|
18897
|
+
`OPENSCOUT_TAIL_${scope.toUpperCase()}_DISCOVERY_WINDOW_MS`,
|
|
18898
|
+
"OPENSCOUT_TAIL_DISCOVERY_WINDOW_MS"
|
|
18899
|
+
], fallback);
|
|
18847
18900
|
}
|
|
18848
18901
|
function discoveryLimit5(scope) {
|
|
18849
18902
|
const fallback = scope === "hot" ? DEFAULT_HOT_DISCOVERY_LIMIT5 : scope === "deep" ? DEFAULT_DEEP_DISCOVERY_LIMIT5 : DEFAULT_SHALLOW_DISCOVERY_LIMIT5;
|
|
18903
|
+
return readPositiveIntEnv5([
|
|
18904
|
+
`OPENSCOUT_TAIL_${scope.toUpperCase()}_DISCOVERY_LIMIT`,
|
|
18905
|
+
"OPENSCOUT_TAIL_DISCOVERY_LIMIT"
|
|
18906
|
+
], fallback);
|
|
18907
|
+
}
|
|
18908
|
+
function kimiSessionsRoot() {
|
|
18909
|
+
const explicit = process.env.OPENSCOUT_TAIL_KIMI_SESSIONS_ROOT?.trim();
|
|
18910
|
+
if (explicit)
|
|
18911
|
+
return explicit;
|
|
18912
|
+
const kimiHome = process.env.KIMI_CODE_HOME?.trim() || join6(homedir6(), ".kimi-code");
|
|
18913
|
+
return join6(kimiHome, "sessions");
|
|
18914
|
+
}
|
|
18915
|
+
function isKimiProcess(command) {
|
|
18916
|
+
const base = commandBasename2(command);
|
|
18917
|
+
return base === "kimi" || command.includes("/.kimi-code/bin/kimi");
|
|
18918
|
+
}
|
|
18919
|
+
async function discoverKimiProcesses() {
|
|
18920
|
+
const all = await listProcesses();
|
|
18921
|
+
const byPid = new Map;
|
|
18922
|
+
for (const proc of all)
|
|
18923
|
+
byPid.set(proc.pid, proc);
|
|
18924
|
+
const out = [];
|
|
18925
|
+
await Promise.all(all.filter((proc) => isKimiProcess(proc.command)).map(async (proc) => {
|
|
18926
|
+
const cwd = await readCwd(proc.pid);
|
|
18927
|
+
const parentChain = buildParentChain(proc.pid, byPid);
|
|
18928
|
+
out.push({
|
|
18929
|
+
pid: proc.pid,
|
|
18930
|
+
ppid: proc.ppid,
|
|
18931
|
+
command: proc.command,
|
|
18932
|
+
etime: proc.etime,
|
|
18933
|
+
cwd,
|
|
18934
|
+
harness: classifyAttribution(parentChain),
|
|
18935
|
+
parentChain,
|
|
18936
|
+
source: SOURCE_NAME5
|
|
18937
|
+
});
|
|
18938
|
+
}));
|
|
18939
|
+
out.sort((left, right) => left.pid - right.pid);
|
|
18940
|
+
return out;
|
|
18941
|
+
}
|
|
18942
|
+
function walkRecentKimiWireFiles(root, scope) {
|
|
18943
|
+
if (!existsSync6(root))
|
|
18944
|
+
return [];
|
|
18945
|
+
const cutoff = Date.now() - discoveryWindowMs5(scope);
|
|
18946
|
+
const found = [];
|
|
18947
|
+
const stack = [root];
|
|
18948
|
+
while (stack.length > 0) {
|
|
18949
|
+
const directory = stack.pop();
|
|
18950
|
+
let entries = [];
|
|
18951
|
+
try {
|
|
18952
|
+
entries = readdirSync5(directory);
|
|
18953
|
+
} catch {
|
|
18954
|
+
continue;
|
|
18955
|
+
}
|
|
18956
|
+
for (const entry of entries) {
|
|
18957
|
+
const path = join6(directory, entry);
|
|
18958
|
+
let stats;
|
|
18959
|
+
try {
|
|
18960
|
+
stats = statSync5(path);
|
|
18961
|
+
} catch {
|
|
18962
|
+
continue;
|
|
18963
|
+
}
|
|
18964
|
+
if (stats.isDirectory()) {
|
|
18965
|
+
stack.push(path);
|
|
18966
|
+
} else if (entry === "wire.jsonl" && stats.mtimeMs >= cutoff) {
|
|
18967
|
+
found.push({ path, mtimeMs: stats.mtimeMs, size: stats.size });
|
|
18968
|
+
}
|
|
18969
|
+
}
|
|
18970
|
+
}
|
|
18971
|
+
return found.sort((left, right) => right.mtimeMs - left.mtimeMs).slice(0, discoveryLimit5(scope));
|
|
18972
|
+
}
|
|
18973
|
+
function readKimiTranscriptMetadata(file2) {
|
|
18974
|
+
const cached2 = metadataCache4.get(file2.path);
|
|
18975
|
+
if (cached2 && cached2.mtimeMs === file2.mtimeMs && cached2.size === file2.size) {
|
|
18976
|
+
return cached2;
|
|
18977
|
+
}
|
|
18978
|
+
const agentId = basename5(dirname2(file2.path));
|
|
18979
|
+
const sessionDirectory = dirname2(dirname2(dirname2(file2.path)));
|
|
18980
|
+
const parentSessionId = basename5(sessionDirectory);
|
|
18981
|
+
let cwd = null;
|
|
18982
|
+
let title = null;
|
|
18983
|
+
try {
|
|
18984
|
+
const state = recordValue(JSON.parse(readFileSync2(join6(sessionDirectory, "state.json"), "utf8")));
|
|
18985
|
+
cwd = typeof state?.workDir === "string" && state.workDir.trim() ? state.workDir.trim() : null;
|
|
18986
|
+
title = typeof state?.title === "string" && state.title.trim() ? state.title.trim() : null;
|
|
18987
|
+
} catch {}
|
|
18988
|
+
const metadata = {
|
|
18989
|
+
cwd,
|
|
18990
|
+
parentSessionId,
|
|
18991
|
+
agentId,
|
|
18992
|
+
sessionId: agentId === "main" ? parentSessionId : `${parentSessionId}:${agentId}`,
|
|
18993
|
+
title
|
|
18994
|
+
};
|
|
18995
|
+
metadataCache4.delete(file2.path);
|
|
18996
|
+
metadataCache4.set(file2.path, { ...file2, ...metadata });
|
|
18997
|
+
while (metadataCache4.size > METADATA_CACHE_LIMIT4) {
|
|
18998
|
+
const oldest = metadataCache4.keys().next().value;
|
|
18999
|
+
if (!oldest)
|
|
19000
|
+
break;
|
|
19001
|
+
metadataCache4.delete(oldest);
|
|
19002
|
+
}
|
|
19003
|
+
return metadata;
|
|
19004
|
+
}
|
|
19005
|
+
function discoverKimiTranscripts(scope) {
|
|
19006
|
+
return walkRecentKimiWireFiles(kimiSessionsRoot(), scope).map((file2) => {
|
|
19007
|
+
const metadata = readKimiTranscriptMetadata(file2);
|
|
19008
|
+
return {
|
|
19009
|
+
source: SOURCE_NAME5,
|
|
19010
|
+
transcriptPath: file2.path,
|
|
19011
|
+
sessionId: metadata.sessionId,
|
|
19012
|
+
cwd: metadata.cwd,
|
|
19013
|
+
project: metadata.cwd ? basename5(metadata.cwd) : "(unknown)",
|
|
19014
|
+
harness: "unattributed",
|
|
19015
|
+
mtimeMs: file2.mtimeMs,
|
|
19016
|
+
size: file2.size
|
|
19017
|
+
};
|
|
19018
|
+
});
|
|
19019
|
+
}
|
|
19020
|
+
function clip5(text, max = MAX_SUMMARY_LEN5) {
|
|
19021
|
+
const flat = text.replace(/\s+/gu, " ").trim();
|
|
19022
|
+
return flat.length <= max ? flat : `${flat.slice(0, max - 1)}\u2026`;
|
|
19023
|
+
}
|
|
19024
|
+
function parseTimestamp3(value) {
|
|
19025
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
19026
|
+
return value < 1000000000000 ? value * 1000 : value;
|
|
19027
|
+
}
|
|
19028
|
+
if (typeof value === "string" && value.trim()) {
|
|
19029
|
+
const parsed = Date.parse(value);
|
|
19030
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
19031
|
+
}
|
|
19032
|
+
return null;
|
|
19033
|
+
}
|
|
19034
|
+
function contentText(content) {
|
|
19035
|
+
if (typeof content === "string")
|
|
19036
|
+
return content.trim();
|
|
19037
|
+
if (!Array.isArray(content))
|
|
19038
|
+
return "";
|
|
19039
|
+
const parts = [];
|
|
19040
|
+
for (const item of content) {
|
|
19041
|
+
const part = recordValue(item);
|
|
19042
|
+
if (!part)
|
|
19043
|
+
continue;
|
|
19044
|
+
if (part.type === "text" && typeof part.text === "string")
|
|
19045
|
+
parts.push(part.text);
|
|
19046
|
+
else if (part.type === "image")
|
|
19047
|
+
parts.push("[image]");
|
|
19048
|
+
else if (part.type === "resource" || part.type === "resource_link")
|
|
19049
|
+
parts.push("[resource]");
|
|
19050
|
+
}
|
|
19051
|
+
return parts.join(" ").trim();
|
|
19052
|
+
}
|
|
19053
|
+
function toolCalls(ctx) {
|
|
19054
|
+
if (!ctx.state)
|
|
19055
|
+
return null;
|
|
19056
|
+
const existing = ctx.state[TOOL_CALL_STATE_KEY2];
|
|
19057
|
+
if (existing instanceof Map)
|
|
19058
|
+
return existing;
|
|
19059
|
+
const next = new Map;
|
|
19060
|
+
ctx.state[TOOL_CALL_STATE_KEY2] = next;
|
|
19061
|
+
return next;
|
|
19062
|
+
}
|
|
19063
|
+
function rememberToolCall2(ctx, id, summary) {
|
|
19064
|
+
if (!id)
|
|
19065
|
+
return;
|
|
19066
|
+
const calls = toolCalls(ctx);
|
|
19067
|
+
if (!calls)
|
|
19068
|
+
return;
|
|
19069
|
+
calls.delete(id);
|
|
19070
|
+
calls.set(id, summary);
|
|
19071
|
+
while (calls.size > TOOL_CALL_STATE_LIMIT2) {
|
|
19072
|
+
const oldest = calls.keys().next().value;
|
|
19073
|
+
if (!oldest)
|
|
19074
|
+
break;
|
|
19075
|
+
calls.delete(oldest);
|
|
19076
|
+
}
|
|
19077
|
+
}
|
|
19078
|
+
function eventIdentity(record2, lineOffset) {
|
|
19079
|
+
const event = recordValue(record2.event);
|
|
19080
|
+
const stable = [
|
|
19081
|
+
event?.uuid,
|
|
19082
|
+
event?.toolCallId,
|
|
19083
|
+
record2.toolCallId,
|
|
19084
|
+
record2.id
|
|
19085
|
+
].find((value) => typeof value === "string" && value.trim());
|
|
19086
|
+
const type = typeof record2.type === "string" ? record2.type : "event";
|
|
19087
|
+
return `${type}:${typeof stable === "string" ? stable : `${String(record2.time ?? "na")}:${lineOffset}`}`;
|
|
19088
|
+
}
|
|
19089
|
+
function summarizeKimiRecord(record2, ctx) {
|
|
19090
|
+
const type = typeof record2.type === "string" ? record2.type : "";
|
|
19091
|
+
if (type === "turn.prompt") {
|
|
19092
|
+
return { kind: "user", summary: clip5(contentText(record2.input) || "[user]") };
|
|
19093
|
+
}
|
|
19094
|
+
if (type === "turn.steer") {
|
|
19095
|
+
const origin = recordValue(record2.origin);
|
|
19096
|
+
const status = typeof origin?.status === "string" ? origin.status : "update";
|
|
19097
|
+
return { kind: "system", summary: clip5(`background task ${status} \xB7 ${contentText(record2.input)}`) };
|
|
19098
|
+
}
|
|
19099
|
+
if (type === "turn.cancel") {
|
|
19100
|
+
return { kind: "system", summary: "turn cancelled" };
|
|
19101
|
+
}
|
|
19102
|
+
if (type === "permission.record_approval_result") {
|
|
19103
|
+
const result = recordValue(record2.result);
|
|
19104
|
+
const decision = typeof result?.decision === "string" ? result.decision : "recorded";
|
|
19105
|
+
const toolName = typeof record2.toolName === "string" ? record2.toolName : "tool";
|
|
19106
|
+
return { kind: "system", summary: clip5(`permission ${decision} \xB7 ${toolName}`) };
|
|
19107
|
+
}
|
|
19108
|
+
if (type === "plan_mode.enter" || type === "plan_mode.exit") {
|
|
19109
|
+
return { kind: "system", summary: type === "plan_mode.enter" ? "plan mode entered" : "plan mode exited" };
|
|
19110
|
+
}
|
|
19111
|
+
if (type === "full_compaction.begin" || type === "full_compaction.complete") {
|
|
19112
|
+
return { kind: "system", summary: type.endsWith("begin") ? "context compaction started" : "context compaction completed" };
|
|
19113
|
+
}
|
|
19114
|
+
if (type === "context.apply_compaction") {
|
|
19115
|
+
const summary = typeof record2.summary === "string" ? record2.summary : "";
|
|
19116
|
+
return { kind: "system", summary: clip5(`context compacted${summary ? ` \xB7 ${summary}` : ""}`) };
|
|
19117
|
+
}
|
|
19118
|
+
if (type !== "context.append_loop_event")
|
|
19119
|
+
return null;
|
|
19120
|
+
const event = recordValue(record2.event);
|
|
19121
|
+
const eventType = typeof event?.type === "string" ? event.type : "";
|
|
19122
|
+
if (eventType === "content.part") {
|
|
19123
|
+
const part = recordValue(event?.part);
|
|
19124
|
+
if (part?.type === "text" && typeof part.text === "string") {
|
|
19125
|
+
return { kind: "assistant", summary: clip5(part.text || "[assistant]") };
|
|
19126
|
+
}
|
|
19127
|
+
if (part?.type === "think" && typeof part.think === "string") {
|
|
19128
|
+
return { kind: "system", summary: clip5(`[thinking] ${part.think}`) };
|
|
19129
|
+
}
|
|
19130
|
+
return null;
|
|
19131
|
+
}
|
|
19132
|
+
if (eventType === "tool.call") {
|
|
19133
|
+
const name = typeof event?.name === "string" ? event.name : "tool";
|
|
19134
|
+
const summary = clip5(formatToolCall(name, event?.args));
|
|
19135
|
+
const callId = typeof event?.toolCallId === "string" ? event.toolCallId : "";
|
|
19136
|
+
rememberToolCall2(ctx, callId, summary);
|
|
19137
|
+
return { kind: "tool", summary };
|
|
19138
|
+
}
|
|
19139
|
+
if (eventType === "tool.result") {
|
|
19140
|
+
const callId = typeof event?.toolCallId === "string" ? event.toolCallId : "";
|
|
19141
|
+
return {
|
|
19142
|
+
kind: "tool-result",
|
|
19143
|
+
summary: clip5(formatToolResult(event?.result, toolCalls(ctx)?.get(callId)))
|
|
19144
|
+
};
|
|
19145
|
+
}
|
|
19146
|
+
return null;
|
|
19147
|
+
}
|
|
19148
|
+
function parseKimiLine(line, ctx) {
|
|
19149
|
+
const record2 = parseJsonRecord5(line.trim());
|
|
19150
|
+
if (!record2)
|
|
19151
|
+
return null;
|
|
19152
|
+
const parsed = summarizeKimiRecord(record2, ctx);
|
|
19153
|
+
if (!parsed)
|
|
19154
|
+
return null;
|
|
19155
|
+
const sessionId = ctx.transcript.sessionId ?? basename5(dirname2(dirname2(dirname2(ctx.transcriptPath))));
|
|
19156
|
+
const cwd = ctx.transcript.cwd ?? ctx.process.cwd ?? "";
|
|
19157
|
+
const nestedEvent = recordValue(record2.event);
|
|
19158
|
+
return {
|
|
19159
|
+
id: `${SOURCE_NAME5}:${sessionId}:${eventIdentity(record2, ctx.lineOffset)}`,
|
|
19160
|
+
ts: parseTimestamp3(record2.time) ?? parseTimestamp3(nestedEvent?.time) ?? parseTimestamp3(record2.created_at) ?? Date.now(),
|
|
19161
|
+
source: SOURCE_NAME5,
|
|
19162
|
+
sessionId,
|
|
19163
|
+
pid: ctx.process.pid,
|
|
19164
|
+
parentPid: ctx.process.ppid || null,
|
|
19165
|
+
project: cwd ? basename5(cwd) : ctx.transcript.project,
|
|
19166
|
+
cwd,
|
|
19167
|
+
harness: ctx.process.harness,
|
|
19168
|
+
kind: parsed.kind,
|
|
19169
|
+
summary: parsed.summary,
|
|
19170
|
+
raw: record2
|
|
19171
|
+
};
|
|
19172
|
+
}
|
|
19173
|
+
var KimiSource = {
|
|
19174
|
+
name: SOURCE_NAME5,
|
|
19175
|
+
discoverProcesses() {
|
|
19176
|
+
return discoverKimiProcesses();
|
|
19177
|
+
},
|
|
19178
|
+
discoverTranscripts(_processes, scope = "shallow") {
|
|
19179
|
+
return discoverKimiTranscripts(scope);
|
|
19180
|
+
},
|
|
19181
|
+
parseLine(line, ctx) {
|
|
19182
|
+
return parseKimiLine(line, ctx);
|
|
19183
|
+
}
|
|
19184
|
+
};
|
|
19185
|
+
|
|
19186
|
+
// packages/runtime/src/tail/opencode-source.ts
|
|
19187
|
+
import { closeSync as closeSync5, existsSync as existsSync7, openSync as openSync5, readdirSync as readdirSync6, readFileSync as readFileSync3, readSync as readSync5, statSync as statSync6 } from "fs";
|
|
19188
|
+
import { homedir as homedir7 } from "os";
|
|
19189
|
+
import { basename as basename6, join as join7, sep } from "path";
|
|
19190
|
+
var SOURCE_NAME6 = "opencode";
|
|
19191
|
+
var MAX_SUMMARY_LEN6 = 200;
|
|
19192
|
+
var DEFAULT_HOT_DISCOVERY_WINDOW_MS6 = 10 * 60 * 1000;
|
|
19193
|
+
var DEFAULT_SHALLOW_DISCOVERY_WINDOW_MS6 = 24 * 60 * 60 * 1000;
|
|
19194
|
+
var DEFAULT_DEEP_DISCOVERY_WINDOW_MS6 = 24 * 60 * 60 * 1000;
|
|
19195
|
+
var DEFAULT_HOT_DISCOVERY_LIMIT6 = 32;
|
|
19196
|
+
var DEFAULT_SHALLOW_DISCOVERY_LIMIT6 = 80;
|
|
19197
|
+
var DEFAULT_DEEP_DISCOVERY_LIMIT6 = 80;
|
|
19198
|
+
var DEFAULT_MESSAGES_PER_SESSION = 50;
|
|
19199
|
+
var HEAD_READ_BYTES5 = 128 * 1024;
|
|
19200
|
+
function readPositiveIntEnv6(names, fallback) {
|
|
19201
|
+
for (const name of names) {
|
|
19202
|
+
const raw = Number.parseInt(process.env[name] ?? "", 10);
|
|
19203
|
+
if (Number.isFinite(raw) && raw > 0)
|
|
19204
|
+
return raw;
|
|
19205
|
+
}
|
|
19206
|
+
return fallback;
|
|
19207
|
+
}
|
|
19208
|
+
function discoveryWindowMs6(scope) {
|
|
19209
|
+
const fallback = scope === "hot" ? DEFAULT_HOT_DISCOVERY_WINDOW_MS6 : scope === "deep" ? DEFAULT_DEEP_DISCOVERY_WINDOW_MS6 : DEFAULT_SHALLOW_DISCOVERY_WINDOW_MS6;
|
|
19210
|
+
const scopedName = `OPENSCOUT_TAIL_${scope.toUpperCase()}_DISCOVERY_WINDOW_MS`;
|
|
19211
|
+
return readPositiveIntEnv6([scopedName, "OPENSCOUT_TAIL_DISCOVERY_WINDOW_MS"], fallback);
|
|
19212
|
+
}
|
|
19213
|
+
function discoveryLimit6(scope) {
|
|
19214
|
+
const fallback = scope === "hot" ? DEFAULT_HOT_DISCOVERY_LIMIT6 : scope === "deep" ? DEFAULT_DEEP_DISCOVERY_LIMIT6 : DEFAULT_SHALLOW_DISCOVERY_LIMIT6;
|
|
18850
19215
|
const scopedName = `OPENSCOUT_TAIL_${scope.toUpperCase()}_DISCOVERY_LIMIT`;
|
|
18851
|
-
return
|
|
19216
|
+
return readPositiveIntEnv6([scopedName, "OPENSCOUT_TAIL_DISCOVERY_LIMIT"], fallback);
|
|
18852
19217
|
}
|
|
18853
19218
|
function messagesPerSession() {
|
|
18854
|
-
return
|
|
19219
|
+
return readPositiveIntEnv6(["OPENSCOUT_TAIL_OPENCODE_MESSAGES_PER_SESSION"], DEFAULT_MESSAGES_PER_SESSION);
|
|
18855
19220
|
}
|
|
18856
19221
|
function opencodeStorageRoots() {
|
|
18857
19222
|
const explicit = process.env.OPENSCOUT_TAIL_OPENCODE_STORAGE_ROOT;
|
|
18858
19223
|
if (explicit?.trim())
|
|
18859
19224
|
return [explicit.trim()];
|
|
18860
|
-
return [
|
|
19225
|
+
return [join7(homedir7(), ".local", "share", "opencode", "storage")].filter((root) => existsSync7(root));
|
|
18861
19226
|
}
|
|
18862
19227
|
function isOpenCodeProcess(command) {
|
|
18863
19228
|
const base = commandBasename2(command).toLowerCase();
|
|
@@ -18881,7 +19246,7 @@ async function discoverOpenCodeProcesses() {
|
|
|
18881
19246
|
cwd,
|
|
18882
19247
|
harness: classifyAttribution(parentChain),
|
|
18883
19248
|
parentChain,
|
|
18884
|
-
source:
|
|
19249
|
+
source: SOURCE_NAME6
|
|
18885
19250
|
});
|
|
18886
19251
|
}));
|
|
18887
19252
|
out.sort((a, b) => a.pid - b.pid);
|
|
@@ -18890,7 +19255,7 @@ async function discoverOpenCodeProcesses() {
|
|
|
18890
19255
|
function metadataRecord3(value) {
|
|
18891
19256
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
18892
19257
|
}
|
|
18893
|
-
function
|
|
19258
|
+
function parseJsonRecord6(text) {
|
|
18894
19259
|
try {
|
|
18895
19260
|
return metadataRecord3(JSON.parse(text));
|
|
18896
19261
|
} catch {
|
|
@@ -18899,7 +19264,7 @@ function parseJsonRecord5(text) {
|
|
|
18899
19264
|
}
|
|
18900
19265
|
function readJsonFile2(filePath) {
|
|
18901
19266
|
try {
|
|
18902
|
-
return
|
|
19267
|
+
return parseJsonRecord6(readFileSync3(filePath, "utf8"));
|
|
18903
19268
|
} catch {
|
|
18904
19269
|
return null;
|
|
18905
19270
|
}
|
|
@@ -18941,22 +19306,22 @@ function partTimestamp(part) {
|
|
|
18941
19306
|
return numberValue(time3, "end") ?? numberValue(time3, "start") ?? numberValue(time3, "created");
|
|
18942
19307
|
}
|
|
18943
19308
|
function walkRecentSessionFiles(root, scope) {
|
|
18944
|
-
const cutoff = Date.now() -
|
|
19309
|
+
const cutoff = Date.now() - discoveryWindowMs6(scope);
|
|
18945
19310
|
const found = [];
|
|
18946
|
-
const stack = [
|
|
19311
|
+
const stack = [join7(root, "session")];
|
|
18947
19312
|
while (stack.length > 0) {
|
|
18948
19313
|
const dir = stack.pop();
|
|
18949
19314
|
let entries = [];
|
|
18950
19315
|
try {
|
|
18951
|
-
entries =
|
|
19316
|
+
entries = readdirSync6(dir);
|
|
18952
19317
|
} catch {
|
|
18953
19318
|
continue;
|
|
18954
19319
|
}
|
|
18955
19320
|
for (const entry of entries) {
|
|
18956
|
-
const path =
|
|
19321
|
+
const path = join7(dir, entry);
|
|
18957
19322
|
let stats;
|
|
18958
19323
|
try {
|
|
18959
|
-
stats =
|
|
19324
|
+
stats = statSync6(path);
|
|
18960
19325
|
} catch {
|
|
18961
19326
|
continue;
|
|
18962
19327
|
}
|
|
@@ -18972,23 +19337,23 @@ function walkRecentSessionFiles(root, scope) {
|
|
|
18972
19337
|
return found;
|
|
18973
19338
|
}
|
|
18974
19339
|
function walkRecentMessageSessionFiles(root, scope) {
|
|
18975
|
-
const cutoff = Date.now() -
|
|
18976
|
-
const messageRoot =
|
|
19340
|
+
const cutoff = Date.now() - discoveryWindowMs6(scope);
|
|
19341
|
+
const messageRoot = join7(root, "message");
|
|
18977
19342
|
let sessionDirs = [];
|
|
18978
19343
|
try {
|
|
18979
|
-
sessionDirs =
|
|
19344
|
+
sessionDirs = readdirSync6(messageRoot);
|
|
18980
19345
|
} catch {
|
|
18981
19346
|
return [];
|
|
18982
19347
|
}
|
|
18983
19348
|
const found = new Map;
|
|
18984
19349
|
for (const sessionId of sessionDirs) {
|
|
18985
|
-
const dir =
|
|
19350
|
+
const dir = join7(messageRoot, sessionId);
|
|
18986
19351
|
let entries = [];
|
|
18987
19352
|
try {
|
|
18988
|
-
const stats =
|
|
19353
|
+
const stats = statSync6(dir);
|
|
18989
19354
|
if (!stats.isDirectory())
|
|
18990
19355
|
continue;
|
|
18991
|
-
entries =
|
|
19356
|
+
entries = readdirSync6(dir);
|
|
18992
19357
|
} catch {
|
|
18993
19358
|
continue;
|
|
18994
19359
|
}
|
|
@@ -18997,7 +19362,7 @@ function walkRecentMessageSessionFiles(root, scope) {
|
|
|
18997
19362
|
if (!entry.endsWith(".json"))
|
|
18998
19363
|
continue;
|
|
18999
19364
|
try {
|
|
19000
|
-
const stats =
|
|
19365
|
+
const stats = statSync6(join7(dir, entry));
|
|
19001
19366
|
if (stats.isFile() && stats.mtimeMs >= cutoff && stats.mtimeMs > latestMessageMtime) {
|
|
19002
19367
|
latestMessageMtime = stats.mtimeMs;
|
|
19003
19368
|
}
|
|
@@ -19007,9 +19372,9 @@ function walkRecentMessageSessionFiles(root, scope) {
|
|
|
19007
19372
|
}
|
|
19008
19373
|
if (latestMessageMtime <= 0)
|
|
19009
19374
|
continue;
|
|
19010
|
-
const sessionPath =
|
|
19375
|
+
const sessionPath = join7(root, "session", "global", `${sessionId}.json`);
|
|
19011
19376
|
try {
|
|
19012
|
-
const sessionStats =
|
|
19377
|
+
const sessionStats = statSync6(sessionPath);
|
|
19013
19378
|
if (!sessionStats.isFile())
|
|
19014
19379
|
continue;
|
|
19015
19380
|
found.set(sessionPath, {
|
|
@@ -19024,7 +19389,7 @@ function walkRecentMessageSessionFiles(root, scope) {
|
|
|
19024
19389
|
return [...found.values()];
|
|
19025
19390
|
}
|
|
19026
19391
|
function sessionIdFromPath(filePath) {
|
|
19027
|
-
return
|
|
19392
|
+
return basename6(filePath).replace(/\.json$/u, "");
|
|
19028
19393
|
}
|
|
19029
19394
|
function storageRootFromSessionPath(filePath) {
|
|
19030
19395
|
const marker = `${sep}session${sep}`;
|
|
@@ -19045,17 +19410,17 @@ function discoverOpenCodeTranscripts(scope) {
|
|
|
19045
19410
|
byPath.set(file2.path, file2);
|
|
19046
19411
|
}
|
|
19047
19412
|
}
|
|
19048
|
-
return [...byPath.values()].sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0,
|
|
19049
|
-
const session = readJsonFile2(file2.path) ??
|
|
19413
|
+
return [...byPath.values()].sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, discoveryLimit6(scope)).map((file2) => {
|
|
19414
|
+
const session = readJsonFile2(file2.path) ?? parseJsonRecord6(readFileHead5(file2.path));
|
|
19050
19415
|
const sessionId = stringValue(session, "id") ?? sessionIdFromPath(file2.path);
|
|
19051
19416
|
const cwd = stringValue(session, "directory");
|
|
19052
19417
|
const title = stringValue(session, "title");
|
|
19053
19418
|
return {
|
|
19054
|
-
source:
|
|
19419
|
+
source: SOURCE_NAME6,
|
|
19055
19420
|
transcriptPath: file2.path,
|
|
19056
19421
|
sessionId,
|
|
19057
19422
|
cwd,
|
|
19058
|
-
project: cwd ?
|
|
19423
|
+
project: cwd ? basename6(cwd) : title ?? "OpenCode",
|
|
19059
19424
|
harness: "unattributed",
|
|
19060
19425
|
mtimeMs: file2.mtimeMs,
|
|
19061
19426
|
size: file2.size
|
|
@@ -19063,10 +19428,10 @@ function discoverOpenCodeTranscripts(scope) {
|
|
|
19063
19428
|
});
|
|
19064
19429
|
}
|
|
19065
19430
|
function readOpenCodeMessages(root, sessionId) {
|
|
19066
|
-
const dir =
|
|
19431
|
+
const dir = join7(root, "message", sessionId);
|
|
19067
19432
|
let entries = [];
|
|
19068
19433
|
try {
|
|
19069
|
-
entries =
|
|
19434
|
+
entries = readdirSync6(dir);
|
|
19070
19435
|
} catch {
|
|
19071
19436
|
return [];
|
|
19072
19437
|
}
|
|
@@ -19074,10 +19439,10 @@ function readOpenCodeMessages(root, sessionId) {
|
|
|
19074
19439
|
for (const entry of entries) {
|
|
19075
19440
|
if (!entry.endsWith(".json"))
|
|
19076
19441
|
continue;
|
|
19077
|
-
const path =
|
|
19442
|
+
const path = join7(dir, entry);
|
|
19078
19443
|
let stats;
|
|
19079
19444
|
try {
|
|
19080
|
-
stats =
|
|
19445
|
+
stats = statSync6(path);
|
|
19081
19446
|
} catch {
|
|
19082
19447
|
continue;
|
|
19083
19448
|
}
|
|
@@ -19091,10 +19456,10 @@ function readOpenCodeMessages(root, sessionId) {
|
|
|
19091
19456
|
return messages.sort((a, b) => (messageTimestamp(a) ?? a.__mtimeMs) - (messageTimestamp(b) ?? b.__mtimeMs)).slice(-messagesPerSession());
|
|
19092
19457
|
}
|
|
19093
19458
|
function readOpenCodeParts(root, messageId) {
|
|
19094
|
-
const dir =
|
|
19459
|
+
const dir = join7(root, "part", messageId);
|
|
19095
19460
|
let entries = [];
|
|
19096
19461
|
try {
|
|
19097
|
-
entries =
|
|
19462
|
+
entries = readdirSync6(dir);
|
|
19098
19463
|
} catch {
|
|
19099
19464
|
return [];
|
|
19100
19465
|
}
|
|
@@ -19102,10 +19467,10 @@ function readOpenCodeParts(root, messageId) {
|
|
|
19102
19467
|
for (const entry of entries) {
|
|
19103
19468
|
if (!entry.endsWith(".json"))
|
|
19104
19469
|
continue;
|
|
19105
|
-
const path =
|
|
19470
|
+
const path = join7(dir, entry);
|
|
19106
19471
|
let stats;
|
|
19107
19472
|
try {
|
|
19108
|
-
stats =
|
|
19473
|
+
stats = statSync6(path);
|
|
19109
19474
|
} catch {
|
|
19110
19475
|
continue;
|
|
19111
19476
|
}
|
|
@@ -19118,7 +19483,7 @@ function readOpenCodeParts(root, messageId) {
|
|
|
19118
19483
|
}
|
|
19119
19484
|
return parts.sort((a, b) => (partTimestamp(a) ?? a.__mtimeMs) - (partTimestamp(b) ?? b.__mtimeMs));
|
|
19120
19485
|
}
|
|
19121
|
-
function
|
|
19486
|
+
function clip6(text, max = MAX_SUMMARY_LEN6) {
|
|
19122
19487
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
19123
19488
|
return flat.length <= max ? flat : `${flat.slice(0, max - 1)}\u2026`;
|
|
19124
19489
|
}
|
|
@@ -19131,24 +19496,24 @@ function summarizeToolPart(part) {
|
|
|
19131
19496
|
const tool = stringValue(part, "tool") ?? "tool";
|
|
19132
19497
|
const status = stringValue(state, "status");
|
|
19133
19498
|
const title = stringValue(state, "title") ?? stringValue(metadata, "description") ?? stringValue(metadata, "preview");
|
|
19134
|
-
return
|
|
19499
|
+
return clip6(`${tool}${status ? ` ${status}` : ""}${title ? ` \xB7 ${title}` : ""}`, 80);
|
|
19135
19500
|
}
|
|
19136
19501
|
function summarizeOpenCodeMessage(message, parts) {
|
|
19137
19502
|
const textParts = parts.filter((part) => stringValue(part, "type") === "text").map((part) => stringValue(part, "text")).filter((text) => Boolean(text));
|
|
19138
19503
|
if (textParts.length > 0)
|
|
19139
|
-
return
|
|
19504
|
+
return clip6(textParts.join(" "));
|
|
19140
19505
|
const summary = nestedRecord(message, "summary");
|
|
19141
19506
|
const title = stringValue(summary, "title");
|
|
19142
19507
|
if (title)
|
|
19143
|
-
return
|
|
19508
|
+
return clip6(title);
|
|
19144
19509
|
const toolParts = parts.filter((part) => stringValue(part, "type") === "tool");
|
|
19145
19510
|
if (toolParts.length > 0) {
|
|
19146
|
-
return
|
|
19511
|
+
return clip6(toolParts.slice(-3).map(summarizeToolPart).join(" \xB7 "));
|
|
19147
19512
|
}
|
|
19148
19513
|
const role = stringValue(message, "role") ?? "message";
|
|
19149
19514
|
const model = modelId(message);
|
|
19150
19515
|
const finish = stringValue(message, "finish");
|
|
19151
|
-
return
|
|
19516
|
+
return clip6(`${role}${model ? ` \xB7 ${model}` : ""}${finish ? ` \xB7 ${finish}` : ""}`);
|
|
19152
19517
|
}
|
|
19153
19518
|
function eventKindForRole(role) {
|
|
19154
19519
|
if (role === "user")
|
|
@@ -19158,20 +19523,20 @@ function eventKindForRole(role) {
|
|
|
19158
19523
|
return "system";
|
|
19159
19524
|
}
|
|
19160
19525
|
function openCodeEventFromMessage(message, parts, ctx, fallbackCwd, index) {
|
|
19161
|
-
const messageId = stringValue(message, "id") ??
|
|
19526
|
+
const messageId = stringValue(message, "id") ?? basename6(message.__filePath).replace(/\.json$/u, "");
|
|
19162
19527
|
const sessionId = stringValue(message, "sessionID") ?? ctx.transcript.sessionId ?? sessionIdFromPath(ctx.transcriptPath);
|
|
19163
19528
|
const pathRecord = nestedRecord(message, "path");
|
|
19164
19529
|
const cwd = stringValue(pathRecord, "cwd") ?? fallbackCwd;
|
|
19165
19530
|
const role = stringValue(message, "role");
|
|
19166
19531
|
const ts = messageTimestamp(message) ?? message.__mtimeMs;
|
|
19167
19532
|
return {
|
|
19168
|
-
id: `${
|
|
19533
|
+
id: `${SOURCE_NAME6}:${sessionId}:${messageId}:${ts || index}`,
|
|
19169
19534
|
ts: ts || Date.now(),
|
|
19170
|
-
source:
|
|
19535
|
+
source: SOURCE_NAME6,
|
|
19171
19536
|
sessionId,
|
|
19172
19537
|
pid: ctx.process.pid,
|
|
19173
19538
|
parentPid: ctx.process.ppid || null,
|
|
19174
|
-
project: cwd ?
|
|
19539
|
+
project: cwd ? basename6(cwd) : ctx.transcript.project,
|
|
19175
19540
|
cwd,
|
|
19176
19541
|
harness: ctx.process.harness,
|
|
19177
19542
|
kind: eventKindForRole(role),
|
|
@@ -19183,7 +19548,7 @@ function openCodeEventFromMessage(message, parts, ctx, fallbackCwd, index) {
|
|
|
19183
19548
|
};
|
|
19184
19549
|
}
|
|
19185
19550
|
function parseOpenCodeSession(text, ctx) {
|
|
19186
|
-
const session =
|
|
19551
|
+
const session = parseJsonRecord6(text);
|
|
19187
19552
|
if (!session)
|
|
19188
19553
|
return [];
|
|
19189
19554
|
const root = storageRootFromSessionPath(ctx.transcriptPath);
|
|
@@ -19193,7 +19558,7 @@ function parseOpenCodeSession(text, ctx) {
|
|
|
19193
19558
|
const messages = readOpenCodeMessages(root, sessionId);
|
|
19194
19559
|
if (messages.length > 0) {
|
|
19195
19560
|
return messages.map((message, index) => {
|
|
19196
|
-
const messageId = stringValue(message, "id") ??
|
|
19561
|
+
const messageId = stringValue(message, "id") ?? basename6(message.__filePath).replace(/\.json$/u, "");
|
|
19197
19562
|
return openCodeEventFromMessage(message, readOpenCodeParts(root, messageId), ctx, fallbackCwd, index);
|
|
19198
19563
|
});
|
|
19199
19564
|
}
|
|
@@ -19201,22 +19566,22 @@ function parseOpenCodeSession(text, ctx) {
|
|
|
19201
19566
|
const updated = numberValue(nestedRecord(session, "time"), "updated") ?? numberValue(nestedRecord(session, "time"), "created") ?? Date.now();
|
|
19202
19567
|
const title = stringValue(session, "title") ?? "session updated";
|
|
19203
19568
|
return [{
|
|
19204
|
-
id: `${
|
|
19569
|
+
id: `${SOURCE_NAME6}:${sessionId}:session:${updated}`,
|
|
19205
19570
|
ts: updated,
|
|
19206
|
-
source:
|
|
19571
|
+
source: SOURCE_NAME6,
|
|
19207
19572
|
sessionId,
|
|
19208
19573
|
pid: ctx.process.pid,
|
|
19209
19574
|
parentPid: ctx.process.ppid || null,
|
|
19210
|
-
project: fallbackCwd ?
|
|
19575
|
+
project: fallbackCwd ? basename6(fallbackCwd) : ctx.transcript.project,
|
|
19211
19576
|
cwd: fallbackCwd,
|
|
19212
19577
|
harness: ctx.process.harness,
|
|
19213
19578
|
kind: "system",
|
|
19214
|
-
summary:
|
|
19579
|
+
summary: clip6(title),
|
|
19215
19580
|
raw: session
|
|
19216
19581
|
}];
|
|
19217
19582
|
}
|
|
19218
19583
|
var OpenCodeSource = {
|
|
19219
|
-
name:
|
|
19584
|
+
name: SOURCE_NAME6,
|
|
19220
19585
|
discoverProcesses() {
|
|
19221
19586
|
return discoverOpenCodeProcesses();
|
|
19222
19587
|
},
|
|
@@ -19232,32 +19597,32 @@ var OpenCodeSource = {
|
|
|
19232
19597
|
};
|
|
19233
19598
|
|
|
19234
19599
|
// packages/runtime/src/tail/pi-source.ts
|
|
19235
|
-
import { closeSync as closeSync6, existsSync as
|
|
19236
|
-
import { homedir as
|
|
19237
|
-
import { basename as
|
|
19238
|
-
var
|
|
19239
|
-
var
|
|
19240
|
-
var
|
|
19241
|
-
var
|
|
19242
|
-
var
|
|
19243
|
-
var
|
|
19244
|
-
var
|
|
19245
|
-
var
|
|
19600
|
+
import { closeSync as closeSync6, existsSync as existsSync8, openSync as openSync6, readdirSync as readdirSync7, readSync as readSync6, statSync as statSync7 } from "fs";
|
|
19601
|
+
import { homedir as homedir8 } from "os";
|
|
19602
|
+
import { basename as basename7, join as join8, relative as relative2 } from "path";
|
|
19603
|
+
var SOURCE_NAME7 = "pi";
|
|
19604
|
+
var MAX_SUMMARY_LEN7 = 200;
|
|
19605
|
+
var DEFAULT_HOT_DISCOVERY_WINDOW_MS7 = 10 * 60 * 1000;
|
|
19606
|
+
var DEFAULT_SHALLOW_DISCOVERY_WINDOW_MS7 = 24 * 60 * 60 * 1000;
|
|
19607
|
+
var DEFAULT_DEEP_DISCOVERY_WINDOW_MS7 = 24 * 60 * 60 * 1000;
|
|
19608
|
+
var DEFAULT_HOT_DISCOVERY_LIMIT7 = 64;
|
|
19609
|
+
var DEFAULT_SHALLOW_DISCOVERY_LIMIT7 = 160;
|
|
19610
|
+
var DEFAULT_DEEP_DISCOVERY_LIMIT7 = 160;
|
|
19246
19611
|
var HEAD_READ_BYTES6 = 256 * 1024;
|
|
19247
|
-
var
|
|
19248
|
-
var
|
|
19612
|
+
var METADATA_CACHE_LIMIT5 = 512;
|
|
19613
|
+
var metadataCache5 = new Map;
|
|
19249
19614
|
function rememberMetadata4(file2, metadata) {
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
while (
|
|
19253
|
-
const oldest =
|
|
19615
|
+
metadataCache5.delete(file2.path);
|
|
19616
|
+
metadataCache5.set(file2.path, { ...file2, ...metadata });
|
|
19617
|
+
while (metadataCache5.size > METADATA_CACHE_LIMIT5) {
|
|
19618
|
+
const oldest = metadataCache5.keys().next().value;
|
|
19254
19619
|
if (!oldest)
|
|
19255
19620
|
break;
|
|
19256
|
-
|
|
19621
|
+
metadataCache5.delete(oldest);
|
|
19257
19622
|
}
|
|
19258
19623
|
return metadata;
|
|
19259
19624
|
}
|
|
19260
|
-
function
|
|
19625
|
+
function readPositiveIntEnv7(names, fallback) {
|
|
19261
19626
|
for (const name of names) {
|
|
19262
19627
|
const raw = Number.parseInt(process.env[name] ?? "", 10);
|
|
19263
19628
|
if (Number.isFinite(raw) && raw > 0)
|
|
@@ -19265,23 +19630,23 @@ function readPositiveIntEnv6(names, fallback) {
|
|
|
19265
19630
|
}
|
|
19266
19631
|
return fallback;
|
|
19267
19632
|
}
|
|
19268
|
-
function
|
|
19269
|
-
const fallback = scope === "hot" ?
|
|
19633
|
+
function discoveryWindowMs7(scope) {
|
|
19634
|
+
const fallback = scope === "hot" ? DEFAULT_HOT_DISCOVERY_WINDOW_MS7 : scope === "deep" ? DEFAULT_DEEP_DISCOVERY_WINDOW_MS7 : DEFAULT_SHALLOW_DISCOVERY_WINDOW_MS7;
|
|
19270
19635
|
const scopedName = `OPENSCOUT_TAIL_${scope.toUpperCase()}_DISCOVERY_WINDOW_MS`;
|
|
19271
|
-
return
|
|
19636
|
+
return readPositiveIntEnv7([scopedName, "OPENSCOUT_TAIL_DISCOVERY_WINDOW_MS"], fallback);
|
|
19272
19637
|
}
|
|
19273
|
-
function
|
|
19274
|
-
const fallback = scope === "hot" ?
|
|
19638
|
+
function discoveryLimit7(scope) {
|
|
19639
|
+
const fallback = scope === "hot" ? DEFAULT_HOT_DISCOVERY_LIMIT7 : scope === "deep" ? DEFAULT_DEEP_DISCOVERY_LIMIT7 : DEFAULT_SHALLOW_DISCOVERY_LIMIT7;
|
|
19275
19640
|
const scopedName = `OPENSCOUT_TAIL_${scope.toUpperCase()}_DISCOVERY_LIMIT`;
|
|
19276
|
-
return
|
|
19641
|
+
return readPositiveIntEnv7([scopedName, "OPENSCOUT_TAIL_DISCOVERY_LIMIT"], fallback);
|
|
19277
19642
|
}
|
|
19278
19643
|
function projectsRoot2() {
|
|
19279
|
-
return process.env.OPENSCOUT_TAIL_PI_SESSIONS_ROOT ??
|
|
19644
|
+
return process.env.OPENSCOUT_TAIL_PI_SESSIONS_ROOT ?? join8(homedir8(), ".pi", "agent", "sessions");
|
|
19280
19645
|
}
|
|
19281
19646
|
function listJsonlFiles2(dir) {
|
|
19282
19647
|
let entries = [];
|
|
19283
19648
|
try {
|
|
19284
|
-
entries =
|
|
19649
|
+
entries = readdirSync7(dir);
|
|
19285
19650
|
} catch {
|
|
19286
19651
|
return [];
|
|
19287
19652
|
}
|
|
@@ -19304,7 +19669,7 @@ function readFileHead6(filePath) {
|
|
|
19304
19669
|
}
|
|
19305
19670
|
}
|
|
19306
19671
|
}
|
|
19307
|
-
function
|
|
19672
|
+
function parseJsonRecord7(line) {
|
|
19308
19673
|
try {
|
|
19309
19674
|
const value = JSON.parse(line);
|
|
19310
19675
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -19312,7 +19677,7 @@ function parseJsonRecord6(line) {
|
|
|
19312
19677
|
return null;
|
|
19313
19678
|
}
|
|
19314
19679
|
}
|
|
19315
|
-
function
|
|
19680
|
+
function parseTimestamp4(value) {
|
|
19316
19681
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
19317
19682
|
return value > 1000000000000 ? value : value * 1000;
|
|
19318
19683
|
}
|
|
@@ -19322,7 +19687,7 @@ function parseTimestamp3(value) {
|
|
|
19322
19687
|
}
|
|
19323
19688
|
return null;
|
|
19324
19689
|
}
|
|
19325
|
-
function
|
|
19690
|
+
function clip7(text, max = MAX_SUMMARY_LEN7) {
|
|
19326
19691
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
19327
19692
|
return flat.length <= max ? flat : `${flat.slice(0, max - 1)}\u2026`;
|
|
19328
19693
|
}
|
|
@@ -19335,14 +19700,14 @@ function decodePiProjectDir(dirName) {
|
|
|
19335
19700
|
return `/${inner.replace(/-/g, "/")}`;
|
|
19336
19701
|
}
|
|
19337
19702
|
function sessionIdFromPiPath(filePath) {
|
|
19338
|
-
const name =
|
|
19703
|
+
const name = basename7(filePath).replace(/\.jsonl$/, "");
|
|
19339
19704
|
const separator = name.lastIndexOf("_");
|
|
19340
19705
|
if (separator >= 0)
|
|
19341
19706
|
return name.slice(separator + 1);
|
|
19342
19707
|
return name;
|
|
19343
19708
|
}
|
|
19344
19709
|
function readPiMetadata(file2) {
|
|
19345
|
-
const cached2 =
|
|
19710
|
+
const cached2 = metadataCache5.get(file2.path);
|
|
19346
19711
|
if (cached2 && cached2.mtimeMs === file2.mtimeMs && cached2.size === file2.size) {
|
|
19347
19712
|
return { cwd: cached2.cwd, sessionId: cached2.sessionId };
|
|
19348
19713
|
}
|
|
@@ -19350,7 +19715,7 @@ function readPiMetadata(file2) {
|
|
|
19350
19715
|
let cwd = null;
|
|
19351
19716
|
let sessionId = null;
|
|
19352
19717
|
for (const line of head.split(/\r?\n/)) {
|
|
19353
|
-
const record2 =
|
|
19718
|
+
const record2 = parseJsonRecord7(line.trim());
|
|
19354
19719
|
if (!record2)
|
|
19355
19720
|
continue;
|
|
19356
19721
|
if (record2.type === "session") {
|
|
@@ -19376,26 +19741,26 @@ function fallbackCwdForPath2(filePath) {
|
|
|
19376
19741
|
return dirName ? decodePiProjectDir(dirName) : null;
|
|
19377
19742
|
}
|
|
19378
19743
|
function listRecentPiProjectTranscripts(root, scope) {
|
|
19379
|
-
const cutoff = Date.now() -
|
|
19744
|
+
const cutoff = Date.now() - discoveryWindowMs7(scope);
|
|
19380
19745
|
const found = [];
|
|
19381
19746
|
let projectDirs = [];
|
|
19382
19747
|
try {
|
|
19383
|
-
projectDirs =
|
|
19748
|
+
projectDirs = readdirSync7(root);
|
|
19384
19749
|
} catch {
|
|
19385
19750
|
return [];
|
|
19386
19751
|
}
|
|
19387
19752
|
for (const entry of projectDirs) {
|
|
19388
|
-
const projectDir =
|
|
19753
|
+
const projectDir = join8(root, entry);
|
|
19389
19754
|
try {
|
|
19390
|
-
if (!
|
|
19755
|
+
if (!statSync7(projectDir).isDirectory())
|
|
19391
19756
|
continue;
|
|
19392
19757
|
} catch {
|
|
19393
19758
|
continue;
|
|
19394
19759
|
}
|
|
19395
19760
|
for (const file2 of listJsonlFiles2(projectDir)) {
|
|
19396
|
-
const path =
|
|
19761
|
+
const path = join8(projectDir, file2);
|
|
19397
19762
|
try {
|
|
19398
|
-
const stats =
|
|
19763
|
+
const stats = statSync7(path);
|
|
19399
19764
|
if (stats.mtimeMs < cutoff)
|
|
19400
19765
|
continue;
|
|
19401
19766
|
found.push({ path, mtimeMs: stats.mtimeMs, size: stats.size });
|
|
@@ -19404,7 +19769,7 @@ function listRecentPiProjectTranscripts(root, scope) {
|
|
|
19404
19769
|
}
|
|
19405
19770
|
}
|
|
19406
19771
|
}
|
|
19407
|
-
return found.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0,
|
|
19772
|
+
return found.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, discoveryLimit7(scope));
|
|
19408
19773
|
}
|
|
19409
19774
|
function isPiProcess(command) {
|
|
19410
19775
|
return commandBasename2(command) === "pi";
|
|
@@ -19427,7 +19792,7 @@ async function discoverPiProcesses() {
|
|
|
19427
19792
|
cwd,
|
|
19428
19793
|
harness: classifyAttribution(parentChain),
|
|
19429
19794
|
parentChain,
|
|
19430
|
-
source:
|
|
19795
|
+
source: SOURCE_NAME7
|
|
19431
19796
|
});
|
|
19432
19797
|
}));
|
|
19433
19798
|
out.sort((a, b) => a.pid - b.pid);
|
|
@@ -19435,18 +19800,18 @@ async function discoverPiProcesses() {
|
|
|
19435
19800
|
}
|
|
19436
19801
|
function discoverPiTranscripts(scope) {
|
|
19437
19802
|
const root = projectsRoot2();
|
|
19438
|
-
if (!
|
|
19803
|
+
if (!existsSync8(root))
|
|
19439
19804
|
return [];
|
|
19440
19805
|
return listRecentPiProjectTranscripts(root, scope).map((file2) => {
|
|
19441
19806
|
const meta3 = readPiMetadata(file2);
|
|
19442
19807
|
const cwd = meta3.cwd ?? fallbackCwdForPath2(file2.path);
|
|
19443
19808
|
const sessionId = meta3.sessionId ?? sessionIdFromPiPath(file2.path);
|
|
19444
19809
|
return {
|
|
19445
|
-
source:
|
|
19810
|
+
source: SOURCE_NAME7,
|
|
19446
19811
|
transcriptPath: file2.path,
|
|
19447
19812
|
sessionId,
|
|
19448
19813
|
cwd,
|
|
19449
|
-
project: cwd ?
|
|
19814
|
+
project: cwd ? basename7(cwd) : projectDirNameForPath2(file2.path) ?? "(unknown)",
|
|
19450
19815
|
harness: "unattributed",
|
|
19451
19816
|
mtimeMs: file2.mtimeMs,
|
|
19452
19817
|
size: file2.size
|
|
@@ -19472,14 +19837,14 @@ function summarizePiMessage(message) {
|
|
|
19472
19837
|
const content = message.content;
|
|
19473
19838
|
if (role === "user") {
|
|
19474
19839
|
const text = textFromPiContent(content);
|
|
19475
|
-
return { kind: "user", summary:
|
|
19840
|
+
return { kind: "user", summary: clip7(text || "[user]") };
|
|
19476
19841
|
}
|
|
19477
19842
|
if (role === "toolResult") {
|
|
19478
19843
|
const text = textFromPiContent(content);
|
|
19479
19844
|
const toolName = typeof message.toolName === "string" ? message.toolName : undefined;
|
|
19480
19845
|
return {
|
|
19481
19846
|
kind: "tool-result",
|
|
19482
|
-
summary:
|
|
19847
|
+
summary: clip7(formatToolResult(text, toolName))
|
|
19483
19848
|
};
|
|
19484
19849
|
}
|
|
19485
19850
|
if (role === "assistant") {
|
|
@@ -19501,14 +19866,14 @@ function summarizePiMessage(message) {
|
|
|
19501
19866
|
}
|
|
19502
19867
|
}
|
|
19503
19868
|
if (toolParts.length > 0) {
|
|
19504
|
-
return { kind: "tool", summary:
|
|
19869
|
+
return { kind: "tool", summary: clip7(toolParts.join(" \xB7 ")) };
|
|
19505
19870
|
}
|
|
19506
|
-
return { kind: "assistant", summary:
|
|
19871
|
+
return { kind: "assistant", summary: clip7(textParts.join(" ") || "[assistant]") };
|
|
19507
19872
|
}
|
|
19508
19873
|
return null;
|
|
19509
19874
|
}
|
|
19510
19875
|
function parsePiLine(line, ctx) {
|
|
19511
|
-
const record2 =
|
|
19876
|
+
const record2 = parseJsonRecord7(line.trim());
|
|
19512
19877
|
if (!record2 || record2.type !== "message" || typeof record2.message !== "object" || !record2.message) {
|
|
19513
19878
|
return null;
|
|
19514
19879
|
}
|
|
@@ -19518,16 +19883,16 @@ function parsePiLine(line, ctx) {
|
|
|
19518
19883
|
return null;
|
|
19519
19884
|
const sessionId = ctx.transcript.sessionId ?? sessionIdFromPiPath(ctx.transcriptPath);
|
|
19520
19885
|
const cwd = ctx.transcript.cwd ?? ctx.process.cwd ?? "";
|
|
19521
|
-
const ts =
|
|
19886
|
+
const ts = parseTimestamp4(record2.timestamp) ?? parseTimestamp4(message.timestamp) ?? Date.now();
|
|
19522
19887
|
const recordId = typeof record2.id === "string" && record2.id.trim() ? record2.id : String(ctx.lineOffset);
|
|
19523
19888
|
return {
|
|
19524
|
-
id: `${
|
|
19889
|
+
id: `${SOURCE_NAME7}:${sessionId}:${recordId}`,
|
|
19525
19890
|
ts,
|
|
19526
|
-
source:
|
|
19891
|
+
source: SOURCE_NAME7,
|
|
19527
19892
|
sessionId,
|
|
19528
19893
|
pid: ctx.process.pid,
|
|
19529
19894
|
parentPid: ctx.process.ppid || null,
|
|
19530
|
-
project: cwd ?
|
|
19895
|
+
project: cwd ? basename7(cwd) : ctx.transcript.project,
|
|
19531
19896
|
cwd,
|
|
19532
19897
|
harness: ctx.process.harness,
|
|
19533
19898
|
kind: parsed.kind,
|
|
@@ -19536,7 +19901,7 @@ function parsePiLine(line, ctx) {
|
|
|
19536
19901
|
};
|
|
19537
19902
|
}
|
|
19538
19903
|
var PiSource = {
|
|
19539
|
-
name:
|
|
19904
|
+
name: SOURCE_NAME7,
|
|
19540
19905
|
discoverProcesses() {
|
|
19541
19906
|
return discoverPiProcesses();
|
|
19542
19907
|
},
|
|
@@ -19566,19 +19931,19 @@ function sessionRegistryKey(transcript) {
|
|
|
19566
19931
|
}
|
|
19567
19932
|
|
|
19568
19933
|
// packages/runtime/src/tail/service.ts
|
|
19569
|
-
function
|
|
19934
|
+
function readPositiveIntEnv8(name, fallback) {
|
|
19570
19935
|
const raw = Number.parseInt(process.env[name] ?? "", 10);
|
|
19571
19936
|
return Number.isFinite(raw) && raw > 0 ? raw : fallback;
|
|
19572
19937
|
}
|
|
19573
|
-
var TAIL_POLL_INTERVAL_MS =
|
|
19574
|
-
var HOT_DISCOVERY_INTERVAL_MS =
|
|
19575
|
-
var DISCOVERY_CACHE_MAX_AGE_MS =
|
|
19576
|
-
var SHALLOW_DISCOVERY_INTERVAL_MS =
|
|
19577
|
-
var DEEP_DISCOVERY_INTERVAL_MS =
|
|
19938
|
+
var TAIL_POLL_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_POLL_INTERVAL_MS", 500);
|
|
19939
|
+
var HOT_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_HOT_DISCOVERY_INTERVAL_MS", 30000);
|
|
19940
|
+
var DISCOVERY_CACHE_MAX_AGE_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_DISCOVERY_CACHE_MAX_AGE_MS", HOT_DISCOVERY_INTERVAL_MS);
|
|
19941
|
+
var SHALLOW_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_SHALLOW_DISCOVERY_INTERVAL_MS", 10 * 60000);
|
|
19942
|
+
var DEEP_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_DEEP_DISCOVERY_INTERVAL_MS", 60 * 60000);
|
|
19578
19943
|
var PER_SESSION_BUFFER_LIMIT = 2000;
|
|
19579
19944
|
var AGGREGATE_BUFFER_LIMIT = 1e4;
|
|
19580
|
-
var QUIET_EVENT_COALESCE_WINDOW_MS =
|
|
19581
|
-
var QUIET_EVENT_COALESCE_MAX_KEYS =
|
|
19945
|
+
var QUIET_EVENT_COALESCE_WINDOW_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_QUIET_EVENT_COALESCE_WINDOW_MS", 5000);
|
|
19946
|
+
var QUIET_EVENT_COALESCE_MAX_KEYS = readPositiveIntEnv8("OPENSCOUT_TAIL_QUIET_EVENT_COALESCE_MAX_KEYS", 2000);
|
|
19582
19947
|
var RAW_MAX_DEPTH = 5;
|
|
19583
19948
|
var RAW_MAX_STRING_LEN = 1000;
|
|
19584
19949
|
var RAW_MAX_ARRAY_ITEMS = 25;
|
|
@@ -19586,9 +19951,9 @@ var RAW_MAX_OBJECT_KEYS = 50;
|
|
|
19586
19951
|
var RECENT_TRANSCRIPT_READ_BYTES = 512 * 1024;
|
|
19587
19952
|
var SESSION_TRANSCRIPT_READ_BYTES = 8 * 1024 * 1024;
|
|
19588
19953
|
var RECENT_TRANSCRIPT_LINES_PER_FILE = 200;
|
|
19589
|
-
var RECENT_TRANSCRIPT_MAX_FILES =
|
|
19590
|
-
var NATIVE_TAIL_SOURCES = new Set(["grok", "opencode", "cursor"]);
|
|
19591
|
-
var sources = [GrokSource, ClaudeSource, CodexSource, CursorSource, OpenCodeSource, PiSource];
|
|
19954
|
+
var RECENT_TRANSCRIPT_MAX_FILES = readPositiveIntEnv8("OPENSCOUT_TAIL_RECENT_TRANSCRIPT_MAX_FILES", 24);
|
|
19955
|
+
var NATIVE_TAIL_SOURCES = new Set(["grok", "kimi", "opencode", "cursor"]);
|
|
19956
|
+
var sources = [GrokSource, KimiSource, ClaudeSource, CodexSource, CursorSource, OpenCodeSource, PiSource];
|
|
19592
19957
|
var watchers = new Map;
|
|
19593
19958
|
var aggregateBuffer = [];
|
|
19594
19959
|
var perSessionBuffer = new Map;
|
|
@@ -20275,7 +20640,15 @@ function isCodexChunkToolResult(summary) {
|
|
|
20275
20640
|
const trimmed = summary.trim();
|
|
20276
20641
|
return trimmed.startsWith("-> Chunk ID:") || /^->\s+Wall time:/u.test(trimmed);
|
|
20277
20642
|
}
|
|
20643
|
+
function isCursorProcessSample(event) {
|
|
20644
|
+
if (event.source !== "cursor" || event.kind !== "system")
|
|
20645
|
+
return false;
|
|
20646
|
+
const summary = event.summary.trim().toLowerCase();
|
|
20647
|
+
return summary === "process sample" || summary.startsWith("process sample \xB7");
|
|
20648
|
+
}
|
|
20278
20649
|
function isTailNoiseEvent(event) {
|
|
20650
|
+
if (isCursorProcessSample(event))
|
|
20651
|
+
return true;
|
|
20279
20652
|
if (event.source === "grok") {
|
|
20280
20653
|
const summary2 = event.summary.trim().toLowerCase();
|
|
20281
20654
|
if (summary2 === "first token" || summary2.startsWith("loop ")) {
|
|
@@ -20317,12 +20690,12 @@ function filterTailEventsForDisplay(events) {
|
|
|
20317
20690
|
}
|
|
20318
20691
|
// packages/runtime/src/harness-topology/service.ts
|
|
20319
20692
|
import { createHash } from "crypto";
|
|
20320
|
-
import { homedir as
|
|
20693
|
+
import { homedir as homedir13 } from "os";
|
|
20321
20694
|
|
|
20322
20695
|
// packages/agent-sessions/src/adapters/claude-code/team-topology.ts
|
|
20323
|
-
import { existsSync as
|
|
20324
|
-
import { homedir as
|
|
20325
|
-
import { basename as
|
|
20696
|
+
import { existsSync as existsSync9, readdirSync as readdirSync8, readFileSync as readFileSync4, statSync as statSync8 } from "fs";
|
|
20697
|
+
import { homedir as homedir9 } from "os";
|
|
20698
|
+
import { basename as basename8, dirname as dirname3, join as join9, relative as relative3 } from "path";
|
|
20326
20699
|
var TOPOLOGY_SCHEMA_VERSION = "openscout.observed-harness-topology.v1";
|
|
20327
20700
|
var CLAUDE_TOPOLOGY_SOURCE = "claude-code-agent-teams";
|
|
20328
20701
|
var SESSION_ID_KEYS = new Set([
|
|
@@ -20365,7 +20738,7 @@ function sourceRefId(kind, value) {
|
|
|
20365
20738
|
}
|
|
20366
20739
|
function readJsonObject(path) {
|
|
20367
20740
|
try {
|
|
20368
|
-
const parsed = JSON.parse(
|
|
20741
|
+
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
20369
20742
|
return isObject3(parsed) ? parsed : null;
|
|
20370
20743
|
} catch {
|
|
20371
20744
|
return null;
|
|
@@ -20373,30 +20746,30 @@ function readJsonObject(path) {
|
|
|
20373
20746
|
}
|
|
20374
20747
|
function statIsDirectory(path) {
|
|
20375
20748
|
try {
|
|
20376
|
-
return
|
|
20749
|
+
return statSync8(path).isDirectory();
|
|
20377
20750
|
} catch {
|
|
20378
20751
|
return false;
|
|
20379
20752
|
}
|
|
20380
20753
|
}
|
|
20381
20754
|
function statIsFile(path) {
|
|
20382
20755
|
try {
|
|
20383
|
-
return
|
|
20756
|
+
return statSync8(path).isFile();
|
|
20384
20757
|
} catch {
|
|
20385
20758
|
return false;
|
|
20386
20759
|
}
|
|
20387
20760
|
}
|
|
20388
20761
|
function readTeamConfigs(homeDir) {
|
|
20389
|
-
const teamsRoot =
|
|
20390
|
-
if (!
|
|
20762
|
+
const teamsRoot = join9(homeDir, ".claude", "teams");
|
|
20763
|
+
if (!existsSync9(teamsRoot) || !statIsDirectory(teamsRoot)) {
|
|
20391
20764
|
return [];
|
|
20392
20765
|
}
|
|
20393
20766
|
const teams = [];
|
|
20394
|
-
for (const entry of
|
|
20395
|
-
const teamDir =
|
|
20767
|
+
for (const entry of readdirSync8(teamsRoot)) {
|
|
20768
|
+
const teamDir = join9(teamsRoot, entry);
|
|
20396
20769
|
if (!statIsDirectory(teamDir)) {
|
|
20397
20770
|
continue;
|
|
20398
20771
|
}
|
|
20399
|
-
const configPath =
|
|
20772
|
+
const configPath = join9(teamDir, "config.json");
|
|
20400
20773
|
const config2 = readJsonObject(configPath);
|
|
20401
20774
|
if (!config2) {
|
|
20402
20775
|
continue;
|
|
@@ -20534,8 +20907,8 @@ function membersFromConfig(team, groupId, configRefId) {
|
|
|
20534
20907
|
return { agents, relationships, agentByExternal };
|
|
20535
20908
|
}
|
|
20536
20909
|
function readTaskFiles(tasksRoot, teamName) {
|
|
20537
|
-
const teamTasksRoot =
|
|
20538
|
-
if (!
|
|
20910
|
+
const teamTasksRoot = join9(tasksRoot, teamName);
|
|
20911
|
+
if (!existsSync9(teamTasksRoot) || !statIsDirectory(teamTasksRoot)) {
|
|
20539
20912
|
return [];
|
|
20540
20913
|
}
|
|
20541
20914
|
const result = [];
|
|
@@ -20544,8 +20917,8 @@ function readTaskFiles(tasksRoot, teamName) {
|
|
|
20544
20917
|
const current = stack.pop();
|
|
20545
20918
|
if (!current)
|
|
20546
20919
|
continue;
|
|
20547
|
-
for (const entry of
|
|
20548
|
-
const path =
|
|
20920
|
+
for (const entry of readdirSync8(current)) {
|
|
20921
|
+
const path = join9(current, entry);
|
|
20549
20922
|
if (statIsDirectory(path)) {
|
|
20550
20923
|
stack.push(path);
|
|
20551
20924
|
} else if (statIsFile(path)) {
|
|
@@ -20576,14 +20949,14 @@ function firstMarkdownTitle(raw) {
|
|
|
20576
20949
|
function parseTaskFile(taskPath, teamName, tasksRoot, sourceRef) {
|
|
20577
20950
|
let raw;
|
|
20578
20951
|
try {
|
|
20579
|
-
raw =
|
|
20952
|
+
raw = readFileSync4(taskPath, "utf8");
|
|
20580
20953
|
} catch {
|
|
20581
20954
|
return null;
|
|
20582
20955
|
}
|
|
20583
|
-
const relativePath = relative3(
|
|
20956
|
+
const relativePath = relative3(join9(tasksRoot, teamName), taskPath);
|
|
20584
20957
|
const fallbackId = relativePath.replace(/\.[^.]+$/u, "");
|
|
20585
|
-
const fallbackTitle = firstMarkdownTitle(raw) ??
|
|
20586
|
-
const inferredState = inferTaskStateFromPath(
|
|
20958
|
+
const fallbackTitle = firstMarkdownTitle(raw) ?? basename8(fallbackId);
|
|
20959
|
+
const inferredState = inferTaskStateFromPath(dirname3(relativePath));
|
|
20587
20960
|
let parsed = null;
|
|
20588
20961
|
try {
|
|
20589
20962
|
const json2 = JSON.parse(raw);
|
|
@@ -20614,7 +20987,7 @@ function parseTaskFile(taskPath, teamName, tasksRoot, sourceRef) {
|
|
|
20614
20987
|
};
|
|
20615
20988
|
}
|
|
20616
20989
|
function tasksFromFiles(homeDir, teamName, agentByExternal) {
|
|
20617
|
-
const tasksRoot =
|
|
20990
|
+
const tasksRoot = join9(homeDir, ".claude", "tasks");
|
|
20618
20991
|
const taskFiles = readTaskFiles(tasksRoot, teamName);
|
|
20619
20992
|
const sourceRefs = [];
|
|
20620
20993
|
const parsedTasks = [];
|
|
@@ -20702,7 +21075,7 @@ function leaderAgentForTeam(team, groupId, configRefId, options) {
|
|
|
20702
21075
|
};
|
|
20703
21076
|
}
|
|
20704
21077
|
function readClaudeAgentTeamTopology(options = {}) {
|
|
20705
|
-
const homeDir = options.homeDir ??
|
|
21078
|
+
const homeDir = options.homeDir ?? homedir9();
|
|
20706
21079
|
const teams = readTeamConfigs(homeDir).filter((team) => teamMatches(team, options));
|
|
20707
21080
|
if (teams.length === 0) {
|
|
20708
21081
|
return null;
|
|
@@ -20773,9 +21146,9 @@ function readClaudeAgentTeamTopology(options = {}) {
|
|
|
20773
21146
|
}
|
|
20774
21147
|
|
|
20775
21148
|
// packages/agent-sessions/src/adapters/claude-code/subagent-topology.ts
|
|
20776
|
-
import { existsSync as
|
|
20777
|
-
import { homedir as
|
|
20778
|
-
import { join as
|
|
21149
|
+
import { existsSync as existsSync10, readdirSync as readdirSync9, readFileSync as readFileSync5, statSync as statSync9 } from "fs";
|
|
21150
|
+
import { homedir as homedir10 } from "os";
|
|
21151
|
+
import { join as join10, normalize, sep as sep2 } from "path";
|
|
20779
21152
|
var TOPOLOGY_SCHEMA_VERSION2 = "openscout.observed-harness-topology.v1";
|
|
20780
21153
|
var CLAUDE_SUBAGENT_TOPOLOGY_SOURCE = "claude-code-subagents";
|
|
20781
21154
|
var DEFAULT_MAX_PARENT_SESSIONS = 40;
|
|
@@ -20797,28 +21170,28 @@ function sourceRefId2(kind, value) {
|
|
|
20797
21170
|
}
|
|
20798
21171
|
function statIsDirectory2(path) {
|
|
20799
21172
|
try {
|
|
20800
|
-
return
|
|
21173
|
+
return statSync9(path).isDirectory();
|
|
20801
21174
|
} catch {
|
|
20802
21175
|
return false;
|
|
20803
21176
|
}
|
|
20804
21177
|
}
|
|
20805
21178
|
function statIsFile2(path) {
|
|
20806
21179
|
try {
|
|
20807
|
-
return
|
|
21180
|
+
return statSync9(path).isFile();
|
|
20808
21181
|
} catch {
|
|
20809
21182
|
return false;
|
|
20810
21183
|
}
|
|
20811
21184
|
}
|
|
20812
21185
|
function statMtimeMs(path) {
|
|
20813
21186
|
try {
|
|
20814
|
-
return
|
|
21187
|
+
return statSync9(path).mtimeMs;
|
|
20815
21188
|
} catch {
|
|
20816
21189
|
return 0;
|
|
20817
21190
|
}
|
|
20818
21191
|
}
|
|
20819
21192
|
function readText(path) {
|
|
20820
21193
|
try {
|
|
20821
|
-
return
|
|
21194
|
+
return readFileSync5(path, "utf8");
|
|
20822
21195
|
} catch {
|
|
20823
21196
|
return null;
|
|
20824
21197
|
}
|
|
@@ -20851,30 +21224,30 @@ function parseJsonLines(path) {
|
|
|
20851
21224
|
return events;
|
|
20852
21225
|
}
|
|
20853
21226
|
function projectsRoot3(homeDir) {
|
|
20854
|
-
return
|
|
21227
|
+
return join10(homeDir, ".claude", "projects");
|
|
20855
21228
|
}
|
|
20856
21229
|
function discoverParentSessionDirs(homeDir, maxParentSessions, sessionFilter) {
|
|
20857
21230
|
const root = projectsRoot3(homeDir);
|
|
20858
|
-
if (!
|
|
21231
|
+
if (!existsSync10(root) || !statIsDirectory2(root))
|
|
20859
21232
|
return [];
|
|
20860
21233
|
const discovered = [];
|
|
20861
|
-
for (const projectEntry of
|
|
20862
|
-
const projectDir =
|
|
21234
|
+
for (const projectEntry of readdirSync9(root).sort()) {
|
|
21235
|
+
const projectDir = join10(root, projectEntry);
|
|
20863
21236
|
if (!statIsDirectory2(projectDir))
|
|
20864
21237
|
continue;
|
|
20865
|
-
for (const sessionEntry of
|
|
21238
|
+
for (const sessionEntry of readdirSync9(projectDir).sort()) {
|
|
20866
21239
|
if (sessionFilter && sessionEntry !== sessionFilter)
|
|
20867
21240
|
continue;
|
|
20868
|
-
const sessionDir =
|
|
21241
|
+
const sessionDir = join10(projectDir, sessionEntry);
|
|
20869
21242
|
if (!statIsDirectory2(sessionDir))
|
|
20870
21243
|
continue;
|
|
20871
|
-
const subagentsDir =
|
|
21244
|
+
const subagentsDir = join10(sessionDir, "subagents");
|
|
20872
21245
|
if (!statIsDirectory2(subagentsDir))
|
|
20873
21246
|
continue;
|
|
20874
|
-
const directSubagents =
|
|
21247
|
+
const directSubagents = readdirSync9(subagentsDir).some((entry) => /^agent-[a-zA-Z0-9]+\.jsonl$/u.test(entry));
|
|
20875
21248
|
if (!directSubagents)
|
|
20876
21249
|
continue;
|
|
20877
|
-
const parentSessionPath =
|
|
21250
|
+
const parentSessionPath = join10(projectDir, `${sessionEntry}.jsonl`);
|
|
20878
21251
|
discovered.push({
|
|
20879
21252
|
sessionId: sessionEntry,
|
|
20880
21253
|
projectDir,
|
|
@@ -21068,8 +21441,8 @@ function readSubagentRecord(parent, parentSummary, file2) {
|
|
|
21068
21441
|
if (!match?.[1])
|
|
21069
21442
|
return null;
|
|
21070
21443
|
const agentId = match[1];
|
|
21071
|
-
const transcriptPath =
|
|
21072
|
-
const metaPath =
|
|
21444
|
+
const transcriptPath = join10(parent.subagentsDir, file2);
|
|
21445
|
+
const metaPath = join10(parent.subagentsDir, `agent-${agentId}.meta.json`);
|
|
21073
21446
|
const meta3 = statIsFile2(metaPath) ? parseSubagentMeta(metaPath) : undefined;
|
|
21074
21447
|
const toolUseId = meta3?.toolUseId;
|
|
21075
21448
|
const parentToolUse = toolUseId ? parentSummary.toolUses.get(toolUseId) : undefined;
|
|
@@ -21281,21 +21654,21 @@ function buildTopology(parents, observedAt) {
|
|
|
21281
21654
|
};
|
|
21282
21655
|
}
|
|
21283
21656
|
function readClaudeSubagentTopology(options = {}) {
|
|
21284
|
-
const homeDir = options.homeDir ??
|
|
21657
|
+
const homeDir = options.homeDir ?? homedir10();
|
|
21285
21658
|
const maxParentSessions = options.maxParentSessions ?? DEFAULT_MAX_PARENT_SESSIONS;
|
|
21286
21659
|
const sessionId = options.claudeSessionId?.trim();
|
|
21287
21660
|
const parents = discoverParentSessionDirs(homeDir, maxParentSessions, sessionId).map((parent) => {
|
|
21288
21661
|
const parentSummary = readParentSummary(parent.parentSessionPath);
|
|
21289
|
-
const records =
|
|
21662
|
+
const records = readdirSync9(parent.subagentsDir).sort().map((file2) => readSubagentRecord(parent, parentSummary, file2)).filter((record2) => Boolean(record2));
|
|
21290
21663
|
return { parent, parentSummary, records };
|
|
21291
21664
|
}).filter(({ parent, parentSummary, records }) => records.length > 0 && parentMatchesOptions(parent, parentSummary, records, options));
|
|
21292
21665
|
return buildTopology(parents, (options.now ?? (() => new Date))().toISOString());
|
|
21293
21666
|
}
|
|
21294
21667
|
|
|
21295
21668
|
// packages/agent-sessions/src/adapters/claude-code/workflow-topology.ts
|
|
21296
|
-
import { existsSync as
|
|
21297
|
-
import { homedir as
|
|
21298
|
-
import { basename as
|
|
21669
|
+
import { existsSync as existsSync11, readdirSync as readdirSync10, readFileSync as readFileSync6, statSync as statSync10 } from "fs";
|
|
21670
|
+
import { homedir as homedir11 } from "os";
|
|
21671
|
+
import { basename as basename10, join as join11, normalize as normalize2, relative as relative4, sep as sep3 } from "path";
|
|
21299
21672
|
var TOPOLOGY_SCHEMA_VERSION3 = "openscout.observed-harness-topology.v1";
|
|
21300
21673
|
var CLAUDE_WORKFLOW_TOPOLOGY_SOURCE = "claude-code-workflows";
|
|
21301
21674
|
var DEFAULT_MAX_WORKFLOW_RUNS = 20;
|
|
@@ -21316,28 +21689,28 @@ function sourceRefId3(kind, value) {
|
|
|
21316
21689
|
}
|
|
21317
21690
|
function statIsDirectory3(path) {
|
|
21318
21691
|
try {
|
|
21319
|
-
return
|
|
21692
|
+
return statSync10(path).isDirectory();
|
|
21320
21693
|
} catch {
|
|
21321
21694
|
return false;
|
|
21322
21695
|
}
|
|
21323
21696
|
}
|
|
21324
21697
|
function statIsFile3(path) {
|
|
21325
21698
|
try {
|
|
21326
|
-
return
|
|
21699
|
+
return statSync10(path).isFile();
|
|
21327
21700
|
} catch {
|
|
21328
21701
|
return false;
|
|
21329
21702
|
}
|
|
21330
21703
|
}
|
|
21331
21704
|
function statMtimeMs2(path) {
|
|
21332
21705
|
try {
|
|
21333
|
-
return
|
|
21706
|
+
return statSync10(path).mtimeMs;
|
|
21334
21707
|
} catch {
|
|
21335
21708
|
return 0;
|
|
21336
21709
|
}
|
|
21337
21710
|
}
|
|
21338
21711
|
function readText2(path) {
|
|
21339
21712
|
try {
|
|
21340
|
-
return
|
|
21713
|
+
return readFileSync6(path, "utf8");
|
|
21341
21714
|
} catch {
|
|
21342
21715
|
return null;
|
|
21343
21716
|
}
|
|
@@ -21370,33 +21743,33 @@ function parseJsonLines2(path) {
|
|
|
21370
21743
|
return events;
|
|
21371
21744
|
}
|
|
21372
21745
|
function discoverWorkflowDirs(homeDir, maxRuns) {
|
|
21373
|
-
const projectsRoot4 =
|
|
21374
|
-
if (!
|
|
21746
|
+
const projectsRoot4 = join11(homeDir, ".claude", "projects");
|
|
21747
|
+
if (!existsSync11(projectsRoot4) || !statIsDirectory3(projectsRoot4)) {
|
|
21375
21748
|
return [];
|
|
21376
21749
|
}
|
|
21377
21750
|
const discovered = [];
|
|
21378
|
-
for (const projectEntry of
|
|
21379
|
-
const projectDir =
|
|
21751
|
+
for (const projectEntry of readdirSync10(projectsRoot4).sort()) {
|
|
21752
|
+
const projectDir = join11(projectsRoot4, projectEntry);
|
|
21380
21753
|
if (!statIsDirectory3(projectDir))
|
|
21381
21754
|
continue;
|
|
21382
|
-
for (const sessionEntry of
|
|
21383
|
-
const sessionDir =
|
|
21755
|
+
for (const sessionEntry of readdirSync10(projectDir).sort()) {
|
|
21756
|
+
const sessionDir = join11(projectDir, sessionEntry);
|
|
21384
21757
|
if (!statIsDirectory3(sessionDir))
|
|
21385
21758
|
continue;
|
|
21386
|
-
const workflowsRoot =
|
|
21759
|
+
const workflowsRoot = join11(sessionDir, "subagents", "workflows");
|
|
21387
21760
|
if (!statIsDirectory3(workflowsRoot))
|
|
21388
21761
|
continue;
|
|
21389
|
-
for (const runEntry of
|
|
21762
|
+
for (const runEntry of readdirSync10(workflowsRoot).sort()) {
|
|
21390
21763
|
if (!runEntry.startsWith("wf_"))
|
|
21391
21764
|
continue;
|
|
21392
|
-
const workflowDir =
|
|
21765
|
+
const workflowDir = join11(workflowsRoot, runEntry);
|
|
21393
21766
|
if (!statIsDirectory3(workflowDir))
|
|
21394
21767
|
continue;
|
|
21395
21768
|
discovered.push({
|
|
21396
21769
|
runId: runEntry,
|
|
21397
21770
|
workflowDir,
|
|
21398
21771
|
parentSessionId: sessionEntry,
|
|
21399
|
-
parentSessionPath:
|
|
21772
|
+
parentSessionPath: join11(projectDir, `${sessionEntry}.jsonl`),
|
|
21400
21773
|
projectDir,
|
|
21401
21774
|
mtimeMs: statMtimeMs2(workflowDir)
|
|
21402
21775
|
});
|
|
@@ -21517,7 +21890,7 @@ function readWorkflowLaunch(parentSessionPath, runId) {
|
|
|
21517
21890
|
return;
|
|
21518
21891
|
}
|
|
21519
21892
|
function findGeneratedScriptForRun(homeDir, runId) {
|
|
21520
|
-
const projectsRoot4 =
|
|
21893
|
+
const projectsRoot4 = join11(homeDir, ".claude", "projects");
|
|
21521
21894
|
if (!statIsDirectory3(projectsRoot4))
|
|
21522
21895
|
return;
|
|
21523
21896
|
const stack = [{ path: projectsRoot4, depth: 0 }];
|
|
@@ -21525,8 +21898,8 @@ function findGeneratedScriptForRun(homeDir, runId) {
|
|
|
21525
21898
|
const current = stack.pop();
|
|
21526
21899
|
if (!current || current.depth > 8)
|
|
21527
21900
|
continue;
|
|
21528
|
-
for (const entry of
|
|
21529
|
-
const fullPath =
|
|
21901
|
+
for (const entry of readdirSync10(current.path).sort()) {
|
|
21902
|
+
const fullPath = join11(current.path, entry);
|
|
21530
21903
|
if (statIsDirectory3(fullPath)) {
|
|
21531
21904
|
stack.push({ path: fullPath, depth: current.depth + 1 });
|
|
21532
21905
|
} else if (statIsFile3(fullPath) && entry.endsWith(`${runId}.js`)) {
|
|
@@ -21597,7 +21970,7 @@ function readWorkflowScript(homeDir, launch, runId) {
|
|
|
21597
21970
|
return parsed;
|
|
21598
21971
|
}
|
|
21599
21972
|
function readJournal(workflowDir) {
|
|
21600
|
-
const journalPath =
|
|
21973
|
+
const journalPath = join11(workflowDir, "journal.jsonl");
|
|
21601
21974
|
const events = parseJsonLines2(journalPath);
|
|
21602
21975
|
const startedByAgent = new Map;
|
|
21603
21976
|
const resultByAgent = new Map;
|
|
@@ -21703,11 +22076,11 @@ function statusForAgent(journal, agentId) {
|
|
|
21703
22076
|
return "materialized";
|
|
21704
22077
|
}
|
|
21705
22078
|
function readWorkflowAgents(run2, journal, script) {
|
|
21706
|
-
const files = statIsDirectory3(run2.workflowDir) ?
|
|
22079
|
+
const files = statIsDirectory3(run2.workflowDir) ? readdirSync10(run2.workflowDir).sort() : [];
|
|
21707
22080
|
return files.map((file2) => /^agent-([a-zA-Z0-9]+)\.jsonl$/u.exec(file2)).filter((match) => Boolean(match)).map((match) => {
|
|
21708
22081
|
const agentId = match[1] ?? "unknown";
|
|
21709
|
-
const transcriptPath =
|
|
21710
|
-
const metaPath =
|
|
22082
|
+
const transcriptPath = join11(run2.workflowDir, `agent-${agentId}.jsonl`);
|
|
22083
|
+
const metaPath = join11(run2.workflowDir, `agent-${agentId}.meta.json`);
|
|
21711
22084
|
const events = parseJsonLines2(transcriptPath);
|
|
21712
22085
|
const meta3 = readJsonObject3(metaPath);
|
|
21713
22086
|
const result = resultObjectForAgent(journal, agentId);
|
|
@@ -21769,7 +22142,7 @@ function appendSourceRef2(sourceRefs, seen, sourceRef) {
|
|
|
21769
22142
|
sourceRefs.push(sourceRef);
|
|
21770
22143
|
}
|
|
21771
22144
|
function agentNameForFile(relativeFile, agentId) {
|
|
21772
|
-
return relativeFile ?
|
|
22145
|
+
return relativeFile ? basename10(relativeFile) : `workflow ${agentId.slice(0, 8)}`;
|
|
21773
22146
|
}
|
|
21774
22147
|
function plannedFileEntries(run2) {
|
|
21775
22148
|
const basePath = run2.script?.basePath;
|
|
@@ -21804,7 +22177,7 @@ function buildTopologyForRuns(runs, observedAt) {
|
|
|
21804
22177
|
const workflowGroupId = `claude-workflow:${runSegment}`;
|
|
21805
22178
|
const workflowRefId = sourceRefId3("claude-workflow-dir", run2.workflowDir);
|
|
21806
22179
|
const parentSessionRefId = sourceRefId3("claude-workflow-parent-session", run2.parentSessionPath);
|
|
21807
|
-
const journalPath =
|
|
22180
|
+
const journalPath = join11(run2.workflowDir, "journal.jsonl");
|
|
21808
22181
|
const journalRefId = sourceRefId3("claude-workflow-journal", journalPath);
|
|
21809
22182
|
const scriptRefId = run2.script?.scriptPath ? sourceRefId3("claude-workflow-script", run2.script.scriptPath) : undefined;
|
|
21810
22183
|
appendSourceRef2(sourceRefs, sourceRefIds, {
|
|
@@ -22010,7 +22383,7 @@ function buildTopologyForRuns(runs, observedAt) {
|
|
|
22010
22383
|
};
|
|
22011
22384
|
}
|
|
22012
22385
|
function readClaudeWorkflowTopology(options = {}) {
|
|
22013
|
-
const homeDir = options.homeDir ??
|
|
22386
|
+
const homeDir = options.homeDir ?? homedir11();
|
|
22014
22387
|
const maxRuns = options.maxWorkflowRuns ?? DEFAULT_MAX_WORKFLOW_RUNS;
|
|
22015
22388
|
const sessionId = options.claudeSessionId?.trim();
|
|
22016
22389
|
const runs = discoverWorkflowDirs(homeDir, maxRuns).filter((workflowDir) => !sessionId || workflowDir.parentSessionId === sessionId).map((workflowDir) => readWorkflowRun(homeDir, workflowDir)).filter((run2) => workflowMatchesOptions(run2, options));
|
|
@@ -22018,9 +22391,9 @@ function readClaudeWorkflowTopology(options = {}) {
|
|
|
22018
22391
|
}
|
|
22019
22392
|
|
|
22020
22393
|
// packages/agent-sessions/src/adapters/codex/topology.ts
|
|
22021
|
-
import { existsSync as
|
|
22022
|
-
import { homedir as
|
|
22023
|
-
import { basename as
|
|
22394
|
+
import { existsSync as existsSync12, readdirSync as readdirSync11, readFileSync as readFileSync7, statSync as statSync11 } from "fs";
|
|
22395
|
+
import { homedir as homedir12 } from "os";
|
|
22396
|
+
import { basename as basename11, join as join12 } from "path";
|
|
22024
22397
|
var TOPOLOGY_SCHEMA_VERSION4 = "openscout.observed-harness-topology.v1";
|
|
22025
22398
|
var CODEX_TOPOLOGY_SOURCE = "codex-subagents";
|
|
22026
22399
|
function isObject6(value) {
|
|
@@ -22045,14 +22418,14 @@ function sourceRefId4(kind, value) {
|
|
|
22045
22418
|
}
|
|
22046
22419
|
function statIsDirectory4(path) {
|
|
22047
22420
|
try {
|
|
22048
|
-
return
|
|
22421
|
+
return statSync11(path).isDirectory();
|
|
22049
22422
|
} catch {
|
|
22050
22423
|
return false;
|
|
22051
22424
|
}
|
|
22052
22425
|
}
|
|
22053
22426
|
function statIsFile4(path) {
|
|
22054
22427
|
try {
|
|
22055
|
-
return
|
|
22428
|
+
return statSync11(path).isFile();
|
|
22056
22429
|
} catch {
|
|
22057
22430
|
return false;
|
|
22058
22431
|
}
|
|
@@ -22139,7 +22512,7 @@ function parseTomlKeyValues(raw) {
|
|
|
22139
22512
|
}
|
|
22140
22513
|
function readTomlKeyValues(path) {
|
|
22141
22514
|
try {
|
|
22142
|
-
return parseTomlKeyValues(
|
|
22515
|
+
return parseTomlKeyValues(readFileSync7(path, "utf8"));
|
|
22143
22516
|
} catch {
|
|
22144
22517
|
return null;
|
|
22145
22518
|
}
|
|
@@ -22153,22 +22526,22 @@ function firstString3(record2, keys) {
|
|
|
22153
22526
|
return;
|
|
22154
22527
|
}
|
|
22155
22528
|
function readAgentDefinitions(root, scope) {
|
|
22156
|
-
const agentsDir =
|
|
22157
|
-
if (!
|
|
22529
|
+
const agentsDir = join12(root, ".codex", "agents");
|
|
22530
|
+
if (!existsSync12(agentsDir) || !statIsDirectory4(agentsDir)) {
|
|
22158
22531
|
return { agents: [], sourceRefs: [] };
|
|
22159
22532
|
}
|
|
22160
22533
|
const agents = [];
|
|
22161
22534
|
const sourceRefs = [];
|
|
22162
|
-
for (const entry of
|
|
22535
|
+
for (const entry of readdirSync11(agentsDir).sort()) {
|
|
22163
22536
|
if (!entry.endsWith(".toml"))
|
|
22164
22537
|
continue;
|
|
22165
|
-
const path =
|
|
22538
|
+
const path = join12(agentsDir, entry);
|
|
22166
22539
|
if (!statIsFile4(path))
|
|
22167
22540
|
continue;
|
|
22168
22541
|
const parsed = readTomlKeyValues(path);
|
|
22169
22542
|
if (!parsed)
|
|
22170
22543
|
continue;
|
|
22171
|
-
const name = firstString3(parsed, ["name"]) ??
|
|
22544
|
+
const name = firstString3(parsed, ["name"]) ?? basename11(entry, ".toml");
|
|
22172
22545
|
const description = firstString3(parsed, ["description"]);
|
|
22173
22546
|
const model = firstString3(parsed, ["model"]);
|
|
22174
22547
|
const sandboxMode = firstString3(parsed, ["sandbox_mode", "sandbox"]);
|
|
@@ -22201,8 +22574,8 @@ function readAgentDefinitions(root, scope) {
|
|
|
22201
22574
|
function readProjectAgentsConfig(cwd) {
|
|
22202
22575
|
if (!cwd)
|
|
22203
22576
|
return {};
|
|
22204
|
-
const configPath =
|
|
22205
|
-
if (!
|
|
22577
|
+
const configPath = join12(cwd, ".codex", "config.toml");
|
|
22578
|
+
if (!existsSync12(configPath) || !statIsFile4(configPath)) {
|
|
22206
22579
|
return {};
|
|
22207
22580
|
}
|
|
22208
22581
|
const parsed = readTomlKeyValues(configPath);
|
|
@@ -22261,7 +22634,7 @@ class CodexObservedTopologyTracker {
|
|
|
22261
22634
|
this.threadPath = options.threadPath?.trim() || null;
|
|
22262
22635
|
this.cwd = options.cwd;
|
|
22263
22636
|
this.sessionName = options.sessionName;
|
|
22264
|
-
this.homeDir = options.homeDir ??
|
|
22637
|
+
this.homeDir = options.homeDir ?? homedir12();
|
|
22265
22638
|
this.now = options.now ?? (() => new Date);
|
|
22266
22639
|
}
|
|
22267
22640
|
updateThread(thread) {
|
|
@@ -22462,9 +22835,9 @@ class CodexObservedTopologyTracker {
|
|
|
22462
22835
|
}
|
|
22463
22836
|
|
|
22464
22837
|
// packages/runtime/src/harness-topology/service.ts
|
|
22465
|
-
var DEFAULT_POLL_INTERVAL_MS =
|
|
22838
|
+
var DEFAULT_POLL_INTERVAL_MS = readPositiveIntEnv9("OPENSCOUT_TOPOLOGY_POLL_INTERVAL_MS", 1e4);
|
|
22466
22839
|
var EVENT_BUFFER_LIMIT = 500;
|
|
22467
|
-
function
|
|
22840
|
+
function readPositiveIntEnv9(name, fallback) {
|
|
22468
22841
|
const raw = Number.parseInt(process.env[name] ?? "", 10);
|
|
22469
22842
|
return Number.isFinite(raw) && raw > 0 ? raw : fallback;
|
|
22470
22843
|
}
|
|
@@ -22512,7 +22885,7 @@ function normalizeSources(sources2) {
|
|
|
22512
22885
|
}
|
|
22513
22886
|
function scanObservedHarnessTopologies(options = {}) {
|
|
22514
22887
|
const sources2 = normalizeSources(options.sources);
|
|
22515
|
-
const homeDir = options.homeDir ??
|
|
22888
|
+
const homeDir = options.homeDir ?? homedir13();
|
|
22516
22889
|
const now = options.now;
|
|
22517
22890
|
const topologies = [];
|
|
22518
22891
|
if (sources2.includes("claude")) {
|
|
@@ -25312,7 +25685,7 @@ class BrokerDeliveryStore {
|
|
|
25312
25685
|
|
|
25313
25686
|
// packages/runtime/src/broker-journal.ts
|
|
25314
25687
|
import { appendFile, mkdir, readFile, writeFile } from "fs/promises";
|
|
25315
|
-
import { dirname as
|
|
25688
|
+
import { dirname as dirname5 } from "path";
|
|
25316
25689
|
function cloneSnapshot(snapshot) {
|
|
25317
25690
|
return createRuntimeRegistrySnapshot({
|
|
25318
25691
|
nodes: { ...snapshot.nodes },
|
|
@@ -25465,7 +25838,7 @@ class FileBackedBrokerJournal {
|
|
|
25465
25838
|
}
|
|
25466
25839
|
const retained = this.selectEntriesToAppend(entries);
|
|
25467
25840
|
this.writeQueue = this.writeQueue.then(async () => {
|
|
25468
|
-
await mkdir(
|
|
25841
|
+
await mkdir(dirname5(this.filePath), { recursive: true });
|
|
25469
25842
|
if (retained.length === 0) {
|
|
25470
25843
|
return;
|
|
25471
25844
|
}
|
|
@@ -25522,7 +25895,7 @@ class FileBackedBrokerJournal {
|
|
|
25522
25895
|
return [...this.state.invocationDispatchJobs.values()].filter((job) => !options.state || job.state === options.state).sort((left, right) => left.createdAt - right.createdAt).slice(0, limit);
|
|
25523
25896
|
}
|
|
25524
25897
|
async rewriteEntries(entries) {
|
|
25525
|
-
await mkdir(
|
|
25898
|
+
await mkdir(dirname5(this.filePath), { recursive: true });
|
|
25526
25899
|
const payload = entries.length > 0 ? `${entries.map((entry) => JSON.stringify(entry)).join(`
|
|
25527
25900
|
`)}
|
|
25528
25901
|
` : "";
|
|
@@ -26038,6 +26411,7 @@ class BrokerReadCursorStore {
|
|
|
26038
26411
|
}
|
|
26039
26412
|
|
|
26040
26413
|
// packages/runtime/src/broker-work-item-store.ts
|
|
26414
|
+
import { createHash as createHash2 } from "crypto";
|
|
26041
26415
|
function metadataStringValue(metadata, key) {
|
|
26042
26416
|
const value = metadata?.[key];
|
|
26043
26417
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -26098,11 +26472,34 @@ function metadataContainsDeliveryWorkItemValues(existing, expected) {
|
|
|
26098
26472
|
}
|
|
26099
26473
|
return true;
|
|
26100
26474
|
}
|
|
26475
|
+
function deliveryWorkItemFingerprint(record2) {
|
|
26476
|
+
const metadata = { ...record2.metadata ?? {} };
|
|
26477
|
+
delete metadata.deliveryWorkItemFingerprint;
|
|
26478
|
+
const identity2 = normalizeComparableDeliveryValue({
|
|
26479
|
+
title: record2.title,
|
|
26480
|
+
summary: record2.summary,
|
|
26481
|
+
acceptanceState: record2.acceptanceState,
|
|
26482
|
+
createdById: record2.createdById,
|
|
26483
|
+
ownerId: record2.ownerId,
|
|
26484
|
+
nextMoveOwnerId: record2.nextMoveOwnerId,
|
|
26485
|
+
conversationId: record2.conversationId,
|
|
26486
|
+
parentId: record2.parentId,
|
|
26487
|
+
priority: record2.priority,
|
|
26488
|
+
labels: record2.labels,
|
|
26489
|
+
requestedById: record2.kind === "work_item" ? record2.requestedById : undefined,
|
|
26490
|
+
metadata
|
|
26491
|
+
});
|
|
26492
|
+
return createHash2("sha256").update(JSON.stringify(identity2)).digest("hex");
|
|
26493
|
+
}
|
|
26101
26494
|
function existingDeliveryWorkItemMatches(existing, proposed) {
|
|
26102
26495
|
if (existing.kind !== "work_item" || proposed.kind !== "work_item") {
|
|
26103
26496
|
return false;
|
|
26104
26497
|
}
|
|
26105
|
-
|
|
26498
|
+
const existingFingerprint = metadataStringValue(existing.metadata, "deliveryWorkItemFingerprint");
|
|
26499
|
+
if (existingFingerprint) {
|
|
26500
|
+
return existingFingerprint === deliveryWorkItemFingerprint(proposed);
|
|
26501
|
+
}
|
|
26502
|
+
return existing.title === proposed.title && (existing.summary ?? "") === (proposed.summary ?? "") && existing.createdById === proposed.createdById && existing.conversationId === proposed.conversationId && existing.parentId === proposed.parentId && existing.priority === proposed.priority && sameDeliveryWorkItemLabels(existing.labels, proposed.labels) && existing.requestedById === proposed.requestedById && metadataContainsDeliveryWorkItemValues(existing.metadata, proposed.metadata);
|
|
26106
26503
|
}
|
|
26107
26504
|
function invocationCollaborationRecordId(invocation) {
|
|
26108
26505
|
const nested = invocation.context?.["collaboration"];
|
|
@@ -26180,12 +26577,16 @@ class BrokerWorkItemStore {
|
|
|
26180
26577
|
return;
|
|
26181
26578
|
}
|
|
26182
26579
|
const now = flight.completedAt ?? Date.now();
|
|
26183
|
-
const
|
|
26184
|
-
const
|
|
26580
|
+
const requiresReview = flight.state === "completed" && record2.acceptanceState !== "none";
|
|
26581
|
+
const nextState = flight.state === "completed" ? requiresReview ? "review" : "done" : flight.state === "cancelled" ? "cancelled" : "waiting";
|
|
26582
|
+
const nextEventKind = flight.state === "completed" ? requiresReview ? "review_requested" : "done" : flight.state === "cancelled" ? "cancelled" : "waiting";
|
|
26583
|
+
const nextMoveOwnerId = requiresReview ? record2.requestedById ?? record2.createdById : flight.state === "failed" ? record2.requestedById ?? record2.ownerId : record2.nextMoveOwnerId;
|
|
26185
26584
|
const summary = compactWorkSummary(output) ?? compactWorkSummary(flight.output) ?? compactWorkSummary(flight.error) ?? compactWorkSummary(flight.summary) ?? `${flight.targetAgentId} completed.`;
|
|
26186
26585
|
const nextRecord = {
|
|
26187
26586
|
...record2,
|
|
26188
26587
|
state: nextState,
|
|
26588
|
+
acceptanceState: requiresReview ? "pending" : record2.acceptanceState,
|
|
26589
|
+
nextMoveOwnerId,
|
|
26189
26590
|
summary: record2.summary ?? summary,
|
|
26190
26591
|
updatedAt: now,
|
|
26191
26592
|
progress: {
|
|
@@ -26194,7 +26595,19 @@ class BrokerWorkItemStore {
|
|
|
26194
26595
|
completedSteps: flight.state === "completed" ? 1 : record2.progress?.completedSteps,
|
|
26195
26596
|
totalSteps: flight.state === "completed" ? 1 : record2.progress?.totalSteps
|
|
26196
26597
|
},
|
|
26197
|
-
|
|
26598
|
+
reviewRequestedAt: requiresReview ? now : record2.reviewRequestedAt,
|
|
26599
|
+
completedAt: nextState === "done" || nextState === "cancelled" ? record2.completedAt ?? now : undefined,
|
|
26600
|
+
...flight.state === "failed" ? {
|
|
26601
|
+
waitingOn: {
|
|
26602
|
+
kind: "actor",
|
|
26603
|
+
label: "Decide whether to retry the failed execution",
|
|
26604
|
+
...nextMoveOwnerId ? { targetId: nextMoveOwnerId } : {},
|
|
26605
|
+
metadata: {
|
|
26606
|
+
invocationId: invocation.id,
|
|
26607
|
+
flightId: flight.id
|
|
26608
|
+
}
|
|
26609
|
+
}
|
|
26610
|
+
} : { waitingOn: undefined },
|
|
26198
26611
|
metadata: {
|
|
26199
26612
|
...record2.metadata ?? {},
|
|
26200
26613
|
lastInvocationId: invocation.id,
|
|
@@ -26245,7 +26658,7 @@ class BrokerWorkItemStore {
|
|
|
26245
26658
|
const source = metadataStringValue(input.payload.invocationMetadata, "source") || metadataStringValue(input.payload.messageMetadata, "source") || "broker-delivery";
|
|
26246
26659
|
const recordId = workItem.id?.trim() || input.payload.collaborationRecordId?.trim() || this.options.createId("work");
|
|
26247
26660
|
const labels = mergeScoutLabels(input.payload.labels, workItem.labels);
|
|
26248
|
-
|
|
26661
|
+
const record2 = {
|
|
26249
26662
|
id: recordId,
|
|
26250
26663
|
kind: "work_item",
|
|
26251
26664
|
state: "working",
|
|
@@ -26269,6 +26682,11 @@ class BrokerWorkItemStore {
|
|
|
26269
26682
|
deliveryRequestId: input.requestId
|
|
26270
26683
|
}
|
|
26271
26684
|
};
|
|
26685
|
+
record2.metadata = {
|
|
26686
|
+
...record2.metadata ?? {},
|
|
26687
|
+
deliveryWorkItemFingerprint: deliveryWorkItemFingerprint(record2)
|
|
26688
|
+
};
|
|
26689
|
+
return record2;
|
|
26272
26690
|
}
|
|
26273
26691
|
buildDeliveryWorkItemCreatedEvent(record2, input) {
|
|
26274
26692
|
return {
|
|
@@ -26289,15 +26707,15 @@ class BrokerWorkItemStore {
|
|
|
26289
26707
|
|
|
26290
26708
|
// packages/runtime/src/local-agents.ts
|
|
26291
26709
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
26292
|
-
import { existsSync as
|
|
26710
|
+
import { existsSync as existsSync29, readFileSync as readFileSync15 } from "fs";
|
|
26293
26711
|
import { mkdir as mkdir8, rm as rm4, stat as stat6, writeFile as writeFile8 } from "fs/promises";
|
|
26294
|
-
import { basename as
|
|
26712
|
+
import { basename as basename16, dirname as dirname18, join as join30, resolve as resolve12 } from "path";
|
|
26295
26713
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
26296
26714
|
|
|
26297
26715
|
// packages/agent-sessions/src/codex-executable.ts
|
|
26298
26716
|
import { execFileSync } from "child_process";
|
|
26299
26717
|
import { accessSync, constants } from "fs";
|
|
26300
|
-
import { delimiter, join as
|
|
26718
|
+
import { delimiter, join as join13 } from "path";
|
|
26301
26719
|
function isExecutable(filePath) {
|
|
26302
26720
|
if (!filePath)
|
|
26303
26721
|
return false;
|
|
@@ -26341,11 +26759,11 @@ function codexAppBundleCandidates(env) {
|
|
|
26341
26759
|
const appNames = ["Codex.app", "ChatGPT.app"];
|
|
26342
26760
|
const candidates = appNames.flatMap((appName) => [
|
|
26343
26761
|
{
|
|
26344
|
-
path:
|
|
26762
|
+
path: join13("/Applications", appName, "Contents", "Resources", "codex"),
|
|
26345
26763
|
source: "codex_app_bundle"
|
|
26346
26764
|
},
|
|
26347
26765
|
{
|
|
26348
|
-
path:
|
|
26766
|
+
path: join13(env.HOME ?? "", "Applications", appName, "Contents", "Resources", "codex"),
|
|
26349
26767
|
source: "codex_app_bundle"
|
|
26350
26768
|
}
|
|
26351
26769
|
]);
|
|
@@ -26353,7 +26771,7 @@ function codexAppBundleCandidates(env) {
|
|
|
26353
26771
|
}
|
|
26354
26772
|
function pathCandidates(env) {
|
|
26355
26773
|
return (env.PATH ?? "").split(delimiter).filter(Boolean).map((directory) => ({
|
|
26356
|
-
path:
|
|
26774
|
+
path: join13(directory, "codex"),
|
|
26357
26775
|
source: "path"
|
|
26358
26776
|
}));
|
|
26359
26777
|
}
|
|
@@ -26364,7 +26782,7 @@ function commonCandidates(env) {
|
|
|
26364
26782
|
"/opt/homebrew/bin",
|
|
26365
26783
|
"/usr/local/bin"
|
|
26366
26784
|
].filter(Boolean).map((directory) => ({
|
|
26367
|
-
path:
|
|
26785
|
+
path: join13(directory, "codex"),
|
|
26368
26786
|
source: "common"
|
|
26369
26787
|
}));
|
|
26370
26788
|
}
|
|
@@ -26490,9 +26908,9 @@ function isDispatchStalledError(error48) {
|
|
|
26490
26908
|
}
|
|
26491
26909
|
// packages/runtime/src/repo-service/process.ts
|
|
26492
26910
|
import { spawn as spawn2 } from "child_process";
|
|
26493
|
-
import { existsSync as
|
|
26911
|
+
import { existsSync as existsSync13 } from "fs";
|
|
26494
26912
|
import { Socket as Socket2 } from "net";
|
|
26495
|
-
import { dirname as
|
|
26913
|
+
import { dirname as dirname6, resolve } from "path";
|
|
26496
26914
|
import { fileURLToPath } from "url";
|
|
26497
26915
|
var REPO_SERVICE_MAX_BUFFER = 2 * 1024 * 1024;
|
|
26498
26916
|
var CAPABILITIES_SCHEMA2 = "openscout.probe.capabilities/v1";
|
|
@@ -26521,7 +26939,7 @@ function resolveRepoServiceCommand(subcommand) {
|
|
|
26521
26939
|
if (explicit) {
|
|
26522
26940
|
return { command: explicit, args: [subcommand], subcommand };
|
|
26523
26941
|
}
|
|
26524
|
-
const moduleDir =
|
|
26942
|
+
const moduleDir = dirname6(fileURLToPath(import.meta.url));
|
|
26525
26943
|
const candidateRoots = [resolve(moduleDir, "../../../.."), process.cwd()];
|
|
26526
26944
|
const seen = new Set;
|
|
26527
26945
|
for (const root of candidateRoots) {
|
|
@@ -26529,7 +26947,7 @@ function resolveRepoServiceCommand(subcommand) {
|
|
|
26529
26947
|
continue;
|
|
26530
26948
|
seen.add(root);
|
|
26531
26949
|
const manifestPath = resolve(root, "crates", "openscout-repo-service", "Cargo.toml");
|
|
26532
|
-
if (!
|
|
26950
|
+
if (!existsSync13(manifestPath))
|
|
26533
26951
|
continue;
|
|
26534
26952
|
return {
|
|
26535
26953
|
command: process.env.CARGO?.trim() || "cargo",
|
|
@@ -26645,7 +27063,7 @@ class RepoServiceSocketClient {
|
|
|
26645
27063
|
return { state: "spawn" };
|
|
26646
27064
|
}
|
|
26647
27065
|
const socketPath = resolveScoutdProbesSocketPath(this.env);
|
|
26648
|
-
const socketExists =
|
|
27066
|
+
const socketExists = existsSync13(socketPath);
|
|
26649
27067
|
if (!socketExists) {
|
|
26650
27068
|
this.capabilities = null;
|
|
26651
27069
|
this.lastError = null;
|
|
@@ -26931,8 +27349,8 @@ async function requestJsonWithBun2(connect, socketPath, payload, timeoutMs) {
|
|
|
26931
27349
|
}
|
|
26932
27350
|
|
|
26933
27351
|
// packages/runtime/src/system-probes/git-build-info.ts
|
|
26934
|
-
import { existsSync as
|
|
26935
|
-
import { dirname as
|
|
27352
|
+
import { existsSync as existsSync14, realpathSync, statSync as statSync12 } from "fs";
|
|
27353
|
+
import { dirname as dirname7, resolve as resolve2 } from "path";
|
|
26936
27354
|
var staticMetadataByRepo = new Map;
|
|
26937
27355
|
function realpathOrResolved(path) {
|
|
26938
27356
|
try {
|
|
@@ -26944,8 +27362,8 @@ function realpathOrResolved(path) {
|
|
|
26944
27362
|
function directoryOrParent(path) {
|
|
26945
27363
|
const resolved = resolve2(path);
|
|
26946
27364
|
try {
|
|
26947
|
-
const stat2 =
|
|
26948
|
-
return stat2.isDirectory() ? resolved :
|
|
27365
|
+
const stat2 = statSync12(resolved);
|
|
27366
|
+
return stat2.isDirectory() ? resolved : dirname7(resolved);
|
|
26949
27367
|
} catch {
|
|
26950
27368
|
return resolved;
|
|
26951
27369
|
}
|
|
@@ -26953,10 +27371,10 @@ function directoryOrParent(path) {
|
|
|
26953
27371
|
function canonicalRepoRoot(rawPath) {
|
|
26954
27372
|
let current = realpathOrResolved(directoryOrParent(rawPath));
|
|
26955
27373
|
while (true) {
|
|
26956
|
-
if (
|
|
27374
|
+
if (existsSync14(resolve2(current, ".git"))) {
|
|
26957
27375
|
return realpathOrResolved(current);
|
|
26958
27376
|
}
|
|
26959
|
-
const parent =
|
|
27377
|
+
const parent = dirname7(current);
|
|
26960
27378
|
if (parent === current) {
|
|
26961
27379
|
return realpathOrResolved(directoryOrParent(rawPath));
|
|
26962
27380
|
}
|
|
@@ -27576,8 +27994,8 @@ var tailscaleStatusProbe = defineProbe({
|
|
|
27576
27994
|
});
|
|
27577
27995
|
|
|
27578
27996
|
// packages/runtime/src/system-probes/tmux.ts
|
|
27579
|
-
import { homedir as
|
|
27580
|
-
import { join as
|
|
27997
|
+
import { homedir as homedir14 } from "os";
|
|
27998
|
+
import { join as join14 } from "path";
|
|
27581
27999
|
var TMUX_TTL_MS = 5000;
|
|
27582
28000
|
var TMUX_TIMEOUT_MS = 1500;
|
|
27583
28001
|
var ZELLIJ_TIMEOUT_MS = 1500;
|
|
@@ -27628,7 +28046,7 @@ function tmuxSocketArgs(key) {
|
|
|
27628
28046
|
return key === "default" ? [] : ["-S", key];
|
|
27629
28047
|
}
|
|
27630
28048
|
function zellijSocketDirFromEnv(env) {
|
|
27631
|
-
return env.ZELLIJ_SOCKET_DIR?.trim() || env.OPENSCOUT_ZELLIJ_SOCKET_DIR?.trim() ||
|
|
28049
|
+
return env.ZELLIJ_SOCKET_DIR?.trim() || env.OPENSCOUT_ZELLIJ_SOCKET_DIR?.trim() || join14(env.HOME?.trim() || homedir14(), ".openscout", "zellij-sockets");
|
|
27632
28050
|
}
|
|
27633
28051
|
function zellijSocketKey(input) {
|
|
27634
28052
|
if (typeof input === "string")
|
|
@@ -27837,15 +28255,15 @@ async function captureTmuxPane(target, input) {
|
|
|
27837
28255
|
// packages/runtime/src/system-probes/sessions.ts
|
|
27838
28256
|
import { createReadStream } from "fs";
|
|
27839
28257
|
import { readdir, stat as stat2 } from "fs/promises";
|
|
27840
|
-
import { homedir as
|
|
27841
|
-
import { basename as
|
|
28258
|
+
import { homedir as homedir15 } from "os";
|
|
28259
|
+
import { basename as basename12, dirname as dirname8, join as join15, resolve as resolve3 } from "path";
|
|
27842
28260
|
import { createInterface } from "readline";
|
|
27843
28261
|
function positiveInteger2(value, fallback, max) {
|
|
27844
28262
|
return Number.isFinite(value) && value > 0 ? Math.min(max, Math.floor(value)) : fallback;
|
|
27845
28263
|
}
|
|
27846
28264
|
function normalizeScanKey(input) {
|
|
27847
28265
|
return {
|
|
27848
|
-
home: resolve3(input.home?.trim() ||
|
|
28266
|
+
home: resolve3(input.home?.trim() || homedir15()),
|
|
27849
28267
|
workspaceRoot: input.workspaceRoot?.trim() ? resolve3(input.workspaceRoot) : null,
|
|
27850
28268
|
maxAgeDays: positiveInteger2(input.maxAgeDays, 14, 3650),
|
|
27851
28269
|
limit: positiveInteger2(input.limit, 250, 1e4)
|
|
@@ -27869,7 +28287,7 @@ function extractProjectName(filePath) {
|
|
|
27869
28287
|
const claudeMatch = filePath.match(/\.claude\/projects\/[^/]*-dev-([^/]+)/);
|
|
27870
28288
|
if (claudeMatch?.[1])
|
|
27871
28289
|
return claudeMatch[1];
|
|
27872
|
-
return
|
|
28290
|
+
return basename12(dirname8(filePath)) || "unknown";
|
|
27873
28291
|
}
|
|
27874
28292
|
function detectAgent(filePath, fallback = "unknown") {
|
|
27875
28293
|
if (filePath.includes(".claude"))
|
|
@@ -27901,7 +28319,7 @@ async function scanJsonlFiles(input) {
|
|
|
27901
28319
|
for (const entry of entries) {
|
|
27902
28320
|
if (input.signal.aborted || out.length >= input.cap)
|
|
27903
28321
|
return;
|
|
27904
|
-
const filePath =
|
|
28322
|
+
const filePath = join15(directory, entry.name);
|
|
27905
28323
|
if (entry.isDirectory()) {
|
|
27906
28324
|
if (input.skipSubagents && entry.name === "subagents")
|
|
27907
28325
|
continue;
|
|
@@ -27932,9 +28350,9 @@ async function scanSessionFilesLocal(input, ctx) {
|
|
|
27932
28350
|
const normalized = normalizeScanKey(input);
|
|
27933
28351
|
const cutoffMs = Date.now() - normalized.maxAgeDays * 24 * 60 * 60000;
|
|
27934
28352
|
const roots = [
|
|
27935
|
-
{ root:
|
|
27936
|
-
{ root:
|
|
27937
|
-
{ root:
|
|
28353
|
+
{ root: join15(normalized.home, ".claude", "projects"), agent: "claude-code", maxDepth: 8, skipSubagents: true },
|
|
28354
|
+
{ root: join15(normalized.home, ".codex"), agent: "codex", maxDepth: 8, skipSubagents: true },
|
|
28355
|
+
{ root: join15(normalized.home, ".openai-codex"), agent: "codex", maxDepth: 8, skipSubagents: true }
|
|
27938
28356
|
];
|
|
27939
28357
|
const results = [];
|
|
27940
28358
|
const cap = Math.max(normalized.limit * 4, normalized.limit + 100);
|
|
@@ -28037,7 +28455,7 @@ var sessionsSearchProbe = defineProbeFamily({
|
|
|
28037
28455
|
run: (key, ctx) => searchSessionFilesLocal(parseKey(key), ctx)
|
|
28038
28456
|
});
|
|
28039
28457
|
// packages/runtime/src/system-probes/cert-status.ts
|
|
28040
|
-
import { existsSync as
|
|
28458
|
+
import { existsSync as existsSync15, realpathSync as realpathSync2 } from "fs";
|
|
28041
28459
|
import { resolve as resolve4 } from "path";
|
|
28042
28460
|
function canonicalCertPath(path) {
|
|
28043
28461
|
try {
|
|
@@ -28058,7 +28476,7 @@ var certStatusProbe = defineProbeFamily({
|
|
|
28058
28476
|
maxConcurrentKeys: 2,
|
|
28059
28477
|
normalizeKey: canonicalCertPath,
|
|
28060
28478
|
run: async (certPath, ctx) => {
|
|
28061
|
-
if (!
|
|
28479
|
+
if (!existsSync15(certPath)) {
|
|
28062
28480
|
return {
|
|
28063
28481
|
certPath,
|
|
28064
28482
|
exists: false,
|
|
@@ -29052,14 +29470,14 @@ class SessionRegistry {
|
|
|
29052
29470
|
}
|
|
29053
29471
|
}
|
|
29054
29472
|
// packages/agent-sessions/src/adapters/grok-acp/adapter.ts
|
|
29055
|
-
import { existsSync as
|
|
29056
|
-
import { homedir as
|
|
29057
|
-
import { join as
|
|
29473
|
+
import { existsSync as existsSync16 } from "fs";
|
|
29474
|
+
import { homedir as homedir16 } from "os";
|
|
29475
|
+
import { join as join16 } from "path";
|
|
29058
29476
|
|
|
29059
29477
|
// packages/agent-sessions/src/adapters/acp/adapter.ts
|
|
29060
29478
|
import { spawn as spawn3 } from "child_process";
|
|
29061
29479
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
29062
|
-
import { dirname as
|
|
29480
|
+
import { dirname as dirname9, isAbsolute, relative as relative5, resolve as resolve5 } from "path";
|
|
29063
29481
|
import { pathToFileURL } from "url";
|
|
29064
29482
|
var DEFAULT_STARTUP_TIMEOUT_MS = 30000;
|
|
29065
29483
|
var DEFAULT_REQUEST_TIMEOUT_MS = 60000;
|
|
@@ -29830,7 +30248,7 @@ ${text}`
|
|
|
29830
30248
|
return;
|
|
29831
30249
|
}
|
|
29832
30250
|
const filePath = this.resolveAllowedPath(requestedPath);
|
|
29833
|
-
await mkdir2(
|
|
30251
|
+
await mkdir2(dirname9(filePath), { recursive: true });
|
|
29834
30252
|
await writeFile2(filePath, params.content, "utf8");
|
|
29835
30253
|
this.writeResult(message.id, {});
|
|
29836
30254
|
}
|
|
@@ -30000,8 +30418,8 @@ function defaultGrokCommand(env) {
|
|
|
30000
30418
|
if (override) {
|
|
30001
30419
|
return override;
|
|
30002
30420
|
}
|
|
30003
|
-
const installed =
|
|
30004
|
-
return
|
|
30421
|
+
const installed = join16(homedir16(), ".grok", "bin", "grok");
|
|
30422
|
+
return existsSync16(installed) ? installed : "grok";
|
|
30005
30423
|
}
|
|
30006
30424
|
function isRecord4(value) {
|
|
30007
30425
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -30062,6 +30480,66 @@ var createAdapter = (config2) => {
|
|
|
30062
30480
|
}
|
|
30063
30481
|
});
|
|
30064
30482
|
};
|
|
30483
|
+
// packages/agent-sessions/src/adapters/kimi-acp/adapter.ts
|
|
30484
|
+
import { existsSync as existsSync17 } from "fs";
|
|
30485
|
+
import { homedir as homedir17 } from "os";
|
|
30486
|
+
import { join as join17 } from "path";
|
|
30487
|
+
var DEFAULT_KIMI_ARGS = ["acp"];
|
|
30488
|
+
var DEFAULT_KIMI_STARTUP_TIMEOUT_MS = 60000;
|
|
30489
|
+
var KIMI_ACP_ADAPTER_TYPE = "kimi-acp";
|
|
30490
|
+
function isRecord5(value) {
|
|
30491
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
30492
|
+
}
|
|
30493
|
+
function stringValue9(value) {
|
|
30494
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
30495
|
+
}
|
|
30496
|
+
function stringArray4(value) {
|
|
30497
|
+
if (!Array.isArray(value)) {
|
|
30498
|
+
return null;
|
|
30499
|
+
}
|
|
30500
|
+
const entries = value.filter((entry) => typeof entry === "string");
|
|
30501
|
+
return entries.length === value.length ? entries : null;
|
|
30502
|
+
}
|
|
30503
|
+
function firstNonEmptyString2(...values) {
|
|
30504
|
+
for (const value of values) {
|
|
30505
|
+
const trimmed = value?.trim();
|
|
30506
|
+
if (trimmed) {
|
|
30507
|
+
return trimmed;
|
|
30508
|
+
}
|
|
30509
|
+
}
|
|
30510
|
+
return null;
|
|
30511
|
+
}
|
|
30512
|
+
function defaultKimiCommand(env) {
|
|
30513
|
+
const override = firstNonEmptyString2(env?.KIMI_CLI_BIN, process.env.KIMI_CLI_BIN);
|
|
30514
|
+
if (override) {
|
|
30515
|
+
return override;
|
|
30516
|
+
}
|
|
30517
|
+
const installedCandidates = [
|
|
30518
|
+
join17(homedir17(), ".kimi-code", "bin", "kimi"),
|
|
30519
|
+
join17(homedir17(), ".local", "bin", "kimi")
|
|
30520
|
+
];
|
|
30521
|
+
return installedCandidates.find((candidate) => existsSync17(candidate)) ?? "kimi";
|
|
30522
|
+
}
|
|
30523
|
+
var createAdapter2 = (config2) => {
|
|
30524
|
+
const rawOptions = isRecord5(config2.options) ? config2.options : {};
|
|
30525
|
+
const command = stringValue9(rawOptions.command) ?? defaultKimiCommand(config2.env);
|
|
30526
|
+
const args = stringArray4(rawOptions.args) ?? DEFAULT_KIMI_ARGS;
|
|
30527
|
+
const authMethodPreference = stringArray4(rawOptions.authMethodPreference) ?? ["login"];
|
|
30528
|
+
return new AcpAdapter({
|
|
30529
|
+
...config2,
|
|
30530
|
+
options: {
|
|
30531
|
+
clientName: "openscout",
|
|
30532
|
+
clientTitle: "OpenScout",
|
|
30533
|
+
...rawOptions,
|
|
30534
|
+
adapterType: KIMI_ACP_ADAPTER_TYPE,
|
|
30535
|
+
command,
|
|
30536
|
+
args,
|
|
30537
|
+
startupTimeoutMs: typeof rawOptions.startupTimeoutMs === "number" ? rawOptions.startupTimeoutMs : DEFAULT_KIMI_STARTUP_TIMEOUT_MS,
|
|
30538
|
+
requireAuth: typeof rawOptions.requireAuth === "boolean" ? rawOptions.requireAuth : true,
|
|
30539
|
+
authMethodPreference
|
|
30540
|
+
}
|
|
30541
|
+
});
|
|
30542
|
+
};
|
|
30065
30543
|
// packages/agent-sessions/src/runtime/process.ts
|
|
30066
30544
|
async function spawnHarnessProcess(command, args, options) {
|
|
30067
30545
|
if (typeof Bun !== "undefined") {
|
|
@@ -31193,7 +31671,7 @@ class PiAdapter extends BaseAdapter {
|
|
|
31193
31671
|
});
|
|
31194
31672
|
}
|
|
31195
31673
|
}
|
|
31196
|
-
var
|
|
31674
|
+
var createAdapter3 = (config2) => new PiAdapter(config2);
|
|
31197
31675
|
// packages/runtime/src/requester-timeout.ts
|
|
31198
31676
|
class RequesterWaitTimeoutError extends Error {
|
|
31199
31677
|
code = "REQUESTER_WAIT_TIMEOUT";
|
|
@@ -31210,32 +31688,32 @@ function isRequesterWaitTimeoutError(error48) {
|
|
|
31210
31688
|
return error48 instanceof RequesterWaitTimeoutError || Boolean(error48) && typeof error48 === "object" && error48.code === "REQUESTER_WAIT_TIMEOUT" && typeof error48.timeoutMs === "number";
|
|
31211
31689
|
}
|
|
31212
31690
|
|
|
31213
|
-
// packages/runtime/src/
|
|
31214
|
-
var
|
|
31215
|
-
function completedText(snapshot) {
|
|
31691
|
+
// packages/runtime/src/acp-agent-invocation.ts
|
|
31692
|
+
var DEFAULT_ACP_HARD_CEILING_MS = 30 * 60000;
|
|
31693
|
+
function completedText(snapshot, label) {
|
|
31216
31694
|
const turn = snapshot?.turns.at(-1);
|
|
31217
31695
|
if (!turn) {
|
|
31218
|
-
return
|
|
31696
|
+
return `The ${label} session completed without an observable turn.`;
|
|
31219
31697
|
}
|
|
31220
31698
|
const text = turn.blocks.map(({ block }) => block.type === "text" ? block.text.trim() : "").filter(Boolean).join(`
|
|
31221
31699
|
|
|
31222
31700
|
`);
|
|
31223
|
-
return text ||
|
|
31701
|
+
return text || `The ${label} session completed without a text reply.`;
|
|
31224
31702
|
}
|
|
31225
|
-
async function
|
|
31703
|
+
async function invokeAcpAgent(options) {
|
|
31226
31704
|
const registry3 = new SessionRegistry({
|
|
31227
31705
|
adapters: {
|
|
31228
|
-
|
|
31706
|
+
[options.adapterType]: options.createAdapter
|
|
31229
31707
|
}
|
|
31230
31708
|
});
|
|
31231
|
-
const session = await registry3.createSession(
|
|
31709
|
+
const session = await registry3.createSession(options.adapterType, {
|
|
31232
31710
|
sessionId: options.sessionId,
|
|
31233
|
-
name: options.name ??
|
|
31711
|
+
name: options.name ?? options.label,
|
|
31234
31712
|
cwd: options.cwd
|
|
31235
31713
|
});
|
|
31236
|
-
const turn =
|
|
31714
|
+
const turn = runAcpTurn(registry3, session.id, options);
|
|
31237
31715
|
try {
|
|
31238
|
-
return await waitForRequesterResult(turn, options.timeoutMs,
|
|
31716
|
+
return await waitForRequesterResult(turn, options.timeoutMs, options.label);
|
|
31239
31717
|
} catch (error48) {
|
|
31240
31718
|
if (isRequesterWaitTimeoutError(error48)) {
|
|
31241
31719
|
turn.catch(() => {
|
|
@@ -31245,52 +31723,48 @@ async function invokeGrokAcpAgent(options) {
|
|
|
31245
31723
|
throw error48;
|
|
31246
31724
|
}
|
|
31247
31725
|
}
|
|
31248
|
-
async function
|
|
31726
|
+
async function runAcpTurn(registry3, sessionId, options) {
|
|
31249
31727
|
try {
|
|
31250
31728
|
await new Promise((resolve6, reject) => {
|
|
31251
31729
|
let unsubscribe = () => {};
|
|
31252
31730
|
let settled = false;
|
|
31731
|
+
const hardCeilingMs = options.hardCeilingMs ?? DEFAULT_ACP_HARD_CEILING_MS;
|
|
31253
31732
|
const finish = (error48) => {
|
|
31254
31733
|
if (settled)
|
|
31255
31734
|
return;
|
|
31256
31735
|
settled = true;
|
|
31257
31736
|
clearTimeout(hardCeiling);
|
|
31258
31737
|
unsubscribe();
|
|
31259
|
-
if (error48)
|
|
31738
|
+
if (error48)
|
|
31260
31739
|
reject(error48);
|
|
31261
|
-
|
|
31740
|
+
else
|
|
31262
31741
|
resolve6();
|
|
31263
|
-
}
|
|
31264
31742
|
};
|
|
31265
31743
|
const hardCeiling = setTimeout(() => {
|
|
31266
|
-
finish(new Error(
|
|
31267
|
-
},
|
|
31744
|
+
finish(new Error(`${options.label} exceeded the ${hardCeilingMs}ms hard ceiling.`));
|
|
31745
|
+
}, hardCeilingMs);
|
|
31268
31746
|
hardCeiling.unref?.();
|
|
31269
31747
|
unsubscribe = registry3.onEvent(({ event }) => {
|
|
31270
|
-
if ("sessionId" in event && event.sessionId !== sessionId)
|
|
31748
|
+
if ("sessionId" in event && event.sessionId !== sessionId)
|
|
31271
31749
|
return;
|
|
31272
|
-
}
|
|
31273
31750
|
if (event.event === "turn:end") {
|
|
31274
31751
|
finish();
|
|
31275
31752
|
return;
|
|
31276
31753
|
}
|
|
31277
31754
|
if (event.event === "turn:error") {
|
|
31278
|
-
finish(new Error(event.message ||
|
|
31755
|
+
finish(new Error(event.message || `${options.label} turn failed.`));
|
|
31279
31756
|
}
|
|
31280
31757
|
});
|
|
31281
|
-
Promise.resolve(registry3.send({
|
|
31282
|
-
sessionId,
|
|
31283
|
-
text: prompt
|
|
31284
|
-
})).catch((error48) => {
|
|
31758
|
+
Promise.resolve(registry3.send({ sessionId, text: options.prompt })).catch((error48) => {
|
|
31285
31759
|
finish(error48 instanceof Error ? error48 : new Error(String(error48)));
|
|
31286
31760
|
});
|
|
31287
31761
|
});
|
|
31288
31762
|
const snapshot = registry3.getSessionSnapshot(sessionId);
|
|
31289
31763
|
return {
|
|
31290
|
-
output: completedText(snapshot),
|
|
31764
|
+
output: completedText(snapshot, options.label),
|
|
31291
31765
|
sessionId,
|
|
31292
31766
|
metadata: {
|
|
31293
|
-
adapterType:
|
|
31767
|
+
adapterType: options.adapterType,
|
|
31294
31768
|
providerMeta: snapshot?.session.providerMeta
|
|
31295
31769
|
}
|
|
31296
31770
|
};
|
|
@@ -31308,9 +31782,8 @@ function requesterTimeoutMs(timeoutMs) {
|
|
|
31308
31782
|
}
|
|
31309
31783
|
async function waitForRequesterResult(promise2, timeoutMs, label) {
|
|
31310
31784
|
const effectiveTimeoutMs = requesterTimeoutMs(timeoutMs);
|
|
31311
|
-
if (effectiveTimeoutMs === null)
|
|
31785
|
+
if (effectiveTimeoutMs === null)
|
|
31312
31786
|
return await promise2;
|
|
31313
|
-
}
|
|
31314
31787
|
let timer = null;
|
|
31315
31788
|
const timeout = new Promise((_resolve, reject) => {
|
|
31316
31789
|
timer = setTimeout(() => {
|
|
@@ -31319,9 +31792,28 @@ async function waitForRequesterResult(promise2, timeoutMs, label) {
|
|
|
31319
31792
|
timer.unref?.();
|
|
31320
31793
|
});
|
|
31321
31794
|
return await Promise.race([promise2, timeout]).finally(() => {
|
|
31322
|
-
if (timer)
|
|
31795
|
+
if (timer)
|
|
31323
31796
|
clearTimeout(timer);
|
|
31324
|
-
|
|
31797
|
+
});
|
|
31798
|
+
}
|
|
31799
|
+
|
|
31800
|
+
// packages/runtime/src/grok-acp-invocation.ts
|
|
31801
|
+
async function invokeGrokAcpAgent(options) {
|
|
31802
|
+
return await invokeAcpAgent({
|
|
31803
|
+
...options,
|
|
31804
|
+
adapterType: "grok-acp",
|
|
31805
|
+
createAdapter,
|
|
31806
|
+
label: "Grok ACP"
|
|
31807
|
+
});
|
|
31808
|
+
}
|
|
31809
|
+
|
|
31810
|
+
// packages/runtime/src/kimi-acp-invocation.ts
|
|
31811
|
+
async function invokeKimiAcpAgent(options) {
|
|
31812
|
+
return await invokeAcpAgent({
|
|
31813
|
+
...options,
|
|
31814
|
+
adapterType: "kimi-acp",
|
|
31815
|
+
createAdapter: createAdapter2,
|
|
31816
|
+
label: "Kimi Code ACP"
|
|
31325
31817
|
});
|
|
31326
31818
|
}
|
|
31327
31819
|
|
|
@@ -31329,8 +31821,8 @@ async function waitForRequesterResult(promise2, timeoutMs, label) {
|
|
|
31329
31821
|
import { randomUUID } from "crypto";
|
|
31330
31822
|
import { spawn as spawn4 } from "child_process";
|
|
31331
31823
|
import { appendFile as appendFile2, mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
31332
|
-
import { existsSync as
|
|
31333
|
-
import { join as
|
|
31824
|
+
import { existsSync as existsSync19, readFileSync as readFileSync8 } from "fs";
|
|
31825
|
+
import { join as join19 } from "path";
|
|
31334
31826
|
|
|
31335
31827
|
// packages/runtime/src/managed-agent-environment.ts
|
|
31336
31828
|
function managedAgentEnvironmentEntries(options) {
|
|
@@ -31357,31 +31849,31 @@ function buildManagedAgentShellExports(options) {
|
|
|
31357
31849
|
}
|
|
31358
31850
|
|
|
31359
31851
|
// packages/runtime/src/tool-resolution.ts
|
|
31360
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as
|
|
31361
|
-
import { homedir as
|
|
31362
|
-
import { basename as
|
|
31852
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync18 } from "fs";
|
|
31853
|
+
import { homedir as homedir18 } from "os";
|
|
31854
|
+
import { basename as basename13, dirname as dirname10, join as join18, resolve as resolve6 } from "path";
|
|
31363
31855
|
var DEFAULT_COMMON_EXECUTABLE_DIRECTORIES = [
|
|
31364
|
-
|
|
31856
|
+
join18(homedir18(), ".bun", "bin"),
|
|
31365
31857
|
"/opt/homebrew/bin",
|
|
31366
31858
|
"/usr/local/bin"
|
|
31367
31859
|
];
|
|
31368
31860
|
function commonClaudeExecutableDirectories(env) {
|
|
31369
|
-
const home = env.HOME ??
|
|
31861
|
+
const home = env.HOME ?? homedir18();
|
|
31370
31862
|
return [
|
|
31371
|
-
|
|
31372
|
-
|
|
31863
|
+
join18(home, ".local", "bin"),
|
|
31864
|
+
join18(home, ".claude", "local"),
|
|
31373
31865
|
"/opt/homebrew/bin",
|
|
31374
31866
|
"/usr/local/bin",
|
|
31375
|
-
|
|
31867
|
+
join18(home, ".bun", "bin")
|
|
31376
31868
|
];
|
|
31377
31869
|
}
|
|
31378
31870
|
function expandHomePath(value, env = process.env) {
|
|
31379
|
-
const home = env.HOME ??
|
|
31871
|
+
const home = env.HOME ?? homedir18();
|
|
31380
31872
|
if (value === "~") {
|
|
31381
31873
|
return home;
|
|
31382
31874
|
}
|
|
31383
31875
|
if (value.startsWith("~/")) {
|
|
31384
|
-
return
|
|
31876
|
+
return join18(home, value.slice(2));
|
|
31385
31877
|
}
|
|
31386
31878
|
return value;
|
|
31387
31879
|
}
|
|
@@ -31438,7 +31930,7 @@ function resolveExecutableFromSearch(options) {
|
|
|
31438
31930
|
], env);
|
|
31439
31931
|
for (const directory of searchDirectories) {
|
|
31440
31932
|
for (const name of options.names) {
|
|
31441
|
-
const candidate =
|
|
31933
|
+
const candidate = join18(directory, name);
|
|
31442
31934
|
if (isExecutablePath(candidate)) {
|
|
31443
31935
|
return {
|
|
31444
31936
|
path: candidate,
|
|
@@ -31452,7 +31944,7 @@ function resolveExecutableFromSearch(options) {
|
|
|
31452
31944
|
function resolveExecutableFromDirectories(directories, names, env, source) {
|
|
31453
31945
|
for (const directory of dedupeDirectories(directories, env)) {
|
|
31454
31946
|
for (const name of names) {
|
|
31455
|
-
const candidate =
|
|
31947
|
+
const candidate = join18(directory, name);
|
|
31456
31948
|
if (isExecutablePath(candidate)) {
|
|
31457
31949
|
return { path: candidate, source };
|
|
31458
31950
|
}
|
|
@@ -31492,12 +31984,12 @@ function resolveOpenScoutRepoRoot(options = {}) {
|
|
|
31492
31984
|
for (const start of starts) {
|
|
31493
31985
|
let current = resolve6(start);
|
|
31494
31986
|
while (true) {
|
|
31495
|
-
const scoutEntry =
|
|
31496
|
-
const runtimeEntry =
|
|
31497
|
-
if (
|
|
31987
|
+
const scoutEntry = join18(current, "apps", "desktop", "bin", "scout.ts");
|
|
31988
|
+
const runtimeEntry = join18(current, "packages", "runtime", "bin", "openscout-runtime.mjs");
|
|
31989
|
+
if (existsSync18(scoutEntry) && existsSync18(runtimeEntry)) {
|
|
31498
31990
|
return current;
|
|
31499
31991
|
}
|
|
31500
|
-
const parent =
|
|
31992
|
+
const parent = dirname10(current);
|
|
31501
31993
|
if (parent === current) {
|
|
31502
31994
|
break;
|
|
31503
31995
|
}
|
|
@@ -31510,8 +32002,8 @@ function resolveRepoEntrypoint(repoRoot, relativePath) {
|
|
|
31510
32002
|
if (!repoRoot) {
|
|
31511
32003
|
return null;
|
|
31512
32004
|
}
|
|
31513
|
-
const candidate =
|
|
31514
|
-
return
|
|
32005
|
+
const candidate = join18(repoRoot, relativePath);
|
|
32006
|
+
return existsSync18(candidate) ? candidate : null;
|
|
31515
32007
|
}
|
|
31516
32008
|
function findExecutableOnSearchPath(name, env) {
|
|
31517
32009
|
const searchDirectories = dedupeDirectories([
|
|
@@ -31519,7 +32011,7 @@ function findExecutableOnSearchPath(name, env) {
|
|
|
31519
32011
|
...DEFAULT_COMMON_EXECUTABLE_DIRECTORIES
|
|
31520
32012
|
], env);
|
|
31521
32013
|
for (const directory of searchDirectories) {
|
|
31522
|
-
const candidate =
|
|
32014
|
+
const candidate = join18(directory, name);
|
|
31523
32015
|
if (isExecutablePath(candidate)) {
|
|
31524
32016
|
return { path: candidate, source: "path" };
|
|
31525
32017
|
}
|
|
@@ -31580,12 +32072,12 @@ function errorMessage2(error48) {
|
|
|
31580
32072
|
var SESSION_CATALOG_FILENAME = "session-catalog.json";
|
|
31581
32073
|
var SESSION_CATALOG_MAX_ENTRIES = 64;
|
|
31582
32074
|
function readSessionCatalogSync(runtimeDirectory) {
|
|
31583
|
-
const catalogPath =
|
|
32075
|
+
const catalogPath = join19(runtimeDirectory, SESSION_CATALOG_FILENAME);
|
|
31584
32076
|
try {
|
|
31585
|
-
if (!
|
|
31586
|
-
const legacyPath =
|
|
31587
|
-
if (
|
|
31588
|
-
const legacyId =
|
|
32077
|
+
if (!existsSync19(catalogPath)) {
|
|
32078
|
+
const legacyPath = join19(runtimeDirectory, "claude-session-id.txt");
|
|
32079
|
+
if (existsSync19(legacyPath)) {
|
|
32080
|
+
const legacyId = readFileSync8(legacyPath, "utf8").trim();
|
|
31589
32081
|
if (legacyId) {
|
|
31590
32082
|
return {
|
|
31591
32083
|
activeSessionId: legacyId,
|
|
@@ -31595,7 +32087,7 @@ function readSessionCatalogSync(runtimeDirectory) {
|
|
|
31595
32087
|
}
|
|
31596
32088
|
return { activeSessionId: null, sessions: [] };
|
|
31597
32089
|
}
|
|
31598
|
-
const raw =
|
|
32090
|
+
const raw = readFileSync8(catalogPath, "utf8").trim();
|
|
31599
32091
|
if (!raw)
|
|
31600
32092
|
return { activeSessionId: null, sessions: [] };
|
|
31601
32093
|
const parsed = JSON.parse(raw);
|
|
@@ -31611,7 +32103,7 @@ async function readSessionCatalog(runtimeDirectory) {
|
|
|
31611
32103
|
return readSessionCatalogSync(runtimeDirectory);
|
|
31612
32104
|
}
|
|
31613
32105
|
async function writeSessionCatalog(runtimeDirectory, catalog) {
|
|
31614
|
-
const catalogPath =
|
|
32106
|
+
const catalogPath = join19(runtimeDirectory, SESSION_CATALOG_FILENAME);
|
|
31615
32107
|
await mkdir3(runtimeDirectory, { recursive: true });
|
|
31616
32108
|
await writeFile3(catalogPath, JSON.stringify(catalog, null, 2) + `
|
|
31617
32109
|
`);
|
|
@@ -31643,8 +32135,8 @@ class ClaudeStreamJsonSession {
|
|
|
31643
32135
|
constructor(options) {
|
|
31644
32136
|
this.options = options;
|
|
31645
32137
|
this.catalogDirectory = options.runtimeDirectory;
|
|
31646
|
-
this.stdoutLogPath =
|
|
31647
|
-
this.stderrLogPath =
|
|
32138
|
+
this.stdoutLogPath = join19(options.logsDirectory, "stdout.log");
|
|
32139
|
+
this.stderrLogPath = join19(options.logsDirectory, "stderr.log");
|
|
31648
32140
|
this.lastConfigSignature = this.configSignature(options);
|
|
31649
32141
|
}
|
|
31650
32142
|
matches(options) {
|
|
@@ -31800,7 +32292,7 @@ class ClaudeStreamJsonSession {
|
|
|
31800
32292
|
async startSession() {
|
|
31801
32293
|
await mkdir3(this.options.runtimeDirectory, { recursive: true });
|
|
31802
32294
|
await mkdir3(this.options.logsDirectory, { recursive: true });
|
|
31803
|
-
await writeFile3(
|
|
32295
|
+
await writeFile3(join19(this.options.runtimeDirectory, "prompt.txt"), this.options.systemPrompt);
|
|
31804
32296
|
const catalog = await readSessionCatalog(this.catalogDirectory);
|
|
31805
32297
|
this.claudeSessionId = catalog.activeSessionId;
|
|
31806
32298
|
this.resumedSessionId = this.claudeSessionId;
|
|
@@ -31985,14 +32477,14 @@ async function shutdownClaudeStreamJsonAgent(options, shutdownOptions = {}) {
|
|
|
31985
32477
|
|
|
31986
32478
|
// packages/agent-sessions/src/local/transports/codex-app-server.ts
|
|
31987
32479
|
import { spawn as spawn5 } from "child_process";
|
|
31988
|
-
import { homedir as
|
|
32480
|
+
import { homedir as homedir20 } from "os";
|
|
31989
32481
|
import { appendFile as appendFile3, copyFile, mkdir as mkdir4, readFile as readFile5, rm as rm2, stat as stat3, symlink, writeFile as writeFile4 } from "fs/promises";
|
|
31990
|
-
import { join as
|
|
32482
|
+
import { join as join21, resolve as resolve8 } from "path";
|
|
31991
32483
|
|
|
31992
32484
|
// packages/agent-sessions/src/codex-launch-config.ts
|
|
31993
|
-
import { accessSync as accessSync3, constants as constants3, existsSync as
|
|
31994
|
-
import { homedir as
|
|
31995
|
-
import { basename as
|
|
32485
|
+
import { accessSync as accessSync3, constants as constants3, existsSync as existsSync20 } from "fs";
|
|
32486
|
+
import { homedir as homedir19 } from "os";
|
|
32487
|
+
import { basename as basename14, delimiter as delimiter2, dirname as dirname11, join as join20, resolve as resolve7 } from "path";
|
|
31996
32488
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
31997
32489
|
function isExecutable2(filePath) {
|
|
31998
32490
|
if (!filePath) {
|
|
@@ -32013,7 +32505,7 @@ function ancestorChain(start) {
|
|
|
32013
32505
|
let current = resolve7(start);
|
|
32014
32506
|
while (true) {
|
|
32015
32507
|
chain.push(current);
|
|
32016
|
-
const parent =
|
|
32508
|
+
const parent = dirname11(current);
|
|
32017
32509
|
if (parent === current) {
|
|
32018
32510
|
return chain;
|
|
32019
32511
|
}
|
|
@@ -32023,14 +32515,14 @@ function ancestorChain(start) {
|
|
|
32023
32515
|
function resolveExecutableFromSearchPath(names, env) {
|
|
32024
32516
|
const pathEntries = (env.PATH ?? "").split(delimiter2).filter(Boolean);
|
|
32025
32517
|
const commonDirectories = [
|
|
32026
|
-
|
|
32027
|
-
|
|
32518
|
+
join20(homedir19(), ".local", "bin"),
|
|
32519
|
+
join20(homedir19(), ".bun", "bin"),
|
|
32028
32520
|
"/opt/homebrew/bin",
|
|
32029
32521
|
"/usr/local/bin"
|
|
32030
32522
|
];
|
|
32031
32523
|
for (const directory of [...pathEntries, ...commonDirectories]) {
|
|
32032
32524
|
for (const name of names) {
|
|
32033
|
-
const candidate =
|
|
32525
|
+
const candidate = join20(directory, name);
|
|
32034
32526
|
if (isExecutable2(candidate)) {
|
|
32035
32527
|
return candidate;
|
|
32036
32528
|
}
|
|
@@ -32049,7 +32541,7 @@ function resolveBunExecutable2(env) {
|
|
|
32049
32541
|
return candidate;
|
|
32050
32542
|
}
|
|
32051
32543
|
}
|
|
32052
|
-
if (
|
|
32544
|
+
if (basename14(process.execPath).startsWith("bun") && isExecutable2(process.execPath)) {
|
|
32053
32545
|
return process.execPath;
|
|
32054
32546
|
}
|
|
32055
32547
|
return resolveExecutableFromSearchPath(["bun"], env);
|
|
@@ -32069,12 +32561,12 @@ function resolveScoutExecutable(env) {
|
|
|
32069
32561
|
return resolveExecutableFromSearchPath(["scout"], env);
|
|
32070
32562
|
}
|
|
32071
32563
|
function resolveRepoScoutScript(currentDirectory) {
|
|
32072
|
-
const moduleDirectory =
|
|
32564
|
+
const moduleDirectory = dirname11(fileURLToPath2(import.meta.url));
|
|
32073
32565
|
const starts = uniquePaths([currentDirectory, moduleDirectory]);
|
|
32074
32566
|
for (const start of starts) {
|
|
32075
32567
|
for (const candidate of ancestorChain(start)) {
|
|
32076
|
-
const scriptPath =
|
|
32077
|
-
if (
|
|
32568
|
+
const scriptPath = join20(candidate, "apps", "desktop", "bin", "scout.ts");
|
|
32569
|
+
if (existsSync20(scriptPath)) {
|
|
32078
32570
|
return scriptPath;
|
|
32079
32571
|
}
|
|
32080
32572
|
}
|
|
@@ -32191,6 +32683,10 @@ function normalizeCodexModelValue(value) {
|
|
|
32191
32683
|
if (!trimmed) {
|
|
32192
32684
|
return null;
|
|
32193
32685
|
}
|
|
32686
|
+
const lower = trimmed.toLowerCase();
|
|
32687
|
+
if (lower === "5.6" || lower === "gpt-5.6") {
|
|
32688
|
+
return "gpt-5.6-sol";
|
|
32689
|
+
}
|
|
32194
32690
|
if (/^\d+(?:\.\d+)*(?:-[A-Za-z0-9][A-Za-z0-9._-]*)?$/.test(trimmed)) {
|
|
32195
32691
|
return `gpt-${trimmed}`;
|
|
32196
32692
|
}
|
|
@@ -32417,7 +32913,7 @@ function isTruthyEnvironmentFlag(value) {
|
|
|
32417
32913
|
}
|
|
32418
32914
|
function defaultCodexHome(env) {
|
|
32419
32915
|
const configured = env[MANAGED_CODEX_HOME_SOURCE_ENV]?.trim() || env.CODEX_HOME?.trim();
|
|
32420
|
-
return configured ? resolve8(configured) :
|
|
32916
|
+
return configured ? resolve8(configured) : join21(homedir20(), ".codex");
|
|
32421
32917
|
}
|
|
32422
32918
|
function managedCodexHomeConfig(sourceConfig) {
|
|
32423
32919
|
const selectedLines = [];
|
|
@@ -32448,8 +32944,8 @@ async function readOptionalTextFile(path) {
|
|
|
32448
32944
|
}
|
|
32449
32945
|
}
|
|
32450
32946
|
async function linkOptionalCodexHomeFile(sourceHome, managedHome, fileName) {
|
|
32451
|
-
const sourcePath =
|
|
32452
|
-
const targetPath =
|
|
32947
|
+
const sourcePath = join21(sourceHome, fileName);
|
|
32948
|
+
const targetPath = join21(managedHome, fileName);
|
|
32453
32949
|
let sourceStat;
|
|
32454
32950
|
try {
|
|
32455
32951
|
sourceStat = await stat3(sourcePath);
|
|
@@ -32478,7 +32974,7 @@ async function prepareManagedCodexHome(options, env) {
|
|
|
32478
32974
|
return env;
|
|
32479
32975
|
}
|
|
32480
32976
|
const sourceHome = defaultCodexHome(env);
|
|
32481
|
-
const managedHome =
|
|
32977
|
+
const managedHome = join21(options.runtimeDirectory, MANAGED_CODEX_HOME_DIRECTORY);
|
|
32482
32978
|
if (resolve8(sourceHome) === resolve8(managedHome)) {
|
|
32483
32979
|
return {
|
|
32484
32980
|
...env,
|
|
@@ -32487,8 +32983,8 @@ async function prepareManagedCodexHome(options, env) {
|
|
|
32487
32983
|
};
|
|
32488
32984
|
}
|
|
32489
32985
|
await mkdir4(managedHome, { recursive: true });
|
|
32490
|
-
const sourceConfig = await readOptionalTextFile(
|
|
32491
|
-
await writeFile4(
|
|
32986
|
+
const sourceConfig = await readOptionalTextFile(join21(sourceHome, "config.toml"));
|
|
32987
|
+
await writeFile4(join21(managedHome, "config.toml"), managedCodexHomeConfig(sourceConfig), "utf8");
|
|
32492
32988
|
for (const fileName of MANAGED_CODEX_HOME_LINKED_FILES) {
|
|
32493
32989
|
await linkOptionalCodexHomeFile(sourceHome, managedHome, fileName);
|
|
32494
32990
|
}
|
|
@@ -32576,7 +33072,7 @@ function parseCodexMaybeJson(value) {
|
|
|
32576
33072
|
}
|
|
32577
33073
|
}
|
|
32578
33074
|
async function readCodexSessionCatalog(runtimeDirectory) {
|
|
32579
|
-
const raw = await readOptionalFile(
|
|
33075
|
+
const raw = await readOptionalFile(join21(runtimeDirectory, SESSION_CATALOG_FILENAME2));
|
|
32580
33076
|
if (!raw) {
|
|
32581
33077
|
return { activeSessionId: null, sessions: [] };
|
|
32582
33078
|
}
|
|
@@ -32591,7 +33087,7 @@ async function readCodexSessionCatalog(runtimeDirectory) {
|
|
|
32591
33087
|
}
|
|
32592
33088
|
async function writeCodexSessionCatalog(runtimeDirectory, catalog) {
|
|
32593
33089
|
await mkdir4(runtimeDirectory, { recursive: true });
|
|
32594
|
-
await writeFile4(
|
|
33090
|
+
await writeFile4(join21(runtimeDirectory, SESSION_CATALOG_FILENAME2), JSON.stringify(catalog, null, 2) + `
|
|
32595
33091
|
`);
|
|
32596
33092
|
}
|
|
32597
33093
|
async function recordCodexSessionCatalog(runtimeDirectory, threadId, input) {
|
|
@@ -32652,10 +33148,10 @@ class CodexAppServerTransport {
|
|
|
32652
33148
|
errorListeners = new Set;
|
|
32653
33149
|
constructor(options) {
|
|
32654
33150
|
this.options = options;
|
|
32655
|
-
this.threadIdPath =
|
|
32656
|
-
this.statePath =
|
|
32657
|
-
this.stdoutLogPath =
|
|
32658
|
-
this.stderrLogPath =
|
|
33151
|
+
this.threadIdPath = join21(options.runtimeDirectory, "codex-thread-id.txt");
|
|
33152
|
+
this.statePath = join21(options.runtimeDirectory, "state.json");
|
|
33153
|
+
this.stdoutLogPath = join21(options.logsDirectory, "stdout.log");
|
|
33154
|
+
this.stderrLogPath = join21(options.logsDirectory, "stderr.log");
|
|
32659
33155
|
this.lastConfigSignature = this.configSignature(options);
|
|
32660
33156
|
}
|
|
32661
33157
|
get currentThreadId() {
|
|
@@ -32810,7 +33306,7 @@ class CodexAppServerTransport {
|
|
|
32810
33306
|
async startSession() {
|
|
32811
33307
|
await mkdir4(this.options.runtimeDirectory, { recursive: true });
|
|
32812
33308
|
await mkdir4(this.options.logsDirectory, { recursive: true });
|
|
32813
|
-
await writeFile4(
|
|
33309
|
+
await writeFile4(join21(this.options.runtimeDirectory, "prompt.txt"), this.options.systemPrompt);
|
|
32814
33310
|
this.proactiveShutdown = null;
|
|
32815
33311
|
try {
|
|
32816
33312
|
await assertCodexWorkingDirectory(this.options.cwd, this.options.agentName);
|
|
@@ -33479,9 +33975,9 @@ async function shutdownCodexAppServerLocalAgent(options, shutdownOptions = {}) {
|
|
|
33479
33975
|
const session = codexAppServerClients.get(key);
|
|
33480
33976
|
if (!session) {
|
|
33481
33977
|
if (shutdownOptions.resetThread) {
|
|
33482
|
-
const threadId = await readOptionalFile(
|
|
33978
|
+
const threadId = await readOptionalFile(join21(options.runtimeDirectory, "codex-thread-id.txt"));
|
|
33483
33979
|
await closeCodexSessionCatalog(options.runtimeDirectory, threadId);
|
|
33484
|
-
await rm2(
|
|
33980
|
+
await rm2(join21(options.runtimeDirectory, "codex-thread-id.txt"), { force: true });
|
|
33485
33981
|
}
|
|
33486
33982
|
return;
|
|
33487
33983
|
}
|
|
@@ -33627,16 +34123,16 @@ function buildInvocationCollaborationContextPrompt(invocation) {
|
|
|
33627
34123
|
}
|
|
33628
34124
|
|
|
33629
34125
|
// packages/runtime/src/pi-rpc.ts
|
|
33630
|
-
import { existsSync as
|
|
34126
|
+
import { existsSync as existsSync21 } from "fs";
|
|
33631
34127
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "fs/promises";
|
|
33632
34128
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
33633
|
-
import { homedir as
|
|
33634
|
-
import { join as
|
|
34129
|
+
import { homedir as homedir21 } from "os";
|
|
34130
|
+
import { join as join22 } from "path";
|
|
33635
34131
|
var DEFAULT_PI_RPC_TIMEOUT_MS = 300000;
|
|
33636
34132
|
var PI_SCOUT_EXTENSION_CANDIDATES = [
|
|
33637
34133
|
process.env.OPENSCOUT_PI_SCOUT_EXTENSION_PATH,
|
|
33638
|
-
|
|
33639
|
-
|
|
34134
|
+
join22(homedir21(), ".pi", "agent", "extensions", "pi-scout"),
|
|
34135
|
+
join22(homedir21(), "dev", "pi-scout")
|
|
33640
34136
|
].filter((candidate) => Boolean(candidate));
|
|
33641
34137
|
var PI_RPC_FLAGS_WITH_VALUES = new Set([
|
|
33642
34138
|
"--model",
|
|
@@ -33688,7 +34184,7 @@ function resolveDefaultPiScoutExtension() {
|
|
|
33688
34184
|
return null;
|
|
33689
34185
|
}
|
|
33690
34186
|
for (const candidate of PI_SCOUT_EXTENSION_CANDIDATES) {
|
|
33691
|
-
if (
|
|
34187
|
+
if (existsSync21(candidate)) {
|
|
33692
34188
|
return candidate;
|
|
33693
34189
|
}
|
|
33694
34190
|
}
|
|
@@ -33768,7 +34264,7 @@ function parsePiRpcLaunchArgs(launchArgs, options) {
|
|
|
33768
34264
|
const parsed = {
|
|
33769
34265
|
extensions: [],
|
|
33770
34266
|
extraArgs: [],
|
|
33771
|
-
sessionDir:
|
|
34267
|
+
sessionDir: join22(options.runtimeDirectory, "pi-sessions")
|
|
33772
34268
|
};
|
|
33773
34269
|
for (let index = 0;index < launchArgs.length; index += 1) {
|
|
33774
34270
|
const current = launchArgs[index] ?? "";
|
|
@@ -33880,11 +34376,11 @@ class PiRpcAgentSession {
|
|
|
33880
34376
|
}
|
|
33881
34377
|
await mkdir5(this.options.runtimeDirectory, { recursive: true });
|
|
33882
34378
|
await mkdir5(this.options.logsDirectory, { recursive: true });
|
|
33883
|
-
await writeFile5(
|
|
34379
|
+
await writeFile5(join22(this.options.runtimeDirectory, "prompt.txt"), this.options.systemPrompt);
|
|
33884
34380
|
const launch = parsePiRpcLaunchArgs(this.options.launchArgs, {
|
|
33885
34381
|
runtimeDirectory: this.options.runtimeDirectory
|
|
33886
34382
|
});
|
|
33887
|
-
const adapter2 =
|
|
34383
|
+
const adapter2 = createAdapter3({
|
|
33888
34384
|
sessionId: this.options.sessionId,
|
|
33889
34385
|
name: `${this.options.agentName} Pi RPC`,
|
|
33890
34386
|
cwd: this.options.cwd,
|
|
@@ -34048,10 +34544,10 @@ async function shutdownPiRpcAgent(options) {
|
|
|
34048
34544
|
|
|
34049
34545
|
// packages/runtime/src/setup.ts
|
|
34050
34546
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
34051
|
-
import { existsSync as
|
|
34547
|
+
import { existsSync as existsSync24, readFileSync as readFileSync10 } from "fs";
|
|
34052
34548
|
import { access, chmod, mkdir as mkdir7, readdir as readdir3, readFile as readFile8, realpath, rm as rm3, stat as stat5, writeFile as writeFile7 } from "fs/promises";
|
|
34053
|
-
import { homedir as
|
|
34054
|
-
import { basename as
|
|
34549
|
+
import { homedir as homedir25, hostname as hostname3, userInfo } from "os";
|
|
34550
|
+
import { basename as basename15, dirname as dirname14, isAbsolute as isAbsolute2, join as join26, relative as relative6, resolve as resolve10 } from "path";
|
|
34055
34551
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
34056
34552
|
|
|
34057
34553
|
// node_modules/.bun/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
|
|
@@ -35002,52 +35498,59 @@ function parse5(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
|
|
|
35002
35498
|
|
|
35003
35499
|
// packages/runtime/src/harness-catalog.ts
|
|
35004
35500
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
35005
|
-
import { existsSync as
|
|
35501
|
+
import { existsSync as existsSync23, statSync as statSync13 } from "fs";
|
|
35006
35502
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
|
|
35007
|
-
import { homedir as
|
|
35008
|
-
import { dirname as
|
|
35503
|
+
import { homedir as homedir23 } from "os";
|
|
35504
|
+
import { dirname as dirname12, join as join24 } from "path";
|
|
35009
35505
|
|
|
35010
35506
|
// packages/runtime/src/support-paths.ts
|
|
35011
|
-
import { existsSync as
|
|
35012
|
-
import { homedir as
|
|
35013
|
-
import { join as
|
|
35507
|
+
import { existsSync as existsSync22, mkdirSync, rmSync, writeFileSync } from "fs";
|
|
35508
|
+
import { homedir as homedir22 } from "os";
|
|
35509
|
+
import { join as join23 } from "path";
|
|
35014
35510
|
var OPENSCOUT_RPC_CUTOVER_MARKER = "rpc-runtime-cutover-v1";
|
|
35511
|
+
function assertTestIsolatedUserData(operation, isolationEnvKey) {
|
|
35512
|
+
if (true)
|
|
35513
|
+
return;
|
|
35514
|
+
if (process.env[isolationEnvKey]?.trim())
|
|
35515
|
+
return;
|
|
35516
|
+
throw new Error(`Refusing to ${operation} while NODE_ENV=test without ${isolationEnvKey} set. ` + "Tests must isolate OpenScout user data in a temp directory (see prepareHome in onboarding.test.ts).");
|
|
35517
|
+
}
|
|
35015
35518
|
function resolveOpenScoutSupportPaths() {
|
|
35016
|
-
const home =
|
|
35017
|
-
const supportDirectory = process.env.OPENSCOUT_SUPPORT_DIRECTORY ??
|
|
35018
|
-
const logsDirectory =
|
|
35019
|
-
const runtimeDirectory =
|
|
35020
|
-
const catalogDirectory =
|
|
35021
|
-
const controlHome = process.env.OPENSCOUT_CONTROL_HOME ??
|
|
35022
|
-
const knowledgeDirectory =
|
|
35519
|
+
const home = homedir22();
|
|
35520
|
+
const supportDirectory = process.env.OPENSCOUT_SUPPORT_DIRECTORY ?? join23(home, "Library", "Application Support", "OpenScout");
|
|
35521
|
+
const logsDirectory = join23(supportDirectory, "logs");
|
|
35522
|
+
const runtimeDirectory = join23(supportDirectory, "runtime");
|
|
35523
|
+
const catalogDirectory = join23(supportDirectory, "catalog");
|
|
35524
|
+
const controlHome = process.env.OPENSCOUT_CONTROL_HOME ?? join23(home, ".openscout", "control-plane");
|
|
35525
|
+
const knowledgeDirectory = join23(controlHome, "knowledge");
|
|
35023
35526
|
return {
|
|
35024
35527
|
supportDirectory,
|
|
35025
35528
|
logsDirectory,
|
|
35026
|
-
appLogsDirectory:
|
|
35027
|
-
brokerLogsDirectory:
|
|
35529
|
+
appLogsDirectory: join23(logsDirectory, "app"),
|
|
35530
|
+
brokerLogsDirectory: join23(logsDirectory, "broker"),
|
|
35028
35531
|
runtimeDirectory,
|
|
35029
35532
|
catalogDirectory,
|
|
35030
|
-
relayAgentsDirectory:
|
|
35031
|
-
settingsPath:
|
|
35032
|
-
harnessCatalogPath:
|
|
35033
|
-
relayAgentsRegistryPath:
|
|
35034
|
-
managedInstallsPath:
|
|
35035
|
-
hostInfoPath:
|
|
35036
|
-
relayHubDirectory: process.env.OPENSCOUT_RELAY_HUB ??
|
|
35533
|
+
relayAgentsDirectory: join23(runtimeDirectory, "agents"),
|
|
35534
|
+
settingsPath: join23(supportDirectory, "settings.json"),
|
|
35535
|
+
harnessCatalogPath: join23(catalogDirectory, "harness-catalog.json"),
|
|
35536
|
+
relayAgentsRegistryPath: join23(supportDirectory, "relay-agents.json"),
|
|
35537
|
+
managedInstallsPath: join23(supportDirectory, "managed-installs.json"),
|
|
35538
|
+
hostInfoPath: join23(supportDirectory, ".host-info"),
|
|
35539
|
+
relayHubDirectory: process.env.OPENSCOUT_RELAY_HUB ?? join23(home, ".openscout", "relay"),
|
|
35037
35540
|
controlHome,
|
|
35038
35541
|
knowledgeDirectory,
|
|
35039
|
-
knowledgeQmdDirectory:
|
|
35040
|
-
knowledgeSqlitePath:
|
|
35041
|
-
desktopStatusPath:
|
|
35042
|
-
workspaceStatePath:
|
|
35043
|
-
cutoverMarkerPath:
|
|
35542
|
+
knowledgeQmdDirectory: join23(knowledgeDirectory, "qmd"),
|
|
35543
|
+
knowledgeSqlitePath: join23(knowledgeDirectory, "knowledge.sqlite"),
|
|
35544
|
+
desktopStatusPath: join23(supportDirectory, "agent-status.json"),
|
|
35545
|
+
workspaceStatePath: join23(supportDirectory, "workspace-state.json"),
|
|
35546
|
+
cutoverMarkerPath: join23(supportDirectory, OPENSCOUT_RPC_CUTOVER_MARKER)
|
|
35044
35547
|
};
|
|
35045
35548
|
}
|
|
35046
35549
|
function localAgentRuntimeDirectory(agentId) {
|
|
35047
|
-
return
|
|
35550
|
+
return join23(resolveOpenScoutSupportPaths().relayAgentsDirectory, agentId);
|
|
35048
35551
|
}
|
|
35049
35552
|
function localAgentLogsDirectory(agentId) {
|
|
35050
|
-
return
|
|
35553
|
+
return join23(localAgentRuntimeDirectory(agentId), "logs");
|
|
35051
35554
|
}
|
|
35052
35555
|
function relayAgentRuntimeDirectory(agentId) {
|
|
35053
35556
|
return localAgentRuntimeDirectory(agentId);
|
|
@@ -35056,8 +35559,9 @@ function relayAgentLogsDirectory(agentId) {
|
|
|
35056
35559
|
return localAgentLogsDirectory(agentId);
|
|
35057
35560
|
}
|
|
35058
35561
|
function ensureOpenScoutCleanSlateSync() {
|
|
35562
|
+
assertTestIsolatedUserData("reset the OpenScout support directory", "OPENSCOUT_SUPPORT_DIRECTORY");
|
|
35059
35563
|
const paths = resolveOpenScoutSupportPaths();
|
|
35060
|
-
if (
|
|
35564
|
+
if (existsSync22(paths.cutoverMarkerPath)) {
|
|
35061
35565
|
return;
|
|
35062
35566
|
}
|
|
35063
35567
|
rmSync(paths.supportDirectory, { recursive: true, force: true });
|
|
@@ -35114,6 +35618,10 @@ var BUILT_IN_HARNESS_CATALOG = [
|
|
|
35114
35618
|
command: "claude",
|
|
35115
35619
|
sessionFlag: "--resume"
|
|
35116
35620
|
},
|
|
35621
|
+
sessionDefaults: {
|
|
35622
|
+
defaultTransport: "tmux",
|
|
35623
|
+
fallbackTransports: ["claude_stream_json"]
|
|
35624
|
+
},
|
|
35117
35625
|
capabilities: ["chat", "invoke", "deliver", "summarize", "review"]
|
|
35118
35626
|
},
|
|
35119
35627
|
{
|
|
@@ -35150,6 +35658,10 @@ var BUILT_IN_HARNESS_CATALOG = [
|
|
|
35150
35658
|
command: "grok",
|
|
35151
35659
|
sessionFlag: "--resume"
|
|
35152
35660
|
},
|
|
35661
|
+
sessionDefaults: {
|
|
35662
|
+
defaultHarness: "grok-acp",
|
|
35663
|
+
defaultTransport: "grok_acp"
|
|
35664
|
+
},
|
|
35153
35665
|
capabilities: ["chat", "invoke", "deliver", "summarize", "review"],
|
|
35154
35666
|
metadata: {
|
|
35155
35667
|
invocationModel: "tmux_interactive"
|
|
@@ -35189,6 +35701,9 @@ var BUILT_IN_HARNESS_CATALOG = [
|
|
|
35189
35701
|
sessionFlag: "resume",
|
|
35190
35702
|
cwdFlag: "-C"
|
|
35191
35703
|
},
|
|
35704
|
+
sessionDefaults: {
|
|
35705
|
+
defaultTransport: "codex_app_server"
|
|
35706
|
+
},
|
|
35192
35707
|
capabilities: ["chat", "invoke", "deliver", "review", "execute"]
|
|
35193
35708
|
},
|
|
35194
35709
|
{
|
|
@@ -35221,12 +35736,53 @@ var BUILT_IN_HARNESS_CATALOG = [
|
|
|
35221
35736
|
loginCommand: "grok login",
|
|
35222
35737
|
notReadyMessage: "Grok ACP is installed but still needs a cached login or XAI_API_KEY."
|
|
35223
35738
|
},
|
|
35739
|
+
sessionDefaults: {
|
|
35740
|
+
defaultTransport: "grok_acp"
|
|
35741
|
+
},
|
|
35224
35742
|
capabilities: ["chat", "invoke", "deliver", "review", "execute"],
|
|
35225
35743
|
metadata: {
|
|
35226
35744
|
adapterType: "grok-acp",
|
|
35227
35745
|
transport: "acp_stdio"
|
|
35228
35746
|
}
|
|
35229
35747
|
},
|
|
35748
|
+
{
|
|
35749
|
+
name: "kimi",
|
|
35750
|
+
harness: "kimi",
|
|
35751
|
+
label: "Kimi Code",
|
|
35752
|
+
description: "Kimi Code CLI coding agent over ACP",
|
|
35753
|
+
homepage: "https://www.kimi.com/code/docs/en/",
|
|
35754
|
+
tags: ["coding", "cli", "kimi", "moonshot", "acp"],
|
|
35755
|
+
featured: true,
|
|
35756
|
+
order: 4,
|
|
35757
|
+
support: {
|
|
35758
|
+
...DEFAULT_SUPPORT,
|
|
35759
|
+
workspace: true,
|
|
35760
|
+
collaboration: true,
|
|
35761
|
+
files: true
|
|
35762
|
+
},
|
|
35763
|
+
install: {
|
|
35764
|
+
binary: "kimi",
|
|
35765
|
+
requires: ["curl"],
|
|
35766
|
+
macos: "curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash",
|
|
35767
|
+
linux: "curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash",
|
|
35768
|
+
windows: "irm https://code.kimi.com/kimi-code/install.ps1 | iex"
|
|
35769
|
+
},
|
|
35770
|
+
readiness: {
|
|
35771
|
+
anyOf: [
|
|
35772
|
+
{ kind: "file", path: "~/.kimi-code/credentials", label: "~/.kimi-code/credentials", fileType: "directory" }
|
|
35773
|
+
],
|
|
35774
|
+
loginCommand: "kimi login",
|
|
35775
|
+
notReadyMessage: "Kimi Code is installed but still needs a cached login from kimi login."
|
|
35776
|
+
},
|
|
35777
|
+
sessionDefaults: {
|
|
35778
|
+
defaultTransport: "kimi_acp"
|
|
35779
|
+
},
|
|
35780
|
+
capabilities: ["chat", "invoke", "deliver", "review", "execute"],
|
|
35781
|
+
metadata: {
|
|
35782
|
+
adapterType: "kimi-acp",
|
|
35783
|
+
transport: "acp_stdio"
|
|
35784
|
+
}
|
|
35785
|
+
},
|
|
35230
35786
|
{
|
|
35231
35787
|
name: "cursor",
|
|
35232
35788
|
harness: "cursor",
|
|
@@ -35337,11 +35893,11 @@ var BUILT_IN_HARNESS_CATALOG = [
|
|
|
35337
35893
|
}
|
|
35338
35894
|
];
|
|
35339
35895
|
function expandHomePath2(value) {
|
|
35340
|
-
const home = process.env.HOME?.trim() ||
|
|
35896
|
+
const home = process.env.HOME?.trim() || homedir23();
|
|
35341
35897
|
if (value === "~")
|
|
35342
35898
|
return home;
|
|
35343
35899
|
if (value.startsWith("~/"))
|
|
35344
|
-
return
|
|
35900
|
+
return join24(home, value.slice(2));
|
|
35345
35901
|
return value;
|
|
35346
35902
|
}
|
|
35347
35903
|
function defaultWhichBinary(binary, platform) {
|
|
@@ -35375,12 +35931,12 @@ function defaultRunCommand(command, platform) {
|
|
|
35375
35931
|
}
|
|
35376
35932
|
function defaultRequirementExists(requirement) {
|
|
35377
35933
|
const expanded = expandHomePath2(requirement.path);
|
|
35378
|
-
if (!
|
|
35934
|
+
if (!existsSync23(expanded))
|
|
35379
35935
|
return false;
|
|
35380
35936
|
if (requirement.fileType === "any" || !requirement.fileType)
|
|
35381
35937
|
return true;
|
|
35382
35938
|
try {
|
|
35383
|
-
const fileStat =
|
|
35939
|
+
const fileStat = statSync13(expanded);
|
|
35384
35940
|
return requirement.fileType === "directory" ? fileStat.isDirectory() : fileStat.isFile();
|
|
35385
35941
|
} catch {
|
|
35386
35942
|
return false;
|
|
@@ -35417,6 +35973,17 @@ function mergeLaunch(base, override) {
|
|
|
35417
35973
|
args: override?.args ?? base?.args ?? []
|
|
35418
35974
|
};
|
|
35419
35975
|
}
|
|
35976
|
+
function mergeSessionDefaults(base, override) {
|
|
35977
|
+
const defaultTransport = override?.defaultTransport ?? base?.defaultTransport;
|
|
35978
|
+
if (!defaultTransport)
|
|
35979
|
+
return;
|
|
35980
|
+
return {
|
|
35981
|
+
...base ?? {},
|
|
35982
|
+
...override ?? {},
|
|
35983
|
+
defaultTransport,
|
|
35984
|
+
fallbackTransports: override?.fallbackTransports ? [...override.fallbackTransports] : base?.fallbackTransports ? [...base.fallbackTransports] : undefined
|
|
35985
|
+
};
|
|
35986
|
+
}
|
|
35420
35987
|
function formatRequirement(requirement) {
|
|
35421
35988
|
if (requirement.label?.trim())
|
|
35422
35989
|
return requirement.label.trim();
|
|
@@ -35443,6 +36010,22 @@ function codexCandidateReport(candidate, selectedPath) {
|
|
|
35443
36010
|
selected: candidate.path === selectedPath
|
|
35444
36011
|
};
|
|
35445
36012
|
}
|
|
36013
|
+
function resolveHarnessSessionDefaults(harness, options = {}) {
|
|
36014
|
+
if (!harness)
|
|
36015
|
+
return null;
|
|
36016
|
+
const entry = (options.entries ?? BUILT_IN_HARNESS_CATALOG).find((candidate) => candidate.harness === harness || candidate.name === harness);
|
|
36017
|
+
const defaults = entry?.sessionDefaults;
|
|
36018
|
+
if (!entry || !defaults)
|
|
36019
|
+
return null;
|
|
36020
|
+
const fallbackTransports = [...defaults.fallbackTransports ?? []];
|
|
36021
|
+
const supportedTransports = new Set([defaults.defaultTransport, ...fallbackTransports]);
|
|
36022
|
+
const requestedTransport = options.transportOverride?.trim();
|
|
36023
|
+
return {
|
|
36024
|
+
harness: String(defaults.defaultHarness ?? entry.harness),
|
|
36025
|
+
transport: requestedTransport && supportedTransports.has(requestedTransport) ? requestedTransport : defaults.defaultTransport,
|
|
36026
|
+
fallbackTransports
|
|
36027
|
+
};
|
|
36028
|
+
}
|
|
35446
36029
|
function createBuiltInHarnessCatalog() {
|
|
35447
36030
|
return BUILT_IN_HARNESS_CATALOG.map((entry) => ({
|
|
35448
36031
|
...entry,
|
|
@@ -35456,6 +36039,10 @@ function createBuiltInHarnessCatalog() {
|
|
|
35456
36039
|
} : undefined,
|
|
35457
36040
|
launch: entry.launch ? { ...entry.launch, args: [...entry.launch.args] } : undefined,
|
|
35458
36041
|
resume: entry.resume ? { ...entry.resume } : undefined,
|
|
36042
|
+
sessionDefaults: entry.sessionDefaults ? {
|
|
36043
|
+
...entry.sessionDefaults,
|
|
36044
|
+
fallbackTransports: entry.sessionDefaults.fallbackTransports ? [...entry.sessionDefaults.fallbackTransports] : undefined
|
|
36045
|
+
} : undefined,
|
|
35459
36046
|
resolveEnv: entry.resolveEnv ? [...entry.resolveEnv] : undefined,
|
|
35460
36047
|
capabilities: [...entry.capabilities],
|
|
35461
36048
|
metadata: entry.metadata ? { ...entry.metadata } : undefined
|
|
@@ -35473,6 +36060,7 @@ function mergeHarnessCatalogEntries(baseEntries, overrides = {}) {
|
|
|
35473
36060
|
install: mergeInstall(entry.install, override.install),
|
|
35474
36061
|
readiness: mergeReadiness(entry.readiness, override.readiness),
|
|
35475
36062
|
launch: mergeLaunch(entry.launch, override.launch),
|
|
36063
|
+
sessionDefaults: mergeSessionDefaults(entry.sessionDefaults, override.sessionDefaults),
|
|
35476
36064
|
resume: override.resume && entry.resume ? { ...entry.resume, ...override.resume } : entry.resume,
|
|
35477
36065
|
tags: override.tags ? [...override.tags] : entry.tags,
|
|
35478
36066
|
capabilities: override.capabilities ? [...override.capabilities] : entry.capabilities,
|
|
@@ -35503,6 +36091,7 @@ function mergeHarnessCatalogEntries(baseEntries, overrides = {}) {
|
|
|
35503
36091
|
readiness: mergeReadiness(undefined, override.readiness),
|
|
35504
36092
|
launch: mergeLaunch(undefined, override.launch),
|
|
35505
36093
|
resume: override.resume?.command && override.resume?.sessionFlag ? { command: override.resume.command, sessionFlag: override.resume.sessionFlag, cwdFlag: override.resume.cwdFlag } : undefined,
|
|
36094
|
+
sessionDefaults: mergeSessionDefaults(undefined, override.sessionDefaults),
|
|
35506
36095
|
resolveEnv: override.resolveEnv ? [...override.resolveEnv] : undefined,
|
|
35507
36096
|
capabilities: [...override.capabilities],
|
|
35508
36097
|
metadata: override.metadata ? { ...override.metadata } : undefined
|
|
@@ -35586,7 +36175,7 @@ async function readHarnessCatalogOverrides(overridePath = resolveOpenScoutSuppor
|
|
|
35586
36175
|
}
|
|
35587
36176
|
}
|
|
35588
36177
|
async function writeHarnessCatalogOverrides(overrides, overridePath = resolveOpenScoutSupportPaths().harnessCatalogPath) {
|
|
35589
|
-
await mkdir6(
|
|
36178
|
+
await mkdir6(dirname12(overridePath), { recursive: true });
|
|
35590
36179
|
const payload = {
|
|
35591
36180
|
version: HARNESS_CATALOG_VERSION,
|
|
35592
36181
|
entries: overrides,
|
|
@@ -35596,7 +36185,7 @@ async function writeHarnessCatalogOverrides(overrides, overridePath = resolveOpe
|
|
|
35596
36185
|
`, "utf8");
|
|
35597
36186
|
}
|
|
35598
36187
|
async function ensureHarnessCatalogOverrideFile(overridePath = resolveOpenScoutSupportPaths().harnessCatalogPath) {
|
|
35599
|
-
if (
|
|
36188
|
+
if (existsSync23(overridePath))
|
|
35600
36189
|
return;
|
|
35601
36190
|
await writeHarnessCatalogOverrides({}, overridePath);
|
|
35602
36191
|
}
|
|
@@ -35618,7 +36207,7 @@ async function loadHarnessCatalogSnapshot(options = {}) {
|
|
|
35618
36207
|
}
|
|
35619
36208
|
|
|
35620
36209
|
// packages/runtime/src/open-scout-network.ts
|
|
35621
|
-
import { readFileSync as
|
|
36210
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
35622
36211
|
var DEFAULT_OPENSCOUT_NETWORK_RENDEZVOUS_URL = "https://mesh.oscout.net";
|
|
35623
36212
|
var DEFAULT_OPENSCOUT_NETWORK_PAIRING_RELAY_URL = "wss://mesh.oscout.net/v1/relay";
|
|
35624
36213
|
function defaultOpenScoutNetworkSettings() {
|
|
@@ -35631,7 +36220,7 @@ function defaultOpenScoutNetworkSettings() {
|
|
|
35631
36220
|
}
|
|
35632
36221
|
function normalizeOpenScoutNetworkSettings(input) {
|
|
35633
36222
|
const base = defaultOpenScoutNetworkSettings();
|
|
35634
|
-
const record2 =
|
|
36223
|
+
const record2 = isRecord6(input) ? input : {};
|
|
35635
36224
|
return {
|
|
35636
36225
|
discoveryEnabled: typeof record2.discoveryEnabled === "boolean" ? record2.discoveryEnabled : base.discoveryEnabled,
|
|
35637
36226
|
rendezvousUrl: normalizeUrlString(record2.rendezvousUrl, base.rendezvousUrl),
|
|
@@ -35641,10 +36230,10 @@ function normalizeOpenScoutNetworkSettings(input) {
|
|
|
35641
36230
|
}
|
|
35642
36231
|
function readOpenScoutNetworkSettingsSync() {
|
|
35643
36232
|
try {
|
|
35644
|
-
const raw =
|
|
36233
|
+
const raw = readFileSync9(resolveOpenScoutSupportPaths().settingsPath, "utf8");
|
|
35645
36234
|
const parsed = JSON.parse(raw);
|
|
35646
|
-
const network =
|
|
35647
|
-
return normalizeOpenScoutNetworkSettings(
|
|
36235
|
+
const network = isRecord6(parsed) && isRecord6(parsed.network) ? parsed.network : {};
|
|
36236
|
+
return normalizeOpenScoutNetworkSettings(isRecord6(network.openScoutNetwork) ? network.openScoutNetwork : {});
|
|
35648
36237
|
} catch {
|
|
35649
36238
|
return defaultOpenScoutNetworkSettings();
|
|
35650
36239
|
}
|
|
@@ -35673,14 +36262,14 @@ function readBooleanEnv(value) {
|
|
|
35673
36262
|
return false;
|
|
35674
36263
|
return;
|
|
35675
36264
|
}
|
|
35676
|
-
function
|
|
36265
|
+
function isRecord6(value) {
|
|
35677
36266
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35678
36267
|
}
|
|
35679
36268
|
|
|
35680
36269
|
// packages/runtime/src/user-project-hints.ts
|
|
35681
36270
|
import { readdir as readdir2, readFile as readFile7, stat as stat4 } from "fs/promises";
|
|
35682
|
-
import { homedir as
|
|
35683
|
-
import { dirname as
|
|
36271
|
+
import { homedir as homedir24 } from "os";
|
|
36272
|
+
import { dirname as dirname13, join as join25, resolve as resolve9 } from "path";
|
|
35684
36273
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
35685
36274
|
var PROJECT_HINT_MARKERS = [
|
|
35686
36275
|
".git",
|
|
@@ -35717,7 +36306,7 @@ async function resolveExistingDirectoryHint(pathLike) {
|
|
|
35717
36306
|
return absolutePath;
|
|
35718
36307
|
}
|
|
35719
36308
|
if (info.isFile()) {
|
|
35720
|
-
return
|
|
36309
|
+
return dirname13(absolutePath);
|
|
35721
36310
|
}
|
|
35722
36311
|
} catch {
|
|
35723
36312
|
return null;
|
|
@@ -35737,14 +36326,14 @@ async function findLikelyProjectRoot(absolutePath) {
|
|
|
35737
36326
|
let lastCandidate = null;
|
|
35738
36327
|
while (true) {
|
|
35739
36328
|
for (const marker of PROJECT_HINT_MARKERS) {
|
|
35740
|
-
if (await pathExists(
|
|
36329
|
+
if (await pathExists(join25(current, marker))) {
|
|
35741
36330
|
lastCandidate = current;
|
|
35742
36331
|
if (marker === ".git" || marker === ".openscout/project.json") {
|
|
35743
36332
|
return current;
|
|
35744
36333
|
}
|
|
35745
36334
|
}
|
|
35746
36335
|
}
|
|
35747
|
-
const parent =
|
|
36336
|
+
const parent = dirname13(current);
|
|
35748
36337
|
if (parent === current) {
|
|
35749
36338
|
return lastCandidate ?? absolutePath;
|
|
35750
36339
|
}
|
|
@@ -35760,16 +36349,16 @@ async function appendPathHint(pathLike, roots) {
|
|
|
35760
36349
|
}
|
|
35761
36350
|
function cursorWorkspaceStoragePath(home) {
|
|
35762
36351
|
if (process.platform === "darwin") {
|
|
35763
|
-
return
|
|
36352
|
+
return join25(home, "Library", "Application Support", "Cursor", "User", "workspaceStorage");
|
|
35764
36353
|
}
|
|
35765
36354
|
if (process.platform === "win32") {
|
|
35766
36355
|
const appData = process.env.APPDATA;
|
|
35767
36356
|
if (appData) {
|
|
35768
|
-
return
|
|
36357
|
+
return join25(appData, "Cursor", "User", "workspaceStorage");
|
|
35769
36358
|
}
|
|
35770
|
-
return
|
|
36359
|
+
return join25(home, "AppData", "Roaming", "Cursor", "User", "workspaceStorage");
|
|
35771
36360
|
}
|
|
35772
|
-
return
|
|
36361
|
+
return join25(home, ".config", "Cursor", "User", "workspaceStorage");
|
|
35773
36362
|
}
|
|
35774
36363
|
function collectPathLikeStrings(value, out, depth) {
|
|
35775
36364
|
if (depth > 4 || value === null || value === undefined) {
|
|
@@ -35798,7 +36387,7 @@ function collectPathLikeStrings(value, out, depth) {
|
|
|
35798
36387
|
}
|
|
35799
36388
|
}
|
|
35800
36389
|
async function appendCodexHistoryPaths(home, roots) {
|
|
35801
|
-
const candidates = [
|
|
36390
|
+
const candidates = [join25(home, ".codex", "history.jsonl"), join25(home, ".openai-codex", "history.jsonl")];
|
|
35802
36391
|
const maxLines = 2500;
|
|
35803
36392
|
const maxBytes = 4 * 1024 * 1024;
|
|
35804
36393
|
for (const filePath of candidates) {
|
|
@@ -35849,7 +36438,7 @@ async function appendCursorWorkspacePaths(home, roots) {
|
|
|
35849
36438
|
return;
|
|
35850
36439
|
}
|
|
35851
36440
|
for (const id of ids) {
|
|
35852
|
-
const workspaceJsonPath =
|
|
36441
|
+
const workspaceJsonPath = join25(base, id, "workspace.json");
|
|
35853
36442
|
let raw;
|
|
35854
36443
|
try {
|
|
35855
36444
|
raw = await readFile7(workspaceJsonPath, "utf8");
|
|
@@ -35885,7 +36474,7 @@ async function appendCursorWorkspacePaths(home, roots) {
|
|
|
35885
36474
|
}
|
|
35886
36475
|
const wsRaw = await readFile7(wsFile, "utf8");
|
|
35887
36476
|
const wsDoc = JSON.parse(wsRaw);
|
|
35888
|
-
const wsDir =
|
|
36477
|
+
const wsDir = dirname13(wsFile);
|
|
35889
36478
|
for (const f of wsDoc.folders ?? []) {
|
|
35890
36479
|
if (typeof f.path !== "string" || !f.path) {
|
|
35891
36480
|
continue;
|
|
@@ -35898,7 +36487,7 @@ async function appendCursorWorkspacePaths(home, roots) {
|
|
|
35898
36487
|
}
|
|
35899
36488
|
}
|
|
35900
36489
|
async function appendClaudeProjectSlugs(home, roots) {
|
|
35901
|
-
const projectsDir =
|
|
36490
|
+
const projectsDir = join25(home, ".claude", "projects");
|
|
35902
36491
|
let names = [];
|
|
35903
36492
|
try {
|
|
35904
36493
|
names = await readdir2(projectsDir, { withFileTypes: false });
|
|
@@ -35914,7 +36503,7 @@ async function appendClaudeProjectSlugs(home, roots) {
|
|
|
35914
36503
|
}
|
|
35915
36504
|
}
|
|
35916
36505
|
async function appendClaudeSessionPaths(home, roots) {
|
|
35917
|
-
const projectsDir =
|
|
36506
|
+
const projectsDir = join25(home, ".claude", "projects");
|
|
35918
36507
|
const maxProjectDirectories = 200;
|
|
35919
36508
|
const maxSessionFiles = 400;
|
|
35920
36509
|
const maxLinesPerFile = 400;
|
|
@@ -35929,7 +36518,7 @@ async function appendClaudeSessionPaths(home, roots) {
|
|
|
35929
36518
|
for (const projectName of projectNames) {
|
|
35930
36519
|
let entries = [];
|
|
35931
36520
|
try {
|
|
35932
|
-
entries = await readdir2(
|
|
36521
|
+
entries = await readdir2(join25(projectsDir, projectName), { withFileTypes: false });
|
|
35933
36522
|
} catch {
|
|
35934
36523
|
continue;
|
|
35935
36524
|
}
|
|
@@ -35940,7 +36529,7 @@ async function appendClaudeSessionPaths(home, roots) {
|
|
|
35940
36529
|
if (!entry.endsWith(".jsonl")) {
|
|
35941
36530
|
continue;
|
|
35942
36531
|
}
|
|
35943
|
-
const sessionPath =
|
|
36532
|
+
const sessionPath = join25(projectsDir, projectName, entry);
|
|
35944
36533
|
let info;
|
|
35945
36534
|
try {
|
|
35946
36535
|
info = await stat4(sessionPath);
|
|
@@ -35982,7 +36571,7 @@ async function appendClaudeSessionPaths(home, roots) {
|
|
|
35982
36571
|
}
|
|
35983
36572
|
}
|
|
35984
36573
|
async function collectUserLevelProjectRootHints(options = {}) {
|
|
35985
|
-
const home = options.home ??
|
|
36574
|
+
const home = options.home ?? homedir24();
|
|
35986
36575
|
const roots = new Set;
|
|
35987
36576
|
try {
|
|
35988
36577
|
await appendClaudeProjectSlugs(home, roots);
|
|
@@ -36160,7 +36749,7 @@ async function matchNestedMarkers(projectRoot, nestedMarkers) {
|
|
|
36160
36749
|
if (nestedMarkers.length === 0) {
|
|
36161
36750
|
return [];
|
|
36162
36751
|
}
|
|
36163
|
-
const hits = await Promise.all(nestedMarkers.map(async (marker) => await pathExists2(
|
|
36752
|
+
const hits = await Promise.all(nestedMarkers.map(async (marker) => await pathExists2(join26(projectRoot, marker)) ? marker : null));
|
|
36164
36753
|
return hits.filter((marker) => Boolean(marker));
|
|
36165
36754
|
}
|
|
36166
36755
|
function nowSeconds() {
|
|
@@ -36168,10 +36757,10 @@ function nowSeconds() {
|
|
|
36168
36757
|
}
|
|
36169
36758
|
function expandHomePath3(value) {
|
|
36170
36759
|
if (value === "~") {
|
|
36171
|
-
return
|
|
36760
|
+
return homedir25();
|
|
36172
36761
|
}
|
|
36173
36762
|
if (value.startsWith("~/")) {
|
|
36174
|
-
return
|
|
36763
|
+
return join26(homedir25(), value.slice(2));
|
|
36175
36764
|
}
|
|
36176
36765
|
return value;
|
|
36177
36766
|
}
|
|
@@ -36258,16 +36847,16 @@ function resolveTelegramConfigSeedValue(key, currentDirectory) {
|
|
|
36258
36847
|
return envValue;
|
|
36259
36848
|
}
|
|
36260
36849
|
if (currentDirectory) {
|
|
36261
|
-
const currentDirValue = readEnvFileValue(
|
|
36850
|
+
const currentDirValue = readEnvFileValue(join26(currentDirectory, ".env.local"), key).trim();
|
|
36262
36851
|
if (currentDirValue) {
|
|
36263
36852
|
return currentDirValue;
|
|
36264
36853
|
}
|
|
36265
36854
|
}
|
|
36266
|
-
const home =
|
|
36855
|
+
const home = homedir25();
|
|
36267
36856
|
if (!home) {
|
|
36268
36857
|
return "";
|
|
36269
36858
|
}
|
|
36270
|
-
return readEnvFileValue(
|
|
36859
|
+
return readEnvFileValue(join26(home, ".env.local"), key).trim();
|
|
36271
36860
|
}
|
|
36272
36861
|
function normalizeTelegramBridgeMode(value) {
|
|
36273
36862
|
const normalized = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
@@ -36298,7 +36887,7 @@ function resolveNodeQualifier() {
|
|
|
36298
36887
|
function readNodeAliasSync() {
|
|
36299
36888
|
try {
|
|
36300
36889
|
const settingsPath = resolveOpenScoutSupportPaths().settingsPath;
|
|
36301
|
-
const raw =
|
|
36890
|
+
const raw = readFileSync10(settingsPath, "utf8");
|
|
36302
36891
|
const settings = JSON.parse(raw);
|
|
36303
36892
|
return settings.node?.alias?.trim() || null;
|
|
36304
36893
|
} catch {
|
|
@@ -36574,13 +37163,13 @@ function defaultSettings() {
|
|
|
36574
37163
|
};
|
|
36575
37164
|
}
|
|
36576
37165
|
function projectConfigPath(projectRoot) {
|
|
36577
|
-
return
|
|
37166
|
+
return join26(projectRoot, ".openscout", "project.json");
|
|
36578
37167
|
}
|
|
36579
37168
|
function projectGitignorePath(projectRoot) {
|
|
36580
|
-
return
|
|
37169
|
+
return join26(projectRoot, ".gitignore");
|
|
36581
37170
|
}
|
|
36582
37171
|
function legacyLocalRelayLinkPath(projectRoot) {
|
|
36583
|
-
return
|
|
37172
|
+
return join26(projectRoot, ".openscout", "relay.json");
|
|
36584
37173
|
}
|
|
36585
37174
|
async function pathExists2(filePath) {
|
|
36586
37175
|
try {
|
|
@@ -36606,15 +37195,15 @@ async function readJsonFile3(filePath) {
|
|
|
36606
37195
|
}
|
|
36607
37196
|
}
|
|
36608
37197
|
async function writeJsonFile(filePath, value) {
|
|
36609
|
-
await mkdir7(
|
|
37198
|
+
await mkdir7(dirname14(filePath), { recursive: true });
|
|
36610
37199
|
await writeFile7(filePath, JSON.stringify(value, null, 2) + `
|
|
36611
37200
|
`, "utf8");
|
|
36612
37201
|
}
|
|
36613
37202
|
function codexEnvironmentPath(projectRoot) {
|
|
36614
|
-
return
|
|
37203
|
+
return join26(projectRoot, ".codex", "environments", "environment.toml");
|
|
36615
37204
|
}
|
|
36616
37205
|
function currentHomeDirectory() {
|
|
36617
|
-
return process.env.HOME?.trim() ||
|
|
37206
|
+
return process.env.HOME?.trim() || homedir25();
|
|
36618
37207
|
}
|
|
36619
37208
|
function normalizeProjectScriptSet(value) {
|
|
36620
37209
|
if (typeof value !== "object" || !value) {
|
|
@@ -36770,11 +37359,11 @@ async function readCodexEnvironmentImport(projectRoot) {
|
|
|
36770
37359
|
}
|
|
36771
37360
|
async function readClaudeProjectImport(projectRoot) {
|
|
36772
37361
|
const slug = encodeClaudeProjectsSlug(projectRoot);
|
|
36773
|
-
const sourcePath =
|
|
37362
|
+
const sourcePath = join26(currentHomeDirectory(), ".claude", "projects", slug);
|
|
36774
37363
|
if (!await isDirectory(sourcePath)) {
|
|
36775
37364
|
return null;
|
|
36776
37365
|
}
|
|
36777
|
-
const memoryPath = await pathExists2(
|
|
37366
|
+
const memoryPath = await pathExists2(join26(sourcePath, "memory", "MEMORY.md")) ? join26(sourcePath, "memory", "MEMORY.md") : undefined;
|
|
36778
37367
|
let entries = [];
|
|
36779
37368
|
try {
|
|
36780
37369
|
entries = await readdir3(sourcePath, { withFileTypes: false });
|
|
@@ -36789,7 +37378,7 @@ async function readClaudeProjectImport(projectRoot) {
|
|
|
36789
37378
|
continue;
|
|
36790
37379
|
}
|
|
36791
37380
|
sessionCount += 1;
|
|
36792
|
-
const sessionPath =
|
|
37381
|
+
const sessionPath = join26(sourcePath, entry);
|
|
36793
37382
|
let body;
|
|
36794
37383
|
try {
|
|
36795
37384
|
body = await readFile8(sessionPath, "utf8");
|
|
@@ -36851,7 +37440,7 @@ function applyImportedEnvironmentSeeds(config2, codexImport, projectRoot) {
|
|
|
36851
37440
|
...(config2.environment?.actions?.length ?? 0) === 0 && importedEnvironment.actions ? { actions: importedEnvironment.actions } : {}
|
|
36852
37441
|
};
|
|
36853
37442
|
}
|
|
36854
|
-
const defaultProjectName = titleCase(
|
|
37443
|
+
const defaultProjectName = titleCase(basename15(projectRoot));
|
|
36855
37444
|
if (codexImport?.name?.trim() && (!config2.project.name?.trim() || config2.project.name === defaultProjectName)) {
|
|
36856
37445
|
next.project = {
|
|
36857
37446
|
...config2.project,
|
|
@@ -36904,11 +37493,11 @@ async function ensureProjectConfigIgnored(projectRoot) {
|
|
|
36904
37493
|
}
|
|
36905
37494
|
async function readLegacyRelayConfig() {
|
|
36906
37495
|
const relayHub = resolveOpenScoutSupportPaths().relayHubDirectory;
|
|
36907
|
-
return readJsonFile3(
|
|
37496
|
+
return readJsonFile3(join26(relayHub, "config.json"));
|
|
36908
37497
|
}
|
|
36909
37498
|
async function readLegacyAgentRegistry() {
|
|
36910
37499
|
const relayHub = resolveOpenScoutSupportPaths().relayHubDirectory;
|
|
36911
|
-
return await readJsonFile3(
|
|
37500
|
+
return await readJsonFile3(join26(relayHub, "agents.json")) ?? {};
|
|
36912
37501
|
}
|
|
36913
37502
|
async function detectHarnessMarkers(projectRoot) {
|
|
36914
37503
|
const detected = {
|
|
@@ -36920,7 +37509,7 @@ async function detectHarnessMarkers(projectRoot) {
|
|
|
36920
37509
|
};
|
|
36921
37510
|
for (const harness of MANAGED_AGENT_HARNESSES) {
|
|
36922
37511
|
for (const marker of PROJECT_HARNESS_MARKERS[harness]) {
|
|
36923
|
-
if (await pathExists2(
|
|
37512
|
+
if (await pathExists2(join26(projectRoot, marker))) {
|
|
36924
37513
|
detected[harness].push(marker);
|
|
36925
37514
|
}
|
|
36926
37515
|
}
|
|
@@ -37067,7 +37656,7 @@ async function seedWorkspaceRoots(options) {
|
|
|
37067
37656
|
const roots = new Set;
|
|
37068
37657
|
const currentProjectRoot = options.currentDirectory ? await findNearestProjectRoot(options.currentDirectory) : null;
|
|
37069
37658
|
if (currentProjectRoot) {
|
|
37070
|
-
roots.add(
|
|
37659
|
+
roots.add(dirname14(currentProjectRoot));
|
|
37071
37660
|
}
|
|
37072
37661
|
const legacyRoot = options.legacyRelayConfig?.projectRoot?.trim();
|
|
37073
37662
|
if (legacyRoot) {
|
|
@@ -37075,11 +37664,11 @@ async function seedWorkspaceRoots(options) {
|
|
|
37075
37664
|
}
|
|
37076
37665
|
for (const record2 of Object.values(options.legacyAgents ?? {})) {
|
|
37077
37666
|
if (record2.cwd?.trim()) {
|
|
37078
|
-
roots.add(
|
|
37667
|
+
roots.add(dirname14(normalizePath(record2.cwd)));
|
|
37079
37668
|
}
|
|
37080
37669
|
}
|
|
37081
37670
|
if (roots.size === 0) {
|
|
37082
|
-
roots.add(
|
|
37671
|
+
roots.add(join26(homedir25(), "dev"));
|
|
37083
37672
|
}
|
|
37084
37673
|
return Array.from(roots);
|
|
37085
37674
|
}
|
|
@@ -37094,7 +37683,7 @@ async function readOpenScoutSettings(options = {}) {
|
|
|
37094
37683
|
legacyAgents
|
|
37095
37684
|
});
|
|
37096
37685
|
}
|
|
37097
|
-
var SETUP_MODULE_DIRECTORY =
|
|
37686
|
+
var SETUP_MODULE_DIRECTORY = dirname14(fileURLToPath4(import.meta.url));
|
|
37098
37687
|
var SCOUT_SKILL_REPO_ROOT = resolve10(SETUP_MODULE_DIRECTORY, "..", "..", "..");
|
|
37099
37688
|
async function readRelayAgentOverrides() {
|
|
37100
37689
|
const supportPaths = resolveOpenScoutSupportPaths();
|
|
@@ -37177,13 +37766,13 @@ async function findNearestProjectRoot(startDirectory) {
|
|
|
37177
37766
|
let current = normalizePath(startDirectory);
|
|
37178
37767
|
let lastCandidate = null;
|
|
37179
37768
|
while (true) {
|
|
37180
|
-
if (await pathExists2(
|
|
37769
|
+
if (await pathExists2(join26(current, ".git"))) {
|
|
37181
37770
|
return current;
|
|
37182
37771
|
}
|
|
37183
|
-
if (await pathExists2(projectConfigPath(current)) || await pathExists2(
|
|
37772
|
+
if (await pathExists2(projectConfigPath(current)) || await pathExists2(join26(current, "package.json")) || await pathExists2(join26(current, "AGENTS.md")) || await pathExists2(join26(current, "CLAUDE.md"))) {
|
|
37184
37773
|
lastCandidate = current;
|
|
37185
37774
|
}
|
|
37186
|
-
const parent =
|
|
37775
|
+
const parent = dirname14(current);
|
|
37187
37776
|
if (parent === current) {
|
|
37188
37777
|
return lastCandidate;
|
|
37189
37778
|
}
|
|
@@ -37191,7 +37780,7 @@ async function findNearestProjectRoot(startDirectory) {
|
|
|
37191
37780
|
}
|
|
37192
37781
|
}
|
|
37193
37782
|
function defaultProjectConfig(projectRoot, settings, preferredHarness) {
|
|
37194
|
-
const projectName =
|
|
37783
|
+
const projectName = basename15(projectRoot);
|
|
37195
37784
|
const definitionId = normalizeAgentId(projectName);
|
|
37196
37785
|
const relativeRoot = relative6(projectRoot, projectRoot) || ".";
|
|
37197
37786
|
return {
|
|
@@ -37365,7 +37954,7 @@ async function scanSourceRoot(sourceRoot) {
|
|
|
37365
37954
|
if (PROJECT_SCAN_SKIP_DIRECTORIES.has(entry.name)) {
|
|
37366
37955
|
continue;
|
|
37367
37956
|
}
|
|
37368
|
-
const nextPath =
|
|
37957
|
+
const nextPath = join26(currentDirectory, entry.name);
|
|
37369
37958
|
if (entry.isSymbolicLink()) {
|
|
37370
37959
|
if (!await isDirectory(nextPath)) {
|
|
37371
37960
|
continue;
|
|
@@ -37406,7 +37995,7 @@ function relativeProjectPath(projectRoot, sourceRoot) {
|
|
|
37406
37995
|
return relative6(sourceRoot, projectRoot) || ".";
|
|
37407
37996
|
}
|
|
37408
37997
|
function resolveProjectRootFromConfig(projectRoot, config2) {
|
|
37409
|
-
return normalizePath(
|
|
37998
|
+
return normalizePath(join26(projectRoot, config2.project.root ?? "."));
|
|
37410
37999
|
}
|
|
37411
38000
|
function mergeResolvedAgentConfig(base, override, settings) {
|
|
37412
38001
|
if (!override) {
|
|
@@ -37482,7 +38071,7 @@ function relayAgentOverrideFromResolvedConfig(config2) {
|
|
|
37482
38071
|
}
|
|
37483
38072
|
function projectDefaultDefinitionIds(config2) {
|
|
37484
38073
|
return new Set([
|
|
37485
|
-
|
|
38074
|
+
basename15(config2.projectRoot),
|
|
37486
38075
|
config2.projectName
|
|
37487
38076
|
].map((value) => normalizeAgentId(value)).filter(Boolean));
|
|
37488
38077
|
}
|
|
@@ -37523,8 +38112,8 @@ function selectorFromInput(value) {
|
|
|
37523
38112
|
}
|
|
37524
38113
|
async function resolveManifestBackedAgent(projectRoot, config2, settings, override) {
|
|
37525
38114
|
const resolvedProjectRoot = resolveProjectRootFromConfig(projectRoot, config2);
|
|
37526
|
-
const projectName = config2.project.name?.trim() || titleCase(config2.project.id ||
|
|
37527
|
-
const fallbackDefinitionId = normalizeAgentId(config2.project.id ||
|
|
38115
|
+
const projectName = config2.project.name?.trim() || titleCase(config2.project.id || basename15(resolvedProjectRoot));
|
|
38116
|
+
const fallbackDefinitionId = normalizeAgentId(config2.project.id || basename15(resolvedProjectRoot));
|
|
37528
38117
|
const definitionId = normalizeAgentId(config2.agent?.id || override?.definitionId || fallbackDefinitionId);
|
|
37529
38118
|
const detectedHarness = await detectPreferredHarness(resolvedProjectRoot, settings.agents.defaultHarness);
|
|
37530
38119
|
const runtimeDefaults = config2.agent?.runtime?.defaults;
|
|
@@ -37562,7 +38151,7 @@ async function resolveManifestBackedAgent(projectRoot, config2, settings, overri
|
|
|
37562
38151
|
return mergeResolvedAgentConfig(base, override, settings);
|
|
37563
38152
|
}
|
|
37564
38153
|
async function resolveInferredAgent(projectRoot, settings, override) {
|
|
37565
|
-
const projectName =
|
|
38154
|
+
const projectName = basename15(projectRoot);
|
|
37566
38155
|
const definitionId = normalizeAgentId(override?.definitionId?.trim() || projectName);
|
|
37567
38156
|
const detectedHarness = await detectPreferredHarness(projectRoot, settings.agents.defaultHarness);
|
|
37568
38157
|
const defaultHarness = normalizeManagedHarness(override?.defaultHarness ?? override?.runtime?.harness, normalizeManagedHarness(detectedHarness, "claude"));
|
|
@@ -37598,7 +38187,7 @@ async function resolveInferredAgent(projectRoot, settings, override) {
|
|
|
37598
38187
|
return mergeResolvedAgentConfig(base, override, settings);
|
|
37599
38188
|
}
|
|
37600
38189
|
async function buildProjectInventoryEntry(agent, sourceRoot) {
|
|
37601
|
-
const manifestRoot = agent.projectConfigPath ? normalizePath(
|
|
38190
|
+
const manifestRoot = agent.projectConfigPath ? normalizePath(join26(dirname14(agent.projectConfigPath), "..")) : null;
|
|
37602
38191
|
const manifest = manifestRoot ? await readProjectConfig(manifestRoot) : null;
|
|
37603
38192
|
const markers = await detectHarnessMarkers(agent.projectRoot);
|
|
37604
38193
|
const harnesses = new Map;
|
|
@@ -37706,7 +38295,7 @@ async function loadResolvedRelayAgents(options = {}) {
|
|
|
37706
38295
|
const sourceRootByProject = new Map(workspaceCandidates.map((candidate) => [candidate.projectRoot, candidate.sourceRoot]));
|
|
37707
38296
|
if (process.env.OPENSCOUT_SKIP_USER_PROJECT_HINTS !== "1") {
|
|
37708
38297
|
try {
|
|
37709
|
-
const hintHome = options.userLevelHintsHome ??
|
|
38298
|
+
const hintHome = options.userLevelHintsHome ?? homedir25();
|
|
37710
38299
|
const userHints = await collectUserLevelProjectRootHints({ home: hintHome });
|
|
37711
38300
|
for (const hint of userHints) {
|
|
37712
38301
|
const normalized = normalizePath(hint);
|
|
@@ -37862,13 +38451,13 @@ async function ensureRelayAgentConfigured(value, options = {}) {
|
|
|
37862
38451
|
|
|
37863
38452
|
// packages/runtime/src/broker-process-manager.ts
|
|
37864
38453
|
import { spawn as spawn6, spawnSync as spawnSync2 } from "child_process";
|
|
37865
|
-
import { existsSync as
|
|
37866
|
-
import { homedir as
|
|
37867
|
-
import { dirname as
|
|
38454
|
+
import { existsSync as existsSync27, readFileSync as readFileSync13 } from "fs";
|
|
38455
|
+
import { homedir as homedir27 } from "os";
|
|
38456
|
+
import { dirname as dirname16, join as join28, resolve as resolve11 } from "path";
|
|
37868
38457
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
37869
38458
|
|
|
37870
38459
|
// packages/runtime/src/broker-api.ts
|
|
37871
|
-
import { existsSync as
|
|
38460
|
+
import { existsSync as existsSync25 } from "fs";
|
|
37872
38461
|
import { request as httpRequest } from "http";
|
|
37873
38462
|
var activeScoutBrokerServices = [];
|
|
37874
38463
|
var DEFAULT_BROKER_JSON_REQUEST_TIMEOUT_MS = 30000;
|
|
@@ -37925,7 +38514,7 @@ function errorMessage4(error48) {
|
|
|
37925
38514
|
}
|
|
37926
38515
|
function requestBrokerOverUnixSocket(socketPath, baseUrl, path, options) {
|
|
37927
38516
|
return new Promise((resolve11, reject) => {
|
|
37928
|
-
if (!
|
|
38517
|
+
if (!existsSync25(socketPath)) {
|
|
37929
38518
|
reject(Object.assign(new Error(`Scout broker socket does not exist: ${socketPath}`), { code: "ENOENT" }));
|
|
37930
38519
|
return;
|
|
37931
38520
|
}
|
|
@@ -38070,11 +38659,11 @@ function unregisterActiveScoutBrokerService(serviceOrBaseUrl) {
|
|
|
38070
38659
|
}
|
|
38071
38660
|
|
|
38072
38661
|
// packages/runtime/src/tailscale.ts
|
|
38073
|
-
import { readFileSync as
|
|
38662
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
38074
38663
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
38075
38664
|
var DEFAULT_TAILSCALE_STATUS_TIMEOUT_MS2 = 1500;
|
|
38076
38665
|
function readStatusJsonFromFileSync(filePath) {
|
|
38077
|
-
const raw =
|
|
38666
|
+
const raw = readFileSync11(filePath, "utf8");
|
|
38078
38667
|
return parseTailscaleStatusJson(raw);
|
|
38079
38668
|
}
|
|
38080
38669
|
function statusTimeoutMs2(env) {
|
|
@@ -38130,14 +38719,14 @@ function readTailscaleSelfWebHostsSync(env = process.env) {
|
|
|
38130
38719
|
|
|
38131
38720
|
// packages/runtime/src/local-config.ts
|
|
38132
38721
|
import {
|
|
38133
|
-
existsSync as
|
|
38722
|
+
existsSync as existsSync26,
|
|
38134
38723
|
mkdirSync as mkdirSync2,
|
|
38135
|
-
readFileSync as
|
|
38724
|
+
readFileSync as readFileSync12,
|
|
38136
38725
|
renameSync,
|
|
38137
38726
|
writeFileSync as writeFileSync2
|
|
38138
38727
|
} from "fs";
|
|
38139
|
-
import { homedir as
|
|
38140
|
-
import { dirname as
|
|
38728
|
+
import { homedir as homedir26, hostname as osHostname } from "os";
|
|
38729
|
+
import { dirname as dirname15, join as join27 } from "path";
|
|
38141
38730
|
var LOCAL_CONFIG_VERSION = 1;
|
|
38142
38731
|
var DEFAULT_SCOUT_WEB_PORTAL_HOST = "scout.local";
|
|
38143
38732
|
var DEFAULT_SCOUT_WEB_DEV_HOST = `dev.${DEFAULT_SCOUT_WEB_PORTAL_HOST}`;
|
|
@@ -38162,17 +38751,17 @@ var DEFAULT_LOCAL_CONFIG = {
|
|
|
38162
38751
|
}
|
|
38163
38752
|
};
|
|
38164
38753
|
function localConfigHome() {
|
|
38165
|
-
return process.env.OPENSCOUT_HOME ??
|
|
38754
|
+
return process.env.OPENSCOUT_HOME ?? join27(homedir26(), ".openscout");
|
|
38166
38755
|
}
|
|
38167
38756
|
function localConfigPath() {
|
|
38168
|
-
return
|
|
38757
|
+
return join27(localConfigHome(), "config.json");
|
|
38169
38758
|
}
|
|
38170
38759
|
function loadLocalConfig() {
|
|
38171
38760
|
const configPath = localConfigPath();
|
|
38172
|
-
if (!
|
|
38761
|
+
if (!existsSync26(configPath))
|
|
38173
38762
|
return { version: LOCAL_CONFIG_VERSION };
|
|
38174
38763
|
try {
|
|
38175
|
-
return validateLocalConfig(JSON.parse(
|
|
38764
|
+
return validateLocalConfig(JSON.parse(readFileSync12(configPath, "utf8")));
|
|
38176
38765
|
} catch {
|
|
38177
38766
|
return { version: LOCAL_CONFIG_VERSION };
|
|
38178
38767
|
}
|
|
@@ -38375,7 +38964,7 @@ function buildLocalBrokerControlUrl(host = DEFAULT_BROKER_HOST, port = DEFAULT_B
|
|
|
38375
38964
|
return buildDefaultBrokerUrl(localBrokerControlHost2(host), port);
|
|
38376
38965
|
}
|
|
38377
38966
|
function buildDefaultBrokerSocketPath(runtimeDirectory) {
|
|
38378
|
-
return
|
|
38967
|
+
return join28(runtimeDirectory, "broker.sock");
|
|
38379
38968
|
}
|
|
38380
38969
|
var DEFAULT_BROKER_URL = buildDefaultBrokerUrl();
|
|
38381
38970
|
function normalizeBrokerUrl(value) {
|
|
@@ -38408,17 +38997,17 @@ function runtimePackageDir() {
|
|
|
38408
38997
|
const fromGlobal = findGlobalRuntimeDir();
|
|
38409
38998
|
if (fromGlobal)
|
|
38410
38999
|
return fromGlobal;
|
|
38411
|
-
const moduleDir =
|
|
39000
|
+
const moduleDir = dirname16(fileURLToPath5(import.meta.url));
|
|
38412
39001
|
return resolve11(moduleDir, "..");
|
|
38413
39002
|
}
|
|
38414
39003
|
function isInstalledRuntimePackageDir(candidate) {
|
|
38415
|
-
return
|
|
39004
|
+
return existsSync27(join28(candidate, "package.json")) && existsSync27(join28(candidate, "bin", "openscout-runtime.mjs"));
|
|
38416
39005
|
}
|
|
38417
39006
|
function findGlobalRuntimeDir() {
|
|
38418
39007
|
const candidates = [
|
|
38419
|
-
|
|
38420
|
-
|
|
38421
|
-
|
|
39008
|
+
join28(homedir27(), ".bun", "node_modules", "@openscout", "runtime"),
|
|
39009
|
+
join28(homedir27(), ".bun", "install", "global", "node_modules", "@openscout", "runtime"),
|
|
39010
|
+
join28(homedir27(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime")
|
|
38422
39011
|
];
|
|
38423
39012
|
for (const c of candidates) {
|
|
38424
39013
|
if (isInstalledRuntimePackageDir(c))
|
|
@@ -38431,7 +39020,7 @@ function findGlobalRuntimeDir() {
|
|
|
38431
39020
|
const scoutPkg = resolve11(scoutBin, "..", "..");
|
|
38432
39021
|
if (isInstalledRuntimePackageDir(scoutPkg))
|
|
38433
39022
|
return scoutPkg;
|
|
38434
|
-
const nested =
|
|
39023
|
+
const nested = join28(scoutPkg, "node_modules", "@openscout", "runtime");
|
|
38435
39024
|
if (isInstalledRuntimePackageDir(nested))
|
|
38436
39025
|
return nested;
|
|
38437
39026
|
const sibling = resolve11(scoutPkg, "..", "runtime");
|
|
@@ -38442,7 +39031,7 @@ function findGlobalRuntimeDir() {
|
|
|
38442
39031
|
return null;
|
|
38443
39032
|
}
|
|
38444
39033
|
function findBundledRuntimeDir() {
|
|
38445
|
-
const moduleDir =
|
|
39034
|
+
const moduleDir = dirname16(fileURLToPath5(import.meta.url));
|
|
38446
39035
|
return resolveBundledRuntimeDirFromModuleDir(moduleDir);
|
|
38447
39036
|
}
|
|
38448
39037
|
function resolveBundledRuntimeDirFromModuleDir(moduleDir) {
|
|
@@ -38459,11 +39048,11 @@ function resolveBundledRuntimeDirFromModuleDir(moduleDir) {
|
|
|
38459
39048
|
function findWorkspaceRuntimeDir(startDir) {
|
|
38460
39049
|
let current = resolve11(startDir);
|
|
38461
39050
|
while (true) {
|
|
38462
|
-
const candidate =
|
|
38463
|
-
if (
|
|
39051
|
+
const candidate = join28(current, "packages", "runtime");
|
|
39052
|
+
if (existsSync27(join28(candidate, "package.json")) && existsSync27(join28(candidate, "src"))) {
|
|
38464
39053
|
return candidate;
|
|
38465
39054
|
}
|
|
38466
|
-
const parent =
|
|
39055
|
+
const parent = dirname16(current);
|
|
38467
39056
|
if (parent === current)
|
|
38468
39057
|
return null;
|
|
38469
39058
|
current = parent;
|
|
@@ -38510,17 +39099,17 @@ function resolveBrokerServiceConfig() {
|
|
|
38510
39099
|
const serviceAdapter = resolveBrokerServiceAdapter();
|
|
38511
39100
|
const uid = typeof process.getuid === "function" ? process.getuid() : Number.parseInt(process.env.UID ?? "0", 10);
|
|
38512
39101
|
const supportPaths = resolveOpenScoutSupportPaths();
|
|
38513
|
-
const defaultSupportDir =
|
|
39102
|
+
const defaultSupportDir = join28(homedir27(), "Library", "Application Support", "OpenScout");
|
|
38514
39103
|
const supportDirectory = isTmpPath(supportPaths.supportDirectory) ? defaultSupportDir : supportPaths.supportDirectory;
|
|
38515
|
-
const runtimeDirectory =
|
|
38516
|
-
const logsDirectory =
|
|
38517
|
-
const controlHome = isTmpPath(supportPaths.controlHome) ?
|
|
39104
|
+
const runtimeDirectory = join28(supportDirectory, "runtime");
|
|
39105
|
+
const logsDirectory = join28(supportDirectory, "logs", "broker");
|
|
39106
|
+
const controlHome = isTmpPath(supportPaths.controlHome) ? join28(homedir27(), ".openscout", "control-plane") : supportPaths.controlHome;
|
|
38518
39107
|
const advertiseScope = resolveAdvertiseScope();
|
|
38519
39108
|
const brokerHost = resolveBrokerHost(advertiseScope);
|
|
38520
39109
|
const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(resolveBrokerPort()), 10);
|
|
38521
39110
|
const brokerUrl = resolveBrokerUrl(brokerHost, brokerPort, advertiseScope);
|
|
38522
39111
|
const brokerSocketPath = process.env.OPENSCOUT_BROKER_SOCKET_PATH ?? buildDefaultBrokerSocketPath(runtimeDirectory);
|
|
38523
|
-
const launchAgentPath =
|
|
39112
|
+
const launchAgentPath = join28(homedir27(), "Library", "LaunchAgents", `${label}.plist`);
|
|
38524
39113
|
return {
|
|
38525
39114
|
label,
|
|
38526
39115
|
mode,
|
|
@@ -38531,8 +39120,8 @@ function resolveBrokerServiceConfig() {
|
|
|
38531
39120
|
supportDirectory,
|
|
38532
39121
|
runtimeDirectory,
|
|
38533
39122
|
logsDirectory,
|
|
38534
|
-
stdoutLogPath:
|
|
38535
|
-
stderrLogPath:
|
|
39123
|
+
stdoutLogPath: join28(logsDirectory, "stdout.log"),
|
|
39124
|
+
stderrLogPath: join28(logsDirectory, "stderr.log"),
|
|
38536
39125
|
controlHome,
|
|
38537
39126
|
runtimePackageDir: runtimePackageDir(),
|
|
38538
39127
|
bunExecutable: serviceAdapter === "macos-scoutd" ? resolveBunExecutable3() : resolveOptionalBunExecutable(),
|
|
@@ -38566,10 +39155,10 @@ function resolveEnvExecutable(value) {
|
|
|
38566
39155
|
function findWorkspaceRootFromRuntimeDir(runtimePackageDir2) {
|
|
38567
39156
|
let current = resolve11(runtimePackageDir2);
|
|
38568
39157
|
while (true) {
|
|
38569
|
-
if (
|
|
39158
|
+
if (existsSync27(join28(current, "Cargo.toml")) && existsSync27(join28(current, "crates", "scoutd", "Cargo.toml"))) {
|
|
38570
39159
|
return current;
|
|
38571
39160
|
}
|
|
38572
|
-
const parent =
|
|
39161
|
+
const parent = dirname16(current);
|
|
38573
39162
|
if (parent === current)
|
|
38574
39163
|
return null;
|
|
38575
39164
|
current = parent;
|
|
@@ -38586,13 +39175,13 @@ function resolveScoutdCommand(config2 = resolveBrokerServiceConfig()) {
|
|
|
38586
39175
|
}
|
|
38587
39176
|
const workspaceRoot = findWorkspaceRootFromRuntimeDir(config2.runtimePackageDir);
|
|
38588
39177
|
const packageCandidates = [
|
|
38589
|
-
|
|
38590
|
-
|
|
38591
|
-
|
|
38592
|
-
workspaceRoot ?
|
|
38593
|
-
workspaceRoot ?
|
|
38594
|
-
|
|
38595
|
-
|
|
39178
|
+
join28(config2.runtimePackageDir, "bin", "scoutd"),
|
|
39179
|
+
join28(config2.runtimePackageDir, "native", "scoutd"),
|
|
39180
|
+
join28(config2.runtimePackageDir, "scoutd"),
|
|
39181
|
+
workspaceRoot ? join28(workspaceRoot, "packages", "cli", "bin", "scoutd") : null,
|
|
39182
|
+
workspaceRoot ? join28(workspaceRoot, "packages", "runtime", "bin", "scoutd") : null,
|
|
39183
|
+
join28(config2.runtimeDirectory, "scoutd"),
|
|
39184
|
+
join28(dirname16(config2.runtimePackageDir), "scout", "bin", "scoutd")
|
|
38596
39185
|
];
|
|
38597
39186
|
for (const candidate of packageCandidates) {
|
|
38598
39187
|
const resolved = executableCandidate(candidate);
|
|
@@ -38606,8 +39195,8 @@ function resolveScoutdCommand(config2 = resolveBrokerServiceConfig()) {
|
|
|
38606
39195
|
}
|
|
38607
39196
|
if (workspaceRoot && workspaceScoutdAllowed()) {
|
|
38608
39197
|
for (const candidate of [
|
|
38609
|
-
|
|
38610
|
-
|
|
39198
|
+
join28(workspaceRoot, "target", "release", "scoutd"),
|
|
39199
|
+
join28(workspaceRoot, "target", "debug", "scoutd")
|
|
38611
39200
|
]) {
|
|
38612
39201
|
const resolved = executableCandidate(candidate);
|
|
38613
39202
|
if (resolved) {
|
|
@@ -38641,7 +39230,7 @@ function nativeServiceEnvironment(config2, scoutdPath) {
|
|
|
38641
39230
|
}
|
|
38642
39231
|
return env;
|
|
38643
39232
|
}
|
|
38644
|
-
function
|
|
39233
|
+
function isRecord7(value) {
|
|
38645
39234
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38646
39235
|
}
|
|
38647
39236
|
function readString3(value) {
|
|
@@ -38656,8 +39245,31 @@ function readNumber3(value) {
|
|
|
38656
39245
|
function readHealthTransport(value) {
|
|
38657
39246
|
return value === "unix_socket" || value === "http" || value === "in_process" ? value : undefined;
|
|
38658
39247
|
}
|
|
39248
|
+
function readRuntimeFreshness(value) {
|
|
39249
|
+
if (!isRecord7(value))
|
|
39250
|
+
return;
|
|
39251
|
+
const state = readString3(value.state);
|
|
39252
|
+
const basis = readString3(value.basis);
|
|
39253
|
+
const detail = readString3(value.detail);
|
|
39254
|
+
if (!state || !basis || !detail)
|
|
39255
|
+
return;
|
|
39256
|
+
return {
|
|
39257
|
+
state,
|
|
39258
|
+
intentional: readBoolean(value.intentional) ?? false,
|
|
39259
|
+
basis,
|
|
39260
|
+
artifactCommit: readString3(value.artifactCommit) ?? null,
|
|
39261
|
+
expectedCommit: readString3(value.expectedCommit) ?? null,
|
|
39262
|
+
pin: readString3(value.pin) ?? null,
|
|
39263
|
+
pinReason: readString3(value.pinReason) ?? null,
|
|
39264
|
+
manifestPath: readString3(value.manifestPath) ?? null,
|
|
39265
|
+
version: readString3(value.version) ?? null,
|
|
39266
|
+
builtAt: readString3(value.builtAt) ?? null,
|
|
39267
|
+
sourceDirty: readBoolean(value.sourceDirty) ?? null,
|
|
39268
|
+
detail
|
|
39269
|
+
};
|
|
39270
|
+
}
|
|
38659
39271
|
function normalizeNativeServiceStatus(input, config2) {
|
|
38660
|
-
const healthRecord =
|
|
39272
|
+
const healthRecord = isRecord7(input.health) ? input.health : {};
|
|
38661
39273
|
const healthReachable = readBoolean(healthRecord.reachable) ?? readBoolean(input.reachable) ?? false;
|
|
38662
39274
|
const healthOk = readBoolean(healthRecord.ok) ?? (typeof input.health === "boolean" ? input.health : undefined) ?? false;
|
|
38663
39275
|
const healthError = readString3(healthRecord.error) ?? readString3(input.healthError);
|
|
@@ -38665,12 +39277,13 @@ function normalizeNativeServiceStatus(input, config2) {
|
|
|
38665
39277
|
const healthNodeId = readString3(healthRecord.nodeId);
|
|
38666
39278
|
const healthMeshId = readString3(healthRecord.meshId);
|
|
38667
39279
|
const healthSocketFallbackError = readString3(healthRecord.socketFallbackError);
|
|
38668
|
-
const healthCounts =
|
|
38669
|
-
const installed = readBoolean(input.installed) ??
|
|
39280
|
+
const healthCounts = isRecord7(healthRecord.counts) ? healthRecord.counts : undefined;
|
|
39281
|
+
const installed = readBoolean(input.installed) ?? existsSync27(config2.launchAgentPath);
|
|
38670
39282
|
const loaded = readBoolean(input.loaded) ?? false;
|
|
38671
39283
|
const stdoutLogPath = readString3(input.stdoutLogPath) ?? config2.stdoutLogPath;
|
|
38672
39284
|
const stderrLogPath = readString3(input.stderrLogPath) ?? config2.stderrLogPath;
|
|
38673
39285
|
const lastLogLine = readString3(input.lastLogLine) ?? (healthReachable ? readLastLogLine([stdoutLogPath, stderrLogPath]) : readLastLogLine([stderrLogPath, stdoutLogPath]));
|
|
39286
|
+
const runtimeFreshness = readRuntimeFreshness(input.runtimeFreshness);
|
|
38674
39287
|
return {
|
|
38675
39288
|
label: readString3(input.label) ?? config2.label,
|
|
38676
39289
|
mode: readString3(input.mode) ?? config2.mode,
|
|
@@ -38701,10 +39314,11 @@ function normalizeNativeServiceStatus(input, config2) {
|
|
|
38701
39314
|
...healthNodeId ? { nodeId: healthNodeId } : {},
|
|
38702
39315
|
...healthMeshId ? { meshId: healthMeshId } : {},
|
|
38703
39316
|
...healthCounts ? { counts: healthCounts } : {},
|
|
38704
|
-
...
|
|
38705
|
-
...
|
|
39317
|
+
...isRecord7(healthRecord.build) ? { build: healthRecord.build } : {},
|
|
39318
|
+
...isRecord7(healthRecord.services) ? { services: healthRecord.services } : {},
|
|
38706
39319
|
error: healthError
|
|
38707
39320
|
},
|
|
39321
|
+
...runtimeFreshness ? { runtimeFreshness } : {},
|
|
38708
39322
|
lastLogLine
|
|
38709
39323
|
};
|
|
38710
39324
|
}
|
|
@@ -38796,7 +39410,7 @@ async function runScoutdServiceCommand(command, config2, timeoutMs = SCOUTD_DEFA
|
|
|
38796
39410
|
function readCoreAgentsSync() {
|
|
38797
39411
|
try {
|
|
38798
39412
|
const settingsPath = resolveOpenScoutSupportPaths().settingsPath;
|
|
38799
|
-
const raw =
|
|
39413
|
+
const raw = readFileSync13(settingsPath, "utf8");
|
|
38800
39414
|
const settings = JSON.parse(raw);
|
|
38801
39415
|
const raw_agents = settings?.agents?.coreAgents;
|
|
38802
39416
|
if (Array.isArray(raw_agents)) {
|
|
@@ -38809,10 +39423,10 @@ function bootoutCommand(config2) {
|
|
|
38809
39423
|
return `/bin/launchctl bootout ${config2.serviceTarget}`;
|
|
38810
39424
|
}
|
|
38811
39425
|
function readLogLines(path) {
|
|
38812
|
-
if (!
|
|
39426
|
+
if (!existsSync27(path)) {
|
|
38813
39427
|
return [];
|
|
38814
39428
|
}
|
|
38815
|
-
return
|
|
39429
|
+
return readFileSync13(path, "utf8").split(`
|
|
38816
39430
|
`).map((line) => line.trim()).filter(Boolean);
|
|
38817
39431
|
}
|
|
38818
39432
|
function isPackageScriptBanner(line) {
|
|
@@ -39009,8 +39623,12 @@ function formatBrokerServiceStatus(status) {
|
|
|
39009
39623
|
`reachable: ${status.reachable ? "yes" : "no"}`,
|
|
39010
39624
|
`health: ${status.health.ok ? "ok" : status.health.error ?? "unreachable"}`,
|
|
39011
39625
|
`health transport: ${status.health.transport ?? "unknown"}`,
|
|
39626
|
+
`runtime freshness: ${status.runtimeFreshness?.state ?? "unavailable"}`,
|
|
39012
39627
|
`logs: ${status.stdoutLogPath}`
|
|
39013
39628
|
];
|
|
39629
|
+
if (status.runtimeFreshness) {
|
|
39630
|
+
lines.push(`runtime freshness detail: ${status.runtimeFreshness.detail}`);
|
|
39631
|
+
}
|
|
39014
39632
|
if (status.health.socketFallbackError) {
|
|
39015
39633
|
lines.push(`socket fallback: ${status.health.socketFallbackError}`);
|
|
39016
39634
|
}
|
|
@@ -39087,28 +39705,28 @@ function compileCodexPermissionProfile(profileInput) {
|
|
|
39087
39705
|
}
|
|
39088
39706
|
|
|
39089
39707
|
// packages/runtime/src/user-config.ts
|
|
39090
|
-
import { existsSync as
|
|
39091
|
-
import { homedir as
|
|
39092
|
-
import { dirname as
|
|
39708
|
+
import { existsSync as existsSync28, readFileSync as readFileSync14, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
39709
|
+
import { homedir as homedir28 } from "os";
|
|
39710
|
+
import { dirname as dirname17, join as join29 } from "path";
|
|
39093
39711
|
function userConfigPath() {
|
|
39094
|
-
return
|
|
39712
|
+
return join29(process.env.OPENSCOUT_HOME ?? join29(homedir28(), ".openscout"), "user.json");
|
|
39095
39713
|
}
|
|
39096
39714
|
function loadUserConfig() {
|
|
39097
39715
|
const configPath = userConfigPath();
|
|
39098
|
-
if (!
|
|
39716
|
+
if (!existsSync28(configPath))
|
|
39099
39717
|
return {};
|
|
39100
39718
|
try {
|
|
39101
|
-
return JSON.parse(
|
|
39719
|
+
return JSON.parse(readFileSync14(configPath, "utf8"));
|
|
39102
39720
|
} catch {
|
|
39103
39721
|
return {};
|
|
39104
39722
|
}
|
|
39105
39723
|
}
|
|
39106
39724
|
function readSettingsOperatorName() {
|
|
39107
39725
|
const settingsPath = resolveOpenScoutSupportPaths().settingsPath;
|
|
39108
|
-
if (!
|
|
39726
|
+
if (!existsSync28(settingsPath))
|
|
39109
39727
|
return "";
|
|
39110
39728
|
try {
|
|
39111
|
-
const settings = JSON.parse(
|
|
39729
|
+
const settings = JSON.parse(readFileSync14(settingsPath, "utf8"));
|
|
39112
39730
|
const candidate = typeof settings.profile?.operatorName === "string" ? settings.profile.operatorName : typeof settings.operatorName === "string" ? settings.operatorName : "";
|
|
39113
39731
|
return candidate.trim();
|
|
39114
39732
|
} catch {
|
|
@@ -39128,7 +39746,7 @@ function resolveOperatorHandle() {
|
|
|
39128
39746
|
}
|
|
39129
39747
|
|
|
39130
39748
|
// packages/runtime/src/local-agents.ts
|
|
39131
|
-
var MODULE_DIRECTORY =
|
|
39749
|
+
var MODULE_DIRECTORY = dirname18(fileURLToPath6(import.meta.url));
|
|
39132
39750
|
var OPENSCOUT_REPO_ROOT = resolve12(MODULE_DIRECTORY, "..", "..", "..");
|
|
39133
39751
|
function isBrokerSnapshotMessage(value) {
|
|
39134
39752
|
if (!value || typeof value !== "object")
|
|
@@ -39156,14 +39774,14 @@ function resolveProjectsRoot(projectPath) {
|
|
|
39156
39774
|
}
|
|
39157
39775
|
try {
|
|
39158
39776
|
const supportPaths = resolveOpenScoutSupportPaths();
|
|
39159
|
-
if (!
|
|
39160
|
-
return
|
|
39777
|
+
if (!existsSync29(supportPaths.settingsPath)) {
|
|
39778
|
+
return dirname18(projectPath);
|
|
39161
39779
|
}
|
|
39162
|
-
const raw = JSON.parse(
|
|
39780
|
+
const raw = JSON.parse(readFileSync15(supportPaths.settingsPath, "utf8"));
|
|
39163
39781
|
const workspaceRoot = raw.discovery?.workspaceRoots?.find((entry) => typeof entry === "string" && entry.trim().length > 0);
|
|
39164
|
-
return workspaceRoot ? resolve12(workspaceRoot) :
|
|
39782
|
+
return workspaceRoot ? resolve12(workspaceRoot) : dirname18(projectPath);
|
|
39165
39783
|
} catch {
|
|
39166
|
-
return
|
|
39784
|
+
return dirname18(projectPath);
|
|
39167
39785
|
}
|
|
39168
39786
|
}
|
|
39169
39787
|
function resolveBrokerUrl2() {
|
|
@@ -39181,7 +39799,7 @@ function normalizeBrokerTimestamp(value) {
|
|
|
39181
39799
|
return ms === null ? 0 : Math.floor(ms / 1000);
|
|
39182
39800
|
}
|
|
39183
39801
|
function scoutCliPath() {
|
|
39184
|
-
return
|
|
39802
|
+
return join30(OPENSCOUT_REPO_ROOT, "packages", "cli", "bin", "scout.mjs");
|
|
39185
39803
|
}
|
|
39186
39804
|
function legacyNodeBrokerRelayCommand() {
|
|
39187
39805
|
return `node ${JSON.stringify(scoutCliPath())}`;
|
|
@@ -39205,17 +39823,18 @@ var SUPPORTED_LOCAL_AGENT_HARNESSES = ["claude", "codex", "grok", "pi"];
|
|
|
39205
39823
|
var SUPPORTED_SCOUT_HARNESSES = [
|
|
39206
39824
|
...SUPPORTED_LOCAL_AGENT_HARNESSES,
|
|
39207
39825
|
"grok-acp",
|
|
39826
|
+
"kimi",
|
|
39208
39827
|
"flue"
|
|
39209
39828
|
];
|
|
39210
39829
|
function resolveScoutSkillPath() {
|
|
39211
39830
|
const candidatePaths = [
|
|
39212
|
-
|
|
39213
|
-
|
|
39214
|
-
|
|
39215
|
-
|
|
39831
|
+
join30(OPENSCOUT_REPO_ROOT, ".agents", "skills", "scout", "SKILL.md"),
|
|
39832
|
+
join30(process.env.HOME ?? "", ".agents", "skills", "scout", "SKILL.md"),
|
|
39833
|
+
join30(OPENSCOUT_REPO_ROOT, ".agents", "skills", "relay-agent-comms", "SKILL.md"),
|
|
39834
|
+
join30(process.env.HOME ?? "", ".agents", "skills", "relay-agent-comms", "SKILL.md")
|
|
39216
39835
|
];
|
|
39217
39836
|
for (const path of candidatePaths) {
|
|
39218
|
-
if (
|
|
39837
|
+
if (existsSync29(path)) {
|
|
39219
39838
|
return path;
|
|
39220
39839
|
}
|
|
39221
39840
|
}
|
|
@@ -39485,7 +40104,7 @@ function expandHomePath4(value) {
|
|
|
39485
40104
|
return process.env.HOME ?? process.cwd();
|
|
39486
40105
|
}
|
|
39487
40106
|
if (value.startsWith("~/")) {
|
|
39488
|
-
return
|
|
40107
|
+
return join30(process.env.HOME ?? process.cwd(), value.slice(2));
|
|
39489
40108
|
}
|
|
39490
40109
|
return value;
|
|
39491
40110
|
}
|
|
@@ -39770,6 +40389,23 @@ function stripLaunchReasoningEffortForHarness(harness, launchArgs) {
|
|
|
39770
40389
|
}
|
|
39771
40390
|
return next2;
|
|
39772
40391
|
}
|
|
40392
|
+
if (harness === "claude" || harness === "grok") {
|
|
40393
|
+
const next2 = [];
|
|
40394
|
+
const normalized2 = normalizeLocalAgentLaunchArgs(launchArgs);
|
|
40395
|
+
const flags = ["--effort", "--reasoning-effort"];
|
|
40396
|
+
for (let index = 0;index < normalized2.length; index += 1) {
|
|
40397
|
+
const current = normalized2[index] ?? "";
|
|
40398
|
+
if (flags.includes(current)) {
|
|
40399
|
+
index += 1;
|
|
40400
|
+
continue;
|
|
40401
|
+
}
|
|
40402
|
+
if (flags.some((flag) => current.startsWith(`${flag}=`))) {
|
|
40403
|
+
continue;
|
|
40404
|
+
}
|
|
40405
|
+
next2.push(current);
|
|
40406
|
+
}
|
|
40407
|
+
return next2;
|
|
40408
|
+
}
|
|
39773
40409
|
if (harness !== "codex") {
|
|
39774
40410
|
return normalizeLaunchArgsForHarness(harness, launchArgs);
|
|
39775
40411
|
}
|
|
@@ -39803,6 +40439,9 @@ function buildLaunchArgsForRequestedReasoningEffort(harness, reasoningEffort) {
|
|
|
39803
40439
|
if (harness === "codex") {
|
|
39804
40440
|
return normalizeCodexAppServerLaunchArgs(["--reasoning-effort", reasoningEffort]);
|
|
39805
40441
|
}
|
|
40442
|
+
if (harness === "claude") {
|
|
40443
|
+
return ["--effort", reasoningEffort];
|
|
40444
|
+
}
|
|
39806
40445
|
if (harness === "pi") {
|
|
39807
40446
|
return ["--thinking", reasoningEffort.trim().toLowerCase() === "none" ? "off" : reasoningEffort];
|
|
39808
40447
|
}
|
|
@@ -39963,7 +40602,7 @@ function normalizeLocalAgentCardLifecycle(value, now = Date.now()) {
|
|
|
39963
40602
|
function normalizeLocalAgentRecord(agentId, record2) {
|
|
39964
40603
|
const cwd = normalizeProjectPath(record2.cwd || process.cwd());
|
|
39965
40604
|
const projectRoot = normalizeProjectPath(record2.projectRoot || cwd);
|
|
39966
|
-
const project = record2.project?.trim() ||
|
|
40605
|
+
const project = record2.project?.trim() || basename16(projectRoot);
|
|
39967
40606
|
const definitionId = record2.definitionId?.trim() || agentId;
|
|
39968
40607
|
const defaultHarness = activeLocalHarness(record2);
|
|
39969
40608
|
const harnessProfiles = normalizeLocalHarnessProfiles(agentId, {
|
|
@@ -40015,7 +40654,7 @@ function localAgentRecordFromRelayAgentOverride(agentId, override) {
|
|
|
40015
40654
|
return normalizeLocalAgentRecord(agentId, {
|
|
40016
40655
|
definitionId: override.definitionId ?? agentId,
|
|
40017
40656
|
registrationSource: override.source,
|
|
40018
|
-
project: override.projectName ??
|
|
40657
|
+
project: override.projectName ?? basename16(override.projectRoot || override.runtime?.cwd || agentId),
|
|
40019
40658
|
projectRoot: override.projectRoot ?? override.runtime?.cwd,
|
|
40020
40659
|
tmuxSession: override.runtime?.sessionId ?? `relay-${agentId}`,
|
|
40021
40660
|
cwd: override.runtime?.cwd ?? override.projectRoot,
|
|
@@ -40150,6 +40789,12 @@ function attachedCodexEndpointLaunchArgs(endpoint) {
|
|
|
40150
40789
|
reasoningEffort: endpointMetadataString(endpoint, "reasoningEffort")
|
|
40151
40790
|
});
|
|
40152
40791
|
}
|
|
40792
|
+
function attachedClaudeEndpointLaunchArgs(endpoint) {
|
|
40793
|
+
return applyRequestedRuntimeOptionsToLaunchArgs("claude", endpointMetadataStringArray(endpoint, "launchArgs"), {
|
|
40794
|
+
model: endpointMetadataString(endpoint, "model"),
|
|
40795
|
+
reasoningEffort: endpointMetadataString(endpoint, "reasoningEffort")
|
|
40796
|
+
});
|
|
40797
|
+
}
|
|
40153
40798
|
function attachedPiEndpointLaunchArgs(endpoint) {
|
|
40154
40799
|
return applyRequestedRuntimeOptionsToLaunchArgs("pi", endpointMetadataStringArray(endpoint, "launchArgs"), {
|
|
40155
40800
|
model: endpointMetadataString(endpoint, "model"),
|
|
@@ -40192,6 +40837,14 @@ function attachedLocalSessionSystemPrompt(endpoint) {
|
|
|
40192
40837
|
}
|
|
40193
40838
|
return "Resume the existing session without changing its identity or prior context.";
|
|
40194
40839
|
}
|
|
40840
|
+
function attachedCodexApprovalPolicy(endpoint) {
|
|
40841
|
+
const value = endpointMetadataString(endpoint, "approvalPolicy");
|
|
40842
|
+
return value === "untrusted" || value === "on-request" || value === "on-failure" || value === "never" ? value : undefined;
|
|
40843
|
+
}
|
|
40844
|
+
function attachedCodexSandbox(endpoint) {
|
|
40845
|
+
const value = endpointMetadataString(endpoint, "sandbox");
|
|
40846
|
+
return value === "read-only" || value === "workspace-write" || value === "danger-full-access" ? value : undefined;
|
|
40847
|
+
}
|
|
40195
40848
|
function buildCodexEndpointSessionOptions(endpoint) {
|
|
40196
40849
|
const agentName = endpointAgentName(endpoint);
|
|
40197
40850
|
const ownsSessionThread = endpoint.metadata?.source === "scoutbot";
|
|
@@ -40204,6 +40857,8 @@ function buildCodexEndpointSessionOptions(endpoint) {
|
|
|
40204
40857
|
runtimeDirectory: relayAgentRuntimeDirectory(agentName),
|
|
40205
40858
|
logsDirectory: relayAgentLogsDirectory(agentName),
|
|
40206
40859
|
launchArgs: attachedCodexEndpointLaunchArgs(endpoint),
|
|
40860
|
+
approvalPolicy: attachedCodexApprovalPolicy(endpoint),
|
|
40861
|
+
sandbox: attachedCodexSandbox(endpoint),
|
|
40207
40862
|
threadId,
|
|
40208
40863
|
requireExistingThread: Boolean(threadId) && !ownsSessionThread
|
|
40209
40864
|
});
|
|
@@ -40217,7 +40872,7 @@ function buildClaudeEndpointSessionOptions(endpoint) {
|
|
|
40217
40872
|
systemPrompt: attachedLocalSessionSystemPrompt(endpoint),
|
|
40218
40873
|
runtimeDirectory: relayAgentRuntimeDirectory(agentName),
|
|
40219
40874
|
logsDirectory: relayAgentLogsDirectory(agentName),
|
|
40220
|
-
launchArgs:
|
|
40875
|
+
launchArgs: attachedClaudeEndpointLaunchArgs(endpoint)
|
|
40221
40876
|
};
|
|
40222
40877
|
}
|
|
40223
40878
|
function buildPiEndpointSessionOptions(endpoint) {
|
|
@@ -40270,7 +40925,7 @@ function isLocalAgentEndpointAlive(endpoint) {
|
|
|
40270
40925
|
if (endpoint.transport === "pi_rpc") {
|
|
40271
40926
|
return isPiRpcAgentAlive(buildPiEndpointSessionOptions(endpoint));
|
|
40272
40927
|
}
|
|
40273
|
-
if (endpoint.transport === "grok_acp") {
|
|
40928
|
+
if (endpoint.transport === "grok_acp" || endpoint.transport === "kimi_acp") {
|
|
40274
40929
|
return endpoint.state !== "offline";
|
|
40275
40930
|
}
|
|
40276
40931
|
const sessionId = endpoint.sessionId ?? (typeof endpoint.metadata?.tmuxSession === "string" ? String(endpoint.metadata.tmuxSession) : null);
|
|
@@ -40434,7 +41089,7 @@ function buildScoutReplyContext(agentName, invocation) {
|
|
|
40434
41089
|
};
|
|
40435
41090
|
}
|
|
40436
41091
|
function scoutReplyContextPath(runtimeDirectory) {
|
|
40437
|
-
return
|
|
41092
|
+
return join30(runtimeDirectory, "scout-reply-context.json");
|
|
40438
41093
|
}
|
|
40439
41094
|
function withScoutReplyContextEnvironment(options) {
|
|
40440
41095
|
return {
|
|
@@ -40702,7 +41357,7 @@ function stripLocalAgentReplyMetadata(body, flightId, asker) {
|
|
|
40702
41357
|
async function sendLocalAgentPrompt(agentName, record2, prompt) {
|
|
40703
41358
|
const harness = normalizeLocalAgentHarness(record2.harness);
|
|
40704
41359
|
if (harness === "codex") {
|
|
40705
|
-
const promptPipe =
|
|
41360
|
+
const promptPipe = join30(relayAgentRuntimeDirectory(agentName), "prompt.pipe");
|
|
40706
41361
|
await writeFile8(promptPipe, prompt.trim() + "\x00");
|
|
40707
41362
|
return;
|
|
40708
41363
|
}
|
|
@@ -40939,10 +41594,10 @@ function buildLocalAgentLaunchCommand(agentName, record2, projectPath, promptFil
|
|
|
40939
41594
|
const harness = normalizeLocalAgentHarness(record2.harness);
|
|
40940
41595
|
const extraArgs = shellQuoteArguments(harness === "claude" ? normalizeClaudeRuntimeLaunchArgs(record2.launchArgs) : harness === "grok" ? normalizeGrokRuntimeLaunchArgs(record2.launchArgs) : normalizeLaunchArgsForHarness(harness, record2.launchArgs));
|
|
40941
41596
|
if (harness === "codex") {
|
|
40942
|
-
return `exec bash ${JSON.stringify(workerScript ??
|
|
41597
|
+
return `exec bash ${JSON.stringify(workerScript ?? join30(relayAgentRuntimeDirectory(agentName), "codex-worker.sh"))}`;
|
|
40943
41598
|
}
|
|
40944
41599
|
if (harness === "pi") {
|
|
40945
|
-
const sessionDir =
|
|
41600
|
+
const sessionDir = join30(relayAgentRuntimeDirectory(agentName), "pi-sessions");
|
|
40946
41601
|
return [
|
|
40947
41602
|
"pi",
|
|
40948
41603
|
`--append-system-prompt "$(cat ${JSON.stringify(promptFile)})"`,
|
|
@@ -40981,12 +41636,12 @@ function isShellCommandAvailable(binary) {
|
|
|
40981
41636
|
if (!binary.trim())
|
|
40982
41637
|
return false;
|
|
40983
41638
|
if (binary.includes("/"))
|
|
40984
|
-
return
|
|
41639
|
+
return existsSync29(binary);
|
|
40985
41640
|
const pathValue = process.env.PATH ?? "";
|
|
40986
41641
|
for (const directory of pathValue.split(":")) {
|
|
40987
41642
|
if (!directory)
|
|
40988
41643
|
continue;
|
|
40989
|
-
if (
|
|
41644
|
+
if (existsSync29(join30(directory, binary)))
|
|
40990
41645
|
return true;
|
|
40991
41646
|
}
|
|
40992
41647
|
return false;
|
|
@@ -41038,7 +41693,7 @@ async function ensureLocalAgentOnline(agentName, record2) {
|
|
|
41038
41693
|
return normalizedRecord;
|
|
41039
41694
|
}
|
|
41040
41695
|
const projectPath = normalizedRecord.cwd;
|
|
41041
|
-
const projectName = normalizedRecord.project ||
|
|
41696
|
+
const projectName = normalizedRecord.project || basename16(projectPath);
|
|
41042
41697
|
const systemPromptTemplate = normalizedRecord.systemPrompt || buildLocalAgentSystemPromptTemplate();
|
|
41043
41698
|
const systemPrompt = renderLocalAgentSystemPromptTemplate(systemPromptTemplate, buildLocalAgentTemplateContext(agentName, projectName, projectPath), { transport: normalizedRecord.transport });
|
|
41044
41699
|
const agentRuntimeDir = relayAgentRuntimeDirectory(agentName);
|
|
@@ -41046,7 +41701,7 @@ async function ensureLocalAgentOnline(agentName, record2) {
|
|
|
41046
41701
|
await mkdir8(agentRuntimeDir, { recursive: true });
|
|
41047
41702
|
await mkdir8(logsDir, { recursive: true });
|
|
41048
41703
|
if (normalizedRecord.transport === "codex_app_server") {
|
|
41049
|
-
await writeFile8(
|
|
41704
|
+
await writeFile8(join30(agentRuntimeDir, "prompt.txt"), systemPrompt);
|
|
41050
41705
|
await ensureCodexAppServerAgentOnline(buildCodexAgentSessionOptions(agentName, normalizedRecord, systemPrompt));
|
|
41051
41706
|
const registry4 = await readLocalAgentRegistry();
|
|
41052
41707
|
registry4[agentName] = {
|
|
@@ -41058,7 +41713,7 @@ async function ensureLocalAgentOnline(agentName, record2) {
|
|
|
41058
41713
|
return registry4[agentName];
|
|
41059
41714
|
}
|
|
41060
41715
|
if (normalizedRecord.transport === "claude_stream_json") {
|
|
41061
|
-
await writeFile8(
|
|
41716
|
+
await writeFile8(join30(agentRuntimeDir, "prompt.txt"), systemPrompt);
|
|
41062
41717
|
await ensureClaudeStreamJsonAgentOnline(buildClaudeAgentSessionOptions(agentName, normalizedRecord, systemPrompt));
|
|
41063
41718
|
const registry4 = await readLocalAgentRegistry();
|
|
41064
41719
|
registry4[agentName] = {
|
|
@@ -41070,7 +41725,7 @@ async function ensureLocalAgentOnline(agentName, record2) {
|
|
|
41070
41725
|
return registry4[agentName];
|
|
41071
41726
|
}
|
|
41072
41727
|
if (normalizedRecord.transport === "pi_rpc") {
|
|
41073
|
-
await writeFile8(
|
|
41728
|
+
await writeFile8(join30(agentRuntimeDir, "prompt.txt"), systemPrompt);
|
|
41074
41729
|
await ensurePiRpcAgentOnline(buildPiAgentSessionOptions(agentName, normalizedRecord, systemPrompt));
|
|
41075
41730
|
const registry4 = await readLocalAgentRegistry();
|
|
41076
41731
|
registry4[agentName] = {
|
|
@@ -41083,17 +41738,17 @@ async function ensureLocalAgentOnline(agentName, record2) {
|
|
|
41083
41738
|
}
|
|
41084
41739
|
const initialMessage = buildLocalAgentInitialMessage(projectName, agentName);
|
|
41085
41740
|
const bootstrapPrompt = buildLocalAgentBootstrapPrompt(normalizeLocalAgentHarness(normalizedRecord.harness), systemPrompt, initialMessage);
|
|
41086
|
-
const queueDirectory =
|
|
41087
|
-
const processingDirectory =
|
|
41088
|
-
const processedDirectory =
|
|
41089
|
-
const promptFile =
|
|
41090
|
-
const initialFile =
|
|
41091
|
-
const launchScript =
|
|
41092
|
-
const workerScript =
|
|
41093
|
-
const codexSessionIdFile =
|
|
41094
|
-
const stateFile =
|
|
41095
|
-
const stdoutLogFile =
|
|
41096
|
-
const stderrLogFile =
|
|
41741
|
+
const queueDirectory = join30(agentRuntimeDir, "queue");
|
|
41742
|
+
const processingDirectory = join30(queueDirectory, "processing");
|
|
41743
|
+
const processedDirectory = join30(queueDirectory, "processed");
|
|
41744
|
+
const promptFile = join30(agentRuntimeDir, "prompt.txt");
|
|
41745
|
+
const initialFile = join30(agentRuntimeDir, "initial.txt");
|
|
41746
|
+
const launchScript = join30(agentRuntimeDir, "launch.sh");
|
|
41747
|
+
const workerScript = join30(agentRuntimeDir, "codex-worker.sh");
|
|
41748
|
+
const codexSessionIdFile = join30(agentRuntimeDir, "codex-session-id.txt");
|
|
41749
|
+
const stateFile = join30(agentRuntimeDir, "state.json");
|
|
41750
|
+
const stdoutLogFile = join30(logsDir, "stdout.log");
|
|
41751
|
+
const stderrLogFile = join30(logsDir, "stderr.log");
|
|
41097
41752
|
await writeFile8(promptFile, systemPrompt);
|
|
41098
41753
|
await writeFile8(initialFile, bootstrapPrompt);
|
|
41099
41754
|
await writeFile8(stderrLogFile, "");
|
|
@@ -41157,14 +41812,15 @@ async function ensureLocalAgentOnline(agentName, record2) {
|
|
|
41157
41812
|
updatedAt: new Date().toISOString()
|
|
41158
41813
|
}, null, 2) + `
|
|
41159
41814
|
`);
|
|
41160
|
-
|
|
41161
|
-
|
|
41162
|
-
|
|
41815
|
+
let sessionOnline = false;
|
|
41816
|
+
for (let attempt = 0;attempt < 20 && !sessionOnline; attempt += 1) {
|
|
41817
|
+
sessionOnline = await isLocalAgentSessionAliveAsync(normalizedRecord.tmuxSession);
|
|
41818
|
+
if (!sessionOnline) {
|
|
41819
|
+
await new Promise((resolve13) => setTimeout(resolve13, 100));
|
|
41163
41820
|
}
|
|
41164
|
-
await new Promise((resolve13) => setTimeout(resolve13, 100));
|
|
41165
41821
|
}
|
|
41166
|
-
if (!
|
|
41167
|
-
const stderrTail =
|
|
41822
|
+
if (!sessionOnline) {
|
|
41823
|
+
const stderrTail = existsSync29(stderrLogFile) ? readFileSync15(stderrLogFile, "utf8").trim().split(/\r?\n/).slice(-10).join(`
|
|
41168
41824
|
`).trim() : "";
|
|
41169
41825
|
throw new Error(stderrTail ? `Relay agent ${agentName} failed to stay online:
|
|
41170
41826
|
${stderrTail}` : `Relay agent ${agentName} failed to stay online.`);
|
|
@@ -41186,9 +41842,9 @@ ${stderrTail}` : `Relay agent ${agentName} failed to stay online.`);
|
|
|
41186
41842
|
}
|
|
41187
41843
|
function readPersistedSessionCatalogId(runtimeDir) {
|
|
41188
41844
|
try {
|
|
41189
|
-
const catalogPath =
|
|
41190
|
-
if (
|
|
41191
|
-
const raw =
|
|
41845
|
+
const catalogPath = join30(runtimeDir, "session-catalog.json");
|
|
41846
|
+
if (existsSync29(catalogPath)) {
|
|
41847
|
+
const raw = readFileSync15(catalogPath, "utf8").trim();
|
|
41192
41848
|
if (raw) {
|
|
41193
41849
|
const catalog = JSON.parse(raw);
|
|
41194
41850
|
if (typeof catalog.activeSessionId === "string" && catalog.activeSessionId.trim()) {
|
|
@@ -41203,9 +41859,9 @@ function readPersistedSessionCatalogId(runtimeDir) {
|
|
|
41203
41859
|
}
|
|
41204
41860
|
function readPersistedLegacySessionId(runtimeDir, filename) {
|
|
41205
41861
|
try {
|
|
41206
|
-
const legacyPath =
|
|
41207
|
-
if (
|
|
41208
|
-
const value =
|
|
41862
|
+
const legacyPath = join30(runtimeDir, filename);
|
|
41863
|
+
if (existsSync29(legacyPath)) {
|
|
41864
|
+
const value = readFileSync15(legacyPath, "utf8").trim();
|
|
41209
41865
|
return value || null;
|
|
41210
41866
|
}
|
|
41211
41867
|
return null;
|
|
@@ -41502,11 +42158,27 @@ async function invokeLocalAgentEndpoint(endpoint, invocation) {
|
|
|
41502
42158
|
metadata: result.metadata
|
|
41503
42159
|
};
|
|
41504
42160
|
}
|
|
42161
|
+
if (!existing && endpoint.transport === "kimi_acp") {
|
|
42162
|
+
const cwd = endpoint.cwd ?? endpoint.projectRoot ?? process.cwd();
|
|
42163
|
+
const sessionId = endpoint.sessionId?.trim() || agentRuntimeId;
|
|
42164
|
+
const result = await invokeKimiAcpAgent({
|
|
42165
|
+
sessionId,
|
|
42166
|
+
cwd,
|
|
42167
|
+
prompt,
|
|
42168
|
+
name: String(endpoint.metadata?.agentName ?? endpoint.metadata?.definitionId ?? "Kimi Code ACP"),
|
|
42169
|
+
timeoutMs: invocation.timeoutMs
|
|
42170
|
+
});
|
|
42171
|
+
return {
|
|
42172
|
+
output: result.output,
|
|
42173
|
+
externalSessionId: result.sessionId,
|
|
42174
|
+
metadata: result.metadata
|
|
42175
|
+
};
|
|
42176
|
+
}
|
|
41505
42177
|
const projectRoot = endpoint.projectRoot ?? endpoint.cwd;
|
|
41506
42178
|
const requestedHarness = invocation.execution?.harness;
|
|
41507
42179
|
const record2 = existing ?? (projectRoot ? {
|
|
41508
42180
|
definitionId,
|
|
41509
|
-
project:
|
|
42181
|
+
project: basename16(projectRoot),
|
|
41510
42182
|
projectRoot,
|
|
41511
42183
|
tmuxSession: String(endpoint.metadata?.tmuxSession ?? `relay-${agentRuntimeId}`),
|
|
41512
42184
|
cwd: projectRoot,
|
|
@@ -41599,8 +42271,8 @@ function shouldDisableGeneratedCodexEndpoint(endpoint) {
|
|
|
41599
42271
|
}
|
|
41600
42272
|
|
|
41601
42273
|
// packages/runtime/src/scout-dispatcher.ts
|
|
41602
|
-
import { homedir as
|
|
41603
|
-
import { basename as
|
|
42274
|
+
import { homedir as homedir29 } from "os";
|
|
42275
|
+
import { basename as basename17, resolve as resolve13 } from "path";
|
|
41604
42276
|
|
|
41605
42277
|
// packages/runtime/src/a2a-http-endpoint.ts
|
|
41606
42278
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
@@ -41939,7 +42611,8 @@ var directLocalAgentTransports = new Set([
|
|
|
41939
42611
|
"codex_app_server",
|
|
41940
42612
|
"claude_stream_json",
|
|
41941
42613
|
"pi_rpc",
|
|
41942
|
-
"grok_acp"
|
|
42614
|
+
"grok_acp",
|
|
42615
|
+
"kimi_acp"
|
|
41943
42616
|
]);
|
|
41944
42617
|
function isDirectLocalAgentTransport(transport) {
|
|
41945
42618
|
return typeof transport === "string" && directLocalAgentTransports.has(transport);
|
|
@@ -42220,7 +42893,7 @@ function normalizeProjectPath2(value) {
|
|
|
42220
42893
|
const trimmed = value?.trim();
|
|
42221
42894
|
if (!trimmed)
|
|
42222
42895
|
return;
|
|
42223
|
-
const home = process.env.HOME?.trim() ||
|
|
42896
|
+
const home = process.env.HOME?.trim() || homedir29();
|
|
42224
42897
|
if (trimmed === "~")
|
|
42225
42898
|
return home;
|
|
42226
42899
|
if (trimmed.startsWith("~/"))
|
|
@@ -42445,7 +43118,7 @@ function resolveProjectPathTarget(snapshot, projectPath, options) {
|
|
|
42445
43118
|
function sessionTargetLabel(endpoint, sessionId) {
|
|
42446
43119
|
const shortId = sessionId.length > 8 ? sessionId.slice(0, 8) : sessionId;
|
|
42447
43120
|
const root = endpoint.cwd?.trim() || endpoint.projectRoot?.trim();
|
|
42448
|
-
return root ? `${
|
|
43121
|
+
return root ? `${basename17(root)}:${shortId}` : `session:${sessionId}`;
|
|
42449
43122
|
}
|
|
42450
43123
|
function resolveSessionTarget(snapshot, sessionId, options) {
|
|
42451
43124
|
const label = sessionRouteLabel(sessionId, options.harness);
|
|
@@ -42740,7 +43413,7 @@ class BrokerDeliveryRouter {
|
|
|
42740
43413
|
}
|
|
42741
43414
|
|
|
42742
43415
|
// packages/runtime/src/session-alias.ts
|
|
42743
|
-
import { basename as
|
|
43416
|
+
import { basename as basename18 } from "path";
|
|
42744
43417
|
function sessionActorAlias(snapshot, actorId) {
|
|
42745
43418
|
const actor = snapshot.actors[actorId];
|
|
42746
43419
|
if (!actor || actor.kind !== "session") {
|
|
@@ -42769,7 +43442,7 @@ function isCardlessSessionActor(snapshot, actorId) {
|
|
|
42769
43442
|
return endpoint?.metadata?.cardless === true;
|
|
42770
43443
|
}
|
|
42771
43444
|
function formatSessionAliasPointer(input) {
|
|
42772
|
-
const project = input.projectRoot?.trim() ?
|
|
43445
|
+
const project = input.projectRoot?.trim() ? basename18(input.projectRoot.trim()) : null;
|
|
42773
43446
|
const scope = [project, input.harness?.trim()].filter(Boolean).join(", ");
|
|
42774
43447
|
const target = input.sessionId.length > 24 ? `${input.sessionId.slice(0, 12)}\u2026${input.sessionId.slice(-6)}` : input.sessionId;
|
|
42775
43448
|
return scope ? `alias ${input.alias} \u2192 ${target} (${scope})` : `alias ${input.alias} \u2192 ${target}`;
|
|
@@ -44582,7 +45255,7 @@ class BrokerLocalAgentSyncService {
|
|
|
44582
45255
|
|
|
44583
45256
|
// packages/runtime/src/iroh-bridge.ts
|
|
44584
45257
|
import { spawn as spawn7 } from "child_process";
|
|
44585
|
-
import { join as
|
|
45258
|
+
import { join as join31 } from "path";
|
|
44586
45259
|
function resolveIrohBridgeBin() {
|
|
44587
45260
|
const explicit = process.env.OPENSCOUT_IROH_BRIDGE_BIN?.trim();
|
|
44588
45261
|
return explicit || null;
|
|
@@ -44592,7 +45265,7 @@ function resolveIrohBridgeIdentityPath() {
|
|
|
44592
45265
|
if (explicit) {
|
|
44593
45266
|
return explicit;
|
|
44594
45267
|
}
|
|
44595
|
-
return
|
|
45268
|
+
return join31(resolveOpenScoutSupportPaths().runtimeDirectory, "mesh", "iroh.key");
|
|
44596
45269
|
}
|
|
44597
45270
|
function canUseIrohBridge(options = {}) {
|
|
44598
45271
|
return Boolean(options.bridgeBin?.trim() || resolveIrohBridgeBin());
|
|
@@ -45458,9 +46131,9 @@ function createPeerDeliveryWorker(deps, config2 = {}) {
|
|
|
45458
46131
|
}
|
|
45459
46132
|
|
|
45460
46133
|
// packages/runtime/src/pairing-session-agents.ts
|
|
45461
|
-
import { existsSync as
|
|
45462
|
-
import { basename as
|
|
45463
|
-
import { homedir as
|
|
46134
|
+
import { existsSync as existsSync30, readFileSync as readFileSync16 } from "fs";
|
|
46135
|
+
import { basename as basename19, join as join32 } from "path";
|
|
46136
|
+
import { homedir as homedir30 } from "os";
|
|
45464
46137
|
var DEFAULT_PAIRING_PORT = 43130;
|
|
45465
46138
|
var PAIRING_CONNECT_TIMEOUT_MS = 1500;
|
|
45466
46139
|
var PAIRING_REQUEST_TIMEOUT_MS = 1e4;
|
|
@@ -45468,19 +46141,19 @@ var DEFAULT_PAIRING_POLL_INTERVAL_MS = 350;
|
|
|
45468
46141
|
var DEFAULT_PAIRING_INVOCATION_TIMEOUT_MS = 45000;
|
|
45469
46142
|
var MAX_SYNTHETIC_OUTPUT_CHARS = 1200;
|
|
45470
46143
|
function pairingPaths() {
|
|
45471
|
-
const home = process.env.HOME?.trim() ||
|
|
45472
|
-
const rootDir =
|
|
46144
|
+
const home = process.env.HOME?.trim() || homedir30();
|
|
46145
|
+
const rootDir = join32(home, ".scout", "pairing");
|
|
45473
46146
|
return {
|
|
45474
|
-
configPath:
|
|
45475
|
-
runtimeStatePath:
|
|
46147
|
+
configPath: join32(rootDir, "config.json"),
|
|
46148
|
+
runtimeStatePath: join32(rootDir, "runtime.json")
|
|
45476
46149
|
};
|
|
45477
46150
|
}
|
|
45478
46151
|
function readJsonFile4(filePath) {
|
|
45479
|
-
if (!
|
|
46152
|
+
if (!existsSync30(filePath)) {
|
|
45480
46153
|
return null;
|
|
45481
46154
|
}
|
|
45482
46155
|
try {
|
|
45483
|
-
return JSON.parse(
|
|
46156
|
+
return JSON.parse(readFileSync16(filePath, "utf8"));
|
|
45484
46157
|
} catch {
|
|
45485
46158
|
return null;
|
|
45486
46159
|
}
|
|
@@ -45490,7 +46163,7 @@ function resolvePairingBridgePort(options = {}) {
|
|
|
45490
46163
|
return options.port;
|
|
45491
46164
|
}
|
|
45492
46165
|
const { configPath, runtimeStatePath } = pairingPaths();
|
|
45493
|
-
const configExists =
|
|
46166
|
+
const configExists = existsSync30(configPath);
|
|
45494
46167
|
const runtimeSnapshot = readJsonFile4(runtimeStatePath);
|
|
45495
46168
|
if (!configExists && !runtimeSnapshot) {
|
|
45496
46169
|
return null;
|
|
@@ -45647,7 +46320,7 @@ function shortPairingSessionId(sessionId) {
|
|
|
45647
46320
|
}
|
|
45648
46321
|
function pairingProjectLabel(session) {
|
|
45649
46322
|
const cwd = session.cwd?.trim();
|
|
45650
|
-
return cwd ?
|
|
46323
|
+
return cwd ? basename19(cwd) : null;
|
|
45651
46324
|
}
|
|
45652
46325
|
function pairingDisplayName(session, shortId) {
|
|
45653
46326
|
const explicit = session.name?.trim();
|
|
@@ -45678,6 +46351,9 @@ function pairingHarness(adapterType) {
|
|
|
45678
46351
|
if (normalized === "grok-acp" || normalized.includes("grok") && normalized.includes("acp")) {
|
|
45679
46352
|
return "grok-acp";
|
|
45680
46353
|
}
|
|
46354
|
+
if (normalized === "kimi-acp" || normalized.includes("kimi")) {
|
|
46355
|
+
return "kimi";
|
|
46356
|
+
}
|
|
45681
46357
|
return "bridge";
|
|
45682
46358
|
}
|
|
45683
46359
|
function pairingEndpointState(status) {
|
|
@@ -46030,9 +46706,9 @@ async function invokePairingSessionEndpoint(endpoint, invocation, options = {})
|
|
|
46030
46706
|
}
|
|
46031
46707
|
|
|
46032
46708
|
// packages/runtime/src/sqlite-store.ts
|
|
46033
|
-
import { createHash as
|
|
46709
|
+
import { createHash as createHash4 } from "crypto";
|
|
46034
46710
|
import { mkdirSync as mkdirSync4 } from "fs";
|
|
46035
|
-
import { dirname as
|
|
46711
|
+
import { dirname as dirname19 } from "path";
|
|
46036
46712
|
|
|
46037
46713
|
// node_modules/.bun/drizzle-orm@0.45.2+e80f9ee8788b3855/node_modules/drizzle-orm/entity.js
|
|
46038
46714
|
var entityKind = Symbol.for("drizzle:entityKind");
|
|
@@ -46633,7 +47309,7 @@ function sql(strings, ...params) {
|
|
|
46633
47309
|
return new SQL([new StringChunk(str)]);
|
|
46634
47310
|
}
|
|
46635
47311
|
sql2.raw = raw;
|
|
46636
|
-
function
|
|
47312
|
+
function join33(chunks, separator) {
|
|
46637
47313
|
const result = [];
|
|
46638
47314
|
for (const [i, chunk] of chunks.entries()) {
|
|
46639
47315
|
if (i > 0 && separator !== undefined) {
|
|
@@ -46643,7 +47319,7 @@ function sql(strings, ...params) {
|
|
|
46643
47319
|
}
|
|
46644
47320
|
return new SQL(result);
|
|
46645
47321
|
}
|
|
46646
|
-
sql2.join =
|
|
47322
|
+
sql2.join = join33;
|
|
46647
47323
|
function identifier(value) {
|
|
46648
47324
|
return new Name(value);
|
|
46649
47325
|
}
|
|
@@ -48950,7 +49626,7 @@ class SQLiteSelectQueryBuilderBase extends TypedQueryBuilder {
|
|
|
48950
49626
|
const tableName = getTableLikeName(table);
|
|
48951
49627
|
for (const item of extractUsedTable(table))
|
|
48952
49628
|
this.usedTables.add(item);
|
|
48953
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
49629
|
+
if (typeof tableName === "string" && this.config.joins?.some((join33) => join33.alias === tableName)) {
|
|
48954
49630
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
48955
49631
|
}
|
|
48956
49632
|
if (!this.isPartialSelect) {
|
|
@@ -49364,7 +50040,7 @@ class SQLiteUpdateBase extends QueryPromise {
|
|
|
49364
50040
|
createJoin(joinType) {
|
|
49365
50041
|
return (table, on) => {
|
|
49366
50042
|
const tableName = getTableLikeName(table);
|
|
49367
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
50043
|
+
if (typeof tableName === "string" && this.config.joins.some((join33) => join33.alias === tableName)) {
|
|
49368
50044
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
49369
50045
|
}
|
|
49370
50046
|
if (typeof on === "function") {
|
|
@@ -50746,8 +51422,8 @@ class NodeSqliteDatabaseAdapter {
|
|
|
50746
51422
|
}
|
|
50747
51423
|
|
|
50748
51424
|
// packages/runtime/src/control-plane-migrations.ts
|
|
50749
|
-
import { existsSync as
|
|
50750
|
-
import { join as
|
|
51425
|
+
import { existsSync as existsSync31 } from "fs";
|
|
51426
|
+
import { join as join33 } from "path";
|
|
50751
51427
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
50752
51428
|
|
|
50753
51429
|
// node_modules/.bun/drizzle-orm@0.45.2+e80f9ee8788b3855/node_modules/drizzle-orm/migrator.js
|
|
@@ -51571,7 +52247,7 @@ function resolveControlPlaneDrizzleMigrationsFolder() {
|
|
|
51571
52247
|
const candidates = ["../drizzle", "./drizzle"];
|
|
51572
52248
|
for (const candidate of candidates) {
|
|
51573
52249
|
const folder = fileURLToPath7(new URL(candidate, import.meta.url));
|
|
51574
|
-
if (
|
|
52250
|
+
if (existsSync31(join33(folder, "meta", "_journal.json"))) {
|
|
51575
52251
|
return folder;
|
|
51576
52252
|
}
|
|
51577
52253
|
}
|
|
@@ -51613,8 +52289,8 @@ function controlPlaneDatabaseFilename(database) {
|
|
|
51613
52289
|
}
|
|
51614
52290
|
function applyControlPlaneDrizzleMigrations(database) {
|
|
51615
52291
|
const migrationsFolder = resolveControlPlaneDrizzleMigrationsFolder();
|
|
51616
|
-
const journalPath =
|
|
51617
|
-
if (!
|
|
52292
|
+
const journalPath = join33(migrationsFolder, "meta", "_journal.json");
|
|
52293
|
+
if (!existsSync31(journalPath)) {
|
|
51618
52294
|
return false;
|
|
51619
52295
|
}
|
|
51620
52296
|
const migrations = readMigrationFiles({ migrationsFolder });
|
|
@@ -51770,15 +52446,15 @@ class Conversations {
|
|
|
51770
52446
|
}
|
|
51771
52447
|
|
|
51772
52448
|
// packages/runtime/src/budget-observations.ts
|
|
51773
|
-
import { createHash as
|
|
52449
|
+
import { createHash as createHash3 } from "crypto";
|
|
51774
52450
|
var QUOTA_HISTORY_BUCKET_MS = 60 * 60 * 1000;
|
|
51775
52451
|
function stableHash(value) {
|
|
51776
|
-
return
|
|
52452
|
+
return createHash3("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 24);
|
|
51777
52453
|
}
|
|
51778
52454
|
function metadataRecord7(value) {
|
|
51779
52455
|
return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
51780
52456
|
}
|
|
51781
|
-
function
|
|
52457
|
+
function stringValue10(value) {
|
|
51782
52458
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
51783
52459
|
}
|
|
51784
52460
|
function numberValue6(value) {
|
|
@@ -51828,7 +52504,7 @@ function budgetObservationsFromEndpoint(endpoint, now = Date.now()) {
|
|
|
51828
52504
|
harness: endpoint.harness,
|
|
51829
52505
|
transport: endpoint.transport,
|
|
51830
52506
|
adapterType: endpoint.transport,
|
|
51831
|
-
model:
|
|
52507
|
+
model: stringValue10(metadata?.model),
|
|
51832
52508
|
sessionId: endpoint.sessionId,
|
|
51833
52509
|
projectRoot: endpoint.projectRoot,
|
|
51834
52510
|
cwd: endpoint.cwd,
|
|
@@ -51924,7 +52600,7 @@ function normalizeTimestampMs(value) {
|
|
|
51924
52600
|
return epochMs(value);
|
|
51925
52601
|
}
|
|
51926
52602
|
function stableHash2(value, length = 20) {
|
|
51927
|
-
return
|
|
52603
|
+
return createHash4("sha256").update(value).digest("hex").slice(0, length);
|
|
51928
52604
|
}
|
|
51929
52605
|
function metadataStringValue6(metadata, key) {
|
|
51930
52606
|
const value = metadata?.[key];
|
|
@@ -51960,29 +52636,29 @@ function isSqliteConstraintError(error48) {
|
|
|
51960
52636
|
function metadataValue2(metadata, key) {
|
|
51961
52637
|
return metadata?.[key];
|
|
51962
52638
|
}
|
|
51963
|
-
function
|
|
52639
|
+
function stringValue11(metadata, key) {
|
|
51964
52640
|
const value = metadataValue2(metadata, key);
|
|
51965
52641
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
51966
52642
|
}
|
|
51967
52643
|
function invocationStringValue2(invocation, key) {
|
|
51968
|
-
const contextValue =
|
|
52644
|
+
const contextValue = stringValue11(invocation.context, key);
|
|
51969
52645
|
if (contextValue) {
|
|
51970
52646
|
return contextValue;
|
|
51971
52647
|
}
|
|
51972
52648
|
const nestedContext = metadataValue2(invocation.context, "collaboration");
|
|
51973
52649
|
if (nestedContext && typeof nestedContext === "object" && !Array.isArray(nestedContext)) {
|
|
51974
|
-
const nestedValue =
|
|
52650
|
+
const nestedValue = stringValue11(nestedContext, key);
|
|
51975
52651
|
if (nestedValue) {
|
|
51976
52652
|
return nestedValue;
|
|
51977
52653
|
}
|
|
51978
52654
|
}
|
|
51979
|
-
const metadataEntry =
|
|
52655
|
+
const metadataEntry = stringValue11(invocation.metadata, key);
|
|
51980
52656
|
if (metadataEntry) {
|
|
51981
52657
|
return metadataEntry;
|
|
51982
52658
|
}
|
|
51983
52659
|
const nestedMetadata = metadataValue2(invocation.metadata, "collaboration");
|
|
51984
52660
|
if (nestedMetadata && typeof nestedMetadata === "object" && !Array.isArray(nestedMetadata)) {
|
|
51985
|
-
return
|
|
52661
|
+
return stringValue11(nestedMetadata, key);
|
|
51986
52662
|
}
|
|
51987
52663
|
return;
|
|
51988
52664
|
}
|
|
@@ -52300,7 +52976,7 @@ class SQLiteControlPlaneStore {
|
|
|
52300
52976
|
flushPendingEventsTimer = null;
|
|
52301
52977
|
conversationsApi = null;
|
|
52302
52978
|
constructor(dbPath) {
|
|
52303
|
-
mkdirSync4(
|
|
52979
|
+
mkdirSync4(dirname19(dbPath), { recursive: true });
|
|
52304
52980
|
this.db = openControlPlaneSqliteDatabase(dbPath, { create: true });
|
|
52305
52981
|
configureControlPlaneDatabase(this.db);
|
|
52306
52982
|
migrateControlPlaneDatabaseSchema(this.db);
|
|
@@ -54500,6 +55176,21 @@ class RecoverableSQLiteProjection {
|
|
|
54500
55176
|
this.journal = journal;
|
|
54501
55177
|
this.options = options;
|
|
54502
55178
|
}
|
|
55179
|
+
statusSnapshot() {
|
|
55180
|
+
if (this.options.disabled) {
|
|
55181
|
+
return {
|
|
55182
|
+
state: "disabled",
|
|
55183
|
+
detail: "SQLite projection is disabled by configuration."
|
|
55184
|
+
};
|
|
55185
|
+
}
|
|
55186
|
+
if (this.store) {
|
|
55187
|
+
return { state: "ready", detail: null };
|
|
55188
|
+
}
|
|
55189
|
+
return {
|
|
55190
|
+
state: "degraded",
|
|
55191
|
+
detail: this.lastUnavailableReason ?? (this.closed ? "SQLite projection is closed." : "SQLite projection is not ready.")
|
|
55192
|
+
};
|
|
55193
|
+
}
|
|
54503
55194
|
warm() {
|
|
54504
55195
|
this.enqueue(async () => {
|
|
54505
55196
|
await this.ensureStore();
|
|
@@ -54996,8 +55687,8 @@ class ThreadEventPlane {
|
|
|
54996
55687
|
}
|
|
54997
55688
|
|
|
54998
55689
|
// packages/runtime/src/build-info.ts
|
|
54999
|
-
import { readFileSync as
|
|
55000
|
-
import { dirname as
|
|
55690
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
55691
|
+
import { dirname as dirname20, join as join34 } from "path";
|
|
55001
55692
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
55002
55693
|
var cachedBuildIdentity = null;
|
|
55003
55694
|
function envString(...names) {
|
|
@@ -55011,8 +55702,8 @@ function envString(...names) {
|
|
|
55011
55702
|
}
|
|
55012
55703
|
function readRuntimePackageJson() {
|
|
55013
55704
|
try {
|
|
55014
|
-
const packagePath =
|
|
55015
|
-
const parsed = JSON.parse(
|
|
55705
|
+
const packagePath = join34(dirname20(fileURLToPath8(import.meta.url)), "..", "package.json");
|
|
55706
|
+
const parsed = JSON.parse(readFileSync17(packagePath, "utf8"));
|
|
55016
55707
|
return {
|
|
55017
55708
|
name: typeof parsed.name === "string" && parsed.name.trim() ? parsed.name.trim() : null,
|
|
55018
55709
|
version: typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : null
|
|
@@ -55625,6 +56316,7 @@ function createBrokerCoreService(deps) {
|
|
|
55625
56316
|
meshId: deps.meshId,
|
|
55626
56317
|
build: deps.build ?? loadOpenScoutRuntimeBuildIdentity(),
|
|
55627
56318
|
services: deps.readChildServices?.(),
|
|
56319
|
+
...deps.readProjectionStatus ? { projection: deps.readProjectionStatus() } : {},
|
|
55628
56320
|
counts: {
|
|
55629
56321
|
nodes: Object.keys(snapshot.nodes).length,
|
|
55630
56322
|
actors: Object.keys(snapshot.actors).length,
|
|
@@ -55687,9 +56379,9 @@ function createBrokerCoreService(deps) {
|
|
|
55687
56379
|
}
|
|
55688
56380
|
|
|
55689
56381
|
// packages/runtime/src/mesh-rendezvous.ts
|
|
55690
|
-
import { existsSync as
|
|
55691
|
-
import { homedir as
|
|
55692
|
-
import { join as
|
|
56382
|
+
import { existsSync as existsSync32, readFileSync as readFileSync18 } from "fs";
|
|
56383
|
+
import { homedir as homedir31 } from "os";
|
|
56384
|
+
import { join as join35 } from "path";
|
|
55693
56385
|
var DEFAULT_RENDEZVOUS_TTL_MS = 60000;
|
|
55694
56386
|
var DEFAULT_RENDEZVOUS_INTERVAL_MS = 30000;
|
|
55695
56387
|
function resolveMeshRendezvousPublishConfig(env = process.env, options = {}) {
|
|
@@ -55789,20 +56481,20 @@ function startMeshRendezvousPublisher(node, options) {
|
|
|
55789
56481
|
};
|
|
55790
56482
|
}
|
|
55791
56483
|
function readMobilePairingMeshEntrypoint(env = process.env, now = Date.now()) {
|
|
55792
|
-
const runtimeStatePath = env.OPENSCOUT_PAIRING_RUNTIME_STATE_PATH ??
|
|
55793
|
-
if (!
|
|
56484
|
+
const runtimeStatePath = env.OPENSCOUT_PAIRING_RUNTIME_STATE_PATH ?? join35(env.HOME ?? homedir31(), ".scout", "pairing", "runtime.json");
|
|
56485
|
+
if (!existsSync32(runtimeStatePath)) {
|
|
55794
56486
|
return;
|
|
55795
56487
|
}
|
|
55796
56488
|
try {
|
|
55797
|
-
return mobilePairingMeshEntrypointFromSnapshot(JSON.parse(
|
|
56489
|
+
return mobilePairingMeshEntrypointFromSnapshot(JSON.parse(readFileSync18(runtimeStatePath, "utf8")), now);
|
|
55798
56490
|
} catch {
|
|
55799
56491
|
return;
|
|
55800
56492
|
}
|
|
55801
56493
|
}
|
|
55802
56494
|
function mobilePairingMeshEntrypointFromSnapshot(input, now = Date.now()) {
|
|
55803
|
-
if (!
|
|
56495
|
+
if (!isRecord8(input))
|
|
55804
56496
|
return;
|
|
55805
|
-
const pairing =
|
|
56497
|
+
const pairing = isRecord8(input["pairing"]) ? input["pairing"] : undefined;
|
|
55806
56498
|
if (!pairing)
|
|
55807
56499
|
return;
|
|
55808
56500
|
const relay = readString5(pairing["relay"]);
|
|
@@ -55876,7 +56568,7 @@ function readFallbackRelays(pairing) {
|
|
|
55876
56568
|
}
|
|
55877
56569
|
try {
|
|
55878
56570
|
const parsed = JSON.parse(qrValue);
|
|
55879
|
-
return
|
|
56571
|
+
return isRecord8(parsed) ? readStringArray(parsed["fallbackRelays"]) : [];
|
|
55880
56572
|
} catch {
|
|
55881
56573
|
return [];
|
|
55882
56574
|
}
|
|
@@ -55890,7 +56582,7 @@ function readNumber5(value) {
|
|
|
55890
56582
|
function readStringArray(value) {
|
|
55891
56583
|
return Array.isArray(value) ? value.map(readString5).filter((entry) => Boolean(entry)) : [];
|
|
55892
56584
|
}
|
|
55893
|
-
function
|
|
56585
|
+
function isRecord8(value) {
|
|
55894
56586
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
55895
56587
|
}
|
|
55896
56588
|
function isPublicKeyHex(value) {
|
|
@@ -55899,10 +56591,10 @@ function isPublicKeyHex(value) {
|
|
|
55899
56591
|
|
|
55900
56592
|
// packages/runtime/src/mobile-push.ts
|
|
55901
56593
|
import { Database as Database2 } from "bun:sqlite";
|
|
55902
|
-
import { mkdirSync as mkdirSync5, readFileSync as
|
|
56594
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync19 } from "fs";
|
|
55903
56595
|
import { connect as connectHttp2 } from "http2";
|
|
55904
56596
|
import { createPrivateKey, sign as signWithKey } from "crypto";
|
|
55905
|
-
import { dirname as
|
|
56597
|
+
import { dirname as dirname21, join as join36 } from "path";
|
|
55906
56598
|
var MOBILE_PUSH_SCHEMA = `
|
|
55907
56599
|
CREATE TABLE IF NOT EXISTS mobile_push_registrations (
|
|
55908
56600
|
id TEXT PRIMARY KEY,
|
|
@@ -55930,7 +56622,7 @@ var dbHandle = null;
|
|
|
55930
56622
|
var dbPath = null;
|
|
55931
56623
|
var cachedApnsJwt = null;
|
|
55932
56624
|
function resolveControlPlaneDbPath() {
|
|
55933
|
-
return
|
|
56625
|
+
return join36(resolveOpenScoutSupportPaths().controlHome, "control-plane.sqlite");
|
|
55934
56626
|
}
|
|
55935
56627
|
function ensureMobilePushSchema(database) {
|
|
55936
56628
|
database.exec("PRAGMA busy_timeout = 5000;");
|
|
@@ -55944,7 +56636,7 @@ function writeDb() {
|
|
|
55944
56636
|
dbHandle = null;
|
|
55945
56637
|
}
|
|
55946
56638
|
if (!dbHandle) {
|
|
55947
|
-
mkdirSync5(
|
|
56639
|
+
mkdirSync5(dirname21(nextPath), { recursive: true });
|
|
55948
56640
|
dbHandle = new Database2(nextPath, { create: true });
|
|
55949
56641
|
dbPath = nextPath;
|
|
55950
56642
|
ensureMobilePushSchema(dbHandle);
|
|
@@ -56135,7 +56827,7 @@ function loadApnsCredentials() {
|
|
|
56135
56827
|
privateKeyPem = Buffer.from(inlineBase64, "base64").toString("utf8");
|
|
56136
56828
|
}
|
|
56137
56829
|
if (!privateKeyPem && path) {
|
|
56138
|
-
privateKeyPem =
|
|
56830
|
+
privateKeyPem = readFileSync19(path, "utf8");
|
|
56139
56831
|
}
|
|
56140
56832
|
if (!teamId || !keyId || !privateKeyPem) {
|
|
56141
56833
|
return null;
|
|
@@ -56314,8 +57006,8 @@ async function broadcastApnsAlertToActiveMobileDevices(alert) {
|
|
|
56314
57006
|
|
|
56315
57007
|
// packages/runtime/src/repo-watch/index.ts
|
|
56316
57008
|
import { lstat } from "fs/promises";
|
|
56317
|
-
import { homedir as
|
|
56318
|
-
import { basename as
|
|
57009
|
+
import { homedir as homedir32 } from "os";
|
|
57010
|
+
import { basename as basename20, dirname as dirname22, isAbsolute as isAbsolute3, relative as relative7, resolve as resolve14 } from "path";
|
|
56319
57011
|
var DEFAULT_CACHE_TTL_MS = 2500;
|
|
56320
57012
|
var DEFAULT_MAX_ROOTS = 8;
|
|
56321
57013
|
var DEFAULT_MAX_WORKTREES = 4;
|
|
@@ -56323,31 +57015,31 @@ var DEFAULT_MAX_FILES_PER_WORKTREE = 12;
|
|
|
56323
57015
|
var DEFAULT_SCAN_BUDGET_MS = 4000;
|
|
56324
57016
|
var cachedSnapshot = null;
|
|
56325
57017
|
var lastUsefulSnapshot = null;
|
|
56326
|
-
function
|
|
57018
|
+
function readPositiveIntEnv10(name, fallback) {
|
|
56327
57019
|
const raw = Number.parseInt(process.env[name] ?? "", 10);
|
|
56328
57020
|
return Number.isFinite(raw) && raw > 0 ? raw : fallback;
|
|
56329
57021
|
}
|
|
56330
|
-
function
|
|
57022
|
+
function stringValue12(value) {
|
|
56331
57023
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
56332
57024
|
}
|
|
56333
57025
|
function metadataString4(metadata, key) {
|
|
56334
57026
|
if (!metadata)
|
|
56335
57027
|
return null;
|
|
56336
|
-
return
|
|
57028
|
+
return stringValue12(metadata[key]);
|
|
56337
57029
|
}
|
|
56338
57030
|
function expandHome(input) {
|
|
56339
57031
|
if (input === "~")
|
|
56340
|
-
return
|
|
57032
|
+
return homedir32();
|
|
56341
57033
|
if (input.startsWith("~/"))
|
|
56342
|
-
return resolve14(
|
|
57034
|
+
return resolve14(homedir32(), input.slice(2));
|
|
56343
57035
|
return input;
|
|
56344
57036
|
}
|
|
56345
57037
|
function normalizePath2(input) {
|
|
56346
57038
|
return resolve14(expandHome(input.trim()));
|
|
56347
57039
|
}
|
|
56348
57040
|
function isBroadLocalRootPath(path) {
|
|
56349
|
-
const home = normalizePath2(
|
|
56350
|
-
return path === home || path === resolve14(home, "dev") || path === resolve14(home, "Developer") || path ===
|
|
57041
|
+
const home = normalizePath2(homedir32());
|
|
57042
|
+
return path === home || path === resolve14(home, "dev") || path === resolve14(home, "Developer") || path === dirname22(home) || path === "/";
|
|
56351
57043
|
}
|
|
56352
57044
|
function isTempLocalPath(path) {
|
|
56353
57045
|
const roots = [
|
|
@@ -56463,7 +57155,7 @@ async function existingDirectoryForPath(path) {
|
|
|
56463
57155
|
if (stats.isDirectory())
|
|
56464
57156
|
return path;
|
|
56465
57157
|
if (stats.isFile())
|
|
56466
|
-
return
|
|
57158
|
+
return dirname22(path);
|
|
56467
57159
|
return null;
|
|
56468
57160
|
} catch {
|
|
56469
57161
|
return null;
|
|
@@ -56896,7 +57588,7 @@ async function scanWorktree(worktree, hints, git2, now, options) {
|
|
|
56896
57588
|
return {
|
|
56897
57589
|
id: `worktree:${hashId2(worktree.path)}`,
|
|
56898
57590
|
path: worktree.path,
|
|
56899
|
-
name:
|
|
57591
|
+
name: basename20(worktree.path) || worktree.path,
|
|
56900
57592
|
isBare: worktree.bare,
|
|
56901
57593
|
branch,
|
|
56902
57594
|
status: parsed.status,
|
|
@@ -56971,7 +57663,7 @@ async function scanProject(root, git2, now, maxWorktrees, options) {
|
|
|
56971
57663
|
return {
|
|
56972
57664
|
project: {
|
|
56973
57665
|
id: `repo:${hashId2(root.commonGitDir)}`,
|
|
56974
|
-
name:
|
|
57666
|
+
name: basename20(rootPath) || basename20(root.commonGitDir) || rootPath,
|
|
56975
57667
|
root: rootPath,
|
|
56976
57668
|
commonGitDir: root.commonGitDir,
|
|
56977
57669
|
attention,
|
|
@@ -57018,7 +57710,7 @@ function worktreeFromNative(worktree, hints) {
|
|
|
57018
57710
|
return {
|
|
57019
57711
|
id: `worktree:${hashId2(worktree.path)}`,
|
|
57020
57712
|
path: worktree.path,
|
|
57021
|
-
name: worktree.name ||
|
|
57713
|
+
name: worktree.name || basename20(worktree.path) || worktree.path,
|
|
57022
57714
|
isBare: worktree.isBare,
|
|
57023
57715
|
branch,
|
|
57024
57716
|
status: worktree.status,
|
|
@@ -57051,7 +57743,7 @@ function projectsFromNativeScan(response, hints) {
|
|
|
57051
57743
|
const rootPath = worktrees[0]?.path ?? rawProject.root;
|
|
57052
57744
|
projects.push({
|
|
57053
57745
|
id: `repo:${hashId2(rawProject.commonGitDir)}`,
|
|
57054
|
-
name:
|
|
57746
|
+
name: basename20(rootPath) || basename20(rawProject.commonGitDir) || rootPath,
|
|
57055
57747
|
root: rootPath,
|
|
57056
57748
|
commonGitDir: rawProject.commonGitDir,
|
|
57057
57749
|
attention,
|
|
@@ -57176,10 +57868,10 @@ async function scanWithTypeScriptRepoWatch(options) {
|
|
|
57176
57868
|
async function getRepoWatchSnapshot(options = {}) {
|
|
57177
57869
|
const now = options.now?.() ?? Date.now();
|
|
57178
57870
|
const cacheTtlMs = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
57179
|
-
const maxRoots = options.maxRoots ??
|
|
57180
|
-
const maxWorktrees = options.maxWorktrees ??
|
|
57181
|
-
const maxFiles = options.maxFilesPerWorktree ??
|
|
57182
|
-
const scanBudgetMs = options.scanBudgetMs ??
|
|
57871
|
+
const maxRoots = options.maxRoots ?? readPositiveIntEnv10("OPENSCOUT_REPO_WATCH_MAX_ROOTS", DEFAULT_MAX_ROOTS);
|
|
57872
|
+
const maxWorktrees = options.maxWorktrees ?? readPositiveIntEnv10("OPENSCOUT_REPO_WATCH_MAX_WORKTREES", DEFAULT_MAX_WORKTREES);
|
|
57873
|
+
const maxFiles = options.maxFilesPerWorktree ?? readPositiveIntEnv10("OPENSCOUT_REPO_WATCH_MAX_FILES_PER_WORKTREE", DEFAULT_MAX_FILES_PER_WORKTREE);
|
|
57874
|
+
const scanBudgetMs = options.scanBudgetMs ?? readPositiveIntEnv10("OPENSCOUT_REPO_WATCH_SCAN_BUDGET_MS", DEFAULT_SCAN_BUDGET_MS);
|
|
57183
57875
|
const deadlineMs = scanBudgetMs > 0 ? Date.now() + scanBudgetMs : null;
|
|
57184
57876
|
const git2 = options.git ?? defaultGit;
|
|
57185
57877
|
const hints = normalizeHints([
|
|
@@ -57389,8 +58081,8 @@ function repoWatchHintsFromTailDiscovery(discovery) {
|
|
|
57389
58081
|
|
|
57390
58082
|
// packages/runtime/src/broker-web-control-service.ts
|
|
57391
58083
|
import { spawn as spawn8 } from "child_process";
|
|
57392
|
-
import { existsSync as
|
|
57393
|
-
import { dirname as
|
|
58084
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync6, openSync as openSync7 } from "fs";
|
|
58085
|
+
import { dirname as dirname23, join as join37, resolve as resolve15 } from "path";
|
|
57394
58086
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
57395
58087
|
var DEFAULT_WEB_PROCESS_NAME = "scout-web";
|
|
57396
58088
|
var DEFAULT_START_POLL_TIMEOUT_MS = 15000;
|
|
@@ -57492,7 +58184,7 @@ class BrokerWebControlService {
|
|
|
57492
58184
|
this.trustedHosts = new Set([...options.trustedHosts ?? []].map((host) => host.trim().replace(/\.$/, "").toLowerCase()).filter(Boolean));
|
|
57493
58185
|
this.tailnetWebHosts = (options.tailnetWebHosts ?? []).map((host) => host.trim()).filter(Boolean);
|
|
57494
58186
|
this.webProcessName = options.webProcessName ?? DEFAULT_WEB_PROCESS_NAME;
|
|
57495
|
-
this.moduleDirectory = options.moduleDirectory ??
|
|
58187
|
+
this.moduleDirectory = options.moduleDirectory ?? dirname23(fileURLToPath9(import.meta.url));
|
|
57496
58188
|
this.cwd = options.cwd ?? (() => process.cwd());
|
|
57497
58189
|
this.sleep = options.sleep ?? ((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms)));
|
|
57498
58190
|
this.startPollTimeoutMs = options.startPollTimeoutMs ?? DEFAULT_START_POLL_TIMEOUT_MS;
|
|
@@ -57627,7 +58319,7 @@ class BrokerWebControlService {
|
|
|
57627
58319
|
return this.options.resolveEntry();
|
|
57628
58320
|
}
|
|
57629
58321
|
const explicit = this.env.OPENSCOUT_WEB_SERVER_ENTRY?.trim();
|
|
57630
|
-
if (explicit &&
|
|
58322
|
+
if (explicit && existsSync33(explicit)) {
|
|
57631
58323
|
return explicit;
|
|
57632
58324
|
}
|
|
57633
58325
|
const repoRoot = this.resolveRepoRoot();
|
|
@@ -57641,7 +58333,7 @@ class BrokerWebControlService {
|
|
|
57641
58333
|
resolve15(this.moduleDirectory, "..", "..", "scout-control-plane-web.mjs"),
|
|
57642
58334
|
resolve15(this.moduleDirectory, "..", "..", "scout-web-server.mjs")
|
|
57643
58335
|
];
|
|
57644
|
-
return candidates.find((candidate) =>
|
|
58336
|
+
return candidates.find((candidate) => existsSync33(candidate)) ?? null;
|
|
57645
58337
|
}
|
|
57646
58338
|
resolveRepoRoot() {
|
|
57647
58339
|
return resolveOpenScoutRepoRoot({
|
|
@@ -57660,9 +58352,9 @@ class BrokerWebControlService {
|
|
|
57660
58352
|
return this.options.resolveLogPath();
|
|
57661
58353
|
}
|
|
57662
58354
|
const config2 = resolveBrokerServiceConfig();
|
|
57663
|
-
const logDirectory =
|
|
58355
|
+
const logDirectory = join37(config2.supportDirectory, "logs", "web");
|
|
57664
58356
|
mkdirSync6(logDirectory, { recursive: true });
|
|
57665
|
-
return
|
|
58357
|
+
return join37(logDirectory, "supervised-web.log");
|
|
57666
58358
|
}
|
|
57667
58359
|
spawnWebServer(context = {}) {
|
|
57668
58360
|
const entry = this.resolveEntry();
|
|
@@ -58276,7 +58968,7 @@ class BrokerA2AService {
|
|
|
58276
58968
|
|
|
58277
58969
|
// packages/runtime/src/broker-capability-matrix-service.ts
|
|
58278
58970
|
import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
|
|
58279
|
-
import { dirname as
|
|
58971
|
+
import { dirname as dirname24, join as join40 } from "path";
|
|
58280
58972
|
|
|
58281
58973
|
// packages/runtime/src/capability-matrix.ts
|
|
58282
58974
|
function buildRuntimeCapabilityMatrixSnapshot(options) {
|
|
@@ -58736,10 +59428,10 @@ function errorMessage5(error48) {
|
|
|
58736
59428
|
|
|
58737
59429
|
// packages/runtime/src/mcp-server-catalog.ts
|
|
58738
59430
|
import { readFile as readFile9 } from "fs/promises";
|
|
58739
|
-
import { join as
|
|
59431
|
+
import { join as join38 } from "path";
|
|
58740
59432
|
var RUNTIME_MCP_SERVER_CATALOG_FILE = "mcp-servers.json";
|
|
58741
59433
|
function resolveRuntimeMcpServerCatalogPath(path) {
|
|
58742
|
-
return path ??
|
|
59434
|
+
return path ?? join38(resolveOpenScoutSupportPaths().catalogDirectory, RUNTIME_MCP_SERVER_CATALOG_FILE);
|
|
58743
59435
|
}
|
|
58744
59436
|
async function loadRuntimeMcpServerCatalog(options = {}) {
|
|
58745
59437
|
const path = resolveRuntimeMcpServerCatalogPath(options.path);
|
|
@@ -58822,10 +59514,10 @@ function isNotFoundError(error48) {
|
|
|
58822
59514
|
|
|
58823
59515
|
// packages/runtime/src/model-catalog.ts
|
|
58824
59516
|
import { readFile as readFile10 } from "fs/promises";
|
|
58825
|
-
import { join as
|
|
59517
|
+
import { join as join39 } from "path";
|
|
58826
59518
|
var RUNTIME_MODEL_CATALOG_FILE = "model-catalog.json";
|
|
58827
59519
|
function resolveRuntimeModelCatalogPath(path) {
|
|
58828
|
-
return path ??
|
|
59520
|
+
return path ?? join39(resolveOpenScoutSupportPaths().catalogDirectory, RUNTIME_MODEL_CATALOG_FILE);
|
|
58829
59521
|
}
|
|
58830
59522
|
async function loadRuntimeModelCatalogInput(options = {}) {
|
|
58831
59523
|
const path = resolveRuntimeModelCatalogPath(options.path);
|
|
@@ -58912,7 +59604,7 @@ function resolveCapabilityMatrixCacheTtlMs(env = process.env) {
|
|
|
58912
59604
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_CAPABILITY_MATRIX_CACHE_TTL_MS;
|
|
58913
59605
|
}
|
|
58914
59606
|
function defaultCapabilityMatrixCachePath() {
|
|
58915
|
-
return
|
|
59607
|
+
return join40(resolveOpenScoutSupportPaths().runtimeDirectory, "capability-matrix.json");
|
|
58916
59608
|
}
|
|
58917
59609
|
function isCapabilityMatrixSnapshot(value) {
|
|
58918
59610
|
return Boolean(value) && typeof value === "object" && typeof value.generatedAt === "number" && Array.isArray(value.sources) && Array.isArray(value.capabilities) && Array.isArray(value.warnings);
|
|
@@ -59003,7 +59695,7 @@ class BrokerCapabilityMatrixService {
|
|
|
59003
59695
|
async writePersisted(snapshot) {
|
|
59004
59696
|
try {
|
|
59005
59697
|
const path = this.cachePath();
|
|
59006
|
-
await (this.options.ensureDirectory ?? mkdir9)(
|
|
59698
|
+
await (this.options.ensureDirectory ?? mkdir9)(dirname24(path), { recursive: true });
|
|
59007
59699
|
await (this.options.writeTextFile ?? writeFile9)(path, `${JSON.stringify(snapshot, null, 2)}
|
|
59008
59700
|
`, "utf8");
|
|
59009
59701
|
} catch {}
|
|
@@ -59011,7 +59703,7 @@ class BrokerCapabilityMatrixService {
|
|
|
59011
59703
|
}
|
|
59012
59704
|
|
|
59013
59705
|
// packages/runtime/src/broker-managed-session-helpers.ts
|
|
59014
|
-
import { basename as
|
|
59706
|
+
import { basename as basename21, resolve as resolve16 } from "path";
|
|
59015
59707
|
function localAgentMetadataSource(metadata) {
|
|
59016
59708
|
const source = metadata?.source;
|
|
59017
59709
|
return typeof source === "string" && source.trim().length > 0 ? source : null;
|
|
@@ -59127,11 +59819,11 @@ function updateManagedSessionAgent(agent, input) {
|
|
|
59127
59819
|
};
|
|
59128
59820
|
}
|
|
59129
59821
|
function managedLocalSessionDefaultDisplayName(input) {
|
|
59130
|
-
const projectName =
|
|
59822
|
+
const projectName = basename21(input.projectRoot ?? input.cwd) || input.cwd;
|
|
59131
59823
|
return input.transport === "codex_app_server" ? `Codex (${projectName})` : `Claude (${projectName})`;
|
|
59132
59824
|
}
|
|
59133
59825
|
function suggestedManagedLocalSessionSelector(input) {
|
|
59134
|
-
const projectName = normalizeAgentSelectorSegment(
|
|
59826
|
+
const projectName = normalizeAgentSelectorSegment(basename21(input.projectRoot ?? input.cwd) || "session") || "session";
|
|
59135
59827
|
const prefix = input.transport === "codex_app_server" ? "codex" : "claude";
|
|
59136
59828
|
return `@${prefix}-${projectName}`;
|
|
59137
59829
|
}
|
|
@@ -59169,7 +59861,7 @@ function buildManagedLocalSessionAgent(input) {
|
|
|
59169
59861
|
function buildManagedLocalSessionPairingEndpointBinding(input) {
|
|
59170
59862
|
const projectRoot = resolve16(input.projectRoot ?? input.cwd);
|
|
59171
59863
|
const cwd = resolve16(input.cwd);
|
|
59172
|
-
const projectName =
|
|
59864
|
+
const projectName = basename21(projectRoot) || projectRoot;
|
|
59173
59865
|
const definitionId = input.definitionId?.trim() || selectorHandle(input.selector ?? input.agentId);
|
|
59174
59866
|
const base = buildManagedPairingEndpointBinding({
|
|
59175
59867
|
agentId: input.agentId,
|
|
@@ -60221,8 +60913,23 @@ function localInvocationTargetIdentity(targetId, agent, actor) {
|
|
|
60221
60913
|
}
|
|
60222
60914
|
|
|
60223
60915
|
// packages/runtime/src/broker-cardless-session.ts
|
|
60224
|
-
import { basename as
|
|
60916
|
+
import { basename as basename22, resolve as resolve18 } from "path";
|
|
60225
60917
|
var CARDLESS_SESSION_SOURCE = "scout-cardless-session";
|
|
60918
|
+
function resolveCardlessSessionSpawnTarget(requestedHarness, options = {}) {
|
|
60919
|
+
const defaults = resolveHarnessSessionDefaults(requestedHarness ?? "claude", {
|
|
60920
|
+
transportOverride: options.claudeTransport
|
|
60921
|
+
});
|
|
60922
|
+
if (defaults && isCardlessSessionSpawnTransport(defaults.transport)) {
|
|
60923
|
+
return {
|
|
60924
|
+
harness: defaults.harness,
|
|
60925
|
+
transport: defaults.transport
|
|
60926
|
+
};
|
|
60927
|
+
}
|
|
60928
|
+
throw new Error(`cannot auto-spawn a session for harness "${requestedHarness}"; ` + `the harness catalog has no supported session defaults. ` + `Bring a worker online first (scout up) to use other harnesses.`);
|
|
60929
|
+
}
|
|
60930
|
+
function isCardlessSessionSpawnTransport(value) {
|
|
60931
|
+
return value === "claude_stream_json" || value === "codex_app_server" || value === "grok_acp" || value === "kimi_acp" || value === "tmux";
|
|
60932
|
+
}
|
|
60226
60933
|
function resolveCardlessSessionPath(path) {
|
|
60227
60934
|
return resolve18(expandHomePath(path));
|
|
60228
60935
|
}
|
|
@@ -60260,7 +60967,7 @@ function cardlessSessionDisplayName(input) {
|
|
|
60260
60967
|
}
|
|
60261
60968
|
function buildCardlessSessionActor(input) {
|
|
60262
60969
|
const projectRoot = resolveCardlessSessionPath(input.projectRoot ?? input.cwd);
|
|
60263
|
-
const projectName =
|
|
60970
|
+
const projectName = basename22(projectRoot) || projectRoot;
|
|
60264
60971
|
const shortId = input.sessionId.length > 8 ? input.sessionId.slice(0, 8) : input.sessionId;
|
|
60265
60972
|
const handle = cleanCardlessSessionHandle(input);
|
|
60266
60973
|
return {
|
|
@@ -60283,7 +60990,7 @@ function buildCardlessSessionActor(input) {
|
|
|
60283
60990
|
function buildCardlessSessionEndpoint(input) {
|
|
60284
60991
|
const projectRoot = resolveCardlessSessionPath(input.projectRoot ?? input.cwd);
|
|
60285
60992
|
const cwd = resolveCardlessSessionPath(input.cwd);
|
|
60286
|
-
const projectName =
|
|
60993
|
+
const projectName = basename22(projectRoot) || projectRoot;
|
|
60287
60994
|
const externalSessionId = input.externalSessionId?.trim();
|
|
60288
60995
|
const endpointSessionId = input.pairingSessionId?.trim() || input.sessionId;
|
|
60289
60996
|
const launchArgs = input.launchArgs?.map((entry) => entry.trim()).filter(Boolean);
|
|
@@ -60334,14 +61041,14 @@ async function registerCardlessSession(registry3, input) {
|
|
|
60334
61041
|
}
|
|
60335
61042
|
|
|
60336
61043
|
// packages/runtime/src/provisional-agent-names-config.ts
|
|
60337
|
-
import { existsSync as
|
|
60338
|
-
import { homedir as
|
|
60339
|
-
import { isAbsolute as isAbsolute4, join as
|
|
61044
|
+
import { existsSync as existsSync34, readFileSync as readFileSync20, writeFileSync as writeFileSync4, mkdirSync as mkdirSync7 } from "fs";
|
|
61045
|
+
import { homedir as homedir33 } from "os";
|
|
61046
|
+
import { isAbsolute as isAbsolute4, join as join41, resolve as resolve19 } from "path";
|
|
60340
61047
|
function openScoutHome() {
|
|
60341
|
-
return process.env.OPENSCOUT_HOME ??
|
|
61048
|
+
return process.env.OPENSCOUT_HOME ?? join41(homedir33(), ".openscout");
|
|
60342
61049
|
}
|
|
60343
61050
|
function defaultProvisionalAgentNamesPath() {
|
|
60344
|
-
return
|
|
61051
|
+
return join41(openScoutHome(), "provisional-agent-names.json");
|
|
60345
61052
|
}
|
|
60346
61053
|
function resolveProvisionalAgentNamesMode(config2) {
|
|
60347
61054
|
return config2.provisionalAgentNamesMode === "extend" ? "extend" : "replace";
|
|
@@ -60370,7 +61077,7 @@ function resolvePoolFilePath(filePath) {
|
|
|
60370
61077
|
return isAbsolute4(trimmed) ? trimmed : resolve19(openScoutHome(), trimmed);
|
|
60371
61078
|
}
|
|
60372
61079
|
function readProvisionalAgentNamesJsonFile(filePath) {
|
|
60373
|
-
return parseProvisionalAgentNamesJson(
|
|
61080
|
+
return parseProvisionalAgentNamesJson(readFileSync20(filePath, "utf8"));
|
|
60374
61081
|
}
|
|
60375
61082
|
function loadInlineProvisionalAgentNames(config2) {
|
|
60376
61083
|
const customNames = normalizeProvisionalAgentNamesSetting(config2.provisionalAgentNames);
|
|
@@ -60386,7 +61093,7 @@ function loadInlineProvisionalAgentNames(config2) {
|
|
|
60386
61093
|
}
|
|
60387
61094
|
function loadFileProvisionalAgentNames(config2 = loadUserConfig()) {
|
|
60388
61095
|
const envFile = process.env.OPENSCOUT_PROVISIONAL_AGENT_NAMES_FILE?.trim();
|
|
60389
|
-
if (envFile &&
|
|
61096
|
+
if (envFile && existsSync34(envFile)) {
|
|
60390
61097
|
const names = readProvisionalAgentNamesJsonFile(envFile);
|
|
60391
61098
|
if (names.length > 0) {
|
|
60392
61099
|
return { names, source: "env-file", sourcePath: envFile };
|
|
@@ -60394,7 +61101,7 @@ function loadFileProvisionalAgentNames(config2 = loadUserConfig()) {
|
|
|
60394
61101
|
}
|
|
60395
61102
|
if (config2.provisionalAgentNamesFile?.trim()) {
|
|
60396
61103
|
const filePath = resolvePoolFilePath(config2.provisionalAgentNamesFile);
|
|
60397
|
-
if (
|
|
61104
|
+
if (existsSync34(filePath)) {
|
|
60398
61105
|
const names = readProvisionalAgentNamesJsonFile(filePath);
|
|
60399
61106
|
if (names.length > 0) {
|
|
60400
61107
|
return { names, source: "user-config-file", sourcePath: filePath };
|
|
@@ -60402,7 +61109,7 @@ function loadFileProvisionalAgentNames(config2 = loadUserConfig()) {
|
|
|
60402
61109
|
}
|
|
60403
61110
|
}
|
|
60404
61111
|
const homeJson = defaultProvisionalAgentNamesPath();
|
|
60405
|
-
if (
|
|
61112
|
+
if (existsSync34(homeJson)) {
|
|
60406
61113
|
const names = readProvisionalAgentNamesJsonFile(homeJson);
|
|
60407
61114
|
if (names.length > 0) {
|
|
60408
61115
|
return { names, source: "home-json", sourcePath: homeJson };
|
|
@@ -60923,6 +61630,7 @@ var AGENT_HARNESSES = [
|
|
|
60923
61630
|
"claude",
|
|
60924
61631
|
"grok",
|
|
60925
61632
|
"grok-acp",
|
|
61633
|
+
"kimi",
|
|
60926
61634
|
"flue",
|
|
60927
61635
|
"cursor",
|
|
60928
61636
|
"native",
|
|
@@ -62091,12 +62799,12 @@ function createBrokerHttpRouter(deps) {
|
|
|
62091
62799
|
|
|
62092
62800
|
// packages/runtime/src/broker-server-lifecycle.ts
|
|
62093
62801
|
import { lstat as lstat2, mkdir as mkdir10, unlink } from "fs/promises";
|
|
62094
|
-
import { dirname as
|
|
62802
|
+
import { dirname as dirname25 } from "path";
|
|
62095
62803
|
function isAddressInUse(error48) {
|
|
62096
62804
|
return Boolean(error48 && typeof error48 === "object" && "code" in error48 && error48.code === "EADDRINUSE");
|
|
62097
62805
|
}
|
|
62098
62806
|
async function prepareBrokerSocketPath(socketPath) {
|
|
62099
|
-
await mkdir10(
|
|
62807
|
+
await mkdir10(dirname25(socketPath), { recursive: true, mode: 448 });
|
|
62100
62808
|
try {
|
|
62101
62809
|
const existing = await lstat2(socketPath);
|
|
62102
62810
|
if (!existing.isSocket()) {
|
|
@@ -63929,14 +64637,14 @@ function createRuntimeId2(prefix) {
|
|
|
63929
64637
|
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
63930
64638
|
}
|
|
63931
64639
|
function resolveControlPlaneHome() {
|
|
63932
|
-
return process.env.OPENSCOUT_CONTROL_HOME ??
|
|
64640
|
+
return process.env.OPENSCOUT_CONTROL_HOME ?? join42(process.env.HOME ?? process.cwd(), ".openscout", "control-plane");
|
|
63933
64641
|
}
|
|
63934
64642
|
function sleep2(ms) {
|
|
63935
64643
|
return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
|
|
63936
64644
|
}
|
|
63937
64645
|
var controlHome = resolveControlPlaneHome();
|
|
63938
|
-
var dbPath2 =
|
|
63939
|
-
var journalPath =
|
|
64646
|
+
var dbPath2 = join42(controlHome, "control-plane.sqlite");
|
|
64647
|
+
var journalPath = join42(controlHome, "broker-journal.jsonl");
|
|
63940
64648
|
var port = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
|
|
63941
64649
|
var advertiseScope = resolveAdvertiseScope();
|
|
63942
64650
|
var host = resolveBrokerHost(advertiseScope);
|
|
@@ -64256,7 +64964,7 @@ function currentHostInfo() {
|
|
|
64256
64964
|
}
|
|
64257
64965
|
async function writeHostInfo() {
|
|
64258
64966
|
const hostInfoPath = resolveOpenScoutSupportPaths().hostInfoPath;
|
|
64259
|
-
await mkdir11(
|
|
64967
|
+
await mkdir11(dirname26(hostInfoPath), { recursive: true });
|
|
64260
64968
|
const temporaryPath = `${hostInfoPath}.tmp`;
|
|
64261
64969
|
await writeFile10(temporaryPath, `${JSON.stringify(currentHostInfo(), null, 2)}
|
|
64262
64970
|
`, "utf8");
|
|
@@ -64281,7 +64989,7 @@ async function readRelayAgentRegistrySignature() {
|
|
|
64281
64989
|
const registryPath = resolveOpenScoutSupportPaths().relayAgentsRegistryPath;
|
|
64282
64990
|
const info = await stat7(registryPath);
|
|
64283
64991
|
const contents = await readFile12(registryPath);
|
|
64284
|
-
const hash2 =
|
|
64992
|
+
const hash2 = createHash5("sha256").update(contents).digest("base64url");
|
|
64285
64993
|
return `${info.mtimeMs}:${info.size}:${hash2}`;
|
|
64286
64994
|
} catch (error48) {
|
|
64287
64995
|
if (error48 && typeof error48 === "object" && "code" in error48 && error48.code === "ENOENT") {
|
|
@@ -64512,10 +65220,12 @@ async function createCardlessProjectSessionForDelivery(input) {
|
|
|
64512
65220
|
input.createdAt;
|
|
64513
65221
|
const projectRoot = resolve20(expandHomePath(input.projectPath));
|
|
64514
65222
|
const requestedHarness = input.execution?.harness;
|
|
64515
|
-
const { harness, transport } =
|
|
65223
|
+
const { harness, transport } = resolveCardlessSessionSpawnTarget(requestedHarness, {
|
|
65224
|
+
claudeTransport: process.env.OPENSCOUT_CLAUDE_CARDLESS_TRANSPORT
|
|
65225
|
+
});
|
|
64516
65226
|
const launchArgs = launchArgsForCardlessSession(harness, input.execution);
|
|
64517
65227
|
const sessionId = createRuntimeId2("session");
|
|
64518
|
-
const projectName =
|
|
65228
|
+
const projectName = basename23(projectRoot) || projectRoot;
|
|
64519
65229
|
const snapshot = runtime.snapshot();
|
|
64520
65230
|
const projectSessionIndex = Object.values(snapshot.endpoints).filter((endpoint2) => {
|
|
64521
65231
|
const endpointProjectRoot = endpoint2.projectRoot ?? (typeof endpoint2.metadata?.projectRoot === "string" ? endpoint2.metadata.projectRoot : undefined) ?? endpoint2.cwd;
|
|
@@ -64564,19 +65274,6 @@ async function createCardlessProjectSessionForDelivery(input) {
|
|
|
64564
65274
|
}
|
|
64565
65275
|
};
|
|
64566
65276
|
}
|
|
64567
|
-
function resolveCardlessSpawnTarget(requestedHarness) {
|
|
64568
|
-
switch (requestedHarness ?? "claude") {
|
|
64569
|
-
case "codex":
|
|
64570
|
-
return { harness: "codex", transport: "codex_app_server" };
|
|
64571
|
-
case "grok":
|
|
64572
|
-
case "grok-acp":
|
|
64573
|
-
return { harness: "grok-acp", transport: "grok_acp" };
|
|
64574
|
-
case "claude":
|
|
64575
|
-
return { harness: "claude", transport: "claude_stream_json" };
|
|
64576
|
-
default:
|
|
64577
|
-
throw new Error(`cannot auto-spawn a session for harness "${requestedHarness}"; ` + `supported: claude, codex, grok (runs over ACP). ` + `Bring a worker online first (scout up) to use other harnesses.`);
|
|
64578
|
-
}
|
|
64579
|
-
}
|
|
64580
65277
|
function launchArgsForCardlessSession(harness, execution) {
|
|
64581
65278
|
const model = execution?.model?.trim();
|
|
64582
65279
|
const reasoningEffort = execution?.reasoningEffort?.trim();
|
|
@@ -64786,6 +65483,7 @@ var brokerService = createBrokerCoreService({
|
|
|
64786
65483
|
threadEvents,
|
|
64787
65484
|
isReconciledStaleFlightActivityItem,
|
|
64788
65485
|
readChildServices: () => webControl.readChildServiceSnapshots(),
|
|
65486
|
+
readProjectionStatus: () => projection.statusSnapshot(),
|
|
64789
65487
|
readHome: () => homeService.read(),
|
|
64790
65488
|
readCapabilities: readBrokerCapabilityMatrixSnapshot,
|
|
64791
65489
|
executeCommand: handleCommand,
|