omnius 1.0.229 → 1.0.230

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
@@ -642889,6 +642889,31 @@ function extractFinalTelegramReplyJson(buffer2) {
642889
642889
  const partial = extractPartialTelegramReplyJson(stripped);
642890
642890
  return partial && partial.trim().length > 0 ? partial.trim() : null;
642891
642891
  }
642892
+ function normalizeTelegramEchoComparableText(text) {
642893
+ return stripTelegramHiddenThinking(text).toLowerCase().replace(/https?:\/\/\S+/g, " ").replace(/@[a-z0-9_]{3,32}/gi, " @user ").replace(/[^\p{L}\p{N}@]+/gu, " ").replace(/\s+/g, " ").trim();
642894
+ }
642895
+ function telegramVisibleReplyNearEcho(incoming, outgoing) {
642896
+ const source = normalizeTelegramEchoComparableText(incoming);
642897
+ const reply = normalizeTelegramEchoComparableText(outgoing);
642898
+ if (source.length < 20 || reply.length < 20) return false;
642899
+ if (source === reply) return true;
642900
+ const sourceTokens = source.split(" ").filter(Boolean);
642901
+ const replyTokens = reply.split(" ").filter(Boolean);
642902
+ if (sourceTokens.length < 4 || replyTokens.length < 4) return false;
642903
+ const lengthRatio = Math.min(source.length, reply.length) / Math.max(source.length, reply.length);
642904
+ if (lengthRatio < 0.72) return false;
642905
+ const sourceSet = new Set(sourceTokens);
642906
+ const replySet = new Set(replyTokens);
642907
+ let overlap = 0;
642908
+ for (const token of replySet) {
642909
+ if (sourceSet.has(token)) overlap += 1;
642910
+ }
642911
+ const dice = 2 * overlap / (sourceSet.size + replySet.size);
642912
+ return dice >= 0.9;
642913
+ }
642914
+ function telegramMentionMatchesUsername(mention, usernameLower) {
642915
+ return mention.trim().replace(/^@/, "").toLowerCase() === usernameLower;
642916
+ }
642892
642917
  function estimatePromptTokensFromRequest(request) {
642893
642918
  let chars = 0;
642894
642919
  for (const m2 of request.messages ?? []) {
@@ -644871,6 +644896,8 @@ Rules:
644871
644896
  7. Do not claim older chat is unavailable when the context stream contains it. If asked what you see, summarize the supplied transcript, speakers, and relationship/tone signals.
644872
644897
  8. Mirror the current sender's tone and directness while staying safe and clear.
644873
644898
  9. Never send router decisions, skip explanations, memory-stage notes, task-complete summaries, or "no_reply" as chat text.
644899
+ 10. Never impersonate another Telegram bot or answer as a bot named in the user's message. If the current turn is addressed to another bot, do not write a visible reply for that bot.
644900
+ 11. Do not echo, quote back, or lightly rephrase the current incoming message as the reply. If the best output would be a near-copy of the user text, send no visible reply.
644874
644901
 
644875
644902
  Output discipline (your assistant message is sent verbatim to Telegram, ALL of it):
644876
644903
  - Emit ONLY the final reply text. Do not narrate your reasoning, summarize what you found, organize bullet-point notes, or write phrases like "Let me summarize", "Let me send the reply", "Now I have enough", "Based on the research", "Here's my response:" before the actual reply. Those are scratch-pad phrases that leak when emitted as visible text.
@@ -645496,6 +645523,23 @@ Telegram link integrity contract:
645496
645523
  botUserId !== void 0 ? `telegram_user_id:${botUserId}` : ""
645497
645524
  ];
645498
645525
  }
