switchroom 0.15.39 → 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.
@@ -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 = import_yaml9.parseDocument(yamlText);
28444
+ const doc = import_yaml10.parseDocument(yamlText);
28445
28445
  const root = doc.contents;
28446
- if (!import_yaml9.isMap(root)) {
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 (import_yaml9.isMap(existing)) {
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 import_yaml9;
28463
+ var import_yaml10;
28464
28464
  var init_auth_active_yaml = __esm(() => {
28465
- import_yaml9 = __toESM(require_dist(), 1);
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 spawnSync2 } from "node:child_process";
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 = spawnSync2("tmux", ["has-session", "-t", session], {
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 spawnSync6 } from "node:child_process";
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 = spawnSync6("docker", ["inspect", "-f", format, container], { encoding: "utf-8", timeout: 5000 });
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 = spawnSync6("docker", ["exec", container, "test", "-S", path4], { encoding: "utf-8", timeout: 5000 });
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(AUTH_BROKER_CONTAINER, "{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}");
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 \`${AUTH_BROKER_CONTAINER}\` not found via \`docker inspect\``,
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(AUTH_BROKER_CONTAINER, socketPath)) {
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 AUTH_BROKER_CONTAINER = "switchroom-auth-broker";
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 spawnSync7 } from "node:child_process";
30200
+ import { spawnSync as spawnSync8 } from "node:child_process";
30201
30201
  function realDockerInspect(ref, format) {
30202
30202
  try {
30203
- const r = spawnSync7("docker", ["inspect", ref, "--format", format], {
30203
+ const r = spawnSync8("docker", ["inspect", ref, "--format", format], {
30204
30204
  encoding: "utf-8",
30205
30205
  timeout: 5000
30206
30206
  });
@@ -32321,7 +32321,7 @@ __export(exports_doctor, {
32321
32321
  checkAgents: () => checkAgents,
32322
32322
  MFF_VAULT_KEY: () => MFF_VAULT_KEY
32323
32323
  });
32324
- import { execSync as execSync3, spawnSync as spawnSync8 } from "node:child_process";
32324
+ import { execSync as execSync3, spawnSync as spawnSync9 } from "node:child_process";
32325
32325
  import {
32326
32326
  accessSync as accessSync2,
32327
32327
  constants as fsConstants5,
@@ -32669,7 +32669,7 @@ function probeVaultBrokerSocketPair(agentName) {
32669
32669
  const dataPath = `/run/switchroom/broker/${agentName}/sock`;
32670
32670
  const unlockPath = `/run/switchroom/broker/${agentName}/unlock`;
32671
32671
  const script = `D=0; U=0; ` + `test -S '${dataPath}' && D=1; ` + `test -S '${unlockPath}' && U=1; ` + `echo "D=$D U=$U"`;
32672
- const r = spawnSync8("docker", ["exec", "switchroom-vault-broker", "sh", "-c", script], { stdio: "pipe", timeout: 3000 });
32672
+ const r = spawnSync9("docker", ["exec", "switchroom-vault-broker", "sh", "-c", script], { stdio: "pipe", timeout: 3000 });
32673
32673
  if (r.error || r.status === null)
32674
32674
  return "unreachable";
32675
32675
  if (r.status !== 0) {
@@ -32868,7 +32868,7 @@ function checkHindsightConsumer(config, opts) {
32868
32868
  }
32869
32869
  function probeAuthBrokerSocket(consumerName) {
32870
32870
  const containerPath = `/run/switchroom/auth-broker/${consumerName}/sock`;
32871
- const r = spawnSync8("docker", ["exec", "switchroom-auth-broker", "test", "-S", containerPath], { stdio: "pipe", timeout: 3000 });
32871
+ const r = spawnSync9("docker", ["exec", "switchroom-auth-broker", "test", "-S", containerPath], { stdio: "pipe", timeout: 3000 });
32872
32872
  if (r.error || r.status === null)
32873
32873
  return "unreachable";
32874
32874
  if (r.status === 0)
@@ -33759,7 +33759,7 @@ async function checkMffAuthFlow(envPath = mffEnvPath(), timeoutMs = 8000) {
33759
33759
  const python3 = which("python3") ?? "python3";
33760
33760
  let token;
33761
33761
  try {
33762
- const result = spawnSync8(python3, [authScript, "--quiet"], {
33762
+ const result = spawnSync9(python3, [authScript, "--quiet"], {
33763
33763
  timeout: timeoutMs,
33764
33764
  encoding: "utf-8",
33765
33765
  env: { ...process.env, ...env2 }
@@ -49790,9 +49790,9 @@ __export(exports_server, {
49790
49790
  dispatchTool: () => dispatchTool,
49791
49791
  TOOLS: () => TOOLS
49792
49792
  });
49793
- import { spawnSync as spawnSync14 } from "node:child_process";
49793
+ import { spawnSync as spawnSync15 } from "node:child_process";
49794
49794
  function execCli(args, stdin) {
49795
- const r = spawnSync14(CLI_BIN, args, {
49795
+ const r = spawnSync15(CLI_BIN, args, {
49796
49796
  encoding: "utf-8",
49797
49797
  env: process.env,
49798
49798
  timeout: 15000,
@@ -50702,8 +50702,8 @@ var {
50702
50702
  } = import__.default;
50703
50703
 
50704
50704
  // src/build-info.ts
50705
- var VERSION = "0.15.39";
50706
- var COMMIT_SHA = "69e5a2e8";
50705
+ var VERSION = "0.15.40";
50706
+ var COMMIT_SHA = "fd53cf02";
50707
50707
 
50708
50708
  // src/cli/agent.ts
50709
50709
  init_source();
@@ -52601,7 +52601,7 @@ function buildHumanizerEnvVars(agentDir, agent) {
52601
52601
  function buildToolSearchEnvVars() {
52602
52602
  if (process.env.SWITCHROOM_DISABLE_TOOL_SEARCH === "1")
52603
52603
  return {};
52604
- return { ENABLE_TOOL_SEARCH: process.env.SWITCHROOM_TOOL_SEARCH_MODE ?? "auto" };
52604
+ return { ENABLE_TOOL_SEARCH: process.env.SWITCHROOM_TOOL_SEARCH_MODE ?? "true" };
52605
52605
  }
52606
52606
  var SWITCHROOM_OWNED_SETTINGS_KEYS = new Set([
52607
52607
  "permissions",
@@ -59732,6 +59732,134 @@ function pruneEmptyMap(doc, path) {
59732
59732
  // src/cli/auth-microsoft.ts
59733
59733
  init_helpers();
59734
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
+
59735
59863
  // src/auth/default-oauth-clients.ts
59736
59864
  var DEFAULT_MICROSOFT_CLIENT_ID = "9dff88fa-3126-457b-9d1d-37e58c219019";
59737
59865
  function resolveMicrosoftClientId(configClientId) {
@@ -59820,19 +59948,16 @@ function registerAuthMicrosoftSubcommands(program3, authParent) {
59820
59948
  registerAccountList2(account);
59821
59949
  }
59822
59950
  function registerEnable2(microsoftParent, program3) {
59823
- 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[] \u2014 does NOT mint the broker credentials (use `auth microsoft account add` for that).").action(withConfigError(async (account, agents) => {
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) => {
59824
59952
  const normalizedAccount = validateAndNormalizeAccountEmail2(account);
59825
59953
  const config = getConfig(program3);
59826
59954
  agents = expandAllAgents2(agents, config);
59827
59955
  validateAgentSlugs(agents, config);
59828
59956
  const yamlPath = getConfigPath(program3);
59829
59957
  const before = readFileSync26(yamlPath, "utf-8");
59830
- const enabledBefore = getEnabledAgentsBefore2(before, normalizedAccount);
59831
- const after = enableAgentsOnMicrosoftAccount(before, normalizedAccount, agents);
59832
- if (after !== before)
59833
- writeFileSync16(yamlPath, after);
59834
- const enabledAfter = getEnabledAgentsForMicrosoftAccount(after, normalizedAccount) ?? [];
59835
- 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);
59836
59961
  console.log();
59837
59962
  if (newlyEnabled.length === 0) {
59838
59963
  console.log(`No change \u2014 all of ${agents.join(", ")} already enabled on ${source_default.bold(normalizedAccount)}.`);
@@ -59843,9 +59968,26 @@ function registerEnable2(microsoftParent, program3) {
59843
59968
  const alreadyEnabled = enabledAfter.filter((a) => !newlyEnabled.includes(a));
59844
59969
  console.log(` ${source_default.gray("already enabled on:")} ${alreadyEnabled.join(", ")}`);
59845
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
+ }
59846
59987
  console.log();
59847
- if (newlyEnabled.length > 0) {
59848
- console.log(`Next: ${source_default.bold(`switchroom agent restart ${newlyEnabled.join(" ")}`)} so the wrapper picks up the new ACL.`);
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.`);
59849
59991
  console.log();
59850
59992
  }
59851
59993
  }));
@@ -59864,11 +60006,9 @@ function registerDisable2(microsoftParent, program3) {
59864
60006
  console.log();
59865
60007
  return;
59866
60008
  }
59867
- const after = disableAgentsOnMicrosoftAccount(before, normalizedAccount, agents);
59868
- if (after !== before)
59869
- writeFileSync16(yamlPath, after);
59870
- const enabledAfter = getEnabledAgentsForMicrosoftAccount(after, normalizedAccount) ?? [];
59871
- 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);
59872
60012
  console.log();
59873
60013
  if (removed.length === 0) {
59874
60014
  console.log(`No change \u2014 none of ${agents.join(", ")} were enabled on ${source_default.bold(normalizedAccount)}.`);
@@ -59880,9 +60020,22 @@ function registerDisable2(microsoftParent, program3) {
59880
60020
  } else {
59881
60021
  console.log(` ${source_default.gray("still enabled on:")} ${enabledAfter.join(", ")}`);
59882
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
+ }
59883
60036
  console.log();
59884
60037
  if (removed.length > 0) {
59885
- console.log(`Next: ${source_default.bold(`switchroom agent restart ${removed.join(" ")}`)} so the wrapper drops its access.`);
60038
+ console.log(`Next: ${source_default.bold(`switchroom agent restart ${removed.join(" ")}`)} so the agent drops the Microsoft MCP from its config.`);
59886
60039
  console.log();
59887
60040
  }
59888
60041
  }));
@@ -65692,8 +65845,8 @@ init_vault();
65692
65845
  // src/cli/vault-auto-unlock.ts
65693
65846
  init_loader();
65694
65847
  init_client();
65695
- var import_yaml10 = __toESM(require_dist(), 1);
65696
- import { spawnSync as spawnSync3 } from "node:child_process";
65848
+ var import_yaml11 = __toESM(require_dist(), 1);
65849
+ import { spawnSync as spawnSync4 } from "node:child_process";
65697
65850
  import { readFileSync as readFileSync33, writeFileSync as writeFileSync20 } from "node:fs";
65698
65851
  import { homedir as homedir18 } from "node:os";
65699
65852
  import { join as join34 } from "node:path";
@@ -65725,7 +65878,7 @@ function encryptCredential(passphrase, credPath) {
65725
65878
  }
65726
65879
  function setVaultBrokerAutoUnlock(configPath, value) {
65727
65880
  const raw = readFileSync33(configPath, "utf-8");
65728
- const doc = import_yaml10.default.parseDocument(raw);
65881
+ const doc = import_yaml11.default.parseDocument(raw);
65729
65882
  doc.setIn(["vault", "broker", "autoUnlock"], value);
65730
65883
  writeFileSync20(configPath, doc.toString(), "utf-8");
65731
65884
  }
@@ -65733,7 +65886,7 @@ var DEFAULT_COMPOSE_FILE = join34(homedir18(), ".switchroom", "compose", "docker
65733
65886
  async function applyAutoUnlock(opts = {}) {
65734
65887
  const log = opts.log ?? ((s) => console.log(s));
65735
65888
  const err = opts.err ?? ((s) => console.error(s));
65736
- const runDockerCompose = opts.runDockerCompose ?? ((args) => spawnSync3("docker", args, { stdio: "inherit" }));
65889
+ const runDockerCompose = opts.runDockerCompose ?? ((args) => spawnSync4("docker", args, { stdio: "inherit" }));
65737
65890
  const verifyTimeoutMs = opts.verifyTimeoutMs ?? 1e4;
65738
65891
  const configPath = opts.configPath ?? findConfigFile();
65739
65892
  const composeFile = opts.composeFile ?? DEFAULT_COMPOSE_FILE;
@@ -67647,9 +67800,9 @@ init_paths();
67647
67800
  import { createInterface as createInterface4 } from "node:readline";
67648
67801
 
67649
67802
  // src/cli/telegram-yaml.ts
67650
- var import_yaml11 = __toESM(require_dist(), 1);
67803
+ var import_yaml12 = __toESM(require_dist(), 1);
67651
67804
  function setLinearAgent(yamlText, agentName, opts) {
67652
- const doc = import_yaml11.parseDocument(yamlText);
67805
+ const doc = import_yaml12.parseDocument(yamlText);
67653
67806
  ensureAgent(doc, agentName);
67654
67807
  const block = { enabled: true, token: opts.token };
67655
67808
  if (opts.workspaceId)
@@ -67659,7 +67812,7 @@ function setLinearAgent(yamlText, agentName, opts) {
67659
67812
  return String(doc);
67660
67813
  }
67661
67814
  function setLinearDefaultTeam(yamlText, agentName, teamId) {
67662
- const doc = import_yaml11.parseDocument(yamlText);
67815
+ const doc = import_yaml12.parseDocument(yamlText);
67663
67816
  ensureAgent(doc, agentName);
67664
67817
  if (!doc.hasIn(["agents", agentName, "channels", "telegram", "linear_agent"])) {
67665
67818
  throw new Error(`agent '${agentName}' has no linear_agent block. Run 'switchroom linear-agent setup --agent ${agentName} --token <token>' first.`);
@@ -67674,13 +67827,13 @@ function setLinearDefaultTeam(yamlText, agentName, teamId) {
67674
67827
  return String(doc);
67675
67828
  }
67676
67829
  function setTelegramFeature(yamlText, agentName, feature, value) {
67677
- const doc = import_yaml11.parseDocument(yamlText);
67830
+ const doc = import_yaml12.parseDocument(yamlText);
67678
67831
  ensureAgent(doc, agentName);
67679
67832
  doc.setIn(["agents", agentName, "channels", "telegram", feature], value);
67680
67833
  return String(doc);
67681
67834
  }
67682
67835
  function removeTelegramFeature(yamlText, agentName, feature) {
67683
- const doc = import_yaml11.parseDocument(yamlText);
67836
+ const doc = import_yaml12.parseDocument(yamlText);
67684
67837
  if (!hasAgent(doc, agentName))
67685
67838
  return yamlText;
67686
67839
  if (!doc.hasIn(["agents", agentName, "channels", "telegram", feature])) {
@@ -67698,21 +67851,21 @@ function ensureAgent(doc, agentName) {
67698
67851
  }
67699
67852
  function hasAgent(doc, agentName) {
67700
67853
  const agents = doc.get("agents");
67701
- if (!import_yaml11.isMap(agents))
67854
+ if (!import_yaml12.isMap(agents))
67702
67855
  return false;
67703
67856
  return agents.has(agentName);
67704
67857
  }
67705
67858
  function pruneEmptyMap2(doc, path4) {
67706
67859
  const node = doc.getIn(path4);
67707
- if (import_yaml11.isMap(node) && node.items.length === 0) {
67860
+ if (import_yaml12.isMap(node) && node.items.length === 0) {
67708
67861
  doc.deleteIn(path4);
67709
67862
  }
67710
67863
  }
67711
67864
  function addWebhookSource(yamlText, agentName, source) {
67712
- const doc = import_yaml11.parseDocument(yamlText);
67865
+ const doc = import_yaml12.parseDocument(yamlText);
67713
67866
  ensureAgent(doc, agentName);
67714
67867
  const existing = doc.getIn(["agents", agentName, "channels", "telegram", "webhook_sources"]);
67715
- if (import_yaml11.isSeq(existing)) {
67868
+ if (import_yaml12.isSeq(existing)) {
67716
67869
  const seq = existing;
67717
67870
  for (const item of seq.items) {
67718
67871
  const v = item.value ?? item;
@@ -67726,10 +67879,10 @@ function addWebhookSource(yamlText, agentName, source) {
67726
67879
  return String(doc);
67727
67880
  }
67728
67881
  function addAgentSecret(yamlText, agentName, key) {
67729
- const doc = import_yaml11.parseDocument(yamlText);
67882
+ const doc = import_yaml12.parseDocument(yamlText);
67730
67883
  ensureAgent(doc, agentName);
67731
67884
  const existing = doc.getIn(["agents", agentName, "secrets"]);
67732
- if (import_yaml11.isSeq(existing)) {
67885
+ if (import_yaml12.isSeq(existing)) {
67733
67886
  const seq = existing;
67734
67887
  for (const item of seq.items) {
67735
67888
  const v = item.value ?? item;
@@ -67743,11 +67896,11 @@ function addAgentSecret(yamlText, agentName, key) {
67743
67896
  return String(doc);
67744
67897
  }
67745
67898
  function removeWebhookSource(yamlText, agentName, source) {
67746
- const doc = import_yaml11.parseDocument(yamlText);
67899
+ const doc = import_yaml12.parseDocument(yamlText);
67747
67900
  if (!hasAgent(doc, agentName))
67748
67901
  return yamlText;
67749
67902
  const existing = doc.getIn(["agents", agentName, "channels", "telegram", "webhook_sources"]);
67750
- if (!import_yaml11.isSeq(existing))
67903
+ if (!import_yaml12.isSeq(existing))
67751
67904
  return yamlText;
67752
67905
  const seq = existing;
67753
67906
  const beforeLen = seq.items.length;
@@ -68795,17 +68948,17 @@ function generateHindsightComposeSnippet() {
68795
68948
  }
68796
68949
  async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFAULT_UID) {
68797
68950
  const fs4 = await import("node:fs");
68798
- const { parseDocument: parseDocument6, isMap: isMap6, isSeq: isSeq4, YAMLMap, YAMLSeq } = await Promise.resolve().then(() => __toESM(require_dist(), 1));
68951
+ const { parseDocument: parseDocument7, isMap: isMap7, isSeq: isSeq4, YAMLMap, YAMLSeq } = await Promise.resolve().then(() => __toESM(require_dist(), 1));
68799
68952
  const { atomicWriteFileSync: atomicWriteFileSync3 } = await Promise.resolve().then(() => (init_atomic(), exports_atomic));
68800
68953
  const raw = fs4.readFileSync(configPath, "utf-8");
68801
- const doc = parseDocument6(raw);
68954
+ const doc = parseDocument7(raw);
68802
68955
  const root = doc.contents;
68803
- if (!isMap6(root)) {
68956
+ if (!isMap7(root)) {
68804
68957
  return { added: false, reason: "switchroom.yaml root is not a map" };
68805
68958
  }
68806
68959
  const authRaw = root.get("auth", true);
68807
68960
  let authNode;
68808
- if (isMap6(authRaw)) {
68961
+ if (isMap7(authRaw)) {
68809
68962
  authNode = authRaw;
68810
68963
  } else {
68811
68964
  authNode = new YAMLMap;
@@ -68820,7 +68973,7 @@ async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFA
68820
68973
  doc.setIn(["auth", "consumers"], consumersNode);
68821
68974
  }
68822
68975
  for (const item of consumersNode.items) {
68823
- if (isMap6(item)) {
68976
+ if (isMap7(item)) {
68824
68977
  const name = item.get("name");
68825
68978
  if (name === HINDSIGHT_CONSUMER_NAME) {
68826
68979
  return { added: false, reason: "already present" };
@@ -68846,7 +68999,7 @@ async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFA
68846
68999
 
68847
69000
  // src/cli/memory.ts
68848
69001
  init_loader();
68849
- var import_yaml12 = __toESM(require_dist(), 1);
69002
+ var import_yaml13 = __toESM(require_dist(), 1);
68850
69003
  import { existsSync as existsSync44, readFileSync as readFileSync40, writeFileSync as writeFileSync23 } from "node:fs";
68851
69004
  import { join as join39 } from "node:path";
68852
69005
  function readRecallLog(agentDir, limit) {
@@ -69051,7 +69204,7 @@ Cross-agent reflection plan
69051
69204
  try {
69052
69205
  if (existsSync44(configPath)) {
69053
69206
  const raw = readFileSync40(configPath, "utf-8");
69054
- const doc = import_yaml12.default.parseDocument(raw);
69207
+ const doc = import_yaml13.default.parseDocument(raw);
69055
69208
  if (!doc.has("memory")) {
69056
69209
  doc.set("memory", { backend: "hindsight", shared_collection: "shared", config: { provider, url } });
69057
69210
  } else {
@@ -69175,7 +69328,7 @@ import { timingSafeEqual as timingSafeEqual3, randomBytes as randomBytes11 } fro
69175
69328
  init_lifecycle();
69176
69329
  init_manager();
69177
69330
  init_hindsight();
69178
- import { spawnSync as spawnSync5 } from "node:child_process";
69331
+ import { spawnSync as spawnSync6 } from "node:child_process";
69179
69332
  import { existsSync as existsSync47, readFileSync as readFileSync43, statSync as statSync22 } from "node:fs";
69180
69333
  import { resolve as resolve28, join as join44 } from "node:path";
69181
69334
 
@@ -73861,54 +74014,6 @@ function installGlobalErrorHandlers() {
73861
74014
  init_loader();
73862
74015
  init_merge();
73863
74016
 
73864
- // src/config/agent-workspace-account.ts
73865
- var import_yaml13 = __toESM(require_dist(), 1);
73866
- function blockKey(provider) {
73867
- return `${provider}_workspace`;
73868
- }
73869
- function setAgentWorkspaceAccount(yamlText, provider, agent, account) {
73870
- const doc = import_yaml13.parseDocument(yamlText);
73871
- const agentsNode = doc.get("agents");
73872
- if (!import_yaml13.isMap(agentsNode)) {
73873
- throw new Error("switchroom.yaml has no `agents:` map");
73874
- }
73875
- if (!agentsNode.has(agent)) {
73876
- throw new Error(`agent '${agent}' is not declared in switchroom.yaml`);
73877
- }
73878
- const path4 = ["agents", agent, blockKey(provider), "account"];
73879
- const current = doc.getIn(path4);
73880
- if (current === account)
73881
- return yamlText;
73882
- doc.setIn(path4, account);
73883
- return String(doc);
73884
- }
73885
- function clearAgentWorkspaceAccount(yamlText, provider, agent) {
73886
- const doc = import_yaml13.parseDocument(yamlText);
73887
- const agentsNode = doc.get("agents");
73888
- if (!import_yaml13.isMap(agentsNode))
73889
- return yamlText;
73890
- if (!agentsNode.has(agent))
73891
- return yamlText;
73892
- const blockPath = ["agents", agent, blockKey(provider)];
73893
- const block = doc.getIn(blockPath);
73894
- if (!import_yaml13.isMap(block))
73895
- return yamlText;
73896
- const accountPath = [...blockPath, "account"];
73897
- if (doc.getIn(accountPath) === undefined)
73898
- return yamlText;
73899
- doc.deleteIn(accountPath);
73900
- const after = doc.getIn(blockPath);
73901
- if (import_yaml13.isMap(after) && after.items.length === 0) {
73902
- doc.deleteIn(blockPath);
73903
- }
73904
- return String(doc);
73905
- }
73906
- function getAgentWorkspaceAccount(yamlText, provider, agent) {
73907
- const doc = import_yaml13.parseDocument(yamlText);
73908
- const v = doc.getIn(["agents", agent, blockKey(provider), "account"]);
73909
- return typeof v === "string" ? v : null;
73910
- }
73911
-
73912
74017
  // src/web/config-edit-plan.ts
73913
74018
  init_schema();
73914
74019
  var import_yaml14 = __toESM(require_dist(), 1);
@@ -73955,7 +74060,7 @@ import {
73955
74060
  rmSync as rmrf,
73956
74061
  writeFileSync as writeFileSync25
73957
74062
  } from "node:fs";
73958
- import { spawnSync as spawnSync4 } from "node:child_process";
74063
+ import { spawnSync as spawnSync5 } from "node:child_process";
73959
74064
  import { tmpdir as tmpdir4 } from "node:os";
73960
74065
  import { join as join41 } from "node:path";
73961
74066
 
@@ -73970,7 +74075,7 @@ function generateUnifiedDiff(before, after, name = "switchroom.yaml", gitBin = "
73970
74075
  mkdirSync26(join41(dir, "new"), { recursive: true });
73971
74076
  writeFileSync25(join41(dir, "cur", name), before);
73972
74077
  writeFileSync25(join41(dir, "new", name), after);
73973
- const r = spawnSync4(gitBin, ["diff", "--no-index", "--no-color", "--", `cur/${name}`, `new/${name}`], { cwd: dir, encoding: "utf-8", timeout: 1e4 });
74078
+ const r = spawnSync5(gitBin, ["diff", "--no-index", "--no-color", "--", `cur/${name}`, `new/${name}`], { cwd: dir, encoding: "utf-8", timeout: 1e4 });
73974
74079
  if (r.status === 0)
73975
74080
  return "";
73976
74081
  if (r.status !== 1) {
@@ -74757,7 +74862,7 @@ function inspectEnv(container, keys) {
74757
74862
  const out = {};
74758
74863
  for (const k of keys)
74759
74864
  out[k] = null;
74760
- const res = spawnSync5("docker", ["inspect", "--format", "{{json .Config.Env}}", container], { encoding: "utf-8", timeout: 4000 });
74865
+ const res = spawnSync6("docker", ["inspect", "--format", "{{json .Config.Env}}", container], { encoding: "utf-8", timeout: 4000 });
74761
74866
  if (res.error || res.status !== 0 || !res.stdout)
74762
74867
  return out;
74763
74868
  try {
@@ -77669,7 +77774,7 @@ init_source();
77669
77774
  init_loader();
77670
77775
  init_lifecycle();
77671
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";
77672
- import { spawnSync as spawnSync9 } from "node:child_process";
77777
+ import { spawnSync as spawnSync10 } from "node:child_process";
77673
77778
  import { join as join61, dirname as dirname15, resolve as resolve35 } from "node:path";
77674
77779
  import { homedir as homedir37 } from "node:os";
77675
77780
 
@@ -77739,7 +77844,7 @@ function rebuildRefusalMessage(scriptPath) {
77739
77844
  }
77740
77845
  function planUpdate(opts) {
77741
77846
  const composePath = opts.composePath ?? DEFAULT_COMPOSE_PATH;
77742
- const runner = opts.runner ?? defaultRunner;
77847
+ const runner = opts.runner ?? defaultRunner2;
77743
77848
  const scriptPath = opts.scriptPath ?? process.argv[1] ?? "";
77744
77849
  const steps = [];
77745
77850
  if (opts.pin) {
@@ -77944,8 +78049,8 @@ function planUpdate(opts) {
77944
78049
  });
77945
78050
  return steps;
77946
78051
  }
77947
- function defaultRunner(cmd, args) {
77948
- const r = spawnSync9(cmd, args, { stdio: "inherit" });
78052
+ function defaultRunner2(cmd, args) {
78053
+ const r = spawnSync10(cmd, args, { stdio: "inherit" });
77949
78054
  return { status: r.status ?? 1 };
77950
78055
  }
77951
78056
  function writeMarkerInPreferredLocation(agent, reason, runner) {
@@ -78020,7 +78125,7 @@ function defaultStatusProbe(composePath) {
78020
78125
  }
78021
78126
  let serviceList = [];
78022
78127
  try {
78023
- const r = spawnSync9("docker", ["compose", "-p", "switchroom", "-f", composePath, "config", "--services"], { encoding: "utf-8", timeout: 1e4 });
78128
+ const r = spawnSync10("docker", ["compose", "-p", "switchroom", "-f", composePath, "config", "--services"], { encoding: "utf-8", timeout: 1e4 });
78024
78129
  if (r.status !== 0) {
78025
78130
  warnings.push(`docker compose config --services failed: ${r.stderr?.trim() ?? r.error?.message ?? "unknown"}`);
78026
78131
  return { cliVersion, cliBuiltAt, services, warnings };
@@ -78037,7 +78142,7 @@ function defaultStatusProbe(composePath) {
78037
78142
  let containerCreatedAt = null;
78038
78143
  let status = "<unknown>";
78039
78144
  try {
78040
- const r = spawnSync9("docker", ["inspect", "-f", "{{.Config.Image}}|{{.Created}}|{{.State.Status}}", containerName2], { encoding: "utf-8", timeout: 5000 });
78145
+ const r = spawnSync10("docker", ["inspect", "-f", "{{.Config.Image}}|{{.Created}}|{{.State.Status}}", containerName2], { encoding: "utf-8", timeout: 5000 });
78041
78146
  if (r.status === 0) {
78042
78147
  const [img, created, st] = r.stdout.trim().split("|");
78043
78148
  image = img ?? null;
@@ -78053,7 +78158,7 @@ function defaultStatusProbe(composePath) {
78053
78158
  let imagePulledAt = null;
78054
78159
  if (image) {
78055
78160
  try {
78056
- const r = spawnSync9("docker", ["image", "inspect", "-f", "{{.Id}}|{{.Created}}|{{.Metadata.LastTagTime}}", image], { encoding: "utf-8", timeout: 5000 });
78161
+ const r = spawnSync10("docker", ["image", "inspect", "-f", "{{.Id}}|{{.Created}}|{{.Metadata.LastTagTime}}", image], { encoding: "utf-8", timeout: 5000 });
78057
78162
  if (r.status === 0) {
78058
78163
  const [id, created, lastTag] = r.stdout.trim().split("|");
78059
78164
  imageDigestShort = id?.replace(/^sha256:/, "").slice(0, 12) ?? null;
@@ -78199,7 +78304,7 @@ function registerUpdateCommand(program3) {
78199
78304
 
78200
78305
  // src/cli/rollout.ts
78201
78306
  init_helpers();
78202
- import { spawnSync as spawnSync10 } from "node:child_process";
78307
+ import { spawnSync as spawnSync11 } from "node:child_process";
78203
78308
  import { readFileSync as readFileSync53, chownSync as chownSync6, statSync as statSync27 } from "node:fs";
78204
78309
  init_atomic();
78205
78310
  function normalizeVersion(v) {
@@ -78371,11 +78476,11 @@ function registerRolloutCommand(program3) {
78371
78476
  const scriptPath = process.argv[1] ?? "switchroom";
78372
78477
  const deps = {
78373
78478
  run: (args) => {
78374
- const r = spawnSync10(process.execPath, [scriptPath, ...args], { stdio: "inherit" });
78479
+ const r = spawnSync11(process.execPath, [scriptPath, ...args], { stdio: "inherit" });
78375
78480
  return { status: r.status ?? 1 };
78376
78481
  },
78377
78482
  probeVersion: (agent) => {
78378
- const r = spawnSync10("docker", ["exec", `switchroom-${agent}`, "sh", "-lc", "switchroom --version"], { encoding: "utf8" });
78483
+ const r = spawnSync11("docker", ["exec", `switchroom-${agent}`, "sh", "-lc", "switchroom --version"], { encoding: "utf8" });
78379
78484
  if (r.status !== 0)
78380
78485
  return null;
78381
78486
  return (r.stdout ?? "").trim().split(`
@@ -79874,7 +79979,7 @@ init_helpers();
79874
79979
  init_loader();
79875
79980
  import { existsSync as existsSync64 } from "node:fs";
79876
79981
  import { resolve as resolve40, sep as sep3 } from "node:path";
79877
- import { spawnSync as spawnSync11 } from "node:child_process";
79982
+ import { spawnSync as spawnSync12 } from "node:child_process";
79878
79983
 
79879
79984
  // src/agents/workspace.ts
79880
79985
  import { readFile as readFile2, stat } from "node:fs/promises";
@@ -80587,7 +80692,7 @@ function registerWorkspaceCommand(program3) {
80587
80692
  process.exit(1);
80588
80693
  }
80589
80694
  const editor = process.env["EDITOR"] ?? process.env["VISUAL"] ?? "vi";
80590
- const child = spawnSync11(editor, [target], { stdio: "inherit" });
80695
+ const child = spawnSync12(editor, [target], { stdio: "inherit" });
80591
80696
  if (child.status !== 0 && child.status !== null) {
80592
80697
  process.exit(child.status);
80593
80698
  }
@@ -80654,7 +80759,7 @@ function registerWorkspaceCommand(program3) {
80654
80759
  `);
80655
80760
  return;
80656
80761
  }
80657
- const statusResult = spawnSync11("git", ["status", "--short"], {
80762
+ const statusResult = spawnSync12("git", ["status", "--short"], {
80658
80763
  cwd: dir,
80659
80764
  encoding: "utf-8"
80660
80765
  });
@@ -80669,7 +80774,7 @@ function registerWorkspaceCommand(program3) {
80669
80774
  return;
80670
80775
  }
80671
80776
  const message = opts.message || `checkpoint: ${new Date().toISOString()}`;
80672
- const addResult = spawnSync11("git", ["add", "-A"], {
80777
+ const addResult = spawnSync12("git", ["add", "-A"], {
80673
80778
  cwd: dir,
80674
80779
  encoding: "utf-8"
80675
80780
  });
@@ -80678,7 +80783,7 @@ function registerWorkspaceCommand(program3) {
80678
80783
  `);
80679
80784
  process.exit(1);
80680
80785
  }
80681
- const commitResult = spawnSync11("git", ["commit", "-m", message], {
80786
+ const commitResult = spawnSync12("git", ["commit", "-m", message], {
80682
80787
  cwd: dir,
80683
80788
  encoding: "utf-8"
80684
80789
  });
@@ -80687,7 +80792,7 @@ function registerWorkspaceCommand(program3) {
80687
80792
  `);
80688
80793
  process.exit(1);
80689
80794
  }
80690
- const shaResult = spawnSync11("git", ["rev-parse", "--short", "HEAD"], {
80795
+ const shaResult = spawnSync12("git", ["rev-parse", "--short", "HEAD"], {
80691
80796
  cwd: dir,
80692
80797
  encoding: "utf-8"
80693
80798
  });
@@ -80708,7 +80813,7 @@ function registerWorkspaceCommand(program3) {
80708
80813
  `);
80709
80814
  return;
80710
80815
  }
80711
- const child = spawnSync11("git", ["status", "--short"], {
80816
+ const child = spawnSync12("git", ["status", "--short"], {
80712
80817
  cwd: dir,
80713
80818
  stdio: "inherit"
80714
80819
  });
@@ -85807,7 +85912,7 @@ import {
85807
85912
  } from "node:fs";
85808
85913
  import { tmpdir as tmpdir5, homedir as homedir46 } from "node:os";
85809
85914
  import { dirname as dirname24, join as join81, relative as relative2, resolve as resolve48 } from "node:path";
85810
- import { spawnSync as spawnSync12 } from "node:child_process";
85915
+ import { spawnSync as spawnSync13 } from "node:child_process";
85811
85916
 
85812
85917
  // src/cli/skill-common.ts
85813
85918
  var import_yaml23 = __toESM(require_dist(), 1);
@@ -86060,7 +86165,7 @@ function loadFromDir(dir) {
86060
86165
  function loadFromTarball(tarPath) {
86061
86166
  const isGz = tarPath.endsWith(".gz") || tarPath.endsWith(".tgz");
86062
86167
  const listFlags = isGz ? ["-tzf"] : ["-tf"];
86063
- const list2 = spawnSync12("tar", [...listFlags, tarPath], {
86168
+ const list2 = spawnSync13("tar", [...listFlags, tarPath], {
86064
86169
  encoding: "utf-8",
86065
86170
  stdio: ["ignore", "pipe", "pipe"]
86066
86171
  });
@@ -86077,7 +86182,7 @@ function loadFromTarball(tarPath) {
86077
86182
  const staging = mkdtempSync5(join81(tmpdir5(), "skill-apply-extract-"));
86078
86183
  try {
86079
86184
  const flags = isGz ? ["-xzf"] : ["-xf"];
86080
- const r = spawnSync12("tar", [
86185
+ const r = spawnSync13("tar", [
86081
86186
  ...flags,
86082
86187
  tarPath,
86083
86188
  "-C",
@@ -86152,7 +86257,7 @@ function validatePayload(name, files) {
86152
86257
  if (errors2.length === 0) {
86153
86258
  for (const [path8, content] of Object.entries(files)) {
86154
86259
  if (SH_SCRIPT_RE2.test(path8)) {
86155
- const r = spawnSync12("bash", ["-n"], {
86260
+ const r = spawnSync13("bash", ["-n"], {
86156
86261
  input: content,
86157
86262
  encoding: "utf-8"
86158
86263
  });
@@ -86164,7 +86269,7 @@ function validatePayload(name, files) {
86164
86269
  const tmpPy = join81(tmp, "check.py");
86165
86270
  try {
86166
86271
  writeFileSync40(tmpPy, content);
86167
- const r = spawnSync12("python3", ["-m", "py_compile", tmpPy], {
86272
+ const r = spawnSync13("python3", ["-m", "py_compile", tmpPy], {
86168
86273
  encoding: "utf-8"
86169
86274
  });
86170
86275
  if (r.status !== 0) {
@@ -86327,7 +86432,7 @@ function registerSkillCommand(program3) {
86327
86432
  \u2713 Wrote ${name} to ${currentDir}`));
86328
86433
  const applyBin = process.argv[1] ?? "switchroom";
86329
86434
  console.log(source_default.gray(`Running \`switchroom apply --non-interactive\`...`));
86330
- const r = spawnSync12(process.argv0, [applyBin, "apply", "--non-interactive"], { stdio: "inherit" });
86435
+ const r = spawnSync13(process.argv0, [applyBin, "apply", "--non-interactive"], { stdio: "inherit" });
86331
86436
  if (r.status !== 0) {
86332
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.)`));
86333
86438
  }
@@ -86359,7 +86464,7 @@ import {
86359
86464
  } from "node:fs";
86360
86465
  import { dirname as dirname25, join as join82, relative as relative3, resolve as resolve49 } from "node:path";
86361
86466
  import { homedir as homedir47, tmpdir as tmpdir6 } from "node:os";
86362
- import { spawnSync as spawnSync13 } from "node:child_process";
86467
+ import { spawnSync as spawnSync14 } from "node:child_process";
86363
86468
  init_helpers();
86364
86469
  init_source();
86365
86470
  var PERSONAL_PREFIX = "personal-";
@@ -86548,7 +86653,7 @@ function behavioralValidate(files) {
86548
86653
  const errors2 = [];
86549
86654
  for (const [path8, content] of Object.entries(files)) {
86550
86655
  if (SH_SCRIPT_RE.test(path8)) {
86551
- const r = spawnSync13("bash", ["-n"], { input: content, encoding: "utf-8" });
86656
+ const r = spawnSync14("bash", ["-n"], { input: content, encoding: "utf-8" });
86552
86657
  if (r.status !== 0) {
86553
86658
  errors2.push(`${path8} fails \`bash -n\`: ${(r.stderr ?? "").trim()}`);
86554
86659
  }
@@ -86557,7 +86662,7 @@ function behavioralValidate(files) {
86557
86662
  const tmpPy = join82(tmp, "check.py");
86558
86663
  try {
86559
86664
  writeFileSync41(tmpPy, content);
86560
- const r = spawnSync13("python3", ["-m", "py_compile", tmpPy], {
86665
+ const r = spawnSync14("python3", ["-m", "py_compile", tmpPy], {
86561
86666
  encoding: "utf-8"
86562
86667
  });
86563
86668
  if (r.status !== 0) {
@@ -87250,15 +87355,15 @@ init_helpers();
87250
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";
87251
87356
  import { homedir as homedir49 } from "node:os";
87252
87357
  import { join as join84 } from "node:path";
87253
- import { spawnSync as spawnSync16 } from "node:child_process";
87358
+ import { spawnSync as spawnSync17 } from "node:child_process";
87254
87359
 
87255
87360
  // src/cli/deploy-version-guard.ts
87256
- import { spawnSync as spawnSync15 } from "node:child_process";
87257
- var defaultRunner2 = (args) => {
87258
- const r = spawnSync15("docker", args, { encoding: "utf8" });
87361
+ import { spawnSync as spawnSync16 } from "node:child_process";
87362
+ var defaultRunner3 = (args) => {
87363
+ const r = spawnSync16("docker", args, { encoding: "utf8" });
87259
87364
  return { ok: r.status === 0, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
87260
87365
  };
87261
- function deployedImageTag(container, run = defaultRunner2) {
87366
+ function deployedImageTag(container, run = defaultRunner3) {
87262
87367
  const r = run(["inspect", "-f", "{{.Config.Image}}", container]);
87263
87368
  if (!r.ok)
87264
87369
  return null;
@@ -87427,7 +87532,7 @@ function backupExistingCompose() {
87427
87532
  return bak;
87428
87533
  }
87429
87534
  function runDocker(args) {
87430
- const r = spawnSync16("docker", args, { encoding: "utf8" });
87535
+ const r = spawnSync17("docker", args, { encoding: "utf8" });
87431
87536
  return {
87432
87537
  ok: r.status === 0,
87433
87538
  stdout: r.stdout ?? "",
@@ -87629,7 +87734,7 @@ init_helpers();
87629
87734
  import { existsSync as existsSync85, mkdirSync as mkdirSync49, writeFileSync as writeFileSync43, copyFileSync as copyFileSync13 } from "node:fs";
87630
87735
  import { homedir as homedir50 } from "node:os";
87631
87736
  import { join as join85 } from "node:path";
87632
- import { spawnSync as spawnSync17 } from "node:child_process";
87737
+ import { spawnSync as spawnSync18 } from "node:child_process";
87633
87738
  function resolveWebImageTag(explicitTag, release) {
87634
87739
  if (explicitTag)
87635
87740
  return explicitTag;
@@ -87728,7 +87833,7 @@ function backupExistingCompose2() {
87728
87833
  return bak;
87729
87834
  }
87730
87835
  function runDocker2(args) {
87731
- const r = spawnSync17("docker", args, { encoding: "utf8" });
87836
+ const r = spawnSync18("docker", args, { encoding: "utf8" });
87732
87837
  return {
87733
87838
  ok: r.status === 0,
87734
87839
  stdout: r.stdout ?? "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "switchroom",
3
- "version": "0.15.39",
3
+ "version": "0.15.40",
4
4
  "description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -54519,9 +54519,9 @@ function readTurnActiveMarkerAgeMs(stateDir, now) {
54519
54519
  }
54520
54520
 
54521
54521
  // ../src/build-info.ts
54522
- var VERSION = "0.15.39";
54523
- var COMMIT_SHA = "69e5a2e8";
54524
- var COMMIT_DATE = "2026-06-18T12:27:21+10:00";
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
54526
  var COMMITS_AHEAD_OF_TAG = 4;
54527
54527