omnius 1.0.170 → 1.0.172

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -546736,14 +546736,30 @@ function estimateTokens2(text) {
546736
546736
  function normalizeSignalContent(content) {
546737
546737
  return content.replace(/\r\n/g, "\n").split("\n").map((line) => line.trimEnd()).join("\n").trim();
546738
546738
  }
546739
+ function urlSpanAt(text, index) {
546740
+ URL_RE.lastIndex = 0;
546741
+ for (const match of text.matchAll(URL_RE)) {
546742
+ const start2 = match.index ?? 0;
546743
+ const end = start2 + match[0].length;
546744
+ if (start2 < index && index < end)
546745
+ return { start: start2, end };
546746
+ }
546747
+ return null;
546748
+ }
546739
546749
  function truncateText2(text, maxChars) {
546740
546750
  if (text.length <= maxChars)
546741
546751
  return { text, truncated: false };
546742
546752
  if (maxChars <= 40)
546743
546753
  return { text: text.slice(0, maxChars), truncated: true };
546754
+ const suffix = CONTEXT_FABRIC_TRUNCATION_SUFFIX;
546755
+ let cutIndex = maxChars - suffix.length;
546756
+ const urlSpan = urlSpanAt(text, cutIndex);
546757
+ if (urlSpan) {
546758
+ cutIndex = urlSpan.start;
546759
+ }
546760
+ const prefix = text.slice(0, Math.max(0, cutIndex)).trimEnd();
546744
546761
  return {
546745
- text: `${text.slice(0, maxChars - 36).trimEnd()}
546746
- ... [truncated by context fabric]`,
546762
+ text: `${prefix}${suffix}`,
546747
546763
  truncated: true
546748
546764
  };
546749
546765
  }
@@ -546812,7 +546828,7 @@ function signalFromBlock(kind, source, content, options2 = {}) {
546812
546828
  metadata: options2.metadata
546813
546829
  };
546814
546830
  }
