omnius 1.0.33 → 1.0.34

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
@@ -599929,6 +599929,21 @@ function telegramSpeakerLabel(msg) {
599929
599929
  if (msg.fromUserId) return `user:${msg.fromUserId}`;
599930
599930
  return "Telegram user";
599931
599931
  }
599932
+ function telegramReplySenderLabel(sender) {
599933
+ if (!sender) return "unknown sender";
599934
+ if (sender.username) return `@${sender.username}`;
599935
+ if (sender.title) return sender.title;
599936
+ if (sender.firstName) return sender.firstName;
599937
+ if (sender.id) return `user:${sender.id}`;
599938
+ return "unknown sender";
599939
+ }
599940
+ function telegramReplyParameters(replyToMessageId) {
599941
+ if (!replyToMessageId || !Number.isFinite(replyToMessageId)) return void 0;
599942
+ return {
599943
+ message_id: Math.floor(replyToMessageId),
599944
+ allow_sending_without_reply: true
599945
+ };
599946
+ }
599932
599947
  function telegramHistorySpeaker(entry) {
599933
599948
  if (entry.role === "assistant") return entry.speaker || "Assistant";
599934
599949
  if (entry.speaker) return entry.speaker;
@@ -600344,6 +600359,140 @@ function normalizeTelegramMedia(message2) {
600344
600359
  }
600345
600360
  return void 0;
600346
600361
  }
