omnius 1.0.885 → 1.0.887

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
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/dist/index.js
3
- size: 38501421 bytes
4
- sha256: 93169deae92540705e32001d313d4ce473ab593892b4961028c6d743b672aa17
3
+ size: 38539614 bytes
4
+ sha256: 600a8c3a7f3dafeeb42f8fcba1c2da654064f82e535a29165a2ff2aeb5761e53
package/dist/library.js CHANGED
@@ -345015,7 +345015,7 @@ var StreamInterruptedError = class extends Error {
345015
345015
  fatal = true;
345016
345016
  retryable = false;
345017
345017
  constructor(failure) {
345018
- super("Inference ended after streaming output began. Automatic replay is disabled.");
345018
+ super("Inference ended after model progress began. Automatic replay is disabled.");
345019
345019
  this.failure = failure;
345020
345020
  this.name = "InferenceStreamInterruptedError";
345021
345021
  }
@@ -345464,7 +345464,10 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345464
345464
  }
345465
345465
  let localProgress = false;
345466
345466
  const localPacket = { ...this.localRequest(request), onLocalInferenceSemanticProgress: () => {
345467
- localProgress = true;
345467
+ if (!localProgress) {
345468
+ localProgress = true;
345469
+ this.lifecycle(request, "selected", void 0, void 0, void 0, void 0, void 0, true);
345470
+ }
345468
345471
  request.onLocalInferenceSemanticProgress?.();
345469
345472
  } };
345470
345473
  if (!this.eligible(request)) {
@@ -345472,9 +345475,13 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345472
345475
  return local(request);
345473
345476
  this.fence(request);
345474
345477
  try {
345475
- return await this.attempt(localPacket, this.localAttemptTimeoutMs(request), local);
345478
+ return await this.attempt(localPacket, this.localAttemptTimeoutMs(request), local, "local_first_frame", true);
345476
345479
  } catch (error) {
345477
345480
  this.fence(request);
345481
+ if (this.retainedLocalAdmission(error, request))
345482
+ throw error;
345483
+ if (localProgress && this.initialWaitTimeout(error))
345484
+ throw new StreamInterruptedError(safeFailure(error, request));
345478
345485
  throw this.localWaiting(error) ?? (!localProgress && this.initialWaitTimeout(error) ? new LocalInferenceNotReadyError("initial_response_timeout", error) : error);
345479
345486
  }
345480
345487
  }
@@ -345487,7 +345494,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345487
345494
  if (bounded3.localAdmissionFailure !== void 0)
345488
345495
  throw bounded3.localAdmissionFailure;
345489
345496
  return local(bounded3);
345490
- });
345497
+ }, "local_first_frame", true);
345491
345498
  if (!usableResult(result))
345492
345499
  throw new EmptyInferenceResponse();
345493
345500
  this.lifecycle(request, "succeeded");
@@ -345505,6 +345512,8 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345505
345512
  this.lifecycle(request, "failed", void 0, classified);
345506
345513
  if (classified instanceof LocalInferenceNotReadyError)
345507
345514
  throw classified;
345515
+ if (localProgress && this.initialWaitTimeout(error))
345516
+ throw new StreamInterruptedError(safeFailure(error, request));
345508
345517
  if (!transportFailure(error))
345509
345518
  throw error;
345510
345519
  }
@@ -345588,7 +345597,10 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345588
345597
  }
345589
345598
  let localProgress = false;
345590
345599
  const localPacket = { ...this.localRequest(request), onLocalInferenceSemanticProgress: () => {
345591
- localProgress = true;
345600
+ if (!localProgress) {
345601
+ localProgress = true;
345602
+ this.lifecycle(request, "selected", void 0, void 0, void 0, void 0, void 0, true);
345603
+ }
345592
345604
  request.onLocalInferenceSemanticProgress?.();
345593
345605
  } };
345594
345606
  if (!this.eligible(request)) {
@@ -345601,6 +345613,10 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345601
345613
  yield* this.boundedStream(localPacket, this.localAttemptTimeoutMs(request), local, true, "local_first_frame");
345602
345614
  } catch (error) {
345603
345615
  this.fence(request);
345616
+ if (this.retainedLocalAdmission(error, request))
345617
+ throw error;
345618
+ if (localProgress && this.initialWaitTimeout(error))
345619
+ throw new StreamInterruptedError(safeFailure(error, request));
345604
345620
  throw this.localWaiting(error) ?? (!localProgress && this.initialWaitTimeout(error) ? new LocalInferenceNotReadyError("initial_response_timeout", error) : error);
345605
345621
  }
