Skip to content

Commit c3cda09

Browse files
author
li
committed
Merge branch 'main' into bugfix_1010
# Conflicts: # dist/copilot_web/App-BAhsLA_k.js # dist/copilot_web/App-CuMdgNo-.js # dist/copilot_web/App-D20OCP3V.js # dist/copilot_web/DebugResult-BeEv9QOc.js # dist/copilot_web/DebugResult-CJvu9_Eq.js # dist/copilot_web/DebugResult-CMLMZ1Zj.js # dist/copilot_web/WorkflowOption-BwjPcrmI.js # dist/copilot_web/WorkflowOption-CLWpJzah.js # dist/copilot_web/WorkflowOption-ChQrrvK_.js # dist/copilot_web/input.js # dist/copilot_web/workflowChat-B_fMY0j3.js # ui/src/components/chat/ApiKeyModal.tsx
2 parents d7119f6 + 121ac8a commit c3cda09

File tree

8 files changed

+229
-13
lines changed

8 files changed

+229
-13
lines changed

backend/controller/conversation_api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ async def invoke_chat(request):
245245
# Workflow LLM settings (optional, used by tools/agents that need a different LLM)
246246
"workflow_llm_api_key": request.headers.get('Workflow-LLM-Api-Key'),
247247
"workflow_llm_base_url": request.headers.get('Workflow-LLM-Base-Url'),
248+
"workflow_llm_model": request.headers.get('Workflow-LLM-Model'),
248249
"model_select": next((x['data'][0] for x in ext if x['type'] == 'model_select' and x.get('data')), None)
249250
}
250251

@@ -514,6 +515,7 @@ async def invoke_debug(request):
514515
# Workflow LLM settings (optional)
515516
"workflow_llm_api_key": request.headers.get('Workflow-LLM-Api-Key'),
516517
"workflow_llm_base_url": request.headers.get('Workflow-LLM-Base-Url'),
518+
"workflow_llm_model": request.headers.get('Workflow-LLM-Model'),
517519
}
518520

519521
# 获取当前语言

backend/controller/llm_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'''
22
Author: ai-business-hql [email protected]
33
Date: 2025-07-14 16:46:20
4-
LastEditors: ai-business-hql qingli.hql@alibaba-inc.com
5-
LastEditTime: 2025-08-11 16:08:07
4+
LastEditors: ai-business-hql ai.bussiness.hql@gmail.com
5+
LastEditTime: 2025-10-15 17:17:28
66
FilePath: /comfyui_copilot/backend/controller/llm_api.py
77
Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
88
'''

backend/service/mcp_client.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
"Detected incorrect or missing 'agents' package while loading MCP components. "
3030
"Please install 'openai-agents' and ensure this plugin prefers it. Commands:\n"
3131
" python -m pip uninstall -y agents gym tensorflow\n"
32-
" python -m pip install -U openai-agents\n\n"
33-
"Or set COMFYUI_COPILOT_PREFER_OPENAI_AGENTS=1 to prefer openai-agents without uninstalling."
32+
" python -m pip install -U openai-agents"
3433
)
3534

3635
from ..agent_factory import create_agent

backend/service/workflow_rewrite_tools.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
"Detected incorrect or missing 'agents' package while loading tools. "
1616
"Please install 'openai-agents' and ensure this plugin prefers it. Commands:\n"
1717
" python -m pip uninstall -y agents gym tensorflow\n"
18-
" python -m pip install -U openai-agents\n\n"
19-
"Or set COMFYUI_COPILOT_PREFER_OPENAI_AGENTS=1 to prefer openai-agents without uninstalling."
18+
" python -m pip install -U openai-agents\n"
2019
)
2120
from .workflow_rewrite_agent_simple import rewrite_workflow_simple
2221

backend/utils/key_utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
'''
2+
Author: ai-business-hql [email protected]
3+
Date: 2025-10-11 16:46:10
4+
LastEditors: ai-business-hql [email protected]
5+
LastEditTime: 2025-10-15 14:35:41
6+
FilePath: /ComfyUI-Copilot/backend/utils/key_utils.py
7+
Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
8+
'''
19
from copy import deepcopy
210

311
def workflow_config_adapt(config: dict) -> dict:
@@ -17,5 +25,10 @@ def workflow_config_adapt(config: dict) -> dict:
1725
if new_config.get("workflow_llm_base_url"):
1826
new_config["openai_base_url"] = new_config.get("workflow_llm_base_url")
1927
new_config["workflow_llm_base_url"] = None
28+
if new_config.get("workflow_llm_model"):
29+
new_config["model_select"] = new_config.get("workflow_llm_model")
30+
new_config["workflow_llm_model"] = None
31+
else:
32+
new_config["model_select"] = None
2033

2134
return new_config

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "ComfyUI-Copilot"
33
description = "Your Intelligent Assistant for Comfy-UI."
4-
version = "2.0.18"
4+
version = "2.0.19"
55
license = {file = "LICENSE"}
66

77
[project.urls]

