@nemesis-oss/ollama-sdk 1.18.0 → 1.19.1
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/CHANGELOG.md +45 -0
- package/README.md +9 -9
- package/dist/{anthropic-CvGVSoVP.d.ts → anthropic-Bf16hGLL.d.cts} +3 -3
- package/dist/{anthropic-BvHOsidk.d.cts → anthropic-BmFk4Pjq.d.ts} +3 -3
- package/dist/{compose-CeFbHJeO.d.ts → compose-75UFDzOO.d.ts} +1 -1
- package/dist/{compose-DFkmtUOP.d.cts → compose-C4QxEZOS.d.cts} +1 -1
- package/dist/generated-api.cjs +5 -3
- package/dist/generated-api.cjs.map +1 -1
- package/dist/generated-api.d.cts +9 -9
- package/dist/generated-api.d.ts +9 -9
- package/dist/generated-api.js +5 -3
- package/dist/generated-api.js.map +1 -1
- package/dist/generated-runtime.cjs +22 -4
- package/dist/generated-runtime.cjs.map +1 -1
- package/dist/generated-runtime.d.cts +2 -2
- package/dist/generated-runtime.d.ts +2 -2
- package/dist/generated-runtime.js +22 -4
- package/dist/generated-runtime.js.map +1 -1
- package/dist/index.cjs +163 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -66
- package/dist/index.d.ts +145 -66
- package/dist/index.js +162 -29
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools.json +3 -3
- package/dist/mcp-generated.cjs +5 -3
- package/dist/mcp-generated.cjs.map +1 -1
- package/dist/mcp-generated.d.cts +2 -2
- package/dist/mcp-generated.d.ts +2 -2
- package/dist/mcp-generated.js +5 -3
- package/dist/mcp-generated.js.map +1 -1
- package/dist/{runtime-CdZP-N7j.d.cts → runtime-CjCriL5A.d.cts} +56 -5
- package/dist/{runtime-CFuv7Ifh.d.ts → runtime-EwyUaNnZ.d.ts} +56 -5
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.d.cts +3 -3
- package/dist/skills.d.ts +3 -3
- package/dist/skills.js.map +1 -1
- package/dist/{types-DbPnfVh-.d.cts → types-Y3u0FtdN.d.cts} +10 -0
- package/dist/{types-DbPnfVh-.d.ts → types-Y3u0FtdN.d.ts} +10 -0
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -193,6 +193,11 @@ var OllamaAuthError = class extends OllamaClientError {
|
|
|
193
193
|
super(message, { ...options, code: "auth_error", retryable: false });
|
|
194
194
|
}
|
|
195
195
|
};
|
|
196
|
+
var OllamaPaymentRequiredError = class extends OllamaClientError {
|
|
197
|
+
constructor(message, options) {
|
|
198
|
+
super(message, { ...options, code: "payment_required", retryable: false, status: 402 });
|
|
199
|
+
}
|
|
200
|
+
};
|
|
196
201
|
var OllamaNotFoundError = class extends OllamaClientError {
|
|
197
202
|
constructor(message, options) {
|
|
198
203
|
super(message, { ...options, code: "not_found", retryable: false });
|
|
@@ -423,15 +428,56 @@ function isNetworkLevelError(error) {
|
|
|
423
428
|
}
|
|
424
429
|
return false;
|
|
425
430
|
}
|
|
431
|
+
function lookupHeader(headers, name) {
|
|
432
|
+
if (headers === void 0) {
|
|
433
|
+
return void 0;
|
|
434
|
+
}
|
|
435
|
+
const needle = name.toLowerCase();
|
|
436
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
437
|
+
if (key.toLowerCase() === needle) {
|
|
438
|
+
return value;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return void 0;
|
|
442
|
+
}
|
|
443
|
+
var HTTP_DATE_PATTERN = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/;
|
|
444
|
+
function parseRetryAfterMs(headerValue, now = Date.now()) {
|
|
445
|
+
if (headerValue === void 0) {
|
|
446
|
+
return void 0;
|
|
447
|
+
}
|
|
448
|
+
const trimmed = headerValue.trim();
|
|
449
|
+
if (trimmed === "") {
|
|
450
|
+
return void 0;
|
|
451
|
+
}
|
|
452
|
+
if (/^\d+$/.test(trimmed)) {
|
|
453
|
+
const seconds = Number(trimmed);
|
|
454
|
+
if (!Number.isSafeInteger(seconds)) {
|
|
455
|
+
return void 0;
|
|
456
|
+
}
|
|
457
|
+
return seconds * 1e3;
|
|
458
|
+
}
|
|
459
|
+
if (!HTTP_DATE_PATTERN.test(trimmed)) {
|
|
460
|
+
return void 0;
|
|
461
|
+
}
|
|
462
|
+
const instant = Date.parse(trimmed);
|
|
463
|
+
if (Number.isNaN(instant)) {
|
|
464
|
+
return void 0;
|
|
465
|
+
}
|
|
466
|
+
return Math.max(0, instant - now);
|
|
467
|
+
}
|
|
426
468
|
function statusToError(status, message, options) {
|
|
427
469
|
if (status === 401 || status === 403) {
|
|
428
470
|
return new OllamaAuthError(message, { ...options, status });
|
|
429
471
|
}
|
|
472
|
+
if (status === 402) {
|
|
473
|
+
return new OllamaPaymentRequiredError(message, options);
|
|
474
|
+
}
|
|
430
475
|
if (status === 404) {
|
|
431
476
|
return new OllamaNotFoundError(message, { ...options, status });
|
|
432
477
|
}
|
|
433
478
|
if (status === 429) {
|
|
434
|
-
|
|
479
|
+
const retryAfterMs = parseRetryAfterMs(lookupHeader(options.response?.headers, "retry-after"));
|
|
480
|
+
return new OllamaRateLimitError(message, { ...options, status, retryAfterMs });
|
|
435
481
|
}
|
|
436
482
|
if (status === 502) {
|
|
437
483
|
return new OllamaBadGatewayError(message, { ...options });
|
|
@@ -1134,6 +1180,21 @@ function sameHeaders(actual, expected) {
|
|
|
1134
1180
|
const expectedKeys = Object.keys(expectedEntries);
|
|
1135
1181
|
return actualKeys.length === expectedKeys.length && expectedKeys.every((key) => actualEntries[key] === expectedEntries[key]);
|
|
1136
1182
|
}
|
|
1183
|
+
function retryAfterHeaderFrom(response) {
|
|
1184
|
+
try {
|
|
1185
|
+
const headers = response?.headers;
|
|
1186
|
+
if (headers === null || headers === void 0 || typeof headers.get !== "function") {
|
|
1187
|
+
return void 0;
|
|
1188
|
+
}
|
|
1189
|
+
const value = headers.get("retry-after");
|
|
1190
|
+
if (value === null || value === "") {
|
|
1191
|
+
return void 0;
|
|
1192
|
+
}
|
|
1193
|
+
return { "retry-after": value };
|
|
1194
|
+
} catch {
|
|
1195
|
+
return void 0;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1137
1198
|
var HttpClient = class {
|
|
1138
1199
|
baseUrl;
|
|
1139
1200
|
apiKey;
|
|
@@ -1201,7 +1262,12 @@ var HttpClient = class {
|
|
|
1201
1262
|
durationMs: Date.now() - startedAt,
|
|
1202
1263
|
error: mapError(new Error(`HTTP ${response2.status}`), {
|
|
1203
1264
|
request: { method: request.method, url: request.url },
|
|
1204
|
-
|
|
1265
|
+
// Mirrors the middleware path, which reports context.headers:
|
|
1266
|
+
// a 429 lifecycle event carries the server's Retry-After.
|
|
1267
|
+
response: {
|
|
1268
|
+
status: response2.status,
|
|
1269
|
+
headers: retryAfterHeaderFrom(response2)
|
|
1270
|
+
}
|
|
1205
1271
|
}),
|
|
1206
1272
|
timestamp: Date.now()
|
|
1207
1273
|
});
|
|
@@ -1307,7 +1373,11 @@ var HttpClient = class {
|
|
|
1307
1373
|
const message = typeof errorBody === "object" && errorBody !== null && "error" in errorBody ? String(errorBody.error) : `HTTP ${response.status} ${response.statusText}`;
|
|
1308
1374
|
throw mapError(new Error(message), {
|
|
1309
1375
|
request: { method, url },
|
|
1310
|
-
response: {
|
|
1376
|
+
response: {
|
|
1377
|
+
status: response.status,
|
|
1378
|
+
headers: retryAfterHeaderFrom(response),
|
|
1379
|
+
body: errorBody
|
|
1380
|
+
}
|
|
1311
1381
|
});
|
|
1312
1382
|
}
|
|
1313
1383
|
if (options.method === "HEAD" || response.status === 204) {
|
|
@@ -1372,7 +1442,11 @@ var HttpClient = class {
|
|
|
1372
1442
|
const errorText = await response.text();
|
|
1373
1443
|
throw mapError(new Error(errorText || `HTTP ${response.status}`), {
|
|
1374
1444
|
request: { method, url },
|
|
1375
|
-
response: {
|
|
1445
|
+
response: {
|
|
1446
|
+
status: response.status,
|
|
1447
|
+
headers: retryAfterHeaderFrom(response),
|
|
1448
|
+
body: errorText
|
|
1449
|
+
}
|
|
1376
1450
|
});
|
|
1377
1451
|
}
|
|
1378
1452
|
if (!response.body) {
|
|
@@ -1436,7 +1510,11 @@ var HttpClient = class {
|
|
|
1436
1510
|
const errorText = await response.text();
|
|
1437
1511
|
throw mapError(new Error(errorText || `HTTP ${response.status}`), {
|
|
1438
1512
|
request: { method, url },
|
|
1439
|
-
response: {
|
|
1513
|
+
response: {
|
|
1514
|
+
status: response.status,
|
|
1515
|
+
headers: retryAfterHeaderFrom(response),
|
|
1516
|
+
body: errorText
|
|
1517
|
+
}
|
|
1440
1518
|
});
|
|
1441
1519
|
}
|
|
1442
1520
|
if (!response.body) {
|
|
@@ -1742,7 +1820,7 @@ function contextWarningMessage(check2, kind) {
|
|
|
1742
1820
|
if (check2.windowSource === "client-default") {
|
|
1743
1821
|
return `${where}: estimated prompt size ${estimate} is close to or beyond the client's \`defaultContextLength\` (${check2.effectiveContextLength}, injected as \`num_ctx\`). The server will likely silently truncate the top of the conversation \u2014 the model loses earlier turns with no error. Raise \`defaultContextLength\`, set \`options.num_ctx\` per request, or shorten the conversation.${suggestion} Estimates are heuristic (\xB120\u201330%); see \`estimateTokens\`.`;
|
|
1744
1822
|
}
|
|
1745
|
-
return `${where}: estimated prompt size ${estimate} outright exceeds
|
|
1823
|
+
return `${where}: estimated prompt size ${estimate} outright exceeds the worst-case floor for the unset-\`num_ctx\` window (${OLLAMA_FALLBACK_CONTEXT_LENGTH} tokens \u2014 current daemons default higher, tiered by VRAM: 4096 / 32768 / 262144; \`OLLAMA_CONTEXT_LENGTH\` can override either way). If your daemon's effective window is that small, the server will silently truncate the top of the conversation \u2014 the model loses earlier turns with no error. Set \`options.num_ctx\` (or the client's \`defaultContextLength\`) to an explicit window \u2014 or discover the real one via \`client.models.getContextLength()\` \u2014 to make truncation visible and controllable.${suggestion} Estimates are heuristic (\xB120\u201330%); see \`estimateTokens\`.`;
|
|
1746
1824
|
}
|
|
1747
1825
|
|
|
1748
1826
|
// src/context-discovery.ts
|
|
@@ -2470,6 +2548,12 @@ function sleep(ms, signal) {
|
|
|
2470
2548
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
2471
2549
|
});
|
|
2472
2550
|
}
|
|
2551
|
+
function retryDelayMs(error, attempt, backoff) {
|
|
2552
|
+
if (error instanceof OllamaRateLimitError && error.retryAfterMs !== void 0) {
|
|
2553
|
+
return error.retryAfterMs;
|
|
2554
|
+
}
|
|
2555
|
+
return calculateBackoff(attempt, backoff);
|
|
2556
|
+
}
|
|
2473
2557
|
async function withRetry(operation, config = DEFAULT_RETRY_CONFIG, signal) {
|
|
2474
2558
|
let attempt = 0;
|
|
2475
2559
|
while (true) {
|
|
@@ -2481,7 +2565,7 @@ async function withRetry(operation, config = DEFAULT_RETRY_CONFIG, signal) {
|
|
|
2481
2565
|
if (attempt >= config.maxRetries || !shouldRetry(error, attempt)) {
|
|
2482
2566
|
throw error;
|
|
2483
2567
|
}
|
|
2484
|
-
const delayMs =
|
|
2568
|
+
const delayMs = retryDelayMs(error, attempt, config.backoff);
|
|
2485
2569
|
config.onRetry?.(error, attempt, delayMs);
|
|
2486
2570
|
await sleep(delayMs, signal);
|
|
2487
2571
|
attempt += 1;
|
|
@@ -2650,7 +2734,8 @@ var ModelsClient = class {
|
|
|
2650
2734
|
}
|
|
2651
2735
|
/**
|
|
2652
2736
|
* Discovers the model's real context window from the server — no more
|
|
2653
|
-
*
|
|
2737
|
+
* default-window guesswork (current daemons tier the unset-`num_ctx`
|
|
2738
|
+
* default by VRAM: 4k / 32k / 256k). Consults, in precedence order:
|
|
2654
2739
|
*
|
|
2655
2740
|
* 1. `GET /api/ps` — the window the **running instance actually
|
|
2656
2741
|
* allocated** (exact, reflects the Modelfile `num_ctx` default and
|
|
@@ -2662,7 +2747,7 @@ var ModelsClient = class {
|
|
|
2662
2747
|
* 3. `POST /api/show` `model_info["<arch>.context_length"]` — the
|
|
2663
2748
|
* model's **native GGUF maximum** (a ceiling to raise `num_ctx`
|
|
2664
2749
|
* toward, not the allocated window).
|
|
2665
|
-
* 4. Fallback —
|
|
2750
|
+
* 4. Fallback — the 2048 worst-case floor for the unset-`num_ctx` window.
|
|
2666
2751
|
*
|
|
2667
2752
|
* The result carries every signal it found, so `nativeContextLength:
|
|
2668
2753
|
* 131072` vs `contextLength: 4096` (a 32× gap seen in the official API
|
|
@@ -4425,14 +4510,25 @@ var OllamaRuntime = class {
|
|
|
4425
4510
|
const hasImages = bodyHasImages(body);
|
|
4426
4511
|
const maxBytesWithImages = req.operation.constraints?.maxRequestBytesWithImages;
|
|
4427
4512
|
const maxBytesBase = req.operation.constraints?.maxRequestBytes;
|
|
4428
|
-
const
|
|
4429
|
-
if (
|
|
4513
|
+
const textAndSchemaBytes = hasImages ? serializeWithoutImages(body).byteLength : serialized.byteLength;
|
|
4514
|
+
if (maxBytesBase !== void 0 && textAndSchemaBytes > maxBytesBase) {
|
|
4515
|
+
throw new OllamaRequestTooLargeError(
|
|
4516
|
+
`Operation ${req.operation.operationId} (${req.operation.method} ${req.operation.path}) text and schema (images excluded) is ${textAndSchemaBytes} bytes, exceeding the contract limit of ${maxBytesBase} bytes.`,
|
|
4517
|
+
{
|
|
4518
|
+
operationId: req.operation.operationId,
|
|
4519
|
+
actualBytes: textAndSchemaBytes,
|
|
4520
|
+
maxBytes: maxBytesBase,
|
|
4521
|
+
request: { method: req.operation.method, url: req.operation.path }
|
|
4522
|
+
}
|
|
4523
|
+
);
|
|
4524
|
+
}
|
|
4525
|
+
if (maxBytesWithImages !== void 0 && serialized.byteLength > maxBytesWithImages) {
|
|
4430
4526
|
throw new OllamaRequestTooLargeError(
|
|
4431
|
-
`Operation ${req.operation.operationId} (${req.operation.method} ${req.operation.path}) request body is ${serialized.byteLength} bytes, exceeding the contract limit of ${
|
|
4527
|
+
`Operation ${req.operation.operationId} (${req.operation.method} ${req.operation.path}) request body is ${serialized.byteLength} bytes, exceeding the contract limit of ${maxBytesWithImages} bytes (whole request, images included).`,
|
|
4432
4528
|
{
|
|
4433
4529
|
operationId: req.operation.operationId,
|
|
4434
4530
|
actualBytes: serialized.byteLength,
|
|
4435
|
-
maxBytes:
|
|
4531
|
+
maxBytes: maxBytesWithImages,
|
|
4436
4532
|
request: { method: req.operation.method, url: req.operation.path }
|
|
4437
4533
|
}
|
|
4438
4534
|
);
|
|
@@ -4574,6 +4670,13 @@ function bodyHasImages(body) {
|
|
|
4574
4670
|
const images = obj.images;
|
|
4575
4671
|
return Array.isArray(images) && images.length > 0;
|
|
4576
4672
|
}
|
|
4673
|
+
function serializeWithoutImages(body) {
|
|
4674
|
+
if (typeof body === "object" && body !== null && !Array.isArray(body)) {
|
|
4675
|
+
const { images: _images, ...rest } = body;
|
|
4676
|
+
return serializeForByteCount(rest);
|
|
4677
|
+
}
|
|
4678
|
+
return serializeForByteCount(body);
|
|
4679
|
+
}
|
|
4577
4680
|
function resolvePathParams(pathTemplate, pathParams) {
|
|
4578
4681
|
if (!pathTemplate.includes("{")) return pathTemplate;
|
|
4579
4682
|
const params = pathParams ?? {};
|
|
@@ -5326,7 +5429,7 @@ var systemOneOp = {
|
|
|
5326
5429
|
path: "/v1/systemone",
|
|
5327
5430
|
request: { $ref: "#/schemas/SystemOneRequest" },
|
|
5328
5431
|
response: { $ref: "#/schemas/SystemOneResponse" },
|
|
5329
|
-
environment: { local: true, cloud:
|
|
5432
|
+
environment: { local: true, cloud: true },
|
|
5330
5433
|
transport: { mode: "json", streaming: false },
|
|
5331
5434
|
capabilities: {
|
|
5332
5435
|
thinking: "unsupported",
|
|
@@ -5344,8 +5447,10 @@ var systemOneOp = {
|
|
|
5344
5447
|
status: { documented: true, experimental: true },
|
|
5345
5448
|
domain: "native",
|
|
5346
5449
|
notes: [
|
|
5347
|
-
"Local
|
|
5348
|
-
"64 KiB
|
|
5450
|
+
"Local and cloud: model accepts cloud models (e.g. clef:cloud); cloud models require Ollama >= 0.40.5 or the hosted https://ollama.com endpoint.",
|
|
5451
|
+
"Local dual cap: text and schema (excluding images) within 64 KiB AND the whole request within 32 MiB, including base64 and JSON overhead.",
|
|
5452
|
+
"Cloud requests: paid plan or usage credits required; up to 64 questions named with up to 100 ASCII letters, digits, `_`, `.`, or `-`; up to 4 images of at most 4 MiB and 16 megapixels each (8 MiB total); requests within 13 MiB; input within the model's 65,536-token context window.",
|
|
5453
|
+
"401 when a cloud model is requested without signing in or with an invalid API key (through a local server the response includes a signin_url); 402 when the cloud model is not included in the Free plan or a payment fails.",
|
|
5349
5454
|
"No tools, no generation controls (temperature, top_p, etc.).",
|
|
5350
5455
|
"Vision is model-dependent: images are accepted by vision-weighted models (Clef/Clef Flash) but not by text-only models.",
|
|
5351
5456
|
"Experimental: behavioral surface may change between Ollama releases."
|
|
@@ -6301,11 +6406,15 @@ var OllamaClient = class _OllamaClient {
|
|
|
6301
6406
|
* 1–64 typed questions (choice, noul, or score) against a provided state
|
|
6302
6407
|
* and returns typed answers with probabilities and confidence.
|
|
6303
6408
|
*
|
|
6304
|
-
* Local
|
|
6305
|
-
*
|
|
6306
|
-
*
|
|
6307
|
-
*
|
|
6308
|
-
*
|
|
6409
|
+
* Local and cloud (since the 2026-10-16 upstream System One cloud
|
|
6410
|
+
* launch): `model` also accepts cloud models such as `clef:cloud` —
|
|
6411
|
+
* cloud models require Ollama >= 0.40.5 or the hosted
|
|
6412
|
+
* `https://ollama.com` endpoint. Requires Ollama >= 0.35.0 locally.
|
|
6413
|
+
* The runtime enforces the version constraint automatically (lazily
|
|
6414
|
+
* fetching `/api/version` when `enforceVersion` is `'auto'` or
|
|
6415
|
+
* `'strict'`). Request size is checked client-side as a dual cap:
|
|
6416
|
+
* text and schema (images excluded) within 64 KiB AND the whole
|
|
6417
|
+
* request within 32 MiB.
|
|
6309
6418
|
*
|
|
6310
6419
|
* The generic `Q` parameter captures the caller's question map at
|
|
6311
6420
|
* compile time, giving key-safe answer access:
|
|
@@ -6339,7 +6448,9 @@ var OllamaClient = class _OllamaClient {
|
|
|
6339
6448
|
* through a local server. Requires an Ollama account API key: pass `apiKey` to the
|
|
6340
6449
|
* client constructor or set `OLLAMA_API_KEY`. Applies the same default `timeoutMs` and
|
|
6341
6450
|
* retry policy as inference calls, but never cross-endpoint-fails-over — there is only
|
|
6342
|
-
* ever the one cloud endpoint to call.
|
|
6451
|
+
* ever the one cloud endpoint to call. If the service answers 429 with a `Retry-After`
|
|
6452
|
+
* header, the transport parses it into `OllamaRateLimitError.retryAfterMs` and the
|
|
6453
|
+
* retry loop sleeps exactly that long instead of jittered backoff (see ADR 0035).
|
|
6343
6454
|
*/
|
|
6344
6455
|
async webSearch(req) {
|
|
6345
6456
|
const { count, max_results, ...rest } = req;
|
|
@@ -6370,8 +6481,11 @@ var OllamaClient = class _OllamaClient {
|
|
|
6370
6481
|
* web search, and web fetch, bucketed by hour (`range: '24h'`) or day (`'7d'`/`'30d'`).
|
|
6371
6482
|
*
|
|
6372
6483
|
* See {@link OllamaClient.webSearch} for the cloud-endpoint/auth/timeout/retry
|
|
6373
|
-
* behavior, which applies identically here.
|
|
6374
|
-
* endpoint
|
|
6484
|
+
* behavior, which applies identically here. The pinned contract documents this
|
|
6485
|
+
* endpoint's 429 with a `Retry-After` header ("Seconds to wait before retrying"),
|
|
6486
|
+
* which the SDK parses into `OllamaRateLimitError.retryAfterMs` and honors verbatim
|
|
6487
|
+
* when retrying. Query parameters mirror the official endpoint: `range`
|
|
6488
|
+
* (`'24h' | '7d' | '30d'`, server default `'7d'`) and `scope`
|
|
6375
6489
|
* (`'self' | 'team'`, server default `'self'`; team scope requires a team admin).
|
|
6376
6490
|
* Omitted options are left unset so the server applies its own defaults.
|
|
6377
6491
|
*
|
|
@@ -6404,7 +6518,9 @@ var OllamaClient = class _OllamaClient {
|
|
|
6404
6518
|
* object (`balance_usd`/`allowance_usd`/`period`) or, on legacy plans, session/weekly
|
|
6405
6519
|
* percentage limits; the shape is discriminated at runtime by the server response.
|
|
6406
6520
|
* See {@link OllamaClient.webSearch} for the cloud-endpoint/auth/timeout/retry
|
|
6407
|
-
* behavior, which applies identically here.
|
|
6521
|
+
* behavior, which applies identically here. Like `/api/usage`, the pinned contract
|
|
6522
|
+
* documents this endpoint's 429 with a `Retry-After` header, parsed into
|
|
6523
|
+
* `OllamaRateLimitError.retryAfterMs` and honored verbatim when retrying (ADR 0035).
|
|
6408
6524
|
*
|
|
6409
6525
|
* ```ts
|
|
6410
6526
|
* const balance = await client.balance();
|
|
@@ -6690,6 +6806,21 @@ function sleep2(ms, signal) {
|
|
|
6690
6806
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
6691
6807
|
});
|
|
6692
6808
|
}
|
|
6809
|
+
function retryAfterMsFromResponse(response) {
|
|
6810
|
+
try {
|
|
6811
|
+
const headers = response?.headers;
|
|
6812
|
+
if (headers === null || headers === void 0 || typeof headers.get !== "function") {
|
|
6813
|
+
return void 0;
|
|
6814
|
+
}
|
|
6815
|
+
const value = headers.get("retry-after");
|
|
6816
|
+
if (value === null || value === "") {
|
|
6817
|
+
return void 0;
|
|
6818
|
+
}
|
|
6819
|
+
return parseRetryAfterMs(value);
|
|
6820
|
+
} catch {
|
|
6821
|
+
return void 0;
|
|
6822
|
+
}
|
|
6823
|
+
}
|
|
6693
6824
|
async function fetchWithBackoff(input, init, config = {}) {
|
|
6694
6825
|
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
6695
6826
|
if (typeof fetchImpl !== "function") {
|
|
@@ -6711,7 +6842,8 @@ async function fetchWithBackoff(input, init, config = {}) {
|
|
|
6711
6842
|
...signal !== void 0 ? { signal } : {}
|
|
6712
6843
|
});
|
|
6713
6844
|
if (RETRYABLE_STATUS_CODES.has(response.status) && attempt < maxRetries) {
|
|
6714
|
-
const
|
|
6845
|
+
const serverDelayMs = response.status === 429 ? retryAfterMsFromResponse(response) : void 0;
|
|
6846
|
+
const delayMs = serverDelayMs ?? calculateBackoff(attempt, backoff);
|
|
6715
6847
|
config.onRetry?.(attempt, response.status, delayMs);
|
|
6716
6848
|
await sleep2(delayMs, signal);
|
|
6717
6849
|
continue;
|
|
@@ -8256,8 +8388,9 @@ function createModelAffinityScheduler(client, options) {
|
|
|
8256
8388
|
// src/system-one.ts
|
|
8257
8389
|
var MAX_SYSTEM_ONE_IMAGES_BYTES = 32 * 1024 * 1024;
|
|
8258
8390
|
var MAX_SYSTEM_ONE_REQUEST_BYTES = 64 * 1024;
|
|
8259
|
-
function estimateSystemOneRequestBytes(request) {
|
|
8260
|
-
|
|
8391
|
+
function estimateSystemOneRequestBytes(request, options) {
|
|
8392
|
+
const body = options?.excludeImages && request.images !== void 0 ? { ...request, images: void 0 } : request;
|
|
8393
|
+
return new TextEncoder().encode(JSON.stringify(body)).byteLength;
|
|
8261
8394
|
}
|
|
8262
8395
|
|
|
8263
8396
|
exports.ATTR_GEN_AI_OPERATION_NAME = ATTR_GEN_AI_OPERATION_NAME;
|
|
@@ -8325,6 +8458,7 @@ exports.OllamaModelRoutingError = OllamaModelRoutingError;
|
|
|
8325
8458
|
exports.OllamaNetworkError = OllamaNetworkError;
|
|
8326
8459
|
exports.OllamaNotFoundError = OllamaNotFoundError;
|
|
8327
8460
|
exports.OllamaOverloadedError = OllamaOverloadedError;
|
|
8461
|
+
exports.OllamaPaymentRequiredError = OllamaPaymentRequiredError;
|
|
8328
8462
|
exports.OllamaQuotaExceededError = OllamaQuotaExceededError;
|
|
8329
8463
|
exports.OllamaRateLimitError = OllamaRateLimitError;
|
|
8330
8464
|
exports.OllamaRequestTooLargeError = OllamaRequestTooLargeError;
|
|
@@ -8414,6 +8548,7 @@ exports.observeStream = observeStream;
|
|
|
8414
8548
|
exports.onProgress = onProgress;
|
|
8415
8549
|
exports.parseFrontmatter = parseFrontmatter;
|
|
8416
8550
|
exports.parseNdjsonStream = parseNdjsonStream;
|
|
8551
|
+
exports.parseRetryAfterMs = parseRetryAfterMs;
|
|
8417
8552
|
exports.parseSseStream = parseSseStream;
|
|
8418
8553
|
exports.parseStructuredOutput = parseStructuredOutput;
|
|
8419
8554
|
exports.recommendContextWindow = recommendContextWindow;
|