switchroom 0.15.38 → 0.15.40
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
|
@@ -28441,13 +28441,13 @@ function setAuthActive(yamlText, label) {
|
|
|
28441
28441
|
if (typeof label !== "string" || label.length === 0) {
|
|
28442
28442
|
throw new Error("setAuthActive: label must be a non-empty string");
|
|
28443
28443
|
}
|
|
28444
|
-
const doc =
|
|
28444
|
+
const doc = import_yaml10.parseDocument(yamlText);
|
|
28445
28445
|
const root = doc.contents;
|
|
28446
|
-
if (!
|
|
28446
|
+
if (!import_yaml10.isMap(root)) {
|
|
28447
28447
|
throw new Error("setAuthActive: YAML root is not a map");
|
|
28448
28448
|
}
|
|
28449
28449
|
const existing = root.get("auth", true);
|
|
28450
|
-
if (
|
|
28450
|
+
if (import_yaml10.isMap(existing)) {
|
|
28451
28451
|
if (existing.get("active") === label) {
|
|
28452
28452
|
return yamlText;
|
|
28453
28453
|
}
|
|
@@ -28460,9 +28460,9 @@ function setAuthActive(yamlText, label) {
|
|
|
28460
28460
|
`) ? out : out + `
|
|
28461
28461
|
`;
|
|
28462
28462
|
}
|
|
28463
|
-
var
|
|
28463
|
+
var import_yaml10;
|
|
28464
28464
|
var init_auth_active_yaml = __esm(() => {
|
|
28465
|
-
|
|
28465
|
+
import_yaml10 = __toESM(require_dist(), 1);
|
|
28466
28466
|
});
|
|
28467
28467
|
|
|
28468
28468
|
// src/auth/via-claude.ts
|
|
@@ -28476,11 +28476,11 @@ __export(exports_via_claude, {
|
|
|
28476
28476
|
PRE_PASTE_RULES: () => PRE_PASTE_RULES,
|
|
28477
28477
|
POST_PASTE_RULES: () => POST_PASTE_RULES
|
|
28478
28478
|
});
|
|
28479
|
-
import { execFileSync as execFileSync14, spawnSync as
|
|
28479
|
+
import { execFileSync as execFileSync14, spawnSync as spawnSync3 } from "node:child_process";
|
|
28480
28480
|
import { existsSync as existsSync32, mkdirSync as mkdirSync19, readFileSync as readFileSync27 } from "node:fs";
|
|
28481
28481
|
import { join as join25, resolve as resolve24 } from "node:path";
|
|
28482
28482
|
function tmuxHasSession(session) {
|
|
28483
|
-
const r =
|
|
28483
|
+
const r = spawnSync3("tmux", ["has-session", "-t", session], {
|
|
28484
28484
|
stdio: ["ignore", "ignore", "ignore"]
|
|
28485
28485
|
});
|
|
28486
28486
|
return r.status === 0;
|
|
@@ -29947,12 +29947,12 @@ var init_doctor_docker = __esm(() => {
|
|
|
29947
29947
|
// src/cli/doctor-auth-broker.ts
|
|
29948
29948
|
import { existsSync as existsSync53, readFileSync as readFileSync50 } from "node:fs";
|
|
29949
29949
|
import { createHash as createHash10 } from "node:crypto";
|
|
29950
|
-
import { spawnSync as
|
|
29950
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
29951
29951
|
import { homedir as homedir27 } from "node:os";
|
|
29952
29952
|
import { join as join49 } from "node:path";
|
|
29953
29953
|
function defaultDockerInspect(container, format) {
|
|
29954
29954
|
try {
|
|
29955
|
-
const r =
|
|
29955
|
+
const r = spawnSync7("docker", ["inspect", "-f", format, container], { encoding: "utf-8", timeout: 5000 });
|
|
29956
29956
|
if (r.status !== 0)
|
|
29957
29957
|
return null;
|
|
29958
29958
|
return r.stdout.trim();
|
|
@@ -29962,7 +29962,7 @@ function defaultDockerInspect(container, format) {
|
|
|
29962
29962
|
}
|
|
29963
29963
|
function defaultDockerExecExists(container, path4) {
|
|
29964
29964
|
try {
|
|
29965
|
-
const r =
|
|
29965
|
+
const r = spawnSync7("docker", ["exec", container, "test", "-S", path4], { encoding: "utf-8", timeout: 5000 });
|
|
29966
29966
|
return r.status === 0;
|
|
29967
29967
|
} catch {
|
|
29968
29968
|
return false;
|
|
@@ -29976,12 +29976,12 @@ function sha256Hex(content) {
|
|
|
29976
29976
|
}
|
|
29977
29977
|
function checkAuthBrokerServiceHealth(deps = {}) {
|
|
29978
29978
|
const inspect = deps.dockerInspect ?? defaultDockerInspect;
|
|
29979
|
-
const status = inspect(
|
|
29979
|
+
const status = inspect(AUTH_BROKER_CONTAINER2, "{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}");
|
|
29980
29980
|
if (status === null) {
|
|
29981
29981
|
return {
|
|
29982
29982
|
name: "auth-broker: service health",
|
|
29983
29983
|
status: "fail",
|
|
29984
|
-
detail: `container \`${
|
|
29984
|
+
detail: `container \`${AUTH_BROKER_CONTAINER2}\` not found via \`docker inspect\``,
|
|
29985
29985
|
fix: "Run `switchroom apply` to bring the broker online, then `switchroom doctor` again."
|
|
29986
29986
|
};
|
|
29987
29987
|
}
|
|
@@ -30029,7 +30029,7 @@ function checkAuthBrokerPerAgentSockets(config, deps = {}) {
|
|
|
30029
30029
|
const missing = [];
|
|
30030
30030
|
for (const agent of agents) {
|
|
30031
30031
|
const socketPath = `/run/switchroom/auth-broker/${agent}/sock`;
|
|
30032
|
-
if (!execExists(
|
|
30032
|
+
if (!execExists(AUTH_BROKER_CONTAINER2, socketPath)) {
|
|
30033
30033
|
missing.push(agent);
|
|
30034
30034
|
}
|
|
30035
30035
|
}
|
|
@@ -30190,17 +30190,17 @@ function runAuthBrokerChecks(config, deps = {}) {
|
|
|
30190
30190
|
const rank = { fail: 0, warn: 1, ok: 2, skip: 3 };
|
|
30191
30191
|
return [...results].sort((a, b) => rank[a.status] - rank[b.status]);
|
|
30192
30192
|
}
|
|
30193
|
-
var
|
|
30193
|
+
var AUTH_BROKER_CONTAINER2 = "switchroom-auth-broker";
|
|
30194
30194
|
var init_doctor_auth_broker = __esm(() => {
|
|
30195
30195
|
init_account_store();
|
|
30196
30196
|
init_paths();
|
|
30197
30197
|
});
|
|
30198
30198
|
|
|
30199
30199
|
// src/cli/doctor-hostd.ts
|
|
30200
|
-
import { spawnSync as
|
|
30200
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
30201
30201
|
function realDockerInspect(ref, format) {
|
|
30202
30202
|
try {
|
|
30203
|
-
const r =
|
|
30203
|
+
const r = spawnSync8("docker", ["inspect", ref, "--format", format], {
|
|
30204
30204
|
encoding: "utf-8",
|
|
30205
30205
|
timeout: 5000
|
|
30206
30206
|
});
|
|
@@ -31571,6 +31571,13 @@ var init_doctor_notion = __esm(() => {
|
|
|
31571
31571
|
});
|
|
31572
31572
|
|
|
31573
31573
|
// src/cli/doctor-mcp-secrets.ts
|
|
31574
|
+
function entryScopeDenies(agent, allow, deny) {
|
|
31575
|
+
if (deny.includes(agent))
|
|
31576
|
+
return true;
|
|
31577
|
+
if (allow.length > 0 && !allow.includes(agent))
|
|
31578
|
+
return true;
|
|
31579
|
+
return false;
|
|
31580
|
+
}
|
|
31574
31581
|
function computeMcpSecretRequirements(config) {
|
|
31575
31582
|
const cfg = config;
|
|
31576
31583
|
const reqs = [];
|
|
@@ -31650,20 +31657,19 @@ async function runMcpSecretChecks(config, deps = {}) {
|
|
|
31650
31657
|
});
|
|
31651
31658
|
continue;
|
|
31652
31659
|
}
|
|
31653
|
-
if (
|
|
31654
|
-
const updated = [...new Set([...acl.allow, r.agent])].sort().join(",");
|
|
31660
|
+
if (entryScopeDenies(r.agent, acl.allow, acl.deny)) {
|
|
31655
31661
|
results.push({
|
|
31656
31662
|
name,
|
|
31657
31663
|
status: "fail",
|
|
31658
|
-
detail: `agent '${r.agent}' loads MCP '${r.server}' but
|
|
31659
|
-
fix: `switchroom vault set ${key} --allow ${
|
|
31664
|
+
detail: `agent '${r.agent}' loads MCP '${r.server}' but the vault entry scope for '${key}' denies it \u2014 the broker will deny at runtime`,
|
|
31665
|
+
fix: `switchroom vault set ${key} --allow ${[...new Set([...acl.allow, r.agent])].sort().join(",")} (vault set overwrites the scope \u2014 re-state the full list including '${r.agent}'; and drop it from --deny if present).`
|
|
31660
31666
|
});
|
|
31661
31667
|
continue;
|
|
31662
31668
|
}
|
|
31663
31669
|
results.push({
|
|
31664
31670
|
name,
|
|
31665
31671
|
status: "ok",
|
|
31666
|
-
detail: `MCP '${r.server}' \u2192 '${key}' present +
|
|
31672
|
+
detail: `MCP '${r.server}' \u2192 '${key}' present + scope-allowed`
|
|
31667
31673
|
});
|
|
31668
31674
|
}
|
|
31669
31675
|
}
|
|
@@ -32315,7 +32321,7 @@ __export(exports_doctor, {
|
|
|
32315
32321
|
checkAgents: () => checkAgents,
|
|
32316
32322
|
MFF_VAULT_KEY: () => MFF_VAULT_KEY
|
|
32317
32323
|
});
|
|
32318
|
-
import { execSync as execSync3, spawnSync as
|
|
32324
|
+
import { execSync as execSync3, spawnSync as spawnSync9 } from "node:child_process";
|
|
32319
32325
|
import {
|
|
32320
32326
|
accessSync as accessSync2,
|
|
32321
32327
|
constants as fsConstants5,
|
|
@@ -32663,7 +32669,7 @@ function probeVaultBrokerSocketPair(agentName) {
|
|
|
32663
32669
|
const dataPath = `/run/switchroom/broker/${agentName}/sock`;
|
|
32664
32670
|
const unlockPath = `/run/switchroom/broker/${agentName}/unlock`;
|
|
32665
32671
|
const script = `D=0; U=0; ` + `test -S '${dataPath}' && D=1; ` + `test -S '${unlockPath}' && U=1; ` + `echo "D=$D U=$U"`;
|
|
32666
|
-
const r =
|
|
32672
|
+
const r = spawnSync9("docker", ["exec", "switchroom-vault-broker", "sh", "-c", script], { stdio: "pipe", timeout: 3000 });
|
|
32667
32673
|
if (r.error || r.status === null)
|
|
32668
32674
|
return "unreachable";
|
|
32669
32675
|
if (r.status !== 0) {
|
|
@@ -32862,7 +32868,7 @@ function checkHindsightConsumer(config, opts) {
|
|
|
32862
32868
|
}
|
|
32863
32869
|
function probeAuthBrokerSocket(consumerName) {
|
|
32864
32870
|
const containerPath = `/run/switchroom/auth-broker/${consumerName}/sock`;
|
|
32865
|
-
const r =
|
|
32871
|
+
const r = spawnSync9("docker", ["exec", "switchroom-auth-broker", "test", "-S", containerPath], { stdio: "pipe", timeout: 3000 });
|
|
32866
32872
|
if (r.error || r.status === null)
|
|
32867
32873
|
return "unreachable";
|
|
32868
32874
|
if (r.status === 0)
|
|
@@ -33753,7 +33759,7 @@ async function checkMffAuthFlow(envPath = mffEnvPath(), timeoutMs = 8000) {
|
|
|
33753
33759
|
const python3 = which("python3") ?? "python3";
|
|
33754
33760
|
let token;
|
|
33755
33761
|
try {
|
|
33756
|
-
const result =
|
|
33762
|
+
const result = spawnSync9(python3, [authScript, "--quiet"], {
|
|
33757
33763
|
timeout: timeoutMs,
|
|
33758
33764
|
encoding: "utf-8",
|
|
33759
33765
|
env: { ...process.env, ...env2 }
|
|
@@ -34014,7 +34020,11 @@ function registerDoctorCommand(program3) {
|
|
|
34014
34020
|
const { getViaBrokerStructured: getViaBrokerStructured2 } = await Promise.resolve().then(() => (init_client(), exports_client));
|
|
34015
34021
|
const result = await getViaBrokerStructured2(key);
|
|
34016
34022
|
if (result.kind === "ok") {
|
|
34017
|
-
return {
|
|
34023
|
+
return {
|
|
34024
|
+
kind: "ok",
|
|
34025
|
+
allow: result.entry.scope?.allow ?? [],
|
|
34026
|
+
deny: result.entry.scope?.deny ?? []
|
|
34027
|
+
};
|
|
34018
34028
|
}
|
|
34019
34029
|
if (result.kind === "not_found")
|
|
34020
34030
|
return { kind: "not_found" };
|
|
@@ -49780,9 +49790,9 @@ __export(exports_server, {
|
|
|
49780
49790
|
dispatchTool: () => dispatchTool,
|
|
49781
49791
|
TOOLS: () => TOOLS
|
|
49782
49792
|
});
|
|
49783
|
-
import { spawnSync as
|
|
49793
|
+
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
49784
49794
|
function execCli(args, stdin) {
|
|
49785
|
-
const r =
|
|
49795
|
+
const r = spawnSync15(CLI_BIN, args, {
|
|
49786
49796
|
encoding: "utf-8",
|
|
49787
49797
|
env: process.env,
|
|
49788
49798
|
timeout: 15000,
|
|
@@ -50692,8 +50702,8 @@ var {
|
|
|
50692
50702
|
} = import__.default;
|
|
50693
50703
|
|
|
50694
50704
|
// src/build-info.ts
|
|
50695
|
-
var VERSION = "0.15.
|
|
50696
|
-
var COMMIT_SHA = "
|
|
50705
|
+
var VERSION = "0.15.40";
|
|
50706
|
+
var COMMIT_SHA = "fd53cf02";
|
|
50697
50707
|
|
|
50698
50708
|
// src/cli/agent.ts
|
|
50699
50709
|
init_source();
|
|
@@ -52591,7 +52601,7 @@ function buildHumanizerEnvVars(agentDir, agent) {
|
|
|
52591
52601
|
function buildToolSearchEnvVars() {
|
|
52592
52602
|
if (process.env.SWITCHROOM_DISABLE_TOOL_SEARCH === "1")
|
|
52593
52603
|
return {};
|
|
52594
|
-
return { ENABLE_TOOL_SEARCH: process.env.SWITCHROOM_TOOL_SEARCH_MODE ?? "
|
|
52604
|
+
return { ENABLE_TOOL_SEARCH: process.env.SWITCHROOM_TOOL_SEARCH_MODE ?? "true" };
|
|
52595
52605
|
}
|
|
52596
52606
|
var SWITCHROOM_OWNED_SETTINGS_KEYS = new Set([
|
|
52597
52607
|
"permissions",
|
|
@@ -59722,6 +59732,134 @@ function pruneEmptyMap(doc, path) {
|
|
|
59722
59732
|
// src/cli/auth-microsoft.ts
|
|
59723
59733
|
init_helpers();
|
|
59724
59734
|
|
|
59735
|
+
// src/config/agent-workspace-account.ts
|
|
59736
|
+
var import_yaml9 = __toESM(require_dist(), 1);
|
|
59737
|
+
function blockKey(provider) {
|
|
59738
|
+
return `${provider}_workspace`;
|
|
59739
|
+
}
|
|
59740
|
+
function setAgentWorkspaceAccount(yamlText, provider, agent, account) {
|
|
59741
|
+
const doc = import_yaml9.parseDocument(yamlText);
|
|
59742
|
+
const agentsNode = doc.get("agents");
|
|
59743
|
+
if (!import_yaml9.isMap(agentsNode)) {
|
|
59744
|
+
throw new Error("switchroom.yaml has no `agents:` map");
|
|
59745
|
+
}
|
|
59746
|
+
if (!agentsNode.has(agent)) {
|
|
59747
|
+
throw new Error(`agent '${agent}' is not declared in switchroom.yaml`);
|
|
59748
|
+
}
|
|
59749
|
+
const path = ["agents", agent, blockKey(provider), "account"];
|
|
59750
|
+
const current = doc.getIn(path);
|
|
59751
|
+
if (current === account)
|
|
59752
|
+
return yamlText;
|
|
59753
|
+
doc.setIn(path, account);
|
|
59754
|
+
return String(doc);
|
|
59755
|
+
}
|
|
59756
|
+
function clearAgentWorkspaceAccount(yamlText, provider, agent) {
|
|
59757
|
+
const doc = import_yaml9.parseDocument(yamlText);
|
|
59758
|
+
const agentsNode = doc.get("agents");
|
|
59759
|
+
if (!import_yaml9.isMap(agentsNode))
|
|
59760
|
+
return yamlText;
|
|
59761
|
+
if (!agentsNode.has(agent))
|
|
59762
|
+
return yamlText;
|
|
59763
|
+
const blockPath = ["agents", agent, blockKey(provider)];
|
|
59764
|
+
const block = doc.getIn(blockPath);
|
|
59765
|
+
if (!import_yaml9.isMap(block))
|
|
59766
|
+
return yamlText;
|
|
59767
|
+
const accountPath = [...blockPath, "account"];
|
|
59768
|
+
if (doc.getIn(accountPath) === undefined)
|
|
59769
|
+
return yamlText;
|
|
59770
|
+
doc.deleteIn(accountPath);
|
|
59771
|
+
const after = doc.getIn(blockPath);
|
|
59772
|
+
if (import_yaml9.isMap(after) && after.items.length === 0) {
|
|
59773
|
+
doc.deleteIn(blockPath);
|
|
59774
|
+
}
|
|
59775
|
+
return String(doc);
|
|
59776
|
+
}
|
|
59777
|
+
function getAgentWorkspaceAccount(yamlText, provider, agent) {
|
|
59778
|
+
const doc = import_yaml9.parseDocument(yamlText);
|
|
59779
|
+
const v = doc.getIn(["agents", agent, blockKey(provider), "account"]);
|
|
59780
|
+
return typeof v === "string" ? v : null;
|
|
59781
|
+
}
|
|
59782
|
+
|
|
59783
|
+
// src/cli/microsoft-enable-plan.ts
|
|
59784
|
+
function planMicrosoftEnable(yamlText, account, agents) {
|
|
59785
|
+
const enabledBefore = getEnabledAgentsForMicrosoftAccount(yamlText, account) ?? [];
|
|
59786
|
+
let text = enableAgentsOnMicrosoftAccount(yamlText, account, agents);
|
|
59787
|
+
const selectorSet = [];
|
|
59788
|
+
const selectorConflict = [];
|
|
59789
|
+
for (const agent of agents) {
|
|
59790
|
+
const current = getAgentWorkspaceAccount(text, "microsoft", agent);
|
|
59791
|
+
if (current == null) {
|
|
59792
|
+
text = setAgentWorkspaceAccount(text, "microsoft", agent, account);
|
|
59793
|
+
selectorSet.push(agent);
|
|
59794
|
+
} else if (current.toLowerCase() !== account.toLowerCase()) {
|
|
59795
|
+
selectorConflict.push({ agent, current });
|
|
59796
|
+
}
|
|
59797
|
+
}
|
|
59798
|
+
const enabledAfter = getEnabledAgentsForMicrosoftAccount(text, account) ?? [];
|
|
59799
|
+
const newlyEnabled = enabledAfter.filter((a) => !enabledBefore.includes(a));
|
|
59800
|
+
return { text, newlyEnabled, enabledAfter, selectorSet, selectorConflict };
|
|
59801
|
+
}
|
|
59802
|
+
function planMicrosoftDisable(yamlText, account, agents) {
|
|
59803
|
+
const enabledBefore = getEnabledAgentsForMicrosoftAccount(yamlText, account) ?? [];
|
|
59804
|
+
let text = disableAgentsOnMicrosoftAccount(yamlText, account, agents);
|
|
59805
|
+
const enabledAfter = getEnabledAgentsForMicrosoftAccount(text, account) ?? [];
|
|
59806
|
+
const removed = enabledBefore.filter((a) => !enabledAfter.includes(a));
|
|
59807
|
+
const selectorCleared = [];
|
|
59808
|
+
for (const agent of removed) {
|
|
59809
|
+
if (getAgentWorkspaceAccount(text, "microsoft", agent)?.toLowerCase() === account.toLowerCase()) {
|
|
59810
|
+
text = clearAgentWorkspaceAccount(text, "microsoft", agent);
|
|
59811
|
+
selectorCleared.push(agent);
|
|
59812
|
+
}
|
|
59813
|
+
}
|
|
59814
|
+
return { text, removed, enabledAfter, selectorCleared };
|
|
59815
|
+
}
|
|
59816
|
+
|
|
59817
|
+
// src/auth/broker/reload-signal.ts
|
|
59818
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
59819
|
+
var AUTH_BROKER_CONTAINER = "switchroom-auth-broker";
|
|
59820
|
+
var defaultRunner = (args) => {
|
|
59821
|
+
const r = spawnSync2("docker", args, { encoding: "utf8" });
|
|
59822
|
+
return {
|
|
59823
|
+
status: r.status,
|
|
59824
|
+
stderr: typeof r.stderr === "string" ? r.stderr : "",
|
|
59825
|
+
error: r.error
|
|
59826
|
+
};
|
|
59827
|
+
};
|
|
59828
|
+
function reloadAuthBroker(opts = {}) {
|
|
59829
|
+
const runner = opts.runner ?? defaultRunner;
|
|
59830
|
+
const container = opts.container ?? AUTH_BROKER_CONTAINER;
|
|
59831
|
+
const { status, stderr, error } = runner([
|
|
59832
|
+
"kill",
|
|
59833
|
+
"--signal=HUP",
|
|
59834
|
+
container
|
|
59835
|
+
]);
|
|
59836
|
+
if (error) {
|
|
59837
|
+
if (error.code === "ENOENT") {
|
|
59838
|
+
return { ok: false, reason: "no-docker" };
|
|
59839
|
+
}
|
|
59840
|
+
return { ok: false, reason: "error", detail: error.message };
|
|
59841
|
+
}
|
|
59842
|
+
if (status === 0)
|
|
59843
|
+
return { ok: true };
|
|
59844
|
+
const lower = stderr.toLowerCase();
|
|
59845
|
+
if (lower.includes("no such container") || lower.includes("is not running") || lower.includes("cannot kill")) {
|
|
59846
|
+
return { ok: false, reason: "not-running" };
|
|
59847
|
+
}
|
|
59848
|
+
return { ok: false, reason: "error", detail: stderr.trim() || `exit ${status}` };
|
|
59849
|
+
}
|
|
59850
|
+
function authBrokerReloadHint(result) {
|
|
59851
|
+
if (result.ok)
|
|
59852
|
+
return null;
|
|
59853
|
+
switch (result.reason) {
|
|
59854
|
+
case "not-running":
|
|
59855
|
+
return "auth-broker is not running \u2014 it will pick up this change on next start.";
|
|
59856
|
+
case "no-docker":
|
|
59857
|
+
return "Could not reach Docker to hot-reload the auth-broker; restart it so the change takes effect: docker restart switchroom-auth-broker";
|
|
59858
|
+
case "error":
|
|
59859
|
+
return `Could not hot-reload the auth-broker (${result.detail ?? "unknown error"}); restart it so the change takes effect: docker restart switchroom-auth-broker`;
|
|
59860
|
+
}
|
|
59861
|
+
}
|
|
59862
|
+
|
|
59725
59863
|
// src/auth/default-oauth-clients.ts
|
|
59726
59864
|
var DEFAULT_MICROSOFT_CLIENT_ID = "9dff88fa-3126-457b-9d1d-37e58c219019";
|
|
59727
59865
|
function resolveMicrosoftClientId(configClientId) {
|
|
@@ -59810,19 +59948,16 @@ function registerAuthMicrosoftSubcommands(program3, authParent) {
|
|
|
59810
59948
|
registerAccountList2(account);
|
|
59811
59949
|
}
|
|
59812
59950
|
function registerEnable2(microsoftParent, program3) {
|
|
59813
|
-
microsoftParent.command("enable <account> <agents...>").description("Enable a Microsoft account on one or more agents. Use `all` to enable on every declared agent. Appends to microsoft_accounts.<account>.enabled_for[]
|
|
59951
|
+
microsoftParent.command("enable <account> <agents...>").description("Enable a Microsoft account on one or more agents. Use `all` to enable on every declared agent. Appends to microsoft_accounts.<account>.enabled_for[] AND pins agents.<agent>.microsoft_workspace.account (both are required, else the broker returns ACCOUNT_NOT_FOUND), then hot-reloads the running auth-broker so it's live immediately. Does NOT mint the broker credentials \u2014 use `auth microsoft account add` for that.").action(withConfigError(async (account, agents) => {
|
|
59814
59952
|
const normalizedAccount = validateAndNormalizeAccountEmail2(account);
|
|
59815
59953
|
const config = getConfig(program3);
|
|
59816
59954
|
agents = expandAllAgents2(agents, config);
|
|
59817
59955
|
validateAgentSlugs(agents, config);
|
|
59818
59956
|
const yamlPath = getConfigPath(program3);
|
|
59819
59957
|
const before = readFileSync26(yamlPath, "utf-8");
|
|
59820
|
-
const
|
|
59821
|
-
|
|
59822
|
-
|
|
59823
|
-
writeFileSync16(yamlPath, after);
|
|
59824
|
-
const enabledAfter = getEnabledAgentsForMicrosoftAccount(after, normalizedAccount) ?? [];
|
|
59825
|
-
const newlyEnabled = enabledAfter.filter((a) => !enabledBefore.includes(a));
|
|
59958
|
+
const { text, newlyEnabled, enabledAfter, selectorSet, selectorConflict } = planMicrosoftEnable(before, normalizedAccount, agents);
|
|
59959
|
+
if (text !== before)
|
|
59960
|
+
writeFileSync16(yamlPath, text);
|
|
59826
59961
|
console.log();
|
|
59827
59962
|
if (newlyEnabled.length === 0) {
|
|
59828
59963
|
console.log(`No change \u2014 all of ${agents.join(", ")} already enabled on ${source_default.bold(normalizedAccount)}.`);
|
|
@@ -59833,9 +59968,26 @@ function registerEnable2(microsoftParent, program3) {
|
|
|
59833
59968
|
const alreadyEnabled = enabledAfter.filter((a) => !newlyEnabled.includes(a));
|
|
59834
59969
|
console.log(` ${source_default.gray("already enabled on:")} ${alreadyEnabled.join(", ")}`);
|
|
59835
59970
|
}
|
|
59971
|
+
if (selectorSet.length > 0) {
|
|
59972
|
+
console.log(` ${source_default.green("\u2713")} ${source_default.gray("pinned")} ${source_default.bold("microsoft_workspace.account")} ${source_default.gray("on:")} ${selectorSet.join(", ")}`);
|
|
59973
|
+
}
|
|
59974
|
+
for (const { agent, current } of selectorConflict) {
|
|
59975
|
+
console.log(source_default.yellow(` \u26a0 ${source_default.bold(agent)} already pins a different account (${source_default.bold(current)}) \u2014 left as-is. Repin with \`switchroom auth microsoft disable ${current} ${agent}\` first if that's unintended.`));
|
|
59976
|
+
}
|
|
59977
|
+
if (text !== before) {
|
|
59978
|
+
const reload = reloadAuthBroker();
|
|
59979
|
+
if (reload.ok) {
|
|
59980
|
+
console.log(` ${source_default.green("\u2713")} ${source_default.gray("auth-broker hot-reloaded \u2014 credentials are live.")}`);
|
|
59981
|
+
} else {
|
|
59982
|
+
const hint = authBrokerReloadHint(reload);
|
|
59983
|
+
if (hint)
|
|
59984
|
+
console.log(source_default.yellow(` \u26a0 ${hint}`));
|
|
59985
|
+
}
|
|
59986
|
+
}
|
|
59836
59987
|
console.log();
|
|
59837
|
-
if (newlyEnabled.length > 0) {
|
|
59838
|
-
|
|
59988
|
+
if (newlyEnabled.length > 0 || selectorSet.length > 0) {
|
|
59989
|
+
const restartTargets = [...new Set([...newlyEnabled, ...selectorSet])];
|
|
59990
|
+
console.log(`Next: ${source_default.bold(`switchroom agent restart ${restartTargets.join(" ")}`)} to regenerate the agent's MCP config and surface the Microsoft/OneDrive tools.`);
|
|
59839
59991
|
console.log();
|
|
59840
59992
|
}
|
|
59841
59993
|
}));
|
|
@@ -59854,11 +60006,9 @@ function registerDisable2(microsoftParent, program3) {
|
|
|
59854
60006
|
console.log();
|
|
59855
60007
|
return;
|
|
59856
60008
|
}
|
|
59857
|
-
const
|
|
59858
|
-
if (
|
|
59859
|
-
writeFileSync16(yamlPath,
|
|
59860
|
-
const enabledAfter = getEnabledAgentsForMicrosoftAccount(after, normalizedAccount) ?? [];
|
|
59861
|
-
const removed = enabledBefore.filter((a) => !enabledAfter.includes(a));
|
|
60009
|
+
const { text, removed, enabledAfter, selectorCleared } = planMicrosoftDisable(before, normalizedAccount, agents);
|
|
60010
|
+
if (text !== before)
|
|
60011
|
+
writeFileSync16(yamlPath, text);
|
|
59862
60012
|
console.log();
|
|
59863
60013
|
if (removed.length === 0) {
|
|
59864
60014
|
console.log(`No change \u2014 none of ${agents.join(", ")} were enabled on ${source_default.bold(normalizedAccount)}.`);
|
|
@@ -59870,9 +60020,22 @@ function registerDisable2(microsoftParent, program3) {
|
|
|
59870
60020
|
} else {
|
|
59871
60021
|
console.log(` ${source_default.gray("still enabled on:")} ${enabledAfter.join(", ")}`);
|
|
59872
60022
|
}
|
|
60023
|
+
if (selectorCleared.length > 0) {
|
|
60024
|
+
console.log(` ${source_default.gray("cleared")} ${source_default.bold("microsoft_workspace.account")} ${source_default.gray("on:")} ${selectorCleared.join(", ")}`);
|
|
60025
|
+
}
|
|
60026
|
+
if (text !== before) {
|
|
60027
|
+
const reload = reloadAuthBroker();
|
|
60028
|
+
if (reload.ok) {
|
|
60029
|
+
console.log(` ${source_default.green("\u2713")} ${source_default.gray("auth-broker hot-reloaded \u2014 access revoked live.")}`);
|
|
60030
|
+
} else {
|
|
60031
|
+
const hint = authBrokerReloadHint(reload);
|
|
60032
|
+
if (hint)
|
|
60033
|
+
console.log(source_default.yellow(` \u26a0 ${hint}`));
|
|
60034
|
+
}
|
|
60035
|
+
}
|
|
59873
60036
|
console.log();
|
|
59874
60037
|
if (removed.length > 0) {
|
|
59875
|
-
console.log(`Next: ${source_default.bold(`switchroom agent restart ${removed.join(" ")}`)} so the
|
|
60038
|
+
console.log(`Next: ${source_default.bold(`switchroom agent restart ${removed.join(" ")}`)} so the agent drops the Microsoft MCP from its config.`);
|
|
59876
60039
|
console.log();
|
|
59877
60040
|
}
|
|
59878
60041
|
}));
|
|
@@ -65682,8 +65845,8 @@ init_vault();
|
|
|
65682
65845
|
// src/cli/vault-auto-unlock.ts
|
|
65683
65846
|
init_loader();
|
|
65684
65847
|
init_client();
|
|
65685
|
-
var
|
|
65686
|
-
import { spawnSync as
|
|
65848
|
+
var import_yaml11 = __toESM(require_dist(), 1);
|
|
65849
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
65687
65850
|
import { readFileSync as readFileSync33, writeFileSync as writeFileSync20 } from "node:fs";
|
|
65688
65851
|
import { homedir as homedir18 } from "node:os";
|
|
65689
65852
|
import { join as join34 } from "node:path";
|
|
@@ -65715,7 +65878,7 @@ function encryptCredential(passphrase, credPath) {
|
|
|
65715
65878
|
}
|
|
65716
65879
|
function setVaultBrokerAutoUnlock(configPath, value) {
|
|
65717
65880
|
const raw = readFileSync33(configPath, "utf-8");
|
|
65718
|
-
const doc =
|
|
65881
|
+
const doc = import_yaml11.default.parseDocument(raw);
|
|
65719
65882
|
doc.setIn(["vault", "broker", "autoUnlock"], value);
|
|
65720
65883
|
writeFileSync20(configPath, doc.toString(), "utf-8");
|
|
65721
65884
|
}
|
|
@@ -65723,7 +65886,7 @@ var DEFAULT_COMPOSE_FILE = join34(homedir18(), ".switchroom", "compose", "docker
|
|
|
65723
65886
|
async function applyAutoUnlock(opts = {}) {
|
|
65724
65887
|
const log = opts.log ?? ((s) => console.log(s));
|
|
65725
65888
|
const err = opts.err ?? ((s) => console.error(s));
|
|
65726
|
-
const runDockerCompose = opts.runDockerCompose ?? ((args) =>
|
|
65889
|
+
const runDockerCompose = opts.runDockerCompose ?? ((args) => spawnSync4("docker", args, { stdio: "inherit" }));
|
|
65727
65890
|
const verifyTimeoutMs = opts.verifyTimeoutMs ?? 1e4;
|
|
65728
65891
|
const configPath = opts.configPath ?? findConfigFile();
|
|
65729
65892
|
const composeFile = opts.composeFile ?? DEFAULT_COMPOSE_FILE;
|
|
@@ -67637,9 +67800,9 @@ init_paths();
|
|
|
67637
67800
|
import { createInterface as createInterface4 } from "node:readline";
|
|
67638
67801
|
|
|
67639
67802
|
// src/cli/telegram-yaml.ts
|
|
67640
|
-
var
|
|
67803
|
+
var import_yaml12 = __toESM(require_dist(), 1);
|
|
67641
67804
|
function setLinearAgent(yamlText, agentName, opts) {
|
|
67642
|
-
const doc =
|
|
67805
|
+
const doc = import_yaml12.parseDocument(yamlText);
|
|
67643
67806
|
ensureAgent(doc, agentName);
|
|
67644
67807
|
const block = { enabled: true, token: opts.token };
|
|
67645
67808
|
if (opts.workspaceId)
|
|
@@ -67649,7 +67812,7 @@ function setLinearAgent(yamlText, agentName, opts) {
|
|
|
67649
67812
|
return String(doc);
|
|
67650
67813
|
}
|
|
67651
67814
|
function setLinearDefaultTeam(yamlText, agentName, teamId) {
|
|
67652
|
-
const doc =
|
|
67815
|
+
const doc = import_yaml12.parseDocument(yamlText);
|
|
67653
67816
|
ensureAgent(doc, agentName);
|
|
67654
67817
|
if (!doc.hasIn(["agents", agentName, "channels", "telegram", "linear_agent"])) {
|
|
67655
67818
|
throw new Error(`agent '${agentName}' has no linear_agent block. Run 'switchroom linear-agent setup --agent ${agentName} --token <token>' first.`);
|
|
@@ -67664,13 +67827,13 @@ function setLinearDefaultTeam(yamlText, agentName, teamId) {
|
|
|
67664
67827
|
return String(doc);
|
|
67665
67828
|
}
|
|
67666
67829
|
function setTelegramFeature(yamlText, agentName, feature, value) {
|
|
67667
|
-
const doc =
|
|
67830
|
+
const doc = import_yaml12.parseDocument(yamlText);
|
|
67668
67831
|
ensureAgent(doc, agentName);
|
|
67669
67832
|
doc.setIn(["agents", agentName, "channels", "telegram", feature], value);
|
|
67670
67833
|
return String(doc);
|
|
67671
67834
|
}
|
|
67672
67835
|
function removeTelegramFeature(yamlText, agentName, feature) {
|
|
67673
|
-
const doc =
|
|
67836
|
+
const doc = import_yaml12.parseDocument(yamlText);
|
|
67674
67837
|
if (!hasAgent(doc, agentName))
|
|
67675
67838
|
return yamlText;
|
|
67676
67839
|
if (!doc.hasIn(["agents", agentName, "channels", "telegram", feature])) {
|
|
@@ -67688,21 +67851,21 @@ function ensureAgent(doc, agentName) {
|
|
|
67688
67851
|
}
|
|
67689
67852
|
function hasAgent(doc, agentName) {
|
|
67690
67853
|
const agents = doc.get("agents");
|
|
67691
|
-
if (!
|
|
67854
|
+
if (!import_yaml12.isMap(agents))
|
|
67692
67855
|
return false;
|
|
67693
67856
|
return agents.has(agentName);
|
|
67694
67857
|
}
|
|
67695
67858
|
function pruneEmptyMap2(doc, path4) {
|
|
67696
67859
|
const node = doc.getIn(path4);
|
|
67697
|
-
if (
|
|
67860
|
+
if (import_yaml12.isMap(node) && node.items.length === 0) {
|
|
67698
67861
|
doc.deleteIn(path4);
|
|
67699
67862
|
}
|
|
67700
67863
|
}
|
|
67701
67864
|
function addWebhookSource(yamlText, agentName, source) {
|
|
67702
|
-
const doc =
|
|
67865
|
+
const doc = import_yaml12.parseDocument(yamlText);
|
|
67703
67866
|
ensureAgent(doc, agentName);
|
|
67704
67867
|
const existing = doc.getIn(["agents", agentName, "channels", "telegram", "webhook_sources"]);
|
|
67705
|
-
if (
|
|
67868
|
+
if (import_yaml12.isSeq(existing)) {
|
|
67706
67869
|
const seq = existing;
|
|
67707
67870
|
for (const item of seq.items) {
|
|
67708
67871
|
const v = item.value ?? item;
|
|
@@ -67716,10 +67879,10 @@ function addWebhookSource(yamlText, agentName, source) {
|
|
|
67716
67879
|
return String(doc);
|
|
67717
67880
|
}
|
|
67718
67881
|
function addAgentSecret(yamlText, agentName, key) {
|
|
67719
|
-
const doc =
|
|
67882
|
+
const doc = import_yaml12.parseDocument(yamlText);
|
|
67720
67883
|
ensureAgent(doc, agentName);
|
|
67721
67884
|
const existing = doc.getIn(["agents", agentName, "secrets"]);
|
|
67722
|
-
if (
|
|
67885
|
+
if (import_yaml12.isSeq(existing)) {
|
|
67723
67886
|
const seq = existing;
|
|
67724
67887
|
for (const item of seq.items) {
|
|
67725
67888
|
const v = item.value ?? item;
|
|
@@ -67733,11 +67896,11 @@ function addAgentSecret(yamlText, agentName, key) {
|
|
|
67733
67896
|
return String(doc);
|
|
67734
67897
|
}
|
|
67735
67898
|
function removeWebhookSource(yamlText, agentName, source) {
|
|
67736
|
-
const doc =
|
|
67899
|
+
const doc = import_yaml12.parseDocument(yamlText);
|
|
67737
67900
|
if (!hasAgent(doc, agentName))
|
|
67738
67901
|
return yamlText;
|
|
67739
67902
|
const existing = doc.getIn(["agents", agentName, "channels", "telegram", "webhook_sources"]);
|
|
67740
|
-
if (!
|
|
67903
|
+
if (!import_yaml12.isSeq(existing))
|
|
67741
67904
|
return yamlText;
|
|
67742
67905
|
const seq = existing;
|
|
67743
67906
|
const beforeLen = seq.items.length;
|
|
@@ -68599,6 +68762,8 @@ var HINDSIGHT_DEFAULT_MEM_LIMIT = "4g";
|
|
|
68599
68762
|
var HINDSIGHT_DEFAULT_MEM_RESERVATION = "2g";
|
|
68600
68763
|
var HINDSIGHT_DEFAULT_PIDS_LIMIT = 1000;
|
|
68601
68764
|
var HINDSIGHT_DEFAULT_SHM_SIZE = "2g";
|
|
68765
|
+
var HINDSIGHT_HEALTHCHECK_PY = 'import urllib.request,sys; sys.exit(0 if urllib.request.urlopen("http://localhost:8888/health",timeout=4).getcode()==200 else 1)';
|
|
68766
|
+
var HINDSIGHT_HEALTHCHECK_CMD = `python3 -c '${HINDSIGHT_HEALTHCHECK_PY}'`;
|
|
68602
68767
|
function isPortFree(port) {
|
|
68603
68768
|
return new Promise((resolve28) => {
|
|
68604
68769
|
const server = createServer4();
|
|
@@ -68690,6 +68855,16 @@ function startHindsight(ports) {
|
|
|
68690
68855
|
`--memory-reservation=${HINDSIGHT_DEFAULT_MEM_RESERVATION}`,
|
|
68691
68856
|
`--pids-limit=${HINDSIGHT_DEFAULT_PIDS_LIMIT}`,
|
|
68692
68857
|
`--shm-size=${HINDSIGHT_DEFAULT_SHM_SIZE}`,
|
|
68858
|
+
"--health-cmd",
|
|
68859
|
+
HINDSIGHT_HEALTHCHECK_CMD,
|
|
68860
|
+
"--health-interval",
|
|
68861
|
+
"30s",
|
|
68862
|
+
"--health-timeout",
|
|
68863
|
+
"5s",
|
|
68864
|
+
"--health-retries",
|
|
68865
|
+
"3",
|
|
68866
|
+
"--health-start-period",
|
|
68867
|
+
"60s",
|
|
68693
68868
|
"-p",
|
|
68694
68869
|
`127.0.0.1:${apiPort}:8888`,
|
|
68695
68870
|
"-p",
|
|
@@ -68697,6 +68872,8 @@ function startHindsight(ports) {
|
|
|
68697
68872
|
"-v",
|
|
68698
68873
|
"switchroom-hindsight-data:/home/hindsight/.pg0",
|
|
68699
68874
|
"-v",
|
|
68875
|
+
"switchroom-hindsight-backups:/backups",
|
|
68876
|
+
"-v",
|
|
68700
68877
|
`${HINDSIGHT_BROKER_SOCK_VOLUME}:/run/switchroom/auth-broker`,
|
|
68701
68878
|
"--tmpfs",
|
|
68702
68879
|
`/run/claude-creds:rw,mode=0700,uid=${HINDSIGHT_DEFAULT_UID},gid=${HINDSIGHT_DEFAULT_UID}`,
|
|
@@ -68744,8 +68921,15 @@ function generateHindsightComposeSnippet() {
|
|
|
68744
68921
|
` mem_reservation: ${HINDSIGHT_DEFAULT_MEM_RESERVATION}`,
|
|
68745
68922
|
` pids_limit: ${HINDSIGHT_DEFAULT_PIDS_LIMIT}`,
|
|
68746
68923
|
` shm_size: ${HINDSIGHT_DEFAULT_SHM_SIZE}`,
|
|
68924
|
+
" healthcheck:",
|
|
68925
|
+
` test: ${JSON.stringify(["CMD", "python3", "-c", HINDSIGHT_HEALTHCHECK_PY])}`,
|
|
68926
|
+
" interval: 30s",
|
|
68927
|
+
" timeout: 5s",
|
|
68928
|
+
" retries: 3",
|
|
68929
|
+
" start_period: 60s",
|
|
68747
68930
|
" volumes:",
|
|
68748
68931
|
" - switchroom-hindsight-data:/home/hindsight/.pg0",
|
|
68932
|
+
" - switchroom-hindsight-backups:/backups",
|
|
68749
68933
|
` - ${HINDSIGHT_BROKER_SOCK_VOLUME}:/run/switchroom/auth-broker`,
|
|
68750
68934
|
" tmpfs:",
|
|
68751
68935
|
` - /run/claude-creds:rw,mode=0700,uid=${HINDSIGHT_DEFAULT_UID},gid=${HINDSIGHT_DEFAULT_UID}`,
|
|
@@ -68753,6 +68937,7 @@ function generateHindsightComposeSnippet() {
|
|
|
68753
68937
|
"",
|
|
68754
68938
|
"volumes:",
|
|
68755
68939
|
" switchroom-hindsight-data:",
|
|
68940
|
+
" switchroom-hindsight-backups:",
|
|
68756
68941
|
` ${HINDSIGHT_BROKER_SOCK_VOLUME}:`,
|
|
68757
68942
|
" external: true",
|
|
68758
68943
|
" # Bound by the switchroom-auth-broker singleton in the main",
|
|
@@ -68763,17 +68948,17 @@ function generateHindsightComposeSnippet() {
|
|
|
68763
68948
|
}
|
|
68764
68949
|
async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFAULT_UID) {
|
|
68765
68950
|
const fs4 = await import("node:fs");
|
|
68766
|
-
const { parseDocument:
|
|
68951
|
+
const { parseDocument: parseDocument7, isMap: isMap7, isSeq: isSeq4, YAMLMap, YAMLSeq } = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
68767
68952
|
const { atomicWriteFileSync: atomicWriteFileSync3 } = await Promise.resolve().then(() => (init_atomic(), exports_atomic));
|
|
68768
68953
|
const raw = fs4.readFileSync(configPath, "utf-8");
|
|
68769
|
-
const doc =
|
|
68954
|
+
const doc = parseDocument7(raw);
|
|
68770
68955
|
const root = doc.contents;
|
|
68771
|
-
if (!
|
|
68956
|
+
if (!isMap7(root)) {
|
|
68772
68957
|
return { added: false, reason: "switchroom.yaml root is not a map" };
|
|
68773
68958
|
}
|
|
68774
68959
|
const authRaw = root.get("auth", true);
|
|
68775
68960
|
let authNode;
|
|
68776
|
-
if (
|
|
68961
|
+
if (isMap7(authRaw)) {
|
|
68777
68962
|
authNode = authRaw;
|
|
68778
68963
|
} else {
|
|
68779
68964
|
authNode = new YAMLMap;
|
|
@@ -68788,7 +68973,7 @@ async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFA
|
|
|
68788
68973
|
doc.setIn(["auth", "consumers"], consumersNode);
|
|
68789
68974
|
}
|
|
68790
68975
|
for (const item of consumersNode.items) {
|
|
68791
|
-
if (
|
|
68976
|
+
if (isMap7(item)) {
|
|
68792
68977
|
const name = item.get("name");
|
|
68793
68978
|
if (name === HINDSIGHT_CONSUMER_NAME) {
|
|
68794
68979
|
return { added: false, reason: "already present" };
|
|
@@ -68814,7 +68999,7 @@ async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFA
|
|
|
68814
68999
|
|
|
68815
69000
|
// src/cli/memory.ts
|
|
68816
69001
|
init_loader();
|
|
68817
|
-
var
|
|
69002
|
+
var import_yaml13 = __toESM(require_dist(), 1);
|
|
68818
69003
|
import { existsSync as existsSync44, readFileSync as readFileSync40, writeFileSync as writeFileSync23 } from "node:fs";
|
|
68819
69004
|
import { join as join39 } from "node:path";
|
|
68820
69005
|
function readRecallLog(agentDir, limit) {
|
|
@@ -69019,7 +69204,7 @@ Cross-agent reflection plan
|
|
|
69019
69204
|
try {
|
|
69020
69205
|
if (existsSync44(configPath)) {
|
|
69021
69206
|
const raw = readFileSync40(configPath, "utf-8");
|
|
69022
|
-
const doc =
|
|
69207
|
+
const doc = import_yaml13.default.parseDocument(raw);
|
|
69023
69208
|
if (!doc.has("memory")) {
|
|
69024
69209
|
doc.set("memory", { backend: "hindsight", shared_collection: "shared", config: { provider, url } });
|
|
69025
69210
|
} else {
|
|
@@ -69143,7 +69328,7 @@ import { timingSafeEqual as timingSafeEqual3, randomBytes as randomBytes11 } fro
|
|
|
69143
69328
|
init_lifecycle();
|
|
69144
69329
|
init_manager();
|
|
69145
69330
|
init_hindsight();
|
|
69146
|
-
import { spawnSync as
|
|
69331
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
69147
69332
|
import { existsSync as existsSync47, readFileSync as readFileSync43, statSync as statSync22 } from "node:fs";
|
|
69148
69333
|
import { resolve as resolve28, join as join44 } from "node:path";
|
|
69149
69334
|
|
|
@@ -73829,54 +74014,6 @@ function installGlobalErrorHandlers() {
|
|
|
73829
74014
|
init_loader();
|
|
73830
74015
|
init_merge();
|
|
73831
74016
|
|
|
73832
|
-
// src/config/agent-workspace-account.ts
|
|
73833
|
-
var import_yaml13 = __toESM(require_dist(), 1);
|
|
73834
|
-
function blockKey(provider) {
|
|
73835
|
-
return `${provider}_workspace`;
|
|
73836
|
-
}
|
|
73837
|
-
function setAgentWorkspaceAccount(yamlText, provider, agent, account) {
|
|
73838
|
-
const doc = import_yaml13.parseDocument(yamlText);
|
|
73839
|
-
const agentsNode = doc.get("agents");
|
|
73840
|
-
if (!import_yaml13.isMap(agentsNode)) {
|
|
73841
|
-
throw new Error("switchroom.yaml has no `agents:` map");
|
|
73842
|
-
}
|
|
73843
|
-
if (!agentsNode.has(agent)) {
|
|
73844
|
-
throw new Error(`agent '${agent}' is not declared in switchroom.yaml`);
|
|
73845
|
-
}
|
|
73846
|
-
const path4 = ["agents", agent, blockKey(provider), "account"];
|
|
73847
|
-
const current = doc.getIn(path4);
|
|
73848
|
-
if (current === account)
|
|
73849
|
-
return yamlText;
|
|
73850
|
-
doc.setIn(path4, account);
|
|
73851
|
-
return String(doc);
|
|
73852
|
-
}
|
|
73853
|
-
function clearAgentWorkspaceAccount(yamlText, provider, agent) {
|
|
73854
|
-
const doc = import_yaml13.parseDocument(yamlText);
|
|
73855
|
-
const agentsNode = doc.get("agents");
|
|
73856
|
-
if (!import_yaml13.isMap(agentsNode))
|
|
73857
|
-
return yamlText;
|
|
73858
|
-
if (!agentsNode.has(agent))
|
|
73859
|
-
return yamlText;
|
|
73860
|
-
const blockPath = ["agents", agent, blockKey(provider)];
|
|
73861
|
-
const block = doc.getIn(blockPath);
|
|
73862
|
-
if (!import_yaml13.isMap(block))
|
|
73863
|
-
return yamlText;
|
|
73864
|
-
const accountPath = [...blockPath, "account"];
|
|
73865
|
-
if (doc.getIn(accountPath) === undefined)
|
|
73866
|
-
return yamlText;
|
|
73867
|
-
doc.deleteIn(accountPath);
|
|
73868
|
-
const after = doc.getIn(blockPath);
|
|
73869
|
-
if (import_yaml13.isMap(after) && after.items.length === 0) {
|
|
73870
|
-
doc.deleteIn(blockPath);
|
|
73871
|
-
}
|
|
73872
|
-
return String(doc);
|
|
73873
|
-
}
|
|
73874
|
-
function getAgentWorkspaceAccount(yamlText, provider, agent) {
|
|
73875
|
-
const doc = import_yaml13.parseDocument(yamlText);
|
|
73876
|
-
const v = doc.getIn(["agents", agent, blockKey(provider), "account"]);
|
|
73877
|
-
return typeof v === "string" ? v : null;
|
|
73878
|
-
}
|
|
73879
|
-
|
|
73880
74017
|
// src/web/config-edit-plan.ts
|
|
73881
74018
|
init_schema();
|
|
73882
74019
|
var import_yaml14 = __toESM(require_dist(), 1);
|
|
@@ -73923,7 +74060,7 @@ import {
|
|
|
73923
74060
|
rmSync as rmrf,
|
|
73924
74061
|
writeFileSync as writeFileSync25
|
|
73925
74062
|
} from "node:fs";
|
|
73926
|
-
import { spawnSync as
|
|
74063
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
73927
74064
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
73928
74065
|
import { join as join41 } from "node:path";
|
|
73929
74066
|
|
|
@@ -73938,7 +74075,7 @@ function generateUnifiedDiff(before, after, name = "switchroom.yaml", gitBin = "
|
|
|
73938
74075
|
mkdirSync26(join41(dir, "new"), { recursive: true });
|
|
73939
74076
|
writeFileSync25(join41(dir, "cur", name), before);
|
|
73940
74077
|
writeFileSync25(join41(dir, "new", name), after);
|
|
73941
|
-
const r =
|
|
74078
|
+
const r = spawnSync5(gitBin, ["diff", "--no-index", "--no-color", "--", `cur/${name}`, `new/${name}`], { cwd: dir, encoding: "utf-8", timeout: 1e4 });
|
|
73942
74079
|
if (r.status === 0)
|
|
73943
74080
|
return "";
|
|
73944
74081
|
if (r.status !== 1) {
|
|
@@ -74725,7 +74862,7 @@ function inspectEnv(container, keys) {
|
|
|
74725
74862
|
const out = {};
|
|
74726
74863
|
for (const k of keys)
|
|
74727
74864
|
out[k] = null;
|
|
74728
|
-
const res =
|
|
74865
|
+
const res = spawnSync6("docker", ["inspect", "--format", "{{json .Config.Env}}", container], { encoding: "utf-8", timeout: 4000 });
|
|
74729
74866
|
if (res.error || res.status !== 0 || !res.stdout)
|
|
74730
74867
|
return out;
|
|
74731
74868
|
try {
|
|
@@ -77637,7 +77774,7 @@ init_source();
|
|
|
77637
77774
|
init_loader();
|
|
77638
77775
|
init_lifecycle();
|
|
77639
77776
|
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";
|
|
77640
|
-
import { spawnSync as
|
|
77777
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
77641
77778
|
import { join as join61, dirname as dirname15, resolve as resolve35 } from "node:path";
|
|
77642
77779
|
import { homedir as homedir37 } from "node:os";
|
|
77643
77780
|
|
|
@@ -77707,7 +77844,7 @@ function rebuildRefusalMessage(scriptPath) {
|
|
|
77707
77844
|
}
|
|
77708
77845
|
function planUpdate(opts) {
|
|
77709
77846
|
const composePath = opts.composePath ?? DEFAULT_COMPOSE_PATH;
|
|
77710
|
-
const runner = opts.runner ??
|
|
77847
|
+
const runner = opts.runner ?? defaultRunner2;
|
|
77711
77848
|
const scriptPath = opts.scriptPath ?? process.argv[1] ?? "";
|
|
77712
77849
|
const steps = [];
|
|
77713
77850
|
if (opts.pin) {
|
|
@@ -77912,8 +78049,8 @@ function planUpdate(opts) {
|
|
|
77912
78049
|
});
|
|
77913
78050
|
return steps;
|
|
77914
78051
|
}
|
|
77915
|
-
function
|
|
77916
|
-
const r =
|
|
78052
|
+
function defaultRunner2(cmd, args) {
|
|
78053
|
+
const r = spawnSync10(cmd, args, { stdio: "inherit" });
|
|
77917
78054
|
return { status: r.status ?? 1 };
|
|
77918
78055
|
}
|
|
77919
78056
|
function writeMarkerInPreferredLocation(agent, reason, runner) {
|
|
@@ -77988,7 +78125,7 @@ function defaultStatusProbe(composePath) {
|
|
|
77988
78125
|
}
|
|
77989
78126
|
let serviceList = [];
|
|
77990
78127
|
try {
|
|
77991
|
-
const r =
|
|
78128
|
+
const r = spawnSync10("docker", ["compose", "-p", "switchroom", "-f", composePath, "config", "--services"], { encoding: "utf-8", timeout: 1e4 });
|
|
77992
78129
|
if (r.status !== 0) {
|
|
77993
78130
|
warnings.push(`docker compose config --services failed: ${r.stderr?.trim() ?? r.error?.message ?? "unknown"}`);
|
|
77994
78131
|
return { cliVersion, cliBuiltAt, services, warnings };
|
|
@@ -78005,7 +78142,7 @@ function defaultStatusProbe(composePath) {
|
|
|
78005
78142
|
let containerCreatedAt = null;
|
|
78006
78143
|
let status = "<unknown>";
|
|
78007
78144
|
try {
|
|
78008
|
-
const r =
|
|
78145
|
+
const r = spawnSync10("docker", ["inspect", "-f", "{{.Config.Image}}|{{.Created}}|{{.State.Status}}", containerName2], { encoding: "utf-8", timeout: 5000 });
|
|
78009
78146
|
if (r.status === 0) {
|
|
78010
78147
|
const [img, created, st] = r.stdout.trim().split("|");
|
|
78011
78148
|
image = img ?? null;
|
|
@@ -78021,7 +78158,7 @@ function defaultStatusProbe(composePath) {
|
|
|
78021
78158
|
let imagePulledAt = null;
|
|
78022
78159
|
if (image) {
|
|
78023
78160
|
try {
|
|
78024
|
-
const r =
|
|
78161
|
+
const r = spawnSync10("docker", ["image", "inspect", "-f", "{{.Id}}|{{.Created}}|{{.Metadata.LastTagTime}}", image], { encoding: "utf-8", timeout: 5000 });
|
|
78025
78162
|
if (r.status === 0) {
|
|
78026
78163
|
const [id, created, lastTag] = r.stdout.trim().split("|");
|
|
78027
78164
|
imageDigestShort = id?.replace(/^sha256:/, "").slice(0, 12) ?? null;
|
|
@@ -78167,7 +78304,7 @@ function registerUpdateCommand(program3) {
|
|
|
78167
78304
|
|
|
78168
78305
|
// src/cli/rollout.ts
|
|
78169
78306
|
init_helpers();
|
|
78170
|
-
import { spawnSync as
|
|
78307
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
78171
78308
|
import { readFileSync as readFileSync53, chownSync as chownSync6, statSync as statSync27 } from "node:fs";
|
|
78172
78309
|
init_atomic();
|
|
78173
78310
|
function normalizeVersion(v) {
|
|
@@ -78339,11 +78476,11 @@ function registerRolloutCommand(program3) {
|
|
|
78339
78476
|
const scriptPath = process.argv[1] ?? "switchroom";
|
|
78340
78477
|
const deps = {
|
|
78341
78478
|
run: (args) => {
|
|
78342
|
-
const r =
|
|
78479
|
+
const r = spawnSync11(process.execPath, [scriptPath, ...args], { stdio: "inherit" });
|
|
78343
78480
|
return { status: r.status ?? 1 };
|
|
78344
78481
|
},
|
|
78345
78482
|
probeVersion: (agent) => {
|
|
78346
|
-
const r =
|
|
78483
|
+
const r = spawnSync11("docker", ["exec", `switchroom-${agent}`, "sh", "-lc", "switchroom --version"], { encoding: "utf8" });
|
|
78347
78484
|
if (r.status !== 0)
|
|
78348
78485
|
return null;
|
|
78349
78486
|
return (r.stdout ?? "").trim().split(`
|
|
@@ -79842,7 +79979,7 @@ init_helpers();
|
|
|
79842
79979
|
init_loader();
|
|
79843
79980
|
import { existsSync as existsSync64 } from "node:fs";
|
|
79844
79981
|
import { resolve as resolve40, sep as sep3 } from "node:path";
|
|
79845
|
-
import { spawnSync as
|
|
79982
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
79846
79983
|
|
|
79847
79984
|
// src/agents/workspace.ts
|
|
79848
79985
|
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
@@ -80555,7 +80692,7 @@ function registerWorkspaceCommand(program3) {
|
|
|
80555
80692
|
process.exit(1);
|
|
80556
80693
|
}
|
|
80557
80694
|
const editor = process.env["EDITOR"] ?? process.env["VISUAL"] ?? "vi";
|
|
80558
|
-
const child =
|
|
80695
|
+
const child = spawnSync12(editor, [target], { stdio: "inherit" });
|
|
80559
80696
|
if (child.status !== 0 && child.status !== null) {
|
|
80560
80697
|
process.exit(child.status);
|
|
80561
80698
|
}
|
|
@@ -80622,7 +80759,7 @@ function registerWorkspaceCommand(program3) {
|
|
|
80622
80759
|
`);
|
|
80623
80760
|
return;
|
|
80624
80761
|
}
|
|
80625
|
-
const statusResult =
|
|
80762
|
+
const statusResult = spawnSync12("git", ["status", "--short"], {
|
|
80626
80763
|
cwd: dir,
|
|
80627
80764
|
encoding: "utf-8"
|
|
80628
80765
|
});
|
|
@@ -80637,7 +80774,7 @@ function registerWorkspaceCommand(program3) {
|
|
|
80637
80774
|
return;
|
|
80638
80775
|
}
|
|
80639
80776
|
const message = opts.message || `checkpoint: ${new Date().toISOString()}`;
|
|
80640
|
-
const addResult =
|
|
80777
|
+
const addResult = spawnSync12("git", ["add", "-A"], {
|
|
80641
80778
|
cwd: dir,
|
|
80642
80779
|
encoding: "utf-8"
|
|
80643
80780
|
});
|
|
@@ -80646,7 +80783,7 @@ function registerWorkspaceCommand(program3) {
|
|
|
80646
80783
|
`);
|
|
80647
80784
|
process.exit(1);
|
|
80648
80785
|
}
|
|
80649
|
-
const commitResult =
|
|
80786
|
+
const commitResult = spawnSync12("git", ["commit", "-m", message], {
|
|
80650
80787
|
cwd: dir,
|
|
80651
80788
|
encoding: "utf-8"
|
|
80652
80789
|
});
|
|
@@ -80655,7 +80792,7 @@ function registerWorkspaceCommand(program3) {
|
|
|
80655
80792
|
`);
|
|
80656
80793
|
process.exit(1);
|
|
80657
80794
|
}
|
|
80658
|
-
const shaResult =
|
|
80795
|
+
const shaResult = spawnSync12("git", ["rev-parse", "--short", "HEAD"], {
|
|
80659
80796
|
cwd: dir,
|
|
80660
80797
|
encoding: "utf-8"
|
|
80661
80798
|
});
|
|
@@ -80676,7 +80813,7 @@ function registerWorkspaceCommand(program3) {
|
|
|
80676
80813
|
`);
|
|
80677
80814
|
return;
|
|
80678
80815
|
}
|
|
80679
|
-
const child =
|
|
80816
|
+
const child = spawnSync12("git", ["status", "--short"], {
|
|
80680
80817
|
cwd: dir,
|
|
80681
80818
|
stdio: "inherit"
|
|
80682
80819
|
});
|
|
@@ -83273,14 +83410,14 @@ async function computeAgentConnectionIssues(config, agentName, vaultAclReader) {
|
|
|
83273
83410
|
});
|
|
83274
83411
|
continue;
|
|
83275
83412
|
}
|
|
83276
|
-
if (
|
|
83413
|
+
if (entryScopeDenies(agentName, acl.allow, acl.deny)) {
|
|
83277
83414
|
const updated = [...new Set([...acl.allow, agentName])].sort().join(",");
|
|
83278
83415
|
issues.push({
|
|
83279
83416
|
server: r.server,
|
|
83280
83417
|
key,
|
|
83281
83418
|
kind: "acl",
|
|
83282
|
-
detail: `MCP '${r.server}'
|
|
83283
|
-
fix: `switchroom vault set ${key} --allow ${updated} (re-state the full list)`
|
|
83419
|
+
detail: `MCP '${r.server}' \u2014 vault entry scope for '${key}' denies this agent \u2014 broker will deny at runtime`,
|
|
83420
|
+
fix: `switchroom vault set ${key} --allow ${updated} (re-state the full list; drop from --deny if present)`
|
|
83284
83421
|
});
|
|
83285
83422
|
}
|
|
83286
83423
|
}
|
|
@@ -83710,7 +83847,11 @@ Applying switchroom config...
|
|
|
83710
83847
|
const { getViaBrokerStructured: getViaBrokerStructured2 } = await Promise.resolve().then(() => (init_client(), exports_client));
|
|
83711
83848
|
const result = await getViaBrokerStructured2(key);
|
|
83712
83849
|
if (result.kind === "ok") {
|
|
83713
|
-
return {
|
|
83850
|
+
return {
|
|
83851
|
+
kind: "ok",
|
|
83852
|
+
allow: result.entry.scope?.allow ?? [],
|
|
83853
|
+
deny: result.entry.scope?.deny ?? []
|
|
83854
|
+
};
|
|
83714
83855
|
}
|
|
83715
83856
|
if (result.kind === "not_found")
|
|
83716
83857
|
return { kind: "not_found" };
|
|
@@ -85771,7 +85912,7 @@ import {
|
|
|
85771
85912
|
} from "node:fs";
|
|
85772
85913
|
import { tmpdir as tmpdir5, homedir as homedir46 } from "node:os";
|
|
85773
85914
|
import { dirname as dirname24, join as join81, relative as relative2, resolve as resolve48 } from "node:path";
|
|
85774
|
-
import { spawnSync as
|
|
85915
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
85775
85916
|
|
|
85776
85917
|
// src/cli/skill-common.ts
|
|
85777
85918
|
var import_yaml23 = __toESM(require_dist(), 1);
|
|
@@ -86024,7 +86165,7 @@ function loadFromDir(dir) {
|
|
|
86024
86165
|
function loadFromTarball(tarPath) {
|
|
86025
86166
|
const isGz = tarPath.endsWith(".gz") || tarPath.endsWith(".tgz");
|
|
86026
86167
|
const listFlags = isGz ? ["-tzf"] : ["-tf"];
|
|
86027
|
-
const list2 =
|
|
86168
|
+
const list2 = spawnSync13("tar", [...listFlags, tarPath], {
|
|
86028
86169
|
encoding: "utf-8",
|
|
86029
86170
|
stdio: ["ignore", "pipe", "pipe"]
|
|
86030
86171
|
});
|
|
@@ -86041,7 +86182,7 @@ function loadFromTarball(tarPath) {
|
|
|
86041
86182
|
const staging = mkdtempSync5(join81(tmpdir5(), "skill-apply-extract-"));
|
|
86042
86183
|
try {
|
|
86043
86184
|
const flags = isGz ? ["-xzf"] : ["-xf"];
|
|
86044
|
-
const r =
|
|
86185
|
+
const r = spawnSync13("tar", [
|
|
86045
86186
|
...flags,
|
|
86046
86187
|
tarPath,
|
|
86047
86188
|
"-C",
|
|
@@ -86116,7 +86257,7 @@ function validatePayload(name, files) {
|
|
|
86116
86257
|
if (errors2.length === 0) {
|
|
86117
86258
|
for (const [path8, content] of Object.entries(files)) {
|
|
86118
86259
|
if (SH_SCRIPT_RE2.test(path8)) {
|
|
86119
|
-
const r =
|
|
86260
|
+
const r = spawnSync13("bash", ["-n"], {
|
|
86120
86261
|
input: content,
|
|
86121
86262
|
encoding: "utf-8"
|
|
86122
86263
|
});
|
|
@@ -86128,7 +86269,7 @@ function validatePayload(name, files) {
|
|
|
86128
86269
|
const tmpPy = join81(tmp, "check.py");
|
|
86129
86270
|
try {
|
|
86130
86271
|
writeFileSync40(tmpPy, content);
|
|
86131
|
-
const r =
|
|
86272
|
+
const r = spawnSync13("python3", ["-m", "py_compile", tmpPy], {
|
|
86132
86273
|
encoding: "utf-8"
|
|
86133
86274
|
});
|
|
86134
86275
|
if (r.status !== 0) {
|
|
@@ -86291,7 +86432,7 @@ function registerSkillCommand(program3) {
|
|
|
86291
86432
|
\u2713 Wrote ${name} to ${currentDir}`));
|
|
86292
86433
|
const applyBin = process.argv[1] ?? "switchroom";
|
|
86293
86434
|
console.log(source_default.gray(`Running \`switchroom apply --non-interactive\`...`));
|
|
86294
|
-
const r =
|
|
86435
|
+
const r = spawnSync13(process.argv0, [applyBin, "apply", "--non-interactive"], { stdio: "inherit" });
|
|
86295
86436
|
if (r.status !== 0) {
|
|
86296
86437
|
console.error(source_default.yellow(`(warning: \`switchroom apply\` exited ${r.status} \u2014 skill is ` + `in the pool but symlinks may not be refreshed. Re-run manually.)`));
|
|
86297
86438
|
}
|
|
@@ -86323,7 +86464,7 @@ import {
|
|
|
86323
86464
|
} from "node:fs";
|
|
86324
86465
|
import { dirname as dirname25, join as join82, relative as relative3, resolve as resolve49 } from "node:path";
|
|
86325
86466
|
import { homedir as homedir47, tmpdir as tmpdir6 } from "node:os";
|
|
86326
|
-
import { spawnSync as
|
|
86467
|
+
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
86327
86468
|
init_helpers();
|
|
86328
86469
|
init_source();
|
|
86329
86470
|
var PERSONAL_PREFIX = "personal-";
|
|
@@ -86512,7 +86653,7 @@ function behavioralValidate(files) {
|
|
|
86512
86653
|
const errors2 = [];
|
|
86513
86654
|
for (const [path8, content] of Object.entries(files)) {
|
|
86514
86655
|
if (SH_SCRIPT_RE.test(path8)) {
|
|
86515
|
-
const r =
|
|
86656
|
+
const r = spawnSync14("bash", ["-n"], { input: content, encoding: "utf-8" });
|
|
86516
86657
|
if (r.status !== 0) {
|
|
86517
86658
|
errors2.push(`${path8} fails \`bash -n\`: ${(r.stderr ?? "").trim()}`);
|
|
86518
86659
|
}
|
|
@@ -86521,7 +86662,7 @@ function behavioralValidate(files) {
|
|
|
86521
86662
|
const tmpPy = join82(tmp, "check.py");
|
|
86522
86663
|
try {
|
|
86523
86664
|
writeFileSync41(tmpPy, content);
|
|
86524
|
-
const r =
|
|
86665
|
+
const r = spawnSync14("python3", ["-m", "py_compile", tmpPy], {
|
|
86525
86666
|
encoding: "utf-8"
|
|
86526
86667
|
});
|
|
86527
86668
|
if (r.status !== 0) {
|
|
@@ -87214,15 +87355,15 @@ init_helpers();
|
|
|
87214
87355
|
import { existsSync as existsSync84, mkdirSync as mkdirSync48, readdirSync as readdirSync33, readFileSync as readFileSync72, writeFileSync as writeFileSync42, statSync as statSync35, copyFileSync as copyFileSync12 } from "node:fs";
|
|
87215
87356
|
import { homedir as homedir49 } from "node:os";
|
|
87216
87357
|
import { join as join84 } from "node:path";
|
|
87217
|
-
import { spawnSync as
|
|
87358
|
+
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
87218
87359
|
|
|
87219
87360
|
// src/cli/deploy-version-guard.ts
|
|
87220
|
-
import { spawnSync as
|
|
87221
|
-
var
|
|
87222
|
-
const r =
|
|
87361
|
+
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
87362
|
+
var defaultRunner3 = (args) => {
|
|
87363
|
+
const r = spawnSync16("docker", args, { encoding: "utf8" });
|
|
87223
87364
|
return { ok: r.status === 0, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
87224
87365
|
};
|
|
87225
|
-
function deployedImageTag(container, run =
|
|
87366
|
+
function deployedImageTag(container, run = defaultRunner3) {
|
|
87226
87367
|
const r = run(["inspect", "-f", "{{.Config.Image}}", container]);
|
|
87227
87368
|
if (!r.ok)
|
|
87228
87369
|
return null;
|
|
@@ -87391,7 +87532,7 @@ function backupExistingCompose() {
|
|
|
87391
87532
|
return bak;
|
|
87392
87533
|
}
|
|
87393
87534
|
function runDocker(args) {
|
|
87394
|
-
const r =
|
|
87535
|
+
const r = spawnSync17("docker", args, { encoding: "utf8" });
|
|
87395
87536
|
return {
|
|
87396
87537
|
ok: r.status === 0,
|
|
87397
87538
|
stdout: r.stdout ?? "",
|
|
@@ -87593,7 +87734,7 @@ init_helpers();
|
|
|
87593
87734
|
import { existsSync as existsSync85, mkdirSync as mkdirSync49, writeFileSync as writeFileSync43, copyFileSync as copyFileSync13 } from "node:fs";
|
|
87594
87735
|
import { homedir as homedir50 } from "node:os";
|
|
87595
87736
|
import { join as join85 } from "node:path";
|
|
87596
|
-
import { spawnSync as
|
|
87737
|
+
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
87597
87738
|
function resolveWebImageTag(explicitTag, release) {
|
|
87598
87739
|
if (explicitTag)
|
|
87599
87740
|
return explicitTag;
|
|
@@ -87692,7 +87833,7 @@ function backupExistingCompose2() {
|
|
|
87692
87833
|
return bak;
|
|
87693
87834
|
}
|
|
87694
87835
|
function runDocker2(args) {
|
|
87695
|
-
const r =
|
|
87836
|
+
const r = spawnSync18("docker", args, { encoding: "utf8" });
|
|
87696
87837
|
return {
|
|
87697
87838
|
ok: r.status === 0,
|
|
87698
87839
|
stdout: r.stdout ?? "",
|
package/package.json
CHANGED
|
@@ -28,6 +28,8 @@ You are operating in the **{{topicName}}** {{#if topicEmoji}}{{topicEmoji}} {{/i
|
|
|
28
28
|
- Prefer `trash` over `rm` when available (recoverable beats gone forever).
|
|
29
29
|
- Safe to do freely: read files, explore, organize, search the web, check calendars, work within this workspace.
|
|
30
30
|
- Ask first: sending emails, tweets, public posts, anything that leaves the machine, anything you're uncertain about.
|
|
31
|
+
- **Batch foreseeable approvals; don't drip surprises.** When you can already see that several actions will each need the user's approval, tell them up front which approvals are coming and why. Request independent ones together so they can decide once; for dependent ones (one's input comes from another), say what you're doing first and what approval comes next — a permission card should never arrive out of the blue.
|
|
32
|
+
- **A timed-out approval isn't a denial.** If a request came back denied only because the user was away (a timeout, not an explicit "no"), don't silently abandon it. When they're back, remind them it's still pending and re-offer it if they still want it.
|
|
31
33
|
|
|
32
34
|
## Execution Bias
|
|
33
35
|
|
|
@@ -54519,11 +54519,11 @@ function readTurnActiveMarkerAgeMs(stateDir, now) {
|
|
|
54519
54519
|
}
|
|
54520
54520
|
|
|
54521
54521
|
// ../src/build-info.ts
|
|
54522
|
-
var VERSION = "0.15.
|
|
54523
|
-
var COMMIT_SHA = "
|
|
54524
|
-
var COMMIT_DATE = "2026-06-
|
|
54522
|
+
var VERSION = "0.15.40";
|
|
54523
|
+
var COMMIT_SHA = "fd53cf02";
|
|
54524
|
+
var COMMIT_DATE = "2026-06-18T13:00:59+10:00";
|
|
54525
54525
|
var LATEST_PR = null;
|
|
54526
|
-
var COMMITS_AHEAD_OF_TAG =
|
|
54526
|
+
var COMMITS_AHEAD_OF_TAG = 4;
|
|
54527
54527
|
|
|
54528
54528
|
// gateway/boot-version.ts
|
|
54529
54529
|
function formatRelativeAgo(iso) {
|