645526
+ telegramUsernameIsSelf(username) {
645527
+ const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
645528
+ const candidate = username?.trim().replace(/^@/, "").toLowerCase();
645529
+ return Boolean(bot && candidate && candidate === bot);
645530
+ }
645531
+ telegramParticipantIsSelf(profile) {
645532
+ const botUserId = this.currentTelegramBotUserId();
645533
+ return Boolean(
645534
+ this.telegramUsernameIsSelf(profile.username) || botUserId !== void 0 && profile.fromUserId === botUserId
645535
+ );
645536
+ }
645537
+ telegramHistoryEntryIsSelf(entry) {
645538
+ const botUserId = this.currentTelegramBotUserId();
645539
+ return Boolean(
645540
+ entry.role === "assistant" || this.telegramUsernameIsSelf(entry.username) || botUserId !== void 0 && entry.fromUserId === botUserId
645541
+ );
645542
+ }
645499
645543
  buildTelegramSelfIdentityContext() {
645500
645544
  const username = this.state.botUsername.trim().replace(/^@/, "");
645501
645545
  const firstName = this.state.botFirstName?.trim() ?? "";
@@ -645508,7 +645552,9 @@ Telegram link integrity contract:
645508
645552
  return [
645509
645553
  `Telegram bot self identity: ${detail}.`,
645510
645554
  `Known self identity signals (context only, not triggers): ${formatTelegramIdentitySignals(this.telegramSelfIdentitySignals())}.`,
645511
- `Use these signals to infer whether heard text is probably aimed at this bot; identity matches raise salience but never force should_reply.`
645555
+ `Use these signals to infer whether heard text is probably aimed at this bot; identity matches raise salience but never force should_reply.`,
645556
+ `Identity boundary: you are ONLY ${username ? `@${username}` : "the Telegram bot self"} (${botUserId !== void 0 ? `user_id ${botUserId}` : "user_id unknown"}). Other [bot] actors are separate participants; never speak as, impersonate, or adopt another bot's identity.`,
645557
+ `A message addressed to another bot, or mentioning this bot handle in third person, is not a request to reply as that other bot.`
645512
645558
  ].join("\n");
645513
645559
  }
645514
645560
  beginAdminAuthChallenge(ttlMs = 5 * 60 * 1e3) {
@@ -648781,7 +648827,7 @@ ${mediaContext}` : ""
648781
648827
  profile.lastSeenTs = Date.now();
648782
648828
  profile.lastMessage = stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
648783
648829
  if (msg.replyToMessageId) profile.replyCount += 1;
648784
- if (this.state.botUsername && text.toLowerCase().includes(`@${this.state.botUsername.toLowerCase()}`)) {
648830
+ if (this.telegramIdentitySalienceAddressesBot(this.telegramMessageIdentitySalienceSignals(msg))) {
648785
648831
  profile.directAddressCount += 1;
648786
648832
  }
648787
648833
  for (const tag of inferTelegramToneTags(text)) profile.toneTags.add(tag);
@@ -649630,6 +649676,7 @@ ${lines.join("\n")}`;
649630
649676
  });
649631
649677
  const selected = sortedByBenefit.slice(0, tier1Count);
649632
649678
  const participantLines = selected.map((profile) => {
649679
+ const selfMark = this.telegramParticipantIsSelf(profile) ? " (self)" : "";
649633
649680
  const label = profile.username && profile.username !== "unknown" ? `@${profile.username}` : profile.firstName || `user:${profile.fromUserId}`;
649634
649681
  const tones = [...profile.toneTags].slice(0, 5).join(", ") || "neutral";
649635
649682
  const direct = profile.directAddressCount ? `, direct-addresses:${profile.directAddressCount}` : "";
@@ -649638,7 +649685,7 @@ ${lines.join("\n")}`;
649638
649685
  key: `tier1.participant.${profile.username ?? profile.fromUserId}`,
649639
649686
  needle: profile.username ?? String(profile.fromUserId)
649640
649687
  });
649641
- return `- ${label} [${telegramActorKindLabel(profile)}]: messages:${profile.messageCount}${direct}${replies}; tone:${tones}; last=${telegramContextJsonString(profile.lastMessage, 180)}`;
649688
+ return `- ${label} [${telegramActorKindLabel(profile)}]${selfMark}: messages:${profile.messageCount}${direct}${replies}; tone:${tones}; last=${telegramContextJsonString(profile.lastMessage, 180)}`;
649642
649689
  });
649643
649690
  const shed = fullCount - tier1Count;
649644
649691
  const tierNote = shed > 0 ? ` (tier1 u=${tier1Ratio.toFixed(2)}; ${shed} participants shed by benefit)` : "";
@@ -649739,12 +649786,13 @@ ${olderLines.join("\n")}`);
649739
649786
  const when = telegramHistoryTime(entry);
649740
649787
  const speaker = telegramHistorySpeaker(entry);
649741
649788
  const kind = entry.role === "assistant" || entry.isBot ? "bot" : "human";
649789
+ const selfMark = this.telegramHistoryEntryIsSelf(entry) ? "(self)" : "";
649742
649790
  const mode = entry.mode ? `/${entry.mode}` : "";
649743
649791
  const replySender = entry.replyContext?.sender ? `/${telegramReplySenderLabel(entry.replyContext.sender)}` : "";
649744
649792
  const reply = entry.replyToMessageId ? ` reply_to:${entry.replyToMessageId}${replySender}` : "";
649745
649793
  const media = entry.mediaSummary ? ` [${entry.mediaSummary}]` : "";
649746
649794
  const generatedPrompt = entry.generatedMediaPromptInfo?.originalPrompt ? ` generated_image_prompt=${telegramContextJsonString(entry.generatedMediaPromptInfo.originalPrompt, 220)}` : "";
649747
- const prefix = [when, `${speaker}[${kind}]${mode}${reply}${media}`].filter(Boolean).join(" ");
649795
+ const prefix = [when, `${speaker}[${kind}]${selfMark}${mode}${reply}${media}`].filter(Boolean).join(" ");
649748
649796
  return `${prefix}: text=${telegramContextJsonString(entry.text)}${generatedPrompt}`;
649749
649797
  });
