omnius 1.0.84 → 1.0.86

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
@@ -607686,6 +607686,398 @@ var init_tool_policy = __esm({
607686
607686
  }
607687
607687
  });
607688
607688
 
607689
+ // packages/cli/src/tui/telegram-help-menu.ts
607690
+ function telegramSyntheticHelpSignatures() {
607691
+ return [
607692
+ { signature: "/help", description: "Show interactive command help" },
607693
+ { signature: "/start", description: "Show Telegram bridge status and authentication instructions" },
607694
+ { signature: "/auth <code>", description: "Authenticate this Telegram user as bot admin using the TUI code" },
607695
+ { signature: "/call", description: "Get the active voice call link when a call session is running" },
607696
+ { signature: "/reflect", description: "Run scoped Telegram chat reflection over retained chat history" },
607697
+ { signature: "/reflect status", description: "Show the latest scoped Telegram reflection artifact" },
607698
+ { signature: "/reflect now", description: "Run reflection and let the model decide whether to post a public follow-up" },
607699
+ { signature: "/reflect auto on|off", description: "Enable or disable model-gated idle follow-ups for this chat" },
607700
+ { signature: "/reflection", description: "Alias for /reflect" },
607701
+ { signature: "/daydream", description: "Alias for /reflect in Telegram chats" }
607702
+ ];
607703
+ }
607704
+ function telegramHelpCommandAllowed(cmd, scope) {
607705
+ if (cmd.name === "dream") return false;
607706
+ if (scope === "admin") return cmd.implementationStatus === "implemented";
607707
+ return TELEGRAM_PUBLIC_HELP_COMMANDS.has(cmd.name);
607708
+ }
607709
+ function parseArgsHint(argsHint) {
607710
+ if (!argsHint) return [];
607711
+ const args = [];
607712
+ const re = /<(\w+)(\?)?>/g;
607713
+ let match;
607714
+ while ((match = re.exec(argsHint)) !== null) {
607715
+ const name10 = match[1];
607716
+ const optional2 = match[2] === "?";
607717
+ args.push({
607718
+ name: name10,
607719
+ type: "string",
607720
+ required: !optional2,
607721
+ description: ""
607722
+ });
607723
+ }
607724
+ return args;
607725
+ }
607726
+ function buildScopedToolList(scope) {
607727
+ const commands = listCommandRegistry({ includePlanned: false }).filter((cmd) => telegramHelpCommandAllowed(cmd, scope));
607728
+ const syntheticSigs = telegramSyntheticHelpSignatures();
607729
+ const commandSigs = commands.flatMap((cmd) => cmd.signatures);
607730
+ const allSigs = [...syntheticSigs, ...commandSigs];
607731
+ const seen = /* @__PURE__ */ new Set();
607732
+ const unique = allSigs.filter((sig) => {
607733
+ if (seen.has(sig.signature)) return false;
607734
+ seen.add(sig.signature);
607735
+ return true;
607736
+ });
607737
+ const entries = [];
607738
+ for (const sig of unique) {
607739
+ const matchingCmd = commands.find(
607740
+ (cmd) => cmd.signatures.some((s2) => s2.signature === sig.signature)
607741
+ );
607742
+ const args = matchingCmd ? parseArgsHint(matchingCmd.argsHint) : [];
607743
+ const name10 = sig.signature.replace(/^\//, "").split(/\s+/)[0] ?? sig.signature;
607744
+ entries.push({
607745
+ name: name10,
607746
+ signature: sig.signature,
607747
+ description: sig.description,
607748
+ arguments: args
607749
+ });
607750
+ }
607751
+ return entries;
607752
+ }
607753
+ function encodeHelpCallback(action, value2) {
607754
+ const raw = `${CALLBACK_PREFIX}:${action}:${value2}`;
607755
+ return raw.slice(0, MAX_CALLBACK_DATA);
607756
+ }
607757
+ function decodeHelpCallback(data) {
607758
+ if (!data.startsWith(CALLBACK_PREFIX + ":")) return null;
607759
+ const parts = data.split(":");
607760
+ if (parts.length < 3) return null;
607761
+ const action = parts[1];
607762
+ const value2 = parts.slice(2).join(":");
607763
+ if (action !== "page" && action !== "detail" && action !== "back" && action !== "close") return null;
607764
+ return { action, value: value2 };
607765
+ }
607766
+ function buildToolListKeyboard(tools, page2, scope, countdown = null) {
607767
+ const totalPages = Math.max(1, Math.ceil(tools.length / TOOLS_PER_PAGE));
607768
+ const start2 = page2 * TOOLS_PER_PAGE;
607769
+ const pageTools = tools.slice(start2, start2 + TOOLS_PER_PAGE);
607770
+ const rows = [];
607771
+ let currentRow = [];
607772
+ for (const tool of pageTools) {
607773
+ const label = tool.name.length > 18 ? tool.name.slice(0, 17) + "…" : tool.name;
607774
+ currentRow.push({
607775
+ text: label,
607776
+ callback_data: encodeHelpCallback("detail", tool.name)
607777
+ });
607778
+ if (currentRow.length >= GRID_COLS) {
607779
+ rows.push(currentRow);
607780
+ currentRow = [];
607781
+ }
607782
+ }
607783
+ if (currentRow.length > 0) {
607784
+ rows.push(currentRow);
607785
+ }
607786
+ const navRow = [];
607787
+ if (page2 === 0) {
607788
+ const closeLabel = countdown != null ? `✖ ${countdown}` : "✖ Close";
607789
+ navRow.push({ text: closeLabel, callback_data: encodeHelpCallback("close", "0") });
607790
+ }
607791
+ if (page2 > 0) {
607792
+ navRow.push({ text: "◀️ Back", callback_data: encodeHelpCallback("page", page2 - 1) });
607793
+ }
607794
+ navRow.push({
607795
+ text: `${page2 + 1}/${totalPages}`,
607796
+ callback_data: encodeHelpCallback("page", page2.toString())
607797
+ // re-send same page (no-op, just indicator)
607798
+ });
607799
+ if (page2 < totalPages - 1) {
607800
+ navRow.push({ text: "▶️ Next", callback_data: encodeHelpCallback("page", page2 + 1) });
607801
+ }
607802
+ rows.push(navRow);
607803
+ return rows;
607804
+ }
607805
+ function buildToolDetailKeyboard(tool, page2) {
607806
+ const rows = [];
607807
+ for (const arg of tool.arguments) {
607808
+ const req2 = arg.required ? "●" : "○";
607809
+ const label = `${req2} ${arg.name}`.slice(0, 30);
607810
+ rows.push([{
607811
+ text: label,
607812
+ callback_data: encodeHelpCallback("detail", tool.name)
607813
+ // stay on detail
607814
+ }]);
607815
+ }
607816
+ rows.push([{
607817
+ text: "🔙 Back to tools",
607818
+ callback_data: encodeHelpCallback("back", page2.toString())
607819
+ }]);
607820
+ return rows;
607821
+ }
607822
+ function escapeHTML(text) {
607823
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
607824
+ }
607825
+ function buildToolListText(tools, page2, scope) {
607826
+ const totalPages = Math.max(1, Math.ceil(tools.length / TOOLS_PER_PAGE));
607827
+ const start2 = page2 * TOOLS_PER_PAGE;
607828
+ const pageTools = tools.slice(start2, start2 + TOOLS_PER_PAGE);
607829
+ const lines = [
607830
+ `<b>🛠 Commands (${scope === "admin" ? "admin full scope" : "public secure scope"})</b>`,
607831
+ `<i>Page ${page2 + 1} of ${totalPages} — ${tools.length} commands</i>`,
607832
+ ""
607833
+ ];
607834
+ for (const tool of pageTools) {
607835
+ lines.push(`<code>${escapeHTML(tool.signature)}</code>`);
607836
+ lines.push(` ${escapeHTML(tool.description)}`);
607837
+ }
607838
+ lines.push("");
607839
+ lines.push("<i>Tap a command for details, or use ◀️▶️ to navigate.</i>");
607840
+ return lines.join("\n");
607841
+ }
607842
+ function buildToolDetailText(tool) {
607843
+ const lines = [
607844
+ `<b>📌 ${escapeHTML(tool.signature)}</b>`,
607845
+ "",
607846
+ escapeHTML(tool.description),
607847
+ ""
607848
+ ];
607849
+ if (tool.arguments.length > 0) {
607850
+ lines.push("<b>Arguments:</b>");
607851
+ lines.push("");
607852
+ for (const arg of tool.arguments) {
607853
+ const reqBadge = arg.required ? "<b>[required]</b>" : "<i>[optional]</i>";
607854
+ lines.push(`<code>${escapeHTML(arg.name)}</code> ${reqBadge} <i>${escapeHTML(arg.type)}</i>`);
607855
+ if (arg.description) {
607856
+ lines.push(` ${escapeHTML(arg.description)}`);
607857
+ }
607858
+ lines.push("");
607859
+ }
607860
+ } else {
607861
+ lines.push("<i>No arguments.</i>");
607862
+ }
607863
+ lines.push("🔙 <i>Tap Back to return to the tool list.</i>");
607864
+ return lines.join("\n");
607865
+ }
607866
+ function renderHelpMenu(scope) {
607867
+ const tools = buildScopedToolList(scope);
607868
+ const text = buildToolListText(tools, 0, scope);
607869
+ const inline_keyboard = buildToolListKeyboard(tools, 0, scope);
607870
+ return { text, replyMarkup: { inline_keyboard } };
607871
+ }
607872
+ function renderHelpMenuPage(scope, page2) {
607873
+ const tools = buildScopedToolList(scope);
607874
+ const totalPages = Math.max(1, Math.ceil(tools.length / TOOLS_PER_PAGE));
607875
+ page2 = Math.max(0, Math.min(page2, totalPages - 1));
607876
+ const text = buildToolListText(tools, page2, scope);
607877
+ const inline_keyboard = buildToolListKeyboard(tools, page2, scope);
607878
+ return { text, replyMarkup: { inline_keyboard } };
607879
+ }
607880
+ function renderHelpMenuPageWithCountdown(scope, page2, countdown) {
607881
+ const tools = buildScopedToolList(scope);
607882
+ const totalPages = Math.max(1, Math.ceil(tools.length / TOOLS_PER_PAGE));
607883
+ page2 = Math.max(0, Math.min(page2, totalPages - 1));
607884
+ const text = buildToolListText(tools, page2, scope);
607885
+ const inline_keyboard = buildToolListKeyboard(tools, page2, scope, countdown);
607886
+ return { text, replyMarkup: { inline_keyboard } };
607887
+ }
607888
+ function renderHelpToolDetail(scope, toolName, returnPage) {
607889
+ const tools = buildScopedToolList(scope);
607890
+ const tool = tools.find((t2) => t2.name === toolName);
607891
+ if (!tool) return null;
607892
+ const text = buildToolDetailText(tool);
607893
+ const inline_keyboard = buildToolDetailKeyboard(tool, returnPage);
607894
+ return { text, replyMarkup: { inline_keyboard } };
607895
+ }
607896
+ function handleHelpCallback(callbackData, currentState) {
607897
+ const decoded = decodeHelpCallback(callbackData);
607898
+ if (!decoded) return null;
607899
+ const { action, value: value2 } = decoded;
607900
+ let newState;
607901
+ let render2;
607902
+ switch (action) {
607903
+ case "page": {
607904
+ const page2 = parseInt(value2, 10);
607905
+ if (isNaN(page2)) return null;
607906
+ render2 = renderHelpMenuPage(currentState.scope, page2);
607907
+ newState = { ...currentState, page: page2, view: "list", detailToolName: null, lastInteractionAt: Date.now() };
607908
+ break;
607909
+ }
607910
+ case "detail": {
607911
+ const detail = renderHelpToolDetail(currentState.scope, value2, currentState.page);
607912
+ if (!detail) return null;
607913
+ render2 = detail;
607914
+ newState = { ...currentState, view: "detail", detailToolName: value2, lastInteractionAt: Date.now() };
607915
+ break;
607916
+ }
607917
+ case "back": {
607918
+ const page2 = parseInt(value2, 10);
607919
+ if (isNaN(page2)) return null;
607920
+ render2 = renderHelpMenuPage(currentState.scope, page2);
607921
+ newState = { ...currentState, page: page2, view: "list", detailToolName: null, lastInteractionAt: Date.now() };
607922
+ break;
607923
+ }
607924
+ case "close": {
607925
+ return { render: null, newState: currentState, close: true };
607926
+ }
607927
+ default:
607928
+ return null;
607929
+ }
607930
+ return { render: render2, newState };
607931
+ }
607932
+ var TOOLS_PER_PAGE, GRID_COLS, CALLBACK_PREFIX, MAX_CALLBACK_DATA, INACTIVITY_TIMEOUT_MS, COUNTDOWN_SECONDS, TELEGRAM_PUBLIC_HELP_COMMANDS, HelpMenuStateStore, HelpMenuTimerManager;
607933
+ var init_telegram_help_menu = __esm({
607934
+ "packages/cli/src/tui/telegram-help-menu.ts"() {
607935
+ "use strict";
607936
+ init_command_registry();
607937
+ TOOLS_PER_PAGE = 10;
607938
+ GRID_COLS = 5;
607939
+ CALLBACK_PREFIX = "help";
607940
+ MAX_CALLBACK_DATA = 64;
607941
+ INACTIVITY_TIMEOUT_MS = 6e4;
607942
+ COUNTDOWN_SECONDS = 10;
607943
+ TELEGRAM_PUBLIC_HELP_COMMANDS = /* @__PURE__ */ new Set(["help", "start", "auth", "call"]);
607944
+ HelpMenuStateStore = class {
607945
+ states = /* @__PURE__ */ new Map();
607946
+ TTL_MS = 30 * 60 * 1e3;
607947
+ // 30 min
607948
+ key(chatId, messageId) {
607949
+ return `${chatId}:${messageId}`;
607950
+ }
607951
+ set(state) {
607952
+ this.states.set(this.key(state.chatId, state.messageId), state);
607953
+ }
607954
+ get(chatId, messageId) {
607955
+ return this.states.get(this.key(chatId, messageId));
607956
+ }
607957
+ delete(chatId, messageId) {
607958
+ this.states.delete(this.key(chatId, messageId));
607959
+ }
607960
+ /** Prune expired states */
607961
+ prune() {
607962
+ const now = Date.now();
607963
+ for (const [k, v] of this.states) {
607964
+ if (now - v.createdAt > this.TTL_MS) this.states.delete(k);
607965
+ }
607966
+ }
607967
+ };
607968
+ HelpMenuTimerManager = class {
607969
+ inactivityTimers = /* @__PURE__ */ new Map();
607970
+ countdownIntervals = /* @__PURE__ */ new Map();
607971
+ stateStore;
607972
+ callbacks;
607973
+ constructor(stateStore, callbacks) {
607974
+ this.stateStore = stateStore;
607975
+ this.callbacks = callbacks;
607976
+ }
607977
+ key(chatId, messageId) {
607978
+ return `${chatId}:${messageId}`;
607979
+ }
607980
+ /** Start the inactivity timer for a newly created menu */
607981
+ startTimer(state) {
607982
+ this.clearTimer(state.chatId, state.messageId);
607983
+ const k = this.key(state.chatId, state.messageId);
607984
+ const timer = setTimeout(() => {
607985
+ this.inactivityTimers.delete(k);
607986
+ this.startCountdown(state);
607987
+ }, INACTIVITY_TIMEOUT_MS);
607988
+ this.inactivityTimers.set(k, timer);
607989
+ }
607990
+ /** Reset the inactivity timer after user interaction */
607991
+ resetTimer(chatId, messageId) {
607992
+ const state = this.stateStore.get(chatId, messageId);
607993
+ if (!state) return;
607994
+ this.cancelCountdown(chatId, messageId);
607995
+ const updated = { ...state, lastInteractionAt: Date.now(), countdownValue: null };
607996
+ this.stateStore.set(updated);
607997
+ this.startTimer(updated);
607998
+ }
607999
+ /** Clear all timers for a menu (used when menu is closed or deleted) */
608000
+ clearTimer(chatId, messageId) {
608001
+ const k = this.key(chatId, messageId);
608002
+ const timer = this.inactivityTimers.get(k);
608003
+ if (timer) {
608004
+ clearTimeout(timer);
608005
+ this.inactivityTimers.delete(k);
608006
+ }
608007
+ this.cancelCountdown(chatId, messageId);
608008
+ }
608009
+ /** Start the 10-second countdown, updating the close button each second */
608010
+ startCountdown(state) {
608011
+ const k = this.key(state.chatId, state.messageId);
608012
+ let countdown = COUNTDOWN_SECONDS;
608013
+ const updatedState = { ...state, countdownValue: countdown, lastInteractionAt: Date.now() };
608014
+ this.stateStore.set(updatedState);
608015
+ this.updateCountdownButton(updatedState);
608016
+ const interval = setInterval(() => {
608017
+ countdown--;
608018
+ if (countdown <= 0) {
608019
+ clearInterval(interval);
608020
+ this.countdownIntervals.delete(k);
608021
+ this.deleteMenu(state.chatId, state.messageId);
608022
+ } else {
608023
+ const s2 = { ...state, countdownValue: countdown, lastInteractionAt: Date.now() };
608024
+ this.stateStore.set(s2);
608025
+ this.updateCountdownButton(s2);
608026
+ }
608027
+ }, 1e3);
608028
+ this.countdownIntervals.set(k, interval);
608029
+ }
608030
+ cancelCountdown(chatId, messageId) {
608031
+ const k = this.key(chatId, messageId);
608032
+ const interval = this.countdownIntervals.get(k);
608033
+ if (interval) {
608034
+ clearInterval(interval);
608035
+ this.countdownIntervals.delete(k);
608036
+ }
608037
+ }
608038
+ /** Update the close button to show countdown value */
608039
+ async updateCountdownButton(state) {
608040
+ try {
608041
+ let render2;
608042
+ if (state.view === "list") {
608043
+ render2 = renderHelpMenuPageWithCountdown(state.scope, state.page, state.countdownValue);
608044
+ } else {
608045
+ render2 = renderHelpToolDetail(state.scope, state.detailToolName, state.page);
608046
+ }
608047
+ if (!render2) return;
608048
+ await this.callbacks.editMessageText(
608049
+ state.chatId,
608050
+ state.messageId,
608051
+ render2.text,
608052
+ render2.replyMarkup
608053
+ );
608054
+ } catch {
608055
+ }
608056
+ }
608057
+ /** Delete the menu message and clean up state */
608058
+ async deleteMenu(chatId, messageId) {
608059
+ this.clearTimer(chatId, messageId);
608060
+ this.stateStore.delete(chatId, messageId);
608061
+ try {
608062
+ await this.callbacks.deleteMessage(chatId, messageId);
608063
+ } catch {
608064
+ }
608065
+ }
608066
+ /** Clean up all timers (for shutdown) */
608067
+ destroyAll() {
608068
+ for (const [k, timer] of this.inactivityTimers) {
608069
+ clearTimeout(timer);
608070
+ }
608071
+ this.inactivityTimers.clear();
608072
+ for (const [k, interval] of this.countdownIntervals) {
608073
+ clearInterval(interval);
608074
+ }
608075
+ this.countdownIntervals.clear();
608076
+ }
608077
+ };
608078
+ }
608079
+ });
608080
+
607689
608081
  // packages/cli/src/tui/telegram-creative-tools.ts
607690
608082
  import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes21 } from "node:crypto";
