ellm-proxy 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/bin/commands/autostart.js +213 -0
  4. package/bin/commands/config.js +8 -0
  5. package/bin/commands/pm2.js +28 -0
  6. package/bin/commands/service.js +107 -0
  7. package/bin/ellm-proxy.js +61 -0
  8. package/dist/package.json +1 -0
  9. package/dist/server.js +12176 -0
  10. package/dist/web-ui/assets/DashboardView-CQdlgirS.js +1 -0
  11. package/dist/web-ui/assets/DashboardView-qrQrkgLA.css +1 -0
  12. package/dist/web-ui/assets/LayoutView-BaY4Pz9W.js +1 -0
  13. package/dist/web-ui/assets/LoginView-CPvz1Ylx.js +1 -0
  14. package/dist/web-ui/assets/LoginView-Dg0mB6ok.css +1 -0
  15. package/dist/web-ui/assets/LogsView-B-bIj36j.js +9 -0
  16. package/dist/web-ui/assets/LogsView-Wl3_adHm.css +1 -0
  17. package/dist/web-ui/assets/ProcessView-0x_ShSwV.js +1 -0
  18. package/dist/web-ui/assets/ProcessView-DzMqBJmd.css +1 -0
  19. package/dist/web-ui/assets/ProvidersView-BxAxDRFH.css +1 -0
  20. package/dist/web-ui/assets/ProvidersView-GQENcvJS.js +31 -0
  21. package/dist/web-ui/assets/SettingsView-BDkymsrS.css +1 -0
  22. package/dist/web-ui/assets/SettingsView-BrAiaskZ.js +1 -0
  23. package/dist/web-ui/assets/config-DNn5cjYY.js +1 -0
  24. package/dist/web-ui/assets/index-BecfPmag.css +1 -0
  25. package/dist/web-ui/assets/index-DFlUx18F.js +96 -0
  26. package/dist/web-ui/assets/providers-CGEmOxne.js +1 -0
  27. package/dist/web-ui/assets/useApi-BRPinb_2.js +1 -0
  28. package/dist/web-ui/assets/useManagerApi-BDWJz5o6.js +1 -0
  29. package/dist/web-ui/assets/useToast-D7xlwSg6.js +1 -0
  30. package/dist/web-ui/config.js +10 -0
  31. package/dist/web-ui/index.html +15 -0
  32. package/docs/DESIGN.md +99 -0
  33. package/ellm.config.example.json +33 -0
  34. package/manager/api/harness/backup.js +20 -0
  35. package/manager/api/harness/claude-code.js +54 -0
  36. package/manager/api/harness/codex.js +123 -0
  37. package/manager/api/harness/dsh.js +175 -0
  38. package/manager/api/harness/index.js +118 -0
  39. package/manager/api/service.js +157 -0
  40. package/manager/index.js +170 -0
  41. package/package.json +40 -0
  42. package/utils/interpreter.js +14 -0
  43. package/utils/paths.js +44 -0
  44. package/utils/pm2.js +130 -0
  45. package/utils/port.js +35 -0
  46. package/utils/service.js +189 -0
  47. package/utils/ui.js +59 -0