600362
+ function telegramOptionalString(value2) {
600363
+ return typeof value2 === "string" && value2.trim() ? value2 : void 0;
600364
+ }
600365
+ function telegramOptionalNumber(value2) {
600366
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : void 0;
600367
+ }
600368
+ function normalizeTelegramReplySender(message2) {
600369
+ if (!message2) return void 0;
600370
+ const from3 = typeof message2.from === "object" && message2.from ? message2.from : void 0;
600371
+ const senderChat = typeof message2.sender_chat === "object" && message2.sender_chat ? message2.sender_chat : void 0;
600372
+ const origin = typeof message2.origin === "object" && message2.origin ? message2.origin : void 0;
600373
+ const originUser = typeof origin?.sender_user === "object" && origin.sender_user ? origin.sender_user : void 0;
600374
+ const originChat = typeof origin?.chat === "object" && origin.chat ? origin.chat : void 0;
600375
+ const source = from3 ?? senderChat ?? originUser ?? originChat;
600376
+ if (!source) {
600377
+ const senderUserName = telegramOptionalString(origin?.sender_user_name);
600378
+ const authorSignature = telegramOptionalString(origin?.author_signature);
600379
+ if (!senderUserName && !authorSignature) return void 0;
600380
+ return {
600381
+ firstName: senderUserName ?? authorSignature
600382
+ };
600383
+ }
600384
+ return {
600385
+ id: telegramOptionalNumber(source.id),
600386
+ username: telegramOptionalString(source.username),
600387
+ firstName: telegramOptionalString(source.first_name),
600388
+ title: telegramOptionalString(source.title),
600389
+ isBot: typeof source.is_bot === "boolean" ? source.is_bot : void 0
600390
+ };
600391
+ }
600392
+ function telegramReplyTextFromMessage(message2, poll) {
600393
+ return telegramOptionalString(message2.text) ?? telegramOptionalString(message2.caption) ?? (poll ? formatTelegramPollSummary(poll) : void 0);
600394
+ }
600395
+ function telegramReplyOriginSummary(origin) {
600396
+ if (!origin || typeof origin !== "object") return void 0;
600397
+ const record = origin;
600398
+ const type = telegramOptionalString(record.type);
600399
+ const sender = normalizeTelegramReplySender({ origin: record });
600400
+ const label = sender?.username ? `@${sender.username}` : sender?.title ?? sender?.firstName;
600401
+ return [type ? `origin:${type}` : "", label ? `from ${label}` : ""].filter(Boolean).join(" ") || void 0;
600402
+ }
600403
+ function normalizeTelegramQuote(raw) {
600404
+ if (!raw || typeof raw !== "object") return void 0;
600405
+ const quote = raw;
600406
+ const text = telegramOptionalString(quote.text);
600407
+ const position = telegramOptionalNumber(quote.position);
600408
+ if (!text && position === void 0) return void 0;
600409
+ return { text, position };
600410
+ }
600411
+ function normalizeTelegramReplyContext(message2) {
600412
+ const quote = normalizeTelegramQuote(message2.quote);
600413
+ const replyTo = message2.reply_to_message && typeof message2.reply_to_message === "object" ? message2.reply_to_message : void 0;
600414
+ if (replyTo) {
600415
+ const poll = normalizeTelegramPoll(replyTo.poll);
600416
+ const media = normalizeTelegramMedia(replyTo);
600417
+ return {
600418
+ kind: "message",
600419
+ source: "reply_to_message",
600420
+ messageId: telegramOptionalNumber(replyTo.message_id),
600421
+ chatId: normalizeTelegramChatId(replyTo.chat?.id ?? message2.chat?.id),
600422
+ threadId: telegramOptionalNumber(replyTo.message_thread_id ?? message2.message_thread_id),
600423
+ sender: normalizeTelegramReplySender(replyTo),
600424
+ text: telegramReplyTextFromMessage(replyTo, poll),
600425
+ caption: telegramOptionalString(replyTo.caption),
600426
+ quote: quote?.text,
600427
+ quotePosition: quote?.position,
600428
+ media,
600429
+ poll,
600430
+ checklistTaskId: telegramOptionalNumber(message2.reply_to_checklist_task_id),
600431
+ pollOptionId: telegramOptionalString(message2.reply_to_poll_option_id)
600432
+ };
600433
+ }
600434
+ const externalReply = message2.external_reply && typeof message2.external_reply === "object" ? message2.external_reply : void 0;
600435
+ if (externalReply) {
600436
+ const poll = normalizeTelegramPoll(externalReply.poll);
600437
+ const media = normalizeTelegramMedia(externalReply);
600438
+ return {
600439
+ kind: "external",
600440
+ source: "external_reply",
600441
+ messageId: telegramOptionalNumber(externalReply.message_id),
600442
+ chatId: externalReply.chat?.id !== void 0 ? normalizeTelegramChatId(externalReply.chat.id) : void 0,
600443
+ threadId: telegramOptionalNumber(message2.message_thread_id),
600444
+ sender: normalizeTelegramReplySender(externalReply),
600445
+ text: telegramReplyTextFromMessage(externalReply, poll),
600446
+ caption: telegramOptionalString(externalReply.caption),
600447
+ quote: quote?.text,
600448
+ quotePosition: quote?.position,
600449
+ media,
600450
+ poll,
600451
+ checklistTaskId: telegramOptionalNumber(message2.reply_to_checklist_task_id),
600452
+ pollOptionId: telegramOptionalString(message2.reply_to_poll_option_id),
600453
+ originSummary: telegramReplyOriginSummary(externalReply.origin)
600454
+ };
600455
+ }
600456
+ if (quote?.text) {
600457
+ return {
600458
+ kind: "quote",
600459
+ source: "quote",
600460
+ threadId: telegramOptionalNumber(message2.message_thread_id),
600461
+ quote: quote.text,
600462
+ quotePosition: quote.position
600463
+ };
600464
+ }
600465
+ const story = message2.reply_to_story && typeof message2.reply_to_story === "object" ? message2.reply_to_story : void 0;
600466
+ if (story) {
600467
+ return {
600468
+ kind: "story",
600469
+ source: "reply_to_story",
600470
+ chatId: story.chat?.id !== void 0 ? normalizeTelegramChatId(story.chat.id) : void 0,
600471
+ storyId: telegramOptionalNumber(story.id),
600472
+ sender: normalizeTelegramReplySender(story),
600473
+ threadId: telegramOptionalNumber(message2.message_thread_id)
600474
+ };
600475
+ }
600476
+ const checklistTaskId = telegramOptionalNumber(message2.reply_to_checklist_task_id);
600477
+ if (checklistTaskId !== void 0) {
600478
+ return {
600479
+ kind: "checklist_task",
600480
+ source: "reply_to_checklist_task",
600481
+ checklistTaskId,
600482
+ threadId: telegramOptionalNumber(message2.message_thread_id)
600483
+ };
600484
+ }
600485
+ const pollOptionId = telegramOptionalString(message2.reply_to_poll_option_id);
600486
+ if (pollOptionId) {
600487
+ return {
600488
+ kind: "poll_option",
600489
+ source: "reply_to_poll_option",
600490
+ pollOptionId,
600491
+ threadId: telegramOptionalNumber(message2.message_thread_id)
600492
+ };
600493
+ }
600494
+ return void 0;
600495
+ }
600347
600496
  function telegramMediaIsImage(media) {
600348
600497
  if (media.type === "photo") return true;
600349
600498
  if (media.mimeType?.toLowerCase().startsWith("image/")) return true;
@@ -600426,10 +600575,7 @@ function normalizeTelegramUpdate(update2) {
600426
600575
  const username = message2.from?.username ?? message2.sender_chat?.username ?? "";
600427
600576
  const chatType = message2.chat?.type ?? "private";
600428
600577
  const media = normalizeTelegramMedia(message2);
600429
- const replyTo = message2.reply_to_message && typeof message2.reply_to_message === "object" ? message2.reply_to_message : void 0;
600430
- const replyToMedia = replyTo ? normalizeTelegramMedia(replyTo) : void 0;
600431
- const replyToPoll = replyTo ? normalizeTelegramPoll(replyTo.poll) : void 0;
600432
- const replyToText = replyTo ? replyTo.text || replyTo.caption || (replyToPoll ? formatTelegramPollSummary(replyToPoll) : "") : "";
600578
+ const replyContext = normalizeTelegramReplyContext(message2);
600433
600579
  const poll = normalizeTelegramPoll(message2.poll);
600434
600580
  const livePhoto = normalizeTelegramLivePhoto(message2.live_photo);
600435
600581
  const text = message2.text || message2.caption || (poll ? formatTelegramPollSummary(poll) : "");
@@ -600444,8 +600590,6 @@ function normalizeTelegramUpdate(update2) {
600444
600590
  chatType,
600445
600591
  chatTitle: message2.chat?.title,
600446
600592
  media,
600447
- replyToMedia,
600448
- replyToText: replyToText || void 0,
600449
600593
  poll,
600450
600594
  livePhoto,
600451
600595
  guestQueryId: typeof message2.guest_query_id === "string" ? message2.guest_query_id : void 0,
@@ -600454,9 +600598,13 @@ function normalizeTelegramUpdate(update2) {
600454
600598
  isGuestMessage: sourceUpdateType === "guest_message",
600455
600599
  isDirectMessages: Boolean(message2.chat?.is_direct_messages),
600456
600600
  parentChatId: message2.chat?.parent_chat?.id ?? message2.direct_messages_topic?.parent_topic?.id,
600457
- replyToMessageId: replyTo?.message_id,
600458
- replyToUsername: replyTo?.from?.username ?? replyTo?.sender_chat?.username,
600459
- replyToBot: Boolean(replyTo?.from?.is_bot),
600601
+ messageThreadId: telegramOptionalNumber(message2.message_thread_id),
600602
+ replyContext,
600603
+ replyToMedia: replyContext?.media,
600604
+ replyToText: replyContext?.text || replyContext?.quote,
600605
+ replyToMessageId: replyContext?.messageId,
600606
+ replyToUsername: replyContext?.sender?.username,
600607
+ replyToBot: Boolean(replyContext?.sender?.isBot),
600460
600608
  mentionedUsernames: extractTelegramMentionedUsernames(message2, text),
600461
600609
  sourceUpdateType
600462
600610
  };
@@ -601095,6 +601243,134 @@ Telegram response contract:
601095
601243
  }
601096
601244
  this.chatHistory.set(sessionKey, existing);
601097
601245
  }
601246
+ telegramReplySenderWithSelfFlag(sender) {
601247
+ if (!sender) return void 0;
601248
+ const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
601249
+ const senderUsername = sender.username?.trim().replace(/^@/, "").toLowerCase();
601250
+ const isSelf = Boolean(sender.isSelf || bot && senderUsername === bot);
601251
+ return isSelf === sender.isSelf ? sender : { ...sender, isSelf };
601252
+ }
601253
+ telegramReplyContextFromHistoryEntry(entry) {
601254
+ if (!entry.messageId) return void 0;
601255
+ const sender = entry.role === "assistant" ? {
601256
+ username: this.state.botUsername || void 0,
601257
+ firstName: entry.speaker || "Assistant",
601258
+ isBot: true,
601259
+ isSelf: true
601260
+ } : {
601261
+ id: entry.fromUserId,
601262
+ username: entry.username,
601263
+ firstName: entry.firstName,
601264
+ isBot: false
601265
+ };
601266
+ return {
601267
+ kind: "message",
601268
+ source: "local_history",
601269
+ messageId: entry.messageId,
601270
+ chatId: entry.chatId,
601271
+ threadId: entry.messageThreadId,
601272
+ sender: this.telegramReplySenderWithSelfFlag(sender),
601273
+ text: entry.text,
601274
+ mediaSummary: entry.mediaSummary
601275
+ };
601276
+ }
601277
+ resolveTelegramReplyContext(sessionKey, msg) {
601278
+ this.ensureTelegramConversationLoaded(sessionKey);
601279
+ const targetId = msg.replyContext?.messageId ?? msg.replyToMessageId;
601280
+ const history = this.chatHistory.get(sessionKey) ?? [];
601281
+ const local = targetId ? [...history].reverse().find((entry) => entry.messageId === targetId) : void 0;
601282
+ const localContext = local ? this.telegramReplyContextFromHistoryEntry(local) : void 0;
601283
+ let reply;
601284
+ if (msg.replyContext && localContext) {
601285
+ reply = {
601286
+ ...localContext,
601287
+ ...msg.replyContext,
601288
+ chatId: msg.replyContext.chatId ?? localContext.chatId,
601289
+ threadId: msg.replyContext.threadId ?? localContext.threadId,
601290
+ sender: this.telegramReplySenderWithSelfFlag({
601291
+ ...localContext.sender ?? {},
601292
+ ...msg.replyContext.sender ?? {}
601293
+ }),
601294
+ text: msg.replyContext.text ?? localContext.text,
601295
+ mediaSummary: msg.replyContext.mediaSummary ?? localContext.mediaSummary
601296
+ };
601297
+ } else if (msg.replyContext) {
601298
+ reply = {
601299
+ ...msg.replyContext,
601300
+ sender: this.telegramReplySenderWithSelfFlag(msg.replyContext.sender)
601301
+ };
601302
+ } else if (localContext) {
601303
+ reply = localContext;
601304
+ } else if (msg.replyToMessageId) {
601305
+ reply = {
601306
+ kind: "message",
601307
+ source: "local_history",
601308
+ messageId: msg.replyToMessageId,
601309
+ threadId: msg.messageThreadId
601310
+ };
601311
+ }
601312
+ return reply;
601313
+ }
601314
+ quoteTelegramContextBlock(text, maxLength = 1800) {
601315
+ const clean3 = stripTelegramHiddenThinking(text).trim();
601316
+ const clipped = clean3.length > maxLength ? `${clean3.slice(0, Math.max(0, maxLength - 60)).trimEnd()}
601317
+ [reply context truncated]` : clean3;
601318
+ return clipped.split(/\r?\n/).map((line) => `> ${line}`).join("\n");
601319
+ }
601320
+ buildTelegramCurrentReplyContext(sessionKey, msg) {
601321
+ const reply = this.resolveTelegramReplyContext(sessionKey, msg);
601322
+ if (!reply) return "";
601323
+ const current = telegramSpeakerLabel(msg);
601324
+ const target = telegramReplySenderLabel(reply.sender);
601325
+ const selfMarker = reply.sender?.isSelf ? " (bot/self)" : reply.sender?.isBot ? " (bot)" : "";
601326
+ const targetId = reply.messageId ? ` message_id ${reply.messageId}` : "";
601327
+ const relation = reply.kind === "external" ? "is replying to an external Telegram message" : reply.kind === "quote" ? "is replying to a quoted Telegram excerpt" : reply.kind === "story" ? "is replying to a Telegram story" : reply.kind === "checklist_task" ? "is replying to a Telegram checklist task" : reply.kind === "poll_option" ? "is replying to a Telegram poll option" : "is replying to a Telegram message";
601328
+ const metadata = [
601329
+ `Current message_id ${msg.messageId} from ${current} ${relation}${targetId}.`,
601330
+ `Replied-to author: ${target}${selfMarker}.`,
601331
+ `Reply source: ${reply.source}.`,
601332
+ reply.chatId !== void 0 ? `Replied-to chat_id: ${String(reply.chatId)}.` : "",
601333
+ reply.threadId !== void 0 ? `Telegram thread/topic id: ${reply.threadId}.` : "",
601334
+ reply.originSummary ? `External origin: ${reply.originSummary}.` : "",
601335
+ reply.storyId !== void 0 ? `Story id: ${reply.storyId}.` : "",
601336
+ reply.checklistTaskId !== void 0 ? `Checklist task id: ${reply.checklistTaskId}.` : "",
601337
+ reply.pollOptionId ? `Poll option id: ${reply.pollOptionId}.` : ""
601338
+ ].filter(Boolean);
601339
+ const content = reply.text || reply.caption;
601340
+ const blocks = [
601341
+ "### Current Telegram Reply Relationship",
601342
+ metadata.join("\n"),
601343
+ reply.quote ? `Quoted excerpt:
601344
+ ${this.quoteTelegramContextBlock(reply.quote, 1e3)}` : "",
601345
+ content ? `Replied-to content:
601346
+ ${this.quoteTelegramContextBlock(content, 2200)}` : "",
601347
+ reply.mediaSummary ? `Replied-to media: ${reply.mediaSummary}` : "",
601348
+ reply.media && !reply.mediaSummary ? `Replied-to media: ${reply.media.type}${reply.media.fileName ? ` ${reply.media.fileName}` : ""}${reply.media.mimeType ? ` ${reply.media.mimeType}` : ""}` : "",
601349
+ msg.text ? `Current user message:
601350
+ ${this.quoteTelegramContextBlock(msg.text, 1e3)}` : "",
601351
+ 'Instruction: resolve pronouns, follow-up requests, and requests like "links", "repos", "instructions", "that", or "this" against the replied-to content before broader chat/workspace context.'
601352
+ ].filter(Boolean);
601353
+ return blocks.join("\n");
601354
+ }
601355
+ formatTelegramCurrentMessageForPrompt(sessionKey, msg, header, mediaContext = "") {
601356
+ return [
601357
+ this.buildTelegramCurrentReplyContext(sessionKey, msg),
601358
+ `${header}:
601359
+ ${msg.text}`,
601360
+ mediaContext ? `[Media attached - processed content below]
601361
+ ${mediaContext}` : ""
601362
+ ].filter(Boolean).join("\n\n");
601363
+ }
601364
+ formatTelegramReplyEdgeForTui(sessionKey, msg) {
601365
+ const reply = this.resolveTelegramReplyContext(sessionKey, msg);
601366
+ if (!reply) return "";
601367
+ const current = telegramSpeakerLabel(msg);
601368
+ const target = telegramReplySenderLabel(reply.sender);
601369
+ const selfMarker = reply.sender?.isSelf ? " (bot/self)" : "";
601370
+ const id = reply.messageId ? ` #${reply.messageId}` : "";
601371
+ const preview = truncateTelegramContextLine(reply.quote || reply.text || reply.caption || reply.mediaSummary || reply.originSummary || reply.kind, 160);
601372
+ return `reply: ${current} -> ${target}${selfMarker}${id}${preview ? `: "${preview}"` : ""}`;
601373
+ }
601098
601374
  telegramConversationPath(sessionKey) {
601099
601375
  const safe = createHash19("sha1").update(sessionKey).digest("hex").slice(0, 20);
601100
601376
  return join121(this.telegramConversationDir, `${safe}.json`);
@@ -601197,7 +601473,9 @@ Telegram response contract:
601197
601473
  firstName: msg.firstName,
601198
601474
  fromUserId: msg.fromUserId,
601199
601475
  messageId: msg.messageId,
601476
+ messageThreadId: msg.messageThreadId,
601200
601477
  replyToMessageId: msg.replyToMessageId,
601478
+ replyContext: msg.replyContext,
601201
601479
  chatType: msg.chatType,
601202
601480
  chatTitle: msg.chatTitle,
601203
601481
  mediaSummary
@@ -601221,7 +601499,7 @@ Telegram response contract:
601221
601499
  }
601222
601500
  this.saveTelegramConversationState(sessionKey);
601223
601501
  }
