Merge branch 'main' of gitlab.alibaba-inc.com:aidc-innovation/ComfyUI-Copilot into main

This commit is contained in:
shaili
2025-02-12 17:17:05 +08:00
9 changed files with 1457 additions and 258 deletions
+6
View File
@@ -0,0 +1,6 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["copilot_web/workflowChat-nlzNpdzN.js","copilot_web/input.js","copilot_web/assets/input-BiPrIQoG.css"].map(path => {
const apiBase = window.comfyAPI?.api?.api?.api_base;
const prefix = apiBase ? `${apiBase.substring(1)}/` : '';
return `${prefix}${path}`;
}))))=>i.map(i=>d[i]);
import{r as t,j as s,R as w,_}from"./input.js";const D=9999999,f={EXPLAIN_NODE:"copilot:explain-node"},b=w.lazy(()=>_(()=>import("./workflowChat-nlzNpdzN.js"),__vite__mapDeps([0,1,2])));function N(){const g=t.useRef(null),[E,r]=t.useState(!1),[i,l]=t.useState(),[o,u]=t.useState(!1),[a,m]=t.useState({x:0,y:0}),[h,c]=t.useState(!1);t.useEffect(()=>{const e=()=>{console.log("Explain node event received"),r(!0),c(!0)};return window.addEventListener(f.EXPLAIN_NODE,e),()=>window.removeEventListener(f.EXPLAIN_NODE,e)},[]),t.useEffect(()=>{l({x:window.innerWidth-160,y:20})},[]);const x=e=>{e.preventDefault(),u(!0);const n=e.currentTarget.getBoundingClientRect();m({x:e.clientX-n.left,y:e.clientY-n.top})};return t.useEffect(()=>{const e=d=>{if(o){const p=Math.min(Math.max(0,d.clientX-a.x),window.innerWidth-100),v=Math.min(Math.max(0,d.clientY-a.y),window.innerHeight-40);l({x:p,y:v})}},n=()=>{u(!1)};return o&&(document.addEventListener("mousemove",e),document.addEventListener("mouseup",n)),()=>{document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",n)}},[o,a]),i?s.jsx("div",{ref:g,children:s.jsxs("div",{className:"fixed",style:{zIndex:D,left:i.x,top:i.y,cursor:o?"grabbing":"grab"},children:[s.jsx("button",{onMouseDown:x,onClick:()=>{r(!0)},className:"px-4 py-2 border border-gray-300 rounded-md bg-white text-black hover:bg-green-600 transition-colors select-none",children:"copilot"}),s.jsx(b,{onClose:()=>{r(!1),c(!1)},visible:E,triggerUsage:h,onUsageTriggered:()=>c(!1)})]})}):null}export{N as default};
-6
View File
@@ -1,6 +0,0 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["copilot_web/workflowChat-2b2JOI-A.js","copilot_web/input.js","copilot_web/assets/input-BiPrIQoG.css"].map(path => {
const apiBase = window.comfyAPI?.api?.api?.api_base;
const prefix = apiBase ? `${apiBase.substring(1)}/` : '';
return `${prefix}${path}`;
}))))=>i.map(i=>d[i]);
import{r as t,j as s,R as p,_ as v}from"./input.js";const w=9999999,E=p.lazy(()=>v(()=>import("./workflowChat-2b2JOI-A.js"),__vite__mapDeps([0,1,2])));function y(){const d=t.useRef(null),[f,a]=t.useState(!1),[r,c]=t.useState(),[o,u]=t.useState(!1),[i,m]=t.useState({x:0,y:0});t.useEffect(()=>{c({x:window.innerWidth-160,y:20})},[]);const h=e=>{e.preventDefault(),u(!0);const n=e.currentTarget.getBoundingClientRect();m({x:e.clientX-n.left,y:e.clientY-n.top})};return t.useEffect(()=>{const e=l=>{if(o){const x=Math.min(Math.max(0,l.clientX-i.x),window.innerWidth-100),g=Math.min(Math.max(0,l.clientY-i.y),window.innerHeight-40);c({x,y:g})}},n=()=>{u(!1)};return o&&(document.addEventListener("mousemove",e),document.addEventListener("mouseup",n)),()=>{document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",n)}},[o,i]),r?s.jsx("div",{ref:d,children:s.jsxs("div",{className:"fixed",style:{zIndex:w,left:r.x,top:r.y,cursor:o?"grabbing":"grab"},children:[s.jsx("button",{onMouseDown:h,onClick:()=>a(!0),className:"px-4 py-2 border border-gray-300 rounded-md bg-white text-black hover:bg-green-600 transition-colors select-none",children:"copilot"}),s.jsx(E,{onClose:()=>a(!1),visible:f})]})}):null}export{y as default};
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+31
View File
@@ -0,0 +1,31 @@
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
// 定义事件常量
const COPILOT_EVENTS = {
EXPLAIN_NODE: 'copilot:explain-node'
};
function addExtraMenuOptions(nodeType, nodeData, app) {
const original_getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
nodeType.prototype.getExtraMenuOptions = function (_, options) {
original_getExtraMenuOptions?.apply(this, arguments);
options.push({
content: "Explain with Copilot",
callback: async () => {
const nodeTypeUniqueId = nodeType?.comfyClass;
// 触发自定义事件
window.dispatchEvent(new CustomEvent(COPILOT_EVENTS.EXPLAIN_NODE, {
detail: { nodeType: nodeTypeUniqueId }
}));
}
})
}
}
app.registerExtension({
name: "ComfyUI-Copilot-Bridge",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
addExtraMenuOptions(nodeType, nodeData, app);
},
})
+25 -2
View File
@@ -1,5 +1,6 @@
import React, { useRef, useState, useEffect } from "react";
import { DRAWER_Z_INDEX } from "./const";
import { COPILOT_EVENTS } from "./constants/events";
const WorkflowChat = React.lazy(() => import("./workflowChat/workflowChat"));
export default function App() {
@@ -8,6 +9,18 @@ export default function App() {
const [position, setPosition] = useState<{ x: number; y: number }>();
const [isDragging, setIsDragging] = useState(false);
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
const [shouldTriggerUsage, setShouldTriggerUsage] = useState(false);
useEffect(() => {
const handleExplainNode = () => {
console.log("Explain node event received");
setShowChat(true);
setShouldTriggerUsage(true);
};
window.addEventListener(COPILOT_EVENTS.EXPLAIN_NODE, handleExplainNode);
return () => window.removeEventListener(COPILOT_EVENTS.EXPLAIN_NODE, handleExplainNode);
}, []);
useEffect(() => {
setPosition({
@@ -65,12 +78,22 @@ export default function App() {
>
<button
onMouseDown={handleMouseDown}
onClick={() => setShowChat(true)}
onClick={() => {
setShowChat(true);
}}
className="px-4 py-2 border border-gray-300 rounded-md bg-white text-black hover:bg-green-600 transition-colors select-none"
>
copilot
</button>
<WorkflowChat onClose={() => setShowChat(false)} visible={showChat} />
<WorkflowChat
onClose={() => {
setShowChat(false);
setShouldTriggerUsage(false);
}}
visible={showChat}
triggerUsage={shouldTriggerUsage}
onUsageTriggered={() => setShouldTriggerUsage(false)}
/>
</div>
</div>
);
+3
View File
@@ -0,0 +1,3 @@
export const COPILOT_EVENTS = {
EXPLAIN_NODE: 'copilot:explain-node'
} as const;
+1334 -201
View File
File diff suppressed because it is too large Load Diff
+10 -1
View File
@@ -14,9 +14,11 @@ import React from "react";
interface WorkflowChatProps {
onClose?: () => void;
visible?: boolean;
triggerUsage?: boolean;
onUsageTriggered?: () => void;
}
export default function WorkflowChat({ onClose, visible = true }: WorkflowChatProps) {
export default function WorkflowChat({ onClose, visible = true, triggerUsage = false, onUsageTriggered }: WorkflowChatProps) {
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState<string>('');
const [latestInput, setLatestInput] = useState<string>('');
@@ -285,6 +287,13 @@ export default function WorkflowChat({ onClose, visible = true }: WorkflowChatPr
};
}, [uploadedImages]);
useEffect(() => {
if (triggerUsage && onUsageTriggered) {
handleSendMessageWithIntent('node_explain');
onUsageTriggered();
}
}, [triggerUsage]);
return (
<div
className="fixed top-0 right-0 h-full shadow-lg bg-white