@aituber-onair/chat 0.13.0 → 0.15.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 +90 -4
- package/README.md +87 -4
- package/dist/cjs/constants/gemini.d.ts +3 -0
- package/dist/cjs/constants/gemini.d.ts.map +1 -1
- package/dist/cjs/constants/gemini.js +7 -1
- package/dist/cjs/constants/gemini.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/services/ChatServiceFactory.d.ts +2 -2
- package/dist/cjs/services/ChatServiceFactory.d.ts.map +1 -1
- package/dist/cjs/services/ChatServiceFactory.js.map +1 -1
- package/dist/cjs/services/providers/ChatServiceProvider.d.ts +9 -2
- package/dist/cjs/services/providers/ChatServiceProvider.d.ts.map +1 -1
- package/dist/cjs/services/providers/gemini/GeminiChatService.d.ts.map +1 -1
- package/dist/cjs/services/providers/gemini/GeminiChatService.js +7 -4
- package/dist/cjs/services/providers/gemini/GeminiChatService.js.map +1 -1
- package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.d.ts.map +1 -1
- package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.js +3 -0
- package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.js.map +1 -1
- package/dist/cjs/services/providers/index.d.ts +2 -1
- package/dist/cjs/services/providers/index.d.ts.map +1 -1
- package/dist/cjs/services/providers/index.js +2 -0
- package/dist/cjs/services/providers/index.js.map +1 -1
- package/dist/cjs/services/providers/openai/OpenAIChatService.d.ts +1 -1
- package/dist/cjs/services/providers/openai/OpenAIChatService.d.ts.map +1 -1
- package/dist/cjs/services/providers/openai/OpenAIChatService.js +31 -12
- 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 +1 -1
- package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
- package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts +21 -0
- package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts.map +1 -0
- package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js +56 -0
- package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js.map +1 -0
- package/dist/esm/constants/gemini.d.ts +3 -0
- package/dist/esm/constants/gemini.d.ts.map +1 -1
- package/dist/esm/constants/gemini.js +6 -0
- package/dist/esm/constants/gemini.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/services/ChatServiceFactory.d.ts +2 -2
- package/dist/esm/services/ChatServiceFactory.d.ts.map +1 -1
- package/dist/esm/services/ChatServiceFactory.js.map +1 -1
- package/dist/esm/services/providers/ChatServiceProvider.d.ts +9 -2
- package/dist/esm/services/providers/ChatServiceProvider.d.ts.map +1 -1
- package/dist/esm/services/providers/gemini/GeminiChatService.d.ts.map +1 -1
- package/dist/esm/services/providers/gemini/GeminiChatService.js +7 -4
- package/dist/esm/services/providers/gemini/GeminiChatService.js.map +1 -1
- package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.d.ts.map +1 -1
- package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.js +4 -1
- package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.js.map +1 -1
- package/dist/esm/services/providers/index.d.ts +2 -1
- package/dist/esm/services/providers/index.d.ts.map +1 -1
- package/dist/esm/services/providers/index.js +2 -0
- package/dist/esm/services/providers/index.js.map +1 -1
- package/dist/esm/services/providers/openai/OpenAIChatService.d.ts +1 -1
- package/dist/esm/services/providers/openai/OpenAIChatService.d.ts.map +1 -1
- package/dist/esm/services/providers/openai/OpenAIChatService.js +31 -12
- 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 +1 -1
- package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
- package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts +21 -0
- package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts.map +1 -0
- package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js +52 -0
- package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js.map +1 -0
- package/dist/umd/aituber-onair-chat.js +106 -13
- package/dist/umd/aituber-onair-chat.min.js +6 -6
- package/package.json +3 -1
|
@@ -72,6 +72,9 @@ var AITuberOnAirChat = (() => {
|
|
|
72
72
|
MODEL_GEMINI_2_5_FLASH_LITE: () => MODEL_GEMINI_2_5_FLASH_LITE,
|
|
73
73
|
MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17: () => MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17,
|
|
74
74
|
MODEL_GEMINI_2_5_PRO: () => MODEL_GEMINI_2_5_PRO,
|
|
75
|
+
MODEL_GEMINI_3_1_PRO_PREVIEW: () => MODEL_GEMINI_3_1_PRO_PREVIEW,
|
|
76
|
+
MODEL_GEMINI_3_FLASH_PREVIEW: () => MODEL_GEMINI_3_FLASH_PREVIEW,
|
|
77
|
+
MODEL_GEMINI_3_PRO_PREVIEW: () => MODEL_GEMINI_3_PRO_PREVIEW,
|
|
75
78
|
MODEL_GLM_4_6: () => MODEL_GLM_4_6,
|
|
76
79
|
MODEL_GLM_4_6V: () => MODEL_GLM_4_6V,
|
|
77
80
|
MODEL_GLM_4_6V_FLASH: () => MODEL_GLM_4_6V_FLASH,
|
|
@@ -117,6 +120,7 @@ var AITuberOnAirChat = (() => {
|
|
|
117
120
|
OPENROUTER_VISION_SUPPORTED_MODELS: () => OPENROUTER_VISION_SUPPORTED_MODELS,
|
|
118
121
|
OpenAIChatService: () => OpenAIChatService,
|
|
119
122
|
OpenAIChatServiceProvider: () => OpenAIChatServiceProvider,
|
|
123
|
+
OpenAICompatibleChatServiceProvider: () => OpenAICompatibleChatServiceProvider,
|
|
120
124
|
OpenRouterChatService: () => OpenRouterChatService,
|
|
121
125
|
OpenRouterChatServiceProvider: () => OpenRouterChatServiceProvider,
|
|
122
126
|
StreamTextAccumulator: () => StreamTextAccumulator,
|
|
@@ -194,6 +198,9 @@ var AITuberOnAirChat = (() => {
|
|
|
194
198
|
|
|
195
199
|
// src/constants/gemini.ts
|
|
196
200
|
var ENDPOINT_GEMINI_API = "https://generativelanguage.googleapis.com";
|
|
201
|
+
var MODEL_GEMINI_3_1_PRO_PREVIEW = "gemini-3.1-pro-preview";
|
|
202
|
+
var MODEL_GEMINI_3_PRO_PREVIEW = "gemini-3-pro-preview";
|
|
203
|
+
var MODEL_GEMINI_3_FLASH_PREVIEW = "gemini-3-flash-preview";
|
|
197
204
|
var MODEL_GEMINI_2_5_PRO = "gemini-2.5-pro";
|
|
198
205
|
var MODEL_GEMINI_2_5_FLASH = "gemini-2.5-flash";
|
|
199
206
|
var MODEL_GEMINI_2_5_FLASH_LITE = "gemini-2.5-flash-lite";
|
|
@@ -201,6 +208,9 @@ var AITuberOnAirChat = (() => {
|
|
|
201
208
|
var MODEL_GEMINI_2_0_FLASH = "gemini-2.0-flash";
|
|
202
209
|
var MODEL_GEMINI_2_0_FLASH_LITE = "gemini-2.0-flash-lite";
|
|
203
210
|
var GEMINI_VISION_SUPPORTED_MODELS = [
|
|
211
|
+
MODEL_GEMINI_3_1_PRO_PREVIEW,
|
|
212
|
+
MODEL_GEMINI_3_PRO_PREVIEW,
|
|
213
|
+
MODEL_GEMINI_3_FLASH_PREVIEW,
|
|
204
214
|
MODEL_GEMINI_2_5_PRO,
|
|
205
215
|
MODEL_GEMINI_2_5_FLASH,
|
|
206
216
|
MODEL_GEMINI_2_5_FLASH_LITE,
|
|
@@ -1714,13 +1724,16 @@ If it's in another language, summarize in that language.
|
|
|
1714
1724
|
};
|
|
1715
1725
|
const isLite = /flash[-_]lite/.test(model);
|
|
1716
1726
|
const isGemini25 = /gemini-2\.5/.test(model);
|
|
1717
|
-
const
|
|
1727
|
+
const isGemini3Preview = /^gemini-3(?:\.[0-9]+)?-.*preview/.test(model);
|
|
1728
|
+
const requiresV1beta = isLite || isGemini25 || isGemini3Preview;
|
|
1729
|
+
const firstVer = requiresV1beta ? "v1beta" : "v1";
|
|
1718
1730
|
const tryApi = async () => {
|
|
1719
1731
|
try {
|
|
1720
1732
|
const payload = firstVer === "v1" ? body : this.adaptKeysForApi(body);
|
|
1721
1733
|
return await fetchOnce(firstVer, payload);
|
|
1722
1734
|
} catch (e) {
|
|
1723
|
-
|
|
1735
|
+
const looksLikeVersionMismatch = /Unknown name|Cannot find field|404/.test(e?.message || "") || e?.status === 404;
|
|
1736
|
+
if (!requiresV1beta && looksLikeVersionMismatch) {
|
|
1724
1737
|
return await fetchOnce("v1beta", this.adaptKeysForApi(body));
|
|
1725
1738
|
}
|
|
1726
1739
|
throw e;
|
|
@@ -2027,6 +2040,9 @@ If it's in another language, summarize in that language.
|
|
|
2027
2040
|
*/
|
|
2028
2041
|
getSupportedModels() {
|
|
2029
2042
|
return [
|
|
2043
|
+
MODEL_GEMINI_3_1_PRO_PREVIEW,
|
|
2044
|
+
MODEL_GEMINI_3_PRO_PREVIEW,
|
|
2045
|
+
MODEL_GEMINI_3_FLASH_PREVIEW,
|
|
2030
2046
|
MODEL_GEMINI_2_5_PRO,
|
|
2031
2047
|
MODEL_GEMINI_2_5_FLASH,
|
|
2032
2048
|
MODEL_GEMINI_2_5_FLASH_LITE,
|
|
@@ -2317,9 +2333,8 @@ If it's in another language, summarize in that language.
|
|
|
2317
2333
|
* @param model Name of the model to use
|
|
2318
2334
|
* @param visionModel Name of the vision model
|
|
2319
2335
|
*/
|
|
2320
|
-
constructor(apiKey, model = MODEL_GPT_4O_MINI, visionModel = MODEL_GPT_4O_MINI, tools, endpoint = ENDPOINT_OPENAI_CHAT_COMPLETIONS_API, mcpServers = [], responseLength, verbosity, reasoning_effort, enableReasoningSummary = false) {
|
|
2321
|
-
|
|
2322
|
-
this.provider = "openai";
|
|
2336
|
+
constructor(apiKey, model = MODEL_GPT_4O_MINI, visionModel = MODEL_GPT_4O_MINI, tools, endpoint = ENDPOINT_OPENAI_CHAT_COMPLETIONS_API, mcpServers = [], responseLength, verbosity, reasoning_effort, enableReasoningSummary = false, provider = "openai", validateVisionModel = true) {
|
|
2337
|
+
this.provider = provider;
|
|
2323
2338
|
this.apiKey = apiKey;
|
|
2324
2339
|
this.model = model;
|
|
2325
2340
|
this.tools = tools || [];
|
|
@@ -2329,7 +2344,7 @@ If it's in another language, summarize in that language.
|
|
|
2329
2344
|
this.verbosity = verbosity;
|
|
2330
2345
|
this.reasoning_effort = reasoning_effort;
|
|
2331
2346
|
this.enableReasoningSummary = enableReasoningSummary;
|
|
2332
|
-
if (!VISION_SUPPORTED_MODELS.includes(visionModel)) {
|
|
2347
|
+
if (validateVisionModel && !VISION_SUPPORTED_MODELS.includes(visionModel)) {
|
|
2333
2348
|
throw new Error(
|
|
2334
2349
|
`Model ${visionModel} does not support vision capabilities.`
|
|
2335
2350
|
);
|
|
@@ -2464,9 +2479,12 @@ If it's in another language, summarize in that language.
|
|
|
2464
2479
|
}
|
|
2465
2480
|
async callOpenAI(messages, model, stream = false, maxTokens) {
|
|
2466
2481
|
const body = this.buildRequestBody(messages, model, stream, maxTokens);
|
|
2467
|
-
const
|
|
2468
|
-
|
|
2469
|
-
|
|
2482
|
+
const headers = {};
|
|
2483
|
+
const shouldSendAuthorization = this.provider !== "openai-compatible" || this.apiKey.trim() !== "";
|
|
2484
|
+
if (shouldSendAuthorization) {
|
|
2485
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
2486
|
+
}
|
|
2487
|
+
const res = await ChatServiceHttpClient.post(this.endpoint, body, headers);
|
|
2470
2488
|
return res;
|
|
2471
2489
|
}
|
|
2472
2490
|
/**
|
|
@@ -2479,11 +2497,19 @@ If it's in another language, summarize in that language.
|
|
|
2479
2497
|
model,
|
|
2480
2498
|
stream
|
|
2481
2499
|
};
|
|
2482
|
-
const tokenLimit = maxTokens !== void 0 ? maxTokens : getMaxTokensForResponseLength(this.responseLength);
|
|
2500
|
+
const tokenLimit = maxTokens !== void 0 ? maxTokens : this.provider === "openai-compatible" ? this.responseLength !== void 0 ? getMaxTokensForResponseLength(this.responseLength) : void 0 : getMaxTokensForResponseLength(this.responseLength);
|
|
2483
2501
|
if (isResponsesAPI) {
|
|
2484
|
-
|
|
2502
|
+
if (tokenLimit !== void 0) {
|
|
2503
|
+
body.max_output_tokens = tokenLimit;
|
|
2504
|
+
}
|
|
2485
2505
|
} else {
|
|
2486
|
-
|
|
2506
|
+
if (tokenLimit !== void 0) {
|
|
2507
|
+
if (this.provider === "openai-compatible") {
|
|
2508
|
+
body.max_tokens = tokenLimit;
|
|
2509
|
+
} else {
|
|
2510
|
+
body.max_completion_tokens = tokenLimit;
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2487
2513
|
}
|
|
2488
2514
|
if (isResponsesAPI) {
|
|
2489
2515
|
body.input = this.cleanMessagesForResponsesAPI(messages);
|
|
@@ -2772,6 +2798,71 @@ If it's in another language, summarize in that language.
|
|
|
2772
2798
|
}
|
|
2773
2799
|
};
|
|
2774
2800
|
|
|
2801
|
+
// src/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.ts
|
|
2802
|
+
var OpenAICompatibleChatServiceProvider = class {
|
|
2803
|
+
createChatService(options) {
|
|
2804
|
+
this.validateRequiredOptions(options);
|
|
2805
|
+
return new OpenAIChatService(
|
|
2806
|
+
options.apiKey?.trim() ?? "",
|
|
2807
|
+
options.model,
|
|
2808
|
+
options.visionModel ?? options.model,
|
|
2809
|
+
options.tools,
|
|
2810
|
+
options.endpoint,
|
|
2811
|
+
[],
|
|
2812
|
+
options.responseLength,
|
|
2813
|
+
options.verbosity,
|
|
2814
|
+
options.reasoning_effort,
|
|
2815
|
+
options.enableReasoningSummary,
|
|
2816
|
+
this.getProviderName(),
|
|
2817
|
+
false
|
|
2818
|
+
);
|
|
2819
|
+
}
|
|
2820
|
+
getProviderName() {
|
|
2821
|
+
return "openai-compatible";
|
|
2822
|
+
}
|
|
2823
|
+
/**
|
|
2824
|
+
* Model list depends on each compatible server implementation.
|
|
2825
|
+
*/
|
|
2826
|
+
getSupportedModels() {
|
|
2827
|
+
return [];
|
|
2828
|
+
}
|
|
2829
|
+
supportsVision() {
|
|
2830
|
+
return false;
|
|
2831
|
+
}
|
|
2832
|
+
getDefaultModel() {
|
|
2833
|
+
return "local-model";
|
|
2834
|
+
}
|
|
2835
|
+
validateRequiredOptions(options) {
|
|
2836
|
+
if (options.mcpServers !== void 0) {
|
|
2837
|
+
throw new Error(
|
|
2838
|
+
"openai-compatible provider does not support mcpServers."
|
|
2839
|
+
);
|
|
2840
|
+
}
|
|
2841
|
+
const endpoint = options.endpoint?.trim();
|
|
2842
|
+
if (!endpoint) {
|
|
2843
|
+
throw new Error(
|
|
2844
|
+
"openai-compatible provider requires endpoint (full URL)."
|
|
2845
|
+
);
|
|
2846
|
+
}
|
|
2847
|
+
let endpointUrl;
|
|
2848
|
+
try {
|
|
2849
|
+
endpointUrl = new URL(endpoint);
|
|
2850
|
+
} catch {
|
|
2851
|
+
throw new Error(
|
|
2852
|
+
"openai-compatible provider requires endpoint to be a full URL."
|
|
2853
|
+
);
|
|
2854
|
+
}
|
|
2855
|
+
if (endpointUrl.protocol !== "http:" && endpointUrl.protocol !== "https:") {
|
|
2856
|
+
throw new Error(
|
|
2857
|
+
"openai-compatible provider requires endpoint to be a full URL."
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
if (!options.model?.trim()) {
|
|
2861
|
+
throw new Error("openai-compatible provider requires model.");
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
};
|
|
2865
|
+
|
|
2775
2866
|
// src/services/providers/openai/OpenAIChatServiceProvider.ts
|
|
2776
2867
|
var OpenAIChatServiceProvider = class {
|
|
2777
2868
|
/**
|
|
@@ -2810,7 +2901,8 @@ If it's in another language, summarize in that language.
|
|
|
2810
2901
|
optimizedOptions.responseLength,
|
|
2811
2902
|
optimizedOptions.verbosity,
|
|
2812
2903
|
optimizedOptions.reasoning_effort,
|
|
2813
|
-
optimizedOptions.enableReasoningSummary
|
|
2904
|
+
optimizedOptions.enableReasoningSummary,
|
|
2905
|
+
this.getProviderName()
|
|
2814
2906
|
);
|
|
2815
2907
|
}
|
|
2816
2908
|
/**
|
|
@@ -3508,6 +3600,7 @@ If it's in another language, summarize in that language.
|
|
|
3508
3600
|
// src/services/providers/index.ts
|
|
3509
3601
|
var DEFAULT_CHAT_SERVICE_PROVIDERS = [
|
|
3510
3602
|
new OpenAIChatServiceProvider(),
|
|
3603
|
+
new OpenAICompatibleChatServiceProvider(),
|
|
3511
3604
|
new GeminiChatServiceProvider(),
|
|
3512
3605
|
new ClaudeChatServiceProvider(),
|
|
3513
3606
|
new OpenRouterChatServiceProvider(),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var AITuberOnAirChat=(()=>{var
|
|
1
|
+
"use strict";var AITuberOnAirChat=(()=>{var st=Object.defineProperty;var Gt=Object.getOwnPropertyDescriptor;var Ft=Object.getOwnPropertyNames;var Ut=Object.prototype.hasOwnProperty;var Ht=(n,e)=>{for(var t in e)st(n,t,{get:e[t],enumerable:!0})},Wt=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Ft(e))!Ut.call(n,s)&&s!==t&&st(n,s,{get:()=>e[s],enumerable:!(o=Gt(e,s))||o.enumerable});return n};var Bt=n=>Wt(st({},"__esModule",{value:!0}),n);var Qt={};Ht(Qt,{CHAT_RESPONSE_LENGTH:()=>V,CLAUDE_VISION_SUPPORTED_MODELS:()=>ce,ChatServiceFactory:()=>re,ChatServiceHttpClient:()=>_,ClaudeChatService:()=>q,ClaudeChatServiceProvider:()=>z,DEFAULT_MAX_TOKENS:()=>Et,DEFAULT_SUMMARY_PROMPT_TEMPLATE:()=>zt,DEFAULT_VISION_PROMPT:()=>qt,EMOTION_TAG_CLEANUP_REGEX:()=>St,EMOTION_TAG_REGEX:()=>Dt,ENDPOINT_CLAUDE_API:()=>ct,ENDPOINT_GEMINI_API:()=>pt,ENDPOINT_KIMI_CHAT_COMPLETIONS_API:()=>K,ENDPOINT_OPENAI_CHAT_COMPLETIONS_API:()=>G,ENDPOINT_OPENAI_RESPONSES_API:()=>y,ENDPOINT_OPENROUTER_API:()=>ht,ENDPOINT_ZAI_CHAT_COMPLETIONS_API:()=>me,EmotionParser:()=>$,GEMINI_VISION_SUPPORTED_MODELS:()=>pe,GPT5_PRESETS:()=>yt,GPT_5_MODELS:()=>Pt,GeminiChatService:()=>J,GeminiChatServiceProvider:()=>Z,HttpError:()=>A,KIMI_VISION_SUPPORTED_MODELS:()=>Lt,KimiChatService:()=>X,KimiChatServiceProvider:()=>Y,MAX_TOKENS_BY_LENGTH:()=>bt,MODEL_ANTHROPIC_CLAUDE_3_5_SONNET:()=>mt,MODEL_ANTHROPIC_CLAUDE_3_7_SONNET:()=>qe,MODEL_ANTHROPIC_CLAUDE_4_5_HAIKU:()=>ze,MODEL_ANTHROPIC_CLAUDE_OPUS_4:()=>je,MODEL_ANTHROPIC_CLAUDE_SONNET_4:()=>$e,MODEL_CLAUDE_3_5_HAIKU:()=>xe,MODEL_CLAUDE_3_5_SONNET:()=>Ie,MODEL_CLAUDE_3_7_SONNET:()=>Le,MODEL_CLAUDE_3_HAIKU:()=>S,MODEL_CLAUDE_4_5_HAIKU:()=>Ae,MODEL_CLAUDE_4_5_OPUS:()=>we,MODEL_CLAUDE_4_5_SONNET:()=>Re,MODEL_CLAUDE_4_6_OPUS:()=>ke,MODEL_CLAUDE_4_6_SONNET:()=>Ne,MODEL_CLAUDE_4_OPUS:()=>De,MODEL_CLAUDE_4_SONNET:()=>be,MODEL_GEMINI_2_0_FLASH:()=>Pe,MODEL_GEMINI_2_0_FLASH_LITE:()=>D,MODEL_GEMINI_2_5_FLASH:()=>ye,MODEL_GEMINI_2_5_FLASH_LITE:()=>Se,MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17:()=>Te,MODEL_GEMINI_2_5_PRO:()=>Ee,MODEL_GEMINI_3_1_PRO_PREVIEW:()=>Me,MODEL_GEMINI_3_FLASH_PREVIEW:()=>Oe,MODEL_GEMINI_3_PRO_PREVIEW:()=>Ce,MODEL_GLM_4_6:()=>Ct,MODEL_GLM_4_6V:()=>Qe,MODEL_GLM_4_6V_FLASH:()=>k,MODEL_GLM_4_6V_FLASHX:()=>et,MODEL_GLM_4_7:()=>W,MODEL_GLM_4_7_FLASH:()=>Mt,MODEL_GLM_4_7_FLASHX:()=>vt,MODEL_GLM_5:()=>ft,MODEL_GOOGLE_GEMINI_2_5_FLASH:()=>Ze,MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE_PREVIEW_09_2025:()=>Xe,MODEL_GOOGLE_GEMINI_2_5_PRO:()=>Je,MODEL_GPT_4O:()=>fe,MODEL_GPT_4O_MINI:()=>N,MODEL_GPT_4_1:()=>de,MODEL_GPT_4_1_MINI:()=>_e,MODEL_GPT_4_1_NANO:()=>ge,MODEL_GPT_4_5_PREVIEW:()=>ve,MODEL_GPT_5:()=>ae,MODEL_GPT_5_1:()=>b,MODEL_GPT_5_MINI:()=>ne,MODEL_GPT_5_NANO:()=>F,MODEL_GPT_OSS_20B_FREE:()=>R,MODEL_KIMI_K2_5:()=>T,MODEL_MOONSHOTAI_KIMI_K2_5:()=>Ve,MODEL_O1:()=>nt,MODEL_O1_MINI:()=>rt,MODEL_O3_MINI:()=>it,MODEL_OPENAI_GPT_4O:()=>We,MODEL_OPENAI_GPT_4_1_MINI:()=>Be,MODEL_OPENAI_GPT_4_1_NANO:()=>Ke,MODEL_OPENAI_GPT_5_1_CHAT:()=>Ge,MODEL_OPENAI_GPT_5_1_CODEX:()=>Fe,MODEL_OPENAI_GPT_5_MINI:()=>Ue,MODEL_OPENAI_GPT_5_NANO:()=>He,MODEL_ZAI_GLM_4_5_AIR:()=>dt,MODEL_ZAI_GLM_4_5_AIR_FREE:()=>Ye,MODEL_ZAI_GLM_4_7_FLASH:()=>ut,OPENROUTER_CREDITS_THRESHOLD:()=>$t,OPENROUTER_FREE_DAILY_LIMIT_HIGH_CREDITS:()=>jt,OPENROUTER_FREE_DAILY_LIMIT_LOW_CREDITS:()=>Kt,OPENROUTER_FREE_MODELS:()=>he,OPENROUTER_FREE_RATE_LIMIT_PER_MINUTE:()=>_t,OPENROUTER_VISION_SUPPORTED_MODELS:()=>xt,OpenAIChatService:()=>w,OpenAIChatServiceProvider:()=>ee,OpenAICompatibleChatServiceProvider:()=>Q,OpenRouterChatService:()=>te,OpenRouterChatServiceProvider:()=>oe,StreamTextAccumulator:()=>g,VISION_SUPPORTED_MODELS:()=>le,ZAIChatService:()=>se,ZAIChatServiceProvider:()=>ie,ZAI_VISION_SUPPORTED_MODELS:()=>It,allowsReasoningMinimal:()=>lt,allowsReasoningNone:()=>at,buildOpenAICompatibleTools:()=>L,getMaxTokensForResponseLength:()=>C,installGASFetch:()=>kt,isGPT5Model:()=>U,isKimiVisionModel:()=>j,isOpenRouterFreeModel:()=>gt,isOpenRouterVisionModel:()=>H,isZaiToolStreamModel:()=>Ot,isZaiVisionModel:()=>B,parseOpenAICompatibleOneShot:()=>I,parseOpenAICompatibleTextStream:()=>P,parseOpenAICompatibleToolStream:()=>x,processChatWithOptionalTools:()=>f,resolveVisionModel:()=>O,runOnceText:()=>Yt,screenplayToText:()=>Xt,textToScreenplay:()=>Rt,textsToScreenplay:()=>Zt});var G="https://api.openai.com/v1/chat/completions",y="https://api.openai.com/v1/responses",F="gpt-5-nano",ne="gpt-5-mini",ae="gpt-5",b="gpt-5.1",de="gpt-4.1",_e="gpt-4.1-mini",ge="gpt-4.1-nano",N="gpt-4o-mini",fe="gpt-4o",it="o3-mini",rt="o1-mini",nt="o1",ve="gpt-4.5-preview",le=[F,ne,ae,b,de,_e,ge,N,fe,ve,"o1"],Pt=[F,ne,ae,b];function U(n){return Pt.includes(n)}function at(n){return n===b}function lt(n){return n!==b}var pt="https://generativelanguage.googleapis.com",Me="gemini-3.1-pro-preview",Ce="gemini-3-pro-preview",Oe="gemini-3-flash-preview",Ee="gemini-2.5-pro",ye="gemini-2.5-flash",Se="gemini-2.5-flash-lite",Te="gemini-2.5-flash-lite-preview-06-17",Pe="gemini-2.0-flash",D="gemini-2.0-flash-lite",pe=[Me,Ce,Oe,Ee,ye,Se,Te,Pe,D];var ct="https://api.anthropic.com/v1/messages",S="claude-3-haiku-20240307",xe="claude-3-5-haiku-20241022",Ie="claude-3-5-sonnet-20241022",Le="claude-3-7-sonnet-20250219",be="claude-4-sonnet-20250514",De="claude-4-opus-20250514",Re="claude-sonnet-4-5-20250929",Ae="claude-haiku-4-5-20251001",we="claude-opus-4-5-20251101",Ne="claude-sonnet-4-6",ke="claude-opus-4-6",ce=[S,xe,Ie,Le,be,De,Re,Ae,we,Ne,ke];var ht="https://openrouter.ai/api/v1/chat/completions",R="openai/gpt-oss-20b:free",Ve="moonshotai/kimi-k2.5",Ge="openai/gpt-5.1-chat",Fe="openai/gpt-5.1-codex",Ue="openai/gpt-5-mini",He="openai/gpt-5-nano",We="openai/gpt-4o",Be="openai/gpt-4.1-mini",Ke="openai/gpt-4.1-nano",je="anthropic/claude-opus-4",$e="anthropic/claude-sonnet-4",qe="anthropic/claude-3.7-sonnet",mt="anthropic/claude-3.5-sonnet",ze="anthropic/claude-haiku-4.5",Je="google/gemini-2.5-pro",Ze="google/gemini-2.5-flash",Xe="google/gemini-2.5-flash-lite-preview-09-2025",ut="z-ai/glm-4.7-flash",dt="z-ai/glm-4.5-air",Ye="z-ai/glm-4.5-air:free",he=[R,Ye],xt=[Ge,Fe,Ue,He,We,Be,Ke,je,$e,qe,ze,Je,Ze,Xe,Ve],_t=20,Kt=50,jt=1e3,$t=10;function gt(n){return he.some(e=>n.includes(e))}function H(n){return xt.some(e=>n.includes(e))}var me="https://api.z.ai/api/paas/v4/chat/completions",ft="glm-5",W="glm-4.7",vt="glm-4.7-FlashX",Mt="glm-4.7-Flash",Ct="glm-4.6",Qe="glm-4.6V",et="glm-4.6V-FlashX",k="glm-4.6V-Flash",It=[Qe,et,k];function B(n){return It.includes(n)}function Ot(n){return n.toLowerCase().startsWith("glm-4.6")}var K="https://api.moonshot.ai/v1/chat/completions",T="kimi-k2.5",Lt=[T];function j(n){return Lt.includes(n)}var V={VERY_SHORT:"veryShort",SHORT:"short",MEDIUM:"medium",LONG:"long",VERY_LONG:"veryLong",DEEP:"deep"},bt={[V.VERY_SHORT]:40,[V.SHORT]:100,[V.MEDIUM]:200,[V.LONG]:300,[V.VERY_LONG]:1e3,[V.DEEP]:5e3},Et=5e3,yt={casual:{reasoning_effort:"minimal",verbosity:"low",description:"Fast responses for casual chat, quick questions (GPT-4 like experience)"},balanced:{reasoning_effort:"medium",verbosity:"medium",description:"Balanced reasoning for business tasks, learning, general problem solving"},expert:{reasoning_effort:"high",verbosity:"high",description:"Deep reasoning for research, complex analysis, expert-level tasks"}};function C(n){return n?bt[n]??Et:Et}var qt="You are a friendly AI avatar. Comment on the situation based on the broadcast screen.",zt=`You are a skilled summarizing assistant.
|
|
2
2
|
Analyze the following conversation and produce a summary in the **same language** as the majority of the conversation:
|
|
3
3
|
- Summaries should highlight key points
|
|
4
4
|
- Stay concise (around {maxLength} characters if possible)
|
|
@@ -7,8 +7,8 @@ Analyze the following conversation and produce a summary in the **same language*
|
|
|
7
7
|
If the conversation is in Japanese, summarize in Japanese.
|
|
8
8
|
If it's in English, summarize in English.
|
|
9
9
|
If it's in another language, summarize in that language.
|
|
10
|
-
`;var A=class extends Error{constructor(t,o,s){super(`HTTP ${t}: ${o}`);this.status=t;this.statusText=o;this.body=s;this.name="HttpError"}},
|
|
11
|
-
`);s=l.pop()||"";for(let
|
|
12
|
-
`))!==-1;){let m=a.slice(0,c).trim();if(a=a.slice(c+1),!m.startsWith("data:"))continue;let u=m.slice(5).trim();if(u==="[DONE]")break;let p=JSON.parse(u);if(p.type==="content_block_delta"&&p.delta?.text&&(t(p.delta.text),i.push({type:"text",text:p.delta.text})),p.type==="content_block_start"&&p.content_block?.type==="tool_use"?r.set(p.index,{id:p.content_block.id,name:p.content_block.name,args:""}):p.type==="content_block_start"&&p.content_block?.type==="mcp_tool_use"?r.set(p.index,{id:p.content_block.id,name:p.content_block.name,args:"",server_name:p.content_block.server_name}):p.type==="content_block_start"&&p.content_block?.type==="tool_result"?i.push({type:"tool_result",tool_use_id:p.content_block.tool_use_id,content:p.content_block.content??""}):p.type==="content_block_start"&&p.content_block?.type==="mcp_tool_result"&&i.push({type:"mcp_tool_result",tool_use_id:p.content_block.tool_use_id,is_error:p.content_block.is_error??!1,content:p.content_block.content??[]}),p.type==="content_block_delta"&&p.delta?.type==="input_json_delta"){let d=r.get(p.index);d&&(d.args+=p.delta.partial_json||"")}if(p.type==="content_block_stop"&&r.has(p.index)){let{id:d,name:v,args:O,server_name:L}=r.get(p.index);L?i.push({type:"mcp_tool_use",id:d,name:v,server_name:L,input:JSON.parse(O||"{}")}):i.push({type:"tool_use",id:d,name:v,input:JSON.parse(O||"{}")}),r.delete(p.index)}}}return{blocks:i,stop_reason:i.some(l=>l.type==="tool_use"||l.type==="mcp_tool_use")?"tool_use":"end"}}async parsePureStream(e,t){let{blocks:o}=await this.parseStream(e,t);return o.filter(s=>s.type==="text").map(s=>s.text).join("")}parseOneShot(e){let t=[];return(e.content??[]).forEach(o=>{o.type==="text"?t.push({type:"text",text:o.text}):o.type==="tool_use"?t.push({type:"tool_use",id:o.id,name:o.name,input:o.input??{}}):o.type==="mcp_tool_use"?t.push({type:"mcp_tool_use",id:o.id,name:o.name,server_name:o.server_name,input:o.input??{}}):o.type==="tool_result"?t.push({type:"tool_result",tool_use_id:o.tool_use_id,content:o.content??""}):o.type==="mcp_tool_result"&&t.push({type:"mcp_tool_result",tool_use_id:o.tool_use_id,is_error:o.is_error??!1,content:o.content??[]})}),{blocks:t,stop_reason:t.some(o=>o.type==="tool_use"||o.type==="mcp_tool_use")?"tool_use":"end"}}async chatOnce(e,t=!0,o=()=>{},s){let i=await this.callClaude(e,this.model,t,s),r=t?await this.parseStream(i,o):this.parseOneShot(await i.json());return this.convertToStandardCompletion(r)}async visionChatOnce(e,t=!1,o=()=>{},s){let i=await this.callClaude(e,this.visionModel,t,s),r=t?await this.parseStream(i,o):this.parseOneShot(await i.json());return this.convertToStandardCompletion(r)}convertToStandardCompletion(e){return{blocks:e.blocks.filter(o=>o.type==="text"||o.type==="tool_use"||o.type==="tool_result"),stop_reason:e.stop_reason}}};var z=class{createChatService(e){let t=C({model:e.model,visionModel:e.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultModel(),supportsVisionForModel:o=>this.supportsVisionForModel(o),validate:"resolved"});return new $(e.apiKey,e.model||this.getDefaultModel(),t,e.tools??[],e.mcpServers??[],e.responseLength)}getProviderName(){return"claude"}getSupportedModels(){return[y,ye,Te,Se,Pe,xe,Ie,Le,De,be,Re]}getDefaultModel(){return y}supportsVision(){return!0}supportsVisionForModel(e){return pe.includes(e)}};var Xe=class{static async fetchToolSchemas(e){try{let t={"Content-Type":"application/json"};e.authorization_token&&(t.Authorization=`Bearer ${e.authorization_token}`);let s=await(await _.post(`${e.url}/tools`,{},t)).json();return Array.isArray(s.tools)?s.tools.map(i=>({name:`mcp_${e.name}_${i.name}`,description:i.description||`Tool from ${e.name} MCP server`,parameters:i.inputSchema||{type:"object",properties:{},required:[]}})):[{name:`mcp_${e.name}_search`,description:`Search using ${e.name} MCP server`,parameters:{type:"object",properties:{query:{type:"string",description:"Search query"}},required:["query"]}}]}catch(t){return console.warn(`Failed to fetch MCP schemas from ${e.name}:`,t),[{name:`mcp_${e.name}_search`,description:`Search using ${e.name} MCP server (schema fetch failed)`,parameters:{type:"object",properties:{query:{type:"string",description:"Search query"}},required:["query"]}}]}}static async fetchAllToolSchemas(e){let t=[];for(let o of e)try{let s=await this.fetchToolSchemas(o);t.push(...s)}catch(s){console.error(`Failed to fetch schemas from ${o.name}:`,s)}return t}};var q=class{constructor(e,t=b,o=b,s=[],i=[],r){this.provider="gemini";this.mcpToolSchemas=[];this.mcpSchemasInitialized=!1;this.callIdMap=new Map;if(this.apiKey=e,this.model=t,this.responseLength=r,!le.includes(o))throw new Error(`Model ${o} does not support vision capabilities.`);this.visionModel=o,this.tools=s,this.mcpServers=i}safeJsonParse(e){try{return JSON.parse(e)}catch{return e}}normalizeToolResult(e){return e===null?{content:null}:typeof e=="object"?e:{content:e}}adaptKeysForApi(e){let t={toolConfig:"tool_config",functionCallingConfig:"function_calling_config",functionDeclarations:"function_declarations",functionCall:"function_call",functionResponse:"function_response"};return Array.isArray(e)?e.map(o=>this.adaptKeysForApi(o)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([o,s])=>[t[o]??o,this.adaptKeysForApi(s)])):e}getModel(){return this.model}getVisionModel(){return this.visionModel}getMCPServers(){return this.mcpServers}addMCPServer(e){this.mcpServers.push(e),this.mcpSchemasInitialized=!1}removeMCPServer(e){this.mcpServers=this.mcpServers.filter(t=>t.name!==e),this.mcpSchemasInitialized=!1}hasMCPServers(){return this.mcpServers.length>0}async initializeMCPSchemas(){if(!(this.mcpSchemasInitialized||this.mcpServers.length===0))try{let e=new Promise((o,s)=>setTimeout(()=>s(new Error("MCP schema fetch timeout")),5e3)),t=Xe.fetchAllToolSchemas(this.mcpServers);this.mcpToolSchemas=await Promise.race([t,e]),this.mcpSchemasInitialized=!0}catch(e){console.warn("Failed to initialize MCP schemas, using fallback:",e),this.mcpToolSchemas=this.mcpServers.map(t=>({name:`mcp_${t.name}_search`,description:`Search using ${t.name} MCP server (fallback)`,parameters:{type:"object",properties:{query:{type:"string",description:"Search query"}},required:["query"]}})),this.mcpSchemasInitialized=!0}}async processChat(e,t,o){try{await f({hasTools:this.tools.length>0||this.mcpServers.length>0,runWithoutTools:async()=>{let s=await this.callGemini(e,this.model,!0),{blocks:i}=await this.parseStream(s,t);return g.getFullText(i)},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"Received functionCall. Use chatOnce() loop when tools are enabled."})}catch(s){throw console.error("Error in processChat:",s),s}}async processVisionChat(e,t,o){try{await f({hasTools:this.tools.length>0||this.mcpServers.length>0,runWithoutTools:async()=>{let s=await this.callGemini(e,this.visionModel,!0),{blocks:i}=await this.parseStream(s,t);return g.getFullText(i)},runWithTools:()=>this.visionChatOnce(e),onToolBlocks:s=>{s.filter(i=>i.type==="text").forEach(i=>t(i.text))},onCompleteResponse:o,toolErrorMessage:"Received functionCall. Use visionChatOnce() loop when tools are enabled."})}catch(s){throw console.error("Error in processVisionChat:",s),s}}convertMessagesToGeminiFormat(e){let t=[],o=null,s=[],i=()=>{o&&s.length&&(t.push({role:o,parts:[...s]}),s=[])};for(let r of e){let a=this.mapRoleToGemini(r.role);if(r.tool_calls){i();for(let l of r.tool_calls)this.callIdMap.set(l.id,l.function.name),t.push({role:"model",parts:[{functionCall:{name:l.function.name,args:JSON.parse(l.function.arguments||"{}")}}]});continue}if(r.role==="tool"){i();let l=r.name??this.callIdMap.get(r.tool_call_id)??"result";t.push({role:"user",parts:[{functionResponse:{name:l,response:this.normalizeToolResult(this.safeJsonParse(r.content))}}]});continue}a!==o&&i(),o=a,s.push({text:r.content})}return i(),t}async callGemini(e,t,o=!1,s){let a={contents:e.some(d=>Array.isArray(d.content)&&d.content.some(v=>v?.type==="image_url"||v?.inlineData))?await this.convertVisionMessagesToGeminiFormat(e):this.convertMessagesToGeminiFormat(e),generationConfig:{maxOutputTokens:s!==void 0?s:M(this.responseLength)}},l=[];if(this.tools.length>0&&l.push(...this.tools.map(d=>({name:d.name,description:d.description,parameters:d.parameters}))),this.mcpServers.length>0)try{await this.initializeMCPSchemas(),l.push(...this.mcpToolSchemas.map(d=>({name:d.name,description:d.description,parameters:d.parameters})))}catch(d){console.warn("MCP initialization failed, skipping MCP tools:",d)}l.length>0&&(a.tools=[{functionDeclarations:l}],a.toolConfig={functionCallingConfig:{mode:"AUTO"}});let h=async(d,v)=>{let O=o?"streamGenerateContent":"generateContent",L=o?"?alt=sse":"",Ye=`${rt}/${d}/models/${t}:${O}${L}${L?"&":"?"}key=${this.apiKey}`;return _.post(Ye,v)},c=/flash[-_]lite/.test(t),m=/gemini-2\.5/.test(t),u=c||m?"v1beta":"v1",p=async()=>{try{let d=u==="v1"?a:this.adaptKeysForApi(a);return await h(u,d)}catch(d){if(!(c||m)&&/Unknown name|Cannot find field|404/.test(d.message))return await h("v1beta",this.adaptKeysForApi(a));throw d}};try{return await p()}catch(d){throw d.body&&(console.error("Gemini API Error Details:",d.body),console.error("Request Body:",JSON.stringify(a,null,2))),d}}async convertVisionMessagesToGeminiFormat(e){let t=[],o=null,s=[];for(let i of e){let r=this.mapRoleToGemini(i.role);if(i.tool_calls){for(let a of i.tool_calls)t.push({role:"model",parts:[{functionCall:{name:a.function.name,args:JSON.parse(a.function.arguments||"{}")}}]});continue}if(i.role==="tool"){let a=i.name??this.callIdMap.get(i.tool_call_id)??"result";t.push({role:"user",parts:[{functionResponse:{name:a,response:this.normalizeToolResult(this.safeJsonParse(i.content))}}]});continue}if(r!==o&&s.length>0&&(t.push({role:o,parts:[...s]}),s=[]),o=r,typeof i.content=="string")s.push({text:i.content});else if(Array.isArray(i.content)){for(let a of i.content)if(a.type==="text")s.push({text:a.text});else if(a.type==="image_url")try{let h=await(await _.get(a.image_url.url)).blob(),c=await this.blobToBase64(h);s.push({inlineData:{mimeType:h.type||"image/jpeg",data:c.split(",")[1]}})}catch(l){throw console.error("Error processing image:",l),new Error(`Failed to process image: ${l.message}`)}}}return o&&s.length>0&&t.push({role:o,parts:[...s]}),t}blobToBase64(e){return new Promise((t,o)=>{let s=new FileReader;s.onloadend=()=>t(s.result),s.onerror=o,s.readAsDataURL(e)})}mapRoleToGemini(e){switch(e){case"system":return"model";case"user":return"user";case"assistant":return"model";default:return"user"}}async parseStream(e,t){let o=e.body.getReader(),s=new TextDecoder,i=[],r=[],a="",l=c=>{if(!c||c==="[DONE]")return;let m;try{m=JSON.parse(c)}catch{return}for(let u of m.candidates??[])for(let p of u.content?.parts??[])p.text&&(t(p.text),g.addTextBlock(i,p.text)),p.functionCall&&r.push({type:"tool_use",id:this.genUUID(),name:p.functionCall.name,input:p.functionCall.args??{}}),p.functionResponse&&r.push({type:"tool_result",tool_use_id:p.functionResponse.name,content:JSON.stringify(p.functionResponse.response)})};for(;;){let{done:c,value:m}=await o.read();if(c)break;a+=s.decode(m,{stream:!0});let u;for(;(u=a.indexOf(`
|
|
13
|
-
`))!==-1;){let p=a.slice(0,u);if(a=a.slice(u+1),p.endsWith("\r")&&(p=p.slice(0,-1)),!p.trim()){l("");continue}p.startsWith("data:")&&(p=p.slice(5).trim()),p&&l(p)}}return a&&l(a),{blocks:[...i,...r],stop_reason:r.some(
|
|
14
|
-
`);a=d.pop()||"";for(let v=0;v<d.length;v++){let O=d[v].trim();if(O.startsWith("event:"))u=O.slice(6).trim();else if(O.startsWith("data:"))p=O.slice(5).trim();else if(O===""&&u&&p){try{let L=JSON.parse(p),Ye=this.handleResponsesSSEEvent(u,L,t,i,r)}catch{console.warn("Failed to parse SSE data:",p)}u="",p=""}}}let l=Array.from(r.values()).map(c=>({type:"tool_use",id:c.id,name:c.name,input:c.input||{}}));return{blocks:[...i,...l],stop_reason:l.length?"tool_use":"end"}}handleResponsesSSEEvent(e,t,o,s,i){switch(e){case"response.output_item.added":t.item?.type==="message"&&Array.isArray(t.item.content)?t.item.content.forEach(r=>{r.type==="output_text"&&r.text&&(o(r.text),g.append(s,r.text))}):t.item?.type==="function_call"&&i.set(t.item.id,{id:t.item.id,name:t.item.name,input:t.item.arguments?JSON.parse(t.item.arguments):{}});break;case"response.content_part.added":t.part?.type==="output_text"&&typeof t.part.text=="string"&&(o(t.part.text),g.append(s,t.part.text));break;case"response.output_text.delta":case"response.content_part.delta":{let r=typeof t.delta=="string"?t.delta:t.delta?.text??"";r&&(o(r),g.append(s,r))}break;case"response.output_text.done":case"response.content_part.done":break;case"response.completed":return"completed";case"response.reasoning.started":case"response.reasoning.delta":case"response.reasoning.done":break;default:break}}parseResponsesOneShot(e){let t=[];return e.output&&Array.isArray(e.output)&&e.output.forEach(o=>{o.type==="message"&&o.content&&o.content.forEach(s=>{s.type==="output_text"&&s.text&&t.push({type:"text",text:s.text})}),o.type==="function_call"&&t.push({type:"tool_use",id:o.id,name:o.name,input:o.arguments?JSON.parse(o.arguments):{}})}),{blocks:t,stop_reason:t.some(o=>o.type==="tool_use")?"tool_use":"end"}}};var Q=class{createChatService(e){let t=this.optimizeGPT5Options(e),o=C({model:t.model,visionModel:t.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultModel(),supportsVisionForModel:h=>this.supportsVisionForModel(h),validate:"resolved"}),s=t.tools,i=t.mcpServers??[],r=t.model||this.getDefaultModel(),a=!1;i.length>0?a=!0:F(r)&&(a=(t.gpt5EndpointPreference||"chat")==="responses");let l=t.endpoint||(a?E:V);return new Y(t.apiKey,r,o,s,l,i,t.responseLength,t.verbosity,t.reasoning_effort,t.enableReasoningSummary)}getProviderName(){return"openai"}getSupportedModels(){return[G,re,ne,D,ue,de,_e,w,ge,et,tt,"o1",fe]}getDefaultModel(){return G}supportsVision(){return!0}supportsVisionForModel(e){return ae.includes(e)}optimizeGPT5Options(e){let t=e.model||this.getDefaultModel();if(!F(t))return e;let o={...e};if(e.gpt5Preset){let s=Mt[e.gpt5Preset];o.reasoning_effort=s.reasoning_effort,o.verbosity=s.verbosity}else e.reasoning_effort||(o.reasoning_effort=this.getDefaultReasoningEffortForModel(t));return o.reasoning_effort=this.normalizeReasoningEffort(t,o.reasoning_effort),o}getDefaultReasoningEffortForModel(e){return e===D?"none":"medium"}normalizeReasoningEffort(e,t){if(t)return t==="none"&&!st(e)?this.getDefaultReasoningEffortForModel(e):t==="minimal"&&!it(e)?"none":t}};var ee=class{constructor(e,t=R,o=R,s,i=at,r,a,l,h,c,m){this.provider="openrouter";this.lastRequestTime=0;this.requestCount=0;this.apiKey=e,this.model=t,this.tools=s||[],this.endpoint=i,this.responseLength=r,this.appName=a,this.appUrl=l,this.reasoning_effort=h,this.includeReasoning=c,this.reasoningMaxTokens=m,this.visionModel=o}getModel(){return this.model}getVisionModel(){return this.visionModel}async applyRateLimiting(){if(!mt(this.model))return;let e=Date.now(),t=e-this.lastRequestTime;if(t>6e4&&(this.requestCount=0),this.requestCount>=ht){let o=6e4-t;o>0&&(console.log(`Rate limit reached for free tier. Waiting ${o}ms...`),await new Promise(s=>setTimeout(s,o)),this.requestCount=0)}this.lastRequestTime=e,this.requestCount++}async processChat(e,t,o){await this.applyRateLimiting(),await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callOpenRouter(e,this.model,!0);return this.handleStream(s,t)},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."})}async processVisionChat(e,t,o){if(!U(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);await this.applyRateLimiting();try{await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callOpenRouter(e,this.visionModel,!0);return this.handleStream(s,t)},runWithTools:()=>this.visionChatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processVisionChat received tool_calls. ChatProcessor must use visionChatOnce() loop when tools are enabled."})}catch(s){throw console.error("Error in processVisionChat:",s),s}}async chatOnce(e,t=!0,o=()=>{},s){await this.applyRateLimiting();let i=await this.callOpenRouter(e,this.model,t,s);return t?this.parseStream(i,o):this.parseOneShot(await i.json())}async visionChatOnce(e,t=!1,o=()=>{},s){if(!U(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);await this.applyRateLimiting();let i=await this.callOpenRouter(e,this.visionModel,t,s);return t?this.parseStream(i,o):this.parseOneShot(await i.json())}async callOpenRouter(e,t,o=!1,s){let i=this.buildRequestBody(e,t,o,s),r={Authorization:`Bearer ${this.apiKey}`};return this.appUrl&&(r["HTTP-Referer"]=this.appUrl),this.appName&&(r["X-Title"]=this.appName),await _.post(this.endpoint,i,r)}buildRequestBody(e,t,o,s){let i={model:t,messages:e,stream:o};if((s!==void 0?s:M(this.responseLength))&&console.warn("OpenRouter: Token limits are not supported for gpt-oss-20b model due to known issues. Using unlimited tokens instead."),this.reasoning_effort!==void 0||this.includeReasoning!==void 0||this.reasoningMaxTokens){if(i.reasoning={},this.reasoning_effort&&this.reasoning_effort!=="none"){let a=this.reasoning_effort==="minimal"?"low":this.reasoning_effort;i.reasoning.effort=a}(this.reasoning_effort==="none"||this.includeReasoning!==!0)&&(i.reasoning.exclude=!0),this.reasoningMaxTokens&&(i.reasoning.max_tokens=this.reasoningMaxTokens)}else i.reasoning={exclude:!0};return this.tools.length>0&&(i.tools=I(this.tools,"chat-completions"),i.tool_choice="auto"),i}async handleStream(e,t){return S(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}async parseStream(e,t){return P(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}parseOneShot(e){return x(e)}};var te=class{createChatService(e){let t=C({model:e.model,visionModel:e.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:e.model||this.getDefaultModel(),supportsVisionForModel:r=>this.supportsVisionForModel(r),validate:"explicit"}),o=e.tools,s=e.appName,i=e.appUrl;return new ee(e.apiKey,e.model||this.getDefaultModel(),t,o,e.endpoint,e.responseLength,s,i,e.reasoning_effort,e.includeReasoning,e.reasoningMaxTokens)}getProviderName(){return"openrouter"}getSupportedModels(){return[R,qe,we,Ne,ke,Ve,Ge,Fe,Ue,He,Be,We,lt,Ke,je,$e,ze,pt,ct,Ae]}getDefaultModel(){return R}supportsVision(){return this.getSupportedModels().some(e=>this.supportsVisionForModel(e))}supportsVisionForModel(e){return U(e)}getFreeModels(){return ce}isModelFree(e){return ce.includes(e)||e.endsWith(":free")}};var oe=class{constructor(e,t=H,o=N,s,i=he,r,a,l){this.provider="zai";this.apiKey=e,this.model=t,this.tools=s||[],this.endpoint=i,this.responseLength=r,this.responseFormat=a,this.thinking=l??{type:"disabled"},this.visionModel=o}getModel(){return this.model}getVisionModel(){return this.visionModel}async processChat(e,t,o){await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callZAI(e,this.model,!0);return this.handleStream(s,t)},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."})}async processVisionChat(e,t,o){if(!B(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callZAI(e,this.visionModel,!0);return this.handleStream(s,t)},runWithTools:()=>this.visionChatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processVisionChat received tool_calls. ChatProcessor must use visionChatOnce() loop when tools are enabled."})}async chatOnce(e,t=!0,o=()=>{},s){let i=await this.callZAI(e,this.model,t,s);return this.parseResponse(i,t,o)}async visionChatOnce(e,t=!1,o=()=>{},s){if(!B(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);let i=await this.callZAI(e,this.visionModel,t,s);return this.parseResponse(i,t,o)}async parseResponse(e,t,o){return t?this.parseStream(e,o):this.parseOneShot(await e.json())}async callZAI(e,t,o=!1,s){let i=this.buildRequestBody(e,t,o,s);return await _.post(this.endpoint,i,{Authorization:`Bearer ${this.apiKey}`})}buildRequestBody(e,t,o,s){let i={model:t,stream:o,messages:e},r=s!==void 0?s:M(this.responseLength);r!==void 0&&(i.max_tokens=r),this.responseFormat&&(i.response_format=this.responseFormat),this.thinking&&(i.thinking=this.thinking);let a=this.buildToolsDefinition();return a.length>0&&(i.tools=a,i.tool_choice="auto",o&&ft(t)&&(i.tool_stream=!0)),i}buildToolsDefinition(){return I(this.tools,"chat-completions")}async handleStream(e,t){return S(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}async parseStream(e,t){return P(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}parseOneShot(e){return x(e)}};var se=class{createChatService(e){let t=e.model||this.getDefaultModel(),o=C({model:t,visionModel:e.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultVisionModel(),supportsVisionForModel:r=>this.supportsVisionForModel(r),validate:"explicit"}),s=e.tools,i=e.thinking??{type:"disabled"};return new oe(e.apiKey,t,o,s,e.endpoint||he,e.responseLength,e.responseFormat,i)}getProviderName(){return"zai"}getSupportedModels(){return[ut,H,dt,_t,gt,Je,Ze,N]}getDefaultModel(){return H}getDefaultVisionModel(){return N}supportsVision(){return!0}supportsVisionForModel(e){return B(e)}};var Dt=[new Q,new J,new z,new te,new se,new X];var ie=class{static registerProvider(e){this.providers.set(e.getProviderName(),e)}static createChatService(e,t){let o=this.providers.get(e);if(!o)throw new Error(`Unknown chat provider: ${e}`);return o.createChatService(t)}static getProviders(){return this.providers}static getAvailableProviders(){return Array.from(this.providers.keys())}static getSupportedModels(e){let t=this.providers.get(e);return t?t.getSupportedModels():[]}};ie.providers=new Map;Dt.forEach(n=>ie.registerProvider(n));function bt(){_.setFetch(async(n,e={})=>{let t=(e.method||"GET").toString().toUpperCase(),o=e.headers,s={};if(Array.isArray(o))for(let[m,u]of o)s[m]=String(u);else if(o&&typeof o=="object")for(let[m,u]of Object.entries(o))s[m]=String(u);let i={method:t,headers:s,muteHttpExceptions:!0},r=e.body;typeof r=="string"?i.payload=r:r!=null&&(s["Content-Type"]||(s["Content-Type"]="application/json"),i.payload=JSON.stringify(r));let a=UrlFetchApp.fetch(n,i),l=a.getResponseCode(),h=a.getContentText();return{ok:l>=200&&l<300,status:l,statusText:String(l),text:async()=>h,json:async()=>h?JSON.parse(h):null}})}return Vt(zt);})();
|
|
10
|
+
`;var A=class extends Error{constructor(t,o,s){super(`HTTP ${t}: ${o}`);this.status=t;this.statusText=o;this.body=s;this.name="HttpError"}},ue=class ue{static setFetch(e){this.fetchImpl=e}static async post(e,t,o={},s={}){let{timeout:i=3e4,retries:r=0,retryDelay:a=1e3}=s,c={...{"Content-Type":"application/json"},...o},h=null;for(let m=0;m<=r;m++)try{let u=typeof AbortController<"u",p=u?new AbortController:void 0,v=u?setTimeout(()=>p.abort(),i):void 0,M=await ue.fetchImpl(e,{method:"POST",headers:c,body:typeof t=="string"?t:JSON.stringify(t),...p?{signal:p.signal}:{}});if(v&&clearTimeout(v),!M.ok){let d=await M.text();throw new A(M.status,M.statusText,d)}return M}catch(u){if(h=u,u instanceof A&&u.status>=400&&u.status<500)throw u;if(u instanceof Error&&u.name==="AbortError")throw new Error(`Request timeout after ${i}ms`);m<r&&await new Promise(p=>setTimeout(p,a*(m+1)))}throw h||new Error("Request failed")}static async handleErrorResponse(e){let t=await e.text();throw new A(e.status,e.statusText,t)}static async get(e,t={},o={}){let{timeout:s=3e4,retries:i=0,retryDelay:r=1e3}=o,a=null;for(let l=0;l<=i;l++)try{let c=typeof AbortController<"u",h=c?new AbortController:void 0,m=c?setTimeout(()=>h.abort(),s):void 0,u=await ue.fetchImpl(e,{method:"GET",headers:t,...h?{signal:h.signal}:{}});if(m&&clearTimeout(m),!u.ok){let p=await u.text();throw new A(u.status,u.statusText,p)}return u}catch(c){if(a=c,c instanceof A&&c.status>=400&&c.status<500)throw c;if(c instanceof Error&&c.name==="AbortError")throw new Error(`Request timeout after ${s}ms`);l<i&&await new Promise(h=>setTimeout(h,r*(l+1)))}throw a||new Error("Request failed")}};ue.fetchImpl=(e,t)=>fetch(e,t);var _=ue;var g=class{static append(e,t){if(!t)return;let o=e[e.length-1];o&&o.type==="text"?o.text+=t:e.push({type:"text",text:t})}static getFullText(e){return e.filter(t=>t.type==="text").map(t=>t.text).join("")}static addTextBlock(e,t){t&&e.push({type:"text",text:t})}};var Jt=["happy","sad","angry","surprised","neutral"],Dt=/\[([a-z]+)\]/i,St=/\[[a-z]+\]\s*/gi,$=class{static extractEmotion(e){let t=e.match(Dt);if(t){let o=t[1].toLowerCase(),s=e.replace(St,"").trim();return{emotion:o,cleanText:s}}return{cleanText:e}}static isValidEmotion(e){return Jt.includes(e)}static cleanEmotionTags(e){return e.replace(St,"").trim()}static addEmotionTag(e,t){return`[${e}] ${t}`}};function Rt(n){let{emotion:e,cleanText:t}=$.extractEmotion(n);return e?{emotion:e,text:t}:{text:t}}function Zt(n){return n.map(e=>Rt(e))}function Xt(n){return n.emotion?$.addEmotionTag(n.emotion,n.text):n.text}async function Yt(n,e){let{blocks:t}=await n.chatOnce(e,!1,()=>{});return g.getFullText(t)}var At=(n,e)=>{try{return JSON.parse(n)}catch(t){if(e){e(n,t);return}throw t}},wt=async(n,e)=>{let t=n.body?.getReader();if(!t)throw new Error("Response body is null.");let o=new TextDecoder,s="",i=!1;for(;!i;){let{done:r,value:a}=await t.read();if(r)break;s+=o.decode(a,{stream:!0});let l=s.split(`
|
|
11
|
+
`);s=l.pop()||"";for(let c of l){let h=c.trim();if(!h||h.startsWith(":")||!h.startsWith("data:"))continue;let m=h.slice(5).trim();if(m==="[DONE]"){i=!0;break}e(m)}}};async function P(n,e,t={}){let o="";return await wt(n,s=>{let i=At(s,t.onJsonError);if(!i)return;let r=i.choices?.[0]?.delta?.content||"";r&&(e(r),o+=r)}),o}async function x(n,e,t={}){let o=[],s=new Map,i=t.appendTextBlock??g.append;await wt(n,l=>{let c=At(l,t.onJsonError);if(!c)return;let h=c.choices?.[0]?.delta;h?.content&&(e(h.content),i(o,h.content)),h?.tool_calls&&h.tool_calls.forEach(m=>{let u=s.get(m.index)??{id:m.id,name:m.function?.name,args:""};u.args+=m.function?.arguments||"",s.set(m.index,u)})});let r=Array.from(s.entries()).sort((l,c)=>l[0]-c[0]).map(([l,c])=>({type:"tool_use",id:c.id,name:c.name,input:JSON.parse(c.args||"{}")}));return{blocks:[...o,...r],stop_reason:r.length?"tool_use":"end"}}function I(n){let e=n?.choices?.[0],t=[];return e?.message?.tool_calls?.length?e.message.tool_calls.forEach(o=>t.push({type:"tool_use",id:o.id,name:o.function?.name,input:JSON.parse(o.function?.arguments||"{}")})):e?.message?.content&&t.push({type:"text",text:e.message.content}),{blocks:t,stop_reason:e?.finish_reason==="tool_calls"||t.some(o=>o.type==="tool_use")?"tool_use":"end"}}var L=(n,e="chat-completions")=>n.length===0?[]:e==="responses"?n.map(t=>({type:"function",name:t.name,description:t.description,parameters:t.parameters})):n.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.parameters}}));async function f(n){if(!n.hasTools){let t=await n.runWithoutTools();await n.onCompleteResponse(t);return}let e=await n.runWithTools();if(n.onToolBlocks&&n.onToolBlocks(e.blocks),e.stop_reason==="end"){let t=g.getFullText(e.blocks);await n.onCompleteResponse(t);return}throw new Error(n.toolErrorMessage)}var O=n=>{let e=n.model??n.defaultModel,t=n.visionModel??(n.supportsVisionForModel(e)?e:n.defaultVisionModel);if(n.validate==="explicit"&&n.visionModel&&!n.supportsVisionForModel(n.visionModel))throw new Error(`Model ${n.visionModel} does not support vision capabilities.`);if(n.validate==="resolved"&&!n.supportsVisionForModel(t))throw new Error(`Model ${t} does not support vision capabilities.`);return t};var q=class{constructor(e,t=S,o=S,s=[],i=[],r){this.provider="claude";if(this.apiKey=e,this.model=t||S,this.visionModel=o||S,this.tools=s,this.mcpServers=i,this.responseLength=r,!ce.includes(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`)}getModel(){return this.model}getVisionModel(){return this.visionModel}getMCPServers(){return this.mcpServers}addMCPServer(e){this.mcpServers.push(e)}removeMCPServer(e){this.mcpServers=this.mcpServers.filter(t=>t.name!==e)}hasMCPServers(){return this.mcpServers.length>0}async processChat(e,t,o){await f({hasTools:this.tools.length>0||this.mcpServers.length>0,runWithoutTools:async()=>{let s=await this.callClaude(e,this.model,!0);return this.parsePureStream(s,t)},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."})}async processVisionChat(e,t,o){await f({hasTools:this.tools.length>0||this.mcpServers.length>0,runWithoutTools:async()=>{let s=await this.callClaude(e,this.visionModel,!0);return this.parsePureStream(s,t)},runWithTools:()=>this.visionChatOnce(e),onCompleteResponse:o,toolErrorMessage:"processVisionChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."})}convertMessagesToClaudeFormat(e){return e.map(t=>({role:this.mapRoleToClaude(t.role),content:t.content}))}convertVisionMessagesToClaudeFormat(e){return e.map(t=>{if(typeof t.content=="string")return{role:this.mapRoleToClaude(t.role),content:[{type:"text",text:t.content}]};if(Array.isArray(t.content)){let o=t.content.map(s=>{if(s.type==="image_url"){if(s.image_url.url.startsWith("data:")){let i=s.image_url.url.match(/^data:([^;]+);base64,(.+)$/);return i?{type:"image",source:{type:"base64",media_type:i[1],data:i[2]}}:null}return{type:"image",source:{type:"url",url:s.image_url.url,media_type:this.getMimeTypeFromUrl(s.image_url.url)}}}return s}).filter(s=>s);return{role:this.mapRoleToClaude(t.role),content:o}}return{role:this.mapRoleToClaude(t.role),content:[]}})}mapRoleToClaude(e){switch(e){case"system":return"system";case"user":return"user";case"assistant":return"assistant";default:return"user"}}getMimeTypeFromUrl(e){switch(e.split(".").pop()?.toLowerCase()){case"jpg":case"jpeg":return"image/jpeg";case"png":return"image/png";case"gif":return"image/gif";case"webp":return"image/webp";default:return"image/jpeg"}}async callClaude(e,t,o,s){let i=e.find(m=>m.role==="system")?.content??"",r=e.filter(m=>m.role!=="system"),a=r.some(m=>Array.isArray(m.content)&&m.content.some(u=>u.type==="image_url"||u.type==="image")),l={model:t,system:i,messages:a?this.convertVisionMessagesToClaudeFormat(r):this.convertMessagesToClaudeFormat(r),stream:o,max_tokens:s!==void 0?s:C(this.responseLength)};this.tools.length&&(l.tools=this.tools.map(m=>({name:m.name,description:m.description,input_schema:m.parameters})),l.tool_choice={type:"auto"}),this.mcpServers.length>0&&(l.mcp_servers=this.mcpServers);let c={"Content-Type":"application/json","x-api-key":this.apiKey,"anthropic-version":"2023-06-01","anthropic-dangerous-direct-browser-access":"true"};return this.mcpServers.length>0&&(c["anthropic-beta"]="mcp-client-2025-04-04"),await _.post(ct,l,c)}async parseStream(e,t){let o=e.body.getReader(),s=new TextDecoder,i=[],r=new Map,a="";for(;;){let{done:l,value:c}=await o.read();if(l)break;a+=s.decode(c,{stream:!0});let h;for(;(h=a.indexOf(`
|
|
12
|
+
`))!==-1;){let m=a.slice(0,h).trim();if(a=a.slice(h+1),!m.startsWith("data:"))continue;let u=m.slice(5).trim();if(u==="[DONE]")break;let p=JSON.parse(u);if(p.type==="content_block_delta"&&p.delta?.text&&(t(p.delta.text),i.push({type:"text",text:p.delta.text})),p.type==="content_block_start"&&p.content_block?.type==="tool_use"?r.set(p.index,{id:p.content_block.id,name:p.content_block.name,args:""}):p.type==="content_block_start"&&p.content_block?.type==="mcp_tool_use"?r.set(p.index,{id:p.content_block.id,name:p.content_block.name,args:"",server_name:p.content_block.server_name}):p.type==="content_block_start"&&p.content_block?.type==="tool_result"?i.push({type:"tool_result",tool_use_id:p.content_block.tool_use_id,content:p.content_block.content??""}):p.type==="content_block_start"&&p.content_block?.type==="mcp_tool_result"&&i.push({type:"mcp_tool_result",tool_use_id:p.content_block.tool_use_id,is_error:p.content_block.is_error??!1,content:p.content_block.content??[]}),p.type==="content_block_delta"&&p.delta?.type==="input_json_delta"){let v=r.get(p.index);v&&(v.args+=p.delta.partial_json||"")}if(p.type==="content_block_stop"&&r.has(p.index)){let{id:v,name:M,args:d,server_name:E}=r.get(p.index);E?i.push({type:"mcp_tool_use",id:v,name:M,server_name:E,input:JSON.parse(d||"{}")}):i.push({type:"tool_use",id:v,name:M,input:JSON.parse(d||"{}")}),r.delete(p.index)}}}return{blocks:i,stop_reason:i.some(l=>l.type==="tool_use"||l.type==="mcp_tool_use")?"tool_use":"end"}}async parsePureStream(e,t){let{blocks:o}=await this.parseStream(e,t);return o.filter(s=>s.type==="text").map(s=>s.text).join("")}parseOneShot(e){let t=[];return(e.content??[]).forEach(o=>{o.type==="text"?t.push({type:"text",text:o.text}):o.type==="tool_use"?t.push({type:"tool_use",id:o.id,name:o.name,input:o.input??{}}):o.type==="mcp_tool_use"?t.push({type:"mcp_tool_use",id:o.id,name:o.name,server_name:o.server_name,input:o.input??{}}):o.type==="tool_result"?t.push({type:"tool_result",tool_use_id:o.tool_use_id,content:o.content??""}):o.type==="mcp_tool_result"&&t.push({type:"mcp_tool_result",tool_use_id:o.tool_use_id,is_error:o.is_error??!1,content:o.content??[]})}),{blocks:t,stop_reason:t.some(o=>o.type==="tool_use"||o.type==="mcp_tool_use")?"tool_use":"end"}}async chatOnce(e,t=!0,o=()=>{},s){let i=await this.callClaude(e,this.model,t,s),r=t?await this.parseStream(i,o):this.parseOneShot(await i.json());return this.convertToStandardCompletion(r)}async visionChatOnce(e,t=!1,o=()=>{},s){let i=await this.callClaude(e,this.visionModel,t,s),r=t?await this.parseStream(i,o):this.parseOneShot(await i.json());return this.convertToStandardCompletion(r)}convertToStandardCompletion(e){return{blocks:e.blocks.filter(o=>o.type==="text"||o.type==="tool_use"||o.type==="tool_result"),stop_reason:e.stop_reason}}};var z=class{createChatService(e){let t=O({model:e.model,visionModel:e.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultModel(),supportsVisionForModel:o=>this.supportsVisionForModel(o),validate:"resolved"});return new q(e.apiKey,e.model||this.getDefaultModel(),t,e.tools??[],e.mcpServers??[],e.responseLength)}getProviderName(){return"claude"}getSupportedModels(){return[S,xe,Ie,Le,be,De,Re,Ae,we,Ne,ke]}getDefaultModel(){return S}supportsVision(){return!0}supportsVisionForModel(e){return ce.includes(e)}};var tt=class{static async fetchToolSchemas(e){try{let t={"Content-Type":"application/json"};e.authorization_token&&(t.Authorization=`Bearer ${e.authorization_token}`);let s=await(await _.post(`${e.url}/tools`,{},t)).json();return Array.isArray(s.tools)?s.tools.map(i=>({name:`mcp_${e.name}_${i.name}`,description:i.description||`Tool from ${e.name} MCP server`,parameters:i.inputSchema||{type:"object",properties:{},required:[]}})):[{name:`mcp_${e.name}_search`,description:`Search using ${e.name} MCP server`,parameters:{type:"object",properties:{query:{type:"string",description:"Search query"}},required:["query"]}}]}catch(t){return console.warn(`Failed to fetch MCP schemas from ${e.name}:`,t),[{name:`mcp_${e.name}_search`,description:`Search using ${e.name} MCP server (schema fetch failed)`,parameters:{type:"object",properties:{query:{type:"string",description:"Search query"}},required:["query"]}}]}}static async fetchAllToolSchemas(e){let t=[];for(let o of e)try{let s=await this.fetchToolSchemas(o);t.push(...s)}catch(s){console.error(`Failed to fetch schemas from ${o.name}:`,s)}return t}};var J=class{constructor(e,t=D,o=D,s=[],i=[],r){this.provider="gemini";this.mcpToolSchemas=[];this.mcpSchemasInitialized=!1;this.callIdMap=new Map;if(this.apiKey=e,this.model=t,this.responseLength=r,!pe.includes(o))throw new Error(`Model ${o} does not support vision capabilities.`);this.visionModel=o,this.tools=s,this.mcpServers=i}safeJsonParse(e){try{return JSON.parse(e)}catch{return e}}normalizeToolResult(e){return e===null?{content:null}:typeof e=="object"?e:{content:e}}adaptKeysForApi(e){let t={toolConfig:"tool_config",functionCallingConfig:"function_calling_config",functionDeclarations:"function_declarations",functionCall:"function_call",functionResponse:"function_response"};return Array.isArray(e)?e.map(o=>this.adaptKeysForApi(o)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([o,s])=>[t[o]??o,this.adaptKeysForApi(s)])):e}getModel(){return this.model}getVisionModel(){return this.visionModel}getMCPServers(){return this.mcpServers}addMCPServer(e){this.mcpServers.push(e),this.mcpSchemasInitialized=!1}removeMCPServer(e){this.mcpServers=this.mcpServers.filter(t=>t.name!==e),this.mcpSchemasInitialized=!1}hasMCPServers(){return this.mcpServers.length>0}async initializeMCPSchemas(){if(!(this.mcpSchemasInitialized||this.mcpServers.length===0))try{let e=new Promise((o,s)=>setTimeout(()=>s(new Error("MCP schema fetch timeout")),5e3)),t=tt.fetchAllToolSchemas(this.mcpServers);this.mcpToolSchemas=await Promise.race([t,e]),this.mcpSchemasInitialized=!0}catch(e){console.warn("Failed to initialize MCP schemas, using fallback:",e),this.mcpToolSchemas=this.mcpServers.map(t=>({name:`mcp_${t.name}_search`,description:`Search using ${t.name} MCP server (fallback)`,parameters:{type:"object",properties:{query:{type:"string",description:"Search query"}},required:["query"]}})),this.mcpSchemasInitialized=!0}}async processChat(e,t,o){try{await f({hasTools:this.tools.length>0||this.mcpServers.length>0,runWithoutTools:async()=>{let s=await this.callGemini(e,this.model,!0),{blocks:i}=await this.parseStream(s,t);return g.getFullText(i)},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"Received functionCall. Use chatOnce() loop when tools are enabled."})}catch(s){throw console.error("Error in processChat:",s),s}}async processVisionChat(e,t,o){try{await f({hasTools:this.tools.length>0||this.mcpServers.length>0,runWithoutTools:async()=>{let s=await this.callGemini(e,this.visionModel,!0),{blocks:i}=await this.parseStream(s,t);return g.getFullText(i)},runWithTools:()=>this.visionChatOnce(e),onToolBlocks:s=>{s.filter(i=>i.type==="text").forEach(i=>t(i.text))},onCompleteResponse:o,toolErrorMessage:"Received functionCall. Use visionChatOnce() loop when tools are enabled."})}catch(s){throw console.error("Error in processVisionChat:",s),s}}convertMessagesToGeminiFormat(e){let t=[],o=null,s=[],i=()=>{o&&s.length&&(t.push({role:o,parts:[...s]}),s=[])};for(let r of e){let a=this.mapRoleToGemini(r.role);if(r.tool_calls){i();for(let l of r.tool_calls)this.callIdMap.set(l.id,l.function.name),t.push({role:"model",parts:[{functionCall:{name:l.function.name,args:JSON.parse(l.function.arguments||"{}")}}]});continue}if(r.role==="tool"){i();let l=r.name??this.callIdMap.get(r.tool_call_id)??"result";t.push({role:"user",parts:[{functionResponse:{name:l,response:this.normalizeToolResult(this.safeJsonParse(r.content))}}]});continue}a!==o&&i(),o=a,s.push({text:r.content})}return i(),t}async callGemini(e,t,o=!1,s){let a={contents:e.some(d=>Array.isArray(d.content)&&d.content.some(E=>E?.type==="image_url"||E?.inlineData))?await this.convertVisionMessagesToGeminiFormat(e):this.convertMessagesToGeminiFormat(e),generationConfig:{maxOutputTokens:s!==void 0?s:C(this.responseLength)}},l=[];if(this.tools.length>0&&l.push(...this.tools.map(d=>({name:d.name,description:d.description,parameters:d.parameters}))),this.mcpServers.length>0)try{await this.initializeMCPSchemas(),l.push(...this.mcpToolSchemas.map(d=>({name:d.name,description:d.description,parameters:d.parameters})))}catch(d){console.warn("MCP initialization failed, skipping MCP tools:",d)}l.length>0&&(a.tools=[{functionDeclarations:l}],a.toolConfig={functionCallingConfig:{mode:"AUTO"}});let c=async(d,E)=>{let ot=o?"streamGenerateContent":"generateContent",Tt=o?"?alt=sse":"",Vt=`${pt}/${d}/models/${t}:${ot}${Tt}${Tt?"&":"?"}key=${this.apiKey}`;return _.post(Vt,E)},h=/flash[-_]lite/.test(t),m=/gemini-2\.5/.test(t),u=/^gemini-3(?:\.[0-9]+)?-.*preview/.test(t),p=h||m||u,v=p?"v1beta":"v1",M=async()=>{try{let d=v==="v1"?a:this.adaptKeysForApi(a);return await c(v,d)}catch(d){let E=/Unknown name|Cannot find field|404/.test(d?.message||"")||d?.status===404;if(!p&&E)return await c("v1beta",this.adaptKeysForApi(a));throw d}};try{return await M()}catch(d){throw d.body&&(console.error("Gemini API Error Details:",d.body),console.error("Request Body:",JSON.stringify(a,null,2))),d}}async convertVisionMessagesToGeminiFormat(e){let t=[],o=null,s=[];for(let i of e){let r=this.mapRoleToGemini(i.role);if(i.tool_calls){for(let a of i.tool_calls)t.push({role:"model",parts:[{functionCall:{name:a.function.name,args:JSON.parse(a.function.arguments||"{}")}}]});continue}if(i.role==="tool"){let a=i.name??this.callIdMap.get(i.tool_call_id)??"result";t.push({role:"user",parts:[{functionResponse:{name:a,response:this.normalizeToolResult(this.safeJsonParse(i.content))}}]});continue}if(r!==o&&s.length>0&&(t.push({role:o,parts:[...s]}),s=[]),o=r,typeof i.content=="string")s.push({text:i.content});else if(Array.isArray(i.content)){for(let a of i.content)if(a.type==="text")s.push({text:a.text});else if(a.type==="image_url")try{let c=await(await _.get(a.image_url.url)).blob(),h=await this.blobToBase64(c);s.push({inlineData:{mimeType:c.type||"image/jpeg",data:h.split(",")[1]}})}catch(l){throw console.error("Error processing image:",l),new Error(`Failed to process image: ${l.message}`)}}}return o&&s.length>0&&t.push({role:o,parts:[...s]}),t}blobToBase64(e){return new Promise((t,o)=>{let s=new FileReader;s.onloadend=()=>t(s.result),s.onerror=o,s.readAsDataURL(e)})}mapRoleToGemini(e){switch(e){case"system":return"model";case"user":return"user";case"assistant":return"model";default:return"user"}}async parseStream(e,t){let o=e.body.getReader(),s=new TextDecoder,i=[],r=[],a="",l=h=>{if(!h||h==="[DONE]")return;let m;try{m=JSON.parse(h)}catch{return}for(let u of m.candidates??[])for(let p of u.content?.parts??[])p.text&&(t(p.text),g.addTextBlock(i,p.text)),p.functionCall&&r.push({type:"tool_use",id:this.genUUID(),name:p.functionCall.name,input:p.functionCall.args??{}}),p.functionResponse&&r.push({type:"tool_result",tool_use_id:p.functionResponse.name,content:JSON.stringify(p.functionResponse.response)})};for(;;){let{done:h,value:m}=await o.read();if(h)break;a+=s.decode(m,{stream:!0});let u;for(;(u=a.indexOf(`
|
|
13
|
+
`))!==-1;){let p=a.slice(0,u);if(a=a.slice(u+1),p.endsWith("\r")&&(p=p.slice(0,-1)),!p.trim()){l("");continue}p.startsWith("data:")&&(p=p.slice(5).trim()),p&&l(p)}}return a&&l(a),{blocks:[...i,...r],stop_reason:r.some(h=>h.type==="tool_use")?"tool_use":"end"}}parseOneShot(e){let t=[],o=[];for(let i of e.candidates??[])for(let r of i.content?.parts??[])r.text&&t.push({type:"text",text:r.text}),r.functionCall&&o.push({type:"tool_use",id:this.genUUID(),name:r.functionCall.name,input:r.functionCall.args??{}}),r.functionResponse&&o.push({type:"tool_result",tool_use_id:r.functionResponse.name,content:JSON.stringify(r.functionResponse.response)});return{blocks:[...t,...o],stop_reason:o.some(i=>i.type==="tool_use")?"tool_use":"end"}}async chatOnce(e,t=!0,o=()=>{},s){let i=await this.callGemini(e,this.model,t,s);return t?this.parseStream(i,o):this.parseOneShot(await i.json())}async visionChatOnce(e,t=!1,o=()=>{},s){let i=await this.callGemini(e,this.visionModel,t,s);return t?this.parseStream(i,o):this.parseOneShot(await i.json())}genUUID(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}};var Z=class{createChatService(e){let t=O({model:e.model,visionModel:e.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultModel(),supportsVisionForModel:o=>this.supportsVisionForModel(o),validate:"resolved"});return new J(e.apiKey,e.model||this.getDefaultModel(),t,e.tools||[],e.mcpServers||[],e.responseLength)}getProviderName(){return"gemini"}getSupportedModels(){return[Me,Ce,Oe,Ee,ye,Se,Te,Pe,D]}getDefaultModel(){return D}supportsVision(){return!0}supportsVisionForModel(e){return pe.includes(e)}};var X=class{constructor(e,t=T,o=T,s,i=K,r,a,l){this.provider="kimi";this.apiKey=e,this.model=t,this.tools=s||[],this.endpoint=i,this.responseLength=r,this.responseFormat=a,this.thinking=l??{type:"enabled"},this.visionModel=o}getModel(){return this.model}getVisionModel(){return this.visionModel}async processChat(e,t,o){await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callKimi(e,this.model,!0);return this.handleStream(s,t)},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."})}async processVisionChat(e,t,o){if(!j(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callKimi(e,this.visionModel,!0);return this.handleStream(s,t)},runWithTools:()=>this.visionChatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processVisionChat received tool_calls. ChatProcessor must use visionChatOnce() loop when tools are enabled."})}async chatOnce(e,t=!0,o=()=>{},s){let i=await this.callKimi(e,this.model,t,s);return this.parseResponse(i,t,o)}async visionChatOnce(e,t=!1,o=()=>{},s){if(!j(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);let i=await this.callKimi(e,this.visionModel,t,s);return this.parseResponse(i,t,o)}async parseResponse(e,t,o){return t?this.parseStream(e,o):this.parseOneShot(await e.json())}async callKimi(e,t,o=!1,s){let i=this.buildRequestBody(e,t,o,s);return await _.post(this.endpoint,i,{Authorization:`Bearer ${this.apiKey}`})}buildRequestBody(e,t,o,s){let i={model:t,stream:o,messages:e},r=s!==void 0?s:C(this.responseLength);r!==void 0&&(i.max_tokens=r),this.responseFormat&&(i.response_format=this.responseFormat);let a=this.tools.length>0?{type:"disabled"}:this.thinking;a&&(this.isSelfHostedEndpoint()?a.type==="disabled"&&(i.chat_template_kwargs={thinking:!1}):i.thinking=a);let l=this.buildToolsDefinition();return l.length>0&&(i.tools=l,i.tool_choice="auto"),i}isSelfHostedEndpoint(){return this.normalizeEndpoint(this.endpoint)!==this.normalizeEndpoint(K)}normalizeEndpoint(e){return e.replace(/\/+$/,"")}buildToolsDefinition(){return L(this.tools,"chat-completions")}async handleStream(e,t){return P(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}async parseStream(e,t){return x(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}parseOneShot(e){return I(e)}};var Y=class{createChatService(e){let t=this.resolveEndpoint(e),o=e.model||this.getDefaultModel(),s=O({model:o,visionModel:e.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultVisionModel(),supportsVisionForModel:l=>this.supportsVisionForModel(l),validate:"explicit"}),i=e.tools,r=e.thinking??{type:"enabled"},a=i&&i.length>0?{type:"disabled"}:r;return new X(e.apiKey,o,s,i,t,e.responseLength,e.responseFormat,a)}getProviderName(){return"kimi"}getSupportedModels(){return[T]}getDefaultModel(){return T}getDefaultVisionModel(){return T}supportsVision(){return!0}supportsVisionForModel(e){return j(e)}resolveEndpoint(e){if(e.endpoint)return this.normalizeEndpoint(e.endpoint);if(e.baseUrl){let t=this.normalizeEndpoint(e.baseUrl);return t.endsWith("/chat/completions")?t:`${t}/chat/completions`}return K}normalizeEndpoint(e){return e.replace(/\/+$/,"")}};var w=class{constructor(e,t=N,o=N,s,i=G,r=[],a,l,c,h=!1,m="openai",u=!0){if(this.provider=m,this.apiKey=e,this.model=t,this.tools=s||[],this.endpoint=i,this.mcpServers=r,this.responseLength=a,this.verbosity=l,this.reasoning_effort=c,this.enableReasoningSummary=h,u&&!le.includes(o))throw new Error(`Model ${o} does not support vision capabilities.`);this.visionModel=o}getModel(){return this.model}getVisionModel(){return this.visionModel}async processChat(e,t,o){await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callOpenAI(e,this.model,!0),i=this.endpoint===y;try{if(i){let r=await this.parseResponsesStream(s,t);return g.getFullText(r.blocks)}return this.handleStream(s,t)}catch(r){throw console.error("[processChat] Error in streaming/completion:",r),r}},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."})}async processVisionChat(e,t,o){try{await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callOpenAI(e,this.visionModel,!0),i=this.endpoint===y;try{if(i){let r=await this.parseResponsesStream(s,t);return g.getFullText(r.blocks)}return this.handleStream(s,t)}catch(r){throw console.error("[processVisionChat] Error in streaming/completion:",r),r}},runWithTools:()=>this.visionChatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processVisionChat received tool_calls. ChatProcessor must use visionChatOnce() loop when tools are enabled."})}catch(s){throw console.error("Error in processVisionChat:",s),s}}async chatOnce(e,t=!0,o=()=>{},s){let i=await this.callOpenAI(e,this.model,t,s);return this.parseResponse(i,t,o)}async visionChatOnce(e,t=!1,o=()=>{},s){let i=await this.callOpenAI(e,this.visionModel,t,s);return this.parseResponse(i,t,o)}async parseResponse(e,t,o){return this.endpoint===y?t?this.parseResponsesStream(e,o):this.parseResponsesOneShot(await e.json()):t?this.parseStream(e,o):this.parseOneShot(await e.json())}async callOpenAI(e,t,o=!1,s){let i=this.buildRequestBody(e,t,o,s),r={};return(this.provider!=="openai-compatible"||this.apiKey.trim()!=="")&&(r.Authorization=`Bearer ${this.apiKey}`),await _.post(this.endpoint,i,r)}buildRequestBody(e,t,o,s){let i=this.endpoint===y;this.validateMCPCompatibility();let r={model:t,stream:o},a=s!==void 0?s:this.provider==="openai-compatible"?this.responseLength!==void 0?C(this.responseLength):void 0:C(this.responseLength);i?a!==void 0&&(r.max_output_tokens=a):a!==void 0&&(this.provider==="openai-compatible"?r.max_tokens=a:r.max_completion_tokens=a),i?r.input=this.cleanMessagesForResponsesAPI(e):r.messages=e,U(t)&&(i?(this.reasoning_effort&&(r.reasoning={...r.reasoning,effort:this.reasoning_effort},this.enableReasoningSummary&&(r.reasoning.summary="auto")),this.verbosity&&(r.text={...r.text,format:{type:"text"},verbosity:this.verbosity})):(this.reasoning_effort&&(r.reasoning_effort=this.reasoning_effort),this.verbosity&&(r.verbosity=this.verbosity)));let l=this.buildToolsDefinition();return l.length>0&&(r.tools=l,i||(r.tool_choice="auto")),r}validateMCPCompatibility(){if(this.mcpServers.length>0&&this.endpoint===G)throw new Error(`MCP servers are not supported with Chat Completions API. Current endpoint: ${this.endpoint}. Please use OpenAI Responses API endpoint: ${y}. MCP tools are only available in the Responses API endpoint.`)}cleanMessagesForResponsesAPI(e){return e.map(t=>{let s={role:t.role==="tool"?"user":t.role};return typeof t.content=="string"?s.content=t.content:Array.isArray(t.content)?s.content=t.content.map(i=>i.type==="text"?{type:"input_text",text:i.text}:i.type==="image_url"?{type:"input_image",image_url:i.image_url.url}:i):s.content=t.content,s})}buildToolsDefinition(){let e=this.endpoint===y,t=[];return this.tools.length>0&&t.push(...L(this.tools,e?"responses":"chat-completions")),this.mcpServers.length>0&&e&&t.push(...this.buildMCPToolsDefinition()),t}buildMCPToolsDefinition(){return this.mcpServers.map(e=>{let t={type:"mcp",server_label:e.name,server_url:e.url};return e.require_approval&&(t.require_approval=e.require_approval),e.tool_configuration?.allowed_tools&&(t.allowed_tools=e.tool_configuration.allowed_tools),e.authorization_token&&(t.headers={Authorization:`Bearer ${e.authorization_token}`}),t})}async handleStream(e,t){return P(e,t)}async parseStream(e,t){return x(e,t,{appendTextBlock:g.addTextBlock})}parseOneShot(e){return I(e)}async parseResponsesStream(e,t){let o=e.body.getReader(),s=new TextDecoder,i=[],r=new Map,a="";for(;;){let{done:h,value:m}=await o.read();if(h)break;a+=s.decode(m,{stream:!0});let u="",p="",v=a.split(`
|
|
14
|
+
`);a=v.pop()||"";for(let M=0;M<v.length;M++){let d=v[M].trim();if(d.startsWith("event:"))u=d.slice(6).trim();else if(d.startsWith("data:"))p=d.slice(5).trim();else if(d===""&&u&&p){try{let E=JSON.parse(p),ot=this.handleResponsesSSEEvent(u,E,t,i,r)}catch{console.warn("Failed to parse SSE data:",p)}u="",p=""}}}let l=Array.from(r.values()).map(h=>({type:"tool_use",id:h.id,name:h.name,input:h.input||{}}));return{blocks:[...i,...l],stop_reason:l.length?"tool_use":"end"}}handleResponsesSSEEvent(e,t,o,s,i){switch(e){case"response.output_item.added":t.item?.type==="message"&&Array.isArray(t.item.content)?t.item.content.forEach(r=>{r.type==="output_text"&&r.text&&(o(r.text),g.append(s,r.text))}):t.item?.type==="function_call"&&i.set(t.item.id,{id:t.item.id,name:t.item.name,input:t.item.arguments?JSON.parse(t.item.arguments):{}});break;case"response.content_part.added":t.part?.type==="output_text"&&typeof t.part.text=="string"&&(o(t.part.text),g.append(s,t.part.text));break;case"response.output_text.delta":case"response.content_part.delta":{let r=typeof t.delta=="string"?t.delta:t.delta?.text??"";r&&(o(r),g.append(s,r))}break;case"response.output_text.done":case"response.content_part.done":break;case"response.completed":return"completed";case"response.reasoning.started":case"response.reasoning.delta":case"response.reasoning.done":break;default:break}}parseResponsesOneShot(e){let t=[];return e.output&&Array.isArray(e.output)&&e.output.forEach(o=>{o.type==="message"&&o.content&&o.content.forEach(s=>{s.type==="output_text"&&s.text&&t.push({type:"text",text:s.text})}),o.type==="function_call"&&t.push({type:"tool_use",id:o.id,name:o.name,input:o.arguments?JSON.parse(o.arguments):{}})}),{blocks:t,stop_reason:t.some(o=>o.type==="tool_use")?"tool_use":"end"}}};var Q=class{createChatService(e){return this.validateRequiredOptions(e),new w(e.apiKey?.trim()??"",e.model,e.visionModel??e.model,e.tools,e.endpoint,[],e.responseLength,e.verbosity,e.reasoning_effort,e.enableReasoningSummary,this.getProviderName(),!1)}getProviderName(){return"openai-compatible"}getSupportedModels(){return[]}supportsVision(){return!1}getDefaultModel(){return"local-model"}validateRequiredOptions(e){if(e.mcpServers!==void 0)throw new Error("openai-compatible provider does not support mcpServers.");let t=e.endpoint?.trim();if(!t)throw new Error("openai-compatible provider requires endpoint (full URL).");let o;try{o=new URL(t)}catch{throw new Error("openai-compatible provider requires endpoint to be a full URL.")}if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error("openai-compatible provider requires endpoint to be a full URL.");if(!e.model?.trim())throw new Error("openai-compatible provider requires model.")}};var ee=class{createChatService(e){let t=this.optimizeGPT5Options(e),o=O({model:t.model,visionModel:t.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultModel(),supportsVisionForModel:c=>this.supportsVisionForModel(c),validate:"resolved"}),s=t.tools,i=t.mcpServers??[],r=t.model||this.getDefaultModel(),a=!1;i.length>0?a=!0:U(r)&&(a=(t.gpt5EndpointPreference||"chat")==="responses");let l=t.endpoint||(a?y:G);return new w(t.apiKey,r,o,s,l,i,t.responseLength,t.verbosity,t.reasoning_effort,t.enableReasoningSummary,this.getProviderName())}getProviderName(){return"openai"}getSupportedModels(){return[F,ne,ae,b,de,_e,ge,N,fe,it,rt,"o1",ve]}getDefaultModel(){return F}supportsVision(){return!0}supportsVisionForModel(e){return le.includes(e)}optimizeGPT5Options(e){let t=e.model||this.getDefaultModel();if(!U(t))return e;let o={...e};if(e.gpt5Preset){let s=yt[e.gpt5Preset];o.reasoning_effort=s.reasoning_effort,o.verbosity=s.verbosity}else e.reasoning_effort||(o.reasoning_effort=this.getDefaultReasoningEffortForModel(t));return o.reasoning_effort=this.normalizeReasoningEffort(t,o.reasoning_effort),o}getDefaultReasoningEffortForModel(e){return e===b?"none":"medium"}normalizeReasoningEffort(e,t){if(t)return t==="none"&&!at(e)?this.getDefaultReasoningEffortForModel(e):t==="minimal"&&!lt(e)?"none":t}};var te=class{constructor(e,t=R,o=R,s,i=ht,r,a,l,c,h,m){this.provider="openrouter";this.lastRequestTime=0;this.requestCount=0;this.apiKey=e,this.model=t,this.tools=s||[],this.endpoint=i,this.responseLength=r,this.appName=a,this.appUrl=l,this.reasoning_effort=c,this.includeReasoning=h,this.reasoningMaxTokens=m,this.visionModel=o}getModel(){return this.model}getVisionModel(){return this.visionModel}async applyRateLimiting(){if(!gt(this.model))return;let e=Date.now(),t=e-this.lastRequestTime;if(t>6e4&&(this.requestCount=0),this.requestCount>=_t){let o=6e4-t;o>0&&(console.log(`Rate limit reached for free tier. Waiting ${o}ms...`),await new Promise(s=>setTimeout(s,o)),this.requestCount=0)}this.lastRequestTime=e,this.requestCount++}async processChat(e,t,o){await this.applyRateLimiting(),await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callOpenRouter(e,this.model,!0);return this.handleStream(s,t)},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."})}async processVisionChat(e,t,o){if(!H(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);await this.applyRateLimiting();try{await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callOpenRouter(e,this.visionModel,!0);return this.handleStream(s,t)},runWithTools:()=>this.visionChatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processVisionChat received tool_calls. ChatProcessor must use visionChatOnce() loop when tools are enabled."})}catch(s){throw console.error("Error in processVisionChat:",s),s}}async chatOnce(e,t=!0,o=()=>{},s){await this.applyRateLimiting();let i=await this.callOpenRouter(e,this.model,t,s);return t?this.parseStream(i,o):this.parseOneShot(await i.json())}async visionChatOnce(e,t=!1,o=()=>{},s){if(!H(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);await this.applyRateLimiting();let i=await this.callOpenRouter(e,this.visionModel,t,s);return t?this.parseStream(i,o):this.parseOneShot(await i.json())}async callOpenRouter(e,t,o=!1,s){let i=this.buildRequestBody(e,t,o,s),r={Authorization:`Bearer ${this.apiKey}`};return this.appUrl&&(r["HTTP-Referer"]=this.appUrl),this.appName&&(r["X-Title"]=this.appName),await _.post(this.endpoint,i,r)}buildRequestBody(e,t,o,s){let i={model:t,messages:e,stream:o};if((s!==void 0?s:C(this.responseLength))&&console.warn("OpenRouter: Token limits are not supported for gpt-oss-20b model due to known issues. Using unlimited tokens instead."),this.reasoning_effort!==void 0||this.includeReasoning!==void 0||this.reasoningMaxTokens){if(i.reasoning={},this.reasoning_effort&&this.reasoning_effort!=="none"){let a=this.reasoning_effort==="minimal"?"low":this.reasoning_effort;i.reasoning.effort=a}(this.reasoning_effort==="none"||this.includeReasoning!==!0)&&(i.reasoning.exclude=!0),this.reasoningMaxTokens&&(i.reasoning.max_tokens=this.reasoningMaxTokens)}else i.reasoning={exclude:!0};return this.tools.length>0&&(i.tools=L(this.tools,"chat-completions"),i.tool_choice="auto"),i}async handleStream(e,t){return P(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}async parseStream(e,t){return x(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}parseOneShot(e){return I(e)}};var oe=class{createChatService(e){let t=O({model:e.model,visionModel:e.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:e.model||this.getDefaultModel(),supportsVisionForModel:r=>this.supportsVisionForModel(r),validate:"explicit"}),o=e.tools,s=e.appName,i=e.appUrl;return new te(e.apiKey,e.model||this.getDefaultModel(),t,o,e.endpoint,e.responseLength,s,i,e.reasoning_effort,e.includeReasoning,e.reasoningMaxTokens)}getProviderName(){return"openrouter"}getSupportedModels(){return[R,Ye,Ge,Fe,Ue,He,We,Be,Ke,je,$e,qe,mt,ze,Je,Ze,Xe,ut,dt,Ve]}getDefaultModel(){return R}supportsVision(){return this.getSupportedModels().some(e=>this.supportsVisionForModel(e))}supportsVisionForModel(e){return H(e)}getFreeModels(){return he}isModelFree(e){return he.includes(e)||e.endsWith(":free")}};var se=class{constructor(e,t=W,o=k,s,i=me,r,a,l){this.provider="zai";this.apiKey=e,this.model=t,this.tools=s||[],this.endpoint=i,this.responseLength=r,this.responseFormat=a,this.thinking=l??{type:"disabled"},this.visionModel=o}getModel(){return this.model}getVisionModel(){return this.visionModel}async processChat(e,t,o){await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callZAI(e,this.model,!0);return this.handleStream(s,t)},runWithTools:()=>this.chatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."})}async processVisionChat(e,t,o){if(!B(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);await f({hasTools:this.tools.length>0,runWithoutTools:async()=>{let s=await this.callZAI(e,this.visionModel,!0);return this.handleStream(s,t)},runWithTools:()=>this.visionChatOnce(e,!0,t),onCompleteResponse:o,toolErrorMessage:"processVisionChat received tool_calls. ChatProcessor must use visionChatOnce() loop when tools are enabled."})}async chatOnce(e,t=!0,o=()=>{},s){let i=await this.callZAI(e,this.model,t,s);return this.parseResponse(i,t,o)}async visionChatOnce(e,t=!1,o=()=>{},s){if(!B(this.visionModel))throw new Error(`Model ${this.visionModel} does not support vision capabilities.`);let i=await this.callZAI(e,this.visionModel,t,s);return this.parseResponse(i,t,o)}async parseResponse(e,t,o){return t?this.parseStream(e,o):this.parseOneShot(await e.json())}async callZAI(e,t,o=!1,s){let i=this.buildRequestBody(e,t,o,s);return await _.post(this.endpoint,i,{Authorization:`Bearer ${this.apiKey}`})}buildRequestBody(e,t,o,s){let i={model:t,stream:o,messages:e},r=s!==void 0?s:C(this.responseLength);r!==void 0&&(i.max_tokens=r),this.responseFormat&&(i.response_format=this.responseFormat),this.thinking&&(i.thinking=this.thinking);let a=this.buildToolsDefinition();return a.length>0&&(i.tools=a,i.tool_choice="auto",o&&Ot(t)&&(i.tool_stream=!0)),i}buildToolsDefinition(){return L(this.tools,"chat-completions")}async handleStream(e,t){return P(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}async parseStream(e,t){return x(e,t,{onJsonError:o=>console.debug("Failed to parse SSE data:",o)})}parseOneShot(e){return I(e)}};var ie=class{createChatService(e){let t=e.model||this.getDefaultModel(),o=O({model:t,visionModel:e.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultVisionModel(),supportsVisionForModel:r=>this.supportsVisionForModel(r),validate:"explicit"}),s=e.tools,i=e.thinking??{type:"disabled"};return new se(e.apiKey,t,o,s,e.endpoint||me,e.responseLength,e.responseFormat,i)}getProviderName(){return"zai"}getSupportedModels(){return[ft,W,vt,Mt,Ct,Qe,et,k]}getDefaultModel(){return W}getDefaultVisionModel(){return k}supportsVision(){return!0}supportsVisionForModel(e){return B(e)}};var Nt=[new ee,new Q,new Z,new z,new oe,new ie,new Y];var re=class{static registerProvider(e){this.providers.set(e.getProviderName(),e)}static createChatService(e,t){let o=this.providers.get(e);if(!o)throw new Error(`Unknown chat provider: ${e}`);return o.createChatService(t)}static getProviders(){return this.providers}static getAvailableProviders(){return Array.from(this.providers.keys())}static getSupportedModels(e){let t=this.providers.get(e);return t?t.getSupportedModels():[]}};re.providers=new Map;Nt.forEach(n=>re.registerProvider(n));function kt(){_.setFetch(async(n,e={})=>{let t=(e.method||"GET").toString().toUpperCase(),o=e.headers,s={};if(Array.isArray(o))for(let[m,u]of o)s[m]=String(u);else if(o&&typeof o=="object")for(let[m,u]of Object.entries(o))s[m]=String(u);let i={method:t,headers:s,muteHttpExceptions:!0},r=e.body;typeof r=="string"?i.payload=r:r!=null&&(s["Content-Type"]||(s["Content-Type"]="application/json"),i.payload=JSON.stringify(r));let a=UrlFetchApp.fetch(n,i),l=a.getResponseCode(),c=a.getContentText();return{ok:l>=200&&l<300,status:l,statusText:String(l),text:async()=>c,json:async()=>c?JSON.parse(c):null}})}return Bt(Qt);})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aituber-onair/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Chat and LLM API integration library for AITuber OnAir",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
"test": "npm run typecheck && vitest run",
|
|
27
27
|
"test:watch": "vitest",
|
|
28
28
|
"test:coverage": "vitest run --coverage",
|
|
29
|
+
"openai-compatible:probe": "node examples/compat-probe/index.js",
|
|
30
|
+
"openai-compatible:mock-server": "node examples/mock-openai-server/server.js",
|
|
29
31
|
"fmt": "biome format . --write",
|
|
30
32
|
"fmt:check": "biome format .",
|
|
31
33
|
"lint": "biome lint .",
|