switchroom 0.18.18 → 0.18.19

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.
@@ -6824,99 +6824,28 @@ function hardenCardBreaks(text) {
6824
6824
  }
6825
6825
  return restore(pieces.join(""));
6826
6826
  }
6827
- function addParagraphSpacers(text) {
6828
- if (!text.includes(`
6829
-
6830
- `))
6831
- return text;
6832
- const nonce = Math.random().toString(36).slice(2);
6833
- const { masked, restore, placeholder } = maskCodeRegions(text, nonce);
6834
- if (!masked.includes(`
6835
-
6836
- `))
6837
- return restore(masked);
6838
- const spacerLine = PARAGRAPH_SPACER;
6839
- const isBlankLine = (line) => /^[ \t\r\f\v]*$/.test(line);
6840
- const asciiTrim = (line) => line.replace(/^[ \t\r\f\v]+|[ \t\r\f\v]+$/g, "");
6841
- const blockKind = (line) => {
6842
- if (asciiTrim(line) === spacerLine)
6843
- return "spacer";
6844
- if (isFenceOpenLine(line, placeholder))
6845
- return "fence";
6846
- if (isListItemLine(line))
6847
- return "list";
6848
- if (isTableRowLine(line) || isTableDelimiterLine(line))
6849
- return "table";
6850
- if (isBlockquoteLine(line))
6851
- return "quote";
6852
- if (isHeadingLine(line))
6853
- return "heading";
6854
- if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line.trimStart()))
6855
- return "divider";
6856
- return "prose";
6857
- };
6858
- const SAME_KIND_TIGHT = new Set([
6859
- "list",
6860
- "table",
6861
- "quote",
6862
- "fence",
6863
- "divider"
6864
- ]);
6865
- const shouldSpaceGap = (above, below) => {
6866
- const a = blockKind(above);
6867
- const b = blockKind(below);
6868
- if (a === "spacer" || b === "spacer")
6869
- return false;
6870
- if (a === b && SAME_KIND_TIGHT.has(a))
6871
- return false;
6872
- return true;
6873
- };
6874
- const lines = masked.split(`
6875
- `);
6876
- const out = [];
6877
- for (let i = 0;i < lines.length; i++) {
6878
- const line = lines[i];
6879
- const isBlank = isBlankLine(line);
6880
- if (isBlank) {
6881
- const prevEmitted = out.length > 0 ? out[out.length - 1] : null;
6882
- const prevIsBlank = prevEmitted != null && isBlankLine(prevEmitted);
6883
- if (!prevIsBlank) {
6884
- const above = lastNonBlank(out, isBlankLine);
6885
- const below = nextNonBlank(lines, i + 1, isBlankLine);
6886
- const alreadySpaced = above != null && asciiTrim(above) === spacerLine || below != null && asciiTrim(below) === spacerLine;
6887
- if (!alreadySpaced && above != null && below != null && shouldSpaceGap(above, below)) {
6888
- out.push("");
6889
- out.push(spacerLine);
6890
- out.push("");
6891
- continue;
6892
- }
6893
- }
6894
- }
6895
- out.push(line);
6896
- }
6897
- return restore(out.join(`
6898
- `));
6899
- }
6900
- function lastNonBlank(arr, isBlank) {
6901
- for (let i = arr.length - 1;i >= 0; i--) {
6902
- if (!isBlank(arr[i]))
6903
- return arr[i];
6904
- }
6905
- return null;
6906
- }
6907
- function nextNonBlank(lines, from, isBlank) {
6908
- for (let i = from;i < lines.length; i++) {
6909
- if (!isBlank(lines[i]))
6910
- return lines[i];
6911
- }
6912
- return null;
6913
- }
6914
6827
  function normalizePunctuation(text) {
6915
6828
  if (!/[\u2014\u2013\u2022\u00b7]/.test(text))
6916
6829
  return text;
6917
6830
  const nonce = Math.random().toString(36).slice(2);
6918
6831
  const { masked, restore } = maskCodeRegions(text, nonce);
6919
- let out = masked.replace(/(\S)[ \t][\u2014\u2013][ \t](?=(\S))/g, (_m, a, b) => /\d/.test(a) && /\d/.test(b) ? `${a}-` : `${a}, `).replace(/(\w)\u2014(?=(\w))/g, (_m, a, b) => /\d/.test(a) && /\d/.test(b) ? `${a}-` : `${a}, `).replace(/(\w)\u2013(?=\w)/g, "$1-");
6832
+ const linkMasks = [];
6833
+ const LINK_MASK_PH = `\x00RML${nonce}_`;
6834
+ const maskedLinks = masked.replace(/(\]\()([^)\n]*)(\))/g, (_m, open, href, close) => {
6835
+ const idx = linkMasks.length;
6836
+ linkMasks.push(href);
6837
+ return `${open}${LINK_MASK_PH}${idx}\x00${close}`;
6838
+ });
6839
+ const maskedAutolinks = maskedLinks.replace(/(<)([a-zA-Z][a-zA-Z0-9+.-]*:[^>\s]*)(>)/g, (_m, lt, uri, gt) => {
6840
+ const idx = linkMasks.length;
6841
+ linkMasks.push(uri);
6842
+ return `${lt}${LINK_MASK_PH}${idx}\x00${gt}`;
6843
+ });
6844
+ const escNonce = nonce.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6845
+ const linkRestoreRe = new RegExp(`\x00RML${escNonce}_(\\d+)\x00`, "g");
6846
+ const restoreLinks = (s) => s.replace(linkRestoreRe, (_m, idx) => linkMasks[Number(idx)] ?? _m);
6847
+ let out = maskedAutolinks.replace(/(\S)[ \t][\u2014\u2013][ \t](?=(\S))/g, (_m, a, b) => /\d/.test(a) && /\d/.test(b) ? `${a}-` : `${a}, `).replace(/(\w)\u2014(?=(\w))/g, (_m, a, b) => /\d/.test(a) && /\d/.test(b) ? `${a}-` : `${a}, `).replace(/(\w)\u2013(?=\w)/g, "$1-");
6848
+ out = restoreLinks(out);
6920
6849
  out = out.split(`
6921
6850
  `).map((line) => line.replace(/^([ \t]*)[\u2022\u00b7][ \t]+/, "$1- ")).join(`
6922
6851
  `);
