switchroom 0.13.57 → 0.13.59

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.
@@ -16334,10 +16334,10 @@ __export(exports_client, {
16334
16334
  AuthBrokerClient: () => AuthBrokerClient
16335
16335
  });
16336
16336
  import * as net from "node:net";
16337
- import { existsSync as existsSync7 } from "node:fs";
16337
+ import { existsSync as existsSync6 } from "node:fs";
16338
16338
  import { homedir as homedir3 } from "node:os";
16339
16339
  import { randomUUID as randomUUID3 } from "node:crypto";
16340
- import { join as join9 } from "node:path";
16340
+ import { join as join8 } from "node:path";
16341
16341
  function reviveDate(v) {
16342
16342
  if (v == null)
16343
16343
  return null;
@@ -16347,7 +16347,7 @@ function reviveDate(v) {
16347
16347
  return Number.isNaN(d.getTime()) ? null : d;
16348
16348
  }
16349
16349
  function operatorSocketPath(home = homedir3()) {
16350
- return join9(home, ".switchroom", "state", "auth-broker-operator", "sock");
16350
+ return join8(home, ".switchroom", "state", "auth-broker-operator", "sock");
16351
16351
  }
16352
16352
  function resolveAuthBrokerSocketPath(opts) {
16353
16353
  if (opts?.socket)
@@ -16617,7 +16617,7 @@ async function withAuthBrokerClient(fn, opts) {
16617
16617
  }
16618
16618
  }
16619
16619
  function authBrokerSocketExists(opts) {
16620
- return existsSync7(resolveAuthBrokerSocketPath(opts));
16620
+ return existsSync6(resolveAuthBrokerSocketPath(opts));
16621
16621
  }
16622
16622
  var DEFAULT_TIMEOUT_MS = 5000, AuthBrokerError, AuthBrokerUnreachableError;
16623
16623
  var init_client = __esm(() => {
@@ -24109,7 +24109,7 @@ var init_schema = __esm(() => {
24109
24109
  });
24110
24110
 
24111
24111
  // ../src/config/paths.ts
24112
- import { existsSync as existsSync8 } from "node:fs";
24112
+ import { existsSync as existsSync7 } from "node:fs";
24113
24113
  import { resolve as resolve2 } from "node:path";
24114
24114
  function home() {
24115
24115
  return process.env.HOME ?? "/root";
@@ -24128,9 +24128,9 @@ function resolveDualPath(pathStr) {
24128
24128
  const absolute = resolve2(h, rest);
24129
24129
  if (rest.startsWith(`${DEFAULT_STATE_DIR}/`)) {
24130
24130
  const frag = rest.slice(DEFAULT_STATE_DIR.length + 1);
24131
- if (!existsSync8(absolute)) {
24131
+ if (!existsSync7(absolute)) {
24132
24132
  const legacy = resolve2(h, LEGACY_STATE_DIR, frag);
24133
- if (existsSync8(legacy)) {
24133
+ if (existsSync7(legacy)) {
24134
24134
  warnLegacyStateOnce(legacy);
24135
24135
  return legacy;
24136
24136
  }
@@ -24155,14 +24155,14 @@ var init_overlay_schema = __esm(() => {
24155
24155
  });
24156
24156
 
24157
24157
  // ../src/config/overlay-loader.ts
24158
- import { existsSync as existsSync9, readFileSync as readFileSync4, readdirSync, statSync as statSync2 } from "node:fs";
24158
+ import { existsSync as existsSync8, readFileSync as readFileSync4, readdirSync, statSync as statSync2 } from "node:fs";
24159
24159
  import { resolve as resolve3 } from "node:path";
24160
24160
  function overlayDirFor(agentName3, subdir) {
24161
24161
  const base = resolveDualPath(`~/.switchroom/agents/${agentName3}/${subdir}`);
24162
24162
  return resolve3(base);
24163
24163
  }
24164
24164
  function listYamlFiles(dir) {
24165
- if (!existsSync9(dir))
24165
+ if (!existsSync8(dir))
24166
24166
  return [];
24167
24167
  let entries;
24168
24168
  try {
@@ -24619,7 +24619,7 @@ function validateNotionWorkspaceConfig(config) {
24619
24619
  }
24620
24620
 
24621
24621
  // ../src/config/loader.ts
24622
- import { readFileSync as readFileSync5, existsSync as existsSync10 } from "node:fs";
24622
+ import { readFileSync as readFileSync5, existsSync as existsSync9 } from "node:fs";
24623
24623
  import { homedir as homedir5 } from "node:os";
24624
24624
  import { resolve as resolve4 } from "node:path";
24625
24625
  function formatZodErrors(error) {
@@ -24686,7 +24686,7 @@ function findConfigFile(startDir) {
24686
24686
  resolve4(userDir, "clerk.yml")
24687
24687
  ].filter(Boolean);
24688
24688
  for (const path of searchPaths) {
24689
- if (existsSync10(path)) {
24689
+ if (existsSync9(path)) {
24690
24690
  return path;
24691
24691
  }
24692
24692
  }
@@ -24694,7 +24694,7 @@ function findConfigFile(startDir) {
24694
24694
  }
24695
24695
  function loadConfig(configPath) {
24696
24696
  const filePath = configPath ?? findConfigFile();
24697
- if (!existsSync10(filePath)) {
24697
+ if (!existsSync9(filePath)) {
24698
24698
  throw new ConfigError(`Config file not found: ${filePath}`);
24699
24699
  }
24700
24700
  let raw;
@@ -24802,7 +24802,7 @@ __export(exports_history, {
24802
24802
  _resetForTests: () => _resetForTests
24803
24803
  });
24804
24804
  import { chmodSync as chmodSync2, mkdirSync as mkdirSync9 } from "fs";
24805
- import { join as join12 } from "path";
24805
+ import { join as join11 } from "path";
24806
24806
  function loadDatabaseClass() {
24807
24807
  if (DatabaseClass != null)
24808
24808
  return DatabaseClass;
@@ -24825,7 +24825,7 @@ function initHistory(stateDir, retentionDays = 30) {
24825
24825
  return;
24826
24826
  const Database = loadDatabaseClass();
24827
24827
  mkdirSync9(stateDir, { recursive: true, mode: 448 });
24828
- const path = join12(stateDir, "history.db");
24828
+ const path = join11(stateDir, "history.db");
24829
24829
  db = new Database(path, { create: true });
24830
24830
  db.exec("PRAGMA journal_mode = WAL");
24831
24831
  db.exec("PRAGMA synchronous = NORMAL");
@@ -25015,11 +25015,11 @@ var DatabaseClass = null, DEFAULT_LIMIT = 10, MAX_LIMIT = 50, db = null;
25015
25015
  var init_history = () => {};
25016
25016
 
25017
25017
  // quota-check.ts
25018
- import { readFileSync as readFileSync8, existsSync as existsSync13 } from "fs";
25019
- import { join as join13 } from "path";
25018
+ import { readFileSync as readFileSync8, existsSync as existsSync12 } from "fs";
25019
+ import { join as join12 } from "path";
25020
25020
  function readOauthToken(claudeConfigDir) {
25021
- const tokenFile = join13(claudeConfigDir, ".oauth-token");
25022
- if (!existsSync13(tokenFile))
25021
+ const tokenFile = join12(claudeConfigDir, ".oauth-token");
25022
+ if (!existsSync12(tokenFile))
25023
25023
  return null;
25024
25024
  try {
25025
25025
  const raw = readFileSync8(tokenFile, "utf-8").trim();
@@ -25501,7 +25501,7 @@ function isDockerRuntime() {
25501
25501
  import * as net3 from "node:net";
25502
25502
  import * as fs from "node:fs";
25503
25503
  import { homedir as homedir7 } from "node:os";
25504
- import { join as join17 } from "node:path";
25504
+ import { join as join16 } from "node:path";
25505
25505
  function defaultBrokerSocketPath() {
25506
25506
  if (fs.existsSync(OPERATOR_SOCKET_PATH))
25507
25507
  return OPERATOR_SOCKET_PATH;
@@ -25510,7 +25510,7 @@ function defaultBrokerSocketPath() {
25510
25510
  return LEGACY_SOCKET_PATH;
25511
25511
  }
25512
25512
  function vaultTokenFilePath(agentSlug) {
25513
- return join17(homedir7(), ".switchroom", "agents", agentSlug, ".vault-token");
25513
+ return join16(homedir7(), ".switchroom", "agents", agentSlug, ".vault-token");
25514
25514
  }
25515
25515
  function readVaultTokenFile(agentSlug) {
25516
25516
  const filePath = vaultTokenFilePath(agentSlug);
@@ -25665,8 +25665,8 @@ var DEFAULT_TIMEOUT_MS3 = 2000, LEGACY_SOCKET_PATH, OPERATOR_SOCKET_PATH;
25665
25665
  var init_client2 = __esm(() => {
25666
25666
  init_protocol2();
25667
25667
  init_peercred();
25668
- LEGACY_SOCKET_PATH = join17(homedir7(), ".switchroom", "vault-broker.sock");
25669
- OPERATOR_SOCKET_PATH = join17(homedir7(), ".switchroom", "broker-operator", "sock");
25668
+ LEGACY_SOCKET_PATH = join16(homedir7(), ".switchroom", "vault-broker.sock");
25669
+ OPERATOR_SOCKET_PATH = join16(homedir7(), ".switchroom", "broker-operator", "sock");
25670
25670
  });
25671
25671
 
25672
25672
  // ../src/drive/deep-links.ts
@@ -27779,15 +27779,15 @@ var init_secretlint_source = __esm(() => {
27779
27779
  });
27780
27780
 
27781
27781
  // card-format.ts
27782
- function escapeHtml9(s) {
27782
+ function escapeHtml8(s) {
27783
27783
  return s.replace(/[&<>]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;" })[c]);
27784
27784
  }
27785
- function truncate6(s, n) {
27785
+ function truncate5(s, n) {
27786
27786
  return s.length > n ? s.slice(0, n - 1) + "\u2026" : s;
27787
27787
  }
27788
27788
 
27789
27789
  // gateway/auth-line.ts
27790
- function escapeHtml10(s) {
27790
+ function escapeHtml9(s) {
27791
27791
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
27792
27792
  }
27793
27793
  function formatRelativeMs2(ms) {
@@ -27847,7 +27847,7 @@ function renderAuthLine(state4, agentName3, now = Date.now()) {
27847
27847
  if (!acc)
27848
27848
  continue;
27849
27849
  const marker = label === activeLabel ? "\u25b6" : "\u21b3";
27850
- const labelHtml = `<code>${escapeHtml10(acc.label)}</code>`;
27850
+ const labelHtml = `<code>${escapeHtml9(acc.label)}</code>`;
27851
27851
  const quotaLine = formatAuthQuotaLine(acc, now);
27852
27852
  rows.push(quotaLine ? `${marker} ${labelHtml} ${quotaLine}` : `${marker} ${labelHtml}`);
27853
27853
  }
@@ -27855,15 +27855,15 @@ function renderAuthLine(state4, agentName3, now = Date.now()) {
27855
27855
  }
27856
27856
 
27857
27857
  // gateway/quota-cache.ts
27858
- import { existsSync as existsSync24, readFileSync as readFileSync22, writeFileSync as writeFileSync13, mkdirSync as mkdirSync11 } from "fs";
27859
- import { join as join21, dirname as dirname8 } from "path";
27858
+ import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync13, mkdirSync as mkdirSync11 } from "fs";
27859
+ import { join as join20, dirname as dirname8 } from "path";
27860
27860
  function defaultCachePath() {
27861
- return process.env.SWITCHROOM_QUOTA_CACHE_PATH ?? join21(process.env.HOME ?? "/tmp", ".switchroom", "quota-cache.json");
27861
+ return process.env.SWITCHROOM_QUOTA_CACHE_PATH ?? join20(process.env.HOME ?? "/tmp", ".switchroom", "quota-cache.json");
27862
27862
  }
27863
27863
  function readQuotaCache(opts = {}) {
27864
27864
  const path = opts.path ?? defaultCachePath();
27865
27865
  const now = opts.now ?? Date.now();
27866
- if (!existsSync24(path))
27866
+ if (!existsSync23(path))
27867
27867
  return null;
27868
27868
  let entry;
27869
27869
  try {
@@ -27904,8 +27904,8 @@ var init_quota_cache = __esm(() => {
27904
27904
  });
27905
27905
 
27906
27906
  // gateway/boot-probes.ts
27907
- import { readFileSync as readFileSync23, readdirSync as readdirSync4, existsSync as existsSync25 } from "fs";
27908
- import { join as join22 } from "path";
27907
+ import { readFileSync as readFileSync23, readdirSync as readdirSync4, existsSync as existsSync24 } from "fs";
27908
+ import { join as join21 } from "path";
27909
27909
  import { execFile as execFileCb } from "child_process";
27910
27910
  import { promisify as promisify3 } from "util";
27911
27911
  async function withTimeout(label, p, timeoutMs = PROBE_TIMEOUT_MS) {
@@ -27947,8 +27947,8 @@ function mapPlan(billingType, hasExtra) {
27947
27947
  }
27948
27948
  async function probeAccount(agentDir) {
27949
27949
  return withTimeout("Account", (async () => {
27950
- const claudeDir = join22(agentDir, ".claude");
27951
- const claudeJsonPath = join22(claudeDir, ".claude.json");
27950
+ const claudeDir = join21(agentDir, ".claude");
27951
+ const claudeJsonPath = join21(claudeDir, ".claude.json");
27952
27952
  let cfg = {};
27953
27953
  try {
27954
27954
  const raw = readFileSync23(claudeJsonPath, "utf8");
@@ -27969,10 +27969,10 @@ async function probeAccount(agentDir) {
27969
27969
  let tokenStr = "";
27970
27970
  let status = "ok";
27971
27971
  for (const candidate of [
27972
- join22(claudeDir, ".oauth-token.meta.json"),
27973
- join22(claudeDir, "accounts", "default", ".oauth-token.meta.json")
27972
+ join21(claudeDir, ".oauth-token.meta.json"),
27973
+ join21(claudeDir, "accounts", "default", ".oauth-token.meta.json")
27974
27974
  ]) {
27975
- if (existsSync25(candidate)) {
27975
+ if (existsSync24(candidate)) {
27976
27976
  try {
27977
27977
  const meta = JSON.parse(readFileSync23(candidate, "utf8"));
27978
27978
  if (meta.expiresAt) {
@@ -28149,7 +28149,7 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
28149
28149
  if (!cgroup)
28150
28150
  return null;
28151
28151
  const procsPath = `/sys/fs/cgroup${cgroup}/cgroup.procs`;
28152
- if (!existsSync25(procsPath))
28152
+ if (!existsSync24(procsPath))
28153
28153
  return null;
28154
28154
  const pidsRaw = readFileSync23(procsPath, "utf-8");
28155
28155
  const pids = pidsRaw.split(`
@@ -28356,9 +28356,9 @@ async function probeQuota(claudeConfigDir, _agentDir, fetchImpl = fetch, opts =
28356
28356
  let claudeDirForProbe = null;
28357
28357
  for (const candidate of [
28358
28358
  claudeConfigDir,
28359
- join22(claudeConfigDir, "accounts", "default")
28359
+ join21(claudeConfigDir, "accounts", "default")
28360
28360
  ]) {
28361
- if (existsSync25(join22(candidate, ".oauth-token"))) {
28361
+ if (existsSync24(join21(candidate, ".oauth-token"))) {
28362
28362
  claudeDirForProbe = candidate;
28363
28363
  break;
28364
28364
  }
@@ -28529,7 +28529,7 @@ async function probeUds(label, socketPath, opts = {}) {
28529
28529
  }
28530
28530
  return withTimeout(label, (async () => {
28531
28531
  if (!opts.connectImpl) {
28532
- if (!existsSync25(socketPath)) {
28532
+ if (!existsSync24(socketPath)) {
28533
28533
  return {
28534
28534
  status: "fail",
28535
28535
  label,
@@ -28593,7 +28593,7 @@ async function probeSkills(agentDir, opts = {}) {
28593
28593
  return withTimeout("Skills", (async () => {
28594
28594
  const fs2 = opts.fs ?? realSkillsFs;
28595
28595
  const max = opts.maxNamesShown ?? 3;
28596
- const skillsDir = join22(agentDir, ".claude", "skills");
28596
+ const skillsDir = join21(agentDir, ".claude", "skills");
28597
28597
  if (!fs2.exists(skillsDir)) {
28598
28598
  return { status: "ok", label: "Skills", detail: "no skills dir" };
28599
28599
  }
@@ -28608,17 +28608,17 @@ async function probeSkills(agentDir, opts = {}) {
28608
28608
  }
28609
28609
  const dangling = [];
28610
28610
  for (const name of entries) {
28611
- const skillPath = join22(skillsDir, name);
28611
+ const skillPath = join21(skillsDir, name);
28612
28612
  if (!fs2.exists(skillPath)) {
28613
28613
  dangling.push(name);
28614
28614
  continue;
28615
28615
  }
28616
- const skillMd = join22(skillPath, "SKILL.md");
28616
+ const skillMd = join21(skillPath, "SKILL.md");
28617
28617
  if (!fs2.exists(skillMd) && !fs2.exists(skillPath + ".md")) {
28618
28618
  continue;
28619
28619
  }
28620
28620
  }
28621
- const overlayDir = opts.overlaySkillsDir ?? join22(agentDir, "skills.d");
28621
+ const overlayDir = opts.overlaySkillsDir ?? join21(agentDir, "skills.d");
28622
28622
  const overlaySlugs = new Set;
28623
28623
  if (fs2.exists(overlayDir)) {
28624
28624
  let overlayEntries = [];
@@ -28673,16 +28673,16 @@ var init_boot_probes = __esm(() => {
28673
28673
  const { statSync: statSync7 } = __require("fs");
28674
28674
  return statSync7(p).mtimeMs;
28675
28675
  },
28676
- exists: (p) => existsSync25(p)
28676
+ exists: (p) => existsSync24(p)
28677
28677
  };
28678
28678
  realSkillsFs = {
28679
28679
  readdir: (p) => readdirSync4(p),
28680
- exists: (p) => existsSync25(p)
28680
+ exists: (p) => existsSync24(p)
28681
28681
  };
28682
28682
  });
28683
28683
 
28684
28684
  // gateway/boot-issue-cache.ts
28685
- import { existsSync as existsSync26, readFileSync as readFileSync24, writeFileSync as writeFileSync14, mkdirSync as mkdirSync12, renameSync as renameSync9 } from "fs";
28685
+ import { existsSync as existsSync25, readFileSync as readFileSync24, writeFileSync as writeFileSync14, mkdirSync as mkdirSync12, renameSync as renameSync9 } from "fs";
28686
28686
  import { dirname as dirname9 } from "path";
28687
28687
  function fingerprintProbe(key, r) {
28688
28688
  if (r.status === "ok")
@@ -28762,7 +28762,7 @@ function diffProbes(probes, cache, opts = {}) {
28762
28762
  return out;
28763
28763
  }
28764
28764
  function loadCache(path, now = Date.now) {
28765
- if (!existsSync26(path))
28765
+ if (!existsSync25(path))
28766
28766
  return { ...EMPTY_CACHE, probes: {} };
28767
28767
  let raw;
28768
28768
  try {
@@ -28833,7 +28833,7 @@ __export(exports_boot_card, {
28833
28833
  renderBootCard: () => renderBootCard,
28834
28834
  renderAccountRows: () => renderAuthLine
28835
28835
  });
28836
- import { join as join23 } from "path";
28836
+ import { join as join22 } from "path";
28837
28837
  function resolvePersonaName(slug, loadConfig3) {
28838
28838
  try {
28839
28839
  const config = loadConfig3 ? loadConfig3() : loadConfig();
@@ -28858,14 +28858,14 @@ function shouldSkipDuplicateBootCard(gate, site) {
28858
28858
  function renderNextStep(text) {
28859
28859
  const parts = text.split("`");
28860
28860
  if (parts.length % 2 === 0)
28861
- return escapeHtml9(text);
28862
- return parts.map((p, i) => i % 2 === 0 ? escapeHtml9(p) : `<code>${escapeHtml9(p)}</code>`).join("");
28861
+ return escapeHtml8(text);
28862
+ return parts.map((p, i) => i % 2 === 0 ? escapeHtml8(p) : `<code>${escapeHtml8(p)}</code>`).join("");
28863
28863
  }
28864
28864
  function renderBootCard(opts) {
28865
28865
  const { agentName: agentName3, version: version2, probes, restartReason, restartAgeMs } = opts;
28866
28866
  const agentSlug = opts.agentSlug ?? agentName3;
28867
28867
  const ackEmoji = restartReason ? REASON_EMOJI[restartReason] : "\u2705";
28868
- const ack = `${ackEmoji} <b>${escapeHtml9(agentName3)}</b> back up \u00b7 ${escapeHtml9(version2)}`;
28868
+ const ack = `${ackEmoji} <b>${escapeHtml8(agentName3)}</b> back up \u00b7 ${escapeHtml8(version2)}`;
28869
28869
  const degradedRows = [];
28870
28870
  const snoozeSet = new Set(opts.snoozeRows ?? []);
28871
28871
  if (opts.resolvedRows && opts.resolvedRows.length > 0) {
@@ -28873,13 +28873,13 @@ function renderBootCard(opts) {
28873
28873
  const lbl = PROBE_LABELS[key];
28874
28874
  if (!lbl)
28875
28875
  continue;
28876
- degradedRows.push(`\u2705 <b>${escapeHtml9(lbl)}</b> resolved`);
28876
+ degradedRows.push(`\u2705 <b>${escapeHtml8(lbl)}</b> resolved`);
28877
28877
  }
28878
28878
  }
28879
28879
  if (restartReason === "crash") {
28880
28880
  const ageStr = restartAgeMs != null && restartAgeMs > 0 ? ` \u00b7 ${(restartAgeMs / 1000).toFixed(1)}s ago` : "";
28881
- degradedRows.push(`\u26a0\ufe0f <b>Restart</b> ${escapeHtml9(REASON_LABEL.crash)}${ageStr}`);
28882
- const tailCmd = process.env.SWITCHROOM_RUNTIME === "docker" ? `docker logs --tail 100 switchroom-${escapeHtml9(agentSlug)}` : `journalctl --user -u switchroom-${escapeHtml9(agentSlug)} -n 100`;
28881
+ degradedRows.push(`\u26a0\ufe0f <b>Restart</b> ${escapeHtml8(REASON_LABEL.crash)}${ageStr}`);
28882
+ const tailCmd = process.env.SWITCHROOM_RUNTIME === "docker" ? `docker logs --tail 100 switchroom-${escapeHtml8(agentSlug)}` : `journalctl --user -u switchroom-${escapeHtml8(agentSlug)} -n 100`;
28883
28883
  degradedRows.push(` \u21b3 Tail logs: <code>${tailCmd}</code>`);
28884
28884
  }
28885
28885
  if (probes) {
@@ -28892,7 +28892,7 @@ function renderBootCard(opts) {
28892
28892
  if (snoozeSet.has(key))
28893
28893
  continue;
28894
28894
  const dot = DOT[r.status] ?? DOT.fail;
28895
- degradedRows.push(`${dot} <b>${PROBE_LABELS[key]}</b> ${escapeHtml9(r.detail)}`);
28895
+ degradedRows.push(`${dot} <b>${PROBE_LABELS[key]}</b> ${escapeHtml8(r.detail)}`);
28896
28896
  if (r.nextStep) {
28897
28897
  degradedRows.push(` \u21b3 ${renderNextStep(r.nextStep)}`);
28898
28898
  }
@@ -28914,7 +28914,7 @@ function renderBootCard(opts) {
28914
28914
  `);
28915
28915
  }
28916
28916
  async function runAllProbes(opts) {
28917
- const claudeDir = join23(opts.agentDir, ".claude");
28917
+ const claudeDir = join22(opts.agentDir, ".claude");
28918
28918
  const probes = {};
28919
28919
  const slug = opts.agentSlug ?? opts.agentName;
28920
28920
  await Promise.allSettled([
@@ -29158,10 +29158,10 @@ import { randomBytes as randomBytes5, scryptSync, createCipheriv, createDecipher
29158
29158
  import {
29159
29159
  readFileSync as readFileSync31,
29160
29160
  writeFileSync as writeFileSync19,
29161
- existsSync as existsSync33,
29161
+ existsSync as existsSync32,
29162
29162
  renameSync as renameSync11,
29163
29163
  mkdirSync as mkdirSync18,
29164
- unlinkSync as unlinkSync13,
29164
+ unlinkSync as unlinkSync12,
29165
29165
  lstatSync,
29166
29166
  realpathSync
29167
29167
  } from "node:fs";
@@ -29196,7 +29196,7 @@ function normalizeSecrets(raw) {
29196
29196
  return out;
29197
29197
  }
29198
29198
  function openVault(passphrase, vaultPath) {
29199
- if (!existsSync33(vaultPath)) {
29199
+ if (!existsSync32(vaultPath)) {
29200
29200
  throw new VaultError(`Vault file not found: ${vaultPath}`);
29201
29201
  }
29202
29202
  let vaultFile;
@@ -29247,15 +29247,15 @@ var init_vault = __esm(() => {
29247
29247
  // ../src/vault/resolver.ts
29248
29248
  import {
29249
29249
  chmodSync as chmodSync4,
29250
- closeSync as closeSync8,
29250
+ closeSync as closeSync7,
29251
29251
  mkdirSync as mkdirSync19,
29252
29252
  mkdtempSync as mkdtempSync2,
29253
- openSync as openSync8,
29253
+ openSync as openSync7,
29254
29254
  rmSync as rmSync3,
29255
29255
  statSync as statSync11,
29256
29256
  writeSync as writeSync2
29257
29257
  } from "node:fs";
29258
- import { join as join32 } from "node:path";
29258
+ import { join as join31 } from "node:path";
29259
29259
  import { tmpdir } from "node:os";
29260
29260
  import { constants as fsConstants } from "node:fs";
29261
29261
  function isVaultReference(value) {
@@ -29307,26 +29307,26 @@ function materializationRoot() {
29307
29307
  return cachedRoot;
29308
29308
  const xdg = process.env.XDG_RUNTIME_DIR;
29309
29309
  if (xdg) {
29310
- const base = join32(xdg, "switchroom", "vault");
29310
+ const base = join31(xdg, "switchroom", "vault");
29311
29311
  mkdirSync19(base, { recursive: true, mode: 448 });
29312
- cachedRoot = mkdtempSync2(join32(base, "run-"));
29312
+ cachedRoot = mkdtempSync2(join31(base, "run-"));
29313
29313
  } else {
29314
- cachedRoot = mkdtempSync2(join32(tmpdir(), "switchroom-vault-"));
29314
+ cachedRoot = mkdtempSync2(join31(tmpdir(), "switchroom-vault-"));
29315
29315
  }
29316
29316
  chmodSync4(cachedRoot, 448);
29317
29317
  return cachedRoot;
29318
29318
  }
29319
29319
  function writeFileExclusive(filePath, content) {
29320
29320
  const buf = typeof content === "string" ? Buffer.from(content, "utf8") : content;
29321
- const fd = openSync8(filePath, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL, 384);
29321
+ const fd = openSync7(filePath, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL, 384);
29322
29322
  try {
29323
29323
  writeSync2(fd, buf);
29324
29324
  } finally {
29325
- closeSync8(fd);
29325
+ closeSync7(fd);
29326
29326
  }
29327
29327
  }
29328
29328
  function materializeFilesEntry(key, files) {
29329
- const dir = join32(materializationRoot(), key);
29329
+ const dir = join31(materializationRoot(), key);
29330
29330
  if (materializedDirs.has(dir)) {
29331
29331
  try {
29332
29332
  rmSync3(dir, { recursive: true, force: true });
@@ -29342,7 +29342,7 @@ function materializeFilesEntry(key, files) {
29342
29342
  if (filename.includes("/") || filename.includes("\\") || filename === ".." || filename === "." || filename.includes("\x00")) {
29343
29343
  throw new Error(`Refusing to materialize vault file with unsafe name: ${filename}`);
29344
29344
  }
29345
- const filePath = join32(dir, filename);
29345
+ const filePath = join31(dir, filename);
29346
29346
  const content = encoding === "base64" ? Buffer.from(value, "base64") : value;
29347
29347
  writeFileExclusive(filePath, content);
29348
29348
  }
@@ -29475,7 +29475,7 @@ __export(exports_materialize_bot_token, {
29475
29475
  materializeBotToken: () => materializeBotToken,
29476
29476
  BotTokenMaterializeError: () => BotTokenMaterializeError
29477
29477
  });
29478
- import { existsSync as existsSync34 } from "node:fs";
29478
+ import { existsSync as existsSync33 } from "node:fs";
29479
29479
  function pickConfiguredToken(config, agentName3) {
29480
29480
  if (agentName3) {
29481
29481
  const agent = config.agents?.[agentName3];
@@ -29489,7 +29489,7 @@ function tryDirectVaultRead(ref, config, passphrase) {
29489
29489
  if (!passphrase)
29490
29490
  return null;
29491
29491
  const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
29492
- if (!existsSync34(vaultPath))
29492
+ if (!existsSync33(vaultPath))
29493
29493
  return null;
29494
29494
  try {
29495
29495
  const secrets = openVault(passphrase, vaultPath);
@@ -29607,7 +29607,7 @@ function truncateDiffForCard(unifiedDiff, maxLines = 50, maxChars = 3000) {
29607
29607
  }
29608
29608
  return out === unifiedDiff ? out : out + sentinel;
29609
29609
  }
29610
- function escapeHtml12(s) {
29610
+ function escapeHtml11(s) {
29611
29611
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
29612
29612
  }
29613
29613
  function clipReason(reason) {
@@ -29618,10 +29618,10 @@ function clipReason(reason) {
29618
29618
  function buildConfigApprovalCardBody(args) {
29619
29619
  const safeReason = clipReason(args.reason);
29620
29620
  const render = (diff) => `\uD83D\uDEE0 <b>Config edit proposed</b>
29621
- ` + `Agent: <code>${escapeHtml12(args.agentName)}</code>
29622
- ` + `Reason: ${escapeHtml12(safeReason)}
29621
+ ` + `Agent: <code>${escapeHtml11(args.agentName)}</code>
29622
+ ` + `Reason: ${escapeHtml11(safeReason)}
29623
29623
 
29624
- ` + `<pre>${escapeHtml12(diff)}</pre>`;
29624
+ ` + `<pre>${escapeHtml11(diff)}</pre>`;
29625
29625
  return truncateRawToFit({
29626
29626
  raw: args.unifiedDiff,
29627
29627
  render,
@@ -29728,8 +29728,8 @@ async function handleRequestConfigFinalize(_client, msg, deps) {
29728
29728
  }
29729
29729
  pending.delete(msg.requestId);
29730
29730
  const body = msg.outcome === "applied" ? `\u2705 <b>Applied</b>${msg.detail ? `
29731
- ${escapeHtml12(msg.detail)}` : ""}` : `\u26a0\ufe0f <b>Reconcile failed; rolled back</b>${msg.detail ? `
29732
- ${escapeHtml12(msg.detail)}` : ""}`;
29731
+ ${escapeHtml11(msg.detail)}` : ""}` : `\u26a0\ufe0f <b>Reconcile failed; rolled back</b>${msg.detail ? `
29732
+ ${escapeHtml11(msg.detail)}` : ""}`;
29733
29733
  try {
29734
29734
  await deps.editCard({
29735
29735
  chatId: entry.chatId,
@@ -29794,7 +29794,7 @@ __export(exports_tmux, {
29794
29794
  captureAgentPane: () => captureAgentPane
29795
29795
  });
29796
29796
  import { execFileSync as execFileSync4 } from "node:child_process";
29797
- import { mkdirSync as mkdirSync20, readdirSync as readdirSync6, statSync as statSync12, unlinkSync as unlinkSync14, writeFileSync as writeFileSync20 } from "node:fs";
29797
+ import { mkdirSync as mkdirSync20, readdirSync as readdirSync6, statSync as statSync12, unlinkSync as unlinkSync13, writeFileSync as writeFileSync20 } from "node:fs";
29798
29798
  import { resolve as resolve7 } from "node:path";
29799
29799
  function captureAgentPane(opts) {
29800
29800
  const { agentName: agentName3, agentDir, reason } = opts;
@@ -29908,7 +29908,7 @@ function pruneOldReports(dir, retain) {
29908
29908
  }).sort((a, b) => b.mtimeMs - a.mtimeMs);
29909
29909
  for (const stale of files.slice(retain)) {
29910
29910
  try {
29911
- unlinkSync14(stale.full);
29911
+ unlinkSync13(stale.full);
29912
29912
  } catch {}
29913
29913
  }
29914
29914
  }
@@ -29999,17 +29999,17 @@ function registerApprovalsCommands(bot, opts) {
29999
29999
  return;
30000
30000
  }
30001
30001
  if (decisions.length === 0) {
30002
- await ctx.reply(agentFilter ? `No active approvals for <code>${escapeHtml13(agentFilter)}</code>.` : "No active approvals.", { parse_mode: "HTML" });
30002
+ await ctx.reply(agentFilter ? `No active approvals for <code>${escapeHtml12(agentFilter)}</code>.` : "No active approvals.", { parse_mode: "HTML" });
30003
30003
  return;
30004
30004
  }
30005
30005
  const byAgent = new Map;
30006
30006
  for (const d of decisions)
30007
30007
  byAgent.set(d.agent_unit, (byAgent.get(d.agent_unit) ?? 0) + 1);
30008
- const summary = Array.from(byAgent.entries()).map(([a, n]) => `\u2022 <b>${escapeHtml13(a)}</b>: ${n}`).join(`
30008
+ const summary = Array.from(byAgent.entries()).map(([a, n]) => `\u2022 <b>${escapeHtml12(a)}</b>: ${n}`).join(`
30009
30009
  `);
30010
30010
  const detail = decisions.slice(0, 20).map((d) => {
30011
30011
  const ttl = d.ttl_expires_at === null ? "always" : `until ${new Date(d.ttl_expires_at).toISOString().slice(0, 16).replace("T", " ")}`;
30012
- return `<code>${escapeHtml13(d.id.slice(0, 8))}</code> ` + `${escapeHtml13(d.agent_unit)} \u2192 ` + `<code>${escapeHtml13(d.scope)}</code> ` + `(${escapeHtml13(d.action)}, ${ttl}) ` + `\u00b7 /approvals revoke ${escapeHtml13(d.id)}`;
30012
+ return `<code>${escapeHtml12(d.id.slice(0, 8))}</code> ` + `${escapeHtml12(d.agent_unit)} \u2192 ` + `<code>${escapeHtml12(d.scope)}</code> ` + `(${escapeHtml12(d.action)}, ${ttl}) ` + `\u00b7 /approvals revoke ${escapeHtml12(d.id)}`;
30013
30013
  }).join(`
30014
30014
  `);
30015
30015
  await ctx.reply(`<b>Active approvals</b>
@@ -30035,13 +30035,13 @@ ${detail}`, {
30035
30035
  await ctx.reply("Approval kernel unreachable.");
30036
30036
  return;
30037
30037
  }
30038
- await ctx.reply(ok ? `Revoked <code>${escapeHtml13(id)}</code>.` : `No such active decision <code>${escapeHtml13(id)}</code>.`, { parse_mode: "HTML" });
30038
+ await ctx.reply(ok ? `Revoked <code>${escapeHtml12(id)}</code>.` : `No such active decision <code>${escapeHtml12(id)}</code>.`, { parse_mode: "HTML" });
30039
30039
  return;
30040
30040
  }
30041
- await ctx.reply(`Unknown subcommand <code>${escapeHtml13(sub)}</code>. ` + `Use <code>/approvals list</code> or <code>/approvals revoke &lt;id&gt;</code>. ` + `(<code>add</code> and <code>stats</code> are coming in a follow-up.)`, { parse_mode: "HTML" });
30041
+ await ctx.reply(`Unknown subcommand <code>${escapeHtml12(sub)}</code>. ` + `Use <code>/approvals list</code> or <code>/approvals revoke &lt;id&gt;</code>. ` + `(<code>add</code> and <code>stats</code> are coming in a follow-up.)`, { parse_mode: "HTML" });
30042
30042
  });
30043
30043
  }
30044
- function escapeHtml13(s) {
30044
+ function escapeHtml12(s) {
30045
30045
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
30046
30046
  }
30047
30047
  var init_approvals_commands = __esm(() => {
@@ -30123,16 +30123,16 @@ function renderAccountRow2(snap, opts) {
30123
30123
  const lines = [];
30124
30124
  const marker = snap.isActive ? "\u25cf " : "";
30125
30125
  if (!snap.quota) {
30126
- lines.push(`${marker}<code>${escapeHtml14(snap.label)}</code> <i>quota probe failed</i>`);
30126
+ lines.push(`${marker}<code>${escapeHtml13(snap.label)}</code> <i>quota probe failed</i>`);
30127
30127
  if (snap.quotaError) {
30128
- lines.push(` <i>${escapeHtml14(snap.quotaError)}</i>`);
30128
+ lines.push(` <i>${escapeHtml13(snap.quotaError)}</i>`);
30129
30129
  }
30130
30130
  return lines;
30131
30131
  }
30132
30132
  const q = snap.quota;
30133
30133
  const fiveStr = fmtPct2(q.fiveHourUtilizationPct);
30134
30134
  const sevenStr = fmtPct2(q.sevenDayUtilizationPct);
30135
- lines.push(`${marker}<code>${escapeHtml14(snap.label)}</code> ${fiveStr} / ${sevenStr}`);
30135
+ lines.push(`${marker}<code>${escapeHtml13(snap.label)}</code> ${fiveStr} / ${sevenStr}`);
30136
30136
  const health = classifyHealth2(snap);
30137
30137
  if (health === "blocked") {
30138
30138
  const win = bindingWindow2(q);
@@ -30238,13 +30238,13 @@ function renderFallbackAnnouncement2(input) {
30238
30238
  const limitWord = input.oldQuota ? limitWordFor2(input.oldQuota) : "quota";
30239
30239
  const headerLimit = limitWord === "quota" ? "quota cap" : `${limitWord} limit`;
30240
30240
  if (!input.newLabel) {
30241
- lines.push(`\uD83D\uDD34 <b>All accounts blocked \u00b7 ${headerLimit} on ${escapeHtml14(input.oldLabel)}</b>`);
30241
+ lines.push(`\uD83D\uDD34 <b>All accounts blocked \u00b7 ${headerLimit} on ${escapeHtml13(input.oldLabel)}</b>`);
30242
30242
  lines.push("");
30243
- lines.push(`Triggered by: agent <b>${escapeHtml14(input.triggerAgent)}</b>`);
30243
+ lines.push(`Triggered by: agent <b>${escapeHtml13(input.triggerAgent)}</b>`);
30244
30244
  if (input.oldQuota) {
30245
30245
  const recovery = recoveryAtFor2(input.oldQuota);
30246
30246
  if (recovery) {
30247
- lines.push(`${escapeHtml14(input.oldLabel)} recovers ${formatAbsolute2(recovery, tz)} ` + `(in ${formatRelative2(recovery, now)})`);
30247
+ lines.push(`${escapeHtml13(input.oldLabel)} recovers ${formatAbsolute2(recovery, tz)} ` + `(in ${formatRelative2(recovery, now)})`);
30248
30248
  }
30249
30249
  }
30250
30250
  lines.push("");
@@ -30252,15 +30252,15 @@ function renderFallbackAnnouncement2(input) {
30252
30252
  return lines.join(`
30253
30253
  `);
30254
30254
  }
30255
- lines.push(`\u2713 <b>Switched fleet \u00b7 ${headerLimit} on ${escapeHtml14(input.oldLabel)}</b>`);
30255
+ lines.push(`\u2713 <b>Switched fleet \u00b7 ${headerLimit} on ${escapeHtml13(input.oldLabel)}</b>`);
30256
30256
  lines.push("");
30257
- lines.push(`<code>${escapeHtml14(input.oldLabel)}</code> \u2192 <code>${escapeHtml14(input.newLabel)}</code>`);
30258
- lines.push(`Triggered by: agent <b>${escapeHtml14(input.triggerAgent)}</b>`);
30257
+ lines.push(`<code>${escapeHtml13(input.oldLabel)}</code> \u2192 <code>${escapeHtml13(input.newLabel)}</code>`);
30258
+ lines.push(`Triggered by: agent <b>${escapeHtml13(input.triggerAgent)}</b>`);
30259
30259
  lines.push("");
30260
30260
  if (input.oldQuota) {
30261
30261
  const recovery = recoveryAtFor2(input.oldQuota);
30262
30262
  if (recovery) {
30263
- lines.push(`<code>${escapeHtml14(input.oldLabel)}</code> recovers ` + `${formatAbsolute2(recovery, tz)} (in ${formatRelative2(recovery, now)})`);
30263
+ lines.push(`<code>${escapeHtml13(input.oldLabel)}</code> recovers ` + `${formatAbsolute2(recovery, tz)} (in ${formatRelative2(recovery, now)})`);
30264
30264
  }
30265
30265
  }
30266
30266
  if (input.newQuota) {
@@ -30268,7 +30268,7 @@ function renderFallbackAnnouncement2(input) {
30268
30268
  const sevenStr = fmtPct2(input.newQuota.sevenDayUtilizationPct);
30269
30269
  const hasHeadroom = input.newQuota.fiveHourUtilizationPct < THROTTLING_THRESHOLD_PCT2 && input.newQuota.sevenDayUtilizationPct < THROTTLING_THRESHOLD_PCT2;
30270
30270
  const headroomStr = hasHeadroom ? "<i>(plenty of headroom)</i>" : "<i>(near limit \u2014 watch this)</i>";
30271
- lines.push(`<code>${escapeHtml14(input.newLabel)}</code> now: ${fiveStr} of 5h \u00b7 ${sevenStr} of 7d ${headroomStr}`);
30271
+ lines.push(`<code>${escapeHtml13(input.newLabel)}</code> now: ${fiveStr} of 5h \u00b7 ${sevenStr} of 7d ${headroomStr}`);
30272
30272
  } else {
30273
30273
  lines.push(`<i>(quota probe for new account is pending \u2014 will reflect on next /auth)</i>`);
30274
30274
  }
@@ -30327,7 +30327,7 @@ function switchPriority2(s) {
30327
30327
  return 2;
30328
30328
  return 3;
30329
30329
  }
30330
- function escapeHtml14(s) {
30330
+ function escapeHtml13(s) {
30331
30331
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
30332
30332
  }
30333
30333
  function buildSnapshotsFromState2(state4, quotas) {
@@ -30504,14 +30504,14 @@ import {
30504
30504
  renameSync as renameSync12,
30505
30505
  realpathSync as realpathSync2,
30506
30506
  chmodSync as chmodSync5,
30507
- openSync as openSync9,
30508
- closeSync as closeSync9,
30509
- existsSync as existsSync35,
30510
- unlinkSync as unlinkSync15,
30507
+ openSync as openSync8,
30508
+ closeSync as closeSync8,
30509
+ existsSync as existsSync34,
30510
+ unlinkSync as unlinkSync14,
30511
30511
  appendFileSync as appendFileSync3
30512
30512
  } from "fs";
30513
30513
  import { homedir as homedir12 } from "os";
30514
- import { join as join33, extname, sep as sep3, basename as basename8 } from "path";
30514
+ import { join as join32, extname, sep as sep3, basename as basename7 } from "path";
30515
30515
 
30516
30516
  // plugin-logger.ts
30517
30517
  import { appendFileSync, mkdirSync, renameSync, statSync, existsSync } from "fs";
@@ -31559,6 +31559,109 @@ function isTelegramSurfaceTool(toolName) {
31559
31559
  return suffix === "reply" || suffix === "stream_reply" || suffix === "edit_message" || suffix === "react";
31560
31560
  }
31561
31561
 
31562
+ // draft-transport.ts
31563
+ var DRAFT_STREAM_STATE_KEY = Symbol.for("switchroom.draftStreamState");
31564
+ function getDraftStreamState() {
31565
+ const g = globalThis;
31566
+ let state = g[DRAFT_STREAM_STATE_KEY];
31567
+ if (!state) {
31568
+ state = { nextDraftId: 0 };
31569
+ g[DRAFT_STREAM_STATE_KEY] = state;
31570
+ }
31571
+ return state;
31572
+ }
31573
+ function allocateDraftId() {
31574
+ const state = getDraftStreamState();
31575
+ state.nextDraftId = state.nextDraftId >= 2147483647 ? 1 : state.nextDraftId + 1;
31576
+ return state.nextDraftId;
31577
+ }
31578
+
31579
+ // tool-activity-summary.ts
31580
+ var READ_VERBS = new Set(["read"]);
31581
+ var WRITE_VERBS = new Set(["wrote", "created", "edited"]);
31582
+ function makeEmptyActivityState() {
31583
+ return { counts: {}, order: [], firstToolName: null };
31584
+ }
31585
+ function verbForTool(toolName) {
31586
+ if (!toolName)
31587
+ return null;
31588
+ const mcpMatch = /^mcp__([^_]+)__(.+)$/.exec(toolName);
31589
+ if (mcpMatch && mcpMatch[1] === "switchroom-telegram")
31590
+ return null;
31591
+ const suffix = (mcpMatch ? mcpMatch[2] : toolName).toLowerCase();
31592
+ switch (suffix) {
31593
+ case "read":
31594
+ return "read";
31595
+ case "write":
31596
+ return "created";
31597
+ case "edit":
31598
+ case "multiedit":
31599
+ case "notebookedit":
31600
+ return "edited";
31601
+ case "bash":
31602
+ case "bashoutput":
31603
+ case "killshell":
31604
+ return "ran";
31605
+ case "websearch":
31606
+ case "grep":
31607
+ case "glob":
31608
+ return "searched";
31609
+ case "webfetch":
31610
+ return "fetched";
31611
+ case "task":
31612
+ case "agent":
31613
+ return "dispatched";
31614
+ case "todowrite":
31615
+ case "todoread":
31616
+ return "noted";
31617
+ default:
31618
+ return "used";
31619
+ }
31620
+ }
31621
+ function register(state, toolName) {
31622
+ const verb = verbForTool(toolName);
31623
+ if (!verb)
31624
+ return false;
31625
+ if (state.firstToolName == null)
31626
+ state.firstToolName = toolName;
31627
+ const prior = state.counts[verb] ?? 0;
31628
+ if (prior === 0)
31629
+ state.order.push(verb);
31630
+ state.counts[verb] = prior + 1;
31631
+ return true;
31632
+ }
31633
+ var VERB_PHRASE = {
31634
+ read: { singular: "read a file", plural: "read $N files" },
31635
+ edited: { singular: "edited a file", plural: "edited $N files" },
31636
+ created: { singular: "created a file", plural: "created $N files" },
31637
+ ran: { singular: "ran a command", plural: "ran $N commands" },
31638
+ searched: { singular: "ran a search", plural: "ran $N searches" },
31639
+ fetched: { singular: "fetched a URL", plural: "fetched $N URLs" },
31640
+ dispatched: { singular: "dispatched a sub-agent", plural: "dispatched $N sub-agents" },
31641
+ noted: { singular: "updated the todo list", plural: "updated the todo list ($N edits)" },
31642
+ used: { singular: "used a tool", plural: "used $N tools" }
31643
+ };
31644
+ function formatSummary(state) {
31645
+ const phrases = [];
31646
+ for (const verb of state.order) {
31647
+ const n = state.counts[verb] ?? 0;
31648
+ if (n <= 0)
31649
+ continue;
31650
+ const p = VERB_PHRASE[verb];
31651
+ phrases.push(n === 1 ? p.singular : p.plural.replace("$N", String(n)));
31652
+ }
31653
+ if (phrases.length === 0)
31654
+ return null;
31655
+ const sentence = phrases.join(", ");
31656
+ return sentence.charAt(0).toUpperCase() + sentence.slice(1);
31657
+ }
31658
+ function registerAndRender(state, toolName) {
31659
+ const changed = register(state, toolName);
31660
+ if (!changed)
31661
+ return null;
31662
+ return formatSummary(state);
31663
+ }
31664
+
31562
31665
  // tool-labels.ts
31563
31666
  var MAX_LABEL_CHARS = 60;
31564
31667
  var MAX_BASH_CHARS = 40;
@@ -31755,264 +31858,6 @@ function prettifyServer(name) {
31755
31858
  return name.charAt(0).toUpperCase() + name.slice(1);
31756
31859
  }
31757
31860
 
31758
- // tool-intent-surface.ts
31759
- var MAX_LABEL_LEN = 140;
31760
- function frameworkVerbFor(toolName) {
31761
- const m = /^mcp__[^_]+__(.+)$/.exec(toolName);
31762
- const suffix = (m ? m[1] : toolName).toLowerCase();
31763
- switch (suffix) {
31764
- case "bash":
31765
- case "bashoutput":
31766
- case "killshell":
31767
- return "running";
31768
- case "websearch":
31769
- case "grep":
31770
- case "glob":
31771
- return "searching";
31772
- case "webfetch":
31773
- return "fetching";
31774
- case "read":
31775
- return "reading";
31776
- case "write":
31777
- return "writing";
31778
- case "edit":
31779
- case "multiedit":
31780
- case "notebookedit":
31781
- return "editing";
31782
- case "todowrite":
31783
- case "todoread":
31784
- return "noting";
31785
- case "task":
31786
- case "agent":
31787
- return "dispatching";
31788
- case "toolsearch":
31789
- return "loading tools";
31790
- default:
31791
- if (m)
31792
- return `using ${m[1].replace(/_/g, " ")}`;
31793
- return `using ${toolName}`;
31794
- }
31795
- }
31796
- function isUserFacingTool(toolName) {
31797
- const m = /^mcp__switchroom-telegram__(.+)$/.exec(toolName);
31798
- const suffix = m ? m[1] : toolName;
31799
- return suffix === "reply" || suffix === "stream_reply" || suffix === "edit_message" || suffix === "react" || suffix === "send_typing" || suffix === "pin_message" || suffix === "delete_message" || suffix === "forward_message" || suffix === "download_attachment" || suffix === "get_recent_messages" || suffix === "progress_update";
31800
- }
31801
- function deriveIntentSurface(toolName, toolInput, precomputedLabel) {
31802
- if (!toolName)
31803
- return { text: null };
31804
- if (isUserFacingTool(toolName))
31805
- return { text: null };
31806
- const label = toolLabel(toolName, toolInput, undefined, precomputedLabel);
31807
- if (!label || !label.trim()) {
31808
- return {
31809
- text: `<i>${escapeHtml(frameworkVerbFor(toolName))}</i>`
31810
- };
31811
- }
31812
- const verb = frameworkVerbFor(toolName);
31813
- const safeLabel = escapeHtml(label).slice(0, MAX_LABEL_LEN);
31814
- return { text: `<i>${escapeHtml(verb)}:</i> ${safeLabel}` };
31815
- }
31816
- function escapeHtml(s) {
31817
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
31818
- }
31819
-
31820
- // tool-labels.ts
31821
- var MAX_LABEL_CHARS2 = 60;
31822
- var MAX_BASH_CHARS2 = 40;
31823
- var MAX_DESCRIPTION_CHARS2 = 160;
31824
- function basename2(p) {
31825
- if (!p)
31826
- return "";
31827
- const parts = p.split("/").filter(Boolean);
31828
- return parts.length > 0 ? parts[parts.length - 1] : p;
31829
- }
31830
- function shortenGrepPath2(p) {
31831
- if (!p)
31832
- return "repo";
31833
- const hadTrailingSlash = /\/+$/.test(p);
31834
- const trimmed = p.replace(/\/+$/, "");
31835
- const parts = trimmed.split("/").filter(Boolean);
31836
- if (parts.length === 0)
31837
- return "repo";
31838
- const last = parts[parts.length - 1];
31839
- if (hadTrailingSlash)
31840
- return `${last}/`;
31841
- if (last.startsWith(".") && !last.slice(1).includes("."))
31842
- return last;
31843
- if (!last.includes("."))
31844
- return `${last}/`;
31845
- return last;
31846
- }
31847
- function hostFromUrl2(u) {
31848
- if (!u)
31849
- return "";
31850
- try {
31851
- return new URL(u).host;
31852
- } catch {
31853
- return truncate2(u);
31854
- }
31855
- }
31856
- function truncate2(s, n = MAX_LABEL_CHARS2) {
31857
- if (s.length <= n)
31858
- return s;
31859
- return s.slice(0, n - 1) + "\u2026";
31860
- }
31861
- function stripHtml2(s) {
31862
- return s.replace(/<\/?[a-zA-Z][^>]*>/g, "");
31863
- }
31864
- function firstLine2(s) {
31865
- const idx = s.indexOf(`
31866
- `);
31867
- return idx === -1 ? s : s.slice(0, idx);
31868
- }
31869
- function toolLabel2(tool, input, preamble, precomputedLabel) {
31870
- if (precomputedLabel && precomputedLabel.trim().length > 0) {
31871
- return truncate2(firstLine2(precomputedLabel.trim()), MAX_DESCRIPTION_CHARS2);
31872
- }
31873
- if (!input || typeof input !== "object")
31874
- return "";
31875
- const str = (k) => typeof input[k] === "string" ? input[k] : undefined;
31876
- const preambleLabel = () => {
31877
- if (!preamble)
31878
- return null;
31879
- if (preamble.includes(`
31880
- `))
31881
- return null;
31882
- const trimmed = preamble.trim();
31883
- if (!trimmed)
31884
- return null;
31885
- if (trimmed.length > MAX_DESCRIPTION_CHARS2)
31886
- return null;
31887
- return trimmed;
31888
- };
31889
- switch (tool) {
31890
- case "Read":
31891
- case "Write":
31892
- case "NotebookEdit":
31893
- case "Edit": {
31894
- const pre = preambleLabel();
31895
- if (pre)
31896
- return pre;
31897
- return truncate2(basename2(str("file_path") ?? ""));
31898
- }
31899
- case "Bash":
31900
- case "BashOutput": {
31901
- const description = str("description");
31902
- if (description)
31903
- return truncate2(firstLine2(description), MAX_DESCRIPTION_CHARS2);
31904
- const pre = preambleLabel();
31905
- if (pre)
31906
- return pre;
31907
- const cmd = str("command") ?? str("bash_id") ?? "";
31908
- return truncate2(firstLine2(cmd), MAX_BASH_CHARS2);
31909
- }
31910
- case "KillShell":
31911
- return truncate2(str("shell_id") ?? "");
31912
- case "Glob": {
31913
- const pre = preambleLabel();
31914
- if (pre)
31915
- return pre;
31916
- return truncate2(str("pattern") ?? "");
31917
- }
31918
- case "Grep": {
31919
- const pre = preambleLabel();
31920
- if (pre)
31921
- return pre;
31922
- const pat = str("pattern") ?? "";
31923
- if (!pat)
31924
- return "";
31925
- const path = str("path");
31926
- const where = shortenGrepPath2(path ?? "");
31927
- return truncate2(`"${pat}" (in ${where})`);
31928
- }
31929
- case "WebFetch":
31930
- return truncate2(hostFromUrl2(str("url") ?? ""));
31931
- case "WebSearch": {
31932
- const q = str("query") ?? "";
31933
- return q ? truncate2(`"${q}"`) : "";
31934
- }
31935
- case "Task":
31936
- case "Agent": {
31937
- const desc = str("description") ?? str("subagent_type") ?? "";
31938
- return truncate2(desc);
31939
- }
31940
- case "TodoWrite":
31941
- case "TaskCreate":
31942
- case "TaskUpdate":
31943
- case "TaskList":
31944
- case "TaskGet":
31945
- case "TaskStop":
31946
- case "TaskOutput":
31947
- return "";
31948
- case "Skill":
31949
- return truncate2(str("skill") ?? "");
31950
- case "SlashCommand":
31951
- return truncate2(str("command") ?? "");
31952
- case "ToolSearch": {
31953
- const q = str("query") ?? "";
31954
- if (!q)
31955
- return "";
31956
- const selectMatch = q.match(/^\s*select\s*:\s*(.+)$/i);
31957
- if (selectMatch) {
31958
- const names = selectMatch[1].split(",").map((n) => n.trim()).filter((n) => n.length > 0).join(", ");
31959
- return truncate2(`Loading schema: ${names}`);
31960
- }
31961
- return truncate2(`Searching tools: ${q}`);
31962
- }
31963
- default:
31964
- if (tool.startsWith("mcp__")) {
31965
- const description = str("description");
31966
- if (description)
31967
- return truncate2(firstLine2(stripHtml2(description)), MAX_DESCRIPTION_CHARS2);
31968
- const label = mcpBaseLabel2(tool);
31969
- const query = str("query") ?? str("text") ?? str("name");
31970
- if (label && query) {
31971
- const budget = Math.max(8, MAX_LABEL_CHARS2 - label.length - 4);
31972
- const preview = truncate2(firstLine2(stripHtml2(query)), budget);
31973
- return `${label} (${preview})`;
31974
- }
31975
- if (label)
31976
- return truncate2(label);
31977
- }
31978
- for (const k of ["description", "file_path", "path", "url", "query", "pattern", "command"]) {
31979
- const v = str(k);
31980
- if (v != null && v.length > 0) {
31981
- if (k === "file_path" || k === "path")
31982
- return truncate2(basename2(v));
31983
- if (k === "url")
31984
- return truncate2(hostFromUrl2(v));
31985
- if (k === "description")
31986
- return truncate2(firstLine2(v), MAX_DESCRIPTION_CHARS2);
31987
- return truncate2(firstLine2(v));
31988
- }
31989
- }
31990
- return "";
31991
- }
31992
- }
31993
- function mcpBaseLabel2(tool) {
31994
- if (!tool.startsWith("mcp__"))
31995
- return "";
31996
- const parts = tool.slice("mcp__".length).split("__");
31997
- if (parts.length < 2)
31998
- return "";
31999
- const rawServer = parts[0];
32000
- const action = parts.slice(1).join("__");
32001
- if (!rawServer || !action)
32002
- return "";
32003
- return `${prettifyServer2(rawServer)}: ${action}`;
32004
- }
32005
- function prettifyServer2(name) {
32006
- const LABELS = {
32007
- "switchroom-telegram": "Telegram"
32008
- };
32009
- if (LABELS[name])
32010
- return LABELS[name];
32011
- if (!name)
32012
- return name;
32013
- return name.charAt(0).toUpperCase() + name.slice(1);
32014
- }
32015
-
32016
31861
  // gateway/chat-key.ts
32017
31862
  function chatKey(chatId, threadId) {
32018
31863
  const t = threadId == null || threadId === 0 ? "_" : String(threadId);
@@ -32121,18 +31966,18 @@ function isDraft429(err) {
32121
31966
  const text = typeof err === "string" ? err : err instanceof Error ? err.message : typeof err === "object" && err != null && ("description" in err) ? typeof err.description === "string" ? err.description : "" : "";
32122
31967
  return /sendMessageDraft/i.test(text);
32123
31968
  }
32124
- var DRAFT_STREAM_STATE_KEY = Symbol.for("switchroom.draftStreamState");
32125
- function getDraftStreamState() {
31969
+ var DRAFT_STREAM_STATE_KEY2 = Symbol.for("switchroom.draftStreamState");
31970
+ function getDraftStreamState2() {
32126
31971
  const g = globalThis;
32127
- let state = g[DRAFT_STREAM_STATE_KEY];
31972
+ let state = g[DRAFT_STREAM_STATE_KEY2];
32128
31973
  if (!state) {
32129
31974
  state = { nextDraftId: 0 };
32130
- g[DRAFT_STREAM_STATE_KEY] = state;
31975
+ g[DRAFT_STREAM_STATE_KEY2] = state;
32131
31976
  }
32132
31977
  return state;
32133
31978
  }
32134
- function allocateDraftId() {
32135
- const state = getDraftStreamState();
31979
+ function allocateDraftId2() {
31980
+ const state = getDraftStreamState2();
32136
31981
  state.nextDraftId = state.nextDraftId >= 2147483647 ? 1 : state.nextDraftId + 1;
32137
31982
  return state.nextDraftId;
32138
31983
  }
@@ -32162,7 +32007,7 @@ function createDraftStream(send, edit, config = {}) {
32162
32007
  warn?.('draft-stream: previewTransport="auto" with sendMessageDraft but isPrivateChat undefined \u2014 defaulting to message transport');
32163
32008
  }
32164
32009
  let usesDraftTransport = prefersDraft && draftApi != null;
32165
- let draftId = usesDraftTransport ? allocateDraftId() : undefined;
32010
+ let draftId = usesDraftTransport ? allocateDraftId2() : undefined;
32166
32011
  if (prefersDraft && !usesDraftTransport) {
32167
32012
  warn?.("draft-stream: sendMessageDraft unavailable; falling back to sendMessage/editMessageText");
32168
32013
  }
@@ -32270,7 +32115,7 @@ function createDraftStream(send, edit, config = {}) {
32270
32115
  const newMsgId = await send(chunk);
32271
32116
  messageId = newMsgId;
32272
32117
  persistedTextLen = textToSend.length;
32273
- draftId = allocateDraftId();
32118
+ draftId = allocateDraftId2();
32274
32119
  currentChunkStartedAt = null;
32275
32120
  persistChainFires++;
32276
32121
  sendFires++;
@@ -33145,7 +32990,7 @@ function installTgPostLogger(bot) {
33145
32990
  }
33146
32991
 
33147
32992
  // attachment-path.ts
33148
- import { join as join2, basename as basename3, resolve, sep } from "node:path";
32993
+ import { join as join2, basename as basename2, resolve, sep } from "node:path";
33149
32994
  function sanitizeExtension(ext) {
33150
32995
  if (ext == null)
33151
32996
  return "bin";
@@ -33174,7 +33019,7 @@ function assertInsideInbox(inboxDir, candidatePath) {
33174
33019
  const inboxReal = resolve(inboxDir);
33175
33020
  const candidateReal = resolve(candidatePath);
33176
33021
  if (candidateReal !== inboxReal && !candidateReal.startsWith(inboxReal + sep)) {
33177
- throw new Error(`attachment path escape: ${basename3(candidatePath)} resolved outside ${inboxDir}`);
33022
+ throw new Error(`attachment path escape: ${basename2(candidatePath)} resolved outside ${inboxDir}`);
33178
33023
  }
33179
33024
  }
33180
33025
 
@@ -38514,45 +38359,6 @@ function recordSilentTurnEnd(args, deps) {
38514
38359
  }
38515
38360
  var recordUndeliveredTurnEnd = recordSilentTurnEnd;
38516
38361
 
38517
- // ack-flag.ts
38518
- import { closeSync, existsSync as existsSync6, openSync, unlinkSync as unlinkSync2 } from "node:fs";
38519
- import { join as join7 } from "node:path";
38520
- var ACK_SENT_MARKER = "ack-sent.flag";
38521
- function markerPath() {
38522
- const dir = process.env.TELEGRAM_STATE_DIR;
38523
- if (!dir)
38524
- return null;
38525
- return join7(dir, ACK_SENT_MARKER);
38526
- }
38527
- function markAckSent() {
38528
- const path = markerPath();
38529
- if (path == null)
38530
- return;
38531
- if (existsSync6(path))
38532
- return;
38533
- try {
38534
- const fd = openSync(path, "w");
38535
- closeSync(fd);
38536
- } catch (err) {
38537
- process.stderr.write(`ack-flag: markAckSent failed path=${path}: ${err}
38538
- `);
38539
- }
38540
- }
38541
- function clearAckSent() {
38542
- const path = markerPath();
38543
- if (path == null)
38544
- return;
38545
- try {
38546
- unlinkSync2(path);
38547
- } catch (err) {
38548
- const code = err?.code;
38549
- if (code === "ENOENT")
38550
- return;
38551
- process.stderr.write(`ack-flag: clearAckSent failed path=${path}: ${err}
38552
- `);
38553
- }
38554
- }
38555
-
38556
38362
  // final-answer-detect.ts
38557
38363
  var FINAL_ANSWER_MIN_CHARS = 200;
38558
38364
  function isFinalAnswerReply(input) {
@@ -38586,7 +38392,7 @@ function isSilentFlushMarker(text) {
38586
38392
  var MIN_INITIAL_CHARS = 50;
38587
38393
  var DEFAULT_THROTTLE_MS = 1000;
38588
38394
  var TELEGRAM_MAX_CHARS2 = 4096;
38589
- var allocateDraftId2 = allocateDraftId;
38395
+ var allocateDraftId3 = allocateDraftId2;
38590
38396
  function createAnswerStream(config) {
38591
38397
  const {
38592
38398
  chatId,
@@ -38609,7 +38415,7 @@ function createAnswerStream(config) {
38609
38415
  const effectiveThrottle = Math.max(250, throttleMs);
38610
38416
  const preferDraft = isPrivateChat && draftApi != null;
38611
38417
  let usesDraftTransport = preferDraft;
38612
- let draftId = preferDraft ? allocateDraftId2() : undefined;
38418
+ let draftId = preferDraft ? allocateDraftId3() : undefined;
38613
38419
  let streamMsgId;
38614
38420
  let pendingText = null;
38615
38421
  let lastSentText = "";
@@ -38858,7 +38664,7 @@ function createAnswerStream(config) {
38858
38664
  if (staleDraftId != null) {
38859
38665
  clearDraftBestEffort(staleDraftId);
38860
38666
  }
38861
- draftId = allocateDraftId2();
38667
+ draftId = allocateDraftId3();
38862
38668
  }
38863
38669
  log?.(`answer-stream: forceNewMessage (gen=${generation})`);
38864
38670
  },
@@ -38976,7 +38782,7 @@ async function gatewayStartupRetry(fn, opts = {}) {
38976
38782
 
38977
38783
  // gateway/quarantine.ts
38978
38784
  import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync4 } from "node:fs";
38979
- import { join as join8 } from "node:path";
38785
+ import { join as join7 } from "node:path";
38980
38786
  var QUARANTINE_FILENAME = "quarantine.json";
38981
38787
  function writeQuarantineMarker(telegramStateDir, reason, detail, nowFn = Date.now) {
38982
38788
  mkdirSync6(telegramStateDir, { recursive: true, mode: 448 });
@@ -38986,7 +38792,7 @@ function writeQuarantineMarker(telegramStateDir, reason, detail, nowFn = Date.no
38986
38792
  ts: nowFn(),
38987
38793
  detail
38988
38794
  };
38989
- writeFileSync4(join8(telegramStateDir, QUARANTINE_FILENAME), JSON.stringify(marker) + `
38795
+ writeFileSync4(join7(telegramStateDir, QUARANTINE_FILENAME), JSON.stringify(marker) + `
38990
38796
  `, "utf-8");
38991
38797
  }
38992
38798
 
@@ -39064,16 +38870,16 @@ function renderAccountRow(snap, opts) {
39064
38870
  const lines = [];
39065
38871
  const marker = snap.isActive ? "\u25cf " : "";
39066
38872
  if (!snap.quota) {
39067
- lines.push(`${marker}<code>${escapeHtml2(snap.label)}</code> <i>quota probe failed</i>`);
38873
+ lines.push(`${marker}<code>${escapeHtml(snap.label)}</code> <i>quota probe failed</i>`);
39068
38874
  if (snap.quotaError) {
39069
- lines.push(` <i>${escapeHtml2(snap.quotaError)}</i>`);
38875
+ lines.push(` <i>${escapeHtml(snap.quotaError)}</i>`);
39070
38876
  }
39071
38877
  return lines;
39072
38878
  }
39073
38879
  const q = snap.quota;
39074
38880
  const fiveStr = fmtPct(q.fiveHourUtilizationPct);
39075
38881
  const sevenStr = fmtPct(q.sevenDayUtilizationPct);
39076
- lines.push(`${marker}<code>${escapeHtml2(snap.label)}</code> ${fiveStr} / ${sevenStr}`);
38882
+ lines.push(`${marker}<code>${escapeHtml(snap.label)}</code> ${fiveStr} / ${sevenStr}`);
39077
38883
  const health = classifyHealth(snap);
39078
38884
  if (health === "blocked") {
39079
38885
  const win = bindingWindow(q);
@@ -39179,13 +38985,13 @@ function renderFallbackAnnouncement(input) {
39179
38985
  const limitWord = input.oldQuota ? limitWordFor(input.oldQuota) : "quota";
39180
38986
  const headerLimit = limitWord === "quota" ? "quota cap" : `${limitWord} limit`;
39181
38987
  if (!input.newLabel) {
39182
- lines.push(`\uD83D\uDD34 <b>All accounts blocked \u00b7 ${headerLimit} on ${escapeHtml2(input.oldLabel)}</b>`);
38988
+ lines.push(`\uD83D\uDD34 <b>All accounts blocked \u00b7 ${headerLimit} on ${escapeHtml(input.oldLabel)}</b>`);
39183
38989
  lines.push("");
39184
- lines.push(`Triggered by: agent <b>${escapeHtml2(input.triggerAgent)}</b>`);
38990
+ lines.push(`Triggered by: agent <b>${escapeHtml(input.triggerAgent)}</b>`);
39185
38991
  if (input.oldQuota) {
39186
38992
  const recovery = recoveryAtFor(input.oldQuota);
39187
38993
  if (recovery) {
39188
- lines.push(`${escapeHtml2(input.oldLabel)} recovers ${formatAbsolute(recovery, tz)} ` + `(in ${formatRelative(recovery, now)})`);
38994
+ lines.push(`${escapeHtml(input.oldLabel)} recovers ${formatAbsolute(recovery, tz)} ` + `(in ${formatRelative(recovery, now)})`);
39189
38995
  }
39190
38996
  }
39191
38997
  lines.push("");
@@ -39193,15 +38999,15 @@ function renderFallbackAnnouncement(input) {
39193
38999
  return lines.join(`
39194
39000
  `);
39195
39001
  }
39196
- lines.push(`\u2713 <b>Switched fleet \u00b7 ${headerLimit} on ${escapeHtml2(input.oldLabel)}</b>`);
39002
+ lines.push(`\u2713 <b>Switched fleet \u00b7 ${headerLimit} on ${escapeHtml(input.oldLabel)}</b>`);
39197
39003
  lines.push("");
39198
- lines.push(`<code>${escapeHtml2(input.oldLabel)}</code> \u2192 <code>${escapeHtml2(input.newLabel)}</code>`);
39199
- lines.push(`Triggered by: agent <b>${escapeHtml2(input.triggerAgent)}</b>`);
39004
+ lines.push(`<code>${escapeHtml(input.oldLabel)}</code> \u2192 <code>${escapeHtml(input.newLabel)}</code>`);
39005
+ lines.push(`Triggered by: agent <b>${escapeHtml(input.triggerAgent)}</b>`);
39200
39006
  lines.push("");
39201
39007
  if (input.oldQuota) {
39202
39008
  const recovery = recoveryAtFor(input.oldQuota);
39203
39009
  if (recovery) {
39204
- lines.push(`<code>${escapeHtml2(input.oldLabel)}</code> recovers ` + `${formatAbsolute(recovery, tz)} (in ${formatRelative(recovery, now)})`);
39010
+ lines.push(`<code>${escapeHtml(input.oldLabel)}</code> recovers ` + `${formatAbsolute(recovery, tz)} (in ${formatRelative(recovery, now)})`);
39205
39011
  }
39206
39012
  }
39207
39013
  if (input.newQuota) {
@@ -39209,7 +39015,7 @@ function renderFallbackAnnouncement(input) {
39209
39015
  const sevenStr = fmtPct(input.newQuota.sevenDayUtilizationPct);
39210
39016
  const hasHeadroom = input.newQuota.fiveHourUtilizationPct < THROTTLING_THRESHOLD_PCT && input.newQuota.sevenDayUtilizationPct < THROTTLING_THRESHOLD_PCT;
39211
39017
  const headroomStr = hasHeadroom ? "<i>(plenty of headroom)</i>" : "<i>(near limit \u2014 watch this)</i>";
39212
- lines.push(`<code>${escapeHtml2(input.newLabel)}</code> now: ${fiveStr} of 5h \u00b7 ${sevenStr} of 7d ${headroomStr}`);
39018
+ lines.push(`<code>${escapeHtml(input.newLabel)}</code> now: ${fiveStr} of 5h \u00b7 ${sevenStr} of 7d ${headroomStr}`);
39213
39019
  } else {
39214
39020
  lines.push(`<i>(quota probe for new account is pending \u2014 will reflect on next /auth)</i>`);
39215
39021
  }
@@ -39268,7 +39074,7 @@ function switchPriority(s) {
39268
39074
  return 2;
39269
39075
  return 3;
39270
39076
  }
39271
- function escapeHtml2(s) {
39077
+ function escapeHtml(s) {
39272
39078
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
39273
39079
  }
39274
39080
  function buildSnapshotsFromState(state3, quotas) {
@@ -39361,7 +39167,7 @@ function parseAuthCommand(text) {
39361
39167
  if (tail.length > 0) {
39362
39168
  return {
39363
39169
  kind: "help",
39364
- reason: `Unknown <code>rm</code> modifier: <code>${escapeHtml3(tail)}</code>. Use <code>/auth rm &lt;label&gt; confirm</code> to confirm.`
39170
+ reason: `Unknown <code>rm</code> modifier: <code>${escapeHtml2(tail)}</code>. Use <code>/auth rm &lt;label&gt; confirm</code> to confirm.`
39365
39171
  };
39366
39172
  }
39367
39173
  return { kind: "rm-prompt", label };
@@ -39381,7 +39187,7 @@ function parseAuthCommand(text) {
39381
39187
  if (sub !== "override") {
39382
39188
  return {
39383
39189
  kind: "help",
39384
- reason: `Unknown <code>agent</code> subcommand: <code>${escapeHtml3(sub || "(none)")}</code>. Try <code>/auth agent override &lt;agent&gt; &lt;label|clear&gt;</code>.`
39190
+ reason: `Unknown <code>agent</code> subcommand: <code>${escapeHtml2(sub || "(none)")}</code>. Try <code>/auth agent override &lt;agent&gt; &lt;label|clear&gt;</code>.`
39385
39191
  };
39386
39192
  }
39387
39193
  const agent = parts[2];
@@ -39403,7 +39209,7 @@ function parseAuthCommand(text) {
39403
39209
  case "help":
39404
39210
  return { kind: "help" };
39405
39211
  default:
39406
- return { kind: "help", reason: `Unknown verb: <code>${escapeHtml3(verb)}</code>` };
39212
+ return { kind: "help", reason: `Unknown verb: <code>${escapeHtml2(verb)}</code>` };
39407
39213
  }
39408
39214
  }
39409
39215
  async function handleAuthCommand(parsed, ctx) {
@@ -39457,7 +39263,7 @@ async function handleAuthCommand(parsed, ctx) {
39457
39263
  };
39458
39264
  } catch (err) {
39459
39265
  return {
39460
- text: `<b>/auth show failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39266
+ text: `<b>/auth show failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39461
39267
  html: true
39462
39268
  };
39463
39269
  }
@@ -39469,7 +39275,7 @@ async function handleAuthCommand(parsed, ctx) {
39469
39275
  const agent = state3.agents.find((a) => a.name === agentName3);
39470
39276
  if (!agent) {
39471
39277
  return {
39472
- text: `<b>/auth show:</b> no agent named <code>${escapeHtml3(agentName3)}</code> in broker view.
39278
+ text: `<b>/auth show:</b> no agent named <code>${escapeHtml2(agentName3)}</code> in broker view.
39473
39279
  ` + `Run <code>/auth show</code> for the fleet snapshot.`,
39474
39280
  html: true
39475
39281
  };
@@ -39477,7 +39283,7 @@ async function handleAuthCommand(parsed, ctx) {
39477
39283
  return { text: renderAgentDetail(state3, agent), html: true };
39478
39284
  } catch (err) {
39479
39285
  return {
39480
- text: `<b>/auth show failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39286
+ text: `<b>/auth show failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39481
39287
  html: true
39482
39288
  };
39483
39289
  }
@@ -39499,13 +39305,13 @@ async function handleAuthCommand(parsed, ctx) {
39499
39305
  try {
39500
39306
  const result = await ctx.client.setActive(parsed.label);
39501
39307
  return {
39502
- text: `<b>Active account \u2192</b> <code>${escapeHtml3(result.active)}</code>
39308
+ text: `<b>Active account \u2192</b> <code>${escapeHtml2(result.active)}</code>
39503
39309
  ` + `Re-mirrored credentials for ${result.fanned.length} agent${result.fanned.length === 1 ? "" : "s"}.`,
39504
39310
  html: true
39505
39311
  };
39506
39312
  } catch (err) {
39507
39313
  return {
39508
- text: `<b>/auth use failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39314
+ text: `<b>/auth use failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39509
39315
  html: true
39510
39316
  };
39511
39317
  }
@@ -39523,13 +39329,13 @@ async function handleAuthCommand(parsed, ctx) {
39523
39329
  }
39524
39330
  const result = await ctx.client.setActive(nextLabel);
39525
39331
  return {
39526
- text: `<b>Rotated:</b> active \u2192 <code>${escapeHtml3(result.active)}</code>
39332
+ text: `<b>Rotated:</b> active \u2192 <code>${escapeHtml2(result.active)}</code>
39527
39333
  ` + `Re-mirrored credentials for ${result.fanned.length} agent${result.fanned.length === 1 ? "" : "s"}.`,
39528
39334
  html: true
39529
39335
  };
39530
39336
  } catch (err) {
39531
39337
  return {
39532
- text: `<b>/auth rotate failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39338
+ text: `<b>/auth rotate failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39533
39339
  html: true
39534
39340
  };
39535
39341
  }
@@ -39540,20 +39346,20 @@ async function handleAuthCommand(parsed, ctx) {
39540
39346
  state3 = await ctx.client.listState();
39541
39347
  } catch (err) {
39542
39348
  return {
39543
- text: `<b>/auth rm failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39349
+ text: `<b>/auth rm failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39544
39350
  html: true
39545
39351
  };
39546
39352
  }
39547
39353
  const exists = state3.accounts.some((a) => a.label === parsed.label);
39548
39354
  if (!exists) {
39549
39355
  return {
39550
- text: `<b>/auth rm:</b> no account named <code>${escapeHtml3(parsed.label)}</code>. ` + `Run <code>/auth show</code> for the current list.`,
39356
+ text: `<b>/auth rm:</b> no account named <code>${escapeHtml2(parsed.label)}</code>. ` + `Run <code>/auth show</code> for the current list.`,
39551
39357
  html: true
39552
39358
  };
39553
39359
  }
39554
39360
  if (state3.active === parsed.label) {
39555
39361
  return {
39556
- text: `<b>/auth rm refused.</b> <code>${escapeHtml3(parsed.label)}</code> is the fleet active. ` + `Switch with <code>/auth use &lt;other&gt;</code> or <code>/auth rotate</code> first.`,
39362
+ text: `<b>/auth rm refused.</b> <code>${escapeHtml2(parsed.label)}</code> is the fleet active. ` + `Switch with <code>/auth use &lt;other&gt;</code> or <code>/auth rotate</code> first.`,
39557
39363
  html: true
39558
39364
  };
39559
39365
  }
@@ -39564,10 +39370,10 @@ async function handleAuthCommand(parsed, ctx) {
39564
39370
  });
39565
39371
  }
39566
39372
  return {
39567
- text: `<b>\u26a0 /auth rm</b> \u2014 about to remove <code>${escapeHtml3(parsed.label)}</code> from the broker.
39568
- ` + `The fleet active is unchanged. Any agent override pointing at <code>${escapeHtml3(parsed.label)}</code> will stop working.
39373
+ text: `<b>\u26a0 /auth rm</b> \u2014 about to remove <code>${escapeHtml2(parsed.label)}</code> from the broker.
39374
+ ` + `The fleet active is unchanged. Any agent override pointing at <code>${escapeHtml2(parsed.label)}</code> will stop working.
39569
39375
 
39570
- ` + `Send <code>/auth rm ${escapeHtml3(parsed.label)} confirm</code> within ${Math.round(AUTH_RM_CONFIRM_TTL_MS / 1000)}s to proceed.`,
39376
+ ` + `Send <code>/auth rm ${escapeHtml2(parsed.label)} confirm</code> within ${Math.round(AUTH_RM_CONFIRM_TTL_MS / 1000)}s to proceed.`,
39571
39377
  html: true
39572
39378
  };
39573
39379
  }
@@ -39579,7 +39385,7 @@ async function handleAuthCommand(parsed, ctx) {
39579
39385
  pendingAuthRmFlows.delete(ctx.chatId);
39580
39386
  }
39581
39387
  return {
39582
- text: `<b>/auth rm:</b> no pending confirm for <code>${escapeHtml3(parsed.label)}</code> (expired or not started). ` + `Send <code>/auth rm ${escapeHtml3(parsed.label)}</code> first.`,
39388
+ text: `<b>/auth rm:</b> no pending confirm for <code>${escapeHtml2(parsed.label)}</code> (expired or not started). ` + `Send <code>/auth rm ${escapeHtml2(parsed.label)}</code> first.`,
39583
39389
  html: true
39584
39390
  };
39585
39391
  }
@@ -39588,12 +39394,12 @@ async function handleAuthCommand(parsed, ctx) {
39588
39394
  try {
39589
39395
  const data = await ctx.client.rmAccount(parsed.label);
39590
39396
  return {
39591
- text: `<b>Removed</b> <code>${escapeHtml3(data.label)}</code> from the broker.`,
39397
+ text: `<b>Removed</b> <code>${escapeHtml2(data.label)}</code> from the broker.`,
39592
39398
  html: true
39593
39399
  };
39594
39400
  } catch (err) {
39595
39401
  return {
39596
- text: `<b>/auth rm failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39402
+ text: `<b>/auth rm failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39597
39403
  html: true
39598
39404
  };
39599
39405
  }
@@ -39604,7 +39410,7 @@ async function handleAuthCommand(parsed, ctx) {
39604
39410
  const targets = parsed.label ? state3.accounts.filter((a) => a.label === parsed.label).map((a) => a.label) : state3.accounts.map((a) => a.label);
39605
39411
  if (parsed.label && targets.length === 0) {
39606
39412
  return {
39607
- text: `<b>/auth refresh:</b> no account named <code>${escapeHtml3(parsed.label)}</code>.`,
39413
+ text: `<b>/auth refresh:</b> no account named <code>${escapeHtml2(parsed.label)}</code>.`,
39608
39414
  html: true
39609
39415
  };
39610
39416
  }
@@ -39623,10 +39429,10 @@ async function handleAuthCommand(parsed, ctx) {
39623
39429
  formatExpiryAbs(data.expiresAt)
39624
39430
  ]);
39625
39431
  } catch (err) {
39626
- failures.push(`${label}: ${escapeHtml3(err?.message ?? String(err))}`);
39432
+ failures.push(`${label}: ${escapeHtml2(err?.message ?? String(err))}`);
39627
39433
  }
39628
39434
  }
39629
- const head = targets.length === 1 ? `<b>Refreshed</b> <code>${escapeHtml3(targets[0])}</code>` : `<b>Refreshed</b> ${rows.length - 1}/${targets.length} account${targets.length === 1 ? "" : "s"}`;
39435
+ const head = targets.length === 1 ? `<b>Refreshed</b> <code>${escapeHtml2(targets[0])}</code>` : `<b>Refreshed</b> ${rows.length - 1}/${targets.length} account${targets.length === 1 ? "" : "s"}`;
39630
39436
  const table = rows.length > 1 ? `
39631
39437
  <pre>${alignTable(rows)}</pre>` : "";
39632
39438
  const failBlock = failures.length > 0 ? `
@@ -39636,7 +39442,7 @@ ${failures.map((f) => ` ${f}`).join(`
39636
39442
  return { text: head + table + failBlock, html: true };
39637
39443
  } catch (err) {
39638
39444
  return {
39639
- text: `<b>/auth refresh failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39445
+ text: `<b>/auth refresh failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39640
39446
  html: true
39641
39447
  };
39642
39448
  }
@@ -39645,12 +39451,12 @@ ${failures.map((f) => ` ${f}`).join(`
39645
39451
  try {
39646
39452
  const data = await ctx.client.setOverride(parsed.agent, parsed.label);
39647
39453
  return {
39648
- text: `<b>Override set.</b> <code>${escapeHtml3(data.agent)}</code> is now pinned to ` + `<code>${escapeHtml3(data.account ?? parsed.label)}</code>.`,
39454
+ text: `<b>Override set.</b> <code>${escapeHtml2(data.agent)}</code> is now pinned to ` + `<code>${escapeHtml2(data.account ?? parsed.label)}</code>.`,
39649
39455
  html: true
39650
39456
  };
39651
39457
  } catch (err) {
39652
39458
  return {
39653
- text: `<b>/auth agent override failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39459
+ text: `<b>/auth agent override failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39654
39460
  html: true
39655
39461
  };
39656
39462
  }
@@ -39659,12 +39465,12 @@ ${failures.map((f) => ` ${f}`).join(`
39659
39465
  try {
39660
39466
  const data = await ctx.client.setOverride(parsed.agent, null);
39661
39467
  return {
39662
- text: `<b>Override cleared</b> on <code>${escapeHtml3(data.agent)}</code> ` + `\u2014 back to fleet active.`,
39468
+ text: `<b>Override cleared</b> on <code>${escapeHtml2(data.agent)}</code> ` + `\u2014 back to fleet active.`,
39663
39469
  html: true
39664
39470
  };
39665
39471
  } catch (err) {
39666
39472
  return {
39667
- text: `<b>/auth agent override failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39473
+ text: `<b>/auth agent override failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39668
39474
  html: true
39669
39475
  };
39670
39476
  }
@@ -39743,7 +39549,7 @@ function formatAccountsTable(state3, now) {
39743
39549
  const status = isActive ? "active" : acc.exhausted ? "exhausted" : "available";
39744
39550
  const expires = acc.expiresAt != null ? formatRelativeMs(acc.expiresAt - now) : "\u2014";
39745
39551
  const quotaReset = acc.exhausted && acc.exhausted_until != null && acc.exhausted_until > now ? formatRelativeMs(acc.exhausted_until - now) : "\u2014";
39746
- rows.push([`${marker} ${escapeHtml3(acc.label)}`, status, expires, quotaReset]);
39552
+ rows.push([`${marker} ${escapeHtml2(acc.label)}`, status, expires, quotaReset]);
39747
39553
  }
39748
39554
  return alignTable(rows);
39749
39555
  }
@@ -39751,15 +39557,15 @@ function formatAgentsTable(state3) {
39751
39557
  const rows = [["AGENT", "ACTIVE", "SOURCE"]];
39752
39558
  for (const a of state3.agents) {
39753
39559
  const source = a.override ? "override" : a.account === state3.active ? "fleet-active" : "pinned";
39754
- rows.push([escapeHtml3(a.name), escapeHtml3(a.account), source]);
39560
+ rows.push([escapeHtml2(a.name), escapeHtml2(a.account), source]);
39755
39561
  }
39756
39562
  return alignTable(rows);
39757
39563
  }
39758
39564
  function renderAgentDetail(state3, agent, now = Date.now()) {
39759
39565
  const lines = [];
39760
- lines.push(`<b>${escapeHtml3(agent.name)}</b>`);
39566
+ lines.push(`<b>${escapeHtml2(agent.name)}</b>`);
39761
39567
  const source = agent.override ? "override" : "fleet-active";
39762
- lines.push(`Active account: <code>${escapeHtml3(agent.account)}</code> (${source})`);
39568
+ lines.push(`Active account: <code>${escapeHtml2(agent.account)}</code> (${source})`);
39763
39569
  const acct = state3.accounts.find((a) => a.label === agent.account);
39764
39570
  if (acct) {
39765
39571
  const expRel = acct.expiresAt != null ? formatRelativeMs(acct.expiresAt - now) : "\u2014";
@@ -39782,11 +39588,11 @@ function formatConsumersTable(state3, now) {
39782
39588
  const rows = [["CONSUMER", "ACTIVE", "STATUS"]];
39783
39589
  for (const c of state3.consumers) {
39784
39590
  const status = c.last_seen_at == null ? "socket bound" : `socket bound (last seen ${formatRelativeMs(now - c.last_seen_at)} ago)`;
39785
- rows.push([escapeHtml3(c.name), escapeHtml3(c.account), status]);
39591
+ rows.push([escapeHtml2(c.name), escapeHtml2(c.account), status]);
39786
39592
  }
39787
39593
  return alignTable(rows);
39788
39594
  }
39789
- function escapeHtml3(s) {
39595
+ function escapeHtml2(s) {
39790
39596
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
39791
39597
  }
39792
39598
  function formatRelativeMs(ms) {
@@ -39871,7 +39677,7 @@ import * as net2 from "node:net";
39871
39677
  init_protocol();
39872
39678
  import { homedir as homedir4 } from "node:os";
39873
39679
  import { randomUUID as randomUUID4 } from "node:crypto";
39874
- import { join as join10 } from "node:path";
39680
+ import { join as join9 } from "node:path";
39875
39681
  var DEFAULT_TIMEOUT_MS2 = 5000;
39876
39682
  function reviveDate2(v) {
39877
39683
  if (v == null)
@@ -39882,7 +39688,7 @@ function reviveDate2(v) {
39882
39688
  return Number.isNaN(d.getTime()) ? null : d;
39883
39689
  }
39884
39690
  function operatorSocketPath2(home = homedir4()) {
39885
- return join10(home, ".switchroom", "state", "auth-broker-operator", "sock");
39691
+ return join9(home, ".switchroom", "state", "auth-broker-operator", "sock");
39886
39692
  }
39887
39693
  function resolveAuthBrokerSocketPath2(opts) {
39888
39694
  if (opts?.socket)
@@ -40214,16 +40020,16 @@ function createFleetFallbackGate(opts) {
40214
40020
 
40215
40021
  // gateway/auth-add-flow.ts
40216
40022
  import { spawn } from "node:child_process";
40217
- import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync7, rmSync as rmSync2 } from "node:fs";
40023
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync7, rmSync as rmSync2 } from "node:fs";
40218
40024
  import { homedir as homedir6 } from "node:os";
40219
- import { join as join11 } from "node:path";
40025
+ import { join as join10 } from "node:path";
40220
40026
  import { randomBytes as randomBytes2 } from "node:crypto";
40221
40027
 
40222
40028
  // ../src/auth/manager.ts
40223
40029
  import {
40224
40030
  readFileSync as readFileSync6,
40225
40031
  readdirSync as readdirSync2,
40226
- existsSync as existsSync11,
40032
+ existsSync as existsSync10,
40227
40033
  writeFileSync as writeFileSync5,
40228
40034
  mkdirSync as mkdirSync7,
40229
40035
  mkdtempSync,
@@ -40250,7 +40056,7 @@ function parseSetupTokenUrl(output) {
40250
40056
  }
40251
40057
  function readTokenFromCredentialsFile(credentialsFilePath) {
40252
40058
  try {
40253
- if (!existsSync11(credentialsFilePath))
40059
+ if (!existsSync10(credentialsFilePath))
40254
40060
  return null;
40255
40061
  const raw = readFileSync6(credentialsFilePath, "utf-8");
40256
40062
  const parsed = JSON.parse(raw);
@@ -40269,7 +40075,7 @@ function readTokenFromCredentialsFile(credentialsFilePath) {
40269
40075
  var pendingAuthAddFlows = new Map;
40270
40076
  function pickScratchDir(label, home2 = homedir6()) {
40271
40077
  const suffix = randomBytes2(8).toString("hex");
40272
- return join11(home2, ".switchroom", "accounts", ".in-progress", `${label}-${suffix}`);
40078
+ return join10(home2, ".switchroom", "accounts", ".in-progress", `${label}-${suffix}`);
40273
40079
  }
40274
40080
  function cleanScratchDir(scratchDir) {
40275
40081
  try {
@@ -40330,7 +40136,7 @@ async function startAccountAuthSession(label, opts = {}) {
40330
40136
  async function submitAccountAuthCode(flow, code, opts = {}) {
40331
40137
  const pollIntervalMs = opts.pollIntervalMs ?? 250;
40332
40138
  const pollTimeoutMs = opts.pollTimeoutMs ?? 120000;
40333
- const credentialsPath = join11(flow.scratchDir, ".credentials.json");
40139
+ const credentialsPath = join10(flow.scratchDir, ".credentials.json");
40334
40140
  if (!flow.child.stdin || flow.child.stdin.destroyed) {
40335
40141
  cleanScratchDir(flow.scratchDir);
40336
40142
  throw new Error("claude setup-token process stdin is not writable (child may have exited)");
@@ -40340,7 +40146,7 @@ async function submitAccountAuthCode(flow, code, opts = {}) {
40340
40146
  const deadline = Date.now() + pollTimeoutMs;
40341
40147
  while (Date.now() < deadline) {
40342
40148
  await new Promise((r) => setTimeout(r, pollIntervalMs));
40343
- if (existsSync12(credentialsPath)) {
40149
+ if (existsSync11(credentialsPath)) {
40344
40150
  const token = readTokenFromCredentialsFile(credentialsPath);
40345
40151
  if (token) {
40346
40152
  try {
@@ -41101,11 +40907,11 @@ function renderTable(headers, rows) {
41101
40907
  if (colCount <= 3 && rowCount <= 6) {
41102
40908
  const bullets = rows.map((row) => {
41103
40909
  const cells = headers.map((_, i) => (row[i] ?? "").trim());
41104
- const key = escapeHtml5(cells[0] || "\u2014");
41105
- const rest = cells.slice(1).filter((v) => v !== "").map((v) => ` \u2014 ${escapeHtml5(v)}`).join("");
40910
+ const key = escapeHtml4(cells[0] || "\u2014");
40911
+ const rest = cells.slice(1).filter((v) => v !== "").map((v) => ` \u2014 ${escapeHtml4(v)}`).join("");
41106
40912
  return `\u2022 <b>${key}</b>${rest}`;
41107
40913
  });
41108
- const headerLine = colCount >= 2 ? `<b>${headers.map((h) => escapeHtml5(h)).join(" / ")}</b>
40914
+ const headerLine = colCount >= 2 ? `<b>${headers.map((h) => escapeHtml4(h)).join(" / ")}</b>
41109
40915
  ` : "";
41110
40916
  return headerLine + bullets.join(`
41111
40917
  `);
@@ -41120,7 +40926,7 @@ function renderTable(headers, rows) {
41120
40926
  sepLine,
41121
40927
  ...rows.map((r) => formatRow(r))
41122
40928
  ];
41123
- return `<pre>${escapeHtml5(lines.join(`
40929
+ return `<pre>${escapeHtml4(lines.join(`
41124
40930
  `))}</pre>`;
41125
40931
  }
41126
40932
  function extractMarkdownTables(text, store2, placeholderPrefix) {
@@ -41168,7 +40974,7 @@ function markdownToHtml(text) {
41168
40974
  const INLINE_PH = "\x00CODEINLINE";
41169
40975
  const TABLE_PH = "\x00TABLEBLOCK";
41170
40976
  let result = text.replace(/```(\w*)\n([\s\S]*?)```/g, (_m, lang, code) => {
41171
- const escaped = escapeHtml5(code.replace(/\n$/, ""));
40977
+ const escaped = escapeHtml4(code.replace(/\n$/, ""));
41172
40978
  const cls = lang ? ` class="language-${lang}"` : "";
41173
40979
  const idx = codeBlocks.length;
41174
40980
  codeBlocks.push(`<pre><code${cls}>${escaped}</code></pre>`);
@@ -41181,7 +40987,7 @@ function markdownToHtml(text) {
41181
40987
  const inlineCodes = [];
41182
40988
  result = result.replace(/`([^`\n]+)`/g, (_m, code) => {
41183
40989
  const idx = inlineCodes.length;
41184
- inlineCodes.push(`<code>${escapeHtml5(code)}</code>`);
40990
+ inlineCodes.push(`<code>${escapeHtml4(code)}</code>`);
41185
40991
  return `${INLINE_PH}${idx}\x00`;
41186
40992
  });
41187
40993
  const htmlTags = [];
@@ -41193,24 +40999,24 @@ function markdownToHtml(text) {
41193
40999
  htmlTags.push(match);
41194
41000
  return `${HTMLTAG_PH}${idx}\x00`;
41195
41001
  });
41196
- result = escapeHtml5(result);
41002
+ result = escapeHtml4(result);
41197
41003
  result = result.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
41198
41004
  result = result.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<i>$1</i>");
41199
41005
  result = result.replace(/(?<![\w_])_(?!_)([^_\n]+?)_(?![\w_])/g, "<i>$1</i>");
41200
41006
  result = result.replace(/~~(.+?)~~/g, "<s>$1</s>");
41201
- result = result.replace(new RegExp(`${escapeHtml5(BLOCK_PH)}(\\d+)${escapeHtml5("\x00")}`, "g"), (_m, idx) => codeBlocks[Number(idx)]);
41202
- result = result.replace(new RegExp(`${escapeHtml5(TABLE_PH)}(\\d+)${escapeHtml5("\x00")}`, "g"), (_m, idx) => codeBlocks[Number(idx)]);
41203
- result = result.replace(new RegExp(`${escapeHtml5(INLINE_PH)}(\\d+)${escapeHtml5("\x00")}`, "g"), (_m, idx) => inlineCodes[Number(idx)]);
41007
+ result = result.replace(new RegExp(`${escapeHtml4(BLOCK_PH)}(\\d+)${escapeHtml4("\x00")}`, "g"), (_m, idx) => codeBlocks[Number(idx)]);
41008
+ result = result.replace(new RegExp(`${escapeHtml4(TABLE_PH)}(\\d+)${escapeHtml4("\x00")}`, "g"), (_m, idx) => codeBlocks[Number(idx)]);
41009
+ result = result.replace(new RegExp(`${escapeHtml4(INLINE_PH)}(\\d+)${escapeHtml4("\x00")}`, "g"), (_m, idx) => inlineCodes[Number(idx)]);
41204
41010
  const ALLOWED_LINK_SCHEMES = /^(?:https?|mailto|tel|tg):/i;
41205
41011
  result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, linkText, url) => {
41206
41012
  const safe = ALLOWED_LINK_SCHEMES.test(url.trim()) ? url.trim() : "#";
41207
- return `<a href="${escapeHtml5(safe)}">${linkText}</a>`;
41013
+ return `<a href="${escapeHtml4(safe)}">${linkText}</a>`;
41208
41014
  });
41209
41015
  result = result.replace(/(?<![<\/\w>])(\b[\w][\w.-]*\.(?:ts|js|py|rs|go|json|yaml|yml|toml|md|txt|sh|bash|zsh|css|html|xml|sql|env|cfg|conf|ini|log|csv|tsx|jsx|vue|svelte|rb|java|kt|swift|c|cpp|h|hpp|zig|asm|wasm|lock|mod|sum)\b)(?![^<]*>)/g, "<code>$1</code>");
41210
- result = result.replace(new RegExp(`${escapeHtml5(HTMLTAG_PH)}(\\d+)${escapeHtml5("\x00")}`, "g"), (_m, idx) => htmlTags[Number(idx)]);
41016
+ result = result.replace(new RegExp(`${escapeHtml4(HTMLTAG_PH)}(\\d+)${escapeHtml4("\x00")}`, "g"), (_m, idx) => htmlTags[Number(idx)]);
41211
41017
  return result;
41212
41018
  }
41213
- function escapeHtml5(text) {
41019
+ function escapeHtml4(text) {
41214
41020
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
41215
41021
  }
41216
41022
  function telegramHtmlToPlainText(html) {
@@ -41611,7 +41417,7 @@ async function finalizeCallback(ctx, opts) {
41611
41417
  }
41612
41418
 
41613
41419
  // welcome-text.ts
41614
- function escapeHtml6(text) {
41420
+ function escapeHtml5(text) {
41615
41421
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
41616
41422
  }
41617
41423
  function formatAuthLine(auth) {
@@ -41623,13 +41429,13 @@ function formatAuthLine(auth) {
41623
41429
  return "\u2717 not authenticated";
41624
41430
  }
41625
41431
  const sub = auth.subscription_type ?? "subscription";
41626
- const expires = auth.expires_in ? ` \u00b7 expires ${escapeHtml6(auth.expires_in)}` : "";
41627
- return `\u2713 ${escapeHtml6(sub)}${expires}`;
41432
+ const expires = auth.expires_in ? ` \u00b7 expires ${escapeHtml5(auth.expires_in)}` : "";
41433
+ return `\u2713 ${escapeHtml5(sub)}${expires}`;
41628
41434
  }
41629
41435
  function formatAgentLine(meta) {
41630
41436
  const m = meta.model && meta.model.length > 0 ? meta.model : "default";
41631
- const topic = meta.topicName ? ` \u00b7 topic: ${escapeHtml6([meta.topicEmoji, meta.topicName].filter(Boolean).join(" "))}` : "";
41632
- return `<b>${escapeHtml6(meta.agentName)}</b> \u00b7 model: <code>${escapeHtml6(m)}</code>${topic}`;
41437
+ const topic = meta.topicName ? ` \u00b7 topic: ${escapeHtml5([meta.topicEmoji, meta.topicName].filter(Boolean).join(" "))}` : "";
41438
+ return `<b>${escapeHtml5(meta.agentName)}</b> \u00b7 model: <code>${escapeHtml5(m)}</code>${topic}`;
41633
41439
  }
41634
41440
  function startText(agentName3, dmDisabled) {
41635
41441
  if (dmDisabled)
@@ -41637,7 +41443,7 @@ function startText(agentName3, dmDisabled) {
41637
41443
  return [
41638
41444
  `<b>Switchroom</b> \u2014 Telegram on your Claude Pro or Max subscription.`,
41639
41445
  ``,
41640
- `This bot is the <b>${escapeHtml6(agentName3)}</b> agent. Pair first, then send messages here and they reach the agent; replies and reactions come back.`,
41446
+ `This bot is the <b>${escapeHtml5(agentName3)}</b> agent. Pair first, then send messages here and they reach the agent; replies and reactions come back.`,
41641
41447
  ``,
41642
41448
  `<b>To pair:</b>`,
41643
41449
  `1. DM me anything \u2014 you'll get a 6-char code`,
@@ -41651,7 +41457,7 @@ function helpText(agentName3) {
41651
41457
  return [
41652
41458
  `<b>Switchroom</b> \u2014 your Pro/Max subscription, wired to Telegram.`,
41653
41459
  ``,
41654
- `This bot is the <b>${escapeHtml6(agentName3)}</b> agent. Text and photos route through to it; replies, reactions and progress cards come back.`,
41460
+ `This bot is the <b>${escapeHtml5(agentName3)}</b> agent. Text and photos route through to it; replies, reactions and progress cards come back.`,
41655
41461
  ``,
41656
41462
  `Tool approvals surface as inline buttons (\u2705 / \u274c) or via <code>/approve</code>, <code>/deny</code>, <code>/pending</code>. Start a fresh session with <code>/new</code> or <code>/reset</code>.`,
41657
41463
  ``,
@@ -41670,40 +41476,40 @@ var STATUS_DOT = {
41670
41476
  function statusPairedText(params) {
41671
41477
  const { user, meta } = params;
41672
41478
  const lines = [
41673
- `Paired as ${escapeHtml6(user)}.`,
41479
+ `Paired as ${escapeHtml5(user)}.`,
41674
41480
  ``,
41675
41481
  `Agent: ${formatAgentLine(meta)}`,
41676
41482
  `Auth: ${formatAuthLine(meta.auth)}`
41677
41483
  ];
41678
41484
  if (meta.status)
41679
- lines.push(`Status: <code>${escapeHtml6(meta.status)}</code>${meta.uptime ? ` \u00b7 up ${escapeHtml6(meta.uptime)}` : ""}`);
41485
+ lines.push(`Status: <code>${escapeHtml5(meta.status)}</code>${meta.uptime ? ` \u00b7 up ${escapeHtml5(meta.uptime)}` : ""}`);
41680
41486
  if (meta.live && meta.live.length > 0) {
41681
41487
  lines.push("");
41682
41488
  lines.push("<b>Health</b>");
41683
41489
  for (const row of meta.live) {
41684
41490
  const dot = STATUS_DOT[row.status] ?? STATUS_DOT.fail;
41685
- lines.push(`${dot} <b>${escapeHtml6(row.label)}</b> ${escapeHtml6(row.detail)}`);
41491
+ lines.push(`${dot} <b>${escapeHtml5(row.label)}</b> ${escapeHtml5(row.detail)}`);
41686
41492
  }
41687
41493
  }
41688
41494
  const audit = meta.audit;
41689
41495
  if (audit) {
41690
41496
  lines.push("");
41691
41497
  if (audit.version)
41692
- lines.push(`<b>Version</b> ${escapeHtml6(audit.version)}`);
41498
+ lines.push(`<b>Version</b> ${escapeHtml5(audit.version)}`);
41693
41499
  if (meta.extendsProfile)
41694
- lines.push(`<b>Profile</b> ${escapeHtml6(meta.extendsProfile)}`);
41500
+ lines.push(`<b>Profile</b> ${escapeHtml5(meta.extendsProfile)}`);
41695
41501
  if (audit.tools)
41696
- lines.push(`<b>Tools</b> ${escapeHtml6(audit.tools)}`);
41502
+ lines.push(`<b>Tools</b> ${escapeHtml5(audit.tools)}`);
41697
41503
  if (audit.toolsDeny)
41698
- lines.push(`<b>Deny</b> ${escapeHtml6(audit.toolsDeny)}`);
41504
+ lines.push(`<b>Deny</b> ${escapeHtml5(audit.toolsDeny)}`);
41699
41505
  if (audit.skills)
41700
- lines.push(`<b>Skills</b> ${escapeHtml6(audit.skills)}`);
41506
+ lines.push(`<b>Skills</b> ${escapeHtml5(audit.skills)}`);
41701
41507
  if (audit.limits)
41702
- lines.push(`<b>Limits</b> ${escapeHtml6(audit.limits)}`);
41508
+ lines.push(`<b>Limits</b> ${escapeHtml5(audit.limits)}`);
41703
41509
  if (audit.channel)
41704
- lines.push(`<b>Channel</b> ${escapeHtml6(audit.channel)}`);
41510
+ lines.push(`<b>Channel</b> ${escapeHtml5(audit.channel)}`);
41705
41511
  if (audit.memoryBank)
41706
- lines.push(`<b>Memory</b> ${escapeHtml6(audit.memoryBank)}`);
41512
+ lines.push(`<b>Memory</b> ${escapeHtml5(audit.memoryBank)}`);
41707
41513
  }
41708
41514
  return lines.join(`
41709
41515
  `);
@@ -41711,7 +41517,7 @@ function statusPairedText(params) {
41711
41517
  function statusPendingText(code) {
41712
41518
  return `Pending pairing \u2014 run in Claude Code:
41713
41519
 
41714
- <code>/telegram:access pair ${escapeHtml6(code)}</code>`;
41520
+ <code>/telegram:access pair ${escapeHtml5(code)}</code>`;
41715
41521
  }
41716
41522
  function statusUnpairedText() {
41717
41523
  return "Not paired. Send me a message to get a pairing code.";
@@ -41740,7 +41546,7 @@ var TELEGRAM_BASE_COMMANDS = TELEGRAM_MENU_COMMANDS.slice(0, 3);
41740
41546
  var TELEGRAM_SWITCHROOM_COMMANDS = TELEGRAM_MENU_COMMANDS.slice(3);
41741
41547
  function switchroomHelpText(agentName3) {
41742
41548
  return [
41743
- `<b>Switchroom bot</b> \u2014 commands for the <b>${escapeHtml6(agentName3)}</b> agent.`,
41549
+ `<b>Switchroom bot</b> \u2014 commands for the <b>${escapeHtml5(agentName3)}</b> agent.`,
41744
41550
  ``,
41745
41551
  `<b>Session &amp; approvals</b>`,
41746
41552
  `<code>/new</code> \u2014 fresh session (flush handoff, restart)`,
@@ -41788,15 +41594,15 @@ function switchroomHelpText(agentName3) {
41788
41594
  `);
41789
41595
  }
41790
41596
  function restartAckText(agentName3) {
41791
- return `\uD83D\uDD04 Restarting <b>${escapeHtml6(agentName3)}</b>\u2026`;
41597
+ return `\uD83D\uDD04 Restarting <b>${escapeHtml5(agentName3)}</b>\u2026`;
41792
41598
  }
41793
41599
  function newSessionAckText(agentName3, flushedHandoff) {
41794
41600
  const tail = flushedHandoff ? " \u00b7 flushed handoff" : "";
41795
- return `\uD83C\uDD95 Started fresh session for <b>${escapeHtml6(agentName3)}</b>${tail} \u00b7 restarting\u2026`;
41601
+ return `\uD83C\uDD95 Started fresh session for <b>${escapeHtml5(agentName3)}</b>${tail} \u00b7 restarting\u2026`;
41796
41602
  }
41797
41603
  function resetSessionAckText(agentName3, flushedHandoff) {
41798
41604
  const tail = flushedHandoff ? " \u00b7 flushed handoff" : "";
41799
- return `\uD83D\uDD04 Reset session for <b>${escapeHtml6(agentName3)}</b>${tail} \u00b7 restarting\u2026`;
41605
+ return `\uD83D\uDD04 Reset session for <b>${escapeHtml5(agentName3)}</b>${tail} \u00b7 restarting\u2026`;
41800
41606
  }
41801
41607
 
41802
41608
  // gateway/auth-status-adapter.ts
@@ -41900,8 +41706,8 @@ function isTurnFlushSafetyEnabled(env = process.env) {
41900
41706
  }
41901
41707
 
41902
41708
  // handoff-continuity.ts
41903
- import { readFileSync as readFileSync9, unlinkSync as unlinkSync3, existsSync as existsSync14, writeFileSync as writeFileSync6, renameSync as renameSync2 } from "node:fs";
41904
- import { dirname as dirname7, join as join14 } from "node:path";
41709
+ import { readFileSync as readFileSync9, unlinkSync as unlinkSync2, existsSync as existsSync13, writeFileSync as writeFileSync6, renameSync as renameSync2 } from "node:fs";
41710
+ import { dirname as dirname7, join as join13 } from "node:path";
41905
41711
  var TOPIC_DISPLAY_MAX = 117;
41906
41712
  var HANDOFF_TOPIC_FILENAME = ".handoff-topic";
41907
41713
  var LAST_TURN_SUMMARY_FILENAME = ".last-turn-summary";
@@ -41912,8 +41718,8 @@ function resolveAgentDirFromEnv() {
41912
41718
  return dirname7(state3);
41913
41719
  }
41914
41720
  function readHandoffTopic(agentDir) {
41915
- const p = join14(agentDir, HANDOFF_TOPIC_FILENAME);
41916
- if (!existsSync14(p))
41721
+ const p = join13(agentDir, HANDOFF_TOPIC_FILENAME);
41722
+ if (!existsSync13(p))
41917
41723
  return null;
41918
41724
  let raw;
41919
41725
  try {
@@ -41931,8 +41737,8 @@ function readHandoffTopic(agentDir) {
41931
41737
  return topic;
41932
41738
  }
41933
41739
  function readLastTurnSummary(agentDir) {
41934
- const p = join14(agentDir, LAST_TURN_SUMMARY_FILENAME);
41935
- if (!existsSync14(p))
41740
+ const p = join13(agentDir, LAST_TURN_SUMMARY_FILENAME);
41741
+ if (!existsSync13(p))
41936
41742
  return null;
41937
41743
  let raw;
41938
41744
  try {
@@ -41951,16 +41757,16 @@ function readLastTurnSummary(agentDir) {
41951
41757
  }
41952
41758
  function consumeHandoffTopic(agentDir) {
41953
41759
  const primary = readHandoffTopic(agentDir);
41954
- const primaryPath = join14(agentDir, HANDOFF_TOPIC_FILENAME);
41955
- const fallbackPath = join14(agentDir, LAST_TURN_SUMMARY_FILENAME);
41760
+ const primaryPath = join13(agentDir, HANDOFF_TOPIC_FILENAME);
41761
+ const fallbackPath = join13(agentDir, LAST_TURN_SUMMARY_FILENAME);
41956
41762
  const removeFallback = () => {
41957
41763
  try {
41958
- unlinkSync3(fallbackPath);
41764
+ unlinkSync2(fallbackPath);
41959
41765
  } catch {}
41960
41766
  };
41961
41767
  if (primary !== null) {
41962
41768
  try {
41963
- unlinkSync3(primaryPath);
41769
+ unlinkSync2(primaryPath);
41964
41770
  } catch {}
41965
41771
  removeFallback();
41966
41772
  return primary;
@@ -41981,7 +41787,7 @@ function shouldShowHandoffLine() {
41981
41787
  function formatHandoffLine(topic, format) {
41982
41788
  const prefix = "\u21a9\ufe0f Picked up where we left off, ";
41983
41789
  if (format === "html") {
41984
- return `<i>${prefix}${escapeHtml7(topic)}</i>
41790
+ return `<i>${prefix}${escapeHtml6(topic)}</i>
41985
41791
 
41986
41792
  `;
41987
41793
  }
@@ -41996,7 +41802,7 @@ function formatHandoffLine(topic, format) {
41996
41802
 
41997
41803
  `;
41998
41804
  }
41999
- function escapeHtml7(s) {
41805
+ function escapeHtml6(s) {
42000
41806
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
42001
41807
  }
42002
41808
  var MDV2_SPECIALS = /[_*\[\]()~`>#+\-=|{}.!\\]/g;
@@ -42005,15 +41811,15 @@ function escapeMarkdownV2(s) {
42005
41811
  }
42006
41812
 
42007
41813
  // active-reactions.ts
42008
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, renameSync as renameSync3, existsSync as existsSync15, unlinkSync as unlinkSync4 } from "node:fs";
42009
- import { join as join15 } from "node:path";
41814
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, renameSync as renameSync3, existsSync as existsSync14, unlinkSync as unlinkSync3 } from "node:fs";
41815
+ import { join as join14 } from "node:path";
42010
41816
  var ACTIVE_REACTIONS_FILENAME = ".active-reactions.json";
42011
41817
  function reactionsPath(agentDir) {
42012
- return join15(agentDir, ACTIVE_REACTIONS_FILENAME);
41818
+ return join14(agentDir, ACTIVE_REACTIONS_FILENAME);
42013
41819
  }
42014
41820
  function readActiveReactions(agentDir) {
42015
41821
  const p = reactionsPath(agentDir);
42016
- if (!existsSync15(p))
41822
+ if (!existsSync14(p))
42017
41823
  return [];
42018
41824
  let raw;
42019
41825
  try {
@@ -42043,7 +41849,7 @@ function writeActiveReactions(agentDir, reactions) {
42043
41849
  const p = reactionsPath(agentDir);
42044
41850
  if (reactions.length === 0) {
42045
41851
  try {
42046
- unlinkSync4(p);
41852
+ unlinkSync3(p);
42047
41853
  } catch {}
42048
41854
  return;
42049
41855
  }
@@ -42068,20 +41874,20 @@ function removeActiveReaction(agentDir, chatId, messageId) {
42068
41874
  }
42069
41875
  function clearActiveReactions(agentDir) {
42070
41876
  try {
42071
- unlinkSync4(reactionsPath(agentDir));
41877
+ unlinkSync3(reactionsPath(agentDir));
42072
41878
  } catch {}
42073
41879
  }
42074
41880
 
42075
41881
  // active-reactions.ts
42076
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, renameSync as renameSync4, existsSync as existsSync16, unlinkSync as unlinkSync5 } from "node:fs";
42077
- import { join as join16 } from "node:path";
41882
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, renameSync as renameSync4, existsSync as existsSync15, unlinkSync as unlinkSync4 } from "node:fs";
41883
+ import { join as join15 } from "node:path";
42078
41884
  var ACTIVE_REACTIONS_FILENAME2 = ".active-reactions.json";
42079
41885
  function reactionsPath2(agentDir) {
42080
- return join16(agentDir, ACTIVE_REACTIONS_FILENAME2);
41886
+ return join15(agentDir, ACTIVE_REACTIONS_FILENAME2);
42081
41887
  }
42082
41888
  function readActiveReactions2(agentDir) {
42083
41889
  const p = reactionsPath2(agentDir);
42084
- if (!existsSync16(p))
41890
+ if (!existsSync15(p))
42085
41891
  return [];
42086
41892
  let raw;
42087
41893
  try {
@@ -42109,7 +41915,7 @@ function readActiveReactions2(agentDir) {
42109
41915
  }
42110
41916
  function clearActiveReactions2(agentDir) {
42111
41917
  try {
42112
- unlinkSync5(reactionsPath2(agentDir));
41918
+ unlinkSync4(reactionsPath2(agentDir));
42113
41919
  } catch {}
42114
41920
  }
42115
41921
 
@@ -42962,14 +42768,14 @@ async function approvalRecord(args, opts) {
42962
42768
  }
42963
42769
 
42964
42770
  // quota-check.ts
42965
- import { readFileSync as readFileSync13, existsSync as existsSync18 } from "fs";
42966
- import { join as join18 } from "path";
42771
+ import { readFileSync as readFileSync13, existsSync as existsSync17 } from "fs";
42772
+ import { join as join17 } from "path";
42967
42773
  var OAUTH_BETA2 = "oauth-2025-04-20";
42968
42774
  var DEFAULT_USER_AGENT2 = "claude-cli/1.0.0 (external, cli)";
42969
42775
  var DEFAULT_PROBE_MODEL2 = "claude-haiku-4-5-20251001";
42970
42776
  function readOauthToken2(claudeConfigDir) {
42971
- const tokenFile = join18(claudeConfigDir, ".oauth-token");
42972
- if (!existsSync18(tokenFile))
42777
+ const tokenFile = join17(claudeConfigDir, ".oauth-token");
42778
+ if (!existsSync17(tokenFile))
42973
42779
  return null;
42974
42780
  try {
42975
42781
  const raw = readFileSync13(tokenFile, "utf-8").trim();
@@ -43568,7 +43374,7 @@ init_schema();
43568
43374
  init_paths();
43569
43375
  init_overlay_loader();
43570
43376
  init_merge();
43571
- import { readFileSync as readFileSync14, existsSync as existsSync19 } from "node:fs";
43377
+ import { readFileSync as readFileSync14, existsSync as existsSync18 } from "node:fs";
43572
43378
  import { homedir as homedir8 } from "node:os";
43573
43379
  import { resolve as resolve5 } from "node:path";
43574
43380
 
@@ -43644,7 +43450,7 @@ function findConfigFile2(startDir) {
43644
43450
  resolve5(userDir, "clerk.yml")
43645
43451
  ].filter(Boolean);
43646
43452
  for (const path of searchPaths) {
43647
- if (existsSync19(path)) {
43453
+ if (existsSync18(path)) {
43648
43454
  return path;
43649
43455
  }
43650
43456
  }
@@ -43652,7 +43458,7 @@ function findConfigFile2(startDir) {
43652
43458
  }
43653
43459
  function loadConfig2(configPath) {
43654
43460
  const filePath = configPath ?? findConfigFile2();
43655
- if (!existsSync19(filePath)) {
43461
+ if (!existsSync18(filePath)) {
43656
43462
  throw new ConfigError2(`Config file not found: ${filePath}`);
43657
43463
  }
43658
43464
  let raw;
@@ -44085,9 +43891,9 @@ function resolveOutboundTopic(config, event) {
44085
43891
  }
44086
43892
 
44087
43893
  // ../src/agents/perf.ts
44088
- import { existsSync as existsSync20, readFileSync as readFileSync15 } from "node:fs";
43894
+ import { existsSync as existsSync19, readFileSync as readFileSync15 } from "node:fs";
44089
43895
  function readTurnUsages(jsonlPath, lastN) {
44090
- if (!existsSync20(jsonlPath))
43896
+ if (!existsSync19(jsonlPath))
44091
43897
  return [];
44092
43898
  if (lastN <= 0)
44093
43899
  return [];
@@ -44231,7 +44037,7 @@ function nextCompactNotify(state3, ev) {
44231
44037
  }
44232
44038
 
44233
44039
  // gateway/hostd-dispatch.ts
44234
- import { existsSync as existsSync21 } from "node:fs";
44040
+ import { existsSync as existsSync20 } from "node:fs";
44235
44041
  import { randomBytes as randomBytes3 } from "node:crypto";
44236
44042
 
44237
44043
  // ../src/host-control/client.ts
@@ -44522,13 +44328,13 @@ function hostdSocketPath(agentName3) {
44522
44328
  function hostdWillBeUsed(agentName3) {
44523
44329
  if (!isHostdEnabled())
44524
44330
  return false;
44525
- return existsSync21(hostdSocketPath(agentName3));
44331
+ return existsSync20(hostdSocketPath(agentName3));
44526
44332
  }
44527
44333
  async function tryHostdDispatch(agentName3, req) {
44528
44334
  if (!isHostdEnabled())
44529
44335
  return "not-configured";
44530
44336
  const sockPath = hostdSocketPath(agentName3);
44531
- if (!existsSync21(sockPath))
44337
+ if (!existsSync20(sockPath))
44532
44338
  return "not-configured";
44533
44339
  try {
44534
44340
  return await hostdRequest({ socketPath: sockPath, timeoutMs: 5000 }, req);
@@ -44552,7 +44358,7 @@ async function hostdGetStatusOnce(agentName3, targetRequestId) {
44552
44358
  if (!isHostdEnabled())
44553
44359
  return "not-configured";
44554
44360
  const sockPath = hostdSocketPath(agentName3);
44555
- if (!existsSync21(sockPath))
44361
+ if (!existsSync20(sockPath))
44556
44362
  return "not-configured";
44557
44363
  try {
44558
44364
  const resp = await hostdRequest({ socketPath: sockPath, timeoutMs: 3000 }, {
@@ -44573,7 +44379,7 @@ async function pollHostdStatus(agentName3, targetRequestId, opts) {
44573
44379
  if (!isHostdEnabled())
44574
44380
  return "not-configured";
44575
44381
  const sockPath = hostdSocketPath(agentName3);
44576
- if (!existsSync21(sockPath))
44382
+ if (!existsSync20(sockPath))
44577
44383
  return "not-configured";
44578
44384
  const now = opts.now ?? Date.now;
44579
44385
  const sleep2 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
@@ -44651,7 +44457,7 @@ function shouldSweepChatAtBoot(chatId) {
44651
44457
  }
44652
44458
 
44653
44459
  // gateway/ipc-server.ts
44654
- import { renameSync as renameSync5, unlinkSync as unlinkSync6 } from "fs";
44460
+ import { renameSync as renameSync5, unlinkSync as unlinkSync5 } from "fs";
44655
44461
  var MAX_BUFFER_SIZE = 1024 * 1024;
44656
44462
  var VALID_OPERATOR_KINDS = new Set([
44657
44463
  "credentials-expired",
@@ -44769,7 +44575,7 @@ function createIpcServer(options) {
44769
44575
  renameSync5(socketPath, socketPath + ".bak");
44770
44576
  } catch {}
44771
44577
  try {
44772
- unlinkSync6(socketPath + ".bak");
44578
+ unlinkSync5(socketPath + ".bak");
44773
44579
  } catch {}
44774
44580
  const clients = new Set;
44775
44581
  const agentIndex = new Map;
@@ -45375,13 +45181,13 @@ function buildMs365CardText(p) {
45375
45181
  const lines = [];
45376
45182
  lines.push(`\uD83D\uDCC4 Microsoft 365 write approval`);
45377
45183
  lines.push("");
45378
- lines.push(`Agent: ${truncate3(p.agentName, 64)}`);
45379
- lines.push(`Tool: ${truncate3(p.toolName.replace(/^mcp__/, ""), 96)}`);
45380
- lines.push(`Item: ${truncate3(p.itemDisplayName, 256)}`);
45184
+ lines.push(`Agent: ${truncate2(p.agentName, 64)}`);
45185
+ lines.push(`Tool: ${truncate2(p.toolName.replace(/^mcp__/, ""), 96)}`);
45186
+ lines.push(`Item: ${truncate2(p.itemDisplayName, 256)}`);
45381
45187
  if (p.itemId !== "(new)") {
45382
- lines.push(`ID: ${truncate3(p.itemId, 96)}`);
45188
+ lines.push(`ID: ${truncate2(p.itemId, 96)}`);
45383
45189
  }
45384
- lines.push(`Account: ${truncate3(p.accountEmail, 96)}`);
45190
+ lines.push(`Account: ${truncate2(p.accountEmail, 96)}`);
45385
45191
  if (typeof p.sizeBytesBefore === "number" || typeof p.sizeBytesAfter === "number") {
45386
45192
  const before = p.sizeBytesBefore ?? 0;
45387
45193
  const after = p.sizeBytesAfter ?? 0;
@@ -45390,18 +45196,18 @@ function buildMs365CardText(p) {
45390
45196
  lines.push(`Size: ${humanBytes(before)} \u2192 ${humanBytes(after)} (${sign}${humanBytes(delta)})`);
45391
45197
  }
45392
45198
  if (p.deepLink) {
45393
- lines.push(`Link: ${truncate3(p.deepLink, 256)}`);
45199
+ lines.push(`Link: ${truncate2(p.deepLink, 256)}`);
45394
45200
  }
45395
45201
  if (p.agentRationale) {
45396
45202
  lines.push("");
45397
- lines.push(`\uD83D\uDCAC ${truncate3(p.agentRationale, 512)}`);
45203
+ lines.push(`\uD83D\uDCAC ${truncate2(p.agentRationale, 512)}`);
45398
45204
  }
45399
45205
  lines.push("");
45400
45206
  lines.push("\u26a0\ufe0f Weak attestation (RFC \u00a78 v1): operator should click through to verify the actual change before approving. Structural diff coming v1.5.");
45401
45207
  return lines.join(`
45402
45208
  `);
45403
45209
  }
45404
- function truncate3(s, n) {
45210
+ function truncate2(s, n) {
45405
45211
  if (s.length <= n)
45406
45212
  return s;
45407
45213
  return s.slice(0, n - 1) + "\u2026";
@@ -45517,9 +45323,9 @@ function buildDiffPreviewCard(input) {
45517
45323
  }
45518
45324
  const preview = input.preview;
45519
45325
  const bodyLines = [];
45520
- bodyLines.push(`<b>${escapeHtml8(preview.title)}</b>`);
45326
+ bodyLines.push(`<b>${escapeHtml7(preview.title)}</b>`);
45521
45327
  for (const line of preview.lines) {
45522
- bodyLines.push(escapeHtml8(line.text));
45328
+ bodyLines.push(escapeHtml7(line.text));
45523
45329
  }
45524
45330
  const text = bodyLines.join(`
45525
45331
  `);
@@ -45572,7 +45378,7 @@ function buildDiffPreviewCard(input) {
45572
45378
  }
45573
45379
  return { text, reply_markup: kb };
45574
45380
  }
45575
- function escapeHtml8(s) {
45381
+ function escapeHtml7(s) {
45576
45382
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
45577
45383
  }
45578
45384
 
@@ -46418,14 +46224,14 @@ function buildVaultSaveDiscardedInbound(opts) {
46418
46224
  // gateway/subagent-handback-inbound-builder.ts
46419
46225
  var HANDBACK_RESULT_MAX = 3000;
46420
46226
  var HANDBACK_DESC_MAX = 200;
46421
- function truncate4(s, max) {
46227
+ function truncate3(s, max) {
46422
46228
  const t = s.trim();
46423
46229
  return t.length > max ? t.slice(0, max) + "\u2026" : t;
46424
46230
  }
46425
46231
  function buildSubagentHandbackInbound(opts) {
46426
46232
  const ts = opts.nowMs ?? Date.now();
46427
- const desc = truncate4(opts.ctx.taskDescription, HANDBACK_DESC_MAX) || "(no description)";
46428
- const result = truncate4(opts.ctx.resultText, HANDBACK_RESULT_MAX);
46233
+ const desc = truncate3(opts.ctx.taskDescription, HANDBACK_DESC_MAX) || "(no description)";
46234
+ const result = truncate3(opts.ctx.resultText, HANDBACK_RESULT_MAX);
46429
46235
  const text = opts.ctx.outcome === "failed" ? `\uD83E\uDD1D A background worker you dispatched has FAILED.
46430
46236
 
46431
46237
  ` + `Task: ${desc}
@@ -46489,7 +46295,7 @@ function decideSubagentHandback(input) {
46489
46295
  var PROGRESS_RESULT_MAX = 800;
46490
46296
  var PROGRESS_DESC_MAX = 200;
46491
46297
  var DEFAULT_PROGRESS_INTERVAL_MS = 5 * 60 * 1000;
46492
- function truncate5(s, max) {
46298
+ function truncate4(s, max) {
46493
46299
  const t = s.trim();
46494
46300
  return t.length > max ? t.slice(0, max) + "\u2026" : t;
46495
46301
  }
@@ -46503,8 +46309,8 @@ function formatElapsed(ms) {
46503
46309
  }
46504
46310
  function buildSubagentProgressInbound(opts) {
46505
46311
  const ts = opts.nowMs ?? Date.now();
46506
- const desc = truncate5(opts.ctx.taskDescription, PROGRESS_DESC_MAX) || "(no description)";
46507
- const summary = truncate5(opts.ctx.latestSummary, PROGRESS_RESULT_MAX);
46312
+ const desc = truncate4(opts.ctx.taskDescription, PROGRESS_DESC_MAX) || "(no description)";
46313
+ const summary = truncate4(opts.ctx.latestSummary, PROGRESS_RESULT_MAX);
46508
46314
  const elapsed = formatElapsed(opts.ctx.elapsedMs);
46509
46315
  const expiresAt = ts + 2 * opts.ctx.progressIntervalMs;
46510
46316
  const text = `\uD83D\uDD04 A background worker you dispatched is still running.
@@ -46832,7 +46638,7 @@ function escapeBody(s) {
46832
46638
  }
46833
46639
 
46834
46640
  // gateway/pid-file.ts
46835
- import { writeFileSync as writeFileSync9, readFileSync as readFileSync16, unlinkSync as unlinkSync7, renameSync as renameSync6 } from "node:fs";
46641
+ import { writeFileSync as writeFileSync9, readFileSync as readFileSync16, unlinkSync as unlinkSync6, renameSync as renameSync6 } from "node:fs";
46836
46642
  function writePidFile(path, record) {
46837
46643
  const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
46838
46644
  writeFileSync9(tmp, JSON.stringify(record), "utf-8");
@@ -46840,7 +46646,7 @@ function writePidFile(path, record) {
46840
46646
  }
46841
46647
  function clearPidFile(path) {
46842
46648
  try {
46843
- unlinkSync7(path);
46649
+ unlinkSync6(path);
46844
46650
  } catch {}
46845
46651
  }
46846
46652
 
@@ -47057,7 +46863,7 @@ function safeCount(fn) {
47057
46863
  }
47058
46864
 
47059
46865
  // gateway/session-marker.ts
47060
- import { writeFileSync as writeFileSync10, readFileSync as readFileSync18, renameSync as renameSync7, unlinkSync as unlinkSync8 } from "node:fs";
46866
+ import { writeFileSync as writeFileSync10, readFileSync as readFileSync18, renameSync as renameSync7, unlinkSync as unlinkSync7 } from "node:fs";
47061
46867
  function writeSessionMarker(path, marker) {
47062
46868
  const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
47063
46869
  writeFileSync10(tmp, JSON.stringify(marker), "utf-8");
@@ -47087,7 +46893,7 @@ function shouldFireRestartBanner(input) {
47087
46893
  }
47088
46894
 
47089
46895
  // gateway/clean-shutdown-marker.ts
47090
- import { writeFileSync as writeFileSync11, readFileSync as readFileSync19, renameSync as renameSync8, unlinkSync as unlinkSync9 } from "node:fs";
46896
+ import { writeFileSync as writeFileSync11, readFileSync as readFileSync19, renameSync as renameSync8, unlinkSync as unlinkSync8 } from "node:fs";
47091
46897
  var DEFAULT_MAX_AGE_MS = 60000;
47092
46898
  function writeCleanShutdownMarker(path, marker) {
47093
46899
  const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
@@ -47111,7 +46917,7 @@ function readCleanShutdownMarker(path) {
47111
46917
  }
47112
46918
  function clearCleanShutdownMarker(path) {
47113
46919
  try {
47114
- unlinkSync9(path);
46920
+ unlinkSync8(path);
47115
46921
  } catch {}
47116
46922
  }
47117
46923
  function shouldSuppressRecoveryBanner(marker, now, maxAgeMs = DEFAULT_MAX_AGE_MS) {
@@ -47891,16 +47697,16 @@ function classifyAdminGate(text, myAgentName) {
47891
47697
 
47892
47698
  // subagent-watcher.ts
47893
47699
  import {
47894
- existsSync as existsSync23,
47895
- openSync as openSync3,
47700
+ existsSync as existsSync22,
47701
+ openSync as openSync2,
47896
47702
  readSync,
47897
47703
  statSync as statSync6,
47898
- closeSync as closeSync3,
47704
+ closeSync as closeSync2,
47899
47705
  watch,
47900
47706
  readdirSync as readdirSync3,
47901
47707
  readFileSync as readFileSync21
47902
47708
  } from "fs";
47903
- import { join as join20 } from "path";
47709
+ import { join as join19 } from "path";
47904
47710
 
47905
47711
  // operator-events.ts
47906
47712
  var DEFAULT_OPERATOR_EVENT_COOLDOWN_MS2 = 5 * 60000;
@@ -48024,7 +47830,7 @@ function sanitiseToolArg(name, raw) {
48024
47830
  case "NotebookEdit": {
48025
47831
  const fp = raw.file_path;
48026
47832
  if (typeof fp === "string" && fp.length > 0)
48027
- out = basename4(fp);
47833
+ out = basename3(fp);
48028
47834
  break;
48029
47835
  }
48030
47836
  case "Bash": {
@@ -48060,7 +47866,7 @@ function sanitiseToolArg(name, raw) {
48060
47866
  out = out.slice(0, SANITISE_MAX_LEN - 1) + "\u2026";
48061
47867
  return out;
48062
47868
  }
48063
- function basename4(p) {
47869
+ function basename3(p) {
48064
47870
  const idx = p.lastIndexOf("/");
48065
47871
  return idx === -1 ? p : p.slice(idx + 1);
48066
47872
  }
@@ -48142,29 +47948,29 @@ function bumpSubagentActivity(db2, args) {
48142
47948
 
48143
47949
  // gateway/turn-active-marker.ts
48144
47950
  import {
48145
- closeSync as closeSync2,
48146
- existsSync as existsSync22,
47951
+ closeSync,
47952
+ existsSync as existsSync21,
48147
47953
  mkdirSync as mkdirSync10,
48148
- openSync as openSync2,
47954
+ openSync,
48149
47955
  readFileSync as readFileSync20,
48150
47956
  statSync as statSync5,
48151
- unlinkSync as unlinkSync10,
47957
+ unlinkSync as unlinkSync9,
48152
47958
  utimesSync,
48153
47959
  writeFileSync as writeFileSync12
48154
47960
  } from "node:fs";
48155
- import { join as join19 } from "node:path";
47961
+ import { join as join18 } from "node:path";
48156
47962
  var TURN_ACTIVE_MARKER_FILE = "turn-active.json";
48157
47963
  function touchTurnActiveMarker(stateDir) {
48158
- const path = join19(stateDir, TURN_ACTIVE_MARKER_FILE);
48159
- if (!existsSync22(path))
47964
+ const path = join18(stateDir, TURN_ACTIVE_MARKER_FILE);
47965
+ if (!existsSync21(path))
48160
47966
  return;
48161
47967
  const now = new Date;
48162
47968
  try {
48163
47969
  utimesSync(path, now, now);
48164
47970
  } catch {
48165
47971
  try {
48166
- const fd = openSync2(path, "r+");
48167
- closeSync2(fd);
47972
+ const fd = openSync(path, "r+");
47973
+ closeSync(fd);
48168
47974
  } catch {}
48169
47975
  }
48170
47976
  }
@@ -48378,11 +48184,11 @@ function startSubagentWatcher(config) {
48378
48184
  clearTimeout(ref.ref);
48379
48185
  });
48380
48186
  const fs2 = config.fs ?? {
48381
- existsSync: existsSync23,
48187
+ existsSync: existsSync22,
48382
48188
  readdirSync: readdirSync3,
48383
48189
  statSync: statSync6,
48384
- openSync: openSync3,
48385
- closeSync: closeSync3,
48190
+ openSync: openSync2,
48191
+ closeSync: closeSync2,
48386
48192
  readSync,
48387
48193
  watch
48388
48194
  };
@@ -48547,7 +48353,7 @@ function startSubagentWatcher(config) {
48547
48353
  if (idleMs >= threshold) {
48548
48354
  entry.stallNotified = true;
48549
48355
  entry.stalledAt = n;
48550
- const desc = escapeHtml9(truncate6(entry.description, 80));
48356
+ const desc = escapeHtml8(truncate5(entry.description, 80));
48551
48357
  const idleSec = Math.floor(idleMs / 1000);
48552
48358
  log?.(`subagent-watcher: stall detected for ${entry.agentId} (idle ${idleSec}s): ${desc}`);
48553
48359
  if (db2 != null) {
@@ -48612,8 +48418,8 @@ function startSubagentWatcher(config) {
48612
48418
  function rescanSubagentDirs() {
48613
48419
  if (stopped)
48614
48420
  return;
48615
- const claudeHome = join20(agentDir, ".claude");
48616
- const projectsRoot = join20(claudeHome, "projects");
48421
+ const claudeHome = join19(agentDir, ".claude");
48422
+ const projectsRoot = join19(claudeHome, "projects");
48617
48423
  if (!fs2.existsSync(projectsRoot))
48618
48424
  return;
48619
48425
  let projectDirs;
@@ -48630,7 +48436,7 @@ function startSubagentWatcher(config) {
48630
48436
  }
48631
48437
  continue;
48632
48438
  }
48633
- const projectPath = join20(projectsRoot, pDir);
48439
+ const projectPath = join19(projectsRoot, pDir);
48634
48440
  let sessionDirs;
48635
48441
  try {
48636
48442
  sessionDirs = fs2.readdirSync(projectPath);
@@ -48640,7 +48446,7 @@ function startSubagentWatcher(config) {
48640
48446
  for (const sDir of sessionDirs) {
48641
48447
  if (sDir.endsWith(".jsonl"))
48642
48448
  continue;
48643
- const subagentsPath = join20(projectPath, sDir, "subagents");
48449
+ const subagentsPath = join19(projectPath, sDir, "subagents");
48644
48450
  if (!fs2.existsSync(subagentsPath))
48645
48451
  continue;
48646
48452
  if (!dirWatchers.has(subagentsPath)) {
@@ -48648,7 +48454,7 @@ function startSubagentWatcher(config) {
48648
48454
  const w = fs2.watch(subagentsPath, (_event, filename) => {
48649
48455
  if (!filename || !filename.toString().startsWith("agent-") || !filename.toString().endsWith(".jsonl"))
48650
48456
  return;
48651
- const filePath = join20(subagentsPath, filename.toString());
48457
+ const filePath = join19(subagentsPath, filename.toString());
48652
48458
  if (!knownFiles.has(filePath)) {
48653
48459
  scanSubagentsDir(subagentsPath);
48654
48460
  }
@@ -48673,7 +48479,7 @@ function startSubagentWatcher(config) {
48673
48479
  for (const e of entries) {
48674
48480
  if (!e.startsWith("agent-") || !e.endsWith(".jsonl"))
48675
48481
  continue;
48676
- const filePath = join20(subagentsPath, e);
48482
+ const filePath = join19(subagentsPath, e);
48677
48483
  if (knownFiles.has(filePath))
48678
48484
  continue;
48679
48485
  const agentId = e.slice("agent-".length, -".jsonl".length);
@@ -48790,15 +48596,15 @@ function determineRestartReason(opts) {
48790
48596
  init_boot_card();
48791
48597
 
48792
48598
  // gateway/update-announce.ts
48793
- import { existsSync as existsSync27, mkdirSync as mkdirSync13, openSync as openSync4, closeSync as closeSync4, readFileSync as readFileSync25 } from "node:fs";
48794
- import { join as join25 } from "node:path";
48599
+ import { existsSync as existsSync26, mkdirSync as mkdirSync13, openSync as openSync3, closeSync as closeSync3, readFileSync as readFileSync25 } from "node:fs";
48600
+ import { join as join24 } from "node:path";
48795
48601
  import { homedir as homedir10 } from "node:os";
48796
48602
 
48797
48603
  // ../src/host-control/audit-reader.ts
48798
48604
  import { homedir as homedir9 } from "node:os";
48799
- import { join as join24 } from "node:path";
48605
+ import { join as join23 } from "node:path";
48800
48606
  function defaultAuditLogPath(home2 = homedir9()) {
48801
- return join24(home2, ".switchroom", "host-control-audit.log");
48607
+ return join23(home2, ".switchroom", "host-control-audit.log");
48802
48608
  }
48803
48609
  function parseAuditLine(line) {
48804
48610
  const trimmed = line.trim();
@@ -48904,7 +48710,7 @@ function readAndFilter(raw, filters, limit) {
48904
48710
  var DEFAULT_LOOKBACK_MS = 10 * 60 * 1000;
48905
48711
  function readLastTerminalUpdateAudit(opts = {}) {
48906
48712
  const path = opts.auditLogPath ?? defaultAuditLogPath();
48907
- const exists = opts.exists ?? existsSync27;
48713
+ const exists = opts.exists ?? existsSync26;
48908
48714
  const readFile = opts.readFile ?? ((p) => readFileSync25(p, "utf-8"));
48909
48715
  if (!exists(path))
48910
48716
  return null;
@@ -48966,18 +48772,18 @@ function renderUpdateOutcomeLine(entry) {
48966
48772
  `);
48967
48773
  }
48968
48774
  function claimUpdateAnnouncement(requestId, opts = {}) {
48969
- const stateDir = opts.stateDir ?? process.env.TELEGRAM_STATE_DIR ?? join25(homedir10(), ".switchroom");
48970
- const dir = join25(stateDir, "update-announced");
48775
+ const stateDir = opts.stateDir ?? process.env.TELEGRAM_STATE_DIR ?? join24(homedir10(), ".switchroom");
48776
+ const dir = join24(stateDir, "update-announced");
48971
48777
  try {
48972
48778
  mkdirSync13(dir, { recursive: true });
48973
48779
  } catch {
48974
48780
  return false;
48975
48781
  }
48976
48782
  const safeId = requestId.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 200);
48977
- const path = join25(dir, safeId);
48783
+ const path = join24(dir, safeId);
48978
48784
  try {
48979
- const fd = openSync4(path, "wx");
48980
- closeSync4(fd);
48785
+ const fd = openSync3(path, "wx");
48786
+ closeSync3(fd);
48981
48787
  return true;
48982
48788
  } catch {
48983
48789
  return false;
@@ -49021,7 +48827,7 @@ function renderIssuesCard(opts) {
49021
48827
  const maxSeverity = sorted[0].severity;
49022
48828
  const headerEmoji = SEVERITY_EMOJI[maxSeverity];
49023
48829
  const count = sorted.length;
49024
- const header = `${headerEmoji} <b>${escapeHtml9(opts.agentName)}</b> \u00b7 ${count} ${count === 1 ? "issue" : "issues"}`;
48830
+ const header = `${headerEmoji} <b>${escapeHtml8(opts.agentName)}</b> \u00b7 ${count} ${count === 1 ? "issue" : "issues"}`;
49025
48831
  const maxRows = opts.maxRows ?? DEFAULT_MAX_ROWS;
49026
48832
  const visible = sorted.slice(0, maxRows);
49027
48833
  const overflow = sorted.length - visible.length;
@@ -49030,10 +48836,10 @@ function renderIssuesCard(opts) {
49030
48836
  const emoji = SEVERITY_EMOJI[e.severity];
49031
48837
  const occ = e.occurrences > 1 ? ` <i>(\u00d7${e.occurrences})</i>` : "";
49032
48838
  const ago = relTime(now - e.last_seen);
49033
- const head = `${emoji} <code>${escapeHtml9(e.fingerprint)}</code> ${escapeHtml9(e.summary)}${occ} \u2014 <i>${ago}</i>`;
48839
+ const head = `${emoji} <code>${escapeHtml8(e.fingerprint)}</code> ${escapeHtml8(e.summary)}${occ} \u2014 <i>${ago}</i>`;
49034
48840
  const remediation = formatRemediation(e.detail);
49035
48841
  return remediation == null ? head : `${head}
49036
- \u2192 <i>${escapeHtml9(remediation)}</i>`;
48842
+ \u2192 <i>${escapeHtml8(remediation)}</i>`;
49037
48843
  });
49038
48844
  const lines = [header, "", ...rows];
49039
48845
  if (overflow > 0) {
@@ -49194,24 +49000,24 @@ function createIssuesCardHandle(opts) {
49194
49000
  }
49195
49001
 
49196
49002
  // issues-watcher.ts
49197
- import { existsSync as existsSync29, statSync as statSync8 } from "node:fs";
49198
- import { join as join27 } from "node:path";
49003
+ import { existsSync as existsSync28, statSync as statSync8 } from "node:fs";
49004
+ import { join as join26 } from "node:path";
49199
49005
 
49200
49006
  // ../src/issues/store.ts
49201
49007
  import {
49202
- closeSync as closeSync5,
49203
- existsSync as existsSync28,
49008
+ closeSync as closeSync4,
49009
+ existsSync as existsSync27,
49204
49010
  mkdirSync as mkdirSync14,
49205
- openSync as openSync5,
49011
+ openSync as openSync4,
49206
49012
  readdirSync as readdirSync5,
49207
49013
  readFileSync as readFileSync27,
49208
49014
  renameSync as renameSync10,
49209
49015
  statSync as statSync7,
49210
- unlinkSync as unlinkSync11,
49016
+ unlinkSync as unlinkSync10,
49211
49017
  writeFileSync as writeFileSync16,
49212
49018
  writeSync
49213
49019
  } from "node:fs";
49214
- import { join as join26 } from "node:path";
49020
+ import { join as join25 } from "node:path";
49215
49021
  import { randomBytes as randomBytes4 } from "node:crypto";
49216
49022
  import { execSync } from "node:child_process";
49217
49023
 
@@ -49227,8 +49033,8 @@ var SEVERITY_RANK2 = {
49227
49033
  var ISSUES_FILE = "issues.jsonl";
49228
49034
  var ISSUES_LOCK = "issues.lock";
49229
49035
  function readAll(stateDir) {
49230
- const path = join26(stateDir, ISSUES_FILE);
49231
- if (!existsSync28(path))
49036
+ const path = join25(stateDir, ISSUES_FILE);
49037
+ if (!existsSync27(path))
49232
49038
  return [];
49233
49039
  let raw;
49234
49040
  try {
@@ -49264,7 +49070,7 @@ function list(stateDir, opts = {}) {
49264
49070
  });
49265
49071
  }
49266
49072
  function resolve6(stateDir, fingerprint, nowFn = Date.now) {
49267
- if (!existsSync28(join26(stateDir, ISSUES_FILE)))
49073
+ if (!existsSync27(join25(stateDir, ISSUES_FILE)))
49268
49074
  return 0;
49269
49075
  return withLock(stateDir, () => {
49270
49076
  const all = readAll(stateDir);
@@ -49282,7 +49088,7 @@ function resolve6(stateDir, fingerprint, nowFn = Date.now) {
49282
49088
  });
49283
49089
  }
49284
49090
  function writeAll(stateDir, events) {
49285
- const path = join26(stateDir, ISSUES_FILE);
49091
+ const path = join25(stateDir, ISSUES_FILE);
49286
49092
  sweepOrphanTmpFiles(stateDir);
49287
49093
  const tmp = `${path}.tmp-${process.pid}-${randomBytes4(4).toString("hex")}`;
49288
49094
  const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
@@ -49304,11 +49110,11 @@ function sweepOrphanTmpFiles(stateDir) {
49304
49110
  for (const entry of entries) {
49305
49111
  if (!entry.startsWith(TMP_PREFIX))
49306
49112
  continue;
49307
- const tmpPath2 = join26(stateDir, entry);
49113
+ const tmpPath2 = join25(stateDir, entry);
49308
49114
  try {
49309
49115
  const stat = statSync7(tmpPath2);
49310
49116
  if (stat.mtimeMs < cutoff) {
49311
- unlinkSync11(tmpPath2);
49117
+ unlinkSync10(tmpPath2);
49312
49118
  }
49313
49119
  } catch {}
49314
49120
  }
@@ -49316,12 +49122,12 @@ function sweepOrphanTmpFiles(stateDir) {
49316
49122
  var LOCK_RETRY_MS = 25;
49317
49123
  var LOCK_TIMEOUT_MS = 1e4;
49318
49124
  function withLock(stateDir, fn) {
49319
- const lockPath = join26(stateDir, ISSUES_LOCK);
49125
+ const lockPath = join25(stateDir, ISSUES_LOCK);
49320
49126
  const startedAt = Date.now();
49321
49127
  let fd = null;
49322
49128
  while (fd === null) {
49323
49129
  try {
49324
- fd = openSync5(lockPath, "wx");
49130
+ fd = openSync4(lockPath, "wx");
49325
49131
  try {
49326
49132
  writeSync(fd, String(process.pid));
49327
49133
  } catch {}
@@ -49341,10 +49147,10 @@ function withLock(stateDir, fn) {
49341
49147
  return fn();
49342
49148
  } finally {
49343
49149
  try {
49344
- closeSync5(fd);
49150
+ closeSync4(fd);
49345
49151
  } catch {}
49346
49152
  try {
49347
- unlinkSync11(lockPath);
49153
+ unlinkSync10(lockPath);
49348
49154
  } catch {}
49349
49155
  }
49350
49156
  }
@@ -49358,13 +49164,13 @@ function tryStealStaleLock(lockPath) {
49358
49164
  const pid = Number(pidStr);
49359
49165
  if (!Number.isFinite(pid) || pid <= 0) {
49360
49166
  try {
49361
- unlinkSync11(lockPath);
49167
+ unlinkSync10(lockPath);
49362
49168
  } catch {}
49363
49169
  return true;
49364
49170
  }
49365
49171
  if (pid === process.pid) {
49366
49172
  try {
49367
- unlinkSync11(lockPath);
49173
+ unlinkSync10(lockPath);
49368
49174
  } catch {}
49369
49175
  return true;
49370
49176
  }
@@ -49379,7 +49185,7 @@ function tryStealStaleLock(lockPath) {
49379
49185
  return false;
49380
49186
  }
49381
49187
  try {
49382
- unlinkSync11(lockPath);
49188
+ unlinkSync10(lockPath);
49383
49189
  } catch {}
49384
49190
  return true;
49385
49191
  }
@@ -49401,7 +49207,7 @@ function isIssueEvent(v) {
49401
49207
  // issues-watcher.ts
49402
49208
  var DEFAULT_POLL_INTERVAL_MS2 = 2000;
49403
49209
  function startIssuesWatcher(opts) {
49404
- const path = join27(opts.stateDir, ISSUES_FILE);
49210
+ const path = join26(opts.stateDir, ISSUES_FILE);
49405
49211
  const log = opts.log ?? (() => {});
49406
49212
  const intervalMs = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
49407
49213
  const setIntervalFn = opts.setInterval ?? setInterval;
@@ -49449,7 +49255,7 @@ function startIssuesWatcher(opts) {
49449
49255
  };
49450
49256
  }
49451
49257
  function defaultSignatureProvider(path) {
49452
- if (!existsSync29(path))
49258
+ if (!existsSync28(path))
49453
49259
  return null;
49454
49260
  try {
49455
49261
  const stat = statSync8(path);
@@ -49462,7 +49268,7 @@ function defaultReadEvents(stateDir) {
49462
49268
  return readAll(stateDir);
49463
49269
  }
49464
49270
  // permission-title.ts
49465
- import { basename as basename6 } from "node:path";
49271
+ import { basename as basename5 } from "node:path";
49466
49272
  var COMMAND_TITLE_MAX = 40;
49467
49273
  var PATH_TITLE_MAX = 40;
49468
49274
  var DESCRIPTION_LINE_MAX = 240;
@@ -49513,13 +49319,13 @@ function summarizeToolForTitle(toolName, inputPreview) {
49513
49319
  return `${toolName} (${skill})`;
49514
49320
  const command = readString(input, "command");
49515
49321
  if (command)
49516
- return `${toolName}: ${truncate7(command, COMMAND_TITLE_MAX)}`;
49322
+ return `${toolName}: ${truncate6(command, COMMAND_TITLE_MAX)}`;
49517
49323
  const argHint = firstScalarArgHint(input);
49518
49324
  return argHint ? `${toolName} (${argHint})` : toolName;
49519
49325
  }
49520
49326
  case "Bash": {
49521
49327
  const command = readString(input, "command");
49522
- return command ? `${toolName}: ${truncate7(command, COMMAND_TITLE_MAX)}` : toolName;
49328
+ return command ? `${toolName}: ${truncate6(command, COMMAND_TITLE_MAX)}` : toolName;
49523
49329
  }
49524
49330
  case "Read":
49525
49331
  case "Edit":
@@ -49527,17 +49333,17 @@ function summarizeToolForTitle(toolName, inputPreview) {
49527
49333
  case "MultiEdit":
49528
49334
  case "NotebookEdit": {
49529
49335
  const filePath = readString(input, "file_path") ?? readString(input, "notebook_path");
49530
- return filePath ? `${toolName}: ${truncate7(basename6(filePath), PATH_TITLE_MAX)}` : toolName;
49336
+ return filePath ? `${toolName}: ${truncate6(basename5(filePath), PATH_TITLE_MAX)}` : toolName;
49531
49337
  }
49532
49338
  case "Glob":
49533
49339
  case "Grep": {
49534
49340
  const pattern = readString(input, "pattern");
49535
- return pattern ? `${toolName}: ${truncate7(pattern, COMMAND_TITLE_MAX)}` : toolName;
49341
+ return pattern ? `${toolName}: ${truncate6(pattern, COMMAND_TITLE_MAX)}` : toolName;
49536
49342
  }
49537
49343
  case "WebFetch":
49538
49344
  case "WebSearch": {
49539
49345
  const query2 = readString(input, "url") ?? readString(input, "query");
49540
- return query2 ? `${toolName}: ${truncate7(query2, COMMAND_TITLE_MAX)}` : toolName;
49346
+ return query2 ? `${toolName}: ${truncate6(query2, COMMAND_TITLE_MAX)}` : toolName;
49541
49347
  }
49542
49348
  default:
49543
49349
  return toolName;
@@ -49576,7 +49382,7 @@ function firstScalarArgHint(input) {
49576
49382
  if (SKIP.has(key))
49577
49383
  continue;
49578
49384
  if (typeof value === "string" && value.length > 0) {
49579
- return `${key}: ${truncate7(value, INPUT_VALUE_MAX)}`;
49385
+ return `${key}: ${truncate6(value, INPUT_VALUE_MAX)}`;
49580
49386
  }
49581
49387
  if (typeof value === "number" || typeof value === "boolean") {
49582
49388
  return `${key}: ${String(value)}`;
@@ -49608,10 +49414,10 @@ function skillBasenameFromPath(input) {
49608
49414
  return null;
49609
49415
  const trimmed = path.replace(/\/SKILL\.md$/i, "").replace(/\/$/, "");
49610
49416
  const lastSlash = trimmed.lastIndexOf("/");
49611
- const basename7 = lastSlash >= 0 ? trimmed.slice(lastSlash + 1) : trimmed;
49612
- return basename7.length > 0 ? basename7 : null;
49417
+ const basename6 = lastSlash >= 0 ? trimmed.slice(lastSlash + 1) : trimmed;
49418
+ return basename6.length > 0 ? basename6 : null;
49613
49419
  }
49614
- function truncate7(text, max) {
49420
+ function truncate6(text, max) {
49615
49421
  const collapsed = text.replace(/\s+/g, " ").trim();
49616
49422
  if (collapsed.length <= max)
49617
49423
  return collapsed;
@@ -49619,7 +49425,7 @@ function truncate7(text, max) {
49619
49425
  }
49620
49426
 
49621
49427
  // permission-rule.ts
49622
- import { basename as basename7 } from "node:path";
49428
+ import { basename as basename6 } from "node:path";
49623
49429
  function resolveAlwaysAllowRule(toolName, inputPreview) {
49624
49430
  if (!toolName)
49625
49431
  return null;
@@ -49685,12 +49491,12 @@ function skillBasenameFromPath2(input) {
49685
49491
  if (!path)
49686
49492
  return null;
49687
49493
  const trimmed = path.replace(/\/SKILL\.md$/i, "").replace(/\/$/, "");
49688
- return basename7(trimmed) || null;
49494
+ return basename6(trimmed) || null;
49689
49495
  }
49690
49496
 
49691
49497
  // credits-watch.ts
49692
- import { readFileSync as readFileSync28, writeFileSync as writeFileSync17, existsSync as existsSync30, mkdirSync as mkdirSync15 } from "fs";
49693
- import { join as join28 } from "path";
49498
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync17, existsSync as existsSync29, mkdirSync as mkdirSync15 } from "fs";
49499
+ import { join as join27 } from "path";
49694
49500
  var STATE_FILE = "credits-watch.json";
49695
49501
  var FATAL_REASONS = new Set([
49696
49502
  "out_of_credits",
@@ -49702,8 +49508,8 @@ function emptyCreditState() {
49702
49508
  return { lastNotifiedReason: null, lastNotifiedAt: 0 };
49703
49509
  }
49704
49510
  function readClaudeJsonOverage(claudeConfigDir) {
49705
- const path = join28(claudeConfigDir, ".claude.json");
49706
- if (!existsSync30(path))
49511
+ const path = join27(claudeConfigDir, ".claude.json");
49512
+ if (!existsSync29(path))
49707
49513
  return null;
49708
49514
  let raw;
49709
49515
  try {
@@ -49731,7 +49537,7 @@ function evaluateCreditState(args) {
49731
49537
  if (!currentIsFatal && prevIsFatal) {
49732
49538
  return {
49733
49539
  kind: "notify",
49734
- message: `\u2705 <b>${escapeHtml11(agentName3)}</b>: credits restored \u2014 agent should resume normal operation.`,
49540
+ message: `\u2705 <b>${escapeHtml10(agentName3)}</b>: credits restored \u2014 agent should resume normal operation.`,
49735
49541
  newState: { lastNotifiedReason: null, lastNotifiedAt: now },
49736
49542
  transition: "exited"
49737
49543
  };
@@ -49760,12 +49566,12 @@ function evaluateCreditState(args) {
49760
49566
  function buildEntryMessage(agentName3, reason) {
49761
49567
  const desc = humanizeReason(reason);
49762
49568
  return [
49763
- `\u26a0\ufe0f <b>${escapeHtml11(agentName3)}</b>: ${desc}`,
49569
+ `\u26a0\ufe0f <b>${escapeHtml10(agentName3)}</b>: ${desc}`,
49764
49570
  ``,
49765
49571
  `Cron tasks and inbound replies will fail until this is resolved. Check`,
49766
49572
  `your subscription or pre-paid usage at <a href="https://console.anthropic.com">console.anthropic.com</a>.`,
49767
49573
  ``,
49768
- `<i>Source: Claude CLI cache (cachedExtraUsageDisabledReason=${escapeHtml11(reason)})</i>`
49574
+ `<i>Source: Claude CLI cache (cachedExtraUsageDisabledReason=${escapeHtml10(reason)})</i>`
49769
49575
  ].join(`
49770
49576
  `);
49771
49577
  }
@@ -49783,12 +49589,12 @@ function humanizeReason(reason) {
49783
49589
  return `usage disabled (${reason})`;
49784
49590
  }
49785
49591
  }
49786
- function escapeHtml11(s) {
49592
+ function escapeHtml10(s) {
49787
49593
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
49788
49594
  }
49789
49595
  function loadCreditState(stateDir) {
49790
- const path = join28(stateDir, STATE_FILE);
49791
- if (!existsSync30(path))
49596
+ const path = join27(stateDir, STATE_FILE);
49597
+ if (!existsSync29(path))
49792
49598
  return emptyCreditState();
49793
49599
  try {
49794
49600
  const raw = readFileSync28(path, "utf-8");
@@ -49804,54 +49610,54 @@ function loadCreditState(stateDir) {
49804
49610
  }
49805
49611
  function saveCreditState(stateDir, state4) {
49806
49612
  mkdirSync15(stateDir, { recursive: true });
49807
- const path = join28(stateDir, STATE_FILE);
49613
+ const path = join27(stateDir, STATE_FILE);
49808
49614
  writeFileSync17(path, JSON.stringify(state4, null, 2) + `
49809
49615
  `, { mode: 384 });
49810
49616
  }
49811
49617
 
49812
49618
  // gateway/turn-active-marker.ts
49813
49619
  import {
49814
- closeSync as closeSync6,
49815
- existsSync as existsSync31,
49620
+ closeSync as closeSync5,
49621
+ existsSync as existsSync30,
49816
49622
  mkdirSync as mkdirSync16,
49817
- openSync as openSync6,
49623
+ openSync as openSync5,
49818
49624
  readFileSync as readFileSync29,
49819
49625
  statSync as statSync9,
49820
- unlinkSync as unlinkSync12,
49626
+ unlinkSync as unlinkSync11,
49821
49627
  utimesSync as utimesSync2,
49822
49628
  writeFileSync as writeFileSync18
49823
49629
  } from "node:fs";
49824
- import { join as join29 } from "node:path";
49630
+ import { join as join28 } from "node:path";
49825
49631
  var TURN_ACTIVE_MARKER_FILE2 = "turn-active.json";
49826
49632
  function writeTurnActiveMarker(stateDir, marker) {
49827
49633
  try {
49828
49634
  mkdirSync16(stateDir, { recursive: true });
49829
- writeFileSync18(join29(stateDir, TURN_ACTIVE_MARKER_FILE2), JSON.stringify(marker, null, 2) + `
49635
+ writeFileSync18(join28(stateDir, TURN_ACTIVE_MARKER_FILE2), JSON.stringify(marker, null, 2) + `
49830
49636
  `, { mode: 384 });
49831
49637
  } catch {}
49832
49638
  }
49833
49639
  function touchTurnActiveMarker2(stateDir) {
49834
- const path = join29(stateDir, TURN_ACTIVE_MARKER_FILE2);
49835
- if (!existsSync31(path))
49640
+ const path = join28(stateDir, TURN_ACTIVE_MARKER_FILE2);
49641
+ if (!existsSync30(path))
49836
49642
  return;
49837
49643
  const now = new Date;
49838
49644
  try {
49839
49645
  utimesSync2(path, now, now);
49840
49646
  } catch {
49841
49647
  try {
49842
- const fd = openSync6(path, "r+");
49843
- closeSync6(fd);
49648
+ const fd = openSync5(path, "r+");
49649
+ closeSync5(fd);
49844
49650
  } catch {}
49845
49651
  }
49846
49652
  }
49847
49653
  function removeTurnActiveMarker(stateDir) {
49848
49654
  try {
49849
- unlinkSync12(join29(stateDir, TURN_ACTIVE_MARKER_FILE2));
49655
+ unlinkSync11(join28(stateDir, TURN_ACTIVE_MARKER_FILE2));
49850
49656
  } catch {}
49851
49657
  }
49852
49658
  function sweepStaleTurnActiveMarker(stateDir, opts) {
49853
- const path = join29(stateDir, TURN_ACTIVE_MARKER_FILE2);
49854
- if (!existsSync31(path))
49659
+ const path = join28(stateDir, TURN_ACTIVE_MARKER_FILE2);
49660
+ if (!existsSync30(path))
49855
49661
  return false;
49856
49662
  const now = opts.now ?? Date.now();
49857
49663
  try {
@@ -49865,7 +49671,7 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
49865
49671
  try {
49866
49672
  payload = readFileSync29(path, "utf8");
49867
49673
  } catch {}
49868
- unlinkSync12(path);
49674
+ unlinkSync11(path);
49869
49675
  if (opts.onRemove) {
49870
49676
  try {
49871
49677
  opts.onRemove({
@@ -49882,10 +49688,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
49882
49688
  }
49883
49689
 
49884
49690
  // ../src/build-info.ts
49885
- var VERSION = "0.13.57";
49886
- var COMMIT_SHA = "bed7cd14";
49887
- var COMMIT_DATE = "2026-05-27T21:24:41Z";
49888
- var LATEST_PR = 1925;
49691
+ var VERSION = "0.13.59";
49692
+ var COMMIT_SHA = "0f0b953e";
49693
+ var COMMIT_DATE = "2026-05-28T00:31:56Z";
49694
+ var LATEST_PR = 1936;
49889
49695
  var COMMITS_AHEAD_OF_TAG = 0;
49890
49696
 
49891
49697
  // gateway/boot-version.ts
@@ -49959,11 +49765,11 @@ init_peercred();
49959
49765
  import * as net4 from "node:net";
49960
49766
  import * as fs2 from "node:fs";
49961
49767
  import { homedir as homedir11 } from "node:os";
49962
- import { join as join30 } from "node:path";
49768
+ import { join as join29 } from "node:path";
49963
49769
  var DEFAULT_TIMEOUT_MS4 = 2000;
49964
49770
  var UNLOCK_TIMEOUT_MS = 30000;
49965
- var LEGACY_SOCKET_PATH2 = join30(homedir11(), ".switchroom", "vault-broker.sock");
49966
- var OPERATOR_SOCKET_PATH2 = join30(homedir11(), ".switchroom", "broker-operator", "sock");
49771
+ var LEGACY_SOCKET_PATH2 = join29(homedir11(), ".switchroom", "vault-broker.sock");
49772
+ var OPERATOR_SOCKET_PATH2 = join29(homedir11(), ".switchroom", "broker-operator", "sock");
49967
49773
  function defaultBrokerSocketPath2() {
49968
49774
  if (fs2.existsSync(OPERATOR_SOCKET_PATH2))
49969
49775
  return OPERATOR_SOCKET_PATH2;
@@ -50186,7 +49992,7 @@ function resolveVaultApprovalPosture(broker) {
50186
49992
 
50187
49993
  // registry/turns-schema.ts
50188
49994
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync17 } from "fs";
50189
- import { join as join31 } from "path";
49995
+ import { join as join30 } from "path";
50190
49996
  var DatabaseClass2 = null;
50191
49997
  function loadDatabaseClass2() {
50192
49998
  if (DatabaseClass2 != null)
@@ -50245,9 +50051,9 @@ function applySchema(db2) {
50245
50051
  }
50246
50052
  function openTurnsDb(agentDir) {
50247
50053
  const Database = loadDatabaseClass2();
50248
- const dir = join31(agentDir, "telegram");
50054
+ const dir = join30(agentDir, "telegram");
50249
50055
  mkdirSync17(dir, { recursive: true, mode: 448 });
50250
- const path = join31(dir, "registry.db");
50056
+ const path = join30(dir, "registry.db");
50251
50057
  const db2 = new Database(path, { create: true });
50252
50058
  applySchema(db2);
50253
50059
  try {
@@ -50388,11 +50194,11 @@ installGlobalErrorHandlers();
50388
50194
  process.on("beforeExit", () => {
50389
50195
  shutdownAnalytics();
50390
50196
  });
50391
- var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join33(homedir12(), ".claude", "channels", "telegram");
50392
- var ACCESS_FILE = join33(STATE_DIR, "access.json");
50393
- var APPROVED_DIR = join33(STATE_DIR, "approved");
50394
- var ENV_FILE = join33(STATE_DIR, ".env");
50395
- var INBOX_DIR = join33(STATE_DIR, "inbox");
50197
+ var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join32(homedir12(), ".claude", "channels", "telegram");
50198
+ var ACCESS_FILE = join32(STATE_DIR, "access.json");
50199
+ var APPROVED_DIR = join32(STATE_DIR, "approved");
50200
+ var ENV_FILE = join32(STATE_DIR, ".env");
50201
+ var INBOX_DIR = join32(STATE_DIR, "inbox");
50396
50202
  function triggerSelfRestart(targetAgent, reason, delayMs = 300) {
50397
50203
  const isDocker = process.env.SWITCHROOM_RUNTIME === "docker";
50398
50204
  const selfAgent = process.env.SWITCHROOM_AGENT_NAME;
@@ -50583,7 +50389,7 @@ function assertSendable(f) {
50583
50389
  } catch {
50584
50390
  throw new Error(`refusing to send file \u2014 cannot resolve real path: ${f}`);
50585
50391
  }
50586
- const inbox = join33(stateReal, "inbox");
50392
+ const inbox = join32(stateReal, "inbox");
50587
50393
  if (real.startsWith(stateReal + sep3) && !real.startsWith(inbox + sep3)) {
50588
50394
  throw new Error(`refusing to send channel state: ${f}`);
50589
50395
  }
@@ -50689,7 +50495,7 @@ var HISTORY_ENABLED = HISTORY_ACCESS.historyEnabled !== false;
50689
50495
  if (HISTORY_ENABLED) {
50690
50496
  try {
50691
50497
  initHistory(STATE_DIR, HISTORY_ACCESS.historyRetentionDays ?? 30);
50692
- process.stderr.write(`telegram gateway: history capture enabled at ${join33(STATE_DIR, "history.db")}
50498
+ process.stderr.write(`telegram gateway: history capture enabled at ${join32(STATE_DIR, "history.db")}
50693
50499
  `);
50694
50500
  } catch (err) {
50695
50501
  process.stderr.write(`telegram gateway: history init failed (${err.message}) \u2014 capture disabled
@@ -50706,10 +50512,10 @@ try {
50706
50512
  process.stderr.write(`telegram gateway: turn-registry boot-reaper stamped ${reaped} orphaned turn(s) as ended_via='restart'
50707
50513
  `);
50708
50514
  } else {
50709
- process.stderr.write(`telegram gateway: turn-registry initialized at ${join33(agentDir, "telegram", "registry.db")}
50515
+ process.stderr.write(`telegram gateway: turn-registry initialized at ${join32(agentDir, "telegram", "registry.db")}
50710
50516
  `);
50711
50517
  }
50712
- const pendingEnvPath = join33(agentDir, ".pending-turn.env");
50518
+ const pendingEnvPath = join32(agentDir, ".pending-turn.env");
50713
50519
  try {
50714
50520
  const pending2 = findMostRecentInterruptedTurn(turnsDb);
50715
50521
  if (pending2 != null) {
@@ -50729,7 +50535,7 @@ try {
50729
50535
  renameSync12(pendingEnvTmp, pendingEnvPath);
50730
50536
  process.stderr.write(`telegram gateway: pending-turn env written to ${pendingEnvPath} turnKey=${pending2.turn_key} endedVia=${pending2.ended_via ?? "open"}
50731
50537
  `);
50732
- } else if (existsSync35(pendingEnvPath)) {
50538
+ } else if (existsSync34(pendingEnvPath)) {
50733
50539
  rmSync4(pendingEnvPath, { force: true });
50734
50540
  process.stderr.write(`telegram gateway: pending-turn env cleared (clean previous shutdown)
50735
50541
  `);
@@ -50783,7 +50589,7 @@ function checkApprovals() {
50783
50589
  return;
50784
50590
  }
50785
50591
  for (const senderId of files) {
50786
- const file = join33(APPROVED_DIR, senderId);
50592
+ const file = join32(APPROVED_DIR, senderId);
50787
50593
  bot.api.sendMessage(senderId, "Paired! Say hi to Claude.").then(() => rmSync4(file, { force: true }), (err) => {
50788
50594
  process.stderr.write(`telegram gateway: failed to send approval confirm: ${err}
50789
50595
  `);
@@ -51660,11 +51466,11 @@ var unpinProgressCardForChat = null;
51660
51466
  var getPinnedProgressCardMessageId = null;
51661
51467
  var completeProgressCardTurn = null;
51662
51468
  var subagentWatcher = null;
51663
- var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join33(STATE_DIR, "gateway.sock");
51469
+ var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join32(STATE_DIR, "gateway.sock");
51664
51470
  mkdirSync21(STATE_DIR, { recursive: true, mode: 448 });
51665
- var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ?? join33(STATE_DIR, "gateway.pid.json");
51666
- var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ?? join33(STATE_DIR, "gateway-session.json");
51667
- var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join33(STATE_DIR, "clean-shutdown.json");
51471
+ var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ?? join32(STATE_DIR, "gateway.pid.json");
51472
+ var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ?? join32(STATE_DIR, "gateway-session.json");
51473
+ var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join32(STATE_DIR, "clean-shutdown.json");
51668
51474
  var GATEWAY_STARTED_AT_MS = Date.now();
51669
51475
  var BOOT_CARD_ENABLED = process.env.SWITCHROOM_BOOT_CARD !== "false";
51670
51476
  var activeBootCard = null;
@@ -51693,7 +51499,7 @@ function ensureIssuesCard(chatId, threadId) {
51693
51499
  bot: botApi,
51694
51500
  log: (msg) => process.stderr.write(`telegram gateway: ${msg}
51695
51501
  `),
51696
- persistPath: join33(stateDir, "issues-card.json")
51502
+ persistPath: join32(stateDir, "issues-card.json")
51697
51503
  });
51698
51504
  activeIssuesWatcher = startIssuesWatcher({
51699
51505
  stateDir,
@@ -51862,13 +51668,13 @@ startTimer2({
51862
51668
  }
51863
51669
  });
51864
51670
  var inboundSpool = STATIC ? undefined : createInboundSpool({
51865
- path: join33(STATE_DIR, "inbound-spool.jsonl"),
51671
+ path: join32(STATE_DIR, "inbound-spool.jsonl"),
51866
51672
  fs: {
51867
51673
  appendFileSync: (p, d) => appendFileSync3(p, d),
51868
51674
  readFileSync: (p) => readFileSync32(p, "utf8"),
51869
51675
  writeFileSync: (p, d) => writeFileSync21(p, d),
51870
51676
  renameSync: (a, b) => renameSync12(a, b),
51871
- existsSync: (p) => existsSync35(p),
51677
+ existsSync: (p) => existsSync34(p),
51872
51678
  statSizeSync: (p) => statSync13(p).size
51873
51679
  }
51874
51680
  });
@@ -52096,7 +51902,7 @@ ${reminder}
52096
51902
  noteSubagentDispatch(key);
52097
51903
  }
52098
51904
  if (ev.toolUseId != null && ev.toolUseId.length > 0 && !isTelegramSurfaceTool(ev.toolName)) {
52099
- const label = toolLabel2(ev.toolName, ev.input, undefined, ev.precomputedLabel);
51905
+ const label = toolLabel(ev.toolName, ev.input, undefined, ev.precomputedLabel);
52100
51906
  noteToolStart(key, ev.toolUseId, ev.toolName, label.length > 0 ? label : null, Date.now());
52101
51907
  const evInput = ev.input;
52102
51908
  if (ev.toolName === "Agent" || ev.toolName === "Task" || ev.toolName === "Bash" && evInput?.run_in_background === true) {
@@ -52681,12 +52487,6 @@ ${url}`;
52681
52487
  });
52682
52488
  noteOutbound(statusKey(chat_id, threadId), Date.now());
52683
52489
  noteOutbound2(statusKey(chat_id, threadId), Date.now());
52684
- try {
52685
- markAckSent();
52686
- } catch (err) {
52687
- process.stderr.write(`telegram gateway: markAckSent failed: ${err}
52688
- `);
52689
- }
52690
52490
  if (isFinalAnswerReply({ text: rawText, disableNotification })) {
52691
52491
  clearSilentEndState(statusKey(chat_id, threadId));
52692
52492
  }
@@ -53014,12 +52814,6 @@ async function executeStreamReply(args) {
53014
52814
  const sKey = statusKey(streamChatId, streamThreadId);
53015
52815
  noteOutbound(sKey, Date.now());
53016
52816
  noteOutbound2(sKey, Date.now());
53017
- try {
53018
- markAckSent();
53019
- } catch (err) {
53020
- process.stderr.write(`telegram gateway: markAckSent (stream_reply) failed: ${err}
53021
- `);
53022
- }
53023
52817
  if (isFinalAnswerReply({
53024
52818
  text: args.text ?? "",
53025
52819
  disableNotification: args.disable_notification === true,
@@ -53370,10 +53164,10 @@ async function executeSendGif(rawArgs) {
53370
53164
  };
53371
53165
  }
53372
53166
  async function publishToTelegraph(text, shortName, authorName) {
53373
- const accountPath = join33(STATE_DIR, "telegraph-account.json");
53167
+ const accountPath = join32(STATE_DIR, "telegraph-account.json");
53374
53168
  let account = null;
53375
53169
  try {
53376
- if (existsSync35(accountPath)) {
53170
+ if (existsSync34(accountPath)) {
53377
53171
  const raw = readFileSync32(accountPath, "utf-8");
53378
53172
  const parsed = JSON.parse(raw);
53379
53173
  if (parsed.shortName && parsed.accessToken) {
@@ -53859,6 +53653,74 @@ function closeProgressLane(chatId, threadId) {
53859
53653
  }
53860
53654
  }
53861
53655
  }
53656
+ async function drainActivitySummary(turn) {
53657
+ try {
53658
+ while (turn.activityPendingRender !== turn.activityLastSentRender) {
53659
+ const target = turn.activityPendingRender;
53660
+ if (target == null)
53661
+ break;
53662
+ const html = `<i>${target}</i>`;
53663
+ const chat = turn.sessionChatId;
53664
+ const thread = turn.sessionThreadId;
53665
+ const useDraft = turn.isDm && thread == null && sendMessageDraftFn != null;
53666
+ try {
53667
+ if (useDraft) {
53668
+ if (turn.activityDraftId == null) {
53669
+ turn.activityDraftId = allocateDraftId();
53670
+ }
53671
+ const draftId = turn.activityDraftId;
53672
+ await sendMessageDraftFn(chat, draftId, html, undefined);
53673
+ } else if (turn.activityMessageId == null) {
53674
+ const sent = await robustApiCall(() => bot.api.sendMessage(chat, html, {
53675
+ ...thread != null ? { message_thread_id: thread } : {},
53676
+ parse_mode: "HTML",
53677
+ disable_notification: true
53678
+ }), { chat_id: chat, ...thread != null ? { threadId: thread } : {}, verb: "activity-summary.send" });
53679
+ turn.activityMessageId = sent.message_id;
53680
+ } else {
53681
+ const id = turn.activityMessageId;
53682
+ await robustApiCall(() => bot.api.editMessageText(chat, id, html, { parse_mode: "HTML" }), { chat_id: chat, ...thread != null ? { threadId: thread } : {}, verb: "activity-summary.edit" });
53683
+ }
53684
+ turn.activityLastSentRender = target;
53685
+ } catch (err) {
53686
+ const msg = err instanceof Error ? err.message : String(err);
53687
+ if (!msg.includes("message is not modified")) {
53688
+ process.stderr.write(`telegram gateway: activity-summary drain failed: ${msg}
53689
+ `);
53690
+ }
53691
+ turn.activityLastSentRender = target;
53692
+ }
53693
+ }
53694
+ } finally {
53695
+ turn.activityInFlight = null;
53696
+ }
53697
+ }
53698
+ function clearActivitySummary(turn) {
53699
+ const chat = turn.sessionChatId;
53700
+ const thread = turn.sessionThreadId;
53701
+ const inFlight = turn.activityInFlight ?? Promise.resolve();
53702
+ inFlight.then(async () => {
53703
+ if (turn.activityDraftId != null && sendMessageDraftFn != null) {
53704
+ const draftId = turn.activityDraftId;
53705
+ turn.activityDraftId = null;
53706
+ try {
53707
+ await sendMessageDraftFn(chat, draftId, "", undefined);
53708
+ } catch (err) {
53709
+ process.stderr.write(`telegram gateway: activity-summary draft-clear failed: ${err}
53710
+ `);
53711
+ }
53712
+ } else if (turn.activityMessageId != null) {
53713
+ const id = turn.activityMessageId;
53714
+ turn.activityMessageId = null;
53715
+ try {
53716
+ await robustApiCall(() => bot.api.deleteMessage(chat, id), { chat_id: chat, ...thread != null ? { threadId: thread } : {}, verb: "activity-summary.delete" });
53717
+ } catch (err) {
53718
+ process.stderr.write(`telegram gateway: activity-summary delete failed: ${err}
53719
+ `);
53720
+ }
53721
+ }
53722
+ });
53723
+ }
53862
53724
  function handleSessionEvent(ev) {
53863
53725
  switch (ev.kind) {
53864
53726
  case "enqueue": {
@@ -53866,7 +53728,6 @@ function handleSessionEvent(ev) {
53866
53728
  if (ev.chatId) {
53867
53729
  const enqThreadId = ev.threadId != null ? Number(ev.threadId) : undefined;
53868
53730
  clearPending(statusKey(ev.chatId, enqThreadId), "handback");
53869
- clearAckSent();
53870
53731
  }
53871
53732
  if (ev.chatId) {
53872
53733
  const prior = currentTurn;
@@ -53892,7 +53753,12 @@ function handleSessionEvent(ev) {
53892
53753
  lastAssistantMsgId: null,
53893
53754
  lastAssistantDone: false,
53894
53755
  toolCallCount: 0,
53895
- intentSurfaceFired: false,
53756
+ toolActivity: makeEmptyActivityState(),
53757
+ activityMessageId: null,
53758
+ activityDraftId: null,
53759
+ activityInFlight: null,
53760
+ activityPendingRender: null,
53761
+ activityLastSentRender: null,
53896
53762
  answerStream: null,
53897
53763
  isDm: isDmChatId(ev.chatId)
53898
53764
  };
@@ -53952,37 +53818,23 @@ function handleSessionEvent(ev) {
53952
53818
  const ctrl = activeStatusReactions.get(statusKey(turn.sessionChatId, turn.sessionThreadId));
53953
53819
  const name = ev.toolName;
53954
53820
  if (isTelegramReplyTool(name)) {
53821
+ const wasFirstReply = !turn.replyCalled;
53955
53822
  turn.replyCalled = true;
53956
53823
  if (turn.orphanedReplyTimeoutId != null) {
53957
53824
  clearTimeout(turn.orphanedReplyTimeoutId);
53958
53825
  turn.orphanedReplyTimeoutId = null;
53959
53826
  }
53827
+ if (wasFirstReply) {
53828
+ clearActivitySummary(turn);
53829
+ }
53960
53830
  }
53961
- if (!turn.replyCalled && !turn.intentSurfaceFired && !isTelegramSurfaceTool(name)) {
53962
- turn.intentSurfaceFired = true;
53963
- const surface = deriveIntentSurface(name, ev.input, ev.precomputedLabel);
53964
- if (surface.text != null) {
53965
- try {
53966
- markAckSent();
53967
- } catch (err) {
53968
- process.stderr.write(`telegram gateway: intent-surface markAckSent failed: ${err}
53969
- `);
53831
+ if (!turn.replyCalled && !isTelegramSurfaceTool(name)) {
53832
+ const rendered = registerAndRender(turn.toolActivity, name);
53833
+ if (rendered != null) {
53834
+ turn.activityPendingRender = rendered;
53835
+ if (turn.activityInFlight == null) {
53836
+ turn.activityInFlight = drainActivitySummary(turn);
53970
53837
  }
53971
- const surfaceChat = turn.sessionChatId;
53972
- const surfaceThread = turn.sessionThreadId;
53973
- const surfaceText = surface.text;
53974
- (async () => {
53975
- try {
53976
- await robustApiCall(() => bot.api.sendMessage(surfaceChat, surfaceText, {
53977
- ...surfaceThread != null ? { message_thread_id: surfaceThread } : {},
53978
- parse_mode: "HTML",
53979
- disable_notification: true
53980
- }), { chat_id: surfaceChat, ...surfaceThread != null ? { threadId: surfaceThread } : {}, verb: "intent-surface" });
53981
- } catch (err) {
53982
- process.stderr.write(`telegram gateway: intent-surface send failed: ${err}
53983
- `);
53984
- }
53985
- })();
53986
53838
  }
53987
53839
  }
53988
53840
  if (!ctrl)
@@ -55339,7 +55191,7 @@ function getMyAgentName() {
55339
55191
  const fromEnv = process.env.SWITCHROOM_AGENT_NAME;
55340
55192
  if (fromEnv && fromEnv.trim().length > 0)
55341
55193
  return fromEnv.trim();
55342
- return basename8(process.cwd());
55194
+ return basename7(process.cwd());
55343
55195
  }
55344
55196
  function isSelfTargetingCommand(name) {
55345
55197
  if (name === "all")
@@ -55352,7 +55204,7 @@ function restartMarkerPath() {
55352
55204
  const agentDir = resolveAgentDirFromEnv();
55353
55205
  if (!agentDir)
55354
55206
  return null;
55355
- return join33(agentDir, "restart-pending.json");
55207
+ return join32(agentDir, "restart-pending.json");
55356
55208
  }
55357
55209
  function writeRestartMarker(marker) {
55358
55210
  const p = restartMarkerPath();
@@ -55476,7 +55328,7 @@ var _dockerReachable;
55476
55328
  function isDockerReachable() {
55477
55329
  if (_dockerReachable !== undefined)
55478
55330
  return _dockerReachable;
55479
- if (!existsSync35("/var/run/docker.sock")) {
55331
+ if (!existsSync34("/var/run/docker.sock")) {
55480
55332
  _dockerReachable = false;
55481
55333
  return _dockerReachable;
55482
55334
  }
@@ -55493,11 +55345,11 @@ function _resetDockerReachableCache() {
55493
55345
  }
55494
55346
  function spawnSwitchroomDetached(args, onFailure) {
55495
55347
  const fullArgs = SWITCHROOM_CONFIG ? ["--config", SWITCHROOM_CONFIG, ...args] : args;
55496
- const logPath = join33(STATE_DIR, "detached-spawn.log");
55348
+ const logPath = join32(STATE_DIR, "detached-spawn.log");
55497
55349
  let outFd = null;
55498
55350
  try {
55499
55351
  mkdirSync21(STATE_DIR, { recursive: true });
55500
- outFd = openSync9(logPath, "a");
55352
+ outFd = openSync8(logPath, "a");
55501
55353
  writeFileSync21(logPath, `
55502
55354
  [${new Date().toISOString()}] spawn ${SWITCHROOM_CLI} ${fullArgs.join(" ")}
55503
55355
  `, { flag: "a" });
@@ -55512,7 +55364,7 @@ function spawnSwitchroomDetached(args, onFailure) {
55512
55364
  });
55513
55365
  if (outFd != null) {
55514
55366
  try {
55515
- closeSync9(outFd);
55367
+ closeSync8(outFd);
55516
55368
  } catch {}
55517
55369
  }
55518
55370
  if (onFailure) {
@@ -55866,8 +55718,8 @@ bot.use(async (ctx, next) => {
55866
55718
  });
55867
55719
  function readRecentDenialsForAgent(agentName3, windowMs, limit) {
55868
55720
  try {
55869
- const auditPath = join33(homedir12(), ".switchroom", "vault-audit.log");
55870
- if (!existsSync35(auditPath))
55721
+ const auditPath = join32(homedir12(), ".switchroom", "vault-audit.log");
55722
+ if (!existsSync34(auditPath))
55871
55723
  return [];
55872
55724
  const raw = readFileSync32(auditPath, "utf8");
55873
55725
  return recentDenialsFromAuditLog(raw, { agentName: agentName3, windowMs, limit });
@@ -55920,7 +55772,7 @@ async function buildAgentMetadata(agentName3) {
55920
55772
  try {
55921
55773
  const agentDir = resolveAgentDirFromEnv();
55922
55774
  if (agentDir) {
55923
- const raw = readFileSync32(join33(agentDir, ".claude", ".claude.json"), "utf8");
55775
+ const raw = readFileSync32(join32(agentDir, ".claude", ".claude.json"), "utf8");
55924
55776
  claudeJson = JSON.parse(raw);
55925
55777
  }
55926
55778
  } catch {}
@@ -56134,10 +55986,10 @@ bot.command("restart", async (ctx) => {
56134
55986
  function flushAgentHandoff(agentDir) {
56135
55987
  let removed = 0;
56136
55988
  for (const fname of [".handoff.md", ".handoff-topic"]) {
56137
- const p = join33(agentDir, fname);
55989
+ const p = join32(agentDir, fname);
56138
55990
  try {
56139
- if (existsSync35(p)) {
56140
- unlinkSync15(p);
55991
+ if (existsSync34(p)) {
55992
+ unlinkSync14(p);
56141
55993
  removed++;
56142
55994
  }
56143
55995
  } catch (err) {
@@ -56192,7 +56044,7 @@ async function handleNewOrResetCommand(ctx, kind) {
56192
56044
  writeRestartMarker({ chat_id: chatId, thread_id: threadId ?? null, ack_message_id: ackId, ts: Date.now() });
56193
56045
  if (agentDir != null) {
56194
56046
  try {
56195
- writeFileSync21(join33(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
56047
+ writeFileSync21(join32(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
56196
56048
  `, "utf8");
56197
56049
  } catch (err) {
56198
56050
  process.stderr.write(`telegram gateway: failed to write force-fresh marker: ${err}
@@ -56553,14 +56405,14 @@ bot.command("interrupt", async (ctx) => {
56553
56405
  var lockoutOps = {
56554
56406
  readFileSync: (p, enc) => readFileSync32(p, enc),
56555
56407
  writeFileSync: (p, data, opts) => writeFileSync21(p, data, opts),
56556
- existsSync: (p) => existsSync35(p),
56408
+ existsSync: (p) => existsSync34(p),
56557
56409
  mkdirSync: (p, opts) => mkdirSync21(p, opts),
56558
- joinPath: (...parts) => join33(...parts)
56410
+ joinPath: (...parts) => join32(...parts)
56559
56411
  };
56560
56412
  var FLEET_FALLBACK_DEDUP_MS = 30000;
56561
56413
  function isAuthBrokerSocketReachable() {
56562
56414
  try {
56563
- return existsSync35(resolveAuthBrokerSocketPath2());
56415
+ return existsSync34(resolveAuthBrokerSocketPath2());
56564
56416
  } catch {
56565
56417
  return false;
56566
56418
  }
@@ -56621,7 +56473,7 @@ async function runCreditWatch() {
56621
56473
  if (!agentDir)
56622
56474
  return;
56623
56475
  const agentName3 = getMyAgentName();
56624
- const claudeConfigDir = join33(agentDir, ".claude");
56476
+ const claudeConfigDir = join32(agentDir, ".claude");
56625
56477
  const stateDir = STATE_DIR;
56626
56478
  const reason = readClaudeJsonOverage(claudeConfigDir);
56627
56479
  const prev = loadCreditState(stateDir);
@@ -56831,9 +56683,9 @@ async function handleVaultRecentDenialCallback(ctx, data) {
56831
56683
  return;
56832
56684
  }
56833
56685
  const { token, id } = result;
56834
- const tokenPath = join33(homedir12(), ".switchroom", "agents", agentName3, ".vault-token");
56686
+ const tokenPath = join32(homedir12(), ".switchroom", "agents", agentName3, ".vault-token");
56835
56687
  try {
56836
- mkdirSync21(join33(homedir12(), ".switchroom", "agents", agentName3), { recursive: true });
56688
+ mkdirSync21(join32(homedir12(), ".switchroom", "agents", agentName3), { recursive: true });
56837
56689
  writeFileSync21(tokenPath, token, { mode: 384 });
56838
56690
  } catch (err) {
56839
56691
  await switchroomReply(ctx, `<b>Grant created (${escapeHtmlForTg(id)}) but token write failed:</b> ${escapeHtmlForTg(String(err))}
@@ -56910,9 +56762,9 @@ async function performVaultAccessApproval(ctx, pending2, stageId, senderId, atte
56910
56762
  return;
56911
56763
  }
56912
56764
  const { token, id } = result;
56913
- const tokenPath = join33(homedir12(), ".switchroom", "agents", pending2.agent, ".vault-token");
56765
+ const tokenPath = join32(homedir12(), ".switchroom", "agents", pending2.agent, ".vault-token");
56914
56766
  try {
56915
- mkdirSync21(join33(homedir12(), ".switchroom", "agents", pending2.agent), { recursive: true });
56767
+ mkdirSync21(join32(homedir12(), ".switchroom", "agents", pending2.agent), { recursive: true });
56916
56768
  writeFileSync21(tokenPath, token, { mode: 384 });
56917
56769
  } catch (err) {
56918
56770
  await switchroomReply(ctx, `<b>Grant created (${escapeHtmlForTg(id)}) but token write failed:</b> ${escapeHtmlForTg(String(err))}
@@ -57388,9 +57240,9 @@ async function executeGrantWizard(ctx, chatId, state4) {
57388
57240
  return;
57389
57241
  }
57390
57242
  const { token, id } = result;
57391
- const tokenPath = join33(homedir12(), ".switchroom", "agents", state4.agent, ".vault-token");
57243
+ const tokenPath = join32(homedir12(), ".switchroom", "agents", state4.agent, ".vault-token");
57392
57244
  try {
57393
- mkdirSync21(join33(homedir12(), ".switchroom", "agents", state4.agent), { recursive: true });
57245
+ mkdirSync21(join32(homedir12(), ".switchroom", "agents", state4.agent), { recursive: true });
57394
57246
  writeFileSync21(tokenPath, token, { mode: 384 });
57395
57247
  } catch (err) {
57396
57248
  await switchroomReply(ctx, `<b>Grant created but token write failed:</b> ${escapeHtmlForTg(String(err))}`, { html: true });
@@ -58248,7 +58100,7 @@ bot.command("usage", async (ctx) => {
58248
58100
  await switchroomReply(ctx, "<b>/usage:</b> cannot resolve agent dir.", { html: true });
58249
58101
  return;
58250
58102
  }
58251
- const result = await fetchQuota2({ claudeConfigDir: join33(agentDir, ".claude") });
58103
+ const result = await fetchQuota2({ claudeConfigDir: join32(agentDir, ".claude") });
58252
58104
  if (!result.ok) {
58253
58105
  await switchroomReply(ctx, `<b>/usage:</b> ${escapeHtmlForTg(result.reason)}`, { html: true });
58254
58106
  return;
@@ -58793,7 +58645,7 @@ async function maybeTranscribeVoice(fileId, mimeType, language) {
58793
58645
  let apiKey = null;
58794
58646
  try {
58795
58647
  const path = __require("path").join(__require("os").homedir(), ".switchroom", "openai-api-key");
58796
- if (existsSync35(path)) {
58648
+ if (existsSync34(path)) {
58797
58649
  apiKey = readFileSync32(path, "utf-8").trim();
58798
58650
  }
58799
58651
  } catch (err) {
@@ -59654,7 +59506,7 @@ var didOneTimeSetup = false;
59654
59506
  agentName: agentDisplayName,
59655
59507
  agentSlug,
59656
59508
  version: formatBootVersion(),
59657
- agentDir: agentDir ?? join33(homedir12(), ".switchroom", "agents", agentSlug),
59509
+ agentDir: agentDir ?? join32(homedir12(), ".switchroom", "agents", agentSlug),
59658
59510
  gatewayInfo: { pid: process.pid, startedAtMs: GATEWAY_STARTED_AT_MS },
59659
59511
  restartReason: reason,
59660
59512
  restartAgeMs: markerAgeMs,