607691
608083
  import {
@@ -611355,7 +611747,7 @@ function splitTelegramReminderDue(raw) {
611355
611747
  if (suffixMatch) return { due: suffixMatch[2].trim(), message: suffixMatch[1].trim() };
611356
611748
  return { message: text };
611357
611749
  }
611358
- function telegramSyntheticHelpSignatures() {
611750
+ function telegramSyntheticHelpSignatures2() {
611359
611751
  return [
611360
611752
  { signature: "/help", description: "Show Telegram command help" },
611361
611753
  { signature: "/start", description: "Show Telegram bridge status and authentication instructions" },
@@ -611369,15 +611761,15 @@ function telegramSyntheticHelpSignatures() {
611369
611761
  { signature: "/daydream", description: "Alias for /reflect in Telegram chats" }
611370
611762
  ];
611371
611763
  }
611372
- function telegramHelpCommandAllowed(cmd, scope) {
611764
+ function telegramHelpCommandAllowed2(cmd, scope) {
611373
611765
  if (cmd.name === "dream") return false;
611374
611766
  if (scope === "admin") return cmd.implementationStatus === "implemented";
611375
- return TELEGRAM_PUBLIC_HELP_COMMANDS.has(cmd.name) || TELEGRAM_PUBLIC_BOT_COMMAND_NAMES.has(cmd.name);
611767
+ return TELEGRAM_PUBLIC_HELP_COMMANDS2.has(cmd.name) || TELEGRAM_PUBLIC_BOT_COMMAND_NAMES.has(cmd.name);
611376
611768
  }
611377
611769
  function buildTelegramHelpHTML(scope, maxPublicCommands = 24) {
611378
- const commands = listCommandRegistry({ includePlanned: false }).filter((cmd) => telegramHelpCommandAllowed(cmd, scope));
611770
+ const commands = listCommandRegistry({ includePlanned: false }).filter((cmd) => telegramHelpCommandAllowed2(cmd, scope));
611379
611771
  const signatures = [
611380
- ...telegramSyntheticHelpSignatures(),
611772
+ ...telegramSyntheticHelpSignatures2(),
611381
611773
  ...commands.flatMap((cmd) => cmd.signatures)
611382
611774
  ];
611383
611775
  const seen = /* @__PURE__ */ new Set();
@@ -612091,7 +612483,7 @@ function renderTelegramSubAgentError(username, error) {
612091
612483
  process.stdout.write(` ${c3.dim("│")} ${c3.red("✘")} @${username}: ${c3.dim(preview)}
612092
612484
  `);
612093
612485
  }
612094
- 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_COMMANDS, 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;
612486
+ 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;
612095
612487
  var init_telegram_bridge = __esm({
612096
612488
  "packages/cli/src/tui/telegram-bridge.ts"() {
612097
612489
  "use strict";
@@ -612102,6 +612494,7 @@ var init_telegram_bridge = __esm({
612102
612494
  init_tool_policy();
612103
612495
  init_media_routing();
612104
612496
  init_command_registry();
612497
+ init_telegram_help_menu();
612105
612498
  init_scoped_personality();
612106
612499
  init_telegram_creative_tools();
612107
612500
  init_omnius_directory();
@@ -612468,7 +612861,7 @@ External acquisition contract:
612468
612861
  bruteForceMaxCycles: 0,
612469
612862
  allowTurnExtension: false
612470
612863
  };
612471
- TELEGRAM_PUBLIC_HELP_COMMANDS = /* @__PURE__ */ new Set(["help", "start", "auth", "call"]);
612864
+ TELEGRAM_PUBLIC_HELP_COMMANDS2 = /* @__PURE__ */ new Set(["help", "start", "auth", "call"]);
612472
612865
  TELEGRAM_REMINDER_SLASH_COMMANDS = /* @__PURE__ */ new Set(["remind", "reminder", "reminders"]);
612473
612866
  TELEGRAM_REFLECTION_SLASH_COMMANDS = /* @__PURE__ */ new Set(["reflect", "reflection", "daydream", "dream"]);
612474
612867
  TELEGRAM_PUBLIC_BOT_COMMAND_NAMES = new Set(
@@ -612562,6 +612955,12 @@ External acquisition contract:
612562
612955
  telegramBotRightsCache = /* @__PURE__ */ new Map();
612563
612956
  /** Short-lived Telegram inline button state directory */
612564
612957
  telegramToolButtonDir;
612958
+ /** Interactive help menu state store (inline keyboard navigation) */
612959
+ helpMenuStates = new HelpMenuStateStore();
612960
+ /** Auto-close timer manager for help menus (inactivity → countdown → delete) */
612961
+ helpMenuTimers = null;
612962
+ /** Prune expired help menu states every 5 minutes */
612963
+ helpMenuPruneTimer = null;
612565
612964
  /** Command handler for admin DM slash commands (wired from interactive.ts) */
612566
612965
  commandHandler = null;
612567
612966
  /** Callback fired after a Telegram user completes the TUI-only admin auth challenge */
@@ -612983,21 +613382,53 @@ No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code
612983
613382
  }
612984
613383
  async replyWithTelegramHelp(msg, isAdmin) {
612985
613384
  const scope = isAdmin ? "admin" : "public";
612986
- const chunks = splitTelegramHTMLMessage(buildTelegramHelpHTML(scope));
613385
+ const menu = renderHelpMenu(scope);
612987
613386
  if (msg.guestQueryId) {
613387
+ const chunks = splitTelegramHTMLMessage(buildTelegramHelpHTML(isAdmin ? "admin" : "public"));
612988
613388
  await this.answerGuestQuery(msg.guestQueryId, chunks[0] ?? "", { parseMode: "HTML" });
612989
613389
  return;
612990
613390
  }
612991
- for (let i2 = 0; i2 < chunks.length; i2++) {
612992
- const chunk = chunks[i2];
612993
- if (i2 === 0) {
612994
- await this.replyToTelegramMessage(msg, chunk, {
612995
- html: true,
612996
- replyToMessageId: msg.chatType !== "private" ? msg.messageId : void 0
613391
+ const sent = await this.apiCall("sendMessage", {
613392
+ chat_id: msg.chatId,
613393
+ text: menu.text,
613394
+ parse_mode: "HTML",
613395
+ reply_markup: JSON.stringify(menu.replyMarkup),
613396
+ ...msg.chatType !== "private" ? { reply_to_message_id: msg.messageId } : {}
613397
+ });
613398
+ if (sent.ok && sent.result?.message_id) {
613399
+ const state = {
613400
+ chatId: msg.chatId,
613401
+ messageId: sent.result.message_id,
613402
+ scope,
613403
+ page: 0,
613404
+ view: "list",
613405
+ detailToolName: null,
613406
+ fromUserId: msg.fromUserId ?? 0,
613407
+ createdAt: Date.now(),
613408
+ lastInteractionAt: Date.now(),
613409
+ countdownValue: null
613410
+ };
613411
+ this.helpMenuStates.set(state);
613412
+ if (!this.helpMenuTimers) {
613413
+ this.helpMenuTimers = new HelpMenuTimerManager(this.helpMenuStates, {
613414
+ editMessageText: async (chatId, messageId, text, replyMarkup) => {
613415
+ await this.apiCall("editMessageText", {
613416
+ chat_id: chatId,
613417
+ message_id: messageId,
613418
+ text,
613419
+ parse_mode: "HTML",
613420
+ reply_markup: JSON.stringify(replyMarkup)
613421
+ });
613422
+ },
613423
+ deleteMessage: async (chatId, messageId) => {
613424
+ await this.apiCall("deleteMessage", {
613425
+ chat_id: chatId,
613426
+ message_id: messageId
613427
+ });
613428
+ }
612997
613429
  });
612998
- } else {
612999
- await this.sendMessageHTML(msg.chatId, chunk);
613000
613430
  }
613431
+ this.helpMenuTimers.startTimer(state);
613001
613432
  }
613002
613433
  }
613003
613434
  recordChatHistory(sessionKey, entry) {
@@ -619310,6 +619741,71 @@ Scoped workspace: ${scopedRoot}`,
619310
619741
  return Boolean(result.ok);
619311
619742
  }
619312
619743
  async handleTelegramCallbackQuery(callback) {
619744
+ const helpDecoded = decodeHelpCallback(callback.data);
619745
+ if (helpDecoded) {
619746
+ let answerText2 = "";
619747
+ let alert2 = false;
619748
+ try {
619749
+ const chatId = callback.chatId;
619750
+ const messageId = callback.messageId;
619751
+ if (!chatId || !messageId) {
619752
+ answerText2 = "Cannot identify menu message.";
619753
+ alert2 = true;
619754
+ return;
619755
+ }
619756
+ const menuState = this.helpMenuStates.get(chatId, messageId);
619757
+ if (!menuState) {
619758
+ answerText2 = "This help menu expired. Send /help for a fresh one.";
619759
+ alert2 = true;
619760
+ return;
619761
+ }
619762
+ const isAdmin = this.isAdminActor(callback.fromUserId, callback.username);
619763
+ if (callback.fromUserId !== menuState.fromUserId && !isAdmin) {
619764
+ answerText2 = "Only the user who opened this menu can navigate it.";
619765
+ alert2 = true;
619766
+ return;
619767
+ }
619768
+ const result = handleHelpCallback(callback.data, menuState);
619769
+ if (!result) {
619770
+ answerText2 = "Unknown menu action.";
619771
+ alert2 = true;
619772
+ return;
619773
+ }
619774
+ if (result.close) {
619775
+ this.helpMenuStates.delete(chatId, messageId);
619776
+ this.helpMenuTimers?.deleteMenu(chatId, messageId);
619777
+ try {
619778
+ await this.apiCall("deleteMessage", {
619779
+ chat_id: chatId,
619780
+ message_id: messageId
619781
+ });
619782
+ } catch {
619783
+ }
619784
+ await this.answerCallbackQuery(callback.id).catch(() => false);
619785
+ return;
619786
+ }
619787
+ this.helpMenuStates.set(result.newState);
619788
+ this.helpMenuTimers?.resetTimer(chatId, messageId);
619789
+ await this.apiCall("editMessageText", {
619790
+ chat_id: chatId,
619791
+ message_id: messageId,
619792
+ text: result.render.text,
619793
+ parse_mode: "HTML",
619794
+ reply_markup: JSON.stringify(result.render.replyMarkup)
619795
+ });
619796
+ answerText2 = "";
619797
+ } catch (err) {
619798
+ answerText2 = err instanceof Error ? err.message : String(err);
619799
+ alert2 = true;
619800
+ } finally {
619801
+ if (answerText2) {
619802
+ await this.answerCallbackQuery(callback.id, answerText2.slice(0, 180), alert2).catch(() => false);
619803
+ } else {
619804
+ await this.answerCallbackQuery(callback.id).catch(() => false);
619805
+ }
619806
+ }
619807
+ return;
619808
+ }
619313
619809
  let answerText = "Updated.";
619314
619810
  let alert = false;
619315
619811
  try {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.84",
3
+ "version": "1.0.86",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.84",
9
+ "version": "1.0.86",
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.84",
3
+ "version": "1.0.86",
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",