@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.
Files changed (73) hide show
  1. package/README.ja.md +90 -4
  2. package/README.md +87 -4
  3. package/dist/cjs/constants/gemini.d.ts +3 -0
  4. package/dist/cjs/constants/gemini.d.ts.map +1 -1
  5. package/dist/cjs/constants/gemini.js +7 -1
  6. package/dist/cjs/constants/gemini.js.map +1 -1
  7. package/dist/cjs/index.d.ts +2 -1
  8. package/dist/cjs/index.d.ts.map +1 -1
  9. package/dist/cjs/index.js +3 -1
  10. package/dist/cjs/index.js.map +1 -1
  11. package/dist/cjs/services/ChatServiceFactory.d.ts +2 -2
  12. package/dist/cjs/services/ChatServiceFactory.d.ts.map +1 -1
  13. package/dist/cjs/services/ChatServiceFactory.js.map +1 -1
  14. package/dist/cjs/services/providers/ChatServiceProvider.d.ts +9 -2
  15. package/dist/cjs/services/providers/ChatServiceProvider.d.ts.map +1 -1
  16. package/dist/cjs/services/providers/gemini/GeminiChatService.d.ts.map +1 -1
  17. package/dist/cjs/services/providers/gemini/GeminiChatService.js +7 -4
  18. package/dist/cjs/services/providers/gemini/GeminiChatService.js.map +1 -1
  19. package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.d.ts.map +1 -1
  20. package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.js +3 -0
  21. package/dist/cjs/services/providers/gemini/GeminiChatServiceProvider.js.map +1 -1
  22. package/dist/cjs/services/providers/index.d.ts +2 -1
  23. package/dist/cjs/services/providers/index.d.ts.map +1 -1
  24. package/dist/cjs/services/providers/index.js +2 -0
  25. package/dist/cjs/services/providers/index.js.map +1 -1
  26. package/dist/cjs/services/providers/openai/OpenAIChatService.d.ts +1 -1
  27. package/dist/cjs/services/providers/openai/OpenAIChatService.d.ts.map +1 -1
  28. package/dist/cjs/services/providers/openai/OpenAIChatService.js +31 -12
  29. package/dist/cjs/services/providers/openai/OpenAIChatService.js.map +1 -1
  30. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.d.ts.map +1 -1
  31. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js +1 -1
  32. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
  33. package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts +21 -0
  34. package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts.map +1 -0
  35. package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js +56 -0
  36. package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js.map +1 -0
  37. package/dist/esm/constants/gemini.d.ts +3 -0
  38. package/dist/esm/constants/gemini.d.ts.map +1 -1
  39. package/dist/esm/constants/gemini.js +6 -0
  40. package/dist/esm/constants/gemini.js.map +1 -1
  41. package/dist/esm/index.d.ts +2 -1
  42. package/dist/esm/index.d.ts.map +1 -1
  43. package/dist/esm/index.js +1 -0
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/services/ChatServiceFactory.d.ts +2 -2
  46. package/dist/esm/services/ChatServiceFactory.d.ts.map +1 -1
  47. package/dist/esm/services/ChatServiceFactory.js.map +1 -1
  48. package/dist/esm/services/providers/ChatServiceProvider.d.ts +9 -2
  49. package/dist/esm/services/providers/ChatServiceProvider.d.ts.map +1 -1
  50. package/dist/esm/services/providers/gemini/GeminiChatService.d.ts.map +1 -1
  51. package/dist/esm/services/providers/gemini/GeminiChatService.js +7 -4
  52. package/dist/esm/services/providers/gemini/GeminiChatService.js.map +1 -1
  53. package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.d.ts.map +1 -1
  54. package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.js +4 -1
  55. package/dist/esm/services/providers/gemini/GeminiChatServiceProvider.js.map +1 -1
  56. package/dist/esm/services/providers/index.d.ts +2 -1
  57. package/dist/esm/services/providers/index.d.ts.map +1 -1
  58. package/dist/esm/services/providers/index.js +2 -0
  59. package/dist/esm/services/providers/index.js.map +1 -1
  60. package/dist/esm/services/providers/openai/OpenAIChatService.d.ts +1 -1
  61. package/dist/esm/services/providers/openai/OpenAIChatService.d.ts.map +1 -1
  62. package/dist/esm/services/providers/openai/OpenAIChatService.js +31 -12
  63. package/dist/esm/services/providers/openai/OpenAIChatService.js.map +1 -1
  64. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.d.ts.map +1 -1
  65. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js +1 -1
  66. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
  67. package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts +21 -0
  68. package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts.map +1 -0
  69. package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js +52 -0
  70. package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js.map +1 -0
  71. package/dist/umd/aituber-onair-chat.js +106 -13
  72. package/dist/umd/aituber-onair-chat.min.js +6 -6
  73. 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 firstVer = isLite || isGemini25 ? "v1beta" : "v1";
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
- if (!(isLite || isGemini25) && /Unknown name|Cannot find field|404/.test(e.message)) {
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
- /** Provider name */
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 res = await ChatServiceHttpClient.post(this.endpoint, body, {
2468
- Authorization: `Bearer ${this.apiKey}`
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
- body.max_output_tokens = tokenLimit;
2502
+ if (tokenLimit !== void 0) {
2503
+ body.max_output_tokens = tokenLimit;
2504
+ }
2485
2505
  } else {
2486
- body.max_completion_tokens = tokenLimit;
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 Qe=Object.defineProperty;var Rt=Object.getOwnPropertyDescriptor;var At=Object.getOwnPropertyNames;var wt=Object.prototype.hasOwnProperty;var Nt=(n,e)=>{for(var t in e)Qe(n,t,{get:e[t],enumerable:!0})},kt=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of At(e))!wt.call(n,s)&&s!==t&&Qe(n,s,{get:()=>e[s],enumerable:!(o=Rt(e,s))||o.enumerable});return n};var Vt=n=>kt(Qe({},"__esModule",{value:!0}),n);var zt={};Nt(zt,{CHAT_RESPONSE_LENGTH:()=>k,CLAUDE_VISION_SUPPORTED_MODELS:()=>pe,ChatServiceFactory:()=>ie,ChatServiceHttpClient:()=>_,ClaudeChatService:()=>$,ClaudeChatServiceProvider:()=>z,DEFAULT_MAX_TOKENS:()=>vt,DEFAULT_SUMMARY_PROMPT_TEMPLATE:()=>Bt,DEFAULT_VISION_PROMPT:()=>Ht,EMOTION_TAG_CLEANUP_REGEX:()=>Ct,EMOTION_TAG_REGEX:()=>Pt,ENDPOINT_CLAUDE_API:()=>nt,ENDPOINT_GEMINI_API:()=>rt,ENDPOINT_KIMI_CHAT_COMPLETIONS_API:()=>W,ENDPOINT_OPENAI_CHAT_COMPLETIONS_API:()=>V,ENDPOINT_OPENAI_RESPONSES_API:()=>E,ENDPOINT_OPENROUTER_API:()=>at,ENDPOINT_ZAI_CHAT_COMPLETIONS_API:()=>he,EmotionParser:()=>j,GEMINI_VISION_SUPPORTED_MODELS:()=>le,GPT5_PRESETS:()=>Mt,GPT_5_MODELS:()=>Ot,GeminiChatService:()=>q,GeminiChatServiceProvider:()=>J,HttpError:()=>A,KIMI_VISION_SUPPORTED_MODELS:()=>Tt,KimiChatService:()=>Z,KimiChatServiceProvider:()=>X,MAX_TOKENS_BY_LENGTH:()=>St,MODEL_ANTHROPIC_CLAUDE_3_5_SONNET:()=>lt,MODEL_ANTHROPIC_CLAUDE_3_7_SONNET:()=>We,MODEL_ANTHROPIC_CLAUDE_4_5_HAIKU:()=>Ke,MODEL_ANTHROPIC_CLAUDE_OPUS_4:()=>He,MODEL_ANTHROPIC_CLAUDE_SONNET_4:()=>Be,MODEL_CLAUDE_3_5_HAIKU:()=>ye,MODEL_CLAUDE_3_5_SONNET:()=>Te,MODEL_CLAUDE_3_7_SONNET:()=>Se,MODEL_CLAUDE_3_HAIKU:()=>y,MODEL_CLAUDE_4_5_HAIKU:()=>Le,MODEL_CLAUDE_4_5_OPUS:()=>De,MODEL_CLAUDE_4_5_SONNET:()=>Ie,MODEL_CLAUDE_4_6_OPUS:()=>Re,MODEL_CLAUDE_4_6_SONNET:()=>be,MODEL_CLAUDE_4_OPUS:()=>xe,MODEL_CLAUDE_4_SONNET:()=>Pe,MODEL_GEMINI_2_0_FLASH:()=>Ee,MODEL_GEMINI_2_0_FLASH_LITE:()=>b,MODEL_GEMINI_2_5_FLASH:()=>Me,MODEL_GEMINI_2_5_FLASH_LITE:()=>Ce,MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17:()=>Oe,MODEL_GEMINI_2_5_PRO:()=>ve,MODEL_GLM_4_6:()=>gt,MODEL_GLM_4_6V:()=>Je,MODEL_GLM_4_6V_FLASH:()=>N,MODEL_GLM_4_6V_FLASHX:()=>Ze,MODEL_GLM_4_7:()=>H,MODEL_GLM_4_7_FLASH:()=>_t,MODEL_GLM_4_7_FLASHX:()=>dt,MODEL_GLM_5:()=>ut,MODEL_GOOGLE_GEMINI_2_5_FLASH:()=>$e,MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE_PREVIEW_09_2025:()=>ze,MODEL_GOOGLE_GEMINI_2_5_PRO:()=>je,MODEL_GPT_4O:()=>ge,MODEL_GPT_4O_MINI:()=>w,MODEL_GPT_4_1:()=>ue,MODEL_GPT_4_1_MINI:()=>de,MODEL_GPT_4_1_NANO:()=>_e,MODEL_GPT_4_5_PREVIEW:()=>fe,MODEL_GPT_5:()=>ne,MODEL_GPT_5_1:()=>D,MODEL_GPT_5_MINI:()=>re,MODEL_GPT_5_NANO:()=>G,MODEL_GPT_OSS_20B_FREE:()=>R,MODEL_KIMI_K2_5:()=>T,MODEL_MOONSHOTAI_KIMI_K2_5:()=>Ae,MODEL_O1:()=>ot,MODEL_O1_MINI:()=>tt,MODEL_O3_MINI:()=>et,MODEL_OPENAI_GPT_4O:()=>Ge,MODEL_OPENAI_GPT_4_1_MINI:()=>Fe,MODEL_OPENAI_GPT_4_1_NANO:()=>Ue,MODEL_OPENAI_GPT_5_1_CHAT:()=>we,MODEL_OPENAI_GPT_5_1_CODEX:()=>Ne,MODEL_OPENAI_GPT_5_MINI:()=>ke,MODEL_OPENAI_GPT_5_NANO:()=>Ve,MODEL_ZAI_GLM_4_5_AIR:()=>ct,MODEL_ZAI_GLM_4_5_AIR_FREE:()=>qe,MODEL_ZAI_GLM_4_7_FLASH:()=>pt,OPENROUTER_CREDITS_THRESHOLD:()=>Ut,OPENROUTER_FREE_DAILY_LIMIT_HIGH_CREDITS:()=>Ft,OPENROUTER_FREE_DAILY_LIMIT_LOW_CREDITS:()=>Gt,OPENROUTER_FREE_MODELS:()=>ce,OPENROUTER_FREE_RATE_LIMIT_PER_MINUTE:()=>ht,OPENROUTER_VISION_SUPPORTED_MODELS:()=>Et,OpenAIChatService:()=>Y,OpenAIChatServiceProvider:()=>Q,OpenRouterChatService:()=>ee,OpenRouterChatServiceProvider:()=>te,StreamTextAccumulator:()=>g,VISION_SUPPORTED_MODELS:()=>ae,ZAIChatService:()=>oe,ZAIChatServiceProvider:()=>se,ZAI_VISION_SUPPORTED_MODELS:()=>yt,allowsReasoningMinimal:()=>it,allowsReasoningNone:()=>st,buildOpenAICompatibleTools:()=>I,getMaxTokensForResponseLength:()=>M,installGASFetch:()=>bt,isGPT5Model:()=>F,isKimiVisionModel:()=>K,isOpenRouterFreeModel:()=>mt,isOpenRouterVisionModel:()=>U,isZaiToolStreamModel:()=>ft,isZaiVisionModel:()=>B,parseOpenAICompatibleOneShot:()=>x,parseOpenAICompatibleTextStream:()=>S,parseOpenAICompatibleToolStream:()=>P,processChatWithOptionalTools:()=>f,resolveVisionModel:()=>C,runOnceText:()=>$t,screenplayToText:()=>jt,textToScreenplay:()=>xt,textsToScreenplay:()=>Kt});var V="https://api.openai.com/v1/chat/completions",E="https://api.openai.com/v1/responses",G="gpt-5-nano",re="gpt-5-mini",ne="gpt-5",D="gpt-5.1",ue="gpt-4.1",de="gpt-4.1-mini",_e="gpt-4.1-nano",w="gpt-4o-mini",ge="gpt-4o",et="o3-mini",tt="o1-mini",ot="o1",fe="gpt-4.5-preview",ae=[G,re,ne,D,ue,de,_e,w,ge,fe,"o1"],Ot=[G,re,ne,D];function F(n){return Ot.includes(n)}function st(n){return n===D}function it(n){return n!==D}var rt="https://generativelanguage.googleapis.com",ve="gemini-2.5-pro",Me="gemini-2.5-flash",Ce="gemini-2.5-flash-lite",Oe="gemini-2.5-flash-lite-preview-06-17",Ee="gemini-2.0-flash",b="gemini-2.0-flash-lite",le=[ve,Me,Ce,Oe,Ee,b];var nt="https://api.anthropic.com/v1/messages",y="claude-3-haiku-20240307",ye="claude-3-5-haiku-20241022",Te="claude-3-5-sonnet-20241022",Se="claude-3-7-sonnet-20250219",Pe="claude-4-sonnet-20250514",xe="claude-4-opus-20250514",Ie="claude-sonnet-4-5-20250929",Le="claude-haiku-4-5-20251001",De="claude-opus-4-5-20251101",be="claude-sonnet-4-6",Re="claude-opus-4-6",pe=[y,ye,Te,Se,Pe,xe,Ie,Le,De,be,Re];var at="https://openrouter.ai/api/v1/chat/completions",R="openai/gpt-oss-20b:free",Ae="moonshotai/kimi-k2.5",we="openai/gpt-5.1-chat",Ne="openai/gpt-5.1-codex",ke="openai/gpt-5-mini",Ve="openai/gpt-5-nano",Ge="openai/gpt-4o",Fe="openai/gpt-4.1-mini",Ue="openai/gpt-4.1-nano",He="anthropic/claude-opus-4",Be="anthropic/claude-sonnet-4",We="anthropic/claude-3.7-sonnet",lt="anthropic/claude-3.5-sonnet",Ke="anthropic/claude-haiku-4.5",je="google/gemini-2.5-pro",$e="google/gemini-2.5-flash",ze="google/gemini-2.5-flash-lite-preview-09-2025",pt="z-ai/glm-4.7-flash",ct="z-ai/glm-4.5-air",qe="z-ai/glm-4.5-air:free",ce=[R,qe],Et=[we,Ne,ke,Ve,Ge,Fe,Ue,He,Be,We,Ke,je,$e,ze,Ae],ht=20,Gt=50,Ft=1e3,Ut=10;function mt(n){return ce.some(e=>n.includes(e))}function U(n){return Et.some(e=>n.includes(e))}var he="https://api.z.ai/api/paas/v4/chat/completions",ut="glm-5",H="glm-4.7",dt="glm-4.7-FlashX",_t="glm-4.7-Flash",gt="glm-4.6",Je="glm-4.6V",Ze="glm-4.6V-FlashX",N="glm-4.6V-Flash",yt=[Je,Ze,N];function B(n){return yt.includes(n)}function ft(n){return n.toLowerCase().startsWith("glm-4.6")}var W="https://api.moonshot.ai/v1/chat/completions",T="kimi-k2.5",Tt=[T];function K(n){return Tt.includes(n)}var k={VERY_SHORT:"veryShort",SHORT:"short",MEDIUM:"medium",LONG:"long",VERY_LONG:"veryLong",DEEP:"deep"},St={[k.VERY_SHORT]:40,[k.SHORT]:100,[k.MEDIUM]:200,[k.LONG]:300,[k.VERY_LONG]:1e3,[k.DEEP]:5e3},vt=5e3,Mt={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 M(n){return n?St[n]??vt:vt}var Ht="You are a friendly AI avatar. Comment on the situation based on the broadcast screen.",Bt=`You are a skilled summarizing assistant.
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"}},me=class me{static setFetch(e){this.fetchImpl=e}static async post(e,t,o={},s={}){let{timeout:i=3e4,retries:r=0,retryDelay:a=1e3}=s,h={...{"Content-Type":"application/json"},...o},c=null;for(let m=0;m<=r;m++)try{let u=typeof AbortController<"u",p=u?new AbortController:void 0,d=u?setTimeout(()=>p.abort(),i):void 0,v=await me.fetchImpl(e,{method:"POST",headers:h,body:typeof t=="string"?t:JSON.stringify(t),...p?{signal:p.signal}:{}});if(d&&clearTimeout(d),!v.ok){let O=await v.text();throw new A(v.status,v.statusText,O)}return v}catch(u){if(c=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 c||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 h=typeof AbortController<"u",c=h?new AbortController:void 0,m=h?setTimeout(()=>c.abort(),s):void 0,u=await me.fetchImpl(e,{method:"GET",headers:t,...c?{signal:c.signal}:{}});if(m&&clearTimeout(m),!u.ok){let p=await u.text();throw new A(u.status,u.statusText,p)}return u}catch(h){if(a=h,h instanceof A&&h.status>=400&&h.status<500)throw h;if(h instanceof Error&&h.name==="AbortError")throw new Error(`Request timeout after ${s}ms`);l<i&&await new Promise(c=>setTimeout(c,r*(l+1)))}throw a||new Error("Request failed")}};me.fetchImpl=(e,t)=>fetch(e,t);var _=me;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 Wt=["happy","sad","angry","surprised","neutral"],Pt=/\[([a-z]+)\]/i,Ct=/\[[a-z]+\]\s*/gi,j=class{static extractEmotion(e){let t=e.match(Pt);if(t){let o=t[1].toLowerCase(),s=e.replace(Ct,"").trim();return{emotion:o,cleanText:s}}return{cleanText:e}}static isValidEmotion(e){return Wt.includes(e)}static cleanEmotionTags(e){return e.replace(Ct,"").trim()}static addEmotionTag(e,t){return`[${e}] ${t}`}};function xt(n){let{emotion:e,cleanText:t}=j.extractEmotion(n);return e?{emotion:e,text:t}:{text:t}}function Kt(n){return n.map(e=>xt(e))}function jt(n){return n.emotion?j.addEmotionTag(n.emotion,n.text):n.text}async function $t(n,e){let{blocks:t}=await n.chatOnce(e,!1,()=>{});return g.getFullText(t)}var It=(n,e)=>{try{return JSON.parse(n)}catch(t){if(e){e(n,t);return}throw t}},Lt=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 h of l){let c=h.trim();if(!c||c.startsWith(":")||!c.startsWith("data:"))continue;let m=c.slice(5).trim();if(m==="[DONE]"){i=!0;break}e(m)}}};async function S(n,e,t={}){let o="";return await Lt(n,s=>{let i=It(s,t.onJsonError);if(!i)return;let r=i.choices?.[0]?.delta?.content||"";r&&(e(r),o+=r)}),o}async function P(n,e,t={}){let o=[],s=new Map,i=t.appendTextBlock??g.append;await Lt(n,l=>{let h=It(l,t.onJsonError);if(!h)return;let c=h.choices?.[0]?.delta;c?.content&&(e(c.content),i(o,c.content)),c?.tool_calls&&c.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,h)=>l[0]-h[0]).map(([l,h])=>({type:"tool_use",id:h.id,name:h.name,input:JSON.parse(h.args||"{}")}));return{blocks:[...o,...r],stop_reason:r.length?"tool_use":"end"}}function x(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 I=(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 C=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 $=class{constructor(e,t=y,o=y,s=[],i=[],r){this.provider="claude";if(this.apiKey=e,this.model=t||y,this.visionModel=o||y,this.tools=s,this.mcpServers=i,this.responseLength=r,!pe.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:M(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 h={"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&&(h["anthropic-beta"]="mcp-client-2025-04-04"),await _.post(nt,l,h)}async parseStream(e,t){let o=e.body.getReader(),s=new TextDecoder,i=[],r=new Map,a="";for(;;){let{done:l,value:h}=await o.read();if(l)break;a+=s.decode(h,{stream:!0});let c;for(;(c=a.indexOf(`
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(c=>c.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 J=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 q(e.apiKey,e.model||this.getDefaultModel(),t,e.tools||[],e.mcpServers||[],e.responseLength)}getProviderName(){return"gemini"}getSupportedModels(){return[ve,Me,Ce,Oe,Ee,b]}getDefaultModel(){return b}supportsVision(){return!0}supportsVisionForModel(e){return le.includes(e)}};var Z=class{constructor(e,t=T,o=T,s,i=W,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(!K(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(!K(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:M(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(W)}normalizeEndpoint(e){return e.replace(/\/+$/,"")}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 X=class{createChatService(e){let t=this.resolveEndpoint(e),o=e.model||this.getDefaultModel(),s=C({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 Z(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 K(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 W}normalizeEndpoint(e){return e.replace(/\/+$/,"")}};var Y=class{constructor(e,t=w,o=w,s,i=V,r=[],a,l,h,c=!1){this.provider="openai";if(this.apiKey=e,this.model=t,this.tools=s||[],this.endpoint=i,this.mcpServers=r,this.responseLength=a,this.verbosity=l,this.reasoning_effort=h,this.enableReasoningSummary=c,!ae.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===E;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===E;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===E?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);return await _.post(this.endpoint,i,{Authorization:`Bearer ${this.apiKey}`})}buildRequestBody(e,t,o,s){let i=this.endpoint===E;this.validateMCPCompatibility();let r={model:t,stream:o},a=s!==void 0?s:M(this.responseLength);i?r.max_output_tokens=a:r.max_completion_tokens=a,i?r.input=this.cleanMessagesForResponsesAPI(e):r.messages=e,F(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===V)throw new Error(`MCP servers are not supported with Chat Completions API. Current endpoint: ${this.endpoint}. Please use OpenAI Responses API endpoint: ${E}. 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===E,t=[];return this.tools.length>0&&t.push(...I(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 S(e,t)}async parseStream(e,t){return P(e,t,{appendTextBlock:g.addTextBlock})}parseOneShot(e){return x(e)}async parseResponsesStream(e,t){let o=e.body.getReader(),s=new TextDecoder,i=[],r=new Map,a="";for(;;){let{done:c,value:m}=await o.read();if(c)break;a+=s.decode(m,{stream:!0});let u="",p="",d=a.split(`
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.13.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 .",