omnius 1.0.498 → 1.0.500

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)
@@ -583224,6 +583249,13 @@ ${parts.join("\n")}
583224
583249
  toolProfile: options2?.toolProfile ?? void 0,
583225
583250
  bruteForce: options2?.bruteForce ?? true,
583226
583251
  bruteForceMaxCycles: options2?.bruteForceMaxCycles ?? 100,
583252
+ // TODO-USAGE: default the empty-plan elicitation ON. Without it, a run
583253
+ // that starts with no todos NEVER receives the "create a todo plan"
583254
+ // nudge (the existing-plan reminder only fires once todos already exist —
583255
+ // a chicken-and-egg that left live runs planning-free). Turning it on
583256
+ // prompts the model to decompose into a checklist at the empty state,
583257
+ // which also feeds the per-todo context compression on completion.
583258
+ elicitTodoCreation: options2?.elicitTodoCreation ?? true,
583227
583259
  allowTurnExtension: options2?.allowTurnExtension ?? true,
583228
583260
  completionProvenanceGuard: options2?.completionProvenanceGuard ?? true,
583229
583261
  backwardPassReview: options2?.backwardPassReview,
@@ -589417,6 +589449,12 @@ Respond with your assessment, then take action.`;
589417
589449
  this._focusSupervisor = this.options.focusSupervisor === "off" ? null : new FocusSupervisor({
589418
589450
  mode: this.options.focusSupervisor,
589419
589451
  modelTier: this.options.modelTier,
589452
+ // SILENCE (operator directive): the supervisor must not stop agents
589453
+ // or re-serve cached responses from earlier commands. It observes,
589454
+ // sets directives, and advises, but every hard block downgrades to a
589455
+ // pass so the model is free to act — including re-reading to confirm
589456
+ // a change landed. Restore blocking with OMNIUS_FOCUS_SUPERVISOR_SILENT=0.
589457
+ silent: resolveFocusSupervisorSilent(),
589420
589458
  repeatGateMax: this._resolveRepeatGateMax(),
589421
589459
  availableTools: this.tools.keys(),
589422
589460
  // WO-3: convergence circuit-breaker escalates a non-converging
@@ -589533,6 +589571,7 @@ Respond with your assessment, then take action.`;
589533
589571
  }
589534
589572
  this._fileRegistry.clear();
589535
589573
  this._memexArchive.clear();
589574
+ this._todoOutputLedger.clear();
589536
589575
  this._sessionId = this.options.sessionId && String(this.options.sessionId) || process.env["OMNIUS_SESSION_ID"] && String(process.env["OMNIUS_SESSION_ID"]) || `session-${Date.now()}`;