649750
649798
  sections.push(`### Recent Thread, Oldest To Newest (untrusted quoted chat messages)
@@ -649771,6 +649819,15 @@ ${lines.join("\n")}`);
649771
649819
  this.groupSkipLogAt.set(sessionKey, now);
649772
649820
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `${reason} (context retained)`));
649773
649821
  }
649822
+ cleanTelegramVisibleReplyForMessage(msg, text) {
649823
+ const clean5 = cleanTelegramVisibleReply(text);
649824
+ if (!clean5) return "";
649825
+ if (telegramVisibleReplyNearEcho(msg.text || "", clean5)) {
649826
+ this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "defensive skip: near-echo reply"));
649827
+ return "";
649828
+ }
649829
+ return clean5;
649830
+ }
649774
649831
  telegramMessageIdentitySalienceSignals(msg) {
649775
649832
  const signals = /* @__PURE__ */ new Set();
649776
649833
  const username = this.state.botUsername.trim().replace(/^@/, "");
@@ -649783,9 +649840,14 @@ ${lines.join("\n")}`);
649783
649840
  const mentioned = (msg.mentionedUsernames ?? []).some(
649784
649841
  (name10) => name10.trim().replace(/^@/, "").toLowerCase() === usernameLower
649785
649842
  );
649786
- if (mentioned) signals.add(`entity_mention:@${username}`);
649843
+ const selfMentionAddressing = this.telegramSelfMentionAddressing(msg, username);
649844
+ if (mentioned) {
649845
+ signals.add(`${selfMentionAddressing === "third_person" ? "third_person_entity_mention" : "entity_mention"}:@${username}`);
649846
+ }
649787
649847
  const rawMention = new RegExp(`(^|[^A-Za-z0-9_@])@${telegramRegexEscape(username)}(?![A-Za-z0-9_])`, "i");
649788
- if (rawMention.test(text)) signals.add(`raw_text_mention:@${username}`);
649848
+ if (rawMention.test(text)) {
649849
+ signals.add(`${selfMentionAddressing === "third_person" ? "third_person_mention" : "raw_text_mention"}:@${username}`);
649850
+ }
649789
649851
  if (msg.replyToUsername && msg.replyToUsername.trim().replace(/^@/, "").toLowerCase() === usernameLower) {
649790
649852
  signals.add(`reply_to_username:@${username}`);
649791
649853
  }
@@ -649803,6 +649865,71 @@ ${lines.join("\n")}`);
649803
649865
  if (resolvedReply?.sender?.isSelf) signals.add("reply_to_self_history");
649804
649866
  return [...signals];
649805
649867
  }
