omnius 1.0.210 → 1.0.212

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
@@ -559029,6 +559029,7 @@ var init_agenticRunner = __esm({
559029
559029
  bruteForce: options2?.bruteForce ?? true,
559030
559030
  bruteForceMaxCycles: options2?.bruteForceMaxCycles ?? 100,
559031
559031
  allowTurnExtension: options2?.allowTurnExtension ?? true,
559032
+ completionProvenanceGuard: options2?.completionProvenanceGuard ?? true,
559032
559033
  modelTier: options2?.modelTier ?? "large",
559033
559034
  contextWindowSize: options2?.contextWindowSize ?? 0,
559034
559035
  personality: options2?.personality ?? PERSONALITY_PRESETS.balanced,
@@ -559898,6 +559899,198 @@ Do NOT call task_complete until all items are marked completed via todo_write.`;
559898
559899
  `Continue the work loop: inspect the failed evidence, make the smallest targeted fix, then rerun the relevant verification. Use the full available verification spectrum for the artifact you changed: static syntax, build/typecheck, tests, service startup, runtime logs, browser/page errors, console output, network failures, screenshots, accessibility/DOM state, and end-to-end user flow checks where applicable. The exact tools are stack-dependent; the standard is objective runtime evidence, not self-report.`
559899
559900
  ].join("\n");
559900
559901
  }
559902
+ buildMissionCompletionContract(task, context2) {
559903
+ if (process.env["OMNIUS_DISABLE_MISSION_COMPLETION_CONTRACT"] === "1")
559904
+ return "";
559905
+ const profile = this._inferCompletionProfile(`${task}
559906
+ ${context2 ?? ""}`);
559907
+ const requirements = [];
559908
+ if (profile.browser)
559909
+ requirements.push("browser/UI state must be proven by a post-action screenshot/DOM/observe_bundle pass");
559910
+ if (profile.desktop)
559911
+ requirements.push("desktop state must be proven by vision_action_loop observe or desktop_describe after the final action");
559912
+ if (profile.code)
559913
+ requirements.push("code/file changes must be proven by a relevant build/test/typecheck/runtime command after the last edit");
559914
+ if (profile.research)
559915
+ requirements.push("research/root-cause claims must cite concrete inspected files, commands, logs, or source artifacts");
559916
+ if (requirements.length === 0)
559917
+ requirements.push("final claims must name the concrete evidence used or state that the task required no external action");
559918
+ return [
559919
+ `[MISSION COMPLETION CONTRACT]`,
559920
+ `Current ask: ${task.slice(0, 500)}`,
559921
+ ``,
559922
+ `Before claiming success or calling task_complete, satisfy the mission-specific evidence requirements:`,
559923
+ ...requirements.map((line) => `- ${line}.`),
559924
+ ``,
559925
+ `The final task_complete summary for any action-heavy task must include a compact Provenance/Evidence note naming the validating tool output, command, screenshot, DOM state, file path, or blocker. Self-confidence is not evidence.`,
559926
+ `For browser/form/account/send flows: after the last click/type/navigate/submit action, capture a fresh browser observation and verify the visible final state before completion.`,
559927
+ `If completion is impossible, use a summary beginning BLOCKED: and name the exact blocker plus the evidence already collected.`
559928
+ ].join("\n");
559929
+ }
559930
+ _inferCompletionProfile(text) {
559931
+ const t2 = text.toLowerCase();
559932
+ const browser3 = /\b(browser|web\s*page|website|page|playwright|selenium|chromedriver|chrome|headless|gui|proton|login|captcha|form|account|compose|mail|submit|click|type|fill)\b/.test(t2);
559933
+ const desktop = /\b(desktop|screen|application|app\b|window|file manager|open a file|laptop|screenshot|vision_action_loop|desktop_describe|desktop_click)\b/.test(t2);
559934
+ const code8 = /\b(implement|fix|patch|refactor|rewrite|build|compile|typecheck|test suite|unit test|integration test|source file|codebase|package|typescript|javascript|python|rust|golang)\b/.test(t2);
559935
+ const research = /\b(discover|root cause|triage|deep dive|review|audit|investigate|prove|validate|forensics|diagnostic|failure mode)\b/.test(t2);
559936
+ const formLike = /\b(form|fill|submit|signup|sign up|login|log in|account|compose|send|sent|mail|captcha|checkout|payment|upload)\b/.test(t2);
559937
+ return { browser: browser3, desktop, code: code8, research, formLike };
559938
+ }
559939
+ _completionSummaryHasProvenance(summary) {
559940
+ return /\b(provenance|evidence|verified|validated|confirmed|observed|screenshot|dom|console|network|log|test|typecheck|build|passed|opened|sent|created|submitted|blocked)\b/i.test(summary);
559941
+ }
559942
+ _isBlockedCompletionSummary(summary) {
559943
+ return /^\s*(?:BLOCKED|PARTIAL|NO FILE CHANGES REQUIRED)\b/i.test(summary);
559944
+ }
559945
+ _browserActionKind(entry) {
559946
+ if (!/^(browser_action|playwright_browser|carbonyl_browser)$/.test(entry.name))
559947
+ return "other";
559948
+ const args = this._parseExactArgsKey(entry.argsKey);
559949
+ const action = String(args.get("action") ?? args.get("tool") ?? args.get("command") ?? "").toLowerCase();
559950
+ if (/^(screenshot|dom|dom_summary|observe|observe_bundle|page_errors|console_logs|network_log|accessibility|snapshot|state|url|title)$/.test(action)) {
559951
+ return "observe";
559952
+ }
559953
+ if (/^(navigate|click|click_xy|vision_click|visual_click|type|fill|press|select|submit|evaluate|scroll|scroll_up|scroll_down|back|forward)$/.test(action)) {
559954
+ return "state";
559955
+ }
559956
+ return entry.name === "carbonyl_browser" ? "state" : "other";
559957
+ }
559958
+ _desktopActionKind(entry) {
559959
+ if (/^(desktop_describe|screenshot)$/.test(entry.name))
559960
+ return "observe";
559961
+ if (entry.name === "desktop_click")
559962
+ return "state";
559963
+ if (entry.name !== "vision_action_loop")
559964
+ return "other";
559965
+ const args = this._parseExactArgsKey(entry.argsKey);
559966
+ const action = String(args.get("action") ?? "").toLowerCase();
559967
+ if (/^(observe|screenshot|describe|ocr|state)$/.test(action))
559968
+ return "observe";
559969
+ if (/^(click|type|key|press|open|focus|drag|scroll)$/.test(action))
559970
+ return "state";
559971
+ return "other";
559972
+ }
559973
+ _isVerificationShell(entry) {
559974
+ if (entry.name !== "shell" && entry.name !== "background_run")
559975
+ return false;
559976
+ if (entry.success !== true)
559977
+ return false;
559978
+ const args = this._parseExactArgsKey(entry.argsKey);
559979
+ const command = String(args.get("command") ?? args.get("cmd") ?? "").toLowerCase();
559980
+ return /\b(test|typecheck|check|build|compile|verify|lint|pytest|vitest|jest|playwright|cypress|tsc|cargo\s+test|go\s+test|npm\s+run|pnpm\s+run|yarn\s+run)\b/.test(command);
559981
+ }
559982
+ _evaluateCompletionProvenanceGate(input) {
559983
+ if (this.options.completionProvenanceGuard === false)
559984
+ return { proceed: true };
559985
+ if (process.env["OMNIUS_DISABLE_COMPLETION_PROVENANCE_GUARD"] === "1")
559986
+ return { proceed: true };
559987
+ const summary = input.summary || "";
559988
+ const blockedSummary = this._isBlockedCompletionSummary(summary);
559989
+ const profile = this._inferCompletionProfile(input.taskGoal);
559990
+ const log22 = input.toolCallLog.filter((entry) => entry.name !== "task_complete");
559991
+ const browserUsed = log22.some((entry) => /^(browser_action|playwright_browser|carbonyl_browser)$/.test(entry.name));
559992
+ const desktopUsed = log22.some((entry) => /^(desktop_describe|desktop_click|vision_action_loop|screenshot)$/.test(entry.name));
559993
+ const mutated = log22.some((entry) => entry.mutated === true);
559994
+ const issues = [];
559995
+ const actionHeavy = profile.browser || profile.desktop || profile.code || profile.research || browserUsed || desktopUsed || mutated || this._fileWritesThisRun > 0;
559996
+ if (!actionHeavy)
559997
+ return { proceed: true };
559998
+ if (blockedSummary)
559999
+ return { proceed: true };
560000
+ const successfulNonCompletion = log22.filter((entry) => entry.success === true);
560001
+ if (successfulNonCompletion.length === 0) {
560002
+ issues.push("No successful objective tool result is recorded for this action-oriented task.");
560003
+ }
560004
+ const requiresBrowser = profile.browser || browserUsed;
560005
+ const requiresDesktop = profile.desktop || desktopUsed;
560006
+ if (requiresBrowser) {
560007
+ let lastStateIdx = -1;
560008
+ let lastObserveIdx = -1;
560009
+ log22.forEach((entry, idx) => {
560010
+ if (entry.success !== true)
560011
+ return;
560012
+ const kind = this._browserActionKind(entry);
560013
+ if (kind === "state")
560014
+ lastStateIdx = idx;
560015
+ if (kind === "observe")
560016
+ lastObserveIdx = idx;
560017
+ });
560018
+ if (lastStateIdx >= 0 && lastObserveIdx <= lastStateIdx) {
560019
+ issues.push("Browser state changed after the last browser observation. Capture a fresh screenshot/DOM/observe_bundle after the final click/type/navigate/submit before completion.");
560020
+ } else if (profile.formLike && lastObserveIdx < 0) {
560021
+ issues.push("This looks like a form/account/send flow, but no successful post-action browser observation is recorded.");
560022
+ }
560023
+ }
560024
+ if (requiresDesktop) {
560025
+ let lastStateIdx = -1;
560026
+ let lastObserveIdx = -1;
560027
+ log22.forEach((entry, idx) => {
560028
+ if (entry.success !== true)
560029
+ return;
560030
+ const kind = this._desktopActionKind(entry);
560031
+ if (kind === "state")
560032
+ lastStateIdx = idx;
560033
+ if (kind === "observe")
560034
+ lastObserveIdx = idx;
560035
+ });
560036
+ if (lastStateIdx >= 0 && lastObserveIdx <= lastStateIdx) {
560037
+ issues.push("Desktop state changed after the last visual observation. Run vision_action_loop observe or desktop_describe after the final desktop action before completion.");
560038
+ }
560039
+ }
560040
+ const mutatedEntries = log22.map((entry, idx) => ({ entry, idx })).filter(({ entry }) => entry.mutated === true);
560041
+ if (profile.code || mutatedEntries.length > 0 || this._fileWritesThisRun > 0) {
560042
+ const lastMutationIdx = mutatedEntries.length > 0 ? Math.max(...mutatedEntries.map(({ idx }) => idx)) : -1;
560043
+ const verifiedAfterMutation = log22.some((entry, idx) => {
560044
+ if (lastMutationIdx >= 0 && idx <= lastMutationIdx)
560045
+ return false;
560046
+ if (this._isVerificationShell(entry))
560047
+ return true;
560048
+ if (entry.success === true && this._browserActionKind(entry) === "observe")
560049
+ return true;
560050
+ if (entry.success === true && this._desktopActionKind(entry) === "observe")
560051
+ return true;
560052
+ return false;
560053
+ });
560054
+ if (lastMutationIdx >= 0 && !verifiedAfterMutation) {
560055
+ issues.push("Files were changed but no successful verification command or runtime observation appears after the last mutation.");
560056
+ }
560057
+ }
560058
+ const lastNonCompletion = [...log22].reverse().find(Boolean);
560059
+ if (lastNonCompletion?.success === false) {
560060
+ issues.push(`The most recent non-completion tool result failed (${lastNonCompletion.name}); resolve or explicitly report BLOCKED before completing.`);
560061
+ }
560062
+ if (!this._completionSummaryHasProvenance(summary)) {
560063
+ issues.push("The completion summary does not include an explicit Evidence/Provenance note.");
560064
+ }
560065
+ if (issues.length === 0)
560066
+ return { proceed: true };
560067
+ const recentEvidence = successfulNonCompletion.slice(-6).map((entry) => {
560068
+ const preview = (entry.outputPreview ?? "").replace(/\s+/g, " ").slice(0, 160);
560069
+ return `- ${entry.name}(${entry.argsKey.slice(0, 120)})${preview ? ` -> ${preview}` : ""}`;
560070
+ }).join("\n");
560071
+ return {
560072
+ proceed: false,
560073
+ reason: issues[0] ?? "missing provenance",
560074
+ feedback: [
560075
+ `[COMPLETION PROVENANCE REQUIRED]`,
560076
+ ``,
560077
+ `You attempted to finish, but the completion claim is not yet proven against the current mission.`,
560078
+ ``,
560079
+ `Blocking issues:`,
560080
+ ...issues.map((issue, index) => `${index + 1}. ${issue}`),
560081
+ ``,
560082
+ recentEvidence ? `Recent successful evidence already available:
560083
+ ${recentEvidence}` : `Recent successful evidence already available: none recorded.`,
560084
+ ``,
560085
+ `Do the smallest missing verification step now. For browser/UI work, take a fresh screenshot/DOM/observe_bundle after the final action. For desktop work, run vision_action_loop observe or desktop_describe after the final action. For code/file changes, run the relevant build/test/typecheck/runtime check after the last edit.`,
560086
+ ``,
560087
+ `Only then call task_complete with this shape:`,
560088
+ `Summary: <what changed or what final state was reached>`,
560089
+ `Provenance: <tool/command/screenshot/DOM/log/file evidence proving it>`,
560090
+ `If impossible, call task_complete with summary starting BLOCKED: and name the blocker plus evidence.`
560091
+ ].join("\n")
560092
+ };
560093
+ }
559901
560094
  /**
559902
560095
  * REG-47: post-implementation backward-pass review.
559903
560096
  *
@@ -561829,6 +562022,30 @@ ${blob}
561829
562022
  _buildToolFingerprint(name10, args) {
561830
562023
  return `${name10}:${this._buildExactArgsKey(args)}`;
561831
562024
  }
562025
+ _dedupeToolCallsForResponse(toolCalls, turn) {
562026
+ if (toolCalls.length <= 1)
562027
+ return toolCalls;
562028
+ const seen = /* @__PURE__ */ new Set();
562029
+ const deduped = [];
562030
+ let dropped = 0;
562031
+ for (const tc of toolCalls) {
562032
+ const fp = this._buildToolFingerprint(tc.name, tc.arguments ?? {});
562033
+ if (seen.has(fp)) {
562034
+ dropped++;
562035
+ continue;
562036
+ }
562037
+ seen.add(fp);
562038
+ deduped.push(tc);
562039
+ }
562040
+ if (dropped > 0) {
562041
+ this.emit({
562042
+ type: "status",
562043
+ content: `Response dedupe: dropped ${dropped} exact duplicate tool call(s) before execution (turn ${turn})`,
562044
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
562045
+ });
562046
+ }
562047
+ return deduped;
562048
+ }
561832
562049
  _decodeToolFingerprint(fingerprint) {
561833
562050
  const colonIdx = fingerprint.indexOf(":");
561834
562051
  const toolName = colonIdx > 0 ? fingerprint.slice(0, colonIdx) : fingerprint;
@@ -562704,7 +562921,6 @@ Respond with your assessment, then take action.`;
562704
562921
  const contextComposition = await this.assembleContext(task, context2);
562705
562922
  const systemPrompt = contextComposition.assembled;
562706
562923
  this._contextTree = new ContextTree(`sys-${systemPrompt.length}`, cleanedTask.slice(0, 200));
562707
- this._phaseMessageStartIdx = 2;
562708
562924
  this.emit({
562709
562925
  type: "status",
562710
562926
  content: `Context assembled: ${contextComposition.sections.map((s2) => `${s2.label}(${s2.tokenEstimate}t)`).join(" + ")} = ~${contextComposition.totalTokenEstimate}t`,
@@ -562748,10 +562964,13 @@ TASK: ${scrubbedTask}` : scrubbedTask;
562748
562964
  }
562749
562965
  });
562750
562966
  }
562967
+ const missionCompletionContract = this.buildMissionCompletionContract(cleanedTask, context2);
562751
562968
  const messages2 = [
562752
562969
  { role: "system", content: systemPrompt },
562970
+ ...missionCompletionContract ? [{ role: "system", content: missionCompletionContract }] : [],
562753
562971
  { role: "user", content: userContent }
562754
562972
  ];
562973
+ this._phaseMessageStartIdx = messages2.length;
562755
562974
  if (process.env["OMNIUS_DISABLE_DECOMP1"] !== "1") {
562756
562975
  try {
562757
562976
  const _taskBodyForDecomp = typeof userContent === "string" ? userContent : "";
@@ -563009,6 +563228,24 @@ TASK: ${scrubbedTask}` : scrubbedTask;
563009
563228
  });
563010
563229
  return true;
563011
563230
  };
563231
+ const holdProvenanceTaskComplete = (args, turn) => {
563232
+ const proposedSummary = extractTaskCompleteSummary(args);
563233
+ const gate = this._evaluateCompletionProvenanceGate({
563234
+ summary: proposedSummary,
563235
+ taskGoal: cleanedTask,
563236
+ toolCallLog
563237
+ });
563238
+ if (gate.proceed)
563239
+ return false;
563240
+ messages2.push({ role: "system", content: gate.feedback });
563241
+ this.emit({
563242
+ type: "status",
563243
+ content: `task_complete held by completion provenance guard: ${gate.reason}`,
563244
+ turn,
563245
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
563246
+ });
563247
+ return true;
563248
+ };
563012
563249
  const turnCap = this.options.maxTurns && this.options.maxTurns > 0 ? this.options.maxTurns : Number.MAX_SAFE_INTEGER;
563013
563250
  for (let turn = 0; turn < turnCap; turn++) {
563014
563251
  clearTurnState(this._appState);
@@ -564689,6 +564926,14 @@ ${memoryLines.join("\n")}`
564689
564926
  if (msg.toolCalls && msg.toolCalls.length > 0) {
564690
564927
  consecutiveTextOnly = 0;
564691
564928
  consecutiveThinkOnly = 0;
564929
+ msg.toolCalls = this._dedupeToolCallsForResponse(msg.toolCalls, turn);
564930
+ if (msg.toolCalls.length === 0) {
564931
+ messages2.push({
564932
+ role: "system",
564933
+ content: "[RESPONSE DEDUPE] All tool calls in the last response were exact duplicates and were dropped. Use the prior results already in context/cache to continue."
564934
+ });
564935
+ continue;
564936
+ }
564692
564937
  const _RESPONSE_CALL_CAPS = {
564693
564938
  small: 2,
564694
564939
  medium: 4,
@@ -566219,6 +566464,13 @@ Respond with EXACTLY this structure before your next tool call:
566219
566464
  editFeedbackRequiredBeforeMoreEdits = this._buildBatchEditAtomicAbortGuidance(tc.arguments);
566220
566465
  this.pendingUserMessages.push(editFeedbackRequiredBeforeMoreEdits);
566221
566466
  }
566467
+ const currentLogEntry = toolCallLog[_toolLogTailIdx];
566468
+ if (currentLogEntry) {
566469
+ currentLogEntry.success = result.success;
566470
+ currentLogEntry.mutated = realFileMutation;
566471
+ currentLogEntry.mutatedFiles = realMutationPaths;
566472
+ currentLogEntry.outputPreview = (result.success ? result.llmContent ?? result.output ?? output : result.error ?? result.output ?? output).toString().slice(0, 500);
566473
+ }
566222
566474
  this.emit({
566223
566475
  type: "tool_result",
566224
566476
  toolName: tc.name,
@@ -566608,7 +566860,7 @@ ${sr.result.output}`;
566608
566860
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
566609
566861
  });
