omnius 1.0.70 → 1.0.72

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
@@ -609574,6 +609574,28 @@ import { join as join127, resolve as resolve43, basename as basename27, relative
609574
609574
  import { homedir as homedir40 } from "node:os";
609575
609575
  import { writeFile as writeFileAsync } from "node:fs/promises";
609576
609576
  import { createHash as createHash23, randomBytes as randomBytes22, randomInt } from "node:crypto";
609577
+ function cleanTelegramDecisionNote(value2, maxLength = 260) {
609578
+ if (typeof value2 !== "string") return void 0;
609579
+ const clean5 = stripTelegramHiddenThinking(value2).replace(/\s+/g, " ").trim();
609580
+ if (!clean5) return void 0;
609581
+ return clean5.length > maxLength ? `${clean5.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...` : clean5;
609582
+ }
609583
+ function telegramDecisionNote(parsed, keys, nestedKeys = ["internal_notes", "internalNotes", "notes"]) {
609584
+ for (const key of keys) {
609585
+ const direct = cleanTelegramDecisionNote(parsed[key]);
609586
+ if (direct) return direct;
609587
+ }
609588
+ for (const nestedKey of nestedKeys) {
609589
+ const nested = parsed[nestedKey];
609590
+ if (!nested || typeof nested !== "object" || Array.isArray(nested)) continue;
609591
+ const record = nested;
609592
+ for (const key of keys) {
609593
+ const value2 = cleanTelegramDecisionNote(record[key]);
609594
+ if (value2) return value2;
609595
+ }
609596
+ }
609597
+ return void 0;
609598
+ }
609577
609599
  function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
609578
609600
  const cleaned = stripTelegramHiddenThinking(text).replace(/```(?:json)?/gi, "").replace(/```/g, "").trim();
609579
609601
  const jsonText = cleaned.startsWith("{") ? cleaned : cleaned.match(/\{[\s\S]*\}/)?.[0] ?? "";
@@ -609603,7 +609625,11 @@ function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
609603
609625
  attentionDelta: Number.isFinite(attentionDeltaRaw) ? Math.max(-1, Math.min(1, attentionDeltaRaw)) : void 0,
609604
609626
  attentionScore: Number.isFinite(attentionScoreRaw) ? Math.max(0, Math.min(1, attentionScoreRaw)) : void 0,
609605
609627
  nextCheckAfterMessages: Number.isFinite(nextMessagesRaw) ? Math.max(1, Math.floor(nextMessagesRaw)) : void 0,
609606
- nextCheckAfterMs: Number.isFinite(nextMsRaw) ? Math.max(0, Math.floor(nextMsRaw)) : void 0
609628
+ nextCheckAfterMs: Number.isFinite(nextMsRaw) ? Math.max(0, Math.floor(nextMsRaw)) : void 0,
609629
+ silentDisposition: telegramDecisionNote(parsed, ["silent_disposition", "silentDisposition", "disposition"]),
609630
+ mentalNote: telegramDecisionNote(parsed, ["mental_note", "mentalNote", "observation", "insight"]),
609631
+ memoryNote: telegramDecisionNote(parsed, ["memory_note", "memoryNote", "memory"]),
609632
+ relationshipNote: telegramDecisionNote(parsed, ["relationship_note", "relationshipNote", "relationship"])
609607
609633
  };
609608
609634
  } catch {
609609
609635
  return null;
@@ -609951,6 +609977,9 @@ function truncateTelegramContextLine(text, maxLength = TELEGRAM_CONTEXT_LINE_LIM
609951
609977
  if (compact2.length <= maxLength) return compact2;
609952
609978
  return `${compact2.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
609953
609979
  }
609980
+ function telegramRegexEscape(text) {
609981
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
609982
+ }
609954
609983
  function redactTelegramLocalPaths(text) {
609955
609984
  return text.replace(/\/(?:home|root|tmp|var|etc|usr|opt|mnt|media|srv|run)\/[^\s"'`<>)]*/g, "[local-path-redacted]");
609956
609985
  }
@@ -609996,6 +610025,10 @@ function telegramHistoryTime(entry) {
609996
610025
  minute: "2-digit"
609997
610026
  });
609998
610027
  }