649868
+ telegramIdentitySalienceAddressesBot(signals) {
649869
+ return signals.some(
649870
+ (signal) => !signal.startsWith("third_person_mention:") && !signal.startsWith("third_person_entity_mention:")
649871
+ );
649872
+ }
649873
+ telegramCurrentMessageAddressedToOtherBot(msg) {
649874
+ const username = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
649875
+ const replyUsername = msg.replyToUsername?.trim().replace(/^@/, "").toLowerCase();
649876
+ if (replyUsername && replyUsername !== username && msg.replyToBot) {
649877
+ return `@${msg.replyToUsername.trim().replace(/^@/, "")}`;
649878
+ }
649879
+ const replySender = msg.replyContext?.sender;
649880
+ const replyContextUsername = replySender?.username?.trim().replace(/^@/, "").toLowerCase();
649881
+ if (replyContextUsername && replyContextUsername !== username && replySender?.isBot) {
649882
+ return `@${replySender.username.trim().replace(/^@/, "")}`;
649883
+ }
649884
+ const text = msg.text || "";
649885
+ const firstMention = text.match(/(^|[^A-Za-z0-9_@])@([A-Za-z0-9_]{3,32})(?![A-Za-z0-9_])/);
649886
+ if (firstMention?.[2] && firstMention[2].toLowerCase() !== username) {
649887
+ const mentioned = (msg.mentionedUsernames ?? []).find(
649888
+ (name10) => telegramMentionMatchesUsername(name10, firstMention[2].toLowerCase())
649889
+ );
649890
+ if (mentioned) return `@${firstMention[2]}`;
649891
+ }
649892
+ return null;
649893
+ }
649894
+ telegramSelfMentionAddressing(msg, username) {
649895
+ if (msg.chatType === "private") return "direct";
649896
+ if (this.telegramMessageRepliesToBot(msg)) return "direct";
649897
+ const usernameLower = username.toLowerCase();
649898
+ const text = msg.text || "";
649899
+ const mentionRegex = new RegExp(`(^|[^A-Za-z0-9_@])@${telegramRegexEscape(username)}(?![A-Za-z0-9_])`, "ig");
649900
+ const mentions = [];
649901
+ let match;
649902
+ while ((match = mentionRegex.exec(text)) !== null) {
649903
+ const delimiterLength = match[1]?.length ?? 0;
649904
+ const start2 = match.index + delimiterLength;
649905
+ mentions.push({
649906
+ start: start2,
649907
+ before: text.slice(0, start2),
649908
+ after: text.slice(start2 + username.length + 1)
649909
+ });
649910
+ }
649911
+ const hasSelfMention = mentions.length > 0 || (msg.mentionedUsernames ?? []).some(
649912
+ (name10) => telegramMentionMatchesUsername(name10, usernameLower)
649913
+ );
649914
+ if (!hasSelfMention) return "direct";
649915
+ const addressedOther = this.telegramCurrentMessageAddressedToOtherBot(msg);
649916
+ const anyDirect = mentions.some(({ before, after }) => {
649917
+ const prefix = before.trim().toLowerCase();
649918
+ const suffix = after.trimStart();
649919
+ const prefixIsVocative = /^(hey|hi|hello|yo|ok|okay|please|pls|sir|omg|btw)[\s,:-]*$/i.test(prefix);
649920
+ const prefixIsEmpty = prefix.length === 0;
649921
+ const suffixLooksAddressed = suffix.length === 0 || /^[,;:!?-]/.test(suffix) || /^(can|could|would|will|are|do|does|did|please|pls|help|tell|show|explain|check|look|stop|start|reply|respond)\b/i.test(suffix);
649922
+ return (prefixIsEmpty || prefixIsVocative) && suffixLooksAddressed;
649923
+ });
649924
+ if (anyDirect && !addressedOther) return "direct";
649925
+ const thirdPersonPattern = new RegExp(
649926
+ `\\b(to|about|for|from|with|against|via|using|mentioning|mentions|mentioned|tagging|tagged|responding\\s+to|replying\\s+to|talking\\s+to|talking\\s+about|stop\\s+responding\\s+to)\\s+@${telegramRegexEscape(username)}\\b`,
649927
+ "i"
649928
+ );
649929
+ if (thirdPersonPattern.test(text)) return "third_person";
649930
+ if (addressedOther) return "third_person";
649931
+ return anyDirect ? "direct" : "third_person";
649932
+ }
649806
649933
  telegramMessageRepliesToBot(msg) {
649807
649934
  const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
649808
649935
  const botUserId = this.currentTelegramBotUserId();
@@ -650928,8 +651055,12 @@ ${candidateFilter.join(",")}`;
650928
651055
  const forcedRoute = this.interactionMode === "chat" || this.interactionMode === "action" ? this.interactionMode : null;
650929
651056
  const isGroup = msg.chatType !== "private";
650930
651057
  const identitySalienceSignals = this.telegramMessageIdentitySalienceSignals(msg);
650931
- const addressesBot = identitySalienceSignals.length > 0;
651058
+ const addressesBot = this.telegramIdentitySalienceAddressesBot(identitySalienceSignals);
650932
651059
  const sessionKey = this.sessionKeyForMessage(msg);
651060
+ const addressedOtherBot = this.telegramCurrentMessageAddressedToOtherBot(msg);
651061
+ const thirdPersonSelfMention = identitySalienceSignals.some(
651062
+ (signal) => signal.startsWith("third_person_mention:") || signal.startsWith("third_person_entity_mention:")
651063
+ );
650933
651064
  const daydreamForceCheck = isGroup && this.shouldForceAnalysisFromChannelDaydream(sessionKey);
650934
651065
  const stimulationProbe = this.stimulation.observe({
650935
651066
  channelId: sessionKey,
@@ -650962,6 +651093,7 @@ ${candidateFilter.join(",")}`;
650962
651093
  `Tool context: ${toolContext}`,
650963
651094
  `Platform notification/direct-address signal (salience evidence only, not a decision): ${addressesBot ? "yes" : "no"}`,
650964
651095
  `Platform salience signals (context only, not triggers): ${identitySalienceSignals.length ? identitySalienceSignals.join(", ") : "none"}`,
651096
+ addressedOtherBot && thirdPersonSelfMention ? `Identity-boundary observation: addressed to ${addressedOtherBot}; references this bot only in third person, so a visible reply from this bot is likely not expected.` : addressedOtherBot ? `Identity-boundary observation: addressed to ${addressedOtherBot}, a separate bot actor; do not answer as that bot.` : thirdPersonSelfMention ? `Identity-boundary observation: this bot is mentioned in third person; infer whether silence is more natural than replying.` : "",
650965
651097
  `Current chat type: ${msg.chatType}`,
650966
651098
  `Current sender: ${telegramSpeakerLabel(msg)} [${telegramActorKindLabel(msg)}]`,
650967
651099
  this.formatTelegramDeliveryCapabilityContext(sessionKey, msg),
@@ -651037,6 +651169,7 @@ ${stimulationProbe.context}`,
651037
651169
  `Reply discretion: make a human-like attention decision from the full social context. Observe the message, relationship stream, reply graph, conversation momentum, prior bot involvement, speaker intent, and notification-like signals, then decide whether a visible reply would be natural.`,
651038
651170
  `No hard triggers: direct address, @mentions, name/identity references, private-chat delivery, replies, active threads, and stimulation score are evidence only. They may raise or lower salience, but none guarantees should_reply=true or should_reply=false.`,
651039
651171
  `High-salience evidence: private DMs, exact @username matches, display-name self references, and replies to this bot are notification-like signals. They should usually move attention toward deeper processing and a likely response unless the surrounding context makes silence more natural.`,
651172
+ `Identity-boundary rule: third-person references to this bot, especially inside messages addressed to another bot, are context only and must not be treated as direct address.`,
651040
651173
  `No keyword routing: do not use static keyword rules. Infer whether identity references are actually aimed at this bot from syntax, tone, recent turns, and relationships.`,
651041
651174
  `Observation notes: omit note fields on the fast path. Do not expose hidden chain-of-thought or produce scratch notes in this router JSON.`,
651042
651175
  `Reply-mode preference capture: if and only if the current sender explicitly expresses a durable preference for reply cadence/order, populate reply_mode_preference as a typed update. Do not infer this from style, keywords, tone, or one-off task shape. Use null otherwise.`,
@@ -652897,7 +653030,7 @@ Join: ${newUrl}`);
652897
653030
  subAgent.typingInterval = null;
