utilitas 1998.2.64 → 1998.2.66
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/README.md +14 -14
- package/dist/utilitas.lite.mjs +1 -1
- package/dist/utilitas.lite.mjs.map +1 -1
- package/lib/alan.mjs +178 -241
- package/lib/manifest.mjs +1 -1
- package/package.json +1 -1
package/lib/alan.mjs
CHANGED
|
@@ -46,32 +46,31 @@ const _NEED = [
|
|
|
46
46
|
];
|
|
47
47
|
|
|
48
48
|
const [
|
|
49
|
-
OPENAI, GEMINI,
|
|
50
|
-
OLLAMA,
|
|
49
|
+
OPENAI, GEMINI, OPENAI_EMBEDDING, GEMINI_EMEDDING, OPENAI_TRAINING,
|
|
50
|
+
OLLAMA, GPT_4O_MINI, GPT_4O, GPT_O1, GPT_O3_MINI, GEMINI_20_FLASH,
|
|
51
51
|
GEMINI_20_FLASH_THINKING, GEMINI_20_PRO, NOVA, EMBEDDING_001, DEEPSEEK_R1,
|
|
52
|
-
DEEPSEEK_R1_70B, DEEPSEEK_R1_32B, MD_CODE,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
DEEPSEEK_R1_70B, DEEPSEEK_R1_32B, MD_CODE, TEXT_EMBEDDING_3_SMALL,
|
|
53
|
+
TEXT_EMBEDDING_3_LARGE, CLOUD_37_SONNET, AUDIO, WAV, ATTACHMENTS, CHAT,
|
|
54
|
+
OPENAI_VOICE, MEDIUM, LOW, HIGH, GPT_REASONING_EFFORT, THINK, THINK_STR,
|
|
55
|
+
THINK_END, AZURE, TOOLS_STR, TOOLS_END, TOOLS, TEXT, THINKING, OK, FUNC,
|
|
56
|
+
GPT_45, REDACTED_THINKING, GEMMA_3_27B, AZURE_OPENAI, ANTHROPIC,
|
|
57
|
+
VERTEX_ANTHROPIC, GEMMA327B, size8k, ais, MAX_TOOL_RECURSION, LOG, name,
|
|
58
|
+
user, system, assistant, MODEL, JSON_OBJECT, TOOL, silent, NOT_INIT,
|
|
59
|
+
INVALID_FILE, tokenSafeRatio, GPT_QUERY_LIMIT, minsOfDay,
|
|
60
|
+
CONTENT_IS_REQUIRED,
|
|
61
61
|
] = [
|
|
62
|
-
'
|
|
63
|
-
'OPENAI_TRAINING', '
|
|
64
|
-
'
|
|
62
|
+
'OpenAI', 'Gemini', 'OPENAI_EMBEDDING', 'GEMINI_EMEDDING',
|
|
63
|
+
'OPENAI_TRAINING', 'Ollama', 'gpt-4o-mini', 'gpt-4o', 'o1', 'o3-mini',
|
|
64
|
+
'gemini-2.0-flash', 'gemini-2.0-flash-thinking-exp',
|
|
65
65
|
'gemini-2.0-pro-exp', 'nova', 'embedding-001', 'deepseek-r1',
|
|
66
|
-
'deepseek-r1:70b', 'deepseek-r1:32b', '```', '
|
|
67
|
-
'text-embedding-3-
|
|
68
|
-
'claude-3-7-sonnet@20250219', 'audio', 'wav', 'CHATGPT_MINI',
|
|
66
|
+
'deepseek-r1:70b', 'deepseek-r1:32b', '```', 'text-embedding-3-small',
|
|
67
|
+
'text-embedding-3-large', 'claude-3-7-sonnet@20250219', 'audio', 'wav',
|
|
69
68
|
'[ATTACHMENTS]', 'CHAT', 'OPENAI_VOICE', 'medium', 'low', 'high',
|
|
70
69
|
'medium', 'think', '<think>', '</think>', 'AZURE', '<tools>',
|
|
71
70
|
'</tools>', 'tools', 'text', 'thinking', 'OK', 'function',
|
|
72
71
|
'gpt-4.5-preview', 'redacted_thinking', 'gemma-3-27b-it',
|
|
73
72
|
'AZURE OPENAI', 'ANTHROPIC', 'VERTEX ANTHROPIC', 'gemma3:27b',
|
|
74
|
-
7680 * 4320,
|
|
73
|
+
7680 * 4320, [], 10, { log: true }, 'Alan', 'user', 'system',
|
|
75
74
|
'assistant', 'model', 'json_object', 'tool', true,
|
|
76
75
|
'AI engine has not been initialized.', 'Invalid file data.', 1.1, 100,
|
|
77
76
|
60 * 24, 'Content is required.',
|
|
@@ -90,23 +89,16 @@ const [
|
|
|
90
89
|
'text/plain', 'audio/x-wav', 'audio/ogg',
|
|
91
90
|
];
|
|
92
91
|
|
|
93
|
-
const [tool,
|
|
94
|
-
type => ({ type }),
|
|
95
|
-
messages => ({ messages }), text => ({ text }),
|
|
96
|
-
];
|
|
97
|
-
|
|
92
|
+
const [tool, messages, text]
|
|
93
|
+
= [type => ({ type }), messages => ({ messages }), text => ({ text })];
|
|
98
94
|
const [CODE_INTERPRETER, RETRIEVAL, FUNCTION]
|
|
99
95
|
= ['code_interpreter', 'retrieval', FUNC].map(tool);
|
|
100
|
-
const chatConfig
|
|
101
|
-
= { sessions: new Map(), engines: {}, systemPrompt: INSTRUCTIONS };
|
|
102
96
|
const [sessionType, aiType]
|
|
103
97
|
= [`${name.toUpperCase()}-SESSION`, `${name.toUpperCase()}-AI`];
|
|
104
98
|
const [newSessionId, newAiId]
|
|
105
99
|
= [sessionType, aiType].map(type => () => createUoid({ type }));
|
|
100
|
+
const chatConfig = { sessions: new Map(), systemPrompt: INSTRUCTIONS };
|
|
106
101
|
const tokenSafe = count => Math.ceil(count * tokenSafeRatio);
|
|
107
|
-
const clients = {};
|
|
108
|
-
const unifyProvider = options => unifyType(options?.provider, 'AI provider');
|
|
109
|
-
const unifyEngine = options => unifyType(options?.engine, 'AI engine');
|
|
110
102
|
const trimTailing = text => text.replace(/[\.\s]*$/, '');
|
|
111
103
|
const renderText = (t, o) => _renderText(t, { extraCodeBlock: 0, ...o || {} });
|
|
112
104
|
const log = (cnt, opt) => _log(cnt, import.meta.url, { time: 1, ...opt || {} });
|
|
@@ -128,18 +120,8 @@ const DEFAULT_MODELS = {
|
|
|
128
120
|
[OPENAI_EMBEDDING]: TEXT_EMBEDDING_3_SMALL,
|
|
129
121
|
[GEMINI_EMEDDING]: EMBEDDING_001,
|
|
130
122
|
[OPENAI_TRAINING]: GPT_4O_MINI, // https://platform.openai.com/docs/guides/fine-tuning
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
[CHATGPT_MINI]: GPT_4O_MINI,
|
|
134
|
-
[CHATGPT_REASONING]: GPT_O3_MINI,
|
|
135
123
|
};
|
|
136
124
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
125
|
DEFAULT_MODELS[CHAT] = DEFAULT_MODELS[GEMINI];
|
|
144
126
|
|
|
145
127
|
const tokenRatioByWords = Math.min(
|
|
@@ -164,17 +146,14 @@ const MODELS = {
|
|
|
164
146
|
requestLimitsRPM: 10000,
|
|
165
147
|
tokenLimitsTPD: 1000000000,
|
|
166
148
|
tokenLimitsTPM: 10000000,
|
|
167
|
-
|
|
149
|
+
audio: 'gpt-4o-mini-audio-preview',
|
|
150
|
+
fast: true,
|
|
168
151
|
json: true,
|
|
169
|
-
vision: true,
|
|
170
152
|
tools: true,
|
|
171
|
-
|
|
172
|
-
supportedMimeTypes: [
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
supportedAudioTypes: [
|
|
176
|
-
wav,
|
|
177
|
-
],
|
|
153
|
+
vision: true,
|
|
154
|
+
supportedMimeTypes: [png, jpeg, gif, webp],
|
|
155
|
+
supportedAudioTypes: [wav],
|
|
156
|
+
trainingData: 'Oct 2023',
|
|
178
157
|
},
|
|
179
158
|
[GPT_4O]: {
|
|
180
159
|
contextWindow: 128000,
|
|
@@ -183,17 +162,13 @@ const MODELS = {
|
|
|
183
162
|
requestLimitsRPM: 10000,
|
|
184
163
|
tokenLimitsTPD: 20000000,
|
|
185
164
|
tokenLimitsTPM: 2000000,
|
|
186
|
-
|
|
165
|
+
audio: 'gpt-4o-audio-preview',
|
|
187
166
|
json: true,
|
|
188
|
-
vision: true,
|
|
189
167
|
tools: true,
|
|
190
|
-
|
|
191
|
-
supportedMimeTypes: [
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
supportedAudioTypes: [
|
|
195
|
-
wav,
|
|
196
|
-
],
|
|
168
|
+
vision: true,
|
|
169
|
+
supportedMimeTypes: [png, jpeg, gif, webp],
|
|
170
|
+
supportedAudioTypes: [wav],
|
|
171
|
+
trainingData: 'Oct 2023',
|
|
197
172
|
},
|
|
198
173
|
[GPT_O1]: {
|
|
199
174
|
contextWindow: 200000,
|
|
@@ -202,14 +177,14 @@ const MODELS = {
|
|
|
202
177
|
requestLimitsRPM: 10000,
|
|
203
178
|
tokenLimitsTPD: 200000000,
|
|
204
179
|
tokenLimitsTPM: 2000000,
|
|
205
|
-
trainingData: 'Oct 2023',
|
|
206
180
|
json: true,
|
|
207
181
|
reasoning: true,
|
|
208
|
-
vision: true,
|
|
209
182
|
tools: true,
|
|
183
|
+
vision: true,
|
|
210
184
|
supportedMimeTypes: [
|
|
211
185
|
png, jpeg, gif, webp,
|
|
212
186
|
],
|
|
187
|
+
trainingData: 'Oct 2023',
|
|
213
188
|
},
|
|
214
189
|
[GPT_O3_MINI]: {
|
|
215
190
|
contextWindow: 200000,
|
|
@@ -218,14 +193,13 @@ const MODELS = {
|
|
|
218
193
|
requestLimitsRPM: 10000,
|
|
219
194
|
tokenLimitsTPD: 1000000000,
|
|
220
195
|
tokenLimitsTPM: 10000000,
|
|
221
|
-
|
|
196
|
+
fast: true,
|
|
222
197
|
json: true,
|
|
223
198
|
reasoning: true,
|
|
224
|
-
vision: true,
|
|
225
199
|
tools: true,
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
200
|
+
vision: true,
|
|
201
|
+
supportedMimeTypes: [png, jpeg, gif, webp],
|
|
202
|
+
trainingData: 'Oct 2023',
|
|
229
203
|
},
|
|
230
204
|
[GPT_45]: {
|
|
231
205
|
contextWindow: 128000,
|
|
@@ -235,20 +209,18 @@ const MODELS = {
|
|
|
235
209
|
tokenLimitsTPD: 100000000,
|
|
236
210
|
tokenLimitsTPM: 1000000,
|
|
237
211
|
json: true,
|
|
238
|
-
vision: true,
|
|
239
212
|
tools: true,
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
],
|
|
213
|
+
vision: true,
|
|
214
|
+
supportedMimeTypes: [png, jpeg, gif, webp],
|
|
243
215
|
trainingData: 'Oct 2023',
|
|
244
216
|
},
|
|
245
217
|
[GEMINI_20_FLASH]: {
|
|
246
218
|
// https://ai.google.dev/gemini-api/docs/models/gemini
|
|
247
219
|
// https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/send-multimodal-prompts?hl=en#gemini-send-multimodal-samples-pdf-nodejs
|
|
248
220
|
// Audio / Video Comming Soon: https://ai.google.dev/gemini-api/docs/models/gemini#gemini-2.0-flash
|
|
221
|
+
audioCostTokens: 1000000, // 8.4 hours => 1 million tokens
|
|
249
222
|
contextWindow: 1048576,
|
|
250
223
|
imageCostTokens: size8k / (768 * 768) * 258,
|
|
251
|
-
audioCostTokens: 1000000, // 8.4 hours => 1 million tokens
|
|
252
224
|
maxAudioLength: 60 * 60 * 8.4, // 9.5 hours
|
|
253
225
|
maxAudioPerPrompt: 1,
|
|
254
226
|
maxFileSize: 20 * 1024 * 1024, // 20 MB
|
|
@@ -260,17 +232,18 @@ const MODELS = {
|
|
|
260
232
|
maxVideoLengthWithAudio: 60 * 50, // 50 minutes
|
|
261
233
|
maxVideoLengthWithoutAudio: 60 * 60, // 1 hour
|
|
262
234
|
maxVideoPerPrompt: 10,
|
|
263
|
-
requestLimitsRPM: 2000,
|
|
264
235
|
requestLimitsRPD: 1500,
|
|
236
|
+
requestLimitsRPM: 2000,
|
|
265
237
|
tokenLimitsTPM: 4 * 1000000,
|
|
266
|
-
|
|
267
|
-
vision: true,
|
|
238
|
+
fast: true,
|
|
268
239
|
json: true,
|
|
269
240
|
tools: true,
|
|
241
|
+
vision: true,
|
|
270
242
|
supportedMimeTypes: [
|
|
271
243
|
png, jpeg, mov, mpeg, mp4, mpg, avi, wmv, mpegps, flv, pdf, aac,
|
|
272
244
|
flac, mp3, m4a, mpga, opus, pcm, wav, webm, tgpp,
|
|
273
245
|
],
|
|
246
|
+
trainingData: 'August 2024',
|
|
274
247
|
},
|
|
275
248
|
[GEMINI_20_FLASH_THINKING]: {
|
|
276
249
|
// https://cloud.google.com/vertex-ai/generative-ai/docs/thinking-mode?hl=en
|
|
@@ -284,12 +257,10 @@ const MODELS = {
|
|
|
284
257
|
requestLimitsRPM: 1000,
|
|
285
258
|
requestLimitsRPD: 1500,
|
|
286
259
|
tokenLimitsTPM: 4 * 1000000,
|
|
287
|
-
trainingData: 'August 2024',
|
|
288
|
-
vision: true,
|
|
289
260
|
reasoning: true,
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
261
|
+
vision: true,
|
|
262
|
+
supportedMimeTypes: [png, jpeg],
|
|
263
|
+
trainingData: 'August 2024',
|
|
293
264
|
},
|
|
294
265
|
[GEMINI_20_PRO]: {
|
|
295
266
|
contextWindow: 2097152,
|
|
@@ -302,21 +273,22 @@ const MODELS = {
|
|
|
302
273
|
requestLimitsRPM: 1000,
|
|
303
274
|
requestLimitsRPD: 1500,
|
|
304
275
|
tokenLimitsTPM: 4 * 1000000,
|
|
305
|
-
trainingData: 'August 2024',
|
|
306
|
-
vision: true,
|
|
307
276
|
json: true,
|
|
277
|
+
vision: true,
|
|
308
278
|
supportedMimeTypes: [
|
|
309
279
|
png, jpeg, mov, mpeg, mp4, mpg, avi, wmv, mpegps, flv, pdf, aac,
|
|
310
280
|
flac, mp3, m4a, mpga, opus, pcm, wav, webm, tgpp,
|
|
311
281
|
],
|
|
282
|
+
trainingData: 'August 2024',
|
|
312
283
|
},
|
|
313
284
|
[GEMMA_3_27B]: {
|
|
314
285
|
contextWindow: 128 * 1000,
|
|
315
286
|
imageCostTokens: 256,
|
|
316
287
|
maxImageSize: 896 * 896,
|
|
317
288
|
maxOutputTokens: 1024 * 8,
|
|
318
|
-
|
|
289
|
+
fast: true,
|
|
319
290
|
json: true,
|
|
291
|
+
vision: true,
|
|
320
292
|
supportedMimeTypes: [png, jpeg],
|
|
321
293
|
},
|
|
322
294
|
[DEEPSEEK_R1]: {
|
|
@@ -360,12 +332,12 @@ const MODELS = {
|
|
|
360
332
|
requestLimitsRPM: 50,
|
|
361
333
|
tokenLimitsITPM: 40000,
|
|
362
334
|
tokenLimitsOTPM: 8000,
|
|
363
|
-
|
|
335
|
+
json: true,
|
|
364
336
|
reasoning: true,
|
|
365
337
|
tools: true,
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
338
|
+
vision: true,
|
|
339
|
+
supportedMimeTypes: [png, jpeg, gif, webp, pdf],
|
|
340
|
+
trainingData: 'Apr 2024',
|
|
369
341
|
},
|
|
370
342
|
};
|
|
371
343
|
|
|
@@ -401,10 +373,13 @@ const MAX_TRIM_TRY = MAX_INPUT_TOKENS / 1000;
|
|
|
401
373
|
|
|
402
374
|
let tokeniser;
|
|
403
375
|
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
376
|
+
const unifyProvider = provider => {
|
|
377
|
+
assert(provider = (provider || '').trim(), 'AI provider is required.');
|
|
378
|
+
for (let type of [OPENAI, AZURE_OPENAI, AZURE, GEMINI, ANTHROPIC,
|
|
379
|
+
VERTEX_ANTHROPIC, OLLAMA]) {
|
|
380
|
+
if (insensitiveCompare(provider, type)) { return type; }
|
|
381
|
+
}
|
|
382
|
+
throwError(`Invalid AI provider: ${provider}.`);
|
|
408
383
|
};
|
|
409
384
|
|
|
410
385
|
const tools = [
|
|
@@ -502,8 +477,8 @@ const toolsGemini = async () => (await toolsOpenAI()).map(x => ({
|
|
|
502
477
|
}));
|
|
503
478
|
|
|
504
479
|
const init = async (options = {}) => {
|
|
505
|
-
const id = newAiId();
|
|
506
|
-
const provider = unifyProvider(options);
|
|
480
|
+
const id = options.id || newAiId();
|
|
481
|
+
const provider = unifyProvider(options?.provider);
|
|
507
482
|
const modelName = options.model || DEFAULT_MODELS[provider];
|
|
508
483
|
assert(modelName, `Model is required for provider: ${provider}.`);
|
|
509
484
|
let model = options.modelConfig || MODELS[modelName];
|
|
@@ -512,49 +487,49 @@ const init = async (options = {}) => {
|
|
|
512
487
|
switch (provider) {
|
|
513
488
|
case OPENAI:
|
|
514
489
|
assertApiKey(provider, options);
|
|
515
|
-
ais
|
|
490
|
+
ais.push({
|
|
516
491
|
id, provider, model, client: await OpenAI(options),
|
|
517
492
|
prompt: async (cnt, opts) => await promptOpenAI(id, cnt, opts),
|
|
518
493
|
embedding: async (i, o) => await createOpenAIEmbedding(id, i, o),
|
|
519
|
-
};
|
|
494
|
+
});
|
|
520
495
|
break;
|
|
521
496
|
case AZURE_OPENAI:
|
|
522
497
|
assertApiKey(provider, options);
|
|
523
498
|
assert(options.endpoint,
|
|
524
|
-
|
|
525
|
-
ais
|
|
499
|
+
`${provider} api endpoint and deployment are required.`);
|
|
500
|
+
ais.push({
|
|
526
501
|
id, provider, model, client: await AzureOpenAI({
|
|
527
502
|
apiVersion: '2025-01-01-preview',
|
|
528
503
|
deployment: model.name, ...options,
|
|
529
504
|
}),
|
|
530
505
|
prompt: async (cnt, opts) => await promptOpenAI(id, cnt, opts),
|
|
531
|
-
};
|
|
506
|
+
});
|
|
532
507
|
break;
|
|
533
508
|
case AZURE:
|
|
534
509
|
assertApiKey(provider, options);
|
|
535
510
|
assert(options.baseURL, `${provider} api endpoint is required.`);
|
|
536
|
-
ais
|
|
511
|
+
ais.push({
|
|
537
512
|
id, provider, model, client: await OpenAI(options),
|
|
538
513
|
prompt: async (cnt, opts) => await promptOpenAI(id, cnt, opts),
|
|
539
|
-
};
|
|
514
|
+
});
|
|
540
515
|
break;
|
|
541
516
|
case GEMINI:
|
|
542
517
|
assertApiKey(provider, options);
|
|
543
518
|
const { GoogleGenerativeAI } = await need('@google/generative-ai');
|
|
544
|
-
ais
|
|
519
|
+
ais.push({
|
|
545
520
|
id, provider, model,
|
|
546
521
|
client: new GoogleGenerativeAI(options.apiKey),
|
|
547
522
|
prompt: async (cnt, opts) => await promptGemini(id, cnt, opts),
|
|
548
523
|
embedding: async (i, o) => await createGeminiEmbedding(id, i, o),
|
|
549
|
-
};
|
|
524
|
+
});
|
|
550
525
|
break;
|
|
551
526
|
case ANTHROPIC:
|
|
552
527
|
assertApiKey(provider, options);
|
|
553
528
|
const Anthropic = (await need('@anthropic-ai/sdk')).Anthropic;
|
|
554
|
-
ais
|
|
529
|
+
ais.push({
|
|
555
530
|
id, provider, model, client: new Anthropic(options),
|
|
556
531
|
prompt: async (cnt, opts) => await promptAnthropic(id, cnt, opts),
|
|
557
|
-
};
|
|
532
|
+
});
|
|
558
533
|
break;
|
|
559
534
|
case VERTEX_ANTHROPIC:
|
|
560
535
|
// https://github.com/anthropics/anthropic-sdk-typescript/tree/main/packages/vertex-sdk
|
|
@@ -562,21 +537,21 @@ const init = async (options = {}) => {
|
|
|
562
537
|
const AnthropicVertex = (await need('@anthropic-ai/vertex-sdk')).AnthropicVertex;
|
|
563
538
|
process.env['GOOGLE_APPLICATION_CREDENTIALS'] = options.credentials;
|
|
564
539
|
process.env['ANTHROPIC_VERTEX_PROJECT_ID'] = options.projectId;
|
|
565
|
-
ais
|
|
540
|
+
ais.push({
|
|
566
541
|
id, provider, model,
|
|
567
542
|
client: new AnthropicVertex({ region: options?.region || 'us-east5' }),
|
|
568
543
|
prompt: async (cnt, opts) => await promptAnthropic(id, cnt, opts),
|
|
569
|
-
};
|
|
544
|
+
});
|
|
570
545
|
break;
|
|
571
546
|
case OLLAMA:
|
|
572
547
|
// https://github.com/ollama/ollama/blob/main/docs/openai.md
|
|
573
548
|
const baseURL = 'http://localhost:11434/v1/';
|
|
574
|
-
ais
|
|
549
|
+
ais.push({
|
|
575
550
|
id, provider, model, client: await OpenAI({
|
|
576
551
|
baseURL, apiKey: 'ollama', ...options
|
|
577
552
|
}),
|
|
578
553
|
prompt: async (cnt, opts) => await promptOpenAI(id, cnt, opts),
|
|
579
|
-
};
|
|
554
|
+
});
|
|
580
555
|
const phLog = m => log(`Ollama preheat: ${m?.message || m}`);
|
|
581
556
|
ignoreErrFunc(async () => {
|
|
582
557
|
phLog(await (await fetch(`${baseURL}completions`, {
|
|
@@ -589,15 +564,32 @@ const init = async (options = {}) => {
|
|
|
589
564
|
default:
|
|
590
565
|
throwError(`Invalid AI provider: ${options.provider || 'null'}.`);
|
|
591
566
|
}
|
|
592
|
-
return ais
|
|
567
|
+
return ais.find(x => x.id === id);
|
|
593
568
|
};
|
|
594
569
|
|
|
595
|
-
const getAi = async (id, options) => {
|
|
570
|
+
const getAi = async (id, options = {}) => {
|
|
596
571
|
if (id) {
|
|
597
|
-
|
|
598
|
-
|
|
572
|
+
const ai = ais.find(x => x.id === id);
|
|
573
|
+
assert(ais, `AI not found: ${id}.`);
|
|
574
|
+
return options?.client ? ai?.client : ai;
|
|
575
|
+
} else if (options?.select) {
|
|
576
|
+
const res = [];
|
|
577
|
+
for (let x of ais) {
|
|
578
|
+
let select = true;
|
|
579
|
+
for (let i in options.select) {
|
|
580
|
+
if (options.select[i] && i !== 'fast' && !x.model[i]) {
|
|
581
|
+
select = false; break;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
select && (res.push(x));
|
|
585
|
+
}
|
|
586
|
+
const best = options.select?.fast ? res.filter(x => x.model.fast) : res;
|
|
587
|
+
if (best.length) { return options.all ? best : best[0]; }
|
|
588
|
+
assert(res.length, 'AI not found.');
|
|
589
|
+
log(`Best match AI not found, fallbacked: ${JSON.stringify(options.select)}.`);
|
|
590
|
+
return options.all ? res : res[0];
|
|
599
591
|
}
|
|
600
|
-
return ais;
|
|
592
|
+
return options.all ? ais : ais[0];
|
|
601
593
|
};
|
|
602
594
|
|
|
603
595
|
const countTokens = async (input, options) => {
|
|
@@ -702,12 +694,8 @@ const buildGeminiHistory = (text, options) => buildGeminiMessage(
|
|
|
702
694
|
text, { ...options || {}, history: true }
|
|
703
695
|
);
|
|
704
696
|
|
|
705
|
-
const
|
|
706
|
-
|
|
707
|
-
);
|
|
708
|
-
|
|
709
|
-
const listOpenAIModels = async (options) => {
|
|
710
|
-
const { client } = await getOpenAIClient(options);
|
|
697
|
+
const listOpenAIModels = async (aiId, options) => {
|
|
698
|
+
const { client } = await getAi(aiId);
|
|
711
699
|
const resp = await client.models.list();
|
|
712
700
|
return options?.raw ? resp : resp.data;
|
|
713
701
|
};
|
|
@@ -826,11 +814,11 @@ const buildPrompts = async (model, input, options = {}) => {
|
|
|
826
814
|
...model?.supportedMimeTypes || [], ...model.supportedAudioTypes || []
|
|
827
815
|
].includes(x.mime_type));
|
|
828
816
|
switch (options.flavor) {
|
|
829
|
-
case
|
|
817
|
+
case OPENAI:
|
|
830
818
|
systemPrompt = buildGptMessage(options.systemPrompt, _system);
|
|
831
819
|
prompt = buildGptMessage(content, options);
|
|
832
820
|
break;
|
|
833
|
-
case
|
|
821
|
+
case ANTHROPIC:
|
|
834
822
|
systemPrompt = options.systemPrompt;
|
|
835
823
|
prompt = buildClaudeMessage(content, { ...options, cache_control: true });
|
|
836
824
|
break;
|
|
@@ -845,11 +833,11 @@ const buildPrompts = async (model, input, options = {}) => {
|
|
|
845
833
|
history = [];
|
|
846
834
|
(options.messages?.length ? options.messages : []).map((x, i) => {
|
|
847
835
|
switch (options.flavor) {
|
|
848
|
-
case
|
|
836
|
+
case OPENAI:
|
|
849
837
|
history.push(buildGptMessage(x.request, _user));
|
|
850
838
|
history.push(buildGptMessage(x.response, _assistant));
|
|
851
839
|
break;
|
|
852
|
-
case
|
|
840
|
+
case ANTHROPIC:
|
|
853
841
|
history.push(buildClaudeMessage(x.request, _user));
|
|
854
842
|
history.push(buildClaudeMessage(x.response, _assistant));
|
|
855
843
|
break;
|
|
@@ -861,13 +849,13 @@ const buildPrompts = async (model, input, options = {}) => {
|
|
|
861
849
|
}
|
|
862
850
|
});
|
|
863
851
|
switch (options.flavor) {
|
|
864
|
-
case
|
|
852
|
+
case OPENAI:
|
|
865
853
|
history = messages([
|
|
866
854
|
systemPrompt, ...history, prompt,
|
|
867
855
|
...options.toolsResult?.length ? options.toolsResult : []
|
|
868
856
|
]);
|
|
869
857
|
break;
|
|
870
|
-
case
|
|
858
|
+
case ANTHROPIC:
|
|
871
859
|
history = messages([
|
|
872
860
|
...history, prompt,
|
|
873
861
|
...options.toolsResult?.length ? options.toolsResult : []
|
|
@@ -893,7 +881,7 @@ const buildPrompts = async (model, input, options = {}) => {
|
|
|
893
881
|
content = trimTailing(trimTailing(content).slice(0, -1)) + '...';
|
|
894
882
|
}
|
|
895
883
|
}, model.maxInputTokens - options.attachments?.length * ATTACHMENT_TOKEN_COST);
|
|
896
|
-
if ([
|
|
884
|
+
if ([OPENAI].includes(options.flavor) || options.model === GEMMA_3_27B) {
|
|
897
885
|
systemPrompt = null;
|
|
898
886
|
}
|
|
899
887
|
return { systemPrompt, history, prompt };
|
|
@@ -914,13 +902,13 @@ const handleToolsCall = async (msg, options) => {
|
|
|
914
902
|
const calls = msg.tool_calls || msg.content || msg.parts || [];
|
|
915
903
|
if (calls.length) {
|
|
916
904
|
switch (options?.flavor) {
|
|
917
|
-
case
|
|
905
|
+
case ANTHROPIC: preRes.push(msg); break;
|
|
918
906
|
case GEMINI: preRes.push(msg); break;
|
|
919
|
-
case
|
|
907
|
+
case OPENAI: default: preRes.push(msg); break;
|
|
920
908
|
}
|
|
921
909
|
for (const fn of calls) {
|
|
922
910
|
switch (options?.flavor) {
|
|
923
|
-
case
|
|
911
|
+
case ANTHROPIC:
|
|
924
912
|
input = fn.input = String.isString(fn?.input)
|
|
925
913
|
? parseJson(fn.input) : fn?.input;
|
|
926
914
|
packMsg = (content, is_error) => ({
|
|
@@ -939,7 +927,7 @@ const handleToolsCall = async (msg, options) => {
|
|
|
939
927
|
}
|
|
940
928
|
});
|
|
941
929
|
break;
|
|
942
|
-
case
|
|
930
|
+
case OPENAI: default:
|
|
943
931
|
input = parseJson(fn?.function?.arguments);
|
|
944
932
|
packMsg = (content = '', e = false) => ({
|
|
945
933
|
role: TOOL, tool_call_id: fn.id,
|
|
@@ -976,7 +964,7 @@ const handleToolsCall = async (msg, options) => {
|
|
|
976
964
|
}
|
|
977
965
|
if (content.length) {
|
|
978
966
|
switch (options?.flavor) {
|
|
979
|
-
case
|
|
967
|
+
case ANTHROPIC: content = [{ role: user, content }]; break;
|
|
980
968
|
case GEMINI: content = [{ role: FUNC, parts: content }]; break;
|
|
981
969
|
}
|
|
982
970
|
}
|
|
@@ -998,7 +986,7 @@ const promptOpenAI = async (aiId, content, options = {}) => {
|
|
|
998
986
|
options.result ?? '', Buffer.alloc(0), null, [], false,
|
|
999
987
|
provider === AZURE
|
|
1000
988
|
];
|
|
1001
|
-
options.flavor =
|
|
989
|
+
options.flavor = OPENAI;
|
|
1002
990
|
options.model = options.model || model.name;
|
|
1003
991
|
const { history }
|
|
1004
992
|
= await buildPrompts(MODELS[options.model], content, options);
|
|
@@ -1077,7 +1065,7 @@ const promptAnthropic = async (aiId, content, options = {}) => {
|
|
|
1077
1065
|
+ '46C9A13E193C177646C7398A98432ECCCE4C1253D5E2D82641AC0E52CC2876CB'
|
|
1078
1066
|
); // https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
|
|
1079
1067
|
const { systemPrompt: system, history }
|
|
1080
|
-
= await buildPrompts(model, content, { ...options, flavor:
|
|
1068
|
+
= await buildPrompts(model, content, { ...options, flavor: ANTHROPIC });
|
|
1081
1069
|
const resp = await client.beta.messages.create({
|
|
1082
1070
|
model: options.model, ...history, system, stream: true,
|
|
1083
1071
|
max_tokens: options.extendedThinking ? 128000 : model.maxOutputTokens,
|
|
@@ -1128,7 +1116,7 @@ const promptAnthropic = async (aiId, content, options = {}) => {
|
|
|
1128
1116
|
]
|
|
1129
1117
|
};
|
|
1130
1118
|
const { toolsResult, toolsResponse } = await handleToolsCall(
|
|
1131
|
-
event, { ...options, result, flavor:
|
|
1119
|
+
event, { ...options, result, flavor: ANTHROPIC },
|
|
1132
1120
|
);
|
|
1133
1121
|
if (tool_use.length && countToolCalls(toolsResponse) < MAX_TOOL_RECURSION) {
|
|
1134
1122
|
return await promptAnthropic(aiId, content, {
|
|
@@ -1139,8 +1127,8 @@ const promptAnthropic = async (aiId, content, options = {}) => {
|
|
|
1139
1127
|
return packResp({ text: mergeMsgs(toolsResponse, tool_use) }, options);
|
|
1140
1128
|
};
|
|
1141
1129
|
|
|
1142
|
-
const uploadFile = async (input, options) => {
|
|
1143
|
-
const { client } = await
|
|
1130
|
+
const uploadFile = async (aiId, input, options) => {
|
|
1131
|
+
const { client } = await getAi(aiId);
|
|
1144
1132
|
const { content: file, cleanup } = await convert(input, {
|
|
1145
1133
|
input: options?.input, ...options || {}, expected: STREAM,
|
|
1146
1134
|
errorMessage: INVALID_FILE, suffix: options?.suffix,
|
|
@@ -1151,20 +1139,20 @@ const uploadFile = async (input, options) => {
|
|
|
1151
1139
|
return resp;
|
|
1152
1140
|
};
|
|
1153
1141
|
|
|
1154
|
-
const uploadFileForFineTuning = async (content, options) => await uploadFile(
|
|
1155
|
-
content, { suffix: 'jsonl', ...options, params: { purpose: 'fine-tune' } }
|
|
1142
|
+
const uploadFileForFineTuning = async (aiId, content, options) => await uploadFile(
|
|
1143
|
+
aiId, content, { suffix: 'jsonl', ...options, params: { purpose: 'fine-tune' } }
|
|
1156
1144
|
);
|
|
1157
1145
|
|
|
1158
|
-
const listFiles = async (options) => {
|
|
1159
|
-
const { client } = await
|
|
1146
|
+
const listFiles = async (aiId, options) => {
|
|
1147
|
+
const { client } = await getAi(aiId);
|
|
1160
1148
|
const files = [];
|
|
1161
1149
|
const list = await client.files.list(options?.params || {});
|
|
1162
1150
|
for await (const file of list) { files.push(file); }
|
|
1163
1151
|
return files;
|
|
1164
1152
|
};
|
|
1165
1153
|
|
|
1166
|
-
const deleteFile = async (file_id, options) => {
|
|
1167
|
-
const { client } = await
|
|
1154
|
+
const deleteFile = async (aiId, file_id, options) => {
|
|
1155
|
+
const { client } = await getAi(aiId);
|
|
1168
1156
|
return await client.files.del(file_id);
|
|
1169
1157
|
};
|
|
1170
1158
|
|
|
@@ -1294,48 +1282,48 @@ const buildGptTrainingCases = (cases, opts) => cases.map(x => JSON.stringify(
|
|
|
1294
1282
|
buildGptTrainingCase(x.prompt, x.response, { ...x.options, ...opts })
|
|
1295
1283
|
)).join('\n');
|
|
1296
1284
|
|
|
1297
|
-
const createGptFineTuningJob = async (training_file, options) => {
|
|
1298
|
-
const { client } = await
|
|
1285
|
+
const createGptFineTuningJob = async (aiId, training_file, options) => {
|
|
1286
|
+
const { client } = await getAi(aiId);
|
|
1299
1287
|
return await client.fineTuning.jobs.create({
|
|
1300
1288
|
training_file, model: options?.model || DEFAULT_MODELS[OPENAI_TRAINING],
|
|
1301
1289
|
})
|
|
1302
1290
|
};
|
|
1303
1291
|
|
|
1304
|
-
const getGptFineTuningJob = async (job_id, options) => {
|
|
1305
|
-
const { client } = await
|
|
1292
|
+
const getGptFineTuningJob = async (aiId, job_id, options) => {
|
|
1293
|
+
const { client } = await getAi(aiId);
|
|
1306
1294
|
// https://platform.openai.com/finetune/[job_id]?filter=all
|
|
1307
1295
|
return await client.fineTuning.jobs.retrieve(job_id);
|
|
1308
1296
|
};
|
|
1309
1297
|
|
|
1310
|
-
const cancelGptFineTuningJob = async (job_id, options) => {
|
|
1311
|
-
const { client } = await
|
|
1298
|
+
const cancelGptFineTuningJob = async (aiId, job_id, options) => {
|
|
1299
|
+
const { client } = await getAi(aiId);
|
|
1312
1300
|
return await client.fineTuning.jobs.cancel(job_id);
|
|
1313
1301
|
};
|
|
1314
1302
|
|
|
1315
|
-
const listGptFineTuningJobs = async (options) => {
|
|
1316
|
-
const { client } = await
|
|
1303
|
+
const listGptFineTuningJobs = async (aiId, options) => {
|
|
1304
|
+
const { client } = await getAi(aiId);
|
|
1317
1305
|
const resp = await client.fineTuning.jobs.list({
|
|
1318
1306
|
limit: GPT_QUERY_LIMIT, ...options?.params
|
|
1319
1307
|
});
|
|
1320
1308
|
return options?.raw ? resp : resp.data;
|
|
1321
1309
|
};
|
|
1322
1310
|
|
|
1323
|
-
const listGptFineTuningEvents = async (job_id, options) => {
|
|
1324
|
-
const { client } = await
|
|
1311
|
+
const listGptFineTuningEvents = async (aiId, job_id, options) => {
|
|
1312
|
+
const { client } = await getAi(aiId);
|
|
1325
1313
|
const resp = await client.fineTuning.jobs.listEvents(job_id, {
|
|
1326
1314
|
limit: GPT_QUERY_LIMIT, ...options?.params,
|
|
1327
1315
|
});
|
|
1328
1316
|
return options?.raw ? resp : resp.data;
|
|
1329
1317
|
};
|
|
1330
1318
|
|
|
1331
|
-
const tailGptFineTuningEvents = async (job_id, options) => {
|
|
1319
|
+
const tailGptFineTuningEvents = async (aiId, job_id, options) => {
|
|
1332
1320
|
assert(job_id, 'Job ID is required.');
|
|
1333
|
-
const [loopName, listOpts] = [`GPT
|
|
1321
|
+
const [loopName, listOpts] = [`GPT-${job_id}`, {
|
|
1334
1322
|
...options, params: { ...options?.params, order: 'ascending' }
|
|
1335
1323
|
}];
|
|
1336
1324
|
let lastEvent;
|
|
1337
1325
|
return await loop(async () => {
|
|
1338
|
-
const resp = await listGptFineTuningEvents(job_id, {
|
|
1326
|
+
const resp = await listGptFineTuningEvents(aiId, job_id, {
|
|
1339
1327
|
...listOpts, params: {
|
|
1340
1328
|
...listOpts?.params,
|
|
1341
1329
|
...(lastEvent ? { after: lastEvent.id } : {}),
|
|
@@ -1348,33 +1336,23 @@ const tailGptFineTuningEvents = async (job_id, options) => {
|
|
|
1348
1336
|
}, 3, 2, 1, loopName, { silent, ...options });
|
|
1349
1337
|
};
|
|
1350
1338
|
|
|
1351
|
-
const initChat = async (options) => {
|
|
1352
|
-
options
|
|
1353
|
-
engines: options?.engines || { [DEFAULT_MODELS[CHAT]]: {} },
|
|
1354
|
-
...options || {},
|
|
1355
|
-
};
|
|
1356
|
-
if (options?.sessions) {
|
|
1339
|
+
const initChat = async (options = {}) => {
|
|
1340
|
+
if (options.sessions) {
|
|
1357
1341
|
assert(
|
|
1358
1342
|
options.sessions?.get && options.sessions?.set,
|
|
1359
1343
|
'Invalid session storage provider.'
|
|
1360
1344
|
);
|
|
1361
1345
|
chatConfig.sessions = options.sessions;
|
|
1362
1346
|
}
|
|
1363
|
-
options
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
chatConfig.systemPrompt, { role: system }
|
|
1373
|
-
)]); // Use Gemini instead of ChatGPT because of the longer pack
|
|
1374
|
-
assert(
|
|
1375
|
-
pmptTokens < mxPmpt,
|
|
1376
|
-
`System prompt is too long: ${pmptTokens} / ${mxPmpt} tokens.`
|
|
1377
|
-
);
|
|
1347
|
+
options.instructions && (chatConfig.systemPrompt = options.instructions);
|
|
1348
|
+
// Use Gemini instead of ChatGPT because of the longer package.
|
|
1349
|
+
const [spTokens, ais] = await Promise.all([countTokens([buildGeminiHistory(
|
|
1350
|
+
chatConfig.systemPrompt, { role: system }
|
|
1351
|
+
)]), getAi(null, { all: true })]);
|
|
1352
|
+
for (const ai of ais) {
|
|
1353
|
+
const mxPmpt = ai.model.maxInputTokens / 2;
|
|
1354
|
+
assert(spTokens < mxPmpt,
|
|
1355
|
+
`System prompt is too long: ${spTokens} / ${mxPmpt} tokens.`);
|
|
1378
1356
|
}
|
|
1379
1357
|
return chatConfig;
|
|
1380
1358
|
};
|
|
@@ -1410,53 +1388,30 @@ const resetSession = async (sessionId, options) => {
|
|
|
1410
1388
|
return await setSession(sessionId, session);
|
|
1411
1389
|
};
|
|
1412
1390
|
|
|
1413
|
-
const
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
// log(result);
|
|
1421
|
-
return result;
|
|
1422
|
-
};
|
|
1423
|
-
|
|
1424
|
-
const talk = async (input, options) => {
|
|
1425
|
-
let [engine, chat, resp, sessionId] = [
|
|
1426
|
-
unifyEngine({
|
|
1427
|
-
engine: Object.keys(chatConfig.engines)?.[0] || DEFAULT_MODELS[CHAT],
|
|
1428
|
-
...options,
|
|
1429
|
-
}), { request: input || ATTACHMENTS }, null,
|
|
1430
|
-
options?.sessionId || newSessionId(),
|
|
1431
|
-
];
|
|
1432
|
-
assert(chatConfig.engines[engine], NOT_INIT);
|
|
1433
|
-
const session = await getSession(sessionId, { engine, ...options });
|
|
1434
|
-
log(`Prompt (${engine}): ${JSON.stringify(input)}`);
|
|
1435
|
-
const pmtOptions = {
|
|
1436
|
-
messages: session.messages, model: chatConfig.engines[engine].model,
|
|
1437
|
-
...options,
|
|
1438
|
-
};
|
|
1439
|
-
switch (engine) {
|
|
1440
|
-
case CHATGPT: resp = await promptOpenAI(input, pmtOptions); break;
|
|
1441
|
-
case GEMINI: resp = await promptGemini(input, pmtOptions); break;
|
|
1442
|
-
case CLAUDE: resp = await promptAnthropic(input, pmtOptions); break;
|
|
1443
|
-
// case OLLAMA: resp = await promptOllama(input, pmtOptions); break;
|
|
1444
|
-
case AZURE: resp = await promptAzure(input, pmtOptions); break;
|
|
1445
|
-
default: throwError(`Invalid AI engine: '${engine}'.`);
|
|
1446
|
-
}
|
|
1391
|
+
const talk = async (input, options = {}) => {
|
|
1392
|
+
let [chat, sessionId] =
|
|
1393
|
+
[{ request: input || ATTACHMENTS }, options.sessionId || newSessionId()];
|
|
1394
|
+
const session = await getSession(sessionId, options);
|
|
1395
|
+
const resp = await prompt(input, {
|
|
1396
|
+
messages: session.messages, log: true, ...options,
|
|
1397
|
+
});
|
|
1447
1398
|
chat.response = resp.text;
|
|
1448
1399
|
chat.request && chat.response && session.messages.push(chat);
|
|
1449
1400
|
await setSession(sessionId, session, options);
|
|
1450
|
-
return {
|
|
1401
|
+
return {
|
|
1402
|
+
sessionId, ...resp, spoken: renderText(
|
|
1403
|
+
resp.text, { noCode: true, noLink: true }
|
|
1404
|
+
).replace(/\[\^\d\^\]/ig, ''),
|
|
1405
|
+
};
|
|
1451
1406
|
};
|
|
1452
1407
|
|
|
1453
|
-
const getMaxChatPromptLimit = (options) => {
|
|
1408
|
+
const getMaxChatPromptLimit = async (options) => {
|
|
1454
1409
|
let resp = 0;
|
|
1455
|
-
|
|
1456
|
-
if (options?.
|
|
1457
|
-
const maxInputTokens =
|
|
1410
|
+
(await getAi(null, { all: true })).map(x => {
|
|
1411
|
+
if (options?.aiId && options?.aiId !== x.id) { return; }
|
|
1412
|
+
const maxInputTokens = x.model.maxInputTokens;
|
|
1458
1413
|
resp = resp ? Math.min(resp, maxInputTokens) : maxInputTokens;
|
|
1459
|
-
}
|
|
1414
|
+
});
|
|
1460
1415
|
assert(resp > 0, 'Chat engine has not been initialized.');
|
|
1461
1416
|
return options?.raw ? resp : Math.min(resp, MAX_INPUT_TOKENS);
|
|
1462
1417
|
};
|
|
@@ -1490,28 +1445,17 @@ const distillFile = async (attachments, o) => {
|
|
|
1490
1445
|
attachments = await Promise.all(attachments);
|
|
1491
1446
|
// print(attachments);
|
|
1492
1447
|
return await prompt(strPmt, {
|
|
1493
|
-
|
|
1448
|
+
simple: true, select: { vision: true, fast: true }, ...o, attachments,
|
|
1494
1449
|
});
|
|
1495
1450
|
};
|
|
1496
1451
|
|
|
1497
|
-
const prompt = async (input, options) => {
|
|
1498
|
-
|
|
1499
|
-
const
|
|
1500
|
-
options
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
if (engine.client === OPENAI) {
|
|
1505
|
-
if (options?.fast) {
|
|
1506
|
-
extra.model = DEFAULT_MODELS[CHATGPT_MINI];
|
|
1507
|
-
} else if (options?.reasoning) {
|
|
1508
|
-
extra.model = DEFAULT_MODELS[CHATGPT_REASONING];
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
return await engine.func(input, { ...extra, ...options || {} });
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
throwError('No AI provider is available.');
|
|
1452
|
+
const prompt = async (input, options = {}) => {
|
|
1453
|
+
const ai = await getAi(options?.aiId, options);
|
|
1454
|
+
const tag = `${ai.provider} (${ai.model.name})`;
|
|
1455
|
+
options.log && log(`Prompt ${tag}: ${JSON.stringify(input)}`);
|
|
1456
|
+
const resp = await ai.prompt(input, options);
|
|
1457
|
+
options.log && log(`Response ${tag}: ${JSON.stringify(resp.text)}`);
|
|
1458
|
+
return resp;
|
|
1515
1459
|
};
|
|
1516
1460
|
|
|
1517
1461
|
const trimPrompt = async (getPrompt, trimFunc, contextWindow, options) => {
|
|
@@ -1553,23 +1497,16 @@ const analyzeSessions = async (sessionIds, options) => {
|
|
|
1553
1497
|
x, JSON.stringify(sses[x]).length,
|
|
1554
1498
|
]).sort((x, y) => y[1] - x[1])[0][0]];
|
|
1555
1499
|
}
|
|
1556
|
-
}, getMaxChatPromptLimit(options));
|
|
1500
|
+
}, await getMaxChatPromptLimit(options));
|
|
1557
1501
|
const aiResp = Object.keys(sses) ? (await prompt(getInput(), {
|
|
1558
|
-
jsonMode: true,
|
|
1502
|
+
jsonMode: true, simple: true, select: { json: true, fase: true },
|
|
1503
|
+
...options || {}
|
|
1559
1504
|
})) : {};
|
|
1560
1505
|
assert(aiResp, 'Unable to analyze sessions.');
|
|
1561
1506
|
ids.map(x => resp[x] = aiResp[x] || null);
|
|
1562
1507
|
return Array.isArray(sessionIds) ? resp : resp[sessionIds[0]];
|
|
1563
1508
|
};
|
|
1564
1509
|
|
|
1565
|
-
const PREFERRED_ENGINES = [
|
|
1566
|
-
{ client: OPENAI, func: promptOpenAI, multimodal: 0 },
|
|
1567
|
-
{ client: GEMINI, func: promptGemini, multimodal: 1 },
|
|
1568
|
-
{ client: CLAUDE, func: promptAnthropic, multimodal: 2 },
|
|
1569
|
-
// { client: AZURE, func: promptAzure, multimodal: 3 },
|
|
1570
|
-
// { client: OLLAMA, func: promptOllama, multimodal: 99 },
|
|
1571
|
-
]; // keep gpt first to avoid gemini grounding by default
|
|
1572
|
-
|
|
1573
1510
|
export default init;
|
|
1574
1511
|
export {
|
|
1575
1512
|
ATTACHMENT_TOKEN_COST, CLOUD_37_SONNET, CODE_INTERPRETER, DEEPSEEK_R1,
|