switchroom 0.15.34 → 0.15.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/switchroom.js
CHANGED
|
@@ -23528,8 +23528,8 @@ var init_resolver = __esm(() => {
|
|
|
23528
23528
|
|
|
23529
23529
|
// src/agents/compose.ts
|
|
23530
23530
|
import { createHash as createHash3 } from "node:crypto";
|
|
23531
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync13 } from "node:fs";
|
|
23532
|
-
import { join as join10 } from "node:path";
|
|
23531
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync13, lstatSync as lstatSync4, readlinkSync as readlinkSync5 } from "node:fs";
|
|
23532
|
+
import { join as join10, isAbsolute, dirname as dirname3, resolve as resolve12 } from "node:path";
|
|
23533
23533
|
function parseMemToMib(s) {
|
|
23534
23534
|
const m = /^(\d+(?:\.\d+)?)\s*([gmk]?)b?$/i.exec(s.trim());
|
|
23535
23535
|
if (!m)
|
|
@@ -23707,6 +23707,23 @@ function readStrippedCaps(agent) {
|
|
|
23707
23707
|
return caps.map(String);
|
|
23708
23708
|
return [];
|
|
23709
23709
|
}
|
|
23710
|
+
function conditionalMountPresent(probePath, hostHome, probeHome) {
|
|
23711
|
+
if (existsSync15(probePath))
|
|
23712
|
+
return true;
|
|
23713
|
+
try {
|
|
23714
|
+
if (!lstatSync4(probePath).isSymbolicLink())
|
|
23715
|
+
return false;
|
|
23716
|
+
let target = readlinkSync5(probePath);
|
|
23717
|
+
if (!isAbsolute(target))
|
|
23718
|
+
target = resolve12(dirname3(probePath), target);
|
|
23719
|
+
if (hostHome && probeHome && hostHome !== probeHome && target.startsWith(hostHome + "/")) {
|
|
23720
|
+
target = probeHome + target.slice(hostHome.length);
|
|
23721
|
+
}
|
|
23722
|
+
return existsSync15(target);
|
|
23723
|
+
} catch {
|
|
23724
|
+
return false;
|
|
23725
|
+
}
|
|
23726
|
+
}
|
|
23710
23727
|
function generateCompose(opts) {
|
|
23711
23728
|
const { config } = opts;
|
|
23712
23729
|
assertNoAgentUidCollision(config);
|
|
@@ -24079,16 +24096,16 @@ function emitAgentService(lines, a, imageTag, buildMode, buildContext, homePrefi
|
|
|
24079
24096
|
lines.push(` - ${homePrefix}/.switchroom/logs/${a.name}:/var/log/switchroom`);
|
|
24080
24097
|
lines.push(` - ${homePrefix}/.switchroom/agents/${a.name}:${homePrefix}/.switchroom/agents/${a.name}`);
|
|
24081
24098
|
lines.push(` - ${homePrefix}/.claude/projects/${a.name}:${homePrefix}/.claude/projects/${a.name}`);
|
|
24082
|
-
if (
|
|
24099
|
+
if (conditionalMountPresent(`${probeHome}/.switchroom/skills`, hostHomeForChecks, probeHome)) {
|
|
24083
24100
|
lines.push(` - ${homePrefix}/.switchroom/skills:${homePrefix}/.switchroom/skills:ro`);
|
|
24084
24101
|
}
|
|
24085
|
-
if (
|
|
24102
|
+
if (conditionalMountPresent(`${probeHome}/.switchroom/mcp-launchers`, hostHomeForChecks, probeHome)) {
|
|
24086
24103
|
lines.push(` - ${homePrefix}/.switchroom/mcp-launchers:${homePrefix}/.switchroom/mcp-launchers:ro`);
|
|
24087
24104
|
}
|
|
24088
|
-
if (
|
|
24105
|
+
if (conditionalMountPresent(`${probeHome}/.switchroom/fleet`, hostHomeForChecks, probeHome)) {
|
|
24089
24106
|
lines.push(` - ${homePrefix}/.switchroom/fleet:${homePrefix}/.switchroom/fleet:ro`);
|
|
24090
24107
|
}
|
|
24091
|
-
if (
|
|
24108
|
+
if (conditionalMountPresent(`${probeHome}/.switchroom/credentials/${a.name}`, hostHomeForChecks, probeHome)) {
|
|
24092
24109
|
lines.push(` - ${homePrefix}/.switchroom/credentials/${a.name}:${homePrefix}/.switchroom/credentials:ro`);
|
|
24093
24110
|
}
|
|
24094
24111
|
try {
|
|
@@ -24098,7 +24115,7 @@ function emitAgentService(lines, a, imageTag, buildMode, buildContext, homePrefi
|
|
|
24098
24115
|
mkdirSync11(`${probeHome}/.switchroom/agents/${a.name}/schedule.d`, { recursive: true });
|
|
24099
24116
|
} catch {}
|
|
24100
24117
|
lines.push(` - ${homePrefix}/.switchroom/audit/${a.name}:${homePrefix}/.switchroom/audit/${a.name}:rw`);
|
|
24101
|
-
if (
|
|
24118
|
+
if (conditionalMountPresent(`${probeHome}/.switchroom-config`, hostHomeForChecks, probeHome)) {
|
|
24102
24119
|
try {
|
|
24103
24120
|
mkdirSync11(`${probeHome}/.switchroom-config/agents/${a.name}/personal-skills`, { recursive: true });
|
|
24104
24121
|
} catch {}
|
|
@@ -24113,8 +24130,9 @@ function emitAgentService(lines, a, imageTag, buildMode, buildContext, homePrefi
|
|
|
24113
24130
|
if (existsSync15(`${probeHome}/.switchroom/webkite/config.toml`)) {
|
|
24114
24131
|
lines.push(` - ${homePrefix}/.switchroom/webkite/config.toml:/state/agent/home/.config/webkite/config.toml:ro`);
|
|
24115
24132
|
}
|
|
24116
|
-
|
|
24117
|
-
|
|
24133
|
+
const bundledSkillsBakeDir = probeHome && hostHomeForChecks && probeHome !== hostHomeForChecks && bundledSkillsPoolDir.startsWith(probeHome + "/") ? hostHomeForChecks + bundledSkillsPoolDir.slice(probeHome.length) : bundledSkillsPoolDir;
|
|
24134
|
+
if (bundledSkillsPoolDir && existsSync15(bundledSkillsPoolDir) && !bundledSkillsBakeDir.startsWith(`${hostHomeForChecks}/.switchroom/skills`)) {
|
|
24135
|
+
lines.push(` - ${bundledSkillsBakeDir}:${bundledSkillsBakeDir}:ro`);
|
|
24118
24136
|
}
|
|
24119
24137
|
if (switchroomConfigPath) {
|
|
24120
24138
|
lines.push(` - ${switchroomConfigPath}:/state/config/switchroom.yaml:ro`);
|
|
@@ -24227,7 +24245,7 @@ var init_tmux = __esm(() => {
|
|
|
24227
24245
|
});
|
|
24228
24246
|
|
|
24229
24247
|
// src/agents/docker-fleet.ts
|
|
24230
|
-
import { resolve as
|
|
24248
|
+
import { resolve as resolve13 } from "node:path";
|
|
24231
24249
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync6 } from "node:fs";
|
|
24232
24250
|
import { homedir as homedir7 } from "node:os";
|
|
24233
24251
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
@@ -24237,11 +24255,11 @@ function resolveSwitchroomHome(explicit) {
|
|
|
24237
24255
|
const envHome = process.env.SWITCHROOM_HOME;
|
|
24238
24256
|
if (envHome && envHome.length > 0)
|
|
24239
24257
|
return envHome;
|
|
24240
|
-
return
|
|
24258
|
+
return resolve13(process.env.HOME ?? "", ".switchroom");
|
|
24241
24259
|
}
|
|
24242
24260
|
function bringUpAgentService(opts) {
|
|
24243
24261
|
const home2 = resolveSwitchroomHome(opts.switchroomHome);
|
|
24244
|
-
const composeDir =
|
|
24262
|
+
const composeDir = resolve13(home2, "compose");
|
|
24245
24263
|
mkdirSync12(composeDir, { recursive: true, mode: 493 });
|
|
24246
24264
|
let switchroomConfigPath = opts.switchroomConfigPath;
|
|
24247
24265
|
if (!switchroomConfigPath && !opts.generateComposeContent) {
|
|
@@ -24256,7 +24274,7 @@ function bringUpAgentService(opts) {
|
|
|
24256
24274
|
homeDir: homedir7(),
|
|
24257
24275
|
switchroomConfigPath
|
|
24258
24276
|
});
|
|
24259
|
-
const composePath =
|
|
24277
|
+
const composePath = resolve13(composeDir, "docker-compose.yml");
|
|
24260
24278
|
writeFileSync6(composePath, compose, { mode: 384 });
|
|
24261
24279
|
const dockerBin = opts.dockerBin ?? "docker";
|
|
24262
24280
|
const stdio = opts.stdio ?? "inherit";
|
|
@@ -24375,7 +24393,7 @@ var init_singleton_reconcile = __esm(() => {
|
|
|
24375
24393
|
// src/agents/lifecycle.ts
|
|
24376
24394
|
import { execFileSync as execFileSync8, spawn, spawnSync } from "node:child_process";
|
|
24377
24395
|
import { existsSync as existsSync17, mkdirSync as mkdirSync13, writeFileSync as writeFileSync7, renameSync as renameSync4, readFileSync as readFileSync15 } from "node:fs";
|
|
24378
|
-
import { resolve as
|
|
24396
|
+
import { resolve as resolve14, join as join13 } from "node:path";
|
|
24379
24397
|
import { connect } from "node:net";
|
|
24380
24398
|
function cleanShutdownMarkerPathForAgent(name) {
|
|
24381
24399
|
const agentsDir = process.env.SWITCHROOM_AGENTS_DIR ?? resolveStatePath("agents");
|
|
@@ -24438,7 +24456,7 @@ function composeFilePath() {
|
|
|
24438
24456
|
const override = process.env.SWITCHROOM_COMPOSE_FILE;
|
|
24439
24457
|
if (override && override.length > 0)
|
|
24440
24458
|
return override;
|
|
24441
|
-
return
|
|
24459
|
+
return resolve14(resolveSwitchroomHome(), "compose", "docker-compose.yml");
|
|
24442
24460
|
}
|
|
24443
24461
|
function reconcileSingletonImages(log) {
|
|
24444
24462
|
return reconcileSingletons({ composeFile: composeFilePath(), log });
|
|
@@ -24487,7 +24505,7 @@ function restartAgent(name, reason) {
|
|
|
24487
24505
|
function gracefulRestartAgent(name) {
|
|
24488
24506
|
return new Promise((resolvePromise, reject) => {
|
|
24489
24507
|
const agentsDir = process.env.SWITCHROOM_AGENTS_DIR ?? resolveStatePath("agents");
|
|
24490
|
-
const agentDir =
|
|
24508
|
+
const agentDir = resolve14(agentsDir, name);
|
|
24491
24509
|
const socketPath = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join13(agentDir, "telegram", "gateway.sock");
|
|
24492
24510
|
if (!existsSync17(socketPath)) {
|
|
24493
24511
|
reject(new Error("Gateway socket not found. Is the gateway running?"));
|
|
@@ -25131,7 +25149,7 @@ import {
|
|
|
25131
25149
|
chmodSync as chmodSync3,
|
|
25132
25150
|
statSync as statSync13
|
|
25133
25151
|
} from "node:fs";
|
|
25134
|
-
import { join as join17, resolve as
|
|
25152
|
+
import { join as join17, resolve as resolve16 } from "node:path";
|
|
25135
25153
|
function extractCodeChallenge(url) {
|
|
25136
25154
|
const match = url.match(/[?&]code_challenge=([A-Za-z0-9_-]+)/);
|
|
25137
25155
|
return match ? match[1] : null;
|
|
@@ -25394,7 +25412,7 @@ function getAllAuthStatuses(config) {
|
|
|
25394
25412
|
const agentsDir = resolveAgentsDir(config);
|
|
25395
25413
|
const statuses = {};
|
|
25396
25414
|
for (const name of Object.keys(config.agents)) {
|
|
25397
|
-
const agentDir =
|
|
25415
|
+
const agentDir = resolve16(agentsDir, name);
|
|
25398
25416
|
statuses[name] = getAuthStatus(name, agentDir);
|
|
25399
25417
|
}
|
|
25400
25418
|
return statuses;
|
|
@@ -26440,7 +26458,7 @@ class AuthBrokerClient {
|
|
|
26440
26458
|
return this.socket;
|
|
26441
26459
|
if (this.connecting)
|
|
26442
26460
|
return this.connecting;
|
|
26443
|
-
this.connecting = new Promise((
|
|
26461
|
+
this.connecting = new Promise((resolve23, reject) => {
|
|
26444
26462
|
const sock = new net2.Socket;
|
|
26445
26463
|
const onError = (err) => {
|
|
26446
26464
|
sock.removeAllListeners();
|
|
@@ -26464,7 +26482,7 @@ class AuthBrokerClient {
|
|
|
26464
26482
|
sock.on("error", (err) => this.onSocketError(err));
|
|
26465
26483
|
sock.on("close", () => this.onSocketClose());
|
|
26466
26484
|
this.socket = sock;
|
|
26467
|
-
|
|
26485
|
+
resolve23(sock);
|
|
26468
26486
|
});
|
|
26469
26487
|
sock.connect({ path: this.socketPath });
|
|
26470
26488
|
});
|
|
@@ -26524,7 +26542,7 @@ class AuthBrokerClient {
|
|
|
26524
26542
|
const sock = await this.ensureConnected();
|
|
26525
26543
|
const id = req.id;
|
|
26526
26544
|
const frame = encodeRequest2(req);
|
|
26527
|
-
return new Promise((
|
|
26545
|
+
return new Promise((resolve23, reject) => {
|
|
26528
26546
|
const timer = setTimeout(() => {
|
|
26529
26547
|
this.pending.delete(id);
|
|
26530
26548
|
reject(new AuthBrokerUnreachableError(`request ${req.op} timed out after ${this.timeoutMs}ms`, this.socketPath));
|
|
@@ -26532,7 +26550,7 @@ class AuthBrokerClient {
|
|
|
26532
26550
|
this.pending.set(id, {
|
|
26533
26551
|
resolve: (resp) => {
|
|
26534
26552
|
if (resp.ok) {
|
|
26535
|
-
|
|
26553
|
+
resolve23(resp.data);
|
|
26536
26554
|
} else {
|
|
26537
26555
|
reject(new AuthBrokerError(resp.error.code, resp.error.message));
|
|
26538
26556
|
}
|
|
@@ -26632,7 +26650,7 @@ import {
|
|
|
26632
26650
|
writeFileSync as writeFileSync14
|
|
26633
26651
|
} from "node:fs";
|
|
26634
26652
|
import { homedir as homedir11 } from "node:os";
|
|
26635
|
-
import { join as join23, resolve as
|
|
26653
|
+
import { join as join23, resolve as resolve23 } from "node:path";
|
|
26636
26654
|
function accountsRootOverride() {
|
|
26637
26655
|
const v = process.env.SWITCHROOM_ACCOUNTS_DIR;
|
|
26638
26656
|
if (v && v.length > 0 && v.startsWith("/"))
|
|
@@ -26640,7 +26658,7 @@ function accountsRootOverride() {
|
|
|
26640
26658
|
return;
|
|
26641
26659
|
}
|
|
26642
26660
|
function accountsRoot(home2 = homedir11()) {
|
|
26643
|
-
return accountsRootOverride() ??
|
|
26661
|
+
return accountsRootOverride() ?? resolve23(home2, ".switchroom", "accounts");
|
|
26644
26662
|
}
|
|
26645
26663
|
function accountDir(label, home2 = homedir11()) {
|
|
26646
26664
|
return join23(accountsRoot(home2), label);
|
|
@@ -26991,18 +27009,18 @@ async function openBrowser(url, platform = process.platform, spawnImpl = spawn2)
|
|
|
26991
27009
|
cmd = "xdg-open";
|
|
26992
27010
|
args = [url];
|
|
26993
27011
|
}
|
|
26994
|
-
return new Promise((
|
|
27012
|
+
return new Promise((resolve24) => {
|
|
26995
27013
|
try {
|
|
26996
27014
|
const p = spawnImpl(cmd, args, { stdio: "ignore", detached: true });
|
|
26997
|
-
p.once("error", () =>
|
|
27015
|
+
p.once("error", () => resolve24(false));
|
|
26998
27016
|
p.once("spawn", () => {
|
|
26999
27017
|
try {
|
|
27000
27018
|
p.unref();
|
|
27001
27019
|
} catch {}
|
|
27002
|
-
|
|
27020
|
+
resolve24(true);
|
|
27003
27021
|
});
|
|
27004
27022
|
} catch {
|
|
27005
|
-
|
|
27023
|
+
resolve24(false);
|
|
27006
27024
|
}
|
|
27007
27025
|
});
|
|
27008
27026
|
}
|
|
@@ -27014,18 +27032,18 @@ async function runLoopbackOAuth(cfg, opts = {}) {
|
|
|
27014
27032
|
const state = crypto2.randomBytes(16).toString("hex");
|
|
27015
27033
|
let server = null;
|
|
27016
27034
|
let timer = null;
|
|
27017
|
-
const closeServer = () => new Promise((
|
|
27035
|
+
const closeServer = () => new Promise((resolve24) => {
|
|
27018
27036
|
if (!server)
|
|
27019
|
-
return
|
|
27037
|
+
return resolve24();
|
|
27020
27038
|
const s = server;
|
|
27021
27039
|
server = null;
|
|
27022
|
-
s.close(() =>
|
|
27040
|
+
s.close(() => resolve24());
|
|
27023
27041
|
try {
|
|
27024
27042
|
s.unref();
|
|
27025
27043
|
} catch {}
|
|
27026
27044
|
});
|
|
27027
27045
|
try {
|
|
27028
|
-
const { code, redirectUri } = await new Promise((
|
|
27046
|
+
const { code, redirectUri } = await new Promise((resolve24, reject) => {
|
|
27029
27047
|
server = http.createServer((req, res) => {
|
|
27030
27048
|
try {
|
|
27031
27049
|
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -27054,7 +27072,7 @@ async function runLoopbackOAuth(cfg, opts = {}) {
|
|
|
27054
27072
|
}
|
|
27055
27073
|
renderHtml(res, 200, "Authorization complete", "Authorization complete. You can close this tab and return to the terminal.");
|
|
27056
27074
|
const hostHeader = req.headers.host ?? `${host}:?`;
|
|
27057
|
-
|
|
27075
|
+
resolve24({
|
|
27058
27076
|
code: gotCode,
|
|
27059
27077
|
redirectUri: `http://${hostHeader}`
|
|
27060
27078
|
});
|
|
@@ -27465,7 +27483,7 @@ var init_client3 = __esm(() => {
|
|
|
27465
27483
|
|
|
27466
27484
|
// src/vault/approvals/wait.ts
|
|
27467
27485
|
function defaultSleep(ms, signal) {
|
|
27468
|
-
return new Promise((
|
|
27486
|
+
return new Promise((resolve24, reject) => {
|
|
27469
27487
|
if (signal?.aborted) {
|
|
27470
27488
|
reject(new DOMException("Aborted", "AbortError"));
|
|
27471
27489
|
return;
|
|
@@ -27476,7 +27494,7 @@ function defaultSleep(ms, signal) {
|
|
|
27476
27494
|
};
|
|
27477
27495
|
const timer = setTimeout(() => {
|
|
27478
27496
|
signal?.removeEventListener("abort", onAbort);
|
|
27479
|
-
|
|
27497
|
+
resolve24();
|
|
27480
27498
|
}, ms);
|
|
27481
27499
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
27482
27500
|
});
|
|
@@ -27629,7 +27647,7 @@ function getVaultPath(configPath) {
|
|
|
27629
27647
|
}
|
|
27630
27648
|
}
|
|
27631
27649
|
function promptHidden(prompt) {
|
|
27632
|
-
return new Promise((
|
|
27650
|
+
return new Promise((resolve24, reject) => {
|
|
27633
27651
|
const rl = createInterface2({
|
|
27634
27652
|
input: process.stdin,
|
|
27635
27653
|
output: process.stdout
|
|
@@ -27649,7 +27667,7 @@ function promptHidden(prompt) {
|
|
|
27649
27667
|
rl.close();
|
|
27650
27668
|
process.stdout.write(`
|
|
27651
27669
|
`);
|
|
27652
|
-
|
|
27670
|
+
resolve24(input);
|
|
27653
27671
|
} else if (char === "\x03") {
|
|
27654
27672
|
stdin.setRawMode(false);
|
|
27655
27673
|
stdin.removeListener("data", onData);
|
|
@@ -27668,20 +27686,20 @@ function promptHidden(prompt) {
|
|
|
27668
27686
|
} else {
|
|
27669
27687
|
rl.question(prompt, (answer) => {
|
|
27670
27688
|
rl.close();
|
|
27671
|
-
|
|
27689
|
+
resolve24(answer);
|
|
27672
27690
|
});
|
|
27673
27691
|
}
|
|
27674
27692
|
});
|
|
27675
27693
|
}
|
|
27676
27694
|
function promptLine(prompt) {
|
|
27677
|
-
return new Promise((
|
|
27695
|
+
return new Promise((resolve24) => {
|
|
27678
27696
|
const rl = createInterface2({
|
|
27679
27697
|
input: process.stdin,
|
|
27680
27698
|
output: process.stdout
|
|
27681
27699
|
});
|
|
27682
27700
|
rl.question(prompt, (answer) => {
|
|
27683
27701
|
rl.close();
|
|
27684
|
-
|
|
27702
|
+
resolve24(answer);
|
|
27685
27703
|
});
|
|
27686
27704
|
});
|
|
27687
27705
|
}
|
|
@@ -28238,18 +28256,18 @@ async function openBrowser2(url, platform = process.platform, spawnImpl = spawn3
|
|
|
28238
28256
|
cmd = "xdg-open";
|
|
28239
28257
|
args = [url];
|
|
28240
28258
|
}
|
|
28241
|
-
return new Promise((
|
|
28259
|
+
return new Promise((resolve24) => {
|
|
28242
28260
|
try {
|
|
28243
28261
|
const p = spawnImpl(cmd, args, { stdio: "ignore", detached: true });
|
|
28244
|
-
p.once("error", () =>
|
|
28262
|
+
p.once("error", () => resolve24(false));
|
|
28245
28263
|
p.once("spawn", () => {
|
|
28246
28264
|
try {
|
|
28247
28265
|
p.unref();
|
|
28248
28266
|
} catch {}
|
|
28249
|
-
|
|
28267
|
+
resolve24(true);
|
|
28250
28268
|
});
|
|
28251
28269
|
} catch {
|
|
28252
|
-
|
|
28270
|
+
resolve24(false);
|
|
28253
28271
|
}
|
|
28254
28272
|
});
|
|
28255
28273
|
}
|
|
@@ -28262,18 +28280,18 @@ async function runLoopbackOAuth2(cfg, opts = {}) {
|
|
|
28262
28280
|
const { verifier, challenge } = generatePkcePair();
|
|
28263
28281
|
let server = null;
|
|
28264
28282
|
let timer = null;
|
|
28265
|
-
const closeServer = () => new Promise((
|
|
28283
|
+
const closeServer = () => new Promise((resolve24) => {
|
|
28266
28284
|
if (!server)
|
|
28267
|
-
return
|
|
28285
|
+
return resolve24();
|
|
28268
28286
|
const s = server;
|
|
28269
28287
|
server = null;
|
|
28270
|
-
s.close(() =>
|
|
28288
|
+
s.close(() => resolve24());
|
|
28271
28289
|
try {
|
|
28272
28290
|
s.unref();
|
|
28273
28291
|
} catch {}
|
|
28274
28292
|
});
|
|
28275
28293
|
try {
|
|
28276
|
-
const { code, redirectUri } = await new Promise((
|
|
28294
|
+
const { code, redirectUri } = await new Promise((resolve24, reject) => {
|
|
28277
28295
|
server = http2.createServer((req, res) => {
|
|
28278
28296
|
try {
|
|
28279
28297
|
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -28303,7 +28321,7 @@ async function runLoopbackOAuth2(cfg, opts = {}) {
|
|
|
28303
28321
|
}
|
|
28304
28322
|
renderHtml2(res, 200, "Microsoft authorization complete", "You can close this tab and return to the terminal.");
|
|
28305
28323
|
const hostHeader = req.headers.host ?? `${host}:?`;
|
|
28306
|
-
|
|
28324
|
+
resolve24({
|
|
28307
28325
|
code: gotCode,
|
|
28308
28326
|
redirectUri: `http://${hostHeader}`
|
|
28309
28327
|
});
|
|
@@ -28460,7 +28478,7 @@ __export(exports_via_claude, {
|
|
|
28460
28478
|
});
|
|
28461
28479
|
import { execFileSync as execFileSync14, spawnSync as spawnSync2 } from "node:child_process";
|
|
28462
28480
|
import { existsSync as existsSync32, mkdirSync as mkdirSync19, readFileSync as readFileSync27 } from "node:fs";
|
|
28463
|
-
import { join as join25, resolve as
|
|
28481
|
+
import { join as join25, resolve as resolve24 } from "node:path";
|
|
28464
28482
|
function tmuxHasSession(session) {
|
|
28465
28483
|
const r = spawnSync2("tmux", ["has-session", "-t", session], {
|
|
28466
28484
|
stdio: ["ignore", "ignore", "ignore"]
|
|
@@ -28504,7 +28522,7 @@ async function runViaClaude(opts) {
|
|
|
28504
28522
|
const urlTimeout = opts.urlTimeoutMs ?? VIA_CLAUDE_DEFAULTS.urlTimeoutMs;
|
|
28505
28523
|
const credsTimeout = opts.credentialsTimeoutMs ?? VIA_CLAUDE_DEFAULTS.credentialsTimeoutMs;
|
|
28506
28524
|
const poll = opts.pollMs ?? VIA_CLAUDE_DEFAULTS.pollMs;
|
|
28507
|
-
const configDir =
|
|
28525
|
+
const configDir = resolve24(opts.configDir);
|
|
28508
28526
|
mkdirSync19(configDir, { recursive: true });
|
|
28509
28527
|
const credentialsPath2 = join25(configDir, ".credentials.json");
|
|
28510
28528
|
const capture = opts.capturePane ?? (() => tmuxCapturePane(SESSION));
|
|
@@ -29281,7 +29299,7 @@ var init_audit_reader = () => {};
|
|
|
29281
29299
|
import { connect as connect2 } from "node:net";
|
|
29282
29300
|
async function hostdRequest(opts, req) {
|
|
29283
29301
|
const timeoutMs = opts.timeoutMs ?? 5000;
|
|
29284
|
-
return new Promise((
|
|
29302
|
+
return new Promise((resolve28, reject) => {
|
|
29285
29303
|
const socket = connect2(opts.socketPath);
|
|
29286
29304
|
let buf = "";
|
|
29287
29305
|
let settled = false;
|
|
@@ -29327,7 +29345,7 @@ async function hostdRequest(opts, req) {
|
|
|
29327
29345
|
settled = true;
|
|
29328
29346
|
clearTimeout(timer);
|
|
29329
29347
|
socket.end();
|
|
29330
|
-
|
|
29348
|
+
resolve28(resp);
|
|
29331
29349
|
} catch (err) {
|
|
29332
29350
|
if (settled)
|
|
29333
29351
|
return;
|
|
@@ -29404,7 +29422,7 @@ import {
|
|
|
29404
29422
|
readFileSync as readFileSync48,
|
|
29405
29423
|
readdirSync as readdirSync19
|
|
29406
29424
|
} from "node:fs";
|
|
29407
|
-
import { dirname as
|
|
29425
|
+
import { dirname as dirname13, join as join48 } from "node:path";
|
|
29408
29426
|
import { execSync as execSync2 } from "node:child_process";
|
|
29409
29427
|
function locateManifestPath() {
|
|
29410
29428
|
let dir = import.meta.dirname;
|
|
@@ -29412,7 +29430,7 @@ function locateManifestPath() {
|
|
|
29412
29430
|
const candidate = join48(dir, "dependencies.json");
|
|
29413
29431
|
if (existsSync52(candidate))
|
|
29414
29432
|
return candidate;
|
|
29415
|
-
dir =
|
|
29433
|
+
dir = dirname13(dir);
|
|
29416
29434
|
}
|
|
29417
29435
|
return null;
|
|
29418
29436
|
}
|
|
@@ -30512,7 +30530,7 @@ import {
|
|
|
30512
30530
|
existsSync as realExistsSync,
|
|
30513
30531
|
readFileSync as realReadFileSync
|
|
30514
30532
|
} from "node:fs";
|
|
30515
|
-
import { join as join51, resolve as
|
|
30533
|
+
import { join as join51, resolve as resolve31 } from "node:path";
|
|
30516
30534
|
import { homedir as homedir29 } from "node:os";
|
|
30517
30535
|
function resolveDeps(config, deps) {
|
|
30518
30536
|
let agentsDir = deps.agentsDir;
|
|
@@ -30627,7 +30645,7 @@ function checkScaffoldWiring(config, driveAgents, d) {
|
|
|
30627
30645
|
];
|
|
30628
30646
|
}
|
|
30629
30647
|
for (const name of driveAgents) {
|
|
30630
|
-
const agentDir =
|
|
30648
|
+
const agentDir = resolve31(d.agentsDir, name);
|
|
30631
30649
|
if (!d.existsSync(agentDir)) {
|
|
30632
30650
|
results.push({
|
|
30633
30651
|
name: `drive: ${name} scaffold`,
|
|
@@ -30665,7 +30683,7 @@ function checkScaffoldWiring(config, driveAgents, d) {
|
|
|
30665
30683
|
let trustOk = false;
|
|
30666
30684
|
let trustDetail = "no .claude/.claude.json";
|
|
30667
30685
|
if (trustRead.kind === "ok") {
|
|
30668
|
-
const proj = trustRead.data?.projects?.[
|
|
30686
|
+
const proj = trustRead.data?.projects?.[resolve31(agentDir)];
|
|
30669
30687
|
const enabled = proj?.enabledMcpjsonServers;
|
|
30670
30688
|
if (Array.isArray(enabled) && enabled.includes("gdrive")) {
|
|
30671
30689
|
trustOk = true;
|
|
@@ -30990,7 +31008,7 @@ var init_doctor_webkite = __esm(() => {
|
|
|
30990
31008
|
|
|
30991
31009
|
// src/cli/doctor-cron-session.ts
|
|
30992
31010
|
import { statSync as realStatSync } from "node:fs";
|
|
30993
|
-
import { resolve as
|
|
31011
|
+
import { resolve as resolve32 } from "node:path";
|
|
30994
31012
|
function agentRunsCronSession(config, agent) {
|
|
30995
31013
|
const raw = config.agents[agent];
|
|
30996
31014
|
if (!raw)
|
|
@@ -31006,7 +31024,7 @@ function runCronSessionChecks(config, deps = defaultDeps2) {
|
|
|
31006
31024
|
if (!agentRunsCronSession(config, agent))
|
|
31007
31025
|
continue;
|
|
31008
31026
|
const name = `cron-session: ${agent}`;
|
|
31009
|
-
const alivePath =
|
|
31027
|
+
const alivePath = resolve32(agentsDir, agent, "telegram", ".bridge-alive-cron");
|
|
31010
31028
|
let mtimeMs;
|
|
31011
31029
|
try {
|
|
31012
31030
|
mtimeMs = deps.statMtimeMs(alivePath);
|
|
@@ -31055,7 +31073,7 @@ var init_doctor_cron_session = __esm(() => {
|
|
|
31055
31073
|
});
|
|
31056
31074
|
|
|
31057
31075
|
// src/cli/doctor-scaffold-wiring.ts
|
|
31058
|
-
import { join as join53, resolve as
|
|
31076
|
+
import { join as join53, resolve as resolve33 } from "node:path";
|
|
31059
31077
|
function readJson2(d, path4) {
|
|
31060
31078
|
if (!d.existsSync(path4))
|
|
31061
31079
|
return { kind: "absent" };
|
|
@@ -31089,7 +31107,7 @@ function checkIntegrationScaffoldWiring(args) {
|
|
|
31089
31107
|
];
|
|
31090
31108
|
}
|
|
31091
31109
|
for (const name of agents) {
|
|
31092
|
-
const agentDir =
|
|
31110
|
+
const agentDir = resolve33(agentsDir, name);
|
|
31093
31111
|
if (!deps.existsSync(agentDir)) {
|
|
31094
31112
|
results.push({
|
|
31095
31113
|
name: `${label}: ${name} scaffold`,
|
|
@@ -31129,7 +31147,7 @@ function checkIntegrationScaffoldWiring(args) {
|
|
|
31129
31147
|
let trustDetail = "no .claude/.claude.json";
|
|
31130
31148
|
if (trustRead.kind === "ok") {
|
|
31131
31149
|
const projects = trustRead.data?.projects ?? {};
|
|
31132
|
-
const proj = projects[
|
|
31150
|
+
const proj = projects[resolve33(agentDir)];
|
|
31133
31151
|
const enabled = proj?.enabledMcpjsonServers;
|
|
31134
31152
|
if (Array.isArray(enabled) && enabled.includes(mcpKey)) {
|
|
31135
31153
|
trustOk = true;
|
|
@@ -32202,13 +32220,13 @@ import {
|
|
|
32202
32220
|
accessSync as accessSync2,
|
|
32203
32221
|
constants as fsConstants5,
|
|
32204
32222
|
existsSync as existsSync57,
|
|
32205
|
-
lstatSync as
|
|
32223
|
+
lstatSync as lstatSync7,
|
|
32206
32224
|
mkdirSync as mkdirSync31,
|
|
32207
32225
|
readFileSync as readFileSync51,
|
|
32208
32226
|
readdirSync as readdirSync21,
|
|
32209
32227
|
statSync as statSync25
|
|
32210
32228
|
} from "node:fs";
|
|
32211
|
-
import { dirname as
|
|
32229
|
+
import { dirname as dirname14, join as join60, resolve as resolve34 } from "node:path";
|
|
32212
32230
|
import { createPublicKey, createPrivateKey } from "node:crypto";
|
|
32213
32231
|
function findInNvm(bin) {
|
|
32214
32232
|
const nvmRoot = join60(process.env.HOME ?? "", ".nvm", "versions", "node");
|
|
@@ -32529,7 +32547,7 @@ function checkLegacyState() {
|
|
|
32529
32547
|
const legacySock = join60(h, ".switchroom", "vault-broker.sock");
|
|
32530
32548
|
let sockStat = null;
|
|
32531
32549
|
try {
|
|
32532
|
-
sockStat =
|
|
32550
|
+
sockStat = lstatSync7(legacySock);
|
|
32533
32551
|
} catch {}
|
|
32534
32552
|
if (sockStat) {
|
|
32535
32553
|
results.push({
|
|
@@ -33121,7 +33139,7 @@ function checkLeakedHomeSwitchroom(agentName, agentDir) {
|
|
|
33121
33139
|
const path4 = join60(agentDir, "home", ".switchroom");
|
|
33122
33140
|
let stats;
|
|
33123
33141
|
try {
|
|
33124
|
-
stats =
|
|
33142
|
+
stats = lstatSync7(path4);
|
|
33125
33143
|
} catch (err) {
|
|
33126
33144
|
if (err.code === "ENOENT") {
|
|
33127
33145
|
return {
|
|
@@ -33222,7 +33240,7 @@ function checkAgents(config, configPath) {
|
|
|
33222
33240
|
const statuses = getAllAgentStatuses(config);
|
|
33223
33241
|
const authStatuses = getAllAuthStatuses(config);
|
|
33224
33242
|
for (const [name, agentConfig] of Object.entries(config.agents)) {
|
|
33225
|
-
const agentDir =
|
|
33243
|
+
const agentDir = resolve34(agentsDir, name);
|
|
33226
33244
|
if (!existsSync57(agentDir)) {
|
|
33227
33245
|
results.push({
|
|
33228
33246
|
name: `${name}: scaffold`,
|
|
@@ -33405,7 +33423,7 @@ function mffAgentName(config) {
|
|
|
33405
33423
|
function mffEnvPath(config) {
|
|
33406
33424
|
const home2 = process.env.HOME ?? "/root";
|
|
33407
33425
|
const agent = mffAgentName(config);
|
|
33408
|
-
return agent ?
|
|
33426
|
+
return agent ? resolve34(home2, ".switchroom/credentials", agent, "my-family-finance/.env") : resolve34(home2, ".switchroom/credentials/my-family-finance/.env");
|
|
33409
33427
|
}
|
|
33410
33428
|
function mffEnvState(envPath) {
|
|
33411
33429
|
if (!existsSync57(envPath))
|
|
@@ -33622,7 +33640,7 @@ async function checkMffAuthFlow(envPath = mffEnvPath(), timeoutMs = 8000) {
|
|
|
33622
33640
|
detail: "skipped (MFF_API_URL not set)"
|
|
33623
33641
|
};
|
|
33624
33642
|
}
|
|
33625
|
-
const credDir =
|
|
33643
|
+
const credDir = dirname14(envPath);
|
|
33626
33644
|
const authScript = join60(credDir, "claude-auth.py");
|
|
33627
33645
|
if (!existsSync57(authScript)) {
|
|
33628
33646
|
return {
|
|
@@ -33821,14 +33839,14 @@ async function checkManifestDrift(probers) {
|
|
|
33821
33839
|
return results;
|
|
33822
33840
|
}
|
|
33823
33841
|
function runDockerSection(config) {
|
|
33824
|
-
const composePath =
|
|
33842
|
+
const composePath = resolve34(process.env.HOME ?? "", ".switchroom", "compose", "docker-compose.yml");
|
|
33825
33843
|
const active = isDockerMode({ composePath });
|
|
33826
33844
|
let composeYaml;
|
|
33827
33845
|
let dockerfileAgent;
|
|
33828
33846
|
try {
|
|
33829
33847
|
composeYaml = readFileSync51(composePath, "utf8");
|
|
33830
33848
|
} catch {}
|
|
33831
|
-
const dockerfilePath =
|
|
33849
|
+
const dockerfilePath = resolve34(process.env.HOME ?? "", ".switchroom", "docker", "Dockerfile.agent");
|
|
33832
33850
|
try {
|
|
33833
33851
|
dockerfileAgent = readFileSync51(dockerfilePath, "utf8");
|
|
33834
33852
|
} catch {}
|
|
@@ -42201,7 +42219,7 @@ class Protocol {
|
|
|
42201
42219
|
return;
|
|
42202
42220
|
}
|
|
42203
42221
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
|
|
42204
|
-
await new Promise((
|
|
42222
|
+
await new Promise((resolve51) => setTimeout(resolve51, pollInterval));
|
|
42205
42223
|
options?.signal?.throwIfAborted();
|
|
42206
42224
|
}
|
|
42207
42225
|
} catch (error2) {
|
|
@@ -42213,7 +42231,7 @@ class Protocol {
|
|
|
42213
42231
|
}
|
|
42214
42232
|
request(request, resultSchema, options) {
|
|
42215
42233
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
42216
|
-
return new Promise((
|
|
42234
|
+
return new Promise((resolve51, reject) => {
|
|
42217
42235
|
const earlyReject = (error2) => {
|
|
42218
42236
|
reject(error2);
|
|
42219
42237
|
};
|
|
@@ -42291,7 +42309,7 @@ class Protocol {
|
|
|
42291
42309
|
if (!parseResult.success) {
|
|
42292
42310
|
reject(parseResult.error);
|
|
42293
42311
|
} else {
|
|
42294
|
-
|
|
42312
|
+
resolve51(parseResult.data);
|
|
42295
42313
|
}
|
|
42296
42314
|
} catch (error2) {
|
|
42297
42315
|
reject(error2);
|
|
@@ -42482,12 +42500,12 @@ class Protocol {
|
|
|
42482
42500
|
interval = task.pollInterval;
|
|
42483
42501
|
}
|
|
42484
42502
|
} catch {}
|
|
42485
|
-
return new Promise((
|
|
42503
|
+
return new Promise((resolve51, reject) => {
|
|
42486
42504
|
if (signal.aborted) {
|
|
42487
42505
|
reject(new McpError(ErrorCode2.InvalidRequest, "Request cancelled"));
|
|
42488
42506
|
return;
|
|
42489
42507
|
}
|
|
42490
|
-
const timeoutId = setTimeout(
|
|
42508
|
+
const timeoutId = setTimeout(resolve51, interval);
|
|
42491
42509
|
signal.addEventListener("abort", () => {
|
|
42492
42510
|
clearTimeout(timeoutId);
|
|
42493
42511
|
reject(new McpError(ErrorCode2.InvalidRequest, "Request cancelled"));
|
|
@@ -45472,7 +45490,7 @@ var require_compile = __commonJS((exports2) => {
|
|
|
45472
45490
|
const schOrFunc = root.refs[ref];
|
|
45473
45491
|
if (schOrFunc)
|
|
45474
45492
|
return schOrFunc;
|
|
45475
|
-
let _sch =
|
|
45493
|
+
let _sch = resolve51.call(this, root, ref);
|
|
45476
45494
|
if (_sch === undefined) {
|
|
45477
45495
|
const schema = (_a = root.localRefs) === null || _a === undefined ? undefined : _a[ref];
|
|
45478
45496
|
const { schemaId } = this.opts;
|
|
@@ -45499,7 +45517,7 @@ var require_compile = __commonJS((exports2) => {
|
|
|
45499
45517
|
function sameSchemaEnv(s1, s2) {
|
|
45500
45518
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
45501
45519
|
}
|
|
45502
|
-
function
|
|
45520
|
+
function resolve51(root, ref) {
|
|
45503
45521
|
let sch;
|
|
45504
45522
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
45505
45523
|
ref = sch;
|
|
@@ -46029,7 +46047,7 @@ var require_fast_uri = __commonJS((exports2, module) => {
|
|
|
46029
46047
|
}
|
|
46030
46048
|
return uri;
|
|
46031
46049
|
}
|
|
46032
|
-
function
|
|
46050
|
+
function resolve51(baseURI, relativeURI, options) {
|
|
46033
46051
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
46034
46052
|
const resolved = resolveComponent(parse6(baseURI, schemelessOptions), parse6(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
46035
46053
|
schemelessOptions.skipEscape = true;
|
|
@@ -46257,7 +46275,7 @@ var require_fast_uri = __commonJS((exports2, module) => {
|
|
|
46257
46275
|
var fastUri = {
|
|
46258
46276
|
SCHEMES,
|
|
46259
46277
|
normalize,
|
|
46260
|
-
resolve:
|
|
46278
|
+
resolve: resolve51,
|
|
46261
46279
|
resolveComponent,
|
|
46262
46280
|
equal,
|
|
46263
46281
|
serialize,
|
|
@@ -49640,12 +49658,12 @@ class StdioServerTransport {
|
|
|
49640
49658
|
this.onclose?.();
|
|
49641
49659
|
}
|
|
49642
49660
|
send(message) {
|
|
49643
|
-
return new Promise((
|
|
49661
|
+
return new Promise((resolve51) => {
|
|
49644
49662
|
const json = serializeMessage(message);
|
|
49645
49663
|
if (this._stdout.write(json)) {
|
|
49646
|
-
|
|
49664
|
+
resolve51();
|
|
49647
49665
|
} else {
|
|
49648
|
-
this._stdout.once("drain",
|
|
49666
|
+
this._stdout.once("drain", resolve51);
|
|
49649
49667
|
}
|
|
49650
49668
|
});
|
|
49651
49669
|
}
|
|
@@ -50574,12 +50592,12 @@ var {
|
|
|
50574
50592
|
} = import__.default;
|
|
50575
50593
|
|
|
50576
50594
|
// src/build-info.ts
|
|
50577
|
-
var VERSION = "0.15.
|
|
50578
|
-
var COMMIT_SHA = "
|
|
50595
|
+
var VERSION = "0.15.36";
|
|
50596
|
+
var COMMIT_SHA = "18736aec";
|
|
50579
50597
|
|
|
50580
50598
|
// src/cli/agent.ts
|
|
50581
50599
|
init_source();
|
|
50582
|
-
import { join as join20, resolve as
|
|
50600
|
+
import { join as join20, resolve as resolve22 } from "node:path";
|
|
50583
50601
|
import { rmSync as rmSync9, existsSync as existsSync28, readFileSync as readFileSync23, writeFileSync as writeFileSync13 } from "node:fs";
|
|
50584
50602
|
import { homedir as homedir8 } from "node:os";
|
|
50585
50603
|
|
|
@@ -54523,7 +54541,7 @@ init_compose();
|
|
|
54523
54541
|
import { chownSync as chownSync2 } from "node:fs";
|
|
54524
54542
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
54525
54543
|
import { homedir as homedir6 } from "node:os";
|
|
54526
|
-
import { basename as basename4, dirname as
|
|
54544
|
+
import { basename as basename4, dirname as dirname4, join as join12 } from "node:path";
|
|
54527
54545
|
|
|
54528
54546
|
// src/config/release-resolve.ts
|
|
54529
54547
|
function resolveImageTag(release) {
|
|
@@ -54544,11 +54562,28 @@ function resolveRelease(opts) {
|
|
|
54544
54562
|
return opts.root;
|
|
54545
54563
|
return;
|
|
54546
54564
|
}
|
|
54565
|
+
function parseSemverTag(tag) {
|
|
54566
|
+
if (!tag)
|
|
54567
|
+
return null;
|
|
54568
|
+
const m = /^v(\d+)\.(\d+)\.(\d+)$/.exec(tag.trim());
|
|
54569
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
54570
|
+
}
|
|
54571
|
+
function compareReleaseTags(a, b) {
|
|
54572
|
+
const pa = parseSemverTag(a);
|
|
54573
|
+
const pb = parseSemverTag(b);
|
|
54574
|
+
if (!pa || !pb)
|
|
54575
|
+
return null;
|
|
54576
|
+
for (let i = 0;i < 3; i++) {
|
|
54577
|
+
if (pa[i] !== pb[i])
|
|
54578
|
+
return pa[i] < pb[i] ? -1 : 1;
|
|
54579
|
+
}
|
|
54580
|
+
return 0;
|
|
54581
|
+
}
|
|
54547
54582
|
// src/cli/operator-uid.ts
|
|
54548
54583
|
import {
|
|
54549
54584
|
chownSync,
|
|
54550
54585
|
existsSync as existsSync16,
|
|
54551
|
-
lstatSync as
|
|
54586
|
+
lstatSync as lstatSync5,
|
|
54552
54587
|
readdirSync as readdirSync7,
|
|
54553
54588
|
realpathSync as realpathSync3,
|
|
54554
54589
|
statSync as statSync8
|
|
@@ -54584,7 +54619,7 @@ function restoreOperatorOwnership(home2, operatorUid, deps = {}) {
|
|
|
54584
54619
|
const exists = deps.exists ?? ((p) => existsSync16(p));
|
|
54585
54620
|
const isSymlink = deps.isSymlink ?? ((p) => {
|
|
54586
54621
|
try {
|
|
54587
|
-
return
|
|
54622
|
+
return lstatSync5(p).isSymbolicLink();
|
|
54588
54623
|
} catch {
|
|
54589
54624
|
return false;
|
|
54590
54625
|
}
|
|
@@ -54676,7 +54711,7 @@ async function writeComposeFile(opts) {
|
|
|
54676
54711
|
previous = null;
|
|
54677
54712
|
}
|
|
54678
54713
|
const previousImageTag = previous ? AGENT_IMAGE_TAG_RE.exec(previous)?.[1] ?? null : null;
|
|
54679
|
-
await mkdir(
|
|
54714
|
+
await mkdir(dirname4(opts.composePath), { recursive: true });
|
|
54680
54715
|
await writeFile(opts.composePath, content, { encoding: "utf8", mode: 384 });
|
|
54681
54716
|
if (operatorUid !== undefined && process.geteuid?.() === 0) {
|
|
54682
54717
|
try {
|
|
@@ -54698,7 +54733,7 @@ init_merge();
|
|
|
54698
54733
|
|
|
54699
54734
|
// src/agents/in-flight.ts
|
|
54700
54735
|
import { readdirSync as readdirSync8, statSync as statSync9 } from "node:fs";
|
|
54701
|
-
import { resolve as
|
|
54736
|
+
import { resolve as resolve15 } from "node:path";
|
|
54702
54737
|
var DEFAULT_RECENCY_MS = 30000;
|
|
54703
54738
|
function safeReaddir(path) {
|
|
54704
54739
|
try {
|
|
@@ -54725,7 +54760,7 @@ function collectJsonl(root, maxDepth = 4) {
|
|
|
54725
54760
|
while (stack.length > 0) {
|
|
54726
54761
|
const { dir, depth } = stack.pop();
|
|
54727
54762
|
for (const entry of safeReaddir(dir)) {
|
|
54728
|
-
const full =
|
|
54763
|
+
const full = resolve15(dir, entry);
|
|
54729
54764
|
let isDir = false;
|
|
54730
54765
|
try {
|
|
54731
54766
|
isDir = statSync9(full).isDirectory();
|
|
@@ -54753,16 +54788,16 @@ function detectInFlight(opts) {
|
|
|
54753
54788
|
lastActivityMs: 0,
|
|
54754
54789
|
details: []
|
|
54755
54790
|
};
|
|
54756
|
-
const tasksRoot =
|
|
54791
|
+
const tasksRoot = resolve15(opts.agentDir, ".claude", "tasks");
|
|
54757
54792
|
for (const sessionId of safeReaddir(tasksRoot)) {
|
|
54758
|
-
const sessionDir =
|
|
54793
|
+
const sessionDir = resolve15(tasksRoot, sessionId);
|
|
54759
54794
|
let sessionHasRecent = false;
|
|
54760
54795
|
let newestSubject = null;
|
|
54761
54796
|
let newestMtime = 0;
|
|
54762
54797
|
for (const entry of safeReaddir(sessionDir)) {
|
|
54763
54798
|
if (!entry.endsWith(".json"))
|
|
54764
54799
|
continue;
|
|
54765
|
-
const mtime = safeMtimeMs(
|
|
54800
|
+
const mtime = safeMtimeMs(resolve15(sessionDir, entry));
|
|
54766
54801
|
if (mtime > result.lastActivityMs)
|
|
54767
54802
|
result.lastActivityMs = mtime;
|
|
54768
54803
|
if (isRecent(mtime, cutoff)) {
|
|
@@ -54778,9 +54813,9 @@ function detectInFlight(opts) {
|
|
|
54778
54813
|
result.details.push(`session ${sessionId.slice(0, 8)} task ${newestSubject ?? "?"}`);
|
|
54779
54814
|
}
|
|
54780
54815
|
}
|
|
54781
|
-
const projectsRoot =
|
|
54816
|
+
const projectsRoot = resolve15(opts.agentDir, ".claude", "projects");
|
|
54782
54817
|
for (const slug of safeReaddir(projectsRoot)) {
|
|
54783
|
-
const slugDir =
|
|
54818
|
+
const slugDir = resolve15(projectsRoot, slug);
|
|
54784
54819
|
for (const jsonl of collectJsonl(slugDir, 4)) {
|
|
54785
54820
|
const mtime = safeMtimeMs(jsonl);
|
|
54786
54821
|
if (mtime > result.lastActivityMs)
|
|
@@ -54831,11 +54866,11 @@ async function ask(question, defaultValue) {
|
|
|
54831
54866
|
throw new Error(`Non-interactive mode: no default for "${question}"`);
|
|
54832
54867
|
}
|
|
54833
54868
|
const rl = createReadlineInterface();
|
|
54834
|
-
return new Promise((
|
|
54869
|
+
return new Promise((resolve16) => {
|
|
54835
54870
|
const suffix = defaultValue ? ` [${defaultValue}]` : "";
|
|
54836
54871
|
rl.question(`${question}${suffix}: `, (answer) => {
|
|
54837
54872
|
rl.close();
|
|
54838
|
-
|
|
54873
|
+
resolve16(answer.trim() || defaultValue || "");
|
|
54839
54874
|
});
|
|
54840
54875
|
});
|
|
54841
54876
|
}
|
|
@@ -54845,14 +54880,14 @@ async function askYesNo(question, defaultYes = true) {
|
|
|
54845
54880
|
}
|
|
54846
54881
|
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
54847
54882
|
const rl = createReadlineInterface();
|
|
54848
|
-
return new Promise((
|
|
54883
|
+
return new Promise((resolve16) => {
|
|
54849
54884
|
rl.question(`${question} ${hint} `, (answer) => {
|
|
54850
54885
|
rl.close();
|
|
54851
54886
|
const normalized = answer.trim().toLowerCase();
|
|
54852
54887
|
if (normalized === "") {
|
|
54853
|
-
|
|
54888
|
+
resolve16(defaultYes);
|
|
54854
54889
|
} else {
|
|
54855
|
-
|
|
54890
|
+
resolve16(normalized === "y" || normalized === "yes");
|
|
54856
54891
|
}
|
|
54857
54892
|
});
|
|
54858
54893
|
});
|
|
@@ -54867,14 +54902,14 @@ ${question}`);
|
|
|
54867
54902
|
console.log(` ${i + 1}) ${choices[i]}`);
|
|
54868
54903
|
}
|
|
54869
54904
|
const rl = createReadlineInterface();
|
|
54870
|
-
return new Promise((
|
|
54905
|
+
return new Promise((resolve16) => {
|
|
54871
54906
|
rl.question(`Enter choice [1-${choices.length}]: `, (answer) => {
|
|
54872
54907
|
rl.close();
|
|
54873
54908
|
const idx = parseInt(answer.trim(), 10) - 1;
|
|
54874
54909
|
if (idx >= 0 && idx < choices.length) {
|
|
54875
|
-
|
|
54910
|
+
resolve16(choices[idx]);
|
|
54876
54911
|
} else {
|
|
54877
|
-
|
|
54912
|
+
resolve16(choices[0]);
|
|
54878
54913
|
}
|
|
54879
54914
|
});
|
|
54880
54915
|
});
|
|
@@ -54885,11 +54920,11 @@ async function waitForAction(message) {
|
|
|
54885
54920
|
return;
|
|
54886
54921
|
}
|
|
54887
54922
|
const rl = createReadlineInterface();
|
|
54888
|
-
return new Promise((
|
|
54923
|
+
return new Promise((resolve16) => {
|
|
54889
54924
|
rl.question(`${message}
|
|
54890
54925
|
Press Enter when ready...`, () => {
|
|
54891
54926
|
rl.close();
|
|
54892
|
-
|
|
54927
|
+
resolve16();
|
|
54893
54928
|
});
|
|
54894
54929
|
});
|
|
54895
54930
|
}
|
|
@@ -55772,7 +55807,7 @@ function readCacheTelemetry(agentDir) {
|
|
|
55772
55807
|
|
|
55773
55808
|
// src/agents/create-orchestrator.ts
|
|
55774
55809
|
init_loader();
|
|
55775
|
-
import { resolve as
|
|
55810
|
+
import { resolve as resolve17 } from "node:path";
|
|
55776
55811
|
import { existsSync as existsSync23, rmSync as rmSync6 } from "node:fs";
|
|
55777
55812
|
init_lifecycle();
|
|
55778
55813
|
init_manager();
|
|
@@ -55849,7 +55884,7 @@ async function pollForDmStart(token, timeoutMs = 120000) {
|
|
|
55849
55884
|
throw new Error("Timed out waiting for /start DM");
|
|
55850
55885
|
}
|
|
55851
55886
|
function sleep(ms) {
|
|
55852
|
-
return new Promise((
|
|
55887
|
+
return new Promise((resolve17) => setTimeout(resolve17, ms));
|
|
55853
55888
|
}
|
|
55854
55889
|
|
|
55855
55890
|
// src/agents/create-orchestrator.ts
|
|
@@ -55876,8 +55911,8 @@ async function createAgent(opts) {
|
|
|
55876
55911
|
const configPath = configPathOpt ?? (() => {
|
|
55877
55912
|
const cwd = process.cwd();
|
|
55878
55913
|
const candidates = [
|
|
55879
|
-
|
|
55880
|
-
|
|
55914
|
+
resolve17(cwd, "switchroom.yaml"),
|
|
55915
|
+
resolve17(cwd, "switchroom.yml")
|
|
55881
55916
|
];
|
|
55882
55917
|
for (const c of candidates) {
|
|
55883
55918
|
if (existsSync23(c))
|
|
@@ -55920,7 +55955,7 @@ async function createAgent(opts) {
|
|
|
55920
55955
|
throw new Error(`Internal: wrote agent "${name}" to yaml but reload didn't pick it up.`);
|
|
55921
55956
|
}
|
|
55922
55957
|
const agentsDir = resolveAgentsDir(config);
|
|
55923
|
-
const agentDir =
|
|
55958
|
+
const agentDir = resolve17(agentsDir, name);
|
|
55924
55959
|
await withRollback(() => {
|
|
55925
55960
|
scaffoldAgent(name, agentConfig, agentsDir, config.telegram, config, undefined, configPath);
|
|
55926
55961
|
rollbackStack.push(() => rmSync6(agentDir, { recursive: true, force: true }));
|
|
@@ -55941,7 +55976,7 @@ async function completeCreation(name, code, opts = {}) {
|
|
|
55941
55976
|
}
|
|
55942
55977
|
const configPath = opts.configPath ?? (() => {
|
|
55943
55978
|
const cwd = process.cwd();
|
|
55944
|
-
const candidates = [
|
|
55979
|
+
const candidates = [resolve17(cwd, "switchroom.yaml"), resolve17(cwd, "switchroom.yml")];
|
|
55945
55980
|
for (const c of candidates)
|
|
55946
55981
|
if (existsSync23(c))
|
|
55947
55982
|
return c;
|
|
@@ -55949,7 +55984,7 @@ async function completeCreation(name, code, opts = {}) {
|
|
|
55949
55984
|
})();
|
|
55950
55985
|
const config = loadConfig(configPath);
|
|
55951
55986
|
const agentsDir = resolveAgentsDir(config);
|
|
55952
|
-
const agentDir =
|
|
55987
|
+
const agentDir = resolve17(agentsDir, name);
|
|
55953
55988
|
if (!existsSync23(agentDir)) {
|
|
55954
55989
|
throw new Error(`Agent dir not found: ${agentDir}. Run createAgent first.`);
|
|
55955
55990
|
}
|
|
@@ -55989,7 +56024,7 @@ async function completeCreation(name, code, opts = {}) {
|
|
|
55989
56024
|
}
|
|
55990
56025
|
|
|
55991
56026
|
// src/agents/add-orchestrator.ts
|
|
55992
|
-
import { resolve as
|
|
56027
|
+
import { resolve as resolve19, join as join18 } from "node:path";
|
|
55993
56028
|
import { existsSync as existsSync25, rmSync as rmSync7, statSync as statSync15 } from "node:fs";
|
|
55994
56029
|
import { execFileSync as execFileSync12 } from "node:child_process";
|
|
55995
56030
|
|
|
@@ -56082,7 +56117,7 @@ function enforceUsername(username, agentSlug, expectedUsername, loose, warn) {
|
|
|
56082
56117
|
|
|
56083
56118
|
// src/setup/profile-picker.ts
|
|
56084
56119
|
import { existsSync as existsSync24, readdirSync as readdirSync12, statSync as statSync14 } from "node:fs";
|
|
56085
|
-
import { resolve as
|
|
56120
|
+
import { resolve as resolve18 } from "node:path";
|
|
56086
56121
|
var PROFILE_GLOSSES = {
|
|
56087
56122
|
default: "minimal baseline \u2014 generic chat helper, no opinion.",
|
|
56088
56123
|
coding: "developer copilot \u2014 architecture + code-review skills.",
|
|
@@ -56090,16 +56125,16 @@ var PROFILE_GLOSSES = {
|
|
|
56090
56125
|
"health-coach": "wellness coach \u2014 daily check-ins, weekly reviews."
|
|
56091
56126
|
};
|
|
56092
56127
|
var DEFAULT_MAX_ATTEMPTS2 = 3;
|
|
56093
|
-
var PROFILES_ROOT2 =
|
|
56128
|
+
var PROFILES_ROOT2 = resolve18(import.meta.dirname, "../../profiles");
|
|
56094
56129
|
function defaultListProfileSkills(profileName) {
|
|
56095
|
-
const skillsDir =
|
|
56130
|
+
const skillsDir = resolve18(PROFILES_ROOT2, profileName, "skills");
|
|
56096
56131
|
if (!existsSync24(skillsDir)) {
|
|
56097
56132
|
return [];
|
|
56098
56133
|
}
|
|
56099
56134
|
try {
|
|
56100
56135
|
return readdirSync12(skillsDir).filter((entry) => {
|
|
56101
56136
|
try {
|
|
56102
|
-
return statSync14(
|
|
56137
|
+
return statSync14(resolve18(skillsDir, entry)).isDirectory();
|
|
56103
56138
|
} catch {
|
|
56104
56139
|
return false;
|
|
56105
56140
|
}
|
|
@@ -56378,7 +56413,7 @@ async function addAgent(opts) {
|
|
|
56378
56413
|
}
|
|
56379
56414
|
function runFinalPreflight(inputs) {
|
|
56380
56415
|
const { name, agentDir, expectedUserId, isUnitActive, configPath } = inputs;
|
|
56381
|
-
const unitPath =
|
|
56416
|
+
const unitPath = resolve19(process.env.HOME ?? "/root", ".config/systemd/user", `switchroom-${name}.service`);
|
|
56382
56417
|
let autoaccept = { ok: false, detail: `unit not found at ${unitPath}` };
|
|
56383
56418
|
if (existsSync25(unitPath)) {
|
|
56384
56419
|
const fs2 = __require("node:fs");
|
|
@@ -56397,7 +56432,7 @@ function runFinalPreflight(inputs) {
|
|
|
56397
56432
|
detail: `systemd unit missing at ${unitPath}. ` + `Fix: switchroom agent reconcile ${name}`
|
|
56398
56433
|
};
|
|
56399
56434
|
}
|
|
56400
|
-
const envPath =
|
|
56435
|
+
const envPath = resolve19(agentDir, "telegram", ".env");
|
|
56401
56436
|
let token = { ok: false, detail: `telegram/.env missing at ${envPath}` };
|
|
56402
56437
|
if (existsSync25(envPath)) {
|
|
56403
56438
|
const fs2 = __require("node:fs");
|
|
@@ -56425,7 +56460,7 @@ function runFinalPreflight(inputs) {
|
|
|
56425
56460
|
detail: `systemctl probe failed: ${err.message}`
|
|
56426
56461
|
};
|
|
56427
56462
|
}
|
|
56428
|
-
const accessPath =
|
|
56463
|
+
const accessPath = resolve19(agentDir, "telegram", "access.json");
|
|
56429
56464
|
let access;
|
|
56430
56465
|
if (!existsSync25(accessPath)) {
|
|
56431
56466
|
access = {
|
|
@@ -56452,7 +56487,7 @@ function runFinalPreflight(inputs) {
|
|
|
56452
56487
|
};
|
|
56453
56488
|
}
|
|
56454
56489
|
}
|
|
56455
|
-
const settingsPath =
|
|
56490
|
+
const settingsPath = resolve19(agentDir, ".claude", "settings.json");
|
|
56456
56491
|
let mcp;
|
|
56457
56492
|
if (!existsSync25(settingsPath)) {
|
|
56458
56493
|
mcp = {
|
|
@@ -56533,7 +56568,7 @@ function runFinalPreflight(inputs) {
|
|
|
56533
56568
|
};
|
|
56534
56569
|
}
|
|
56535
56570
|
function pruneBundledSkills(agentDir, keep, scope) {
|
|
56536
|
-
const skillsDir =
|
|
56571
|
+
const skillsDir = resolve19(agentDir, ".claude", "skills");
|
|
56537
56572
|
if (!existsSync25(skillsDir)) {
|
|
56538
56573
|
return [];
|
|
56539
56574
|
}
|
|
@@ -56581,7 +56616,7 @@ import { execFileSync as dockerExecFile } from "node:child_process";
|
|
|
56581
56616
|
init_loader();
|
|
56582
56617
|
init_vault();
|
|
56583
56618
|
init_lifecycle();
|
|
56584
|
-
import { resolve as
|
|
56619
|
+
import { resolve as resolve20 } from "node:path";
|
|
56585
56620
|
import {
|
|
56586
56621
|
existsSync as existsSync26,
|
|
56587
56622
|
mkdtempSync as mkdtempSync3,
|
|
@@ -56609,7 +56644,7 @@ function defaultDeps() {
|
|
|
56609
56644
|
saveVault,
|
|
56610
56645
|
resolveVaultPath: (config) => resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc"),
|
|
56611
56646
|
snapshotDir: (src) => {
|
|
56612
|
-
const tmp = mkdtempSync3(
|
|
56647
|
+
const tmp = mkdtempSync3(resolve20(tmpdir2(), "switchroom-rename-snap-"));
|
|
56613
56648
|
cpSync(src, tmp, { recursive: true });
|
|
56614
56649
|
return tmp;
|
|
56615
56650
|
},
|
|
@@ -56681,8 +56716,8 @@ async function renameAgent(opts, injectedDeps) {
|
|
|
56681
56716
|
if (config.agents[newName]) {
|
|
56682
56717
|
throw new Error(`Agent "${newName}" is already defined in switchroom.yaml. ` + `Choose a different name or remove the existing entry first.`);
|
|
56683
56718
|
}
|
|
56684
|
-
const oldAgentDir =
|
|
56685
|
-
const newAgentDir =
|
|
56719
|
+
const oldAgentDir = resolve20(agentsDir, oldName);
|
|
56720
|
+
const newAgentDir = resolve20(agentsDir, newName);
|
|
56686
56721
|
if (!_existsSync(oldAgentDir)) {
|
|
56687
56722
|
throw new Error(`Agent directory not found: ${oldAgentDir}. ` + `The agent may not have been scaffolded yet.`);
|
|
56688
56723
|
}
|
|
@@ -56819,7 +56854,7 @@ async function renameAgent(opts, injectedDeps) {
|
|
|
56819
56854
|
init_source();
|
|
56820
56855
|
init_helpers();
|
|
56821
56856
|
init_loader();
|
|
56822
|
-
import { resolve as
|
|
56857
|
+
import { resolve as resolve21 } from "node:path";
|
|
56823
56858
|
function registerAgentPerfCommand(agent) {
|
|
56824
56859
|
agent.command("perf <name>").description("Show cache-hit telemetry for an agent (cache_read / cache_creation per-turn from the latest session JSONL)").option("--last <n>", "Number of recent assistant turns to analyze", "20").option("--full", "Analyze every turn in the JSONL (overrides --last)").option("--json", "Output as JSON").action(withConfigError(async (name, opts) => {
|
|
56825
56860
|
const config = getConfig(program2(agent));
|
|
@@ -56829,8 +56864,8 @@ function registerAgentPerfCommand(agent) {
|
|
|
56829
56864
|
console.error(source_default.red(`Agent "${name}" is not defined in switchroom.yaml`));
|
|
56830
56865
|
process.exit(1);
|
|
56831
56866
|
}
|
|
56832
|
-
const agentDir =
|
|
56833
|
-
const claudeConfigDir =
|
|
56867
|
+
const agentDir = resolve21(agentsDir, name);
|
|
56868
|
+
const claudeConfigDir = resolve21(agentDir, ".claude");
|
|
56834
56869
|
const jsonl = findLatestSessionJsonl(claudeConfigDir);
|
|
56835
56870
|
if (!jsonl) {
|
|
56836
56871
|
if (opts.json) {
|
|
@@ -57031,11 +57066,11 @@ function checkQuarantineRefusal(agentsDir, name) {
|
|
|
57031
57066
|
}
|
|
57032
57067
|
function preflightCheck(name, agentDir, _usesDevChannels) {
|
|
57033
57068
|
const errors2 = [];
|
|
57034
|
-
const startSh =
|
|
57069
|
+
const startSh = resolve22(agentDir, "start.sh");
|
|
57035
57070
|
if (!existsSync28(startSh)) {
|
|
57036
57071
|
errors2.push(`start.sh not found at ${startSh}`);
|
|
57037
57072
|
}
|
|
57038
|
-
const envPath =
|
|
57073
|
+
const envPath = resolve22(agentDir, "telegram", ".env");
|
|
57039
57074
|
if (existsSync28(envPath)) {
|
|
57040
57075
|
const envContent = readFileSync23(envPath, "utf-8");
|
|
57041
57076
|
if (!envContent.includes("TELEGRAM_BOT_TOKEN=") || envContent.includes("# Set your bot token")) {
|
|
@@ -57044,13 +57079,13 @@ function preflightCheck(name, agentDir, _usesDevChannels) {
|
|
|
57044
57079
|
} else {
|
|
57045
57080
|
errors2.push(`telegram/.env not found at ${envPath}`);
|
|
57046
57081
|
}
|
|
57047
|
-
if (!existsSync28(
|
|
57082
|
+
if (!existsSync28(resolve22(agentDir, ".claude", "settings.json"))) {
|
|
57048
57083
|
errors2.push(`.claude/settings.json not found. Run: switchroom agent reconcile ${name}`);
|
|
57049
57084
|
}
|
|
57050
57085
|
return errors2;
|
|
57051
57086
|
}
|
|
57052
57087
|
function buildStatusInputs(name, config, agentsDir) {
|
|
57053
|
-
const agentDir =
|
|
57088
|
+
const agentDir = resolve22(agentsDir, name);
|
|
57054
57089
|
const agentConfig = config.agents[name];
|
|
57055
57090
|
let hindsightApiUrl = null;
|
|
57056
57091
|
let hindsightBankId = name;
|
|
@@ -57199,7 +57234,7 @@ async function reconcileAndRestartAgent(name, config, agentsDir, configPath, opt
|
|
|
57199
57234
|
}
|
|
57200
57235
|
}
|
|
57201
57236
|
if (!opts.force) {
|
|
57202
|
-
const envPath =
|
|
57237
|
+
const envPath = resolve22(agentsDir, name, "telegram", ".env");
|
|
57203
57238
|
if (existsSync28(envPath)) {
|
|
57204
57239
|
const envContent = readFileSync23(envPath, "utf-8");
|
|
57205
57240
|
const match = envContent.match(/^TELEGRAM_BOT_TOKEN=(.+)$/m);
|
|
@@ -57318,7 +57353,7 @@ function registerAgentCommand(program3) {
|
|
|
57318
57353
|
console.error(source_default.red(`Agent "${name}" is not defined in switchroom.yaml`));
|
|
57319
57354
|
process.exit(1);
|
|
57320
57355
|
}
|
|
57321
|
-
const agentDir =
|
|
57356
|
+
const agentDir = resolve22(agentsDir, name);
|
|
57322
57357
|
let hindsightApiUrl = null;
|
|
57323
57358
|
let hindsightBankId = name;
|
|
57324
57359
|
if (isHindsightEnabled(config)) {
|
|
@@ -57389,7 +57424,7 @@ function registerAgentCommand(program3) {
|
|
|
57389
57424
|
Scaffolding agent: ${name}
|
|
57390
57425
|
`));
|
|
57391
57426
|
scaffoldAgent(name, agentConfig, agentsDir, config.telegram, config, undefined, getConfigPath(program3));
|
|
57392
|
-
const agentDir =
|
|
57427
|
+
const agentDir = resolve22(agentsDir, name);
|
|
57393
57428
|
console.log(source_default.green(` Agent "${name}" scaffolded at ${agentDir}`));
|
|
57394
57429
|
console.log(source_default.gray(`
|
|
57395
57430
|
Next: switchroom apply (regenerates docker-compose.yml + brings up new agent)
|
|
@@ -57408,7 +57443,7 @@ Scaffolding agent: ${name}
|
|
|
57408
57443
|
continue;
|
|
57409
57444
|
}
|
|
57410
57445
|
if (!opts.force) {
|
|
57411
|
-
const agentDir =
|
|
57446
|
+
const agentDir = resolve22(agentsDir, n);
|
|
57412
57447
|
const usesDevChannels = config.agents[n].channels?.telegram?.plugin !== "official";
|
|
57413
57448
|
const errors2 = preflightCheck(n, agentDir, usesDevChannels);
|
|
57414
57449
|
if (errors2.length > 0) {
|
|
@@ -57510,7 +57545,7 @@ Scaffolding agent: ${name}
|
|
|
57510
57545
|
sawAbort = true;
|
|
57511
57546
|
continue;
|
|
57512
57547
|
}
|
|
57513
|
-
const agentDir =
|
|
57548
|
+
const agentDir = resolve22(agentsDir, n);
|
|
57514
57549
|
if (!opts.force) {
|
|
57515
57550
|
const usesDevChannels = config.agents[n].channels?.telegram?.plugin !== "official";
|
|
57516
57551
|
const errors2 = preflightCheck(n, agentDir, usesDevChannels);
|
|
@@ -57696,7 +57731,7 @@ Scaffolding agent: ${name}
|
|
|
57696
57731
|
useSwitchroomPlugin: usesSwitchroomTelegramPlugin(agentConfig),
|
|
57697
57732
|
configPath
|
|
57698
57733
|
});
|
|
57699
|
-
const settingsPath =
|
|
57734
|
+
const settingsPath = resolve22(agentsDir, n, ".claude", "settings.json");
|
|
57700
57735
|
let actual = {};
|
|
57701
57736
|
if (existsSync28(settingsPath)) {
|
|
57702
57737
|
try {
|
|
@@ -57941,7 +57976,7 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
|
|
|
57941
57976
|
agent.command("permissions <name>").description("Show the current permissions.allow list for an agent").action(withConfigError(async (name) => {
|
|
57942
57977
|
const config = getConfig(program3);
|
|
57943
57978
|
const agentsDir = resolveAgentsDir(config);
|
|
57944
|
-
const settingsPath =
|
|
57979
|
+
const settingsPath = resolve22(agentsDir, name, ".claude", "settings.json");
|
|
57945
57980
|
if (!existsSync28(settingsPath)) {
|
|
57946
57981
|
console.error(source_default.red(`Agent "${name}" not found at ${settingsPath}`));
|
|
57947
57982
|
process.exit(1);
|
|
@@ -57971,12 +58006,12 @@ Permissions for ${name}
|
|
|
57971
58006
|
agent.command("destroy <name>").description("Remove an agent's directory (run `switchroom apply` after to remove the container)").option("-y, --yes", "Skip confirmation prompt").action(withConfigError(async (name, opts) => {
|
|
57972
58007
|
const config = getConfig(program3);
|
|
57973
58008
|
const agentsDir = resolveAgentsDir(config);
|
|
57974
|
-
const agentDir =
|
|
58009
|
+
const agentDir = resolve22(agentsDir, name);
|
|
57975
58010
|
if (!opts.yes) {
|
|
57976
58011
|
process.stdout.write(source_default.yellow(`Destroy agent "${name}"? This removes ${agentDir}. (Run \`switchroom apply\` after to take the container down.) [y/N] `));
|
|
57977
|
-
const response = await new Promise((
|
|
58012
|
+
const response = await new Promise((resolve23) => {
|
|
57978
58013
|
process.stdin.setEncoding("utf-8");
|
|
57979
|
-
process.stdin.once("data", (data) =>
|
|
58014
|
+
process.stdin.once("data", (data) => resolve23(data.toString().trim()));
|
|
57980
58015
|
});
|
|
57981
58016
|
if (response.toLowerCase() !== "y") {
|
|
57982
58017
|
console.log("Aborted.");
|
|
@@ -58051,7 +58086,7 @@ Bootstrapping agent: ${name}
|
|
|
58051
58086
|
`));
|
|
58052
58087
|
}
|
|
58053
58088
|
process.stdout.write(source_default.bold(" Paste the browser code here: "));
|
|
58054
|
-
const code = await new Promise((
|
|
58089
|
+
const code = await new Promise((resolve23) => {
|
|
58055
58090
|
process.stdin.setEncoding("utf-8");
|
|
58056
58091
|
let buf = "";
|
|
58057
58092
|
process.stdin.on("data", (chunk) => {
|
|
@@ -58060,7 +58095,7 @@ Bootstrapping agent: ${name}
|
|
|
58060
58095
|
`);
|
|
58061
58096
|
if (newlineIdx !== -1) {
|
|
58062
58097
|
process.stdin.removeAllListeners("data");
|
|
58063
|
-
|
|
58098
|
+
resolve23(buf.slice(0, newlineIdx).trim());
|
|
58064
58099
|
}
|
|
58065
58100
|
});
|
|
58066
58101
|
});
|
|
@@ -58188,7 +58223,7 @@ switchroom agent add: ${name}
|
|
|
58188
58223
|
composePath = upRes.composePath;
|
|
58189
58224
|
console.log(source_default.gray(` Wrote compose: ${composePath}`));
|
|
58190
58225
|
} catch (err) {
|
|
58191
|
-
composePath =
|
|
58226
|
+
composePath = resolve22(process.env.SWITCHROOM_HOME ?? resolve22(process.env.HOME ?? "", ".switchroom"), "compose", "docker-compose.yml");
|
|
58192
58227
|
console.error(source_default.red(` docker compose up failed: ${err.message}`));
|
|
58193
58228
|
try {
|
|
58194
58229
|
dockerExecFile("docker", [
|
|
@@ -58204,7 +58239,7 @@ switchroom agent add: ${name}
|
|
|
58204
58239
|
stopAgent(name);
|
|
58205
58240
|
} catch {}
|
|
58206
58241
|
const agentsDirRollback = resolveAgentsDir(cfg);
|
|
58207
|
-
const agentDirRollback =
|
|
58242
|
+
const agentDirRollback = resolve22(agentsDirRollback, name);
|
|
58208
58243
|
if (existsSync28(agentDirRollback)) {
|
|
58209
58244
|
rmSync9(agentDirRollback, { recursive: true, force: true });
|
|
58210
58245
|
console.log(source_default.gray(` Rolled back: removed ${agentDirRollback}`));
|
|
@@ -58256,9 +58291,9 @@ Rename agent "${oldName}" \u2192 "${newName}"?
|
|
|
58256
58291
|
` + ` reconcile, and start ${newName}.
|
|
58257
58292
|
` + ` Hindsight mode: ${hindsightMode}
|
|
58258
58293
|
` + `[y/N] `));
|
|
58259
|
-
const answer = await new Promise((
|
|
58294
|
+
const answer = await new Promise((resolve23) => {
|
|
58260
58295
|
process.stdin.setEncoding("utf-8");
|
|
58261
|
-
process.stdin.once("data", (d) =>
|
|
58296
|
+
process.stdin.once("data", (d) => resolve23(d.toString().trim()));
|
|
58262
58297
|
});
|
|
58263
58298
|
if (answer.toLowerCase() !== "y") {
|
|
58264
58299
|
console.log("Aborted.");
|
|
@@ -58787,7 +58822,7 @@ init_loader();
|
|
|
58787
58822
|
init_manager();
|
|
58788
58823
|
init_helpers();
|
|
58789
58824
|
import { existsSync as existsSync33, readFileSync as readFileSync28 } from "node:fs";
|
|
58790
|
-
import { join as join26, resolve as
|
|
58825
|
+
import { join as join26, resolve as resolve25 } from "node:path";
|
|
58791
58826
|
|
|
58792
58827
|
// src/cli/auth-google.ts
|
|
58793
58828
|
init_source();
|
|
@@ -59356,8 +59391,8 @@ async function readVisibleLine(prompt) {
|
|
|
59356
59391
|
output: process.stdout
|
|
59357
59392
|
});
|
|
59358
59393
|
try {
|
|
59359
|
-
return await new Promise((
|
|
59360
|
-
rl.question(prompt, (answer) =>
|
|
59394
|
+
return await new Promise((resolve24) => {
|
|
59395
|
+
rl.question(prompt, (answer) => resolve24(answer));
|
|
59361
59396
|
});
|
|
59362
59397
|
} finally {
|
|
59363
59398
|
rl.close();
|
|
@@ -59365,7 +59400,7 @@ async function readVisibleLine(prompt) {
|
|
|
59365
59400
|
}
|
|
59366
59401
|
async function readHiddenLine(prompt) {
|
|
59367
59402
|
const { createInterface: createInterface3 } = await import("node:readline");
|
|
59368
|
-
return await new Promise((
|
|
59403
|
+
return await new Promise((resolve24, reject) => {
|
|
59369
59404
|
const rl = createInterface3({
|
|
59370
59405
|
input: process.stdin,
|
|
59371
59406
|
output: process.stdout
|
|
@@ -59385,7 +59420,7 @@ async function readHiddenLine(prompt) {
|
|
|
59385
59420
|
rl.close();
|
|
59386
59421
|
process.stdout.write(`
|
|
59387
59422
|
`);
|
|
59388
|
-
|
|
59423
|
+
resolve24(input);
|
|
59389
59424
|
} else if (char === "\x03") {
|
|
59390
59425
|
stdin.setRawMode(false);
|
|
59391
59426
|
stdin.removeListener("data", onData);
|
|
@@ -59404,7 +59439,7 @@ async function readHiddenLine(prompt) {
|
|
|
59404
59439
|
} else {
|
|
59405
59440
|
rl.question(prompt, (answer) => {
|
|
59406
59441
|
rl.close();
|
|
59407
|
-
|
|
59442
|
+
resolve24(answer);
|
|
59408
59443
|
});
|
|
59409
59444
|
}
|
|
59410
59445
|
});
|
|
@@ -60024,14 +60059,14 @@ async function readHiddenLine2(prompt) {
|
|
|
60024
60059
|
input: process.stdin,
|
|
60025
60060
|
output: process.stdout
|
|
60026
60061
|
});
|
|
60027
|
-
return new Promise((
|
|
60062
|
+
return new Promise((resolve24) => {
|
|
60028
60063
|
rl.question(prompt, (answer) => {
|
|
60029
60064
|
rl.close();
|
|
60030
|
-
|
|
60065
|
+
resolve24(answer);
|
|
60031
60066
|
});
|
|
60032
60067
|
});
|
|
60033
60068
|
}
|
|
60034
|
-
return new Promise((
|
|
60069
|
+
return new Promise((resolve24, reject) => {
|
|
60035
60070
|
const rl = readline.createInterface({
|
|
60036
60071
|
input: process.stdin,
|
|
60037
60072
|
output: process.stdout
|
|
@@ -60053,7 +60088,7 @@ async function readHiddenLine2(prompt) {
|
|
|
60053
60088
|
rl.close();
|
|
60054
60089
|
stdout.write(`
|
|
60055
60090
|
`);
|
|
60056
|
-
|
|
60091
|
+
resolve24(line);
|
|
60057
60092
|
return;
|
|
60058
60093
|
}
|
|
60059
60094
|
if (ch === "" || ch === "\b") {
|
|
@@ -60497,7 +60532,7 @@ function printAgentDetail(state, agent) {
|
|
|
60497
60532
|
function loadCredentialsFromAgent(agentName) {
|
|
60498
60533
|
const config = getConfigSafe();
|
|
60499
60534
|
const agentsDir = resolveAgentsDir(config);
|
|
60500
|
-
const agentDir =
|
|
60535
|
+
const agentDir = resolve25(agentsDir, agentName);
|
|
60501
60536
|
const credsPath = join26(agentDir, ".claude", ".credentials.json");
|
|
60502
60537
|
if (!existsSync33(credsPath)) {
|
|
60503
60538
|
console.error(source_default.red(` Agent "${agentName}" has no .claude/.credentials.json \u2014 log it in first.`));
|
|
@@ -60570,8 +60605,8 @@ async function loadCredentialsViaClaude(label) {
|
|
|
60570
60605
|
output: process.stdout
|
|
60571
60606
|
});
|
|
60572
60607
|
try {
|
|
60573
|
-
return await new Promise((
|
|
60574
|
-
rl.question(" Paste the code Claude shows you: ", (answer) =>
|
|
60608
|
+
return await new Promise((resolve26) => {
|
|
60609
|
+
rl.question(" Paste the code Claude shows you: ", (answer) => resolve26(answer));
|
|
60575
60610
|
});
|
|
60576
60611
|
} finally {
|
|
60577
60612
|
rl.close();
|
|
@@ -61229,7 +61264,7 @@ init_compose();
|
|
|
61229
61264
|
init_vault();
|
|
61230
61265
|
import * as net3 from "node:net";
|
|
61231
61266
|
import { mkdirSync as mkdirSync23, chmodSync as chmodSync7, chownSync as chownSync4, existsSync as existsSync37, readFileSync as readFileSync32, readdirSync as readdirSync17, statSync as statSync20, unlinkSync as unlinkSync8, writeFileSync as writeFileSync19, renameSync as renameSync10 } from "node:fs";
|
|
61232
|
-
import { dirname as
|
|
61267
|
+
import { dirname as dirname8, resolve as resolve27, basename as basename6 } from "node:path";
|
|
61233
61268
|
import * as os4 from "node:os";
|
|
61234
61269
|
import * as path3 from "node:path";
|
|
61235
61270
|
|
|
@@ -61240,7 +61275,7 @@ import {
|
|
|
61240
61275
|
chmodSync as chmodSync4,
|
|
61241
61276
|
existsSync as existsSync35,
|
|
61242
61277
|
fsyncSync as fsyncSync4,
|
|
61243
|
-
lstatSync as
|
|
61278
|
+
lstatSync as lstatSync6,
|
|
61244
61279
|
mkdirSync as mkdirSync20,
|
|
61245
61280
|
openSync as openSync6,
|
|
61246
61281
|
closeSync as closeSync6,
|
|
@@ -61251,7 +61286,7 @@ import {
|
|
|
61251
61286
|
unlinkSync as unlinkSync7
|
|
61252
61287
|
} from "node:fs";
|
|
61253
61288
|
import { createHash as createHash5 } from "node:crypto";
|
|
61254
|
-
import { basename as basename5, dirname as
|
|
61289
|
+
import { basename as basename5, dirname as dirname5, join as join28 } from "node:path";
|
|
61255
61290
|
function vaultLayoutPaths(home2) {
|
|
61256
61291
|
const switchroomRoot = join28(home2, ".switchroom");
|
|
61257
61292
|
return {
|
|
@@ -61394,7 +61429,7 @@ your fleet works after \`switchroom apply\`, then delete it.
|
|
|
61394
61429
|
}
|
|
61395
61430
|
function lstatSyncOrNull(path) {
|
|
61396
61431
|
try {
|
|
61397
|
-
return
|
|
61432
|
+
return lstatSync6(path);
|
|
61398
61433
|
} catch {
|
|
61399
61434
|
return null;
|
|
61400
61435
|
}
|
|
@@ -61404,7 +61439,7 @@ function sha256File(path) {
|
|
|
61404
61439
|
return createHash5("sha256").update(data).digest("hex");
|
|
61405
61440
|
}
|
|
61406
61441
|
function atomicReplaceWithSymlink(target, linkTarget) {
|
|
61407
|
-
const tmp = join28(
|
|
61442
|
+
const tmp = join28(dirname5(target), `.${basename5(target)}.symlink-tmp`);
|
|
61408
61443
|
if (existsSync35(tmp)) {
|
|
61409
61444
|
try {
|
|
61410
61445
|
unlinkSync7(tmp);
|
|
@@ -61436,7 +61471,7 @@ init_loader();
|
|
|
61436
61471
|
// src/vault/auto-unlock.ts
|
|
61437
61472
|
import { createHmac, randomBytes as randomBytes6, createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2 } from "node:crypto";
|
|
61438
61473
|
import { chmodSync as chmodSync5, existsSync as existsSync36, mkdirSync as mkdirSync21, readFileSync as readFileSync31, writeFileSync as writeFileSync18 } from "node:fs";
|
|
61439
|
-
import { dirname as
|
|
61474
|
+
import { dirname as dirname6 } from "node:path";
|
|
61440
61475
|
var FORMAT_VERSION = 1;
|
|
61441
61476
|
var SALT_LEN = 16;
|
|
61442
61477
|
var NONCE_LEN = 12;
|
|
@@ -61525,7 +61560,7 @@ function decryptAutoUnlock(blob, machineId) {
|
|
|
61525
61560
|
}
|
|
61526
61561
|
function writeAutoUnlockFile(passphrase, filePath) {
|
|
61527
61562
|
const blob = encryptAutoUnlock(passphrase);
|
|
61528
|
-
mkdirSync21(
|
|
61563
|
+
mkdirSync21(dirname6(filePath), { recursive: true, mode: 448 });
|
|
61529
61564
|
writeFileSync18(filePath, blob, { mode: 384 });
|
|
61530
61565
|
chmodSync5(filePath, 384);
|
|
61531
61566
|
}
|
|
@@ -61557,7 +61592,7 @@ import * as path from "node:path";
|
|
|
61557
61592
|
// src/vault/broker/test-isolation-guard.ts
|
|
61558
61593
|
import { mkdtempSync as mkdtempSync4 } from "node:fs";
|
|
61559
61594
|
import { homedir as homedir14, tmpdir as tmpdir3 } from "node:os";
|
|
61560
|
-
import { join as join29, resolve as
|
|
61595
|
+
import { join as join29, resolve as resolve26, sep } from "node:path";
|
|
61561
61596
|
function isTestRuntime() {
|
|
61562
61597
|
return process.env.VITEST !== undefined;
|
|
61563
61598
|
}
|
|
@@ -61565,11 +61600,11 @@ function escapeHatchSet() {
|
|
|
61565
61600
|
return process.env.SWITCHROOM_ALLOW_PROD_VAULT_IN_TEST === "1";
|
|
61566
61601
|
}
|
|
61567
61602
|
function realSwitchroomHome() {
|
|
61568
|
-
return
|
|
61603
|
+
return resolve26(homedir14(), ".switchroom");
|
|
61569
61604
|
}
|
|
61570
61605
|
function isUnderRealSwitchroomHome(p) {
|
|
61571
61606
|
const home2 = realSwitchroomHome();
|
|
61572
|
-
const r =
|
|
61607
|
+
const r = resolve26(p);
|
|
61573
61608
|
return r === home2 || r.startsWith(home2 + sep);
|
|
61574
61609
|
}
|
|
61575
61610
|
var warnedVault = false;
|
|
@@ -61704,13 +61739,13 @@ function genSalt(rounds, seed_length, callback) {
|
|
|
61704
61739
|
throw Error("Illegal callback: " + typeof callback);
|
|
61705
61740
|
_async(callback);
|
|
61706
61741
|
} else
|
|
61707
|
-
return new Promise(function(
|
|
61742
|
+
return new Promise(function(resolve27, reject) {
|
|
61708
61743
|
_async(function(err, res) {
|
|
61709
61744
|
if (err) {
|
|
61710
61745
|
reject(err);
|
|
61711
61746
|
return;
|
|
61712
61747
|
}
|
|
61713
|
-
|
|
61748
|
+
resolve27(res);
|
|
61714
61749
|
});
|
|
61715
61750
|
});
|
|
61716
61751
|
}
|
|
@@ -61730,13 +61765,13 @@ function hash(password, salt, callback, progressCallback) {
|
|
|
61730
61765
|
throw Error("Illegal callback: " + typeof callback);
|
|
61731
61766
|
_async(callback);
|
|
61732
61767
|
} else
|
|
61733
|
-
return new Promise(function(
|
|
61768
|
+
return new Promise(function(resolve27, reject) {
|
|
61734
61769
|
_async(function(err, res) {
|
|
61735
61770
|
if (err) {
|
|
61736
61771
|
reject(err);
|
|
61737
61772
|
return;
|
|
61738
61773
|
}
|
|
61739
|
-
|
|
61774
|
+
resolve27(res);
|
|
61740
61775
|
});
|
|
61741
61776
|
});
|
|
61742
61777
|
}
|
|
@@ -61769,13 +61804,13 @@ function compare(password, hashValue, callback, progressCallback) {
|
|
|
61769
61804
|
throw Error("Illegal callback: " + typeof callback);
|
|
61770
61805
|
_async(callback);
|
|
61771
61806
|
} else
|
|
61772
|
-
return new Promise(function(
|
|
61807
|
+
return new Promise(function(resolve27, reject) {
|
|
61773
61808
|
_async(function(err, res) {
|
|
61774
61809
|
if (err) {
|
|
61775
61810
|
reject(err);
|
|
61776
61811
|
return;
|
|
61777
61812
|
}
|
|
61778
|
-
|
|
61813
|
+
resolve27(res);
|
|
61779
61814
|
});
|
|
61780
61815
|
});
|
|
61781
61816
|
}
|
|
@@ -63935,7 +63970,7 @@ class VaultBroker {
|
|
|
63935
63970
|
if (process.platform !== "linux" && process.env.SWITCHROOM_BROKER_ALLOW_NON_LINUX !== "1") {
|
|
63936
63971
|
throw new Error(`vault-broker is Linux-only (running on ${process.platform}). ` + `The broker's ACL relies on cgroup-based systemd unit identification, ` + `which is not available on this platform. ` + `Use 'switchroom vault get --no-broker' for direct vault access. ` + `If you need to run the broker for development on this platform, ` + `set SWITCHROOM_BROKER_ALLOW_NON_LINUX=1 \u2014 but understand that the ` + `broker will accept any same-user caller without per-cron ACL enforcement.`);
|
|
63937
63972
|
}
|
|
63938
|
-
this.socketPath =
|
|
63973
|
+
this.socketPath = resolve27(socketPath);
|
|
63939
63974
|
this.unlockSocketPath = unlockSocketFor(this.socketPath);
|
|
63940
63975
|
this.startedAt = Date.now();
|
|
63941
63976
|
if (this.testOpts._testConfig) {
|
|
@@ -63945,7 +63980,7 @@ class VaultBroker {
|
|
|
63945
63980
|
this.config = loadConfig2(configPath);
|
|
63946
63981
|
}
|
|
63947
63982
|
if (vaultPath) {
|
|
63948
|
-
this.vaultPath =
|
|
63983
|
+
this.vaultPath = resolve27(vaultPath);
|
|
63949
63984
|
} else {
|
|
63950
63985
|
this.vaultPath = resolvePath(this.config.vault?.path ?? "~/.switchroom/vault.enc");
|
|
63951
63986
|
}
|
|
@@ -63957,7 +63992,7 @@ class VaultBroker {
|
|
|
63957
63992
|
this.passphrase = this.testOpts._testPassphrase;
|
|
63958
63993
|
}
|
|
63959
63994
|
process.umask(63);
|
|
63960
|
-
const parentDir =
|
|
63995
|
+
const parentDir = dirname8(this.socketPath);
|
|
63961
63996
|
mkdirSync23(parentDir, { recursive: true, mode: 448 });
|
|
63962
63997
|
try {
|
|
63963
63998
|
chmodSync7(parentDir, 448);
|
|
@@ -64060,7 +64095,7 @@ class VaultBroker {
|
|
|
64060
64095
|
return this.secrets;
|
|
64061
64096
|
}
|
|
64062
64097
|
bindAgentSocket(socketPath) {
|
|
64063
|
-
const abs =
|
|
64098
|
+
const abs = resolve27(socketPath);
|
|
64064
64099
|
const agentName = socketPathToAgent(abs);
|
|
64065
64100
|
if (agentName === null) {
|
|
64066
64101
|
return Promise.reject(new Error(`bindAgentSocket: socket path '${abs}' does not match the canonical ` + `/run/switchroom/broker/<agent>.sock shape \u2014 refusing to bind without ` + `a verifiable agent identity`));
|
|
@@ -64140,7 +64175,7 @@ class VaultBroker {
|
|
|
64140
64175
|
});
|
|
64141
64176
|
}
|
|
64142
64177
|
_bindDataSocket() {
|
|
64143
|
-
return new Promise((
|
|
64178
|
+
return new Promise((resolve28, reject) => {
|
|
64144
64179
|
const server = net3.createServer((socket) => {
|
|
64145
64180
|
this._handleDataConnection(socket);
|
|
64146
64181
|
});
|
|
@@ -64152,7 +64187,7 @@ class VaultBroker {
|
|
|
64152
64187
|
chmodSync7(this.socketPath, 384);
|
|
64153
64188
|
} catch {}
|
|
64154
64189
|
this.server = server;
|
|
64155
|
-
|
|
64190
|
+
resolve28();
|
|
64156
64191
|
});
|
|
64157
64192
|
});
|
|
64158
64193
|
}
|
|
@@ -64169,7 +64204,7 @@ class VaultBroker {
|
|
|
64169
64204
|
} catch {}
|
|
64170
64205
|
}
|
|
64171
64206
|
bindOperatorListener(socketPath, operatorUid) {
|
|
64172
|
-
const abs =
|
|
64207
|
+
const abs = resolve27(socketPath);
|
|
64173
64208
|
const identity = socketPathToIdentity(abs);
|
|
64174
64209
|
if (identity?.kind !== "operator") {
|
|
64175
64210
|
return Promise.reject(new Error(`bindOperatorListener: socket path '${abs}' does not match the canonical ` + `/run/switchroom/broker/operator/sock shape \u2014 refusing to bind`));
|
|
@@ -64233,7 +64268,7 @@ class VaultBroker {
|
|
|
64233
64268
|
});
|
|
64234
64269
|
}
|
|
64235
64270
|
_bindUnlockSocket() {
|
|
64236
|
-
return new Promise((
|
|
64271
|
+
return new Promise((resolve28, reject) => {
|
|
64237
64272
|
const server = net3.createServer((socket) => {
|
|
64238
64273
|
this._handleUnlockConnection(socket);
|
|
64239
64274
|
});
|
|
@@ -64245,7 +64280,7 @@ class VaultBroker {
|
|
|
64245
64280
|
chmodSync7(this.unlockSocketPath, 384);
|
|
64246
64281
|
} catch {}
|
|
64247
64282
|
this.unlockServer = server;
|
|
64248
|
-
|
|
64283
|
+
resolve28();
|
|
64249
64284
|
});
|
|
64250
64285
|
});
|
|
64251
64286
|
}
|
|
@@ -65430,15 +65465,15 @@ class VaultBroker {
|
|
|
65430
65465
|
}
|
|
65431
65466
|
}
|
|
65432
65467
|
function detectVaultLayoutDrift(vaultPath) {
|
|
65433
|
-
const dir =
|
|
65468
|
+
const dir = dirname8(vaultPath);
|
|
65434
65469
|
if (basename6(dir) !== "vault")
|
|
65435
65470
|
return;
|
|
65436
65471
|
if (basename6(vaultPath) !== "vault.enc")
|
|
65437
65472
|
return;
|
|
65438
|
-
const switchroomDir =
|
|
65473
|
+
const switchroomDir = dirname8(dir);
|
|
65439
65474
|
if (basename6(switchroomDir) !== ".switchroom")
|
|
65440
65475
|
return;
|
|
65441
|
-
const home2 =
|
|
65476
|
+
const home2 = dirname8(switchroomDir);
|
|
65442
65477
|
const result = inspectVaultLayout(home2);
|
|
65443
65478
|
if (result.kind === "divergent") {
|
|
65444
65479
|
throw new VaultError(`Vault layout divergence detected at boot: ${result.details.oldPath} and ${result.details.newPath} are both regular files with different content. An older switchroom CLI may have written to the legacy path after migration ran. Run \`switchroom apply\` from the host to surface the recovery recipe (state E refusal with literal \`mv\` commands). See docs/operators/state-e-recovery.md.`);
|
|
@@ -65472,11 +65507,11 @@ async function main() {
|
|
|
65472
65507
|
if (e.name.startsWith("."))
|
|
65473
65508
|
continue;
|
|
65474
65509
|
if ((e.isFile() || e.isSocket()) && e.name.endsWith(".sock")) {
|
|
65475
|
-
flat.push(
|
|
65510
|
+
flat.push(resolve27(perAgentDir, e.name));
|
|
65476
65511
|
continue;
|
|
65477
65512
|
}
|
|
65478
65513
|
if (e.isDirectory()) {
|
|
65479
|
-
const candidate =
|
|
65514
|
+
const candidate = resolve27(perAgentDir, e.name, "sock");
|
|
65480
65515
|
if (socketPathToAgent(candidate) !== null) {
|
|
65481
65516
|
subdirs.push(candidate);
|
|
65482
65517
|
}
|
|
@@ -65658,7 +65693,7 @@ function getAutoUnlockCredPath(configPath) {
|
|
|
65658
65693
|
async function promptPassphrase() {
|
|
65659
65694
|
if (!process.stdin.isTTY) {
|
|
65660
65695
|
const { createInterface: createInterface3 } = await import("node:readline");
|
|
65661
|
-
return new Promise((
|
|
65696
|
+
return new Promise((resolve28, reject) => {
|
|
65662
65697
|
const rl = createInterface3({ input: process.stdin, terminal: false });
|
|
65663
65698
|
let settled = false;
|
|
65664
65699
|
rl.once("line", (line) => {
|
|
@@ -65669,7 +65704,7 @@ async function promptPassphrase() {
|
|
|
65669
65704
|
reject(new Error("Empty passphrase \u2014 aborting"));
|
|
65670
65705
|
return;
|
|
65671
65706
|
}
|
|
65672
|
-
|
|
65707
|
+
resolve28(passphrase);
|
|
65673
65708
|
});
|
|
65674
65709
|
rl.once("close", () => {
|
|
65675
65710
|
if (!settled) {
|
|
@@ -65678,7 +65713,7 @@ async function promptPassphrase() {
|
|
|
65678
65713
|
});
|
|
65679
65714
|
});
|
|
65680
65715
|
}
|
|
65681
|
-
return new Promise((
|
|
65716
|
+
return new Promise((resolve28, reject) => {
|
|
65682
65717
|
process.stdout.write("Vault passphrase: ");
|
|
65683
65718
|
const stdin = process.stdin;
|
|
65684
65719
|
stdin.setRawMode(true);
|
|
@@ -65698,7 +65733,7 @@ async function promptPassphrase() {
|
|
|
65698
65733
|
if (!input) {
|
|
65699
65734
|
reject(new Error("Empty passphrase \u2014 aborting"));
|
|
65700
65735
|
} else {
|
|
65701
|
-
|
|
65736
|
+
resolve28(input);
|
|
65702
65737
|
}
|
|
65703
65738
|
} else if (char === "\x03") {
|
|
65704
65739
|
cleanup();
|
|
@@ -66773,7 +66808,7 @@ function getVaultPath4(configPath) {
|
|
|
66773
66808
|
}
|
|
66774
66809
|
}
|
|
66775
66810
|
function promptLine2(prompt, hidden = false) {
|
|
66776
|
-
return new Promise((
|
|
66811
|
+
return new Promise((resolve28, reject) => {
|
|
66777
66812
|
const rl = createInterface3({
|
|
66778
66813
|
input: process.stdin,
|
|
66779
66814
|
output: process.stderr
|
|
@@ -66793,7 +66828,7 @@ function promptLine2(prompt, hidden = false) {
|
|
|
66793
66828
|
rl.close();
|
|
66794
66829
|
process.stderr.write(`
|
|
66795
66830
|
`);
|
|
66796
|
-
|
|
66831
|
+
resolve28(input);
|
|
66797
66832
|
} else if (char === "\x03") {
|
|
66798
66833
|
stdin.setRawMode(false);
|
|
66799
66834
|
stdin.removeListener("data", onData);
|
|
@@ -66813,17 +66848,17 @@ function promptLine2(prompt, hidden = false) {
|
|
|
66813
66848
|
} else {
|
|
66814
66849
|
rl.question(prompt, (answer) => {
|
|
66815
66850
|
rl.close();
|
|
66816
|
-
|
|
66851
|
+
resolve28(answer);
|
|
66817
66852
|
});
|
|
66818
66853
|
}
|
|
66819
66854
|
});
|
|
66820
66855
|
}
|
|
66821
66856
|
function readStdinToEnd() {
|
|
66822
|
-
return new Promise((
|
|
66857
|
+
return new Promise((resolve28, reject) => {
|
|
66823
66858
|
const chunks = [];
|
|
66824
66859
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
66825
66860
|
process.stdin.on("end", () => {
|
|
66826
|
-
|
|
66861
|
+
resolve28(Buffer.concat(chunks).toString("utf8"));
|
|
66827
66862
|
});
|
|
66828
66863
|
process.stdin.on("error", reject);
|
|
66829
66864
|
});
|
|
@@ -68073,7 +68108,7 @@ function registerDispatchVerb(tg, _program) {
|
|
|
68073
68108
|
}));
|
|
68074
68109
|
}
|
|
68075
68110
|
function promptHidden2(prompt) {
|
|
68076
|
-
return new Promise((
|
|
68111
|
+
return new Promise((resolve28, reject) => {
|
|
68077
68112
|
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
68078
68113
|
if (process.stdin.isTTY) {
|
|
68079
68114
|
process.stdout.write(prompt);
|
|
@@ -68090,7 +68125,7 @@ function promptHidden2(prompt) {
|
|
|
68090
68125
|
rl.close();
|
|
68091
68126
|
process.stdout.write(`
|
|
68092
68127
|
`);
|
|
68093
|
-
|
|
68128
|
+
resolve28(input);
|
|
68094
68129
|
} else if (char === "\x03") {
|
|
68095
68130
|
stdin.setRawMode(false);
|
|
68096
68131
|
stdin.removeListener("data", onData);
|
|
@@ -68109,7 +68144,7 @@ function promptHidden2(prompt) {
|
|
|
68109
68144
|
} else {
|
|
68110
68145
|
rl.question(prompt, (answer) => {
|
|
68111
68146
|
rl.close();
|
|
68112
|
-
|
|
68147
|
+
resolve28(answer);
|
|
68113
68148
|
});
|
|
68114
68149
|
}
|
|
68115
68150
|
});
|
|
@@ -68447,11 +68482,11 @@ var HINDSIGHT_DEFAULT_MEM_RESERVATION = "2g";
|
|
|
68447
68482
|
var HINDSIGHT_DEFAULT_PIDS_LIMIT = 1000;
|
|
68448
68483
|
var HINDSIGHT_DEFAULT_SHM_SIZE = "2g";
|
|
68449
68484
|
function isPortFree(port) {
|
|
68450
|
-
return new Promise((
|
|
68485
|
+
return new Promise((resolve28) => {
|
|
68451
68486
|
const server = createServer4();
|
|
68452
|
-
server.once("error", () =>
|
|
68487
|
+
server.once("error", () => resolve28(false));
|
|
68453
68488
|
server.once("listening", () => {
|
|
68454
|
-
server.close(() =>
|
|
68489
|
+
server.close(() => resolve28(true));
|
|
68455
68490
|
});
|
|
68456
68491
|
server.listen(port, "127.0.0.1");
|
|
68457
68492
|
});
|
|
@@ -68982,7 +69017,7 @@ import {
|
|
|
68982
69017
|
writeSync as writeSync6,
|
|
68983
69018
|
constants as fsConstants3
|
|
68984
69019
|
} from "node:fs";
|
|
68985
|
-
import { resolve as
|
|
69020
|
+
import { resolve as resolve29, extname, join as join47, relative, dirname as dirname11 } from "node:path";
|
|
68986
69021
|
import { homedir as homedir26 } from "node:os";
|
|
68987
69022
|
import { timingSafeEqual as timingSafeEqual3, randomBytes as randomBytes11 } from "node:crypto";
|
|
68988
69023
|
|
|
@@ -68992,7 +69027,7 @@ init_manager();
|
|
|
68992
69027
|
init_hindsight();
|
|
68993
69028
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
68994
69029
|
import { existsSync as existsSync47, readFileSync as readFileSync43, statSync as statSync22 } from "node:fs";
|
|
68995
|
-
import { resolve as
|
|
69030
|
+
import { resolve as resolve28, join as join44 } from "node:path";
|
|
68996
69031
|
|
|
68997
69032
|
// src/web/memory-remediation.ts
|
|
68998
69033
|
init_hindsight();
|
|
@@ -69126,7 +69161,7 @@ init_client();
|
|
|
69126
69161
|
import { homedir as homedir23 } from "node:os";
|
|
69127
69162
|
|
|
69128
69163
|
// node_modules/.bun/posthog-node@5.29.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
|
|
69129
|
-
import { dirname as
|
|
69164
|
+
import { dirname as dirname9, posix, sep as sep2 } from "path";
|
|
69130
69165
|
function createModulerModifier() {
|
|
69131
69166
|
const getModuleFromFileName = createGetModuleFromFilename();
|
|
69132
69167
|
return async (frames) => {
|
|
@@ -69135,7 +69170,7 @@ function createModulerModifier() {
|
|
|
69135
69170
|
return frames;
|
|
69136
69171
|
};
|
|
69137
69172
|
}
|
|
69138
|
-
function createGetModuleFromFilename(basePath = process.argv[1] ?
|
|
69173
|
+
function createGetModuleFromFilename(basePath = process.argv[1] ? dirname9(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
|
|
69139
69174
|
const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
|
|
69140
69175
|
return (filename) => {
|
|
69141
69176
|
if (!filename)
|
|
@@ -71474,14 +71509,14 @@ async function addSourceContext(frames) {
|
|
|
71474
71509
|
return frames;
|
|
71475
71510
|
}
|
|
71476
71511
|
function getContextLinesFromFile(path4, ranges, output) {
|
|
71477
|
-
return new Promise((
|
|
71512
|
+
return new Promise((resolve28) => {
|
|
71478
71513
|
const stream = createReadStream(path4);
|
|
71479
71514
|
const lineReaded = createInterface5({
|
|
71480
71515
|
input: stream
|
|
71481
71516
|
});
|
|
71482
71517
|
function destroyStreamAndResolve() {
|
|
71483
71518
|
stream.destroy();
|
|
71484
|
-
|
|
71519
|
+
resolve28();
|
|
71485
71520
|
}
|
|
71486
71521
|
let lineNumber = 0;
|
|
71487
71522
|
let currentRangeIndex = 0;
|
|
@@ -72721,9 +72756,9 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
72721
72756
|
if (this.disabled || this.optedOut)
|
|
72722
72757
|
return;
|
|
72723
72758
|
if (!this._waitUntilCycle) {
|
|
72724
|
-
let
|
|
72759
|
+
let resolve28;
|
|
72725
72760
|
const promise = new Promise((r) => {
|
|
72726
|
-
|
|
72761
|
+
resolve28 = r;
|
|
72727
72762
|
});
|
|
72728
72763
|
try {
|
|
72729
72764
|
waitUntil(promise);
|
|
@@ -72731,7 +72766,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
72731
72766
|
return;
|
|
72732
72767
|
}
|
|
72733
72768
|
this._waitUntilCycle = {
|
|
72734
|
-
resolve:
|
|
72769
|
+
resolve: resolve28,
|
|
72735
72770
|
startedAt: Date.now(),
|
|
72736
72771
|
timer: undefined
|
|
72737
72772
|
};
|
|
@@ -72757,11 +72792,11 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
72757
72792
|
return cycle?.resolve;
|
|
72758
72793
|
}
|
|
72759
72794
|
async resolveWaitUntilFlush() {
|
|
72760
|
-
const
|
|
72795
|
+
const resolve28 = this._consumeWaitUntilCycle();
|
|
72761
72796
|
try {
|
|
72762
72797
|
await super.flush();
|
|
72763
72798
|
} catch {} finally {
|
|
72764
|
-
|
|
72799
|
+
resolve28?.();
|
|
72765
72800
|
}
|
|
72766
72801
|
}
|
|
72767
72802
|
getPersistedProperty(key) {
|
|
@@ -72861,15 +72896,15 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
72861
72896
|
return true;
|
|
72862
72897
|
if (this.featureFlagsPoller === undefined)
|
|
72863
72898
|
return false;
|
|
72864
|
-
return new Promise((
|
|
72899
|
+
return new Promise((resolve28) => {
|
|
72865
72900
|
const timeout = setTimeout(() => {
|
|
72866
72901
|
cleanup();
|
|
72867
|
-
|
|
72902
|
+
resolve28(false);
|
|
72868
72903
|
}, timeoutMs);
|
|
72869
72904
|
const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
|
|
72870
72905
|
clearTimeout(timeout);
|
|
72871
72906
|
cleanup();
|
|
72872
|
-
|
|
72907
|
+
resolve28(count > 0);
|
|
72873
72908
|
});
|
|
72874
72909
|
});
|
|
72875
72910
|
}
|
|
@@ -73213,13 +73248,13 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
73213
73248
|
this.context?.enter(data, options);
|
|
73214
73249
|
}
|
|
73215
73250
|
async _shutdown(shutdownTimeoutMs) {
|
|
73216
|
-
const
|
|
73251
|
+
const resolve28 = this._consumeWaitUntilCycle();
|
|
73217
73252
|
await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
|
|
73218
73253
|
this.errorTracking.shutdown();
|
|
73219
73254
|
try {
|
|
73220
73255
|
return await super._shutdown(shutdownTimeoutMs);
|
|
73221
73256
|
} finally {
|
|
73222
|
-
|
|
73257
|
+
resolve28?.();
|
|
73223
73258
|
}
|
|
73224
73259
|
}
|
|
73225
73260
|
async _requestRemoteConfigPayload(flagKey) {
|
|
@@ -73573,7 +73608,7 @@ import {
|
|
|
73573
73608
|
readFileSync as readFileSync41,
|
|
73574
73609
|
writeFileSync as writeFileSync24
|
|
73575
73610
|
} from "node:fs";
|
|
73576
|
-
import { dirname as
|
|
73611
|
+
import { dirname as dirname10 } from "node:path";
|
|
73577
73612
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
73578
73613
|
var DEFAULT_KEY = "phc_qKY87cKWZm6ZyCtk7LcRd2cU8Sg42u7Ywhui5stYCegd";
|
|
73579
73614
|
var DEFAULT_HOST = "https://us.i.posthog.com";
|
|
@@ -73601,7 +73636,7 @@ function getDistinctId() {
|
|
|
73601
73636
|
const id = randomUUID3();
|
|
73602
73637
|
cachedDistinctId = id;
|
|
73603
73638
|
try {
|
|
73604
|
-
mkdirSync25(
|
|
73639
|
+
mkdirSync25(dirname10(path4), { recursive: true });
|
|
73605
73640
|
writeFileSync24(path4, id, "utf-8");
|
|
73606
73641
|
} catch {}
|
|
73607
73642
|
return id;
|
|
@@ -73657,7 +73692,7 @@ function installGlobalErrorHandlers() {
|
|
|
73657
73692
|
const flushWithTimeout = async (error, kind) => {
|
|
73658
73693
|
await Promise.race([
|
|
73659
73694
|
captureException(error, { kind }),
|
|
73660
|
-
new Promise((
|
|
73695
|
+
new Promise((resolve28) => setTimeout(resolve28, FLUSH_TIMEOUT_MS))
|
|
73661
73696
|
]);
|
|
73662
73697
|
};
|
|
73663
73698
|
process.on("uncaughtException", (err) => {
|
|
@@ -74266,7 +74301,7 @@ var DASHBOARD_CACHE_TTL = {
|
|
|
74266
74301
|
};
|
|
74267
74302
|
function readLastTurnAt(agentsDir, name) {
|
|
74268
74303
|
try {
|
|
74269
|
-
const db = openTurnsDb(
|
|
74304
|
+
const db = openTurnsDb(resolve28(agentsDir, name));
|
|
74270
74305
|
try {
|
|
74271
74306
|
const turns = listTurnsForAgent(db, { limit: 1 });
|
|
74272
74307
|
return turns.length > 0 ? turns[0].started_at : null;
|
|
@@ -74279,7 +74314,7 @@ function readLastTurnAt(agentsDir, name) {
|
|
|
74279
74314
|
}
|
|
74280
74315
|
function agentBridgeAlive(agentsDir, name, maxAgeMs = 30000, now = Date.now()) {
|
|
74281
74316
|
try {
|
|
74282
|
-
const f =
|
|
74317
|
+
const f = resolve28(agentsDir, name, "telegram", ".bridge-alive");
|
|
74283
74318
|
return now - statSync22(f).mtimeMs <= maxAgeMs;
|
|
74284
74319
|
} catch {
|
|
74285
74320
|
return false;
|
|
@@ -74367,7 +74402,7 @@ async function handleGetLogs(name, lines = 50, deps = {}) {
|
|
|
74367
74402
|
function handleGetTurns(config, agentName, limit) {
|
|
74368
74403
|
try {
|
|
74369
74404
|
const agentsDir = resolveAgentsDir(config);
|
|
74370
|
-
const agentDir =
|
|
74405
|
+
const agentDir = resolve28(agentsDir, agentName);
|
|
74371
74406
|
const db = openTurnsDb(agentDir);
|
|
74372
74407
|
try {
|
|
74373
74408
|
const turns = listTurnsForAgent(db, { limit });
|
|
@@ -74385,7 +74420,7 @@ function handleGetTurns(config, agentName, limit) {
|
|
|
74385
74420
|
function handleGetSubagents(config, agentName, status) {
|
|
74386
74421
|
try {
|
|
74387
74422
|
const agentsDir = resolveAgentsDir(config);
|
|
74388
|
-
const agentDir =
|
|
74423
|
+
const agentDir = resolve28(agentsDir, agentName);
|
|
74389
74424
|
const db = openTurnsDb(agentDir);
|
|
74390
74425
|
try {
|
|
74391
74426
|
applySubagentsSchema(db);
|
|
@@ -74929,7 +74964,7 @@ async function handleGetSchedule(config, deps = {}) {
|
|
|
74929
74964
|
const recentByAgent = {};
|
|
74930
74965
|
const agents = new Set(entries.map((e) => e.agent));
|
|
74931
74966
|
for (const agent of agents) {
|
|
74932
|
-
const rows = readRecentFires(
|
|
74967
|
+
const rows = readRecentFires(resolve28(agentsDir, agent, "scheduler.jsonl"));
|
|
74933
74968
|
if (rows.length > 0)
|
|
74934
74969
|
recentByAgent[agent] = rows.slice(-10);
|
|
74935
74970
|
}
|
|
@@ -75479,7 +75514,7 @@ function escapeHtml3(s) {
|
|
|
75479
75514
|
import net4 from "node:net";
|
|
75480
75515
|
function forwardToGateway(socketPath, req, opts = {}) {
|
|
75481
75516
|
const timeoutMs = opts.timeoutMs ?? 5000;
|
|
75482
|
-
return new Promise((
|
|
75517
|
+
return new Promise((resolve29) => {
|
|
75483
75518
|
let settled = false;
|
|
75484
75519
|
let buf = "";
|
|
75485
75520
|
const done = (value) => {
|
|
@@ -75489,7 +75524,7 @@ function forwardToGateway(socketPath, req, opts = {}) {
|
|
|
75489
75524
|
try {
|
|
75490
75525
|
conn.destroy();
|
|
75491
75526
|
} catch {}
|
|
75492
|
-
|
|
75527
|
+
resolve29(value);
|
|
75493
75528
|
};
|
|
75494
75529
|
const conn = net4.createConnection(socketPath);
|
|
75495
75530
|
conn.setEncoding("utf8");
|
|
@@ -75857,7 +75892,7 @@ function resolveWebToken() {
|
|
|
75857
75892
|
return existing;
|
|
75858
75893
|
}
|
|
75859
75894
|
const token = randomBytes11(32).toString("hex");
|
|
75860
|
-
mkdirSync29(
|
|
75895
|
+
mkdirSync29(dirname11(tokenPath), { recursive: true, mode: 448 });
|
|
75861
75896
|
try {
|
|
75862
75897
|
const fd = openSync10(tokenPath, fsConstants3.O_WRONLY | fsConstants3.O_CREAT | fsConstants3.O_EXCL, 384);
|
|
75863
75898
|
try {
|
|
@@ -76114,7 +76149,7 @@ function parseRoute(pathname, method) {
|
|
|
76114
76149
|
return null;
|
|
76115
76150
|
}
|
|
76116
76151
|
function startWebServer(config, port, hostname = "127.0.0.1", configPath) {
|
|
76117
|
-
const uiDirRaw =
|
|
76152
|
+
const uiDirRaw = resolve29(import.meta.dirname, "ui");
|
|
76118
76153
|
const uiDir = existsSync50(uiDirRaw) ? realpathSync4(uiDirRaw) : uiDirRaw;
|
|
76119
76154
|
const token = resolveWebToken();
|
|
76120
76155
|
const freshConfig = () => {
|
|
@@ -76391,7 +76426,7 @@ function startWebServer(config, port, hostname = "127.0.0.1", configPath) {
|
|
|
76391
76426
|
return new Response("Not Found", { status: 404 });
|
|
76392
76427
|
}
|
|
76393
76428
|
const rel = relative(uiDir, realFullPath);
|
|
76394
|
-
if (rel.startsWith("..") ||
|
|
76429
|
+
if (rel.startsWith("..") || resolve29(uiDir, rel) !== realFullPath) {
|
|
76395
76430
|
return new Response("Forbidden", { status: 403 });
|
|
76396
76431
|
}
|
|
76397
76432
|
const ext = extname(realFullPath);
|
|
@@ -76546,7 +76581,7 @@ Starting Switchroom dashboard...
|
|
|
76546
76581
|
init_source();
|
|
76547
76582
|
init_loader();
|
|
76548
76583
|
import { existsSync as existsSync51, copyFileSync as copyFileSync8, readFileSync as readFileSync47, writeFileSync as writeFileSync27, mkdirSync as mkdirSync30 } from "node:fs";
|
|
76549
|
-
import { resolve as
|
|
76584
|
+
import { resolve as resolve30, dirname as dirname12 } from "node:path";
|
|
76550
76585
|
init_vault();
|
|
76551
76586
|
init_manager();
|
|
76552
76587
|
|
|
@@ -76737,12 +76772,12 @@ async function stepConfigFile(configPath, nonInteractive) {
|
|
|
76737
76772
|
console.log(source_default.gray(` Loading ${existingConfig}`));
|
|
76738
76773
|
const config = loadConfig(existingConfig);
|
|
76739
76774
|
console.log(source_default.green(` ${STEP_DONE} Config loaded`) + source_default.gray(` (${Object.keys(config.agents).length} agents)`));
|
|
76740
|
-
return { config, configPath:
|
|
76775
|
+
return { config, configPath: resolve30(existingConfig) };
|
|
76741
76776
|
}
|
|
76742
76777
|
return await copyExampleConfig(nonInteractive);
|
|
76743
76778
|
}
|
|
76744
76779
|
async function copyExampleConfig(nonInteractive) {
|
|
76745
|
-
const examplesDir =
|
|
76780
|
+
const examplesDir = resolve30(import.meta.dirname, "../../examples");
|
|
76746
76781
|
let choice;
|
|
76747
76782
|
if (nonInteractive) {
|
|
76748
76783
|
choice = "switchroom";
|
|
@@ -76753,18 +76788,18 @@ async function copyExampleConfig(nonInteractive) {
|
|
|
76753
76788
|
]);
|
|
76754
76789
|
choice = choice.split(" ")[0];
|
|
76755
76790
|
}
|
|
76756
|
-
const srcFile =
|
|
76791
|
+
const srcFile = resolve30(examplesDir, `${choice}.yaml`);
|
|
76757
76792
|
const destFile = resolvePath("~/.switchroom/switchroom.yaml");
|
|
76758
76793
|
if (!existsSync51(srcFile)) {
|
|
76759
76794
|
throw new ConfigError(`Example config not found: ${choice}.yaml`);
|
|
76760
76795
|
}
|
|
76761
|
-
mkdirSync30(
|
|
76796
|
+
mkdirSync30(dirname12(destFile), { recursive: true });
|
|
76762
76797
|
copyFileSync8(srcFile, destFile);
|
|
76763
76798
|
console.log(source_default.green(` Copied ${choice}.yaml -> ${destFile}`));
|
|
76764
76799
|
console.log(source_default.yellow(` Edit ${destFile} to customize, then re-run switchroom setup.`));
|
|
76765
76800
|
const config = loadConfig(destFile);
|
|
76766
76801
|
console.log(source_default.green(` ${STEP_DONE} Config loaded`) + source_default.gray(` (${Object.keys(config.agents).length} agents)`));
|
|
76767
|
-
return { config, configPath:
|
|
76802
|
+
return { config, configPath: resolve30(destFile) };
|
|
76768
76803
|
}
|
|
76769
76804
|
async function stepBotToken(config, nonInteractive) {
|
|
76770
76805
|
stepHeader(2, "Bot tokens", STEP_ACTIVE);
|
|
@@ -77272,7 +77307,7 @@ async function stepAutoUnlock(config, switchroomConfigPath, nonInteractive) {
|
|
|
77272
77307
|
const choice = await askChoice(" Approval posture", [PASSPHRASE_CHOICE, TELEGRAM_ID_CHOICE]);
|
|
77273
77308
|
if (choice === TELEGRAM_ID_CHOICE) {
|
|
77274
77309
|
try {
|
|
77275
|
-
const yamlPath = existsSync51(
|
|
77310
|
+
const yamlPath = existsSync51(resolve30(process.cwd(), "switchroom.yaml")) ? resolve30(process.cwd(), "switchroom.yaml") : resolve30(process.cwd(), "switchroom.yml");
|
|
77276
77311
|
if (existsSync51(yamlPath)) {
|
|
77277
77312
|
const content = readFileSync47(yamlPath, "utf-8");
|
|
77278
77313
|
const result = insertVaultBrokerApprovalAuth(content, "telegram-id");
|
|
@@ -77304,8 +77339,8 @@ async function stepDangerousMode(config, nonInteractive) {
|
|
|
77304
77339
|
}
|
|
77305
77340
|
if (enableDangerous) {
|
|
77306
77341
|
const configPaths = [
|
|
77307
|
-
|
|
77308
|
-
|
|
77342
|
+
resolve30(process.cwd(), "switchroom.yaml"),
|
|
77343
|
+
resolve30(process.cwd(), "switchroom.yml")
|
|
77309
77344
|
];
|
|
77310
77345
|
for (const configPath of configPaths) {
|
|
77311
77346
|
if (existsSync51(configPath)) {
|
|
@@ -77339,7 +77374,7 @@ async function stepOnboardingGuidance(config, nonInteractive) {
|
|
|
77339
77374
|
const agentNames = Object.keys(config.agents);
|
|
77340
77375
|
let allAuthenticated = true;
|
|
77341
77376
|
for (const name of agentNames) {
|
|
77342
|
-
const agentDir =
|
|
77377
|
+
const agentDir = resolve30(agentsDir, name);
|
|
77343
77378
|
const status = getAuthStatus(name, agentDir);
|
|
77344
77379
|
if (status.authenticated) {
|
|
77345
77380
|
console.log(` ${source_default.green("OK")} ${source_default.bold(name)}` + source_default.gray(` - authenticated (expires: ${status.timeUntilExpiry ?? "unknown"})`));
|
|
@@ -77439,7 +77474,7 @@ init_loader();
|
|
|
77439
77474
|
init_lifecycle();
|
|
77440
77475
|
import { cpSync as cpSync2, existsSync as existsSync58, mkdirSync as mkdirSync32, readFileSync as readFileSync52, realpathSync as realpathSync6, rmSync as rmSync12, statSync as statSync26, chownSync as chownSync5 } from "node:fs";
|
|
77441
77476
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
77442
|
-
import { join as join61, dirname as
|
|
77477
|
+
import { join as join61, dirname as dirname15, resolve as resolve35 } from "node:path";
|
|
77443
77478
|
import { homedir as homedir37 } from "node:os";
|
|
77444
77479
|
|
|
77445
77480
|
// src/cli/release-yaml.ts
|
|
@@ -77481,7 +77516,7 @@ function defaultPersistPin(configPath) {
|
|
|
77481
77516
|
}
|
|
77482
77517
|
var DEFAULT_COMPOSE_PATH = join61(homedir37(), ".switchroom", "compose", "docker-compose.yml");
|
|
77483
77518
|
function runningFromSwitchroomCheckout(scriptPath) {
|
|
77484
|
-
let dir =
|
|
77519
|
+
let dir = dirname15(scriptPath);
|
|
77485
77520
|
for (let i = 0;i < 12; i++) {
|
|
77486
77521
|
if (existsSync58(join61(dir, ".git"))) {
|
|
77487
77522
|
try {
|
|
@@ -77490,7 +77525,7 @@ function runningFromSwitchroomCheckout(scriptPath) {
|
|
|
77490
77525
|
return true;
|
|
77491
77526
|
} catch {}
|
|
77492
77527
|
}
|
|
77493
|
-
const parent =
|
|
77528
|
+
const parent = dirname15(dir);
|
|
77494
77529
|
if (parent === dir)
|
|
77495
77530
|
break;
|
|
77496
77531
|
dir = parent;
|
|
@@ -77644,7 +77679,7 @@ function planUpdate(opts) {
|
|
|
77644
77679
|
opts.syncBundledSkillsFn();
|
|
77645
77680
|
return;
|
|
77646
77681
|
}
|
|
77647
|
-
const source =
|
|
77682
|
+
const source = resolve35(import.meta.dirname, "../../skills");
|
|
77648
77683
|
const dest = join61(homedir37(), ".switchroom", "skills", "_bundled");
|
|
77649
77684
|
if (!existsSync58(source)) {
|
|
77650
77685
|
process.stderr.write(`switchroom update: sync-bundled-skills \u2014 CLI bundle has no adjacent skills/ at ${source}; skipping.
|
|
@@ -77655,7 +77690,7 @@ function planUpdate(opts) {
|
|
|
77655
77690
|
if (existsSync58(dest)) {
|
|
77656
77691
|
rmSync12(dest, { recursive: true, force: true });
|
|
77657
77692
|
}
|
|
77658
|
-
mkdirSync32(
|
|
77693
|
+
mkdirSync32(dirname15(dest), { recursive: true });
|
|
77659
77694
|
cpSync2(source, dest, { recursive: true, dereference: false });
|
|
77660
77695
|
} catch (err) {
|
|
77661
77696
|
throw new Error(`sync-bundled-skills failed: ${err.message}`);
|
|
@@ -77757,7 +77792,7 @@ function defaultStatusProbe(composePath) {
|
|
|
77757
77792
|
try {
|
|
77758
77793
|
cliBuiltAt = new Date(statSync26(scriptPath).mtimeMs).toISOString();
|
|
77759
77794
|
} catch {}
|
|
77760
|
-
let dir =
|
|
77795
|
+
let dir = dirname15(scriptPath);
|
|
77761
77796
|
for (let i = 0;i < 8; i++) {
|
|
77762
77797
|
const pkgPath = join61(dir, "package.json");
|
|
77763
77798
|
if (existsSync58(pkgPath)) {
|
|
@@ -77770,7 +77805,7 @@ function defaultStatusProbe(composePath) {
|
|
|
77770
77805
|
}
|
|
77771
77806
|
break;
|
|
77772
77807
|
}
|
|
77773
|
-
const parent =
|
|
77808
|
+
const parent = dirname15(dir);
|
|
77774
77809
|
if (parent === dir)
|
|
77775
77810
|
break;
|
|
77776
77811
|
dir = parent;
|
|
@@ -78193,7 +78228,7 @@ init_source();
|
|
|
78193
78228
|
init_helpers();
|
|
78194
78229
|
init_loader();
|
|
78195
78230
|
init_lifecycle();
|
|
78196
|
-
import { resolve as
|
|
78231
|
+
import { resolve as resolve36 } from "node:path";
|
|
78197
78232
|
|
|
78198
78233
|
// src/cli/version.ts
|
|
78199
78234
|
init_source();
|
|
@@ -78201,7 +78236,7 @@ init_helpers();
|
|
|
78201
78236
|
init_lifecycle();
|
|
78202
78237
|
import { execSync as execSync4 } from "node:child_process";
|
|
78203
78238
|
import { existsSync as existsSync59, readFileSync as readFileSync54 } from "node:fs";
|
|
78204
|
-
import { dirname as
|
|
78239
|
+
import { dirname as dirname16, join as join62 } from "node:path";
|
|
78205
78240
|
function getClaudeCodeVersion() {
|
|
78206
78241
|
try {
|
|
78207
78242
|
const out = execSync4("claude --version 2>/dev/null", {
|
|
@@ -78260,7 +78295,7 @@ function locateSwitchroomInstallDir() {
|
|
|
78260
78295
|
}
|
|
78261
78296
|
} catch {}
|
|
78262
78297
|
}
|
|
78263
|
-
dir =
|
|
78298
|
+
dir = dirname16(dir);
|
|
78264
78299
|
}
|
|
78265
78300
|
return null;
|
|
78266
78301
|
}
|
|
@@ -78348,7 +78383,7 @@ function registerRestartCommand(program3) {
|
|
|
78348
78383
|
}
|
|
78349
78384
|
const didRestart = res.restarted || !graceful;
|
|
78350
78385
|
if (didRestart) {
|
|
78351
|
-
const agentDir =
|
|
78386
|
+
const agentDir = resolve36(agentsDir, name);
|
|
78352
78387
|
const converged = waitForAuthConverge(name, agentDir);
|
|
78353
78388
|
if (!converged) {
|
|
78354
78389
|
console.log(source_default.yellow(` ${name}: agent is up but auth status didn't converge in 30s \u2014 check logs`));
|
|
@@ -78429,7 +78464,7 @@ Dependency manifest`));
|
|
|
78429
78464
|
// src/cli/handoff.ts
|
|
78430
78465
|
init_helpers();
|
|
78431
78466
|
init_loader();
|
|
78432
|
-
import { resolve as
|
|
78467
|
+
import { resolve as resolve37 } from "node:path";
|
|
78433
78468
|
function registerHandoffCommand(program3) {
|
|
78434
78469
|
program3.command("handoff <agent>", { hidden: true }).description("Build the agent's session handoff sidecars \u2014 a transcript-tail " + "briefing (.handoff.md) and topic line (.handoff-topic). " + "[internal \u2014 used by the Stop hook]").option("--max-turns <n>", "Max turns kept in the handoff transcript tail", String(DEFAULT_MAX_TURNS)).action(withConfigError(async (agentName, opts) => {
|
|
78435
78470
|
let agentConfig;
|
|
@@ -78443,7 +78478,7 @@ function registerHandoffCommand(program3) {
|
|
|
78443
78478
|
return;
|
|
78444
78479
|
}
|
|
78445
78480
|
const agentsDir = resolveAgentsDir(config);
|
|
78446
|
-
agentDir =
|
|
78481
|
+
agentDir = resolve37(agentsDir, agentName);
|
|
78447
78482
|
} catch (err) {
|
|
78448
78483
|
if (!(err instanceof ConfigError))
|
|
78449
78484
|
throw err;
|
|
@@ -78458,7 +78493,7 @@ function registerHandoffCommand(program3) {
|
|
|
78458
78493
|
`);
|
|
78459
78494
|
return;
|
|
78460
78495
|
}
|
|
78461
|
-
const claudeConfigDir =
|
|
78496
|
+
const claudeConfigDir = resolve37(agentDir, ".claude");
|
|
78462
78497
|
const jsonl = findLatestSessionJsonl(claudeConfigDir);
|
|
78463
78498
|
if (!jsonl) {
|
|
78464
78499
|
process.stderr.write(`handoff: no session JSONL under ${claudeConfigDir}/projects; skipping
|
|
@@ -78967,7 +79002,7 @@ function record(stateDir, input, nowFn = Date.now) {
|
|
|
78967
79002
|
return result;
|
|
78968
79003
|
});
|
|
78969
79004
|
}
|
|
78970
|
-
function
|
|
79005
|
+
function resolve38(stateDir, fingerprint, nowFn = Date.now) {
|
|
78971
79006
|
if (!existsSync60(join63(stateDir, ISSUES_FILE)))
|
|
78972
79007
|
return 0;
|
|
78973
79008
|
return withLock(stateDir, () => {
|
|
@@ -79255,11 +79290,11 @@ function registerIssuesCommand(program3) {
|
|
|
79255
79290
|
const stateDir = resolveStateDir2(opts);
|
|
79256
79291
|
let flipped;
|
|
79257
79292
|
if (opts.source && opts.code) {
|
|
79258
|
-
flipped =
|
|
79293
|
+
flipped = resolve38(stateDir, computeFingerprint(opts.source, opts.code));
|
|
79259
79294
|
} else if (opts.source && !fingerprint) {
|
|
79260
79295
|
flipped = resolveAllBySource(stateDir, opts.source);
|
|
79261
79296
|
} else if (fingerprint) {
|
|
79262
|
-
flipped =
|
|
79297
|
+
flipped = resolve38(stateDir, fingerprint);
|
|
79263
79298
|
} else {
|
|
79264
79299
|
process.stderr.write(`issues resolve: need either <fingerprint>, --source, or --source + --code
|
|
79265
79300
|
`);
|
|
@@ -79356,7 +79391,7 @@ function relTime(deltaMs) {
|
|
|
79356
79391
|
init_source();
|
|
79357
79392
|
import { existsSync as existsSync63 } from "node:fs";
|
|
79358
79393
|
import { homedir as homedir40 } from "node:os";
|
|
79359
|
-
import { join as join66, resolve as
|
|
79394
|
+
import { join as join66, resolve as resolve39 } from "node:path";
|
|
79360
79395
|
|
|
79361
79396
|
// src/deps/python.ts
|
|
79362
79397
|
import { createHash as createHash11 } from "node:crypto";
|
|
@@ -79367,7 +79402,7 @@ import {
|
|
|
79367
79402
|
rmSync as rmSync13,
|
|
79368
79403
|
writeFileSync as writeFileSync29
|
|
79369
79404
|
} from "node:fs";
|
|
79370
|
-
import { dirname as
|
|
79405
|
+
import { dirname as dirname17, join as join64 } from "node:path";
|
|
79371
79406
|
import { homedir as homedir38 } from "node:os";
|
|
79372
79407
|
import { execFileSync as execFileSync19 } from "node:child_process";
|
|
79373
79408
|
|
|
@@ -79414,7 +79449,7 @@ function ensurePythonEnv(opts) {
|
|
|
79414
79449
|
if (existsSync61(venvDir)) {
|
|
79415
79450
|
rmSync13(venvDir, { recursive: true, force: true });
|
|
79416
79451
|
}
|
|
79417
|
-
mkdirSync34(
|
|
79452
|
+
mkdirSync34(dirname17(venvDir), { recursive: true });
|
|
79418
79453
|
try {
|
|
79419
79454
|
execFileSync19(hostPython, ["-m", "venv", venvDir], { stdio: "pipe" });
|
|
79420
79455
|
} catch (err) {
|
|
@@ -79455,7 +79490,7 @@ import {
|
|
|
79455
79490
|
rmSync as rmSync14,
|
|
79456
79491
|
writeFileSync as writeFileSync30
|
|
79457
79492
|
} from "node:fs";
|
|
79458
|
-
import { dirname as
|
|
79493
|
+
import { dirname as dirname18, join as join65 } from "node:path";
|
|
79459
79494
|
import { homedir as homedir39 } from "node:os";
|
|
79460
79495
|
import { execFileSync as execFileSync20 } from "node:child_process";
|
|
79461
79496
|
|
|
@@ -79482,7 +79517,7 @@ function defaultNodeCacheRoot() {
|
|
|
79482
79517
|
return join65(homedir39(), ".switchroom", "deps", "node");
|
|
79483
79518
|
}
|
|
79484
79519
|
function hashDepInputs(packageJsonPath) {
|
|
79485
|
-
const sourceDir =
|
|
79520
|
+
const sourceDir = dirname18(packageJsonPath);
|
|
79486
79521
|
const hasher = createHash12("sha256");
|
|
79487
79522
|
hasher.update(`package.json
|
|
79488
79523
|
`);
|
|
@@ -79507,7 +79542,7 @@ function ensureNodeEnv(opts) {
|
|
|
79507
79542
|
if (!existsSync62(packageJsonPath)) {
|
|
79508
79543
|
throw new NodeEnvError(`package.json not found: ${packageJsonPath}`);
|
|
79509
79544
|
}
|
|
79510
|
-
const sourceDir =
|
|
79545
|
+
const sourceDir = dirname18(packageJsonPath);
|
|
79511
79546
|
const envDir = join65(cacheRoot, skillName);
|
|
79512
79547
|
const stampPath = join65(envDir, ".package.sha256");
|
|
79513
79548
|
const nodeModulesDir = join65(envDir, "node_modules");
|
|
@@ -79563,7 +79598,7 @@ function ensureNodeEnv(opts) {
|
|
|
79563
79598
|
|
|
79564
79599
|
// src/cli/deps.ts
|
|
79565
79600
|
function builtinSkillsRoot() {
|
|
79566
|
-
return
|
|
79601
|
+
return resolve39(homedir40(), ".switchroom/skills/_bundled");
|
|
79567
79602
|
}
|
|
79568
79603
|
function registerDepsCommand(program3) {
|
|
79569
79604
|
const deps = program3.command("deps").description("Manage cached per-skill dependency environments");
|
|
@@ -79642,7 +79677,7 @@ function registerDepsCommand(program3) {
|
|
|
79642
79677
|
init_helpers();
|
|
79643
79678
|
init_loader();
|
|
79644
79679
|
import { existsSync as existsSync64 } from "node:fs";
|
|
79645
|
-
import { resolve as
|
|
79680
|
+
import { resolve as resolve40, sep as sep3 } from "node:path";
|
|
79646
79681
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
79647
79682
|
|
|
79648
79683
|
// src/agents/workspace.ts
|
|
@@ -80348,8 +80383,8 @@ function registerWorkspaceCommand(program3) {
|
|
|
80348
80383
|
const dir = resolveAgentWorkspaceDirOrExit(program3, agentName);
|
|
80349
80384
|
if (!dir)
|
|
80350
80385
|
return;
|
|
80351
|
-
const resolvedWorkspace =
|
|
80352
|
-
const target =
|
|
80386
|
+
const resolvedWorkspace = resolve40(dir);
|
|
80387
|
+
const target = resolve40(resolvedWorkspace, file ?? "AGENTS.md");
|
|
80353
80388
|
if (!isInsideWorkspace(resolvedWorkspace, target)) {
|
|
80354
80389
|
process.stderr.write(`workspace edit: refusing path traversal outside workspace dir (${target})
|
|
80355
80390
|
`);
|
|
@@ -80417,7 +80452,7 @@ function registerWorkspaceCommand(program3) {
|
|
|
80417
80452
|
const dir = resolveAgentWorkspaceDirOrExit(program3, agentName);
|
|
80418
80453
|
if (!dir)
|
|
80419
80454
|
return;
|
|
80420
|
-
const gitDir =
|
|
80455
|
+
const gitDir = resolve40(dir, ".git");
|
|
80421
80456
|
if (!existsSync64(gitDir)) {
|
|
80422
80457
|
process.stdout.write(`Workspace is not a git repository. Re-run \`switchroom agent create ${agentName}\` ` + `or manually \`git init\` in ${dir} to enable versioning.
|
|
80423
80458
|
`);
|
|
@@ -80471,7 +80506,7 @@ function registerWorkspaceCommand(program3) {
|
|
|
80471
80506
|
const dir = resolveAgentWorkspaceDirOrExit(program3, agentName);
|
|
80472
80507
|
if (!dir)
|
|
80473
80508
|
return;
|
|
80474
|
-
const gitDir =
|
|
80509
|
+
const gitDir = resolve40(dir, ".git");
|
|
80475
80510
|
if (!existsSync64(gitDir)) {
|
|
80476
80511
|
process.stdout.write(`Workspace is not a git repository.
|
|
80477
80512
|
`);
|
|
@@ -80495,7 +80530,7 @@ function resolveAgentWorkspaceDirOrExit(program3, agentName) {
|
|
|
80495
80530
|
return;
|
|
80496
80531
|
}
|
|
80497
80532
|
const agentsDir = resolveAgentsDir(config);
|
|
80498
|
-
const agentDir =
|
|
80533
|
+
const agentDir = resolve40(agentsDir, agentName);
|
|
80499
80534
|
const dir = resolveAgentWorkspaceDir(agentDir);
|
|
80500
80535
|
if (!existsSync64(dir)) {
|
|
80501
80536
|
process.stderr.write(`workspace: ${dir} does not exist yet. Run \`switchroom setup\` or \`switchroom agent scaffold ${agentName}\` to seed it.
|
|
@@ -80534,7 +80569,7 @@ init_helpers();
|
|
|
80534
80569
|
init_loader();
|
|
80535
80570
|
init_merge();
|
|
80536
80571
|
import { copyFileSync as copyFileSync10, existsSync as existsSync65, readFileSync as readFileSync58, writeFileSync as writeFileSync31 } from "node:fs";
|
|
80537
|
-
import { join as join67, resolve as
|
|
80572
|
+
import { join as join67, resolve as resolve41 } from "node:path";
|
|
80538
80573
|
init_schema();
|
|
80539
80574
|
function resolveSoulTargetOrExit(program3, agentName) {
|
|
80540
80575
|
const config = getConfig(program3);
|
|
@@ -80547,7 +80582,7 @@ function resolveSoulTargetOrExit(program3, agentName) {
|
|
|
80547
80582
|
const profileName = merged.extends ?? DEFAULT_PROFILE;
|
|
80548
80583
|
const profilePath = getProfilePath(profileName);
|
|
80549
80584
|
const agentsDir = resolveAgentsDir(config);
|
|
80550
|
-
const agentDir =
|
|
80585
|
+
const agentDir = resolve41(agentsDir, agentName);
|
|
80551
80586
|
const workspaceDir = resolveAgentWorkspaceDir(agentDir);
|
|
80552
80587
|
if (!existsSync65(workspaceDir)) {
|
|
80553
80588
|
console.error(`soul: ${workspaceDir} does not exist yet. Run \`switchroom setup\` ` + `or \`switchroom agent scaffold ${agentName}\` to seed it.`);
|
|
@@ -80625,7 +80660,7 @@ function registerSoulCommand(program3) {
|
|
|
80625
80660
|
init_helpers();
|
|
80626
80661
|
init_loader();
|
|
80627
80662
|
import { existsSync as existsSync66, readFileSync as readFileSync59, readdirSync as readdirSync23, statSync as statSync29 } from "node:fs";
|
|
80628
|
-
import { resolve as
|
|
80663
|
+
import { resolve as resolve42, join as join68 } from "node:path";
|
|
80629
80664
|
import { createHash as createHash13 } from "node:crypto";
|
|
80630
80665
|
init_merge();
|
|
80631
80666
|
init_hindsight();
|
|
@@ -80723,7 +80758,7 @@ function registerDebugCommand(program3) {
|
|
|
80723
80758
|
process.exit(1);
|
|
80724
80759
|
}
|
|
80725
80760
|
const agentsDir = resolveAgentsDir(config);
|
|
80726
|
-
const agentDir =
|
|
80761
|
+
const agentDir = resolve42(agentsDir, agentName);
|
|
80727
80762
|
if (!existsSync66(agentDir)) {
|
|
80728
80763
|
console.error(`Agent directory not found: ${agentDir}`);
|
|
80729
80764
|
process.exit(1);
|
|
@@ -80900,7 +80935,7 @@ init_source();
|
|
|
80900
80935
|
// src/worktree/claim.ts
|
|
80901
80936
|
import { execFileSync as execFileSync21 } from "node:child_process";
|
|
80902
80937
|
import { closeSync as closeSync12, mkdirSync as mkdirSync37, openSync as openSync12, existsSync as existsSync68, unlinkSync as unlinkSync13 } from "node:fs";
|
|
80903
|
-
import { join as join70, resolve as
|
|
80938
|
+
import { join as join70, resolve as resolve44 } from "node:path";
|
|
80904
80939
|
import { homedir as homedir42 } from "node:os";
|
|
80905
80940
|
import { randomBytes as randomBytes13 } from "node:crypto";
|
|
80906
80941
|
|
|
@@ -80914,10 +80949,10 @@ import {
|
|
|
80914
80949
|
existsSync as existsSync67,
|
|
80915
80950
|
renameSync as renameSync13
|
|
80916
80951
|
} from "node:fs";
|
|
80917
|
-
import { join as join69, resolve as
|
|
80952
|
+
import { join as join69, resolve as resolve43 } from "node:path";
|
|
80918
80953
|
import { homedir as homedir41 } from "node:os";
|
|
80919
80954
|
function registryDir() {
|
|
80920
|
-
return
|
|
80955
|
+
return resolve43(process.env.SWITCHROOM_WORKTREE_DIR ?? join69(homedir41(), ".switchroom", "worktrees"));
|
|
80921
80956
|
}
|
|
80922
80957
|
function recordPath(id) {
|
|
80923
80958
|
return join69(registryDir(), `${id}.json`);
|
|
@@ -80998,7 +81033,7 @@ function acquireRepoLock(repoPath) {
|
|
|
80998
81033
|
}
|
|
80999
81034
|
var DEFAULT_CONCURRENCY = 5;
|
|
81000
81035
|
function worktreesBaseDir() {
|
|
81001
|
-
return
|
|
81036
|
+
return resolve44(process.env.SWITCHROOM_WORKTREE_BASE ?? join70(homedir42(), ".switchroom", "worktree-checkouts"));
|
|
81002
81037
|
}
|
|
81003
81038
|
function shortId() {
|
|
81004
81039
|
return randomBytes13(4).toString("hex");
|
|
@@ -81662,7 +81697,7 @@ function registerDriveMcpLauncherCommand(program3) {
|
|
|
81662
81697
|
init_scaffold_integration();
|
|
81663
81698
|
import { spawn as spawn5 } from "node:child_process";
|
|
81664
81699
|
import { writeFileSync as writeFileSync34, mkdirSync as mkdirSync39 } from "node:fs";
|
|
81665
|
-
import { dirname as
|
|
81700
|
+
import { dirname as dirname19, join as join72 } from "node:path";
|
|
81666
81701
|
var SOFTERIA_TOKEN_ENV = "MS365_MCP_OAUTH_TOKEN";
|
|
81667
81702
|
var DEFAULT_REFRESH_LEAD_MS = 5 * 60 * 1000;
|
|
81668
81703
|
var MAX_REFRESH_INTERVAL_MS = 60 * 60 * 1000;
|
|
@@ -81687,7 +81722,7 @@ function computeRefreshDelayMs(expiresAt, now, leadMs = DEFAULT_REFRESH_LEAD_MS)
|
|
|
81687
81722
|
function writeRefreshHeartbeat(agentName, data) {
|
|
81688
81723
|
const path7 = heartbeatPath(agentName);
|
|
81689
81724
|
try {
|
|
81690
|
-
mkdirSync39(
|
|
81725
|
+
mkdirSync39(dirname19(path7), { recursive: true });
|
|
81691
81726
|
writeFileSync34(path7, JSON.stringify(data, null, 2), { mode: 420 });
|
|
81692
81727
|
} catch {}
|
|
81693
81728
|
}
|
|
@@ -81718,20 +81753,20 @@ function wireStdio(child) {
|
|
|
81718
81753
|
async function killChild(child, gracefulMs = 3000) {
|
|
81719
81754
|
if (child.exitCode !== null || child.signalCode !== null)
|
|
81720
81755
|
return;
|
|
81721
|
-
return new Promise((
|
|
81756
|
+
return new Promise((resolve45) => {
|
|
81722
81757
|
let killTimer = null;
|
|
81723
81758
|
const onExit = () => {
|
|
81724
81759
|
if (killTimer) {
|
|
81725
81760
|
clearTimeout(killTimer);
|
|
81726
81761
|
killTimer = null;
|
|
81727
81762
|
}
|
|
81728
|
-
|
|
81763
|
+
resolve45();
|
|
81729
81764
|
};
|
|
81730
81765
|
child.once("exit", onExit);
|
|
81731
81766
|
try {
|
|
81732
81767
|
child.kill("SIGTERM");
|
|
81733
81768
|
} catch {
|
|
81734
|
-
|
|
81769
|
+
resolve45();
|
|
81735
81770
|
return;
|
|
81736
81771
|
}
|
|
81737
81772
|
killTimer = setTimeout(() => {
|
|
@@ -81845,8 +81880,8 @@ async function runMs365McpLauncher(opts, rt) {
|
|
|
81845
81880
|
};
|
|
81846
81881
|
process.on("SIGINT", onSignal);
|
|
81847
81882
|
process.on("SIGTERM", onSignal);
|
|
81848
|
-
return new Promise((
|
|
81849
|
-
resolveLauncher =
|
|
81883
|
+
return new Promise((resolve45) => {
|
|
81884
|
+
resolveLauncher = resolve45;
|
|
81850
81885
|
});
|
|
81851
81886
|
}
|
|
81852
81887
|
function registerM365McpLauncherCommand(program3) {
|
|
@@ -81880,7 +81915,7 @@ function registerM365McpLauncherCommand(program3) {
|
|
|
81880
81915
|
init_scaffold_integration();
|
|
81881
81916
|
import { spawn as spawn6 } from "node:child_process";
|
|
81882
81917
|
import { existsSync as existsSync71, mkdirSync as mkdirSync40, writeFileSync as writeFileSync35 } from "node:fs";
|
|
81883
|
-
import { dirname as
|
|
81918
|
+
import { dirname as dirname20 } from "node:path";
|
|
81884
81919
|
var HEARTBEAT_WRITE_INTERVAL_MS = 30 * 1000;
|
|
81885
81920
|
var DEFAULT_HEARTBEAT_PATH = "/state/agent/notion-launcher.heartbeat.json";
|
|
81886
81921
|
var DEFAULT_VAULT_KEY = "notion/integration-token";
|
|
@@ -81890,7 +81925,7 @@ function buildNotionMcpArgs(opts) {
|
|
|
81890
81925
|
}
|
|
81891
81926
|
function defaultWriteHeartbeat(path7, contents) {
|
|
81892
81927
|
try {
|
|
81893
|
-
const dir =
|
|
81928
|
+
const dir = dirname20(path7);
|
|
81894
81929
|
if (!existsSync71(dir))
|
|
81895
81930
|
mkdirSync40(dir, { recursive: true });
|
|
81896
81931
|
writeFileSync35(path7, contents);
|
|
@@ -81948,23 +81983,23 @@ async function runNotionMcpLauncher(opts, runtime) {
|
|
|
81948
81983
|
};
|
|
81949
81984
|
process.on("SIGTERM", () => forward("SIGTERM"));
|
|
81950
81985
|
process.on("SIGINT", () => forward("SIGINT"));
|
|
81951
|
-
const exitCode = await new Promise((
|
|
81986
|
+
const exitCode = await new Promise((resolve45) => {
|
|
81952
81987
|
child.once("exit", (code, signal) => {
|
|
81953
81988
|
clearTimer(heartbeatHandle);
|
|
81954
81989
|
if (typeof code === "number") {
|
|
81955
|
-
|
|
81990
|
+
resolve45(code);
|
|
81956
81991
|
} else if (signal) {
|
|
81957
81992
|
const sigCode = { SIGTERM: 15, SIGINT: 2, SIGKILL: 9 }[signal] ?? 1;
|
|
81958
|
-
|
|
81993
|
+
resolve45(128 + sigCode);
|
|
81959
81994
|
} else {
|
|
81960
|
-
|
|
81995
|
+
resolve45(1);
|
|
81961
81996
|
}
|
|
81962
81997
|
});
|
|
81963
81998
|
child.once("error", (err) => {
|
|
81964
81999
|
clearTimer(heartbeatHandle);
|
|
81965
82000
|
process.stderr.write(`notion-mcp-launcher: child spawn error: ${err.message}
|
|
81966
82001
|
`);
|
|
81967
|
-
|
|
82002
|
+
resolve45(1);
|
|
81968
82003
|
});
|
|
81969
82004
|
});
|
|
81970
82005
|
return exitCode;
|
|
@@ -83022,7 +83057,7 @@ agents:
|
|
|
83022
83057
|
|
|
83023
83058
|
// src/cli/apply.ts
|
|
83024
83059
|
init_resolver();
|
|
83025
|
-
import { dirname as
|
|
83060
|
+
import { dirname as dirname23, join as join75, resolve as resolve46 } from "node:path";
|
|
83026
83061
|
import { homedir as homedir44 } from "node:os";
|
|
83027
83062
|
import { execFileSync as execFileSync24 } from "node:child_process";
|
|
83028
83063
|
init_vault();
|
|
@@ -83219,7 +83254,7 @@ var COMPOSE_PROJECT2 = "switchroom";
|
|
|
83219
83254
|
function resolveVaultBindMountDir(homeDir, ctx) {
|
|
83220
83255
|
const isCustomPath = ctx.migrationKind === "custom-path-skipped";
|
|
83221
83256
|
if (isCustomPath && ctx.customVaultPath) {
|
|
83222
|
-
return
|
|
83257
|
+
return dirname23(ctx.customVaultPath);
|
|
83223
83258
|
}
|
|
83224
83259
|
return join75(homeDir, ".switchroom", "vault");
|
|
83225
83260
|
}
|
|
@@ -83624,7 +83659,7 @@ function copyExampleConfig2(name) {
|
|
|
83624
83659
|
if (!/^[a-z0-9_-]+$/.test(name)) {
|
|
83625
83660
|
throw new Error(`Invalid example name: ${name} (must match /^[a-z0-9_-]+$/)`);
|
|
83626
83661
|
}
|
|
83627
|
-
const dest =
|
|
83662
|
+
const dest = resolve46(process.cwd(), "switchroom.yaml");
|
|
83628
83663
|
if (existsSync74(dest)) {
|
|
83629
83664
|
console.error(source_default.yellow("switchroom.yaml already exists \u2014 skipping example copy"));
|
|
83630
83665
|
return;
|
|
@@ -83635,7 +83670,7 @@ function copyExampleConfig2(name) {
|
|
|
83635
83670
|
console.log(source_default.green(`Copied ${name}.yaml -> switchroom.yaml`));
|
|
83636
83671
|
return;
|
|
83637
83672
|
}
|
|
83638
|
-
const exampleFile =
|
|
83673
|
+
const exampleFile = resolve46(import.meta.dirname, `../../examples/${name}.yaml`);
|
|
83639
83674
|
if (!existsSync74(exampleFile)) {
|
|
83640
83675
|
throw new Error(`Example config not found: ${name}.yaml (available: ${Object.keys(EMBEDDED_EXAMPLES).join(", ")})`);
|
|
83641
83676
|
}
|
|
@@ -84213,10 +84248,10 @@ import {
|
|
|
84213
84248
|
unlinkSync as unlinkSync14,
|
|
84214
84249
|
writeSync as writeSync8
|
|
84215
84250
|
} from "node:fs";
|
|
84216
|
-
import { join as join77, resolve as
|
|
84251
|
+
import { join as join77, resolve as resolve47 } from "node:path";
|
|
84217
84252
|
var STAGING_SUBDIR = ".staging";
|
|
84218
84253
|
function overlayPathsFor(agent, opts = {}) {
|
|
84219
|
-
const base = opts.root ?
|
|
84254
|
+
const base = opts.root ? resolve47(opts.root, agent) : resolve47(resolveDualPath(`~/.switchroom/agents/${agent}`));
|
|
84220
84255
|
const scheduleDir = join77(base, "schedule.d");
|
|
84221
84256
|
const scheduleStagingDir = join77(scheduleDir, STAGING_SUBDIR);
|
|
84222
84257
|
const skillsDir = join77(base, "skills.d");
|
|
@@ -85459,7 +85494,7 @@ function registerAgentConfigSkillWriteCommands(program3) {
|
|
|
85459
85494
|
import {
|
|
85460
85495
|
closeSync as closeSync15,
|
|
85461
85496
|
existsSync as existsSync80,
|
|
85462
|
-
lstatSync as
|
|
85497
|
+
lstatSync as lstatSync9,
|
|
85463
85498
|
mkdirSync as mkdirSync45,
|
|
85464
85499
|
mkdtempSync as mkdtempSync5,
|
|
85465
85500
|
openSync as openSync15,
|
|
@@ -85472,7 +85507,7 @@ import {
|
|
|
85472
85507
|
writeFileSync as writeFileSync39
|
|
85473
85508
|
} from "node:fs";
|
|
85474
85509
|
import { tmpdir as tmpdir5, homedir as homedir46 } from "node:os";
|
|
85475
|
-
import { dirname as
|
|
85510
|
+
import { dirname as dirname24, join as join80, relative as relative2, resolve as resolve48 } from "node:path";
|
|
85476
85511
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
85477
85512
|
|
|
85478
85513
|
// src/cli/skill-common.ts
|
|
@@ -85670,7 +85705,7 @@ function resolveSkillsPoolDir2(override) {
|
|
|
85670
85705
|
}
|
|
85671
85706
|
if (raw === "~")
|
|
85672
85707
|
return homedir46();
|
|
85673
|
-
return
|
|
85708
|
+
return resolve48(raw);
|
|
85674
85709
|
}
|
|
85675
85710
|
function readStdinSync() {
|
|
85676
85711
|
const chunks = [];
|
|
@@ -85889,7 +85924,7 @@ function writePayload(poolDir, name, files) {
|
|
|
85889
85924
|
const target = join80(poolDir, name);
|
|
85890
85925
|
let targetIsSymlink = false;
|
|
85891
85926
|
try {
|
|
85892
|
-
const st =
|
|
85927
|
+
const st = lstatSync9(target);
|
|
85893
85928
|
if (st.isSymbolicLink()) {
|
|
85894
85929
|
targetIsSymlink = true;
|
|
85895
85930
|
}
|
|
@@ -85902,7 +85937,7 @@ function writePayload(poolDir, name, files) {
|
|
|
85902
85937
|
try {
|
|
85903
85938
|
for (const [path8, content] of Object.entries(files)) {
|
|
85904
85939
|
const full = join80(staging, path8);
|
|
85905
|
-
mkdirSync45(
|
|
85940
|
+
mkdirSync45(dirname24(full), { recursive: true, mode: 493 });
|
|
85906
85941
|
const fd = openSync15(full, "wx");
|
|
85907
85942
|
try {
|
|
85908
85943
|
writeFileSync39(fd, content);
|
|
@@ -85916,7 +85951,7 @@ function writePayload(poolDir, name, files) {
|
|
|
85916
85951
|
}
|
|
85917
85952
|
let targetExists = false;
|
|
85918
85953
|
try {
|
|
85919
|
-
|
|
85954
|
+
lstatSync9(target);
|
|
85920
85955
|
targetExists = true;
|
|
85921
85956
|
} catch {}
|
|
85922
85957
|
if (targetExists) {
|
|
@@ -85954,7 +85989,7 @@ function registerSkillCommand(program3) {
|
|
|
85954
85989
|
if (opts.from === undefined) {
|
|
85955
85990
|
files = loadFromStdin();
|
|
85956
85991
|
} else {
|
|
85957
|
-
const fromPath =
|
|
85992
|
+
const fromPath = resolve48(opts.from);
|
|
85958
85993
|
if (!existsSync80(fromPath)) {
|
|
85959
85994
|
fail3(`--from path does not exist: ${opts.from}`);
|
|
85960
85995
|
}
|
|
@@ -86011,7 +86046,7 @@ function sumBytes(files) {
|
|
|
86011
86046
|
import {
|
|
86012
86047
|
closeSync as closeSync16,
|
|
86013
86048
|
existsSync as existsSync81,
|
|
86014
|
-
lstatSync as
|
|
86049
|
+
lstatSync as lstatSync10,
|
|
86015
86050
|
mkdirSync as mkdirSync46,
|
|
86016
86051
|
mkdtempSync as mkdtempSync6,
|
|
86017
86052
|
openSync as openSync16,
|
|
@@ -86023,7 +86058,7 @@ import {
|
|
|
86023
86058
|
utimesSync,
|
|
86024
86059
|
writeFileSync as writeFileSync40
|
|
86025
86060
|
} from "node:fs";
|
|
86026
|
-
import { dirname as
|
|
86061
|
+
import { dirname as dirname25, join as join81, relative as relative3, resolve as resolve49 } from "node:path";
|
|
86027
86062
|
import { homedir as homedir47, tmpdir as tmpdir6 } from "node:os";
|
|
86028
86063
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
86029
86064
|
init_helpers();
|
|
@@ -86034,7 +86069,7 @@ var TRASH_TTL_MS = 24 * 60 * 60 * 1000;
|
|
|
86034
86069
|
var PERSONAL_SKILLS_SUBPATH = "personal-skills";
|
|
86035
86070
|
function resolveConfigSkillsDir(agent) {
|
|
86036
86071
|
const override = process.env.SWITCHROOM_CONFIG_DIR;
|
|
86037
|
-
const candidate = override ?
|
|
86072
|
+
const candidate = override ? resolve49(override) : join81(homedir47(), ".switchroom-config");
|
|
86038
86073
|
if (!existsSync81(candidate))
|
|
86039
86074
|
return null;
|
|
86040
86075
|
return join81(candidate, "agents", agent, PERSONAL_SKILLS_SUBPATH);
|
|
@@ -86068,7 +86103,7 @@ function mirrorToConfigRepo(agent, name, liveSkillDir) {
|
|
|
86068
86103
|
try {
|
|
86069
86104
|
if (liveSkillDir !== null) {
|
|
86070
86105
|
try {
|
|
86071
|
-
const st =
|
|
86106
|
+
const st = lstatSync10(liveSkillDir);
|
|
86072
86107
|
if (st.isSymbolicLink()) {
|
|
86073
86108
|
process.stderr.write(source_default.yellow(`warning: refusing to mirror ${liveSkillDir} \u2014 source is a symlink
|
|
86074
86109
|
`));
|
|
@@ -86129,7 +86164,7 @@ function resolveAgent(opts) {
|
|
|
86129
86164
|
}
|
|
86130
86165
|
function resolveAgentsRoot(opts) {
|
|
86131
86166
|
if (opts.root)
|
|
86132
|
-
return
|
|
86167
|
+
return resolve49(opts.root);
|
|
86133
86168
|
return join81(homedir47(), ".switchroom", "agents");
|
|
86134
86169
|
}
|
|
86135
86170
|
function personalSkillDir(agentsRoot, agent, name) {
|
|
@@ -86159,7 +86194,7 @@ function readStdinSync2() {
|
|
|
86159
86194
|
return Buffer.concat(chunks).toString("utf-8");
|
|
86160
86195
|
}
|
|
86161
86196
|
function loadFromDir2(dir) {
|
|
86162
|
-
const abs =
|
|
86197
|
+
const abs = resolve49(dir);
|
|
86163
86198
|
if (!statSync33(abs).isDirectory()) {
|
|
86164
86199
|
fail4(`--from path is not a directory: ${dir}`);
|
|
86165
86200
|
}
|
|
@@ -86256,7 +86291,7 @@ function sweepTrash(agentsRoot, agent) {
|
|
|
86256
86291
|
function writePersonalSkill(targetDir, files) {
|
|
86257
86292
|
let targetIsSymlink = false;
|
|
86258
86293
|
try {
|
|
86259
|
-
const st =
|
|
86294
|
+
const st = lstatSync10(targetDir);
|
|
86260
86295
|
if (st.isSymbolicLink()) {
|
|
86261
86296
|
targetIsSymlink = true;
|
|
86262
86297
|
}
|
|
@@ -86264,13 +86299,13 @@ function writePersonalSkill(targetDir, files) {
|
|
|
86264
86299
|
if (targetIsSymlink) {
|
|
86265
86300
|
fail4(`refusing to overwrite symlink at ${targetDir}; investigate manually`);
|
|
86266
86301
|
}
|
|
86267
|
-
mkdirSync46(
|
|
86268
|
-
const staging = mkdtempSync6(join81(
|
|
86302
|
+
mkdirSync46(dirname25(targetDir), { recursive: true, mode: 493 });
|
|
86303
|
+
const staging = mkdtempSync6(join81(dirname25(targetDir), `.skill-personal-stage-`));
|
|
86269
86304
|
let oldRename = null;
|
|
86270
86305
|
try {
|
|
86271
86306
|
for (const [path8, content] of Object.entries(files)) {
|
|
86272
86307
|
const full = join81(staging, path8);
|
|
86273
|
-
mkdirSync46(
|
|
86308
|
+
mkdirSync46(dirname25(full), { recursive: true, mode: 493 });
|
|
86274
86309
|
const fd = openSync16(full, "wx");
|
|
86275
86310
|
try {
|
|
86276
86311
|
writeFileSync40(fd, content);
|
|
@@ -86284,7 +86319,7 @@ function writePersonalSkill(targetDir, files) {
|
|
|
86284
86319
|
}
|
|
86285
86320
|
let targetExists = false;
|
|
86286
86321
|
try {
|
|
86287
|
-
|
|
86322
|
+
lstatSync10(targetDir);
|
|
86288
86323
|
targetExists = true;
|
|
86289
86324
|
} catch {}
|
|
86290
86325
|
if (targetExists) {
|
|
@@ -86319,7 +86354,7 @@ function loadValidateWrite(agentsRoot, agent, name, files, ensureNew) {
|
|
|
86319
86354
|
const target = personalSkillDir(agentsRoot, agent, name);
|
|
86320
86355
|
const exists = (() => {
|
|
86321
86356
|
try {
|
|
86322
|
-
|
|
86357
|
+
lstatSync10(target);
|
|
86323
86358
|
return true;
|
|
86324
86359
|
} catch {
|
|
86325
86360
|
return false;
|
|
@@ -86353,7 +86388,7 @@ function loadFiles(opts) {
|
|
|
86353
86388
|
if (opts.from === undefined) {
|
|
86354
86389
|
return loadFromStdin2();
|
|
86355
86390
|
}
|
|
86356
|
-
const p =
|
|
86391
|
+
const p = resolve49(opts.from);
|
|
86357
86392
|
if (!existsSync81(p)) {
|
|
86358
86393
|
fail4(`--from path does not exist: ${opts.from}`);
|
|
86359
86394
|
}
|
|
@@ -86419,7 +86454,7 @@ function resolveCloneSource(source, opts) {
|
|
|
86419
86454
|
if (!existsSync81(dir)) {
|
|
86420
86455
|
fail4(`clone source ${JSON.stringify(source)} not found at ${dir}; ` + `check \`switchroom skill search --tier ${tier}\``, 1);
|
|
86421
86456
|
}
|
|
86422
|
-
const st =
|
|
86457
|
+
const st = lstatSync10(dir);
|
|
86423
86458
|
if (st.isSymbolicLink()) {
|
|
86424
86459
|
fail4(`clone source ${JSON.stringify(source)} is a symlink at ${dir}; ` + `point clone at the canonical pool path instead`);
|
|
86425
86460
|
}
|
|
@@ -86446,7 +86481,7 @@ function readSourceFiles(dir) {
|
|
|
86446
86481
|
continue;
|
|
86447
86482
|
}
|
|
86448
86483
|
try {
|
|
86449
|
-
const st =
|
|
86484
|
+
const st = lstatSync10(full);
|
|
86450
86485
|
if (st.size > CLONE_MAX_FILE_BYTES) {
|
|
86451
86486
|
fail4(`clone source has oversized file ${rel} (${st.size} bytes > ${CLONE_MAX_FILE_BYTES}); ` + `refuse to read`, 3);
|
|
86452
86487
|
}
|
|
@@ -86528,7 +86563,7 @@ function removePersonalAction(name, opts) {
|
|
|
86528
86563
|
}
|
|
86529
86564
|
const target = personalSkillDir(agentsRoot, agent, name);
|
|
86530
86565
|
try {
|
|
86531
|
-
const st =
|
|
86566
|
+
const st = lstatSync10(target);
|
|
86532
86567
|
if (st.isSymbolicLink()) {
|
|
86533
86568
|
fail4(`refusing to remove symlink at ${target}; investigate manually`);
|
|
86534
86569
|
}
|
|
@@ -86622,18 +86657,18 @@ init_helpers();
|
|
|
86622
86657
|
var import_yaml24 = __toESM(require_dist(), 1);
|
|
86623
86658
|
import { existsSync as existsSync82, readdirSync as readdirSync32, readFileSync as readFileSync70, statSync as statSync34 } from "node:fs";
|
|
86624
86659
|
import { homedir as homedir48 } from "node:os";
|
|
86625
|
-
import { join as join82, resolve as
|
|
86660
|
+
import { join as join82, resolve as resolve50 } from "node:path";
|
|
86626
86661
|
var PERSONAL_PREFIX2 = "personal-";
|
|
86627
86662
|
var BUNDLED_SUBDIR = "_bundled";
|
|
86628
86663
|
var AGENT_NAME_RE3 = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
86629
86664
|
function defaultAgentsRoot() {
|
|
86630
|
-
return
|
|
86665
|
+
return resolve50(homedir48(), ".switchroom/agents");
|
|
86631
86666
|
}
|
|
86632
86667
|
function defaultSharedRoot2() {
|
|
86633
|
-
return
|
|
86668
|
+
return resolve50(homedir48(), ".switchroom/skills");
|
|
86634
86669
|
}
|
|
86635
86670
|
function defaultBundledRoot2() {
|
|
86636
|
-
return
|
|
86671
|
+
return resolve50(homedir48(), ".switchroom/skills/_bundled");
|
|
86637
86672
|
}
|
|
86638
86673
|
function readSkillFrontmatter(skillDir) {
|
|
86639
86674
|
const mdPath = join82(skillDir, "SKILL.md");
|
|
@@ -86916,7 +86951,46 @@ init_helpers();
|
|
|
86916
86951
|
import { existsSync as existsSync84, mkdirSync as mkdirSync47, readdirSync as readdirSync33, readFileSync as readFileSync72, writeFileSync as writeFileSync41, statSync as statSync35, copyFileSync as copyFileSync12 } from "node:fs";
|
|
86917
86952
|
import { homedir as homedir49 } from "node:os";
|
|
86918
86953
|
import { join as join83 } from "node:path";
|
|
86954
|
+
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
86955
|
+
|
|
86956
|
+
// src/cli/deploy-version-guard.ts
|
|
86919
86957
|
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
86958
|
+
var defaultRunner2 = (args) => {
|
|
86959
|
+
const r = spawnSync15("docker", args, { encoding: "utf8" });
|
|
86960
|
+
return { ok: r.status === 0, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
86961
|
+
};
|
|
86962
|
+
function deployedImageTag(container, run = defaultRunner2) {
|
|
86963
|
+
const r = run(["inspect", "-f", "{{.Config.Image}}", container]);
|
|
86964
|
+
if (!r.ok)
|
|
86965
|
+
return null;
|
|
86966
|
+
const ref = r.stdout.trim();
|
|
86967
|
+
if (!ref)
|
|
86968
|
+
return null;
|
|
86969
|
+
const noDigest = ref.split("@")[0];
|
|
86970
|
+
const colon = noDigest.lastIndexOf(":");
|
|
86971
|
+
if (colon < 0)
|
|
86972
|
+
return null;
|
|
86973
|
+
const tag = noDigest.slice(colon + 1);
|
|
86974
|
+
return tag && !tag.includes("/") ? tag : null;
|
|
86975
|
+
}
|
|
86976
|
+
function checkDowngrade(opts) {
|
|
86977
|
+
const running = deployedImageTag(opts.container, opts.run);
|
|
86978
|
+
if (opts.allowDowngrade)
|
|
86979
|
+
return { skip: false, running };
|
|
86980
|
+
const cmp = compareReleaseTags(opts.targetTag, running);
|
|
86981
|
+
if (cmp !== null && cmp < 0) {
|
|
86982
|
+
return {
|
|
86983
|
+
skip: true,
|
|
86984
|
+
running,
|
|
86985
|
+
message: `Skipping ${opts.container} deploy \u2014 it is already on ${running}, newer than the ` + `requested ${opts.targetTag}.
|
|
86986
|
+
` + ` Refusing to downgrade: this guards against a concurrent rollout/update ` + `reverting a newer build.
|
|
86987
|
+
` + ` To force the downgrade, re-run with --allow-downgrade.`
|
|
86988
|
+
};
|
|
86989
|
+
}
|
|
86990
|
+
return { skip: false, running };
|
|
86991
|
+
}
|
|
86992
|
+
|
|
86993
|
+
// src/cli/hostd.ts
|
|
86920
86994
|
init_audit_reader();
|
|
86921
86995
|
function resolveHostdImageTag(explicitTag, release) {
|
|
86922
86996
|
if (explicitTag)
|
|
@@ -87054,7 +87128,7 @@ function backupExistingCompose() {
|
|
|
87054
87128
|
return bak;
|
|
87055
87129
|
}
|
|
87056
87130
|
function runDocker(args) {
|
|
87057
|
-
const r =
|
|
87131
|
+
const r = spawnSync16("docker", args, { encoding: "utf8" });
|
|
87058
87132
|
return {
|
|
87059
87133
|
ok: r.status === 0,
|
|
87060
87134
|
stdout: r.stdout ?? "",
|
|
@@ -87081,6 +87155,15 @@ async function doInstall(opts, program3) {
|
|
|
87081
87155
|
const composePath = hostdComposePath();
|
|
87082
87156
|
mkdirSync47(dir, { recursive: true });
|
|
87083
87157
|
const imageTag = resolveHostdImageTag(opts.tag, cfg.release);
|
|
87158
|
+
const guard = checkDowngrade({
|
|
87159
|
+
container: "switchroom-hostd",
|
|
87160
|
+
targetTag: imageTag,
|
|
87161
|
+
allowDowngrade: opts.allowDowngrade
|
|
87162
|
+
});
|
|
87163
|
+
if (guard.skip) {
|
|
87164
|
+
console.log(source_default.yellow(` \u23ed ${opts.dryRun ? "[dry-run] " : ""}${guard.message}`));
|
|
87165
|
+
return;
|
|
87166
|
+
}
|
|
87084
87167
|
const yaml = renderHostdComposeFile({
|
|
87085
87168
|
hostHome: resolveHostdHostHome(),
|
|
87086
87169
|
imageTag,
|
|
@@ -87190,7 +87273,7 @@ ${down.stderr}`));
|
|
|
87190
87273
|
}
|
|
87191
87274
|
function registerHostdCommand(program3) {
|
|
87192
87275
|
const hostd = program3.command("hostd").description("Manage switchroom-hostd, the host-control daemon for admin agents (RFC C)");
|
|
87193
|
-
hostd.command("install").description("Install or refresh the hostd container (writes ~/.switchroom/hostd/docker-compose.yml + docker compose up -d)").option("--tag <tag>", "Image tag override (default: resolved from release.pin in switchroom.yaml, else latest)").option("--dry-run", "Print the compose file and the docker commands without writing or running anything").action(withConfigError(async (opts) => {
|
|
87276
|
+
hostd.command("install").description("Install or refresh the hostd container (writes ~/.switchroom/hostd/docker-compose.yml + docker compose up -d)").option("--tag <tag>", "Image tag override (default: resolved from release.pin in switchroom.yaml, else latest)").option("--dry-run", "Print the compose file and the docker commands without writing or running anything").option("--allow-downgrade", "Deploy even if the running container is on a newer version (overrides the anti-revert guard)").action(withConfigError(async (opts) => {
|
|
87194
87277
|
await doInstall(opts, program3);
|
|
87195
87278
|
}));
|
|
87196
87279
|
hostd.command("status").description("Show daemon state and bound sockets").action(() => doStatus());
|
|
@@ -87247,7 +87330,7 @@ init_helpers();
|
|
|
87247
87330
|
import { existsSync as existsSync85, mkdirSync as mkdirSync48, writeFileSync as writeFileSync42, copyFileSync as copyFileSync13 } from "node:fs";
|
|
87248
87331
|
import { homedir as homedir50 } from "node:os";
|
|
87249
87332
|
import { join as join84 } from "node:path";
|
|
87250
|
-
import { spawnSync as
|
|
87333
|
+
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
87251
87334
|
function resolveWebImageTag(explicitTag, release) {
|
|
87252
87335
|
if (explicitTag)
|
|
87253
87336
|
return explicitTag;
|
|
@@ -87346,7 +87429,7 @@ function backupExistingCompose2() {
|
|
|
87346
87429
|
return bak;
|
|
87347
87430
|
}
|
|
87348
87431
|
function runDocker2(args) {
|
|
87349
|
-
const r =
|
|
87432
|
+
const r = spawnSync17("docker", args, { encoding: "utf8" });
|
|
87350
87433
|
return {
|
|
87351
87434
|
ok: r.status === 0,
|
|
87352
87435
|
stdout: r.stdout ?? "",
|
|
@@ -87366,6 +87449,15 @@ async function doInstall2(opts, program3) {
|
|
|
87366
87449
|
mkdirSync48(dir, { recursive: true });
|
|
87367
87450
|
const cfg = getConfig(program3);
|
|
87368
87451
|
const imageTag = resolveWebImageTag(opts.tag, cfg.release);
|
|
87452
|
+
const guard = checkDowngrade({
|
|
87453
|
+
container: "switchroom-web",
|
|
87454
|
+
targetTag: imageTag,
|
|
87455
|
+
allowDowngrade: opts.allowDowngrade
|
|
87456
|
+
});
|
|
87457
|
+
if (guard.skip) {
|
|
87458
|
+
console.log(source_default.yellow(` \u23ed ${opts.dryRun ? "[dry-run] " : ""}${guard.message}`));
|
|
87459
|
+
return;
|
|
87460
|
+
}
|
|
87369
87461
|
const yaml = renderWebComposeFile({
|
|
87370
87462
|
hostHome: homedir50(),
|
|
87371
87463
|
imageTag,
|
|
@@ -87456,7 +87548,7 @@ ${down.stderr}`));
|
|
|
87456
87548
|
}
|
|
87457
87549
|
function registerWebdCommand(program3) {
|
|
87458
87550
|
const webd = program3.command("webd").description("Manage switchroom-web, the dashboard + GitHub-webhook receiver container");
|
|
87459
|
-
webd.command("install").description("Install or refresh the web container (writes ~/.switchroom/web/docker-compose.yml + docker compose up -d)").option("--tag <tag>", "Image tag override (default: resolved from release.pin in switchroom.yaml, else latest)").option("--dry-run", "Print the compose file and the docker commands without writing or running anything").action(withConfigError(async (opts) => {
|
|
87551
|
+
webd.command("install").description("Install or refresh the web container (writes ~/.switchroom/web/docker-compose.yml + docker compose up -d)").option("--tag <tag>", "Image tag override (default: resolved from release.pin in switchroom.yaml, else latest)").option("--dry-run", "Print the compose file and the docker commands without writing or running anything").option("--allow-downgrade", "Deploy even if the running container is on a newer version (overrides the anti-revert guard)").action(withConfigError(async (opts) => {
|
|
87460
87552
|
await doInstall2(opts, program3);
|
|
87461
87553
|
}));
|
|
87462
87554
|
webd.command("status").description("Show web-service container state").action(() => doStatus2());
|