omnius 1.0.388 → 1.0.389

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
@@ -572459,11 +572459,86 @@ function computeEffectiveThink(params) {
572459
572459
  return params.defaultThink;
572460
572460
  }
572461
572461
  function sanitizeHistoryThink(messages2) {
572462
- return messages2.map((m2) => {
572462
+ const referencedToolCallIds = /* @__PURE__ */ new Set();
572463
+ for (const message2 of messages2) {
572464
+ if (message2.role === "tool" && message2.tool_call_id) {
572465
+ referencedToolCallIds.add(message2.tool_call_id);
572466
+ }
572467
+ }
572468
+ const stripped = messages2.map((m2) => {
572463
572469
  if (m2.role !== "assistant" || typeof m2.content !== "string")
572464
572470
  return m2;
572465
572471
  return { ...m2, content: stripThinkBlocks(m2.content) };
572466
572472
  });
572473
+ const sanitized = [];
572474
+ for (let i2 = 0; i2 < stripped.length; i2++) {
572475
+ const current = stripped[i2];
572476
+ const next = stripped[i2 + 1];
572477
+ if (isOrphanDuplicateAssistantToolAnchor(current, next, referencedToolCallIds)) {
572478
+ continue;
572479
+ }
572480
+ sanitized.push(current);
572481
+ }
572482
+ return sanitized;
572483
+ }
572484
+ function isOrphanDuplicateAssistantToolAnchor(current, next, referencedToolCallIds) {
572485
+ if (!next)
572486
+ return false;
572487
+ if (current.role !== "assistant" || next.role !== "assistant")
572488
+ return false;
572489
+ if (!Array.isArray(current.tool_calls) || !Array.isArray(next.tool_calls)) {
572490
+ return false;
572491
+ }
572492
+ if (current.tool_calls.length === 0 || next.tool_calls.length === 0) {
572493
+ return false;
572494
+ }
572495
+ if (assistantVisibleText(current).length > 0)
572496
+ return false;
572497
+ if (toolCallsFingerprint(current.tool_calls) !== toolCallsFingerprint(next.tool_calls)) {
572498
+ return false;
572499
+ }
572500
+ const currentIds = current.tool_calls.map((call) => call.id).filter(Boolean);
572501
+ const nextIds = next.tool_calls.map((call) => call.id).filter(Boolean);
572502
+ const currentReferenced = currentIds.some((id) => referencedToolCallIds.has(id));
572503
+ const nextReferenced = nextIds.some((id) => referencedToolCallIds.has(id));
572504
+ return !currentReferenced && (nextReferenced || currentIds.length > 0);
572505
+ }
572506
+ function assistantVisibleText(message2) {
572507
+ if (typeof message2.content === "string")
572508
+ return message2.content.trim();
572509
+ if (!Array.isArray(message2.content))
572510
+ return "";
572511
+ return message2.content.map((part) => part.type === "text" ? part.text ?? "" : "").join("").trim();
572512
+ }
572513
+ function toolCallsFingerprint(calls) {
572514
+ return calls.map((call) => {
572515
+ const args = normalizeToolCallArgumentString(call.function.arguments);
572516
+ return `${call.function.name}:${args}`;
572517
+ }).join("|");
572518
+ }
572519
+ function normalizeToolCallArgumentString(args) {
572520
+ try {
572521
+ return JSON.stringify(JSON.parse(args));
572522
+ } catch {
572523
+ return args.replace(/\s+/g, " ").trim();
572524
+ }
572525
+ }
572526
+ function normalizeEditComparable(text2) {
572527
+ return text2.replace(/\r\n/g, "\n").trim();
572528
+ }
572529
+ function previewInline(text2, max = 140) {
572530
+ const normalized = text2.replace(/\s+/g, " ").trim();
572531
+ if (normalized.length <= max)
572532
+ return JSON.stringify(normalized);
572533
+ return JSON.stringify(`${normalized.slice(0, max - 18)}...#${quickTextHash(normalized)}`);
572534
+ }
572535
+ function quickTextHash(input) {
572536
+ let hash = 2166136261;
572537
+ for (let index = 0; index < input.length; index++) {
572538
+ hash ^= input.charCodeAt(index);
572539
+ hash = Math.imul(hash, 16777619) >>> 0;
572540
+ }
572541
+ return hash.toString(16).padStart(8, "0");
572467
572542
  }
572468
572543
  function applyMemoryPrefixToMessages(messages2, memoryPrefix) {
572469
572544
  const prefix = memoryPrefix?.trim();
@@ -572938,6 +573013,8 @@ var init_agenticRunner = __esm({
572938
573013
  _completionCaveat = null;
572939
573014
  _completionLedger = null;
572940
573015
  _staleEditFamilies = /* @__PURE__ */ new Map();
573016
+ _lastReadTurnByPathKey = /* @__PURE__ */ new Map();
573017
+ _recentSuccessfulReplacements = [];
572941
573018
  // ── WO-AM-01/04/10: Associative memory stores ──
572942
573019
  // Episode store: every tool call → persistent episode with importance + decay
572943
573020
  // Temporal KG: entities + relations with temporal validity (valid_from/valid_until)
@@ -578793,6 +578870,8 @@ Respond with your assessment, then take action.`;
578793
578870
  this._completionLedger = null;
578794
578871
  this._focusTerminalLedgerRecorded = false;
578795
578872
  this._staleEditFamilies.clear();
578873
+ this._lastReadTurnByPathKey.clear();
578874
+ this._recentSuccessfulReplacements = [];
578796
578875
  this._lastWorldStateTurn = -1;
578797
578876
  this._fileWritesSinceLastWorldState = 0;
578798
578877
  this._resetVisualEvidenceState();
@@ -581183,7 +581262,7 @@ ${memoryLines.join("\n")}`
581183
581262
  this.proactivePrune(compacted, turn);
581184
581263
  this.microcompact(compacted, recentToolResults);
581185
581264
  this._insertContextFrame(compacted, await this._buildTurnContextFrame(turn, compacted, recentToolResults, environmentBlock));
581186
- let requestMessages = compacted;
581265
+ let requestMessages = sanitizeHistoryThink(compacted);
581187
581266
  {
581188
581267
  const _limits = this.contextLimits();
581189
581268
  const ceInput = {
@@ -581219,6 +581298,7 @@ ${memoryLines.join("\n")}`
581219
581298
  }
581220
581299
  }
581221
581300
  const { maxOutputTokens: effectiveMaxTokens } = this.contextLimits();
581301
+ requestMessages = sanitizeHistoryThink(requestMessages);
581222
581302
  const chatRequest = {
581223
581303
  messages: requestMessages,
581224
581304
  tools: toolDefs,
@@ -582178,6 +582258,69 @@ Use the saved fact to continue the promised synthesis or next concrete step, or
582178
582258
  systemGuidance: staleRewriteOutput
582179
582259
  };
582180
582260
  }
582261
+ const editReversalBlock = this.editReversalPreflightBlock(tc.name, tc.arguments ?? {}, turn);
582262
+ if (editReversalBlock) {
582263
+ const focusDecision2 = this._focusSupervisor?.evaluateProposedCall({
582264
+ turn,
582265
+ toolName: tc.name,
582266
+ args: tc.arguments ?? {},
582267
+ fingerprint: toolFingerprint,
582268
+ isReadLike: false,
582269
+ stalePreflightMessage: editReversalBlock,
582270
+ context: this._buildFocusContextSnapshot()
582271
+ });
582272
+ const reversalOutput = focusDecision2?.kind === "block_tool_call" ? focusDecision2.message : editReversalBlock;
582273
+ if (focusDecision2 && focusDecision2.kind !== "pass") {
582274
+ this._emitFocusSupervisorEvent({
582275
+ decision: focusDecision2.kind,
582276
+ state: focusDecision2.state,
582277
+ directiveId: focusDecision2.directive.id,
582278
+ reason: focusDecision2.directive.reason,
582279
+ requiredNextAction: focusDecision2.directive.requiredNextAction,
582280
+ blockedTool: tc.name,
582281
+ turn
582282
+ });
582283
+ this._maybeMarkFocusTerminalIncomplete({
582284
+ decision: focusDecision2,
582285
+ blockedTool: tc.name,
582286
+ turn
582287
+ });
582288
+ }
582289
+ this.emit({
582290
+ type: "tool_call",
582291
+ toolName: tc.name,
582292
+ toolArgs: tc.arguments,
582293
+ turn,
582294
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
582295
+ });
582296
+ this.emit({
582297
+ type: "tool_result",
582298
+ toolName: tc.name,
582299
+ success: false,
582300
+ content: reversalOutput.slice(0, 120),
582301
+ turn,
582302
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
582303
+ });
582304
+ this._tagSyntheticFailure({
582305
+ mode: "step_repetition",
582306
+ rationale: "edit attempted to reverse a recent successful replacement without fresh evidence"
582307
+ });
582308
+ if (this._completionLedger) {
582309
+ this._completionLedger = recordToolEvidence(this._completionLedger, {
582310
+ name: tc.name,
582311
+ success: false,
582312
+ outputPreview: reversalOutput.slice(0, 500),
582313
+ argsKey: tc.arguments ? JSON.stringify(tc.arguments).slice(0, 300) : ""
582314
+ });
582315
+ this._saveCompletionLedgerSafe();
582316
+ }
582317
+ return {
582318
+ tc,
582319
+ output: reversalOutput,
582320
+ success: false,
582321
+ systemGuidance: reversalOutput
582322
+ };
582323
+ }
582181
582324
  const baseIsReadLike = ![
582182
582325
  "file_write",
582183
582326
  "file_edit",
@@ -583812,6 +583955,7 @@ Evidence: ${evidencePreview}`.slice(0, 500);
583812
583955
  const filePath = typeof tc.arguments?.path === "string" ? tc.arguments.path : "";
583813
583956
  recordToolExecution(this._appState, tc.name, performance.now() - toolStart, result.success, filePath || void 0);
583814
583957
  this.noteStaleEditGuardOutcome(tc.name, tc.arguments ?? {}, result, turn);
583958
+ this.noteEditReversalOutcome(tc.name, tc.arguments ?? {}, result, turn);
583815
583959
  {
583816
583960
  const beforeDirective = this._focusSupervisor?.snapshot().directive?.id ?? null;
583817
583961
  this._focusSupervisor?.observeToolResult({
@@ -584876,8 +585020,9 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
584876
585020
  }
584877
585021
  }
584878
585022
  this._insertContextFrame(compactedMsgs, await this._buildTurnContextFrame(turn, compactedMsgs, void 0, bfEnvironmentBlock));
585023
+ const modelFacingMessages = sanitizeHistoryThink(compactedMsgs);
584879
585024
  const chatRequest = {
584880
- messages: compactedMsgs,
585025
+ messages: modelFacingMessages,
584881
585026
  tools: toolDefs,
584882
585027
  temperature: this.options.temperature,
584883
585028
  maxTokens: this.options.maxTokens,
@@ -586461,6 +586606,94 @@ ${marker}` : marker);
586461
586606
  `Stale target preview: ${active.preview}`
586462
586607
  ].join("\n");
586463
586608
  }
586609
+ editReversalPreflightBlock(toolName, args, turn) {
586610
+ if (process.env["OMNIUS_ALLOW_BLIND_EDIT_REVERSAL"] === "1")
586611
+ return null;
586612
+ const replacements = this.extractReplacementEdits(toolName, args);
586613
+ if (replacements.length === 0)
586614
+ return null;
586615
+ for (const replacement of replacements) {
586616
+ const prior = [...this._recentSuccessfulReplacements].reverse().find((entry) => entry.pathKey === replacement.pathKey && entry.oldHash === replacement.newHash && entry.newHash === replacement.oldHash && turn - entry.turn <= 8);
586617
+ if (!prior)
586618
+ continue;
586619
+ const lastReadTurn = this._lastReadTurnByPathKey.get(replacement.pathKey) ?? -1;
586620
+ if (lastReadTurn > prior.turn)
586621
+ continue;
586622
+ return [
586623
+ `[EDIT REVERSAL BLOCKED] ${toolName} would exactly reverse a recent successful edit on ${replacement.path}.`,
586624
+ `Prior edit at turn ${prior.turn}: ${previewInline(prior.oldText)} -> ${previewInline(prior.newText)}.`,
586625
+ `Proposed edit: ${previewInline(replacement.oldText)} -> ${previewInline(replacement.newText)}.`,
586626
+ ``,
586627
+ `Do not toggle a target back and forth after verification fails. First file_read the authoritative current file once, then choose one:`,
586628
+ `1. make a different edit based on the fresh file and the latest failure output,`,
586629
+ `2. run a verification command if the current file is already correct, or`,
586630
+ `3. report incomplete/blocked with the concrete failing evidence.`
586631
+ ].join("\n");
586632
+ }
586633
+ return null;
586634
+ }
586635
+ noteEditReversalOutcome(toolName, args, result, turn) {
586636
+ const path12 = this.extractPrimaryToolPath(args);
586637
+ if (toolName === "file_read" && path12 && result.success) {
586638
+ this._lastReadTurnByPathKey.set(this.staleEditPathKey(path12), turn);
586639
+ return;
586640
+ }
586641
+ if (!result.success || result.mutated === false)
586642
+ return;
586643
+ const replacements = this.extractReplacementEdits(toolName, args);
586644
+ if (replacements.length === 0)
586645
+ return;
586646
+ for (const replacement of replacements) {
586647
+ this._recentSuccessfulReplacements.push({
586648
+ ...replacement,
586649
+ tool: toolName,
586650
+ turn
586651
+ });
586652
+ }
586653
+ if (this._recentSuccessfulReplacements.length > 40) {
586654
+ this._recentSuccessfulReplacements = this._recentSuccessfulReplacements.slice(-40);
586655
+ }
586656
+ }
586657
+ extractReplacementEdits(toolName, args) {
586658
+ if (!args)
586659
+ return [];
586660
+ const out = [];
586661
+ const add3 = (path12, oldText, newText) => {
586662
+ if (typeof path12 !== "string" || !path12.trim())
586663
+ return;
586664
+ if (typeof oldText !== "string" || typeof newText !== "string")
586665
+ return;
586666
+ const normalizedOld = normalizeEditComparable(oldText);
586667
+ const normalizedNew = normalizeEditComparable(newText);
586668
+ if (!normalizedOld || !normalizedNew || normalizedOld === normalizedNew)
586669
+ return;
586670
+ out.push({
586671
+ path: path12.trim(),
586672
+ pathKey: this.staleEditPathKey(path12),
586673
+ oldText: normalizedOld,
586674
+ newText: normalizedNew,
586675
+ oldHash: this.quickHash(normalizedOld),
586676
+ newHash: this.quickHash(normalizedNew)
586677
+ });
586678
+ };
586679
+ if (toolName === "file_edit") {
586680
+ add3(this.extractPrimaryToolPath(args), args["old_string"] ?? args["oldString"] ?? args["oldText"], args["new_string"] ?? args["newString"] ?? args["newText"]);
586681
+ return out;
586682
+ }
586683
+ if (toolName === "batch_edit") {
586684
+ const fallbackPath = this.extractPrimaryToolPath(args);
586685
+ const edits = args["edits"];
586686
+ if (!Array.isArray(edits))
586687
+ return out;
586688
+ for (const edit of edits) {
586689
+ if (!edit || typeof edit !== "object")
586690
+ continue;
586691
+ const rec = edit;
586692
+ add3(rec["path"] ?? rec["file"] ?? rec["filePath"] ?? rec["file_path"] ?? fallbackPath, rec["old_string"] ?? rec["oldString"] ?? rec["oldText"], rec["new_string"] ?? rec["newString"] ?? rec["newText"]);
586693
+ }
586694
+ }
586695
+ return out;
586696
+ }
586464
586697
  noteStaleEditGuardOutcome(toolName, args, result, turn) {
586465
586698
  const path12 = this.extractPrimaryToolPath(args);
586466
586699
  const pathKey = path12 ? this.staleEditPathKey(path12) : "";
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.388",
3
+ "version": "1.0.389",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.388",
9
+ "version": "1.0.389",
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.388",
3
+ "version": "1.0.389",
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",