345606
345622
  return;
@@ -345623,7 +345639,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345623
345639
  return;
345624
345640
  } catch (error) {
345625
345641
  this.fence(request);
345626
- if (emitted) {
345642
+ if (emitted || localProgress && this.initialWaitTimeout(error)) {
345627
345643
  if (localSelected)
345628
345644
  this.lifecycle(request, "failed", void 0, error, frames);
345629
345645
  throw new StreamInterruptedError(safeFailure(error, request, void 0, frames));
@@ -345960,7 +345976,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345960
345976
  }
345961
345977
  this.lifecycle(request, "selected", route);
345962
345978
  }
345963
- lifecycle(request, phase, route, error, frames, completedBinding, decision2) {
345979
+ lifecycle(request, phase, route, error, frames, completedBinding, decision2, semanticProgress = false) {
345964
345980
  this.fence(request);
345965
345981
  if (!request.onInferenceRouteLifecycle)
345966
345982
  return;
@@ -345973,6 +345989,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
345973
345989
  providerId: route ? route.keyless?.id ?? route.providerId ?? "remote" : this.primary.providerId ?? "ollama",
345974
345990
  backendType: route ? "vllm" : this.primary.backendType ?? "ollama",
345975
345991
  ...request.logicalRequestId ? { logicalRequestId: request.logicalRequestId } : {},
345992
+ ...semanticProgress ? { semanticProgress: true } : {},
345976
345993
  ...route && (this.schemaRestrictions(route).length || promptOnly) ? { schemaAdapter: {
345977
345994
  omittedNativeKeywords: this.schemaRestrictions(route),
345978
345995
  hostValidation: "unchanged",
@@ -346039,11 +346056,16 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346039
346056
  route.apiKey = current2.apiKey;
346040
346057
  }
346041
346058
  }
346042
- async attempt(request, timeoutMs, operation, deadlineKind = "request") {
346059
+ async attempt(request, timeoutMs, operation, deadlineKind = "request", initialResponseOnly = false) {
346043
346060
  const controller = new AbortController();
346044
346061
  const signal = request.signal ? AbortSignal.any([request.signal, controller.signal]) : controller.signal;
346045
346062
  let timer = setTimeout(() => controller.abort(new AttemptTimeout(deadlineKind)), Math.max(1, timeoutMs));
346046
- const bounded3 = { ...request, signal };
346063
+ const bounded3 = { ...request, signal, ...initialResponseOnly ? { onLocalInferenceSemanticProgress: () => {
346064
+ if (signal.aborted)
346065
+ return;
346066
+ clearTimeout(timer);
346067
+ request.onLocalInferenceSemanticProgress?.();
346068
+ } } : {} };
346047
346069
  try {
346048
346070
  return await this.abortable(operation(bounded3), signal);
346049
346071
  } finally {
@@ -346055,15 +346077,24 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346055
346077
  const controller = new AbortController();
346056
346078
  const signal = request.signal ? AbortSignal.any([request.signal, controller.signal]) : controller.signal;
346057
346079
  let timer = setTimeout(() => controller.abort(new AttemptTimeout(deadlineKind)), Math.max(1, timeoutMs));
346058
- const iterator = operation({ ...request, signal });
346080
+ const progress = () => {
346081
+ if (signal.aborted)
346082
+ return;
346083
+ clearTimeout(timer);
346084
+ request.onLocalInferenceSemanticProgress?.();
346085
+ };
346086
+ const iterator = operation({
346087
+ ...request,
346088
+ signal,
346089
+ ...firstFrameOnly ? { onLocalInferenceSemanticProgress: progress } : {}
346090
+ });
346059
346091
  try {
346060
346092
  for (; ; ) {
346061
346093
  const step = await this.abortable(iterator.next(), signal);
346062
346094
  if (step.done)
346063
346095
  return;
346064
346096
  if (firstFrameOnly && (step.value.type === "tool_call_delta" || step.value.type === "content" && Boolean(step.value.content))) {
346065
- clearTimeout(timer);
346066
- request.onLocalInferenceSemanticProgress?.();
346097
+ progress();
346067
346098
  }
346068
346099
  yield step.value;
346069
346100
  }
@@ -368550,155 +368581,6 @@ async function runStuckAnalyzer(opts) {
368550
368581
  };
368551
368582
  }
368552
368583
 
368553
- // packages/orchestrator/dist/thinking-mode-collapse.js
368554
- function renderModeCollapsePrompt(inputs) {
368555
- const lines = [];
368556
- lines.push("# THINKING STREAM MODE-COLLAPSE ANALYSIS");
368557
- lines.push("");
368558
- lines.push("You are a META-ANALYSIS sub-agent. A model (the generator) has been");
368559
- lines.push("producing internal reasoning tokens for an extended period without");
368560
- lines.push("emitting any visible output or tool calls. A sample of its reasoning");
368561
- lines.push("stream is provided below.");
368562
- lines.push("");
368563
- lines.push("Your job: classify whether the generator is experiencing a MODE COLLAPSE");
368564
- lines.push("(a reasoning loop where it repeats the same idea, goes in circles, or");
368565
- lines.push("degrades into noise) or is still PRODUCTIVELY REASONING (making linear");
368566
- lines.push("progress toward a conclusion).");
368567
- lines.push("");
368568
- lines.push("## Collapse categories");
368569
- lines.push("");
368570
- lines.push("- mode_collapse_exact_repeat: The model emits the exact same sentence or");
368571
- lines.push(" paragraph 2+ times. The text is verbatim identical.");
368572
- lines.push("");
368573
- lines.push("- mode_collapse_semantic_loop: The model rephrases the same idea");
368574
- lines.push(" repeatedly with different wording. Same concept, new sentences.");
368575
- lines.push(" No new reasoning steps or conclusions.");
368576
- lines.push("");
368577
- lines.push("- mode_collapse_circular: The model alternates between two or more");
368578
- lines.push(" positions/approaches without converging. A -> B -> A -> B pattern.");
368579
- lines.push("");
368580
- lines.push("- mode_collapse_degraded: The reasoning quality is visibly degrading —");
368581
- lines.push(" sentences get shorter, less coherent, fragmented, or trail off.");
368582
- lines.push(" The model is losing the thread.");
368583
- lines.push("");
368584
- lines.push("- mode_collapse_stuck_at_start: The model keeps restating the problem or");
368585
- lines.push(" the first step but never moves to subsequent steps. Stuck in a");
368586
- lines.push(" preamble loop.");
368587
- lines.push("");
368588
- lines.push("- healthy: The reasoning is making linear progress. Each sentence builds");
368589
- lines.push(" on or advances from the previous one. The model is analyzing,");
368590
- lines.push(" comparing, planning, or synthesizing in a productive direction.");
368591
- lines.push("");
368592
- lines.push("## Context");
368593
- lines.push(`Goal: ${inputs.goal.slice(0, 500)}`);
368594
- lines.push(`Total thinking produced: ${inputs.totalThinkingChars} characters over ${(inputs.thinkingDurationMs / 1e3).toFixed(0)}s`);
368595
- if (inputs.lastToolNames.length > 0) {
368596
- lines.push(`Recent tool calls before thinking: ${inputs.lastToolNames.join(", ")}`);
368597
- }
368598
- lines.push("");
368599
- lines.push("## Thinking sample (most recent portion)");
368600
- lines.push("");
368601
- lines.push("```");
368602
- lines.push(inputs.thinkingSample.slice(0, 3e3));
368603
- lines.push("```");
368604
- lines.push("");
368605
- lines.push("## Output format");
368606
- lines.push("");
368607
- lines.push("Emit a SINGLE JSON code block with this exact shape:");
368608
- lines.push("");
368609
- lines.push("```json");
368610
- lines.push("{");
368611
- lines.push(' "category": "<one of the categories above>",');
368612
- lines.push(' "diagnosis": "<1-2 sentence diagnosis>",');
368613
- lines.push(' "confidence": <0.0-1.0>,');
368614
- lines.push(' "suggested_action": "<one of: none, abort_and_retry_no_think, abort_and_nudge, abort_and_force_tool_call>"');
368615
- lines.push("}");
368616
- lines.push("```");
368617
- lines.push("");
368618
- lines.push("Only flag as collapse if confidence > 0.7. When unsure, classify as healthy");
368619
- lines.push("with low confidence — false positives (aborting productive reasoning) are");
368620
- lines.push("more harmful than false negatives (letting a collapse continue briefly).");
368621
- return lines.join("\n");
368622
- }
368623
- function parseModeCollapseVerdict(rawResponse) {
368624
- const fallback = (msg) => ({
368625
- category: "healthy",
368626
- diagnosis: `(sub-agent parse failed: ${msg})`,
368627
- confidence: 0,
368628
- suggested_action: "none",
368629
- raw: rawResponse,
368630
- parseFallback: true
368631
- });
368632
- if (!rawResponse || typeof rawResponse !== "string" || rawResponse.trim().length === 0) {
368633
- return fallback("empty response");
368634
- }
368635
- const fenceMatch = rawResponse.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
368636
- let jsonText = null;
368637
- if (fenceMatch) {
368638
- jsonText = fenceMatch[1].trim();
368639
- } else {
368640
- const first = rawResponse.indexOf("{");
368641
- const last = rawResponse.lastIndexOf("}");
368642
- if (first !== -1 && last > first)
368643
- jsonText = rawResponse.slice(first, last + 1);
368644
- }
368645
- if (!jsonText)
368646
- return fallback("no JSON block found");
368647
- let parsed;
368648
- try {
368649
- parsed = JSON.parse(jsonText);
368650
- } catch (e) {
368651
- return fallback(`JSON parse: ${e instanceof Error ? e.message : String(e)}`);
368652
- }
368653
- if (!parsed || typeof parsed !== "object")
368654
- return fallback("not an object");
368655
- const validCategories = [
368656
- "healthy",
368657
- "mode_collapse_exact_repeat",
368658
- "mode_collapse_semantic_loop",
368659
- "mode_collapse_circular",
368660
- "mode_collapse_degraded",
368661
- "mode_collapse_stuck_at_start"
368662
- ];
368663
- const category = typeof parsed.category === "string" && validCategories.includes(parsed.category) ? parsed.category : "healthy";
368664
- const diagnosis = typeof parsed.diagnosis === "string" && parsed.diagnosis.trim().length > 0 ? parsed.diagnosis.slice(0, 500) : "(no diagnosis)";
368665
- const confidence2 = typeof parsed.confidence === "number" ? Math.max(0, Math.min(1, parsed.confidence)) : 0;
368666
- const validActions = [
368667
- "none",
368668
- "abort_and_retry_no_think",
368669
- "abort_and_nudge",
368670
- "abort_and_force_tool_call"
368671
- ];
368672
- const suggested_action = typeof parsed.suggested_action === "string" && validActions.includes(parsed.suggested_action) ? parsed.suggested_action : "none";
368673
- return {
368674
- category,
368675
- diagnosis,
368676
- confidence: confidence2,
368677
- suggested_action,
368678
- raw: rawResponse,
368679
- parseFallback: false
368680
- };
368681
- }
368682
- async function runModeCollapseAnalysis(opts) {
368683
- const startMs = Date.now();
368684
- const prompt = renderModeCollapsePrompt(opts.inputs);
368685
- const promptBytes = Buffer.byteLength(prompt, "utf-8");
368686
- let raw = "";
368687
- try {
368688
- raw = await opts.callable(prompt);
368689
- } catch {
368690
- raw = "";
368691
- }
368692
- const responseBytes = Buffer.byteLength(raw, "utf-8");
368693
- const verdict = parseModeCollapseVerdict(raw);
368694
- return {
368695
- verdict,
368696
- promptBytes,
368697
- responseBytes,
368698
- durationMs: Date.now() - startMs
368699
- };
368700
- }
368701
-
368702
368584
  // packages/orchestrator/dist/native-ollama-messages.js
368703
368585
  function nativeOllamaMessages(messages2) {
368704
368586
  const toolNames = /* @__PURE__ */ new Map();
@@ -428134,28 +428016,6 @@ ${description}`
428134
428016
  });
428135
428017
  this._streamingExecutor.reset();
428136
428018
  let lastFinalizedIdx = -1;
428137
- let firstThinkingTime = 0;
428138
- let watchdogTripped = false;
428139
- let thinkingSample = "";
428140
- let watchdogMs = typeof backend.getThinkingWatchdogMs === "function" ? backend.getThinkingWatchdogMs() : 6e4;
428141
- if (watchdogMs > 15e3) {
428142
- let estimatedHistoryTokens = 0;
428143
- for (const m of request.messages) {
428144
- const c = typeof m.content === "string" ? m.content : "";
428145
- estimatedHistoryTokens += c.length;
428146
- if (m.tool_calls) {
428147
- for (const tc of m.tool_calls) {
428148
- estimatedHistoryTokens += tc.function?.arguments?.length ?? 0;
428149
- }
428150
- }
428151
- }
428152
- estimatedHistoryTokens = Math.round(estimatedHistoryTokens / 4);
428153
- if (estimatedHistoryTokens > 28e3) {
428154
- watchdogMs = Math.min(watchdogMs, 3e4);
428155
- } else if (estimatedHistoryTokens > 24e3) {
428156
- watchdogMs = Math.min(watchdogMs, 45e3);
428157
- }
428158
- }
428159
428019
  for await (const chunk of backend.chatCompletionStream(request)) {
428160
428020
  request.signal?.throwIfAborted();
428161
428021
  if (this.aborted || this._pendingSteeringPreemption)
@@ -428189,25 +428049,6 @@ ${description}`
428189
428049
  } else {
428190
428050
  thinkingContent += fragment;
428191
428051
  }
428192
- if (kind === "thinking") {
428193
- if (firstThinkingTime === 0)
428194
- firstThinkingTime = Date.now();
428195
- if (!watchdogTripped) {
428196
- const elapsed = Date.now() - firstThinkingTime;
428197
- if (elapsed >= watchdogMs) {
428198
- watchdogTripped = true;
428199
- thinkingSample = thinkingContent.slice(-3e3);
428200
- this.emit({
428201
- type: "status",
428202
- content: `Thinking watchdog tripped after ${Math.round(elapsed / 1e3)}s (threshold=${(watchdogMs / 1e3).toFixed(0)}s) — model may be in a reasoning loop`,
428203
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
428204
- });
428205
- break;
428206
- }
428207
- }
428208
- } else {
428209
- firstThinkingTime = 0;
428210
- }
428211
428052
  const buf = kind === "content" ? content : thinkingContent;
428212
428053
  if (buf.length > 200 && buf.length % 100 < fragment.length) {
428213
428054
  const tail = buf.slice(-600);
@@ -428397,80 +428238,9 @@ arguments=` : ""}` + (chunk.toolCallArgs ?? "");
428397
428238
  };
428398
428239
  if (thinkOnlyResponse)
428399
428240
  resp._thinkOnly = true;
428400
- if (watchdogTripped)
428401
- resp._watchdogTripped = true;
428402
428241
  resp._rawTypedModelContent = content;
428403
- if (watchdogTripped && thinkingSample.length > 0) {
428404
- this._fireModeCollapseAnalysis(backend, thinkingSample, thinkingContent.length, Date.now() - (firstThinkingTime || Date.now()), turn);
428405
- }
428406
428242
  return resp;
428407
428243
  }
428408
- /**
428409
- * Fire-and-forget mode-collapse analysis. Called when the streaming
428410
- * watchdog detects extended thinking without visible output. Fires a
428411
- * sub-agent to classify the thinking pattern and updates the backend's
428412
- * elevated scrutiny state for future turns.
428413
- *
428414
- * The sub-agent call runs asynchronously and does NOT block the current
428415
- * response — the watchdog already aborted it. This is purely diagnostic
428416
- * and adjusts thresholds for subsequent turns.
428417
- *
428418
- * Gated behind OMNIUS_MODE_COLLAPSE_ANALYZER env (default "on") so users
428419
- * who want zero extra round-trips can disable it.
428420
- */
428421
- _fireModeCollapseAnalysis(backend, thinkingSample, totalThinkingChars, thinkingDurationMs, turn) {
428422
- const gate = (process.env["OMNIUS_MODE_COLLAPSE_ANALYZER"] || "on").toLowerCase();
428423
- if (gate !== "on" && gate !== "1" && gate !== "true")
428424
- return;
428425
- const goal = this._taskState?.originalGoal || this._taskState?.goal || "";
428426
- const callable = async (prompt) => {
428427
- try {
428428
- const r = await this._dispatchInterruptionOwnedModelRequest(backend, {
428429
- messages: [
428430
- {
428431
- role: "system",
428432
- content: "You are a META-ANALYSIS sub-agent. Classify the generator's thinking stream and emit a structured JSON verdict."
428433
- },
428434
- { role: "user", content: prompt }
428435
- ],
428436
- tools: [],
428437
- temperature: 0,
428438
- maxTokens: parseInt(process.env["OMNIUS_MODE_COLLAPSE_MAX_TOKENS"] || "1024", 10) || 1024,
428439
- timeoutMs: parseInt(process.env["OMNIUS_MODE_COLLAPSE_TIMEOUT_MS"] || "30000", 10) || 3e4
428440
- }, `model:mode_collapse:${turn}`);
428441
- const c = r?.choices?.[0]?.message?.content;
428442
- return typeof c === "string" ? c : "";
428443
- } catch {
428444
- return "";
428445
- }
428446
- };
428447
- runModeCollapseAnalysis({
428448
- inputs: {
428449
- thinkingSample,
428450
- totalThinkingChars,
428451
- thinkingDurationMs,
428452
- goal,
428453
- lastToolNames: []
428454
- },
428455
- callable
428456
- }).then((result) => {
428457
- if (result.verdict.category !== "healthy" && result.verdict.confidence >= 0.7) {
428458
- backend.recordModeCollapse();
428459
- this.emit({
428460
- type: "status",
428461
- content: `Mode-collapse analysis: ${result.verdict.category} (conf=${result.verdict.confidence.toFixed(2)}) — ${result.verdict.diagnosis.slice(0, 120)}. Collapse #${backend.getModeCollapseCount()}, scrutiny level ${backend.getElevatedScrutinyLevel()}`,
428462
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
428463
- });
428464
- } else {
428465
- this.emit({
428466
- type: "status",
428467
- content: `Thinking analysis: ${result.verdict.category} (conf=${result.verdict.confidence.toFixed(2)}) — thinking was healthy, continuing`,
428468
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
428469
- });
428470
- }
428471
- }).catch(() => {
428472
- });
428473
- }
428474
428244
  };
428475
428245
  function stripThinkBlocks(s) {
428476
428246
  if (!s)
@@ -429363,12 +429133,62 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
429363
429133
  });
429364
429134
  }
429365
429135
  async chatCompletion(request) {
429136
+ if (this._provider.protocol === "ollama")
429137
+ request.logicalRequestId = normalizeOllamaLogicalRequestId(request.logicalRequestId ?? crypto.randomUUID());
429366
429138
  return this.remoteFallback().complete(this.requestWithRunSignal(request), async (localRequest) => {
429367
429139
  if (localRequest.localAdmissionFailure !== void 0)
429368
429140
  throw localRequest.localAdmissionFailure;
429141
+ if ((this._provider.protocol === "ollama" || this._provider.protocol === "openai-chat") && isLocalInferenceEndpoint(this.baseUrl) && localRequest.maxTokens > 0)
429142
+ return this.aggregateLocalCompletion(localRequest);
429369
429143
  return this.chatCompletionDirect(localRequest);
429370
429144
  });
429371
429145
  }
429146
+ async aggregateLocalCompletion(request, emptyRecovery) {
429147
+ let content = "", thinking = "";
429148
+ let usage, responseDiagnostics;
429149
+ let finishReason2;
429150
+ const calls = /* @__PURE__ */ new Map();
429151
+ for await (const chunk of this.chatCompletionStreamDirect(request, emptyRecovery)) {
429152
+ request.signal?.throwIfAborted();
429153
+ if (chunk.type === "content" && chunk.content) {
429154
+ if (chunk.thinking)
429155
+ thinking += chunk.content;
429156
+ else
429157
+ content += chunk.content;
429158
+ } else if (chunk.type === "tool_call_delta") {
429159
+ const index = chunk.toolCallIndex ?? 0;
429160
+ const call2 = calls.get(index) ?? { id: chunk.toolCallId ?? (request.configuredEndpointOnly === true ? "" : crypto.randomUUID()), name: "", args: "" };
429161
+ if (chunk.toolCallId)
429162
+ call2.id = chunk.toolCallId;
429163
+ if (chunk.toolCallName)
429164
+ call2.name = chunk.toolCallName;
429165
+ if (chunk.toolCallArgs)
429166
+ call2.args += chunk.toolCallArgs;
429167
+ calls.set(index, call2);
429168
+ } else if (chunk.type === "usage")
429169
+ usage = chunk.usage;
429170
+ else if (chunk.type === "finish") {
429171
+ finishReason2 = chunk.finishReason;
429172
+ if (chunk.responseDiagnostics)
429173
+ responseDiagnostics = chunk.responseDiagnostics;
429174
+ }
429175
+ }
429176
+ request.signal?.throwIfAborted();
429177
+ const message = normalizeProviderToolMessage({ content, tool_calls: [...calls.values()].map((call2) => ({
429178
+ id: call2.id,
429179
+ type: "function",
429180
+ function: { name: call2.name, arguments: call2.args || "{}" }
429181
+ })) }, this.model, request.configuredEndpointOnly === true);
429182
+ return {
429183
+ choices: [{ message: {
429184
+ content: thinking ? `<think>${thinking}</think>${message.content ?? ""}` : message.content,
429185
+ ...message.toolCalls?.length ? { toolCalls: message.toolCalls } : {}
429186
+ } }],
429187
+ ...responseDiagnostics ? { responseDiagnostics } : {},
429188
+ ...finishReason2 ? { outputTruncated: finishReason2 === "length" } : {},
429189
+ ...usage ? { usage: buildAgenticUsage(usage) } : {}
429190
+ };
429191
+ }
429372
429192
  async chatCompletionDirect(request) {
429373
429193
  if (this._provider.protocol === "ollama") {
429374
429194
  request.logicalRequestId = normalizeOllamaLogicalRequestId(request.logicalRequestId ?? crypto.randomUUID());
@@ -429817,6 +429637,8 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
429817
429637
  * Ollama pool routing as non-stream completions.
429818
429638
  */
429819
429639
  async *chatCompletionStream(request) {
429640
+ if (this._provider.protocol === "ollama")
429641
+ request.logicalRequestId = normalizeOllamaLogicalRequestId(request.logicalRequestId ?? crypto.randomUUID());
429820
429642
  const backend = this;
429821
429643
  yield* this.remoteFallback().stream(this.requestWithRunSignal(request), async function* (localRequest) {
429822
429644
  if (localRequest.localAdmissionFailure !== void 0)
@@ -429824,7 +429646,7 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
429824
429646
  yield* backend.chatCompletionStreamDirect(localRequest);
429825
429647
  });
429826
429648
  }
429827
- async *chatCompletionStreamDirect(request) {
429649
+ async *chatCompletionStreamDirect(request, emptyRecovery) {
429828
429650
  if (this._provider.protocol === "ollama") {
429829
429651
  request.logicalRequestId = normalizeOllamaLogicalRequestId(request.logicalRequestId ?? crypto.randomUUID());
429830
429652
  }
@@ -429909,7 +429731,7 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
429909
429731
  stream_options: { include_usage: true }
429910
429732
  };
429911
429733
  const isOllamaTransport = this._provider.protocol === "ollama";
429912
- const useOllamaPool = request.configuredEndpointOnly !== true && isOllamaTransport && shouldUseOllamaPoolForBaseUrl(this.baseUrl);
429734
+ const useOllamaPool = !emptyRecovery && request.configuredEndpointOnly !== true && isOllamaTransport && shouldUseOllamaPoolForBaseUrl(this.baseUrl);
429913
429735
  if (isOllamaTransport)
429914
429736
  body["think"] = effectiveThink;
429915
429737
  if (!isOllamaTransport && request.chatTemplateKwargs)
@@ -429931,7 +429753,7 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
429931
429753
  queuePolicy: request.poolQueuePolicy,
429932
429754
  queueTimeoutMs: request.poolQueueTimeoutMs
429933
429755
  }) : null;
429934
- let requestBaseUrl = poolSlot?.baseUrl ?? this.baseUrl;
429756
+ let requestBaseUrl = emptyRecovery?.baseUrl ?? poolSlot?.baseUrl ?? this.baseUrl;
429935
429757
  let poolSuccess = false;
429936
429758
  const releasePoolSlot = (success) => {
429937
429759
  if (!poolSlot)
@@ -429948,10 +429770,12 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
429948
429770
  const armStreamTimeout = () => {
429949
429771
  const waiting = localInitialDeadline !== void 0 && !localSemanticProgress;
429950
429772
  const timeout = waiting ? Math.max(1, localInitialDeadline - Date.now()) : streamTimeoutMs;
429773
+ if (streamTimeoutHandle) {
429774
+ clearTimeout(streamTimeoutHandle);
429775
+ streamTimeoutHandle = void 0;
429776
+ }
429951
429777
  if (timeout === null)
429952
429778
  return;
429953
- if (streamTimeoutHandle)
429954
- clearTimeout(streamTimeoutHandle);
429955
429779
  streamTimeoutHandle = setTimeout(() => {
429956
429780
  streamAbort.abort(waiting ? new LocalInferenceNotReadyError("initial_response_timeout") : new Error(`stream timeout: no response or chunk within ${(timeout / 1e3).toFixed(0)}s`));
429957
429781
  }, timeout);
@@ -430235,16 +430059,25 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
430235
430059
  yield { type: "finish", finishReason: finishReason2 };
430236
430060
  }
430237
430061
  }
430238
- if (isOllamaTransport && effectiveThink === false && sawReasoningTokens && !accumulatedContent.trim() && !sawToolCallDeltas) {
430062
+ const emptyVisibleOutcome = classifyThinkOutcome(accumulatedContent);
430063
+ const literalThinkingOnly = accumulatedContent.includes("<think>") && (emptyVisibleOutcome === "empty_after_strip" || emptyVisibleOutcome === "unclosed_think");
430064
+ if (!emptyRecovery && isOllamaTransport && effectiveThink === false && (sawReasoningTokens && !accumulatedContent.trim() || literalThinkingOnly) && !sawToolCallDeltas) {
430239
430065
  const nativeRecoveryRequest = withLogicalRequestVariant(request, "native-empty-recovery");
430240
- const nativeRecovery = await this.nativeOllamaChatCompletion(nativeRecoveryRequest, {
430066
+ const nativeRecovery = isLocalInferenceEndpoint(this.baseUrl) && request.maxTokens > 0 ? await this.aggregateLocalCompletion({
430067
+ ...nativeRecoveryRequest,
430068
+ preferNativeOllamaChat: true,
430069
+ think: false,
430070
+ signal: streamAbort.signal,
430071
+ onLocalInferenceSemanticProgress: markLocalSemanticProgress
430072
+ }, { baseUrl: requestBaseUrl }) : await this.nativeOllamaChatCompletion(nativeRecoveryRequest, {
430241
430073
  baseUrl: requestBaseUrl,
430242
430074
  signal: streamAbort.signal,
430243
430075
  noThinkDirectives: true
430244
430076
  });
430245
430077
  const recoveredMessage = nativeRecovery.choices[0]?.message;
430246
430078
  const recoveredContent = recoveredMessage?.content ?? "";
430247
- if (recoveredContent) {
430079
+ const usableRecoveryContent = recoveredContent.trim().length >= 2 && classifyThinkOutcome(recoveredContent) === null;
430080
+ if (usableRecoveryContent) {
430248
430081
  accumulatedContent = recoveredContent;
430249
430082
  yield { type: "content", content: recoveredContent };
430250
430083
  }
@@ -430273,6 +430106,17 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
430273
430106
  type: "finish",
430274
430107
  finishReason: sawToolCallDeltas ? "tool_calls" : "stop"
430275
430108
  };
430109
+ if (!usableRecoveryContent && !sawToolCallDeltas && request.disableEmptyContentRecovery !== true) {
430110
+ const changedRetry = withLogicalRequestVariant(request, "openai-empty-retry");
430111
+ yield* this.chatCompletionStreamDirect({
430112
+ ...changedRetry,
430113
+ responseFormat: void 0,
430114
+ response_format: void 0,
430115
+ think: false,
430116
+ signal: streamAbort.signal,
430117
+ onLocalInferenceSemanticProgress: markLocalSemanticProgress
430118
+ }, { baseUrl: requestBaseUrl });
430119
+ }
430276
430120
  }
430277
430121
  this._finalizeStreamGuard(effectiveThink, accumulatedContent, accumulatedThinking, sawReasoningTokens);
430278
430122
  poolSuccess = true;