546815
- var KIND_ORDER, KIND_LABELS, DEFAULT_KIND_CHAR_BUDGET, ContextLedger, ContextFrameBuilder;
546831
+ var KIND_ORDER, KIND_LABELS, DEFAULT_KIND_CHAR_BUDGET, URL_RE, CONTEXT_FABRIC_TRUNCATION_SUFFIX, ContextLedger, ContextFrameBuilder;
546816
546832
  var init_context_fabric = __esm({
546817
546833
  "packages/orchestrator/dist/context-fabric.js"() {
546818
546834
  "use strict";
@@ -546864,6 +546880,8 @@ var init_context_fabric = __esm({
546864
546880
  environment: 900,
546865
546881
  compaction_summary: 1200
546866
546882
  };
546883
+ URL_RE = /\bhttps?:\/\/[^\s<>"'()[\]{}]+/gi;
546884
+ CONTEXT_FABRIC_TRUNCATION_SUFFIX = "\n... [truncated by context fabric]";
546867
546885
  ContextLedger = class {
546868
546886
  signals = /* @__PURE__ */ new Map();
546869
546887
  sequence = 0;
@@ -558648,7 +558666,7 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
558648
558666
  const lines = output.split("\n");
558649
558667
  const { foldLineThreshold, foldHeadLines, foldTailLines } = this.contextLimits();
558650
558668
  if (lines.length <= foldLineThreshold) {
558651
- return output.slice(0, maxChars) + "\n...(truncated)";
558669
+ return this.truncateTextWithoutCuttingUrl(output, maxChars, "\n...(truncated)");
558652
558670
  }
558653
558671
  const headLines = foldHeadLines;
558654
558672
  const tailLines = foldTailLines;
@@ -558661,10 +558679,27 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
558661
558679
 
558662
558680
  ${tail}`;
558663
558681
  if (folded.length > maxChars) {
558664
- return folded.slice(0, maxChars) + "\n...(truncated)";
558682
+ return this.truncateTextWithoutCuttingUrl(folded, maxChars, "\n...(truncated)");
558665
558683
  }
558666
558684
  return folded;
558667
558685
  }
558686
+ truncateTextWithoutCuttingUrl(text, maxChars, suffix = "...") {
558687
+ if (text.length <= maxChars)
558688
+ return text;
558689
+ if (maxChars <= suffix.length)
558690
+ return text.slice(0, maxChars);
558691
+ let cut = maxChars - suffix.length;
558692
+ const urlRe = /\bhttps?:\/\/[^\s<>"'()[\]{}]+/gi;
558693
+ for (const match of text.matchAll(urlRe)) {
558694
+ const start2 = match.index ?? 0;
558695
+ const end = start2 + match[0].length;
558696
+ if (start2 < cut && cut < end) {
558697
+ cut = start2;
558698
+ break;
558699
+ }
558700
+ }
558701
+ return `${text.slice(0, Math.max(0, cut)).trimEnd()}${suffix}`;
558702
+ }
558668
558703
  async appendInjectedUserMessage(userMsg, messages2, turn) {
558669
558704
  const imagePattern = /\[IMAGE_BASE64:([^:]+):([^\]]+)\]/;
558670
558705
  const imgMatch = userMsg.match(imagePattern);
@@ -592291,7 +592326,7 @@ function extractMediaReferences(text) {
592291
592326
  const offset = match[0].indexOf("MEDIA:");
592292
592327
  addCandidate(value2, match[0].slice(offset), match.index + offset, match.index + match[0].length);
592293
592328
  }
592294
- for (const match of matchAll(URL_RE, text)) {
592329
+ for (const match of matchAll(URL_RE2, text)) {
592295
592330
  const original = trimTrailingPunctuation(match[0]);
592296
592331
  if (original.length !== match[0].length) {
592297
592332
  addCandidate(original, original, match.index, match.index + original.length);
@@ -592415,7 +592450,7 @@ function decodeUri(value2) {
592415
592450
  function trimTrailingPunctuation(value2) {
592416
592451
  return value2.replace(/[),.;:!?]+$/, "");
592417
592452
  }
592418
- var IMAGE_EXT, AUDIO_EXT, VIDEO_EXT, DOC_EXT, MEDIA_DIRECTIVE_RE, AUDIO_AS_VOICE_RE, MARKDOWN_IMAGE_RE, HTML_IMG_RE, URL_RE, LOCAL_PATH_RE;
592453
+ var IMAGE_EXT, AUDIO_EXT, VIDEO_EXT, DOC_EXT, MEDIA_DIRECTIVE_RE, AUDIO_AS_VOICE_RE, MARKDOWN_IMAGE_RE, HTML_IMG_RE, URL_RE2, LOCAL_PATH_RE;
592419
592454
  var init_media_routing = __esm({
592420
592455
  "packages/cli/src/tui/media-routing.ts"() {
592421
592456
  "use strict";
@@ -592447,7 +592482,7 @@ var init_media_routing = __esm({
592447
592482
  AUDIO_AS_VOICE_RE = /\[\[audio_as_voice\]\]/gi;
592448
592483
  MARKDOWN_IMAGE_RE = /!\[[^\]]*]\(([^)\s]+)(?:\s+"[^"]*")?\)/g;
592449
592484
  HTML_IMG_RE = /<img\b[^>]*\bsrc\s*=\s*["']([^"']+)["'][^>]*>/gi;
592450
- URL_RE = /\bhttps?:\/\/[^\s<>"')]+/gi;
592485
+ URL_RE2 = /\bhttps?:\/\/[^\s<>"')]+/gi;
592451
592486
  LOCAL_PATH_RE = /(?:^|[\s([])((?:~|\/)[^\s<>"')\]]+\.(?:png|jpe?g|webp|gif|bmp|tiff?|svg|wav|mp3|ogg|oga|opus|m4a|flac|aac|mp4|mov|mkv|webm|avi|m4v|pdf|txt|md|markdown|csv|tsv|jsonl?|xlsx?|docx?|pptx?|html?|xml|zip|tar|gz))(?:$|[\s),.\]])/gim;
592452
592487
  }
592453
592488
  });
@@ -615360,6 +615395,23 @@ import { existsSync as existsSync109, readFileSync as readFileSync87, readdirSyn
615360
615395
  import { join as join122, basename as basename24 } from "node:path";
615361
615396
  import { execSync as execSync54 } from "node:child_process";
615362
615397
  import { homedir as homedir42 } from "node:os";
615398
+ function projectContextUrlSpanAt(text, index) {
615399
+ PROJECT_CONTEXT_URL_RE.lastIndex = 0;
615400
+ for (const match of text.matchAll(PROJECT_CONTEXT_URL_RE)) {
615401
+ const start2 = match.index ?? 0;
615402
+ const end = start2 + match[0].length;
615403
+ if (start2 < index && index < end) return { start: start2, end };
615404
+ }
615405
+ return null;
615406
+ }
615407
+ function truncateProjectContextText(text, maxChars, suffix = "...") {
615408
+ if (text.length <= maxChars) return text;
615409
+ if (maxChars <= suffix.length) return text.slice(0, maxChars);
615410
+ let cut = maxChars - suffix.length;
615411
+ const span = projectContextUrlSpanAt(text, cut);
615412
+ if (span) cut = span.start;
615413
+ return `${text.slice(0, Math.max(0, cut)).trimEnd()}${suffix}`;
615414
+ }
615363
615415
  function getModelTier(modelName) {
615364
615416
  const m2 = modelName.toLowerCase();
615365
615417
  const sizeMatch = m2.match(/\b(\d+)b\b/);
@@ -615478,7 +615530,7 @@ function loadMemoryContext(repoRoot) {
615478
615530
  if (sorted.length === 0) continue;
615479
615531
  lines.push(`[${bucketKey}]`);
615480
615532
  for (const e2 of sorted) {
615481
- lines.push(` ${e2.key}: ${e2.value.slice(0, 200)}`);
615533
+ lines.push(` ${e2.key}: ${truncateProjectContextText(e2.value, 200, "")}`);
615482
615534
  }
615483
615535
  }
615484
615536
  return lines.join("\n");
@@ -615491,10 +615543,10 @@ function loadSessionHistory2(repoRoot) {
615491
615543
  const status = s2.completed ? "completed" : "incomplete";
615492
615544
  const date = s2.startedAt.split("T")[0];
615493
615545
  const cleanTask = cleanForStorage(s2.task) || s2.task;
615494
- lines.push(`- [${date}] ${cleanTask.slice(0, 80)} (${status}, ${s2.turns ?? 0} turns)`);
615546
+ lines.push(`- [${date}] ${truncateProjectContextText(cleanTask, 80, "")} (${status}, ${s2.turns ?? 0} turns)`);
615495
615547
  if (s2.summary) {
615496
615548
  const cleanSummary = cleanForStorage(s2.summary) || s2.summary;
615497
- lines.push(` Summary: ${cleanSummary.slice(0, 120)}`);
615549
+ lines.push(` Summary: ${truncateProjectContextText(cleanSummary, 120, "")}`);
615498
615550
  }
615499
615551
  }
615500
615552
  const sessionCtx = loadSessionContext(repoRoot);
@@ -615506,8 +615558,8 @@ function loadSessionHistory2(repoRoot) {
615506
615558
  const user = cleanForStorage(entry.task) || entry.task;
615507
615559
  const assistant = cleanForStorage(entry.assistantResponse || entry.summary) || entry.assistantResponse || entry.summary;
615508
615560
  if (!assistant) continue;
615509
- lines.push(`- User: ${user.slice(0, 120)}`);
615510
- lines.push(` Assistant: ${assistant.slice(0, 160)}`);
615561
+ lines.push(`- User: ${truncateProjectContextText(user, 120, "")}`);
615562
+ lines.push(` Assistant: ${truncateProjectContextText(assistant, 160, "")}`);
615511
615563
  }
615512
615564
  }
615513
615565
  return lines.length > 1 ? lines.join("\n") : "";
@@ -615631,7 +615683,7 @@ function loadCustomToolsContext(repoRoot) {
615631
615683
  const tested = tool.qualityGate?.lastTest?.testedAt?.split("T")[0] ?? "passed";
615632
615684
  const schema = tool.qualityGate?.lastTest?.schemaValidation?.status;
615633
615685
  const bits = [
615634
- `- ${tool.name} v${tool.version ?? 1}: ${String(tool.description ?? "").slice(0, 140)}`,
615686
+ `- ${tool.name} v${tool.version ?? 1}: ${truncateProjectContextText(String(tool.description ?? ""), 140, "")}`,
615635
615687
  `docs=${tool.docsPath ?? "missing"}`,
615636
615688
  existsSync109(indexPath) ? `index=${indexPath}` : "",
615637
615689
  `test=${tested}${schema ? `, schema=${schema}` : ""}`,
@@ -615715,7 +615767,7 @@ ${ctx3.gitInfo}`);
615715
615767
  } else if (modelTier === "medium" && ctx3.projectMap.length > 2e3) {
615716
615768
  sections.push(`## Project Map (truncated)
615717
615769
 
615718
- ${ctx3.projectMap.slice(0, 2e3)}
615770
+ ${truncateProjectContextText(ctx3.projectMap, 2e3, "")}
615719
615771
  ...(use find_files/list_directory for full listing)`);
615720
615772
  } else {
615721
615773
  sections.push(`## Project Map
@@ -615772,12 +615824,14 @@ These patterns have been repeated 3+ times. Consider using create_tool to automa
615772
615824
  }
615773
615825
  return sections.join("\n\n");
615774
615826
  }
615827
+ var PROJECT_CONTEXT_URL_RE;
615775
615828
  var init_project_context = __esm({
615776
615829
  "packages/cli/src/tui/project-context.ts"() {
615777
615830
  "use strict";
615778
615831
  init_dist8();
615779
615832
  init_omnius_directory();
615780
615833
  init_dist5();
615834
+ PROJECT_CONTEXT_URL_RE = /\bhttps?:\/\/[^\s<>"'()[\]{}]+/gi;
615781
615835
  }
615782
615836
  });
615783
615837
 
@@ -627420,7 +627474,7 @@ function parseTelegramReflectionFollowupDecision(text) {
627420
627474
  }
627421
627475
  }
627422
627476
  function convertMarkdownToTelegramHTML(md) {
627423
- let html = md;
627477
+ let html = normalizeTelegramOutboundLinks(md);
627424
627478
  html = html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
627425
627479
  html = html.replace(
627426
627480
  /```[\w]*\n([\s\S]*?)```/g,
@@ -627440,6 +627494,31 @@ function convertMarkdownToTelegramHTML(md) {
627440
627494
  function escapeTelegramHTML(text) {
627441
627495
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
627442
627496
  }
627497
+ function normalizeTelegramOutboundLinks(text) {
627498
+ if (!text) return text;
627499
+ return text.replace(
627500
+ TELEGRAM_SPACED_URL_RE,
627501
+ (match) => match.replace(/^(https?:\/\/)\s*/i, "$1").replace(/\s*\.\s*/g, ".").replace(/\s*:\s*(\d+)/g, ":$1")
627502
+ );
627503
+ }
627504
+ function telegramUrlSpanAt(text, index) {
627505
+ TELEGRAM_HTTP_URL_RE.lastIndex = 0;
627506
+ for (const match of text.matchAll(TELEGRAM_HTTP_URL_RE)) {
627507
+ const start2 = match.index ?? 0;
627508
+ const end = start2 + match[0].length;
627509
+ if (start2 < index && index < end) return { start: start2, end };
627510
+ }
627511
+ return null;
627512
+ }
627513
+ function truncateTelegramUrlSafe(text, maxLength, suffix = "...") {
627514
+ const normalized = normalizeTelegramOutboundLinks(text);
627515
+ if (normalized.length <= maxLength) return normalized;
627516
+ if (maxLength <= suffix.length) return normalized.slice(0, maxLength);
627517
+ let cut = maxLength - suffix.length;
627518
+ const span = telegramUrlSpanAt(normalized, cut);
627519
+ if (span) cut = span.start;
627520
+ return `${normalized.slice(0, Math.max(0, cut)).trimEnd()}${suffix}`;
627521
+ }
627443
627522
  function splitTelegramMessageText(text, maxLength = 3900) {
627444
627523
  const trimmed = text.trim();
627445
627524
  if (!trimmed) return [];
@@ -627545,7 +627624,7 @@ function stripTelegramStuckSelfTalk(text) {
627545
627624
  return kept.join("\n\n");
627546
627625
  }
627547
627626
  function cleanTelegramVisibleReply(text, options2 = {}) {
627548
- const clean5 = stripTelegramHiddenThinking(text).trim();
627627
+ const clean5 = normalizeTelegramOutboundLinks(stripTelegramHiddenThinking(text)).trim();
627549
627628
  if (!clean5) return "";
627550
627629
  if (options2.suppressPotentialNoReplyPrefix && isTelegramPotentialNoReplyPrefix(clean5)) return "";
627551
627630
  if (isTelegramInternalStatusText(clean5)) return "";
@@ -627586,16 +627665,14 @@ function dedupeTelegramVisibleReply(text) {
627586
627665
  return out.join(" ").trim();
627587
627666
  }
627588
627667
  function truncateTelegramContext(text, maxLength) {
627589
- const trimmed = text.trim();
627668
+ const trimmed = normalizeTelegramOutboundLinks(text).trim();
627590
627669
  if (trimmed.length <= maxLength) return trimmed;
627591
- return `${trimmed.slice(0, Math.max(0, maxLength - 80)).trimEnd()}
627592
-
627593
- [Telegram context truncated; use tools for full detail.]`;
627670
+ return truncateTelegramUrlSafe(trimmed, maxLength, "\n\n[Telegram context truncated; use tools for full detail.]");
627594
627671
  }
627595
627672
  function truncateTelegramContextLine(text, maxLength = TELEGRAM_CONTEXT_LINE_LIMIT) {
627596
- const compact3 = stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
627673
+ const compact3 = normalizeTelegramOutboundLinks(stripTelegramHiddenThinking(text)).replace(/\s+/g, " ").trim();
627597
627674
  if (compact3.length <= maxLength) return compact3;
627598
- return `${compact3.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
627675
+ return truncateTelegramUrlSafe(compact3, maxLength);
627599
627676
  }
627600
627677
  function telegramRegexEscape(text) {
627601
627678
  return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -628622,7 +628699,7 @@ function renderTelegramSubAgentError(username, error) {
628622
628699
  process.stdout.write(` ${c3.dim("│")} ${c3.magenta("✘")} @${username}: ${c3.dim(preview)}
628623
628700
  `);
628624
628701
  }
628625
- var TELEGRAM_TOOL_ACTION_GROUPS, TELEGRAM_TOOL_ACTION_GROUP, TELEGRAM_TOOL_MUTATING_GROUPS, DEFAULT_TELEGRAM_TOOL_GROUP_POLICY, TELEGRAM_TOOL_BUTTON_LABELS, TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, TELEGRAM_PUBLIC_VISION_STACK_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT, TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT, TELEGRAM_INTERACTION_DECISION_MINIMAL_SCHEMA, TELEGRAM_INTERACTION_DECISION_REPAIR_SCHEMA, TELEGRAM_CHAT_REPLY_RESPONSE_FORMAT, TELEGRAM_STUCK_SELF_TALK_PREFIXES, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_ASSOCIATIVE_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_USER_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_ACTION_LIMIT, TELEGRAM_ASSOCIATIVE_RELATION_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_MEMORY_GENERIC_QUERY_TOKENS, TELEGRAM_SUB_AGENT_BOUNDED_OPTIONS, TELEGRAM_SUB_AGENT_DEFAULT_LIMIT, TELEGRAM_SUB_AGENT_MAX_LIMIT, TELEGRAM_SUB_AGENT_BURST_CONTEXT_LIMIT, TELEGRAM_PUBLIC_HELP_COMMANDS2, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_PUBLIC_BOT_COMMAND_NAMES, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TELEGRAM_ALLOWED_UPDATES, TELEGRAM_PUBLIC_TOOL_QUOTAS, TelegramBridge;
628702
+ var TELEGRAM_TOOL_ACTION_GROUPS, TELEGRAM_TOOL_ACTION_GROUP, TELEGRAM_TOOL_MUTATING_GROUPS, DEFAULT_TELEGRAM_TOOL_GROUP_POLICY, TELEGRAM_TOOL_BUTTON_LABELS, TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, TELEGRAM_PUBLIC_VISION_STACK_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT, TELEGRAM_LINK_INTEGRITY_CONTRACT, TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT, TELEGRAM_INTERACTION_DECISION_MINIMAL_SCHEMA, TELEGRAM_INTERACTION_DECISION_REPAIR_SCHEMA, TELEGRAM_CHAT_REPLY_RESPONSE_FORMAT, TELEGRAM_SPACED_URL_RE, TELEGRAM_HTTP_URL_RE, TELEGRAM_STUCK_SELF_TALK_PREFIXES, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_ASSOCIATIVE_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_USER_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_ACTION_LIMIT, TELEGRAM_ASSOCIATIVE_RELATION_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_MEMORY_GENERIC_QUERY_TOKENS, TELEGRAM_SUB_AGENT_BOUNDED_OPTIONS, TELEGRAM_SUB_AGENT_DEFAULT_LIMIT, TELEGRAM_SUB_AGENT_MAX_LIMIT, TELEGRAM_SUB_AGENT_BURST_CONTEXT_LIMIT, TELEGRAM_PUBLIC_HELP_COMMANDS2, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_PUBLIC_BOT_COMMAND_NAMES, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TELEGRAM_ALLOWED_UPDATES, TELEGRAM_PUBLIC_TOOL_QUOTAS, TelegramBridge;
628626
628703
  var init_telegram_bridge = __esm({
628627
628704
  "packages/cli/src/tui/telegram-bridge.ts"() {
628628
628705
  "use strict";
@@ -628890,6 +628967,13 @@ External acquisition contract:
628890
628967
  - Treat repeated invalid downloads (saved HTML/JSON/login pages instead of the expected file type) as the same blocker; do not retry past a small bounded number of attempts.
628891
628968
  - The browser tool is for interactive web work; it does not save arbitrary rendered files to disk. For file acquisition, use the download/file tool and verify content-type + size before reporting success.
628892
628969
  - Report the exact blocker concisely and offer lawful alternatives (library hold, official store, summary/discussion if the user supplies an authorized copy).
628970
+ `.trim();
628971
+ TELEGRAM_LINK_INTEGRITY_CONTRACT = `
628972
+ Telegram link integrity contract:
628973
+ - When sending public http(s) URLs, copy the URL exactly from source/tool output.
628974
+ - Never defang, space out, redact, or rewrite dots, slashes, host labels, or TLDs in normal public URLs.
628975
+ - Prefer Markdown links when helpful, but keep the href URL contiguous and parseable.
628976
+ - If you are uncertain a URL is real, say so or omit it instead of reconstructing a broken URL.
628893
628977
  `.trim();
628894
628978
  TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT = {
628895
628979
  type: "json_object"
@@ -628914,6 +628998,8 @@ External acquisition contract:
628914
628998
  }
628915
628999
  }
628916
629000
  };
629001
+ TELEGRAM_SPACED_URL_RE = /\bhttps?:\/\/\s*[A-Za-z0-9-]+(?:\s*\.\s*[A-Za-z0-9-]+)+(?:\s*:\s*\d+)?(?:[/?#][^\s<>"'()[\]{}]*)?/gi;
629002
+ TELEGRAM_HTTP_URL_RE = /\bhttps?:\/\/[^\s<>"'()[\]{}]+/gi;
628917
629003
  TELEGRAM_STUCK_SELF_TALK_PREFIXES = [
628918
629004
  /^i'?ve been stuck for\b/i,
628919
629005
  /^i am (still |currently )?stuck\b/i,
@@ -630197,9 +630283,8 @@ ${message2}`)
630197
630283
  return reply;
630198
630284
  }
630199
630285
  quoteTelegramContextBlock(text, maxLength = 1800) {
630200
- const clean5 = stripTelegramHiddenThinking(text).trim();
630201
- const clipped = clean5.length > maxLength ? `${clean5.slice(0, Math.max(0, maxLength - 60)).trimEnd()}
630202
- [reply context truncated]` : clean5;
630286
+ const clean5 = normalizeTelegramOutboundLinks(stripTelegramHiddenThinking(text)).trim();
630287
+ const clipped = clean5.length > maxLength ? truncateTelegramUrlSafe(clean5, maxLength, "\n[reply context truncated]") : clean5;
630203
630288
  return clipped.split(/\r?\n/).map((line) => `> ${line}`).join("\n");
630204
630289
  }
630205
630290
  buildTelegramCurrentReplyContext(sessionKey, msg) {
@@ -631587,7 +631672,7 @@ ${mediaContext}` : ""
631587
631672
  recordTelegramUserMessage(msg, mode, textOverride) {
631588
631673
  const sessionKey = this.sessionKeyForMessage(msg);
631589
631674
  const mediaSummary = summarizeTelegramMessageAttachments(msg);
631590
- const text = (textOverride ?? msg.text ?? "").trim() || mediaSummary || "[non-text Telegram message]";
631675
+ const text = normalizeTelegramOutboundLinks((textOverride ?? msg.text ?? "").trim()) || mediaSummary || "[non-text Telegram message]";
631591
631676
  this.ensureTelegramConversationLoaded(sessionKey);
631592
631677
  const history = this.chatHistory.get(sessionKey) ?? [];
631593
631678
  const existing = Number.isFinite(msg.messageId) ? history.find(
@@ -631676,7 +631761,7 @@ ${mediaContext}` : ""
631676
631761
  this.saveTelegramConversationState(sessionKey);
631677
631762
  }
631678
631763
  recordTelegramAssistantMessage(msg, text, mode, options2 = {}) {
631679
- const clean5 = stripTelegramHiddenThinking(text).trim();
631764
+ const clean5 = normalizeTelegramOutboundLinks(stripTelegramHiddenThinking(text)).trim();
631680
631765
  if (!clean5) return;
631681
631766
  const sessionKey = this.sessionKeyForMessage(msg);
631682
631767
  const entry = {
@@ -634269,7 +634354,8 @@ Todo/session id: ${sessionId}
634269
634354
  Profile: ${profile}
634270
634355
  Tool context: ${toolContext}
634271
634356
  ${chatLabel}`,
634272
- TELEGRAM_ACTION_RESPONSE_CONTRACT
634357
+ TELEGRAM_ACTION_RESPONSE_CONTRACT,
634358
+ TELEGRAM_LINK_INTEGRITY_CONTRACT
634273
634359
  ];
634274
634360
  sections.push(conversationStream);
634275
634361
  const sendTargetContext = this.buildTelegramSendTargetContext(msg, isAdminDM);
@@ -634638,10 +634724,11 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
634638
634724
  * streamed content. Returns the message_id for subsequent edits.
634639
634725
  */
634640
634726
  async sendLiveMessage(chatId, initialText, replyToMessageId) {
634727
+ const normalizedInitialText = normalizeTelegramOutboundLinks(initialText);
634641
634728
  try {
634642
634729
  const body = {
634643
634730
  chat_id: chatId,
634644
- text: initialText,
634731
+ text: normalizedInitialText,
634645
634732
  parse_mode: "HTML"
634646
634733
  };
634647
634734
  const replyParameters = telegramReplyParameters(replyToMessageId);
@@ -634658,7 +634745,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
634658
634745
  try {
634659
634746
  const body = {
634660
634747
  chat_id: chatId,
634661
- text: initialText
634748
+ text: normalizedInitialText
634662
634749
  };
634663
634750
  const replyParameters = telegramReplyParameters(replyToMessageId);
634664
634751
  if (replyParameters) body["reply_parameters"] = replyParameters;
@@ -634693,7 +634780,8 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
634693
634780
  * Handles rate limits and Telegram's "message is not modified" error silently.
634694
634781
  */
634695
634782
  async editLiveMessage(chatId, messageId, html) {
634696
- const truncated = html.length > 4e3 ? html.slice(0, 3950) + "\n\n<i>... (streaming)</i>" : html;
634783
+ const normalizedHtml = normalizeTelegramOutboundLinks(html);
634784
+ const truncated = normalizedHtml.length > 4e3 ? normalizedHtml.slice(0, 3950) + "\n\n<i>... (streaming)</i>" : normalizedHtml;
634697
634785
  try {
634698
634786
  const result = await this.apiCall("editMessageText", {
634699
634787
  chat_id: chatId,
@@ -634706,7 +634794,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
634706
634794
  return true;
634707
634795
  } catch {
634708
634796
  try {
634709
- const plain = html.replace(/<[^>]+>/g, "");
634797
+ const plain = normalizedHtml.replace(/<[^>]+>/g, "");
634710
634798
  const truncPlain = plain.length > 4e3 ? plain.slice(0, 3950) + "\n\n... (streaming)" : plain;
634711
634799
  const result = await this.apiCall("editMessageText", {
634712
634800
  chat_id: chatId,
@@ -635405,6 +635493,8 @@ ${TELEGRAM_PUBLIC_VISION_STACK_CONTRACT}`;
635405
635493
  role: "system",
635406
635494
  content: `${TELEGRAM_CHAT_MODE_PROMPT}
635407
635495
 
635496
+ ${TELEGRAM_LINK_INTEGRITY_CONTRACT}
635497
+
635408
635498
  ## Runtime Context
635409
635499
 
635410
635500
  ${runtime}
@@ -635730,6 +635820,8 @@ ${GROUP_REPLY_DISCRETION_PROMPT}` : "";
635730
635820
 
635731
635821
  ${TELEGRAM_ACTION_RESPONSE_CONTRACT}
635732
635822
 
635823
+ ${TELEGRAM_LINK_INTEGRITY_CONTRACT}
635824
+
635733
635825
  ${TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT}
635734
635826
 
635735
635827
  ${reminderToolContract}
@@ -635742,6 +635834,7 @@ ${currentTelegramPrompt}`;
635742
635834
  "You have access to isolated per-chat memory (memory_write, memory_read, memory_search) scoped to this conversation.",
635743
635835
  "memory_search may use scope=group/current_chat for this group or scope=user with user_id/username for a participant in this same group. Other groups, admin chats, and private DMs are not accessible here.",
635744
635836
  "You can remember facts about users and retrieve them later. Durable associative memory in the prompt includes participant profiles, relationships, scoped facts, and prior actions retained across days, sessions, and Omnius updates. You also have web_search and web_fetch to look up information.",
635837
+ TELEGRAM_LINK_INTEGRITY_CONTRACT,
635745
635838
  "If a user explicitly states a durable preference for reply cadence/order, call telegram_preference_set. Do not infer or classify reply-mode preferences from keywords, style, tone, or task type.",
635746
635839
  "You have the full scoped Telegram media-analysis stack by default: telegram_media_recent, image_read, ocr, ocr_image_advanced, vision, pdf_to_text, ocr_pdf, transcribe_file, video_understand, audio_analyze, and identity_memory. For complex textual imagery, screenshots, forms, scans, or dense labels, prefer ocr_image_advanced after resolving media with path='reply' or path='latest'.",
635747
635840
  formatIdentityMemoryContext(chatLabel || "Telegram private chat"),
@@ -638322,9 +638415,10 @@ ${text}`.trim());
638322
638415
  return result.messageId ?? null;
638323
638416
  }
638324
638417
  async sendMessageHTMLDetailed(chatId, html, replyToMessageId, options2 = {}) {
638325
- const extracted = extractMediaReferences(html);
638418
+ const normalizedHtml = normalizeTelegramOutboundLinks(html);
638419
+ const extracted = extractMediaReferences(normalizedHtml);
638326
638420
  const mediaRefs = this.filterTelegramMediaReferences(extracted.media, options2);
638327
- const sendHtml = extracted.text || (extracted.media.length > 0 ? "" : html);
638421
+ const sendHtml = extracted.text || (extracted.media.length > 0 ? "" : normalizedHtml);
638328
638422
  let sentId = null;
638329
638423
  if (!sendHtml.trim()) {
638330
638424
  for (let idx = 0; idx < mediaRefs.length; idx++) {
@@ -638791,7 +638885,8 @@ Content-Type: ${mimeForPath(pathOrFileId, field === "photo" ? "image" : "video")
638791
638885
  * article carrying the message text Telegram should send to the guest chat.
638792
638886
  */
638793
638887
  async answerGuestQuery(guestQueryId, text, options2 = {}) {
638794
- const truncated = text.length > 4e3 ? text.slice(0, 3950) + "\n\n... (truncated)" : text;
638888
+ const normalizedText = normalizeTelegramOutboundLinks(text);
638889
+ const truncated = normalizedText.length > 4e3 ? normalizedText.slice(0, 3950) + "\n\n... (truncated)" : normalizedText;
638795
638890
  const inputMessageContent = {
638796
638891
  message_text: truncated
638797
638892
  };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.170",
3
+ "version": "1.0.172",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.170",
9
+ "version": "1.0.172",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.170",
3
+ "version": "1.0.172",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",