@@ -0,0 +1 @@
1
+ import{u as D}from"./useToast-D7xlwSg6.js";import{A as q}from"./useApi-BRPinb_2.js";import{u as G}from"./config-DNn5cjYY.js";import{d as N,i as H,n as R,o as x,j as T,w as o,c as U,b as t,t as A,k as B,e as n,a as s,F as L,l as d,$ as J,r as i,m as M,_ as Q}from"./index-DFlUx18F.js";import{m as P}from"./useManagerApi-BDWJz5o6.js";const Z={class:"flex-between"},ee={class:"muted-sm mb-8"},le={class:"switch-row"},se={class:"switch-info"},te={class:"switch-title"},oe={class:"switch-row"},ae={class:"switch-info"},ne={class:"switch-title"},ie={class:"switch-row"},ue={class:"switch-info"},de={class:"switch-title"},re=N({__name:"HarnessSwitches",setup(O){const{toast:h}=D(),v=d(!0),k=d(!1),u=d(null),g=d(null),c=d(null),p=d(null),y=d("success"),w=async m=>{m||(u.value?k.value=!0:v.value=!0);try{u.value=await P.harness(),g.value=null}catch(l){m||(g.value=l.message)}finally{m||(v.value=!1,k.value=!1)}};H(()=>w(!1));const E={claudeCode:{label:"Claude Code",file:"~/.claude/settings.json",toggle:P.setClaudeCode},codex:{label:"Codex CLI",file:"~/.codex/config.toml",toggle:P.setCodex},dsh:{label:"DeepSeek Harness",file:"~/.dsh/settings.yaml",toggle:P.setDsh}},b=async(m,l)=>{if(!u.value||c.value)return;const _=E[m],a=l?`确定开启 ${_.label} 代理?将改写 ${_.file}(开启前自动备份,关闭时从备份还原)。`:`确定关闭 ${_.label} 代理?将从备份还原 ${_.file}(无备份时移除代理相关配置)。`;try{await J.confirm(a,l?"开启确认":"关闭确认",{confirmButtonText:l?"开启":"关闭",cancelButtonText:"取消",type:"warning"})}catch{return}c.value=m;try{const e=await _.toggle(l);p.value=e.note??null,y.value=l?"success":"info",h(l?"已开启代理":"已关闭代理","success")}catch(e){h(e.message||"操作失败","error")}finally{c.value=null,await w(!0)}};return(m,l)=>{const _=i("el-button"),a=i("el-alert"),e=i("el-tag"),V=i("el-switch"),S=i("el-divider"),C=i("el-empty"),$=i("el-card"),I=M("loading");return R((x(),T($,{shadow:"never"},{header:o(()=>[t("div",Z,[l[7]||(l[7]=t("span",{class:"fw-600"},"代理开关",-1)),s(_,{loading:k.value,onClick:l[0]||(l[0]=f=>w(!1))},{default:o(()=>[...l[6]||(l[6]=[n("刷新",-1)])]),_:1},8,["loading"])])]),default:o(()=>[u.value?(x(),U(L,{key:0},[t("div",ee," 将本机 CLI 工具的流量一键指向 ellm-proxy 网关("+A(u.value.gatewayBase)+")。 开启前自动备份原配置为 *.ellm-bak(保留最早的原始备份),关闭时从备份还原。 ",1),p.value?(x(),T(a,{key:0,title:p.value,type:y.value,"show-icon":"",class:"mb-8",onClose:l[1]||(l[1]=f=>p.value=null)},null,8,["title","type"])):B("",!0),t("div",le,[t("div",se,[t("div",te,[l[8]||(l[8]=n(" Claude Code ",-1)),s(e,{type:u.value.claudeCode?"success":"info",size:"small","disable-transitions":""},{default:o(()=>[n(A(u.value.claudeCode?"已开启":"未开启"),1)]),_:1},8,["type"])]),l[9]||(l[9]=t("div",{class:"switch-desc"},[n(" 写入 "),t("code",null,"~/.claude/settings.json"),n(" 的 env.ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN, 鉴权取网关配置的 masterKey(未设置将开启失败);其余字段原样保留,重启 Claude Code 会话后生效。 ")],-1))]),s(V,{"model-value":u.value.claudeCode,loading:c.value==="claudeCode",onChange:l[2]||(l[2]=f=>b("claudeCode",!!f))},null,8,["model-value","loading"])]),s(S,{class:"switch-divider"}),t("div",oe,[t("div",ae,[t("div",ne,[l[10]||(l[10]=n(" Codex CLI ",-1)),s(e,{type:u.value.codex?"success":"info",size:"small","disable-transitions":""},{default:o(()=>[n(A(u.value.codex?"已开启":"未开启"),1)]),_:1},8,["type"])]),l[11]||(l[11]=t("div",{class:"switch-desc"},[n(" 写入 "),t("code",null,"~/.codex/config.toml"),n(" 的 model_provider 与 [model_providers.ellm-proxy] 段 (保留用户注释与排版);开启后需按提示设置环境变量 ELLM_PROXY_API_KEY 供 Codex 鉴权。 ")],-1))]),s(V,{"model-value":u.value.codex,loading:c.value==="codex",onChange:l[3]||(l[3]=f=>b("codex",!!f))},null,8,["model-value","loading"])]),s(S,{class:"switch-divider"}),t("div",ie,[t("div",ue,[t("div",de,[l[12]||(l[12]=n(" DeepSeek Harness ",-1)),s(e,{type:u.value.dsh?"success":"info",size:"small","disable-transitions":""},{default:o(()=>[n(A(u.value.dsh?"已开启":"未开启"),1)]),_:1},8,["type"])]),l[13]||(l[13]=t("div",{class:"switch-desc"},[n(" 写入 "),t("code",null,"~/.dsh/settings.yaml"),n(" 的 llm-deepseek.baseURL 与 "),t("code",null,"~/.dsh/.credentials.yaml"),n(" 的 DEEPSEEK_API_KEY(取网关 masterKey,未设置则写占位值);模型请在 dsh 内选择与网关部署名一致的模型。 dsh 为 developer preview,配置格式可能随版本变化。 ")],-1))]),s(V,{"model-value":u.value.dsh,loading:c.value==="dsh",onChange:l[4]||(l[4]=f=>b("dsh",!!f))},null,8,["model-value","loading"])])],64)):(x(),T(C,{key:1,description:g.value||"暂无开关状态"},{default:o(()=>[s(_,{type:"primary",onClick:l[5]||(l[5]=f=>w(!1))},{default:o(()=>[...l[14]||(l[14]=[n("重试",-1)])]),_:1})]),_:1},8,["description"]))]),_:1})),[[I,v.value]])}}}),me=Q(re,[["__scopeId","data-v-e8a0f661"]]),ve={class:"flex-col-gap"},ce={class:"flex-between"},pe={class:"muted-sm"},_e={key:0},fe={class:"flex-end"},xe=N({__name:"SettingsView",setup(O){const{toast:h}=D(),v=G(),k=d("basic"),u=d(!0),g=d(!1),c=d(""),p=d(29770),y=d(null),w=d("passthrough"),E=d(!1),b=d(""),m=d(""),l=async()=>{var a;try{await v.load(),c.value=v.config.masterKey||"",p.value=v.config.port??29770,w.value=v.config.compression==="plain"?"plain":"passthrough",E.value=v.config.logContent===!0;const e=(a=v.config["web-ui"])==null?void 0:a["login-account"];b.value=(e==null?void 0:e.username)||"",m.value=(e==null?void 0:e.password)||"";try{y.value=await q.get("/api/status").then(V=>V.listenPort)}catch{y.value=null}}catch(e){h(e.message,"error")}finally{u.value=!1}},_=async()=>{g.value=!0;try{await v.update(a=>{var e;a.masterKey=c.value.trim(),a.port=p.value,a.compression=w.value,a.logContent=E.value,a["web-ui"]??(a["web-ui"]={}),(e=a["web-ui"])["login-account"]??(e["login-account"]={}),a["web-ui"]["login-account"].username=b.value.trim(),a["web-ui"]["login-account"].password=m.value}),h("设置已保存并生效","success")}catch(a){h(a.message,"error")}finally{g.value=!1}};return H(l),(a,e)=>{const V=i("el-tag"),S=i("el-input"),C=i("el-form-item"),$=i("el-input-number"),I=i("el-option"),f=i("el-select"),z=i("el-switch"),W=i("el-form"),j=i("el-card"),Y=i("el-button"),K=i("el-tab-pane"),F=i("el-tabs"),X=M("loading");return x(),T(F,{modelValue:k.value,"onUpdate:modelValue":e[6]||(e[6]=r=>k.value=r),class:"settings-tabs"},{default:o(()=>[s(K,{label:"基本设置",name:"basic"},{default:o(()=>[R((x(),U("div",ve,[s(j,{shadow:"never"},{header:o(()=>[t("div",ce,[e[8]||(e[8]=t("span",{class:"fw-600"},"基本设置",-1)),s(V,{type:"success"},{default:o(()=>[...e[7]||(e[7]=[n("运行中",-1)])]),_:1})])]),default:o(()=>[s(W,{"label-position":"top"},{default:o(()=>[s(C,{label:"Master Key"},{default:o(()=>[s(S,{modelValue:c.value,"onUpdate:modelValue":e[0]||(e[0]=r=>c.value=r),type:"password",placeholder:"sk-1234","show-password":""},null,8,["modelValue"]),e[9]||(e[9]=t("div",{class:"muted-sm"}," 网关 API 认证密钥(/v1/* 请求需携带 Bearer <masterKey>;留空 = 本地放行) ",-1))]),_:1}),s(C,{label:"监听端口 (port)"},{default:o(()=>[s($,{modelValue:p.value,"onUpdate:modelValue":e[1]||(e[1]=r=>p.value=r),min:1,max:65535,step:1,class:"full-width"},null,8,["modelValue"]),t("div",pe,[e[11]||(e[11]=n(" 网关与管理台 API 的监听端口,保存后下次重启生效 ",-1)),y.value!==null?(x(),U(L,{key:0},[e[10]||(e[10]=n(" ;当前实际监听 ",-1)),t("b",null,A(y.value),1),y.value!==p.value?(x(),U("span",_e,"(由 PORT 环境变量覆盖,此配置值不生效)")):B("",!0)],64)):B("",!0)])]),_:1}),s(C,{label:"压缩语义 (compression)"},{default:o(()=>[s(f,{modelValue:w.value,"onUpdate:modelValue":e[2]||(e[2]=r=>w.value=r),class:"full-width"},{default:o(()=>[s(I,{label:"透传 (passthrough)",value:"passthrough"}),s(I,{label:"明文 (plain)",value:"plain"})]),_:1},8,["modelValue"]),e[12]||(e[12]=t("div",{class:"muted-sm"},"上游响应压缩处理方式,保存后热更新生效",-1))]),_:1}),s(C,{label:"日志内容捕获 (logContent)"},{default:o(()=>[s(z,{modelValue:E.value,"onUpdate:modelValue":e[3]||(e[3]=r=>E.value=r)},null,8,["modelValue"]),e[13]||(e[13]=t("div",{class:"muted-sm"}," 记录完整请求/响应(含上游原始与转换后内容)进日志详情,用于排查定位问题;开启后有少量内存与存储开销,保存后热更新生效 ",-1))]),_:1}),s(C,{label:"管理台用户名 (web-ui.login-account.username)"},{default:o(()=>[s(S,{modelValue:b.value,"onUpdate:modelValue":e[4]||(e[4]=r=>b.value=r),placeholder:"admin"},null,8,["modelValue"]),e[14]||(e[14]=t("div",{class:"muted-sm"}," 管理台登录用户名,留空回退 WEBUI_USERNAME 环境变量或默认 admin ",-1))]),_:1}),s(C,{label:"管理台密码 (web-ui.login-account.password)"},{default:o(()=>[s(S,{modelValue:m.value,"onUpdate:modelValue":e[5]||(e[5]=r=>m.value=r),type:"password",placeholder:"admin","show-password":""},null,8,["modelValue"]),e[15]||(e[15]=t("div",{class:"muted-sm"}," 管理台登录密码,留空回退 WEBUI_PASSWORD 环境变量或默认 admin;修改保存后立即生效,需用新账号重新登录 ",-1))]),_:1})]),_:1})]),_:1}),t("div",fe,[s(Y,{type:"primary",loading:g.value,disabled:g.value,onClick:_},{default:o(()=>[n(A(g.value?"保存中...":"保存设置"),1)]),_:1},8,["loading","disabled"])])])),[[X,u.value]])]),_:1}),s(K,{label:"代理开关",name:"harness",lazy:""},{default:o(()=>[s(me)]),_:1})]),_:1},8,["modelValue"])}}});export{xe as default};
@@ -0,0 +1 @@
1
+ import{U as p,l as u,f as n}from"./index-DFlUx18F.js";import{A as i}from"./useApi-BRPinb_2.js";const m=p("config",()=>{const e=u({}),o=u(!1),t=n(()=>Array.isArray(e.value.providers)?e.value.providers:[]),l=n(()=>t.value.length),c=n(()=>t.value.reduce((a,d)=>{var s;return a+(((s=d.models)==null?void 0:s.length)??0)},0));async function f(){o.value=!0;try{e.value=await i.get("/api/config")}finally{o.value=!1}}async function r(){return await i.put("/api/config",e.value)}async function v(a){return a(e.value),await r()}return{config:e,loading:o,providers:t,providerCount:l,totalModelCount:c,load:f,save:r,update:v}});export{m as u};