@aituber-onair/chat 0.13.0 → 0.14.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 (53) hide show
  1. package/README.ja.md +89 -3
  2. package/README.md +86 -3
  3. package/dist/cjs/index.d.ts +2 -1
  4. package/dist/cjs/index.d.ts.map +1 -1
  5. package/dist/cjs/index.js +3 -1
  6. package/dist/cjs/index.js.map +1 -1
  7. package/dist/cjs/services/ChatServiceFactory.d.ts +2 -2
  8. package/dist/cjs/services/ChatServiceFactory.d.ts.map +1 -1
  9. package/dist/cjs/services/ChatServiceFactory.js.map +1 -1
  10. package/dist/cjs/services/providers/ChatServiceProvider.d.ts +9 -2
  11. package/dist/cjs/services/providers/ChatServiceProvider.d.ts.map +1 -1
  12. package/dist/cjs/services/providers/index.d.ts +2 -1
  13. package/dist/cjs/services/providers/index.d.ts.map +1 -1
  14. package/dist/cjs/services/providers/index.js +2 -0
  15. package/dist/cjs/services/providers/index.js.map +1 -1
  16. package/dist/cjs/services/providers/openai/OpenAIChatService.d.ts +1 -1
  17. package/dist/cjs/services/providers/openai/OpenAIChatService.d.ts.map +1 -1
  18. package/dist/cjs/services/providers/openai/OpenAIChatService.js +31 -12
  19. package/dist/cjs/services/providers/openai/OpenAIChatService.js.map +1 -1
  20. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.d.ts.map +1 -1
  21. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js +1 -1
  22. package/dist/cjs/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
  23. package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts +21 -0
  24. package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts.map +1 -0
  25. package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js +56 -0
  26. package/dist/cjs/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js.map +1 -0
  27. package/dist/esm/index.d.ts +2 -1
  28. package/dist/esm/index.d.ts.map +1 -1
  29. package/dist/esm/index.js +1 -0
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/services/ChatServiceFactory.d.ts +2 -2
  32. package/dist/esm/services/ChatServiceFactory.d.ts.map +1 -1
  33. package/dist/esm/services/ChatServiceFactory.js.map +1 -1
  34. package/dist/esm/services/providers/ChatServiceProvider.d.ts +9 -2
  35. package/dist/esm/services/providers/ChatServiceProvider.d.ts.map +1 -1
  36. package/dist/esm/services/providers/index.d.ts +2 -1
  37. package/dist/esm/services/providers/index.d.ts.map +1 -1
  38. package/dist/esm/services/providers/index.js +2 -0
  39. package/dist/esm/services/providers/index.js.map +1 -1
  40. package/dist/esm/services/providers/openai/OpenAIChatService.d.ts +1 -1
  41. package/dist/esm/services/providers/openai/OpenAIChatService.d.ts.map +1 -1
  42. package/dist/esm/services/providers/openai/OpenAIChatService.js +31 -12
  43. package/dist/esm/services/providers/openai/OpenAIChatService.js.map +1 -1
  44. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.d.ts.map +1 -1
  45. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js +1 -1
  46. package/dist/esm/services/providers/openai/OpenAIChatServiceProvider.js.map +1 -1
  47. package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts +21 -0
  48. package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.d.ts.map +1 -0
  49. package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js +52 -0
  50. package/dist/esm/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.js.map +1 -0
  51. package/dist/umd/aituber-onair-chat.js +89 -11
  52. package/dist/umd/aituber-onair-chat.min.js +6 -6
  53. package/package.json +3 -1