601224
- recordTelegramAssistantMessage(msg, text, mode) {
601502
+ recordTelegramAssistantMessage(msg, text, mode, options2 = {}) {
601225
601503
  const clean3 = stripTelegramHiddenThinking(text).trim();
601226
601504
  if (!clean3) return;
601227
601505
  const sessionKey = this.sessionKeyForMessage(msg);
@@ -601231,6 +601509,9 @@ Telegram response contract:
601231
601509
  mode,
601232
601510
  chatId: msg.chatId,
601233
601511
  speaker: this.state.botUsername ? `@${this.state.botUsername}` : "Assistant",
601512
+ messageId: options2.messageId ?? void 0,
601513
+ messageThreadId: msg.messageThreadId,
601514
+ replyToMessageId: options2.replyToMessageId,
601234
601515
  chatType: msg.chatType,
601235
601516
  chatTitle: msg.chatTitle
601236
601517
  };
@@ -601467,12 +601748,14 @@ Telegram response contract:
601467
601748
  })).sort((a2, b) => b.score - a2.score || b.card.updatedAt - a2.card.updatedAt).slice(0, limit);
601468
601749
  }
601469
601750
  buildTelegramConversationContextStream(sessionKey, msg, maxRecent = TELEGRAM_CONTEXT_RECENT_DEFAULT) {
601751
+ this.ensureTelegramConversationLoaded(sessionKey);
601470
601752
  const history = this.chatHistory.get(sessionKey) ?? [];
601471
601753
  const participants = [...this.chatParticipants.get(sessionKey)?.values() ?? []].sort((a2, b) => b.lastSeenTs - a2.lastSeenTs);
601472
601754
  const isGroup = msg.chatType !== "private";
601473
601755
  const retainedCount = history.length;
601474
601756
  const olderCount = Math.max(0, retainedCount - maxRecent);
601475
601757
  const currentSpeaker = telegramSpeakerLabel(msg);
601758
+ const currentReplyContext = this.buildTelegramCurrentReplyContext(sessionKey, msg);
601476
601759
  const sections = [
601477
601760
  "## Telegram Conversation Context Stream",
601478
601761
  [
@@ -601480,9 +601763,13 @@ Telegram response contract:
601480
601763
  `Retained messages in bridge memory: ${retainedCount}`,
601481
601764
  olderCount ? `Older retained messages compacted below: ${olderCount}` : "",
601482
601765
  `Current sender: ${currentSpeaker}${msg.fromUserId ? ` (id ${msg.fromUserId})` : ""}`,
601766
+ msg.messageThreadId !== void 0 ? `Current Telegram thread/topic id: ${msg.messageThreadId}` : "",
601483
601767
  msg.replyToMessageId ? `Current message replies to message_id ${msg.replyToMessageId}` : ""
601484
601768
  ].filter(Boolean).join("\n")
601485
601769
  ];
601770
+ if (currentReplyContext) {
601771
+ sections.push(currentReplyContext);
601772
+ }
601486
601773
  const scopedPersonality = this.renderTelegramScopedPersonality(sessionKey, msg);
601487
601774
  if (scopedPersonality) {
601488
601775
  sections.push(scopedPersonality);
@@ -601557,7 +601844,8 @@ ${olderLines.join("\n")}`);
601557
601844
  const when = telegramHistoryTime(entry);
601558
601845
  const speaker = telegramHistorySpeaker(entry);
601559
601846
  const mode = entry.mode ? `/${entry.mode}` : "";
601560
- const reply = entry.replyToMessageId ? ` reply_to:${entry.replyToMessageId}` : "";
601847
+ const replySender = entry.replyContext?.sender ? `/${telegramReplySenderLabel(entry.replyContext.sender)}` : "";
601848
+ const reply = entry.replyToMessageId ? ` reply_to:${entry.replyToMessageId}${replySender}` : "";
601561
601849
  const media = entry.mediaSummary ? ` [${entry.mediaSummary}]` : "";
601562
601850
  const prefix = [when, `${speaker}${mode}${reply}${media}`].filter(Boolean).join(" ");
601563
601851
  return `${prefix}: ${truncateTelegramContextLine(entry.text)}`;
@@ -601593,11 +601881,20 @@ ${lines.join("\n")}`);
601593
601881
  );
