@aituber-onair/chat 0.55.0 → 0.57.0
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.ja.md +48 -8
- package/README.md +54 -9
- package/dist/cjs/constants/claude.d.ts +1 -0
- package/dist/cjs/constants/claude.d.ts.map +1 -1
- package/dist/cjs/constants/claude.js +3 -1
- package/dist/cjs/constants/claude.js.map +1 -1
- package/dist/cjs/constants/openai.d.ts +5 -3
- package/dist/cjs/constants/openai.d.ts.map +1 -1
- package/dist/cjs/constants/openai.js +24 -7
- package/dist/cjs/constants/openai.js.map +1 -1
- package/dist/cjs/constants/xai.d.ts +1 -0
- package/dist/cjs/constants/xai.d.ts.map +1 -1
- package/dist/cjs/constants/xai.js +7 -2
- package/dist/cjs/constants/xai.js.map +1 -1
- package/dist/cjs/services/ChatService.d.ts +2 -0
- package/dist/cjs/services/ChatService.d.ts.map +1 -1
- package/dist/cjs/services/ChatServiceFactory.d.ts.map +1 -1
- package/dist/cjs/services/ChatServiceFactory.js +20 -15
- package/dist/cjs/services/ChatServiceFactory.js.map +1 -1
- package/dist/cjs/services/providers/ChatServiceProvider.d.ts +2 -0
- package/dist/cjs/services/providers/ChatServiceProvider.d.ts.map +1 -1
- package/dist/cjs/services/providers/claude/ClaudeChatServiceProvider.d.ts.map +1 -1
- package/dist/cjs/services/providers/claude/ClaudeChatServiceProvider.js +1 -0
- package/dist/cjs/services/providers/claude/ClaudeChatServiceProvider.js.map +1 -1
- package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.d.ts +24 -3
- package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.d.ts.map +1 -1
- package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.js +211 -15
- package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.js.map +1 -1
- package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.d.ts.map +1 -1
- package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.js +1 -0
- package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.js.map +1 -1
- package/dist/cjs/services/providers/openai/OpenAIChatService.js +1 -1
- package/dist/cjs/services/providers/openai/OpenAIChatService.js.map +1 -1
- package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.d.ts.map +1 -1
- package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js +10 -0
- package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
- package/dist/cjs/services/providers/xai/XAIChatServiceProvider.d.ts.map +1 -1
- package/dist/cjs/services/providers/xai/XAIChatServiceProvider.js +1 -0
- package/dist/cjs/services/providers/xai/XAIChatServiceProvider.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +1 -0
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/openaiCompatibleEndpoint.d.ts +57 -0
- package/dist/cjs/utils/openaiCompatibleEndpoint.d.ts.map +1 -0
- package/dist/cjs/utils/openaiCompatibleEndpoint.js +193 -0
- package/dist/cjs/utils/openaiCompatibleEndpoint.js.map +1 -0
- package/dist/esm/constants/claude.d.ts +1 -0
- package/dist/esm/constants/claude.d.ts.map +1 -1
- package/dist/esm/constants/claude.js +2 -0
- package/dist/esm/constants/claude.js.map +1 -1
- package/dist/esm/constants/openai.d.ts +5 -3
- package/dist/esm/constants/openai.d.ts.map +1 -1
- package/dist/esm/constants/openai.js +23 -6
- package/dist/esm/constants/openai.js.map +1 -1
- package/dist/esm/constants/xai.d.ts +1 -0
- package/dist/esm/constants/xai.d.ts.map +1 -1
- package/dist/esm/constants/xai.js +6 -1
- package/dist/esm/constants/xai.js.map +1 -1
- package/dist/esm/services/ChatService.d.ts +2 -0
- package/dist/esm/services/ChatService.d.ts.map +1 -1
- package/dist/esm/services/ChatServiceFactory.d.ts.map +1 -1
- package/dist/esm/services/ChatServiceFactory.js +21 -16
- package/dist/esm/services/ChatServiceFactory.js.map +1 -1
- package/dist/esm/services/providers/ChatServiceProvider.d.ts +2 -0
- package/dist/esm/services/providers/ChatServiceProvider.d.ts.map +1 -1
- package/dist/esm/services/providers/claude/ClaudeChatServiceProvider.d.ts.map +1 -1
- package/dist/esm/services/providers/claude/ClaudeChatServiceProvider.js +2 -1
- package/dist/esm/services/providers/claude/ClaudeChatServiceProvider.js.map +1 -1
- package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.d.ts +24 -3
- package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.d.ts.map +1 -1
- package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.js +211 -15
- package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.js.map +1 -1
- package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.d.ts.map +1 -1
- package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.js +1 -0
- package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.js.map +1 -1
- package/dist/esm/services/providers/openai/OpenAIChatService.js +1 -1
- package/dist/esm/services/providers/openai/OpenAIChatService.js.map +1 -1
- package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.d.ts.map +1 -1
- package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js +11 -1
- package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
- package/dist/esm/services/providers/xai/XAIChatServiceProvider.d.ts.map +1 -1
- package/dist/esm/services/providers/xai/XAIChatServiceProvider.js +2 -1
- package/dist/esm/services/providers/xai/XAIChatServiceProvider.js.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/openaiCompatibleEndpoint.d.ts +57 -0
- package/dist/esm/utils/openaiCompatibleEndpoint.d.ts.map +1 -0
- package/dist/esm/utils/openaiCompatibleEndpoint.js +186 -0
- package/dist/esm/utils/openaiCompatibleEndpoint.js.map +1 -0
- package/dist/umd/aituber-onair-chat.js +500 -25
- package/dist/umd/aituber-onair-chat.min.js +8 -8
- package/package.json +1 -1
|
@@ -99,6 +99,7 @@ var AITuberOnAirChat = (() => {
|
|
|
99
99
|
MODEL_CLAUDE_4_OPUS: () => MODEL_CLAUDE_4_OPUS,
|
|
100
100
|
MODEL_CLAUDE_4_SONNET: () => MODEL_CLAUDE_4_SONNET,
|
|
101
101
|
MODEL_CLAUDE_5_1_FABLE: () => MODEL_CLAUDE_5_1_FABLE,
|
|
102
|
+
MODEL_CLAUDE_5_5_OPUS: () => MODEL_CLAUDE_5_5_OPUS,
|
|
102
103
|
MODEL_CLAUDE_5_FABLE: () => MODEL_CLAUDE_5_FABLE,
|
|
103
104
|
MODEL_CLAUDE_5_OPUS: () => MODEL_CLAUDE_5_OPUS,
|
|
104
105
|
MODEL_CLAUDE_5_SONNET: () => MODEL_CLAUDE_5_SONNET,
|
|
@@ -171,6 +172,8 @@ var AITuberOnAirChat = (() => {
|
|
|
171
172
|
MODEL_GPT_5_MINI: () => MODEL_GPT_5_MINI,
|
|
172
173
|
MODEL_GPT_5_NANO: () => MODEL_GPT_5_NANO,
|
|
173
174
|
MODEL_GPT_6_ASTRA: () => MODEL_GPT_6_ASTRA,
|
|
175
|
+
MODEL_GPT_6_LUNA: () => MODEL_GPT_6_LUNA,
|
|
176
|
+
MODEL_GPT_6_SOL: () => MODEL_GPT_6_SOL,
|
|
174
177
|
MODEL_GPT_OSS_20B_FREE: () => MODEL_GPT_OSS_20B_FREE,
|
|
175
178
|
MODEL_GROK_4_1_FAST_NON_REASONING: () => MODEL_GROK_4_1_FAST_NON_REASONING,
|
|
176
179
|
MODEL_GROK_4_1_FAST_REASONING: () => MODEL_GROK_4_1_FAST_REASONING,
|
|
@@ -179,6 +182,7 @@ var AITuberOnAirChat = (() => {
|
|
|
179
182
|
MODEL_GROK_4_3: () => MODEL_GROK_4_3,
|
|
180
183
|
MODEL_GROK_4_5: () => MODEL_GROK_4_5,
|
|
181
184
|
MODEL_GROK_4_6: () => MODEL_GROK_4_6,
|
|
185
|
+
MODEL_GROK_4_7: () => MODEL_GROK_4_7,
|
|
182
186
|
MODEL_INCEPTION_MERCURY_2_5: () => MODEL_INCEPTION_MERCURY_2_5,
|
|
183
187
|
MODEL_INCLUSIONAI_LING_3_0_FLASH_VL_FREE: () => MODEL_INCLUSIONAI_LING_3_0_FLASH_VL_FREE,
|
|
184
188
|
MODEL_KIMI_K2_5: () => MODEL_KIMI_K2_5,
|
|
@@ -248,6 +252,7 @@ var AITuberOnAirChat = (() => {
|
|
|
248
252
|
MODEL_ZAI_GLM_5_3_FLASH: () => MODEL_ZAI_GLM_5_3_FLASH,
|
|
249
253
|
MistralChatService: () => MistralChatService,
|
|
250
254
|
MistralChatServiceProvider: () => MistralChatServiceProvider,
|
|
255
|
+
OPENAI_COMPATIBLE_LOCAL_PRESETS: () => OPENAI_COMPATIBLE_LOCAL_PRESETS,
|
|
251
256
|
OPENROUTER_CREDITS_THRESHOLD: () => OPENROUTER_CREDITS_THRESHOLD,
|
|
252
257
|
OPENROUTER_DEPRECATED_MODELS: () => OPENROUTER_DEPRECATED_MODELS,
|
|
253
258
|
OPENROUTER_FREE_DAILY_LIMIT_HIGH_CREDITS: () => OPENROUTER_FREE_DAILY_LIMIT_HIGH_CREDITS,
|
|
@@ -258,6 +263,7 @@ var AITuberOnAirChat = (() => {
|
|
|
258
263
|
OpenAIChatService: () => OpenAIChatService,
|
|
259
264
|
OpenAIChatServiceProvider: () => OpenAIChatServiceProvider,
|
|
260
265
|
OpenAICompatibleChatServiceProvider: () => OpenAICompatibleChatServiceProvider,
|
|
266
|
+
OpenAICompatibleEndpointError: () => OpenAICompatibleEndpointError,
|
|
261
267
|
OpenRouterChatService: () => OpenRouterChatService,
|
|
262
268
|
OpenRouterChatServiceProvider: () => OpenRouterChatServiceProvider,
|
|
263
269
|
PLAMO_API_BASE_URL: () => PLAMO_API_BASE_URL,
|
|
@@ -329,6 +335,7 @@ var AITuberOnAirChat = (() => {
|
|
|
329
335
|
isZaiReasoningEffortModel: () => isZaiReasoningEffortModel,
|
|
330
336
|
isZaiToolStreamModel: () => isZaiToolStreamModel,
|
|
331
337
|
isZaiVisionModel: () => isZaiVisionModel,
|
|
338
|
+
listOpenAICompatibleModels: () => listOpenAICompatibleModels,
|
|
332
339
|
normalizeClaudeReasoningEffort: () => normalizeClaudeReasoningEffort,
|
|
333
340
|
normalizeDeepSeekReasoningEffort: () => normalizeDeepSeekReasoningEffort,
|
|
334
341
|
normalizeGeminiReasoningEffort: () => normalizeGeminiReasoningEffort,
|
|
@@ -340,11 +347,13 @@ var AITuberOnAirChat = (() => {
|
|
|
340
347
|
parseOpenAICompatibleToolStream: () => parseOpenAICompatibleToolStream,
|
|
341
348
|
processChatWithOptionalTools: () => processChatWithOptionalTools,
|
|
342
349
|
refreshOpenRouterFreeModels: () => refreshOpenRouterFreeModels,
|
|
350
|
+
resolveOpenAICompatibleEndpoint: () => resolveOpenAICompatibleEndpoint,
|
|
343
351
|
resolveVisionModel: () => resolveVisionModel,
|
|
344
352
|
runOnceText: () => runOnceText,
|
|
345
353
|
safeJsonParse: () => safeJsonParse,
|
|
346
354
|
safeParseToolCallInput: () => safeParseToolCallInput,
|
|
347
355
|
screenplayToText: () => screenplayToText,
|
|
356
|
+
testOpenAICompatibleConnection: () => testOpenAICompatibleConnection,
|
|
348
357
|
textToScreenplay: () => textToScreenplay,
|
|
349
358
|
textsToScreenplay: () => textsToScreenplay
|
|
350
359
|
});
|
|
@@ -353,6 +362,8 @@ var AITuberOnAirChat = (() => {
|
|
|
353
362
|
var ENDPOINT_OPENAI_CHAT_COMPLETIONS_API = "https://api.openai.com/v1/chat/completions";
|
|
354
363
|
var ENDPOINT_OPENAI_RESPONSES_API = "https://api.openai.com/v1/responses";
|
|
355
364
|
var MODEL_GPT_6_ASTRA = "gpt-6-astra";
|
|
365
|
+
var MODEL_GPT_6_SOL = "gpt-6-sol";
|
|
366
|
+
var MODEL_GPT_6_LUNA = "gpt-6-luna";
|
|
356
367
|
var MODEL_GPT_5_NANO = "gpt-5-nano";
|
|
357
368
|
var MODEL_GPT_5_MINI = "gpt-5-mini";
|
|
358
369
|
var MODEL_GPT_5 = "gpt-5";
|
|
@@ -376,6 +387,8 @@ var AITuberOnAirChat = (() => {
|
|
|
376
387
|
var MODEL_O1 = "o1";
|
|
377
388
|
var VISION_SUPPORTED_MODELS = [
|
|
378
389
|
MODEL_GPT_6_ASTRA,
|
|
390
|
+
MODEL_GPT_6_SOL,
|
|
391
|
+
MODEL_GPT_6_LUNA,
|
|
379
392
|
MODEL_GPT_5_NANO,
|
|
380
393
|
MODEL_GPT_5_MINI,
|
|
381
394
|
MODEL_GPT_5,
|
|
@@ -416,19 +429,19 @@ var AITuberOnAirChat = (() => {
|
|
|
416
429
|
return GPT_5_MODELS.includes(model);
|
|
417
430
|
}
|
|
418
431
|
function isOpenAIReasoningModel(model) {
|
|
419
|
-
return model === MODEL_GPT_6_ASTRA || isGPT5Model(model);
|
|
432
|
+
return model === MODEL_GPT_6_ASTRA || model === MODEL_GPT_6_SOL || model === MODEL_GPT_6_LUNA || isGPT5Model(model);
|
|
420
433
|
}
|
|
421
434
|
function isResponsesOnlyGPT5Model(model) {
|
|
422
435
|
return model === MODEL_GPT_5_4_PRO;
|
|
423
436
|
}
|
|
424
437
|
function allowsReasoningXHigh(model) {
|
|
425
|
-
return model === MODEL_GPT_6_ASTRA || model === MODEL_GPT_5_6 || model === MODEL_GPT_5_6_SOL || model === MODEL_GPT_5_6_TERRA || model === MODEL_GPT_5_6_LUNA || model === MODEL_GPT_5_5 || model === MODEL_GPT_5_4 || model === MODEL_GPT_5_4_MINI || model === MODEL_GPT_5_4_NANO || model === MODEL_GPT_5_4_PRO;
|
|
438
|
+
return model === MODEL_GPT_6_ASTRA || model === MODEL_GPT_6_SOL || model === MODEL_GPT_6_LUNA || model === MODEL_GPT_5_6 || model === MODEL_GPT_5_6_SOL || model === MODEL_GPT_5_6_TERRA || model === MODEL_GPT_5_6_LUNA || model === MODEL_GPT_5_5 || model === MODEL_GPT_5_4 || model === MODEL_GPT_5_4_MINI || model === MODEL_GPT_5_4_NANO || model === MODEL_GPT_5_4_PRO;
|
|
426
439
|
}
|
|
427
440
|
function allowsReasoningMax(model) {
|
|
428
|
-
return model === MODEL_GPT_6_ASTRA || model === MODEL_GPT_5_6 || model === MODEL_GPT_5_6_SOL || model === MODEL_GPT_5_6_TERRA || model === MODEL_GPT_5_6_LUNA;
|
|
441
|
+
return model === MODEL_GPT_6_ASTRA || model === MODEL_GPT_6_SOL || model === MODEL_GPT_6_LUNA || model === MODEL_GPT_5_6 || model === MODEL_GPT_5_6_SOL || model === MODEL_GPT_5_6_TERRA || model === MODEL_GPT_5_6_LUNA;
|
|
429
442
|
}
|
|
430
443
|
function allowsReasoningNone(model) {
|
|
431
|
-
return model === MODEL_GPT_5_6 || model === MODEL_GPT_5_6_SOL || model === MODEL_GPT_5_6_TERRA || model === MODEL_GPT_5_6_LUNA || model === MODEL_GPT_5_1 || model === MODEL_GPT_5_4 || model === MODEL_GPT_5_5 || model === MODEL_GPT_5_4_MINI || model === MODEL_GPT_5_4_NANO;
|
|
444
|
+
return model === MODEL_GPT_6_SOL || model === MODEL_GPT_6_LUNA || model === MODEL_GPT_5_6 || model === MODEL_GPT_5_6_SOL || model === MODEL_GPT_5_6_TERRA || model === MODEL_GPT_5_6_LUNA || model === MODEL_GPT_5_1 || model === MODEL_GPT_5_4 || model === MODEL_GPT_5_5 || model === MODEL_GPT_5_4_MINI || model === MODEL_GPT_5_4_NANO;
|
|
432
445
|
}
|
|
433
446
|
function allowsReasoningMinimal(model) {
|
|
434
447
|
return model === MODEL_GPT_5_NANO || model === MODEL_GPT_5_MINI || model === MODEL_GPT_5;
|
|
@@ -446,7 +459,7 @@ var AITuberOnAirChat = (() => {
|
|
|
446
459
|
return "medium";
|
|
447
460
|
}
|
|
448
461
|
function getDefaultReasoningEffortForOpenAIModel(model) {
|
|
449
|
-
return model === MODEL_GPT_6_ASTRA ? "low" : getDefaultReasoningEffortForGPT5Model(model);
|
|
462
|
+
return model === MODEL_GPT_6_ASTRA ? "low" : model === MODEL_GPT_6_SOL ? "medium" : model === MODEL_GPT_6_LUNA ? "low" : getDefaultReasoningEffortForGPT5Model(model);
|
|
450
463
|
}
|
|
451
464
|
|
|
452
465
|
// src/constants/gemini.ts
|
|
@@ -561,6 +574,7 @@ var AITuberOnAirChat = (() => {
|
|
|
561
574
|
var MODEL_CLAUDE_5_FABLE = "claude-fable-5";
|
|
562
575
|
var MODEL_CLAUDE_5_SONNET = "claude-sonnet-5";
|
|
563
576
|
var MODEL_CLAUDE_5_OPUS = "claude-opus-5";
|
|
577
|
+
var MODEL_CLAUDE_5_5_OPUS = "claude-opus-5-5";
|
|
564
578
|
var CLAUDE_DEPRECATED_MODELS = [
|
|
565
579
|
MODEL_CLAUDE_3_HAIKU,
|
|
566
580
|
MODEL_CLAUDE_3_5_HAIKU,
|
|
@@ -605,7 +619,8 @@ var AITuberOnAirChat = (() => {
|
|
|
605
619
|
MODEL_CLAUDE_4_8_OPUS,
|
|
606
620
|
MODEL_CLAUDE_5_FABLE,
|
|
607
621
|
MODEL_CLAUDE_5_SONNET,
|
|
608
|
-
MODEL_CLAUDE_5_OPUS
|
|
622
|
+
MODEL_CLAUDE_5_OPUS,
|
|
623
|
+
MODEL_CLAUDE_5_5_OPUS
|
|
609
624
|
];
|
|
610
625
|
function getClaudeSupportedReasoningEfforts(model) {
|
|
611
626
|
return CLAUDE_REASONING_EFFORTS_BY_MODEL[model] ?? [];
|
|
@@ -1054,6 +1069,7 @@ var AITuberOnAirChat = (() => {
|
|
|
1054
1069
|
// src/constants/xai.ts
|
|
1055
1070
|
var ENDPOINT_XAI_CHAT_COMPLETIONS_API = "https://api.x.ai/v1/chat/completions";
|
|
1056
1071
|
var MODEL_GROK_4_6 = "grok-4.6";
|
|
1072
|
+
var MODEL_GROK_4_7 = "grok-4.7";
|
|
1057
1073
|
var MODEL_GROK_4_5 = "grok-4.5";
|
|
1058
1074
|
var MODEL_GROK_4_3 = "grok-4.3";
|
|
1059
1075
|
var MODEL_GROK_4_20_REASONING = "grok-4.20-0309-reasoning";
|
|
@@ -1066,6 +1082,7 @@ var AITuberOnAirChat = (() => {
|
|
|
1066
1082
|
];
|
|
1067
1083
|
var XAI_VISION_SUPPORTED_MODELS = [
|
|
1068
1084
|
MODEL_GROK_4_6,
|
|
1085
|
+
MODEL_GROK_4_7,
|
|
1069
1086
|
MODEL_GROK_4_5,
|
|
1070
1087
|
MODEL_GROK_4_3,
|
|
1071
1088
|
MODEL_GROK_4_20_REASONING,
|
|
@@ -1078,7 +1095,7 @@ var AITuberOnAirChat = (() => {
|
|
|
1078
1095
|
return getXaiSupportedReasoningEfforts(model).length > 0;
|
|
1079
1096
|
}
|
|
1080
1097
|
function getXaiSupportedReasoningEfforts(model) {
|
|
1081
|
-
if (model === MODEL_GROK_4_6) {
|
|
1098
|
+
if (model === MODEL_GROK_4_6 || model === MODEL_GROK_4_7) {
|
|
1082
1099
|
return ["low", "medium", "high", "xhigh"];
|
|
1083
1100
|
}
|
|
1084
1101
|
if (model === MODEL_GROK_4_5) {
|
|
@@ -1093,6 +1110,9 @@ var AITuberOnAirChat = (() => {
|
|
|
1093
1110
|
return getXaiSupportedReasoningEfforts(model).includes("none");
|
|
1094
1111
|
}
|
|
1095
1112
|
function getDefaultXaiReasoningEffort(model) {
|
|
1113
|
+
if (model === MODEL_GROK_4_7) {
|
|
1114
|
+
return "low";
|
|
1115
|
+
}
|
|
1096
1116
|
if (model === MODEL_GROK_4_6 || model === MODEL_GROK_4_5) {
|
|
1097
1117
|
return "low";
|
|
1098
1118
|
}
|
|
@@ -1811,6 +1831,192 @@ If it's in another language, summarize in that language.
|
|
|
1811
1831
|
};
|
|
1812
1832
|
}
|
|
1813
1833
|
|
|
1834
|
+
// src/utils/openaiCompatibleEndpoint.ts
|
|
1835
|
+
var OPENAI_COMPATIBLE_LOCAL_PRESETS = [
|
|
1836
|
+
{
|
|
1837
|
+
id: "ollama",
|
|
1838
|
+
label: "Ollama",
|
|
1839
|
+
baseUrl: "http://localhost:11434/v1",
|
|
1840
|
+
docsUrl: "https://docs.ollama.com/api/openai-compatibility",
|
|
1841
|
+
corsHint: "Set OLLAMA_ORIGINS to allow additional browser origins."
|
|
1842
|
+
},
|
|
1843
|
+
{
|
|
1844
|
+
id: "lmStudio",
|
|
1845
|
+
label: "LM Studio",
|
|
1846
|
+
baseUrl: "http://localhost:1234/v1",
|
|
1847
|
+
docsUrl: "https://lmstudio.ai/docs/developer/openai-compat",
|
|
1848
|
+
corsHint: "Start the server with lms server start --cors for browser access."
|
|
1849
|
+
},
|
|
1850
|
+
{
|
|
1851
|
+
id: "llamaCpp",
|
|
1852
|
+
label: "llama.cpp",
|
|
1853
|
+
baseUrl: "http://127.0.0.1:8080/v1",
|
|
1854
|
+
docsUrl: "https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md",
|
|
1855
|
+
corsHint: "All origins are allowed by default; use --cors-origins to restrict them."
|
|
1856
|
+
},
|
|
1857
|
+
{
|
|
1858
|
+
id: "vllm",
|
|
1859
|
+
label: "vLLM",
|
|
1860
|
+
baseUrl: "http://localhost:8000/v1",
|
|
1861
|
+
docsUrl: "https://docs.vllm.ai/en/latest/serving/online_serving/openai_compatible_server/",
|
|
1862
|
+
corsHint: "All origins are allowed by default; use --allowed-origins to restrict them."
|
|
1863
|
+
}
|
|
1864
|
+
];
|
|
1865
|
+
var OpenAICompatibleEndpointError = class extends Error {
|
|
1866
|
+
constructor(code, message, status) {
|
|
1867
|
+
super(message);
|
|
1868
|
+
this.name = "OpenAICompatibleEndpointError";
|
|
1869
|
+
this.code = code;
|
|
1870
|
+
this.status = status;
|
|
1871
|
+
}
|
|
1872
|
+
};
|
|
1873
|
+
function resolveOpenAICompatibleEndpoint(input) {
|
|
1874
|
+
let url;
|
|
1875
|
+
try {
|
|
1876
|
+
url = new URL(input.trim());
|
|
1877
|
+
} catch {
|
|
1878
|
+
throw new OpenAICompatibleEndpointError(
|
|
1879
|
+
"invalid-url",
|
|
1880
|
+
"Enter a valid HTTP or HTTPS endpoint URL."
|
|
1881
|
+
);
|
|
1882
|
+
}
|
|
1883
|
+
if (url.protocol !== "http:" && url.protocol !== "https:" || url.search || url.hash || url.username || url.password) {
|
|
1884
|
+
throw new OpenAICompatibleEndpointError(
|
|
1885
|
+
"invalid-url",
|
|
1886
|
+
"Use an HTTP or HTTPS endpoint URL without credentials, a query, or a fragment."
|
|
1887
|
+
);
|
|
1888
|
+
}
|
|
1889
|
+
const path = url.pathname.replace(/\/+$/, "");
|
|
1890
|
+
if (path.endsWith("/api/chat") || path.endsWith("/api/generate")) {
|
|
1891
|
+
throw new OpenAICompatibleEndpointError(
|
|
1892
|
+
"invalid-url",
|
|
1893
|
+
"This looks like Ollama's native API URL. Use the OpenAI-compatible base URL instead, e.g. http://localhost:11434/v1."
|
|
1894
|
+
);
|
|
1895
|
+
}
|
|
1896
|
+
const basePath = !path || path === "/" ? "/v1" : path.endsWith("/chat/completions") ? path.slice(0, -"/chat/completions".length) : path;
|
|
1897
|
+
const baseUrl = `${url.origin}${basePath}`;
|
|
1898
|
+
return {
|
|
1899
|
+
baseUrl,
|
|
1900
|
+
chatCompletionsUrl: `${baseUrl}/chat/completions`,
|
|
1901
|
+
modelsUrl: `${baseUrl}/models`
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
async function listOpenAICompatibleModels(options) {
|
|
1905
|
+
const { modelsUrl } = resolveOpenAICompatibleEndpoint(options.endpoint);
|
|
1906
|
+
const timeoutMs = options.timeoutMs ?? 8e3;
|
|
1907
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
1908
|
+
throw new RangeError("timeoutMs must be a positive finite number.");
|
|
1909
|
+
}
|
|
1910
|
+
if (options.signal?.aborted) {
|
|
1911
|
+
throw new OpenAICompatibleEndpointError(
|
|
1912
|
+
"aborted",
|
|
1913
|
+
"The models request was aborted by the caller."
|
|
1914
|
+
);
|
|
1915
|
+
}
|
|
1916
|
+
const controller = new AbortController();
|
|
1917
|
+
let abortCause;
|
|
1918
|
+
const onAbort = () => {
|
|
1919
|
+
if (!abortCause) abortCause = "caller";
|
|
1920
|
+
controller.abort();
|
|
1921
|
+
};
|
|
1922
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
1923
|
+
if (options.signal?.aborted) onAbort();
|
|
1924
|
+
const timeout = setTimeout(() => {
|
|
1925
|
+
if (!abortCause) abortCause = "timeout";
|
|
1926
|
+
controller.abort();
|
|
1927
|
+
}, timeoutMs);
|
|
1928
|
+
try {
|
|
1929
|
+
const headers = {};
|
|
1930
|
+
if (options.apiKey?.trim()) {
|
|
1931
|
+
headers.Authorization = `Bearer ${options.apiKey.trim()}`;
|
|
1932
|
+
}
|
|
1933
|
+
const response = await (options.fetch ?? fetch)(modelsUrl, {
|
|
1934
|
+
method: "GET",
|
|
1935
|
+
headers,
|
|
1936
|
+
signal: controller.signal
|
|
1937
|
+
});
|
|
1938
|
+
if (abortCause) {
|
|
1939
|
+
throw new OpenAICompatibleEndpointError(
|
|
1940
|
+
"aborted",
|
|
1941
|
+
"The models request was aborted by the caller."
|
|
1942
|
+
);
|
|
1943
|
+
}
|
|
1944
|
+
if (!response.ok) {
|
|
1945
|
+
throw new OpenAICompatibleEndpointError(
|
|
1946
|
+
"http",
|
|
1947
|
+
`Model listing failed with HTTP ${response.status}.`,
|
|
1948
|
+
response.status
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
let body;
|
|
1952
|
+
try {
|
|
1953
|
+
body = await response.json();
|
|
1954
|
+
} catch {
|
|
1955
|
+
throw new OpenAICompatibleEndpointError(
|
|
1956
|
+
"invalid-response",
|
|
1957
|
+
"The models endpoint did not return valid JSON."
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
if (!body || typeof body !== "object" || !("data" in body) || !Array.isArray(body.data) || !body.data.every(
|
|
1961
|
+
(model) => model && typeof model === "object" && "id" in model && typeof model.id === "string"
|
|
1962
|
+
)) {
|
|
1963
|
+
throw new OpenAICompatibleEndpointError(
|
|
1964
|
+
"invalid-response",
|
|
1965
|
+
"The models response must contain data with model IDs."
|
|
1966
|
+
);
|
|
1967
|
+
}
|
|
1968
|
+
if (abortCause) {
|
|
1969
|
+
throw new OpenAICompatibleEndpointError(
|
|
1970
|
+
"aborted",
|
|
1971
|
+
"The models request was aborted by the caller."
|
|
1972
|
+
);
|
|
1973
|
+
}
|
|
1974
|
+
return [...new Set(body.data.map((model) => model.id))];
|
|
1975
|
+
} catch (error) {
|
|
1976
|
+
if (abortCause === "caller") {
|
|
1977
|
+
throw new OpenAICompatibleEndpointError(
|
|
1978
|
+
"aborted",
|
|
1979
|
+
"The models request was aborted by the caller."
|
|
1980
|
+
);
|
|
1981
|
+
}
|
|
1982
|
+
if (abortCause === "timeout") {
|
|
1983
|
+
throw new OpenAICompatibleEndpointError(
|
|
1984
|
+
"timeout",
|
|
1985
|
+
`The models request timed out after ${timeoutMs} ms.`
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
if (error instanceof OpenAICompatibleEndpointError) throw error;
|
|
1989
|
+
throw new OpenAICompatibleEndpointError(
|
|
1990
|
+
"network",
|
|
1991
|
+
"Could not reach the models endpoint. In a browser, this is usually a CORS restriction or the server is not running."
|
|
1992
|
+
);
|
|
1993
|
+
} finally {
|
|
1994
|
+
clearTimeout(timeout);
|
|
1995
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
async function testOpenAICompatibleConnection(options) {
|
|
1999
|
+
const startedAt = Date.now();
|
|
2000
|
+
try {
|
|
2001
|
+
const models = await listOpenAICompatibleModels(options);
|
|
2002
|
+
return {
|
|
2003
|
+
ok: true,
|
|
2004
|
+
latencyMs: Date.now() - startedAt,
|
|
2005
|
+
models,
|
|
2006
|
+
...options.model !== void 0 ? { modelFound: models.includes(options.model) } : {}
|
|
2007
|
+
};
|
|
2008
|
+
} catch (error) {
|
|
2009
|
+
if (error instanceof RangeError) throw error;
|
|
2010
|
+
return {
|
|
2011
|
+
ok: false,
|
|
2012
|
+
error: error instanceof OpenAICompatibleEndpointError ? error : new OpenAICompatibleEndpointError(
|
|
2013
|
+
"network",
|
|
2014
|
+
"Could not reach the models endpoint. In a browser, this is usually a CORS restriction or the server is not running."
|
|
2015
|
+
)
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
|
|
1814
2020
|
// src/utils/openaiCompatibleTools.ts
|
|
1815
2021
|
var buildOpenAICompatibleTools = (tools, format = "chat-completions") => {
|
|
1816
2022
|
if (tools.length === 0) return [];
|
|
@@ -2628,7 +2834,8 @@ If it's in another language, summarize in that language.
|
|
|
2628
2834
|
MODEL_CLAUDE_5_1_FABLE,
|
|
2629
2835
|
MODEL_CLAUDE_5_FABLE,
|
|
2630
2836
|
MODEL_CLAUDE_5_SONNET,
|
|
2631
|
-
MODEL_CLAUDE_5_OPUS
|
|
2837
|
+
MODEL_CLAUDE_5_OPUS,
|
|
2838
|
+
MODEL_CLAUDE_5_5_OPUS
|
|
2632
2839
|
];
|
|
2633
2840
|
}
|
|
2634
2841
|
/**
|
|
@@ -4335,6 +4542,7 @@ If it's in another language, summarize in that language.
|
|
|
4335
4542
|
var GeminiNanoChatService = class {
|
|
4336
4543
|
constructor(options = {}) {
|
|
4337
4544
|
this.provider = "gemini-nano";
|
|
4545
|
+
this.consumedTranscript = [];
|
|
4338
4546
|
this.expectedInputLanguages = options.expectedInputLanguages ?? [
|
|
4339
4547
|
"ja",
|
|
4340
4548
|
"en"
|
|
@@ -4344,6 +4552,7 @@ If it's in another language, summarize in that language.
|
|
|
4344
4552
|
...prompt
|
|
4345
4553
|
}));
|
|
4346
4554
|
this._responseLength = options.responseLength;
|
|
4555
|
+
this.sessionMode = options.sessionMode ?? "stateless";
|
|
4347
4556
|
}
|
|
4348
4557
|
getModel() {
|
|
4349
4558
|
return MODEL_GEMINI_NANO;
|
|
@@ -4351,23 +4560,33 @@ If it's in another language, summarize in that language.
|
|
|
4351
4560
|
getVisionModel() {
|
|
4352
4561
|
return MODEL_GEMINI_NANO;
|
|
4353
4562
|
}
|
|
4563
|
+
/** Destroy any persistent Prompt API sessions held by this service. */
|
|
4564
|
+
dispose() {
|
|
4565
|
+
this.destroyPersistentSessions();
|
|
4566
|
+
}
|
|
4354
4567
|
/**
|
|
4355
4568
|
* Process chat messages using Gemini Nano.
|
|
4356
|
-
*
|
|
4357
|
-
*
|
|
4569
|
+
* Streams response deltas when Chrome exposes promptStreaming(), then calls
|
|
4570
|
+
* onCompleteResponse with the complete response.
|
|
4358
4571
|
*/
|
|
4359
4572
|
async processChat(messages, onPartialResponse, onCompleteResponse) {
|
|
4360
|
-
const response = await this.generateResponse(
|
|
4361
|
-
|
|
4573
|
+
const response = await this.generateResponse(
|
|
4574
|
+
messages,
|
|
4575
|
+
true,
|
|
4576
|
+
onPartialResponse
|
|
4577
|
+
);
|
|
4362
4578
|
await onCompleteResponse(response);
|
|
4363
4579
|
}
|
|
4364
4580
|
async processVisionChat(_messages, _onPartialResponse, _onCompleteResponse) {
|
|
4365
4581
|
throw new Error("Gemini Nano does not support vision capabilities.");
|
|
4366
4582
|
}
|
|
4367
|
-
async chatOnce(messages,
|
|
4583
|
+
async chatOnce(messages, stream = false, onPartialResponse = () => {
|
|
4368
4584
|
}, _maxTokens) {
|
|
4369
|
-
const response = await this.generateResponse(
|
|
4370
|
-
|
|
4585
|
+
const response = await this.generateResponse(
|
|
4586
|
+
messages,
|
|
4587
|
+
stream,
|
|
4588
|
+
onPartialResponse
|
|
4589
|
+
);
|
|
4371
4590
|
return {
|
|
4372
4591
|
blocks: [{ type: "text", text: response }],
|
|
4373
4592
|
stop_reason: "end"
|
|
@@ -4380,7 +4599,7 @@ If it's in another language, summarize in that language.
|
|
|
4380
4599
|
/**
|
|
4381
4600
|
* Core logic: extract system prompt, manage session, call prompt().
|
|
4382
4601
|
*/
|
|
4383
|
-
async generateResponse(messages) {
|
|
4602
|
+
async generateResponse(messages, stream, onPartialResponse) {
|
|
4384
4603
|
const api = getLanguageModelAPI();
|
|
4385
4604
|
if (!api) {
|
|
4386
4605
|
throw new Error(
|
|
@@ -4388,11 +4607,8 @@ If it's in another language, summarize in that language.
|
|
|
4388
4607
|
);
|
|
4389
4608
|
}
|
|
4390
4609
|
const modelOptions = this.getModelOptions();
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
throw new Error(
|
|
4394
|
-
`Gemini Nano Prompt API is not ready in this environment. LanguageModel.availability() returned "${availability}". Expected "available" or "downloadable".`
|
|
4395
|
-
);
|
|
4610
|
+
if (this.sessionMode === "stateless") {
|
|
4611
|
+
await this.ensureAvailability(api, modelOptions);
|
|
4396
4612
|
}
|
|
4397
4613
|
const systemMessages = messages.filter((m) => m.role === "system");
|
|
4398
4614
|
const systemPrompt = systemMessages.map((m) => m.content).join("\n");
|
|
@@ -4402,14 +4618,31 @@ If it's in another language, summarize in that language.
|
|
|
4402
4618
|
throw new Error("No user message found in the provided messages.");
|
|
4403
4619
|
}
|
|
4404
4620
|
const lastUserMessage = conversationMessages[lastUserMessageIndex];
|
|
4621
|
+
const contextHistory = conversationMessages.slice(0, lastUserMessageIndex);
|
|
4622
|
+
if (this.sessionMode === "persistent") {
|
|
4623
|
+
return this.generatePersistentResponse(
|
|
4624
|
+
api,
|
|
4625
|
+
systemPrompt,
|
|
4626
|
+
contextHistory,
|
|
4627
|
+
lastUserMessage.content,
|
|
4628
|
+
modelOptions,
|
|
4629
|
+
stream,
|
|
4630
|
+
onPartialResponse
|
|
4631
|
+
);
|
|
4632
|
+
}
|
|
4405
4633
|
const session = await this.createSession(
|
|
4406
4634
|
api,
|
|
4407
4635
|
systemPrompt,
|
|
4408
|
-
|
|
4636
|
+
contextHistory,
|
|
4409
4637
|
modelOptions
|
|
4410
4638
|
);
|
|
4411
4639
|
try {
|
|
4412
|
-
return await
|
|
4640
|
+
return await this.promptSession(
|
|
4641
|
+
session,
|
|
4642
|
+
lastUserMessage.content,
|
|
4643
|
+
stream,
|
|
4644
|
+
onPartialResponse
|
|
4645
|
+
);
|
|
4413
4646
|
} finally {
|
|
4414
4647
|
try {
|
|
4415
4648
|
session.destroy();
|
|
@@ -4417,6 +4650,241 @@ If it's in another language, summarize in that language.
|
|
|
4417
4650
|
}
|
|
4418
4651
|
}
|
|
4419
4652
|
}
|
|
4653
|
+
async generatePersistentResponse(api, systemPrompt, contextHistory, userPrompt, modelOptions, stream, onPartialResponse) {
|
|
4654
|
+
const sessionKey = this.getPersistentSessionKey(systemPrompt, modelOptions);
|
|
4655
|
+
if (this.persistentSessionKey !== sessionKey) {
|
|
4656
|
+
this.destroyPersistentSessions();
|
|
4657
|
+
}
|
|
4658
|
+
if (!this.baseSession && !this.liveSession) {
|
|
4659
|
+
await this.ensureAvailability(api, modelOptions);
|
|
4660
|
+
await this.createPersistentBaseSession(
|
|
4661
|
+
api,
|
|
4662
|
+
systemPrompt,
|
|
4663
|
+
contextHistory,
|
|
4664
|
+
modelOptions
|
|
4665
|
+
);
|
|
4666
|
+
this.persistentSessionKey = sessionKey;
|
|
4667
|
+
}
|
|
4668
|
+
let session = await this.getPersistentLiveSession(
|
|
4669
|
+
api,
|
|
4670
|
+
systemPrompt,
|
|
4671
|
+
contextHistory,
|
|
4672
|
+
modelOptions
|
|
4673
|
+
);
|
|
4674
|
+
const reusedLiveSession = session === this.liveSession && this.isHistoryCompatible(contextHistory, this.consumedTranscript);
|
|
4675
|
+
this.persistentSessionKey = sessionKey;
|
|
4676
|
+
try {
|
|
4677
|
+
const response = await this.promptSession(
|
|
4678
|
+
session,
|
|
4679
|
+
userPrompt,
|
|
4680
|
+
stream,
|
|
4681
|
+
onPartialResponse
|
|
4682
|
+
);
|
|
4683
|
+
this.recordConsumedTranscript(
|
|
4684
|
+
contextHistory,
|
|
4685
|
+
userPrompt,
|
|
4686
|
+
response,
|
|
4687
|
+
reusedLiveSession
|
|
4688
|
+
);
|
|
4689
|
+
return response;
|
|
4690
|
+
} catch (error) {
|
|
4691
|
+
if (!this.isQuotaExceededError(error)) {
|
|
4692
|
+
this.destroyPersistentLiveSession();
|
|
4693
|
+
throw error;
|
|
4694
|
+
}
|
|
4695
|
+
this.destroyPersistentLiveSession();
|
|
4696
|
+
session = await this.getPersistentLiveSession(
|
|
4697
|
+
api,
|
|
4698
|
+
systemPrompt,
|
|
4699
|
+
[],
|
|
4700
|
+
modelOptions
|
|
4701
|
+
);
|
|
4702
|
+
this.persistentSessionKey = sessionKey;
|
|
4703
|
+
try {
|
|
4704
|
+
const response = await this.promptSession(
|
|
4705
|
+
session,
|
|
4706
|
+
userPrompt,
|
|
4707
|
+
stream,
|
|
4708
|
+
onPartialResponse
|
|
4709
|
+
);
|
|
4710
|
+
this.recordConsumedTranscript([], userPrompt, response, false);
|
|
4711
|
+
return response;
|
|
4712
|
+
} catch (retryError) {
|
|
4713
|
+
this.destroyPersistentLiveSession();
|
|
4714
|
+
throw retryError;
|
|
4715
|
+
}
|
|
4716
|
+
}
|
|
4717
|
+
}
|
|
4718
|
+
async ensureAvailability(api, modelOptions) {
|
|
4719
|
+
const availability = await api.availability(modelOptions);
|
|
4720
|
+
if (availability !== "available" && availability !== "downloadable") {
|
|
4721
|
+
throw new Error(
|
|
4722
|
+
`Gemini Nano Prompt API is not ready in this environment. LanguageModel.availability() returned "${availability}". Expected "available" or "downloadable".`
|
|
4723
|
+
);
|
|
4724
|
+
}
|
|
4725
|
+
}
|
|
4726
|
+
async createPersistentBaseSession(api, systemPrompt, contextHistory, modelOptions) {
|
|
4727
|
+
this.baseSession = await this.createSession(
|
|
4728
|
+
api,
|
|
4729
|
+
systemPrompt,
|
|
4730
|
+
[],
|
|
4731
|
+
modelOptions
|
|
4732
|
+
);
|
|
4733
|
+
if (contextHistory.length > 0) {
|
|
4734
|
+
this.liveSession = await this.createSession(
|
|
4735
|
+
api,
|
|
4736
|
+
systemPrompt,
|
|
4737
|
+
contextHistory,
|
|
4738
|
+
modelOptions
|
|
4739
|
+
);
|
|
4740
|
+
this.consumedTranscript = contextHistory.map((message) => ({
|
|
4741
|
+
...message
|
|
4742
|
+
}));
|
|
4743
|
+
} else if (typeof this.baseSession.clone === "function") {
|
|
4744
|
+
this.liveSession = await this.baseSession.clone();
|
|
4745
|
+
} else {
|
|
4746
|
+
this.liveSession = this.baseSession;
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4749
|
+
async getPersistentLiveSession(api, systemPrompt, contextHistory, modelOptions) {
|
|
4750
|
+
if (this.liveSession && this.isHistoryCompatible(contextHistory, this.consumedTranscript)) {
|
|
4751
|
+
return this.liveSession;
|
|
4752
|
+
}
|
|
4753
|
+
if (this.liveSession && this.liveSession !== this.baseSession) {
|
|
4754
|
+
this.destroyPersistentLiveSession();
|
|
4755
|
+
}
|
|
4756
|
+
if (contextHistory.length === 0 && this.baseSession) {
|
|
4757
|
+
if (typeof this.baseSession.clone === "function") {
|
|
4758
|
+
this.liveSession = await this.baseSession.clone();
|
|
4759
|
+
} else {
|
|
4760
|
+
if (this.consumedTranscript.length > 0) {
|
|
4761
|
+
this.destroyPersistentSessions();
|
|
4762
|
+
await this.createPersistentBaseSession(
|
|
4763
|
+
api,
|
|
4764
|
+
systemPrompt,
|
|
4765
|
+
[],
|
|
4766
|
+
modelOptions
|
|
4767
|
+
);
|
|
4768
|
+
return this.liveSession;
|
|
4769
|
+
}
|
|
4770
|
+
this.liveSession = this.baseSession;
|
|
4771
|
+
}
|
|
4772
|
+
return this.liveSession;
|
|
4773
|
+
}
|
|
4774
|
+
if (this.baseSession && typeof this.baseSession.clone === "function") {
|
|
4775
|
+
this.liveSession = await this.createSession(
|
|
4776
|
+
api,
|
|
4777
|
+
systemPrompt,
|
|
4778
|
+
contextHistory,
|
|
4779
|
+
modelOptions
|
|
4780
|
+
);
|
|
4781
|
+
return this.liveSession;
|
|
4782
|
+
}
|
|
4783
|
+
this.destroyPersistentSessions();
|
|
4784
|
+
await this.ensureAvailability(api, modelOptions);
|
|
4785
|
+
await this.createPersistentBaseSessionWithHistory(
|
|
4786
|
+
api,
|
|
4787
|
+
systemPrompt,
|
|
4788
|
+
contextHistory,
|
|
4789
|
+
modelOptions
|
|
4790
|
+
);
|
|
4791
|
+
return this.liveSession;
|
|
4792
|
+
}
|
|
4793
|
+
async createPersistentBaseSessionWithHistory(api, systemPrompt, contextHistory, modelOptions) {
|
|
4794
|
+
this.baseSession = await this.createSession(
|
|
4795
|
+
api,
|
|
4796
|
+
systemPrompt,
|
|
4797
|
+
contextHistory,
|
|
4798
|
+
modelOptions
|
|
4799
|
+
);
|
|
4800
|
+
this.liveSession = this.baseSession;
|
|
4801
|
+
this.consumedTranscript = contextHistory.map((message) => ({
|
|
4802
|
+
...message
|
|
4803
|
+
}));
|
|
4804
|
+
}
|
|
4805
|
+
recordConsumedTranscript(contextHistory, userPrompt, response, reusedLiveSession) {
|
|
4806
|
+
const priorTranscript = reusedLiveSession ? this.consumedTranscript : contextHistory;
|
|
4807
|
+
this.consumedTranscript = [
|
|
4808
|
+
...priorTranscript,
|
|
4809
|
+
{ role: "user", content: userPrompt },
|
|
4810
|
+
{ role: "assistant", content: response }
|
|
4811
|
+
];
|
|
4812
|
+
}
|
|
4813
|
+
getPersistentSessionKey(systemPrompt, modelOptions) {
|
|
4814
|
+
return JSON.stringify({
|
|
4815
|
+
systemPrompt,
|
|
4816
|
+
modelOptions,
|
|
4817
|
+
initialPrompts: this.initialPrompts,
|
|
4818
|
+
responseLength: this._responseLength
|
|
4819
|
+
});
|
|
4820
|
+
}
|
|
4821
|
+
isHistoryCompatible(left, right) {
|
|
4822
|
+
if (left.length === 0 || right.length === 0) {
|
|
4823
|
+
return left.length === 0 && right.length === 0;
|
|
4824
|
+
}
|
|
4825
|
+
return this.isSuffix(left, right) || this.isSuffix(right, left);
|
|
4826
|
+
}
|
|
4827
|
+
isSuffix(candidate, full) {
|
|
4828
|
+
if (candidate.length > full.length) return false;
|
|
4829
|
+
const offset = full.length - candidate.length;
|
|
4830
|
+
return candidate.every(
|
|
4831
|
+
(message, index) => message.role === full[offset + index].role && message.content === full[offset + index].content
|
|
4832
|
+
);
|
|
4833
|
+
}
|
|
4834
|
+
isQuotaExceededError(error) {
|
|
4835
|
+
return typeof error === "object" && error !== null && "name" in error && error.name === "QuotaExceededError";
|
|
4836
|
+
}
|
|
4837
|
+
destroyPersistentLiveSession() {
|
|
4838
|
+
if (this.liveSession) {
|
|
4839
|
+
this.destroySession(this.liveSession);
|
|
4840
|
+
if (this.liveSession === this.baseSession) {
|
|
4841
|
+
this.baseSession = void 0;
|
|
4842
|
+
}
|
|
4843
|
+
}
|
|
4844
|
+
this.liveSession = void 0;
|
|
4845
|
+
this.consumedTranscript = [];
|
|
4846
|
+
}
|
|
4847
|
+
destroyPersistentSessions() {
|
|
4848
|
+
if (this.liveSession && this.liveSession !== this.baseSession) {
|
|
4849
|
+
this.destroySession(this.liveSession);
|
|
4850
|
+
}
|
|
4851
|
+
if (this.baseSession) {
|
|
4852
|
+
this.destroySession(this.baseSession);
|
|
4853
|
+
}
|
|
4854
|
+
this.baseSession = void 0;
|
|
4855
|
+
this.liveSession = void 0;
|
|
4856
|
+
this.persistentSessionKey = void 0;
|
|
4857
|
+
this.consumedTranscript = [];
|
|
4858
|
+
}
|
|
4859
|
+
destroySession(session) {
|
|
4860
|
+
try {
|
|
4861
|
+
session.destroy();
|
|
4862
|
+
} catch {
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
async promptSession(session, prompt, stream, onPartialResponse) {
|
|
4866
|
+
if (stream && typeof session.promptStreaming === "function") {
|
|
4867
|
+
const reader = session.promptStreaming(prompt).getReader();
|
|
4868
|
+
let response2 = "";
|
|
4869
|
+
let streamMode = "unknown";
|
|
4870
|
+
while (true) {
|
|
4871
|
+
const { done, value } = await reader.read();
|
|
4872
|
+
if (done) break;
|
|
4873
|
+
const chunk = String(value ?? "");
|
|
4874
|
+
if (streamMode === "unknown" && response2 !== "") {
|
|
4875
|
+
streamMode = chunk.startsWith(response2) ? "cumulative" : "delta";
|
|
4876
|
+
}
|
|
4877
|
+
const isCumulative = streamMode === "cumulative";
|
|
4878
|
+
const delta = isCumulative ? chunk.slice(response2.length) : chunk;
|
|
4879
|
+
response2 = isCumulative ? chunk : response2 + chunk;
|
|
4880
|
+
if (delta) onPartialResponse(delta);
|
|
4881
|
+
}
|
|
4882
|
+
return response2;
|
|
4883
|
+
}
|
|
4884
|
+
const response = await session.prompt(prompt);
|
|
4885
|
+
onPartialResponse(response);
|
|
4886
|
+
return response;
|
|
4887
|
+
}
|
|
4420
4888
|
/**
|
|
4421
4889
|
* Create a new LanguageModel session with structured initial prompts.
|
|
4422
4890
|
* System instructions, few-shot examples, and conversation history retain
|
|
@@ -4511,7 +4979,8 @@ If it's in another language, summarize in that language.
|
|
|
4511
4979
|
expectedInputLanguages: options.expectedInputLanguages,
|
|
4512
4980
|
expectedOutputLanguages: options.expectedOutputLanguages,
|
|
4513
4981
|
initialPrompts: options.initialPrompts,
|
|
4514
|
-
responseLength: options.responseLength
|
|
4982
|
+
responseLength: options.responseLength,
|
|
4983
|
+
sessionMode: options.sessionMode
|
|
4515
4984
|
});
|
|
4516
4985
|
}
|
|
4517
4986
|
getProviderName() {
|
|
@@ -5061,6 +5530,9 @@ If it's in another language, summarize in that language.
|
|
|
5061
5530
|
let shouldUseResponsesAPI = false;
|
|
5062
5531
|
if (mcpServers.length > 0 || modelName === MODEL_GPT_6_ASTRA || visionModel === MODEL_GPT_6_ASTRA) {
|
|
5063
5532
|
shouldUseResponsesAPI = true;
|
|
5533
|
+
} else if (modelName === MODEL_GPT_6_SOL || visionModel === MODEL_GPT_6_SOL || modelName === MODEL_GPT_6_LUNA || visionModel === MODEL_GPT_6_LUNA) {
|
|
5534
|
+
const preference = optimizedOptions.gpt5EndpointPreference || "responses";
|
|
5535
|
+
shouldUseResponsesAPI = preference !== "chat" || optimizedOptions.reasoning_effort !== "none";
|
|
5064
5536
|
} else if (isResponsesOnlyGPT5Model(modelName)) {
|
|
5065
5537
|
shouldUseResponsesAPI = true;
|
|
5066
5538
|
} else if (isOpenAIReasoningModel(modelName)) {
|
|
@@ -5107,6 +5579,8 @@ If it's in another language, summarize in that language.
|
|
|
5107
5579
|
MODEL_GPT_5_5,
|
|
5108
5580
|
MODEL_GPT_5_6,
|
|
5109
5581
|
MODEL_GPT_6_ASTRA,
|
|
5582
|
+
MODEL_GPT_6_SOL,
|
|
5583
|
+
MODEL_GPT_6_LUNA,
|
|
5110
5584
|
MODEL_GPT_5_6_SOL,
|
|
5111
5585
|
MODEL_GPT_5_6_TERRA,
|
|
5112
5586
|
MODEL_GPT_5_6_LUNA,
|
|
@@ -6035,6 +6509,7 @@ If it's in another language, summarize in that language.
|
|
|
6035
6509
|
getSupportedModels() {
|
|
6036
6510
|
return [
|
|
6037
6511
|
MODEL_GROK_4_6,
|
|
6512
|
+
MODEL_GROK_4_7,
|
|
6038
6513
|
MODEL_GROK_4_5,
|
|
6039
6514
|
MODEL_GROK_4_3,
|
|
6040
6515
|
MODEL_GROK_4_20_REASONING,
|
|
@@ -6553,7 +7028,7 @@ If it's in another language, summarize in that language.
|
|
|
6553
7028
|
mcp: MCP_SUPPORTED_PROVIDERS.has(providerName),
|
|
6554
7029
|
jsonMode: JSON_MODE_SUPPORTED_PROVIDERS.has(providerName),
|
|
6555
7030
|
responseLength: true,
|
|
6556
|
-
reasoningEffort: providerName === "openai" && model === MODEL_GPT_6_ASTRA ? ["low", "medium", "high", "xhigh", "max"] : providerName === "claude" && model ? [...getClaudeSupportedReasoningEfforts(model)] : providerName === "gemini" && model ? [...getGeminiSupportedReasoningEfforts(model)] : providerName === "kimi" && model ? [...getKimiSupportedReasoningEfforts(model)] : providerName === "deepseek" && model ? [...getDeepSeekSupportedReasoningEfforts(model)] : providerName === "openrouter" && model ? [...getOpenRouterSupportedReasoningEfforts(model)] : providerName === "xai" && model ? [...getXaiSupportedReasoningEfforts(model)] : providerName === "zai" && model ? [...getZaiSupportedReasoningEfforts(model)] : REASONING_EFFORT_BY_PROVIDER[providerName] ?? []
|
|
7031
|
+
reasoningEffort: providerName === "openai" && model === MODEL_GPT_6_ASTRA ? ["low", "medium", "high", "xhigh", "max"] : providerName === "openai" && model === MODEL_GPT_6_SOL ? ["none", "low", "medium", "high", "xhigh", "max"] : providerName === "openai" && model === MODEL_GPT_6_LUNA ? ["none", "low", "medium", "high", "xhigh", "max"] : providerName === "claude" && model ? [...getClaudeSupportedReasoningEfforts(model)] : providerName === "gemini" && model ? [...getGeminiSupportedReasoningEfforts(model)] : providerName === "kimi" && model ? [...getKimiSupportedReasoningEfforts(model)] : providerName === "deepseek" && model ? [...getDeepSeekSupportedReasoningEfforts(model)] : providerName === "openrouter" && model ? [...getOpenRouterSupportedReasoningEfforts(model)] : providerName === "xai" && model ? [...getXaiSupportedReasoningEfforts(model)] : providerName === "zai" && model ? [...getZaiSupportedReasoningEfforts(model)] : REASONING_EFFORT_BY_PROVIDER[providerName] ?? []
|
|
6557
7032
|
};
|
|
6558
7033
|
}
|
|
6559
7034
|
/**
|