678 lines
25 KiB
JavaScript
678 lines
25 KiB
JavaScript
// Safe API Provider Selector Node - Model list updates without auto-fetch
|
|
import { app } from "../../../scripts/app.js";
|
|
|
|
// Hardcoded model lists for immediate updates (no fetch on load)
|
|
const PROVIDER_MODELS = {
|
|
"openai": [
|
|
"gpt-4o-mini",
|
|
"babbage-002",
|
|
"chatgpt-4o-latest",
|
|
"chatgpt-5-latest",
|
|
"codex-mini-latest",
|
|
"computer-use-preview",
|
|
"computer-use-preview-2025-03-11",
|
|
"dall-e-2",
|
|
"dall-e-3",
|
|
"davinci-002",
|
|
"gpt-3.5-turbo",
|
|
"gpt-3.5-turbo-0125",
|
|
"gpt-3.5-turbo-1106",
|
|
"gpt-3.5-turbo-16k",
|
|
"gpt-3.5-turbo-instruct",
|
|
"gpt-3.5-turbo-instruct-0914",
|
|
"gpt-4",
|
|
"gpt-4-0125-preview",
|
|
"gpt-4-0613",
|
|
"gpt-4-1106-preview",
|
|
"gpt-4-turbo",
|
|
"gpt-4-turbo-2024-04-09",
|
|
"gpt-4-turbo-preview",
|
|
"gpt-4.1",
|
|
"gpt-4.1-2025-04-14",
|
|
"gpt-4.1-mini",
|
|
"gpt-4.1-mini-2025-04-14",
|
|
"gpt-4.1-nano",
|
|
"gpt-4.1-nano-2025-04-14",
|
|
"gpt-4.5-preview",
|
|
"gpt-4.5-preview-2025-02-27",
|
|
"gpt-4o",
|
|
"gpt-4o-2024-05-13",
|
|
"gpt-4o-2024-08-06",
|
|
"gpt-4o-2024-11-20",
|
|
"gpt-4o-audio-preview",
|
|
"gpt-4o-audio-preview-2024-10-01",
|
|
"gpt-4o-audio-preview-2024-12-17",
|
|
"gpt-4o-audio-preview-2025-06-03",
|
|
"gpt-4o-mini-2024-07-18",
|
|
"gpt-4o-mini-audio-preview",
|
|
"gpt-4o-mini-audio-preview-2024-12-17",
|
|
"gpt-4o-mini-realtime-preview",
|
|
"gpt-4o-mini-realtime-preview-2024-12-17",
|
|
"gpt-4o-mini-search-preview",
|
|
"gpt-4o-mini-search-preview-2025-03-11",
|
|
"gpt-4o-mini-transcribe",
|
|
"gpt-4o-mini-tts",
|
|
"gpt-4o-realtime-preview",
|
|
"gpt-4o-realtime-preview-2024-10-01",
|
|
"gpt-4o-realtime-preview-2024-12-17",
|
|
"gpt-4o-realtime-preview-2025-06-03",
|
|
"gpt-4o-search-preview",
|
|
"gpt-4o-search-preview-2025-03-11",
|
|
"gpt-4o-transcribe",
|
|
"gpt-5",
|
|
"gpt-5-2025-08-07",
|
|
"gpt-5-chat-latest",
|
|
"gpt-5-mini",
|
|
"gpt-5-mini-2025-08-07",
|
|
"gpt-5-nano",
|
|
"gpt-5-nano-2025-08-07",
|
|
"gpt-audio",
|
|
"gpt-audio-2025-08-28",
|
|
"gpt-image-1",
|
|
"gpt-realtime",
|
|
"gpt-realtime-2025-08-28",
|
|
"gpt40-0806-loco-vm",
|
|
"o1",
|
|
"o1-2024-12-17",
|
|
"o1-mini",
|
|
"o1-mini-2024-09-12",
|
|
"o1-preview",
|
|
"o1-preview-2024-09-12",
|
|
"o1-pro",
|
|
"o1-pro-2025-03-19",
|
|
"o3",
|
|
"o3-2025-04-16",
|
|
"o3-deep-research",
|
|
"o3-deep-research-2025-06-26",
|
|
"o3-mini",
|
|
"o3-mini-2025-01-31",
|
|
"o3-pro",
|
|
"o3-pro-2025-06-10",
|
|
"o4-mini",
|
|
"o4-mini-2025-04-16",
|
|
"o4-mini-deep-research",
|
|
"o4-mini-deep-research-2025-06-26",
|
|
"omni-moderation-2024-09-26",
|
|
"omni-moderation-latest",
|
|
"text-embedding-3-large",
|
|
"text-embedding-3-small",
|
|
"text-embedding-ada-002",
|
|
"tts-1",
|
|
"tts-1-1106",
|
|
"tts-1-hd",
|
|
"tts-1-hd-1106",
|
|
"tts-l-hd",
|
|
"whisper-1",
|
|
"whisper-I"
|
|
],
|
|
"gemini": [
|
|
"gemini-2.5-flash-image-preview",
|
|
"aqa",
|
|
"embedding-001",
|
|
"embedding-gecko-001",
|
|
"gemini-1.5-flash",
|
|
"gemini-1.5-flash-002",
|
|
"gemini-1.5-flash-8b",
|
|
"gemini-1.5-flash-8b-001",
|
|
"gemini-1.5-flash-8b-latest",
|
|
"gemini-1.5-flash-latest",
|
|
"gemini-1.5-pro",
|
|
"gemini-1.5-pro-002",
|
|
"gemini-1.5-pro-latest",
|
|
"gemini-2.0-flash",
|
|
"gemini-2.0-flash-001",
|
|
"gemini-2.0-flash-exp",
|
|
"gemini-2.0-flash-lite",
|
|
"gemini-2.0-flash-lite-001",
|
|
"gemini-2.0-flash-lite-preview",
|
|
"gemini-2.0-flash-lite-preview-02-05",
|
|
"gemini-2.0-flash-thinking-exp",
|
|
"gemini-2.0-flash-thinking-exp-01-21",
|
|
"gemini-2.0-flash-thinking-exp-1219",
|
|
"gemini-2.0-pro-exp",
|
|
"gemini-2.0-pro-exp-02-05",
|
|
"gemini-2.5-flash",
|
|
"gemini-2.5-flash-image-preview",
|
|
"gemini-2.5-flash-lite",
|
|
"gemini-2.5-flash-lite-preview-06-17",
|
|
"gemini-2.5-flash-preview-05-20",
|
|
"gemini-2.5-flash-preview-tts",
|
|
"gemini-2.5-pro",
|
|
"gemini-2.5-pro-preview-03-25",
|
|
"gemini-2.5-pro-preview-05-06",
|
|
"gemini-2.5-pro-preview-06-05",
|
|
"gemini-2.5-pro-preview-tts",
|
|
"gemini-embedding-001",
|
|
"gemini-embedding-exp",
|
|
"gemini-embedding-exp-03-07",
|
|
"gemini-exp-1206",
|
|
"gemma-3-12b-it",
|
|
"gemma-3-1b-it",
|
|
"gemma-3-27b-it",
|
|
"gemma-3-4b-it",
|
|
"gemma-3n-e2b-it",
|
|
"gemma-3n-e4b-it",
|
|
"imagen-3.0-generate-002",
|
|
"imagen-4.0-generate-preview-06-06",
|
|
"imagen-4.0-ultra-generate-preview-06-06",
|
|
"learnlm-2.0-flash-experimental",
|
|
"text-embedding-004"
|
|
],
|
|
"groq": [
|
|
"moonshotai/kimi-k2-instruct",
|
|
"allam-2-7b",
|
|
"compound-beta",
|
|
"compound-beta-mini",
|
|
"deepseek-r1-distill-llama-70b",
|
|
"gemma2-9b-it",
|
|
"llama-3.1-8b-instant",
|
|
"llama-3.3-70b-versatile",
|
|
"meta-llama/llama-4-maverick-17b-128e-instruct",
|
|
"meta-llama/llama-4-scout-17b-16e-instruct",
|
|
"meta-llama/llama-guard-4-12b",
|
|
"meta-llama/llama-prompt-guard-2-22m",
|
|
"meta-llama/llama-prompt-guard-2-86m",
|
|
"openai/gpt-oss-120b",
|
|
"openai/gpt-oss-20b",
|
|
"playai-tts",
|
|
"playai-tts-arabic",
|
|
"qwen/qwen3-32b",
|
|
"whisper-large-v3",
|
|
"whisper-large-v3-turbo"
|
|
],
|
|
"anthropic": [
|
|
"claude-3-5-sonnet-20241022", "claude-3-5-haiku-20241022",
|
|
"claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307"
|
|
],
|
|
"mistral": [
|
|
"mistral-large-latest", "mistral-medium-latest", "mistral-small-latest",
|
|
"mistral-tiny-latest", "codestral-latest", "pixtral-12b-latest",
|
|
"open-mixtral-8x22b", "open-mixtral-8x7b", "open-mistral-7b"
|
|
],
|
|
"deepseek": [
|
|
"deepseek-chat",
|
|
"deepseek-coder"
|
|
],
|
|
"bfl": ["flux-kontext-max"],
|
|
"suno": ["V3_5", "V4", "V4_5"],
|
|
"wavespeed": [
|
|
"wavespeed-ai/flux-kontext-dev-ultra-fast", "wavespeed-ai/flux-kontext-dev/multi-ultra-fast", "wavespeed-ai/hunyuan-image-3", "wavespeed-ai/qwen-image/edit-plus",
|
|
"bytedance/portrait", "bytedance/seededit-v3", "google/imagen4", "google/imagen4-fast", "google/imagen4-ultra",
|
|
"google/nano-banana/edit", "bytedance/dreamina-v3.1/text-to-image",
|
|
"minimax/hailuo-02/t2v-standard", "minimax/hailuo-02/t2v-pro",
|
|
"minimax/hailuo-02/i2v-pro", "minimax/hailuo-02/i2v-standard",
|
|
"kwaivgi/kling-v2.1-i2v-standard", "kwaivgi/kling-v2.1-i2v-pro", "kwaivgi/kling-v2.1-i2v-master",
|
|
"kwaivgi/kling-v2.5-turbo-pro/image-to-video", "kwaivgi/kling-v2.5-turbo-pro/text-to-video",
|
|
"kwaivgi/kling-lipsync/audio-to-video", "kwaivgi/kling-lipsync/text-to-video",
|
|
"kwaivgi/kling-v1-ai-avatar-pro", "kwaivgi/kling-effects",
|
|
"google/veo3-fast/image-to-video", "google/veo3/image-to-video",
|
|
"google/veo3-fast", "wavespeed-ai/veo2-t2v", "wavespeed-ai/veo2-i2v",
|
|
"alibaba/wan-2.5/text-to-video", "alibaba/wan-2.5/text-to-video-fast",
|
|
"alibaba/wan-2.5/image-to-video", "alibaba/wan-2.5/image-to-video-fast"
|
|
],
|
|
"openrouter": [
|
|
"google/gemini-2.5-flash-image-preview",
|
|
"agentica-org/deepcoder-14b-preview",
|
|
"agentica-org/deepcoder-14b-preview:free",
|
|
"ai21/jamba-large-1.7",
|
|
"ai21/jamba-mini-1.7",
|
|
"aion-labs/aion-1.0",
|
|
"aion-labs/aion-1.0-mini",
|
|
"aion-labs/aion-rp-llama-3.1-8b",
|
|
"alfredpros/codellama-7b-instruct-solidity",
|
|
"alpindale/goliath-120b",
|
|
"amazon/nova-lite-v1",
|
|
"amazon/nova-micro-v1",
|
|
"amazon/nova-pro-v1",
|
|
"anthracite-org/magnum-v2-72b",
|
|
"anthracite-org/magnum-v4-72b",
|
|
"anthropic/claude-3-haiku",
|
|
"anthropic/claude-3-opus",
|
|
"anthropic/claude-3.5-haiku",
|
|
"anthropic/claude-3.5-haiku-20241022",
|
|
"anthropic/claude-3.5-sonnet",
|
|
"anthropic/claude-3.5-sonnet-20240620",
|
|
"anthropic/claude-3.7-sonnet",
|
|
"anthropic/claude-3.7-sonnet:thinking",
|
|
"anthropic/claude-opus-4",
|
|
"anthropic/claude-opus-4.1",
|
|
"anthropic/claude-sonnet-4",
|
|
"arcee-ai/coder-large",
|
|
"arcee-ai/maestro-reasoning",
|
|
"arcee-ai/spotlight",
|
|
"arcee-ai/virtuoso-large",
|
|
"arliai/qwq-32b-arliai-rpr-v1",
|
|
"arliai/qwq-32b-arliai-rpr-v1:free",
|
|
"baidu/ernie-4.5-21b-a3b",
|
|
"baidu/ernie-4.5-300b-a47b",
|
|
"baidu/ernie-4.5-vl-28b-a3b",
|
|
"baidu/ernie-4.5-vl-424b-a47b",
|
|
"bytedance/ui-tars-1.5-7b",
|
|
"cognitivecomputations/dolphin-mistral-24b-venice-edition:free",
|
|
"cognitivecomputations/dolphin-mixtral-8x22b",
|
|
"cognitivecomputations/dolphin3.0-mistral-24b",
|
|
"cognitivecomputations/dolphin3.0-mistral-24b:free",
|
|
"cognitivecomputations/dolphin3.0-r1-mistral-24b",
|
|
"cognitivecomputations/dolphin3.0-r1-mistral-24b:free",
|
|
"cohere/command",
|
|
"cohere/command-a",
|
|
"cohere/command-r",
|
|
"cohere/command-r-03-2024",
|
|
"cohere/command-r-08-2024",
|
|
"cohere/command-r-plus",
|
|
"cohere/command-r-plus-04-2024",
|
|
"cohere/command-r-plus-08-2024",
|
|
"cohere/command-r7b-12-2024",
|
|
"deepseek/deepseek-chat",
|
|
"deepseek/deepseek-chat-v3-0324",
|
|
"deepseek/deepseek-chat-v3-0324:free",
|
|
"deepseek/deepseek-chat-v3.1",
|
|
"deepseek/deepseek-chat-v3.1:free",
|
|
"deepseek/deepseek-prover-v2",
|
|
"deepseek/deepseek-r1",
|
|
"deepseek/deepseek-r1-0528",
|
|
"deepseek/deepseek-r1-0528-qwen3-8b",
|
|
"deepseek/deepseek-r1-0528-qwen3-8b:free",
|
|
"deepseek/deepseek-r1-0528:free",
|
|
"deepseek/deepseek-r1-distill-llama-70b",
|
|
"deepseek/deepseek-r1-distill-llama-70b:free",
|
|
"deepseek/deepseek-r1-distill-llama-8b",
|
|
"deepseek/deepseek-r1-distill-qwen-14b",
|
|
"deepseek/deepseek-r1-distill-qwen-14b:free",
|
|
"deepseek/deepseek-r1-distill-qwen-32b",
|
|
"deepseek/deepseek-r1:free",
|
|
"deepseek/deepseek-v3.1-base",
|
|
"eleutherai/llemma_7b",
|
|
"google/gemini-2.0-flash-001",
|
|
"google/gemini-2.0-flash-exp:free",
|
|
"google/gemini-2.0-flash-lite-001",
|
|
"google/gemini-2.5-flash",
|
|
"google/gemini-2.5-flash-image-preview",
|
|
"google/gemini-2.5-flash-image-preview:free",
|
|
"google/gemini-2.5-flash-lite",
|
|
"google/gemini-2.5-flash-lite-preview-06-17",
|
|
"google/gemini-2.5-pro",
|
|
"google/gemini-2.5-pro-exp-03-25",
|
|
"google/gemini-2.5-pro-preview",
|
|
"google/gemini-2.5-pro-preview-05-06",
|
|
"google/gemini-flash-1.5",
|
|
"google/gemini-flash-1.5-8b",
|
|
"google/gemini-pro-1.5",
|
|
"google/gemma-2-27b-it",
|
|
"google/gemma-2-9b-it",
|
|
"google/gemma-2-9b-it:free",
|
|
"google/gemma-3-12b-it",
|
|
"google/gemma-3-12b-it:free",
|
|
"google/gemma-3-27b-it",
|
|
"google/gemma-3-27b-it:free",
|
|
"google/gemma-3-4b-it",
|
|
"google/gemma-3-4b-it:free",
|
|
"google/gemma-3n-e2b-it:free",
|
|
"google/gemma-3n-e4b-it",
|
|
"google/gemma-3n-e4b-it:free",
|
|
"gryphe/mythomax-l2-13b",
|
|
"inception/mercury",
|
|
"inception/mercury-coder",
|
|
"infermatic/mn-inferor-12b",
|
|
"inflection/inflection-3-pi",
|
|
"inflection/inflection-3-productivity",
|
|
"liquid/lfm-3b",
|
|
"liquid/lfm-7b",
|
|
"mancer/weaver",
|
|
"meta-llama/llama-3-70b-instruct",
|
|
"meta-llama/llama-3-8b-instruct",
|
|
"meta-llama/llama-3.1-405b",
|
|
"meta-llama/llama-3.1-405b-instruct",
|
|
"meta-llama/llama-3.1-405b-instruct:free",
|
|
"meta-llama/llama-3.1-70b-instruct",
|
|
"meta-llama/llama-3.1-8b-instruct",
|
|
"meta-llama/llama-3.2-11b-vision-instruct",
|
|
"meta-llama/llama-3.2-1b-instruct",
|
|
"meta-llama/llama-3.2-3b-instruct",
|
|
"meta-llama/llama-3.2-3b-instruct:free",
|
|
"meta-llama/llama-3.2-90b-vision-instruct",
|
|
"meta-llama/llama-3.3-70b-instruct",
|
|
"meta-llama/llama-3.3-70b-instruct:free",
|
|
"meta-llama/llama-3.3-8b-instruct:free",
|
|
"meta-llama/llama-4-maverick",
|
|
"meta-llama/llama-4-maverick:free",
|
|
"meta-llama/llama-4-scout",
|
|
"meta-llama/llama-4-scout:free",
|
|
"meta-llama/llama-guard-2-8b",
|
|
"meta-llama/llama-guard-3-8b",
|
|
"meta-llama/llama-guard-4-12b",
|
|
"microsoft/mai-ds-r1",
|
|
"microsoft/mai-ds-r1:free",
|
|
"microsoft/phi-3-medium-128k-instruct",
|
|
"microsoft/phi-3-mini-128k-instruct",
|
|
"microsoft/phi-3.5-mini-128k-instruct",
|
|
"microsoft/phi-4",
|
|
"microsoft/phi-4-multimodal-instruct",
|
|
"microsoft/phi-4-reasoning-plus",
|
|
"microsoft/wizardlm-2-8x22b",
|
|
"minimax/minimax-01",
|
|
"minimax/minimax-m1",
|
|
"mistralai/codestral-2501",
|
|
"mistralai/codestral-2508",
|
|
"mistralai/devstral-medium",
|
|
"mistralai/devstral-small",
|
|
"mistralai/devstral-small-2505",
|
|
"mistralai/devstral-small-2505:free",
|
|
"mistralai/magistral-medium-2506",
|
|
"mistralai/magistral-medium-2506:thinking",
|
|
"mistralai/magistral-small-2506",
|
|
"mistralai/ministral-3b",
|
|
"mistralai/ministral-8b",
|
|
"mistralai/mistral-7b-instruct",
|
|
"mistralai/mistral-7b-instruct-v0.1",
|
|
"mistralai/mistral-7b-instruct-v0.3",
|
|
"mistralai/mistral-7b-instruct:free",
|
|
"mistralai/mistral-large",
|
|
"mistralai/mistral-large-2407",
|
|
"mistralai/mistral-large-2411",
|
|
"mistralai/mistral-medium-3",
|
|
"mistralai/mistral-medium-3.1",
|
|
"mistralai/mistral-nemo",
|
|
"mistralai/mistral-nemo:free",
|
|
"mistralai/mistral-saba",
|
|
"mistralai/mistral-small",
|
|
"mistralai/mistral-small-24b-instruct-2501",
|
|
"mistralai/mistral-small-24b-instruct-2501:free",
|
|
"mistralai/mistral-small-3.1-24b-instruct",
|
|
"mistralai/mistral-small-3.1-24b-instruct:free",
|
|
"mistralai/mistral-small-3.2-24b-instruct",
|
|
"mistralai/mistral-small-3.2-24b-instruct:free",
|
|
"mistralai/mistral-tiny",
|
|
"mistralai/mixtral-8x22b-instruct",
|
|
"mistralai/mixtral-8x7b-instruct",
|
|
"mistralai/pixtral-12b",
|
|
"mistralai/pixtral-large-2411",
|
|
"moonshotai/kimi-dev-72b",
|
|
"moonshotai/kimi-dev-72b:free",
|
|
"moonshotai/kimi-k2",
|
|
"moonshotai/kimi-k2:free",
|
|
"moonshotai/kimi-vl-a3b-thinking",
|
|
"moonshotai/kimi-vl-a3b-thinking:free",
|
|
"morph/morph-v3-fast",
|
|
"morph/morph-v3-large",
|
|
"neversleep/llama-3-lumimaid-70b",
|
|
"neversleep/llama-3.1-lumimaid-8b",
|
|
"neversleep/noromaid-20b",
|
|
"nousresearch/deephermes-3-llama-3-8b-preview:free",
|
|
"nousresearch/deephermes-3-mistral-24b-preview",
|
|
"nousresearch/hermes-2-pro-llama-3-8b",
|
|
"nousresearch/hermes-3-llama-3.1-405b",
|
|
"nousresearch/hermes-3-llama-3.1-70b",
|
|
"nousresearch/hermes-4-405b",
|
|
"nousresearch/hermes-4-70b",
|
|
"nvidia/llama-3.1-nemotron-70b-instruct",
|
|
"nvidia/llama-3.1-nemotron-ultra-253b-v1",
|
|
"nvidia/llama-3.1-nemotron-ultra-253b-v1:free",
|
|
"nvidia/llama-3.3-nemotron-super-49b-v1",
|
|
"openai/chatgpt-4o-latest",
|
|
"openai/codex-mini",
|
|
"openai/gpt-3.5-turbo",
|
|
"openai/gpt-3.5-turbo-0613",
|
|
"openai/gpt-3.5-turbo-16k",
|
|
"openai/gpt-3.5-turbo-instruct",
|
|
"openai/gpt-4",
|
|
"openai/gpt-4-0314",
|
|
"openai/gpt-4-1106-preview",
|
|
"openai/gpt-4-turbo",
|
|
"openai/gpt-4-turbo-preview",
|
|
"openai/gpt-4.1",
|
|
"openai/gpt-4.1-mini",
|
|
"openai/gpt-4.1-nano",
|
|
"openai/gpt-4o",
|
|
"openai/gpt-4o-2024-05-13",
|
|
"openai/gpt-4o-2024-08-06",
|
|
"openai/gpt-4o-2024-11-20",
|
|
"openai/gpt-4o-audio-preview",
|
|
"openai/gpt-4o-mini",
|
|
"openai/gpt-4o-mini-2024-07-18",
|
|
"openai/gpt-4o-mini-search-preview",
|
|
"openai/gpt-4o-search-preview",
|
|
"openai/gpt-4o:extended",
|
|
"openai/gpt-5",
|
|
"openai/gpt-5-chat",
|
|
"openai/gpt-5-mini",
|
|
"openai/gpt-5-nano",
|
|
"openai/gpt-oss-120b",
|
|
"openai/gpt-oss-120b:free",
|
|
"openai/gpt-oss-20b",
|
|
"openai/gpt-oss-20b:free",
|
|
"openai/o1",
|
|
"openai/o1-mini",
|
|
"openai/o1-mini-2024-09-12",
|
|
"openai/o1-pro",
|
|
"openai/o3",
|
|
"openai/o3-mini",
|
|
"openai/o3-mini-high",
|
|
"openai/o3-pro",
|
|
"openai/o4-mini",
|
|
"openai/o4-mini-high",
|
|
"opengvlab/internvl3-14b",
|
|
"openrouter/auto",
|
|
"perplexity/r1-1776",
|
|
"perplexity/sonar",
|
|
"perplexity/sonar-deep-research",
|
|
"perplexity/sonar-pro",
|
|
"perplexity/sonar-reasoning",
|
|
"perplexity/sonar-reasoning-pro",
|
|
"pygmalionai/mythalion-13b",
|
|
"qwen/qwen-2.5-72b-instruct",
|
|
"qwen/qwen-2.5-72b-instruct:free",
|
|
"qwen/qwen-2.5-7b-instruct",
|
|
"qwen/qwen-2.5-coder-32b-instruct",
|
|
"qwen/qwen-2.5-coder-32b-instruct:free",
|
|
"qwen/qwen-2.5-vl-7b-instruct",
|
|
"qwen/qwen-max",
|
|
"qwen/qwen-plus",
|
|
"qwen/qwen-turbo",
|
|
"qwen/qwen-vl-max",
|
|
"qwen/qwen-vl-plus",
|
|
"qwen/qwen2.5-vl-32b-instruct",
|
|
"qwen/qwen2.5-vl-32b-instruct:free",
|
|
"qwen/qwen2.5-vl-72b-instruct",
|
|
"qwen/qwen2.5-vl-72b-instruct:free",
|
|
"qwen/qwen3-14b",
|
|
"qwen/qwen3-14b:free",
|
|
"qwen/qwen3-235b-a22b",
|
|
"qwen/qwen3-235b-a22b-2507",
|
|
"qwen/qwen3-235b-a22b-thinking-2507",
|
|
"qwen/qwen3-235b-a22b:free",
|
|
"qwen/qwen3-30b-a3b",
|
|
"qwen/qwen3-30b-a3b-instruct-2507",
|
|
"qwen/qwen3-30b-a3b-thinking-2507",
|
|
"qwen/qwen3-30b-a3b:free",
|
|
"qwen/qwen3-32b",
|
|
"qwen/qwen3-4b:free",
|
|
"qwen/qwen3-8b",
|
|
"qwen/qwen3-8b:free",
|
|
"qwen/qwen3-coder",
|
|
"qwen/qwen3-coder-30b-a3b-instruct",
|
|
"qwen/qwen3-coder:free",
|
|
"qwen/qwq-32b",
|
|
"qwen/qwq-32b-preview",
|
|
"qwen/qwq-32b:free",
|
|
"raifle/sorcererlm-8x22b",
|
|
"rekaai/reka-flash-3:free",
|
|
"sao10k/l3-euryale-70b",
|
|
"sao10k/l3-lunaris-8b",
|
|
"sao10k/l3.1-euryale-70b",
|
|
"sao10k/l3.3-euryale-70b",
|
|
"scb10x/llama3.1-typhoon2-70b-instruct",
|
|
"shisa-ai/shisa-v2-llama3.3-70b",
|
|
"shisa-ai/shisa-v2-llama3.3-70b:free",
|
|
"sophosympatheia/midnight-rose-70b",
|
|
"switchpoint/router",
|
|
"tencent/hunyuan-a13b-instruct",
|
|
"tencent/hunyuan-a13b-instruct:free",
|
|
"thedrummer/anubis-70b-v1.1",
|
|
"thedrummer/anubis-pro-105b-v1",
|
|
"thedrummer/rocinante-12b",
|
|
"thedrummer/skyfall-36b-v2",
|
|
"thedrummer/unslopnemo-12b",
|
|
"thudm/glm-4-32b",
|
|
"thudm/glm-4.1v-9b-thinking",
|
|
"thudm/glm-z1-32b",
|
|
"tngtech/deepseek-r1t-chimera",
|
|
"tngtech/deepseek-r1t-chimera:free",
|
|
"tngtech/deepseek-r1t2-chimera:free",
|
|
"undi95/remm-slerp-l2-13b",
|
|
"x-ai/grok-2-1212",
|
|
"x-ai/grok-2-vision-1212",
|
|
"x-ai/grok-3",
|
|
"x-ai/grok-3-beta",
|
|
"x-ai/grok-3-mini",
|
|
"x-ai/grok-3-mini-beta",
|
|
"x-ai/grok-4",
|
|
"x-ai/grok-code-fast-1",
|
|
"x-ai/grok-vision-beta",
|
|
"z-ai/glm-4-32b",
|
|
"z-ai/glm-4.5",
|
|
"z-ai/glm-4.5-air",
|
|
"z-ai/glm-4.5-air:free",
|
|
"z-ai/glm-4.5v",
|
|
]
|
|
};
|
|
|
|
app.registerExtension({
|
|
name: "ComfyLLMToolkit.APIProviderSelector",
|
|
|
|
async nodeCreated(node) {
|
|
if (node.comfyClass === "APIProviderSelectorNode") {
|
|
// Find the widgets safely
|
|
const providerWidget = node.widgets?.find(w => w.name === "provider");
|
|
const modelWidget = node.widgets?.find(w => w.name === "llm_model");
|
|
const apiKeyWidget = node.widgets?.find(w => w.name === "external_api_key");
|
|
|
|
if (!providerWidget || !modelWidget) {
|
|
console.warn("APIProviderSelector: Required widgets not found");
|
|
return;
|
|
}
|
|
|
|
// Function to update model list based on provider
|
|
const updateModelList = (provider) => {
|
|
// Skip if graph is loading to prevent freezes
|
|
if (app.graph?.isLoading) {
|
|
return;
|
|
}
|
|
|
|
const models = PROVIDER_MODELS[provider] || ["No models available"];
|
|
|
|
// Update the widget options
|
|
modelWidget.options.values = models;
|
|
|
|
// Set to first model if current selection is invalid
|
|
if (!models.includes(modelWidget.value)) {
|
|
modelWidget.value = models[0];
|
|
}
|
|
|
|
// Mark node as dirty to trigger re-render
|
|
node.setDirtyCanvas(true);
|
|
|
|
console.log(`APIProviderSelector: Updated models for ${provider}: ${models.length} models`);
|
|
};
|
|
|
|
// Store original callback
|
|
const originalProviderCallback = providerWidget.callback;
|
|
|
|
// Fetch models from JSON files or hardcoded fallback
|
|
const updateLLMModels = async () => {
|
|
const provider = providerWidget.value;
|
|
const external_api_key = apiKeyWidget ? apiKeyWidget.value : "";
|
|
|
|
try {
|
|
// Use POST request to fetch from the dynamic endpoint
|
|
const response = await fetch('/ComfyLLMToolkit/get_provider_models', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
provider: provider,
|
|
external_api_key: external_api_key
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
console.log(`APIProviderSelector: Loaded models via POST:`, data);
|
|
|
|
if (data.models && Array.isArray(data.models) && data.models.length > 0) {
|
|
// Update both the cache and widget
|
|
PROVIDER_MODELS[provider] = data.models;
|
|
modelWidget.options.values = data.models;
|
|
|
|
// Set to first model if current selection is invalid
|
|
if (!data.models.includes(modelWidget.value)) {
|
|
modelWidget.value = data.models[0];
|
|
}
|
|
|
|
node.setDirtyCanvas(true);
|
|
console.log(`APIProviderSelector: Updated ${data.models.length} models for ${provider}`);
|
|
} else {
|
|
throw new Error("No models available from provider API");
|
|
}
|
|
} catch (error) {
|
|
console.error("Error updating models via POST:", error);
|
|
|
|
// Fallback to hardcoded models on error
|
|
const models = PROVIDER_MODELS[provider] || ["No models available (fallback)"];
|
|
modelWidget.options.values = models;
|
|
if (!models.includes(modelWidget.value)) {
|
|
modelWidget.value = models[0];
|
|
}
|
|
node.setDirtyCanvas(true);
|
|
}
|
|
};
|
|
|
|
// Add manual refresh button as a widget
|
|
if (!node.widgets.find(w => w.name === "_refresh_models")) {
|
|
const refreshButton = node.addWidget("button", "_refresh_models", "Refresh Models", () => {
|
|
updateLLMModels();
|
|
});
|
|
refreshButton.serialize = false; // Don't save button in workflow
|
|
}
|
|
|
|
// Update callback to use new function
|
|
providerWidget.callback = function() {
|
|
// Call original callback if it exists
|
|
if (originalProviderCallback) {
|
|
originalProviderCallback.apply(this, arguments);
|
|
}
|
|
|
|
// Fetch fresh models when provider changes
|
|
updateLLMModels();
|
|
};
|
|
|
|
// Initial model fetch
|
|
// updateLLMModels();
|
|
}
|
|
},
|
|
|
|
async loadedGraphNode(node) {
|
|
if (node.comfyClass === "APIProviderSelectorNode") {
|
|
// Re-initialize model list when loading a saved workflow
|
|
const providerWidget = node.widgets?.find(w => w.name === "provider");
|
|
const modelWidget = node.widgets?.find(w => w.name === "llm_model");
|
|
|
|
if (providerWidget && modelWidget) {
|
|
const models = PROVIDER_MODELS[providerWidget.value] || ["No models available"];
|
|
modelWidget.options.values = models;
|
|
|
|
// Ensure saved model is still valid
|
|
if (!models.includes(modelWidget.value)) {
|
|
modelWidget.value = models[0];
|
|
}
|
|
|
|
console.log(`APIProviderSelector: Restored ${providerWidget.value} with model ${modelWidget.value}`);
|
|
}
|
|
}
|
|
}
|
|
});
|