omnius 1.0.873 → 1.0.874

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: 37773730 bytes
4
- sha256: f762c00e6a2c7407ca37ff6c15bacffd0028cd2c2927dd91fd7db512549090c8
3
+ size: 37925419 bytes
4
+ sha256: 60600931f277c7850afc402e56d9985628d48802a8c905961f9396a865666432
package/dist/library.js CHANGED
@@ -340844,14 +340844,14 @@ var registrations = [
340844
340844
  label: "Built-in free",
340845
340845
  protocol: "openai-chat",
340846
340846
  local: false,
340847
- apiPrefix: "/inference/v1",
340848
- paths: { chat: "/inference/v1/chat/completions", models: "/inference/v1/models" },
340847
+ apiPrefix: "/inference/openai/v1",
340848
+ paths: { chat: "/inference/openai/v1/chat/completions", models: "/inference/openai/v1/models" },
340849
340849
  auth: { strategy: "bearer", required: false, staticHeaders: { Authorization: "Bearer public" } },
340850
340850
  capabilities: CHAT_CAPABILITIES,
340851
- defaultUrl: "https://opencode.ai/inference/v1",
340851
+ defaultUrl: "https://opencode.ai/inference/openai/v1",
340852
340852
  description: "Built-in models with public access where permitted and optional provider-bound API credentials."
340853
340853
  }),
340854
- match: (url) => url.protocol === "https:" && url.hostname.toLowerCase() === "opencode.ai" && !url.port && /^\/inference\/v1(?:\/(?:models|chat\/completions|responses))?\/?$/.test(url.pathname)
340854
+ match: (url) => url.protocol === "https:" && url.hostname.toLowerCase() === "opencode.ai" && !url.port && /^\/inference\/(?:openai\/)?v1(?:\/(?:models|chat\/completions|responses))?\/?$/.test(url.pathname)
340855
340855
  },