601594
601882
  if (mentioned) return true;
601595
601883
  if (msg.replyToUsername && msg.replyToUsername.trim().replace(/^@/, "").toLowerCase() === bot) return true;
601884
+ const replyUsername = msg.replyContext?.sender?.username?.trim().replace(/^@/, "").toLowerCase();
601885
+ if (replyUsername && replyUsername === bot) return true;
601886
+ const resolvedReply = this.resolveTelegramReplyContext(this.sessionKeyForMessage(msg), msg);
601887
+ if (resolvedReply?.sender?.isSelf) return true;
601596
601888
  return false;
601597
601889
  }
601598
601890
  telegramMessageRepliesToBot(msg) {
601599
601891
  const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
601600
- return !!bot && !!msg.replyToUsername && msg.replyToUsername.trim().replace(/^@/, "").toLowerCase() === bot;
601892
+ if (!bot) return false;
601893
+ const legacyReply = msg.replyToUsername?.trim().replace(/^@/, "").toLowerCase();
601894
+ const contextReply = msg.replyContext?.sender?.username?.trim().replace(/^@/, "").toLowerCase();
601895
+ if (legacyReply === bot || contextReply === bot) return true;
601896
+ const resolvedReply = this.resolveTelegramReplyContext(this.sessionKeyForMessage(msg), msg);
601897
+ return Boolean(resolvedReply?.sender?.isSelf);
601601
601898
  }
