dsh-plugin-agentflow 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js
CHANGED
|
@@ -336,7 +336,7 @@ html body {
|
|
|
336
336
|
.dark .af-panel .af-row:hover {
|
|
337
337
|
background: #1d1e1b;
|
|
338
338
|
}
|
|
339
|
-
`,aW=`w-full rounded-lg border border-[#E1E2DD] bg-[#FCFCFA] px-2.5 py-2 text-[13px] leading-[1.65] text-[#1B1B18] outline-none transition-colors placeholder:text-[#9a9a92] focus:border-[#24543F] focus:bg-white dark:border-[#33353B] dark:bg-[#17181B] dark:text-[#EDEDE8] dark:focus:border-[#6aa583] dark:focus:bg-[#1B1C20]`,oW=`rounded-[4px] px-2.5 py-1.5 text-[12px] text-[#5b6472] transition-colors hover:bg-[#EFEFEA] dark:text-[#a3a39b] dark:hover:bg-[#232421]`;function sW(e){return(0,p.jsxs)(`aside`,{className:`af-panel absolute bottom-0 right-0 top-14 z-30 flex w-[420px] flex-col border-l border-[#E3E4DF] bg-[#FCFCFA] dark:border-[#262724] dark:bg-[#17181B]`,role:`complementary`,"aria-label":`节点详情`,children:[(0,p.jsx)(`style`,{children:iW}),(0,p.jsx)(lW,{...e},e.node.id)]})}function cW(e,...t){let n=e.trim().toLowerCase();return!n||t.some(e=>String(e??``).toLowerCase().includes(n))}function lW(e){let{node:t,nodes:n,edges:r,boardId:i,skills:a,servers:o,catalog:s,bridge:c,running:l,onPatch:d,onDerive:f,onVerify:m,onRerun:h,onRefreshModels:g,onEdgesChange:_,onDelete:v,onClose:y}=e,[b,x]=(0,u.useState)(t.label),[S,C]=(0,u.useState)(t.task),[w,T]=(0,u.useState)(t.criteria),[E,D]=(0,u.useState)(QU),[O,k]=(0,u.useState)(0),[A,M]=(0,u.useState)(``),[N,P]=(0,u.useState)(``),[I,L]=(0,u.useState)(null),R=(0,u.useRef)(null),z=(0,u.useRef)(null);(0,u.useEffect)(()=>{mW(R.current)},[S]),(0,u.useEffect)(()=>{mW(z.current)},[w]);let B=(0,u.useRef)(d);(0,u.useEffect)(()=>{B.current=d},[d]);let V=(0,u.useRef)({}),H=(0,u.useRef)(null),W=(0,u.useCallback)(()=>{H.current!==null&&(window.clearTimeout(H.current),H.current=null);let e=V.current;Object.keys(e).length&&(V.current={},B.current(e))},[]),G=(0,u.useCallback)(e=>{V.current={...V.current,...e},H.current!==null&&window.clearTimeout(H.current),H.current=window.setTimeout(W,400)},[W]);(0,u.useEffect)(()=>()=>{if(H.current!==null){window.clearTimeout(H.current),H.current=null;let e=V.current;Object.keys(e).length&&B.current(e)}},[]),(0,u.useEffect)(()=>{let e=e=>{(e.metaKey||e.ctrlKey)&&String(e.key).toLowerCase()===`s`&&W()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[W]);let[ee,te]=(0,u.useState)(r);(0,u.useEffect)(()=>{te(r)},[r]);let ne=new Set(ee.filter(e=>e.to===t.id).map(e=>e.from)),K=n.filter(e=>e.id!==t.id);function re(e){let n=[...ee.filter(e=>e.to!==t.id),...e.map(e=>({from:e,to:t.id}))];te(n),_(n)}function ae(e,n){let r=new Set(t.skills);n?r.add(e):r.delete(e),d({skills:[...r]})}let q=s?.providers??[],oe=t.provider&&t.model?`${t.provider}/${t.model}`:``,J=q.some(e=>e.id===t.provider&&e.models.some(e=>e.id===t.model)),ce=t.model&&!J?t.model:``,le=J?q.find(e=>e.id===t.provider)?.models.find(e=>e.id===t.model)??null:null,ue=le?.levels??[],de=le?.defaultLevel??``,fe=q.every(e=>!e.models.length),pe=new Set,he=[];for(let e of E){let{provider:t,model:n}=eW(e.value),r=q.find(e=>e.id===t),i=r?.models.find(e=>e.id===n);r&&i&&!pe.has(e.value)&&(pe.add(e.value),he.push({title:i.name,label:`${r.label} · ${i.name}`,value:`${YU}${e.value}`}))}let ge=[];he.length&&ge.push({title:`最近使用`,label:`最近使用`,value:qU,selectable:!1,children:he}),ce&&ge.push({title:`当前值`,label:`当前值`,value:JU,selectable:!1,children:[{title:ce,label:tW(t.provider,ce),value:KU}]});for(let e of q){let t=e.models.length;ge.push({title:t?`${e.label}(${t})`:e.label,label:e.label,value:`p:${e.id}`,selectable:!1,children:e.error?[{title:e.error,label:e.error,value:`e:${e.id}`,disabled:!0}]:e.models.map(t=>({title:t.name,label:`${e.label} · ${t.name}`,value:`${e.id}/${t.id}`}))})}let _e=q.find(e=>e.id===t.provider),ve=E.map(e=>e.provider).find(e=>q.some(t=>t.id===e)),ye=_e?.id??ve??``,be=[...he.length?[qU]:[],...ce?[JU]:[],...ye?[`p:${ye}`]:[]],xe=J?oe:ce?KU:void 0,X=t.fallback??[],Se=t.fallbackEfforts??{},Ce=new Set(X),we=q.map(e=>{let t=e.models.length,n=e.error?[{title:e.error,label:e.error,value:`e:${e.id}`,disabled:!0}]:e.models.filter(t=>{let n=`${e.id}/${t.id}`;return n!==oe&&!Ce.has(n)}).map(t=>({title:t.name,label:`${e.label} · ${t.name}`,value:`${e.id}/${t.id}`}));return{title:t?`${e.label}(${t})`:e.label,label:e.label,value:`p:${e.id}`,selectable:!1,children:n}}).filter(e=>e.children.length>0),Te=ye?[`p:${ye}`]:[];function Ee(e){if(!e||e===KU)return;let n=e.startsWith(YU)?e.slice(2):e,{provider:r,model:i}=eW(n),a=q.find(e=>e.id===r),o=a?.models.find(e=>e.id===i);if(!a||!o)return;let s=o.levels.includes(t.reasoningEffort??``)?t.reasoningEffort??``:``,c={value:n,label:o.name,provider:r},l=[c,...E.filter(e=>e.value!==c.value)].slice(0,ZU);D(l),$U(l),d({provider:r,model:i,reasoningEffort:s})}function De(e){let{provider:t,model:n}=eW(e),r=q.find(e=>e.id===t),i=r?.models.find(e=>e.id===n);return!r||!i?{label:`${e}(不在 DSH 目录里)`,levels:[]}:{label:`${r.label} · ${i.name}`,levels:i.levels}}function Oe(e,t){d({fallback:e,fallbackEfforts:t})}function ke(e){e&&e.includes(`/`)&&!Ce.has(e)&&(Oe([...X,e],{...Se,[e]:``}),k(e=>e+1))}function Ae(e){let t={...Se};delete t[e],Oe(X.filter(t=>t!==e),t)}function je(e,t){Oe(X,{...Se,[e]:t})}let Me=nW[t.status]??nW.idle,Ne=t.type===`orchestrator`,Pe=n.some(e=>e.id!==t.id&&e.type===`orchestrator`),Fe=OU.map(e=>({...e,disabled:e.value===`orchestrator`&&Pe})),Ie=rW.find(e=>e.value===(t.verify??``))??rW[0],Le=t.status===`review`,Re=a.filter(e=>cW(A,e.name,e.description)),ze=o.map(e=>({...e,tools:e.tools.filter(e=>cW(N,e.name,e.description))})).filter(e=>cW(N,e.name)||e.tools.length>0),Be=N.trim()?ze.map(e=>e.name):I??o.filter(e=>e.ok&&e.tools.length).slice(0,1).map(e=>e.name);return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`header`,{className:`flex shrink-0 items-center gap-2 border-b ${WU} bg-[#FAFAF7] px-5 py-3.5 dark:bg-[#1B1C20]`,children:[(0,p.jsx)(`input`,{value:b,onChange:e=>{let t=e.target.value;x(t),G({label:t})},onBlur:W,onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur()},placeholder:`节点名称`,"aria-label":`节点名称`,className:`min-w-0 flex-1 rounded-[3px] border-0 bg-transparent p-0 text-[17px] font-semibold tracking-tight outline-none placeholder:text-[#a8a8a0] focus-visible:ring-2 focus-visible:ring-[#24543F]/30 dark:placeholder:text-[#6f6f68] dark:focus-visible:ring-[#6aa583]/40 ${VU}`}),(0,p.jsxs)(`span`,{className:`flex shrink-0 items-center gap-1.5 text-[12px] ${HU}`,children:[(0,p.jsx)(`span`,{className:`h-[6px] w-[6px] rounded-full ${Me.dot}`}),Me.label]}),(0,p.jsx)(`button`,{type:`button`,onClick:y,"aria-label":`关闭详情`,title:`关闭`,className:`-mr-1 grid h-8 w-8 shrink-0 place-items-center rounded-[4px] text-[#6b6b66] transition-colors hover:bg-[#EFEFEA] dark:text-[#8b8b85] dark:hover:bg-[#232421]`,children:(0,p.jsx)(Y,{size:16})})]}),t.verdict&&(0,p.jsxs)(`div`,{className:`shrink-0 border-b px-5 py-2 text-[12px] leading-[1.5] ${WU} ${t.verdict.pass?`bg-[#EEF3EF] text-[#24543F] dark:bg-[#1B2A22] dark:text-[#8FC3A7]`:`bg-[#FBEFEA] text-[#B4451F] dark:bg-[#2A1C17] dark:text-[#E08A6A]`}`,children:[pW(t.verdict.by),` `,t.verdict.pass?`通过`:`未通过`,t.verdict.reason?`:${t.verdict.reason}`:``]}),t.error&&(0,p.jsx)(`div`,{className:`shrink-0 border-b px-5 py-2 text-[12px] leading-[1.5] ${WU} bg-[#FBEFEA] text-[#B4451F] dark:bg-[#2A1C17] dark:text-[#E08A6A]`,children:t.error}),(0,p.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 pb-6 pt-3`,children:[Ne?null:(0,p.jsxs)(uW,{title:`节点类型`,children:[(0,p.jsx)(jb,{value:t.type||`llm`,onChange:e=>d({type:e}),options:Fe,"aria-label":`节点类型`,className:`w-full`,size:`middle`}),Pe?(0,p.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${UU}`,children:`画布已有根节点,这张卡不能再设为调度卡。`}):null]}),(0,p.jsx)(uW,{title:`模型`,extra:(0,p.jsxs)(`button`,{type:`button`,onClick:g,title:`重新读取 DSH 的模型目录`,className:`flex items-center gap-1 text-[11px] transition-opacity hover:opacity-70 ${UU}`,children:[(0,p.jsx)(ie,{size:11}),`刷新`]}),children:(0,p.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,p.jsx)(Nk,{value:xe,placeholder:`选择模型`,showSearch:!0,treeNodeFilterProp:`title`,treeDefaultExpandAll:!1,treeDefaultExpandedKeys:be,treeNodeLabelProp:`label`,treeData:ge,onChange:Ee,"aria-label":`模型`,className:`w-full`,size:`middle`}),(0,p.jsx)(jb,{value:t.reasoningEffort??``,onChange:e=>d({reasoningEffort:e}),disabled:!ue.length,"aria-label":`推理强度`,title:ue.length?`推理强度`:`当前模型没有可选推理档位`,options:[{value:``,label:`推理强度:模型默认${de?`(${de})`:``}`},...ue.map(e=>({value:e,label:e}))],className:`w-full`,size:`middle`}),fe&&(0,p.jsxs)(`div`,{className:`flex items-start gap-1.5 text-[11px] leading-[1.6] ${HU}`,children:[(0,p.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-50`}),(0,p.jsx)(`span`,{children:`没读到 DSH 的模型目录,检查 DSH 凭据或网络。`})]}),(0,p.jsxs)(`div`,{className:`flex items-start gap-1.5 border-t border-[#EDEEE9] pt-2 text-[11px] leading-[1.6] dark:border-[#2A2C31] ${c&&!c.healthy?`text-[#B4451F] dark:text-[#e08a6a]`:HU}`,children:[(0,p.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-60`}),(0,p.jsxs)(`span`,{children:[`模型通道:DSH 内核(未连接时不可跑图)`,c&&!c.healthy?` · ${c.reason||`原因未知`}`:``]})]})]})}),(0,p.jsx)(uW,{title:`兜底模型`,extra:X.length?(0,p.jsxs)(`span`,{className:`text-[11px] ${HU}`,children:[X.length,` 个 · 按顺序重试`]}):void 0,children:(0,p.jsxs)(`div`,{className:`space-y-1.5`,children:[X.map(e=>{let t=De(e);return(0,p.jsxs)(`div`,{className:`flex min-h-[32px] items-center gap-2 border-b py-1 last:border-b-0 ${WU}`,children:[(0,p.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[12px] ${VU}`,title:t.label,children:t.label}),(0,p.jsx)(jb,{size:`small`,value:Se[e]??``,disabled:!t.levels.length,title:t.levels.length?`这条兜底的推理强度`:`该模型没有可选推理档位`,options:[{value:``,label:`模型默认`},...t.levels.map(e=>({value:e,label:e}))],onChange:t=>je(e,t),"aria-label":`${t.label} 的推理强度`,style:{width:104}}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>Ae(e),"aria-label":`移除兜底模型 ${t.label}`,title:`移除`,className:`grid h-7 w-7 shrink-0 place-items-center rounded-[4px] transition-colors hover:bg-[#FBEFEA] hover:text-[#B4451F] dark:hover:bg-[#2A1C17] dark:hover:text-[#e08a6a] ${UU}`,children:(0,p.jsx)(Y,{size:13})})]},e)}),(0,p.jsx)(Nk,{onChange:ke,placeholder:`添加兜底模型…`,showSearch:!0,treeNodeFilterProp:`title`,treeDefaultExpandAll:!1,treeDefaultExpandedKeys:Te,treeNodeLabelProp:`label`,treeData:we,"aria-label":`添加兜底模型`,className:`w-full`,size:`middle`},O),(0,p.jsxs)(`div`,{className:`flex items-start gap-1.5 pt-0.5 text-[11px] leading-[1.6] ${HU}`,children:[(0,p.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-50`}),(0,p.jsx)(`span`,{children:`兜底模型:主模型失败后按顺序尝试,可单独设推理强度`})]})]})}),(0,p.jsxs)(uW,{title:Ne?`人格`:`任务`,children:[(0,p.jsx)(`textarea`,{ref:R,rows:3,value:S,onChange:e=>{C(e.target.value),G({task:e.target.value}),mW(e.currentTarget)},onBlur:W,placeholder:Ne?`默认:只负责和用户对话,再严格按后续节点的 AgentFlow 流执行(可自己改)`:`写清楚这张卡要做什么…`,className:`${aW} max-h-[240px] resize-none overflow-y-auto`}),Ne&&(0,p.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${UU}`,children:`默认人格只是起点,可以自己改:它只负责和用户对话,确认需求后严格按后续节点的流程执行。`})]}),(0,p.jsx)(uW,{title:`完成标准`,children:(0,p.jsx)(`textarea`,{ref:z,rows:2,value:w,onChange:e=>{T(e.target.value),G({criteria:e.target.value}),mW(e.currentTarget)},onBlur:W,placeholder:`做到什么程度算完成…`,className:`${aW} max-h-[200px] resize-none overflow-y-auto`})}),(0,p.jsxs)(uW,{title:`结果判断`,children:[(0,p.jsx)(`div`,{role:`radiogroup`,"aria-label":`结果判断`,className:`flex gap-[2px] rounded-[6px] bg-[#EFEFEA] p-[3px] dark:bg-[#232421]`,children:rW.map(e=>{let n=(t.verify??``)===e.value;return(0,p.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":n,title:e.desc,onClick:()=>d({verify:e.value}),className:`flex-1 rounded-[4px] px-1 py-[5px] text-[13px] leading-[1.3] transition-colors ${n?`bg-white text-[#1B1B18] shadow-[0_1px_2px_rgba(0,0,0,0.06)] dark:bg-[#3A3B35] dark:text-[#e8e8e4]`:`hover:text-[#1B1B18] dark:hover:text-[#e8e8e4] ${HU}`}`,children:e.label},e.value||`none`)})}),(0,p.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${UU}`,children:Ie.desc}),(t.verify??``)===`jev`&&(0,p.jsx)(`p`,{className:`mt-1.5 rounded-[4px] border border-[#E9D9B8] bg-[#FBF4E6] px-2 py-1.5 text-[11px] leading-[1.5] text-[#8a6220] dark:border-[#4a3a1c] dark:bg-[#2a2314] dark:text-[#e0b866]`,children:`需要本机安装 jev(TypeSafe)并配置 API key,否则这张卡跑到判定时会失败。`})]}),(0,p.jsx)(uW,{title:`技能`,extra:(0,p.jsxs)(`span`,{className:`text-[11px] ${UU}`,children:[`已选 `,t.skills.length]}),children:a.length===0?(0,p.jsx)(dW,{children:`没有找到技能`}):(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(AD,{value:A,onChange:e=>M(e.target.value),allowClear:!0,size:`middle`,placeholder:`搜索技能名或描述…`,"aria-label":`搜索技能`,prefix:(0,p.jsx)(se,{size:12,className:UU}),className:`mb-2`}),Re.length===0?(0,p.jsxs)(dW,{children:[`没有匹配「`,A.trim(),`」的技能`]}):null,(0,p.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto`,children:Re.map(e=>{let n=t.skills.includes(e.name);return(0,p.jsx)(GT,{className:`af-row`,checked:n,onChange:t=>ae(e.name,t.target.checked),title:e.description,children:(0,p.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`shrink-0 text-[13px] ${VU}`,children:e.name}),(0,p.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-right text-[11px] ${UU}`,children:e.description||`无描述`})]})},e.name)})})]})}),(0,p.jsx)(uW,{title:`MCP 工具`,extra:(0,p.jsxs)(`span`,{className:`text-[11px] ${UU}`,children:[`已选 `,t.tools.length]}),children:o.length===0?(0,p.jsx)(dW,{children:`还没配置 MCP 服务器`}):(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(AD,{value:N,onChange:e=>P(e.target.value),allowClear:!0,size:`middle`,placeholder:`搜索服务器或工具…`,"aria-label":`搜索 MCP 工具`,prefix:(0,p.jsx)(se,{size:12,className:UU}),className:`mb-2`}),ze.length===0?(0,p.jsxs)(dW,{children:[`没有匹配「`,N.trim(),`」的工具`]}):null,(0,p.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto af-tree`,children:(0,p.jsx)(jO,{checkable:!0,selectable:!1,expandedKeys:Be,onExpand:e=>L(e),treeData:ze.map(e=>({key:e.name,selectable:!1,title:(0,p.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`h-[5px] w-[5px] shrink-0 rounded-full ${e.ok?`bg-[#24543F] dark:bg-[#6aa583]`:`bg-[#B4451F] dark:bg-[#e08a6a]`}`}),(0,p.jsx)(`span`,{className:`text-[12px] font-medium ${VU}`,children:e.name}),(0,p.jsxs)(`span`,{className:`text-[11px] ${UU}`,children:[e.tools.length,` 个工具`]}),!e.ok&&(0,p.jsx)(`span`,{className:`text-[11px] text-[#B4451F] dark:text-[#e08a6a]`,children:`连接失败`})]}),children:e.tools.map(t=>({key:`${e.name}.${t.name}`,title:(0,p.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`shrink-0 text-[13px] ${VU}`,children:t.name}),(0,p.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-right text-[11px] ${UU}`,children:t.description})]})}))})),checkedKeys:t.tools,onCheck:e=>{let t=Array.isArray(e)?e:e.checked;d({tools:t.filter(e=>String(e).includes(`.`))})}})})]})}),Ne?null:(0,p.jsx)(uW,{title:`上游`,children:K.length===0?(0,p.jsx)(dW,{children:`还没有其它卡片`}):(0,p.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto`,children:K.map(e=>{let n=ne.has(e.id),r=!n&&fW(ee,t.id,e.id),i=n?[...ne].filter(t=>t!==e.id):[...ne,e.id];return(0,p.jsx)(GT,{className:`af-row ${r?`af-row-disabled`:``}`,checked:n,disabled:r,onChange:()=>re(i),children:(0,p.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[13px] ${VU}`,children:e.label||e.id}),r&&(0,p.jsx)(`span`,{className:`shrink-0 text-[11px] ${UU}`,children:`会成环`})]})},e.id)})})})]}),Le&&(0,p.jsxs)(`div`,{className:`shrink-0 border-t ${WU} bg-[#FAEFE6] px-5 py-3 dark:bg-[#2A1C17]`,children:[(0,p.jsx)(`p`,{className:`text-[12px] text-[#B4451F] dark:text-[#e08a6a]`,children:`这张卡跑完了,等你判断结果`}),(0,p.jsxs)(`div`,{className:`mt-2 flex gap-2`,children:[(0,p.jsx)(`button`,{type:`button`,onClick:()=>m(!0),className:`h-8 flex-1 rounded-[4px] bg-[#24543F] text-[13px] font-medium text-white transition-colors hover:bg-[#1D4634] dark:bg-[#3F7A5F] dark:hover:bg-[#4B8B6D]`,children:`通过`}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>m(!1),className:`h-8 flex-1 rounded-[4px] text-[13px] text-[#6b6b66] transition-colors hover:bg-white/60 dark:text-[#a3a39b] dark:hover:bg-[#232421]`,children:`打回重跑`})]})]}),(0,p.jsxs)(`footer`,{className:`shrink-0 border-t ${WU} bg-[#FAFAF7] px-5 py-3 dark:bg-[#1B1C20]`,children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,p.jsxs)(`button`,{type:`button`,onClick:h,disabled:l,className:`flex h-8 flex-1 items-center justify-center gap-1.5 rounded-[4px] bg-[#24543F] text-[13px] font-medium text-white transition-colors hover:bg-[#1D4634] disabled:cursor-not-allowed disabled:opacity-50 dark:bg-[#3F7A5F] dark:hover:bg-[#4B8B6D]`,children:[l?(0,p.jsx)(U,{size:13,className:`animate-spin`}):(0,p.jsx)(ie,{size:13}),l?`运行中…`:`重跑此卡`]}),Ne?null:(0,p.jsxs)(`button`,{type:`button`,onClick:()=>f(`prev`),className:`${oW} flex items-center gap-1`,children:[(0,p.jsx)(F,{size:13}),`加上游`]}),(0,p.jsxs)(`button`,{type:`button`,onClick:()=>f(`next`),className:`${oW} flex items-center gap-1`,children:[(0,p.jsx)(j,{size:13}),`加下游`]})]}),(0,p.jsx)(`div`,{className:`mt-1 flex justify-end`,children:(0,p.jsxs)(`button`,{type:`button`,onClick:v,disabled:Ne,title:Ne?`根节点是对话入口(人格来源),不能删除`:void 0,className:`flex items-center gap-1.5 rounded-[4px] px-2.5 py-1.5 text-[12px] text-[#B4451F] transition-colors hover:bg-[#FBEFEA] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent dark:text-[#e08a6a] dark:hover:bg-[#2A1C17]`,children:[(0,p.jsx)(me,{size:13}),`删除此卡`]})})]})]})}function uW({title:e,extra:t,children:n}){return(0,p.jsxs)(`section`,{className:`mt-3 rounded-xl border p-3 first:mt-1 ${GU}`,children:[(0,p.jsxs)(`div`,{className:`mb-2.5 flex items-center justify-between gap-2`,children:[(0,p.jsx)(`h3`,{className:`text-[12px] font-semibold tracking-[0.01em] ${VU}`,children:e}),t]}),n]})}function dW({children:e}){return(0,p.jsx)(`p`,{className:`py-1 text-[12px] leading-[1.6] ${UU}`,children:e})}function fW(e,t,n){if(t===n)return!0;let r=new Set([t]),i=[t];for(;i.length;){let t=i.pop();for(let a of e)if(a.from===t){if(a.to===n)return!0;r.has(a.to)||(r.add(a.to),i.push(a.to))}}return!1}function pW(e){return e===`human`?`人工`:e===`jev`?`jev`:e===`self`?`自评`:e||`系统`}function mW(e){e&&(e.style.height=`auto`,e.style.height=`${e.scrollHeight}px`)}var{Text:hW}=PA;function gW({open:e,config:t,servers:n,onClose:r,onSaved:i,onError:a}){let o=t,[s,c]=(0,u.useState)(o?.mock??!1),[l,d]=(0,u.useState)(!1),[f,m]=(0,u.useState)(null),[h,g]=(0,u.useState)(!1),_=(0,u.useRef)(a);(0,u.useEffect)(()=>{_.current=a},[a]),(0,u.useEffect)(()=>{e&&c(o?.mock??!1)},[e,o?.mock]),(0,u.useEffect)(()=>{if(!e)return;let t=!1;return g(!0),JA.getBridge().then(e=>{t||m(e)}).catch(e=>{t||_.current(`读取模型通道状态失败:${e.message}`)}).finally(()=>{t||g(!1)}),()=>{t=!0}},[e]);async function v(){if(h)return;g(!0);let[e,t]=await Promise.allSettled([JA.getBridge(),JA.getModels(!0)]);e.status===`fulfilled`?m(e.value):_.current(`读取模型通道状态失败:${e.reason.message}`),t.status===`rejected`&&_.current(`重新读取模型目录失败:${t.reason.message}`),g(!1)}async function y(e){if(l||!t)return;let n=s;c(e),d(!0);try{let t=await JA.putConfig({mock:e}),n=typeof t?.mock==`boolean`?t.mock:e;c(n),i({mock:n})}catch(e){c(n),a(`切换 mock 失败:${e.message}`)}finally{d(!1)}}let b=Object.entries(o?.providers??{}),x=o?.mcpServers??n.map(e=>({name:e.name})),S=o?.skillDirs?.length?o.skillDirs:o?.dshPaths?.skills?[o.dshPaths.skills]:[],C=f?f.healthy?(0,p.jsx)(WO,{color:`success`,style:{marginInlineEnd:0},children:`已连接`}):(0,p.jsx)(WO,{color:`warning`,style:{marginInlineEnd:0},children:`未连接`}):(0,p.jsx)(hW,{type:`secondary`,style:{fontSize:12},children:`读取中…`}),w=f&&(f.lastError||f.reason)||``;return(0,p.jsxs)(PD,{open:e,title:`设置`,width:640,centered:!0,getContainer:()=>document.querySelector(`.af-canvas`)??document.body,onCancel:r,styles:{body:{maxHeight:`calc(100vh - 220px)`,overflowY:`auto`,paddingTop:12}},footer:(0,p.jsx)(oD,{justify:`flex-end`,children:(0,p.jsx)(VS,{onClick:r,children:`关闭`})}),children:[(0,p.jsx)(Vl,{type:`info`,showIcon:!0,title:`模型、MCP 服务器、技能都来自 DSH 的配置。要增删改请到 DSH 的 cordis.patch.yml,AgentFlow 这边只读。`,description:o?.dshPaths?.patch?(0,p.jsxs)(hW,{type:`secondary`,style:{fontSize:12,wordBreak:`break-all`},children:[`patch:`,(0,p.jsx)(hW,{code:!0,style:{fontSize:12},children:o.dshPaths.patch})]}):void 0}),(0,p.jsx)(_W,{title:`模型`,extra:(0,p.jsxs)(hW,{type:`secondary`,style:{fontSize:11},children:[b.length,` 个`]}),children:b.length===0?(0,p.jsx)(eb,{image:eb.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置模型提供商`}):b.map(([e,t])=>(0,p.jsx)(Rw,{size:`small`,style:{marginBottom:12},title:(0,p.jsx)(hW,{strong:!0,style:{fontSize:14},children:t.label||e}),extra:t.hasKey?(0,p.jsx)(WO,{color:`green`,style:{marginInlineEnd:0},children:`已配置 key`}):(0,p.jsx)(WO,{color:`red`,style:{marginInlineEnd:0},children:`缺 key`}),children:(0,p.jsx)(LE,{size:`small`,column:1,colon:!1,items:[{key:`provider`,label:`provider`,children:(0,p.jsx)(hW,{code:!0,children:e})},{key:`baseURL`,label:`baseURL`,children:(0,p.jsx)(hW,{code:!0,children:t.baseURL||`—`})},{key:`model`,label:`model`,children:(0,p.jsx)(hW,{code:!0,children:t.model||`—`})}]})},e))}),(0,p.jsxs)(_W,{title:`模型通道`,extra:(0,p.jsx)(VS,{size:`small`,loading:h,onClick:()=>void v(),children:`刷新`}),children:[f&&!f.healthy&&(0,p.jsx)(Vl,{type:`warning`,showIcon:!0,style:{marginBottom:10},title:`DSH 未运行或插件未加载,画布不能调模型`}),(0,p.jsx)(LE,{size:`small`,bordered:!0,column:1,colon:!1,items:[{key:`status`,label:`状态`,children:C},{key:`infoPath`,label:`发现文件`,children:(0,p.jsx)(hW,{code:!0,style:{fontSize:12,wordBreak:`break-all`,userSelect:`text`},title:f?.dir,children:f?.infoPath||`—`})},{key:`version`,label:`版本`,children:f?.version==null?`—`:(0,p.jsx)(hW,{code:!0,children:f.version})},{key:`startedAt`,label:`启动时间`,children:vW(f?.startedAt??null)},{key:`providers`,label:`provider 数`,children:f?String(f.providers):`—`},{key:`modelCount`,label:`模型数`,children:f?String(f.modelCount):`—`},{key:`lastError`,label:`最后错误`,children:w?(0,p.jsx)(hW,{type:`danger`,style:{fontSize:12,wordBreak:`break-all`},children:w}):(0,p.jsx)(hW,{type:`secondary`,children:`—`})}]})]}),(0,p.jsx)(_W,{title:`MCP 服务器`,extra:(0,p.jsxs)(hW,{type:`secondary`,style:{fontSize:11},children:[x.length,` 个`]}),children:x.length===0?(0,p.jsx)(eb,{image:eb.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置 MCP 服务器`}):(0,p.jsx)(LE,{size:`small`,bordered:!0,column:1,colon:!1,items:x.map(e=>({key:e.name,label:(0,p.jsx)(hW,{strong:!0,style:{fontSize:13},children:e.name}),children:e.kind?(0,p.jsx)(WO,{style:{marginInlineEnd:0},children:e.kind}):(0,p.jsx)(hW,{type:`secondary`,children:`—`})}))})}),(0,p.jsx)(_W,{title:`技能目录`,extra:(0,p.jsxs)(hW,{type:`secondary`,style:{fontSize:11},children:[S.length,` 个`]}),children:S.length===0?(0,p.jsx)(eb,{image:eb.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置技能目录`}):(0,p.jsx)(oD,{vertical:!0,gap:6,children:S.map(e=>(0,p.jsx)(hW,{code:!0,style:{fontSize:12,wordBreak:`break-all`},children:e},e))})}),(0,p.jsx)(_W,{title:`运行模式`,children:(0,p.jsx)(Rw,{size:`small`,children:(0,p.jsxs)(oD,{align:`center`,justify:`space-between`,gap:16,children:[(0,p.jsxs)(`div`,{style:{minWidth:0},children:[(0,p.jsx)(hW,{strong:!0,style:{display:`block`,fontSize:15},children:`mock 模式`}),(0,p.jsx)(hW,{type:`secondary`,style:{display:`block`,fontSize:12},children:`AgentFlow 自己的开关,不属于 DSH 配置。打开后不真正调用模型。`})]}),(0,p.jsx)(UD,{checked:s,loading:l,disabled:!t,onChange:e=>void y(e)})]})})})]})}function _W({title:e,extra:t,children:n}){return(0,p.jsxs)(`section`,{style:{marginTop:20},children:[(0,p.jsxs)(oD,{align:`center`,justify:`space-between`,gap:8,style:{marginBottom:8},children:[(0,p.jsx)(hW,{strong:!0,style:{fontSize:13},children:e}),t]}),n]})}function vW(e){if(typeof e!=`number`||!Number.isFinite(e)||e<=0)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`}var{Text:yW}=PA,bW=`'SFMono-Regular', Menlo, Consolas, 'Liberation Mono', ui-monospace, monospace`;function xW({open:e,boardId:t,boardName:n,onClose:r}){let{token:i}=ek.useToken(),[a,o]=(0,u.useState)(null),[s,c]=(0,u.useState)(null),[l,d]=(0,u.useState)(!1),[f,m]=(0,u.useState)(``),[h,g]=(0,u.useState)([]),[_,v]=(0,u.useState)(!1),[y,b]=(0,u.useState)(null),x=(0,u.useCallback)(async()=>{v(!0);try{let e=await JA.listCommands();g(e.commands)}catch{g([])}finally{v(!1)}},[]);(0,u.useEffect)(()=>{e&&(o(null),c(null),d(!1),m(``),x())},[e,x]);async function S(){if(!l){d(!0),c(null),o(null);try{let e=f.trim(),n=await JA.exportCommand(t,e||void 0);o(n),await x()}catch(e){let t=e.message||`未知错误`;c({title:t.includes(`HTTP 400`)?`生成失败(检查命令名)`:`生成失败`,detail:t})}finally{d(!1)}}}async function C(e){if(!y&&window.confirm(`删除命令 /${e}?删掉后 DSH 里立刻就不能用了。`)){b(e),c(null);try{await JA.deleteCommand(e),a?.name===e&&o(null),await x()}catch(e){c({title:`删除失败`,detail:e.message})}finally{b(null)}}}let w=h.filter(e=>!t||e.board===t),T={border:`1px solid ${i.colorBorderSecondary}`,borderRadius:8,background:i.colorFillTertiary,padding:`10px 12px`,fontFamily:bW,fontSize:12,lineHeight:1.7,whiteSpace:`pre-wrap`,wordBreak:`break-all`,color:i.colorText};return(0,p.jsxs)(PD,{open:e,title:`生成斜杠命令`,width:640,centered:!0,onCancel:r,styles:{body:{maxHeight:`calc(100vh - 240px)`,overflowY:`auto`}},footer:(0,p.jsxs)(oD,{justify:`flex-end`,gap:8,children:[(0,p.jsx)(VS,{onClick:r,children:`关闭`}),(0,p.jsx)(VS,{type:`primary`,icon:(0,p.jsx)(z,{size:14}),loading:l,onClick:()=>void S(),children:`生成`})]}),children:[(0,p.jsx)(Vl,{type:`info`,showIcon:!0,title:`把这张画布挂成一条 DSH 斜杠命令:生成后在对话里输入 /命令名,就能进入这张画布的工作流(无参数先看画布,带文字直接进流程)。命令即时生效,不用重启 DSH。`,style:{marginBottom:16}}),(0,p.jsxs)(`div`,{style:{marginBottom:12},children:[(0,p.jsx)(yW,{type:`secondary`,style:{fontSize:12},children:`当前画布:`}),(0,p.jsx)(yW,{strong:!0,style:{fontSize:12},children:n||t||`索引里的第一张画布`})]}),(0,p.jsxs)(`div`,{style:{marginBottom:16},children:[(0,p.jsx)(yW,{style:{fontSize:12,display:`block`,marginBottom:6},children:`命令名(可选)`}),(0,p.jsx)(AD,{value:f,onChange:e=>m(e.target.value),placeholder:`留空=按画布 id 自动生成(agentflow-…)`,maxLength:48,disabled:l}),(0,p.jsx)(yW,{type:`secondary`,style:{fontSize:11},children:`小写字母开头,只允许 a-z 0-9 _ -,不超过 48 个字符;同名会覆盖旧命令。`})]}),s&&(0,p.jsx)(Vl,{type:`error`,showIcon:!0,title:s.title,description:s.detail?(0,p.jsx)(yW,{style:{fontSize:12,fontFamily:bW,wordBreak:`break-all`},children:s.detail}):void 0,style:{marginBottom:16}}),a&&(0,p.jsxs)(`div`,{style:{marginBottom:16},children:[(0,p.jsx)(Vl,{type:`success`,showIcon:!0,title:a.replaced?`命令已更新(覆盖了同名旧命令)`:`命令已生成`,description:(0,p.jsxs)(`div`,{children:[(0,p.jsxs)(`div`,{style:{marginBottom:4},children:[`命令名:`,(0,p.jsxs)(yW,{code:!0,copyable:!0,style:{fontSize:12},children:[`/`,a.name]})]}),(0,p.jsxs)(`div`,{style:{marginBottom:4},children:[`用法:在 DSH 对话里输入 `,(0,p.jsxs)(yW,{code:!0,style:{fontSize:12},children:[`/`,a.name]}),`,回车即可。`]}),(0,p.jsx)(`div`,{style:{marginBottom:4},children:(0,p.jsx)(`b`,{children:`已即时生效,无需重启。`})}),(0,p.jsxs)(`div`,{children:[`文件:`,(0,p.jsx)(yW,{code:!0,copyable:!0,style:{fontSize:12,wordBreak:`break-all`},children:a.file})]})]})}),(0,p.jsx)(oD,{justify:`flex-end`,style:{marginTop:8},children:(0,p.jsx)(VS,{size:`small`,danger:!0,icon:(0,p.jsx)(me,{size:13}),loading:y===a.name,onClick:()=>void C(a.name),children:`删除命令`})})]}),(0,p.jsxs)(`div`,{children:[(0,p.jsxs)(oD,{align:`baseline`,justify:`space-between`,style:{marginBottom:6},children:[(0,p.jsx)(yW,{strong:!0,style:{fontSize:13},children:`这张画布已有的命令`}),(0,p.jsx)(yW,{type:`secondary`,style:{fontSize:11},children:_?`读取中…`:`${w.length} 条`})]}),w.length===0?(0,p.jsx)(`div`,{style:{...T,color:i.colorTextTertiary},children:_?`正在读取…`:`还没有命令,点右下角「生成」创建一条。`}):(0,p.jsx)(`div`,{style:{border:`1px solid ${i.colorBorderSecondary}`,borderRadius:8},children:w.map((e,t)=>(0,p.jsxs)(oD,{align:`center`,gap:8,style:{padding:`8px 12px`,borderTop:t===0?void 0:`1px solid ${i.colorBorderSecondary}`},children:[(0,p.jsxs)(yW,{code:!0,style:{fontSize:12},children:[`/`,e.name]}),(0,p.jsx)(yW,{type:`secondary`,style:{fontSize:11},children:SW(e.createdAt)}),(0,p.jsx)(`div`,{style:{marginLeft:`auto`},children:(0,p.jsx)(VS,{size:`small`,type:`text`,danger:!0,icon:(0,p.jsx)(me,{size:13}),loading:y===e.name,onClick:()=>void C(e.name),children:`删除`})})]},e.name))})]})]})}function SW(e){if(!e)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}var CW=`border-[#E3E4DF] dark:border-[#262724]`,wW=`text-[#1B1B18] dark:text-[#e8e8e4]`,TW=`text-[#6b6b66] dark:text-[#8b8b85]`,EW=`text-[#8b8b85] dark:text-[#8b8b85]`;function DW(){try{let e=globalThis.__AGENTFLOW_HOST__;return e&&typeof e==`object`?e:null}catch{return null}}function OW(){return DW()?.remote===!0}function kW(){let[e,t]=(0,u.useState)(`list`),[n,r]=(0,u.useState)([]),[i,a]=(0,u.useState)([]),[o,s]=(0,u.useState)({}),[c,l]=(0,u.useState)(!0),[d,f]=(0,u.useState)(null),[m,h]=(0,u.useState)(null),[g,_]=(0,u.useState)(``),[v,y]=(0,u.useState)(null),[b,x]=(0,u.useState)(null),[S,C]=(0,u.useState)(!1),[w,T]=(0,u.useState)(``),[E,D]=(0,u.useState)(!1),[O,k]=(0,u.useState)(null),[A,j]=(0,u.useState)(``),M=(0,u.useRef)(!1),P=(0,u.useRef)(!1),[F,I]=(0,u.useState)([]),[L,R]=(0,u.useState)([]),[B,H]=(0,u.useState)(null),[W,ee]=(0,u.useState)(null),[te,ne]=(0,u.useState)(null),[re,ie]=(0,u.useState)(!1),[ae,oe]=(0,u.useState)(!1),[se,J]=(0,u.useState)(!1),[le,ue]=(0,u.useState)(!1),de=(0,u.useRef)(!1),pe=(0,u.useRef)(!1),me=(0,u.useCallback)(()=>{pe.current=!0,J(!0)},[]),he=(0,u.useCallback)(()=>{pe.current=!1,J(!1)},[]),ge=(0,u.useRef)(0),_e=(0,u.useRef)(null);(0,u.useEffect)(()=>{_e.current=m},[m]),(0,u.useEffect)(()=>{if(!m||e!==`board`)return;let t=window.setTimeout(()=>{JA.putBoard(m.id,m).catch(e=>{console.warn(`[agentflow] 自动保存失败:`,e)}),r(e=>e.map(e=>e.id===m.id?{...e,presetOutdated:!0}:e))},200);return()=>window.clearTimeout(t)},[m,e]),(0,u.useEffect)(()=>{let e=()=>{let e=_e.current;if(e)try{fetch(WA(`/api/boards/${encodeURIComponent(e.id)}`),{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({board:e}),keepalive:!0}).catch(()=>{})}catch{}};return window.addEventListener(`pagehide`,e),()=>window.removeEventListener(`pagehide`,e)},[]);let[Y,ve]=(0,u.useState)(()=>{let e=DW();if(e?.remote){if(e.theme===`dark`)return!0;if(e.theme===`light`)return!1;try{return window.matchMedia(`(prefers-color-scheme: dark)`).matches}catch{return!1}}try{localStorage.removeItem(`agentflow-theme`)}catch{}try{let e=sessionStorage.getItem(`agentflow-theme`);if(e===`dark`)return!0;if(e===`light`)return!1}catch{}try{let e=new URLSearchParams(window.location.search).get(`theme`);if(e===`dark`)return!0;if(e===`light`)return!1}catch{}try{return window.matchMedia(`(prefers-color-scheme: dark)`).matches}catch{return!1}});(0,u.useEffect)(()=>{if(OW())window.dispatchEvent(new Event(`themechange`));else{document.documentElement.classList.toggle(`dark`,Y);try{sessionStorage.setItem(`agentflow-theme`,Y?`dark`:`light`)}catch{}window.dispatchEvent(new Event(`themechange`))}},[Y]),(0,u.useEffect)(()=>{if(!OW())return;let e=e=>{let t=e.detail?.theme;t===`dark`?ve(!0):t===`light`&&ve(!1)};return window.addEventListener(`agentflow-theme`,e),()=>window.removeEventListener(`agentflow-theme`,e)},[]);let[ye,be]=(0,u.useState)(null),xe=(0,u.useRef)(null),X=(0,u.useCallback)((e,t=`ok`)=>{be({msg:e,kind:t}),xe.current&&window.clearTimeout(xe.current),xe.current=window.setTimeout(()=>be(null),3200)},[]),Se=(0,u.useCallback)((e,t)=>{h(n=>n&&{...n,nodes:n.nodes.map(n=>n.id===e?{...n,...t}:n)})},[]),Ce=(0,u.useRef)(null),we=(0,u.useRef)(null);(0,u.useEffect)(()=>{if(Ce.current=d,OW()&&d)try{window.dispatchEvent(new CustomEvent(`agentflow-board-active`,{detail:{boardId:d}}))}catch{}},[d]),(0,u.useEffect)(()=>{_(m?.name??``)},[m?.id,m?.name]);let Te=(0,u.useCallback)(async(e=!1)=>{e||l(!0);let[t,n]=await Promise.allSettled([JA.listBoards(),JA.listPresets()]);if(t.status===`fulfilled`){let e=t.value.boards;r(e);let n=await Promise.allSettled(e.map(e=>JA.getBoard(e.id))),i={};n.forEach((t,n)=>{t.status===`fulfilled`&&(i[e[n].id]=jW(t.value.board))}),s(i)}else X(`加载画布列表失败:${t.reason.message}`,`err`);n.status===`fulfilled`?a(n.value.presets):X(`加载预设列表失败:${n.reason.message}`,`err`),e||l(!1)},[X]);(0,u.useEffect)(()=>{Te(),JA.getSkills().then(e=>I(e.skills)).catch(()=>{}),JA.getMcp().then(e=>R(e.servers)).catch(()=>{}),JA.getConfig().then(H).catch(()=>{}),JA.getModels().then(ee).catch(()=>{}),JA.getBridge().then(ne).catch(()=>{})},[Te]);let Ee=(0,u.useRef)(0);(0,u.useEffect)(()=>{v&&(Date.now()-Ee.current<3e4||(Ee.current=Date.now(),JA.getModels(!0).then(ee).catch(()=>{}),JA.getBridge().then(ne).catch(()=>{})))},[v]);let{running:De,run:Oe,stop:ke}=YA((0,u.useCallback)(e=>{let t=we.current!=null&&Ce.current!==we.current;if((e.type===`run:end`||e.type===`run:error`)&&(we.current=null),!t)switch(e.type){case`node:start`:Se(e.id,{status:`running`});break;case`node:delta`:h(t=>t&&{...t,nodes:t.nodes.map(t=>t.id===e.id?{...t,delta:(t.delta||``)+e.chunk}:t)});break;case`node:done`:Se(e.id,{status:e.status??`done`,content:e.content,usage:e.usage,verdict:e.verdict??null,error:null,delta:void 0});break;case`node:failed`:Se(e.id,{status:`failed`,error:`该节点所有模型都失败`});break;case`node:blocked`:Se(e.id,{status:`blocked`});break;case`node:retry`:h(t=>t&&{...t,nodes:t.nodes.map(t=>t.id===e.id?{...t,delta:void 0}:t)}),X(`${e.id} 换 ${e.model} 重试:${e.error}`,`err`);break;case`run:end`:{let{done:t,failed:n,blocked:r,review:i}=e.summary,a=[`完成 ${t.length}`];i.length&&a.push(`待确认 ${i.length}`),n.length&&a.push(`失败 ${n.length}`),r.length&&a.push(`阻塞 ${r.length}`),X(a.join(`,`),n.length||r.length?`err`:`ok`);break}case`run:error`:X(`运行出错:${e.error}`,`err`)}},[Se,X])),Ae=(0,u.useCallback)(e=>{let t=Ce.current;t&&(we.current=t,Oe(e,t))},[Oe]),je=(0,u.useCallback)(()=>{we.current=null,ke()},[ke]),Me=(0,u.useCallback)(async e=>{let n=++ge.current;t(`board`),f(e),h(null),_(``),y(null),oe(!1),he();let r=await JA.getBoard(e).then(e=>({status:`fulfilled`,value:e})).catch(e=>({status:`rejected`,reason:e}));n===ge.current&&(r.status===`rejected`?(X(`打开画布失败:${r.reason.message}`,`err`),t(`list`),f(null),he(),Te(!0)):h(r.value.board))},[Te,X]),Ne=(0,u.useRef)((()=>{let e=DW();return e?.remote&&e.boardId?e.boardId:typeof window>`u`?null:new URLSearchParams(window.location.search).get(`board`)})());(0,u.useEffect)(()=>{let e=Ne.current;e&&(Ne.current=null,Me(e))},[Me]),(0,u.useEffect)(()=>{if(!OW())return;let e=e=>{let t=e.detail?.boardId;t&&t!==Ce.current&&Me(t)};return window.addEventListener(`agentflow-board`,e),()=>window.removeEventListener(`agentflow-board`,e)},[Me]);let Pe=(0,u.useCallback)(()=>{ge.current+=1,t(`list`),h(null),f(null),y(null),oe(!1),he(),Te(!0)},[Te]);function Fe(){Pe()}function Ie(e){Me(e)}let Le=(0,u.useCallback)(async()=>{let e=_e.current;if(!e)return!1;try{return await JA.putBoard(e.id,e),he(),!0}catch(e){return X(`保存画布失败:${e.message}`,`err`),!1}},[X,he]),Re=(0,u.useCallback)(async()=>{let e=_e.current;if(!e||de.current)return!1;de.current=!0,ue(!0);try{return await JA.putBoard(e.id,e),he(),r(t=>t.map(t=>t.id===e.id?{...t,name:e.name,nodeCount:e.nodes.length,presetOutdated:!1,updatedAt:Date.now()}:t)),X(`已保存`),!0}catch(e){return X(`保存失败:${e.message}`,`err`),!1}finally{de.current=!1,ue(!1)}},[X,he]);(0,u.useEffect)(()=>{let t=t=>{(t.metaKey||t.ctrlKey)&&String(t.key).toLowerCase()===`s`&&(t.preventDefault(),e===`board`&&window.setTimeout(()=>void Re(),0))};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[Re,e]);let ze=(0,u.useCallback)(async e=>{m&&(!pe.current||await Le())&&Ae(e)},[m,Le,Ae]),Be=(0,u.useCallback)(async()=>{m&&(!pe.current||await Le())&&oe(!0)},[m,Le]),Ve=(0,u.useCallback)((e,t)=>{Se(e,t),me()},[Se]),He=(0,u.useCallback)(e=>{h(t=>t&&{...t,edges:e}),me()},[]),Ue=(0,u.useCallback)((e,t,n)=>{m&&(h({...m,nodes:m.nodes.map(r=>r.id===e?{...r,x:t,y:n}:r)}),me())},[m]),We=(0,u.useCallback)((e,t)=>{if(!m)return;let n=m.nodes.find(t=>t.id===e);if(!n)return;let r=W?.providers.find(e=>e.models.length),i=n.provider||r?.id||``,a=n.model||r?.models[0]?.id||``,o=AW(m.nodes),s={id:o,label:t===`next`?`下游卡片`:`上游卡片`,type:`llm`,x:t===`next`?n.x+360:n.x-360,y:n.y,provider:i,model:a,reasoningEffort:``,fallback:[],fallbackEfforts:{},task:``,criteria:``,skills:[],tools:[],verify:``,content:``,status:`idle`,usage:null,error:null,verdict:null};h({...m,nodes:[...m.nodes,s],edges:[...m.edges,t===`next`?{from:e,to:o}:{from:o,to:e}]}),y(o),me(),X(t===`next`?`已派生下游卡片(未保存)`:`已添加上游卡片(未保存)`)},[m,W,X]),Ge=(0,u.useCallback)((e,t)=>{m&&e!==t&&(m.nodes.find(e=>e.id===t)?.type===`orchestrator`?X(`根节点是对话入口,不能有上游节点`,`err`):m.edges.some(n=>n.from===e&&n.to===t)||(NW(m.edges,e,t)?X(`这条连线会形成环,已忽略`,`err`):(h({...m,edges:[...m.edges,{from:e,to:t}]}),me())))},[m,X]),Ke=(0,u.useCallback)(e=>{m&&(h({...m,nodes:m.nodes.filter(t=>t.id!==e),edges:m.edges.filter(t=>t.from!==e&&t.to!==e)}),y(null),me(),X(`已删除(未保存)`))},[m,X]),qe=(0,u.useCallback)(async(e,t)=>{if(!pe.current||await Le())try{let n=await JA.verify(e,t,void 0,Ce.current);Se(e,{status:n.status,verdict:n.verdict}),X(t?`已通过`:`已打回,可以改完再跑`)}catch(e){X(`操作失败:${e.message}`,`err`)}},[Se,X,Le]),Je=(0,u.useMemo)(()=>m?.nodes.find(e=>e.id===v)??null,[m,v]),Ye=(0,u.useMemo)(()=>new Set(n.map(e=>e.presetId).filter(e=>!!e)),[n]),Xe=(0,u.useMemo)(()=>i.filter(e=>!Ye.has(e.id)),[i,Ye]);function Ze(){T(``),C(!0)}async function Qe(){let e=w.trim();if(e&&!E){D(!0);try{let n=await JA.createBoard({name:e});ge.current+=1,C(!1),T(``),h(n.board),f(n.board.id),y(null),he(),t(`board`),Te(!0)}catch(e){X(`新建画布失败:${e.message}`,`err`)}finally{D(!1)}}}async function $e(e){if(!b){x(e.id);try{let n=await JA.importPreset(e.id);X(n.reused?`已有这张画布:${e.name}`:`已从预设创建画布:${e.name}`),ge.current+=1,h(n.board),f(n.board.id),y(null),he(),t(`board`),Te(!0)}catch(e){let t=e.message;t.includes(`HTTP 501`)?X(`创建画布功能还没上线(服务端 P1 未完成)`,`err`):X(`创建画布失败:${t}`,`err`)}finally{x(null)}}}function et(e){k(e.id),j(e.name)}async function tt(e){if(O!==e.id)return;let t=M.current;if(M.current=!1,k(null),t){j(e.name);return}let n=A.trim();if(n&&n!==e.name)try{let t=await JA.patchBoard(e.id,{name:n});r(r=>r.map(r=>r.id===e.id?{...r,name:n,updatedAt:t.meta?.updatedAt??r.updatedAt}:r)),m?.id===e.id&&h(e=>e&&{...e,name:n}),X(`画布已重命名`)}catch(e){X(`重命名失败:${e.message}`,`err`)}}async function nt(e){if(n.length<=1)X(`至少要保留一张画布`,`err`);else if(window.confirm(`删除画布《${e.name}》?里面的节点会一起删掉,且不可恢复。`))try{await JA.deleteBoard(e.id),X(`画布已删除`),await Te(!0)}catch(e){X(`删除失败:${e.message}`,`err`)}}async function rt(){if(!m)return;let e=P.current;if(P.current=!1,e){_(m.name);return}let t=g.trim();if(!t)_(m.name);else if(t!==m.name)try{let e=await JA.patchBoard(m.id,{name:t});h(e=>e&&{...e,name:t}),r(n=>n.map(n=>n.id===m.id?{...n,name:t,updatedAt:e.meta?.updatedAt??n.updatedAt}:n)),X(`画布已重命名`)}catch(e){_(m.name),X(`重命名失败:${e.message}`,`err`)}}let it=(0,u.useRef)(null);return(0,p.jsx)(Md,{locale:UA.default,getPopupContainer:()=>it.current??document.body,theme:{algorithm:Y?ek.darkAlgorithm:ek.defaultAlgorithm,token:{colorPrimary:`#24543F`,borderRadius:7,fontSize:15,fontFamily:`-apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', ui-sans-serif, sans-serif`},components:{Drawer:{paddingLG:20},Modal:{borderRadiusLG:12},Card:{borderRadiusLG:10}}},children:(0,p.jsxs)(`div`,{ref:it,className:`af-canvas flex h-full flex-col${Y?` dark`:``}`,children:[e===`list`?(0,p.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-3 border-b ${CW} bg-[#FCFCFA] px-5 dark:bg-[#17181b]`,children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`grid h-7 w-7 place-items-center rounded-[4px] bg-[#24543F] text-white`,children:`◈`}),(0,p.jsx)(`span`,{className:`text-[17px] font-semibold tracking-tight ${wW}`,children:`AgentFlow`})]}),(0,p.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,p.jsx)(VS,{type:`primary`,icon:(0,p.jsx)(K,{size:14}),onClick:Ze,children:`新建画布`}),(0,p.jsx)(VS,{icon:Y?(0,p.jsx)(fe,{size:14}):(0,p.jsx)(G,{size:14}),onClick:()=>ve(e=>!e),title:Y?`切到浅色`:`切到深色`}),(0,p.jsx)(VS,{icon:(0,p.jsx)(ce,{size:14}),onClick:()=>ie(!0),children:`设置`})]})]}):(0,p.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b ${CW} bg-[#FCFCFA] px-4 dark:bg-[#17181b]`,children:[(0,p.jsxs)(`button`,{type:`button`,onClick:Fe,title:`返回画布列表`,className:`flex shrink-0 items-center gap-1 rounded-[4px] px-2 py-1.5 text-[12px] transition-colors hover:bg-[#EFEFEA] dark:hover:bg-[#232421] ${TW}`,children:[(0,p.jsx)(N,{size:14}),`返回列表`]}),(0,p.jsx)(`div`,{className:`h-5 w-px shrink-0 bg-[#E3E4DF] dark:bg-[#2c2d29]`}),(0,p.jsx)(`input`,{value:g,onChange:e=>_(e.target.value),onBlur:()=>void rt(),onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur(),e.key===`Escape`&&(P.current=!0,e.currentTarget.blur())},disabled:!m,placeholder:`画布名称`,"aria-label":`画布名称`,className:`min-w-0 max-w-[280px] flex-1 rounded-[3px] border-0 bg-transparent px-1 py-1 text-[16px] font-semibold tracking-tight outline-none placeholder:text-[#a8a8a0] focus-visible:ring-2 focus-visible:ring-[#24543F]/30 disabled:bg-transparent dark:placeholder:text-[#6f6f68] dark:focus-visible:ring-[#6aa583]/40 ${wW}`}),se&&(0,p.jsx)(`span`,{title:`有未保存的修改`,"aria-label":`有未保存的修改`,className:`h-1.5 w-1.5 shrink-0 rounded-full bg-[#B4451F] dark:bg-[#e08a6a]`}),(0,p.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,p.jsx)(VS,{icon:(0,p.jsx)(q,{size:14}),disabled:!m,loading:le,onClick:()=>void Re(),title:`保存画布并更新预设(⌘S / Ctrl+S)`,children:`保存`}),De?(0,p.jsx)(VS,{danger:!0,icon:(0,p.jsx)(U,{size:14,className:`animate-spin`}),onClick:je,children:`停止`}):(0,p.jsx)(VS,{type:`primary`,icon:(0,p.jsx)(V,{size:14}),disabled:!m,onClick:()=>void ze(),title:`先保存,再跑一遍验证(会真实调用模型)`,children:`验证 AgentFlow`}),(0,p.jsx)(VS,{icon:(0,p.jsx)(z,{size:14}),disabled:!m,onClick:()=>void Be(),children:`生成命令`}),(0,p.jsx)(VS,{icon:Y?(0,p.jsx)(fe,{size:14}):(0,p.jsx)(G,{size:14}),onClick:()=>ve(e=>!e),title:Y?`切到浅色`:`切到深色`}),(0,p.jsx)(VS,{icon:(0,p.jsx)(ce,{size:14}),onClick:()=>ie(!0),children:`设置`})]})]}),e===`list`?(0,p.jsx)(`main`,{className:`min-h-0 flex-1 overflow-y-auto bg-[#F4F5F2] px-6 py-7 dark:bg-[#111214]`,children:(0,p.jsxs)(`div`,{className:`mx-auto w-full max-w-[1080px]`,children:[(0,p.jsxs)(`div`,{className:`mb-5`,children:[(0,p.jsx)(`h1`,{className:`text-[20px] font-semibold tracking-tight ${wW}`,children:`画布`}),(0,p.jsx)(`p`,{className:`mt-1 text-[12px] leading-[1.6] ${TW}`,children:`每张画布对应一个 DSH 预设;编辑会自动保存,点「保存」才会更新/生成预设。`})]}),c&&n.length===0?(0,p.jsx)(`div`,{className:`py-16 text-center text-[13px] ${TW}`,children:`正在加载画布…`}):(0,p.jsxs)(p.Fragment,{children:[n.length===0?(0,p.jsx)(`div`,{className:`rounded-[8px] border border-dashed ${CW} py-14 text-center text-[13px] ${TW}`,children:`还没有画布,点右上角「新建画布」开始。`}):(0,p.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3`,children:n.map(e=>{let t=e.presetId?i.find(t=>t.id===e.presetId):null;return(0,p.jsxs)(`article`,{className:`flex min-h-[150px] flex-col rounded-[8px] border ${CW} bg-[#FCFCFA] p-4 dark:bg-[#17181B]`,children:[(0,p.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,p.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[O===e.id?(0,p.jsx)(AD,{size:`small`,autoFocus:!0,maxLength:60,value:A,onChange:e=>j(e.target.value),onBlur:()=>void tt(e),onPressEnter:e=>e.currentTarget.blur(),onKeyDown:e=>{e.key===`Escape`&&(M.current=!0,e.currentTarget.blur())},"aria-label":`重命名画布 ${e.name}`}):(0,p.jsx)(`button`,{type:`button`,onClick:()=>Ie(e.id),title:e.name,className:`block max-w-full text-left`,children:(0,p.jsx)(`h2`,{className:`truncate text-[15px] font-semibold ${wW}`,children:e.name})}),(0,p.jsxs)(`p`,{className:`mt-1 text-[11px] leading-[1.6] ${EW}`,children:[e.nodeCount,` 个节点 · 更新于 `,MW(e.updatedAt)]}),o[e.id]!==void 0&&(0,p.jsxs)(`p`,{className:`mt-0.5 truncate text-[11px] leading-[1.6] ${TW}`,title:o[e.id]||`没有调度卡,首次导出会自动补一张`,children:[`对话入口:`,o[e.id]||`未设置(首次导出会自动补一张调度卡)`]})]}),(0,p.jsxs)(`div`,{className:`flex shrink-0 flex-col items-end gap-1`,children:[(0,p.jsx)(WO,{color:t?`blue`:`default`,style:{marginInlineEnd:0},children:t?t.name:`自定义`}),e.presetOutdated&&(0,p.jsx)(WO,{color:`orange`,style:{marginInlineEnd:0},children:`预设未更新`}),e.hasDraft&&(0,p.jsx)(WO,{color:`gold`,style:{marginInlineEnd:0},children:`草稿`})]})]}),(0,p.jsxs)(`div`,{className:`mt-auto flex flex-wrap items-center gap-1 pt-3`,children:[(0,p.jsx)(VS,{size:`small`,type:`primary`,onClick:()=>Ie(e.id),children:`编辑`}),(0,p.jsx)(VS,{size:`small`,type:`text`,onClick:()=>et(e),children:`重命名`}),(0,p.jsx)(VS,{size:`small`,type:`text`,danger:!0,disabled:n.length<=1,title:n.length<=1?`至少要保留一张画布`:void 0,onClick:()=>void nt(e),children:`删除`})]})]},e.id)})}),Xe.length>0&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`div`,{className:`mb-3 mt-8 flex flex-wrap items-baseline gap-2`,children:[(0,p.jsx)(`h2`,{className:`text-[13px] font-semibold ${wW}`,children:`还没有画布的预设`}),(0,p.jsx)(`span`,{className:`text-[11px] ${EW}`,children:`从预设生成一张单卡片画布,再继续编辑`})]}),(0,p.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3`,children:Xe.map(e=>(0,p.jsxs)(`article`,{className:`flex min-h-[150px] flex-col rounded-[8px] border border-dashed ${CW} bg-[#F9F9F6] p-4 dark:bg-[#151617]`,children:[(0,p.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,p.jsx)(`h2`,{className:`min-w-0 flex-1 truncate text-[15px] font-semibold ${wW}`,title:e.name,children:e.name}),(0,p.jsx)(WO,{style:{marginInlineEnd:0,flexShrink:0},children:e.source===`bundle`?`bundle`:`自定义`})]}),(0,p.jsx)(`p`,{className:`mt-1 line-clamp-3 text-[12px] leading-[1.6] ${TW}`,children:e.description||`没有描述`}),(0,p.jsx)(`div`,{className:`mt-auto pt-3`,children:(0,p.jsx)(VS,{size:`small`,loading:b===e.id,onClick:()=>void $e(e),children:`创建画布`})})]},e.id))})]})]})]})}):(0,p.jsxs)(`main`,{className:`relative min-h-0 flex-1`,children:[(0,p.jsxs)(`div`,{className:`pointer-events-none absolute left-4 top-[12px] z-10 flex items-center gap-1.5 rounded-[4px] bg-[#FCFCFA]/90 px-2 py-1 text-[11px] text-[#6b6b66] dark:bg-[#17181b]/90 dark:text-[#8b8b85]`,children:[(0,p.jsx)(`span`,{className:`h-[5px] w-[5px] rounded-full`,style:{background:B?B.mock?`#B4451F`:`#24543F`:`#b9bcb4`}}),B?B.mock?`mock`:`real`:`连接中`]}),m?(0,p.jsx)(BU,{board:m,selectedId:v,running:De,onSelect:y,onMove:Ue,onDerive:We,onConnect:Ge}):(0,p.jsx)(`div`,{className:`grid h-full place-items-center text-[13px] text-[#8a93a3]`,children:`正在加载画布…`})]}),e===`board`&&m&&Je&&(0,p.jsx)(sW,{node:Je,nodes:m.nodes,edges:m.edges,boardId:m.id,skills:F,servers:L,catalog:W,bridge:te,running:De,onPatch:e=>Ve(Je.id,e),onDerive:e=>We(Je.id,e),onVerify:e=>void qe(Je.id,e),onEdgesChange:He,onRefreshModels:()=>{Ee.current=Date.now(),JA.getModels(!0).then(ee).catch(e=>X(`刷新模型失败:${e.message}`,`err`)),JA.getBridge().then(ne).catch(()=>{})},onRerun:()=>void ze([Je.id]),onDelete:()=>void Ke(Je.id),onClose:()=>y(null)}),(0,p.jsx)(gW,{open:re,config:B,servers:L,onClose:()=>ie(!1),onSaved:e=>{H(t=>t&&{...t,mock:e.mock}),JA.getMcp().then(e=>R(e.servers)).catch(()=>{}),X(`设置已保存`)},onError:e=>X(e,`err`)}),(0,p.jsx)(xW,{open:ae,boardId:d,boardName:g,onClose:()=>oe(!1)}),(0,p.jsx)(PD,{open:S,title:`新建画布`,centered:!0,getContainer:()=>it.current??document.body,okText:`创建`,cancelText:`取消`,confirmLoading:E,okButtonProps:{disabled:!w.trim()},onOk:()=>void Qe(),onCancel:()=>C(!1),children:(0,p.jsx)(AD,{autoFocus:!0,maxLength:60,placeholder:`画布名称,例如「活动文案」`,value:w,onChange:e=>T(e.target.value),onPressEnter:()=>{w.trim()&&!E&&Qe()}})}),ye&&(0,p.jsx)(`div`,{className:`absolute bottom-6 left-1/2 z-50 -translate-x-1/2 rounded-lg px-4 py-2 text-[13px] shadow-lg ${ye.kind===`err`?`bg-[#ffebee] text-[#c62828] dark:bg-[#3a1b1f] dark:text-[#ff9a9a]`:`bg-[#1C1C1A] text-white dark:bg-[#e7e9ee] dark:text-[#0f1116]`}`,children:ye.msg})]})})}function AW(e){let t=`n-${Date.now().toString(36)}`,n=t,r=2;for(;e.some(e=>e.id===n);)n=`${t}-${r++}`;return n}function jW(e){let t=e.nodes.find(e=>e.type===`orchestrator`)??(e.nodes.length===1?e.nodes[0]:null);return t?t.label||t.id:null}function MW(e){if(!e)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}function NW(e,t,n){let r=new Set,i=[n];for(;i.length;){let n=i.pop();if(n===t)return!0;if(!r.has(n)){r.add(n);for(let t of e)t.from===n&&i.push(t.to)}}return!1}var PW=`http://127.0.0.1:8791`;function FW(e){return String(e??``).trim().replace(/\/+$/,``)}function IW(e){let t=FW(e);return t&&(PW=t),PW}function LW(){return PW}function RW(){try{if(document.body&&document.body.hasAttribute(`data-ds-dark-theme`))return`dark`}catch{}try{if(document.documentElement.classList.contains(`dark`))return`dark`}catch{}try{if(window.matchMedia&&window.matchMedia(`(prefers-color-scheme: dark)`).matches)return`dark`}catch{}return`light`}function zW(e){let t=RW(),n=()=>{let n=RW();n!==t&&(t=n,e(n))},r=[];try{if(typeof MutationObserver<`u`){let e=new MutationObserver(n);document.body&&(e.observe(document.body,{attributes:!0,attributeFilter:[`data-ds-dark-theme`,`class`]}),r.push(e));let t=new MutationObserver(n);t.observe(document.documentElement,{attributes:!0,attributeFilter:[`class`,`data-theme`]}),r.push(t)}}catch{}let i=null,a=()=>n();try{i=window.matchMedia(`(prefers-color-scheme: dark)`),i.addEventListener(`change`,a)}catch{i=null}return window.addEventListener(`focus`,n),()=>{for(let e of r)e.disconnect();if(i)try{i.removeEventListener(`change`,a)}catch{}window.removeEventListener(`focus`,n)}}var BW=`__AGENTFLOW_HOST__`,VW=`data-agentflow-style`,HW=[0,1e3,2500],UW=6e3,WW=2e3;function GW(){try{let e=globalThis[BW];return e&&typeof e==`object`?e:null}catch{return null}}function KW(e){let t={apiBase:e.apiBase,theme:e.theme,boardId:e.boardId,remote:!0};return globalThis[BW]=t,t}var qW=`
|
|
339
|
+
`,aW=`w-full rounded-lg border border-[#E1E2DD] bg-[#FCFCFA] px-2.5 py-2 text-[13px] leading-[1.65] text-[#1B1B18] outline-none transition-colors placeholder:text-[#9a9a92] focus:border-[#24543F] focus:bg-white dark:border-[#33353B] dark:bg-[#17181B] dark:text-[#EDEDE8] dark:focus:border-[#6aa583] dark:focus:bg-[#1B1C20]`,oW=`rounded-[4px] px-2.5 py-1.5 text-[12px] text-[#5b6472] transition-colors hover:bg-[#EFEFEA] dark:text-[#a3a39b] dark:hover:bg-[#232421]`;function sW(e){return(0,p.jsxs)(`aside`,{className:`af-panel absolute bottom-0 right-0 top-14 z-30 flex w-[420px] flex-col border-l border-[#E3E4DF] bg-[#FCFCFA] dark:border-[#262724] dark:bg-[#17181B]`,role:`complementary`,"aria-label":`节点详情`,children:[(0,p.jsx)(`style`,{children:iW}),(0,p.jsx)(lW,{...e},e.node.id)]})}function cW(e,...t){let n=e.trim().toLowerCase();return!n||t.some(e=>String(e??``).toLowerCase().includes(n))}function lW(e){let{node:t,nodes:n,edges:r,boardId:i,skills:a,servers:o,catalog:s,bridge:c,running:l,onPatch:d,onDerive:f,onVerify:m,onRerun:h,onRefreshModels:g,onEdgesChange:_,onDelete:v,onClose:y}=e,[b,x]=(0,u.useState)(t.label),[S,C]=(0,u.useState)(t.task),[w,T]=(0,u.useState)(t.criteria),[E,D]=(0,u.useState)(QU),[O,k]=(0,u.useState)(0),[A,M]=(0,u.useState)(``),[N,P]=(0,u.useState)(``),[I,L]=(0,u.useState)(null),R=(0,u.useRef)(null),z=(0,u.useRef)(null);(0,u.useEffect)(()=>{mW(R.current)},[S]),(0,u.useEffect)(()=>{mW(z.current)},[w]);let B=(0,u.useRef)(d);(0,u.useEffect)(()=>{B.current=d},[d]);let V=(0,u.useRef)({}),H=(0,u.useRef)(null),W=(0,u.useCallback)(()=>{H.current!==null&&(window.clearTimeout(H.current),H.current=null);let e=V.current;Object.keys(e).length&&(V.current={},B.current(e))},[]),G=(0,u.useCallback)(e=>{V.current={...V.current,...e},H.current!==null&&window.clearTimeout(H.current),H.current=window.setTimeout(W,400)},[W]);(0,u.useEffect)(()=>()=>{if(H.current!==null){window.clearTimeout(H.current),H.current=null;let e=V.current;Object.keys(e).length&&B.current(e)}},[]),(0,u.useEffect)(()=>{let e=e=>{(e.metaKey||e.ctrlKey)&&String(e.key).toLowerCase()===`s`&&W()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[W]);let[ee,te]=(0,u.useState)(r);(0,u.useEffect)(()=>{te(r)},[r]);let ne=new Set(ee.filter(e=>e.to===t.id).map(e=>e.from)),K=n.filter(e=>e.id!==t.id);function re(e){let n=[...ee.filter(e=>e.to!==t.id),...e.map(e=>({from:e,to:t.id}))];te(n),_(n)}function ae(e,n){let r=new Set(t.skills);n?r.add(e):r.delete(e),d({skills:[...r]})}let q=s?.providers??[],oe=t.provider&&t.model?`${t.provider}/${t.model}`:``,J=q.some(e=>e.id===t.provider&&e.models.some(e=>e.id===t.model)),ce=t.model&&!J?t.model:``,le=J?q.find(e=>e.id===t.provider)?.models.find(e=>e.id===t.model)??null:null,ue=le?.levels??[],de=le?.defaultLevel??``,fe=q.every(e=>!e.models.length),pe=new Set,he=[];for(let e of E){let{provider:t,model:n}=eW(e.value),r=q.find(e=>e.id===t),i=r?.models.find(e=>e.id===n);r&&i&&!pe.has(e.value)&&(pe.add(e.value),he.push({title:i.name,label:`${r.label} · ${i.name}`,value:`${YU}${e.value}`}))}let ge=[];he.length&&ge.push({title:`最近使用`,label:`最近使用`,value:qU,selectable:!1,children:he}),ce&&ge.push({title:`当前值`,label:`当前值`,value:JU,selectable:!1,children:[{title:ce,label:tW(t.provider,ce),value:KU}]});for(let e of q){let t=e.models.length;ge.push({title:t?`${e.label}(${t})`:e.label,label:e.label,value:`p:${e.id}`,selectable:!1,children:e.error?[{title:e.error,label:e.error,value:`e:${e.id}`,disabled:!0}]:e.models.map(t=>({title:t.name,label:`${e.label} · ${t.name}`,value:`${e.id}/${t.id}`}))})}let _e=q.find(e=>e.id===t.provider),ve=E.map(e=>e.provider).find(e=>q.some(t=>t.id===e)),ye=_e?.id??ve??``,be=[...he.length?[qU]:[],...ce?[JU]:[],...ye?[`p:${ye}`]:[]],xe=J?oe:ce?KU:void 0,X=t.fallback??[],Se=t.fallbackEfforts??{},Ce=new Set(X),we=q.map(e=>{let t=e.models.length,n=e.error?[{title:e.error,label:e.error,value:`e:${e.id}`,disabled:!0}]:e.models.filter(t=>{let n=`${e.id}/${t.id}`;return n!==oe&&!Ce.has(n)}).map(t=>({title:t.name,label:`${e.label} · ${t.name}`,value:`${e.id}/${t.id}`}));return{title:t?`${e.label}(${t})`:e.label,label:e.label,value:`p:${e.id}`,selectable:!1,children:n}}).filter(e=>e.children.length>0),Te=ye?[`p:${ye}`]:[];function Ee(e){if(!e||e===KU)return;let n=e.startsWith(YU)?e.slice(2):e,{provider:r,model:i}=eW(n),a=q.find(e=>e.id===r),o=a?.models.find(e=>e.id===i);if(!a||!o)return;let s=o.levels.includes(t.reasoningEffort??``)?t.reasoningEffort??``:``,c={value:n,label:o.name,provider:r},l=[c,...E.filter(e=>e.value!==c.value)].slice(0,ZU);D(l),$U(l),d({provider:r,model:i,reasoningEffort:s})}function De(e){let{provider:t,model:n}=eW(e),r=q.find(e=>e.id===t),i=r?.models.find(e=>e.id===n);return!r||!i?{label:`${e}(不在 DSH 目录里)`,levels:[]}:{label:`${r.label} · ${i.name}`,levels:i.levels}}function Oe(e,t){d({fallback:e,fallbackEfforts:t})}function ke(e){e&&e.includes(`/`)&&!Ce.has(e)&&(Oe([...X,e],{...Se,[e]:``}),k(e=>e+1))}function Ae(e){let t={...Se};delete t[e],Oe(X.filter(t=>t!==e),t)}function je(e,t){Oe(X,{...Se,[e]:t})}let Me=nW[t.status]??nW.idle,Ne=t.type===`orchestrator`,Pe=n.some(e=>e.id!==t.id&&e.type===`orchestrator`),Fe=OU.map(e=>({...e,disabled:e.value===`orchestrator`&&Pe})),Ie=rW.find(e=>e.value===(t.verify??``))??rW[0],Le=t.status===`review`,Re=a.filter(e=>cW(A,e.name,e.description)),ze=o.map(e=>({...e,tools:e.tools.filter(e=>cW(N,e.name,e.description))})).filter(e=>cW(N,e.name)||e.tools.length>0),Be=N.trim()?ze.map(e=>e.name):I??o.filter(e=>e.ok&&e.tools.length).slice(0,1).map(e=>e.name);return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`header`,{className:`flex shrink-0 items-center gap-2 border-b ${WU} bg-[#FAFAF7] px-5 py-3.5 dark:bg-[#1B1C20]`,children:[(0,p.jsx)(`input`,{value:b,onChange:e=>{let t=e.target.value;x(t),G({label:t})},onBlur:W,onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur()},placeholder:`节点名称`,"aria-label":`节点名称`,className:`min-w-0 flex-1 rounded-[3px] border-0 bg-transparent p-0 text-[17px] font-semibold tracking-tight outline-none placeholder:text-[#a8a8a0] focus-visible:ring-2 focus-visible:ring-[#24543F]/30 dark:placeholder:text-[#6f6f68] dark:focus-visible:ring-[#6aa583]/40 ${VU}`}),(0,p.jsxs)(`span`,{className:`flex shrink-0 items-center gap-1.5 text-[12px] ${HU}`,children:[(0,p.jsx)(`span`,{className:`h-[6px] w-[6px] rounded-full ${Me.dot}`}),Me.label]}),(0,p.jsx)(`button`,{type:`button`,onClick:y,"aria-label":`关闭详情`,title:`关闭`,className:`-mr-1 grid h-8 w-8 shrink-0 place-items-center rounded-[4px] text-[#6b6b66] transition-colors hover:bg-[#EFEFEA] dark:text-[#8b8b85] dark:hover:bg-[#232421]`,children:(0,p.jsx)(Y,{size:16})})]}),t.verdict&&(0,p.jsxs)(`div`,{className:`shrink-0 border-b px-5 py-2 text-[12px] leading-[1.5] ${WU} ${t.verdict.pass?`bg-[#EEF3EF] text-[#24543F] dark:bg-[#1B2A22] dark:text-[#8FC3A7]`:`bg-[#FBEFEA] text-[#B4451F] dark:bg-[#2A1C17] dark:text-[#E08A6A]`}`,children:[pW(t.verdict.by),` `,t.verdict.pass?`通过`:`未通过`,t.verdict.reason?`:${t.verdict.reason}`:``]}),t.error&&(0,p.jsx)(`div`,{className:`shrink-0 border-b px-5 py-2 text-[12px] leading-[1.5] ${WU} bg-[#FBEFEA] text-[#B4451F] dark:bg-[#2A1C17] dark:text-[#E08A6A]`,children:t.error}),(0,p.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 pb-6 pt-3`,children:[Ne?null:(0,p.jsxs)(uW,{title:`节点类型`,children:[(0,p.jsx)(jb,{value:t.type||`llm`,onChange:e=>d({type:e}),options:Fe,"aria-label":`节点类型`,className:`w-full`,size:`middle`}),Pe?(0,p.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${UU}`,children:`画布已有根节点,这张卡不能再设为调度卡。`}):null]}),(0,p.jsx)(uW,{title:`模型`,extra:(0,p.jsxs)(`button`,{type:`button`,onClick:g,title:`重新读取 DSH 的模型目录`,className:`flex items-center gap-1 text-[11px] transition-opacity hover:opacity-70 ${UU}`,children:[(0,p.jsx)(ie,{size:11}),`刷新`]}),children:(0,p.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,p.jsx)(Nk,{value:xe,placeholder:`选择模型`,showSearch:!0,treeNodeFilterProp:`title`,treeDefaultExpandAll:!1,treeDefaultExpandedKeys:be,treeNodeLabelProp:`label`,treeData:ge,onChange:Ee,"aria-label":`模型`,className:`w-full`,size:`middle`}),(0,p.jsx)(jb,{value:t.reasoningEffort??``,onChange:e=>d({reasoningEffort:e}),disabled:!ue.length,"aria-label":`推理强度`,title:ue.length?`推理强度`:`当前模型没有可选推理档位`,options:[{value:``,label:`推理强度:模型默认${de?`(${de})`:``}`},...ue.map(e=>({value:e,label:e}))],className:`w-full`,size:`middle`}),fe&&(0,p.jsxs)(`div`,{className:`flex items-start gap-1.5 text-[11px] leading-[1.6] ${HU}`,children:[(0,p.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-50`}),(0,p.jsx)(`span`,{children:`没读到 DSH 的模型目录,检查 DSH 凭据或网络。`})]}),(0,p.jsxs)(`div`,{className:`flex items-start gap-1.5 border-t border-[#EDEEE9] pt-2 text-[11px] leading-[1.6] dark:border-[#2A2C31] ${c&&!c.healthy?`text-[#B4451F] dark:text-[#e08a6a]`:HU}`,children:[(0,p.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-60`}),(0,p.jsxs)(`span`,{children:[`模型通道:DSH 内核(未连接时不可跑图)`,c&&!c.healthy?` · ${c.reason||`原因未知`}`:``]})]})]})}),(0,p.jsx)(uW,{title:`兜底模型`,extra:X.length?(0,p.jsxs)(`span`,{className:`text-[11px] ${HU}`,children:[X.length,` 个 · 按顺序重试`]}):void 0,children:(0,p.jsxs)(`div`,{className:`space-y-1.5`,children:[X.map(e=>{let t=De(e);return(0,p.jsxs)(`div`,{className:`flex min-h-[32px] items-center gap-2 border-b py-1 last:border-b-0 ${WU}`,children:[(0,p.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[12px] ${VU}`,title:t.label,children:t.label}),(0,p.jsx)(jb,{size:`small`,value:Se[e]??``,disabled:!t.levels.length,title:t.levels.length?`这条兜底的推理强度`:`该模型没有可选推理档位`,options:[{value:``,label:`模型默认`},...t.levels.map(e=>({value:e,label:e}))],onChange:t=>je(e,t),"aria-label":`${t.label} 的推理强度`,style:{width:104}}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>Ae(e),"aria-label":`移除兜底模型 ${t.label}`,title:`移除`,className:`grid h-7 w-7 shrink-0 place-items-center rounded-[4px] transition-colors hover:bg-[#FBEFEA] hover:text-[#B4451F] dark:hover:bg-[#2A1C17] dark:hover:text-[#e08a6a] ${UU}`,children:(0,p.jsx)(Y,{size:13})})]},e)}),(0,p.jsx)(Nk,{onChange:ke,placeholder:`添加兜底模型…`,showSearch:!0,treeNodeFilterProp:`title`,treeDefaultExpandAll:!1,treeDefaultExpandedKeys:Te,treeNodeLabelProp:`label`,treeData:we,"aria-label":`添加兜底模型`,className:`w-full`,size:`middle`},O),(0,p.jsxs)(`div`,{className:`flex items-start gap-1.5 pt-0.5 text-[11px] leading-[1.6] ${HU}`,children:[(0,p.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-50`}),(0,p.jsx)(`span`,{children:`兜底模型:主模型失败后按顺序尝试,可单独设推理强度`})]})]})}),(0,p.jsxs)(uW,{title:Ne?`人格`:`任务`,children:[(0,p.jsx)(`textarea`,{ref:R,rows:3,value:S,onChange:e=>{C(e.target.value),G({task:e.target.value}),mW(e.currentTarget)},onBlur:W,placeholder:Ne?`默认:只负责和用户对话,再严格按后续节点的 AgentFlow 流执行(可自己改)`:`写清楚这张卡要做什么…`,className:`${aW} max-h-[240px] resize-none overflow-y-auto`}),Ne&&(0,p.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${UU}`,children:`默认人格只是起点,可以自己改:它只负责和用户对话,确认需求后严格按后续节点的流程执行。`})]}),(0,p.jsx)(uW,{title:`完成标准`,children:(0,p.jsx)(`textarea`,{ref:z,rows:2,value:w,onChange:e=>{T(e.target.value),G({criteria:e.target.value}),mW(e.currentTarget)},onBlur:W,placeholder:`做到什么程度算完成…`,className:`${aW} max-h-[200px] resize-none overflow-y-auto`})}),(0,p.jsxs)(uW,{title:`结果判断`,children:[(0,p.jsx)(`div`,{role:`radiogroup`,"aria-label":`结果判断`,className:`flex gap-[2px] rounded-[6px] bg-[#EFEFEA] p-[3px] dark:bg-[#232421]`,children:rW.map(e=>{let n=(t.verify??``)===e.value;return(0,p.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":n,title:e.desc,onClick:()=>d({verify:e.value}),className:`flex-1 rounded-[4px] px-1 py-[5px] text-[13px] leading-[1.3] transition-colors ${n?`bg-white text-[#1B1B18] shadow-[0_1px_2px_rgba(0,0,0,0.06)] dark:bg-[#3A3B35] dark:text-[#e8e8e4]`:`hover:text-[#1B1B18] dark:hover:text-[#e8e8e4] ${HU}`}`,children:e.label},e.value||`none`)})}),(0,p.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${UU}`,children:Ie.desc}),(t.verify??``)===`jev`&&(0,p.jsx)(`p`,{className:`mt-1.5 rounded-[4px] border border-[#E9D9B8] bg-[#FBF4E6] px-2 py-1.5 text-[11px] leading-[1.5] text-[#8a6220] dark:border-[#4a3a1c] dark:bg-[#2a2314] dark:text-[#e0b866]`,children:`需要本机安装 jev(TypeSafe)并配置 API key,否则这张卡跑到判定时会失败。`})]}),(0,p.jsx)(uW,{title:`技能`,extra:(0,p.jsxs)(`span`,{className:`text-[11px] ${UU}`,children:[`已选 `,t.skills.length]}),children:a.length===0?(0,p.jsx)(dW,{children:`没有找到技能`}):(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(AD,{value:A,onChange:e=>M(e.target.value),allowClear:!0,size:`middle`,placeholder:`搜索技能名或描述…`,"aria-label":`搜索技能`,prefix:(0,p.jsx)(se,{size:12,className:UU}),className:`mb-2`}),Re.length===0?(0,p.jsxs)(dW,{children:[`没有匹配「`,A.trim(),`」的技能`]}):null,(0,p.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto`,children:Re.map(e=>{let n=t.skills.includes(e.name);return(0,p.jsx)(GT,{className:`af-row`,checked:n,onChange:t=>ae(e.name,t.target.checked),title:e.description,children:(0,p.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`shrink-0 text-[13px] ${VU}`,children:e.name}),(0,p.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-right text-[11px] ${UU}`,children:e.description||`无描述`})]})},e.name)})})]})}),(0,p.jsx)(uW,{title:`MCP 工具`,extra:(0,p.jsxs)(`span`,{className:`text-[11px] ${UU}`,children:[`已选 `,t.tools.length]}),children:o.length===0?(0,p.jsx)(dW,{children:`还没配置 MCP 服务器`}):(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(AD,{value:N,onChange:e=>P(e.target.value),allowClear:!0,size:`middle`,placeholder:`搜索服务器或工具…`,"aria-label":`搜索 MCP 工具`,prefix:(0,p.jsx)(se,{size:12,className:UU}),className:`mb-2`}),ze.length===0?(0,p.jsxs)(dW,{children:[`没有匹配「`,N.trim(),`」的工具`]}):null,(0,p.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto af-tree`,children:(0,p.jsx)(jO,{checkable:!0,selectable:!1,expandedKeys:Be,onExpand:e=>L(e),treeData:ze.map(e=>({key:e.name,selectable:!1,title:(0,p.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`h-[5px] w-[5px] shrink-0 rounded-full ${e.ok?`bg-[#24543F] dark:bg-[#6aa583]`:`bg-[#B4451F] dark:bg-[#e08a6a]`}`}),(0,p.jsx)(`span`,{className:`text-[12px] font-medium ${VU}`,children:e.name}),(0,p.jsxs)(`span`,{className:`text-[11px] ${UU}`,children:[e.tools.length,` 个工具`]}),!e.ok&&(0,p.jsx)(`span`,{className:`text-[11px] text-[#B4451F] dark:text-[#e08a6a]`,children:`连接失败`})]}),children:e.tools.map(t=>({key:`${e.name}.${t.name}`,title:(0,p.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`shrink-0 text-[13px] ${VU}`,children:t.name}),(0,p.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-right text-[11px] ${UU}`,children:t.description})]})}))})),checkedKeys:t.tools,onCheck:e=>{let t=Array.isArray(e)?e:e.checked;d({tools:t.filter(e=>String(e).includes(`.`))})}})})]})}),Ne?null:(0,p.jsx)(uW,{title:`上游`,children:K.length===0?(0,p.jsx)(dW,{children:`还没有其它卡片`}):(0,p.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto`,children:K.map(e=>{let n=ne.has(e.id),r=!n&&fW(ee,t.id,e.id),i=n?[...ne].filter(t=>t!==e.id):[...ne,e.id];return(0,p.jsx)(GT,{className:`af-row ${r?`af-row-disabled`:``}`,checked:n,disabled:r,onChange:()=>re(i),children:(0,p.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[13px] ${VU}`,children:e.label||e.id}),r&&(0,p.jsx)(`span`,{className:`shrink-0 text-[11px] ${UU}`,children:`会成环`})]})},e.id)})})})]}),Le&&(0,p.jsxs)(`div`,{className:`shrink-0 border-t ${WU} bg-[#FAEFE6] px-5 py-3 dark:bg-[#2A1C17]`,children:[(0,p.jsx)(`p`,{className:`text-[12px] text-[#B4451F] dark:text-[#e08a6a]`,children:`这张卡跑完了,等你判断结果`}),(0,p.jsxs)(`div`,{className:`mt-2 flex gap-2`,children:[(0,p.jsx)(`button`,{type:`button`,onClick:()=>m(!0),className:`h-8 flex-1 rounded-[4px] bg-[#24543F] text-[13px] font-medium text-white transition-colors hover:bg-[#1D4634] dark:bg-[#3F7A5F] dark:hover:bg-[#4B8B6D]`,children:`通过`}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>m(!1),className:`h-8 flex-1 rounded-[4px] text-[13px] text-[#6b6b66] transition-colors hover:bg-white/60 dark:text-[#a3a39b] dark:hover:bg-[#232421]`,children:`打回重跑`})]})]}),(0,p.jsxs)(`footer`,{className:`shrink-0 border-t ${WU} bg-[#FAFAF7] px-5 py-3 dark:bg-[#1B1C20]`,children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,p.jsxs)(`button`,{type:`button`,onClick:h,disabled:l,className:`flex h-8 flex-1 items-center justify-center gap-1.5 rounded-[4px] bg-[#24543F] text-[13px] font-medium text-white transition-colors hover:bg-[#1D4634] disabled:cursor-not-allowed disabled:opacity-50 dark:bg-[#3F7A5F] dark:hover:bg-[#4B8B6D]`,children:[l?(0,p.jsx)(U,{size:13,className:`animate-spin`}):(0,p.jsx)(ie,{size:13}),l?`运行中…`:`重跑此卡`]}),Ne?null:(0,p.jsxs)(`button`,{type:`button`,onClick:()=>f(`prev`),className:`${oW} flex items-center gap-1`,children:[(0,p.jsx)(F,{size:13}),`加上游`]}),(0,p.jsxs)(`button`,{type:`button`,onClick:()=>f(`next`),className:`${oW} flex items-center gap-1`,children:[(0,p.jsx)(j,{size:13}),`加下游`]})]}),(0,p.jsx)(`div`,{className:`mt-1 flex justify-end`,children:(0,p.jsxs)(`button`,{type:`button`,onClick:v,disabled:Ne,title:Ne?`根节点是对话入口(人格来源),不能删除`:void 0,className:`flex items-center gap-1.5 rounded-[4px] px-2.5 py-1.5 text-[12px] text-[#B4451F] transition-colors hover:bg-[#FBEFEA] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent dark:text-[#e08a6a] dark:hover:bg-[#2A1C17]`,children:[(0,p.jsx)(me,{size:13}),`删除此卡`]})})]})]})}function uW({title:e,extra:t,children:n}){return(0,p.jsxs)(`section`,{className:`mt-3 rounded-xl border p-3 first:mt-1 ${GU}`,children:[(0,p.jsxs)(`div`,{className:`mb-2.5 flex items-center justify-between gap-2`,children:[(0,p.jsx)(`h3`,{className:`text-[12px] font-semibold tracking-[0.01em] ${VU}`,children:e}),t]}),n]})}function dW({children:e}){return(0,p.jsx)(`p`,{className:`py-1 text-[12px] leading-[1.6] ${UU}`,children:e})}function fW(e,t,n){if(t===n)return!0;let r=new Set([t]),i=[t];for(;i.length;){let t=i.pop();for(let a of e)if(a.from===t){if(a.to===n)return!0;r.has(a.to)||(r.add(a.to),i.push(a.to))}}return!1}function pW(e){return e===`human`?`人工`:e===`jev`?`jev`:e===`self`?`自评`:e||`系统`}function mW(e){e&&(e.style.height=`auto`,e.style.height=`${e.scrollHeight}px`)}var{Text:hW}=PA;function gW({open:e,config:t,servers:n,onClose:r,onSaved:i,onError:a}){let o=t,[s,c]=(0,u.useState)(o?.mock??!1),[l,d]=(0,u.useState)(!1),[f,m]=(0,u.useState)(null),[h,g]=(0,u.useState)(!1),_=(0,u.useRef)(a);(0,u.useEffect)(()=>{_.current=a},[a]),(0,u.useEffect)(()=>{e&&c(o?.mock??!1)},[e,o?.mock]),(0,u.useEffect)(()=>{if(!e)return;let t=!1;return g(!0),JA.getBridge().then(e=>{t||m(e)}).catch(e=>{t||_.current(`读取模型通道状态失败:${e.message}`)}).finally(()=>{t||g(!1)}),()=>{t=!0}},[e]);async function v(){if(h)return;g(!0);let[e,t]=await Promise.allSettled([JA.getBridge(),JA.getModels(!0)]);e.status===`fulfilled`?m(e.value):_.current(`读取模型通道状态失败:${e.reason.message}`),t.status===`rejected`&&_.current(`重新读取模型目录失败:${t.reason.message}`),g(!1)}async function y(e){if(l||!t)return;let n=s;c(e),d(!0);try{let t=await JA.putConfig({mock:e}),n=typeof t?.mock==`boolean`?t.mock:e;c(n),i({mock:n})}catch(e){c(n),a(`切换 mock 失败:${e.message}`)}finally{d(!1)}}let b=Object.entries(o?.providers??{}),x=o?.mcpServers??n.map(e=>({name:e.name})),S=o?.skillDirs?.length?o.skillDirs:o?.dshPaths?.skills?[o.dshPaths.skills]:[],C=f?f.healthy?(0,p.jsx)(WO,{color:`success`,style:{marginInlineEnd:0},children:`已连接`}):(0,p.jsx)(WO,{color:`warning`,style:{marginInlineEnd:0},children:`未连接`}):(0,p.jsx)(hW,{type:`secondary`,style:{fontSize:12},children:`读取中…`}),w=f&&(f.lastError||f.reason)||``;return(0,p.jsxs)(PD,{open:e,title:`设置`,width:640,centered:!0,getContainer:()=>document.querySelector(`.af-canvas`)??document.body,onCancel:r,styles:{body:{maxHeight:`calc(100vh - 220px)`,overflowY:`auto`,paddingTop:12}},footer:(0,p.jsx)(oD,{justify:`flex-end`,children:(0,p.jsx)(VS,{onClick:r,children:`关闭`})}),children:[(0,p.jsx)(Vl,{type:`info`,showIcon:!0,title:`模型、MCP 服务器、技能都来自 DSH 的配置。要增删改请到 DSH 的 cordis.patch.yml,AgentFlow 这边只读。`,description:o?.dshPaths?.patch?(0,p.jsxs)(hW,{type:`secondary`,style:{fontSize:12,wordBreak:`break-all`},children:[`patch:`,(0,p.jsx)(hW,{code:!0,style:{fontSize:12},children:o.dshPaths.patch})]}):void 0}),(0,p.jsx)(_W,{title:`模型`,extra:(0,p.jsxs)(hW,{type:`secondary`,style:{fontSize:11},children:[b.length,` 个`]}),children:b.length===0?(0,p.jsx)(eb,{image:eb.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置模型提供商`}):b.map(([e,t])=>(0,p.jsx)(Rw,{size:`small`,style:{marginBottom:12},title:(0,p.jsx)(hW,{strong:!0,style:{fontSize:14},children:t.label||e}),extra:t.hasKey?(0,p.jsx)(WO,{color:`green`,style:{marginInlineEnd:0},children:`已配置 key`}):(0,p.jsx)(WO,{color:`red`,style:{marginInlineEnd:0},children:`缺 key`}),children:(0,p.jsx)(LE,{size:`small`,column:1,colon:!1,items:[{key:`provider`,label:`provider`,children:(0,p.jsx)(hW,{code:!0,children:e})},{key:`baseURL`,label:`baseURL`,children:(0,p.jsx)(hW,{code:!0,children:t.baseURL||`—`})},{key:`model`,label:`model`,children:(0,p.jsx)(hW,{code:!0,children:t.model||`—`})}]})},e))}),(0,p.jsxs)(_W,{title:`模型通道`,extra:(0,p.jsx)(VS,{size:`small`,loading:h,onClick:()=>void v(),children:`刷新`}),children:[f&&!f.healthy&&(0,p.jsx)(Vl,{type:`warning`,showIcon:!0,style:{marginBottom:10},title:`DSH 未运行或插件未加载,画布不能调模型`}),(0,p.jsx)(LE,{size:`small`,bordered:!0,column:1,colon:!1,items:[{key:`status`,label:`状态`,children:C},{key:`infoPath`,label:`发现文件`,children:(0,p.jsx)(hW,{code:!0,style:{fontSize:12,wordBreak:`break-all`,userSelect:`text`},title:f?.dir,children:f?.infoPath||`—`})},{key:`version`,label:`版本`,children:f?.version==null?`—`:(0,p.jsx)(hW,{code:!0,children:f.version})},{key:`startedAt`,label:`启动时间`,children:vW(f?.startedAt??null)},{key:`providers`,label:`provider 数`,children:f?String(f.providers):`—`},{key:`modelCount`,label:`模型数`,children:f?String(f.modelCount):`—`},{key:`lastError`,label:`最后错误`,children:w?(0,p.jsx)(hW,{type:`danger`,style:{fontSize:12,wordBreak:`break-all`},children:w}):(0,p.jsx)(hW,{type:`secondary`,children:`—`})}]})]}),(0,p.jsx)(_W,{title:`MCP 服务器`,extra:(0,p.jsxs)(hW,{type:`secondary`,style:{fontSize:11},children:[x.length,` 个`]}),children:x.length===0?(0,p.jsx)(eb,{image:eb.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置 MCP 服务器`}):(0,p.jsx)(LE,{size:`small`,bordered:!0,column:1,colon:!1,items:x.map(e=>({key:e.name,label:(0,p.jsx)(hW,{strong:!0,style:{fontSize:13},children:e.name}),children:e.kind?(0,p.jsx)(WO,{style:{marginInlineEnd:0},children:e.kind}):(0,p.jsx)(hW,{type:`secondary`,children:`—`})}))})}),(0,p.jsx)(_W,{title:`技能目录`,extra:(0,p.jsxs)(hW,{type:`secondary`,style:{fontSize:11},children:[S.length,` 个`]}),children:S.length===0?(0,p.jsx)(eb,{image:eb.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置技能目录`}):(0,p.jsx)(oD,{vertical:!0,gap:6,children:S.map(e=>(0,p.jsx)(hW,{code:!0,style:{fontSize:12,wordBreak:`break-all`},children:e},e))})}),(0,p.jsx)(_W,{title:`运行模式`,children:(0,p.jsx)(Rw,{size:`small`,children:(0,p.jsxs)(oD,{align:`center`,justify:`space-between`,gap:16,children:[(0,p.jsxs)(`div`,{style:{minWidth:0},children:[(0,p.jsx)(hW,{strong:!0,style:{display:`block`,fontSize:15},children:`mock 模式`}),(0,p.jsx)(hW,{type:`secondary`,style:{display:`block`,fontSize:12},children:`AgentFlow 自己的开关,不属于 DSH 配置。打开后不真正调用模型。`})]}),(0,p.jsx)(UD,{checked:s,loading:l,disabled:!t,onChange:e=>void y(e)})]})})})]})}function _W({title:e,extra:t,children:n}){return(0,p.jsxs)(`section`,{style:{marginTop:20},children:[(0,p.jsxs)(oD,{align:`center`,justify:`space-between`,gap:8,style:{marginBottom:8},children:[(0,p.jsx)(hW,{strong:!0,style:{fontSize:13},children:e}),t]}),n]})}function vW(e){if(typeof e!=`number`||!Number.isFinite(e)||e<=0)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`}var{Text:yW}=PA,bW=`'SFMono-Regular', Menlo, Consolas, 'Liberation Mono', ui-monospace, monospace`;function xW({open:e,boardId:t,boardName:n,onClose:r}){let{token:i}=ek.useToken(),[a,o]=(0,u.useState)(null),[s,c]=(0,u.useState)(null),[l,d]=(0,u.useState)(!1),[f,m]=(0,u.useState)(``),[h,g]=(0,u.useState)([]),[_,v]=(0,u.useState)(!1),[y,b]=(0,u.useState)(null),x=(0,u.useCallback)(async()=>{v(!0);try{let e=await JA.listCommands();g(e.commands)}catch{g([])}finally{v(!1)}},[]);(0,u.useEffect)(()=>{e&&(o(null),c(null),d(!1),m(``),x())},[e,x]);async function S(){if(!l){d(!0),c(null),o(null);try{let e=f.trim(),n=await JA.exportCommand(t,e||void 0);o(n),await x()}catch(e){let t=e.message||`未知错误`;c({title:t.includes(`HTTP 400`)?`生成失败(检查命令名)`:`生成失败`,detail:t})}finally{d(!1)}}}async function C(e){if(!y&&window.confirm(`删除命令 /${e}?删掉后 DSH 里立刻就不能用了。`)){b(e),c(null);try{await JA.deleteCommand(e),a?.name===e&&o(null),await x()}catch(e){c({title:`删除失败`,detail:e.message})}finally{b(null)}}}let w=h.filter(e=>!t||e.board===t),T={border:`1px solid ${i.colorBorderSecondary}`,borderRadius:8,background:i.colorFillTertiary,padding:`10px 12px`,fontFamily:bW,fontSize:12,lineHeight:1.7,whiteSpace:`pre-wrap`,wordBreak:`break-all`,color:i.colorText};return(0,p.jsxs)(PD,{open:e,title:`生成斜杠命令`,width:640,centered:!0,onCancel:r,styles:{body:{maxHeight:`calc(100vh - 240px)`,overflowY:`auto`}},footer:(0,p.jsxs)(oD,{justify:`flex-end`,gap:8,children:[(0,p.jsx)(VS,{onClick:r,children:`关闭`}),(0,p.jsx)(VS,{type:`primary`,icon:(0,p.jsx)(z,{size:14}),loading:l,onClick:()=>void S(),children:`生成`})]}),children:[(0,p.jsx)(Vl,{type:`info`,showIcon:!0,title:`把这张画布挂成一条 DSH 斜杠命令:生成后在对话里输入 /命令名,就能进入这张画布的工作流(无参数先看画布,带文字直接进流程)。命令即时生效,不用重启 DSH。`,style:{marginBottom:16}}),(0,p.jsxs)(`div`,{style:{marginBottom:12},children:[(0,p.jsx)(yW,{type:`secondary`,style:{fontSize:12},children:`当前画布:`}),(0,p.jsx)(yW,{strong:!0,style:{fontSize:12},children:n||t||`索引里的第一张画布`})]}),(0,p.jsxs)(`div`,{style:{marginBottom:16},children:[(0,p.jsx)(yW,{style:{fontSize:12,display:`block`,marginBottom:6},children:`命令名(可选)`}),(0,p.jsx)(AD,{value:f,onChange:e=>m(e.target.value),placeholder:`留空=按画布 id 自动生成(agentflow-…)`,maxLength:48,disabled:l}),(0,p.jsx)(yW,{type:`secondary`,style:{fontSize:11},children:`小写字母开头,只允许 a-z 0-9 _ -,不超过 48 个字符;同名会覆盖旧命令。`})]}),s&&(0,p.jsx)(Vl,{type:`error`,showIcon:!0,title:s.title,description:s.detail?(0,p.jsx)(yW,{style:{fontSize:12,fontFamily:bW,wordBreak:`break-all`},children:s.detail}):void 0,style:{marginBottom:16}}),a&&(0,p.jsxs)(`div`,{style:{marginBottom:16},children:[(0,p.jsx)(Vl,{type:`success`,showIcon:!0,title:a.replaced?`命令已更新(覆盖了同名旧命令)`:`命令已生成`,description:(0,p.jsxs)(`div`,{children:[(0,p.jsxs)(`div`,{style:{marginBottom:4},children:[`命令名:`,(0,p.jsxs)(yW,{code:!0,copyable:!0,style:{fontSize:12},children:[`/`,a.name]})]}),(0,p.jsxs)(`div`,{style:{marginBottom:4},children:[`用法:在 DSH 对话里输入 `,(0,p.jsxs)(yW,{code:!0,style:{fontSize:12},children:[`/`,a.name]}),`,回车即可。`]}),(0,p.jsx)(`div`,{style:{marginBottom:4},children:(0,p.jsx)(`b`,{children:`已即时生效,无需重启。`})}),(0,p.jsxs)(`div`,{children:[`文件:`,(0,p.jsx)(yW,{code:!0,copyable:!0,style:{fontSize:12,wordBreak:`break-all`},children:a.file})]})]})}),(0,p.jsx)(oD,{justify:`flex-end`,style:{marginTop:8},children:(0,p.jsx)(VS,{size:`small`,danger:!0,icon:(0,p.jsx)(me,{size:13}),loading:y===a.name,onClick:()=>void C(a.name),children:`删除命令`})})]}),(0,p.jsxs)(`div`,{children:[(0,p.jsxs)(oD,{align:`baseline`,justify:`space-between`,style:{marginBottom:6},children:[(0,p.jsx)(yW,{strong:!0,style:{fontSize:13},children:`这张画布已有的命令`}),(0,p.jsx)(yW,{type:`secondary`,style:{fontSize:11},children:_?`读取中…`:`${w.length} 条`})]}),w.length===0?(0,p.jsx)(`div`,{style:{...T,color:i.colorTextTertiary},children:_?`正在读取…`:`还没有命令,点右下角「生成」创建一条。`}):(0,p.jsx)(`div`,{style:{border:`1px solid ${i.colorBorderSecondary}`,borderRadius:8},children:w.map((e,t)=>(0,p.jsxs)(oD,{align:`center`,gap:8,style:{padding:`8px 12px`,borderTop:t===0?void 0:`1px solid ${i.colorBorderSecondary}`},children:[(0,p.jsxs)(yW,{code:!0,style:{fontSize:12},children:[`/`,e.name]}),(0,p.jsx)(yW,{type:`secondary`,style:{fontSize:11},children:SW(e.createdAt)}),(0,p.jsx)(`div`,{style:{marginLeft:`auto`},children:(0,p.jsx)(VS,{size:`small`,type:`text`,danger:!0,icon:(0,p.jsx)(me,{size:13}),loading:y===e.name,onClick:()=>void C(e.name),children:`删除`})})]},e.name))})]})]})}function SW(e){if(!e)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}var CW=`border-[#E3E4DF] dark:border-[#262724]`,wW=`text-[#1B1B18] dark:text-[#e8e8e4]`,TW=`text-[#6b6b66] dark:text-[#8b8b85]`,EW=`text-[#8b8b85] dark:text-[#8b8b85]`;function DW(){try{let e=globalThis.__AGENTFLOW_HOST__;return e&&typeof e==`object`?e:null}catch{return null}}function OW(){return DW()?.remote===!0}function kW(){let[e,t]=(0,u.useState)(`list`),[n,r]=(0,u.useState)([]),[i,a]=(0,u.useState)([]),[o,s]=(0,u.useState)({}),[c,l]=(0,u.useState)(!0),[d,f]=(0,u.useState)(null),[m,h]=(0,u.useState)(null),[g,_]=(0,u.useState)(``),[v,y]=(0,u.useState)(null),[b,x]=(0,u.useState)(null),[S,C]=(0,u.useState)(!1),[w,T]=(0,u.useState)(``),[E,D]=(0,u.useState)(!1),[O,k]=(0,u.useState)(null),[A,j]=(0,u.useState)(``),M=(0,u.useRef)(!1),P=(0,u.useRef)(!1),[F,I]=(0,u.useState)([]),[L,R]=(0,u.useState)([]),[B,H]=(0,u.useState)(null),[W,ee]=(0,u.useState)(null),[te,ne]=(0,u.useState)(null),[re,ie]=(0,u.useState)(!1),[ae,oe]=(0,u.useState)(!1),[se,J]=(0,u.useState)(!1),[le,ue]=(0,u.useState)(!1),de=(0,u.useRef)(!1),pe=(0,u.useRef)(!1),me=(0,u.useCallback)(()=>{pe.current=!0,J(!0)},[]),he=(0,u.useCallback)(()=>{pe.current=!1,J(!1)},[]),ge=(0,u.useRef)(0),_e=(0,u.useRef)(null);(0,u.useEffect)(()=>{_e.current=m},[m]),(0,u.useEffect)(()=>{if(!m||e!==`board`)return;let t=window.setTimeout(()=>{JA.putBoard(m.id,m).catch(e=>{console.warn(`[agentflow] 自动保存失败:`,e)}),r(e=>e.map(e=>e.id===m.id?{...e,presetOutdated:!0}:e))},200);return()=>window.clearTimeout(t)},[m,e]),(0,u.useEffect)(()=>{let e=()=>{let e=_e.current;if(e)try{fetch(WA(`/api/boards/${encodeURIComponent(e.id)}`),{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({board:e}),keepalive:!0}).catch(()=>{})}catch{}};return window.addEventListener(`pagehide`,e),()=>window.removeEventListener(`pagehide`,e)},[]);let[Y,ve]=(0,u.useState)(()=>{let e=DW();if(e?.remote){if(e.theme===`dark`)return!0;if(e.theme===`light`)return!1;try{return window.matchMedia(`(prefers-color-scheme: dark)`).matches}catch{return!1}}try{localStorage.removeItem(`agentflow-theme`)}catch{}try{let e=sessionStorage.getItem(`agentflow-theme`);if(e===`dark`)return!0;if(e===`light`)return!1}catch{}try{let e=new URLSearchParams(window.location.search).get(`theme`);if(e===`dark`)return!0;if(e===`light`)return!1}catch{}try{return window.matchMedia(`(prefers-color-scheme: dark)`).matches}catch{return!1}});(0,u.useEffect)(()=>{if(OW())window.dispatchEvent(new Event(`themechange`));else{document.documentElement.classList.toggle(`dark`,Y);try{sessionStorage.setItem(`agentflow-theme`,Y?`dark`:`light`)}catch{}window.dispatchEvent(new Event(`themechange`))}},[Y]),(0,u.useEffect)(()=>{if(!OW())return;let e=e=>{let t=e.detail?.theme;t===`dark`?ve(!0):t===`light`&&ve(!1)};return window.addEventListener(`agentflow-theme`,e),()=>window.removeEventListener(`agentflow-theme`,e)},[]);let[ye,be]=(0,u.useState)(null),xe=(0,u.useRef)(null),X=(0,u.useCallback)((e,t=`ok`)=>{be({msg:e,kind:t}),xe.current&&window.clearTimeout(xe.current),xe.current=window.setTimeout(()=>be(null),3200)},[]),Se=(0,u.useCallback)((e,t)=>{h(n=>n&&{...n,nodes:n.nodes.map(n=>n.id===e?{...n,...t}:n)})},[]),Ce=(0,u.useRef)(null),we=(0,u.useRef)(null);(0,u.useEffect)(()=>{if(Ce.current=d,OW()&&d)try{window.dispatchEvent(new CustomEvent(`agentflow-board-active`,{detail:{boardId:d}}))}catch{}},[d]),(0,u.useEffect)(()=>{_(m?.name??``)},[m?.id,m?.name]);let Te=(0,u.useCallback)(async(e=!1)=>{e||l(!0);let[t,n]=await Promise.allSettled([JA.listBoards(),JA.listPresets()]);if(t.status===`fulfilled`){let e=t.value.boards;r(e);let n=await Promise.allSettled(e.map(e=>JA.getBoard(e.id))),i={};n.forEach((t,n)=>{t.status===`fulfilled`&&(i[e[n].id]=jW(t.value.board))}),s(i)}else X(`加载画布列表失败:${t.reason.message}`,`err`);n.status===`fulfilled`?a(n.value.presets):X(`加载预设列表失败:${n.reason.message}`,`err`),e||l(!1)},[X]);(0,u.useEffect)(()=>{Te(),JA.getSkills().then(e=>I(e.skills)).catch(()=>{}),JA.getMcp().then(e=>R(e.servers)).catch(()=>{}),JA.getConfig().then(H).catch(()=>{}),JA.getModels().then(ee).catch(()=>{}),JA.getBridge().then(ne).catch(()=>{})},[Te]);let Ee=(0,u.useRef)(0);(0,u.useEffect)(()=>{v&&(Date.now()-Ee.current<3e4||(Ee.current=Date.now(),JA.getModels(!0).then(ee).catch(()=>{}),JA.getBridge().then(ne).catch(()=>{})))},[v]);let{running:De,run:Oe,stop:ke}=YA((0,u.useCallback)(e=>{let t=we.current!=null&&Ce.current!==we.current;if((e.type===`run:end`||e.type===`run:error`)&&(we.current=null),!t)switch(e.type){case`node:start`:Se(e.id,{status:`running`});break;case`node:delta`:h(t=>t&&{...t,nodes:t.nodes.map(t=>t.id===e.id?{...t,delta:(t.delta||``)+e.chunk}:t)});break;case`node:done`:Se(e.id,{status:e.status??`done`,content:e.content,usage:e.usage,verdict:e.verdict??null,error:null,delta:void 0});break;case`node:failed`:Se(e.id,{status:`failed`,error:`该节点所有模型都失败`});break;case`node:blocked`:Se(e.id,{status:`blocked`});break;case`node:retry`:h(t=>t&&{...t,nodes:t.nodes.map(t=>t.id===e.id?{...t,delta:void 0}:t)}),X(`${e.id} 换 ${e.model} 重试:${e.error}`,`err`);break;case`run:end`:{let{done:t,failed:n,blocked:r,review:i}=e.summary,a=[`完成 ${t.length}`];i.length&&a.push(`待确认 ${i.length}`),n.length&&a.push(`失败 ${n.length}`),r.length&&a.push(`阻塞 ${r.length}`),X(a.join(`,`),n.length||r.length?`err`:`ok`);break}case`run:error`:X(`运行出错:${e.error}`,`err`)}},[Se,X])),Ae=(0,u.useCallback)(e=>{let t=Ce.current;t&&(we.current=t,Oe(e,t))},[Oe]),je=(0,u.useCallback)(()=>{we.current=null,ke()},[ke]),Me=(0,u.useCallback)(async e=>{let n=++ge.current;t(`board`),f(e),h(null),_(``),y(null),oe(!1),he();let r=await JA.getBoard(e).then(e=>({status:`fulfilled`,value:e})).catch(e=>({status:`rejected`,reason:e}));n===ge.current&&(r.status===`rejected`?(X(`打开画布失败:${r.reason.message}`,`err`),t(`list`),f(null),he(),Te(!0)):h(r.value.board))},[Te,X]),Ne=(0,u.useRef)((()=>{let e=DW();return e?.remote&&e.boardId?e.boardId:typeof window>`u`?null:new URLSearchParams(window.location.search).get(`board`)})());(0,u.useEffect)(()=>{let e=Ne.current;e&&(Ne.current=null,Me(e))},[Me]),(0,u.useEffect)(()=>{if(!OW())return;let e=e=>{let t=e.detail?.boardId;t&&t!==Ce.current&&Me(t)};return window.addEventListener(`agentflow-board`,e),()=>window.removeEventListener(`agentflow-board`,e)},[Me]);let Pe=(0,u.useCallback)(()=>{ge.current+=1,t(`list`),h(null),f(null),y(null),oe(!1),he(),Te(!0)},[Te]);function Fe(){Pe()}function Ie(e){Me(e)}let Le=(0,u.useCallback)(async()=>{let e=_e.current;if(!e)return!1;try{return await JA.putBoard(e.id,e),he(),!0}catch(e){return X(`保存画布失败:${e.message}`,`err`),!1}},[X,he]),Re=(0,u.useCallback)(async()=>{let e=_e.current;if(!e||de.current)return!1;de.current=!0,ue(!0);try{return await JA.putBoard(e.id,e),he(),r(t=>t.map(t=>t.id===e.id?{...t,name:e.name,nodeCount:e.nodes.length,presetOutdated:!1,updatedAt:Date.now()}:t)),X(`已保存`),!0}catch(e){return X(`保存失败:${e.message}`,`err`),!1}finally{de.current=!1,ue(!1)}},[X,he]);(0,u.useEffect)(()=>{let t=t=>{(t.metaKey||t.ctrlKey)&&String(t.key).toLowerCase()===`s`&&(t.preventDefault(),e===`board`&&window.setTimeout(()=>void Re(),0))};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[Re,e]);let ze=(0,u.useCallback)(async e=>{m&&(!pe.current||await Le())&&Ae(e)},[m,Le,Ae]),Be=(0,u.useCallback)(async()=>{m&&(!pe.current||await Le())&&oe(!0)},[m,Le]),Ve=(0,u.useCallback)((e,t)=>{Se(e,t),me()},[Se]),He=(0,u.useCallback)(e=>{h(t=>t&&{...t,edges:e}),me()},[]),Ue=(0,u.useCallback)((e,t,n)=>{m&&(h({...m,nodes:m.nodes.map(r=>r.id===e?{...r,x:t,y:n}:r)}),me())},[m]),We=(0,u.useCallback)((e,t)=>{if(!m)return;let n=m.nodes.find(t=>t.id===e);if(!n)return;let r=W?.providers.find(e=>e.models.length),i=n.provider||r?.id||``,a=n.model||r?.models[0]?.id||``,o=AW(m.nodes),s={id:o,label:t===`next`?`下游卡片`:`上游卡片`,type:`llm`,x:t===`next`?n.x+360:n.x-360,y:n.y,provider:i,model:a,reasoningEffort:``,fallback:[],fallbackEfforts:{},task:``,criteria:``,skills:[],tools:[],verify:``,content:``,status:`idle`,usage:null,error:null,verdict:null};h({...m,nodes:[...m.nodes,s],edges:[...m.edges,t===`next`?{from:e,to:o}:{from:o,to:e}]}),y(o),me(),X(t===`next`?`已派生下游卡片(未保存)`:`已添加上游卡片(未保存)`)},[m,W,X]),Ge=(0,u.useCallback)((e,t)=>{m&&e!==t&&(m.nodes.find(e=>e.id===t)?.type===`orchestrator`?X(`根节点是对话入口,不能有上游节点`,`err`):m.edges.some(n=>n.from===e&&n.to===t)||(NW(m.edges,e,t)?X(`这条连线会形成环,已忽略`,`err`):(h({...m,edges:[...m.edges,{from:e,to:t}]}),me())))},[m,X]),Ke=(0,u.useCallback)(e=>{m&&(h({...m,nodes:m.nodes.filter(t=>t.id!==e),edges:m.edges.filter(t=>t.from!==e&&t.to!==e)}),y(null),me(),X(`已删除(未保存)`))},[m,X]),qe=(0,u.useCallback)(async(e,t)=>{if(!pe.current||await Le())try{let n=await JA.verify(e,t,void 0,Ce.current);Se(e,{status:n.status,verdict:n.verdict}),X(t?`已通过`:`已打回,可以改完再跑`)}catch(e){X(`操作失败:${e.message}`,`err`)}},[Se,X,Le]),Je=(0,u.useMemo)(()=>m?.nodes.find(e=>e.id===v)??null,[m,v]),Ye=(0,u.useMemo)(()=>new Set(n.map(e=>e.presetId).filter(e=>!!e)),[n]),Xe=(0,u.useMemo)(()=>i.filter(e=>!Ye.has(e.id)),[i,Ye]);function Ze(){T(``),C(!0)}async function Qe(){let e=w.trim();if(e&&!E){D(!0);try{let n=await JA.createBoard({name:e});ge.current+=1,C(!1),T(``),h(n.board),f(n.board.id),y(null),he(),t(`board`),Te(!0)}catch(e){X(`新建画布失败:${e.message}`,`err`)}finally{D(!1)}}}async function $e(e){if(!b){x(e.id);try{let n=await JA.importPreset(e.id);X(n.reused?`已有这张画布:${e.name}`:`已从预设创建画布:${e.name}`),ge.current+=1,h(n.board),f(n.board.id),y(null),he(),t(`board`),Te(!0)}catch(e){let t=e.message;t.includes(`HTTP 501`)?X(`创建画布功能还没上线(服务端 P1 未完成)`,`err`):X(`创建画布失败:${t}`,`err`)}finally{x(null)}}}function et(e){k(e.id),j(e.name)}async function tt(e){if(O!==e.id)return;let t=M.current;if(M.current=!1,k(null),t){j(e.name);return}let n=A.trim();if(n&&n!==e.name)try{let t=await JA.patchBoard(e.id,{name:n});r(r=>r.map(r=>r.id===e.id?{...r,name:n,updatedAt:t.meta?.updatedAt??r.updatedAt}:r)),m?.id===e.id&&h(e=>e&&{...e,name:n}),X(`画布已重命名`)}catch(e){X(`重命名失败:${e.message}`,`err`)}}async function nt(e){if(n.length<=1)X(`至少要保留一张画布`,`err`);else if(window.confirm(`删除画布《${e.name}》?里面的节点会一起删掉,且不可恢复。`))try{await JA.deleteBoard(e.id),X(`画布已删除`),await Te(!0)}catch(e){X(`删除失败:${e.message}`,`err`)}}async function rt(){if(!m)return;let e=P.current;if(P.current=!1,e){_(m.name);return}let t=g.trim();if(!t)_(m.name);else if(t!==m.name)try{let e=await JA.patchBoard(m.id,{name:t});h(e=>e&&{...e,name:t}),r(n=>n.map(n=>n.id===m.id?{...n,name:t,updatedAt:e.meta?.updatedAt??n.updatedAt}:n)),X(`画布已重命名`)}catch(e){_(m.name),X(`重命名失败:${e.message}`,`err`)}}let it=(0,u.useRef)(null);return(0,p.jsx)(Md,{locale:UA.default,getPopupContainer:()=>it.current??document.body,theme:{algorithm:Y?ek.darkAlgorithm:ek.defaultAlgorithm,token:{colorPrimary:`#24543F`,borderRadius:7,fontSize:15,fontFamily:`-apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', ui-sans-serif, sans-serif`},components:{Drawer:{paddingLG:20},Modal:{borderRadiusLG:12},Card:{borderRadiusLG:10}}},children:(0,p.jsxs)(`div`,{ref:it,className:`af-canvas flex h-full flex-col${Y?` dark`:``}`,children:[e===`list`?(0,p.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-3 border-b ${CW} bg-[#FCFCFA] px-5 dark:bg-[#17181b]`,children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`span`,{className:`grid h-7 w-7 place-items-center rounded-[4px] bg-[#24543F] text-white`,children:`◈`}),(0,p.jsx)(`span`,{className:`text-[17px] font-semibold tracking-tight ${wW}`,children:`AgentFlow`})]}),(0,p.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,p.jsx)(VS,{type:`primary`,icon:(0,p.jsx)(K,{size:14}),onClick:Ze,children:`新建画布`}),(0,p.jsx)(VS,{icon:Y?(0,p.jsx)(fe,{size:14}):(0,p.jsx)(G,{size:14}),onClick:()=>ve(e=>!e),title:Y?`切到浅色`:`切到深色`}),(0,p.jsx)(VS,{icon:(0,p.jsx)(ce,{size:14}),onClick:()=>ie(!0),children:`设置`})]})]}):(0,p.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b ${CW} bg-[#FCFCFA] px-4 dark:bg-[#17181b]`,children:[(0,p.jsxs)(`button`,{type:`button`,onClick:Fe,title:`返回画布列表`,className:`flex shrink-0 items-center gap-1 rounded-[4px] px-2 py-1.5 text-[12px] transition-colors hover:bg-[#EFEFEA] dark:hover:bg-[#232421] ${TW}`,children:[(0,p.jsx)(N,{size:14}),`返回列表`]}),(0,p.jsx)(`div`,{className:`h-5 w-px shrink-0 bg-[#E3E4DF] dark:bg-[#2c2d29]`}),(0,p.jsx)(`input`,{value:g,onChange:e=>_(e.target.value),onBlur:()=>void rt(),onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur(),e.key===`Escape`&&(P.current=!0,e.currentTarget.blur())},disabled:!m,placeholder:`画布名称`,"aria-label":`画布名称`,className:`min-w-0 max-w-[280px] flex-1 rounded-[3px] border-0 bg-transparent px-1 py-1 text-[16px] font-semibold tracking-tight outline-none placeholder:text-[#a8a8a0] focus-visible:ring-2 focus-visible:ring-[#24543F]/30 disabled:bg-transparent dark:placeholder:text-[#6f6f68] dark:focus-visible:ring-[#6aa583]/40 ${wW}`}),se&&(0,p.jsx)(`span`,{title:`有未保存的修改`,"aria-label":`有未保存的修改`,className:`h-1.5 w-1.5 shrink-0 rounded-full bg-[#B4451F] dark:bg-[#e08a6a]`}),(0,p.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,p.jsx)(VS,{icon:(0,p.jsx)(q,{size:14}),disabled:!m,loading:le,onClick:()=>void Re(),title:`保存画布(⌘S / Ctrl+S)`,children:`保存`}),De?(0,p.jsx)(VS,{danger:!0,icon:(0,p.jsx)(U,{size:14,className:`animate-spin`}),onClick:je,children:`停止`}):(0,p.jsx)(VS,{type:`primary`,icon:(0,p.jsx)(V,{size:14}),disabled:!m,onClick:()=>void ze(),title:`先保存,再跑一遍验证(会真实调用模型)`,children:`验证 AgentFlow`}),(0,p.jsx)(VS,{icon:(0,p.jsx)(z,{size:14}),disabled:!m,onClick:()=>void Be(),children:`生成命令`}),(0,p.jsx)(VS,{icon:Y?(0,p.jsx)(fe,{size:14}):(0,p.jsx)(G,{size:14}),onClick:()=>ve(e=>!e),title:Y?`切到浅色`:`切到深色`}),(0,p.jsx)(VS,{icon:(0,p.jsx)(ce,{size:14}),onClick:()=>ie(!0),children:`设置`})]})]}),e===`list`?(0,p.jsx)(`main`,{className:`min-h-0 flex-1 overflow-y-auto bg-[#F4F5F2] px-6 py-7 dark:bg-[#111214]`,children:(0,p.jsxs)(`div`,{className:`mx-auto w-full max-w-[1080px]`,children:[(0,p.jsxs)(`div`,{className:`mb-5`,children:[(0,p.jsx)(`h1`,{className:`text-[20px] font-semibold tracking-tight ${wW}`,children:`画布`}),(0,p.jsx)(`p`,{className:`mt-1 text-[12px] leading-[1.6] ${TW}`,children:`每张画布就是一张工作流;编辑自动保存,点「生成命令」把它变成一条对话命令。`})]}),c&&n.length===0?(0,p.jsx)(`div`,{className:`py-16 text-center text-[13px] ${TW}`,children:`正在加载画布…`}):(0,p.jsxs)(p.Fragment,{children:[n.length===0?(0,p.jsx)(`div`,{className:`rounded-[8px] border border-dashed ${CW} py-14 text-center text-[13px] ${TW}`,children:`还没有画布,点右上角「新建画布」开始。`}):(0,p.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3`,children:n.map(e=>{let t=e.presetId?i.find(t=>t.id===e.presetId):null;return(0,p.jsxs)(`article`,{className:`flex min-h-[150px] flex-col rounded-[8px] border ${CW} bg-[#FCFCFA] p-4 dark:bg-[#17181B]`,children:[(0,p.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,p.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[O===e.id?(0,p.jsx)(AD,{size:`small`,autoFocus:!0,maxLength:60,value:A,onChange:e=>j(e.target.value),onBlur:()=>void tt(e),onPressEnter:e=>e.currentTarget.blur(),onKeyDown:e=>{e.key===`Escape`&&(M.current=!0,e.currentTarget.blur())},"aria-label":`重命名画布 ${e.name}`}):(0,p.jsx)(`button`,{type:`button`,onClick:()=>Ie(e.id),title:e.name,className:`block max-w-full text-left`,children:(0,p.jsx)(`h2`,{className:`truncate text-[15px] font-semibold ${wW}`,children:e.name})}),(0,p.jsxs)(`p`,{className:`mt-1 text-[11px] leading-[1.6] ${EW}`,children:[e.nodeCount,` 个节点 · 更新于 `,MW(e.updatedAt)]}),o[e.id]!==void 0&&(0,p.jsxs)(`p`,{className:`mt-0.5 truncate text-[11px] leading-[1.6] ${TW}`,title:o[e.id]||`没有调度卡;生成命令前先补一张`,children:[`对话入口:`,o[e.id]||`未设置(生成命令前先补一张调度卡)`]})]}),(0,p.jsxs)(`div`,{className:`flex shrink-0 flex-col items-end gap-1`,children:[(0,p.jsx)(WO,{color:t?`blue`:`default`,style:{marginInlineEnd:0},children:t?t.name:`自定义`}),e.hasDraft&&(0,p.jsx)(WO,{color:`gold`,style:{marginInlineEnd:0},children:`草稿`})]})]}),(0,p.jsxs)(`div`,{className:`mt-auto flex flex-wrap items-center gap-1 pt-3`,children:[(0,p.jsx)(VS,{size:`small`,type:`primary`,onClick:()=>Ie(e.id),children:`编辑`}),(0,p.jsx)(VS,{size:`small`,type:`text`,onClick:()=>et(e),children:`重命名`}),(0,p.jsx)(VS,{size:`small`,type:`text`,danger:!0,disabled:n.length<=1,title:n.length<=1?`至少要保留一张画布`:void 0,onClick:()=>void nt(e),children:`删除`})]})]},e.id)})}),Xe.length>0&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`div`,{className:`mb-3 mt-8 flex flex-wrap items-baseline gap-2`,children:[(0,p.jsx)(`h2`,{className:`text-[13px] font-semibold ${wW}`,children:`还没有画布的旧预设`}),(0,p.jsx)(`span`,{className:`text-[11px] ${EW}`,children:`从旧预设生成一张画布,再编辑并生成命令`})]}),(0,p.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3`,children:Xe.map(e=>(0,p.jsxs)(`article`,{className:`flex min-h-[150px] flex-col rounded-[8px] border border-dashed ${CW} bg-[#F9F9F6] p-4 dark:bg-[#151617]`,children:[(0,p.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,p.jsx)(`h2`,{className:`min-w-0 flex-1 truncate text-[15px] font-semibold ${wW}`,title:e.name,children:e.name}),(0,p.jsx)(WO,{style:{marginInlineEnd:0,flexShrink:0},children:e.source===`bundle`?`bundle`:`自定义`})]}),(0,p.jsx)(`p`,{className:`mt-1 line-clamp-3 text-[12px] leading-[1.6] ${TW}`,children:e.description||`没有描述`}),(0,p.jsx)(`div`,{className:`mt-auto pt-3`,children:(0,p.jsx)(VS,{size:`small`,loading:b===e.id,onClick:()=>void $e(e),children:`创建画布`})})]},e.id))})]})]})]})}):(0,p.jsxs)(`main`,{className:`relative min-h-0 flex-1`,children:[(0,p.jsxs)(`div`,{className:`pointer-events-none absolute left-4 top-[12px] z-10 flex items-center gap-1.5 rounded-[4px] bg-[#FCFCFA]/90 px-2 py-1 text-[11px] text-[#6b6b66] dark:bg-[#17181b]/90 dark:text-[#8b8b85]`,children:[(0,p.jsx)(`span`,{className:`h-[5px] w-[5px] rounded-full`,style:{background:B?B.mock?`#B4451F`:`#24543F`:`#b9bcb4`}}),B?B.mock?`mock`:`real`:`连接中`]}),m?(0,p.jsx)(BU,{board:m,selectedId:v,running:De,onSelect:y,onMove:Ue,onDerive:We,onConnect:Ge}):(0,p.jsx)(`div`,{className:`grid h-full place-items-center text-[13px] text-[#8a93a3]`,children:`正在加载画布…`})]}),e===`board`&&m&&Je&&(0,p.jsx)(sW,{node:Je,nodes:m.nodes,edges:m.edges,boardId:m.id,skills:F,servers:L,catalog:W,bridge:te,running:De,onPatch:e=>Ve(Je.id,e),onDerive:e=>We(Je.id,e),onVerify:e=>void qe(Je.id,e),onEdgesChange:He,onRefreshModels:()=>{Ee.current=Date.now(),JA.getModels(!0).then(ee).catch(e=>X(`刷新模型失败:${e.message}`,`err`)),JA.getBridge().then(ne).catch(()=>{})},onRerun:()=>void ze([Je.id]),onDelete:()=>void Ke(Je.id),onClose:()=>y(null)}),(0,p.jsx)(gW,{open:re,config:B,servers:L,onClose:()=>ie(!1),onSaved:e=>{H(t=>t&&{...t,mock:e.mock}),JA.getMcp().then(e=>R(e.servers)).catch(()=>{}),X(`设置已保存`)},onError:e=>X(e,`err`)}),(0,p.jsx)(xW,{open:ae,boardId:d,boardName:g,onClose:()=>oe(!1)}),(0,p.jsx)(PD,{open:S,title:`新建画布`,centered:!0,getContainer:()=>it.current??document.body,okText:`创建`,cancelText:`取消`,confirmLoading:E,okButtonProps:{disabled:!w.trim()},onOk:()=>void Qe(),onCancel:()=>C(!1),children:(0,p.jsx)(AD,{autoFocus:!0,maxLength:60,placeholder:`画布名称,例如「活动文案」`,value:w,onChange:e=>T(e.target.value),onPressEnter:()=>{w.trim()&&!E&&Qe()}})}),ye&&(0,p.jsx)(`div`,{className:`absolute bottom-6 left-1/2 z-50 -translate-x-1/2 rounded-lg px-4 py-2 text-[13px] shadow-lg ${ye.kind===`err`?`bg-[#ffebee] text-[#c62828] dark:bg-[#3a1b1f] dark:text-[#ff9a9a]`:`bg-[#1C1C1A] text-white dark:bg-[#e7e9ee] dark:text-[#0f1116]`}`,children:ye.msg})]})})}function AW(e){let t=`n-${Date.now().toString(36)}`,n=t,r=2;for(;e.some(e=>e.id===n);)n=`${t}-${r++}`;return n}function jW(e){let t=e.nodes.find(e=>e.type===`orchestrator`)??(e.nodes.length===1?e.nodes[0]:null);return t?t.label||t.id:null}function MW(e){if(!e)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}function NW(e,t,n){let r=new Set,i=[n];for(;i.length;){let n=i.pop();if(n===t)return!0;if(!r.has(n)){r.add(n);for(let t of e)t.from===n&&i.push(t.to)}}return!1}var PW=`http://127.0.0.1:8791`;function FW(e){return String(e??``).trim().replace(/\/+$/,``)}function IW(e){let t=FW(e);return t&&(PW=t),PW}function LW(){return PW}function RW(){try{if(document.body&&document.body.hasAttribute(`data-ds-dark-theme`))return`dark`}catch{}try{if(document.documentElement.classList.contains(`dark`))return`dark`}catch{}try{if(window.matchMedia&&window.matchMedia(`(prefers-color-scheme: dark)`).matches)return`dark`}catch{}return`light`}function zW(e){let t=RW(),n=()=>{let n=RW();n!==t&&(t=n,e(n))},r=[];try{if(typeof MutationObserver<`u`){let e=new MutationObserver(n);document.body&&(e.observe(document.body,{attributes:!0,attributeFilter:[`data-ds-dark-theme`,`class`]}),r.push(e));let t=new MutationObserver(n);t.observe(document.documentElement,{attributes:!0,attributeFilter:[`class`,`data-theme`]}),r.push(t)}}catch{}let i=null,a=()=>n();try{i=window.matchMedia(`(prefers-color-scheme: dark)`),i.addEventListener(`change`,a)}catch{i=null}return window.addEventListener(`focus`,n),()=>{for(let e of r)e.disconnect();if(i)try{i.removeEventListener(`change`,a)}catch{}window.removeEventListener(`focus`,n)}}var BW=`__AGENTFLOW_HOST__`,VW=`data-agentflow-style`,HW=[0,1e3,2500],UW=6e3,WW=2e3;function GW(){try{let e=globalThis[BW];return e&&typeof e==`object`?e:null}catch{return null}}function KW(e){let t={apiBase:e.apiBase,theme:e.theme,boardId:e.boardId,remote:!0};return globalThis[BW]=t,t}var qW=`
|
|
340
340
|
@keyframes af-host-spin { to { transform: rotate(360deg); } }
|
|
341
341
|
.af-host, .af-host *, .af-host *::before, .af-host *::after { box-sizing: border-box; }
|
|
342
342
|
.af-host-spinner {
|
package/package.json
CHANGED
|
@@ -345,4 +345,4 @@ html body {
|
|
|
345
345
|
.dark .af-panel .af-row:hover {
|
|
346
346
|
background: #1d1e1b;
|
|
347
347
|
}
|
|
348
|
-
`,uW=`w-full rounded-lg border border-[#E1E2DD] bg-[#FCFCFA] px-2.5 py-2 text-[13px] leading-[1.65] text-[#1B1B18] outline-none transition-colors placeholder:text-[#9a9a92] focus:border-[#24543F] focus:bg-white dark:border-[#33353B] dark:bg-[#17181B] dark:text-[#EDEDE8] dark:focus:border-[#6aa583] dark:focus:bg-[#1B1C20]`,dW=`rounded-[4px] px-2.5 py-1.5 text-[12px] text-[#5b6472] transition-colors hover:bg-[#EFEFEA] dark:text-[#a3a39b] dark:hover:bg-[#232421]`;function fW(e){return(0,$.jsxs)(`aside`,{className:`af-panel absolute bottom-0 right-0 top-14 z-30 flex w-[420px] flex-col border-l border-[#E3E4DF] bg-[#FCFCFA] dark:border-[#262724] dark:bg-[#17181B]`,role:`complementary`,"aria-label":`节点详情`,children:[(0,$.jsx)(`style`,{children:lW}),(0,$.jsx)(mW,{...e},e.node.id)]})}function pW(e,...t){let n=e.trim().toLowerCase();return!n||t.some(e=>String(e??``).toLowerCase().includes(n))}function mW(e){let{node:t,nodes:n,edges:r,boardId:i,skills:a,servers:o,catalog:s,bridge:c,running:l,onPatch:u,onDerive:d,onVerify:f,onRerun:p,onRefreshModels:m,onEdgesChange:h,onDelete:g,onClose:v}=e,[y,b]=(0,_.useState)(t.label),[x,S]=(0,_.useState)(t.task),[C,w]=(0,_.useState)(t.criteria),[T,E]=(0,_.useState)(rW),[D,O]=(0,_.useState)(0),[k,A]=(0,_.useState)(``),[j,M]=(0,_.useState)(``),[N,F]=(0,_.useState)(null),I=(0,_.useRef)(null),L=(0,_.useRef)(null);(0,_.useEffect)(()=>{yW(I.current)},[x]),(0,_.useEffect)(()=>{yW(L.current)},[C]);let z=(0,_.useRef)(u);(0,_.useEffect)(()=>{z.current=u},[u]);let B=(0,_.useRef)({}),V=(0,_.useRef)(null),H=(0,_.useCallback)(()=>{V.current!==null&&(window.clearTimeout(V.current),V.current=null);let e=B.current;Object.keys(e).length&&(B.current={},z.current(e))},[]),U=(0,_.useCallback)(e=>{B.current={...B.current,...e},V.current!==null&&window.clearTimeout(V.current),V.current=window.setTimeout(H,400)},[H]);(0,_.useEffect)(()=>()=>{if(V.current!==null){window.clearTimeout(V.current),V.current=null;let e=B.current;Object.keys(e).length&&z.current(e)}},[]),(0,_.useEffect)(()=>{let e=e=>{(e.metaKey||e.ctrlKey)&&String(e.key).toLowerCase()===`s`&&H()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[H]);let[W,ee]=(0,_.useState)(r);(0,_.useEffect)(()=>{ee(r)},[r]);let ne=new Set(W.filter(e=>e.to===t.id).map(e=>e.from)),re=n.filter(e=>e.id!==t.id);function ie(e){let n=[...W.filter(e=>e.to!==t.id),...e.map(e=>({from:e,to:t.id}))];ee(n),h(n)}function ae(e,n){let r=new Set(t.skills);n?r.add(e):r.delete(e),u({skills:[...r]})}let G=s?.providers??[],K=t.provider&&t.model?`${t.provider}/${t.model}`:``,oe=G.some(e=>e.id===t.provider&&e.models.some(e=>e.id===t.model)),ce=t.model&&!oe?t.model:``,q=oe?G.find(e=>e.id===t.provider)?.models.find(e=>e.id===t.model)??null:null,le=q?.levels??[],ue=q?.defaultLevel??``,de=G.every(e=>!e.models.length),fe=new Set,pe=[];for(let e of T){let{provider:t,model:n}=aW(e.value),r=G.find(e=>e.id===t),i=r?.models.find(e=>e.id===n);r&&i&&!fe.has(e.value)&&(fe.add(e.value),pe.push({title:i.name,label:`${r.label} · ${i.name}`,value:`${eW}${e.value}`}))}let me=[];pe.length&&me.push({title:`最近使用`,label:`最近使用`,value:QU,selectable:!1,children:pe}),ce&&me.push({title:`当前值`,label:`当前值`,value:$U,selectable:!1,children:[{title:ce,label:oW(t.provider,ce),value:ZU}]});for(let e of G){let t=e.models.length;me.push({title:t?`${e.label}(${t})`:e.label,label:e.label,value:`p:${e.id}`,selectable:!1,children:e.error?[{title:e.error,label:e.error,value:`e:${e.id}`,disabled:!0}]:e.models.map(t=>({title:t.name,label:`${e.label} · ${t.name}`,value:`${e.id}/${t.id}`}))})}let he=G.find(e=>e.id===t.provider),ge=T.map(e=>e.provider).find(e=>G.some(t=>t.id===e)),ve=he?.id??ge??``,ye=[...pe.length?[QU]:[],...ce?[$U]:[],...ve?[`p:${ve}`]:[]],be=oe?K:ce?ZU:void 0,Y=t.fallback??[],Se=t.fallbackEfforts??{},Ce=new Set(Y),we=G.map(e=>{let t=e.models.length,n=e.error?[{title:e.error,label:e.error,value:`e:${e.id}`,disabled:!0}]:e.models.filter(t=>{let n=`${e.id}/${t.id}`;return n!==K&&!Ce.has(n)}).map(t=>({title:t.name,label:`${e.label} · ${t.name}`,value:`${e.id}/${t.id}`}));return{title:t?`${e.label}(${t})`:e.label,label:e.label,value:`p:${e.id}`,selectable:!1,children:n}}).filter(e=>e.children.length>0),Te=ve?[`p:${ve}`]:[];function Ee(e){if(!e||e===ZU)return;let n=e.startsWith(eW)?e.slice(2):e,{provider:r,model:i}=aW(n),a=G.find(e=>e.id===r),o=a?.models.find(e=>e.id===i);if(!a||!o)return;let s=o.levels.includes(t.reasoningEffort??``)?t.reasoningEffort??``:``,c={value:n,label:o.name,provider:r},l=[c,...T.filter(e=>e.value!==c.value)].slice(0,nW);E(l),iW(l),u({provider:r,model:i,reasoningEffort:s})}function De(e){let{provider:t,model:n}=aW(e),r=G.find(e=>e.id===t),i=r?.models.find(e=>e.id===n);return!r||!i?{label:`${e}(不在 DSH 目录里)`,levels:[]}:{label:`${r.label} · ${i.name}`,levels:i.levels}}function Oe(e,t){u({fallback:e,fallbackEfforts:t})}function ke(e){e&&e.includes(`/`)&&!Ce.has(e)&&(Oe([...Y,e],{...Se,[e]:``}),O(e=>e+1))}function Ae(e){let t={...Se};delete t[e],Oe(Y.filter(t=>t!==e),t)}function je(e,t){Oe(Y,{...Se,[e]:t})}let Me=sW[t.status]??sW.idle,Ne=t.type===`orchestrator`,Pe=n.some(e=>e.id!==t.id&&e.type===`orchestrator`),Fe=NU.map(e=>({...e,disabled:e.value===`orchestrator`&&Pe})),Ie=cW.find(e=>e.value===(t.verify??``))??cW[0],Le=t.status===`review`,Re=a.filter(e=>pW(k,e.name,e.description)),ze=o.map(e=>({...e,tools:e.tools.filter(e=>pW(j,e.name,e.description))})).filter(e=>pW(j,e.name)||e.tools.length>0),Be=j.trim()?ze.map(e=>e.name):N??o.filter(e=>e.ok&&e.tools.length).slice(0,1).map(e=>e.name);return(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`header`,{className:`flex shrink-0 items-center gap-2 border-b ${YU} bg-[#FAFAF7] px-5 py-3.5 dark:bg-[#1B1C20]`,children:[(0,$.jsx)(`input`,{value:y,onChange:e=>{let t=e.target.value;b(t),U({label:t})},onBlur:H,onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur()},placeholder:`节点名称`,"aria-label":`节点名称`,className:`min-w-0 flex-1 rounded-[3px] border-0 bg-transparent p-0 text-[17px] font-semibold tracking-tight outline-none placeholder:text-[#a8a8a0] focus-visible:ring-2 focus-visible:ring-[#24543F]/30 dark:placeholder:text-[#6f6f68] dark:focus-visible:ring-[#6aa583]/40 ${KU}`}),(0,$.jsxs)(`span`,{className:`flex shrink-0 items-center gap-1.5 text-[12px] ${qU}`,children:[(0,$.jsx)(`span`,{className:`h-[6px] w-[6px] rounded-full ${Me.dot}`}),Me.label]}),(0,$.jsx)(`button`,{type:`button`,onClick:v,"aria-label":`关闭详情`,title:`关闭`,className:`-mr-1 grid h-8 w-8 shrink-0 place-items-center rounded-[4px] text-[#6b6b66] transition-colors hover:bg-[#EFEFEA] dark:text-[#8b8b85] dark:hover:bg-[#232421]`,children:(0,$.jsx)(xe,{size:16})})]}),t.verdict&&(0,$.jsxs)(`div`,{className:`shrink-0 border-b px-5 py-2 text-[12px] leading-[1.5] ${YU} ${t.verdict.pass?`bg-[#EEF3EF] text-[#24543F] dark:bg-[#1B2A22] dark:text-[#8FC3A7]`:`bg-[#FBEFEA] text-[#B4451F] dark:bg-[#2A1C17] dark:text-[#E08A6A]`}`,children:[vW(t.verdict.by),` `,t.verdict.pass?`通过`:`未通过`,t.verdict.reason?`:${t.verdict.reason}`:``]}),t.error&&(0,$.jsx)(`div`,{className:`shrink-0 border-b px-5 py-2 text-[12px] leading-[1.5] ${YU} bg-[#FBEFEA] text-[#B4451F] dark:bg-[#2A1C17] dark:text-[#E08A6A]`,children:t.error}),(0,$.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 pb-6 pt-3`,children:[Ne?null:(0,$.jsxs)(hW,{title:`节点类型`,children:[(0,$.jsx)(Fb,{value:t.type||`llm`,onChange:e=>u({type:e}),options:Fe,"aria-label":`节点类型`,className:`w-full`,size:`middle`}),Pe?(0,$.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${JU}`,children:`画布已有根节点,这张卡不能再设为调度卡。`}):null]}),(0,$.jsx)(hW,{title:`模型`,extra:(0,$.jsxs)(`button`,{type:`button`,onClick:m,title:`重新读取 DSH 的模型目录`,className:`flex items-center gap-1 text-[11px] transition-opacity hover:opacity-70 ${JU}`,children:[(0,$.jsx)(se,{size:11}),`刷新`]}),children:(0,$.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,$.jsx)(Lk,{value:be,placeholder:`选择模型`,showSearch:!0,treeNodeFilterProp:`title`,treeDefaultExpandAll:!1,treeDefaultExpandedKeys:ye,treeNodeLabelProp:`label`,treeData:me,onChange:Ee,"aria-label":`模型`,className:`w-full`,size:`middle`}),(0,$.jsx)(Fb,{value:t.reasoningEffort??``,onChange:e=>u({reasoningEffort:e}),disabled:!le.length,"aria-label":`推理强度`,title:le.length?`推理强度`:`当前模型没有可选推理档位`,options:[{value:``,label:`推理强度:模型默认${ue?`(${ue})`:``}`},...le.map(e=>({value:e,label:e}))],className:`w-full`,size:`middle`}),de&&(0,$.jsxs)(`div`,{className:`flex items-start gap-1.5 text-[11px] leading-[1.6] ${qU}`,children:[(0,$.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-50`}),(0,$.jsx)(`span`,{children:`没读到 DSH 的模型目录,检查 DSH 凭据或网络。`})]}),(0,$.jsxs)(`div`,{className:`flex items-start gap-1.5 border-t border-[#EDEEE9] pt-2 text-[11px] leading-[1.6] dark:border-[#2A2C31] ${c&&!c.healthy?`text-[#B4451F] dark:text-[#e08a6a]`:qU}`,children:[(0,$.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-60`}),(0,$.jsxs)(`span`,{children:[`模型通道:DSH 内核(未连接时不可跑图)`,c&&!c.healthy?` · ${c.reason||`原因未知`}`:``]})]})]})}),(0,$.jsx)(hW,{title:`兜底模型`,extra:Y.length?(0,$.jsxs)(`span`,{className:`text-[11px] ${qU}`,children:[Y.length,` 个 · 按顺序重试`]}):void 0,children:(0,$.jsxs)(`div`,{className:`space-y-1.5`,children:[Y.map(e=>{let t=De(e);return(0,$.jsxs)(`div`,{className:`flex min-h-[32px] items-center gap-2 border-b py-1 last:border-b-0 ${YU}`,children:[(0,$.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[12px] ${KU}`,title:t.label,children:t.label}),(0,$.jsx)(Fb,{size:`small`,value:Se[e]??``,disabled:!t.levels.length,title:t.levels.length?`这条兜底的推理强度`:`该模型没有可选推理档位`,options:[{value:``,label:`模型默认`},...t.levels.map(e=>({value:e,label:e}))],onChange:t=>je(e,t),"aria-label":`${t.label} 的推理强度`,style:{width:104}}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>Ae(e),"aria-label":`移除兜底模型 ${t.label}`,title:`移除`,className:`grid h-7 w-7 shrink-0 place-items-center rounded-[4px] transition-colors hover:bg-[#FBEFEA] hover:text-[#B4451F] dark:hover:bg-[#2A1C17] dark:hover:text-[#e08a6a] ${JU}`,children:(0,$.jsx)(xe,{size:13})})]},e)}),(0,$.jsx)(Lk,{onChange:ke,placeholder:`添加兜底模型…`,showSearch:!0,treeNodeFilterProp:`title`,treeDefaultExpandAll:!1,treeDefaultExpandedKeys:Te,treeNodeLabelProp:`label`,treeData:we,"aria-label":`添加兜底模型`,className:`w-full`,size:`middle`},D),(0,$.jsxs)(`div`,{className:`flex items-start gap-1.5 pt-0.5 text-[11px] leading-[1.6] ${qU}`,children:[(0,$.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-50`}),(0,$.jsx)(`span`,{children:`兜底模型:主模型失败后按顺序尝试,可单独设推理强度`})]})]})}),(0,$.jsxs)(hW,{title:Ne?`人格`:`任务`,children:[(0,$.jsx)(`textarea`,{ref:I,rows:3,value:x,onChange:e=>{S(e.target.value),U({task:e.target.value}),yW(e.currentTarget)},onBlur:H,placeholder:Ne?`默认:只负责和用户对话,再严格按后续节点的 AgentFlow 流执行(可自己改)`:`写清楚这张卡要做什么…`,className:`${uW} max-h-[240px] resize-none overflow-y-auto`}),Ne&&(0,$.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${JU}`,children:`默认人格只是起点,可以自己改:它只负责和用户对话,确认需求后严格按后续节点的流程执行。`})]}),(0,$.jsx)(hW,{title:`完成标准`,children:(0,$.jsx)(`textarea`,{ref:L,rows:2,value:C,onChange:e=>{w(e.target.value),U({criteria:e.target.value}),yW(e.currentTarget)},onBlur:H,placeholder:`做到什么程度算完成…`,className:`${uW} max-h-[200px] resize-none overflow-y-auto`})}),(0,$.jsxs)(hW,{title:`结果判断`,children:[(0,$.jsx)(`div`,{role:`radiogroup`,"aria-label":`结果判断`,className:`flex gap-[2px] rounded-[6px] bg-[#EFEFEA] p-[3px] dark:bg-[#232421]`,children:cW.map(e=>{let n=(t.verify??``)===e.value;return(0,$.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":n,title:e.desc,onClick:()=>u({verify:e.value}),className:`flex-1 rounded-[4px] px-1 py-[5px] text-[13px] leading-[1.3] transition-colors ${n?`bg-white text-[#1B1B18] shadow-[0_1px_2px_rgba(0,0,0,0.06)] dark:bg-[#3A3B35] dark:text-[#e8e8e4]`:`hover:text-[#1B1B18] dark:hover:text-[#e8e8e4] ${qU}`}`,children:e.label},e.value||`none`)})}),(0,$.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${JU}`,children:Ie.desc}),(t.verify??``)===`jev`&&(0,$.jsx)(`p`,{className:`mt-1.5 rounded-[4px] border border-[#E9D9B8] bg-[#FBF4E6] px-2 py-1.5 text-[11px] leading-[1.5] text-[#8a6220] dark:border-[#4a3a1c] dark:bg-[#2a2314] dark:text-[#e0b866]`,children:`需要本机安装 jev(TypeSafe)并配置 API key,否则这张卡跑到判定时会失败。`})]}),(0,$.jsx)(hW,{title:`技能`,extra:(0,$.jsxs)(`span`,{className:`text-[11px] ${JU}`,children:[`已选 `,t.skills.length]}),children:a.length===0?(0,$.jsx)(gW,{children:`没有找到技能`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(PD,{value:k,onChange:e=>A(e.target.value),allowClear:!0,size:`middle`,placeholder:`搜索技能名或描述…`,"aria-label":`搜索技能`,prefix:(0,$.jsx)(J,{size:12,className:JU}),className:`mb-2`}),Re.length===0?(0,$.jsxs)(gW,{children:[`没有匹配「`,k.trim(),`」的技能`]}):null,(0,$.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto`,children:Re.map(e=>{let n=t.skills.includes(e.name);return(0,$.jsx)(YT,{className:`af-row`,checked:n,onChange:t=>ae(e.name,t.target.checked),title:e.description,children:(0,$.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`shrink-0 text-[13px] ${KU}`,children:e.name}),(0,$.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-right text-[11px] ${JU}`,children:e.description||`无描述`})]})},e.name)})})]})}),(0,$.jsx)(hW,{title:`MCP 工具`,extra:(0,$.jsxs)(`span`,{className:`text-[11px] ${JU}`,children:[`已选 `,t.tools.length]}),children:o.length===0?(0,$.jsx)(gW,{children:`还没配置 MCP 服务器`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(PD,{value:j,onChange:e=>M(e.target.value),allowClear:!0,size:`middle`,placeholder:`搜索服务器或工具…`,"aria-label":`搜索 MCP 工具`,prefix:(0,$.jsx)(J,{size:12,className:JU}),className:`mb-2`}),ze.length===0?(0,$.jsxs)(gW,{children:[`没有匹配「`,j.trim(),`」的工具`]}):null,(0,$.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto af-tree`,children:(0,$.jsx)(FO,{checkable:!0,selectable:!1,expandedKeys:Be,onExpand:e=>F(e),treeData:ze.map(e=>({key:e.name,selectable:!1,title:(0,$.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`h-[5px] w-[5px] shrink-0 rounded-full ${e.ok?`bg-[#24543F] dark:bg-[#6aa583]`:`bg-[#B4451F] dark:bg-[#e08a6a]`}`}),(0,$.jsx)(`span`,{className:`text-[12px] font-medium ${KU}`,children:e.name}),(0,$.jsxs)(`span`,{className:`text-[11px] ${JU}`,children:[e.tools.length,` 个工具`]}),!e.ok&&(0,$.jsx)(`span`,{className:`text-[11px] text-[#B4451F] dark:text-[#e08a6a]`,children:`连接失败`})]}),children:e.tools.map(t=>({key:`${e.name}.${t.name}`,title:(0,$.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`shrink-0 text-[13px] ${KU}`,children:t.name}),(0,$.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-right text-[11px] ${JU}`,children:t.description})]})}))})),checkedKeys:t.tools,onCheck:e=>{let t=Array.isArray(e)?e:e.checked;u({tools:t.filter(e=>String(e).includes(`.`))})}})})]})}),Ne?null:(0,$.jsx)(hW,{title:`上游`,children:re.length===0?(0,$.jsx)(gW,{children:`还没有其它卡片`}):(0,$.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto`,children:re.map(e=>{let n=ne.has(e.id),r=!n&&_W(W,t.id,e.id),i=n?[...ne].filter(t=>t!==e.id):[...ne,e.id];return(0,$.jsx)(YT,{className:`af-row ${r?`af-row-disabled`:``}`,checked:n,disabled:r,onChange:()=>ie(i),children:(0,$.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[13px] ${KU}`,children:e.label||e.id}),r&&(0,$.jsx)(`span`,{className:`shrink-0 text-[11px] ${JU}`,children:`会成环`})]})},e.id)})})})]}),Le&&(0,$.jsxs)(`div`,{className:`shrink-0 border-t ${YU} bg-[#FAEFE6] px-5 py-3 dark:bg-[#2A1C17]`,children:[(0,$.jsx)(`p`,{className:`text-[12px] text-[#B4451F] dark:text-[#e08a6a]`,children:`这张卡跑完了,等你判断结果`}),(0,$.jsxs)(`div`,{className:`mt-2 flex gap-2`,children:[(0,$.jsx)(`button`,{type:`button`,onClick:()=>f(!0),className:`h-8 flex-1 rounded-[4px] bg-[#24543F] text-[13px] font-medium text-white transition-colors hover:bg-[#1D4634] dark:bg-[#3F7A5F] dark:hover:bg-[#4B8B6D]`,children:`通过`}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>f(!1),className:`h-8 flex-1 rounded-[4px] text-[13px] text-[#6b6b66] transition-colors hover:bg-white/60 dark:text-[#a3a39b] dark:hover:bg-[#232421]`,children:`打回重跑`})]})]}),(0,$.jsxs)(`footer`,{className:`shrink-0 border-t ${YU} bg-[#FAFAF7] px-5 py-3 dark:bg-[#1B1C20]`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,$.jsxs)(`button`,{type:`button`,onClick:p,disabled:l,className:`flex h-8 flex-1 items-center justify-center gap-1.5 rounded-[4px] bg-[#24543F] text-[13px] font-medium text-white transition-colors hover:bg-[#1D4634] disabled:cursor-not-allowed disabled:opacity-50 dark:bg-[#3F7A5F] dark:hover:bg-[#4B8B6D]`,children:[l?(0,$.jsx)(te,{size:13,className:`animate-spin`}):(0,$.jsx)(se,{size:13}),l?`运行中…`:`重跑此卡`]}),Ne?null:(0,$.jsxs)(`button`,{type:`button`,onClick:()=>d(`prev`),className:`${dW} flex items-center gap-1`,children:[(0,$.jsx)(R,{size:13}),`加上游`]}),(0,$.jsxs)(`button`,{type:`button`,onClick:()=>d(`next`),className:`${dW} flex items-center gap-1`,children:[(0,$.jsx)(P,{size:13}),`加下游`]})]}),(0,$.jsx)(`div`,{className:`mt-1 flex justify-end`,children:(0,$.jsxs)(`button`,{type:`button`,onClick:g,disabled:Ne,title:Ne?`根节点是对话入口(人格来源),不能删除`:void 0,className:`flex items-center gap-1.5 rounded-[4px] px-2.5 py-1.5 text-[12px] text-[#B4451F] transition-colors hover:bg-[#FBEFEA] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent dark:text-[#e08a6a] dark:hover:bg-[#2A1C17]`,children:[(0,$.jsx)(_e,{size:13}),`删除此卡`]})})]})]})}function hW({title:e,extra:t,children:n}){return(0,$.jsxs)(`section`,{className:`mt-3 rounded-xl border p-3 first:mt-1 ${XU}`,children:[(0,$.jsxs)(`div`,{className:`mb-2.5 flex items-center justify-between gap-2`,children:[(0,$.jsx)(`h3`,{className:`text-[12px] font-semibold tracking-[0.01em] ${KU}`,children:e}),t]}),n]})}function gW({children:e}){return(0,$.jsx)(`p`,{className:`py-1 text-[12px] leading-[1.6] ${JU}`,children:e})}function _W(e,t,n){if(t===n)return!0;let r=new Set([t]),i=[t];for(;i.length;){let t=i.pop();for(let a of e)if(a.from===t){if(a.to===n)return!0;r.has(a.to)||(r.add(a.to),i.push(a.to))}}return!1}function vW(e){return e===`human`?`人工`:e===`jev`?`jev`:e===`self`?`自评`:e||`系统`}function yW(e){e&&(e.style.height=`auto`,e.style.height=`${e.scrollHeight}px`)}var{Text:bW}=RA;function xW({open:e,config:t,servers:n,onClose:r,onSaved:i,onError:a}){let o=t,[s,c]=(0,_.useState)(o?.mock??!1),[l,u]=(0,_.useState)(!1),[d,f]=(0,_.useState)(null),[p,m]=(0,_.useState)(!1),h=(0,_.useRef)(a);(0,_.useEffect)(()=>{h.current=a},[a]),(0,_.useEffect)(()=>{e&&c(o?.mock??!1)},[e,o?.mock]),(0,_.useEffect)(()=>{if(!e)return;let t=!1;return m(!0),QA.getBridge().then(e=>{t||f(e)}).catch(e=>{t||h.current(`读取模型通道状态失败:${e.message}`)}).finally(()=>{t||m(!1)}),()=>{t=!0}},[e]);async function g(){if(p)return;m(!0);let[e,t]=await Promise.allSettled([QA.getBridge(),QA.getModels(!0)]);e.status===`fulfilled`?f(e.value):h.current(`读取模型通道状态失败:${e.reason.message}`),t.status===`rejected`&&h.current(`重新读取模型目录失败:${t.reason.message}`),m(!1)}async function v(e){if(l||!t)return;let n=s;c(e),u(!0);try{let t=await QA.putConfig({mock:e}),n=typeof t?.mock==`boolean`?t.mock:e;c(n),i({mock:n})}catch(e){c(n),a(`切换 mock 失败:${e.message}`)}finally{u(!1)}}let y=Object.entries(o?.providers??{}),b=o?.mcpServers??n.map(e=>({name:e.name})),x=o?.skillDirs?.length?o.skillDirs:o?.dshPaths?.skills?[o.dshPaths.skills]:[],S=d?d.healthy?(0,$.jsx)(JO,{color:`success`,style:{marginInlineEnd:0},children:`已连接`}):(0,$.jsx)(JO,{color:`warning`,style:{marginInlineEnd:0},children:`未连接`}):(0,$.jsx)(bW,{type:`secondary`,style:{fontSize:12},children:`读取中…`}),C=d&&(d.lastError||d.reason)||``;return(0,$.jsxs)(RD,{open:e,title:`设置`,width:640,centered:!0,getContainer:()=>document.querySelector(`.af-canvas`)??document.body,onCancel:r,styles:{body:{maxHeight:`calc(100vh - 220px)`,overflowY:`auto`,paddingTop:12}},footer:(0,$.jsx)(uD,{justify:`flex-end`,children:(0,$.jsx)(GS,{onClick:r,children:`关闭`})}),children:[(0,$.jsx)(Kl,{type:`info`,showIcon:!0,title:`模型、MCP 服务器、技能都来自 DSH 的配置。要增删改请到 DSH 的 cordis.patch.yml,AgentFlow 这边只读。`,description:o?.dshPaths?.patch?(0,$.jsxs)(bW,{type:`secondary`,style:{fontSize:12,wordBreak:`break-all`},children:[`patch:`,(0,$.jsx)(bW,{code:!0,style:{fontSize:12},children:o.dshPaths.patch})]}):void 0}),(0,$.jsx)(SW,{title:`模型`,extra:(0,$.jsxs)(bW,{type:`secondary`,style:{fontSize:11},children:[y.length,` 个`]}),children:y.length===0?(0,$.jsx)(ib,{image:ib.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置模型提供商`}):y.map(([e,t])=>(0,$.jsx)(Hw,{size:`small`,style:{marginBottom:12},title:(0,$.jsx)(bW,{strong:!0,style:{fontSize:14},children:t.label||e}),extra:t.hasKey?(0,$.jsx)(JO,{color:`green`,style:{marginInlineEnd:0},children:`已配置 key`}):(0,$.jsx)(JO,{color:`red`,style:{marginInlineEnd:0},children:`缺 key`}),children:(0,$.jsx)(VE,{size:`small`,column:1,colon:!1,items:[{key:`provider`,label:`provider`,children:(0,$.jsx)(bW,{code:!0,children:e})},{key:`baseURL`,label:`baseURL`,children:(0,$.jsx)(bW,{code:!0,children:t.baseURL||`—`})},{key:`model`,label:`model`,children:(0,$.jsx)(bW,{code:!0,children:t.model||`—`})}]})},e))}),(0,$.jsxs)(SW,{title:`模型通道`,extra:(0,$.jsx)(GS,{size:`small`,loading:p,onClick:()=>void g(),children:`刷新`}),children:[d&&!d.healthy&&(0,$.jsx)(Kl,{type:`warning`,showIcon:!0,style:{marginBottom:10},title:`DSH 未运行或插件未加载,画布不能调模型`}),(0,$.jsx)(VE,{size:`small`,bordered:!0,column:1,colon:!1,items:[{key:`status`,label:`状态`,children:S},{key:`infoPath`,label:`发现文件`,children:(0,$.jsx)(bW,{code:!0,style:{fontSize:12,wordBreak:`break-all`,userSelect:`text`},title:d?.dir,children:d?.infoPath||`—`})},{key:`version`,label:`版本`,children:d?.version==null?`—`:(0,$.jsx)(bW,{code:!0,children:d.version})},{key:`startedAt`,label:`启动时间`,children:CW(d?.startedAt??null)},{key:`providers`,label:`provider 数`,children:d?String(d.providers):`—`},{key:`modelCount`,label:`模型数`,children:d?String(d.modelCount):`—`},{key:`lastError`,label:`最后错误`,children:C?(0,$.jsx)(bW,{type:`danger`,style:{fontSize:12,wordBreak:`break-all`},children:C}):(0,$.jsx)(bW,{type:`secondary`,children:`—`})}]})]}),(0,$.jsx)(SW,{title:`MCP 服务器`,extra:(0,$.jsxs)(bW,{type:`secondary`,style:{fontSize:11},children:[b.length,` 个`]}),children:b.length===0?(0,$.jsx)(ib,{image:ib.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置 MCP 服务器`}):(0,$.jsx)(VE,{size:`small`,bordered:!0,column:1,colon:!1,items:b.map(e=>({key:e.name,label:(0,$.jsx)(bW,{strong:!0,style:{fontSize:13},children:e.name}),children:e.kind?(0,$.jsx)(JO,{style:{marginInlineEnd:0},children:e.kind}):(0,$.jsx)(bW,{type:`secondary`,children:`—`})}))})}),(0,$.jsx)(SW,{title:`技能目录`,extra:(0,$.jsxs)(bW,{type:`secondary`,style:{fontSize:11},children:[x.length,` 个`]}),children:x.length===0?(0,$.jsx)(ib,{image:ib.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置技能目录`}):(0,$.jsx)(uD,{vertical:!0,gap:6,children:x.map(e=>(0,$.jsx)(bW,{code:!0,style:{fontSize:12,wordBreak:`break-all`},children:e},e))})}),(0,$.jsx)(SW,{title:`运行模式`,children:(0,$.jsx)(Hw,{size:`small`,children:(0,$.jsxs)(uD,{align:`center`,justify:`space-between`,gap:16,children:[(0,$.jsxs)(`div`,{style:{minWidth:0},children:[(0,$.jsx)(bW,{strong:!0,style:{display:`block`,fontSize:15},children:`mock 模式`}),(0,$.jsx)(bW,{type:`secondary`,style:{display:`block`,fontSize:12},children:`AgentFlow 自己的开关,不属于 DSH 配置。打开后不真正调用模型。`})]}),(0,$.jsx)(qD,{checked:s,loading:l,disabled:!t,onChange:e=>void v(e)})]})})})]})}function SW({title:e,extra:t,children:n}){return(0,$.jsxs)(`section`,{style:{marginTop:20},children:[(0,$.jsxs)(uD,{align:`center`,justify:`space-between`,gap:8,style:{marginBottom:8},children:[(0,$.jsx)(bW,{strong:!0,style:{fontSize:13},children:e}),t]}),n]})}function CW(e){if(typeof e!=`number`||!Number.isFinite(e)||e<=0)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`}var{Text:wW}=RA,TW=`'SFMono-Regular', Menlo, Consolas, 'Liberation Mono', ui-monospace, monospace`;function EW({open:e,boardId:t,boardName:n,onClose:r}){let{token:i}=ik.useToken(),[a,o]=(0,_.useState)(null),[s,c]=(0,_.useState)(null),[l,u]=(0,_.useState)(!1),[d,f]=(0,_.useState)(``),[p,m]=(0,_.useState)([]),[h,g]=(0,_.useState)(!1),[v,y]=(0,_.useState)(null),b=(0,_.useCallback)(async()=>{g(!0);try{let e=await QA.listCommands();m(e.commands)}catch{m([])}finally{g(!1)}},[]);(0,_.useEffect)(()=>{e&&(o(null),c(null),u(!1),f(``),b())},[e,b]);async function x(){if(!l){u(!0),c(null),o(null);try{let e=d.trim(),n=await QA.exportCommand(t,e||void 0);o(n),await b()}catch(e){let t=e.message||`未知错误`;c({title:t.includes(`HTTP 400`)?`生成失败(检查命令名)`:`生成失败`,detail:t})}finally{u(!1)}}}async function S(e){if(!v&&window.confirm(`删除命令 /${e}?删掉后 DSH 里立刻就不能用了。`)){y(e),c(null);try{await QA.deleteCommand(e),a?.name===e&&o(null),await b()}catch(e){c({title:`删除失败`,detail:e.message})}finally{y(null)}}}let C=p.filter(e=>!t||e.board===t),w={border:`1px solid ${i.colorBorderSecondary}`,borderRadius:8,background:i.colorFillTertiary,padding:`10px 12px`,fontFamily:TW,fontSize:12,lineHeight:1.7,whiteSpace:`pre-wrap`,wordBreak:`break-all`,color:i.colorText};return(0,$.jsxs)(RD,{open:e,title:`生成斜杠命令`,width:640,centered:!0,onCancel:r,styles:{body:{maxHeight:`calc(100vh - 240px)`,overflowY:`auto`}},footer:(0,$.jsxs)(uD,{justify:`flex-end`,gap:8,children:[(0,$.jsx)(GS,{onClick:r,children:`关闭`}),(0,$.jsx)(GS,{type:`primary`,icon:(0,$.jsx)(H,{size:14}),loading:l,onClick:()=>void x(),children:`生成`})]}),children:[(0,$.jsx)(Kl,{type:`info`,showIcon:!0,title:`把这张画布挂成一条 DSH 斜杠命令:生成后在对话里输入 /命令名,就能进入这张画布的工作流(无参数先看画布,带文字直接进流程)。命令即时生效,不用重启 DSH。`,style:{marginBottom:16}}),(0,$.jsxs)(`div`,{style:{marginBottom:12},children:[(0,$.jsx)(wW,{type:`secondary`,style:{fontSize:12},children:`当前画布:`}),(0,$.jsx)(wW,{strong:!0,style:{fontSize:12},children:n||t||`索引里的第一张画布`})]}),(0,$.jsxs)(`div`,{style:{marginBottom:16},children:[(0,$.jsx)(wW,{style:{fontSize:12,display:`block`,marginBottom:6},children:`命令名(可选)`}),(0,$.jsx)(PD,{value:d,onChange:e=>f(e.target.value),placeholder:`留空=按画布 id 自动生成(agentflow-…)`,maxLength:48,disabled:l}),(0,$.jsx)(wW,{type:`secondary`,style:{fontSize:11},children:`小写字母开头,只允许 a-z 0-9 _ -,不超过 48 个字符;同名会覆盖旧命令。`})]}),s&&(0,$.jsx)(Kl,{type:`error`,showIcon:!0,title:s.title,description:s.detail?(0,$.jsx)(wW,{style:{fontSize:12,fontFamily:TW,wordBreak:`break-all`},children:s.detail}):void 0,style:{marginBottom:16}}),a&&(0,$.jsxs)(`div`,{style:{marginBottom:16},children:[(0,$.jsx)(Kl,{type:`success`,showIcon:!0,title:a.replaced?`命令已更新(覆盖了同名旧命令)`:`命令已生成`,description:(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`div`,{style:{marginBottom:4},children:[`命令名:`,(0,$.jsxs)(wW,{code:!0,copyable:!0,style:{fontSize:12},children:[`/`,a.name]})]}),(0,$.jsxs)(`div`,{style:{marginBottom:4},children:[`用法:在 DSH 对话里输入 `,(0,$.jsxs)(wW,{code:!0,style:{fontSize:12},children:[`/`,a.name]}),`,回车即可。`]}),(0,$.jsx)(`div`,{style:{marginBottom:4},children:(0,$.jsx)(`b`,{children:`已即时生效,无需重启。`})}),(0,$.jsxs)(`div`,{children:[`文件:`,(0,$.jsx)(wW,{code:!0,copyable:!0,style:{fontSize:12,wordBreak:`break-all`},children:a.file})]})]})}),(0,$.jsx)(uD,{justify:`flex-end`,style:{marginTop:8},children:(0,$.jsx)(GS,{size:`small`,danger:!0,icon:(0,$.jsx)(_e,{size:13}),loading:v===a.name,onClick:()=>void S(a.name),children:`删除命令`})})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(uD,{align:`baseline`,justify:`space-between`,style:{marginBottom:6},children:[(0,$.jsx)(wW,{strong:!0,style:{fontSize:13},children:`这张画布已有的命令`}),(0,$.jsx)(wW,{type:`secondary`,style:{fontSize:11},children:h?`读取中…`:`${C.length} 条`})]}),C.length===0?(0,$.jsx)(`div`,{style:{...w,color:i.colorTextTertiary},children:h?`正在读取…`:`还没有命令,点右下角「生成」创建一条。`}):(0,$.jsx)(`div`,{style:{border:`1px solid ${i.colorBorderSecondary}`,borderRadius:8},children:C.map((e,t)=>(0,$.jsxs)(uD,{align:`center`,gap:8,style:{padding:`8px 12px`,borderTop:t===0?void 0:`1px solid ${i.colorBorderSecondary}`},children:[(0,$.jsxs)(wW,{code:!0,style:{fontSize:12},children:[`/`,e.name]}),(0,$.jsx)(wW,{type:`secondary`,style:{fontSize:11},children:DW(e.createdAt)}),(0,$.jsx)(`div`,{style:{marginLeft:`auto`},children:(0,$.jsx)(GS,{size:`small`,type:`text`,danger:!0,icon:(0,$.jsx)(_e,{size:13}),loading:v===e.name,onClick:()=>void S(e.name),children:`删除`})})]},e.name))})]})]})}function DW(e){if(!e)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}var OW=`border-[#E3E4DF] dark:border-[#262724]`,kW=`text-[#1B1B18] dark:text-[#e8e8e4]`,AW=`text-[#6b6b66] dark:text-[#8b8b85]`,jW=`text-[#8b8b85] dark:text-[#8b8b85]`;function MW(){try{let e=globalThis.__AGENTFLOW_HOST__;return e&&typeof e==`object`?e:null}catch{return null}}function NW(){return MW()?.remote===!0}function PW(){let[e,t]=(0,_.useState)(`list`),[n,r]=(0,_.useState)([]),[i,a]=(0,_.useState)([]),[o,s]=(0,_.useState)({}),[c,l]=(0,_.useState)(!0),[u,d]=(0,_.useState)(null),[f,p]=(0,_.useState)(null),[m,h]=(0,_.useState)(``),[g,v]=(0,_.useState)(null),[y,b]=(0,_.useState)(null),[x,S]=(0,_.useState)(!1),[C,w]=(0,_.useState)(``),[T,E]=(0,_.useState)(!1),[D,O]=(0,_.useState)(null),[k,A]=(0,_.useState)(``),j=(0,_.useRef)(!1),M=(0,_.useRef)(!1),[N,P]=(0,_.useState)([]),[F,L]=(0,_.useState)([]),[R,z]=(0,_.useState)(null),[B,V]=(0,_.useState)(null),[U,ee]=(0,_.useState)(null),[ne,ie]=(0,_.useState)(!1),[ae,G]=(0,_.useState)(!1),[oe,se]=(0,_.useState)(!1),[ce,le]=(0,_.useState)(!1),J=(0,_.useRef)(!1),ue=(0,_.useRef)(!1),fe=(0,_.useCallback)(()=>{ue.current=!0,se(!0)},[]),pe=(0,_.useCallback)(()=>{ue.current=!1,se(!1)},[]),me=(0,_.useRef)(0),ge=(0,_.useRef)(null);(0,_.useEffect)(()=>{ge.current=f},[f]),(0,_.useEffect)(()=>{if(!f||e!==`board`)return;let t=window.setTimeout(()=>{QA.putBoard(f.id,f).catch(e=>{console.warn(`[agentflow] 自动保存失败:`,e)}),r(e=>e.map(e=>e.id===f.id?{...e,presetOutdated:!0}:e))},200);return()=>window.clearTimeout(t)},[f,e]),(0,_.useEffect)(()=>{let e=()=>{let e=ge.current;if(e)try{fetch(JA(`/api/boards/${encodeURIComponent(e.id)}`),{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({board:e}),keepalive:!0}).catch(()=>{})}catch{}};return window.addEventListener(`pagehide`,e),()=>window.removeEventListener(`pagehide`,e)},[]);let[_e,ve]=(0,_.useState)(()=>{let e=MW();if(e?.remote){if(e.theme===`dark`)return!0;if(e.theme===`light`)return!1;try{return window.matchMedia(`(prefers-color-scheme: dark)`).matches}catch{return!1}}try{localStorage.removeItem(`agentflow-theme`)}catch{}try{let e=sessionStorage.getItem(`agentflow-theme`);if(e===`dark`)return!0;if(e===`light`)return!1}catch{}try{let e=new URLSearchParams(window.location.search).get(`theme`);if(e===`dark`)return!0;if(e===`light`)return!1}catch{}try{return window.matchMedia(`(prefers-color-scheme: dark)`).matches}catch{return!1}});(0,_.useEffect)(()=>{if(NW())window.dispatchEvent(new Event(`themechange`));else{document.documentElement.classList.toggle(`dark`,_e);try{sessionStorage.setItem(`agentflow-theme`,_e?`dark`:`light`)}catch{}window.dispatchEvent(new Event(`themechange`))}},[_e]),(0,_.useEffect)(()=>{if(!NW())return;let e=e=>{let t=e.detail?.theme;t===`dark`?ve(!0):t===`light`&&ve(!1)};return window.addEventListener(`agentflow-theme`,e),()=>window.removeEventListener(`agentflow-theme`,e)},[]);let[ye,be]=(0,_.useState)(null),xe=(0,_.useRef)(null),Y=(0,_.useCallback)((e,t=`ok`)=>{be({msg:e,kind:t}),xe.current&&window.clearTimeout(xe.current),xe.current=window.setTimeout(()=>be(null),3200)},[]),Se=(0,_.useCallback)((e,t)=>{p(n=>n&&{...n,nodes:n.nodes.map(n=>n.id===e?{...n,...t}:n)})},[]),Ce=(0,_.useRef)(null),we=(0,_.useRef)(null);(0,_.useEffect)(()=>{if(Ce.current=u,NW()&&u)try{window.dispatchEvent(new CustomEvent(`agentflow-board-active`,{detail:{boardId:u}}))}catch{}},[u]),(0,_.useEffect)(()=>{h(f?.name??``)},[f?.id,f?.name]);let Te=(0,_.useCallback)(async(e=!1)=>{e||l(!0);let[t,n]=await Promise.allSettled([QA.listBoards(),QA.listPresets()]);if(t.status===`fulfilled`){let e=t.value.boards;r(e);let n=await Promise.allSettled(e.map(e=>QA.getBoard(e.id))),i={};n.forEach((t,n)=>{t.status===`fulfilled`&&(i[e[n].id]=IW(t.value.board))}),s(i)}else Y(`加载画布列表失败:${t.reason.message}`,`err`);n.status===`fulfilled`?a(n.value.presets):Y(`加载预设列表失败:${n.reason.message}`,`err`),e||l(!1)},[Y]);(0,_.useEffect)(()=>{Te(),QA.getSkills().then(e=>P(e.skills)).catch(()=>{}),QA.getMcp().then(e=>L(e.servers)).catch(()=>{}),QA.getConfig().then(z).catch(()=>{}),QA.getModels().then(V).catch(()=>{}),QA.getBridge().then(ee).catch(()=>{})},[Te]);let Ee=(0,_.useRef)(0);(0,_.useEffect)(()=>{g&&(Date.now()-Ee.current<3e4||(Ee.current=Date.now(),QA.getModels(!0).then(V).catch(()=>{}),QA.getBridge().then(ee).catch(()=>{})))},[g]);let{running:De,run:Oe,stop:ke}=$A((0,_.useCallback)(e=>{let t=we.current!=null&&Ce.current!==we.current;if((e.type===`run:end`||e.type===`run:error`)&&(we.current=null),!t)switch(e.type){case`node:start`:Se(e.id,{status:`running`});break;case`node:delta`:p(t=>t&&{...t,nodes:t.nodes.map(t=>t.id===e.id?{...t,delta:(t.delta||``)+e.chunk}:t)});break;case`node:done`:Se(e.id,{status:e.status??`done`,content:e.content,usage:e.usage,verdict:e.verdict??null,error:null,delta:void 0});break;case`node:failed`:Se(e.id,{status:`failed`,error:`该节点所有模型都失败`});break;case`node:blocked`:Se(e.id,{status:`blocked`});break;case`node:retry`:p(t=>t&&{...t,nodes:t.nodes.map(t=>t.id===e.id?{...t,delta:void 0}:t)}),Y(`${e.id} 换 ${e.model} 重试:${e.error}`,`err`);break;case`run:end`:{let{done:t,failed:n,blocked:r,review:i}=e.summary,a=[`完成 ${t.length}`];i.length&&a.push(`待确认 ${i.length}`),n.length&&a.push(`失败 ${n.length}`),r.length&&a.push(`阻塞 ${r.length}`),Y(a.join(`,`),n.length||r.length?`err`:`ok`);break}case`run:error`:Y(`运行出错:${e.error}`,`err`)}},[Se,Y])),Ae=(0,_.useCallback)(e=>{let t=Ce.current;t&&(we.current=t,Oe(e,t))},[Oe]),je=(0,_.useCallback)(()=>{we.current=null,ke()},[ke]),Me=(0,_.useCallback)(async e=>{let n=++me.current;t(`board`),d(e),p(null),h(``),v(null),G(!1),pe();let r=await QA.getBoard(e).then(e=>({status:`fulfilled`,value:e})).catch(e=>({status:`rejected`,reason:e}));n===me.current&&(r.status===`rejected`?(Y(`打开画布失败:${r.reason.message}`,`err`),t(`list`),d(null),pe(),Te(!0)):p(r.value.board))},[Te,Y]),Ne=(0,_.useRef)((()=>{let e=MW();return e?.remote&&e.boardId?e.boardId:typeof window>`u`?null:new URLSearchParams(window.location.search).get(`board`)})());(0,_.useEffect)(()=>{let e=Ne.current;e&&(Ne.current=null,Me(e))},[Me]),(0,_.useEffect)(()=>{if(!NW())return;let e=e=>{let t=e.detail?.boardId;t&&t!==Ce.current&&Me(t)};return window.addEventListener(`agentflow-board`,e),()=>window.removeEventListener(`agentflow-board`,e)},[Me]);let Pe=(0,_.useCallback)(()=>{me.current+=1,t(`list`),p(null),d(null),v(null),G(!1),pe(),Te(!0)},[Te]);function Fe(){Pe()}function Ie(e){Me(e)}let Le=(0,_.useCallback)(async()=>{let e=ge.current;if(!e)return!1;try{return await QA.putBoard(e.id,e),pe(),!0}catch(e){return Y(`保存画布失败:${e.message}`,`err`),!1}},[Y,pe]),Re=(0,_.useCallback)(async()=>{let e=ge.current;if(!e||J.current)return!1;J.current=!0,le(!0);try{return await QA.putBoard(e.id,e),pe(),r(t=>t.map(t=>t.id===e.id?{...t,name:e.name,nodeCount:e.nodes.length,presetOutdated:!1,updatedAt:Date.now()}:t)),Y(`已保存`),!0}catch(e){return Y(`保存失败:${e.message}`,`err`),!1}finally{J.current=!1,le(!1)}},[Y,pe]);(0,_.useEffect)(()=>{let t=t=>{(t.metaKey||t.ctrlKey)&&String(t.key).toLowerCase()===`s`&&(t.preventDefault(),e===`board`&&window.setTimeout(()=>void Re(),0))};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[Re,e]);let ze=(0,_.useCallback)(async e=>{f&&(!ue.current||await Le())&&Ae(e)},[f,Le,Ae]),Be=(0,_.useCallback)(async()=>{f&&(!ue.current||await Le())&&G(!0)},[f,Le]),Ve=(0,_.useCallback)((e,t)=>{Se(e,t),fe()},[Se]),He=(0,_.useCallback)(e=>{p(t=>t&&{...t,edges:e}),fe()},[]),Ue=(0,_.useCallback)((e,t,n)=>{f&&(p({...f,nodes:f.nodes.map(r=>r.id===e?{...r,x:t,y:n}:r)}),fe())},[f]),We=(0,_.useCallback)((e,t)=>{if(!f)return;let n=f.nodes.find(t=>t.id===e);if(!n)return;let r=B?.providers.find(e=>e.models.length),i=n.provider||r?.id||``,a=n.model||r?.models[0]?.id||``,o=FW(f.nodes),s={id:o,label:t===`next`?`下游卡片`:`上游卡片`,type:`llm`,x:t===`next`?n.x+360:n.x-360,y:n.y,provider:i,model:a,reasoningEffort:``,fallback:[],fallbackEfforts:{},task:``,criteria:``,skills:[],tools:[],verify:``,content:``,status:`idle`,usage:null,error:null,verdict:null};p({...f,nodes:[...f.nodes,s],edges:[...f.edges,t===`next`?{from:e,to:o}:{from:o,to:e}]}),v(o),fe(),Y(t===`next`?`已派生下游卡片(未保存)`:`已添加上游卡片(未保存)`)},[f,B,Y]),Ge=(0,_.useCallback)((e,t)=>{f&&e!==t&&(f.nodes.find(e=>e.id===t)?.type===`orchestrator`?Y(`根节点是对话入口,不能有上游节点`,`err`):f.edges.some(n=>n.from===e&&n.to===t)||(RW(f.edges,e,t)?Y(`这条连线会形成环,已忽略`,`err`):(p({...f,edges:[...f.edges,{from:e,to:t}]}),fe())))},[f,Y]),Ke=(0,_.useCallback)(e=>{f&&(p({...f,nodes:f.nodes.filter(t=>t.id!==e),edges:f.edges.filter(t=>t.from!==e&&t.to!==e)}),v(null),fe(),Y(`已删除(未保存)`))},[f,Y]),qe=(0,_.useCallback)(async(e,t)=>{if(!ue.current||await Le())try{let n=await QA.verify(e,t,void 0,Ce.current);Se(e,{status:n.status,verdict:n.verdict}),Y(t?`已通过`:`已打回,可以改完再跑`)}catch(e){Y(`操作失败:${e.message}`,`err`)}},[Se,Y,Le]),Je=(0,_.useMemo)(()=>f?.nodes.find(e=>e.id===g)??null,[f,g]),Ye=(0,_.useMemo)(()=>new Set(n.map(e=>e.presetId).filter(e=>!!e)),[n]),Xe=(0,_.useMemo)(()=>i.filter(e=>!Ye.has(e.id)),[i,Ye]);function Ze(){w(``),S(!0)}async function Qe(){let e=C.trim();if(e&&!T){E(!0);try{let n=await QA.createBoard({name:e});me.current+=1,S(!1),w(``),p(n.board),d(n.board.id),v(null),pe(),t(`board`),Te(!0)}catch(e){Y(`新建画布失败:${e.message}`,`err`)}finally{E(!1)}}}async function $e(e){if(!y){b(e.id);try{let n=await QA.importPreset(e.id);Y(n.reused?`已有这张画布:${e.name}`:`已从预设创建画布:${e.name}`),me.current+=1,p(n.board),d(n.board.id),v(null),pe(),t(`board`),Te(!0)}catch(e){let t=e.message;t.includes(`HTTP 501`)?Y(`创建画布功能还没上线(服务端 P1 未完成)`,`err`):Y(`创建画布失败:${t}`,`err`)}finally{b(null)}}}function et(e){O(e.id),A(e.name)}async function tt(e){if(D!==e.id)return;let t=j.current;if(j.current=!1,O(null),t){A(e.name);return}let n=k.trim();if(n&&n!==e.name)try{let t=await QA.patchBoard(e.id,{name:n});r(r=>r.map(r=>r.id===e.id?{...r,name:n,updatedAt:t.meta?.updatedAt??r.updatedAt}:r)),f?.id===e.id&&p(e=>e&&{...e,name:n}),Y(`画布已重命名`)}catch(e){Y(`重命名失败:${e.message}`,`err`)}}async function nt(e){if(n.length<=1)Y(`至少要保留一张画布`,`err`);else if(window.confirm(`删除画布《${e.name}》?里面的节点会一起删掉,且不可恢复。`))try{await QA.deleteBoard(e.id),Y(`画布已删除`),await Te(!0)}catch(e){Y(`删除失败:${e.message}`,`err`)}}async function rt(){if(!f)return;let e=M.current;if(M.current=!1,e){h(f.name);return}let t=m.trim();if(!t)h(f.name);else if(t!==f.name)try{let e=await QA.patchBoard(f.id,{name:t});p(e=>e&&{...e,name:t}),r(n=>n.map(n=>n.id===f.id?{...n,name:t,updatedAt:e.meta?.updatedAt??n.updatedAt}:n)),Y(`画布已重命名`)}catch(e){h(f.name),Y(`重命名失败:${e.message}`,`err`)}}let it=(0,_.useRef)(null);return(0,$.jsx)(Ld,{locale:qA.default,getPopupContainer:()=>it.current??document.body,theme:{algorithm:_e?ik.darkAlgorithm:ik.defaultAlgorithm,token:{colorPrimary:`#24543F`,borderRadius:7,fontSize:15,fontFamily:`-apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', ui-sans-serif, sans-serif`},components:{Drawer:{paddingLG:20},Modal:{borderRadiusLG:12},Card:{borderRadiusLG:10}}},children:(0,$.jsxs)(`div`,{ref:it,className:`af-canvas flex h-full flex-col${_e?` dark`:``}`,children:[e===`list`?(0,$.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-3 border-b ${OW} bg-[#FCFCFA] px-5 dark:bg-[#17181b]`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`grid h-7 w-7 place-items-center rounded-[4px] bg-[#24543F] text-white`,children:`◈`}),(0,$.jsx)(`span`,{className:`text-[17px] font-semibold tracking-tight ${kW}`,children:`AgentFlow`})]}),(0,$.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,$.jsx)(GS,{type:`primary`,icon:(0,$.jsx)(K,{size:14}),onClick:Ze,children:`新建画布`}),(0,$.jsx)(GS,{icon:_e?(0,$.jsx)(he,{size:14}):(0,$.jsx)(re,{size:14}),onClick:()=>ve(e=>!e),title:_e?`切到浅色`:`切到深色`}),(0,$.jsx)(GS,{icon:(0,$.jsx)(de,{size:14}),onClick:()=>ie(!0),children:`设置`})]})]}):(0,$.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b ${OW} bg-[#FCFCFA] px-4 dark:bg-[#17181b]`,children:[(0,$.jsxs)(`button`,{type:`button`,onClick:Fe,title:`返回画布列表`,className:`flex shrink-0 items-center gap-1 rounded-[4px] px-2 py-1.5 text-[12px] transition-colors hover:bg-[#EFEFEA] dark:hover:bg-[#232421] ${AW}`,children:[(0,$.jsx)(I,{size:14}),`返回列表`]}),(0,$.jsx)(`div`,{className:`h-5 w-px shrink-0 bg-[#E3E4DF] dark:bg-[#2c2d29]`}),(0,$.jsx)(`input`,{value:m,onChange:e=>h(e.target.value),onBlur:()=>void rt(),onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur(),e.key===`Escape`&&(M.current=!0,e.currentTarget.blur())},disabled:!f,placeholder:`画布名称`,"aria-label":`画布名称`,className:`min-w-0 max-w-[280px] flex-1 rounded-[3px] border-0 bg-transparent px-1 py-1 text-[16px] font-semibold tracking-tight outline-none placeholder:text-[#a8a8a0] focus-visible:ring-2 focus-visible:ring-[#24543F]/30 disabled:bg-transparent dark:placeholder:text-[#6f6f68] dark:focus-visible:ring-[#6aa583]/40 ${kW}`}),oe&&(0,$.jsx)(`span`,{title:`有未保存的修改`,"aria-label":`有未保存的修改`,className:`h-1.5 w-1.5 shrink-0 rounded-full bg-[#B4451F] dark:bg-[#e08a6a]`}),(0,$.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,$.jsx)(GS,{icon:(0,$.jsx)(q,{size:14}),disabled:!f,loading:ce,onClick:()=>void Re(),title:`保存画布并更新预设(⌘S / Ctrl+S)`,children:`保存`}),De?(0,$.jsx)(GS,{danger:!0,icon:(0,$.jsx)(te,{size:14,className:`animate-spin`}),onClick:je,children:`停止`}):(0,$.jsx)(GS,{type:`primary`,icon:(0,$.jsx)(W,{size:14}),disabled:!f,onClick:()=>void ze(),title:`先保存,再跑一遍验证(会真实调用模型)`,children:`验证 AgentFlow`}),(0,$.jsx)(GS,{icon:(0,$.jsx)(H,{size:14}),disabled:!f,onClick:()=>void Be(),children:`生成命令`}),(0,$.jsx)(GS,{icon:_e?(0,$.jsx)(he,{size:14}):(0,$.jsx)(re,{size:14}),onClick:()=>ve(e=>!e),title:_e?`切到浅色`:`切到深色`}),(0,$.jsx)(GS,{icon:(0,$.jsx)(de,{size:14}),onClick:()=>ie(!0),children:`设置`})]})]}),e===`list`?(0,$.jsx)(`main`,{className:`min-h-0 flex-1 overflow-y-auto bg-[#F4F5F2] px-6 py-7 dark:bg-[#111214]`,children:(0,$.jsxs)(`div`,{className:`mx-auto w-full max-w-[1080px]`,children:[(0,$.jsxs)(`div`,{className:`mb-5`,children:[(0,$.jsx)(`h1`,{className:`text-[20px] font-semibold tracking-tight ${kW}`,children:`画布`}),(0,$.jsx)(`p`,{className:`mt-1 text-[12px] leading-[1.6] ${AW}`,children:`每张画布对应一个 DSH 预设;编辑会自动保存,点「保存」才会更新/生成预设。`})]}),c&&n.length===0?(0,$.jsx)(`div`,{className:`py-16 text-center text-[13px] ${AW}`,children:`正在加载画布…`}):(0,$.jsxs)($.Fragment,{children:[n.length===0?(0,$.jsx)(`div`,{className:`rounded-[8px] border border-dashed ${OW} py-14 text-center text-[13px] ${AW}`,children:`还没有画布,点右上角「新建画布」开始。`}):(0,$.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3`,children:n.map(e=>{let t=e.presetId?i.find(t=>t.id===e.presetId):null;return(0,$.jsxs)(`article`,{className:`flex min-h-[150px] flex-col rounded-[8px] border ${OW} bg-[#FCFCFA] p-4 dark:bg-[#17181B]`,children:[(0,$.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,$.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[D===e.id?(0,$.jsx)(PD,{size:`small`,autoFocus:!0,maxLength:60,value:k,onChange:e=>A(e.target.value),onBlur:()=>void tt(e),onPressEnter:e=>e.currentTarget.blur(),onKeyDown:e=>{e.key===`Escape`&&(j.current=!0,e.currentTarget.blur())},"aria-label":`重命名画布 ${e.name}`}):(0,$.jsx)(`button`,{type:`button`,onClick:()=>Ie(e.id),title:e.name,className:`block max-w-full text-left`,children:(0,$.jsx)(`h2`,{className:`truncate text-[15px] font-semibold ${kW}`,children:e.name})}),(0,$.jsxs)(`p`,{className:`mt-1 text-[11px] leading-[1.6] ${jW}`,children:[e.nodeCount,` 个节点 · 更新于 `,LW(e.updatedAt)]}),o[e.id]!==void 0&&(0,$.jsxs)(`p`,{className:`mt-0.5 truncate text-[11px] leading-[1.6] ${AW}`,title:o[e.id]||`没有调度卡,首次导出会自动补一张`,children:[`对话入口:`,o[e.id]||`未设置(首次导出会自动补一张调度卡)`]})]}),(0,$.jsxs)(`div`,{className:`flex shrink-0 flex-col items-end gap-1`,children:[(0,$.jsx)(JO,{color:t?`blue`:`default`,style:{marginInlineEnd:0},children:t?t.name:`自定义`}),e.presetOutdated&&(0,$.jsx)(JO,{color:`orange`,style:{marginInlineEnd:0},children:`预设未更新`}),e.hasDraft&&(0,$.jsx)(JO,{color:`gold`,style:{marginInlineEnd:0},children:`草稿`})]})]}),(0,$.jsxs)(`div`,{className:`mt-auto flex flex-wrap items-center gap-1 pt-3`,children:[(0,$.jsx)(GS,{size:`small`,type:`primary`,onClick:()=>Ie(e.id),children:`编辑`}),(0,$.jsx)(GS,{size:`small`,type:`text`,onClick:()=>et(e),children:`重命名`}),(0,$.jsx)(GS,{size:`small`,type:`text`,danger:!0,disabled:n.length<=1,title:n.length<=1?`至少要保留一张画布`:void 0,onClick:()=>void nt(e),children:`删除`})]})]},e.id)})}),Xe.length>0&&(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`div`,{className:`mb-3 mt-8 flex flex-wrap items-baseline gap-2`,children:[(0,$.jsx)(`h2`,{className:`text-[13px] font-semibold ${kW}`,children:`还没有画布的预设`}),(0,$.jsx)(`span`,{className:`text-[11px] ${jW}`,children:`从预设生成一张单卡片画布,再继续编辑`})]}),(0,$.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3`,children:Xe.map(e=>(0,$.jsxs)(`article`,{className:`flex min-h-[150px] flex-col rounded-[8px] border border-dashed ${OW} bg-[#F9F9F6] p-4 dark:bg-[#151617]`,children:[(0,$.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,$.jsx)(`h2`,{className:`min-w-0 flex-1 truncate text-[15px] font-semibold ${kW}`,title:e.name,children:e.name}),(0,$.jsx)(JO,{style:{marginInlineEnd:0,flexShrink:0},children:e.source===`bundle`?`bundle`:`自定义`})]}),(0,$.jsx)(`p`,{className:`mt-1 line-clamp-3 text-[12px] leading-[1.6] ${AW}`,children:e.description||`没有描述`}),(0,$.jsx)(`div`,{className:`mt-auto pt-3`,children:(0,$.jsx)(GS,{size:`small`,loading:y===e.id,onClick:()=>void $e(e),children:`创建画布`})})]},e.id))})]})]})]})}):(0,$.jsxs)(`main`,{className:`relative min-h-0 flex-1`,children:[(0,$.jsxs)(`div`,{className:`pointer-events-none absolute left-4 top-[12px] z-10 flex items-center gap-1.5 rounded-[4px] bg-[#FCFCFA]/90 px-2 py-1 text-[11px] text-[#6b6b66] dark:bg-[#17181b]/90 dark:text-[#8b8b85]`,children:[(0,$.jsx)(`span`,{className:`h-[5px] w-[5px] rounded-full`,style:{background:R?R.mock?`#B4451F`:`#24543F`:`#b9bcb4`}}),R?R.mock?`mock`:`real`:`连接中`]}),f?(0,$.jsx)(GU,{board:f,selectedId:g,running:De,onSelect:v,onMove:Ue,onDerive:We,onConnect:Ge}):(0,$.jsx)(`div`,{className:`grid h-full place-items-center text-[13px] text-[#8a93a3]`,children:`正在加载画布…`})]}),e===`board`&&f&&Je&&(0,$.jsx)(fW,{node:Je,nodes:f.nodes,edges:f.edges,boardId:f.id,skills:N,servers:F,catalog:B,bridge:U,running:De,onPatch:e=>Ve(Je.id,e),onDerive:e=>We(Je.id,e),onVerify:e=>void qe(Je.id,e),onEdgesChange:He,onRefreshModels:()=>{Ee.current=Date.now(),QA.getModels(!0).then(V).catch(e=>Y(`刷新模型失败:${e.message}`,`err`)),QA.getBridge().then(ee).catch(()=>{})},onRerun:()=>void ze([Je.id]),onDelete:()=>void Ke(Je.id),onClose:()=>v(null)}),(0,$.jsx)(xW,{open:ne,config:R,servers:F,onClose:()=>ie(!1),onSaved:e=>{z(t=>t&&{...t,mock:e.mock}),QA.getMcp().then(e=>L(e.servers)).catch(()=>{}),Y(`设置已保存`)},onError:e=>Y(e,`err`)}),(0,$.jsx)(EW,{open:ae,boardId:u,boardName:m,onClose:()=>G(!1)}),(0,$.jsx)(RD,{open:x,title:`新建画布`,centered:!0,getContainer:()=>it.current??document.body,okText:`创建`,cancelText:`取消`,confirmLoading:T,okButtonProps:{disabled:!C.trim()},onOk:()=>void Qe(),onCancel:()=>S(!1),children:(0,$.jsx)(PD,{autoFocus:!0,maxLength:60,placeholder:`画布名称,例如「活动文案」`,value:C,onChange:e=>w(e.target.value),onPressEnter:()=>{C.trim()&&!T&&Qe()}})}),ye&&(0,$.jsx)(`div`,{className:`absolute bottom-6 left-1/2 z-50 -translate-x-1/2 rounded-lg px-4 py-2 text-[13px] shadow-lg ${ye.kind===`err`?`bg-[#ffebee] text-[#c62828] dark:bg-[#3a1b1f] dark:text-[#ff9a9a]`:`bg-[#1C1C1A] text-white dark:bg-[#e7e9ee] dark:text-[#0f1116]`}`,children:ye.msg})]})})}function FW(e){let t=`n-${Date.now().toString(36)}`,n=t,r=2;for(;e.some(e=>e.id===n);)n=`${t}-${r++}`;return n}function IW(e){let t=e.nodes.find(e=>e.type===`orchestrator`)??(e.nodes.length===1?e.nodes[0]:null);return t?t.label||t.id:null}function LW(e){if(!e)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}function RW(e,t,n){let r=new Set,i=[n];for(;i.length;){let n=i.pop();if(n===t)return!0;if(!r.has(n)){r.add(n);for(let t of e)t.from===n&&i.push(t.to)}}return!1}(0,v.createRoot)(document.getElementById(`root`)).render((0,$.jsx)(_.StrictMode,{children:(0,$.jsx)(PW,{})}));
|
|
348
|
+
`,uW=`w-full rounded-lg border border-[#E1E2DD] bg-[#FCFCFA] px-2.5 py-2 text-[13px] leading-[1.65] text-[#1B1B18] outline-none transition-colors placeholder:text-[#9a9a92] focus:border-[#24543F] focus:bg-white dark:border-[#33353B] dark:bg-[#17181B] dark:text-[#EDEDE8] dark:focus:border-[#6aa583] dark:focus:bg-[#1B1C20]`,dW=`rounded-[4px] px-2.5 py-1.5 text-[12px] text-[#5b6472] transition-colors hover:bg-[#EFEFEA] dark:text-[#a3a39b] dark:hover:bg-[#232421]`;function fW(e){return(0,$.jsxs)(`aside`,{className:`af-panel absolute bottom-0 right-0 top-14 z-30 flex w-[420px] flex-col border-l border-[#E3E4DF] bg-[#FCFCFA] dark:border-[#262724] dark:bg-[#17181B]`,role:`complementary`,"aria-label":`节点详情`,children:[(0,$.jsx)(`style`,{children:lW}),(0,$.jsx)(mW,{...e},e.node.id)]})}function pW(e,...t){let n=e.trim().toLowerCase();return!n||t.some(e=>String(e??``).toLowerCase().includes(n))}function mW(e){let{node:t,nodes:n,edges:r,boardId:i,skills:a,servers:o,catalog:s,bridge:c,running:l,onPatch:u,onDerive:d,onVerify:f,onRerun:p,onRefreshModels:m,onEdgesChange:h,onDelete:g,onClose:v}=e,[y,b]=(0,_.useState)(t.label),[x,S]=(0,_.useState)(t.task),[C,w]=(0,_.useState)(t.criteria),[T,E]=(0,_.useState)(rW),[D,O]=(0,_.useState)(0),[k,A]=(0,_.useState)(``),[j,M]=(0,_.useState)(``),[N,F]=(0,_.useState)(null),I=(0,_.useRef)(null),L=(0,_.useRef)(null);(0,_.useEffect)(()=>{yW(I.current)},[x]),(0,_.useEffect)(()=>{yW(L.current)},[C]);let z=(0,_.useRef)(u);(0,_.useEffect)(()=>{z.current=u},[u]);let B=(0,_.useRef)({}),V=(0,_.useRef)(null),H=(0,_.useCallback)(()=>{V.current!==null&&(window.clearTimeout(V.current),V.current=null);let e=B.current;Object.keys(e).length&&(B.current={},z.current(e))},[]),U=(0,_.useCallback)(e=>{B.current={...B.current,...e},V.current!==null&&window.clearTimeout(V.current),V.current=window.setTimeout(H,400)},[H]);(0,_.useEffect)(()=>()=>{if(V.current!==null){window.clearTimeout(V.current),V.current=null;let e=B.current;Object.keys(e).length&&z.current(e)}},[]),(0,_.useEffect)(()=>{let e=e=>{(e.metaKey||e.ctrlKey)&&String(e.key).toLowerCase()===`s`&&H()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[H]);let[W,ee]=(0,_.useState)(r);(0,_.useEffect)(()=>{ee(r)},[r]);let ne=new Set(W.filter(e=>e.to===t.id).map(e=>e.from)),re=n.filter(e=>e.id!==t.id);function ie(e){let n=[...W.filter(e=>e.to!==t.id),...e.map(e=>({from:e,to:t.id}))];ee(n),h(n)}function ae(e,n){let r=new Set(t.skills);n?r.add(e):r.delete(e),u({skills:[...r]})}let G=s?.providers??[],K=t.provider&&t.model?`${t.provider}/${t.model}`:``,oe=G.some(e=>e.id===t.provider&&e.models.some(e=>e.id===t.model)),ce=t.model&&!oe?t.model:``,q=oe?G.find(e=>e.id===t.provider)?.models.find(e=>e.id===t.model)??null:null,le=q?.levels??[],ue=q?.defaultLevel??``,de=G.every(e=>!e.models.length),fe=new Set,pe=[];for(let e of T){let{provider:t,model:n}=aW(e.value),r=G.find(e=>e.id===t),i=r?.models.find(e=>e.id===n);r&&i&&!fe.has(e.value)&&(fe.add(e.value),pe.push({title:i.name,label:`${r.label} · ${i.name}`,value:`${eW}${e.value}`}))}let me=[];pe.length&&me.push({title:`最近使用`,label:`最近使用`,value:QU,selectable:!1,children:pe}),ce&&me.push({title:`当前值`,label:`当前值`,value:$U,selectable:!1,children:[{title:ce,label:oW(t.provider,ce),value:ZU}]});for(let e of G){let t=e.models.length;me.push({title:t?`${e.label}(${t})`:e.label,label:e.label,value:`p:${e.id}`,selectable:!1,children:e.error?[{title:e.error,label:e.error,value:`e:${e.id}`,disabled:!0}]:e.models.map(t=>({title:t.name,label:`${e.label} · ${t.name}`,value:`${e.id}/${t.id}`}))})}let he=G.find(e=>e.id===t.provider),ge=T.map(e=>e.provider).find(e=>G.some(t=>t.id===e)),ve=he?.id??ge??``,ye=[...pe.length?[QU]:[],...ce?[$U]:[],...ve?[`p:${ve}`]:[]],be=oe?K:ce?ZU:void 0,Y=t.fallback??[],Se=t.fallbackEfforts??{},Ce=new Set(Y),we=G.map(e=>{let t=e.models.length,n=e.error?[{title:e.error,label:e.error,value:`e:${e.id}`,disabled:!0}]:e.models.filter(t=>{let n=`${e.id}/${t.id}`;return n!==K&&!Ce.has(n)}).map(t=>({title:t.name,label:`${e.label} · ${t.name}`,value:`${e.id}/${t.id}`}));return{title:t?`${e.label}(${t})`:e.label,label:e.label,value:`p:${e.id}`,selectable:!1,children:n}}).filter(e=>e.children.length>0),Te=ve?[`p:${ve}`]:[];function Ee(e){if(!e||e===ZU)return;let n=e.startsWith(eW)?e.slice(2):e,{provider:r,model:i}=aW(n),a=G.find(e=>e.id===r),o=a?.models.find(e=>e.id===i);if(!a||!o)return;let s=o.levels.includes(t.reasoningEffort??``)?t.reasoningEffort??``:``,c={value:n,label:o.name,provider:r},l=[c,...T.filter(e=>e.value!==c.value)].slice(0,nW);E(l),iW(l),u({provider:r,model:i,reasoningEffort:s})}function De(e){let{provider:t,model:n}=aW(e),r=G.find(e=>e.id===t),i=r?.models.find(e=>e.id===n);return!r||!i?{label:`${e}(不在 DSH 目录里)`,levels:[]}:{label:`${r.label} · ${i.name}`,levels:i.levels}}function Oe(e,t){u({fallback:e,fallbackEfforts:t})}function ke(e){e&&e.includes(`/`)&&!Ce.has(e)&&(Oe([...Y,e],{...Se,[e]:``}),O(e=>e+1))}function Ae(e){let t={...Se};delete t[e],Oe(Y.filter(t=>t!==e),t)}function je(e,t){Oe(Y,{...Se,[e]:t})}let Me=sW[t.status]??sW.idle,Ne=t.type===`orchestrator`,Pe=n.some(e=>e.id!==t.id&&e.type===`orchestrator`),Fe=NU.map(e=>({...e,disabled:e.value===`orchestrator`&&Pe})),Ie=cW.find(e=>e.value===(t.verify??``))??cW[0],Le=t.status===`review`,Re=a.filter(e=>pW(k,e.name,e.description)),ze=o.map(e=>({...e,tools:e.tools.filter(e=>pW(j,e.name,e.description))})).filter(e=>pW(j,e.name)||e.tools.length>0),Be=j.trim()?ze.map(e=>e.name):N??o.filter(e=>e.ok&&e.tools.length).slice(0,1).map(e=>e.name);return(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`header`,{className:`flex shrink-0 items-center gap-2 border-b ${YU} bg-[#FAFAF7] px-5 py-3.5 dark:bg-[#1B1C20]`,children:[(0,$.jsx)(`input`,{value:y,onChange:e=>{let t=e.target.value;b(t),U({label:t})},onBlur:H,onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur()},placeholder:`节点名称`,"aria-label":`节点名称`,className:`min-w-0 flex-1 rounded-[3px] border-0 bg-transparent p-0 text-[17px] font-semibold tracking-tight outline-none placeholder:text-[#a8a8a0] focus-visible:ring-2 focus-visible:ring-[#24543F]/30 dark:placeholder:text-[#6f6f68] dark:focus-visible:ring-[#6aa583]/40 ${KU}`}),(0,$.jsxs)(`span`,{className:`flex shrink-0 items-center gap-1.5 text-[12px] ${qU}`,children:[(0,$.jsx)(`span`,{className:`h-[6px] w-[6px] rounded-full ${Me.dot}`}),Me.label]}),(0,$.jsx)(`button`,{type:`button`,onClick:v,"aria-label":`关闭详情`,title:`关闭`,className:`-mr-1 grid h-8 w-8 shrink-0 place-items-center rounded-[4px] text-[#6b6b66] transition-colors hover:bg-[#EFEFEA] dark:text-[#8b8b85] dark:hover:bg-[#232421]`,children:(0,$.jsx)(xe,{size:16})})]}),t.verdict&&(0,$.jsxs)(`div`,{className:`shrink-0 border-b px-5 py-2 text-[12px] leading-[1.5] ${YU} ${t.verdict.pass?`bg-[#EEF3EF] text-[#24543F] dark:bg-[#1B2A22] dark:text-[#8FC3A7]`:`bg-[#FBEFEA] text-[#B4451F] dark:bg-[#2A1C17] dark:text-[#E08A6A]`}`,children:[vW(t.verdict.by),` `,t.verdict.pass?`通过`:`未通过`,t.verdict.reason?`:${t.verdict.reason}`:``]}),t.error&&(0,$.jsx)(`div`,{className:`shrink-0 border-b px-5 py-2 text-[12px] leading-[1.5] ${YU} bg-[#FBEFEA] text-[#B4451F] dark:bg-[#2A1C17] dark:text-[#E08A6A]`,children:t.error}),(0,$.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 pb-6 pt-3`,children:[Ne?null:(0,$.jsxs)(hW,{title:`节点类型`,children:[(0,$.jsx)(Fb,{value:t.type||`llm`,onChange:e=>u({type:e}),options:Fe,"aria-label":`节点类型`,className:`w-full`,size:`middle`}),Pe?(0,$.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${JU}`,children:`画布已有根节点,这张卡不能再设为调度卡。`}):null]}),(0,$.jsx)(hW,{title:`模型`,extra:(0,$.jsxs)(`button`,{type:`button`,onClick:m,title:`重新读取 DSH 的模型目录`,className:`flex items-center gap-1 text-[11px] transition-opacity hover:opacity-70 ${JU}`,children:[(0,$.jsx)(se,{size:11}),`刷新`]}),children:(0,$.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,$.jsx)(Lk,{value:be,placeholder:`选择模型`,showSearch:!0,treeNodeFilterProp:`title`,treeDefaultExpandAll:!1,treeDefaultExpandedKeys:ye,treeNodeLabelProp:`label`,treeData:me,onChange:Ee,"aria-label":`模型`,className:`w-full`,size:`middle`}),(0,$.jsx)(Fb,{value:t.reasoningEffort??``,onChange:e=>u({reasoningEffort:e}),disabled:!le.length,"aria-label":`推理强度`,title:le.length?`推理强度`:`当前模型没有可选推理档位`,options:[{value:``,label:`推理强度:模型默认${ue?`(${ue})`:``}`},...le.map(e=>({value:e,label:e}))],className:`w-full`,size:`middle`}),de&&(0,$.jsxs)(`div`,{className:`flex items-start gap-1.5 text-[11px] leading-[1.6] ${qU}`,children:[(0,$.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-50`}),(0,$.jsx)(`span`,{children:`没读到 DSH 的模型目录,检查 DSH 凭据或网络。`})]}),(0,$.jsxs)(`div`,{className:`flex items-start gap-1.5 border-t border-[#EDEEE9] pt-2 text-[11px] leading-[1.6] dark:border-[#2A2C31] ${c&&!c.healthy?`text-[#B4451F] dark:text-[#e08a6a]`:qU}`,children:[(0,$.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-60`}),(0,$.jsxs)(`span`,{children:[`模型通道:DSH 内核(未连接时不可跑图)`,c&&!c.healthy?` · ${c.reason||`原因未知`}`:``]})]})]})}),(0,$.jsx)(hW,{title:`兜底模型`,extra:Y.length?(0,$.jsxs)(`span`,{className:`text-[11px] ${qU}`,children:[Y.length,` 个 · 按顺序重试`]}):void 0,children:(0,$.jsxs)(`div`,{className:`space-y-1.5`,children:[Y.map(e=>{let t=De(e);return(0,$.jsxs)(`div`,{className:`flex min-h-[32px] items-center gap-2 border-b py-1 last:border-b-0 ${YU}`,children:[(0,$.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[12px] ${KU}`,title:t.label,children:t.label}),(0,$.jsx)(Fb,{size:`small`,value:Se[e]??``,disabled:!t.levels.length,title:t.levels.length?`这条兜底的推理强度`:`该模型没有可选推理档位`,options:[{value:``,label:`模型默认`},...t.levels.map(e=>({value:e,label:e}))],onChange:t=>je(e,t),"aria-label":`${t.label} 的推理强度`,style:{width:104}}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>Ae(e),"aria-label":`移除兜底模型 ${t.label}`,title:`移除`,className:`grid h-7 w-7 shrink-0 place-items-center rounded-[4px] transition-colors hover:bg-[#FBEFEA] hover:text-[#B4451F] dark:hover:bg-[#2A1C17] dark:hover:text-[#e08a6a] ${JU}`,children:(0,$.jsx)(xe,{size:13})})]},e)}),(0,$.jsx)(Lk,{onChange:ke,placeholder:`添加兜底模型…`,showSearch:!0,treeNodeFilterProp:`title`,treeDefaultExpandAll:!1,treeDefaultExpandedKeys:Te,treeNodeLabelProp:`label`,treeData:we,"aria-label":`添加兜底模型`,className:`w-full`,size:`middle`},D),(0,$.jsxs)(`div`,{className:`flex items-start gap-1.5 pt-0.5 text-[11px] leading-[1.6] ${qU}`,children:[(0,$.jsx)(`span`,{className:`mt-[5px] h-[3px] w-[3px] shrink-0 rounded-full bg-current opacity-50`}),(0,$.jsx)(`span`,{children:`兜底模型:主模型失败后按顺序尝试,可单独设推理强度`})]})]})}),(0,$.jsxs)(hW,{title:Ne?`人格`:`任务`,children:[(0,$.jsx)(`textarea`,{ref:I,rows:3,value:x,onChange:e=>{S(e.target.value),U({task:e.target.value}),yW(e.currentTarget)},onBlur:H,placeholder:Ne?`默认:只负责和用户对话,再严格按后续节点的 AgentFlow 流执行(可自己改)`:`写清楚这张卡要做什么…`,className:`${uW} max-h-[240px] resize-none overflow-y-auto`}),Ne&&(0,$.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${JU}`,children:`默认人格只是起点,可以自己改:它只负责和用户对话,确认需求后严格按后续节点的流程执行。`})]}),(0,$.jsx)(hW,{title:`完成标准`,children:(0,$.jsx)(`textarea`,{ref:L,rows:2,value:C,onChange:e=>{w(e.target.value),U({criteria:e.target.value}),yW(e.currentTarget)},onBlur:H,placeholder:`做到什么程度算完成…`,className:`${uW} max-h-[200px] resize-none overflow-y-auto`})}),(0,$.jsxs)(hW,{title:`结果判断`,children:[(0,$.jsx)(`div`,{role:`radiogroup`,"aria-label":`结果判断`,className:`flex gap-[2px] rounded-[6px] bg-[#EFEFEA] p-[3px] dark:bg-[#232421]`,children:cW.map(e=>{let n=(t.verify??``)===e.value;return(0,$.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":n,title:e.desc,onClick:()=>u({verify:e.value}),className:`flex-1 rounded-[4px] px-1 py-[5px] text-[13px] leading-[1.3] transition-colors ${n?`bg-white text-[#1B1B18] shadow-[0_1px_2px_rgba(0,0,0,0.06)] dark:bg-[#3A3B35] dark:text-[#e8e8e4]`:`hover:text-[#1B1B18] dark:hover:text-[#e8e8e4] ${qU}`}`,children:e.label},e.value||`none`)})}),(0,$.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-[1.5] ${JU}`,children:Ie.desc}),(t.verify??``)===`jev`&&(0,$.jsx)(`p`,{className:`mt-1.5 rounded-[4px] border border-[#E9D9B8] bg-[#FBF4E6] px-2 py-1.5 text-[11px] leading-[1.5] text-[#8a6220] dark:border-[#4a3a1c] dark:bg-[#2a2314] dark:text-[#e0b866]`,children:`需要本机安装 jev(TypeSafe)并配置 API key,否则这张卡跑到判定时会失败。`})]}),(0,$.jsx)(hW,{title:`技能`,extra:(0,$.jsxs)(`span`,{className:`text-[11px] ${JU}`,children:[`已选 `,t.skills.length]}),children:a.length===0?(0,$.jsx)(gW,{children:`没有找到技能`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(PD,{value:k,onChange:e=>A(e.target.value),allowClear:!0,size:`middle`,placeholder:`搜索技能名或描述…`,"aria-label":`搜索技能`,prefix:(0,$.jsx)(J,{size:12,className:JU}),className:`mb-2`}),Re.length===0?(0,$.jsxs)(gW,{children:[`没有匹配「`,k.trim(),`」的技能`]}):null,(0,$.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto`,children:Re.map(e=>{let n=t.skills.includes(e.name);return(0,$.jsx)(YT,{className:`af-row`,checked:n,onChange:t=>ae(e.name,t.target.checked),title:e.description,children:(0,$.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`shrink-0 text-[13px] ${KU}`,children:e.name}),(0,$.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-right text-[11px] ${JU}`,children:e.description||`无描述`})]})},e.name)})})]})}),(0,$.jsx)(hW,{title:`MCP 工具`,extra:(0,$.jsxs)(`span`,{className:`text-[11px] ${JU}`,children:[`已选 `,t.tools.length]}),children:o.length===0?(0,$.jsx)(gW,{children:`还没配置 MCP 服务器`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(PD,{value:j,onChange:e=>M(e.target.value),allowClear:!0,size:`middle`,placeholder:`搜索服务器或工具…`,"aria-label":`搜索 MCP 工具`,prefix:(0,$.jsx)(J,{size:12,className:JU}),className:`mb-2`}),ze.length===0?(0,$.jsxs)(gW,{children:[`没有匹配「`,j.trim(),`」的工具`]}):null,(0,$.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto af-tree`,children:(0,$.jsx)(FO,{checkable:!0,selectable:!1,expandedKeys:Be,onExpand:e=>F(e),treeData:ze.map(e=>({key:e.name,selectable:!1,title:(0,$.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`h-[5px] w-[5px] shrink-0 rounded-full ${e.ok?`bg-[#24543F] dark:bg-[#6aa583]`:`bg-[#B4451F] dark:bg-[#e08a6a]`}`}),(0,$.jsx)(`span`,{className:`text-[12px] font-medium ${KU}`,children:e.name}),(0,$.jsxs)(`span`,{className:`text-[11px] ${JU}`,children:[e.tools.length,` 个工具`]}),!e.ok&&(0,$.jsx)(`span`,{className:`text-[11px] text-[#B4451F] dark:text-[#e08a6a]`,children:`连接失败`})]}),children:e.tools.map(t=>({key:`${e.name}.${t.name}`,title:(0,$.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`shrink-0 text-[13px] ${KU}`,children:t.name}),(0,$.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-right text-[11px] ${JU}`,children:t.description})]})}))})),checkedKeys:t.tools,onCheck:e=>{let t=Array.isArray(e)?e:e.checked;u({tools:t.filter(e=>String(e).includes(`.`))})}})})]})}),Ne?null:(0,$.jsx)(hW,{title:`上游`,children:re.length===0?(0,$.jsx)(gW,{children:`还没有其它卡片`}):(0,$.jsx)(`div`,{className:`max-h-[180px] overflow-y-auto`,children:re.map(e=>{let n=ne.has(e.id),r=!n&&_W(W,t.id,e.id),i=n?[...ne].filter(t=>t!==e.id):[...ne,e.id];return(0,$.jsx)(YT,{className:`af-row ${r?`af-row-disabled`:``}`,checked:n,disabled:r,onChange:()=>ie(i),children:(0,$.jsxs)(`span`,{className:`flex min-w-0 flex-1 items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[13px] ${KU}`,children:e.label||e.id}),r&&(0,$.jsx)(`span`,{className:`shrink-0 text-[11px] ${JU}`,children:`会成环`})]})},e.id)})})})]}),Le&&(0,$.jsxs)(`div`,{className:`shrink-0 border-t ${YU} bg-[#FAEFE6] px-5 py-3 dark:bg-[#2A1C17]`,children:[(0,$.jsx)(`p`,{className:`text-[12px] text-[#B4451F] dark:text-[#e08a6a]`,children:`这张卡跑完了,等你判断结果`}),(0,$.jsxs)(`div`,{className:`mt-2 flex gap-2`,children:[(0,$.jsx)(`button`,{type:`button`,onClick:()=>f(!0),className:`h-8 flex-1 rounded-[4px] bg-[#24543F] text-[13px] font-medium text-white transition-colors hover:bg-[#1D4634] dark:bg-[#3F7A5F] dark:hover:bg-[#4B8B6D]`,children:`通过`}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>f(!1),className:`h-8 flex-1 rounded-[4px] text-[13px] text-[#6b6b66] transition-colors hover:bg-white/60 dark:text-[#a3a39b] dark:hover:bg-[#232421]`,children:`打回重跑`})]})]}),(0,$.jsxs)(`footer`,{className:`shrink-0 border-t ${YU} bg-[#FAFAF7] px-5 py-3 dark:bg-[#1B1C20]`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,$.jsxs)(`button`,{type:`button`,onClick:p,disabled:l,className:`flex h-8 flex-1 items-center justify-center gap-1.5 rounded-[4px] bg-[#24543F] text-[13px] font-medium text-white transition-colors hover:bg-[#1D4634] disabled:cursor-not-allowed disabled:opacity-50 dark:bg-[#3F7A5F] dark:hover:bg-[#4B8B6D]`,children:[l?(0,$.jsx)(te,{size:13,className:`animate-spin`}):(0,$.jsx)(se,{size:13}),l?`运行中…`:`重跑此卡`]}),Ne?null:(0,$.jsxs)(`button`,{type:`button`,onClick:()=>d(`prev`),className:`${dW} flex items-center gap-1`,children:[(0,$.jsx)(R,{size:13}),`加上游`]}),(0,$.jsxs)(`button`,{type:`button`,onClick:()=>d(`next`),className:`${dW} flex items-center gap-1`,children:[(0,$.jsx)(P,{size:13}),`加下游`]})]}),(0,$.jsx)(`div`,{className:`mt-1 flex justify-end`,children:(0,$.jsxs)(`button`,{type:`button`,onClick:g,disabled:Ne,title:Ne?`根节点是对话入口(人格来源),不能删除`:void 0,className:`flex items-center gap-1.5 rounded-[4px] px-2.5 py-1.5 text-[12px] text-[#B4451F] transition-colors hover:bg-[#FBEFEA] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent dark:text-[#e08a6a] dark:hover:bg-[#2A1C17]`,children:[(0,$.jsx)(_e,{size:13}),`删除此卡`]})})]})]})}function hW({title:e,extra:t,children:n}){return(0,$.jsxs)(`section`,{className:`mt-3 rounded-xl border p-3 first:mt-1 ${XU}`,children:[(0,$.jsxs)(`div`,{className:`mb-2.5 flex items-center justify-between gap-2`,children:[(0,$.jsx)(`h3`,{className:`text-[12px] font-semibold tracking-[0.01em] ${KU}`,children:e}),t]}),n]})}function gW({children:e}){return(0,$.jsx)(`p`,{className:`py-1 text-[12px] leading-[1.6] ${JU}`,children:e})}function _W(e,t,n){if(t===n)return!0;let r=new Set([t]),i=[t];for(;i.length;){let t=i.pop();for(let a of e)if(a.from===t){if(a.to===n)return!0;r.has(a.to)||(r.add(a.to),i.push(a.to))}}return!1}function vW(e){return e===`human`?`人工`:e===`jev`?`jev`:e===`self`?`自评`:e||`系统`}function yW(e){e&&(e.style.height=`auto`,e.style.height=`${e.scrollHeight}px`)}var{Text:bW}=RA;function xW({open:e,config:t,servers:n,onClose:r,onSaved:i,onError:a}){let o=t,[s,c]=(0,_.useState)(o?.mock??!1),[l,u]=(0,_.useState)(!1),[d,f]=(0,_.useState)(null),[p,m]=(0,_.useState)(!1),h=(0,_.useRef)(a);(0,_.useEffect)(()=>{h.current=a},[a]),(0,_.useEffect)(()=>{e&&c(o?.mock??!1)},[e,o?.mock]),(0,_.useEffect)(()=>{if(!e)return;let t=!1;return m(!0),QA.getBridge().then(e=>{t||f(e)}).catch(e=>{t||h.current(`读取模型通道状态失败:${e.message}`)}).finally(()=>{t||m(!1)}),()=>{t=!0}},[e]);async function g(){if(p)return;m(!0);let[e,t]=await Promise.allSettled([QA.getBridge(),QA.getModels(!0)]);e.status===`fulfilled`?f(e.value):h.current(`读取模型通道状态失败:${e.reason.message}`),t.status===`rejected`&&h.current(`重新读取模型目录失败:${t.reason.message}`),m(!1)}async function v(e){if(l||!t)return;let n=s;c(e),u(!0);try{let t=await QA.putConfig({mock:e}),n=typeof t?.mock==`boolean`?t.mock:e;c(n),i({mock:n})}catch(e){c(n),a(`切换 mock 失败:${e.message}`)}finally{u(!1)}}let y=Object.entries(o?.providers??{}),b=o?.mcpServers??n.map(e=>({name:e.name})),x=o?.skillDirs?.length?o.skillDirs:o?.dshPaths?.skills?[o.dshPaths.skills]:[],S=d?d.healthy?(0,$.jsx)(JO,{color:`success`,style:{marginInlineEnd:0},children:`已连接`}):(0,$.jsx)(JO,{color:`warning`,style:{marginInlineEnd:0},children:`未连接`}):(0,$.jsx)(bW,{type:`secondary`,style:{fontSize:12},children:`读取中…`}),C=d&&(d.lastError||d.reason)||``;return(0,$.jsxs)(RD,{open:e,title:`设置`,width:640,centered:!0,getContainer:()=>document.querySelector(`.af-canvas`)??document.body,onCancel:r,styles:{body:{maxHeight:`calc(100vh - 220px)`,overflowY:`auto`,paddingTop:12}},footer:(0,$.jsx)(uD,{justify:`flex-end`,children:(0,$.jsx)(GS,{onClick:r,children:`关闭`})}),children:[(0,$.jsx)(Kl,{type:`info`,showIcon:!0,title:`模型、MCP 服务器、技能都来自 DSH 的配置。要增删改请到 DSH 的 cordis.patch.yml,AgentFlow 这边只读。`,description:o?.dshPaths?.patch?(0,$.jsxs)(bW,{type:`secondary`,style:{fontSize:12,wordBreak:`break-all`},children:[`patch:`,(0,$.jsx)(bW,{code:!0,style:{fontSize:12},children:o.dshPaths.patch})]}):void 0}),(0,$.jsx)(SW,{title:`模型`,extra:(0,$.jsxs)(bW,{type:`secondary`,style:{fontSize:11},children:[y.length,` 个`]}),children:y.length===0?(0,$.jsx)(ib,{image:ib.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置模型提供商`}):y.map(([e,t])=>(0,$.jsx)(Hw,{size:`small`,style:{marginBottom:12},title:(0,$.jsx)(bW,{strong:!0,style:{fontSize:14},children:t.label||e}),extra:t.hasKey?(0,$.jsx)(JO,{color:`green`,style:{marginInlineEnd:0},children:`已配置 key`}):(0,$.jsx)(JO,{color:`red`,style:{marginInlineEnd:0},children:`缺 key`}),children:(0,$.jsx)(VE,{size:`small`,column:1,colon:!1,items:[{key:`provider`,label:`provider`,children:(0,$.jsx)(bW,{code:!0,children:e})},{key:`baseURL`,label:`baseURL`,children:(0,$.jsx)(bW,{code:!0,children:t.baseURL||`—`})},{key:`model`,label:`model`,children:(0,$.jsx)(bW,{code:!0,children:t.model||`—`})}]})},e))}),(0,$.jsxs)(SW,{title:`模型通道`,extra:(0,$.jsx)(GS,{size:`small`,loading:p,onClick:()=>void g(),children:`刷新`}),children:[d&&!d.healthy&&(0,$.jsx)(Kl,{type:`warning`,showIcon:!0,style:{marginBottom:10},title:`DSH 未运行或插件未加载,画布不能调模型`}),(0,$.jsx)(VE,{size:`small`,bordered:!0,column:1,colon:!1,items:[{key:`status`,label:`状态`,children:S},{key:`infoPath`,label:`发现文件`,children:(0,$.jsx)(bW,{code:!0,style:{fontSize:12,wordBreak:`break-all`,userSelect:`text`},title:d?.dir,children:d?.infoPath||`—`})},{key:`version`,label:`版本`,children:d?.version==null?`—`:(0,$.jsx)(bW,{code:!0,children:d.version})},{key:`startedAt`,label:`启动时间`,children:CW(d?.startedAt??null)},{key:`providers`,label:`provider 数`,children:d?String(d.providers):`—`},{key:`modelCount`,label:`模型数`,children:d?String(d.modelCount):`—`},{key:`lastError`,label:`最后错误`,children:C?(0,$.jsx)(bW,{type:`danger`,style:{fontSize:12,wordBreak:`break-all`},children:C}):(0,$.jsx)(bW,{type:`secondary`,children:`—`})}]})]}),(0,$.jsx)(SW,{title:`MCP 服务器`,extra:(0,$.jsxs)(bW,{type:`secondary`,style:{fontSize:11},children:[b.length,` 个`]}),children:b.length===0?(0,$.jsx)(ib,{image:ib.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置 MCP 服务器`}):(0,$.jsx)(VE,{size:`small`,bordered:!0,column:1,colon:!1,items:b.map(e=>({key:e.name,label:(0,$.jsx)(bW,{strong:!0,style:{fontSize:13},children:e.name}),children:e.kind?(0,$.jsx)(JO,{style:{marginInlineEnd:0},children:e.kind}):(0,$.jsx)(bW,{type:`secondary`,children:`—`})}))})}),(0,$.jsx)(SW,{title:`技能目录`,extra:(0,$.jsxs)(bW,{type:`secondary`,style:{fontSize:11},children:[x.length,` 个`]}),children:x.length===0?(0,$.jsx)(ib,{image:ib.PRESENTED_IMAGE_SIMPLE,description:`DSH 没有配置技能目录`}):(0,$.jsx)(uD,{vertical:!0,gap:6,children:x.map(e=>(0,$.jsx)(bW,{code:!0,style:{fontSize:12,wordBreak:`break-all`},children:e},e))})}),(0,$.jsx)(SW,{title:`运行模式`,children:(0,$.jsx)(Hw,{size:`small`,children:(0,$.jsxs)(uD,{align:`center`,justify:`space-between`,gap:16,children:[(0,$.jsxs)(`div`,{style:{minWidth:0},children:[(0,$.jsx)(bW,{strong:!0,style:{display:`block`,fontSize:15},children:`mock 模式`}),(0,$.jsx)(bW,{type:`secondary`,style:{display:`block`,fontSize:12},children:`AgentFlow 自己的开关,不属于 DSH 配置。打开后不真正调用模型。`})]}),(0,$.jsx)(qD,{checked:s,loading:l,disabled:!t,onChange:e=>void v(e)})]})})})]})}function SW({title:e,extra:t,children:n}){return(0,$.jsxs)(`section`,{style:{marginTop:20},children:[(0,$.jsxs)(uD,{align:`center`,justify:`space-between`,gap:8,style:{marginBottom:8},children:[(0,$.jsx)(bW,{strong:!0,style:{fontSize:13},children:e}),t]}),n]})}function CW(e){if(typeof e!=`number`||!Number.isFinite(e)||e<=0)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`}var{Text:wW}=RA,TW=`'SFMono-Regular', Menlo, Consolas, 'Liberation Mono', ui-monospace, monospace`;function EW({open:e,boardId:t,boardName:n,onClose:r}){let{token:i}=ik.useToken(),[a,o]=(0,_.useState)(null),[s,c]=(0,_.useState)(null),[l,u]=(0,_.useState)(!1),[d,f]=(0,_.useState)(``),[p,m]=(0,_.useState)([]),[h,g]=(0,_.useState)(!1),[v,y]=(0,_.useState)(null),b=(0,_.useCallback)(async()=>{g(!0);try{let e=await QA.listCommands();m(e.commands)}catch{m([])}finally{g(!1)}},[]);(0,_.useEffect)(()=>{e&&(o(null),c(null),u(!1),f(``),b())},[e,b]);async function x(){if(!l){u(!0),c(null),o(null);try{let e=d.trim(),n=await QA.exportCommand(t,e||void 0);o(n),await b()}catch(e){let t=e.message||`未知错误`;c({title:t.includes(`HTTP 400`)?`生成失败(检查命令名)`:`生成失败`,detail:t})}finally{u(!1)}}}async function S(e){if(!v&&window.confirm(`删除命令 /${e}?删掉后 DSH 里立刻就不能用了。`)){y(e),c(null);try{await QA.deleteCommand(e),a?.name===e&&o(null),await b()}catch(e){c({title:`删除失败`,detail:e.message})}finally{y(null)}}}let C=p.filter(e=>!t||e.board===t),w={border:`1px solid ${i.colorBorderSecondary}`,borderRadius:8,background:i.colorFillTertiary,padding:`10px 12px`,fontFamily:TW,fontSize:12,lineHeight:1.7,whiteSpace:`pre-wrap`,wordBreak:`break-all`,color:i.colorText};return(0,$.jsxs)(RD,{open:e,title:`生成斜杠命令`,width:640,centered:!0,onCancel:r,styles:{body:{maxHeight:`calc(100vh - 240px)`,overflowY:`auto`}},footer:(0,$.jsxs)(uD,{justify:`flex-end`,gap:8,children:[(0,$.jsx)(GS,{onClick:r,children:`关闭`}),(0,$.jsx)(GS,{type:`primary`,icon:(0,$.jsx)(H,{size:14}),loading:l,onClick:()=>void x(),children:`生成`})]}),children:[(0,$.jsx)(Kl,{type:`info`,showIcon:!0,title:`把这张画布挂成一条 DSH 斜杠命令:生成后在对话里输入 /命令名,就能进入这张画布的工作流(无参数先看画布,带文字直接进流程)。命令即时生效,不用重启 DSH。`,style:{marginBottom:16}}),(0,$.jsxs)(`div`,{style:{marginBottom:12},children:[(0,$.jsx)(wW,{type:`secondary`,style:{fontSize:12},children:`当前画布:`}),(0,$.jsx)(wW,{strong:!0,style:{fontSize:12},children:n||t||`索引里的第一张画布`})]}),(0,$.jsxs)(`div`,{style:{marginBottom:16},children:[(0,$.jsx)(wW,{style:{fontSize:12,display:`block`,marginBottom:6},children:`命令名(可选)`}),(0,$.jsx)(PD,{value:d,onChange:e=>f(e.target.value),placeholder:`留空=按画布 id 自动生成(agentflow-…)`,maxLength:48,disabled:l}),(0,$.jsx)(wW,{type:`secondary`,style:{fontSize:11},children:`小写字母开头,只允许 a-z 0-9 _ -,不超过 48 个字符;同名会覆盖旧命令。`})]}),s&&(0,$.jsx)(Kl,{type:`error`,showIcon:!0,title:s.title,description:s.detail?(0,$.jsx)(wW,{style:{fontSize:12,fontFamily:TW,wordBreak:`break-all`},children:s.detail}):void 0,style:{marginBottom:16}}),a&&(0,$.jsxs)(`div`,{style:{marginBottom:16},children:[(0,$.jsx)(Kl,{type:`success`,showIcon:!0,title:a.replaced?`命令已更新(覆盖了同名旧命令)`:`命令已生成`,description:(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`div`,{style:{marginBottom:4},children:[`命令名:`,(0,$.jsxs)(wW,{code:!0,copyable:!0,style:{fontSize:12},children:[`/`,a.name]})]}),(0,$.jsxs)(`div`,{style:{marginBottom:4},children:[`用法:在 DSH 对话里输入 `,(0,$.jsxs)(wW,{code:!0,style:{fontSize:12},children:[`/`,a.name]}),`,回车即可。`]}),(0,$.jsx)(`div`,{style:{marginBottom:4},children:(0,$.jsx)(`b`,{children:`已即时生效,无需重启。`})}),(0,$.jsxs)(`div`,{children:[`文件:`,(0,$.jsx)(wW,{code:!0,copyable:!0,style:{fontSize:12,wordBreak:`break-all`},children:a.file})]})]})}),(0,$.jsx)(uD,{justify:`flex-end`,style:{marginTop:8},children:(0,$.jsx)(GS,{size:`small`,danger:!0,icon:(0,$.jsx)(_e,{size:13}),loading:v===a.name,onClick:()=>void S(a.name),children:`删除命令`})})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(uD,{align:`baseline`,justify:`space-between`,style:{marginBottom:6},children:[(0,$.jsx)(wW,{strong:!0,style:{fontSize:13},children:`这张画布已有的命令`}),(0,$.jsx)(wW,{type:`secondary`,style:{fontSize:11},children:h?`读取中…`:`${C.length} 条`})]}),C.length===0?(0,$.jsx)(`div`,{style:{...w,color:i.colorTextTertiary},children:h?`正在读取…`:`还没有命令,点右下角「生成」创建一条。`}):(0,$.jsx)(`div`,{style:{border:`1px solid ${i.colorBorderSecondary}`,borderRadius:8},children:C.map((e,t)=>(0,$.jsxs)(uD,{align:`center`,gap:8,style:{padding:`8px 12px`,borderTop:t===0?void 0:`1px solid ${i.colorBorderSecondary}`},children:[(0,$.jsxs)(wW,{code:!0,style:{fontSize:12},children:[`/`,e.name]}),(0,$.jsx)(wW,{type:`secondary`,style:{fontSize:11},children:DW(e.createdAt)}),(0,$.jsx)(`div`,{style:{marginLeft:`auto`},children:(0,$.jsx)(GS,{size:`small`,type:`text`,danger:!0,icon:(0,$.jsx)(_e,{size:13}),loading:v===e.name,onClick:()=>void S(e.name),children:`删除`})})]},e.name))})]})]})}function DW(e){if(!e)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}var OW=`border-[#E3E4DF] dark:border-[#262724]`,kW=`text-[#1B1B18] dark:text-[#e8e8e4]`,AW=`text-[#6b6b66] dark:text-[#8b8b85]`,jW=`text-[#8b8b85] dark:text-[#8b8b85]`;function MW(){try{let e=globalThis.__AGENTFLOW_HOST__;return e&&typeof e==`object`?e:null}catch{return null}}function NW(){return MW()?.remote===!0}function PW(){let[e,t]=(0,_.useState)(`list`),[n,r]=(0,_.useState)([]),[i,a]=(0,_.useState)([]),[o,s]=(0,_.useState)({}),[c,l]=(0,_.useState)(!0),[u,d]=(0,_.useState)(null),[f,p]=(0,_.useState)(null),[m,h]=(0,_.useState)(``),[g,v]=(0,_.useState)(null),[y,b]=(0,_.useState)(null),[x,S]=(0,_.useState)(!1),[C,w]=(0,_.useState)(``),[T,E]=(0,_.useState)(!1),[D,O]=(0,_.useState)(null),[k,A]=(0,_.useState)(``),j=(0,_.useRef)(!1),M=(0,_.useRef)(!1),[N,P]=(0,_.useState)([]),[F,L]=(0,_.useState)([]),[R,z]=(0,_.useState)(null),[B,V]=(0,_.useState)(null),[U,ee]=(0,_.useState)(null),[ne,ie]=(0,_.useState)(!1),[ae,G]=(0,_.useState)(!1),[oe,se]=(0,_.useState)(!1),[ce,le]=(0,_.useState)(!1),J=(0,_.useRef)(!1),ue=(0,_.useRef)(!1),fe=(0,_.useCallback)(()=>{ue.current=!0,se(!0)},[]),pe=(0,_.useCallback)(()=>{ue.current=!1,se(!1)},[]),me=(0,_.useRef)(0),ge=(0,_.useRef)(null);(0,_.useEffect)(()=>{ge.current=f},[f]),(0,_.useEffect)(()=>{if(!f||e!==`board`)return;let t=window.setTimeout(()=>{QA.putBoard(f.id,f).catch(e=>{console.warn(`[agentflow] 自动保存失败:`,e)}),r(e=>e.map(e=>e.id===f.id?{...e,presetOutdated:!0}:e))},200);return()=>window.clearTimeout(t)},[f,e]),(0,_.useEffect)(()=>{let e=()=>{let e=ge.current;if(e)try{fetch(JA(`/api/boards/${encodeURIComponent(e.id)}`),{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({board:e}),keepalive:!0}).catch(()=>{})}catch{}};return window.addEventListener(`pagehide`,e),()=>window.removeEventListener(`pagehide`,e)},[]);let[_e,ve]=(0,_.useState)(()=>{let e=MW();if(e?.remote){if(e.theme===`dark`)return!0;if(e.theme===`light`)return!1;try{return window.matchMedia(`(prefers-color-scheme: dark)`).matches}catch{return!1}}try{localStorage.removeItem(`agentflow-theme`)}catch{}try{let e=sessionStorage.getItem(`agentflow-theme`);if(e===`dark`)return!0;if(e===`light`)return!1}catch{}try{let e=new URLSearchParams(window.location.search).get(`theme`);if(e===`dark`)return!0;if(e===`light`)return!1}catch{}try{return window.matchMedia(`(prefers-color-scheme: dark)`).matches}catch{return!1}});(0,_.useEffect)(()=>{if(NW())window.dispatchEvent(new Event(`themechange`));else{document.documentElement.classList.toggle(`dark`,_e);try{sessionStorage.setItem(`agentflow-theme`,_e?`dark`:`light`)}catch{}window.dispatchEvent(new Event(`themechange`))}},[_e]),(0,_.useEffect)(()=>{if(!NW())return;let e=e=>{let t=e.detail?.theme;t===`dark`?ve(!0):t===`light`&&ve(!1)};return window.addEventListener(`agentflow-theme`,e),()=>window.removeEventListener(`agentflow-theme`,e)},[]);let[ye,be]=(0,_.useState)(null),xe=(0,_.useRef)(null),Y=(0,_.useCallback)((e,t=`ok`)=>{be({msg:e,kind:t}),xe.current&&window.clearTimeout(xe.current),xe.current=window.setTimeout(()=>be(null),3200)},[]),Se=(0,_.useCallback)((e,t)=>{p(n=>n&&{...n,nodes:n.nodes.map(n=>n.id===e?{...n,...t}:n)})},[]),Ce=(0,_.useRef)(null),we=(0,_.useRef)(null);(0,_.useEffect)(()=>{if(Ce.current=u,NW()&&u)try{window.dispatchEvent(new CustomEvent(`agentflow-board-active`,{detail:{boardId:u}}))}catch{}},[u]),(0,_.useEffect)(()=>{h(f?.name??``)},[f?.id,f?.name]);let Te=(0,_.useCallback)(async(e=!1)=>{e||l(!0);let[t,n]=await Promise.allSettled([QA.listBoards(),QA.listPresets()]);if(t.status===`fulfilled`){let e=t.value.boards;r(e);let n=await Promise.allSettled(e.map(e=>QA.getBoard(e.id))),i={};n.forEach((t,n)=>{t.status===`fulfilled`&&(i[e[n].id]=IW(t.value.board))}),s(i)}else Y(`加载画布列表失败:${t.reason.message}`,`err`);n.status===`fulfilled`?a(n.value.presets):Y(`加载预设列表失败:${n.reason.message}`,`err`),e||l(!1)},[Y]);(0,_.useEffect)(()=>{Te(),QA.getSkills().then(e=>P(e.skills)).catch(()=>{}),QA.getMcp().then(e=>L(e.servers)).catch(()=>{}),QA.getConfig().then(z).catch(()=>{}),QA.getModels().then(V).catch(()=>{}),QA.getBridge().then(ee).catch(()=>{})},[Te]);let Ee=(0,_.useRef)(0);(0,_.useEffect)(()=>{g&&(Date.now()-Ee.current<3e4||(Ee.current=Date.now(),QA.getModels(!0).then(V).catch(()=>{}),QA.getBridge().then(ee).catch(()=>{})))},[g]);let{running:De,run:Oe,stop:ke}=$A((0,_.useCallback)(e=>{let t=we.current!=null&&Ce.current!==we.current;if((e.type===`run:end`||e.type===`run:error`)&&(we.current=null),!t)switch(e.type){case`node:start`:Se(e.id,{status:`running`});break;case`node:delta`:p(t=>t&&{...t,nodes:t.nodes.map(t=>t.id===e.id?{...t,delta:(t.delta||``)+e.chunk}:t)});break;case`node:done`:Se(e.id,{status:e.status??`done`,content:e.content,usage:e.usage,verdict:e.verdict??null,error:null,delta:void 0});break;case`node:failed`:Se(e.id,{status:`failed`,error:`该节点所有模型都失败`});break;case`node:blocked`:Se(e.id,{status:`blocked`});break;case`node:retry`:p(t=>t&&{...t,nodes:t.nodes.map(t=>t.id===e.id?{...t,delta:void 0}:t)}),Y(`${e.id} 换 ${e.model} 重试:${e.error}`,`err`);break;case`run:end`:{let{done:t,failed:n,blocked:r,review:i}=e.summary,a=[`完成 ${t.length}`];i.length&&a.push(`待确认 ${i.length}`),n.length&&a.push(`失败 ${n.length}`),r.length&&a.push(`阻塞 ${r.length}`),Y(a.join(`,`),n.length||r.length?`err`:`ok`);break}case`run:error`:Y(`运行出错:${e.error}`,`err`)}},[Se,Y])),Ae=(0,_.useCallback)(e=>{let t=Ce.current;t&&(we.current=t,Oe(e,t))},[Oe]),je=(0,_.useCallback)(()=>{we.current=null,ke()},[ke]),Me=(0,_.useCallback)(async e=>{let n=++me.current;t(`board`),d(e),p(null),h(``),v(null),G(!1),pe();let r=await QA.getBoard(e).then(e=>({status:`fulfilled`,value:e})).catch(e=>({status:`rejected`,reason:e}));n===me.current&&(r.status===`rejected`?(Y(`打开画布失败:${r.reason.message}`,`err`),t(`list`),d(null),pe(),Te(!0)):p(r.value.board))},[Te,Y]),Ne=(0,_.useRef)((()=>{let e=MW();return e?.remote&&e.boardId?e.boardId:typeof window>`u`?null:new URLSearchParams(window.location.search).get(`board`)})());(0,_.useEffect)(()=>{let e=Ne.current;e&&(Ne.current=null,Me(e))},[Me]),(0,_.useEffect)(()=>{if(!NW())return;let e=e=>{let t=e.detail?.boardId;t&&t!==Ce.current&&Me(t)};return window.addEventListener(`agentflow-board`,e),()=>window.removeEventListener(`agentflow-board`,e)},[Me]);let Pe=(0,_.useCallback)(()=>{me.current+=1,t(`list`),p(null),d(null),v(null),G(!1),pe(),Te(!0)},[Te]);function Fe(){Pe()}function Ie(e){Me(e)}let Le=(0,_.useCallback)(async()=>{let e=ge.current;if(!e)return!1;try{return await QA.putBoard(e.id,e),pe(),!0}catch(e){return Y(`保存画布失败:${e.message}`,`err`),!1}},[Y,pe]),Re=(0,_.useCallback)(async()=>{let e=ge.current;if(!e||J.current)return!1;J.current=!0,le(!0);try{return await QA.putBoard(e.id,e),pe(),r(t=>t.map(t=>t.id===e.id?{...t,name:e.name,nodeCount:e.nodes.length,presetOutdated:!1,updatedAt:Date.now()}:t)),Y(`已保存`),!0}catch(e){return Y(`保存失败:${e.message}`,`err`),!1}finally{J.current=!1,le(!1)}},[Y,pe]);(0,_.useEffect)(()=>{let t=t=>{(t.metaKey||t.ctrlKey)&&String(t.key).toLowerCase()===`s`&&(t.preventDefault(),e===`board`&&window.setTimeout(()=>void Re(),0))};return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[Re,e]);let ze=(0,_.useCallback)(async e=>{f&&(!ue.current||await Le())&&Ae(e)},[f,Le,Ae]),Be=(0,_.useCallback)(async()=>{f&&(!ue.current||await Le())&&G(!0)},[f,Le]),Ve=(0,_.useCallback)((e,t)=>{Se(e,t),fe()},[Se]),He=(0,_.useCallback)(e=>{p(t=>t&&{...t,edges:e}),fe()},[]),Ue=(0,_.useCallback)((e,t,n)=>{f&&(p({...f,nodes:f.nodes.map(r=>r.id===e?{...r,x:t,y:n}:r)}),fe())},[f]),We=(0,_.useCallback)((e,t)=>{if(!f)return;let n=f.nodes.find(t=>t.id===e);if(!n)return;let r=B?.providers.find(e=>e.models.length),i=n.provider||r?.id||``,a=n.model||r?.models[0]?.id||``,o=FW(f.nodes),s={id:o,label:t===`next`?`下游卡片`:`上游卡片`,type:`llm`,x:t===`next`?n.x+360:n.x-360,y:n.y,provider:i,model:a,reasoningEffort:``,fallback:[],fallbackEfforts:{},task:``,criteria:``,skills:[],tools:[],verify:``,content:``,status:`idle`,usage:null,error:null,verdict:null};p({...f,nodes:[...f.nodes,s],edges:[...f.edges,t===`next`?{from:e,to:o}:{from:o,to:e}]}),v(o),fe(),Y(t===`next`?`已派生下游卡片(未保存)`:`已添加上游卡片(未保存)`)},[f,B,Y]),Ge=(0,_.useCallback)((e,t)=>{f&&e!==t&&(f.nodes.find(e=>e.id===t)?.type===`orchestrator`?Y(`根节点是对话入口,不能有上游节点`,`err`):f.edges.some(n=>n.from===e&&n.to===t)||(RW(f.edges,e,t)?Y(`这条连线会形成环,已忽略`,`err`):(p({...f,edges:[...f.edges,{from:e,to:t}]}),fe())))},[f,Y]),Ke=(0,_.useCallback)(e=>{f&&(p({...f,nodes:f.nodes.filter(t=>t.id!==e),edges:f.edges.filter(t=>t.from!==e&&t.to!==e)}),v(null),fe(),Y(`已删除(未保存)`))},[f,Y]),qe=(0,_.useCallback)(async(e,t)=>{if(!ue.current||await Le())try{let n=await QA.verify(e,t,void 0,Ce.current);Se(e,{status:n.status,verdict:n.verdict}),Y(t?`已通过`:`已打回,可以改完再跑`)}catch(e){Y(`操作失败:${e.message}`,`err`)}},[Se,Y,Le]),Je=(0,_.useMemo)(()=>f?.nodes.find(e=>e.id===g)??null,[f,g]),Ye=(0,_.useMemo)(()=>new Set(n.map(e=>e.presetId).filter(e=>!!e)),[n]),Xe=(0,_.useMemo)(()=>i.filter(e=>!Ye.has(e.id)),[i,Ye]);function Ze(){w(``),S(!0)}async function Qe(){let e=C.trim();if(e&&!T){E(!0);try{let n=await QA.createBoard({name:e});me.current+=1,S(!1),w(``),p(n.board),d(n.board.id),v(null),pe(),t(`board`),Te(!0)}catch(e){Y(`新建画布失败:${e.message}`,`err`)}finally{E(!1)}}}async function $e(e){if(!y){b(e.id);try{let n=await QA.importPreset(e.id);Y(n.reused?`已有这张画布:${e.name}`:`已从预设创建画布:${e.name}`),me.current+=1,p(n.board),d(n.board.id),v(null),pe(),t(`board`),Te(!0)}catch(e){let t=e.message;t.includes(`HTTP 501`)?Y(`创建画布功能还没上线(服务端 P1 未完成)`,`err`):Y(`创建画布失败:${t}`,`err`)}finally{b(null)}}}function et(e){O(e.id),A(e.name)}async function tt(e){if(D!==e.id)return;let t=j.current;if(j.current=!1,O(null),t){A(e.name);return}let n=k.trim();if(n&&n!==e.name)try{let t=await QA.patchBoard(e.id,{name:n});r(r=>r.map(r=>r.id===e.id?{...r,name:n,updatedAt:t.meta?.updatedAt??r.updatedAt}:r)),f?.id===e.id&&p(e=>e&&{...e,name:n}),Y(`画布已重命名`)}catch(e){Y(`重命名失败:${e.message}`,`err`)}}async function nt(e){if(n.length<=1)Y(`至少要保留一张画布`,`err`);else if(window.confirm(`删除画布《${e.name}》?里面的节点会一起删掉,且不可恢复。`))try{await QA.deleteBoard(e.id),Y(`画布已删除`),await Te(!0)}catch(e){Y(`删除失败:${e.message}`,`err`)}}async function rt(){if(!f)return;let e=M.current;if(M.current=!1,e){h(f.name);return}let t=m.trim();if(!t)h(f.name);else if(t!==f.name)try{let e=await QA.patchBoard(f.id,{name:t});p(e=>e&&{...e,name:t}),r(n=>n.map(n=>n.id===f.id?{...n,name:t,updatedAt:e.meta?.updatedAt??n.updatedAt}:n)),Y(`画布已重命名`)}catch(e){h(f.name),Y(`重命名失败:${e.message}`,`err`)}}let it=(0,_.useRef)(null);return(0,$.jsx)(Ld,{locale:qA.default,getPopupContainer:()=>it.current??document.body,theme:{algorithm:_e?ik.darkAlgorithm:ik.defaultAlgorithm,token:{colorPrimary:`#24543F`,borderRadius:7,fontSize:15,fontFamily:`-apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', ui-sans-serif, sans-serif`},components:{Drawer:{paddingLG:20},Modal:{borderRadiusLG:12},Card:{borderRadiusLG:10}}},children:(0,$.jsxs)(`div`,{ref:it,className:`af-canvas flex h-full flex-col${_e?` dark`:``}`,children:[e===`list`?(0,$.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-3 border-b ${OW} bg-[#FCFCFA] px-5 dark:bg-[#17181b]`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`grid h-7 w-7 place-items-center rounded-[4px] bg-[#24543F] text-white`,children:`◈`}),(0,$.jsx)(`span`,{className:`text-[17px] font-semibold tracking-tight ${kW}`,children:`AgentFlow`})]}),(0,$.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,$.jsx)(GS,{type:`primary`,icon:(0,$.jsx)(K,{size:14}),onClick:Ze,children:`新建画布`}),(0,$.jsx)(GS,{icon:_e?(0,$.jsx)(he,{size:14}):(0,$.jsx)(re,{size:14}),onClick:()=>ve(e=>!e),title:_e?`切到浅色`:`切到深色`}),(0,$.jsx)(GS,{icon:(0,$.jsx)(de,{size:14}),onClick:()=>ie(!0),children:`设置`})]})]}):(0,$.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b ${OW} bg-[#FCFCFA] px-4 dark:bg-[#17181b]`,children:[(0,$.jsxs)(`button`,{type:`button`,onClick:Fe,title:`返回画布列表`,className:`flex shrink-0 items-center gap-1 rounded-[4px] px-2 py-1.5 text-[12px] transition-colors hover:bg-[#EFEFEA] dark:hover:bg-[#232421] ${AW}`,children:[(0,$.jsx)(I,{size:14}),`返回列表`]}),(0,$.jsx)(`div`,{className:`h-5 w-px shrink-0 bg-[#E3E4DF] dark:bg-[#2c2d29]`}),(0,$.jsx)(`input`,{value:m,onChange:e=>h(e.target.value),onBlur:()=>void rt(),onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur(),e.key===`Escape`&&(M.current=!0,e.currentTarget.blur())},disabled:!f,placeholder:`画布名称`,"aria-label":`画布名称`,className:`min-w-0 max-w-[280px] flex-1 rounded-[3px] border-0 bg-transparent px-1 py-1 text-[16px] font-semibold tracking-tight outline-none placeholder:text-[#a8a8a0] focus-visible:ring-2 focus-visible:ring-[#24543F]/30 disabled:bg-transparent dark:placeholder:text-[#6f6f68] dark:focus-visible:ring-[#6aa583]/40 ${kW}`}),oe&&(0,$.jsx)(`span`,{title:`有未保存的修改`,"aria-label":`有未保存的修改`,className:`h-1.5 w-1.5 shrink-0 rounded-full bg-[#B4451F] dark:bg-[#e08a6a]`}),(0,$.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,$.jsx)(GS,{icon:(0,$.jsx)(q,{size:14}),disabled:!f,loading:ce,onClick:()=>void Re(),title:`保存画布(⌘S / Ctrl+S)`,children:`保存`}),De?(0,$.jsx)(GS,{danger:!0,icon:(0,$.jsx)(te,{size:14,className:`animate-spin`}),onClick:je,children:`停止`}):(0,$.jsx)(GS,{type:`primary`,icon:(0,$.jsx)(W,{size:14}),disabled:!f,onClick:()=>void ze(),title:`先保存,再跑一遍验证(会真实调用模型)`,children:`验证 AgentFlow`}),(0,$.jsx)(GS,{icon:(0,$.jsx)(H,{size:14}),disabled:!f,onClick:()=>void Be(),children:`生成命令`}),(0,$.jsx)(GS,{icon:_e?(0,$.jsx)(he,{size:14}):(0,$.jsx)(re,{size:14}),onClick:()=>ve(e=>!e),title:_e?`切到浅色`:`切到深色`}),(0,$.jsx)(GS,{icon:(0,$.jsx)(de,{size:14}),onClick:()=>ie(!0),children:`设置`})]})]}),e===`list`?(0,$.jsx)(`main`,{className:`min-h-0 flex-1 overflow-y-auto bg-[#F4F5F2] px-6 py-7 dark:bg-[#111214]`,children:(0,$.jsxs)(`div`,{className:`mx-auto w-full max-w-[1080px]`,children:[(0,$.jsxs)(`div`,{className:`mb-5`,children:[(0,$.jsx)(`h1`,{className:`text-[20px] font-semibold tracking-tight ${kW}`,children:`画布`}),(0,$.jsx)(`p`,{className:`mt-1 text-[12px] leading-[1.6] ${AW}`,children:`每张画布就是一张工作流;编辑自动保存,点「生成命令」把它变成一条对话命令。`})]}),c&&n.length===0?(0,$.jsx)(`div`,{className:`py-16 text-center text-[13px] ${AW}`,children:`正在加载画布…`}):(0,$.jsxs)($.Fragment,{children:[n.length===0?(0,$.jsx)(`div`,{className:`rounded-[8px] border border-dashed ${OW} py-14 text-center text-[13px] ${AW}`,children:`还没有画布,点右上角「新建画布」开始。`}):(0,$.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3`,children:n.map(e=>{let t=e.presetId?i.find(t=>t.id===e.presetId):null;return(0,$.jsxs)(`article`,{className:`flex min-h-[150px] flex-col rounded-[8px] border ${OW} bg-[#FCFCFA] p-4 dark:bg-[#17181B]`,children:[(0,$.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,$.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[D===e.id?(0,$.jsx)(PD,{size:`small`,autoFocus:!0,maxLength:60,value:k,onChange:e=>A(e.target.value),onBlur:()=>void tt(e),onPressEnter:e=>e.currentTarget.blur(),onKeyDown:e=>{e.key===`Escape`&&(j.current=!0,e.currentTarget.blur())},"aria-label":`重命名画布 ${e.name}`}):(0,$.jsx)(`button`,{type:`button`,onClick:()=>Ie(e.id),title:e.name,className:`block max-w-full text-left`,children:(0,$.jsx)(`h2`,{className:`truncate text-[15px] font-semibold ${kW}`,children:e.name})}),(0,$.jsxs)(`p`,{className:`mt-1 text-[11px] leading-[1.6] ${jW}`,children:[e.nodeCount,` 个节点 · 更新于 `,LW(e.updatedAt)]}),o[e.id]!==void 0&&(0,$.jsxs)(`p`,{className:`mt-0.5 truncate text-[11px] leading-[1.6] ${AW}`,title:o[e.id]||`没有调度卡;生成命令前先补一张`,children:[`对话入口:`,o[e.id]||`未设置(生成命令前先补一张调度卡)`]})]}),(0,$.jsxs)(`div`,{className:`flex shrink-0 flex-col items-end gap-1`,children:[(0,$.jsx)(JO,{color:t?`blue`:`default`,style:{marginInlineEnd:0},children:t?t.name:`自定义`}),e.hasDraft&&(0,$.jsx)(JO,{color:`gold`,style:{marginInlineEnd:0},children:`草稿`})]})]}),(0,$.jsxs)(`div`,{className:`mt-auto flex flex-wrap items-center gap-1 pt-3`,children:[(0,$.jsx)(GS,{size:`small`,type:`primary`,onClick:()=>Ie(e.id),children:`编辑`}),(0,$.jsx)(GS,{size:`small`,type:`text`,onClick:()=>et(e),children:`重命名`}),(0,$.jsx)(GS,{size:`small`,type:`text`,danger:!0,disabled:n.length<=1,title:n.length<=1?`至少要保留一张画布`:void 0,onClick:()=>void nt(e),children:`删除`})]})]},e.id)})}),Xe.length>0&&(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`div`,{className:`mb-3 mt-8 flex flex-wrap items-baseline gap-2`,children:[(0,$.jsx)(`h2`,{className:`text-[13px] font-semibold ${kW}`,children:`还没有画布的旧预设`}),(0,$.jsx)(`span`,{className:`text-[11px] ${jW}`,children:`从旧预设生成一张画布,再编辑并生成命令`})]}),(0,$.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3`,children:Xe.map(e=>(0,$.jsxs)(`article`,{className:`flex min-h-[150px] flex-col rounded-[8px] border border-dashed ${OW} bg-[#F9F9F6] p-4 dark:bg-[#151617]`,children:[(0,$.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,$.jsx)(`h2`,{className:`min-w-0 flex-1 truncate text-[15px] font-semibold ${kW}`,title:e.name,children:e.name}),(0,$.jsx)(JO,{style:{marginInlineEnd:0,flexShrink:0},children:e.source===`bundle`?`bundle`:`自定义`})]}),(0,$.jsx)(`p`,{className:`mt-1 line-clamp-3 text-[12px] leading-[1.6] ${AW}`,children:e.description||`没有描述`}),(0,$.jsx)(`div`,{className:`mt-auto pt-3`,children:(0,$.jsx)(GS,{size:`small`,loading:y===e.id,onClick:()=>void $e(e),children:`创建画布`})})]},e.id))})]})]})]})}):(0,$.jsxs)(`main`,{className:`relative min-h-0 flex-1`,children:[(0,$.jsxs)(`div`,{className:`pointer-events-none absolute left-4 top-[12px] z-10 flex items-center gap-1.5 rounded-[4px] bg-[#FCFCFA]/90 px-2 py-1 text-[11px] text-[#6b6b66] dark:bg-[#17181b]/90 dark:text-[#8b8b85]`,children:[(0,$.jsx)(`span`,{className:`h-[5px] w-[5px] rounded-full`,style:{background:R?R.mock?`#B4451F`:`#24543F`:`#b9bcb4`}}),R?R.mock?`mock`:`real`:`连接中`]}),f?(0,$.jsx)(GU,{board:f,selectedId:g,running:De,onSelect:v,onMove:Ue,onDerive:We,onConnect:Ge}):(0,$.jsx)(`div`,{className:`grid h-full place-items-center text-[13px] text-[#8a93a3]`,children:`正在加载画布…`})]}),e===`board`&&f&&Je&&(0,$.jsx)(fW,{node:Je,nodes:f.nodes,edges:f.edges,boardId:f.id,skills:N,servers:F,catalog:B,bridge:U,running:De,onPatch:e=>Ve(Je.id,e),onDerive:e=>We(Je.id,e),onVerify:e=>void qe(Je.id,e),onEdgesChange:He,onRefreshModels:()=>{Ee.current=Date.now(),QA.getModels(!0).then(V).catch(e=>Y(`刷新模型失败:${e.message}`,`err`)),QA.getBridge().then(ee).catch(()=>{})},onRerun:()=>void ze([Je.id]),onDelete:()=>void Ke(Je.id),onClose:()=>v(null)}),(0,$.jsx)(xW,{open:ne,config:R,servers:F,onClose:()=>ie(!1),onSaved:e=>{z(t=>t&&{...t,mock:e.mock}),QA.getMcp().then(e=>L(e.servers)).catch(()=>{}),Y(`设置已保存`)},onError:e=>Y(e,`err`)}),(0,$.jsx)(EW,{open:ae,boardId:u,boardName:m,onClose:()=>G(!1)}),(0,$.jsx)(RD,{open:x,title:`新建画布`,centered:!0,getContainer:()=>it.current??document.body,okText:`创建`,cancelText:`取消`,confirmLoading:T,okButtonProps:{disabled:!C.trim()},onOk:()=>void Qe(),onCancel:()=>S(!1),children:(0,$.jsx)(PD,{autoFocus:!0,maxLength:60,placeholder:`画布名称,例如「活动文案」`,value:C,onChange:e=>w(e.target.value),onPressEnter:()=>{C.trim()&&!T&&Qe()}})}),ye&&(0,$.jsx)(`div`,{className:`absolute bottom-6 left-1/2 z-50 -translate-x-1/2 rounded-lg px-4 py-2 text-[13px] shadow-lg ${ye.kind===`err`?`bg-[#ffebee] text-[#c62828] dark:bg-[#3a1b1f] dark:text-[#ff9a9a]`:`bg-[#1C1C1A] text-white dark:bg-[#e7e9ee] dark:text-[#0f1116]`}`,children:ye.msg})]})})}function FW(e){let t=`n-${Date.now().toString(36)}`,n=t,r=2;for(;e.some(e=>e.id===n);)n=`${t}-${r++}`;return n}function IW(e){let t=e.nodes.find(e=>e.type===`orchestrator`)??(e.nodes.length===1?e.nodes[0]:null);return t?t.label||t.id:null}function LW(e){if(!e)return`—`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`—`;let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}function RW(e,t,n){let r=new Set,i=[n];for(;i.length;){let n=i.pop();if(n===t)return!0;if(!r.has(n)){r.add(n);for(let t of e)t.from===n&&i.push(t.to)}}return!1}(0,v.createRoot)(document.getElementById(`root`)).render((0,$.jsx)(_.StrictMode,{children:(0,$.jsx)(PW,{})}));
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>AgentFlow · 物料画布</title>
|
|
7
|
-
|
|
7
|
+
<!-- 独立页面 / iframe 回退:画布根容器靠 .af-canvas{height:100%} 撑满,
|
|
8
|
+
样式作用域化之后 html/body/#root 的高度规则只留在这里(内联模式由 CanvasHost 负责) -->
|
|
9
|
+
<style>html,body,#root{height:100%;margin:0}</style>
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-Bjj6NK57.js"></script>
|
|
8
11
|
<link rel="stylesheet" crossorigin href="/assets/index-BRBK2BoT.css">
|
|
9
12
|
</head>
|
|
10
13
|
<body>
|