566610
566862
  } else {
566611
- if (holdNoProgressTaskComplete(matchTc.arguments, turn)) {
566863
+ if (holdNoProgressTaskComplete(matchTc.arguments, turn) || holdProvenanceTaskComplete(matchTc.arguments, turn)) {
566612
566864
  continue;
566613
566865
  }
566614
566866
  const _bp1 = await this._runBackwardPassReview(turn);
@@ -566664,7 +566916,7 @@ ${sr.result.output}`;
566664
566916
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
566665
566917
  });
566666
566918
  } else {
566667
- if (holdNoProgressTaskComplete(r2.tc.arguments, turn)) {
566919
+ if (holdNoProgressTaskComplete(r2.tc.arguments, turn) || holdProvenanceTaskComplete(r2.tc.arguments, turn)) {
566668
566920
  continue;
566669
566921
  }
566670
566922
  const _bp2 = await this._runBackwardPassReview(turn);
@@ -566756,7 +567008,7 @@ ${sr.result.output}`;
566756
567008
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
566757
567009
  });
566758
567010
  } else {
566759
- if (holdNoProgressTaskComplete(r2.tc.arguments, turn)) {
567011
+ if (holdNoProgressTaskComplete(r2.tc.arguments, turn) || holdProvenanceTaskComplete(r2.tc.arguments, turn)) {
566760
567012
  continue;
566761
567013
  }
566762
567014
  const _bp3 = await this._runBackwardPassReview(turn);
@@ -566974,6 +567226,10 @@ Call task_complete(summary="...") NOW with whatever you have.`
566974
567226
  });
566975
567227
  }
566976
567228
  if (/task.?complete|all tests pass/i.test(content)) {
567229
+ const completionArgs = { summary: content };
567230
+ if (holdNoProgressTaskComplete(completionArgs, turn) || holdProvenanceTaskComplete(completionArgs, turn)) {
567231
+ continue;
567232
+ }
566977
567233
  completed = true;
566978
567234
  summary = content;
566979
567235
  break;
@@ -567332,6 +567588,14 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
567332
567588
  if (msg.toolCalls && msg.toolCalls.length > 0) {
567333
567589
  consecutiveTextOnly = 0;
567334
567590
  consecutiveThinkOnly = 0;
567591
+ msg.toolCalls = this._dedupeToolCallsForResponse(msg.toolCalls, turn);
567592
+ if (msg.toolCalls.length === 0) {
567593
+ messages2.push({
567594
+ role: "system",
567595
+ content: "[RESPONSE DEDUPE] All tool calls in the last response were exact duplicates and were dropped. Use the prior results already in context/cache to continue."
567596
+ });
567597
+ continue;
567598
+ }
567335
567599
  messages2.push({
567336
567600
  role: "assistant",
567337
567601
  content: msg.content || null,
@@ -567528,7 +567792,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
567528
567792
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
567529
567793
  });
567530
567794
  } else {
567531
- if (holdNoProgressTaskComplete(tc.arguments, turn)) {
567795
+ if (holdNoProgressTaskComplete(tc.arguments, turn) || holdProvenanceTaskComplete(tc.arguments, turn)) {
567532
567796
  continue;
567533
567797
  }
567534
567798
  const _bp4 = await this._runBackwardPassReview(turn);
@@ -567581,22 +567845,9 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
567581
567845
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
567582
567846
  });
567583
567847
  } else {
567584
- if (process.env["OMNIUS_DISABLE_PROGRESS_GATES"] !== "1") {
567585
- const gate = computeNoProgressCompletionGate({
567586
- summary: content,
567587
- toolCallLog,
567588
- taskState: this._taskState
567589
- });
567590
- if (gate.shouldInject && gate.content) {
567591
- messages2.push({ role: "system", content: gate.content });
567592
- this.emit({
567593
- type: "status",
567594
- content: "text completion held: discovery happened but no deliverable or explicit blocker is recorded",
567595
- turn,
567596
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
567597
- });
567598
- continue;
567599
- }
567848
+ const completionArgs = { summary: content };
567849
+ if (holdNoProgressTaskComplete(completionArgs, turn) || holdProvenanceTaskComplete(completionArgs, turn)) {
567850
+ continue;
567600
567851
  }
567601
567852
  completed = true;
567602
567853
  summary = content;
@@ -572272,6 +572523,54 @@ ${description}`
572272
572523
  releasePoolSlot(poolSuccess);
572273
572524
  }
572274
572525
  }