601602
601899
  applyTelegramStimulationDecision(sessionKey, decision) {
601603
601900
  this.stimulation.applyAgentDecision(sessionKey, {
@@ -601649,6 +601946,7 @@ ${lines.join("\n")}`);
601649
601946
  );
601650
601947
  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.`;
601651
601948
  const context2 = this.buildTelegramConversationContextStream(sessionKey, msg, isGroup ? 36 : 20);
601949
+ const currentReplyContext = this.buildTelegramCurrentReplyContext(sessionKey, msg);
601652
601950
  const userPrompt = [
601653
601951
  `You are the Telegram live routing and reply-discretion model.`,
601654
601952
  `Return JSON only, with no markdown and no explanation outside JSON.`,
@@ -601673,6 +601971,7 @@ ${lines.join("\n")}`);
601673
601971
  `Current sender: ${telegramSpeakerLabel(msg)}`,
601674
601972
  msg.replyToMessageId ? `Current message replies to message_id ${msg.replyToMessageId}` : "",
601675
601973
  msg.replyToUsername ? `Current message replies to @${msg.replyToUsername}` : "",
601974
+ currentReplyContext,
601676
601975
  (msg.mentionedUsernames ?? []).length > 0 ? `Current message mentions: ${(msg.mentionedUsernames ?? []).map((name10) => `@${name10}`).join(", ")}` : "",
601677
601976
  msg.media ? `Current message has media: ${summarizeTelegramMessageAttachments(msg)}` : "",
601678
601977
  ``,
@@ -602065,7 +602364,8 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
602065
602364
  text: initialText,
602066
602365
  parse_mode: "HTML"
602067
602366
  };
602068
- if (replyToMessageId) body["reply_to_message_id"] = replyToMessageId;
602367
+ const replyParameters = telegramReplyParameters(replyToMessageId);
602368
+ if (replyParameters) body["reply_parameters"] = replyParameters;
602069
602369
  const result = await this.apiCall("sendMessage", body);
602070
602370
  this.state.messagesSent++;
602071
602371
  return result.result?.message_id ?? null;
@@ -602075,7 +602375,8 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
602075
602375
  chat_id: chatId,
602076
602376
  text: initialText
602077
602377
  };
602078
- if (replyToMessageId) body["reply_to_message_id"] = replyToMessageId;
602378
+ const replyParameters = telegramReplyParameters(replyToMessageId);
602379
+ if (replyParameters) body["reply_parameters"] = replyParameters;
602079
602380
  const result = await this.apiCall("sendMessage", body);
602080
602381
  this.state.messagesSent++;
602081
602382
  return result.result?.message_id ?? null;
@@ -602118,7 +602419,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
602118
602419
  }
602119
602420
  async sendOrEditFinalTelegramHTML(msg, html, liveMessageId) {
602120
602421
  const chunks = splitTelegramMessageText(html, 3900);
602121
- if (chunks.length === 0) return;
602422
+ if (chunks.length === 0) return null;
602122
602423
  const replyToMessageId = msg.chatType !== "private" ? msg.messageId : void 0;
602123
602424
  if (liveMessageId && !msg.guestQueryId) {
602124
602425
  const edited = await this.editLiveMessage(msg.chatId, liveMessageId, chunks[0]);
@@ -602126,16 +602427,19 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
602126
602427
  for (const chunk of chunks.slice(1)) {
602127
602428
  await this.sendMessageHTML(msg.chatId, chunk);
602128
602429
  }
602129
- return;
602430
+ return liveMessageId;
602130
602431
  }
602131
602432
  }
602132
602433
  if (msg.guestQueryId) {
602133
602434
  await this.answerGuestQuery(msg.guestQueryId, chunks.join("\n\n"), { parseMode: "HTML" });
602134
- return;
602435
+ return null;
602135
602436
  }
602437
+ let firstMessageId = null;
602136
602438
  for (let idx = 0; idx < chunks.length; idx++) {
602137
- await this.sendMessageHTML(msg.chatId, chunks[idx], idx === 0 ? replyToMessageId : void 0);
602439
+ const messageId = await this.sendMessageHTML(msg.chatId, chunks[idx], idx === 0 ? replyToMessageId : void 0);
602440
+ if (firstMessageId === null) firstMessageId = messageId;
602138
602441
  }
602442
+ return firstMessageId;
602139
602443
  }
602140
602444
  async deleteLiveMessage(chatId, messageId) {
602141
602445
  try {
@@ -602267,16 +602571,16 @@ Join: ${newUrl}`);
602267
602571
  return;
602268
602572
  }
602269
602573
  }
602270
- let steeringText = msg.text;
602574
+ let mediaContext = "";
602271
602575
  if (msg.media || msg.replyToMedia) {
602272
- const mediaContext = await this.processMediaContextForMessage(msg);
602273
- if (mediaContext) {
602274
- steeringText += `
602275
-
602276
- [Media attached — processed content below]
602277
- ${mediaContext}`;
602278
- }
602576
+ mediaContext = await this.processMediaContextForMessage(msg);
602279
602577
  }
602578
+ const steeringText = this.formatTelegramCurrentMessageForPrompt(
602579
+ sessionKey,
602580
+ msg,
602581
+ `Telegram steering message from @${msg.username}`,
602582
+ mediaContext
602583
+ );
602280
602584
  if (isGroup) {
602281
602585
  this.markLastTelegramUserMessageMode(msg, "steering");
602282
602586
  } else {
@@ -602337,11 +602641,18 @@ ${mediaContext}`;
602337
602641
  `✈ @${msg.username || "telegram"}`,
602338
602642
  `Telegram ${toolContext} message: ${msg.text.slice(0, 160)}`
602339
602643
  );
602644
+ const replyEdge = this.formatTelegramReplyEdgeForTui(sessionKey, msg);
602645
+ if (replyEdge) {
602646
+ this.subAgentViewCallbacks?.onWrite(subAgent.viewId, replyEdge);
602647
+ }
602340
602648
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `✈ Telegram message from @${msg.username}: ${msg.text}`);
602341
602649
  if (this.canUseChatActions(msg)) {
602342
602650
  subAgent.typingInterval = this.startTypingIndicator(msg.chatId);
602343
602651
  }
602344
602652
  this.tuiWrite(() => renderTelegramSubAgentStart(msg.username, msg.text, isAdminDM));
602653
+ if (replyEdge) {
602654
+ this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, replyEdge));
602655
+ }
602345
602656
  try {
602346
602657
  let mediaContext = "";
602347
602658
  if (msg.media || msg.replyToMedia) {
@@ -602371,9 +602682,12 @@ ${mediaContext}`;
602371
602682
  await subAgent.liveMessagePromise.catch(() => {
602372
602683
  });
602373
602684
  }
602374
- this.recordTelegramAssistantMessage(msg, finalText, "action");
602375
602685
  const finalHtml = convertMarkdownToTelegramHTML(finalText);
602376
- await this.sendOrEditFinalTelegramHTML(msg, finalHtml, subAgent.liveMessageId);
602686
+ const sentMessageId = await this.sendOrEditFinalTelegramHTML(msg, finalHtml, subAgent.liveMessageId);
602687
+ this.recordTelegramAssistantMessage(msg, finalText, "action", {
602688
+ messageId: sentMessageId,
602689
+ replyToMessageId: msg.chatType !== "private" ? msg.messageId : void 0
602690
+ });
602377
602691
  await this.sendGeneratedArtifactsFromSubAgent(
602378
602692
  msg,
602379
602693
  subAgent,
@@ -602439,6 +602753,10 @@ ${mediaContext}`;
602439
602753
  `✈ @${msg.username || "telegram"}`,
602440
602754
  `Telegram admin chat: ${msg.text.slice(0, 160)}`
602441
602755
  );
602756
+ const replyEdge = this.formatTelegramReplyEdgeForTui(sessionKey, msg);
602757
+ if (replyEdge) {
602758
+ this.subAgentViewCallbacks?.onWrite(subAgent.viewId, replyEdge);
602759
+ }
602442
602760
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `✈ Telegram admin chat from @${msg.username}: ${msg.text}`);
602443
602761
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `route: chat (${this.interactionMode}) with admin tools`);
602444
602762
  this.subAgentViewCallbacks?.onStatus(subAgent.viewId, "running");
@@ -602446,6 +602764,9 @@ ${mediaContext}`;
602446
602764
  subAgent.typingInterval = this.startTypingIndicator(msg.chatId);
602447
602765
  }
602448
602766
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `admin chat with full context/tools (${this.interactionMode})`));
602767
+ if (replyEdge) {
602768
+ this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, replyEdge));
602769
+ }
602449
602770
  try {
602450
602771
  let mediaContext = "";
602451
602772
  if (msg.media || msg.replyToMedia) {
@@ -602470,9 +602791,12 @@ ${mediaContext}`;
602470
602791
  this.subAgentViewCallbacks?.onStatus(subAgent.viewId, "completed");
602471
602792
  return;
602472
602793
  }
602473
- this.recordTelegramAssistantMessage(msg, finalText, "chat");
602474
602794
  const finalHtml = convertMarkdownToTelegramHTML(finalText);
602475
- await this.sendOrEditFinalTelegramHTML(msg, finalHtml, subAgent.liveMessageId);
602795
+ const sentMessageId = await this.sendOrEditFinalTelegramHTML(msg, finalHtml, subAgent.liveMessageId);
602796
+ this.recordTelegramAssistantMessage(msg, finalText, "chat", {
602797
+ messageId: sentMessageId,
602798
+ replyToMessageId: msg.chatType !== "private" ? msg.messageId : void 0
602799
+ });
602476
602800
  await this.sendGeneratedArtifactsFromSubAgent(
602477
602801
  msg,
602478
602802
  subAgent,
@@ -602510,6 +602834,7 @@ ${mediaContext}`;
602510
602834
  return;
602511
602835
  }
602512
602836
  const viewId = `${this.viewIdForMessage(msg)}-chat`;
602837
+ const sessionKey = this.sessionKeyForMessage(msg);
602513
602838
  let typingInterval = null;
602514
602839
  let liveMessageId = null;
602515
602840
  let accumulated = "";
@@ -602524,6 +602849,10 @@ ${mediaContext}`;
602524
602849
  `✈ @${msg.username || "telegram"}`,
602525
602850
  `Telegram quick chat: ${msg.text.slice(0, 160)}`
602526
602851
  );
602852
+ const replyEdge = this.formatTelegramReplyEdgeForTui(sessionKey, msg);
602853
+ if (replyEdge) {
602854
+ this.subAgentViewCallbacks?.onWrite(viewId, replyEdge);
602855
+ }
602527
602856
  this.subAgentViewCallbacks?.onWrite(viewId, `✈ Telegram quick chat from @${msg.username}: ${msg.text}`);
602528
602857
  this.subAgentViewCallbacks?.onWrite(viewId, `route: chat (${this.interactionMode})`);
602529
602858
  this.subAgentViewCallbacks?.onStatus(viewId, "running");
@@ -602592,9 +602921,12 @@ ${mediaContext}`;
602592
602921
  this.subAgentViewCallbacks?.onStatus(viewId, "completed");
602593
602922
  return;
602594
602923
  }
