omnius 1.0.467 → 1.0.469

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,31 +14235,125 @@ 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
  }
14241
14300
  function buildMissingOldStringLlmContent(input) {
14301
+ const attemptedLineCount = input.attemptedOldString.split("\n").length;
14302
+ const attemptedCharCount = input.attemptedOldString.length;
14242
14303
  const lines = [
14243
14304
  "[FILE_EDIT_OLD_STRING_NOT_FOUND]",
14244
14305
  `path=${input.path}`,
14245
14306
  "The attempted old_string was absent from the current file.",
14307
+ `attempted_old_string_lines=${attemptedLineCount}`,
14308
+ `attempted_old_string_chars=${attemptedCharCount}`,
14309
+ "repair_state=needs_current_range",
14310
+ "patch_ready=false",
14311
+ "read_required=true unless current path+start_line+end_line+expected_hash are already present in active evidence",
14246
14312
  "Do not copy diagnostic gutters into old_string. Ignore line numbers, leading '>' markers, and the '|' separator.",
14313
+ "Transport rule: file_edit is for exact unique current text. If the intended edit is a contiguous line-range delete/replace/insert, use file_patch with start_line/end_line from file_read and expected_hash or expected_old_content.",
14314
+ "Range patch contract: if patch_ready=true or current target line range plus expected_hash are known, call file_patch. If the range/hash is missing after stale exact edit failure, file_read the target once.",
14247
14315
  "",
14248
- "attempted_old_string:",
14249
- fencedText(input.attemptedOldString)
14316
+ ...diagnosticTextBlock("attempted_old_string", input.attemptedOldString)
14250
14317
  ];
14251
14318
  if (input.snippetContent) {
14252
14319
  const range = input.snippetStartLine && input.snippetEndLine && input.totalLines ? `lines ${input.snippetStartLine}-${input.snippetEndLine} of ${input.totalLines}` : "closest current text";
14253
- lines.push("", `copyable_current_text_without_gutters (${range}):`, fencedText(stripDiagnosticGutters(input.snippetContent)), "", "Next action: build a new file_edit old_string only from the copyable_current_text_without_gutters block, or file_read the target if more context is needed.");
14320
+ lines.push("", `current_anchor_range=${range}`, "target_range_status=anchor_only_not_patch_ready", `copyable_current_text_without_gutters (${range}):`, fencedText(stripDiagnosticGutters(input.snippetContent)), "", "Next action: build a new file_edit old_string only from the copyable_current_text_without_gutters block, or use file_patch from fresh file_read line numbers when the target is a block/range.");
14254
14321
  } else {
14255
- lines.push("", "Next action: file_read the target, then build old_string from exact current file content.");
14322
+ lines.push("", "Next action: file_read the target, then either build old_string from exact current file content or use file_patch for a line-range edit.");
14256
14323
  }
14257
14324
  lines.push("", "Do not use shell text-rewrite commands as a workaround for this edit failure; keep the change tracked through file_edit, batch_edit, file_patch, or file_write.");
14258
14325
  if (input.newString.length > 0) {
14259
- lines.push("", "desired_new_string:", fencedText(input.newString));
14326
+ lines.push("", ...diagnosticTextBlock("desired_new_string", input.newString));
14260
14327
  }
14261
14328
  return lines.join("\n");
14262
14329
  }
