@runfusion/fusion 0.38.0 → 0.39.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.
Files changed (59) hide show
  1. package/dist/bin.js +3325 -858
  2. package/dist/client/.vite/manifest.json +58 -58
  3. package/dist/client/assets/{AgentDetailView-CquLtIia.js → AgentDetailView-nS4sABBv.js} +1 -1
  4. package/dist/client/assets/{AgentPermissionPolicyEditor-Dk-oEs1X.js → AgentPermissionPolicyEditor-DiYAo51R.js} +1 -1
  5. package/dist/client/assets/{AgentsView-BZVOpQ05.js → AgentsView-VbUsJLma.js} +3 -3
  6. package/dist/client/assets/ChatView-B1AMky9x.js +6 -0
  7. package/dist/client/assets/{DevServerView-BRA00XoT.js → DevServerView-CyFdAcCd.js} +1 -1
  8. package/dist/client/assets/{DirectoryPicker-D496NTjZ.js → DirectoryPicker-C7v2Esic.js} +1 -1
  9. package/dist/client/assets/{DocumentsView-DIRlgdeB.js → DocumentsView-P_YIsnO0.js} +1 -1
  10. package/dist/client/assets/{EvalsView-By5mtr80.js → EvalsView-2zyH0dWG.js} +1 -1
  11. package/dist/client/assets/{ExperimentalAgentOnboardingModal-Br57oNdX.js → ExperimentalAgentOnboardingModal-DoRPGkfN.js} +1 -1
  12. package/dist/client/assets/{GoalsView-B65urz9k.css → GoalsView-Dky8vDoG.css} +1 -1
  13. package/dist/client/assets/GoalsView-l0PVSxK4.js +2 -0
  14. package/dist/client/assets/{InsightsView-Hm7vX2lr.js → InsightsView-BZKu5-C3.js} +1 -1
  15. package/dist/client/assets/{MemoryView-BLozyYur.js → MemoryView-CYBNC_h8.js} +1 -1
  16. package/dist/client/assets/{NodesView-bXC6WoE2.js → NodesView-CQ63uWC8.js} +1 -1
  17. package/dist/client/assets/{PiExtensionsManager-DEiqcMkx.js → PiExtensionsManager-BNXxlpb6.js} +1 -1
  18. package/dist/client/assets/{PluginManager-l4224zxk.js → PluginManager-DejpEyl7.js} +1 -1
  19. package/dist/client/assets/{ResearchView-CpsR1Q56.js → ResearchView-B4u2YieX.js} +1 -1
  20. package/dist/client/assets/{SecretsView-Bwme1zZI.js → SecretsView-DvMMG_rf.js} +1 -1
  21. package/dist/client/assets/SettingsModal-986SEzVN.css +1 -0
  22. package/dist/client/assets/SettingsModal-C2mfeKp1.js +31 -0
  23. package/dist/client/assets/{SettingsModal-32vUNWRe.js → SettingsModal-Dmz2aH3c.js} +1 -1
  24. package/dist/client/assets/{SetupWizardModal-BFD9E0H_.js → SetupWizardModal-BiIFP3De.js} +1 -1
  25. package/dist/client/assets/{SkillsView-CZMLY7F_.js → SkillsView-CRARYL_G.js} +1 -1
  26. package/dist/client/assets/{StashRecoveryView-jgZeWbZo.js → StashRecoveryView-DHj0O6sE.js} +1 -1
  27. package/dist/client/assets/{TodoView-DXdnOymj.js → TodoView-CjyU1h-B.js} +1 -1
  28. package/dist/client/assets/{dashboard-view-H8SnaCPP.js → dashboard-view-BVckVLAO.js} +1 -1
  29. package/dist/client/assets/{folder-open-Dh5_gv6L.js → folder-open-CJgBSqdA.js} +1 -1
  30. package/dist/client/assets/index-BonLYFW-.js +742 -0
  31. package/dist/client/assets/index-nzIVQsA_.css +1 -0
  32. package/dist/client/assets/{upload-ntU2YHPl.js → upload-hsiV4Ixv.js} +1 -1
  33. package/dist/client/assets/{users-BWK61s9U.js → users-D63HpHlZ.js} +1 -1
  34. package/dist/client/index.html +2 -2
  35. package/dist/client/version.json +1 -1
  36. package/dist/droid-cli/package.json +1 -1
  37. package/dist/extension.js +3073 -785
  38. package/dist/pi-claude-cli/package.json +1 -1
  39. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  40. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  41. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  42. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +38 -4
  43. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  44. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  45. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  46. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  47. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  48. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  49. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  50. package/package.json +1 -1
  51. package/skill/fusion/SKILL.md +1 -1
  52. package/skill/fusion/references/extension-tools.md +47 -1
  53. package/skill/fusion/references/fusion-capabilities.md +6 -1
  54. package/dist/client/assets/ChatView-CErtz86Y.js +0 -6
  55. package/dist/client/assets/GoalsView-COI14CWJ.js +0 -1
  56. package/dist/client/assets/SettingsModal-D_uIvf6n.css +0 -1
  57. package/dist/client/assets/SettingsModal-DdrXxMPW.js +0 -31
  58. package/dist/client/assets/index-B9hAW3eU.css +0 -1
  59. package/dist/client/assets/index-w1dPHtmq.js +0 -742
