@nemesis-oss/ollama-sdk 1.10.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 +72 -0
- package/README.md +296 -1
- package/dist/{anthropic-CPaoxeLX.d.ts → anthropic-CKp5TmAP.d.ts} +1 -1
- package/dist/{anthropic-DuE8M6Tz.d.cts → anthropic-Did0lQxP.d.cts} +1 -1
- package/dist/{compose-BQYXdpar.d.ts → compose-6UOPEknN.d.ts} +1 -1
- package/dist/{compose-lt-Qz3lI.d.cts → compose-DhvoUrWa.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 +790 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +870 -97
- package/dist/index.d.ts +870 -97
- package/dist/index.js +776 -107
- 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-BV9SK_cf.d.ts → runtime-CIQYCRL3.d.ts} +29 -2
- package/dist/{runtime-BsdBbuOv.d.cts → runtime-DmI1cOEq.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-BtQexFpT.d.cts → types-B57ZZfp3.d.cts} +15 -1
- package/dist/{types-BtQexFpT.d.ts → types-B57ZZfp3.d.ts} +15 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
1
|
+
import { T as ThinkingMetadata, M as ModelResponse, R as RequestCancellationOptions, S as ShowRequestOptions, a as ShowResponse, P as PullRequestOptions, b as ProgressResponse, c as PushRequestOptions, C as CreateRequestOptions, D as DeleteRequestOptions, d as StatusResponse, e as CopyRequestOptions, f as PsResponse, V as VersionResponse, g as ToolParameters, h as ThinkValue, i as ToolCall, j as ChatRequestOptions, k as ModelOptions, l as ToolDefinition, F as FormatOption, m as ChatResponse, n as Message, G as GenerateRequestOptions, o as GenerateResponse, E as EmbedRequestOptions, p as EmbedResponse, q as EmbeddingsRequestOptions, r as EmbeddingsResponse, W as WebSearchRequestOptions, s as WebSearchResponse, t as WebFetchRequestOptions, u as WebFetchResponse, U as UsageRequestOptions, B as BalanceRequestOptions, v as PingResult, w as VisionInput } from './types-B57ZZfp3.cjs';
|
|
2
|
+
export { L as ListResponse, x as Logprob, y as LogprobToken, z as ModelDetails, A as Role, H as ToolCallFunction, I as ToolFunctionDefinition, J as ToolProperty, K as UsageRange, N as UsageScope, O as WebSearchResult, Q as imageStringNeedsResolution, X as resolveImageInput } from './types-B57ZZfp3.cjs';
|
|
3
|
+
import { H as HttpClient, F as FetchLike, M as Middleware, L as Logger, R as RequestLifecycleHook, c as OllamaStreamEvent, A as AbortableAsyncIterable, d as OllamaStreamEventType, P as ProgressStreamResult, B as BinaryBody, O as OllamaRuntime, C as ChatStreamResult, G as GenerateStreamResult, e as RawUsageSource, T as TokenUsage } from './runtime-DmI1cOEq.cjs';
|
|
4
|
+
export { D as DoneEvent, E as ErrorEvent, f as HttpBody, g as HttpClientOptions, h as HttpRequestOptions, i as LifecycleErrorEvent, j as LifecycleRetryEvent, k as LifecycleStartEvent, l as LifecycleSuccessEvent, m as LogFn, n as MessageEvent, o as MiddlewareContext, N as NANOS_PER_MS, p as NANOS_PER_SECOND, q as NOOP_LOGGER, r as NextFunction, s as OllamaAbortError, t as OllamaAgentMaxIterationsError, u as OllamaAgentMaxToolCallsError, v as OllamaAgentToolLoopError, w as OllamaAuthError, x as OllamaBadGatewayError, y as OllamaClientError, z as OllamaClientErrorOptions, J as OllamaErrorRequestContext, K as OllamaErrorResponseContext, Q as OllamaGenericClientError, U as OllamaIncompatibleModelError, V as OllamaMcpError, W as OllamaModelRoutingError, X as OllamaNetworkError, Y as OllamaNotFoundError, Z as OllamaOverloadedError, _ as OllamaQuotaExceededError, $ as OllamaRateLimitError, a0 as OllamaRequestTooLargeError, a1 as OllamaRequestValidationError, a2 as OllamaResponseValidationError, a3 as OllamaServerError, a4 as OllamaServerVersionUnknownError, a5 as OllamaSkillInvalidError, a6 as OllamaSkillNotFoundError, a7 as OllamaStreamError, a8 as OllamaTimeoutError, a9 as OllamaToolTimeoutError, aa as OllamaToolValidationError, ab as OllamaUnsupportedCapabilityError, ac as RequestContext, ad as RequestLifecycleEvent, ae as ResponseContext, af as SseEvent, ag as ThinkingEvent, ah as TokenEvent, ai as ToolCallEvent, aj as composeMiddleware, ak as createConsoleLogger, al as extractUsage, am as mapError, an as parseSseStream } from './runtime-DmI1cOEq.cjs';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
-
import { R as RequestRunner, S as SystemOneChoiceAnswer, o as SystemOneNoulAnswer, p as SystemOneScoreAnswer, q as SystemOneChoiceQuestion, r as SystemOneNoulQuestion, s as SystemOneScoreQuestion, t as SystemOneRequest$1, u as SystemOneResponse$1, v as SystemOneContent, N as NativeApi, w as OpenAICompatClient, x as AnthropicCompatClient } from './anthropic-
|
|
7
|
-
export { y as AnthropicCacheControl, z as AnthropicContentBlock, B as AnthropicImageContentBlock, C as AnthropicMessage, n as AnthropicMessageStreamEvent, A as AnthropicMessagesRequest, m as AnthropicMessagesResponse, D as AnthropicMessagesStream, E as AnthropicMetadata, F as AnthropicOutputConfig, G as AnthropicRedactedThinkingContentBlock, H as AnthropicSystem, I as AnthropicSystemTextBlock, J as AnthropicTextContentBlock, K as AnthropicThinkingConfig, L as AnthropicThinkingContentBlock, M as AnthropicTool, P as AnthropicToolChoice, Q as AnthropicToolResultContentBlock, T as AnthropicToolUseContentBlock, U as AnthropicUnknownStreamEvent, V as OllamaAnthropicContentBlock, W as OllamaAnthropicMessage, X as OllamaAnthropicMessagesRequest, Y as OllamaAnthropicSystem, Z as OllamaAnthropicSystemTextBlock, _ as OllamaAnthropicTextContentBlock, $ as OllamaAnthropicThinkingConfig, a0 as OllamaAnthropicTool, a1 as OllamaAnthropicToolResultContentBlock, a2 as OllamaOpenAIChatCompletionRequest, a3 as OllamaOpenAICompletionRequest, a4 as OllamaOpenAIEmbeddingRequest, a5 as OllamaOpenAIReasoningEffort, a6 as OllamaOpenAIResponsesRequest, a7 as OpenAIChatCompletionChoice, b as OpenAIChatCompletionChunk, a8 as OpenAIChatCompletionChunkChoice, a9 as OpenAIChatCompletionDelta, O as OpenAIChatCompletionRequest, a as OpenAIChatCompletionResponse, aa as OpenAIChatCompletionStream, ab as OpenAICompletionChoice, e as OpenAICompletionChunk, c as OpenAICompletionRequest, d as OpenAICompletionResponse, ac as OpenAICompletionStream, ad as OpenAIContentPart, ae as OpenAIEmbeddingInput, af as OpenAIEmbeddingItem, f as OpenAIEmbeddingRequest, g as OpenAIEmbeddingResponse, ag as OpenAIFunctionDefinition, ah as OpenAIImageUrlContentPart, h as OpenAIListModelsResponse, ai as OpenAIMessage, i as OpenAIModelItem, aj as OpenAIReasoningEffort, ak as OpenAIResponseFormat, al as OpenAIResponsesCompletedEvent, am as OpenAIResponsesContentPartAddedEvent, an as OpenAIResponsesContentPartDoneEvent, ao as OpenAIResponsesCreatedEvent, ap as OpenAIResponsesError, aq as OpenAIResponsesEventBase, ar as OpenAIResponsesFailedEvent, as as OpenAIResponsesFunctionCallArgumentsDeltaEvent, at as OpenAIResponsesFunctionCallArgumentsDoneEvent, au as OpenAIResponsesInProgressEvent, av as OpenAIResponsesIncompleteDetails, aw as OpenAIResponsesIncompleteEvent, ax as OpenAIResponsesOutputContent, ay as OpenAIResponsesOutputFunctionCall, az as OpenAIResponsesOutputItem, aA as OpenAIResponsesOutputItemAddedEvent, aB as OpenAIResponsesOutputItemDoneEvent, aC as OpenAIResponsesOutputMessage, aD as OpenAIResponsesOutputReasoning, aE as OpenAIResponsesOutputRefusal, aF as OpenAIResponsesOutputTextContent, aG as OpenAIResponsesOutputTextDeltaEvent, aH as OpenAIResponsesOutputTextDoneEvent, aI as OpenAIResponsesQueuedEvent, aJ as OpenAIResponsesReasoningSummaryPartAddedEvent, aK as OpenAIResponsesReasoningSummaryPartDoneEvent, aL as OpenAIResponsesReasoningSummaryTextDeltaEvent, aM as OpenAIResponsesReasoningSummaryTextDoneEvent, aN as OpenAIResponsesReasoningTextDeltaEvent, aO as OpenAIResponsesReasoningTextDoneEvent, aP as OpenAIResponsesRefusalDeltaEvent, aQ as OpenAIResponsesRefusalDoneEvent, j as OpenAIResponsesRequest, k as OpenAIResponsesResponse, aR as OpenAIResponsesStatus, aS as OpenAIResponsesStream, aT as OpenAIResponsesStreamError, l as OpenAIResponsesStreamEvent, aU as OpenAIResponsesUsage, aV as OpenAIStreamOptions, aW as OpenAITextContentPart, aX as OpenAITool, aY as OpenAIToolCall, aZ as OpenAIToolCallDelta, a_ as OpenAIUsage, a$ as SystemOneConfidence, b0 as SystemOneProbabilities } from './anthropic-
|
|
8
|
-
import { T as ToolHandler, a as Tool, A as AnyTool, b as ToolRegistry, c as ToolExecutionResult } from './compose-
|
|
9
|
-
export { d as AppliedSkillResult, e as ApplySkillOptions, P as ParsedFrontmatter, S as Skill, f as SkillFrontmatter, g as SkillSummary, h as ToolExecutionContext, i as ToolExecutionFailure, j as ToolExecutionSuccess, k as ToolRegistryOptions, l as applySkill, p as parseFrontmatter } from './compose-
|
|
6
|
+
import { R as RequestRunner, S as SystemOneChoiceAnswer, o as SystemOneNoulAnswer, p as SystemOneScoreAnswer, q as SystemOneChoiceQuestion, r as SystemOneNoulQuestion, s as SystemOneScoreQuestion, t as SystemOneRequest$1, u as SystemOneResponse$1, v as SystemOneContent, N as NativeApi, w as OpenAICompatClient, x as AnthropicCompatClient } from './anthropic-Did0lQxP.cjs';
|
|
7
|
+
export { y as AnthropicCacheControl, z as AnthropicContentBlock, B as AnthropicImageContentBlock, C as AnthropicMessage, n as AnthropicMessageStreamEvent, A as AnthropicMessagesRequest, m as AnthropicMessagesResponse, D as AnthropicMessagesStream, E as AnthropicMetadata, F as AnthropicOutputConfig, G as AnthropicRedactedThinkingContentBlock, H as AnthropicSystem, I as AnthropicSystemTextBlock, J as AnthropicTextContentBlock, K as AnthropicThinkingConfig, L as AnthropicThinkingContentBlock, M as AnthropicTool, P as AnthropicToolChoice, Q as AnthropicToolResultContentBlock, T as AnthropicToolUseContentBlock, U as AnthropicUnknownStreamEvent, V as OllamaAnthropicContentBlock, W as OllamaAnthropicMessage, X as OllamaAnthropicMessagesRequest, Y as OllamaAnthropicSystem, Z as OllamaAnthropicSystemTextBlock, _ as OllamaAnthropicTextContentBlock, $ as OllamaAnthropicThinkingConfig, a0 as OllamaAnthropicTool, a1 as OllamaAnthropicToolResultContentBlock, a2 as OllamaOpenAIChatCompletionRequest, a3 as OllamaOpenAICompletionRequest, a4 as OllamaOpenAIEmbeddingRequest, a5 as OllamaOpenAIReasoningEffort, a6 as OllamaOpenAIResponsesRequest, a7 as OpenAIChatCompletionChoice, b as OpenAIChatCompletionChunk, a8 as OpenAIChatCompletionChunkChoice, a9 as OpenAIChatCompletionDelta, O as OpenAIChatCompletionRequest, a as OpenAIChatCompletionResponse, aa as OpenAIChatCompletionStream, ab as OpenAICompletionChoice, e as OpenAICompletionChunk, c as OpenAICompletionRequest, d as OpenAICompletionResponse, ac as OpenAICompletionStream, ad as OpenAIContentPart, ae as OpenAIEmbeddingInput, af as OpenAIEmbeddingItem, f as OpenAIEmbeddingRequest, g as OpenAIEmbeddingResponse, ag as OpenAIFunctionDefinition, ah as OpenAIImageUrlContentPart, h as OpenAIListModelsResponse, ai as OpenAIMessage, i as OpenAIModelItem, aj as OpenAIReasoningEffort, ak as OpenAIResponseFormat, al as OpenAIResponsesCompletedEvent, am as OpenAIResponsesContentPartAddedEvent, an as OpenAIResponsesContentPartDoneEvent, ao as OpenAIResponsesCreatedEvent, ap as OpenAIResponsesError, aq as OpenAIResponsesEventBase, ar as OpenAIResponsesFailedEvent, as as OpenAIResponsesFunctionCallArgumentsDeltaEvent, at as OpenAIResponsesFunctionCallArgumentsDoneEvent, au as OpenAIResponsesInProgressEvent, av as OpenAIResponsesIncompleteDetails, aw as OpenAIResponsesIncompleteEvent, ax as OpenAIResponsesOutputContent, ay as OpenAIResponsesOutputFunctionCall, az as OpenAIResponsesOutputItem, aA as OpenAIResponsesOutputItemAddedEvent, aB as OpenAIResponsesOutputItemDoneEvent, aC as OpenAIResponsesOutputMessage, aD as OpenAIResponsesOutputReasoning, aE as OpenAIResponsesOutputRefusal, aF as OpenAIResponsesOutputTextContent, aG as OpenAIResponsesOutputTextDeltaEvent, aH as OpenAIResponsesOutputTextDoneEvent, aI as OpenAIResponsesQueuedEvent, aJ as OpenAIResponsesReasoningSummaryPartAddedEvent, aK as OpenAIResponsesReasoningSummaryPartDoneEvent, aL as OpenAIResponsesReasoningSummaryTextDeltaEvent, aM as OpenAIResponsesReasoningSummaryTextDoneEvent, aN as OpenAIResponsesReasoningTextDeltaEvent, aO as OpenAIResponsesReasoningTextDoneEvent, aP as OpenAIResponsesRefusalDeltaEvent, aQ as OpenAIResponsesRefusalDoneEvent, j as OpenAIResponsesRequest, k as OpenAIResponsesResponse, aR as OpenAIResponsesStatus, aS as OpenAIResponsesStream, aT as OpenAIResponsesStreamError, l as OpenAIResponsesStreamEvent, aU as OpenAIResponsesUsage, aV as OpenAIStreamOptions, aW as OpenAITextContentPart, aX as OpenAITool, aY as OpenAIToolCall, aZ as OpenAIToolCallDelta, a_ as OpenAIUsage, a$ as SystemOneConfidence, b0 as SystemOneProbabilities } from './anthropic-Did0lQxP.cjs';
|
|
8
|
+
import { T as ToolHandler, a as Tool, A as AnyTool, b as ToolRegistry, c as ToolExecutionResult } from './compose-DhvoUrWa.cjs';
|
|
9
|
+
export { d as AppliedSkillResult, e as ApplySkillOptions, P as ParsedFrontmatter, S as Skill, f as SkillFrontmatter, g as SkillSummary, h as ToolExecutionContext, i as ToolExecutionFailure, j as ToolExecutionSuccess, k as ToolRegistryOptions, l as applySkill, p as parseFrontmatter } from './compose-DhvoUrWa.cjs';
|
|
10
10
|
import { M as McpClientLike, a as McpToolDescriptor, b as McpTask, c as McpCallToolResult } from './types-CI-gM2u5.cjs';
|
|
11
11
|
export { d as McpContentBlock, e as McpCreateTaskResult, f as McpElicitationFormRequest, g as McpElicitationHandlers, h as McpElicitationRequest, i as McpElicitationResult, j as McpElicitationUrlRequest, k as McpIcon, l as McpInputRequiredResult, m as McpListToolsParams, n as McpListToolsResult, o as McpRequestOptions, p as McpServerCapabilities, q as McpTaskMethod, r as McpTaskRequest, s as McpTaskStatus, t as McpToolAnnotations, u as McpToolCallResult, v as McpToolExecution } from './types-CI-gM2u5.cjs';
|
|
12
12
|
import * as Otel from '@opentelemetry/api';
|
|
@@ -122,6 +122,220 @@ interface UsageResponse {
|
|
|
122
122
|
readonly buckets: readonly UsageBucket[];
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Model capability detection and runtime environment inference.
|
|
127
|
+
*/
|
|
128
|
+
|
|
129
|
+
type RuntimeMode = 'local' | 'cloud' | 'unknown';
|
|
130
|
+
/**
|
|
131
|
+
* Best-effort classification of a model's parallel tool-call emission
|
|
132
|
+
* behavior. Used by agent loops that need to know whether the model
|
|
133
|
+
* is likely to emit multiple `tool_calls` in a single assistant
|
|
134
|
+
* message (parallel) or one-at-a-time (sequential).
|
|
135
|
+
*
|
|
136
|
+
* This is a **heuristic** derived from runtime mode + model family
|
|
137
|
+
* pattern matching against `/api/show`'s reported model_info. The
|
|
138
|
+
* SDK does NOT normalize between cloud and local — it reports the
|
|
139
|
+
* best assessment it can and lets the caller decide how to act.
|
|
140
|
+
*
|
|
141
|
+
* See ADR 0023 for the rationale and the recommended caller pattern.
|
|
142
|
+
*/
|
|
143
|
+
type ParallelToolCallBehavior = 'yes' | 'no' | 'unknown';
|
|
144
|
+
interface ModelCapabilities {
|
|
145
|
+
readonly model: string;
|
|
146
|
+
readonly reported: readonly string[];
|
|
147
|
+
readonly supportsTools: boolean;
|
|
148
|
+
readonly supportsVision: boolean;
|
|
149
|
+
readonly supportsEmbedding: boolean;
|
|
150
|
+
readonly supportsCompletion: boolean;
|
|
151
|
+
readonly supportsThinking: boolean;
|
|
152
|
+
/** Model-defined thinking values and default, when /api/show reports them. */
|
|
153
|
+
readonly thinking?: ThinkingMetadata | undefined;
|
|
154
|
+
readonly supportsStreaming: true;
|
|
155
|
+
/** Maximum model context length reported by /api/show model_info, when available. */
|
|
156
|
+
readonly contextLength?: number | undefined;
|
|
157
|
+
/**
|
|
158
|
+
* Best-effort inference, not a guarantee: Ollama's `/api/show` does not report structured
|
|
159
|
+
* output support as a queryable capability, so this is inferred from {@link inferRuntimeMode}
|
|
160
|
+
* — `false` for `cloud`, since Ollama Cloud does not currently support structured outputs;
|
|
161
|
+
* `true` for `local`/`unknown`. A locally-hosted model that genuinely can't follow a JSON
|
|
162
|
+
* schema will still report `true` here; the request itself is the only reliable way to find
|
|
163
|
+
* out. `OllamaClient.chat`/`generate` apply this same inference as a fail-fast pre-flight
|
|
164
|
+
* guard whenever `format` is set, throwing `OllamaUnsupportedCapabilityError` rather than
|
|
165
|
+
* making a network call that Ollama Cloud is known to reject.
|
|
166
|
+
*/
|
|
167
|
+
readonly supportsStructuredOutputRequest: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Best-effort inference of whether the model is likely to emit
|
|
170
|
+
* **multiple `tool_calls` in a single assistant message** (parallel)
|
|
171
|
+
* vs **one tool call per assistant turn** (sequential).
|
|
172
|
+
*
|
|
173
|
+
* The SDK does NOT normalize between cloud and local — it reports
|
|
174
|
+
* the best assessment it can and lets the caller decide. Agent
|
|
175
|
+
* authors who need hard sequential execution should set
|
|
176
|
+
* `ToolRegistry`'s `maxConcurrency: 1` regardless of this field's
|
|
177
|
+
* value, since the model's behavior is not deterministic across
|
|
178
|
+
* prompts.
|
|
179
|
+
*
|
|
180
|
+
* Inference matrix (see ADR 0023):
|
|
181
|
+
*
|
|
182
|
+
* - **`'yes'`** — the model is known to emit parallel tool calls:
|
|
183
|
+
* - Cloud-mode endpoints (the OpenAI/Anthropic compat bridges
|
|
184
|
+
* proxy to proprietary models like GPT-4o, Claude, which
|
|
185
|
+
* freely emit parallel tool calls).
|
|
186
|
+
* - Local models from families that ship with parallel-tool-call
|
|
187
|
+
* training (Qwen 2.5+, Llama 3.1+ tool-use variants, Mistral
|
|
188
|
+
* function-calling fine-tunes, Hermes 2/3, Command R+).
|
|
189
|
+
*
|
|
190
|
+
* - **`'no'`** — the model is known to emit at most one tool call
|
|
191
|
+
* per assistant turn. Currently no model family is classified
|
|
192
|
+
* as `'no'` by default; the field is reserved for future
|
|
193
|
+
* narrowing as more is learned about specific models.
|
|
194
|
+
*
|
|
195
|
+
* - **`'unknown'`** — the model family is not in the known-yes or
|
|
196
|
+
* known-no list, OR `/api/show` didn't return enough
|
|
197
|
+
* information to make an assessment. Callers should treat
|
|
198
|
+
* `'unknown'` as "ask the model and see what it does" — the
|
|
199
|
+
* `ToolRegistry` will execute whatever calls the model emits,
|
|
200
|
+
* in parallel via `Promise.all` by default.
|
|
201
|
+
*
|
|
202
|
+
* See: `src/tools/registry.ts` for `maxConcurrency` enforcement,
|
|
203
|
+
* and ADR 0023 for the full design rationale.
|
|
204
|
+
*/
|
|
205
|
+
readonly parallelToolCalls: ParallelToolCallBehavior;
|
|
206
|
+
}
|
|
207
|
+
declare function inferRuntimeMode(baseUrl: string): RuntimeMode;
|
|
208
|
+
/**
|
|
209
|
+
* Scans `/api/show`'s `model_info` for the model's **native** context length
|
|
210
|
+
* (keys are architecture-prefixed: `llama.context_length`,
|
|
211
|
+
* `gemma4.context_length`, …). Also re-exported by `src/context-discovery.ts`
|
|
212
|
+
* as `extractNativeContextLength` for the context-window discovery flow.
|
|
213
|
+
*/
|
|
214
|
+
declare function extractContextLength(modelInfo?: Record<string, unknown>): number | undefined;
|
|
215
|
+
declare function detectModelCapabilities(http: HttpClient, model: string, signal?: AbortSignal): Promise<ModelCapabilities>;
|
|
216
|
+
declare function listAvailableModels(http: HttpClient): Promise<ModelResponse[]>;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Dynamic context-window discovery.
|
|
220
|
+
*
|
|
221
|
+
* Guessing context windows ("it's probably 2048… or 4096?") is how silent
|
|
222
|
+
* truncation happens. Ollama advertises the real numbers in two places, and
|
|
223
|
+
* they answer *different questions*:
|
|
224
|
+
*
|
|
225
|
+
* - **`GET /api/ps`** reports `context_length` for every currently-running
|
|
226
|
+
* model — the window the runner has **actually allocated**. This is the
|
|
227
|
+
* exact, server-enforced number: it already reflects the model's Modelfile
|
|
228
|
+
* `num_ctx` default (if any) and the memory the runner was able to claim.
|
|
229
|
+
* Only meaningful while the model is loaded.
|
|
230
|
+
* - **`POST /api/show`** exposes two deeper signals in its response:
|
|
231
|
+
* - `model_info["<architecture>.context_length"]` — the model's **native**
|
|
232
|
+
* maximum from its GGUF metadata (e.g. `gemma4.context_length: 131072`).
|
|
233
|
+
* This is the ceiling you could raise `num_ctx` to, not the window you
|
|
234
|
+
* have. The official API examples show a model whose native max is
|
|
235
|
+
* 131072 while its running instance allocated 4096 — a 32× gap.
|
|
236
|
+
* - `parameters` — the Modelfile's serialized option list; a
|
|
237
|
+
* `num_ctx <n>` line (when the model's author set one) is the default
|
|
238
|
+
* window the runner will allocate for this model.
|
|
239
|
+
*
|
|
240
|
+
* `OllamaClient.models.getContextLength()` consults them in precedence order
|
|
241
|
+
* (see {@link resolveContextLength}) and returns every signal it found, so
|
|
242
|
+
* callers can both act on the effective window *now* and know how much
|
|
243
|
+
* headroom exists for raising it.
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
/** Request shape for {@link ModelsClient.getContextLength}. */
|
|
247
|
+
interface ContextDiscoveryRequestOptions extends RequestCancellationOptions {
|
|
248
|
+
/** Model to introspect (tag optional — `"llama3.1"` matches `"llama3.1:latest"`). */
|
|
249
|
+
readonly model: string;
|
|
250
|
+
/**
|
|
251
|
+
* Skip the `GET /api/ps` lookup — e.g. on cloud endpoints where the local
|
|
252
|
+
* running-models listing isn't meaningful, or when the extra round-trip
|
|
253
|
+
* isn't wanted. Discovery then falls back to `/api/show` signals only.
|
|
254
|
+
*/
|
|
255
|
+
readonly skipRunningCheck?: boolean | undefined;
|
|
256
|
+
}
|
|
257
|
+
/** Where a discovered context window came from, in precedence order. */
|
|
258
|
+
type ContextLengthSource =
|
|
259
|
+
/** `GET /api/ps` — window actually allocated by the running instance (exact). */
|
|
260
|
+
'running'
|
|
261
|
+
/** `POST /api/show` `parameters` — Modelfile-authored `num_ctx` default. */
|
|
262
|
+
| 'parameters'
|
|
263
|
+
/** `POST /api/show` `model_info["*.context_length"]` — native GGUF maximum. */
|
|
264
|
+
| 'model-info'
|
|
265
|
+
/** Nothing discoverable — Ollama's conservative unset-`num_ctx` default (2048). */
|
|
266
|
+
| 'fallback';
|
|
267
|
+
/** Result of {@link ModelsClient.getContextLength}. */
|
|
268
|
+
interface DiscoveredContextLength {
|
|
269
|
+
/**
|
|
270
|
+
* The effective context window to program against, resolved by precedence:
|
|
271
|
+
* `running` (exact, when loaded) → `parameters` (Modelfile default) →
|
|
272
|
+
* `model-info` (native max) → `2048` fallback.
|
|
273
|
+
*/
|
|
274
|
+
readonly contextLength: number;
|
|
275
|
+
/** Which source produced {@link contextLength}. */
|
|
276
|
+
readonly source: ContextLengthSource;
|
|
277
|
+
/** Window allocated by the running instance, when the model is loaded and reports it. */
|
|
278
|
+
readonly runningContextLength?: number | undefined;
|
|
279
|
+
/** Modelfile `num_ctx` default from `/api/show`'s `parameters` string, when set. */
|
|
280
|
+
readonly parameterContextLength?: number | undefined;
|
|
281
|
+
/** Native GGUF maximum from `model_info["*.context_length"]`, when reported. */
|
|
282
|
+
readonly nativeContextLength?: number | undefined;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Parses `num_ctx <n>` out of `/api/show`'s `parameters` string.
|
|
286
|
+
*
|
|
287
|
+
* The string is the Modelfile's serialized option list — one `name value`
|
|
288
|
+
* pair per line, value separated by whitespace padding, e.g.
|
|
289
|
+
* `"num_stop 8192\nnum_ctx 4096"`. Returns `undefined` when no positive
|
|
290
|
+
* integer `num_ctx` line is present.
|
|
291
|
+
*/
|
|
292
|
+
declare function extractParameterNumCtx(parameters?: string | undefined): number | undefined;
|
|
293
|
+
/**
|
|
294
|
+
* Whether `model` is currently resident (loaded in VRAM) per a `GET /api/ps`
|
|
295
|
+
* response — exact or tag-less-prefix match, same resolution rules as Ollama
|
|
296
|
+
* itself applies to model names. See {@link matchesModelReference}.
|
|
297
|
+
*/
|
|
298
|
+
declare function isModelResident(psModels: readonly {
|
|
299
|
+
readonly name?: string | undefined;
|
|
300
|
+
readonly model?: string | undefined;
|
|
301
|
+
}[], model: string): boolean;
|
|
302
|
+
/**
|
|
303
|
+
* Finds the context window Ollama actually allocated for `model`, from a
|
|
304
|
+
* `GET /api/ps` response. Matching mirrors Ollama's own model resolution:
|
|
305
|
+
* exact match on the entry's `name`/`model`, or — when `model` carries no
|
|
306
|
+
* tag — any entry whose name starts with `<model>:`.
|
|
307
|
+
*
|
|
308
|
+
* Returns `undefined` when the model isn't loaded or the running entry
|
|
309
|
+
* doesn't report `context_length` (older server versions).
|
|
310
|
+
*/
|
|
311
|
+
declare function findRunningModelContextLength(psModels: readonly ModelResponse[], model: string): number | undefined;
|
|
312
|
+
/** Internal inputs to {@link resolveContextLength}; each signal independently optional. */
|
|
313
|
+
interface ContextLengthSignals {
|
|
314
|
+
readonly running?: number | undefined;
|
|
315
|
+
readonly parameter?: number | undefined;
|
|
316
|
+
readonly native?: number | undefined;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Resolves the effective context window from whatever signals were
|
|
320
|
+
* discovered, by precedence:
|
|
321
|
+
*
|
|
322
|
+
* 1. **`running`** — the allocated window of the loaded instance. When the
|
|
323
|
+
* model is in memory this is the ground truth; it already incorporates
|
|
324
|
+
* any Modelfile `num_ctx` default.
|
|
325
|
+
* 2. **`parameter`** — the Modelfile's `num_ctx`, i.e. the window the
|
|
326
|
+
* runner *will* allocate for this model on the next cold load.
|
|
327
|
+
* 3. **`native`** — the GGUF maximum. Only used when nothing tighter is
|
|
328
|
+
* known: a fresh `num_ctx`-less load may allocate far less than native
|
|
329
|
+
* (Ollama's conservative default), so native is a *ceiling*, not an
|
|
330
|
+
* expectation.
|
|
331
|
+
* 4. **Fallback** — {@link OLLAMA_FALLBACK_CONTEXT_LENGTH} (2048), the
|
|
332
|
+
* conservative server-side default, so the result is always actionable.
|
|
333
|
+
*
|
|
334
|
+
* Pure — used by `ModelsClient.getContextLength()` and exported for callers
|
|
335
|
+
* that already hold `/api/ps` / `/api/show` responses.
|
|
336
|
+
*/
|
|
337
|
+
declare function resolveContextLength(signals: ContextLengthSignals): DiscoveredContextLength;
|
|
338
|
+
|
|
125
339
|
/**
|
|
126
340
|
* Exponential backoff with full jitter calculation.
|
|
127
341
|
*/
|
|
@@ -152,9 +366,133 @@ declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
|
|
152
366
|
*/
|
|
153
367
|
declare function withRetry<T>(operation: (attempt: number) => Promise<T>, config?: RetryConfig, signal?: AbortSignal): Promise<T>;
|
|
154
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Multi-host model-affinity routing — prefer the endpoint already holding the
|
|
371
|
+
* requested model in VRAM.
|
|
372
|
+
*
|
|
373
|
+
* Ollama daemons keep a bounded set of models resident (`OLLAMA_MAX_LOADED_MODELS`).
|
|
374
|
+
* With several interchangeable endpoints serving the same models, sending a request
|
|
375
|
+
* to a host that doesn't currently hold the model forces an unload/cold-load swap
|
|
376
|
+
* on that host — the thrashing `ModelAffinityScheduler` avoids for a *single*
|
|
377
|
+
* client's task queues. This router brings the same affinity to the *multi-host*
|
|
378
|
+
* request path: given the candidate endpoints `executeWithFailover` would try
|
|
379
|
+
* anyway, it reorders them so hosts whose `GET /api/ps` shows the requested model
|
|
380
|
+
* resident come first.
|
|
381
|
+
*
|
|
382
|
+
* Design constraints (see ADR 0028):
|
|
383
|
+
*
|
|
384
|
+
* - **Zero added request latency.** Reordering is synchronous and consults only
|
|
385
|
+
* cached `/api/ps` snapshots. A request never waits for a probe: when a
|
|
386
|
+
* snapshot is missing or stale, the request proceeds with the unchanged
|
|
387
|
+
* candidate order and the refresh happens in the background, warming the cache
|
|
388
|
+
* for subsequent requests.
|
|
389
|
+
* - **Race-free with `least-connections`.** The reorder runs entirely between the
|
|
390
|
+
* registry's synchronous `candidates()`/`filterWithCapacity()` and the
|
|
391
|
+
* endpoint's `acquire()` — no `await` in between — so the strategy's
|
|
392
|
+
* no-two-calls-pick-the-same-idle-endpoint guarantee is untouched. Affinity
|
|
393
|
+
* only reorders *within* the runnable set; priority tiers and per-strategy
|
|
394
|
+
* ordering stay intact inside the resident/non-resident groups.
|
|
395
|
+
* - **Best-effort, never blocking, never failing a request.** A probe failure is
|
|
396
|
+
* recorded with a short backoff (`failureRetryMs`) and never cached as data;
|
|
397
|
+
* the affected endpoint is simply treated as unknown until a probe succeeds.
|
|
398
|
+
* - **Fresh-data-only decisions.** Only snapshots within `ttlMs` reorder
|
|
399
|
+
* requests — `/api/ps` can change at any moment (evictions, other clients),
|
|
400
|
+
* so stale data is treated as no data. Last-known snapshots are still exposed
|
|
401
|
+
* via `status()` for observability.
|
|
402
|
+
*/
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* One `/api/ps` running-model entry, as the router consumes it — name/model only.
|
|
406
|
+
* Optional to match the generated `Ps` wire shape; hand-written `ModelResponse`
|
|
407
|
+
* values (required fields) are assignable as-is.
|
|
408
|
+
*/
|
|
409
|
+
interface AffinityRunningModel {
|
|
410
|
+
readonly name?: string | undefined;
|
|
411
|
+
readonly model?: string | undefined;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Options for dynamic model-affinity routing across endpoints. Configured under
|
|
415
|
+
* `OllamaClientConfig.endpointHealth.modelAffinity`; implemented by
|
|
416
|
+
* `OllamaClient`'s request path (`executeWithFailover`), which has HTTP access —
|
|
417
|
+
* the `EndpointRegistry` itself ignores this key.
|
|
418
|
+
*/
|
|
419
|
+
interface ModelAffinityRoutingOptions {
|
|
420
|
+
/**
|
|
421
|
+
* How long a `GET /api/ps` snapshot stays fresh enough to reorder requests
|
|
422
|
+
* (default 30_000ms). Mirrors `ModelAffinityScheduler`'s `psCacheTtlMs`.
|
|
423
|
+
*/
|
|
424
|
+
readonly ttlMs?: number | undefined;
|
|
425
|
+
/**
|
|
426
|
+
* How long a failed `/api/ps` probe suppresses retries against that endpoint
|
|
427
|
+
* (default 5_000ms) — a dead host isn't probed on every request while it's
|
|
428
|
+
* down, and comes back automatically once it recovers. Failures are never
|
|
429
|
+
* cached as data.
|
|
430
|
+
*/
|
|
431
|
+
readonly failureRetryMs?: number | undefined;
|
|
432
|
+
}
|
|
433
|
+
/** Introspection snapshot for one endpoint's affinity cache. */
|
|
434
|
+
interface ModelAffinitySnapshot {
|
|
435
|
+
readonly endpointName: string;
|
|
436
|
+
readonly baseUrl: string;
|
|
437
|
+
/** Model names reported resident by the last successful probe (may be stale). */
|
|
438
|
+
readonly loadedModels: readonly string[];
|
|
439
|
+
/** When the last successful probe completed — `undefined` if it never succeeded. */
|
|
440
|
+
readonly fetchedAt: number | undefined;
|
|
441
|
+
/** Whether the snapshot is within `ttlMs` and therefore still drives reordering. */
|
|
442
|
+
readonly fresh: boolean;
|
|
443
|
+
}
|
|
444
|
+
/** Test seam: injectable clock — defaults to `Date.now`. */
|
|
445
|
+
type NowFn = () => number;
|
|
446
|
+
/**
|
|
447
|
+
* Cache-and-reorder engine for multi-host model affinity. See the module docs for
|
|
448
|
+
* the design constraints; `OllamaClient` constructs one (only when
|
|
449
|
+
* `endpointHealth.modelAffinity` is set) and calls {@link reorder} synchronously
|
|
450
|
+
* inside its request path.
|
|
451
|
+
*/
|
|
452
|
+
declare class ModelAffinityRouter {
|
|
453
|
+
private readonly fetchPs;
|
|
454
|
+
private readonly ttlMs;
|
|
455
|
+
private readonly failureRetryMs;
|
|
456
|
+
private readonly now;
|
|
457
|
+
private readonly cache;
|
|
458
|
+
private readonly failedAt;
|
|
459
|
+
private readonly inflight;
|
|
460
|
+
constructor(fetchPs: (endpoint: OllamaEndpoint) => Promise<readonly AffinityRunningModel[]>, options?: ModelAffinityRoutingOptions & {
|
|
461
|
+
readonly now?: NowFn;
|
|
462
|
+
});
|
|
463
|
+
/**
|
|
464
|
+
* Synchronously reorders `candidates` so endpoints whose fresh `/api/ps`
|
|
465
|
+
* snapshot shows `model` resident come first (relative order preserved within
|
|
466
|
+
* each group). Returns the input unchanged — and kicks a background refresh —
|
|
467
|
+
* when any candidate's snapshot is missing or stale: a wrong reorder is worse
|
|
468
|
+
* than no reorder, and the first request after a cache miss simply isn't
|
|
469
|
+
* reordered. No-op without a `model` or with fewer than two candidates.
|
|
470
|
+
*/
|
|
471
|
+
reorder(candidates: readonly OllamaEndpoint[], model: string | undefined): readonly OllamaEndpoint[];
|
|
472
|
+
/**
|
|
473
|
+
* Forces a refresh of the affinity cache for the given endpoints (deduped with
|
|
474
|
+
* any in-flight refresh; bypasses the failure backoff, because this is an
|
|
475
|
+
* explicit caller request — `client.warmModelAffinity()`). Resolves once every
|
|
476
|
+
* probe has settled — successfully or not; individual failures never reject.
|
|
477
|
+
*/
|
|
478
|
+
warm(endpoints: readonly OllamaEndpoint[]): Promise<void>;
|
|
479
|
+
/** Introspection snapshots for the given endpoints (defaults to cached ones). */
|
|
480
|
+
status(endpoints?: readonly OllamaEndpoint[]): readonly ModelAffinitySnapshot[];
|
|
481
|
+
/**
|
|
482
|
+
* Starts (or joins) a background refresh for `endpoint`, unless one is already
|
|
483
|
+
* in flight or the failure backoff suppresses it. Fire-and-forget: the promise
|
|
484
|
+
* is stored only for dedupe/warm-joins; callers never await it on the request
|
|
485
|
+
* path.
|
|
486
|
+
*/
|
|
487
|
+
private kickRefresh;
|
|
488
|
+
/** Refreshes one endpoint's snapshot; never rejects (failures record a backoff). */
|
|
489
|
+
private refresh;
|
|
490
|
+
}
|
|
491
|
+
|
|
155
492
|
/**
|
|
156
493
|
* Multi-endpoint registry with priority routing and circuit breaker failover.
|
|
157
494
|
*/
|
|
495
|
+
|
|
158
496
|
interface OllamaEndpoint {
|
|
159
497
|
readonly name: string;
|
|
160
498
|
readonly baseUrl: string;
|
|
@@ -222,6 +560,18 @@ interface EndpointRegistryOptions {
|
|
|
222
560
|
* any other in-flight request — it never blocks indefinitely on its own.
|
|
223
561
|
*/
|
|
224
562
|
readonly maxConcurrentPerEndpoint?: number | undefined;
|
|
563
|
+
/**
|
|
564
|
+
* Dynamic model-affinity routing across endpoints: reorder each request's
|
|
565
|
+
* candidates so endpoints whose `GET /api/ps` shows the requested model already
|
|
566
|
+
* resident in VRAM are tried first — avoiding unload/cold-load swaps on
|
|
567
|
+
* `OLLAMA_MAX_LOADED_MODELS`-bounded daemons. Off unless set.
|
|
568
|
+
*
|
|
569
|
+
* Implemented by `OllamaClient`'s request path (`executeWithFailover` + a
|
|
570
|
+
* TTL-cached `ModelAffinityRouter`), not by this registry — the registry is a
|
|
571
|
+
* pure, HTTP-free data structure and simply ignores this key. See
|
|
572
|
+
* `src/providers/model-affinity-router.ts` and ADR 0028.
|
|
573
|
+
*/
|
|
574
|
+
readonly modelAffinity?: ModelAffinityRoutingOptions | undefined;
|
|
225
575
|
}
|
|
226
576
|
declare class EndpointRegistry {
|
|
227
577
|
private readonly endpoints;
|
|
@@ -445,92 +795,6 @@ interface EndpointHealthCheckResult {
|
|
|
445
795
|
}
|
|
446
796
|
declare function checkEndpointHealth(endpoint: OllamaEndpoint, fetchImpl?: FetchLike, timeoutMs?: number, middleware?: readonly Middleware[] | undefined, onLifecycleEvent?: RequestLifecycleHook | undefined): Promise<EndpointHealthCheckResult>;
|
|
447
797
|
|
|
448
|
-
/**
|
|
449
|
-
* Model capability detection and runtime environment inference.
|
|
450
|
-
*/
|
|
451
|
-
|
|
452
|
-
type RuntimeMode = 'local' | 'cloud' | 'unknown';
|
|
453
|
-
/**
|
|
454
|
-
* Best-effort classification of a model's parallel tool-call emission
|
|
455
|
-
* behavior. Used by agent loops that need to know whether the model
|
|
456
|
-
* is likely to emit multiple `tool_calls` in a single assistant
|
|
457
|
-
* message (parallel) or one-at-a-time (sequential).
|
|
458
|
-
*
|
|
459
|
-
* This is a **heuristic** derived from runtime mode + model family
|
|
460
|
-
* pattern matching against `/api/show`'s reported model_info. The
|
|
461
|
-
* SDK does NOT normalize between cloud and local — it reports the
|
|
462
|
-
* best assessment it can and lets the caller decide how to act.
|
|
463
|
-
*
|
|
464
|
-
* See ADR 0023 for the rationale and the recommended caller pattern.
|
|
465
|
-
*/
|
|
466
|
-
type ParallelToolCallBehavior = 'yes' | 'no' | 'unknown';
|
|
467
|
-
interface ModelCapabilities {
|
|
468
|
-
readonly model: string;
|
|
469
|
-
readonly reported: readonly string[];
|
|
470
|
-
readonly supportsTools: boolean;
|
|
471
|
-
readonly supportsVision: boolean;
|
|
472
|
-
readonly supportsEmbedding: boolean;
|
|
473
|
-
readonly supportsCompletion: boolean;
|
|
474
|
-
readonly supportsThinking: boolean;
|
|
475
|
-
/** Model-defined thinking values and default, when /api/show reports them. */
|
|
476
|
-
readonly thinking?: ThinkingMetadata | undefined;
|
|
477
|
-
readonly supportsStreaming: true;
|
|
478
|
-
/** Maximum model context length reported by /api/show model_info, when available. */
|
|
479
|
-
readonly contextLength?: number | undefined;
|
|
480
|
-
/**
|
|
481
|
-
* Best-effort inference, not a guarantee: Ollama's `/api/show` does not report structured
|
|
482
|
-
* output support as a queryable capability, so this is inferred from {@link inferRuntimeMode}
|
|
483
|
-
* — `false` for `cloud`, since Ollama Cloud does not currently support structured outputs;
|
|
484
|
-
* `true` for `local`/`unknown`. A locally-hosted model that genuinely can't follow a JSON
|
|
485
|
-
* schema will still report `true` here; the request itself is the only reliable way to find
|
|
486
|
-
* out. `OllamaClient.chat`/`generate` apply this same inference as a fail-fast pre-flight
|
|
487
|
-
* guard whenever `format` is set, throwing `OllamaUnsupportedCapabilityError` rather than
|
|
488
|
-
* making a network call that Ollama Cloud is known to reject.
|
|
489
|
-
*/
|
|
490
|
-
readonly supportsStructuredOutputRequest: boolean;
|
|
491
|
-
/**
|
|
492
|
-
* Best-effort inference of whether the model is likely to emit
|
|
493
|
-
* **multiple `tool_calls` in a single assistant message** (parallel)
|
|
494
|
-
* vs **one tool call per assistant turn** (sequential).
|
|
495
|
-
*
|
|
496
|
-
* The SDK does NOT normalize between cloud and local — it reports
|
|
497
|
-
* the best assessment it can and lets the caller decide. Agent
|
|
498
|
-
* authors who need hard sequential execution should set
|
|
499
|
-
* `ToolRegistry`'s `maxConcurrency: 1` regardless of this field's
|
|
500
|
-
* value, since the model's behavior is not deterministic across
|
|
501
|
-
* prompts.
|
|
502
|
-
*
|
|
503
|
-
* Inference matrix (see ADR 0023):
|
|
504
|
-
*
|
|
505
|
-
* - **`'yes'`** — the model is known to emit parallel tool calls:
|
|
506
|
-
* - Cloud-mode endpoints (the OpenAI/Anthropic compat bridges
|
|
507
|
-
* proxy to proprietary models like GPT-4o, Claude, which
|
|
508
|
-
* freely emit parallel tool calls).
|
|
509
|
-
* - Local models from families that ship with parallel-tool-call
|
|
510
|
-
* training (Qwen 2.5+, Llama 3.1+ tool-use variants, Mistral
|
|
511
|
-
* function-calling fine-tunes, Hermes 2/3, Command R+).
|
|
512
|
-
*
|
|
513
|
-
* - **`'no'`** — the model is known to emit at most one tool call
|
|
514
|
-
* per assistant turn. Currently no model family is classified
|
|
515
|
-
* as `'no'` by default; the field is reserved for future
|
|
516
|
-
* narrowing as more is learned about specific models.
|
|
517
|
-
*
|
|
518
|
-
* - **`'unknown'`** — the model family is not in the known-yes or
|
|
519
|
-
* known-no list, OR `/api/show` didn't return enough
|
|
520
|
-
* information to make an assessment. Callers should treat
|
|
521
|
-
* `'unknown'` as "ask the model and see what it does" — the
|
|
522
|
-
* `ToolRegistry` will execute whatever calls the model emits,
|
|
523
|
-
* in parallel via `Promise.all` by default.
|
|
524
|
-
*
|
|
525
|
-
* See: `src/tools/registry.ts` for `maxConcurrency` enforcement,
|
|
526
|
-
* and ADR 0023 for the full design rationale.
|
|
527
|
-
*/
|
|
528
|
-
readonly parallelToolCalls: ParallelToolCallBehavior;
|
|
529
|
-
}
|
|
530
|
-
declare function inferRuntimeMode(baseUrl: string): RuntimeMode;
|
|
531
|
-
declare function detectModelCapabilities(http: HttpClient, model: string, signal?: AbortSignal): Promise<ModelCapabilities>;
|
|
532
|
-
declare function listAvailableModels(http: HttpClient): Promise<ModelResponse[]>;
|
|
533
|
-
|
|
534
798
|
/**
|
|
535
799
|
* Dual-mode (AsyncIterator and EventEmitter-like) stream wrapper.
|
|
536
800
|
*/
|
|
@@ -606,7 +870,39 @@ declare class ModelsClient {
|
|
|
606
870
|
create(request: CreateRequestOptions): Promise<ProgressResponse | OllamaStream<ProgressResponse, ProgressStreamResult>>;
|
|
607
871
|
delete(request: DeleteRequestOptions): Promise<StatusResponse>;
|
|
608
872
|
copy(request: CopyRequestOptions): Promise<StatusResponse>;
|
|
609
|
-
ps(): Promise<PsResponse>;
|
|
873
|
+
ps(request?: RequestCancellationOptions): Promise<PsResponse>;
|
|
874
|
+
/**
|
|
875
|
+
* Discovers the model's real context window from the server — no more
|
|
876
|
+
* 2048/4096 guesswork. Consults, in precedence order:
|
|
877
|
+
*
|
|
878
|
+
* 1. `GET /api/ps` — the window the **running instance actually
|
|
879
|
+
* allocated** (exact, reflects the Modelfile `num_ctx` default and
|
|
880
|
+
* what fit in memory); skipped when the model isn't loaded, when
|
|
881
|
+
* `skipRunningCheck` is set, or harmlessly on servers without the
|
|
882
|
+
* field.
|
|
883
|
+
* 2. `POST /api/show` `parameters` — a Modelfile-authored
|
|
884
|
+
* `num_ctx <n>` default, i.e. the window a cold load will allocate.
|
|
885
|
+
* 3. `POST /api/show` `model_info["<arch>.context_length"]` — the
|
|
886
|
+
* model's **native GGUF maximum** (a ceiling to raise `num_ctx`
|
|
887
|
+
* toward, not the allocated window).
|
|
888
|
+
* 4. Fallback — Ollama's conservative unset-`num_ctx` default (2048).
|
|
889
|
+
*
|
|
890
|
+
* The result carries every signal it found, so `nativeContextLength:
|
|
891
|
+
* 131072` vs `contextLength: 4096` (a 32× gap seen in the official API
|
|
892
|
+
* examples) is visible rather than guessed. Typical wiring:
|
|
893
|
+
*
|
|
894
|
+
* ```ts
|
|
895
|
+
* const { contextLength, source, nativeContextLength } =
|
|
896
|
+
* await client.models.getContextLength({ model: 'gemma4' });
|
|
897
|
+
* // -> { contextLength: 4096, source: 'running', nativeContextLength: 131072 }
|
|
898
|
+
* ```
|
|
899
|
+
*
|
|
900
|
+
* Makes two server calls (`/api/ps` + `/api/show`) unless
|
|
901
|
+
* `skipRunningCheck` is set. A 404 from `/api/ps` (endpoint without the
|
|
902
|
+
* listing) is treated as "not running" and never fails the lookup;
|
|
903
|
+
* other transport errors propagate normally.
|
|
904
|
+
*/
|
|
905
|
+
getContextLength(request: ContextDiscoveryRequestOptions): Promise<DiscoveredContextLength>;
|
|
610
906
|
version(): Promise<VersionResponse>;
|
|
611
907
|
/**
|
|
612
908
|
* Immediately unloads `model` from VRAM/RAM by issuing an empty
|
|
@@ -904,6 +1200,147 @@ interface SessionTurn {
|
|
|
904
1200
|
/** The full underlying `/api/chat` response (usage, durations, thinking, …). */
|
|
905
1201
|
readonly response: ChatResponse;
|
|
906
1202
|
}
|
|
1203
|
+
/** Options for {@link compactConversationHistory} / {@link ConversationSession.compact}. */
|
|
1204
|
+
interface CompactionOptions {
|
|
1205
|
+
/**
|
|
1206
|
+
* Estimated-token budget the compacted history must fit within (including
|
|
1207
|
+
* any retained system message and the 10%-style reply reservation below).
|
|
1208
|
+
* Estimated with the same CJK-aware heuristic as the pre-flight checks
|
|
1209
|
+
* (`estimateMessageTokens` — ±20–30%, message overhead + tool calls +
|
|
1210
|
+
* `IMAGE_TOKEN_ESTIMATE` per image included).
|
|
1211
|
+
*/
|
|
1212
|
+
readonly maxEstimatedTokens: number;
|
|
1213
|
+
/**
|
|
1214
|
+
* Tokens subtracted from the budget and reserved for the model's next
|
|
1215
|
+
* reply (default `0` for the pure function; `session.compact()` defaults
|
|
1216
|
+
* to ~10% of the window, mirroring the pre-flight warning threshold's
|
|
1217
|
+
* headroom).
|
|
1218
|
+
*/
|
|
1219
|
+
readonly reserveForReply?: number | undefined;
|
|
1220
|
+
/**
|
|
1221
|
+
* Trailing messages always retained, even when they don't fit the budget
|
|
1222
|
+
* (default `2` — the latest user/assistant exchange). Guarantees a
|
|
1223
|
+
* compacted conversation never loses its most recent context; an
|
|
1224
|
+
* oversized tail is retained deliberately rather than truncated, because
|
|
1225
|
+
* silent truncation is the server's failure mode, not one this SDK
|
|
1226
|
+
* reproduces.
|
|
1227
|
+
*/
|
|
1228
|
+
readonly minTailMessages?: number | undefined;
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Sliding-window history compaction: keep the pinned system message(s) plus
|
|
1232
|
+
* the most recent turns that fit `maxEstimatedTokens`, dropping the oldest
|
|
1233
|
+
* turns in between.
|
|
1234
|
+
*
|
|
1235
|
+
* Deliberately **not** automatic anywhere in the SDK: compaction rewrites the
|
|
1236
|
+
* prompt prefix, so the next request's KV-cache hit rate drops to zero and
|
|
1237
|
+
* the whole retained suffix re-evaluates. That tradeoff (latency + recompute
|
|
1238
|
+
* for a window that now fits) is sometimes exactly right — long-running
|
|
1239
|
+
* agent threads that would otherwise silently lose their oldest turns — and
|
|
1240
|
+
* sometimes catastrophic (a hot cache-friendly session that never actually
|
|
1241
|
+
* overflows). `ConversationSession.cacheStats` makes the "session no longer
|
|
1242
|
+
* fits" case visible; this function is the explicit, caller-initiated fix.
|
|
1243
|
+
*
|
|
1244
|
+
* Semantics:
|
|
1245
|
+
*
|
|
1246
|
+
* - **Leading `system` messages are always retained** and count against
|
|
1247
|
+
* the budget (they consume context too).
|
|
1248
|
+
* - Non-system messages are walked newest → oldest; each is retained while
|
|
1249
|
+
* it fits the remaining budget, or while fewer than `minTailMessages`
|
|
1250
|
+
* have been retained.
|
|
1251
|
+
* - Mid-conversation `system`/`tool` messages are ordinary tailable
|
|
1252
|
+
* history (only the *leading* system block is pinned).
|
|
1253
|
+
* - Returns a new array; the input is never mutated. Message objects are
|
|
1254
|
+
* reused by reference (sessions freeze them; external arrays are copied
|
|
1255
|
+
* defensively by the caller if needed).
|
|
1256
|
+
*
|
|
1257
|
+
* ```ts
|
|
1258
|
+
* const kept = compactConversationHistory(session.getMessages(), {
|
|
1259
|
+
* maxEstimatedTokens: window.contextLength,
|
|
1260
|
+
* reserveForReply: 512,
|
|
1261
|
+
* });
|
|
1262
|
+
* ```
|
|
1263
|
+
*/
|
|
1264
|
+
declare function compactConversationHistory(messages: readonly Message[], options: CompactionOptions): readonly Message[];
|
|
1265
|
+
/** Options for {@link sanitizeHistoryForNextTurn}; all fields optional. */
|
|
1266
|
+
interface HistorySanitizeOptions {
|
|
1267
|
+
/**
|
|
1268
|
+
* Messages — counted from the **end** of the array — whose `images` are
|
|
1269
|
+
* preserved. Default `1`: only the final message keeps its image payload,
|
|
1270
|
+
* which is the rolling one-image window long-running vision chats almost
|
|
1271
|
+
* always want (sanitize after appending the newest turn, and every prior
|
|
1272
|
+
* base64 payload is gone by the next request). `0` evicts images
|
|
1273
|
+
* everywhere; negative values clamp to `0`.
|
|
1274
|
+
*/
|
|
1275
|
+
readonly keepImagesOnLastMessages?: number | undefined;
|
|
1276
|
+
/**
|
|
1277
|
+
* Optional note appended to the `content` of each evicted message so the
|
|
1278
|
+
* model can still tell an image used to be there — e.g.
|
|
1279
|
+
* `"[image from an earlier turn removed to save context]"`. When omitted
|
|
1280
|
+
* (default) the `images` field is dropped and the text is untouched,
|
|
1281
|
+
* matching the wire behavior of never having sent the image at all.
|
|
1282
|
+
*/
|
|
1283
|
+
readonly imagePlaceholder?: string | undefined;
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Vision-history hygiene: returns a copy of `messages` with image payloads
|
|
1287
|
+
* evicted from every message outside the trailing keep-window, conversation
|
|
1288
|
+
* text fully preserved.
|
|
1289
|
+
*
|
|
1290
|
+
* Ollama's `/api/chat` is stateless — each request re-sends and re-bills the
|
|
1291
|
+
* whole history, base64 images included (each one costing real context
|
|
1292
|
+
* tokens via `IMAGE_TOKEN_ESTIMATE` in the pre-flight estimators). A
|
|
1293
|
+
* consumer-managed `messages` array therefore re-uploads every image from
|
|
1294
|
+
* every prior turn on every request, long after the model has already
|
|
1295
|
+
* answered the question that needed them. This helper is the explicit fix:
|
|
1296
|
+
*
|
|
1297
|
+
* ```ts
|
|
1298
|
+
* history.push({ role: 'user', content: 'What is in THIS photo?', images: [nextImage] });
|
|
1299
|
+
* await client.chat({ model, messages: sanitizeHistoryForNextTurn(history) });
|
|
1300
|
+
* ```
|
|
1301
|
+
*
|
|
1302
|
+
* Same philosophy as {@link compactConversationHistory}: caller-initiated,
|
|
1303
|
+
* never automatic. Two deliberate tradeoffs, both documented in ADR 0027:
|
|
1304
|
+
*
|
|
1305
|
+
* - **The model loses access to evicted images** — it keeps the
|
|
1306
|
+
* conversation text (and the optional `imagePlaceholder` note) but can
|
|
1307
|
+
* no longer "see" earlier pictures. That is the point: a bounded
|
|
1308
|
+
* payload in exchange for fading visual memory.
|
|
1309
|
+
* - **KV-prefix invalidation** — evicting rewrites the message at that
|
|
1310
|
+
* position, so the next turn's prompt prefix diverges and the cache
|
|
1311
|
+
* re-evaluates from that point. A hot cache-friendly session shouldn't
|
|
1312
|
+
* sanitize; a growing vision session should.
|
|
1313
|
+
*
|
|
1314
|
+
* Pure: the input array is never mutated, and messages that keep their
|
|
1315
|
+
* images are reused by reference (identity-stable for the untouched ones,
|
|
1316
|
+
* fresh copies only where eviction happened).
|
|
1317
|
+
*/
|
|
1318
|
+
declare function sanitizeHistoryForNextTurn(messages: readonly Message[], options?: HistorySanitizeOptions): readonly Message[];
|
|
1319
|
+
/** Options for {@link ConversationSession.compact}; all fields optional. */
|
|
1320
|
+
interface SessionCompactionOptions {
|
|
1321
|
+
/**
|
|
1322
|
+
* Token budget for the compacted history. Defaults to the session's own
|
|
1323
|
+
* window: `options.num_ctx` from the session config, or Ollama's
|
|
1324
|
+
* conservative 2048 fallback when unset — pair with
|
|
1325
|
+
* `client.models.getContextLength()` to program against the real window.
|
|
1326
|
+
*/
|
|
1327
|
+
readonly maxEstimatedTokens?: number | undefined;
|
|
1328
|
+
/** Reply reservation; defaults to ~10% of the (derived) budget. */
|
|
1329
|
+
readonly reserveForReply?: number | undefined;
|
|
1330
|
+
/** Trailing messages always kept (default `2`). See {@link CompactionOptions}. */
|
|
1331
|
+
readonly minTailMessages?: number | undefined;
|
|
1332
|
+
}
|
|
1333
|
+
/** What {@link ConversationSession.compact} did. */
|
|
1334
|
+
interface SessionCompactionResult {
|
|
1335
|
+
/** Number of messages dropped from the front of the tailable history. */
|
|
1336
|
+
readonly droppedMessages: number;
|
|
1337
|
+
/** Estimated tokens of the whole history before compaction. */
|
|
1338
|
+
readonly estimatedTokensBefore: number;
|
|
1339
|
+
/** Estimated tokens of the retained history after compaction. */
|
|
1340
|
+
readonly estimatedTokensAfter: number;
|
|
1341
|
+
/** The budget that was applied (after the reply reservation). */
|
|
1342
|
+
readonly effectiveBudget: number;
|
|
1343
|
+
}
|
|
907
1344
|
/** Per-turn overrides — none of these touch the history prefix, so they are KV-safe. */
|
|
908
1345
|
interface ConversationSendOptions extends Pick<ChatRequestOptions, 'signal' | 'timeoutMs'> {
|
|
909
1346
|
readonly options?: ModelOptions | undefined;
|
|
@@ -973,6 +1410,23 @@ declare class ConversationSession {
|
|
|
973
1410
|
* its frozen messages has no effect on the session.
|
|
974
1411
|
*/
|
|
975
1412
|
getMessages(): readonly Message[];
|
|
1413
|
+
/**
|
|
1414
|
+
* Compacts the session's history in place: pinned system prompt plus the
|
|
1415
|
+
* most recent turns that fit the budget, oldest tailable turns dropped.
|
|
1416
|
+
*
|
|
1417
|
+
* This is the explicit escape hatch for sessions that outgrew their
|
|
1418
|
+
* window — `cacheStats.hitRate` collapsing toward zero while history grows
|
|
1419
|
+
* is the usual symptom, and the pre-flight warnings on `chat()` fire once
|
|
1420
|
+
* the prompt estimate crosses the threshold. After compaction the next
|
|
1421
|
+
* turn's prompt prefix differs from everything before it, so the KV cache
|
|
1422
|
+
* starts cold — visible as a one-turn `evaluatedTokens` spike in
|
|
1423
|
+
* `cacheStats`. Cumulative cache tallies are deliberately **not** reset:
|
|
1424
|
+
* they are observations, and the spike is part of the story.
|
|
1425
|
+
*
|
|
1426
|
+
* Returns the before/after estimates and the drop count. No-op (zero
|
|
1427
|
+
* drops, equal before/after estimates) when the history already fits.
|
|
1428
|
+
*/
|
|
1429
|
+
compact(options?: SessionCompactionOptions): SessionCompactionResult;
|
|
976
1430
|
/**
|
|
977
1431
|
* Clears the conversation back to its initial state (system prompt, zero
|
|
978
1432
|
* turns, zeroed cache statistics). The next turn starts with a cold cache
|
|
@@ -1558,6 +2012,16 @@ declare class OllamaClient {
|
|
|
1558
2012
|
* (streams, via `executeWithFailover`'s `holdUntil` release path).
|
|
1559
2013
|
*/
|
|
1560
2014
|
private readonly activeRequests;
|
|
2015
|
+
/**
|
|
2016
|
+
* Dynamic multi-host model-affinity routing, active only when
|
|
2017
|
+
* `config.endpointHealth.modelAffinity` is set — see
|
|
2018
|
+
* `src/providers/model-affinity-router.ts` and ADR 0028. `undefined` means
|
|
2019
|
+
* the request path skips reordering entirely (zero overhead, and no `/api/ps`
|
|
2020
|
+
* probes are ever issued).
|
|
2021
|
+
*/
|
|
2022
|
+
private readonly modelAffinity;
|
|
2023
|
+
/** Default timeout for one-off probe requests (`ping`, affinity `/api/ps` refreshes). */
|
|
2024
|
+
private static readonly PROBE_TIMEOUT_MS;
|
|
1561
2025
|
constructor(config?: OllamaClientConfig);
|
|
1562
2026
|
get modelsClient(): ModelsClient;
|
|
1563
2027
|
/**
|
|
@@ -1772,7 +2236,15 @@ declare class OllamaClient {
|
|
|
1772
2236
|
readonly createModel: (r: CreateRequestOptions) => Promise<ProgressResponse | OllamaStream<ProgressResponse, ProgressStreamResult>>;
|
|
1773
2237
|
readonly deleteModel: (req: DeleteRequestOptions) => Promise<StatusResponse>;
|
|
1774
2238
|
readonly copyModel: (req: CopyRequestOptions) => Promise<StatusResponse>;
|
|
1775
|
-
readonly ps: () => Promise<PsResponse>;
|
|
2239
|
+
readonly ps: (request?: RequestCancellationOptions) => Promise<PsResponse>;
|
|
2240
|
+
/**
|
|
2241
|
+
* Discovers the model's real context window — the allocated window of the
|
|
2242
|
+
* running instance (`/api/ps`), the Modelfile `num_ctx` default, and the
|
|
2243
|
+
* native GGUF maximum (`/api/show` `model_info`), resolved by precedence.
|
|
2244
|
+
* Convenience alias for {@link ModelsClient.getContextLength} — see that
|
|
2245
|
+
* method for the full contract and the precedence order.
|
|
2246
|
+
*/
|
|
2247
|
+
readonly getContextLength: (request: ContextDiscoveryRequestOptions) => Promise<DiscoveredContextLength>;
|
|
1776
2248
|
readonly version: () => Promise<VersionResponse>;
|
|
1777
2249
|
readonly createBlob: (digest: string, data: BinaryBody) => Promise<void>;
|
|
1778
2250
|
readonly checkBlob: (digest: string) => Promise<boolean>;
|
|
@@ -1883,7 +2355,49 @@ declare class OllamaClient {
|
|
|
1883
2355
|
capabilities(model: string, signal?: AbortSignal): Promise<ModelCapabilities>;
|
|
1884
2356
|
runtimeMode(): RuntimeMode;
|
|
1885
2357
|
healthCheck(): Promise<EndpointHealthCheckResult[]>;
|
|
2358
|
+
/**
|
|
2359
|
+
* Ultra-lightweight liveness probe against the client's current best
|
|
2360
|
+
* endpoint: `HEAD /` — the root ping Ollama's documentation defines for
|
|
2361
|
+
* load-balancer health checks (HTTP 200; the daemon answers `GET /` with the
|
|
2362
|
+
* plain-text body "Ollama is running", which a HEAD request doesn't transfer).
|
|
2363
|
+
*
|
|
2364
|
+
* Deliberately a *single-endpoint, single-shot* probe — no failover to other
|
|
2365
|
+
* candidates, no retry — so the answer reflects one concrete host, not "some
|
|
2366
|
+
* endpoint eventually answered". To audit every configured endpoint, use
|
|
2367
|
+
* {@link healthCheck} (which probes all of them, and also reports the server
|
|
2368
|
+
* version at the cost of the heavier `GET /api/version` round trip).
|
|
2369
|
+
*
|
|
2370
|
+
* Resolves — never throws — with `{ healthy: false, error }` for connection
|
|
2371
|
+
* failures and timeouts; only caller-initiated cancellation (`signal`/
|
|
2372
|
+
* `destroy()`) rejects, mirroring how any other aborted request behaves.
|
|
2373
|
+
*/
|
|
2374
|
+
ping(options?: RequestCancellationOptions): Promise<PingResult>;
|
|
2375
|
+
/**
|
|
2376
|
+
* Affinity-cache snapshots for every configured endpoint — which models each
|
|
2377
|
+
* host held in VRAM at the last successful `/api/ps` probe, when that was, and
|
|
2378
|
+
* whether it's still fresh. Empty when `endpointHealth.modelAffinity` isn't
|
|
2379
|
+
* configured (no probes are ever issued, so there is nothing to report).
|
|
2380
|
+
*/
|
|
2381
|
+
modelAffinityStatus(): readonly ModelAffinitySnapshot[];
|
|
2382
|
+
/**
|
|
2383
|
+
* Explicitly refreshes the model-affinity cache for every configured endpoint
|
|
2384
|
+
* (deduped with any in-flight background refresh). No-op — resolves
|
|
2385
|
+
* immediately — when `endpointHealth.modelAffinity` isn't configured. Use it
|
|
2386
|
+
* to warm the cache at startup so the very first request already routes by
|
|
2387
|
+
* residency instead of waiting for the self-warming first-round refresh.
|
|
2388
|
+
*/
|
|
2389
|
+
warmModelAffinity(): Promise<void>;
|
|
1886
2390
|
endpointStatus(): EndpointHealth[];
|
|
2391
|
+
/**
|
|
2392
|
+
* Fetches one endpoint's `GET /api/ps` running-model list for the affinity
|
|
2393
|
+
* router. Bypasses `executeWithFailover` deliberately: probes must not
|
|
2394
|
+
* reenter the routing machinery they inform, must not touch the registry's
|
|
2395
|
+
* circuit-breaker/failure bookkeeping (a dead host's probe failing must not
|
|
2396
|
+
* cool it down harder than its real traffic already does), and must not fail
|
|
2397
|
+
* over to a different host (the answer is per-host by definition). Failures
|
|
2398
|
+
* propagate to the router, which records a short backoff and retries later.
|
|
2399
|
+
*/
|
|
2400
|
+
private fetchEndpointRunningModels;
|
|
1887
2401
|
/**
|
|
1888
2402
|
* Immediately aborts every in-flight request and active stream managed by
|
|
1889
2403
|
* this client — the clean teardown path for short-lived processes, CLI
|
|
@@ -2607,6 +3121,22 @@ interface AgentConfig {
|
|
|
2607
3121
|
readonly maxIterations?: number | undefined;
|
|
2608
3122
|
/** Maximum total tool calls allowed during one agent run. */
|
|
2609
3123
|
readonly maxToolCalls?: number | undefined;
|
|
3124
|
+
/**
|
|
3125
|
+
* Cycle detection: maximum executions of one *identical* tool call — same
|
|
3126
|
+
* tool name and same arguments — during a single run. When the model would
|
|
3127
|
+
* exceed this budget (the classic stuck-loop signature: re-emitting the
|
|
3128
|
+
* same call without reacting to its results), the run fails fast with
|
|
3129
|
+
* {@link OllamaAgentToolLoopError} instead of burning the remaining
|
|
3130
|
+
* iterations on the same wasted call.
|
|
3131
|
+
*
|
|
3132
|
+
* Off by default (`undefined`), matching `maxToolCalls`: an explicit,
|
|
3133
|
+
* caller-owned guardrail. Counting is per canonical signature, so
|
|
3134
|
+
* argument key order never splits one repeated call into several
|
|
3135
|
+
* "distinct" ones. Every call handed to the registry counts — failed,
|
|
3136
|
+
* unregistered, and timed-out executions included, since re-calling a
|
|
3137
|
+
* failing tool with unchanged arguments is exactly the loop this catches.
|
|
3138
|
+
*/
|
|
3139
|
+
readonly maxRepeatedToolCalls?: number | undefined;
|
|
2610
3140
|
readonly hooks?: AgentHooks | undefined;
|
|
2611
3141
|
/** Validate tool support from /api/show before starting a tool-enabled run. Default: true. */
|
|
2612
3142
|
readonly validateToolCapability?: boolean | undefined;
|
|
@@ -2642,6 +3172,18 @@ interface AgentChatClient {
|
|
|
2642
3172
|
readonly message: Message;
|
|
2643
3173
|
}>;
|
|
2644
3174
|
}
|
|
3175
|
+
/**
|
|
3176
|
+
* Canonical signature of a tool call for cycle detection: `name(args)` with
|
|
3177
|
+
* recursively key-sorted arguments, so the same call re-emitted by a model
|
|
3178
|
+
* in a different argument key order collapses to one signature instead of
|
|
3179
|
+
* counting as two "distinct" calls.
|
|
3180
|
+
*
|
|
3181
|
+
* ```ts
|
|
3182
|
+
* canonicalToolCallSignature({ function: { name: 'search', arguments: { q: 'x' } } })
|
|
3183
|
+
* // 'search({"q":"x"})'
|
|
3184
|
+
* ```
|
|
3185
|
+
*/
|
|
3186
|
+
declare function canonicalToolCallSignature(toolCall: ToolCall): string;
|
|
2645
3187
|
/**
|
|
2646
3188
|
* Runs a multi-turn `chat` + tool-execution loop until the model responds without
|
|
2647
3189
|
* requesting further tool calls, or `maxIterations` is exceeded. Tool calls within a
|
|
@@ -2658,6 +3200,7 @@ declare class Agent {
|
|
|
2658
3200
|
private readonly tools?;
|
|
2659
3201
|
private readonly maxIterations;
|
|
2660
3202
|
private readonly maxToolCalls?;
|
|
3203
|
+
private readonly maxRepeatedToolCalls?;
|
|
2661
3204
|
private readonly hooks?;
|
|
2662
3205
|
private readonly validateToolCapability;
|
|
2663
3206
|
private readonly toolContextSize;
|
|
@@ -2720,6 +3263,93 @@ declare const ATTR_OLLAMA_AGENT_MAX_ITERATIONS = "ollama.agent.max_iterations";
|
|
|
2720
3263
|
declare const ATTR_OLLAMA_AGENT_ITERATION = "ollama.agent.iteration";
|
|
2721
3264
|
declare const GEN_AI_SYSTEM_OLLAMA = "ollama";
|
|
2722
3265
|
|
|
3266
|
+
/**
|
|
3267
|
+
* Standardized telemetry normalizer — raw nanosecond counters to derived metrics.
|
|
3268
|
+
*
|
|
3269
|
+
* Ollama reports every duration as an **integer in nanoseconds** on its generation
|
|
3270
|
+
* responses (`total_duration`, `load_duration`, `prompt_eval_duration`,
|
|
3271
|
+
* `eval_duration` — see the official "Usage" documentation), plus token counters
|
|
3272
|
+
* (`prompt_eval_count`, `prompt_eval_cached_count`, `eval_count`). Consumers that
|
|
3273
|
+
* want milliseconds, tokens/second, or a cache-hit ratio otherwise each reimplement
|
|
3274
|
+
* the same division-and-rounding math — this module is that math, once, with the
|
|
3275
|
+
* formulas the official docs spell out:
|
|
3276
|
+
*
|
|
3277
|
+
* - `tokensPerSecond` = `eval_count / (eval_duration / 1e9)` — generation throughput.
|
|
3278
|
+
* - `promptTokensPerSecond` = `prompt_eval_count / (prompt_eval_duration / 1e9)` —
|
|
3279
|
+
* prompt ingestion (pre-fill) throughput.
|
|
3280
|
+
* - `cacheHitRatio` = `prompt_eval_cached_count / (cached + evaluated)` — see the
|
|
3281
|
+
* note on {@link FormattedTelemetry.cacheHitRatio} for why the denominator is the
|
|
3282
|
+
* *sum*, not `prompt_eval_count` alone.
|
|
3283
|
+
*
|
|
3284
|
+
* Pure and dependency-free: {@link formatTelemetry} never fetches, never throws, and
|
|
3285
|
+
* treats every missing counter as `0` — partial responses (stream final events,
|
|
3286
|
+
* older servers without `prompt_eval_cached_count`) format cleanly instead of
|
|
3287
|
+
* producing `NaN`/`Infinity`.
|
|
3288
|
+
*
|
|
3289
|
+
* The input is structural: any response object carrying these optional fields —
|
|
3290
|
+
* `GenerateResponse`, `ChatResponse`, the final `GenerateStreamEvent`,
|
|
3291
|
+
* `EmbedResponse` — can be passed directly, no picking/plucking required.
|
|
3292
|
+
*/
|
|
3293
|
+
/**
|
|
3294
|
+
* The raw nanosecond/token counters Ollama attaches to generation responses. Every
|
|
3295
|
+
* field is optional because servers report a subset: streaming final events may omit
|
|
3296
|
+
* load counters, older builds predate `prompt_eval_cached_count`, and embeddings
|
|
3297
|
+
* carry no `eval_count`. Accepts full response objects structurally.
|
|
3298
|
+
*/
|
|
3299
|
+
interface RawOllamaMetrics {
|
|
3300
|
+
/** Total end-to-end request latency, nanoseconds. */
|
|
3301
|
+
readonly total_duration?: number | undefined;
|
|
3302
|
+
/** Model cold-load and weight-transfer time into VRAM, nanoseconds. */
|
|
3303
|
+
readonly load_duration?: number | undefined;
|
|
3304
|
+
/** Prompt tokens freshly evaluated this request (not served from the KV cache). */
|
|
3305
|
+
readonly prompt_eval_count?: number | undefined;
|
|
3306
|
+
/** Prompt tokens served from the KV prompt cache (prefix reuse). */
|
|
3307
|
+
readonly prompt_eval_cached_count?: number | undefined;
|
|
3308
|
+
/** Prompt ingestion / pre-fill processing time, nanoseconds. */
|
|
3309
|
+
readonly prompt_eval_duration?: number | undefined;
|
|
3310
|
+
/** Tokens generated (the response proper). */
|
|
3311
|
+
readonly eval_count?: number | undefined;
|
|
3312
|
+
/** Token generation time, nanoseconds. */
|
|
3313
|
+
readonly eval_duration?: number | undefined;
|
|
3314
|
+
}
|
|
3315
|
+
/** The normalized, human-scale view of one response's {@link RawOllamaMetrics}. */
|
|
3316
|
+
interface FormattedTelemetry {
|
|
3317
|
+
/** `total_duration` in milliseconds, 2 decimals. */
|
|
3318
|
+
readonly totalLatencyMs: number;
|
|
3319
|
+
/** `load_duration` in milliseconds, 2 decimals — 0 when the model was already resident. */
|
|
3320
|
+
readonly modelLoadMs: number;
|
|
3321
|
+
/** `prompt_eval_duration` in milliseconds, 2 decimals. */
|
|
3322
|
+
readonly promptEvalMs: number;
|
|
3323
|
+
/** `eval_duration` in milliseconds, 2 decimals. */
|
|
3324
|
+
readonly generationMs: number;
|
|
3325
|
+
/** `eval_count / eval_duration` in tokens/second, 1 decimal — 0 when either is absent. */
|
|
3326
|
+
readonly tokensPerSecond: number;
|
|
3327
|
+
/** `prompt_eval_count / prompt_eval_duration` in tokens/second, 1 decimal. */
|
|
3328
|
+
readonly promptTokensPerSecond: number;
|
|
3329
|
+
/**
|
|
3330
|
+
* Share of prompt tokens served from the KV cache:
|
|
3331
|
+
* `cached / (cached + evaluated)`, 3 decimals.
|
|
3332
|
+
*
|
|
3333
|
+
* The denominator is the **sum**, not `prompt_eval_count` alone, because Ollama
|
|
3334
|
+
* reports `prompt_eval_count: 0` on a *full* cache hit — the same house semantics
|
|
3335
|
+
* as `ConversationSession`'s `cacheStats.hitRate` (see `src/conversation.ts`). A
|
|
3336
|
+
* `cached / prompt_eval_count` formula would report a perfect cache as `0`.
|
|
3337
|
+
*/
|
|
3338
|
+
readonly cacheHitRatio: number;
|
|
3339
|
+
}
|
|
3340
|
+
/**
|
|
3341
|
+
* Derives the standardized metrics summary from one response's raw nanosecond
|
|
3342
|
+
* counters. Pure — never throws, never fetches; every missing counter reads as `0`.
|
|
3343
|
+
*
|
|
3344
|
+
* ```ts
|
|
3345
|
+
* const res = await client.chat({ model: 'llama3.2', messages });
|
|
3346
|
+
* const t = formatTelemetry(res);
|
|
3347
|
+
* console.log(t.tokensPerSecond, 'tok/s |', t.totalLatencyMs, 'ms |',
|
|
3348
|
+
* `${Math.round(t.cacheHitRatio * 100)}% prompt cache hit`);
|
|
3349
|
+
* ```
|
|
3350
|
+
*/
|
|
3351
|
+
declare function formatTelemetry(raw: RawOllamaMetrics): FormattedTelemetry;
|
|
3352
|
+
|
|
2723
3353
|
/**
|
|
2724
3354
|
* Cross-runtime helpers with no Node.js API dependency, so they stay safe to import from
|
|
2725
3355
|
* the core client bundle (see ADR 0006 — Edge Runtime CI).
|
|
@@ -2796,6 +3426,11 @@ declare const IMAGE_TOKEN_ESTIMATE = 300;
|
|
|
2796
3426
|
* model-specific tokenizer.
|
|
2797
3427
|
*/
|
|
2798
3428
|
declare function estimateTokens(text: string): number;
|
|
3429
|
+
/**
|
|
3430
|
+
* Rough per-message framing overhead: role tags, chat-template delimiters.
|
|
3431
|
+
*/
|
|
3432
|
+
declare const MESSAGE_OVERHEAD_TOKENS = 4;
|
|
3433
|
+
declare function estimateMessageTokens(message: Message): number;
|
|
2799
3434
|
/**
|
|
2800
3435
|
* Estimated prompt tokens for a `/api/chat` request: every message plus
|
|
2801
3436
|
* tool-schema overhead (each tool definition's JSON schema serializes into
|
|
@@ -2851,4 +3486,142 @@ declare const OLLAMA_FALLBACK_CONTEXT_LENGTH = 2048;
|
|
|
2851
3486
|
*/
|
|
2852
3487
|
declare function contextWarningMessage(check: ContextCheck, kind: 'chat' | 'generate'): string;
|
|
2853
3488
|
|
|
2854
|
-
|
|
3489
|
+
/**
|
|
3490
|
+
* Model-affinity scheduling: keep the daemon's working set small.
|
|
3491
|
+
*
|
|
3492
|
+
* Ollama's concurrency model (per the official FAQ):
|
|
3493
|
+
*
|
|
3494
|
+
* - A model's KV cache scales by `OLLAMA_NUM_PARALLEL × context_length` —
|
|
3495
|
+
* parallel requests to the *same* loaded model are cheap (each gets its
|
|
3496
|
+
* own slot of the already-allocated cache).
|
|
3497
|
+
* - Requests for a *different* model queue until the first goes idle or is
|
|
3498
|
+
* evicted (`OLLAMA_MAX_LOADED_MODELS`, default 3× GPU count) — a swap is
|
|
3499
|
+
* an expensive unload/cold-load cycle: seconds of VRAM churn that a
|
|
3500
|
+
* concurrent multi-model workload pays again and again when it
|
|
3501
|
+
* interleaves models arbitrarily.
|
|
3502
|
+
* - Once `OLLAMA_MAX_QUEUE` (default 512) requests are waiting, new ones
|
|
3503
|
+
* are rejected outright with 503s.
|
|
3504
|
+
*
|
|
3505
|
+
* `ModelAffinityScheduler` is the client-side counterpart for workloads that
|
|
3506
|
+
* juggle several models — extraction on a coder model, reasoning on a
|
|
3507
|
+
* thinking model, embeddings for retrieval. It groups tasks into per-model
|
|
3508
|
+
* serial queues and caps how many *distinct* models have work in flight
|
|
3509
|
+
* (`concurrentModels`, default 1), preferring to deepen the currently-active
|
|
3510
|
+
* model over starting the next one — the anti-thrashing order. Candidate
|
|
3511
|
+
* lists let a task run on whichever of several interchangeable models is
|
|
3512
|
+
* already loaded (`GET /api/ps`, cached with a TTL).
|
|
3513
|
+
*
|
|
3514
|
+
* It is a user-space primitive, deliberately not wired into `OllamaClient`'s
|
|
3515
|
+
* request path: affinity decisions are workload policy, and the scheduler is
|
|
3516
|
+
* the foundation the multi-instance routing work builds on. See ADR 0026.
|
|
3517
|
+
*/
|
|
3518
|
+
|
|
3519
|
+
/**
|
|
3520
|
+
* The minimal client surface the scheduler needs. `OllamaClient` satisfies it
|
|
3521
|
+
* structurally; tests and custom setups can pass any compatible object.
|
|
3522
|
+
*/
|
|
3523
|
+
interface ModelAffinityClient {
|
|
3524
|
+
readonly models: {
|
|
3525
|
+
ps(): Promise<{
|
|
3526
|
+
readonly models: ReadonlyArray<{
|
|
3527
|
+
readonly name: string;
|
|
3528
|
+
}>;
|
|
3529
|
+
}>;
|
|
3530
|
+
};
|
|
3531
|
+
}
|
|
3532
|
+
/** Options for {@link ModelAffinityScheduler}. */
|
|
3533
|
+
interface ModelAffinitySchedulerOptions {
|
|
3534
|
+
/**
|
|
3535
|
+
* Maximum number of *distinct* models with work in flight at once
|
|
3536
|
+
* (default `1`). `1` is the anti-thrashing setting: one model stays hot
|
|
3537
|
+
* until its queue drains, then the next loads. Raise it only when the
|
|
3538
|
+
* host has VRAM for several concurrent models
|
|
3539
|
+
* (`OLLAMA_MAX_LOADED_MODELS`).
|
|
3540
|
+
*/
|
|
3541
|
+
readonly concurrentModels?: number | undefined;
|
|
3542
|
+
/**
|
|
3543
|
+
* Parallel tasks allowed per active model (default `1`). Raising this
|
|
3544
|
+
* mirrors the server's own `OLLAMA_NUM_PARALLEL` — same-model parallelism
|
|
3545
|
+
* reuses the loaded weights without swap cost.
|
|
3546
|
+
*/
|
|
3547
|
+
readonly perModelConcurrency?: number | undefined;
|
|
3548
|
+
/**
|
|
3549
|
+
* How long a `GET /api/ps` result is reused when choosing among candidate
|
|
3550
|
+
* models (default `30_000` ms). Only multi-candidate `run()` calls and
|
|
3551
|
+
* `loadedModels()` consult the server; single-model tasks never do.
|
|
3552
|
+
*/
|
|
3553
|
+
readonly psCacheTtlMs?: number | undefined;
|
|
3554
|
+
}
|
|
3555
|
+
/** Live scheduling state, from {@link ModelAffinityScheduler.stats}. */
|
|
3556
|
+
interface ModelAffinityStats {
|
|
3557
|
+
/** Models with at least one task currently executing. */
|
|
3558
|
+
readonly activeModels: readonly string[];
|
|
3559
|
+
/** Tasks waiting in queues (not yet started). */
|
|
3560
|
+
readonly queuedTasks: number;
|
|
3561
|
+
}
|
|
3562
|
+
/**
|
|
3563
|
+
* Groups async work by model with load-aware dispatch.
|
|
3564
|
+
*
|
|
3565
|
+
* ```ts
|
|
3566
|
+
* const scheduler = new ModelAffinityScheduler(client);
|
|
3567
|
+
*
|
|
3568
|
+
* // Serial queue per model; one model hot at a time (default):
|
|
3569
|
+
* await scheduler.run('deepseek-r1', () => reason(client));
|
|
3570
|
+
* await scheduler.run('qwen2.5:coder', () => extract(client));
|
|
3571
|
+
*
|
|
3572
|
+
* // Either-or: picks whichever candidate is already loaded (/api/ps):
|
|
3573
|
+
* const summary = await scheduler.run(
|
|
3574
|
+
* ['qwen2.5:coder', 'qwen2.5:14b'],
|
|
3575
|
+
* (model) => extractWith(client, model),
|
|
3576
|
+
* );
|
|
3577
|
+
* ```
|
|
3578
|
+
*
|
|
3579
|
+
* Dispatch order is **affinity-sticky, not round-robin**: when a queued
|
|
3580
|
+
* model is already active, its tasks start before a different model's (up to
|
|
3581
|
+
* `perModelConcurrency`), because deepening the hot model avoids a swap.
|
|
3582
|
+
* Tasks run in FIFO order within each model's queue. Task functions are the
|
|
3583
|
+
* caller's own — the scheduler adds no retry, timeout, or failover, and a
|
|
3584
|
+
* rejected task simply rejects its `run()` promise while its siblings
|
|
3585
|
+
* proceed.
|
|
3586
|
+
*/
|
|
3587
|
+
declare class ModelAffinityScheduler {
|
|
3588
|
+
private readonly client;
|
|
3589
|
+
private readonly queues;
|
|
3590
|
+
private readonly concurrentModels;
|
|
3591
|
+
private readonly perModelConcurrency;
|
|
3592
|
+
private readonly psCacheTtlMs;
|
|
3593
|
+
private psCache;
|
|
3594
|
+
private readonly drainWaiters;
|
|
3595
|
+
constructor(client: ModelAffinityClient, options?: ModelAffinitySchedulerOptions);
|
|
3596
|
+
/**
|
|
3597
|
+
* Runs `task` on the scheduler, serialized per model. When `model` is a
|
|
3598
|
+
* list of candidates, the already-loaded one is preferred (fresh
|
|
3599
|
+
* `/api/ps` data subject to the TTL cache); with none loaded — or when the
|
|
3600
|
+
* lookup fails — the first candidate runs. The chosen model is handed to
|
|
3601
|
+
* the task.
|
|
3602
|
+
*/
|
|
3603
|
+
run<T>(model: string | readonly string[], task: (model: string) => Promise<T>): Promise<T>;
|
|
3604
|
+
/**
|
|
3605
|
+
* Names of the models currently loaded, per `GET /api/ps`, cached for
|
|
3606
|
+
* `psCacheTtlMs`. Degrades to an empty list when the server can't answer
|
|
3607
|
+
* (never throws; candidate selection treats it as "nothing loaded").
|
|
3608
|
+
*/
|
|
3609
|
+
loadedModels(): Promise<readonly string[]>;
|
|
3610
|
+
/** Current scheduling state — active models and queued task count. */
|
|
3611
|
+
get stats(): ModelAffinityStats;
|
|
3612
|
+
/**
|
|
3613
|
+
* Resolves once every queue is empty and no task is running. Does not
|
|
3614
|
+
* abort anything — tasks are caller-owned; abort them via their own
|
|
3615
|
+
* signals before disposing if needed.
|
|
3616
|
+
*/
|
|
3617
|
+
dispose(): Promise<void>;
|
|
3618
|
+
private chooseCandidate;
|
|
3619
|
+
private refreshPsNames;
|
|
3620
|
+
private pump;
|
|
3621
|
+
private activeModelCount;
|
|
3622
|
+
private execute;
|
|
3623
|
+
}
|
|
3624
|
+
/** Convenience factory — `createModelAffinityScheduler(client, opts)` reads better in setups. */
|
|
3625
|
+
declare function createModelAffinityScheduler(client: ModelAffinityClient | OllamaClient, options?: ModelAffinitySchedulerOptions): ModelAffinityScheduler;
|
|
3626
|
+
|
|
3627
|
+
export { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_REQUEST_MODEL, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_USAGE_INPUT_TOKENS, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_OLLAMA_AGENT_ITERATION, ATTR_OLLAMA_AGENT_MAX_ITERATIONS, ATTR_OLLAMA_ENDPOINT_ATTEMPT, ATTR_OLLAMA_ENDPOINT_NAME, ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT, ATTR_URL_FULL, AbortableAsyncIterable, type AffinityRunningModel, Agent, type AgentChatClient, type AgentConfig, type AgentHooks, type AgentResult, type AgentRunInput, type AgentTurn, type AnswerFor, AnthropicCompatClient, AnyTool, type BackoffOptions, BalanceRequestOptions, type BalanceResponse, type BlobUploadResult, ChatRequestOptions, ChatResponse, ChatStreamResult, type ChoiceDecision, type CompactionOptions, type ContextCheck, type ContextCheckOptions, type ContextDiscoveryRequestOptions, type ContextLengthSignals, type ContextLengthSource, type ContextWindowSource, type ConversationSendOptions, ConversationSession, type ConversationSessionOptions, CopyRequestOptions, CreateRequestOptions, type CumulativeCacheStats, DEFAULT_BACKOFF, DEFAULT_BASE_URL, DEFAULT_CONTEXT_WARNING_THRESHOLD, DEFAULT_EMBED_BATCH_SIZE, DEFAULT_EMBED_CONCURRENCY, DEFAULT_FAILOVER_CODES, DEFAULT_FETCH_BACKOFF_CONFIG, DEFAULT_RETRY_CONFIG, DEFAULT_TIMEOUT_MS, type Decision, type DefineToolOptions, DeleteRequestOptions, type DiscoveredContextLength, type EmbedBatchOptions, type EmbedBatchResult, EmbedRequestOptions, EmbedResponse, EmbeddingsRequestOptions, EmbeddingsResponse, type EndpointHealth, type EndpointHealthCheckResult, EndpointRegistry, type EndpointRegistryOptions, FetchLike, type FetchWithBackoffConfig, FormatOption, type FormattedTelemetry, GEN_AI_SYSTEM_OLLAMA, GenerateRequestOptions, GenerateResponse, GenerateStreamResult, type HistorySanitizeOptions, HttpClient, IMAGE_TOKEN_ESTIMATE, type IncludedBalance, KEEP_ALIVE_INDEFINITE, KEEP_ALIVE_UNLOAD, KNOWN_DONE_REASONS, type KeepAlive, type KnownDoneReason, type LegacyBalanceLimit, type LegacyIncludedBalance, type LoadMcpToolsOptions, Logger, MAX_SYSTEM_ONE_IMAGES_BYTES, MAX_SYSTEM_ONE_REQUEST_BYTES, MESSAGE_OVERHEAD_TOKENS, McpBridge, type McpBridgeOptions, McpCallToolResult, McpClientLike, McpTask, McpToolDescriptor, Message, Middleware, type ModelAffinityClient, ModelAffinityRouter, type ModelAffinityRoutingOptions, ModelAffinityScheduler, type ModelAffinitySchedulerOptions, type ModelAffinitySnapshot, type ModelAffinityStats, type ModelCapabilities, ModelOptions, ModelResponse, ModelsClient, type NoulDecision, OLLAMA_CLOUD_BASE_URL, OLLAMA_FALLBACK_CONTEXT_LENGTH, OllamaClient, type OllamaClientConfig, type OllamaCloudFreeTierQuotaBudgets, type OllamaCredentialConfig, type OllamaEndpoint, OllamaStream, OllamaStreamEvent, OllamaStreamEventType, OpenAICompatClient, type OversizedEmbedInput, type ParallelToolCallBehavior, PingResult, ProgressResponse, ProgressStreamResult, PsResponse, PullRequestOptions, PushRequestOptions, QuotaManager, type QuotaManagerOptions, type QuotaWindowConfig, type QuotaWindowStatus, RETRYABLE_STATUS_CODES, type RankResult, type RawOllamaMetrics, RawUsageSource, RequestCancellationOptions, RequestLifecycleHook, RequestRunner, type ResponsesCreateRequest, type ResponsesCreateResponse, ResponsesModule, type ResponsesReasoningEffort, type ResponsesStreamEvent, type ResponsesToolDefinition, type ResponsesUsage, type RetryConfig, type RuntimeMode, type ScoreDecision, type SessionCompactionOptions, type SessionCompactionResult, type SessionTurn, ShowRequestOptions, ShowResponse, type SpanAttributeValue, type SpanAttributes, StatusResponse, type SupportedSchema, type SystemOneAnswer, type SystemOneAnswers, SystemOneChoiceAnswer, SystemOneChoiceQuestion, SystemOneContent, SystemOneNoulAnswer, SystemOneNoulQuestion, type SystemOneQuestion, type SystemOneQuestions, type SystemOneRequest, type SystemOneResponse, SystemOneScoreAnswer, SystemOneScoreQuestion, type SystemOneUsage, ThinkValue, ThinkingMetadata, type TimeoutSignal, TokenUsage, Tool, ToolCall, ToolCallAccumulator, ToolDefinition, ToolExecutionResult, ToolHandler, ToolParameters, ToolRegistry, type TurnCacheStats, type UsageBucket, type UsageMetrics, UsageRequestOptions, type UsageResponse, VersionResponse, VisionInput, WebFetchRequestOptions, WebFetchResponse, WebSearchRequestOptions, WebSearchResponse, addSpanEvent, batchEmbed, calculateBackoff, canonicalToolCallSignature, checkChatContext, checkEndpointHealth, checkGenerateContext, compactConversationHistory, contextWarningMessage, createDecision, createModelAffinityScheduler, createOllamaCloudFreeTierQuota, createTimeoutSignal, defineTool, detectModelCapabilities, embedBatchOverflowMessage, encodeImage, estimateChatRequestTokens, estimateGenerateRequestTokens, estimateMessageTokens, estimateSystemOneRequestBytes, estimateTokens, extractContextLength as extractNativeContextLength, extractParameterNumCtx, fetchWithBackoff, findOversizedEmbedInputs, findRunningModelContextLength, formatTelemetry, inferRuntimeMode, isKeepAliveSugar, isKnownDoneReason, isModelResident, isSameToolCall, listAllMcpTools, listAvailableModels, loadMcpTools, mergeToolCall, mergeToolCallArgumentsString, mergeToolCallArrays, normalizeChatStream, normalizeGenerateStream, normalizeKeepAlive, normalizeProgressStream, parseNdjsonStream, parseStructuredOutput, registerMcpTools, resolveContextLength, resolveCredentialEndpoints, sanitizeHistoryForNextTurn, setSpanError, toDataStream, toResponse, toTextStream, withRetry, withSpan, zodToJsonSchema };
|