@nemesis-oss/ollama-sdk 1.19.0 → 1.20.0
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 +46 -0
- package/README.md +8 -8
- package/dist/{anthropic-CAvwqIjx.d.ts → anthropic-BFOC6eI7.d.ts} +7 -1
- package/dist/{anthropic-DIPnBwlf.d.cts → anthropic-C2-qaxjI.d.cts} +7 -1
- package/dist/{compose-C4QxEZOS.d.cts → compose-BXXgHmrS.d.cts} +1 -1
- package/dist/{compose-75UFDzOO.d.ts → compose-DaG83yId.d.ts} +1 -1
- package/dist/generated-api.cjs +1 -1
- package/dist/generated-api.cjs.map +1 -1
- package/dist/generated-api.d.cts +7 -7
- package/dist/generated-api.d.ts +7 -7
- package/dist/generated-api.js +1 -1
- package/dist/generated-api.js.map +1 -1
- package/dist/generated-models-schemas.cjs +25 -2
- package/dist/generated-models-schemas.cjs.map +1 -1
- package/dist/generated-models-schemas.d.cts +97 -5
- package/dist/generated-models-schemas.d.ts +97 -5
- package/dist/generated-models-schemas.js +24 -3
- package/dist/generated-models-schemas.js.map +1 -1
- package/dist/generated-runtime.cjs +23 -2
- 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 +23 -2
- package/dist/generated-runtime.js.map +1 -1
- package/dist/index.cjs +227 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +169 -46
- package/dist/index.d.ts +169 -46
- package/dist/index.js +222 -29
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools.json +1 -1
- package/dist/mcp-generated.cjs +1 -1
- 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 +1 -1
- package/dist/mcp-generated.js.map +1 -1
- package/dist/{runtime-C28YEAHC.d.cts → runtime-CpO3H6yy.d.cts} +55 -2
- package/dist/{runtime-DYCxYGG-.d.ts → runtime-DPSrPwAa.d.ts} +55 -2
- 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-Y3u0FtdN.d.cts → types-CnsZ24tm.d.cts} +17 -1
- package/dist/{types-Y3u0FtdN.d.ts → types-CnsZ24tm.d.ts} +17 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -303,6 +303,17 @@ var OllamaToolTimeoutError = class extends OllamaClientError {
|
|
|
303
303
|
this.timeoutMs = options.timeoutMs;
|
|
304
304
|
}
|
|
305
305
|
};
|
|
306
|
+
var OllamaCloudModelVersionError = class extends OllamaClientError {
|
|
307
|
+
model;
|
|
308
|
+
serverVersion;
|
|
309
|
+
minRequiredVersion;
|
|
310
|
+
constructor(message, options) {
|
|
311
|
+
super(message, { ...options, code: "cloud_model_version", retryable: false });
|
|
312
|
+
this.model = options.model;
|
|
313
|
+
this.serverVersion = options.serverVersion;
|
|
314
|
+
this.minRequiredVersion = options.minRequiredVersion;
|
|
315
|
+
}
|
|
316
|
+
};
|
|
306
317
|
var OllamaUnsupportedCapabilityError = class extends OllamaClientError {
|
|
307
318
|
capability;
|
|
308
319
|
constructor(message, options) {
|
|
@@ -428,6 +439,43 @@ function isNetworkLevelError(error) {
|
|
|
428
439
|
}
|
|
429
440
|
return false;
|
|
430
441
|
}
|
|
442
|
+
function lookupHeader(headers, name) {
|
|
443
|
+
if (headers === void 0) {
|
|
444
|
+
return void 0;
|
|
445
|
+
}
|
|
446
|
+
const needle = name.toLowerCase();
|
|
447
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
448
|
+
if (key.toLowerCase() === needle) {
|
|
449
|
+
return value;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return void 0;
|
|
453
|
+
}
|
|
454
|
+
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$/;
|
|
455
|
+
function parseRetryAfterMs(headerValue, now = Date.now()) {
|
|
456
|
+
if (headerValue === void 0) {
|
|
457
|
+
return void 0;
|
|
458
|
+
}
|
|
459
|
+
const trimmed = headerValue.trim();
|
|
460
|
+
if (trimmed === "") {
|
|
461
|
+
return void 0;
|
|
462
|
+
}
|
|
463
|
+
if (/^\d+$/.test(trimmed)) {
|
|
464
|
+
const seconds = Number(trimmed);
|
|
465
|
+
if (!Number.isSafeInteger(seconds)) {
|
|
466
|
+
return void 0;
|
|
467
|
+
}
|
|
468
|
+
return seconds * 1e3;
|
|
469
|
+
}
|
|
470
|
+
if (!HTTP_DATE_PATTERN.test(trimmed)) {
|
|
471
|
+
return void 0;
|
|
472
|
+
}
|
|
473
|
+
const instant = Date.parse(trimmed);
|
|
474
|
+
if (Number.isNaN(instant)) {
|
|
475
|
+
return void 0;
|
|
476
|
+
}
|
|
477
|
+
return Math.max(0, instant - now);
|
|
478
|
+
}
|
|
431
479
|
function statusToError(status, message, options) {
|
|
432
480
|
if (status === 401 || status === 403) {
|
|
433
481
|
return new OllamaAuthError(message, { ...options, status });
|
|
@@ -439,7 +487,8 @@ function statusToError(status, message, options) {
|
|
|
439
487
|
return new OllamaNotFoundError(message, { ...options, status });
|
|
440
488
|
}
|
|
441
489
|
if (status === 429) {
|
|
442
|
-
|
|
490
|
+
const retryAfterMs = parseRetryAfterMs(lookupHeader(options.response?.headers, "retry-after"));
|
|
491
|
+
return new OllamaRateLimitError(message, { ...options, status, retryAfterMs });
|
|
443
492
|
}
|
|
444
493
|
if (status === 502) {
|
|
445
494
|
return new OllamaBadGatewayError(message, { ...options });
|
|
@@ -1142,6 +1191,21 @@ function sameHeaders(actual, expected) {
|
|
|
1142
1191
|
const expectedKeys = Object.keys(expectedEntries);
|
|
1143
1192
|
return actualKeys.length === expectedKeys.length && expectedKeys.every((key) => actualEntries[key] === expectedEntries[key]);
|
|
1144
1193
|
}
|
|
1194
|
+
function retryAfterHeaderFrom(response) {
|
|
1195
|
+
try {
|
|
1196
|
+
const headers = response?.headers;
|
|
1197
|
+
if (headers === null || headers === void 0 || typeof headers.get !== "function") {
|
|
1198
|
+
return void 0;
|
|
1199
|
+
}
|
|
1200
|
+
const value = headers.get("retry-after");
|
|
1201
|
+
if (value === null || value === "") {
|
|
1202
|
+
return void 0;
|
|
1203
|
+
}
|
|
1204
|
+
return { "retry-after": value };
|
|
1205
|
+
} catch {
|
|
1206
|
+
return void 0;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1145
1209
|
var HttpClient = class {
|
|
1146
1210
|
baseUrl;
|
|
1147
1211
|
apiKey;
|
|
@@ -1209,7 +1273,12 @@ var HttpClient = class {
|
|
|
1209
1273
|
durationMs: Date.now() - startedAt,
|
|
1210
1274
|
error: mapError(new Error(`HTTP ${response2.status}`), {
|
|
1211
1275
|
request: { method: request.method, url: request.url },
|
|
1212
|
-
|
|
1276
|
+
// Mirrors the middleware path, which reports context.headers:
|
|
1277
|
+
// a 429 lifecycle event carries the server's Retry-After.
|
|
1278
|
+
response: {
|
|
1279
|
+
status: response2.status,
|
|
1280
|
+
headers: retryAfterHeaderFrom(response2)
|
|
1281
|
+
}
|
|
1213
1282
|
}),
|
|
1214
1283
|
timestamp: Date.now()
|
|
1215
1284
|
});
|
|
@@ -1315,7 +1384,11 @@ var HttpClient = class {
|
|
|
1315
1384
|
const message = typeof errorBody === "object" && errorBody !== null && "error" in errorBody ? String(errorBody.error) : `HTTP ${response.status} ${response.statusText}`;
|
|
1316
1385
|
throw mapError(new Error(message), {
|
|
1317
1386
|
request: { method, url },
|
|
1318
|
-
response: {
|
|
1387
|
+
response: {
|
|
1388
|
+
status: response.status,
|
|
1389
|
+
headers: retryAfterHeaderFrom(response),
|
|
1390
|
+
body: errorBody
|
|
1391
|
+
}
|
|
1319
1392
|
});
|
|
1320
1393
|
}
|
|
1321
1394
|
if (options.method === "HEAD" || response.status === 204) {
|
|
@@ -1380,7 +1453,11 @@ var HttpClient = class {
|
|
|
1380
1453
|
const errorText = await response.text();
|
|
1381
1454
|
throw mapError(new Error(errorText || `HTTP ${response.status}`), {
|
|
1382
1455
|
request: { method, url },
|
|
1383
|
-
response: {
|
|
1456
|
+
response: {
|
|
1457
|
+
status: response.status,
|
|
1458
|
+
headers: retryAfterHeaderFrom(response),
|
|
1459
|
+
body: errorText
|
|
1460
|
+
}
|
|
1384
1461
|
});
|
|
1385
1462
|
}
|
|
1386
1463
|
if (!response.body) {
|
|
@@ -1444,7 +1521,11 @@ var HttpClient = class {
|
|
|
1444
1521
|
const errorText = await response.text();
|
|
1445
1522
|
throw mapError(new Error(errorText || `HTTP ${response.status}`), {
|
|
1446
1523
|
request: { method, url },
|
|
1447
|
-
response: {
|
|
1524
|
+
response: {
|
|
1525
|
+
status: response.status,
|
|
1526
|
+
headers: retryAfterHeaderFrom(response),
|
|
1527
|
+
body: errorText
|
|
1528
|
+
}
|
|
1448
1529
|
});
|
|
1449
1530
|
}
|
|
1450
1531
|
if (!response.body) {
|
|
@@ -1750,7 +1831,7 @@ function contextWarningMessage(check2, kind) {
|
|
|
1750
1831
|
if (check2.windowSource === "client-default") {
|
|
1751
1832
|
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\`.`;
|
|
1752
1833
|
}
|
|
1753
|
-
return `${where}: estimated prompt size ${estimate} outright exceeds
|
|
1834
|
+
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\`.`;
|
|
1754
1835
|
}
|
|
1755
1836
|
|
|
1756
1837
|
// src/context-discovery.ts
|
|
@@ -2478,6 +2559,12 @@ function sleep(ms, signal) {
|
|
|
2478
2559
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
2479
2560
|
});
|
|
2480
2561
|
}
|
|
2562
|
+
function retryDelayMs(error, attempt, backoff) {
|
|
2563
|
+
if (error instanceof OllamaRateLimitError && error.retryAfterMs !== void 0) {
|
|
2564
|
+
return error.retryAfterMs;
|
|
2565
|
+
}
|
|
2566
|
+
return calculateBackoff(attempt, backoff);
|
|
2567
|
+
}
|
|
2481
2568
|
async function withRetry(operation, config = DEFAULT_RETRY_CONFIG, signal) {
|
|
2482
2569
|
let attempt = 0;
|
|
2483
2570
|
while (true) {
|
|
@@ -2489,7 +2576,7 @@ async function withRetry(operation, config = DEFAULT_RETRY_CONFIG, signal) {
|
|
|
2489
2576
|
if (attempt >= config.maxRetries || !shouldRetry(error, attempt)) {
|
|
2490
2577
|
throw error;
|
|
2491
2578
|
}
|
|
2492
|
-
const delayMs =
|
|
2579
|
+
const delayMs = retryDelayMs(error, attempt, config.backoff);
|
|
2493
2580
|
config.onRetry?.(error, attempt, delayMs);
|
|
2494
2581
|
await sleep(delayMs, signal);
|
|
2495
2582
|
attempt += 1;
|
|
@@ -2658,7 +2745,8 @@ var ModelsClient = class {
|
|
|
2658
2745
|
}
|
|
2659
2746
|
/**
|
|
2660
2747
|
* Discovers the model's real context window from the server — no more
|
|
2661
|
-
*
|
|
2748
|
+
* default-window guesswork (current daemons tier the unset-`num_ctx`
|
|
2749
|
+
* default by VRAM: 4k / 32k / 256k). Consults, in precedence order:
|
|
2662
2750
|
*
|
|
2663
2751
|
* 1. `GET /api/ps` — the window the **running instance actually
|
|
2664
2752
|
* allocated** (exact, reflects the Modelfile `num_ctx` default and
|
|
@@ -2670,7 +2758,7 @@ var ModelsClient = class {
|
|
|
2670
2758
|
* 3. `POST /api/show` `model_info["<arch>.context_length"]` — the
|
|
2671
2759
|
* model's **native GGUF maximum** (a ceiling to raise `num_ctx`
|
|
2672
2760
|
* toward, not the allocated window).
|
|
2673
|
-
* 4. Fallback —
|
|
2761
|
+
* 4. Fallback — the 2048 worst-case floor for the unset-`num_ctx` window.
|
|
2674
2762
|
*
|
|
2675
2763
|
* The result carries every signal it found, so `nativeContextLength:
|
|
2676
2764
|
* 131072` vs `contextLength: 4096` (a 32× gap seen in the official API
|
|
@@ -4156,6 +4244,9 @@ var ShowResponseSchema = zod.z.object({
|
|
|
4156
4244
|
modified_at: zod.z.string().optional(),
|
|
4157
4245
|
details: zod.z.object({}).optional(),
|
|
4158
4246
|
template: zod.z.string().optional(),
|
|
4247
|
+
renderer: zod.z.string().optional(),
|
|
4248
|
+
parser: zod.z.string().optional(),
|
|
4249
|
+
template_source: zod.z.string().optional(),
|
|
4159
4250
|
capabilities: zod.z.array(zod.z.string()).optional(),
|
|
4160
4251
|
model_info: zod.z.object({}).optional()
|
|
4161
4252
|
});
|
|
@@ -4247,9 +4338,26 @@ var UsageMetricsSchema = zod.z.object({
|
|
|
4247
4338
|
output_tokens: zod.z.number().optional()
|
|
4248
4339
|
});
|
|
4249
4340
|
|
|
4341
|
+
// src/generated/models/UsageGroup.schema.ts
|
|
4342
|
+
var UsageGroupSchema = zod.z.intersection(
|
|
4343
|
+
UsageMetricsSchema,
|
|
4344
|
+
zod.z.object({
|
|
4345
|
+
model: zod.z.string()
|
|
4346
|
+
})
|
|
4347
|
+
);
|
|
4348
|
+
|
|
4349
|
+
// src/generated/models/UsageSummary.schema.ts
|
|
4350
|
+
var UsageSummarySchema = zod.z.intersection(
|
|
4351
|
+
UsageMetricsSchema,
|
|
4352
|
+
zod.z.object({
|
|
4353
|
+
groups: zod.z.array(UsageGroupSchema).optional(),
|
|
4354
|
+
remainder: UsageMetricsSchema.optional()
|
|
4355
|
+
})
|
|
4356
|
+
);
|
|
4357
|
+
|
|
4250
4358
|
// src/generated/models/UsageBucket.schema.ts
|
|
4251
4359
|
var UsageBucketSchema = zod.z.intersection(
|
|
4252
|
-
|
|
4360
|
+
UsageSummarySchema,
|
|
4253
4361
|
zod.z.object({
|
|
4254
4362
|
from: zod.z.string(),
|
|
4255
4363
|
until: zod.z.string(),
|
|
@@ -4262,9 +4370,10 @@ var UsageResponseSchema = zod.z.object({
|
|
|
4262
4370
|
range: zod.z.enum(["24h", "7d", "30d"]),
|
|
4263
4371
|
scope: zod.z.enum(["self", "team"]),
|
|
4264
4372
|
granularity: zod.z.enum(["hour", "day"]),
|
|
4373
|
+
group_by: zod.z.enum(["model"]).optional(),
|
|
4265
4374
|
from: zod.z.string(),
|
|
4266
4375
|
until: zod.z.string(),
|
|
4267
|
-
totals:
|
|
4376
|
+
totals: UsageSummarySchema,
|
|
4268
4377
|
buckets: zod.z.array(UsageBucketSchema)
|
|
4269
4378
|
});
|
|
4270
4379
|
var VersionResponseSchema = zod.z.object({
|
|
@@ -5707,6 +5816,29 @@ function createDecision(client) {
|
|
|
5707
5816
|
};
|
|
5708
5817
|
}
|
|
5709
5818
|
|
|
5819
|
+
// src/system-one.ts
|
|
5820
|
+
var MAX_SYSTEM_ONE_IMAGES_BYTES = 32 * 1024 * 1024;
|
|
5821
|
+
var MAX_SYSTEM_ONE_REQUEST_BYTES = 64 * 1024;
|
|
5822
|
+
var CLOUD_MODEL_SUFFIX = ":cloud";
|
|
5823
|
+
var CLOUD_MODEL_MIN_OLLAMA_VERSION = "0.40.5";
|
|
5824
|
+
function isCloudModel(model) {
|
|
5825
|
+
return model.endsWith(CLOUD_MODEL_SUFFIX);
|
|
5826
|
+
}
|
|
5827
|
+
function compareOllamaVersions(a, b) {
|
|
5828
|
+
const pa = a.split(".").map((s) => Number.parseInt(s, 10) || 0);
|
|
5829
|
+
const pb = b.split(".").map((s) => Number.parseInt(s, 10) || 0);
|
|
5830
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
|
|
5831
|
+
const va = pa[i] ?? 0;
|
|
5832
|
+
const vb = pb[i] ?? 0;
|
|
5833
|
+
if (va !== vb) return va - vb;
|
|
5834
|
+
}
|
|
5835
|
+
return 0;
|
|
5836
|
+
}
|
|
5837
|
+
function estimateSystemOneRequestBytes(request, options) {
|
|
5838
|
+
const body = options?.excludeImages && request.images !== void 0 ? { ...request, images: void 0 } : request;
|
|
5839
|
+
return new TextEncoder().encode(JSON.stringify(body)).byteLength;
|
|
5840
|
+
}
|
|
5841
|
+
|
|
5710
5842
|
// src/client.ts
|
|
5711
5843
|
var logicalRequestSequence = 0;
|
|
5712
5844
|
function createLogicalRequestId() {
|
|
@@ -6333,9 +6465,13 @@ var OllamaClient = class _OllamaClient {
|
|
|
6333
6465
|
* launch): `model` also accepts cloud models such as `clef:cloud` —
|
|
6334
6466
|
* cloud models require Ollama >= 0.40.5 or the hosted
|
|
6335
6467
|
* `https://ollama.com` endpoint. Requires Ollama >= 0.35.0 locally.
|
|
6336
|
-
*
|
|
6468
|
+
* Both version constraints are enforced client-side before the request
|
|
6469
|
+
* is sent: the blanket 0.35.0 floor by the generated runtime (lazily
|
|
6337
6470
|
* fetching `/api/version` when `enforceVersion` is `'auto'` or
|
|
6338
|
-
* `'strict'`)
|
|
6471
|
+
* `'strict'`), and the model-dependent 0.40.5 cloud gate by this
|
|
6472
|
+
* wrapper — a cloud model through a local server older than 0.40.5
|
|
6473
|
+
* throws {@link OllamaCloudModelVersionError} without a round-trip
|
|
6474
|
+
* (ADR 0036). Request size is checked client-side as a dual cap:
|
|
6339
6475
|
* text and schema (images excluded) within 64 KiB AND the whole
|
|
6340
6476
|
* request within 32 MiB.
|
|
6341
6477
|
*
|
|
@@ -6360,10 +6496,44 @@ var OllamaClient = class _OllamaClient {
|
|
|
6360
6496
|
* `client.native.systemOne(request)` directly.
|
|
6361
6497
|
*/
|
|
6362
6498
|
async systemOne(request) {
|
|
6499
|
+
await this.assertCloudModelSupported(request.model);
|
|
6363
6500
|
return this.native.systemOne(
|
|
6364
6501
|
request
|
|
6365
6502
|
);
|
|
6366
6503
|
}
|
|
6504
|
+
/**
|
|
6505
|
+
* Cloud-model version gate for {@link systemOne} — throws
|
|
6506
|
+
* {@link OllamaCloudModelVersionError} when a cloud model is requested
|
|
6507
|
+
* through a local server older than {@link CLOUD_MODEL_MIN_OLLAMA_VERSION}
|
|
6508
|
+
* (0.40.5). No-op for non-cloud models and for cloud-mode clients
|
|
6509
|
+
* (hosted `ollama.com`). The `/api/version` probe goes through the normal
|
|
6510
|
+
* failover machinery and is cached per client instance (reset on failure,
|
|
6511
|
+
* so a later gated call retries), so at most one extra round-trip happens
|
|
6512
|
+
* across all gated calls.
|
|
6513
|
+
*/
|
|
6514
|
+
async assertCloudModelSupported(model) {
|
|
6515
|
+
if (!isCloudModel(model)) return;
|
|
6516
|
+
const candidates = this.registry.candidates();
|
|
6517
|
+
const baseUrl = candidates[0]?.baseUrl ?? DEFAULT_BASE_URL;
|
|
6518
|
+
if (inferRuntimeMode(baseUrl) !== "local") return;
|
|
6519
|
+
let version;
|
|
6520
|
+
try {
|
|
6521
|
+
if (this.serverVersionCache === void 0) {
|
|
6522
|
+
this.serverVersionCache = this.native.version().then((v) => v.version);
|
|
6523
|
+
}
|
|
6524
|
+
version = await this.serverVersionCache;
|
|
6525
|
+
} catch {
|
|
6526
|
+
this.serverVersionCache = void 0;
|
|
6527
|
+
return;
|
|
6528
|
+
}
|
|
6529
|
+
if (version && compareOllamaVersions(version, CLOUD_MODEL_MIN_OLLAMA_VERSION) < 0) {
|
|
6530
|
+
throw new OllamaCloudModelVersionError(
|
|
6531
|
+
`System One cloud model "${model}" requires Ollama >= ${CLOUD_MODEL_MIN_OLLAMA_VERSION} when routed through a local server (this server reports ${version}). Upgrade Ollama, or point an endpoint at https://ollama.com.`,
|
|
6532
|
+
{ model, serverVersion: version, minRequiredVersion: CLOUD_MODEL_MIN_OLLAMA_VERSION }
|
|
6533
|
+
);
|
|
6534
|
+
}
|
|
6535
|
+
}
|
|
6536
|
+
serverVersionCache;
|
|
6367
6537
|
// --- Web Endpoints ---
|
|
6368
6538
|
/**
|
|
6369
6539
|
* Ollama's hosted web search tool (`POST https://ollama.com/api/web_search`) — a fixed
|
|
@@ -6371,7 +6541,9 @@ var OllamaClient = class _OllamaClient {
|
|
|
6371
6541
|
* through a local server. Requires an Ollama account API key: pass `apiKey` to the
|
|
6372
6542
|
* client constructor or set `OLLAMA_API_KEY`. Applies the same default `timeoutMs` and
|
|
6373
6543
|
* retry policy as inference calls, but never cross-endpoint-fails-over — there is only
|
|
6374
|
-
* ever the one cloud endpoint to call.
|
|
6544
|
+
* ever the one cloud endpoint to call. If the service answers 429 with a `Retry-After`
|
|
6545
|
+
* header, the transport parses it into `OllamaRateLimitError.retryAfterMs` and the
|
|
6546
|
+
* retry loop sleeps exactly that long instead of jittered backoff (see ADR 0035).
|
|
6375
6547
|
*/
|
|
6376
6548
|
async webSearch(req) {
|
|
6377
6549
|
const { count, max_results, ...rest } = req;
|
|
@@ -6402,14 +6574,24 @@ var OllamaClient = class _OllamaClient {
|
|
|
6402
6574
|
* web search, and web fetch, bucketed by hour (`range: '24h'`) or day (`'7d'`/`'30d'`).
|
|
6403
6575
|
*
|
|
6404
6576
|
* See {@link OllamaClient.webSearch} for the cloud-endpoint/auth/timeout/retry
|
|
6405
|
-
* behavior, which applies identically here.
|
|
6406
|
-
* endpoint
|
|
6407
|
-
*
|
|
6577
|
+
* behavior, which applies identically here. The pinned contract documents this
|
|
6578
|
+
* endpoint's 429 with a `Retry-After` header ("Seconds to wait before retrying"),
|
|
6579
|
+
* which the SDK parses into `OllamaRateLimitError.retryAfterMs` and honors verbatim
|
|
6580
|
+
* when retrying. Query parameters mirror the official endpoint: `range`
|
|
6581
|
+
* (`'24h' | '7d' | '30d'`, server default `'7d'`), `scope`
|
|
6582
|
+
* (`'self' | 'team'`, server default `'self'`; team scope requires a team
|
|
6583
|
+
* admin), and — since the 2026-10-22 pin (upstream 2476d5e) — `groupBy`
|
|
6584
|
+
* (`group_by=model`), which makes `totals` and every bucket carry up to 10
|
|
6585
|
+
* per-model `UsageGroup` entries plus a `remainder` roll-up, with the
|
|
6586
|
+
* selection echoed back as `group_by` on the response.
|
|
6408
6587
|
* Omitted options are left unset so the server applies its own defaults.
|
|
6409
6588
|
*
|
|
6410
6589
|
* ```ts
|
|
6411
|
-
* const usage = await client.usage({ range: '24h' });
|
|
6590
|
+
* const usage = await client.usage({ range: '24h', groupBy: 'model' });
|
|
6412
6591
|
* console.log(usage.totals.request_count, usage.totals.usage_usd);
|
|
6592
|
+
* for (const group of usage.totals.groups ?? []) {
|
|
6593
|
+
* console.log(group.model, group.usage_usd);
|
|
6594
|
+
* }
|
|
6413
6595
|
* for (const bucket of usage.buckets) {
|
|
6414
6596
|
* if (bucket.partial) continue; // current hour, still in progress
|
|
6415
6597
|
* // ...
|
|
@@ -6420,6 +6602,7 @@ var OllamaClient = class _OllamaClient {
|
|
|
6420
6602
|
const params = new URLSearchParams();
|
|
6421
6603
|
if (req.range !== void 0) params.set("range", req.range);
|
|
6422
6604
|
if (req.scope !== void 0) params.set("scope", req.scope);
|
|
6605
|
+
if (req.groupBy !== void 0) params.set("group_by", req.groupBy);
|
|
6423
6606
|
const query = params.toString();
|
|
6424
6607
|
return this.executeCloudRequest(
|
|
6425
6608
|
(http, signal) => http.request({
|
|
@@ -6436,7 +6619,9 @@ var OllamaClient = class _OllamaClient {
|
|
|
6436
6619
|
* object (`balance_usd`/`allowance_usd`/`period`) or, on legacy plans, session/weekly
|
|
6437
6620
|
* percentage limits; the shape is discriminated at runtime by the server response.
|
|
6438
6621
|
* See {@link OllamaClient.webSearch} for the cloud-endpoint/auth/timeout/retry
|
|
6439
|
-
* behavior, which applies identically here.
|
|
6622
|
+
* behavior, which applies identically here. Like `/api/usage`, the pinned contract
|
|
6623
|
+
* documents this endpoint's 429 with a `Retry-After` header, parsed into
|
|
6624
|
+
* `OllamaRateLimitError.retryAfterMs` and honored verbatim when retrying (ADR 0035).
|
|
6440
6625
|
*
|
|
6441
6626
|
* ```ts
|
|
6442
6627
|
* const balance = await client.balance();
|
|
@@ -6722,6 +6907,21 @@ function sleep2(ms, signal) {
|
|
|
6722
6907
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
6723
6908
|
});
|
|
6724
6909
|
}
|
|
6910
|
+
function retryAfterMsFromResponse(response) {
|
|
6911
|
+
try {
|
|
6912
|
+
const headers = response?.headers;
|
|
6913
|
+
if (headers === null || headers === void 0 || typeof headers.get !== "function") {
|
|
6914
|
+
return void 0;
|
|
6915
|
+
}
|
|
6916
|
+
const value = headers.get("retry-after");
|
|
6917
|
+
if (value === null || value === "") {
|
|
6918
|
+
return void 0;
|
|
6919
|
+
}
|
|
6920
|
+
return parseRetryAfterMs(value);
|
|
6921
|
+
} catch {
|
|
6922
|
+
return void 0;
|
|
6923
|
+
}
|
|
6924
|
+
}
|
|
6725
6925
|
async function fetchWithBackoff(input, init, config = {}) {
|
|
6726
6926
|
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
6727
6927
|
if (typeof fetchImpl !== "function") {
|
|
@@ -6743,7 +6943,8 @@ async function fetchWithBackoff(input, init, config = {}) {
|
|
|
6743
6943
|
...signal !== void 0 ? { signal } : {}
|
|
6744
6944
|
});
|
|
6745
6945
|
if (RETRYABLE_STATUS_CODES.has(response.status) && attempt < maxRetries) {
|
|
6746
|
-
const
|
|
6946
|
+
const serverDelayMs = response.status === 429 ? retryAfterMsFromResponse(response) : void 0;
|
|
6947
|
+
const delayMs = serverDelayMs ?? calculateBackoff(attempt, backoff);
|
|
6747
6948
|
config.onRetry?.(attempt, response.status, delayMs);
|
|
6748
6949
|
await sleep2(delayMs, signal);
|
|
6749
6950
|
continue;
|
|
@@ -8285,14 +8486,6 @@ function createModelAffinityScheduler(client, options) {
|
|
|
8285
8486
|
return new ModelAffinityScheduler(client, options);
|
|
8286
8487
|
}
|
|
8287
8488
|
|
|
8288
|
-
// src/system-one.ts
|
|
8289
|
-
var MAX_SYSTEM_ONE_IMAGES_BYTES = 32 * 1024 * 1024;
|
|
8290
|
-
var MAX_SYSTEM_ONE_REQUEST_BYTES = 64 * 1024;
|
|
8291
|
-
function estimateSystemOneRequestBytes(request, options) {
|
|
8292
|
-
const body = options?.excludeImages && request.images !== void 0 ? { ...request, images: void 0 } : request;
|
|
8293
|
-
return new TextEncoder().encode(JSON.stringify(body)).byteLength;
|
|
8294
|
-
}
|
|
8295
|
-
|
|
8296
8489
|
exports.ATTR_GEN_AI_OPERATION_NAME = ATTR_GEN_AI_OPERATION_NAME;
|
|
8297
8490
|
exports.ATTR_GEN_AI_REQUEST_MODEL = ATTR_GEN_AI_REQUEST_MODEL;
|
|
8298
8491
|
exports.ATTR_GEN_AI_RESPONSE_MODEL = ATTR_GEN_AI_RESPONSE_MODEL;
|
|
@@ -8313,6 +8506,8 @@ exports.ATTR_URL_FULL = ATTR_URL_FULL;
|
|
|
8313
8506
|
exports.Agent = Agent;
|
|
8314
8507
|
exports.AnthropicCompatClient = AnthropicCompatClient;
|
|
8315
8508
|
exports.AnthropicMessagesStream = AnthropicMessagesStream;
|
|
8509
|
+
exports.CLOUD_MODEL_MIN_OLLAMA_VERSION = CLOUD_MODEL_MIN_OLLAMA_VERSION;
|
|
8510
|
+
exports.CLOUD_MODEL_SUFFIX = CLOUD_MODEL_SUFFIX;
|
|
8316
8511
|
exports.ConversationSession = ConversationSession;
|
|
8317
8512
|
exports.DEFAULT_BACKOFF = DEFAULT_BACKOFF;
|
|
8318
8513
|
exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
@@ -8351,6 +8546,7 @@ exports.OllamaAuthError = OllamaAuthError;
|
|
|
8351
8546
|
exports.OllamaBadGatewayError = OllamaBadGatewayError;
|
|
8352
8547
|
exports.OllamaClient = OllamaClient;
|
|
8353
8548
|
exports.OllamaClientError = OllamaClientError;
|
|
8549
|
+
exports.OllamaCloudModelVersionError = OllamaCloudModelVersionError;
|
|
8354
8550
|
exports.OllamaGenericClientError = OllamaGenericClientError;
|
|
8355
8551
|
exports.OllamaIncompatibleModelError = OllamaIncompatibleModelError;
|
|
8356
8552
|
exports.OllamaMcpError = OllamaMcpError;
|
|
@@ -8396,6 +8592,7 @@ exports.checkEndpointHealth = checkEndpointHealth;
|
|
|
8396
8592
|
exports.checkGenerateContext = checkGenerateContext;
|
|
8397
8593
|
exports.compactConversationHistory = compactConversationHistory;
|
|
8398
8594
|
exports.compareDraftPerformance = compareDraftPerformance;
|
|
8595
|
+
exports.compareOllamaVersions = compareOllamaVersions;
|
|
8399
8596
|
exports.composeMiddleware = composeMiddleware;
|
|
8400
8597
|
exports.computeProgressPercent = computeProgressPercent;
|
|
8401
8598
|
exports.contextWarningMessage = contextWarningMessage;
|
|
@@ -8428,6 +8625,7 @@ exports.formatWebFetchResult = formatWebFetchResult;
|
|
|
8428
8625
|
exports.formatWebSearchResult = formatWebSearchResult;
|
|
8429
8626
|
exports.imageStringNeedsResolution = imageStringNeedsResolution;
|
|
8430
8627
|
exports.inferRuntimeMode = inferRuntimeMode;
|
|
8628
|
+
exports.isCloudModel = isCloudModel;
|
|
8431
8629
|
exports.isKeepAliveSugar = isKeepAliveSugar;
|
|
8432
8630
|
exports.isKnownDoneReason = isKnownDoneReason;
|
|
8433
8631
|
exports.isModelResident = isModelResident;
|
|
@@ -8448,6 +8646,7 @@ exports.observeStream = observeStream;
|
|
|
8448
8646
|
exports.onProgress = onProgress;
|
|
8449
8647
|
exports.parseFrontmatter = parseFrontmatter;
|
|
8450
8648
|
exports.parseNdjsonStream = parseNdjsonStream;
|
|
8649
|
+
exports.parseRetryAfterMs = parseRetryAfterMs;
|
|
8451
8650
|
exports.parseSseStream = parseSseStream;
|
|
8452
8651
|
exports.parseStructuredOutput = parseStructuredOutput;
|
|
8453
8652
|
exports.recommendContextWindow = recommendContextWindow;
|