@providerprotocol/ai 0.0.10 → 0.0.12

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.
Files changed (64) hide show
  1. package/dist/index.d.ts +7 -1
  2. package/dist/index.js +37 -9
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -10
  5. package/src/anthropic/index.ts +0 -3
  6. package/src/core/image.ts +0 -188
  7. package/src/core/llm.ts +0 -624
  8. package/src/core/provider.ts +0 -92
  9. package/src/google/index.ts +0 -3
  10. package/src/http/errors.ts +0 -112
  11. package/src/http/fetch.ts +0 -210
  12. package/src/http/index.ts +0 -31
  13. package/src/http/keys.ts +0 -136
  14. package/src/http/retry.ts +0 -205
  15. package/src/http/sse.ts +0 -136
  16. package/src/index.ts +0 -32
  17. package/src/ollama/index.ts +0 -3
  18. package/src/openai/index.ts +0 -39
  19. package/src/openrouter/index.ts +0 -11
  20. package/src/providers/anthropic/index.ts +0 -17
  21. package/src/providers/anthropic/llm.ts +0 -196
  22. package/src/providers/anthropic/transform.ts +0 -434
  23. package/src/providers/anthropic/types.ts +0 -213
  24. package/src/providers/google/index.ts +0 -17
  25. package/src/providers/google/llm.ts +0 -203
  26. package/src/providers/google/transform.ts +0 -447
  27. package/src/providers/google/types.ts +0 -214
  28. package/src/providers/ollama/index.ts +0 -43
  29. package/src/providers/ollama/llm.ts +0 -272
  30. package/src/providers/ollama/transform.ts +0 -434
  31. package/src/providers/ollama/types.ts +0 -260
  32. package/src/providers/openai/index.ts +0 -186
  33. package/src/providers/openai/llm.completions.ts +0 -201
  34. package/src/providers/openai/llm.responses.ts +0 -211
  35. package/src/providers/openai/transform.completions.ts +0 -561
  36. package/src/providers/openai/transform.responses.ts +0 -708
  37. package/src/providers/openai/types.ts +0 -1249
  38. package/src/providers/openrouter/index.ts +0 -177
  39. package/src/providers/openrouter/llm.completions.ts +0 -201
  40. package/src/providers/openrouter/llm.responses.ts +0 -211
  41. package/src/providers/openrouter/transform.completions.ts +0 -538
  42. package/src/providers/openrouter/transform.responses.ts +0 -742
  43. package/src/providers/openrouter/types.ts +0 -717
  44. package/src/providers/xai/index.ts +0 -223
  45. package/src/providers/xai/llm.completions.ts +0 -201
  46. package/src/providers/xai/llm.messages.ts +0 -195
  47. package/src/providers/xai/llm.responses.ts +0 -211
  48. package/src/providers/xai/transform.completions.ts +0 -565
  49. package/src/providers/xai/transform.messages.ts +0 -448
  50. package/src/providers/xai/transform.responses.ts +0 -678
  51. package/src/providers/xai/types.ts +0 -938
  52. package/src/types/content.ts +0 -133
  53. package/src/types/errors.ts +0 -85
  54. package/src/types/index.ts +0 -105
  55. package/src/types/llm.ts +0 -211
  56. package/src/types/messages.ts +0 -205
  57. package/src/types/provider.ts +0 -195
  58. package/src/types/schema.ts +0 -58
  59. package/src/types/stream.ts +0 -146
  60. package/src/types/thread.ts +0 -226
  61. package/src/types/tool.ts +0 -88
  62. package/src/types/turn.ts +0 -118
  63. package/src/utils/id.ts +0 -28
  64. package/src/xai/index.ts +0 -41
