@runfusion/fusion 0.9.3 → 0.10.0
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/dist/bin.js +4077 -1291
- package/dist/client/assets/{AgentDetailView-D9UWpTYr.js → AgentDetailView-BtpZ4jxh.js} +3 -3
- package/dist/client/assets/{AgentsView-DeCfRupM.js → AgentsView-Dxdtt0Bm.js} +3 -3
- package/dist/client/assets/ChatView-Bra9fNAG.js +1 -0
- package/dist/client/assets/{DevServerView-B7EjWlgc.js → DevServerView-UkgjEw9-.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-crtmkC00.js → DirectoryPicker-Cls4HWxP.js} +1 -1
- package/dist/client/assets/{DocumentsView-BLxVoopL.js → DocumentsView-BRBUPFVA.js} +1 -1
- package/dist/client/assets/{InsightsView-CcdTychV.js → InsightsView-BRDqHCLb.js} +1 -1
- package/dist/client/assets/{MemoryView-rSwx9Md8.js → MemoryView-DvTrwFnQ.js} +1 -1
- package/dist/client/assets/{NodesView-Bwz0cHKV.js → NodesView-C4Ffl_o0.js} +3 -3
- package/dist/client/assets/{PiExtensionsManager-Uo3E8Ae7.js → PiExtensionsManager-CeI1syeZ.js} +3 -3
- package/dist/client/assets/{PluginManager-HtW8xVY8.js → PluginManager-BgeoYhLk.js} +1 -1
- package/dist/client/assets/ResearchView-BVJFgfat.css +1 -0
- package/dist/client/assets/ResearchView-fmEOm4A2.js +1 -0
- package/dist/client/assets/{RoadmapsView-C2j64cbz.js → RoadmapsView-DNb4x75S.js} +2 -2
- package/dist/client/assets/{SettingsModal-YjpwLH2V.css → SettingsModal-9HS8MnmW.css} +1 -1
- package/dist/client/assets/SettingsModal-CDPDmHhd.css +1 -0
- package/dist/client/assets/{SettingsModal-CVd9kNk7.js → SettingsModal-CRMr4tL6.js} +1 -1
- package/dist/client/assets/SettingsModal-D1xq0WZm.js +31 -0
- package/dist/client/assets/{SetupWizardModal-Dy-vQpTm.js → SetupWizardModal-tF8B_aG_.js} +1 -1
- package/dist/client/assets/{SkillsView-BQwTyjxc.js → SkillsView-uyl47gSf.js} +1 -1
- package/dist/client/assets/{TodoView-Dce4DrzU.js → TodoView-CbzDtV53.js} +2 -2
- package/dist/client/assets/{folder-open-DWUflP4Q.js → folder-open-DPpmGJ-v.js} +1 -1
- package/dist/client/assets/{index-C3-q81dV.css → index-BqK6TvSa.css} +1 -1
- package/dist/client/assets/index-DyXZm9QN.js +656 -0
- package/dist/client/assets/{list-checks-CusZ_RMn.js → list-checks-D62pw1I8.js} +1 -1
- package/dist/client/assets/{star-C-NXZn1F.js → star-B8EbxNgI.js} +1 -1
- package/dist/client/assets/{upload-CXJ5L6L4.js → upload-CpnLno9z.js} +1 -1
- package/dist/client/assets/{users-YaA3x5mt.js → users-B_C_0qzA.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/extension.js +3201 -714
- package/dist/pi-claude-cli/index.ts +31 -5
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/pi-claude-cli/src/__tests__/process-manager.test.ts +90 -0
- package/dist/pi-claude-cli/src/__tests__/provider.test.ts +13 -3
- package/dist/pi-claude-cli/src/process-manager.ts +65 -0
- package/package.json +1 -1
- package/dist/client/assets/ChatView-ChlqnJfu.js +0 -1
- package/dist/client/assets/ResearchView-BV-iy9g8.js +0 -1
- package/dist/client/assets/ResearchView-aQkoD9QR.css +0 -1
- package/dist/client/assets/SettingsModal-ClnT1Lcv.js +0 -31
- package/dist/client/assets/SettingsModal-FfIAhzcJ.css +0 -1
- package/dist/client/assets/index-Bs3RZu5I.js +0 -656
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{u as Ie}from"./SettingsModal-
|
|
1
|
+
import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{u as Ie}from"./SettingsModal-CRMr4tL6.js";import{bl as ke,bm as Ee,bn as Le,t as Re,bo as qe,bp as Pe,bq as We,br as we,bs as Me,bt as Te,bu as _e,bv as Oe,bw as Ae,bx as Ue,q as Qe,by as He,L as w,bz as Fe}from"./index-DyXZm9QN.js";import"./vendor-xterm-DzcZoU0P.js";const _=".fusion/memory/MEMORY.md",$e=5e4,Ye="0 3 * * *",Be="0 4 * * *";function he(i){return{memoryEnabled:i.memoryEnabled!==!1,memoryAutoSummarizeEnabled:i.memoryAutoSummarizeEnabled??!1,memoryAutoSummarizeThresholdChars:i.memoryAutoSummarizeThresholdChars??$e,memoryAutoSummarizeSchedule:i.memoryAutoSummarizeSchedule??Ye,memoryDreamsEnabled:i.memoryDreamsEnabled??!1,memoryDreamsSchedule:i.memoryDreamsSchedule??Be}}function De(i,t){return i.some(c=>c.path===t)?t:i.find(c=>c.path===_)?.path??i[0]?.path??_}function Ge(i={}){const{projectId:t}=i,[c,j]=a.useState(""),[z,M]=a.useState(!0),[C,k]=a.useState(!1),[g,b]=a.useState(!1),[r,x]=a.useState(null),[O,J]=a.useState(!0),[X,I]=a.useState(!1),[v,W]=a.useState(()=>he({})),[A,ee]=a.useState(!0),[ue,U]=a.useState(!1),[o,S]=a.useState([]),[se,L]=a.useState(!0),[m,E]=a.useState(_),[T,u]=a.useState(""),[d,te]=a.useState(!1),[Q,p]=a.useState(!1),[ae,H]=a.useState(!1),[ne,$]=a.useState(!1),[Y,re]=a.useState(!1),[F,D]=a.useState(null),[ye,R]=a.useState(!0),[ge,B]=a.useState(!1),[ie,G]=a.useState(!1),[le,V]=a.useState(null),{status:me,loading:Z,refresh:f}=Ie({projectId:t}),be=a.useCallback(n=>{u(n),p(!0)},[]),N=a.useCallback(async n=>{te(!0);try{const{content:l}=await ke(n,t);E(n),u(l),p(!1)}finally{te(!1)}},[t]),q=a.useCallback(async()=>{L(!0);try{const{files:n}=await Ee(t);if(S(n),n.length===0){E(_),u(""),p(!1);return}const l=De(n,m);l!==m&&await N(l)}finally{L(!1)}},[t,m,N]);a.useEffect(()=>{let n=!1;async function l(){try{const s=await Ue(t);n||(j(s.content),M(!1))}catch{n||(j(""),M(!1))}}return l(),()=>{n=!0}},[t]),a.useEffect(()=>{let n=!1;async function l(){try{const s=await Me(t);n||(x(s.content),I(s.exists),J(!1))}catch{n||(x(null),I(!1),J(!1))}}return l(),()=>{n=!0}},[t]),a.useEffect(()=>{let n=!1;async function l(){ee(!0);try{const s=await Qe(t);n||W(he(s))}catch{n||W(he({}))}finally{n||ee(!1)}}return l(),()=>{n=!0}},[t]),a.useEffect(()=>{let n=!1;async function l(){L(!0);try{const{files:s}=await Ee(t);if(n)return;if(S(s),s.length===0){E(_),u(""),p(!1);return}const h=De(s,m),{content:y}=await ke(h,t);if(n)return;E(h),u(y),p(!1)}catch{n||(S([]),E(_),u(""),p(!1))}finally{n||L(!1)}}return l(),()=>{n=!0}},[t,m]),a.useEffect(()=>{let n=!1;async function l(){try{const s=await we(t);n||(D(s),R(!1))}catch{n||(D(null),R(!1))}}return l(),()=>{n=!0}},[t]),a.useEffect(()=>{let n=!1;async function l(){try{const s=await He(t);n||V(s)}catch{n||V(null)}}return l(),()=>{n=!0}},[t]);const ce=a.useCallback(n=>{j(n),k(!0)},[]),oe=a.useCallback(async()=>{if(C){b(!0);try{await Le(c,t),k(!1)}finally{b(!1)}}},[c,C,t]),xe=a.useCallback(async n=>{U(!0);try{const l=await Re(n,t);W(he(l))}finally{U(!1)}},[t]),pe=a.useCallback(async n=>{await N(n)},[N]),fe=a.useCallback(async()=>{if(Q){H(!0);try{await qe(m,T,t),p(!1),await q()}finally{H(!1)}}},[T,Q,m,t,q]),je=a.useCallback(async()=>{G(!0);try{const n=await Pe(t);return await f(),n}finally{G(!1)}},[t,f]),ve=a.useCallback(async n=>We(n,t),[t]),K=a.useCallback(async()=>{try{const n=await we(t);D(n)}catch{D(null)}},[t]),P=a.useCallback(async()=>{try{const n=await Me(t);x(n.content),I(n.exists)}catch{x(null),I(!1)}},[t]),de=a.useCallback(async n=>{await Te(n,t),await P()},[t,P]),Se=a.useCallback(async()=>{$(!0);try{const n=await _e(t);return await Promise.all([P(),K()]),{success:n.success,summary:n.summary}}finally{$(!1)}},[t,P,K]),Ne=a.useCallback(async()=>{re(!0);try{return await Oe(t)}finally{re(!1)}},[t]),Ce=a.useCallback(async n=>{B(!0);try{const l=n?await Ae(n,t):await Ae(t);if(n){const s=l.path??n;E(s),u(l.content),p(!1),await q();return}j(l.content),k(!0)}finally{B(!1)}},[t,q]);return{workingMemory:c,workingMemoryLoading:z,workingMemoryDirty:C,setWorkingMemory:ce,saveWorkingMemory:oe,savingWorkingMemory:g,insightsContent:r,insightsLoading:O,insightsExists:X,refreshInsights:P,saveInsights:de,memorySettings:v,settingsLoading:A,savingMemorySettings:ue,saveMemorySettings:xe,memoryFiles:o,memoryFilesLoading:se,selectedFilePath:m,selectedFileContent:T,selectedFileLoading:d,selectedFileDirty:Q,setSelectedFileContent:be,selectFile:pe,saveSelectedFile:fe,savingSelectedFile:ae,reloadMemoryFiles:q,backendStatus:me,backendLoading:Z,extractInsights:Se,extracting:ne,triggerDreamNow:Ne,dreamRunning:Y,auditReport:F,auditLoading:ye,refreshAudit:K,compactMemory:Ce,compacting:ge,installQmdAction:je,installingQmd:ie,testRetrieval:ve,stats:le}}const Ve={Patterns:"pattern",Principles:"principle",Conventions:"convention",Pitfalls:"pitfall",Context:"context"},Ze={"long-term":"Long-term",daily:"Daily",dreams:"Dreams"},Ke={"long-term":"Curated durable decisions, conventions, constraints, and pitfalls promoted from dreams.",daily:"Raw daily observations, open loops, and running context for dream processing.",dreams:"Synthesized patterns and open loops promoted from daily memory."};function Je(i){if(!i)return[];const t=[],c=i.split(/(?=^## )/m);for(const j of c){const z=j.trim();if(!z)continue;const M=z.match(/^##\s+(.+?)(\n|$)/);if(M){const C=M[1].trim(),k=Ve[C]??C.toLowerCase(),g=z.slice(M[0].length).trim(),b=g.split(`
|
|
2
2
|
`).map(r=>r.replace(/^-\s+/,"").trim()).filter(r=>r.length>0&&(r.startsWith("- ")||r.startsWith("* ")));(b.length>0||g.length>0)&&t.push({name:C,key:k,items:b.length>0?b:g.length>0?[g]:[],expanded:!0})}}return t}function Xe(i){if(!i)return null;const t=i.match(/##\s+Last\s+Updated:\s*(\d{4}-\d{2}-\d{2})/i);return t?t[1]:null}function es(i){return i.reduce((t,c)=>t+c.items.length,0)}function ss(i){switch(i){case"file":return"File (.fusion/memory/)";case"readonly":return"Read-Only";case"qmd":return"QMD (Quantized Memory Distillation)";default:return i}}function ts(i){switch(i){case"healthy":return"Healthy";case"warning":return"Warning";case"issues":return"Issues Found"}}function ls({projectId:i,addToast:t}){const[c,j]=a.useState("working"),[z,M]=a.useState(new Set),[C,k]=a.useState(!1),[g,b]=a.useState(null),[r,x]=a.useState({memoryEnabled:!0,memoryAutoSummarizeEnabled:!1,memoryAutoSummarizeThresholdChars:5e4,memoryAutoSummarizeSchedule:"0 3 * * *",memoryDreamsEnabled:!1,memoryDreamsSchedule:"0 4 * * *"}),[O,J]=a.useState(""),[X,I]=a.useState(!1),[v,W]=a.useState(null),{insightsContent:A,insightsLoading:ee,insightsExists:ue,saveInsights:U,memorySettings:o,settingsLoading:S,saveMemorySettings:se,savingMemorySettings:L,backendStatus:m,backendLoading:E,extractInsights:T,extracting:u,auditReport:d,auditLoading:te,refreshAudit:Q,compactMemory:p,compacting:ae,installQmdAction:H,installingQmd:ne,testRetrieval:$,memoryFiles:Y,memoryFilesLoading:re,selectedFilePath:F,selectedFileContent:D,selectedFileLoading:ye,selectedFileDirty:R,setSelectedFileContent:ge,selectFile:B,saveSelectedFile:ie,savingSelectedFile:G,reloadMemoryFiles:le,triggerDreamNow:V,dreamRunning:me}=Ge({projectId:i});a.useEffect(()=>{x(o)},[o]);const Z=a.useMemo(()=>r.memoryEnabled!==o.memoryEnabled||r.memoryAutoSummarizeEnabled!==o.memoryAutoSummarizeEnabled||r.memoryAutoSummarizeThresholdChars!==o.memoryAutoSummarizeThresholdChars||r.memoryAutoSummarizeSchedule!==o.memoryAutoSummarizeSchedule||r.memoryDreamsEnabled!==o.memoryDreamsEnabled||r.memoryDreamsSchedule!==o.memoryDreamsSchedule,[r,o]),f=a.useMemo(()=>Y.find(s=>s.path===F),[Y,F]),be=f?Ke[f.layer]:"Edits the selected memory file.",N=a.useMemo(()=>Je(A),[A]),q=a.useMemo(()=>es(N),[N]),ce=a.useMemo(()=>Xe(A),[A]),oe=a.useCallback(s=>{M(h=>{const y=new Set(h);return y.has(s)?y.delete(s):y.add(s),y})},[]),xe=a.useCallback(async s=>{try{await B(s)}catch{t("Failed to load memory file","error")}},[B,t]),pe=a.useCallback(async()=>{try{await ie(),t("Memory saved","success")}catch{t("Failed to save memory","error")}},[ie,t]),fe=a.useCallback(async()=>{if(!Z)return;const s={};r.memoryEnabled!==o.memoryEnabled&&(s.memoryEnabled=r.memoryEnabled),r.memoryAutoSummarizeEnabled!==o.memoryAutoSummarizeEnabled&&(s.memoryAutoSummarizeEnabled=r.memoryAutoSummarizeEnabled),r.memoryAutoSummarizeThresholdChars!==o.memoryAutoSummarizeThresholdChars&&(s.memoryAutoSummarizeThresholdChars=r.memoryAutoSummarizeThresholdChars),r.memoryAutoSummarizeSchedule!==o.memoryAutoSummarizeSchedule&&(s.memoryAutoSummarizeSchedule=r.memoryAutoSummarizeSchedule),r.memoryDreamsEnabled!==o.memoryDreamsEnabled&&(s.memoryDreamsEnabled=r.memoryDreamsEnabled),r.memoryDreamsSchedule!==o.memoryDreamsSchedule&&(s.memoryDreamsSchedule=r.memoryDreamsSchedule);try{await se(s),t("Memory settings saved","success")}catch{t("Failed to save memory settings","error")}},[Z,r,o,se,t]),je=a.useCallback(async()=>{try{const s=await H();t(s.qmdAvailable?"qmd installed successfully":"qmd install finished, but qmd is still unavailable",s.qmdAvailable?"success":"info")}catch{t("Failed to install qmd","error")}},[H,t]),ve=a.useCallback(async()=>{I(!0),W(null);try{const s=await $(O);W(s),t(s.qmdAvailable?"Memory retrieval test complete":"qmd is not installed; local fallback was used",s.qmdAvailable?"success":"info")}catch{t("Failed to test memory retrieval","error")}finally{I(!1)}},[O,$,t]),K=a.useCallback(async()=>{try{await V(),t("Dream processing completed","success"),await le()}catch(s){t(s instanceof Error?s.message:"Failed to run dream processing","error")}},[V,le,t]),P=a.useCallback(async()=>{try{await p(F),t("Memory file compacted","success")}catch{t("Failed to compact memory","error")}},[p,F,t]),de=a.useCallback(async()=>{try{const s=await T();t(s.summary,"success")}catch(s){t(s instanceof Error?s.message:"Failed to extract insights","error")}},[T,t]),Se=a.useCallback(async()=>{if(g!==null)try{await U(g),k(!1),b(null),t("Insights saved","success")}catch{t("Failed to save insights","error")}},[g,U,t]),Ne=a.useCallback(()=>{b(A??""),k(!0)},[A]),Ce=a.useCallback(()=>{k(!1),b(null)},[]),n=!E&&m!==null,l=m?.capabilities?.writable??!1;return e.jsxs("div",{className:"memory-view",children:[e.jsx("div",{className:"memory-view-header",children:e.jsxs("div",{children:[e.jsx("h2",{children:"Memory"}),e.jsx("p",{className:"memory-view-description",children:"Working memory, long-term insights, and engine status"})]})}),e.jsxs("div",{className:"memory-view-tabs",role:"tablist",children:[e.jsx("button",{type:"button",role:"tab","aria-selected":c==="working",className:`memory-view-tab${c==="working"?" memory-view-tab--active":""}`,onClick:()=>j("working"),"data-testid":"memory-tab-working",children:"Working Memory"}),e.jsx("button",{type:"button",role:"tab","aria-selected":c==="insights",className:`memory-view-tab${c==="insights"?" memory-view-tab--active":""}`,onClick:()=>j("insights"),"data-testid":"memory-tab-insights",children:"Insights"}),e.jsx("button",{type:"button",role:"tab","aria-selected":c==="engines",className:`memory-view-tab${c==="engines"?" memory-view-tab--active":""}`,onClick:()=>j("engines"),"data-testid":"memory-tab-engines",children:"Engines"})]}),e.jsxs("div",{className:"memory-view-content",children:[c==="working"&&e.jsxs("div",{className:"memory-working-tab",children:[n&&!l&&e.jsx("div",{className:"memory-readonly-banner",children:"This memory backend is read-only. Changes cannot be saved."}),re||ye?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(w,{size:20,className:"animate-spin"}),e.jsx("span",{children:"Loading memory file…"})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"memory-editor-section",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryViewFilePath",children:"Memory File"}),e.jsx("select",{id:"memoryViewFilePath",className:"select",value:F,onChange:s=>{xe(s.target.value)},disabled:R,children:Y.map(s=>e.jsxs("option",{value:s.path,children:[s.label," - ",s.path]},s.path))}),e.jsx("small",{children:R?"Save or discard the current edits before switching files.":"Choose any project memory file to view or edit."})]}),f&&e.jsxs("div",{className:"memory-file-summary",children:[e.jsx("span",{children:Ze[f.layer]}),e.jsx("strong",{children:f.path}),e.jsxs("small",{children:[f.size.toLocaleString()," bytes · updated ",new Date(f.updatedAt).toLocaleString()]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:f?.label||"Memory Editor"}),e.jsx("small",{children:be}),e.jsx("div",{className:"memory-editor-container",children:e.jsx(Fe,{content:D,onChange:ge,readOnly:!l,filePath:F})})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsxs("span",{className:"memory-char-count",children:[D.length," characters"]}),e.jsx("div",{className:"memory-flex-spacer"}),l&&D.length>0&&e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:P,disabled:ae||R,children:ae?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Compacting…"]}):"Compact Selected File"}),R&&l&&e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:pe,disabled:G,children:G?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Saving…"]}):"Save"})]}),e.jsxs("div",{className:"memory-config-section",children:[e.jsxs("div",{className:"memory-settings-group",children:[e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:"memoryDreamsEnabled",className:"checkbox-label",children:[e.jsx("input",{id:"memoryDreamsEnabled",type:"checkbox",checked:r.memoryDreamsEnabled,onChange:s=>{x(h=>({...h,memoryDreamsEnabled:s.target.checked}))},disabled:!r.memoryEnabled||S}),"Process dreams from daily memory"]}),e.jsx("small",{children:"Turns daily notes into DREAMS.md and promotes reusable lessons into MEMORY.md."})]}),r.memoryEnabled&&r.memoryDreamsEnabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryDreamsSchedule",children:"Dream Schedule"}),e.jsx("input",{id:"memoryDreamsSchedule",type:"text",className:"input",value:r.memoryDreamsSchedule,onChange:s=>{x(h=>({...h,memoryDreamsSchedule:s.target.value}))},placeholder:"0 4 * * *",disabled:S}),e.jsx("small",{children:"Cron expression for dream processing."})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("button",{type:"button",className:"btn btn-sm",onClick:K,disabled:me||!r.memoryDreamsEnabled,children:me?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Dreaming…"]}):"Dream Now"}),e.jsx("small",{children:"Manually trigger dream processing now."})]})]})]}),e.jsxs("div",{className:"memory-settings-group",children:[e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:"memoryAutoSummarizeEnabled",className:"checkbox-label",children:[e.jsx("input",{id:"memoryAutoSummarizeEnabled",type:"checkbox",checked:r.memoryAutoSummarizeEnabled,onChange:s=>{x(h=>({...h,memoryAutoSummarizeEnabled:s.target.checked}))},disabled:!r.memoryEnabled||S}),"Auto-Summarize Memory"]}),e.jsx("small",{children:"Automatically compact memory when it exceeds the threshold on a schedule"})]}),r.memoryEnabled&&r.memoryAutoSummarizeEnabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryAutoSummarizeThresholdChars",children:"Compaction Threshold (chars)"}),e.jsx("input",{id:"memoryAutoSummarizeThresholdChars",type:"number",className:"input",value:r.memoryAutoSummarizeThresholdChars,onChange:s=>{x(h=>({...h,memoryAutoSummarizeThresholdChars:parseInt(s.target.value,10)||5e4}))},min:1e3,disabled:S}),e.jsx("small",{children:"Memory will be compacted when it exceeds this character count"})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"memoryAutoSummarizeSchedule",children:"Schedule (cron)"}),e.jsx("input",{id:"memoryAutoSummarizeSchedule",type:"text",className:"input",value:r.memoryAutoSummarizeSchedule,onChange:s=>{x(h=>({...h,memoryAutoSummarizeSchedule:s.target.value}))},placeholder:"0 3 * * *",disabled:S}),e.jsx("small",{children:"Cron expression for auto-summarize schedule (default: daily at 3 AM)"})]})]})]}),!r.memoryEnabled&&e.jsx("div",{className:"settings-empty-state memory-status-message",children:"Memory is currently disabled. Enable memory tools in Settings to edit these automations."}),Z&&e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:fe,disabled:L||S,children:L?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Saving…"]}):"Save Settings"})})]})]})]}),c==="insights"&&e.jsx("div",{className:"memory-insights-tab",children:ee?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(w,{size:20,className:"animate-spin"}),e.jsx("span",{children:"Loading insights…"})]}):C?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"memory-editor-container",children:e.jsx(Fe,{content:g??"",onChange:b,readOnly:!1,filePath:".fusion/memory/INSIGHTS.md"})}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:Ce,children:"Cancel"}),e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:Se,children:"Save Insights"})]})]}):!ue||N.length===0?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx("p",{children:"No insights extracted yet."}),e.jsx("p",{children:'Insights are automatically extracted from working memory. Click "Extract Now" to trigger extraction manually.'}),e.jsx("button",{type:"button",className:"btn btn-primary btn-sm memory-empty-extract-button",onClick:de,disabled:u,children:u?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Extracting…"]}):"Extract Now"})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"memory-stats-row",children:[e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value",children:q}),e.jsx("div",{className:"memory-stat-label",children:"Total Insights"})]}),e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value",children:N.length}),e.jsx("div",{className:"memory-stat-label",children:"Categories"})]}),ce&&e.jsxs("div",{className:"memory-stat-card",children:[e.jsx("div",{className:"memory-stat-value memory-stat-value--updated",children:ce}),e.jsx("div",{className:"memory-stat-label",children:"Last Updated"})]})]}),e.jsxs("div",{className:"memory-action-bar",children:[e.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:de,disabled:u,children:u?e.jsxs(e.Fragment,{children:[e.jsx(w,{size:14,className:"animate-spin"}),"Extracting…"]}):"Extract Now"}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:Ne,children:"Edit Raw"})]}),e.jsx("div",{className:"memory-categories-list",children:N.map(s=>{const h=!z.has(s.key);return e.jsxs("div",{className:"memory-category-section",children:[e.jsxs("div",{className:"memory-category-header",onClick:()=>oe(s.key),role:"button",tabIndex:0,onKeyDown:y=>{(y.key==="Enter"||y.key===" ")&&(y.preventDefault(),oe(s.key))},children:[e.jsx("h4",{children:s.name}),e.jsx("span",{className:"memory-category-count",children:s.items.length})]}),h&&e.jsx("div",{className:"memory-category-items",children:s.items.map((y,ze)=>e.jsx("div",{className:"memory-insight-item",children:y.replace(/^-\s+/,"").replace(/^\*\s+/,"")},ze))})]},s.key)})})]})}),c==="engines"&&e.jsx("div",{className:"memory-engines-tab",children:E||te?e.jsxs("div",{className:"memory-empty-state",children:[e.jsx(w,{size:20,className:"animate-spin"}),e.jsx("span",{children:"Loading engine status…"})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"memory-engine-card memory-qmd-card",children:[e.jsx("h3",{children:"QMD Integration"}),m?.qmdAvailable===!0?e.jsxs("div",{className:"memory-engine-status",children:[e.jsx("span",{className:"memory-health-badge memory-health-badge--healthy",children:"Installed"}),e.jsx("span",{className:"memory-char-count",children:"qmd is available on PATH."})]}):m?.qmdAvailable===!1?e.jsxs("div",{className:"settings-empty-state memory-status-message",children:[e.jsxs("span",{children:["qmd is not installed. Search will use local files. Install indexed retrieval: ",e.jsx("code",{children:m.qmdInstallCommand||"bun install -g @tobilu/qmd"})]}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:je,disabled:ne,children:ne?"Installing…":"Install qmd"})]}):e.jsxs("div",{className:"memory-engine-status",children:[e.jsx("span",{className:"memory-health-badge",children:"Checking"}),e.jsx("span",{className:"memory-char-count",children:"Checking qmd availability…"})]}),e.jsxs("div",{className:"memory-capability-row",children:[m?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:"Readable"}),m?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:"Writable"}),m?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:"Atomic Writes"}),m?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:"Persistent"})]})]}),e.jsxs("div",{className:"memory-engine-card memory-retrieval-card",children:[e.jsx("h3",{children:"Test Memory Search"}),e.jsxs("div",{className:"memory-retrieval-input-row",children:[e.jsx("input",{type:"text",className:"input",value:O,onChange:s=>J(s.target.value),placeholder:"Search memory with qmd"}),e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:ve,disabled:X,children:X?"Testing…":"Test Retrieval"})]}),e.jsx("small",{className:"settings-muted",children:"Runs the same qmd-backed memory_search path agents use."}),v&&e.jsxs("div",{className:"memory-test-result",children:[e.jsxs("strong",{children:[v.results.length," result",v.results.length===1?"":"s"," ",'for "',v.query,'"']}),e.jsxs("small",{children:["qmd ",v.qmdAvailable?"available":"missing"," · ",v.usedFallback?"local fallback used":"qmd path used"]}),v.results.length>0?e.jsx("ul",{children:v.results.map((s,h)=>e.jsxs("li",{children:[e.jsxs("span",{children:[s.path,":",s.lineStart]}),e.jsx("p",{children:s.snippet})]},`${s.path}-${s.lineStart}-${h}`))}):e.jsx("small",{children:"No matching memory found."})]})]}),e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:"Current Backend"}),e.jsx("div",{className:"memory-engine-status",children:e.jsx("span",{className:"memory-emphasis-text",children:ss(m?.currentBackend??"unknown")})}),e.jsxs("div",{className:"memory-capability-row",children:[m?.capabilities?.readable&&e.jsx("span",{className:"memory-capability-badge",children:"Readable"}),m?.capabilities?.writable&&e.jsx("span",{className:"memory-capability-badge",children:"Writable"}),m?.capabilities?.supportsAtomicWrite&&e.jsx("span",{className:"memory-capability-badge",children:"Atomic Writes"}),m?.capabilities?.persistent&&e.jsx("span",{className:"memory-capability-badge",children:"Persistent"})]})]}),d&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsxs("div",{className:"memory-health-header",children:[e.jsx("h3",{children:"Health Status"}),e.jsx("span",{className:`memory-health-badge memory-health-badge--${d.health}`,children:ts(d.health)})]}),e.jsxs("div",{className:"memory-health-grid",children:[e.jsxs("div",{children:[e.jsx("div",{className:"memory-health-label",children:"Working Memory"}),e.jsxs("div",{className:"memory-emphasis-text",children:[d.workingMemory.size," chars"]}),e.jsxs("div",{className:"memory-health-detail",children:[d.workingMemory.sectionCount," sections"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"memory-health-label",children:"Insights Memory"}),e.jsxs("div",{className:"memory-emphasis-text",children:[d.insightsMemory.size," chars"]}),e.jsxs("div",{className:"memory-health-detail",children:[d.insightsMemory.insightCount," insights"]})]})]}),e.jsxs("div",{className:"memory-health-section",children:[e.jsx("div",{className:"memory-health-label",children:"Last Extraction"}),e.jsx("div",{className:"memory-emphasis-text",children:d.extraction.success?e.jsx("span",{className:"memory-status-text memory-status-text--success",children:"Success"}):e.jsx("span",{className:"memory-status-text memory-status-text--error",children:"Failed"})}),e.jsx("div",{className:"memory-health-detail",children:d.extraction.summary||`${d.extraction.insightCount} insights extracted`})]}),e.jsxs("div",{className:"memory-health-section",children:[e.jsx("div",{className:"memory-health-label",children:"Pruning"}),e.jsx("div",{className:"memory-emphasis-text",children:d.pruning.applied?e.jsx("span",{className:"memory-status-text memory-status-text--warning",children:"Applied"}):e.jsx("span",{className:"memory-status-text memory-status-text--muted",children:"Not needed"})}),d.pruning.applied&&e.jsx("div",{className:"memory-health-detail",children:d.pruning.reason})]})]}),d&&d.checks.length>0&&e.jsxs("div",{className:"memory-engine-card",children:[e.jsx("h3",{children:"Audit Checks"}),e.jsx("div",{children:d.checks.map(s=>e.jsxs("div",{className:"memory-audit-check",children:[e.jsx("span",{className:s.passed?"memory-audit-check-passed":"memory-audit-check-failed",children:s.passed?"✓":"✗"}),e.jsxs("div",{className:"memory-audit-check-content",children:[e.jsx("div",{className:"memory-emphasis-text",children:s.name}),e.jsx("div",{className:"memory-health-detail",children:s.details})]})]},s.id))})]}),e.jsx("div",{className:"memory-action-bar",children:e.jsx("button",{type:"button",className:"btn btn-secondary btn-sm",onClick:()=>Q(),children:"Run Audit"})}),e.jsxs("div",{className:"memory-settings-note",children:[e.jsx("span",{children:"Note: Change backend type in"}),e.jsx("button",{type:"button",className:"memory-settings-note-button",onClick:()=>{t("Open Settings → Memory to change backend type","info")},children:"Settings → Memory"})]})]})})]})]})}export{ls as MemoryView};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as n,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Y,
|
|
1
|
+
import{r as n,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Y,au as xe,av as ge,aw as pe,ax as je,ay as Z,az as Q,A as T,aA as _e,N as Ne,O as be,aB as ee,aC as ve,aD as Ce,X as V,aE as ke,aF as Se,R as J,D as G,G as we}from"./index-DyXZm9QN.js";import{U as se}from"./upload-CpnLno9z.js";import"./vendor-xterm-DzcZoU0P.js";/**
|
|
2
2
|
* @license lucide-react v1.7.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -8,7 +8,7 @@ import{r as n,j as e}from"./vendor-react-K0fH_qHe.js";import{c as Y,ao as xe,ap
|
|
|
8
8
|
*
|
|
9
9
|
* This source code is licensed under the ISC license.
|
|
10
10
|
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
-
*/const Ee=[["path",{d:"M12 20h.01",key:"zekei9"}],["path",{d:"M2 8.82a15 15 0 0 1 20 0",key:"dnpr2z"}],["path",{d:"M5 12.859a10 10 0 0 1 14 0",key:"1x1e6c"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0",key:"1bycff"}]],Re=Y("wifi",Ee);function U(t){const{lastSyncAt:l,remoteReachable:s,diff:r}=t,f=r.global.length+r.project.length;return l===null?{syncState:"never-synced",lastSyncAt:l,diffCount:0}:s?f>0?{syncState:"diff",lastSyncAt:l,diffCount:f}:{syncState:"synced",lastSyncAt:l,diffCount:0}:{syncState:"error",lastSyncAt:l,diffCount:f}}function te(t){if(t===null)return"Never synced";const l=new Date(t);if(Number.isNaN(l.getTime()))return"Never synced";const r=Date.now()-l.getTime(),f=Math.floor(r/1e3),m=Math.floor(f/60),c=Math.floor(m/60),u=Math.floor(c/24);return m<1?"Synced just now":m<60?`Synced ${m}m ago`:c<24?`Synced ${c}h ago`:`Synced ${u}d ago`}function ae(t){switch(t){case"synced":return"var(--color-success)";case"pending":return"var(--color-warning)";case"diff":return"var(--color-warning)";case"error":return"var(--color-error)";case"never-synced":return"var(--text-muted)"}}const Pe=3e4;function $e(){const[t,l]=n.useState({}),[s,r]=n.useState(!1),[f,m]=n.useState({}),[c,u]=n.useState(null),o=n.useRef(new Set),y=n.useRef(!1),g=n.useRef(null),j=n.useRef(null),C=n.useCallback(async(h,d)=>{try{const p=await xe(h);l(z=>({...z,[h]:p})),u(null)}catch(p){console.error(`Failed to fetch sync status for node ${h}:`,p),u(p instanceof Error?p.message:"Failed to fetch sync status")}},[]),_=n.useCallback(async()=>{const h=Array.from(o.current);if(h.length===0)return;g.current&&g.current.abort(),g.current=new AbortController;const d=!y.current;d&&r(!0),u(null);try{const p=await Promise.allSettled(h.map(L=>C(L,d)));y.current=!0,p.filter(L=>L.status==="rejected").length>0&&u("Some sync status requests failed")}catch(p){if(p instanceof Error&&p.name==="AbortError")return;u(p instanceof Error?p.message:"Failed to fetch sync status"),y.current=!0}finally{r(!1)}},[C]),S=n.useCallback(()=>{j.current&&clearInterval(j.current),j.current=setInterval(()=>{_()},Pe)},[_]),A=n.useCallback(()=>{j.current&&(clearInterval(j.current),j.current=null)},[]);n.useEffect(()=>(_(),S(),()=>{A(),g.current&&g.current.abort()}),[_,S,A]);const a=n.useCallback(h=>{o.current.has(h)||(o.current.add(h),C(h,!y.current))},[C]),i=n.useCallback(h=>{o.current.delete(h),l(d=>{const p={...d};return delete p[h],p}),o.current.size===0&&A()},[A]),x=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{const d=await ge(h);return C(h,!1),!d.success&&d.error&&u(d.error),d}catch(d){const p=d instanceof Error?d.message:"Push settings failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[C]),b=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{const d=await pe(h);return C(h,!1),!d.success&&d.error&&u(d.error),d}catch(d){const p=d instanceof Error?d.message:"Pull settings failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[C]),w=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{return await je(h)}catch(d){const p=d instanceof Error?d.message:"Auth sync failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[]),$=n.useCallback(h=>t[h]?.authMatch,[t]),v=n.useCallback(h=>t[h]?.authDiff,[t]);return{syncStatusMap:t,loading:s,actionLoading:f,error:c,refresh:_,trackNode:a,untrackNode:i,pushSettings:x,pullSettings:b,syncAuth:w,getAuthSyncState:$,getAuthProviders:v}}function Le(t,l){return l.type==="remote"?t.nodeId===l.id:t.nodeId===l.id||t.nodeId===void 0||t.nodeId===null}function ne(t,l){return t.filter(s=>Le(s,l))}function H(t,l){return ne(t,l).length}const ze={online:{label:"Online",color:"var(--color-success)",className:"node-card__status--online"},offline:{label:"Offline",color:"var(--color-error)",className:"node-card__status--offline"},connecting:{label:"Connecting",color:"var(--color-warning)",className:"node-card__status--connecting"},error:{label:"Error",color:"var(--color-error)",className:"node-card__status--error"}},De={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function Oe(t,l){if(t==="match")return"Auth credentials match";if(t==="not-synced")return"Auth not synced";if(l&&Object.keys(l).length>0){const s=Object.entries(l).filter(([,r])=>r==="differs").map(([r])=>r);if(s.length>0)return`Auth credentials differ: ${s.join(", ")}`}return"Auth credentials differ"}function Fe(t,l=42){return t.length<=l?t:`${t.slice(0,l-3)}...`}function Ie(t,l){const s=t.node,r=l.node;if(s.id!==r.id||s.name!==r.name||s.type!==r.type||s.url!==r.url||s.status!==r.status||s.maxConcurrent!==r.maxConcurrent||s.updatedAt!==r.updatedAt||t.isLoading!==l.isLoading)return!1;const f=t.syncStatus,m=l.syncStatus;if(!(!f&&!m)){if(!f||!m)return!1;if(f.syncState!==m.syncState||f.lastSyncAt!==m.lastSyncAt||f.diffCount!==m.diffCount)return!1}if(t.authSyncState!==l.authSyncState)return!1;const c=t.authSyncProviders,u=l.authSyncProviders;if(c!==u){if(!c||!u)return!1;{const g=Object.keys(c),j=Object.keys(u);if(g.length!==j.length||g.some(C=>c[C]!==u[C]))return!1}}const o=H(t.projects,s),y=H(l.projects,r);return o===y}function Ke({node:t,projects:l,onHealthCheck:s,onEdit:r,onRemove:f,isLoading:m=!1,syncStatus:c,authSyncState:u,authSyncProviders:o}){const[y,g]=n.useState(!1),j=ze[t.status],C=n.useMemo(()=>H(l,t),[l,t]),_=n.useCallback(()=>{r(t)},[r,t]),S=n.useCallback(x=>{x.stopPropagation(),s(t.id)},[s,t.id]),A=n.useCallback(x=>{x.stopPropagation(),r(t)},[r,t]),a=n.useCallback(x=>{if(x.stopPropagation(),!y){g(!0);return}f(t.id),g(!1)},[y,f,t.id]),i=n.useCallback(x=>{(x.key==="Enter"||x.key===" ")&&(x.preventDefault(),r(t))},[r,t]);return e.jsxs("article",{className:`node-card ${m?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:_,onKeyDown:i,children:[e.jsx("header",{className:"node-card__header",children:e.jsxs("div",{className:"node-card__title-wrap",children:[e.jsx("div",{className:"node-card__icon",children:e.jsx(Z,{size:18})}),e.jsxs("div",{children:[e.jsx("h3",{className:"node-card__name",title:t.name,children:t.name}),e.jsxs("div",{className:"node-card__meta-row",children:[e.jsx("span",{className:"node-card__type-badge",children:t.type==="local"?"Local":"Remote"}),e.jsxs("span",{className:`node-card__status ${j.className}`,style:{color:j.color},"data-status":t.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:j.color},"aria-hidden":!0}),j.label]}),t.type==="remote"&&u&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${u}`,title:Oe(u,o),"aria-label":`Auth sync: ${u==="match"?"credentials match":u==="differs"?"credentials differ":"not synced"}`,style:{color:De[u]},children:e.jsx(Q,{size:14})})]})]})]})}),e.jsxs("div",{className:"node-card__body",children:[t.type==="remote"&&t.url&&e.jsx("div",{className:"node-card__url",title:t.url,children:Fe(t.url)}),e.jsxs("div",{className:"node-card__metrics",children:[e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Projects"}),e.jsx("span",{className:"node-card__metric-value",children:C})]}),e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Concurrency"}),e.jsx("span",{className:"node-card__metric-value",children:t.maxConcurrent})]})]}),t.type==="remote"&&c&&e.jsxs("div",{className:"node-card__sync","data-sync-state":c.syncState,"data-testid":"node-card-sync",children:[e.jsx("span",{className:"node-card__sync-dot",style:{backgroundColor:ae(c.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:te(c.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:S,disabled:m,"aria-label":"Run node health check",title:"Health Check",children:[e.jsx(T,{size:14}),e.jsx("span",{children:"Health"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:A,disabled:m,"aria-label":"Edit node",title:"Edit",children:[e.jsx(_e,{size:14}),e.jsx("span",{children:"Edit"})]}),e.jsxs("button",{className:`btn btn-sm node-card__action node-card__action--remove ${y?"btn-danger is-armed":""}`,type:"button",onClick:a,disabled:m,"aria-label":y?"Confirm remove node":"Remove node",title:y?"Confirm remove":"Remove",children:[e.jsx(Ne,{size:14}),e.jsx("span",{children:y?"Confirm":"Remove"})]})]})]})}const Ue=n.memo(Ke,Ie),O={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--triage)",error:"var(--color-error)"},D=28,W=12,Ve=300,Be=120;function He({nodes:t,className:l}){const s=n.useMemo(()=>t.find(o=>o.type==="local")??t[0],[t]),r=n.useMemo(()=>t.filter(o=>o.type==="remote"),[t]),f=n.useMemo(()=>{const o=Ve,y=Math.max(0,r.length-4)*20;return o+y},[r.length]),m=f/2,c=f/2,u=n.useMemo(()=>{if(r.length===0)return[];const o=Math.min(Be,f/2-D-10),y=2*Math.PI/r.length,g=-Math.PI/2;return r.map((j,C)=>{const _=g+C*y;return{node:j,x:m+o*Math.cos(_),y:c+o*Math.sin(_)}})},[r,f,m,c]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${l??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:"No nodes to display"})})}):e.jsxs("div",{className:`mesh-topology ${l??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${f} ${f}`,preserveAspectRatio:"xMidYMid meet","aria-label":"Node mesh topology visualization",children:[u.map(o=>e.jsx("line",{className:"mesh-topology__link",x1:m,y1:c,x2:o.x,y2:o.y},`link-${o.node.id}`)),s&&e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${m}, ${c})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:D,fill:O[s.status],"aria-label":`${s.name} (${s.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:D+W,textAnchor:"middle",children:s.name.length>12?`${s.name.slice(0,10)}…`:s.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-D-10})`,children:[e.jsx("circle",{className:"mesh-topology__node-type-badge",r:"8"}),e.jsx("text",{className:"mesh-topology__node-type-text",textAnchor:"middle",dominantBaseline:"middle",children:s.type==="local"?"L":"R"})]})]}),u.map(o=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${o.x}, ${o.y})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:D,fill:O[o.node.status],"aria-label":`${o.node.name} (${o.node.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:D+W,textAnchor:"middle",children:o.node.name.length>12?`${o.node.name.slice(0,10)}…`:o.node.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-D-10})`,children:[e.jsx("circle",{className:"mesh-topology__node-type-badge",r:"8"}),e.jsx("text",{className:"mesh-topology__node-type-text",textAnchor:"middle",dominantBaseline:"middle",children:o.node.type==="local"?"L":"R"})]})]},o.node.id))]}),e.jsxs("div",{className:"mesh-topology__legend",children:[e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:O.online}}),e.jsx("span",{children:"Online"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:O.offline}}),e.jsx("span",{children:"Offline"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:O.connecting}}),e.jsx("span",{children:"Connecting"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:O.error}}),e.jsx("span",{children:"Error"})]})]}),e.jsx("p",{className:"mesh-topology__notice",children:"Peer-to-peer discovery data unavailable."})]})}const qe=n.memo(He),q=1,X=10;function Xe(t){const l={};return t.name.trim()||(l.name="Name is required"),t.type==="remote"&&!t.url?.trim()&&(l.url="URL is required for remote nodes"),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<q||t.maxConcurrent>X)&&(l.maxConcurrent=`Concurrency must be between ${q} and ${X}`),l}function Je({isOpen:t,onClose:l,onSubmit:s,addToast:r}){const[f,m]=n.useState(""),[c,u]=n.useState("local"),[o,y]=n.useState(""),[g,j]=n.useState(""),[C,_]=n.useState(2),[S,A]=n.useState({}),[a,i]=n.useState(!1),x=n.useCallback(()=>{m(""),u("local"),y(""),j(""),_(2),A({}),i(!1)},[]),b=n.useCallback(()=>{a||(x(),l())},[a,l,x]);n.useEffect(()=>{if(!t){x();return}const v=h=>{h.key==="Escape"&&(h.preventDefault(),b())};return document.addEventListener("keydown",v),()=>{document.removeEventListener("keydown",v)}},[b,t,x]);const w=n.useMemo(()=>({name:f.trim(),type:c,url:c==="remote"&&o.trim()||void 0,apiKey:c==="remote"&&g||void 0,maxConcurrent:C}),[g,C,f,c,o]),$=n.useCallback(async()=>{if(a)return;const v=Xe(w);if(A(v),!(Object.keys(v).length>0)){i(!0);try{await s(w),r(`Node "${w.name}" registered`,"success"),b()}catch(h){const d=h instanceof Error?h.message:"Failed to register node";r(d,"error")}finally{i(!1)}}},[r,b,w,a,s]);return t?e.jsx("div",{className:"modal-overlay open",onClick:b,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:v=>v.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Add Node",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Add Node"}),e.jsx("button",{className:"modal-close",onClick:b,disabled:a,"aria-label":"Close add node modal",children:"×"})]}),e.jsxs("div",{className:"modal-body add-node-modal__body",children:[e.jsx("p",{className:"add-node-modal__description",children:"Register a node to distribute task execution across machines."}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{className:"input",type:"text",value:f,onChange:v=>m(v.target.value),placeholder:"Build Machine",disabled:a,"aria-invalid":!!S.name,autoFocus:!0}),S.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${c==="local"?"active":""}`,"data-type":"local",onClick:()=>u("local"),disabled:a,"aria-pressed":c==="local",children:"Local"}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${c==="remote"?"active":""}`,"data-type":"remote",onClick:()=>u("remote"),disabled:a,"aria-pressed":c==="remote",children:"Remote"})]}),e.jsxs("div",{className:"add-node-modal__remote-fields","data-testid":"remote-fields-container","data-visible":c==="remote",children:[e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"URL"}),e.jsx("input",{className:"input",type:"text",value:o,onChange:v=>y(v.target.value),placeholder:"https://node.example.com",disabled:a,"aria-invalid":!!S.url}),S.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:g,onChange:v=>j(v.target.value),placeholder:"Optional",disabled:a})]})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),e.jsx("input",{className:"input",type:"number",min:q,max:X,value:C,onChange:v=>_(Number(v.target.value)),disabled:a,"aria-invalid":!!S.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:"Max simultaneous task agents (1–10)"}),S.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.maxConcurrent})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:b,disabled:a,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:$,disabled:a,children:a?"Adding...":"Add Node"})]})]})}):null}function Ge({nodeId:t,entries:l,loading:s=!1,singleNode:r=!1}){const[f,m]=n.useState(!1),[c,u]=n.useState("all"),[o,y]=n.useState("all"),g=n.useCallback(()=>{m(a=>!a)},[]),j=n.useMemo(()=>{const a=new Set;for(const i of l)a.add(i.nodeName);return Array.from(a).sort()},[l]),C=n.useMemo(()=>{let a=[...l];return c!=="all"&&(a=a.filter(i=>i.direction===c)),!r&&o!=="all"&&(a=a.filter(i=>i.nodeName===o)),a.sort((i,x)=>{const b=new Date(i.timestamp).getTime();return new Date(x.timestamp).getTime()-b}),a},[l,c,o,r]),_=n.useCallback(a=>new Date(a).toLocaleString(),[]),S=n.useCallback(a=>{switch(a){case"success":return"settings-sync-log__badge--success";case"conflict":return"settings-sync-log__badge--conflict";case"error":return"settings-sync-log__badge--error";default:return""}},[]),A=n.useCallback(a=>{switch(a){case"success":return"Success";case"conflict":return"Conflict";case"error":return"Error";default:return a}},[]);return e.jsxs("div",{className:"settings-sync-log",children:[e.jsxs("button",{className:"settings-sync-log__header",type:"button",onClick:g,"aria-expanded":f,"data-testid":"settings-sync-log-header",children:[e.jsx(be,{size:16,className:`settings-sync-log__chevron ${f?"settings-sync-log__chevron--expanded":""}`}),e.jsxs("span",{children:[l.length," ",l.length===1?"entry":"entries"]})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"settings-sync-log__filters",children:[e.jsxs("label",{children:["Direction:",e.jsxs("select",{value:c,onChange:a=>u(a.target.value),children:[e.jsx("option",{value:"all",children:"All"}),e.jsx("option",{value:"push",children:"Push"}),e.jsx("option",{value:"pull",children:"Pull"})]})]}),!r&&e.jsxs("label",{children:["Node:",e.jsxs("select",{value:o,onChange:a=>y(a.target.value),children:[e.jsx("option",{value:"all",children:"All Nodes"}),j.map(a=>e.jsx("option",{value:a,children:a},a))]})]})]}),s&&l.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"Loading..."}):C.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"No sync history available"}):e.jsx("div",{className:"settings-sync-log__list",children:C.map(a=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:_(a.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:a.direction==="push"?e.jsx(se,{size:14,"data-testid":"upload-icon"}):e.jsx(ee,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${S(a.result)}`,children:A(a.result)}),!r&&e.jsx("span",{className:"settings-sync-log__entry-node",children:a.nodeName}),a.details&&e.jsx("span",{className:"settings-sync-log__entry-details",title:a.details,children:a.details})]},a.id))})]})]})}function We(t,l){const s=typeof t=="string"?t:JSON.stringify(t,null,2),r=typeof l=="string"?l:JSON.stringify(l,null,2);if(s===r)return s;const f=s.split(`
|
|
11
|
+
*/const Ee=[["path",{d:"M12 20h.01",key:"zekei9"}],["path",{d:"M2 8.82a15 15 0 0 1 20 0",key:"dnpr2z"}],["path",{d:"M5 12.859a10 10 0 0 1 14 0",key:"1x1e6c"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0",key:"1bycff"}]],Re=Y("wifi",Ee);function U(t){const{lastSyncAt:l,remoteReachable:s,diff:r}=t,f=r.global.length+r.project.length;return l===null?{syncState:"never-synced",lastSyncAt:l,diffCount:0}:s?f>0?{syncState:"diff",lastSyncAt:l,diffCount:f}:{syncState:"synced",lastSyncAt:l,diffCount:0}:{syncState:"error",lastSyncAt:l,diffCount:f}}function te(t){if(t===null)return"Never synced";const l=new Date(t);if(Number.isNaN(l.getTime()))return"Never synced";const r=Date.now()-l.getTime(),f=Math.floor(r/1e3),m=Math.floor(f/60),c=Math.floor(m/60),u=Math.floor(c/24);return m<1?"Synced just now":m<60?`Synced ${m}m ago`:c<24?`Synced ${c}h ago`:`Synced ${u}d ago`}function ae(t){switch(t){case"synced":return"var(--color-success)";case"pending":return"var(--color-warning)";case"diff":return"var(--color-warning)";case"error":return"var(--color-error)";case"never-synced":return"var(--text-muted)"}}const Pe=3e4;function $e(){const[t,l]=n.useState({}),[s,r]=n.useState(!1),[f,m]=n.useState({}),[c,u]=n.useState(null),o=n.useRef(new Set),y=n.useRef(!1),g=n.useRef(null),j=n.useRef(null),C=n.useCallback(async(h,d)=>{try{const p=await xe(h);l(z=>({...z,[h]:p})),u(null)}catch(p){console.error(`Failed to fetch sync status for node ${h}:`,p),u(p instanceof Error?p.message:"Failed to fetch sync status")}},[]),_=n.useCallback(async()=>{const h=Array.from(o.current);if(h.length===0)return;g.current&&g.current.abort(),g.current=new AbortController;const d=!y.current;d&&r(!0),u(null);try{const p=await Promise.allSettled(h.map(L=>C(L,d)));y.current=!0,p.filter(L=>L.status==="rejected").length>0&&u("Some sync status requests failed")}catch(p){if(p instanceof Error&&p.name==="AbortError")return;u(p instanceof Error?p.message:"Failed to fetch sync status"),y.current=!0}finally{r(!1)}},[C]),S=n.useCallback(()=>{j.current&&clearInterval(j.current),j.current=setInterval(()=>{_()},Pe)},[_]),A=n.useCallback(()=>{j.current&&(clearInterval(j.current),j.current=null)},[]);n.useEffect(()=>(_(),S(),()=>{A(),g.current&&g.current.abort()}),[_,S,A]);const a=n.useCallback(h=>{o.current.has(h)||(o.current.add(h),C(h,!y.current))},[C]),i=n.useCallback(h=>{o.current.delete(h),l(d=>{const p={...d};return delete p[h],p}),o.current.size===0&&A()},[A]),x=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{const d=await ge(h);return C(h,!1),!d.success&&d.error&&u(d.error),d}catch(d){const p=d instanceof Error?d.message:"Push settings failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[C]),b=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{const d=await pe(h);return C(h,!1),!d.success&&d.error&&u(d.error),d}catch(d){const p=d instanceof Error?d.message:"Pull settings failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[C]),w=n.useCallback(async h=>{m(d=>({...d,[h]:!0})),u(null);try{return await je(h)}catch(d){const p=d instanceof Error?d.message:"Auth sync failed";throw u(p),d}finally{m(d=>{const p={...d};return delete p[h],p})}},[]),$=n.useCallback(h=>t[h]?.authMatch,[t]),v=n.useCallback(h=>t[h]?.authDiff,[t]);return{syncStatusMap:t,loading:s,actionLoading:f,error:c,refresh:_,trackNode:a,untrackNode:i,pushSettings:x,pullSettings:b,syncAuth:w,getAuthSyncState:$,getAuthProviders:v}}function Le(t,l){return l.type==="remote"?t.nodeId===l.id:t.nodeId===l.id||t.nodeId===void 0||t.nodeId===null}function ne(t,l){return t.filter(s=>Le(s,l))}function H(t,l){return ne(t,l).length}const ze={online:{label:"Online",color:"var(--color-success)",className:"node-card__status--online"},offline:{label:"Offline",color:"var(--color-error)",className:"node-card__status--offline"},connecting:{label:"Connecting",color:"var(--color-warning)",className:"node-card__status--connecting"},error:{label:"Error",color:"var(--color-error)",className:"node-card__status--error"}},De={match:"var(--color-success)",differs:"var(--color-warning)","not-synced":"var(--text-muted)"};function Oe(t,l){if(t==="match")return"Auth credentials match";if(t==="not-synced")return"Auth not synced";if(l&&Object.keys(l).length>0){const s=Object.entries(l).filter(([,r])=>r==="differs").map(([r])=>r);if(s.length>0)return`Auth credentials differ: ${s.join(", ")}`}return"Auth credentials differ"}function Fe(t,l=42){return t.length<=l?t:`${t.slice(0,l-3)}...`}function Ie(t,l){const s=t.node,r=l.node;if(s.id!==r.id||s.name!==r.name||s.type!==r.type||s.url!==r.url||s.status!==r.status||s.maxConcurrent!==r.maxConcurrent||s.updatedAt!==r.updatedAt||t.isLoading!==l.isLoading)return!1;const f=t.syncStatus,m=l.syncStatus;if(!(!f&&!m)){if(!f||!m)return!1;if(f.syncState!==m.syncState||f.lastSyncAt!==m.lastSyncAt||f.diffCount!==m.diffCount)return!1}if(t.authSyncState!==l.authSyncState)return!1;const c=t.authSyncProviders,u=l.authSyncProviders;if(c!==u){if(!c||!u)return!1;{const g=Object.keys(c),j=Object.keys(u);if(g.length!==j.length||g.some(C=>c[C]!==u[C]))return!1}}const o=H(t.projects,s),y=H(l.projects,r);return o===y}function Ke({node:t,projects:l,onHealthCheck:s,onEdit:r,onRemove:f,isLoading:m=!1,syncStatus:c,authSyncState:u,authSyncProviders:o}){const[y,g]=n.useState(!1),j=ze[t.status],C=n.useMemo(()=>H(l,t),[l,t]),_=n.useCallback(()=>{r(t)},[r,t]),S=n.useCallback(x=>{x.stopPropagation(),s(t.id)},[s,t.id]),A=n.useCallback(x=>{x.stopPropagation(),r(t)},[r,t]),a=n.useCallback(x=>{if(x.stopPropagation(),!y){g(!0);return}f(t.id),g(!1)},[y,f,t.id]),i=n.useCallback(x=>{(x.key==="Enter"||x.key===" ")&&(x.preventDefault(),r(t))},[r,t]);return e.jsxs("article",{className:`node-card ${m?"node-card--loading":""}`,"data-node-id":t.id,role:"button",tabIndex:0,onClick:_,onKeyDown:i,children:[e.jsx("header",{className:"node-card__header",children:e.jsxs("div",{className:"node-card__title-wrap",children:[e.jsx("div",{className:"node-card__icon",children:e.jsx(Z,{size:18})}),e.jsxs("div",{children:[e.jsx("h3",{className:"node-card__name",title:t.name,children:t.name}),e.jsxs("div",{className:"node-card__meta-row",children:[e.jsx("span",{className:"node-card__type-badge",children:t.type==="local"?"Local":"Remote"}),e.jsxs("span",{className:`node-card__status ${j.className}`,style:{color:j.color},"data-status":t.status,children:[e.jsx("span",{className:"node-card__status-indicator",style:{backgroundColor:j.color},"aria-hidden":!0}),j.label]}),t.type==="remote"&&u&&e.jsx("span",{className:`node-card__auth-indicator node-card__auth-indicator--${u}`,title:Oe(u,o),"aria-label":`Auth sync: ${u==="match"?"credentials match":u==="differs"?"credentials differ":"not synced"}`,style:{color:De[u]},children:e.jsx(Q,{size:14})})]})]})]})}),e.jsxs("div",{className:"node-card__body",children:[t.type==="remote"&&t.url&&e.jsx("div",{className:"node-card__url",title:t.url,children:Fe(t.url)}),e.jsxs("div",{className:"node-card__metrics",children:[e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Projects"}),e.jsx("span",{className:"node-card__metric-value",children:C})]}),e.jsxs("div",{className:"node-card__metric",children:[e.jsx("span",{className:"node-card__metric-label",children:"Concurrency"}),e.jsx("span",{className:"node-card__metric-value",children:t.maxConcurrent})]})]}),t.type==="remote"&&c&&e.jsxs("div",{className:"node-card__sync","data-sync-state":c.syncState,"data-testid":"node-card-sync",children:[e.jsx("span",{className:"node-card__sync-dot",style:{backgroundColor:ae(c.syncState)},"aria-hidden":!0}),e.jsx("span",{className:"node-card__sync-time",children:te(c.lastSyncAt)})]})]}),e.jsxs("footer",{className:"node-card__actions",children:[e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:S,disabled:m,"aria-label":"Run node health check",title:"Health Check",children:[e.jsx(T,{size:14}),e.jsx("span",{children:"Health"})]}),e.jsxs("button",{className:"btn btn-sm node-card__action",type:"button",onClick:A,disabled:m,"aria-label":"Edit node",title:"Edit",children:[e.jsx(_e,{size:14}),e.jsx("span",{children:"Edit"})]}),e.jsxs("button",{className:`btn btn-sm node-card__action node-card__action--remove ${y?"btn-danger is-armed":""}`,type:"button",onClick:a,disabled:m,"aria-label":y?"Confirm remove node":"Remove node",title:y?"Confirm remove":"Remove",children:[e.jsx(Ne,{size:14}),e.jsx("span",{children:y?"Confirm":"Remove"})]})]})]})}const Ue=n.memo(Ke,Ie),O={online:"var(--success, var(--color-success))",offline:"var(--text-dim)",connecting:"var(--triage)",error:"var(--color-error)"},D=28,W=12,Be=300,Ve=120;function He({nodes:t,className:l}){const s=n.useMemo(()=>t.find(o=>o.type==="local")??t[0],[t]),r=n.useMemo(()=>t.filter(o=>o.type==="remote"),[t]),f=n.useMemo(()=>{const o=Be,y=Math.max(0,r.length-4)*20;return o+y},[r.length]),m=f/2,c=f/2,u=n.useMemo(()=>{if(r.length===0)return[];const o=Math.min(Ve,f/2-D-10),y=2*Math.PI/r.length,g=-Math.PI/2;return r.map((j,C)=>{const _=g+C*y;return{node:j,x:m+o*Math.cos(_),y:c+o*Math.sin(_)}})},[r,f,m,c]);return t.length===0?e.jsx("div",{className:`mesh-topology mesh-topology--empty ${l??""}`,children:e.jsx("div",{className:"mesh-topology__empty-state",children:e.jsx("p",{children:"No nodes to display"})})}):e.jsxs("div",{className:`mesh-topology ${l??""}`,children:[e.jsxs("svg",{className:"mesh-topology__svg",viewBox:`0 0 ${f} ${f}`,preserveAspectRatio:"xMidYMid meet","aria-label":"Node mesh topology visualization",children:[u.map(o=>e.jsx("line",{className:"mesh-topology__link",x1:m,y1:c,x2:o.x,y2:o.y},`link-${o.node.id}`)),s&&e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${m}, ${c})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:D,fill:O[s.status],"aria-label":`${s.name} (${s.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:D+W,textAnchor:"middle",children:s.name.length>12?`${s.name.slice(0,10)}…`:s.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-D-10})`,children:[e.jsx("circle",{className:"mesh-topology__node-type-badge",r:"8"}),e.jsx("text",{className:"mesh-topology__node-type-text",textAnchor:"middle",dominantBaseline:"middle",children:s.type==="local"?"L":"R"})]})]}),u.map(o=>e.jsxs("g",{className:"mesh-topology__node",transform:`translate(${o.x}, ${o.y})`,children:[e.jsx("circle",{className:"mesh-topology__node-circle",r:D,fill:O[o.node.status],"aria-label":`${o.node.name} (${o.node.status})`}),e.jsx("text",{className:"mesh-topology__node-label",y:D+W,textAnchor:"middle",children:o.node.name.length>12?`${o.node.name.slice(0,10)}…`:o.node.name}),e.jsxs("g",{className:"mesh-topology__node-type",transform:`translate(0 ${-D-10})`,children:[e.jsx("circle",{className:"mesh-topology__node-type-badge",r:"8"}),e.jsx("text",{className:"mesh-topology__node-type-text",textAnchor:"middle",dominantBaseline:"middle",children:o.node.type==="local"?"L":"R"})]})]},o.node.id))]}),e.jsxs("div",{className:"mesh-topology__legend",children:[e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:O.online}}),e.jsx("span",{children:"Online"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:O.offline}}),e.jsx("span",{children:"Offline"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:O.connecting}}),e.jsx("span",{children:"Connecting"})]}),e.jsxs("div",{className:"mesh-topology__legend-item",children:[e.jsx("span",{className:"mesh-topology__legend-dot",style:{background:O.error}}),e.jsx("span",{children:"Error"})]})]}),e.jsx("p",{className:"mesh-topology__notice",children:"Peer-to-peer discovery data unavailable."})]})}const qe=n.memo(He),q=1,X=10;function Xe(t){const l={};return t.name.trim()||(l.name="Name is required"),t.type==="remote"&&!t.url?.trim()&&(l.url="URL is required for remote nodes"),(!Number.isFinite(t.maxConcurrent)||t.maxConcurrent<q||t.maxConcurrent>X)&&(l.maxConcurrent=`Concurrency must be between ${q} and ${X}`),l}function Je({isOpen:t,onClose:l,onSubmit:s,addToast:r}){const[f,m]=n.useState(""),[c,u]=n.useState("local"),[o,y]=n.useState(""),[g,j]=n.useState(""),[C,_]=n.useState(2),[S,A]=n.useState({}),[a,i]=n.useState(!1),x=n.useCallback(()=>{m(""),u("local"),y(""),j(""),_(2),A({}),i(!1)},[]),b=n.useCallback(()=>{a||(x(),l())},[a,l,x]);n.useEffect(()=>{if(!t){x();return}const v=h=>{h.key==="Escape"&&(h.preventDefault(),b())};return document.addEventListener("keydown",v),()=>{document.removeEventListener("keydown",v)}},[b,t,x]);const w=n.useMemo(()=>({name:f.trim(),type:c,url:c==="remote"&&o.trim()||void 0,apiKey:c==="remote"&&g||void 0,maxConcurrent:C}),[g,C,f,c,o]),$=n.useCallback(async()=>{if(a)return;const v=Xe(w);if(A(v),!(Object.keys(v).length>0)){i(!0);try{await s(w),r(`Node "${w.name}" registered`,"success"),b()}catch(h){const d=h instanceof Error?h.message:"Failed to register node";r(d,"error")}finally{i(!1)}}},[r,b,w,a,s]);return t?e.jsx("div",{className:"modal-overlay open",onClick:b,children:e.jsxs("div",{className:"modal modal-md add-node-modal",onClick:v=>v.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Add Node",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Add Node"}),e.jsx("button",{className:"modal-close",onClick:b,disabled:a,"aria-label":"Close add node modal",children:"×"})]}),e.jsxs("div",{className:"modal-body add-node-modal__body",children:[e.jsx("p",{className:"add-node-modal__description",children:"Register a node to distribute task execution across machines."}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{className:"input",type:"text",value:f,onChange:v=>m(v.target.value),placeholder:"Build Machine",disabled:a,"aria-invalid":!!S.name,autoFocus:!0}),S.name&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.name})]}),e.jsxs("div",{className:"add-node-modal__type-toggle",children:[e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${c==="local"?"active":""}`,"data-type":"local",onClick:()=>u("local"),disabled:a,"aria-pressed":c==="local",children:"Local"}),e.jsx("button",{type:"button",className:`add-node-modal__type-btn ${c==="remote"?"active":""}`,"data-type":"remote",onClick:()=>u("remote"),disabled:a,"aria-pressed":c==="remote",children:"Remote"})]}),e.jsxs("div",{className:"add-node-modal__remote-fields","data-testid":"remote-fields-container","data-visible":c==="remote",children:[e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"URL"}),e.jsx("input",{className:"input",type:"text",value:o,onChange:v=>y(v.target.value),placeholder:"https://node.example.com",disabled:a,"aria-invalid":!!S.url}),S.url&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.url})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"API Key"}),e.jsx("input",{className:"input",type:"password",value:g,onChange:v=>j(v.target.value),placeholder:"Optional",disabled:a})]})]}),e.jsxs("label",{className:"add-node-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),e.jsx("input",{className:"input",type:"number",min:q,max:X,value:C,onChange:v=>_(Number(v.target.value)),disabled:a,"aria-invalid":!!S.maxConcurrent}),e.jsx("span",{className:"add-node-modal__hint",children:"Max simultaneous task agents (1–10)"}),S.maxConcurrent&&e.jsx("span",{className:"form-error add-node-modal__error",children:S.maxConcurrent})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:b,disabled:a,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm","data-testid":"add-node-submit",onClick:$,disabled:a,children:a?"Adding...":"Add Node"})]})]})}):null}function Ge({nodeId:t,entries:l,loading:s=!1,singleNode:r=!1}){const[f,m]=n.useState(!1),[c,u]=n.useState("all"),[o,y]=n.useState("all"),g=n.useCallback(()=>{m(a=>!a)},[]),j=n.useMemo(()=>{const a=new Set;for(const i of l)a.add(i.nodeName);return Array.from(a).sort()},[l]),C=n.useMemo(()=>{let a=[...l];return c!=="all"&&(a=a.filter(i=>i.direction===c)),!r&&o!=="all"&&(a=a.filter(i=>i.nodeName===o)),a.sort((i,x)=>{const b=new Date(i.timestamp).getTime();return new Date(x.timestamp).getTime()-b}),a},[l,c,o,r]),_=n.useCallback(a=>new Date(a).toLocaleString(),[]),S=n.useCallback(a=>{switch(a){case"success":return"settings-sync-log__badge--success";case"conflict":return"settings-sync-log__badge--conflict";case"error":return"settings-sync-log__badge--error";default:return""}},[]),A=n.useCallback(a=>{switch(a){case"success":return"Success";case"conflict":return"Conflict";case"error":return"Error";default:return a}},[]);return e.jsxs("div",{className:"settings-sync-log",children:[e.jsxs("button",{className:"settings-sync-log__header",type:"button",onClick:g,"aria-expanded":f,"data-testid":"settings-sync-log-header",children:[e.jsx(be,{size:16,className:`settings-sync-log__chevron ${f?"settings-sync-log__chevron--expanded":""}`}),e.jsxs("span",{children:[l.length," ",l.length===1?"entry":"entries"]})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"settings-sync-log__filters",children:[e.jsxs("label",{children:["Direction:",e.jsxs("select",{value:c,onChange:a=>u(a.target.value),children:[e.jsx("option",{value:"all",children:"All"}),e.jsx("option",{value:"push",children:"Push"}),e.jsx("option",{value:"pull",children:"Pull"})]})]}),!r&&e.jsxs("label",{children:["Node:",e.jsxs("select",{value:o,onChange:a=>y(a.target.value),children:[e.jsx("option",{value:"all",children:"All Nodes"}),j.map(a=>e.jsx("option",{value:a,children:a},a))]})]})]}),s&&l.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"Loading..."}):C.length===0?e.jsx("div",{className:"settings-sync-log__empty",children:"No sync history available"}):e.jsx("div",{className:"settings-sync-log__list",children:C.map(a=>e.jsxs("div",{className:"settings-sync-log__entry",children:[e.jsx("span",{className:"settings-sync-log__entry-timestamp",children:_(a.timestamp)}),e.jsx("span",{className:"settings-sync-log__entry-direction",children:a.direction==="push"?e.jsx(se,{size:14,"data-testid":"upload-icon"}):e.jsx(ee,{size:14,"data-testid":"download-icon"})}),e.jsx("span",{className:`settings-sync-log__entry-result ${S(a.result)}`,children:A(a.result)}),!r&&e.jsx("span",{className:"settings-sync-log__entry-node",children:a.nodeName}),a.details&&e.jsx("span",{className:"settings-sync-log__entry-details",title:a.details,children:a.details})]},a.id))})]})]})}function We(t,l){const s=typeof t=="string"?t:JSON.stringify(t,null,2),r=typeof l=="string"?l:JSON.stringify(l,null,2);if(s===r)return s;const f=s.split(`
|
|
12
12
|
`),m=r.split(`
|
|
13
13
|
`),c=[],u=Math.max(f.length,m.length);for(let o=0;o<u;o++){const y=f[o],g=m[o];y!==void 0&&y!==g&&c.push(`- ${y}`),g!==void 0&&g!==y&&c.push(`+ ${g}`),y!==void 0&&y===g&&c.push(` ${y}`)}return c.join(`
|
|
14
|
-
`)}function Ye({isOpen:t,onClose:l,onResolve:s,conflicts:r,localNodeName:f,remoteNodeName:m,addToast:c}){const[u,o]=n.useState({}),[y,g]=n.useState(!1);n.useEffect(()=>{const a={};for(const i of r)u[i.key]||(a[i.key]={resolution:"local"});Object.keys(a).length>0&&o(i=>({...i,...a}))},[r,u]),n.useEffect(()=>{if(!t)return;const a=i=>{i.key==="Escape"&&(i.preventDefault(),l())};return document.addEventListener("keydown",a),()=>document.removeEventListener("keydown",a)},[t,l]);const j=n.useCallback((a,i)=>{o(x=>{const b=x[a]??{};return i==="manual"?{...x,[a]:{resolution:"manual",manualValue:b.manualValue??JSON.stringify(r.find(w=>w.key===a)?.localValue??null,null,2)}}:{...x,[a]:{resolution:i}}})},[r]),C=n.useCallback((a,i)=>{o(x=>({...x,[a]:{...x[a],resolution:"manual",manualValue:i}}))},[]),_=n.useCallback(a=>{const i={};for(const x of r)i[x.key]={resolution:a};o(i)},[r]),S=n.useCallback(async()=>{g(!0);try{const a=r.map(i=>{const x=u[i.key]??{resolution:"local"};let b;switch(x.resolution){case"remote":b=i.remoteValue;break;case"manual":try{b=JSON.parse(x.manualValue??"null")}catch{b=x.manualValue??null}break;case"local":default:b=i.localValue;break}return{key:i.key,value:b}});await s(a),c("Settings conflicts resolved successfully","success"),l()}catch(a){const i=a instanceof Error?a.message:"Failed to resolve conflicts";c(i,"error")}finally{g(!1)}},[c,r,l,s,u]),A=n.useMemo(()=>{const a={};for(const i of r)a[i.key]=We(i.localValue,i.remoteValue);return a},[r]);return!t||r.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:l,children:e.jsxs("div",{className:"modal modal-lg settings-sync-conflict-modal",onClick:a=>a.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Resolve Settings Conflicts",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Resolve Settings Conflicts"}),e.jsx("button",{className:"modal-close",onClick:l,"aria-label":"Close conflict modal",children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:r.map(a=>{const i=u[a.key]??{resolution:"local"},x=A[a.key];return e.jsxs("div",{className:"settings-sync-conflict-modal__conflict-item",children:[e.jsx("div",{className:"settings-sync-conflict-modal__key",children:a.key}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-panel",children:[e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:f}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:x})})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:m}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:x})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="local",onChange:()=>j(a.key,"local")}),"Keep Local"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="remote",onChange:()=>j(a.key,"remote")}),"Keep Remote"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="manual",onChange:()=>j(a.key,"manual")}),"Merge Manually"]})]}),i.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:i.manualValue??"",onChange:b=>C(a.key,b.target.value),placeholder:"Enter JSON value..."})]},a.key)})}),e.jsxs("div",{className:"settings-sync-conflict-modal__bulk-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:()=>_("local"),type:"button",children:"Resolve All: Keep Local"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>_("remote"),type:"button",children:"Resolve All: Keep Remote"})]})]}),e.jsxs("div",{className:"modal-actions settings-sync-conflict-modal__footer",children:[e.jsx("button",{className:"btn btn-sm",onClick:l,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:S,disabled:y,children:y?"Resolving...":"Confirm"})]})]})})}function V(t){if(!t)return"—";const l=new Date(t);return Number.isNaN(l.getTime())?"—":l.toLocaleString()}function Ze({isOpen:t,onClose:l,node:s,projects:r,onUpdate:f,onHealthCheck:m,addToast:c,syncStatus:u,onPushSettings:o,onPullSettings:y,onSyncAuth:g,syncHistory:j=[],onResolveConflicts:C}){const _=n.useRef(!0),[S,A]=n.useState(!1),[a,i]=n.useState(""),[x,b]=n.useState(""),[w,$]=n.useState(""),[v,h]=n.useState(2),[d,p]=n.useState(!1),[z,L]=n.useState(!1),[k,M]=n.useState(!1),[P,F]=n.useState(!1),[I,E]=n.useState(null),[le,re]=n.useState(!1),[ce]=n.useState([]);n.useEffect(()=>(_.current=!0,()=>{_.current=!1}),[]),n.useEffect(()=>{if(!s||!t){A(!1);return}i(s.name),b(s.url??""),$(s.apiKey??""),h(s.maxConcurrent),A(!1)},[t,s]),n.useEffect(()=>{if(!t)return;const N=R=>{R.key==="Escape"&&(R.preventDefault(),l())};return document.addEventListener("keydown",N),()=>document.removeEventListener("keydown",N)},[t,l]);const K=n.useMemo(()=>s?ne(r,s):[],[s,r]),oe=n.useCallback(async()=>{if(s)try{if(await m(s.id),!_.current)return;c(`Health check completed for ${s.name}`,"success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Health check failed";c(R,"error")}},[c,s,m]),ie=n.useCallback(async()=>{if(!(!s||!o)){E(null),L(!0);try{if(await o(s.id),!_.current)return;c("Settings pushed successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Push settings failed";E(R),c(R,"error")}finally{_.current&&L(!1)}}},[c,s,o]),de=n.useCallback(async()=>{if(!(!s||!y)){E(null),M(!0);try{if(await y(s.id),!_.current)return;c("Settings pulled successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Pull settings failed";E(R),c(R,"error")}finally{_.current&&M(!1)}}},[c,s,y]),ue=n.useCallback(async()=>{if(!(!s||!g)){E(null),F(!0);try{if(await g(s.id),!_.current)return;c("Auth credentials synced successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Auth sync failed";E(R),c(R,"error")}finally{_.current&&F(!1)}}},[c,s,g]),me=n.useCallback(()=>{E(null)},[]),he=n.useCallback(async()=>{if(!s||d)return;const N=a.trim();if(!N){c("Name is required","error");return}if(s.type==="remote"&&!x.trim()){c("URL is required for remote nodes","error");return}if(!Number.isFinite(v)||v<1){c("Concurrency must be at least 1","error");return}p(!0);try{await f(s.id,{name:N,url:s.type==="remote"&&x.trim()||void 0,apiKey:s.type==="remote"&&w||void 0,maxConcurrent:v}),c(`Updated ${N}`,"success"),A(!1)}catch(R){const ye=R instanceof Error?R.message:"Failed to update node";c(ye,"error")}finally{p(!1)}},[c,w,d,v,a,s,f,x]),fe=n.useCallback(()=>{s&&(i(s.name),b(s.url??""),$(s.apiKey??""),h(s.maxConcurrent),A(!1))},[s]);return!t||!s?null:e.jsxs("div",{className:"modal-overlay open",onClick:l,children:[e.jsxs("div",{className:"modal modal-lg node-detail-modal",onClick:N=>N.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":`Node details for ${s.name}`,children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Node Details"}),e.jsx("button",{className:"modal-close",onClick:l,"aria-label":"Close node detail modal",children:"×"})]}),e.jsxs("div",{className:"modal-body node-detail-modal__body",children:[e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("div",{className:"node-detail-modal__section-header",children:[e.jsx("h4",{children:"Overview"}),!S&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>A(!0),children:[e.jsx(ve,{size:14}),"Edit"]})]}),e.jsxs("div",{className:"node-detail-modal__grid",children:[e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Name"}),S?e.jsx("input",{className:"input",value:a,onChange:N=>i(N.target.value),disabled:d}):e.jsx("strong",{children:s.name})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Type"}),e.jsx("strong",{children:s.type==="local"?"Local":"Remote"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Status"}),e.jsx("strong",{children:s.status})]}),e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),S?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:v,onChange:N=>h(Number(N.target.value)),disabled:d}):e.jsx("strong",{children:s.maxConcurrent})]}),s.type==="remote"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"URL"}),S?e.jsx("input",{className:"input",value:x,onChange:N=>b(N.target.value),disabled:d}):e.jsx("strong",{children:s.url??"—"})]}),e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"API Key"}),S?e.jsx("input",{className:"input",type:"password",value:w,onChange:N=>$(N.target.value),placeholder:"Leave blank to keep unchanged",disabled:d}):e.jsx("strong",{children:s.apiKey?"••••••••":"Not configured"})]})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Created"}),e.jsx("strong",{children:V(s.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Updated"}),e.jsx("strong",{children:V(s.updatedAt)})]})]}),S&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:he,disabled:d,children:[e.jsx(Ce,{size:14}),d?"Saving...":"Save"]}),e.jsxs("button",{className:"btn btn-sm",onClick:fe,disabled:d,children:[e.jsx(B,{size:14}),"Cancel"]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[s.type==="local"?"Projects":"Assigned Projects"," (",K.length,")"]}),K.length===0?e.jsx("p",{className:"node-detail-modal__empty",children:s.type==="local"?"No projects are running on this node.":"No projects are assigned to this node."}):e.jsx("ul",{className:"node-detail-modal__project-list",children:K.map(N=>e.jsxs("li",{className:"node-detail-modal__project-item",children:[e.jsx("span",{children:N.name}),e.jsx("code",{children:N.id})]},N.id))})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Health"}),e.jsxs("div",{className:"node-detail-modal__health-row",children:[e.jsxs("span",{children:["Status: ",e.jsx("strong",{children:s.status})]}),e.jsxs("span",{children:["Last check: ",e.jsx("strong",{children:V(s.updatedAt)})]})]})]}),s.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Settings Sync"}),u&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:"node-detail-modal__sync-dot",style:{backgroundColor:ae(u.syncState)},"aria-hidden":!0}),e.jsxs("span",{children:["Last sync:"," ",e.jsx("strong",{children:u.lastSyncAt?te(u.lastSyncAt):"Never synced"})]}),u.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:["Differences: ",e.jsx("strong",{children:u.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:ie,disabled:z||!o,children:[e.jsx(se,{size:14}),z?"Pushing...":"Push Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:de,disabled:k||!y,children:[e.jsx(ee,{size:14}),k?"Pulling...":"Pull Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:ue,disabled:P||!g,children:[e.jsx(Q,{size:14}),P?"Syncing...":"Sync Auth"]})]}),I&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:I}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:me,"aria-label":"Dismiss error",children:e.jsx(B,{size:14})})]})]}),s.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Sync History"}),e.jsx(Ge,{nodeId:s.id,entries:j,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:oe,children:[e.jsx(T,{size:14}),"Health Check"]}),e.jsx("button",{className:"btn btn-sm",onClick:l,children:"Close"})]})]}),s.type==="remote"&&e.jsx(Ye,{isOpen:le,onClose:()=>re(!1),onResolve:C??(async()=>{}),conflicts:ce,localNodeName:"Local",remoteNodeName:s.name,addToast:c})]})}function ts({addToast:t,onClose:l}){const{nodes:s,loading:r,error:f,refresh:m,register:c,update:u,unregister:o,healthCheck:y}=ke(),{projects:g}=Se(),{syncStatusMap:j,pushSettings:C,pullSettings:_,syncAuth:S,trackNode:A,getAuthSyncState:a,getAuthProviders:i}=$e(),[x,b]=n.useState(!1),[w,$]=n.useState(null);n.useEffect(()=>{const k=s.filter(M=>M.type==="remote");for(const M of k)A(M.id)},[s,A]),n.useEffect(()=>{if(!w)return;const k=s.find(M=>M.id===w.id)??null;$(k)},[s,w]);const v=n.useMemo(()=>{const k=s.length,M=s.filter(E=>E.status==="online").length,P=s.filter(E=>E.status==="offline"||E.status==="error").length,F=s.filter(E=>E.type==="remote").length,I=s.filter(E=>E.type==="remote"&&j[E.id]&&U(j[E.id]).syncState==="synced").length;return{total:k,online:M,offline:P,remote:F,synced:I}},[s,j]),h=n.useCallback(async k=>{await c(k)},[c]),d=n.useCallback(async()=>{try{await m()}catch{t("Failed to refresh nodes","error")}},[t,m]),p=n.useCallback(async k=>{try{await y(k),t("Node health check complete","success")}catch(M){const P=M instanceof Error?M.message:"Health check failed";t(P,"error")}},[t,y]),z=n.useCallback(async k=>{try{await o(k),t("Node removed","success"),w?.id===k&&$(null)}catch(M){const P=M instanceof Error?M.message:"Failed to remove node";t(P,"error")}},[t,w?.id,o]),L=n.useCallback(async(k,M)=>{await u(k,M)},[u]);return e.jsxs("div",{className:"nodes-view","data-testid":"nodes-view",children:[e.jsxs("div",{className:"nodes-view-header",children:[e.jsxs("div",{className:"nodes-view-title",children:[e.jsxs("h2",{children:[e.jsx(Z,{size:20}),"Nodes"]}),e.jsxs("span",{className:"nodes-view-count",children:[s.length," registered"]})]}),e.jsxs("div",{className:"nodes-view-actions",children:[e.jsx("button",{className:"btn-icon nodes-view-close",onClick:l,"aria-label":"Close nodes view",children:e.jsx(B,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void d(),disabled:r,children:[e.jsx(J,{size:14,className:r?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>b(!0),children:[e.jsx(G,{size:14}),"Add Node"]})]})]}),e.jsxs("div",{className:"nodes-view-stats",children:[e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-total",children:[e.jsx("span",{children:"Total"}),e.jsx("strong",{children:v.total})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--online","data-testid":"nodes-stat-online",children:[e.jsxs("span",{children:[e.jsx(Re,{size:14})," Online"]}),e.jsx("strong",{children:v.online})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--offline","data-testid":"nodes-stat-offline",children:[e.jsxs("span",{children:[e.jsx(Me,{size:14})," Offline"]}),e.jsx("strong",{children:v.offline})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-remote",children:[e.jsxs("span",{children:[e.jsx(we,{size:14})," Remote"]}),e.jsx("strong",{children:v.remote})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--synced","data-testid":"nodes-stat-synced",children:[e.jsxs("span",{children:[e.jsx(J,{size:14})," Synced"]}),e.jsx("strong",{children:v.synced})]})]}),f&&e.jsx("div",{className:"nodes-view-error",children:f}),!r&&s.length>0&&e.jsxs("section",{className:"nodes-view-topology","aria-label":"Mesh Topology",children:[e.jsx("h3",{className:"nodes-view-section-title",children:"Mesh Topology"}),e.jsx(qe,{nodes:s})]}),r?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((k,M)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},M))}):s.length===0?e.jsxs("div",{className:"nodes-view-empty",children:[e.jsx("p",{children:"No nodes are registered yet."}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>b(!0),children:[e.jsx(G,{size:14}),"Add First Node"]})]}):e.jsx("div",{className:"nodes-view-grid",children:s.map(k=>{const M=k.type==="remote"&&j[k.id]?U(j[k.id]):void 0;return e.jsx(Ue,{node:k,projects:g,onHealthCheck:P=>{p(P)},onEdit:P=>$(P),onRemove:P=>{z(P)},isLoading:r,syncStatus:M,authSyncState:k.type==="remote"?a(k.id):void 0,authSyncProviders:k.type==="remote"?i(k.id):void 0},k.id)})}),e.jsx(Je,{isOpen:x,onClose:()=>b(!1),onSubmit:h,addToast:t}),e.jsx(Ze,{isOpen:w!==null,onClose:()=>$(null),node:w,projects:g,onUpdate:L,onHealthCheck:p,addToast:t,syncStatus:w?.type==="remote"&&w&&j[w.id]?U(j[w.id]):void 0,onPushSettings:C,onPullSettings:_,onSyncAuth:S})]})}export{ts as NodesView};
|
|
14
|
+
`)}function Ye({isOpen:t,onClose:l,onResolve:s,conflicts:r,localNodeName:f,remoteNodeName:m,addToast:c}){const[u,o]=n.useState({}),[y,g]=n.useState(!1);n.useEffect(()=>{const a={};for(const i of r)u[i.key]||(a[i.key]={resolution:"local"});Object.keys(a).length>0&&o(i=>({...i,...a}))},[r,u]),n.useEffect(()=>{if(!t)return;const a=i=>{i.key==="Escape"&&(i.preventDefault(),l())};return document.addEventListener("keydown",a),()=>document.removeEventListener("keydown",a)},[t,l]);const j=n.useCallback((a,i)=>{o(x=>{const b=x[a]??{};return i==="manual"?{...x,[a]:{resolution:"manual",manualValue:b.manualValue??JSON.stringify(r.find(w=>w.key===a)?.localValue??null,null,2)}}:{...x,[a]:{resolution:i}}})},[r]),C=n.useCallback((a,i)=>{o(x=>({...x,[a]:{...x[a],resolution:"manual",manualValue:i}}))},[]),_=n.useCallback(a=>{const i={};for(const x of r)i[x.key]={resolution:a};o(i)},[r]),S=n.useCallback(async()=>{g(!0);try{const a=r.map(i=>{const x=u[i.key]??{resolution:"local"};let b;switch(x.resolution){case"remote":b=i.remoteValue;break;case"manual":try{b=JSON.parse(x.manualValue??"null")}catch{b=x.manualValue??null}break;case"local":default:b=i.localValue;break}return{key:i.key,value:b}});await s(a),c("Settings conflicts resolved successfully","success"),l()}catch(a){const i=a instanceof Error?a.message:"Failed to resolve conflicts";c(i,"error")}finally{g(!1)}},[c,r,l,s,u]),A=n.useMemo(()=>{const a={};for(const i of r)a[i.key]=We(i.localValue,i.remoteValue);return a},[r]);return!t||r.length===0?null:e.jsx("div",{className:"modal-overlay open",onClick:l,children:e.jsxs("div",{className:"modal modal-lg settings-sync-conflict-modal",onClick:a=>a.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Resolve Settings Conflicts",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Resolve Settings Conflicts"}),e.jsx("button",{className:"modal-close",onClick:l,"aria-label":"Close conflict modal",children:"×"})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("div",{className:"settings-sync-conflict-modal__conflict-list",children:r.map(a=>{const i=u[a.key]??{resolution:"local"},x=A[a.key];return e.jsxs("div",{className:"settings-sync-conflict-modal__conflict-item",children:[e.jsx("div",{className:"settings-sync-conflict-modal__key",children:a.key}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-panel",children:[e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:f}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:x})})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__diff-side",children:[e.jsx("div",{className:"settings-sync-conflict-modal__diff-label",children:m}),e.jsx("div",{className:"settings-sync-conflict-modal__diff-content",children:e.jsx("pre",{style:{margin:0,whiteSpace:"pre-wrap"},children:x})})]})]}),e.jsxs("div",{className:"settings-sync-conflict-modal__resolution",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="local",onChange:()=>j(a.key,"local")}),"Keep Local"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="remote",onChange:()=>j(a.key,"remote")}),"Keep Remote"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",name:`resolution-${a.key}`,checked:i.resolution==="manual",onChange:()=>j(a.key,"manual")}),"Merge Manually"]})]}),i.resolution==="manual"&&e.jsx("textarea",{className:"settings-sync-conflict-modal__manual-input",value:i.manualValue??"",onChange:b=>C(a.key,b.target.value),placeholder:"Enter JSON value..."})]},a.key)})}),e.jsxs("div",{className:"settings-sync-conflict-modal__bulk-actions",children:[e.jsx("button",{className:"btn btn-sm",onClick:()=>_("local"),type:"button",children:"Resolve All: Keep Local"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>_("remote"),type:"button",children:"Resolve All: Keep Remote"})]})]}),e.jsxs("div",{className:"modal-actions settings-sync-conflict-modal__footer",children:[e.jsx("button",{className:"btn btn-sm",onClick:l,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary btn-sm",onClick:S,disabled:y,children:y?"Resolving...":"Confirm"})]})]})})}function B(t){if(!t)return"—";const l=new Date(t);return Number.isNaN(l.getTime())?"—":l.toLocaleString()}function Ze({isOpen:t,onClose:l,node:s,projects:r,onUpdate:f,onHealthCheck:m,addToast:c,syncStatus:u,onPushSettings:o,onPullSettings:y,onSyncAuth:g,syncHistory:j=[],onResolveConflicts:C}){const _=n.useRef(!0),[S,A]=n.useState(!1),[a,i]=n.useState(""),[x,b]=n.useState(""),[w,$]=n.useState(""),[v,h]=n.useState(2),[d,p]=n.useState(!1),[z,L]=n.useState(!1),[k,M]=n.useState(!1),[P,F]=n.useState(!1),[I,E]=n.useState(null),[le,re]=n.useState(!1),[ce]=n.useState([]);n.useEffect(()=>(_.current=!0,()=>{_.current=!1}),[]),n.useEffect(()=>{if(!s||!t){A(!1);return}i(s.name),b(s.url??""),$(s.apiKey??""),h(s.maxConcurrent),A(!1)},[t,s]),n.useEffect(()=>{if(!t)return;const N=R=>{R.key==="Escape"&&(R.preventDefault(),l())};return document.addEventListener("keydown",N),()=>document.removeEventListener("keydown",N)},[t,l]);const K=n.useMemo(()=>s?ne(r,s):[],[s,r]),oe=n.useCallback(async()=>{if(s)try{if(await m(s.id),!_.current)return;c(`Health check completed for ${s.name}`,"success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Health check failed";c(R,"error")}},[c,s,m]),ie=n.useCallback(async()=>{if(!(!s||!o)){E(null),L(!0);try{if(await o(s.id),!_.current)return;c("Settings pushed successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Push settings failed";E(R),c(R,"error")}finally{_.current&&L(!1)}}},[c,s,o]),de=n.useCallback(async()=>{if(!(!s||!y)){E(null),M(!0);try{if(await y(s.id),!_.current)return;c("Settings pulled successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Pull settings failed";E(R),c(R,"error")}finally{_.current&&M(!1)}}},[c,s,y]),ue=n.useCallback(async()=>{if(!(!s||!g)){E(null),F(!0);try{if(await g(s.id),!_.current)return;c("Auth credentials synced successfully","success")}catch(N){if(!_.current)return;const R=N instanceof Error?N.message:"Auth sync failed";E(R),c(R,"error")}finally{_.current&&F(!1)}}},[c,s,g]),me=n.useCallback(()=>{E(null)},[]),he=n.useCallback(async()=>{if(!s||d)return;const N=a.trim();if(!N){c("Name is required","error");return}if(s.type==="remote"&&!x.trim()){c("URL is required for remote nodes","error");return}if(!Number.isFinite(v)||v<1){c("Concurrency must be at least 1","error");return}p(!0);try{await f(s.id,{name:N,url:s.type==="remote"&&x.trim()||void 0,apiKey:s.type==="remote"&&w||void 0,maxConcurrent:v}),c(`Updated ${N}`,"success"),A(!1)}catch(R){const ye=R instanceof Error?R.message:"Failed to update node";c(ye,"error")}finally{p(!1)}},[c,w,d,v,a,s,f,x]),fe=n.useCallback(()=>{s&&(i(s.name),b(s.url??""),$(s.apiKey??""),h(s.maxConcurrent),A(!1))},[s]);return!t||!s?null:e.jsxs("div",{className:"modal-overlay open",onClick:l,children:[e.jsxs("div",{className:"modal modal-lg node-detail-modal",onClick:N=>N.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":`Node details for ${s.name}`,children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:"Node Details"}),e.jsx("button",{className:"modal-close",onClick:l,"aria-label":"Close node detail modal",children:"×"})]}),e.jsxs("div",{className:"modal-body node-detail-modal__body",children:[e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("div",{className:"node-detail-modal__section-header",children:[e.jsx("h4",{children:"Overview"}),!S&&e.jsxs("button",{className:"btn btn-sm",onClick:()=>A(!0),children:[e.jsx(ve,{size:14}),"Edit"]})]}),e.jsxs("div",{className:"node-detail-modal__grid",children:[e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Name"}),S?e.jsx("input",{className:"input",value:a,onChange:N=>i(N.target.value),disabled:d}):e.jsx("strong",{children:s.name})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Type"}),e.jsx("strong",{children:s.type==="local"?"Local":"Remote"})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Status"}),e.jsx("strong",{children:s.status})]}),e.jsxs("label",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Max Concurrent"}),S?e.jsx("input",{className:"input",type:"number",min:1,max:10,value:v,onChange:N=>h(Number(N.target.value)),disabled:d}):e.jsx("strong",{children:s.maxConcurrent})]}),s.type==="remote"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"URL"}),S?e.jsx("input",{className:"input",value:x,onChange:N=>b(N.target.value),disabled:d}):e.jsx("strong",{children:s.url??"—"})]}),e.jsxs("label",{className:"node-detail-modal__field node-detail-modal__field--full",children:[e.jsx("span",{children:"API Key"}),S?e.jsx("input",{className:"input",type:"password",value:w,onChange:N=>$(N.target.value),placeholder:"Leave blank to keep unchanged",disabled:d}):e.jsx("strong",{children:s.apiKey?"••••••••":"Not configured"})]})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Created"}),e.jsx("strong",{children:B(s.createdAt)})]}),e.jsxs("div",{className:"node-detail-modal__field",children:[e.jsx("span",{children:"Updated"}),e.jsx("strong",{children:B(s.updatedAt)})]})]}),S&&e.jsxs("div",{className:"node-detail-modal__edit-actions",children:[e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:he,disabled:d,children:[e.jsx(Ce,{size:14}),d?"Saving...":"Save"]}),e.jsxs("button",{className:"btn btn-sm",onClick:fe,disabled:d,children:[e.jsx(V,{size:14}),"Cancel"]})]})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsxs("h4",{children:[s.type==="local"?"Projects":"Assigned Projects"," (",K.length,")"]}),K.length===0?e.jsx("p",{className:"node-detail-modal__empty",children:s.type==="local"?"No projects are running on this node.":"No projects are assigned to this node."}):e.jsx("ul",{className:"node-detail-modal__project-list",children:K.map(N=>e.jsxs("li",{className:"node-detail-modal__project-item",children:[e.jsx("span",{children:N.name}),e.jsx("code",{children:N.id})]},N.id))})]}),e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Health"}),e.jsxs("div",{className:"node-detail-modal__health-row",children:[e.jsxs("span",{children:["Status: ",e.jsx("strong",{children:s.status})]}),e.jsxs("span",{children:["Last check: ",e.jsx("strong",{children:B(s.updatedAt)})]})]})]}),s.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Settings Sync"}),u&&e.jsxs("div",{className:"node-detail-modal__sync-status",children:[e.jsx("span",{className:"node-detail-modal__sync-dot",style:{backgroundColor:ae(u.syncState)},"aria-hidden":!0}),e.jsxs("span",{children:["Last sync:"," ",e.jsx("strong",{children:u.lastSyncAt?te(u.lastSyncAt):"Never synced"})]}),u.diffCount>0&&e.jsxs("span",{className:"node-detail-modal__sync-diff",children:["Differences: ",e.jsx("strong",{children:u.diffCount})]})]}),e.jsxs("div",{className:"node-detail-modal__sync-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:ie,disabled:z||!o,children:[e.jsx(se,{size:14}),z?"Pushing...":"Push Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:de,disabled:k||!y,children:[e.jsx(ee,{size:14}),k?"Pulling...":"Pull Settings"]}),e.jsxs("button",{className:"btn btn-sm",onClick:ue,disabled:P||!g,children:[e.jsx(Q,{size:14}),P?"Syncing...":"Sync Auth"]})]}),I&&e.jsxs("div",{className:"node-detail-modal__sync-error",children:[e.jsx("span",{children:I}),e.jsx("button",{className:"node-detail-modal__sync-error-dismiss",onClick:me,"aria-label":"Dismiss error",children:e.jsx(V,{size:14})})]})]}),s.type==="remote"&&e.jsxs("section",{className:"node-detail-modal__section",children:[e.jsx("h4",{children:"Sync History"}),e.jsx(Ge,{nodeId:s.id,entries:j,singleNode:!0})]})]}),e.jsxs("div",{className:"modal-actions node-detail-modal__actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:oe,children:[e.jsx(T,{size:14}),"Health Check"]}),e.jsx("button",{className:"btn btn-sm",onClick:l,children:"Close"})]})]}),s.type==="remote"&&e.jsx(Ye,{isOpen:le,onClose:()=>re(!1),onResolve:C??(async()=>{}),conflicts:ce,localNodeName:"Local",remoteNodeName:s.name,addToast:c})]})}function ts({addToast:t,onClose:l}){const{nodes:s,loading:r,error:f,refresh:m,register:c,update:u,unregister:o,healthCheck:y}=ke(),{projects:g}=Se(),{syncStatusMap:j,pushSettings:C,pullSettings:_,syncAuth:S,trackNode:A,getAuthSyncState:a,getAuthProviders:i}=$e(),[x,b]=n.useState(!1),[w,$]=n.useState(null);n.useEffect(()=>{const k=s.filter(M=>M.type==="remote");for(const M of k)A(M.id)},[s,A]),n.useEffect(()=>{if(!w)return;const k=s.find(M=>M.id===w.id)??null;$(k)},[s,w]);const v=n.useMemo(()=>{const k=s.length,M=s.filter(E=>E.status==="online").length,P=s.filter(E=>E.status==="offline"||E.status==="error").length,F=s.filter(E=>E.type==="remote").length,I=s.filter(E=>E.type==="remote"&&j[E.id]&&U(j[E.id]).syncState==="synced").length;return{total:k,online:M,offline:P,remote:F,synced:I}},[s,j]),h=n.useCallback(async k=>{await c(k)},[c]),d=n.useCallback(async()=>{try{await m()}catch{t("Failed to refresh nodes","error")}},[t,m]),p=n.useCallback(async k=>{try{await y(k),t("Node health check complete","success")}catch(M){const P=M instanceof Error?M.message:"Health check failed";t(P,"error")}},[t,y]),z=n.useCallback(async k=>{try{await o(k),t("Node removed","success"),w?.id===k&&$(null)}catch(M){const P=M instanceof Error?M.message:"Failed to remove node";t(P,"error")}},[t,w?.id,o]),L=n.useCallback(async(k,M)=>{await u(k,M)},[u]);return e.jsxs("div",{className:"nodes-view","data-testid":"nodes-view",children:[e.jsxs("div",{className:"nodes-view-header",children:[e.jsxs("div",{className:"nodes-view-title",children:[e.jsxs("h2",{children:[e.jsx(Z,{size:20}),"Nodes"]}),e.jsxs("span",{className:"nodes-view-count",children:[s.length," registered"]})]}),e.jsxs("div",{className:"nodes-view-actions",children:[e.jsx("button",{className:"btn-icon nodes-view-close",onClick:l,"aria-label":"Close nodes view",children:e.jsx(V,{size:16})}),e.jsxs("button",{className:"btn btn-sm",onClick:()=>void d(),disabled:r,children:[e.jsx(J,{size:14,className:r?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>b(!0),children:[e.jsx(G,{size:14}),"Add Node"]})]})]}),e.jsxs("div",{className:"nodes-view-stats",children:[e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-total",children:[e.jsx("span",{children:"Total"}),e.jsx("strong",{children:v.total})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--online","data-testid":"nodes-stat-online",children:[e.jsxs("span",{children:[e.jsx(Re,{size:14})," Online"]}),e.jsx("strong",{children:v.online})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--offline","data-testid":"nodes-stat-offline",children:[e.jsxs("span",{children:[e.jsx(Me,{size:14})," Offline"]}),e.jsx("strong",{children:v.offline})]}),e.jsxs("div",{className:"nodes-view-stat","data-testid":"nodes-stat-remote",children:[e.jsxs("span",{children:[e.jsx(we,{size:14})," Remote"]}),e.jsx("strong",{children:v.remote})]}),e.jsxs("div",{className:"nodes-view-stat nodes-view-stat--synced","data-testid":"nodes-stat-synced",children:[e.jsxs("span",{children:[e.jsx(J,{size:14})," Synced"]}),e.jsx("strong",{children:v.synced})]})]}),f&&e.jsx("div",{className:"nodes-view-error",children:f}),!r&&s.length>0&&e.jsxs("section",{className:"nodes-view-topology","aria-label":"Mesh Topology",children:[e.jsx("h3",{className:"nodes-view-section-title",children:"Mesh Topology"}),e.jsx(qe,{nodes:s})]}),r?e.jsx("div",{className:"nodes-view-grid",children:Array.from({length:4}).map((k,M)=>e.jsx("div",{className:"node-card node-card--loading","aria-hidden":!0},M))}):s.length===0?e.jsxs("div",{className:"nodes-view-empty",children:[e.jsx("p",{children:"No nodes are registered yet."}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>b(!0),children:[e.jsx(G,{size:14}),"Add First Node"]})]}):e.jsx("div",{className:"nodes-view-grid",children:s.map(k=>{const M=k.type==="remote"&&j[k.id]?U(j[k.id]):void 0;return e.jsx(Ue,{node:k,projects:g,onHealthCheck:P=>{p(P)},onEdit:P=>$(P),onRemove:P=>{z(P)},isLoading:r,syncStatus:M,authSyncState:k.type==="remote"?a(k.id):void 0,authSyncProviders:k.type==="remote"?i(k.id):void 0},k.id)})}),e.jsx(Je,{isOpen:x,onClose:()=>b(!1),onSubmit:h,addToast:t}),e.jsx(Ze,{isOpen:w!==null,onClose:()=>$(null),node:w,projects:g,onUpdate:L,onHealthCheck:p,addToast:t,syncStatus:w?.type==="remote"&&w&&j[w.id]?U(j[w.id]):void 0,onPushSettings:C,onPullSettings:_,onSyncAuth:S})]})}export{ts as NodesView};
|
package/dist/client/assets/{PiExtensionsManager-Uo3E8Ae7.js → PiExtensionsManager-CeI1syeZ.js}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{c as
|
|
1
|
+
import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{c as M,dN as J,dO as V,dP as Y,R as $,dF as y,D as Z,O as T,I as ee,N as se,cj as L,F as D,dQ as ae,dR as te,dS as O,X as ie}from"./index-DyXZm9QN.js";import"./vendor-xterm-DzcZoU0P.js";/**
|
|
2
2
|
* @license lucide-react v1.7.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const ne=[["path",{d:"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z",key:"e79jfc"}],["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}]],M
|
|
6
|
+
*/const ne=[["path",{d:"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z",key:"e79jfc"}],["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}]],_=M("palette",ne);/**
|
|
7
7
|
* @license lucide-react v1.7.0 - ISC
|
|
8
8
|
*
|
|
9
9
|
* This source code is licensed under the ISC license.
|
|
10
10
|
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
-
*/const le=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],
|
|
11
|
+
*/const le=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],I=M("puzzle",le);function ce(t){return t.replace(/-/g,"-")}function re(t){return{"fusion-global":"Fusion Global","pi-global":"Pi Global","fusion-project":"Fusion Project","pi-project":"Pi Project",package:"Package"}[t]??t}function oe(t){return t.startsWith("npm:")?"npm":t.startsWith("git:")?"git":"local"}function de(t){return t.replace(/^(npm:|git:)/,"")}function he({addToast:t,projectId:x}){const[c,A]=l.useState(null),[f,P]=l.useState(!0),[N,S]=l.useState(!1),[E,w]=l.useState(!1),[h,F]=l.useState(""),[G,W]=l.useState(new Set),[p,q]=l.useState([]),[b,z]=l.useState(!0),[B,C]=l.useState(!1),r=l.useCallback(async()=>{try{P(!0);const s=await J();A(s)}catch(s){t(`Failed to load Pi settings: ${s instanceof Error?s.message:String(s)}`,"error")}finally{P(!1)}},[t]),m=l.useCallback(async()=>{try{z(!0);const s=await V(x);q(s.extensions)}catch(s){t(`Failed to load extensions: ${s instanceof Error?s.message:String(s)}`,"error")}finally{z(!1)}},[t,x]),K=l.useCallback(async s=>{try{C(!0);const i=s.enabled?[...p.filter(a=>a.enabled&&a.id!==s.id).map(a=>a.id),s.id]:p.filter(a=>a.enabled&&a.id!==s.id).map(a=>a.id);await Y(i,x),await m(),t(s.enabled?"Extension disabled":"Extension enabled","success")}catch(i){t(`Failed to update extension: ${i instanceof Error?i.message:String(i)}`,"error")}finally{C(!1)}},[p,x,m,t]);l.useEffect(()=>{r()},[r]),l.useEffect(()=>{m()},[m]);const Q=s=>{W(i=>{const a=new Set(i);return a.has(s)?a.delete(s):a.add(s),a})},R=async()=>{if(!h.trim()){t("Please enter a package source","error");return}try{S(!0),await ae(h.trim()),t("Package installed successfully","success"),F(""),await r()}catch(s){t(`Failed to install package: ${s instanceof Error?s.message:String(s)}`,"error")}finally{S(!1)}},U=async()=>{try{w(!0),await te(x),await Promise.all([r(),m()]),t("Fusion skill reinstalled successfully","success")}catch(s){t(`Failed to reinstall Fusion skill: ${s instanceof Error?s.message:String(s)}`,"error")}finally{w(!1)}},X=async s=>{if(!c)return;const i=c.packages.filter(a=>(typeof a=="string"?a:a.source)!==s);try{await O({packages:i}),t("Package removed","success"),await r()}catch(a){t(`Failed to remove package: ${a instanceof Error?a.message:String(a)}`,"error")}},H=async(s,i)=>{if(!c)return;const a=c[s].filter(n=>n!==i);try{await O({[s]:a}),t(`${s.slice(0,-1)} removed`,"success"),await r()}catch(n){t(`Failed to update settings: ${n instanceof Error?n.message:String(n)}`,"error")}},u=(s,i,a)=>!c||c[a].length===0?null:e.jsxs("div",{className:"pi-ext-section",children:[e.jsxs("div",{className:"pi-ext-section-header",children:[e.jsx(i,{size:14}),e.jsx("span",{children:s}),e.jsx("span",{className:"pi-ext-count",children:c[a].length})]}),e.jsx("div",{className:"pi-ext-resource-list",children:c[a].map((n,g)=>e.jsxs("span",{className:"pi-ext-resource-tag",children:[e.jsx("span",{className:"pi-ext-resource-path",children:n}),e.jsx("button",{className:"btn-icon touch-target pi-ext-resource-remove",onClick:()=>H(a,n),title:`Remove ${n}`,"aria-label":`Remove ${n}`,children:e.jsx(ie,{size:12})})]},g))})]});return e.jsxs("div",{className:"pi-ext-manager",children:[e.jsxs("div",{className:"pi-ext-manager-header",children:[e.jsx("h4",{className:"pi-ext-manager-title",children:"Pi Extensions"}),e.jsx("div",{className:"pi-ext-manager-actions",children:e.jsx("button",{className:"btn-icon",onClick:r,title:"Refresh",disabled:f,children:e.jsx($,{size:16,className:f?"spin":""})})})]}),f?e.jsx("div",{className:"loading-state",children:"Loading Pi settings…"}):c?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"pi-ext-add-form",children:[e.jsxs("div",{className:"pi-ext-add-form-row",children:[e.jsx("input",{type:"text",className:"input",placeholder:"npm:pi-extension-name or git:https://github.com/...",value:h,onChange:s=>F(s.target.value),onKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),R())},disabled:N}),e.jsxs("button",{className:"btn btn-primary",onClick:R,disabled:N||!h.trim(),children:[e.jsx(Z,{size:14}),N?"Installing…":"Add"]})]}),e.jsx("div",{className:"pi-ext-add-form-row",children:e.jsx("button",{className:"btn",onClick:U,disabled:E,children:E?"Reinstalling Fusion…":"Reinstall Fusion skill"})})]}),c.packages.length>0?e.jsx("div",{className:"pi-ext-package-list",children:c.packages.map((s,i)=>{const a=typeof s=="string"?s:s.source,n=oe(a),g=de(a),j=typeof s=="object"&&s!==null,v=j&&(s.extensions?.length??0)>0||(s.skills?.length??0)>0||(s.prompts?.length??0)>0||(s.themes?.length??0)>0,k=G.has(i);return e.jsxs("div",{className:"pi-ext-package-card",children:[e.jsxs("div",{className:"pi-ext-package-header",children:[j&&v?e.jsx("button",{className:"pi-ext-expand-btn",onClick:()=>Q(i),"aria-expanded":k,children:k?e.jsx(T,{size:14}):e.jsx(ee,{size:14})}):e.jsx("span",{className:"pi-ext-expand-placeholder"}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${n}`,children:n}),e.jsx("span",{className:"pi-ext-package-source",children:g}),e.jsxs("div",{className:"pi-ext-package-actions",children:[j&&v&&e.jsxs("span",{className:"pi-ext-filter-hint",children:[s.extensions?.length??0," ext,"," ",s.skills?.length??0," skill,"," ",s.prompts?.length??0," prompt,"," ",s.themes?.length??0," theme"]}),e.jsx("button",{className:"btn-icon touch-target pi-ext-remove-btn",onClick:()=>X(a),title:"Remove package","aria-label":`Remove package ${g}`,children:e.jsx(se,{size:14})})]})]}),j&&v&&k&&e.jsxs("div",{className:"pi-ext-filter-list",children:[s.extensions?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(I,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Extensions:"}),s.extensions.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.skills?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(L,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Skills:"}),s.skills.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.prompts?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(D,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Prompts:"}),s.prompts.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.themes?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(_,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Themes:"}),s.themes.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null]})]},i)})}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"No packages configured."}),e.jsx("p",{className:"text-muted",children:"Add a package source above to get started."})]}),e.jsxs("div",{className:"pi-ext-top-level",children:[u("Extensions",I,"extensions"),u("Skills",L,"skills"),u("Prompts",D,"prompts"),u("Themes",_,"themes")]})]}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"Failed to load Pi settings."})]}),e.jsxs("div",{className:"pi-ext-discovered-section",children:[e.jsxs("div",{className:"pi-ext-discovered-header",children:[e.jsx("h4",{children:"Discovered Extensions"}),e.jsx("button",{className:"btn-icon",onClick:m,disabled:b,title:"Refresh extensions",children:e.jsx($,{size:14,className:b?"spin":""})})]}),e.jsx("p",{className:"pi-ext-description",children:"Installed extensions resolved from packages and configured paths."}),b?e.jsx("div",{className:"loading-state",children:"Loading extensions…"}):p.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"No extensions discovered."})]}):e.jsx("div",{className:"pi-ext-list",children:p.map(s=>e.jsxs("div",{className:"pi-ext-item",children:[e.jsxs("div",{className:"pi-ext-item-content",children:[e.jsxs("div",{className:"pi-ext-info",children:[e.jsx("span",{className:"pi-ext-name",children:s.name}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${ce(s.source)}`,children:re(s.source)})]}),e.jsx("span",{className:"pi-ext-path",children:s.path})]}),e.jsx("div",{className:"pi-ext-actions",children:e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>void K(s),disabled:B,"aria-label":`Toggle ${s.name}`}),e.jsx("span",{className:"toggle-slider"})]})})]},s.id))})]})]})}export{he as PiExtensionsManager};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as u,j as s}from"./vendor-react-K0fH_qHe.js";import{p as ee,dx as se,s as ne,X as k,aj as te,D as A,dy as O,N as _,R as ie,dz as ae,au as le,c3 as re,dA as ce,dB as de,dC as ue,dD as oe,dE as V,c0 as ge}from"./index-Bs3RZu5I.js";import{D as me}from"./DirectoryPicker-crtmkC00.js";import"./vendor-xterm-DzcZoU0P.js";import"./folder-open-DWUflP4Q.js";const H=[{id:"fusion-plugin-hermes-runtime",name:"Hermes Runtime",path:"./plugins/fusion-plugin-hermes-runtime",experimental:!0},{id:"fusion-plugin-paperclip-runtime",name:"Paperclip Runtime",path:"./plugins/fusion-plugin-paperclip-runtime"},{id:"fusion-plugin-openclaw-runtime",name:"OpenClaw Runtime",path:"./plugins/fusion-plugin-openclaw-runtime",experimental:!0}],j={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function fe({addToast:l,projectId:c}){const[N,x]=u.useState([]),[S,w]=u.useState(!0),[M,f]=u.useState(!1),[b,v]=u.useState(""),[C,P]=u.useState(!1),[h,I]=u.useState(null),[i,y]=u.useState(null),[a,p]=u.useState({}),[G,$]=u.useState(!1),[R,E]=u.useState(null),{confirm:J}=ee(),o=u.useCallback(async()=>{try{w(!0);const e=await se(c);x(e)}catch(e){l(`Failed to load plugins: ${e instanceof Error?e.message:String(e)}`,"error")}finally{w(!1)}},[c,l]);u.useEffect(()=>{o()},[o]);const K=u.useRef([]);K.current=N,u.useEffect(()=>{const e=c?`?projectId=${encodeURIComponent(c)}`:"",n=g=>{try{const t=JSON.parse(g.data);if(c&&t.projectId&&t.projectId!==c)return;switch(t.transition){case"installing":case"enabled":case"disabled":case"settings-updated":x(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],enabled:t.enabled,state:t.state,settings:t.settings,error:t.error},r}else return o(),d});break;case"uninstalled":x(d=>d.filter(m=>m.id!==t.pluginId));break;case"error":x(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],state:t.state,error:t.error},r}return d});break}}catch{}};return ne(`/api/events${e}`,{events:{"plugin:lifecycle":n},onReconnect:()=>{o()}})},[c,o]);const z=async()=>{if(!b.trim()){l("Please enter a plugin path","error");return}try{P(!0),await V({path:b},c),l("Plugin installed successfully","success"),f(!1),v(""),await o()}catch(e){l(`Failed to install plugin: ${e instanceof Error?e.message:String(e)}`,"error")}finally{P(!1)}},X=async e=>{try{E(e.id),await V({path:e.path},c),l(`${e.name} installed successfully`,"success"),await o()}catch(n){l(`Failed to install ${e.name}: ${n instanceof Error?n.message:String(n)}`,"error")}finally{E(null)}},B=async e=>{try{await ue(e.id,c),l(`${e.name} enabled`,"success"),await o()}catch(n){l(`Failed to enable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},F=async e=>{try{await de(e.id,c),l(`${e.name} disabled`,"success"),await o()}catch(n){l(`Failed to disable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},D=async e=>{try{I(e.id),await ce(e.id,c),l(`${e.name} reloaded`,"success"),await o()}catch(n){l(`Failed to reload plugin: ${n instanceof Error?n.message:String(n)}`,"error")}finally{I(null)}},L=async e=>{if(await J({title:"Uninstall Plugin",message:`Are you sure you want to uninstall "${e.name}"?`,danger:!0}))try{await oe(e.id,c),l(`${e.name} uninstalled`,"success"),await o(),y(null)}catch(g){l(`Failed to uninstall plugin: ${g instanceof Error?g.message:String(g)}`,"error")}},Q=async e=>{y(e);try{$(!0);const n=await ge(e.id,c);p(n)}catch{p({})}finally{$(!1)}},W=async()=>{if(i)try{await re(i.id,a,c),l("Settings saved","success")}catch(e){l(`Failed to save settings: ${e instanceof Error?e.message:String(e)}`,"error")}};if(i)return s.jsxs("div",{className:"plugin-manager-detail","data-testid":"plugin-manager-detail",children:[s.jsxs("div",{className:"plugin-manager-detail-header",children:[s.jsx("button",{className:"btn-icon",onClick:()=>y(null),"aria-label":"Back to plugin list",children:s.jsx(k,{size:16})}),s.jsxs("div",{className:"plugin-detail-title",children:[s.jsx("h4",{className:"plugin-detail-name",children:i.name}),s.jsx("span",{className:"plugin-state-badge",style:{color:j[i.state]||j.installed},children:i.state})]})]}),s.jsxs("div",{className:"plugin-detail-content",children:[s.jsxs("div",{className:"plugin-detail-card",children:[i.description&&s.jsx("p",{className:"plugin-description",children:i.description}),i.author&&s.jsxs("p",{className:"plugin-detail-meta-row",children:[s.jsx("span",{className:"text-muted",children:"Author:"}),i.author]}),i.homepage&&s.jsxs("p",{className:"plugin-detail-meta-row plugin-homepage",children:[s.jsx("span",{className:"text-muted",children:"Homepage:"}),s.jsxs("a",{href:i.homepage,target:"_blank",rel:"noopener noreferrer",children:[i.homepage,s.jsx(te,{size:12})]})]}),s.jsxs("p",{className:"plugin-detail-meta-row",children:[s.jsx("span",{className:"text-muted",children:"Version:"}),i.version]})]}),s.jsxs("div",{className:"plugin-detail-card",children:[s.jsx("h5",{className:"plugin-detail-section-heading",children:"Settings"}),G?s.jsx("p",{className:"text-muted",children:"Loading..."}):i.settingsSchema&&Object.keys(i.settingsSchema).length>0?s.jsxs("div",{className:"plugin-settings-form",children:[Object.entries(i.settingsSchema).map(([e,n])=>{const g=`setting-${e}-help`;return s.jsxs("div",{className:"form-group",children:[s.jsxs("label",{htmlFor:`setting-${e}`,children:[n.label||e,n.required&&" *"]}),n.type==="string"&&!n.multiline&&s.jsx("input",{type:"text",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="string"&&n.multiline&&s.jsx("textarea",{id:`setting-${e}`,rows:4,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="password"&&s.jsx("input",{type:"password",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="number"&&s.jsx("input",{type:"number",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:Number(t.target.value)}),"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="boolean"&&s.jsxs("label",{className:"checkbox-label",children:[s.jsx("input",{type:"checkbox",checked:a[e]??!1,onChange:t=>p({...a,[e]:t.target.checked})}),n.description]}),n.type==="enum"&&s.jsxs("select",{id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),"aria-describedby":n.description&&!n.required?g:void 0,children:[s.jsx("option",{value:"",children:"Select..."}),n.enumValues?.map(t=>s.jsx("option",{value:t,children:t},t))]}),n.type==="array"&&s.jsxs("div",{className:"plugin-settings-array",children:[a[e]?.map((t,d)=>s.jsxs("div",{className:"plugin-settings-array-item",children:[s.jsx("input",{type:n.itemType==="number"?"number":"text",value:t??"",onChange:m=>{const r=m.target.value,q=[...a[e]||[]];q[d]=n.itemType==="number"?Number(r):r,p({...a,[e]:q})}}),s.jsx("button",{className:"btn-icon",onClick:()=>{const r=[...a[e]||[]];r.splice(d,1),p({...a,[e]:r})},"aria-label":"Remove item",children:s.jsx(k,{size:14})})]},d)),s.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const t=a[e]||[],d=n.itemType==="number"?0:"";p({...a,[e]:[...t,d]})},children:[s.jsx(A,{size:14})," Add Item"]})]}),n.description&&!n.required&&!n.multiline&&s.jsx("span",{id:g,className:"form-help",children:n.description})]},e)}),s.jsx("button",{className:"btn btn-primary",onClick:W,children:"Save Settings"})]}):s.jsx("p",{className:"text-muted",children:"No configurable settings."})]}),s.jsxs("div",{className:"plugin-detail-actions",children:[i.state==="started"&&s.jsxs("button",{className:"btn btn-secondary",onClick:()=>D(i),disabled:h===i.id,children:[s.jsx(O,{size:14,className:h===i.id?"spin":""}),h===i.id?"Reloading...":"Reload"]}),i.enabled?s.jsx("button",{className:"btn btn-secondary",onClick:()=>F(i),children:"Disable"}):s.jsx("button",{className:"btn btn-primary",onClick:()=>B(i),children:"Enable"}),s.jsxs("button",{className:"btn btn-danger",onClick:()=>L(i),children:[s.jsx(_,{size:14})," Uninstall"]})]})]})]});const Y=new Set(N.map(e=>e.id)),Z=new Set(H.map(e=>e.id)),U=N.filter(e=>!Z.has(e.id)),T=()=>s.jsxs("section",{className:"plugin-bundled-runtime-section","aria-label":"Bundled Runtime Plugins",children:[s.jsxs("div",{className:"plugin-bundled-runtime-header",children:[s.jsx("h4",{className:"plugin-bundled-runtime-heading",children:"Bundled Runtime Plugins"}),s.jsx("p",{className:"plugin-bundled-runtime-description",children:"Install Fusion's bundled runtimes directly from this screen."})]}),s.jsx("div",{className:"plugin-bundled-runtime-list","aria-label":"Bundled runtime plugin recommendations",children:H.map(e=>{const n=Y.has(e.id);return s.jsxs("div",{className:"plugin-bundled-runtime-item",children:[s.jsxs("div",{className:"plugin-bundled-runtime-meta",children:[s.jsx("span",{className:"plugin-bundled-runtime-name",children:e.name}),e.experimental&&s.jsx("span",{className:"plugin-bundled-runtime-badge",children:"Experimental"}),s.jsx("span",{className:`plugin-bundled-runtime-status ${n?"plugin-bundled-runtime-status--installed":"plugin-bundled-runtime-status--available"}`,children:n?"Installed":"Not installed"})]}),s.jsx("button",{className:`btn ${n?"btn-secondary":"btn-primary"} btn-sm`,onClick:()=>X(e),disabled:n||R===e.id,children:n?"Installed":R===e.id?"Installing...":`Install ${e.name}`})]},e.id)})})]});return s.jsxs("div",{className:"plugin-manager","data-testid":"plugin-manager",children:[s.jsxs("div",{className:"plugin-manager-header",children:[s.jsx("span",{className:"plugin-manager-header-title",children:"Installed Plugins"}),s.jsxs("div",{className:"plugin-manager-actions",children:[s.jsxs("button",{className:"btn btn-sm btn-ghost",onClick:o,title:"Refresh","aria-label":"Refresh plugin list",children:[s.jsx(ie,{size:14,className:S?"spin":""}),"Refresh"]}),s.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>f(!0),children:[s.jsx(A,{size:14})," Install"]})]})]}),M&&s.jsxs("div",{className:"plugin-install-form",children:[s.jsxs("p",{className:"plugin-install-hint",children:["Browse to a plugin package root (contains ",s.jsx("code",{children:"manifest.json"}),") or a built ",s.jsx("code",{children:"dist"})," directory."]}),s.jsx(me,{value:b,onChange:v,placeholder:"Absolute path to plugin directory or dist folder",onInputKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),z())}}),s.jsxs("div",{className:"plugin-install-actions",children:[s.jsx("button",{className:"btn btn-primary",onClick:z,disabled:C||!b.trim(),children:C?"Installing...":"Install Plugin"}),s.jsx("button",{className:"btn btn-secondary",onClick:()=>{f(!1),v("")},children:"Cancel"})]})]}),S?s.jsx("div",{className:"settings-empty-state",children:"Loading plugins..."}):s.jsxs(s.Fragment,{children:[U.length===0?s.jsxs("div",{className:"settings-empty-state",children:[s.jsx(ae,{size:32,className:"text-muted"}),s.jsx("p",{children:"No plugins installed."}),s.jsx("p",{className:"text-muted",children:"Install a plugin to get started, or use a bundled runtime below."})]}):s.jsx("div",{className:"plugin-list",children:U.map(e=>s.jsxs("div",{className:"plugin-item",children:[s.jsxs("div",{className:"plugin-info",children:[s.jsx("span",{className:"plugin-name",children:e.name}),s.jsxs("span",{className:"plugin-version text-muted",children:["v",e.version]}),s.jsx("span",{className:"plugin-state-badge",style:{color:j[e.state]||j.installed},children:e.state})]}),s.jsxs("div",{className:"plugin-actions",children:[e.state==="started"&&s.jsx("button",{className:"btn-icon",onClick:()=>D(e),disabled:h===e.id,title:"Reload",children:s.jsx(O,{size:14,className:h===e.id?"spin":""})}),s.jsxs("label",{className:"toggle-switch",children:[s.jsx("input",{type:"checkbox",checked:e.enabled,onChange:()=>e.enabled?F(e):B(e)}),s.jsx("span",{className:"toggle-slider"})]}),s.jsx("button",{className:"btn-icon",onClick:()=>Q(e),title:"Settings",children:s.jsx(le,{size:14})}),s.jsx("button",{className:"btn-icon",onClick:()=>L(e),title:"Uninstall",children:s.jsx(_,{size:14})})]})]},e.id))}),T()]})]})}export{fe as PluginManager,j as STATE_COLORS};
|
|
1
|
+
import{r as u,j as s}from"./vendor-react-K0fH_qHe.js";import{p as ee,dD as se,s as ne,X as k,aj as te,D as A,dE as O,N as _,R as ie,dF as ae,aA as le,c9 as re,dG as ce,dH as de,dI as ue,dJ as oe,dK as H,c6 as ge}from"./index-DyXZm9QN.js";import{D as me}from"./DirectoryPicker-Cls4HWxP.js";import"./vendor-xterm-DzcZoU0P.js";import"./folder-open-DPpmGJ-v.js";const V=[{id:"fusion-plugin-hermes-runtime",name:"Hermes Runtime",path:"./plugins/fusion-plugin-hermes-runtime",experimental:!0},{id:"fusion-plugin-paperclip-runtime",name:"Paperclip Runtime",path:"./plugins/fusion-plugin-paperclip-runtime"},{id:"fusion-plugin-openclaw-runtime",name:"OpenClaw Runtime",path:"./plugins/fusion-plugin-openclaw-runtime",experimental:!0}],j={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function fe({addToast:l,projectId:c}){const[N,x]=u.useState([]),[S,w]=u.useState(!0),[G,f]=u.useState(!1),[b,v]=u.useState(""),[C,P]=u.useState(!1),[h,I]=u.useState(null),[i,y]=u.useState(null),[a,p]=u.useState({}),[J,$]=u.useState(!1),[R,E]=u.useState(null),{confirm:K}=ee(),o=u.useCallback(async()=>{try{w(!0);const e=await se(c);x(e)}catch(e){l(`Failed to load plugins: ${e instanceof Error?e.message:String(e)}`,"error")}finally{w(!1)}},[c,l]);u.useEffect(()=>{o()},[o]);const M=u.useRef([]);M.current=N,u.useEffect(()=>{const e=c?`?projectId=${encodeURIComponent(c)}`:"",n=g=>{try{const t=JSON.parse(g.data);if(c&&t.projectId&&t.projectId!==c)return;switch(t.transition){case"installing":case"enabled":case"disabled":case"settings-updated":x(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],enabled:t.enabled,state:t.state,settings:t.settings,error:t.error},r}else return o(),d});break;case"uninstalled":x(d=>d.filter(m=>m.id!==t.pluginId));break;case"error":x(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],state:t.state,error:t.error},r}return d});break}}catch{}};return ne(`/api/events${e}`,{events:{"plugin:lifecycle":n},onReconnect:()=>{o()}})},[c,o]);const z=async()=>{if(!b.trim()){l("Please enter a plugin path","error");return}try{P(!0),await H({path:b},c),l("Plugin installed successfully","success"),f(!1),v(""),await o()}catch(e){l(`Failed to install plugin: ${e instanceof Error?e.message:String(e)}`,"error")}finally{P(!1)}},X=async e=>{try{E(e.id),await H({path:e.path},c),l(`${e.name} installed successfully`,"success"),await o()}catch(n){l(`Failed to install ${e.name}: ${n instanceof Error?n.message:String(n)}`,"error")}finally{E(null)}},F=async e=>{try{await ue(e.id,c),l(`${e.name} enabled`,"success"),await o()}catch(n){l(`Failed to enable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},B=async e=>{try{await de(e.id,c),l(`${e.name} disabled`,"success"),await o()}catch(n){l(`Failed to disable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},D=async e=>{try{I(e.id),await ce(e.id,c),l(`${e.name} reloaded`,"success"),await o()}catch(n){l(`Failed to reload plugin: ${n instanceof Error?n.message:String(n)}`,"error")}finally{I(null)}},L=async e=>{if(await K({title:"Uninstall Plugin",message:`Are you sure you want to uninstall "${e.name}"?`,danger:!0}))try{await oe(e.id,c),l(`${e.name} uninstalled`,"success"),await o(),y(null)}catch(g){l(`Failed to uninstall plugin: ${g instanceof Error?g.message:String(g)}`,"error")}},Q=async e=>{y(e);try{$(!0);const n=await ge(e.id,c);p(n)}catch{p({})}finally{$(!1)}},W=async()=>{if(i)try{await re(i.id,a,c),l("Settings saved","success")}catch(e){l(`Failed to save settings: ${e instanceof Error?e.message:String(e)}`,"error")}};if(i)return s.jsxs("div",{className:"plugin-manager-detail","data-testid":"plugin-manager-detail",children:[s.jsxs("div",{className:"plugin-manager-detail-header",children:[s.jsx("button",{className:"btn-icon",onClick:()=>y(null),"aria-label":"Back to plugin list",children:s.jsx(k,{size:16})}),s.jsxs("div",{className:"plugin-detail-title",children:[s.jsx("h4",{className:"plugin-detail-name",children:i.name}),s.jsx("span",{className:"plugin-state-badge",style:{color:j[i.state]||j.installed},children:i.state})]})]}),s.jsxs("div",{className:"plugin-detail-content",children:[s.jsxs("div",{className:"plugin-detail-card",children:[i.description&&s.jsx("p",{className:"plugin-description",children:i.description}),i.author&&s.jsxs("p",{className:"plugin-detail-meta-row",children:[s.jsx("span",{className:"text-muted",children:"Author:"}),i.author]}),i.homepage&&s.jsxs("p",{className:"plugin-detail-meta-row plugin-homepage",children:[s.jsx("span",{className:"text-muted",children:"Homepage:"}),s.jsxs("a",{href:i.homepage,target:"_blank",rel:"noopener noreferrer",children:[i.homepage,s.jsx(te,{size:12})]})]}),s.jsxs("p",{className:"plugin-detail-meta-row",children:[s.jsx("span",{className:"text-muted",children:"Version:"}),i.version]})]}),s.jsxs("div",{className:"plugin-detail-card",children:[s.jsx("h5",{className:"plugin-detail-section-heading",children:"Settings"}),J?s.jsx("p",{className:"text-muted",children:"Loading..."}):i.settingsSchema&&Object.keys(i.settingsSchema).length>0?s.jsxs("div",{className:"plugin-settings-form",children:[Object.entries(i.settingsSchema).map(([e,n])=>{const g=`setting-${e}-help`;return s.jsxs("div",{className:"form-group",children:[s.jsxs("label",{htmlFor:`setting-${e}`,children:[n.label||e,n.required&&" *"]}),n.type==="string"&&!n.multiline&&s.jsx("input",{type:"text",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="string"&&n.multiline&&s.jsx("textarea",{id:`setting-${e}`,rows:4,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="password"&&s.jsx("input",{type:"password",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="number"&&s.jsx("input",{type:"number",id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:Number(t.target.value)}),"aria-describedby":n.description&&!n.required?g:void 0}),n.type==="boolean"&&s.jsxs("label",{className:"checkbox-label",children:[s.jsx("input",{type:"checkbox",checked:a[e]??!1,onChange:t=>p({...a,[e]:t.target.checked})}),n.description]}),n.type==="enum"&&s.jsxs("select",{id:`setting-${e}`,value:a[e]??"",onChange:t=>p({...a,[e]:t.target.value}),"aria-describedby":n.description&&!n.required?g:void 0,children:[s.jsx("option",{value:"",children:"Select..."}),n.enumValues?.map(t=>s.jsx("option",{value:t,children:t},t))]}),n.type==="array"&&s.jsxs("div",{className:"plugin-settings-array",children:[a[e]?.map((t,d)=>s.jsxs("div",{className:"plugin-settings-array-item",children:[s.jsx("input",{type:n.itemType==="number"?"number":"text",value:t??"",onChange:m=>{const r=m.target.value,q=[...a[e]||[]];q[d]=n.itemType==="number"?Number(r):r,p({...a,[e]:q})}}),s.jsx("button",{className:"btn-icon",onClick:()=>{const r=[...a[e]||[]];r.splice(d,1),p({...a,[e]:r})},"aria-label":"Remove item",children:s.jsx(k,{size:14})})]},d)),s.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const t=a[e]||[],d=n.itemType==="number"?0:"";p({...a,[e]:[...t,d]})},children:[s.jsx(A,{size:14})," Add Item"]})]}),n.description&&!n.required&&!n.multiline&&s.jsx("span",{id:g,className:"form-help",children:n.description})]},e)}),s.jsx("button",{className:"btn btn-primary",onClick:W,children:"Save Settings"})]}):s.jsx("p",{className:"text-muted",children:"No configurable settings."})]}),s.jsxs("div",{className:"plugin-detail-actions",children:[i.state==="started"&&s.jsxs("button",{className:"btn btn-secondary",onClick:()=>D(i),disabled:h===i.id,children:[s.jsx(O,{size:14,className:h===i.id?"spin":""}),h===i.id?"Reloading...":"Reload"]}),i.enabled?s.jsx("button",{className:"btn btn-secondary",onClick:()=>B(i),children:"Disable"}):s.jsx("button",{className:"btn btn-primary",onClick:()=>F(i),children:"Enable"}),s.jsxs("button",{className:"btn btn-danger",onClick:()=>L(i),children:[s.jsx(_,{size:14})," Uninstall"]})]})]})]});const Y=new Set(N.map(e=>e.id)),Z=new Set(V.map(e=>e.id)),U=N.filter(e=>!Z.has(e.id)),T=()=>s.jsxs("section",{className:"plugin-bundled-runtime-section","aria-label":"Bundled Runtime Plugins",children:[s.jsxs("div",{className:"plugin-bundled-runtime-header",children:[s.jsx("h4",{className:"plugin-bundled-runtime-heading",children:"Bundled Runtime Plugins"}),s.jsx("p",{className:"plugin-bundled-runtime-description",children:"Install Fusion's bundled runtimes directly from this screen."})]}),s.jsx("div",{className:"plugin-bundled-runtime-list","aria-label":"Bundled runtime plugin recommendations",children:V.map(e=>{const n=Y.has(e.id);return s.jsxs("div",{className:"plugin-bundled-runtime-item",children:[s.jsxs("div",{className:"plugin-bundled-runtime-meta",children:[s.jsx("span",{className:"plugin-bundled-runtime-name",children:e.name}),e.experimental&&s.jsx("span",{className:"plugin-bundled-runtime-badge",children:"Experimental"}),s.jsx("span",{className:`plugin-bundled-runtime-status ${n?"plugin-bundled-runtime-status--installed":"plugin-bundled-runtime-status--available"}`,children:n?"Installed":"Not installed"})]}),s.jsx("button",{className:`btn ${n?"btn-secondary":"btn-primary"} btn-sm`,onClick:()=>X(e),disabled:n||R===e.id,children:n?"Installed":R===e.id?"Installing...":`Install ${e.name}`})]},e.id)})})]});return s.jsxs("div",{className:"plugin-manager","data-testid":"plugin-manager",children:[s.jsxs("div",{className:"plugin-manager-header",children:[s.jsx("span",{className:"plugin-manager-header-title",children:"Installed Plugins"}),s.jsxs("div",{className:"plugin-manager-actions",children:[s.jsxs("button",{className:"btn btn-sm btn-ghost",onClick:o,title:"Refresh","aria-label":"Refresh plugin list",children:[s.jsx(ie,{size:14,className:S?"spin":""}),"Refresh"]}),s.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>f(!0),children:[s.jsx(A,{size:14})," Install"]})]})]}),G&&s.jsxs("div",{className:"plugin-install-form",children:[s.jsxs("p",{className:"plugin-install-hint",children:["Browse to a plugin package root (contains ",s.jsx("code",{children:"manifest.json"}),") or a built ",s.jsx("code",{children:"dist"})," directory."]}),s.jsx(me,{value:b,onChange:v,placeholder:"Absolute path to plugin directory or dist folder",onInputKeyDown:e=>{e.key==="Enter"&&(e.preventDefault(),z())}}),s.jsxs("div",{className:"plugin-install-actions",children:[s.jsx("button",{className:"btn btn-primary",onClick:z,disabled:C||!b.trim(),children:C?"Installing...":"Install Plugin"}),s.jsx("button",{className:"btn btn-secondary",onClick:()=>{f(!1),v("")},children:"Cancel"})]})]}),S?s.jsx("div",{className:"settings-empty-state",children:"Loading plugins..."}):s.jsxs(s.Fragment,{children:[U.length===0?s.jsxs("div",{className:"settings-empty-state",children:[s.jsx(ae,{size:32,className:"text-muted"}),s.jsx("p",{children:"No plugins installed."}),s.jsx("p",{className:"text-muted",children:"Install a plugin to get started, or use a bundled runtime below."})]}):s.jsx("div",{className:"plugin-list",children:U.map(e=>s.jsxs("div",{className:"plugin-item",children:[s.jsxs("div",{className:"plugin-info",children:[s.jsx("span",{className:"plugin-name",children:e.name}),s.jsxs("span",{className:"plugin-version text-muted",children:["v",e.version]}),s.jsx("span",{className:"plugin-state-badge",style:{color:j[e.state]||j.installed},children:e.state})]}),s.jsxs("div",{className:"plugin-actions",children:[e.state==="started"&&s.jsx("button",{className:"btn-icon",onClick:()=>D(e),disabled:h===e.id,title:"Reload",children:s.jsx(O,{size:14,className:h===e.id?"spin":""})}),s.jsxs("label",{className:"toggle-switch",children:[s.jsx("input",{type:"checkbox",checked:e.enabled,onChange:()=>e.enabled?B(e):F(e)}),s.jsx("span",{className:"toggle-slider"})]}),s.jsx("button",{className:"btn-icon",onClick:()=>Q(e),title:"Settings",children:s.jsx(le,{size:14})}),s.jsx("button",{className:"btn-icon",onClick:()=>L(e),title:"Uninstall",children:s.jsx(_,{size:14})})]})]},e.id))}),T()]})]})}export{fe as PluginManager,j as STATE_COLORS};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.research-view{display:flex;flex-direction:column;gap:var(--space-md);height:100%;min-height:0;padding:var(--space-lg)}.research-view__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-md)}.research-view__title{margin:0}.research-view__subtitle{margin:var(--space-xs) 0 0;color:var(--text-muted)}.research-view__layout{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);gap:var(--space-md);min-height:0;flex:1}.research-view__sidebar,.research-view__reader{padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-md);min-height:0}.research-view__form{display:flex;flex-direction:column;gap:var(--space-sm)}.research-view__form .form-group,.research-view__history-header.form-group,.research-view__actions .form-group{margin:0;padding:0}.research-view__textarea{min-height:calc(var(--space-2xl) * 3);resize:vertical}.research-view__providers{display:grid;gap:var(--space-xs)}.research-view__history-header{display:flex;flex-direction:column;align-items:stretch;gap:var(--space-xs)}.research-view__history-search-row{display:flex;align-items:center;gap:var(--space-xs)}.research-view__history{display:flex;flex-direction:column;gap:var(--space-xs);overflow:auto}.research-view__history-item{border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-sm);background:var(--surface);color:var(--text);text-align:left;padding:var(--space-sm);min-height:calc(var(--space-lg) * 2 + var(--space-xs));display:flex;flex-direction:column;justify-content:center;gap:var(--space-xs);transition:border-color var(--transition-fast),box-shadow var(--transition-fast),background-color var(--transition-fast)}.research-view__history-item:hover{background:var(--card-hover);border-color:var(--todo)}.research-view__history-item:focus-visible{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.research-view__history-item--active{border-color:var(--todo);box-shadow:var(--focus-ring)}.research-view__status-row{display:flex;align-items:center;gap:var(--space-xs);text-transform:capitalize}.research-view__run-title,.research-view__run-query,.research-view__run-summary{margin:0}.research-view__run-query{color:var(--text-muted)}.research-view__actions{display:flex;flex-wrap:wrap;gap:var(--space-xs);margin-top:var(--space-sm)}.research-view__citations{margin:var(--space-sm) 0 0;padding-left:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-xs)}.research-view__citations a{color:var(--text)}.research-view__error{color:var(--color-error)}.research-view__findings{display:flex;flex-direction:column;gap:var(--space-sm)}.research-view__finding{padding:var(--space-sm)}.research-view__finding h4,.research-view__finding p{margin:0}.research-view__events{margin:var(--space-sm) 0 0;padding-left:var(--space-lg)}.research-view__stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-sm)}.research-view__stat-card{border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-sm);padding:var(--space-sm);background:var(--surface)}.research-view__stat-label{color:var(--text-muted);text-transform:uppercase;font-size:.75rem}.research-view__stat-value{font-family:var(--font-mono);font-size:1rem}.research-view__state--error{border-color:var(--color-error)}@media(max-width:768px){.research-view{padding:var(--space-md)}.research-view__layout{grid-template-columns:minmax(0,1fr)}.research-view__header{flex-direction:column}.research-view__stats{grid-template-columns:minmax(0,1fr)}.research-view__history-item{min-height:calc(var(--space-lg) * 2 + var(--space-sm))}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as c,j as e}from"./vendor-react-K0fH_qHe.js";import{am as $,an as B,s as H,ao as z,ap as G,aq as J,ar as W,as as K,at as X,L as Y,S as Z}from"./index-DyXZm9QN.js";import"./vendor-xterm-DzcZoU0P.js";const ee=300,se=4e3;function re(A){const a=A?.projectId,[_,r]=c.useState([]),[i,w]=c.useState(null),[p,m]=c.useState(null),[R,S]=c.useState({available:!0}),[T,C]=c.useState(!0),[F,E]=c.useState(null),[x,q]=c.useState(""),f=c.useRef(0),j=c.useRef(0),y=c.useRef(a);c.useEffect(()=>{y.current!==a&&(y.current=a,j.current++)},[a]);const o=c.useCallback(async(t=x)=>{const n=++f.current,h=a;E(null);try{const u=await $({q:t||void 0,limit:100},h);if(n!==f.current||h!==a)return;r(u.runs),S(u.availability),i&&!u.runs.some(l=>l.id===i)&&(w(null),m(null))}catch(u){if(n!==f.current||h!==a)return;E(u instanceof Error?u.message:"Failed to load research runs")}finally{n===f.current&&C(!1)}},[a,x,i]),b=c.useCallback(async t=>{const n=await B(t,a);return m(n.run),S(n.availability),n.run},[a]);return c.useEffect(()=>{C(!0);const t=window.setTimeout(()=>{o(x)},ee);return()=>window.clearTimeout(t)},[o,x]),c.useEffect(()=>{if(!i){m(null);return}b(i)},[b,i]),c.useEffect(()=>{const t=j.current,n=()=>j.current!==t,h=a?`?projectId=${encodeURIComponent(a)}`:"";let u=!0;const l=()=>{!u||n()||(o(),i&&b(i))},P=H(`/api/events${h}`,{events:{"research:run:created":l,"research:run:updated":l,"research:run:completed":l,"research:run:failed":l,"research:run:cancelled":l},onReconnect:l}),v=window.setInterval(l,se);return()=>{u=!1,P(),window.clearInterval(v)}},[a,o,i,b]),{runs:_,selectedRun:p,selectedRunId:i,setSelectedRunId:w,availability:R,loading:T,error:F,searchQuery:x,setSearchQuery:q,refresh:o,createRun:t=>X(t,a),cancelRun:async t=>{const n=await K(t,a);return i===t&&m(n.run),await o(),n},retryRun:async t=>{const n=await W(t,a);return i===t&&m(n.run),await o(),n},exportRun:(t,n)=>J(t,n,a),createTaskFromRun:(t,n)=>G(t,{title:n},a),attachRunToTask:(t,n,h)=>z(t,{taskId:n,mode:h},a),statusCounts:_.reduce((t,n)=>(t[n.status]+=1,t),{pending:0,running:0,completed:0,failed:0,cancelled:0})}}const te=["web-search","page-fetch","github","local-docs","llm-synthesis"],ae={"web-search":"Web Search","page-fetch":"Page Fetch",github:"GitHub","local-docs":"Local Docs","llm-synthesis":"LLM Synthesis"};function le({projectId:A,addToast:a}){const{runs:_,selectedRun:r,selectedRunId:i,setSelectedRunId:w,availability:p,loading:m,error:R,searchQuery:S,setSearchQuery:T,createRun:C,cancelRun:F,retryRun:E,exportRun:x,createTaskFromRun:q,attachRunToTask:f,statusCounts:j,refresh:y}=re({projectId:A}),[o,b]=c.useState(""),[t,n]=c.useState(!1),[h,u]=c.useState(["web-search","llm-synthesis"]),[l,P]=c.useState(""),[v,L]=c.useState(null),V=p.supportedProviders??te,M=c.useMemo(()=>r?r.status:"No run selected",[r]),U=c.useMemo(()=>r?r.status==="pending"?"status-dot status-dot--pending":r.status==="running"?"status-dot status-dot--connecting":r.status==="completed"?"status-dot status-dot--online":r.status==="failed"||r.status==="cancelled"?"status-dot status-dot--error":"status-dot":"status-dot",[r]),D=p.supportedExportFormats??["markdown","json","html"],I=async(s,d,N)=>{L(s);try{await d(),a?.(N,"success"),await y()}catch(g){a?.(g instanceof Error?g.message:"Action failed","error")}finally{L(null)}},O=async s=>{if(r){L(`export-${s}`);try{const d=await x(r.id,s),N=new Blob([d.content],{type:"text/plain;charset=utf-8"}),g=URL.createObjectURL(N),k=document.createElement("a");k.href=g,k.download=d.filename,document.body.appendChild(k),k.click(),k.remove(),URL.revokeObjectURL(g),a?.(`Exported ${d.filename}`,"success")}catch(d){a?.(d instanceof Error?d.message:"Export failed","error")}finally{L(null)}}},Q=async()=>{if(o.trim()){n(!0);try{const s=await C({query:o.trim(),providers:h});w(s.run.id),b(""),a?.("Research run created","success"),await y()}catch(s){a?.(s instanceof Error?s.message:"Failed to create run","error")}finally{n(!1)}}};return e.jsxs("section",{className:"research-view","aria-label":"Research view",children:[e.jsxs("header",{className:"research-view__header",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"research-view__title",children:"Research"}),e.jsx("p",{className:"research-view__subtitle",children:"Create and track research runs with cited findings."})]}),e.jsx("button",{className:"btn",type:"button",onClick:()=>void y(),children:"Refresh"})]}),p.available?e.jsxs("div",{className:"research-view__layout",children:[e.jsxs("aside",{className:"research-view__sidebar card",children:[e.jsxs("div",{className:"research-view__form",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"research-query",children:"Query"}),e.jsx("textarea",{id:"research-query",className:"input research-view__textarea",value:o,onChange:s=>b(s.target.value)})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Providers"}),e.jsx("div",{className:"research-view__providers",children:V.map(s=>e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:h.includes(s),onChange:()=>{u(d=>d.includes(s)?d.filter(N=>N!==s):[...d,s])}}),e.jsx("span",{children:ae[s]??s})]},s))})]}),e.jsxs("button",{className:"btn btn-primary",type:"button",disabled:!o.trim()||t,onClick:()=>void Q(),children:[t?e.jsx(Y,{className:"animate-spin",size:14}):null,"Create Run"]})]}),e.jsxs("div",{className:"research-view__history-header form-group",children:[e.jsx("label",{htmlFor:"research-run-search",children:"Search"}),e.jsxs("div",{className:"research-view__history-search-row",children:[e.jsx(Z,{size:14}),e.jsx("input",{id:"research-run-search",className:"input",placeholder:"Search runs",value:S,onChange:s=>T(s.target.value)})]})]}),e.jsx("div",{className:"research-view__history","data-testid":"research-state-running",children:_.map(s=>e.jsxs("button",{className:`research-view__history-item${i===s.id?" research-view__history-item--active":""}`,onClick:()=>w(s.id),children:[e.jsx("span",{className:"card-id",children:s.id}),e.jsx("span",{children:s.title})]},s.id))})]}),e.jsxs("div",{className:"research-view__reader card",children:[m&&e.jsx("p",{"data-testid":"research-state-loading",children:"Loading research runs…"}),!m&&R&&e.jsx("p",{"data-testid":"research-state-error",children:R}),!m&&!R&&_.length===0&&e.jsx("p",{"data-testid":"research-state-empty",children:"No research runs yet"}),r&&e.jsxs("div",{children:[e.jsxs("div",{className:"research-view__status-row",children:[e.jsx("span",{className:U}),e.jsx("strong",{children:M})]}),e.jsx("h3",{className:"research-view__run-title",children:r.title}),e.jsx("p",{className:"research-view__run-query",children:r.query}),e.jsx("p",{className:"research-view__run-summary","data-testid":"research-state-results",children:r.results?.summary??"No summary yet."}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",disabled:v==="cancel",onClick:()=>void I("cancel",()=>F(r.id),"Run cancelled"),children:"Cancel"}),e.jsx("button",{className:"btn",type:"button",disabled:v==="retry",onClick:()=>void I("retry",()=>E(r.id),"Run retried"),children:"Retry"}),D.includes("markdown")&&e.jsx("button",{className:"btn",type:"button",disabled:v==="export-markdown",onClick:()=>void O("markdown"),children:"Export MD"}),D.includes("json")&&e.jsx("button",{className:"btn",type:"button",disabled:v==="export-json",onClick:()=>void O("json"),children:"Export JSON"}),D.includes("html")&&e.jsx("button",{className:"btn",type:"button",disabled:v==="export-html",onClick:()=>void O("html"),children:"Export HTML"})]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn btn-primary",type:"button",disabled:v==="create-task",onClick:()=>void I("create-task",()=>q(r.id,`Research: ${r.title}`),"Task created from research"),children:"Create Task"}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"research-task-id",children:"Task ID"}),e.jsx("input",{id:"research-task-id",className:"input",placeholder:"Task ID",value:l,onChange:s=>P(s.target.value)})]}),e.jsx("button",{className:"btn",type:"button",disabled:!l.trim()||v==="attach-task",onClick:()=>void I("attach-task",()=>f(r.id,l.trim(),"document"),"Attached to task"),children:"Attach to Task"})]}),r.error&&e.jsx("p",{className:"research-view__error",children:r.error}),Array.isArray(r.results?.findings)&&r.results.findings.length>0&&e.jsx("div",{className:"research-view__findings",children:r.results.findings.map(s=>e.jsxs("article",{className:"research-view__finding card",children:[e.jsx("h4",{children:s.heading}),e.jsx("p",{children:s.content})]},s.heading))}),Array.isArray(r.results?.citations)&&r.results.citations.length>0&&e.jsx("ul",{className:"research-view__citations",children:r.results.citations.map(s=>e.jsx("li",{children:e.jsx("a",{href:s,target:"_blank",rel:"noreferrer",children:s})},s))}),r.events.length>0&&e.jsxs("details",{children:[e.jsx("summary",{children:"Run history"}),e.jsx("ul",{className:"research-view__events",children:r.events.map(s=>e.jsx("li",{children:s.message},s.id))})]})]}),!r&&_.length>0&&e.jsx("p",{children:"Select a run to view details."}),e.jsxs("div",{className:"research-view__stats",children:[e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Running"}),e.jsx("div",{className:"research-view__stat-value",children:j.running})]}),e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Completed"}),e.jsx("div",{className:"research-view__stat-value",children:j.completed})]}),e.jsxs("div",{className:"research-view__stat-card",children:[e.jsx("div",{className:"research-view__stat-label",children:"Failed"}),e.jsx("div",{className:"research-view__stat-value",children:j.failed})]})]})]})]}):e.jsxs("div",{className:"research-view__state research-view__state--error card","data-testid":"research-state-unavailable",children:[e.jsx("p",{children:p.reason??"Research is unavailable for this project."}),p.setupInstructions&&e.jsx("p",{children:p.setupInstructions})]})]})}export{le as ResearchView};
|