@stacksjs/ai 0.70.55 → 0.70.56

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 (46) hide show
  1. package/package.json +10 -7
  2. package/src/agents/claude/index.ts +0 -310
  3. package/src/agents/index.ts +0 -7
  4. package/src/buddy.ts +0 -619
  5. package/src/drivers/anthropic/index.ts +0 -430
  6. package/src/drivers/claude-agent-sdk/index.ts +0 -370
  7. package/src/drivers/index.ts +0 -14
  8. package/src/drivers/ollama/index.ts +0 -514
  9. package/src/drivers/openai/index.ts +0 -529
  10. package/src/image.ts +0 -607
  11. package/src/index.ts +0 -53
  12. package/src/mcp.ts +0 -658
  13. package/src/personalization.ts +0 -490
  14. package/src/search.ts +0 -555
  15. package/src/text.ts +0 -79
  16. package/src/types.ts +0 -229
  17. package/src/utils/client-bedrock-runtime.ts +0 -51
  18. package/src/utils/client-bedrock.ts +0 -75
  19. package/src/utils/model-access.ts +0 -32
  20. package/src/utils/retry.ts +0 -124
  21. package/src/utils/tokens.ts +0 -159
  22. package/src/utils/usage.ts +0 -98
  23. package/src/utils/vision.ts +0 -119
  24. /package/dist/{src/agents → agents}/claude/index.d.ts +0 -0
  25. /package/dist/{src/agents → agents}/index.d.ts +0 -0
  26. /package/dist/{src/buddy.d.ts → buddy.d.ts} +0 -0
  27. /package/dist/{src/drivers → drivers}/anthropic/index.d.ts +0 -0
  28. /package/dist/{src/drivers → drivers}/claude-agent-sdk/index.d.ts +0 -0
  29. /package/dist/{src/drivers → drivers}/index.d.ts +0 -0
  30. /package/dist/{src/drivers → drivers}/ollama/index.d.ts +0 -0
  31. /package/dist/{src/drivers → drivers}/openai/index.d.ts +0 -0
  32. /package/dist/{src/image.d.ts → image.d.ts} +0 -0
  33. /package/dist/{src/index.d.ts → index.d.ts} +0 -0
  34. /package/dist/{src/index.js → index.js} +0 -0
  35. /package/dist/{src/mcp.d.ts → mcp.d.ts} +0 -0
  36. /package/dist/{src/personalization.d.ts → personalization.d.ts} +0 -0
  37. /package/dist/{src/search.d.ts → search.d.ts} +0 -0
  38. /package/dist/{src/text.d.ts → text.d.ts} +0 -0
  39. /package/dist/{src/types.d.ts → types.d.ts} +0 -0
  40. /package/dist/{src/utils → utils}/client-bedrock-runtime.d.ts +0 -0
  41. /package/dist/{src/utils → utils}/client-bedrock.d.ts +0 -0
  42. /package/dist/{src/utils → utils}/model-access.d.ts +0 -0
  43. /package/dist/{src/utils → utils}/retry.d.ts +0 -0
  44. /package/dist/{src/utils → utils}/tokens.d.ts +0 -0
  45. /package/dist/{src/utils → utils}/usage.d.ts +0 -0
  46. /package/dist/{src/utils → utils}/vision.d.ts +0 -0