610028
+ function formatTelegramIdentitySignals(signals) {
610029
+ const unique = [...new Set(signals.map((signal) => signal.trim()).filter(Boolean))];
610030
+ return unique.length > 0 ? unique.join(", ") : "none";
610031
+ }
609999
610032
  function summarizeTelegramMessageAttachments(msg) {
610000
610033
  const parts = [];
610001
610034
  if (msg.media) {
@@ -611157,12 +611190,12 @@ Public Telegram runs have the full scoped media-analysis stack for media posted
611157
611190
  - These tools are current-chat scoped. Never inspect arbitrary local files, reveal local paths, or claim access to media outside this Telegram chat scope.
611158
611191
  `.trim();
611159
611192
  GROUP_REPLY_DISCRETION_PROMPT = `
611160
- REPLY DISCRETION: You are in a group chat. The live router has already filtered
611161
- most ambient chatter. Continue to be selective:
611162
- 1. Respond when someone directly addresses the bot, replies to the bot, or keeps
611163
- an active bot-involved task moving.
611164
- 2. Stay silent for conversation between other people, third-person commentary
611165
- about the bot, status chatter, or questions clearly meant for someone else.
611193
+ REPLY DISCRETION: You are in a group chat. The live router selected this turn
611194
+ using context, attention, and relationship signals. Continue that same approach:
611195
+ 1. Use the supplied conversation context to decide whether a visible reply is
611196
+ socially appropriate for this specific turn.
611197
+ 2. Treat direct address, replies, ongoing task continuity, and speaker intent as
611198
+ contextual evidence, not automatic triggers.
611166
611199
  3. Do not reply just because you know an answer or could add color.
611167
611200
  4. Peer bots are labeled as bots in context. Do not reflexively answer bot
611168
611201
  chatter; only continue bot-to-bot exchanges when the message is clearly
@@ -611375,7 +611408,9 @@ External acquisition contract:
611375
611408
  lastUpdateId = 0;
611376
611409
  state = {
611377
611410
  active: false,
611411
+ botUserId: void 0,
611378
611412
  botUsername: "",
611413
+ botFirstName: void 0,
611379
611414
  supportsGuestQueries: false,
611380
611415
  canReadAllGroupMessages: false,
611381
611416
  interactionMode: "auto",
@@ -611545,6 +611580,38 @@ External acquisition contract:
611545
611580
  get botUsername() {
611546
611581
  return this.state.botUsername;
611547
611582
  }
611583
+ currentTelegramBotUserId() {
611584
+ const stateId = this.state.botUserId;
611585
+ if (typeof stateId === "number" && Number.isFinite(stateId)) return stateId;
611586
+ if (typeof this.botUserId === "number" && Number.isFinite(this.botUserId)) return this.botUserId;
611587
+ return void 0;
611588
+ }
611589
+ telegramSelfIdentitySignals() {
611590
+ const username = this.state.botUsername.trim().replace(/^@/, "");
611591
+ const firstName = this.state.botFirstName?.trim() ?? "";
611592
+ const botUserId = this.currentTelegramBotUserId();
611593
+ return [
611594
+ username ? `@${username}` : "",
611595
+ username,
611596
+ firstName,
611597
+ botUserId !== void 0 ? `telegram_user_id:${botUserId}` : ""
611598
+ ];
611599
+ }
611600
+ buildTelegramSelfIdentityContext() {
611601
+ const username = this.state.botUsername.trim().replace(/^@/, "");
611602
+ const firstName = this.state.botFirstName?.trim() ?? "";
611603
+ const botUserId = this.currentTelegramBotUserId();
611604
+ const detail = [
611605
+ botUserId !== void 0 ? `user_id=${botUserId}` : "user_id=unknown",
611606
+ username ? `username=@${username}` : "username=unknown",
611607
+ firstName ? `display_name=${firstName}` : "display_name=unknown"
611608
+ ].join(", ");
611609
+ return [
611610
+ `Telegram bot self identity: ${detail}.`,
611611
+ `Known self identity signals (context only, not triggers): ${formatTelegramIdentitySignals(this.telegramSelfIdentitySignals())}.`,
611612
+ `Use these signals to infer whether heard text is probably aimed at this bot; identity matches raise salience but never force should_reply.`
611613
+ ].join("\n");
611614
+ }
611548
611615
  beginAdminAuthChallenge(ttlMs = 5 * 60 * 1e3) {
611549
611616
  const code8 = String(randomInt(1e5, 1e6));
611550
611617
  this.adminAuthChallenge = {
@@ -611572,6 +611639,56 @@ External acquisition contract:
611572
611639
  viewIdForMessage(msg) {
611573
611640
  return `telegram-${this.sessionKeyForMessage(msg).replace(/[^A-Za-z0-9_-]/g, "-")}`;
611574
611641
  }
611642
+ attentionViewIdForMessage(msg) {
611643
+ const id = Number.isFinite(msg.messageId) ? msg.messageId : Date.now();
611644
+ return `${this.viewIdForMessage(msg)}-heard-${id}`;
611645
+ }
611646
+ registerTelegramAttentionView(msg, toolContext, detail = "heard message") {
611647
+ if (!this.subAgentViewCallbacks) return null;
611648
+ const viewId = this.attentionViewIdForMessage(msg);
611649
+ const preview = truncateTelegramContextLine(msg.text || summarizeTelegramMessageAttachments(msg) || "[non-text Telegram message]", 160);
611650
+ const chat = msg.chatTitle || msg.chatType;
611651
+ this.subAgentViewCallbacks.onRegister(
611652
+ viewId,
611653
+ `✈ heard @${msg.username || "telegram"}`,
611654
+ `Telegram attention: ${preview}`
611655
+ );
611656
+ this.subAgentViewCallbacks.onWrite(
611657
+ viewId,
611658
+ `heard: @${msg.username || "unknown"} [${telegramActorKindLabel(msg)}] in ${chat}: ${preview}`
611659
+ );
611660
+ const replyEdge = this.formatTelegramReplyEdgeForTui(this.sessionKeyForMessage(msg), msg);
611661
+ if (replyEdge) this.subAgentViewCallbacks.onWrite(viewId, replyEdge);
611662
+ this.subAgentViewCallbacks.onWrite(viewId, `context: ${detail}; tool_context=${toolContext}; assessing attention, memory, and relationship state`);
611663
+ this.subAgentViewCallbacks.onStatus(viewId, "running");
611664
+ return viewId;
611665
+ }
611666
+ writeTelegramAttentionDecision(viewId, decision) {
611667
+ if (!viewId || !this.subAgentViewCallbacks) return;
611668
+ const route = decision.shouldReply ? `reply via ${decision.route}` : "silent";
611669
+ const attention = [
611670
+ decision.attentionState ? `state=${decision.attentionState}` : "",
611671
+ decision.attentionDelta !== void 0 ? `delta=${decision.attentionDelta.toFixed(2)}` : "",
611672
+ decision.attentionScore !== void 0 ? `score=${decision.attentionScore.toFixed(2)}` : ""
611673
+ ].filter(Boolean).join(", ");
611674
+ const cadence = [
611675
+ decision.nextCheckAfterMessages !== void 0 ? `after ${decision.nextCheckAfterMessages} message(s)` : "",
611676
+ decision.nextCheckAfterMs !== void 0 ? `after ${Math.round(decision.nextCheckAfterMs / 1e3)}s` : ""
611677
+ ].filter(Boolean).join(" or ");
611678
+ const lines = [
611679
+ `decision: ${route} (${decision.source}, confidence ${decision.confidence.toFixed(2)})`,
611680
+ attention ? `attention: ${attention}` : "",
611681
+ `reason: ${decision.reason}`,
611682
+ decision.silentDisposition ? `silent disposition: ${decision.silentDisposition}` : "",
611683
+ decision.mentalNote ? `mental note: ${decision.mentalNote}` : "",
611684
+ decision.memoryNote ? `memory note: ${decision.memoryNote}` : "",
611685
+ decision.relationshipNote ? `relationship note: ${decision.relationshipNote}` : "",
611686
+ cadence ? `next attention sample: ${cadence}` : ""
611687
+ ].filter(Boolean);
611688
+ this.subAgentViewCallbacks.onWrite(viewId, lines.join("\n"));
611689
+ this.subAgentViewCallbacks.onStatus(viewId, "completed");
611690
+ this.subAgentViewCallbacks.onComplete(viewId);
611691
+ }
611575
611692
  normalizeTelegramCommandText(input) {
611576
611693
  const trimmed = input.trim();
611577
611694
  if (!trimmed.startsWith("/")) return input;
@@ -611771,7 +611888,10 @@ No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code
611771
611888
  if (!sender) return void 0;
611772
611889
  const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
611773
611890
  const senderUsername = sender.username?.trim().replace(/^@/, "").toLowerCase();
611774
- const isSelf = Boolean(sender.isSelf || bot && senderUsername === bot);
611891
+ const botUserId = this.currentTelegramBotUserId();
611892
+ const isSelf = Boolean(
611893
+ sender.isSelf || bot && senderUsername === bot || botUserId !== void 0 && sender.id === botUserId
611894
+ );
611775
611895
  return isSelf === sender.isSelf ? sender : { ...sender, isSelf };
611776
611896
  }
611777
611897
  telegramReplyContextFromHistoryEntry(entry) {
@@ -614210,26 +614330,45 @@ ${lines.join("\n")}`);
614210
614330
  this.groupSkipLogAt.set(sessionKey, now);
614211
614331
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `${reason} (context retained)`));
614212
614332
  }
614213
- telegramMessageAddressesBot(msg) {
614214
- const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
614215
- if (!bot) return false;
614216
- const mentioned = (msg.mentionedUsernames ?? []).some(
614217
- (name10) => name10.trim().replace(/^@/, "").toLowerCase() === bot
614218
- );
614219
- if (mentioned) return true;
614220
- if (msg.replyToUsername && msg.replyToUsername.trim().replace(/^@/, "").toLowerCase() === bot) return true;
614221
- const replyUsername = msg.replyContext?.sender?.username?.trim().replace(/^@/, "").toLowerCase();
614222
- if (replyUsername && replyUsername === bot) return true;
614333
+ telegramMessageIdentitySalienceSignals(msg) {
614334
+ const signals = /* @__PURE__ */ new Set();
614335
+ const username = this.state.botUsername.trim().replace(/^@/, "");
614336
+ const usernameLower = username.toLowerCase();
614337
+ const displayName = this.state.botFirstName?.trim() ?? "";
614338
+ const botUserId = this.currentTelegramBotUserId();
614339
+ const text = msg.text || "";
614340
+ if (msg.chatType === "private") signals.add("private_dm_delivery");
614341
+ if (usernameLower) {
614342
+ const mentioned = (msg.mentionedUsernames ?? []).some(
614343
+ (name10) => name10.trim().replace(/^@/, "").toLowerCase() === usernameLower
614344
+ );
614345
+ if (mentioned) signals.add(`entity_mention:@${username}`);
614346
+ const rawMention = new RegExp(`(^|[^A-Za-z0-9_@])@${telegramRegexEscape(username)}(?![A-Za-z0-9_])`, "i");
614347
+ if (rawMention.test(text)) signals.add(`raw_text_mention:@${username}`);
614348
+ if (msg.replyToUsername && msg.replyToUsername.trim().replace(/^@/, "").toLowerCase() === usernameLower) {
614349
+ signals.add(`reply_to_username:@${username}`);
614350
+ }
614351
+ const replyUsername = msg.replyContext?.sender?.username?.trim().replace(/^@/, "").toLowerCase();
614352
+ if (replyUsername && replyUsername === usernameLower) signals.add(`reply_context_username:@${username}`);
614353
+ }
614354
+ if (displayName.length >= 3) {
614355
+ const displayPattern = new RegExp(`(^|[^\\p{L}\\p{N}_])${telegramRegexEscape(displayName)}(?![\\p{L}\\p{N}_])`, "iu");
614356
+ if (displayPattern.test(text)) signals.add(`display_name:${displayName}`);
614357
+ }
614358
+ if (botUserId !== void 0 && msg.replyContext?.sender?.id === botUserId) {
614359
+ signals.add(`reply_context_user_id:${botUserId}`);
614360
+ }
614223
614361
  const resolvedReply = this.resolveTelegramReplyContext(this.sessionKeyForMessage(msg), msg);
614224
- if (resolvedReply?.sender?.isSelf) return true;
614225
- return false;
614362
+ if (resolvedReply?.sender?.isSelf) signals.add("reply_to_self_history");
614363
+ return [...signals];
614226
614364
  }
614227
614365
  telegramMessageRepliesToBot(msg) {
614228
614366
  const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
614229
- if (!bot) return false;
614367
+ const botUserId = this.currentTelegramBotUserId();
614230
614368
  const legacyReply = msg.replyToUsername?.trim().replace(/^@/, "").toLowerCase();
614231
614369
  const contextReply = msg.replyContext?.sender?.username?.trim().replace(/^@/, "").toLowerCase();
614232
- if (legacyReply === bot || contextReply === bot) return true;
614370
+ if (bot && (legacyReply === bot || contextReply === bot)) return true;
614371
+ if (botUserId !== void 0 && msg.replyContext?.sender?.id === botUserId) return true;
614233
614372
  const resolvedReply = this.resolveTelegramReplyContext(this.sessionKeyForMessage(msg), msg);
614234
614373
  return Boolean(resolvedReply?.sender?.isSelf);
614235
614374
  }
@@ -614247,7 +614386,8 @@ ${lines.join("\n")}`);
614247
614386
  const config = this.agentConfig;
614248
614387
  const forcedRoute = this.interactionMode === "chat" || this.interactionMode === "action" ? this.interactionMode : null;
614249
614388
  const isGroup = msg.chatType !== "private";
614250
- const addressesBot = this.telegramMessageAddressesBot(msg);
614389
+ const identitySalienceSignals = this.telegramMessageIdentitySalienceSignals(msg);
614390
+ const addressesBot = identitySalienceSignals.length > 0;
614251
614391
  const sessionKey = this.sessionKeyForMessage(msg);
614252
614392
  const daydreamForceCheck = isGroup && this.shouldForceAnalysisFromChannelDaydream(sessionKey);
614253
614393
  const stimulationProbe = this.stimulation.observe({
@@ -614258,22 +614398,15 @@ ${lines.join("\n")}`);
614258
614398
  activeAgent: this.subAgents.has(sessionKey),
614259
614399
  forceAnalyze: daydreamForceCheck
614260
614400
  });
614261
- if (isGroup && !stimulationProbe.shouldAnalyze) {
614262
- return {
614263
- route: forcedRoute ?? "chat",
614264
- shouldReply: false,
614265
- confidence: 0.35,
614266
- reason: `stimulation cadence held analysis (${stimulationProbe.reason}); context retained`,
614267
- source: "attention-gated"
614268
- };
614269
- }
614270
614401
  if (!config) {
614271
614402
  const fallback2 = {
614272
614403
  route: forcedRoute ?? (isGroup ? "action" : "chat"),
614273
- shouldReply: !isGroup || addressesBot,
614404
+ shouldReply: false,
614274
614405
  confidence: 0,
614275
- reason: isGroup ? addressesBot ? "router inference unavailable; Telegram message directly addresses the bot" : "router inference unavailable; public group fails closed without keyword heuristics" : "router inference unavailable; private chat defaults to quick reply",
614276
- source: "inference-unavailable"
614406
+ reason: "router inference unavailable; no model-derived reply decision",
614407
+ source: "inference-unavailable",
614408
+ silentDisposition: "retained as context without replying",
614409
+ mentalNote: "router unavailable, so no model-derived attention note was produced"
614277
614410
  };
614278
614411
  this.applyTelegramStimulationDecision(sessionKey, fallback2);
614279
614412
  return fallback2;
@@ -614286,21 +614419,24 @@ ${lines.join("\n")}`);
614286
614419
  const forcedLine = forcedRoute ? `The operator selected Telegram mode "${forcedRoute}". The route field MUST be "${forcedRoute}", but should_reply must still be inferred live from context.` : `The operator selected Telegram mode "auto". Infer route live from context.`;
614287
614420
  const context2 = this.buildTelegramConversationContextStream(sessionKey, msg, isGroup ? 36 : 20);
614288
614421
  const currentReplyContext = this.buildTelegramCurrentReplyContext(sessionKey, msg);
614422
+ const selfIdentityContext = this.buildTelegramSelfIdentityContext();
614289
614423
  const userPrompt = [
614290
614424
  `You are the Telegram live routing and reply-discretion model.`,
614291
614425
  `Return JSON only, with no markdown and no explanation outside JSON.`,
614292
614426
  ``,
614293
- `Schema: {"route":"chat"|"action","should_reply":true|false,"confidence":0.0-1.0,"reason":"short reason","attention_state":"idle"|"observing"|"engaged"|"cooldown","attention_delta":-1.0..1.0,"next_check_after_messages":1..12}`,
614427
+ `Schema: {"route":"chat"|"action","should_reply":true|false,"confidence":0.0-1.0,"reason":"short reason","attention_state":"idle"|"observing"|"engaged"|"cooldown","attention_delta":-1.0..1.0,"next_check_after_messages":1..12,"silent_disposition":"short outcome-level disposition","mental_note":"short outcome-level observation","memory_note":"short memory/summary update","relationship_note":"short relationship/thread note"}`,
614294
614428
  ``,
614295
614429
  `Route meanings:`,
614296
614430
  `- chat: a short conversational answer can be produced without tools.`,
614297
614431
  `- action: tools, workspace context, media processing, web lookup, delegation, or a multi-step agent loop may be needed.`,
614298
614432
  `Route discipline: greetings, acknowledgements, casual tone/style discussion, and simple conversational questions are chat. Use action only when the message asks you to inspect, create, change, send, remember, search, analyze media, extract text from images/screenshots/forms/scans, name/enroll/identify a person/face/voice from media, or otherwise do tool-backed work.`,
614299
614433
  ``,
614300
- `Reply discretion: infer from the live thread, speaker relationships, direct platform signals, replies, tone, current message, and any private channel daydream artifact supplied in context. Do not use static keyword rules.`,
614301
- `Private chats: should_reply is normally true.`,
614302
- `Group/public chats: default should_reply to false unless the current message clearly addresses the bot, replies to the bot, continues an active bot-involved exchange, assigns the bot work, asks for the bot's view, or is semantically connected to durable memory/current discussion in a way where a concise bot reply is socially useful. Ambient chatter, third-person discussion about the bot, commands meant for a human, or questions among other people are false. Do not set true just because the bot could help.`,
614303
- `Bot-to-bot discipline: sender labels include [bot] or [human]. Treat peer bots as autonomous actors, not human users. Be more conservative with peer-bot messages unless explicitly addressed, and avoid bot loops by preferring no_reply for repetitive bot chatter.`,
614434
+ `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.`,
614435
+ `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.`,
614436
+ `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.`,
614437
+ `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.`,
614438
+ `Observation notes: always fill silent_disposition, mental_note, memory_note, and relationship_note with concise outcome-level notes for the TUI. Do not expose hidden chain-of-thought; summarize what the bot did with the heard message.`,
614439
+ `Bot-to-bot discipline: sender labels include [bot] or [human]. Treat peer bots as autonomous actors, not human users. Avoid bot loops by replying only when the exchange context makes a response socially useful.`,
614304
614440
  `Ingress discipline: this Telegram message has already been retained as chat context. should_reply controls only whether to emit a visible reply.`,
614305
614441
  `Memory discipline: use durable associative user memory, relationships, prior actions, and recent context to infer whether this speaker is continuing a bot-related thread. A mention is not required when the semantic target is clearly the bot or an ongoing bot-mediated discussion.`,
614306
614442
  `Channel daydream discipline: a daydream artifact may highlight relationship signals, unresolved questions, or possible reply opportunities from idle reflection. It can justify analyzing this turn, but it does not force a reply. Reply only if the current user entry makes the intervention timely and socially appropriate.`,
@@ -614308,8 +614444,9 @@ ${lines.join("\n")}`);
614308
614444
  forcedLine,
614309
614445
  ``,
614310
614446
  `Tool context: ${toolContext}`,
614311
- `Bot username: ${this.state.botUsername || "unknown"}`,
614312
- `Current message directly addresses this bot: ${addressesBot ? "yes" : "no"}`,
614447
+ selfIdentityContext,
614448
+ `Platform notification/direct-address signal (salience evidence only, not a decision): ${addressesBot ? "yes" : "no"}`,
614449
+ `Platform salience signals (context only, not triggers): ${identitySalienceSignals.length ? identitySalienceSignals.join(", ") : "none"}`,
614313
614450
  `Current chat type: ${msg.chatType}`,
614314
614451
  `Current sender: ${telegramSpeakerLabel(msg)} [${telegramActorKindLabel(msg)}]`,
614315
614452
  msg.replyToMessageId ? `Current message replies to message_id ${msg.replyToMessageId}` : "",
@@ -614318,8 +614455,9 @@ ${lines.join("\n")}`);
614318
614455
  (msg.mentionedUsernames ?? []).length > 0 ? `Current message mentions: ${(msg.mentionedUsernames ?? []).map((name10) => `@${name10}`).join(", ")}` : "",
614319
614456
  msg.media ? `Current message has media: ${summarizeTelegramMessageAttachments(msg)}` : "",
614320
614457
  ``,
614321
- `Current stimulation state before semantic decision:
614458
+ `Current stimulation state before semantic decision (context only; do not treat cadence as a hard reply filter):
614322
614459
  ${stimulationProbe.context}`,
614460
+ `Stimulation analysis cadence says: ${stimulationProbe.shouldAnalyze ? "analyze-now" : `low-priority sample (${stimulationProbe.reason})`}. You must still make the should_reply decision semantically.`,
614323
614461
  ``,
614324
614462
  context2,
614325
614463
  ``,
@@ -614343,7 +614481,7 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
614343
614481
  });
614344
614482
  const text = result.choices[0]?.message?.content ?? "";
614345
614483
  const parsed = parseTelegramInteractionDecision(text, forcedRoute, {
614346
- defaultShouldReply: !isGroup
614484
+ defaultShouldReply: false
614347
614485
  });
614348
614486
  if (parsed) {
614349
614487
  this.applyTelegramStimulationDecision(sessionKey, parsed);
@@ -614353,10 +614491,12 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
614353
614491
  }
614354
614492
  const fallback = {
614355
614493
  route: forcedRoute ?? (isGroup ? "action" : "chat"),
614356
- shouldReply: !isGroup || addressesBot,
614494
+ shouldReply: false,
614357
614495
  confidence: 0,
614358
- reason: isGroup ? addressesBot ? "router inference failed; Telegram message directly addresses the bot" : "router inference failed; public group fails closed without keyword heuristics" : "router inference failed; private chat defaults to quick reply",
614359
- source: "inference-unavailable"
614496
+ reason: "router inference failed; no model-derived reply decision",
614497
+ source: "inference-unavailable",
614498
+ silentDisposition: "retained as context without replying",
614499
+ mentalNote: "router failed, so no model-derived attention note was produced"
614360
614500
  };
614361
614501
  this.applyTelegramStimulationDecision(sessionKey, fallback);
614362
614502
  return fallback;
@@ -614706,7 +614846,9 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
614706
614846
  }
614707
614847
  this.state = {
614708
614848
  active: true,
614849
+ botUserId: typeof me.result?.id === "number" ? me.result.id : void 0,
614709
614850
  botUsername: me.result?.username ?? "unknown",
614851
+ botFirstName: typeof me.result?.first_name === "string" ? me.result.first_name : void 0,
614710
614852
  supportsGuestQueries: Boolean(me.result?.supports_guest_queries),
614711
614853
  canReadAllGroupMessages: me.result?.can_read_all_group_messages === true,
614712
614854
  interactionMode: this.interactionMode,
@@ -614954,10 +615096,8 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
614954
615096
  if (startsWithSlash && isAdminAuthSecretCommand && await this.handleAdminAuthCommand({ ...msg, text: normalizedCommandText })) {
614955
615097
  return;
614956
615098
  }
614957
- if (msg.chatType !== "private") {
614958
- this.recordTelegramUserMessage(msg, "ambient");
614959
- this.tuiWrite(() => renderTelegramIngressMessage(msg));
614960
- }
615099
+ this.recordTelegramUserMessage(msg, "ambient");
615100
+ this.tuiWrite(() => renderTelegramIngressMessage(msg));
614961
615101
  if (startsWithSlash && !isAdminAuthSecretCommand && await this.handleAdminAuthCommand({ ...msg, text: normalizedCommandText })) {
614962
615102
  return;
614963
615103
  }
@@ -615079,8 +615219,9 @@ Join: ${newUrl}`);
615079
615219
  if (existing && !existing.aborted) {
615080
615220
  const isGroup = msg.chatType !== "private";
615081
615221
  if (isGroup) {
615082
- this.recordTelegramUserMessage(msg, "ambient");
615222
+ const attentionViewId2 = this.registerTelegramAttentionView(msg, existing.toolContext || toolContext, "active Telegram thread");
615083
615223
  const decision2 = await this.inferTelegramInteractionDecision(msg, existing.toolContext || toolContext);
615224
+ this.writeTelegramAttentionDecision(attentionViewId2, decision2);
615084
615225
  this.markLastTelegramUserMessageMode(msg, decision2.shouldReply ? "steering" : "ambient");
615085
615226
  this.subAgentViewCallbacks?.onWrite(
615086
615227
  existing.viewId,
@@ -615115,8 +615256,9 @@ Join: ${newUrl}`);
615115
615256
  }
615116
615257
  return;
615117
615258
  }
615118
- this.recordTelegramUserMessage(msg, "ambient");
615259
+ const attentionViewId = this.registerTelegramAttentionView(msg, toolContext);
615119
615260
  const decision = await this.inferTelegramInteractionDecision(msg, toolContext);
615261
+ this.writeTelegramAttentionDecision(attentionViewId, decision);
615120
615262
  this.markLastTelegramUserMessageMode(msg, decision.shouldReply ? decision.route : "ambient");
615121
615263
  this.subAgentViewCallbacks?.onWrite(
615122
615264
  this.viewIdForMessage(msg),
@@ -615498,6 +615640,7 @@ ${TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT}
615498
615640
  ${TELEGRAM_PUBLIC_VISION_STACK_CONTRACT}`;
615499
615641
  const groupHint = isGroup ? `Telegram group: ${msg.chatTitle || "unknown"}. The live router selected this turn as reply-worthy; keep the reply short and relevant. Never output a skip decision, no_reply marker, memory-stage note, or completion status.` : "Telegram private chat.";
615500
615642
  const runtime = buildTelegramRuntimeContext(/* @__PURE__ */ new Date());
615643
+ const selfIdentityContext = this.buildTelegramSelfIdentityContext();
615501
615644
  const messages2 = [
615502
615645
  {
615503
615646
  role: "system",
@@ -615507,6 +615650,8 @@ ${TELEGRAM_PUBLIC_VISION_STACK_CONTRACT}`;
615507
615650
 
615508
615651
  ${runtime}
615509
615652
 
615653
+ ${selfIdentityContext}
615654
+
615510
615655
  ${safety}
615511
615656
 
615512
615657
  ${groupHint}
@@ -615783,10 +615928,13 @@ Respond concisely and safely. Send the actual chat reply, not router/status/comp
615783
615928
  [Media attached — processed content below]
615784
615929
  ${mediaContext}`;
615785
615930
  }
615931
+ const selfIdentityContext = this.buildTelegramSelfIdentityContext();
615786
615932
  const systemCtx = isAdminDM ? `${runtimeContext}
615933
+ ${selfIdentityContext}
615787
615934
  Telegram admin: @${msg.username}
615788
615935
  Telegram profile: ${profile}
615789
615936
  Todo/session id: ${sessionContext.sessionId}` : `${runtimeContext}
615937
+ ${selfIdentityContext}
615790
615938
  Telegram ${isGroup ? "group" : "public"} chat. Respond concisely. Safety filter: ACTIVE.${creativeWorkspace ? `
615791
615939
 
615792
615940
  ${creativeWorkspace}` : ""}`;
@@ -617197,7 +617345,9 @@ Scoped workspace: ${scopedRoot}`,
617197
617345
  }
617198
617346
  const botId = result.result.id;
617199
617347
  this.botUserId = botId;
617348
+ this.state.botUserId = botId;
617200
617349
  if (typeof result.result.username === "string") this.state.botUsername = result.result.username;
617350
+ if (typeof result.result.first_name === "string") this.state.botFirstName = result.result.first_name;
617201
617351
  return botId;
617202
617352
  }
617203
617353
  async getChatMember(chatId, userId) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.70",
3
+ "version": "1.0.72",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.70",
9
+ "version": "1.0.72",
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.70",
3
+ "version": "1.0.72",
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",