589537
589576
  this._appState = createAppState({
589538
589577
  sessionId: this._sessionId,
@@ -598019,6 +598058,17 @@ ${result.output}`, "utf-8");
598019
598058
  } catch {
598020
598059
  }
598021
598060
  const savedPath = _pathJoin(this.omniusStateDir(), "tool-results", `${handleId}.txt`);
598061
+ this._recordTodoOutputLedgerEntry({
598062
+ memexId: handleId,
598063
+ toolName,
598064
+ target: this.extractPrimaryToolPath(args) || "",
598065
+ diskPath: savedPath,
598066
+ chars: result.output.length,
598067
+ lineCount,
598068
+ turn,
598069
+ preview: preview.slice(0, 200),
598070
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
598071
+ });
598022
598072
  const folded = this.foldOutput(modelContent, maxLen);
598023
598073
  return this.wrapToolOutputForModel(toolName, `[Tool output truncated — ${result.output.length} chars, ${lineCount} lines]
598024
598074
  Full output saved to: ${savedPath}
@@ -598238,6 +598288,76 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
598238
598288
  return content;
598239
598289
  }
598240
598290
  // ---------------------------------------------------------------------------
598291
+ // Part 3 — per-todo full-tool-output ledger
598292
+ // ---------------------------------------------------------------------------
598293
+ /**
598294
+ * The id of the todo currently in_progress (the deepest in_progress leaf), or
598295
+ * "_unassigned" when nothing is active. Full outputs externalized while this
598296
+ * is active are bound to it so completion can flush a consolidated ledger.
598297
+ */
598298
+ _activeTodoId() {
598299
+ try {
598300
+ const todos = this.readSessionTodos() || [];
598301
+ const inProgress = todos.filter((t2) => t2.status === "in_progress");
598302
+ if (inProgress.length === 0)
598303
+ return "_unassigned";
598304
+ const childless = inProgress.filter((t2) => !todos.some((c9) => c9.parentId === t2.id));
598305
+ const chosen = childless[childless.length - 1] ?? inProgress[inProgress.length - 1];
598306
+ return chosen.id || "_unassigned";
598307
+ } catch {
598308
+ return "_unassigned";
598309
+ }
598310
+ }
598311
+ /** Bind one externalized full output to the active todo's ledger. */
598312
+ _recordTodoOutputLedgerEntry(entry) {
598313
+ try {
598314
+ const key = this._activeTodoId();
598315
+ let bucket = this._todoOutputLedger.get(key);
598316
+ if (!bucket) {
598317
+ bucket = [];
598318
+ this._todoOutputLedger.set(key, bucket);
598319
+ }
598320
+ bucket.push(entry);
598321
+ const cap = 500;
598322
+ if (bucket.length > cap)
598323
+ bucket.splice(0, bucket.length - cap);
598324
+ } catch {
598325
+ }
598326
+ }
598327
+ /**
598328
+ * Flush a completed todo's full-output ledger to disk as a single compressed
598329
+ * index alongside its summary chunk, then drop it from memory. The full
598330
+ * bodies stay in .omnius/tool-results/; this file is the high-signal,
598331
+ * low-noise stub that lists what was produced and where to retrieve it.
598332
+ * Returns the ledger path when written, else null.
598333
+ */
598334
+ _flushTodoOutputLedger(todoId, todoContent, workingDir) {
598335
+ try {
598336
+ const bucket = this._todoOutputLedger.get(todoId);
598337
+ if (!bucket || bucket.length === 0)
598338
+ return null;
598339
+ const totalChars = bucket.reduce((n2, e2) => n2 + (e2.chars || 0), 0);
598340
+ const dir = _pathJoin(workingDir, ".omnius", "todo-chunks");
598341
+ _fsMkdirSync(dir, { recursive: true });
598342
+ const safeId3 = todoId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
598343
+ const ledgerPath = _pathJoin(dir, `${safeId3}.ledger.json`);
598344
+ _fsWriteFileSync(ledgerPath, JSON.stringify({
598345
+ todoId,
598346
+ todoContent: todoContent.slice(0, 300),
598347
+ entryCount: bucket.length,
598348
+ totalChars,
598349
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
598350
+ // High-signal, low-noise stubs. Each points at its full body on disk
598351
+ // and via memex_retrieve(memexId) for on-demand re-materialisation.
598352
+ outputs: bucket
598353
+ }, null, 2), "utf-8");
598354
+ this._todoOutputLedger.delete(todoId);
598355
+ return { path: ledgerPath, entryCount: bucket.length, totalChars };
598356
+ } catch {
598357
+ return null;
598358
+ }
598359
+ }
598360
+ // ---------------------------------------------------------------------------
598241
598361
  // Todo context chunker: fire-and-forget summarization of completed todo work
598242
598362
  // ---------------------------------------------------------------------------
598243
598363
  /**
@@ -598260,6 +598380,15 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
598260
598380
  sessionId: this._sessionId
598261
598381
  };
598262
598382
  this._evictCompletedTodoMessages(startTurn, currentTurn, todoId, todo.content, messages2);
598383
+ const _ledger = this._flushTodoOutputLedger(todoId, todo.content, workingDir);
598384
+ if (_ledger) {
598385
+ this.emit({
598386
+ type: "status",
598387
+ 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`,
598388
+ turn: currentTurn,
598389
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
598390
+ });
598391
+ }
598263
598392
  runTodoChunker({
598264
598393
  inputs,
598265
598394
  callable: async (prompt) => {
@@ -608949,7 +609078,7 @@ function canonicalize(value2) {
608949
609078
  return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalize(obj[k])}`).join(",")}}`;
608950
609079
  }
608951
609080
  function shouldBlockCall(fingerprint, history, opts = {}) {
608952
- const blockOnPriorSuccess = opts.blockOnPriorSuccess ?? true;
609081
+ const blockOnPriorSuccess = opts.blockOnPriorSuccess ?? false;
608953
609082
  const maxIdenticalErrors = opts.maxIdenticalErrors ?? 2;
608954
609083
  const same = history.filter((h) => h.fingerprint === fingerprint);
608955
609084
  if (same.length === 0)
@@ -679499,6 +679628,26 @@ var init_stream_renderer = __esm({
679499
679628
  }
679500
679629
  this.scheduleFlush(kind);
679501
679630
  }
679631
+ /**
679632
+ * Flush any buffered partial line and close the current row WITHOUT ending
679633
+ * the stream. Call this before out-of-band output (a tool box, a live block)
679634
+ * interleaves with an in-progress assistant stream: it forces the reasoning
679635
+ * streamed so far to land ABOVE the interleaved block instead of the tail
679636
+ * leaking BELOW it. Safe to call when idle (no-op if nothing is pending).
679637
+ */
679638
+ flushPendingLine() {
679639
+ if (!this.enabled) return;
679640
+ this.cancelFlush();
679641
+ if (this.lineBuffer.length > 0) {
679642
+ const kind = this.inThinkBlock ? "thinking" : this.inToolArgs ? "tool_args" : "content";
679643
+ this.writeHighlighted(this.lineBuffer, kind);
679644
+ this.lineBuffer = "";
679645
+ }
679646
+ if (this.lineStarted) {
679647
+ process.stdout.write("\n");
679648
+ this.lineStarted = false;
679649
+ }
679650
+ }
679502
679651
  /** Called when streaming ends for this response */
679503
679652
  onStreamEnd() {
679504
679653
  if (!this.enabled) return;
@@ -679619,8 +679768,11 @@ var init_stream_renderer = __esm({
679619
679768
  this.writeRaw("\n");
679620
679769
  this.lineStarted = false;
679621
679770
  } else if (text3.length > remaining) {
679622
- const head = text3.slice(0, firstChunkLen).replace(/\s+$/, "");
679623
- const tail = text3.slice(firstChunkLen).replace(/^\s+/, "");
679771
+ const window2 = text3.slice(0, firstChunkLen);
679772
+ const sp = window2.replace(/\s+$/, "").lastIndexOf(" ");
679773
+ const wb = sp > 0 ? sp : firstChunkLen;
679774
+ const head = text3.slice(0, wb).replace(/\s+$/, "");
679775
+ const tail = text3.slice(wb).replace(/^\s+/, "");
679624
679776
  this.writeRaw(highlight(head) + "\n");
679625
679777
  this.lineStarted = false;
679626
679778
  text3 = tail;
@@ -679634,8 +679786,8 @@ var init_stream_renderer = __esm({
679634
679786
  for (let i2 = 0; i2 < lines.length; i2++) {
679635
679787
  const isFirst = i2 === 0;
679636
679788
  const isLast = i2 === lines.length - 1;
679637
- const lp = isBlockquote && !isFirst ? " │ " : isFirst ? usePrefix : " ";
679638
- const chunk = isBlockquote && !isFirst ? "> " + lines[i2].replace(/^\s+/, "") : lines[i2];
679789
+ const lp = isFirst ? usePrefix : "";
679790
+ const chunk = isFirst ? lines[i2] : isBlockquote ? "> " + lines[i2].replace(/^\s+/, "") : lines[i2].replace(/^\s+/, "");
679639
679791
  const needsNewline = !isLast || trailingNewline;
679640
679792
  this.writeRaw(
679641
679793
  dimText(lp) + highlight(chunk) + (needsNewline ? "\n" : "")
@@ -742973,6 +743125,7 @@ function gatherMemorySnippets(root) {
742973
743125
  return snippets;
742974
743126
  }
742975
743127
  async function createSteeringIntakeBackend(config, repoRoot) {
743128
+ const normalizeSteeringBaseUrl = (url) => url.replace(/\/(v1|api)\/?$/i, "").replace(/\/+$/, "");
742976
743129
  if (config.backendType === "nexus") {
742977
743130
  const nexusTool = new NexusTool(repoRoot);
742978
743131
  await nexusTool.execute({ action: "connect" });
@@ -742985,12 +743138,8 @@ async function createSteeringIntakeBackend(config, repoRoot) {
742985
743138
  false
742986
743139
  );
742987
743140
  }
742988
- return new OllamaAgenticBackend(
742989
- config.backendUrl,
742990
- config.model,
742991
- config.apiKey,
742992
- false
742993
- );
743141
+ const steeringBaseUrl = normalizeSteeringBaseUrl(config.backendUrl);
743142
+ return new OllamaAgenticBackend(steeringBaseUrl, config.model, config.apiKey, false);
742994
743143
  }
742995
743144
  function formatTaskCompletionMeta(meta) {
742996
743145
  if (!meta) return "no prior task metrics recorded";
@@ -744517,6 +744666,7 @@ ${entry.fullContent}`
744517
744666
  `
744518
744667
  );
744519
744668
  } else {
744669
+ stream?.renderer.flushPendingLine?.();
744520
744670
  renderToolCallStart(
744521
744671
  event.toolName ?? "unknown",
744522
744672
  event.toolArgs ?? {},
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.498",
3
+ "version": "1.0.500",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.498",
9
+ "version": "1.0.500",
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.498",
3
+ "version": "1.0.500",
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",