602595
- this.recordTelegramAssistantMessage(msg, cleaned, "chat");
602596
602924
  const finalHtml = convertMarkdownToTelegramHTML(cleaned);
602597
- await this.sendOrEditFinalTelegramHTML(msg, finalHtml, liveMessageId);
602925
+ const sentMessageId = await this.sendOrEditFinalTelegramHTML(msg, finalHtml, liveMessageId);
602926
+ this.recordTelegramAssistantMessage(msg, cleaned, "chat", {
602927
+ messageId: sentMessageId,
602928
+ replyToMessageId: msg.chatType !== "private" ? msg.messageId : void 0
602929
+ });
602598
602930
  this.subAgentViewCallbacks?.onWrite(viewId, `completed: ${cleaned}`);
602599
602931
  this.subAgentViewCallbacks?.onStatus(viewId, "completed");
602600
602932
  } catch (err) {
@@ -602657,12 +602989,15 @@ ${conversationStream}`
602657
602989
  }
602658
602990
  ];
602659
602991
  const chatLabel = isGroup ? ` in group "${msg.chatTitle || "unknown"}"` : "";
602992
+ const currentPrompt = this.formatTelegramCurrentMessageForPrompt(
602993
+ sessionKey,
602994
+ msg,
602995
+ `Telegram message from @${msg.username}${chatLabel}`,
602996
+ mediaContext
602997
+ );
602660
602998
  messages2.push({
602661
602999
  role: "user",
602662
- content: `Telegram message from @${msg.username}${chatLabel}:
602663
- ${msg.text}${mediaContext ? `
602664
-
602665
- ${mediaContext}` : ""}`
603000
+ content: currentPrompt
602666
603001
  });
602667
603002
  return messages2;
602668
603003
  }
@@ -602869,6 +603204,11 @@ ${mediaContext}` : ""}`
602869
603204
 
602870
603205
  ${GROUP_REPLY_DISCRETION_PROMPT}` : "";
