Files
projectAIpopular/gateway/static/assets/SettingsView-B4tzUqnq.js
T
tzt ddef8bec1c feat(v3): T29 token 级流式输出(SSE 流式解析 + delta 事件 + 打字机渲染,D10)
- OpenAICompatChat 默认 stream=True:httpx 流式解析 OpenAI chunk,
  tool_calls 碎片按 index 组装(不在正文展示),include_usage 计量;
  失败自动回退非流式一次(已有部分增量输出则如实抛出);
  补 raise_for_status(修复流式 4xx 误入回退的缺陷)
- ToolLoop 增 on_delta(签名探测兼容 2/3 参 chat_fn);_loads_json_object 宽松解析
- DeltaThrottle >=48 字符节流落 delta 事件;单模型与两级模式(含规划者)接线
- 前端:streamText 打字机渲染 + 光标动画;工具/阶段事件到达时清空归档
- 配套修复:AgentView 闭包持有 push 前原始对象导致响应式丢失、过程事件不渲染
- 测试 +7(SSE 解析/碎片组装/回退/部分失败抛出/on_delta/节流/service delta 事件),
  全量 296 passed
2026-09-01 23:41:45 +08:00

1 line
24 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{A as e,B as t,D as n,E as r,F as i,G as a,I as o,L as s,M as c,N as ee,O as l,P as te,S as ne,T as u,U as d,V as f,W as re,_ as ie,a as ae,b as oe,c as se,d as ce,g as le,h as ue,i as de,j as p,k as m,l as fe,m as pe,o as me,p as he,r as ge,t as h,u as _e,w as ve,x as ye,y as be,z as g}from"./index-C4nTxB0s.js";var xe={class:`settings-view`},Se={class:`settings-section`},Ce={class:`section-body`},we={class:`role-bar`},Te=[`onUpdate:modelValue`],Ee=[`value`],De={key:0,class:`pool-table`},Oe={class:`mono`},ke=[`onUpdate:modelValue`,`onChange`],Ae={class:`row-actions`},je=[`disabled`,`onClick`],Me=[`onClick`],Ne=[`onClick`],Pe={key:1,class:`no-models`},Fe={key:3,class:`pool-edit`},Ie={class:`pool-edit-title`},Le={class:`form-grid`},Re={class:`field`},ze={class:`field`},Be={class:`field`},Ve={class:`field`},He=[`disabled`],Ue={id:`pool-model-options`},We=[`value`],Ge={key:0,class:`field full-width`},Ke={key:1,class:`field`},qe={class:`field`},Je={class:`field`},Ye={class:`field`},Xe={class:`field`},Ze={class:`pool-edit-actions`},Qe={class:`checkbox-label`},$e=[`disabled`],et={class:`settings-section`},tt={class:`section-title`},nt={class:`title-right`},rt={class:`section-body`},it={class:`server-control-bar`},at={class:`server-info`},ot={class:`model-chip`},st={class:`model-chip port-chip`},ct={class:`model-chip pid-chip`},lt={key:1,class:`server-idle`},ut={class:`server-actions`},dt=[`disabled`],ft=[`disabled`],pt={key:0,class:`error-msg llama-error`},mt={class:`local-models`},ht={class:`local-models-header`},gt=[`disabled`],_t={key:0,class:`no-models`},vt={key:1,class:`model-list`},yt=[`onClick`],bt={class:`model-item-name`},xt={class:`model-item-size`},St={class:`download-section`},Ct={class:`download-form`},wt=[`disabled`],Tt=[`disabled`],Et={key:0,class:`progress-wrap`},Dt={class:`progress-bar`},Ot={class:`progress-info`},kt={key:1,class:`error-msg download-error`},At={key:2,class:`done-msg`},jt={class:`form-grid`,style:{"margin-top":`16px`}},Mt={class:`field full-width`},Nt={key:0,class:`field full-width`},Pt=[`disabled`],Ft={class:`input-row`},It=[`placeholder`],Lt={key:1,class:`field full-width`},Rt=[`disabled`],zt=[`value`],Bt=[`value`],Vt={key:3,class:`field-hint warn`},Ht={key:2,class:`field`},Ut={class:`field`},Wt={class:`field`},Gt={class:`field`},Kt={class:`settings-section`},qt={class:`section-title`},Jt={class:`title-right`},Yt={class:`section-body`},Xt={class:`form-grid`},Zt={class:`field full-width`},Qt=[`disabled`],$t={class:`field full-width`},en={class:`field full-width`},tn=[`disabled`],nn=[`value`],rn={key:0,class:`field-hint warn`},an={class:`settings-section`},on={class:`section-body`},sn={class:`form-grid`},cn={class:`field full-width`},ln={class:`checkbox-label`},un={class:`field`},dn={class:`field`},fn={class:`field full-width`},pn={class:`actions`},mn=[`disabled`],hn=[`disabled`],_=h(ee({__name:`SettingsView`,setup(ee){let h=f(!1),_=f(``),v=f(null),gn=[{key:`architect`,label:`🧠 Architect(决策/终审)`},{key:`worker`,label:`🔧 Worker(实现/自验证)`},{key:`agent`,label:`🤖 Agent(智能体工具)`}],_n={local:`本地/零成本`,budget:`低价 API`,premium:`旗舰 API`},y=f({roles:{architect:``,worker:``,agent:``},entries:[]}),b=t({architect:``,worker:``,agent:``}),x=f(null),S=f(!1),C=f(``),w=f(``),T=f(!1),E=f(!1),D=f(!1),vn=f([]),yn=l(()=>y.value.entries.filter(e=>e.enabled));function bn(e){return _n[e]??e}async function xn(){try{y.value=await se(),b.architect=y.value.roles.architect||``,b.worker=y.value.roles.worker||``,b.agent=y.value.roles.agent||``}catch{}}async function Sn(){try{y.value=await ue({...b}),v.value={ok:!0,msg:`✅ 角色已更新,管线已重建`}}catch(e){v.value={ok:!1,msg:`❌ 角色指派失败:`+(e?.response?.data?.detail||e?.message||e)},await xn()}setTimeout(()=>v.value=null,3e3)}function Cn(){S.value=!0,x.value={name:``,tier:`budget`,backend:`openai`,base_url:``,model:``,api_key:``,price_in:.1,price_out:.1,temperature:.3,max_tokens:4096,enabled:!0}}function wn(e){S.value=!1,x.value={...e,api_key:``}}async function Tn(){if(x.value){E.value=!0;try{y.value=await ye(x.value),x.value=null,v.value={ok:!0,msg:`✅ 模型条目已保存`}}catch(e){v.value={ok:!1,msg:`❌ 保存失败:`+(e?.response?.data?.detail||e?.message||e)}}finally{E.value=!1,setTimeout(()=>v.value=null,3e3)}}}async function En(e){confirm(`删除模型条目「${e.name}」?相关角色指派会一并清空。`)&&(y.value=await ge(e.id))}async function Dn(e){y.value=await ye({...e,api_key:``})}async function On(e){C.value=e.id,w.value=``;try{let t=await be(e.id);T.value=t.ok,w.value=t.ok?`✅ ${e.name} 连接正常`:`❌ ${e.name}: ${t.detail||`连接失败`}`}catch(e){T.value=!1,w.value=`❌ `+(e?.message||String(e))}finally{C.value=``}}async function kn(){if(x.value){D.value=!0;try{let e;e=!S.value&&x.value.id?await ce(x.value.id):x.value.backend===`mock`?{models:[{id:`mock`,name:`mock(内置模拟)`}]}:await _e(x.value.backend||`openai`,x.value.base_url||``,x.value.api_key||``),e.error?(T.value=!1,w.value=e.error,vn.value=[]):vn.value=e.models||[]}finally{D.value=!1}}}let O=f({running:!1}),k=f(!1),A=f(!1),j=f([]),M=f(!1),N=f(``),P=f(!1),F=f(``),I=f(0),L=f(``),An=f(``),jn=f(``),R=f(null),Mn=f(``),z=f(``),Nn=f(!1),B=null,V=f([]),H=f([]),U=t({worker:!1,architect:!1}),W=t({worker:``,architect:``}),G=t({worker:!1,architect:!1}),K=t({worker:null,architect:null}),q=t({worker:``,architect:``}),J=[{id:`deepseek-v4-flash`,name:`deepseek-v4-flash(推荐)`},{id:`deepseek-v4-pro`,name:`deepseek-v4-pro(推理模式)`},{id:`deepseek-coder`,name:`deepseek-coder`},{id:`gpt-4o-mini`,name:`gpt-4o-mini`},{id:`gpt-4o`,name:`gpt-4o`},{id:`claude-3-5-sonnet-20241022`,name:`claude-3.5-sonnet`},{id:`qwen-plus`,name:`qwen-plus`},{id:`qwen-max`,name:`qwen-max`}],Y=f(null),X=t({worker:{backend:`mock`,model:``,base_url:``,port:8901,temperature:.3,max_fix_attempts:2,code_timeout_s:10},architect:{model:`deepseek-v4-flash`,base_url:`https://api.deepseek.com`,api_key:``},pipeline:{fast_path:!0,rounds_cap:6,api_token_cap:8e3,breach_policy:`architect_do`}}),Pn=l(()=>X.worker.backend===`llama_server`?`http://127.0.0.1:${X.worker.port}/v1`:`http://127.0.0.1:11434/v1`),Fn=l(()=>Y.value?JSON.stringify(X)!==JSON.stringify(Y.value):!1);function In(e){return e>=1e9?(e/1e9).toFixed(1)+` GB`:e>=1e6?(e/1e6).toFixed(1)+` MB`:e>=1e3?(e/1e3).toFixed(0)+` KB`:e+` B`}async function Ln(){try{let e=await me();return O.value=e,e}catch{return O.value={running:!1},{running:!1}}}async function Z(){M.value=!0;try{j.value=await fe()}catch{j.value=[]}finally{M.value=!1}}async function Rn(){if(!X.worker.model){alert(`请先从上方「本地模型」列表中选择一个模型,再启动服务`);return}k.value=!0;try{let e=await le(X.worker.model,X.worker.port,99,4096);O.value=e,e.running&&(X.worker.backend=`llama_server`,X.worker.base_url=`http://127.0.0.1:${e.port}/v1`,await Z(),await Q())}catch(e){O.value={running:!1,error:String(e?.message||e)}}finally{k.value=!1}}async function zn(){A.value=!0;try{await ie(),O.value={running:!1}}catch{O.value={running:!1}}finally{A.value=!1}}function Bn(e){N.value=e.id,X.worker.model=e.id}function Vn(){F.value.trim()&&(z.value=``,Nn.value=!1,I.value=0,L.value=``,An.value=``,jn.value=`0 B`,R.value=null,P.value=!0,de(F.value.trim()).then(e=>{if(e.error){z.value=e.error,P.value=!1;return}if(e.done){Hn(e);return}B=ne(F.value.trim()),B.subscribe({onProgress:Hn,onDone:e=>{Hn(e),B?.close(),B=null}})}))}function Hn(e){I.value=Math.round(e.progress_pct),L.value=e.speed,An.value=e.eta,jn.value=In(e.downloaded_bytes),R.value=e.total_bytes?In(e.total_bytes):null,Mn.value=e.dest,e.done&&(P.value=!1,e.error?z.value=e.error:(Nn.value=!0,Z()))}async function Un(){W.worker=``,V.value=[],X.worker.backend!==`mock`&&await Q()}async function Wn(){W.architect=``,H.value=[],await Gn()}async function Q(){if(X.worker.backend!==`mock`){U.worker=!0,W.worker=``;try{let e=await _e(X.worker.backend,X.worker.base_url,``);e.error?X.worker.backend===`llama_server`?W.worker=`💡 llama-server 未启动,请先点击上方「启动服务」`:W.worker=e.error||`连接失败`:V.value=e.models||[]}catch{W.worker=`获取模型列表失败`}finally{U.worker=!1}}}async function Gn(){if(U.architect=!0,W.architect=``,!X.architect.base_url){H.value=[...J],U.architect=!1;return}try{let e=await _e(`openai`,X.architect.base_url,X.architect.api_key||``);e.error?(W.architect=e.error,H.value=[...J]):(e.models||[]).length>0?H.value=e.models||[]:H.value=[...J]}catch{W.architect=`获取模型列表失败`,H.value=[...J]}finally{U.architect=!1}}async function Kn(){if(X.worker.backend!==`mock`){G.worker=!0,K.worker=null,q.worker=``;try{let e=await he(X.worker.backend,X.worker.base_url,``);K.worker=e.ok,e.ok||(q.worker=e.detail||`连接失败`)}catch(e){K.worker=!1,q.worker=e?.message||String(e)}finally{G.worker=!1}}}async function qn(){if(!X.architect.base_url){K.architect=!1,q.architect=`请先填写 API 端点`;return}G.architect=!0,K.architect=null,q.architect=``;try{let e=await he(`openai`,X.architect.base_url,X.architect.api_key||``);K.architect=e.ok,e.ok||(q.architect=e.detail||`连接失败`)}catch(e){K.architect=!1,q.architect=e?.message||String(e)}finally{G.architect=!1}}function $(e,t){if(t)for(let n of Object.keys(e))t[n]!==void 0&&(typeof e[n]==`object`&&typeof t[n]==`object`&&e[n]!==null?$(e[n],t[n]):e[n]=t[n])}async function Jn(){_.value=``;try{let[e,t]=await Promise.all([ae(),Ln()]);O.value=t,xn(),e.worker&&$(X.worker,e.worker),e.architect&&$(X.architect,e.architect),e.pipeline&&$(X.pipeline,e.pipeline),Y.value=JSON.parse(JSON.stringify(X)),await Z(),H.value=[...J],X.worker.backend!==`mock`&&Q(),X.worker.model&&(N.value=X.worker.model)}catch(e){_.value=`加载配置失败:`+(e?.message||String(e))}}async function Yn(){h.value=!0,v.value=null;try{let e=JSON.parse(JSON.stringify(X));e.architect.api_key||delete e.architect.api_key;let t=await oe(e);$(X.worker,t.worker||{}),$(X.architect,t.architect||{}),$(X.pipeline,t.pipeline||{}),Y.value=JSON.parse(JSON.stringify(X)),v.value={ok:!0,msg:`✅ 设置已保存,管线已重建`},setTimeout(()=>v.value=null,3e3)}catch(e){v.value={ok:!1,msg:`❌ 保存失败:`+(e?.message||String(e))}}finally{h.value=!1}}async function Xn(){if(confirm(`确定恢复默认设置?`)){h.value=!0,v.value=null;try{let e=await pe();$(X.worker,e.worker||{}),$(X.architect,e.architect||{}),$(X.pipeline,e.pipeline||{}),Y.value=JSON.parse(JSON.stringify(X)),V.value=[],H.value=[...J],K.worker=null,K.architect=null,v.value={ok:!0,msg:`✅ 已恢复默认设置`},setTimeout(()=>v.value=null,3e3)}catch(e){v.value={ok:!1,msg:`❌ 重置失败:`+(e?.message||String(e))}}finally{h.value=!1}}}return te(Jn),i(()=>{B?.close()}),(t,i)=>(o(),p(`div`,xe,[i[68]||=m(`header`,{class:`settings-header`},[m(`h2`,null,`⚙️ 模型设置`),m(`p`,{class:`subtitle`},`配置小模型(Worker)与大模型(Architect)参数,保存后实时生效`)],-1),m(`section`,Se,[m(`div`,{class:`section-title`},[i[29]||=m(`span`,null,`🗄️ 模型池(多价位异构模型)`,-1),m(`div`,{class:`title-right`},[m(`button`,{class:`btn-refresh`,onClick:Cn},` 添加模型`)])]),m(`div`,Ce,[m(`div`,we,[(o(),p(n,null,s(gn,e=>m(`div`,{class:`role-item`,key:e.key},[m(`label`,null,a(e.label),1),g(m(`select`,{"onUpdate:modelValue":t=>b[e.key]=t,onChange:Sn},[i[30]||=m(`option`,{value:``},`经典设置(下方表单)`,-1),(o(!0),p(n,null,s(yn.value,e=>(o(),p(`option`,{key:e.id,value:e.id},a(e.name),9,Ee))),128))],40,Te),[[u,b[e.key]]])])),64))]),i[44]||=m(`p`,{class:`role-hint`},` 按价位组织模型:本地 llama.cpp 为零成本档,低价 API 干批量活,旗舰 API 做决策—— 随时切换,保存后管线自动重建。 `,-1),y.value.entries.length?(o(),p(`table`,De,[i[31]||=m(`thead`,null,[m(`tr`,null,[m(`th`,null,`名称`),m(`th`,null,`档位`),m(`th`,null,`后端`),m(`th`,null,`模型`),m(`th`,null,`单价 $/1M(入/出)`),m(`th`,null,`启用`),m(`th`,null,`操作`)])],-1),m(`tbody`,null,[(o(!0),p(n,null,s(y.value.entries,e=>(o(),p(`tr`,{key:e.id},[m(`td`,null,a(e.name),1),m(`td`,null,[m(`span`,{class:d([`tier-badge`,`tier-`+e.tier])},a(bn(e.tier)),3)]),m(`td`,null,a(e.backend),1),m(`td`,Oe,a(e.model||`—`),1),m(`td`,null,a(e.price_in)+` / `+a(e.price_out),1),m(`td`,null,[g(m(`input`,{type:`checkbox`,"onUpdate:modelValue":t=>e.enabled=t,onChange:t=>Dn(e)},null,40,ke),[[ve,e.enabled]])]),m(`td`,Ae,[m(`button`,{class:`btn-refresh`,disabled:C.value===e.id,onClick:t=>On(e)},a(C.value===e.id?`…`:`测试`),9,je),m(`button`,{class:`btn-refresh`,onClick:t=>wn(e)},`编辑`,8,Me),m(`button`,{class:`btn-refresh danger`,onClick:t=>En(e)},`删除`,8,Ne)])]))),128))])])):(o(),p(`div`,Pe,` 池为空——可添加本地 llama.cpp 模型(零成本档)、低价 API、旗舰 API 等,随时指派给 Architect / Worker / Agent。 `)),w.value?(o(),p(`div`,{key:2,class:d([`field-hint`,T.value?`ok`:`warn`])},a(w.value),3)):e(``,!0),x.value?(o(),p(`div`,Fe,[m(`div`,Ie,a(S.value?`添加模型`:`编辑模型`),1),m(`div`,Le,[m(`div`,Re,[i[32]||=m(`label`,null,`名称`,-1),g(m(`input`,{"onUpdate:modelValue":i[0]||=e=>x.value.name=e,placeholder:`如:DeepSeek 旗舰 / 本地 Qwen4B`},null,512),[[r,x.value.name]])]),m(`div`,ze,[i[34]||=m(`label`,null,`档位`,-1),g(m(`select`,{"onUpdate:modelValue":i[1]||=e=>x.value.tier=e},[...i[33]||=[m(`option`,{value:`local`},`local(本地 / 零边际成本)`,-1),m(`option`,{value:`budget`},`budget(低价 API`,-1),m(`option`,{value:`premium`},`premium(旗舰 API`,-1)]],512),[[u,x.value.tier]])]),m(`div`,Be,[i[36]||=m(`label`,null,`后端`,-1),g(m(`select`,{"onUpdate:modelValue":i[2]||=e=>x.value.backend=e},[...i[35]||=[m(`option`,{value:`openai`},`openai / 兼容 API`,-1),m(`option`,{value:`llama_server`},`llama_server(内置本地)`,-1),m(`option`,{value:`mock`},`mock(模拟)`,-1)]],512),[[u,x.value.backend]])]),m(`div`,Ve,[m(`label`,null,[i[37]||=c(` 模型 `,-1),m(`button`,{class:`btn-refresh btn-inline`,disabled:D.value,onClick:kn},a(D.value?`…`:`🔄 刷新列表`),9,He)]),g(m(`input`,{"onUpdate:modelValue":i[3]||=e=>x.value.model=e,list:`pool-model-options`,placeholder:`模型名`},null,512),[[r,x.value.model]]),m(`datalist`,Ue,[(o(!0),p(n,null,s(vn.value,e=>(o(),p(`option`,{key:e.id,value:e.id},null,8,We))),128))])]),x.value.backend===`mock`?e(``,!0):(o(),p(`div`,Ge,[i[38]||=m(`label`,null,`API 地址`,-1),g(m(`input`,{"onUpdate:modelValue":i[4]||=e=>x.value.base_url=e,placeholder:`https://api.deepseek.com 或 http://127.0.0.1:8901/v1`},null,512),[[r,x.value.base_url]])])),x.value.backend===`openai`?(o(),p(`div`,Ke,[m(`label`,null,`API Key`+a(x.value.api_key_set?`(已设置,留空保留)`:``),1),g(m(`input`,{"onUpdate:modelValue":i[5]||=e=>x.value.api_key=e,type:`password`,autocomplete:`off`,placeholder:`sk-…`},null,512),[[r,x.value.api_key]])])):e(``,!0),m(`div`,qe,[i[39]||=m(`label`,null,`输入单价 $/1M`,-1),g(m(`input`,{"onUpdate:modelValue":i[6]||=e=>x.value.price_in=e,type:`number`,min:`0`,step:`0.01`},null,512),[[r,x.value.price_in,void 0,{number:!0}]])]),m(`div`,Je,[i[40]||=m(`label`,null,`输出单价 $/1M`,-1),g(m(`input`,{"onUpdate:modelValue":i[7]||=e=>x.value.price_out=e,type:`number`,min:`0`,step:`0.01`},null,512),[[r,x.value.price_out,void 0,{number:!0}]])]),m(`div`,Ye,[i[41]||=m(`label`,null,`Temperature`,-1),g(m(`input`,{"onUpdate:modelValue":i[8]||=e=>x.value.temperature=e,type:`number`,min:`0`,max:`2`,step:`0.05`},null,512),[[r,x.value.temperature,void 0,{number:!0}]])]),m(`div`,Xe,[i[42]||=m(`label`,null,`Max Tokens`,-1),g(m(`input`,{"onUpdate:modelValue":i[9]||=e=>x.value.max_tokens=e,type:`number`,min:`256`,max:`32768`},null,512),[[r,x.value.max_tokens,void 0,{number:!0}]])])]),m(`div`,Ze,[m(`label`,Qe,[g(m(`input`,{type:`checkbox`,"onUpdate:modelValue":i[10]||=e=>x.value.enabled=e},null,512),[[ve,x.value.enabled]]),i[43]||=c(` 启用 `,-1)]),m(`button`,{class:`btn-primary`,disabled:E.value,onClick:Tn},a(E.value?`保存中…`:`保存条目`),9,$e),m(`button`,{class:`btn-secondary`,onClick:i[11]||=e=>x.value=null},`取消`)])])):e(``,!0)])]),m(`section`,et,[m(`div`,tt,[i[45]||=m(`span`,null,`🔧 小模型 (Worker · 本地 llama.cpp)`,-1),m(`div`,nt,[m(`span`,{class:d([`server-badge`,O.value.running?`badge-running`:`badge-stopped`])},a(O.value.running?`● 运行中`:`○ 已停止`),3)])]),m(`div`,rt,[m(`div`,it,[m(`div`,at,[O.value.running?(o(),p(n,{key:0},[m(`span`,ot,a(O.value.model?.split(/[/\\]/).pop()),1),m(`span`,st,`:`+a(O.value.port),1),m(`span`,ct,`PID `+a(O.value.pid),1)],64)):(o(),p(`span`,lt,`llama-server 未运行 — 点击「启动服务」即可启用`))]),m(`div`,ut,[O.value.running?(o(),p(`button`,{key:1,class:`btn-stop`,disabled:k.value||A.value,onClick:zn},a(A.value?`停止中…`:`■ 停止服务`),9,ft)):(o(),p(`button`,{key:0,class:`btn-start`,disabled:k.value||A.value,onClick:Rn},a(k.value?`启动中…`:`▶ 启动服务`),9,dt))])]),O.value.error?(o(),p(`div`,pt,a(O.value.error),1)):e(``,!0),m(`div`,mt,[m(`div`,ht,[m(`span`,null,`📁 本地模型 (`+a(j.value.length)+`)`,1),m(`button`,{class:`btn-refresh`,disabled:M.value,onClick:Z},a(M.value?`…`:`🔄`),9,gt)]),j.value.length===0&&!M.value?(o(),p(`div`,_t,` 暂无本地模型,请下载或放置 .gguf 文件到 models/ 目录 `)):(o(),p(`div`,vt,[(o(!0),p(n,null,s(j.value,e=>(o(),p(`div`,{key:e.id,class:d([`model-item`,N.value===e.id?`selected`:``]),onClick:t=>Bn(e)},[m(`span`,bt,a(e.name),1),m(`span`,xt,a(e.size_mb)+` MB`,1)],10,yt))),128))]))]),m(`div`,St,[i[46]||=m(`div`,{class:`download-header`},`⬇️ 下载模型`,-1),m(`div`,Ct,[g(m(`input`,{"onUpdate:modelValue":i[12]||=e=>F.value=e,class:`download-input`,placeholder:`HuggingFace 路径或直链,如:Qwen/Qwen3-4B-GGUF/Qwen3-4B-Q4_K_M.gguf`,disabled:P.value},null,8,wt),[[r,F.value]]),m(`button`,{class:`btn-download`,disabled:P.value||!F.value.trim(),onClick:Vn},a(P.value?I.value+`%`:`下载`),9,Tt)]),P.value?(o(),p(`div`,Et,[m(`div`,Dt,[m(`div`,{class:`progress-fill`,style:re({width:I.value+`%`})},null,4)]),m(`div`,Ot,[m(`span`,null,a(L.value),1),m(`span`,null,a(An.value),1),m(`span`,null,a(jn.value)+`/`+a(R.value||`?`),1)])])):e(``,!0),z.value?(o(),p(`div`,kt,a(z.value),1)):e(``,!0),Nn.value&&!z.value?(o(),p(`div`,At,` ✅ 下载完成:`+a(Mn.value),1)):e(``,!0)]),m(`div`,jt,[m(`div`,Mt,[i[48]||=m(`label`,null,`后端类型`,-1),g(m(`select`,{"onUpdate:modelValue":i[13]||=e=>X.worker.backend=e,onChange:Un},[...i[47]||=[m(`option`,{value:`mock`},`mock(模拟,不真实调用)`,-1),m(`option`,{value:`llama_server`},`llama_server(内置本地服务,推荐)`,-1),m(`option`,{value:`openai`},`openai / 兼容 APIOllama 等)`,-1)]],544),[[u,X.worker.backend]])]),X.worker.backend===`mock`?e(``,!0):(o(),p(`div`,Nt,[m(`label`,null,[i[49]||=c(` API 地址 `,-1),m(`button`,{class:`btn-refresh btn-inline`,disabled:G.worker,onClick:Kn},a(G.worker?`…`:`🔗 连接测试`),9,Pt)]),m(`div`,Ft,[g(m(`input`,{"onUpdate:modelValue":i[14]||=e=>X.worker.base_url=e,placeholder:Pn.value,onBlur:Un},null,40,It),[[r,X.worker.base_url]]),K.worker===null?e(``,!0):(o(),p(`span`,{key:0,class:d([`ping-badge`,K.worker?`ping-ok`:`ping-err`])},a(K.worker?`✅ 正常`:`❌ `+q.worker),3))])])),X.worker.backend===`mock`?e(``,!0):(o(),p(`div`,Lt,[m(`label`,null,[i[50]||=c(` 模型 `,-1),m(`button`,{class:`btn-refresh btn-inline`,disabled:U.worker,onClick:Q},a(U.worker?`…`:`🔄 刷新列表`),9,Rt)]),X.worker.backend===`llama_server`?g((o(),p(`select`,{key:0,"onUpdate:modelValue":i[15]||=e=>X.worker.model=e},[i[51]||=m(`option`,{value:``,disabled:``},`—— 从本地模型中选择 ——`,-1),(o(!0),p(n,null,s(j.value,e=>(o(),p(`option`,{key:e.id,value:e.id},a(e.name),9,zt))),128))],512)),[[u,X.worker.model]]):X.worker.backend===`openai`?g((o(),p(`select`,{key:1,"onUpdate:modelValue":i[16]||=e=>X.worker.model=e},[i[52]||=m(`option`,{value:``,disabled:``},`—— 从 API 获取 ——`,-1),(o(!0),p(n,null,s(V.value,e=>(o(),p(`option`,{key:e.id,value:e.id},a(e.name||e.id),9,Bt))),128))],512)),[[u,X.worker.model]]):g((o(),p(`input`,{key:2,"onUpdate:modelValue":i[17]||=e=>X.worker.model=e,placeholder:`输入模型名称…`},null,512)),[[r,X.worker.model]]),W.worker?(o(),p(`span`,Vt,a(W.worker),1)):e(``,!0)])),X.worker.backend===`llama_server`?(o(),p(`div`,Ht,[i[53]||=m(`label`,null,`端口`,-1),g(m(`input`,{"onUpdate:modelValue":i[18]||=e=>X.worker.port=e,type:`number`,min:`1`,max:`65535`},null,512),[[r,X.worker.port,void 0,{number:!0}]])])):e(``,!0),m(`div`,Ut,[i[54]||=m(`label`,null,`Temperature`,-1),g(m(`input`,{"onUpdate:modelValue":i[19]||=e=>X.worker.temperature=e,type:`number`,min:`0`,max:`2`,step:`0.05`},null,512),[[r,X.worker.temperature,void 0,{number:!0}]])]),m(`div`,Wt,[i[55]||=m(`label`,null,`最大修复轮次`,-1),g(m(`input`,{"onUpdate:modelValue":i[20]||=e=>X.worker.max_fix_attempts=e,type:`number`,min:`0`,max:`10`},null,512),[[r,X.worker.max_fix_attempts,void 0,{number:!0}]])]),m(`div`,Gt,[i[56]||=m(`label`,null,`代码执行超时 (秒)`,-1),g(m(`input`,{"onUpdate:modelValue":i[21]||=e=>X.worker.code_timeout_s=e,type:`number`,min:`1`,max:`300`},null,512),[[r,X.worker.code_timeout_s,void 0,{number:!0}]])])])])]),m(`section`,Kt,[m(`div`,qt,[i[57]||=m(`span`,null,`🧠 大模型 (Architect · API 云端)`,-1),m(`div`,Jt,[K.architect===null?e(``,!0):(o(),p(`span`,{key:0,class:d([`ping-badge`,K.architect?`ping-ok`:`ping-err`])},a(K.architect?`✅ 已连接`:`❌ `+q.architect),3))])]),m(`div`,Yt,[m(`div`,Xt,[m(`div`,Zt,[m(`label`,null,[i[58]||=c(` API 端点 `,-1),m(`button`,{class:`btn-refresh btn-inline`,disabled:G.architect,onClick:qn},a(G.architect?`…`:`🔗 连接测试`),9,Qt)]),g(m(`input`,{"onUpdate:modelValue":i[22]||=e=>X.architect.base_url=e,placeholder:`https://api.deepseek.com`,onBlur:Wn},null,544),[[r,X.architect.base_url]])]),m(`div`,$t,[i[59]||=m(`label`,null,`API Key(保存在本地 config/settings.json,不入代码库;优先级高于 .env)`,-1),g(m(`input`,{"onUpdate:modelValue":i[23]||=e=>X.architect.api_key=e,type:`password`,placeholder:`sk-xxxxxxxxxxxxxxxx`,autocomplete:`off`},null,512),[[r,X.architect.api_key]])]),m(`div`,en,[m(`label`,null,[i[60]||=c(` 模型 `,-1),m(`button`,{class:`btn-refresh btn-inline`,disabled:U.architect,onClick:Gn},a(U.architect?`…`:`🔄 刷新列表`),9,tn)]),g(m(`select`,{"onUpdate:modelValue":i[24]||=e=>X.architect.model=e,class:`model-select`},[i[61]||=m(`option`,{value:``,disabled:``},`—— 从 API 获取模型列表 ——`,-1),(o(!0),p(n,null,s(H.value,e=>(o(),p(`option`,{key:e.id,value:e.id},a(e.name||e.id),9,nn))),128))],512),[[u,X.architect.model]]),W.architect?(o(),p(`span`,rn,a(W.architect),1)):e(``,!0)])])])]),m(`section`,an,[i[67]||=m(`div`,{class:`section-title`},[m(`span`,null,`⚙️ 协作管线 (Pipeline)`)],-1),m(`div`,on,[m(`div`,sn,[m(`div`,cn,[m(`label`,ln,[g(m(`input`,{type:`checkbox`,"onUpdate:modelValue":i[25]||=e=>X.pipeline.fast_path=e},null,512),[[ve,X.pipeline.fast_path]]),i[62]||=c(` 启用快路径(简单查询跳过本地模型,直接由大模型回答,省 API 费用) `,-1)])]),m(`div`,un,[i[63]||=m(`label`,null,`最大协作轮次`,-1),g(m(`input`,{"onUpdate:modelValue":i[26]||=e=>X.pipeline.rounds_cap=e,type:`number`,min:`1`,max:`20`},null,512),[[r,X.pipeline.rounds_cap,void 0,{number:!0}]])]),m(`div`,dn,[i[64]||=m(`label`,null,`API Token 熔断上限`,-1),g(m(`input`,{"onUpdate:modelValue":i[27]||=e=>X.pipeline.api_token_cap=e,type:`number`,min:`100`,max:`100000`},null,512),[[r,X.pipeline.api_token_cap,void 0,{number:!0}]])]),m(`div`,fn,[i[66]||=m(`label`,null,`超限策略`,-1),g(m(`select`,{"onUpdate:modelValue":i[28]||=e=>X.pipeline.breach_policy=e},[...i[65]||=[m(`option`,{value:`architect_do`},`architect_do(超限交给大模型处理,推荐)`,-1),m(`option`,{value:`local_only`},`local_only(强制留在本地小模型)`,-1)]],512),[[u,X.pipeline.breach_policy]])])])])]),m(`div`,pn,[m(`button`,{class:`btn-primary`,disabled:h.value||!Fn.value,onClick:Yn},a(h.value?`保存中…`:`💾 保存设置`),9,mn),m(`button`,{class:`btn-secondary`,disabled:h.value,onClick:Xn},` 🔁 恢复默认 `,8,hn)]),v.value?(o(),p(`div`,{key:0,class:d([`toast`,v.value.ok?`toast-ok`:`toast-err`])},a(v.value.msg),3)):e(``,!0)]))}}),[[`__scopeId`,`data-v-7b21dc2a`]]);export{_ as default};