@nemesis-oss/ollama-sdk 1.11.0 → 1.12.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 CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.12.0] — Daemon liveness & telemetry standardization: formatTelemetry, dynamic host model-affinity routing, root ping
4
+
5
+ The October 10 documentation digest ("Daemon Liveness & Telemetry Standardization") reviewed the official operational surfaces — the root liveness probe (`HEAD /` → 200, body "Ollama is running"), `GET /api/version`, `GET /api/ps` runner introspection, and the nanosecond duration counters on every generation response. Verified against the codebase first (see [ADR 0028](./docs/adr/0028-telemetry-normalization-host-affinity-root-ping.md)): two of the digest's gap assessments were stale — multi-host pooling with least-connections routing, capacity caps, and 503/`OLLAMA_MAX_QUEUE` saturation failover already exist (`endpoints` + `endpointHealth` + `DEFAULT_FAILOVER_CODES`), so the proposed `LoadBalancedOllamaClient` was **not** added (it would fork the existing routing engine); the real gaps — telemetry math, dynamic multi-host affinity, and the root ping — are implemented, all additive, no breaking changes. 865 pre-existing tests stay green, 33 new tests added.
6
+
7
+ ### Standardized telemetry normalizer (`formatTelemetry`, `src/telemetry/metrics.ts`)
8
+
9
+ - **`formatTelemetry(raw)`** derives the human-scale summary from Ollama's raw nanosecond/token counters: `totalLatencyMs`, `modelLoadMs`, `promptEvalMs`, `generationMs` (ns→ms, 2 decimals), `tokensPerSecond` (`eval_count / (eval_duration / 1e9)` — the official Usage-doc formula), `promptTokensPerSecond`, and `cacheHitRatio` — pure, never throws, missing counters read as `0` (never `NaN`/`Infinity`, so partial payloads like stream final events and older servers format cleanly).
10
+ - The input is **structural**: any response object carrying the optional counters — `ChatResponse`, `GenerateResponse`, the final `GenerateStreamEvent`, `EmbedResponse` — passes as-is, no plucking. Purity and structural acceptance are pinned by tests with real response objects (no casts).
11
+ - **`cacheHitRatio` deliberately deviates from the digest's sketch**: `cached / (cached + evaluated)`, not `cached / prompt_eval_count` — Ollama reports `prompt_eval_count: 0` on a _full_ cache hit, so the digest's formula divides by zero and reads a perfect cache as "no caching". The sum denominator is the SDK's established `ConversationSession.cacheStats.hitRate` semantics; the two surfaces now share documented, tested math.
12
+
13
+ ### Dynamic host model-affinity routing (`endpointHealth.modelAffinity` + `ModelAffinityRouter`)
14
+
15
+ - The digest's "tomorrow's focus" item, shipped: with several interchangeable endpoints, **opt-in** `endpointHealth: { modelAffinity: { ttlMs?, failureRetryMs? } }` reorders each request's candidate endpoints so hosts whose `GET /api/ps` shows the requested model already resident in VRAM are tried first — avoiding the unload/cold-load swap a miss forces on `OLLAMA_MAX_LOADED_MODELS`-bounded daemons. The multi-host counterpart of `ModelAffinityScheduler` (v1.11.0); the two compose.
16
+ - **Zero added request latency**: reordering is synchronous and cache-only — a request never waits for a probe. On a cache miss the request proceeds with the unchanged order while a background refresh (TTL 30s default, deduped, 5s failure backoff) warms the cache. `client.warmModelAffinity()` pre-warms at startup; `client.modelAffinityStatus()` exposes per-endpoint snapshots (loaded models, fetch time, freshness) for observability.
17
+ - **Partial knowledge suppresses the reorder** — if any candidate's snapshot is stale or unknown, the original order stands (routing on partial residency data risks the exact cold-load swap the feature prevents). Probe failures are never cached as data; probes bypass `executeWithFailover` entirely (no reentry, no circuit-breaker pollution, no cross-host failover — the answer is per-host by definition).
18
+ - **Race-free with `'least-connections'`**: no `await` between candidate selection, the reorder, and the endpoint's `acquire()` — the strategy's deterministic one-per-account guarantee is untouched; priority tiers, capacity caps, `models`-scoped credentials, and single-endpoint pinning all keep working.
19
+ - **Matching is shared, not duplicated**: "resident" uses the same matcher as context-window discovery (`isModelResident`, refactored out of `findRunningModelContextLength` — exact `name`/`model` match or tag-less prefix `llama3` ↔ `llama3:latest`, never `llama` → `llama3.1`). Off unless configured: without `modelAffinity` the router isn't constructed and no `/api/ps` probes are ever issued.
20
+
21
+ ### Root liveness probe (`client.ping()`)
22
+
23
+ - The official ultra-lightweight liveness check: `HEAD /` against the current best candidate endpoint, resolving `{ healthy, latencyMs, baseUrl, error? }` — the docs define this exact probe for load-balancer health checks (`GET /` answers the plain-text body "Ollama is running"; HEAD doesn't transfer it).
24
+ - **Single-shot by design** — no retry, no failover: a liveness probe's value is that it answers about _one concrete host_, not "some endpoint eventually answered". Fleet audits remain `healthCheck()`'s job (every endpoint, plus the version via the heavier `GET /api/version`). Resolves rather than throws on connection failure/timeout/error status (monitoring loops treat it as a datapoint); only caller-initiated cancellation (`signal`, `destroy()`) rejects, like any other aborted request. Uses the client's `fetch`/middleware/lifecycle pipeline like every other request.
25
+
26
+ ### Documentation
27
+
28
+ - README: three Key Features bullets; a "Standardized Telemetry" section (before OpenTelemetry, which it complements); a "Model-affinity routing across hosts" subsection in the Multi-Endpoint guide (with the `warmModelAffinity`/`modelAffinityStatus` flow); `ping()` in the health-check intro. ADR 0028 records the audit verdicts, the declined `LoadBalancedOllamaClient` fork, and the `cacheHitRatio` deviation rationale.
29
+ - New examples: `examples/telemetry.ts` and `examples/multi-host-affinity.ts`.
30
+
3
31
  ## [1.11.0] — Documentation digest + production-readiness audit: context discovery, compaction, affinity scheduling, agent cycle detection, URL-join hardening, vision-history hygiene
4
32
 
5
33
  Three real gaps from the follow-up documentation digest on concurrency & memory-scaling mechanics (see [ADR 0026](./docs/adr/0026-context-discovery-history-compaction-model-affinity.md)) and three verified findings from the October 9 production-readiness audit on agent-loop ergonomics, transport hardening, and multi-turn memory retention (see [ADR 0027](./docs/adr/0027-agent-cycle-detection-url-join-history-hygiene.md)) — all additive, no breaking changes; 778 pre-existing tests stay green, 87 new tests added (40 digest + 47 audit). Stale claims in both reports were verified against the codebase and answered with documentation and tests instead of new code (one digest claim, two audit claims).
package/README.md CHANGED
@@ -29,6 +29,9 @@
29
29
  - 🧠 **Dynamic Context-Window Discovery**: `client.models.getContextLength({ model })` resolves the real window from the server — the allocated window of the running instance (`/api/ps`), the Modelfile `num_ctx` default, and the native GGUF maximum (`model_info`), in precedence order — so applications stop hardcoding 2048/4096 guesses.
30
30
  - 🔁 **Model-Affinity Scheduling**: `ModelAffinityScheduler` runs multi-model workloads through per-model serial queues with a distinct-model cap (default 1), deepening the already-hot model before loading the next — the anti-thrashing order for `OLLAMA_NUM_PARALLEL`/`OLLAMA_MAX_LOADED_MODELS`-bounded daemons — and routes candidate lists to whichever model is already loaded.
31
31
  - 🛡️ **Agent Loop Guardrails**: `Agent` is a boundary-checked runner out of the box — `maxIterations` (default 10), an opt-in `maxToolCalls` budget, and opt-in **cycle detection** (`maxRepeatedToolCalls`) that fails fast with `OllamaAgentToolLoopError` the moment the model re-emits one identical tool call instead of burning the whole iteration budget on it; tool rejections (including unregistered names) are always encapsulated as `role: 'tool'` results, never loop crashes.
32
+ - 📊 **Standardized Telemetry (`formatTelemetry`)**: One pure call turns Ollama's raw nanosecond counters into the summary humans want — ms latencies, `tokensPerSecond`/`promptTokensPerSecond` per the official Usage-doc formulas, and the KV `cacheHitRatio` — accepting any response object structurally (`chat`, `generate`, stream final events, `embed`), with missing counters reading as `0`, never `NaN`.
33
+ - 🧲 **Dynamic Host Model-Affinity Routing**: With several interchangeable endpoints, opt-in `endpointHealth.modelAffinity` reorders each request's candidates so the host already holding the requested model in VRAM (`GET /api/ps`, TTL-cached, zero added request latency) is tried first — no more forced unload/cold-load swaps under `OLLAMA_MAX_LOADED_MODELS`.
34
+ - 🩺 **Root Liveness Probe (`ping`)**: `client.ping()` is the official ultra-lightweight `HEAD /` health check — single-shot (no retry, no failover: the answer is about one concrete host), resolves instead of throwing, reports latency; `healthCheck()` remains the fleet-wide audit.
32
35
  - 🧼 **Vision History Hygiene**: `sanitizeHistoryForNextTurn()` evicts stale base64 image payloads from consumer-managed multi-turn vision histories — every `/api/chat` request re-sends the whole history, so old images silently bloat payload, context, and heap; the helper keeps images only on the trailing window you choose, conversation text fully preserved.
33
36
  - 🌊 **Web Stream Adapters**: Drop-in adapters (`toTextStream`, `toDataStream`, `toResponse`) for Next.js Route Handlers and Vercel AI SDK.
34
37
  - 📈 **OpenTelemetry Instrumentation**: Automatic spans for HTTP requests, endpoint failover, chat/generate calls, and agent runs — zero-cost when OpenTelemetry isn't installed.
@@ -936,6 +939,11 @@ const client = new OllamaClient({
936
939
  // Active health check probe
937
940
  const health = await client.healthCheck();
938
941
  console.log(health);
942
+
943
+ // Ultra-lightweight single-host liveness probe — the official `HEAD /` root
944
+ // ping (no retry, no failover: an answer about one concrete host).
945
+ const { healthy, latencyMs } = await client.ping();
946
+ console.log(healthy, `${latencyMs}ms`);
939
947
  ```
940
948
 
941
949
  Failover applies to inference calls (`chat`, `generate`, `embed`, `embeddings`,
@@ -1164,6 +1172,64 @@ initial HTTP round trip:
1164
1172
  between turns, outside any `chat()` call, so a slow tool never ties up one of your
1165
1173
  scarce concurrent-request accounts.
1166
1174
 
1175
+ #### Model-affinity routing across hosts (prefer the resident host)
1176
+
1177
+ With several *interchangeable* endpoints serving the same models — the fleet-of-workstations
1178
+ case, not the per-credential Cloud case — sending a request to a host that doesn't currently
1179
+ hold the model forces that host to evict something and cold-load it: the multi-host version
1180
+ of the thrashing `ModelAffinityScheduler` prevents inside one client. Opt in with
1181
+ `endpointHealth.modelAffinity` and each request's candidates are reordered so hosts whose
1182
+ `GET /api/ps` shows the requested model already resident in VRAM are tried first:
1183
+
1184
+ ```typescript
1185
+ const client = new OllamaClient({
1186
+ endpoints: [
1187
+ { name: 'gpu-a', baseUrl: 'http://gpu-a.internal:11434' },
1188
+ { name: 'gpu-b', baseUrl: 'http://gpu-b.internal:11434' },
1189
+ { name: 'gpu-c', baseUrl: 'http://gpu-c.internal:11434' },
1190
+ ],
1191
+ endpointHealth: {
1192
+ strategy: 'least-connections',
1193
+ modelAffinity: { ttlMs: 30_000 }, // /api/ps snapshot freshness (default 30s)
1194
+ },
1195
+ });
1196
+
1197
+ // Optional but recommended at startup: pre-warm the residency cache so even the
1198
+ // first request routes to the host already holding the model.
1199
+ await client.warmModelAffinity();
1200
+
1201
+ await client.chat({ model: 'llama3.2', messages }); // → the host with llama3.2 in VRAM
1202
+
1203
+ // Observability: what each host held, when it was last probed, whether it's fresh.
1204
+ console.log(client.modelAffinityStatus());
1205
+ ```
1206
+
1207
+ The design never trades latency for affinity (see
1208
+ [ADR 0028](./docs/adr/0028-telemetry-normalization-host-affinity-root-ping.md)):
1209
+
1210
+ - **Zero added request latency.** Reordering is synchronous and consults only cached
1211
+ `/api/ps` snapshots. A request never waits for a probe: on a cache miss it proceeds
1212
+ with the unchanged order while a background refresh warms the cache for the next one.
1213
+ - **Partial knowledge suppresses the reorder.** If any candidate's snapshot is stale or
1214
+ unknown (a host was just rebooted, a probe failed), the original order stands —
1215
+ routing on partial residency data risks exactly the cold-load swap this exists to
1216
+ avoid. Probe failures are never cached as data and a 5s backoff keeps a dead host
1217
+ from being re-probed on every request.
1218
+ - **No probes at all unless configured.** Without `modelAffinity`, the router isn't even
1219
+ constructed — zero overhead, and no `/api/ps` traffic.
1220
+ - **Composes with everything above.** Affinity reorders *within* the runnable set:
1221
+ priority tiers, `least-connections` ordering, capacity caps, and `models`-scoped
1222
+ credentials keep working exactly as before, and single-endpoint-pinned operations
1223
+ (model/blob management, `capabilities()`) are never moved to a different host.
1224
+ Residency matching follows Ollama's own name resolution (`llama3` matches
1225
+ `llama3:latest` but never `llama3.1`), shared with context-window discovery so the
1226
+ two features can't disagree about what "loaded" means.
1227
+
1228
+ For the *single-host* counterpart — per-model serial queues that deepen the already-hot
1229
+ model before loading the next one — see
1230
+ [Model-Affinity Scheduling](#model-affinity-scheduling-multi-model-anti-thrashing); the
1231
+ two compose: a scheduler per host, affinity routing between hosts.
1232
+
1167
1233
  ### Client Teardown: `destroy()`
1168
1234
 
1169
1235
  Inside `node:worker_threads` tasks, CLI runners, serverless handlers, and other
@@ -1197,6 +1263,60 @@ returns `0`.
1197
1263
 
1198
1264
  ---
1199
1265
 
1266
+ ### Standardized Telemetry (`formatTelemetry`)
1267
+
1268
+ Ollama reports every duration on its generation responses as an **integer in
1269
+ nanoseconds** (`total_duration`, `load_duration`, `prompt_eval_duration`, `eval_duration`)
1270
+ alongside token counters (`prompt_eval_count`, `prompt_eval_cached_count`, `eval_count`).
1271
+ Turning those into the numbers humans actually want — milliseconds, tokens/second, cache
1272
+ hit rate — is the same division-and-rounding math every consumer would otherwise
1273
+ hand-roll (and the easy mistakes are real: `NaN` on missing counters, integer division,
1274
+ a cache ratio that divides by the wrong denominator). `formatTelemetry` is that math,
1275
+ once, with the official Usage-doc formulas:
1276
+
1277
+ ```typescript
1278
+ import { OllamaClient, formatTelemetry } from '@nemesis-oss/ollama-sdk';
1279
+
1280
+ const client = new OllamaClient();
1281
+
1282
+ const res = await client.chat({
1283
+ model: 'llama3.2',
1284
+ messages: [{ role: 'user', content: 'Why is the sky blue?' }],
1285
+ });
1286
+
1287
+ // Any response object works as-is — chat, generate, the final stream event,
1288
+ // embed. No plucking required: the counters are read structurally.
1289
+ const t = formatTelemetry(res);
1290
+ console.log(t);
1291
+ // {
1292
+ // totalLatencyMs: 3712.5, // total_duration / 1e6, 2 decimals
1293
+ // modelLoadMs: 250, // cold-load into VRAM (0 when resident)
1294
+ // promptEvalMs: 1000, // prompt pre-fill
1295
+ // generationMs: 2400, // token generation
1296
+ // tokensPerSecond: 50, // eval_count / (eval_duration / 1e9) — official formula
1297
+ // promptTokensPerSecond: 200, // prompt_eval_count / (prompt_eval_duration / 1e9)
1298
+ // cacheHitRatio: 0.429 // cached / (cached + evaluated), 3 decimals
1299
+ // }
1300
+ ```
1301
+
1302
+ Two behaviors worth knowing:
1303
+
1304
+ - **Missing counters read as `0`** — partial payloads (stream final events, older
1305
+ servers without `prompt_eval_cached_count`, embeddings) format cleanly instead of
1306
+ producing `NaN`/`Infinity`, and zero durations never divide into rates.
1307
+ - **`cacheHitRatio` uses `cached / (cached + evaluated)`**, not
1308
+ `cached / prompt_eval_count`: Ollama reports `prompt_eval_count: 0` on a *full* cache
1309
+ hit, so dividing by it alone would read a perfect cache as "no caching at all". This
1310
+ is the same semantics as [`ConversationSession`'s
1311
+ `cacheStats.hitRate`](#kv-cache-aware-conversation-sessions), so the two surfaces can
1312
+ never disagree.
1313
+
1314
+ `formatTelemetry` is pure — no fetching, no throwing, no mutation — so it drops
1315
+ straight into log lines, dashboards, and streaming pipelines alike. For span-based
1316
+ instrumentation of requests themselves, see
1317
+ [Observability with OpenTelemetry](#observability-with-opentelemetry) below; the two
1318
+ compose (spans for *where/when*, `formatTelemetry` for *how fast*).
1319
+
1200
1320
  ### Observability with OpenTelemetry
1201
1321
 
1202
1322
  The client automatically emits [OpenTelemetry](https://opentelemetry.io/) spans for HTTP
@@ -1,4 +1,4 @@
1
- import { O as OllamaRuntime, H as HttpClient, A as AbortableAsyncIterable, af as SseEvent, y as OllamaClientError } from './runtime-CCm4CtU_.js';
1
+ import { O as OllamaRuntime, H as HttpClient, A as AbortableAsyncIterable, af as SseEvent, y as OllamaClientError } from './runtime-CIQYCRL3.js';
2
2
 
3
3
  /**
4
4
  * AUTO-GENERATED by `npm run contract:generate`. DO NOT EDIT.
@@ -1,4 +1,4 @@
1
- import { O as OllamaRuntime, H as HttpClient, A as AbortableAsyncIterable, af as SseEvent, y as OllamaClientError } from './runtime-DTtWCxDs.cjs';
1
+ import { O as OllamaRuntime, H as HttpClient, A as AbortableAsyncIterable, af as SseEvent, y as OllamaClientError } from './runtime-DmI1cOEq.cjs';
2
2
 
3
3
  /**
4
4
  * AUTO-GENERATED by `npm run contract:generate`. DO NOT EDIT.
@@ -1,4 +1,4 @@
1
- import { l as ToolDefinition, i as ToolCall, n as Message } from './types-BtQexFpT.js';
1
+ import { l as ToolDefinition, i as ToolCall, n as Message } from './types-B57ZZfp3.js';
2
2
  import { z } from 'zod';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { l as ToolDefinition, i as ToolCall, n as Message } from './types-BtQexFpT.cjs';
1
+ import { l as ToolDefinition, i as ToolCall, n as Message } from './types-B57ZZfp3.cjs';
2
2
  import { z } from 'zod';
3
3
 
4
4
  /**
@@ -1,8 +1,8 @@
1
- import { O as OpenAIChatCompletionRequest, a as OpenAIChatCompletionResponse, b as OpenAIChatCompletionChunk, c as OpenAICompletionRequest, d as OpenAICompletionResponse, e as OpenAICompletionChunk, f as OpenAIEmbeddingRequest, g as OpenAIEmbeddingResponse, h as OpenAIListModelsResponse, i as OpenAIModelItem, j as OpenAIResponsesRequest, k as OpenAIResponsesResponse, l as OpenAIResponsesStreamEvent, A as AnthropicMessagesRequest, m as AnthropicMessagesResponse, n as AnthropicMessageStreamEvent } from './anthropic-DinrABof.cjs';
2
- export { N as NativeApi } from './anthropic-DinrABof.cjs';
3
- import { O as OllamaRuntime } from './runtime-DTtWCxDs.cjs';
4
- export { a as OperationDefinition } from './runtime-DTtWCxDs.cjs';
5
- import './types-BtQexFpT.cjs';
1
+ import { O as OpenAIChatCompletionRequest, a as OpenAIChatCompletionResponse, b as OpenAIChatCompletionChunk, c as OpenAICompletionRequest, d as OpenAICompletionResponse, e as OpenAICompletionChunk, f as OpenAIEmbeddingRequest, g as OpenAIEmbeddingResponse, h as OpenAIListModelsResponse, i as OpenAIModelItem, j as OpenAIResponsesRequest, k as OpenAIResponsesResponse, l as OpenAIResponsesStreamEvent, A as AnthropicMessagesRequest, m as AnthropicMessagesResponse, n as AnthropicMessageStreamEvent } from './anthropic-Did0lQxP.cjs';
2
+ export { N as NativeApi } from './anthropic-Did0lQxP.cjs';
3
+ import { O as OllamaRuntime } from './runtime-DmI1cOEq.cjs';
4
+ export { a as OperationDefinition } from './runtime-DmI1cOEq.cjs';
5
+ import './types-B57ZZfp3.cjs';
6
6
  import 'zod';
7
7
 
8
8
  /**
@@ -1,8 +1,8 @@
1
- import { O as OpenAIChatCompletionRequest, a as OpenAIChatCompletionResponse, b as OpenAIChatCompletionChunk, c as OpenAICompletionRequest, d as OpenAICompletionResponse, e as OpenAICompletionChunk, f as OpenAIEmbeddingRequest, g as OpenAIEmbeddingResponse, h as OpenAIListModelsResponse, i as OpenAIModelItem, j as OpenAIResponsesRequest, k as OpenAIResponsesResponse, l as OpenAIResponsesStreamEvent, A as AnthropicMessagesRequest, m as AnthropicMessagesResponse, n as AnthropicMessageStreamEvent } from './anthropic-CfricAhK.js';
2
- export { N as NativeApi } from './anthropic-CfricAhK.js';
3
- import { O as OllamaRuntime } from './runtime-CCm4CtU_.js';
4
- export { a as OperationDefinition } from './runtime-CCm4CtU_.js';
5
- import './types-BtQexFpT.js';
1
+ import { O as OpenAIChatCompletionRequest, a as OpenAIChatCompletionResponse, b as OpenAIChatCompletionChunk, c as OpenAICompletionRequest, d as OpenAICompletionResponse, e as OpenAICompletionChunk, f as OpenAIEmbeddingRequest, g as OpenAIEmbeddingResponse, h as OpenAIListModelsResponse, i as OpenAIModelItem, j as OpenAIResponsesRequest, k as OpenAIResponsesResponse, l as OpenAIResponsesStreamEvent, A as AnthropicMessagesRequest, m as AnthropicMessagesResponse, n as AnthropicMessageStreamEvent } from './anthropic-CKp5TmAP.js';
2
+ export { N as NativeApi } from './anthropic-CKp5TmAP.js';
3
+ import { O as OllamaRuntime } from './runtime-CIQYCRL3.js';
4
+ export { a as OperationDefinition } from './runtime-CIQYCRL3.js';
5
+ import './types-B57ZZfp3.js';
6
6
  import 'zod';
7
7
 
8
8
  /**
@@ -1,6 +1,6 @@
1
- export { I as InvokeRequest, O as OllamaRuntime, b as OllamaRuntimeOptions, a as OperationDefinition, S as SchemaRef } from './runtime-DTtWCxDs.cjs';
1
+ export { I as InvokeRequest, O as OllamaRuntime, b as OllamaRuntimeOptions, a as OperationDefinition, S as SchemaRef } from './runtime-DmI1cOEq.cjs';
2
2
  import { z } from 'zod';
3
- import './types-BtQexFpT.cjs';
3
+ import './types-B57ZZfp3.cjs';
4
4
 
5
5
  /**
6
6
  * AUTO-GENERATED by `npm run contract:generate`. DO NOT EDIT.
@@ -1,6 +1,6 @@
1
- export { I as InvokeRequest, O as OllamaRuntime, b as OllamaRuntimeOptions, a as OperationDefinition, S as SchemaRef } from './runtime-CCm4CtU_.js';
1
+ export { I as InvokeRequest, O as OllamaRuntime, b as OllamaRuntimeOptions, a as OperationDefinition, S as SchemaRef } from './runtime-CIQYCRL3.js';
2
2
  import { z } from 'zod';
3
- import './types-BtQexFpT.js';
3
+ import './types-B57ZZfp3.js';
4
4
 
5
5
  /**
6
6
  * AUTO-GENERATED by `npm run contract:generate`. DO NOT EDIT.