652898
653031
  }
652899
653032
  this.stopTelegramPublicProgressMessage(subAgent);
652900
- const finalText = cleanTelegramVisibleReply(result || "");
653033
+ const finalText = this.cleanTelegramVisibleReplyForMessage(msg, result || "");
652901
653034
  if (isAdminDM && !this.telegramAdminRunCompleted(subAgent)) {
652902
653035
  const incompleteText = this.telegramAdminIncompleteRunText(subAgent, finalText);
652903
653036
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, incompleteText);
@@ -653056,7 +653189,7 @@ Join: ${newUrl}`);
653056
653189
  clearInterval(subAgent.typingInterval);
653057
653190
  subAgent.typingInterval = null;
653058
653191
  }
653059
- const finalText = cleanTelegramVisibleReply(result || "");
653192
+ const finalText = this.cleanTelegramVisibleReplyForMessage(msg, result || "");
653060
653193
  if (subAgent.liveMessagePromise) {
653061
653194
  await subAgent.liveMessagePromise.catch(() => {
653062
653195
  });
@@ -653223,7 +653356,7 @@ Join: ${newUrl}`);
653223
653356
  clearInterval(typingInterval);
653224
653357
  typingInterval = null;
653225
653358
  }
653226
- const cleaned = cleanTelegramVisibleReply(finalText || accumulated);
653359
+ const cleaned = this.cleanTelegramVisibleReplyForMessage(msg, finalText || accumulated);
653227
653360
  const pendingLiveMessage = liveMessagePromise;
653228
653361
  if (pendingLiveMessage) {
653229
653362
  await pendingLiveMessage.catch(() => {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.229",
3
+ "version": "1.0.230",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.229",
9
+ "version": "1.0.230",
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.229",
3
+ "version": "1.0.230",
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",