@@ -1,434 +0,0 @@
1
- import type { LLMRequest, LLMResponse } from '../../types/llm.ts';
2
- import type { Message } from '../../types/messages.ts';
3
- import type { StreamEvent } from '../../types/stream.ts';
4
- import type { Tool, ToolCall } from '../../types/tool.ts';
5
- import type { TokenUsage } from '../../types/turn.ts';
6
- import type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';
7
- import {
8
- AssistantMessage,
9
- isUserMessage,
10
- isAssistantMessage,
11
- isToolResultMessage,
12
- } from '../../types/messages.ts';
13
- import type {
14
- OllamaLLMParams,
15
- OllamaRequest,
16
- OllamaMessage,
17
- OllamaTool,
18
- OllamaResponse,
19
- OllamaStreamChunk,
20
- OllamaToolCall,
21
- OllamaOptions,
22
- } from './types.ts';
23
-
24
- /**
25
- * Transform UPP request to Ollama format
26
- *
27
- * Params are spread to allow pass-through of any Ollama API fields,
28
- * even those not explicitly defined in our type. This enables developers to
29
- * use new API features without waiting for library updates.
30
- *
31
- * Note: Ollama uses nested 'options' for model parameters. Params that belong
32
- * in options (like temperature, top_p, etc.) are spread into options, while
33
- * top-level params (like keep_alive, think) are spread at the request level.
34
- */
35
- export function transformRequest<TParams extends OllamaLLMParams>(
36
- request: LLMRequest<TParams>,
37
- modelId: string
38
- ): OllamaRequest {
39
- const params = (request.params ?? {}) as OllamaLLMParams;
40
-
41
- // Extract top-level params vs options params
42
- const {
43
- keep_alive,
44
- think,
45
- logprobs,
46
- top_logprobs,
47
- ...optionsParams
48
- } = params;
49
-
50
- // Spread params to pass through all fields, then set required fields
51
- const ollamaRequest: OllamaRequest = {
52
- model: modelId,
53
- messages: transformMessages(request.messages, request.system),
54
- };
55
-
56
- // Add top-level params if provided
57
- if (keep_alive !== undefined) ollamaRequest.keep_alive = keep_alive;
58
- if (think !== undefined) ollamaRequest.think = think;
59
- if (logprobs !== undefined) ollamaRequest.logprobs = logprobs;
60
- if (top_logprobs !== undefined) ollamaRequest.top_logprobs = top_logprobs;
61
-
62
- // Spread remaining params into options to pass through all model parameters
63
- if (Object.keys(optionsParams).length > 0) {
64
- ollamaRequest.options = optionsParams as OllamaOptions;
65
- }
66
-
67
- // Tools come from request, not params
68
- if (request.tools && request.tools.length > 0) {
69
- ollamaRequest.tools = request.tools.map(transformTool);
70
- }
71
-
72
- // Structured output via format field
73
- if (request.structure) {
74
- ollamaRequest.format = request.structure as unknown as Record<string, unknown>;
75
- }
76
-
77
- return ollamaRequest;
78
- }
79
-
80
- /**
81
- * Transform UPP Messages to Ollama messages
82
- */
83
- function transformMessages(messages: Message[], system?: string): OllamaMessage[] {
84
- const ollamaMessages: OllamaMessage[] = [];
85
-
86
- // System prompt as first message
87
- if (system) {
88
- ollamaMessages.push({
89
- role: 'system',
90
- content: system,
91
- });
92
- }
93
-
94
- for (const msg of messages) {
95
- if (isUserMessage(msg)) {
96
- const textContent: string[] = [];
97
- const images: string[] = [];
98
-
99
- for (const block of msg.content) {
100
- if (block.type === 'text') {
101
- textContent.push(block.text);
102
- } else if (block.type === 'image') {
103
- const imageBlock = block as ImageBlock;
104
- if (imageBlock.source.type === 'base64') {
105
- images.push(imageBlock.source.data);
106
- } else if (imageBlock.source.type === 'bytes') {
107
- // Convert bytes to base64
108
- const base64 = btoa(
109
- Array.from(imageBlock.source.data)
110
- .map((b) => String.fromCharCode(b))
111
- .join('')
112
- );
113
- images.push(base64);
114
- } else if (imageBlock.source.type === 'url') {
115
- // Ollama doesn't support URL images directly
116
- // Would need to fetch and convert, for now just add as text
117
- textContent.push(`[Image: ${imageBlock.source.url}]`);
118
- }
119
- }
120
- }
121
-
122
- const message: OllamaMessage = {
123
- role: 'user',
124
- content: textContent.join('\n'),
125
- };
126
-
127
- if (images.length > 0) {
128
- message.images = images;
129
- }
130
-
131
- ollamaMessages.push(message);
132
- } else if (isAssistantMessage(msg)) {
133
- const textContent = msg.content
134
- .filter((block): block is TextBlock => block.type === 'text')
135
- .map((block) => block.text)
136
- .join('\n');
137
-
138
- const message: OllamaMessage = {
139
- role: 'assistant',
140
- content: textContent,
141
- };
142
-
143
- // Add tool calls if present
144
- if (msg.toolCalls && msg.toolCalls.length > 0) {
145
- message.tool_calls = msg.toolCalls.map((call) => ({
146
- function: {
147
- name: call.toolName,
148
- arguments: call.arguments,
149
- },
150
- }));
151
- }
152
-
153
- ollamaMessages.push(message);
154
- } else if (isToolResultMessage(msg)) {
155
- // Tool results are sent as 'tool' role messages
156
- for (const result of msg.results) {
157
- ollamaMessages.push({
158
- role: 'tool',
159
- tool_name: result.toolCallId, // In our UPP, toolCallId maps to tool name for Ollama
160
- content:
161
- typeof result.result === 'string'
162
- ? result.result
163
- : JSON.stringify(result.result),
164
- });
165
- }
166
- }
167
- }
168
-
169
- return ollamaMessages;
170
- }
171
-
172
- /**
173
- * Transform a UPP Tool to Ollama format
174
- */
175
- function transformTool(tool: Tool): OllamaTool {
176
- return {
177
- type: 'function',
178
- function: {
179
- name: tool.name,
180
- description: tool.description,
181
- parameters: {
182
- type: 'object',
183
- properties: tool.parameters.properties,
184
- required: tool.parameters.required,
185
- },
186
- },
187
- };
188
- }
189
-
190
- /**
191
- * Transform Ollama response to UPP LLMResponse
192
- */
193
- export function transformResponse(data: OllamaResponse): LLMResponse {
194
- const textContent: TextBlock[] = [];
195
- const toolCalls: ToolCall[] = [];
196
- let structuredData: unknown;
197
-
198
- // Add main content
199
- if (data.message.content) {
200
- textContent.push({ type: 'text', text: data.message.content });
201
-
202
- // Try to parse as JSON for structured output
203
- try {
204
- structuredData = JSON.parse(data.message.content);
205
- } catch {
206
- // Not valid JSON - that's fine, might not be structured output
207
- }
208
- }
209
-
210
- // Extract tool calls
211
- if (data.message.tool_calls) {
212
- for (const call of data.message.tool_calls) {
213
- toolCalls.push({
214
- toolCallId: call.function.name, // Ollama doesn't have separate IDs, use name
215
- toolName: call.function.name,
216
- arguments: call.function.arguments,
217
- });
218
- }
219
- }
220
-
221
- const message = new AssistantMessage(
222
- textContent,
223
- toolCalls.length > 0 ? toolCalls : undefined,
224
- {
225
- metadata: {
226
- ollama: {
227
- model: data.model,
228
- created_at: data.created_at,
229
- done_reason: data.done_reason,
230
- thinking: data.message.thinking,
231
- total_duration: data.total_duration,
232
- load_duration: data.load_duration,
233
- prompt_eval_duration: data.prompt_eval_duration,
234
- eval_duration: data.eval_duration,
235
- logprobs: data.logprobs,
236
- },
237
- },
238
- }
239
- );
240
-
241
- // Calculate token usage
242
- const usage: TokenUsage = {
243
- inputTokens: data.prompt_eval_count ?? 0,
244
- outputTokens: data.eval_count ?? 0,
245
- totalTokens: (data.prompt_eval_count ?? 0) + (data.eval_count ?? 0),
246
- };
247
-
248
- // Map done_reason to standard stop reason
249
- let stopReason = 'end_turn';
250
- if (data.done_reason === 'length') {
251
- stopReason = 'max_tokens';
252
- } else if (data.done_reason === 'stop') {
253
- stopReason = 'end_turn';
254
- } else if (toolCalls.length > 0) {
255
- stopReason = 'tool_use';
256
- }
257
-
258
- return {
259
- message,
260
- usage,
261
- stopReason,
262
- data: structuredData,
263
- };
264
- }
265
-
266
- /**
267
- * State for accumulating streaming response
268
- */
269
- export interface StreamState {
270
- model: string;
271
- content: string;
272
- thinking: string;
273
- toolCalls: Array<{ name: string; args: Record<string, unknown> }>;
274
- doneReason: string | null;
275
- promptEvalCount: number;
276
- evalCount: number;
277
- totalDuration: number;
278
- isFirstChunk: boolean;
279
- createdAt: string;
280
- }
281
-
282
- /**
283
- * Create initial stream state
284
- */
285
- export function createStreamState(): StreamState {
286
- return {
287
- model: '',
288
- content: '',
289
- thinking: '',
290
- toolCalls: [],
291
- doneReason: null,
292
- promptEvalCount: 0,
293
- evalCount: 0,
294
- totalDuration: 0,
295
- isFirstChunk: true,
296
- createdAt: '',
297
- };
298
- }
299
-
300
- /**
301
- * Transform Ollama stream chunk to UPP StreamEvents
302
- */
303
- export function transformStreamChunk(
304
- chunk: OllamaStreamChunk,
305
- state: StreamState
306
- ): StreamEvent[] {
307
- const events: StreamEvent[] = [];
308
-
309
- // First chunk - emit message start
310
- if (state.isFirstChunk) {
311
- state.model = chunk.model;
312
- state.createdAt = chunk.created_at;
313
- events.push({ type: 'message_start', index: 0, delta: {} });
314
- state.isFirstChunk = false;
315
- }
316
-
317
- // Process message content
318
- if (chunk.message) {
319
- // Text content delta
320
- if (chunk.message.content) {
321
- state.content += chunk.message.content;
322
- events.push({
323
- type: 'text_delta',
324
- index: 0,
325
- delta: { text: chunk.message.content },
326
- });
327
- }
328
-
329
- // Thinking content delta
330
- if (chunk.message.thinking) {
331
- state.thinking += chunk.message.thinking;
332
- events.push({
333
- type: 'reasoning_delta',
334
- index: 0,
335
- delta: { text: chunk.message.thinking },
336
- });
337
- }
338
-
339
- // Tool calls (typically come in final chunk)
340
- if (chunk.message.tool_calls) {
341
- for (const call of chunk.message.tool_calls) {
342
- state.toolCalls.push({
343
- name: call.function.name,
344
- args: call.function.arguments,
345
- });
346
- events.push({
347
- type: 'tool_call_delta',
348
- index: state.toolCalls.length - 1,
349
- delta: {
350
- toolCallId: call.function.name,
351
- toolName: call.function.name,
352
- argumentsJson: JSON.stringify(call.function.arguments),
353
- },
354
- });
355
- }
356
- }
357
- }
358
-
359
- // Final chunk with metrics
360
- if (chunk.done) {
361
- state.doneReason = chunk.done_reason ?? null;
362
- state.promptEvalCount = chunk.prompt_eval_count ?? 0;
363
- state.evalCount = chunk.eval_count ?? 0;
364
- state.totalDuration = chunk.total_duration ?? 0;
365
- events.push({ type: 'message_stop', index: 0, delta: {} });
366
- }
367
-
368
- return events;
369
- }
370
-
371
- /**
372
- * Build LLMResponse from accumulated stream state
373
- */
374
- export function buildResponseFromState(state: StreamState): LLMResponse {
375
- const textContent: TextBlock[] = [];
376
- const toolCalls: ToolCall[] = [];
377
- let structuredData: unknown;
378
-
379
- if (state.content) {
380
- textContent.push({ type: 'text', text: state.content });
381
-
382
- // Try to parse as JSON for structured output
383
- try {
384
- structuredData = JSON.parse(state.content);
385
- } catch {
386
- // Not valid JSON - that's fine
387
- }
388
- }
389
-
390
- for (const tc of state.toolCalls) {
391
- toolCalls.push({
392
- toolCallId: tc.name,
393
- toolName: tc.name,
394
- arguments: tc.args,
395
- });
396
- }
397
-
398
- const message = new AssistantMessage(
399
- textContent,
400
- toolCalls.length > 0 ? toolCalls : undefined,
401
- {
402
- metadata: {
403
- ollama: {
404
- model: state.model,
405
- created_at: state.createdAt,
406
- done_reason: state.doneReason,
407
- thinking: state.thinking || undefined,
408
- total_duration: state.totalDuration,
409
- },
410
- },
411
- }
412
- );
413
-
414
- const usage: TokenUsage = {
415
- inputTokens: state.promptEvalCount,
416
- outputTokens: state.evalCount,
417
- totalTokens: state.promptEvalCount + state.evalCount,
418
- };
419
-
420
- // Map done_reason to standard stop reason
421
- let stopReason = 'end_turn';
422
- if (state.doneReason === 'length') {
423
- stopReason = 'max_tokens';
424
- } else if (toolCalls.length > 0) {
425
- stopReason = 'tool_use';
426
- }
427
-
428
- return {
429
- message,
430
- usage,
431
- stopReason,
432
- data: structuredData,
433
- };
434
- }
@@ -1,260 +0,0 @@
1
- /**
2
- * Ollama-specific LLM parameters
3
- * These map to Ollama's runtime options
4
- */
5
- export interface OllamaLLMParams {
6
- /** Maximum number of tokens to predict (default: -1 = infinite) */
7
- num_predict?: number;
8
-
9
- /** Temperature for randomness (default: 0.8) */
10
- temperature?: number;
11
-
12
- /** Top-p (nucleus) sampling (default: 0.9) */
13
- top_p?: number;
14
-
15
- /** Top-k sampling (default: 40) */
16
- top_k?: number;
17
-
18
- /** Minimum probability for a token to be considered (default: 0.0) */
19
- min_p?: number;
20
-
21
- /** Typical p sampling (default: 1.0 = disabled) */
22
- typical_p?: number;
23
-
24
- /** Repeat penalty (default: 1.1) */
25
- repeat_penalty?: number;
26
-
27
- /** Number of tokens to look back for repeat penalty (default: 64) */
28
- repeat_last_n?: number;
29
-
30
- /** Presence penalty (default: 0.0) */
31
- presence_penalty?: number;
32
-
33
- /** Frequency penalty (default: 0.0) */
34
- frequency_penalty?: number;
35
-
36
- /** Mirostat sampling mode (0 = disabled, 1 = Mirostat, 2 = Mirostat 2.0) */
37
- mirostat?: 0 | 1 | 2;
38
-
39
- /** Mirostat learning rate (default: 0.1) */
40
- mirostat_eta?: number;
41
-
42
- /** Mirostat target entropy (default: 5.0) */
43
- mirostat_tau?: number;
44
-
45
- /** Penalize newlines (default: true) */
46
- penalize_newline?: boolean;
47
-
48
- /** Stop sequences */
49
- stop?: string[];
50
-
51
- /** Seed for deterministic sampling (default: random) */
52
- seed?: number;
53
-
54
- /** Number of tokens to keep from initial prompt (default: 4) */
55
- num_keep?: number;
56
-
57
- /** Context window size (default: model-dependent) */
58
- num_ctx?: number;
59
-
60
- /** Number of batches (default: 512) */
61
- num_batch?: number;
62
-
63
- /** Number of threads (default: auto) */
64
- num_thread?: number;
65
-
66
- /** Number of layers to offload to GPU (default: auto) */
67
- num_gpu?: number;
68
-
69
- /** Main GPU to use (default: 0) */
70
- main_gpu?: number;
71
-
72
- /** Enable low VRAM mode */
73
- low_vram?: boolean;
74
-
75
- /** Enable f16 KV cache */
76
- f16_kv?: boolean;
77
-
78
- /** Use mmap for model loading */
79
- use_mmap?: boolean;
80
-
81
- /** Use mlock for memory locking */
82
- use_mlock?: boolean;
83
-
84
- /** Vocabulary only mode */
85
- vocab_only?: boolean;
86
-
87
- /** NUMA support */
88
- numa?: boolean;
89
-
90
- /** TFS-Z sampling (default: 1.0 = disabled) */
91
- tfs_z?: number;
92
-
93
- /** Enable thinking mode (for models that support it) */
94
- think?: boolean | 'high' | 'medium' | 'low';
95
-
96
- /** Keep model loaded in memory (string duration like "5m" or number of seconds) */
97
- keep_alive?: string | number;
98
-
99
- /** Return log probabilities */
100
- logprobs?: boolean;
101
-
102
- /** Number of top log probabilities to return */
103
- top_logprobs?: number;
104
- }
105
-
106
- /**
107
- * Ollama chat message format
108
- */
109
- export interface OllamaMessage {
110
- role: 'system' | 'user' | 'assistant' | 'tool';
111
- content: string;
112
- /** Base64 encoded images for vision models */
113
- images?: string[];
114
- /** Tool calls made by the assistant */
115
- tool_calls?: OllamaToolCall[];
116
- /** Tool name when role is 'tool' */
117
- tool_name?: string;
118
- }
119
-
120
- /**
121
- * Ollama tool call format
122
- */
123
- export interface OllamaToolCall {
124
- function: {
125
- name: string;
126
- arguments: Record<string, unknown>;
127
- };
128
- }
129
-
130
- /**
131
- * Ollama tool definition format
132
- */
133
- export interface OllamaTool {
134
- type: 'function';
135
- function: {
136
- name: string;
137
- description: string;
138
- parameters: {
139
- type: 'object';
140
- properties: Record<string, unknown>;
141
- required?: string[];
142
- };
143
- };
144
- }
145
-
146
- /**
147
- * Ollama API request body for chat endpoint
148
- */
149
- export interface OllamaRequest {
150
- model: string;
151
- messages: OllamaMessage[];
152
- stream?: boolean;
153
- format?: 'json' | Record<string, unknown>;
154
- options?: OllamaOptions;
155
- tools?: OllamaTool[];
156
- keep_alive?: string | number;
157
- think?: boolean | 'high' | 'medium' | 'low';
158
- logprobs?: boolean;
159
- top_logprobs?: number;
160
- }
161
-
162
- /**
163
- * Ollama runtime options (passed in options field)
164
- */
165
- export interface OllamaOptions {
166
- num_predict?: number;
167
- temperature?: number;
168
- top_p?: number;
169
- top_k?: number;
170
- min_p?: number;
171
- typical_p?: number;
172
- repeat_penalty?: number;
173
- repeat_last_n?: number;
174
- presence_penalty?: number;
175
- frequency_penalty?: number;
176
- mirostat?: 0 | 1 | 2;
177
- mirostat_eta?: number;
178
- mirostat_tau?: number;
179
- penalize_newline?: boolean;
180
- stop?: string[];
181
- seed?: number;
182
- num_keep?: number;
183
- num_ctx?: number;
184
- num_batch?: number;
185
- num_thread?: number;
186
- num_gpu?: number;
187
- main_gpu?: number;
188
- low_vram?: boolean;
189
- f16_kv?: boolean;
190
- use_mmap?: boolean;
191
- use_mlock?: boolean;
192
- vocab_only?: boolean;
193
- numa?: boolean;
194
- tfs_z?: number;
195
- }
196
-
197
- /**
198
- * Ollama API response format
199
- */
200
- export interface OllamaResponse {
201
- model: string;
202
- created_at: string;
203
- message: OllamaResponseMessage;
204
- done: boolean;
205
- done_reason?: 'stop' | 'length' | 'load' | 'unload';
206
- total_duration?: number;
207
- load_duration?: number;
208
- prompt_eval_count?: number;
209
- prompt_eval_duration?: number;
210
- eval_count?: number;
211
- eval_duration?: number;
212
- logprobs?: OllamaLogprob[];
213
- }
214
-
215
- /**
216
- * Ollama response message format
217
- */
218
- export interface OllamaResponseMessage {
219
- role: 'assistant';
220
- content: string;
221
- /** Thinking content (if think mode enabled) */
222
- thinking?: string;
223
- /** Tool calls requested by the model */
224
- tool_calls?: OllamaToolCall[];
225
- /** Images (for multimodal responses) */
226
- images?: string[];
227
- }
228
-
229
- /**
230
- * Ollama log probability format
231
- */
232
- export interface OllamaLogprob {
233
- token: string;
234
- logprob: number;
235
- bytes?: number[];
236
- top_logprobs?: Array<{
237
- token: string;
238
- logprob: number;
239
- bytes?: number[];
240
- }>;
241
- }
242
-
243
- /**
244
- * Ollama streaming response chunk
245
- * Same structure as regular response but partial
246
- */
247
- export interface OllamaStreamChunk {
248
- model: string;
249
- created_at: string;
250
- message: OllamaResponseMessage;
251
- done: boolean;
252
- done_reason?: 'stop' | 'length' | 'load' | 'unload';
253
- total_duration?: number;
254
- load_duration?: number;
255
- prompt_eval_count?: number;
256
- prompt_eval_duration?: number;
257
- eval_count?: number;
258
- eval_duration?: number;
259
- logprobs?: OllamaLogprob[];
260
- }