@@ -1 +1 @@
1
- import{r as g,j as e}from"./vendor-react-K0fH_qHe.js";import{v as ye,eM as je,eN as Y,s as Ne,X as Z,aB as Se,a_ as ve,J as T,b6 as ee,_ as se,R as we,eO as Ce,ax as Ie,eP as Pe,eQ as $e,cK as Re,eR as Ee,eS as ke,eT as Be,eU as Le,eV as te,cH as Ae,eW as Fe}from"./index-w1dPHtmq.js";import{D as De}from"./DirectoryPicker-D496NTjZ.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";import"./folder-open-Dh5_gv6L.js";const le="fusion-plugin-agent-browser",ne={enabled:{type:"boolean",label:"Enable Agent Browser",group:"General"},installChannel:{type:"enum",label:"Install Channel",enumValues:["stable","beta","nightly"],defaultValue:"stable",group:"General"},commandTimeoutMs:{type:"number",label:"Command Timeout (ms)",defaultValue:12e4,group:"General"},headlessMode:{type:"boolean",label:"Headless Mode",defaultValue:!0,group:"Browser"},allowedDomains:{type:"array",label:"Allowed Domains",itemType:"string",group:"Browser"},promptExecutorSystem:{type:"string",label:"Executor System Prompt",multiline:!0,group:"Prompt Contributions"},promptExecutorTask:{type:"string",label:"Executor Task Prompt",multiline:!0,group:"Prompt Contributions"},promptTriage:{type:"string",label:"Triage Prompt",multiline:!0,group:"Prompt Contributions"},promptReviewer:{type:"string",label:"Reviewer Prompt",multiline:!0,group:"Prompt Contributions"},promptHeartbeat:{type:"string",label:"Heartbeat Prompt",multiline:!0,group:"Prompt Contributions"},skillExposure:{type:"enum",label:"Skill Exposure",enumValues:["none","selected","all"],defaultValue:"selected",group:"Skills"}},ae=[{id:"fusion-plugin-hermes-runtime",name:"Hermes Runtime",description:"Runtime provider for Hermes CLI-backed execution.",category:"runtime",path:"./plugins/fusion-plugin-hermes-runtime",experimental:!0},{id:"fusion-plugin-paperclip-runtime",name:"Paperclip Runtime",description:"Runtime provider for Paperclip agent connections.",category:"runtime",path:"./plugins/fusion-plugin-paperclip-runtime"},{id:"fusion-plugin-openclaw-runtime",name:"OpenClaw Runtime",description:"Runtime provider for OpenClaw execution.",category:"runtime",path:"./plugins/fusion-plugin-openclaw-runtime",experimental:!0},{id:"fusion-plugin-droid-runtime",name:"Droid Runtime",description:"Runtime provider for Droid CLI execution.",category:"runtime",path:"./plugins/fusion-plugin-droid-runtime",experimental:!0},{id:"fusion-plugin-dependency-graph",name:"Dependency Graph",description:"Dashboard plugin for task dependency graph visualization.",category:"integration",path:"./plugins/fusion-plugin-dependency-graph"},{id:"fusion-plugin-reports",name:"Reports",description:"View report history, compare runs side-by-side, and export standalone HTML summaries.",category:"integration",path:"./plugins/fusion-plugin-reports"},{id:"fusion-plugin-whatsapp-chat",name:"WhatsApp Chat",description:"Pairs to WhatsApp Web (multi-device) with QR or pairing code, then bridges direct chats to a Fusion agent.",category:"integration",path:"./plugins/fusion-plugin-whatsapp-chat"},{id:"fusion-plugin-cli-printing-press",name:"CLI Printing Press",description:"Guided wizard for drafting external service CLI definitions.",category:"integration",path:"./plugins/fusion-plugin-cli-printing-press"},{id:le,name:"Agent Browser",description:"Built-in integration metadata. Package install support lands in FN-3101.",category:"integration",hasSetup:!0}],I={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function Oe(i){const c=i.settingsSchema,h=c&&Object.keys(c).length>0;return i.id!==le?h?c:void 0:h?{...ne,...c}:ne}function ze(i){const c=new Map,h=[];for(const[x,f]of Object.entries(i))if(f.group){const N=c.get(f.group)??[];N.push([x,f]),c.set(f.group,N)}else h.push([x,f]);return{grouped:c,ungrouped:h}}function ie(i,c="plugin-error-text"){return i.state!=="error"||!i.error?null:e.jsx("p",{className:c,title:i.error,children:i.error})}function We({addToast:i,projectId:c}){const[h,x]=g.useState([]),[f,N]=g.useState(!0),[re,P]=g.useState(!1),[w,$]=g.useState(""),[B,L]=g.useState(!1),[A,F]=g.useState(!1),[S,D]=g.useState(null),[r,R]=g.useState(null),[p,b]=g.useState({}),[ce,O]=g.useState(!1),[z,U]=g.useState(null),[oe,E]=g.useState({}),[ue,G]=g.useState(null),[C,_]=g.useState(null),{confirm:de}=ye(),m=g.useCallback(async()=>{try{N(!0);const s=await je(c);x(s)}catch(s){i(`Failed to load plugins: ${s instanceof Error?s.message:String(s)}`,"error")}finally{N(!1)}},[c,i]);g.useEffect(()=>{m()},[m]),g.useEffect(()=>{const s=ae.filter(o=>o.hasSetup&&h.some(l=>l.id===o.id));if(s.length===0)return;let n=!1;return Promise.all(s.map(async o=>{try{const l=await Y(o.id,c);if(n)return;E(u=>({...u,[o.id]:l}))}catch{if(n)return;E(l=>({...l,[o.id]:{hasSetup:!0,setupCheckDeferred:!0,deferredReason:"plugin-not-started",pluginState:"installed"}}))}})),()=>{n=!0}},[h,c]);const pe=g.useRef([]);pe.current=h,g.useEffect(()=>{const s=c?`?projectId=${encodeURIComponent(c)}`:"",n=o=>{try{const l=JSON.parse(o.data);if(l.scope==="project"&&(l.projectId??c)!==c)return;switch(l.transition){case"installing":case"enabled":case"disabled":case"settings-updated":x(u=>{const a=u.findIndex(t=>t.id===l.pluginId);if(a>=0){const t=[...u];return t[a]={...t[a],enabled:l.enabled,state:l.state,settings:l.settings,error:l.error},t}else return m(),u});break;case"state-changed":x(u=>{const a=u.findIndex(t=>t.id===l.pluginId);if(a>=0){const t=[...u];return t[a]={...t[a],state:l.state,error:l.error},t}return u});break;case"uninstalled":x(u=>u.filter(a=>a.id!==l.pluginId));break;case"error":x(u=>{const a=u.findIndex(t=>t.id===l.pluginId);if(a>=0){const t=[...u];return t[a]={...t[a],state:l.state,error:l.error},t}return u});break}}catch{}};return Ne(`/api/events${s}`,{events:{"plugin:lifecycle":n},onReconnect:()=>{m()}})},[c,m]);const M=async()=>{if(!w.trim()){i("Please enter a plugin path","error");return}try{L(!0),await te({path:w,...A?{aiScanOnLoad:!0}:{}},c),i("Plugin installed globally","success"),P(!1),$(""),F(!1),await m()}catch(s){i(`Failed to install plugin: ${s instanceof Error?s.message:String(s)}`,"error")}finally{L(!1)}},ge=async s=>{if(!s.path){i(`${s.name} is built in and does not have an installable package yet`,"warning");return}try{U(s.id),await te({path:s.path},c),i(`${s.name} installed globally`,"success"),await m()}catch(n){i(`Failed to install ${s.name}: ${n instanceof Error?n.message:String(n)}`,"error")}finally{U(null)}},V=async s=>{try{_(s.id);const n=await Fe(s.id,c);if(!n.success){i(`Failed to install ${s.name} setup: ${n.error??"unknown error"}`,"error");return}i(`${s.name} setup installed`,"success"),G(s.id);const o=await Y(s.id,c);E(l=>({...l,[s.id]:o}))}catch(n){i(`Failed to install ${s.name} setup: ${n instanceof Error?n.message:String(n)}`,"error")}finally{_(null),G(null)}},q=async s=>{try{const n=await Be(s.id,c);if(n.state==="error"){i(`Failed to enable ${s.name}: ${n.error??"Unknown error"}`,"error"),await m();return}i(`${s.name} enabled for this project`,"success"),await m()}catch(n){i(`Failed to enable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},H=async s=>{try{await ke(s.id,c),i(`${s.name} disabled for this project`,"success"),await m()}catch(n){i(`Failed to disable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},W=async s=>{try{D(s.id),await Ee(s.id,c),i(`${s.name} reloaded`,"success"),await m()}catch(n){i(`Failed to reload plugin: ${n instanceof Error?n.message:String(n)}`,"error")}finally{D(null)}},J=async s=>{if(await de({title:"Uninstall Plugin Globally",message:`Are you sure you want to uninstall "${s.name}" globally (all projects)?`,danger:!0}))try{await Le(s.id,c),i(`${s.name} uninstalled globally`,"success"),await m(),R(null)}catch(o){i(`Failed to uninstall plugin: ${o instanceof Error?o.message:String(o)}`,"error")}},me=async(s,n)=>{try{await Pe(s.id,{aiScanOnLoad:n},c),i(`AI scan on load ${n?"enabled":"disabled"}`,"success"),await m()}catch(o){i(`Failed to update plugin: ${o instanceof Error?o.message:String(o)}`,"error")}},he=async s=>{try{await $e(s.id,c),i(`${s.name} rescanned`,"success"),await m()}catch(n){i(`Failed to rescan plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},k=async s=>{R(s);try{O(!0);const n=await Ae(s.id,c);b(n)}catch{b({})}finally{O(!1)}},be=async()=>{if(r)try{await Re(r.id,p,c),i("Settings saved","success")}catch(s){i(`Failed to save settings: ${s instanceof Error?s.message:String(s)}`,"error")}};if(r)return e.jsxs("div",{className:"plugin-manager-detail","data-testid":"plugin-manager-detail",children:[e.jsxs("div",{className:"plugin-manager-detail-header",children:[e.jsx("button",{className:"btn-icon",onClick:()=>R(null),"aria-label":"Back to plugin list",children:e.jsx(Z,{size:16})}),e.jsxs("div",{className:"plugin-detail-title",children:[e.jsxs("div",{className:"plugin-detail-title-copy",children:[e.jsx("h4",{className:"plugin-detail-name",children:r.name}),ie(r,"plugin-error-text plugin-error-text--detail")]}),e.jsx("span",{className:"plugin-state-badge",style:{color:I[r.state]||I.installed},children:r.state})]})]}),e.jsxs("div",{className:"plugin-detail-content",children:[e.jsxs("div",{className:"plugin-detail-card",children:[r.description&&e.jsx("p",{className:"plugin-description",children:r.description}),r.author&&e.jsxs("p",{className:"plugin-detail-meta-row",children:[e.jsx("span",{className:"text-muted",children:"Author:"}),r.author]}),r.homepage&&e.jsxs("p",{className:"plugin-detail-meta-row plugin-homepage",children:[e.jsx("span",{className:"text-muted",children:"Homepage:"}),e.jsxs("a",{href:r.homepage,target:"_blank",rel:"noopener noreferrer",children:[r.homepage,e.jsx(Se,{size:12})]})]}),e.jsxs("p",{className:"plugin-detail-meta-row",children:[e.jsx("span",{className:"text-muted",children:"Version:"}),r.version]})]}),e.jsxs("div",{className:"plugin-detail-card",children:[e.jsx("h5",{className:"plugin-detail-section-heading",children:"Security Scan"}),e.jsxs("div",{className:"plugin-security-row",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:!!r.aiScanOnLoad,onChange:s=>void me(r,s.target.checked)}),"Enable AI scan before load/reload"]}),e.jsxs("button",{className:"btn btn-secondary btn-sm",onClick:()=>void he(r),children:[e.jsx(ve,{size:14})," Rescan and Reload"]})]}),e.jsx("p",{className:"text-muted",children:"Turning this on only updates configuration. Use Rescan and Reload to run it now."}),r.lastSecurityScan?e.jsxs("div",{className:"plugin-security-results",children:[e.jsxs("div",{className:"plugin-security-header",children:[e.jsx("span",{className:`plugin-state-badge plugin-security-badge plugin-security-badge--${r.lastSecurityScan.verdict}`,children:r.lastSecurityScan.verdict}),e.jsx("span",{className:"text-muted",children:r.lastSecurityScan.scannedAt})]}),e.jsx("p",{className:"plugin-security-summary",children:r.lastSecurityScan.summary}),e.jsxs("details",{children:[e.jsxs("summary",{children:["Findings (",r.lastSecurityScan.findings.length,")"]}),e.jsx("ul",{className:"plugin-security-findings",children:r.lastSecurityScan.findings.map((s,n)=>e.jsxs("li",{children:[e.jsx("strong",{children:s.severity})," ",s.category," — ",s.file,": ",s.reason]},`${s.file}-${n}`))})]})]}):e.jsx("p",{className:"text-muted",children:"No security scan has been run yet."})]}),e.jsxs("div",{className:"plugin-detail-card",children:[e.jsx("h5",{className:"plugin-detail-section-heading",children:"Settings"}),ce?e.jsx("p",{className:"text-muted",children:"Loading..."}):(()=>{const s=Oe(r);return s&&Object.keys(s).length>0?e.jsxs("div",{className:"plugin-settings-form",children:[(()=>{const{grouped:n,ungrouped:o}=ze(s),l=[];o.length>0&&l.push({title:null,entries:o});for(const[u,a]of n.entries())l.push({title:u,entries:a});return l.map(u=>e.jsxs("div",{className:u.title?"plugin-settings-group":void 0,children:[u.title&&e.jsx("h6",{className:"plugin-settings-group-heading",children:u.title}),u.entries.map(([a,t])=>{const y=`setting-${a}-help`;return e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:`setting-${a}`,children:[t.label||a,t.required&&" *"]}),t.type==="string"&&!t.multiline&&e.jsx("input",{className:"input",type:"text",id:`setting-${a}`,value:p[a]??"",onChange:d=>b({...p,[a]:d.target.value}),placeholder:t.description,"aria-describedby":t.description&&!t.required?y:void 0}),t.type==="string"&&t.multiline&&e.jsx("textarea",{className:"input",id:`setting-${a}`,rows:4,value:p[a]??"",onChange:d=>b({...p,[a]:d.target.value}),placeholder:t.description,"aria-describedby":t.description&&!t.required?y:void 0}),t.type==="password"&&e.jsx("input",{className:"input",type:"password",id:`setting-${a}`,value:p[a]??"",onChange:d=>b({...p,[a]:d.target.value}),placeholder:t.description,"aria-describedby":t.description&&!t.required?y:void 0}),t.type==="number"&&e.jsx("input",{className:"input",type:"number",id:`setting-${a}`,value:p[a]??"",onChange:d=>b({...p,[a]:Number(d.target.value)}),"aria-describedby":t.description&&!t.required?y:void 0}),t.type==="boolean"&&e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:p[a]??!1,onChange:d=>b({...p,[a]:d.target.checked})}),t.description]}),t.type==="enum"&&e.jsxs("select",{className:"select",id:`setting-${a}`,value:p[a]??"",onChange:d=>b({...p,[a]:d.target.value}),"aria-describedby":t.description&&!t.required?y:void 0,children:[e.jsx("option",{value:"",children:"Select..."}),t.enumValues?.map(d=>e.jsx("option",{value:d,children:d},d))]}),t.type==="array"&&e.jsxs("div",{className:"plugin-settings-array",children:[p[a]?.map((d,j)=>e.jsxs("div",{className:"plugin-settings-array-item",children:[e.jsx("input",{className:"input",type:t.itemType==="number"?"number":"text",value:d??"",onChange:Q=>{const v=Q.target.value,X=[...p[a]||[]];X[j]=t.itemType==="number"?Number(v):v,b({...p,[a]:X})}}),e.jsx("button",{className:"btn-icon",onClick:()=>{const v=[...p[a]||[]];v.splice(j,1),b({...p,[a]:v})},"aria-label":"Remove item",children:e.jsx(Z,{size:14})})]},j)),e.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const d=p[a]||[],j=t.itemType==="number"?0:"";b({...p,[a]:[...d,j]})},children:[e.jsx(T,{size:14})," Add Item"]})]}),t.description&&!t.required&&!t.multiline&&e.jsx("span",{id:y,className:"form-help",children:t.description})]},a)})]},u.title??"ungrouped"))})(),e.jsx("button",{className:"btn btn-primary",onClick:be,children:"Save Settings"})]}):e.jsx("p",{className:"text-muted",children:"No configurable settings."})})()]}),e.jsxs("div",{className:"plugin-detail-actions",children:[r.state==="started"&&e.jsxs("button",{className:"btn btn-secondary",onClick:()=>W(r),disabled:S===r.id,children:[e.jsx(ee,{size:14,className:S===r.id?"spin":""}),S===r.id?"Reloading...":"Reload"]}),r.enabled?e.jsx("button",{className:"btn btn-secondary",onClick:()=>H(r),children:"Disable in Project"}):e.jsx("button",{className:"btn btn-primary",onClick:()=>q(r),children:"Enable in Project"}),e.jsxs("button",{className:"btn btn-danger",onClick:()=>J(r),children:[e.jsx(se,{size:14})," Uninstall Globally"]})]})]})]});const xe=new Map(h.map(s=>[s.id,s])),K=h,fe=()=>e.jsxs("section",{className:"plugin-builtins-section","aria-label":"Built-in Plugins",children:[e.jsxs("div",{className:"plugin-builtins-header",children:[e.jsx("h4",{className:"plugin-builtins-heading",children:"Built-in Plugins"}),e.jsx("p",{className:"plugin-builtins-description",children:"Built-in plugin catalog for runtimes and integrations."})]}),e.jsx("div",{className:"plugin-builtins-list","aria-label":"Built-in plugin recommendations",children:ae.map(s=>{const n=xe.get(s.id),o=!!n,l=oe[s.id],u=!!(l&&"setupCheckDeferred"in l&&l.setupCheckDeferred),a=l&&"status"in l?l.status:void 0,t=o&&s.hasSetup&&l?.hasSetup&&!u&&n?.state==="started"&&(a==="not-installed"||a==="error"),y=o&&l?.hasSetup&&a==="installed",d=ue===s.id,j=!s.path;return e.jsxs("div",{className:"plugin-builtins-item",children:[e.jsxs("div",{className:"plugin-builtins-meta",children:[e.jsx("span",{className:"plugin-builtins-name",children:s.name}),s.experimental&&e.jsx("span",{className:"plugin-builtins-runtime-badge",children:"Experimental"}),e.jsx("span",{className:"plugin-builtins-runtime-badge",children:s.category}),e.jsx("span",{className:`plugin-builtins-status ${o?"plugin-builtins-status--installed":"plugin-builtins-status--available"}`,children:o?"Installed":j?"Built in":"Not installed"}),t&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--warning",children:"Setup required"}),y&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--ready",children:"Setup ready"}),d&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--pending",children:"Checking setup..."}),u&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--deferred",children:"Start plugin to check setup"}),e.jsx("span",{className:"plugin-builtins-description-text",children:s.description})]}),j?o&&t?e.jsx("button",{className:"btn btn-primary btn-sm",onClick:()=>void V(s),disabled:C===s.id||d,children:C===s.id?"Setting up...":"Install Setup"}):o&&n?e.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>void k(n),children:"Manage"}):e.jsx("span",{className:"plugin-builtins-metadata-only",children:"Built-in metadata only"}):e.jsx("button",{className:`btn ${o&&!t?"btn-secondary":"btn-primary"} btn-sm`,onClick:()=>{if(!o){ge(s);return}if(t){V(s);return}n&&k(n)},disabled:z===s.id||C===s.id||d,children:o?t?C===s.id?"Setting up...":"Install Setup":"Manage":z===s.id?"Installing...":`Install ${s.name}`})]},s.id)})})]});return e.jsxs("div",{className:"plugin-manager","data-testid":"plugin-manager",children:[e.jsxs("div",{className:"plugin-manager-header",children:[e.jsx("span",{className:"plugin-manager-header-title",children:"Installed Plugins"}),e.jsxs("div",{className:"plugin-manager-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:m,title:"Refresh","aria-label":"Refresh plugin list",children:[e.jsx(we,{size:14,className:f?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>P(!0),children:[e.jsx(T,{size:14})," Install"]})]})]}),re&&e.jsxs("div",{className:"plugin-install-form",children:[e.jsxs("p",{className:"plugin-install-hint",children:["Browse to a plugin package root (contains ",e.jsx("code",{children:"manifest.json"}),") or a built ",e.jsx("code",{children:"dist"})," directory."]}),e.jsx(De,{value:w,onChange:$,placeholder:"Absolute path to plugin directory or dist folder",onInputKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),M())}}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:A,onChange:s=>F(s.target.checked)}),"Enable AI security scan on load"]}),e.jsxs("div",{className:"plugin-install-actions",children:[e.jsx("button",{className:"btn btn-primary",onClick:M,disabled:B||!w.trim(),children:B?"Installing...":"Install Plugin Globally"}),e.jsx("button",{className:"btn btn-secondary",onClick:()=>{P(!1),$("")},children:"Cancel"})]})]}),f?e.jsx("div",{className:"settings-empty-state",children:"Loading plugins..."}):e.jsxs(e.Fragment,{children:[K.length===0?e.jsxs("div",{className:"settings-empty-state",children:[e.jsx(Ce,{size:32,className:"text-muted"}),e.jsx("p",{children:"No plugins installed."}),e.jsx("p",{className:"text-muted",children:"Install a plugin to get started, or use the built-in catalog below."})]}):e.jsx("div",{className:"plugin-list",children:K.map(s=>e.jsxs("div",{className:"plugin-item",children:[e.jsx("div",{className:"plugin-info",children:e.jsxs("div",{className:"plugin-copy",children:[e.jsxs("div",{className:"plugin-copy-header",children:[e.jsx("span",{className:"plugin-name",children:s.name}),e.jsxs("span",{className:"plugin-version text-muted",children:["v",s.version]}),e.jsx("span",{className:"plugin-state-badge",style:{color:I[s.state]||I.installed},children:s.state})]}),ie(s)]})}),e.jsxs("div",{className:"plugin-actions",children:[s.state==="started"&&e.jsx("button",{className:"btn-icon",onClick:()=>W(s),disabled:S===s.id,title:"Reload",children:e.jsx(ee,{size:14,className:S===s.id?"spin":""})}),e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>s.enabled?H(s):q(s),"aria-label":`${s.enabled?"Disable":"Enable"} ${s.name}`}),e.jsx("span",{className:"toggle-slider"})]}),e.jsx("button",{className:"btn-icon",onClick:()=>k(s),title:"Settings",children:e.jsx(Ie,{size:14})}),e.jsx("button",{className:"btn-icon",onClick:()=>J(s),title:"Uninstall globally",children:e.jsx(se,{size:14})})]})]},s.id))}),fe()]})]})}export{ne as AGENT_BROWSER_SETTINGS_SCHEMA,le as BUILTIN_AGENT_BROWSER_PLUGIN_ID,We as PluginManager,I as STATE_COLORS};
1
+ import{r as g,j as e}from"./vendor-react-K0fH_qHe.js";import{v as ye,eM as je,eN as Y,s as Ne,X as Z,aB as Se,a_ as ve,J as T,b6 as ee,_ as se,R as we,eO as Ce,ax as Ie,eP as Pe,eQ as $e,cK as Re,eR as Ee,eS as ke,eT as Be,eU as Le,eV as te,cH as Ae,eW as Fe}from"./index-BonLYFW-.js";import{D as De}from"./DirectoryPicker-C7v2Esic.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";import"./folder-open-CJgBSqdA.js";const le="fusion-plugin-agent-browser",ne={enabled:{type:"boolean",label:"Enable Agent Browser",group:"General"},installChannel:{type:"enum",label:"Install Channel",enumValues:["stable","beta","nightly"],defaultValue:"stable",group:"General"},commandTimeoutMs:{type:"number",label:"Command Timeout (ms)",defaultValue:12e4,group:"General"},headlessMode:{type:"boolean",label:"Headless Mode",defaultValue:!0,group:"Browser"},allowedDomains:{type:"array",label:"Allowed Domains",itemType:"string",group:"Browser"},promptExecutorSystem:{type:"string",label:"Executor System Prompt",multiline:!0,group:"Prompt Contributions"},promptExecutorTask:{type:"string",label:"Executor Task Prompt",multiline:!0,group:"Prompt Contributions"},promptTriage:{type:"string",label:"Triage Prompt",multiline:!0,group:"Prompt Contributions"},promptReviewer:{type:"string",label:"Reviewer Prompt",multiline:!0,group:"Prompt Contributions"},promptHeartbeat:{type:"string",label:"Heartbeat Prompt",multiline:!0,group:"Prompt Contributions"},skillExposure:{type:"enum",label:"Skill Exposure",enumValues:["none","selected","all"],defaultValue:"selected",group:"Skills"}},ae=[{id:"fusion-plugin-hermes-runtime",name:"Hermes Runtime",description:"Runtime provider for Hermes CLI-backed execution.",category:"runtime",path:"./plugins/fusion-plugin-hermes-runtime",experimental:!0},{id:"fusion-plugin-paperclip-runtime",name:"Paperclip Runtime",description:"Runtime provider for Paperclip agent connections.",category:"runtime",path:"./plugins/fusion-plugin-paperclip-runtime"},{id:"fusion-plugin-openclaw-runtime",name:"OpenClaw Runtime",description:"Runtime provider for OpenClaw execution.",category:"runtime",path:"./plugins/fusion-plugin-openclaw-runtime",experimental:!0},{id:"fusion-plugin-droid-runtime",name:"Droid Runtime",description:"Runtime provider for Droid CLI execution.",category:"runtime",path:"./plugins/fusion-plugin-droid-runtime",experimental:!0},{id:"fusion-plugin-dependency-graph",name:"Dependency Graph",description:"Dashboard plugin for task dependency graph visualization.",category:"integration",path:"./plugins/fusion-plugin-dependency-graph"},{id:"fusion-plugin-reports",name:"Reports",description:"View report history, compare runs side-by-side, and export standalone HTML summaries.",category:"integration",path:"./plugins/fusion-plugin-reports"},{id:"fusion-plugin-whatsapp-chat",name:"WhatsApp Chat",description:"Pairs to WhatsApp Web (multi-device) with QR or pairing code, then bridges direct chats to a Fusion agent.",category:"integration",path:"./plugins/fusion-plugin-whatsapp-chat"},{id:"fusion-plugin-cli-printing-press",name:"CLI Printing Press",description:"Guided wizard for drafting external service CLI definitions.",category:"integration",path:"./plugins/fusion-plugin-cli-printing-press"},{id:le,name:"Agent Browser",description:"Built-in integration metadata. Package install support lands in FN-3101.",category:"integration",hasSetup:!0}],I={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function Oe(i){const c=i.settingsSchema,h=c&&Object.keys(c).length>0;return i.id!==le?h?c:void 0:h?{...ne,...c}:ne}function ze(i){const c=new Map,h=[];for(const[x,f]of Object.entries(i))if(f.group){const N=c.get(f.group)??[];N.push([x,f]),c.set(f.group,N)}else h.push([x,f]);return{grouped:c,ungrouped:h}}function ie(i,c="plugin-error-text"){return i.state!=="error"||!i.error?null:e.jsx("p",{className:c,title:i.error,children:i.error})}function We({addToast:i,projectId:c}){const[h,x]=g.useState([]),[f,N]=g.useState(!0),[re,P]=g.useState(!1),[w,$]=g.useState(""),[B,L]=g.useState(!1),[A,F]=g.useState(!1),[S,D]=g.useState(null),[r,R]=g.useState(null),[p,b]=g.useState({}),[ce,O]=g.useState(!1),[z,U]=g.useState(null),[oe,E]=g.useState({}),[ue,G]=g.useState(null),[C,_]=g.useState(null),{confirm:de}=ye(),m=g.useCallback(async()=>{try{N(!0);const s=await je(c);x(s)}catch(s){i(`Failed to load plugins: ${s instanceof Error?s.message:String(s)}`,"error")}finally{N(!1)}},[c,i]);g.useEffect(()=>{m()},[m]),g.useEffect(()=>{const s=ae.filter(o=>o.hasSetup&&h.some(l=>l.id===o.id));if(s.length===0)return;let n=!1;return Promise.all(s.map(async o=>{try{const l=await Y(o.id,c);if(n)return;E(u=>({...u,[o.id]:l}))}catch{if(n)return;E(l=>({...l,[o.id]:{hasSetup:!0,setupCheckDeferred:!0,deferredReason:"plugin-not-started",pluginState:"installed"}}))}})),()=>{n=!0}},[h,c]);const pe=g.useRef([]);pe.current=h,g.useEffect(()=>{const s=c?`?projectId=${encodeURIComponent(c)}`:"",n=o=>{try{const l=JSON.parse(o.data);if(l.scope==="project"&&(l.projectId??c)!==c)return;switch(l.transition){case"installing":case"enabled":case"disabled":case"settings-updated":x(u=>{const a=u.findIndex(t=>t.id===l.pluginId);if(a>=0){const t=[...u];return t[a]={...t[a],enabled:l.enabled,state:l.state,settings:l.settings,error:l.error},t}else return m(),u});break;case"state-changed":x(u=>{const a=u.findIndex(t=>t.id===l.pluginId);if(a>=0){const t=[...u];return t[a]={...t[a],state:l.state,error:l.error},t}return u});break;case"uninstalled":x(u=>u.filter(a=>a.id!==l.pluginId));break;case"error":x(u=>{const a=u.findIndex(t=>t.id===l.pluginId);if(a>=0){const t=[...u];return t[a]={...t[a],state:l.state,error:l.error},t}return u});break}}catch{}};return Ne(`/api/events${s}`,{events:{"plugin:lifecycle":n},onReconnect:()=>{m()}})},[c,m]);const M=async()=>{if(!w.trim()){i("Please enter a plugin path","error");return}try{L(!0),await te({path:w,...A?{aiScanOnLoad:!0}:{}},c),i("Plugin installed globally","success"),P(!1),$(""),F(!1),await m()}catch(s){i(`Failed to install plugin: ${s instanceof Error?s.message:String(s)}`,"error")}finally{L(!1)}},ge=async s=>{if(!s.path){i(`${s.name} is built in and does not have an installable package yet`,"warning");return}try{U(s.id),await te({path:s.path},c),i(`${s.name} installed globally`,"success"),await m()}catch(n){i(`Failed to install ${s.name}: ${n instanceof Error?n.message:String(n)}`,"error")}finally{U(null)}},V=async s=>{try{_(s.id);const n=await Fe(s.id,c);if(!n.success){i(`Failed to install ${s.name} setup: ${n.error??"unknown error"}`,"error");return}i(`${s.name} setup installed`,"success"),G(s.id);const o=await Y(s.id,c);E(l=>({...l,[s.id]:o}))}catch(n){i(`Failed to install ${s.name} setup: ${n instanceof Error?n.message:String(n)}`,"error")}finally{_(null),G(null)}},q=async s=>{try{const n=await Be(s.id,c);if(n.state==="error"){i(`Failed to enable ${s.name}: ${n.error??"Unknown error"}`,"error"),await m();return}i(`${s.name} enabled for this project`,"success"),await m()}catch(n){i(`Failed to enable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},H=async s=>{try{await ke(s.id,c),i(`${s.name} disabled for this project`,"success"),await m()}catch(n){i(`Failed to disable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},W=async s=>{try{D(s.id),await Ee(s.id,c),i(`${s.name} reloaded`,"success"),await m()}catch(n){i(`Failed to reload plugin: ${n instanceof Error?n.message:String(n)}`,"error")}finally{D(null)}},J=async s=>{if(await de({title:"Uninstall Plugin Globally",message:`Are you sure you want to uninstall "${s.name}" globally (all projects)?`,danger:!0}))try{await Le(s.id,c),i(`${s.name} uninstalled globally`,"success"),await m(),R(null)}catch(o){i(`Failed to uninstall plugin: ${o instanceof Error?o.message:String(o)}`,"error")}},me=async(s,n)=>{try{await Pe(s.id,{aiScanOnLoad:n},c),i(`AI scan on load ${n?"enabled":"disabled"}`,"success"),await m()}catch(o){i(`Failed to update plugin: ${o instanceof Error?o.message:String(o)}`,"error")}},he=async s=>{try{await $e(s.id,c),i(`${s.name} rescanned`,"success"),await m()}catch(n){i(`Failed to rescan plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},k=async s=>{R(s);try{O(!0);const n=await Ae(s.id,c);b(n)}catch{b({})}finally{O(!1)}},be=async()=>{if(r)try{await Re(r.id,p,c),i("Settings saved","success")}catch(s){i(`Failed to save settings: ${s instanceof Error?s.message:String(s)}`,"error")}};if(r)return e.jsxs("div",{className:"plugin-manager-detail","data-testid":"plugin-manager-detail",children:[e.jsxs("div",{className:"plugin-manager-detail-header",children:[e.jsx("button",{className:"btn-icon",onClick:()=>R(null),"aria-label":"Back to plugin list",children:e.jsx(Z,{size:16})}),e.jsxs("div",{className:"plugin-detail-title",children:[e.jsxs("div",{className:"plugin-detail-title-copy",children:[e.jsx("h4",{className:"plugin-detail-name",children:r.name}),ie(r,"plugin-error-text plugin-error-text--detail")]}),e.jsx("span",{className:"plugin-state-badge",style:{color:I[r.state]||I.installed},children:r.state})]})]}),e.jsxs("div",{className:"plugin-detail-content",children:[e.jsxs("div",{className:"plugin-detail-card",children:[r.description&&e.jsx("p",{className:"plugin-description",children:r.description}),r.author&&e.jsxs("p",{className:"plugin-detail-meta-row",children:[e.jsx("span",{className:"text-muted",children:"Author:"}),r.author]}),r.homepage&&e.jsxs("p",{className:"plugin-detail-meta-row plugin-homepage",children:[e.jsx("span",{className:"text-muted",children:"Homepage:"}),e.jsxs("a",{href:r.homepage,target:"_blank",rel:"noopener noreferrer",children:[r.homepage,e.jsx(Se,{size:12})]})]}),e.jsxs("p",{className:"plugin-detail-meta-row",children:[e.jsx("span",{className:"text-muted",children:"Version:"}),r.version]})]}),e.jsxs("div",{className:"plugin-detail-card",children:[e.jsx("h5",{className:"plugin-detail-section-heading",children:"Security Scan"}),e.jsxs("div",{className:"plugin-security-row",children:[e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:!!r.aiScanOnLoad,onChange:s=>void me(r,s.target.checked)}),"Enable AI scan before load/reload"]}),e.jsxs("button",{className:"btn btn-secondary btn-sm",onClick:()=>void he(r),children:[e.jsx(ve,{size:14})," Rescan and Reload"]})]}),e.jsx("p",{className:"text-muted",children:"Turning this on only updates configuration. Use Rescan and Reload to run it now."}),r.lastSecurityScan?e.jsxs("div",{className:"plugin-security-results",children:[e.jsxs("div",{className:"plugin-security-header",children:[e.jsx("span",{className:`plugin-state-badge plugin-security-badge plugin-security-badge--${r.lastSecurityScan.verdict}`,children:r.lastSecurityScan.verdict}),e.jsx("span",{className:"text-muted",children:r.lastSecurityScan.scannedAt})]}),e.jsx("p",{className:"plugin-security-summary",children:r.lastSecurityScan.summary}),e.jsxs("details",{children:[e.jsxs("summary",{children:["Findings (",r.lastSecurityScan.findings.length,")"]}),e.jsx("ul",{className:"plugin-security-findings",children:r.lastSecurityScan.findings.map((s,n)=>e.jsxs("li",{children:[e.jsx("strong",{children:s.severity})," ",s.category," — ",s.file,": ",s.reason]},`${s.file}-${n}`))})]})]}):e.jsx("p",{className:"text-muted",children:"No security scan has been run yet."})]}),e.jsxs("div",{className:"plugin-detail-card",children:[e.jsx("h5",{className:"plugin-detail-section-heading",children:"Settings"}),ce?e.jsx("p",{className:"text-muted",children:"Loading..."}):(()=>{const s=Oe(r);return s&&Object.keys(s).length>0?e.jsxs("div",{className:"plugin-settings-form",children:[(()=>{const{grouped:n,ungrouped:o}=ze(s),l=[];o.length>0&&l.push({title:null,entries:o});for(const[u,a]of n.entries())l.push({title:u,entries:a});return l.map(u=>e.jsxs("div",{className:u.title?"plugin-settings-group":void 0,children:[u.title&&e.jsx("h6",{className:"plugin-settings-group-heading",children:u.title}),u.entries.map(([a,t])=>{const y=`setting-${a}-help`;return e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:`setting-${a}`,children:[t.label||a,t.required&&" *"]}),t.type==="string"&&!t.multiline&&e.jsx("input",{className:"input",type:"text",id:`setting-${a}`,value:p[a]??"",onChange:d=>b({...p,[a]:d.target.value}),placeholder:t.description,"aria-describedby":t.description&&!t.required?y:void 0}),t.type==="string"&&t.multiline&&e.jsx("textarea",{className:"input",id:`setting-${a}`,rows:4,value:p[a]??"",onChange:d=>b({...p,[a]:d.target.value}),placeholder:t.description,"aria-describedby":t.description&&!t.required?y:void 0}),t.type==="password"&&e.jsx("input",{className:"input",type:"password",id:`setting-${a}`,value:p[a]??"",onChange:d=>b({...p,[a]:d.target.value}),placeholder:t.description,"aria-describedby":t.description&&!t.required?y:void 0}),t.type==="number"&&e.jsx("input",{className:"input",type:"number",id:`setting-${a}`,value:p[a]??"",onChange:d=>b({...p,[a]:Number(d.target.value)}),"aria-describedby":t.description&&!t.required?y:void 0}),t.type==="boolean"&&e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:p[a]??!1,onChange:d=>b({...p,[a]:d.target.checked})}),t.description]}),t.type==="enum"&&e.jsxs("select",{className:"select",id:`setting-${a}`,value:p[a]??"",onChange:d=>b({...p,[a]:d.target.value}),"aria-describedby":t.description&&!t.required?y:void 0,children:[e.jsx("option",{value:"",children:"Select..."}),t.enumValues?.map(d=>e.jsx("option",{value:d,children:d},d))]}),t.type==="array"&&e.jsxs("div",{className:"plugin-settings-array",children:[p[a]?.map((d,j)=>e.jsxs("div",{className:"plugin-settings-array-item",children:[e.jsx("input",{className:"input",type:t.itemType==="number"?"number":"text",value:d??"",onChange:Q=>{const v=Q.target.value,X=[...p[a]||[]];X[j]=t.itemType==="number"?Number(v):v,b({...p,[a]:X})}}),e.jsx("button",{className:"btn-icon",onClick:()=>{const v=[...p[a]||[]];v.splice(j,1),b({...p,[a]:v})},"aria-label":"Remove item",children:e.jsx(Z,{size:14})})]},j)),e.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const d=p[a]||[],j=t.itemType==="number"?0:"";b({...p,[a]:[...d,j]})},children:[e.jsx(T,{size:14})," Add Item"]})]}),t.description&&!t.required&&!t.multiline&&e.jsx("span",{id:y,className:"form-help",children:t.description})]},a)})]},u.title??"ungrouped"))})(),e.jsx("button",{className:"btn btn-primary",onClick:be,children:"Save Settings"})]}):e.jsx("p",{className:"text-muted",children:"No configurable settings."})})()]}),e.jsxs("div",{className:"plugin-detail-actions",children:[r.state==="started"&&e.jsxs("button",{className:"btn btn-secondary",onClick:()=>W(r),disabled:S===r.id,children:[e.jsx(ee,{size:14,className:S===r.id?"spin":""}),S===r.id?"Reloading...":"Reload"]}),r.enabled?e.jsx("button",{className:"btn btn-secondary",onClick:()=>H(r),children:"Disable in Project"}):e.jsx("button",{className:"btn btn-primary",onClick:()=>q(r),children:"Enable in Project"}),e.jsxs("button",{className:"btn btn-danger",onClick:()=>J(r),children:[e.jsx(se,{size:14})," Uninstall Globally"]})]})]})]});const xe=new Map(h.map(s=>[s.id,s])),K=h,fe=()=>e.jsxs("section",{className:"plugin-builtins-section","aria-label":"Built-in Plugins",children:[e.jsxs("div",{className:"plugin-builtins-header",children:[e.jsx("h4",{className:"plugin-builtins-heading",children:"Built-in Plugins"}),e.jsx("p",{className:"plugin-builtins-description",children:"Built-in plugin catalog for runtimes and integrations."})]}),e.jsx("div",{className:"plugin-builtins-list","aria-label":"Built-in plugin recommendations",children:ae.map(s=>{const n=xe.get(s.id),o=!!n,l=oe[s.id],u=!!(l&&"setupCheckDeferred"in l&&l.setupCheckDeferred),a=l&&"status"in l?l.status:void 0,t=o&&s.hasSetup&&l?.hasSetup&&!u&&n?.state==="started"&&(a==="not-installed"||a==="error"),y=o&&l?.hasSetup&&a==="installed",d=ue===s.id,j=!s.path;return e.jsxs("div",{className:"plugin-builtins-item",children:[e.jsxs("div",{className:"plugin-builtins-meta",children:[e.jsx("span",{className:"plugin-builtins-name",children:s.name}),s.experimental&&e.jsx("span",{className:"plugin-builtins-runtime-badge",children:"Experimental"}),e.jsx("span",{className:"plugin-builtins-runtime-badge",children:s.category}),e.jsx("span",{className:`plugin-builtins-status ${o?"plugin-builtins-status--installed":"plugin-builtins-status--available"}`,children:o?"Installed":j?"Built in":"Not installed"}),t&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--warning",children:"Setup required"}),y&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--ready",children:"Setup ready"}),d&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--pending",children:"Checking setup..."}),u&&e.jsx("span",{className:"plugin-builtins-setup-status plugin-builtins-setup-status--deferred",children:"Start plugin to check setup"}),e.jsx("span",{className:"plugin-builtins-description-text",children:s.description})]}),j?o&&t?e.jsx("button",{className:"btn btn-primary btn-sm",onClick:()=>void V(s),disabled:C===s.id||d,children:C===s.id?"Setting up...":"Install Setup"}):o&&n?e.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>void k(n),children:"Manage"}):e.jsx("span",{className:"plugin-builtins-metadata-only",children:"Built-in metadata only"}):e.jsx("button",{className:`btn ${o&&!t?"btn-secondary":"btn-primary"} btn-sm`,onClick:()=>{if(!o){ge(s);return}if(t){V(s);return}n&&k(n)},disabled:z===s.id||C===s.id||d,children:o?t?C===s.id?"Setting up...":"Install Setup":"Manage":z===s.id?"Installing...":`Install ${s.name}`})]},s.id)})})]});return e.jsxs("div",{className:"plugin-manager","data-testid":"plugin-manager",children:[e.jsxs("div",{className:"plugin-manager-header",children:[e.jsx("span",{className:"plugin-manager-header-title",children:"Installed Plugins"}),e.jsxs("div",{className:"plugin-manager-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:m,title:"Refresh","aria-label":"Refresh plugin list",children:[e.jsx(we,{size:14,className:f?"spin":""}),"Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:()=>P(!0),children:[e.jsx(T,{size:14})," Install"]})]})]}),re&&e.jsxs("div",{className:"plugin-install-form",children:[e.jsxs("p",{className:"plugin-install-hint",children:["Browse to a plugin package root (contains ",e.jsx("code",{children:"manifest.json"}),") or a built ",e.jsx("code",{children:"dist"})," directory."]}),e.jsx(De,{value:w,onChange:$,placeholder:"Absolute path to plugin directory or dist folder",onInputKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),M())}}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:A,onChange:s=>F(s.target.checked)}),"Enable AI security scan on load"]}),e.jsxs("div",{className:"plugin-install-actions",children:[e.jsx("button",{className:"btn btn-primary",onClick:M,disabled:B||!w.trim(),children:B?"Installing...":"Install Plugin Globally"}),e.jsx("button",{className:"btn btn-secondary",onClick:()=>{P(!1),$("")},children:"Cancel"})]})]}),f?e.jsx("div",{className:"settings-empty-state",children:"Loading plugins..."}):e.jsxs(e.Fragment,{children:[K.length===0?e.jsxs("div",{className:"settings-empty-state",children:[e.jsx(Ce,{size:32,className:"text-muted"}),e.jsx("p",{children:"No plugins installed."}),e.jsx("p",{className:"text-muted",children:"Install a plugin to get started, or use the built-in catalog below."})]}):e.jsx("div",{className:"plugin-list",children:K.map(s=>e.jsxs("div",{className:"plugin-item",children:[e.jsx("div",{className:"plugin-info",children:e.jsxs("div",{className:"plugin-copy",children:[e.jsxs("div",{className:"plugin-copy-header",children:[e.jsx("span",{className:"plugin-name",children:s.name}),e.jsxs("span",{className:"plugin-version text-muted",children:["v",s.version]}),e.jsx("span",{className:"plugin-state-badge",style:{color:I[s.state]||I.installed},children:s.state})]}),ie(s)]})}),e.jsxs("div",{className:"plugin-actions",children:[s.state==="started"&&e.jsx("button",{className:"btn-icon",onClick:()=>W(s),disabled:S===s.id,title:"Reload",children:e.jsx(ee,{size:14,className:S===s.id?"spin":""})}),e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>s.enabled?H(s):q(s),"aria-label":`${s.enabled?"Disable":"Enable"} ${s.name}`}),e.jsx("span",{className:"toggle-slider"})]}),e.jsx("button",{className:"btn-icon",onClick:()=>k(s),title:"Settings",children:e.jsx(Ie,{size:14})}),e.jsx("button",{className:"btn-icon",onClick:()=>J(s),title:"Uninstall globally",children:e.jsx(se,{size:14})})]})]},s.id))}),fe()]})]})}export{ne as AGENT_BROWSER_SETTINGS_SCHEMA,le as BUILTIN_AGENT_BROWSER_PLUGIN_ID,We as PluginManager,I as STATE_COLORS};
@@ -1 +1 @@
1
- import{r as n,j as e}from"./vendor-react-K0fH_qHe.js";import{a7 as z,a8 as le,a9 as oe,ak as de,aE as be,ac as te,aF as fe,s as ve,aG as W,aH as xe,aI as pe,aJ as ye,aK as ge,aL as Re,aM as _e,ao as je,u as Se,aN as we,x as Ne,aO as Ee,L as ke,S as Ce}from"./index-w1dPHtmq.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const Ae="builtin",Q={pageFetch:!0,github:!1,localDocs:!0,llmSynthesis:!0};function ae(r){const t=r?.researchGlobalDefaults,i=r?.researchSettings;return{enabled:i?.enabled??r?.researchEnabled??r?.researchGlobalEnabled??!0,searchProvider:i?.searchProvider??t?.searchProvider??r?.researchGlobalWebSearchProvider??Ae,synthesisProvider:i?.synthesisProvider??t?.synthesisProvider,synthesisModelId:i?.synthesisModelId??t?.synthesisModelId,enabledSources:{webSearch:!0,pageFetch:i?.enabledSources?.pageFetch??t?.enabledSources?.pageFetch??Q.pageFetch,github:i?.enabledSources?.github??t?.enabledSources?.github??Q.github,localDocs:i?.enabledSources?.localDocs??t?.enabledSources?.localDocs??Q.localDocs,llmSynthesis:i?.enabledSources?.llmSynthesis??t?.enabledSources?.llmSynthesis??Q.llmSynthesis},limits:{maxConcurrentRuns:i?.limits?.maxConcurrentRuns??r?.researchMaxConcurrentRuns??r?.researchGlobalMaxConcurrentRuns??3,maxSourcesPerRun:i?.limits?.maxSourcesPerRun??t?.maxSourcesPerRun??r?.researchMaxSourcesPerRun??r?.researchGlobalMaxSourcesPerRun??20,maxDurationMs:i?.limits?.maxDurationMs??r?.researchDefaultTimeout??r?.researchGlobalDefaultTimeout??3e5,requestTimeoutMs:i?.limits?.requestTimeoutMs??r?.researchGlobalFetchTimeoutMs??3e4},defaultExportFormat:t?.defaultExportFormat??"markdown"}}const Pe=300,Te=4e3,Ie=["queued","running","cancelling","retry_waiting"];function re(r,t){if(r instanceof je){const i=r;return{message:r.message,status:r.status,code:i.researchCode??"INTERNAL_ERROR",setupHint:i.setupHint,retryable:i.retryable}}return r instanceof Error?{message:r.message,code:"INTERNAL_ERROR"}:{message:t,code:"INTERNAL_ERROR"}}function Le(r){if(!r)return{cancelable:!1,retryable:!1,isTransitioning:!1,blockingReason:"No run selected"};const t=Ie.includes(r.status),i=r.status==="queued"||r.status==="running",f=r.lifecycle?.retryable,y=r.status==="failed"||r.status==="timed_out",a=!!(y&&f);let _;return!i&&t?_="Run is already transitioning":!i&&r.status==="completed"?_="Completed runs cannot be cancelled":!i&&r.status==="cancelled"?_="Run is already cancelled":!i&&r.status==="retry_exhausted"?_="Retry attempts exhausted":!i&&r.status==="failed"?_="Failed runs cannot be cancelled":!i&&r.status==="timed_out"&&(_="Timed out runs cannot be cancelled"),!a&&y&&f===!1&&(_=r.lifecycle?.errorCode==="RETRY_EXHAUSTED"?"Retry attempts exhausted":"Run is not retryable"),{cancelable:i,retryable:a,isTransitioning:t,blockingReason:_}}function Me(r){const t=r?.projectId,i=t??"",f=`${oe.RESEARCH_RUNS_PREFIX}${i}`,y=`${oe.RESEARCH_SELECTED_ID_PREFIX}${i}`,a=z(f,{maxAgeMs:le}),_=z(y,{maxAgeMs:de}),N=n.useRef(Array.isArray(a)&&a.length>0),[j,A]=n.useState(()=>Array.isArray(a)?a:[]),[x,T]=n.useState(_??null),[F,w]=n.useState(null),[D,I]=n.useState({available:!0}),[q,L]=n.useState(!(Array.isArray(a)&&a.length>0)),[H,M]=n.useState(null),[P,R]=n.useState(null),[g,E]=n.useState(""),o=n.useRef(0),v=n.useRef(0),$=n.useRef(t);n.useEffect(()=>{$.current!==t&&($.current=t,v.current++);const c=z(f,{maxAgeMs:le}),l=z(y,{maxAgeMs:de}),h=Array.isArray(c)&&c.length>0;A(Array.isArray(c)?c:[]),T(l??null),w(null),L(!h),N.current=h},[t,f,y]);const k=n.useCallback(async(c=g)=>{const l=++o.current,h=t;N.current||L(!0),M(null),R(null);try{const m=await be({q:c||void 0,limit:100},h);if(l!==o.current||h!==t)return;A(m.runs),te(f,m.runs,{maxBytes:5e5}),N.current=!0,I(m.availability),x&&!m.runs.some(p=>p.id===x)&&(T(null),te(y,null,{maxBytes:5e5}),w(null))}catch(m){if(l!==o.current||h!==t)return;const p=re(m,"Failed to load research runs");M(p.message),R(p)}finally{l===o.current&&L(!1)}},[t,f,g,y,x]),O=n.useCallback(async c=>{const l=await fe(c,t);return w(l.run),I(l.availability),l.run},[t]);n.useEffect(()=>{N.current||L(!0);const c=window.setTimeout(()=>{k(g)},Pe);return()=>window.clearTimeout(c)},[k,g]),n.useEffect(()=>{if(!x){w(null);return}O(x)},[O,x]),n.useEffect(()=>{const c=v.current,l=()=>v.current!==c,h=t?`?projectId=${encodeURIComponent(t)}`:"";let m=!0;const p=()=>{!m||l()||(k(),x&&O(x))},S=`/api/events${h}`,U=ve(S,{events:{"research:run:created":p,"research:run:updated":p,"research:run:completed":p,"research:run:failed":p,"research:run:cancelled":p},onReconnect:()=>{W({view:"useResearch",trigger:"sse-reconnect",projectId:t,replayAttempted:!1,sseChannel:S}),p()}});W({view:"useResearch",trigger:"sse-open",projectId:t,replayAttempted:!1,sseChannel:S});const G=window.setInterval(p,Te);return()=>{m=!1,U(),window.clearInterval(G)}},[t,k,x,O]);const B=n.useCallback(c=>{T(c),te(y,c,{maxBytes:5e5})},[y]);return{runs:j,selectedRun:F,selectedRunId:x,setSelectedRunId:B,availability:D,loading:q,error:H,searchQuery:g,setSearchQuery:E,refresh:k,createRun:c=>_e(c,t),cancelRun:async c=>{try{R(null);const l=await Re(c,t);return x===c&&w(l.run),await k(),l}catch(l){const h=re(l,"Failed to cancel run");throw R(h),h}},retryRun:async c=>{try{R(null);const l=await ge(c,t);return x===c&&w(l.run),await k(),l}catch(l){const h=re(l,"Failed to retry run");throw R(h),h}},exportRun:(c,l)=>ye(c,l,t),createTaskFromRun:(c,l,h,m,p,S)=>pe(c,{title:l,findingId:h,description:m,priority:p,attachExport:S},t),attachRunToTask:(c,l,h,m)=>xe(c,{taskId:l,findingId:h,attachExport:m},t),uiError:P,runActionState:Le(F),statusCounts:j.reduce((c,l)=>(c[l.status]+=1,c),{queued:0,running:0,cancelling:0,retry_waiting:0,completed:0,failed:0,cancelled:0,timed_out:0,retry_exhausted:0})}}function Fe({open:r,mode:t,run:i,finding:f,projectId:y,onClose:a,onConfirm:_}){Se(r);const[N,j]=n.useState(!1),[A,x]=n.useState(""),[T,F]=n.useState(""),[w,D]=n.useState("normal"),[I,q]=n.useState(""),[L,H]=n.useState([]),[M,P]=n.useState(!1),[R,g]=n.useState(!1),E=n.useMemo(()=>{const o=(f.content??"").split(/(?<=[.!?])\s+/)[0]??"";return`${f.heading||"Research finding"} — ${o}`.trim()},[f.content,f.heading]);return n.useEffect(()=>{r&&(j(!1),x(`Research: ${f.heading||i.title}`),F(E),D("normal"),q(""),t==="enrich"&&(P(!0),we(50,0,y).then(o=>H(o.filter(v=>v.column!=="archived"))).finally(()=>P(!1))))},[r,t,y,f.heading,E,i.title]),r?e.jsx("div",{className:"modal-overlay open",role:"presentation",onClick:a,children:e.jsxs("div",{className:"modal modal-lg research-task-action-modal",role:"dialog","aria-modal":"true",onClick:o=>o.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:t==="create"?"Create task from finding":"Enrich existing task"}),e.jsx("button",{className:"modal-close",type:"button","aria-label":"Close",onClick:a,children:"×"})]}),e.jsxs("div",{className:"research-task-action-modal__body",children:[e.jsxs("div",{className:"card research-task-action-modal__preview",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Run:"})," ",i.id]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Finding:"})," ",f.id,f.heading?` — ${f.heading}`:""]}),e.jsx("p",{children:E||"No preview available."})]}),t==="create"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"research-task-action-modal__field",children:["Title",e.jsx("input",{className:"input",value:A,onChange:o=>x(o.target.value)})]}),e.jsxs("label",{className:"research-task-action-modal__field",children:["Description",e.jsx("textarea",{className:"input research-task-action-modal__textarea",value:T,onChange:o=>F(o.target.value)})]}),e.jsxs("label",{className:"research-task-action-modal__field",children:["Priority",e.jsxs("select",{className:"select",value:w,onChange:o=>D(o.target.value),children:[e.jsx("option",{value:"low",children:"Low"}),e.jsx("option",{value:"normal",children:"Normal"}),e.jsx("option",{value:"high",children:"High"}),e.jsx("option",{value:"urgent",children:"Urgent"})]})]})]}):e.jsxs("label",{className:"research-task-action-modal__field",children:["Target task",e.jsx("input",{className:"input",list:"research-task-action-task-list",value:I,placeholder:M?"Loading tasks…":"Enter task ID",onChange:o=>q(o.target.value)}),e.jsx("datalist",{id:"research-task-action-task-list",children:L.map(o=>e.jsx("option",{value:o.id,children:o.title},o.id))})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:N,onChange:o=>j(o.target.checked)}),e.jsx("span",{children:"Attach markdown export artifact"})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:a,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",type:"button",disabled:R||t==="enrich"&&!I,onClick:()=>{g(!0),_({taskId:t==="enrich"?I:void 0,title:t==="create"?A.trim():void 0,description:t==="create"?T.trim():void 0,priority:t==="create"?w:void 0,attachExport:N}).finally(()=>g(!1))},children:t==="create"?"Create Task":"Enrich Task"})]})]})}):null}const De=["web-search","page-fetch","github","local-docs","llm-synthesis"],qe={"web-search":"webSearch","page-fetch":"pageFetch",github:"github","local-docs":"localDocs","llm-synthesis":"llmSynthesis"},Oe={"web-search":"Web Search","page-fetch":"Page Fetch",github:"GitHub","local-docs":"Local Docs","llm-synthesis":"LLM Synthesis"};let ne=!1;function Be({projectId:r,addToast:t,onOpenSettings:i,readinessVersion:f=0}){n.useEffect(()=>(W({view:"ResearchView",trigger:ne?"route-active":"remount",projectId:r,replayAttempted:!1}),ne=!1,()=>{ne=!0,W({view:"ResearchView",trigger:"route-inactive",projectId:r,replayAttempted:!1})}),[r]);const{runs:y,selectedRun:a,selectedRunId:_,setSelectedRunId:N,availability:j,loading:A,error:x,searchQuery:T,setSearchQuery:F,createRun:w,cancelRun:D,retryRun:I,exportRun:q,createTaskFromRun:L,attachRunToTask:H,statusCounts:M,refresh:P,uiError:R,runActionState:g}=Me({projectId:r}),[E,o]=n.useState(""),[v,$]=n.useState(()=>ae(void 0)),[k,O]=n.useState([]),[B,c]=n.useState(!1),[l,h]=n.useState([]),[m,p]=n.useState(null),[S,U]=n.useState(null),G=j.supportedProviders??De,X=v.searchProvider,Y=s=>s==="web-search"?!0:v.enabledSources[qe[s]];n.useEffect(()=>{const s=G.filter(d=>Y(d));h(d=>{const b=d.filter(u=>s.includes(u));return b.length>0?b:s})},[v.enabledSources,G]),n.useEffect(()=>{let s=!1;return Promise.all([Ne(r),Ee().catch(()=>({providers:[]}))]).then(([d,b])=>{s||($(ae(d)),O(b.providers.filter(u=>u.type==="api_key").map(u=>({id:u.id,authenticated:u.authenticated}))))}).catch(()=>{s||$(ae(void 0))}),()=>{s=!0}},[r,f]);const ue=n.useMemo(()=>a?a.status:"No run selected",[a]),he=n.useMemo(()=>a?a.status==="queued"||a.status==="retry_waiting"?"status-dot status-dot--pending":a.status==="running"?"status-dot status-dot--connecting":a.status==="completed"?"status-dot status-dot--online":a.status==="failed"||a.status==="cancelled"?"status-dot status-dot--error":"status-dot":"status-dot",[a]),J=j.supportedExportFormats??["markdown","json","html"],Z=n.useMemo(()=>new Map(k.map(s=>[s.id,s.authenticated])),[k]),ee=n.useMemo(()=>{const s=new Set;return v.enabledSources.webSearch&&X&&s.add(X),v.enabledSources.llmSynthesis&&v.synthesisProvider&&s.add(v.synthesisProvider),[...s].filter(d=>Z.has(d))},[v.enabledSources.llmSynthesis,v.enabledSources.webSearch,v.synthesisProvider,X,Z]).find(s=>Z.get(s)!==!0),V=n.useMemo(()=>j.available?v.enabled?ee?{reason:`Missing API key for ${ee}.`,details:"Add provider credentials in Authentication settings.",settingsSection:"authentication"}:null:{reason:"Research is disabled for this project.",details:"Enable project research settings to create runs.",settingsSection:"research-project"}:{reason:j.reason??"Research is unavailable for this project.",details:j.setupInstructions,settingsSection:"research-project"},[j.available,j.reason,j.setupInstructions,v.enabled,ee]),K=async(s,d,b)=>{p(s);try{await d(),t?.(b,"success"),await P()}catch(u){t?.(u instanceof Error?u.message:"Action failed","error")}finally{p(null)}},se=async s=>{if(a){p(`export-${s}`);try{const d=await q(a.id,s),b=new Blob([d.content],{type:"text/plain;charset=utf-8"}),u=URL.createObjectURL(b),C=document.createElement("a");C.href=u,C.download=d.filename,document.body.appendChild(C),C.click(),C.remove(),URL.revokeObjectURL(u),t?.(`Exported ${d.filename}`,"success")}catch(d){t?.(d instanceof Error?d.message:"Export failed","error")}finally{p(null)}}},me=async()=>{if(E.trim()){c(!0);try{const s=l.filter(b=>Y(b));if(s.length===0){c(!1),t?.("No enabled research sources are available for this project.","error");return}const d=await w({query:E.trim(),providers:s});N(d.run.id),o(""),t?.("Research run created","success"),await P()}catch(s){t?.(s instanceof Error?s.message:"Failed to create run","error")}finally{c(!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:"Cited search and synthesis runs: gather sources, fetch content, and synthesize findings."})]}),e.jsx("div",{className:"research-view__header-actions",children:e.jsx("button",{className:"btn",type:"button",onClick:()=>void P(),children:"Refresh"})})]}),V?e.jsxs("div",{className:"research-view__state research-view__state--error card","data-testid":"research-state-unavailable",children:[e.jsx("p",{children:V.reason}),V.details&&e.jsx("p",{children:V.details}),e.jsxs("p",{children:["Current defaults: provider ",v.searchProvider??"(not set)",", max sources ",v.limits.maxSourcesPerRun]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:()=>void P(),children:"Refresh"}),e.jsx("button",{className:"btn btn-primary",type:"button",onClick:()=>i?.(V.settingsSection),children:"Open Settings"})]})]}):e.jsx(e.Fragment,{children:e.jsxs("div",{className:"research-view__layout",children:[e.jsx("aside",{className:"research-view__sidebar card",children:e.jsxs("div",{className:"research-view__sidebar-content",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:E,onChange:s=>o(s.target.value)})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Providers"}),e.jsx("div",{className:"research-view__providers",children:G.map(s=>{const d=Y(s),b=s==="web-search";return e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:b||l.includes(s),disabled:b||!d,onChange:()=>{b||!d||h(u=>u.includes(s)?u.filter(C=>C!==s):[...u,s])}}),e.jsxs("span",{children:[Oe[s]??s,b?e.jsx("span",{className:"research-view__provider-lock",children:"Always on"}):null]})]},s)})})]}),e.jsxs("button",{className:"btn btn-primary",type:"button",disabled:!E.trim()||B,onClick:()=>void me(),children:[B?e.jsx(ke,{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(Ce,{size:14}),e.jsx("input",{id:"research-run-search",className:"input",placeholder:"Search runs",value:T,onChange:s=>F(s.target.value)})]})]}),e.jsx("div",{className:"research-view__history","data-testid":"research-state-running",children:y.map(s=>e.jsxs("button",{type:"button",className:`research-view__history-item card${_===s.id?" research-view__history-item--active":""}`,onClick:()=>N(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:[A&&e.jsx("p",{"data-testid":"research-state-loading",children:"Loading research runs…"}),!A&&x&&e.jsx("p",{"data-testid":"research-state-error",children:x}),!A&&!x&&y.length===0&&e.jsx("p",{"data-testid":"research-state-empty",children:"No research runs yet"}),e.jsxs("div",{className:"research-view__reader-content",children:[a&&e.jsxs("div",{className:"research-view__run-detail",children:[e.jsxs("div",{className:"research-view__status-row",children:[e.jsx("span",{className:he}),e.jsx("strong",{children:ue})]}),e.jsx("h3",{className:"research-view__run-title",children:a.title}),e.jsx("p",{className:"research-view__run-query",children:a.query}),e.jsx("p",{className:"research-view__run-summary","data-testid":"research-state-results",children:a.results?.summary??"No summary yet."}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",title:g.cancelable?void 0:g.blockingReason,disabled:m==="cancel"||m==="retry"||!g.cancelable,onClick:()=>void K("cancel",()=>D(a.id),"Run cancelled"),children:"Cancel"}),e.jsx("button",{className:"btn",type:"button",title:g.retryable?void 0:g.blockingReason,disabled:m==="cancel"||m==="retry"||!g.retryable,onClick:()=>void K("retry",()=>I(a.id),"Run retried"),children:"Retry"}),J.includes("markdown")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-markdown",onClick:()=>void se("markdown"),children:"Export MD"}),J.includes("json")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-json",onClick:()=>void se("json"),children:"Export JSON"}),J.includes("html")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-html",onClick:()=>void se("html"),children:"Export HTML"})]}),a.error&&e.jsx("p",{className:"research-view__error",children:a.error}),R&&e.jsxs("div",{className:"form-error",role:"alert",children:[e.jsx("p",{children:R.message}),R.setupHint&&e.jsx("p",{children:R.setupHint}),R.code==="MISSING_CREDENTIALS"&&e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>i?.("authentication"),children:"Open Authentication Settings"}),R.code==="FEATURE_DISABLED"&&e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>i?.("research-project"),children:"Open Research Settings"})]}),g.blockingReason&&e.jsx("p",{className:"research-view__run-query",children:g.blockingReason}),Array.isArray(a.results?.findings)&&a.results.findings.length>0&&e.jsx("div",{className:"research-view__findings",children:a.results.findings.map((s,d)=>{const u=s.id?.trim()||`finding-${d+1}`;return e.jsxs("article",{className:"research-view__finding card",children:[e.jsx("h4",{children:s.heading}),e.jsx("p",{children:s.content}),e.jsxs("div",{className:"research-view__actions research-view__finding-actions",children:[e.jsx("button",{className:"btn btn-primary btn-sm",type:"button",onClick:()=>U({mode:"create",findingId:u}),children:"Create Task"}),e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>U({mode:"enrich",findingId:u}),children:"Enrich Task"})]})]},u)})}),Array.isArray(a.results?.citations)&&a.results.citations.length>0&&e.jsx("ul",{className:"research-view__citations",children:a.results.citations.map(s=>e.jsx("li",{children:e.jsx("a",{href:s,target:"_blank",rel:"noreferrer",children:s})},s))}),a.events.length>0&&e.jsxs("details",{children:[e.jsx("summary",{children:"Run history"}),e.jsx("ul",{className:"research-view__events",children:a.events.map(s=>e.jsx("li",{children:s.message},s.id))})]})]}),!a&&y.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:M.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:M.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:M.failed})]})]})]})]})]})}),a&&S&&(()=>{const s=a.results?.findings?.findIndex((b,u)=>(b.id?.trim()||`finding-${u+1}`)===S.findingId)??-1,d=s>=0?a.results.findings[s]:null;return d?e.jsx(Fe,{open:!0,mode:S.mode,run:a,finding:{id:S.findingId,heading:d.heading,content:d.content},projectId:r,onClose:()=>U(null),onConfirm:async({taskId:b,title:u,description:C,priority:ce,attachExport:ie})=>{S.mode==="create"?await K("create-task",()=>L(a.id,u,S.findingId,C,ce,ie),"Task created from research"):b&&await K("attach-task",()=>H(a.id,b,S.findingId,ie),"Task enriched from research"),U(null)}}):null})()]})}export{Be as ResearchView};
1
+ import{r as n,j as e}from"./vendor-react-K0fH_qHe.js";import{a7 as z,a8 as le,a9 as oe,ak as de,aE as be,ac as te,aF as fe,s as ve,aG as W,aH as xe,aI as pe,aJ as ye,aK as ge,aL as Re,aM as _e,ao as je,u as Se,aN as we,x as Ne,aO as Ee,L as ke,S as Ce}from"./index-BonLYFW-.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const Ae="builtin",Q={pageFetch:!0,github:!1,localDocs:!0,llmSynthesis:!0};function ae(r){const t=r?.researchGlobalDefaults,i=r?.researchSettings;return{enabled:i?.enabled??r?.researchEnabled??r?.researchGlobalEnabled??!0,searchProvider:i?.searchProvider??t?.searchProvider??r?.researchGlobalWebSearchProvider??Ae,synthesisProvider:i?.synthesisProvider??t?.synthesisProvider,synthesisModelId:i?.synthesisModelId??t?.synthesisModelId,enabledSources:{webSearch:!0,pageFetch:i?.enabledSources?.pageFetch??t?.enabledSources?.pageFetch??Q.pageFetch,github:i?.enabledSources?.github??t?.enabledSources?.github??Q.github,localDocs:i?.enabledSources?.localDocs??t?.enabledSources?.localDocs??Q.localDocs,llmSynthesis:i?.enabledSources?.llmSynthesis??t?.enabledSources?.llmSynthesis??Q.llmSynthesis},limits:{maxConcurrentRuns:i?.limits?.maxConcurrentRuns??r?.researchMaxConcurrentRuns??r?.researchGlobalMaxConcurrentRuns??3,maxSourcesPerRun:i?.limits?.maxSourcesPerRun??t?.maxSourcesPerRun??r?.researchMaxSourcesPerRun??r?.researchGlobalMaxSourcesPerRun??20,maxDurationMs:i?.limits?.maxDurationMs??r?.researchDefaultTimeout??r?.researchGlobalDefaultTimeout??3e5,requestTimeoutMs:i?.limits?.requestTimeoutMs??r?.researchGlobalFetchTimeoutMs??3e4},defaultExportFormat:t?.defaultExportFormat??"markdown"}}const Pe=300,Te=4e3,Ie=["queued","running","cancelling","retry_waiting"];function re(r,t){if(r instanceof je){const i=r;return{message:r.message,status:r.status,code:i.researchCode??"INTERNAL_ERROR",setupHint:i.setupHint,retryable:i.retryable}}return r instanceof Error?{message:r.message,code:"INTERNAL_ERROR"}:{message:t,code:"INTERNAL_ERROR"}}function Le(r){if(!r)return{cancelable:!1,retryable:!1,isTransitioning:!1,blockingReason:"No run selected"};const t=Ie.includes(r.status),i=r.status==="queued"||r.status==="running",f=r.lifecycle?.retryable,y=r.status==="failed"||r.status==="timed_out",a=!!(y&&f);let _;return!i&&t?_="Run is already transitioning":!i&&r.status==="completed"?_="Completed runs cannot be cancelled":!i&&r.status==="cancelled"?_="Run is already cancelled":!i&&r.status==="retry_exhausted"?_="Retry attempts exhausted":!i&&r.status==="failed"?_="Failed runs cannot be cancelled":!i&&r.status==="timed_out"&&(_="Timed out runs cannot be cancelled"),!a&&y&&f===!1&&(_=r.lifecycle?.errorCode==="RETRY_EXHAUSTED"?"Retry attempts exhausted":"Run is not retryable"),{cancelable:i,retryable:a,isTransitioning:t,blockingReason:_}}function Me(r){const t=r?.projectId,i=t??"",f=`${oe.RESEARCH_RUNS_PREFIX}${i}`,y=`${oe.RESEARCH_SELECTED_ID_PREFIX}${i}`,a=z(f,{maxAgeMs:le}),_=z(y,{maxAgeMs:de}),N=n.useRef(Array.isArray(a)&&a.length>0),[j,A]=n.useState(()=>Array.isArray(a)?a:[]),[x,T]=n.useState(_??null),[F,w]=n.useState(null),[D,I]=n.useState({available:!0}),[q,L]=n.useState(!(Array.isArray(a)&&a.length>0)),[H,M]=n.useState(null),[P,R]=n.useState(null),[g,E]=n.useState(""),o=n.useRef(0),v=n.useRef(0),$=n.useRef(t);n.useEffect(()=>{$.current!==t&&($.current=t,v.current++);const c=z(f,{maxAgeMs:le}),l=z(y,{maxAgeMs:de}),h=Array.isArray(c)&&c.length>0;A(Array.isArray(c)?c:[]),T(l??null),w(null),L(!h),N.current=h},[t,f,y]);const k=n.useCallback(async(c=g)=>{const l=++o.current,h=t;N.current||L(!0),M(null),R(null);try{const m=await be({q:c||void 0,limit:100},h);if(l!==o.current||h!==t)return;A(m.runs),te(f,m.runs,{maxBytes:5e5}),N.current=!0,I(m.availability),x&&!m.runs.some(p=>p.id===x)&&(T(null),te(y,null,{maxBytes:5e5}),w(null))}catch(m){if(l!==o.current||h!==t)return;const p=re(m,"Failed to load research runs");M(p.message),R(p)}finally{l===o.current&&L(!1)}},[t,f,g,y,x]),O=n.useCallback(async c=>{const l=await fe(c,t);return w(l.run),I(l.availability),l.run},[t]);n.useEffect(()=>{N.current||L(!0);const c=window.setTimeout(()=>{k(g)},Pe);return()=>window.clearTimeout(c)},[k,g]),n.useEffect(()=>{if(!x){w(null);return}O(x)},[O,x]),n.useEffect(()=>{const c=v.current,l=()=>v.current!==c,h=t?`?projectId=${encodeURIComponent(t)}`:"";let m=!0;const p=()=>{!m||l()||(k(),x&&O(x))},S=`/api/events${h}`,U=ve(S,{events:{"research:run:created":p,"research:run:updated":p,"research:run:completed":p,"research:run:failed":p,"research:run:cancelled":p},onReconnect:()=>{W({view:"useResearch",trigger:"sse-reconnect",projectId:t,replayAttempted:!1,sseChannel:S}),p()}});W({view:"useResearch",trigger:"sse-open",projectId:t,replayAttempted:!1,sseChannel:S});const G=window.setInterval(p,Te);return()=>{m=!1,U(),window.clearInterval(G)}},[t,k,x,O]);const B=n.useCallback(c=>{T(c),te(y,c,{maxBytes:5e5})},[y]);return{runs:j,selectedRun:F,selectedRunId:x,setSelectedRunId:B,availability:D,loading:q,error:H,searchQuery:g,setSearchQuery:E,refresh:k,createRun:c=>_e(c,t),cancelRun:async c=>{try{R(null);const l=await Re(c,t);return x===c&&w(l.run),await k(),l}catch(l){const h=re(l,"Failed to cancel run");throw R(h),h}},retryRun:async c=>{try{R(null);const l=await ge(c,t);return x===c&&w(l.run),await k(),l}catch(l){const h=re(l,"Failed to retry run");throw R(h),h}},exportRun:(c,l)=>ye(c,l,t),createTaskFromRun:(c,l,h,m,p,S)=>pe(c,{title:l,findingId:h,description:m,priority:p,attachExport:S},t),attachRunToTask:(c,l,h,m)=>xe(c,{taskId:l,findingId:h,attachExport:m},t),uiError:P,runActionState:Le(F),statusCounts:j.reduce((c,l)=>(c[l.status]+=1,c),{queued:0,running:0,cancelling:0,retry_waiting:0,completed:0,failed:0,cancelled:0,timed_out:0,retry_exhausted:0})}}function Fe({open:r,mode:t,run:i,finding:f,projectId:y,onClose:a,onConfirm:_}){Se(r);const[N,j]=n.useState(!1),[A,x]=n.useState(""),[T,F]=n.useState(""),[w,D]=n.useState("normal"),[I,q]=n.useState(""),[L,H]=n.useState([]),[M,P]=n.useState(!1),[R,g]=n.useState(!1),E=n.useMemo(()=>{const o=(f.content??"").split(/(?<=[.!?])\s+/)[0]??"";return`${f.heading||"Research finding"} — ${o}`.trim()},[f.content,f.heading]);return n.useEffect(()=>{r&&(j(!1),x(`Research: ${f.heading||i.title}`),F(E),D("normal"),q(""),t==="enrich"&&(P(!0),we(50,0,y).then(o=>H(o.filter(v=>v.column!=="archived"))).finally(()=>P(!1))))},[r,t,y,f.heading,E,i.title]),r?e.jsx("div",{className:"modal-overlay open",role:"presentation",onClick:a,children:e.jsxs("div",{className:"modal modal-lg research-task-action-modal",role:"dialog","aria-modal":"true",onClick:o=>o.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:t==="create"?"Create task from finding":"Enrich existing task"}),e.jsx("button",{className:"modal-close",type:"button","aria-label":"Close",onClick:a,children:"×"})]}),e.jsxs("div",{className:"research-task-action-modal__body",children:[e.jsxs("div",{className:"card research-task-action-modal__preview",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Run:"})," ",i.id]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Finding:"})," ",f.id,f.heading?` — ${f.heading}`:""]}),e.jsx("p",{children:E||"No preview available."})]}),t==="create"?e.jsxs(e.Fragment,{children:[e.jsxs("label",{className:"research-task-action-modal__field",children:["Title",e.jsx("input",{className:"input",value:A,onChange:o=>x(o.target.value)})]}),e.jsxs("label",{className:"research-task-action-modal__field",children:["Description",e.jsx("textarea",{className:"input research-task-action-modal__textarea",value:T,onChange:o=>F(o.target.value)})]}),e.jsxs("label",{className:"research-task-action-modal__field",children:["Priority",e.jsxs("select",{className:"select",value:w,onChange:o=>D(o.target.value),children:[e.jsx("option",{value:"low",children:"Low"}),e.jsx("option",{value:"normal",children:"Normal"}),e.jsx("option",{value:"high",children:"High"}),e.jsx("option",{value:"urgent",children:"Urgent"})]})]})]}):e.jsxs("label",{className:"research-task-action-modal__field",children:["Target task",e.jsx("input",{className:"input",list:"research-task-action-task-list",value:I,placeholder:M?"Loading tasks…":"Enter task ID",onChange:o=>q(o.target.value)}),e.jsx("datalist",{id:"research-task-action-task-list",children:L.map(o=>e.jsx("option",{value:o.id,children:o.title},o.id))})]}),e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:N,onChange:o=>j(o.target.checked)}),e.jsx("span",{children:"Attach markdown export artifact"})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:a,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",type:"button",disabled:R||t==="enrich"&&!I,onClick:()=>{g(!0),_({taskId:t==="enrich"?I:void 0,title:t==="create"?A.trim():void 0,description:t==="create"?T.trim():void 0,priority:t==="create"?w:void 0,attachExport:N}).finally(()=>g(!1))},children:t==="create"?"Create Task":"Enrich Task"})]})]})}):null}const De=["web-search","page-fetch","github","local-docs","llm-synthesis"],qe={"web-search":"webSearch","page-fetch":"pageFetch",github:"github","local-docs":"localDocs","llm-synthesis":"llmSynthesis"},Oe={"web-search":"Web Search","page-fetch":"Page Fetch",github:"GitHub","local-docs":"Local Docs","llm-synthesis":"LLM Synthesis"};let ne=!1;function Be({projectId:r,addToast:t,onOpenSettings:i,readinessVersion:f=0}){n.useEffect(()=>(W({view:"ResearchView",trigger:ne?"route-active":"remount",projectId:r,replayAttempted:!1}),ne=!1,()=>{ne=!0,W({view:"ResearchView",trigger:"route-inactive",projectId:r,replayAttempted:!1})}),[r]);const{runs:y,selectedRun:a,selectedRunId:_,setSelectedRunId:N,availability:j,loading:A,error:x,searchQuery:T,setSearchQuery:F,createRun:w,cancelRun:D,retryRun:I,exportRun:q,createTaskFromRun:L,attachRunToTask:H,statusCounts:M,refresh:P,uiError:R,runActionState:g}=Me({projectId:r}),[E,o]=n.useState(""),[v,$]=n.useState(()=>ae(void 0)),[k,O]=n.useState([]),[B,c]=n.useState(!1),[l,h]=n.useState([]),[m,p]=n.useState(null),[S,U]=n.useState(null),G=j.supportedProviders??De,X=v.searchProvider,Y=s=>s==="web-search"?!0:v.enabledSources[qe[s]];n.useEffect(()=>{const s=G.filter(d=>Y(d));h(d=>{const b=d.filter(u=>s.includes(u));return b.length>0?b:s})},[v.enabledSources,G]),n.useEffect(()=>{let s=!1;return Promise.all([Ne(r),Ee().catch(()=>({providers:[]}))]).then(([d,b])=>{s||($(ae(d)),O(b.providers.filter(u=>u.type==="api_key").map(u=>({id:u.id,authenticated:u.authenticated}))))}).catch(()=>{s||$(ae(void 0))}),()=>{s=!0}},[r,f]);const ue=n.useMemo(()=>a?a.status:"No run selected",[a]),he=n.useMemo(()=>a?a.status==="queued"||a.status==="retry_waiting"?"status-dot status-dot--pending":a.status==="running"?"status-dot status-dot--connecting":a.status==="completed"?"status-dot status-dot--online":a.status==="failed"||a.status==="cancelled"?"status-dot status-dot--error":"status-dot":"status-dot",[a]),J=j.supportedExportFormats??["markdown","json","html"],Z=n.useMemo(()=>new Map(k.map(s=>[s.id,s.authenticated])),[k]),ee=n.useMemo(()=>{const s=new Set;return v.enabledSources.webSearch&&X&&s.add(X),v.enabledSources.llmSynthesis&&v.synthesisProvider&&s.add(v.synthesisProvider),[...s].filter(d=>Z.has(d))},[v.enabledSources.llmSynthesis,v.enabledSources.webSearch,v.synthesisProvider,X,Z]).find(s=>Z.get(s)!==!0),V=n.useMemo(()=>j.available?v.enabled?ee?{reason:`Missing API key for ${ee}.`,details:"Add provider credentials in Authentication settings.",settingsSection:"authentication"}:null:{reason:"Research is disabled for this project.",details:"Enable project research settings to create runs.",settingsSection:"research-project"}:{reason:j.reason??"Research is unavailable for this project.",details:j.setupInstructions,settingsSection:"research-project"},[j.available,j.reason,j.setupInstructions,v.enabled,ee]),K=async(s,d,b)=>{p(s);try{await d(),t?.(b,"success"),await P()}catch(u){t?.(u instanceof Error?u.message:"Action failed","error")}finally{p(null)}},se=async s=>{if(a){p(`export-${s}`);try{const d=await q(a.id,s),b=new Blob([d.content],{type:"text/plain;charset=utf-8"}),u=URL.createObjectURL(b),C=document.createElement("a");C.href=u,C.download=d.filename,document.body.appendChild(C),C.click(),C.remove(),URL.revokeObjectURL(u),t?.(`Exported ${d.filename}`,"success")}catch(d){t?.(d instanceof Error?d.message:"Export failed","error")}finally{p(null)}}},me=async()=>{if(E.trim()){c(!0);try{const s=l.filter(b=>Y(b));if(s.length===0){c(!1),t?.("No enabled research sources are available for this project.","error");return}const d=await w({query:E.trim(),providers:s});N(d.run.id),o(""),t?.("Research run created","success"),await P()}catch(s){t?.(s instanceof Error?s.message:"Failed to create run","error")}finally{c(!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:"Cited search and synthesis runs: gather sources, fetch content, and synthesize findings."})]}),e.jsx("div",{className:"research-view__header-actions",children:e.jsx("button",{className:"btn",type:"button",onClick:()=>void P(),children:"Refresh"})})]}),V?e.jsxs("div",{className:"research-view__state research-view__state--error card","data-testid":"research-state-unavailable",children:[e.jsx("p",{children:V.reason}),V.details&&e.jsx("p",{children:V.details}),e.jsxs("p",{children:["Current defaults: provider ",v.searchProvider??"(not set)",", max sources ",v.limits.maxSourcesPerRun]}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",onClick:()=>void P(),children:"Refresh"}),e.jsx("button",{className:"btn btn-primary",type:"button",onClick:()=>i?.(V.settingsSection),children:"Open Settings"})]})]}):e.jsx(e.Fragment,{children:e.jsxs("div",{className:"research-view__layout",children:[e.jsx("aside",{className:"research-view__sidebar card",children:e.jsxs("div",{className:"research-view__sidebar-content",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:E,onChange:s=>o(s.target.value)})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Providers"}),e.jsx("div",{className:"research-view__providers",children:G.map(s=>{const d=Y(s),b=s==="web-search";return e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:b||l.includes(s),disabled:b||!d,onChange:()=>{b||!d||h(u=>u.includes(s)?u.filter(C=>C!==s):[...u,s])}}),e.jsxs("span",{children:[Oe[s]??s,b?e.jsx("span",{className:"research-view__provider-lock",children:"Always on"}):null]})]},s)})})]}),e.jsxs("button",{className:"btn btn-primary",type:"button",disabled:!E.trim()||B,onClick:()=>void me(),children:[B?e.jsx(ke,{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(Ce,{size:14}),e.jsx("input",{id:"research-run-search",className:"input",placeholder:"Search runs",value:T,onChange:s=>F(s.target.value)})]})]}),e.jsx("div",{className:"research-view__history","data-testid":"research-state-running",children:y.map(s=>e.jsxs("button",{type:"button",className:`research-view__history-item card${_===s.id?" research-view__history-item--active":""}`,onClick:()=>N(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:[A&&e.jsx("p",{"data-testid":"research-state-loading",children:"Loading research runs…"}),!A&&x&&e.jsx("p",{"data-testid":"research-state-error",children:x}),!A&&!x&&y.length===0&&e.jsx("p",{"data-testid":"research-state-empty",children:"No research runs yet"}),e.jsxs("div",{className:"research-view__reader-content",children:[a&&e.jsxs("div",{className:"research-view__run-detail",children:[e.jsxs("div",{className:"research-view__status-row",children:[e.jsx("span",{className:he}),e.jsx("strong",{children:ue})]}),e.jsx("h3",{className:"research-view__run-title",children:a.title}),e.jsx("p",{className:"research-view__run-query",children:a.query}),e.jsx("p",{className:"research-view__run-summary","data-testid":"research-state-results",children:a.results?.summary??"No summary yet."}),e.jsxs("div",{className:"research-view__actions",children:[e.jsx("button",{className:"btn",type:"button",title:g.cancelable?void 0:g.blockingReason,disabled:m==="cancel"||m==="retry"||!g.cancelable,onClick:()=>void K("cancel",()=>D(a.id),"Run cancelled"),children:"Cancel"}),e.jsx("button",{className:"btn",type:"button",title:g.retryable?void 0:g.blockingReason,disabled:m==="cancel"||m==="retry"||!g.retryable,onClick:()=>void K("retry",()=>I(a.id),"Run retried"),children:"Retry"}),J.includes("markdown")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-markdown",onClick:()=>void se("markdown"),children:"Export MD"}),J.includes("json")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-json",onClick:()=>void se("json"),children:"Export JSON"}),J.includes("html")&&e.jsx("button",{className:"btn",type:"button",disabled:m==="export-html",onClick:()=>void se("html"),children:"Export HTML"})]}),a.error&&e.jsx("p",{className:"research-view__error",children:a.error}),R&&e.jsxs("div",{className:"form-error",role:"alert",children:[e.jsx("p",{children:R.message}),R.setupHint&&e.jsx("p",{children:R.setupHint}),R.code==="MISSING_CREDENTIALS"&&e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>i?.("authentication"),children:"Open Authentication Settings"}),R.code==="FEATURE_DISABLED"&&e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>i?.("research-project"),children:"Open Research Settings"})]}),g.blockingReason&&e.jsx("p",{className:"research-view__run-query",children:g.blockingReason}),Array.isArray(a.results?.findings)&&a.results.findings.length>0&&e.jsx("div",{className:"research-view__findings",children:a.results.findings.map((s,d)=>{const u=s.id?.trim()||`finding-${d+1}`;return e.jsxs("article",{className:"research-view__finding card",children:[e.jsx("h4",{children:s.heading}),e.jsx("p",{children:s.content}),e.jsxs("div",{className:"research-view__actions research-view__finding-actions",children:[e.jsx("button",{className:"btn btn-primary btn-sm",type:"button",onClick:()=>U({mode:"create",findingId:u}),children:"Create Task"}),e.jsx("button",{className:"btn btn-sm",type:"button",onClick:()=>U({mode:"enrich",findingId:u}),children:"Enrich Task"})]})]},u)})}),Array.isArray(a.results?.citations)&&a.results.citations.length>0&&e.jsx("ul",{className:"research-view__citations",children:a.results.citations.map(s=>e.jsx("li",{children:e.jsx("a",{href:s,target:"_blank",rel:"noreferrer",children:s})},s))}),a.events.length>0&&e.jsxs("details",{children:[e.jsx("summary",{children:"Run history"}),e.jsx("ul",{className:"research-view__events",children:a.events.map(s=>e.jsx("li",{children:s.message},s.id))})]})]}),!a&&y.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:M.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:M.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:M.failed})]})]})]})]})]})}),a&&S&&(()=>{const s=a.results?.findings?.findIndex((b,u)=>(b.id?.trim()||`finding-${u+1}`)===S.findingId)??-1,d=s>=0?a.results.findings[s]:null;return d?e.jsx(Fe,{open:!0,mode:S.mode,run:a,finding:{id:S.findingId,heading:d.heading,content:d.content},projectId:r,onClose:()=>U(null),onConfirm:async({taskId:b,title:u,description:C,priority:ce,attachExport:ie})=>{S.mode==="create"?await K("create-task",()=>L(a.id,u,S.findingId,C,ce,ie),"Task created from research"):b&&await K("attach-task",()=>H(a.id,b,S.findingId,ie),"Task enriched from research"),U(null)}}):null})()]})}export{Be as ResearchView};
@@ -1 +1 @@
1
- import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{R as B,J as oe,ae as J,af as q,bC as ie,bD as de,b4 as pe,_ as ue}from"./index-w1dPHtmq.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const he="__sync_passphrase__",k={key:"",value:"",description:"",scope:"project",accessPolicy:"prompt",envExportable:!1,envExportKey:""},c={className:"secrets-action-icon","aria-hidden":!0,style:{width:"1em",height:"1em"}},me={...c,className:"secrets-action-icon spin"},be=({addToast:o})=>{const[P,Y]=l.useState([]),[R,K]=l.useState(!0),[M,T]=l.useState(null),[_,y]=l.useState(null),[i,A]=l.useState(null),[G,h]=l.useState(!1),[U,b]=l.useState(null),[n,t]=l.useState(k),[N,f]=l.useState(!1),[$,g]=l.useState({}),[z,D]=l.useState(null),[d,Q]=l.useState(!1),[W,O]=l.useState(!1),[v,V]=l.useState(""),[S,F]=l.useState(""),[X,I]=l.useState(!1),C=l.useRef(new Map),E=l.useRef(new Map),r=l.useCallback(async(s,a)=>{const p=await fetch(s,{...a,headers:{"Content-Type":"application/json",...a?.headers??{}}});if(!p.ok){const u=await p.json().catch(()=>({error:"Request failed"}));throw new Error(String(u?.error??"Request failed"))}if(p.status!==204)return p.json()},[]),m=l.useCallback(async()=>{K(!0),T(null);try{const s=await r("/api/secrets");Y(s.secrets)}catch(s){T(s instanceof Error?s.message:String(s))}finally{K(!1)}},[r]),j=l.useCallback(async()=>{try{const s=await r("/api/secrets/sync-passphrase");Q(!!s.configured)}catch(s){o?.(`Failed to load sync passphrase status: ${s instanceof Error?s.message:String(s)}`,"error")}},[o,r]);l.useEffect(()=>(m(),j(),()=>{C.current.forEach(s=>clearTimeout(s)),E.current.forEach(s=>clearTimeout(s))}),[m,j]);const w=()=>{O(!1),V(""),F("")},Z=async s=>{await r("/api/secrets/sync-passphrase",{method:"PUT",body:JSON.stringify({passphrase:s})})},ee=async()=>{I(!0);try{await Z(v),o?.(d?"Sync passphrase rotated":"Sync passphrase set","success"),w(),await j()}catch(s){o?.(`Failed to save sync passphrase: ${s instanceof Error?s.message:String(s)}`,"error")}finally{I(!1)}},se=async()=>{if(window.confirm("Clear the cross-node sync passphrase? Existing sync pairs will stop working until you set a new passphrase."))try{await r("/api/secrets/sync-passphrase",{method:"DELETE"}),o?.("Sync passphrase cleared","success"),await j()}catch(a){o?.(`Failed to clear sync passphrase: ${a instanceof Error?a.message:String(a)}`,"error")}},ae=()=>{A(null),t(k),h(!0),f(!1),y(null)},ne=s=>{A(s),t({key:s.key,value:"",description:s.description??"",scope:s.scope,accessPolicy:s.accessPolicy,envExportable:s.envExportable,envExportKey:s.envExportKey??""}),h(!0),f(!1),y(null)},le=async()=>{y(null);try{if(i){const s={key:n.key,description:n.description||null,accessPolicy:n.accessPolicy,envExportable:n.envExportable,envExportKey:n.envExportable&&n.envExportKey||null};n.value&&(s.value=n.value),await r(`/api/secrets/${i.scope}/${i.id}`,{method:"PATCH",body:JSON.stringify(s)})}else await r("/api/secrets",{method:"POST",body:JSON.stringify({scope:n.scope,key:n.key,value:n.value,description:n.description||null,accessPolicy:n.accessPolicy,envExportable:n.envExportable,envExportKey:n.envExportable&&n.envExportKey||null})});h(!1),t(k),await m()}catch(s){y(s instanceof Error?s.message:String(s))}},te=async s=>{const a=await r(`/api/secrets/${s.scope}/${s.id}/reveal`,{method:"POST"});g(x=>({...x,[s.id]:a.value})),o?.("Revealed","success");const p=setTimeout(()=>{g(x=>({...x,[s.id]:null}))},3e4),u=C.current.get(s.id);u&&clearTimeout(u),C.current.set(s.id,p)},ce=async s=>{const a=$[s.id];if(!a)return;await navigator.clipboard.writeText(a),D(s.id),o?.("Copied","success");const p=setTimeout(()=>{D(null),g(x=>({...x,[s.id]:null}))},1500),u=E.current.get(s.id);u&&clearTimeout(u),E.current.set(s.id,p)},re=async s=>{await r(`/api/secrets/${s.scope}/${s.id}`,{method:"DELETE"}),b(null),await m()},H=l.useMemo(()=>[...P].filter(s=>!(s.scope==="global"&&s.key===he)).sort((s,a)=>s.key.localeCompare(a.key)),[P]),L=v.length>0&&v===S;return e.jsxs("section",{className:"secrets-view",children:[e.jsxs("div",{className:"secrets-header",children:[e.jsx("h2",{children:"Secrets"}),e.jsxs("div",{className:"secrets-header-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:()=>void m(),children:[e.jsx(B,{...c})," Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:ae,children:[e.jsx(oe,{...c})," Add Secret"]})]})]}),e.jsxs("article",{className:"card secrets-sync-card",children:[e.jsxs("div",{className:"secrets-sync-header",children:[e.jsxs("div",{children:[e.jsx("h3",{children:"Cross-Node Sync Passphrase"}),e.jsxs("p",{className:"secrets-sync-status",children:[e.jsx("span",{className:`status-dot ${d?"status-dot--online":"status-dot--pending"}`,"aria-hidden":"true"})," ",d?"Configured":"Not configured"]})]}),e.jsxs("div",{className:"secrets-sync-actions",children:[e.jsx("button",{className:"btn",onClick:()=>O(!0),children:d?"Rotate":"Set passphrase"}),d?e.jsx("button",{className:"btn btn-danger",onClick:()=>void se(),children:"Clear"}):null]})]}),e.jsx("p",{className:"secrets-sync-copy",children:"Shared passphrase used to wrap cross-node secret bundles. Both nodes in a sync pair must share the same value. Stored locally only; never transmitted."})]}),M?e.jsx("div",{className:"form-error",children:M}):null,R?e.jsxs("div",{className:"secrets-loading",children:[e.jsx(B,{...me})," Loading…"]}):null,!R&&H.length===0?e.jsx("div",{className:"secrets-empty",children:"No secrets found."}):null,e.jsx("div",{className:"secrets-list",children:H.map(s=>{const a=$[s.id];return e.jsxs("article",{className:"card secrets-row",children:[e.jsxs("div",{className:"secrets-row-main",children:[e.jsx("div",{className:"secrets-row-key",children:s.key}),e.jsxs("div",{className:"secrets-row-meta",children:[e.jsx("span",{className:"secrets-chip",children:s.scope}),e.jsx("span",{className:"secrets-chip",children:s.accessPolicy}),s.envExportable?e.jsx("span",{className:"secrets-chip",children:"env_exportable"}):null]}),a?e.jsx("pre",{className:"secrets-revealed",children:a}):null]}),e.jsxs("div",{className:"secrets-row-side",children:[e.jsx("span",{className:"secrets-row-read",children:s.lastReadAt?new Date(s.lastReadAt).toLocaleString():"Never read"}),e.jsxs("div",{className:"secrets-row-actions",children:[e.jsx("button",{type:"button",className:"btn btn-icon secrets-visibility-toggle",onClick:()=>void te(s),"aria-label":a?"Hide":"Reveal",children:a?e.jsx(J,{...c}):e.jsx(q,{...c})}),e.jsx("button",{className:"btn btn-icon",onClick:()=>void ce(s),"aria-label":"Copy",disabled:!a,children:z===s.id?e.jsx(ie,{...c}):e.jsx(de,{...c})}),e.jsx("button",{className:"btn btn-icon",onClick:()=>ne(s),"aria-label":"Edit",children:e.jsx(pe,{...c})}),e.jsx("button",{className:"btn btn-icon btn-danger",onClick:()=>b(s.id),"aria-label":"Delete",children:e.jsx(ue,{...c})})]}),U===s.id?e.jsxs("div",{className:"secrets-confirm",children:[e.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>void re(s),children:"Confirm"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>b(null),children:"Cancel"})]}):null]})]},s.id)})}),W?e.jsx("div",{className:"modal-overlay open",role:"presentation",children:e.jsxs("div",{className:"modal",role:"dialog","aria-modal":"true","aria-label":d?"Rotate sync passphrase":"Set sync passphrase",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:d?"Rotate sync passphrase":"Set sync passphrase"}),e.jsx("button",{className:"modal-close",onClick:w,"aria-label":"Close",children:"×"})]}),e.jsxs("div",{className:"secrets-modal-body",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Passphrase"}),e.jsx("input",{"aria-label":"Passphrase",className:"input",type:"password",autoComplete:"new-password",value:v,onChange:s=>V(s.target.value)})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Confirm passphrase"}),e.jsx("input",{"aria-label":"Confirm passphrase",className:"input",type:"password",autoComplete:"new-password",value:S,onChange:s=>F(s.target.value)})]}),!L&&S.length>0?e.jsx("div",{className:"form-error",children:"Passphrases must match."}):null]}),e.jsx("div",{className:"modal-actions",children:e.jsxs("div",{className:"modal-actions-right",children:[e.jsx("button",{className:"btn",onClick:w,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void ee(),disabled:!L||X,children:d?"Rotate":"Set passphrase"})]})})]})}):null,G?e.jsx("div",{className:"modal-overlay open",role:"presentation",children:e.jsxs("div",{className:"modal",role:"dialog","aria-modal":"true","aria-label":i?"Edit secret":"Add secret",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:i?"Edit secret":"Add secret"}),e.jsx("button",{className:"modal-close",onClick:()=>h(!1),"aria-label":"Close",children:"×"})]}),e.jsxs("div",{className:"secrets-modal-body",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Key"}),e.jsx("input",{className:"input",value:n.key,onChange:s=>t(a=>({...a,key:s.target.value}))})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Value"}),e.jsxs("div",{className:"secrets-value-row",children:[e.jsx("input",{className:"input",type:N?"text":"password",autoComplete:"off",spellCheck:!1,value:n.value,onChange:s=>t(a=>({...a,value:s.target.value}))}),e.jsx("button",{type:"button",className:"btn btn-icon secrets-visibility-toggle",onClick:()=>f(s=>!s),"aria-label":N?"Hide value":"Show value",children:N?e.jsx(J,{...c}):e.jsx(q,{...c})})]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Description"}),e.jsx("textarea",{className:"input",value:n.description,onChange:s=>t(a=>({...a,description:s.target.value}))})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Scope"}),e.jsxs("div",{className:"secrets-radio-row",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",checked:n.scope==="project",onChange:()=>t(s=>({...s,scope:"project"})),disabled:!!i})," Project"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",checked:n.scope==="global",onChange:()=>t(s=>({...s,scope:"global"})),disabled:!!i})," Global"]})]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Access policy"}),e.jsxs("select",{className:"select",value:n.accessPolicy,onChange:s=>t(a=>({...a,accessPolicy:s.target.value})),children:[e.jsx("option",{value:"auto",children:"auto"}),e.jsx("option",{value:"prompt",children:"prompt"}),e.jsx("option",{value:"deny",children:"deny"})]})]}),e.jsx("div",{className:"form-group",children:e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:n.envExportable,onChange:s=>t(a=>({...a,envExportable:s.target.checked}))})," Export to env"]})}),n.envExportable?e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Env key"}),e.jsx("input",{className:"input",value:n.envExportKey,onChange:s=>t(a=>({...a,envExportKey:s.target.value}))})]}):null,_?e.jsx("div",{className:"form-error",children:_}):null]}),e.jsx("div",{className:"modal-actions",children:e.jsxs("div",{className:"modal-actions-right",children:[e.jsx("button",{className:"btn",onClick:()=>h(!1),children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void le(),children:i?"Save":"Create"})]})})]})}):null]})};export{be as SecretsView};
1
+ import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{R as B,J as oe,ae as J,af as q,bC as ie,bD as de,b4 as pe,_ as ue}from"./index-BonLYFW-.js";import"./vendor-xterm-DzcZoU0P.js";import"./vendor-codemirror-jBKmHyH0.js";const he="__sync_passphrase__",k={key:"",value:"",description:"",scope:"project",accessPolicy:"prompt",envExportable:!1,envExportKey:""},c={className:"secrets-action-icon","aria-hidden":!0,style:{width:"1em",height:"1em"}},me={...c,className:"secrets-action-icon spin"},be=({addToast:o})=>{const[P,Y]=l.useState([]),[R,K]=l.useState(!0),[M,T]=l.useState(null),[_,y]=l.useState(null),[i,A]=l.useState(null),[G,h]=l.useState(!1),[U,b]=l.useState(null),[n,t]=l.useState(k),[N,f]=l.useState(!1),[$,g]=l.useState({}),[z,D]=l.useState(null),[d,Q]=l.useState(!1),[W,O]=l.useState(!1),[v,V]=l.useState(""),[S,F]=l.useState(""),[X,I]=l.useState(!1),C=l.useRef(new Map),E=l.useRef(new Map),r=l.useCallback(async(s,a)=>{const p=await fetch(s,{...a,headers:{"Content-Type":"application/json",...a?.headers??{}}});if(!p.ok){const u=await p.json().catch(()=>({error:"Request failed"}));throw new Error(String(u?.error??"Request failed"))}if(p.status!==204)return p.json()},[]),m=l.useCallback(async()=>{K(!0),T(null);try{const s=await r("/api/secrets");Y(s.secrets)}catch(s){T(s instanceof Error?s.message:String(s))}finally{K(!1)}},[r]),j=l.useCallback(async()=>{try{const s=await r("/api/secrets/sync-passphrase");Q(!!s.configured)}catch(s){o?.(`Failed to load sync passphrase status: ${s instanceof Error?s.message:String(s)}`,"error")}},[o,r]);l.useEffect(()=>(m(),j(),()=>{C.current.forEach(s=>clearTimeout(s)),E.current.forEach(s=>clearTimeout(s))}),[m,j]);const w=()=>{O(!1),V(""),F("")},Z=async s=>{await r("/api/secrets/sync-passphrase",{method:"PUT",body:JSON.stringify({passphrase:s})})},ee=async()=>{I(!0);try{await Z(v),o?.(d?"Sync passphrase rotated":"Sync passphrase set","success"),w(),await j()}catch(s){o?.(`Failed to save sync passphrase: ${s instanceof Error?s.message:String(s)}`,"error")}finally{I(!1)}},se=async()=>{if(window.confirm("Clear the cross-node sync passphrase? Existing sync pairs will stop working until you set a new passphrase."))try{await r("/api/secrets/sync-passphrase",{method:"DELETE"}),o?.("Sync passphrase cleared","success"),await j()}catch(a){o?.(`Failed to clear sync passphrase: ${a instanceof Error?a.message:String(a)}`,"error")}},ae=()=>{A(null),t(k),h(!0),f(!1),y(null)},ne=s=>{A(s),t({key:s.key,value:"",description:s.description??"",scope:s.scope,accessPolicy:s.accessPolicy,envExportable:s.envExportable,envExportKey:s.envExportKey??""}),h(!0),f(!1),y(null)},le=async()=>{y(null);try{if(i){const s={key:n.key,description:n.description||null,accessPolicy:n.accessPolicy,envExportable:n.envExportable,envExportKey:n.envExportable&&n.envExportKey||null};n.value&&(s.value=n.value),await r(`/api/secrets/${i.scope}/${i.id}`,{method:"PATCH",body:JSON.stringify(s)})}else await r("/api/secrets",{method:"POST",body:JSON.stringify({scope:n.scope,key:n.key,value:n.value,description:n.description||null,accessPolicy:n.accessPolicy,envExportable:n.envExportable,envExportKey:n.envExportable&&n.envExportKey||null})});h(!1),t(k),await m()}catch(s){y(s instanceof Error?s.message:String(s))}},te=async s=>{const a=await r(`/api/secrets/${s.scope}/${s.id}/reveal`,{method:"POST"});g(x=>({...x,[s.id]:a.value})),o?.("Revealed","success");const p=setTimeout(()=>{g(x=>({...x,[s.id]:null}))},3e4),u=C.current.get(s.id);u&&clearTimeout(u),C.current.set(s.id,p)},ce=async s=>{const a=$[s.id];if(!a)return;await navigator.clipboard.writeText(a),D(s.id),o?.("Copied","success");const p=setTimeout(()=>{D(null),g(x=>({...x,[s.id]:null}))},1500),u=E.current.get(s.id);u&&clearTimeout(u),E.current.set(s.id,p)},re=async s=>{await r(`/api/secrets/${s.scope}/${s.id}`,{method:"DELETE"}),b(null),await m()},H=l.useMemo(()=>[...P].filter(s=>!(s.scope==="global"&&s.key===he)).sort((s,a)=>s.key.localeCompare(a.key)),[P]),L=v.length>0&&v===S;return e.jsxs("section",{className:"secrets-view",children:[e.jsxs("div",{className:"secrets-header",children:[e.jsx("h2",{children:"Secrets"}),e.jsxs("div",{className:"secrets-header-actions",children:[e.jsxs("button",{className:"btn btn-sm",onClick:()=>void m(),children:[e.jsx(B,{...c})," Refresh"]}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:ae,children:[e.jsx(oe,{...c})," Add Secret"]})]})]}),e.jsxs("article",{className:"card secrets-sync-card",children:[e.jsxs("div",{className:"secrets-sync-header",children:[e.jsxs("div",{children:[e.jsx("h3",{children:"Cross-Node Sync Passphrase"}),e.jsxs("p",{className:"secrets-sync-status",children:[e.jsx("span",{className:`status-dot ${d?"status-dot--online":"status-dot--pending"}`,"aria-hidden":"true"})," ",d?"Configured":"Not configured"]})]}),e.jsxs("div",{className:"secrets-sync-actions",children:[e.jsx("button",{className:"btn",onClick:()=>O(!0),children:d?"Rotate":"Set passphrase"}),d?e.jsx("button",{className:"btn btn-danger",onClick:()=>void se(),children:"Clear"}):null]})]}),e.jsx("p",{className:"secrets-sync-copy",children:"Shared passphrase used to wrap cross-node secret bundles. Both nodes in a sync pair must share the same value. Stored locally only; never transmitted."})]}),M?e.jsx("div",{className:"form-error",children:M}):null,R?e.jsxs("div",{className:"secrets-loading",children:[e.jsx(B,{...me})," Loading…"]}):null,!R&&H.length===0?e.jsx("div",{className:"secrets-empty",children:"No secrets found."}):null,e.jsx("div",{className:"secrets-list",children:H.map(s=>{const a=$[s.id];return e.jsxs("article",{className:"card secrets-row",children:[e.jsxs("div",{className:"secrets-row-main",children:[e.jsx("div",{className:"secrets-row-key",children:s.key}),e.jsxs("div",{className:"secrets-row-meta",children:[e.jsx("span",{className:"secrets-chip",children:s.scope}),e.jsx("span",{className:"secrets-chip",children:s.accessPolicy}),s.envExportable?e.jsx("span",{className:"secrets-chip",children:"env_exportable"}):null]}),a?e.jsx("pre",{className:"secrets-revealed",children:a}):null]}),e.jsxs("div",{className:"secrets-row-side",children:[e.jsx("span",{className:"secrets-row-read",children:s.lastReadAt?new Date(s.lastReadAt).toLocaleString():"Never read"}),e.jsxs("div",{className:"secrets-row-actions",children:[e.jsx("button",{type:"button",className:"btn btn-icon secrets-visibility-toggle",onClick:()=>void te(s),"aria-label":a?"Hide":"Reveal",children:a?e.jsx(J,{...c}):e.jsx(q,{...c})}),e.jsx("button",{className:"btn btn-icon",onClick:()=>void ce(s),"aria-label":"Copy",disabled:!a,children:z===s.id?e.jsx(ie,{...c}):e.jsx(de,{...c})}),e.jsx("button",{className:"btn btn-icon",onClick:()=>ne(s),"aria-label":"Edit",children:e.jsx(pe,{...c})}),e.jsx("button",{className:"btn btn-icon btn-danger",onClick:()=>b(s.id),"aria-label":"Delete",children:e.jsx(ue,{...c})})]}),U===s.id?e.jsxs("div",{className:"secrets-confirm",children:[e.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>void re(s),children:"Confirm"}),e.jsx("button",{className:"btn btn-sm",onClick:()=>b(null),children:"Cancel"})]}):null]})]},s.id)})}),W?e.jsx("div",{className:"modal-overlay open",role:"presentation",children:e.jsxs("div",{className:"modal",role:"dialog","aria-modal":"true","aria-label":d?"Rotate sync passphrase":"Set sync passphrase",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:d?"Rotate sync passphrase":"Set sync passphrase"}),e.jsx("button",{className:"modal-close",onClick:w,"aria-label":"Close",children:"×"})]}),e.jsxs("div",{className:"secrets-modal-body",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Passphrase"}),e.jsx("input",{"aria-label":"Passphrase",className:"input",type:"password",autoComplete:"new-password",value:v,onChange:s=>V(s.target.value)})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Confirm passphrase"}),e.jsx("input",{"aria-label":"Confirm passphrase",className:"input",type:"password",autoComplete:"new-password",value:S,onChange:s=>F(s.target.value)})]}),!L&&S.length>0?e.jsx("div",{className:"form-error",children:"Passphrases must match."}):null]}),e.jsx("div",{className:"modal-actions",children:e.jsxs("div",{className:"modal-actions-right",children:[e.jsx("button",{className:"btn",onClick:w,children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void ee(),disabled:!L||X,children:d?"Rotate":"Set passphrase"})]})})]})}):null,G?e.jsx("div",{className:"modal-overlay open",role:"presentation",children:e.jsxs("div",{className:"modal",role:"dialog","aria-modal":"true","aria-label":i?"Edit secret":"Add secret",children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h3",{children:i?"Edit secret":"Add secret"}),e.jsx("button",{className:"modal-close",onClick:()=>h(!1),"aria-label":"Close",children:"×"})]}),e.jsxs("div",{className:"secrets-modal-body",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Key"}),e.jsx("input",{className:"input",value:n.key,onChange:s=>t(a=>({...a,key:s.target.value}))})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Value"}),e.jsxs("div",{className:"secrets-value-row",children:[e.jsx("input",{className:"input",type:N?"text":"password",autoComplete:"off",spellCheck:!1,value:n.value,onChange:s=>t(a=>({...a,value:s.target.value}))}),e.jsx("button",{type:"button",className:"btn btn-icon secrets-visibility-toggle",onClick:()=>f(s=>!s),"aria-label":N?"Hide value":"Show value",children:N?e.jsx(J,{...c}):e.jsx(q,{...c})})]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Description"}),e.jsx("textarea",{className:"input",value:n.description,onChange:s=>t(a=>({...a,description:s.target.value}))})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Scope"}),e.jsxs("div",{className:"secrets-radio-row",children:[e.jsxs("label",{children:[e.jsx("input",{type:"radio",checked:n.scope==="project",onChange:()=>t(s=>({...s,scope:"project"})),disabled:!!i})," Project"]}),e.jsxs("label",{children:[e.jsx("input",{type:"radio",checked:n.scope==="global",onChange:()=>t(s=>({...s,scope:"global"})),disabled:!!i})," Global"]})]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Access policy"}),e.jsxs("select",{className:"select",value:n.accessPolicy,onChange:s=>t(a=>({...a,accessPolicy:s.target.value})),children:[e.jsx("option",{value:"auto",children:"auto"}),e.jsx("option",{value:"prompt",children:"prompt"}),e.jsx("option",{value:"deny",children:"deny"})]})]}),e.jsx("div",{className:"form-group",children:e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:n.envExportable,onChange:s=>t(a=>({...a,envExportable:s.target.checked}))})," Export to env"]})}),n.envExportable?e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Env key"}),e.jsx("input",{className:"input",value:n.envExportKey,onChange:s=>t(a=>({...a,envExportKey:s.target.value}))})]}):null,_?e.jsx("div",{className:"form-error",children:_}):null]}),e.jsx("div",{className:"modal-actions",children:e.jsxs("div",{className:"modal-actions-right",children:[e.jsx("button",{className:"btn",onClick:()=>h(!1),children:"Cancel"}),e.jsx("button",{className:"btn btn-primary",onClick:()=>void le(),children:i?"Save":"Create"})]})})]})}):null]})};export{be as SecretsView};
@@ -0,0 +1 @@
1
+ .settings-header-actions{--settings-header-action-height: calc(var(--space-md) * 2 + var(--space-xs) / 2);display:flex;align-items:stretch;gap:var(--space-xs);margin-left:auto;margin-right:var(--space-sm)}.settings-header-actions>.settings-github-star-btn,.settings-header-actions>.settings-header-discord-btn{height:var(--settings-header-action-height);box-sizing:border-box}.settings-header-discord-btn,.settings-footer-help-btn{display:inline-flex;align-items:center}@media(max-width:768px){.settings-modal .modal-header{flex-wrap:nowrap;align-items:center;column-gap:var(--space-sm)}.settings-modal-heading{flex:1 1 0;min-width:0}.settings-header-actions{margin-left:auto;margin-right:var(--space-sm)}}.settings-github-star-btn{display:inline-flex;align-items:stretch;border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-pill);background:var(--card);color:var(--text);font-size:12px;font-weight:500;text-decoration:none;overflow:hidden;transition:border-color var(--transition-fast),background var(--transition-fast)}.settings-github-star-btn:hover{border-color:var(--text-muted);background:var(--card-hover)}.settings-github-star-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);border-color:var(--todo)}.settings-github-star-btn__action{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--space-xs) calc(var(--space-sm) + var(--space-xs) / 2)}.settings-github-star-btn__count{display:inline-flex;align-items:center;padding:var(--space-xs) calc(var(--space-sm) + var(--space-xs) / 4);border-left:var(--btn-border-width) solid var(--border);background:color-mix(in srgb,var(--surface) 60%,var(--card));color:var(--text-muted);font-variant-numeric:tabular-nums}.settings-modal{width:min(95vw,1100px);max-width:95vw;min-width:520px;height:80vh;min-height:480px;max-height:calc(100dvh - var(--overlay-padding-top, 10vh) - 16px);overflow:hidden;resize:both}@media(max-width:768px){.modal-overlay.settings-modal-overlay,.modal-overlay:has(.settings-modal){padding:0;inset:0;align-items:stretch;justify-content:stretch}.modal.settings-modal{width:100vw;min-width:0;max-width:100vw;height:100dvh;min-height:100dvh;max-height:100dvh;margin:0;border:none;border-radius:0;resize:none;flex:1 1 auto}.modal.settings-modal[style*=--keyboard-overlap]{height:var(--vv-height, 100dvh);min-height:var(--vv-height, 100dvh);max-height:var(--vv-height, 100dvh);transform:translateY(var(--vv-offset-top, 0px));will-change:transform}}.settings-modal-heading{display:flex;flex-direction:column;gap:var(--space-xs)}.settings-modal-heading h3{margin:0}.settings-modal-version{margin:0;font-size:.85rem;color:var(--text-muted);font-weight:500}.settings-modal-footer-version{display:flex;align-items:center;gap:var(--space-xs);margin-right:var(--space-sm);min-width:0}.settings-update-check{display:flex;align-items:center;gap:var(--space-sm);min-width:0}@media(max-width:768px){.settings-modal-footer-version{flex:1 1 100%;margin-right:0}.settings-update-check{flex-wrap:wrap;row-gap:var(--space-xs)}.settings-footer-help-btn{flex-shrink:0}}.settings-version-check-btn{--settings-inline-touch-target: calc(var(--space-lg) + var(--space-lg) + var(--space-xs));display:inline-flex;align-items:center;gap:var(--space-xs);margin:0;min-height:var(--settings-inline-touch-target);padding:var(--space-xs) var(--space-sm);border:none;background:transparent;color:var(--text-muted);cursor:pointer;transition:opacity var(--transition-fast),box-shadow var(--transition-fast)}.settings-version-check-btn:hover:not(:disabled){opacity:.85}.settings-version-check-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);border-radius:var(--radius-sm)}.settings-version-check-btn:disabled{cursor:default;opacity:.7}.settings-version-check-btn svg{color:var(--text-muted)}.settings-version-check-btn svg.spinning{animation:settings-update-spin 1s linear infinite}.settings-update-result{font-size:.85rem;font-weight:500}.settings-update-result--up-to-date{color:var(--color-success)}.settings-update-result--available{color:var(--color-info)}.settings-update-result--error{color:var(--text-muted)}.settings-update-result-link{color:var(--color-info);text-decoration:underline;transition:color var(--transition-fast),box-shadow var(--transition-fast)}.settings-update-result-link:hover{color:color-mix(in srgb,var(--color-info) 80%,var(--text))}.settings-update-result-link:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);border-radius:var(--radius-sm)}@keyframes settings-update-spin{to{transform:rotate(360deg)}}.backup-stats{display:flex;align-items:center;gap:var(--space-lg);padding:var(--space-sm) var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:color-mix(in srgb,var(--surface) 85%,transparent)}.backup-stat{display:flex;flex:1 1 0;flex-direction:column;align-items:center;gap:var(--space-xs);min-width:0}.backup-stat-value{color:var(--text);font-size:1rem;font-weight:600;font-variant-numeric:tabular-nums}.backup-stat-label{color:var(--text-muted);font-size:.75rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.backup-list{margin-top:var(--space-sm)}.backup-list summary{padding:var(--space-sm) 0;color:var(--text-muted);cursor:pointer;transition:color var(--transition-fast)}.backup-list summary:hover{color:var(--text)}.backup-list summary:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:var(--focus-ring-strong)}.backup-list ul{display:flex;flex-direction:column;gap:var(--space-xs);margin:0;margin-top:var(--space-sm);padding:0;list-style:none}.backup-list li{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);padding:var(--space-sm) 0;border-top:var(--btn-border-width) solid color-mix(in srgb,var(--border) 80%,transparent)}.backup-list li code{min-width:0;color:var(--text);font-family:var(--font-mono);font-size:.75rem;white-space:nowrap;overflow-x:auto}.backup-size{color:var(--text-muted);font-family:var(--font-mono);font-size:.75rem;text-align:right;white-space:nowrap}@media(max-width:768px){.backup-stats{flex-direction:column;align-items:stretch;gap:var(--space-sm)}.backup-stat{align-items:flex-start}.backup-list ul{max-height:calc(var(--space-xl) * 9 + var(--space-md));overflow-y:auto;-webkit-overflow-scrolling:touch}.backup-list li code{white-space:normal;overflow-wrap:anywhere;word-break:normal}}.settings-layout{display:flex;flex:1;flex-direction:row;min-height:0;overflow:hidden}.settings-mobile-section-picker{display:none}.settings-sidebar{width:170px;min-width:170px;border-right:1px solid var(--border);display:flex;flex-direction:column;overflow-y:auto;padding:var(--space-sm) var(--space-sm);gap:calc(var(--space-xs) / 2);background:color-mix(in srgb,var(--text) 10%,transparent);scrollbar-color:var(--border) transparent;scrollbar-width:thin}.settings-sidebar::-webkit-scrollbar{width:6px}.settings-sidebar::-webkit-scrollbar-track{background:transparent}.settings-sidebar::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius-sm)}.settings-sidebar::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.settings-research-source-locked{cursor:default;color:var(--text-muted)!important}.settings-research-source-locked input[type=checkbox]{cursor:not-allowed}.settings-research-source-grid,.settings-research-limits-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-sm)}.settings-research-limit-field{display:flex;flex-direction:column;gap:var(--space-xs)}.settings-research-limits-error{grid-column:1 / -1}@media(max-width:768px){.settings-research-source-grid,.settings-research-limits-grid{grid-template-columns:1fr}}.settings-nav-item{display:block;width:100%;padding:var(--space-sm) var(--space-md);font-size:13px;font-weight:500;color:var(--text-muted);background:none;border:none;border-left:3px solid transparent;border-radius:0 var(--radius-md) var(--radius-md) 0;cursor:pointer;text-align:left;transition:background var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast)}.settings-nav-item:hover{background:var(--bg);color:var(--text);border-left-color:var(--border)}.settings-nav-item:focus-visible{box-shadow:var(--focus-ring-strong);outline:none}.settings-nav-item.active{background:var(--bg);color:var(--todo);font-weight:600;border-left-color:var(--todo)}.settings-group-header{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);padding:var(--space-md) var(--space-md) var(--space-xs);margin-top:var(--space-sm);user-select:none}.settings-group-header:first-child{margin-top:0}.settings-content{flex:1;overflow-x:hidden;overflow-y:auto;padding:4px 0 12px;scrollbar-color:var(--border) transparent;scrollbar-width:thin}.settings-content::-webkit-scrollbar{width:6px}.settings-content::-webkit-scrollbar-track{background:transparent}.settings-content::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius-sm)}.settings-content::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.settings-content>*{animation:settingsFadeIn var(--transition-normal)}@keyframes settingsFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.settings-section-heading{font-size:14px;font-weight:600;padding:var(--space-lg) var(--space-xl) var(--space-md);margin:0 0 var(--space-md);color:var(--text);border-bottom:1px solid var(--border)}.settings-content>.settings-section-heading:first-child,.settings-modal-section>.settings-section-heading:first-child{padding-top:var(--space-md)}.settings-section-heading--spaced{margin-top:var(--space-lg)}.settings-section-description{margin:0;padding:0 var(--space-xl);margin-bottom:var(--space-sm);color:var(--text-muted);font-size:13px;line-height:1.5}.settings-plugins-subsection-toggle{display:inline-flex;gap:var(--space-xs);padding:0 var(--space-xl);margin:var(--space-md) 0}.settings-plugins-subsection-btn{display:inline-flex;align-items:center;justify-content:center;border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-pill);background:var(--surface);color:var(--text-muted);font-size:.85rem;font-weight:600;padding:var(--space-xs) var(--space-md);cursor:pointer;transition:background var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast),box-shadow var(--transition-fast)}.settings-plugins-subsection-btn:hover{background:var(--surface-hover, color-mix(in srgb, var(--text) 6%, transparent));color:var(--text)}.settings-plugins-subsection-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.settings-plugins-subsection-btn.active{background:color-mix(in srgb,var(--todo) 14%,transparent);border-color:color-mix(in srgb,var(--todo) 45%,var(--border));color:var(--todo)}.settings-plugins-subsection-panel{padding-bottom:var(--space-md)}.settings-scope-icon{margin-right:6px;display:inline-flex;vertical-align:middle;color:var(--text-muted)}.settings-scope-banner{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-xl);margin:0 var(--space-xl) var(--space-xs);font-size:12px;border-radius:var(--radius-md);color:var(--text-muted)}.settings-scope-global{background:color-mix(in srgb,var(--color-info) 8%,transparent);border-left:3px solid color-mix(in srgb,var(--color-info) 40%,transparent)}.settings-scope-project{background:color-mix(in srgb,var(--color-success) 8%,transparent);border-left:3px solid color-mix(in srgb,var(--color-success) 40%,transparent)}.settings-scope-mixed{background:color-mix(in srgb,var(--triage) 8%,transparent);border-left:3px solid color-mix(in srgb,var(--triage) 40%,transparent)}.settings-note{display:block;padding:0 var(--space-xl);margin-top:var(--space-xs);font-size:12px;color:var(--text-muted)}.form-inline-group{display:flex;align-items:center;gap:var(--space-sm)}.form-inline-group .input{flex:1;min-width:0}.btn-link{background:none;border:none;padding:0;font-size:12px;color:var(--accent, #4a90e2);cursor:pointer;text-decoration:underline;white-space:nowrap}.btn-link:hover{text-decoration:none}.settings-overlap-ignore-group code{font-family:var(--font-mono);font-size:.9em}.settings-button-row{display:flex;flex-wrap:wrap;gap:var(--space-sm);margin-top:var(--space-sm)}.settings-raw-output{margin:var(--space-sm) 0 0;padding:var(--space-sm);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);color:var(--text-muted);max-height:calc(var(--space-2xl) * 7);overflow:auto;font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs))}.settings-url-output{display:block;margin-top:var(--space-xs);padding:var(--space-sm);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);color:var(--text-muted);font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));overflow-wrap:anywhere;word-break:break-word;overflow-x:auto;max-width:100%}.settings-qr-preview{margin-top:var(--space-sm);display:flex;flex-direction:column;gap:var(--space-sm)}.settings-qr-preview-label{margin:0;font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.settings-qr-preview-image-wrap{width:fit-content;max-width:100%;padding:var(--space-sm);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--card)}.settings-qr-preview-image{display:block;width:min(calc(var(--space-2xl) * 6),100%);height:auto;aspect-ratio:1 / 1}.remote-provider-selector{display:flex;gap:var(--space-xs);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);padding:var(--space-xs);background:var(--surface)}.remote-provider-option{position:relative;flex:1;cursor:pointer}.remote-provider-option input{position:absolute;opacity:0;width:0;height:0}.remote-provider-option span{display:block;padding:var(--space-sm) var(--space-md);text-align:center;border-radius:var(--radius-sm);border:var(--btn-border-width) solid transparent;color:var(--text-muted);transition:background var(--transition-fast),color var(--transition-fast),border-color var(--transition-fast)}.remote-provider-option-content{display:inline-flex;align-items:center;gap:var(--space-xs)}.remote-provider-option input:checked+span{background:var(--card);color:var(--text);border-color:var(--border)}.remote-provider-option input:focus-visible+span{box-shadow:var(--focus-ring-strong)}.remote-status-bar{--status-color: var(--text-muted);display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);border-radius:var(--radius-md);margin:0 var(--space-xl) var(--space-md);background:color-mix(in srgb,var(--status-color) 10%,transparent)}.remote-status-bar--running{--status-color: var(--color-success)}.remote-status-bar--starting{--status-color: var(--color-warning)}.remote-status-bar--error{--status-color: var(--color-error)}.remote-status-bar--stopped{--status-color: var(--text-muted)}.remote-share-block{display:flex;flex-direction:column;gap:var(--space-sm);margin:0 var(--space-xl) var(--space-md);padding:var(--space-sm) var(--space-md);border:1px solid var(--border);border-radius:var(--radius-md);background:color-mix(in srgb,var(--text-muted) 5%,transparent)}.remote-share-row{display:flex;flex-direction:column;gap:var(--space-xs)}.remote-share-row .settings-qr-preview-image{margin-top:var(--space-xs)}.remote-status-dot{width:var(--space-sm);height:var(--space-sm);border-radius:50%;display:inline-block;flex-shrink:0}.remote-status-dot--running{background:var(--color-success)}.remote-status-dot--starting{background:var(--color-warning)}.remote-status-dot--error{background:var(--color-error)}.remote-status-dot--stopped{background:var(--text-muted)}.remote-status-url{margin-left:auto;font-family:var(--font-mono);overflow-wrap:anywhere;word-break:break-word;user-select:all}.remote-provider-settings{display:flex;flex-direction:column;gap:var(--space-sm)}.remote-cli-detection{display:flex;align-items:flex-start;gap:var(--space-sm);margin:0 var(--space-xl) var(--space-md);padding:var(--space-sm) var(--space-md);border-radius:var(--radius-sm)}.remote-cli-detection--available{background:color-mix(in srgb,var(--color-success) 10%,transparent);color:var(--color-success)}.remote-cli-detection--missing{background:color-mix(in srgb,var(--color-warning) 10%,transparent);color:var(--color-warning)}.remote-cli-detection-content{display:flex;flex-direction:column;gap:var(--space-xs);color:var(--text)}.remote-cli-detection .btn{align-self:flex-start}.remote-cli-install-error{color:var(--color-error)}.remote-cli-manual{color:var(--text-dim)}.remote-external-tunnel-panel{display:flex;flex-direction:column;gap:var(--space-sm);margin:0 var(--space-xl) var(--space-md);padding:var(--space-sm) var(--space-md);border:1px solid var(--border);border-radius:var(--radius-md);background:color-mix(in srgb,var(--color-info) 10%,transparent)}.remote-external-tunnel-header{display:flex;align-items:center;gap:var(--space-sm);color:var(--color-info)}.remote-external-tunnel-qr{display:flex;flex-direction:column;gap:var(--space-xs)}.remote-external-tunnel-actions{display:flex;flex-direction:column;gap:var(--space-sm)}.remote-advanced-details{margin:var(--space-lg) var(--space-xl) 0;border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);background:var(--surface)}.remote-advanced-details>summary{cursor:pointer;color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs));list-style:none}.remote-advanced-details>summary::-webkit-details-marker{display:none}.remote-advanced-details>summary:before{content:"▸";margin-right:var(--space-xs)}.remote-advanced-details[open]>summary:before{content:"▾"}.settings-option-details{margin-top:var(--space-xs)}.settings-research-provider-group{display:flex;flex-direction:column;gap:var(--space-sm)}.settings-research-provider-advanced-details{margin-left:var(--space-md)}.settings-research-empty-state{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-sm)}@media(max-width:768px){.settings-research-provider-advanced-details{margin-left:0}}.settings-option-details>summary{cursor:pointer;color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs));list-style:none}.settings-option-details>summary::-webkit-details-marker{display:none}.settings-option-details>summary:before{content:"▸";margin-right:var(--space-xs)}.settings-option-details[open]>summary:before{content:"▾"}.remote-cf-advanced-details{margin-top:var(--space-xs)}.remote-cf-advanced-details>summary{cursor:pointer;color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs));list-style:none}.remote-cf-advanced-details>summary::-webkit-details-marker{display:none}.remote-cf-advanced-details>summary:before{content:"▸";margin-right:var(--space-xs)}.remote-cf-advanced-details[open]>summary:before{content:"▾"}.remote-cf-advanced-fields{display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.remote-tunnel-actions{margin-top:var(--space-md)}.remote-tunnel-actions .btn{width:100%}.settings-overlap-ignore-list{display:flex;flex-direction:column;gap:var(--space-sm);margin:var(--space-sm) 0}.settings-overlap-ignore-row,.settings-overlap-ignore-path-controls{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--space-sm);align-items:center}.settings-overlap-path-picker-modal{max-width:min(960px,calc(100vw - var(--space-2xl)))}.settings-overlap-path-picker-body{display:flex;flex-direction:column;gap:var(--space-sm);max-height:min(70vh,720px)}.settings-overlap-path-picker-note{margin:0;font-size:12px;color:var(--text-muted)}.settings-section-divider{border-top:1px solid var(--border);margin:var(--space-lg) var(--space-xl)}@media(max-width:768px){.settings-note{padding:0 var(--space-lg)}.settings-overlap-ignore-row,.settings-overlap-ignore-path-controls{grid-template-columns:minmax(0,1fr)}.settings-overlap-ignore-row>.btn{justify-self:start}.settings-overlap-path-picker-modal{max-width:calc(100vw - var(--space-md))}.remote-provider-selector{flex-direction:column}.remote-status-bar{flex-wrap:wrap;margin:0 var(--space-lg) var(--space-md)}.remote-share-block{margin:0 var(--space-lg) var(--space-md)}.remote-status-url{width:100%;margin-left:0;font-size:.8em}.remote-provider-option,.remote-tunnel-actions .btn{min-height:36px}.remote-cli-detection,.remote-external-tunnel-panel{margin:0 var(--space-lg) var(--space-md)}}.ntfy-advanced-disclosure{margin-top:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.ntfy-advanced-disclosure>summary{cursor:pointer;list-style:none;padding:var(--space-sm) var(--space-md);font-size:12px;font-weight:600;color:var(--text)}.ntfy-advanced-disclosure>summary::-webkit-details-marker{display:none}.ntfy-advanced-content{padding:0 var(--space-md) var(--space-md);display:flex;flex-direction:column;gap:var(--space-sm)}.settings-inline-link{color:var(--todo);text-decoration:none;transition:text-decoration var(--transition-fast)}.settings-inline-link:hover{text-decoration:underline}.settings-inline-link:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);border-radius:var(--radius-sm)}.notification-provider-card{border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-lg);background:var(--surface);margin:0 var(--space-xl) var(--space-lg);overflow:hidden}.notification-provider-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-md) var(--space-lg);border-bottom:var(--btn-border-width) solid var(--border)}.notification-provider-body{padding:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-lg)}.notification-provider-actions{display:flex;flex-wrap:wrap;gap:var(--space-sm);padding-top:var(--space-md);border-top:var(--btn-border-width) solid var(--border);margin-top:var(--space-md)}.notification-test-feedback{display:flex;flex-direction:column;gap:var(--space-xs);margin-top:var(--space-sm)}.notification-test-feedback-item{border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-sm);padding:var(--space-xs) var(--space-sm)}.notification-test-feedback-item--success{border-color:color-mix(in srgb,var(--color-success) 45%,var(--border));background:color-mix(in srgb,var(--color-success) 8%,transparent);color:var(--color-success)}.notification-test-feedback-item--error{border-color:color-mix(in srgb,var(--color-error) 45%,var(--border));background:color-mix(in srgb,var(--color-error) 8%,transparent);color:var(--color-error)}@media(max-width:768px){.notification-provider-actions{flex-direction:column}.notification-provider-actions .btn{width:100%}}.memory-status-message{display:flex;gap:var(--space-md);align-items:center;justify-content:space-between;margin-bottom:var(--space-md)}.memory-status-message span{min-width:0}.memory-retrieval-test{margin-top:var(--space-lg)}.memory-test-result{margin:0 var(--space-xl) var(--space-lg);padding:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--card)}.memory-test-result strong,.memory-test-result span{color:var(--text);font-size:12px}.memory-test-result small{display:block;margin-top:var(--space-xs);color:var(--text-muted);font-size:12px}.memory-test-result ul{margin:var(--space-md) 0 0;padding:0;list-style:none}.memory-test-result li{padding-top:var(--space-sm);border-top:var(--btn-border-width) solid var(--border)}.memory-test-result li+li{margin-top:var(--space-sm)}.memory-test-result p{margin:var(--space-xs) 0 0;color:var(--text-muted);font-size:12px;line-height:1.5;overflow-wrap:anywhere}.memory-editor-section{margin-top:var(--space-lg);display:flex;flex:1 1 auto;flex-direction:column;min-height:0}.memory-editor-form-group{display:flex;flex:1 1 auto;flex-direction:column;min-height:0}.memory-file-summary{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--space-xs) var(--space-md);align-items:center;margin:0 var(--space-xl) var(--space-md);padding:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--card)}.memory-file-summary span{display:inline-flex;align-items:center;justify-content:center;padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);color:var(--color-info);background:color-mix(in srgb,var(--color-info) 12%,transparent);font-size:11px;font-weight:600}.memory-file-summary strong{min-width:0;overflow-wrap:anywhere;color:var(--text);font-family:var(--font-mono);font-size:12px}.memory-file-summary small{grid-column:2;color:var(--text-muted);font-size:12px}.memory-editor-frame{min-height:50vh;border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);overflow:hidden;display:flex;flex:1 1 auto;flex-direction:column;min-width:0}.auth-panel-body{padding-inline:var(--space-md)}.auth-section-hint{padding:var(--space-md) var(--space-lg);margin-bottom:var(--space-md);background:var(--bg-tertiary);border-radius:var(--radius-md);font-size:13px;color:var(--text-muted);border-left:3px solid var(--text-muted)}.auth-provider-group{margin-bottom:calc(var(--space-sm) + var(--space-xs) / 2)}.auth-group-label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted);margin-bottom:var(--space-xs);padding:0 4px}.auth-provider-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);margin-bottom:var(--space-xs);overflow:hidden;transition:border-color var(--transition-fast),box-shadow var(--transition-fast)}.auth-provider-card:hover{border-color:var(--text-dim)}.auth-provider-card--authenticated{border-color:color-mix(in srgb,var(--color-success) 40%,var(--border));background:color-mix(in srgb,var(--color-success) 5%,var(--surface))}.auth-provider-card--authenticated:hover{border-color:color-mix(in srgb,var(--color-success) 60%,var(--border))}.auth-provider-header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--space-sm) var(--space-md);gap:12px}.auth-provider-info{display:flex;align-items:center;gap:10px;flex-wrap:wrap;flex:1;min-width:0}.auth-provider-info strong{font-weight:500;color:var(--text)}.auth-provider-icon-slot{display:inline-flex;align-items:center;justify-content:center;inline-size:calc(var(--space-md) + var(--space-xs) * 2);block-size:calc(var(--space-md) + var(--space-xs) * 2);flex-shrink:0}.auth-provider-icon-slot .provider-icon{display:inline-flex}.auth-hint{display:block;padding:12px 4px 0;font-size:12px;color:var(--text-muted);border-top:1px solid var(--border);margin-top:8px}.auth-apikey-section{display:flex;flex-direction:column;gap:var(--space-xs);align-items:flex-end;flex-shrink:0}.auth-apikey-input-row{display:flex;gap:6px;align-items:center}.auth-apikey-input{background:var(--bg-input);border:1px solid var(--border);border-radius:6px;color:var(--text);padding:6px 10px;font-size:13px;width:180px;font-family:monospace}.auth-apikey-input:focus{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring)}.auth-apikey-input:disabled{opacity:.6}.auth-apikey-progress{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);padding-right:4px}.auth-apikey-error{font-size:11px;color:var(--color-error);padding-right:4px}.auth-provider-actions-row{display:flex;width:100%;align-items:center;gap:var(--space-sm)}.auth-device-code-panel{width:100%;margin-top:var(--space-sm);padding:var(--space-sm);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:color-mix(in srgb,var(--surface) 85%,transparent);display:flex;flex-direction:column;gap:var(--space-sm)}.auth-device-code-pill{font-family:var(--font-mono);font-size:calc(var(--space-md) + var(--space-xs) * .5);letter-spacing:var(--space-xs);padding:var(--space-sm) var(--space-md);border-radius:var(--radius-pill);border:var(--btn-border-width) solid var(--border);background:var(--card);color:var(--text);display:flex;align-self:stretch}.auth-key-hint{font-family:var(--font-mono);font-size:12px;color:var(--text-muted);display:inline-block;margin-top:var(--space-xs);user-select:none}.settings-lane-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:500;white-space:nowrap}.settings-lane-badge--override{background-color:color-mix(in srgb,var(--todo) 20%,transparent);color:var(--todo)}.settings-lane-badge--inherited{background-color:color-mix(in srgb,var(--text-muted) 15%,transparent);color:var(--text-muted)}.settings-description{font-size:13px;color:var(--text-dim);padding-inline:var(--space-xl);margin-block:0 var(--space-md);line-height:1.5}.settings-token-cap-row{display:flex;align-items:center;gap:var(--space-sm)}.settings-model-lane-label-row{display:flex;align-items:center;gap:var(--space-sm);margin-bottom:var(--space-xs)}.settings-model-lane-control-row{display:flex;align-items:center;gap:var(--space-sm)}.settings-model-lane-control-main{flex:1}.settings-summarization-actions{justify-content:flex-start}.settings-model-presets{display:flex;flex-direction:column;gap:var(--space-md)}.settings-preset-list{display:flex;flex-direction:column;gap:var(--space-sm)}.settings-preset-item{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-md);padding:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--card)}.settings-preset-item-meta{display:flex;flex-direction:column;gap:var(--space-xs);min-width:0}.settings-preset-item-meta strong{color:var(--text);overflow-wrap:anywhere}.settings-preset-summary{font-size:12px;overflow-wrap:anywhere}.settings-preset-item-actions{display:flex;gap:var(--space-xs);flex-wrap:wrap;justify-content:flex-end}.settings-preset-actions{display:flex;justify-content:flex-start}.settings-preset-editor{display:flex;flex-direction:column;gap:var(--space-md);padding:var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:color-mix(in srgb,var(--surface) 85%,var(--card))}.settings-preset-editor-fields{display:flex;flex-direction:column;gap:var(--space-sm)}.settings-preset-editor .form-group{padding:0}.settings-preset-editor-actions{justify-content:flex-start;margin-top:0;padding:0}.settings-preset-auto-select{margin-top:var(--space-sm)}.settings-preset-size-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-sm)}.settings-preset-size-row{padding:0}@media(max-width:768px){.settings-layout{flex-direction:column;min-height:0}.settings-mobile-section-picker{display:flex;flex-direction:column;gap:var(--space-xs);padding:var(--space-md) var(--space-lg);border-bottom:var(--btn-border-width) solid var(--border);background:var(--surface)}.settings-mobile-section-picker label{color:var(--text-muted);font-weight:600;text-transform:uppercase}.settings-mobile-section-picker select{width:100%}.settings-mobile-section-picker select:focus-visible{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.settings-sidebar{display:none}.settings-nav-item{display:flex;align-items:center;justify-content:center;gap:var(--space-xs);border-left:none;border-bottom:2px solid transparent;border-radius:var(--radius-md) var(--radius-md) 0 0;padding:calc(var(--space-xs) + var(--space-xs) / 2) var(--space-md);white-space:nowrap}.settings-nav-item:hover{border-left-color:transparent;border-bottom-color:var(--border)}.settings-nav-item.active{border-left-color:transparent;border-bottom-color:var(--todo)}.settings-group-header{display:none}.notification-provider-card{margin:0 var(--space-lg) var(--space-md)}.notification-provider-header{padding:var(--space-sm) var(--space-md)}.notification-provider-body{padding:var(--space-md)}.settings-scope-icon{margin-right:0}.settings-content{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto}.settings-content .form-group small{overflow-wrap:break-word;word-break:normal}.settings-content input,.settings-content select,.settings-content textarea{font-size:16px}.settings-section-heading{padding:var(--space-lg) var(--space-lg) var(--space-md);margin:0 0 var(--space-md)}.settings-plugins-subsection-toggle{display:flex;width:100%;padding:0 var(--space-lg)}.settings-plugins-subsection-btn{flex:1;min-height:36px}.settings-plugins-subsection-panel{padding-left:var(--space-lg);padding-right:var(--space-lg)}.form-group{padding:0 calc(var(--space-md) + var(--space-xs) / 2)}.settings-scope-banner{padding:var(--space-sm) var(--space-lg)}.memory-editor-frame{min-height:65vh}.memory-file-summary{grid-template-columns:1fr;margin:0 var(--space-lg) var(--space-md)}.memory-status-message{align-items:stretch;flex-direction:column}.memory-file-summary span{justify-content:flex-start}.memory-file-summary small{grid-column:auto}.settings-description{padding:0 var(--space-lg)}.settings-content .btn,.settings-preset-item-actions .btn{min-height:36px}.auth-provider-row{flex-wrap:wrap;padding:var(--space-md) calc(var(--space-md) + var(--space-xs) / 2);gap:var(--space-sm)}.auth-section-hint{margin:0 calc(var(--space-md) + var(--space-xs) / 2) var(--space-md);padding:calc(var(--space-sm) + var(--space-xs) / 2) calc(var(--space-md) + var(--space-xs) / 2)}.auth-provider-group{margin-bottom:var(--space-md)}.auth-group-label{padding:0 calc(var(--space-md) + var(--space-xs) / 2)}.auth-provider-card{margin:0 calc(var(--space-md) + var(--space-xs) / 2) var(--space-sm)}.auth-provider-header{flex-wrap:wrap;padding:calc(var(--space-sm) + var(--space-xs) / 2) calc(var(--space-md) + var(--space-xs) / 2);gap:10px}.auth-provider-header>div:not(.auth-provider-info):not(.auth-apikey-section){margin-left:auto}.auth-provider-actions-row{width:100%;justify-content:flex-end}.auth-device-code-panel{width:100%}.auth-device-code-pill{max-width:100%;overflow-wrap:anywhere}.auth-provider-info{width:100%;flex-basis:100%}.auth-apikey-section{width:100%;flex-basis:100%;align-items:flex-end}.auth-apikey-input-row{width:100%;flex-wrap:wrap;justify-content:flex-end}.auth-apikey-input{flex:1;min-width:120px;width:auto}.auth-apikey-input-row .btn{flex-shrink:0;margin-left:auto}.auth-hint{padding:var(--space-md) calc(var(--space-md) + var(--space-xs) / 2) 0}.settings-model-presets{gap:var(--space-sm)}.settings-preset-item{flex-direction:column;align-items:stretch;padding:var(--space-sm) var(--space-md)}.settings-preset-item-actions{justify-content:flex-start}.settings-preset-editor{padding:var(--space-sm) var(--space-md)}.settings-preset-editor-actions{flex-wrap:wrap}.settings-preset-size-grid{grid-template-columns:1fr;gap:var(--space-xs)}.settings-node-routing-note{padding:var(--space-sm) var(--space-md);font-size:12px}}.settings-node-routing-note{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md) var(--space-lg);margin-top:var(--space-sm);color:var(--text-muted);font-size:13px;line-height:1.5}.settings-node-status{display:inline-flex;align-items:center;gap:var(--space-xs);margin-top:var(--space-sm);font-size:12px;color:var(--text-muted)}.auth-advanced-disclosure{margin-top:var(--space-md);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.auth-advanced-disclosure>summary{cursor:pointer;padding:var(--space-sm) var(--space-md)}.auth-advanced-content{display:flex;flex-direction:column;gap:var(--space-sm);padding:0 var(--space-md) var(--space-md)}.auth-custom-provider-item{display:flex;justify-content:space-between;align-items:center;gap:var(--space-sm)}.auth-custom-provider-actions{display:flex;gap:var(--space-sm)}.settings-warning-banner{margin-top:var(--space-sm);padding:var(--space-sm) var(--space-md);border:1px solid var(--color-warning);border-radius:var(--radius-md);background:color-mix(in srgb,var(--color-warning) 12%,transparent);color:var(--text);font-size:var(--font-sm, .875rem);line-height:1.4}.settings-warning-banner strong{color:var(--color-warning);margin-right:var(--space-xs)}@media(max-width:768px){.auth-custom-provider-item{flex-direction:column;align-items:flex-start}.settings-warning-banner{padding:var(--space-sm)}}