@aituber-onair/chat 0.22.0 → 0.24.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 (81) hide show
  1. package/README.ja.md +18 -2
  2. package/README.md +18 -2
  3. package/dist/cjs/constants/geminiNano.d.ts +6 -0
  4. package/dist/cjs/constants/geminiNano.d.ts.map +1 -0
  5. package/dist/cjs/constants/geminiNano.js +9 -0
  6. package/dist/cjs/constants/geminiNano.js.map +1 -0
  7. package/dist/cjs/constants/index.d.ts +2 -0
  8. package/dist/cjs/constants/index.d.ts.map +1 -1
  9. package/dist/cjs/constants/index.js +2 -0
  10. package/dist/cjs/constants/index.js.map +1 -1
  11. package/dist/cjs/constants/xai.d.ts +11 -0
  12. package/dist/cjs/constants/xai.d.ts.map +1 -0
  13. package/dist/cjs/constants/xai.js +24 -0
  14. package/dist/cjs/constants/xai.js.map +1 -0
  15. package/dist/cjs/index.d.ts +5 -1
  16. package/dist/cjs/index.d.ts.map +1 -1
  17. package/dist/cjs/index.js +11 -1
  18. package/dist/cjs/index.js.map +1 -1
  19. package/dist/cjs/services/providers/ChatServiceProvider.d.ts +15 -0
  20. package/dist/cjs/services/providers/ChatServiceProvider.d.ts.map +1 -1
  21. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.d.ts +37 -0
  22. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.d.ts.map +1 -0
  23. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.js +128 -0
  24. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatService.js.map +1 -0
  25. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.d.ts +15 -0
  26. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.d.ts.map +1 -0
  27. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.js +35 -0
  28. package/dist/cjs/services/providers/geminiNano/GeminiNanoChatServiceProvider.js.map +1 -0
  29. package/dist/cjs/services/providers/index.d.ts +3 -1
  30. package/dist/cjs/services/providers/index.d.ts.map +1 -1
  31. package/dist/cjs/services/providers/index.js +4 -0
  32. package/dist/cjs/services/providers/index.js.map +1 -1
  33. package/dist/cjs/services/providers/xai/XAIChatService.d.ts +65 -0
  34. package/dist/cjs/services/providers/xai/XAIChatService.d.ts.map +1 -0
  35. package/dist/cjs/services/providers/xai/XAIChatService.js +150 -0
  36. package/dist/cjs/services/providers/xai/XAIChatService.js.map +1 -0
  37. package/dist/cjs/services/providers/xai/XAIChatServiceProvider.d.ts +38 -0
  38. package/dist/cjs/services/providers/xai/XAIChatServiceProvider.d.ts.map +1 -0
  39. package/dist/cjs/services/providers/xai/XAIChatServiceProvider.js +76 -0
  40. package/dist/cjs/services/providers/xai/XAIChatServiceProvider.js.map +1 -0
  41. package/dist/esm/constants/geminiNano.d.ts +6 -0
  42. package/dist/esm/constants/geminiNano.d.ts.map +1 -0
  43. package/dist/esm/constants/geminiNano.js +6 -0
  44. package/dist/esm/constants/geminiNano.js.map +1 -0
  45. package/dist/esm/constants/index.d.ts +2 -0
  46. package/dist/esm/constants/index.d.ts.map +1 -1
  47. package/dist/esm/constants/index.js +2 -0
  48. package/dist/esm/constants/index.js.map +1 -1
  49. package/dist/esm/constants/xai.d.ts +11 -0
  50. package/dist/esm/constants/xai.d.ts.map +1 -0
  51. package/dist/esm/constants/xai.js +20 -0
  52. package/dist/esm/constants/xai.js.map +1 -0
  53. package/dist/esm/index.d.ts +5 -1
  54. package/dist/esm/index.d.ts.map +1 -1
  55. package/dist/esm/index.js +6 -0
  56. package/dist/esm/index.js.map +1 -1
  57. package/dist/esm/services/providers/ChatServiceProvider.d.ts +15 -0
  58. package/dist/esm/services/providers/ChatServiceProvider.d.ts.map +1 -1
  59. package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.d.ts +37 -0
  60. package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.d.ts.map +1 -0
  61. package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.js +124 -0
  62. package/dist/esm/services/providers/geminiNano/GeminiNanoChatService.js.map +1 -0
  63. package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.d.ts +15 -0
  64. package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.d.ts.map +1 -0
  65. package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.js +31 -0
  66. package/dist/esm/services/providers/geminiNano/GeminiNanoChatServiceProvider.js.map +1 -0
  67. package/dist/esm/services/providers/index.d.ts +3 -1
  68. package/dist/esm/services/providers/index.d.ts.map +1 -1
  69. package/dist/esm/services/providers/index.js +4 -0
  70. package/dist/esm/services/providers/index.js.map +1 -1
  71. package/dist/esm/services/providers/xai/XAIChatService.d.ts +65 -0
  72. package/dist/esm/services/providers/xai/XAIChatService.d.ts.map +1 -0
  73. package/dist/esm/services/providers/xai/XAIChatService.js +146 -0
  74. package/dist/esm/services/providers/xai/XAIChatService.js.map +1 -0
  75. package/dist/esm/services/providers/xai/XAIChatServiceProvider.d.ts +38 -0
  76. package/dist/esm/services/providers/xai/XAIChatServiceProvider.d.ts.map +1 -0
  77. package/dist/esm/services/providers/xai/XAIChatServiceProvider.js +72 -0
  78. package/dist/esm/services/providers/xai/XAIChatServiceProvider.js.map +1 -0
  79. package/dist/umd/aituber-onair-chat.js +387 -0
  80. package/dist/umd/aituber-onair-chat.min.js +11 -6
  81. package/package.json +1 -1
