@openscout/scout 0.2.51 → 0.2.53
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 +25 -4
- package/dist/client/assets/{arc.es-CXoMwIWo.js → arc.es-DHqqknxg.js} +1 -1
- package/dist/client/assets/index-DYZld5kI.css +1 -0
- package/dist/client/assets/index-DzoSArBb.js +139 -0
- package/dist/client/index.html +2 -2
- package/dist/main.mjs +40824 -40196
- package/dist/pair-supervisor.mjs +486 -320
- package/dist/scout-control-plane-web.mjs +12898 -12173
- package/package.json +2 -2
- package/dist/client/assets/index-C2dy1gpj.css +0 -1
- package/dist/client/assets/index-CGoQ5qP4.js +0 -140
- package/dist/client/assets/index-TVkH_WDG.js +0 -1
package/dist/pair-supervisor.mjs
CHANGED
|
@@ -3376,7 +3376,7 @@ function writeJsonAtomically(filePath, value) {
|
|
|
3376
3376
|
}
|
|
3377
3377
|
|
|
3378
3378
|
// ../../apps/desktop/src/core/pairing/runtime/runtime.ts
|
|
3379
|
-
import { homedir as
|
|
3379
|
+
import { homedir as homedir18 } from "os";
|
|
3380
3380
|
// ../agent-sessions/src/protocol/adapter.ts
|
|
3381
3381
|
class BaseAdapter {
|
|
3382
3382
|
config;
|
|
@@ -4436,9 +4436,144 @@ function decodeClaudeProjectsSlug(slug) {
|
|
|
4436
4436
|
}
|
|
4437
4437
|
// ../agent-sessions/src/adapters/codex.ts
|
|
4438
4438
|
import { spawn } from "child_process";
|
|
4439
|
-
import { access, appendFile, constants, mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
4440
|
-
import { delimiter, join as
|
|
4439
|
+
import { access, appendFile, constants as constants2, mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
4440
|
+
import { delimiter as delimiter2, join as join5 } from "path";
|
|
4441
|
+
import { homedir as homedir6 } from "os";
|
|
4442
|
+
|
|
4443
|
+
// ../agent-sessions/src/codex-launch-config.ts
|
|
4444
|
+
import { accessSync, constants, existsSync as existsSync6 } from "fs";
|
|
4441
4445
|
import { homedir as homedir5 } from "os";
|
|
4446
|
+
import { basename, delimiter, dirname, join as join4, resolve } from "path";
|
|
4447
|
+
import { fileURLToPath } from "url";
|
|
4448
|
+
function isExecutable(filePath) {
|
|
4449
|
+
if (!filePath) {
|
|
4450
|
+
return false;
|
|
4451
|
+
}
|
|
4452
|
+
try {
|
|
4453
|
+
accessSync(filePath, constants.X_OK);
|
|
4454
|
+
return true;
|
|
4455
|
+
} catch {
|
|
4456
|
+
return false;
|
|
4457
|
+
}
|
|
4458
|
+
}
|
|
4459
|
+
function uniquePaths(values) {
|
|
4460
|
+
return [...new Set(values.filter((value) => typeof value === "string" && value.trim().length > 0).map((value) => resolve(value)))];
|
|
4461
|
+
}
|
|
4462
|
+
function ancestorChain(start) {
|
|
4463
|
+
const chain = [];
|
|
4464
|
+
let current = resolve(start);
|
|
4465
|
+
while (true) {
|
|
4466
|
+
chain.push(current);
|
|
4467
|
+
const parent = dirname(current);
|
|
4468
|
+
if (parent === current) {
|
|
4469
|
+
return chain;
|
|
4470
|
+
}
|
|
4471
|
+
current = parent;
|
|
4472
|
+
}
|
|
4473
|
+
}
|
|
4474
|
+
function resolveExecutableFromSearchPath(names, env) {
|
|
4475
|
+
const pathEntries = (env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
4476
|
+
const commonDirectories = [
|
|
4477
|
+
join4(homedir5(), ".local", "bin"),
|
|
4478
|
+
join4(homedir5(), ".bun", "bin"),
|
|
4479
|
+
"/opt/homebrew/bin",
|
|
4480
|
+
"/usr/local/bin"
|
|
4481
|
+
];
|
|
4482
|
+
for (const directory of [...pathEntries, ...commonDirectories]) {
|
|
4483
|
+
for (const name of names) {
|
|
4484
|
+
const candidate = join4(directory, name);
|
|
4485
|
+
if (isExecutable(candidate)) {
|
|
4486
|
+
return candidate;
|
|
4487
|
+
}
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
return null;
|
|
4491
|
+
}
|
|
4492
|
+
function resolveBunExecutable(env) {
|
|
4493
|
+
const explicitCandidates = [
|
|
4494
|
+
env.OPENSCOUT_BUN_BIN,
|
|
4495
|
+
env.SCOUT_BUN_BIN,
|
|
4496
|
+
env.BUN_BIN
|
|
4497
|
+
];
|
|
4498
|
+
for (const candidate of explicitCandidates) {
|
|
4499
|
+
if (isExecutable(candidate)) {
|
|
4500
|
+
return candidate;
|
|
4501
|
+
}
|
|
4502
|
+
}
|
|
4503
|
+
if (basename(process.execPath).startsWith("bun") && isExecutable(process.execPath)) {
|
|
4504
|
+
return process.execPath;
|
|
4505
|
+
}
|
|
4506
|
+
return resolveExecutableFromSearchPath(["bun"], env);
|
|
4507
|
+
}
|
|
4508
|
+
function resolveScoutExecutable(env) {
|
|
4509
|
+
const explicitCandidates = [
|
|
4510
|
+
env.OPENSCOUT_CLI_BIN,
|
|
4511
|
+
env.SCOUT_CLI_BIN,
|
|
4512
|
+
env.OPENSCOUT_SCOUT_BIN,
|
|
4513
|
+
env.SCOUT_BIN
|
|
4514
|
+
];
|
|
4515
|
+
for (const candidate of explicitCandidates) {
|
|
4516
|
+
if (isExecutable(candidate)) {
|
|
4517
|
+
return candidate;
|
|
4518
|
+
}
|
|
4519
|
+
}
|
|
4520
|
+
return resolveExecutableFromSearchPath(["scout"], env);
|
|
4521
|
+
}
|
|
4522
|
+
function resolveRepoScoutScript(currentDirectory) {
|
|
4523
|
+
const moduleDirectory = dirname(fileURLToPath(import.meta.url));
|
|
4524
|
+
const starts = uniquePaths([currentDirectory, moduleDirectory]);
|
|
4525
|
+
for (const start of starts) {
|
|
4526
|
+
for (const candidate of ancestorChain(start)) {
|
|
4527
|
+
const scriptPath = join4(candidate, "apps", "desktop", "bin", "scout.ts");
|
|
4528
|
+
if (existsSync6(scriptPath)) {
|
|
4529
|
+
return scriptPath;
|
|
4530
|
+
}
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4533
|
+
return null;
|
|
4534
|
+
}
|
|
4535
|
+
function resolveContextRoot(currentDirectory, env) {
|
|
4536
|
+
const configured = env.OPENSCOUT_SETUP_CWD?.trim();
|
|
4537
|
+
return resolve(configured || currentDirectory);
|
|
4538
|
+
}
|
|
4539
|
+
function resolveScoutMcpCommand(options) {
|
|
4540
|
+
const env = options.env ?? process.env;
|
|
4541
|
+
const contextRoot = resolveContextRoot(options.currentDirectory, env);
|
|
4542
|
+
const scoutExecutable = resolveScoutExecutable(env);
|
|
4543
|
+
if (scoutExecutable) {
|
|
4544
|
+
return {
|
|
4545
|
+
command: scoutExecutable,
|
|
4546
|
+
args: ["mcp", "--context-root", contextRoot],
|
|
4547
|
+
cwd: contextRoot
|
|
4548
|
+
};
|
|
4549
|
+
}
|
|
4550
|
+
const scoutScript = resolveRepoScoutScript(options.currentDirectory);
|
|
4551
|
+
const bunExecutable = resolveBunExecutable(env);
|
|
4552
|
+
if (scoutScript && bunExecutable) {
|
|
4553
|
+
return {
|
|
4554
|
+
command: bunExecutable,
|
|
4555
|
+
args: [scoutScript, "mcp", "--context-root", contextRoot],
|
|
4556
|
+
cwd: contextRoot
|
|
4557
|
+
};
|
|
4558
|
+
}
|
|
4559
|
+
return null;
|
|
4560
|
+
}
|
|
4561
|
+
function buildScoutMcpCodexLaunchArgs(options) {
|
|
4562
|
+
const resolved = resolveScoutMcpCommand(options);
|
|
4563
|
+
if (!resolved) {
|
|
4564
|
+
return [];
|
|
4565
|
+
}
|
|
4566
|
+
return [
|
|
4567
|
+
"-c",
|
|
4568
|
+
`mcp_servers.scout.command=${JSON.stringify(resolved.command)}`,
|
|
4569
|
+
"-c",
|
|
4570
|
+
`mcp_servers.scout.args=${JSON.stringify(resolved.args)}`,
|
|
4571
|
+
"-c",
|
|
4572
|
+
`mcp_servers.scout.cwd=${JSON.stringify(resolved.cwd)}`
|
|
4573
|
+
];
|
|
4574
|
+
}
|
|
4575
|
+
|
|
4576
|
+
// ../agent-sessions/src/adapters/codex.ts
|
|
4442
4577
|
function parseJsonLine(line) {
|
|
4443
4578
|
try {
|
|
4444
4579
|
return JSON.parse(line);
|
|
@@ -4559,12 +4694,12 @@ function renderActionOutput(item) {
|
|
|
4559
4694
|
function isMissingCodexRolloutError(error) {
|
|
4560
4695
|
return errorMessage(error).toLowerCase().includes("no rollout found for thread id");
|
|
4561
4696
|
}
|
|
4562
|
-
async function
|
|
4697
|
+
async function isExecutable2(filePath) {
|
|
4563
4698
|
if (!filePath) {
|
|
4564
4699
|
return false;
|
|
4565
4700
|
}
|
|
4566
4701
|
try {
|
|
4567
|
-
await access(filePath,
|
|
4702
|
+
await access(filePath, constants2.X_OK);
|
|
4568
4703
|
return true;
|
|
4569
4704
|
} catch {
|
|
4570
4705
|
return false;
|
|
@@ -4576,11 +4711,11 @@ async function resolveCodexExecutable() {
|
|
|
4576
4711
|
process.env.CODEX_BIN
|
|
4577
4712
|
].filter(Boolean);
|
|
4578
4713
|
for (const candidate of explicitCandidates) {
|
|
4579
|
-
if (await
|
|
4714
|
+
if (await isExecutable2(candidate)) {
|
|
4580
4715
|
return candidate;
|
|
4581
4716
|
}
|
|
4582
4717
|
}
|
|
4583
|
-
const pathEntries = (process.env.PATH ?? "").split(
|
|
4718
|
+
const pathEntries = (process.env.PATH ?? "").split(delimiter2).filter(Boolean);
|
|
4584
4719
|
const commonDirectories = [
|
|
4585
4720
|
`${process.env.HOME ?? ""}/.local/bin`,
|
|
4586
4721
|
`${process.env.HOME ?? ""}/.bun/bin`,
|
|
@@ -4588,8 +4723,8 @@ async function resolveCodexExecutable() {
|
|
|
4588
4723
|
"/usr/local/bin"
|
|
4589
4724
|
].filter(Boolean);
|
|
4590
4725
|
for (const directory of [...pathEntries, ...commonDirectories]) {
|
|
4591
|
-
const candidate =
|
|
4592
|
-
if (await
|
|
4726
|
+
const candidate = join5(directory, "codex");
|
|
4727
|
+
if (await isExecutable2(candidate)) {
|
|
4593
4728
|
return candidate;
|
|
4594
4729
|
}
|
|
4595
4730
|
}
|
|
@@ -4691,7 +4826,7 @@ class CodexAdapter extends BaseAdapter {
|
|
|
4691
4826
|
this.pendingRequests.clear();
|
|
4692
4827
|
if (child && child.exitCode === null && !child.killed) {
|
|
4693
4828
|
child.kill("SIGTERM");
|
|
4694
|
-
await new Promise((
|
|
4829
|
+
await new Promise((resolve2) => setTimeout(resolve2, 250));
|
|
4695
4830
|
if (child.exitCode === null && !child.killed) {
|
|
4696
4831
|
child.kill("SIGKILL");
|
|
4697
4832
|
}
|
|
@@ -4700,7 +4835,7 @@ class CodexAdapter extends BaseAdapter {
|
|
|
4700
4835
|
await this.persistState();
|
|
4701
4836
|
}
|
|
4702
4837
|
get codexOptions() {
|
|
4703
|
-
const runtimeRoot =
|
|
4838
|
+
const runtimeRoot = join5(homedir6(), ".scout/pairing", "codex", this.session.id);
|
|
4704
4839
|
const configuredThreadId = this.config.options?.["threadId"];
|
|
4705
4840
|
const requireExistingThread = this.config.options?.["requireExistingThread"];
|
|
4706
4841
|
const rawLaunchArgs = this.config.options?.["launchArgs"];
|
|
@@ -4710,8 +4845,8 @@ class CodexAdapter extends BaseAdapter {
|
|
|
4710
4845
|
sessionId: this.session.id,
|
|
4711
4846
|
cwd: this.config.cwd ?? process.cwd(),
|
|
4712
4847
|
systemPrompt: this.systemPrompt,
|
|
4713
|
-
runtimeDirectory:
|
|
4714
|
-
logsDirectory:
|
|
4848
|
+
runtimeDirectory: join5(runtimeRoot, "runtime"),
|
|
4849
|
+
logsDirectory: join5(runtimeRoot, "logs"),
|
|
4715
4850
|
launchArgs,
|
|
4716
4851
|
threadId: typeof configuredThreadId === "string" && configuredThreadId.trim().length > 0 ? configuredThreadId.trim() : undefined,
|
|
4717
4852
|
requireExistingThread: requireExistingThread ?? Boolean(configuredThreadId)
|
|
@@ -4722,16 +4857,16 @@ class CodexAdapter extends BaseAdapter {
|
|
|
4722
4857
|
return typeof raw === "string" && raw.trim().length > 0 ? raw : "You are a helpful agent working through Pairing.";
|
|
4723
4858
|
}
|
|
4724
4859
|
get threadIdPath() {
|
|
4725
|
-
return
|
|
4860
|
+
return join5(this.codexOptions.runtimeDirectory, "codex-thread-id.txt");
|
|
4726
4861
|
}
|
|
4727
4862
|
get statePath() {
|
|
4728
|
-
return
|
|
4863
|
+
return join5(this.codexOptions.runtimeDirectory, "state.json");
|
|
4729
4864
|
}
|
|
4730
4865
|
get stdoutLogPath() {
|
|
4731
|
-
return
|
|
4866
|
+
return join5(this.codexOptions.logsDirectory, "stdout.log");
|
|
4732
4867
|
}
|
|
4733
4868
|
get stderrLogPath() {
|
|
4734
|
-
return
|
|
4869
|
+
return join5(this.codexOptions.logsDirectory, "stderr.log");
|
|
4735
4870
|
}
|
|
4736
4871
|
enqueue(task) {
|
|
4737
4872
|
const next = this.serialized.then(task, task);
|
|
@@ -4760,14 +4895,22 @@ class CodexAdapter extends BaseAdapter {
|
|
|
4760
4895
|
const options = this.codexOptions;
|
|
4761
4896
|
await mkdir(options.runtimeDirectory, { recursive: true });
|
|
4762
4897
|
await mkdir(options.logsDirectory, { recursive: true });
|
|
4763
|
-
await writeFile(
|
|
4898
|
+
await writeFile(join5(options.runtimeDirectory, "prompt.txt"), options.systemPrompt);
|
|
4764
4899
|
const codexExecutable = await resolveCodexExecutable();
|
|
4765
|
-
const
|
|
4900
|
+
const childEnv = {
|
|
4901
|
+
...process.env,
|
|
4902
|
+
...this.config.env ?? {}
|
|
4903
|
+
};
|
|
4904
|
+
const child = spawn(codexExecutable, [
|
|
4905
|
+
"app-server",
|
|
4906
|
+
...buildScoutMcpCodexLaunchArgs({
|
|
4907
|
+
currentDirectory: options.cwd,
|
|
4908
|
+
env: childEnv
|
|
4909
|
+
}),
|
|
4910
|
+
...options.launchArgs
|
|
4911
|
+
], {
|
|
4766
4912
|
cwd: options.cwd,
|
|
4767
|
-
env:
|
|
4768
|
-
...process.env,
|
|
4769
|
-
...this.config.env ?? {}
|
|
4770
|
-
},
|
|
4913
|
+
env: childEnv,
|
|
4771
4914
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4772
4915
|
});
|
|
4773
4916
|
this.process = child;
|
|
@@ -5477,9 +5620,9 @@ class CodexAdapter extends BaseAdapter {
|
|
|
5477
5620
|
}
|
|
5478
5621
|
async request(method, params) {
|
|
5479
5622
|
const id = String(this.nextRequestId++);
|
|
5480
|
-
return new Promise((
|
|
5623
|
+
return new Promise((resolve2, reject) => {
|
|
5481
5624
|
this.pendingRequests.set(id, {
|
|
5482
|
-
resolve: (value) =>
|
|
5625
|
+
resolve: (value) => resolve2(value),
|
|
5483
5626
|
reject
|
|
5484
5627
|
});
|
|
5485
5628
|
try {
|
|
@@ -6825,8 +6968,8 @@ class EchoAdapter extends BaseAdapter {
|
|
|
6825
6968
|
blockId: actionId,
|
|
6826
6969
|
approval: { version: 1, description: `Run echo tool with: ${text}`, risk: "low" }
|
|
6827
6970
|
});
|
|
6828
|
-
const decision = await new Promise((
|
|
6829
|
-
this.pendingApprovals.set(this.approvalKey(turnId, actionId), { resolve });
|
|
6971
|
+
const decision = await new Promise((resolve2) => {
|
|
6972
|
+
this.pendingApprovals.set(this.approvalKey(turnId, actionId), { resolve: resolve2 });
|
|
6830
6973
|
});
|
|
6831
6974
|
if (this.interrupted) {
|
|
6832
6975
|
this.emitTurnEnd(sessionId, turnId, "stopped");
|
|
@@ -6901,15 +7044,15 @@ class EchoAdapter extends BaseAdapter {
|
|
|
6901
7044
|
delay() {
|
|
6902
7045
|
if (this.stepDelay <= 0)
|
|
6903
7046
|
return Promise.resolve();
|
|
6904
|
-
return new Promise((
|
|
7047
|
+
return new Promise((resolve2) => setTimeout(resolve2, this.stepDelay));
|
|
6905
7048
|
}
|
|
6906
7049
|
}
|
|
6907
7050
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/log.ts
|
|
6908
7051
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync6 } from "fs";
|
|
6909
|
-
import { join as
|
|
6910
|
-
import { homedir as
|
|
6911
|
-
var LOG_DIR =
|
|
6912
|
-
var LOG_FILE =
|
|
7052
|
+
import { join as join6 } from "path";
|
|
7053
|
+
import { homedir as homedir7 } from "os";
|
|
7054
|
+
var LOG_DIR = join6(homedir7(), ".scout/pairing");
|
|
7055
|
+
var LOG_FILE = join6(LOG_DIR, "bridge.log");
|
|
6913
7056
|
mkdirSync6(LOG_DIR, { recursive: true });
|
|
6914
7057
|
function write2(level, category, message, data) {
|
|
6915
7058
|
const ts = new Date().toISOString().slice(11, 23);
|
|
@@ -6993,17 +7136,17 @@ class Bridge {
|
|
|
6993
7136
|
}
|
|
6994
7137
|
|
|
6995
7138
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/config.ts
|
|
6996
|
-
import { existsSync as
|
|
6997
|
-
import { join as
|
|
6998
|
-
import { homedir as
|
|
7139
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
|
|
7140
|
+
import { join as join7 } from "path";
|
|
7141
|
+
import { homedir as homedir8 } from "os";
|
|
6999
7142
|
var DEFAULTS = {
|
|
7000
7143
|
port: 7888,
|
|
7001
7144
|
secure: true
|
|
7002
7145
|
};
|
|
7003
|
-
var CONFIG_DIR =
|
|
7004
|
-
var CONFIG_FILE =
|
|
7146
|
+
var CONFIG_DIR = join7(homedir8(), ".scout/pairing");
|
|
7147
|
+
var CONFIG_FILE = join7(CONFIG_DIR, "config.json");
|
|
7005
7148
|
function loadConfigFile() {
|
|
7006
|
-
if (!
|
|
7149
|
+
if (!existsSync7(CONFIG_FILE)) {
|
|
7007
7150
|
return {};
|
|
7008
7151
|
}
|
|
7009
7152
|
try {
|
|
@@ -7061,12 +7204,12 @@ function resolveConfig() {
|
|
|
7061
7204
|
|
|
7062
7205
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/fileserver.ts
|
|
7063
7206
|
import { isAbsolute } from "path";
|
|
7064
|
-
import { homedir as
|
|
7065
|
-
var ALLOWED_ROOTS = [
|
|
7207
|
+
import { homedir as homedir9 } from "os";
|
|
7208
|
+
var ALLOWED_ROOTS = [homedir9(), "/tmp"];
|
|
7066
7209
|
function isAllowedPath(filePath) {
|
|
7067
7210
|
if (!isAbsolute(filePath))
|
|
7068
7211
|
return false;
|
|
7069
|
-
const relToHome = filePath.slice(
|
|
7212
|
+
const relToHome = filePath.slice(homedir9().length + 1);
|
|
7070
7213
|
if (relToHome.startsWith(".") && !relToHome.startsWith(".claude") && !relToHome.startsWith(".scout/pairing")) {
|
|
7071
7214
|
return false;
|
|
7072
7215
|
}
|
|
@@ -7127,56 +7270,56 @@ function serveFile(url) {
|
|
|
7127
7270
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/server.ts
|
|
7128
7271
|
import { readdirSync as readdirSync3, readFileSync as readFileSync8, realpathSync, statSync as statSync3 } from "fs";
|
|
7129
7272
|
import { execSync as execSync3 } from "child_process";
|
|
7130
|
-
import { basename as
|
|
7131
|
-
import { homedir as
|
|
7273
|
+
import { basename as basename6, isAbsolute as isAbsolute3, join as join17, relative as relative2 } from "path";
|
|
7274
|
+
import { homedir as homedir15 } from "os";
|
|
7132
7275
|
|
|
7133
7276
|
// ../../apps/desktop/src/core/mobile/service.ts
|
|
7134
|
-
import { basename as
|
|
7277
|
+
import { basename as basename5, resolve as resolve6 } from "path";
|
|
7135
7278
|
|
|
7136
7279
|
// ../runtime/src/harness-catalog.ts
|
|
7137
7280
|
import { execFileSync } from "child_process";
|
|
7138
|
-
import { existsSync as
|
|
7281
|
+
import { existsSync as existsSync9, statSync as statSync2 } from "fs";
|
|
7139
7282
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
7140
|
-
import { dirname, join as
|
|
7283
|
+
import { dirname as dirname2, join as join9 } from "path";
|
|
7141
7284
|
|
|
7142
7285
|
// ../runtime/src/support-paths.ts
|
|
7143
|
-
import { existsSync as
|
|
7144
|
-
import { homedir as
|
|
7145
|
-
import { join as
|
|
7286
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync7, rmSync, writeFileSync as writeFileSync4 } from "fs";
|
|
7287
|
+
import { homedir as homedir10 } from "os";
|
|
7288
|
+
import { join as join8 } from "path";
|
|
7146
7289
|
var OPENSCOUT_RPC_CUTOVER_MARKER = "rpc-runtime-cutover-v1";
|
|
7147
7290
|
function resolveOpenScoutSupportPaths() {
|
|
7148
|
-
const home =
|
|
7149
|
-
const supportDirectory = process.env.OPENSCOUT_SUPPORT_DIRECTORY ??
|
|
7150
|
-
const logsDirectory =
|
|
7151
|
-
const runtimeDirectory =
|
|
7152
|
-
const catalogDirectory =
|
|
7291
|
+
const home = homedir10();
|
|
7292
|
+
const supportDirectory = process.env.OPENSCOUT_SUPPORT_DIRECTORY ?? join8(home, "Library", "Application Support", "OpenScout");
|
|
7293
|
+
const logsDirectory = join8(supportDirectory, "logs");
|
|
7294
|
+
const runtimeDirectory = join8(supportDirectory, "runtime");
|
|
7295
|
+
const catalogDirectory = join8(supportDirectory, "catalog");
|
|
7153
7296
|
return {
|
|
7154
7297
|
supportDirectory,
|
|
7155
7298
|
logsDirectory,
|
|
7156
|
-
appLogsDirectory:
|
|
7157
|
-
brokerLogsDirectory:
|
|
7299
|
+
appLogsDirectory: join8(logsDirectory, "app"),
|
|
7300
|
+
brokerLogsDirectory: join8(logsDirectory, "broker"),
|
|
7158
7301
|
runtimeDirectory,
|
|
7159
7302
|
catalogDirectory,
|
|
7160
|
-
relayAgentsDirectory:
|
|
7161
|
-
settingsPath:
|
|
7162
|
-
harnessCatalogPath:
|
|
7163
|
-
relayAgentsRegistryPath:
|
|
7164
|
-
relayHubDirectory: process.env.OPENSCOUT_RELAY_HUB ??
|
|
7165
|
-
controlHome: process.env.OPENSCOUT_CONTROL_HOME ??
|
|
7166
|
-
desktopStatusPath:
|
|
7167
|
-
workspaceStatePath:
|
|
7168
|
-
cutoverMarkerPath:
|
|
7303
|
+
relayAgentsDirectory: join8(runtimeDirectory, "agents"),
|
|
7304
|
+
settingsPath: join8(supportDirectory, "settings.json"),
|
|
7305
|
+
harnessCatalogPath: join8(catalogDirectory, "harness-catalog.json"),
|
|
7306
|
+
relayAgentsRegistryPath: join8(supportDirectory, "relay-agents.json"),
|
|
7307
|
+
relayHubDirectory: process.env.OPENSCOUT_RELAY_HUB ?? join8(home, ".openscout", "relay"),
|
|
7308
|
+
controlHome: process.env.OPENSCOUT_CONTROL_HOME ?? join8(home, ".openscout", "control-plane"),
|
|
7309
|
+
desktopStatusPath: join8(supportDirectory, "agent-status.json"),
|
|
7310
|
+
workspaceStatePath: join8(supportDirectory, "workspace-state.json"),
|
|
7311
|
+
cutoverMarkerPath: join8(supportDirectory, OPENSCOUT_RPC_CUTOVER_MARKER)
|
|
7169
7312
|
};
|
|
7170
7313
|
}
|
|
7171
7314
|
function relayAgentRuntimeDirectory(agentId) {
|
|
7172
|
-
return
|
|
7315
|
+
return join8(resolveOpenScoutSupportPaths().relayAgentsDirectory, agentId);
|
|
7173
7316
|
}
|
|
7174
7317
|
function relayAgentLogsDirectory(agentId) {
|
|
7175
|
-
return
|
|
7318
|
+
return join8(relayAgentRuntimeDirectory(agentId), "logs");
|
|
7176
7319
|
}
|
|
7177
7320
|
function ensureOpenScoutCleanSlateSync() {
|
|
7178
7321
|
const paths = resolveOpenScoutSupportPaths();
|
|
7179
|
-
if (
|
|
7322
|
+
if (existsSync8(paths.cutoverMarkerPath)) {
|
|
7180
7323
|
return;
|
|
7181
7324
|
}
|
|
7182
7325
|
rmSync(paths.supportDirectory, { recursive: true, force: true });
|
|
@@ -7267,7 +7410,7 @@ function expandHomePath(value) {
|
|
|
7267
7410
|
if (value === "~")
|
|
7268
7411
|
return process.env.HOME || value;
|
|
7269
7412
|
if (value.startsWith("~/"))
|
|
7270
|
-
return
|
|
7413
|
+
return join9(process.env.HOME || "~", value.slice(2));
|
|
7271
7414
|
return value;
|
|
7272
7415
|
}
|
|
7273
7416
|
function defaultWhichBinary(binary, platform) {
|
|
@@ -7301,7 +7444,7 @@ function defaultRunCommand(command, platform) {
|
|
|
7301
7444
|
}
|
|
7302
7445
|
function defaultRequirementExists(requirement) {
|
|
7303
7446
|
const expanded = expandHomePath(requirement.path);
|
|
7304
|
-
if (!
|
|
7447
|
+
if (!existsSync9(expanded))
|
|
7305
7448
|
return false;
|
|
7306
7449
|
if (requirement.fileType === "any" || !requirement.fileType)
|
|
7307
7450
|
return true;
|
|
@@ -7496,7 +7639,7 @@ async function readHarnessCatalogOverrides(overridePath = resolveOpenScoutSuppor
|
|
|
7496
7639
|
}
|
|
7497
7640
|
}
|
|
7498
7641
|
async function writeHarnessCatalogOverrides(overrides, overridePath = resolveOpenScoutSupportPaths().harnessCatalogPath) {
|
|
7499
|
-
await mkdir2(
|
|
7642
|
+
await mkdir2(dirname2(overridePath), { recursive: true });
|
|
7500
7643
|
const payload = {
|
|
7501
7644
|
version: HARNESS_CATALOG_VERSION,
|
|
7502
7645
|
entries: overrides,
|
|
@@ -7506,7 +7649,7 @@ async function writeHarnessCatalogOverrides(overrides, overridePath = resolveOpe
|
|
|
7506
7649
|
`, "utf8");
|
|
7507
7650
|
}
|
|
7508
7651
|
async function ensureHarnessCatalogOverrideFile(overridePath = resolveOpenScoutSupportPaths().harnessCatalogPath) {
|
|
7509
|
-
if (
|
|
7652
|
+
if (existsSync9(overridePath))
|
|
7510
7653
|
return;
|
|
7511
7654
|
await writeHarnessCatalogOverrides({}, overridePath);
|
|
7512
7655
|
}
|
|
@@ -7529,11 +7672,11 @@ async function loadHarnessCatalogSnapshot(options = {}) {
|
|
|
7529
7672
|
|
|
7530
7673
|
// ../runtime/src/setup.ts
|
|
7531
7674
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
7532
|
-
import { existsSync as
|
|
7675
|
+
import { existsSync as existsSync10, readFileSync as readFileSync5 } from "fs";
|
|
7533
7676
|
import { access as access2, mkdir as mkdir3, readdir as readdir2, readFile as readFile4, realpath, rm as rm2, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
7534
|
-
import { homedir as
|
|
7535
|
-
import { basename, dirname as
|
|
7536
|
-
import { fileURLToPath as
|
|
7677
|
+
import { homedir as homedir12, hostname, userInfo } from "os";
|
|
7678
|
+
import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute2, join as join11, relative, resolve as resolve3 } from "path";
|
|
7679
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7537
7680
|
|
|
7538
7681
|
// ../../node_modules/.bun/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
|
|
7539
7682
|
/*!
|
|
@@ -8766,9 +8909,9 @@ function buildScoutReturnAddress(input) {
|
|
|
8766
8909
|
}
|
|
8767
8910
|
// ../runtime/src/user-project-hints.ts
|
|
8768
8911
|
import { readdir, readFile as readFile3, stat } from "fs/promises";
|
|
8769
|
-
import { homedir as
|
|
8770
|
-
import { dirname as
|
|
8771
|
-
import { fileURLToPath } from "url";
|
|
8912
|
+
import { homedir as homedir11 } from "os";
|
|
8913
|
+
import { dirname as dirname3, join as join10, resolve as resolve2 } from "path";
|
|
8914
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8772
8915
|
var PROJECT_HINT_MARKERS = [
|
|
8773
8916
|
".git",
|
|
8774
8917
|
".openscout/project.json",
|
|
@@ -8793,18 +8936,18 @@ function decodeClaudeProjectsSlug2(name) {
|
|
|
8793
8936
|
return `/${tail.replace(/-/g, "/")}`;
|
|
8794
8937
|
}
|
|
8795
8938
|
function encodeClaudeProjectsSlug(absolutePath) {
|
|
8796
|
-
const normalized =
|
|
8939
|
+
const normalized = resolve2(absolutePath);
|
|
8797
8940
|
return `-${normalized.replace(/^\//, "").replace(/\//g, "-")}`;
|
|
8798
8941
|
}
|
|
8799
8942
|
async function resolveExistingDirectoryHint(pathLike) {
|
|
8800
|
-
const absolutePath =
|
|
8943
|
+
const absolutePath = resolve2(pathLike);
|
|
8801
8944
|
try {
|
|
8802
8945
|
const info = await stat(absolutePath);
|
|
8803
8946
|
if (info.isDirectory()) {
|
|
8804
8947
|
return absolutePath;
|
|
8805
8948
|
}
|
|
8806
8949
|
if (info.isFile()) {
|
|
8807
|
-
return
|
|
8950
|
+
return dirname3(absolutePath);
|
|
8808
8951
|
}
|
|
8809
8952
|
} catch {
|
|
8810
8953
|
return null;
|
|
@@ -8820,18 +8963,18 @@ async function pathExists(pathLike) {
|
|
|
8820
8963
|
}
|
|
8821
8964
|
}
|
|
8822
8965
|
async function findLikelyProjectRoot(absolutePath) {
|
|
8823
|
-
let current =
|
|
8966
|
+
let current = resolve2(absolutePath);
|
|
8824
8967
|
let lastCandidate = null;
|
|
8825
8968
|
while (true) {
|
|
8826
8969
|
for (const marker of PROJECT_HINT_MARKERS) {
|
|
8827
|
-
if (await pathExists(
|
|
8970
|
+
if (await pathExists(join10(current, marker))) {
|
|
8828
8971
|
lastCandidate = current;
|
|
8829
8972
|
if (marker === ".git" || marker === ".openscout/project.json") {
|
|
8830
8973
|
return current;
|
|
8831
8974
|
}
|
|
8832
8975
|
}
|
|
8833
8976
|
}
|
|
8834
|
-
const parent =
|
|
8977
|
+
const parent = dirname3(current);
|
|
8835
8978
|
if (parent === current) {
|
|
8836
8979
|
return lastCandidate ?? absolutePath;
|
|
8837
8980
|
}
|
|
@@ -8847,16 +8990,16 @@ async function appendPathHint(pathLike, roots) {
|
|
|
8847
8990
|
}
|
|
8848
8991
|
function cursorWorkspaceStoragePath(home) {
|
|
8849
8992
|
if (process.platform === "darwin") {
|
|
8850
|
-
return
|
|
8993
|
+
return join10(home, "Library", "Application Support", "Cursor", "User", "workspaceStorage");
|
|
8851
8994
|
}
|
|
8852
8995
|
if (process.platform === "win32") {
|
|
8853
8996
|
const appData = process.env.APPDATA;
|
|
8854
8997
|
if (appData) {
|
|
8855
|
-
return
|
|
8998
|
+
return join10(appData, "Cursor", "User", "workspaceStorage");
|
|
8856
8999
|
}
|
|
8857
|
-
return
|
|
9000
|
+
return join10(home, "AppData", "Roaming", "Cursor", "User", "workspaceStorage");
|
|
8858
9001
|
}
|
|
8859
|
-
return
|
|
9002
|
+
return join10(home, ".config", "Cursor", "User", "workspaceStorage");
|
|
8860
9003
|
}
|
|
8861
9004
|
function collectPathLikeStrings(value, out, depth) {
|
|
8862
9005
|
if (depth > 4 || value === null || value === undefined) {
|
|
@@ -8885,7 +9028,7 @@ function collectPathLikeStrings(value, out, depth) {
|
|
|
8885
9028
|
}
|
|
8886
9029
|
}
|
|
8887
9030
|
async function appendCodexHistoryPaths(home, roots) {
|
|
8888
|
-
const candidates = [
|
|
9031
|
+
const candidates = [join10(home, ".codex", "history.jsonl"), join10(home, ".openai-codex", "history.jsonl")];
|
|
8889
9032
|
const maxLines = 2500;
|
|
8890
9033
|
const maxBytes = 4 * 1024 * 1024;
|
|
8891
9034
|
for (const filePath of candidates) {
|
|
@@ -8936,7 +9079,7 @@ async function appendCursorWorkspacePaths(home, roots) {
|
|
|
8936
9079
|
return;
|
|
8937
9080
|
}
|
|
8938
9081
|
for (const id of ids) {
|
|
8939
|
-
const workspaceJsonPath =
|
|
9082
|
+
const workspaceJsonPath = join10(base, id, "workspace.json");
|
|
8940
9083
|
let raw;
|
|
8941
9084
|
try {
|
|
8942
9085
|
raw = await readFile3(workspaceJsonPath, "utf8");
|
|
@@ -8951,13 +9094,13 @@ async function appendCursorWorkspacePaths(home, roots) {
|
|
|
8951
9094
|
}
|
|
8952
9095
|
if (typeof doc.folder === "string" && doc.folder.startsWith("file://")) {
|
|
8953
9096
|
try {
|
|
8954
|
-
const folderPath =
|
|
9097
|
+
const folderPath = fileURLToPath2(doc.folder);
|
|
8955
9098
|
await appendPathHint(folderPath, roots);
|
|
8956
9099
|
} catch {}
|
|
8957
9100
|
}
|
|
8958
9101
|
if (typeof doc.workspace === "string" && doc.workspace.startsWith("file://")) {
|
|
8959
9102
|
try {
|
|
8960
|
-
const wsFile =
|
|
9103
|
+
const wsFile = fileURLToPath2(doc.workspace);
|
|
8961
9104
|
if (!wsFile.endsWith(".code-workspace")) {
|
|
8962
9105
|
continue;
|
|
8963
9106
|
}
|
|
@@ -8972,12 +9115,12 @@ async function appendCursorWorkspacePaths(home, roots) {
|
|
|
8972
9115
|
}
|
|
8973
9116
|
const wsRaw = await readFile3(wsFile, "utf8");
|
|
8974
9117
|
const wsDoc = JSON.parse(wsRaw);
|
|
8975
|
-
const wsDir =
|
|
9118
|
+
const wsDir = dirname3(wsFile);
|
|
8976
9119
|
for (const f of wsDoc.folders ?? []) {
|
|
8977
9120
|
if (typeof f.path !== "string" || !f.path) {
|
|
8978
9121
|
continue;
|
|
8979
9122
|
}
|
|
8980
|
-
const resolvedPath =
|
|
9123
|
+
const resolvedPath = resolve2(wsDir, f.path);
|
|
8981
9124
|
await appendPathHint(resolvedPath, roots);
|
|
8982
9125
|
}
|
|
8983
9126
|
} catch {}
|
|
@@ -8985,7 +9128,7 @@ async function appendCursorWorkspacePaths(home, roots) {
|
|
|
8985
9128
|
}
|
|
8986
9129
|
}
|
|
8987
9130
|
async function appendClaudeProjectSlugs(home, roots) {
|
|
8988
|
-
const projectsDir =
|
|
9131
|
+
const projectsDir = join10(home, ".claude", "projects");
|
|
8989
9132
|
let names = [];
|
|
8990
9133
|
try {
|
|
8991
9134
|
names = await readdir(projectsDir, { withFileTypes: false });
|
|
@@ -9001,7 +9144,7 @@ async function appendClaudeProjectSlugs(home, roots) {
|
|
|
9001
9144
|
}
|
|
9002
9145
|
}
|
|
9003
9146
|
async function appendClaudeSessionPaths(home, roots) {
|
|
9004
|
-
const projectsDir =
|
|
9147
|
+
const projectsDir = join10(home, ".claude", "projects");
|
|
9005
9148
|
const maxProjectDirectories = 200;
|
|
9006
9149
|
const maxSessionFiles = 400;
|
|
9007
9150
|
const maxLinesPerFile = 400;
|
|
@@ -9016,7 +9159,7 @@ async function appendClaudeSessionPaths(home, roots) {
|
|
|
9016
9159
|
for (const projectName of projectNames) {
|
|
9017
9160
|
let entries = [];
|
|
9018
9161
|
try {
|
|
9019
|
-
entries = await readdir(
|
|
9162
|
+
entries = await readdir(join10(projectsDir, projectName), { withFileTypes: false });
|
|
9020
9163
|
} catch {
|
|
9021
9164
|
continue;
|
|
9022
9165
|
}
|
|
@@ -9027,7 +9170,7 @@ async function appendClaudeSessionPaths(home, roots) {
|
|
|
9027
9170
|
if (!entry.endsWith(".jsonl")) {
|
|
9028
9171
|
continue;
|
|
9029
9172
|
}
|
|
9030
|
-
const sessionPath =
|
|
9173
|
+
const sessionPath = join10(projectsDir, projectName, entry);
|
|
9031
9174
|
let info;
|
|
9032
9175
|
try {
|
|
9033
9176
|
info = await stat(sessionPath);
|
|
@@ -9069,7 +9212,7 @@ async function appendClaudeSessionPaths(home, roots) {
|
|
|
9069
9212
|
}
|
|
9070
9213
|
}
|
|
9071
9214
|
async function collectUserLevelProjectRootHints(options = {}) {
|
|
9072
|
-
const home = options.home ??
|
|
9215
|
+
const home = options.home ?? homedir11();
|
|
9073
9216
|
const roots = new Set;
|
|
9074
9217
|
try {
|
|
9075
9218
|
await appendClaudeProjectSlugs(home, roots);
|
|
@@ -9237,7 +9380,7 @@ async function matchNestedMarkers(projectRoot, nestedMarkers) {
|
|
|
9237
9380
|
if (nestedMarkers.length === 0) {
|
|
9238
9381
|
return [];
|
|
9239
9382
|
}
|
|
9240
|
-
const hits = await Promise.all(nestedMarkers.map(async (marker) => await pathExists2(
|
|
9383
|
+
const hits = await Promise.all(nestedMarkers.map(async (marker) => await pathExists2(join11(projectRoot, marker)) ? marker : null));
|
|
9241
9384
|
return hits.filter((marker) => Boolean(marker));
|
|
9242
9385
|
}
|
|
9243
9386
|
function nowSeconds() {
|
|
@@ -9245,21 +9388,21 @@ function nowSeconds() {
|
|
|
9245
9388
|
}
|
|
9246
9389
|
function expandHomePath2(value) {
|
|
9247
9390
|
if (value === "~") {
|
|
9248
|
-
return
|
|
9391
|
+
return homedir12();
|
|
9249
9392
|
}
|
|
9250
9393
|
if (value.startsWith("~/")) {
|
|
9251
|
-
return
|
|
9394
|
+
return join11(homedir12(), value.slice(2));
|
|
9252
9395
|
}
|
|
9253
9396
|
return value;
|
|
9254
9397
|
}
|
|
9255
9398
|
function normalizePath(value) {
|
|
9256
|
-
return
|
|
9399
|
+
return resolve3(expandHomePath2(value.trim() || "."));
|
|
9257
9400
|
}
|
|
9258
9401
|
function normalizeProjectRelativePath(projectRoot, value) {
|
|
9259
9402
|
const expanded = expandHomePath2(value.trim() || ".");
|
|
9260
|
-
return isAbsolute2(expanded) ?
|
|
9403
|
+
return isAbsolute2(expanded) ? resolve3(expanded) : resolve3(projectRoot, expanded);
|
|
9261
9404
|
}
|
|
9262
|
-
function
|
|
9405
|
+
function uniquePaths2(values) {
|
|
9263
9406
|
return Array.from(new Set(Array.from(values).map((value) => normalizePath(value))));
|
|
9264
9407
|
}
|
|
9265
9408
|
function normalizeAgentId(value) {
|
|
@@ -9326,16 +9469,16 @@ function resolveTelegramConfigSeedValue(key, currentDirectory) {
|
|
|
9326
9469
|
return envValue;
|
|
9327
9470
|
}
|
|
9328
9471
|
if (currentDirectory) {
|
|
9329
|
-
const currentDirValue = readEnvFileValue(
|
|
9472
|
+
const currentDirValue = readEnvFileValue(join11(currentDirectory, ".env.local"), key).trim();
|
|
9330
9473
|
if (currentDirValue) {
|
|
9331
9474
|
return currentDirValue;
|
|
9332
9475
|
}
|
|
9333
9476
|
}
|
|
9334
|
-
const home =
|
|
9477
|
+
const home = homedir12();
|
|
9335
9478
|
if (!home) {
|
|
9336
9479
|
return "";
|
|
9337
9480
|
}
|
|
9338
|
-
return readEnvFileValue(
|
|
9481
|
+
return readEnvFileValue(join11(home, ".env.local"), key).trim();
|
|
9339
9482
|
}
|
|
9340
9483
|
function normalizeTelegramBridgeMode(value) {
|
|
9341
9484
|
const normalized = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
@@ -9612,13 +9755,13 @@ function defaultSettings() {
|
|
|
9612
9755
|
};
|
|
9613
9756
|
}
|
|
9614
9757
|
function projectConfigPath(projectRoot) {
|
|
9615
|
-
return
|
|
9758
|
+
return join11(projectRoot, ".openscout", "project.json");
|
|
9616
9759
|
}
|
|
9617
9760
|
function projectGitignorePath(projectRoot) {
|
|
9618
|
-
return
|
|
9761
|
+
return join11(projectRoot, ".gitignore");
|
|
9619
9762
|
}
|
|
9620
9763
|
function legacyLocalRelayLinkPath(projectRoot) {
|
|
9621
|
-
return
|
|
9764
|
+
return join11(projectRoot, ".openscout", "relay.json");
|
|
9622
9765
|
}
|
|
9623
9766
|
async function pathExists2(filePath) {
|
|
9624
9767
|
try {
|
|
@@ -9644,15 +9787,15 @@ async function readJsonFile(filePath) {
|
|
|
9644
9787
|
}
|
|
9645
9788
|
}
|
|
9646
9789
|
async function writeJsonFile(filePath, value) {
|
|
9647
|
-
await mkdir3(
|
|
9790
|
+
await mkdir3(dirname4(filePath), { recursive: true });
|
|
9648
9791
|
await writeFile3(filePath, JSON.stringify(value, null, 2) + `
|
|
9649
9792
|
`, "utf8");
|
|
9650
9793
|
}
|
|
9651
9794
|
function codexEnvironmentPath(projectRoot) {
|
|
9652
|
-
return
|
|
9795
|
+
return join11(projectRoot, ".codex", "environments", "environment.toml");
|
|
9653
9796
|
}
|
|
9654
9797
|
function currentHomeDirectory() {
|
|
9655
|
-
return process.env.HOME?.trim() ||
|
|
9798
|
+
return process.env.HOME?.trim() || homedir12();
|
|
9656
9799
|
}
|
|
9657
9800
|
function normalizeProjectScriptSet(value) {
|
|
9658
9801
|
if (typeof value !== "object" || !value) {
|
|
@@ -9808,11 +9951,11 @@ async function readCodexEnvironmentImport(projectRoot) {
|
|
|
9808
9951
|
}
|
|
9809
9952
|
async function readClaudeProjectImport(projectRoot) {
|
|
9810
9953
|
const slug = encodeClaudeProjectsSlug(projectRoot);
|
|
9811
|
-
const sourcePath =
|
|
9954
|
+
const sourcePath = join11(currentHomeDirectory(), ".claude", "projects", slug);
|
|
9812
9955
|
if (!await isDirectory(sourcePath)) {
|
|
9813
9956
|
return null;
|
|
9814
9957
|
}
|
|
9815
|
-
const memoryPath = await pathExists2(
|
|
9958
|
+
const memoryPath = await pathExists2(join11(sourcePath, "memory", "MEMORY.md")) ? join11(sourcePath, "memory", "MEMORY.md") : undefined;
|
|
9816
9959
|
let entries = [];
|
|
9817
9960
|
try {
|
|
9818
9961
|
entries = await readdir2(sourcePath, { withFileTypes: false });
|
|
@@ -9827,7 +9970,7 @@ async function readClaudeProjectImport(projectRoot) {
|
|
|
9827
9970
|
continue;
|
|
9828
9971
|
}
|
|
9829
9972
|
sessionCount += 1;
|
|
9830
|
-
const sessionPath =
|
|
9973
|
+
const sessionPath = join11(sourcePath, entry);
|
|
9831
9974
|
let body;
|
|
9832
9975
|
try {
|
|
9833
9976
|
body = await readFile4(sessionPath, "utf8");
|
|
@@ -9889,7 +10032,7 @@ function applyImportedEnvironmentSeeds(config, codexImport, projectRoot) {
|
|
|
9889
10032
|
...(config.environment?.actions?.length ?? 0) === 0 && importedEnvironment.actions ? { actions: importedEnvironment.actions } : {}
|
|
9890
10033
|
};
|
|
9891
10034
|
}
|
|
9892
|
-
const defaultProjectName = titleCase(
|
|
10035
|
+
const defaultProjectName = titleCase(basename2(projectRoot));
|
|
9893
10036
|
if (codexImport?.name?.trim() && (!config.project.name?.trim() || config.project.name === defaultProjectName)) {
|
|
9894
10037
|
next.project = {
|
|
9895
10038
|
...config.project,
|
|
@@ -9942,11 +10085,11 @@ async function ensureProjectConfigIgnored(projectRoot) {
|
|
|
9942
10085
|
}
|
|
9943
10086
|
async function readLegacyRelayConfig() {
|
|
9944
10087
|
const relayHub = resolveOpenScoutSupportPaths().relayHubDirectory;
|
|
9945
|
-
return readJsonFile(
|
|
10088
|
+
return readJsonFile(join11(relayHub, "config.json"));
|
|
9946
10089
|
}
|
|
9947
10090
|
async function readLegacyAgentRegistry() {
|
|
9948
10091
|
const relayHub = resolveOpenScoutSupportPaths().relayHubDirectory;
|
|
9949
|
-
return await readJsonFile(
|
|
10092
|
+
return await readJsonFile(join11(relayHub, "agents.json")) ?? {};
|
|
9950
10093
|
}
|
|
9951
10094
|
async function detectHarnessMarkers(projectRoot) {
|
|
9952
10095
|
const detected = {
|
|
@@ -9955,7 +10098,7 @@ async function detectHarnessMarkers(projectRoot) {
|
|
|
9955
10098
|
};
|
|
9956
10099
|
for (const harness of MANAGED_AGENT_HARNESSES) {
|
|
9957
10100
|
for (const marker of PROJECT_HARNESS_MARKERS[harness]) {
|
|
9958
|
-
if (await pathExists2(
|
|
10101
|
+
if (await pathExists2(join11(projectRoot, marker))) {
|
|
9959
10102
|
detected[harness].push(marker);
|
|
9960
10103
|
}
|
|
9961
10104
|
}
|
|
@@ -9992,8 +10135,8 @@ async function normalizeSettingsRecord(value, options = {}) {
|
|
|
9992
10135
|
legacyAgents: options.legacyAgents ?? {}
|
|
9993
10136
|
});
|
|
9994
10137
|
const rawWorkspaceRoots = Array.isArray(discovery.workspaceRoots) ? discovery.workspaceRoots.map((entry) => String(entry)) : [];
|
|
9995
|
-
const workspaceRoots =
|
|
9996
|
-
const hiddenProjectRoots =
|
|
10138
|
+
const workspaceRoots = uniquePaths2(rawWorkspaceRoots.length > 0 ? rawWorkspaceRoots : seededWorkspaceRoots);
|
|
10139
|
+
const hiddenProjectRoots = uniquePaths2(Array.isArray(discovery.hiddenProjectRoots) ? discovery.hiddenProjectRoots.map((entry) => String(entry)) : []);
|
|
9997
10140
|
const contextRoot = normalizeOptionalString(discovery.contextRoot) ? normalizePath(String(discovery.contextRoot)) : null;
|
|
9998
10141
|
const seededTelegramBotToken = resolveTelegramConfigSeedValue("TELEGRAM_BOT_TOKEN", options.currentDirectory);
|
|
9999
10142
|
const seededTelegramSecretToken = resolveTelegramConfigSeedValue("TELEGRAM_WEBHOOK_SECRET_TOKEN", options.currentDirectory);
|
|
@@ -10057,7 +10200,7 @@ async function seedWorkspaceRoots(options) {
|
|
|
10057
10200
|
const roots = new Set;
|
|
10058
10201
|
const currentProjectRoot = options.currentDirectory ? await findNearestProjectRoot(options.currentDirectory) : null;
|
|
10059
10202
|
if (currentProjectRoot) {
|
|
10060
|
-
roots.add(
|
|
10203
|
+
roots.add(dirname4(currentProjectRoot));
|
|
10061
10204
|
}
|
|
10062
10205
|
const legacyRoot = options.legacyRelayConfig?.projectRoot?.trim();
|
|
10063
10206
|
if (legacyRoot) {
|
|
@@ -10065,11 +10208,11 @@ async function seedWorkspaceRoots(options) {
|
|
|
10065
10208
|
}
|
|
10066
10209
|
for (const record of Object.values(options.legacyAgents ?? {})) {
|
|
10067
10210
|
if (record.cwd?.trim()) {
|
|
10068
|
-
roots.add(
|
|
10211
|
+
roots.add(dirname4(normalizePath(record.cwd)));
|
|
10069
10212
|
}
|
|
10070
10213
|
}
|
|
10071
10214
|
if (roots.size === 0) {
|
|
10072
|
-
roots.add(
|
|
10215
|
+
roots.add(join11(homedir12(), "dev"));
|
|
10073
10216
|
}
|
|
10074
10217
|
return Array.from(roots);
|
|
10075
10218
|
}
|
|
@@ -10086,11 +10229,11 @@ async function readOpenScoutSettings(options = {}) {
|
|
|
10086
10229
|
});
|
|
10087
10230
|
}
|
|
10088
10231
|
var SCOUT_SKILL_FILE_NAME = "SKILL.md";
|
|
10089
|
-
var SETUP_MODULE_DIRECTORY =
|
|
10090
|
-
var SCOUT_SKILL_REPO_ROOT =
|
|
10232
|
+
var SETUP_MODULE_DIRECTORY = dirname4(fileURLToPath3(import.meta.url));
|
|
10233
|
+
var SCOUT_SKILL_REPO_ROOT = resolve3(SETUP_MODULE_DIRECTORY, "..", "..", "..");
|
|
10091
10234
|
var SCOUT_SKILL_INSTALL_PATHS = {
|
|
10092
|
-
claude:
|
|
10093
|
-
codex:
|
|
10235
|
+
claude: join11(homedir12(), ".claude", "skills", "scout", SCOUT_SKILL_FILE_NAME),
|
|
10236
|
+
codex: join11(homedir12(), ".agents", "skills", "scout", SCOUT_SKILL_FILE_NAME)
|
|
10094
10237
|
};
|
|
10095
10238
|
async function readRelayAgentOverrides() {
|
|
10096
10239
|
const supportPaths = resolveOpenScoutSupportPaths();
|
|
@@ -10173,13 +10316,13 @@ async function findNearestProjectRoot(startDirectory) {
|
|
|
10173
10316
|
let current = normalizePath(startDirectory);
|
|
10174
10317
|
let lastCandidate = null;
|
|
10175
10318
|
while (true) {
|
|
10176
|
-
if (await pathExists2(
|
|
10319
|
+
if (await pathExists2(join11(current, ".git"))) {
|
|
10177
10320
|
return current;
|
|
10178
10321
|
}
|
|
10179
|
-
if (await pathExists2(projectConfigPath(current)) || await pathExists2(
|
|
10322
|
+
if (await pathExists2(projectConfigPath(current)) || await pathExists2(join11(current, "package.json")) || await pathExists2(join11(current, "AGENTS.md")) || await pathExists2(join11(current, "CLAUDE.md"))) {
|
|
10180
10323
|
lastCandidate = current;
|
|
10181
10324
|
}
|
|
10182
|
-
const parent =
|
|
10325
|
+
const parent = dirname4(current);
|
|
10183
10326
|
if (parent === current) {
|
|
10184
10327
|
return lastCandidate;
|
|
10185
10328
|
}
|
|
@@ -10187,7 +10330,7 @@ async function findNearestProjectRoot(startDirectory) {
|
|
|
10187
10330
|
}
|
|
10188
10331
|
}
|
|
10189
10332
|
function defaultProjectConfig(projectRoot, settings, preferredHarness) {
|
|
10190
|
-
const projectName =
|
|
10333
|
+
const projectName = basename2(projectRoot);
|
|
10191
10334
|
const definitionId = normalizeAgentId(projectName);
|
|
10192
10335
|
const relativeRoot = relative(projectRoot, projectRoot) || ".";
|
|
10193
10336
|
return {
|
|
@@ -10361,7 +10504,7 @@ async function scanSourceRoot(sourceRoot) {
|
|
|
10361
10504
|
if (PROJECT_SCAN_SKIP_DIRECTORIES.has(entry.name)) {
|
|
10362
10505
|
continue;
|
|
10363
10506
|
}
|
|
10364
|
-
const nextPath =
|
|
10507
|
+
const nextPath = join11(currentDirectory, entry.name);
|
|
10365
10508
|
if (entry.isSymbolicLink()) {
|
|
10366
10509
|
if (!await isDirectory(nextPath)) {
|
|
10367
10510
|
continue;
|
|
@@ -10402,7 +10545,7 @@ function relativeProjectPath(projectRoot, sourceRoot) {
|
|
|
10402
10545
|
return relative(sourceRoot, projectRoot) || ".";
|
|
10403
10546
|
}
|
|
10404
10547
|
function resolveProjectRootFromConfig(projectRoot, config) {
|
|
10405
|
-
return normalizePath(
|
|
10548
|
+
return normalizePath(join11(projectRoot, config.project.root ?? "."));
|
|
10406
10549
|
}
|
|
10407
10550
|
function mergeResolvedAgentConfig(base, override, settings) {
|
|
10408
10551
|
if (!override) {
|
|
@@ -10494,8 +10637,8 @@ function selectorFromInput(value) {
|
|
|
10494
10637
|
}
|
|
10495
10638
|
async function resolveManifestBackedAgent(projectRoot, config, settings, override) {
|
|
10496
10639
|
const resolvedProjectRoot = resolveProjectRootFromConfig(projectRoot, config);
|
|
10497
|
-
const projectName = config.project.name?.trim() || titleCase(config.project.id ||
|
|
10498
|
-
const fallbackDefinitionId = normalizeAgentId(config.project.id ||
|
|
10640
|
+
const projectName = config.project.name?.trim() || titleCase(config.project.id || basename2(resolvedProjectRoot));
|
|
10641
|
+
const fallbackDefinitionId = normalizeAgentId(config.project.id || basename2(resolvedProjectRoot));
|
|
10499
10642
|
const definitionId = normalizeAgentId(config.agent?.id || override?.definitionId || fallbackDefinitionId);
|
|
10500
10643
|
const detectedHarness = await detectPreferredHarness(resolvedProjectRoot, settings.agents.defaultHarness);
|
|
10501
10644
|
const runtimeDefaults = config.agent?.runtime?.defaults;
|
|
@@ -10532,7 +10675,7 @@ async function resolveManifestBackedAgent(projectRoot, config, settings, overrid
|
|
|
10532
10675
|
return mergeResolvedAgentConfig(base, override, settings);
|
|
10533
10676
|
}
|
|
10534
10677
|
async function resolveInferredAgent(projectRoot, settings, override) {
|
|
10535
|
-
const projectName =
|
|
10678
|
+
const projectName = basename2(projectRoot);
|
|
10536
10679
|
const definitionId = normalizeAgentId(override?.definitionId?.trim() || projectName);
|
|
10537
10680
|
const detectedHarness = await detectPreferredHarness(projectRoot, settings.agents.defaultHarness);
|
|
10538
10681
|
const defaultHarness = normalizeManagedHarness(override?.defaultHarness ?? override?.runtime?.harness, normalizeManagedHarness(detectedHarness, "claude"));
|
|
@@ -10568,7 +10711,7 @@ async function resolveInferredAgent(projectRoot, settings, override) {
|
|
|
10568
10711
|
return mergeResolvedAgentConfig(base, override, settings);
|
|
10569
10712
|
}
|
|
10570
10713
|
async function buildProjectInventoryEntry(agent, sourceRoot) {
|
|
10571
|
-
const manifestRoot = agent.projectConfigPath ? normalizePath(
|
|
10714
|
+
const manifestRoot = agent.projectConfigPath ? normalizePath(join11(dirname4(agent.projectConfigPath), "..")) : null;
|
|
10572
10715
|
const manifest = manifestRoot ? await readProjectConfig(manifestRoot) : null;
|
|
10573
10716
|
const markers = await detectHarnessMarkers(agent.projectRoot);
|
|
10574
10717
|
const harnesses = new Map;
|
|
@@ -10676,7 +10819,7 @@ async function loadResolvedRelayAgents(options = {}) {
|
|
|
10676
10819
|
const sourceRootByProject = new Map(workspaceCandidates.map((candidate) => [candidate.projectRoot, candidate.sourceRoot]));
|
|
10677
10820
|
if (process.env.OPENSCOUT_SKIP_USER_PROJECT_HINTS !== "1") {
|
|
10678
10821
|
try {
|
|
10679
|
-
const hintHome = options.userLevelHintsHome ??
|
|
10822
|
+
const hintHome = options.userLevelHintsHome ?? homedir12();
|
|
10680
10823
|
const userHints = await collectUserLevelProjectRootHints({ home: hintHome });
|
|
10681
10824
|
for (const hint of userHints) {
|
|
10682
10825
|
const normalized = normalizePath(hint);
|
|
@@ -10814,16 +10957,16 @@ async function ensureRelayAgentConfigured(value, options = {}) {
|
|
|
10814
10957
|
|
|
10815
10958
|
// ../runtime/src/local-agents.ts
|
|
10816
10959
|
import { execFileSync as execFileSync3, execSync as execSync2 } from "child_process";
|
|
10817
|
-
import { existsSync as
|
|
10960
|
+
import { existsSync as existsSync12, readFileSync as readFileSync7 } from "fs";
|
|
10818
10961
|
import { mkdir as mkdir6, rm as rm5, stat as stat3, writeFile as writeFile6 } from "fs/promises";
|
|
10819
|
-
import { basename as
|
|
10820
|
-
import { fileURLToPath as
|
|
10962
|
+
import { basename as basename4, dirname as dirname6, join as join15, resolve as resolve5 } from "path";
|
|
10963
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
10821
10964
|
|
|
10822
10965
|
// ../runtime/src/claude-stream-json.ts
|
|
10823
10966
|
import { randomUUID } from "crypto";
|
|
10824
10967
|
import { spawn as spawn2 } from "child_process";
|
|
10825
10968
|
import { appendFile as appendFile2, mkdir as mkdir4, readFile as readFile5, rm as rm3, writeFile as writeFile4 } from "fs/promises";
|
|
10826
|
-
import { join as
|
|
10969
|
+
import { join as join12 } from "path";
|
|
10827
10970
|
|
|
10828
10971
|
// ../runtime/src/managed-agent-environment.ts
|
|
10829
10972
|
function managedAgentEnvironmentEntries(options) {
|
|
@@ -10885,9 +11028,9 @@ class ClaudeStreamJsonSession {
|
|
|
10885
11028
|
lastConfigSignature;
|
|
10886
11029
|
constructor(options) {
|
|
10887
11030
|
this.options = options;
|
|
10888
|
-
this.sessionStatePath =
|
|
10889
|
-
this.stdoutLogPath =
|
|
10890
|
-
this.stderrLogPath =
|
|
11031
|
+
this.sessionStatePath = join12(options.runtimeDirectory, "claude-session-id.txt");
|
|
11032
|
+
this.stdoutLogPath = join12(options.logsDirectory, "stdout.log");
|
|
11033
|
+
this.stderrLogPath = join12(options.logsDirectory, "stderr.log");
|
|
10891
11034
|
this.lastConfigSignature = this.configSignature(options);
|
|
10892
11035
|
}
|
|
10893
11036
|
matches(options) {
|
|
@@ -10914,13 +11057,13 @@ class ClaudeStreamJsonSession {
|
|
|
10914
11057
|
if (this.activeTurn) {
|
|
10915
11058
|
throw new Error(`Claude stream-json session for ${this.options.agentName} already has an active turn.`);
|
|
10916
11059
|
}
|
|
10917
|
-
const outputPromise = new Promise((
|
|
11060
|
+
const outputPromise = new Promise((resolve4, reject) => {
|
|
10918
11061
|
const turn = {
|
|
10919
11062
|
id: randomUUID(),
|
|
10920
11063
|
output: [],
|
|
10921
11064
|
timer: null,
|
|
10922
11065
|
stallMs: stallTimeoutMs,
|
|
10923
|
-
resolve:
|
|
11066
|
+
resolve: resolve4,
|
|
10924
11067
|
reject
|
|
10925
11068
|
};
|
|
10926
11069
|
this.activeTurn = turn;
|
|
@@ -11019,7 +11162,7 @@ class ClaudeStreamJsonSession {
|
|
|
11019
11162
|
async startSession() {
|
|
11020
11163
|
await mkdir4(this.options.runtimeDirectory, { recursive: true });
|
|
11021
11164
|
await mkdir4(this.options.logsDirectory, { recursive: true });
|
|
11022
|
-
await writeFile4(
|
|
11165
|
+
await writeFile4(join12(this.options.runtimeDirectory, "prompt.txt"), this.options.systemPrompt);
|
|
11023
11166
|
this.claudeSessionId = await readOptionalFile2(this.sessionStatePath);
|
|
11024
11167
|
const args = [
|
|
11025
11168
|
"--print",
|
|
@@ -11163,7 +11306,7 @@ async function shutdownClaudeStreamJsonAgent(options, shutdownOptions = {}) {
|
|
|
11163
11306
|
const session = sessions.get(key);
|
|
11164
11307
|
if (!session) {
|
|
11165
11308
|
if (shutdownOptions.resetSession) {
|
|
11166
|
-
await rm3(
|
|
11309
|
+
await rm3(join12(options.runtimeDirectory, "claude-session-id.txt"), { force: true });
|
|
11167
11310
|
}
|
|
11168
11311
|
return;
|
|
11169
11312
|
}
|
|
@@ -11173,8 +11316,8 @@ async function shutdownClaudeStreamJsonAgent(options, shutdownOptions = {}) {
|
|
|
11173
11316
|
|
|
11174
11317
|
// ../runtime/src/codex-app-server.ts
|
|
11175
11318
|
import { spawn as spawn3 } from "child_process";
|
|
11176
|
-
import { access as access3, appendFile as appendFile3, constants as
|
|
11177
|
-
import { delimiter as
|
|
11319
|
+
import { access as access3, appendFile as appendFile3, constants as constants3, mkdir as mkdir5, readFile as readFile6, rm as rm4, writeFile as writeFile5 } from "fs/promises";
|
|
11320
|
+
import { delimiter as delimiter3, join as join13 } from "path";
|
|
11178
11321
|
function sessionKey2(options) {
|
|
11179
11322
|
return `${options.agentName}:${options.sessionId}`;
|
|
11180
11323
|
}
|
|
@@ -11189,12 +11332,12 @@ function metadataRecord(metadata, key) {
|
|
|
11189
11332
|
}
|
|
11190
11333
|
return value;
|
|
11191
11334
|
}
|
|
11192
|
-
async function
|
|
11335
|
+
async function isExecutable3(filePath) {
|
|
11193
11336
|
if (!filePath) {
|
|
11194
11337
|
return false;
|
|
11195
11338
|
}
|
|
11196
11339
|
try {
|
|
11197
|
-
await access3(filePath,
|
|
11340
|
+
await access3(filePath, constants3.X_OK);
|
|
11198
11341
|
return true;
|
|
11199
11342
|
} catch {
|
|
11200
11343
|
return false;
|
|
@@ -11206,20 +11349,20 @@ async function resolveCodexExecutable2() {
|
|
|
11206
11349
|
process.env.CODEX_BIN
|
|
11207
11350
|
].filter(Boolean);
|
|
11208
11351
|
for (const candidate of explicitCandidates) {
|
|
11209
|
-
if (await
|
|
11352
|
+
if (await isExecutable3(candidate)) {
|
|
11210
11353
|
return candidate;
|
|
11211
11354
|
}
|
|
11212
11355
|
}
|
|
11213
11356
|
const bundledCandidates = [
|
|
11214
11357
|
"/Applications/Codex.app/Contents/Resources/codex",
|
|
11215
|
-
|
|
11358
|
+
join13(process.env.HOME ?? "", "Applications", "Codex.app", "Contents", "Resources", "codex")
|
|
11216
11359
|
].filter(Boolean);
|
|
11217
11360
|
for (const candidate of bundledCandidates) {
|
|
11218
|
-
if (await
|
|
11361
|
+
if (await isExecutable3(candidate)) {
|
|
11219
11362
|
return candidate;
|
|
11220
11363
|
}
|
|
11221
11364
|
}
|
|
11222
|
-
const pathEntries = (process.env.PATH ?? "").split(
|
|
11365
|
+
const pathEntries = (process.env.PATH ?? "").split(delimiter3).filter(Boolean);
|
|
11223
11366
|
const commonDirectories = [
|
|
11224
11367
|
`${process.env.HOME ?? ""}/.local/bin`,
|
|
11225
11368
|
`${process.env.HOME ?? ""}/.bun/bin`,
|
|
@@ -11227,8 +11370,8 @@ async function resolveCodexExecutable2() {
|
|
|
11227
11370
|
"/usr/local/bin"
|
|
11228
11371
|
].filter(Boolean);
|
|
11229
11372
|
for (const directory of [...pathEntries, ...commonDirectories]) {
|
|
11230
|
-
const candidate =
|
|
11231
|
-
if (await
|
|
11373
|
+
const candidate = join13(directory, "codex");
|
|
11374
|
+
if (await isExecutable3(candidate)) {
|
|
11232
11375
|
return candidate;
|
|
11233
11376
|
}
|
|
11234
11377
|
}
|
|
@@ -11304,10 +11447,10 @@ class CodexAppServerSession {
|
|
|
11304
11447
|
constructor(options) {
|
|
11305
11448
|
this.options = options;
|
|
11306
11449
|
this.key = sessionKey2(options);
|
|
11307
|
-
this.threadIdPath =
|
|
11308
|
-
this.statePath =
|
|
11309
|
-
this.stdoutLogPath =
|
|
11310
|
-
this.stderrLogPath =
|
|
11450
|
+
this.threadIdPath = join13(options.runtimeDirectory, "codex-thread-id.txt");
|
|
11451
|
+
this.statePath = join13(options.runtimeDirectory, "state.json");
|
|
11452
|
+
this.stdoutLogPath = join13(options.logsDirectory, "stdout.log");
|
|
11453
|
+
this.stderrLogPath = join13(options.logsDirectory, "stderr.log");
|
|
11311
11454
|
this.lastConfigSignature = this.configSignature(options);
|
|
11312
11455
|
}
|
|
11313
11456
|
matches(options) {
|
|
@@ -11335,8 +11478,8 @@ class CodexAppServerSession {
|
|
|
11335
11478
|
if (!this.threadId) {
|
|
11336
11479
|
throw new Error(`Codex app-server session for ${this.options.agentName} has no active thread.`);
|
|
11337
11480
|
}
|
|
11338
|
-
const output = await new Promise(async (
|
|
11339
|
-
const turn = this.createActiveTurn(
|
|
11481
|
+
const output = await new Promise(async (resolve4, reject) => {
|
|
11482
|
+
const turn = this.createActiveTurn(resolve4, reject, timeoutMs);
|
|
11340
11483
|
try {
|
|
11341
11484
|
const response = await this.request("turn/start", {
|
|
11342
11485
|
threadId: this.threadId,
|
|
@@ -11374,8 +11517,8 @@ class CodexAppServerSession {
|
|
|
11374
11517
|
if (!activeTurn?.turnId) {
|
|
11375
11518
|
return this.invoke(prompt, timeoutMs);
|
|
11376
11519
|
}
|
|
11377
|
-
const output = await new Promise(async (
|
|
11378
|
-
const watcher = this.addTurnWatcher(activeTurn,
|
|
11520
|
+
const output = await new Promise(async (resolve4, reject) => {
|
|
11521
|
+
const watcher = this.addTurnWatcher(activeTurn, resolve4, reject, timeoutMs);
|
|
11379
11522
|
try {
|
|
11380
11523
|
await this.request("turn/steer", {
|
|
11381
11524
|
threadId: this.threadId,
|
|
@@ -11444,7 +11587,7 @@ class CodexAppServerSession {
|
|
|
11444
11587
|
this.lineBuffer = "";
|
|
11445
11588
|
if (child && child.exitCode === null && !child.killed) {
|
|
11446
11589
|
child.kill("SIGTERM");
|
|
11447
|
-
await new Promise((
|
|
11590
|
+
await new Promise((resolve4) => setTimeout(resolve4, 250));
|
|
11448
11591
|
if (child.exitCode === null && !child.killed) {
|
|
11449
11592
|
child.kill("SIGKILL");
|
|
11450
11593
|
}
|
|
@@ -11492,15 +11635,22 @@ class CodexAppServerSession {
|
|
|
11492
11635
|
async startSession() {
|
|
11493
11636
|
await mkdir5(this.options.runtimeDirectory, { recursive: true });
|
|
11494
11637
|
await mkdir5(this.options.logsDirectory, { recursive: true });
|
|
11495
|
-
await writeFile5(
|
|
11638
|
+
await writeFile5(join13(this.options.runtimeDirectory, "prompt.txt"), this.options.systemPrompt);
|
|
11496
11639
|
const codexExecutable = await resolveCodexExecutable2();
|
|
11497
|
-
const
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
11640
|
+
const env = buildManagedAgentEnvironment({
|
|
11641
|
+
agentName: this.options.agentName,
|
|
11642
|
+
currentDirectory: this.options.cwd,
|
|
11643
|
+
baseEnv: process.env
|
|
11644
|
+
});
|
|
11645
|
+
const child = spawn3(codexExecutable, [
|
|
11646
|
+
"app-server",
|
|
11647
|
+
...buildScoutMcpCodexLaunchArgs({
|
|
11501
11648
|
currentDirectory: this.options.cwd,
|
|
11502
|
-
|
|
11503
|
-
})
|
|
11649
|
+
env
|
|
11650
|
+
})
|
|
11651
|
+
], {
|
|
11652
|
+
cwd: this.options.cwd,
|
|
11653
|
+
env,
|
|
11504
11654
|
stdio: ["pipe", "pipe", "pipe"]
|
|
11505
11655
|
});
|
|
11506
11656
|
this.process = child;
|
|
@@ -11587,7 +11737,7 @@ class CodexAppServerSession {
|
|
|
11587
11737
|
this.threadPath = started.thread.path ?? null;
|
|
11588
11738
|
await this.persistThreadId();
|
|
11589
11739
|
}
|
|
11590
|
-
createActiveTurn(
|
|
11740
|
+
createActiveTurn(resolve4, reject, timeoutMs) {
|
|
11591
11741
|
if (this.activeTurn) {
|
|
11592
11742
|
throw new Error(`Codex app-server session for ${this.options.agentName} already has an active turn.`);
|
|
11593
11743
|
}
|
|
@@ -11597,7 +11747,7 @@ class CodexAppServerSession {
|
|
|
11597
11747
|
timer: null,
|
|
11598
11748
|
messageOrder: [],
|
|
11599
11749
|
messageByItemId: new Map,
|
|
11600
|
-
resolve:
|
|
11750
|
+
resolve: resolve4,
|
|
11601
11751
|
reject,
|
|
11602
11752
|
watchers: []
|
|
11603
11753
|
};
|
|
@@ -11616,9 +11766,9 @@ class CodexAppServerSession {
|
|
|
11616
11766
|
this.activeTurn = turn;
|
|
11617
11767
|
return turn;
|
|
11618
11768
|
}
|
|
11619
|
-
addTurnWatcher(turn,
|
|
11769
|
+
addTurnWatcher(turn, resolve4, reject, timeoutMs) {
|
|
11620
11770
|
const watcher = {
|
|
11621
|
-
resolve:
|
|
11771
|
+
resolve: resolve4,
|
|
11622
11772
|
reject,
|
|
11623
11773
|
timer: null
|
|
11624
11774
|
};
|
|
@@ -11877,9 +12027,9 @@ class CodexAppServerSession {
|
|
|
11877
12027
|
}
|
|
11878
12028
|
async request(method, params) {
|
|
11879
12029
|
const id = String(this.nextRequestId++);
|
|
11880
|
-
return new Promise((
|
|
12030
|
+
return new Promise((resolve4, reject) => {
|
|
11881
12031
|
this.pendingRequests.set(id, {
|
|
11882
|
-
resolve: (value) =>
|
|
12032
|
+
resolve: (value) => resolve4(value),
|
|
11883
12033
|
reject
|
|
11884
12034
|
});
|
|
11885
12035
|
try {
|
|
@@ -11936,7 +12086,7 @@ async function shutdownCodexAppServerAgent(options, shutdownOptions = {}) {
|
|
|
11936
12086
|
if (!session) {
|
|
11937
12087
|
if (shutdownOptions.resetThread) {
|
|
11938
12088
|
const runtimeDirectory = options.runtimeDirectory;
|
|
11939
|
-
await rm4(
|
|
12089
|
+
await rm4(join13(runtimeDirectory, "codex-thread-id.txt"), { force: true });
|
|
11940
12090
|
}
|
|
11941
12091
|
return;
|
|
11942
12092
|
}
|
|
@@ -11949,10 +12099,13 @@ function buildCollaborationContractPrompt(agentId) {
|
|
|
11949
12099
|
return [
|
|
11950
12100
|
"Collaboration contract:",
|
|
11951
12101
|
` - Identity: act as the stable OpenScout agent "${agentId}" for this turn`,
|
|
12102
|
+
" - Default loop: orient -> resolve -> choose venue -> keep follow-up in that same venue",
|
|
11952
12103
|
" - Treat information-seeking requests as questions and durable execution as work",
|
|
11953
12104
|
" - Use collaboration verbs intentionally: answer, delegate, wait, review, complete",
|
|
11954
12105
|
" - @mention another agent only when handing off real work or requesting a concrete answer",
|
|
12106
|
+
" - One target means DM; group coordination means an explicit channel or separate DMs",
|
|
11955
12107
|
" - Do not broadcast ordinary delegation or wake agents who do not own the next move",
|
|
12108
|
+
" - Tell / update stays on the message path; owned work or a requested reply goes on the ask path",
|
|
11956
12109
|
" - If you can answer safely, answer directly",
|
|
11957
12110
|
" - If more work is required, make the next responsible agent explicit",
|
|
11958
12111
|
" - If blocked, say what you are waiting on and who owns the next move",
|
|
@@ -11964,10 +12117,10 @@ function buildCollaborationContractPrompt(agentId) {
|
|
|
11964
12117
|
|
|
11965
12118
|
// ../runtime/src/broker-service.ts
|
|
11966
12119
|
import { spawnSync } from "child_process";
|
|
11967
|
-
import { existsSync as
|
|
11968
|
-
import { homedir as
|
|
11969
|
-
import { basename as
|
|
11970
|
-
import { fileURLToPath as
|
|
12120
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
12121
|
+
import { homedir as homedir13 } from "os";
|
|
12122
|
+
import { basename as basename3, dirname as dirname5, join as join14, resolve as resolve4 } from "path";
|
|
12123
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
11971
12124
|
function isTmpPath(p) {
|
|
11972
12125
|
return /^\/(?:private\/)?tmp\//.test(p);
|
|
11973
12126
|
}
|
|
@@ -12006,17 +12159,17 @@ function runtimePackageDir() {
|
|
|
12006
12159
|
const fromCwd = findWorkspaceRuntimeDir(process.cwd());
|
|
12007
12160
|
if (fromCwd)
|
|
12008
12161
|
return fromCwd;
|
|
12009
|
-
const moduleDir =
|
|
12010
|
-
return
|
|
12162
|
+
const moduleDir = dirname5(fileURLToPath4(import.meta.url));
|
|
12163
|
+
return resolve4(moduleDir, "..");
|
|
12011
12164
|
}
|
|
12012
12165
|
function isInstalledRuntimePackageDir(candidate) {
|
|
12013
|
-
return
|
|
12166
|
+
return existsSync11(join14(candidate, "package.json")) && existsSync11(join14(candidate, "bin", "openscout-runtime.mjs"));
|
|
12014
12167
|
}
|
|
12015
12168
|
function findGlobalRuntimeDir() {
|
|
12016
12169
|
const candidates = [
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12170
|
+
join14(homedir13(), ".bun", "node_modules", "@openscout", "runtime"),
|
|
12171
|
+
join14(homedir13(), ".bun", "install", "global", "node_modules", "@openscout", "runtime"),
|
|
12172
|
+
join14(homedir13(), ".bun", "install", "global", "node_modules", "@openscout", "scout", "node_modules", "@openscout", "runtime")
|
|
12020
12173
|
];
|
|
12021
12174
|
for (const c of candidates) {
|
|
12022
12175
|
if (isInstalledRuntimePackageDir(c))
|
|
@@ -12026,11 +12179,11 @@ function findGlobalRuntimeDir() {
|
|
|
12026
12179
|
const result = spawnSync("which", ["scout"], { encoding: "utf8", timeout: 3000 });
|
|
12027
12180
|
const scoutBin = result.stdout?.trim();
|
|
12028
12181
|
if (scoutBin) {
|
|
12029
|
-
const scoutPkg =
|
|
12030
|
-
const nested =
|
|
12182
|
+
const scoutPkg = resolve4(scoutBin, "..", "..");
|
|
12183
|
+
const nested = join14(scoutPkg, "node_modules", "@openscout", "runtime");
|
|
12031
12184
|
if (isInstalledRuntimePackageDir(nested))
|
|
12032
12185
|
return nested;
|
|
12033
|
-
const sibling =
|
|
12186
|
+
const sibling = resolve4(scoutPkg, "..", "runtime");
|
|
12034
12187
|
if (isInstalledRuntimePackageDir(sibling))
|
|
12035
12188
|
return sibling;
|
|
12036
12189
|
}
|
|
@@ -12038,35 +12191,35 @@ function findGlobalRuntimeDir() {
|
|
|
12038
12191
|
return null;
|
|
12039
12192
|
}
|
|
12040
12193
|
function findWorkspaceRuntimeDir(startDir) {
|
|
12041
|
-
let current =
|
|
12194
|
+
let current = resolve4(startDir);
|
|
12042
12195
|
while (true) {
|
|
12043
|
-
const candidate =
|
|
12044
|
-
if (
|
|
12196
|
+
const candidate = join14(current, "packages", "runtime");
|
|
12197
|
+
if (existsSync11(join14(candidate, "package.json")) && existsSync11(join14(candidate, "src"))) {
|
|
12045
12198
|
return candidate;
|
|
12046
12199
|
}
|
|
12047
|
-
const parent =
|
|
12200
|
+
const parent = dirname5(current);
|
|
12048
12201
|
if (parent === current)
|
|
12049
12202
|
return null;
|
|
12050
12203
|
current = parent;
|
|
12051
12204
|
}
|
|
12052
12205
|
}
|
|
12053
|
-
function
|
|
12206
|
+
function resolveBunExecutable2() {
|
|
12054
12207
|
const explicit = process.env.OPENSCOUT_BUN_BIN ?? process.env.BUN_BIN;
|
|
12055
12208
|
if (explicit && explicit.trim().length > 0) {
|
|
12056
12209
|
return explicit;
|
|
12057
12210
|
}
|
|
12058
|
-
if (
|
|
12211
|
+
if (basename3(process.execPath).startsWith("bun") && existsSync11(process.execPath)) {
|
|
12059
12212
|
return process.execPath;
|
|
12060
12213
|
}
|
|
12061
12214
|
const pathEntries = (process.env.PATH ?? "").split(":").filter(Boolean);
|
|
12062
12215
|
for (const entry of pathEntries) {
|
|
12063
|
-
const candidate =
|
|
12064
|
-
if (
|
|
12216
|
+
const candidate = join14(entry, "bun");
|
|
12217
|
+
if (existsSync11(candidate)) {
|
|
12065
12218
|
return candidate;
|
|
12066
12219
|
}
|
|
12067
12220
|
}
|
|
12068
|
-
const homeBun =
|
|
12069
|
-
if (
|
|
12221
|
+
const homeBun = join14(homedir13(), ".bun", "bin", "bun");
|
|
12222
|
+
if (existsSync11(homeBun)) {
|
|
12070
12223
|
return homeBun;
|
|
12071
12224
|
}
|
|
12072
12225
|
return "bun";
|
|
@@ -12108,15 +12261,15 @@ function resolveBrokerServiceConfig() {
|
|
|
12108
12261
|
const label = resolveBrokerServiceLabel(mode);
|
|
12109
12262
|
const uid = typeof process.getuid === "function" ? process.getuid() : Number.parseInt(process.env.UID ?? "0", 10);
|
|
12110
12263
|
const supportPaths = resolveOpenScoutSupportPaths();
|
|
12111
|
-
const defaultSupportDir =
|
|
12264
|
+
const defaultSupportDir = join14(homedir13(), "Library", "Application Support", "OpenScout");
|
|
12112
12265
|
const supportDirectory = isTmpPath(supportPaths.supportDirectory) ? defaultSupportDir : supportPaths.supportDirectory;
|
|
12113
|
-
const logsDirectory =
|
|
12114
|
-
const controlHome = isTmpPath(supportPaths.controlHome) ?
|
|
12266
|
+
const logsDirectory = join14(supportDirectory, "logs", "broker");
|
|
12267
|
+
const controlHome = isTmpPath(supportPaths.controlHome) ? join14(homedir13(), ".openscout", "control-plane") : supportPaths.controlHome;
|
|
12115
12268
|
const advertiseScope = resolveAdvertiseScope();
|
|
12116
12269
|
const brokerHost = resolveBrokerHost(advertiseScope);
|
|
12117
12270
|
const brokerPort = Number.parseInt(process.env.OPENSCOUT_BROKER_PORT ?? String(DEFAULT_BROKER_PORT), 10);
|
|
12118
12271
|
const brokerUrl = process.env.OPENSCOUT_BROKER_URL ?? buildDefaultBrokerUrl(brokerHost, brokerPort);
|
|
12119
|
-
const launchAgentPath =
|
|
12272
|
+
const launchAgentPath = join14(homedir13(), "Library", "LaunchAgents", `${label}.plist`);
|
|
12120
12273
|
return {
|
|
12121
12274
|
label,
|
|
12122
12275
|
mode,
|
|
@@ -12126,11 +12279,11 @@ function resolveBrokerServiceConfig() {
|
|
|
12126
12279
|
launchAgentPath,
|
|
12127
12280
|
supportDirectory,
|
|
12128
12281
|
logsDirectory,
|
|
12129
|
-
stdoutLogPath:
|
|
12130
|
-
stderrLogPath:
|
|
12282
|
+
stdoutLogPath: join14(logsDirectory, "stdout.log"),
|
|
12283
|
+
stderrLogPath: join14(logsDirectory, "stderr.log"),
|
|
12131
12284
|
controlHome,
|
|
12132
12285
|
runtimePackageDir: runtimePackageDir(),
|
|
12133
|
-
bunExecutable:
|
|
12286
|
+
bunExecutable: resolveBunExecutable2(),
|
|
12134
12287
|
brokerHost,
|
|
12135
12288
|
brokerPort,
|
|
12136
12289
|
brokerUrl,
|
|
@@ -12147,7 +12300,7 @@ function renderLaunchAgentPlist(config) {
|
|
|
12147
12300
|
OPENSCOUT_BROKER_SERVICE_MODE: config.mode,
|
|
12148
12301
|
OPENSCOUT_BROKER_SERVICE_LABEL: config.label,
|
|
12149
12302
|
OPENSCOUT_ADVERTISE_SCOPE: config.advertiseScope,
|
|
12150
|
-
HOME:
|
|
12303
|
+
HOME: homedir13(),
|
|
12151
12304
|
PATH: launchPath,
|
|
12152
12305
|
...collectOptionalEnvVars([
|
|
12153
12306
|
"OPENSCOUT_MESH_ID",
|
|
@@ -12173,7 +12326,7 @@ function renderLaunchAgentPlist(config) {
|
|
|
12173
12326
|
<key>ProgramArguments</key>
|
|
12174
12327
|
<array>
|
|
12175
12328
|
<string>${xmlEscape(config.bunExecutable)}</string>
|
|
12176
|
-
<string>${xmlEscape(
|
|
12329
|
+
<string>${xmlEscape(join14(config.runtimePackageDir, "bin", "openscout-runtime.mjs"))}</string>
|
|
12177
12330
|
<string>broker</string>
|
|
12178
12331
|
</array>
|
|
12179
12332
|
<key>WorkingDirectory</key>
|
|
@@ -12209,7 +12362,7 @@ function collectOptionalEnvVars(keys) {
|
|
|
12209
12362
|
function resolveLaunchAgentPATH() {
|
|
12210
12363
|
const entries = [
|
|
12211
12364
|
...(process.env.PATH ?? "").split(":").filter(Boolean),
|
|
12212
|
-
|
|
12365
|
+
join14(homedir13(), ".bun", "bin"),
|
|
12213
12366
|
"/opt/homebrew/bin",
|
|
12214
12367
|
"/usr/local/bin",
|
|
12215
12368
|
"/usr/bin",
|
|
@@ -12223,7 +12376,7 @@ function xmlEscape(value) {
|
|
|
12223
12376
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12224
12377
|
}
|
|
12225
12378
|
function ensureParentDirectory(filePath) {
|
|
12226
|
-
mkdirSync8(
|
|
12379
|
+
mkdirSync8(dirname5(filePath), { recursive: true });
|
|
12227
12380
|
}
|
|
12228
12381
|
function ensureServiceDirectories(config) {
|
|
12229
12382
|
ensureOpenScoutCleanSlateSync();
|
|
@@ -12256,7 +12409,7 @@ function launchctlPath() {
|
|
|
12256
12409
|
return "/bin/launchctl";
|
|
12257
12410
|
}
|
|
12258
12411
|
function readLogLines(path2) {
|
|
12259
|
-
if (!
|
|
12412
|
+
if (!existsSync11(path2)) {
|
|
12260
12413
|
return [];
|
|
12261
12414
|
}
|
|
12262
12415
|
return readFileSync6(path2, "utf8").split(`
|
|
@@ -12356,7 +12509,7 @@ async function brokerServiceStatus(config = resolveBrokerServiceConfig()) {
|
|
|
12356
12509
|
ensureServiceDirectories(config);
|
|
12357
12510
|
const launchctl = inspectLaunchctl(config);
|
|
12358
12511
|
const health = await fetchHealthSnapshot(config);
|
|
12359
|
-
const installed =
|
|
12512
|
+
const installed = existsSync11(config.launchAgentPath);
|
|
12360
12513
|
const lastLogLine = health.reachable ? readLastLogLine([config.stdoutLogPath, config.stderrLogPath]) : readLastLogLine([config.stderrLogPath, config.stdoutLogPath]);
|
|
12361
12514
|
return {
|
|
12362
12515
|
label: config.label,
|
|
@@ -12399,7 +12552,7 @@ async function startBrokerService(config = resolveBrokerServiceConfig()) {
|
|
|
12399
12552
|
throw new Error(status.lastLogLine ?? status.health.error ?? "Broker service did not become healthy.");
|
|
12400
12553
|
}
|
|
12401
12554
|
function sleep(ms) {
|
|
12402
|
-
return new Promise((
|
|
12555
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
12403
12556
|
}
|
|
12404
12557
|
async function stopBrokerService(config = resolveBrokerServiceConfig()) {
|
|
12405
12558
|
runCommand(launchctlPath(), ["bootout", config.serviceTarget], { allowFailure: true });
|
|
@@ -12418,7 +12571,7 @@ async function restartBrokerService(config = resolveBrokerServiceConfig()) {
|
|
|
12418
12571
|
}
|
|
12419
12572
|
async function uninstallBrokerService(config = resolveBrokerServiceConfig()) {
|
|
12420
12573
|
await stopBrokerService(config);
|
|
12421
|
-
if (
|
|
12574
|
+
if (existsSync11(config.launchAgentPath)) {
|
|
12422
12575
|
rmSync2(config.launchAgentPath, { force: true });
|
|
12423
12576
|
}
|
|
12424
12577
|
return brokerServiceStatus(config);
|
|
@@ -12476,7 +12629,7 @@ function formatBrokerServiceStatus(status) {
|
|
|
12476
12629
|
return lines.join(`
|
|
12477
12630
|
`);
|
|
12478
12631
|
}
|
|
12479
|
-
if (process.argv[1] &&
|
|
12632
|
+
if (process.argv[1] && fileURLToPath4(import.meta.url) === process.argv[1]) {
|
|
12480
12633
|
await main();
|
|
12481
12634
|
}
|
|
12482
12635
|
|
|
@@ -12488,8 +12641,8 @@ var LOCAL_AGENT_SYSTEM_PROMPT_TEMPLATE_HINT = [
|
|
|
12488
12641
|
].join("");
|
|
12489
12642
|
|
|
12490
12643
|
// ../runtime/src/local-agents.ts
|
|
12491
|
-
var MODULE_DIRECTORY =
|
|
12492
|
-
var OPENSCOUT_REPO_ROOT =
|
|
12644
|
+
var MODULE_DIRECTORY = dirname6(fileURLToPath5(import.meta.url));
|
|
12645
|
+
var OPENSCOUT_REPO_ROOT = resolve5(MODULE_DIRECTORY, "..", "..", "..");
|
|
12493
12646
|
var DEFAULT_LOCAL_AGENT_CAPABILITIES = ["chat", "invoke", "deliver"];
|
|
12494
12647
|
var DEFAULT_LOCAL_AGENT_HARNESS = "claude";
|
|
12495
12648
|
function resolveRelayHub() {
|
|
@@ -12497,18 +12650,18 @@ function resolveRelayHub() {
|
|
|
12497
12650
|
}
|
|
12498
12651
|
function resolveProjectsRoot(projectPath) {
|
|
12499
12652
|
if (process.env.OPENSCOUT_PROJECTS_ROOT?.trim()) {
|
|
12500
|
-
return
|
|
12653
|
+
return resolve5(process.env.OPENSCOUT_PROJECTS_ROOT.trim());
|
|
12501
12654
|
}
|
|
12502
12655
|
try {
|
|
12503
12656
|
const supportPaths = resolveOpenScoutSupportPaths();
|
|
12504
|
-
if (!
|
|
12505
|
-
return
|
|
12657
|
+
if (!existsSync12(supportPaths.settingsPath)) {
|
|
12658
|
+
return dirname6(projectPath);
|
|
12506
12659
|
}
|
|
12507
12660
|
const raw = JSON.parse(readFileSync7(supportPaths.settingsPath, "utf8"));
|
|
12508
12661
|
const workspaceRoot = raw.discovery?.workspaceRoots?.find((entry) => typeof entry === "string" && entry.trim().length > 0);
|
|
12509
|
-
return workspaceRoot ?
|
|
12662
|
+
return workspaceRoot ? resolve5(workspaceRoot) : dirname6(projectPath);
|
|
12510
12663
|
} catch {
|
|
12511
|
-
return
|
|
12664
|
+
return dirname6(projectPath);
|
|
12512
12665
|
}
|
|
12513
12666
|
}
|
|
12514
12667
|
function resolveBrokerUrl() {
|
|
@@ -12518,20 +12671,20 @@ function nowSeconds2() {
|
|
|
12518
12671
|
return Math.floor(Date.now() / 1000);
|
|
12519
12672
|
}
|
|
12520
12673
|
function brokerRelayCommand() {
|
|
12521
|
-
return `node ${JSON.stringify(
|
|
12674
|
+
return `node ${JSON.stringify(join15(OPENSCOUT_REPO_ROOT, "packages", "cli", "bin", "scout.mjs"))}`;
|
|
12522
12675
|
}
|
|
12523
12676
|
function titleCaseLocalAgentName(value) {
|
|
12524
12677
|
return value.split(/[-_.\s]+/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join(" ");
|
|
12525
12678
|
}
|
|
12526
12679
|
function resolveScoutSkillPath() {
|
|
12527
12680
|
const candidatePaths = [
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12681
|
+
join15(OPENSCOUT_REPO_ROOT, ".agents", "skills", "scout", "SKILL.md"),
|
|
12682
|
+
join15(process.env.HOME ?? "", ".agents", "skills", "scout", "SKILL.md"),
|
|
12683
|
+
join15(OPENSCOUT_REPO_ROOT, ".agents", "skills", "relay-agent-comms", "SKILL.md"),
|
|
12684
|
+
join15(process.env.HOME ?? "", ".agents", "skills", "relay-agent-comms", "SKILL.md")
|
|
12532
12685
|
];
|
|
12533
12686
|
for (const path2 of candidatePaths) {
|
|
12534
|
-
if (
|
|
12687
|
+
if (existsSync12(path2)) {
|
|
12535
12688
|
return path2;
|
|
12536
12689
|
}
|
|
12537
12690
|
}
|
|
@@ -12583,12 +12736,18 @@ function buildLocalAgentTmuxProtocolPrompt(context) {
|
|
|
12583
12736
|
return [
|
|
12584
12737
|
"Relay protocol:",
|
|
12585
12738
|
` - Read recent context with: ${context.relayCommand} read --as ${context.agentId}`,
|
|
12586
|
-
` -
|
|
12587
|
-
` - Ask
|
|
12739
|
+
` - Tell one agent with: ${context.relayCommand} send --as ${context.agentId} "@<agent> your message"`,
|
|
12740
|
+
` - Ask one agent and stay attached with: ${context.relayCommand} ask --to <agent> --as ${context.agentId} "your request"`,
|
|
12588
12741
|
"",
|
|
12589
12742
|
"Rules:",
|
|
12590
12743
|
" - Do not use file-backed relay state or side channels directly",
|
|
12591
12744
|
" - Always reply via the broker-backed relay command above so other agents and the app can see your response",
|
|
12745
|
+
" - Default Scout loop: resolve identity, resolve one target, choose DM vs explicit channel, keep follow-up in that same venue",
|
|
12746
|
+
" - Keep one-to-one handoffs in a DM: do not pin a channel when the request is for exactly one agent",
|
|
12747
|
+
" - If you need multiple agents, use separate DMs or an explicit channel; do not guess a venue from multiple mentions",
|
|
12748
|
+
" - Do not use channel.shared for ordinary delegation or follow-up; reserve it for explicit group updates or broadcasts",
|
|
12749
|
+
" - If a short @handle may be ambiguous, resolve the exact target before sending; do not guess and do not fall back to shared",
|
|
12750
|
+
" - Use send for tells and status; use ask when the meaning is 'do this and get back to me'",
|
|
12592
12751
|
" - When replying to an [ask:<id>] request, include the same [ask:<id>] tag in your reply",
|
|
12593
12752
|
" - Use the broker-backed relay read command above to inspect recent context before responding",
|
|
12594
12753
|
` - Follow the scout skill at ${context.scoutSkill} for agent-to-agent communication`
|
|
@@ -12602,7 +12761,14 @@ function buildLocalAgentDirectProtocolPrompt(context) {
|
|
|
12602
12761
|
" - Return your final answer in the assistant message for the current turn",
|
|
12603
12762
|
" - Do not shell out to send the final answer through relay yourself",
|
|
12604
12763
|
` - If you need recent relay context, inspect it with: ${context.relayCommand} read --as ${context.agentId}`,
|
|
12764
|
+
` - If you need to tell one agent something, use: ${context.relayCommand} send --as ${context.agentId} "@<agent> your message"`,
|
|
12605
12765
|
` - If you need another agent to do work, use: ${context.relayCommand} ask --to <agent> --as ${context.agentId} "your request"`,
|
|
12766
|
+
" - Default Scout loop: resolve identity, resolve one target, choose DM vs explicit channel, keep follow-up in that same venue",
|
|
12767
|
+
" - Keep one-to-one handoffs in a DM: do not pin a channel when the request is for exactly one agent",
|
|
12768
|
+
" - If you need multiple agents, use separate DMs or an explicit channel; do not guess a venue from multiple mentions",
|
|
12769
|
+
" - Do not use channel.shared for ordinary delegation or follow-up; reserve it for explicit group updates or broadcasts",
|
|
12770
|
+
" - If a short @handle may be ambiguous, resolve the exact target before sending; do not guess and do not fall back to shared",
|
|
12771
|
+
" - Use send for tells and status; use ask when the meaning is 'do this and get back to me'",
|
|
12606
12772
|
` - Follow the scout skill at ${context.scoutSkill} for agent-to-agent communication`
|
|
12607
12773
|
].join(`
|
|
12608
12774
|
`);
|
|
@@ -12664,7 +12830,7 @@ function buildLegacySimpleRelayPrompt(agentId, projectName, projectPath, relayCo
|
|
|
12664
12830
|
"A primary agent may call into you for context, execution, follow-through, and handoff.",
|
|
12665
12831
|
"",
|
|
12666
12832
|
`You have full access to the codebase at ${projectPath}.`,
|
|
12667
|
-
`There is a structured relay event stream at ${
|
|
12833
|
+
`There is a structured relay event stream at ${join15(relayHub, "channel.jsonl")} shared by all agents.`,
|
|
12668
12834
|
"",
|
|
12669
12835
|
"Your job:",
|
|
12670
12836
|
` - Respond to @${agentId} mentions from other agents`,
|
|
@@ -12757,12 +12923,12 @@ function expandHomePath3(value) {
|
|
|
12757
12923
|
return process.env.HOME ?? process.cwd();
|
|
12758
12924
|
}
|
|
12759
12925
|
if (value.startsWith("~/")) {
|
|
12760
|
-
return
|
|
12926
|
+
return join15(process.env.HOME ?? process.cwd(), value.slice(2));
|
|
12761
12927
|
}
|
|
12762
12928
|
return value;
|
|
12763
12929
|
}
|
|
12764
12930
|
function normalizeProjectPath(value) {
|
|
12765
|
-
return
|
|
12931
|
+
return resolve5(expandHomePath3(value.trim() || "."));
|
|
12766
12932
|
}
|
|
12767
12933
|
function normalizeTmuxSessionName2(value, agentId) {
|
|
12768
12934
|
const fallback = `relay-${agentId}`;
|
|
@@ -12903,7 +13069,7 @@ function recordForHarness(record, harnessOverride) {
|
|
|
12903
13069
|
function normalizeLocalAgentRecord(agentId, record) {
|
|
12904
13070
|
const cwd = normalizeProjectPath(record.cwd || process.cwd());
|
|
12905
13071
|
const projectRoot = normalizeProjectPath(record.projectRoot || cwd);
|
|
12906
|
-
const project = record.project?.trim() ||
|
|
13072
|
+
const project = record.project?.trim() || basename4(projectRoot);
|
|
12907
13073
|
const definitionId = record.definitionId?.trim() || agentId;
|
|
12908
13074
|
const defaultHarness = activeLocalHarness(record);
|
|
12909
13075
|
const harnessProfiles = normalizeLocalHarnessProfiles(agentId, {
|
|
@@ -12968,7 +13134,7 @@ function localAgentRecordFromResolvedConfig(config) {
|
|
|
12968
13134
|
function localAgentRecordFromRelayAgentOverride(agentId, override) {
|
|
12969
13135
|
return normalizeLocalAgentRecord(agentId, {
|
|
12970
13136
|
definitionId: override.definitionId ?? agentId,
|
|
12971
|
-
project: override.projectName ??
|
|
13137
|
+
project: override.projectName ?? basename4(override.projectRoot || override.runtime?.cwd || agentId),
|
|
12972
13138
|
projectRoot: override.projectRoot ?? override.runtime?.cwd,
|
|
12973
13139
|
tmuxSession: override.runtime?.sessionId ?? `relay-${agentId}`,
|
|
12974
13140
|
cwd: override.runtime?.cwd ?? override.projectRoot,
|
|
@@ -13064,7 +13230,7 @@ function buildLocalAgentBootstrapPrompt(_harness, _systemPrompt, initialMessage)
|
|
|
13064
13230
|
function buildLocalAgentLaunchCommand(agentName, record, projectPath, promptFile, workerScript) {
|
|
13065
13231
|
const extraArgs = shellQuoteArguments(normalizeLocalAgentLaunchArgs(record.launchArgs));
|
|
13066
13232
|
if (normalizeLocalAgentHarness(record.harness) === "codex") {
|
|
13067
|
-
return `exec bash ${JSON.stringify(workerScript ??
|
|
13233
|
+
return `exec bash ${JSON.stringify(workerScript ?? join15(relayAgentRuntimeDirectory(agentName), "codex-worker.sh"))}`;
|
|
13068
13234
|
}
|
|
13069
13235
|
return [
|
|
13070
13236
|
"claude",
|
|
@@ -13110,7 +13276,7 @@ async function ensureLocalAgentOnline(agentName, record) {
|
|
|
13110
13276
|
return normalizedRecord;
|
|
13111
13277
|
}
|
|
13112
13278
|
const projectPath = normalizedRecord.cwd;
|
|
13113
|
-
const projectName = normalizedRecord.project ||
|
|
13279
|
+
const projectName = normalizedRecord.project || basename4(projectPath);
|
|
13114
13280
|
const systemPromptTemplate = normalizedRecord.systemPrompt || buildLocalAgentSystemPromptTemplate();
|
|
13115
13281
|
const systemPrompt = renderLocalAgentSystemPromptTemplate(systemPromptTemplate, buildLocalAgentTemplateContext(agentName, projectName, projectPath), { transport: normalizedRecord.transport });
|
|
13116
13282
|
const agentRuntimeDir = relayAgentRuntimeDirectory(agentName);
|
|
@@ -13118,7 +13284,7 @@ async function ensureLocalAgentOnline(agentName, record) {
|
|
|
13118
13284
|
await mkdir6(agentRuntimeDir, { recursive: true });
|
|
13119
13285
|
await mkdir6(logsDir, { recursive: true });
|
|
13120
13286
|
if (normalizedRecord.transport === "codex_app_server") {
|
|
13121
|
-
await writeFile6(
|
|
13287
|
+
await writeFile6(join15(agentRuntimeDir, "prompt.txt"), systemPrompt);
|
|
13122
13288
|
await ensureCodexAppServerAgentOnline(buildCodexAgentSessionOptions(agentName, normalizedRecord, systemPrompt));
|
|
13123
13289
|
const registry2 = await readLocalAgentRegistry();
|
|
13124
13290
|
registry2[agentName] = {
|
|
@@ -13130,7 +13296,7 @@ async function ensureLocalAgentOnline(agentName, record) {
|
|
|
13130
13296
|
return registry2[agentName];
|
|
13131
13297
|
}
|
|
13132
13298
|
if (normalizedRecord.transport === "claude_stream_json") {
|
|
13133
|
-
await writeFile6(
|
|
13299
|
+
await writeFile6(join15(agentRuntimeDir, "prompt.txt"), systemPrompt);
|
|
13134
13300
|
await ensureClaudeStreamJsonAgentOnline(buildClaudeAgentSessionOptions(agentName, normalizedRecord, systemPrompt));
|
|
13135
13301
|
const registry2 = await readLocalAgentRegistry();
|
|
13136
13302
|
registry2[agentName] = {
|
|
@@ -13143,17 +13309,17 @@ async function ensureLocalAgentOnline(agentName, record) {
|
|
|
13143
13309
|
}
|
|
13144
13310
|
const initialMessage = buildLocalAgentInitialMessage(projectName, agentName);
|
|
13145
13311
|
const bootstrapPrompt = buildLocalAgentBootstrapPrompt(normalizeLocalAgentHarness(normalizedRecord.harness), systemPrompt, initialMessage);
|
|
13146
|
-
const queueDirectory =
|
|
13147
|
-
const processingDirectory =
|
|
13148
|
-
const processedDirectory =
|
|
13149
|
-
const promptFile =
|
|
13150
|
-
const initialFile =
|
|
13151
|
-
const launchScript =
|
|
13152
|
-
const workerScript =
|
|
13153
|
-
const codexSessionIdFile =
|
|
13154
|
-
const stateFile =
|
|
13155
|
-
const stdoutLogFile =
|
|
13156
|
-
const stderrLogFile =
|
|
13312
|
+
const queueDirectory = join15(agentRuntimeDir, "queue");
|
|
13313
|
+
const processingDirectory = join15(queueDirectory, "processing");
|
|
13314
|
+
const processedDirectory = join15(queueDirectory, "processed");
|
|
13315
|
+
const promptFile = join15(agentRuntimeDir, "prompt.txt");
|
|
13316
|
+
const initialFile = join15(agentRuntimeDir, "initial.txt");
|
|
13317
|
+
const launchScript = join15(agentRuntimeDir, "launch.sh");
|
|
13318
|
+
const workerScript = join15(agentRuntimeDir, "codex-worker.sh");
|
|
13319
|
+
const codexSessionIdFile = join15(agentRuntimeDir, "codex-session-id.txt");
|
|
13320
|
+
const stateFile = join15(agentRuntimeDir, "state.json");
|
|
13321
|
+
const stdoutLogFile = join15(logsDir, "stdout.log");
|
|
13322
|
+
const stderrLogFile = join15(logsDir, "stderr.log");
|
|
13157
13323
|
await writeFile6(promptFile, systemPrompt);
|
|
13158
13324
|
await writeFile6(initialFile, bootstrapPrompt);
|
|
13159
13325
|
await writeFile6(stderrLogFile, "");
|
|
@@ -13215,10 +13381,10 @@ async function ensureLocalAgentOnline(agentName, record) {
|
|
|
13215
13381
|
if (isLocalAgentSessionAlive(normalizedRecord.tmuxSession)) {
|
|
13216
13382
|
break;
|
|
13217
13383
|
}
|
|
13218
|
-
await new Promise((
|
|
13384
|
+
await new Promise((resolve6) => setTimeout(resolve6, 100));
|
|
13219
13385
|
}
|
|
13220
13386
|
if (!isLocalAgentSessionAlive(normalizedRecord.tmuxSession)) {
|
|
13221
|
-
const stderrTail =
|
|
13387
|
+
const stderrTail = existsSync12(stderrLogFile) ? readFileSync7(stderrLogFile, "utf8").trim().split(/\r?\n/).slice(-10).join(`
|
|
13222
13388
|
`).trim() : "";
|
|
13223
13389
|
throw new Error(stderrTail ? `Relay agent ${agentName} failed to stay online:
|
|
13224
13390
|
${stderrTail}` : `Relay agent ${agentName} failed to stay online.`);
|
|
@@ -13320,7 +13486,7 @@ async function startLocalAgent(input) {
|
|
|
13320
13486
|
}
|
|
13321
13487
|
if (!matchingOverride) {
|
|
13322
13488
|
const configDefinitionId = coldProjectConfig?.agent?.id?.trim() ? normalizeAgentSelectorSegment(coldProjectConfig.agent.id.trim()) : "";
|
|
13323
|
-
const definitionId = requestedDefinitionId || configDefinitionId || normalizeAgentSelectorSegment(
|
|
13489
|
+
const definitionId = requestedDefinitionId || configDefinitionId || normalizeAgentSelectorSegment(basename4(projectRoot)) || "agent";
|
|
13324
13490
|
const configDisplayName = coldProjectConfig?.agent?.displayName?.trim() || "";
|
|
13325
13491
|
const effectiveDisplayName = input.displayName || configDisplayName || titleCaseLocalAgentName(definitionId);
|
|
13326
13492
|
const instance = buildRelayAgentInstance(definitionId, projectRoot);
|
|
@@ -13336,7 +13502,7 @@ async function startLocalAgent(input) {
|
|
|
13336
13502
|
agentId: instance.id,
|
|
13337
13503
|
definitionId,
|
|
13338
13504
|
displayName: effectiveDisplayName,
|
|
13339
|
-
projectName:
|
|
13505
|
+
projectName: basename4(projectRoot),
|
|
13340
13506
|
projectRoot,
|
|
13341
13507
|
projectConfigPath: coldProjectConfigPath,
|
|
13342
13508
|
source: "manual",
|
|
@@ -13372,7 +13538,7 @@ async function startLocalAgent(input) {
|
|
|
13372
13538
|
agentId: instance.id,
|
|
13373
13539
|
definitionId: requestedDefinitionId,
|
|
13374
13540
|
displayName: input.displayName || titleCaseLocalAgentName(requestedDefinitionId),
|
|
13375
|
-
projectName: matchingOverride.projectName ??
|
|
13541
|
+
projectName: matchingOverride.projectName ?? basename4(matchingProjectRoot),
|
|
13376
13542
|
projectRoot: matchingProjectRoot,
|
|
13377
13543
|
projectConfigPath: matchingOverride.projectConfigPath ?? null,
|
|
13378
13544
|
source: "manual",
|
|
@@ -14090,11 +14256,11 @@ async function upScoutAgent(input) {
|
|
|
14090
14256
|
|
|
14091
14257
|
// ../../apps/desktop/src/server/db-queries.ts
|
|
14092
14258
|
import { Database } from "bun:sqlite";
|
|
14093
|
-
import { homedir as
|
|
14094
|
-
import { join as
|
|
14259
|
+
import { homedir as homedir14 } from "os";
|
|
14260
|
+
import { join as join16 } from "path";
|
|
14095
14261
|
function resolveDbPath() {
|
|
14096
|
-
const controlHome = process.env.OPENSCOUT_CONTROL_HOME ??
|
|
14097
|
-
return
|
|
14262
|
+
const controlHome = process.env.OPENSCOUT_CONTROL_HOME ?? join16(homedir14(), ".openscout", "control-plane");
|
|
14263
|
+
return join16(controlHome, "control-plane.sqlite");
|
|
14098
14264
|
}
|
|
14099
14265
|
var _db = null;
|
|
14100
14266
|
function db() {
|
|
@@ -14105,7 +14271,7 @@ function db() {
|
|
|
14105
14271
|
}
|
|
14106
14272
|
return _db;
|
|
14107
14273
|
}
|
|
14108
|
-
var HOME =
|
|
14274
|
+
var HOME = homedir14();
|
|
14109
14275
|
function compact(p) {
|
|
14110
14276
|
if (!p)
|
|
14111
14277
|
return null;
|
|
@@ -14753,8 +14919,8 @@ async function createScoutSession(input, currentDirectory, deviceId) {
|
|
|
14753
14919
|
if (!rawWorkspaceId) {
|
|
14754
14920
|
throw new Error(`Invalid workspaceId.`);
|
|
14755
14921
|
}
|
|
14756
|
-
const workspaceRoot =
|
|
14757
|
-
const projectName =
|
|
14922
|
+
const workspaceRoot = resolve6(rawWorkspaceId);
|
|
14923
|
+
const projectName = basename5(workspaceRoot) || workspaceRoot;
|
|
14758
14924
|
const workspace = {
|
|
14759
14925
|
id: workspaceRoot,
|
|
14760
14926
|
title: projectName,
|
|
@@ -14863,17 +15029,17 @@ async function deriveNewAgentName(projectName, branch, harness) {
|
|
|
14863
15029
|
}
|
|
14864
15030
|
async function createGitWorktree(projectRoot, agentName) {
|
|
14865
15031
|
const { execSync: execSync3 } = await import("child_process");
|
|
14866
|
-
const { join:
|
|
14867
|
-
const { mkdirSync: mkdirSync9, existsSync:
|
|
15032
|
+
const { join: join17 } = await import("path");
|
|
15033
|
+
const { mkdirSync: mkdirSync9, existsSync: existsSync13 } = await import("fs");
|
|
14868
15034
|
try {
|
|
14869
15035
|
execSync3("git rev-parse --git-dir", { cwd: projectRoot, stdio: "pipe" });
|
|
14870
15036
|
} catch {
|
|
14871
15037
|
return null;
|
|
14872
15038
|
}
|
|
14873
15039
|
const branchName = `scout/${agentName}`;
|
|
14874
|
-
const worktreeDir =
|
|
14875
|
-
const worktreePath =
|
|
14876
|
-
if (
|
|
15040
|
+
const worktreeDir = join17(projectRoot, ".scout-worktrees");
|
|
15041
|
+
const worktreePath = join17(worktreeDir, agentName);
|
|
15042
|
+
if (existsSync13(worktreePath)) {
|
|
14877
15043
|
return { path: worktreePath, branch: branchName };
|
|
14878
15044
|
}
|
|
14879
15045
|
mkdirSync9(worktreeDir, { recursive: true });
|
|
@@ -15050,9 +15216,9 @@ async function handleRPCInner(bridge, req, deviceId) {
|
|
|
15050
15216
|
}
|
|
15051
15217
|
case "session/resume": {
|
|
15052
15218
|
const p = req.params;
|
|
15053
|
-
const sessionFilename =
|
|
15219
|
+
const sessionFilename = basename6(p.sessionPath, ".jsonl");
|
|
15054
15220
|
const parentDir = p.sessionPath.substring(0, p.sessionPath.lastIndexOf("/"));
|
|
15055
|
-
const dirName =
|
|
15221
|
+
const dirName = basename6(parentDir);
|
|
15056
15222
|
let cwd;
|
|
15057
15223
|
if (dirName.startsWith("-")) {
|
|
15058
15224
|
const candidate = "/" + dirName.slice(1).replace(/-/g, "/");
|
|
@@ -15119,7 +15285,7 @@ async function handleRPCInner(bridge, req, deviceId) {
|
|
|
15119
15285
|
return { id: req.id, error: { code: -32000, message: "Workspace target is not a directory" } };
|
|
15120
15286
|
}
|
|
15121
15287
|
const adapterType = p.adapter ?? "claude-code";
|
|
15122
|
-
const name = p.name ??
|
|
15288
|
+
const name = p.name ?? basename6(projectPath);
|
|
15123
15289
|
const session = await bridge.createSession(adapterType, {
|
|
15124
15290
|
name,
|
|
15125
15291
|
cwd: projectPath
|
|
@@ -15359,13 +15525,13 @@ function resolveMobileCurrentDirectory() {
|
|
|
15359
15525
|
}
|
|
15360
15526
|
}
|
|
15361
15527
|
function resolveWorkspaceRoot(root) {
|
|
15362
|
-
const expandedRoot = root.replace(/^~/,
|
|
15528
|
+
const expandedRoot = root.replace(/^~/, homedir15());
|
|
15363
15529
|
return realpathSync(expandedRoot);
|
|
15364
15530
|
}
|
|
15365
15531
|
function resolveWorkspacePath(root, requestedPath) {
|
|
15366
15532
|
const normalizedRoot = resolveWorkspaceRoot(root);
|
|
15367
|
-
const expandedPath = requestedPath?.replace(/^~/,
|
|
15368
|
-
const candidate = expandedPath ? isAbsolute3(expandedPath) ? expandedPath :
|
|
15533
|
+
const expandedPath = requestedPath?.replace(/^~/, homedir15());
|
|
15534
|
+
const candidate = expandedPath ? isAbsolute3(expandedPath) ? expandedPath : join17(normalizedRoot, expandedPath) : normalizedRoot;
|
|
15369
15535
|
const resolvedCandidate = realpathSync(candidate);
|
|
15370
15536
|
const rel = relative2(normalizedRoot, resolvedCandidate);
|
|
15371
15537
|
if (rel === "" || !rel.startsWith("..") && !isAbsolute3(rel)) {
|
|
@@ -15395,7 +15561,7 @@ function listDirectories(dirPath) {
|
|
|
15395
15561
|
continue;
|
|
15396
15562
|
if (name === "node_modules" || name === ".build" || name === "target")
|
|
15397
15563
|
continue;
|
|
15398
|
-
const fullPath =
|
|
15564
|
+
const fullPath = join17(dirPath, name);
|
|
15399
15565
|
try {
|
|
15400
15566
|
const stat4 = statSync3(fullPath);
|
|
15401
15567
|
if (!stat4.isDirectory())
|
|
@@ -15418,7 +15584,7 @@ function listDirectories(dirPath) {
|
|
|
15418
15584
|
return entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
15419
15585
|
}
|
|
15420
15586
|
async function discoverSessionFiles(maxAgeDays, limit) {
|
|
15421
|
-
const home =
|
|
15587
|
+
const home = homedir15();
|
|
15422
15588
|
const results = [];
|
|
15423
15589
|
const searchPaths = [
|
|
15424
15590
|
{ pattern: `${home}/.claude/projects`, agent: "claude-code" },
|
|
@@ -18007,8 +18173,8 @@ function emoji() {
|
|
|
18007
18173
|
}
|
|
18008
18174
|
var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
|
|
18009
18175
|
var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
|
|
18010
|
-
var mac = (
|
|
18011
|
-
const escapedDelim = escapeRegex(
|
|
18176
|
+
var mac = (delimiter4) => {
|
|
18177
|
+
const escapedDelim = escapeRegex(delimiter4 ?? ":");
|
|
18012
18178
|
return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
|
|
18013
18179
|
};
|
|
18014
18180
|
var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
|
|
@@ -29958,8 +30124,8 @@ config(en_default());
|
|
|
29958
30124
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/router.ts
|
|
29959
30125
|
import { readFileSync as readFileSync9, readdirSync as readdirSync4, realpathSync as realpathSync2, statSync as statSync4 } from "fs";
|
|
29960
30126
|
import { execSync as execSync4 } from "child_process";
|
|
29961
|
-
import { basename as
|
|
29962
|
-
import { homedir as
|
|
30127
|
+
import { basename as basename7, isAbsolute as isAbsolute4, join as join18, relative as relative3 } from "path";
|
|
30128
|
+
import { homedir as homedir16 } from "os";
|
|
29963
30129
|
var t = initTRPC.context().create();
|
|
29964
30130
|
var logged = t.middleware(async ({ path: path2, type, next }) => {
|
|
29965
30131
|
const start = Date.now();
|
|
@@ -29986,13 +30152,13 @@ function resolveMobileCurrentDirectory2() {
|
|
|
29986
30152
|
}
|
|
29987
30153
|
}
|
|
29988
30154
|
function resolveWorkspaceRoot2(root) {
|
|
29989
|
-
const expandedRoot = root.replace(/^~/,
|
|
30155
|
+
const expandedRoot = root.replace(/^~/, homedir16());
|
|
29990
30156
|
return realpathSync2(expandedRoot);
|
|
29991
30157
|
}
|
|
29992
30158
|
function resolveWorkspacePath2(root, requestedPath) {
|
|
29993
30159
|
const normalizedRoot = resolveWorkspaceRoot2(root);
|
|
29994
|
-
const expandedPath = requestedPath?.replace(/^~/,
|
|
29995
|
-
const candidate = expandedPath ? isAbsolute4(expandedPath) ? expandedPath :
|
|
30160
|
+
const expandedPath = requestedPath?.replace(/^~/, homedir16());
|
|
30161
|
+
const candidate = expandedPath ? isAbsolute4(expandedPath) ? expandedPath : join18(normalizedRoot, expandedPath) : normalizedRoot;
|
|
29996
30162
|
const resolvedCandidate = realpathSync2(candidate);
|
|
29997
30163
|
const rel = relative3(normalizedRoot, resolvedCandidate);
|
|
29998
30164
|
if (rel === "" || !rel.startsWith("..") && !isAbsolute4(rel)) {
|
|
@@ -30022,7 +30188,7 @@ function listDirectories2(dirPath) {
|
|
|
30022
30188
|
continue;
|
|
30023
30189
|
if (name === "node_modules" || name === ".build" || name === "target")
|
|
30024
30190
|
continue;
|
|
30025
|
-
const fullPath =
|
|
30191
|
+
const fullPath = join18(dirPath, name);
|
|
30026
30192
|
try {
|
|
30027
30193
|
const stat4 = statSync4(fullPath);
|
|
30028
30194
|
if (!stat4.isDirectory())
|
|
@@ -30061,7 +30227,7 @@ function detectAgent2(filePath) {
|
|
|
30061
30227
|
return "unknown";
|
|
30062
30228
|
}
|
|
30063
30229
|
async function discoverSessionFiles2(maxAgeDays, limit) {
|
|
30064
|
-
const home =
|
|
30230
|
+
const home = homedir16();
|
|
30065
30231
|
const results = [];
|
|
30066
30232
|
const searchPaths = [
|
|
30067
30233
|
{ pattern: `${home}/.claude/projects`, agent: "claude-code" },
|
|
@@ -30143,23 +30309,23 @@ function bridgeEventIterable(bridge, signal) {
|
|
|
30143
30309
|
return {
|
|
30144
30310
|
[Symbol.asyncIterator]() {
|
|
30145
30311
|
const buffer = [];
|
|
30146
|
-
let
|
|
30312
|
+
let resolve7 = null;
|
|
30147
30313
|
let done = false;
|
|
30148
30314
|
const unsub = bridge.onEvent((event) => {
|
|
30149
30315
|
if (done)
|
|
30150
30316
|
return;
|
|
30151
30317
|
buffer.push(event);
|
|
30152
|
-
if (
|
|
30153
|
-
|
|
30154
|
-
|
|
30318
|
+
if (resolve7) {
|
|
30319
|
+
resolve7();
|
|
30320
|
+
resolve7 = null;
|
|
30155
30321
|
}
|
|
30156
30322
|
});
|
|
30157
30323
|
const cleanup = () => {
|
|
30158
30324
|
done = true;
|
|
30159
30325
|
unsub();
|
|
30160
|
-
if (
|
|
30161
|
-
|
|
30162
|
-
|
|
30326
|
+
if (resolve7) {
|
|
30327
|
+
resolve7();
|
|
30328
|
+
resolve7 = null;
|
|
30163
30329
|
}
|
|
30164
30330
|
};
|
|
30165
30331
|
signal?.addEventListener("abort", cleanup, { once: true });
|
|
@@ -30172,7 +30338,7 @@ function bridgeEventIterable(bridge, signal) {
|
|
|
30172
30338
|
return { done: false, value: buffer.shift() };
|
|
30173
30339
|
}
|
|
30174
30340
|
await new Promise((r) => {
|
|
30175
|
-
|
|
30341
|
+
resolve7 = r;
|
|
30176
30342
|
});
|
|
30177
30343
|
}
|
|
30178
30344
|
},
|
|
@@ -30239,9 +30405,9 @@ var sessionRouter = t.router({
|
|
|
30239
30405
|
adapterType: exports_external.string().optional(),
|
|
30240
30406
|
name: exports_external.string().optional()
|
|
30241
30407
|
})).mutation(async ({ input, ctx }) => {
|
|
30242
|
-
const sessionFilename =
|
|
30408
|
+
const sessionFilename = basename7(input.sessionPath, ".jsonl");
|
|
30243
30409
|
const parentDir = input.sessionPath.substring(0, input.sessionPath.lastIndexOf("/"));
|
|
30244
|
-
const dirName =
|
|
30410
|
+
const dirName = basename7(parentDir);
|
|
30245
30411
|
let cwd;
|
|
30246
30412
|
if (dirName.startsWith("-")) {
|
|
30247
30413
|
const candidate = "/" + dirName.slice(1).replace(/-/g, "/");
|
|
@@ -30445,7 +30611,7 @@ var workspaceRouter = t.router({
|
|
|
30445
30611
|
});
|
|
30446
30612
|
}
|
|
30447
30613
|
const adapterType = input.adapter ?? "claude-code";
|
|
30448
|
-
const name = input.name ??
|
|
30614
|
+
const name = input.name ?? basename7(projectPath);
|
|
30449
30615
|
return ctx.bridge.createSession(adapterType, {
|
|
30450
30616
|
name,
|
|
30451
30617
|
cwd: projectPath
|
|
@@ -32965,8 +33131,8 @@ var Unpromise = class Unpromise2 {
|
|
|
32965
33131
|
status: "fulfilled",
|
|
32966
33132
|
value
|
|
32967
33133
|
};
|
|
32968
|
-
subscribers === null || subscribers === undefined || subscribers.forEach(({ resolve:
|
|
32969
|
-
|
|
33134
|
+
subscribers === null || subscribers === undefined || subscribers.forEach(({ resolve: resolve7 }) => {
|
|
33135
|
+
resolve7(value);
|
|
32970
33136
|
});
|
|
32971
33137
|
});
|
|
32972
33138
|
if ("catch" in thenReturn)
|
|
@@ -33074,15 +33240,15 @@ function resolveSelfTuple(promise2) {
|
|
|
33074
33240
|
return Unpromise.proxy(promise2).then(() => [promise2]);
|
|
33075
33241
|
}
|
|
33076
33242
|
function withResolvers() {
|
|
33077
|
-
let
|
|
33243
|
+
let resolve7;
|
|
33078
33244
|
let reject;
|
|
33079
33245
|
const promise2 = new Promise((_resolve, _reject) => {
|
|
33080
|
-
|
|
33246
|
+
resolve7 = _resolve;
|
|
33081
33247
|
reject = _reject;
|
|
33082
33248
|
});
|
|
33083
33249
|
return {
|
|
33084
33250
|
promise: promise2,
|
|
33085
|
-
resolve:
|
|
33251
|
+
resolve: resolve7,
|
|
33086
33252
|
reject
|
|
33087
33253
|
};
|
|
33088
33254
|
}
|
|
@@ -33128,8 +33294,8 @@ function timerResource(ms) {
|
|
|
33128
33294
|
return makeResource({ start() {
|
|
33129
33295
|
if (timer)
|
|
33130
33296
|
throw new Error("Timer already started");
|
|
33131
|
-
const promise2 = new Promise((
|
|
33132
|
-
timer = setTimeout(() =>
|
|
33297
|
+
const promise2 = new Promise((resolve7) => {
|
|
33298
|
+
timer = setTimeout(() => resolve7(disposablePromiseTimerResult), ms);
|
|
33133
33299
|
});
|
|
33134
33300
|
return promise2;
|
|
33135
33301
|
} }, () => {
|
|
@@ -33332,15 +33498,15 @@ function _takeWithGrace() {
|
|
|
33332
33498
|
return _takeWithGrace.apply(this, arguments);
|
|
33333
33499
|
}
|
|
33334
33500
|
function createDeferred() {
|
|
33335
|
-
let
|
|
33501
|
+
let resolve7;
|
|
33336
33502
|
let reject;
|
|
33337
33503
|
const promise2 = new Promise((res, rej) => {
|
|
33338
|
-
|
|
33504
|
+
resolve7 = res;
|
|
33339
33505
|
reject = rej;
|
|
33340
33506
|
});
|
|
33341
33507
|
return {
|
|
33342
33508
|
promise: promise2,
|
|
33343
|
-
resolve:
|
|
33509
|
+
resolve: resolve7,
|
|
33344
33510
|
reject
|
|
33345
33511
|
};
|
|
33346
33512
|
}
|
|
@@ -34571,14 +34737,14 @@ function parseTRPCMessage(obj, transformer) {
|
|
|
34571
34737
|
}
|
|
34572
34738
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/server-trpc.ts
|
|
34573
34739
|
import { realpathSync as realpathSync3 } from "fs";
|
|
34574
|
-
import { homedir as
|
|
34740
|
+
import { homedir as homedir17 } from "os";
|
|
34575
34741
|
function resolveCurrentDirectory() {
|
|
34576
34742
|
try {
|
|
34577
34743
|
const config2 = resolveConfig();
|
|
34578
34744
|
const configuredRoot = config2.workspace?.root;
|
|
34579
34745
|
if (!configuredRoot)
|
|
34580
34746
|
return process.cwd();
|
|
34581
|
-
const expanded = configuredRoot.replace(/^~/,
|
|
34747
|
+
const expanded = configuredRoot.replace(/^~/, homedir17());
|
|
34582
34748
|
return realpathSync3(expanded);
|
|
34583
34749
|
} catch {
|
|
34584
34750
|
return process.cwd();
|
|
@@ -34696,8 +34862,8 @@ function startBridgeServerTRPC(options) {
|
|
|
34696
34862
|
}
|
|
34697
34863
|
const iterable = isObservable(result) ? observableToAsyncIterable(result, abortController.signal) : result;
|
|
34698
34864
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
34699
|
-
const abortPromise = new Promise((
|
|
34700
|
-
abortController.signal.addEventListener("abort", () =>
|
|
34865
|
+
const abortPromise = new Promise((resolve7) => {
|
|
34866
|
+
abortController.signal.addEventListener("abort", () => resolve7("abort"), {
|
|
34701
34867
|
once: true
|
|
34702
34868
|
});
|
|
34703
34869
|
});
|
|
@@ -35056,7 +35222,7 @@ async function autoStartConfiguredSessions(bridge, sessions3) {
|
|
|
35056
35222
|
try {
|
|
35057
35223
|
const session = await bridge.createSession(entry.adapter, {
|
|
35058
35224
|
name: entry.name,
|
|
35059
|
-
cwd: entry.cwd?.replace(/^~/,
|
|
35225
|
+
cwd: entry.cwd?.replace(/^~/, homedir18()),
|
|
35060
35226
|
options: entry.options
|
|
35061
35227
|
});
|
|
35062
35228
|
console.log(`[bridge] session started: ${session.name} (${entry.adapter})`);
|