ui/src/apis/workflowChatApi.ts

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @Author: ai-business-hql [email protected]
33
* @Date: 2025-06-24 16:29:05
44
* @LastEditors: ai-business-hql [email protected]
5-
* @LastEditTime: 2025-09-29 17:43:30
5+
* @LastEditTime: 2025-10-15 14:49:15
66
* @FilePath: /comfyui_copilot/ui/src/apis/workflowChatApi.ts
77
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
88
*/
@@ -38,13 +38,15 @@ const getOpenAiConfig = () => {
3838
const rsaPublicKey = localStorage.getItem('rsaPublicKey');
3939
const workflowLLMApiKey = localStorage.getItem('workflowLLMApiKey');
4040
const workflowLLMBaseUrl = localStorage.getItem('workflowLLMBaseUrl');
41+
const workflowLLMModel = localStorage.getItem('workflowLLMModel');
4142

4243
return {
4344
openaiApiKey: openaiApiKey || '',
4445
openaiBaseUrl: openaiBaseUrl || '',
4546
rsaPublicKey,
4647
workflowLLMApiKey: workflowLLMApiKey || '',
4748
workflowLLMBaseUrl: workflowLLMBaseUrl || '',
49+
workflowLLMModel: workflowLLMModel || '',
4850
};
4951
};
5052

@@ -145,7 +147,7 @@ export namespace WorkflowChatAPI {
145147
try {
146148
const apiKey = getApiKey();
147149
const browserLanguage = app.extensionManager.setting.get('Comfy.Locale');
148-
const { openaiApiKey, openaiBaseUrl, rsaPublicKey, workflowLLMApiKey, workflowLLMBaseUrl } = getOpenAiConfig();
150+
const { openaiApiKey, openaiBaseUrl, rsaPublicKey, workflowLLMApiKey, workflowLLMBaseUrl, workflowLLMModel } = getOpenAiConfig();
149151
// Generate a unique message ID for this chat request
150152
const messageId = generateUUID();
151153

@@ -269,6 +271,9 @@ export namespace WorkflowChatAPI {
269271
if (workflowLLMApiKey) {
270272
headers['Workflow-LLM-Api-Key'] = workflowLLMApiKey;
271273
}
274+
if (workflowLLMModel) {
275+
headers['Workflow-LLM-Model'] = workflowLLMModel;
276+
}
272277

273278
// Create controller and combine with external signal if provided
274279
const controller = new AbortController();
@@ -600,12 +605,68 @@ export namespace WorkflowChatAPI {
600605
return result as { models: { label: string; name: string; image_enable: boolean }[] };
601606
}
602607

608+
// Fetch models directly from an OpenAI-compatible LLM server via its /models endpoint
609+
export async function listModelsFromLLM(
610+
baseUrl: string,
611+
apiKey?: string
612+
): Promise<string[]> {
613+
const headers: Record<string, string> = {
614+
'accept': 'application/json',
615+
};
616+
617+
if (apiKey && apiKey.trim() !== '') {
618+
headers['Authorization'] = `Bearer ${apiKey}`;
619+
}
620+
621+
// Normalize base URL to avoid double slashes
622+
const normalizedBase = baseUrl.replace(/\/$/, '');
623+
const url = `${normalizedBase}/models`;
624+
625+
const response = await fetch(url, {
626+
method: 'GET',
627+
headers,
628+
});
629+
630+
if (!response.ok) {
631+
throw new Error(`Failed to fetch models from LLM: ${response.status} ${response.statusText}`);
632+
}
633+
634+
const result = await response.json();
635+
636+
// Attempt to support multiple possible shapes
637+
// OpenAI style: { data: [{ id: string }, ...] }
638+
if (Array.isArray(result?.data)) {
639+
const ids = result.data
640+
.map((m: any) => (typeof m === 'string' ? m : (m?.id || m?.name)))
641+
.filter((v: any) => typeof v === 'string' && v.trim() !== '');
642+
return Array.from(new Set(ids));
643+
}
644+
645+
// Alternate style: { models: [{ id/name }, ...] } or [ ... ]
646+
const modelsField = result?.models ?? result;
647+
if (Array.isArray(modelsField)) {
648+
const ids = modelsField
649+
.map((m: any) => (typeof m === 'string' ? m : (m?.id || m?.name)))
650+
.filter((v: any) => typeof v === 'string' && v.trim() !== '');
651+
return Array.from(new Set(ids));
652+
}
653+
654+
// Single object with id/name
655+
const single = result?.id || result?.name;
656+
if (typeof single === 'string' && single.trim() !== '') {
657+
return [single];
658+
}
659+
660+
// Fallback to empty list if shape is unrecognized
661+
return [];
662+
}
663+
603664
export async function* streamDebugAgent(
604665
workflowData: any,
605666
abortSignal?: AbortSignal
606667
): AsyncGenerator<ChatResponse> {
607668
try {
608-
const { openaiApiKey, openaiBaseUrl, workflowLLMApiKey, workflowLLMBaseUrl } = getOpenAiConfig();
669+
const { openaiApiKey, openaiBaseUrl, workflowLLMApiKey, workflowLLMBaseUrl, workflowLLMModel } = getOpenAiConfig();
609670
const browserLanguage = app.extensionManager.setting.get('Comfy.Locale');
610671
const session_id = localStorage.getItem("sessionId") || null;
611672
const apiKey = getApiKey();
@@ -631,7 +692,9 @@ export namespace WorkflowChatAPI {
631692
if (workflowLLMApiKey) {
632693
headers['Workflow-LLM-Api-Key'] = workflowLLMApiKey;
633694
}
634-
695+
if (workflowLLMModel) {
696+
headers['Workflow-LLM-Model'] = workflowLLMModel;
697+
}
635698
// Create controller and combine with external signal if provided
636699
const controller = new AbortController();
637700
const timeoutId = setTimeout(() => controller.abort(), 120000); // 2 minutes timeout

0 commit comments

Comments
 (0)