omnius 1.0.199 → 1.0.200

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
@@ -23044,6 +23044,13 @@ function deleteRepoFromCache(repo) {
23044
23044
  }
23045
23045
  return removed;
23046
23046
  }
23047
+ function deleteCachedModel(repo) {
23048
+ const bytesFreed = deleteRepoFromCache(repo);
23049
+ const meta = readMeta();
23050
+ meta.entries = meta.entries.filter((entry) => entry.repo !== repo);
23051
+ writeMeta(meta);
23052
+ return { repo, bytesFreed };
23053
+ }
23047
23054
  function evictModelsToFreeSpace(args) {
23048
23055
  const safetyMargin = args.safetyMarginBytes ?? 1 * 1024 ** 3;
23049
23056
  const target = args.neededBytes + safetyMargin;
@@ -534863,6 +534870,7 @@ __export(dist_exports, {
534863
534870
  createWorktree: () => createWorktree2,
534864
534871
  defaultExposureForTool: () => defaultExposureForTool,
534865
534872
  defaultExtensionForMime: () => defaultExtensionForMime,
534873
+ deleteCachedModel: () => deleteCachedModel,
534866
534874
  deleteMediaModelAdapter: () => deleteMediaModelAdapter,
534867
534875
  deleteTodos: () => deleteTodos,
534868
534876
  detectCudaDevices: () => detectCudaDevices,
@@ -630825,9 +630833,14 @@ function buildTelegramCommandMenuItems(scope) {
630825
630833
  seen.add(cmd.name);
630826
630834
  items.push({
630827
630835
  label: `/${cmd.name}`,
630828
- command: `/${cmd.name}`,
630829
630836
  description: cmd.signatures[0]?.description ?? signature,
630830
- adminOnly: scope === "admin"
630837
+ adminOnly: scope === "admin",
630838
+ action: {
630839
+ type: "command_detail",
630840
+ command: `/${cmd.name}`,
630841
+ label: `/${cmd.name}`,
630842
+ description: cmd.signatures.map((sig) => `${sig.signature} - ${sig.description}`).join("\n")
630843
+ }
630831
630844
  });
630832
630845
  }
630833
630846
  return items.sort((a2, b) => a2.label.localeCompare(b.label));
@@ -630835,10 +630848,18 @@ function buildTelegramCommandMenuItems(scope) {
630835
630848
  function buildTelegramGenerativeMenuItems(commandName) {
630836
630849
  const name10 = commandName.replace(/^\//, "").toLowerCase();
630837
630850
  if (!GENERATIVE_COMMANDS.has(name10)) return [];
630851
+ if (name10 === "models") {
630852
+ return [
630853
+ { label: "CAD models", description: "Browse text-to-CAD adapters.", action: { type: "models", generation: "cad" } },
630854
+ { label: "3D models", description: "Browse 3D mesh/reconstruction adapters.", action: { type: "models", generation: "model3d" } },
630855
+ { label: "Model store", command: "/models", description: "Show unified model store status.", action: { type: "command", command: "/models" } }
630856
+ ];
630857
+ }
630838
630858
  const title = name10[0].toUpperCase() + name10.slice(1);
630859
+ const generation = name10 === "sound" ? "sound" : name10 === "music" ? "music" : name10;
630839
630860
  return [
630840
- { label: `${title} models`, command: `/${name10} list`, description: `List available ${name10} models and hardware fit.` },
630841
- { label: `${title} setup`, command: `/${name10} setup`, description: `Show setup commands for the ${name10} backend.` }
630861
+ { label: `${title} models`, description: `Browse selectable ${name10} models, metadata, cache state, and actions.`, action: { type: "models", generation } },
630862
+ { label: `${title} setup`, description: `Show setup commands for the ${name10} backend.`, action: { type: "setup_generation", generation } }
630842
630863
  ];
630843
630864
  }
630844
630865
  function encodeTelegramCommandMenuCallback(action, value2) {
@@ -630848,43 +630869,85 @@ function encodeTelegramCommandMenuCallback(action, value2) {
630848
630869
  function decodeTelegramCommandMenuCallback(data) {
630849
630870
  const parts = data.split(":");
630850
630871
  if (parts.length !== 3 || parts[0] !== CALLBACK_PREFIX2) return null;
630851
- const action = parts[1] === "p" ? "page" : parts[1] === "r" ? "run" : parts[1] === "c" ? "close" : null;
630872
+ const action = parts[1] === "p" ? "page" : parts[1] === "r" ? "run" : parts[1] === "c" ? "close" : parts[1] === "b" ? "back" : null;
630852
630873
  if (!action) return null;
630853
630874
  return { action, value: parts[2] ?? "" };
630854
630875
  }
630876
+ function pushTelegramCommandMenuState(state, next) {
630877
+ const crumb = {
630878
+ kind: state.kind,
630879
+ title: state.title,
630880
+ subtitle: state.subtitle,
630881
+ body: state.body,
630882
+ page: state.page,
630883
+ items: state.items
630884
+ };
630885
+ return {
630886
+ ...state,
630887
+ kind: next.kind ?? state.kind,
630888
+ title: next.title,
630889
+ subtitle: next.subtitle,
630890
+ body: next.body,
630891
+ page: next.page ?? 0,
630892
+ items: next.items,
630893
+ breadcrumbs: [...state.breadcrumbs ?? [], crumb]
630894
+ };
630895
+ }
630896
+ function popTelegramCommandMenuState(state) {
630897
+ const stack = state.breadcrumbs ?? [];
630898
+ const previous = stack.at(-1);
630899
+ if (!previous) return null;
630900
+ return {
630901
+ ...state,
630902
+ kind: previous.kind,
630903
+ title: previous.title,
630904
+ subtitle: previous.subtitle,
630905
+ body: previous.body,
630906
+ page: previous.page,
630907
+ items: previous.items,
630908
+ breadcrumbs: stack.slice(0, -1)
630909
+ };
630910
+ }
630855
630911
  function renderTelegramCommandMenu(state) {
630856
630912
  const totalPages = Math.max(1, Math.ceil(state.items.length / PAGE_SIZE2));
630857
630913
  const page2 = Math.max(0, Math.min(state.page, totalPages - 1));
630858
630914
  const start2 = page2 * PAGE_SIZE2;
630859
630915
  const visible = state.items.slice(start2, start2 + PAGE_SIZE2);
630860
- const title = state.kind === "generative" ? "Generative command" : "Commands";
630916
+ const title = state.title || (state.kind === "generative" ? "Generative command" : state.kind === "models" ? "Models" : "Commands");
630861
630917
  const scope = state.scope === "admin" ? "admin" : "public";
630862
630918
  const lines = [
630863
630919
  `<b>${escapeHTML3(title)}</b>`,
630864
630920
  `<i>${escapeHTML3(scope)} scope - page ${page2 + 1}/${totalPages}</i>`,
630921
+ state.subtitle ? escapeHTML3(state.subtitle) : "",
630922
+ state.body ? `<blockquote expandable>${escapeHTML3(state.body)}</blockquote>` : "",
630865
630923
  "",
630866
630924
  ...visible.flatMap((item) => [
630867
- `<code>${escapeHTML3(item.command)}</code>`,
630925
+ item.command ? `<code>${escapeHTML3(item.command)}</code>` : `<b>${escapeHTML3(item.label)}</b>`,
630868
630926
  escapeHTML3(item.description)
630869
630927
  ])
630870
- ];
630928
+ ].filter((line) => line !== "");
630871
630929
  const keyboard = visible.map((item, offset) => [{
630872
630930
  text: item.label.slice(0, 32),
630873
630931
  callback_data: encodeTelegramCommandMenuCallback("run", start2 + offset)
630874
630932
  }]);
630875
630933
  const nav = [];
630876
630934
  nav.push({ text: "Close", callback_data: encodeTelegramCommandMenuCallback("close", 0) });
630935
+ if ((state.breadcrumbs ?? []).length > 0) nav.push({ text: "Back", callback_data: encodeTelegramCommandMenuCallback("back", 0) });
630877
630936
  if (page2 > 0) nav.push({ text: "Prev", callback_data: encodeTelegramCommandMenuCallback("page", page2 - 1) });
630878
630937
  nav.push({ text: `${page2 + 1}/${totalPages}`, callback_data: encodeTelegramCommandMenuCallback("page", page2) });
630879
630938
  if (page2 < totalPages - 1) nav.push({ text: "Next", callback_data: encodeTelegramCommandMenuCallback("page", page2 + 1) });
630880
630939
  keyboard.push(nav);
630881
- return { text: lines.join("\n"), reply_markup: { inline_keyboard: keyboard } };
630940
+ return { text: truncateTelegramMenuText(lines.join("\n")), reply_markup: { inline_keyboard: keyboard } };
630882
630941
  }
630883
630942
  function handleTelegramCommandMenuCallback(data, state, now = Date.now()) {
630884
630943
  const decoded = decodeTelegramCommandMenuCallback(data);
630885
630944
  if (!decoded) return null;
630886
630945
  if (state.expiresAt <= now) return null;
630887
630946
  if (decoded.action === "close") return { close: true };
630947
+ if (decoded.action === "back") {
630948
+ const newState = popTelegramCommandMenuState(state);
630949
+ return newState ? { newState, render: renderTelegramCommandMenu(newState) } : null;
630950
+ }
630888
630951
  if (decoded.action === "page") {
630889
630952
  const totalPages = Math.max(1, Math.ceil(state.items.length / PAGE_SIZE2));
630890
630953
  const page2 = Math.max(0, Math.min(Number.parseInt(decoded.value, 10) || 0, totalPages - 1));
@@ -630893,21 +630956,28 @@ function handleTelegramCommandMenuCallback(data, state, now = Date.now()) {
630893
630956
  }
630894
630957
  const index = Number.parseInt(decoded.value, 10);
630895
630958
  const item = Number.isFinite(index) ? state.items[index] : void 0;
630896
- return item ? { command: item.command } : null;
630959
+ if (!item) return null;
630960
+ return item.command ? { command: item.command, item } : { item };
630897
630961
  }
630898
630962
  function escapeHTML3(text) {
630899
630963
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
630900
630964
  }
630965
+ function truncateTelegramMenuText(text) {
630966
+ if (text.length <= 3900) return text;
630967
+ return `${text.slice(0, 3820)}
630968
+
630969
+ <i>... menu page clipped; use buttons to narrow this view.</i>`;
630970
+ }
630901
630971
  var CALLBACK_PREFIX2, PAGE_SIZE2, TTL_MS, MAX_CALLBACK_DATA_BYTES, GENERATIVE_COMMANDS, TelegramCommandMenuStateStore;
630902
630972
  var init_telegram_command_menu = __esm({
630903
630973
  "packages/cli/src/tui/telegram-command-menu.ts"() {
630904
630974
  "use strict";
630905
630975
  init_command_registry();
630906
630976
  CALLBACK_PREFIX2 = "ocm";
630907
- PAGE_SIZE2 = 8;
630977
+ PAGE_SIZE2 = 7;
630908
630978
  TTL_MS = 10 * 60 * 1e3;
630909
630979
  MAX_CALLBACK_DATA_BYTES = 64;
630910
- GENERATIVE_COMMANDS = /* @__PURE__ */ new Set(["image", "video", "sound", "music"]);
630980
+ GENERATIVE_COMMANDS = /* @__PURE__ */ new Set(["image", "video", "sound", "music", "models"]);
630911
630981
  TelegramCommandMenuStateStore = class {
630912
630982
  states = /* @__PURE__ */ new Map();
630913
630983
  key(chatId, messageId) {
@@ -630916,6 +630986,7 @@ var init_telegram_command_menu = __esm({
630916
630986
  create(input, now = Date.now()) {
630917
630987
  return {
630918
630988
  ...input,
630989
+ breadcrumbs: input.breadcrumbs ?? [],
630919
630990
  createdAt: now,
630920
630991
  expiresAt: now + TTL_MS
630921
630992
  };
@@ -634367,6 +634438,17 @@ import { join as join140, resolve as resolve53, basename as basename35, relative
634367
634438
  import { homedir as homedir44 } from "node:os";
634368
634439
  import { writeFile as writeFileAsync } from "node:fs/promises";
634369
634440
  import { createHash as createHash33, randomBytes as randomBytes25, randomInt } from "node:crypto";
634441
+ function formatModelBytes(bytes) {
634442
+ if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
634443
+ const units = ["B", "KB", "MB", "GB", "TB"];
634444
+ let value2 = bytes;
634445
+ let unit = 0;
634446
+ while (value2 >= 1024 && unit < units.length - 1) {
634447
+ value2 /= 1024;
634448
+ unit++;
634449
+ }
634450
+ return `${value2 >= 10 || unit === 0 ? value2.toFixed(0) : value2.toFixed(1)} ${units[unit]}`;
634451
+ }
634370
634452
  function cleanTelegramDecisionNote(value2, maxLength = 260) {
634371
634453
  if (typeof value2 !== "string") return void 0;
634372
634454
  const clean5 = stripTelegramHiddenThinking(value2).replace(/\s+/g, " ").trim();
@@ -637055,6 +637137,8 @@ Telegram link integrity contract:
637055
637137
  statsMenuPruneTimer = null;
637056
637138
  /** Telegram-native command and generative command menus */
637057
637139
  telegramCommandMenuStates = new TelegramCommandMenuStateStore();
637140
+ /** One-shot Telegram prompt intents created by model-menu "Generate" buttons. */
637141
+ telegramGenerationPromptIntents = /* @__PURE__ */ new Map();
637058
637142
  /** Command handler for admin DM slash commands (wired from interactive.ts) */
637059
637143
  commandHandler = null;
637060
637144
  /** Callback fired after a Telegram user completes the TUI-only admin auth challenge */
@@ -637992,7 +638076,7 @@ ${message2}`)
637992
638076
  return;
637993
638077
  }
637994
638078
  if (msg.guestQueryId || !isAdmin) {
637995
- const lines = items.slice(0, 24).map((item) => `${item.command} - ${item.description}`);
638079
+ const lines = items.slice(0, 24).map((item) => `${item.command ?? item.label} - ${item.description}`);
637996
638080
  const text = ["Available commands:", "", ...lines].join("\n");
637997
638081
  if (msg.guestQueryId) {
637998
638082
  await this.answerGuestQuery(msg.guestQueryId, text);
@@ -638008,9 +638092,14 @@ ${message2}`)
638008
638092
  fromUserId: msg.fromUserId ?? 0,
638009
638093
  scope,
638010
638094
  kind,
638095
+ title: kind === "generative" ? `/${commandName ?? "models"}` : void 0,
638096
+ subtitle: kind === "generative" ? "Telegram-native menu; buttons render data and tools directly here." : void 0,
638011
638097
  page: 0,
638012
638098
  items
638013
638099
  });
638100
+ await this.sendTelegramCommandMenuState(msg, previewState);
638101
+ }
638102
+ async sendTelegramCommandMenuState(msg, previewState) {
638014
638103
  const menu = renderTelegramCommandMenu(previewState);
638015
638104
  const sent = await this.apiCall("sendMessage", {
638016
638105
  chat_id: msg.chatId,
@@ -638027,6 +638116,643 @@ ${message2}`)
638027
638116
  });
638028
638117
  }
638029
638118
  }
638119
+ async editTelegramCommandMenuState(chatId, messageId, state) {
638120
+ const render2 = renderTelegramCommandMenu(state);
638121
+ this.telegramCommandMenuStates.set(state);
638122
+ await this.apiCall("editMessageText", {
638123
+ chat_id: chatId,
638124
+ message_id: messageId,
638125
+ text: render2.text,
638126
+ parse_mode: "HTML",
638127
+ reply_markup: JSON.stringify(render2.reply_markup)
638128
+ });
638129
+ }
638130
+ telegramGenerationIntentKey(chatId, fromUserId) {
638131
+ return `${String(chatId)}:${fromUserId}`;
638132
+ }
638133
+ pruneTelegramGenerationPromptIntents(now = Date.now()) {
638134
+ for (const [key, intent] of this.telegramGenerationPromptIntents) {
638135
+ if (intent.expiresAt <= now) this.telegramGenerationPromptIntents.delete(key);
638136
+ }
638137
+ }
638138
+ telegramGenerationLabel(generation) {
638139
+ if (generation === "model3d") return "3D model";
638140
+ if (generation === "cad") return "CAD";
638141
+ return generation;
638142
+ }
638143
+ telegramModelCachedBytes(dependencies) {
638144
+ return dependencies.reduce((sum, dep) => sum + measureRepoCacheBytes(dep), 0);
638145
+ }
638146
+ telegramImageModelDescriptors() {
638147
+ return imageGenerationModelPresets().map((preset) => {
638148
+ const dependencies = imagePresetDependencyModels(preset, preset.id);
638149
+ return {
638150
+ generation: "image",
638151
+ id: preset.id,
638152
+ label: preset.label,
638153
+ backend: preset.backend,
638154
+ category: preset.category ?? "Image",
638155
+ sizeClass: preset.sizeClass ?? "",
638156
+ quality: preset.quality ?? preset.note,
638157
+ note: preset.note,
638158
+ install: preset.install,
638159
+ minVramGB: preset.minVramGB,
638160
+ recommendedVramGB: preset.recommendedVramGB,
638161
+ approxDownloadGB: preset.approxDownloadGB,
638162
+ dependencies,
638163
+ cachedBytes: this.telegramModelCachedBytes(dependencies)
638164
+ };
638165
+ });
638166
+ }
638167
+ telegramAudioModelDescriptors(kind) {
638168
+ return audioGenerationModelPresets(kind).map((preset) => {
638169
+ const dependencies = [preset.id];
638170
+ return {
638171
+ generation: kind,
638172
+ id: preset.id,
638173
+ label: preset.label,
638174
+ backend: preset.backend,
638175
+ category: preset.category,
638176
+ sizeClass: preset.sizeClass,
638177
+ quality: preset.quality,
638178
+ note: preset.note,
638179
+ install: preset.install,
638180
+ minVramGB: preset.minVramGB,
638181
+ recommendedVramGB: preset.recommendedVramGB,
638182
+ approxDownloadGB: preset.approxDownloadGB,
638183
+ dependencies,
638184
+ cachedBytes: this.telegramModelCachedBytes(dependencies)
638185
+ };
638186
+ });
638187
+ }
638188
+ telegramVideoModelDescriptors() {
638189
+ return videoGenerationModelPresets().map((preset) => {
638190
+ const dependencies = [preset.id];
638191
+ return {
638192
+ generation: "video",
638193
+ id: preset.id,
638194
+ label: preset.label,
638195
+ backend: preset.backend,
638196
+ category: preset.category,
638197
+ sizeClass: preset.sizeClass,
638198
+ quality: preset.quality,
638199
+ note: preset.note,
638200
+ install: preset.install,
638201
+ minVramGB: preset.minVramGB,
638202
+ recommendedVramGB: preset.recommendedVramGB,
638203
+ approxDownloadGB: preset.approxDownloadGB,
638204
+ dependencies,
638205
+ cachedBytes: this.telegramModelCachedBytes(dependencies),
638206
+ unavailableReason: preset.gated ? "Requires Hugging Face token/license acceptance." : void 0
638207
+ };
638208
+ });
638209
+ }
638210
+ telegramCad3dModelDescriptors(generation) {
638211
+ const modality = generation === "cad" ? "cad" : "3d";
638212
+ return listMediaModelCatalog(modality).map((entry) => {
638213
+ const spec = entry.spec;
638214
+ const dependencies = [spec.repoId];
638215
+ const notes = spec.deployment.notes.join(" ");
638216
+ return {
638217
+ generation,
638218
+ id: spec.id,
638219
+ label: spec.label || spec.repoId,
638220
+ backend: spec.backend,
638221
+ category: `${spec.modality}/${spec.status}`,
638222
+ sizeClass: spec.resources.approxDownloadGB ? `~${spec.resources.approxDownloadGB}GB download` : spec.runner,
638223
+ quality: spec.hf.cardExcerpt || notes || spec.runner,
638224
+ note: notes || spec.deployment.install,
638225
+ install: spec.deployment.install,
638226
+ minVramGB: spec.resources.minVramGB,
638227
+ recommendedVramGB: spec.resources.recommendedVramGB,
638228
+ approxDownloadGB: spec.resources.approxDownloadGB,
638229
+ dependencies,
638230
+ cachedBytes: this.telegramModelCachedBytes(dependencies),
638231
+ unavailableReason: spec.deployment.runtimeCompatible ? void 0 : "Catalog metadata exists, but the runtime adapter is not wired for artifact creation."
638232
+ };
638233
+ });
638234
+ }
638235
+ telegramGenerationModelDescriptors(generation) {
638236
+ if (generation === "image") return this.telegramImageModelDescriptors();
638237
+ if (generation === "sound" || generation === "music") return this.telegramAudioModelDescriptors(generation);
638238
+ if (generation === "video") return this.telegramVideoModelDescriptors();
638239
+ return this.telegramCad3dModelDescriptors(generation);
638240
+ }
638241
+ telegramModelDescriptor(generation, id) {
638242
+ return this.telegramGenerationModelDescriptors(generation).find((model) => model.id === id);
638243
+ }
638244
+ telegramModelMenuItems(generation) {
638245
+ return this.telegramGenerationModelDescriptors(generation).map((model) => {
638246
+ const cached = model.cachedBytes > 0 ? `cached ${formatModelBytes(model.cachedBytes)}` : "not downloaded";
638247
+ const fit3 = model.recommendedVramGB ? `${model.recommendedVramGB}GB VRAM rec` : model.minVramGB ? `${model.minVramGB}GB VRAM min` : "VRAM n/a";
638248
+ return {
638249
+ label: model.label,
638250
+ description: `${model.backend} - ${model.category} - ${fit3} - ${cached}`,
638251
+ action: {
638252
+ type: "model_detail",
638253
+ generation,
638254
+ model: model.id
638255
+ }
638256
+ };
638257
+ });
638258
+ }
638259
+ telegramModelDetailBody(model) {
638260
+ const cached = model.cachedBytes > 0 ? `${formatModelBytes(model.cachedBytes)} cached` : "not downloaded";
638261
+ const deps = model.dependencies.length > 0 ? model.dependencies.join(", ") : model.id;
638262
+ return [
638263
+ `id: ${model.id}`,
638264
+ `backend: ${model.backend}`,
638265
+ `category: ${model.category}`,
638266
+ `size: ${model.sizeClass || "unknown"}`,
638267
+ `download: ${model.approxDownloadGB ? `~${model.approxDownloadGB}GB` : "unknown"}; cache: ${cached}`,
638268
+ `vram: min ${model.minVramGB ?? "?"}GB; recommended ${model.recommendedVramGB ?? "?"}GB`,
638269
+ `dependencies: ${deps}`,
638270
+ model.unavailableReason ? `runtime note: ${model.unavailableReason}` : "",
638271
+ "",
638272
+ `quality: ${model.quality}`,
638273
+ "",
638274
+ `note: ${model.note}`,
638275
+ model.install ? `
638276
+ install/prewarm: ${model.install}` : ""
638277
+ ].filter(Boolean).join("\n");
638278
+ }
638279
+ telegramModelDetailItems(model) {
638280
+ return [
638281
+ {
638282
+ label: "Generate",
638283
+ description: "Use this model for the next Telegram message you type.",
638284
+ action: { type: "await_prompt", generation: model.generation, model: model.id, backend: model.backend, label: model.label }
638285
+ },
638286
+ {
638287
+ label: "Load",
638288
+ description: "Download/prewarm or check this model in the generation runtime.",
638289
+ action: { type: "prewarm_model", generation: model.generation, model: model.id, backend: model.backend, label: model.label }
638290
+ },
638291
+ {
638292
+ label: "Delete",
638293
+ description: "Remove cached weights for this model and its adapter/base dependencies.",
638294
+ action: { type: "delete_model", generation: model.generation, model: model.id, backend: model.backend, label: model.label }
638295
+ }
638296
+ ];
638297
+ }
638298
+ async replyWithTelegramModelBrowser(msg, isAdmin, generation) {
638299
+ if (!isAdmin) {
638300
+ await this.replyToTelegramMessage(msg, "Model menus require Telegram admin authentication.");
638301
+ return;
638302
+ }
638303
+ const scope = "admin";
638304
+ const title = `${this.telegramGenerationLabel(generation)} models`;
638305
+ const cachedCount = listCachedModels().length;
638306
+ const previewState = this.telegramCommandMenuStates.create({
638307
+ chatId: msg.chatId,
638308
+ messageId: 0,
638309
+ invokerMessageId: msg.messageId,
638310
+ fromUserId: msg.fromUserId ?? 0,
638311
+ scope,
638312
+ kind: "models",
638313
+ title,
638314
+ subtitle: `${cachedCount} cached model record(s). Select a model for metadata, load, delete, or generate.`,
638315
+ page: 0,
638316
+ items: this.telegramModelMenuItems(generation)
638317
+ });
638318
+ await this.sendTelegramCommandMenuState(msg, previewState);
638319
+ }
638320
+ parseTelegramGenerationMenuKind(value2) {
638321
+ const raw = String(value2 ?? "").toLowerCase();
638322
+ if (raw === "image" || raw === "sound" || raw === "music" || raw === "video" || raw === "cad") return raw;
638323
+ if (raw === "model3d" || raw === "3d" || raw === "model") return "model3d";
638324
+ return null;
638325
+ }
638326
+ async handleTelegramCommandMenuAction(callback, state, action) {
638327
+ if (!action) return { handled: false };
638328
+ const chatId = callback.chatId;
638329
+ const messageId = callback.messageId;
638330
+ if (!chatId || !messageId) return { handled: true, answerText: "Cannot identify menu message.", alert: true };
638331
+ if (action.type === "command_detail") {
638332
+ const command = typeof action.command === "string" ? action.command : "";
638333
+ if (!command) return { handled: true, answerText: "Command metadata is missing.", alert: true };
638334
+ const body = [
638335
+ `command: ${command}`,
638336
+ "",
638337
+ typeof action.description === "string" ? action.description : "No command details available."
638338
+ ].join("\n");
638339
+ const nextState = pushTelegramCommandMenuState(state, {
638340
+ kind: "detail",
638341
+ title: command,
638342
+ subtitle: "Telegram command",
638343
+ body,
638344
+ items: [{
638345
+ label: "Run",
638346
+ command,
638347
+ description: `Execute ${command}.`,
638348
+ action: { type: "command", command }
638349
+ }]
638350
+ });
638351
+ await this.editTelegramCommandMenuState(chatId, messageId, nextState);
638352
+ return { handled: true };
638353
+ }
638354
+ if (action.type === "models") {
638355
+ const generation = this.parseTelegramGenerationMenuKind(action.generation);
638356
+ if (!generation) return { handled: true, answerText: "Unknown model menu.", alert: true };
638357
+ const nextState = pushTelegramCommandMenuState(state, {
638358
+ kind: "models",
638359
+ title: `${this.telegramGenerationLabel(generation)} models`,
638360
+ subtitle: "Select a model for metadata, load, delete, or generate.",
638361
+ items: this.telegramModelMenuItems(generation)
638362
+ });
638363
+ await this.editTelegramCommandMenuState(chatId, messageId, nextState);
638364
+ return { handled: true };
638365
+ }
638366
+ if (action.type === "setup_generation") {
638367
+ const generation = this.parseTelegramGenerationMenuKind(action.generation);
638368
+ if (!generation) return { handled: true, answerText: "Unknown setup menu.", alert: true };
638369
+ await this.answerCallbackQuery(callback.id, `Preparing ${this.telegramGenerationLabel(generation)} setup...`).catch(() => false);
638370
+ await this.replyWithTelegramGenerationSetup({
638371
+ chatId,
638372
+ text: "",
638373
+ username: callback.username,
638374
+ firstName: callback.firstName,
638375
+ messageId,
638376
+ fromUserId: callback.fromUserId,
638377
+ chatType: "private"
638378
+ }, generation);
638379
+ return { handled: true, answered: true };
638380
+ }
638381
+ if (action.type === "model_detail") {
638382
+ const generation = this.parseTelegramGenerationMenuKind(action.generation);
638383
+ const modelId = typeof action.model === "string" ? action.model : "";
638384
+ const descriptor = generation ? this.telegramModelDescriptor(generation, modelId) : void 0;
638385
+ if (!generation || !descriptor) return { handled: true, answerText: "Model metadata is no longer available.", alert: true };
638386
+ const nextState = pushTelegramCommandMenuState(state, {
638387
+ kind: "detail",
638388
+ title: descriptor.label,
638389
+ subtitle: `${this.telegramGenerationLabel(generation)} model`,
638390
+ body: this.telegramModelDetailBody(descriptor),
638391
+ items: this.telegramModelDetailItems(descriptor)
638392
+ });
638393
+ await this.editTelegramCommandMenuState(chatId, messageId, nextState);
638394
+ return { handled: true };
638395
+ }
638396
+ if (action.type === "await_prompt") {
638397
+ const generation = this.parseTelegramGenerationMenuKind(action.generation);
638398
+ const modelId = typeof action.model === "string" ? action.model : "";
638399
+ const descriptor = generation ? this.telegramModelDescriptor(generation, modelId) : void 0;
638400
+ if (!generation || !descriptor) return { handled: true, answerText: "Model metadata is no longer available.", alert: true };
638401
+ const now = Date.now();
638402
+ this.pruneTelegramGenerationPromptIntents(now);
638403
+ this.telegramGenerationPromptIntents.set(this.telegramGenerationIntentKey(chatId, callback.fromUserId), {
638404
+ chatId,
638405
+ chatType: "private",
638406
+ fromUserId: callback.fromUserId,
638407
+ username: callback.username,
638408
+ generation,
638409
+ model: descriptor.id,
638410
+ backend: descriptor.backend,
638411
+ label: descriptor.label,
638412
+ createdAt: now,
638413
+ expiresAt: now + 15 * 6e4,
638414
+ menuMessageId: messageId
638415
+ });
638416
+ const nextState = {
638417
+ ...state,
638418
+ subtitle: "Waiting for your next Telegram message.",
638419
+ body: [
638420
+ `Selected: ${descriptor.label}`,
638421
+ `Model: ${descriptor.id}`,
638422
+ "",
638423
+ `Send the prompt you want to generate. Omnius will expand it first, then run the ${this.telegramGenerationLabel(generation)} pipeline with this model.`,
638424
+ "Send /cancel to clear this pending generation."
638425
+ ].join("\n")
638426
+ };
638427
+ await this.editTelegramCommandMenuState(chatId, messageId, nextState);
638428
+ return { handled: true, answerText: "Send the prompt as your next Telegram message." };
638429
+ }
638430
+ if (action.type === "prewarm_model") {
638431
+ const generation = this.parseTelegramGenerationMenuKind(action.generation);
638432
+ const modelId = typeof action.model === "string" ? action.model : "";
638433
+ const descriptor = generation ? this.telegramModelDescriptor(generation, modelId) : void 0;
638434
+ if (!generation || !descriptor) return { handled: true, answerText: "Model metadata is no longer available.", alert: true };
638435
+ await this.answerCallbackQuery(callback.id, `Loading ${descriptor.label}...`).catch(() => false);
638436
+ await this.runTelegramGenerationPrewarm(chatId, descriptor);
638437
+ return { handled: true, answered: true };
638438
+ }
638439
+ if (action.type === "delete_model") {
638440
+ const generation = this.parseTelegramGenerationMenuKind(action.generation);
638441
+ const modelId = typeof action.model === "string" ? action.model : "";
638442
+ const descriptor = generation ? this.telegramModelDescriptor(generation, modelId) : void 0;
638443
+ if (!generation || !descriptor) return { handled: true, answerText: "Model metadata is no longer available.", alert: true };
638444
+ const message2 = await this.deleteTelegramGenerationModelWeights(descriptor);
638445
+ await this.sendMessageHTML(chatId, convertMarkdownToTelegramHTML(message2));
638446
+ return { handled: true, answerText: "Delete complete." };
638447
+ }
638448
+ return { handled: false };
638449
+ }
638450
+ async deleteTelegramGenerationModelWeights(model) {
638451
+ if (model.backend === "ollama" || model.id.startsWith("x/")) {
638452
+ const base3 = String(this.agentConfig?.backendUrl || "http://localhost:11434").replace(/\/v1\/?$/, "").replace(/\/$/, "");
638453
+ const resp = await fetch(`${base3}/api/delete`, {
638454
+ method: "DELETE",
638455
+ headers: { "Content-Type": "application/json" },
638456
+ body: JSON.stringify({ name: model.id }),
638457
+ signal: AbortSignal.timeout(3e4)
638458
+ }).catch((err) => {
638459
+ throw new Error(`Ollama delete failed: ${err instanceof Error ? err.message : String(err)}`);
638460
+ });
638461
+ if (resp.status === 404) return `No Ollama weights found for ${model.id}.`;
638462
+ if (!resp.ok) {
638463
+ const text = await resp.text().catch(() => "");
638464
+ throw new Error(`Ollama delete failed for ${model.id}: HTTP ${resp.status}${text ? ` - ${text.slice(0, 300)}` : ""}`);
638465
+ }
638466
+ return `Deleted Ollama weights for ${model.id}.`;
638467
+ }
638468
+ const results = model.dependencies.map((repo) => deleteCachedModel(repo));
638469
+ const freed = results.reduce((sum, item) => sum + item.bytesFreed, 0);
638470
+ const lines = results.map((item) => `- ${item.repo}: ${item.bytesFreed > 0 ? formatModelBytes(item.bytesFreed) : "not cached"}`);
638471
+ return [`Deleted cached model weights for ${model.label}.`, `Freed: ${formatModelBytes(freed)}`, ...lines].join("\n");
638472
+ }
638473
+ telegramCreativeRootForChat(chatId) {
638474
+ return telegramCreativeWorkspaceRoot(this.repoRoot || process.cwd(), chatId);
638475
+ }
638476
+ buildTelegramGenerationTool(root, model) {
638477
+ if (model.generation === "image") {
638478
+ return {
638479
+ tool: new ImageGenerateTool(root, this.agentConfig?.backendUrl, {
638480
+ model: model.id,
638481
+ backend: model.backend
638482
+ }),
638483
+ args: { model: model.id, backend: model.backend }
638484
+ };
638485
+ }
638486
+ if (model.generation === "sound" || model.generation === "music") {
638487
+ return {
638488
+ tool: new AudioGenerateTool(root, model.generation === "music" ? { musicModel: model.id, musicBackend: model.backend } : { soundModel: model.id, soundBackend: model.backend }),
638489
+ args: { kind: model.generation, model: model.id, backend: model.backend }
638490
+ };
638491
+ }
638492
+ if (model.generation === "video") {
638493
+ return {
638494
+ tool: new VideoGenerateTool(root, {
638495
+ model: model.id,
638496
+ backend: model.backend,
638497
+ defaultKind: "t2v"
638498
+ }),
638499
+ args: { model: model.id, backend: model.backend, kind: "t2v" }
638500
+ };
638501
+ }
638502
+ const kind = model.generation === "cad" ? "cad" : "3d";
638503
+ return {
638504
+ tool: new ModelGenerateTool(root, kind === "cad" ? { cadModel: model.id, cadBackend: model.backend } : { model3dModel: model.id, model3dBackend: model.backend }),
638505
+ args: { kind, model: model.id, backend: model.backend }
638506
+ };
638507
+ }
638508
+ attachTelegramGenerationProgress(chatId, messageId, heading, model, tool) {
638509
+ if (!messageId) return;
638510
+ const setProgress = tool.setProgressCallback;
638511
+ if (typeof setProgress !== "function") return;
638512
+ let lastEdit = 0;
638513
+ setProgress.call(tool, (event) => {
638514
+ const now = Date.now();
638515
+ if (now - lastEdit < 2500 && event.percent === void 0) return;
638516
+ lastEdit = now;
638517
+ const percent = typeof event.percent === "number" ? ` ${Math.round(event.percent)}%` : "";
638518
+ const elapsed = typeof event.elapsedMs === "number" ? `
638519
+ Elapsed: ${Math.round(event.elapsedMs / 1e3)}s` : "";
638520
+ const html = [
638521
+ `<b>${escapeTelegramHTML(heading)}</b>`,
638522
+ `Model: <code>${escapeTelegramHTML(model.id)}</code>`,
638523
+ `Stage: <code>${escapeTelegramHTML(String(event.stage || "process"))}</code>${percent}`,
638524
+ escapeTelegramHTML(String(event.message || "")),
638525
+ elapsed
638526
+ ].filter(Boolean).join("\n");
638527
+ void this.editLiveMessage(chatId, messageId, html).catch(() => false);
638528
+ });
638529
+ }
638530
+ async runTelegramGenerationPrewarm(chatId, model) {
638531
+ const root = this.telegramCreativeRootForChat(chatId);
638532
+ const { tool, args } = this.buildTelegramGenerationTool(root, model);
638533
+ const liveId = await this.sendMessageHTML(
638534
+ chatId,
638535
+ `<b>Loading ${escapeTelegramHTML(model.label)}</b>
638536
+ Model: <code>${escapeTelegramHTML(model.id)}</code>`
638537
+ );
638538
+ this.attachTelegramGenerationProgress(chatId, liveId, `Loading ${model.label}`, model, tool);
638539
+ const action = model.generation === "model3d" || model.generation === "cad" ? "check" : "prewarm";
638540
+ const result = await tool.execute({ ...args, action });
638541
+ const html = result.success ? `<b>Model load/check complete</b>
638542
+ <blockquote expandable>${escapeTelegramHTML(result.output || "Ready.")}</blockquote>` : `<b>Model load/check failed</b>
638543
+ <blockquote expandable>${escapeTelegramHTML(result.error || result.output || "Unknown failure.")}</blockquote>`;
638544
+ if (liveId) await this.editLiveMessage(chatId, liveId, html).catch(() => false);
638545
+ else await this.sendMessageHTML(chatId, html);
638546
+ }
638547
+ async expandTelegramGenerationPrompt(intent, prompt, modelId = intent.model, backend = intent.backend ?? "auto") {
638548
+ const raw = prompt.trim();
638549
+ if (!raw || !this.agentConfig) return raw;
638550
+ try {
638551
+ const llm = new OllamaAgenticBackend(
638552
+ this.agentConfig.backendUrl,
638553
+ this.agentConfig.model,
638554
+ this.agentConfig.apiKey
638555
+ );
638556
+ const system = [
638557
+ "You rewrite a user's short media-generation request into a stronger production prompt.",
638558
+ "Preserve the user's subject and intent. Add concrete sensory, compositional, timing, material, and style details only where useful.",
638559
+ "Do not add policy commentary, labels, quotes, or explanation. Output only the expanded prompt."
638560
+ ].join(" ");
638561
+ const user = [
638562
+ `Generation type: ${intent.generation}`,
638563
+ `Target model: ${modelId}`,
638564
+ `Backend: ${backend}`,
638565
+ "",
638566
+ "User prompt:",
638567
+ raw
638568
+ ].join("\n");
638569
+ const result = await this.telegramObservableInference(
638570
+ llm,
638571
+ telegramThinkSuppressedRequest({
638572
+ messages: [
638573
+ { role: "system", content: system },
638574
+ { role: "user", content: user }
638575
+ ],
638576
+ tools: [],
638577
+ temperature: 0.4,
638578
+ maxTokens: 700,
638579
+ timeoutMs: Math.min(Math.max(this.agentConfig.timeoutMs ?? 3e4, 5e3), 3e4)
638580
+ }),
638581
+ "chat-fast-path",
638582
+ `generation-prompt:${String(intent.chatId)}:${intent.fromUserId}`
638583
+ );
638584
+ const text = result.choices[0]?.message?.content;
638585
+ if (typeof text !== "string") return raw;
638586
+ const cleaned = text.replace(/^["'`]+|["'`]+$/g, "").replace(/^(?:expanded prompt|prompt|output)\s*:\s*/i, "").trim();
638587
+ return cleaned || raw;
638588
+ } catch {
638589
+ return raw;
638590
+ }
638591
+ }
638592
+ installTelegramPromptExpander(tool, intent) {
638593
+ const setExpander = tool.setPromptExpander;
638594
+ if (typeof setExpander !== "function") return;
638595
+ setExpander.call(tool, async (ctx3) => this.expandTelegramGenerationPrompt(intent, ctx3.originalPrompt, ctx3.model, ctx3.backend));
638596
+ }
638597
+ async sendTelegramGenerationArtifacts(msg, root, result) {
638598
+ const paths = /* @__PURE__ */ new Set();
638599
+ for (const path12 of result.mutatedFiles ?? []) {
638600
+ if (typeof path12 === "string" && path12.trim()) paths.add(resolve53(path12));
638601
+ }
638602
+ for (const path12 of collectGeneratedArtifactPathsFromText(result.output || "", root)) {
638603
+ paths.add(resolve53(path12));
638604
+ }
638605
+ let sent = 0;
638606
+ for (const path12 of paths) {
638607
+ if (!existsSync127(path12) || !statSync46(path12).isFile()) continue;
638608
+ const kind = classifyMedia(path12) ?? "document";
638609
+ const messageId = await this.sendMediaReference(msg.chatId, {
638610
+ original: path12,
638611
+ value: path12,
638612
+ kind,
638613
+ source: "file",
638614
+ audioAsVoice: kind === "voice"
638615
+ }, {
638616
+ replyToMessageId: msg.messageId
638617
+ }).catch(() => null);
638618
+ if (messageId !== null) sent++;
638619
+ }
638620
+ return sent;
638621
+ }
638622
+ async executeTelegramGenerationPrompt(msg, intent) {
638623
+ const descriptor = this.telegramModelDescriptor(intent.generation, intent.model) ?? {
638624
+ generation: intent.generation,
638625
+ id: intent.model,
638626
+ label: intent.label,
638627
+ backend: intent.backend || "auto",
638628
+ category: "",
638629
+ sizeClass: "",
638630
+ quality: "",
638631
+ note: "",
638632
+ cachedBytes: 0,
638633
+ dependencies: [intent.model]
638634
+ };
638635
+ const root = this.telegramCreativeRootForChat(msg.chatId);
638636
+ const { tool, args } = this.buildTelegramGenerationTool(root, descriptor);
638637
+ this.installTelegramPromptExpander(tool, intent);
638638
+ const liveId = await this.sendMessageHTML(
638639
+ msg.chatId,
638640
+ [
638641
+ `<b>${escapeTelegramHTML(this.telegramGenerationLabel(intent.generation))} generation</b>`,
638642
+ `Model: <code>${escapeTelegramHTML(intent.model)}</code>`,
638643
+ "Expanding prompt and preparing runtime..."
638644
+ ].join("\n"),
638645
+ msg.messageId
638646
+ );
638647
+ this.attachTelegramGenerationProgress(msg.chatId, liveId, `${this.telegramGenerationLabel(intent.generation)} generation`, descriptor, tool);
638648
+ const rawPrompt = msg.text.trim();
638649
+ const prompt = intent.generation === "image" || intent.generation === "video" ? rawPrompt : await this.expandTelegramGenerationPrompt(intent, rawPrompt, descriptor.id, descriptor.backend);
638650
+ const result = await tool.execute({
638651
+ ...args,
638652
+ action: "generate",
638653
+ prompt,
638654
+ expand_prompt: true
638655
+ });
638656
+ const artifactCount = result.success ? await this.sendTelegramGenerationArtifacts(msg, root, result) : 0;
638657
+ const summary = result.success ? [
638658
+ `<b>Generation complete</b>`,
638659
+ artifactCount > 0 ? `Sent ${artifactCount} artifact${artifactCount === 1 ? "" : "s"}.` : "No artifact file was detected in the tool result.",
638660
+ `<blockquote expandable>${escapeTelegramHTML(result.output || result.llmContent || "Done.")}</blockquote>`
638661
+ ].join("\n") : [
638662
+ `<b>Generation failed</b>`,
638663
+ `<blockquote expandable>${escapeTelegramHTML(result.error || result.output || "Unknown failure.")}</blockquote>`
638664
+ ].join("\n");
638665
+ if (liveId) await this.editLiveMessage(msg.chatId, liveId, summary).catch(() => false);
638666
+ else await this.sendMessageHTML(msg.chatId, summary, msg.messageId);
638667
+ }
638668
+ async maybeHandleTelegramGenerationPrompt(msg) {
638669
+ this.pruneTelegramGenerationPromptIntents();
638670
+ const key = this.telegramGenerationIntentKey(msg.chatId, msg.fromUserId);
638671
+ const intent = this.telegramGenerationPromptIntents.get(key);
638672
+ if (!intent) return false;
638673
+ if (msg.text.trim().toLowerCase() === "/cancel") {
638674
+ this.telegramGenerationPromptIntents.delete(key);
638675
+ await this.replyToTelegramMessage(msg, "Pending generation cleared.");
638676
+ return true;
638677
+ }
638678
+ if (msg.text.trim().startsWith("/")) return false;
638679
+ this.telegramGenerationPromptIntents.delete(key);
638680
+ await this.executeTelegramGenerationPrompt(msg, intent);
638681
+ return true;
638682
+ }
638683
+ telegramSlashGenerationKind(name10) {
638684
+ if (name10 === "image") return "image";
638685
+ if (name10 === "sound") return "sound";
638686
+ if (name10 === "music") return "music";
638687
+ if (name10 === "video") return "video";
638688
+ return null;
638689
+ }
638690
+ async replyWithTelegramGenerationSetup(msg, generation) {
638691
+ const root = this.telegramCreativeRootForChat(msg.chatId);
638692
+ const settings = resolveSettings(this.repoRoot || process.cwd());
638693
+ let tool;
638694
+ let args;
638695
+ if (generation === "image") {
638696
+ tool = new ImageGenerateTool(root, this.agentConfig?.backendUrl, this.imageGenerationDefaultsForRepo(this.repoRoot || process.cwd()));
638697
+ args = { action: "setup", model: settings.imageModel, backend: settings.imageBackend };
638698
+ } else if (generation === "sound" || generation === "music") {
638699
+ tool = new AudioGenerateTool(root, this.audioGenerationDefaultsForRepo(this.repoRoot || process.cwd()));
638700
+ args = {
638701
+ action: "setup",
638702
+ kind: generation,
638703
+ model: generation === "music" ? settings.musicModel : settings.soundModel,
638704
+ backend: generation === "music" ? settings.musicBackend : settings.soundBackend
638705
+ };
638706
+ } else if (generation === "video") {
638707
+ tool = new VideoGenerateTool(root, this.videoGenerationDefaultsForRepo(this.repoRoot || process.cwd()));
638708
+ args = { action: "setup", model: settings.videoModel, backend: settings.videoBackend };
638709
+ } else {
638710
+ tool = new ModelGenerateTool(root, this.modelGenerationDefaultsForRepo(this.repoRoot || process.cwd()));
638711
+ args = { action: "list_models", kind: generation === "cad" ? "cad" : "3d" };
638712
+ }
638713
+ const result = await tool.execute(args);
638714
+ const html = result.success ? `<b>${escapeTelegramHTML(this.telegramGenerationLabel(generation))} setup</b>
638715
+ <blockquote expandable>${escapeTelegramHTML(result.output || "No setup output.")}</blockquote>` : `<b>${escapeTelegramHTML(this.telegramGenerationLabel(generation))} setup failed</b>
638716
+ <blockquote expandable>${escapeTelegramHTML(result.error || result.output || "Unknown failure.")}</blockquote>`;
638717
+ await this.replyToTelegramMessage(msg, html, { html: true });
638718
+ }
638719
+ async handleTelegramGenerationSlashCommand(msg, isAdmin, normalizedCommandText) {
638720
+ const trimmed = normalizedCommandText.trim();
638721
+ if (!trimmed.startsWith("/")) return false;
638722
+ const [rawName = "", rawSub = ""] = trimmed.split(/\s+/);
638723
+ const name10 = rawName.slice(1).split("@")[0]?.toLowerCase() ?? "";
638724
+ const sub = rawSub.toLowerCase();
638725
+ if (name10 === "models") {
638726
+ if (!sub) {
638727
+ await this.replyWithTelegramCommandMenu(msg, isAdmin, "generative", "models");
638728
+ return true;
638729
+ }
638730
+ if (sub === "3d" || sub === "cad") {
638731
+ await this.replyWithTelegramModelBrowser(msg, isAdmin, sub === "cad" ? "cad" : "model3d");
638732
+ return true;
638733
+ }
638734
+ return false;
638735
+ }
638736
+ const generation = this.telegramSlashGenerationKind(name10);
638737
+ if (!generation) return false;
638738
+ if (!sub) {
638739
+ await this.replyWithTelegramCommandMenu(msg, isAdmin, "generative", name10);
638740
+ return true;
638741
+ }
638742
+ if (sub === "list" || sub === "models" || sub === "menu") {
638743
+ await this.replyWithTelegramModelBrowser(msg, isAdmin, generation);
638744
+ return true;
638745
+ }
638746
+ if (sub === "setup") {
638747
+ if (!isAdmin) {
638748
+ await this.replyToTelegramMessage(msg, "Generation setup requires Telegram admin authentication.");
638749
+ return true;
638750
+ }
638751
+ await this.replyWithTelegramGenerationSetup(msg, generation);
638752
+ return true;
638753
+ }
638754
+ return false;
638755
+ }
638030
638756
  collectSessionMetricsSnapshot() {
638031
638757
  if (this._metricsProvider) {
638032
638758
  try {
@@ -643619,6 +644345,9 @@ ${summary}` : ""
643619
644345
  return;
643620
644346
  }
643621
644347
  const isAdmin = this.isAdminUser(msg);
644348
+ if (await this.maybeHandleTelegramGenerationPrompt(msg)) {
644349
+ return;
644350
+ }
643622
644351
  if (msg.text.trim().startsWith("/") && this.isTelegramCommandsMenuCommand(normalizedCommandText)) {
643623
644352
  await this.replyWithTelegramCommandMenu(msg, isAdmin, "commands");
643624
644353
  return;
@@ -643632,6 +644361,9 @@ ${summary}` : ""
643632
644361
  return;
643633
644362
  }
643634
644363
  const telegramSlash = this.telegramSlashName(normalizedCommandText);
644364
+ if (msg.text.trim().startsWith("/") && await this.handleTelegramGenerationSlashCommand(msg, isAdmin, normalizedCommandText)) {
644365
+ return;
644366
+ }
643635
644367
  if (msg.text.trim().startsWith("/") && TELEGRAM_REFLECTION_SLASH_COMMANDS.has(telegramSlash)) {
643636
644368
  await this.handleTelegramReflectionSlash(msg, normalizedCommandText);
643637
644369
  return;
@@ -646495,6 +647227,15 @@ Scoped workspace: ${scopedRoot}`,
646495
647227
  });
646496
647228
  return;
646497
647229
  }
647230
+ if (result.item?.action && result.item.action.type !== "command") {
647231
+ const actionResult = await this.handleTelegramCommandMenuAction(callback, menuState, result.item.action);
647232
+ if (actionResult.handled) {
647233
+ if (actionResult.answered) answered = true;
647234
+ if (actionResult.answerText) answerText2 = actionResult.answerText;
647235
+ if (actionResult.alert) alert2 = true;
647236
+ return;
647237
+ }
647238
+ }
646498
647239
  if (result.command) {
646499
647240
  if (!this.commandHandler) {
646500
647241
  answerText2 = "No command handler is available.";
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.199",
3
+ "version": "1.0.200",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.199",
9
+ "version": "1.0.200",
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.199",
3
+ "version": "1.0.200",
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",