@@ -7109,6 +7038,7 @@ function splitMarkdownChunks(text, maxLen = RICH_MESSAGE_MAX_CHARS) {
7109
7038
  }
7110
7039
  cut = backOffOpenFence(rest, cut);
7111
7040
  cut = backOffTableRow(rest, cut);
7041
+ cut = backOffOpenInline(rest, cut);
7112
7042
  if (cut <= 0) {
7113
7043
  const sliced = hardSliceToCap(rest, maxLen);
7114
7044
  chunks.push(stripBoundarySpacers(sliced[0], "trailing"));
@@ -7121,11 +7051,10 @@ function splitMarkdownChunks(text, maxLen = RICH_MESSAGE_MAX_CHARS) {
7121
7051
  return chunks.map((c) => stripBoundarySpacers(c, "trailing"));
7122
7052
  }
7123
7053
  function stripBoundarySpacers(chunk, side) {
7124
- const sp = PARAGRAPH_SPACER;
7125
7054
  if (side === "leading") {
7126
- return chunk.replace(new RegExp(`^(?:[ \\t]*${sp}?[ \\t]*\\n+)+`), "");
7055
+ return chunk.replace(/^(?:[ \t]*\n)+/, "");
7127
7056
  }
7128
- return chunk.replace(new RegExp(`(?:\\n+[ \\t]*${sp}?[ \\t]*)+$`), "");
7057
+ return chunk.replace(/(?:\n[ \t]*)+$/, "");
7129
7058
  }
7130
7059
  function backOffOpenFence(text, cut) {
7131
7060
  if (cut <= 0 || cut >= text.length)
@@ -7154,7 +7083,38 @@ function backOffTableRow(text, cut) {
7154
7083
  }
7155
7084
  return cut;
7156
7085
  }
7157
- var RICH_MESSAGE_MAX_CHARS = 32768, PARAGRAPH_SPACER = "\u00a0";
7086
+ function backOffOpenInline(text, cut) {
7087
+ if (cut <= 0 || cut >= text.length)
7088
+ return cut;
7089
+ let earliest = cut;
7090
+ for (const re of INLINE_SPAN_PATTERNS) {
7091
+ re.lastIndex = 0;
7092
+ let m;
7093
+ while ((m = re.exec(text)) !== null) {
7094
+ const start = m.index;
7095
+ const end = start + m[0].length;
7096
+ if (start < cut && cut < end && start < earliest)
7097
+ earliest = start;
7098
+ if (start >= cut)
7099
+ break;
7100
+ if (re.lastIndex === start)
7101
+ re.lastIndex = start + 1;
7102
+ }
7103
+ }
7104
+ return earliest;
7105
+ }
7106
+ var RICH_MESSAGE_MAX_CHARS = 32768, INLINE_SPAN_PATTERNS;
7107
+ var init_format = __esm(() => {
7108
+ INLINE_SPAN_PATTERNS = [
7109
+ /`[^`\n]+`/g,
7110
+ /\*\*\*[^*\n]+\*\*\*/g,
7111
+ /___[^_\n]+___/g,
7112
+ /\*\*[^*\n]+\*\*/g,
7113
+ /__[^_\n]+__/g,
7114
+ /(?<![\w*])_[^_\n]+_(?![\w*])/g,
7115
+ /\[[^\]\n]*\]\([^)\n]*\)/g
7116
+ ];
7117
+ });
7158
7118
 
7159
7119
  // text-voice-scrub.ts
7160
7120
  function enabled() {
@@ -7339,6 +7299,7 @@ function cleanWorkerResultParagraph(s) {
7339
7299
  return kept.join(" ").replace(/\s+/g, " ").trim();
7340
7300
  }
7341
7301
  var init_card_format = __esm(() => {
7302
+ init_format();
7342
7303
  init_text_voice_scrub();
7343
7304
  });
7344
7305
 
@@ -7480,6 +7441,7 @@ function ttlMsFromToken(token) {
7480
7441
  }
7481
7442
  var import_grammy3;
7482
7443
  var init_approval_card = __esm(() => {
7444
+ init_format();
7483
7445
  import_grammy3 = __toESM(require_mod2(), 1);
7484
7446
  });
7485
7447
 
@@ -36885,6 +36847,7 @@ function parseConfigApprovalCallback(data) {
36885
36847
  var pending, TELEGRAM_SENDMESSAGE_LIMIT2 = 32768, RENDERED_BODY_CAP2 = 32000, REASON_MAX_CHARS = 500, REASON_ELLIPSIS = "\u2026", DIFF_SENTINEL = `
36886
36848
  [\u2026 diff continues, see attached file]`;
36887
36849
  var init_config_approval_handler = __esm(() => {
36850
+ init_format();
36888
36851
  pending = new Map;
36889
36852
  });
36890
36853
 
@@ -37009,6 +36972,7 @@ ${detail}`)));
37009
36972
  });