@@ -1,514 +0,0 @@
1
- /**
2
- * Ollama API Driver
3
- *
4
- * Local LLM integration via Ollama.
5
- * Supports chat completions, streaming, and embeddings.
6
- */
7
-
8
- import type { AIDriver, AIDriverConfig, AIMessage, AIResult, ChatCompletionOptions, OllamaAPIResponse } from '../../types'
9
-
10
- export interface OllamaDriverConfig extends AIDriverConfig {
11
- host?: string
12
- model?: string
13
- embeddingModel?: string
14
- }
15
-
16
- const DEFAULT_HOST = 'http://localhost:11434'
17
- const DEFAULT_MODEL = 'llama3.2'
18
- const DEFAULT_EMBEDDING_MODEL = 'nomic-embed-text'
19
-
20
- let globalConfig: OllamaDriverConfig = {}
21
-
22
- /**
23
- * Configure Ollama globally
24
- */
25
- export function configure(config: OllamaDriverConfig): void {
26
- globalConfig = { ...globalConfig, ...config }
27
- }
28
-
29
- function getConfig(config?: Partial<OllamaDriverConfig>): OllamaDriverConfig {
30
- return {
31
- host: config?.host || globalConfig.host || process.env.OLLAMA_HOST || DEFAULT_HOST,
32
- model: config?.model || globalConfig.model || process.env.OLLAMA_MODEL || DEFAULT_MODEL,
33
- embeddingModel: config?.embeddingModel || globalConfig.embeddingModel || DEFAULT_EMBEDDING_MODEL,
34
- }
35
- }
36
-
37
- export function createOllamaDriver(config: OllamaDriverConfig = {}): AIDriver {
38
- const {
39
- host = process.env.OLLAMA_HOST || DEFAULT_HOST,
40
- model = process.env.OLLAMA_MODEL || DEFAULT_MODEL,
41
- embeddingModel = DEFAULT_EMBEDDING_MODEL,
42
- } = config
43
-
44
- return {
45
- name: 'Ollama',
46
-
47
- async process(command: string, systemPrompt: string, history: AIMessage[]): Promise<string> {
48
- const response = await fetch(`${host}/api/chat`, {
49
- method: 'POST',
50
- headers: { 'Content-Type': 'application/json' },
51
- body: JSON.stringify({
52
- model,
53
- messages: [
54
- { role: 'system', content: systemPrompt },
55
- ...history,
56
- { role: 'user', content: command },
57
- ],
58
- stream: false,
59
- }),
60
- })
61
-
62
- if (!response.ok) {
63
- const error = await response.text()
64
- throw new Error(`Ollama API error: ${error}`)
65
- }
66
-
67
- const data = (await response.json()) as OllamaAPIResponse
68
- return data.message.content
69
- },
70
-
71
- async *stream(command: string, systemPrompt: string, history: AIMessage[]): AsyncGenerator<string> {
72
- const response = await fetch(`${host}/api/chat`, {
73
- method: 'POST',
74
- headers: { 'Content-Type': 'application/json' },
75
- body: JSON.stringify({
76
- model,
77
- messages: [
78
- { role: 'system', content: systemPrompt },
79
- ...history,
80
- { role: 'user', content: command },
81
- ],
82
- stream: true,
83
- }),
84
- })
85
-
86
- if (!response.ok) {
87
- const error = await response.text()
88
- throw new Error(`Ollama API error: ${error}`)
89
- }
90
-
91
- const reader = response.body?.getReader()
92
- if (!reader) throw new Error('No response body')
93
-
94
- const decoder = new TextDecoder()
95
- let buffer = ''
96
-
97
- while (true) {
98
- const { done, value } = await reader.read()
99
- if (done) break
100
-
101
- buffer += decoder.decode(value, { stream: true })
102
- const lines = buffer.split('\n')
103
- buffer = lines.pop() || ''
104
-
105
- for (const line of lines) {
106
- if (!line.trim()) continue
107
-
108
- try {
109
- const data = JSON.parse(line) as OllamaAPIResponse
110
- if (data.message?.content) {
111
- yield data.message.content
112
- }
113
- }
114
- catch {
115
- // Skip invalid JSON
116
- }
117
- }
118
- }
119
- },
120
-
121
- async embed(input: string | string[]): Promise<number[] | number[][]> {
122
- const inputs = Array.isArray(input) ? input : [input]
123
- const embeddings: number[][] = []
124
-
125
- for (const text of inputs) {
126
- const response = await fetch(`${host}/api/embeddings`, {
127
- method: 'POST',
128
- headers: { 'Content-Type': 'application/json' },
129
- body: JSON.stringify({
130
- model: embeddingModel,
131
- prompt: text,
132
- }),
133
- })
134
-
135
- if (!response.ok) {
136
- const error = await response.text()
137
- throw new Error(`Ollama Embeddings API error: ${error}`)
138
- }
139
-
140
- const data = (await response.json()) as { embedding: number[] }
141
- embeddings.push(data.embedding)
142
- }
143
-
144
- return Array.isArray(input) ? embeddings : embeddings[0]
145
- },
146
- }
147
- }
148
-
149
- /**
150
- * Chat completion with full options
151
- */
152
- export async function chat(
153
- messages: AIMessage[],
154
- options: ChatCompletionOptions = {},
155
- ): Promise<AIResult> {
156
- const config = getConfig()
157
- const {
158
- model = config.model,
159
- temperature,
160
- topP,
161
- stop,
162
- } = options
163
-
164
- const response = await fetch(`${config.host}/api/chat`, {
165
- method: 'POST',
166
- headers: { 'Content-Type': 'application/json' },
167
- body: JSON.stringify({
168
- model,
169
- messages,
170
- stream: false,
171
- options: {
172
- temperature,
173
- top_p: topP,
174
- stop,
175
- },
176
- }),
177
- })
178
-
179
- if (!response.ok) {
180
- const error = await response.text()
181
- throw new Error(`Ollama API error: ${error}`)
182
- }
183
-
184
- const data = (await response.json()) as any
185
-
186
- return {
187
- content: data.message.content,
188
- model: data.model,
189
- usage: {
190
- promptTokens: data.prompt_eval_count || 0,
191
- completionTokens: data.eval_count || 0,
192
- totalTokens: (data.prompt_eval_count || 0) + (data.eval_count || 0),
193
- },
194
- finishReason: data.done_reason || 'stop',
195
- }
196
- }
197
-
198
- /**
199
- * Stream chat completion
200
- */
201
- export async function* streamChat(
202
- messages: AIMessage[],
203
- options: ChatCompletionOptions = {},
204
- ): AsyncGenerator<string> {
205
- const config = getConfig()
206
- const {
207
- model = config.model,
208
- temperature,
209
- topP,
210
- stop,
211
- } = options
212
-
213
- const response = await fetch(`${config.host}/api/chat`, {
214
- method: 'POST',
215
- headers: { 'Content-Type': 'application/json' },
216
- body: JSON.stringify({
217
- model,
218
- messages,
219
- stream: true,
220
- options: {
221
- temperature,
222
- top_p: topP,
223
- stop,
224
- },
225
- }),
226
- })
227
-
228
- if (!response.ok) {
229
- const error = await response.text()
230
- throw new Error(`Ollama API error: ${error}`)
231
- }
232
-
233
- const reader = response.body?.getReader()
234
- if (!reader) throw new Error('No response body')
235
-
236
- const decoder = new TextDecoder()
237
- let buffer = ''
238
-
239
- while (true) {
240
- const { done, value } = await reader.read()
241
- if (done) break
242
-
243
- buffer += decoder.decode(value, { stream: true })
244
- const lines = buffer.split('\n')
245
- buffer = lines.pop() || ''
246
-
247
- for (const line of lines) {
248
- if (!line.trim()) continue
249
-
250
- try {
251
- const data = JSON.parse(line) as OllamaAPIResponse
252
- if (data.message?.content) {
253
- yield data.message.content
254
- }
255
- }
256
- catch {
257
- // Skip invalid JSON
258
- }
259
- }
260
- }
261
- }
262
-
263
- /**
264
- * Generate text completion (non-chat)
265
- */
266
- export async function generate(
267
- prompt: string,
268
- options: {
269
- model?: string
270
- system?: string
271
- template?: string
272
- context?: number[]
273
- raw?: boolean
274
- format?: 'json'
275
- images?: string[]
276
- } = {},
277
- ): Promise<AIResult> {
278
- const config = getConfig()
279
-
280
- const response = await fetch(`${config.host}/api/generate`, {
281
- method: 'POST',
282
- headers: { 'Content-Type': 'application/json' },
283
- body: JSON.stringify({
284
- model: options.model || config.model,
285
- prompt,
286
- system: options.system,
287
- template: options.template,
288
- context: options.context,
289
- raw: options.raw,
290
- format: options.format,
291
- images: options.images,
292
- stream: false,
293
- }),
294
- })
295
-
296
- if (!response.ok) {
297
- const error = await response.text()
298
- throw new Error(`Ollama API error: ${error}`)
299
- }
300
-
301
- const data = (await response.json()) as any
302
-
303
- return {
304
- content: data.response,
305
- model: data.model,
306
- usage: {
307
- promptTokens: data.prompt_eval_count || 0,
308
- completionTokens: data.eval_count || 0,
309
- totalTokens: (data.prompt_eval_count || 0) + (data.eval_count || 0),
310
- },
311
- }
312
- }
313
-
314
- /**
315
- * Create embeddings
316
- */
317
- export async function embed(
318
- input: string | string[],
319
- model?: string,
320
- ): Promise<number[] | number[][]> {
321
- const config = getConfig()
322
- const embeddingModel = model || config.embeddingModel
323
-
324
- const inputs = Array.isArray(input) ? input : [input]
325
- const embeddings: number[][] = []
326
-
327
- for (const text of inputs) {
328
- const response = await fetch(`${config.host}/api/embeddings`, {
329
- method: 'POST',
330
- headers: { 'Content-Type': 'application/json' },
331
- body: JSON.stringify({
332
- model: embeddingModel,
333
- prompt: text,
334
- }),
335
- })
336
-
337
- if (!response.ok) {
338
- const error = await response.text()
339
- throw new Error(`Ollama Embeddings API error: ${error}`)
340
- }
341
-
342
- const data = (await response.json()) as { embedding: number[] }
343
- embeddings.push(data.embedding)
344
- }
345
-
346
- return Array.isArray(input) ? embeddings : embeddings[0]
347
- }
348
-
349
- /**
350
- * List available models
351
- */
352
- export async function listModels(): Promise<Array<{
353
- name: string
354
- modified_at: string
355
- size: number
356
- digest: string
357
- details: {
358
- format: string
359
- family: string
360
- families: string[]
361
- parameter_size: string
362
- quantization_level: string
363
- }
364
- }>> {
365
- const config = getConfig()
366
-
367
- const response = await fetch(`${config.host}/api/tags`, {
368
- method: 'GET',
369
- })
370
-
371
- if (!response.ok) {
372
- const error = await response.text()
373
- throw new Error(`Ollama API error: ${error}`)
374
- }
375
-
376
- const data = (await response.json()) as { models: any[] }
377
- return data.models
378
- }
379
-
380
- /**
381
- * Pull a model from the library
382
- */
383
- export async function pullModel(
384
- name: string,
385
- onProgress?: (status: string, completed?: number, total?: number) => void,
386
- ): Promise<void> {
387
- const config = getConfig()
388
-
389
- const response = await fetch(`${config.host}/api/pull`, {
390
- method: 'POST',
391
- headers: { 'Content-Type': 'application/json' },
392
- body: JSON.stringify({ name, stream: true }),
393
- })
394
-
395
- if (!response.ok) {
396
- const error = await response.text()
397
- throw new Error(`Ollama API error: ${error}`)
398
- }
399
-
400
- const reader = response.body?.getReader()
401
- if (!reader) return
402
-
403
- const decoder = new TextDecoder()
404
- let buffer = ''
405
-
406
- while (true) {
407
- const { done, value } = await reader.read()
408
- if (done) break
409
-
410
- buffer += decoder.decode(value, { stream: true })
411
- const lines = buffer.split('\n')
412
- buffer = lines.pop() || ''
413
-
414
- for (const line of lines) {
415
- if (!line.trim()) continue
416
-
417
- try {
418
- const data = JSON.parse(line) as { status?: string; completed?: number; total?: number }
419
- if (onProgress) {
420
- onProgress(data.status, data.completed, data.total)
421
- }
422
- }
423
- catch {
424
- // Skip invalid JSON
425
- }
426
- }
427
- }
428
- }
429
-
430
- /**
431
- * Delete a model
432
- */
433
- export async function deleteModel(name: string): Promise<void> {
434
- const config = getConfig()
435
-
436
- const response = await fetch(`${config.host}/api/delete`, {
437
- method: 'DELETE',
438
- headers: { 'Content-Type': 'application/json' },
439
- body: JSON.stringify({ name }),
440
- })
441
-
442
- if (!response.ok) {
443
- const error = await response.text()
444
- throw new Error(`Ollama API error: ${error}`)
445
- }
446
- }
447
-
448
- /**
449
- * Show model information
450
- */
451
- export async function showModel(_name: string): Promise<{
452
- modelfile: string
453
- parameters: string
454
- template: string
455
- details: {
456
- format: string
457
- family: string
458
- families: string[]
459
- parameter_size: string
460
- quantization_level: string
461
- }
462
- }> {
463
- const config = getConfig()
464
-
465
- const response = await fetch(`${config.host}/api/show`, {
466
- method: 'POST',
467
- headers: { 'Content-Type': 'application/json' },
468
- body: JSON.stringify({ name: _name }),
469
- })
470
-
471
- if (!response.ok) {
472
- const error = await response.text()
473
- throw new Error(`Ollama API error: ${error}`)
474
- }
475
-
476
- return response.json() as any
477
- }
478
-
479
- /**
480
- * Check if Ollama is running
481
- */
482
- export async function isRunning(): Promise<boolean> {
483
- const config = getConfig()
484
-
485
- try {
486
- const response = await fetch(`${config.host}/api/tags`, {
487
- method: 'GET',
488
- })
489
- return response.ok
490
- }
491
- catch {
492
- return false
493
- }
494
- }
495
-
496
- export const ollamaDriver: { create: typeof createOllamaDriver } = {
497
- create: createOllamaDriver,
498
- }
499
-
500
- export const ollama = {
501
- configure,
502
- chat,
503
- streamChat,
504
- generate,
505
- embed,
506
- listModels,
507
- pullModel,
508
- deleteModel,
509
- showModel,
510
- isRunning,
511
- createDriver: createOllamaDriver,
512
- }
513
-
514
- export default ollama