14330
+ function diagnosticTextBlock(label, text2) {
14331
+ const maxChars = 700;
14332
+ const maxLines = 12;
14333
+ const lineCount = text2.split("\n").length;
14334
+ if (text2.length <= maxChars && lineCount <= maxLines) {
14335
+ return [`${label}:`, fencedText(text2)];
14336
+ }
14337
+ return [
14338
+ `${label}_preview:`,
14339
+ fencedText(previewText(text2, maxChars)),
14340
+ `${label}_omitted=true`,
14341
+ `${label}_omitted_reason=stale failed edit payload is not authoritative current file evidence`
14342
+ ];
14343
+ }
14344
+ function previewText(text2, maxChars) {
14345
+ if (text2.length <= maxChars)
14346
+ return text2;
14347
+ const headSize = Math.floor(maxChars * 0.65);
14348
+ const tailSize = Math.max(80, maxChars - headSize - 64);
14349
+ const head = text2.slice(0, headSize).trimEnd();
14350
+ const tail = text2.slice(-tailSize).trimStart();
14351
+ return `${head}
14352
+ ...
14353
+ [omitted ${text2.length - head.length - tail.length} chars]
14354
+ ...
14355
+ ${tail}`;
14356
+ }
14263
14357
  function buildAmbiguousOldStringLlmContent(input) {
14264
14358
  const replaceAllArgs = {
14265
14359
  path: input.path,
@@ -14308,7 +14402,7 @@ var init_file_edit = __esm({
14308
14402
  init_text_encoding();
14309
14403
  FileEditTool = class {
14310
14404
  name = "file_edit";
14311
- description = "Make a precise edit to a file by replacing an exact string match. The old_string must be unique in the file unless replace_all is true. Use replace_all to rename variables or change repeated patterns throughout the file.";
14405
+ description = "Make a precise edit to a file by replacing an exact string match. The old_string must be unique in the file unless replace_all is true. Use replace_all to rename variables or change repeated patterns throughout the file. Use file_patch instead when file_read line numbers identify a contiguous block to delete, replace, or insert around.";
14312
14406
  parameters = {
14313
14407
  type: "object",
14314
14408
  properties: {
@@ -14419,8 +14513,20 @@ var init_file_edit = __esm({
14419
14513
  afterHash: beforeHash
14420
14514
  };
14421
14515
  }
14422
- const occurrences = countOccurrences(content, oldString);
14516
+ let occurrences = countOccurrences(content, oldString);
14517
+ let whitespaceAdjustedMatches = null;
14518
+ let diffOldString = oldString;
14519
+ if (occurrences === 0 && expectedHash) {
14520
+ const matches = findLineEndWhitespaceEquivalentSpans(content, oldString);
14521
+ if (matches.length > 0) {
14522
+ occurrences = matches.length;
14523
+ whitespaceAdjustedMatches = matches;
14524
+ diffOldString = matches[0]?.text ?? oldString;
14525
+ }
14526
+ }
14423
14527
  if (occurrences === 0) {
14528
+ const attemptedOldStringLines = oldString.split("\n").length;
14529
+ const attemptedOldStringChars = oldString.length;
14424
14530
  const alreadyAppliedLines = newString.length > 0 ? findMatchLines(content, newString) : [];
14425
14531
  if (alreadyAppliedLines.length > 0) {
14426
14532
  const lineInfo = alreadyAppliedLines.length === 1 ? `line ${alreadyAppliedLines[0]}` : `${alreadyAppliedLines.length} locations (lines ${alreadyAppliedLines.join(", ")})`;
@@ -14443,10 +14549,12 @@ var init_file_edit = __esm({
14443
14549
  const pct = Math.round(snippet.similarity * 100);
14444
14550
  errorMsg += `
14445
14551
 
14446
- Current file content (closest match, ${pct}% similarity, lines ${snippet.startLine}–${snippet.endLine} of ${snippet.totalLines}):
14552
+ Attempted old_string spans ${attemptedOldStringLines} line(s), ${attemptedOldStringChars} chars. The diagnostic below is the closest anchor-line match, not proof that the whole old_string exists.
14553
+
14554
+ Current file content (closest anchor-line match, ${pct}% line similarity, lines ${snippet.startLine}–${snippet.endLine} of ${snippet.totalLines}):
14447
14555
  ${snippet.content}
14448
14556
 
14449
- Use the EXACT current content above to construct a working old_string. Do not retry with a different guess — the file on disk has changed since you last read it.`;
14557
+ Use the EXACT current content above to construct a working old_string. If the intended change is a contiguous line range, use file_patch with start_line/end_line from a fresh file_read. Do not retry with a different guess — the file on disk has changed since you last read it.`;
14450
14558
  } else {
14451
14559
  errorMsg += ` The file is empty or binary. Use file_read to inspect.`;
14452
14560
  }
@@ -14471,18 +14579,19 @@ Use the EXACT current content above to construct a working old_string. Do not re
14471
14579
  };
14472
14580
  }
14473
14581
  if (!replaceAll && occurrences > 1) {
14474
- const matchLines = findMatchLines(content, oldString);
14475
- const offsets = findMatchOffsets(content, oldString);
14582
+ const matchLines = whitespaceAdjustedMatches ? whitespaceAdjustedMatches.map((match) => lineNumberAtOffset(content, match.start)) : findMatchLines(content, oldString);
14583
+ const offsets = whitespaceAdjustedMatches ? whitespaceAdjustedMatches.map((match) => match.start) : findMatchOffsets(content, oldString);
14476
14584
  const snippets = offsets.slice(0, 4).map((off) => {
14477
14585
  const s2 = snippetAtOffset(content, off, 3);
14478
14586
  return `
14479
14587
  --- match at line ${s2.lineNumber} ---
14480
14588
  ${s2.content}`;
14481
14589
  }).join("\n");
14590
+ 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
14591
  return {
14483
14592
  success: false,
14484
14593
  output: "",
14485
- error: `old_string is not unique — found ${occurrences} occurrences at lines ${matchLines.join(", ")}.
14594
+ error: `${reason}
14486
14595
  ${snippets}
14487
14596
 
14488
14597
  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 +14613,27 @@ Add UNIQUE surrounding context (a function name, distinctive comment, or unique
14504
14613
  let updated;
14505
14614
  let editedLines;
14506
14615
  if (replaceAll) {
14507
- editedLines = findMatchLines(content, oldString);
14508
- updated = replaceAllOccurrences(content, oldString, newString);
14616
+ if (whitespaceAdjustedMatches) {
14617
+ editedLines = whitespaceAdjustedMatches.map((match) => lineNumberAtOffset(content, match.start));
14618
+ updated = replaceSpans(content, whitespaceAdjustedMatches, newString);
14619
+ } else {
14620
+ editedLines = findMatchLines(content, oldString);
14621
+ updated = replaceAllOccurrences(content, oldString, newString);
14622
+ }
14509
14623
  } 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);
14624
+ if (whitespaceAdjustedMatches) {
14625
+ const match = whitespaceAdjustedMatches[0];
14626
+ editedLines = [lineNumberAtOffset(content, match.start)];
14627
+ updated = content.slice(0, match.start) + newString + content.slice(match.end);
14628
+ } else {
14629
+ const index = content.indexOf(oldString);
14630
+ const lineNumber = content.slice(0, index).split("\n").length;
14631
+ editedLines = [lineNumber];
14632
+ updated = content.slice(0, index) + newString + content.slice(index + oldString.length);
14633
+ }
14514
14634
  }
14515
14635
  const afterHash = contentHash(updated);
14516
- const diff = buildCompactDiff(oldString, newString);
14636
+ const diff = buildCompactDiff(diffOldString, newString);
14517
14637
  if (afterHash === beforeHash) {
14518
14638
  return {
14519
14639
  success: true,
@@ -14529,9 +14649,10 @@ Add UNIQUE surrounding context (a function name, distinctive comment, or unique
14529
14649
  }
14530
14650
  if (dryRun) {
14531
14651
  const linesInfo2 = editedLines.length === 1 ? `line ${editedLines[0]}` : `${editedLines.length} locations (lines ${editedLines.join(", ")})`;
14652
+ const matchNote2 = whitespaceAdjustedMatches ? " Matched by verified line-ending whitespace normalization." : "";
14532
14653
  return {
14533
14654
  success: true,
14534
- output: `[DRY RUN] file_edit validated for ${filePath} at ${linesInfo2}. File NOT modified. Call again with dry_run=false to apply.
14655
+ output: `[DRY RUN] file_edit validated for ${filePath} at ${linesInfo2}. File NOT modified. Call again with dry_run=false to apply.${matchNote2}
14535
14656
 
14536
14657
  ${diff}`,
14537
14658
  durationMs: performance.now() - start2,
@@ -14552,10 +14673,11 @@ ${diff}`,
14552
14673
  diff
14553
14674
  });
14554
14675
  const linesInfo = editedLines.length === 1 ? `line ${editedLines[0]}` : `${editedLines.length} locations (lines ${editedLines.join(", ")})`;
14555
- const lineNumberedDiff = buildLineNumberedDiff(oldString, newString, editedLines[0] ?? 1);
14676
+ const lineNumberedDiff = buildLineNumberedDiff(diffOldString, newString, editedLines[0] ?? 1);
14677
+ const matchNote = whitespaceAdjustedMatches ? " (matched by verified line-ending whitespace normalization)" : "";
14556
14678
  return {
14557
14679
  success: true,
14558
- output: `Edited ${filePath} at ${linesInfo} (sha256 ${beforeHash} → ${afterHash})
14680
+ output: `Edited ${filePath} at ${linesInfo}${matchNote} (sha256 ${beforeHash} → ${afterHash})
14559
14681
  ${lineNumberedDiff}`,
14560
14682
  durationMs: performance.now() - start2,
14561
14683
  mutated: true,
@@ -28834,7 +28956,7 @@ var init_file_patch = __esm({
28834
28956
  init_text_encoding();
28835
28957
  FilePatchTool = class {
28836
28958
  name = "file_patch";
28837
- description = "Edit specific line ranges in a file. More precise than string matching for large files. Modes: 'replace' replaces lines start_line..end_line with new_content, 'insert_before' inserts before start_line, 'insert_after' inserts after start_line, 'delete' removes lines start_line..end_line. Use dry_run to preview changes.";
28959
+ description = "Edit specific line ranges in a file. More precise than string matching for large files. Modes: 'replace' replaces lines start_line..end_line with new_content, 'insert_before' inserts before start_line, 'insert_after' inserts after start_line, 'delete' removes lines start_line..end_line. Use this instead of file_edit when file_read line numbers identify the contiguous block to change. Use dry_run to preview changes.";
28838
28960
  parameters = {
28839
28961
  type: "object",
28840
28962
  properties: {
@@ -28885,12 +29007,82 @@ var init_file_patch = __esm({
28885
29007
  description: "Preview the diff without writing. Returns what would change. Default: false"
28886
29008
  }
28887
29009
  },
28888
- required: ["path", "start_line"]
29010
+ required: ["path"],
29011
+ allOf: [
29012
+ {
29013
+ if: { properties: { mode: { const: "delete" } }, required: ["mode"] },
29014
+ then: { required: ["start_line", "end_line"] }
29015
+ },
29016
+ {
29017
+ if: { properties: { mode: { const: "replace" } }, required: ["mode"] },
29018
+ then: { required: ["start_line", "end_line"] }
29019
+ },
29020
+ {
29021
+ if: { properties: { mode: { const: "insert_before" } }, required: ["mode"] },
29022
+ then: { required: ["start_line"] }
29023
+ },
29024
+ {
29025
+ if: { properties: { mode: { const: "insert_after" } }, required: ["mode"] },
29026
+ then: { required: ["start_line"] }
29027
+ }
29028
+ ]
28889
29029
  };
28890
29030
  workingDir;
28891
29031
  constructor(workingDir) {
28892
29032
  this.workingDir = workingDir;
28893
29033
  }
29034
+ validateInput(args) {
29035
+ if (args["operations"] !== void 0) {
29036
+ return {
29037
+ result: false,
29038
+ 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":"..."}.`
29039
+ };
29040
+ }
29041
+ if (typeof args["path"] !== "string" || !args["path"].trim()) {
29042
+ return { result: false, message: "file_patch requires non-empty path." };
29043
+ }
29044
+ const mode = typeof args["mode"] === "string" ? args["mode"] : "replace";
29045
+ if (!["replace", "insert_before", "insert_after", "delete"].includes(mode)) {
29046
+ return {
29047
+ result: false,
29048
+ message: `file_patch mode="${String(args["mode"])}" is invalid. Use replace, insert_before, insert_after, or delete.`
29049
+ };
29050
+ }
29051
+ if (!Number.isInteger(args["start_line"]) || Number(args["start_line"]) < 1) {
29052
+ return {
29053
+ result: false,
29054
+ 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.`
29055
+ };
29056
+ }
29057
+ const hasEndLine = args["end_line"] !== void 0 && args["end_line"] !== null;
29058
+ const hasNewContent = args["new_content"] !== void 0 || args["newContent"] !== void 0 || args["new_content_base64"] !== void 0 || args["newContentBase64"] !== void 0;
29059
+ const hasExpectedTarget = args["expected_hash"] !== void 0 || args["expectedHash"] !== void 0 || args["expected_old_content"] !== void 0;
29060
+ if ((mode === "replace" || mode === "delete") && !hasEndLine) {
29061
+ return {
29062
+ result: false,
29063
+ 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.`
29064
+ };
29065
+ }
29066
+ if ((mode === "replace" || mode === "insert_before" || mode === "insert_after") && !hasNewContent && args["allow_empty_content"] !== true) {
29067
+ return {
29068
+ result: false,
29069
+ 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.`
29070
+ };
29071
+ }
29072
+ if ((mode === "replace" || mode === "delete") && !hasExpectedTarget) {
29073
+ return {
29074
+ result: false,
29075
+ message: `file_patch mode=${mode} requires expected_hash from file_read or expected_old_content copied from the target lines.`
29076
+ };
29077
+ }
29078
+ if ((mode === "insert_before" || mode === "insert_after") && args["expected_hash"] === void 0 && args["expectedHash"] === void 0) {
29079
+ return {
29080
+ result: false,
29081
+ message: `file_patch mode=${mode} requires expected_hash from the most recent file_read so line numbers are versioned.`
29082
+ };
29083
+ }
29084
+ return { result: true };
29085
+ }
28894
29086
  async execute(args) {
28895
29087
  const filePath = args["path"];
28896
29088
  const startLine = args["start_line"];
@@ -577921,6 +578113,46 @@ import { join as _pathJoin, relative as _pathRelative, resolve as _pathResolve }
577921
578113
  import { tmpdir as _osTmpdir } from "node:os";
577922
578114
  import { homedir as _osHomedir } from "node:os";
577923
578115
  import { z as z17 } from "zod";
578116
+ function cleanToolActionReasonField(value2) {
578117
+ return String(value2 ?? "").replace(/\s+/g, " ").trim();
578118
+ }
578119
+ function stripShellQuotedSegments(command) {
578120
+ let out = "";
578121
+ let quote2 = null;
578122
+ let escaped = false;
578123
+ for (let i2 = 0; i2 < command.length; i2++) {
578124
+ const ch = command[i2];
578125
+ if (quote2 === "'") {
578126
+ if (ch === "'")
578127
+ quote2 = null;
578128
+ out += " ";
578129
+ continue;
578130
+ }
578131
+ if (quote2 === '"') {
578132
+ if (escaped) {
578133
+ escaped = false;
578134
+ out += " ";
578135
+ continue;
578136
+ }
578137
+ if (ch === "\\") {
578138
+ escaped = true;
578139
+ out += " ";
578140
+ continue;
578141
+ }
578142
+ if (ch === '"')
578143
+ quote2 = null;
578144
+ out += " ";
578145
+ continue;
578146
+ }
578147
+ if (ch === "'" || ch === '"') {
578148
+ quote2 = ch;
578149
+ out += " ";
578150
+ continue;
578151
+ }
578152
+ out += ch;
578153
+ }
578154
+ return out;
578155
+ }
577924
578156
  function parsePersistentMemoryMode(value2) {
577925
578157
  if (value2 === "full" || value2 === "deferred" || value2 === "off")
577926
578158
  return value2;
@@ -579670,6 +579902,8 @@ ${parts.join("\n")}
579670
579902
  lines.push(`recent_failed_approaches=${ts.failedApproaches.slice(-3).join(" | ").replace(/\s+/g, " ").slice(0, 420)}`);
579671
579903
  }
579672
579904
  lines.push("tool_call_contract=Mutating/side-effectful tool calls require action_reason {task_anchor,intent,evidence,expected_result,scope}; read-only evidence tools may include it but must never be blocked only for missing metadata. Compact public facts only, no hidden chain-of-thought.");
579905
+ lines.push("edit_transport_contract=file_edit is for exact unique current text copied from file_read; file_patch is for line-range delete/replace/insert using file_read line numbers and expected_hash/current target evidence. A failed file_edit invalidates the edit premise; rebuild from current evidence instead of broadening into file_write unless the task is truly whole-file replacement.");
579906
+ lines.push("range_patch_contract=If patch_ready=true or current path+start_line+end_line+expected_hash are known, call file_patch. If read_required=true or a stale exact edit lacks current range/hash, call file_read once. Do not call file_read when patch_ready=true.");
579673
579907
  lines.push(`scope_contract=${Array.from(TOOL_ACTION_REASON_SCOPES).join("|")}; use targeted_patch for constrained code edits and full_file_rewrite only for deliberate whole-file replacement.`);
579674
579908
  const focus = this._focusSupervisor?.snapshot().directive ?? null;
579675
579909
  if (focus) {
@@ -579879,7 +580113,7 @@ ${parts.join("\n")}
579879
580113
  temperature: options2?.temperature ?? 0,
579880
580114
  requestTimeoutMs: options2?.requestTimeoutMs ?? 3e5,
579881
580115
  taskTimeoutMs: options2?.taskTimeoutMs ?? 0,
579882
- // 0 = no hard timeout (turn budget is the loop breaker)
580116
+ // legacy health-check interval only; never a hard timeout
579883
580117
  compactionThreshold: options2?.compactionThreshold ?? 4e4,
579884
580118
  deepContext: options2?.deepContext ?? false,
579885
580119
  dynamicContext: options2?.dynamicContext ?? "",
@@ -583601,17 +583835,18 @@ ${contentPreview}
583601
583835
  const cmd = rawCmd.trim();
583602
583836
  if (!cmd)
583603
583837
  return false;
583604
- if (/(^|[^&\d])(>|>>)\s*\S/.test(cmd))
583838
+ const unquoted = stripShellQuotedSegments(cmd);
583839
+ if (/(^|[^&\d])(>|>>)\s*\S/.test(unquoted))
583605
583840
  return true;
583606
- if (/\|\s*(?:tee|dd)\b/i.test(cmd))
583841
+ if (/\|\s*(?:tee|dd)\b/i.test(unquoted))
583607
583842
  return true;
583608
- if (/\b(?:sed|gsed)\s+(?:[^\n;&|]*\s)?(?:-i|--in-place)\b/i.test(cmd))
583843
+ if (/\b(?:sed|gsed)\s+(?:[^\n;&|]*\s)?(?:-i|--in-place)\b/i.test(unquoted))
583609
583844
  return true;
583610
- if (/\bperl\s+-[A-Za-z]*i[A-Za-z]*\b/.test(cmd))
583845
+ if (/\bperl\s+-[A-Za-z]*i[A-Za-z]*\b/.test(unquoted))
583611
583846
  return true;
583612
- if (/\b(?:cp|mv|rm|mkdir|rmdir|touch|truncate|ln|install|chmod|chown|chgrp|setfacl)\b/i.test(cmd))
583847
+ if (/\b(?:cp|mv|rm|mkdir|rmdir|touch|truncate|ln|install|chmod|chown|chgrp|setfacl)\b/i.test(unquoted))
583613
583848
  return true;
583614
- if (/\b(?:udevadm|mount|umount|modprobe|insmod)\b/i.test(cmd))
583849
+ if (/\b(?:udevadm|mount|umount|modprobe|insmod)\b/i.test(unquoted))
583615
583850
  return true;
583616
583851
  if (/\b(?:python3?|node|ruby|deno|bun)\b[\s\S]{0,240}\b(?:writeFile|writeFileSync|openSync|mkdirSync|renameSync|unlinkSync|rmSync)\b/i.test(cmd))
583617
583852
  return true;
@@ -585870,44 +586105,13 @@ Respond with your assessment, then take action.`;
585870
586105
  }
585871
586106
  const cleanedTask = cleanForStorage(task) || task.slice(0, 500);
585872
586107
  const start2 = Date.now();
585873
- const taskTimeoutMs = this.options.taskTimeoutMs;
585874
- const hardDeadlineMs = Number.isFinite(taskTimeoutMs) && taskTimeoutMs > 0 ? start2 + taskTimeoutMs : Number.POSITIVE_INFINITY;
585875
- let timedOut = false;
585876
- let timeoutSummary = "";
585877
- const remainingTaskMs = () => Number.isFinite(hardDeadlineMs) ? Math.max(0, hardDeadlineMs - Date.now()) : Number.POSITIVE_INFINITY;
586108
+ const taskTimeoutMs = Number.isFinite(this.options.taskTimeoutMs) && this.options.taskTimeoutMs > 0 ? this.options.taskTimeoutMs : Number.POSITIVE_INFINITY;
585878
586109
  const boundedRequestTimeoutMs = () => {
585879
586110
  const configured = Number.isFinite(this.options.requestTimeoutMs) && this.options.requestTimeoutMs > 0 ? this.options.requestTimeoutMs : 3e5;
585880
- const remaining = remainingTaskMs();
585881
- return Number.isFinite(remaining) ? Math.max(1, Math.min(configured, remaining)) : configured;
585882
- };
585883
- const markTaskTimedOut = (phase, turn) => {
585884
- if (timedOut)
585885
- return;
585886
- timedOut = true;
585887
- timeoutSummary = `Incomplete: task timed out after ${taskTimeoutMs}ms during ${phase}.`;
585888
- this.emit({
585889
- type: "error",
585890
- content: timeoutSummary,
585891
- ...typeof turn === "number" ? { turn } : {},
585892
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
585893
- });
585894
- this._onTypedEvent?.({
585895
- type: "run_failed",
585896
- runId: this._sessionId ?? "unknown",
585897
- error: timeoutSummary,
585898
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
585899
- });
585900
- };
585901
- const checkTaskTimeout = (phase, turn) => {
585902
- if (!Number.isFinite(hardDeadlineMs))
585903
- return false;
585904
- if (Date.now() < hardDeadlineMs)
585905
- return false;
585906
- markTaskTimedOut(phase, turn);
585907
- return true;
586111
+ return configured;
585908
586112
  };
585909
586113
  const selfEvalInterval = taskTimeoutMs;
585910
- let nextSelfEval = start2 + selfEvalInterval;
586114
+ let nextSelfEval = Number.isFinite(selfEvalInterval) ? start2 + selfEvalInterval : Number.POSITIVE_INFINITY;
585911
586115
  let selfEvalCount = 0;
585912
586116
  const toolCallLog = [];
585913
586117
  this.aborted = false;
@@ -586774,8 +586978,6 @@ TASK: ${scrubbedTask}` : scrubbedTask;
586774
586978
  };
586775
586979
  const turnCap = this.options.maxTurns && this.options.maxTurns > 0 ? this.options.maxTurns : Number.MAX_SAFE_INTEGER;
586776
586980
  for (let turn = 0; turn < turnCap; turn++) {
586777
- if (checkTaskTimeout("primary turn", turn))
586778
- break;
586779
586981
  clearTurnState(this._appState);
586780
586982
  this._maybeApplyThinkGuard();
586781
586983
  if (this._paused) {
@@ -588448,10 +588650,8 @@ ${memoryLines.join("\n")}`
588448
588650
  break;
588449
588651
  }
588450
588652
  } else {
588451
- const recovered = await this.retryOnTransient(reqErr, chatRequest, turn, hardDeadlineMs);
588653
+ const recovered = await this.retryOnTransient(reqErr, chatRequest, turn);
588452
588654
  if (!recovered) {
588453
- if (checkTaskTimeout("backend request", turn))
588454
- break;
588455
588655
  const errMsg = reqErr instanceof Error ? reqErr.message : String(reqErr);
588456
588656
  const cause = reqErr instanceof Error && reqErr.cause ? ` (${reqErr.cause.message ?? ""} ${reqErr.cause?.code ?? ""})` : "";
588457
588657
  this.emit({
@@ -592131,9 +592331,7 @@ Your most recent tool calls SUCCEEDED. If the task is complete, call task_comple
592131
592331
  }
592132
592332
  }
592133
592333
  let prevCycleToolCalls = toolCallCount;
592134
- while (!completed && !this.aborted && !this._completionIncompleteVerification && !timedOut && this.options.bruteForce && bruteForceCycle < this.options.bruteForceMaxCycles) {
592135
- if (checkTaskTimeout("brute-force re-engagement"))
592136
- break;
592334
+ while (!completed && !this.aborted && !this._completionIncompleteVerification && this.options.bruteForce && bruteForceCycle < this.options.bruteForceMaxCycles) {
592137
592335
  bruteForceCycle++;
592138
592336
  const totalTurns = messages2.filter((m2) => m2.role === "assistant").length;
592139
592337
  if (bruteForceCycle > 1 && toolCallCount === prevCycleToolCalls) {
@@ -592197,8 +592395,6 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
592197
592395
  }
592198
592396
  const restartTurnCap = this.options.maxTurns && this.options.maxTurns > 0 ? this.options.maxTurns : Number.MAX_SAFE_INTEGER;
592199
592397
  for (let turn = 0; turn < restartTurnCap; turn++) {
592200
- if (checkTaskTimeout("brute-force turn", turn))
592201
- break;
592202
592398
  if (this._completionIncompleteVerification)
592203
592399
  break;
592204
592400
  this._maybeApplyThinkGuard();
@@ -592327,10 +592523,8 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
592327
592523
  break;
592328
592524
  }
592329
592525
  } else {
592330
- const recovered = await this.retryOnTransient(reqErr, chatRequest, turn, hardDeadlineMs);
592526
+ const recovered = await this.retryOnTransient(reqErr, chatRequest, turn);
592331
592527
  if (!recovered) {
592332
- if (checkTaskTimeout("brute-force backend request", turn))
592333
- break;
592334
592528
  const errMsg2 = reqErr instanceof Error ? reqErr.message : String(reqErr);
592335
592529
  const cause2 = reqErr instanceof Error && reqErr.cause ? ` (${reqErr.cause.message ?? ""} ${reqErr.cause?.code ?? ""})` : "";
592336
592530
  this.emit({
@@ -592807,9 +593001,6 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
592807
593001
  }
592808
593002
  const durationMs = Date.now() - start2;
592809
593003
  const incompleteVerification = this._completionIncompleteVerification;
592810
- if (timedOut && !summary) {
592811
- summary = timeoutSummary || `Incomplete: task timed out after ${taskTimeoutMs}ms.`;
592812
- }
592813
593004
  if (incompleteVerification && !summary) {
592814
593005
  summary = incompleteVerification.summary;
592815
593006
  }
@@ -594031,7 +594222,7 @@ ${marker}` : marker);
594031
594222
  try {
594032
594223
  raw = JSON.parse(trimmed);
594033
594224
  } catch {
594034
- return null;
594225
+ return { intent: trimmed };
594035
594226
  }
594036
594227
  }
594037
594228
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
@@ -594048,8 +594239,9 @@ ${marker}` : marker);
594048
594239
  }
594049
594240
  _toolActionReasonForCall(toolName, args) {
594050
594241
  const explicit = this._extractToolActionReason(args);
594051
- if (explicit)
594052
- return explicit;
594242
+ if (explicit) {
594243
+ return this._completeToolActionReason(toolName, args, explicit);
594244
+ }
594053
594245
  if (this._shouldSynthesizeMissingToolActionReason(toolName, args)) {
594054
594246
  return this._synthesizeStateUpdateToolActionReason(toolName, args);
594055
594247
  }
@@ -594057,6 +594249,48 @@ ${marker}` : marker);
594057
594249
  return null;
594058
594250
  return this._synthesizeReadOnlyToolActionReason(toolName, args);
594059
594251
  }
594252
+ _completeToolActionReason(toolName, args, partial) {
594253
+ const canonical = this.lookupRegisteredTool(toolName)?.name ?? toolName;
594254
+ const goal = this._taskState.currentStep || this._taskState.nextAction || this._taskState.goal || this._taskState.originalGoal || "current task";
594255
+ const targetPaths = this._extractToolTargetPaths(canonical, args).slice(0, 3);
594256
+ const targetText = targetPaths.length > 0 ? ` for ${targetPaths.join(", ")}` : "";
594257
+ const scope = TOOL_ACTION_REASON_SCOPES.has(String(partial.scope ?? "")) ? String(partial.scope) : this._defaultToolActionReasonScope(canonical);
594258
+ return {
594259
+ task_anchor: cleanToolActionReasonField(partial.task_anchor) || String(goal).replace(/\s+/g, " ").trim().slice(0, 160),
594260
+ intent: cleanToolActionReasonField(partial.intent) || `Run ${canonical}${targetText} for the active task.`,
594261
+ evidence: cleanToolActionReasonField(partial.evidence) || "Runtime completed partial public action metadata from the tool call contract before execution.",
594262
+ expected_result: cleanToolActionReasonField(partial.expected_result) || this._defaultToolActionExpectedResult(canonical, targetText),
594263
+ scope
594264
+ };
594265
+ }
594266
+ _defaultToolActionReasonScope(toolName) {
594267
+ if (toolName === "file_edit" || toolName === "file_patch" || toolName === "batch_edit") {
594268
+ return "targeted_patch";
594269
+ }
594270
+ if (toolName === "create_structured_file")
594271
+ return "new_file";
594272
+ if (toolName === "task_complete")
594273
+ return "completion";
594274
+ if (READ_ONLY_ACTION_REASON_OPTIONAL_TOOLS.has(toolName))
594275
+ return "discovery";
594276
+ return "other";
594277
+ }
594278
+ _defaultToolActionExpectedResult(toolName, targetText) {
594279
+ switch (toolName) {
594280
+ case "file_edit":
594281
+ return `Requested exact edit is applied${targetText}, or a precise edit error is returned.`;
594282
+ case "file_patch":
594283
+ return `Requested line patch is applied${targetText}, or a precise patch error is returned.`;
594284
+ case "batch_edit":
594285
+ return `Requested edit batch is applied${targetText}, or per-edit failure evidence is returned.`;
594286
+ case "file_write":
594287
+ return `Requested file content is written${targetText}, or a precise write error is returned.`;
594288
+ case "shell":
594289
+ return "Command exits with output evidence for the next decision.";
594290
+ default:
594291
+ return `${toolName} completes and returns success or failure evidence.`;
594292
+ }
594293
+ }
594060
594294
  _shouldSynthesizeMissingToolActionReason(toolName, _args) {
594061
594295
  if (this._toolActionReasonPolicy(toolName, _args) === "disabled") {
594062
594296
  return false;
@@ -594107,24 +594341,13 @@ ${marker}` : marker);
594107
594341
  `scope must be one of: ${Array.from(TOOL_ACTION_REASON_SCOPES).join(", ")}.`
594108
594342
  ].join("\n");
594109
594343
  }
594110
- const reason = this._extractToolActionReason(args);
594111
- if (!reason) {
594344
+ const partialReason = this._extractToolActionReason(args);
594345
+ if (!partialReason) {
594112
594346
  if (policy === "optional")
594113
594347
  return null;
594114
594348
  return "[TOOL ACTION REASON CONTRACT] action_reason must be an object with compact public task-state fields.";
594115
594349
  }
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
- }
594350
+ const reason = this._completeToolActionReason(toolName, args, partialReason);
594128
594351
  if (!TOOL_ACTION_REASON_SCOPES.has(reason.scope)) {
594129
594352
  if (policy === "optional")
594130
594353
  return null;
@@ -594324,10 +594547,11 @@ ${marker}` : marker);
594324
594547
  return null;
594325
594548
  if (process.env["OMNIUS_ALLOW_STALE_REPAIR_OVERWRITE"] === "1")
594326
594549
  return null;
594327
- if (this.options.modelTier !== "small" && this.options.modelTier !== "medium")
594328
- return null;
594329
594550
  if (args?.["dry_run"] === true || args?.["dryRun"] === true)
594330
594551
  return null;
594552
+ const tier = this.options.modelTier ?? "large";
594553
+ if (tier !== "small" && tier !== "medium")
594554
+ return null;
594331
594555
  const path12 = this.extractPrimaryToolPath(args);
594332
594556
  if (!path12)
594333
594557
  return null;
@@ -594341,7 +594565,7 @@ ${marker}` : marker);
594341
594565
  return null;
594342
594566
  return [
594343
594567
  `[EDIT REPAIR LOCK] A recent narrow edit to ${active.path} failed because the model-visible target diverged from disk (${active.errorKind}; latest_file_hash=${active.latestFileHash || "unknown"}).`,
594344
- `This full-file overwrite was NOT executed. A stale narrow edit must not be repaired by broad file regeneration on ${this.options.modelTier ?? "unknown"} tier models.`,
594568
+ `This full-file overwrite was NOT executed. A stale narrow edit must not be repaired by broad file regeneration; preserve a constrained edit path until fresh target evidence is used.`,
594345
594569
  ``,
594346
594570
  `Allowed next actions:`,
594347
594571
  `1. file_read ${active.path} once and construct file_edit from exact current text.`,
@@ -597663,6 +597887,8 @@ ${result}`
597663
597887
  return true;
597664
597888
  if (/stream timeout|no response or chunk within|no response within \d+\s*s|stream stalled/i.test(msg))
597665
597889
  return true;
597890
+ if (/AbortError|operation was aborted|aborted due to timeout|signal timed out|timeout.*aborted/i.test(msg))
597891
+ return true;
597666
597892
  if (/received HTML error page/i.test(msg))
597667
597893
  return true;
597668
597894
  if (/model is loading|server busy|overloaded/i.test(msg))
@@ -597943,11 +598169,13 @@ ${description}`
597943
598169
  * until recovery; other transient backend errors use bounded backoff.
597944
598170
  * Returns the response on success, or null if recovery did not apply.
597945
598171
  */
597946
- async retryOnTransient(initialErr, chatRequest, turn, hardDeadlineMs) {
598172
+ async retryOnTransient(initialErr, chatRequest, turn) {
598173
+ if (this.aborted)
598174
+ return null;
597947
598175
  if (!this.isTransientError(initialErr))
597948
598176
  return null;
597949
598177
  const errMsg = flattenErrorText(initialErr);
597950
- const isNetworkError2 = /fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|socket hang up|UND_ERR|other side closed|stream timeout|no response or chunk within|no response within \d+\s*s|stream stalled/i.test(errMsg);
598178
+ const isNetworkError2 = /fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|socket hang up|UND_ERR|other side closed|stream timeout|no response or chunk within|no response within \d+\s*s|stream stalled|AbortError|operation was aborted|aborted due to timeout|signal timed out|timeout.*aborted/i.test(errMsg);
597951
598179
  const isAuthError = this.isRecoverableAuthError(initialErr);
597952
598180
  const isGpuSlotUnavailable = this.isGpuSlotUnavailableError(initialErr);
597953
598181
  const maxRetries = isNetworkError2 || isGpuSlotUnavailable || isAuthError ? Infinity : 3;
@@ -597958,15 +598186,6 @@ ${description}`
597958
598186
  while (attempt <= (maxRetries === Infinity ? Number.MAX_SAFE_INTEGER : maxRetries)) {
597959
598187
  if (this.aborted)
597960
598188
  return null;
597961
- if (Number.isFinite(hardDeadlineMs) && Date.now() >= hardDeadlineMs) {
597962
- this.emit({
597963
- type: "error",
597964
- content: "Task timeout reached during backend retry",
597965
- turn,
597966
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
597967
- });
597968
- return null;
597969
- }
597970
598189
  if (this.isPaymentRequiredError(initialErr) && typeof backend.rotateKey === "function") {
597971
598190
  const rotated = backend.rotateKey();
597972
598191
  if (rotated) {
@@ -598016,7 +598235,7 @@ ${description}`
598016
598235
  }
598017
598236
  }
598018
598237
  const delay4 = isGpuSlotUnavailable ? baseDelayMs : Math.min(baseDelayMs * Math.pow(2, attempt - 1), maxDelayMs);
598019
- const effectiveDelay = Number.isFinite(hardDeadlineMs) ? Math.max(0, Math.min(delay4, hardDeadlineMs - Date.now())) : delay4;
598238
+ const effectiveDelay = delay4;
598020
598239
  const attemptLabel = maxRetries === Infinity ? `${attempt}` : `${attempt}/${maxRetries}`;
598021
598240
  if (isGpuSlotUnavailable) {
598022
598241
  this.emit({
@@ -598034,15 +598253,6 @@ ${description}`
598034
598253
  await new Promise((r2) => setTimeout(r2, effectiveDelay));
598035
598254
  if (this.aborted)
598036
598255
  return null;
598037
- if (Number.isFinite(hardDeadlineMs) && Date.now() >= hardDeadlineMs) {
598038
- this.emit({
598039
- type: "error",
598040
- content: "Task timeout reached before backend retry could resume",
598041
- turn,
598042
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
598043
- });
598044
- return null;
598045
- }
598046
598256
  try {
598047
598257
  this._recordContextWindowDump("agent_turn_transient_retry", chatRequest, turn, attempt);
598048
598258
  const response = this.options.streamEnabled && this.hasStreamingSupport() ? await this.streamingRequest(chatRequest, turn) : await this.backend.chatCompletion(chatRequest);
@@ -688075,7 +688285,7 @@ function renderTelegramSubAgentError(username, error) {
688075
688285
  `${c3.red("✘")} ${c3.bold(`@${username}`)}: ${c3.dim(preview)}`
688076
688286
  );
688077
688287
  }
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;
688288
+ 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
688289
  var init_telegram_bridge = __esm({
688080
688290
  "packages/cli/src/tui/telegram-bridge.ts"() {
688081
688291
  "use strict";
@@ -688603,7 +688813,6 @@ Telegram link integrity contract:
688603
688813
  "message_reaction_count"
688604
688814
  ];
688605
688815
  TELEGRAM_DEFAULT_LONG_POLL_TIMEOUT_SECONDS = 50;
688606
- TELEGRAM_ROUTER_AUTO_MIN_PARAMETERS_B = 8;
688607
688816
  TELEGRAM_PUBLIC_TOOL_QUOTAS = {
688608
688817
  web: { limit: 20, windowMs: 60 * 6e4 },
688609
688818
  media: { limit: 30, windowMs: 60 * 6e4 },
@@ -688658,7 +688867,6 @@ Telegram link integrity contract:
688658
688867
  pollLoopPromise = null;
688659
688868
  pollFatalNotified = false;
688660
688869
  lastUpdateId = 0;
688661
- telegramRouterModelCache = null;
688662
688870
  /**
688663
688871
  * Snapshot of the main agent inference config captured at construction. The
688664
688872
  * effective `agentConfig` is this base overlaid with the Telegram-isolated
@@ -688909,7 +689117,6 @@ Telegram link integrity contract:
688909
689117
  ...next.backendUrl !== void 0 ? { apiKey: next.apiKey ?? "" } : {}
688910
689118
  };
688911
689119
  this.agentConfig = effective;
688912
- this.telegramRouterModelCache = null;
688913
689120
  return effective;
688914
689121
  }
688915
689122
  /** The Telegram-isolated inference override currently in effect (if any). */
@@ -689703,9 +689910,17 @@ No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code
689703
689910
  this.refreshActiveTelegramInteractionCount();
689704
689911
  return queued;
689705
689912
  }
689913
+ telegramMessageExplicitlyAddressesBot(msg) {
689914
+ if (this.telegramMessageRepliesToBot(msg)) return true;
689915
+ const bot = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
689916
+ if (!bot) return false;
689917
+ return (msg.mentionedUsernames ?? []).some(
689918
+ (name10) => name10.trim().replace(/^@/, "").toLowerCase() === bot
689919
+ );
689920
+ }
689706
689921
  shouldFailOpenTelegramRouterUnavailable(msg, toolContext) {
689707
689922
  if (msg.isBot) return false;
689708
- return toolContext === "telegram-admin-dm" || msg.chatType === "private";
689923
+ return toolContext === "telegram-admin-dm" || msg.chatType === "private" || this.telegramMessageExplicitlyAddressesBot(msg);
689709
689924
  }
689710
689925
  buildTelegramRouterUnavailableDecision(msg, toolContext, params) {
689711
689926
  const forcedRoute = this.interactionMode === "chat" || this.interactionMode === "action" ? this.interactionMode : null;
@@ -689718,9 +689933,9 @@ No scoped reflection artifact exists yet for this chat. Use <code>/reflect</code
689718
689933
  route,
689719
689934
  shouldReply: failOpen,
689720
689935
  confidence: failOpen ? 0.55 : 0,
689721
- reason: failOpen ? `${params.reason}; direct private/admin delivery uses degraded visible reply instead of silent halt` : params.reason,
689936
+ reason: failOpen ? `${params.reason}; direct/high-salience delivery uses degraded visible reply instead of silent halt` : params.reason,
689722
689937
  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",
689938
+ 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
689939
  diagnosticNote: params.diagnosticNote,
689725
689940
  raw: params.raw
689726
689941
  };
@@ -695319,90 +695534,9 @@ ${retryText}`,
695319
695534
  this.dispatchQueuedTelegramSessionWorkSoon();
695320
695535
  }
695321
695536
  }
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
695537
  async resolveTelegramRouterBackend(config) {
695392
695538
  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") {
695539
+ if (/^(?:same|main)$/i.test(explicit)) {
695406
695540
  return {
695407
695541
  backend: new OllamaAgenticBackend(
695408
695542
  config.backendUrl,
@@ -695410,128 +695544,23 @@ ${retryText}`,
695410
695544
  config.apiKey
695411
695545
  ),
695412
695546
  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
695547
  source: "main",
695448
- detail: detail2
695548
+ detail: `OMNIUS_TG_ROUTER_MODEL=${explicit}`
695449
695549
  };
695550
+ }
695551
+ if (explicit && !/^(?:0|false|off)$/i.test(explicit)) {
695450
695552
  return {
695451
695553
  backend: new OllamaAgenticBackend(
695452
695554
  config.backendUrl,
695453
- config.model,
695555
+ explicit,
695454
695556
  config.apiKey
695455
695557
  ),
695456
- model: config.model,
695457
- source: "main",
695458
- detail: detail2
695558
+ model: explicit,
695559
+ source: "env",
695560
+ detail: "OMNIUS_TG_ROUTER_MODEL"
695459
695561
  };
695460
695562
  }
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
- };
695563
+ if (config.backendType !== "ollama") {
695535
695564
  return {
695536
695565
  backend: new OllamaAgenticBackend(
695537
695566
  config.backendUrl,
@@ -695539,18 +695568,9 @@ ${candidateFilter.join(",")}`;
695539
695568
  config.apiKey
695540
695569
  ),
695541
695570
  model: config.model,
695542
- source: "main",
695543
- detail: detail2
695571
+ source: "main"
695544
695572
  };
695545
695573
  }
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
695574
  return {
695555
695575
  backend: new OllamaAgenticBackend(
695556
695576
  config.backendUrl,
@@ -695559,7 +695579,7 @@ ${candidateFilter.join(",")}`;
695559
695579
  ),
695560
695580
  model: config.model,
695561
695581
  source: "main",
695562
- detail
695582
+ detail: "using selected Telegram model; automatic router model fallback is disabled"
695563
695583
  };
695564
695584
  }
695565
695585
  async inferTelegramInteractionDecision(msg, toolContext) {
@@ -695818,7 +695838,7 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
695818
695838
  diagnosticNote: this.composeTelegramRouterDiagnosticNote(
695819
695839
  void 0,
695820
695840
  failureNarrative2,
695821
- "router produced no visible attention decision content; repair/strict retry skipped for direct private/admin fail-open",
695841
+ "router produced no visible attention decision content; repair/strict retry skipped for direct/high-salience fail-open",
695822
695842
  diagnostics
695823
695843
  ),
695824
695844
  raw: text2
@@ -728318,8 +728338,9 @@ function adoptHandoffRuns() {
728318
728338
  } catch {
728319
728339
  }
728320
728340
  }
728321
- if (r2.deadlineAtMs && r2.deadlineAtMs > 0 && process.env["OMNIUS_DISABLE_DAEMON_TIMEOUT_KILL"] !== "1") {
728322
- const remainingMs = r2.deadlineAtMs - Date.now();
728341
+ const adoptedDeadlineAtMs = typeof r2.deadlineAtMs === "number" && r2.deadlineAtMs > 0 ? r2.deadlineAtMs : 0;
728342
+ if (false) {
728343
+ const remainingMs = adoptedDeadlineAtMs - Date.now();
728323
728344
  const adoptedPid = r2.pid;
728324
728345
  const adoptedJobId = r2.jobId;
728325
728346
  const fireTimeout = () => {
@@ -728805,13 +728826,13 @@ function handleHelp(req3, res) {
728805
728826
  enable: "POST /v1/chat/completions with body {agent_loop: true} runs an N-turn server-side loop. Daemon executes any tool_calls matching daemon-resident tools and re-prompts; client-side tool_calls cause the loop to yield back so caller can execute them.",
728806
728827
  merge_daemon_tools: "Body field include_daemon_tools: ['read'] (or ['read','run']) merges the daemon's matching tools into the offered tools[] array automatically — no need to hand-list web_search/web_fetch/file_read/etc.",
728807
728828
  max_turns: "Body field max_turns (default 8, max 64).",
728808
- timeout: "Body field timeout_s caps the whole loop (default 30 min, max 1 hour). Per-backend-call timeout is separate (see OMNIUS_BACKEND_TIMEOUT_S).",
728829
+ timeout: "Body field timeout_s is treated as a backend/request liveness hint only; it must not kill an active agent loop.",
728809
728830
  prompt_template: "Body field prompt_template: 'factual-first' prepends a system message instructing the model to call web_search FIRST for any factual question.",
728810
728831
  response_envelope: "Standard OpenAI chat.completion shape PLUS a _agent_loop: {turns, log:[], done, reason} field. Reason is one of: model_returned_content, client_tools_pending, max_turns_exhausted."
728811
728832
  },
728812
728833
  backend_timeout: {
728813
728834
  env: "OMNIUS_BACKEND_TIMEOUT_S — default 120 seconds, max 3600 (1 hour).",
728814
- per_request: "Body field timeout_s on /v1/chat/completions, /v1/run, agent_loop. Caps to 1h.",
728835
+ per_request: "Body field timeout_s on /v1/chat/completions, /v1/run, agent_loop is request/backend liveness only, not a task deadline.",
728815
728836
  rationale: "Q1 (Cody/SA) — was hardcoded 120s, broke cold-start tool-calling thinks on large models."
728816
728837
  },
728817
728838
  run_lifecycle: {
@@ -730113,32 +730134,6 @@ ${task}` : task;
730113
730134
  }
730114
730135
  };
730115
730136
  onChildClose(child, finish);
730116
- const deadline = setTimeout(
730117
- () => {
730118
- if (done) return;
730119
- try {
730120
- if (child.pid) process.kill(-child.pid, "SIGTERM");
730121
- } catch {
730122
- }
730123
- try {
730124
- if (child.pid) process.kill(child.pid, "SIGTERM");
730125
- } catch {
730126
- }
730127
- setTimeout(() => {
730128
- try {
730129
- if (child.pid) process.kill(-child.pid, "SIGKILL");
730130
- } catch {
730131
- }
730132
- try {
730133
- if (child.pid) process.kill(child.pid, "SIGKILL");
730134
- } catch {
730135
- }
730136
- finish();
730137
- }, 3e3).unref();
730138
- },
730139
- (generateTimeoutS + 30) * 1e3
730140
- );
730141
- deadline.unref();
730142
730137
  });
730143
730138
  if (buf.trim()) finalLines.push(buf);
730144
730139
  const rawFinal = finalLines.join("\n").trim();
@@ -730205,33 +730200,6 @@ ${task}` : task;
730205
730200
  }
730206
730201
  };
730207
730202
  onChildClose(child, finish);
730208
- const deadline = setTimeout(
730209
- () => {
730210
- if (done) return;
730211
- killedByDeadline = true;
730212
- try {
730213
- if (child.pid) process.kill(-child.pid, "SIGTERM");
730214
- } catch {
730215
- }
730216
- try {
730217
- if (child.pid) process.kill(child.pid, "SIGTERM");
730218
- } catch {
730219
- }
730220
- setTimeout(() => {
730221
- try {
730222
- if (child.pid) process.kill(-child.pid, "SIGKILL");
730223
- } catch {
730224
- }
730225
- try {
730226
- if (child.pid) process.kill(child.pid, "SIGKILL");
730227
- } catch {
730228
- }
730229
- finish();
730230
- }, 3e3).unref();
730231
- },
730232
- (generateTimeoutS + 30) * 1e3
730233
- );
730234
- deadline.unref();
730235
730203
  });
730236
730204
  if (nonStreamBuf.trim()) nonStreamLines.push(nonStreamBuf);
730237
730205
  const rawNonStream = nonStreamLines.join("\n").trim();
@@ -730255,7 +730223,7 @@ ${task}` : task;
730255
730223
  } catch {
730256
730224
  }
730257
730225
  if (!content) {
730258
- const errMsg = killedByDeadline ? `Agent exceeded ${generateTimeoutS}s timeout and was killed.` : backendError ? `Backend error: ${backendError}` : "Agent produced no response.";
730226
+ const errMsg = backendError ? `Backend error: ${backendError}` : "Agent produced no response.";
730259
730227
  jsonResponse(res, 200, {
730260
730228
  model: model.replace(/^[a-z]+\//, ""),
730261
730229
  created_at: createdAt,
@@ -730844,9 +730812,7 @@ async function handleV1Run(req3, res) {
730844
730812
  } catch {
730845
730813
  }
730846
730814
  let _rca1DeadlineFired = false;
730847
- const _rca1KillSwitch = process.env["OMNIUS_DISABLE_DAEMON_TIMEOUT_KILL"] === "1";
730848
- const _rca1EffectiveTimeoutS = timeout2 && timeout2 > 0 ? timeout2 : activeProfile?.limits?.timeout_s && activeProfile.limits.timeout_s > 0 ? activeProfile.limits.timeout_s : 1800;
730849
- const _rca1DeadlineAtMs = Date.now() + (_rca1EffectiveTimeoutS + 60) * 1e3;
730815
+ const _rca1Deadline = null;
730850
730816
  if (job.pid > 0) {
730851
730817
  const runCtx = getOmniusRunContext();
730852
730818
  registerProcessLease({
@@ -730861,50 +730827,9 @@ async function handleV1Run(req3, res) {
730861
730827
  reason: `API run: ${task.slice(0, 240)}`,
730862
730828
  command: sandbox === "container" ? `container:${`omnius-${id2}`}` : [process.execPath, omniusBin, ...args].join(" "),
730863
730829
  cwd: cwd4,
730864
- hardDeadlineAt: _rca1DeadlineAtMs
730830
+ hardDeadlineAt: void 0
730865
730831
  });
730866
730832
  }
730867
- if (!_rca1KillSwitch) {
730868
- job.deadlineAtMs = _rca1DeadlineAtMs;
730869
- atomicJobWrite(dir, id2, job);
730870
- }
730871
- const _rca1Deadline = _rca1KillSwitch ? null : setTimeout(
730872
- () => {
730873
- if (job.status !== "running") return;
730874
- _rca1DeadlineFired = true;
730875
- job.status = "timeout";
730876
- job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
730877
- atomicJobWrite(dir, id2, job);
730878
- try {
730879
- if (child.pid) process.kill(-child.pid, "SIGTERM");
730880
- } catch {
730881
- }
730882
- try {
730883
- if (child.pid) process.kill(child.pid, "SIGTERM");
730884
- } catch {
730885
- }
730886
- setTimeout(() => {
730887
- try {
730888
- if (child.pid) process.kill(-child.pid, "SIGKILL");
730889
- } catch {
730890
- }
730891
- try {
730892
- if (child.pid) process.kill(child.pid, "SIGKILL");
730893
- } catch {
730894
- }
730895
- }, 3e4).unref();
730896
- try {
730897
- publishEvent(
730898
- "run.timeout",
730899
- { run_id: id2, deadline_s: _rca1EffectiveTimeoutS },
730900
- { subject: authUser, aimsControl: "A.6.2.6" }
730901
- );
730902
- } catch {
730903
- }
730904
- },
730905
- (_rca1EffectiveTimeoutS + 60) * 1e3
730906
- );
730907
- if (_rca1Deadline) _rca1Deadline.unref();
730908
730833
  if (streamMode) {
730909
730834
  res.writeHead(200, {
730910
730835
  "Content-Type": "text/event-stream",
@@ -733990,7 +733915,7 @@ ${historyLines}
733990
733915
  reason: `chat run ${session.id}`,
733991
733916
  command: [process.execPath, omniusBin, ...args].join(" "),
733992
733917
  cwd: cwdPath,
733993
- hardDeadlineAt: Date.now() + chatTimeoutS * 1e3 + 3e4
733918
+ hardDeadlineAt: void 0
733994
733919
  });
733995
733920
  }
733996
733921
  const releaseChatLease = (status2, reason) => {
@@ -734214,7 +734139,6 @@ ${historyLines}
734214
734139
  });
734215
734140
  child.stderr?.on("data", () => {
734216
734141
  });
734217
- const killDeadlineMs = chatTimeoutS * 1e3 + 3e4;
734218
734142
  let killedByDeadline = false;
734219
734143
  await new Promise((resolve77) => {
734220
734144
  let done = false;
@@ -734225,30 +734149,6 @@ ${historyLines}
734225
734149
  }
734226
734150
  };
734227
734151
  onChildClose(child, finish);
734228
- const deadline = setTimeout(() => {
734229
- if (done) return;
734230
- killedByDeadline = true;
734231
- try {
734232
- if (child.pid) process.kill(-child.pid, "SIGTERM");
734233
- } catch {
734234
- }
734235
- try {
734236
- if (child.pid) process.kill(child.pid, "SIGTERM");
734237
- } catch {
734238
- }
734239
- setTimeout(() => {
734240
- try {
734241
- if (child.pid) process.kill(-child.pid, "SIGKILL");
734242
- } catch {
734243
- }
734244
- try {
734245
- if (child.pid) process.kill(child.pid, "SIGKILL");
734246
- } catch {
734247
- }
734248
- finish();
734249
- }, 3e3).unref();
734250
- }, killDeadlineMs);
734251
- deadline.unref();
734252
734152
  });
734253
734153
  if (nonStreamBuf.trim()) nonStreamLines.push(nonStreamBuf);
734254
734154
  const rawNonStream = nonStreamLines.join("\n").trim();
@@ -734290,7 +734190,7 @@ ${historyLines}
734290
734190
  "X-Session-ID, X-Request-ID, X-API-Version, ETag"
734291
734191
  );
734292
734192
  if (!content) {
734293
- const errMsg = killedByDeadline ? `Agent exceeded ${chatTimeoutS}s timeout and was killed. Try a simpler prompt or increase timeout_s in the request body.` : backendError ? `Backend error: ${backendError}` : "Agent produced no response. The model may have failed to load (try a smaller model or check 'ollama ps' for VRAM contention).";
734193
+ const errMsg = backendError ? `Backend error: ${backendError}` : "Agent produced no response. The model may have failed to load (try a smaller model or check 'ollama ps' for VRAM contention).";
734294
734194
  try {
734295
734195
  finishInFlightChat(
734296
734196
  session.id,
@@ -739713,8 +739613,6 @@ Only tools allowed by this profile are visible and executable.`
739713
739613
  maxTokens: realtimeEnabled ? 512 : 16384,
739714
739614
  temperature: realtimeEnabled ? 0.6 : 0,
739715
739615
  requestTimeoutMs: config.timeoutMs,
739716
- taskTimeoutMs: 36e5,
739717
- // 60 minutes — never give up prematurely
739718
739616
  compactionThreshold,
739719
739617
  deepContext: deepContext ?? false,
739720
739618
  dynamicContext,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.467",
3
+ "version": "1.0.469",
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.469",
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.469",
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",