37010
36973
  }
37011
36974
  var init_approvals_commands = __esm(() => {
36975
+ init_format();
37012
36976
  init_rich_send();
37013
36977
  init_client3();
37014
36978
  });
@@ -39778,6 +39742,7 @@ class DeferredDoneReactions {
39778
39742
  init_card_format();
39779
39743
 
39780
39744
  // status-no-truncate.ts
39745
+ init_format();
39781
39746
  var STATUS_ROLLING_LINES = 5;
39782
39747
  var STATUS_LINE_MAX = 200;
39783
39748
  var STATUS_CARD_CHAR_BUDGET = RICH_MESSAGE_MAX_CHARS;
@@ -41247,6 +41212,7 @@ var import_grammy2 = __toESM(require_mod2(), 1);
41247
41212
  var import_runner = __toESM(require_mod4(), 1);
41248
41213
  import { AsyncLocalStorage } from "async_hooks";
41249
41214
  init_flood_circuit_breaker();
41215
+ init_format();
41250
41216
 
41251
41217
  // shared/gw-trace-gate.ts
41252
41218
  function computeGwTraceVerbose(flag) {
@@ -41281,6 +41247,7 @@ function escapeHtmlForTg(text) {
41281
41247
 
41282
41248
  // gateway/vault-request-access-card.ts
41283
41249
  init_approval_card();
41250
+ init_format();
41284
41251
  function renderVaultRequestAccessCard(req) {
41285
41252
  const lines = [];
41286
41253
  const scopeLabel = req.scope === "write" ? "write" : "read";
@@ -54817,6 +54784,7 @@ function parse2(markdown) {
54817
54784
  }
54818
54785
 
54819
54786
  // render/render.ts
54787
+ init_format();
54820
54788
  function renderInline(node2, ctx = {}) {
54821
54789
  switch (node2.type) {
54822
54790
  case "plain":
@@ -55022,6 +54990,7 @@ function renderSafe(doc, source, maxLen = RICH_MESSAGE_MAX_CHARS) {
55022
54990
  }
55023
54991
 
55024
54992
  // render/rich-render.ts
54993
+ init_format();
55025
54994
  var PLAIN_TEXT_MAX_CHARS = 4096;
55026
54995
  function parseRichRenderEnabled(raw) {
55027
54996
  if (raw == null)
@@ -55307,6 +55276,10 @@ function handlePtyPartialPure(text4, state, deps) {
55307
55276
  stream.update(text4).catch(() => {});
55308
55277
  return created ? "update-new" : "update-existing";
55309
55278
  }
55279
+
55280
+ // stream-reply-handler.ts
55281
+ init_format();
55282
+
55310
55283
  // chat-lock.ts
55311
55284
  function createChatLock() {
55312
55285
  const chains = new Map;
@@ -56401,6 +56374,7 @@ var import_runner2 = __toESM(require_mod4(), 1);
56401
56374
  import { createHash as createHash2 } from "crypto";
56402
56375
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
56403
56376
  init_flood_circuit_breaker();
56377
+ init_format();
56404
56378
  var tgPostTagStore2 = new AsyncLocalStorage2;
56405
56379
  function _getTgPostTags() {
56406
56380
  return tgPostTagStore2.getStore();
@@ -61497,6 +61471,7 @@ function decideOverPing(input) {
61497
61471
  }
61498
61472
 
61499
61473
  // silent-reply-anchor.ts
61474
+ init_format();
61500
61475
  var TELEGRAM_MSG_CAP = RICH_MESSAGE_MAX_CHARS;
61501
61476
  function enabled3() {
61502
61477
  const v = process.env.SWITCHROOM_DISABLE_SILENT_REPLY_AUTOEDIT;
@@ -62634,6 +62609,7 @@ function safeResolvePersonName(directory, opts, rawFallback) {
62634
62609
  }
62635
62610
 
62636
62611
  // gateway/auth-command.ts
62612
+ init_format();
62637
62613
  init_auth_snapshot_format();
62638
62614
  init_demo_mask();
62639
62615
  var AUTH_RM_CONFIRM_TTL_MS = 60000;
@@ -64783,6 +64759,10 @@ function autoClassifyMidTurnInbound(i) {
64783
64759
  return { decision: "queue", reason: "cross_topic", sameTopic: false };
64784
64760
  return recent && i.msSinceLastAgentOutput <= i.topicSteerWindowMs ? { decision: "steer", reason: "same_topic_recent", sameTopic: true } : { decision: "queue", reason: "same_topic_stale", sameTopic: true };
64785
64761
  }
64762
+
64763
+ // operator-events.ts
64764
+ init_format();
64765
+
64786
64766
  // raw-error-scrub.ts
64787
64767
  function stripRawErrorBytes(raw) {
64788
64768
  if (typeof raw !== "string" || raw.length === 0)
@@ -65352,7 +65332,9 @@ function renderThrottleEscalationNotice(opts) {
65352
65332
  return `${head}
65353
65333
  ${tail}`;
65354
65334
  }
65335
+
65355
65336
  // operator-events.ts
65337
+ init_format();
65356
65338
  function classifyClaudeError(raw) {
65357
65339
  try {
65358
65340
  return classifyInner(raw);
@@ -65539,6 +65521,26 @@ function formatRelativeTail(deltaMs) {
65539
65521
  const remH = hours % 24;
65540
65522
  return remH > 0 ? `~in ${days}d ${remH}h` : `~in ${days}d`;
65541
65523
  }
65524
+ function formatResetClock(resetAt, tz) {
65525
+ if (resetAt == null)
65526
+ return "";
65527
+ const ms = resetAt.getTime();
65528
+ if (!Number.isFinite(ms))
65529
+ return "";
65530
+ return `${fmtLocalClock(ms, tz)} ${tzAbbrev(ms, tz)}`;
65531
+ }
65532
+ function buildRecommendation(parsed, tz) {
65533
+ switch (parsed.kind) {
65534
+ case "auth":
65535
+ return "\u2192 Re-authenticate this account to continue.";
65536
+ case "quota_wall": {
65537
+ const reset2 = formatResetClock(parsed.resetAt, tz);
65538
+ return reset2 ? `\u2192 Switch to another account, or wait for the quota to reset at ${reset2}.` : "\u2192 Switch to another account, or wait for the quota to reset.";
65539
+ }
65540
+ default:
65541
+ return;
65542
+ }
65543
+ }
65542
65544
  function renderLlmError(parsed, agent, tz, now = new Date) {
65543
65545
  const safeAgent = escapeAgent(agent);
65544
65546
  const emoji = kindEmoji(parsed.kind);
@@ -65548,32 +65550,18 @@ function renderLlmError(parsed, agent, tz, now = new Date) {
65548
65550
  lines.push(`_${resetLine}_`);
65549
65551
  if (parsed.model)
65550
65552
  lines.push(`_model: ${escapeAgent(parsed.model)}_`);
65551
- const text4 = lines.join(`
65552
- `);
65553
- switch (parsed.kind) {
65554
- case "auth":
65555
- return {
65556
- text: text4,
65557
- keyboard: {
65558
- inline_keyboard: [
65559
- [
65560
- { text: "\uD83D\uDD10 Reauth now", callback_data: `op:reauth:${encodeURIComponent(agent)}` },
65561
- { text: "\u274c Dismiss", callback_data: `op:dismiss:${encodeURIComponent(agent)}` }
65562
- ]
65563
- ]
65564
- }
65565
- };
65566
- case "quota_wall":
65567
- return {
65568
- text: text4,
65569
- keyboard: {
65570
- inline_keyboard: [
65571
- [{ text: "\u23f3 Wait", callback_data: `op:dismiss:${encodeURIComponent(agent)}` }]
65572
- ]
65573
- }
65574
- };
65575
- default:
65576
- return { text: text4 };
65553
+ const recommendation2 = buildRecommendation(parsed, tz);
65554
+ if (recommendation2)
65555
+ lines.push(recommendation2);
65556
+ return { text: lines.join(`
65557
+ `) };
65558
+ }
65559
+ function renderLlmErrorSafe(parsed, agent, tz, now = new Date) {
65560
+ try {
65561
+ return renderLlmError(parsed, agent, tz, now);
65562
+ } catch {
65563
+ const safeAgent = escapeAgent(agent);
65564
+ return { text: `${kindEmoji(parsed.kind)} ${parsed.coreText} (**${safeAgent}**)` };
65577
65565
  }
65578
65566
  }
65579
65567
  function kindEmoji(kind) {
@@ -66535,100 +66523,28 @@ function hardenCardBreaks2(text4) {
66535
66523
  }
66536
66524
  return restore2(pieces.join(""));
66537
66525
  }
66538
- var PARAGRAPH_SPACER2 = "\u00a0";
66539
- function addParagraphSpacers2(text4) {
66540
- if (!text4.includes(`
66541
-
66542
- `))
66543
- return text4;
66544
- const nonce = Math.random().toString(36).slice(2);
66545
- const { masked, restore: restore2, placeholder } = maskCodeRegions2(text4, nonce);
66546
- if (!masked.includes(`
66547
-
66548
- `))
66549
- return restore2(masked);
66550
- const spacerLine = PARAGRAPH_SPACER2;
66551
- const isBlankLine = (line) => /^[ \t\r\f\v]*$/.test(line);
66552
- const asciiTrim = (line) => line.replace(/^[ \t\r\f\v]+|[ \t\r\f\v]+$/g, "");
66553
- const blockKind = (line) => {
66554
- if (asciiTrim(line) === spacerLine)
66555
- return "spacer";
66556
- if (isFenceOpenLine2(line, placeholder))
66557
- return "fence";
66558
- if (isListItemLine2(line))
66559
- return "list";
66560
- if (isTableRowLine2(line) || isTableDelimiterLine2(line))
66561
- return "table";
66562
- if (isBlockquoteLine2(line))
66563
- return "quote";
66564
- if (isHeadingLine2(line))
66565
- return "heading";
66566
- if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line.trimStart()))
66567
- return "divider";
66568
- return "prose";
66569
- };
66570
- const SAME_KIND_TIGHT = new Set([
66571
- "list",
66572
- "table",
66573
- "quote",
66574
- "fence",
66575
- "divider"
66576
- ]);
66577
- const shouldSpaceGap = (above, below) => {
66578
- const a = blockKind(above);
66579
- const b = blockKind(below);
66580
- if (a === "spacer" || b === "spacer")
66581
- return false;
66582
- if (a === b && SAME_KIND_TIGHT.has(a))
66583
- return false;
66584
- return true;
66585
- };
66586
- const lines = masked.split(`
66587
- `);
66588
- const out = [];
66589
- for (let i = 0;i < lines.length; i++) {
66590
- const line = lines[i];
66591
- const isBlank = isBlankLine(line);
66592
- if (isBlank) {
66593
- const prevEmitted = out.length > 0 ? out[out.length - 1] : null;
66594
- const prevIsBlank = prevEmitted != null && isBlankLine(prevEmitted);
66595
- if (!prevIsBlank) {
66596
- const above = lastNonBlank2(out, isBlankLine);
66597
- const below = nextNonBlank2(lines, i + 1, isBlankLine);
66598
- const alreadySpaced = above != null && asciiTrim(above) === spacerLine || below != null && asciiTrim(below) === spacerLine;
66599
- if (!alreadySpaced && above != null && below != null && shouldSpaceGap(above, below)) {
66600
- out.push("");
66601
- out.push(spacerLine);
66602
- out.push("");
66603
- continue;
66604
- }
66605
- }
66606
- }
66607
- out.push(line);
66608
- }
66609
- return restore2(out.join(`
66610
- `));
66611
- }
66612
- function lastNonBlank2(arr, isBlank) {
66613
- for (let i = arr.length - 1;i >= 0; i--) {
66614
- if (!isBlank(arr[i]))
66615
- return arr[i];
66616
- }
66617
- return null;
66618
- }
66619
- function nextNonBlank2(lines, from, isBlank) {
66620
- for (let i = from;i < lines.length; i++) {
66621
- if (!isBlank(lines[i]))
66622
- return lines[i];
66623
- }
66624
- return null;
66625
- }
66626
66526
  function normalizePunctuation2(text4) {
66627
66527
  if (!/[\u2014\u2013\u2022\u00b7]/.test(text4))
66628
66528
  return text4;
66629
66529
  const nonce = Math.random().toString(36).slice(2);
66630
66530
  const { masked, restore: restore2 } = maskCodeRegions2(text4, nonce);
66631
- let out = masked.replace(/(\S)[ \t][\u2014\u2013][ \t](?=(\S))/g, (_m, a, b) => /\d/.test(a) && /\d/.test(b) ? `${a}-` : `${a}, `).replace(/(\w)\u2014(?=(\w))/g, (_m, a, b) => /\d/.test(a) && /\d/.test(b) ? `${a}-` : `${a}, `).replace(/(\w)\u2013(?=\w)/g, "$1-");
66531
+ const linkMasks = [];
66532
+ const LINK_MASK_PH = `\x00RML${nonce}_`;
66533
+ const maskedLinks = masked.replace(/(\]\()([^)\n]*)(\))/g, (_m, open, href, close) => {
66534
+ const idx = linkMasks.length;
66535
+ linkMasks.push(href);
66536
+ return `${open}${LINK_MASK_PH}${idx}\x00${close}`;
66537
+ });
66538
+ const maskedAutolinks = maskedLinks.replace(/(<)([a-zA-Z][a-zA-Z0-9+.-]*:[^>\s]*)(>)/g, (_m, lt, uri, gt) => {
66539
+ const idx = linkMasks.length;
66540
+ linkMasks.push(uri);
66541
+ return `${lt}${LINK_MASK_PH}${idx}\x00${gt}`;
66542
+ });
66543
+ const escNonce = nonce.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
66544
+ const linkRestoreRe = new RegExp(`\x00RML${escNonce}_(\\d+)\x00`, "g");
66545
+ const restoreLinks = (s) => s.replace(linkRestoreRe, (_m, idx) => linkMasks[Number(idx)] ?? _m);
66546
+ let out = maskedAutolinks.replace(/(\S)[ \t][\u2014\u2013][ \t](?=(\S))/g, (_m, a, b) => /\d/.test(a) && /\d/.test(b) ? `${a}-` : `${a}, `).replace(/(\w)\u2014(?=(\w))/g, (_m, a, b) => /\d/.test(a) && /\d/.test(b) ? `${a}-` : `${a}, `).replace(/(\w)\u2013(?=\w)/g, "$1-");
66547
+ out = restoreLinks(out);
66632
66548
  out = out.split(`
66633
66549
  `).map((line) => line.replace(/^([ \t]*)[\u2022\u00b7][ \t]+/, "$1- ")).join(`
66634
66550
  `);
@@ -66821,6 +66737,7 @@ function splitMarkdownChunks2(text4, maxLen = RICH_MESSAGE_MAX_CHARS2) {
66821
66737
  }
66822
66738
  cut = backOffOpenFence2(rest, cut);
66823
66739
  cut = backOffTableRow2(rest, cut);
66740
+ cut = backOffOpenInline2(rest, cut);
66824
66741
  if (cut <= 0) {
66825
66742
  const sliced = hardSliceToCap2(rest, maxLen);
66826
66743
  chunks.push(stripBoundarySpacers2(sliced[0], "trailing"));
@@ -66833,11 +66750,10 @@ function splitMarkdownChunks2(text4, maxLen = RICH_MESSAGE_MAX_CHARS2) {
66833
66750
  return chunks.map((c) => stripBoundarySpacers2(c, "trailing"));
66834
66751
  }
66835
66752
  function stripBoundarySpacers2(chunk2, side) {
66836
- const sp = PARAGRAPH_SPACER2;
66837
66753
  if (side === "leading") {
66838
- return chunk2.replace(new RegExp(`^(?:[ \\t]*${sp}?[ \\t]*\\n+)+`), "");
66754
+ return chunk2.replace(/^(?:[ \t]*\n)+/, "");
66839
66755
  }
66840
- return chunk2.replace(new RegExp(`(?:\\n+[ \\t]*${sp}?[ \\t]*)+$`), "");
66756
+ return chunk2.replace(/(?:\n[ \t]*)+$/, "");
66841
66757
  }
66842
66758
  function backOffOpenFence2(text4, cut) {
66843
66759
  if (cut <= 0 || cut >= text4.length)
@@ -66866,6 +66782,35 @@ function backOffTableRow2(text4, cut) {
66866
66782
  }
66867
66783
  return cut;
66868
66784
  }
66785
+ var INLINE_SPAN_PATTERNS2 = [
66786
+ /`[^`\n]+`/g,
66787
+ /\*\*\*[^*\n]+\*\*\*/g,
66788
+ /___[^_\n]+___/g,
66789
+ /\*\*[^*\n]+\*\*/g,
66790
+ /__[^_\n]+__/g,
66791
+ /(?<![\w*])_[^_\n]+_(?![\w*])/g,
66792
+ /\[[^\]\n]*\]\([^)\n]*\)/g
66793
+ ];
66794
+ function backOffOpenInline2(text4, cut) {
66795
+ if (cut <= 0 || cut >= text4.length)
66796
+ return cut;
66797
+ let earliest = cut;
66798
+ for (const re of INLINE_SPAN_PATTERNS2) {
66799
+ re.lastIndex = 0;
66800
+ let m;
66801
+ while ((m = re.exec(text4)) !== null) {
66802
+ const start = m.index;
66803
+ const end = start + m[0].length;
66804
+ if (start < cut && cut < end && start < earliest)
66805
+ earliest = start;
66806
+ if (start >= cut)
66807
+ break;
66808
+ if (re.lastIndex === start)
66809
+ re.lastIndex = start + 1;
66810
+ }
66811
+ }
66812
+ return earliest;
66813
+ }
66869
66814
 
66870
66815
  // rich-send.ts
66871
66816
  var import_grammy8 = __toESM(require_mod2(), 1);
@@ -66984,6 +66929,7 @@ function scrubVoice2(text4) {
66984
66929
  }
66985
66930
 
66986
66931
  // gateway/outbound-send-path.ts
66932
+ init_format();
66987
66933
  init_text_voice_scrub();
66988
66934
  function normalizeOutboundBody(rawText, site, redact2) {
66989
66935
  let text4 = normalizeParagraphBreaks(repairEscapedWhitespace(rawText));
@@ -66997,8 +66943,8 @@ function normalizeOutboundBody(rawText, site, redact2) {
66997
66943
  }
66998
66944
  return { text: text4, voiceReplaced };
66999
66945
  }
67000
- function computeEffectiveText(text4, literalText) {
67001
- return literalText ? text4 : addParagraphSpacers(text4);
66946
+ function computeEffectiveText(text4, _literalText) {
66947
+ return text4;
67002
66948
  }
67003
66949
  function computeReplyChunks(args) {
67004
66950
  const { effectiveText, literalText, limit, chunkMode } = args;
@@ -69339,7 +69285,9 @@ function makeTmuxRunner2(tmuxBin) {
69339
69285
  }
69340
69286
  };
69341
69287
  }
69288
+
69342
69289
  // stream-reply-handler.ts
69290
+ init_format();
69343
69291
  function buildAccentHeader(accent) {
69344
69292
  switch (accent) {
69345
69293
  case "in-progress":
@@ -73169,6 +73117,7 @@ function recordWebhookEvent(rec, deps = {}) {
73169
73117
  }
73170
73118
 
73171
73119
  // gateway/ipc-server.ts
73120
+ init_format();
73172
73121
  import { renameSync as renameSync11, unlinkSync as unlinkSync14, chmodSync as chmodSync9 } from "fs";
73173
73122
  var MAX_BUFFER_SIZE = 1024 * 1024;
73174
73123
  var VALID_OPERATOR_KINDS = new Set([
@@ -73874,6 +73823,7 @@ function validateInput(input) {
73874
73823
  }
73875
73824
 
73876
73825
  // gateway/drive-write-approval.ts
73826
+ init_format();
73877
73827
  var DEFAULT_TTL_MS = 5 * 60 * 1000;
73878
73828
  var MAX_TTL_MS = 30 * 60 * 1000;
73879
73829
  var MIN_TTL_MS = 30 * 1000;
@@ -74004,6 +73954,7 @@ function clampTtl(requested, fallback, min, max) {
74004
73954
  }
74005
73955
 
74006
73956
  // gateway/ms365-write-approval.ts
73957
+ init_format();
74007
73958
  function validateMs365Preview(input) {
74008
73959
  if (!input || typeof input !== "object")
74009
73960
  return null;
@@ -74182,6 +74133,7 @@ async function handleRequestMs365Approval(client3, msg, deps) {
74182
74133
  }
74183
74134
 
74184
74135
  // gateway/diff-preview-card.ts
74136
+ init_format();
74185
74137
  var import_grammy10 = __toESM(require_mod2(), 1);
74186
74138
  var REQUEST_ID_RE = /^[0-9a-f]{32}$/;
74187
74139
  var PENDING_FILE_ID_SENTINEL = "pending-create";
@@ -76340,6 +76292,7 @@ function maybeFireWarmup(ctx) {
76340
76292
 
76341
76293
  // gateway/mental-model-propose-card.ts
76342
76294
  init_approval_card();
76295
+ init_format();
76343
76296
  function renderMentalModelProposeCard(req) {
76344
76297
  const lines = [];
76345
76298
  lines.push(`\uD83E\uDDE0 **${escapeHtmlForTg(req.agent)}** proposes a mental model`);
@@ -82081,10 +82034,10 @@ function readTurnActiveMarkerAgeMs(stateDir, now) {
82081
82034
  }
82082
82035
 
82083
82036
  // ../src/build-info.ts
82084
- var VERSION = "0.18.18";
82085
- var COMMIT_SHA = "a256b3b1";
82086
- var COMMIT_DATE = "2026-07-13T03:10:38Z";
82087
- var LATEST_PR = 3210;
82037
+ var VERSION = "0.18.19";
82038
+ var COMMIT_SHA = "34c72776";
82039
+ var COMMIT_DATE = "2026-07-13T14:06:25+10:00";
82040
+ var LATEST_PR = 3212;
82088
82041
  var COMMITS_AHEAD_OF_TAG = 0;
82089
82042
 
82090
82043
  // gateway/boot-version.ts
@@ -82341,6 +82294,7 @@ async function listGrantsViaBroker2(agent, opts) {
82341
82294
  }
82342
82295
 
82343
82296
  // gateway/linear-activity.ts
82297
+ init_format();
82344
82298
  init_client();
82345
82299
 
82346
82300
  // ../src/linear/oauth-refresh.ts
@@ -86768,6 +86722,7 @@ var inboundCoalescer = createInboundCoalescer({
86768
86722
  });
86769
86723
  function emitGatewayOperatorEvent(event) {
86770
86724
  const { agent, kind } = event;
86725
+ event = { ...event, detail: redactOutboundText(event.detail, "operator_event") };
86771
86726
  let throttleEscalation = null;
86772
86727
  let escalationFired = false;
86773
86728
  let rateLimitedCooldownConsulted = false;
@@ -86872,9 +86827,9 @@ function emitGatewayOperatorEvent(event) {
86872
86827
  return;
86873
86828
  }
86874
86829
  const tz = process.env.SWITCHROOM_TIMEZONE ?? process.env.TZ ?? "UTC";
86875
- const r = renderLlmError(parsed, agent, tz, new Date(now));
86830
+ const r = renderLlmErrorSafe(parsed, agent, tz, new Date(now));
86876
86831
  renderedText = r.text;
86877
- renderedKeyboard = r.keyboard;
86832
+ renderedKeyboard = undefined;
86878
86833
  } else {
86879
86834
  try {
86880
86835
  const r = renderOperatorEvent(event);
@@ -90533,7 +90488,7 @@ async function executeEditMessage(args) {
90533
90488
  editRawText = normalizeParagraphBreaks2(editRawText);
90534
90489
  editRawText = redactOutboundText(editRawText, "edit_message");
90535
90490
  if (!editLiteralText)
90536
- editRawText = addParagraphSpacers2(stripExcessBold2(normalizePunctuation2(editRawText)));
90491
+ editRawText = stripExcessBold2(normalizePunctuation2(editRawText));
90537
90492
  {
90538
90493
  const scrub = scrubVoice2(editRawText);
90539
90494
  if (scrub.replaced > 0) {
@@ -91708,7 +91663,7 @@ function handleSessionEvent(ev) {
91708
91663
  link_preview_options: { is_disabled: true }
91709
91664
  };
91710
91665
  const limit = RICH_MESSAGE_MAX_CHARS2;
91711
- const renderedText = addParagraphSpacers2(capturedText);
91666
+ const renderedText = capturedText;
91712
91667
  const htmlChunks = splitMarkdownChunks2(renderedText, limit);
91713
91668
  const sentIds = [];
91714
91669
  try {
@@ -16994,6 +16994,10 @@ var init_plugin_logger = __esm(() => {
16994
16994
  DEFAULT_LOG_PATH2 = join2(homedir2(), ".switchroom", "logs", "telegram-plugin.log");
16995
16995
  ROTATE_AT_BYTES2 = 50 * 1024 * 1024;
16996
16996
  });
16997
+
16998
+ // format.ts
16999
+ var init_format = () => {};
17000
+
16997
17001
  // raw-error-scrub.ts
16998
17002
  function extractRequestId(raw) {
16999
17003
  if (typeof raw !== "string" || raw.length === 0)
@@ -17079,6 +17083,7 @@ function getNestedObj(obj, key) {
17079
17083
  }
17080
17084
  var DEFAULT_OPERATOR_EVENT_COOLDOWN_MS, cooldownMap;
17081
17085
  var init_operator_events = __esm(() => {
17086
+ init_format();
17082
17087
  DEFAULT_OPERATOR_EVENT_COOLDOWN_MS = 5 * 60000;
17083
17088
  cooldownMap = new Map;
17084
17089
  });
@@ -17098,6 +17103,7 @@ var init_text_voice_scrub = __esm(() => {
17098
17103
 
17099
17104
  // card-format.ts
17100
17105
  var init_card_format = __esm(() => {
17106
+ init_format();
17101
17107
  init_text_voice_scrub();
17102
17108
  });
17103
17109