Feat/moonshot api (#4330) * moonshot * Partial mode + JSON schema * Add logo image * Limit max temp to 1 * Add to captioning extension

0e38bfbf0583ff8f09c282e5c9bd82fa2f6c8a64

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
16 files changed, +170 -22Showing whitespace changes
public/img/moonshot.svg+1 -0
@@ -0,0 +1 @@
1<svg xmlns="http://www.w3.org/2000/svg" width="556" height="557.333" viewBox="0 0 417 418" preserveAspectRatio="xMidYMid meet" xmlns:v="https://vecta.io/nano"><path d="M203.162.45L195.5.601c-17.9 1.5-42.2 6.599-56 11.899a214.62 214.62 0 0 1-8.7 3.201c-3.3 1-1.8 1.9 6.5 4 4.5 1.1 16.801 4.399 27.201 7.299L191 34l24.501 6.5 35 9.5 28 7.5 30 7.9L329 71c12.3 3.6 44 12 45.3 12 2.5 0-16.6-20.899-28.6-31.299-36.3-31.6-82.7-49.6-131.2-51.1L203.162.45zM109.5 27.3c-1.1-.2-4.8 1.3-8.7 3.5-6.5 3.9-24.7 16.901-28 20.101-14.6 14.1-22.2 22.199-28 29.899-3.9 5.1-6.899 9.401-6.699 9.501.4.4 8.2 2.5 19.9 5.6l15 3.999c4.1 1.2 15.2 4.201 24.5 6.601l27.5 7.4 30 8 30.501 8.2L215 138l46.5 12.5c2.8.7 10.2 2.7 16.5 4.4l41.001 11c4.1 1.2 11.999 3.301 17.499 4.601L353.5 175c8.5 2.5 25 6.9 45 12 8.3 2.1 15.9 4.2 16.9 4.6 1.6.6 1.7.2 1.1-5.2-.7-6-3.001-17.7-6.101-31.6-1.9-8.4-2.099-8.7-11.399-10.8-2.5-.5-7.6-1.9-11.5-2.9L337 127.5l-29.5-7.9-31.701-8.6c-2.7-.7-4.799-1.5-4.799-1.9 0-2.5 19.4-22.3 26.3-26.9 2-1.3 3.7-2.8 3.7-3.3 0-.4-1.901-1.199-4.201-1.699-3.9-.9-20.199-5.2-36.299-9.7L239 61.8 217 56l-29.5-7.9-32-8.6-46-12.199zM31.1 104c-1.1 0-2.8 1.501-4.1 3.501C20.8 117.5 10.8 142.1 7.6 155c-2.1 8.5-4.6 20.8-4.6 22.4 0 .8 1.899 1.8 4.299 2.5l61.901 16.6 21 5.5C101.001 204.7 120.5 210 141 215.7l13 3.4c1.9.4 8.2 2 14 3.7l26 7.1L217 236l24.5 6.601 44 11.9L302.5 259c6.1 1.5 19.6 5.1 30 8l30 8 17 4.5 14.7 3.901 8.7 2.2 1-2.6c3.7-9.7 5.4-15.3 7.1-23.3l2.5-11.301c.6-2.5-.301-2.899-23.5-8.799L365 233 352 229.4c-3-.9-11.301-3.1-18.501-4.9L314.5 219.5 247 201.4c-16.9-4.3-28.201-7.9-28.701-8.9-.5-1.6 3.2-8.799 12.7-24.199 2.7-4.6 5-8.701 5-9.201s-1.899-1.4-4.299-1.9c-5.7-1.3-30.201-7.7-40.701-10.6L144.5 134l-11-3L117 126.7 69.5 114C51.8 108.9 32.8 104 31.1 104zM1.935 193.44c-.703.309-.986 1.885-1.436 6.16-1.5 14 1.1 38.9 6.4 59.9 4.5 18.1 4.901 18.799 11.801 20.799L62 292 99.5 302c1.7.4 9.1 2.4 16.5 4.4l28.5 7.6 28.5 7.601 22 5.899c4.7 1.4 17.1 4.7 27.5 7.5L275 349.1l24 6.4 29.101 7.701c11.6 3.1 16.9 4.1 17.6 3.4 14.6-14.1 19.599-19.401 24.599-25.601 5.2-6.5 5.7-7.499 4.1-8.099-4.7-1.8-36.599-10.501-52.699-14.401-3.7-.9-8.6-2.3-11-3.1-2.3-.8-7.101-2.2-10.701-3-3.6-.7-9.6-2.3-13.5-3.4-3.8-1.1-13.7-3.8-22-6l-30-8L204.601 287c-8.1-2.1-14.901-4-15.101-4.2-.2-.3 3.901-18.6 7.301-32.6.7-3.2.7-4.399-.1-4.699-.7-.2-7.501-2-15.201-4s-15.8-4.3-18-5-7.1-2.1-11-2.9c-8.5-2-17-4.2-25-6.7-3.3-1-9.6-2.7-14-3.8L54.5 207.4 23 199c-10.2-2.6-19.2-5.1-20.2-5.5-.35-.125-.63-.163-.864-.06zm18.563 102.62c-.316.053-.498.165-.498.34 0 1 4 8.8 7.8 15.3 2.3 3.9 4.2 7.4 4.2 7.8 0 2.1 21.4 28.6 29.6 36.7 12.2 12 12.501 12.3 24.901 21.3 12.5 9 35.5 21.999 43.5 24.599 1.4.4 6.3 2.1 11 3.8 31.5 11.5 69.099 14.601 103.299 8.701C257.199 412.301 282 405.4 282 404c0-.3-7.3-2.399-16.2-4.799l-59.3-15.801-17.101-4.5c-4.9-1.2-5.1-1.7-5.9-19.9-.9-17.8-1.2-19.699-3.8-20.399-1.2-.4-7.999-2.3-15.199-4.2l-28-7.5L109 319.6 81 312l-34-9-21.299-5.9c-2.1-.825-4.256-1.199-5.203-1.04z"/></svg>
\ No newline at end of file1 \ No newline at end of file
public/index.html+36 -8
@@ -652,7 +652,7 @@
652 <input type="number" id="openai_max_tokens" name="openai_max_tokens" class="text_pole" min="1" max="65536">652 <input type="number" id="openai_max_tokens" name="openai_max_tokens" class="text_pole" min="1" max="65536">
653 </div>653 </div>
654 </div>654 </div>
655 <div class="range-block" data-source="openai,custom,xai,aimlapi">655 <div class="range-block" data-source="openai,custom,xai,aimlapi,moonshot">
656 <div class="range-block-title" data-i18n="Multiple swipes per generation">656 <div class="range-block-title" data-i18n="Multiple swipes per generation">
657 Multiple swipes per generation657 Multiple swipes per generation
658 </div>658 </div>
@@ -691,7 +691,7 @@
691 </span>691 </span>
692 </div>692 </div>
693 </div>693 </div>
694 <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,nanogpt,deepseek,xai,pollinations">694 <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,nanogpt,deepseek,xai,pollinations,moonshot">
695 <div class="range-block-title" data-i18n="Temperature">695 <div class="range-block-title" data-i18n="Temperature">
696 Temperature696 Temperature
697 </div>697 </div>
@@ -704,7 +704,7 @@
704 </div>704 </div>
705 </div>705 </div>
706 </div>706 </div>
707 <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek,xai,pollinations">707 <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek,xai,pollinations,moonshot">
708 <div class="range-block-title" data-i18n="Frequency Penalty">708 <div class="range-block-title" data-i18n="Frequency Penalty">
709 Frequency Penalty709 Frequency Penalty
710 </div>710 </div>
@@ -717,7 +717,7 @@
717 </div>717 </div>
718 </div>718 </div>
719 </div>719 </div>
720 <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek,xai,pollinations">720 <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek,xai,pollinations,moonshot">
721 <div class="range-block-title" data-i18n="Presence Penalty">721 <div class="range-block-title" data-i18n="Presence Penalty">
722 Presence Penalty722 Presence Penalty
723 </div>723 </div>
@@ -743,7 +743,7 @@
743 </div>743 </div>
744 </div>744 </div>
745 </div>745 </div>
746 <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,nanogpt,deepseek,xai,pollinations">746 <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,nanogpt,deepseek,xai,pollinations,moonshot">
747 <div class="range-block-title" data-i18n="Top P">747 <div class="range-block-title" data-i18n="Top P">
748 Top P748 Top P
749 </div>749 </div>
@@ -1984,7 +1984,7 @@
1984 </b>1984 </b>
1985 </div>1985 </div>
1986 </div>1986 </div>
1987 <div class="range-block" data-source="openai,cohere,mistralai,custom,claude,aimlapi,openrouter,groq,deepseek,makersuite,vertexai,ai21,xai,pollinations">1987 <div class="range-block" data-source="openai,cohere,mistralai,custom,claude,aimlapi,openrouter,groq,deepseek,makersuite,vertexai,ai21,xai,pollinations,moonshot">
1988 <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand">1988 <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand">
1989 <input id="openai_function_calling" type="checkbox" />1989 <input id="openai_function_calling" type="checkbox" />
1990 <span data-i18n="Enable function calling">Enable function calling</span>1990 <span data-i18n="Enable function calling">Enable function calling</span>
@@ -1995,7 +1995,7 @@
1995 <strong data-i18n="enable_functions_desc_4">Not supported when Prompt Post-Processing with "no tools" is used!</strong>1995 <strong data-i18n="enable_functions_desc_4">Not supported when Prompt Post-Processing with "no tools" is used!</strong>
1996 </div>1996 </div>
1997 </div>1997 </div>
1998 <div class="range-block" data-source="openai,aimlapi,openrouter,mistralai,makersuite,vertexai,claude,custom,xai,pollinations">1998 <div class="range-block" data-source="openai,aimlapi,openrouter,mistralai,makersuite,vertexai,claude,custom,xai,pollinations,moonshot">
1999 <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand">1999 <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand">
2000 <input id="openai_image_inlining" type="checkbox" />2000 <input id="openai_image_inlining" type="checkbox" />
2001 <span data-i18n="Send inline images">Send inline images</span>2001 <span data-i18n="Send inline images">Send inline images</span>
@@ -2065,7 +2065,7 @@
2065 </span>2065 </span>
2066 </div>2066 </div>
2067 </div>2067 </div>
2068 <div class="range-block" data-source="deepseek,aimlapi,openrouter,custom,claude,xai,makersuite,vertexai,pollinations">2068 <div class="range-block" data-source="deepseek,aimlapi,openrouter,custom,claude,xai,makersuite,vertexai,pollinations,moonshot">
2069 <label for="openai_show_thoughts" class="checkbox_label widthFreeExpand">2069 <label for="openai_show_thoughts" class="checkbox_label widthFreeExpand">
2070 <input id="openai_show_thoughts" type="checkbox" />2070 <input id="openai_show_thoughts" type="checkbox" />
2071 <span data-i18n="Request model reasoning">Request model reasoning</span>2071 <span data-i18n="Request model reasoning">Request model reasoning</span>
@@ -2797,6 +2797,7 @@
2797 <option value="makersuite">Google AI Studio</option>2797 <option value="makersuite">Google AI Studio</option>
2798 <option value="vertexai">Google Vertex AI</option>2798 <option value="vertexai">Google Vertex AI</option>
2799 <option value="mistralai">MistralAI</option>2799 <option value="mistralai">MistralAI</option>
2800 <option value="moonshot">Moonshot AI</option>
2800 <option value="nanogpt">NanoGPT</option>2801 <option value="nanogpt">NanoGPT</option>
2801 <option value="openrouter">OpenRouter</option>2802 <option value="openrouter">OpenRouter</option>
2802 <option value="perplexity">Perplexity</option>2803 <option value="perplexity">Perplexity</option>
@@ -3627,6 +3628,33 @@
3627 </span>3628 </span>
3628 </div>3629 </div>
3629 </div>3630 </div>
3631 <div id="moonshot_form" data-source="moonshot">
3632 <h4>
3633 <a data-i18n="Moonshot AI API Key" href="https://platform.moonshot.ai/console/api-keys" target="_blank" rel="noopener noreferrer">
3634 Moonshot AI API Key
3635 </a>
3636 </h4>
3637 <div class="flex-container">
3638 <input id="api_key_moonshot" name="api_key_moonshot" class="text_pole flex1" value="" type="text" autocomplete="off">
3639 <div title="Manage API keys" data-i18n="[title]Manage API keys" class="menu_button fa-solid fa-key fa-fw manage-api-keys" data-key="api_key_moonshot"></div>
3640 </div>
3641 <div data-for="api_key_moonshot" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you click 'Connect'.">
3642 For privacy reasons, your API key will be hidden after you click 'Connect'.
3643 </div>
3644 <h4 data-i18n="Moonshot AI Model">Moonshot AI Model</h4>
3645 <select id="model_moonshot_select">
3646 <option value="kimi-k2-0711-preview">kimi-k2-0711-preview</option>
3647 <option value="moonshot-v1-8k">moonshot-v1-8k</option>
3648 <option value="moonshot-v1-32k">moonshot-v1-32k</option>
3649 <option value="moonshot-v1-128k">moonshot-v1-128k</option>
3650 <option value="moonshot-v1-auto">moonshot-v1-auto</option>
3651 <option value="kimi-latest">kimi-latest</option>
3652 <option value="moonshot-v1-8k-vision-preview">moonshot-v1-8k-vision-preview</option>
3653 <option value="moonshot-v1-32k-vision-preview">moonshot-v1-32k-vision-preview</option>
3654 <option value="moonshot-v1-128k-vision-preview">moonshot-v1-128k-vision-preview</option>
3655 <option value="kimi-thinking-preview">kimi-thinking-preview</option>
3656 </select>
3657 </div>
3630 <div id="prompt_post_processing_form">3658 <div id="prompt_post_processing_form">
3631 <h4>3659 <h4>
3632 <span data-i18n="Prompt Post-Processing">3660 <span data-i18n="Prompt Post-Processing">
public/scripts/RossAscends-mods.js+1 -0
@@ -410,6 +410,7 @@ function RA_autoconnect(PrevApi) {
410 || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK)410 || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK)
411 || (secret_state[SECRET_KEYS.XAI] && oai_settings.chat_completion_source == chat_completion_sources.XAI)411 || (secret_state[SECRET_KEYS.XAI] && oai_settings.chat_completion_source == chat_completion_sources.XAI)
412 || (secret_state[SECRET_KEYS.AIMLAPI] && oai_settings.chat_completion_source == chat_completion_sources.AIMLAPI)412 || (secret_state[SECRET_KEYS.AIMLAPI] && oai_settings.chat_completion_source == chat_completion_sources.AIMLAPI)
413 || (secret_state[SECRET_KEYS.MOONSHOT] && oai_settings.chat_completion_source == chat_completion_sources.MOONSHOT)
413 || (oai_settings.chat_completion_source === chat_completion_sources.POLLINATIONS)414 || (oai_settings.chat_completion_source === chat_completion_sources.POLLINATIONS)
414 || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM)415 || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM)
415 ) {416 ) {
public/scripts/extensions/caption/index.js+1 -0
@@ -438,6 +438,7 @@ jQuery(async function () {
438 'groq': SECRET_KEYS.GROQ,438 'groq': SECRET_KEYS.GROQ,
439 'cohere': SECRET_KEYS.COHERE,439 'cohere': SECRET_KEYS.COHERE,
440 'aimlapi': SECRET_KEYS.AIMLAPI,440 'aimlapi': SECRET_KEYS.AIMLAPI,
441 'moonshot': SECRET_KEYS.MOONSHOT,
441 };442 };
442443
443 if (chatCompletionApis[api] && secret_state[chatCompletionApis[api]]) {444 if (chatCompletionApis[api] && secret_state[chatCompletionApis[api]]) {
public/scripts/extensions/caption/settings.html+4 -0
@@ -27,6 +27,7 @@
27 <option value="koboldcpp">KoboldCpp</option>27 <option value="koboldcpp">KoboldCpp</option>
28 <option value="llamacpp">llama.cpp</option>28 <option value="llamacpp">llama.cpp</option>
29 <option value="mistral">MistralAI</option>29 <option value="mistral">MistralAI</option>
30 <option value="moonshot">Moonshot AI</option>
30 <option value="ollama">Ollama</option>31 <option value="ollama">Ollama</option>
31 <option value="openai">OpenAI</option>32 <option value="openai">OpenAI</option>
32 <option value="openrouter">OpenRouter</option>33 <option value="openrouter">OpenRouter</option>
@@ -51,6 +52,9 @@
51 <option data-type="mistral" value="mistral-small-latest">mistral-small-latest</option>52 <option data-type="mistral" value="mistral-small-latest">mistral-small-latest</option>
52 <option data-type="mistral" value="mistral-medium-latest">mistral-medium-latest</option>53 <option data-type="mistral" value="mistral-medium-latest">mistral-medium-latest</option>
53 <option data-type="mistral" value="mistral-medium-2505">mistral-medium-2505</option>54 <option data-type="mistral" value="mistral-medium-2505">mistral-medium-2505</option>
55 <option data-type="moonshot" value="moonshot-v1-8k-vision-preview">moonshot-v1-8k-vision-preview</option>
56 <option data-type="moonshot" value="moonshot-v1-32k-vision-preview">moonshot-v1-32k-vision-preview</option>
57 <option data-type="moonshot" value="moonshot-v1-128k-vision-preview">moonshot-v1-128k-vision-preview</option>
54 <option data-type="openai" value="gpt-4.1">gpt-4.1</option>58 <option data-type="openai" value="gpt-4.1">gpt-4.1</option>
55 <option data-type="openai" value="gpt-4.1-2025-04-14">gpt-4.1-2025-04-14</option>59 <option data-type="openai" value="gpt-4.1-2025-04-14">gpt-4.1-2025-04-14</option>
56 <option data-type="openai" value="gpt-4.1-mini">gpt-4.1-mini</option>60 <option data-type="openai" value="gpt-4.1-mini">gpt-4.1-mini</option>
public/scripts/extensions/shared.js+4 -0
@@ -238,6 +238,10 @@ function throwIfInvalidModel(useReverseProxy) {
238 if (multimodalApi === 'aimlapi' && !secret_state[SECRET_KEYS.AIMLAPI]) {238 if (multimodalApi === 'aimlapi' && !secret_state[SECRET_KEYS.AIMLAPI]) {
239 throw new Error('AI/ML API key is not set.');239 throw new Error('AI/ML API key is not set.');
240 }240 }
241
242 if (multimodalApi === 'moonshot' && !secret_state[SECRET_KEYS.MOONSHOT]) {
243 throw new Error('Moonshot AI API key is not set.');
244 }
241}245}
242246
243/**247/**
public/scripts/openai.js+72 -2
@@ -183,6 +183,7 @@ export const chat_completion_sources = {
183 AIMLAPI: 'aimlapi',183 AIMLAPI: 'aimlapi',
184 XAI: 'xai',184 XAI: 'xai',
185 POLLINATIONS: 'pollinations',185 POLLINATIONS: 'pollinations',
186 MOONSHOT: 'moonshot',
186};187};
187188
188const character_names_behavior = {189const character_names_behavior = {
@@ -272,6 +273,7 @@ export const settingsToUpdate = {
272 aimlapi_model: ['#model_aimlapi_select', 'aimlapi_model', false, true],273 aimlapi_model: ['#model_aimlapi_select', 'aimlapi_model', false, true],
273 xai_model: ['#model_xai_select', 'xai_model', false, true],274 xai_model: ['#model_xai_select', 'xai_model', false, true],
274 pollinations_model: ['#model_pollinations_select', 'pollinations_model', false, true],275 pollinations_model: ['#model_pollinations_select', 'pollinations_model', false, true],
276 moonshot_model: ['#model_moonshot_select', 'moonshot_model', false, true],
275 custom_model: ['#custom_model_id', 'custom_model', false, true],277 custom_model: ['#custom_model_id', 'custom_model', false, true],
276 custom_url: ['#custom_api_url_text', 'custom_url', false, true],278 custom_url: ['#custom_api_url_text', 'custom_url', false, true],
277 custom_include_body: ['#custom_include_body', 'custom_include_body', false, true],279 custom_include_body: ['#custom_include_body', 'custom_include_body', false, true],
@@ -367,6 +369,7 @@ const default_settings = {
367 aimlapi_model: 'gpt-4o-mini-2024-07-18',369 aimlapi_model: 'gpt-4o-mini-2024-07-18',
368 xai_model: 'grok-3-beta',370 xai_model: 'grok-3-beta',
369 pollinations_model: 'openai',371 pollinations_model: 'openai',
372 moonshot_model: 'kimi-latest',
370 custom_model: '',373 custom_model: '',
371 custom_url: '',374 custom_url: '',
372 custom_include_body: '',375 custom_include_body: '',
@@ -453,6 +456,7 @@ const oai_settings = {
453 aimlapi_model: 'gpt-4-turbo',456 aimlapi_model: 'gpt-4-turbo',
454 xai_model: 'grok-3-beta',457 xai_model: 'grok-3-beta',
455 pollinations_model: 'openai',458 pollinations_model: 'openai',
459 moonshot_model: 'kimi-latest',
456 custom_model: '',460 custom_model: '',
457 custom_url: '',461 custom_url: '',
458 custom_include_body: '',462 custom_include_body: '',
@@ -1613,6 +1617,8 @@ export function getChatCompletionModel(source = null) {
1613 return oai_settings.xai_model;1617 return oai_settings.xai_model;
1614 case chat_completion_sources.POLLINATIONS:1618 case chat_completion_sources.POLLINATIONS:
1615 return oai_settings.pollinations_model;1619 return oai_settings.pollinations_model;
1620 case chat_completion_sources.MOONSHOT:
1621 return oai_settings.moonshot_model;
1616 default:1622 default:
1617 console.error(`Unknown chat completion source: ${activeSource}`);1623 console.error(`Unknown chat completion source: ${activeSource}`);
1618 return '';1624 return '';
@@ -2038,13 +2044,14 @@ async function sendOpenAIRequest(type, messages, signal, { jsonSchema = null } =
2038 const isAimlapi = oai_settings.chat_completion_source == chat_completion_sources.AIMLAPI;2044 const isAimlapi = oai_settings.chat_completion_source == chat_completion_sources.AIMLAPI;
2039 const isXAI = oai_settings.chat_completion_source == chat_completion_sources.XAI;2045 const isXAI = oai_settings.chat_completion_source == chat_completion_sources.XAI;
2040 const isPollinations = oai_settings.chat_completion_source == chat_completion_sources.POLLINATIONS;2046 const isPollinations = oai_settings.chat_completion_source == chat_completion_sources.POLLINATIONS;
2047 const isMoonshot = oai_settings.chat_completion_source == chat_completion_sources.MOONSHOT;
2041 const isTextCompletion = isOAI && textCompletionModels.includes(oai_settings.openai_model);2048 const isTextCompletion = isOAI && textCompletionModels.includes(oai_settings.openai_model);
2042 const isQuiet = type === 'quiet';2049 const isQuiet = type === 'quiet';
2043 const isImpersonate = type === 'impersonate';2050 const isImpersonate = type === 'impersonate';
2044 const isContinue = type === 'continue';2051 const isContinue = type === 'continue';
2045 const stream = oai_settings.stream_openai && !isQuiet && !(isOAI && ['o1-2024-12-17', 'o1'].includes(oai_settings.openai_model));2052 const stream = oai_settings.stream_openai && !isQuiet && !(isOAI && ['o1-2024-12-17', 'o1'].includes(oai_settings.openai_model));
2046 const useLogprobs = !!power_user.request_token_probabilities;2053 const useLogprobs = !!power_user.request_token_probabilities;
2047 const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom || isXAI || isAimlapi);2054 const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom || isXAI || isAimlapi || isMoonshot);
20482055
2049 const logitBiasSources = [chat_completion_sources.OPENAI, chat_completion_sources.OPENROUTER, chat_completion_sources.CUSTOM];2056 const logitBiasSources = [chat_completion_sources.OPENAI, chat_completion_sources.OPENROUTER, chat_completion_sources.CUSTOM];
2050 if (oai_settings.bias_preset_selected2057 if (oai_settings.bias_preset_selected
@@ -2384,7 +2391,7 @@ export function getStreamingReply(data, state, { chatCompletionSource = null, ov
2384 state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || '');2391 state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || '');
2385 }2392 }
2386 return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? '';2393 return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? '';
2387 } else if ([chat_completion_sources.CUSTOM, chat_completion_sources.POLLINATIONS, chat_completion_sources.AIMLAPI].includes(chat_completion_source)) {2394 } else if ([chat_completion_sources.CUSTOM, chat_completion_sources.POLLINATIONS, chat_completion_sources.AIMLAPI, chat_completion_sources.MOONSHOT].includes(chat_completion_source)) {
2388 if (show_thoughts) {2395 if (show_thoughts) {
2389 state.reasoning +=2396 state.reasoning +=
2390 data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content ??2397 data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content ??
@@ -3345,6 +3352,7 @@ function loadOpenAISettings(data, settings) {
3345 oai_settings.aimlapi_model = settings.aimlapi_model ?? default_settings.aimlapi_model;3352 oai_settings.aimlapi_model = settings.aimlapi_model ?? default_settings.aimlapi_model;
3346 oai_settings.xai_model = settings.xai_model ?? default_settings.xai_model;3353 oai_settings.xai_model = settings.xai_model ?? default_settings.xai_model;
3347 oai_settings.pollinations_model = settings.pollinations_model ?? default_settings.pollinations_model;3354 oai_settings.pollinations_model = settings.pollinations_model ?? default_settings.pollinations_model;
3355 oai_settings.moonshot_model = settings.moonshot_model ?? default_settings.moonshot_model;
3348 oai_settings.custom_model = settings.custom_model ?? default_settings.custom_model;3356 oai_settings.custom_model = settings.custom_model ?? default_settings.custom_model;
3349 oai_settings.custom_url = settings.custom_url ?? default_settings.custom_url;3357 oai_settings.custom_url = settings.custom_url ?? default_settings.custom_url;
3350 oai_settings.custom_include_body = settings.custom_include_body ?? default_settings.custom_include_body;3358 oai_settings.custom_include_body = settings.custom_include_body ?? default_settings.custom_include_body;
@@ -3442,6 +3450,8 @@ function loadOpenAISettings(data, settings) {
3442 $(`#model_xai_select option[value="${oai_settings.xai_model}"`).prop('selected', true);3450 $(`#model_xai_select option[value="${oai_settings.xai_model}"`).prop('selected', true);
3443 $('#model_pollinations_select').val(oai_settings.pollinations_model);3451 $('#model_pollinations_select').val(oai_settings.pollinations_model);
3444 $(`#model_pollinations_select option[value="${oai_settings.pollinations_model}"`).prop('selected', true);3452 $(`#model_pollinations_select option[value="${oai_settings.pollinations_model}"`).prop('selected', true);
3453 $('#model_moonshot_select').val(oai_settings.moonshot_model);
3454 $(`#model_moonshot_select option[value="${oai_settings.moonshot_model}"`).prop('selected', true);
3445 $('#custom_model_id').val(oai_settings.custom_model);3455 $('#custom_model_id').val(oai_settings.custom_model);
3446 $('#custom_api_url_text').val(oai_settings.custom_url);3456 $('#custom_api_url_text').val(oai_settings.custom_url);
3447 $('#openai_max_context').val(oai_settings.openai_max_context);3457 $('#openai_max_context').val(oai_settings.openai_max_context);
@@ -3714,6 +3724,7 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
3714 xai_model: settings.xai_model,3724 xai_model: settings.xai_model,
3715 pollinations_model: settings.pollinations_model,3725 pollinations_model: settings.pollinations_model,
3716 aimlapi_model: settings.aimlapi_model,3726 aimlapi_model: settings.aimlapi_model,
3727 moonshot_model: settings.moonshot_model,
3717 custom_model: settings.custom_model,3728 custom_model: settings.custom_model,
3718 custom_url: settings.custom_url,3729 custom_url: settings.custom_url,
3719 custom_include_body: settings.custom_include_body,3730 custom_include_body: settings.custom_include_body,
@@ -4424,6 +4435,28 @@ function getGroqMaxContext(model, isUnlocked) {
4424 return Object.entries(contextMap).find(([key]) => model.includes(key))?.[1] || max_128k;4435 return Object.entries(contextMap).find(([key]) => model.includes(key))?.[1] || max_128k;
4425}4436}
44264437
4438function getMoonshotMaxContext(model, isUnlocked) {
4439 if (isUnlocked) {
4440 return unlocked_max;
4441 }
4442
4443 const contextMap = {
4444 'moonshot-v1-8k': max_8k,
4445 'moonshot-v1-32k': max_32k,
4446 'moonshot-v1-128k': max_128k,
4447 'moonshot-v1-auto': max_128k,
4448 'moonshot-v1-8k-vision-preview': max_8k,
4449 'moonshot-v1-32k-vision-preview': max_32k,
4450 'moonshot-v1-128k-vision-preview': max_128k,
4451 'kimi-k2-0711-preview': max_32k,
4452 'kimi-latest': max_32k,
4453 'kimi-thinking-preview': max_32k,
4454 };
4455
4456 // Return context size if model found, otherwise default to 32k
4457 return Object.entries(contextMap).find(([key]) => model.includes(key))?.[1] || max_32k;
4458}
4459
4427async function onModelChange() {4460async function onModelChange() {
4428 biasCache = undefined;4461 biasCache = undefined;
4429 let value = String($(this).val() || '');4462 let value = String($(this).val() || '');
@@ -4559,6 +4592,11 @@ async function onModelChange() {
4559 oai_settings.xai_model = value;4592 oai_settings.xai_model = value;
4560 }4593 }
45614594
4595 if (value && $(this).is('#model_moonshot_select')) {
4596 console.log('Moonshot model changed to', value);
4597 oai_settings.moonshot_model = value;
4598 }
4599
4562 if ([chat_completion_sources.MAKERSUITE, chat_completion_sources.VERTEXAI].includes(oai_settings.chat_completion_source)) {4600 if ([chat_completion_sources.MAKERSUITE, chat_completion_sources.VERTEXAI].includes(oai_settings.chat_completion_source)) {
4563 if (oai_settings.max_context_unlocked) {4601 if (oai_settings.max_context_unlocked) {
4564 $('#openai_max_context').attr('max', max_2mil);4602 $('#openai_max_context').attr('max', max_2mil);
@@ -4822,6 +4860,15 @@ async function onModelChange() {
4822 $('#freq_pen_openai').attr('max', 2).attr('min', -2).val(oai_settings.freq_pen_openai).trigger('input');4860 $('#freq_pen_openai').attr('max', 2).attr('min', -2).val(oai_settings.freq_pen_openai).trigger('input');
4823 }4861 }
48244862
4863 if (oai_settings.chat_completion_source === chat_completion_sources.MOONSHOT) {
4864 const maxContext = getMoonshotMaxContext(oai_settings.moonshot_model, oai_settings.max_context_unlocked);
4865 $('#openai_max_context').attr('max', maxContext);
4866 oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context);
4867 $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');
4868 oai_settings.temp_openai = Math.min(claude_max_temp, oai_settings.temp_openai);
4869 $('#temp_openai').attr('max', claude_max_temp).val(oai_settings.temp_openai).trigger('input');
4870 }
4871
4825 $('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max')));4872 $('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max')));
48264873
4827 saveSettingsDebounced();4874 saveSettingsDebounced();
@@ -5053,6 +5100,19 @@ async function onConnectButtonClick(e) {
5053 }5100 }
5054 }5101 }
50555102
5103 if (oai_settings.chat_completion_source == chat_completion_sources.MOONSHOT) {
5104 const api_key_moonshot = String($('#api_key_moonshot').val()).trim();
5105
5106 if (api_key_moonshot.length) {
5107 await writeSecret(SECRET_KEYS.MOONSHOT, api_key_moonshot);
5108 }
5109
5110 if (!secret_state[SECRET_KEYS.MOONSHOT]) {
5111 console.log('No secret key saved for Moonshot');
5112 return;
5113 }
5114 }
5115
5056 startStatusLoading();5116 startStatusLoading();
5057 saveSettingsDebounced();5117 saveSettingsDebounced();
5058 await getStatusOpen();5118 await getStatusOpen();
@@ -5114,6 +5174,9 @@ function toggleChatCompletionForms() {
5114 else if (oai_settings.chat_completion_source == chat_completion_sources.POLLINATIONS) {5174 else if (oai_settings.chat_completion_source == chat_completion_sources.POLLINATIONS) {
5115 $('#model_pollinations_select').trigger('change');5175 $('#model_pollinations_select').trigger('change');
5116 }5176 }
5177 else if (oai_settings.chat_completion_source == chat_completion_sources.MOONSHOT) {
5178 $('#model_moonshot_select').trigger('change');
5179 }
5117 $('[data-source]').each(function () {5180 $('[data-source]').each(function () {
5118 const validSources = $(this).data('source').split(',');5181 const validSources = $(this).data('source').split(',');
5119 $(this).toggle(validSources.includes(oai_settings.chat_completion_source));5182 $(this).toggle(validSources.includes(oai_settings.chat_completion_source));
@@ -5221,6 +5284,10 @@ export function isImageInliningSupported() {
5221 'grok-4',5284 'grok-4',
5222 'grok-2-vision',5285 'grok-2-vision',
5223 'grok-vision',5286 'grok-vision',
5287 // Moonshot
5288 'moonshot-v1-8k-vision-preview',
5289 'moonshot-v1-32k-vision-preview',
5290 'moonshot-v1-128k-vision-preview',
5224 ];5291 ];
52255292
5226 switch (oai_settings.chat_completion_source) {5293 switch (oai_settings.chat_completion_source) {
@@ -5249,6 +5316,8 @@ export function isImageInliningSupported() {
5249 return visionSupportedModels.some(model => oai_settings.aimlapi_model.includes(model));5316 return visionSupportedModels.some(model => oai_settings.aimlapi_model.includes(model));
5250 case chat_completion_sources.POLLINATIONS:5317 case chat_completion_sources.POLLINATIONS:
5251 return (Array.isArray(model_list) && model_list.find(m => m.id === oai_settings.pollinations_model)?.vision);5318 return (Array.isArray(model_list) && model_list.find(m => m.id === oai_settings.pollinations_model)?.vision);
5319 case chat_completion_sources.MOONSHOT:
5320 return visionSupportedModels.some(model => oai_settings.moonshot_model.includes(model));
5252 default:5321 default:
5253 return false;5322 return false;
5254 }5323 }
@@ -6037,6 +6106,7 @@ export function initOpenAI() {
6037 $('#model_custom_select').on('change', onModelChange);6106 $('#model_custom_select').on('change', onModelChange);
6038 $('#model_xai_select').on('change', onModelChange);6107 $('#model_xai_select').on('change', onModelChange);
6039 $('#model_pollinations_select').on('change', onModelChange);6108 $('#model_pollinations_select').on('change', onModelChange);
6109 $('#model_moonshot_select').on('change', onModelChange);
6040 $('#settings_preset_openai').on('change', onSettingsPresetChange);6110 $('#settings_preset_openai').on('change', onSettingsPresetChange);
6041 $('#new_oai_preset').on('click', onNewPresetClick);6111 $('#new_oai_preset').on('click', onNewPresetClick);
6042 $('#delete_oai_preset').on('click', onDeletePresetClick);6112 $('#delete_oai_preset').on('click', onDeletePresetClick);
public/scripts/reasoning.js+1 -0
@@ -120,6 +120,7 @@ export function extractReasoningFromData(data, {
120 return data?.content?.find(part => part.type === 'thinking')?.thinking ?? '';120 return data?.content?.find(part => part.type === 'thinking')?.thinking ?? '';
121 case chat_completion_sources.AIMLAPI:121 case chat_completion_sources.AIMLAPI:
122 case chat_completion_sources.POLLINATIONS:122 case chat_completion_sources.POLLINATIONS:
123 case chat_completion_sources.MOONSHOT:
123 case chat_completion_sources.CUSTOM: {124 case chat_completion_sources.CUSTOM: {
124 return data?.choices?.[0]?.message?.reasoning_content125 return data?.choices?.[0]?.message?.reasoning_content
125 ?? data?.choices?.[0]?.message?.reasoning126 ?? data?.choices?.[0]?.message?.reasoning
public/scripts/secrets.js+3 -0
@@ -63,6 +63,7 @@ export const SECRET_KEYS = {
63 VERTEXAI_SERVICE_ACCOUNT: 'vertexai_service_account_json',63 VERTEXAI_SERVICE_ACCOUNT: 'vertexai_service_account_json',
64 MINIMAX: 'api_key_minimax',64 MINIMAX: 'api_key_minimax',
65 MINIMAX_GROUP_ID: 'minimax_group_id',65 MINIMAX_GROUP_ID: 'minimax_group_id',
66 MOONSHOT: 'api_key_moonshot',
66};67};
6768
68const FRIENDLY_NAMES = {69const FRIENDLY_NAMES = {
@@ -114,6 +115,7 @@ const FRIENDLY_NAMES = {
114 [SECRET_KEYS.DEEPLX_URL]: 'DeepLX Endpoint (e.g. http://127.0.0.1:1188/translate)',115 [SECRET_KEYS.DEEPLX_URL]: 'DeepLX Endpoint (e.g. http://127.0.0.1:1188/translate)',
115 [SECRET_KEYS.MINIMAX]: 'MiniMax TTS',116 [SECRET_KEYS.MINIMAX]: 'MiniMax TTS',
116 [SECRET_KEYS.MINIMAX_GROUP_ID]: 'MiniMax Group ID',117 [SECRET_KEYS.MINIMAX_GROUP_ID]: 'MiniMax Group ID',
118 [SECRET_KEYS.MOONSHOT]: 'Moonshot AI',
117};119};
118120
119const INPUT_MAP = {121const INPUT_MAP = {
@@ -148,6 +150,7 @@ const INPUT_MAP = {
148 [SECRET_KEYS.AIMLAPI]: '#api_key_aimlapi',150 [SECRET_KEYS.AIMLAPI]: '#api_key_aimlapi',
149 [SECRET_KEYS.XAI]: '#api_key_xai',151 [SECRET_KEYS.XAI]: '#api_key_xai',
150 [SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT]: '#vertexai_service_account_json',152 [SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT]: '#vertexai_service_account_json',
153 [SECRET_KEYS.MOONSHOT]: '#api_key_moonshot',
151};154};
152155
153const getLabel = () => moment().format('L LT');156const getLabel = () => moment().format('L LT');
public/scripts/slash-commands.js+1 -0
@@ -4805,6 +4805,7 @@ function getModelOptions(quiet) {
4805 { id: 'model_aimlapi_select', api: 'openai', type: chat_completion_sources.AIMLAPI },4805 { id: 'model_aimlapi_select', api: 'openai', type: chat_completion_sources.AIMLAPI },
4806 { id: 'model_xai_select', api: 'openai', type: chat_completion_sources.XAI },4806 { id: 'model_xai_select', api: 'openai', type: chat_completion_sources.XAI },
4807 { id: 'model_pollinations_select', api: 'openai', type: chat_completion_sources.POLLINATIONS },4807 { id: 'model_pollinations_select', api: 'openai', type: chat_completion_sources.POLLINATIONS },
4808 { id: 'model_moonshot_select', api: 'openai', type: chat_completion_sources.MOONSHOT },
4808 { id: 'model_novel_select', api: 'novel', type: null },4809 { id: 'model_novel_select', api: 'novel', type: null },
4809 { id: 'horde_model', api: 'koboldhorde', type: null },4810 { id: 'horde_model', api: 'koboldhorde', type: null },
4810 ];4811 ];
public/scripts/tool-calling.js+1 -0
@@ -620,6 +620,7 @@ export class ToolManager {
620 chat_completion_sources.AI21,620 chat_completion_sources.AI21,
621 chat_completion_sources.XAI,621 chat_completion_sources.XAI,
622 chat_completion_sources.POLLINATIONS,622 chat_completion_sources.POLLINATIONS,
623 chat_completion_sources.MOONSHOT,
623 ];624 ];
624 return supportedSources.includes(oai_settings.chat_completion_source);625 return supportedSources.includes(oai_settings.chat_completion_source);
625 }626 }
src/constants.js+1 -0
@@ -178,6 +178,7 @@ export const CHAT_COMPLETION_SOURCES = {
178 AIMLAPI: 'aimlapi',178 AIMLAPI: 'aimlapi',
179 XAI: 'xai',179 XAI: 'xai',
180 POLLINATIONS: 'pollinations',180 POLLINATIONS: 'pollinations',
181 MOONSHOT: 'moonshot',
181};182};
182183
183/**184/**
src/endpoints/backends/chat-completions.js+32 -10
@@ -65,6 +65,7 @@ const API_DEEPSEEK = 'https://api.deepseek.com/beta';
65const API_XAI = 'https://api.x.ai/v1';65const API_XAI = 'https://api.x.ai/v1';
66const API_AIMLAPI = 'https://api.aimlapi.com/v1';66const API_AIMLAPI = 'https://api.aimlapi.com/v1';
67const API_POLLINATIONS = 'https://text.pollinations.ai/openai';67const API_POLLINATIONS = 'https://text.pollinations.ai/openai';
68const API_MOONSHOT = 'https://api.moonshot.ai/v1';
6869
69/**70/**
70 * Gets OpenRouter transforms based on the request.71 * Gets OpenRouter transforms based on the request.
@@ -98,6 +99,23 @@ function getOpenRouterPlugins(request) {
98}99}
99100
100/**101/**
102 * Hacky way to use JSON schema only if json_object format is supported.
103 * @param {object} bodyParams Additional body parameters
104 * @param {object[]} messages Array of messages
105 * @param {object} jsonSchema JSON schema object
106 */
107function setJsonObjectFormat(bodyParams, messages, jsonSchema) {
108 bodyParams['response_format'] = {
109 type: 'json_object',
110 };
111 const message = {
112 role: 'user',
113 content: `JSON schema for the response:\n${JSON.stringify(jsonSchema.value, null, 4)}`,
114 };
115 messages.push(message);
116}
117
118/**
101 * Sends a request to Claude API.119 * Sends a request to Claude API.
102 * @param {express.Request} request Express request120 * @param {express.Request} request Express request
103 * @param {express.Response} response Express response121 * @param {express.Response} response Express response
@@ -890,7 +908,7 @@ async function sendDeepSeekRequest(request, response) {
890 const postProcessType = String(request.body.model).endsWith('-reasoner')908 const postProcessType = String(request.body.model).endsWith('-reasoner')
891 ? PROMPT_PROCESSING_TYPE.STRICT_TOOLS909 ? PROMPT_PROCESSING_TYPE.STRICT_TOOLS
892 : PROMPT_PROCESSING_TYPE.SEMI_TOOLS;910 : PROMPT_PROCESSING_TYPE.SEMI_TOOLS;
893 const processedMessages = addAssistantPrefix(postProcessPrompt(request.body.messages, postProcessType, getPromptNames(request)), bodyParams.tools);911 const processedMessages = addAssistantPrefix(postProcessPrompt(request.body.messages, postProcessType, getPromptNames(request)), bodyParams.tools, 'prefix');
894912
895 const requestBody = {913 const requestBody = {
896 'messages': processedMessages,914 'messages': processedMessages,
@@ -1220,6 +1238,10 @@ router.post('/status', async function (request, statusResponse) {
1220 apiUrl = API_GROQ;1238 apiUrl = API_GROQ;
1221 apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ);1239 apiKey = readSecret(request.user.directories, SECRET_KEYS.GROQ);
1222 headers = {};1240 headers = {};
1241 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MOONSHOT) {
1242 apiUrl = API_MOONSHOT;
1243 apiKey = readSecret(request.user.directories, SECRET_KEYS.MOONSHOT);
1244 headers = {};
1223 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) {1245 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MAKERSUITE) {
1224 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);1246 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE);
1225 apiUrl = trimTrailingSlash(request.body.reverse_proxy || API_MAKERSUITE);1247 apiUrl = trimTrailingSlash(request.body.reverse_proxy || API_MAKERSUITE);
@@ -1598,17 +1620,17 @@ router.post('/generate', function (request, response) {
1598 referrer: 'sillytavern',1620 referrer: 'sillytavern',
1599 seed: request.body.seed ?? Math.floor(Math.random() * 99999999),1621 seed: request.body.seed ?? Math.floor(Math.random() * 99999999),
1600 };1622 };
1601 // Hack to support JSON schema
1602 if (request.body.json_schema) {1623 if (request.body.json_schema) {
1603 bodyParams['response_format'] = {1624 setJsonObjectFormat(bodyParams, request.body.messages, request.body.json_schema);
1604 type: 'json_object',
1605 };
1606 const message = {
1607 role: 'user',
1608 content: `JSON schema for the response:\n${JSON.stringify(request.body.json_schema.value, null, 4)}`,
1609 };
1610 request.body.messages.push(message);
1611 }1625 }
1626 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MOONSHOT) {
1627 apiUrl = API_MOONSHOT;
1628 apiKey = readSecret(request.user.directories, SECRET_KEYS.MOONSHOT);
1629 headers = {};
1630 bodyParams = {};
1631 request.body.json_schema
1632 ? setJsonObjectFormat(bodyParams, request.body.messages, request.body.json_schema)
1633 : addAssistantPrefix(request.body.messages, [], 'partial');
1612 } else {1634 } else {
1613 console.warn('This chat completion source is not supported yet.');1635 console.warn('This chat completion source is not supported yet.');
1614 return response.status(400).send({ error: true });1636 return response.status(400).send({ error: true });
src/endpoints/openai.js+8 -0
@@ -73,6 +73,10 @@ router.post('/caption-image', async (request, response) => {
73 key = readSecret(request.user.directories, SECRET_KEYS.COHERE);73 key = readSecret(request.user.directories, SECRET_KEYS.COHERE);
74 }74 }
7575
76 if (request.body.api === 'moonshot') {
77 key = readSecret(request.user.directories, SECRET_KEYS.MOONSHOT);
78 }
79
76 const noKeyTypes = ['custom', 'ooba', 'koboldcpp', 'vllm', 'llamacpp', 'pollinations'];80 const noKeyTypes = ['custom', 'ooba', 'koboldcpp', 'vllm', 'llamacpp', 'pollinations'];
77 if (!key && !request.body.reverse_proxy && !noKeyTypes.includes(request.body.api)) {81 if (!key && !request.body.reverse_proxy && !noKeyTypes.includes(request.body.api)) {
78 console.warn('No key found for API', request.body.api);82 console.warn('No key found for API', request.body.api);
@@ -153,6 +157,10 @@ router.post('/caption-image', async (request, response) => {
153 apiUrl = 'https://text.pollinations.ai/openai/chat/completions';157 apiUrl = 'https://text.pollinations.ai/openai/chat/completions';
154 }158 }
155159
160 if (request.body.api === 'moonshot') {
161 apiUrl = 'https://api.moonshot.ai/v1/chat/completions';
162 }
163
156 if (['koboldcpp', 'vllm', 'llamacpp', 'ooba'].includes(request.body.api)) {164 if (['koboldcpp', 'vllm', 'llamacpp', 'ooba'].includes(request.body.api)) {
157 apiUrl = `${trimV1(request.body.server_url)}/v1/chat/completions`;165 apiUrl = `${trimV1(request.body.server_url)}/v1/chat/completions`;
158 }166 }
src/endpoints/secrets.js+1 -0
@@ -56,6 +56,7 @@ export const SECRET_KEYS = {
56 VERTEXAI_SERVICE_ACCOUNT: 'vertexai_service_account_json',56 VERTEXAI_SERVICE_ACCOUNT: 'vertexai_service_account_json',
57 MINIMAX: 'api_key_minimax',57 MINIMAX: 'api_key_minimax',
58 MINIMAX_GROUP_ID: 'minimax_group_id',58 MINIMAX_GROUP_ID: 'minimax_group_id',
59 MOONSHOT: 'api_key_moonshot',
59};60};
6061
61/**62/**
src/prompt-converters.js+3 -2
@@ -53,15 +53,16 @@ export function getPromptNames(request) {
53 * Adds an assistant prefix to the last message.53 * Adds an assistant prefix to the last message.
54 * @param {any[]} prompt Prompt messages array54 * @param {any[]} prompt Prompt messages array
55 * @param {any[]} tools Array of tool definitions55 * @param {any[]} tools Array of tool definitions
56 * @param {string} property The property to set the prefix on
56 * @returns {any[]} Transformed messages array57 * @returns {any[]} Transformed messages array
57 */58 */
58export function addAssistantPrefix(prompt, tools) {59export function addAssistantPrefix(prompt, tools, property) {
59 if (!prompt.length) {60 if (!prompt.length) {
60 return prompt;61 return prompt;
61 }62 }
62 const hasAnyTools = (Array.isArray(tools) && tools.length > 0) || prompt.some(x => x.role === 'tool');63 const hasAnyTools = (Array.isArray(tools) && tools.length > 0) || prompt.some(x => x.role === 'tool');
63 if (!hasAnyTools && prompt[prompt.length - 1].role === 'assistant') {64 if (!hasAnyTools && prompt[prompt.length - 1].role === 'assistant') {
64 prompt[prompt.length - 1].prefix = true;65 prompt[prompt.length - 1][property] = true;
65 }66 }
66 return prompt;67 return prompt;
67}68}