switchroom 0.13.57 → 0.13.58

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.
@@ -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
  }
@@ -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
  }
@@ -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,
@@ -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) {
@@ -30511,7 +30511,7 @@ import {
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 join33, 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
 
@@ -38586,7 +38431,7 @@ function isSilentFlushMarker(text) {
38586
38431
  var MIN_INITIAL_CHARS = 50;
38587
38432
  var DEFAULT_THROTTLE_MS = 1000;
38588
38433
  var TELEGRAM_MAX_CHARS2 = 4096;
38589
- var allocateDraftId2 = allocateDraftId;
38434
+ var allocateDraftId3 = allocateDraftId2;
38590
38435
  function createAnswerStream(config) {
38591
38436
  const {
38592
38437
  chatId,
@@ -38609,7 +38454,7 @@ function createAnswerStream(config) {
38609
38454
  const effectiveThrottle = Math.max(250, throttleMs);
38610
38455
  const preferDraft = isPrivateChat && draftApi != null;
38611
38456
  let usesDraftTransport = preferDraft;
38612
- let draftId = preferDraft ? allocateDraftId2() : undefined;
38457
+ let draftId = preferDraft ? allocateDraftId3() : undefined;
38613
38458
  let streamMsgId;
38614
38459
  let pendingText = null;
38615
38460
  let lastSentText = "";
@@ -38858,7 +38703,7 @@ function createAnswerStream(config) {
38858
38703
  if (staleDraftId != null) {
38859
38704
  clearDraftBestEffort(staleDraftId);
38860
38705
  }
38861
- draftId = allocateDraftId2();
38706
+ draftId = allocateDraftId3();
38862
38707
  }
38863
38708
  log?.(`answer-stream: forceNewMessage (gen=${generation})`);
38864
38709
  },
@@ -39064,16 +38909,16 @@ function renderAccountRow(snap, opts) {
39064
38909
  const lines = [];
39065
38910
  const marker = snap.isActive ? "\u25cf " : "";
39066
38911
  if (!snap.quota) {
39067
- lines.push(`${marker}<code>${escapeHtml2(snap.label)}</code> <i>quota probe failed</i>`);
38912
+ lines.push(`${marker}<code>${escapeHtml(snap.label)}</code> <i>quota probe failed</i>`);
39068
38913
  if (snap.quotaError) {
39069
- lines.push(` <i>${escapeHtml2(snap.quotaError)}</i>`);
38914
+ lines.push(` <i>${escapeHtml(snap.quotaError)}</i>`);
39070
38915
  }
39071
38916
  return lines;
39072
38917
  }
39073
38918
  const q = snap.quota;
39074
38919
  const fiveStr = fmtPct(q.fiveHourUtilizationPct);
39075
38920
  const sevenStr = fmtPct(q.sevenDayUtilizationPct);
39076
- lines.push(`${marker}<code>${escapeHtml2(snap.label)}</code> ${fiveStr} / ${sevenStr}`);
38921
+ lines.push(`${marker}<code>${escapeHtml(snap.label)}</code> ${fiveStr} / ${sevenStr}`);
39077
38922
  const health = classifyHealth(snap);
39078
38923
  if (health === "blocked") {
39079
38924
  const win = bindingWindow(q);
@@ -39179,13 +39024,13 @@ function renderFallbackAnnouncement(input) {
39179
39024
  const limitWord = input.oldQuota ? limitWordFor(input.oldQuota) : "quota";
39180
39025
  const headerLimit = limitWord === "quota" ? "quota cap" : `${limitWord} limit`;
39181
39026
  if (!input.newLabel) {
39182
- lines.push(`\uD83D\uDD34 <b>All accounts blocked \u00b7 ${headerLimit} on ${escapeHtml2(input.oldLabel)}</b>`);
39027
+ lines.push(`\uD83D\uDD34 <b>All accounts blocked \u00b7 ${headerLimit} on ${escapeHtml(input.oldLabel)}</b>`);
39183
39028
  lines.push("");
39184
- lines.push(`Triggered by: agent <b>${escapeHtml2(input.triggerAgent)}</b>`);
39029
+ lines.push(`Triggered by: agent <b>${escapeHtml(input.triggerAgent)}</b>`);
39185
39030
  if (input.oldQuota) {
39186
39031
  const recovery = recoveryAtFor(input.oldQuota);
39187
39032
  if (recovery) {
39188
- lines.push(`${escapeHtml2(input.oldLabel)} recovers ${formatAbsolute(recovery, tz)} ` + `(in ${formatRelative(recovery, now)})`);
39033
+ lines.push(`${escapeHtml(input.oldLabel)} recovers ${formatAbsolute(recovery, tz)} ` + `(in ${formatRelative(recovery, now)})`);
39189
39034
  }
39190
39035
  }
39191
39036
  lines.push("");
@@ -39193,15 +39038,15 @@ function renderFallbackAnnouncement(input) {
39193
39038
  return lines.join(`
39194
39039
  `);
39195
39040
  }
39196
- lines.push(`\u2713 <b>Switched fleet \u00b7 ${headerLimit} on ${escapeHtml2(input.oldLabel)}</b>`);
39041
+ lines.push(`\u2713 <b>Switched fleet \u00b7 ${headerLimit} on ${escapeHtml(input.oldLabel)}</b>`);
39197
39042
  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>`);
39043
+ lines.push(`<code>${escapeHtml(input.oldLabel)}</code> \u2192 <code>${escapeHtml(input.newLabel)}</code>`);
39044
+ lines.push(`Triggered by: agent <b>${escapeHtml(input.triggerAgent)}</b>`);
39200
39045
  lines.push("");
39201
39046
  if (input.oldQuota) {
39202
39047
  const recovery = recoveryAtFor(input.oldQuota);
39203
39048
  if (recovery) {
39204
- lines.push(`<code>${escapeHtml2(input.oldLabel)}</code> recovers ` + `${formatAbsolute(recovery, tz)} (in ${formatRelative(recovery, now)})`);
39049
+ lines.push(`<code>${escapeHtml(input.oldLabel)}</code> recovers ` + `${formatAbsolute(recovery, tz)} (in ${formatRelative(recovery, now)})`);
39205
39050
  }
39206
39051
  }
39207
39052
  if (input.newQuota) {
@@ -39209,7 +39054,7 @@ function renderFallbackAnnouncement(input) {
39209
39054
  const sevenStr = fmtPct(input.newQuota.sevenDayUtilizationPct);
39210
39055
  const hasHeadroom = input.newQuota.fiveHourUtilizationPct < THROTTLING_THRESHOLD_PCT && input.newQuota.sevenDayUtilizationPct < THROTTLING_THRESHOLD_PCT;
39211
39056
  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}`);
39057
+ lines.push(`<code>${escapeHtml(input.newLabel)}</code> now: ${fiveStr} of 5h \u00b7 ${sevenStr} of 7d ${headroomStr}`);
39213
39058
  } else {
39214
39059
  lines.push(`<i>(quota probe for new account is pending \u2014 will reflect on next /auth)</i>`);
39215
39060
  }
@@ -39268,7 +39113,7 @@ function switchPriority(s) {
39268
39113
  return 2;
39269
39114
  return 3;
39270
39115
  }
39271
- function escapeHtml2(s) {
39116
+ function escapeHtml(s) {
39272
39117
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
39273
39118
  }
39274
39119
  function buildSnapshotsFromState(state3, quotas) {
@@ -39361,7 +39206,7 @@ function parseAuthCommand(text) {
39361
39206
  if (tail.length > 0) {
39362
39207
  return {
39363
39208
  kind: "help",
39364
- reason: `Unknown <code>rm</code> modifier: <code>${escapeHtml3(tail)}</code>. Use <code>/auth rm &lt;label&gt; confirm</code> to confirm.`
39209
+ reason: `Unknown <code>rm</code> modifier: <code>${escapeHtml2(tail)}</code>. Use <code>/auth rm &lt;label&gt; confirm</code> to confirm.`
39365
39210
  };
39366
39211
  }
39367
39212
  return { kind: "rm-prompt", label };
@@ -39381,7 +39226,7 @@ function parseAuthCommand(text) {
39381
39226
  if (sub !== "override") {
39382
39227
  return {
39383
39228
  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>.`
39229
+ 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
39230
  };
39386
39231
  }
39387
39232
  const agent = parts[2];
@@ -39403,7 +39248,7 @@ function parseAuthCommand(text) {
39403
39248
  case "help":
39404
39249
  return { kind: "help" };
39405
39250
  default:
39406
- return { kind: "help", reason: `Unknown verb: <code>${escapeHtml3(verb)}</code>` };
39251
+ return { kind: "help", reason: `Unknown verb: <code>${escapeHtml2(verb)}</code>` };
39407
39252
  }
39408
39253
  }
39409
39254
  async function handleAuthCommand(parsed, ctx) {
@@ -39457,7 +39302,7 @@ async function handleAuthCommand(parsed, ctx) {
39457
39302
  };
39458
39303
  } catch (err) {
39459
39304
  return {
39460
- text: `<b>/auth show failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39305
+ text: `<b>/auth show failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39461
39306
  html: true
39462
39307
  };
39463
39308
  }
@@ -39469,7 +39314,7 @@ async function handleAuthCommand(parsed, ctx) {
39469
39314
  const agent = state3.agents.find((a) => a.name === agentName3);
39470
39315
  if (!agent) {
39471
39316
  return {
39472
- text: `<b>/auth show:</b> no agent named <code>${escapeHtml3(agentName3)}</code> in broker view.
39317
+ text: `<b>/auth show:</b> no agent named <code>${escapeHtml2(agentName3)}</code> in broker view.
39473
39318
  ` + `Run <code>/auth show</code> for the fleet snapshot.`,
39474
39319
  html: true
39475
39320
  };
@@ -39477,7 +39322,7 @@ async function handleAuthCommand(parsed, ctx) {
39477
39322
  return { text: renderAgentDetail(state3, agent), html: true };
39478
39323
  } catch (err) {
39479
39324
  return {
39480
- text: `<b>/auth show failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39325
+ text: `<b>/auth show failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39481
39326
  html: true
39482
39327
  };
39483
39328
  }
@@ -39499,13 +39344,13 @@ async function handleAuthCommand(parsed, ctx) {
39499
39344
  try {
39500
39345
  const result = await ctx.client.setActive(parsed.label);
39501
39346
  return {
39502
- text: `<b>Active account \u2192</b> <code>${escapeHtml3(result.active)}</code>
39347
+ text: `<b>Active account \u2192</b> <code>${escapeHtml2(result.active)}</code>
39503
39348
  ` + `Re-mirrored credentials for ${result.fanned.length} agent${result.fanned.length === 1 ? "" : "s"}.`,
39504
39349
  html: true
39505
39350
  };
39506
39351
  } catch (err) {
39507
39352
  return {
39508
- text: `<b>/auth use failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39353
+ text: `<b>/auth use failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39509
39354
  html: true
39510
39355
  };
39511
39356
  }
@@ -39523,13 +39368,13 @@ async function handleAuthCommand(parsed, ctx) {
39523
39368
  }
39524
39369
  const result = await ctx.client.setActive(nextLabel);
39525
39370
  return {
39526
- text: `<b>Rotated:</b> active \u2192 <code>${escapeHtml3(result.active)}</code>
39371
+ text: `<b>Rotated:</b> active \u2192 <code>${escapeHtml2(result.active)}</code>
39527
39372
  ` + `Re-mirrored credentials for ${result.fanned.length} agent${result.fanned.length === 1 ? "" : "s"}.`,
39528
39373
  html: true
39529
39374
  };
39530
39375
  } catch (err) {
39531
39376
  return {
39532
- text: `<b>/auth rotate failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39377
+ text: `<b>/auth rotate failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39533
39378
  html: true
39534
39379
  };
39535
39380
  }
@@ -39540,20 +39385,20 @@ async function handleAuthCommand(parsed, ctx) {
39540
39385
  state3 = await ctx.client.listState();
39541
39386
  } catch (err) {
39542
39387
  return {
39543
- text: `<b>/auth rm failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39388
+ text: `<b>/auth rm failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39544
39389
  html: true
39545
39390
  };
39546
39391
  }
39547
39392
  const exists = state3.accounts.some((a) => a.label === parsed.label);
39548
39393
  if (!exists) {
39549
39394
  return {
39550
- text: `<b>/auth rm:</b> no account named <code>${escapeHtml3(parsed.label)}</code>. ` + `Run <code>/auth show</code> for the current list.`,
39395
+ text: `<b>/auth rm:</b> no account named <code>${escapeHtml2(parsed.label)}</code>. ` + `Run <code>/auth show</code> for the current list.`,
39551
39396
  html: true
39552
39397
  };
39553
39398
  }
39554
39399
  if (state3.active === parsed.label) {
39555
39400
  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.`,
39401
+ 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
39402
  html: true
39558
39403
  };
39559
39404
  }
@@ -39564,10 +39409,10 @@ async function handleAuthCommand(parsed, ctx) {
39564
39409
  });
39565
39410
  }
39566
39411
  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.
39412
+ text: `<b>\u26a0 /auth rm</b> \u2014 about to remove <code>${escapeHtml2(parsed.label)}</code> from the broker.
39413
+ ` + `The fleet active is unchanged. Any agent override pointing at <code>${escapeHtml2(parsed.label)}</code> will stop working.
39569
39414
 
39570
- ` + `Send <code>/auth rm ${escapeHtml3(parsed.label)} confirm</code> within ${Math.round(AUTH_RM_CONFIRM_TTL_MS / 1000)}s to proceed.`,
39415
+ ` + `Send <code>/auth rm ${escapeHtml2(parsed.label)} confirm</code> within ${Math.round(AUTH_RM_CONFIRM_TTL_MS / 1000)}s to proceed.`,
39571
39416
  html: true
39572
39417
  };
39573
39418
  }
@@ -39579,7 +39424,7 @@ async function handleAuthCommand(parsed, ctx) {
39579
39424
  pendingAuthRmFlows.delete(ctx.chatId);
39580
39425
  }
39581
39426
  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.`,
39427
+ 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
39428
  html: true
39584
39429
  };
39585
39430
  }
@@ -39588,12 +39433,12 @@ async function handleAuthCommand(parsed, ctx) {
39588
39433
  try {
39589
39434
  const data = await ctx.client.rmAccount(parsed.label);
39590
39435
  return {
39591
- text: `<b>Removed</b> <code>${escapeHtml3(data.label)}</code> from the broker.`,
39436
+ text: `<b>Removed</b> <code>${escapeHtml2(data.label)}</code> from the broker.`,
39592
39437
  html: true
39593
39438
  };
39594
39439
  } catch (err) {
39595
39440
  return {
39596
- text: `<b>/auth rm failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39441
+ text: `<b>/auth rm failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39597
39442
  html: true
39598
39443
  };
39599
39444
  }
@@ -39604,7 +39449,7 @@ async function handleAuthCommand(parsed, ctx) {
39604
39449
  const targets = parsed.label ? state3.accounts.filter((a) => a.label === parsed.label).map((a) => a.label) : state3.accounts.map((a) => a.label);
39605
39450
  if (parsed.label && targets.length === 0) {
39606
39451
  return {
39607
- text: `<b>/auth refresh:</b> no account named <code>${escapeHtml3(parsed.label)}</code>.`,
39452
+ text: `<b>/auth refresh:</b> no account named <code>${escapeHtml2(parsed.label)}</code>.`,
39608
39453
  html: true
39609
39454
  };
39610
39455
  }
@@ -39623,10 +39468,10 @@ async function handleAuthCommand(parsed, ctx) {
39623
39468
  formatExpiryAbs(data.expiresAt)
39624
39469
  ]);
39625
39470
  } catch (err) {
39626
- failures.push(`${label}: ${escapeHtml3(err?.message ?? String(err))}`);
39471
+ failures.push(`${label}: ${escapeHtml2(err?.message ?? String(err))}`);
39627
39472
  }
39628
39473
  }
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"}`;
39474
+ 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
39475
  const table = rows.length > 1 ? `
39631
39476
  <pre>${alignTable(rows)}</pre>` : "";
39632
39477
  const failBlock = failures.length > 0 ? `
@@ -39636,7 +39481,7 @@ ${failures.map((f) => ` ${f}`).join(`
39636
39481
  return { text: head + table + failBlock, html: true };
39637
39482
  } catch (err) {
39638
39483
  return {
39639
- text: `<b>/auth refresh failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39484
+ text: `<b>/auth refresh failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39640
39485
  html: true
39641
39486
  };
39642
39487
  }
@@ -39645,12 +39490,12 @@ ${failures.map((f) => ` ${f}`).join(`
39645
39490
  try {
39646
39491
  const data = await ctx.client.setOverride(parsed.agent, parsed.label);
39647
39492
  return {
39648
- text: `<b>Override set.</b> <code>${escapeHtml3(data.agent)}</code> is now pinned to ` + `<code>${escapeHtml3(data.account ?? parsed.label)}</code>.`,
39493
+ text: `<b>Override set.</b> <code>${escapeHtml2(data.agent)}</code> is now pinned to ` + `<code>${escapeHtml2(data.account ?? parsed.label)}</code>.`,
39649
39494
  html: true
39650
39495
  };
39651
39496
  } catch (err) {
39652
39497
  return {
39653
- text: `<b>/auth agent override failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39498
+ text: `<b>/auth agent override failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39654
39499
  html: true
39655
39500
  };
39656
39501
  }
@@ -39659,12 +39504,12 @@ ${failures.map((f) => ` ${f}`).join(`
39659
39504
  try {
39660
39505
  const data = await ctx.client.setOverride(parsed.agent, null);
39661
39506
  return {
39662
- text: `<b>Override cleared</b> on <code>${escapeHtml3(data.agent)}</code> ` + `\u2014 back to fleet active.`,
39507
+ text: `<b>Override cleared</b> on <code>${escapeHtml2(data.agent)}</code> ` + `\u2014 back to fleet active.`,
39663
39508
  html: true
39664
39509
  };
39665
39510
  } catch (err) {
39666
39511
  return {
39667
- text: `<b>/auth agent override failed:</b> ${escapeHtml3(err?.message ?? String(err))}`,
39512
+ text: `<b>/auth agent override failed:</b> ${escapeHtml2(err?.message ?? String(err))}`,
39668
39513
  html: true
39669
39514
  };
39670
39515
  }
@@ -39743,7 +39588,7 @@ function formatAccountsTable(state3, now) {
39743
39588
  const status = isActive ? "active" : acc.exhausted ? "exhausted" : "available";
39744
39589
  const expires = acc.expiresAt != null ? formatRelativeMs(acc.expiresAt - now) : "\u2014";
39745
39590
  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]);
39591
+ rows.push([`${marker} ${escapeHtml2(acc.label)}`, status, expires, quotaReset]);
39747
39592
  }
39748
39593
  return alignTable(rows);
39749
39594
  }
@@ -39751,15 +39596,15 @@ function formatAgentsTable(state3) {
39751
39596
  const rows = [["AGENT", "ACTIVE", "SOURCE"]];
39752
39597
  for (const a of state3.agents) {
39753
39598
  const source = a.override ? "override" : a.account === state3.active ? "fleet-active" : "pinned";
39754
- rows.push([escapeHtml3(a.name), escapeHtml3(a.account), source]);
39599
+ rows.push([escapeHtml2(a.name), escapeHtml2(a.account), source]);
39755
39600
  }
39756
39601
  return alignTable(rows);
39757
39602
  }
39758
39603
  function renderAgentDetail(state3, agent, now = Date.now()) {
39759
39604
  const lines = [];
39760
- lines.push(`<b>${escapeHtml3(agent.name)}</b>`);
39605
+ lines.push(`<b>${escapeHtml2(agent.name)}</b>`);
39761
39606
  const source = agent.override ? "override" : "fleet-active";
39762
- lines.push(`Active account: <code>${escapeHtml3(agent.account)}</code> (${source})`);
39607
+ lines.push(`Active account: <code>${escapeHtml2(agent.account)}</code> (${source})`);
39763
39608
  const acct = state3.accounts.find((a) => a.label === agent.account);
39764
39609
  if (acct) {
39765
39610
  const expRel = acct.expiresAt != null ? formatRelativeMs(acct.expiresAt - now) : "\u2014";
@@ -39782,11 +39627,11 @@ function formatConsumersTable(state3, now) {
39782
39627
  const rows = [["CONSUMER", "ACTIVE", "STATUS"]];
39783
39628
  for (const c of state3.consumers) {
39784
39629
  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]);
39630
+ rows.push([escapeHtml2(c.name), escapeHtml2(c.account), status]);
39786
39631
  }
39787
39632
  return alignTable(rows);
39788
39633
  }
39789
- function escapeHtml3(s) {
39634
+ function escapeHtml2(s) {
39790
39635
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
39791
39636
  }
39792
39637
  function formatRelativeMs(ms) {
@@ -41101,11 +40946,11 @@ function renderTable(headers, rows) {
41101
40946
  if (colCount <= 3 && rowCount <= 6) {
41102
40947
  const bullets = rows.map((row) => {
41103
40948
  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("");
40949
+ const key = escapeHtml4(cells[0] || "\u2014");
40950
+ const rest = cells.slice(1).filter((v) => v !== "").map((v) => ` \u2014 ${escapeHtml4(v)}`).join("");
41106
40951
  return `\u2022 <b>${key}</b>${rest}`;
41107
40952
  });
41108
- const headerLine = colCount >= 2 ? `<b>${headers.map((h) => escapeHtml5(h)).join(" / ")}</b>
40953
+ const headerLine = colCount >= 2 ? `<b>${headers.map((h) => escapeHtml4(h)).join(" / ")}</b>
41109
40954
  ` : "";
41110
40955
  return headerLine + bullets.join(`
41111
40956
  `);
@@ -41120,7 +40965,7 @@ function renderTable(headers, rows) {
41120
40965
  sepLine,
41121
40966
  ...rows.map((r) => formatRow(r))
41122
40967
  ];
41123
- return `<pre>${escapeHtml5(lines.join(`
40968
+ return `<pre>${escapeHtml4(lines.join(`
41124
40969
  `))}</pre>`;
41125
40970
  }
41126
40971
  function extractMarkdownTables(text, store2, placeholderPrefix) {
@@ -41168,7 +41013,7 @@ function markdownToHtml(text) {
41168
41013
  const INLINE_PH = "\x00CODEINLINE";
41169
41014
  const TABLE_PH = "\x00TABLEBLOCK";
41170
41015
  let result = text.replace(/```(\w*)\n([\s\S]*?)```/g, (_m, lang, code) => {
41171
- const escaped = escapeHtml5(code.replace(/\n$/, ""));
41016
+ const escaped = escapeHtml4(code.replace(/\n$/, ""));
41172
41017
  const cls = lang ? ` class="language-${lang}"` : "";
41173
41018
  const idx = codeBlocks.length;
41174
41019
  codeBlocks.push(`<pre><code${cls}>${escaped}</code></pre>`);
@@ -41181,7 +41026,7 @@ function markdownToHtml(text) {
41181
41026
  const inlineCodes = [];
41182
41027
  result = result.replace(/`([^`\n]+)`/g, (_m, code) => {
41183
41028
  const idx = inlineCodes.length;
41184
- inlineCodes.push(`<code>${escapeHtml5(code)}</code>`);
41029
+ inlineCodes.push(`<code>${escapeHtml4(code)}</code>`);
41185
41030
  return `${INLINE_PH}${idx}\x00`;
41186
41031
  });
41187
41032
  const htmlTags = [];
@@ -41193,24 +41038,24 @@ function markdownToHtml(text) {
41193
41038
  htmlTags.push(match);
41194
41039
  return `${HTMLTAG_PH}${idx}\x00`;
41195
41040
  });
41196
- result = escapeHtml5(result);
41041
+ result = escapeHtml4(result);
41197
41042
  result = result.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
41198
41043
  result = result.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<i>$1</i>");
41199
41044
  result = result.replace(/(?<![\w_])_(?!_)([^_\n]+?)_(?![\w_])/g, "<i>$1</i>");
41200
41045
  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)]);
41046
+ result = result.replace(new RegExp(`${escapeHtml4(BLOCK_PH)}(\\d+)${escapeHtml4("\x00")}`, "g"), (_m, idx) => codeBlocks[Number(idx)]);
41047
+ result = result.replace(new RegExp(`${escapeHtml4(TABLE_PH)}(\\d+)${escapeHtml4("\x00")}`, "g"), (_m, idx) => codeBlocks[Number(idx)]);
41048
+ result = result.replace(new RegExp(`${escapeHtml4(INLINE_PH)}(\\d+)${escapeHtml4("\x00")}`, "g"), (_m, idx) => inlineCodes[Number(idx)]);
41204
41049
  const ALLOWED_LINK_SCHEMES = /^(?:https?|mailto|tel|tg):/i;
41205
41050
  result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, linkText, url) => {
41206
41051
  const safe = ALLOWED_LINK_SCHEMES.test(url.trim()) ? url.trim() : "#";
41207
- return `<a href="${escapeHtml5(safe)}">${linkText}</a>`;
41052
+ return `<a href="${escapeHtml4(safe)}">${linkText}</a>`;
41208
41053
  });
41209
41054
  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)]);
41055
+ result = result.replace(new RegExp(`${escapeHtml4(HTMLTAG_PH)}(\\d+)${escapeHtml4("\x00")}`, "g"), (_m, idx) => htmlTags[Number(idx)]);
41211
41056
  return result;
41212
41057
  }
41213
- function escapeHtml5(text) {
41058
+ function escapeHtml4(text) {
41214
41059
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
41215
41060
  }
41216
41061
  function telegramHtmlToPlainText(html) {
@@ -41611,7 +41456,7 @@ async function finalizeCallback(ctx, opts) {
41611
41456
  }
41612
41457
 
41613
41458
  // welcome-text.ts
41614
- function escapeHtml6(text) {
41459
+ function escapeHtml5(text) {
41615
41460
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
41616
41461
  }
41617
41462
  function formatAuthLine(auth) {
@@ -41623,13 +41468,13 @@ function formatAuthLine(auth) {
41623
41468
  return "\u2717 not authenticated";
41624
41469
  }
41625
41470
  const sub = auth.subscription_type ?? "subscription";
41626
- const expires = auth.expires_in ? ` \u00b7 expires ${escapeHtml6(auth.expires_in)}` : "";
41627
- return `\u2713 ${escapeHtml6(sub)}${expires}`;
41471
+ const expires = auth.expires_in ? ` \u00b7 expires ${escapeHtml5(auth.expires_in)}` : "";
41472
+ return `\u2713 ${escapeHtml5(sub)}${expires}`;
41628
41473
  }
41629
41474
  function formatAgentLine(meta) {
41630
41475
  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}`;
41476
+ const topic = meta.topicName ? ` \u00b7 topic: ${escapeHtml5([meta.topicEmoji, meta.topicName].filter(Boolean).join(" "))}` : "";
41477
+ return `<b>${escapeHtml5(meta.agentName)}</b> \u00b7 model: <code>${escapeHtml5(m)}</code>${topic}`;
41633
41478
  }
41634
41479
  function startText(agentName3, dmDisabled) {
41635
41480
  if (dmDisabled)
@@ -41637,7 +41482,7 @@ function startText(agentName3, dmDisabled) {
41637
41482
  return [
41638
41483
  `<b>Switchroom</b> \u2014 Telegram on your Claude Pro or Max subscription.`,
41639
41484
  ``,
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.`,
41485
+ `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
41486
  ``,
41642
41487
  `<b>To pair:</b>`,
41643
41488
  `1. DM me anything \u2014 you'll get a 6-char code`,
@@ -41651,7 +41496,7 @@ function helpText(agentName3) {
41651
41496
  return [
41652
41497
  `<b>Switchroom</b> \u2014 your Pro/Max subscription, wired to Telegram.`,
41653
41498
  ``,
41654
- `This bot is the <b>${escapeHtml6(agentName3)}</b> agent. Text and photos route through to it; replies, reactions and progress cards come back.`,
41499
+ `This bot is the <b>${escapeHtml5(agentName3)}</b> agent. Text and photos route through to it; replies, reactions and progress cards come back.`,
41655
41500
  ``,
41656
41501
  `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
41502
  ``,
@@ -41670,40 +41515,40 @@ var STATUS_DOT = {
41670
41515
  function statusPairedText(params) {
41671
41516
  const { user, meta } = params;
41672
41517
  const lines = [
41673
- `Paired as ${escapeHtml6(user)}.`,
41518
+ `Paired as ${escapeHtml5(user)}.`,
41674
41519
  ``,
41675
41520
  `Agent: ${formatAgentLine(meta)}`,
41676
41521
  `Auth: ${formatAuthLine(meta.auth)}`
41677
41522
  ];
41678
41523
  if (meta.status)
41679
- lines.push(`Status: <code>${escapeHtml6(meta.status)}</code>${meta.uptime ? ` \u00b7 up ${escapeHtml6(meta.uptime)}` : ""}`);
41524
+ lines.push(`Status: <code>${escapeHtml5(meta.status)}</code>${meta.uptime ? ` \u00b7 up ${escapeHtml5(meta.uptime)}` : ""}`);
41680
41525
  if (meta.live && meta.live.length > 0) {
41681
41526
  lines.push("");
41682
41527
  lines.push("<b>Health</b>");
41683
41528
  for (const row of meta.live) {
41684
41529
  const dot = STATUS_DOT[row.status] ?? STATUS_DOT.fail;
41685
- lines.push(`${dot} <b>${escapeHtml6(row.label)}</b> ${escapeHtml6(row.detail)}`);
41530
+ lines.push(`${dot} <b>${escapeHtml5(row.label)}</b> ${escapeHtml5(row.detail)}`);
41686
41531
  }
41687
41532
  }
41688
41533
  const audit = meta.audit;
41689
41534
  if (audit) {
41690
41535
  lines.push("");
41691
41536
  if (audit.version)
41692
- lines.push(`<b>Version</b> ${escapeHtml6(audit.version)}`);
41537
+ lines.push(`<b>Version</b> ${escapeHtml5(audit.version)}`);
41693
41538
  if (meta.extendsProfile)
41694
- lines.push(`<b>Profile</b> ${escapeHtml6(meta.extendsProfile)}`);
41539
+ lines.push(`<b>Profile</b> ${escapeHtml5(meta.extendsProfile)}`);
41695
41540
  if (audit.tools)
41696
- lines.push(`<b>Tools</b> ${escapeHtml6(audit.tools)}`);
41541
+ lines.push(`<b>Tools</b> ${escapeHtml5(audit.tools)}`);
41697
41542
  if (audit.toolsDeny)
41698
- lines.push(`<b>Deny</b> ${escapeHtml6(audit.toolsDeny)}`);
41543
+ lines.push(`<b>Deny</b> ${escapeHtml5(audit.toolsDeny)}`);
41699
41544
  if (audit.skills)
41700
- lines.push(`<b>Skills</b> ${escapeHtml6(audit.skills)}`);
41545
+ lines.push(`<b>Skills</b> ${escapeHtml5(audit.skills)}`);
41701
41546
  if (audit.limits)
41702
- lines.push(`<b>Limits</b> ${escapeHtml6(audit.limits)}`);
41547
+ lines.push(`<b>Limits</b> ${escapeHtml5(audit.limits)}`);
41703
41548
  if (audit.channel)
41704
- lines.push(`<b>Channel</b> ${escapeHtml6(audit.channel)}`);
41549
+ lines.push(`<b>Channel</b> ${escapeHtml5(audit.channel)}`);
41705
41550
  if (audit.memoryBank)
41706
- lines.push(`<b>Memory</b> ${escapeHtml6(audit.memoryBank)}`);
41551
+ lines.push(`<b>Memory</b> ${escapeHtml5(audit.memoryBank)}`);
41707
41552
  }
41708
41553
  return lines.join(`
41709
41554
  `);
@@ -41711,7 +41556,7 @@ function statusPairedText(params) {
41711
41556
  function statusPendingText(code) {
41712
41557
  return `Pending pairing \u2014 run in Claude Code:
41713
41558
 
41714
- <code>/telegram:access pair ${escapeHtml6(code)}</code>`;
41559
+ <code>/telegram:access pair ${escapeHtml5(code)}</code>`;
41715
41560
  }
41716
41561
  function statusUnpairedText() {
41717
41562
  return "Not paired. Send me a message to get a pairing code.";
@@ -41740,7 +41585,7 @@ var TELEGRAM_BASE_COMMANDS = TELEGRAM_MENU_COMMANDS.slice(0, 3);
41740
41585
  var TELEGRAM_SWITCHROOM_COMMANDS = TELEGRAM_MENU_COMMANDS.slice(3);
41741
41586
  function switchroomHelpText(agentName3) {
41742
41587
  return [
41743
- `<b>Switchroom bot</b> \u2014 commands for the <b>${escapeHtml6(agentName3)}</b> agent.`,
41588
+ `<b>Switchroom bot</b> \u2014 commands for the <b>${escapeHtml5(agentName3)}</b> agent.`,
41744
41589
  ``,
41745
41590
  `<b>Session &amp; approvals</b>`,
41746
41591
  `<code>/new</code> \u2014 fresh session (flush handoff, restart)`,
@@ -41788,15 +41633,15 @@ function switchroomHelpText(agentName3) {
41788
41633
  `);
41789
41634
  }
41790
41635
  function restartAckText(agentName3) {
41791
- return `\uD83D\uDD04 Restarting <b>${escapeHtml6(agentName3)}</b>\u2026`;
41636
+ return `\uD83D\uDD04 Restarting <b>${escapeHtml5(agentName3)}</b>\u2026`;
41792
41637
  }
41793
41638
  function newSessionAckText(agentName3, flushedHandoff) {
41794
41639
  const tail = flushedHandoff ? " \u00b7 flushed handoff" : "";
41795
- return `\uD83C\uDD95 Started fresh session for <b>${escapeHtml6(agentName3)}</b>${tail} \u00b7 restarting\u2026`;
41640
+ return `\uD83C\uDD95 Started fresh session for <b>${escapeHtml5(agentName3)}</b>${tail} \u00b7 restarting\u2026`;
41796
41641
  }
41797
41642
  function resetSessionAckText(agentName3, flushedHandoff) {
41798
41643
  const tail = flushedHandoff ? " \u00b7 flushed handoff" : "";
41799
- return `\uD83D\uDD04 Reset session for <b>${escapeHtml6(agentName3)}</b>${tail} \u00b7 restarting\u2026`;
41644
+ return `\uD83D\uDD04 Reset session for <b>${escapeHtml5(agentName3)}</b>${tail} \u00b7 restarting\u2026`;
41800
41645
  }
41801
41646
 
41802
41647
  // gateway/auth-status-adapter.ts
@@ -41981,7 +41826,7 @@ function shouldShowHandoffLine() {
41981
41826
  function formatHandoffLine(topic, format) {
41982
41827
  const prefix = "\u21a9\ufe0f Picked up where we left off, ";
41983
41828
  if (format === "html") {
41984
- return `<i>${prefix}${escapeHtml7(topic)}</i>
41829
+ return `<i>${prefix}${escapeHtml6(topic)}</i>
41985
41830
 
41986
41831
  `;
41987
41832
  }
@@ -41996,7 +41841,7 @@ function formatHandoffLine(topic, format) {
41996
41841
 
41997
41842
  `;
41998
41843
  }
41999
- function escapeHtml7(s) {
41844
+ function escapeHtml6(s) {
42000
41845
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
42001
41846
  }
42002
41847
  var MDV2_SPECIALS = /[_*\[\]()~`>#+\-=|{}.!\\]/g;
@@ -45375,13 +45220,13 @@ function buildMs365CardText(p) {
45375
45220
  const lines = [];
45376
45221
  lines.push(`\uD83D\uDCC4 Microsoft 365 write approval`);
45377
45222
  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)}`);
45223
+ lines.push(`Agent: ${truncate2(p.agentName, 64)}`);
45224
+ lines.push(`Tool: ${truncate2(p.toolName.replace(/^mcp__/, ""), 96)}`);
45225
+ lines.push(`Item: ${truncate2(p.itemDisplayName, 256)}`);
45381
45226
  if (p.itemId !== "(new)") {
45382
- lines.push(`ID: ${truncate3(p.itemId, 96)}`);
45227
+ lines.push(`ID: ${truncate2(p.itemId, 96)}`);
45383
45228
  }
45384
- lines.push(`Account: ${truncate3(p.accountEmail, 96)}`);
45229
+ lines.push(`Account: ${truncate2(p.accountEmail, 96)}`);
45385
45230
  if (typeof p.sizeBytesBefore === "number" || typeof p.sizeBytesAfter === "number") {
45386
45231
  const before = p.sizeBytesBefore ?? 0;
45387
45232
  const after = p.sizeBytesAfter ?? 0;
@@ -45390,18 +45235,18 @@ function buildMs365CardText(p) {
45390
45235
  lines.push(`Size: ${humanBytes(before)} \u2192 ${humanBytes(after)} (${sign}${humanBytes(delta)})`);
45391
45236
  }
45392
45237
  if (p.deepLink) {
45393
- lines.push(`Link: ${truncate3(p.deepLink, 256)}`);
45238
+ lines.push(`Link: ${truncate2(p.deepLink, 256)}`);
45394
45239
  }
45395
45240
  if (p.agentRationale) {
45396
45241
  lines.push("");
45397
- lines.push(`\uD83D\uDCAC ${truncate3(p.agentRationale, 512)}`);
45242
+ lines.push(`\uD83D\uDCAC ${truncate2(p.agentRationale, 512)}`);
45398
45243
  }
45399
45244
  lines.push("");
45400
45245
  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
45246
  return lines.join(`
45402
45247
  `);
45403
45248
  }
45404
- function truncate3(s, n) {
45249
+ function truncate2(s, n) {
45405
45250
  if (s.length <= n)
45406
45251
  return s;
45407
45252
  return s.slice(0, n - 1) + "\u2026";
@@ -45517,9 +45362,9 @@ function buildDiffPreviewCard(input) {
45517
45362
  }
45518
45363
  const preview = input.preview;
45519
45364
  const bodyLines = [];
45520
- bodyLines.push(`<b>${escapeHtml8(preview.title)}</b>`);
45365
+ bodyLines.push(`<b>${escapeHtml7(preview.title)}</b>`);
45521
45366
  for (const line of preview.lines) {
45522
- bodyLines.push(escapeHtml8(line.text));
45367
+ bodyLines.push(escapeHtml7(line.text));
45523
45368
  }
45524
45369
  const text = bodyLines.join(`
45525
45370
  `);
@@ -45572,7 +45417,7 @@ function buildDiffPreviewCard(input) {
45572
45417
  }
45573
45418
  return { text, reply_markup: kb };
45574
45419
  }
45575
- function escapeHtml8(s) {
45420
+ function escapeHtml7(s) {
45576
45421
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
45577
45422
  }
45578
45423
 
@@ -46418,14 +46263,14 @@ function buildVaultSaveDiscardedInbound(opts) {
46418
46263
  // gateway/subagent-handback-inbound-builder.ts
46419
46264
  var HANDBACK_RESULT_MAX = 3000;
46420
46265
  var HANDBACK_DESC_MAX = 200;
46421
- function truncate4(s, max) {
46266
+ function truncate3(s, max) {
46422
46267
  const t = s.trim();
46423
46268
  return t.length > max ? t.slice(0, max) + "\u2026" : t;
46424
46269
  }
46425
46270
  function buildSubagentHandbackInbound(opts) {
46426
46271
  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);
46272
+ const desc = truncate3(opts.ctx.taskDescription, HANDBACK_DESC_MAX) || "(no description)";
46273
+ const result = truncate3(opts.ctx.resultText, HANDBACK_RESULT_MAX);
46429
46274
  const text = opts.ctx.outcome === "failed" ? `\uD83E\uDD1D A background worker you dispatched has FAILED.
46430
46275
 
46431
46276
  ` + `Task: ${desc}
@@ -46489,7 +46334,7 @@ function decideSubagentHandback(input) {
46489
46334
  var PROGRESS_RESULT_MAX = 800;
46490
46335
  var PROGRESS_DESC_MAX = 200;
46491
46336
  var DEFAULT_PROGRESS_INTERVAL_MS = 5 * 60 * 1000;
46492
- function truncate5(s, max) {
46337
+ function truncate4(s, max) {
46493
46338
  const t = s.trim();
46494
46339
  return t.length > max ? t.slice(0, max) + "\u2026" : t;
46495
46340
  }
@@ -46503,8 +46348,8 @@ function formatElapsed(ms) {
46503
46348
  }
46504
46349
  function buildSubagentProgressInbound(opts) {
46505
46350
  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);
46351
+ const desc = truncate4(opts.ctx.taskDescription, PROGRESS_DESC_MAX) || "(no description)";
46352
+ const summary = truncate4(opts.ctx.latestSummary, PROGRESS_RESULT_MAX);
46508
46353
  const elapsed = formatElapsed(opts.ctx.elapsedMs);
46509
46354
  const expiresAt = ts + 2 * opts.ctx.progressIntervalMs;
46510
46355
  const text = `\uD83D\uDD04 A background worker you dispatched is still running.
@@ -48024,7 +47869,7 @@ function sanitiseToolArg(name, raw) {
48024
47869
  case "NotebookEdit": {
48025
47870
  const fp = raw.file_path;
48026
47871
  if (typeof fp === "string" && fp.length > 0)
48027
- out = basename4(fp);
47872
+ out = basename3(fp);
48028
47873
  break;
48029
47874
  }
48030
47875
  case "Bash": {
@@ -48060,7 +47905,7 @@ function sanitiseToolArg(name, raw) {
48060
47905
  out = out.slice(0, SANITISE_MAX_LEN - 1) + "\u2026";
48061
47906
  return out;
48062
47907
  }
48063
- function basename4(p) {
47908
+ function basename3(p) {
48064
47909
  const idx = p.lastIndexOf("/");
48065
47910
  return idx === -1 ? p : p.slice(idx + 1);
48066
47911
  }
@@ -48547,7 +48392,7 @@ function startSubagentWatcher(config) {
48547
48392
  if (idleMs >= threshold) {
48548
48393
  entry.stallNotified = true;
48549
48394
  entry.stalledAt = n;
48550
- const desc = escapeHtml9(truncate6(entry.description, 80));
48395
+ const desc = escapeHtml8(truncate5(entry.description, 80));
48551
48396
  const idleSec = Math.floor(idleMs / 1000);
48552
48397
  log?.(`subagent-watcher: stall detected for ${entry.agentId} (idle ${idleSec}s): ${desc}`);
48553
48398
  if (db2 != null) {
@@ -49021,7 +48866,7 @@ function renderIssuesCard(opts) {
49021
48866
  const maxSeverity = sorted[0].severity;
49022
48867
  const headerEmoji = SEVERITY_EMOJI[maxSeverity];
49023
48868
  const count = sorted.length;
49024
- const header = `${headerEmoji} <b>${escapeHtml9(opts.agentName)}</b> \u00b7 ${count} ${count === 1 ? "issue" : "issues"}`;
48869
+ const header = `${headerEmoji} <b>${escapeHtml8(opts.agentName)}</b> \u00b7 ${count} ${count === 1 ? "issue" : "issues"}`;
49025
48870
  const maxRows = opts.maxRows ?? DEFAULT_MAX_ROWS;
49026
48871
  const visible = sorted.slice(0, maxRows);
49027
48872
  const overflow = sorted.length - visible.length;
@@ -49030,10 +48875,10 @@ function renderIssuesCard(opts) {
49030
48875
  const emoji = SEVERITY_EMOJI[e.severity];
49031
48876
  const occ = e.occurrences > 1 ? ` <i>(\u00d7${e.occurrences})</i>` : "";
49032
48877
  const ago = relTime(now - e.last_seen);
49033
- const head = `${emoji} <code>${escapeHtml9(e.fingerprint)}</code> ${escapeHtml9(e.summary)}${occ} \u2014 <i>${ago}</i>`;
48878
+ const head = `${emoji} <code>${escapeHtml8(e.fingerprint)}</code> ${escapeHtml8(e.summary)}${occ} \u2014 <i>${ago}</i>`;
49034
48879
  const remediation = formatRemediation(e.detail);
49035
48880
  return remediation == null ? head : `${head}
49036
- \u2192 <i>${escapeHtml9(remediation)}</i>`;
48881
+ \u2192 <i>${escapeHtml8(remediation)}</i>`;
49037
48882
  });
49038
48883
  const lines = [header, "", ...rows];
49039
48884
  if (overflow > 0) {
@@ -49462,7 +49307,7 @@ function defaultReadEvents(stateDir) {
49462
49307
  return readAll(stateDir);
49463
49308
  }
49464
49309
  // permission-title.ts
49465
- import { basename as basename6 } from "node:path";
49310
+ import { basename as basename5 } from "node:path";
49466
49311
  var COMMAND_TITLE_MAX = 40;
49467
49312
  var PATH_TITLE_MAX = 40;
49468
49313
  var DESCRIPTION_LINE_MAX = 240;
@@ -49513,13 +49358,13 @@ function summarizeToolForTitle(toolName, inputPreview) {
49513
49358
  return `${toolName} (${skill})`;
49514
49359
  const command = readString(input, "command");
49515
49360
  if (command)
49516
- return `${toolName}: ${truncate7(command, COMMAND_TITLE_MAX)}`;
49361
+ return `${toolName}: ${truncate6(command, COMMAND_TITLE_MAX)}`;
49517
49362
  const argHint = firstScalarArgHint(input);
49518
49363
  return argHint ? `${toolName} (${argHint})` : toolName;
49519
49364
  }
49520
49365
  case "Bash": {
49521
49366
  const command = readString(input, "command");
49522
- return command ? `${toolName}: ${truncate7(command, COMMAND_TITLE_MAX)}` : toolName;
49367
+ return command ? `${toolName}: ${truncate6(command, COMMAND_TITLE_MAX)}` : toolName;
49523
49368
  }
49524
49369
  case "Read":
49525
49370
  case "Edit":
@@ -49527,17 +49372,17 @@ function summarizeToolForTitle(toolName, inputPreview) {
49527
49372
  case "MultiEdit":
49528
49373
  case "NotebookEdit": {
49529
49374
  const filePath = readString(input, "file_path") ?? readString(input, "notebook_path");
49530
- return filePath ? `${toolName}: ${truncate7(basename6(filePath), PATH_TITLE_MAX)}` : toolName;
49375
+ return filePath ? `${toolName}: ${truncate6(basename5(filePath), PATH_TITLE_MAX)}` : toolName;
49531
49376
  }
49532
49377
  case "Glob":
49533
49378
  case "Grep": {
49534
49379
  const pattern = readString(input, "pattern");
49535
- return pattern ? `${toolName}: ${truncate7(pattern, COMMAND_TITLE_MAX)}` : toolName;
49380
+ return pattern ? `${toolName}: ${truncate6(pattern, COMMAND_TITLE_MAX)}` : toolName;
49536
49381
  }
49537
49382
  case "WebFetch":
49538
49383
  case "WebSearch": {
49539
49384
  const query2 = readString(input, "url") ?? readString(input, "query");
49540
- return query2 ? `${toolName}: ${truncate7(query2, COMMAND_TITLE_MAX)}` : toolName;
49385
+ return query2 ? `${toolName}: ${truncate6(query2, COMMAND_TITLE_MAX)}` : toolName;
49541
49386
  }
49542
49387
  default:
49543
49388
  return toolName;
@@ -49576,7 +49421,7 @@ function firstScalarArgHint(input) {
49576
49421
  if (SKIP.has(key))
49577
49422
  continue;
49578
49423
  if (typeof value === "string" && value.length > 0) {
49579
- return `${key}: ${truncate7(value, INPUT_VALUE_MAX)}`;
49424
+ return `${key}: ${truncate6(value, INPUT_VALUE_MAX)}`;
49580
49425
  }
49581
49426
  if (typeof value === "number" || typeof value === "boolean") {
49582
49427
  return `${key}: ${String(value)}`;
@@ -49608,10 +49453,10 @@ function skillBasenameFromPath(input) {
49608
49453
  return null;
49609
49454
  const trimmed = path.replace(/\/SKILL\.md$/i, "").replace(/\/$/, "");
49610
49455
  const lastSlash = trimmed.lastIndexOf("/");
49611
- const basename7 = lastSlash >= 0 ? trimmed.slice(lastSlash + 1) : trimmed;
49612
- return basename7.length > 0 ? basename7 : null;
49456
+ const basename6 = lastSlash >= 0 ? trimmed.slice(lastSlash + 1) : trimmed;
49457
+ return basename6.length > 0 ? basename6 : null;
49613
49458
  }
49614
- function truncate7(text, max) {
49459
+ function truncate6(text, max) {
49615
49460
  const collapsed = text.replace(/\s+/g, " ").trim();
49616
49461
  if (collapsed.length <= max)
49617
49462
  return collapsed;
@@ -49619,7 +49464,7 @@ function truncate7(text, max) {
49619
49464
  }
49620
49465
 
49621
49466
  // permission-rule.ts
49622
- import { basename as basename7 } from "node:path";
49467
+ import { basename as basename6 } from "node:path";
49623
49468
  function resolveAlwaysAllowRule(toolName, inputPreview) {
49624
49469
  if (!toolName)
49625
49470
  return null;
@@ -49685,7 +49530,7 @@ function skillBasenameFromPath2(input) {
49685
49530
  if (!path)
49686
49531
  return null;
49687
49532
  const trimmed = path.replace(/\/SKILL\.md$/i, "").replace(/\/$/, "");
49688
- return basename7(trimmed) || null;
49533
+ return basename6(trimmed) || null;
49689
49534
  }
49690
49535
 
49691
49536
  // credits-watch.ts
@@ -49731,7 +49576,7 @@ function evaluateCreditState(args) {
49731
49576
  if (!currentIsFatal && prevIsFatal) {
49732
49577
  return {
49733
49578
  kind: "notify",
49734
- message: `\u2705 <b>${escapeHtml11(agentName3)}</b>: credits restored \u2014 agent should resume normal operation.`,
49579
+ message: `\u2705 <b>${escapeHtml10(agentName3)}</b>: credits restored \u2014 agent should resume normal operation.`,
49735
49580
  newState: { lastNotifiedReason: null, lastNotifiedAt: now },
49736
49581
  transition: "exited"
49737
49582
  };
@@ -49760,12 +49605,12 @@ function evaluateCreditState(args) {
49760
49605
  function buildEntryMessage(agentName3, reason) {
49761
49606
  const desc = humanizeReason(reason);
49762
49607
  return [
49763
- `\u26a0\ufe0f <b>${escapeHtml11(agentName3)}</b>: ${desc}`,
49608
+ `\u26a0\ufe0f <b>${escapeHtml10(agentName3)}</b>: ${desc}`,
49764
49609
  ``,
49765
49610
  `Cron tasks and inbound replies will fail until this is resolved. Check`,
49766
49611
  `your subscription or pre-paid usage at <a href="https://console.anthropic.com">console.anthropic.com</a>.`,
49767
49612
  ``,
49768
- `<i>Source: Claude CLI cache (cachedExtraUsageDisabledReason=${escapeHtml11(reason)})</i>`
49613
+ `<i>Source: Claude CLI cache (cachedExtraUsageDisabledReason=${escapeHtml10(reason)})</i>`
49769
49614
  ].join(`
49770
49615
  `);
49771
49616
  }
@@ -49783,7 +49628,7 @@ function humanizeReason(reason) {
49783
49628
  return `usage disabled (${reason})`;
49784
49629
  }
49785
49630
  }
49786
- function escapeHtml11(s) {
49631
+ function escapeHtml10(s) {
49787
49632
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
49788
49633
  }
49789
49634
  function loadCreditState(stateDir) {
@@ -49882,10 +49727,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
49882
49727
  }
49883
49728
 
49884
49729
  // ../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;
49730
+ var VERSION = "0.13.58";
49731
+ var COMMIT_SHA = "20818078";
49732
+ var COMMIT_DATE = "2026-05-27T22:11:23Z";
49733
+ var LATEST_PR = 1928;
49889
49734
  var COMMITS_AHEAD_OF_TAG = 0;
49890
49735
 
49891
49736
  // gateway/boot-version.ts
@@ -52096,7 +51941,7 @@ ${reminder}
52096
51941
  noteSubagentDispatch(key);
52097
51942
  }
52098
51943
  if (ev.toolUseId != null && ev.toolUseId.length > 0 && !isTelegramSurfaceTool(ev.toolName)) {
52099
- const label = toolLabel2(ev.toolName, ev.input, undefined, ev.precomputedLabel);
51944
+ const label = toolLabel(ev.toolName, ev.input, undefined, ev.precomputedLabel);
52100
51945
  noteToolStart(key, ev.toolUseId, ev.toolName, label.length > 0 ? label : null, Date.now());
52101
51946
  const evInput = ev.input;
52102
51947
  if (ev.toolName === "Agent" || ev.toolName === "Task" || ev.toolName === "Bash" && evInput?.run_in_background === true) {
@@ -53859,6 +53704,74 @@ function closeProgressLane(chatId, threadId) {
53859
53704
  }
53860
53705
  }
53861
53706
  }
53707
+ async function drainActivitySummary(turn) {
53708
+ try {
53709
+ while (turn.activityPendingRender !== turn.activityLastSentRender) {
53710
+ const target = turn.activityPendingRender;
53711
+ if (target == null)
53712
+ break;
53713
+ const html = `<i>${target}</i>`;
53714
+ const chat = turn.sessionChatId;
53715
+ const thread = turn.sessionThreadId;
53716
+ const useDraft = turn.isDm && thread == null && sendMessageDraftFn != null;
53717
+ try {
53718
+ if (useDraft) {
53719
+ if (turn.activityDraftId == null) {
53720
+ turn.activityDraftId = allocateDraftId();
53721
+ }
53722
+ const draftId = turn.activityDraftId;
53723
+ await sendMessageDraftFn(chat, draftId, html, undefined);
53724
+ } else if (turn.activityMessageId == null) {
53725
+ const sent = await robustApiCall(() => bot.api.sendMessage(chat, html, {
53726
+ ...thread != null ? { message_thread_id: thread } : {},
53727
+ parse_mode: "HTML",
53728
+ disable_notification: true
53729
+ }), { chat_id: chat, ...thread != null ? { threadId: thread } : {}, verb: "activity-summary.send" });
53730
+ turn.activityMessageId = sent.message_id;
53731
+ } else {
53732
+ const id = turn.activityMessageId;
53733
+ await robustApiCall(() => bot.api.editMessageText(chat, id, html, { parse_mode: "HTML" }), { chat_id: chat, ...thread != null ? { threadId: thread } : {}, verb: "activity-summary.edit" });
53734
+ }
53735
+ turn.activityLastSentRender = target;
53736
+ } catch (err) {
53737
+ const msg = err instanceof Error ? err.message : String(err);
53738
+ if (!msg.includes("message is not modified")) {
53739
+ process.stderr.write(`telegram gateway: activity-summary drain failed: ${msg}
53740
+ `);
53741
+ }
53742
+ turn.activityLastSentRender = target;
53743
+ }
53744
+ }
53745
+ } finally {
53746
+ turn.activityInFlight = null;
53747
+ }
53748
+ }
53749
+ function clearActivitySummary(turn) {
53750
+ const chat = turn.sessionChatId;
53751
+ const thread = turn.sessionThreadId;
53752
+ const inFlight = turn.activityInFlight ?? Promise.resolve();
53753
+ inFlight.then(async () => {
53754
+ if (turn.activityDraftId != null && sendMessageDraftFn != null) {
53755
+ const draftId = turn.activityDraftId;
53756
+ turn.activityDraftId = null;
53757
+ try {
53758
+ await sendMessageDraftFn(chat, draftId, "", undefined);
53759
+ } catch (err) {
53760
+ process.stderr.write(`telegram gateway: activity-summary draft-clear failed: ${err}
53761
+ `);
53762
+ }
53763
+ } else if (turn.activityMessageId != null) {
53764
+ const id = turn.activityMessageId;
53765
+ turn.activityMessageId = null;
53766
+ try {
53767
+ await robustApiCall(() => bot.api.deleteMessage(chat, id), { chat_id: chat, ...thread != null ? { threadId: thread } : {}, verb: "activity-summary.delete" });
53768
+ } catch (err) {
53769
+ process.stderr.write(`telegram gateway: activity-summary delete failed: ${err}
53770
+ `);
53771
+ }
53772
+ }
53773
+ });
53774
+ }
53862
53775
  function handleSessionEvent(ev) {
53863
53776
  switch (ev.kind) {
53864
53777
  case "enqueue": {
@@ -53892,7 +53805,12 @@ function handleSessionEvent(ev) {
53892
53805
  lastAssistantMsgId: null,
53893
53806
  lastAssistantDone: false,
53894
53807
  toolCallCount: 0,
53895
- intentSurfaceFired: false,
53808
+ toolActivity: makeEmptyActivityState(),
53809
+ activityMessageId: null,
53810
+ activityDraftId: null,
53811
+ activityInFlight: null,
53812
+ activityPendingRender: null,
53813
+ activityLastSentRender: null,
53896
53814
  answerStream: null,
53897
53815
  isDm: isDmChatId(ev.chatId)
53898
53816
  };
@@ -53952,37 +53870,29 @@ function handleSessionEvent(ev) {
53952
53870
  const ctrl = activeStatusReactions.get(statusKey(turn.sessionChatId, turn.sessionThreadId));
53953
53871
  const name = ev.toolName;
53954
53872
  if (isTelegramReplyTool(name)) {
53873
+ const wasFirstReply = !turn.replyCalled;
53955
53874
  turn.replyCalled = true;
53956
53875
  if (turn.orphanedReplyTimeoutId != null) {
53957
53876
  clearTimeout(turn.orphanedReplyTimeoutId);
53958
53877
  turn.orphanedReplyTimeoutId = null;
53959
53878
  }
53879
+ if (wasFirstReply) {
53880
+ clearActivitySummary(turn);
53881
+ }
53960
53882
  }
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) {
53883
+ if (!turn.replyCalled && !isTelegramSurfaceTool(name)) {
53884
+ const rendered = registerAndRender(turn.toolActivity, name);
53885
+ if (rendered != null) {
53965
53886
  try {
53966
53887
  markAckSent();
53967
53888
  } catch (err) {
53968
- process.stderr.write(`telegram gateway: intent-surface markAckSent failed: ${err}
53889
+ process.stderr.write(`telegram gateway: activity-summary markAckSent failed: ${err}
53969
53890
  `);
53970
53891
  }
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
- })();
53892
+ turn.activityPendingRender = rendered;
53893
+ if (turn.activityInFlight == null) {
53894
+ turn.activityInFlight = drainActivitySummary(turn);
53895
+ }
53986
53896
  }
53987
53897
  }
53988
53898
  if (!ctrl)
@@ -55339,7 +55249,7 @@ function getMyAgentName() {
55339
55249
  const fromEnv = process.env.SWITCHROOM_AGENT_NAME;
55340
55250
  if (fromEnv && fromEnv.trim().length > 0)
55341
55251
  return fromEnv.trim();
55342
- return basename8(process.cwd());
55252
+ return basename7(process.cwd());
55343
55253
  }
55344
55254
  function isSelfTargetingCommand(name) {
55345
55255
  if (name === "all")