(function(){
const {useState,useEffect,useRef}=React;
const {Icon,IconButton,Button,Switch,Mark,Dialog,Empty,SkillViewer}=ExtensionUI;
const {MCPForm,UploadPlugin,MarketSettings,SkillFolders,UpdateSettings,PluginDetails}=ExtensionForms;
const tabs=[['plugins','plug','插件'],['skills','doc','技能'],['tools','tools','工具']];
function ExtensionsManager({state,setState,onCompose,notify}){
 const [tab,setTab]=useState(()=>sessionStorage.getItem('extension-tab')||'plugins'),[search,setSearch]=useState(''),[source,setSource]=useState('all'),[category,setCategory]=useState('全部'),[modal,setModal]=useState(null),[menu,setMenu]=useState(false),[busy,setBusy]=useState('');const menuRef=useRef();
 const patch=v=>setState(s=>({...s,...v}));
 const updatePlugin=(id,v)=>setState(s=>({...s,plugins:s.plugins.map(p=>p.id===id?{...p,...v}:p)}));
 const updates=state.plugins.filter(p=>p.installed&&p.marketKey&&p.version!==p.latest);
 function changeTab(t){setTab(t);sessionStorage.setItem('extension-tab',t);setSearch('');setSource('all');setCategory('全部');setMenu(false);}
 useEffect(()=>{const close=e=>{if(!menuRef.current?.contains(e.target))setMenu(false);};const key=e=>{if(e.key==='Escape')setMenu(false);};document.addEventListener('pointerdown',close);document.addEventListener('keydown',key);return()=>{document.removeEventListener('pointerdown',close);document.removeEventListener('keydown',key);};},[]);
 useEffect(()=>{if(state.checkUpdates)patch({lastChecked:Date.now()});},[]);
 useEffect(()=>{if(tab==='skills'&&state.autoScan&&!state.lastScanned)scan(true);},[tab,state.autoScan]);
 useEffect(()=>{const focus=()=>{if(state.autoScan)scan(true);};window.addEventListener('focus',focus);return()=>window.removeEventListener('focus',focus);},[state.autoScan,state.directories,state.scanDiscovered]);
 function compose(kind){setModal(null);onCompose(kind==='plugins'?'使用内置 plugin-creator 技能，帮我创建一个兼容 Codex、Claude Code 和 pi 的插件。请先了解我的工作需求，再设计功能、统一插件包和安装后的鉴权与使用引导。':'使用内置 skill-creator 技能，帮我把一项重复工作整理为可复用的技能。请先了解工作场景、输入材料和期望输出，再生成技能文件夹、SKILL.md 与参考文件。');}
 function install(p){updatePlugin(p.id,{installed:true,enabled:true});notify(p.auth==='none'?p.name+' 已安装，无需鉴权':p.name+' 已安装，请完成连接');if(p.auth!=='none')setModal({type:'plugin',id:p.id,tab:'config'});}
 function update(p){updatePlugin(p.id,{version:p.latest});notify(p.name+' 已更新至 '+p.latest+'（演示）');}
 function scan(quiet=false,dirs=state.directories){if(!dirs.some(d=>d.enabled)){if(!quiet)notify('请先启用一个扫描目录');return;}setBusy('scan');setTimeout(()=>{setState(s=>({...s,skills:s.scanDiscovered?s.skills:[...s.skills,{...ExtensionData.detected,folder:dirs.find(d=>d.enabled).path+'/project-planning'}],scanDiscovered:true,lastScanned:Date.now()}));setBusy('');if(!quiet)notify(state.scanDiscovered?'扫描完成，没有发现新增技能':'发现 1 项新技能：project-planning（演示）');},550);}
 function check(){patch({lastChecked:Date.now()});notify(updates.length?'检查完成，'+updates.length+' 个插件可更新（演示）':'所有市场插件均为最新版本（演示）');}
 const matches=x=>(x.name+' '+(x.description||'')).toLowerCase().includes(search.toLowerCase())&&(source==='all'||x.source===source)&&(category==='全部'||x.category===category);
 const installed=state[tab==='skills'?'skills':'plugins'].filter(x=>x.installed&&matches(x));
 const market=state[tab==='skills'?'skills':'plugins'].filter(x=>!x.installed&&matches(x)&&state.markets.some(m=>m.id===x.source&&m.enabled));
 const pluginDetail=modal?.type==='plugin'?state.plugins.find(p=>p.id===modal.id):null;
 const sourceLabel=x=>x.source==='upload'?'本地上传':x.source==='local'?'本地目录':x.source==='builtin'?'内置':state.markets.find(m=>m.id===x.source)?.name||'插件市场';
 const installSkill=s=>{setState(st=>({...st,skills:st.skills.map(x=>x.id===s.id?{...x,installed:true}:x)}));notify(s.name+' 已安装（演示）');};
 function card(p){return <article className="ext-card" key={p.id}><div className="ext-card-top"><Mark icon={p.icon} color={p.color}/><div className="ext-card-name"><h3><button onClick={()=>setModal({type:'plugin',id:p.id})}>{p.name}</button>{p.installed&&p.version!==p.latest&&<span className="ext-badge blue">可更新</span>}</h3><div className="ext-card-meta"><span>v{p.version}</span><span>·</span><span>{sourceLabel(p)}</span></div></div>{p.installed&&<Switch label={'启用 '+p.name} checked={p.enabled} onChange={v=>updatePlugin(p.id,{enabled:v})}/>}</div><p className="ext-card-description">{p.description}</p><div className="ext-card-footer"><span className={'ext-state '+(p.auth!=='none'&&!p.connected?'pending':'')}>{p.installed?<><i className="dot"/>{!p.enabled?'已停用':p.auth==='none'?'无需鉴权':p.connected?'已连接':'待连接'}</>:<span>Codex · Claude Code · pi</span>}</span><div className="ext-card-buttons">{p.installed?<>{p.version!==p.latest&&<Button small onClick={()=>update(p)}>更新</Button>}<Button small subtle onClick={()=>setModal({type:'plugin',id:p.id,tab:'config'})}>{p.auth!=='none'&&!p.connected?'连接':'配置'}</Button></>:<Button small onClick={()=>install(p)}><Icon name="plus" size={12}/>安装</Button>}</div></div></article>;}
 function skillCard(s){return <article key={s.id} className="ext-card ext-skill-card" role="button" tabIndex={0} aria-label={'查看技能 '+s.name} onClick={()=>setModal({type:'skill',id:s.id})} onKeyDown={e=>{if(e.target===e.currentTarget&&['Enter',' '].includes(e.key)){e.preventDefault();setModal({type:'skill',id:s.id});}}}><div className="ext-card-top"><Mark icon="doc"/><div className="ext-card-name"><h3>{s.name}</h3></div>{s.source==='builtin'&&<span className="ext-badge">内置</span>}</div><p className="ext-card-description" title={s.description}>{s.description}</p><div className="ext-card-footer"><span>{sourceLabel(s)}</span>{s.installed?<span className="ext-text-action">查看文件<Icon name="right" size={12}/></span>:<Button small onClick={e=>{e.stopPropagation();installSkill(s);}}><Icon name="plus" size={12}/>安装</Button>}</div></article>;}
 function section(title,items,render,actions){return <section className="ext-section"><div className="ext-section-title"><h2>{title}<span>{items.length}</span></h2>{actions}</div>{items.length?<div className="ext-grid">{items.map(render)}</div>:<Empty title={search||source!=='all'||category!=='全部'?'没有匹配的内容':'这里还没有内容'} description={search?'试试其他关键词。':'已安装内容或启用市场中的推荐会显示在这里。'}/>}</section>;}
 const toolMatches=m=>(m.name+' '+(m.command||m.url||'')).toLowerCase().includes(search.toLowerCase());
 const manual=state.mcps.filter(toolMatches),derived=state.plugins.filter(p=>p.installed).flatMap(p=>p.mcp.map(m=>({...m,owner:p}))).filter(toolMatches);
 function toolTable(items,plugin){return items.length?<div className="ext-tool-table"><div className="ext-tool-head"><span>名称</span><span>协议</span><span className="ext-tool-source">配置来源</span><span>操作</span></div>{items.map(m=><div className="ext-tool-row" key={(m.owner?.id||'manual')+m.id}><div className="ext-tool-name"><Mark icon={plugin?m.owner.icon:'terminal'} color={plugin?m.owner.color:'slate'}/><div><strong>{m.name}</strong><small title={m.command||m.url}>{m.command||m.url}</small></div></div><span className="ext-tool-protocol">{m.protocol==='stdio'?'stdio':'Streamable HTTP'}</span><span className="ext-tool-source">{plugin?<><Icon name="plug" size={11}/>{m.owner.name}</>:'手动添加'}</span><div className="ext-tool-actions">{plugin?<button className="ext-text-action" onClick={()=>setModal({type:'plugin',id:m.owner.id,tab:'config'})}>插件配置<Icon name="arrow" size={12}/></button>:<><IconButton name="settings" label={'编辑 '+m.name} onClick={()=>setModal({type:'mcp',data:m})}/><IconButton name="trash" label={'删除 '+m.name} onClick={()=>setModal({type:'deleteMCP',data:m})}/></>}</div></div>)}</div>:<Empty title="暂无 MCP 工具" description={search?'试试其他关键词。':plugin?'安装包含 MCP 的插件后，会自动显示在这里。':'添加一个 MCP 服务，扩展助手的工作能力。'}/>;}
 return <div className="management"><div className="extension-center"><div className="ext-topline"><div className="ext-tabs" role="tablist" aria-label="扩展配置">{tabs.map(([key,icon,label],i)=><button role="tab" id={'ext-tab-'+key} aria-controls="ext-panel" aria-selected={tab===key} tabIndex={tab===key?0:-1} className={'ext-tab '+(tab===key?'active':'')} key={key} onClick={()=>changeTab(key)} onKeyDown={e=>{if(['ArrowLeft','ArrowRight','Home','End'].includes(e.key)){e.preventDefault();const n=e.key==='Home'?0:e.key==='End'?2:(i+(e.key==='ArrowRight'?1:2))%3;changeTab(tabs[n][0]);document.getElementById('ext-tab-'+tabs[n][0])?.focus();}}}><Icon name={icon}/>{label}</button>)}</div><div className="ext-actions" ref={menuRef}>{tab==='plugins'&&<IconButton name="bell" label="插件更新消息" onClick={()=>setModal({type:'notifications'})}>{updates.length>0&&state.updateNotifications&&<i className="ext-count-dot"/>}</IconButton>}{tab!=='tools'&&<IconButton name="settings" label={tab==='plugins'?'插件更新设置':'技能发现设置'} onClick={()=>setModal({type:tab==='plugins'?'updates':'folders'})}/>}<Button primary onClick={()=>tab==='tools'?setModal({type:'mcp'}):setMenu(!menu)} aria-expanded={tab==='tools'?undefined:menu}><Icon name="plus" size={14}/>{tab==='plugins'?'添加插件':tab==='skills'?'添加技能':'添加 MCP'}{tab!=='tools'&&<Icon name="down" size={12}/>}</Button>{menu&&<div className="ext-dropdown">{tab==='plugins'&&<button className="ext-menu-item" onClick={()=>{setMenu(false);setModal({type:'upload'});}}><Icon name="upload"/><span>上传插件包<small>支持无需鉴权的本地插件</small></span></button>}<button className="ext-menu-item" onClick={()=>compose(tab)}><Icon name="chat"/><span>通过会话创建<small>使用内置{tab==='plugins'?'插件':'技能'}创作技能</small></span></button><div className="ext-menu-separator"/><button className="ext-menu-item" onClick={()=>{setMenu(false);setModal({type:'markets'});}}><Icon name="globe"/><span>{tab==='plugins'?'连接与管理市场':'管理默认技能市场'}</span></button>{tab==='skills'&&<button className="ext-menu-item" onClick={()=>{setMenu(false);setModal({type:'folders'});}}><Icon name="folder"/><span>配置技能目录</span></button>}</div>}</div></div>
 <div role="tabpanel" id="ext-panel" aria-labelledby={'ext-tab-'+tab}><div className="ext-page-heading"><div><h1>{tab==='plugins'?'为工作，连接更多能力。':tab==='skills'?'把好方法，变成你的技能。':'让助手，连接你的工具。'}</h1><p>{tab==='plugins'?'安装、连接与管理插件，让不同的工作方式在这里汇合。':tab==='skills'?'发现和管理可复用的工作技能，在需要时自然调用。':'统一查看 MCP 服务，管理手动配置与插件提供的工具。'}</p></div><span className="ext-page-meta"><Icon name={tab==='tools'?'tools':'package'} size={13}/>{tab==='tools'?'MCP 配置':'统一工作空间'}</span></div><div className="ext-searchline"><label className="ext-search"><Icon name="search"/><input aria-label={'搜索'+tabs.find(t=>t[0]===tab)[2]} value={search} onChange={e=>setSearch(e.target.value)} placeholder={tab==='plugins'?'搜索插件名称或功能…':tab==='skills'?'搜索技能名称或描述…':'搜索 MCP 名称或地址…'}/>{search&&<IconButton name="close" label="清空搜索" onClick={()=>setSearch('')}/>}</label>{tab!=='tools'&&<select className="ext-filter-select" aria-label="筛选来源" value={source} onChange={e=>setSource(e.target.value)}><option value="all">全部来源</option>{tab==='plugins'?<option value="upload">本地上传</option>:<><option value="local">本地目录</option><option value="builtin">内置技能</option></>}{state.markets.filter(m=>m.kind===tab).map(m=><option key={m.id} value={m.id}>{m.name}</option>)}</select>}</div>
 {tab!=='tools'&&<div className="ext-filter-pills">{['全部','效率','开发','设计','研究',...(tab==='skills'?['创作']:[])].map(c=><button key={c} aria-pressed={category===c} className={'ext-filter-pill '+(category===c?'active':'')} onClick={()=>setCategory(c)}>{c}</button>)}</div>}
 {tab==='plugins'&&<>{updates.length>0&&state.updateNotifications&&<div className="ext-banner"><Icon name="download" size={17}/><div><strong>{updates.length} 个插件有新版本</strong><small>更新后，继续使用熟悉的配置与连接。</small></div><Button small subtle onClick={()=>setModal({type:'notifications'})}>查看更新<Icon name="right" size={12}/></Button></div>}{section('已安装',installed,card,<span className="ext-section-tools">管理所有 Harness 的插件</span>)}{section('发现插件',market,card,<button className="ext-text-action" onClick={()=>setModal({type:'markets'})}><Icon name="globe" size={13}/>管理市场</button>)}<p className="ext-market-note"><Icon name="shield" size={13}/>平台统一插件规范 · 兼容 Codex、Claude Code 与 pi</p></>}
 {tab==='skills'&&<>{section('我的技能',installed,skillCard,<div className="ext-section-tools"><span className="ext-detection"><i className="ext-dot"/>{state.autoScan?'自动发现已开启':'自动发现已关闭'}</span><button className="ext-text-action" disabled={busy==='scan'} onClick={()=>scan()}><Icon name="refresh" size={13} className={busy==='scan'?'ext-spinner':''}/>{busy==='scan'?'扫描中':'刷新'}</button></div>)}<p className="ext-market-note"><Icon name="folder" size={13}/>{state.directories.filter(d=>d.enabled).length} 个扫描目录{state.lastScanned?' · 最近扫描 '+new Date(state.lastScanned).toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'}):' · 自动探测新增技能'}<button className="ext-text-action" onClick={()=>setModal({type:'folders'})}>管理目录</button></p>{section('发现技能',market,skillCard,<button className="ext-text-action" onClick={()=>setModal({type:'markets'})}><Icon name="globe" size={13}/>默认技能市场</button>)}</>}
 {tab==='tools'&&<><section className="ext-section"><div className="ext-section-title"><h2>手动添加<span>{manual.length}</span></h2><span className="ext-section-tools">由你管理配置</span></div>{toolTable(manual,false)}</section><section className="ext-section"><div className="ext-section-title"><h2>插件提供<span>{derived.length}</span></h2><span className="ext-badge">只读</span></div><p className="ext-section-sub">随插件自动显示，具体设置请前往对应插件配置。</p>{toolTable(derived,true)}</section></>}
 <p className="ext-market-note">交互原型 · 数据保存在当前浏览器，安装、扫描与连接均为演示。</p></div></div>
 {modal?.type==='upload'&&<UploadPlugin onClose={()=>setModal(null)} onSave={p=>{setState(s=>({...s,plugins:[...s.plugins,p]}));setModal({type:'plugin',id:p.id,tab:'config'});notify(p.auth==='none'?'插件已安装，无需鉴权（演示）':'插件已安装，请完成连接（演示）');}}/>}
 {modal?.type==='markets'&&<MarketSettings kind={tab} markets={state.markets} onChange={markets=>patch({markets})} onClose={()=>setModal(null)}/>}
 {modal?.type==='folders'&&<SkillFolders state={state} onClose={()=>setModal(null)} onSave={(directories,autoScan)=>{patch({directories,autoScan});setModal(null);scan(false,directories);}}/>}
 {modal?.type==='updates'&&<UpdateSettings state={state} onChange={patch} onCheck={check} onClose={()=>setModal(null)}/>}
 {pluginDetail&&<PluginDetails key={pluginDetail.id} plugin={pluginDetail} initialTab={modal.tab} markets={state.markets} onClose={()=>setModal(null)} onPatch={v=>updatePlugin(pluginDetail.id,v)} onInstall={install} onUpdate={update} onDelete={p=>setModal({type:'deletePlugin',data:p})} onMCP={m=>setModal({type:'mcp',data:m,owner:pluginDetail.id})}/>}
 {modal?.type==='skill'&&<SkillViewer skill={state.skills.find(s=>s.id===modal.id)} onClose={()=>setModal(null)} onCompose={onCompose} onInstall={()=>installSkill(state.skills.find(s=>s.id===modal.id))}/>}
 {modal?.type==='mcp'&&<MCPForm data={modal.data} embedded={!!modal.owner} names={(modal.owner?state.plugins.find(p=>p.id===modal.owner).mcp:state.mcps).filter(m=>m.id!==modal.data?.id).map(m=>m.name)} onClose={()=>modal.owner?setModal({type:'plugin',id:modal.owner,tab:'config'}):setModal(null)} onSave={m=>{if(modal.owner){setState(s=>({...s,plugins:s.plugins.map(p=>p.id===modal.owner?{...p,mcp:p.mcp.map(x=>x.id===m.id?m:x)}:p)}));setModal({type:'plugin',id:modal.owner,tab:'config'});}else{setState(s=>({...s,mcps:s.mcps.some(x=>x.id===m.id)?s.mcps.map(x=>x.id===m.id?m:x):[...s.mcps,m]}));setModal(null);}notify('MCP 配置已保存（演示）');}}/>}
 {modal?.type==='notifications'&&<Dialog title="插件更新" description="根据市场来源与唯一标识，发现已安装插件的新版本。" onClose={()=>setModal(null)} footer={<Button onClick={check}>检查更新</Button>}>{updates.length?updates.map(p=><div className="ext-notification" key={p.id}><Mark icon={p.icon} color={p.color}/><div><h3>{p.name}</h3><p>v{p.version} → v{p.latest}</p><p>{p.releaseNotes?.[0]||'改进功能与使用体验'}</p></div><Button small primary onClick={()=>update(p)}>更新</Button></div>):<Empty title="全部是最新版本" description="有新版本时，会在这里显示更新消息。"/>}</Dialog>}
 {['deletePlugin','deleteMCP'].includes(modal?.type)&&<Dialog title={(modal.type==='deletePlugin'?'卸载插件':'删除 MCP')+'？'} description={'将移除「'+modal.data.name+'」及其当前配置。'} onClose={()=>setModal(null)} footer={<><Button onClick={()=>setModal(null)}>取消</Button><Button primary onClick={()=>{if(modal.type==='deleteMCP')patch({mcps:state.mcps.filter(m=>m.id!==modal.data.id)});else if(modal.data.source==='upload')patch({plugins:state.plugins.filter(p=>p.id!==modal.data.id)});else updatePlugin(modal.data.id,{installed:false,connected:false,mcp:ExtensionData.seed.plugins.find(p=>p.id===modal.data.id)?.mcp||[]});setModal(null);notify('已移除');}}>确认移除</Button></>}><p className="ext-source-note">{modal.type==='deletePlugin'?'来自该插件的 MCP 也会从工具列表移除。市场插件可再次安装。':'之后可通过“添加 MCP”重新配置。'}</p></Dialog>}
 </div>;
}
window.ExtensionsManager=ExtensionsManager;
})();