572526
+ async nativeOllamaChatCompletion(request) {
572527
+ const cleanedMessages = applyMemoryPrefixToMessages(normalizeMessagesForStrictOpenAI(sanitizeHistoryThink(request.messages)), request.memoryPrefix);
572528
+ const requestMessages = injectNoThinkDirective(cleanedMessages);
572529
+ const responseFormat = request.responseFormat ?? request.response_format;
572530
+ const options2 = {
572531
+ temperature: request.temperature,
572532
+ num_predict: request.maxTokens
572533
+ };
572534
+ const reqNumCtx = request.numCtx ?? request.num_ctx;
572535
+ if (Number.isFinite(reqNumCtx) && (reqNumCtx ?? 0) > 0) {
572536
+ options2["num_ctx"] = reqNumCtx;
572537
+ }
572538
+ const body = {
572539
+ model: this.model,
572540
+ messages: requestMessages,
572541
+ stream: false,
572542
+ think: false,
572543
+ options: options2
572544
+ };
572545
+ if (responseFormat !== void 0) {
572546
+ body["format"] = "json";
572547
+ }
572548
+ const effectiveTimeoutMs = Number.isFinite(request.timeoutMs) && request.timeoutMs > 0 ? request.timeoutMs : 0;
572549
+ const timeoutSignal = effectiveTimeoutMs > 0 && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(effectiveTimeoutMs) : void 0;
572550
+ const fetchOpts = {
572551
+ method: "POST",
572552
+ headers: this.authHeaders(),
572553
+ body: JSON.stringify(body)
572554
+ };
572555
+ if (timeoutSignal)
572556
+ fetchOpts.signal = timeoutSignal;
572557
+ const resp = await fetch(`${this.baseUrl}/api/chat`, fetchOpts);
572558
+ if (!resp.ok) {
572559
+ const text = await resp.text().catch(() => "");
572560
+ throw new Error(`Ollama native HTTP ${resp.status}: ${backendHttpErrorDetail(text)}`);
572561
+ }
572562
+ const data = await resp.json();
572563
+ const message2 = data["message"] ?? {};
572564
+ const content = typeof message2["content"] === "string" ? message2["content"] : "";
572565
+ return {
572566
+ choices: [{ message: { content: content || null } }],
572567
+ usage: buildAgenticUsage({
572568
+ totalTokens: numberFromUnknown2(data["prompt_eval_count"]) ?? 0,
572569
+ promptEvalCount: numberFromUnknown2(data["prompt_eval_count"]),
572570
+ completionTokens: numberFromUnknown2(data["eval_count"])
572571
+ })
572572
+ };
572573
+ }
572275
572574
  /** Anthropic Messages API translation — converts our standard format to/from Anthropic's. */