602871
603206
  const chatLabel = isGroup ? ` in group "${msg.chatTitle || "unknown"}"` : "";
603207
+ const currentTelegramPrompt = this.formatTelegramCurrentMessageForPrompt(
603208
+ sessionContext.sessionKey,
603209
+ msg,
603210
+ `${isAdminDM ? "Telegram message from admin" : "Telegram message from"} @${msg.username}${isAdminDM ? "" : chatLabel}`
603211
+ );
602872
603212
  let userPrompt;
602873
603213
  if (isAdminDM) {
602874
603214
  const profileLine = profile === "chat" ? "Handle this as contextual Telegram chat: answer directly if simple, use tools/delegation if needed." : "Handle this as Telegram action work: complete the requested task or clearly report the blocker.";
@@ -602880,8 +603220,7 @@ ${reminderToolContract}
602880
603220
 
602881
603221
  ${profileLine}
602882
603222
 
602883
- Telegram message from admin @${msg.username}:
602884
- ${msg.text}`;
603223
+ ${currentTelegramPrompt}`;
602885
603224
  } else {
602886
603225
  const toolHint = [
602887
603226
  "You have access to isolated per-chat memory (memory_write, memory_read, memory_search) scoped to this conversation.",
@@ -602898,8 +603237,7 @@ ${toolHint}
602898
603237
 
602899
603238
  ---
602900
603239
 
602901
- Telegram message from @${msg.username}${chatLabel}:
602902
- ${msg.text}
603240
+ ${currentTelegramPrompt}
602903
603241
 
602904
603242
  Respond concisely and safely. Send the actual chat reply, not router/status/completion commentary.`;
602905
603243
  }
@@ -603888,12 +604226,12 @@ ${text}`.trim());
603888
604226
  }