340856
340856
  {
340857
340857
  descriptor: descriptor({
@@ -341436,7 +341436,7 @@ function resolveProviderTransport(options) {
341436
341436
  }
341437
341437
  if (provider.id === "builtin-free") {
341438
341438
  const url = parseProviderUrl(rawUrl);
341439
- if (url.protocol !== "https:" || url.hostname.toLowerCase() !== "opencode.ai" || url.port || url.username || url.password || url.search || url.hash || !/^\/inference\/v1(?:\/(?:models|chat\/completions|responses))?\/?$/.test(url.pathname)) {
341439
+ if (url.protocol !== "https:" || url.hostname.toLowerCase() !== "opencode.ai" || url.port || url.username || url.password || url.search || url.hash || !/^\/inference\/(?:openai\/)?v1(?:\/(?:models|chat\/completions|responses))?\/?$/.test(url.pathname)) {
341440
341440
  throw new UnknownProviderProtocolError("Built-in inference requires its exact registered HTTPS endpoint.");
341441
341441
  }
341442
341442
  }
@@ -341631,7 +341631,7 @@ var PROVIDER_PRESETS = [
341631
341631
  ];
341632
341632
 
341633
341633
  // packages/backend-vllm/dist/builtin-free-credentials.js
341634
- var BUILTIN_INFERENCE_ENDPOINT = "https://opencode.ai/inference/v1";
341634
+ var BUILTIN_INFERENCE_ENDPOINTS = /* @__PURE__ */ new Set(["https://opencode.ai/inference/v1", "https://opencode.ai/inference/openai/v1"]);
341635
341635
  function hostEnvironment() {
341636
341636
  return globalThis.process?.env ?? {};
341637
341637
  }
@@ -341649,7 +341649,7 @@ function resolveBuiltInFreeApiKey(baseUrl, env = hostEnvironment()) {
341649
341649
  } catch {
341650
341650
  return void 0;
341651
341651
  }
341652
- if (url.username || url.password || url.search || url.hash || url.href.replace(/\/+$/, "") !== BUILTIN_INFERENCE_ENDPOINT)
341652
+ if (url.username || url.password || url.search || url.hash || !BUILTIN_INFERENCE_ENDPOINTS.has(url.href.replace(/\/+$/, "")))
341653
341653
  return void 0;
341654
341654
  const key = env["OPENCODE_API_KEY"];
341655
341655
  if (key === void 0 || key === "" || key === "public")
@@ -343363,7 +343363,11 @@ init_dist5();
343363
343363
  // packages/orchestrator/dist/opencode-free-models.js
343364
343364
  import { createHash as createHash44, randomBytes as randomBytes6 } from "node:crypto";
343365
343365
  var OPENCODE_MODEL_CATALOG_URL = "https://models.opencode.ai/api.json";
343366
- var OPENCODE_INFERENCE_BASE_URL = "https://opencode.ai/inference/v1";
343366
+ var OPENCODE_LEGACY_INFERENCE_BASE_URL = "https://opencode.ai/inference/v1";
343367
+ var OPENCODE_INFERENCE_BASE_URL = "https://opencode.ai/inference/openai/v1";
343368
+ function isOpenCodeInferenceBaseUrl(value) {
343369
+ return value === OPENCODE_INFERENCE_BASE_URL || value === OPENCODE_LEGACY_INFERENCE_BASE_URL;
343370
+ }
343367
343371
  var OPENCODE_AVAILABLE_MODELS_URL = `${OPENCODE_INFERENCE_BASE_URL}/models`;
343368
343372
  var OPENCODE_COMPATIBILITY_CLIENT_VERSION = "2.0.27";
343369
343373
  var observedModelCompatibility = Object.freeze({
@@ -343382,6 +343386,10 @@ var observedModelCompatibility = Object.freeze({
343382
343386
  // Production chat + review accepted the unchanged host JSON contract only
343383
343387
  // when native response_format was omitted, observed 2026-10-13.
343384
343388
  "big-pickle": Object.freeze({ nativeStructuredOutput: false }),
343389
+ // Canonical chat rejects the real child completion schema unless every
343390
+ // object forbids additional properties (2026-10-17). Preserve its original
343391
+ // host contract through prompt-only framing instead of tightening it.
343392
+ "beam-free": Object.freeze({ nativeStructuredOutput: false }),
343385
343393
  // Step accepts simple native JSON but rejects complex Telegram control
343386
343394
  // schemas with HTTP400. The identical generation + review contract passed
343387
343395
  // when only native framing was omitted (2026-10-13); prefer prompt-only
@@ -343500,7 +343508,7 @@ function tryParseOpenCodeFreeModelCatalog(json5) {
343500
343508
  if (!object2(catalog) || !object2(catalog.opencode))
343501
343509
  return void 0;
343502
343510
  const provider = catalog.opencode;
343503
- if (provider.id !== "opencode" || provider.api !== OPENCODE_INFERENCE_BASE_URL || !["@ai-sdk/openai-compatible", "@ai-sdk/openai"].includes(String(provider.npm)) || !object2(provider.models))
343511
+ if (provider.id !== "opencode" || !isOpenCodeInferenceBaseUrl(provider.api) || !["@ai-sdk/openai-compatible", "@ai-sdk/openai"].includes(String(provider.npm)) || !object2(provider.models))
343504
343512
  return void 0;
343505
343513
  const entries = Object.entries(provider.models);
343506
343514
  if (entries.length > MAX_OPENCODE_CATALOG_MODELS)
@@ -343511,7 +343519,7 @@ function tryParseOpenCodeFreeModelCatalog(json5) {
343511
343519
  continue;
343512
343520
  if (model.limit.input !== void 0 && (!positiveInteger2(model.limit.input) || model.limit.input > model.limit.context))
343513
343521
  continue;
343514
- if (model.provider !== void 0 && (!object2(model.provider) || model.provider.api !== void 0 && model.provider.api !== OPENCODE_INFERENCE_BASE_URL))
343522
+ if (model.provider !== void 0 && (!object2(model.provider) || model.provider.api !== void 0 && !isOpenCodeInferenceBaseUrl(model.provider.api)))
343515
343523
  continue;
343516
343524
  const transport = object2(model.provider) ? model.provider : {};
343517
343525
  const npm = transport.npm ?? provider.npm;
@@ -343752,14 +343760,15 @@ function parseKeylessInferenceRegistry(html) {
343752
343760
 
343753
343761
  // packages/orchestrator/dist/builtin-free-snapshot.js
343754
343762
  var rows = [
343755
- ["muse-spark-1.3-contributor-free", "Muse Spark 1.3 Free", 1048576, 131072, void 0, true, true],
343756
- ["step-5-preview-free", "Step 5 Preview Free", 1e6, 65536, 1e6, true],
343757
- ["nemotron-3-ultra-free", "Nemotron 3 Ultra Free", 1e6, 128e3, void 0, void 0],
343758
- ["mimo-v2.6-flash-free", "MiMo-V2.6-Flash Free", 2e5, 32e3, void 0, void 0],
343759
- ["nemotron-3.5-lightning-free", "Nemotron 3.5 Lightning Free", 262144, 262144, void 0, true],
343763
+ ["beam-free", "Beam Free", 1048576, 131072, void 0, true],
343760
343764
  ["big-pickle", "Big Pickle", 2e5, 32e3, 16e4, true],
343761
- ["cat-jam-free", "Cat Jam Free", 262144, 131072, void 0, true],
343765
+ ["deepseek-v4.1-flash-free", "DeepSeek V4.1 Flash Free", 2e5, 32e3, void 0, true],
343766
+ ["glm-5.3-flash-free", "GLM-5.3-Flash Free", 2e5, 32e3, void 0, true],
343762
343767
  ["longcat-2.5-preview-free", "LongCat 2.5 Preview Free", 1e6, 131072, void 0, void 0],
343768
+ ["mimo-v2.6-flash-free", "MiMo-V2.6-Flash Free", 2e5, 32e3, void 0, void 0],
343769
+ ["nemotron-3-ultra-free", "Nemotron 3 Ultra Free", 1e6, 128e3, void 0, void 0],
343770
+ ["nemotron-3.5-lightning-free", "Nemotron 3.5 Lightning Free", 262144, 262144, void 0, true],
343771
+ ["nemotron-3.5-super-vl-free", "Nemotron 3.5 Super VL Free", 1048576, 131072, 1048576, void 0],
343763
343772
  ["space-bunny-free", "Space Bunny Free", 1048576, 524288, 524288, void 0]
343764
343773
  ];
343765
343774
  var metadata = Object.fromEntries(rows.map(([id5, name, context, output, input, structured_output, responses]) => [id5, {
@@ -343779,6 +343788,15 @@ var BUILTIN_FREE_MODEL_SNAPSHOT = Object.freeze(parseOpenCodeFreeModelCatalog(JS
343779
343788
  models: metadata
343780
343789
  } })).map((model) => Object.freeze(model)));
343781
343790
  var BUILTIN_FREE_MODEL_IDS = new Set(BUILTIN_FREE_MODEL_SNAPSHOT.map((model) => model.model));
343791
+ var BUILTIN_FREE_LEGACY_MODEL_IDS = /* @__PURE__ */ new Set([
343792
+ "cat-jam-free",
343793
+ "muse-spark-1.3-contributor-free",
343794
+ "step-5-preview-free"
343795
+ ]);
343796
+ var BUILTIN_FREE_RECOGNIZED_MODEL_IDS = /* @__PURE__ */ new Set([
343797
+ ...BUILTIN_FREE_MODEL_IDS,
343798
+ ...BUILTIN_FREE_LEGACY_MODEL_IDS
343799
+ ]);
343782
343800
 
343783
343801
  // packages/orchestrator/dist/inference-provider-error.js
343784
343802
  import { createHash as createHash45 } from "node:crypto";
@@ -343988,13 +344006,13 @@ function packet(value, completeResponse = false) {
343988
344006
  if (delta[field] !== void 0 && delta[field] !== null && typeof delta[field] !== "string")
343989
344007
  throw new OpenAIChatResponseError();
343990
344008
  }
343991
- if (delta.tool_calls !== void 0 && !Array.isArray(delta.tool_calls))
344009
+ if (delta.tool_calls !== void 0 && delta.tool_calls !== null && !Array.isArray(delta.tool_calls))
343992
344010
  throw new OpenAIChatResponseError();
343993
344011
  const calls = Array.isArray(delta.tool_calls) ? delta.tool_calls.map((call2, index) => {
343994
- if (!object5(call2) || call2.function !== void 0 && !object5(call2.function) || call2.id !== void 0 && typeof call2.id !== "string" || call2.index !== void 0 && (!Number.isSafeInteger(call2.index) || Number(call2.index) < 0))
344012
+ if (!object5(call2) || call2.function !== void 0 && !object5(call2.function) || call2.id !== void 0 && !(call2.id === null && !complete) && typeof call2.id !== "string" || call2.index !== void 0 && (!Number.isSafeInteger(call2.index) || Number(call2.index) < 0))
343995
344013
  throw new OpenAIChatResponseError();
343996
344014
  const fn = object5(call2.function) ? call2.function : {};
343997
- if (fn.name !== void 0 && typeof fn.name !== "string")
344015
+ if (fn.name !== void 0 && !(fn.name === null && !complete) && typeof fn.name !== "string")
343998
344016
  throw new OpenAIChatResponseError();
343999
344017
  const args = fn.arguments;
344000
344018
  if (args !== void 0 && typeof args !== "string" && !object5(args))
@@ -344009,11 +344027,13 @@ function packet(value, completeResponse = false) {
344009
344027
  if (typeof call2.id !== "string" || !call2.id.trim() || typeof fn.name !== "string" || !fn.name.trim() || !object5(parsed))
344010
344028
  throw new OpenAIChatResponseError();
344011
344029
  }
344012
- return {
344013
- ...call2,
344014
- index: call2.index ?? index,
344015
- function: { ...fn, ...object5(args) ? { arguments: JSON.stringify(args) } : {} }
344016
- };
344030
+ const normalizedCall = { ...call2 };
344031
+ const normalizedFunction = { ...fn, ...object5(args) ? { arguments: JSON.stringify(args) } : {} };
344032
+ if (!complete && normalizedCall.id === null)
344033
+ delete normalizedCall.id;
344034
+ if (!complete && normalizedFunction.name === null)
344035
+ delete normalizedFunction.name;
344036
+ return { ...normalizedCall, index: call2.index ?? index, function: normalizedFunction };
344017
344037
  }) : void 0;
344018
344038
  return {
344019
344039
  ...choice,
@@ -345833,9 +345853,24 @@ var InvalidInferenceResponse = class extends Error {
345833
345853
  };
345834
345854
  var InvalidDiscoveryMetadata = class extends Error {
345835
345855
  };
345856
+ var CatalogModelUnavailable = class extends Error {
345857
+ };
345836
345858
  var OutputReservationUnavailable = class extends Error {
345837
345859
  };
345860
+ var InferenceRoutePolicyError = class extends Error {
345861
+ failure;
345862
+ code = "inference_route_failed";
345863
+ fatal = true;
345864
+ retryable = false;
345865
+ constructor(failure) {
345866
+ super(`Inference request failed (${failure.category}${failure.status === void 0 ? "" : `; HTTP ${failure.status}`}${failure.validationReason ? `; ${failure.validationReason}` : failure.reason && failure.reason !== "terminal" ? `; ${failure.reason}` : ""}).`);
345867
+ this.failure = failure;
345868
+ this.name = "InferenceRoutePolicyError";
345869
+ }
345870
+ };
345838
345871
  var cooldowns = /* @__PURE__ */ new Map();
345872
+ var successfulRoutes = /* @__PURE__ */ new WeakMap();
345873
+ var SAME_MODEL_ATTEMPTS = 3;
345839
345874
  var requestTransports = /* @__PURE__ */ new WeakMap();
345840
345875
  var responseValidators = /* @__PURE__ */ new WeakMap();
345841
345876
  var nextResponseValidator = 0;
@@ -345908,12 +345943,25 @@ function errorChain(error) {
345908
345943
  chain.push(current2);
345909
345944
  return chain;
345910
345945
  }
345946
+ function explicitModelUnavailable(error) {
345947
+ return errorChain(error).some((value) => {
345948
+ if (value instanceof InferenceProviderError && value.status === 429 && value.reason === "upstream")
345949
+ return true;
345950
+ if (!object12(value) || value.name !== "InferenceHttpError" || ![400, 404, 422, 503].includes(Number(value.status)) || !object12(value.responseJson) || !object12(value.responseJson.error))
345951
+ return false;
345952
+ return ["model_not_found", "model_not_available", "model_unavailable", "unsupported_model"].includes(String(value.responseJson.error.code));
345953
+ });
345954
+ }
345955
+ function sameModelTransient(error, request) {
345956
+ const failure = safeFailure(error, request);
345957
+ return !errorChain(error).some((value) => object12(value) && (value.fatal === true || value.retryable === false) || value instanceof AttemptTimeout && (value.deadlineKind === "remote_aggregate" || value.deadlineKind === "caller_request") || value instanceof SyntaxError || value instanceof InvalidInferenceResponse || value instanceof ExpectedInferenceResponseError || object12(value) && value.name === "OpenAIChatResponseError") && (failure.category === "rate_limit" || failure.category === "timeout" || failure.category === "upstream_unavailable" || failure.category === "empty_response" || failure.category === "transport" && transportFailure(error));
345958
+ }
345911
345959
  function safeFailure(error, request, route, streamFrames) {
345912
345960
  const status2 = errorStatus(error);
345913
345961
  const chain = errorChain(error);
345914
345962
  const upstream429 = status2 === 429 && chain.some((value) => value instanceof InferenceProviderError && value.reason === "upstream");
345915
345963
  const access = chain.find((value) => value instanceof InferenceProviderAccessError);
345916
- const category = access ? "access_denied" : upstream429 ? "upstream_unavailable" : status2 === 429 ? "rate_limit" : status2 === 401 || status2 === 403 ? "authentication" : status2 !== void 0 && status2 >= 400 && status2 < 500 ? "request_rejected" : status2 !== void 0 && status2 >= 500 ? "upstream_unavailable" : chain.some((value) => value instanceof AttemptTimeout || object12(value) && (value.name === "TimeoutError" || value.name === "AbortError" || value.code === "ETIMEDOUT") || value instanceof Error && /^stream timeout: no response or chunk within [0-9]+s$/.test(value.message)) ? "timeout" : chain.some((value) => value instanceof EmptyInferenceResponse) ? "empty_response" : chain.some((value) => value instanceof SyntaxError || value instanceof InvalidInferenceResponse || value instanceof ExpectedInferenceResponseError || object12(value) && value.name === "OpenAIChatResponseError") ? "invalid_response" : "transport";
345964
+ const category = chain.some((value) => value instanceof CatalogModelUnavailable) ? "model_unavailable" : access ? "access_denied" : upstream429 ? "upstream_unavailable" : status2 === 429 ? "rate_limit" : status2 === 401 || status2 === 403 ? "authentication" : status2 !== void 0 && status2 >= 400 && status2 < 500 ? "request_rejected" : status2 !== void 0 && status2 >= 500 ? "upstream_unavailable" : chain.some((value) => value instanceof AttemptTimeout || object12(value) && (value.name === "TimeoutError" || value.name === "AbortError" || value.code === "ETIMEDOUT") || value instanceof Error && /^stream timeout: no response or chunk within [0-9]+s$/.test(value.message)) ? "timeout" : chain.some((value) => value instanceof EmptyInferenceResponse) ? "empty_response" : chain.some((value) => value instanceof SyntaxError || value instanceof InvalidInferenceResponse || value instanceof ExpectedInferenceResponseError || object12(value) && value.name === "OpenAIChatResponseError") ? "invalid_response" : "transport";
345917
345965
  const validation = chain.find((value) => value instanceof ExpectedInferenceResponseError);
345918
345966
  const providerSchemaError = chain.find((value) => value instanceof InferenceProviderError && value.reason === "unsupported_schema");
345919
345967
  const malformedEnvelope = chain.some((value) => object12(value) && value.name === "OpenAIChatResponseError");
@@ -345923,6 +345971,7 @@ function safeFailure(error, request, route, streamFrames) {
345923
345971
  return {
345924
345972
  category,
345925
345973
  ...status2 === void 0 ? {} : { status: status2 },
345974
+ ...chain.some((value) => value instanceof CatalogModelUnavailable) ? { catalogReason: "not_in_active_free_catalog" } : {},
345926
345975
  ...access instanceof InferenceProviderAccessError ? { accessReason: access.reason, responseBodySha256: access.responseBodySha256 } : {},
345927
345976
  ...deadline instanceof AttemptTimeout ? { deadlineKind: deadline.deadlineKind } : providerIdle ? { deadlineKind: "provider_idle" } : {},
345928
345977
  ...streamFrames ? {
@@ -346006,6 +346055,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346006
346055
  policy;
346007
346056
  builtInPrimaryRequest = false;
346008
346057
  builtInAlternativesApproved = false;
346058
+ stickyRouting = false;
346009
346059
  now;
346010
346060
  env;
346011
346061
  lastRoute;
@@ -346038,6 +346088,55 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346038
346088
  capacityPolicyScope() {
346039
346089
  return createHash47("sha256").update(canonicalContract(this.policy)).digest("hex");
346040
346090
  }
346091
+ stickyKey() {
346092
+ return createHash47("sha256").update(canonicalContract({
346093
+ primary: this.capacityPrimaryScope(),
346094
+ policy: this.capacityPolicyScope(),
346095
+ credential: resolveBuiltInFreeApiKey(OPENCODE_INFERENCE_BASE_URL, this.env) ?? "public"
346096
+ })).digest("hex");
346097
+ }
346098
+ rememberRoute(route) {
346099
+ if (!this.stickyRouting && !this.builtInPrimaryRequest)
346100
+ return;
346101
+ const fetcher = this.options.fetch ?? fetch;
346102
+ let entries = successfulRoutes.get(fetcher);
346103
+ if (!entries)
346104
+ successfulRoutes.set(fetcher, entries = /* @__PURE__ */ new Map());
346105
+ if (entries.size >= 64)
346106
+ entries.delete(entries.keys().next().value);
346107
+ const { policyAttempt: _attempt, transientFailures: _failures, retryPendingMs: _retry, schemaRecoveryPending: _schema, modelAccessRestricted: _access, lastAttemptRateLimited: _rate, ...retained } = route;
346108
+ entries.set(this.stickyKey(), retained);
346109
+ }
346110
+ /** One bounded decision for both unary and streaming attempts. No transcript writes. */
346111
+ handleStickyFailure(request, candidate, deadline, error, frames) {
346112
+ let disposition = "surface_error";
346113
+ const category = safeFailure(error, request, candidate, frames).category;
346114
+ let reason = category === "authentication" || category === "access_denied" ? "authentication" : category === "request_rejected" ? "request_rejected" : category === "invalid_response" ? "response_contract" : category === "transport" ? "adapter_or_configuration" : "terminal";
346115
+ let retryDelayMs;
346116
+ if (this.learnNativeSchemaRestriction(request, candidate, error)) {
346117
+ disposition = "repair_same_model";
346118
+ reason = "unsupported_capability";
346119
+ } else if (explicitModelUnavailable(error) || errorChain(error).some((value) => value instanceof InferenceProviderError && value.reason === "unsupported_schema")) {
346120
+ disposition = "rotate_model";
346121
+ reason = explicitModelUnavailable(error) ? "model_unavailable" : "unsupported_capability";
346122
+ const entries = successfulRoutes.get(this.options.fetch ?? fetch), key = this.stickyKey();
346123
+ if (entries?.get(key) && routeKey(entries.get(key)) === routeKey(candidate))
346124
+ entries.delete(key);
346125
+ } else if (sameModelTransient(error, request)) {
346126
+ reason = "transient";
346127
+ candidate.transientFailures = (candidate.transientFailures ?? 0) + 1;
346128
+ const hint = errorChain(error).find((value) => object12(value) && typeof value.retryAfterMs === "number" && Number.isFinite(value.retryAfterMs));
346129
+ retryDelayMs = Math.max(1e3 * 2 ** (candidate.transientFailures - 1), object12(hint) && typeof hint.retryAfterMs === "number" ? Math.max(0, hint.retryAfterMs) : 0);
346130
+ if (candidate.transientFailures < SAME_MODEL_ATTEMPTS && retryDelayMs < deadline - this.now()) {
346131
+ disposition = "retry_same_model";
346132
+ candidate.retryPendingMs = retryDelayMs;
346133
+ }
346134
+ }
346135
+ const detail = { disposition, reason, attempt: candidate.policyAttempt ?? 1, ...retryDelayMs === void 0 ? {} : { retryDelayMs } };
346136
+ this.lifecycle(request, "failed", candidate, error, frames, void 0, detail);
346137
+ if (disposition === "surface_error")
346138
+ throw new InferenceRoutePolicyError({ ...safeFailure(error, request, candidate, frames), ...detail });
346139
+ }
346041
346140
  /** Read-only route discovery; never loads or generates with any local/remote model. */
346042
346141
  async prepareContextCapacity(request, options = {}) {
346043
346142
  if (request.configuredEndpointOnly === true || request.maxTokens <= 0 || !Number.isFinite(request.maxTokens))
@@ -346160,7 +346259,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346160
346259
  return localInferenceBrokerReason(reason);
346161
346260
  }
346162
346261
  builtInScope() {
346163
- if (this.primary.providerId !== "builtin-free" || this.primary.baseUrl !== OPENCODE_INFERENCE_BASE_URL)
346262
+ if (this.primary.providerId !== "builtin-free" || !isOpenCodeInferenceBaseUrl(this.primary.baseUrl))
346164
346263
  throw new Error("Built-in inference requires its exact registered public endpoint.");
346165
346264
  this.reloadPolicy();
346166
346265
  const scope = new _RemoteInferenceFallback(this.primary, this.makeBackend, { ...this.options, policy: this.policy });
@@ -346256,7 +346355,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346256
346355
  request = { ...request };
346257
346356
  requestTransports.set(request, "unary");
346258
346357
  const completedBinding = completedCapacityBinding(request);
346259
- const deadline = Math.min(this.now() + this.policy.totalTimeoutMs, this.preparedCapacity(request)?.deadline ?? Infinity);
346358
+ const deadline = Math.min(this.now() + this.policy.totalTimeoutMs, this.preparedCapacity(request)?.deadline ?? Infinity, request.timeoutMs > 0 ? this.now() + request.timeoutMs : Infinity);
346260
346359
  for await (const candidate of this.retryableCandidates(request, deadline)) {
346261
346360
  if (this.now() >= deadline)
346262
346361
  break;
@@ -346276,6 +346375,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346276
346375
  this.fenceRemoteDeadline(bounded3, deadline);
346277
346376
  return remote.chatCompletion(remoteRequest);
346278
346377
  }, remaining <= this.policy.requestTimeoutMs ? "remote_aggregate" : "remote_attempt");
346378
+ this.fenceRemoteDeadline(request, deadline);
346279
346379
  if (!usableResult(result))
346280
346380
  throw new EmptyInferenceResponse();
346281
346381
  const validation = validateRemoteMessage(result.choices[0]?.message, request);
@@ -346286,6 +346386,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346286
346386
  cooldowns.delete(routeKey(candidate));
346287
346387
  cooldowns.delete(rateLimitKey(candidate));
346288
346388
  cooldowns.delete(contractCooldownKey(candidate, request));
346389
+ this.rememberRoute(candidate);
346289
346390
  this.lifecycle(request, "succeeded", candidate, void 0, void 0, completedBinding);
346290
346391
  return this.scrubber(candidate)(result);
346291
346392
  } catch (error) {
@@ -346294,6 +346395,10 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346294
346395
  this.discovery(request, candidate, { stage: "eligibility", outcome: "no_eligible_models", modelCount: 0 });
346295
346396
  continue;
346296
346397
  }
346398
+ if (this.stickyRouting || this.builtInPrimaryRequest) {
346399
+ this.handleStickyFailure(request, candidate, deadline, error);
346400
+ continue;
346401
+ }
346297
346402
  this.lifecycle(request, "failed", candidate, error);
346298
346403
  if (this.restrictedModel(candidate, error))
346299
346404
  continue;
@@ -346373,7 +346478,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346373
346478
  requestTransports.set(request, "stream");
346374
346479
  const completedBinding = completedCapacityBinding(request);
346375
346480
  let emitted = false;
346376
- const deadline = Math.min(this.now() + this.policy.totalTimeoutMs, this.preparedCapacity(request)?.deadline ?? Infinity);
346481
+ const deadline = Math.min(this.now() + this.policy.totalTimeoutMs, this.preparedCapacity(request)?.deadline ?? Infinity, request.timeoutMs > 0 ? this.now() + request.timeoutMs : Infinity);
346377
346482
  for await (const candidate of this.retryableCandidates(request, deadline)) {
346378
346483
  if (this.now() >= deadline)
346379
346484
  break;
@@ -346411,9 +346516,11 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346411
346516
  for await (const chunk of this.scrubStream(track(), candidate)) {
346412
346517
  yield chunk;
346413
346518
  }
346519
+ this.fenceRemoteDeadline(request, deadline);
346414
346520
  cooldowns.delete(routeKey(candidate));
346415
346521
  cooldowns.delete(rateLimitKey(candidate));
346416
346522
  cooldowns.delete(contractCooldownKey(candidate, request));
346523
+ this.rememberRoute(candidate);
346417
346524
  this.lifecycle(request, "succeeded", candidate, void 0, void 0, completedBinding);
346418
346525
  return;
346419
346526
  } catch (error) {
@@ -346422,9 +346529,15 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346422
346529
  this.discovery(request, candidate, { stage: "eligibility", outcome: "no_eligible_models", modelCount: 0 });
346423
346530
  continue;
346424
346531
  }
346425
- this.lifecycle(request, "failed", candidate, error, frames);
346426
- if (emitted)
346532
+ if (emitted) {
346533
+ this.lifecycle(request, "failed", candidate, error, frames);
346427
346534
  throw new StreamInterruptedError(safeFailure(error, request, candidate, frames));
346535
+ }
346536
+ if (this.stickyRouting || this.builtInPrimaryRequest) {
346537
+ this.handleStickyFailure(request, candidate, deadline, error, frames);
346538
+ continue;
346539
+ }
346540
+ this.lifecycle(request, "failed", candidate, error, frames);
346428
346541
  if (this.restrictedModel(candidate, error))
346429
346542
  continue;
346430
346543
  if (errorChain(error).some((value) => value instanceof AttemptTimeout && value.deadlineKind === "remote_aggregate"))
@@ -346687,7 +346800,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346687
346800
  }
346688
346801
  this.lifecycle(request, "selected", route);
346689
346802
  }
346690
- lifecycle(request, phase, route, error, frames, completedBinding) {
346803
+ lifecycle(request, phase, route, error, frames, completedBinding, decision2) {
346691
346804
  this.fence(request);
346692
346805
  if (!request.onInferenceRouteLifecycle)
346693
346806
  return;
@@ -346707,6 +346820,7 @@ var RemoteInferenceFallback = class _RemoteInferenceFallback {
346707
346820
  } } : {},
346708
346821
  ...phase === "failed" ? { failure: {
346709
346822
  ...safeFailure(error, request, route, frames),
346823
+ ...decision2,
346710
346824
  ...!route && this.localBrokerReason(error) ? { brokerReason: this.localBrokerReason(error) } : {}
346711
346825
  } } : {}
346712
346826
  };
@@ -347074,6 +347188,14 @@ ${line}`).join("");
347074
347188
  };
347075
347189
  for await (const candidate of candidates()) {
347076
347190
  const key = routeKey(candidate);
347191
+ if (candidate.baseUrl === OPENCODE_INFERENCE_BASE_URL && candidate.keyless?.clientIdentity === "opencode")
347192
+ this.stickyRouting = true;
347193
+ if (this.stickyRouting || this.builtInPrimaryRequest) {
347194
+ if (this.now() >= deadline)
347195
+ return;
347196
+ yield* this.stickyAttempts(request, candidate, deadline);
347197
+ continue;
347198
+ }
347077
347199
  if (!priority.has(key))
347078
347200
  priority.set(key, priority.size);
347079
347201
  if ((routeCooldown(candidate, request)?.until ?? 0) > this.now()) {
@@ -347137,7 +347259,62 @@ ${line}`).join("");
347137
347259
  defer(candidate);
347138
347260
  }
347139
347261
  }
347262
+ async *stickyAttempts(request, candidate, deadline) {
347263
+ let schemaRetries = 0;
347264
+ while (this.now() < deadline) {
347265
+ this.fence(request);
347266
+ candidate.policyAttempt = (candidate.policyAttempt ?? 0) + 1;
347267
+ yield candidate;
347268
+ if (candidate.schemaRecoveryPending && schemaRetries < SUPPORTED_PROVIDER_SCHEMA_ADAPTATIONS.length) {
347269
+ candidate.schemaRecoveryPending = false;
347270
+ schemaRetries++;
347271
+ continue;
347272
+ }
347273
+ if (candidate.retryPendingMs === void 0)
347274
+ return;
347275
+ const delay2 = candidate.retryPendingMs;
347276
+ candidate.retryPendingMs = void 0;
347277
+ await this.waitForRetry(request, delay2);
347278
+ this.fence(request);
347279
+ if (this.now() >= deadline)
347280
+ throw new InferenceRoutePolicyError({ category: "timeout", deadlineKind: "remote_aggregate", disposition: "surface_error", reason: "transient", attempt: candidate.policyAttempt });
347281
+ }
347282
+ }
347283
+ async waitForRetry(request, delay2) {
347284
+ let timer;
347285
+ try {
347286
+ const pause = new Promise((resolve40) => {
347287
+ timer = setTimeout(resolve40, delay2);
347288
+ });
347289
+ await (request.signal ? this.abortable(pause, request.signal) : pause);
347290
+ } finally {
347291
+ clearTimeout(timer);
347292
+ }
347293
+ }
347140
347294
  async *candidates(request, deadline, includeCooling = false) {
347295
+ const sticky = successfulRoutes.get(this.options.fetch ?? fetch)?.get(this.stickyKey());
347296
+ const eligible = sticky && this.compatible(request, sticky, true) ? sticky : void 0;
347297
+ const pending = [];
347298
+ let matched = !eligible;
347299
+ for await (const candidate of this.catalogCandidates(request, deadline, includeCooling)) {
347300
+ if (!matched && routeKey(candidate) !== routeKey(eligible)) {
347301
+ pending.push(candidate);
347302
+ continue;
347303
+ }
347304
+ if (!matched) {
347305
+ this.stickyRouting = true;
347306
+ matched = true;
347307
+ yield candidate;
347308
+ for (const prior of pending)
347309
+ yield prior;
347310
+ pending.length = 0;
347311
+ } else
347312
+ yield candidate;
347313
+ }
347314
+ for (const candidate of pending)
347315
+ yield candidate;
347316
+ }
347317
+ async *catalogCandidates(request, deadline, includeCooling = false) {
347141
347318
  const seen = /* @__PURE__ */ new Set();
347142
347319
  const configured = [];
347143
347320
  for (const profile3 of this.policy.providers.slice(0, MAX_CONFIGURED_PROVIDERS)) {
@@ -347312,9 +347489,23 @@ ${line}`).join("");
347312
347489
  const zeroPrice = (value) => (typeof value === "number" || typeof value === "string" && value.trim().length > 0) && Number.isFinite(Number(value)) && Number(value) === 0;
347313
347490
  const models = raw.data.filter((model) => chatCatalogModel(model, anonymousTier) && (!kiloCatalog || object12(model.pricing) && zeroPrice(model.pricing.prompt) && zeroPrice(model.pricing.completion) && Object.values(model.pricing).every(zeroPrice)));
347314
347491
  const unique4 = [...new Map(models.map((model) => [String(model.id), model])).values()];
347315
- const preferredModel = this.builtInPrimaryRequest && openCodeCatalog ? this.primary.model : route.model;
347492
+ const remembered = successfulRoutes.get(fetcher)?.get(this.stickyKey());
347493
+ const rememberedHere = remembered && remembered.baseUrl === route.baseUrl && this.compatible(request, remembered, true);
347494
+ const preferredModel = rememberedHere ? remembered.model : this.builtInPrimaryRequest && openCodeCatalog ? this.primary.model : route.model;
347316
347495
  const preferred = unique4.find((model) => model.id === preferredModel);
347317
- const ordered = unique4.sort((a, b) => this.builtInPrimaryRequest && openCodeCatalog && a.id === preferredModel !== (b.id === preferredModel) ? a.id === preferredModel ? -1 : 1 : compareFallbackCatalogModels(a, b, route.model));
347496
+ if (openCodeCatalog && !preferred && (rememberedHere || this.builtInPrimaryRequest) && cache3.get(modelsUrl)?.source !== "bundled") {
347497
+ const removed = { ...route, model: preferredModel };
347498
+ this.discovery(request, removed, {
347499
+ stage: "eligibility",
347500
+ outcome: "unavailable",
347501
+ modelCount: 0,
347502
+ reason: "selected_model_not_in_active_free_catalog"
347503
+ });
347504
+ this.lifecycle(request, "failed", removed, new CatalogModelUnavailable(), void 0, void 0, { disposition: "rotate_model", reason: "model_unavailable", attempt: 0 });
347505
+ if (rememberedHere)
347506
+ successfulRoutes.get(fetcher)?.delete(this.stickyKey());
347507
+ }
347508
+ const ordered = unique4.sort((a, b) => (rememberedHere || this.builtInPrimaryRequest) && openCodeCatalog && a.id === preferredModel !== (b.id === preferredModel) ? a.id === preferredModel ? -1 : 1 : compareFallbackCatalogModels(a, b, route.model));
347318
347509
  const compatible = [];
347319
347510
  const modelLimit = openCodeCatalog ? MAX_OPENCODE_CATALOG_MODELS : MAX_MODELS_PER_PROVIDER;
347320
347511
  for (const selected of ordered) {
@@ -352995,11 +353186,6 @@ var StructuredMemoryExtractionQueue = class {
352995
353186
  }
352996
353187
  };
352997
353188
 
352998
- // packages/orchestrator/dist/inference-provider-presentation.js
352999
- function inferenceProviderDisplayName(providerId) {
353000
- return providerId === "opencode" || providerId === "builtin-free" ? "built-in free" : providerId ?? "remote";
353001
- }
353002
-
353003
353189
  // packages/orchestrator/dist/native-ollama-tool-calls.js
353004
353190
  function object13(value) {
353005
353191
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -393265,12 +393451,6 @@ ${read.content}`;
393265
393451
  onInferenceRoute: (route) => {
393266
393452
  assertCurrent();
393267
393453
  outbound.onInferenceRoute?.(route);
393268
- this.emit({
393269
- type: "status",
393270
- content: `Local inference unavailable; using ${inferenceProviderDisplayName(route.providerId)} (${route.model}).`,
393271
- turn: operation.turn,
393272
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
393273
- });
393274
393454
  },
393275
393455
  onInferenceRouteLifecycle: (receipt) => {
393276
393456
  assertCurrent();
@@ -427998,7 +428178,7 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
427998
428178
  this._inferenceFallbackApprovalHandler = handler;
427999
428179
  }
428000
428180
  isBuiltInPrimary() {
428001
- return this._provider.providerId === "builtin-free" && this._provider.urls.chat === `${OPENCODE_INFERENCE_BASE_URL}/chat/completions`;
428181
+ return this._provider.providerId === "builtin-free" && isOpenCodeInferenceBaseUrl(this._provider.urls.chat?.replace(/\/chat\/completions$/, ""));
428002
428182
  }
428003
428183
  remoteFallback() {
428004
428184
  return this._remoteFallback ??= new RemoteInferenceFallback({
@@ -428378,7 +428558,7 @@ var OllamaAgenticBackend = class _OllamaAgenticBackend {
428378
428558
  };
428379
428559
  }
428380
428560
  usesOpenCodeCompatibility(request) {
428381
- return request.remoteClientIdentity === "opencode" && request.configuredEndpointOnly === true && this._provider.protocol === "openai-chat" && this._provider.urls.chat === `${OPENCODE_INFERENCE_BASE_URL}/chat/completions`;
428561
+ return request.remoteClientIdentity === "opencode" && request.configuredEndpointOnly === true && this._provider.protocol === "openai-chat" && isOpenCodeInferenceBaseUrl(this._provider.urls.chat?.replace(/\/chat\/completions$/, ""));
428382
428562
  }
428383
428563
  usesOpenCodeResponses(request) {
428384
428564
  return this.usesOpenCodeCompatibility(request) && request.remoteOpenCodeApiShape === "responses";