omnius 1.0.467 → 1.0.468

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
@@ -14235,6 +14235,65 @@ function findMatchOffsets(haystack, needle) {
14235
14235
  }
14236
14236
  return offsets;
14237
14237
  }
14238
+ function lineNumberAtOffset(haystack, offset) {
14239
+ return haystack.slice(0, offset).split("\n").length;
14240
+ }
14241
+ function findLineEndWhitespaceEquivalentSpans(haystack, needle) {
14242
+ const normalizedNeedle = normalizeLineEndWhitespaceWithMap(needle).text;
14243
+ if (normalizedNeedle.length === 0)
14244
+ return [];
14245
+ const normalizedHaystack = normalizeLineEndWhitespaceWithMap(haystack);
14246
+ const spans = [];
14247
+ let pos = 0;
14248
+ while ((pos = normalizedHaystack.text.indexOf(normalizedNeedle, pos)) !== -1) {
14249
+ const normalizedEnd = pos + normalizedNeedle.length;
14250
+ const start2 = normalizedHaystack.map[pos];
14251
+ const end = normalizedEnd < normalizedHaystack.map.length ? normalizedHaystack.map[normalizedEnd] : haystack.length;
14252
+ if (start2 !== void 0 && end >= start2) {
14253
+ const text2 = haystack.slice(start2, end);
14254
+ if (text2 !== needle) {
14255
+ spans.push({ start: start2, end, text: text2 });
14256
+ }
14257
+ }
14258
+ pos += Math.max(1, normalizedNeedle.length);
14259
+ }
14260
+ return spans;
14261
+ }
14262
+ function normalizeLineEndWhitespaceWithMap(value2) {
14263
+ const chars = [];
14264
+ const map2 = [];
14265
+ for (let i2 = 0; i2 < value2.length; ) {
14266
+ const ch = value2[i2];
14267
+ if (ch === " " || ch === " ") {
14268
+ let j = i2 + 1;
14269
+ while (j < value2.length && (value2[j] === " " || value2[j] === " ")) {
14270
+ j++;
14271
+ }
14272
+ const next = value2[j];
14273
+ if (j >= value2.length || next === "\n" || next === "\r") {
14274
+ i2 = j;
14275
+ continue;
14276
+ }
14277
+ for (let k = i2; k < j; k++) {
14278
+ chars.push(value2[k]);
14279
+ map2.push(k);
14280
+ }
14281
+ i2 = j;
14282
+ continue;
14283
+ }
14284
+ chars.push(ch);
14285
+ map2.push(i2);
14286
+ i2++;
14287
+ }
14288
+ return { text: chars.join(""), map: map2 };
14289
+ }
14290
+ function replaceSpans(content, spans, replacement) {
14291
+ let updated = content;
14292
+ for (const span of [...spans].sort((a2, b) => b.start - a2.start)) {
14293
+ updated = updated.slice(0, span.start) + replacement + updated.slice(span.end);
14294
+ }
14295
+ return updated;
14296
+ }
14238
14297
  function replaceAllOccurrences(haystack, needle, replacement) {
14239
14298
  return haystack.split(needle).join(replacement);
14240
14299
  }
@@ -14419,7 +14478,17 @@ var init_file_edit = __esm({
14419
14478
  afterHash: beforeHash
14420
14479
  };
14421
14480
  }
14422
- const occurrences = countOccurrences(content, oldString);
14481
+ let occurrences = countOccurrences(content, oldString);
14482
+ let whitespaceAdjustedMatches = null;
14483
+ let diffOldString = oldString;
14484
+ if (occurrences === 0 && expectedHash) {
14485
+ const matches = findLineEndWhitespaceEquivalentSpans(content, oldString);
14486
+ if (matches.length > 0) {
14487
+ occurrences = matches.length;
14488
+ whitespaceAdjustedMatches = matches;
14489
+ diffOldString = matches[0]?.text ?? oldString;
14490
+ }
14491
+ }
14423
14492
  if (occurrences === 0) {
14424
14493
  const alreadyAppliedLines = newString.length > 0 ? findMatchLines(content, newString) : [];
14425
14494
  if (alreadyAppliedLines.length > 0) {
@@ -14471,18 +14540,19 @@ Use the EXACT current content above to construct a working old_string. Do not re
14471
14540
  };
14472
14541
  }
