omnius 1.0.497 → 1.0.499

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
@@ -576445,6 +576445,13 @@ var init_debugArtifactLibrary = __esm({
576445
576445
  });
576446
576446
 
576447
576447
  // packages/orchestrator/dist/focusSupervisor.js
576448
+ function resolveFocusSupervisorSilent(envValue = process.env["OMNIUS_FOCUS_SUPERVISOR_SILENT"]) {
576449
+ const normalized = String(envValue ?? "").trim().toLowerCase();
576450
+ if (normalized === "0" || normalized === "false" || normalized === "off") {
576451
+ return false;
576452
+ }
576453
+ return true;
576454
+ }
576448
576455
  function resolveFocusSupervisorMode(configured, envValue = process.env["OMNIUS_FOCUS_SUPERVISOR"]) {
576449
576456
  if (configured)
576450
576457
  return configured;
@@ -576813,9 +576820,12 @@ var init_focusSupervisor = __esm({
576813
576820
  lastIgnoredDirectiveTurn = null;
576814
576821
  repeatedViolationCounts = /* @__PURE__ */ new Map();
576815
576822
  availableTools = null;
576823
+ /** SILENCE: when true, block() downgrades to pass() (never stops a call). */
576824
+ silent;
576816
576825
  constructor(options2 = {}) {
576817
576826
  this.mode = options2.mode ?? "auto";
576818
576827
  this.modelTier = options2.modelTier ?? "large";
576828
+ this.silent = options2.silent ?? false;
576819
576829
  this.repeatGateMax = Math.max(0, Math.floor(options2.repeatGateMax ?? 3));
576820
576830
  this.availableTools = options2.availableTools ? new Set(Array.from(options2.availableTools)) : null;
576821
576831
  this.convergenceBreaker = options2.convergenceBreaker ?? null;
@@ -577291,6 +577301,11 @@ var init_focusSupervisor = __esm({
577291
577301
  };
577292
577302
  }
577293
577303
  block(directive, message2, success) {
577304
+ if (this.silent) {
577305
+ this.lastDecision = "block_silenced_pass";
577306
+ this.lastReason = directive.reason;
577307
+ return this.pass();
577308
+ }
577294
577309
  this.lastDecision = "block_tool_call";
577295
577310
  this.lastReason = directive.reason;
577296
577311
  return {
@@ -582162,6 +582177,16 @@ var init_agenticRunner = __esm({
582162
582177
  _todoInProgressTurn = /* @__PURE__ */ new Map();
582163
582178
  /** Set of todo IDs that have already been chunked */
582164
582179
  _todoChunked = /* @__PURE__ */ new Set();
582180
+ /**
582181
+ * Explicit tool-output → todo binding. As each FULL tool output is
582182
+ * externalized to .omnius/tool-results/ (the point where it would otherwise
582183
+ * bloat the context chain), we bind it to the todo that was in_progress at
582184
+ * that moment. On completion, that todo's ledger of full outputs is written
582185
+ * to disk (.omnius/todo-chunks/{id}.ledger.json) alongside the summary stub,
582186
+ * so the bulk stays retrievable but out of the live window. Keyed by todo id;
582187
+ * "_unassigned" holds outputs produced while no leaf was in_progress.
582188
+ */
582189
+ _todoOutputLedger = /* @__PURE__ */ new Map();
582165
582190
  // -- ENOENT tracker (prevents path-guessing spirals) --
582166
582191
  // Tracks both consecutive AND sliding-window ENOENT counts. The sliding
582167
582192
  // window catches oscillation patterns (success → ENOENT → success → ENOENT)
@@ -586258,8 +586283,7 @@ ${body}`;
586258
586283
  * summarization, RECOMP (ICLR 2024) observation masking.
586259
586284
  */
586260
586285
  proactivePrune(messages2, currentTurn) {
586261
- if (process.env["OMNIUS_DISABLE_PROACTIVE_PRUNE"] === "1")
586262
- return;
586286
+ return;
586263
586287
  const AGED_FILE_READ_TURNS = 20;
586264
586288
  const AGED_SHELL_TURNS = 12;
586265
586289
  const ERROR_MARKERS = /(?:error|fail|exception|traceback|enoent|enotfound|exit code [^0]|status[: ]+1\d?\d?)/i;
@@ -586273,125 +586297,148 @@ ${body}`;
586273
586297
  let scanTurn = 0;
586274
586298
  for (let i2 = 0; i2 < messages2.length; i2++) {
586275
586299
  const msg = messages2[i2];
586276
- if (msg.role === "assistant" && msg.tool_calls && msg.tool_calls.length > 0) {
586277
- scanTurn++;
586278
- for (const tc of msg.tool_calls) {
586279
- const name10 = tc.function.name;
586280
- let parsedArgs;
586281
- try {
586282
- parsedArgs = JSON.parse(tc.function.arguments || "{}");
586283
- } catch {
586284
- parsedArgs = void 0;
586285
- }
586286
- const fp = parsedArgs ? this._buildToolFingerprint(name10, parsedArgs) : `${name10}:raw#sha256:${_createHash("sha256").update(tc.function.arguments ?? "").digest("hex").slice(0, 20)}`;
586287
- let resultIdx = -1;
586288
- for (let j = i2 + 1; j < Math.min(messages2.length, i2 + 8); j++) {
586289
- const r2 = messages2[j];
586290
- if (r2.role === "tool" && r2.tool_call_id === tc.id) {
586291
- resultIdx = j;
586292
- break;
586293
- }
586294
- }
586295
- if (resultIdx === -1)
586296
- continue;
586297
- const resultMsg = messages2[resultIdx];
586298
- const content = typeof resultMsg.content === "string" ? resultMsg.content : "";
586299
- if (content.startsWith(PRUNE_PREFIX) || content.startsWith(DEDUPE_PREFIX) || content.startsWith(FILE_AGED_PREFIX) || content.startsWith(SHELL_AGED_PREFIX)) {
586300
- if (!seen.has(fp))
586301
- seen.set(fp, { turn: scanTurn, idx: resultIdx });
586302
- continue;
586300
+ if (msg.role !== "assistant") {
586301
+ continue;
586302
+ }
586303
+ const toolCalls = msg.tool_calls ?? [];
586304
+ if (toolCalls.length === 0) {
586305
+ continue;
586306
+ }
586307
+ scanTurn++;
586308
+ for (const tc of toolCalls) {
586309
+ const name10 = tc.function.name;
586310
+ let parsedArgs;
586311
+ try {
586312
+ parsedArgs = JSON.parse(tc.function.arguments || "{}");
586313
+ } catch {
586314
+ parsedArgs = void 0;
586315
+ }
586316
+ const fp = parsedArgs ? this._buildToolFingerprint(name10, parsedArgs) : `${name10}:raw#sha256:${_createHash("sha256").update(tc.function.arguments ?? "").digest("hex").slice(0, 20)}`;
586317
+ let resultIdx = -1;
586318
+ for (let j = i2 + 1; j < Math.min(messages2.length, i2 + 8); j++) {
586319
+ const r2 = messages2[j];
586320
+ if (r2.role === "tool" && r2.tool_call_id === tc.id) {
586321
+ resultIdx = j;
586322
+ break;
586303
586323
  }
586304
- const prior = seen.get(fp);
586305
- if (prior) {
586306
- const priorContent = typeof messages2[prior.idx]?.content === "string" ? messages2[prior.idx].content : "";
586324
+ }
586325
+ if (resultIdx === -1)
586326
+ continue;
586327
+ const resultMsg = messages2[resultIdx];
586328
+ const contentText = textFromMessageContent(resultMsg.content);
586329
+ if (contentText.startsWith(PRUNE_PREFIX) || contentText.startsWith(DEDUPE_PREFIX) || contentText.startsWith(FILE_AGED_PREFIX) || contentText.startsWith(SHELL_AGED_PREFIX)) {
586330
+ if (!seen.has(fp))
586331
+ seen.set(fp, { turn: scanTurn, idx: resultIdx });
586332
+ continue;
586333
+ }
586334
+ const priorIdx = seen.get(fp)?.idx;
586335
+ if (priorIdx === void 0) {
586336
+ seen.set(fp, { turn: scanTurn, idx: resultIdx });
586337
+ } else {
586338
+ const priorIdxSafe = priorIdx;
586339
+ const priorMessage = messages2[priorIdxSafe];
586340
+ if (priorMessage) {
586341
+ const priorContent = textFromMessageContent(priorMessage.content);
586307
586342
  const priorFailed = ERROR_MARKERS.test(priorContent);
586308
586343
  pending2.push({
586309
- idx: prior.idx,
586344
+ idx: priorIdxSafe,
586310
586345
  reason: "dedupe",
586311
586346
  replacement: priorFailed ? `${DEDUPE_PREFIX} ${scanTurn} — duplicate ${name10}() call; the earlier call FAILED (same error as the retained copy below). Do not retry identically.]` : `${DEDUPE_PREFIX} ${scanTurn} — duplicate ${name10}() call]`
586312
586347
  });
586313
- seen.set(fp, { turn: scanTurn, idx: resultIdx });
586314
- continue;
586315
586348
  }
586316
- seen.set(fp, { turn: scanTurn, idx: resultIdx });
586317
- const rkey = this._buildResourceKey(name10, parsedArgs);
586318
- if (rkey) {
586319
- const priorResource = seenResource.get(rkey);
586320
- if (priorResource && priorResource.idx !== resultIdx) {
586321
- const priorContent = typeof messages2[priorResource.idx]?.content === "string" ? messages2[priorResource.idx].content : "";
586349
+ continue;
586350
+ }
586351
+ const rkey = this._buildResourceKey(name10, parsedArgs);
586352
+ if (rkey) {
586353
+ const priorResourceIdx = seenResource.get(rkey)?.idx;
586354
+ if (priorResourceIdx === void 0) {
586355
+ seenResource.set(rkey, { turn: scanTurn, idx: resultIdx });
586356
+ } else if (priorResourceIdx !== resultIdx) {
586357
+ const priorResourceIdxSafe = priorResourceIdx;
586358
+ const priorResourceMessage = messages2[priorResourceIdxSafe];
586359
+ if (priorResourceMessage) {
586360
+ const priorContent = textFromMessageContent(priorResourceMessage.content);
586322
586361
  if (!priorContent.startsWith(PRUNE_PREFIX) && !priorContent.startsWith(DEDUPE_PREFIX) && !priorContent.startsWith(FILE_AGED_PREFIX)) {
586323
586362
  const priorResFailed = ERROR_MARKERS.test(priorContent);
586324
586363
  pending2.push({
586325
- idx: priorResource.idx,
586364
+ idx: priorResourceIdxSafe,
586326
586365
  reason: "dedupe",
586327
586366
  replacement: priorResFailed ? `${DEDUPE_PREFIX} ${scanTurn} — semantic duplicate ${name10}() (same resource: ${rkey}); the earlier call FAILED. Do not retry identically.]` : `${DEDUPE_PREFIX} ${scanTurn} — semantic duplicate ${name10}() (same resource: ${rkey})]`
586328
586367
  });
586329
586368
  }
586330
586369
  }
586331
586370
  seenResource.set(rkey, { turn: scanTurn, idx: resultIdx });
586371
+ } else {
586372
+ seenResource.set(rkey, {
586373
+ turn: scanTurn,
586374
+ idx: priorResourceIdx
586375
+ });
586332
586376
  }
586333
- const ageTurns = currentTurn - scanTurn;
586334
- const wasRecentlyWritten = (() => {
586335
- try {
586336
- const o2 = JSON.parse(tc.function.arguments || "{}");
586337
- const p2 = String(o2.path ?? o2.file ?? "");
586338
- for (let k = Math.max(0, i2 - 20); k < i2; k++) {
586339
- const m2 = messages2[k];
586340
- if (m2.role === "assistant" && m2.tool_calls) {
586341
- for (const tc2 of m2.tool_calls) {
586342
- if ((tc2.function.name === "file_edit" || tc2.function.name === "file_write" || tc2.function.name === "file_patch") && tc2.function.arguments?.includes(p2)) {
586343
- return true;
586344
- }
586377
+ }
586378
+ const ageTurns = currentTurn - scanTurn;
586379
+ const wasRecentlyWritten = (() => {
586380
+ try {
586381
+ const o2 = JSON.parse(tc.function.arguments || "{}");
586382
+ const p2 = String(o2.path ?? o2.file ?? "");
586383
+ for (let k = Math.max(0, i2 - 20); k < i2; k++) {
586384
+ const m2 = messages2[k];
586385
+ const priorTurnToolCalls = m2.tool_calls ?? [];
586386
+ if (m2.role === "assistant") {
586387
+ for (const tc2 of priorTurnToolCalls) {
586388
+ if ((tc2.function.name === "file_edit" || tc2.function.name === "file_write" || tc2.function.name === "file_patch") && tc2.function.arguments?.includes(p2)) {
586389
+ return true;
586345
586390
  }
586346
586391
  }
586347
586392
  }
586348
- return false;
586393
+ }
586394
+ return false;
586395
+ } catch {
586396
+ return false;
586397
+ }
586398
+ })();
586399
+ if (name10 === "file_read" && ageTurns > AGED_FILE_READ_TURNS && contentText.length > 200 && !wasRecentlyWritten) {
586400
+ const pathArg = (() => {
586401
+ try {
586402
+ const o2 = JSON.parse(tc.function.arguments || "{}");
586403
+ return String(o2.path ?? o2.file ?? "?");
586349
586404
  } catch {
586350
- return false;
586405
+ return "?";
586351
586406
  }
586352
586407
  })();
586353
- if (name10 === "file_read" && ageTurns > AGED_FILE_READ_TURNS && content.length > 200 && !wasRecentlyWritten) {
586354
- const pathArg = (() => {
586355
- try {
586356
- const o2 = JSON.parse(tc.function.arguments || "{}");
586357
- return String(o2.path ?? o2.file ?? "?");
586358
- } catch {
586359
- return "?";
586360
- }
586361
- })();
586362
- const lines = content.split("\n");
586363
- const lineCount = lines.length;
586364
- const contentPreview = content.slice(0, 500);
586365
- pending2.push({
586366
- idx: resultIdx,
586367
- reason: "aged_file",
586368
- replacement: `${FILE_AGED_PREFIX} path=${pathArg}, ${lineCount} lines, ${content.length} chars]
586408
+ const lines = contentText.split("\n");
586409
+ const lineCount = lines.length;
586410
+ const contentPreview = contentText.slice(0, 500);
586411
+ pending2.push({
586412
+ idx: resultIdx,
586413
+ reason: "aged_file",
586414
+ replacement: `${FILE_AGED_PREFIX} path=${pathArg}, ${lineCount} lines, ${contentText.length} chars]
586369
586415
  ${contentPreview}
586370
586416
  [End of aged file_read preview — do NOT re-read this file, use the content above]`
586371
- });
586372
- continue;
586373
- }
586374
- if ((name10 === "shell" || name10 === "shell_async" || name10 === "run_tests") && ageTurns > AGED_SHELL_TURNS && content.length > 200 && !ERROR_MARKERS.test(content)) {
586375
- const cmdArg = (() => {
586376
- try {
586377
- const o2 = JSON.parse(tc.function.arguments || "{}");
586378
- return String(o2.command ?? o2.cmd ?? "?").slice(0, 80);
586379
- } catch {
586380
- return "?";
586381
- }
586382
- })();
586383
- pending2.push({
586384
- idx: resultIdx,
586385
- reason: "aged_shell",
586386
- replacement: `${SHELL_AGED_PREFIX} command="${cmdArg}", output ${content.length} chars, no error markers detected]`
586387
- });
586388
- }
586417
+ });
586418
+ continue;
586419
+ }
586420
+ if ((name10 === "shell" || name10 === "shell_async" || name10 === "run_tests") && ageTurns > AGED_SHELL_TURNS && contentText.length > 200 && !ERROR_MARKERS.test(contentText)) {
586421
+ const cmdArg = (() => {
586422
+ try {
586423
+ const o2 = JSON.parse(tc.function.arguments || "{}");
586424
+ return String(o2.command ?? o2.cmd ?? "?").slice(0, 80);
586425
+ } catch {
586426
+ return "?";
586427
+ }
586428
+ })();
586429
+ pending2.push({
586430
+ idx: resultIdx,
586431
+ reason: "aged_shell",
586432
+ replacement: `${SHELL_AGED_PREFIX} command="${cmdArg}", output ${contentText.length} chars, no error markers detected]`
586433
+ });
586389
586434
  }
586390
586435
  }
586391
586436
  }
586392
586437
  if (pending2.length === 0)
586393
586438
  return;
586394
- let dedupes = 0, agedFiles = 0, agedShells = 0;
586439
+ let dedupes = 0;
586440
+ let agedFiles = 0;
586441
+ let agedShells = 0;
586395
586442
  for (const p2 of pending2) {
586396
586443
  const m2 = messages2[p2.idx];
586397
586444
  if (!m2)
@@ -587527,7 +587574,7 @@ ${sections.join("\n")}` : sections.join("\n");
587527
587574
  }
587528
587575
  }
587529
587576
  const sections = [
587530
- "[KNOWLEDGE — cached tool results already known to the runtime. Repeating an exact read/list/search/shell call is a wasted action and will be blocked or served from cache:]"
587577
+ "[KNOWLEDGE — recent tool results for reference. Re-reading a file after an edit is encouraged to capture the latest content; exact re-reads are NOT blocked and always return fresh, up-to-date data.]"
587531
587578
  ];
587532
587579
  if (compactedCount > 0) {
587533
587580
  sections.push(`Compacted cached entries still count as already-known results (${compactedCount}); an exact repeat will be served from cache or skipped, not produce new information.`);
@@ -588419,8 +588466,7 @@ ${blob}
588419
588466
  /** Extract (path, [start,end], whole) for a region-coalesceable read, else null. */
588420
588467
  _readIntervalFromArgs(name10, args) {
588421
588468
  const canonical = this.lookupRegisteredTool(name10)?.name ?? name10;
588422
- if (canonical !== "file_read")
588423
- return null;
588469
+ return null;
588424
588470
  const a2 = args ?? {};
588425
588471
  const path13 = typeof a2["path"] === "string" && a2["path"] || typeof a2["file"] === "string" && a2["file"] || typeof a2["file_path"] === "string" && a2["file_path"] || "";
588426
588472
  if (!path13)
@@ -588428,8 +588474,12 @@ ${blob}
588428
588474
  const offset = typeof a2["offset"] === "number" ? a2["offset"] : void 0;
588429
588475
  const limit = typeof a2["limit"] === "number" ? a2["limit"] : void 0;
588430
588476
  const whole = offset === void 0 && limit === void 0;
588477
+ const safeLimit = limit ?? 0;
588431
588478
  const start2 = Math.max(1, offset ?? 1);
588432
- const end = whole ? Number.POSITIVE_INFINITY : limit !== void 0 ? start2 + Math.max(0, limit) - 1 : Number.POSITIVE_INFINITY;
588479
+ let end = Number.POSITIVE_INFINITY;
588480
+ if (!whole) {
588481
+ end = start2 + Math.max(0, safeLimit) - 1;
588482
+ }
588433
588483
  return { key: `${canonical}|${path13}`, start: start2, end, whole };
588434
588484
  }
588435
588485
  /**
@@ -589392,6 +589442,12 @@ Respond with your assessment, then take action.`;
589392
589442
  this._focusSupervisor = this.options.focusSupervisor === "off" ? null : new FocusSupervisor({
589393
589443
  mode: this.options.focusSupervisor,
589394
589444
  modelTier: this.options.modelTier,
589445
+ // SILENCE (operator directive): the supervisor must not stop agents
589446
+ // or re-serve cached responses from earlier commands. It observes,
589447
+ // sets directives, and advises, but every hard block downgrades to a
589448
+ // pass so the model is free to act — including re-reading to confirm
589449
+ // a change landed. Restore blocking with OMNIUS_FOCUS_SUPERVISOR_SILENT=0.
589450
+ silent: resolveFocusSupervisorSilent(),
589395
589451
  repeatGateMax: this._resolveRepeatGateMax(),
589396
589452
  availableTools: this.tools.keys(),
589397
589453
  // WO-3: convergence circuit-breaker escalates a non-converging
@@ -589508,6 +589564,7 @@ Respond with your assessment, then take action.`;
589508
589564
  }
589509
589565
  this._fileRegistry.clear();
589510
589566
  this._memexArchive.clear();
589567
+ this._todoOutputLedger.clear();
589511
589568
  this._sessionId = this.options.sessionId && String(this.options.sessionId) || process.env["OMNIUS_SESSION_ID"] && String(process.env["OMNIUS_SESSION_ID"]) || `session-${Date.now()}`;
589512
589569
  this._appState = createAppState({
589513
589570
  sessionId: this._sessionId,
@@ -592210,7 +592267,7 @@ ${memoryLines.join("\n")}`
592210
592267
  if (msg.toolCalls && msg.toolCalls.length > 0) {
592211
592268
  consecutiveTextOnly = 0;
592212
592269
  consecutiveThinkOnly = 0;
592213
- msg.toolCalls = this._dedupeToolCallsForResponse(msg.toolCalls, turn);
592270
+ msg.toolCalls = msg.toolCalls;
592214
592271
  if (msg.toolCalls.length === 0) {
592215
592272
  messages2.push({
592216
592273
  role: "system",
@@ -592937,7 +592994,7 @@ Read the current file if needed, make a different concrete edit, or move to veri
592937
592994
  }
592938
592995
  const _repeatGateMax = this._resolveRepeatGateMax();
592939
592996
  const isFailedShellRepeat = tc.name === "shell" && typeof _existingFp?.result === "string" && _existingFp.result.includes("status: failure") && !shellLikelyMutatesFilesystem;
592940
- const repeatGateEligible = isReadLike || tc.name === "memory_write" || isFailedShellRepeat;
592997
+ const repeatGateEligible = tc.name === "memory_write" || isFailedShellRepeat;
592941
592998
  const suppressSuccessfulShellCacheGuidance = tc.name === "shell" && !isFailedShellRepeat;
592942
592999
  if (suppressSuccessfulShellCacheGuidance)
592943
593000
  criticGuidance = null;
@@ -595962,7 +596019,7 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
595962
596019
  if (msg.toolCalls && msg.toolCalls.length > 0) {
595963
596020
  consecutiveTextOnly = 0;
595964
596021
  consecutiveThinkOnly = 0;
595965
- msg.toolCalls = this._dedupeToolCallsForResponse(msg.toolCalls, turn);
596022
+ msg.toolCalls = msg.toolCalls;
595966
596023
  if (msg.toolCalls.length === 0) {
595967
596024
  messages2.push({
595968
596025
  role: "system",
@@ -597994,6 +598051,17 @@ ${result.output}`, "utf-8");
597994
598051
  } catch {
597995
598052
  }
597996
598053
  const savedPath = _pathJoin(this.omniusStateDir(), "tool-results", `${handleId}.txt`);
598054
+ this._recordTodoOutputLedgerEntry({
598055
+ memexId: handleId,
598056
+ toolName,
598057
+ target: this.extractPrimaryToolPath(args) || "",
598058
+ diskPath: savedPath,
598059
+ chars: result.output.length,
598060
+ lineCount,
598061
+ turn,
598062
+ preview: preview.slice(0, 200),
598063
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
598064
+ });
597997
598065
  const folded = this.foldOutput(modelContent, maxLen);
597998
598066
  return this.wrapToolOutputForModel(toolName, `[Tool output truncated — ${result.output.length} chars, ${lineCount} lines]
597999
598067
  Full output saved to: ${savedPath}
@@ -598213,6 +598281,76 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
598213
598281
  return content;
598214
598282
  }
598215
598283
  // ---------------------------------------------------------------------------
598284
+ // Part 3 — per-todo full-tool-output ledger
598285
+ // ---------------------------------------------------------------------------
598286
+ /**
598287
+ * The id of the todo currently in_progress (the deepest in_progress leaf), or
598288
+ * "_unassigned" when nothing is active. Full outputs externalized while this
598289
+ * is active are bound to it so completion can flush a consolidated ledger.
598290
+ */
598291
+ _activeTodoId() {
598292
+ try {
598293
+ const todos = this.readSessionTodos() || [];
598294
+ const inProgress = todos.filter((t2) => t2.status === "in_progress");
598295
+ if (inProgress.length === 0)
598296
+ return "_unassigned";
598297
+ const childless = inProgress.filter((t2) => !todos.some((c9) => c9.parentId === t2.id));
598298
+ const chosen = childless[childless.length - 1] ?? inProgress[inProgress.length - 1];
598299
+ return chosen.id || "_unassigned";
598300
+ } catch {
598301
+ return "_unassigned";
598302
+ }
598303
+ }
598304
+ /** Bind one externalized full output to the active todo's ledger. */
598305
+ _recordTodoOutputLedgerEntry(entry) {
598306
+ try {
598307
+ const key = this._activeTodoId();
598308
+ let bucket = this._todoOutputLedger.get(key);
598309
+ if (!bucket) {
598310
+ bucket = [];
598311
+ this._todoOutputLedger.set(key, bucket);
598312
+ }
598313
+ bucket.push(entry);
598314
+ const cap = 500;
598315
+ if (bucket.length > cap)
598316
+ bucket.splice(0, bucket.length - cap);
598317
+ } catch {
598318
+ }
598319
+ }
598320
+ /**
598321
+ * Flush a completed todo's full-output ledger to disk as a single compressed
598322
+ * index alongside its summary chunk, then drop it from memory. The full
598323
+ * bodies stay in .omnius/tool-results/; this file is the high-signal,
598324
+ * low-noise stub that lists what was produced and where to retrieve it.
598325
+ * Returns the ledger path when written, else null.
598326
+ */
598327
+ _flushTodoOutputLedger(todoId, todoContent, workingDir) {
598328
+ try {
598329
+ const bucket = this._todoOutputLedger.get(todoId);
598330
+ if (!bucket || bucket.length === 0)
598331
+ return null;
598332
+ const totalChars = bucket.reduce((n2, e2) => n2 + (e2.chars || 0), 0);
598333
+ const dir = _pathJoin(workingDir, ".omnius", "todo-chunks");
598334
+ _fsMkdirSync(dir, { recursive: true });
598335
+ const safeId3 = todoId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
598336
+ const ledgerPath = _pathJoin(dir, `${safeId3}.ledger.json`);
598337
+ _fsWriteFileSync(ledgerPath, JSON.stringify({
598338
+ todoId,
598339
+ todoContent: todoContent.slice(0, 300),
598340
+ entryCount: bucket.length,
598341
+ totalChars,
598342
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
598343
+ // High-signal, low-noise stubs. Each points at its full body on disk
598344
+ // and via memex_retrieve(memexId) for on-demand re-materialisation.
598345
+ outputs: bucket
598346
+ }, null, 2), "utf-8");
598347
+ this._todoOutputLedger.delete(todoId);
598348
+ return { path: ledgerPath, entryCount: bucket.length, totalChars };
598349
+ } catch {
598350
+ return null;
598351
+ }
598352
+ }
598353
+ // ---------------------------------------------------------------------------
598216
598354
  // Todo context chunker: fire-and-forget summarization of completed todo work
598217
598355
  // ---------------------------------------------------------------------------
598218
598356
  /**
@@ -598235,6 +598373,15 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
598235
598373
  sessionId: this._sessionId
598236
598374
  };
598237
598375
  this._evictCompletedTodoMessages(startTurn, currentTurn, todoId, todo.content, messages2);
598376
+ const _ledger = this._flushTodoOutputLedger(todoId, todo.content, workingDir);
598377
+ if (_ledger) {
598378
+ this.emit({
598379
+ type: "status",
598380
+ content: `[todo-ledger] "${todo.content.slice(0, 60)}": ${_ledger.entryCount} full output(s) (~${Math.round(_ledger.totalChars / 4)} tok) consolidated to ${_ledger.path} — retrievable via memex_retrieve or the tool-results files`,
598381
+ turn: currentTurn,
598382
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
598383
+ });
598384
+ }
598238
598385
  runTodoChunker({
598239
598386
  inputs,
598240
598387
  callable: async (prompt) => {
@@ -608924,7 +609071,7 @@ function canonicalize(value2) {
608924
609071
  return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalize(obj[k])}`).join(",")}}`;
608925
609072
  }
608926
609073
  function shouldBlockCall(fingerprint, history, opts = {}) {
608927
- const blockOnPriorSuccess = opts.blockOnPriorSuccess ?? true;
609074
+ const blockOnPriorSuccess = opts.blockOnPriorSuccess ?? false;
608928
609075
  const maxIdenticalErrors = opts.maxIdenticalErrors ?? 2;
608929
609076
  const same = history.filter((h) => h.fingerprint === fingerprint);
608930
609077
  if (same.length === 0)
@@ -745514,30 +745661,9 @@ function extractEnhancedPrompt(raw) {
745514
745661
  if (!text2.startsWith("{") && !text2.startsWith("[")) return text2;
745515
745662
  return null;
745516
745663
  }
745517
- async function enhancePromptViaInference(seed, ctx3) {
745664
+ async function enhancePromptViaInference(seed, backend, ctx3) {
745518
745665
  const seedText = seed.trim();
745519
745666
  if (!seedText) return null;
745520
- let backend;
745521
- try {
745522
- if (ctx3.config.backendType === "nexus") {
745523
- const nexusTool = new NexusTool(ctx3.repoRoot);
745524
- const peer = ctx3.config.backendUrl.startsWith("peer://") ? ctx3.config.backendUrl.slice(7) : void 0;
745525
- backend = new NexusAgenticBackend(
745526
- nexusTool.sendCommand.bind(nexusTool),
745527
- ctx3.config.model,
745528
- peer,
745529
- ctx3.config.apiKey
745530
- );
745531
- } else {
745532
- backend = new OllamaAgenticBackend(
745533
- ctx3.config.backendUrl,
745534
- ctx3.config.model,
745535
- ctx3.config.apiKey
745536
- );
745537
- }
745538
- } catch {
745539
- return null;
745540
- }
745541
745667
  const recent = ctx3.recentHistory.filter((h) => h && h.trim()).slice(0, 5).map((h, i2) => ` ${i2 + 1}. ${h.trim().slice(0, 240)}`).join("\n");
745542
745668
  let runtimeCtx = "";
745543
745669
  try {
@@ -747180,8 +747306,13 @@ This is an independent background session started from /background.`
747180
747306
  }
747181
747307
  });
747182
747308
  statusBar.setEnhanceHandler(async (seedPrompt) => {
747183
- return enhancePromptViaInference(seedPrompt, {
747184
- config: currentConfig,
747309
+ let enhanceBackend;
747310
+ try {
747311
+ enhanceBackend = activeTask ? activeTask.runner.getBackend() : await createSteeringIntakeBackend(currentConfig, repoRoot);
747312
+ } catch {
747313
+ return null;
747314
+ }
747315
+ return enhancePromptViaInference(seedPrompt, enhanceBackend, {
747185
747316
  repoRoot,
747186
747317
  recentHistory: savedHistory,
747187
747318
  activeGoal: activeTask ? lastSubmittedPrompt : void 0
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.497",
3
+ "version": "1.0.499",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.497",
9
+ "version": "1.0.499",
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.497",
3
+ "version": "1.0.499",
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",