572276
572575
  async _anthropicChatCompletion(request) {
572277
572576
  const systemMsgs = request.messages.filter((m2) => m2.role === "system");
@@ -647266,8 +647565,13 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`,
647266
647565
  const suppressed = telegramThinkSuppressedRequest(request);
647267
647566
  const requestTimeoutMs = Number.isFinite(suppressed.timeoutMs) && (suppressed.timeoutMs ?? 0) > 0 ? suppressed.timeoutMs : void 0;
647268
647567
  const jsonStartMs = Date.now();
647568
+ const nativeOllamaRouter = diagnostics?.backendType === "ollama" && typeof backend.nativeOllamaChatCompletion === "function";
647269
647569
  try {
647270
- jsonModeResult = await this.telegramObservableInference(
647570
+ jsonModeResult = nativeOllamaRouter ? await backend.nativeOllamaChatCompletion({
647571
+ ...suppressed,
647572
+ responseFormat: TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT,
647573
+ disableEmptyContentRecovery: true
647574
+ }) : await this.telegramObservableInference(
647271
647575
  backend,
647272
647576
  {
647273
647577
  ...suppressed,
@@ -647327,7 +647631,7 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`,
647327
647631
  }
647328
647632
  const plainStartMs = Date.now();
647329
647633
  try {
647330
- const plainResult = await this.telegramObservableInference(
647634
+ const plainResult = nativeOllamaRouter ? await backend.nativeOllamaChatCompletion(suppressed) : await this.telegramObservableInference(
647331
647635
  backend,
647332
647636
  suppressed,
647333
647637
  inferenceKind,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.210",
3
+ "version": "1.0.212",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.210",
9
+ "version": "1.0.212",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
@@ -2310,9 +2310,9 @@
2310
2310
  }
2311
2311
  },
2312
2312
  "node_modules/bare-path": {
2313
- "version": "3.0.0",
2314
- "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
2315
- "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
2313
+ "version": "3.0.1",
2314
+ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.1.tgz",
2315
+ "integrity": "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ==",
2316
2316
  "license": "Apache-2.0",
2317
2317
  "optional": true,
2318
2318
  "dependencies": {
@@ -6886,9 +6886,9 @@
6886
6886
  }
6887
6887
  },
6888
6888
  "node_modules/undici": {
6889
- "version": "7.26.0",
6890
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.26.0.tgz",
6891
- "integrity": "sha512-3O9Tf67pGhgOv9jM35AbhkXAKi13f3oy3aE4CSgr+TckGeY+/iu97ZXN+J7DpHPzLbVApFd1IFhcnBjREYXYcg==",
6889
+ "version": "7.27.0",
6890
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.0.tgz",
6891
+ "integrity": "sha512-+t2Z/GwkZQDtu00813aP66ygViGtPHKhhoFZpQKpKrE+9jIgES+Zw+mFNaDWOVRKiuJjuqKHzD3B1sfGg8+ZOQ==",
6892
6892
  "license": "MIT",
6893
6893
  "engines": {
6894
6894
  "node": ">=20.18.1"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.210",
3
+ "version": "1.0.212",
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",