@@ -38,13 +38,17 @@ var AITuberOnAirChat = (() => {
38
38
  ENDPOINT_OPENAI_CHAT_COMPLETIONS_API: () => ENDPOINT_OPENAI_CHAT_COMPLETIONS_API,
39
39
  ENDPOINT_OPENAI_RESPONSES_API: () => ENDPOINT_OPENAI_RESPONSES_API,
40
40
  ENDPOINT_OPENROUTER_API: () => ENDPOINT_OPENROUTER_API,
41
+ ENDPOINT_XAI_CHAT_COMPLETIONS_API: () => ENDPOINT_XAI_CHAT_COMPLETIONS_API,
41
42
  ENDPOINT_ZAI_CHAT_COMPLETIONS_API: () => ENDPOINT_ZAI_CHAT_COMPLETIONS_API,
42
43
  EmotionParser: () => EmotionParser,
44
+ GEMINI_NANO_MAX_CONTEXT_MESSAGES: () => GEMINI_NANO_MAX_CONTEXT_MESSAGES,
43
45
  GEMINI_VISION_SUPPORTED_MODELS: () => GEMINI_VISION_SUPPORTED_MODELS,
44
46
  GPT5_PRESETS: () => GPT5_PRESETS,
45
47
  GPT_5_MODELS: () => GPT_5_MODELS,
46
48
  GeminiChatService: () => GeminiChatService,
47
49
  GeminiChatServiceProvider: () => GeminiChatServiceProvider,
50
+ GeminiNanoChatService: () => GeminiNanoChatService,
51
+ GeminiNanoChatServiceProvider: () => GeminiNanoChatServiceProvider,
48
52
  HttpError: () => HttpError,
49
53
  KIMI_VISION_SUPPORTED_MODELS: () => KIMI_VISION_SUPPORTED_MODELS,
50
54
  KimiChatService: () => KimiChatService,
@@ -76,6 +80,7 @@ var AITuberOnAirChat = (() => {
76
80
  MODEL_GEMINI_3_1_PRO_PREVIEW: () => MODEL_GEMINI_3_1_PRO_PREVIEW,
77
81
  MODEL_GEMINI_3_FLASH_PREVIEW: () => MODEL_GEMINI_3_FLASH_PREVIEW,
78
82
  MODEL_GEMINI_3_PRO_PREVIEW: () => MODEL_GEMINI_3_PRO_PREVIEW,
83
+ MODEL_GEMINI_NANO: () => MODEL_GEMINI_NANO,
79
84
  MODEL_GLM_4_6: () => MODEL_GLM_4_6,
80
85
  MODEL_GLM_4_6V: () => MODEL_GLM_4_6V,
81
86
  MODEL_GLM_4_6V_FLASH: () => MODEL_GLM_4_6V_FLASH,
@@ -102,6 +107,10 @@ var AITuberOnAirChat = (() => {
102
107
  MODEL_GPT_5_MINI: () => MODEL_GPT_5_MINI,
103
108
  MODEL_GPT_5_NANO: () => MODEL_GPT_5_NANO,
104
109
  MODEL_GPT_OSS_20B_FREE: () => MODEL_GPT_OSS_20B_FREE,
110
+ MODEL_GROK_4_1_FAST_NON_REASONING: () => MODEL_GROK_4_1_FAST_NON_REASONING,
111
+ MODEL_GROK_4_1_FAST_REASONING: () => MODEL_GROK_4_1_FAST_REASONING,
112
+ MODEL_GROK_4_20_NON_REASONING: () => MODEL_GROK_4_20_NON_REASONING,
113
+ MODEL_GROK_4_20_REASONING: () => MODEL_GROK_4_20_REASONING,
105
114
  MODEL_KIMI_K2_5: () => MODEL_KIMI_K2_5,
106
115
  MODEL_MOONSHOTAI_KIMI_K2_5: () => MODEL_MOONSHOTAI_KIMI_K2_5,
107
116
  MODEL_O1: () => MODEL_O1,
@@ -130,6 +139,9 @@ var AITuberOnAirChat = (() => {
130
139
  OpenRouterChatServiceProvider: () => OpenRouterChatServiceProvider,
131
140
  StreamTextAccumulator: () => StreamTextAccumulator,
132
141
  VISION_SUPPORTED_MODELS: () => VISION_SUPPORTED_MODELS,
142
+ XAIChatService: () => XAIChatService,
143
+ XAIChatServiceProvider: () => XAIChatServiceProvider,
144
+ XAI_VISION_SUPPORTED_MODELS: () => XAI_VISION_SUPPORTED_MODELS,
133
145
  ZAIChatService: () => ZAIChatService,
134
146
  ZAIChatServiceProvider: () => ZAIChatServiceProvider,
135
147
  ZAI_VISION_SUPPORTED_MODELS: () => ZAI_VISION_SUPPORTED_MODELS,
@@ -146,6 +158,7 @@ var AITuberOnAirChat = (() => {
146
158
  isOpenRouterFreeModel: () => isOpenRouterFreeModel,
147
159
  isOpenRouterVisionModel: () => isOpenRouterVisionModel,
148
160
  isResponsesOnlyGPT5Model: () => isResponsesOnlyGPT5Model,
161
+ isXaiVisionModel: () => isXaiVisionModel,
149
162
  isZaiToolStreamModel: () => isZaiToolStreamModel,
150
163
  isZaiVisionModel: () => isZaiVisionModel,
151
164
  parseOpenAICompatibleOneShot: () => parseOpenAICompatibleOneShot,
@@ -362,6 +375,22 @@ var AITuberOnAirChat = (() => {
362
375
  return model.toLowerCase().startsWith("glm-4.6");
363
376
  }
364
377
 
378
+ // src/constants/xai.ts
379
+ var ENDPOINT_XAI_CHAT_COMPLETIONS_API = "https://api.x.ai/v1/chat/completions";
380
+ var MODEL_GROK_4_20_REASONING = "grok-4.20-0309-reasoning";
381
+ var MODEL_GROK_4_20_NON_REASONING = "grok-4.20-0309-non-reasoning";
382
+ var MODEL_GROK_4_1_FAST_REASONING = "grok-4-1-fast-reasoning";
383
+ var MODEL_GROK_4_1_FAST_NON_REASONING = "grok-4-1-fast-non-reasoning";
384
+ var XAI_VISION_SUPPORTED_MODELS = [
385
+ MODEL_GROK_4_20_REASONING,
386
+ MODEL_GROK_4_20_NON_REASONING,
387
+ MODEL_GROK_4_1_FAST_REASONING,
388
+ MODEL_GROK_4_1_FAST_NON_REASONING
389
+ ];
390
+ function isXaiVisionModel(model) {
391
+ return XAI_VISION_SUPPORTED_MODELS.includes(model);
392
+ }
393
+
365
394
  // src/constants/kimi.ts
366
395
  var ENDPOINT_KIMI_CHAT_COMPLETIONS_API = "https://api.moonshot.ai/v1/chat/completions";
367
396
  var MODEL_KIMI_K2_5 = "kimi-k2.5";
@@ -427,6 +456,10 @@ If it's in English, summarize in English.
427
456
  If it's in another language, summarize in that language.
428
457
  `;
429
458
 
459
+ // src/constants/geminiNano.ts
460
+ var MODEL_GEMINI_NANO = "gemini-nano";
461
+ var GEMINI_NANO_MAX_CONTEXT_MESSAGES = 20;
462
+
430
463
  // src/utils/chatServiceHttpClient.ts
431
464
  var HttpError = class extends Error {
432
465
  constructor(status, statusText, body) {
@@ -2347,6 +2380,139 @@ If it's in another language, summarize in that language.
2347
2380
  }
2348
2381
  };
2349
2382
 
2383
+ // src/services/providers/geminiNano/GeminiNanoChatService.ts
2384
+ function getLanguageModelAPI() {
2385
+ if (typeof globalThis !== "undefined" && "LanguageModel" in globalThis) {
2386
+ return globalThis.LanguageModel;
2387
+ }
2388
+ return void 0;
2389
+ }
2390
+ var GeminiNanoChatService = class {
2391
+ constructor(options = {}) {
2392
+ this.provider = "gemini-nano";
2393
+ this.expectedInputLanguages = options.expectedInputLanguages ?? ["ja"];
2394
+ this.expectedOutputLanguages = options.expectedOutputLanguages ?? ["ja"];
2395
+ this._responseLength = options.responseLength;
2396
+ void this._responseLength;
2397
+ }
2398
+ getModel() {
2399
+ return MODEL_GEMINI_NANO;
2400
+ }
2401
+ getVisionModel() {
2402
+ return MODEL_GEMINI_NANO;
2403
+ }
2404
+ /**
2405
+ * Process chat messages using Gemini Nano.
2406
+ * Non-streaming: calls onPartialResponse once with the full response,
2407
+ * then calls onCompleteResponse.
2408
+ */
2409
+ async processChat(messages, onPartialResponse, onCompleteResponse) {
2410
+ const response = await this.generateResponse(messages);
2411
+ onPartialResponse(response);
2412
+ await onCompleteResponse(response);
2413
+ }
2414
+ async processVisionChat(_messages, _onPartialResponse, _onCompleteResponse) {
2415
+ throw new Error("Gemini Nano does not support vision capabilities.");
2416
+ }
2417
+ async chatOnce(messages, _stream = false, onPartialResponse = () => {
2418
+ }, _maxTokens) {
2419
+ const response = await this.generateResponse(messages);
2420
+ onPartialResponse(response);
2421
+ return {
2422
+ blocks: [{ type: "text", text: response }],
2423
+ stop_reason: "end"
2424
+ };
2425
+ }
2426
+ async visionChatOnce(_messages, _stream = false, _onPartialResponse = () => {
2427
+ }, _maxTokens) {
2428
+ throw new Error("Gemini Nano does not support vision capabilities.");
2429
+ }
2430
+ /**
2431
+ * Core logic: extract system prompt, manage session, call prompt().
2432
+ */
2433
+ async generateResponse(messages) {
2434
+ const api = getLanguageModelAPI();
2435
+ if (!api) {
2436
+ throw new Error(
2437
+ "Gemini Nano is not available in this environment. Chrome 138+ with Prompt API enabled is required."
2438
+ );
2439
+ }
2440
+ const availability = await api.availability();
2441
+ if (availability !== "available" && availability !== "downloadable") {
2442
+ throw new Error(
2443
+ `Gemini Nano Prompt API is not ready in this environment. LanguageModel.availability() returned "${availability}". Expected "available" or "downloadable".`
2444
+ );
2445
+ }
2446
+ const systemMessages = messages.filter((m) => m.role === "system");
2447
+ const systemPrompt = systemMessages.map((m) => m.content).join("\n");
2448
+ const conversationMessages = messages.filter((m) => m.role !== "system").slice(-GEMINI_NANO_MAX_CONTEXT_MESSAGES);
2449
+ const lastUserMessage = [...conversationMessages].reverse().find((m) => m.role === "user");
2450
+ if (!lastUserMessage) {
2451
+ throw new Error("No user message found in the provided messages.");
2452
+ }
2453
+ const session = await this.createSession(
2454
+ api,
2455
+ systemPrompt,
2456
+ conversationMessages
2457
+ );
2458
+ try {
2459
+ return await session.prompt(lastUserMessage.content);
2460
+ } finally {
2461
+ try {
2462
+ session.destroy();
2463
+ } catch {
2464
+ }
2465
+ }
2466
+ }
2467
+ /**
2468
+ * Create a new LanguageModel session with system prompt and context history.
2469
+ * Context history (excluding the last user message) is embedded in the system prompt.
2470
+ */
2471
+ async createSession(api, systemPrompt, contextHistory) {
2472
+ let prompt = systemPrompt;
2473
+ const historyMessages = contextHistory.slice(0, -1);
2474
+ if (historyMessages.length > 0) {
2475
+ const history = historyMessages.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n");
2476
+ prompt += "\n\n\u4EE5\u4E0B\u306F\u3053\u308C\u307E\u3067\u306E\u4F1A\u8A71\u5C65\u6B74\u3067\u3059\u3002\u3053\u306E\u6587\u8108\u3092\u8E0F\u307E\u3048\u3066\u56DE\u7B54\u3057\u3066\u304F\u3060\u3055\u3044:\n" + history;
2477
+ }
2478
+ return api.create({
2479
+ systemPrompt: prompt,
2480
+ expectedInputs: [
2481
+ { type: "text", languages: this.expectedInputLanguages }
2482
+ ],
2483
+ expectedOutputs: [
2484
+ { type: "text", languages: this.expectedOutputLanguages }
2485
+ ]
2486
+ });
2487
+ }
2488
+ };
2489
+
2490
+ // src/services/providers/geminiNano/GeminiNanoChatServiceProvider.ts
2491
+ var GeminiNanoChatServiceProvider = class {
2492
+ createChatService(options) {
2493
+ return new GeminiNanoChatService({
2494
+ expectedInputLanguages: options.expectedInputLanguages,
2495
+ expectedOutputLanguages: options.expectedOutputLanguages,
2496
+ responseLength: options.responseLength
2497
+ });
2498
+ }
2499
+ getProviderName() {
2500
+ return "gemini-nano";
2501
+ }
2502
+ getSupportedModels() {
2503
+ return [MODEL_GEMINI_NANO];
2504
+ }
2505
+ getDefaultModel() {
2506
+ return MODEL_GEMINI_NANO;
2507
+ }
2508
+ supportsVision() {
2509
+ return false;
2510
+ }
2511
+ getVisionSupportLevel() {
2512
+ return "unsupported";
2513
+ }
2514
+ };
2515
+
2350
2516
  // src/services/providers/kimi/KimiChatService.ts
2351
2517
  var KimiChatService = class {
2352
2518
  /**
@@ -3734,6 +3900,225 @@ If it's in another language, summarize in that language.
3734
3900
  }
3735
3901
  };
3736
3902
 
3903
+ // src/services/providers/xai/XAIChatService.ts
3904
+ var XAIChatService = class {
3905
+ /**
3906
+ * Constructor
3907
+ * @param apiKey xAI API key
3908
+ * @param model Name of the model to use
3909
+ * @param visionModel Name of the vision model
3910
+ */
3911
+ constructor(apiKey, model = MODEL_GROK_4_1_FAST_NON_REASONING, visionModel = MODEL_GROK_4_1_FAST_NON_REASONING, tools, endpoint = ENDPOINT_XAI_CHAT_COMPLETIONS_API, responseLength) {
3912
+ /** Provider name */
3913
+ this.provider = "xai";
3914
+ this.apiKey = apiKey;
3915
+ this.model = model;
3916
+ this.tools = tools || [];
3917
+ this.endpoint = endpoint;
3918
+ this.responseLength = responseLength;
3919
+ this.visionModel = visionModel;
3920
+ }
3921
+ /**
3922
+ * Get the current model name
3923
+ */
3924
+ getModel() {
3925
+ return this.model;
3926
+ }
3927
+ /**
3928
+ * Get the current vision model name
3929
+ */
3930
+ getVisionModel() {
3931
+ return this.visionModel;
3932
+ }
3933
+ /**
3934
+ * Process chat messages
3935
+ */
3936
+ async processChat(messages, onPartialResponse, onCompleteResponse) {
3937
+ await processChatWithOptionalTools({
3938
+ hasTools: this.tools.length > 0,
3939
+ runWithoutTools: async () => {
3940
+ const res = await this.callXAI(messages, this.model, true);
3941
+ return this.handleStream(res, onPartialResponse);
3942
+ },
3943
+ runWithTools: () => this.chatOnce(messages, true, onPartialResponse),
3944
+ onCompleteResponse,
3945
+ toolErrorMessage: "processChat received tool_calls. ChatProcessor must use chatOnce() loop when tools are enabled."
3946
+ });
3947
+ }
3948
+ /**
3949
+ * Process chat messages with images
3950
+ */
3951
+ async processVisionChat(messages, onPartialResponse, onCompleteResponse) {
3952
+ if (!isXaiVisionModel(this.visionModel)) {
3953
+ throw new Error(
3954
+ `Model ${this.visionModel} does not support vision capabilities.`
3955
+ );
3956
+ }
3957
+ await processChatWithOptionalTools({
3958
+ hasTools: this.tools.length > 0,
3959
+ runWithoutTools: async () => {
3960
+ const res = await this.callXAI(messages, this.visionModel, true);
3961
+ return this.handleStream(res, onPartialResponse);
3962
+ },
3963
+ runWithTools: () => this.visionChatOnce(messages, true, onPartialResponse),
3964
+ onCompleteResponse,
3965
+ toolErrorMessage: "processVisionChat received tool_calls. ChatProcessor must use visionChatOnce() loop when tools are enabled."
3966
+ });
3967
+ }
3968
+ /**
3969
+ * Process chat messages with tools (text only)
3970
+ */
3971
+ async chatOnce(messages, stream = true, onPartialResponse = () => {
3972
+ }, maxTokens) {
3973
+ const res = await this.callXAI(messages, this.model, stream, maxTokens);
3974
+ return this.parseResponse(res, stream, onPartialResponse);
3975
+ }
3976
+ /**
3977
+ * Process vision chat messages with tools
3978
+ */
3979
+ async visionChatOnce(messages, stream = false, onPartialResponse = () => {
3980
+ }, maxTokens) {
3981
+ if (!isXaiVisionModel(this.visionModel)) {
3982
+ throw new Error(
3983
+ `Model ${this.visionModel} does not support vision capabilities.`
3984
+ );
3985
+ }
3986
+ const res = await this.callXAI(
3987
+ messages,
3988
+ this.visionModel,
3989
+ stream,
3990
+ maxTokens
3991
+ );
3992
+ return this.parseResponse(res, stream, onPartialResponse);
3993
+ }
3994
+ async parseResponse(res, stream, onPartialResponse) {
3995
+ return stream ? this.parseStream(res, onPartialResponse) : this.parseOneShot(await res.json());
3996
+ }
3997
+ async callXAI(messages, model, stream = false, maxTokens) {
3998
+ const body = this.buildRequestBody(messages, model, stream, maxTokens);
3999
+ const res = await ChatServiceHttpClient.post(this.endpoint, body, {
4000
+ Authorization: `Bearer ${this.apiKey}`
4001
+ });
4002
+ return res;
4003
+ }
4004
+ /**
4005
+ * Build request body (OpenAI-compatible Chat Completions)
4006
+ */
4007
+ buildRequestBody(messages, model, stream, maxTokens) {
4008
+ const body = {
4009
+ model,
4010
+ stream,
4011
+ messages
4012
+ };
4013
+ const tokenLimit = maxTokens !== void 0 ? maxTokens : getMaxTokensForResponseLength(this.responseLength);
4014
+ if (tokenLimit !== void 0) {
4015
+ body.max_tokens = tokenLimit;
4016
+ }
4017
+ const tools = this.buildToolsDefinition();
4018
+ if (tools.length > 0) {
4019
+ body.tools = tools;
4020
+ body.tool_choice = "auto";
4021
+ }
4022
+ return body;
4023
+ }
4024
+ buildToolsDefinition() {
4025
+ return buildOpenAICompatibleTools(this.tools, "chat-completions");
4026
+ }
4027
+ async handleStream(res, onPartial) {
4028
+ return parseOpenAICompatibleTextStream(res, onPartial, {
4029
+ onJsonError: (payload) => console.debug("Failed to parse SSE data:", payload)
4030
+ });
4031
+ }
4032
+ /**
4033
+ * Parse streaming response with tool support
4034
+ */
4035
+ async parseStream(res, onPartial) {
4036
+ return parseOpenAICompatibleToolStream(res, onPartial, {
4037
+ onJsonError: (payload) => console.debug("Failed to parse SSE data:", payload)
4038
+ });
4039
+ }
4040
+ /**
4041
+ * Parse non-streaming response
4042
+ */
4043
+ parseOneShot(data) {
4044
+ return parseOpenAICompatibleOneShot(data);
4045
+ }
4046
+ };
4047
+
4048
+ // src/services/providers/xai/XAIChatServiceProvider.ts
4049
+ var XAIChatServiceProvider = class {
4050
+ /**
4051
+ * Create a chat service instance
4052
+ */
4053
+ createChatService(options) {
4054
+ const model = options.model || this.getDefaultModel();
4055
+ const visionModel = resolveVisionModel({
4056
+ model,
4057
+ visionModel: options.visionModel,
4058
+ defaultModel: this.getDefaultModel(),
4059
+ defaultVisionModel: this.getDefaultVisionModel(),
4060
+ supportsVisionForModel: (visionModel2) => this.supportsVisionForModel(visionModel2),
4061
+ validate: "explicit"
4062
+ });
4063
+ const tools = options.tools;
4064
+ return new XAIChatService(
4065
+ options.apiKey,
4066
+ model,
4067
+ visionModel,
4068
+ tools,
4069
+ options.endpoint || ENDPOINT_XAI_CHAT_COMPLETIONS_API,
4070
+ options.responseLength
4071
+ );
4072
+ }
4073
+ /**
4074
+ * Get the provider name
4075
+ */
4076
+ getProviderName() {
4077
+ return "xai";
4078
+ }
4079
+ /**
4080
+ * Get the list of supported models
4081
+ */
4082
+ getSupportedModels() {
4083
+ return [
4084
+ MODEL_GROK_4_20_REASONING,
4085
+ MODEL_GROK_4_20_NON_REASONING,
4086
+ MODEL_GROK_4_1_FAST_REASONING,
4087
+ MODEL_GROK_4_1_FAST_NON_REASONING
4088
+ ];
4089
+ }
4090
+ /**
4091
+ * Get the default model
4092
+ */
4093
+ getDefaultModel() {
4094
+ return MODEL_GROK_4_1_FAST_NON_REASONING;
4095
+ }
4096
+ /**
4097
+ * Get the default vision model
4098
+ */
4099
+ getDefaultVisionModel() {
4100
+ return MODEL_GROK_4_1_FAST_NON_REASONING;
4101
+ }
4102
+ /**
4103
+ * Check if this provider supports vision
4104
+ */
4105
+ supportsVision() {
4106
+ return this.getVisionSupportLevel() !== "unsupported";
4107
+ }
4108
+ getVisionSupportLevel() {
4109
+ return "supported";
4110
+ }
4111
+ /**
4112
+ * Check if a specific model supports vision capabilities
4113
+ */
4114
+ supportsVisionForModel(model) {
4115
+ return isXaiVisionModel(model);
4116
+ }
4117
+ getVisionSupportLevelForModel(model) {
4118
+ return this.supportsVisionForModel(model) ? "supported" : "unsupported";
4119
+ }
4120
+ };
4121
+
3737
4122
  // src/services/providers/zai/ZAIChatService.ts
3738
4123
  var ZAIChatService = class {
3739
4124
  /**
@@ -3977,9 +4362,11 @@ If it's in another language, summarize in that language.
3977
4362
  new OpenAIChatServiceProvider(),
3978
4363
  new OpenAICompatibleChatServiceProvider(),
3979
4364
  new GeminiChatServiceProvider(),
4365
+ new GeminiNanoChatServiceProvider(),
3980
4366
  new ClaudeChatServiceProvider(),
3981
4367
  new OpenRouterChatServiceProvider(),
3982
4368
  new ZAIChatServiceProvider(),
4369
+ new XAIChatServiceProvider(),
3983
4370
  new KimiChatServiceProvider()
3984
4371
  ];
3985
4372