@@ -117,6 +117,7 @@ var AITuberOnAirChat = (() => {
117
117
  OPENROUTER_VISION_SUPPORTED_MODELS: () => OPENROUTER_VISION_SUPPORTED_MODELS,
118
118
  OpenAIChatService: () => OpenAIChatService,
119
119
  OpenAIChatServiceProvider: () => OpenAIChatServiceProvider,
120
+ OpenAICompatibleChatServiceProvider: () => OpenAICompatibleChatServiceProvider,
120
121
  OpenRouterChatService: () => OpenRouterChatService,
121
122
  OpenRouterChatServiceProvider: () => OpenRouterChatServiceProvider,
122
123
  StreamTextAccumulator: () => StreamTextAccumulator,
@@ -2317,9 +2318,8 @@ If it's in another language, summarize in that language.
2317
2318
  * @param model Name of the model to use
2318
2319
  * @param visionModel Name of the vision model
2319
2320
  */
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";
2321
+ 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) {
2322
+ this.provider = provider;
2323
2323
  this.apiKey = apiKey;
2324
2324
  this.model = model;
2325
2325
  this.tools = tools || [];
@@ -2329,7 +2329,7 @@ If it's in another language, summarize in that language.
2329
2329
  this.verbosity = verbosity;
2330
2330
  this.reasoning_effort = reasoning_effort;
2331
2331
  this.enableReasoningSummary = enableReasoningSummary;
2332
- if (!VISION_SUPPORTED_MODELS.includes(visionModel)) {
2332
+ if (validateVisionModel && !VISION_SUPPORTED_MODELS.includes(visionModel)) {
2333
2333
  throw new Error(
2334
2334
  `Model ${visionModel} does not support vision capabilities.`
2335
2335
  );
@@ -2464,9 +2464,12 @@ If it's in another language, summarize in that language.
2464
2464
  }
2465
2465
  async callOpenAI(messages, model, stream = false, maxTokens) {
2466
2466
  const body = this.buildRequestBody(messages, model, stream, maxTokens);
2467
- const res = await ChatServiceHttpClient.post(this.endpoint, body, {
2468
- Authorization: `Bearer ${this.apiKey}`
2469
- });
2467
+ const headers = {};
2468
+ const shouldSendAuthorization = this.provider !== "openai-compatible" || this.apiKey.trim() !== "";
2469
+ if (shouldSendAuthorization) {
2470
+ headers.Authorization = `Bearer ${this.apiKey}`;
2471
+ }
2472
+ const res = await ChatServiceHttpClient.post(this.endpoint, body, headers);
2470
2473
  return res;
2471
2474
  }
2472
2475
  /**
@@ -2479,11 +2482,19 @@ If it's in another language, summarize in that language.
2479
2482
  model,
2480
2483
  stream
2481
2484
  };
2482
- const tokenLimit = maxTokens !== void 0 ? maxTokens : getMaxTokensForResponseLength(this.responseLength);
2485
+ const tokenLimit = maxTokens !== void 0 ? maxTokens : this.provider === "openai-compatible" ? this.responseLength !== void 0 ? getMaxTokensForResponseLength(this.responseLength) : void 0 : getMaxTokensForResponseLength(this.responseLength);
2483
2486
  if (isResponsesAPI) {
2484
- body.max_output_tokens = tokenLimit;
2487
+ if (tokenLimit !== void 0) {
2488
+ body.max_output_tokens = tokenLimit;
2489
+ }
2485
2490
  } else {
2486
- body.max_completion_tokens = tokenLimit;
2491
+ if (tokenLimit !== void 0) {
2492
+ if (this.provider === "openai-compatible") {
2493
+ body.max_tokens = tokenLimit;
2494
+ } else {
2495
+ body.max_completion_tokens = tokenLimit;
2496
+ }
2497
+ }
2487
2498
  }
2488
2499
  if (isResponsesAPI) {
2489
2500
  body.input = this.cleanMessagesForResponsesAPI(messages);
@@ -2772,6 +2783,71 @@ If it's in another language, summarize in that language.
2772
2783
  }
2773
2784
  };
2774
2785
 
2786
+ // src/services/providers/openaiCompatible/OpenAICompatibleChatServiceProvider.ts
2787
+ var OpenAICompatibleChatServiceProvider = class {
2788
+ createChatService(options) {
2789
+ this.validateRequiredOptions(options);
2790
+ return new OpenAIChatService(
2791
+ options.apiKey?.trim() ?? "",
2792
+ options.model,
2793
+ options.visionModel ?? options.model,
2794
+ options.tools,
2795
+ options.endpoint,
2796
+ [],
2797
+ options.responseLength,
2798
+ options.verbosity,
2799
+ options.reasoning_effort,
2800
+ options.enableReasoningSummary,
2801
+ this.getProviderName(),
2802
+ false
2803
+ );
2804
+ }
2805
+ getProviderName() {
2806
+ return "openai-compatible";
2807
+ }
2808
+ /**
2809
+ * Model list depends on each compatible server implementation.
2810
+ */
2811
+ getSupportedModels() {
2812
+ return [];
2813
+ }
2814
+ supportsVision() {
2815
+ return false;
2816
+ }
2817
+ getDefaultModel() {
2818
+ return "local-model";
2819
+ }
2820
+ validateRequiredOptions(options) {
2821
+ if (options.mcpServers !== void 0) {
2822
+ throw new Error(
2823
+ "openai-compatible provider does not support mcpServers."
2824
+ );
2825
+ }
2826
+ const endpoint = options.endpoint?.trim();
2827
+ if (!endpoint) {
2828
+ throw new Error(
2829
+ "openai-compatible provider requires endpoint (full URL)."
2830
+ );
2831
+ }
2832
+ let endpointUrl;
2833
+ try {
2834
+ endpointUrl = new URL(endpoint);
2835
+ } catch {
2836
+ throw new Error(
2837
+ "openai-compatible provider requires endpoint to be a full URL."
2838
+ );
2839
+ }
2840
+ if (endpointUrl.protocol !== "http:" && endpointUrl.protocol !== "https:") {
2841
+ throw new Error(
2842
+ "openai-compatible provider requires endpoint to be a full URL."
2843
+ );
2844
+ }
2845
+ if (!options.model?.trim()) {
2846
+ throw new Error("openai-compatible provider requires model.");
2847
+ }
2848
+ }
2849
+ };
2850
+
2775
2851
  // src/services/providers/openai/OpenAIChatServiceProvider.ts
2776
2852
  var OpenAIChatServiceProvider = class {
2777
2853
  /**
@@ -2810,7 +2886,8 @@ If it's in another language, summarize in that language.
2810
2886
  optimizedOptions.responseLength,
2811
2887
  optimizedOptions.verbosity,
2812
2888
  optimizedOptions.reasoning_effort,
2813
- optimizedOptions.enableReasoningSummary
2889
+ optimizedOptions.enableReasoningSummary,
2890
+ this.getProviderName()
2814
2891
  );
2815
2892
  }
2816
2893
  /**
@@ -3508,6 +3585,7 @@ If it's in another language, summarize in that language.
3508
3585
  // src/services/providers/index.ts
3509
3586
  var DEFAULT_CHAT_SERVICE_PROVIDERS = [
3510
3587
  new OpenAIChatServiceProvider(),
3588
+ new OpenAICompatibleChatServiceProvider(),
3511
3589
  new GeminiChatServiceProvider(),
3512
3590
  new ClaudeChatServiceProvider(),
3513
3591
  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 et=Object.defineProperty;var At=Object.getOwnPropertyDescriptor;var wt=Object.getOwnPropertyNames;var Nt=Object.prototype.hasOwnProperty;var kt=(n,e)=>{for(var t in e)et(n,t,{get:e[t],enumerable:!0})},Vt=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of wt(e))!Nt.call(n,s)&&s!==t&&et(n,s,{get:()=>e[s],enumerable:!(o=At(e,s))||o.enumerable});return n};var Gt=n=>Vt(et({},"__esModule",{value:!0}),n);var qt={};kt(qt,{CHAT_RESPONSE_LENGTH:()=>V,CLAUDE_VISION_SUPPORTED_MODELS:()=>ce,ChatServiceFactory:()=>re,ChatServiceHttpClient:()=>_,ClaudeChatService:()=>z,ClaudeChatServiceProvider:()=>q,DEFAULT_MAX_TOKENS:()=>Mt,DEFAULT_SUMMARY_PROMPT_TEMPLATE:()=>Wt,DEFAULT_VISION_PROMPT:()=>Bt,EMOTION_TAG_CLEANUP_REGEX:()=>Ot,EMOTION_TAG_REGEX:()=>xt,ENDPOINT_CLAUDE_API:()=>at,ENDPOINT_GEMINI_API:()=>nt,ENDPOINT_KIMI_CHAT_COMPLETIONS_API:()=>K,ENDPOINT_OPENAI_CHAT_COMPLETIONS_API:()=>G,ENDPOINT_OPENAI_RESPONSES_API:()=>E,ENDPOINT_OPENROUTER_API:()=>lt,ENDPOINT_ZAI_CHAT_COMPLETIONS_API:()=>me,EmotionParser:()=>$,GEMINI_VISION_SUPPORTED_MODELS:()=>pe,GPT5_PRESETS:()=>Ct,GPT_5_MODELS:()=>Et,GeminiChatService:()=>J,GeminiChatServiceProvider:()=>Z,HttpError:()=>A,KIMI_VISION_SUPPORTED_MODELS:()=>Tt,KimiChatService:()=>X,KimiChatServiceProvider:()=>Y,MAX_TOKENS_BY_LENGTH:()=>Pt,MODEL_ANTHROPIC_CLAUDE_3_5_SONNET:()=>pt,MODEL_ANTHROPIC_CLAUDE_3_7_SONNET:()=>Ke,MODEL_ANTHROPIC_CLAUDE_4_5_HAIKU:()=>je,MODEL_ANTHROPIC_CLAUDE_OPUS_4:()=>Be,MODEL_ANTHROPIC_CLAUDE_SONNET_4:()=>We,MODEL_CLAUDE_3_5_HAIKU:()=>Se,MODEL_CLAUDE_3_5_SONNET:()=>Te,MODEL_CLAUDE_3_7_SONNET:()=>Pe,MODEL_CLAUDE_3_HAIKU:()=>y,MODEL_CLAUDE_4_5_HAIKU:()=>be,MODEL_CLAUDE_4_5_OPUS:()=>De,MODEL_CLAUDE_4_5_SONNET:()=>Le,MODEL_CLAUDE_4_6_OPUS:()=>Ae,MODEL_CLAUDE_4_6_SONNET:()=>Re,MODEL_CLAUDE_4_OPUS:()=>Ie,MODEL_CLAUDE_4_SONNET:()=>xe,MODEL_GEMINI_2_0_FLASH:()=>ye,MODEL_GEMINI_2_0_FLASH_LITE:()=>D,MODEL_GEMINI_2_5_FLASH:()=>Ce,MODEL_GEMINI_2_5_FLASH_LITE:()=>Oe,MODEL_GEMINI_2_5_FLASH_LITE_PREVIEW_06_17:()=>Ee,MODEL_GEMINI_2_5_PRO:()=>Me,MODEL_GLM_4_6:()=>ft,MODEL_GLM_4_6V:()=>Ze,MODEL_GLM_4_6V_FLASH:()=>k,MODEL_GLM_4_6V_FLASHX:()=>Xe,MODEL_GLM_4_7:()=>B,MODEL_GLM_4_7_FLASH:()=>gt,MODEL_GLM_4_7_FLASHX:()=>_t,MODEL_GLM_5:()=>dt,MODEL_GOOGLE_GEMINI_2_5_FLASH:()=>ze,MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE_PREVIEW_09_2025:()=>qe,MODEL_GOOGLE_GEMINI_2_5_PRO:()=>$e,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:()=>S,MODEL_MOONSHOTAI_KIMI_K2_5:()=>we,MODEL_O1:()=>st,MODEL_O1_MINI:()=>ot,MODEL_O3_MINI:()=>tt,MODEL_OPENAI_GPT_4O:()=>Fe,MODEL_OPENAI_GPT_4_1_MINI:()=>Ue,MODEL_OPENAI_GPT_4_1_NANO:()=>He,MODEL_OPENAI_GPT_5_1_CHAT:()=>Ne,MODEL_OPENAI_GPT_5_1_CODEX:()=>ke,MODEL_OPENAI_GPT_5_MINI:()=>Ve,MODEL_OPENAI_GPT_5_NANO:()=>Ge,MODEL_ZAI_GLM_4_5_AIR:()=>ht,MODEL_ZAI_GLM_4_5_AIR_FREE:()=>Je,MODEL_ZAI_GLM_4_7_FLASH:()=>ct,OPENROUTER_CREDITS_THRESHOLD:()=>Ht,OPENROUTER_FREE_DAILY_LIMIT_HIGH_CREDITS:()=>Ut,OPENROUTER_FREE_DAILY_LIMIT_LOW_CREDITS:()=>Ft,OPENROUTER_FREE_MODELS:()=>he,OPENROUTER_FREE_RATE_LIMIT_PER_MINUTE:()=>mt,OPENROUTER_VISION_SUPPORTED_MODELS:()=>yt,OpenAIChatService:()=>w,OpenAIChatServiceProvider:()=>ee,OpenAICompatibleChatServiceProvider:()=>Q,OpenRouterChatService:()=>te,OpenRouterChatServiceProvider:()=>oe,StreamTextAccumulator:()=>g,VISION_SUPPORTED_MODELS:()=>le,ZAIChatService:()=>se,ZAIChatServiceProvider:()=>ie,ZAI_VISION_SUPPORTED_MODELS:()=>St,allowsReasoningMinimal:()=>rt,allowsReasoningNone:()=>it,buildOpenAICompatibleTools:()=>I,getMaxTokensForResponseLength:()=>M,installGASFetch:()=>Rt,isGPT5Model:()=>U,isKimiVisionModel:()=>j,isOpenRouterFreeModel:()=>ut,isOpenRouterVisionModel:()=>H,isZaiToolStreamModel:()=>vt,isZaiVisionModel:()=>W,parseOpenAICompatibleOneShot:()=>x,parseOpenAICompatibleTextStream:()=>T,parseOpenAICompatibleToolStream:()=>P,processChatWithOptionalTools:()=>f,resolveVisionModel:()=>C,runOnceText:()=>zt,screenplayToText:()=>$t,textToScreenplay:()=>It,textsToScreenplay:()=>jt});var G="https://api.openai.com/v1/chat/completions",E="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",tt="o3-mini",ot="o1-mini",st="o1",ve="gpt-4.5-preview",le=[F,ne,ae,b,de,_e,ge,N,fe,ve,"o1"],Et=[F,ne,ae,b];function U(n){return Et.includes(n)}function it(n){return n===b}function rt(n){return n!==b}var nt="https://generativelanguage.googleapis.com",Me="gemini-2.5-pro",Ce="gemini-2.5-flash",Oe="gemini-2.5-flash-lite",Ee="gemini-2.5-flash-lite-preview-06-17",ye="gemini-2.0-flash",D="gemini-2.0-flash-lite",pe=[Me,Ce,Oe,Ee,ye,D];var at="https://api.anthropic.com/v1/messages",y="claude-3-haiku-20240307",Se="claude-3-5-haiku-20241022",Te="claude-3-5-sonnet-20241022",Pe="claude-3-7-sonnet-20250219",xe="claude-4-sonnet-20250514",Ie="claude-4-opus-20250514",Le="claude-sonnet-4-5-20250929",be="claude-haiku-4-5-20251001",De="claude-opus-4-5-20251101",Re="claude-sonnet-4-6",Ae="claude-opus-4-6",ce=[y,Se,Te,Pe,xe,Ie,Le,be,De,Re,Ae];var lt="https://openrouter.ai/api/v1/chat/completions",R="openai/gpt-oss-20b:free",we="moonshotai/kimi-k2.5",Ne="openai/gpt-5.1-chat",ke="openai/gpt-5.1-codex",Ve="openai/gpt-5-mini",Ge="openai/gpt-5-nano",Fe="openai/gpt-4o",Ue="openai/gpt-4.1-mini",He="openai/gpt-4.1-nano",Be="anthropic/claude-opus-4",We="anthropic/claude-sonnet-4",Ke="anthropic/claude-3.7-sonnet",pt="anthropic/claude-3.5-sonnet",je="anthropic/claude-haiku-4.5",$e="google/gemini-2.5-pro",ze="google/gemini-2.5-flash",qe="google/gemini-2.5-flash-lite-preview-09-2025",ct="z-ai/glm-4.7-flash",ht="z-ai/glm-4.5-air",Je="z-ai/glm-4.5-air:free",he=[R,Je],yt=[Ne,ke,Ve,Ge,Fe,Ue,He,Be,We,Ke,je,$e,ze,qe,we],mt=20,Ft=50,Ut=1e3,Ht=10;function ut(n){return he.some(e=>n.includes(e))}function H(n){return yt.some(e=>n.includes(e))}var me="https://api.z.ai/api/paas/v4/chat/completions",dt="glm-5",B="glm-4.7",_t="glm-4.7-FlashX",gt="glm-4.7-Flash",ft="glm-4.6",Ze="glm-4.6V",Xe="glm-4.6V-FlashX",k="glm-4.6V-Flash",St=[Ze,Xe,k];function W(n){return St.includes(n)}function vt(n){return n.toLowerCase().startsWith("glm-4.6")}var K="https://api.moonshot.ai/v1/chat/completions",S="kimi-k2.5",Tt=[S];function j(n){return Tt.includes(n)}var V={VERY_SHORT:"veryShort",SHORT:"short",MEDIUM:"medium",LONG:"long",VERY_LONG:"veryLong",DEEP:"deep"},Pt={[V.VERY_SHORT]:40,[V.SHORT]:100,[V.MEDIUM]:200,[V.LONG]:300,[V.VERY_LONG]:1e3,[V.DEEP]:5e3},Mt=5e3,Ct={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?Pt[n]??Mt:Mt}var Bt="You are a friendly AI avatar. Comment on the situation based on the broadcast screen.",Wt=`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,m={...{"Content-Type":"application/json"},...o},c=null;for(let h=0;h<=r;h++)try{let u=typeof AbortController<"u",p=u?new AbortController:void 0,d=u?setTimeout(()=>p.abort(),i):void 0,v=await ue.fetchImpl(e,{method:"POST",headers:m,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`);h<r&&await new Promise(p=>setTimeout(p,a*(h+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 m=typeof AbortController<"u",c=m?new AbortController:void 0,h=m?setTimeout(()=>c.abort(),s):void 0,u=await ue.fetchImpl(e,{method:"GET",headers:t,...c?{signal:c.signal}:{}});if(h&&clearTimeout(h),!u.ok){let p=await u.text();throw new A(u.status,u.statusText,p)}return u}catch(m){if(a=m,m instanceof A&&m.status>=400&&m.status<500)throw m;if(m instanceof Error&&m.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")}};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 Kt=["happy","sad","angry","surprised","neutral"],xt=/\[([a-z]+)\]/i,Ot=/\[[a-z]+\]\s*/gi,$=class{static extractEmotion(e){let t=e.match(xt);if(t){let o=t[1].toLowerCase(),s=e.replace(Ot,"").trim();return{emotion:o,cleanText:s}}return{cleanText:e}}static isValidEmotion(e){return Kt.includes(e)}static cleanEmotionTags(e){return e.replace(Ot,"").trim()}static addEmotionTag(e,t){return`[${e}] ${t}`}};function It(n){let{emotion:e,cleanText:t}=$.extractEmotion(n);return e?{emotion:e,text:t}:{text:t}}function jt(n){return n.map(e=>It(e))}function $t(n){return n.emotion?$.addEmotionTag(n.emotion,n.text):n.text}async function zt(n,e){let{blocks:t}=await n.chatOnce(e,!1,()=>{});return g.getFullText(t)}var Lt=(n,e)=>{try{return JSON.parse(n)}catch(t){if(e){e(n,t);return}throw t}},bt=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 m of l){let c=m.trim();if(!c||c.startsWith(":")||!c.startsWith("data:"))continue;let h=c.slice(5).trim();if(h==="[DONE]"){i=!0;break}e(h)}}};async function T(n,e,t={}){let o="";return await bt(n,s=>{let i=Lt(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 bt(n,l=>{let m=Lt(l,t.onJsonError);if(!m)return;let c=m.choices?.[0]?.delta;c?.content&&(e(c.content),i(o,c.content)),c?.tool_calls&&c.tool_calls.forEach(h=>{let u=s.get(h.index)??{id:h.id,name:h.function?.name,args:""};u.args+=h.function?.arguments||"",s.set(h.index,u)})});let r=Array.from(s.entries()).sort((l,m)=>l[0]-m[0]).map(([l,m])=>({type:"tool_use",id:m.id,name:m.name,input:JSON.parse(m.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 z=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,!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(h=>h.role==="system")?.content??"",r=e.filter(h=>h.role!=="system"),a=r.some(h=>Array.isArray(h.content)&&h.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(h=>({name:h.name,description:h.description,input_schema:h.parameters})),l.tool_choice={type:"auto"}),this.mcpServers.length>0&&(l.mcp_servers=this.mcpServers);let m={"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&&(m["anthropic-beta"]="mcp-client-2025-04-04"),await _.post(at,l,m)}async parseStream(e,t){let o=e.body.getReader(),s=new TextDecoder,i=[],r=new Map,a="";for(;;){let{done:l,value:m}=await o.read();if(l)break;a+=s.decode(m,{stream:!0});let c;for(;(c=a.indexOf(`
12
+ `))!==-1;){let h=a.slice(0,c).trim();if(a=a.slice(c+1),!h.startsWith("data:"))continue;let u=h.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 q=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 z(e.apiKey,e.model||this.getDefaultModel(),t,e.tools??[],e.mcpServers??[],e.responseLength)}getProviderName(){return"claude"}getSupportedModels(){return[y,Se,Te,Pe,xe,Ie,Le,be,De,Re,Ae]}getDefaultModel(){return y}supportsVision(){return!0}supportsVisionForModel(e){return ce.includes(e)}};var Ye=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=Ye.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 m=async(d,v)=>{let O=o?"streamGenerateContent":"generateContent",L=o?"?alt=sse":"",Qe=`${nt}/${d}/models/${t}:${O}${L}${L?"&":"?"}key=${this.apiKey}`;return _.post(Qe,v)},c=/flash[-_]lite/.test(t),h=/gemini-2\.5/.test(t),u=c||h?"v1beta":"v1",p=async()=>{try{let d=u==="v1"?a:this.adaptKeysForApi(a);return await m(u,d)}catch(d){if(!(c||h)&&/Unknown name|Cannot find field|404/.test(d.message))return await m("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 m=await(await _.get(a.image_url.url)).blob(),c=await this.blobToBase64(m);s.push({inlineData:{mimeType:m.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 h;try{h=JSON.parse(c)}catch{return}for(let u of h.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:h}=await o.read();if(c)break;a+=s.decode(h,{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 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 J(e.apiKey,e.model||this.getDefaultModel(),t,e.tools||[],e.mcpServers||[],e.responseLength)}getProviderName(){return"gemini"}getSupportedModels(){return[Me,Ce,Oe,Ee,ye,D]}getDefaultModel(){return D}supportsVision(){return!0}supportsVisionForModel(e){return pe.includes(e)}};var X=class{constructor(e,t=S,o=S,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: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(K)}normalizeEndpoint(e){return e.replace(/\/+$/,"")}buildToolsDefinition(){return I(this.tools,"chat-completions")}async handleStream(e,t){return T(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 Y=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 X(e.apiKey,o,s,i,t,e.responseLength,e.responseFormat,a)}getProviderName(){return"kimi"}getSupportedModels(){return[S]}getDefaultModel(){return S}getDefaultVisionModel(){return S}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,m,c=!1,h="openai",u=!0){if(this.provider=h,this.apiKey=e,this.model=t,this.tools=s||[],this.endpoint=i,this.mcpServers=r,this.responseLength=a,this.verbosity=l,this.reasoning_effort=m,this.enableReasoningSummary=c,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===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),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===E;this.validateMCPCompatibility();let r={model:t,stream:o},a=s!==void 0?s:this.provider==="openai-compatible"?this.responseLength!==void 0?M(this.responseLength):void 0:M(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: ${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 T(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:h}=await o.read();if(c)break;a+=s.decode(h,{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),Qe=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){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=C({model:t.model,visionModel:t.visionModel,defaultModel:this.getDefaultModel(),defaultVisionModel:this.getDefaultModel(),supportsVisionForModel:m=>this.supportsVisionForModel(m),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?E: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,tt,ot,"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=Ct[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"&&!it(e)?this.getDefaultReasoningEffortForModel(e):t==="minimal"&&!rt(e)?"none":t}};var te=class{constructor(e,t=R,o=R,s,i=lt,r,a,l,m,c,h){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=m,this.includeReasoning=c,this.reasoningMaxTokens=h,this.visionModel=o}getModel(){return this.model}getVisionModel(){return this.visionModel}async applyRateLimiting(){if(!ut(this.model))return;let e=Date.now(),t=e-this.lastRequestTime;if(t>6e4&&(this.requestCount=0),this.requestCount>=mt){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: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 T(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 oe=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 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,Je,Ne,ke,Ve,Ge,Fe,Ue,He,Be,We,Ke,pt,je,$e,ze,qe,ct,ht,we]}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=B,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(!W(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(!W(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&&vt(t)&&(i.tool_stream=!0)),i}buildToolsDefinition(){return I(this.tools,"chat-completions")}async handleStream(e,t){return T(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 ie=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 se(e.apiKey,t,o,s,e.endpoint||me,e.responseLength,e.responseFormat,i)}getProviderName(){return"zai"}getSupportedModels(){return[dt,B,_t,gt,ft,Ze,Xe,k]}getDefaultModel(){return B}getDefaultVisionModel(){return k}supportsVision(){return!0}supportsVisionForModel(e){return W(e)}};var Dt=[new ee,new Q,new Z,new q,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;Dt.forEach(n=>re.registerProvider(n));function Rt(){_.setFetch(async(n,e={})=>{let t=(e.method||"GET").toString().toUpperCase(),o=e.headers,s={};if(Array.isArray(o))for(let[h,u]of o)s[h]=String(u);else if(o&&typeof o=="object")for(let[h,u]of Object.entries(o))s[h]=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(),m=a.getContentText();return{ok:l>=200&&l<300,status:l,statusText:String(l),text:async()=>m,json:async()=>m?JSON.parse(m):null}})}return Gt(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.14.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 .",