603889
604227
  // ── Message sending ───────────────────────────────────────────────────
603890
604228
  /** Send a response back to a Telegram chat (Markdown → HTML conversion) */
603891
- async sendMessage(chatId, text) {
604229
+ async sendMessage(chatId, text, replyToMessageId) {
603892
604230
  const extracted = extractMediaReferences(text);
603893
604231
  const html = convertMarkdownToTelegramHTML(extracted.text);
603894
- const msgId = extracted.text.trim() ? await this.sendMessageHTML(chatId, html) : null;
604232
+ const msgId = extracted.text.trim() ? await this.sendMessageHTML(chatId, html, replyToMessageId) : null;
603895
604233
  for (const media of extracted.media) {
603896
- await this.sendMediaReference(chatId, media).catch(() => null);
604234
+ await this.sendMediaReference(chatId, media, { replyToMessageId }).catch(() => null);
603897
604235
  }
603898
604236
  return msgId;
603899
604237
  }
@@ -603903,8 +604241,13 @@ ${text}`.trim());
603903
604241
  const sendHtml = extracted.text || (extracted.media.length > 0 ? "" : html);
603904
604242
  let sentId = null;
603905
604243
  if (!sendHtml.trim()) {
603906
- for (const media of extracted.media) {
603907
- const mediaId = await this.sendMediaReference(chatId, media).catch(() => null);
604244
+ for (let idx = 0; idx < extracted.media.length; idx++) {
604245
+ const media = extracted.media[idx];
604246
+ const mediaId = await this.sendMediaReference(
604247
+ chatId,
604248
+ media,
604249
+ idx === 0 ? { replyToMessageId } : {}
604250
+ ).catch(() => null);
603908
604251
  if (sentId === null) sentId = mediaId;
603909
604252
  }
603910
604253
  return sentId;
@@ -603917,7 +604260,8 @@ ${text}`.trim());
603917
604260
  text: chunk,
603918
604261
  parse_mode: "HTML"
603919
604262
  };
603920
- if (idx === 0 && replyToMessageId) body["reply_to_message_id"] = replyToMessageId;
604263
+ const replyParameters = idx === 0 ? telegramReplyParameters(replyToMessageId) : void 0;
604264
+ if (replyParameters) body["reply_parameters"] = replyParameters;
603921
604265
  try {
603922
604266
  const result = await this.apiCall("sendMessage", body);
603923
604267
  if (result.ok === false) throw new Error(String(result.description || "Telegram sendMessage failed"));
@@ -603926,7 +604270,7 @@ ${text}`.trim());
603926
604270
  } catch {
603927
604271
  const plain = chunk.replace(/<[^>]+>/g, "");
603928
604272
  const fallbackBody = { chat_id: chatId, text: plain };
603929
- if (idx === 0 && replyToMessageId) fallbackBody["reply_to_message_id"] = replyToMessageId;
604273
+ if (replyParameters) fallbackBody["reply_parameters"] = replyParameters;
603930
604274
  try {
603931
604275
  const result = await this.apiCall("sendMessage", fallbackBody);
603932
604276
  if (result.ok === false) throw new Error(String(result.description || "Telegram sendMessage failed"));
@@ -603948,7 +604292,7 @@ ${text}`.trim());
603948
604292
  parseMode: options2.html ? "HTML" : void 0
603949
604293
  });
603950
604294
  }
603951
- return options2.html ? this.sendMessageHTML(msg.chatId, text, options2.replyToMessageId) : this.sendMessage(msg.chatId, text);
604295
+ return options2.html ? this.sendMessageHTML(msg.chatId, text, options2.replyToMessageId) : this.sendMessage(msg.chatId, text, options2.replyToMessageId);
603952
604296
  }
603953
604297
  async sendTelegramFileToChat(chatId, path11, options2) {
603954
604298
  const abs = resolve40(path11);
@@ -603973,12 +604317,13 @@ ${text}`.trim());
603973
604317
  async sendMediaReferenceStrict(chatId, media, options2 = {}) {
603974
604318
  const { method, field } = mediaTelegramMethod(media.kind);
603975
604319
  const caption = options2.caption?.trim();
604320
+ const replyParameters = telegramReplyParameters(options2.replyToMessageId);
603976
604321
  if (media.source === "url") {
603977
604322
  const result2 = await this.apiCall(method, {
603978
604323
  chat_id: chatId,
603979
604324
  [field]: media.value,
603980
604325
  ...caption ? { caption } : {},
603981
- ...options2.replyToMessageId ? { reply_to_message_id: options2.replyToMessageId } : {}
604326
+ ...replyParameters ? { reply_parameters: replyParameters } : {}
603982
604327
  });
603983
604328
  if (result2.ok === false) throw new Error(String(result2.description || `Telegram ${method} failed`));
603984
604329
  this.state.messagesSent++;
@@ -604001,7 +604346,7 @@ ${text}`.trim());
604001
604346
  };
604002
604347
  addField("chat_id", String(chatId));
604003
604348
  if (caption) addField("caption", caption);
604004
- if (options2.replyToMessageId) addField("reply_to_message_id", String(options2.replyToMessageId));
604349
+ if (replyParameters) addField("reply_parameters", JSON.stringify(replyParameters));
604005
604350
  parts.push(Buffer.from(`--${boundary}\r
604006
604351
  `));
604007
604352
  parts.push(Buffer.from(
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.33",
3
+ "version": "1.0.34",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.33",
9
+ "version": "1.0.34",
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.33",
3
+ "version": "1.0.34",
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",