14473
14542
  if (!replaceAll && occurrences > 1) {
14474
- const matchLines = findMatchLines(content, oldString);
14475
- const offsets = findMatchOffsets(content, oldString);
14543
+ const matchLines = whitespaceAdjustedMatches ? whitespaceAdjustedMatches.map((match) => lineNumberAtOffset(content, match.start)) : findMatchLines(content, oldString);
14544
+ const offsets = whitespaceAdjustedMatches ? whitespaceAdjustedMatches.map((match) => match.start) : findMatchOffsets(content, oldString);
14476
14545
  const snippets = offsets.slice(0, 4).map((off) => {
14477
14546
  const s2 = snippetAtOffset(content, off, 3);
14478
14547
  return `
14479
14548
  --- match at line ${s2.lineNumber} ---
14480
14549
  ${s2.content}`;
14481
14550
  }).join("\n");
14551
+ const reason = whitespaceAdjustedMatches ? `old_string is not unique after ignoring trailing spaces/tabs at line ends — found ${occurrences} occurrences at lines ${matchLines.join(", ")}.` : `old_string is not unique — found ${occurrences} occurrences at lines ${matchLines.join(", ")}.`;
14482
14552
  return {
14483
14553
  success: false,
14484
14554
  output: "",
14485
- error: `old_string is not unique — found ${occurrences} occurrences at lines ${matchLines.join(", ")}.
14555
+ error: `${reason}
14486
14556
  ${snippets}
14487
14557
 
14488
14558
  Add UNIQUE surrounding context (a function name, distinctive comment, or unique line above/below) to disambiguate. Or set replace_all=true if you want all ${occurrences} occurrences replaced identically.`,
@@ -14504,16 +14574,27 @@ Add UNIQUE surrounding context (a function name, distinctive comment, or unique
14504
14574
  let updated;
14505
14575
  let editedLines;
14506
14576
  if (replaceAll) {
14507
- editedLines = findMatchLines(content, oldString);
14508
- updated = replaceAllOccurrences(content, oldString, newString);
14577
+ if (whitespaceAdjustedMatches) {
14578
+ editedLines = whitespaceAdjustedMatches.map((match) => lineNumberAtOffset(content, match.start));
14579
+ updated = replaceSpans(content, whitespaceAdjustedMatches, newString);
14580
+ } else {
14581
+ editedLines = findMatchLines(content, oldString);
14582
+ updated = replaceAllOccurrences(content, oldString, newString);
14583
+ }
14509
14584
  } else {
14510
- const index = content.indexOf(oldString);
14511
- const lineNumber = content.slice(0, index).split("\n").length;
14512
- editedLines = [lineNumber];
14513
- updated = content.slice(0, index) + newString + content.slice(index + oldString.length);
14585
+ if (whitespaceAdjustedMatches) {
14586
+ const match = whitespaceAdjustedMatches[0];
14587
+ editedLines = [lineNumberAtOffset(content, match.start)];
14588
+ updated = content.slice(0, match.start) + newString + content.slice(match.end);
14589
+ } else {
14590
+ const index = content.indexOf(oldString);
14591
+ const lineNumber = content.slice(0, index).split("\n").length;
14592
+ editedLines = [lineNumber];
14593
+ updated = content.slice(0, index) + newString + content.slice(index + oldString.length);
14594
+ }
14514
14595
  }
14515
14596
  const afterHash = contentHash(updated);
14516
- const diff = buildCompactDiff(oldString, newString);
14597
+ const diff = buildCompactDiff(diffOldString, newString);
14517
14598
  if (afterHash === beforeHash) {
14518
14599
  return {
14519
14600
  success: true,
@@ -14529,9 +14610,10 @@ Add UNIQUE surrounding context (a function name, distinctive comment, or unique
14529
14610
  }
14530
14611
  if (dryRun) {
14531
14612
  const linesInfo2 = editedLines.length === 1 ? `line ${editedLines[0]}` : `${editedLines.length} locations (lines ${editedLines.join(", ")})`;
14613
+ const matchNote2 = whitespaceAdjustedMatches ? " Matched by verified line-ending whitespace normalization." : "";
14532
14614
  return {
14533
14615
  success: true,
14534
- output: `[DRY RUN] file_edit validated for ${filePath} at ${linesInfo2}. File NOT modified. Call again with dry_run=false to apply.
14616
+ output: `[DRY RUN] file_edit validated for ${filePath} at ${linesInfo2}. File NOT modified. Call again with dry_run=false to apply.${matchNote2}
14535
14617
 
14536
14618
  ${diff}`,
14537
14619
  durationMs: performance.now() - start2,
@@ -14552,10 +14634,11 @@ ${diff}`,
14552
14634
  diff
14553
14635
  });
14554
14636
  const linesInfo = editedLines.length === 1 ? `line ${editedLines[0]}` : `${editedLines.length} locations (lines ${editedLines.join(", ")})`;
14555
- const lineNumberedDiff = buildLineNumberedDiff(oldString, newString, editedLines[0] ?? 1);
14637
+ const lineNumberedDiff = buildLineNumberedDiff(diffOldString, newString, editedLines[0] ?? 1);
14638
+ const matchNote = whitespaceAdjustedMatches ? " (matched by verified line-ending whitespace normalization)" : "";
14556
14639
  return {
14557
14640
  success: true,
14558
- output: `Edited ${filePath} at ${linesInfo} (sha256 ${beforeHash} → ${afterHash})
14641
+ output: `Edited ${filePath} at ${linesInfo}${matchNote} (sha256 ${beforeHash} → ${afterHash})
14559
14642
  ${lineNumberedDiff}`,
14560
14643
  durationMs: performance.now() - start2,
14561
14644
  mutated: true,
@@ -28885,12 +28968,82 @@ var init_file_patch = __esm({
28885
28968
  description: "Preview the diff without writing. Returns what would change. Default: false"
28886
28969
  }
28887
28970
  },
28888
- required: ["path", "start_line"]
28971
+ required: ["path"],
28972
+ allOf: [
28973
+ {
28974
+ if: { properties: { mode: { const: "delete" } }, required: ["mode"] },
28975
+ then: { required: ["start_line", "end_line"] }
28976
+ },
28977
+ {
28978
+ if: { properties: { mode: { const: "replace" } }, required: ["mode"] },
28979
+ then: { required: ["start_line", "end_line"] }
28980
+ },
28981
+ {
28982
+ if: { properties: { mode: { const: "insert_before" } }, required: ["mode"] },
28983
+ then: { required: ["start_line"] }
28984
+ },
28985
+ {
28986
+ if: { properties: { mode: { const: "insert_after" } }, required: ["mode"] },
28987
+ then: { required: ["start_line"] }
28988
+ }
28989
+ ]
28889
28990
  };
28890
28991
  workingDir;
28891
28992
  constructor(workingDir) {
28892
28993
  this.workingDir = workingDir;
28893
28994
  }
28995
+ validateInput(args) {
28996
+ if (args["operations"] !== void 0) {
28997
+ return {
28998
+ result: false,
28999
+ message: `file_patch accepts one line operation per call; do not pass operations. For deletion use: {"path":"...","mode":"delete","start_line":8,"end_line":13,"expected_hash":"..."}. For replacement use: {"path":"...","mode":"replace","start_line":8,"end_line":13,"new_content":"...","expected_hash":"..."}.`
29000
+ };
29001
+ }
29002
+ if (typeof args["path"] !== "string" || !args["path"].trim()) {
29003
+ return { result: false, message: "file_patch requires non-empty path." };
29004
+ }
29005
+ const mode = typeof args["mode"] === "string" ? args["mode"] : "replace";
29006
+ if (!["replace", "insert_before", "insert_after", "delete"].includes(mode)) {
29007
+ return {
29008
+ result: false,
29009
+ message: `file_patch mode="${String(args["mode"])}" is invalid. Use replace, insert_before, insert_after, or delete.`
29010
+ };
29011
+ }
29012
+ if (!Number.isInteger(args["start_line"]) || Number(args["start_line"]) < 1) {
29013
+ return {
29014
+ result: false,
29015
+ message: `file_patch requires start_line as a positive 1-based integer. For deleting lines, include mode="delete", start_line, end_line, and expected_hash.`
29016
+ };
29017
+ }
29018
+ const hasEndLine = args["end_line"] !== void 0 && args["end_line"] !== null;
29019
+ const hasNewContent = args["new_content"] !== void 0 || args["newContent"] !== void 0 || args["new_content_base64"] !== void 0 || args["newContentBase64"] !== void 0;
29020
+ const hasExpectedTarget = args["expected_hash"] !== void 0 || args["expectedHash"] !== void 0 || args["expected_old_content"] !== void 0;
29021
+ if ((mode === "replace" || mode === "delete") && !hasEndLine) {
29022
+ return {
29023
+ result: false,
29024
+ message: `file_patch mode=${mode} requires end_line. For deletion use mode="delete" with start_line and end_line; for replacement include end_line and new_content.`
29025
+ };
29026
+ }
29027
+ if ((mode === "replace" || mode === "insert_before" || mode === "insert_after") && !hasNewContent && args["allow_empty_content"] !== true) {
29028
+ return {
29029
+ result: false,
29030
+ message: `file_patch mode=${mode} requires new_content or new_content_base64. If the intended action is removal, use mode="delete" with start_line and end_line instead.`
29031
+ };
29032
+ }
29033
+ if ((mode === "replace" || mode === "delete") && !hasExpectedTarget) {
29034
+ return {
29035
+ result: false,
29036
+ message: `file_patch mode=${mode} requires expected_hash from file_read or expected_old_content copied from the target lines.`
29037
+ };
29038
+ }
29039
+ if ((mode === "insert_before" || mode === "insert_after") && args["expected_hash"] === void 0 && args["expectedHash"] === void 0) {
29040
+ return {
29041
+ result: false,
29042
+ message: `file_patch mode=${mode} requires expected_hash from the most recent file_read so line numbers are versioned.`
29043
+ };
29044
+ }
29045
+ return { result: true };
29046
+ }
28894
29047
  async execute(args) {
28895
29048
  const filePath = args["path"];
28896
29049
  const startLine = args["start_line"];
@@ -577921,6 +578074,9 @@ import { join as _pathJoin, relative as _pathRelative, resolve as _pathResolve }
577921
578074
  import { tmpdir as _osTmpdir } from "node:os";
577922
578075
  import { homedir as _osHomedir } from "node:os";
577923
578076
  import { z as z17 } from "zod";
578077
+ function cleanToolActionReasonField(value2) {
578078
+ return String(value2 ?? "").replace(/\s+/g, " ").trim();
578079
+ }
577924
578080
  function parsePersistentMemoryMode(value2) {
577925
578081
  if (value2 === "full" || value2 === "deferred" || value2 === "off")
577926
578082
  return value2;
@@ -594031,7 +594187,7 @@ ${marker}` : marker);
594031
594187
  try {
594032
594188
  raw = JSON.parse(trimmed);
594033
594189
  } catch {
594034
- return null;
594190
+ return { intent: trimmed };
594035
594191
  }
594036
594192
  }
594037
594193
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
@@ -594048,8 +594204,9 @@ ${marker}` : marker);
594048
594204
  }
594049
594205
  _toolActionReasonForCall(toolName, args) {
594050
594206
  const explicit = this._extractToolActionReason(args);
594051
- if (explicit)
594052
- return explicit;
594207
+ if (explicit) {
594208
+ return this._completeToolActionReason(toolName, args, explicit);
594209
+ }
594053
594210
  if (this._shouldSynthesizeMissingToolActionReason(toolName, args)) {
594054
594211
  return this._synthesizeStateUpdateToolActionReason(toolName, args);
594055
594212
  }
@@ -594057,6 +594214,48 @@ ${marker}` : marker);
594057
594214
  return null;
594058
594215
  return this._synthesizeReadOnlyToolActionReason(toolName, args);
594059
594216
  }
594217
+ _completeToolActionReason(toolName, args, partial) {
594218
+ const canonical = this.lookupRegisteredTool(toolName)?.name ?? toolName;
594219
+ const goal = this._taskState.currentStep || this._taskState.nextAction || this._taskState.goal || this._taskState.originalGoal || "current task";
594220
+ const targetPaths = this._extractToolTargetPaths(canonical, args).slice(0, 3);
594221
+ const targetText = targetPaths.length > 0 ? ` for ${targetPaths.join(", ")}` : "";
594222
+ const scope = TOOL_ACTION_REASON_SCOPES.has(String(partial.scope ?? "")) ? String(partial.scope) : this._defaultToolActionReasonScope(canonical);
594223
+ return {
594224
+ task_anchor: cleanToolActionReasonField(partial.task_anchor) || String(goal).replace(/\s+/g, " ").trim().slice(0, 160),
594225
+ intent: cleanToolActionReasonField(partial.intent) || `Run ${canonical}${targetText} for the active task.`,
594226
+ evidence: cleanToolActionReasonField(partial.evidence) || "Runtime completed partial public action metadata from the tool call contract before execution.",
594227
+ expected_result: cleanToolActionReasonField(partial.expected_result) || this._defaultToolActionExpectedResult(canonical, targetText),
594228
+ scope
594229
+ };
594230
+ }
594231
+ _defaultToolActionReasonScope(toolName) {
594232
+ if (toolName === "file_edit" || toolName === "file_patch" || toolName === "batch_edit") {
594233
+ return "targeted_patch";
594234
+ }
594235
+ if (toolName === "create_structured_file")
594236
+ return "new_file";
594237
+ if (toolName === "task_complete")
594238
+ return "completion";
594239
+ if (READ_ONLY_ACTION_REASON_OPTIONAL_TOOLS.has(toolName))
594240
+ return "discovery";
594241
+ return "other";
594242
+ }
594243
+ _defaultToolActionExpectedResult(toolName, targetText) {
594244
+ switch (toolName) {
594245
+ case "file_edit":
594246
+ return `Requested exact edit is applied${targetText}, or a precise edit error is returned.`;
594247
+ case "file_patch":
594248
+ return `Requested line patch is applied${targetText}, or a precise patch error is returned.`;
594249
+ case "batch_edit":
594250
+ return `Requested edit batch is applied${targetText}, or per-edit failure evidence is returned.`;
594251
+ case "file_write":
594252
+ return `Requested file content is written${targetText}, or a precise write error is returned.`;
594253
+ case "shell":
594254
+ return "Command exits with output evidence for the next decision.";
594255
+ default:
594256
+ return `${toolName} completes and returns success or failure evidence.`;
594257
+ }
594258
+ }
594060
594259
  _shouldSynthesizeMissingToolActionReason(toolName, _args) {
594061
594260
  if (this._toolActionReasonPolicy(toolName, _args) === "disabled") {
594062
594261
  return false;
@@ -594107,24 +594306,13 @@ ${marker}` : marker);
594107
594306
  `scope must be one of: ${Array.from(TOOL_ACTION_REASON_SCOPES).join(", ")}.`
594108
594307
  ].join("\n");
