@nemesis-oss/ollama-sdk 1.3.0 → 1.4.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 +43 -212
- package/README.md +391 -18
- package/dist/compose-BR70yb4W.d.cts +164 -0
- package/dist/compose-DfAqKAFj.d.ts +164 -0
- package/dist/generated-api.cjs +454 -0
- package/dist/generated-api.cjs.map +1 -0
- package/dist/generated-api.d.cts +1651 -0
- package/dist/generated-api.d.ts +1651 -0
- package/dist/generated-api.js +428 -0
- package/dist/generated-api.js.map +1 -0
- package/dist/generated-models-schemas.cjs +328 -0
- package/dist/generated-models-schemas.cjs.map +1 -0
- package/dist/generated-models-schemas.d.cts +463 -0
- package/dist/generated-models-schemas.d.ts +463 -0
- package/dist/generated-models-schemas.js +291 -0
- package/dist/generated-models-schemas.js.map +1 -0
- package/dist/generated-runtime.cjs +145 -0
- package/dist/generated-runtime.cjs.map +1 -0
- package/dist/generated-runtime.d.cts +2 -0
- package/dist/generated-runtime.d.ts +2 -0
- package/dist/generated-runtime.js +143 -0
- package/dist/generated-runtime.js.map +1 -0
- package/dist/index-2RIErNT5.d.cts +583 -0
- package/dist/index-DIQ8NUbU.d.ts +583 -0
- package/dist/index.cjs +1886 -154
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +817 -453
- package/dist/index.d.ts +817 -453
- package/dist/index.js +1877 -155
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools.json +1058 -0
- package/dist/mcp-generated.cjs +386 -0
- package/dist/mcp-generated.cjs.map +1 -0
- package/dist/mcp-generated.d.cts +35 -0
- package/dist/mcp-generated.d.ts +35 -0
- package/dist/mcp-generated.js +381 -0
- package/dist/mcp-generated.js.map +1 -0
- package/dist/mcp-http.cjs +100 -0
- package/dist/mcp-http.cjs.map +1 -0
- package/dist/mcp-http.d.cts +48 -0
- package/dist/mcp-http.d.ts +48 -0
- package/dist/mcp-http.js +96 -0
- package/dist/mcp-http.js.map +1 -0
- package/dist/mcp-stdio.cjs +49 -0
- package/dist/mcp-stdio.cjs.map +1 -0
- package/dist/mcp-stdio.d.cts +34 -0
- package/dist/mcp-stdio.d.ts +34 -0
- package/dist/mcp-stdio.js +47 -0
- package/dist/mcp-stdio.js.map +1 -0
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.d.cts +3 -2
- package/dist/skills.d.ts +3 -2
- package/dist/skills.js.map +1 -1
- package/dist/types-B9_axjum.d.cts +66 -0
- package/dist/types-B9_axjum.d.ts +66 -0
- package/dist/{compose-CDWq8oxJ.d.cts → types-BQhgW-du.d.cts} +68 -171
- package/dist/{compose-CDWq8oxJ.d.ts → types-BQhgW-du.d.ts} +68 -171
- package/package.json +96 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,225 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Unreleased
|
|
4
4
|
|
|
5
|
-
The
|
|
6
|
-
|
|
5
|
+
- **Contract-first hybrid architecture (Waves 1-9).** The SDK now ships a single canonical IR at `contracts/ir/ollama.ir.json` (compiled from `contracts/sources/` + `contracts/overlays/`) that drives seven consumers: TypeScript interfaces, generated API classes, MCP tool descriptors, operation metadata, field-level parity, Zod schemas, and bidirectional endpoint discovery. Adding a new Ollama operation now requires writing one overlay block; everything else is generated. See [ADRs 0013-0019](./docs/adr/README.md) for the full design.
|
|
6
|
+
- **Wave 1** — Contract foundation: sources, overlays, canonical IR, bidirectional endpoint discovery (catches new endpoints like `/v1/systemone` that the OpenAPI spec doesn't yet cover).
|
|
7
|
+
- **Wave 2** — Generated TypeScript interfaces in `src/generated/models/` (36 schemas), with a drift detector comparing against `src/types.ts`.
|
|
8
|
+
- **Wave 3** — Generated API classes (`NativeApi` / `OpenAIApi` / `AnthropicApi`) delegating to a hand-written `OllamaRuntime` seam with environment + version guards.
|
|
9
|
+
- **Wave 4** — `raw: true` option on `HttpClient` so the generated runtime inherits middleware/retry/telemetry for streaming calls (instead of bypassing them with a direct `fetch()`).
|
|
10
|
+
- **Wave 5** — Field-level parity migrated from `docs/api-parity.json` into overlay `parity:` blocks; new IR-driven verifier `npm run verify:contract-parity`.
|
|
11
|
+
- **Wave 6** — MCP tool generation: 21 tool descriptors at `src/generated/mcp/tools.json` with the runtime adapter at `@nemesis-oss/ollama-sdk/mcp/generated`.
|
|
12
|
+
- **Wave 7** — Retired `docs/api-parity.json`, `scripts/verify-api-parity.ts`, and `scripts/parity-status.ts`. The IR-driven verifier is the only parity check.
|
|
13
|
+
- **Wave 8** — `OllamaClient.runtime` accessor returns a cached `OllamaRuntime` sharing the client's transport; non-breaking bridge between the legacy and generated surfaces.
|
|
14
|
+
- **Wave 9** — Zod schema generation: every TypeScript interface has a paired Zod schema at `src/generated/models/<name>.schema.ts` (36 schemas) for runtime validation.
|
|
15
|
+
- **MCP remote transport integration.** Added the optional `@nemesis-oss/ollama-sdk/mcp/http` adapter for MCP Streamable HTTP, explicit legacy SSE, and guarded automatic SSE fallback on compatible non-authentication 4xx responses. It preserves the root package's transport boundary and supports custom `fetch`/`RequestInit` configuration.
|
|
7
16
|
|
|
8
|
-
|
|
17
|
+
- **Ollama API parity refresh.** Updated the compatibility contract against the current documentation: native generate now preserves cached prompt-token metrics through streaming, OpenAI Chat/Completions parity includes documented logprobs fields, OpenAI Responses strict types retain supported `reasoning`/`think` controls, Anthropic `output_config.effort` is forwarded, and native Show/Create contracts include the newly verified fields.
|
|
18
|
+
- **Generate stream fidelity.** Aggregated generate streams now preserve `thinking` alongside response text and cached prompt-token usage.
|
|
19
|
+
- **Anthropic compatibility.** `output_config.effort` is now treated as supported by the current Ollama Messages compatibility docs instead of being silently discarded.
|
|
9
20
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- **Client-side quota monitoring (`QuotaManager`).** Ollama Cloud doesn't expose
|
|
13
|
-
account-level quota through the API — no response header or endpoint reports how much
|
|
14
|
-
of your plan's session/weekly limit is left (see
|
|
15
|
-
[ollama/ollama#15663](https://github.com/ollama/ollama/issues/15663)). `QuotaManager`
|
|
16
|
-
tracks usage you record (via `recordUsage`, which reads `extractUsage`-normalized token
|
|
17
|
-
counts off a raw response) against budgets you configure over one or more rolling
|
|
18
|
-
windows, and refuses to proceed (`canProceed`/`assertCanProceed`) once a window's budget
|
|
19
|
-
is spent — a local safety net to complement, not replace, catching the server's own
|
|
20
|
-
`OllamaRateLimitError`. `createOllamaCloudFreeTierQuota` is a convenience factory
|
|
21
|
-
wiring up the free tier's documented 5-hour session and 7-day weekly window cadence
|
|
22
|
-
(you still supply the token/request budgets, since Ollama doesn't publish the actual
|
|
23
|
-
ceilings). New `OllamaQuotaExceededError` (`code: 'quota_exceeded'`) is thrown by
|
|
24
|
-
`assertCanProceed`. See the [Quota Monitoring](./README.md#quota-monitoring) README
|
|
25
|
-
section.
|
|
26
|
-
- **Credential-scoped multi-key routing.** `OllamaEndpoint` gains an optional `models`
|
|
27
|
-
allow-list, for the common case of several Ollama Cloud API keys each entitled to a
|
|
28
|
-
different model. `EndpointRegistry.candidates(model)` now filters to endpoints whose
|
|
29
|
-
`models` includes the requested model (endpoints without `models` stay eligible for
|
|
30
|
-
every model — fully backward compatible), so `chat`/`generate`/`embed`/`embeddings` and
|
|
31
|
-
model-lifecycle calls (`showModel`, `pullModel`, etc.) automatically resolve the
|
|
32
|
-
authorized credential for the model requested, and cross-endpoint failover between
|
|
33
|
-
differently-scoped endpoints never sends a request to a key that isn't entitled to that
|
|
34
|
-
model. Requesting a model no configured endpoint is scoped to throws the new
|
|
35
|
-
`OllamaModelRoutingError` (`code: 'model_routing_error'`) immediately, before any
|
|
36
|
-
network call — the SDK never probes unauthorized keys to see which one happens to
|
|
37
|
-
work. See the README's
|
|
38
|
-
["Multiple API keys, each entitled to different models"](./README.md#multiple-api-keys-each-entitled-to-different-models)
|
|
39
|
-
and the
|
|
40
|
-
[multi-model agent benchmarking guide](./docs/guides/multi-model-agent-benchmarking.md).
|
|
41
|
-
- **`credentials` + `modelBindings` config.** An ergonomic, map-based alternative to
|
|
42
|
-
writing `endpoints` with per-entry `models` allow-lists by hand: `OllamaClientConfig`
|
|
43
|
-
gains `credentials` (named `{ apiKey, baseUrl?, headers? }` entries, keyed by an id you
|
|
44
|
-
choose), `modelBindings` (maps a model to the credential id, or ids, authorized to serve
|
|
45
|
-
it), and `defaultCredential` (a fallback credential for any model with no explicit
|
|
46
|
-
binding). Both config shapes compile down to the same `EndpointRegistry`/
|
|
47
|
-
`executeWithFailover` routing above — this is config sugar, not a second routing
|
|
48
|
-
mechanism — so behavior (including `OllamaModelRoutingError` on an unrouted model) is
|
|
49
|
-
identical either way. `modelBindings` referencing an unknown credential id throws at
|
|
50
|
-
construction. New `resolveCredentialEndpoints` export for anyone who wants the
|
|
51
|
-
translation without going through `OllamaClient`.
|
|
52
|
-
- **Round-robin candidate selection.** `EndpointRegistryOptions` (passed via
|
|
53
|
-
`OllamaClientConfig.endpointHealth`) gains `strategy: 'priority' | 'round-robin'`
|
|
54
|
-
(default `'priority'`, unchanged prior behavior). With `'round-robin'`,
|
|
55
|
-
`EndpointRegistry.candidates()` rotates each same-priority group of healthy candidates
|
|
56
|
-
by one position per call, so consecutive `chat`/`generate`/`embed`/etc. calls spread
|
|
57
|
-
across a pool of interchangeable endpoints or unbound `credentials` (e.g. several
|
|
58
|
-
free-tier Ollama Cloud keys with no `models`/`modelBindings` restriction) instead of
|
|
59
|
-
always preferring the first one. Candidates at different priorities are unaffected —
|
|
60
|
-
a higher-priority candidate is still always tried first — and failover to the rest of
|
|
61
|
-
the (rotated) list still applies if the first pick fails. See the README's
|
|
62
|
-
["A free pool of interchangeable keys — and spreading load across it"](./README.md#a-free-pool-of-interchangeable-keys--and-spreading-load-across-it).
|
|
63
|
-
- **Least-connections candidate selection.** `EndpointRegistryOptions.strategy` gains a
|
|
64
|
-
third value, `'least-connections'`, alongside `'priority'` (default) and
|
|
65
|
-
`'round-robin'`. Each same-priority tier is ordered by ascending in-flight request
|
|
66
|
-
count (new `EndpointRegistry.acquire`/`release`, wired into `OllamaClient.executeWithFailover`
|
|
67
|
-
around each attempt) rather than a fixed rotation, so concurrent `Promise.all`-style
|
|
68
|
-
fan-out deterministically lands on distinct candidates — the motivating case being
|
|
69
|
-
several Ollama Cloud free-tier accounts, each capped at 1 concurrent request: `N`
|
|
70
|
-
concurrent requests against `N` such accounts land one-per-account rather than risking
|
|
71
|
-
two on the same still-busy one, because the endpoint choice and its `acquire()` happen
|
|
72
|
-
synchronously with no `await` in between (JS's single-threaded execution rules out the
|
|
73
|
-
race entirely). `EndpointHealth` gains `activeRequests`, also exposed via
|
|
74
|
-
`client.endpointStatus()`, for observability regardless of `strategy`. See the README's
|
|
75
|
-
["Concurrent requests across single-slot accounts (least-connections)"](./README.md#concurrent-requests-across-single-slot-accounts-least-connections).
|
|
76
|
-
- **`maxConcurrentPerEndpoint` — queueing past capacity.** `EndpointRegistryOptions`
|
|
77
|
-
gains `maxConcurrentPerEndpoint`, capping in-flight requests per endpoint exactly. Once
|
|
78
|
-
every otherwise-eligible candidate is at that cap, a request waits (FIFO, new
|
|
79
|
-
`EndpointRegistry.filterWithCapacity`/`waitForCapacity`) for one to free rather than
|
|
80
|
-
being routed to an already-saturated candidate — the gap `'least-connections'` alone
|
|
81
|
-
doesn't close for `N + 1` concurrent calls against `N` capacity-1 candidates. Waiting is
|
|
82
|
-
bounded by the request's own `timeoutMs`/`AbortSignal`; a queued call that times out or
|
|
83
|
-
is cancelled is dequeued and rejects without ever being sent.
|
|
84
|
-
|
|
85
|
-
### Fixed
|
|
86
|
-
|
|
87
|
-
- **Streaming requests (`chatStream`/`generateStream`) now hold their endpoint's
|
|
88
|
-
concurrency slot for the lifetime of the stream, not just until it starts.**
|
|
89
|
-
Previously, `acquire`/`release` around a streaming call released the slot as soon as
|
|
90
|
-
`http.requestStream` resolved (response headers received) — before any tokens were
|
|
91
|
-
actually read — so `'least-connections'`/`maxConcurrentPerEndpoint` accounting stopped
|
|
92
|
-
reflecting reality the moment a stream was returned, undercounting real concurrency for
|
|
93
|
-
as long as the caller kept consuming it. `executeWithFailover` gains an internal
|
|
94
|
-
`holdUntil` hook, wired to the returned `OllamaStream`'s `finalResult` for `chatStream`/
|
|
95
|
-
`generateStream` (and the streaming `pull`/`push`/`create` progress endpoints), so the
|
|
96
|
-
slot now releases only once the stream is fully drained, errors, or is aborted.
|
|
97
|
-
|
|
98
|
-
## [1.2.0] - 2026-08-24
|
|
99
|
-
|
|
100
|
-
Closes gaps found during a documentation/API-parity review against the official Ollama
|
|
101
|
-
API — two of which were genuine issues, the rest already covered (multimodal `images`,
|
|
102
|
-
native `think`, `/api/embed`, and full model-lifecycle management all predate this
|
|
103
|
-
release; see the new README sections documenting them).
|
|
104
|
-
|
|
105
|
-
### Fixed
|
|
106
|
-
|
|
107
|
-
- **`webSearch`/`webFetch` were non-functional against real Ollama Cloud.** They
|
|
108
|
-
previously posted to `<configured-baseUrl>/api/websearch` and `/webfetch` — the wrong
|
|
109
|
-
host (Ollama's web tools only ever exist at `https://ollama.com`, never proxied through
|
|
110
|
-
a local server) _and_ the wrong path (missing the underscore: `/api/web_search`,
|
|
111
|
-
`/api/web_fetch`) _and_ the wrong request/response field names. Both methods now always
|
|
112
|
-
target `https://ollama.com` regardless of `baseUrl`/`endpoints`, using the resolved
|
|
113
|
-
`apiKey`/`OLLAMA_API_KEY`, and use the real field names (`max_results` request,
|
|
114
|
-
`content` response). `WebSearchRequestOptions.count` and `WebSearchResult.snippet` are
|
|
115
|
-
kept as `@deprecated` back-compat aliases (mapped to/mirrored from the correct fields)
|
|
116
|
-
rather than removed outright. `WebFetchResponse` gains the `title`/`links` fields the
|
|
117
|
-
real API actually returns.
|
|
118
|
-
|
|
119
|
-
### Added
|
|
21
|
+
- MCP tool arguments are now validated against advertised JSON Schema constraints before dispatch, while `resultMode: 'structured'` preserves raw MCP `CallToolResult` objects for programmatic consumers.
|
|
120
22
|
|
|
121
|
-
|
|
122
|
-
(request) and `ChatResponse`/`GenerateResponse` (response, as a new `Logprob[]` typed
|
|
123
|
-
by the new `Logprob`/`LogprobToken` types), matching the official `/api/chat` and
|
|
124
|
-
`/api/generate` schemas.
|
|
125
|
-
- `OLLAMA_CLOUD_BASE_URL` exported for consumers who want to reference the fixed web-tools
|
|
126
|
-
host directly.
|
|
23
|
+
## [Unreleased]
|
|
127
24
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Brings the SDK's typed surface up to date with Ollama v0.13.3+.
|
|
131
|
-
|
|
132
|
-
### Added
|
|
133
|
-
|
|
134
|
-
- **`/api/create` field parity:** `CreateRequestOptions` now exposes the documented
|
|
135
|
-
`template`, `renderer`, `parser`, `license`, `system`, `parameters`, and `messages`
|
|
136
|
-
fields alongside the existing `from`/`files`/`adapters`/`quantize`. The old
|
|
137
|
-
`modelfile` string field is kept for backward compatibility but marked `@deprecated`
|
|
138
|
-
in favor of the discrete fields.
|
|
139
|
-
- **OpenAI Responses API bridge:** `client.openai.responses()` / `createResponses()`
|
|
140
|
-
POST to `/v1/responses`. Ollama implements this non-statefully, so
|
|
141
|
-
`previous_response_id`/`conversation` are typed but documented as ignored.
|
|
142
|
-
- **`reasoning_effort` / `reasoning.effort`:** Added to `OpenAIChatCompletionRequest`
|
|
143
|
-
for thinking models (`deepseek-r1`, `qwen3`, etc.), matching Ollama's OpenAI
|
|
144
|
-
compatibility docs.
|
|
145
|
-
- **`tool_choice` / `parallel_tool_calls`:** Now typed as accepted-but-ignored on
|
|
146
|
-
`OpenAIChatCompletionRequest` (previously omitted entirely), so passing a standard
|
|
147
|
-
OpenAI request object type-checks without modification.
|
|
148
|
-
- **Raw image bytes:** `Message.images` and `GenerateRequestOptions.images` accept
|
|
149
|
-
`Uint8Array` alongside base64 strings. `OllamaClient.chat()`/`generate()` encode any
|
|
150
|
-
`Uint8Array` entries to base64 automatically via the new `encodeImage` utility
|
|
151
|
-
(exported from the package root), using `Buffer` on Node and `btoa` elsewhere so it
|
|
152
|
-
stays Edge Runtime-safe.
|
|
153
|
-
- **`doneReason` in stream results:** `ChatStreamResult`/`GenerateStreamResult` now
|
|
154
|
-
carry `doneReason`, mapped from the final chunk's `done_reason` (e.g. `"stop"`,
|
|
155
|
-
`"load"`, `"unload"`).
|
|
25
|
+
- **MCP bridge hardening.** MCP tool discovery now supports bounded pagination, repeated-cursor protection, request cancellation, richer MCP metadata types, and structured/non-text result preservation.
|
|
26
|
+
- **Optional Node MCP stdio adapter.** `@nemesis-oss/ollama-sdk/mcp/stdio` connects to local MCP servers using the official `@modelcontextprotocol/client` v2 transport without importing Node-only code into the root package.
|
|
156
27
|
|
|
157
28
|
### Fixed
|
|
158
29
|
|
|
159
|
-
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
## [1.0.0] - 2026-08-17
|
|
163
|
-
|
|
164
|
-
First public release. The version was `0.1.0` throughout development but was never
|
|
165
|
-
published to npm, so the entire feature set below ships as the initial `1.0.0`.
|
|
166
|
-
|
|
167
|
-
`1.0.0` marks the public API surface (`OllamaClient`, `Agent`, `ToolRegistry`, the
|
|
168
|
-
streaming adapters, the error hierarchy, and the compatibility bridges) as stable under
|
|
169
|
-
[Semantic Versioning](https://semver.org/spec/v2.0.0.html) — breaking changes to it now
|
|
170
|
-
require a major version bump.
|
|
30
|
+
- **Documentation consistency.** Restored the package README after an accidental truncation and kept the current MCP/agent capability additions documented.
|
|
31
|
+
- **ADR numbering.** Renumbered the MCP boundary and agent tool-precondition decision to ADR 0011 so ADR 0008 remains uniquely assigned to endpoint failover scope.
|
|
171
32
|
|
|
172
33
|
### Added
|
|
173
34
|
|
|
174
|
-
- **
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
- **
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
- **
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
- **
|
|
187
|
-
|
|
188
|
-
- **
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
- **
|
|
196
|
-
- **OpenTelemetry Instrumentation:** Automatic spans (`@opentelemetry/api` is an optional peer dependency, a no-op when absent or unconfigured) for HTTP requests, endpoint failover attempts, non-streaming `chat`/`generate` calls (using the Gen AI semantic conventions, including token usage), and `Agent` runs (`invoke_agent` → `ollama.agent.turn` → `execute_tool`). See [ADR 0005](./docs/adr/0005-opentelemetry-instrumentation.md).
|
|
197
|
-
- **Edge Runtime CI Verification:** `npm run verify:edge-runtime` bundles `dist/index.js` for a browser/edge platform with `esbuild` (failing on any `node:*` import, matching Cloudflare Workers/Vercel Edge Runtime's own bundlers) and runs a full `OllamaClient` + `Agent` + tool-calling round trip inside `@edge-runtime/vm`'s sandboxed Edge Runtime — a real V8 context exposing only Web Standard globals. Wired into CI as its own job and into `verify`/`prepublishOnly`. See [ADR 0006](./docs/adr/0006-edge-runtime-ci-and-benchmarks.md).
|
|
198
|
-
- **Benchmarks:** `npm run bench` (via `vitest bench`, no new dependency) covers NDJSON stream parsing, Zod schema conversion/structured output parsing, `ToolRegistry` dispatch overhead, and `OllamaClient.chat`'s end-to-end request pipeline overhead. Wired into CI as its own job.
|
|
199
|
-
- **Protocol Compatibility Bridges:**
|
|
200
|
-
- OpenAI compatibility bridge (`/v1/chat/completions`, `/v1/models`), including `stream_options.include_usage` and `tools` (function calling) typing — both confirmed supported by Ollama's OpenAI-compat layer; `tool_choice`/`parallel_tool_calls` are deliberately not typed, since Ollama documents `tool_choice` as explicitly unsupported. `@remarks` JSDoc on `OpenAICompatClient` scopes it as a documented subset of the OpenAI API, not the full Responses API surface.
|
|
201
|
-
- Anthropic compatibility bridge (`/v1/messages`), including `cache_control` typing on content blocks for prompt caching. `@remarks` JSDoc on `AnthropicCompatClient` scopes it as a subset of the Messages API (no tool use, extended thinking, citations, files, or Batches API).
|
|
202
|
-
- **Capability Detection Fixes:** `ModelCapabilities.supportsStructuredOutputRequest` is no longer hardcoded `true` — it's inferred `false` for endpoints classified as `cloud` by `inferRuntimeMode` (Ollama Cloud does not currently support structured outputs) and documented as a best-effort heuristic, not a guarantee, since Ollama doesn't expose this as a queryable capability. Added `supportsThinking`, derived from the model's reported `thinking` capability.
|
|
203
|
-
- **Fail-Fast `OllamaUnsupportedCapabilityError`:** `chat`/`chatStream`/`chatWithSchema` and `generate`/`generateStream`/`generateWithSchema` now throw this error _before making any network call_ when `format` is set against an endpoint inferred as Ollama Cloud, instead of sending a request Ollama Cloud is known to reject. `unsupported_capability` is included in `DEFAULT_FAILOVER_CODES`, so a multi-endpoint setup tries the next candidate (e.g. a local fallback) before the error ever reaches the caller — verified with a test asserting the rejected cloud endpoint's URL is never actually fetched.
|
|
204
|
-
- **`dimensions` on `embed()`:** `EmbedRequestOptions.dimensions` lets callers request truncated embedding vectors, matching Ollama's `/api/embed` parameter.
|
|
205
|
-
- **Environment Variable Fallbacks:** `OllamaClient`'s default single-endpoint `baseUrl`/`apiKey` fall back to `OLLAMA_HOST`/`OLLAMA_API_KEY` (the same variables the official `ollama` CLI and client libraries read) when not passed explicitly, matching the convention of other major LLM SDKs. Guarded to remain a no-op (not a `ReferenceError`) on Edge runtimes where `process` doesn't exist. Explicit `config.baseUrl`/`config.apiKey`, and any use of `config.endpoints`, always take precedence.
|
|
206
|
-
- **Web Standard Stream Adapters:**
|
|
207
|
-
- `toTextStream`, `toDataStream`, and `toResponse` for direct integration with Next.js, Vercel AI SDK, and Web standard streams.
|
|
208
|
-
- **Skills System:**
|
|
209
|
-
- Frontmatter parser for `SKILL.md` documents.
|
|
210
|
-
- Skill composition and prompt injection into system messages (`applySkill`).
|
|
211
|
-
- **Documentation Hygiene:** `OllamaClient.embeddings()` is now marked `@deprecated` (Ollama's `/api/embeddings` was superseded by `/api/embed`, exposed as `embed()`). `ToolCall`, `Agent`, and `ToolRegistry.executeToolCalls` document that Ollama's native tool-calling protocol has no wire-level call ID, dispatch/results are still ordered/concurrency-bounded rather than ID-driven, and that `id`/`tool_call_id` (see above) is a client-synthesized convenience layered on top, not a protocol guarantee.
|
|
212
|
-
- **Testing & Quality Assurance:**
|
|
213
|
-
- New cancellation tests prove `AbortSignal` genuinely aborts the underlying `fetch` call (not just racing a promise) and propagates from `Agent.run` into `ToolExecutionContext.signal`, including the early-abort race where the signal is already aborted before the request starts.
|
|
214
|
-
- 4-tier test architecture: Unit, Integration, Functional, and Behavioral testing (50 tests).
|
|
215
|
-
- VCR record and replay harness with real cassettes generated against `qwen3.5:2b` and `nomic-embed-text:latest`.
|
|
216
|
-
- Multi-node CI/CD workflow (Node 18, 20, 22) and automated npm release with provenance.
|
|
217
|
-
|
|
218
|
-
### Fixed
|
|
219
|
-
|
|
220
|
-
- **`ToolRegistry` rejected every concretely-typed tool.** Its constructor, `register`, and `registerMany` accepted `Tool<never, unknown>`; because `Tool` is invariant in `TParams` (it appears in both `schema: z.ZodType<TParams>` and `execute`), _nothing_ was assignable to it — so `new ToolRegistry([myTool])`, `new ToolRegistry({ tools: [myTool] })`, and `.register(myTool)` all failed to compile for consumers, including the exact example in this README. Replaced with a new exported `AnyTool` alias. Tool authoring keeps full type safety (`defineTool` still infers `TParams` from the Zod schema and type-checks `execute` against it); only the registry's storage type is widened. Found by installing the packed tarball into a throwaway TypeScript project during pre-publish verification. See [ADR 0009](./docs/adr/0009-anytool-registry-variance.md).
|
|
221
|
-
- **Tests are now type-checked.** `tsconfig.json` scoped checking to `src/`, and Vitest's esbuild transform strips types without verifying them — so all 20 test files were unchecked, and had masked the bug above with `as never` casts. `npm run typecheck` now uses `tsconfig.typecheck.json`, covering `src/`, `test/`, `bench/`, and `scripts/`. The casts (and a matching `as unknown as z.ZodType<never>` in `mcp-tools.ts`) are gone.
|
|
222
|
-
|
|
223
|
-
### Changed
|
|
224
|
-
|
|
225
|
-
- **Endpoint Failover Scope:** `ModelsClient` operations (`list`, `show`, `pull`, `push`, `create`, `delete`, `copy`, `ps`, `version`, `createBlob`, `checkBlob`) and `OllamaClient.capabilities()` no longer participate in cross-endpoint failover — each now targets only the single best candidate endpoint (same-endpoint retry via backoff still applies). These operations act on a specific server's local model catalog/blob store, which isn't an interchangeable resource across endpoints the way `chat`/`generate`/`embed` inference is; failing `deleteModel`/`listModels`/etc. over to a different endpoint was silently operating on the wrong server's state, not retrying "the same" request. `chat`/`generate`/`embed`/`embeddings`/`webSearch`/`webFetch` failover behavior is unchanged. See [ADR 0008](./docs/adr/0008-endpoint-failover-scope.md).
|
|
35
|
+
- **First-class MCP bridge.** Added `McpBridge` to convert MCP `tools/list` descriptors into native Ollama tool definitions and register executable MCP-backed tools through the existing `ToolRegistry` without coupling the core package to a transport.
|
|
36
|
+
- **Agent capability preflight and adaptive context.** Tool-enabled `Agent` runs using `OllamaClient` now query `/api/show` before the first model turn, fail with `OllamaIncompatibleModelError` when `tools` is absent, and default to `num_ctx: 32768` clamped to the model-reported context length; explicit `options.num_ctx` remains authoritative.
|
|
37
|
+
- **Model context metadata.** `ModelCapabilities` now exposes `contextLength` parsed from `/api/show` `model_info` and accepts cancellation through the capability lookup.
|
|
38
|
+
- **Machine-readable Ollama contract and IR-driven CI verification.** The canonical IR at `contracts/ir/ollama.ir.json` (compiled from `contracts/sources/` + `contracts/overlays/`) defines the supported Ollama surface, and `verify:contract-parity` checks it against the current official documentation; publishing now runs the same verification.
|
|
39
|
+
- **Support-aware compatibility contract.** API parity manifest v4 now separates supported, explicitly unsupported, and SDK-only fields; verifies Anthropic response fields and the public OpenAI Responses/Anthropic stream unions; and exports strict Ollama-scoped request types without removing the broader compatibility request types.
|
|
40
|
+
- **Strict Anthropic compatibility types.** Ollama-scoped tool and thinking types now exclude provider-only controls while the broader Anthropic compatibility types remain available for callers targeting the wider provider API.
|
|
41
|
+
- **Anthropic Ollama-scope alignment.** The strict Anthropic request type now excludes `output_config`, redacted-thinking input blocks, and nested `cache_control` on tool-result text; the compatibility bridge strips those unsupported cache directives before transmission. Live documentation sections now take precedence over pinned fallbacks, and nested unsupported-field evidence is enforced.
|
|
42
|
+
- **Automated Ollama API parity verifier.** CI now checks the documented native and OpenAI/Anthropic compatibility request surfaces against the SDK's TypeScript interfaces and current official documentation.
|
|
43
|
+
- **Abort-aware retry backoff.** `withRetry` now accepts an optional `AbortSignal`, and `OllamaClient` propagates request cancellation through retry delays so cancelled work does not remain asleep in backoff.
|
|
44
|
+
- **HTTP middleware and request lifecycle hooks.** The existing `middleware` and `onLifecycleEvent` client options are now wired through native, OpenAI/Anthropic compatibility, health-check, and hosted web HTTP paths; retries share the same logical request id.
|
|
45
|
+
- **Shared compatibility endpoint routing.** OpenAI and Anthropic compatibility requests now use the same model-scoped endpoint selection, failover, concurrency limits, and cancellation path as native inference.
|
|
46
|
+
- **Compatibility stream lifecycle.** OpenAI/Anthropic streams now expose `abort()`, hold endpoint capacity until `finalResult` settles, and remain covered by the request timeout for their full lifetime.
|
|
47
|
+
- **OpenAI Responses stream reconstruction.** Responses streams can now reconstruct message, function-call, and reasoning output items from deltas when a terminal full response payload is absent.
|
|
48
|
+
- **OpenAI Responses event/state parity.** Responses streams now understand output-item/content-part lifecycle events, refusal and reasoning-summary events, function-call `call_id` reconstruction, and `response.failed` / `response.incomplete` terminal states; failed or incomplete streams surface a typed `OpenAIResponsesStreamError` instead of a fabricated success response.
|
|
49
|
+
- **Native model-management parity.** The live parity contract now also verifies the documented `/api/copy`, `/api/pull`, `/api/push`, and `/api/delete` request surfaces. The Responses contract now distinguishes Ollama-documented fields from SDK-only vendor extensions.
|
|
50
|
+
- **Native stream cancellation propagation.** NDJSON and SSE readers are cancelled on iterator termination and parent `AbortSignal` cancellation.
|
|
51
|
+
- **Current OpenAI compatibility wire fields.** Chat streaming now preserves model reasoning and `system_fingerprint`, and the completion/chat declarations include current logprob-related fields and cache-aware usage metadata.
|
|
52
|
+
- **Anthropic stream usage preservation.** `message_start` and `message_delta` usage details are merged without discarding cache-related counters.
|
|
53
|
+
- **API parity parser hardening.** Compatibility request-field checks are scoped to endpoint/request sections, sdk-only checks require exact input declarations, and CI fallback snapshots track the rendered hosted Ollama documentation rather than stale server-source structs.
|
|
54
|
+
- **Strict provider compatibility types.** Exported `OllamaAnthropicMessagesRequest` and tightened Ollama-scoped OpenAI request aliases so unsupported provider controls remain compile-time distinguishable while the broader compatibility types remain available; base64 vision content and Responses `truncation` are represented in the strict OpenAI surface.
|
|
55
|
+
- **Generic SSE transport:** added `parseSseStream()` and `HttpClient.requestSseStream()` for provider-neutral OpenAI/Anthropic-compatible streaming. Native Ollama NDJSON streaming remains unchanged.
|
|
56
|
+
- **Typed compatibility streaming:** added OpenAI Chat/Completions/Responses and Anthropic Messages streaming adapters over the shared SSE transport, including text aggregation, tool-call JSON argument accumulation, reasoning/thinking deltas, and final usage/response aggregation.
|