@happyvertical/ai 0.74.8
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/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/README.md +384 -0
- package/dist/chunks/anthropic-BRwbhwIl.js +463 -0
- package/dist/chunks/anthropic-BRwbhwIl.js.map +1 -0
- package/dist/chunks/bedrock-Cf1xUerN.js +808 -0
- package/dist/chunks/bedrock-Cf1xUerN.js.map +1 -0
- package/dist/chunks/bifrost-3mXtQsTj.js +233 -0
- package/dist/chunks/bifrost-3mXtQsTj.js.map +1 -0
- package/dist/chunks/claude-cli-BrHRfkry.js +603 -0
- package/dist/chunks/claude-cli-BrHRfkry.js.map +1 -0
- package/dist/chunks/gateway-admin-C4GFPbZF.js +359 -0
- package/dist/chunks/gateway-admin-C4GFPbZF.js.map +1 -0
- package/dist/chunks/gemini-BfpHXDIQ.js +662 -0
- package/dist/chunks/gemini-BfpHXDIQ.js.map +1 -0
- package/dist/chunks/huggingface-280qv9iv.js +366 -0
- package/dist/chunks/huggingface-280qv9iv.js.map +1 -0
- package/dist/chunks/index-BT4thAvS.js +934 -0
- package/dist/chunks/index-BT4thAvS.js.map +1 -0
- package/dist/chunks/litellm-DhPKa_Jz.js +220 -0
- package/dist/chunks/litellm-DhPKa_Jz.js.map +1 -0
- package/dist/chunks/ollama-Di1ldur0.js +851 -0
- package/dist/chunks/ollama-Di1ldur0.js.map +1 -0
- package/dist/chunks/openai-5snI2diE.js +749 -0
- package/dist/chunks/openai-5snI2diE.js.map +1 -0
- package/dist/chunks/qwen-tts-DgPgdXxG.js +365 -0
- package/dist/chunks/qwen-tts-DgPgdXxG.js.map +1 -0
- package/dist/chunks/usage-DMWiJ2oB.js +21 -0
- package/dist/chunks/usage-DMWiJ2oB.js.map +1 -0
- package/dist/cli/claude-context.d.ts +3 -0
- package/dist/cli/claude-context.d.ts.map +1 -0
- package/dist/cli/claude-context.js +21 -0
- package/dist/cli/claude-context.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/node/factory.d.ts +27 -0
- package/dist/node/factory.d.ts.map +1 -0
- package/dist/shared/client.d.ts +410 -0
- package/dist/shared/client.d.ts.map +1 -0
- package/dist/shared/factory.d.ts +83 -0
- package/dist/shared/factory.d.ts.map +1 -0
- package/dist/shared/message.d.ts +71 -0
- package/dist/shared/message.d.ts.map +1 -0
- package/dist/shared/providers/anthropic.d.ts +82 -0
- package/dist/shared/providers/anthropic.d.ts.map +1 -0
- package/dist/shared/providers/bedrock.d.ts +49 -0
- package/dist/shared/providers/bedrock.d.ts.map +1 -0
- package/dist/shared/providers/bifrost.d.ts +25 -0
- package/dist/shared/providers/bifrost.d.ts.map +1 -0
- package/dist/shared/providers/claude-cli.d.ts +139 -0
- package/dist/shared/providers/claude-cli.d.ts.map +1 -0
- package/dist/shared/providers/gateway-admin.d.ts +35 -0
- package/dist/shared/providers/gateway-admin.d.ts.map +1 -0
- package/dist/shared/providers/gemini.d.ts +116 -0
- package/dist/shared/providers/gemini.d.ts.map +1 -0
- package/dist/shared/providers/huggingface.d.ts +33 -0
- package/dist/shared/providers/huggingface.d.ts.map +1 -0
- package/dist/shared/providers/litellm.d.ts +25 -0
- package/dist/shared/providers/litellm.d.ts.map +1 -0
- package/dist/shared/providers/ollama.d.ts +47 -0
- package/dist/shared/providers/ollama.d.ts.map +1 -0
- package/dist/shared/providers/openai.d.ts +272 -0
- package/dist/shared/providers/openai.d.ts.map +1 -0
- package/dist/shared/providers/qwen-tts.d.ts +85 -0
- package/dist/shared/providers/qwen-tts.d.ts.map +1 -0
- package/dist/shared/providers/usage.d.ts +14 -0
- package/dist/shared/providers/usage.d.ts.map +1 -0
- package/dist/shared/rate-limit.d.ts +13 -0
- package/dist/shared/rate-limit.d.ts.map +1 -0
- package/dist/shared/thread.d.ts +104 -0
- package/dist/shared/thread.d.ts.map +1 -0
- package/dist/shared/types.d.ts +1779 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/metadata.json +35 -0
- package/package.json +62 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { AICapabilities, AIInterface, AIMessage, AIModel, AIResponse, BaseAIOptions, ChatOptions, CompletionOptions, EmbeddingOptions, EmbeddingResponse, ImageDescriptionOptions, ImageEmbeddingOptions, ImageGenerationOptions, ImageGenerationResponse, MessageOptions, TTSOptions, TTSResponse, Voice, VoiceCloneOptions, VoiceDesignOptions, VoiceListOptions } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Shared profile for OpenAI-compatible providers
|
|
4
|
+
*/
|
|
5
|
+
export interface OpenAICompatibleProfile {
|
|
6
|
+
providerLabel: string;
|
|
7
|
+
providerName: string;
|
|
8
|
+
defaultModel: string;
|
|
9
|
+
capabilities: AICapabilities;
|
|
10
|
+
describeModel(modelId: string): string;
|
|
11
|
+
getContextLength(modelId: string): number;
|
|
12
|
+
getModelCapabilities(modelId: string): string[];
|
|
13
|
+
shouldIncludeModel(modelId: string): boolean;
|
|
14
|
+
supportsFunctions(modelId: string): boolean;
|
|
15
|
+
supportsVision(modelId: string): boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface OpenAICompatibleOptions extends BaseAIOptions {
|
|
18
|
+
type?: string;
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
baseUrl?: string;
|
|
21
|
+
organization?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* OpenAI provider implementation that handles all interactions with OpenAI's API.
|
|
25
|
+
* Supports GPT models, embeddings, function calling, streaming, and vision capabilities.
|
|
26
|
+
*/
|
|
27
|
+
export declare class OpenAIProvider implements AIInterface {
|
|
28
|
+
private client;
|
|
29
|
+
private options;
|
|
30
|
+
private readonly profile;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new OpenAI provider instance
|
|
33
|
+
* @param options - Configuration options for the OpenAI provider
|
|
34
|
+
*/
|
|
35
|
+
constructor(options: OpenAICompatibleOptions, profile?: OpenAICompatibleProfile);
|
|
36
|
+
/**
|
|
37
|
+
* Generate a chat completion using OpenAI's chat models
|
|
38
|
+
* @param messages - Array of conversation messages
|
|
39
|
+
* @param options - Optional configuration for the chat completion
|
|
40
|
+
* @returns Promise resolving to the AI response with content and metadata
|
|
41
|
+
* @throws {AIError} When the API request fails or returns invalid data
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const response = await provider.chat([
|
|
46
|
+
* { role: 'system', content: 'You are a helpful assistant.' },
|
|
47
|
+
* { role: 'user', content: 'What is the capital of France?' }
|
|
48
|
+
* ], {
|
|
49
|
+
* model: 'gpt-4o',
|
|
50
|
+
* temperature: 0.7,
|
|
51
|
+
* maxTokens: 150
|
|
52
|
+
* });
|
|
53
|
+
* console.log(response.content); // "Paris is the capital of France."
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
chat(messages: AIMessage[], options?: ChatOptions): Promise<AIResponse>;
|
|
57
|
+
/**
|
|
58
|
+
* Generate a text completion for a given prompt
|
|
59
|
+
* @param prompt - The text prompt to complete
|
|
60
|
+
* @param options - Optional configuration for the completion
|
|
61
|
+
* @returns Promise resolving to the AI response
|
|
62
|
+
* @throws {AIError} When the API request fails
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const response = await provider.complete('The weather today is', {
|
|
67
|
+
* model: 'gpt-4o',
|
|
68
|
+
* maxTokens: 50,
|
|
69
|
+
* temperature: 0.5
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
complete(prompt: string, options?: CompletionOptions): Promise<AIResponse>;
|
|
74
|
+
/**
|
|
75
|
+
* Simple message interface for single-turn interactions with optional history
|
|
76
|
+
*
|
|
77
|
+
* @param text - The message text to send
|
|
78
|
+
* @param options - Configuration options including history, model, etc.
|
|
79
|
+
* @returns Promise resolving to the response content string
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // Simple usage
|
|
84
|
+
* const response = await provider.message('Hello!');
|
|
85
|
+
*
|
|
86
|
+
* // With options
|
|
87
|
+
* const response = await provider.message('Analyze this', {
|
|
88
|
+
* model: 'gpt-4o',
|
|
89
|
+
* responseFormat: { type: 'json_object' }
|
|
90
|
+
* });
|
|
91
|
+
*
|
|
92
|
+
* // With history
|
|
93
|
+
* const response = await provider.message('What was my question?', {
|
|
94
|
+
* history: [
|
|
95
|
+
* { role: 'user', content: 'What is 2+2?' },
|
|
96
|
+
* { role: 'assistant', content: '4' }
|
|
97
|
+
* ]
|
|
98
|
+
* });
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
message(text: string, options?: MessageOptions): Promise<string>;
|
|
102
|
+
/**
|
|
103
|
+
* Generate embeddings for the given text(s)
|
|
104
|
+
* @param text - Single text string or array of texts to embed
|
|
105
|
+
* @param options - Optional configuration for embeddings
|
|
106
|
+
* @returns Promise resolving to embeddings response with vector arrays
|
|
107
|
+
* @throws {AIError} When the API request fails
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* // Single text embedding
|
|
112
|
+
* const response1 = await provider.embed('Hello world');
|
|
113
|
+
* console.log(response1.embeddings[0]); // Array of numbers
|
|
114
|
+
*
|
|
115
|
+
* // Multiple text embeddings
|
|
116
|
+
* const response2 = await provider.embed(['Text 1', 'Text 2']);
|
|
117
|
+
* console.log(response2.embeddings.length); // 2
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
embed(text: string | string[], options?: EmbeddingOptions): Promise<EmbeddingResponse>;
|
|
121
|
+
/**
|
|
122
|
+
* Convert an image to a base64 data URL
|
|
123
|
+
* @param image - Image as URL, base64 data URL, or Buffer
|
|
124
|
+
* @returns base64 data URL string
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
127
|
+
private imageToBase64;
|
|
128
|
+
/**
|
|
129
|
+
* Generate a text description of an image
|
|
130
|
+
* @param image - Image as URL, base64 data URL, or Buffer
|
|
131
|
+
* @param prompt - Custom prompt for description (optional)
|
|
132
|
+
* @param options - Optional configuration
|
|
133
|
+
* @returns Promise resolving to the description string
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const description = await provider.describeImage('https://example.com/image.jpg');
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
describeImage(image: string | Buffer, prompt?: string, options?: ImageDescriptionOptions): Promise<string>;
|
|
141
|
+
/**
|
|
142
|
+
* Generate embeddings for an image using describe-then-embed pattern
|
|
143
|
+
* @param image - Image as URL, base64 data URL, or Buffer
|
|
144
|
+
* @param options - Optional configuration for image embeddings
|
|
145
|
+
* @returns Promise resolving to embeddings response
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* const embedding = await provider.embedImage('https://example.com/image.jpg');
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
embedImage(image: string | Buffer, options?: ImageEmbeddingOptions): Promise<EmbeddingResponse>;
|
|
153
|
+
/**
|
|
154
|
+
* Generate an image from a text prompt using DALL-E
|
|
155
|
+
* @param prompt - Text description of the image to generate
|
|
156
|
+
* @param options - Optional configuration for image generation
|
|
157
|
+
* @returns Promise resolving to generated image(s)
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```typescript
|
|
161
|
+
* const result = await provider.generateImage('A sunset over mountains');
|
|
162
|
+
* fs.writeFileSync('image.png', result.images[0].data);
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
generateImage(prompt: string, options?: ImageGenerationOptions): Promise<ImageGenerationResponse>;
|
|
166
|
+
/**
|
|
167
|
+
* Stream a chat completion response in real-time
|
|
168
|
+
* @param messages - Array of conversation messages
|
|
169
|
+
* @param options - Optional configuration for the chat completion
|
|
170
|
+
* @yields Individual content chunks as they arrive
|
|
171
|
+
* @throws {AIError} When the streaming request fails
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* for await (const chunk of provider.stream([
|
|
176
|
+
* { role: 'user', content: 'Write a story about AI' }
|
|
177
|
+
* ])) {
|
|
178
|
+
* process.stdout.write(chunk);
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
stream(messages: AIMessage[], options?: ChatOptions): AsyncIterable<string>;
|
|
183
|
+
/**
|
|
184
|
+
* Count the number of tokens in the given text
|
|
185
|
+
* @param text - The text to count tokens for
|
|
186
|
+
* @returns Promise resolving to the estimated token count
|
|
187
|
+
*
|
|
188
|
+
* @remarks
|
|
189
|
+
* OpenAI doesn't provide a direct token counting API, so this is an approximation
|
|
190
|
+
* based on the general rule of ~4 characters per token. For precise counting,
|
|
191
|
+
* consider using a dedicated tokenizer library.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const count = await provider.countTokens('Hello, world!');
|
|
196
|
+
* console.log(count); // Approximately 4 tokens
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
countTokens(text: string): Promise<number>;
|
|
200
|
+
/**
|
|
201
|
+
* Get a list of available OpenAI models
|
|
202
|
+
* @returns Promise resolving to an array of model information
|
|
203
|
+
* @throws {AIError} When the API request fails
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* const models = await provider.getModels();
|
|
208
|
+
* const gptModels = models.filter(m => m.id.includes('gpt'));
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
getModels(): Promise<AIModel[]>;
|
|
212
|
+
/**
|
|
213
|
+
* Get the capabilities supported by this OpenAI provider
|
|
214
|
+
* @returns Promise resolving to provider capabilities
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const caps = await provider.getCapabilities();
|
|
219
|
+
* if (caps.functions) {
|
|
220
|
+
* // Provider supports function calling
|
|
221
|
+
* }
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
getCapabilities(): Promise<AICapabilities>;
|
|
225
|
+
synthesizeSpeech(_text: string, _options?: TTSOptions): Promise<TTSResponse>;
|
|
226
|
+
streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer>;
|
|
227
|
+
cloneVoice(_options: VoiceCloneOptions): Promise<Voice>;
|
|
228
|
+
designVoice(_options: VoiceDesignOptions): Promise<Voice>;
|
|
229
|
+
getVoices(_options?: VoiceListOptions): Promise<Voice[]>;
|
|
230
|
+
/**
|
|
231
|
+
* Maps internal AI messages to OpenAI's message format
|
|
232
|
+
* @param messages - Array of internal AI messages
|
|
233
|
+
* @returns Array of OpenAI-compatible message parameters
|
|
234
|
+
* @private
|
|
235
|
+
*/
|
|
236
|
+
private mapMessagesToOpenAI;
|
|
237
|
+
/**
|
|
238
|
+
* Maps internal tool choice format to OpenAI's tool choice format
|
|
239
|
+
* @param toolChoice - Internal tool choice specification
|
|
240
|
+
* @returns OpenAI-compatible tool choice option or undefined
|
|
241
|
+
* @private
|
|
242
|
+
*/
|
|
243
|
+
private mapToolChoice;
|
|
244
|
+
/**
|
|
245
|
+
* Maps OpenAI usage information to internal token usage format
|
|
246
|
+
* @param usage - OpenAI usage object from API response
|
|
247
|
+
* @returns Internal token usage object or undefined
|
|
248
|
+
* @private
|
|
249
|
+
*/
|
|
250
|
+
private mapUsage;
|
|
251
|
+
/**
|
|
252
|
+
* Maps OpenAI finish reason to internal finish reason format
|
|
253
|
+
* @param reason - OpenAI finish reason from API response
|
|
254
|
+
* @returns Internal finish reason
|
|
255
|
+
* @private
|
|
256
|
+
*/
|
|
257
|
+
private mapFinishReason;
|
|
258
|
+
/**
|
|
259
|
+
* Gets the context length for a given OpenAI model
|
|
260
|
+
* @param modelId - The OpenAI model identifier
|
|
261
|
+
* @returns Maximum context length in tokens
|
|
262
|
+
* @private
|
|
263
|
+
*/
|
|
264
|
+
/**
|
|
265
|
+
* Maps OpenAI API errors to internal AI error types
|
|
266
|
+
* @param error - The error object from OpenAI API
|
|
267
|
+
* @returns Appropriate internal AI error instance
|
|
268
|
+
* @private
|
|
269
|
+
*/
|
|
270
|
+
private mapError;
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/shared/providers/openai.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { AICapabilities, AIInterface, AIMessage, AIModel, AIResponse, ChatOptions, CompletionOptions, EmbeddingOptions, EmbeddingResponse, ImageDescriptionOptions, ImageEmbeddingOptions, ImageGenerationOptions, ImageGenerationResponse, MessageOptions, Qwen3TTSOptions, TTSOptions, TTSResponse, Voice, VoiceCloneOptions, VoiceDesignOptions, VoiceListOptions } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Qwen3-TTS provider implementation for text-to-speech synthesis.
|
|
4
|
+
*
|
|
5
|
+
* This provider focuses on TTS capabilities and throws NOT_IMPLEMENTED
|
|
6
|
+
* for text generation methods. Use alongside another provider for full
|
|
7
|
+
* AI capabilities.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { getAI } from '@happyvertical/ai';
|
|
12
|
+
*
|
|
13
|
+
* // Create TTS-only provider
|
|
14
|
+
* const tts = await getAI({
|
|
15
|
+
* type: 'qwen3-tts',
|
|
16
|
+
* endpoint: 'http://localhost:8880'
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Synthesize speech
|
|
20
|
+
* const result = await tts.synthesizeSpeech('Hello, world!', {
|
|
21
|
+
* voice: 'news-anchor',
|
|
22
|
+
* includeWordTimings: true
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // Clone a voice
|
|
26
|
+
* const sample = fs.readFileSync('voice-sample.wav');
|
|
27
|
+
* const voice = await tts.cloneVoice({
|
|
28
|
+
* sampleAudio: sample,
|
|
29
|
+
* name: 'My Custom Voice'
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare class Qwen3TTSProvider implements AIInterface {
|
|
34
|
+
private options;
|
|
35
|
+
private rateLimiter;
|
|
36
|
+
/**
|
|
37
|
+
* Creates a new Qwen3-TTS provider instance
|
|
38
|
+
* @param options - Configuration options for the TTS provider
|
|
39
|
+
*/
|
|
40
|
+
constructor(options: Qwen3TTSOptions);
|
|
41
|
+
/**
|
|
42
|
+
* Get the TTS endpoint URL
|
|
43
|
+
*/
|
|
44
|
+
private get endpoint();
|
|
45
|
+
/**
|
|
46
|
+
* Make an HTTP request to the TTS service
|
|
47
|
+
*/
|
|
48
|
+
private request;
|
|
49
|
+
/**
|
|
50
|
+
* Synthesize speech from text
|
|
51
|
+
*/
|
|
52
|
+
synthesizeSpeech(text: string, options?: TTSOptions): Promise<TTSResponse>;
|
|
53
|
+
/**
|
|
54
|
+
* Stream speech synthesis for real-time playback
|
|
55
|
+
*/
|
|
56
|
+
streamSpeech(text: string, options?: TTSOptions): AsyncIterable<Buffer>;
|
|
57
|
+
/**
|
|
58
|
+
* Clone a voice from an audio sample
|
|
59
|
+
*/
|
|
60
|
+
cloneVoice(options: VoiceCloneOptions): Promise<Voice>;
|
|
61
|
+
/**
|
|
62
|
+
* Design a voice using natural language description
|
|
63
|
+
*/
|
|
64
|
+
designVoice(options: VoiceDesignOptions): Promise<Voice>;
|
|
65
|
+
/**
|
|
66
|
+
* List available voices
|
|
67
|
+
*/
|
|
68
|
+
getVoices(options?: VoiceListOptions): Promise<Voice[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Map API voice response to Voice interface
|
|
71
|
+
*/
|
|
72
|
+
private mapVoice;
|
|
73
|
+
chat(_messages: AIMessage[], _options?: ChatOptions): Promise<AIResponse>;
|
|
74
|
+
complete(_prompt: string, _options?: CompletionOptions): Promise<AIResponse>;
|
|
75
|
+
message(_text: string, _options?: MessageOptions): Promise<string>;
|
|
76
|
+
embed(_text: string | string[], _options?: EmbeddingOptions): Promise<EmbeddingResponse>;
|
|
77
|
+
embedImage(_image: string | Buffer, _options?: ImageEmbeddingOptions): Promise<EmbeddingResponse>;
|
|
78
|
+
describeImage(_image: string | Buffer, _prompt?: string, _options?: ImageDescriptionOptions): Promise<string>;
|
|
79
|
+
generateImage(_prompt: string, _options?: ImageGenerationOptions): Promise<ImageGenerationResponse>;
|
|
80
|
+
stream(_messages: AIMessage[], _options?: ChatOptions): AsyncIterable<string>;
|
|
81
|
+
countTokens(_text: string): Promise<number>;
|
|
82
|
+
getModels(): Promise<AIModel[]>;
|
|
83
|
+
getCapabilities(): Promise<AICapabilities>;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=qwen-tts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qwen-tts.d.ts","sourceRoot":"","sources":["../../../src/shared/providers/qwen-tts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,SAAS,EACT,OAAO,EACP,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,eAAe,EACf,UAAU,EACV,WAAW,EACX,KAAK,EACL,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,UAAU,CAAC;AA4HlB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAClD,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,WAAW,CAAc;IAEjC;;;OAGG;gBACS,OAAO,EAAE,eAAe;IAUpC;;OAEG;IACH,OAAO,KAAK,QAAQ,GAEnB;IAED;;OAEG;YACW,OAAO;IA0CrB;;OAEG;IACG,gBAAgB,CACpB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,WAAW,CAAC;IAiCvB;;OAEG;IACI,YAAY,CACjB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,UAAe,GACvB,aAAa,CAAC,MAAM,CAAC;IA2DxB;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC;IAsB5D;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC;IAe9D;;OAEG;IACG,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAgBjE;;OAEG;IACH,OAAO,CAAC,QAAQ;IAkBV,IAAI,CACR,SAAS,EAAE,SAAS,EAAE,EACtB,QAAQ,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,UAAU,CAAC;IAQhB,QAAQ,CACZ,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,OAAO,CAAC,UAAU,CAAC;IAQhB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAQlE,KAAK,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EACxB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,OAAO,CAAC,iBAAiB,CAAC;IAQvB,UAAU,CACd,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,QAAQ,CAAC,EAAE,qBAAqB,GAC/B,OAAO,CAAC,iBAAiB,CAAC;IAQvB,aAAa,CACjB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,uBAAuB,GACjC,OAAO,CAAC,MAAM,CAAC;IAQZ,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,sBAAsB,GAChC,OAAO,CAAC,uBAAuB,CAAC;IAQ5B,MAAM,CACX,SAAS,EAAE,SAAS,EAAE,EACtB,QAAQ,CAAC,EAAE,WAAW,GACrB,aAAa,CAAC,MAAM,CAAC;IAQlB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ3C,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAuB/B,eAAe,IAAI,OAAO,CAAC,cAAc,CAAC;CAwBjD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseAIOptions, TokenUsage, UsageEvent } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Emit a usage event to the `onUsage` callback configured on provider options.
|
|
4
|
+
*
|
|
5
|
+
* @param providerOptions - The provider's stored options (for `onUsage` and global `usageTags`).
|
|
6
|
+
* @param providerName - Provider identifier (e.g. `'openai'`).
|
|
7
|
+
* @param operation - The operation type that generated this usage.
|
|
8
|
+
* @param model - Model that was used.
|
|
9
|
+
* @param usage - Token usage breakdown, if available.
|
|
10
|
+
* @param startTime - `Date.now()` captured before the API call.
|
|
11
|
+
* @param callTags - Per-call `usageTags` from the method's options.
|
|
12
|
+
*/
|
|
13
|
+
export declare function emitUsage(providerOptions: BaseAIOptions, providerName: string, operation: UsageEvent['operation'], model: string, usage: TokenUsage | undefined, startTime: number, callTags?: Record<string, string>): void;
|
|
14
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/shared/providers/usage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,eAAe,EAAE,aAAa,EAC9B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,EAClC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,GAAG,SAAS,EAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,IAAI,CAoBN"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AIClientOptions } from './client';
|
|
2
|
+
import { AIInterface, GetAIOptions, AIError } from './types';
|
|
3
|
+
export declare function parseRetryAfterSeconds(retryAfter: number | string | null | undefined): number | undefined;
|
|
4
|
+
export declare function extractRetryAfterSeconds(error: unknown): number | undefined;
|
|
5
|
+
export declare function createRateLimitedAI<T extends AIInterface>(client: T, options: GetAIOptions | AIClientOptions): T;
|
|
6
|
+
export declare function __resetAIRateLimitStateForTests(): void;
|
|
7
|
+
export declare function __getAIRateLimitStateForTests(): {
|
|
8
|
+
count: number;
|
|
9
|
+
maxBudgetCoordinators: number;
|
|
10
|
+
ttlMs: number;
|
|
11
|
+
};
|
|
12
|
+
export declare function isRetryableAIError(error: unknown): error is AIError;
|
|
13
|
+
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/shared/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAsB,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAkB,MAAM,SAAS,CAAC;AAiQlD,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAC7C,MAAM,GAAG,SAAS,CAyBpB;AAkBD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAmC3E;AAED,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,WAAW,EACvD,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,YAAY,GAAG,eAAe,GACtC,CAAC,CAwCH;AAED,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD;AAED,wBAAgB,6BAA6B,IAAI;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf,CAMA;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAEnE"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { default as OpenAI } from 'openai';
|
|
2
|
+
import { AIClient, AIClientOptions } from './client';
|
|
3
|
+
import { AIMessage } from './message';
|
|
4
|
+
/**
|
|
5
|
+
* Options for creating an AI conversation thread
|
|
6
|
+
*/
|
|
7
|
+
export interface AIThreadOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Options for the AI client to use in this thread
|
|
10
|
+
*/
|
|
11
|
+
ai: AIClientOptions;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Represents a conversation thread with an AI model
|
|
15
|
+
* Manages messages, references, and conversation state
|
|
16
|
+
*/
|
|
17
|
+
export declare class AIThread {
|
|
18
|
+
/**
|
|
19
|
+
* AI client instance for this thread
|
|
20
|
+
*/
|
|
21
|
+
protected ai: AIClient;
|
|
22
|
+
/**
|
|
23
|
+
* Options used to configure this thread
|
|
24
|
+
*/
|
|
25
|
+
protected options: AIThreadOptions;
|
|
26
|
+
/**
|
|
27
|
+
* Messages in this conversation thread
|
|
28
|
+
*/
|
|
29
|
+
private messages;
|
|
30
|
+
/**
|
|
31
|
+
* Reference materials to include in the conversation context
|
|
32
|
+
*/
|
|
33
|
+
private references;
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new AI thread
|
|
36
|
+
*
|
|
37
|
+
* @param options - Thread configuration options
|
|
38
|
+
*/
|
|
39
|
+
constructor(options: AIThreadOptions);
|
|
40
|
+
/**
|
|
41
|
+
* Factory method to create and initialize a new AI thread
|
|
42
|
+
*
|
|
43
|
+
* @param options - Thread configuration options
|
|
44
|
+
* @returns Promise resolving to an initialized AIThread
|
|
45
|
+
*/
|
|
46
|
+
static create(options: AIThreadOptions): Promise<AIThread>;
|
|
47
|
+
/**
|
|
48
|
+
* Initializes the AI client for this thread
|
|
49
|
+
*/
|
|
50
|
+
initialize(): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Adds a system message to the conversation
|
|
53
|
+
*
|
|
54
|
+
* @param prompt - System message content
|
|
55
|
+
* @returns Promise resolving to the created AIMessage
|
|
56
|
+
*/
|
|
57
|
+
addSystem(prompt: string): Promise<AIMessage>;
|
|
58
|
+
/**
|
|
59
|
+
* Adds a message to the conversation
|
|
60
|
+
*
|
|
61
|
+
* @param options - Message options
|
|
62
|
+
* @param options.role - Role of the message sender
|
|
63
|
+
* @param options.name - Optional name of the message sender
|
|
64
|
+
* @param options.content - Content of the message
|
|
65
|
+
* @returns Promise resolving to the created AIMessage
|
|
66
|
+
*/
|
|
67
|
+
add(options: {
|
|
68
|
+
role: 'user' | 'assistant' | 'system';
|
|
69
|
+
name?: string;
|
|
70
|
+
content: string;
|
|
71
|
+
}): Promise<AIMessage>;
|
|
72
|
+
/**
|
|
73
|
+
* Gets all messages in this thread
|
|
74
|
+
*
|
|
75
|
+
* @returns Array of AIMessage objects
|
|
76
|
+
*/
|
|
77
|
+
get(): AIMessage[];
|
|
78
|
+
/**
|
|
79
|
+
* Adds a reference to be included in the conversation context
|
|
80
|
+
*
|
|
81
|
+
* @param name - Name of the reference
|
|
82
|
+
* @param body - Content of the reference
|
|
83
|
+
*/
|
|
84
|
+
addReference(name: string, body: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Assembles the conversation history for sending to the AI
|
|
87
|
+
* Properly orders system message, references, and conversation messages
|
|
88
|
+
*
|
|
89
|
+
* @returns Array of message parameters formatted for the OpenAI API
|
|
90
|
+
*/
|
|
91
|
+
assembleHistory(): OpenAI.Chat.ChatCompletionMessageParam[];
|
|
92
|
+
/**
|
|
93
|
+
* Sends a prompt to the AI and gets a response
|
|
94
|
+
*
|
|
95
|
+
* @param prompt - Prompt message to send
|
|
96
|
+
* @param options - Options for the AI response
|
|
97
|
+
* @param options.responseFormat - Format for the AI to respond with
|
|
98
|
+
* @returns Promise resolving to the AI response
|
|
99
|
+
*/
|
|
100
|
+
do(prompt: string, options?: {
|
|
101
|
+
responseFormat?: 'html' | 'text' | 'json';
|
|
102
|
+
}): Promise<string>;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=thread.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread.d.ts","sourceRoot":"","sources":["../../src/shared/thread.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,EAAE,EAAE,eAAe,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,QAAQ;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,EAAG,QAAQ,CAAC;IAExB;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,eAAe,CAAC;IAEnC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAmB;IAEnC;;OAEG;IACH,OAAO,CAAC,UAAU,CAAkC;IAEpD;;;;OAIG;gBACS,OAAO,EAAE,eAAe;IAIpC;;;;;OAKG;WACU,MAAM,CAAC,OAAO,EAAE,eAAe;IAM5C;;OAEG;IACU,UAAU;IAIvB;;;;;OAKG;IACU,SAAS,CAAC,MAAM,EAAE,MAAM;IAYrC;;;;;;;;OAQG;IACU,GAAG,CAAC,OAAO,EAAE;QACxB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;QACtC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;KACjB;IAYD;;;;OAIG;IACI,GAAG,IAAI,SAAS,EAAE;IAIzB;;;;;OAKG;IACI,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIrD;;;;;OAKG;IACI,eAAe,IAAI,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;IA8BlE;;;;;;;OAOG;IACU,EAAE,CACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;QACP,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;KAG3C;CAcJ"}
|