@push.rocks/smartai 0.6.1 → 0.7.1
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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/abstract.classes.multimodal.d.ts +65 -0
- package/dist_ts/abstract.classes.multimodal.js +1 -1
- package/dist_ts/provider.anthropic.d.ts +9 -1
- package/dist_ts/provider.anthropic.js +82 -50
- package/dist_ts/provider.exo.d.ts +9 -1
- package/dist_ts/provider.exo.js +13 -1
- package/dist_ts/provider.groq.d.ts +9 -1
- package/dist_ts/provider.groq.js +13 -1
- package/dist_ts/provider.ollama.d.ts +9 -1
- package/dist_ts/provider.ollama.js +13 -1
- package/dist_ts/provider.openai.d.ts +10 -1
- package/dist_ts/provider.openai.js +172 -55
- package/dist_ts/provider.perplexity.d.ts +9 -1
- package/dist_ts/provider.perplexity.js +13 -1
- package/dist_ts/provider.xai.d.ts +9 -1
- package/dist_ts/provider.xai.js +13 -1
- package/package.json +1 -1
- package/readme.md +138 -10
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/abstract.classes.multimodal.ts +70 -0
- package/ts/provider.anthropic.ts +96 -53
- package/ts/provider.exo.ts +24 -1
- package/ts/provider.groq.ts +24 -1
- package/ts/provider.ollama.ts +24 -1
- package/ts/provider.openai.ts +170 -56
- package/ts/provider.perplexity.ts +24 -1
- package/ts/provider.xai.ts +24 -1
- package/readme.research.md +0 -177
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartai',
|
|
6
|
-
version: '0.
|
|
6
|
+
version: '0.7.1',
|
|
7
7
|
description: 'SmartAi is a versatile TypeScript library designed to facilitate integration and interaction with various AI models, offering functionalities for chat, audio generation, document processing, and vision tasks.'
|
|
8
8
|
}
|
|
@@ -50,6 +50,60 @@ export interface ResearchResponse {
|
|
|
50
50
|
metadata?: any;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Options for image generation
|
|
55
|
+
*/
|
|
56
|
+
export interface ImageGenerateOptions {
|
|
57
|
+
prompt: string;
|
|
58
|
+
model?: 'gpt-image-1' | 'dall-e-3' | 'dall-e-2';
|
|
59
|
+
quality?: 'low' | 'medium' | 'high' | 'standard' | 'hd' | 'auto';
|
|
60
|
+
size?: '256x256' | '512x512' | '1024x1024' | '1536x1024' | '1024x1536' | '1792x1024' | '1024x1792' | 'auto';
|
|
61
|
+
style?: 'vivid' | 'natural';
|
|
62
|
+
background?: 'transparent' | 'opaque' | 'auto';
|
|
63
|
+
outputFormat?: 'png' | 'jpeg' | 'webp';
|
|
64
|
+
outputCompression?: number; // 0-100 for webp/jpeg
|
|
65
|
+
moderation?: 'low' | 'auto';
|
|
66
|
+
n?: number; // Number of images to generate
|
|
67
|
+
stream?: boolean;
|
|
68
|
+
partialImages?: number; // 0-3 for streaming
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Options for image editing
|
|
73
|
+
*/
|
|
74
|
+
export interface ImageEditOptions {
|
|
75
|
+
image: Buffer;
|
|
76
|
+
prompt: string;
|
|
77
|
+
mask?: Buffer;
|
|
78
|
+
model?: 'gpt-image-1' | 'dall-e-2';
|
|
79
|
+
quality?: 'low' | 'medium' | 'high' | 'standard' | 'auto';
|
|
80
|
+
size?: '256x256' | '512x512' | '1024x1024' | '1536x1024' | '1024x1536' | 'auto';
|
|
81
|
+
background?: 'transparent' | 'opaque' | 'auto';
|
|
82
|
+
outputFormat?: 'png' | 'jpeg' | 'webp';
|
|
83
|
+
outputCompression?: number;
|
|
84
|
+
n?: number;
|
|
85
|
+
stream?: boolean;
|
|
86
|
+
partialImages?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Response format for image operations
|
|
91
|
+
*/
|
|
92
|
+
export interface ImageResponse {
|
|
93
|
+
images: Array<{
|
|
94
|
+
b64_json?: string;
|
|
95
|
+
url?: string;
|
|
96
|
+
revisedPrompt?: string;
|
|
97
|
+
}>;
|
|
98
|
+
metadata?: {
|
|
99
|
+
model: string;
|
|
100
|
+
quality?: string;
|
|
101
|
+
size?: string;
|
|
102
|
+
outputFormat?: string;
|
|
103
|
+
tokensUsed?: number;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
53
107
|
/**
|
|
54
108
|
* Abstract base class for multi-modal AI models.
|
|
55
109
|
* Provides a common interface for different AI providers (OpenAI, Anthropic, Perplexity, Ollama)
|
|
@@ -131,4 +185,20 @@ export abstract class MultiModalModel {
|
|
|
131
185
|
* @throws Error if the provider doesn't support research capabilities
|
|
132
186
|
*/
|
|
133
187
|
public abstract research(optionsArg: ResearchOptions): Promise<ResearchResponse>;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Image generation from text prompts
|
|
191
|
+
* @param optionsArg Options containing the prompt and generation parameters
|
|
192
|
+
* @returns Promise resolving to the generated image(s)
|
|
193
|
+
* @throws Error if the provider doesn't support image generation
|
|
194
|
+
*/
|
|
195
|
+
public abstract imageGenerate(optionsArg: ImageGenerateOptions): Promise<ImageResponse>;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Image editing and inpainting
|
|
199
|
+
* @param optionsArg Options containing the image, prompt, and editing parameters
|
|
200
|
+
* @returns Promise resolving to the edited image(s)
|
|
201
|
+
* @throws Error if the provider doesn't support image editing
|
|
202
|
+
*/
|
|
203
|
+
public abstract imageEdit(optionsArg: ImageEditOptions): Promise<ImageResponse>;
|
|
134
204
|
}
|
package/ts/provider.anthropic.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import * as paths from './paths.js';
|
|
3
3
|
import { MultiModalModel } from './abstract.classes.multimodal.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ChatOptions,
|
|
6
|
+
ChatResponse,
|
|
7
|
+
ChatMessage,
|
|
8
|
+
ResearchOptions,
|
|
9
|
+
ResearchResponse,
|
|
10
|
+
ImageGenerateOptions,
|
|
11
|
+
ImageEditOptions,
|
|
12
|
+
ImageResponse
|
|
13
|
+
} from './abstract.classes.multimodal.js';
|
|
5
14
|
import type { ImageBlockParam, TextBlockParam } from '@anthropic-ai/sdk/resources/messages';
|
|
6
15
|
|
|
7
16
|
type ContentBlock = ImageBlockParam | TextBlockParam;
|
|
@@ -68,7 +77,7 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
68
77
|
// If we have a complete message, send it to Anthropic
|
|
69
78
|
if (currentMessage) {
|
|
70
79
|
const stream = await this.anthropicApiClient.messages.create({
|
|
71
|
-
model: 'claude-
|
|
80
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
72
81
|
messages: [{ role: currentMessage.role, content: currentMessage.content }],
|
|
73
82
|
system: '',
|
|
74
83
|
stream: true,
|
|
@@ -112,7 +121,7 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
112
121
|
}));
|
|
113
122
|
|
|
114
123
|
const result = await this.anthropicApiClient.messages.create({
|
|
115
|
-
model: 'claude-
|
|
124
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
116
125
|
system: optionsArg.systemMessage,
|
|
117
126
|
messages: [
|
|
118
127
|
...messages,
|
|
@@ -159,7 +168,7 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
159
168
|
];
|
|
160
169
|
|
|
161
170
|
const result = await this.anthropicApiClient.messages.create({
|
|
162
|
-
model: 'claude-
|
|
171
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
163
172
|
messages: [{
|
|
164
173
|
role: 'user',
|
|
165
174
|
content
|
|
@@ -218,7 +227,7 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
218
227
|
}
|
|
219
228
|
|
|
220
229
|
const result = await this.anthropicApiClient.messages.create({
|
|
221
|
-
model: 'claude-
|
|
230
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
222
231
|
system: optionsArg.systemMessage,
|
|
223
232
|
messages: [
|
|
224
233
|
...messages,
|
|
@@ -251,23 +260,27 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
251
260
|
|
|
252
261
|
try {
|
|
253
262
|
// Build the tool configuration for web search
|
|
254
|
-
const tools =
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
required: ['query']
|
|
268
|
-
}
|
|
263
|
+
const tools: any[] = [];
|
|
264
|
+
|
|
265
|
+
if (this.options.enableWebSearch) {
|
|
266
|
+
const webSearchTool: any = {
|
|
267
|
+
type: 'web_search_20250305',
|
|
268
|
+
name: 'web_search'
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// Add optional parameters
|
|
272
|
+
if (optionsArg.maxSources) {
|
|
273
|
+
webSearchTool.max_uses = optionsArg.maxSources;
|
|
269
274
|
}
|
|
270
|
-
|
|
275
|
+
|
|
276
|
+
if (this.options.searchDomainAllowList?.length) {
|
|
277
|
+
webSearchTool.allowed_domains = this.options.searchDomainAllowList;
|
|
278
|
+
} else if (this.options.searchDomainBlockList?.length) {
|
|
279
|
+
webSearchTool.blocked_domains = this.options.searchDomainBlockList;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
tools.push(webSearchTool);
|
|
283
|
+
}
|
|
271
284
|
|
|
272
285
|
// Configure the request based on search depth
|
|
273
286
|
const maxTokens = optionsArg.searchDepth === 'deep' ? 8192 :
|
|
@@ -275,7 +288,7 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
275
288
|
|
|
276
289
|
// Create the research request
|
|
277
290
|
const requestParams: any = {
|
|
278
|
-
model: 'claude-
|
|
291
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
279
292
|
system: systemMessage,
|
|
280
293
|
messages: [
|
|
281
294
|
{
|
|
@@ -290,7 +303,6 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
290
303
|
// Add tools if web search is enabled
|
|
291
304
|
if (tools.length > 0) {
|
|
292
305
|
requestParams.tools = tools;
|
|
293
|
-
requestParams.tool_choice = { type: 'auto' };
|
|
294
306
|
}
|
|
295
307
|
|
|
296
308
|
// Execute the research request
|
|
@@ -304,54 +316,71 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
304
316
|
// Process content blocks
|
|
305
317
|
for (const block of result.content) {
|
|
306
318
|
if ('text' in block) {
|
|
319
|
+
// Accumulate text content
|
|
307
320
|
answer += block.text;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
321
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
322
|
+
// Extract citations if present
|
|
323
|
+
if ('citations' in block && Array.isArray(block.citations)) {
|
|
324
|
+
for (const citation of block.citations) {
|
|
325
|
+
if (citation.type === 'web_search_result_location') {
|
|
326
|
+
sources.push({
|
|
327
|
+
title: citation.title || '',
|
|
328
|
+
url: citation.url || '',
|
|
329
|
+
snippet: citation.cited_text || ''
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
} else if ('type' in block && block.type === 'server_tool_use') {
|
|
335
|
+
// Extract search queries from server tool use
|
|
336
|
+
if (block.name === 'web_search' && block.input && typeof block.input === 'object' && 'query' in block.input) {
|
|
337
|
+
searchQueries.push((block.input as any).query);
|
|
338
|
+
}
|
|
339
|
+
} else if ('type' in block && block.type === 'web_search_tool_result') {
|
|
340
|
+
// Extract sources from web search results
|
|
341
|
+
if (Array.isArray(block.content)) {
|
|
342
|
+
for (const result of block.content) {
|
|
343
|
+
if (result.type === 'web_search_result') {
|
|
344
|
+
// Only add if not already in sources (avoid duplicates from citations)
|
|
345
|
+
if (!sources.some(s => s.url === result.url)) {
|
|
346
|
+
sources.push({
|
|
347
|
+
title: result.title || '',
|
|
348
|
+
url: result.url || '',
|
|
349
|
+
snippet: '' // Search results don't include snippets, only citations do
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
321
356
|
}
|
|
322
357
|
|
|
323
|
-
//
|
|
324
|
-
|
|
325
|
-
|
|
358
|
+
// Fallback: Parse markdown-style links if no citations found
|
|
359
|
+
if (sources.length === 0) {
|
|
360
|
+
const urlRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
361
|
+
let match: RegExpExecArray | null;
|
|
326
362
|
|
|
327
|
-
|
|
328
|
-
// Check if this URL is already in sources
|
|
329
|
-
if (!sources.some(s => s.url === url)) {
|
|
363
|
+
while ((match = urlRegex.exec(answer)) !== null) {
|
|
330
364
|
sources.push({
|
|
331
|
-
title:
|
|
332
|
-
url:
|
|
365
|
+
title: match[1],
|
|
366
|
+
url: match[2],
|
|
333
367
|
snippet: ''
|
|
334
368
|
});
|
|
335
369
|
}
|
|
336
370
|
}
|
|
337
371
|
|
|
338
|
-
//
|
|
339
|
-
|
|
340
|
-
for (const toolUse of result.tool_use) {
|
|
341
|
-
if (toolUse.name === 'web_search' && toolUse.input?.query) {
|
|
342
|
-
searchQueries.push(toolUse.input.query);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
372
|
+
// Check if web search was used based on usage info
|
|
373
|
+
const webSearchCount = result.usage?.server_tool_use?.web_search_requests || 0;
|
|
346
374
|
|
|
347
375
|
return {
|
|
348
376
|
answer,
|
|
349
377
|
sources,
|
|
350
378
|
searchQueries: searchQueries.length > 0 ? searchQueries : undefined,
|
|
351
379
|
metadata: {
|
|
352
|
-
model: 'claude-
|
|
380
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
353
381
|
searchDepth: optionsArg.searchDepth || 'basic',
|
|
354
|
-
tokensUsed: result.usage?.output_tokens
|
|
382
|
+
tokensUsed: result.usage?.output_tokens,
|
|
383
|
+
webSearchesPerformed: webSearchCount
|
|
355
384
|
}
|
|
356
385
|
};
|
|
357
386
|
} catch (error) {
|
|
@@ -359,4 +388,18 @@ export class AnthropicProvider extends MultiModalModel {
|
|
|
359
388
|
throw new Error(`Failed to perform research: ${error.message}`);
|
|
360
389
|
}
|
|
361
390
|
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Image generation is not supported by Anthropic
|
|
394
|
+
*/
|
|
395
|
+
public async imageGenerate(optionsArg: ImageGenerateOptions): Promise<ImageResponse> {
|
|
396
|
+
throw new Error('Image generation is not supported by Anthropic. Claude can only analyze images, not generate them. Please use OpenAI provider for image generation.');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Image editing is not supported by Anthropic
|
|
401
|
+
*/
|
|
402
|
+
public async imageEdit(optionsArg: ImageEditOptions): Promise<ImageResponse> {
|
|
403
|
+
throw new Error('Image editing is not supported by Anthropic. Claude can only analyze images, not edit them. Please use OpenAI provider for image editing.');
|
|
404
|
+
}
|
|
362
405
|
}
|
package/ts/provider.exo.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import * as paths from './paths.js';
|
|
3
3
|
import { MultiModalModel } from './abstract.classes.multimodal.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ChatOptions,
|
|
6
|
+
ChatResponse,
|
|
7
|
+
ChatMessage,
|
|
8
|
+
ResearchOptions,
|
|
9
|
+
ResearchResponse,
|
|
10
|
+
ImageGenerateOptions,
|
|
11
|
+
ImageEditOptions,
|
|
12
|
+
ImageResponse
|
|
13
|
+
} from './abstract.classes.multimodal.js';
|
|
5
14
|
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
|
|
6
15
|
|
|
7
16
|
export interface IExoProviderOptions {
|
|
@@ -129,4 +138,18 @@ export class ExoProvider extends MultiModalModel {
|
|
|
129
138
|
public async research(optionsArg: ResearchOptions): Promise<ResearchResponse> {
|
|
130
139
|
throw new Error('Research capabilities are not yet supported by Exo provider.');
|
|
131
140
|
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Image generation is not supported by Exo
|
|
144
|
+
*/
|
|
145
|
+
public async imageGenerate(optionsArg: ImageGenerateOptions): Promise<ImageResponse> {
|
|
146
|
+
throw new Error('Image generation is not supported by Exo. Please use OpenAI provider for image generation.');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Image editing is not supported by Exo
|
|
151
|
+
*/
|
|
152
|
+
public async imageEdit(optionsArg: ImageEditOptions): Promise<ImageResponse> {
|
|
153
|
+
throw new Error('Image editing is not supported by Exo. Please use OpenAI provider for image editing.');
|
|
154
|
+
}
|
|
132
155
|
}
|
package/ts/provider.groq.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import * as paths from './paths.js';
|
|
3
3
|
import { MultiModalModel } from './abstract.classes.multimodal.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ChatOptions,
|
|
6
|
+
ChatResponse,
|
|
7
|
+
ChatMessage,
|
|
8
|
+
ResearchOptions,
|
|
9
|
+
ResearchResponse,
|
|
10
|
+
ImageGenerateOptions,
|
|
11
|
+
ImageEditOptions,
|
|
12
|
+
ImageResponse
|
|
13
|
+
} from './abstract.classes.multimodal.js';
|
|
5
14
|
|
|
6
15
|
export interface IGroqProviderOptions {
|
|
7
16
|
groqToken: string;
|
|
@@ -193,4 +202,18 @@ export class GroqProvider extends MultiModalModel {
|
|
|
193
202
|
public async research(optionsArg: ResearchOptions): Promise<ResearchResponse> {
|
|
194
203
|
throw new Error('Research capabilities are not yet supported by Groq provider.');
|
|
195
204
|
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Image generation is not supported by Groq
|
|
208
|
+
*/
|
|
209
|
+
public async imageGenerate(optionsArg: ImageGenerateOptions): Promise<ImageResponse> {
|
|
210
|
+
throw new Error('Image generation is not supported by Groq. Please use OpenAI provider for image generation.');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Image editing is not supported by Groq
|
|
215
|
+
*/
|
|
216
|
+
public async imageEdit(optionsArg: ImageEditOptions): Promise<ImageResponse> {
|
|
217
|
+
throw new Error('Image editing is not supported by Groq. Please use OpenAI provider for image editing.');
|
|
218
|
+
}
|
|
196
219
|
}
|
package/ts/provider.ollama.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import * as paths from './paths.js';
|
|
3
3
|
import { MultiModalModel } from './abstract.classes.multimodal.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ChatOptions,
|
|
6
|
+
ChatResponse,
|
|
7
|
+
ChatMessage,
|
|
8
|
+
ResearchOptions,
|
|
9
|
+
ResearchResponse,
|
|
10
|
+
ImageGenerateOptions,
|
|
11
|
+
ImageEditOptions,
|
|
12
|
+
ImageResponse
|
|
13
|
+
} from './abstract.classes.multimodal.js';
|
|
5
14
|
|
|
6
15
|
export interface IOllamaProviderOptions {
|
|
7
16
|
baseUrl?: string;
|
|
@@ -255,4 +264,18 @@ export class OllamaProvider extends MultiModalModel {
|
|
|
255
264
|
public async research(optionsArg: ResearchOptions): Promise<ResearchResponse> {
|
|
256
265
|
throw new Error('Research capabilities are not yet supported by Ollama provider.');
|
|
257
266
|
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Image generation is not supported by Ollama
|
|
270
|
+
*/
|
|
271
|
+
public async imageGenerate(optionsArg: ImageGenerateOptions): Promise<ImageResponse> {
|
|
272
|
+
throw new Error('Image generation is not supported by Ollama. Please use OpenAI provider for image generation.');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Image editing is not supported by Ollama
|
|
277
|
+
*/
|
|
278
|
+
public async imageEdit(optionsArg: ImageEditOptions): Promise<ImageResponse> {
|
|
279
|
+
throw new Error('Image editing is not supported by Ollama. Please use OpenAI provider for image editing.');
|
|
280
|
+
}
|
|
258
281
|
}
|