omnius 1.0.130 → 1.0.132

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
@@ -564387,6 +564387,7 @@ var init_command_registry = __esm({
564387
564387
  ["/telegram status", "Show Telegram bridge status"],
564388
564388
  ["/telegram stop", "Disconnect Telegram bridge"],
564389
564389
  ["/telegram mode auto|chat|action", "Set Telegram interaction routing: auto, fast chat, or action sub-agent"],
564390
+ ["/telegram subagents <1-5>", "Set global Telegram work-slot limit across all chats/groups"],
564390
564391
  ["/telegram auth", "Show a TUI-only one-time code for Telegram admin authentication"],
564391
564392
  ["/telegram auth cancel", "Cancel the pending Telegram admin authentication code"],
564392
564393
  ["/telegram bot <username> <text>", "Send a Bot API bot-to-bot message by @username"],
@@ -597970,6 +597971,31 @@ sleep 1
597970
597971
  renderInfo(`Telegram interaction mode set to ${c3.bold(requested)}${wantsLocalMode ? " (project)" : " (global)"}.`);
597971
597972
  return "handled";
597972
597973
  }
597974
+ if (parts[0] === "subagents" || parts[0] === "sub-agents" || parts[0] === "agents") {
597975
+ const requested = parts.slice(1).find((part) => !part.startsWith("--"));
597976
+ if (!requested) {
597977
+ const settings = ctx3.getTelegramSettings?.() ?? {};
597978
+ renderInfo(`Telegram sub-agent slots: ${c3.bold(String(settings.subAgents ?? 2))} global max (cap 5).`);
597979
+ renderInfo("Use /telegram subagents 1, /telegram subagents 2, ... up to 5.");
597980
+ return "handled";
597981
+ }
597982
+ const parsed = Number(requested);
597983
+ if (!Number.isFinite(parsed) || parsed < 1) {
597984
+ renderWarning("Usage: /telegram subagents <1-5> [--global]");
597985
+ return "handled";
597986
+ }
597987
+ const limit = Math.max(1, Math.min(5, Math.floor(parsed)));
597988
+ const hasGlobalFlagSubAgents = parts.includes("--global");
597989
+ const projectRootSubAgents = ctx3.repoRoot || process.cwd();
597990
+ const projectHasOmniusSubAgents = existsSync104(join117(projectRootSubAgents, ".omnius"));
597991
+ const wantsLocalSubAgents = hasGlobalFlagSubAgents ? false : isLocal || projectHasOmniusSubAgents;
597992
+ ctx3.saveTelegramSettings?.({ subAgents: limit, local: wantsLocalSubAgents });
597993
+ const activeLimit = ctx3.telegramSetSubAgentLimit?.(limit) ?? limit;
597994
+ renderInfo(
597995
+ `Telegram sub-agent slots set to ${c3.bold(String(activeLimit))} global max${parsed > 5 ? " (requested value capped at 5)" : ""}${wantsLocalSubAgents ? " (project)" : " (global)"}.`
597996
+ );
597997
+ return "handled";
597998
+ }
597973
597999
  if (parts[0] === "auth" || parts[0] === "authenticate") {
597974
598000
  if (parts[1] === "cancel") {
597975
598001
  const cancelled = ctx3.telegramCancelAdminAuth?.() ?? false;
@@ -598339,6 +598365,7 @@ sleep 1
598339
598365
  renderInfo(" /telegram stop Stop bridge");
598340
598366
  renderInfo(" /telegram status Show status");
598341
598367
  renderInfo(" /telegram mode auto|chat|action Set interaction routing profile");
598368
+ renderInfo(" /telegram subagents <1-5> Set global Telegram work-slot limit");
598342
598369
  renderInfo(" /telegram auth Show one-time admin auth code");
598343
598370
  renderInfo(" /telegram auth cancel Cancel pending admin auth code");
598344
598371
  renderInfo(" /telegram bot <username> <text> Send bot-to-bot message");
@@ -616665,6 +616692,11 @@ function buildTelegramRuntimeContext(now = /* @__PURE__ */ new Date(), repoRoot)
616665
616692
  function telegramSessionIdFromKey(sessionKey) {
616666
616693
  return `telegram-${createHash25("sha1").update(sessionKey).digest("hex").slice(0, 16)}`;
616667
616694
  }
616695
+ function normalizeTelegramSubAgentLimit(value2) {
616696
+ const parsed = typeof value2 === "number" ? value2 : typeof value2 === "string" && value2.trim() ? Number(value2.trim()) : TELEGRAM_SUB_AGENT_DEFAULT_LIMIT;
616697
+ if (!Number.isFinite(parsed)) return TELEGRAM_SUB_AGENT_DEFAULT_LIMIT;
616698
+ return Math.max(1, Math.min(TELEGRAM_SUB_AGENT_MAX_LIMIT, Math.floor(parsed)));
616699
+ }
616668
616700
  function selectTelegramFinalResponse(args) {
616669
616701
  const committedVisibleReply = cleanTelegramVisibleReply(args.visibleReplyText || "");
616670
616702
  if (committedVisibleReply) return committedVisibleReply;
@@ -617361,11 +617393,13 @@ function normalizeTelegramSendKind(rawKind, path12) {
617361
617393
  }
617362
617394
  return classifyMedia(path12) ?? "document";
617363
617395
  }
617364
- function renderTelegramStart(botUsername, adminId, mode = "auto", canReadAllGroupMessages) {
617396
+ function renderTelegramStart(botUsername, adminId, mode = "auto", canReadAllGroupMessages, maxSubAgents = TELEGRAM_SUB_AGENT_DEFAULT_LIMIT) {
617365
617397
  process.stdout.write(`
617366
617398
  ${c3.cyan("✈")} ${c3.bold("Telegram Bridge")} connected as @${botUsername}
617367
617399
  `);
617368
617400
  process.stdout.write(` ${c3.dim(`Interaction mode: ${mode}`)}
617401
+ `);
617402
+ process.stdout.write(` ${c3.dim(`Telegram work slots: ${maxSubAgents} global max (use /telegram subagents 1-${TELEGRAM_SUB_AGENT_MAX_LIMIT})`)}
617369
617403
  `);
617370
617404
  process.stdout.write(` ${c3.dim("Auto mode uses quick chat for conversational turns and sub-agents for action requests")}
617371
617405
  `);
@@ -617390,12 +617424,14 @@ function renderTelegramStart(botUsername, adminId, mode = "auto", canReadAllGrou
617390
617424
 
617391
617425
  `);
617392
617426
  }
617393
- function renderTelegramStatus(active, botUsername, adminId, activeSubAgents, mode = "auto", canReadAllGroupMessages) {
617427
+ function renderTelegramStatus(active, botUsername, adminId, activeSubAgents, mode = "auto", canReadAllGroupMessages, maxSubAgents = TELEGRAM_SUB_AGENT_DEFAULT_LIMIT, queuedSubAgentSessions = 0) {
617394
617428
  if (active) {
617395
617429
  process.stdout.write(`
617396
617430
  ${c3.green("●")} Telegram bridge: ${c3.bold("active")} (@${botUsername ?? "?"})
617397
617431
  `);
617398
617432
  process.stdout.write(` Mode: ${mode}
617433
+ `);
617434
+ process.stdout.write(` Telegram work slots: ${activeSubAgents ?? 0}/${maxSubAgents} active${queuedSubAgentSessions > 0 ? `, ${queuedSubAgentSessions} queued` : ""}
617399
617435
  `);
617400
617436
  process.stdout.write(` Group ingest: ${canReadAllGroupMessages ? "all delivered group messages" : "privacy-limited by Telegram/BotFather"}
617401
617437
  `);
@@ -617471,7 +617507,7 @@ function renderTelegramSubAgentError(username, error) {
617471
617507
  process.stdout.write(` ${c3.dim("│")} ${c3.magenta("✘")} @${username}: ${c3.dim(preview)}
617472
617508
  `);
617473
617509
  }
617474
- var TELEGRAM_TOOL_ACTION_GROUPS, TELEGRAM_TOOL_ACTION_GROUP, TELEGRAM_TOOL_MUTATING_GROUPS, DEFAULT_TELEGRAM_TOOL_GROUP_POLICY, TELEGRAM_TOOL_BUTTON_LABELS, TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, TELEGRAM_PUBLIC_VISION_STACK_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT, TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT, TELEGRAM_STUCK_SELF_TALK_PREFIXES, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_ASSOCIATIVE_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_USER_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_ACTION_LIMIT, TELEGRAM_ASSOCIATIVE_RELATION_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_MEMORY_GENERIC_QUERY_TOKENS, TELEGRAM_SUB_AGENT_BOUNDED_OPTIONS, TELEGRAM_PUBLIC_HELP_COMMANDS2, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_PUBLIC_BOT_COMMAND_NAMES, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TELEGRAM_ALLOWED_UPDATES, TELEGRAM_PUBLIC_TOOL_QUOTAS, TelegramBridge;
617510
+ var TELEGRAM_TOOL_ACTION_GROUPS, TELEGRAM_TOOL_ACTION_GROUP, TELEGRAM_TOOL_MUTATING_GROUPS, DEFAULT_TELEGRAM_TOOL_GROUP_POLICY, TELEGRAM_TOOL_BUTTON_LABELS, TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, TELEGRAM_PUBLIC_VISION_STACK_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT, TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT, TELEGRAM_STUCK_SELF_TALK_PREFIXES, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_ASSOCIATIVE_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_USER_FACT_LIMIT, TELEGRAM_ASSOCIATIVE_ACTION_LIMIT, TELEGRAM_ASSOCIATIVE_RELATION_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_MEMORY_GENERIC_QUERY_TOKENS, TELEGRAM_SUB_AGENT_BOUNDED_OPTIONS, TELEGRAM_SUB_AGENT_DEFAULT_LIMIT, TELEGRAM_SUB_AGENT_MAX_LIMIT, TELEGRAM_PUBLIC_HELP_COMMANDS2, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_PUBLIC_BOT_COMMAND_NAMES, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TELEGRAM_ALLOWED_UPDATES, TELEGRAM_PUBLIC_TOOL_QUOTAS, TelegramBridge;
617475
617511
  var init_telegram_bridge = __esm({
617476
617512
  "packages/cli/src/tui/telegram-bridge.ts"() {
617477
617513
  "use strict";
@@ -617850,6 +617886,8 @@ External acquisition contract:
617850
617886
  bruteForceMaxCycles: 0,
617851
617887
  allowTurnExtension: false
617852
617888
  };
617889
+ TELEGRAM_SUB_AGENT_DEFAULT_LIMIT = 2;
617890
+ TELEGRAM_SUB_AGENT_MAX_LIMIT = 5;
617853
617891
  TELEGRAM_PUBLIC_HELP_COMMANDS2 = /* @__PURE__ */ new Set(["help", "start", "auth", "call"]);
617854
617892
  TELEGRAM_REMINDER_SLASH_COMMANDS = /* @__PURE__ */ new Set(["remind", "reminder", "reminders"]);
617855
617893
  TELEGRAM_REFLECTION_SLASH_COMMANDS = /* @__PURE__ */ new Set(["reflect", "reflection", "daydream", "dream"]);
@@ -617884,6 +617922,7 @@ External acquisition contract:
617884
617922
  this.telegramConversationDir = resolve45(repoRoot || ".", ".omnius", "telegram-conversations");
617885
617923
  this.telegramSqlitePath = resolve45(repoRoot || ".", ".omnius", "telegram.sqlite");
617886
617924
  this.telegramToolButtonDir = resolve45(repoRoot || ".", ".omnius", "telegram-tool-buttons");
617925
+ this.state.maxSubAgents = normalizeTelegramSubAgentLimit(resolveSettings(repoRoot || ".").telegramSubAgents);
617887
617926
  this.hydrateTelegramCommandMap(buildTelegramBotCommands({ scope: "admin" }));
617888
617927
  }
617889
617928
  botToken;
@@ -617906,14 +617945,28 @@ External acquisition contract:
617906
617945
  startedAt: "",
617907
617946
  messagesReceived: 0,
617908
617947
  messagesSent: 0,
617909
- activeSubAgents: 0
617948
+ activeSubAgents: 0,
617949
+ maxSubAgents: TELEGRAM_SUB_AGENT_DEFAULT_LIMIT,
617950
+ queuedSubAgentSessions: 0
617910
617951
  };
617911
617952
  /** Admin user ID — if set, messages from this user get full memory access */
617912
617953
  adminUserId = null;
617913
617954
  /** Active sub-agents by chat/guest session key */
617914
617955
  subAgents = /* @__PURE__ */ new Map();
617956
+ /** Debounced live-context packets for messages arriving during a runner. */
617957
+ telegramSubAgentContextBuffers = /* @__PURE__ */ new Map();
617915
617958
  /** Active direct chat completions, counted with Telegram activity in the TUI */
617916
617959
  activeChatViews = /* @__PURE__ */ new Set();
617960
+ /**
617961
+ * Global Telegram work admission. This is intentionally broader than
617962
+ * this.subAgents: router inference, fast-chat completions, and action
617963
+ * runners all consume a slot because all of them can block local model
617964
+ * capacity and flood the TUI.
617965
+ */
617966
+ telegramActiveWorkSessions = /* @__PURE__ */ new Set();
617967
+ /** Queued Telegram sessions waiting for a global work slot. */
617968
+ telegramQueuedSessionWork = /* @__PURE__ */ new Map();
617969
+ telegramDispatchQueuedTimer = null;
617917
617970
  /** Lightweight chat history by chat/guest session key */
617918
617971
  chatHistory = /* @__PURE__ */ new Map();
617919
617972
  /** Participant and tone state by chat/guest session key */
@@ -617963,7 +618016,7 @@ External acquisition contract:
617963
618016
  * Live telemetry of every in-flight Ollama call originating from the
617964
618017
  * bridge. Lets the operator see WHY multiple GPUs are spun up at once
617965
618018
  * and HOW each call is progressing — which is the only way to debug a
617966
- * 180s hard-deadline firing event without grepping logs.
618019
+ * router hard-deadline firing event without grepping logs.
617967
618020
  *
617968
618021
  * Each entry tracks:
617969
618022
  * - kind: router | chat-fast-path | followup | sub-agent
@@ -618017,6 +618070,7 @@ External acquisition contract:
618017
618070
  ]);
618018
618071
  /** TUI agent-view callbacks for Telegram sub-agent registration. */
618019
618072
  subAgentViewCallbacks = null;
618073
+ rawSubAgentViewCallbacks = null;
618020
618074
  /** Callback to get active call session URL (wired from interactive.ts) */
618021
618075
  callUrlGetter = null;
618022
618076
  /** Callback to start a call session and return the URL (wired from interactive.ts) */
@@ -618027,6 +618081,10 @@ External acquisition contract:
618027
618081
  callStartInProgress = false;
618028
618082
  /** Callback to write content into the scrollable TUI waterfall area (wired from interactive.ts) */
618029
618083
  writeContent = null;
618084
+ pendingTuiWrites = [];
618085
+ pendingTuiWriteTimer = null;
618086
+ pendingSubAgentViewWrites = /* @__PURE__ */ new Map();
618087
+ pendingSubAgentViewWriteTimer = null;
618030
618088
  /** Media cache — fileUniqueId → cache entry */
618031
618089
  mediaCache = /* @__PURE__ */ new Map();
618032
618090
  /** Media cache directory */
@@ -618074,6 +618132,15 @@ External acquisition contract:
618074
618132
  getInteractionMode() {
618075
618133
  return this.interactionMode;
618076
618134
  }
618135
+ setSubAgentLimit(limit) {
618136
+ const normalized = normalizeTelegramSubAgentLimit(limit);
618137
+ this.state.maxSubAgents = normalized;
618138
+ this.dispatchQueuedTelegramSessionWorkSoon();
618139
+ return normalized;
618140
+ }
618141
+ getSubAgentLimit() {
618142
+ return normalizeTelegramSubAgentLimit(this.state.maxSubAgents);
618143
+ }
618077
618144
  setContextWindowSize(size) {
618078
618145
  this.contextWindowSize = Number.isFinite(size) && size > 0 ? Math.trunc(size) : 0;
618079
618146
  }
@@ -618104,7 +618171,19 @@ External acquisition contract:
618104
618171
  this.adminAuthHandler = handler;
618105
618172
  }
618106
618173
  setSubAgentViewCallbacks(callbacks) {
618107
- this.subAgentViewCallbacks = callbacks;
618174
+ this.rawSubAgentViewCallbacks = callbacks;
618175
+ this.subAgentViewCallbacks = {
618176
+ onRegister: (...args) => callbacks.onRegister(...args),
618177
+ onWrite: (id, text) => this.telegramViewWrite(id, text),
618178
+ onStatus: (...args) => {
618179
+ this.flushTelegramViewWrites();
618180
+ callbacks.onStatus(...args);
618181
+ },
618182
+ onComplete: (...args) => {
618183
+ this.flushTelegramViewWrites();
618184
+ callbacks.onComplete(...args);
618185
+ }
618186
+ };
618108
618187
  }
618109
618188
  /** Register callback to get active call URL for /call button forwarding */
618110
618189
  setCallUrlGetter(getter) {
@@ -618130,7 +618209,12 @@ External acquisition contract:
618130
618209
  return this.polling;
618131
618210
  }
618132
618211
  get stats() {
618133
- return { ...this.state, activeSubAgents: this.activeTelegramInteractionCount() };
618212
+ return {
618213
+ ...this.state,
618214
+ activeSubAgents: this.activeTelegramInteractionCount(),
618215
+ maxSubAgents: this.getSubAgentLimit(),
618216
+ queuedSubAgentSessions: this.telegramQueuedSessionWork.size
618217
+ };
618134
618218
  }
618135
618219
  get botUsername() {
618136
618220
  return this.state.botUsername;
@@ -618412,10 +618496,61 @@ No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code
618412
618496
  }
618413
618497
  /** Write to the scrollable TUI waterfall area (respects status bar scroll region) */
618414
618498
  tuiWrite(fn) {
618499
+ this.pendingTuiWrites.push(fn);
618500
+ if (this.pendingTuiWriteTimer) return;
618501
+ this.pendingTuiWriteTimer = setTimeout(() => this.flushTelegramTuiWrites(), 0);
618502
+ if (typeof this.pendingTuiWriteTimer.unref === "function") {
618503
+ this.pendingTuiWriteTimer.unref();
618504
+ }
618505
+ }
618506
+ flushTelegramTuiWrites() {
618507
+ if (this.pendingTuiWriteTimer) {
618508
+ clearTimeout(this.pendingTuiWriteTimer);
618509
+ this.pendingTuiWriteTimer = null;
618510
+ }
618511
+ const batch2 = this.pendingTuiWrites.splice(0);
618512
+ if (batch2.length === 0) return;
618513
+ const runBatch = () => {
618514
+ for (const fn of batch2) {
618515
+ try {
618516
+ fn();
618517
+ } catch {
618518
+ }
618519
+ }
618520
+ };
618415
618521
  if (this.writeContent) {
618416
- this.writeContent(fn);
618522
+ this.writeContent(runBatch);
618417
618523
  } else {
618418
- fn();
618524
+ runBatch();
618525
+ }
618526
+ }
618527
+ telegramViewWrite(id, text) {
618528
+ const callbacks = this.rawSubAgentViewCallbacks;
618529
+ if (!callbacks) return;
618530
+ const queue = this.pendingSubAgentViewWrites.get(id) ?? [];
618531
+ queue.push(text);
618532
+ this.pendingSubAgentViewWrites.set(id, queue);
618533
+ if (this.pendingSubAgentViewWriteTimer) return;
618534
+ this.pendingSubAgentViewWriteTimer = setTimeout(() => this.flushTelegramViewWrites(), 100);
618535
+ if (typeof this.pendingSubAgentViewWriteTimer.unref === "function") {
618536
+ this.pendingSubAgentViewWriteTimer.unref();
618537
+ }
618538
+ }
618539
+ flushTelegramViewWrites() {
618540
+ if (this.pendingSubAgentViewWriteTimer) {
618541
+ clearTimeout(this.pendingSubAgentViewWriteTimer);
618542
+ this.pendingSubAgentViewWriteTimer = null;
618543
+ }
618544
+ const callbacks = this.rawSubAgentViewCallbacks;
618545
+ if (!callbacks || this.pendingSubAgentViewWrites.size === 0) {
618546
+ this.pendingSubAgentViewWrites.clear();
618547
+ return;
618548
+ }
618549
+ const batch2 = this.pendingSubAgentViewWrites;
618550
+ this.pendingSubAgentViewWrites = /* @__PURE__ */ new Map();
618551
+ for (const [id, lines] of batch2) {
618552
+ if (lines.length === 0) continue;
618553
+ callbacks.onWrite(id, lines.join("\n"));
618419
618554
  }
618420
618555
  }
618421
618556
  sessionKeyForMessage(msg) {
@@ -618423,14 +618558,198 @@ No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code
618423
618558
  return `chat:${String(msg.chatId)}`;
618424
618559
  }
618425
618560
  activeTelegramInteractionCount() {
618426
- return this.subAgents.size + this.activeChatViews.size;
618561
+ return Math.max(
618562
+ this.telegramActiveWorkSessions.size,
618563
+ this.subAgents.size + this.activeChatViews.size
618564
+ );
618427
618565
  }
618428
618566
  refreshActiveTelegramInteractionCount() {
618429
618567
  this.state.activeSubAgents = this.activeTelegramInteractionCount();
618568
+ this.state.maxSubAgents = this.getSubAgentLimit();
618569
+ this.state.queuedSubAgentSessions = this.telegramQueuedSessionWork.size;
618570
+ }
618571
+ telegramWorkCapacityAvailable() {
618572
+ return this.telegramActiveWorkSessions.size < this.getSubAgentLimit();
618573
+ }
618574
+ dispatchQueuedTelegramSessionWorkSoon() {
618575
+ if (this.telegramDispatchQueuedTimer) return;
618576
+ this.telegramDispatchQueuedTimer = setTimeout(() => this.dispatchQueuedTelegramSessionWork(), 0);
618577
+ if (typeof this.telegramDispatchQueuedTimer.unref === "function") {
618578
+ this.telegramDispatchQueuedTimer.unref();
618579
+ }
618580
+ }
618581
+ dispatchQueuedTelegramSessionWork() {
618582
+ if (this.telegramDispatchQueuedTimer) {
618583
+ clearTimeout(this.telegramDispatchQueuedTimer);
618584
+ this.telegramDispatchQueuedTimer = null;
618585
+ }
618586
+ while (this.telegramWorkCapacityAvailable()) {
618587
+ const next = [...this.telegramQueuedSessionWork.values()].filter((work) => !this.telegramActiveWorkSessions.has(work.sessionKey)).sort((a2, b) => a2.lastSpokenAtMs - b.lastSpokenAtMs || a2.enqueuedAtMs - b.enqueuedAtMs)[0];
618588
+ if (!next) break;
618589
+ this.telegramQueuedSessionWork.delete(next.sessionKey);
618590
+ this.startTelegramSessionWork(next);
618591
+ }
618592
+ this.refreshActiveTelegramInteractionCount();
618593
+ }
618594
+ scheduleTelegramSessionWork(msg, toolContext) {
618595
+ const sessionKey = this.sessionKeyForMessage(msg);
618596
+ const now = Date.now();
618597
+ const existing = this.telegramQueuedSessionWork.get(sessionKey);
618598
+ if (this.telegramWorkCapacityAvailable() && !this.telegramActiveWorkSessions.has(sessionKey)) {
618599
+ if (existing) this.telegramQueuedSessionWork.delete(sessionKey);
618600
+ this.startTelegramSessionWork({
618601
+ sessionKey,
618602
+ msg,
618603
+ toolContext,
618604
+ enqueuedAtMs: existing?.enqueuedAtMs ?? now,
618605
+ lastSpokenAtMs: now,
618606
+ messageCount: (existing?.messageCount ?? 0) + 1
618607
+ });
618608
+ return;
618609
+ }
618610
+ this.telegramQueuedSessionWork.set(sessionKey, {
618611
+ sessionKey,
618612
+ msg,
618613
+ toolContext,
618614
+ enqueuedAtMs: existing?.enqueuedAtMs ?? now,
618615
+ lastSpokenAtMs: now,
618616
+ messageCount: (existing?.messageCount ?? 0) + 1
618617
+ });
618618
+ this.refreshActiveTelegramInteractionCount();
618619
+ this.tuiWrite(() => renderTelegramSubAgentEvent(
618620
+ msg.username,
618621
+ `queued Telegram work for ${msg.chatTitle || msg.chatType}; active ${this.telegramActiveWorkSessions.size}/${this.getSubAgentLimit()}, queued ${this.telegramQueuedSessionWork.size}`
618622
+ ));
618623
+ }
618624
+ startTelegramSessionWork(work) {
618625
+ this.telegramActiveWorkSessions.add(work.sessionKey);
618626
+ this.refreshActiveTelegramInteractionCount();
618627
+ void this.processTelegramMessageWork(work.msg, work.toolContext).catch((err) => {
618628
+ this.tuiWrite(() => renderWarning(`Telegram sub-agent error: ${err instanceof Error ? err.message : String(err)}`));
618629
+ }).finally(() => {
618630
+ this.telegramActiveWorkSessions.delete(work.sessionKey);
618631
+ this.refreshActiveTelegramInteractionCount();
618632
+ this.dispatchQueuedTelegramSessionWorkSoon();
618633
+ });
618634
+ }
618635
+ takeQueuedTelegramSessionWork(sessionKey) {
618636
+ const queued = this.telegramQueuedSessionWork.get(sessionKey);
618637
+ if (!queued) return void 0;
618638
+ this.telegramQueuedSessionWork.delete(sessionKey);
618639
+ this.refreshActiveTelegramInteractionCount();
618640
+ return queued;
618641
+ }
618642
+ fallbackTelegramRouterDecision(msg, toolContext, err) {
618643
+ const forcedRoute = this.interactionMode === "chat" || this.interactionMode === "action" ? this.interactionMode : null;
618644
+ const errMsg = err instanceof Error ? err.message : String(err);
618645
+ return {
618646
+ route: forcedRoute ?? (msg.chatType === "private" ? "chat" : "action"),
618647
+ shouldReply: false,
618648
+ confidence: 0,
618649
+ reason: `router unavailable; retained as context without replying (${errMsg.slice(0, 160)})`,
618650
+ source: "inference-unavailable",
618651
+ silentDisposition: "retained as context without replying because the router did not settle",
618652
+ diagnosticNote: `router failure after queue admission: ${errMsg.slice(0, 240)}; tool_context=${toolContext}`
618653
+ };
618430
618654
  }
618431
618655
  canUseChatActions(msg) {
618432
618656
  return !msg.guestQueryId && (typeof msg.chatId === "number" || String(msg.chatId).startsWith("@"));
618433
618657
  }
618658
+ telegramSubAgentContextFlushMs() {
618659
+ const raw = process.env["OMNIUS_TG_SUBAGENT_CONTEXT_FLUSH_MS"];
618660
+ if (raw === "off") return 0;
618661
+ const parsed = raw !== void 0 ? Number(raw) : 650;
618662
+ if (!Number.isFinite(parsed)) return 650;
618663
+ return Math.max(0, Math.min(5e3, Math.floor(parsed)));
618664
+ }
618665
+ clearTelegramSubAgentContextBuffer(sessionKey) {
618666
+ const buffer2 = this.telegramSubAgentContextBuffers.get(sessionKey);
618667
+ if (buffer2?.timer) clearTimeout(buffer2.timer);
618668
+ this.telegramSubAgentContextBuffers.delete(sessionKey);
618669
+ }
618670
+ clearAllTelegramSubAgentContextBuffers() {
618671
+ for (const key of this.telegramSubAgentContextBuffers.keys()) {
618672
+ this.clearTelegramSubAgentContextBuffer(key);
618673
+ }
618674
+ }
618675
+ formatTelegramSubAgentContextPacket(messages2) {
618676
+ const recent = messages2.slice(-12);
618677
+ const dropped = messages2.length - recent.length;
618678
+ return [
618679
+ "[Telegram live context update]",
618680
+ "These Telegram messages arrived while this runner was already active. Treat them as added context, not a new task. Continue the current work and only adjust the reply if the update is directly relevant.",
618681
+ dropped > 0 ? `Older buffered updates omitted from this packet: ${dropped}.` : "",
618682
+ ...recent.map((message2, index) => `### Update ${index + 1}
618683
+ ${message2}`)
618684
+ ].filter(Boolean).join("\n\n");
618685
+ }
618686
+ enqueueTelegramSubAgentContext(sessionKey, subAgent, context2, username) {
618687
+ let buffer2 = this.telegramSubAgentContextBuffers.get(sessionKey);
618688
+ if (!buffer2) {
618689
+ buffer2 = { messages: [], timer: null };
618690
+ this.telegramSubAgentContextBuffers.set(sessionKey, buffer2);
618691
+ }
618692
+ buffer2.messages.push(context2);
618693
+ const flushMs = this.telegramSubAgentContextFlushMs();
618694
+ if (buffer2.timer) return;
618695
+ buffer2.timer = setTimeout(() => {
618696
+ this.flushTelegramSubAgentContextBuffer(sessionKey, username);
618697
+ }, flushMs);
618698
+ if (typeof buffer2.timer.unref === "function") buffer2.timer.unref();
618699
+ this.subAgentViewCallbacks?.onWrite(
618700
+ subAgent.viewId,
618701
+ `live context queued (${buffer2.messages.length} buffered)`
618702
+ );
618703
+ }
618704
+ flushTelegramSubAgentContextBuffer(sessionKey, username = "telegram") {
618705
+ const buffer2 = this.telegramSubAgentContextBuffers.get(sessionKey);
618706
+ if (!buffer2) return;
618707
+ if (buffer2.timer) clearTimeout(buffer2.timer);
618708
+ this.telegramSubAgentContextBuffers.delete(sessionKey);
618709
+ if (buffer2.messages.length === 0) return;
618710
+ const subAgent = this.subAgents.get(sessionKey);
618711
+ if (!subAgent || subAgent.aborted) return;
618712
+ const packet = this.formatTelegramSubAgentContextPacket(buffer2.messages);
618713
+ if (subAgent.runner) {
618714
+ subAgent.runner.injectUserMessage(packet);
618715
+ this.tuiWrite(() => renderTelegramSubAgentEvent(
618716
+ username,
618717
+ `live context consolidated (${buffer2.messages.length} message${buffer2.messages.length === 1 ? "" : "s"})`
618718
+ ));
618719
+ this.subAgentViewCallbacks?.onWrite(
618720
+ subAgent.viewId,
618721
+ `live context injected (${buffer2.messages.length} message${buffer2.messages.length === 1 ? "" : "s"})`
618722
+ );
618723
+ } else {
618724
+ subAgent.pendingMessages.push(packet);
618725
+ this.subAgentViewCallbacks?.onWrite(
618726
+ subAgent.viewId,
618727
+ `live context staged (${buffer2.messages.length} message${buffer2.messages.length === 1 ? "" : "s"})`
618728
+ );
618729
+ }
618730
+ }
618731
+ async enqueueTelegramMessageForExistingSubAgent(msg, subAgent) {
618732
+ const sessionKey = this.sessionKeyForMessage(msg);
618733
+ let mediaContext = "";
618734
+ if (msg.media || msg.replyToMedia) {
618735
+ mediaContext = await this.processMediaContextForMessage(msg);
618736
+ }
618737
+ const isGroup = msg.chatType !== "private";
618738
+ const chatLabel = isGroup ? ` in group "${msg.chatTitle || "unknown"}"` : "";
618739
+ const context2 = this.formatTelegramCurrentMessageForPrompt(
618740
+ sessionKey,
618741
+ msg,
618742
+ `Telegram live context from @${msg.username}${chatLabel}`,
618743
+ mediaContext
618744
+ );
618745
+ if (isGroup) {
618746
+ this.markLastTelegramUserMessageMode(msg, "steering");
618747
+ } else {
618748
+ this.recordTelegramUserMessage(msg, "steering", context2);
618749
+ }
618750
+ this.enqueueTelegramSubAgentContext(sessionKey, subAgent, context2, msg.username);
618751
+ this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "live context queued for active Telegram runner"));
618752
+ }
618434
618753
  async replyWithTelegramHelp(msg, isAdmin) {
618435
618754
  const scope = isAdmin ? "admin" : "public";
618436
618755
  const menu = renderHelpMenu(scope);
@@ -619471,7 +619790,7 @@ ${mediaContext}` : ""
619471
619790
  async runTelegramChannelDmnForSession(sessionKey, reason = "idle", nowMs = Date.now(), force = false) {
619472
619791
  if (!this.repoRoot) return null;
619473
619792
  if (this.channelDmnRunning.has(sessionKey)) return null;
619474
- if (this.subAgents.has(sessionKey)) return null;
619793
+ if (this.subAgents.has(sessionKey) || this.telegramActiveWorkSessions.has(sessionKey)) return null;
619475
619794
  const input = this.buildTelegramChannelDaydreamInput(sessionKey, nowMs);
619476
619795
  if (!input) return null;
619477
619796
  if (input.chatType === "private" && !force) return null;
@@ -621295,7 +621614,7 @@ ${lines.join("\n")}`);
621295
621614
  // ─────────────────────────────────────────────────────────────────
621296
621615
  // Observable inference — streams chatCompletion-shaped calls so the
621297
621616
  // operator can SEE what's happening during a long-running router or
621298
- // chat-fast-path call instead of waiting 180s for a hard-deadline.
621617
+ // chat-fast-path call instead of waiting for a router hard-deadline.
621299
621618
  // ─────────────────────────────────────────────────────────────────
621300
621619
  /**
621301
621620
  * Wrap a chatCompletion-shaped call so the bridge can observe its token
@@ -621699,14 +622018,14 @@ ${retryText}`,
621699
622018
  * in-flight promise, and on completion fire any queued trailing call.
621700
622019
  */
621701
622020
  startCoalescedTelegramRouterCall(sessionKey, msg, toolContext) {
621702
- const HARD_DEADLINE_MS = 18e4;
622021
+ const HARD_DEADLINE_MS = this.telegramRouterHardDeadlineMs();
621703
622022
  const inner = this.inferTelegramInteractionDecision(msg, toolContext);
621704
622023
  const promise = new Promise((resolve54, reject) => {
621705
622024
  let settled = false;
621706
622025
  const guard = setTimeout(() => {
621707
622026
  if (settled) return;
621708
622027
  settled = true;
621709
- reject(new Error("router-coalescer: hard deadline exceeded (180s); inner inference did not settle"));
622028
+ reject(new Error(`router-coalescer: hard deadline exceeded (${Math.round(HARD_DEADLINE_MS / 1e3)}s); inner inference did not settle`));
621710
622029
  }, HARD_DEADLINE_MS);
621711
622030
  if (typeof guard.unref === "function") guard.unref();
621712
622031
  inner.then(
@@ -621744,6 +622063,11 @@ ${retryText}`,
621744
622063
  promise.then(onSettled, onSettled);
621745
622064
  return promise;
621746
622065
  }
622066
+ telegramRouterHardDeadlineMs() {
622067
+ const raw = Number.parseInt(process.env["OMNIUS_TG_ROUTER_HARD_DEADLINE_MS"] ?? "", 10);
622068
+ if (Number.isFinite(raw) && raw >= 5e3 && raw <= 18e4) return raw;
622069
+ return 6e4;
622070
+ }
621747
622071
  /**
621748
622072
  * Forcibly cancel every in-flight + trailing router-coalescer entry.
621749
622073
  * Used on bridge stop() and by the watchdog if it detects the coalescer
@@ -621792,11 +622116,11 @@ ${retryText}`,
621792
622116
  * the iterator, and telegramObservableInference falls back to the
621793
622117
  * non-streaming chatCompletion path. This gives operators a clean
621794
622118
  * "stream silent for 60s, falling back" signal instead of the opaque
621795
- * 180s coalescer hard-deadline.
622119
+ * coalescer hard-deadline.
621796
622120
  *
621797
622121
  * Default 60s — comfortably longer than a healthy cold-load of a 35B
621798
622122
  * model on a warm VRAM cache (typically <30s) but short enough to
621799
- * surface a real wedge before the 180s coalescer fires. Override via
622123
+ * surface a real wedge before the coalescer fires. Override via
621800
622124
  * OMNIUS_TG_STREAM_INACTIVITY_MS (clamped to [10s, 5min]).
621801
622125
  */
621802
622126
  telegramStreamInactivityMs() {
@@ -621866,7 +622190,9 @@ ${retryText}`,
621866
622190
  } catch {
621867
622191
  }
621868
622192
  this.subAgents.delete(sessionKey);
622193
+ this.telegramActiveWorkSessions.delete(sessionKey);
621869
622194
  this.refreshActiveTelegramInteractionCount();
622195
+ this.dispatchQueuedTelegramSessionWorkSoon();
621870
622196
  this.tuiWrite(() => renderTelegramSubAgentEvent(
621871
622197
  agent.username,
621872
622198
  `watchdog: aborted stale sub-agent (idle ${Math.round((now - agent.lastEditMs) / 1e3)}s without completion)`
@@ -621892,7 +622218,7 @@ ${retryText}`,
621892
622218
  privateChannel: !isGroup,
621893
622219
  directSignal: addressesBot,
621894
622220
  replyToAgent: this.telegramMessageRepliesToBot(msg),
621895
- activeAgent: this.subAgents.has(sessionKey),
622221
+ activeAgent: this.subAgents.has(sessionKey) || this.telegramActiveWorkSessions.has(sessionKey),
621896
622222
  forceAnalyze: daydreamForceCheck
621897
622223
  });
621898
622224
  if (!config) {
@@ -622470,7 +622796,9 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
622470
622796
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
622471
622797
  messagesReceived: 0,
622472
622798
  messagesSent: 0,
622473
- activeSubAgents: 0
622799
+ activeSubAgents: 0,
622800
+ maxSubAgents: this.getSubAgentLimit(),
622801
+ queuedSubAgentSessions: 0
622474
622802
  };
622475
622803
  this.botUserId = typeof me.result?.id === "number" ? me.result.id : this.botUserId;
622476
622804
  this.polling = true;
@@ -622559,6 +622887,15 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
622559
622887
  }
622560
622888
  this.stopTelegramSubAgentWatchdog();
622561
622889
  this.cancelTelegramRouterSessionState("bridge stop");
622890
+ this.clearAllTelegramSubAgentContextBuffers();
622891
+ if (this.telegramDispatchQueuedTimer) {
622892
+ clearTimeout(this.telegramDispatchQueuedTimer);
622893
+ this.telegramDispatchQueuedTimer = null;
622894
+ }
622895
+ this.telegramQueuedSessionWork.clear();
622896
+ this.telegramActiveWorkSessions.clear();
622897
+ this.flushTelegramViewWrites();
622898
+ this.flushTelegramTuiWrites();
622562
622899
  this.telegramActiveInferences.clear();
622563
622900
  if (this.telegramSqliteDb && this.telegramSqliteDb !== false) {
622564
622901
  try {
@@ -622887,54 +623224,26 @@ Join: ${newUrl}`);
622887
623224
  }
622888
623225
  const existing = this.subAgents.get(sessionKey);
622889
623226
  if (existing && !existing.aborted) {
622890
- const isGroup = msg.chatType !== "private";
622891
- if (isGroup) {
622892
- const attentionViewId2 = this.registerTelegramAttentionView(msg, existing.toolContext || toolContext, "active Telegram thread");
622893
- const decision3 = await this.inferTelegramInteractionDecisionCoalesced(msg, existing.toolContext || toolContext);
622894
- this.deliverTelegramAttentionDecision(
622895
- sessionKey,
622896
- msg,
622897
- attentionViewId2,
622898
- decision3,
622899
- this.telegramMessageIdentitySalienceSignals(msg),
622900
- this.markLatestTelegramDaydreamOpportunitiesConsidered(sessionKey, msg)
622901
- );
622902
- this.markLastTelegramUserMessageMode(msg, decision3.shouldReply ? "steering" : "ambient");
622903
- this.subAgentViewCallbacks?.onWrite(
622904
- existing.viewId,
622905
- `live steering: ${decision3.shouldReply ? decision3.route : "no_reply"} (${decision3.source}, confidence ${decision3.confidence.toFixed(2)}): ${decision3.reason}`
622906
- );
622907
- if (!decision3.shouldReply) {
622908
- this.maybeLogTelegramGroupSkip(msg, `live inference: no steering — ${decision3.reason}`);
622909
- return;
622910
- }
622911
- }
622912
- let mediaContext = "";
622913
- if (msg.media || msg.replyToMedia) {
622914
- mediaContext = await this.processMediaContextForMessage(msg);
622915
- }
622916
- const steeringText = this.formatTelegramCurrentMessageForPrompt(
622917
- sessionKey,
622918
- msg,
622919
- `Telegram steering message from @${msg.username}`,
622920
- mediaContext
622921
- );
622922
- if (isGroup) {
622923
- this.markLastTelegramUserMessageMode(msg, "steering");
622924
- } else {
622925
- this.recordTelegramUserMessage(msg, "steering", steeringText);
622926
- }
622927
- if (existing.runner) {
622928
- existing.runner.injectUserMessage(steeringText);
622929
- this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "mid-conversation steering injected"));
622930
- } else {
622931
- existing.pendingMessages.push(steeringText);
622932
- this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, `queued (${existing.pendingMessages.length} pending)`));
622933
- }
623227
+ await this.enqueueTelegramMessageForExistingSubAgent(msg, existing);
623228
+ return;
623229
+ }
623230
+ this.scheduleTelegramSessionWork(msg, toolContext);
623231
+ }
623232
+ async processTelegramMessageWork(msg, toolContext) {
623233
+ const sessionKey = this.sessionKeyForMessage(msg);
623234
+ const isAdminDM = toolContext === "telegram-admin-dm";
623235
+ const existing = this.subAgents.get(sessionKey);
623236
+ if (existing && !existing.aborted) {
623237
+ await this.enqueueTelegramMessageForExistingSubAgent(msg, existing);
622934
623238
  return;
622935
623239
  }
622936
623240
  const attentionViewId = this.registerTelegramAttentionView(msg, toolContext);
622937
- const decision2 = await this.inferTelegramInteractionDecisionCoalesced(msg, toolContext);
623241
+ let decision2;
623242
+ try {
623243
+ decision2 = await this.inferTelegramInteractionDecisionCoalesced(msg, toolContext);
623244
+ } catch (err) {
623245
+ decision2 = this.fallbackTelegramRouterDecision(msg, toolContext, err);
623246
+ }
622938
623247
  this.deliverTelegramAttentionDecision(
622939
623248
  sessionKey,
622940
623249
  msg,
@@ -622952,7 +623261,20 @@ Join: ${newUrl}`);
622952
623261
  this.maybeLogTelegramGroupSkip(msg, `live inference: no reply — ${decision2.reason}`);
622953
623262
  return;
622954
623263
  }
622955
- if (decision2.route === "chat") {
623264
+ const existingAfterDecision = this.subAgents.get(sessionKey);
623265
+ if (existingAfterDecision && !existingAfterDecision.aborted) {
623266
+ this.subAgentViewCallbacks?.onWrite(
623267
+ existingAfterDecision.viewId,
623268
+ `live route consolidated: ${decision2.route} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)}): ${decision2.reason}`
623269
+ );
623270
+ await this.enqueueTelegramMessageForExistingSubAgent(
623271
+ msg,
623272
+ existingAfterDecision
623273
+ );
623274
+ return;
623275
+ }
623276
+ const subAgentProfile = decision2.route === "chat" ? "chat" : "action";
623277
+ if (decision2.route === "chat" && msg.chatType === "private") {
622956
623278
  await this.handleTelegramChatCompletion(msg, toolContext);
622957
623279
  return;
622958
623280
  }
@@ -622993,6 +623315,14 @@ Join: ${newUrl}`);
622993
623315
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, replyEdge);
622994
623316
  }
622995
623317
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `✈ Telegram message from @${msg.username}: ${msg.text}`);
623318
+ const queuedForSameSession = this.takeQueuedTelegramSessionWork(sessionKey);
623319
+ if (queuedForSameSession) {
623320
+ await this.enqueueTelegramMessageForExistingSubAgent(queuedForSameSession.msg, subAgent);
623321
+ this.subAgentViewCallbacks?.onWrite(
623322
+ subAgent.viewId,
623323
+ `merged queued session work (${queuedForSameSession.messageCount} message${queuedForSameSession.messageCount === 1 ? "" : "s"}) before runner start`
623324
+ );
623325
+ }
622996
623326
  if (this.canUseChatActions(msg)) {
622997
623327
  subAgent.typingInterval = this.startTypingIndicator(msg.chatId);
622998
623328
  }
@@ -623005,7 +623335,7 @@ Join: ${newUrl}`);
623005
623335
  if (msg.media || msg.replyToMedia) {
623006
623336
  mediaContext = await this.processMediaContextForMessage(msg);
623007
623337
  }
623008
- const result = await this.runSubAgent(msg, subAgent, mediaContext);
623338
+ const result = await this.runSubAgent(msg, subAgent, mediaContext, subAgentProfile);
623009
623339
  if (subAgent.typingInterval) {
623010
623340
  clearInterval(subAgent.typingInterval);
623011
623341
  subAgent.typingInterval = null;
@@ -623031,7 +623361,7 @@ Join: ${newUrl}`);
623031
623361
  }
623032
623362
  const finalHtml = convertMarkdownToTelegramHTML(finalText);
623033
623363
  const sentMessageId = await this.sendOrEditFinalTelegramHTML(msg, finalHtml, subAgent.liveMessageId);
623034
- this.recordTelegramAssistantMessage(msg, finalText, "action", {
623364
+ this.recordTelegramAssistantMessage(msg, finalText, subAgentProfile, {
623035
623365
  messageId: sentMessageId,
623036
623366
  replyToMessageId: msg.chatType !== "private" ? msg.messageId : void 0
623037
623367
  });
@@ -623062,6 +623392,7 @@ Join: ${newUrl}`);
623062
623392
  });
623063
623393
  }
623064
623394
  } finally {
623395
+ this.clearTelegramSubAgentContextBuffer(sessionKey);
623065
623396
  this.subAgents.delete(sessionKey);
623066
623397
  this.refreshActiveTelegramInteractionCount();
623067
623398
  this.subAgentViewCallbacks?.onComplete(subAgent.viewId);
@@ -623172,6 +623503,7 @@ Join: ${newUrl}`);
623172
623503
  });
623173
623504
  }
623174
623505
  } finally {
623506
+ this.clearTelegramSubAgentContextBuffer(sessionKey);
623175
623507
  this.subAgents.delete(sessionKey);
623176
623508
  this.refreshActiveTelegramInteractionCount();
623177
623509
  this.subAgentViewCallbacks?.onComplete(subAgent.viewId);
@@ -657259,10 +657591,12 @@ Log: ${nexusLogPath}`)
657259
657591
  }
657260
657592
  const source = scope === "global" ? globalSettings : projectSettings;
657261
657593
  const mode = source.telegramMode ?? savedSettings.telegramMode ?? "auto";
657594
+ const subAgents = typeof source.telegramSubAgents === "number" ? source.telegramSubAgents : typeof savedSettings.telegramSubAgents === "number" ? savedSettings.telegramSubAgents : 2;
657262
657595
  return {
657263
657596
  key: nonEmptyTelegramSetting(source.telegramKey),
657264
657597
  admin: nonEmptyTelegramSetting(source.telegramAdmin),
657265
657598
  mode,
657599
+ subAgents,
657266
657600
  keyScope: scope
657267
657601
  };
657268
657602
  };
@@ -657872,6 +658206,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
657872
658206
  telegramBridge.setContextWindowSize(resolvedContextWindowSize);
657873
658207
  }
657874
658208
  telegramBridge.setInteractionMode(savedSettings.telegramMode ?? "auto");
658209
+ telegramBridge.setSubAgentLimit(telegramSettingsForScope(scope).subAgents ?? 2);
657875
658210
  telegramBridge.setTelegramToolPolicy(savedSettings.telegramToolPolicy);
657876
658211
  telegramBridge.setMetricsProvider(() => statusBar?.getMetricsSnapshot());
657877
658212
  if (adminId) {
@@ -658006,7 +658341,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
658006
658341
  telegramBridge.botUsername,
658007
658342
  adminId,
658008
658343
  savedSettings.telegramMode ?? "auto",
658009
- telegramBridge.stats.canReadAllGroupMessages
658344
+ telegramBridge.stats.canReadAllGroupMessages,
658345
+ telegramBridge.stats.maxSubAgents
658010
658346
  )
658011
658347
  );
658012
658348
  showPrompt();
@@ -658039,10 +658375,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
658039
658375
  if (settings.mode !== void 0) {
658040
658376
  target.telegramMode = settings.mode;
658041
658377
  }
658378
+ if (settings.subAgents !== void 0) {
658379
+ target.telegramSubAgents = settings.subAgents;
658380
+ }
658042
658381
  const payload = {
658043
658382
  ...settings.key !== void 0 ? { telegramKey: settings.key } : {},
658044
658383
  ...settings.admin !== void 0 ? { telegramAdmin: settings.admin === null ? "" : settings.admin } : {},
658045
- ...settings.mode !== void 0 ? { telegramMode: settings.mode } : {}
658384
+ ...settings.mode !== void 0 ? { telegramMode: settings.mode } : {},
658385
+ ...settings.subAgents !== void 0 ? { telegramSubAgents: settings.subAgents } : {}
658046
658386
  };
658047
658387
  if (targetScope === "project") {
658048
658388
  saveProjectSettings(repoRoot, payload);
@@ -658072,10 +658412,16 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
658072
658412
  savedSettings.telegramMode = mode;
658073
658413
  telegramBridge?.setInteractionMode(mode);
658074
658414
  },
658415
+ telegramSetSubAgentLimit(limit) {
658416
+ savedSettings.telegramSubAgents = limit;
658417
+ return telegramBridge?.setSubAgentLimit(limit) ?? Math.max(1, Math.min(5, Math.floor(limit)));
658418
+ },
658075
658419
  telegramStatus() {
658076
658420
  const active = telegramBridge?.isActive ?? false;
658077
658421
  const botUser = active ? telegramBridge?.botUsername : void 0;
658078
658422
  const subAgents = active ? telegramBridge?.stats.activeSubAgents : void 0;
658423
+ const maxSubAgents = active ? telegramBridge?.stats.maxSubAgents : telegramSettingsForScope(activeTelegramSettingsScope ?? "project").subAgents ?? 2;
658424
+ const queuedSubAgents = active ? telegramBridge?.stats.queuedSubAgentSessions : 0;
658079
658425
  writeContent(
658080
658426
  () => renderTelegramStatus(
658081
658427
  active,
@@ -658083,7 +658429,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
658083
658429
  telegramSettingsForScope(activeTelegramSettingsScope ?? "project").admin,
658084
658430
  subAgents,
658085
658431
  savedSettings.telegramMode ?? "auto",
658086
- active ? telegramBridge?.stats.canReadAllGroupMessages : void 0
658432
+ active ? telegramBridge?.stats.canReadAllGroupMessages : void 0,
658433
+ maxSubAgents,
658434
+ queuedSubAgents
658087
658435
  )
658088
658436
  );
658089
658437
  },
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.130",
3
+ "version": "1.0.132",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.130",
9
+ "version": "1.0.132",
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.130",
3
+ "version": "1.0.132",
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",