@openscout/scout 0.2.19 → 0.2.21
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/README.md +1 -1
- package/dist/control-plane-client/assets/index-D70CFXZt.js +9 -0
- package/dist/control-plane-client/assets/index-DAAaRFvV.css +1 -0
- package/dist/control-plane-client/index.html +2 -2
- package/dist/main.mjs +128 -45
- package/dist/scout-control-plane-web.mjs +72 -46
- package/dist/scout-web-server.mjs +180 -96
- package/package.json +2 -2
- package/dist/control-plane-client/assets/index-Cm-Qrks0.js +0 -9
- package/dist/control-plane-client/assets/index-DcR6uR4b.css +0 -1
|
@@ -1998,6 +1998,7 @@ var init_user_project_hints = __esm(() => {
|
|
|
1998
1998
|
|
|
1999
1999
|
// packages/runtime/src/setup.ts
|
|
2000
2000
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
2001
|
+
import { existsSync as existsSync3, readFileSync } from "fs";
|
|
2001
2002
|
import { access, mkdir as mkdir2, readdir as readdir2, readFile as readFile3, realpath, rm, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
2002
2003
|
import { homedir as homedir3, hostname, userInfo } from "os";
|
|
2003
2004
|
import { basename, dirname as dirname3, isAbsolute, join as join4, relative, resolve as resolve2 } from "path";
|
|
@@ -2175,7 +2176,25 @@ function normalizeTelegramConversationId(value) {
|
|
|
2175
2176
|
return normalized;
|
|
2176
2177
|
}
|
|
2177
2178
|
function resolveNodeQualifier() {
|
|
2178
|
-
|
|
2179
|
+
const fromEnv = process.env.OPENSCOUT_NODE_QUALIFIER?.trim();
|
|
2180
|
+
if (fromEnv) {
|
|
2181
|
+
return normalizeAgentSelectorSegment(fromEnv) || "local";
|
|
2182
|
+
}
|
|
2183
|
+
const alias = readNodeAliasSync();
|
|
2184
|
+
if (alias) {
|
|
2185
|
+
return normalizeAgentSelectorSegment(alias) || "local";
|
|
2186
|
+
}
|
|
2187
|
+
return normalizeAgentSelectorSegment(hostname() || "local") || "local";
|
|
2188
|
+
}
|
|
2189
|
+
function readNodeAliasSync() {
|
|
2190
|
+
try {
|
|
2191
|
+
const settingsPath = resolveOpenScoutSupportPaths().settingsPath;
|
|
2192
|
+
const raw2 = readFileSync(settingsPath, "utf8");
|
|
2193
|
+
const settings = JSON.parse(raw2);
|
|
2194
|
+
return settings.node?.alias?.trim() || null;
|
|
2195
|
+
} catch {
|
|
2196
|
+
return null;
|
|
2197
|
+
}
|
|
2179
2198
|
}
|
|
2180
2199
|
function detectGitBranchUncached(projectRoot) {
|
|
2181
2200
|
try {
|
|
@@ -2376,6 +2395,9 @@ function defaultSettings() {
|
|
|
2376
2395
|
completedAt: null,
|
|
2377
2396
|
skippedAt: null
|
|
2378
2397
|
},
|
|
2398
|
+
node: {
|
|
2399
|
+
alias: ""
|
|
2400
|
+
},
|
|
2379
2401
|
discovery: {
|
|
2380
2402
|
contextRoot: null,
|
|
2381
2403
|
workspaceRoots: [],
|
|
@@ -2775,6 +2797,7 @@ async function normalizeSettingsRecord(value, options = {}) {
|
|
|
2775
2797
|
const candidate = typeof value === "object" && value ? value : {};
|
|
2776
2798
|
const profile = typeof candidate.profile === "object" && candidate.profile ? candidate.profile : {};
|
|
2777
2799
|
const onboarding = typeof candidate.onboarding === "object" && candidate.onboarding ? candidate.onboarding : {};
|
|
2800
|
+
const node = typeof candidate.node === "object" && candidate.node ? candidate.node : {};
|
|
2778
2801
|
const discovery = typeof candidate.discovery === "object" && candidate.discovery ? candidate.discovery : {};
|
|
2779
2802
|
const agents = typeof candidate.agents === "object" && candidate.agents ? candidate.agents : {};
|
|
2780
2803
|
const bridges = typeof candidate.bridges === "object" && candidate.bridges ? candidate.bridges : {};
|
|
@@ -2814,6 +2837,9 @@ async function normalizeSettingsRecord(value, options = {}) {
|
|
|
2814
2837
|
completedAt: normalizeOptionalTimestamp(onboarding.completedAt),
|
|
2815
2838
|
skippedAt: normalizeOptionalTimestamp(onboarding.skippedAt)
|
|
2816
2839
|
},
|
|
2840
|
+
node: {
|
|
2841
|
+
alias: normalizeOptionalString(node.alias)
|
|
2842
|
+
},
|
|
2817
2843
|
discovery: {
|
|
2818
2844
|
contextRoot,
|
|
2819
2845
|
workspaceRoots,
|
|
@@ -2891,6 +2917,10 @@ async function writeOpenScoutSettings(settings, options = {}) {
|
|
|
2891
2917
|
...current.onboarding,
|
|
2892
2918
|
...settings.onboarding ?? {}
|
|
2893
2919
|
},
|
|
2920
|
+
node: {
|
|
2921
|
+
...current.node,
|
|
2922
|
+
...settings.node ?? {}
|
|
2923
|
+
},
|
|
2894
2924
|
discovery: {
|
|
2895
2925
|
...current.discovery,
|
|
2896
2926
|
...settings.discovery ?? {},
|
|
@@ -3822,6 +3852,9 @@ function resolveClaudeStreamJsonOutput(result, fallbackParts) {
|
|
|
3822
3852
|
function sessionKey(options) {
|
|
3823
3853
|
return `${options.agentName}:${options.sessionId}`;
|
|
3824
3854
|
}
|
|
3855
|
+
function errorMessage(error) {
|
|
3856
|
+
return error instanceof Error ? error.message : String(error);
|
|
3857
|
+
}
|
|
3825
3858
|
async function readOptionalFile(filePath) {
|
|
3826
3859
|
try {
|
|
3827
3860
|
const raw2 = await readFile4(filePath, "utf8");
|
|
@@ -3974,17 +4007,35 @@ class ClaudeStreamJsonSession {
|
|
|
3974
4007
|
if (this.claudeSessionId) {
|
|
3975
4008
|
args.push("--resume", this.claudeSessionId);
|
|
3976
4009
|
}
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
4010
|
+
let child;
|
|
4011
|
+
try {
|
|
4012
|
+
child = spawn2("claude", args, {
|
|
4013
|
+
cwd: this.options.cwd,
|
|
4014
|
+
env: buildManagedAgentEnvironment({
|
|
4015
|
+
agentName: this.options.agentName,
|
|
4016
|
+
currentDirectory: this.options.cwd,
|
|
4017
|
+
baseEnv: process.env
|
|
4018
|
+
})
|
|
4019
|
+
});
|
|
4020
|
+
} catch (error) {
|
|
4021
|
+
throw new Error(`Failed to spawn claude: ${errorMessage(error)}`);
|
|
4022
|
+
}
|
|
4023
|
+
this.process = child;
|
|
4024
|
+
child.on("error", (error) => {
|
|
4025
|
+
console.error(`[openscout-runtime] claude process error for ${this.options.agentName}: ${error.message}`);
|
|
4026
|
+
this.process = null;
|
|
4027
|
+
if (this.activeTurn) {
|
|
4028
|
+
const turn = this.activeTurn;
|
|
4029
|
+
this.activeTurn = null;
|
|
4030
|
+
if (turn.timer) {
|
|
4031
|
+
clearTimeout(turn.timer);
|
|
4032
|
+
}
|
|
4033
|
+
turn.reject(new Error(`Claude process error: ${error.message}`));
|
|
4034
|
+
}
|
|
3984
4035
|
});
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
4036
|
+
child.stdout.setEncoding("utf8");
|
|
4037
|
+
child.stderr.setEncoding("utf8");
|
|
4038
|
+
child.stdout.on("data", (chunk) => {
|
|
3988
4039
|
appendFile(this.stdoutLogPath, chunk).catch(() => {
|
|
3989
4040
|
return;
|
|
3990
4041
|
});
|
|
@@ -4000,12 +4051,12 @@ class ClaudeStreamJsonSession {
|
|
|
4000
4051
|
this.handleEvent(JSON.parse(trimmed));
|
|
4001
4052
|
}
|
|
4002
4053
|
});
|
|
4003
|
-
|
|
4054
|
+
child.stderr.on("data", (chunk) => {
|
|
4004
4055
|
appendFile(this.stderrLogPath, chunk).catch(() => {
|
|
4005
4056
|
return;
|
|
4006
4057
|
});
|
|
4007
4058
|
});
|
|
4008
|
-
|
|
4059
|
+
child.on("exit", (code) => {
|
|
4009
4060
|
if (code !== 0 && this.activeTurn) {
|
|
4010
4061
|
const turn = this.activeTurn;
|
|
4011
4062
|
this.activeTurn = null;
|
|
@@ -4150,7 +4201,7 @@ function parseJsonLine(line) {
|
|
|
4150
4201
|
return null;
|
|
4151
4202
|
}
|
|
4152
4203
|
}
|
|
4153
|
-
function
|
|
4204
|
+
function errorMessage2(error) {
|
|
4154
4205
|
if (error instanceof Error) {
|
|
4155
4206
|
return error.message;
|
|
4156
4207
|
}
|
|
@@ -4175,7 +4226,7 @@ async function readOptionalFile2(filePath) {
|
|
|
4175
4226
|
}
|
|
4176
4227
|
}
|
|
4177
4228
|
function isMissingCodexRolloutError(error) {
|
|
4178
|
-
const message =
|
|
4229
|
+
const message = errorMessage2(error).toLowerCase();
|
|
4179
4230
|
return message.includes("no rollout found for thread id");
|
|
4180
4231
|
}
|
|
4181
4232
|
|
|
@@ -4248,7 +4299,7 @@ class CodexAppServerSession {
|
|
|
4248
4299
|
await this.persistState();
|
|
4249
4300
|
} catch (error) {
|
|
4250
4301
|
this.clearActiveTurn(turn);
|
|
4251
|
-
reject(error instanceof Error ? error : new Error(
|
|
4302
|
+
reject(error instanceof Error ? error : new Error(errorMessage2(error)));
|
|
4252
4303
|
}
|
|
4253
4304
|
});
|
|
4254
4305
|
return {
|
|
@@ -4376,7 +4427,7 @@ class CodexAppServerSession {
|
|
|
4376
4427
|
});
|
|
4377
4428
|
});
|
|
4378
4429
|
child.once("error", (error) => {
|
|
4379
|
-
this.failSession(new Error(`Codex app-server failed for ${this.options.agentName}: ${
|
|
4430
|
+
this.failSession(new Error(`Codex app-server failed for ${this.options.agentName}: ${errorMessage2(error)}`));
|
|
4380
4431
|
});
|
|
4381
4432
|
child.once("exit", (code, signal) => {
|
|
4382
4433
|
this.failSession(new Error(`Codex app-server exited for ${this.options.agentName}` + (code !== null ? ` with code ${code}` : "") + (signal ? ` (${signal})` : "")));
|
|
@@ -4412,7 +4463,7 @@ class CodexAppServerSession {
|
|
|
4412
4463
|
await this.persistThreadId();
|
|
4413
4464
|
return;
|
|
4414
4465
|
} catch (error) {
|
|
4415
|
-
await appendFile2(this.stderrLogPath, `[openscout] failed to resume stored Codex thread ${storedThreadId}: ${
|
|
4466
|
+
await appendFile2(this.stderrLogPath, `[openscout] failed to resume stored Codex thread ${storedThreadId}: ${errorMessage2(error)}
|
|
4416
4467
|
`).catch(() => {
|
|
4417
4468
|
return;
|
|
4418
4469
|
});
|
|
@@ -4682,7 +4733,7 @@ class CodexAppServerSession {
|
|
|
4682
4733
|
});
|
|
4683
4734
|
} catch (error) {
|
|
4684
4735
|
this.pendingRequests.delete(id);
|
|
4685
|
-
reject(error instanceof Error ? error : new Error(
|
|
4736
|
+
reject(error instanceof Error ? error : new Error(errorMessage2(error)));
|
|
4686
4737
|
}
|
|
4687
4738
|
});
|
|
4688
4739
|
}
|
|
@@ -4759,7 +4810,7 @@ function buildCollaborationContractPrompt(agentId) {
|
|
|
4759
4810
|
|
|
4760
4811
|
// packages/runtime/src/broker-service.ts
|
|
4761
4812
|
import { spawnSync } from "child_process";
|
|
4762
|
-
import { existsSync as
|
|
4813
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4763
4814
|
import { homedir as homedir5 } from "os";
|
|
4764
4815
|
import { basename as basename3, dirname as dirname5, join as join8, resolve as resolve3 } from "path";
|
|
4765
4816
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -4780,7 +4831,7 @@ function runtimePackageDir() {
|
|
|
4780
4831
|
return resolve3(moduleDir, "..");
|
|
4781
4832
|
}
|
|
4782
4833
|
function isInstalledRuntimePackageDir(candidate) {
|
|
4783
|
-
return
|
|
4834
|
+
return existsSync5(join8(candidate, "package.json")) && existsSync5(join8(candidate, "bin", "openscout-runtime.mjs"));
|
|
4784
4835
|
}
|
|
4785
4836
|
function findGlobalRuntimeDir() {
|
|
4786
4837
|
const bunCandidate = join8(homedir5(), ".bun", "node_modules", "@openscout", "runtime");
|
|
@@ -4798,7 +4849,7 @@ function findWorkspaceRuntimeDir(startDir) {
|
|
|
4798
4849
|
let current = resolve3(startDir);
|
|
4799
4850
|
while (true) {
|
|
4800
4851
|
const candidate = join8(current, "packages", "runtime");
|
|
4801
|
-
if (
|
|
4852
|
+
if (existsSync5(join8(candidate, "package.json")) && existsSync5(join8(candidate, "src"))) {
|
|
4802
4853
|
return candidate;
|
|
4803
4854
|
}
|
|
4804
4855
|
const parent = dirname5(current);
|
|
@@ -4812,18 +4863,18 @@ function resolveBunExecutable() {
|
|
|
4812
4863
|
if (explicit && explicit.trim().length > 0) {
|
|
4813
4864
|
return explicit;
|
|
4814
4865
|
}
|
|
4815
|
-
if (basename3(process.execPath).startsWith("bun") &&
|
|
4866
|
+
if (basename3(process.execPath).startsWith("bun") && existsSync5(process.execPath)) {
|
|
4816
4867
|
return process.execPath;
|
|
4817
4868
|
}
|
|
4818
4869
|
const pathEntries = (process.env.PATH ?? "").split(":").filter(Boolean);
|
|
4819
4870
|
for (const entry of pathEntries) {
|
|
4820
4871
|
const candidate = join8(entry, "bun");
|
|
4821
|
-
if (
|
|
4872
|
+
if (existsSync5(candidate)) {
|
|
4822
4873
|
return candidate;
|
|
4823
4874
|
}
|
|
4824
4875
|
}
|
|
4825
4876
|
const homeBun = join8(homedir5(), ".bun", "bin", "bun");
|
|
4826
|
-
if (
|
|
4877
|
+
if (existsSync5(homeBun)) {
|
|
4827
4878
|
return homeBun;
|
|
4828
4879
|
}
|
|
4829
4880
|
return "bun";
|
|
@@ -5009,10 +5060,10 @@ function launchctlPath() {
|
|
|
5009
5060
|
return "/bin/launchctl";
|
|
5010
5061
|
}
|
|
5011
5062
|
function readLogLines(path) {
|
|
5012
|
-
if (!
|
|
5063
|
+
if (!existsSync5(path)) {
|
|
5013
5064
|
return [];
|
|
5014
5065
|
}
|
|
5015
|
-
return
|
|
5066
|
+
return readFileSync2(path, "utf8").split(`
|
|
5016
5067
|
`).map((line) => line.trim()).filter(Boolean);
|
|
5017
5068
|
}
|
|
5018
5069
|
function isPackageScriptBanner(line) {
|
|
@@ -5109,7 +5160,7 @@ async function brokerServiceStatus(config = resolveBrokerServiceConfig()) {
|
|
|
5109
5160
|
ensureServiceDirectories(config);
|
|
5110
5161
|
const launchctl = inspectLaunchctl(config);
|
|
5111
5162
|
const health = await fetchHealthSnapshot(config);
|
|
5112
|
-
const installed =
|
|
5163
|
+
const installed = existsSync5(config.launchAgentPath);
|
|
5113
5164
|
const lastLogLine = health.reachable ? readLastLogLine([config.stdoutLogPath, config.stderrLogPath]) : readLastLogLine([config.stderrLogPath, config.stdoutLogPath]);
|
|
5114
5165
|
return {
|
|
5115
5166
|
label: config.label,
|
|
@@ -5171,7 +5222,7 @@ async function restartBrokerService(config = resolveBrokerServiceConfig()) {
|
|
|
5171
5222
|
}
|
|
5172
5223
|
async function uninstallBrokerService(config = resolveBrokerServiceConfig()) {
|
|
5173
5224
|
await stopBrokerService(config);
|
|
5174
|
-
if (
|
|
5225
|
+
if (existsSync5(config.launchAgentPath)) {
|
|
5175
5226
|
rmSync2(config.launchAgentPath, { force: true });
|
|
5176
5227
|
}
|
|
5177
5228
|
return brokerServiceStatus(config);
|
|
@@ -5250,7 +5301,7 @@ var init_local_agent_template = __esm(() => {
|
|
|
5250
5301
|
|
|
5251
5302
|
// packages/runtime/src/local-agents.ts
|
|
5252
5303
|
import { execFileSync as execFileSync3, execSync } from "child_process";
|
|
5253
|
-
import { existsSync as
|
|
5304
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
|
|
5254
5305
|
import { mkdir as mkdir5, rm as rm4, stat as stat3, writeFile as writeFile5 } from "fs/promises";
|
|
5255
5306
|
import { basename as basename4, dirname as dirname6, join as join9, resolve as resolve4 } from "path";
|
|
5256
5307
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
@@ -5263,10 +5314,10 @@ function resolveProjectsRoot(projectPath) {
|
|
|
5263
5314
|
}
|
|
5264
5315
|
try {
|
|
5265
5316
|
const supportPaths = resolveOpenScoutSupportPaths();
|
|
5266
|
-
if (!
|
|
5317
|
+
if (!existsSync6(supportPaths.settingsPath)) {
|
|
5267
5318
|
return dirname6(projectPath);
|
|
5268
5319
|
}
|
|
5269
|
-
const raw2 = JSON.parse(
|
|
5320
|
+
const raw2 = JSON.parse(readFileSync3(supportPaths.settingsPath, "utf8"));
|
|
5270
5321
|
const workspaceRoot = raw2.discovery?.workspaceRoots?.find((entry) => typeof entry === "string" && entry.trim().length > 0);
|
|
5271
5322
|
return workspaceRoot ? resolve4(workspaceRoot) : dirname6(projectPath);
|
|
5272
5323
|
} catch {
|
|
@@ -5293,7 +5344,7 @@ function resolveScoutSkillPath() {
|
|
|
5293
5344
|
join9(process.env.HOME ?? "", ".agents", "skills", "relay-agent-comms", "SKILL.md")
|
|
5294
5345
|
];
|
|
5295
5346
|
for (const path of candidatePaths) {
|
|
5296
|
-
if (
|
|
5347
|
+
if (existsSync6(path)) {
|
|
5297
5348
|
return path;
|
|
5298
5349
|
}
|
|
5299
5350
|
}
|
|
@@ -5925,11 +5976,33 @@ function killAgentSession(sessionName) {
|
|
|
5925
5976
|
execSync(`tmux kill-session -t ${JSON.stringify(sessionName)}`, { stdio: "pipe" });
|
|
5926
5977
|
} catch {}
|
|
5927
5978
|
}
|
|
5979
|
+
function isHarnessBinaryAvailable(transport) {
|
|
5980
|
+
const binaryMap = {
|
|
5981
|
+
claude_stream_json: "claude",
|
|
5982
|
+
codex_app_server: "codex"
|
|
5983
|
+
};
|
|
5984
|
+
const binary = binaryMap[transport];
|
|
5985
|
+
if (!binary)
|
|
5986
|
+
return true;
|
|
5987
|
+
try {
|
|
5988
|
+
execFileSync3("sh", ["-lc", `command -v ${binary}`], {
|
|
5989
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
5990
|
+
encoding: "utf8"
|
|
5991
|
+
});
|
|
5992
|
+
return true;
|
|
5993
|
+
} catch {
|
|
5994
|
+
return false;
|
|
5995
|
+
}
|
|
5996
|
+
}
|
|
5928
5997
|
async function ensureLocalAgentOnline(agentName, record) {
|
|
5929
5998
|
const normalizedRecord = normalizeLocalAgentRecord(agentName, record);
|
|
5930
5999
|
if (isLocalAgentRecordOnline(agentName, normalizedRecord)) {
|
|
5931
6000
|
return normalizedRecord;
|
|
5932
6001
|
}
|
|
6002
|
+
if (!isHarnessBinaryAvailable(normalizedRecord.transport)) {
|
|
6003
|
+
console.warn(`[openscout-runtime] skipping warmup for ${agentName}: harness binary for ${normalizedRecord.transport} not found in PATH`);
|
|
6004
|
+
return normalizedRecord;
|
|
6005
|
+
}
|
|
5933
6006
|
const projectPath = normalizedRecord.cwd;
|
|
5934
6007
|
const projectName = normalizedRecord.project || basename4(projectPath);
|
|
5935
6008
|
const systemPromptTemplate = normalizedRecord.systemPrompt || buildLocalAgentSystemPromptTemplate();
|
|
@@ -6039,7 +6112,7 @@ async function ensureLocalAgentOnline(agentName, record) {
|
|
|
6039
6112
|
await new Promise((resolve5) => setTimeout(resolve5, 100));
|
|
6040
6113
|
}
|
|
6041
6114
|
if (!isLocalAgentSessionAlive(normalizedRecord.tmuxSession)) {
|
|
6042
|
-
const stderrTail =
|
|
6115
|
+
const stderrTail = existsSync6(stderrLogFile) ? readFileSync3(stderrLogFile, "utf8").trim().split(/\r?\n/).slice(-10).join(`
|
|
6043
6116
|
`).trim() : "";
|
|
6044
6117
|
throw new Error(stderrTail ? `Relay agent ${agentName} failed to stay online:
|
|
6045
6118
|
${stderrTail}` : `Relay agent ${agentName} failed to stay online.`);
|
|
@@ -6320,15 +6393,26 @@ async function loadRegisteredLocalAgentBindings(nodeId, options = {}) {
|
|
|
6320
6393
|
]);
|
|
6321
6394
|
const requestedAgentIds = new Set((options.agentIds ?? []).filter(Boolean));
|
|
6322
6395
|
const selectedEntries = Object.entries(registry).filter(([agentId]) => requestedAgentIds.size === 0 || requestedAgentIds.has(agentId));
|
|
6323
|
-
|
|
6396
|
+
const results = await Promise.all(selectedEntries.map(async ([agentId, record]) => {
|
|
6324
6397
|
const baseRecord = overrides[agentId]?.projectRoot ? {
|
|
6325
6398
|
...record,
|
|
6326
6399
|
projectRoot: overrides[agentId].projectRoot
|
|
6327
6400
|
} : record;
|
|
6328
6401
|
const harnessRecord = options.harness ? recordForHarness(baseRecord, options.harness) : baseRecord;
|
|
6329
|
-
|
|
6402
|
+
let effectiveRecord;
|
|
6403
|
+
if (options.ensureOnline) {
|
|
6404
|
+
try {
|
|
6405
|
+
effectiveRecord = await ensureLocalAgentOnline(agentId, harnessRecord);
|
|
6406
|
+
} catch (error) {
|
|
6407
|
+
console.error(`[openscout-runtime] failed to warm agent ${agentId}: ${error instanceof Error ? error.message : error}`);
|
|
6408
|
+
effectiveRecord = normalizeLocalAgentRecord(agentId, harnessRecord);
|
|
6409
|
+
}
|
|
6410
|
+
} else {
|
|
6411
|
+
effectiveRecord = normalizeLocalAgentRecord(agentId, harnessRecord);
|
|
6412
|
+
}
|
|
6330
6413
|
return buildLocalAgentBinding(agentId, effectiveRecord, isLocalAgentRecordOnline(agentId, effectiveRecord), nodeId, "relay-agent-registry");
|
|
6331
6414
|
}));
|
|
6415
|
+
return results;
|
|
6332
6416
|
}
|
|
6333
6417
|
async function inferLocalAgentBinding(agentId, nodeId) {
|
|
6334
6418
|
if (!agentId || BUILT_IN_LOCAL_AGENT_IDS.has(agentId)) {
|
|
@@ -7940,7 +8024,7 @@ init_setup();
|
|
|
7940
8024
|
|
|
7941
8025
|
// apps/desktop/src/shared/product.ts
|
|
7942
8026
|
var SCOUT_PRODUCT_NAME = "Scout";
|
|
7943
|
-
var SCOUT_APP_VERSION = "0.2.
|
|
8027
|
+
var SCOUT_APP_VERSION = "0.2.21";
|
|
7944
8028
|
|
|
7945
8029
|
// apps/desktop/src/shared/surface-capabilities.ts
|
|
7946
8030
|
function resolveScoutSurfaceCapabilities(surface) {
|
|
@@ -7987,7 +8071,7 @@ import path3 from "path";
|
|
|
7987
8071
|
// apps/desktop/src/app/host/runtime-service-client.ts
|
|
7988
8072
|
import { spawn } from "child_process";
|
|
7989
8073
|
import { basename as basename2, dirname as dirname4, join as join5 } from "path";
|
|
7990
|
-
import { existsSync as
|
|
8074
|
+
import { existsSync as existsSync4 } from "fs";
|
|
7991
8075
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7992
8076
|
import { homedir as homedir4 } from "os";
|
|
7993
8077
|
function tryWhich(executableName) {
|
|
@@ -7997,13 +8081,13 @@ function tryWhich(executableName) {
|
|
|
7997
8081
|
if (!dir)
|
|
7998
8082
|
continue;
|
|
7999
8083
|
const candidate = join5(dir, executableName);
|
|
8000
|
-
if (
|
|
8084
|
+
if (existsSync4(candidate)) {
|
|
8001
8085
|
return candidate;
|
|
8002
8086
|
}
|
|
8003
8087
|
if (process.platform === "win32") {
|
|
8004
8088
|
for (const ext of [".cmd", ".exe", ".bat"]) {
|
|
8005
8089
|
const withExt = candidate + ext;
|
|
8006
|
-
if (
|
|
8090
|
+
if (existsSync4(withExt))
|
|
8007
8091
|
return withExt;
|
|
8008
8092
|
}
|
|
8009
8093
|
}
|
|
@@ -8015,7 +8099,7 @@ function findNodeModulesRuntimeBin() {
|
|
|
8015
8099
|
let dir = dirname4(fileURLToPath3(import.meta.url));
|
|
8016
8100
|
for (let i = 0;i < 24; i++) {
|
|
8017
8101
|
const candidate = join5(dir, runtimeBinRel);
|
|
8018
|
-
if (
|
|
8102
|
+
if (existsSync4(candidate))
|
|
8019
8103
|
return candidate;
|
|
8020
8104
|
const parent = dirname4(dir);
|
|
8021
8105
|
if (parent === dir)
|
|
@@ -8023,7 +8107,7 @@ function findNodeModulesRuntimeBin() {
|
|
|
8023
8107
|
dir = parent;
|
|
8024
8108
|
}
|
|
8025
8109
|
const bunGlobal = join5(homedir4(), ".bun", "install", "global", "node_modules", "@openscout", "runtime", "bin", "openscout-runtime.mjs");
|
|
8026
|
-
if (
|
|
8110
|
+
if (existsSync4(bunGlobal))
|
|
8027
8111
|
return bunGlobal;
|
|
8028
8112
|
return null;
|
|
8029
8113
|
}
|
|
@@ -8031,7 +8115,7 @@ function findMonorepoOpenscoutRuntimeBin() {
|
|
|
8031
8115
|
let dir = process.cwd();
|
|
8032
8116
|
for (let i = 0;i < 24; i++) {
|
|
8033
8117
|
const candidate = join5(dir, "packages", "runtime", "bin", "openscout-runtime.mjs");
|
|
8034
|
-
if (
|
|
8118
|
+
if (existsSync4(candidate)) {
|
|
8035
8119
|
return candidate;
|
|
8036
8120
|
}
|
|
8037
8121
|
const parent = dirname4(dir);
|
|
@@ -8044,7 +8128,7 @@ function findMonorepoOpenscoutRuntimeBin() {
|
|
|
8044
8128
|
function resolveJavaScriptRuntimeExecutable() {
|
|
8045
8129
|
const explicit = process.env.OPENSCOUT_RUNTIME_NODE_BIN?.trim();
|
|
8046
8130
|
if (explicit) {
|
|
8047
|
-
if (
|
|
8131
|
+
if (existsSync4(explicit)) {
|
|
8048
8132
|
return explicit;
|
|
8049
8133
|
}
|
|
8050
8134
|
const found = tryWhich(explicit);
|
|
@@ -8070,7 +8154,7 @@ function resolveJavaScriptRuntimeExecutable() {
|
|
|
8070
8154
|
function resolveRuntimeServiceEntrypoint() {
|
|
8071
8155
|
const explicit = process.env.OPENSCOUT_RUNTIME_BIN?.trim();
|
|
8072
8156
|
if (explicit) {
|
|
8073
|
-
if (
|
|
8157
|
+
if (existsSync4(explicit)) {
|
|
8074
8158
|
return explicit;
|
|
8075
8159
|
}
|
|
8076
8160
|
const found = tryWhich(explicit);
|
|
@@ -8662,7 +8746,7 @@ function createScoutVoiceState(input = {}) {
|
|
|
8662
8746
|
// apps/desktop/src/app/desktop/shell-probes.ts
|
|
8663
8747
|
init_setup();
|
|
8664
8748
|
init_support_paths();
|
|
8665
|
-
import { existsSync as
|
|
8749
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
|
|
8666
8750
|
import path2 from "path";
|
|
8667
8751
|
|
|
8668
8752
|
// apps/desktop/src/app/desktop/shell-utils.ts
|
|
@@ -8747,7 +8831,7 @@ var PROJECT_GIT_ACTIVITY_CACHE_TTL_MS = 60000;
|
|
|
8747
8831
|
var projectGitActivityCache = new Map;
|
|
8748
8832
|
function readHelperStatus() {
|
|
8749
8833
|
const statusPath = resolveOpenScoutSupportPaths().desktopStatusPath;
|
|
8750
|
-
if (!
|
|
8834
|
+
if (!existsSync7(statusPath)) {
|
|
8751
8835
|
return {
|
|
8752
8836
|
running: false,
|
|
8753
8837
|
detail: null,
|
|
@@ -8755,7 +8839,7 @@ function readHelperStatus() {
|
|
|
8755
8839
|
};
|
|
8756
8840
|
}
|
|
8757
8841
|
try {
|
|
8758
|
-
const raw2 = JSON.parse(
|
|
8842
|
+
const raw2 = JSON.parse(readFileSync4(statusPath, "utf8"));
|
|
8759
8843
|
return {
|
|
8760
8844
|
running: raw2.state === "running",
|
|
8761
8845
|
detail: typeof raw2.detail === "string" ? raw2.detail : null,
|
|
@@ -8793,7 +8877,7 @@ function readTmuxSessionOutput() {
|
|
|
8793
8877
|
}
|
|
8794
8878
|
function readDesktopSettingsRecord() {
|
|
8795
8879
|
try {
|
|
8796
|
-
return JSON.parse(
|
|
8880
|
+
return JSON.parse(readFileSync4(resolveOpenScoutSupportPaths().settingsPath, "utf8"));
|
|
8797
8881
|
} catch {
|
|
8798
8882
|
return {};
|
|
8799
8883
|
}
|
|
@@ -11648,22 +11732,22 @@ async function sendScoutElectronRelayMessage(input, options = {}) {
|
|
|
11648
11732
|
init_support_paths();
|
|
11649
11733
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
11650
11734
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
11651
|
-
import { existsSync as
|
|
11735
|
+
import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
|
|
11652
11736
|
import { open as open2 } from "fs/promises";
|
|
11653
11737
|
import os from "os";
|
|
11654
11738
|
import path5 from "path";
|
|
11655
11739
|
|
|
11656
11740
|
// apps/desktop/src/shared/paths.ts
|
|
11657
|
-
import { existsSync as
|
|
11741
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
|
|
11658
11742
|
import { dirname as dirname7, join as join10, resolve as resolve5 } from "path";
|
|
11659
11743
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
11660
11744
|
function looksLikeWorkspaceRoot(candidate) {
|
|
11661
11745
|
const packageJsonPath = join10(candidate, "package.json");
|
|
11662
|
-
if (!
|
|
11746
|
+
if (!existsSync8(packageJsonPath)) {
|
|
11663
11747
|
return false;
|
|
11664
11748
|
}
|
|
11665
11749
|
try {
|
|
11666
|
-
const parsed = JSON.parse(
|
|
11750
|
+
const parsed = JSON.parse(readFileSync5(packageJsonPath, "utf8"));
|
|
11667
11751
|
return Array.isArray(parsed.workspaces);
|
|
11668
11752
|
} catch {
|
|
11669
11753
|
return false;
|
|
@@ -11671,11 +11755,11 @@ function looksLikeWorkspaceRoot(candidate) {
|
|
|
11671
11755
|
}
|
|
11672
11756
|
function looksLikePackagedAppRoot(candidate) {
|
|
11673
11757
|
const packageJsonPath = join10(candidate, "package.json");
|
|
11674
|
-
if (!
|
|
11758
|
+
if (!existsSync8(packageJsonPath)) {
|
|
11675
11759
|
return false;
|
|
11676
11760
|
}
|
|
11677
11761
|
try {
|
|
11678
|
-
const parsed = JSON.parse(
|
|
11762
|
+
const parsed = JSON.parse(readFileSync5(packageJsonPath, "utf8"));
|
|
11679
11763
|
return parsed.name === "@scout/electron-app";
|
|
11680
11764
|
} catch {
|
|
11681
11765
|
return false;
|
|
@@ -11683,18 +11767,18 @@ function looksLikePackagedAppRoot(candidate) {
|
|
|
11683
11767
|
}
|
|
11684
11768
|
function looksLikeInstalledCliRoot(candidate) {
|
|
11685
11769
|
const packageJsonPath = join10(candidate, "package.json");
|
|
11686
|
-
if (!
|
|
11770
|
+
if (!existsSync8(packageJsonPath)) {
|
|
11687
11771
|
return false;
|
|
11688
11772
|
}
|
|
11689
11773
|
try {
|
|
11690
|
-
const parsed = JSON.parse(
|
|
11774
|
+
const parsed = JSON.parse(readFileSync5(packageJsonPath, "utf8"));
|
|
11691
11775
|
return parsed.name === "@openscout/scout" || parsed.name === "@openscout/cli";
|
|
11692
11776
|
} catch {
|
|
11693
11777
|
return false;
|
|
11694
11778
|
}
|
|
11695
11779
|
}
|
|
11696
11780
|
function looksLikeSourceAppRoot(candidate) {
|
|
11697
|
-
return
|
|
11781
|
+
return existsSync8(join10(candidate, "bin", "scout.ts"));
|
|
11698
11782
|
}
|
|
11699
11783
|
function findMatchingAncestor(startDirectory, predicate) {
|
|
11700
11784
|
let current = resolve5(startDirectory);
|
|
@@ -11768,9 +11852,9 @@ import { spawn as spawn4 } from "child_process";
|
|
|
11768
11852
|
import {
|
|
11769
11853
|
accessSync,
|
|
11770
11854
|
constants as constants2,
|
|
11771
|
-
existsSync as
|
|
11855
|
+
existsSync as existsSync9,
|
|
11772
11856
|
mkdirSync as mkdirSync3,
|
|
11773
|
-
readFileSync as
|
|
11857
|
+
readFileSync as readFileSync6,
|
|
11774
11858
|
statSync as statSync2,
|
|
11775
11859
|
unlinkSync,
|
|
11776
11860
|
writeFileSync as writeFileSync3
|
|
@@ -12009,11 +12093,11 @@ async function loadScoutPairingPendingApprovals(port) {
|
|
|
12009
12093
|
}
|
|
12010
12094
|
function loadScoutPairingConfig() {
|
|
12011
12095
|
const { configPath } = resolveScoutPairingPaths();
|
|
12012
|
-
if (!
|
|
12096
|
+
if (!existsSync9(configPath)) {
|
|
12013
12097
|
return {};
|
|
12014
12098
|
}
|
|
12015
12099
|
try {
|
|
12016
|
-
const payload = JSON.parse(
|
|
12100
|
+
const payload = JSON.parse(readFileSync6(configPath, "utf8"));
|
|
12017
12101
|
return typeof payload === "object" && payload ? payload : {};
|
|
12018
12102
|
} catch {
|
|
12019
12103
|
return {};
|
|
@@ -12044,11 +12128,11 @@ async function resolveDefaultScoutPairingWorkspaceRoot(currentDirectory) {
|
|
|
12044
12128
|
}
|
|
12045
12129
|
function readScoutPairingRuntimeSnapshot() {
|
|
12046
12130
|
const { runtimeStatePath } = resolveScoutPairingPaths();
|
|
12047
|
-
if (!
|
|
12131
|
+
if (!existsSync9(runtimeStatePath)) {
|
|
12048
12132
|
return null;
|
|
12049
12133
|
}
|
|
12050
12134
|
try {
|
|
12051
|
-
const parsed = JSON.parse(
|
|
12135
|
+
const parsed = JSON.parse(readFileSync6(runtimeStatePath, "utf8"));
|
|
12052
12136
|
return parsed?.version === SCOUT_PAIRING_RUNTIME_VERSION ? parsed : null;
|
|
12053
12137
|
} catch {
|
|
12054
12138
|
return null;
|
|
@@ -12062,11 +12146,11 @@ function clearScoutPairingRuntimeSnapshot() {
|
|
|
12062
12146
|
}
|
|
12063
12147
|
function readScoutPairingRuntimePid() {
|
|
12064
12148
|
const { runtimePidPath } = resolveScoutPairingPaths();
|
|
12065
|
-
if (!
|
|
12149
|
+
if (!existsSync9(runtimePidPath)) {
|
|
12066
12150
|
return null;
|
|
12067
12151
|
}
|
|
12068
12152
|
try {
|
|
12069
|
-
const raw2 =
|
|
12153
|
+
const raw2 = readFileSync6(runtimePidPath, "utf8").trim();
|
|
12070
12154
|
const pid = Number(raw2);
|
|
12071
12155
|
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
12072
12156
|
} catch {
|
|
@@ -12118,22 +12202,22 @@ function clearStaleScoutPairingRuntimeFiles() {
|
|
|
12118
12202
|
clearScoutPairingRuntimeSnapshot();
|
|
12119
12203
|
}
|
|
12120
12204
|
function readScoutPairingIdentityFingerprint(identityPath) {
|
|
12121
|
-
if (!
|
|
12205
|
+
if (!existsSync9(identityPath)) {
|
|
12122
12206
|
return null;
|
|
12123
12207
|
}
|
|
12124
12208
|
try {
|
|
12125
|
-
const payload = JSON.parse(
|
|
12209
|
+
const payload = JSON.parse(readFileSync6(identityPath, "utf8"));
|
|
12126
12210
|
return typeof payload.publicKey === "string" && payload.publicKey.length > 0 ? payload.publicKey.slice(0, 16) : null;
|
|
12127
12211
|
} catch {
|
|
12128
12212
|
return null;
|
|
12129
12213
|
}
|
|
12130
12214
|
}
|
|
12131
12215
|
function readScoutPairingTrustedPeerCount(trustedPeersPath) {
|
|
12132
|
-
if (!
|
|
12216
|
+
if (!existsSync9(trustedPeersPath)) {
|
|
12133
12217
|
return 0;
|
|
12134
12218
|
}
|
|
12135
12219
|
try {
|
|
12136
|
-
const payload = JSON.parse(
|
|
12220
|
+
const payload = JSON.parse(readFileSync6(trustedPeersPath, "utf8"));
|
|
12137
12221
|
return Array.isArray(payload) ? payload.length : 0;
|
|
12138
12222
|
} catch {
|
|
12139
12223
|
return 0;
|
|
@@ -12155,11 +12239,11 @@ function formatScoutPairingHistoryTimestamp(value) {
|
|
|
12155
12239
|
}).format(date);
|
|
12156
12240
|
}
|
|
12157
12241
|
function readScoutPairingTrustedPeers(trustedPeersPath) {
|
|
12158
|
-
if (!
|
|
12242
|
+
if (!existsSync9(trustedPeersPath)) {
|
|
12159
12243
|
return [];
|
|
12160
12244
|
}
|
|
12161
12245
|
try {
|
|
12162
|
-
const payload = JSON.parse(
|
|
12246
|
+
const payload = JSON.parse(readFileSync6(trustedPeersPath, "utf8"));
|
|
12163
12247
|
if (!Array.isArray(payload)) {
|
|
12164
12248
|
return [];
|
|
12165
12249
|
}
|
|
@@ -12183,7 +12267,7 @@ function readScoutPairingTrustedPeers(trustedPeersPath) {
|
|
|
12183
12267
|
}
|
|
12184
12268
|
}
|
|
12185
12269
|
function readScoutPairingLogTail(logPath) {
|
|
12186
|
-
if (!
|
|
12270
|
+
if (!existsSync9(logPath)) {
|
|
12187
12271
|
return {
|
|
12188
12272
|
body: "",
|
|
12189
12273
|
updatedAtLabel: null,
|
|
@@ -12191,7 +12275,7 @@ function readScoutPairingLogTail(logPath) {
|
|
|
12191
12275
|
truncated: false
|
|
12192
12276
|
};
|
|
12193
12277
|
}
|
|
12194
|
-
const body =
|
|
12278
|
+
const body = readFileSync6(logPath, "utf8");
|
|
12195
12279
|
const lines = body.split(/\r?\n/g);
|
|
12196
12280
|
const visibleLines = lines.slice(-SCOUT_PAIRING_LOG_TAIL_LINE_LIMIT);
|
|
12197
12281
|
const stats = statSync2(logPath);
|
|
@@ -12262,7 +12346,7 @@ function resolveScoutPairingRuntimeScriptPath() {
|
|
|
12262
12346
|
join11(appRoot, "..", "..", "packages", "electron-app", "dist", "electron", SCOUT_PAIRING_RUNTIME_SCRIPT.replace(/\.ts$/, ".js"))
|
|
12263
12347
|
];
|
|
12264
12348
|
for (const candidate of candidates) {
|
|
12265
|
-
if (
|
|
12349
|
+
if (existsSync9(candidate)) {
|
|
12266
12350
|
return candidate;
|
|
12267
12351
|
}
|
|
12268
12352
|
}
|
|
@@ -12479,7 +12563,7 @@ init_setup();
|
|
|
12479
12563
|
init_support_paths();
|
|
12480
12564
|
await init_local_agents();
|
|
12481
12565
|
import { spawn as spawn5 } from "child_process";
|
|
12482
|
-
import { existsSync as
|
|
12566
|
+
import { existsSync as existsSync10 } from "fs";
|
|
12483
12567
|
import { homedir as homedir8 } from "os";
|
|
12484
12568
|
import path4 from "path";
|
|
12485
12569
|
|
|
@@ -12600,7 +12684,7 @@ function defaultOnboardingContextRoot(explicitRoot, workspaceRoots, fallback) {
|
|
|
12600
12684
|
return path4.resolve(expandHomePath5(chosenRoot));
|
|
12601
12685
|
}
|
|
12602
12686
|
function isExecutable3(candidate) {
|
|
12603
|
-
return
|
|
12687
|
+
return existsSync10(candidate);
|
|
12604
12688
|
}
|
|
12605
12689
|
function resolveScoutElectronScoutExecutable() {
|
|
12606
12690
|
const explicit = process.env.OPENSCOUT_SCOUT_BIN ?? process.env.SCOUT_BIN;
|
|
@@ -12702,7 +12786,7 @@ function buildOnboardingSteps(input) {
|
|
|
12702
12786
|
}
|
|
12703
12787
|
function resolveCurrentProjectConfigPath(onboardingContextRoot) {
|
|
12704
12788
|
const candidate = path4.join(onboardingContextRoot, ".openscout", "project.json");
|
|
12705
|
-
return
|
|
12789
|
+
return existsSync10(candidate) ? candidate : null;
|
|
12706
12790
|
}
|
|
12707
12791
|
async function loadScoutElectronSettingsBase(currentDirectory, services = {}, input = {}) {
|
|
12708
12792
|
const settingsDirectory = resolveSettingsDirectory(currentDirectory);
|
|
@@ -12796,7 +12880,7 @@ function buildScoutElectronAppSettingsState(base, input) {
|
|
|
12796
12880
|
return {
|
|
12797
12881
|
root: compactHomePath4(normalizedRoot) ?? normalizedRoot,
|
|
12798
12882
|
title: path4.basename(normalizedRoot) || normalizedRoot,
|
|
12799
|
-
projectConfigPath:
|
|
12883
|
+
projectConfigPath: existsSync10(projectConfigFilePath) ? compactHomePath4(projectConfigFilePath) ?? projectConfigFilePath : null
|
|
12800
12884
|
};
|
|
12801
12885
|
}),
|
|
12802
12886
|
workspaceRootsNote: "Scan folders are user-configured. Scout walks them recursively to find repos, project roots, and harness evidence.",
|
|
@@ -13196,11 +13280,11 @@ function runOptionalCommand3(command, args) {
|
|
|
13196
13280
|
}
|
|
13197
13281
|
}
|
|
13198
13282
|
function readPackageVersion(candidate) {
|
|
13199
|
-
if (!
|
|
13283
|
+
if (!existsSync11(candidate)) {
|
|
13200
13284
|
return null;
|
|
13201
13285
|
}
|
|
13202
13286
|
try {
|
|
13203
|
-
const payload = JSON.parse(
|
|
13287
|
+
const payload = JSON.parse(readFileSync7(candidate, "utf8"));
|
|
13204
13288
|
if (typeof payload.version === "string" && payload.version.trim().length > 0) {
|
|
13205
13289
|
return payload.version.trim();
|
|
13206
13290
|
}
|
|
@@ -13373,8 +13457,8 @@ function appModeLabel() {
|
|
|
13373
13457
|
try {
|
|
13374
13458
|
const appRoot = resolveScoutAppRoot();
|
|
13375
13459
|
const packageJsonPath = path5.join(appRoot, "package.json");
|
|
13376
|
-
if (
|
|
13377
|
-
const payload = JSON.parse(
|
|
13460
|
+
if (existsSync11(packageJsonPath)) {
|
|
13461
|
+
const payload = JSON.parse(readFileSync7(packageJsonPath, "utf8"));
|
|
13378
13462
|
if (payload.name === "@scout/electron-app") {
|
|
13379
13463
|
return "packaged";
|
|
13380
13464
|
}
|
|
@@ -13504,7 +13588,7 @@ async function tailScoutLogSource(source, tailLines = DEFAULT_LOG_TAIL_LINES) {
|
|
|
13504
13588
|
let truncated = false;
|
|
13505
13589
|
let foundAny = false;
|
|
13506
13590
|
for (const filePath of source.paths) {
|
|
13507
|
-
if (!
|
|
13591
|
+
if (!existsSync11(filePath)) {
|
|
13508
13592
|
continue;
|
|
13509
13593
|
}
|
|
13510
13594
|
foundAny = true;
|
|
@@ -13769,7 +13853,7 @@ async function submitScoutElectronFeedbackReport(input, currentDirectory = proce
|
|
|
13769
13853
|
}
|
|
13770
13854
|
|
|
13771
13855
|
// apps/desktop/src/app/electron/host.ts
|
|
13772
|
-
import { existsSync as
|
|
13856
|
+
import { existsSync as existsSync12 } from "fs";
|
|
13773
13857
|
import { stat as stat5 } from "fs/promises";
|
|
13774
13858
|
import path6 from "path";
|
|
13775
13859
|
function expandHomePath6(value) {
|
|
@@ -13809,16 +13893,16 @@ async function revealScoutElectronPath(filePath, host = {}) {
|
|
|
13809
13893
|
if (!targetPath) {
|
|
13810
13894
|
return false;
|
|
13811
13895
|
}
|
|
13812
|
-
if (
|
|
13896
|
+
if (existsSync12(targetPath)) {
|
|
13813
13897
|
try {
|
|
13814
13898
|
const targetStats = await stat5(targetPath);
|
|
13815
13899
|
if (targetStats.isDirectory()) {
|
|
13816
13900
|
if (!host.openPath) {
|
|
13817
13901
|
throw new Error("Scout path opening is unavailable.");
|
|
13818
13902
|
}
|
|
13819
|
-
const
|
|
13820
|
-
if (
|
|
13821
|
-
throw new Error(
|
|
13903
|
+
const errorMessage3 = await host.openPath(targetPath);
|
|
13904
|
+
if (errorMessage3) {
|
|
13905
|
+
throw new Error(errorMessage3);
|
|
13822
13906
|
}
|
|
13823
13907
|
return true;
|
|
13824
13908
|
}
|
|
@@ -14052,7 +14136,7 @@ function releaseScoutKeepAliveLease(leaseId) {
|
|
|
14052
14136
|
|
|
14053
14137
|
// apps/desktop/src/app/host/agent-session.ts
|
|
14054
14138
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
14055
|
-
import { existsSync as
|
|
14139
|
+
import { existsSync as existsSync13 } from "fs";
|
|
14056
14140
|
import { open as open3 } from "fs/promises";
|
|
14057
14141
|
import path7 from "path";
|
|
14058
14142
|
init_support_paths();
|
|
@@ -14205,7 +14289,7 @@ async function readAgentSessionLogs(agentId, tailLines) {
|
|
|
14205
14289
|
let foundAny = false;
|
|
14206
14290
|
let targetPath = null;
|
|
14207
14291
|
for (const filePath of sources) {
|
|
14208
|
-
if (!
|
|
14292
|
+
if (!existsSync13(filePath)) {
|
|
14209
14293
|
continue;
|
|
14210
14294
|
}
|
|
14211
14295
|
foundAny = true;
|
|
@@ -14384,9 +14468,9 @@ async function openScoutElectronAgentSession(agentId, host = {}) {
|
|
|
14384
14468
|
if (!host.openPath) {
|
|
14385
14469
|
throw new Error("Scout agent-session path opening is unavailable.");
|
|
14386
14470
|
}
|
|
14387
|
-
const
|
|
14388
|
-
if (
|
|
14389
|
-
throw new Error(
|
|
14471
|
+
const errorMessage3 = await host.openPath(targetPath);
|
|
14472
|
+
if (errorMessage3) {
|
|
14473
|
+
throw new Error(errorMessage3);
|
|
14390
14474
|
}
|
|
14391
14475
|
return true;
|
|
14392
14476
|
}
|
|
@@ -15116,7 +15200,7 @@ async function deriveNewAgentName(projectName, branch, harness) {
|
|
|
15116
15200
|
async function createGitWorktree(projectRoot, agentName) {
|
|
15117
15201
|
const { execSync: execSync2 } = await import("child_process");
|
|
15118
15202
|
const { join: join12 } = await import("path");
|
|
15119
|
-
const { mkdirSync: mkdirSync4, existsSync:
|
|
15203
|
+
const { mkdirSync: mkdirSync4, existsSync: existsSync14 } = await import("fs");
|
|
15120
15204
|
try {
|
|
15121
15205
|
execSync2("git rev-parse --git-dir", { cwd: projectRoot, stdio: "pipe" });
|
|
15122
15206
|
} catch {
|
|
@@ -15125,7 +15209,7 @@ async function createGitWorktree(projectRoot, agentName) {
|
|
|
15125
15209
|
const branchName = `scout/${agentName}`;
|
|
15126
15210
|
const worktreeDir = join12(projectRoot, ".scout-worktrees");
|
|
15127
15211
|
const worktreePath = join12(worktreeDir, agentName);
|
|
15128
|
-
if (
|
|
15212
|
+
if (existsSync14(worktreePath)) {
|
|
15129
15213
|
return { path: worktreePath, branch: branchName };
|
|
15130
15214
|
}
|
|
15131
15215
|
mkdirSync4(worktreeDir, { recursive: true });
|