594109
594308
  }
594110
- const reason = this._extractToolActionReason(args);
594111
- if (!reason) {
594309
+ const partialReason = this._extractToolActionReason(args);
594310
+ if (!partialReason) {
594112
594311
  if (policy === "optional")
594113
594312
  return null;
594114
594313
  return "[TOOL ACTION REASON CONTRACT] action_reason must be an object with compact public task-state fields.";
594115
594314
  }
594116
- const missing = [
594117
- "task_anchor",
594118
- "intent",
594119
- "evidence",
594120
- "expected_result",
594121
- "scope"
594122
- ].filter((key) => reason[key].length < 3);
594123
- if (missing.length > 0) {
594124
- if (policy === "optional")
594125
- return null;
594126
- return `[TOOL ACTION REASON CONTRACT] action_reason missing non-empty field(s): ${missing.join(", ")}.`;
594127
- }
594315
+ const reason = this._completeToolActionReason(toolName, args, partialReason);
594128
594316
  if (!TOOL_ACTION_REASON_SCOPES.has(reason.scope)) {
594129
594317
  if (policy === "optional")
594130
594318
  return null;
@@ -688075,7 +688263,7 @@ function renderTelegramSubAgentError(username, error) {
688075
688263
  `${c3.red("✘")} ${c3.bold(`@${username}`)}: ${c3.dim(preview)}`
688076
688264
  );
688077
688265
  }
688078
- 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, TELEGRAM_EVIDENCE_SUFFICIENCY_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT, TELEGRAM_LINK_INTEGRITY_CONTRACT, TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT, TELEGRAM_INTERACTION_DECISION_MINIMAL_SCHEMA, TELEGRAM_INTERACTION_DECISION_REPAIR_SCHEMA, TELEGRAM_CHAT_REPLY_RESPONSE_FORMAT, TELEGRAM_SPACED_URL_RE, TELEGRAM_HTTP_URL_RE, 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_FAST_OPTIONS, TELEGRAM_ADMIN_EVIDENCE_OPTIONS, TELEGRAM_SUB_AGENT_DEFAULT_LIMIT, TELEGRAM_SUB_AGENT_MAX_LIMIT, TELEGRAM_SUB_AGENT_BURST_CONTEXT_LIMIT, TELEGRAM_ADMIN_LIVE_PANEL_PAGES, TELEGRAM_ADMIN_LIVE_MUTATION_TOOLS, 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_DEFAULT_LONG_POLL_TIMEOUT_SECONDS, TELEGRAM_ROUTER_AUTO_MIN_PARAMETERS_B, TELEGRAM_PUBLIC_TOOL_QUOTAS, TelegramBridge;
688266
+ 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, TELEGRAM_EVIDENCE_SUFFICIENCY_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_EXTERNAL_ACQUISITION_CONTRACT, TELEGRAM_LINK_INTEGRITY_CONTRACT, TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT, TELEGRAM_INTERACTION_DECISION_MINIMAL_SCHEMA, TELEGRAM_INTERACTION_DECISION_REPAIR_SCHEMA, TELEGRAM_CHAT_REPLY_RESPONSE_FORMAT, TELEGRAM_SPACED_URL_RE, TELEGRAM_HTTP_URL_RE, 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_FAST_OPTIONS, TELEGRAM_ADMIN_EVIDENCE_OPTIONS, TELEGRAM_SUB_AGENT_DEFAULT_LIMIT, TELEGRAM_SUB_AGENT_MAX_LIMIT, TELEGRAM_SUB_AGENT_BURST_CONTEXT_LIMIT, TELEGRAM_ADMIN_LIVE_PANEL_PAGES, TELEGRAM_ADMIN_LIVE_MUTATION_TOOLS, 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_DEFAULT_LONG_POLL_TIMEOUT_SECONDS, TELEGRAM_PUBLIC_TOOL_QUOTAS, TelegramBridge;
688079
688267
  var init_telegram_bridge = __esm({
688080
688268
  "packages/cli/src/tui/telegram-bridge.ts"() {
688081
688269
  "use strict";
@@ -688603,7 +688791,6 @@ Telegram link integrity contract:
688603
688791
  "message_reaction_count"
688604
688792
  ];
688605
688793
  TELEGRAM_DEFAULT_LONG_POLL_TIMEOUT_SECONDS = 50;
688606
- TELEGRAM_ROUTER_AUTO_MIN_PARAMETERS_B = 8;
688607
688794
  TELEGRAM_PUBLIC_TOOL_QUOTAS = {
688608
688795
  web: { limit: 20, windowMs: 60 * 6e4 },
688609
688796
  media: { limit: 30, windowMs: 60 * 6e4 },
@@ -688658,7 +688845,6 @@ Telegram link integrity contract:
688658
688845
  pollLoopPromise = null;
688659
688846
  pollFatalNotified = false;
688660
688847
  lastUpdateId = 0;
688661
- telegramRouterModelCache = null;
688662
688848
  /**
688663
688849
  * Snapshot of the main agent inference config captured at construction. The
688664
688850
  * effective `agentConfig` is this base overlaid with the Telegram-isolated
@@ -688909,7 +689095,6 @@ Telegram link integrity contract:
688909
689095
  ...next.backendUrl !== void 0 ? { apiKey: next.apiKey ?? "" } : {}
688910
689096
  };
688911
689097
  this.agentConfig = effective;
688912
- this.telegramRouterModelCache = null;
688913
689098
  return effective;
688914
689099
  }
688915
689100
  /** The Telegram-isolated inference override currently in effect (if any). */
@@ -689703,9 +689888,17 @@ No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code
689703
689888
  this.refreshActiveTelegramInteractionCount();
689704
689889
  return queued;
689705
689890
  }
689891
+ telegramMessageExplicitlyAddressesBot(msg) {
689892
+ if (this.telegramMessageRepliesToBot(msg)) return true;
689893
+ const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
689894
+ if (!bot) return false;
689895
+ return (msg.mentionedUsernames ?? []).some(
689896
+ (name10) => name10.trim().replace(/^@/, "").toLowerCase() === bot
689897
+ );
689898
+ }
689706
689899
  shouldFailOpenTelegramRouterUnavailable(msg, toolContext) {
689707
689900
  if (msg.isBot) return false;
689708
- return toolContext === "telegram-admin-dm" || msg.chatType === "private";
689901
+ return toolContext === "telegram-admin-dm" || msg.chatType === "private" || this.telegramMessageExplicitlyAddressesBot(msg);
689709
689902
  }
689710
689903
  buildTelegramRouterUnavailableDecision(msg, toolContext, params) {
689711
689904
  const forcedRoute = this.interactionMode === "chat" || this.interactionMode === "action" ? this.interactionMode : null;
@@ -689718,9 +689911,9 @@ No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code
689718
689911
  route,
689719
689912
  shouldReply: failOpen,
689720
689913
  confidence: failOpen ? 0.55 : 0,
689721
- reason: failOpen ? `${params.reason}; direct private/admin delivery uses degraded visible reply instead of silent halt` : params.reason,
689914
+ reason: failOpen ? `${params.reason}; direct/high-salience delivery uses degraded visible reply instead of silent halt` : params.reason,
689722
689915
  source: "inference-unavailable",
689723
- silentDisposition: failOpen ? "router unavailable; attempting a visible degraded reply for a direct private/admin message" : params.silentDisposition ?? "retained as context without replying because the router decision could not be derived",
689916
+ silentDisposition: failOpen ? "router unavailable; attempting a visible degraded reply for a direct/high-salience message" : params.silentDisposition ?? "retained as context without replying because the router decision could not be derived",
689724
689917
  diagnosticNote: params.diagnosticNote,
689725
689918
  raw: params.raw
689726
689919
  };
@@ -695319,90 +695512,9 @@ ${retryText}`,
695319
695512
  this.dispatchQueuedTelegramSessionWorkSoon();
695320
695513
  }
695321
695514
  }
695322
- telegramRouterAutoModelEnabled() {
695323
- const raw = (process.env["OMNIUS_TG_ROUTER_AUTO_MODEL"] ?? "").trim().toLowerCase();
695324
- return raw === "1" || raw === "true" || raw === "on";
695325
- }
695326
- telegramRouterCandidateModels() {
695327
- const raw = (process.env["OMNIUS_TG_ROUTER_MODEL_CANDIDATES"] ?? "").trim();
695328
- const candidates = raw ? raw.split(/[,\s]+/).map((part) => part.trim()).filter(Boolean) : [];
695329
- return Array.from(new Set(candidates));
695330
- }
695331
- telegramRouterAllowThinkHeavyAutoModels() {
695332
- const raw = (process.env["OMNIUS_TG_ROUTER_ALLOW_THINK_MODELS"] ?? "").trim().toLowerCase();
695333
- return raw === "1" || raw === "true" || raw === "on";
695334
- }
695335
- telegramRouterModelLooksThinkHeavy(name10) {
695336
- return /\b(?:qwen3|qwq|deepseek-r1|r1-|reasoning)\b/i.test(name10);
695337
- }
695338
- normalizeOllamaModelNameForMatch(name10) {
695339
- return name10.trim().toLowerCase().replace(/:latest$/, "");
695340
- }
695341
- async fetchOllamaInstalledModels(baseUrl2) {
695342
- const url = `${baseUrl2.replace(/\/+$/, "")}/api/tags`;
695343
- const timeoutFn = AbortSignal.timeout;
695344
- const res = await fetch(url, {
695345
- signal: typeof timeoutFn === "function" ? timeoutFn(2e3) : void 0
695346
- });
695347
- if (!res.ok)
695348
- throw new Error(`ollama /api/tags returned HTTP ${res.status}`);
695349
- const data = await res.json();
695350
- return Array.isArray(data.models) ? data.models.map((model) => ({
695351
- name: typeof model.name === "string" ? model.name : "",
695352
- sizeBytes: typeof model.size === "number" ? model.size : void 0,
695353
- parameterSize: typeof model.details?.parameter_size === "string" ? model.details.parameter_size : void 0
695354
- })).filter((model) => Boolean(model.name)) : [];
695355
- }
695356
- telegramModelParameterBillions(model) {
695357
- const haystack = `${model.name} ${model.parameterSize ?? ""}`.toLowerCase();
695358
- const billion = haystack.match(/(\d+(?:\.\d+)?)\s*(?:b|bn)\b/);
695359
- if (billion) return Number(billion[1]);
695360
- const million = haystack.match(/(\d+(?:\.\d+)?)\s*m\b/);
695361
- if (million) return Number(million[1]) / 1e3;
695362
- return null;
695363
- }
695364
- scoreTelegramInstalledRouterModel(model) {
695365
- const name10 = model.name.toLowerCase();
695366
- if (/(?:embed|embedding|nomic|bge|e5-|clip|rerank|moondream|llava|vision|vl\b|minicpm|whisper|tts|sdxl|diffusion)/i.test(
695367
- name10
695368
- )) {
695369
- return Number.NEGATIVE_INFINITY;
695370
- }
695371
- const paramsB = this.telegramModelParameterBillions(model);
695372
- if (paramsB !== null && paramsB < TELEGRAM_ROUTER_AUTO_MIN_PARAMETERS_B) {
695373
- return Number.NEGATIVE_INFINITY;
695374
- }
695375
- if (paramsB === null && (model.sizeBytes ?? 0) < 5e9) {
695376
- return Number.NEGATIVE_INFINITY;
695377
- }
695378
- let score = 0;
695379
- if (paramsB !== null) score += paramsB * 10;
695380
- else score += Math.min(80, (model.sizeBytes ?? 0) / 1e9);
695381
- if (/qwen|huihui|qwq/i.test(name10)) score += 80;
695382
- else if (/deepseek|nemotron|llama|mistral|mixtral|command-r|devstral/i.test(name10))
695383
- score += 50;
695384
- else if (/gemma/i.test(name10)) score += 20;
695385
- if (/:latest$/i.test(model.name)) score += 1;
695386
- if (this.telegramRouterModelLooksThinkHeavy(model.name) && !this.telegramRouterAllowThinkHeavyAutoModels()) {
695387
- score -= 15;
695388
- }
695389
- return score;
695390
- }
695391
695515
  async resolveTelegramRouterBackend(config) {
695392
695516
  const explicit = (process.env["OMNIUS_TG_ROUTER_MODEL"] ?? "").trim();
695393
- if (explicit && !/^(?:0|false|off|same|main)$/i.test(explicit)) {
695394
- return {
695395
- backend: new OllamaAgenticBackend(
695396
- config.backendUrl,
695397
- explicit,
695398
- config.apiKey
695399
- ),
695400
- model: explicit,
695401
- source: "env",
695402
- detail: "OMNIUS_TG_ROUTER_MODEL"
695403
- };
695404
- }
695405
- if (config.backendType !== "ollama") {
695517
+ if (/^(?:same|main)$/i.test(explicit)) {
695406
695518
  return {
695407
695519
  backend: new OllamaAgenticBackend(
695408
695520
  config.backendUrl,
@@ -695410,128 +695522,23 @@ ${retryText}`,
695410
695522
  config.apiKey
695411
695523
  ),
695412
695524
  model: config.model,
695413
- source: "main"
695414
- };
695415
- }
695416
- const autoModelEnabled = this.telegramRouterAutoModelEnabled();
695417
- const candidateFilter = this.telegramRouterCandidateModels();
695418
- const candidates = new Set(
695419
- candidateFilter.map(
695420
- (candidate) => this.normalizeOllamaModelNameForMatch(candidate)
695421
- )
695422
- );
695423
- const cacheKey = `${config.backendUrl}
695424
- ${config.model}
695425
- auto=${autoModelEnabled ? "1" : "0"}
695426
- ${candidateFilter.join(",")}`;
695427
- const now2 = Date.now();
695428
- if (this.telegramRouterModelCache && this.telegramRouterModelCache.cacheKey === cacheKey && now2 - this.telegramRouterModelCache.atMs < 6e4) {
695429
- const cached = this.telegramRouterModelCache;
695430
- return {
695431
- backend: new OllamaAgenticBackend(
695432
- config.backendUrl,
695433
- cached.model,
695434
- config.apiKey
695435
- ),
695436
- model: cached.model,
695437
- source: cached.source,
695438
- detail: cached.detail
695439
- };
695440
- }
695441
- if (!autoModelEnabled) {
695442
- const detail2 = "Telegram router auto-model selection is disabled by default; using main model";
695443
- this.telegramRouterModelCache = {
695444
- cacheKey,
695445
- atMs: now2,
695446
- model: config.model,
695447
695525
  source: "main",
695448
- detail: detail2
695526
+ detail: `OMNIUS_TG_ROUTER_MODEL=${explicit}`
695449
695527
  };
695528
+ }
695529
+ if (explicit && !/^(?:0|false|off)$/i.test(explicit)) {
695450
695530
  return {
695451
695531
  backend: new OllamaAgenticBackend(
695452
695532
  config.backendUrl,
695453
- config.model,
695533
+ explicit,
695454
695534
  config.apiKey
695455
695535
  ),
695456
- model: config.model,
695457
- source: "main",
695458
- detail: detail2
695536
+ model: explicit,
695537
+ source: "env",
695538
+ detail: "OMNIUS_TG_ROUTER_MODEL"
695459
695539
  };
695460
695540
  }
