feat: 模型下载分页,样式优化,下载路径修复

This commit is contained in:
li
2025-09-01 18:45:37 +08:00
parent 73259a742b
commit 72a7cf925f
26 changed files with 973 additions and 975 deletions
+4 -2
View File
@@ -754,7 +754,7 @@ async def download_model(request):
# 计算目标目录:优先使用传入的dest_dir,否则使用ComfyUI的models目录下对应类型
resolved_dest_dir = None
if dest_dir:
resolved_dest_dir = os.path.abspath(os.path.expanduser(dest_dir))
resolved_dest_dir = os.path.abspath(os.path.expanduser(f"models/{dest_dir}"))
else:
try:
model_type_paths = folder_paths.get_folder_paths(model_type)
@@ -964,6 +964,7 @@ async def model_suggests(request):
log.info("Received model-suggests request")
try:
keyword = request.query.get('keyword')
if not keyword:
return web.json_response({
"success": False,
@@ -973,7 +974,7 @@ async def model_suggests(request):
# 创建ModelScope网关实例
gateway = ModelScopeGateway()
suggests = gateway.suggest(name=keyword, page_size=6)
suggests = gateway.suggest(name=keyword)
list = suggests["data"] if suggests.get("data") else []
@@ -981,6 +982,7 @@ async def model_suggests(request):
"success": True,
"data": {
"suggests": list,
"total": len(list)
},
"message": f"Get suggests successfully"
})
@@ -1,7 +1,7 @@
function getImportPath(filename) {
return `./${filename}`;
}
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["copilot_web/workflowChat-B3aUvb0D.js","copilot_web/vendor-markdown-_DNnI6VC.js","copilot_web/vendor-react-BVt39aT-.js","copilot_web/message-components-DhOCYYxY.js","copilot_web/input.js","copilot_web/assets/input-DF81T5-R.css","copilot_web/fonts.css"].map(path => {
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["copilot_web/workflowChat-Hx0n46Jv.js","copilot_web/vendor-markdown-B4Av9P7l.js","copilot_web/vendor-react-ByKzdfMq.js","copilot_web/message-components-C9d8zznq.js","copilot_web/input.js","copilot_web/assets/input-vDlPdcfE.css","copilot_web/fonts.css"].map(path => {
const apiBase = window.comfyAPI?.api?.api?.api_base;
if (apiBase) {
// 有 API base 时,使用完整路径
@@ -11,4 +11,4 @@ function getImportPath(filename) {
return `./${path}`;
}
}))))=>i.map(i=>d[i]);
import{_ as a}from"./input.js";import{j as o}from"./vendor-markdown-_DNnI6VC.js";import{r as t,R as i}from"./vendor-react-BVt39aT-.js";import{C as n}from"./message-components-DhOCYYxY.js";const s={EXPLAIN_NODE:"copilot:explain-node",TOOLBOX_USAGE:"copilot:toolbox-usage",TOOLBOX_PARAMETERS:"copilot:toolbox-parameters",TOOLBOX_DOWNSTREAMNODES:"copilot:toolbox-downstreamnodes"},d=i.lazy(()=>a(()=>import(getImportPath("workflowChat-B3aUvb0D.js")).then(e=>e.w),__vite__mapDeps([0,1,2,3,4,5,6])).then(e=>({default:e.default})));function c(){const[e,r]=t.useState(!1);return t.useEffect(()=>{const l=()=>{r(!0)};return window.addEventListener(s.EXPLAIN_NODE,l),()=>window.removeEventListener(s.EXPLAIN_NODE,l)},[]),o.jsx(n,{children:o.jsx("div",{className:"h-full w-full flex flex-col",children:o.jsx(t.Suspense,{fallback:o.jsx("div",{className:"h-full w-full flex items-center justify-center",children:"Loading..."}),children:o.jsx(d,{visible:!0,triggerUsage:e,onUsageTriggered:()=>r(!1)})})})})}const O=Object.freeze(Object.defineProperty({__proto__:null,default:c},Symbol.toStringTag,{value:"Module"}));export{O as A,s as C};
import{_ as a}from"./input.js";import{j as o}from"./vendor-markdown-B4Av9P7l.js";import{r as t,R as i}from"./vendor-react-ByKzdfMq.js";import{C as n}from"./message-components-C9d8zznq.js";const s={EXPLAIN_NODE:"copilot:explain-node",TOOLBOX_USAGE:"copilot:toolbox-usage",TOOLBOX_PARAMETERS:"copilot:toolbox-parameters",TOOLBOX_DOWNSTREAMNODES:"copilot:toolbox-downstreamnodes"},d=i.lazy(()=>a(()=>import(getImportPath("workflowChat-Hx0n46Jv.js")).then(e=>e.w),__vite__mapDeps([0,1,2,3,4,5,6])).then(e=>({default:e.default})));function c(){const[e,r]=t.useState(!1);return t.useEffect(()=>{const l=()=>{r(!0)};return window.addEventListener(s.EXPLAIN_NODE,l),()=>window.removeEventListener(s.EXPLAIN_NODE,l)},[]),o.jsx(n,{children:o.jsx("div",{className:"h-full w-full flex flex-col",children:o.jsx(t.Suspense,{fallback:o.jsx("div",{className:"h-full w-full flex items-center justify-center",children:"Loading..."}),children:o.jsx(d,{visible:!0,triggerUsage:e,onUsageTriggered:()=>r(!1)})})})})}const O=Object.freeze(Object.defineProperty({__proto__:null,default:c},Symbol.toStringTag,{value:"Module"}));export{O as A,s as C};
@@ -1,5 +1,5 @@
function getImportPath(filename) {
return `./${filename}`;
}
import{j as s}from"./vendor-markdown-_DNnI6VC.js";import{r as i}from"./vendor-react-BVt39aT-.js";import{u as A,B as D,R as E,i as x,a as m,W as b}from"./message-components-DhOCYYxY.js";function M({content:f,name:k="Assistant",avatar:O,onAddMessage:y,onUpdateMessage:c,messageId:w}){const{dispatch:u,abortControllerRef:l}=A(),[d,_]=i.useState(!1),[T,G]=i.useState(""),[J,S]=i.useState(!1),[j,N]=i.useState(null),r=i.useMemo(()=>{try{return JSON.parse(f)}catch(e){return console.error("Failed to parse message content:",e),null}},[f]),h=i.useMemo(()=>{if(!r||!r.ext)return null;const e=r.ext.find(t=>t.type==="debug_start_checkpoint"||t.type==="debug_checkpoint"&&t.data?.checkpoint_type==="debug_start");return e&&e.data&&e.data.checkpoint_id?e.data.checkpoint_id:null},[r])||j,C=async()=>{if(d)return;const e=x(),t={id:e,role:"ai",content:JSON.stringify({text:`🔍 Starting workflow analysis...
`,ext:[]}),format:"markdown",name:"Assistant",finished:!1,debugGuide:!0};y?.(t);try{await v(),u({type:"SET_LOADING",payload:!0}),await I(e)}finally{_(!1)}},v=async()=>{try{const e=await m.graphToPrompt(),t=localStorage.getItem("sessionId")||"";if(t&&e){const n=await b.saveWorkflowCheckpoint(t,e.output,e.workflow,"debug_start");if(N(n.version_id),console.log(`Saved debug start checkpoint: ${n.version_id}`),c&&r){const o=[...r.ext||[]].filter(g=>g.type!=="debug_start_checkpoint"&&!(g.type==="debug_checkpoint"&&g.data?.checkpoint_type==="debug_start"));o.push({type:"debug_start_checkpoint",data:{checkpoint_id:n.version_id,checkpoint_type:"debug_start"}});const p={id:w||x(),role:"ai",content:JSON.stringify({text:r.text,ext:o}),format:"debug_guide",name:"Assistant"};c(p)}}}catch(e){console.error("Failed to save checkpoint before debug:",e)}},I=async e=>{try{const t=await m.graphToPrompt();let n="",a=null;l&&(l.current=new AbortController);for await(const o of b.streamDebugAgent(t,l?.current?.signal||void 0))if(o.text){n=o.text,o.ext&&(a=o.ext);const p={id:e,role:"ai",content:JSON.stringify({text:n,ext:a||[]}),format:"markdown",name:"Assistant",finished:!1,debugGuide:!0};c?.(p)}c?.({id:e,role:"ai",content:JSON.stringify({text:n,ext:a||[]}),format:"markdown",name:"Assistant",finished:!0,debugGuide:!0}),u({type:"SET_LOADING",payload:!1}),l.current=null}catch(t){console.error("Error calling debug agent:",t),S(!1);const a={id:e,role:"ai",content:JSON.stringify({text:`I encountered an error while analyzing your workflow: ${t.message||"Unknown error"}`,ext:[]}),format:"markdown",name:"Assistant",finished:!0};c?.(a),u({type:"SET_LOADING",payload:!1}),l.current=null}};return r?s.jsx(D,{name:k,children:s.jsxs("div",{className:"bg-gray-100 pt-4 px-4 pb-3 rounded-lg",children:[s.jsx("div",{className:"flex justify-between items-start",children:s.jsx("p",{className:"text-gray-700 text-sm flex-1",children:r.text})}),s.jsx("div",{className:"flex justify-end mt-4",children:s.jsx("button",{onClick:C,disabled:d,className:`debug-btn bg-debug-btn text-sm text-[#fff] rounded-lg px-4 py-2 ${d?"cursor-not-allowed":"cursor-pointer"}`,children:d?"Analyzing...":"Debug Errors"})}),s.jsx("div",{className:"flex justify-end mt-2",children:!!h&&s.jsx("div",{className:"ml-2 flex-shrink-0",children:s.jsx(E,{checkpointId:h,onRestore:()=>{console.log("Workflow restored from checkpoint")}})})})]})}):null}export{M as DebugGuide};
import{j as s}from"./vendor-markdown-B4Av9P7l.js";import{r as i}from"./vendor-react-ByKzdfMq.js";import{u as A,n as D,R as E,m as x,a as m,W as b}from"./message-components-C9d8zznq.js";function P({content:f,name:k="Assistant",avatar:O,onAddMessage:y,onUpdateMessage:c,messageId:w}){const{dispatch:u,abortControllerRef:l}=A(),[d,_]=i.useState(!1),[T,G]=i.useState(""),[J,S]=i.useState(!1),[j,N]=i.useState(null),r=i.useMemo(()=>{try{return JSON.parse(f)}catch(e){return console.error("Failed to parse message content:",e),null}},[f]),h=i.useMemo(()=>{if(!r||!r.ext)return null;const e=r.ext.find(t=>t.type==="debug_start_checkpoint"||t.type==="debug_checkpoint"&&t.data?.checkpoint_type==="debug_start");return e&&e.data&&e.data.checkpoint_id?e.data.checkpoint_id:null},[r])||j,C=async()=>{if(d)return;const e=x(),t={id:e,role:"ai",content:JSON.stringify({text:`🔍 Starting workflow analysis...
`,ext:[]}),format:"markdown",name:"Assistant",finished:!1,debugGuide:!0};y?.(t);try{await v(),u({type:"SET_LOADING",payload:!0}),await I(e)}finally{_(!1)}},v=async()=>{try{const e=await m.graphToPrompt(),t=localStorage.getItem("sessionId")||"";if(t&&e){const n=await b.saveWorkflowCheckpoint(t,e.output,e.workflow,"debug_start");if(N(n.version_id),console.log(`Saved debug start checkpoint: ${n.version_id}`),c&&r){const o=[...r.ext||[]].filter(g=>g.type!=="debug_start_checkpoint"&&!(g.type==="debug_checkpoint"&&g.data?.checkpoint_type==="debug_start"));o.push({type:"debug_start_checkpoint",data:{checkpoint_id:n.version_id,checkpoint_type:"debug_start"}});const p={id:w||x(),role:"ai",content:JSON.stringify({text:r.text,ext:o}),format:"debug_guide",name:"Assistant"};c(p)}}}catch(e){console.error("Failed to save checkpoint before debug:",e)}},I=async e=>{try{const t=await m.graphToPrompt();let n="",a=null;l&&(l.current=new AbortController);for await(const o of b.streamDebugAgent(t,l?.current?.signal||void 0))if(o.text){n=o.text,o.ext&&(a=o.ext);const p={id:e,role:"ai",content:JSON.stringify({text:n,ext:a||[]}),format:"markdown",name:"Assistant",finished:!1,debugGuide:!0};c?.(p)}c?.({id:e,role:"ai",content:JSON.stringify({text:n,ext:a||[]}),format:"markdown",name:"Assistant",finished:!0,debugGuide:!0}),u({type:"SET_LOADING",payload:!1}),l.current=null}catch(t){console.error("Error calling debug agent:",t),S(!1);const a={id:e,role:"ai",content:JSON.stringify({text:`I encountered an error while analyzing your workflow: ${t.message||"Unknown error"}`,ext:[]}),format:"markdown",name:"Assistant",finished:!0};c?.(a),u({type:"SET_LOADING",payload:!1}),l.current=null}};return r?s.jsx(D,{name:k,children:s.jsxs("div",{className:"bg-gray-100 pt-4 px-4 pb-3 rounded-lg",children:[s.jsx("div",{className:"flex justify-between items-start",children:s.jsx("p",{className:"text-gray-700 text-sm flex-1",children:r.text})}),s.jsx("div",{className:"flex justify-end mt-4",children:s.jsx("button",{onClick:C,disabled:d,className:`debug-btn bg-debug-btn text-sm text-[#fff] rounded-lg px-4 py-2 ${d?"cursor-not-allowed":"cursor-pointer"}`,children:d?"Analyzing...":"Debug Errors"})}),s.jsx("div",{className:"flex justify-end mt-2",children:!!h&&s.jsx("div",{className:"ml-2 flex-shrink-0",children:s.jsx(E,{checkpointId:h,onRestore:()=>{console.log("Workflow restored from checkpoint")}})})})]})}):null}export{P as DebugGuide};
-4
View File
@@ -1,4 +0,0 @@
function getImportPath(filename) {
return `./${filename}`;
}
import{j as e}from"./vendor-markdown-_DNnI6VC.js";import{b as h,c as m,B as u,q as w,R as k}from"./message-components-DhOCYYxY.js";import{r as g}from"./vendor-react-BVt39aT-.js";import{B as j,M as v}from"./workflowChat-B3aUvb0D.js";import"./input.js";/* empty css */import"./App-BehZmgBV.js";const N=i=>{const{title:a="",isWorkflowUpdate:x=!1,className:n="",children:d}=i,[s,r]=g.useState(!1);return e.jsx(j,{className:"rounded-lg ",borderClassName:"rounded-lg",children:e.jsxs("div",{className:`flex flex-col ${n} ${s?"":"max-h-[200px]"}`,children:[e.jsxs("div",{className:"flex justify-between items-center pb-2 border-b border-gray-100",children:[e.jsx("div",{children:typeof a=="string"?e.jsx("h3",{className:"text-sm text-[#fff] font-medium",children:a}):a}),e.jsx("button",{onClick:()=>{r(!s)},children:s?e.jsx(h,{className:"text-gray-700"}):e.jsx(m,{className:"text-gray-700"})})]}),e.jsx("div",{className:"overflow-hidden flex-1",children:d})]})})};function z({content:i,name:a="Assistant",avatar:x,format:n="markdown"}){const d=()=>{let s=null,r=!1,o,c=[];try{if(o=JSON.parse(i),o.ext){let t=o.ext.find(l=>l.type==="workflow_rewrite_checkpoint"||l.type==="debug_checkpoint"&&l.data?.checkpoint_type==="workflow_rewrite_start");t&&t.data&&t.data.checkpoint_id?(s=t.data.checkpoint_id,r=!0):(t=o.ext.find(l=>l.type==="workflow_rewrite_complete"),t&&t.data&&t.data.version_id?(s=t.data.version_id,r=!0):(t=o.ext.find(l=>l.type==="debug_checkpoint"),t&&t.data&&t.data.checkpoint_id&&(s=t.data.checkpoint_id,r=!1))),o.ext.find(l=>l.type==="workflow_update")&&(r=!0),c=o.ext.find(l=>l.type==="param_update")?.data?.model_suggest||[]}}catch(t){return console.error("Failed to parse DebugResult content:",t),null}const p=r?e.jsxs("div",{className:"flex items-center text-green-500",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",clipRule:"evenodd"})}),e.jsx("h4",{className:"font-bold text-xl",children:"Workflow Updated Successfully"})]}):e.jsxs("div",{className:"flex items-center text-gray-900",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",viewBox:"0 0 1024 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"28108",fill:"currentColor",children:e.jsx("path",{d:"M401.048025 844.855924c0 20.341281 16.643052 36.984333 36.984333 36.984333l147.936307 0c20.341281 0 36.984333-16.643052 36.984333-36.984333L622.952998 807.872614 401.048025 807.872614 401.048025 844.855924zM512 142.159744c-142.943596 0-258.888282 115.944686-258.888282 258.888282 0 88.021729 44.011376 165.503405 110.951975 212.288964l0 83.58365c0 20.341281 16.643052 36.984333 36.984333 36.984333l221.903949 0c20.341281 0 36.984333-16.643052 36.984333-36.984333l0-83.58365c66.941622-46.784536 110.951975-124.266212 110.951975-212.288964C770.888282 258.104429 654.943596 142.159744 512 142.159744zM617.588827 552.682561l-31.621185 22.005176 0 85.248569L438.031335 659.936307l0-85.063351L406.41015 552.866756c-49.743938-34.764781-79.33079-91.350544-79.33079-151.634536 0-101.890598 83.029018-184.92064 184.92064-184.92064s184.92064 83.029018 184.92064 184.92064C696.919617 461.332017 667.332764 517.91778 617.588827 552.682561z","p-id":"28277"})}),e.jsx("h4",{className:"font-bold text-xl",children:"Workflow Updated Finished"})]}),f=r?e.jsx("div",{className:"mt-3 text-xs text-gray-700",children:"💡 If you're not satisfied with the changes, click the restore button to revert to the previous version."}):null;return e.jsxs("div",{className:"sticky top-0 left-0 w-full bg-gray-100 p-4 rounded-lg overflow-hidden",children:[e.jsx(N,{title:p,isWorkflowUpdate:r,className:"p-4",children:e.jsxs("div",{className:"prose prose-sm max-w-none",children:[n==="markdown"?e.jsx(w,{response:o||{}}):e.jsx("pre",{className:"whitespace-pre-wrap text-gray-700 text-sm leading-relaxed h-full",children:o?.text||""}),f]})}),c?.length>0&&e.jsx(v,{modelSuggests:c}),e.jsx("div",{className:"flex justify-end mt-2",children:!!s&&e.jsx("div",{className:"ml-2 flex-shrink-0",children:e.jsx(k,{checkpointId:s,onRestore:()=>{console.log(`Workflow restored from ${r?"workflow update":"debug"} checkpoint`)},title:r?`Restore to this version (Version ${s})`:`Restore checkpoint ${s}`})})})]})};return e.jsx(u,{name:a,children:d()})}export{z as DebugResult};
+4
View File
@@ -0,0 +1,4 @@
function getImportPath(filename) {
return `./${filename}`;
}
import{j as e}from"./vendor-markdown-B4Av9P7l.js";import{b as u,c as w,n as g,A as k,R as j}from"./message-components-C9d8zznq.js";import{r as p}from"./vendor-react-ByKzdfMq.js";import{B as v,M as N}from"./workflowChat-Hx0n46Jv.js";import"./input.js";/* empty css */import"./App-a_2xmaLY.js";const y=n=>{const{title:a="",isWorkflowUpdate:f=!1,className:d="",children:c}=n,[i,r]=p.useState(!1);return e.jsx(v,{className:"rounded-lg ",borderClassName:"rounded-lg",children:e.jsxs("div",{className:`flex flex-col ${d} ${i?"":"max-h-[200px]"}`,children:[e.jsxs("div",{className:"flex justify-between items-center pb-2 border-b border-gray-100",children:[e.jsx("div",{children:typeof a=="string"?e.jsx("h3",{className:"text-sm text-[#fff] font-medium",children:a}):a}),e.jsx("button",{onClick:()=>{r(!i)},children:i?e.jsx(u,{className:"text-gray-700"}):e.jsx(w,{className:"text-gray-700"})})]}),e.jsx("div",{className:"overflow-hidden flex-1",children:c})]})})};function E({content:n,name:a="Assistant",avatar:f,format:d="markdown"}){const c=p.useRef(null),i=()=>{let r=null,l=!1,o,x=[];try{if(o=JSON.parse(n),o.ext){let t=o.ext.find(s=>s.type==="workflow_rewrite_checkpoint"||s.type==="debug_checkpoint"&&s.data?.checkpoint_type==="workflow_rewrite_start");t&&t.data&&t.data.checkpoint_id?(r=t.data.checkpoint_id,l=!0):(t=o.ext.find(s=>s.type==="workflow_rewrite_complete"),t&&t.data&&t.data.version_id?(r=t.data.version_id,l=!0):(t=o.ext.find(s=>s.type==="debug_checkpoint"),t&&t.data&&t.data.checkpoint_id&&(r=t.data.checkpoint_id,l=!1))),o.ext.find(s=>s.type==="workflow_update")&&(l=!0),x=o.ext.find(s=>s.type==="param_update")?.data?.model_suggest||[]}}catch(t){return console.error("Failed to parse DebugResult content:",t),null}const h=l?e.jsxs("div",{className:"flex items-center text-green-500",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",clipRule:"evenodd"})}),e.jsx("h4",{className:"font-bold text-xl",children:"Workflow Updated Successfully"})]}):e.jsxs("div",{className:"flex items-center text-gray-900",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",viewBox:"0 0 1024 1024",version:"1.1",xmlns:"http://www.w3.org/2000/svg","p-id":"28108",fill:"currentColor",children:e.jsx("path",{d:"M401.048025 844.855924c0 20.341281 16.643052 36.984333 36.984333 36.984333l147.936307 0c20.341281 0 36.984333-16.643052 36.984333-36.984333L622.952998 807.872614 401.048025 807.872614 401.048025 844.855924zM512 142.159744c-142.943596 0-258.888282 115.944686-258.888282 258.888282 0 88.021729 44.011376 165.503405 110.951975 212.288964l0 83.58365c0 20.341281 16.643052 36.984333 36.984333 36.984333l221.903949 0c20.341281 0 36.984333-16.643052 36.984333-36.984333l0-83.58365c66.941622-46.784536 110.951975-124.266212 110.951975-212.288964C770.888282 258.104429 654.943596 142.159744 512 142.159744zM617.588827 552.682561l-31.621185 22.005176 0 85.248569L438.031335 659.936307l0-85.063351L406.41015 552.866756c-49.743938-34.764781-79.33079-91.350544-79.33079-151.634536 0-101.890598 83.029018-184.92064 184.92064-184.92064s184.92064 83.029018 184.92064 184.92064C696.919617 461.332017 667.332764 517.91778 617.588827 552.682561z","p-id":"28277"})}),e.jsx("h4",{className:"font-bold text-xl",children:"Workflow Updated Finished"})]}),m=l?e.jsx("div",{className:"mt-3 text-xs text-gray-700",children:"💡 If you're not satisfied with the changes, click the restore button to revert to the previous version."}):null;return e.jsxs("div",{ref:c,className:"sticky top-0 left-0 w-full bg-gray-100 p-4 rounded-lg overflow-hidden",children:[e.jsx(y,{title:h,isWorkflowUpdate:l,className:"p-4",children:e.jsxs("div",{className:"prose prose-sm max-w-none",children:[d==="markdown"?e.jsx(k,{response:o||{}}):e.jsx("pre",{className:"whitespace-pre-wrap text-gray-700 text-sm leading-relaxed h-full",children:o?.text||""}),m]})}),x?.length>0&&e.jsx(N,{modelSuggests:x,showPagination:!1}),e.jsx("div",{className:"flex justify-end mt-2",children:!!r&&e.jsx("div",{className:"ml-2 flex-shrink-0",children:e.jsx(j,{checkpointId:r,onRestore:()=>{console.log(`Workflow restored from ${l?"workflow update":"debug"} checkpoint`)},title:l?`Restore to this version (Version ${r})`:`Restore checkpoint ${r}`})})})]})};return e.jsx(g,{name:a,children:i()})}export{E as DebugResult};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
function getImportPath(filename) {
return `./${filename}`;
}
import{c as Wr,g as Wa}from"./vendor-react-BVt39aT-.js";var Ya={exports:{}},rn={};/**
import{c as Wr,g as Wa}from"./vendor-react-ByKzdfMq.js";var Ya={exports:{}},rn={};/**
* @license React
* react-jsx-runtime.production.js
*
@@ -17,4 +17,4 @@ function getImportPath(filename) {
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var se=A;function x(e){var t="https://react.dev/errors/"+e;if(1<arguments.length){t+="?args[]="+encodeURIComponent(arguments[1]);for(var r=2;r<arguments.length;r++)t+="&args[]="+encodeURIComponent(arguments[r])}return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function _(){}var a={d:{f:_,r:function(){throw Error(x(522))},D:_,C:_,L:_,m:_,X:_,S:_,M:_},p:0,findDOMNode:null},fe=Symbol.for("react.portal");function ce(e,t,r){var n=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:fe,key:n==null?null:""+n,children:e,containerInfo:t,implementation:r}}var g=se.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function E(e,t){if(e==="font")return"";if(typeof t=="string")return t==="use-credentials"?t:""}l.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a;l.createPortal=function(e,t){var r=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)throw Error(x(299));return ce(e,t,null,r)};l.flushSync=function(e){var t=g.T,r=a.p;try{if(g.T=null,a.p=2,e)return e()}finally{g.T=t,a.p=r,a.d.f()}};l.preconnect=function(e,t){typeof e=="string"&&(t?(t=t.crossOrigin,t=typeof t=="string"?t==="use-credentials"?t:"":void 0):t=null,a.d.C(e,t))};l.prefetchDNS=function(e){typeof e=="string"&&a.d.D(e)};l.preinit=function(e,t){if(typeof e=="string"&&t&&typeof t.as=="string"){var r=t.as,n=E(r,t.crossOrigin),o=typeof t.integrity=="string"?t.integrity:void 0,s=typeof t.fetchPriority=="string"?t.fetchPriority:void 0;r==="style"?a.d.S(e,typeof t.precedence=="string"?t.precedence:void 0,{crossOrigin:n,integrity:o,fetchPriority:s}):r==="script"&&a.d.X(e,{crossOrigin:n,integrity:o,fetchPriority:s,nonce:typeof t.nonce=="string"?t.nonce:void 0})}};l.preinitModule=function(e,t){if(typeof e=="string")if(typeof t=="object"&&t!==null){if(t.as==null||t.as==="script"){var r=E(t.as,t.crossOrigin);a.d.M(e,{crossOrigin:r,integrity:typeof t.integrity=="string"?t.integrity:void 0,nonce:typeof t.nonce=="string"?t.nonce:void 0})}}else t==null&&a.d.M(e)};l.preload=function(e,t){if(typeof e=="string"&&typeof t=="object"&&t!==null&&typeof t.as=="string"){var r=t.as,n=E(r,t.crossOrigin);a.d.L(e,r,{crossOrigin:n,integrity:typeof t.integrity=="string"?t.integrity:void 0,nonce:typeof t.nonce=="string"?t.nonce:void 0,type:typeof t.type=="string"?t.type:void 0,fetchPriority:typeof t.fetchPriority=="string"?t.fetchPriority:void 0,referrerPolicy:typeof t.referrerPolicy=="string"?t.referrerPolicy:void 0,imageSrcSet:typeof t.imageSrcSet=="string"?t.imageSrcSet:void 0,imageSizes:typeof t.imageSizes=="string"?t.imageSizes:void 0,media:typeof t.media=="string"?t.media:void 0})}};l.preloadModule=function(e,t){if(typeof e=="string")if(t){var r=E(t.as,t.crossOrigin);a.d.m(e,{as:typeof t.as=="string"&&t.as!=="script"?t.as:void 0,crossOrigin:r,integrity:typeof t.integrity=="string"?t.integrity:void 0})}else a.d.m(e)};l.requestFormReset=function(e){a.d.r(e)};l.unstable_batchedUpdates=function(e,t){return e(t)};l.useFormState=function(e,t,r){return g.H.useFormState(e,t,r)};l.useFormStatus=function(){return g.H.useHostTransitionStatus()};l.version="19.1.0";function G(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(G)}catch(e){console.error(e)}}G(),Y.exports=l;var z=Y.exports;const ae=H(z),_e=D({__proto__:null,default:ae},[z]);export{ie as R,z as a,ae as b,le as c,ye as d,_e as e,H as g,A as r};
*/var se=A;function x(e){var t="https://react.dev/errors/"+e;if(1<arguments.length){t+="?args[]="+encodeURIComponent(arguments[1]);for(var r=2;r<arguments.length;r++)t+="&args[]="+encodeURIComponent(arguments[r])}return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function _(){}var a={d:{f:_,r:function(){throw Error(x(522))},D:_,C:_,L:_,m:_,X:_,S:_,M:_},p:0,findDOMNode:null},fe=Symbol.for("react.portal");function ce(e,t,r){var n=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:fe,key:n==null?null:""+n,children:e,containerInfo:t,implementation:r}}var g=se.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function E(e,t){if(e==="font")return"";if(typeof t=="string")return t==="use-credentials"?t:""}l.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a;l.createPortal=function(e,t){var r=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)throw Error(x(299));return ce(e,t,null,r)};l.flushSync=function(e){var t=g.T,r=a.p;try{if(g.T=null,a.p=2,e)return e()}finally{g.T=t,a.p=r,a.d.f()}};l.preconnect=function(e,t){typeof e=="string"&&(t?(t=t.crossOrigin,t=typeof t=="string"?t==="use-credentials"?t:"":void 0):t=null,a.d.C(e,t))};l.prefetchDNS=function(e){typeof e=="string"&&a.d.D(e)};l.preinit=function(e,t){if(typeof e=="string"&&t&&typeof t.as=="string"){var r=t.as,n=E(r,t.crossOrigin),o=typeof t.integrity=="string"?t.integrity:void 0,s=typeof t.fetchPriority=="string"?t.fetchPriority:void 0;r==="style"?a.d.S(e,typeof t.precedence=="string"?t.precedence:void 0,{crossOrigin:n,integrity:o,fetchPriority:s}):r==="script"&&a.d.X(e,{crossOrigin:n,integrity:o,fetchPriority:s,nonce:typeof t.nonce=="string"?t.nonce:void 0})}};l.preinitModule=function(e,t){if(typeof e=="string")if(typeof t=="object"&&t!==null){if(t.as==null||t.as==="script"){var r=E(t.as,t.crossOrigin);a.d.M(e,{crossOrigin:r,integrity:typeof t.integrity=="string"?t.integrity:void 0,nonce:typeof t.nonce=="string"?t.nonce:void 0})}}else t==null&&a.d.M(e)};l.preload=function(e,t){if(typeof e=="string"&&typeof t=="object"&&t!==null&&typeof t.as=="string"){var r=t.as,n=E(r,t.crossOrigin);a.d.L(e,r,{crossOrigin:n,integrity:typeof t.integrity=="string"?t.integrity:void 0,nonce:typeof t.nonce=="string"?t.nonce:void 0,type:typeof t.type=="string"?t.type:void 0,fetchPriority:typeof t.fetchPriority=="string"?t.fetchPriority:void 0,referrerPolicy:typeof t.referrerPolicy=="string"?t.referrerPolicy:void 0,imageSrcSet:typeof t.imageSrcSet=="string"?t.imageSrcSet:void 0,imageSizes:typeof t.imageSizes=="string"?t.imageSizes:void 0,media:typeof t.media=="string"?t.media:void 0})}};l.preloadModule=function(e,t){if(typeof e=="string")if(t){var r=E(t.as,t.crossOrigin);a.d.m(e,{as:typeof t.as=="string"&&t.as!=="script"?t.as:void 0,crossOrigin:r,integrity:typeof t.integrity=="string"?t.integrity:void 0})}else a.d.m(e)};l.requestFormReset=function(e){a.d.r(e)};l.unstable_batchedUpdates=function(e,t){return e(t)};l.useFormState=function(e,t,r){return g.H.useFormState(e,t,r)};l.useFormStatus=function(){return g.H.useHostTransitionStatus()};l.version="19.1.0";function G(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(G)}catch(e){console.error(e)}}G(),Y.exports=l;var z=Y.exports;const ae=H(z),_e=D({__proto__:null,default:ae},[z]);export{ie as R,ae as a,ye as b,le as c,_e as d,z as e,H as g,A as r};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -276,7 +276,6 @@ export function ApiKeyModal({ isOpen, onClose, onSave, initialApiKey = '', onCon
<CollapsibleCard
title={<h3 className="text-sm text-gray-900 dark:text-white font-medium">LLM Configuration (OpenAI / LMStudio / Custom)</h3>}
className='mb-4'
defaultExpanded={true}
>
<div>
{/* API Key */}
+4 -19
View File
@@ -3,7 +3,6 @@ import { XIcon } from "./Icons";
import { Input } from 'antd';
import { debounce } from "lodash";
import ModelOption from "./messages/ModelOption";
import LoadingIcon from "../ui/LoadingIcon";
import type { InputRef } from 'antd';
interface IProps {
@@ -16,15 +15,15 @@ const ModelDownloadModal: React.FC<IProps> = (props) => {
const [loading, setLoading] = useState<boolean>(false)
const [modelSuggests, setModelSuggests] = useState<any[]>([])
const ref = useRef<InputRef>(null)
useEffect(() => {
ref?.current?.focus()
}, [modelSuggests])
const getModelSuggests = async (value: string) => {
const getModelSuggests = async (keyword: string) => {
setLoading(true)
try {
const response = await fetch(`/api/model-suggests?keyword=${value}`)
const response = await fetch(`/api/model-suggests?keyword=${keyword}`)
const data = await response.json()
setModelSuggests(data?.data?.suggests || [])
} catch (e) {
@@ -66,21 +65,7 @@ const ModelDownloadModal: React.FC<IProps> = (props) => {
className="search-input w-1/4 bg-white text-[#888] placeholder-gray-500 border border-gray-300"
/>
</div>
<div className="flex justify-center w-full">
{
loading ? <LoadingIcon className="mt-8 w-8 h-8 text-gray-700"/> : (
modelSuggests?.length > 0 ? <ModelOption modelSuggests={modelSuggests} showTitle={false} /> : <div
className="text-xl text-gray-700 flex flex-col items-center"
>
<svg className="w-20 h-20" viewBox="0 0 1557 1024" fill="currentColor">
<path d="M156.183 690.571h20.806c5.61 0.103 10.116 4.69 10.096 10.3a10.157 10.157 0 0 1-10.096 10.302h-20.786v20.826a10.3 10.3 0 0 1-10.321 10.096 10.137 10.137 0 0 1-10.3-10.096v-20.826h-20.827a10.3 10.3 0 0 1-10.116-10.301c0-5.693 4.443-10.3 10.116-10.3h20.806v-20.848a10.3 10.3 0 0 1 10.3-10.095c5.694 0 10.322 4.423 10.322 10.095v20.827z m1360.336-82.446V587.3a10.137 10.137 0 0 0-10.3-10.096 10.3 10.3 0 0 0-10.301 10.096v20.826h-20.826a10.137 10.137 0 0 0-10.096 10.301c0 5.53 4.546 10.3 10.096 10.3h20.826v20.827c0 5.652 4.608 10.096 10.3 10.096 5.612 0 10.199-4.505 10.301-10.096v-20.826h20.827a10.157 10.157 0 0 0 10.096-10.301 10.3 10.3 0 0 0-10.096-10.3h-20.827zM767.75 948.21H248.867a20.52 20.52 0 0 1-20.56-20.622 20.683 20.683 0 0 1 20.56-20.601h93.463a81.913 81.913 0 0 1-10.956-41.12v-597.95a82.384 82.384 0 0 1 82.528-82.323h61.742V164.85a82.384 82.384 0 0 1 82.528-82.344h494.511a82.343 82.343 0 0 1 82.528 82.323v597.968c0 14.97-3.993 29.018-10.976 41.1h114.023c11.386 0 20.622 9.154 20.622 20.622 0 11.366-9.174 20.602-20.601 20.602H990.942v20.724c0 14.99-3.993 29.017-10.997 41.12h11.059c11.324 0 20.54 9.154 20.54 20.601a20.683 20.683 0 0 1-20.54 20.622H882.57c9.42 15.768 7.372 36.472-6.349 50.172a41.12 41.12 0 0 1-58.281 0l-50.172-50.172z m75.36-41.223h65.53a41.1 41.1 0 0 0 41.08-41.326V266.956c0-22.26-17.816-40.138-39.79-40.138H412.388a39.974 39.974 0 0 0-39.769 40.138V865.66c0 22.813 18.554 41.326 41.04 41.326h312.868l-10.588-10.629a41.141 41.141 0 0 1-10.71-39.83l-19.454-19.475A144.311 144.311 0 0 1 497.31 619.45a144.27 144.27 0 0 1 217.603 188.462l19.455 19.455a41.08 41.08 0 0 1 39.85 10.71l68.91 68.91z m147.833-103.068h62.009a41.243 41.243 0 0 0 41.038-41.223V164.974a41.1 41.1 0 0 0-41.038-41.223H557.886a41.243 41.243 0 0 0-41.018 41.223v20.6h391.546a82.343 82.343 0 0 1 82.528 82.344V803.92zM264.37 46.465h30.717c8.663 0 15.666 6.86 15.666 15.441a15.564 15.564 0 0 1-15.645 15.461H264.39v30.718a15.523 15.523 0 0 1-15.46 15.666 15.564 15.564 0 0 1-15.462-15.666V77.367H202.75a15.523 15.523 0 0 1-15.665-15.46 15.564 15.564 0 0 1 15.665-15.442h30.718V15.748c0-8.662 6.86-15.666 15.461-15.666a15.564 15.564 0 0 1 15.461 15.666v30.717zM22.213 927.588a20.683 20.683 0 0 1 20.56-20.601h123.792c11.345 0 20.54 9.153 20.54 20.6a20.683 20.683 0 0 1-20.56 20.643H42.753a20.52 20.52 0 0 1-20.56-20.622z m650.004-133.232A103.068 103.068 0 1 0 526.452 648.59a103.068 103.068 0 0 0 145.765 145.765zM455.044 309.244c0-11.366 9.215-20.601 20.58-20.601h226.758a20.601 20.601 0 0 1 0 41.222H475.645a20.54 20.54 0 0 1-20.601-20.621z m0 103.067c0-11.386 9.174-20.621 20.478-20.621h330.05a20.478 20.478 0 0 1 20.478 20.621c0 11.386-9.174 20.602-20.478 20.602h-330.07a20.478 20.478 0 0 1-20.479-20.602z m0 103.047c0-11.365 9.195-20.6 20.56-20.6h144.373c11.345 0 20.56 9.153 20.56 20.6 0 11.386-9.195 20.622-20.56 20.622H475.604a20.52 20.52 0 0 1-20.56-20.622zM63.416 391.69a61.845 61.845 0 1 1 0-123.67 61.845 61.845 0 0 1 0 123.69z m0-30.923a30.922 30.922 0 1 0 0.02-61.824 30.922 30.922 0 0 0 0 61.845z m1277.91-92.746a61.845 61.845 0 1 1 0-123.669 61.845 61.845 0 0 1 0 123.69z m0-30.923a30.922 30.922 0 1 0 0-61.824 30.922 30.922 0 0 0 0 61.845z">
</path>
</svg>
Empty
</div>
)
}
</div>
<ModelOption modelSuggests={modelSuggests} loading={loading} showTitle={false} />
</div>
</div>
}
+2 -2
View File
@@ -1,7 +1,7 @@
// Copyright (C) 2025 AIDC-AI
// Licensed under the MIT License.
import React, { ReactNode, useEffect, useState } from 'react';
import { ReactNode, useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
interface PortalProps {
@@ -11,7 +11,7 @@ interface PortalProps {
export function Portal({ children, container = document.body }: PortalProps) {
const [mounted, setMounted] = useState(false);
console.log('container-->', container)
useEffect(() => {
setMounted(true);
return () => setMounted(false);
+98 -122
View File
@@ -1,11 +1,11 @@
import { useEffect, useRef, useState } from "react";
import { createRewriteExpert, deleteRewriteExpert, getRewriteExpertsList, updateRewriteExpert } from "../../apis/rewriteExpertApi";
import { Button, ConfigProvider, Form, Space, Table, type TableProps } from 'antd';
import { Button, Form, Space, Table, type TableProps } from 'antd';
import { Input } from 'antd';
import { XIcon, TrashIcon, CirclePlusIcon, FilePenLineIcon } from "./Icons";
import { debounce } from "lodash";
import Modal from '../ui/Modal';
import { app } from "../../utils/comfyapp";
import TableEmpty from "../ui/TableEmpty";
const { TextArea } = Input
@@ -30,7 +30,6 @@ const RewriteExpertModal: React.FC<IProps> = ({onClose}) => {
const [modalContent, setModalContent] = useState<string | null>(null)
const [editData, setEditData] = useState<DataType | null>(null)
const isAdd = useRef<boolean>(false)
const isDark = app.extensionManager.setting.get('Comfy.ColorPalette') === 'dark';
const onEdit = (item: DataType) => {
setEditData(item)
@@ -167,126 +166,103 @@ const RewriteExpertModal: React.FC<IProps> = ({onClose}) => {
backgroundColor: 'rgba(0,0,0,0.5)'
}}
>
<ConfigProvider
theme={{
components: {
Table: {
borderColor: isDark ? '#666' : '#f0f0f0',
headerBg: isDark ? '#333' : '#fafafa',
headerColor: isDark ? '#fff' : '#fafafa',
rowHoverBg: isDark ? '#333' : '#fafafa',
},
Pagination: {
itemBg: isDark ? 'rgb(24, 24, 27)' : '#fff',
itemActiveBg: isDark ? 'rgb(24, 24, 27)' : '#fff',
colorText: isDark ? 'rgba(255,255,255,0.88)' : 'rgba(0,0,0,0.88)',
colorBgTextHover: isDark ? '#555' : 'rgba(0,0,0,0.06)',
colorPrimary: isDark ? '#aaa' : '#1677ff',
colorPrimaryHover: isDark ? '#999' : '#4096ff',
},
Form: {
labelColor: isDark ? 'rgba(255,255,255,0.88)' : 'rgba(0,0,0,0.88)'
}
}
}}
>
<div className="relative bg-white rounded-xl p-6 w-1/2 h-2/3 flex flex-col">
<div className="flex justify-between items-center mb-6">
<h2 className="text-xl text-gray-900 dark:text-white font-semibold">Set expert experience to help you rewrite workflow</h2>
<button
onClick={onClose}
disabled={loading}
className="bg-white border-none text-gray-500 hover:!text-gray-700"
>
<XIcon className="w-5 h-5" />
</button>
</div>
<div className="flex justify-between mb-2">
<Input
placeholder="Enter search name"
allowClear
value={searchValue}
disabled={loading}
onChange={debounce(handleSearchRewriteExpert, 500)}
className="search-input w-1/4 bg-white text-[#888] placeholder-gray-500 border border-gray-300"
/>
<button
onClick={handleAddRewriteExpert}
className="bg-white border-none text-gray-500 hover:!text-gray-700"
>
<CirclePlusIcon className="w-5 h-5" />
</button>
</div>
<div className="flex-1 min-h-0 overflow-y-auto">
<Table
bordered
loading={loading}
columns={columns}
dataSource={currentDataList}
rowClassName={"bg-white text-gray-800"}
/>
</div>
{
editData && <div className="absolute top-0 left-0 w-full h-full bg-white rounded-xl p-6 z-5 overflow-y-auto">
<h2 className="text-xl text-gray-900 dark:text-white font-semibold">{`${editData?.name && editData?.name !== '' ? 'Edit' : 'Add'} Rewrite Expert`}</h2>
<Form
onFinish={onFinish}
initialValues={editData}
layout="vertical"
>
<Form.Item
name="id"
label="Id"
hidden
>
<Input
disabled
/>
</Form.Item>
<Form.Item
name="name"
label="Name"
rules={[{ required: true }]}
>
<Input
placeholder="Enter name"
/>
</Form.Item>
<Form.Item
name="description"
label="Description"
rules={[{ required: true }]}
>
<TextArea
placeholder="Enter description"
autoSize={{ maxRows: 6 }}
/>
</Form.Item>
<Form.Item
name="content"
label="Content"
rules={[{ required: true }]}
>
<TextArea
placeholder="Enter content"
autoSize={{ maxRows: 10 }}
/>
</Form.Item>
<Form.Item>
<Space align='end' size='middle'>
<Button type="primary" htmlType="submit">
Submit
</Button>
<Button onClick={onCancel}>
Cancel
</Button>
</Space>
</Form.Item>
</Form>
</div>
}
<div className="relative bg-white rounded-xl p-6 w-1/2 h-2/3 flex flex-col">
<div className="flex justify-between items-center mb-6">
<h2 className="text-xl text-gray-900 dark:text-white font-semibold">Set expert experience to help you rewrite workflow</h2>
<button
onClick={onClose}
disabled={loading}
className="bg-white border-none text-gray-500 hover:!text-gray-700"
>
<XIcon className="w-5 h-5" />
</button>
</div>
</ConfigProvider>
<div className="flex justify-between mb-2">
<Input
placeholder="Enter search name"
allowClear
value={searchValue}
disabled={loading}
onChange={debounce(handleSearchRewriteExpert, 500)}
className="search-input w-1/4 bg-white text-[#888] placeholder-gray-500 border border-gray-300"
/>
<button
onClick={handleAddRewriteExpert}
className="bg-white border-none text-gray-500 hover:!text-gray-700"
>
<CirclePlusIcon className="w-5 h-5" />
</button>
</div>
<div className="flex-1 min-h-0 overflow-y-auto">
<Table
bordered
loading={loading}
columns={columns}
dataSource={currentDataList}
rowClassName={"text-gray-800"}
locale={{ emptyText: <TableEmpty /> }}
/>
</div>
{
editData && <div className="absolute top-0 left-0 w-full h-full bg-white rounded-xl p-6 z-5 overflow-y-auto">
<h2 className="text-xl text-gray-900 dark:text-white font-semibold">{`${editData?.name && editData?.name !== '' ? 'Edit' : 'Add'} Rewrite Expert`}</h2>
<Form
onFinish={onFinish}
initialValues={editData}
layout="vertical"
>
<Form.Item
name="id"
label="Id"
hidden
>
<Input
disabled
/>
</Form.Item>
<Form.Item
name="name"
label="Name"
rules={[{ required: true }]}
>
<Input
placeholder="Enter name"
/>
</Form.Item>
<Form.Item
name="description"
label="Description"
rules={[{ required: true }]}
>
<TextArea
placeholder="Enter description"
autoSize={{ maxRows: 6 }}
/>
</Form.Item>
<Form.Item
name="content"
label="Content"
rules={[{ required: true }]}
>
<TextArea
placeholder="Enter content"
autoSize={{ maxRows: 10 }}
/>
</Form.Item>
<Form.Item>
<Space align='end' size='middle'>
<Button type="primary" htmlType="submit">
Submit
</Button>
<Button onClick={onCancel}>
Cancel
</Button>
</Space>
</Form.Item>
</Form>
</div>
}
</div>
<Modal open={!!modalContent && modalContent !== ''} onClose={() => setModalContent(null)}>
<p>{modalContent}</p>
</Modal>
@@ -3,6 +3,8 @@ import RestoreCheckpoint from '../../ui/RestoreCheckpoint';
import DebugCollapsibleCard from '../../ui/DebugCollapsibleCard';
import Markdown from '../../ui/Markdown';
import ModelOption from './ModelOption';
import { Portal } from '../Portal';
import { useRef } from 'react';
interface DebugResultProps {
content: string;
@@ -12,17 +14,7 @@ interface DebugResultProps {
}
export function DebugResult({ content, name = 'Assistant', avatar, format = 'markdown' }: DebugResultProps) {
const formatContent = (text: string) => {
if (format === 'markdown') {
// Simple markdown rendering for basic formatting
return text
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/`(.*?)`/g, '<code class="bg-gray-100 px-1 rounded">$1</code>')
.replace(/\n/g, '<br/>');
}
return text;
};
const ref = useRef<HTMLDivElement>(null)
const renderContent = () => {
let checkPointId = null
@@ -109,7 +101,7 @@ export function DebugResult({ content, name = 'Assistant', avatar, format = 'mar
</div>
) : null
return <div className="sticky top-0 left-0 w-full bg-gray-100 p-4 rounded-lg overflow-hidden">
return <div ref={ref} className="sticky top-0 left-0 w-full bg-gray-100 p-4 rounded-lg overflow-hidden">
<DebugCollapsibleCard
title={title}
isWorkflowUpdate={isWorkflowUpdate}
@@ -131,7 +123,7 @@ export function DebugResult({ content, name = 'Assistant', avatar, format = 'mar
</DebugCollapsibleCard>
{
modelSuggests?.length > 0 && (
<ModelOption modelSuggests={modelSuggests} />
<ModelOption modelSuggests={modelSuggests} showPagination={false} />
)
}
<div className="flex justify-end mt-2">
+86 -61
View File
@@ -3,32 +3,49 @@ import { app } from "../../../utils/comfyapp";
import Modal from "../../ui/Modal";
import { useChatContext } from "../../../context/ChatContext";
import LoadingIcon from "../../ui/LoadingIcon";
import { Table, type TableProps } from 'antd';
import TableEmpty from "../../ui/TableEmpty";
interface IProps {
modelSuggests: any[]
loading?: boolean
showTitle?: boolean
showPagination?: boolean
}
type ColumnsType<T extends object> = TableProps<T>['columns'];
type DataType = {
Id: number
Name: string
Path: string
ChineseName?: string
source_model_type?: string
source_missing_model?: string
source_keyword?: string
model_type?: string
}
const TITLE_ZH = '发现模型缺失,推荐下载以下模型。'
const TITLE_EN = 'Missing models detected. We recommend downloading the following models.'
const TH_ZH = {
name: '名称',
name: '模型ID',
dir: '模型下载存放目录',
option: '操作'
action: '操作'
}
const TH_EN = {
name: 'Name',
name: 'Model ID',
dir: 'Models download directory',
option: 'Option'
action: 'Action'
}
const ModelOption: React.FC<IProps> = (props) => {
const { modelSuggests, showTitle = true } = props
const { modelSuggests, loading = false, showTitle = true, showPagination = true } = props
const { modelDownloadMap, addDownloadId } = useChatContext()
const browserLanguage = app.extensionManager.setting.get('Comfy.Locale');
const [modelPaths, setModelPaths] = useState<string[] | null>(null)
const [selectedPathMap, setSelectedPathMap] = useState<Record<string, string>>({})
const [selectedPathMap, setSelectedPathMap] = useState<Record<number, string>>({})
const [modalContent, setModalContent] = useState<string | null>(null)
const thMap = browserLanguage === 'zh' ? TH_ZH : TH_EN
@@ -36,7 +53,7 @@ const ModelOption: React.FC<IProps> = (props) => {
const response = await fetch('/api/model-paths')
const res = await response.json()
setModelPaths(res?.data?.paths || [])
let selectedPaths: Record<string, string> = {}
let selectedPaths: Record<number, string> = {}
modelSuggests?.forEach(item => {
const index = res?.data?.paths?.findIndex((path: string) => item.model_type === path)
selectedPaths[item.Id] = res?.data?.paths?.[index === -1 ? 0 : index] || ''
@@ -48,8 +65,8 @@ const ModelOption: React.FC<IProps> = (props) => {
getModelPaths()
}, [])
const handleDownload = async (id: string, modelId: string, modelType: string) => {
let body: Record<string, string> = {
const handleDownload = async (id: number, modelId: string, modelType: string) => {
let body: Record<string, string | number> = {
id,
model_id: modelId,
model_type: !!modelType && modelType !== '' ? modelType : selectedPathMap[id],
@@ -72,7 +89,7 @@ const ModelOption: React.FC<IProps> = (props) => {
}
}
const handleSelectedPath = (id: string, path: string) => {
const handleSelectedPath = (id: number, path: string) => {
setSelectedPathMap(prev => ({
...prev,
[id]: path
@@ -94,64 +111,72 @@ const ModelOption: React.FC<IProps> = (props) => {
}
}
const columns: ColumnsType<DataType> = [
{
title: thMap.name,
key: 'modelId',
render: (_, record) => (
<div>{`${record.Path}/${record.Name}`}</div>
)
},
{
title: thMap.dir,
key: 'directory',
render: (_, record) => (
<select
value={selectedPathMap[record.Id]}
onChange={(e) => handleSelectedPath(record.Id, e.target.value)}
className="px-1.5 py-0.5 text-xs rounded-md bg-gray-100
text-gray-700 focus:outline-none focus:ring-2
focus:ring-blue-500 hover:!bg-gray-50"
>
{modelPaths?.map((path: string) => (
<option value={path} key={path}>{path}</option>
))}
</select>
)
},
{
title: thMap.action,
key: 'action',
render: (_, record) => (
<div className="w-full h-full flex justify-center items-center">
{
(!!modelDownloadMap[record.Id] && modelDownloadMap[record.Id].status !== 'failed') ? renderDownloadProgress(modelDownloadMap[record.Id]?.status) : <button
className="text-gray-900 hover:!text-blue-500 disabled:!text-gray-300 flex justify-center items-center bg-transparent border-none"
disabled={!!modelDownloadMap[record.Id]}
onClick={() => handleDownload(record.Id, `${record.Path}/${record.Name}`, record?.model_type || '')}
>
<svg viewBox="0 0 1071 1024" className="w-5 h-5" fill="currentColor">
<path d="M820.376748 284.430361v228.885113a20.509419 20.509419 0 0 0 41.018838 0V249.974538a19.689042 19.689042 0 0 0-2.871319-9.434333v-2.050942a21.739984 21.739984 0 0 0-5.332449-5.332448L423.314402 2.630948a20.509419 20.509419 0 0 0-20.09923 0L10.254709 232.336438a13.946405 13.946405 0 0 0-4.92226 4.92226v2.461131a16.407535 16.407535 0 0 0-5.332449 10.254709v533.244886a8.203767 8.203767 0 0 0 2.46113 2.871319l2.871319 2.871319 392.960462 229.295301a20.09923 20.09923 0 0 0 20.099231 0l196.890419-100.085964a20.919607 20.919607 0 0 0 8.203768-27.892809 20.509419 20.509419 0 0 0-27.89281-8.613956l-164.075349 87.780312v-243.651894l189.917217-102.136905a20.509419 20.509419 0 0 0 11.075086-18.048289V383.695948zM41.018837 287.30168l184.17458 105.8286V615.452379l2.461131 3.281507a11.075086 11.075086 0 0 0 3.281507 2.871319l157.512335 91.882196v252.676038L41.018837 762.710006z m351.941625 210.016448v172.279117l-126.748207-75.88485v-176.381L394.191028 492.395867a22.150172 22.150172 0 0 0-1.230566 3.281507z m20.919608-41.018838l-137.413106-82.037675 146.43725-85.72937L574.263724 369.339355z m0-410.188374l382.295564 205.094187L615.282561 347.189183l-182.944015-98.855399a20.509419 20.509419 0 0 0-20.09923 0L235.448127 351.701255 61.118068 249.974538z m180.072696 549.242233l-159.973466 86.139559v-185.815334-3.691695l160.383654-86.139559zM1066.489773 841.876362a20.509419 20.509419 0 0 0-29.123375 0l-98.035021 95.984079v-229.295301a20.509419 20.509419 0 0 0-41.018837 0v229.295301l-95.98408-95.984079a20.509419 20.509419 0 0 0-29.123375 0 20.509419 20.509419 0 0 0 0 28.713186l131.26028 131.26028a20.919607 20.919607 0 0 0 28.713186 0l131.26028-131.26028a20.509419 20.509419 0 0 0 2.050942-28.713186z">
</path>
</svg>
</button>
}
</div>
)
},
];
if (!modelPaths)
return null
return <div className="mt-4 w-full">
return <div className="mt-4 w-full h-auto flex-1 min-h-0 overflow-y-auto">
{
showTitle && <h3 className="text-xl text-gray-900 font-bold">
{browserLanguage === 'zh' ? TITLE_ZH : TITLE_EN}
</h3>
}
<table className="w-full border-gray-300">
<thead>
<tr>
<th className="px-4 py-1 border border-gray-300">{thMap.name}</th>
<th className="px-4 py-1 border border-gray-300">{thMap.dir}</th>
<th className="px-4 py-1 border border-gray-300">{thMap.option}</th>
</tr>
</thead>
<tbody>
{
modelSuggests.map((item, index) => (
<tr key={index}>
<td className="px-4 py-1 border border-gray-300 text-center">{item.Name}</td>
<td className="px-4 py-1 border border-gray-300 text-center">
<select
value={selectedPathMap[item.Id]}
onChange={(e) => handleSelectedPath(item.Id, e.target.value)}
className="px-1.5 py-0.5 text-xs rounded-md bg-gray-100
text-gray-700 focus:outline-none focus:ring-2
focus:ring-blue-500 hover:!bg-gray-50"
>
{modelPaths.map((path) => (
<option value={path} key={path}>{path}</option>
))}
</select>
</td>
<td className="px-4 py-1 border border-gray-300 text-center">
<div className="w-full h-full flex justify-center items-center">
{
(!!modelDownloadMap[item.Id] && modelDownloadMap[item.Id].status !== 'failed') ? renderDownloadProgress(modelDownloadMap[item.Id]?.status) : <button
className="text-gray-900 hover:!text-blue-500 disabled:!text-gray-300 flex justify-center items-center"
disabled={!!modelDownloadMap[item.Id]}
onClick={() => handleDownload(item.Id, `${item.Path}/${item.Name}`, item?.model_type || '')}
>
<svg viewBox="0 0 1024 1024" className="w-5 h-5" fill='currentColor'>
<path d="M1022.955204 522.570753c0 100.19191-81.516572 181.698249-181.718715 181.698249l-185.637977 0c-11.2973 0-20.466124-9.168824-20.466124-20.466124 0-11.307533 9.168824-20.466124 20.466124-20.466124l185.637977 0c77.628008 0 140.786467-63.148226 140.786467-140.766001 0-77.423347-62.841234-140.448776-140.203182-140.766001-0.419556 0.030699-0.818645 0.051165-1.217734 0.061398-5.945409 0.143263-11.686157-2.292206-15.687284-6.702656-4.001127-4.400217-5.894244-10.335393-5.167696-16.250102 1.330298-10.806113 1.944282-19.760043 1.944282-28.192086 0-60.763922-23.658839-117.884874-66.617234-160.833035-42.968627-42.968627-100.089579-66.617234-160.843268-66.617234-47.368844 0-92.742241 14.449084-131.208321 41.781592-37.616736 26.738991-65.952084 63.700811-81.925894 106.884332-2.425236 6.538927-8.012488 11.399631-14.827707 12.893658-6.815219 1.483794-13.927197-0.603751-18.859533-5.54632-19.289322-19.330254-44.943608-29.972639-72.245418-29.972639-56.322773 0-102.146425 45.813419-102.146425 102.125959 0 0.317225 0.040932 0.982374 0.092098 1.627057 0.061398 0.920976 0.122797 1.831718 0.153496 2.762927 0.337691 9.465582-5.863545 17.928325-15.001669 20.455891-32.356942 8.933463-61.541635 28.550243-82.181721 55.217602-21.305235 27.516704-32.571836 60.508096-32.571836 95.41307 0 86.244246 70.188572 156.422585 156.443052 156.422585l169.981393 0c11.2973 0 20.466124 9.15859 20.466124 20.466124 0 11.2973-9.168824 20.466124-20.466124 20.466124l-169.981393 0c-108.828614 0-197.3753-88.536452-197.3753-197.354833 0-44.053332 14.223956-85.712127 41.126676-120.473839 22.809495-29.460985 53.897537-52.086285 88.710414-64.816215 5.065366-74.322729 67.149353-133.2447 142.751215-133.2447 28.386514 0 55.504128 8.217149 78.651314 23.52581 19.657712-39.868009 48.842405-74.169233 85.497233-100.212376 45.434795-32.295544 99.004875-49.354058 154.918325-49.354058 71.692832 0 139.087778 27.915793 189.782368 78.600149 50.694589 50.694589 78.610382 118.089535 78.610382 189.782368 0 3.704368-0.102331 7.470135-0.296759 11.368932C952.633602 352.568894 1022.955204 429.511287 1022.955204 522.570753z" p-id="4439">
</path>
<path d="M629.258611 820.711014l-102.023628 102.013395c-3.990894 4.001127-9.230222 5.996574-14.46955 5.996574s-10.478655-1.995447-14.46955-5.996574l-102.023628-102.013395c-7.992021-7.992021-7.992021-20.947078 0-28.939099s20.947078-8.002254 28.939099 0l67.087954 67.077721 0-358.699522c0-11.2973 9.15859-20.466124 20.466124-20.466124 11.307533 0 20.466124 9.168824 20.466124 20.466124l0 358.699522 67.087954-67.077721c7.992021-8.002254 20.947078-7.992021 28.939099 0S637.250632 812.718993 629.258611 820.711014z" p-id="4440">
</path>
</svg>
</button>
}
</div>
</td>
</tr>
))
}
</tbody>
</table>
<Table
id="comfyui-copilot-model-download"
bordered
loading={loading}
columns={columns}
dataSource={modelSuggests}
pagination={showPagination ? undefined : false}
rowClassName={"text-gray-800"}
locale={{ emptyText: <TableEmpty /> }}
/>
<Modal open={!!modalContent && modalContent !== ''} onClose={() => setModalContent(null)}>
<p>{modalContent}</p>
</Modal>
+17
View File
@@ -0,0 +1,17 @@
import { Empty } from 'antd';
const TableEmpty = () => {
return <Empty
image={<svg viewBox="0 0 1351 1024" fill="#ffffff73">
<path d="M467.19776 479.648s2.688 2.688 8.096 2.688h393.44c2.688 0 5.376-2.688 8.096-2.688V358.4h409.6c-2.688-8.096-2.688-13.472-8.096-21.568l-264.096-277.568H335.16576l-264.096 277.568c-5.376 2.688-8.096 10.784-8.096 21.568h409.6v121.248h-5.376z m-409.6-61.952v476.96c0 37.728 40.416 70.048 88.928 70.048h1053.632c48.512 0 88.928-32.352 88.928-70.048V412.288H936.06176v64.672c0 32.352-29.632 59.296-61.984 59.296H480.63776c-35.04 0-61.984-26.944-61.984-59.296v-64.672H62.94176v5.376zM1200.18976 1024H146.55776C65.72576 1024 1.05376 964.704 1.05376 894.656V417.696c-2.688-48.512-2.688-94.304 29.632-123.968L313.62976 0H1038.52576l282.944 293.728c32.352 29.632 29.632 83.552 29.632 142.816v455.424C1345.72576 964.736 1278.33376 1024 1200.18976 1024z">
</path>
</svg>}
styles={{
image: {
height: 40
}
}}
/>
}
export default TableEmpty
+35 -4
View File
@@ -3,6 +3,7 @@
import { createContext, useContext, useReducer, Dispatch, useRef, useEffect, useState } from 'react';
import { Message } from '../types/types';
import { app } from '../utils/comfyapp';
import { ConfigProvider } from 'antd';
// Add tab type definition
export type TabType = 'chat' | 'parameter-debug';
@@ -106,6 +107,8 @@ export function ChatProvider({ children }: { children: React.ReactNode }) {
const [modelDownloadMap, setModelDownloadMap] = useState<Record<string, DownloadProgress>>({});
const currentDownloadingId = useRef<string[]>([]);
const isDark = app.extensionManager.setting.get('Comfy.ColorPalette') === 'dark';
const getProgress = async (id: string) => {
const response = await fetch(`/api/download-progress/${id}`)
const res = await response.json()
@@ -124,7 +127,7 @@ export function ChatProvider({ children }: { children: React.ReactNode }) {
percentage: response.percentage,
status: response.status
}
if (response.status === 'finished') {
if (response.status === 'completed') {
currentDownloadingId?.current?.splice(currentDownloadingId?.current?.indexOf(response.id), 1)
}
}
@@ -170,9 +173,37 @@ export function ChatProvider({ children }: { children: React.ReactNode }) {
}, [state.messages, state.sessionId]);
return (
<ChatContext.Provider value={{ state, dispatch, showcasIng, abortControllerRef, modelDownloadMap, addDownloadId }}>
{children}
</ChatContext.Provider>
<ConfigProvider
theme={{
token: {
colorBgContainer: isDark ? '#18181b' : '#fff',
colorTextDescription: isDark ? 'rgba(255,255,255,0.45)' : 'rgba(0,0,0,0.45)',
},
components: {
Table: {
borderColor: isDark ? '#666' : '#f0f0f0',
headerBg: isDark ? '#333' : '#fafafa',
headerColor: isDark ? '#fff' : '#18181b',
rowHoverBg: isDark ? '#333' : '#fafafa',
},
Pagination: {
itemBg: isDark ? 'rgb(24, 24, 27)' : '#fff',
itemActiveBg: isDark ? 'rgb(24, 24, 27)' : '#fff',
colorText: isDark ? 'rgba(255,255,255,0.88)' : 'rgba(0,0,0,0.88)',
colorBgTextHover: isDark ? '#555' : 'rgba(0,0,0,0.06)',
colorPrimary: isDark ? '#aaa' : '#1677ff',
colorPrimaryHover: isDark ? '#999' : '#4096ff',
},
Form: {
labelColor: isDark ? 'rgba(255,255,255,0.88)' : 'rgba(0,0,0,0.88)'
}
}
}}
>
<ChatContext.Provider value={{ state, dispatch, showcasIng, abortControllerRef, modelDownloadMap, addDownloadId }}>
{children}
</ChatContext.Provider>
</ConfigProvider>
);
}
+2 -19
View File
@@ -1,7 +1,8 @@
#comfyui-copilot-plugin,
#comfyui-copilot-image-upload-modal,
#comfyui-copilot-rewrite-expert-modal,
#comfyui-copilot-model-download-modal {
#comfyui-copilot-model-download-modal,
#comfyui-copilot-model-download {
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
@@ -366,9 +367,6 @@
.mt-6 {
margin-top: 1.5rem;
}
.mt-8 {
margin-top: 2rem;
}
.line-clamp-2 {
overflow: hidden;
display: -webkit-box;
@@ -531,9 +529,6 @@
.w-2 {
width: 0.5rem;
}
.w-20 {
width: 5rem;
}
.w-28 {
width: 7rem;
}
@@ -1516,18 +1511,6 @@
}
}
#comfyui-copilot-model-download-modal {
* {
box-sizing: border-box;
border-width: 0;
border-style: solid;
}
button {
background-color: transparent;
background-image: none;
}
}
.hide-scrollbar {
scrollbar-width: none;
/* Firefox */
+2 -14
View File
@@ -1,7 +1,8 @@
#comfyui-copilot-plugin,
#comfyui-copilot-image-upload-modal,
#comfyui-copilot-rewrite-expert-modal,
#comfyui-copilot-model-download-modal {
#comfyui-copilot-model-download-modal,
#comfyui-copilot-model-download {
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -33,19 +34,6 @@
}
/* Specific resets for buttons that might be affected by ComfyUI styles */
button {
background-color: transparent;
background-image: none;
}
}
#comfyui-copilot-model-download-modal {
* {
box-sizing: border-box;
border-width: 0;
border-style: solid;
}
button {
background-color: transparent;
background-image: none;