@nemesis-oss/ollama-sdk 1.9.0 → 1.11.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 +68 -0
- package/README.md +242 -2
- package/dist/{anthropic-5oYIRS6D.d.ts → anthropic-CfricAhK.d.ts} +1 -1
- package/dist/{anthropic-BIh45UXj.d.cts → anthropic-DinrABof.d.cts} +1 -1
- package/dist/{compose-DCVYMvOL.d.ts → compose-BQYXdpar.d.ts} +1 -1
- package/dist/{compose-Dj6FdF2n.d.cts → compose-lt-Qz3lI.d.cts} +1 -1
- package/dist/generated-api.d.cts +5 -5
- package/dist/generated-api.d.ts +5 -5
- 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.map +1 -1
- package/dist/index.cjs +787 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +780 -97
- package/dist/index.d.ts +780 -97
- package/dist/index.js +771 -97
- package/dist/index.js.map +1 -1
- package/dist/mcp-generated.d.cts +2 -2
- package/dist/mcp-generated.d.ts +2 -2
- package/dist/{runtime-C3rfpkZw.d.ts → runtime-CCm4CtU_.d.ts} +29 -2
- package/dist/{runtime-D2W9TfCJ.d.cts → runtime-DTtWCxDs.d.cts} +29 -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-DVcX_zMp.d.cts → types-BtQexFpT.d.cts} +5 -2
- package/dist/{types-DVcX_zMp.d.ts → types-BtQexFpT.d.ts} +5 -2
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.11.0] — Documentation digest + production-readiness audit: context discovery, compaction, affinity scheduling, agent cycle detection, URL-join hardening, vision-history hygiene
|
|
4
|
+
|
|
5
|
+
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).
|
|
6
|
+
|
|
7
|
+
### Dynamic context-window discovery (`src/context-discovery.ts` + `models.getContextLength()`)
|
|
8
|
+
|
|
9
|
+
- **`client.models.getContextLength({ model, skipRunningCheck?, signal?, timeoutMs? })`** resolves the real window instead of 2048/4096 guesswork, by precedence: the **allocated window of the running instance** (`GET /api/ps` `context_length` — exact, reflects the Modelfile default and what fit in memory) → the **Modelfile `num_ctx` default** (`POST /api/show` `parameters`) → the **native GGUF maximum** (`model_info["<arch>.context_length"]` — a ceiling, not an expectation; the official API examples show 131072 native vs 4096 allocated) → the conservative 2048 fallback.
|
|
10
|
+
- Returns every signal it found — `{ contextLength, source, runningContextLength?, parameterContextLength?, nativeContextLength? }` — so "how much headroom could I raise" and "what do I have right now" are both answered. Tag-less model names match their tagged `/api/ps` entries the way Ollama itself resolves them; a 404 from `/api/ps` degrades to the `/api/show` signals instead of failing.
|
|
11
|
+
- Pure pieces exported for callers holding raw responses: `resolveContextLength`, `extractParameterNumCtx`, `findRunningModelContextLength`, `extractNativeContextLength` (the existing capabilities scanner, now public). `ps()` also gained optional `{ signal, timeoutMs }` cancellation; `client.getContextLength` mirrors the models method.
|
|
12
|
+
|
|
13
|
+
### Sliding-window conversation compaction (`compactConversationHistory` + `session.compact()`)
|
|
14
|
+
|
|
15
|
+
- **`compactConversationHistory(messages, { maxEstimatedTokens, reserveForReply?, minTailMessages? })`** — pure helper keeping the leading system message(s) plus the newest turns that fit, dropping the oldest in between. Estimates via the same CJK-aware heuristic as the pre-flight checks (message overhead, `tool_calls`, `IMAGE_TOKEN_ESTIMATE` per image included); `minTailMessages` (default 2) guarantees the newest exchange survives even when oversized — the SDK never reproduces the server's silent truncation.
|
|
16
|
+
- **`session.compact(options?)`** applies it in place, defaulting the budget to the session's `num_ctx` (or the 2048 fallback) minus a 10% reply reservation, and returns `{ droppedMessages, estimatedTokensBefore, estimatedTokensAfter, effectiveBudget }`. Cumulative cache tallies are deliberately never reset — the one-turn `evaluatedTokens` spike after compaction is the visible cost of the KV-prefix invalidation, and compaction stays **manual, never automatic** (see ADR 0026 for the tradeoff).
|
|
17
|
+
|
|
18
|
+
### Model-affinity scheduling (`src/affinity.ts` + `ModelAffinityScheduler`)
|
|
19
|
+
|
|
20
|
+
- Groups async work into **per-model serial queues** with a **distinct-model cap** (`concurrentModels`, default 1) and **per-model parallelism** (`perModelConcurrency`, default 1 — mirror `OLLAMA_NUM_PARALLEL`). Dispatch is **affinity-sticky**: a queued model that is already active deepens before the next model loads, because deepening avoids an unload/cold-load swap — the anti-thrashing order for `OLLAMA_MAX_LOADED_MODELS`-bounded daemons.
|
|
21
|
+
- **Candidate lists** — `run(['a', 'b'], (model) => …)` picks whichever candidate is already loaded per a TTL-cached `GET /api/ps` (default 30s); single-model tasks never touch `/api/ps`, and a failing lookup degrades to the first candidate without caching the failure.
|
|
22
|
+
- Tasks are caller-owned (no retry/timeout/failover injected); a rejected task rejects only its own `run()`. `stats` exposes `{ activeModels, queuedTasks }`; `dispose()` resolves once every queue drains; invalid options and candidate lists fail fast with `OllamaClientError`.
|
|
23
|
+
|
|
24
|
+
### Capacity-planning documentation
|
|
25
|
+
|
|
26
|
+
- New README section mapping the official FAQ's server knobs — `OLLAMA_NUM_PARALLEL` (KV memory scales `NUM_PARALLEL × CONTEXT_LENGTH`), `OLLAMA_MAX_LOADED_MODELS` (3× GPUs), `OLLAMA_MAX_QUEUE` (512 → 503s), `num_ctx` — to their client-side counterparts (`endpointHealth.maxConcurrentPerEndpoint`, `embedBatch`, `ModelAffinityScheduler`, `ToolRegistry.maxConcurrency`, `getContextLength` + pre-flight + compaction), with a note on `OLLAMA_KV_CACHE_TYPE`. One audit-digest claim was stale and is documented as already-covered instead: the SDK's request path has capped and queued per endpoint since `endpointHealth` landed — `maxConcurrentRequests`-style pooling exists as `maxConcurrentPerEndpoint`.
|
|
27
|
+
|
|
28
|
+
### Agent cycle detection (`Agent` `maxRepeatedToolCalls`) — AGN-01
|
|
29
|
+
|
|
30
|
+
- Audit verification first: `Agent` was already a boundary-checked runner — `maxIterations` (default 10) with `OllamaAgentMaxIterationsError`, opt-in `maxToolCalls`, and registry-side encapsulation of every tool failure (unregistered names, argument-validation failures, timeouts, thrown errors) as failed `ToolExecutionResult`s fed back as `role: 'tool'` messages — the loop never crashes on a rejection. The real gap: a _stuck_ model (re-emitting one identical call, ignoring its own results) was indistinguishable from a slow one and burned the whole iteration budget with a generic error.
|
|
31
|
+
- **`AgentConfig.maxRepeatedToolCalls`** (opt-in, like `maxToolCalls`): a per-signature execution budget. Identity is the **canonical signature** — `canonicalToolCallSignature()` (newly exported) renders `name(args)` with recursively key-sorted arguments, so key reordering never splits one repeated call into several, while progressing calls (different arguments) never trip. Failed, unregistered, and timed-out executions count: re-calling a failing tool with unchanged arguments is exactly the loop this catches.
|
|
32
|
+
- Enforcement is batch-preflight, mirroring `maxToolCalls`: checked before the batch executes and before `onToolCallStart` fires (hook pairing stays consistent; duplicate calls within one batch see each other). Exceeding the budget throws **`OllamaAgentToolLoopError`** (`code: 'agent_tool_loop_detected'`, never retryable) with `toolName`, `repeatedExecutions`, `maxRepeatedToolCalls`, and the canonical `signature` truncated at 200 chars — a fail-fast diagnosis at turn N+1 instead of a generic burnout at `maxIterations`.
|
|
33
|
+
- 19 new tests: signature canonicalization (key-order invariance, array-order significance), off-by-default behavior preserved, fail-fast economics (3 model turns instead of 10), distinct-argument progression, within-batch duplicates, failed/unregistered executions counting, hook pairing, error hierarchy and truncation, `RangeError` validation — plus the audit's checklist item: an **end-to-end mock-server test** proving an unregistered tool name is encapsulated as a failed tool result, fed back to the model, and the run converges.
|
|
34
|
+
|
|
35
|
+
### Reverse-proxy subpath hardening (`src/transport/url.ts`) — URL-01
|
|
36
|
+
|
|
37
|
+
- Audit verification first: the claimed `new URL(path, base)` dispatch never existed — `HttpClient` always concatenated `baseUrl + path` and `normalizeBaseUrl` always preserved mount prefixes (unit-tested since the failover work). The real gaps: the exactly-one-slash join invariant was implicit (a future path without its leading slash would silently produce `hostapi/chat`), and nothing proved gateway subpaths end-to-end on the wire.
|
|
38
|
+
- **`joinUrlPath(baseUrl, path)`** now owns the join for all three `HttpClient` request methods (`request`, `requestSseStream`, `requestStream`): collapses trailing/leading slashes, joins with exactly one slash, preserves query strings — byte-identical output for every well-formed input, hardened against malformed ones. The module documents the WHY at the point of use: WHATWG `new URL('/api/chat', 'https://gw/ai/ollama')` discards the `/ai/ollama` mount; the SDK never constructs request URLs that way.
|
|
39
|
+
- 16 new tests pin the behavior at three levels — `joinUrlPath` units (including the audit's exact `https://gateway.internal.corp/ai/ollama` scenario and a WHATWG-hazard regression test), `HttpClient` transport URLs (incl. query-string paths and `requestStream`), and end-to-end `OllamaClient` wire URLs for `/api/chat`, `/api/generate`, OpenAI-compat `/v1/chat/completions`, and scheme-less subpath hosts (`proxy.internal:8080/ollama/`). README gained a "Hosting Behind a Reverse Proxy" section.
|
|
40
|
+
|
|
41
|
+
### Vision-history image eviction (`sanitizeHistoryForNextTurn`) — CTX-01
|
|
42
|
+
|
|
43
|
+
- Audit verification first: every mutation claim was false — `Agent` copies `input.messages`, `ConversationSession` freezes and copies on read, `client.chat` maps encoded messages into new arrays, `withEncodedMessageImages` is allocation-free on passthrough. The real gap: consumer-managed vision histories had no way to evict stale image payloads, and `/api/chat` is stateless — every prior base64 image is re-sent and re-billed (context tokens, upload bytes, heap) on every turn, forever.
|
|
44
|
+
- **`sanitizeHistoryForNextTurn(messages, { keepImagesOnLastMessages?, imagePlaceholder? })`** — pure helper returning a copy with `images` evicted outside a trailing keep-window (default 1: the rolling one-image window), conversation text fully preserved, optional placeholder note so the model can tell an image used to exist. Input arrays never mutated; untouched and kept messages reused by reference.
|
|
45
|
+
- Same philosophy as compaction (ADR 0026): **caller-initiated, never automatic**, because the tradeoffs are workload-specific — the model loses access to evicted images, and eviction invalidates the KV prompt prefix from that point. 12 new tests: default eviction + text preservation, purity and reference-stability, keep-windows (0/N/negative clamp), placeholder behavior (incl. empty content), empty-`images` and `Uint8Array` passthrough, and a wire-level proof that a sanitized history sent through `client.chat` carries no stale base64 while the trailing image survives.
|
|
46
|
+
|
|
47
|
+
## [1.10.0] — Production-readiness audit: batched embedding pipeline, client teardown, type-declaration hardening
|
|
48
|
+
|
|
49
|
+
Three findings from the daily production-readiness audit (see [ADR 0025](./docs/adr/0025-embedding-batching-client-teardown-declaration-portability.md)) — all additive, no breaking changes; 749 pre-existing tests stay green, 29 new tests added.
|
|
50
|
+
|
|
51
|
+
### Batch-constrained embedding pipeline (`src/embed-batch.ts` + `client.embedBatch()`) — EMB-01
|
|
52
|
+
|
|
53
|
+
- **`client.embedBatch({ model, input, batchSize?, concurrency?, … })`** for high-volume RAG/vector ingestion: splits any corpus into bounded `/api/embed` batches (defaults: 32 inputs × 3 in flight) instead of `Promise.all` floods that OOM local daemons, contend sockets, and saturate `OLLAMA_MAX_QUEUE` (503s).
|
|
54
|
+
- **Order-preserving** — `embeddings[i]` always corresponds to `input[i]` regardless of batch completion order; safe to zip straight into a vector store.
|
|
55
|
+
- **Fail-fast** — the first batch error aborts its in-flight siblings (each still riding the client's full failover/retry/auth/telemetry pipeline) and rejects the whole operation with the _original_ error, so a half-indexed corpus never looks like success. Caller `signal` cancels queued and in-flight batches alike (`code: 'aborted'`).
|
|
56
|
+
- **Per-string context-window pre-flight** — Ollama _silently truncates_ embedding inputs longer than `num_ctx`; `embedBatch()` injects `defaultContextLength` as `num_ctx` and warns (or throws under `onContextOverflow: 'throw'`) with the offending indexes _before_ any request is sent. No margin, unlike chat/generate: an embedding prompt is the whole input.
|
|
57
|
+
- `onBatchComplete(done, total)` progress callback; `truncate`/`dimensions`/`keep_alive`/`options`/`timeoutMs` pass through per batch; new exports `batchEmbed`, `findOversizedEmbedInputs`, `embedBatchOverflowMessage`, `DEFAULT_EMBED_BATCH_SIZE`, `DEFAULT_EMBED_CONCURRENCY` + types.
|
|
58
|
+
|
|
59
|
+
### Client teardown — `OllamaClient.destroy(reason)` — THD-01
|
|
60
|
+
|
|
61
|
+
- One call aborts **every in-flight request, active stream, and queued capacity waiter** with `OllamaAbortError` (`code: 'aborted'`, message = `reason`) — the clean-exit path for `node:worker_threads`, CLI runners, and short-lived processes where dangling fetch bodies and unconsumed stream readers keep the event loop alive.
|
|
62
|
+
- Streams reject their `finalResult` and release their `maxConcurrentPerEndpoint` slots via the existing `holdUntil` release path; scopes deregister the moment their work settles, so `destroy()` can tear down a stream mid-consumption but never outlives finished work.
|
|
63
|
+
- Idempotent (repeat calls return `0`) and a drain, not a disable — the client stays usable afterward. Returns the number of aborted operations. Covers every surface that goes through `executeWithFailover`/`executeCloudRequest`: chat/generate/embed (+Batch), models, responses bridge, sessions, agent, usage/balance, web tools.
|
|
64
|
+
|
|
65
|
+
### Type-declaration portability hardening — TYP-03
|
|
66
|
+
|
|
67
|
+
- Verified (not just assumed) the dual-packaging story: `@arethetypeswrong/cli` reports zero problems across node10/node16-CJS/node16-ESM/bundler for every entry point, and the exports map already maps `import → .d.ts` / `require → .d.cts` per subpath.
|
|
68
|
+
- **New `scripts/verify-consumer-types.sh`** (also in CI and `verify:release`): compiles two _real_ consumer projects against the packed tarball — a CommonJS consumer under `--module node16` (the `require` condition, exactly the TS1479 "masquerading ESM types" scenario) and an ESM consumer under `--module nodenext`.
|
|
69
|
+
- **Fixed a real leak it caught**: `VisionInput` included Node's `Buffer` global, so strict consumers without `@types/node` could not compile against our declarations. Now `string | Uint8Array` — Node Buffers are `Uint8Array` subclasses and remain fully accepted (13 vision tests untouched and green) — the published declarations are free of Node ambient globals.
|
|
70
|
+
|
|
3
71
|
## [1.9.0] — Digest upgrades: vision resolver, dual-mode Responses bridge, KV-cache sessions, context safety, blob publishing, cloud usage & balance
|
|
4
72
|
|
|
5
73
|
Five upgrades closing the gaps surfaced by the official Ollama documentation review (see [ADR 0024](./docs/adr/0024-digest-upgrades-vision-responses-sessions-context-blobs.md)) — plus a second-pass recheck against the current official docs (see the last section) that added the Ollama Cloud account endpoints and a missing `/api/create` field. All additive — no breaking changes; 689 pre-existing tests stay green, 60 new tests added.
|
package/README.md
CHANGED
|
@@ -21,14 +21,20 @@
|
|
|
21
21
|
- 🔎 **Ollama Cloud Web Tools**: `webSearch`/`webFetch` wrap Ollama's hosted `/api/web_search` and `/api/web_fetch` tools at `ollama.com` (requires an `OLLAMA_API_KEY`), independent of any local `baseUrl`.
|
|
22
22
|
- 💳 **Ollama Cloud Usage & Balance**: `usage()`/`balance()` wrap Ollama's hosted account endpoints (`GET /api/usage`, `GET /api/balance`) — request counts, USD spend, cached-token totals bucketed by hour/day, and remaining included/purchased credits (including the legacy session/weekly plan shapes) — with the same fixed-cloud-host, API-key, timeout, and retry semantics as the web tools.
|
|
23
23
|
- 🌉 **OpenAI & Anthropic Compatibility Bridges**: Built-in clients for `/v1/chat/completions`, `/v1/responses`, `/v1/models`, and `/v1/messages`, including `reasoning_effort`/`reasoning.effort` for thinking models — plus an ergonomic dual-mode `client.responses.create()` bridge that prefers native `/v1/responses` and transparently re-issues via `/api/chat` on older servers (pre-v0.13.3).
|
|
24
|
-
- 💬 **KV-Cache-Aware Conversation Sessions**: `client.session(model, systemPrompt)` keeps an append-only, prefix-stable history that maximizes Ollama's KV-cache reuse across turns,
|
|
24
|
+
- 💬 **KV-Cache-Aware Conversation Sessions**: `client.session(model, systemPrompt)` keeps an append-only, prefix-stable history that maximizes Ollama's KV-cache reuse across turns, surfaces per-turn + cumulative cache hit rates (`prompt_eval_cached_count`) so cache degradation is visible instead of silent, and offers a one-call `compact()` sliding-window escape hatch when a session outgrows its window.
|
|
25
25
|
- 🛑 **Context-Window Safety**: Heuristic client-side token estimation warns (or throws, `onContextOverflow: 'throw'`) before a request is sent when the prompt approaches the effective `num_ctx` window — Ollama's default behavior is to _silently truncate_ oversized prompts — and `defaultContextLength` makes the window explicit on every request.
|
|
26
26
|
- 📦 **Blob & Custom Model Publishing**: Content-addressed blob management per Ollama's documented protocol — `computeBlobDigest()` (SHA-256 → `sha256:<hex>`), `createBlobFromData()`/`createBlobFromFile()` (HEAD-check + upload, skipping existing blobs), and one-shot `createModelFromGguf()` (upload GGUF shard blobs, then `/api/create` with `files: {name: digest}`).
|
|
27
|
+
- 🧵 **Batched Embeddings with Backpressure**: `client.embedBatch()` splits corpora of any size into bounded `/api/embed` batches (default 32 inputs × 3 in flight) — order-preserving, fail-fast, progress-reporting — so RAG/vector ingestion can't OOM a local daemon or saturate `OLLAMA_MAX_QUEUE` the way `Promise.all` floods do, with per-string context-window pre-flight against silent truncation.
|
|
28
|
+
- 🧹 **Client Teardown (`destroy()`)**: One call aborts every in-flight request, active stream, and queued capacity waiter with `OllamaAbortError` — the clean-exit path for `worker_threads`, CLI runners, and short-lived scripts where dangling fetch bodies keep the event loop alive.
|
|
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
|
+
- 🔁 **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
|
+
- 🛡️ **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
|
+
- 🧼 **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.
|
|
27
33
|
- 🌊 **Web Stream Adapters**: Drop-in adapters (`toTextStream`, `toDataStream`, `toResponse`) for Next.js Route Handlers and Vercel AI SDK.
|
|
28
34
|
- 📈 **OpenTelemetry Instrumentation**: Automatic spans for HTTP requests, endpoint failover, chat/generate calls, and agent runs — zero-cost when OpenTelemetry isn't installed.
|
|
29
35
|
- 📊 **Client-Side Quota Monitoring**: `QuotaManager` tracks token/request usage against budgets you configure across rolling windows (e.g. Ollama Cloud's 5-hour session / 7-day weekly resets) and fails fast with `OllamaQuotaExceededError` before a request is sent.
|
|
30
36
|
- ⚡ **Edge Runtime Verified**: CI bundles and runs the client in a real Edge Runtime sandbox (Cloudflare Workers/Vercel Edge-compatible) with zero Node.js APIs.
|
|
31
|
-
- 📦 **Dual ESM & CJS Build**: Full module support with
|
|
37
|
+
- 📦 **Dual ESM & CJS Build**: Full module support with paired `.d.ts`/`.d.cts` declarations mapped through conditional `exports` — verified in CI by `@arethetypeswrong/cli` **and** by compiling real CommonJS (node16) and ESM (nodenext) consumer projects against the packed tarball.
|
|
32
38
|
- 🧩 **Contract-First Architecture**: A single canonical IR (`contracts/ir/ollama.ir.json`) drives TypeScript interfaces, generated API classes (`NativeApi`/`OpenAIApi`/`AnthropicApi`), MCP tool descriptors, Zod schemas, and field-level parity verification. New Ollama endpoints (like `/v1/systemone`) are caught automatically by bidirectional endpoint discovery. See [ADRs 0013-0019](./docs/adr/README.md).
|
|
33
39
|
|
|
34
40
|
---
|
|
@@ -188,6 +194,21 @@ npm install @nemesis-oss/ollama-sdk zod
|
|
|
188
194
|
|
|
189
195
|
`zod` is a peer dependency (`^3.22.0 || ^4.0.0`) — install whichever major version your project already uses instead of getting a second copy bundled in.
|
|
190
196
|
|
|
197
|
+
### Hosting Behind a Reverse Proxy (subpath mounts)
|
|
198
|
+
|
|
199
|
+
Point `baseUrl` (or `OLLAMA_HOST`) at the mount point and every request path joins underneath it — `/api/chat`, the OpenAI/Anthropic compatibility routes (`/v1/...`), streaming, and generated-surface operations all preserve the prefix:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// Ollama behind https://gateway.internal.corp/ai/ollama →
|
|
203
|
+
// requests go to https://gateway.internal.corp/ai/ollama/api/chat, etc.
|
|
204
|
+
const client = new OllamaClient({ baseUrl: 'https://gateway.internal.corp/ai/ollama' });
|
|
205
|
+
|
|
206
|
+
// Scheme-less gateway hosts with subpaths normalize too:
|
|
207
|
+
// 'proxy.internal:8080/ollama' → http://proxy.internal:8080/ollama/api/chat
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The transport deliberately never uses `new URL(path, base)` — WHATWG semantics discard the base's path segments for absolute paths (`new URL('/api/chat', 'https://gw/ai/ollama')` → `https://gw/api/chat`). URL assembly is owned by a single join helper with an exactly-one-slash invariant, pinned by tests at the unit, transport, and client levels (see `src/transport/url.ts`).
|
|
211
|
+
|
|
191
212
|
---
|
|
192
213
|
|
|
193
214
|
## Quick Start
|
|
@@ -318,6 +339,125 @@ const client = new OllamaClient({
|
|
|
318
339
|
|
|
319
340
|
The estimators are exported for custom pipelines: `estimateTokens(text)` (CJK-aware — ~1 token per CJK character, ~4 chars/token elsewhere), `estimateChatRequestTokens(req)` / `estimateGenerateRequestTokens(req)` (message overhead + tool schemas + `IMAGE_TOKEN_ESTIMATE` per image), and the underlying `checkChatContext` / `checkGenerateContext` / `contextWarningMessage`. All are heuristics (±20–30%) — for exact counts, ask the server (`prompt_eval_count`).
|
|
320
341
|
|
|
342
|
+
### Discovering the Real Context Window
|
|
343
|
+
|
|
344
|
+
Guessing context windows ("it's probably 2048… or 4096?") is how silent truncation happens. Ollama advertises the real numbers in two places, and they answer _different questions_: `GET /api/ps` reports the window the **running instance actually allocated** (exact, reflects the Modelfile `num_ctx` default and what fit in memory), while `POST /api/show` exposes the Modelfile's `num_ctx` default _and_ the model's **native GGUF maximum** in `model_info["<architecture>.context_length"]` — the official API examples show a model with a 131072-token native max whose running instance allocated 4096, a 32× gap. `getContextLength()` consults them in precedence order and returns every signal it found:
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
const window = await client.models.getContextLength({ model: 'gemma4' });
|
|
348
|
+
// -> { contextLength: 4096, // program against this — resolved by precedence
|
|
349
|
+
// source: 'running', // 'running' | 'parameters' | 'model-info' | 'fallback'
|
|
350
|
+
// runningContextLength: 4096, // allocated by the loaded instance (when loaded)
|
|
351
|
+
// nativeContextLength: 131072 } // the ceiling you could raise num_ctx toward
|
|
352
|
+
|
|
353
|
+
// The canonical wiring — make the client's own pre-flight checks exact:
|
|
354
|
+
const client = new OllamaClient({ defaultContextLength: window.contextLength });
|
|
355
|
+
|
|
356
|
+
// Or raise the window deliberately when the model supports it (native max):
|
|
357
|
+
await client.chat({
|
|
358
|
+
model: 'gemma4',
|
|
359
|
+
messages,
|
|
360
|
+
options: { num_ctx: window.nativeContextLength }, // 131072 — needs VRAM to match
|
|
361
|
+
});
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
`skipRunningCheck: true` skips the `/api/ps` round-trip (e.g. cloud/compat-only endpoints); a 404 from `/api/ps` is treated as "not running" and never fails the lookup. The pure pieces — `resolveContextLength()`, `extractParameterNumCtx()`, `findRunningModelContextLength()`, `extractNativeContextLength()` — are exported for callers that already hold `ps`/`show` responses.
|
|
365
|
+
|
|
366
|
+
### Compacting Long Conversations
|
|
367
|
+
|
|
368
|
+
Sessions grow monotonically; windows don't. When `cacheStats.hitRate` collapses while history grows — or the pre-flight warnings above start firing — `compact()` is the explicit fix: it keeps the pinned system prompt plus the most recent turns that fit the budget, dropping the oldest turns in between.
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
const session = client.session('llama3.1', 'You are terse.', {
|
|
372
|
+
options: { num_ctx: 4096 },
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// …many turns later…
|
|
376
|
+
const result = session.compact();
|
|
377
|
+
// -> { droppedMessages: 14, estimatedTokensBefore: 4180,
|
|
378
|
+
// estimatedTokensAfter: 3552, effectiveBudget: 3686 } // num_ctx − 10% reply reserve
|
|
379
|
+
|
|
380
|
+
// Or compact any message array with an explicit budget (the pure helper):
|
|
381
|
+
import { compactConversationHistory } from '@nemesis-oss/ollama-sdk';
|
|
382
|
+
const kept = compactConversationHistory(session.getMessages(), {
|
|
383
|
+
maxEstimatedTokens: 4096,
|
|
384
|
+
reserveForReply: 512, // headroom for the model's next reply
|
|
385
|
+
minTailMessages: 2, // never drop the latest exchange (default)
|
|
386
|
+
});
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Compaction is deliberately **manual, never automatic**: rewriting the history invalidates the prompt prefix, so the next turn starts with a cold KV cache (visible as a one-turn `evaluatedTokens` spike in `cacheStats`). That recompute-for-a-fitting-window tradeoff is sometimes exactly right and sometimes wasteful — the SDK surfaces the numbers and leaves the call to you. Estimates use the same CJK-aware heuristic as the pre-flight checks (tool calls and images included); `minTailMessages` (default 2) guarantees the newest exchange survives even when oversized.
|
|
390
|
+
|
|
391
|
+
### Evicting Stale Images from Vision Histories
|
|
392
|
+
|
|
393
|
+
`/api/chat` is stateless — every request re-sends the whole history, base64 images
|
|
394
|
+
included, and every image costs real context tokens on every turn. A consumer-managed
|
|
395
|
+
vision history therefore re-uploads each photo long after the model answered the
|
|
396
|
+
question that needed it. `sanitizeHistoryForNextTurn()` is the explicit fix — a pure
|
|
397
|
+
helper that evicts image payloads from every message outside a trailing keep-window,
|
|
398
|
+
conversation text fully preserved:
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
import { sanitizeHistoryForNextTurn } from '@nemesis-oss/ollama-sdk';
|
|
402
|
+
|
|
403
|
+
history.push({ role: 'user', content: 'What is in THIS photo?', images: [newImage] });
|
|
404
|
+
|
|
405
|
+
// Old images evicted, only the trailing turn keeps its payload:
|
|
406
|
+
await client.chat({ model: 'llava', messages: sanitizeHistoryForNextTurn(history) });
|
|
407
|
+
|
|
408
|
+
// Keep a wider window, and tell the model what used to be there:
|
|
409
|
+
sanitizeHistoryForNextTurn(history, {
|
|
410
|
+
keepImagesOnLastMessages: 2,
|
|
411
|
+
imagePlaceholder: '[image from an earlier turn removed to save context]',
|
|
412
|
+
});
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
The same philosophy as compaction — caller-initiated, never automatic — with the same
|
|
416
|
+
visible tradeoffs (the model loses access to evicted images; the KV prefix diverges at
|
|
417
|
+
the eviction point, so a hot cache-friendly session shouldn't sanitize). Input arrays
|
|
418
|
+
and untouched messages are never mutated; kept messages are reused by reference. See
|
|
419
|
+
[ADR 0027](./docs/adr/0027-agent-cycle-detection-url-join-history-hygiene.md).
|
|
420
|
+
|
|
421
|
+
### Model-Affinity Scheduling (multi-model anti-thrashing)
|
|
422
|
+
|
|
423
|
+
Ollama's concurrency model (per the official FAQ) makes same-model parallelism cheap — KV cache scales as `OLLAMA_NUM_PARALLEL × context_length` for the _loaded_ model — but switching models is expensive: a request for a different model queues until the first goes idle or is evicted (`OLLAMA_MAX_LOADED_MODELS`, default 3× GPU count), paying an unload/cold-load swap each time. Workloads that interleave models arbitrarily (extraction on a coder model, reasoning on a thinking model) thrash the daemon that way. `ModelAffinityScheduler` is the client-side fix:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { ModelAffinityScheduler } from '@nemesis-oss/ollama-sdk';
|
|
427
|
+
|
|
428
|
+
const scheduler = new ModelAffinityScheduler(client, {
|
|
429
|
+
concurrentModels: 1, // one model hot at a time (default) — the anti-thrash setting
|
|
430
|
+
perModelConcurrency: 1, // mirror the daemon's OLLAMA_NUM_PARALLEL if you raise it
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// Per-model serial queues; the active model deepens before the next one loads:
|
|
434
|
+
await scheduler.run('deepseek-r1', () => reason(client));
|
|
435
|
+
await scheduler.run('qwen2.5:coder', () => extract(client));
|
|
436
|
+
|
|
437
|
+
// Candidate lists: picks whichever model is already loaded (GET /api/ps, TTL-cached):
|
|
438
|
+
const code = await scheduler.run(['qwen2.5:coder', 'qwen2.5:14b'], (model) =>
|
|
439
|
+
extractWith(client, model),
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
scheduler.stats; // { activeModels: ['deepseek-r1'], queuedTasks: 3 }
|
|
443
|
+
await scheduler.dispose(); // waits for every queue to drain
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
Dispatch is **affinity-sticky, not round-robin**: when a queued model is already active, its tasks start before a different model's (up to `perModelConcurrency`), because deepening the hot model avoids a swap. Tasks are your own functions — the scheduler adds no retry, timeout, or failover, and a rejected task only rejects its own `run()` promise. Candidate selection degrades gracefully: if `/api/ps` fails, the first candidate runs and the failure is never cached.
|
|
447
|
+
|
|
448
|
+
### Capacity Planning: OLLAMA_NUM_PARALLEL, MAX_QUEUE & KV-Cache Memory
|
|
449
|
+
|
|
450
|
+
The server-side knobs (official FAQ defaults) and the client-side surfaces that map onto them:
|
|
451
|
+
|
|
452
|
+
| Server knob | Default | Effect | Client-side counterpart |
|
|
453
|
+
| ----------------------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
454
|
+
| `OLLAMA_NUM_PARALLEL` | 1 | Parallel requests **per loaded model**; required memory scales `NUM_PARALLEL × CONTEXT_LENGTH` (a 4K-context model at 4 parallel allocates a 16K KV cache) | `ModelAffinityScheduler({ perModelConcurrency })`, `ToolRegistry({ maxConcurrency })` for agent tool dispatch |
|
|
455
|
+
| `OLLAMA_MAX_LOADED_MODELS` | 3× GPUs (3 on CPU) | Concurrently loaded models; beyond it, requests queue until a model goes idle or is evicted — the swap/thrash cycle | `ModelAffinityScheduler({ concurrentModels })` — keep the working set small; `client.models.pin()`/`unload()` for explicit lifecycle |
|
|
456
|
+
| `OLLAMA_MAX_QUEUE` | 512 | Queued requests beyond this are rejected immediately with **503** | `endpointHealth.maxConcurrentPerEndpoint` (queue client-side instead of saturating the daemon), `embedBatch({ batchSize, concurrency })` for ingestion, retry/failover on 503 |
|
|
457
|
+
| `OLLAMA_CONTEXT_LENGTH` / `num_ctx` | 2048–4096 model-dependent | The window per request — prompts beyond it are **silently truncated** | `models.getContextLength()` for the real number, `defaultContextLength` to make it explicit, pre-flight warnings + `session.compact()` to stay inside it |
|
|
458
|
+
|
|
459
|
+
The two failure modes this table prevents: `Promise.all`-style floods (hundreds of simultaneous requests → queue saturation → 503s, VRAM spikes) and model ping-pong (alternating models → repeated unload/reload stalls). The SDK's request path already caps and queues per endpoint via `endpointHealth` — including `strategy: 'least-connections'` for pools — and `embedBatch`/`ModelAffinityScheduler` extend that discipline to ingestion and multi-model workloads. `OLLAMA_KV_CACHE_TYPE` (`f16`/`q8_0`/`q4_0`) trades KV precision for memory headroom at the daemon level; benchmark its latency impact against these client-side levers before relying on it for throughput.
|
|
460
|
+
|
|
321
461
|
### Blob Management & Custom GGUF Model Publishing
|
|
322
462
|
|
|
323
463
|
Ollama's documented import protocol: push a blob for each file, then reference it in `/api/create`'s `files` map by file name and SHA-256 digest. The SDK wraps the whole flow:
|
|
@@ -462,6 +602,31 @@ console.log(
|
|
|
462
602
|
|
|
463
603
|
`embed()` targets the modern `/api/embed` endpoint (batch `input`, `truncate`, and `dimensions` truncation are all supported). The older single-prompt `/api/embeddings` is still available as `client.embeddings()`, but it's `@deprecated` — Ollama's own docs consider it legacy in favor of `/api/embed`.
|
|
464
604
|
|
|
605
|
+
#### Batched embeddings with backpressure (large corpora)
|
|
606
|
+
|
|
607
|
+
Embedding a whole corpus with `Promise.all(chunks.map(c => client.embed(...)))` is the failure mode every RAG pipeline eventually hits: hundreds of simultaneous requests contend sockets, saturate the daemon's request queue (`OLLAMA_MAX_QUEUE` → 503s), and spike GPU VRAM as the model instance serves every prompt at once. Long inputs have a second, quieter failure mode — Ollama **silently truncates** any input string longer than the model's context window unless `truncate: false` is set.
|
|
608
|
+
|
|
609
|
+
`embedBatch()` is the safe building block for ingestion:
|
|
610
|
+
|
|
611
|
+
```typescript
|
|
612
|
+
const { embeddings, batchCount } = await client.embedBatch({
|
|
613
|
+
model: 'nomic-embed-text:latest',
|
|
614
|
+
input: corpus, // any size — 10 strings or 10 million
|
|
615
|
+
batchSize: 32, // inputs per /api/embed request (default 32)
|
|
616
|
+
concurrency: 3, // batches in flight simultaneously (default 3)
|
|
617
|
+
keep_alive: '10m', // pin the model for the whole ingestion
|
|
618
|
+
onBatchComplete: (done, total) => progress.log(`${done}/${total} batches`),
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
// embeddings[i] always corresponds to corpus[i], no matter which batch
|
|
622
|
+
// finished first — safe to zip straight into a vector store.
|
|
623
|
+
await vectorStore.upsert(corpus.map((text, i) => ({ id: i, text, vector: embeddings[i] })));
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
Every batch rides the client's full pipeline — failover, retry, auth, telemetry — and the operation is **order-preserving** and **fail-fast**: the first batch error aborts its in-flight siblings and rejects the whole call with the original error, so a half-indexed corpus never looks like success. The caller's `signal` cancels queued and in-flight batches alike (`code: 'aborted'`).
|
|
627
|
+
|
|
628
|
+
Like `chat`/`generate`, `embedBatch()` injects `defaultContextLength` as `num_ctx` and pre-checks each input string's estimated tokens against the resolved window — warn (default) or throw (`onContextOverflow: 'throw'`) with the offending indexes _before_ any request is sent, since Ollama truncates embedding inputs silently. Tune `batchSize`/`concurrency` per daemon: lower both for a laptop GPU, raise `concurrency` for remote or multi-endpoint clients.
|
|
629
|
+
|
|
465
630
|
### Model Lifecycle Management
|
|
466
631
|
|
|
467
632
|
Full parity with Ollama's model catalog and blob-store API — every method targets one specific endpoint's local state and deliberately does **not** cross-endpoint fail over (see [ADR 0008](./docs/adr/0008-endpoint-failover-scope.md)):
|
|
@@ -571,6 +736,43 @@ synthesizes a stable client-side ID for tracing and execution correlation:
|
|
|
571
736
|
use Ollama's documented `tool_name` field; the SDK-local `toolCallId` is not sent on
|
|
572
737
|
the wire. See [ADR 0007](./docs/adr/0007-synthetic-tool-call-ids.md).
|
|
573
738
|
|
|
739
|
+
The loop is boundary-checked by construction. `maxIterations` (default 10) bounds the
|
|
740
|
+
run; an optional `maxToolCalls` budget caps total executions; and tool rejections never
|
|
741
|
+
crash the loop — the registry encapsulates unregistered names, argument-validation
|
|
742
|
+
failures, timeouts, and thrown errors as failed `ToolExecutionResult`s that are fed
|
|
743
|
+
back to the model as ordinary `role: 'tool'` messages so it can self-correct. When a
|
|
744
|
+
model gets _stuck_ — re-emitting the same call with unchanged arguments instead of
|
|
745
|
+
reacting to its results — opt-in cycle detection fails fast with a precise diagnosis
|
|
746
|
+
instead of letting the loop burn its whole budget on the same wasted call:
|
|
747
|
+
|
|
748
|
+
```typescript
|
|
749
|
+
import { Agent, OllamaAgentToolLoopError } from '@nemesis-oss/ollama-sdk';
|
|
750
|
+
|
|
751
|
+
const agent = new Agent(client, {
|
|
752
|
+
tools: registry,
|
|
753
|
+
maxIterations: 10,
|
|
754
|
+
maxToolCalls: 40, // total execution budget across the run
|
|
755
|
+
maxRepeatedToolCalls: 3, // per identical call (same name + same arguments)
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
try {
|
|
759
|
+
const result = await agent.run({ model: 'qwen3:8b', messages });
|
|
760
|
+
} catch (error) {
|
|
761
|
+
if (error instanceof OllamaAgentToolLoopError) {
|
|
762
|
+
// The model re-emitted error.toolName with identical arguments a 4th time.
|
|
763
|
+
// error.signature holds the canonical call; error.repeatedExecutions the count.
|
|
764
|
+
// Fail fast at turn 4 instead of burning all 10 iterations on it.
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
Counting is per canonical signature — `canonicalToolCallSignature()` (also exported)
|
|
770
|
+
sorts argument keys recursively, so a model re-emitting the same call in a different
|
|
771
|
+
key order still counts as the same call. Failed, unregistered, and timed-out
|
|
772
|
+
executions count too: re-calling a failing tool with unchanged arguments is exactly
|
|
773
|
+
the pathological loop this catches. Like `maxToolCalls`, the guardrail is opt-in and
|
|
774
|
+
caller-owned — see [ADR 0027](./docs/adr/0027-agent-cycle-detection-url-join-history-hygiene.md).
|
|
775
|
+
|
|
574
776
|
Running several `Agent`s against different models/API keys for different roles (e.g. a
|
|
575
777
|
planning model, a coding model, a research model) is a single `OllamaClient` with
|
|
576
778
|
per-endpoint `models` allow-lists (see
|
|
@@ -962,6 +1164,37 @@ initial HTTP round trip:
|
|
|
962
1164
|
between turns, outside any `chat()` call, so a slow tool never ties up one of your
|
|
963
1165
|
scarce concurrent-request accounts.
|
|
964
1166
|
|
|
1167
|
+
### Client Teardown: `destroy()`
|
|
1168
|
+
|
|
1169
|
+
Inside `node:worker_threads` tasks, CLI runners, serverless handlers, and other
|
|
1170
|
+
short-lived processes, the things that keep an event loop (and therefore the
|
|
1171
|
+
thread or process) alive are exactly the things this SDK manages: in-flight
|
|
1172
|
+
fetch bodies, unconsumed stream readers, and requests queued behind
|
|
1173
|
+
`maxConcurrentPerEndpoint`. `destroy()` is the one-call drain for all of them:
|
|
1174
|
+
|
|
1175
|
+
```typescript
|
|
1176
|
+
import { parentPort, workerData } from 'node:worker_threads';
|
|
1177
|
+
|
|
1178
|
+
const client = new OllamaClient({ baseUrl: workerData.ollamaUrl });
|
|
1179
|
+
try {
|
|
1180
|
+
await processTask(client, workerData.payload);
|
|
1181
|
+
} finally {
|
|
1182
|
+
// Aborts every request/stream still in flight with OllamaAbortError
|
|
1183
|
+
// (code 'aborted'), releases their endpoint slots, and lets the worker
|
|
1184
|
+
// thread exit cleanly. Idempotent — safe to call from a signal handler.
|
|
1185
|
+
const aborted = client.destroy('worker task finished');
|
|
1186
|
+
if (aborted > 0) logger.warn(`torn down ${aborted} in-flight operations`);
|
|
1187
|
+
}
|
|
1188
|
+
```
|
|
1189
|
+
|
|
1190
|
+
Every aborted operation — dispatched **or** still queued — rejects with
|
|
1191
|
+
`OllamaAbortError` carrying the reason; active streams reject their
|
|
1192
|
+
`finalResult` and release their concurrency slots, so nothing dangles after
|
|
1193
|
+
the call returns the count of operations it aborted. `destroy()` is a drain,
|
|
1194
|
+
not a permanent disable: the client stays usable afterward (spawn a fresh one
|
|
1195
|
+
if you want a hard cut), and calling it on an idle client is a no-op that
|
|
1196
|
+
returns `0`.
|
|
1197
|
+
|
|
965
1198
|
---
|
|
966
1199
|
|
|
967
1200
|
### Observability with OpenTelemetry
|
|
@@ -1356,6 +1589,13 @@ npm run bench
|
|
|
1356
1589
|
|
|
1357
1590
|
# Run full CI verification pipeline (typecheck, lint, test, build, edge runtime check)
|
|
1358
1591
|
npm run verify
|
|
1592
|
+
|
|
1593
|
+
# Non-disastrous smoke test: contract gates (validate, IR diff, type drift) + full
|
|
1594
|
+
# verify chain + package type-resolution check + real CJS/ESM consumer compile.
|
|
1595
|
+
# Read-only — no clean, no codegen rewriting src/generated. Live conformance runs
|
|
1596
|
+
# automatically if an Ollama server is reachable on localhost:11434 (otherwise
|
|
1597
|
+
# those tests skip cleanly).
|
|
1598
|
+
npm run smoke
|
|
1359
1599
|
```
|
|
1360
1600
|
|
|
1361
1601
|
---
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as OllamaRuntime, H as HttpClient, A as AbortableAsyncIterable,
|
|
1
|
+
import { O as OllamaRuntime, H as HttpClient, A as AbortableAsyncIterable, af as SseEvent, y as OllamaClientError } from './runtime-CCm4CtU_.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,
|
|
1
|
+
import { O as OllamaRuntime, H as HttpClient, A as AbortableAsyncIterable, af as SseEvent, y as OllamaClientError } from './runtime-DTtWCxDs.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* AUTO-GENERATED by `npm run contract:generate`. DO NOT EDIT.
|
package/dist/generated-api.d.cts
CHANGED
|
@@ -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-
|
|
2
|
-
export { N as NativeApi } from './anthropic-
|
|
3
|
-
import { O as OllamaRuntime } from './runtime-
|
|
4
|
-
export { a as OperationDefinition } from './runtime-
|
|
5
|
-
import './types-
|
|
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';
|
|
6
6
|
import 'zod';
|
|
7
7
|
|
|
8
8
|
/**
|
package/dist/generated-api.d.ts
CHANGED
|
@@ -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-
|
|
2
|
-
export { N as NativeApi } from './anthropic-
|
|
3
|
-
import { O as OllamaRuntime } from './runtime-
|
|
4
|
-
export { a as OperationDefinition } from './runtime-
|
|
5
|
-
import './types-
|
|
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';
|
|
6
6
|
import 'zod';
|
|
7
7
|
|
|
8
8
|
/**
|