695461
- try {
695462
- const installed = await this.fetchOllamaInstalledModels(
695463
- config.backendUrl
695464
- );
695465
- const installedByNormalized = /* @__PURE__ */ new Map();
695466
- for (const model of installed) {
695467
- installedByNormalized.set(
695468
- this.normalizeOllamaModelNameForMatch(model.name),
695469
- model
695470
- );
695471
- }
695472
- const installedMain = installedByNormalized.get(
695473
- this.normalizeOllamaModelNameForMatch(config.model)
695474
- );
695475
- if (installedMain) {
695476
- const resolved = {
695477
- cacheKey,
695478
- atMs: now2,
695479
- model: installedMain.name,
695480
- source: "main",
695481
- detail: "main Telegram router model is installed in Ollama /api/tags; using main model by policy"
695482
- };
695483
- this.telegramRouterModelCache = resolved;
695484
- return {
695485
- backend: new OllamaAgenticBackend(
695486
- config.backendUrl,
695487
- installedMain.name,
695488
- config.apiKey
695489
- ),
695490
- model: installedMain.name,
695491
- source: "main",
695492
- detail: resolved.detail
695493
- };
695494
- }
695495
- if (autoModelEnabled) {
695496
- const pool3 = candidateFilter.length > 0 ? installed.filter(
695497
- (model) => candidates.has(
695498
- this.normalizeOllamaModelNameForMatch(model.name)
695499
- )
695500
- ) : installed;
695501
- const selected = pool3.map((model) => ({
695502
- model,
695503
- score: this.scoreTelegramInstalledRouterModel(model)
695504
- })).filter((entry) => Number.isFinite(entry.score)).sort((a2, b) => b.score - a2.score)[0]?.model;
695505
- if (selected) {
695506
- const resolved = {
695507
- cacheKey,
695508
- atMs: now2,
695509
- model: selected.name,
695510
- source: "auto-installed",
695511
- detail: `main Telegram router model ${JSON.stringify(config.model)} was not found in Ollama /api/tags; selected best installed capable router model dynamically (minimum ${TELEGRAM_ROUTER_AUTO_MIN_PARAMETERS_B}B, excludes embeddings/vision/tiny models)`
695512
- };
695513
- this.telegramRouterModelCache = resolved;
695514
- return {
695515
- backend: new OllamaAgenticBackend(
695516
- config.backendUrl,
695517
- selected.name,
695518
- config.apiKey
695519
- ),
695520
- model: selected.name,
695521
- source: "auto-installed",
695522
- detail: resolved.detail
695523
- };
695524
- }
695525
- }
695526
- } catch (err) {
695527
- const detail2 = `router model auto-detect failed: ${err instanceof Error ? err.message : String(err)}`;
695528
- this.telegramRouterModelCache = {
695529
- cacheKey,
695530
- atMs: now2,
695531
- model: config.model,
695532
- source: "main",
695533
- detail: detail2
695534
- };
695541
+ if (config.backendType !== "ollama") {
695535
695542
  return {
695536
695543
  backend: new OllamaAgenticBackend(
695537
695544
  config.backendUrl,
@@ -695539,18 +695546,9 @@ ${candidateFilter.join(",")}`;
695539
695546
  config.apiKey
695540
695547
  ),
695541
695548
  model: config.model,
695542
- source: "main",
695543
- detail: detail2
695549
+ source: "main"
695544
695550
  };
695545
695551
  }
695546
- const detail = `no installed capable Telegram router model met the dynamic minimum (${TELEGRAM_ROUTER_AUTO_MIN_PARAMETERS_B}B); using main model`;
695547
- this.telegramRouterModelCache = {
695548
- cacheKey,
695549
- atMs: now2,
695550
- model: config.model,
695551
- source: "main",
695552
- detail
695553
- };
695554
695552
  return {
695555
695553
  backend: new OllamaAgenticBackend(
695556
695554
  config.backendUrl,
@@ -695559,7 +695557,7 @@ ${candidateFilter.join(",")}`;
695559
695557
  ),
695560
695558
  model: config.model,
695561
695559
  source: "main",
695562
- detail
695560
+ detail: "using selected Telegram model; automatic router model fallback is disabled"
695563
695561
  };
695564
695562
  }
695565
695563
  async inferTelegramInteractionDecision(msg, toolContext) {
@@ -695818,7 +695816,7 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
695818
695816
  diagnosticNote: this.composeTelegramRouterDiagnosticNote(
695819
695817
  void 0,
695820
695818
  failureNarrative2,
695821
- "router produced no visible attention decision content; repair/strict retry skipped for direct private/admin fail-open",
695819
+ "router produced no visible attention decision content; repair/strict retry skipped for direct/high-salience fail-open",
695822
695820
  diagnostics
695823
695821
  ),
695824
695822
  raw: text2
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.467",
3
+ "version": "1.0.468",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.467",
9
+ "version": "1.0.468",
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.467",
3
+ "version": "1.0.468",
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",