omnius 1.0.538 → 1.0.540

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
@@ -573290,17 +573290,18 @@ function buildTrajectoryCheckpoint(input) {
573290
573290
  const focus = sanitizeTrajectoryText(input.focusDirective, 300);
573291
573291
  const targetPath = inferTargetPath(combinedFailure || outcomeText || focus) ?? latestFailure?.targetPath ?? mostRecentTargetForTool(observations, latestFailure?.toolName);
573292
573292
  const targetFreshness = targetPath ? input.evidenceFreshness?.(targetPath) ?? "unknown" : "unknown";
573293
+ const modifiedFiles = Array.from(state.modifiedFiles).slice(-3);
573293
573294
  const fullWriteIssue = (latestFailure?.toolName === "file_write" || fallbackFailure?.tool === "file_write" || /file_write/i.test(combinedFailure)) && /FULL FILE (?:WRITE LOOP BLOCKED|REWRITE CONTRACT)|overwrite(?:=true)?|expected_hash|Refusing to overwrite existing file/i.test(combinedFailure);
573295
+ const fullWriteRecoveredByMutation = fullWriteIssue && Boolean(targetPath) && modifiedFiles.some(([path16]) => sameProjectPath(path16, targetPath)) && typeof latestFailure?.turn === "number" && typeof input.lastMutationTurn === "number" && input.lastMutationTurn > latestFailure.turn;
573294
573296
  const explicitBlock = /(?:permission denied|needs user input|ask_user|cannot proceed|external dependency|\[.*BLOCKED\])/i.test(combinedFailure);
573295
573297
  const hasRecentFailure = Boolean(combinedFailure);
573296
- const modifiedFiles = Array.from(state.modifiedFiles).slice(-3);
573297
573298
  const verifierDue = modifiedFiles.length > 0 && (input.lastVerifier?.turn === void 0 || input.lastMutationTurn !== void 0 && (input.lastVerifier.turn ?? -1) < input.lastMutationTurn);
573298
573299
  let assessment = "on_trajectory";
573299
573300
  let nextAction = sanitizeTrajectoryText(state.nextAction, 260) || "Take one narrow, evidence-backed action that advances the active task.";
573300
573301
  let successEvidence = "A tool result directly confirms the next action advanced the stated goal.";
573301
573302
  const openQuestions = [];
573302
573303
  const doNotRepeat = [];
573303
- if (fullWriteIssue) {
573304
+ if (fullWriteIssue && !fullWriteRecoveredByMutation) {
573304
573305
  assessment = "recovery_required";
573305
573306
  const target = targetPath || "the existing target file";
573306
573307
  nextAction = targetFreshness === "fresh" ? `Use file_edit/file_patch for the local change in ${target}; do not resume full-file writes.` : `file_read ${target}, then prefer file_edit/file_patch for the local change.`;
@@ -573309,7 +573310,7 @@ function buildTrajectoryCheckpoint(input) {
573309
573310
  if (targetFreshness !== "fresh") {
573310
573311
  openQuestions.push(`Current bytes/hash for ${target} are not freshly evidenced.`);
573311
573312
  }
573312
- } else if (explicitBlock) {
573313
+ } else if (explicitBlock && !fullWriteRecoveredByMutation) {
573313
573314
  assessment = "blocked";
573314
573315
  nextAction = "Resolve or report the explicit blocker with the evidence that established it.";
573315
573316
  successEvidence = "A new observation removes the blocker or documents why it cannot be removed.";
@@ -573319,7 +573320,7 @@ function buildTrajectoryCheckpoint(input) {
573319
573320
  nextAction = extractFocusNextAction(focus) || nextAction;
573320
573321
  successEvidence = "The focus recovery requirement is satisfied by a fresh tool observation.";
573321
573322
  doNotRepeat.push("Ignoring the active focus recovery directive.");
573322
- } else if (hasRecentFailure) {
573323
+ } else if (hasRecentFailure && !fullWriteRecoveredByMutation) {
573323
573324
  assessment = "recovery_required";
573324
573325
  nextAction = "Use the newest failure evidence to make one different, narrow diagnostic or repair action.";
573325
573326
  successEvidence = "The next tool result changes, resolves, or explicitly narrows the observed failure.";
@@ -573329,6 +573330,9 @@ function buildTrajectoryCheckpoint(input) {
573329
573330
  nextAction = "Run the declared verifier or the narrowest relevant validation for the recent mutation.";
573330
573331
  successEvidence = "A post-mutation verifier result is recorded.";
573331
573332
  }
573333
+ if (fullWriteIssue && fullWriteRecoveredByMutation) {
573334
+ doNotRepeat.push("Returning to unguarded file_write after the targeted repair; verify the repair first.");
573335
+ }
573332
573336
  const groundedFacts = [];
573333
573337
  if (state.currentStep.trim()) {
573334
573338
  groundedFacts.push({
@@ -573479,6 +573483,12 @@ function mostRecentTargetForTool(observations, toolName) {
573479
573483
  }
573480
573484
  return null;
573481
573485
  }
573486
+ function sameProjectPath(left, right) {
573487
+ const normalize3 = (value2) => String(value2 ?? "").replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/\/+/g, "/").replace(/\/+$/, "");
573488
+ const a2 = normalize3(left);
573489
+ const b = normalize3(right);
573490
+ return Boolean(a2 && b) && (a2 === b || a2.endsWith(`/${b}`) || b.endsWith(`/${a2}`));
573491
+ }
573482
573492
  function extractFocusNextAction(value2) {
573483
573493
  const match = /(?:Required next action|Next action)\s*:\s*(.+?)(?=\s+(?:Success evidence|Do not repeat|Attention rule)|$)/i.exec(value2);
573484
573494
  if (match?.[1])
@@ -577931,7 +577941,7 @@ function retireDuplicateToolFailures(messages2) {
577931
577941
  }
577932
577942
  out[index] = {
577933
577943
  ...message2,
577934
- content: "[retired_duplicate_tool_failure] a newer matching failure appears later. Use that latest diagnostic; retry only after refreshing prerequisite evidence or correcting the arguments."
577944
+ content: "[retired_duplicate_tool_failure] a newer matching result appears later. Use that latest diagnostic; retry only after refreshing prerequisite evidence or correcting the arguments."
577935
577945
  };
577936
577946
  }
577937
577947
  return out;
@@ -580288,6 +580298,16 @@ var init_focusSupervisor = __esm({
580288
580298
  }
580289
580299
  return action;
580290
580300
  }
580301
+ /**
580302
+ * In silent small-model runner mode, cached failed shell output is diagnostic
580303
+ * evidence, not a substitute for recovery. Asking a small model to "use cached
580304
+ * evidence" repeatedly was itself a loop: it neither changed code nor
580305
+ * selected a new diagnostic. Direct/strict supervisor consumers retain the
580306
+ * legacy cache directive and its hard-block semantics.
580307
+ */
580308
+ shellFailureRequiredNextAction() {
580309
+ return this.silent && this.modelTier === "small" ? "creative_pivot_or_research" : "use_cached_evidence";
580310
+ }
580291
580311
  snapshot() {
580292
580312
  return {
580293
580313
  mode: this.mode,
@@ -580440,11 +580460,12 @@ var init_focusSupervisor = __esm({
580440
580460
  const advisoryOnly = this.repeatGateMax === 0;
580441
580461
  const hitLimit = input.cachedResultFailed ? 1 : Math.max(1, this.repeatGateMax - 1);
580442
580462
  const state = input.cachedResultFailed || duplicateHitCount >= hitLimit ? "cached_evidence" : "warn";
580463
+ const requiredNextAction = input.cachedResultFailed && input.toolName === "shell" ? this.shellFailureRequiredNextAction() : "use_cached_evidence";
580443
580464
  const directive = this.setDirective({
580444
580465
  turn: input.turn,
580445
580466
  state,
580446
580467
  reason: input.cachedResultFailed ? `cached failed ${input.toolName} evidence already exists` : `duplicate ${input.toolName} call has cached evidence`,
580447
- requiredNextAction: "use_cached_evidence",
580468
+ requiredNextAction,
580448
580469
  forbiddenActionFamilies: forbiddenCachedEvidenceFamilies(input, family)
580449
580470
  });
580450
580471
  if (strict && !advisoryOnly && (input.cachedResultFailed || duplicateHitCount >= hitLimit)) {
@@ -580560,7 +580581,7 @@ var init_focusSupervisor = __esm({
580560
580581
  actionFamily(input.toolName, input.args, this.familyCwd),
580561
580582
  input.toolName
580562
580583
  ]) : input.toolName === "shell" ? [actionFamily(input.toolName, input.args, this.familyCwd)] : [actionFamily(input.toolName, input.args, this.familyCwd)];
580563
- const requiredNextAction = ambiguousEditFailure ? "disambiguate_edit_match" : staleEditFailure ? "read_authoritative_target" : input.toolName === "shell" ? "use_cached_evidence" : this.resolveRequiredNextAction("update_todos");
580584
+ const requiredNextAction = ambiguousEditFailure ? "disambiguate_edit_match" : staleEditFailure ? "read_authoritative_target" : input.toolName === "shell" ? this.shellFailureRequiredNextAction() : this.resolveRequiredNextAction("update_todos");
580564
580585
  this.setDirective({
580565
580586
  turn: input.turn,
580566
580587
  state: "forced_replan",
@@ -580572,10 +580593,10 @@ var init_focusSupervisor = __esm({
580572
580593
  const ambiguousEditFailure = isEditTool(input.toolName) && next.errorClass === "stale_ambiguous_target";
580573
580594
  const staleEditFailure = isEditTool(input.toolName) && next.errorClass.startsWith("stale_");
580574
580595
  const shellFailure = input.toolName === "shell";
580575
- const requiredNextAction = ambiguousEditFailure ? "disambiguate_edit_match" : staleEditFailure ? "read_authoritative_target" : shellFailure ? "use_cached_evidence" : this.resolveRequiredNextAction("update_todos");
580596
+ const requiredNextAction = ambiguousEditFailure ? "disambiguate_edit_match" : staleEditFailure ? "read_authoritative_target" : shellFailure ? this.shellFailureRequiredNextAction() : this.resolveRequiredNextAction("update_todos");
580576
580597
  this.setDirective({
580577
580598
  turn: input.turn,
580578
- state: shellFailure ? "cached_evidence" : "warn",
580599
+ state: shellFailure && !this.silent ? "cached_evidence" : "warn",
580579
580600
  reason: `first ${input.toolName} failure (${next.errorClass}): ${next.sample}`,
580580
580601
  requiredNextAction,
580581
580602
  forbiddenActionFamilies: shellFailure ? [actionFamily(input.toolName, input.args, this.familyCwd)] : [actionFamily(input.toolName, input.args, this.familyCwd)]
@@ -594299,12 +594320,13 @@ ${blob}
594299
594320
  this._readCoverage.set(iv.key, pruned.slice(0, 8));
594300
594321
  }
594301
594322
  _dedupeToolCallsForResponse(toolCalls, turn) {
594302
- if (toolCalls.length <= 1)
594303
- return toolCalls;
594323
+ const idDeduped = this._dedupeRepeatedToolCallIdsForResponse(toolCalls, turn);
594324
+ if (idDeduped.length <= 1)
594325
+ return idDeduped;
594304
594326
  const seen = /* @__PURE__ */ new Set();
594305
594327
  const deduped = [];
594306
594328
  let dropped = 0;
594307
- for (const tc of toolCalls) {
594329
+ for (const tc of idDeduped) {
594308
594330
  const fp = this._buildToolFingerprint(tc.name, tc.arguments ?? {});
594309
594331
  if (seen.has(fp)) {
594310
594332
  dropped++;
@@ -594322,6 +594344,36 @@ ${blob}
594322
594344
  }
594323
594345
  return deduped;
594324
594346
  }
594347
+ /**
594348
+ * A provider must never reuse a tool-call ID in one assistant response.
594349
+ * Keep the first occurrence as the canonical call and drop later copies
594350
+ * before either execution or transcript construction. This is deliberately
594351
+ * narrower than fingerprint dedupe: the brute-force loop must still permit
594352
+ * legitimate fresh reads that use distinct call IDs.
594353
+ */
594354
+ _dedupeRepeatedToolCallIdsForResponse(toolCalls, turn) {
594355
+ if (toolCalls.length <= 1)
594356
+ return toolCalls;
594357
+ const seenIds = /* @__PURE__ */ new Set();
594358
+ const deduped = [];
594359
+ let dropped = 0;
594360
+ for (const tc of toolCalls) {
594361
+ if (seenIds.has(tc.id)) {
594362
+ dropped++;
594363
+ continue;
594364
+ }
594365
+ seenIds.add(tc.id);
594366
+ deduped.push(tc);
594367
+ }
594368
+ if (dropped > 0) {
594369
+ this.emit({
594370
+ type: "status",
594371
+ content: `Response ID dedupe: dropped ${dropped} repeated tool call ID${dropped === 1 ? "" : "s"} before execution (turn ${turn})`,
594372
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
594373
+ });
594374
+ }
594375
+ return deduped;
594376
+ }
594325
594377
  _decodeToolFingerprint(fingerprint) {
594326
594378
  const colonIdx = fingerprint.indexOf(":");
594327
594379
  const toolName = colonIdx > 0 ? fingerprint.slice(0, colonIdx) : fingerprint;
@@ -602228,7 +602280,7 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
602228
602280
  if (msg.toolCalls && msg.toolCalls.length > 0) {
602229
602281
  consecutiveTextOnly = 0;
602230
602282
  consecutiveThinkOnly = 0;
602231
- msg.toolCalls = msg.toolCalls;
602283
+ msg.toolCalls = this._dedupeRepeatedToolCallIdsForResponse(msg.toolCalls, turn);
602232
602284
  if (msg.toolCalls.length === 0) {
602233
602285
  messages2.push({
602234
602286
  role: "system",
@@ -641565,17 +641617,28 @@ function stageForAgentEvent(event) {
641565
641617
  return { stage: "compacting" };
641566
641618
  case "debug_adversary":
641567
641619
  return { stage: "adversary_audit" };
641568
- case "trajectory_checkpoint":
641569
- if (/verification_due/i.test(event.content ?? "")) {
641620
+ case "trajectory_checkpoint": {
641621
+ const assessment = event.trajectory?.assessment;
641622
+ if (assessment === "verification_due") {
641570
641623
  return { stage: "verifying", detail: "trajectory" };
641571
641624
  }
641572
- if (/\bblocked\b/i.test(event.content ?? "")) {
641625
+ if (assessment === "blocked") {
641573
641626
  return { stage: "failed", detail: "trajectory" };
641574
641627
  }
641628
+ if (assessment === "recovery_required") {
641629
+ return { stage: "blocked", detail: "trajectory" };
641630
+ }
641631
+ if (/verification_due/i.test(event.content ?? "")) {
641632
+ return { stage: "verifying", detail: "trajectory" };
641633
+ }
641575
641634
  if (/recovery_required/i.test(event.content ?? "")) {
641576
641635
  return { stage: "blocked", detail: "trajectory" };
641577
641636
  }
641637
+ if (/\bblocked\b/i.test(event.content ?? "")) {
641638
+ return { stage: "failed", detail: "trajectory" };
641639
+ }
641578
641640
  return { stage: "planning", detail: "trajectory" };
641641
+ }
641579
641642
  case "complete":
641580
641643
  return { stage: "completed", detail: "done" };
641581
641644
  case "error":
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.538",
3
+ "version": "1.0.540",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.538",
9
+ "version": "1.0.540",
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.538",
3
+ "version": "1.0.540",
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",