ezllm 0.0.36 → 0.0.38

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 (51) hide show
  1. package/README.md +67 -21
  2. package/dist/cli.js +26 -28
  3. package/dist/daemon.js +10 -15
  4. package/dist/plugin-host.js +5 -0
  5. package/dist/server.js +86 -78
  6. package/dist/web-ui/assets/DashboardView-STI4Bkxw.js +1 -0
  7. package/dist/web-ui/assets/LayoutView-CQJN31vh.css +1 -0
  8. package/dist/web-ui/assets/LayoutView-DHXc1jcz.js +1 -0
  9. package/dist/web-ui/assets/{LoginView-Dh-JvmGC.js → LoginView-CwH6eISd.js} +1 -1
  10. package/dist/web-ui/assets/LogsView-CGgzVbGZ.js +5 -0
  11. package/dist/web-ui/assets/LogsView-u-0B5Xpc.css +1 -0
  12. package/dist/web-ui/assets/{ManagedServicesView-C5ZROVtT.js → ManagedServicesView-BvzeGhcb.js} +2 -2
  13. package/dist/web-ui/assets/PluginsView-CNDVeVj8.js +2 -0
  14. package/dist/web-ui/assets/PluginsView-zyTILSF1.css +1 -0
  15. package/dist/web-ui/assets/{ProvidersView-Dwc7I6G0.js → ProvidersView-DTIx2VSi.js} +3 -3
  16. package/dist/web-ui/assets/ServiceStatusView-BvuFCgT-.js +2 -0
  17. package/dist/web-ui/assets/SettingsView-CB_w0Y2E.css +1 -0
  18. package/dist/web-ui/assets/SettingsView-W9bjQ9ly.js +1 -0
  19. package/dist/web-ui/assets/SetupView-CSBKlfcJ.css +1 -0
  20. package/dist/web-ui/assets/SetupView-D5KYolFQ.js +1 -0
  21. package/dist/web-ui/assets/{config-DXHhKDw-.js → config-CX31TfJ4.js} +1 -1
  22. package/dist/web-ui/assets/format-7jzqzMS_.js +1 -0
  23. package/dist/web-ui/assets/{index-BKnCp9qM.js → index-D6ydfwRk.js} +1 -1
  24. package/dist/web-ui/assets/{index-wQvjidwN.css → index-s_h6GEbv.css} +1 -1
  25. package/dist/web-ui/assets/{message-C1fkA9sE.js → message-B022-tc2.js} +1 -1
  26. package/dist/web-ui/assets/providers-C6QKdfzy.js +1 -0
  27. package/dist/web-ui/assets/{router-DI9ZLaCn.js → router-Daxct41S.js} +2 -2
  28. package/dist/web-ui/assets/src-DLq1gsLr.js +1 -0
  29. package/dist/web-ui/assets/updateNote-CttDt8SZ.js +1 -0
  30. package/dist/web-ui/assets/useCopyToast-0dz9T4-H.js +1 -0
  31. package/dist/web-ui/assets/useManagerApi-DdgACgsq.js +1 -0
  32. package/dist/web-ui/assets/{useQuickRangeFilter-Crb6MDvU.js → useQuickRangeFilter-D8oTOMUp.js} +1 -1
  33. package/dist/web-ui/assets/useToast-nQZ8k6t7.js +1 -0
  34. package/dist/web-ui/index.html +4 -4
  35. package/package.json +4 -1
  36. package/dist/cpa.js +0 -15
  37. package/dist/web-ui/assets/DashboardView-4pju0xUn.js +0 -1
  38. package/dist/web-ui/assets/LayoutView-BLjO8ed9.css +0 -1
  39. package/dist/web-ui/assets/LayoutView-DjpChErJ.js +0 -1
  40. package/dist/web-ui/assets/LogsView-BLOCTdb6.js +0 -5
  41. package/dist/web-ui/assets/LogsView-D7FTeaYQ.css +0 -1
  42. package/dist/web-ui/assets/ServiceStatusView-fiaEQZNp.js +0 -2
  43. package/dist/web-ui/assets/SettingsView-DygfiGG8.css +0 -1
  44. package/dist/web-ui/assets/SettingsView-MrcC_nr9.js +0 -1
  45. package/dist/web-ui/assets/SetupView-BLl-ZFOA.css +0 -1
  46. package/dist/web-ui/assets/SetupView-vTCaewVk.js +0 -1
  47. package/dist/web-ui/assets/format-DbT9vkcP.js +0 -1
  48. package/dist/web-ui/assets/providers-BHK2eZZc.js +0 -1
  49. package/dist/web-ui/assets/useManagerApi-l9V9LoLa.js +0 -1
  50. package/dist/web-ui/assets/useToast-PFDoTWpf.js +0 -1
  51. package/dist/web-ui/assets/version-DegxwpkG.js +0 -1
package/dist/cpa.js DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
- import{join as e,resolve as t}from"node:path";import{pathToFileURL as n}from"node:url";import{appendFileSync as r,existsSync as i,readFileSync as a,readdirSync as o,statSync as s}from"node:fs";import{randomBytes as c,randomUUID as l}from"node:crypto";import{homedir as u}from"node:os";import{rename as d,writeFile as f}from"node:fs/promises";import{createServer as p}from"node:http";function m(e,...t){console.log(e,...t)}function h(e,...t){console.warn(e,...t)}function g(e,...t){console.error(e,...t)}var _=class extends Error{status;detail;constructor(e,t,n){super(t),this.name=`CpaHttpError`,this.status=e,this.detail=n}},v=class extends Error{code=`BODY_TOO_LARGE`;constructor(){super(`request body too large`),this.name=`BodyTooLargeError`}};function y(e,t){return{error:{message:e,type:t}}}function b(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function x(e){let t=e.search(/[?#]/);return t>=0?e.slice(0,t):e}function S(e,t,n){if(e.headersSent){try{e.end()}catch{}return}e.writeHead(t,{"Content-Type":`application/json`}),e.end(JSON.stringify(n))}function C(e,t,n){S(e,t,{detail:n})}function w(e,t){C(e,400,y(t,`invalid_request_error`))}function T(e=process.env){return Number(e.PROXY_MAX_BODY||33554432)}function ee(e,t){return new Promise((n,r)=>{let i=[],a=0;e.on(`data`,n=>{if(a+=n.length,a>t){e.destroy(),r(new v);return}i.push(n)}),e.on(`end`,()=>{n(Buffer.concat(i))}),e.on(`error`,r)})}function te(e){return e.length===0?{}:JSON.parse(e.toString(`utf8`))}async function*E(e){if(!e)return;let t=e.getReader();try{for(;;){let{done:e,value:n}=await t.read();if(e)break;n&&(yield Buffer.isBuffer(n)?n:Buffer.from(n))}}finally{try{t.releaseLock()}catch{}}}function D(){let e=new Date,t=e=>String(e).padStart(2,`0`);return`${String(e.getFullYear())}-${t(e.getMonth()+1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}var O=class{#e;constructor(e){this.#e=e}get enabled(){return this.#e!==null}log(e){let t=this.#e;if(t!==null)try{r(t,`[${D()}] ${e}\n`,`utf8`)}catch{}}};function k(e,t=80){let n=String(e??``).replace(/\n/g,` `).trim();return n.length>t?`${n.slice(0,t)}…`:n}function ne(e){try{return JSON.stringify(String(e))}catch{return String(e)}}function A(e,t=2){return JSON.stringify(e,null,t)}function j(e){return`[${e.map(e=>typeof e==`string`?`'${e}'`:String(e)).join(`, `)}]`}var M=class{options;constructor(e){this.options=e}init(){return Promise.resolve({ok:!0})}assertChatReady(){}transformBody(e){return{body:e}}usage(){return Promise.resolve(null)}};function N(...e){return e.find(e=>e!==void 0&&e!==``)??null}function P(e){return e.toLowerCase()===`jetbrains`?`jetbrains`:`auto`}function F(e,t=process.env){let n={host:t.PROXY_HOST||`127.0.0.1`,port:Number(t.PROXY_PORT||8787),apiKey:t.CODEBUDDY2OPENAI_KEY||``,log:null,desensitize:!1,noCompact:!1,noReasoning:!1,skipCheck:!1,credSource:t.CODEBUDDY_CRED_SOURCE||``,provider:t.CPA_PROVIDER||``,help:!1};for(let t=0;t<e.length;t+=1){let r=e[t]??``,i=r.indexOf(`=`),a=r.startsWith(`--`)&&i>=0?r.slice(0,i):r,o=r.startsWith(`--`)&&i>=0?r.slice(i+1):void 0,s=()=>o===void 0?e[++t]:o;switch(a){case`--host`:n.host=s()||n.host;break;case`--port`:n.port=Number(s());break;case`--api-key`:n.apiKey=s()||``;break;case`--log`:n.log=s()||null;break;case`--desensitize`:n.desensitize=!0;break;case`--no-compact`:n.noCompact=!0;break;case`--no-reasoning`:n.noReasoning=!0;break;case`--cred-source`:n.credSource=s()||``;break;case`--provider`:n.provider=s()||n.provider;break;case`--skip-check`:n.skipCheck=!0;break;case`--help`:case`-h`:n.help=!0}}return{help:n.help,options:{host:n.host,port:n.port,apiKey:n.apiKey,logPath:N(n.log??void 0,t.CODEBUDDY2OPENAI_LOG,t.PROXY_LOG),desensitize:n.desensitize,noCompact:n.noCompact,noReasoning:n.noReasoning,credSource:P(n.credSource),skipCheck:n.skipCheck,providerId:n.provider||`codebuddy`}}}function re(e=[`codebuddy`]){return[`cpa(CodeBuddy/WorkBuddy 订阅代理,OpenAI 兼容)`,``,`用法: cpa [选项]`,` --host HOST 监听地址(默认 127.0.0.1)`,` --port PORT 监听端口(默认 8787)`,` --api-key KEY 要求客户端携带的 API key(默认不校验)`,` --log PATH 开启数据日志并写到该文件(默认不记)`,` --desensitize 启用脱敏(零宽空格打断敏感词)`,` --no-compact 配合 --desensitize:仅零宽脱敏、不做压缩摘要`,` --no-reasoning 不透传思考内容(客户端不显示思考过程)`,` --cred-source SRC 凭据来源偏好:jetbrains=优先 IDE 登录态(等价 CODEBUDDY_CRED_SOURCE)`,` --provider ID 供应商实现(默认 codebuddy;可用:${e.join(`、`)})`,` --skip-check 跳过启动预检`,``,`环境变量: PROXY_HOST / PROXY_PORT / PROXY_UPSTREAM / CODEBUDDY_BASE_URL /`,` PROXY_LOG / CODEBUDDY2OPENAI_LOG / CODEBUDDY2OPENAI_KEY / CODEBUDDY_AUTH_DIR /`,` CODEBUDDY_CRED_SOURCE / CPA_PROVIDER`,``].join(`
3
- `)+`
4
- `}var ie=`https://copilot.tencent.com`;function I(e=process.env){return(e.PROXY_UPSTREAM||e.CODEBUDDY_BASE_URL||ie).replace(/\/+$/,``)}function ae(e=process.env){return{pluginVersion:e.CODEBUDDY_PLUGIN_VERSION||`4.12.38401955`,ideName:`JetBrainsIntelliJIdea`,ideType:`JetBrains`,ideVersion:e.CODEBUDDY_IDE_VERSION||`IU-262.10315.125`,product:`SaaS`,envId:`production`,agentIntent:`craft`}}var oe=256,se=6e4,ce=`/v2/plugin/auth/token/refresh`;function L(e){let t=String(e||``).replace(/-/g,``).toLowerCase();return/^[0-9a-f]{32}$/.test(t)?t:c(16).toString(`hex`)}function le(){let e=Promise.resolve();return function(t){let n=e.then(()=>t());return e=n.then(()=>void 0,()=>void 0),n}}var ue=class{#e;#t;#n;#r;#i;#a;#o=null;#s=null;#c=new Map;#l;constructor(e,t={}){this.#e=e,this.#i=!!e.readonly,this.#t=t.backend??I(t.env),this.#n=t.domain??`www.codebuddy.cn`,this.#r=t.profile??ae(t.env),this.#a=t.allowRefresh??!this.#i,this.#l=le()}#u(){let e;try{e=this.#e.fingerprint()}catch{return}(this.#o===null||e!==this.#s)&&(this.#o=this.#e.read(),this.#s=e)}#d(){if(this.#u(),this.#o===null)throw Error(`无法读取登录态:${this.#e.location}`);return this.#o}isExpired(){let e=this.#d().auth?.expiresAt||0;return Date.now()>=e-se}#f(e,t){let n=this.#r,r=e.domain&&e.domain!==`copilot.tencent.com`?e.domain:this.#n,i={"Content-Type":`application/json;charset=UTF-8`,Accept:`application/json`,Authorization:`Bearer ${e.accessToken||``}`,"X-User-Id":t.uid||``,"X-Domain":r,"User-Agent":`${n.ideName}/${n.ideVersion} CodeBuddy/${n.pluginVersion}`,"X-Requested-With":`XMLHttpRequest`,"X-Env-Id":n.envId,"X-Product":n.product,"X-Product-Version":n.pluginVersion,"X-IDE-Name":n.ideName,"X-IDE-Type":n.ideType,"X-IDE-Version":n.ideVersion};return t.enterpriseId&&(i[`X-Enterprise-Id`]=t.enterpriseId,i[`X-Tenant-Id`]=t.enterpriseId),t.departmentFullName&&(i[`X-Department-Info`]=t.departmentFullName),i}async#p(){if(this.#i||!this.#a)throw Error(`登录态来自只读来源(${this.#e.location}),已拒绝自动刷新:刷新会轮换 refreshToken,可能让 IDE/桌面端那份失效并被登出。请在 CodeBuddy 桌面端或 IDE 插件中重新登录以更新 token。`);let e=this.#d(),t=e.auth??{},n=this.#f(t,e.account??{});n[`X-Refresh-Token`]=t.refreshToken||``,n[`X-Auth-Refresh-Source`]=`plugin`;let r=`${this.#t}${ce}`,i;try{i=await(await fetch(r,{method:`POST`,headers:n,body:`{}`,signal:AbortSignal.timeout(15e3)})).json()}catch(e){throw Error(`刷新 token 网络失败:${e instanceof Error?e.message:String(e)}`)}if(i.code!==0||!i.data)throw Error(`刷新 token 失败:${i.msg??JSON.stringify(i)}`);let a=i.data;a.domain=a.domain||t.domain,a.lastRefreshTime=Date.now(),!a.expiresAt&&a.expiresIn&&(a.expiresAt=Date.now()+a.expiresIn*1e3),!a.refreshExpiresAt&&a.refreshExpiresIn&&(a.refreshExpiresAt=Date.now()+a.refreshExpiresIn*1e3),e.auth=a,await this.#e.write(e),this.#o=e,this.#s=this.#e.fingerprint()}async getHeaders(){return this.#l(async()=>{this.isExpired()&&await this.#p();let e=this.#d();return this.#f(e.auth??{},e.account??{})})}async getChatHeaders(e={}){let t=this.#r,n=await this.getHeaders(),r=L(e.sessionId),i=L(e.messageId),a=L(e.requestId),o=L(e.traceId),s=c(8).toString(`hex`),u=this.#c.get(r);this.#m(r,s),n.Accept=`*/*`,n[`Accept-Language`]=`*`,n[`Sec-Fetch-Mode`]=`cors`,n[`X-Agent-Intent`]=e.agentIntent||t.agentIntent,e.model&&(n[`X-Model-Id`]=e.model),n[`X-Conversation-Id`]=r,n[`X-Conversation-Message-Id`]=i,n[`X-Conversation-Request-Id`]=a,n[`X-Request-Id`]=a,n[`X-Request-Trace-Id`]=l(),n[`X-Trace-Id`]=o,n[`X-B3-TraceId`]=o,n[`X-B3-SpanId`]=s,u&&(n[`X-B3-ParentSpanId`]=u),n[`X-B3-Sampled`]=`1`,n.bo=u?`${o}-${s}-1-${u}`:`${o}-${s}-1`,n[`X-Device-Token-Error`]=`sdk_not_initialized`;let d=Date.now();return n.monitor_httpsendtime=String(d),n.monitor_promptpreparestarttime=String(e.prepareStartTime||d),n}#m(e,t){for(this.#c.delete(e),this.#c.set(e,t);this.#c.size>oe;){let e=this.#c.keys().next().value;if(e===void 0)break;this.#c.delete(e)}}summary(){let e=this.#d(),t=e.auth??{},n=e.account??{};return{uid:n.uid,nickname:n.nickname,enterpriseName:n.enterpriseName,tokenExpiresAt:t.expiresAt||0,tokenExpired:this.isExpired(),source:this.#e.location,readonly:this.#i,refreshable:this.#a&&!this.#i}}},de=[`glm-5.2`,`glm-5.1`,`glm-5v-turbo`,`kimi-k2.7`,`kimi-k2.6`,`kimi-k2.5`,`deepseek-v4-pro`,`deepseek-v4-flash`,`minimax-m3-pay`,`hy3-preview-agent`,`auto`],fe=new Set([`text-to-image`,`image-to-image`,`text-to-video`]);function pe(t){let n=u(),r=[];if(process.platform===`darwin`)r.push(`/Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/product.json`);else if(process.platform===`win32`){let n=t.LOCALAPPDATA||``;r.push(e(n,`Programs/WorkBuddy/resources/app.asar.unpacked/cli/product.json`),`C:/Program Files/WorkBuddy/resources/app.asar.unpacked/cli/product.json`)}else r.push(`/opt/WorkBuddy/resources/app.asar.unpacked/cli/product.json`,e(n,`.local/share/WorkBuddy/cli/product.json`));for(let e of r)try{if(i(e)&&s(e).isFile())return e}catch{}return null}function me(e){let t=pe(e);if(t===null)return[];try{let e=JSON.parse(a(t,`utf8`)).models??[],n=[];for(let t of e){if(t===null)continue;let e=t.id;if(!e||(t.tags??[]).some(e=>fe.has(e))||(t.vendor||``)===`tencent`)continue;let r=String(e).toLowerCase();[`completion`,`rewrite`,`jump`,`codewise`].some(e=>r.includes(e))||n.push(e)}return n}catch(e){return h(`Warning: Failed to load models from WorkBuddy product.json: ${e instanceof Error?e.message:String(e)}`),[]}}function he(e=process.env){let t=me(e);return t.length>0?t:de}function ge(t){let n=t.CODEBUDDY_AUTH_DIR;if(n)return[n];let r=u(),i=[`CodeBuddyExtension`,`Data`,`Public`,`auth`];switch(process.platform){case`darwin`:return[e(r,`Library`,`Application Support`,...i)];case`win32`:{let n=t.LOCALAPPDATA||e(r,`AppData`,`Local`);return[e(n,...i)]}default:{let n=t.XDG_DATA_HOME||e(r,`.local`,`share`);return[e(n,...i)]}}}function R(t=process.env){for(let n of ge(t)){let t;try{t=o(n)}catch{continue}let r=t.filter(e=>e.toLowerCase().endsWith(`.info`)).sort()[0];if(r!==void 0)return e(n,r)}return null}function _e(e=process.env){try{return R(e)||`(未找到)`}catch{}return`(未找到)`}var ve=/\.new\.accessToken$/i;function ye(t){let n=u();switch(process.platform){case`darwin`:return[e(n,`Library`,`Application Support`,`JetBrains`)];case`win32`:return[e(t.APPDATA||e(n,`AppData`,`Roaming`),`JetBrains`)];default:return[e(n,`.config`,`JetBrains`),e(n,`.local`,`share`,`JetBrains`)]}}function be(t){let n=[];for(let r of ye(t)){let t;try{t=o(r,{withFileTypes:!0})}catch{continue}for(let i of t){if(!i.isDirectory())continue;let t=e(r,i.name,`options`,`secret-storage.xml`);try{s(t).isFile()&&n.push(t)}catch{continue}}}return n}function xe(e){return String(e).replace(/&lt;/g,`<`).replace(/&gt;/g,`>`).replace(/&quot;/g,`"`).replace(/&apos;/g,`'`).replace(/&#(\d+);/g,(e,t)=>String.fromCharCode(Number(t))).replace(/&amp;/g,`&`)}function Se(e){let t=a(e,`utf8`),n=/<Entry\s+key="([^"]*)"\s+value="([^"]*)"\s*\/?>/g,r=[],i;for(;(i=n.exec(t))!==null;){let e=i[1]??``,t=i[2]??``;ve.test(e)&&r.push({key:e,value:t})}if(r.length===0)return null;r.sort((e,t)=>t.value.length-e.value.length);let o=r[0];return o===void 0?null:{key:o.key,session:JSON.parse(xe(o.value))}}var Ce=class{path;readonly=!1;constructor(e){this.path=e}get location(){return this.path}fingerprint(){return String(s(this.path).mtimeMs)}read(){return JSON.parse(a(this.path,`utf8`))}async write(e){let t=`${this.path}.tmp`;await f(t,JSON.stringify(e,null,2),`utf8`),await d(t,this.path)}},we=class{path;readonly=!0;#e=null;constructor(e){this.path=e,this.read()}get location(){return this.#e?`${this.path} :: ${this.#e}`:this.path}fingerprint(){let e=s(this.path);return`${String(e.mtimeMs)}:${String(e.size)}`}read(){let e=Se(this.path);if(!e)throw Error(`未在 ${this.path} 中找到 *.new.accessToken 凭据条目`);return this.#e=e.key,e.session}write(e){throw Error(`JetBrains secret-storage.xml 为只读来源,拒绝回写`)}};function Te(e,t=process.env){let n=()=>{for(let e of be(t))try{return new we(e)}catch{continue}return null};if(e===`jetbrains`){let e=n();if(e)return e}let r=R(t);return r?new Ce(r):n()}var Ee=`​`,De=`DoS,DDoS,exploit,credential testing,credential stuffing,supply chain compromise,supply-chain compromise,detection evasion,C2 frameworks,C2 framework,command and control,malicious purposes,malicious intent,mass targeting,brute force,brute-force,privilege escalation,reverse shell,remote code execution,SQL injection,XSS,CSRF,phishing,malware,ransomware,keylogger,rootkit,backdoor,botnet,zero-day,0day,vulnerability,vulnerabilities,red teaming,red-teaming,sandbox,sandboxing,sandboxed,unsandboxed,escalated privileges,escalated,escalation,destructive action,destructive command,destructive,attack,attacks,cybersecurity,security review,exploit development,hacking,penetration testing,penetration test,injection,weaponize,weaponized,harmful,dangerous,abuse,abusive,illegal,terrorist,terrorism,bomb,weapon,weapons,drug,drugs,narcotic,suicide,self-harm,murder,kill,violence,violent,Claude Code,Claude Opus,Claude Sonnet,Claude Haiku,Claude Fable,Anthropic,Co-Authored-By,noreply@anthropic.com`.split(`,`);function z(e){return String(e).replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}var Oe=new RegExp(De.slice().sort((e,t)=>t.length-e.length).map(z).join(`|`),`gi`),ke=[`# AGENTS.md instructions`,`<environment_context>`,`<permissions instructions>`,`<collaboration_mode>`,`<skills_instructions>`,`<system-reminder>`,`# claudeMd`],B=[`You are a coding agent running in the Codex CLI`,`Within this context, Codex refers to`,`# How you work`,`You are Claude Code`],Ae=[`<permissions instructions>`,`Filesystem sandboxing defines which files can be read or written.`,`## How to request escalation`],je=[`<skills_instructions>`,`### Available skills`,`### How to use skills`],Me=[[`<environment_context>`,`</environment_context>`,`Environment context is provided by the harness.`],[`<permissions instructions>`,`</permissions instructions>`,`Runtime permissions apply: filesystem access may be sandboxed, network may be restricted, and some commands may require user approval.`],[`<collaboration_mode>`,`</collaboration_mode>`,`Collaboration mode instructions are provided by the harness.`],[`<skills_instructions>`,`</skills_instructions>`,`Runtime skill metadata is available. Use relevant skills only when explicitly requested or clearly applicable.`],[`<plugins_instructions>`,`</plugins_instructions>`,`Runtime plugin metadata is available when relevant.`],[`<system-reminder>`,`</system-reminder>`,`Runtime reminder context is provided by the harness.`]],Ne=[`The following deferred tools are now available via ToolSearch.`,`Available agent types for the Agent tool:`,`The following sk​ills are available for use with the Sk​ill tool:`,`## MCP Server Instructions`],Pe=`Runtime tool, agent, skill, and MCP metadata is available separately.`,Fe=`You are a coding assistant in Codex CLI. Be precise, helpful, concise, and safe. Inspect the repository, use available tools when needed, follow repository instructions, and keep the user informed with concise progress updates.`;function Ie(e){return e.length<=1?e:e.charAt(0)+Ee+e.slice(1)}function V(e){return e&&String(e).replace(Oe,e=>Ie(e))}function H(e){return typeof e==`object`&&!!e&&e.type===`text`}function U(e){let t=typeof e==`string`?e:``;if(Array.isArray(e)){let n=[];for(let t of e)H(t)&&n.push(String(t.text||``));t=n.join(``)}return t}function W(e){let t=U(e);return ke.some(e=>t.includes(e))}var Le=/\n{3,}/g;function G(e,t){if(!t)return t;let n=t;for(let[e,t,r]of Me){let i=RegExp(`\\s*`+z(e)+`[\\s\\S]*?`+z(t)+`\\s*`,`g`);n=n.replace(i,`
5
-
6
- `+r+`
7
-
8
- `)}let r=Ne.filter(e=>n.includes(e)).map(e=>n.indexOf(e));if(r.length){let e=Math.min(...r.filter(e=>e>=0)),t=n.slice(0,e).replace(/\s+$/,``);n=t?t+`
9
-
10
- Runtime tool, agent, skill, and MCP metadata is available separately.`:Pe}if(e===`system`&&B.some(e=>n.includes(e))){let e=[],t=RegExp(`^[\\s\\S]*?(?=\\n# AGENTS\\.md spec|\\n## Responsiveness|\\n## Planning|\\n## Task execution|$)`).exec(n);if(t){let n=(t[0]??``).trim();n&&e.push(n)}for(let t of[`## Personality`,`# AGENTS.md spec`]){let r=RegExp(z(t)+`[\\s\\S]*?(?=\\n## |\\n# |$)`).exec(n);if(r){let t=(r[0]??``).trim();t&&e.push(t)}}n=e.length?e.join(`
11
-
12
- `):Fe}return e===`user`&&W(n)&&(n.includes(`# AGENTS.md instructions`)||t.includes(`<environment_context>`)||t.includes(`<skills_instructions>`))?`Repository instructions and durable user context are provided. Follow repository guidance while answering the user’s actual request.`:(n=n.replace(Le,`
13
-
14
- `).trim(),n)}function Re(e,t){let n=U(t);return n?e===`system`&&B.some(e=>n.includes(e))?n.includes(`You are Claude Code`)?`You are a coding assistant. Be precise, helpful, concise, and safe. Use available tools when needed, follow repository instructions, and keep the user informed.`:`You are a coding assistant in Codex CLI. Be precise, helpful, concise, and safe. Use available tools when needed, follow repository instructions, and keep the user informed.`:Ae.some(e=>n.includes(e))?`Runtime permissions apply: filesystem access may be sandboxed, network may be restricted, and some commands may require user approval.`:je.some(e=>n.includes(e))?`Runtime skill metadata is available. Use relevant skills only when explicitly requested or clearly applicable.`:e===`user`&&W(t)?`Repository instructions and environment context are provided. Follow repository guidance while answering the user’s actual request.`:null:null}function K(e,t=!1){if(Array.isArray(e))return e.map(e=>K(e,t));if(typeof e==`object`&&e){let n={};for(let[r,i]of Object.entries(e))if((r===`description`||r===`title`)&&typeof i==`string`){if(t)continue;n[r]=V(i)}else n[r]=K(i,t);return n}return e}function ze(e,t=[`system`],n={}){let{desensitizeHarnessUser:r=!1,compactHarness:i=!1}=n,a=Array.isArray(e)?e:[],o=[];for(let e of a){if(!e||typeof e!=`object`){o.push(e);continue}let n=e,a=n.role,s=typeof a==`string`&&t.includes(a);a===`user`&&r&&(s=W(n.content));let c={...n};if(s){let e=n.content,t=i?Re(a,e):null;if(t!==null)c.content=V(t);else if(typeof e==`string`)c.content=V(G(a,e));else if(Array.isArray(e)){let t=[];for(let n of e)if(H(n)){let e={...n};e.text=V(G(a,String(n.text||``))),t.push(e)}else t.push(n);c.content=t}}o.push(c)}return o}function Be(e,t={}){let{roles:n=[`system`],desensitizeHarnessUser:r=!1,desensitizeTools:i=!1,compactHarness:a=!1,stripToolMetadata:o=!1}=t,s=!1,c={...e};return e.messages&&(c.messages=ze(e.messages,n,{desensitizeHarnessUser:r,compactHarness:a}),s=!0),i&&e.tools&&(c.tools=K(e.tools,o),s=!0),s?c:e}var Ve=[[/\(you will usually use this for PRs\)/gi,`(you will typically use this for PRs)`],[/x-anthropic-/gi,`x-cc-`],[/You are Claude Code\s*,\s*Anthropic['’]s/gi,`You are Claude Code, from Anthropic's`]];function He(e){let t=e;for(let[e,n]of Ve)t=t.replace(e,n);return t}function Ue(e){let t=new WeakSet,n=0,r=e=>{if(typeof e==`string`)return He(e);if(!e||typeof e!=`object`||t.has(e))return e;t.add(e);let i=Array.isArray(e)?[]:{};for(let t of Object.keys(e)){let a=e[t],o=r(a);i[t]=o,o!==a&&(n+=1)}return i};return[r(e),n]}function We(e,t){return t.enabled?Be(e,{roles:[`system`,`developer`],desensitizeHarnessUser:!0,desensitizeTools:!0,compactHarness:t.forceCompact||!t.noCompact,stripToolMetadata:!0}):e}var Ge=`/billing/meter/get-user-resource-summary`,Ke=15e3,qe=`credits`;function q(e){if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`&&e.trim()!==``){let t=Number(e);if(Number.isFinite(t))return t}return null}function Je(e){if(!b(e))return null;let t=q(e.CycleTotalCapacity),n=q(e.CycleRemainCapacity);if(t===null||n===null)return null;let r=q(e.CycleUsedCapacity)??Math.max(0,t-n);return{packageCode:typeof e.PackageCode==`string`?e.PackageCode:``,total:t,remain:n,used:r}}function Ye(e){if(!b(e))throw Error(`上游未返回额度数据(响应缺少 data)`);let t=Array.isArray(e.Packages)?e.Packages:[],n=t.map(Je).filter(e=>e!==null);if(n.length===0)throw Error(`上游未返回有效资源包(Packages 为空或各包的容量字段不可解析)`);let r=n.reduce((e,t)=>e+t.total,0),i=n.reduce((e,t)=>e+t.remain,0),a=n.reduce((e,t)=>e+t.used,0),o=t.map(e=>b(e)?e.CapacityUnit:void 0).find(e=>typeof e==`string`&&e!==``);return{unit:typeof o==`string`?o:qe,total:r,remain:i,used:a,packages:n,subscriptionName:typeof e.SubscriptionPackageName==`string`?e.SubscriptionPackageName:``,isPaidUser:e.IsPaidUser===!0}}async function Xe(e,t){let n;try{n=await fetch(`${e}${Ge}`,{method:`POST`,headers:{...t,"Content-Type":`application/json;charset=UTF-8`},body:`{}`,signal:AbortSignal.timeout(Ke)})}catch(e){let t=e instanceof Error?e.message:String(e);throw new _(502,`额度查询网络失败:${t}`,y(`额度查询网络失败:${t}`,`upstream_error`))}if(!n.ok){let e=await n.text().then(e=>e.replace(/\s+/g,` `).trim().slice(0,200)).catch(()=>``);throw new _(502,`额度查询失败:HTTP ${String(n.status)}${e===``?``:` ${e}`}`,y(e===``?`upstream HTTP ${String(n.status)}`:e,`upstream_error`))}let r;try{r=await n.json()}catch{throw new _(502,`额度查询失败:响应不是 JSON`,y(`响应不是 JSON`,`upstream_error`))}if(!b(r)||r.code!==0){let e=b(r)&&typeof r.msg==`string`?r.msg:JSON.stringify(r);throw new _(502,`额度查询被拒绝:${e}`,y(e,`upstream_error`))}return Ye(r.data)}var Ze=class extends M{id=`codebuddy`;label=`CodeBuddy/WorkBuddy 订阅代理`;#e;#t=null;#n=null;constructor(e){super(e),this.#e=I()}async init(){try{let e=Te(this.options.credSource);return e===null?(this.#n=`未找到登录凭据,请先在桌面端登录 CodeBuddy/WorkBuddy`,{ok:!1,reason:this.#n}):(this.#t=new ue(e,{backend:this.#e}),{ok:!0})}catch(e){return this.#n=`加载登录态失败:${e instanceof Error?e.message:String(e)}`,{ok:!1,reason:this.#n}}}assertChatReady(){this.#r()}chatUrl(){return`${this.#e}/v2/chat/completions`}buildHeaders(e){return this.#r().getChatHeaders(e)}transformBody(e){let{desensitize:t,noCompact:n}=this.options,[r,i]=Ue(We(e,{enabled:t,noCompact:n}));return{body:r,changed:i}}async listModels(){return he()}async usage(){let e=await this.#r().getHeaders();return Xe(this.#e,e)}healthDetails(){let e={auth_file:_e(),upstream:this.#e};if(this.#t!==null)try{e.credential=this.#t.summary()}catch(t){e.credential_error=t instanceof Error?t.message:String(t)}else this.#n!==null&&(e.credential_error=this.#n);return e}#r(){if(this.#t!==null)return this.#t;let e=this.#n??`未找到登录凭据,请先在桌面端登录 CodeBuddy/WorkBuddy`;throw new _(503,e,y(e,`auth_error`))}},J={codebuddy:e=>new Ze(e)};function Y(){return Object.keys(J)}function Qe(e,t){let n=J[e];if(n===void 0)throw Error(`未知供应商 "${e}"(可用:${Y().join(`、`)})`);return n(t)}async function X(e,t,n,r){let i={method:`POST`,headers:t,body:JSON.stringify(n)};return r!==null&&(i.signal=AbortSignal.timeout(r)),fetch(e.chatUrl,i)}function $e(e){for(let t=e.length-1;t>=0;--t){let n=e[t];if(typeof n!=`object`||!n)continue;let r=n;if(r.role!==`user`)continue;let i=r.content??``;if(Array.isArray(i)){for(let e of i)if(typeof e==`object`&&e&&e.type===`text`)return String(e.text??``);return``}return String(i)}return``}async function*et(e){for(let t of e.toString(`utf8`).split(/\r?\n/))yield t}function tt(e,t,n,r,i=``){let a=(Date.now()-n)/1e3,o=i?`[${i}] `:``,s=r.choices[0]??{index:0,message:{},finish_reason:``},c=s.finish_reason,l=s.message,u=Array.isArray(l.tool_calls)?l.tool_calls:[],d=r.usage??{},f=c===`content-filter`?` ⚠️内容审核拦截`:``,p=u.map(e=>e.function?.name);e.logger.log(`${o}◀ RESPONSE ${t} | ${a.toFixed(1)}s | finish=${String(c)}${f}`+(p.length?` | tool_calls=${j(p)}`:``)+` | tokens=${d.total_tokens===void 0?`?`:String(d.total_tokens)}`),e.logger.enabled&&e.logger.log(`${o}── RESPONSE BODY ──\n${A(r)}`)}async function nt(e){let t=[],n=new Map,r=null,i=null,a=null;for await(let o of e){let e=String(o).trim();if(!e||!e.startsWith(`data:`))continue;let s=e.slice(5).trim();if(s===`[DONE]`)break;let c;try{c=JSON.parse(s)}catch{continue}r=c.model??r,c.usage&&(a=c.usage);for(let e of c.choices??[]){e.finish_reason&&(i=e.finish_reason);let r=e.delta??{};r.content&&t.push(r.content);for(let e of r.tool_calls??[]){let t=e.index===void 0||e.index===null?0:e.index,r=n.get(t);r===void 0&&(r={id:null,name:null,arguments:``},n.set(t,r)),e.id&&(r.id=e.id);let i=e.function??{};i.name&&(r.name=i.name),i.arguments&&(r.arguments+=i.arguments)}}}let o=null;n.size>0&&(o=[...n.entries()].sort((e,t)=>e[0]-t[0]).map(([,e])=>({id:e.id,type:`function`,function:{name:e.name,arguments:e.arguments}})),i??=`tool_calls`);let s={role:`assistant`,content:t.join(``)||null};return o&&(s.tool_calls=o),{id:`chatcmpl-${c(12).toString(`hex`)}`,object:`chat.completion`,created:Math.floor(Date.now()/1e3),model:r??`unknown`,choices:[{index:0,message:s,finish_reason:i??`stop`}],usage:a??{prompt_tokens:0,completion_tokens:0,total_tokens:0}}}function rt(e,t){try{return JSON.parse(e.toString(`utf8`))}catch{return{error:{message:e.toString(`utf8`).slice(0,500),type:`upstream_error`,code:t}}}}function Z(e,t){let n={error:{message:e.toString(`utf8`).slice(0,500),type:`upstream_error`,code:t}};return`data: ${JSON.stringify(n)}\n\n`}async function it(e,t,n,r,i=`?`,a=0,o=``){let s=Number(process.env.PROXY_RC_MAX_CHARS||8e3),l=t.dropReasoning,u=t.logger,d=null,f=[],p={},m=!1,h=0,g=0,_=0,v=``,y=null,b=[],x=o?`[${o}] `:``,S=()=>{if(!v)return;let t=y??{},n={id:t.id||`chatcmpl-${c(8).toString(`hex`)}`,object:t.object||`chat.completion.chunk`,created:t.created||Math.floor(Date.now()/1e3),model:t.model||i,choices:[{index:0,delta:{role:`assistant`,content:``,reasoning_content:v,function_call:null,refusal:``,tool_calls:[],extra_fields:null},logprobs:null,finish_reason:``}],usage:null};e.write(`data: ${JSON.stringify(n)}\n\n`),_+=1,v=``},C=t=>{if(t.startsWith(`data:`)){let n=t.slice(5).trim();if(n===`[DONE]`){S(),e.write(`${t}\n`);return}let r=null;try{r=JSON.parse(n)}catch{}if(r!==null){r.usage&&(p={...p,...r.usage}),y??=r;let t=!1;for(let e of r.choices??[]){e.finish_reason&&(d=e.finish_reason);let n=e.delta??{};n.reasoning_content?(g+=1,l?delete n.reasoning_content:(v+=n.reasoning_content,!n.content&&!(n.tool_calls??[]).length&&!n.function_call&&(t=!0))):n.reasoning_content===``&&(delete n.reasoning_content,h+=1);for(let e of n.tool_calls??[]){let t=e.function?.name;t&&f.push(t)}}t&&(r.choices??[]).length===1?v.length>=s&&S():(S(),e.write(`data: ${JSON.stringify(r)}\n`)),(n.includes(`content-filter`)||n.includes(`敏感`)||n.includes(`审核`))&&(m=!0);return}}e.write(`${t}\n`)};try{let a=await X(t,n,r,null);if(a.status!==200){let t=Buffer.from(await a.arrayBuffer());u.log(`${x}✗ HTTP ${String(a.status)} | ${i} | ${k(t.toString(`utf8`),200)}`),u.enabled&&u.log(`${x}── ERROR BODY ──\n${t.toString(`utf8`)}`),e.write(Z(t,a.status)),e.end();return}let o=Buffer.alloc(0);for await(let e of E(a.body))if(e&&e.length)for(u.enabled&&b.push(e),o=Buffer.concat([o,e]);;){let e=o.indexOf(`
15
- `);if(e<0)break;let t=o.subarray(0,e).toString(`utf8`).replace(/\r$/,``);o=o.subarray(e+1),C(t)}o.length&&C(o.toString(`utf8`)),S(),e.end()}catch(t){let n=t instanceof Error?t.message:String(t);u.log(`${x}✗ 网络错误 | ${i} | ${n}`),e.headersSent||e.writeHead(200,{"Content-Type":`text/event-stream`}),e.write(Z(Buffer.from(n),502)),e.end()}let w=a?(Date.now()-a)/1e3:0,T=m||d===`content-filter`?` ⚠️内容审核拦截`:``;u.log(`${x}◀ RESPONSE ${i} | ${w.toFixed(1)}s | stream finish=${String(d)}${T}`+(f.length?` | tool_calls=${j(f)}`:``)+` | tokens=${p.total_tokens===void 0?`?`:String(p.total_tokens)} | stripped_empty_rc=${String(h)} | rc_agg=${String(g)}→${String(_)}`+(l?` | reasoning=hidden`:``)),u.enabled&&u.log(`${x}── RESPONSE RAW SSE ──\n${Buffer.concat(b).toString(`utf8`)}`)}var at=[`model`,`messages`,`tools`,`tool_choice`,`temperature`,`max_tokens`,`max_completion_tokens`,`top_p`,`stream`,`stream_options`,`stop`,`presence_penalty`,`frequency_penalty`,`n`,`response_format`,`seed`,`user`,`reasoning_effort`,`verbosity`,`reasoning_summary`],ot=3e5,st=6e4;function ct(e){let t={...e,usageQuery:lt(e.provider)};return p((n,r)=>{gt(t,n,r).catch(t=>{e.logger.log(`[fatal] handler error: ${t instanceof Error&&t.stack?t.stack:String(t)}`);try{r.headersSent||r.writeHead(500,{"Content-Type":`application/json`}),r.end(JSON.stringify({detail:y(String(t),`internal_error`)}))}catch{}})})}function lt(e){let t=null;return async()=>{let n=Date.now();if(t!==null&&n-t.at<st)return{usage:t.usage,fetchedAt:t.at,cached:!0};let r=await e.usage();return r===null?null:(t={at:n,usage:r},{usage:r,fetchedAt:n,cached:!1})}}function ut(e){return async()=>{let t=await e.usage();return t===null?null:{usage:t,fetchedAt:Date.now(),cached:!1}}}function Q(e,t){let n=e.apiKey;if(!n)return;let r=t.headers.authorization,i=t.headers[`x-api-key`],a=``;if(r&&r.startsWith(`Bearer `)&&(a=r.slice(7).trim()),!a&&i&&(a=String(i)),a!==n)throw new _(401,`invalid api key`,y(`invalid api key`,`auth_error`))}function dt(e){let t=(...t)=>{for(let n of t){let t=e[n];if(t)return Array.isArray(t)?t[0]:t}};return{sessionId:t(`x-session-id`,`x-zcode-session-id`,`x-conversation-id`),messageId:t(`x-query-id`,`x-conversation-message-id`,`x-message-id`),requestId:t(`x-request-id`,`x-zcode-request-id`),traceId:t(`x-zcode-trace-id`,`x-trace-id`,`x-b3-traceid`)}}function ft(e,t){S(t,200,{status:`ok`,platform:process.platform,node:process.version.replace(/^v/,``),mode:`direct-proxy (native function calling)`,...e.provider.healthDetails()})}async function pt(e,t){let n=await(e.usageQuery??ut(e.provider))();if(n===null){S(t,501,{detail:y(`供应商 ${e.provider.id} 不支持额度查询`,`not_implemented`)});return}S(t,200,{status:`ok`,provider:e.provider.id,fetchedAt:n.fetchedAt,cached:n.cached,usage:n.usage})}async function mt(e,t,n){Q(e.options,t),S(n,200,{object:`list`,data:(await e.provider.listModels()).map(t=>({id:t,object:`model`,created:17e8,owned_by:e.provider.id}))})}async function ht(e,t,n){let{options:r,provider:i,logger:a}=e;Q(r,t),i.assertChatReady();let o=Date.now(),s=await ee(t,T()),l;try{l=te(s)}catch(e){return w(n,`bad json: ${e instanceof Error?e.message:String(e)}`)}let u=b(l)?l:{},d=Array.isArray(u.messages)?u.messages:[];if(d.length===0)return w(n,`messages is required`);let f=!!u.stream,p={};for(let e of at)e in u&&(p[e]=u[e]);`model`in p||(p.model=`auto`),p.stream=!0,`stream_options`in p||(p.stream_options={include_usage:!0}),Array.isArray(p.messages)&&(p.messages=p.messages.map(e=>b(e)&&e.role===`developer`?{...e,role:`system`}:e));let m=i.transformBody(p),h=m.body,g=u.model,_=typeof g==`string`&&g!==``?g:`auto`,v=(Array.isArray(u.tools)?u.tools:[]).filter(b).map(e=>b(e.function)?e.function.name:void 0),x=$e(d),E=c(4).toString(`hex`);a.log(`[${E}] ▶ REQUEST ${_} | stream=${String(f)} | msgs=${String(d.length)}`+(v.length?` | tools=${j(v)}`:``)+(m.changed?` | fingerprint_rewrites=${String(m.changed)}`:``)+(x?` | last_user=${ne(k(x,60))}`:``)),a.enabled&&a.log(`[${E}] ── REQUEST BODY (发往后端) ──\n${A(h)}`);let D=await i.buildHeaders({model:_,...dt(t.headers),prepareStartTime:o});a.log(`[${E}] ── 后端会话 ── conv=${String(D[`X-Conversation-Id`])} req=${String(D[`X-Request-Id`])}`);let O=Date.now(),M={chatUrl:i.chatUrl(),logger:a,dropReasoning:r.noReasoning};if(f){n.writeHead(200,{"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,"X-Accel-Buffering":`no`}),await it(n,M,D,h,_,O,E);return}let N,P;try{let e=await X(M,D,h,ot);N=e.status,P=Buffer.from(await e.arrayBuffer())}catch(e){let t=e instanceof Error?e.message:String(e);return a.log(`[${E}] ✗ 网络错误 | ${_} | ${t}`),C(n,502,y(`upstream error: ${t}`,`upstream_error`))}if(N!==200)return a.log(`[${E}] ✗ HTTP ${String(N)} | ${_} | ${k(P.toString(`utf8`),200)}`),a.enabled&&a.log(`[${E}] ── ERROR BODY ──\n${P.toString(`utf8`)}`),C(n,N,rt(P,N));let F=await nt(et(P));tt(M,_,O,F,E),S(n,200,F)}async function gt(e,t,n){let r=x(t.url??`/`),i=(t.method??`GET`).toUpperCase();!r.startsWith(`/v1/`)&&(r===`/chat/completions`||r===`/models`)&&(r=`/v1${r}`);try{if(i===`GET`&&r===`/health`){ft(e,n);return}if(i===`GET`&&r===`/usage`){await pt(e,n);return}if(i===`GET`&&r===`/v1/models`){await mt(e,t,n);return}if(i===`POST`&&r===`/v1/chat/completions`){await ht(e,t,n);return}S(n,404,{detail:y(`未找到:${i} ${r}`,`not_found`)})}catch(t){if(t instanceof _){e.logger.log(`✗ ${i} ${r} → ${String(t.status)} ${t.message}`),S(n,t.status,{detail:t.detail});return}e.logger.log(`[fatal] ${i} ${r}: ${t instanceof Error&&t.stack?t.stack:String(t)}`),S(n,500,{detail:y(t instanceof Error?t.message:String(t),`internal_error`)})}}function _t(e){m(`==== 预检 ====`),m(`平台 : ${process.platform}`),m(`Node : ${process.version}`),m(`上游 : ${e.chatUrl()}(直连,原生 function calling)`);let t=e.healthDetails(),n=t.auth_file;m(`登录文件 : ${typeof n==`string`&&n!==``?n:`(未找到)`}`);let r=t.credential;if(b(r)){let e=typeof r.nickname==`string`?r.nickname:``,t=r.enterpriseName;m(`账号 : ${typeof t==`string`&&t!==``?`${e} / ${t}`:e||`(未知)`}`),m(`token过期 : ${r.tokenExpired===!0?`是(将自动刷新)`:`否`}`)}else h(``),h(typeof t.credential_error==`string`?`[警告] ${t.credential_error}`:`[警告] 未找到登录凭据。请先在桌面端完成登录(CodeBuddy/WorkBuddy)。`);m(`================`)}async function $(e=process.argv.slice(2),t=process.env){let{options:n,help:r}=F(e,t);if(r)return process.stdout.write(re(Y())),null;let i=Qe(n.providerId,n),a=new O(n.logPath),o=await i.init();o.ok||h(`[cpa] ${o.reason??`初始化未完成`}`),n.skipCheck||_t(i),m(`[cpa] ✅ 监听 http://${n.host}:${String(n.port)}(${i.label})`),m(`[cpa] GET /v1/models`),m(`[cpa] POST /v1/chat/completions (原生 tools/tool_calls,支持流式)`),m(`[cpa] GET /health`),m(`[cpa] GET /usage (账号额度快照)`),n.apiKey&&m(`[cpa] 鉴权已启用(API key 已设置)`),a.enabled&&m(`[cpa] 日志 : ${n.logPath??``}`),n.desensitize&&m(`[cpa] 脱敏 : 已启用(${n.noCompact?`零宽脱敏 + 保留全文`:`零宽脱敏 + 压缩摘要`})`),n.noReasoning&&m(`[cpa] 思考 : 已隐藏(不透传 reasoning_content)`),m(`[cpa] 按 Ctrl+C 退出。`),a.log(`==== converter 启动 ====`);let s=ct({options:n,provider:i,logger:a});return await new Promise((e,t)=>{s.once(`error`,t),s.listen(n.port,n.host,()=>{s.off(`error`,t),e()})}),m(`[cpa] listening on ${n.host}:${String(n.port)}`),{server:s,provider:i,options:n}}var vt=process.argv[1];vt!==void 0&&import.meta.url===n(t(vt)).href&&$().catch(e=>{g(`[cpa] 启动失败:${e instanceof Error?e.message:String(e)}`),process.exitCode=1});export{$ as main};
@@ -1 +0,0 @@
1
- import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Q as s,Tt as c,V as l,Wt as u,Z as d,a as f,at as ee,bt as p,et as m,fn as h,ht as te,it as g,j as _,k as v,mt as y,nt as b,sn as ne,vt as x,w as S}from"./router-DI9ZLaCn.js";import{t as C}from"./useManagerApi-l9V9LoLa.js";import{t as w}from"./providers-BHK2eZZc.js";import{c as T,o as re,t as E,v as D,y as O}from"./format-DbT9vkcP.js";import{n as k,t as ie}from"./useQuickRangeFilter-Crb6MDvU.js";x();function ae(e){let{loadError:t,run:n}=O(e),r=c(null);function i(e){let t=async()=>{let i=await n(e);return i?r.value===t&&(r.value=null):r.value=t,i};return t}function a(e){n(r.value??e)}return{loadError:t,track:i,retry:a}}l(),x(),u();var oe={class:`flex-col-gap`},se={class:`kv-grid`},ce={class:`kv-label`},le={class:`kv-value`},ue=[`onClick`],de={class:`kv-item kv-span-2`},fe={class:`kv-value`},pe={key:1,class:`kv-unit`},me={class:`kv-item`},he={class:`kv-value`},ge={class:`kv-unit`},_e={class:`kv-item`},ve={class:`kv-value`},ye={class:`flex-between card-header-wrap`},be={class:`flex-gap-8`},xe={class:`usage-grid`},Se={class:`usage-cell`},Ce={class:`usage-num orange`},we={class:`usage-cell`},Te={class:`usage-num blue`},Ee={class:`usage-cell`},De={class:`usage-num green`},Oe={class:`usage-cell`},ke={class:`usage-num purple`},Ae={class:`usage-cell`},je={class:`usage-num purple`},Me={key:0,class:`usage-cell`},Ne={class:`usage-num gray`},Pe={key:0},Fe=[`onClick`],A=n({__name:`DashboardView`,setup(n){let l=w(),{copyWithToast:u}=D(),{loadError:x,track:O,retry:A}=ae(),Ie={local:`本机 API 地址`,lan:`局域网地址`,other:`API 地址`},j=c(null),M=c(!0),N=c(``),{rangeKey:P,dateRange:F,onRangeChange:Le}=ie(()=>I(),`today`),Re=()=>{P.value=``,I()},ze=i(()=>{let e=new Set;for(let t of l.suppliers)for(let n of t.models)e.add(n.modelName);if(j.value?.models)for(let t of j.value.models)e.add(t.model);return[...e].sort()}),Be=k(),I=O(async()=>{let e=Be();M.value=!0;try{let t=new URLSearchParams;N.value&&t.set(`model`,N.value),F.value?.length===2&&(t.set(`startDate`,F.value[0]),t.set(`endDate`,F.value[1]));let n=t.toString(),r=await f.get(`/api/usage${n?`?${n}`:``}`);if(!e())return;j.value=r}catch(t){if(!e())return;throw t}finally{e()&&(M.value=!1)}}),Ve=k(),L=O(async()=>{let e=Ve();try{await Promise.all([I(),l.loadProviders()])}catch(t){if(!e())return;throw t}finally{e()&&(M.value=!1)}}),He=()=>A(L),R=window.location.hostname,z=Number(window.location.port)||null,B=i(()=>E({protocol:window.location.protocol,hostname:R,port:z})),V=c(null),H=c(null),U=c(!1),W=c(!0),G=c(Date.now()),K=c(null),q=c([]),J=i(()=>K.value??z),Y=e=>E({protocol:`http:`,hostname:e,port:J.value}),X=i(()=>R===`127.0.0.1`||R===`::1`||R===`localhost`?`local`:q.value.includes(R)?`lan`:`other`),Z=i(()=>J.value?q.value.map(Y).filter(e=>e!==B.value):[]),Q=i(()=>{let e=J.value?Y(`127.0.0.1`):``;return e!==``&&e!==B.value?e:``}),Ue=i(()=>{let e=[];return X.value===`lan`?e.push({label:`局域网地址`,values:[B.value,...Z.value]}):(e.push({label:Ie[X.value],values:[B.value]}),Z.value.length>0&&e.push({label:`局域网地址`,values:Z.value})),Q.value!==``&&e.push({label:`本机 API 地址`,values:[Q.value]}),e.map((t,n)=>({...t,span2:e.length%2==1&&n===e.length-1}))}),We=async()=>{let[e,t]=await Promise.allSettled([C.processes(),f.get(`/api/status`)]);if(W.value=!1,e.status===`fulfilled`&&(V.value=e.value[0]??null),t.status===`rejected`){H.value=null,U.value=!0;return}let n=t.value?.masterKey;H.value=typeof n==`string`?n:null,U.value=typeof n!=`string`;let r=t.value?.listenPort;K.value=typeof r==`number`&&r>0?r:null;let i=t.value?.lanAddresses;q.value=Array.isArray(i)?i.filter(e=>typeof e==`string`):[],G.value=Date.now()},Ge=e=>{if(!e.startedAt)return`-`;let t=Math.max(0,Math.floor((G.value-e.startedAt)/1e3)),n=Math.floor(t/86400);t-=n*86400;let r=Math.floor(t/3600);t-=r*3600;let i=Math.floor(t/60);return t-=i*60,[n?`${n}天`:``,r?`${r}时`:``,i?`${i}分`:``,`${t}秒`].filter(Boolean).join(` `)},Ke=i(()=>U.value?`获取失败,请刷新重试`:H.value===null?`-`:`未设置(/v1 免鉴权)`),$;return d(()=>{L(),We(),$=window.setInterval(We,1e4)}),s(()=>window.clearInterval($)),(n,i)=>{let s=g(`el-button`),c=g(`el-alert`),l=g(`el-card`),d=g(`el-option`),f=g(`el-select`),C=g(`el-date-picker`),w=g(`el-table-column`),E=g(`el-table`),D=g(`el-empty`),O=ee(`loading`);return m(),r(`div`,oe,[o(x)?(m(),e(c,{key:0,title:o(x),type:`error`,"show-icon":``,closable:!1},{default:y(()=>[t(s,{size:`small`,onClick:He},{default:y(()=>[...i[4]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0),t(l,{shadow:`never`},{header:y(()=>[...i[5]||=[v(`span`,{class:`fw-600`},`服务信息`,-1)]]),default:y(()=>[te((m(),r(`div`,se,[(m(!0),r(S,null,b(Ue.value,e=>(m(),r(`div`,{key:e.label+e.values[0],class:ne([`kv-item`,{"kv-span-2":e.span2}])},[v(`div`,ce,h(e.label),1),v(`div`,le,[(m(!0),r(S,null,b(e.values,e=>(m(),r(`div`,{key:e},[v(`span`,{class:`copy-text`,onClick:t=>o(u)(e)},h(e),9,ue)]))),128))])],2))),128)),v(`div`,de,[i[6]||=v(`div`,{class:`kv-label`},`API 密钥`,-1),v(`div`,fe,[H.value?(m(),r(`span`,{key:0,class:`copy-text`,onClick:i[0]||=e=>o(u)(H.value)},h(H.value),1)):_(``,!0),H.value?(m(),r(`span`,pe,`(/v1 需 Bearer 认证)`)):(m(),r(S,{key:2},[a(h(Ke.value),1)],64))])]),v(`div`,me,[i[9]||=v(`div`,{class:`kv-label`},`运行状态`,-1),v(`div`,he,[V.value?(m(),r(S,{key:0},[i[7]||=v(`span`,{class:`status-dot running`},null,-1),i[8]||=a(`运行中 `,-1),v(`span`,ge,`PID `+h(V.value.pid??`-`),1)],64)):(m(),r(S,{key:1},[a(`-`)],64))])]),v(`div`,_e,[i[10]||=v(`div`,{class:`kv-label`},`运行时长`,-1),v(`div`,ve,h(V.value?Ge(V.value):`-`),1)])])),[[O,M.value||W.value]])]),_:1}),j.value?(m(),e(l,{key:1,shadow:`never`},{header:y(()=>[v(`div`,ye,[i[12]||=v(`span`,{class:`fw-600`},`用量统计`,-1),v(`div`,be,[t(f,{modelValue:N.value,"onUpdate:modelValue":i[1]||=e=>N.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`220px`},onChange:o(I)},{default:y(()=>[(m(!0),r(S,null,b(ze.value,t=>(m(),e(d,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`onChange`]),t(f,{modelValue:o(P),"onUpdate:modelValue":i[2]||=e=>p(P)?P.value=e:null,placeholder:`时间范围`,clearable:``,style:{width:`130px`},onChange:o(Le)},{default:y(()=>[t(d,{label:`今天`,value:`today`}),t(d,{label:`昨天`,value:`yesterday`}),t(d,{label:`前天`,value:`beforeYesterday`}),t(d,{label:`近三天`,value:`last3days`}),t(d,{label:`本周`,value:`week`}),t(d,{label:`本月`,value:`month`})]),_:1},8,[`modelValue`,`onChange`]),t(C,{modelValue:o(F),"onUpdate:modelValue":i[3]||=e=>p(F)?F.value=e:null,type:`daterange`,"range-separator":`至`,"start-placeholder":`开始日期`,"end-placeholder":`结束日期`,"value-format":`YYYY-MM-DD`,style:{width:`260px`},onChange:Re},null,8,[`modelValue`]),t(s,{loading:M.value,onClick:o(I)},{default:y(()=>[...i[11]||=[a(`刷新`,-1)]]),_:1},8,[`loading`,`onClick`])])])]),default:y(()=>[v(`div`,xe,[v(`div`,Se,[v(`div`,Ce,h(o(T)(j.value.total.total_tokens)),1),i[13]||=v(`div`,{class:`usage-label`},`总 Token`,-1)]),v(`div`,we,[v(`div`,Te,h(o(T)(j.value.total.input_tokens)),1),i[14]||=v(`div`,{class:`usage-label`},`输入 Token`,-1)]),v(`div`,Ee,[v(`div`,De,h(o(T)(j.value.total.output_tokens)),1),i[15]||=v(`div`,{class:`usage-label`},`输出 Token`,-1)]),v(`div`,Oe,[v(`div`,ke,h(o(T)(j.value.total.cache_read_tokens)),1),i[16]||=v(`div`,{class:`usage-label`},`缓存读取`,-1)]),v(`div`,Ae,[v(`div`,je,h(j.value.total.cache_rate==null?`-`:j.value.total.cache_rate+`%`),1),i[17]||=v(`div`,{class:`usage-label`},`缓存命中率`,-1)]),j.value.logStorageMB==null?_(``,!0):(m(),r(`div`,Me,[v(`div`,Ne,h(j.value.logStorageMB),1),i[18]||=v(`div`,{class:`usage-label`},`数据目录占用 (MB)`,-1)]))]),j.value.models?.length?(m(),r(`div`,Pe,[i[19]||=v(`div`,{class:`section-title`},`模型用量`,-1),t(E,{data:j.value.models,stripe:``,class:`full-width`},{default:y(()=>[t(w,{prop:`model`,label:`模型`,"min-width":`200`},{default:y(({row:e})=>[v(`span`,{class:`copy-text`,onClick:t=>o(u)(e.model)},h(e.model),9,Fe)]),_:1}),t(w,{label:`调用次数`,width:`90`,align:`center`},{default:y(({row:e})=>[a(h(e.calls),1)]),_:1}),t(w,{label:`平均耗时`,width:`110`,align:`center`},{default:y(({row:e})=>[a(h(o(re)(e.avg_duration)),1)]),_:1}),t(w,{label:`总 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(T)(e.total_tokens)),1)]),_:1}),t(w,{label:`输入 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(T)(e.input_tokens)),1)]),_:1}),t(w,{label:`输出 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(T)(e.output_tokens)),1)]),_:1}),t(w,{label:`缓存读取`,width:`130`,align:`center`},{default:y(({row:e})=>[a(h(o(T)(e.cache_read_tokens)),1)]),_:1}),t(w,{label:`缓存命中率`,width:`110`,align:`center`},{default:y(({row:e})=>[a(h(e.cache_rate==null?`-`:e.cache_rate+`%`),1)]),_:1})]),_:1},8,[`data`])])):(m(),e(D,{key:1,description:`暂无调用记录`,"image-size":60}))]),_:1})):_(``,!0)])}}});export{A as default};
@@ -1 +0,0 @@
1
- .mt-8[data-v-ea1efda8]{margin-top:8px}.mt-12[data-v-ea1efda8]{margin-top:12px}.check-body[data-v-ea1efda8]{min-height:80px}.alert-hint[data-v-ea1efda8]{margin-top:4px;font-size:12px;line-height:1.6}.alert-hint code[data-v-ea1efda8]{background:var(--el-fill-color-light);border-radius:4px;padding:1px 6px;font-size:12px}.version-row[data-v-ea1efda8]{align-items:center;gap:8px;margin-bottom:8px;display:flex}.version-label[data-v-ea1efda8]{color:var(--el-text-color-secondary);font-size:13px}.muted-sm[data-v-ea1efda8]{color:var(--el-text-color-secondary);margin-top:8px;font-size:12px}.user-chip[data-v-26778c58]{cursor:pointer;border-radius:999px;outline:none;align-items:center;gap:8px;padding:4px 8px 4px 4px;transition:background .15s;display:flex}.user-chip[data-v-26778c58]:hover{background:var(--el-fill-color-light)}.user-avatar[data-v-26778c58]{color:#fff;background:linear-gradient(135deg,#4f8df9 0%,#2563eb 100%);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:28px;height:28px;font-size:13px;font-weight:600;display:inline-flex}.user-name[data-v-26778c58]{color:var(--el-text-color-primary);text-overflow:ellipsis;white-space:nowrap;max-width:120px;font-size:13px;overflow:hidden}.user-chip .el-icon--right[data-v-26778c58]{color:var(--el-text-color-secondary);font-size:12px}
@@ -1 +0,0 @@
1
- import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Tt as s,V as c,Wt as l,Z as u,at as d,et as f,fn as p,ht as m,i as h,it as g,j as _,k as v,l as y,lt as b,mt as x,n as S,o as C,u as w,vt as T,w as E}from"./router-DI9ZLaCn.js";import{m as D}from"./message-C1fkA9sE.js";import{n as O,t as k}from"./index-BKnCp9qM.js";import{n as A,t as j}from"./useManagerApi-l9V9LoLa.js";import{t as M}from"./useToast-PFDoTWpf.js";import{n as N,t as P}from"./version-DegxwpkG.js";c(),l(),T();var F={class:`check-body`},I={class:`version-row`},L={class:`version-row`},R={class:`muted-sm`},z=k(n({__name:`UpdateCheckDialog`,props:{modelValue:{type:Boolean,default:!1},modelModifiers:{}},emits:[`update:modelValue`],setup(n){let{toast:i}=M(),c=b(n,`modelValue`),l=s(!1),u=s(!1),h=s(null),y=s(null),S=s(null),C=s(null),w=null,T=()=>w?.abort(),D=e=>new Date(e).toLocaleString(),k=e=>`https://www.npmjs.com/package/ezllm/v/${e}`,z=async()=>{y.value=null,S.value=null,C.value=null,l.value=!0;try{let e=await j.update();if(h.value=e,!e.supported)return;y.value=await j.checkUpdate()}catch(e){S.value=e.message||`检查更新失败`}finally{l.value=!1}},B=async()=>{if(!y.value)return;let e=y.value.latestVersion;try{await O.confirm(`确定更新到 ${e}?服务会自动重启并在启动时安装新版本:重启期间管理台短暂不可访问(预计 1~3 分钟),更新完成后自动恢复。`,`更新确认`,{confirmButtonText:`立即更新`,cancelButtonText:`取消`,type:`warning`})}catch{return}u.value=!0;let t=new AbortController;w=t;try{let e=await j.update(),n=await j.applyUpdate();if(!n.updated){C.value=`已是最新版本 ${n.toVersion}`,y.value={hasUpdate:!1,currentVersion:n.toVersion,latestVersion:n.toVersion,checkedAt:Date.now()};return}C.value=`正在重启服务并安装 ${n.toVersion}(预计 1~3 分钟):重启期间管理台短暂不可访问,完成后这里会自动显示结果。`;let r=await A({targetVersion:n.toVersion,sinceAppliedAt:e.lastApply?.appliedAt??null,signal:t.signal});if(t.signal.aborted)return;r&&!r.error?(i(`已更新到 ${r.toVersion}`,`success`),C.value=`已更新 ${r.fromVersion} → ${r.toVersion},服务已在新版本上运行。`,y.value={hasUpdate:!1,currentVersion:r.toVersion,latestVersion:r.toVersion,checkedAt:Date.now()}):r?.error?(i(`更新失败:${r.error}`,`error`),C.value=N(r.error)):C.value=`更新仍在进行(安装耗时较长):稍后刷新页面查看最新状态。`}catch(e){i(e.message||`更新失败`,`error`)}finally{u.value=!1,w===t&&(w=null)}};return(n,i)=>{let s=g(`el-alert`),b=g(`el-tag`),w=g(`el-link`),O=g(`el-button`),A=g(`el-dialog`),j=d(`loading`);return f(),e(A,{modelValue:c.value,"onUpdate:modelValue":i[2]||=e=>c.value=e,title:`检查更新`,width:`420px`,"close-on-click-modal":!u.value,onOpen:z,onClose:T},{footer:x(()=>[y.value?.hasUpdate?(f(),e(O,{key:0,type:`primary`,loading:u.value,onClick:B},{default:x(()=>[a(p(u.value?`更新中...`:`立即更新`),1)]),_:1},8,[`loading`])):_(``,!0),t(O,{onClick:i[1]||=e=>c.value=!1},{default:x(()=>[...i[11]||=[a(`关闭`,-1)]]),_:1})]),default:x(()=>[m((f(),r(`div`,F,[h.value&&!h.value.supported?(f(),e(s,{key:0,title:`当前为源码运行模式,更新功能不可用`,type:`info`,"show-icon":``,closable:!1},{default:x(()=>[...i[3]||=[v(`div`,{class:`alert-hint`},[a(` 仅 npm 全局安装的包支持自动更新。本地开发用仓库里的 `),v(`code`,null,`pnpm upgrade:local`),a(` 更新运行中的服务。 `)],-1)]]),_:1})):y.value?(f(),r(E,{key:1},[v(`div`,I,[i[5]||=v(`span`,{class:`version-label`},`当前版本`,-1),t(b,{size:`small`},{default:x(()=>[a(p(y.value.currentVersion),1)]),_:1}),o(P)(y.value.currentVersion)?(f(),e(b,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:x(()=>[...i[4]||=[a(`本地构建`,-1)]]),_:1})):_(``,!0)]),v(`div`,L,[i[6]||=v(`span`,{class:`version-label`},`最新版本`,-1),t(b,{type:y.value.hasUpdate?`warning`:`success`,size:`small`,"disable-transitions":``},{default:x(()=>[a(p(y.value.latestVersion),1)]),_:1},8,[`type`])]),t(s,{title:y.value.hasUpdate?`发现新版本 ${y.value.latestVersion}(当前 ${y.value.currentVersion})`:`已是最新版本 ${y.value.currentVersion}`,type:y.value.hasUpdate?`warning`:`success`,"show-icon":``,closable:!1,class:`mt-12`},null,8,[`title`,`type`]),v(`div`,R,[a(` 检查时间:`+p(D(y.value.checkedAt))+` `,1),y.value.hasUpdate?(f(),r(E,{key:0},[i[8]||=a(` · `,-1),t(w,{type:`primary`,href:k(y.value.latestVersion),target:`_blank`},{default:x(()=>[...i[7]||=[a(`在 npm 查看该版本`,-1)]]),_:1},8,[`href`])],64)):_(``,!0)])],64)):!l.value&&S.value?(f(),e(s,{key:2,title:S.value,type:`error`,"show-icon":``,closable:!1},{default:x(()=>[i[10]||=v(`div`,{class:`alert-hint`},` 检查需访问 npm 源,可能是网络不可达或版本号解析失败;稍后重试即可。 `,-1),t(O,{size:`small`,class:`mt-8`,onClick:z},{default:x(()=>[...i[9]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0)])),[[j,l.value]]),C.value?(f(),e(s,{key:0,title:C.value,type:`info`,"show-icon":``,class:`mt-12`,onClose:i[0]||=e=>C.value=null},null,8,[`title`])):_(``,!0)]),_:1},8,[`modelValue`,`close-on-click-modal`])}}}),[[`__scopeId`,`data-v-ea1efda8`]]);c(),l(),T();var B={class:`layout`},V=[`title`],H={key:0,class:`header-version-tag`},U={class:`header-nav`},W={class:`header-actions`},G={class:`user-chip`},K={class:`user-avatar`},q={class:`user-name`},J={class:`main`},Y={class:`page`},X=k(n({__name:`LayoutView`,setup(n){let c=y(),l=w(),d=s(!1);u(()=>{S()});let m=i(()=>h.value?.version||``),b=i(()=>P(h.value?.version)),T=i(()=>b.value?`本地构建版本(upgrade:local 产物)`:`当前运行版本`),E=i(()=>h.value?.authRequired!==!1),O=i(()=>{if(!E.value)return`免登录`;let e=localStorage.getItem(`webui_token`)||``;try{return atob(e).split(`:`)[0]||`用户`}catch{return`用户`}}),k=i(()=>{let e=c.path;return e===`/`?`/`:e.startsWith(`/providers`)?`/providers`:e.startsWith(`/service-status`)?`/service-status`:e.startsWith(`/managed-services`)?`/managed-services`:e.startsWith(`/settings`)?`/settings`:e.startsWith(`/logs`)?`/logs`:`/`}),A=e=>{e===`logout`&&(C(),l.push(`/login`)),e===`check-update`&&(d.value=!0)};return(n,i)=>{let s=g(`el-menu-item`),c=g(`el-menu`),l=g(`el-icon`),u=g(`el-dropdown-item`),h=g(`el-dropdown-menu`),y=g(`el-dropdown`),S=g(`el-header`),C=g(`router-view`);return f(),r(`div`,B,[t(S,{class:`header`},{default:x(()=>[i[9]||=v(`div`,{class:`brand`},[v(`span`,{class:`brand-mark`},`EZ`),v(`h1`,null,`LLM`)],-1),m.value?(f(),r(`span`,{key:0,class:`header-version`,title:T.value},[a(` v`+p(m.value),1),b.value?(f(),r(`span`,H,`本地构建`)):_(``,!0)],8,V)):_(``,!0),v(`nav`,U,[t(c,{mode:`horizontal`,"default-active":k.value,ellipsis:!1,router:``,class:`header-menu`},{default:x(()=>[t(s,{index:`/`},{default:x(()=>[...i[1]||=[a(`首页`,-1)]]),_:1}),t(s,{index:`/providers`},{default:x(()=>[...i[2]||=[a(`供应商管理`,-1)]]),_:1}),t(s,{index:`/service-status`},{default:x(()=>[...i[3]||=[a(`服务状态`,-1)]]),_:1}),t(s,{index:`/managed-services`},{default:x(()=>[...i[4]||=[a(`托管服务`,-1)]]),_:1}),t(s,{index:`/logs`},{default:x(()=>[...i[5]||=[a(`日志`,-1)]]),_:1}),t(s,{index:`/settings`},{default:x(()=>[...i[6]||=[a(`设置`,-1)]]),_:1})]),_:1},8,[`default-active`])]),v(`div`,W,[t(y,{trigger:`click`,onCommand:A,class:`ml-12`},{dropdown:x(()=>[t(h,null,{default:x(()=>[t(u,{command:`check-update`},{default:x(()=>[...i[7]||=[a(`检查更新`,-1)]]),_:1}),E.value?(f(),e(u,{key:0,command:`logout`,divided:``},{default:x(()=>[...i[8]||=[a(`退出`,-1)]]),_:1})):_(``,!0)]),_:1})]),default:x(()=>[v(`div`,G,[v(`span`,K,p(O.value.charAt(0).toUpperCase()),1),v(`span`,q,p(O.value),1),t(l,{class:`el-icon--right`},{default:x(()=>[t(o(D))]),_:1})])]),_:1})])]),_:1}),v(`main`,J,[v(`div`,Y,[t(C)])]),t(z,{modelValue:d.value,"onUpdate:modelValue":i[0]||=e=>d.value=e},null,8,[`modelValue`])])}}}),[[`__scopeId`,`data-v-26778c58`]]);export{X as default};
@@ -1,5 +0,0 @@
1
- import{A as e,Ct as t,F as n,I as r,M as i,O as a,P as o,Pt as s,S as c,Tt as l,V as u,Wt as d,Z as f,a as p,at as ee,bt as m,et as h,fn as g,ft as _,ht as v,it as y,j as b,k as x,m as S,mt as C,nt as w,vt as T,w as E,x as D,xt as O}from"./router-DI9ZLaCn.js";import{R as k,S as te}from"./message-C1fkA9sE.js";import{n as A,t as j}from"./index-BKnCp9qM.js";import{t as M}from"./providers-BHK2eZZc.js";import{_ as N,a as P,c as F,d as I,f as L,g as R,i as ne,l as z,n as re,o as ie,r as B,u as V,v as H,y as ae}from"./format-DbT9vkcP.js";import{t as oe}from"./useToast-PFDoTWpf.js";import{n as se,t as ce}from"./useQuickRangeFilter-Crb6MDvU.js";u(),T(),d();var U={class:`detail-content`},le={key:0,class:`ip-link`},ue={class:`ip-pop`},W={class:`ip-pop-row`},de={key:0,class:`ip-pop-row`},G={key:1,class:`ip-pop-error`},K={key:2},q=[`href`],fe={key:1},pe={key:1},me={class:`error-text`},J={class:`pane-bar`},he={class:`json-block`},ge={class:`pane-bar`},_e={class:`json-block`},Y={class:`pane-bar`},ve={class:`json-block`},ye={class:`pane-bar`},X={class:`json-block`},be={class:`pane-bar`},Z={class:`json-block`},Q={class:`pane-bar`},xe={class:`json-block`},$={class:`pane-bar`},Se={class:`json-block`},Ce={class:`pane-bar`},we={class:`json-block`},Te=j(r({__name:`LogDetailDialog`,setup(t,{expose:r}){let{copyWithToast:c}=H(),{loadError:u,run:d}=ae(),f=l(!1),m=l(null),_=l(!1),S=l(`info`),w=l(!1),T=l(null),D=se(),k=e=>{T.value=e,f.value=!0,m.value=null,S.value=`info`;let t=D();_.value=!0,d(async()=>{try{let n=`?id=${String(e.id)}`,r=await p.get(`/api/logs/detail`+n);if(!t())return;if(r&&r.detail){let e={...r.detail,...r.meta};e.response&&=O(e.response),e.request&&=O(e.request),m.value=e}else m.value=r}catch(e){if(!t())return;throw e}finally{t()&&(_.value=!1)}})},te=()=>{T.value&&k(T.value)};r({open:k});let A=a(()=>z(m.value?.response?.inbound_request)),j=a(()=>z(m.value?.response?.upstream_request)),M=a(()=>I(m.value?.response?.upstream_response_text)),P=a(()=>(m.value?.response?.upstream_stream_frames||[]).join(`
2
-
3
- `)),L=a(()=>z(m.value?.response?.client_response)),R=a(()=>(m.value?.response?.client_stream_frames||[]).join(`
4
-
5
- `)),ne=a(()=>z(m.value?.request)),B=a(()=>z(m.value?.response)),oe=async e=>{if(!(e._ipInfo||e._ipInfoError)){w.value=!0;try{let t=await p.get(`/api/logs/ipinfo?ip=${encodeURIComponent(e.ip)}`);t.error?e._ipInfoError=t.error:e._ipInfo=t}catch{e._ipInfoError=`查询失败`}finally{w.value=!1}}},ce=e=>[e.country,e.region,e.city].filter(Boolean).join(` · `)||`-`;return(t,r)=>{let a=y(`el-button`),l=y(`el-alert`),d=y(`el-descriptions-item`),p=y(`el-tag`),T=y(`el-divider`),D=y(`el-popover`),O=y(`el-descriptions`),k=y(`el-tab-pane`),I=y(`el-tabs`),z=y(`el-dialog`),H=ee(`loading`);return h(),e(z,{modelValue:f.value,"onUpdate:modelValue":r[11]||=e=>f.value=e,title:`日志详情`,width:`80%`,top:`5vh`,"destroy-on-close":``},{default:C(()=>[s(u)?(h(),e(l,{key:0,title:s(u),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:C(()=>[n(a,{size:`small`,onClick:te},{default:C(()=>[...r[12]||=[o(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):b(``,!0),v((h(),i(`div`,U,[m.value?(h(),e(I,{key:0,modelValue:S.value,"onUpdate:modelValue":r[10]||=e=>S.value=e},{default:C(()=>[n(k,{lazy:``,label:`基本信息`,name:`info`},{default:C(()=>[n(O,{column:2,border:``},{default:C(()=>[n(d,{label:`时间`},{default:C(()=>[o(g(s(V)(m.value.time)),1)]),_:1}),n(d,{label:`模型`},{default:C(()=>[o(g(m.value.model),1)]),_:1}),n(d,{label:`方法`},{default:C(()=>[o(g(m.value.method),1)]),_:1}),n(d,{label:`路径`},{default:C(()=>[o(g(m.value.path),1)]),_:1}),n(d,{label:`状态码`},{default:C(()=>[o(g(m.value.status),1)]),_:1}),n(d,{label:`流式`},{default:C(()=>[n(p,{type:m.value.stream?`warning`:`info`},{default:C(()=>[o(g(m.value.stream?`是`:`否`),1)]),_:1},8,[`type`])]),_:1}),n(d,{label:`IP`},{default:C(()=>[m.value.ip?(h(),i(`span`,le,[n(D,{placement:`right`,width:`240`,trigger:`click`,onShow:r[0]||=e=>oe(m.value)},{reference:C(()=>[x(`span`,null,g(m.value.ip),1)]),default:C(()=>[v((h(),i(`div`,ue,[m.value._ipInfo?(h(),i(E,{key:0},[x(`div`,W,[r[13]||=x(`span`,{class:`ip-pop-label`},`归属地`,-1),x(`span`,null,g(ce(m.value._ipInfo)),1)]),m.value._ipInfo.isp?(h(),i(`div`,de,[r[14]||=x(`span`,{class:`ip-pop-label`},`运营商`,-1),x(`span`,null,g(m.value._ipInfo.isp),1)])):b(``,!0)],64)):m.value._ipInfoError?(h(),i(`div`,G,g(m.value._ipInfoError),1)):(h(),i(`span`,K,`查询中...`)),n(T,{style:{margin:`8px 0`}}),x(`a`,{class:`ip-pop-link`,href:`https://m.ip138.com/iplookup.php?ip=${encodeURIComponent(m.value.ip)}`,target:`_blank`},`在 ip138 查看`,8,q)])),[[H,w.value]])]),_:1})])):(h(),i(`span`,fe,`-`))]),_:1}),n(d,{label:`Session`},{default:C(()=>[o(g(m.value.session_id||`-`),1)]),_:1}),n(d,{label:`ID`},{default:C(()=>[m.value._id==null?(h(),i(`span`,pe,`-`)):(h(),i(`span`,{key:0,class:`request-id`,title:`点击复制(日志 id 同时是响应头 x-request-id)`,onClick:r[1]||=e=>s(c)(String(m.value._id))},g(m.value._id),1))]),_:1}),n(d,{label:`输入 Token(含缓存读取)`},{default:C(()=>[o(g(s(F)(m.value.input_tokens??0)),1)]),_:1}),n(d,{label:`输出 Token`},{default:C(()=>[o(g(s(F)(m.value.output_tokens??0)),1)]),_:1}),n(d,{label:`缓存读取`},{default:C(()=>[o(g(s(F)(m.value.cache_read_tokens??0)),1)]),_:1}),n(d,{label:`请求耗时`},{default:C(()=>[o(g(s(ie)(m.value.duration)),1)]),_:1}),n(d,{label:`缓存命中率`},{default:C(()=>[o(g(s(re)(m.value)),1)]),_:1}),m.value.error?(h(),e(d,{key:0,label:`错误`,span:2},{default:C(()=>[x(`span`,me,g(m.value.error),1)]),_:1})):b(``,!0)]),_:1}),m.value.response?.truncated?(h(),e(l,{key:0,class:`mt-16`,type:`warning`,closable:!1,title:`内容超过单请求捕获上限,已截断`})):b(``,!0)]),_:1}),m.value.response?._capture?(h(),i(E,{key:0},[n(k,{lazy:``,label:`客户端请求`,name:`inbound`},{default:C(()=>[x(`div`,J,[n(a,{size:`small`,class:`copy-btn`,onClick:r[2]||=e=>s(c)(A.value)},{default:C(()=>[...r[15]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,he,g(s(N)(A.value)),1)]),_:1}),n(k,{lazy:``,label:`转发上游的请求`,name:`upstreamReq`},{default:C(()=>[x(`div`,ge,[n(a,{size:`small`,class:`copy-btn`,onClick:r[3]||=e=>s(c)(j.value)},{default:C(()=>[...r[16]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,_e,g(s(N)(j.value)),1)]),_:1}),m.value.response.upstream_response_text?(h(),e(k,{key:0,lazy:``,label:`上游响应(原始)`,name:`upstreamRes`},{default:C(()=>[x(`div`,Y,[n(a,{size:`small`,class:`copy-btn`,onClick:r[4]||=e=>s(c)(m.value.response.upstream_response_text)},{default:C(()=>[...r[17]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,ve,g(s(N)(M.value)),1)]),_:1})):m.value.response.upstream_stream_frames?.length?(h(),e(k,{key:1,lazy:``,label:`上游响应(原始流,${m.value.response.upstream_stream_frames.length} 帧)`,name:`upstreamStream`},{default:C(()=>[x(`div`,ye,[n(a,{size:`small`,class:`copy-btn`,onClick:r[5]||=e=>s(c)(P.value)},{default:C(()=>[...r[18]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,X,g(s(N)(P.value)),1)]),_:1},8,[`label`])):b(``,!0),m.value.response.client_response!==void 0&&m.value.response.client_response!==null?(h(),e(k,{key:2,lazy:``,label:`回写客户端(转换后)`,name:`clientRes`},{default:C(()=>[x(`div`,be,[n(a,{size:`small`,class:`copy-btn`,onClick:r[6]||=e=>s(c)(L.value)},{default:C(()=>[...r[19]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,Z,g(s(N)(L.value)),1)]),_:1})):m.value.response.client_stream_frames?.length?(h(),e(k,{key:3,lazy:``,label:`回写客户端(${m.value.response.client_stream_frames.length} 帧)`,name:`clientStream`},{default:C(()=>[x(`div`,Q,[n(a,{size:`small`,class:`copy-btn`,onClick:r[7]||=e=>s(c)(R.value)},{default:C(()=>[...r[20]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,xe,g(s(N)(R.value)),1)]),_:1},8,[`label`])):b(``,!0)],64)):(h(),i(E,{key:1},[n(k,{lazy:``,label:`请求体`,name:`request`},{default:C(()=>[x(`div`,$,[n(a,{size:`small`,class:`copy-btn`,onClick:r[8]||=e=>s(c)(ne.value)},{default:C(()=>[...r[21]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,Se,g(s(N)(ne.value)),1)]),_:1}),n(k,{lazy:``,label:`响应体`,name:`response`},{default:C(()=>[x(`div`,Ce,[n(a,{size:`small`,class:`copy-btn`,onClick:r[9]||=e=>s(c)(B.value)},{default:C(()=>[...r[22]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,we,g(s(N)(B.value)),1)]),_:1})],64))]),_:1},8,[`modelValue`])):b(``,!0)])),[[H,_.value]])]),_:1},8,[`modelValue`])}}}),[[`__scopeId`,`data-v-9c192d20`]]);u(),T(),d(),S();var Ee={class:`session-table`},De={class:`group-detail`},Oe=[`title`],ke={key:0,class:`detail-error`},Ae={class:`detail-footer`},je={class:`detail-count`},Me=[`title`,`onClick`],Ne=[`title`],Pe=[`title`],Fe=50,Ie=j(r({__name:`SessionGroupTable`,props:{groups:{},noSession:{},loading:{type:Boolean},filterParams:{}},emits:[`open-detail`],setup(r,{emit:u}){let d=r,f=u,{copyWithToast:m}=H(),S=a(()=>d.noSession?[...d.groups,d.noSession]:d.groups),w=e=>e.session_id||`__no_session__`,T=l(null),E=t(new Map),D={loading:!1,items:[],total:0,nextPage:1,error:null},O=e=>E.get(w(e))??D,k=async(e,t)=>{let n=(e=>(E.has(e)||E.set(e,{loading:!1,items:[],total:0,nextPage:1,error:null}),E.get(e)))(w(e));if(!n.loading){n.loading=!0,n.error=null;try{let r={...d.filterParams,sort:`time`,order:`desc`,page:String(t),pageSize:String(Fe)};e.session_id?r.sessionId=e.session_id:r.noSession=`1`;let i=await p.get(`/api/logs?`+new URLSearchParams(r).toString()),a=i.items||[];n.items=t===1?a:[...n.items,...a],n.total=i.total||0,n.nextPage=t+1}catch(e){n.error=e?.message||`加载失败`}finally{n.loading=!1}}},te=(e,t)=>{t.some(t=>w(t)===w(e))&&O(e).items.length===0&&k(e,1)},A=e=>{let t=O(e);t.loading||t.items.length>=t.total||k(e,t.nextPage)},j=e=>{T.value?.toggleRowExpansion(e)};return _(()=>S.value.map(w),e=>{let t=new Set(e);for(let e of[...E.keys()])t.has(e)||E.delete(e)}),(t,a)=>{let l=y(`el-table-column`),u=y(`el-tag`),d=y(`el-button`),p=y(`el-table`),_=y(`el-empty`),E=ee(`loading`);return h(),i(`div`,Ee,[S.value.length>0||r.loading?v((h(),e(p,{key:0,ref_key:`tableRef`,ref:T,data:S.value,height:`100%`,"row-key":w,stripe:``,onExpandChange:te,onRowClick:j},{default:C(()=>[n(l,{type:`expand`},{default:C(({row:t})=>[x(`div`,De,[v((h(),e(p,{data:O(t).items,size:`small`,stripe:``},{default:C(()=>[n(l,{label:`时间`,width:`165`},{default:C(({row:e})=>[o(g(s(V)(e.time)),1)]),_:1}),n(l,{prop:`model`,label:`模型`,"min-width":`150`}),n(l,{label:`客户端`,"min-width":`130`},{default:C(({row:e})=>[x(`span`,{title:e.user_agent||``},g(s(B)(e)),9,Oe)]),_:1}),n(l,{label:`状态`,width:`80`,align:`center`},{default:C(({row:e})=>[n(u,{size:`small`,type:e.status>=400?`danger`:e.status>=300?`warning`:`success`},{default:C(()=>[o(g(e.status),1)]),_:2},1032,[`type`])]),_:1}),n(l,{label:`输入`,width:`100`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.input_tokens??0)),1)]),_:1}),n(l,{label:`输出`,width:`100`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.output_tokens??0)),1)]),_:1}),n(l,{label:`缓存读取`,width:`100`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.cache_read_tokens??0)),1)]),_:1}),n(l,{label:`缓存命中率`,width:`105`,align:`center`},{default:C(({row:e})=>[o(g(s(re)(e)),1)]),_:1}),n(l,{label:`请求耗时`,width:`90`,align:`center`},{default:C(({row:e})=>[o(g(s(ie)(e.duration)),1)]),_:1}),n(l,{label:`详情`,width:`70`,align:`center`},{default:C(({row:e})=>[n(d,{link:``,type:`primary`,onClick:t=>f(`open-detail`,e)},{default:C(()=>[...a[0]||=[o(`查看`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`])),[[E,O(t).loading]]),O(t).error?(h(),i(`div`,ke,[o(g(O(t).error)+` `,1),n(d,{link:``,type:`primary`,size:`small`,onClick:e=>k(t,1)},{default:C(()=>[...a[1]||=[o(`重试`,-1)]]),_:1},8,[`onClick`])])):b(``,!0),x(`div`,Ae,[x(`span`,je,`已显示 `+g(O(t).items.length)+` / `+g(O(t).total)+` 条`,1),O(t).items.length<O(t).total?(h(),e(d,{key:0,size:`small`,loading:O(t).loading,onClick:e=>A(t)},{default:C(()=>[...a[2]||=[o(` 加载更多 `,-1)]]),_:1},8,[`loading`,`onClick`])):b(``,!0)])])]),_:1}),n(l,{label:`Session`,width:`140`},{default:C(({row:t})=>[t.session_id?(h(),i(`span`,{key:0,class:`session-id`,title:`${t.session_id}(点击复制)`,onClick:c(e=>s(m)(t.session_id),[`stop`])},g(s(R)(t.session_id)),9,Me)):(h(),e(u,{key:1,size:`small`,type:`info`,title:`未携带会话标识的请求(NULL / 空串 session_id)`},{default:C(()=>[...a[3]||=[o(` 无 Session `,-1)]]),_:1}))]),_:1}),n(l,{label:`请求数`,width:`80`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.calls)),1)]),_:1}),n(l,{label:`模型`,"min-width":`150`},{default:C(({row:e})=>[x(`span`,{title:e.models||``},g(s(L)(e.models)),9,Ne)]),_:1}),n(l,{label:`客户端`,"min-width":`140`},{default:C(({row:e})=>[x(`span`,{title:e.clients||``},g(s(P)(e.clients)),9,Pe)]),_:1}),n(l,{label:`输入`,width:`105`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.input_tokens)),1)]),_:1}),n(l,{label:`输出`,width:`105`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.output_tokens)),1)]),_:1}),n(l,{label:`缓存读取`,width:`120`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.cache_read_tokens)),1)]),_:1}),n(l,{label:`首次请求`,width:`165`},{default:C(({row:e})=>[o(g(s(V)(e.first_time)),1)]),_:1}),n(l,{label:`最后请求`,width:`165`},{default:C(({row:e})=>[o(g(s(V)(e.last_time)),1)]),_:1})]),_:1},8,[`data`])),[[E,r.loading]]):(h(),e(_,{key:1,description:`当前筛选下没有日志`}))])}}}),[[`__scopeId`,`data-v-2ff0b8c0`]]);u(),T(),S(),d();var Le={class:`logs-page`},Re={class:`filter-bar`},ze={class:`table-wrap`},Be=[`onClick`],Ve={key:1},He=[`title`,`onClick`],Ue={key:1},We=[`title`,`onClick`],Ge={key:1},Ke={class:`pagination-bar`},qe=j(r({__name:`LogsView`,setup(t){let r=M(),{toast:c}=oe(),{copyWithToast:u}=H(),{loadError:d,run:_}=ae(),{rangeKey:S,dateRange:T,setRange:O,onRangeChange:j}=ce(()=>$()),N=l(`2xx`),P=l(``),I=l(``),L=l(``),z=l(`session`),U=l([]),le=l([]),ue=l(null),W=l(0),de=l(0),G=l(1),K=l(20),q=l(!1),fe=l(null),pe=e=>{fe.value?.open(e)},me=a(()=>{let e=new Set;for(let t of r.suppliers)for(let n of t.models)e.add(n.modelName);for(let t of U.value)t.model&&e.add(t.model);return[...e].sort()}),J=l([]),he=a(()=>{let e=new Set(J.value);for(let t of U.value)t.client&&e.add(t.client);return[...e].sort()}),ge=async()=>{try{let e=await p.get(`/api/logs/clients`);J.value=e.clients||[]}catch{J.value=[]}},_e=e=>{S.value=``,T.value=e||null,$()},Y=()=>{let e={};T.value&&T.value.length===2&&(e.startDate=T.value[0],e.endDate=T.value[1]),N.value&&(e.status=N.value),P.value&&(e.model=P.value),I.value&&(e.client=I.value);let t=L.value.trim();return t&&(e.sessionId=t),e},ve=a(()=>Y()),ye=se(),X=()=>_(async()=>{let e=ye();q.value=!0;try{let t={...Y(),page:String(G.value),pageSize:String(K.value)};if(z.value===`session`){let n=new URLSearchParams(t).toString(),r=await p.get(`/api/logs/sessions?`+n);if(!e())return;le.value=r.groups||[],ue.value=r.noSession??null,W.value=r.total||0,de.value=r.rowsTotal||0}else{let n=new URLSearchParams({...t,sort:`time`,order:`desc`}).toString(),r=await p.get(`/api/logs?`+n);if(!e())return;U.value=r.items||[],W.value=r.total||0}}catch(t){if(!e())return;throw t}finally{e()&&(q.value=!1)}}),be=e=>{z.value!==e&&(z.value=e,G.value=1,K.value=z.value===`session`?20:50,X())},Z=l(!1),Q=a(()=>z.value===`session`?de.value:W.value),xe=async()=>{if(Z.value||Q.value===0)return;let e=z.value===`session`?`(按筛选行数计,含「无 Session」组)`:``;try{await A.confirm(`将永久清理当前筛选条件下的 ${Q.value} 条日志${e},清理后不可恢复,请谨慎操作!`,`清理确认`,{confirmButtonText:`确认清理`,cancelButtonText:`取消`,type:`warning`})}catch{return}Z.value=!0;try{let e=new URLSearchParams(Y()).toString(),t=await p.post(`/api/logs/clear?`+e,{});c(`已清理 ${t.deleted??0} 条日志`,`success`),G.value>1&&(G.value=1),X()}catch(e){c(e.message||`清理失败`,`error`)}finally{Z.value=!1}},$=()=>{G.value=1,ge(),X()},Se=()=>{S.value=`today`,T.value=null,N.value=`2xx`,P.value=``,I.value=``,L.value=``,G.value=1,K.value=z.value===`session`?20:50,O(`today`)};return f(()=>{r.loadProviders().catch(()=>{}),ge(),O(`today`)}),(t,r)=>{let a=y(`el-button`),c=y(`el-alert`),l=y(`el-option`),f=y(`el-select`),p=y(`el-date-picker`),_=y(`el-input`),O=y(`el-tooltip`),A=y(`el-button-group`),M=y(`el-card`),H=y(`el-table-column`),ae=y(`el-tag`),oe=y(`el-table`),se=y(`el-pagination`),ce=ee(`loading`);return h(),i(`div`,Le,[s(d)?(h(),e(c,{key:0,title:s(d),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:C(()=>[n(a,{size:`small`,onClick:X},{default:C(()=>[...r[10]||=[o(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):b(``,!0),n(M,{shadow:`never`},{default:C(()=>[x(`div`,Re,[n(f,{modelValue:s(S),"onUpdate:modelValue":r[0]||=e=>m(S)?S.value=e:null,placeholder:`时间范围`,clearable:``,style:{width:`114px`},onChange:s(j)},{default:C(()=>[n(l,{label:`今天`,value:`today`}),n(l,{label:`昨天`,value:`yesterday`}),n(l,{label:`前天`,value:`beforeYesterday`}),n(l,{label:`近三天`,value:`last3days`}),n(l,{label:`本周`,value:`week`}),n(l,{label:`本月`,value:`month`})]),_:1},8,[`modelValue`,`onChange`]),n(p,{modelValue:s(T),"onUpdate:modelValue":r[1]||=e=>m(T)?T.value=e:null,type:`daterange`,"value-format":`YYYY-MM-DD`,"range-separator":`至`,"start-placeholder":`开始日期`,"end-placeholder":`结束日期`,style:{width:`240px`},onChange:_e},null,8,[`modelValue`]),n(f,{modelValue:N.value,"onUpdate:modelValue":r[2]||=e=>N.value=e,placeholder:`全部状态`,clearable:``,style:{width:`106px`},onChange:$},{default:C(()=>[n(l,{label:`成功 (2xx)`,value:`2xx`}),n(l,{label:`3xx`,value:`3xx`}),n(l,{label:`4xx`,value:`4xx`}),n(l,{label:`5xx`,value:`5xx`}),n(l,{label:`错误 (4xx+)`,value:`err`})]),_:1},8,[`modelValue`]),n(f,{modelValue:P.value,"onUpdate:modelValue":r[3]||=e=>P.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`176px`},onChange:$},{default:C(()=>[(h(!0),i(E,null,w(me.value,t=>(h(),e(l,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`]),n(f,{modelValue:I.value,"onUpdate:modelValue":r[4]||=e=>I.value=e,placeholder:`全部客户端`,clearable:``,filterable:``,style:{width:`130px`},onChange:$},{default:C(()=>[(h(!0),i(E,null,w(he.value,t=>(h(),e(l,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`]),n(_,{modelValue:L.value,"onUpdate:modelValue":r[5]||=e=>L.value=e,class:`session-input`,placeholder:`Session ID(前缀匹配)`,clearable:``,onKeyup:D($,[`enter`])},null,8,[`modelValue`]),n(A,{class:`view-switch push-right`},{default:C(()=>[n(O,{content:`按会话分组`,placement:`top`,"show-after":300},{default:C(()=>[n(a,{type:z.value===`session`?`primary`:`default`,icon:s(te),"aria-label":`按会话分组`,onClick:r[6]||=e=>be(`session`)},null,8,[`type`,`icon`])]),_:1}),n(O,{content:`列表`,placement:`top`,"show-after":300},{default:C(()=>[n(a,{type:z.value===`list`?`primary`:`default`,icon:s(k),"aria-label":`列表视图`,onClick:r[7]||=e=>be(`list`)},null,8,[`type`,`icon`])]),_:1})]),_:1}),n(a,{type:`primary`,onClick:$},{default:C(()=>[...r[11]||=[o(`搜索`,-1)]]),_:1}),n(a,{onClick:Se},{default:C(()=>[...r[12]||=[o(`重置`,-1)]]),_:1})])]),_:1}),n(M,{shadow:`never`,class:`mt-16 table-card`},{default:C(()=>[x(`div`,ze,[z.value===`list`?v((h(),e(oe,{key:0,data:U.value,stripe:``,height:`100%`},{default:C(()=>[n(H,{prop:`id`,label:`ID`,"min-width":`80`},{default:C(({row:e})=>[e.id==null?(h(),i(`span`,Ve,`-`)):(h(),i(`span`,{key:0,class:`request-id`,title:`点击复制(日志 id 同时是响应头 x-request-id,可用于关联控制台日志与检索)`,onClick:t=>s(u)(String(e.id))},g(e.id),9,Be))]),_:1}),n(H,{prop:`time`,label:`时间`,width:`180`},{default:C(({row:e})=>[o(g(s(V)(e.time)),1)]),_:1}),n(H,{prop:`model`,label:`模型`,"min-width":`180`}),n(H,{label:`客户端`,"min-width":`150`},{default:C(({row:e})=>[e.client||e.user_agent?(h(),i(`span`,{key:0,class:`request-id`,title:s(ne)(e),onClick:t=>s(u)(e.user_agent||e.client)},g(s(B)(e)),9,He)):(h(),i(`span`,Ue,`-`))]),_:1}),n(H,{label:`Session`,width:`140`},{default:C(({row:e})=>[e.session_id?(h(),i(`span`,{key:0,class:`request-id`,title:`${e.session_id}(点击复制)`,onClick:t=>s(u)(e.session_id)},g(s(R)(e.session_id)),9,We)):(h(),i(`span`,Ge,`-`))]),_:1}),n(H,{label:`输入`,"min-width":`110`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.input_tokens??0)),1)]),_:1}),n(H,{label:`输出`,"min-width":`110`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.output_tokens??0)),1)]),_:1}),n(H,{label:`缓存读取`,"min-width":`90`,align:`center`},{default:C(({row:e})=>[o(g(s(F)(e.cache_read_tokens??0)),1)]),_:1}),n(H,{label:`缓存命中率`,"min-width":`105`,align:`center`},{default:C(({row:e})=>[x(`span`,null,g(s(re)(e)),1)]),_:1}),n(H,{label:`请求耗时`,"min-width":`90`,align:`center`},{default:C(({row:e})=>[o(g(s(ie)(e.duration)),1)]),_:1}),n(H,{prop:`status`,label:`状态`,width:`80`,align:`center`},{default:C(({row:e})=>[n(ae,{size:`small`,type:e.status>=400?`danger`:e.status>=300?`warning`:`success`},{default:C(()=>[o(g(e.status),1)]),_:2},1032,[`type`])]),_:1}),n(H,{label:`详情`,width:`70`,align:`center`},{default:C(({row:e})=>[n(a,{link:``,type:`primary`,onClick:t=>pe(e)},{default:C(()=>[...r[13]||=[o(`查看`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`])),[[ce,q.value]]):b(``,!0),z.value===`session`?(h(),e(Ie,{key:1,groups:le.value,"no-session":ue.value,loading:q.value,"filter-params":ve.value,onOpenDetail:pe},null,8,[`groups`,`no-session`,`loading`,`filter-params`])):b(``,!0)]),x(`div`,Ke,[n(a,{type:`danger`,plain:``,size:`small`,loading:Z.value,disabled:Q.value===0,onClick:xe},{default:C(()=>[...r[14]||=[o(`清理已筛选日志`,-1)]]),_:1},8,[`loading`,`disabled`]),n(se,{class:`push-right`,"current-page":G.value,"onUpdate:currentPage":r[8]||=e=>G.value=e,"page-size":K.value,"onUpdate:pageSize":r[9]||=e=>K.value=e,total:W.value,"page-sizes":[20,50,100,200],layout:`total, sizes, prev, pager, next`,onCurrentChange:X,onSizeChange:X},null,8,[`current-page`,`page-size`,`total`])])]),_:1}),n(Te,{ref_key:`logDetailRef`,ref:fe},null,512)])}}}),[[`__scopeId`,`data-v-9b1602a9`]]);export{qe as default};
@@ -1 +0,0 @@
1
- .ip-link[data-v-9c192d20]{color:#409eff;cursor:pointer}.ip-link[data-v-9c192d20]:hover{text-decoration:underline}.ip-pop[data-v-9c192d20]{min-height:20px;font-size:13px}.ip-pop-row[data-v-9c192d20]{gap:8px;margin-bottom:4px;display:flex}.ip-pop-label[data-v-9c192d20]{color:#909399;flex-shrink:0}.ip-pop-error[data-v-9c192d20]{color:#f56c6c}.ip-pop-link[data-v-9c192d20]{color:#409eff;font-size:13px}.error-text[data-v-9c192d20]{color:#f56c6c}.pane-bar[data-v-9c192d20]{flex-shrink:0;justify-content:flex-end;margin-bottom:8px;display:flex}.json-block[data-v-9c192d20]{white-space:pre-wrap;word-break:break-all;background:#f5f7fa;border:1px solid #e4e7ed;border-radius:4px;flex:1;min-height:0;padding:12px;font-size:13px;line-height:1.5;overflow:auto}.detail-content[data-v-9c192d20]{flex-direction:column;height:78vh;display:flex;overflow:hidden}.detail-content[data-v-9c192d20] .el-tabs{flex-direction:column;flex:1;min-height:0;display:flex}.detail-content[data-v-9c192d20] .el-tabs__content{flex:1;min-height:0}.detail-content[data-v-9c192d20] .el-tab-pane{flex-direction:column;height:100%;display:flex;overflow:auto}.copy-btn[data-v-9c192d20]{margin-left:8px;padding:2px 10px;font-size:12px}.session-table[data-v-2ff0b8c0]{height:100%}.session-id[data-v-2ff0b8c0]{cursor:pointer;white-space:nowrap;text-overflow:ellipsis;font-family:ui-monospace,Consolas,monospace;display:block;overflow:hidden}.session-id[data-v-2ff0b8c0]:hover{color:var(--el-color-primary)}.group-detail[data-v-2ff0b8c0]{padding:4px 16px 8px 48px}.detail-error[data-v-2ff0b8c0]{color:var(--el-color-danger);margin-top:8px;font-size:12px}.detail-footer[data-v-2ff0b8c0]{justify-content:flex-end;align-items:center;gap:12px;margin-top:8px;display:flex}.detail-count[data-v-2ff0b8c0]{color:var(--el-text-color-secondary);font-size:12px}.logs-page[data-v-9b1602a9]{flex-direction:column;height:calc(100vh - 124px);display:flex;overflow:hidden}.request-id[data-v-9b1602a9]{cursor:pointer;white-space:nowrap;text-overflow:ellipsis;font-family:ui-monospace,Consolas,monospace;display:block;overflow:hidden}.request-id[data-v-9b1602a9]:hover{color:var(--el-color-primary)}.filter-bar[data-v-9b1602a9]{flex-wrap:nowrap;align-items:center;gap:12px;display:flex}.filter-bar[data-v-9b1602a9]>*{flex:none}.filter-bar .session-input[data-v-9b1602a9]{flex:160px;min-width:100px}.filter-bar .push-right[data-v-9b1602a9]{margin-left:auto}.filter-bar .view-switch[data-v-9b1602a9]{flex:none}.filter-bar[data-v-9b1602a9] .el-button+.el-button{margin-left:0}@media (width<=900px){.filter-bar[data-v-9b1602a9]{flex-wrap:wrap}.filter-bar .session-input[data-v-9b1602a9]{flex-basis:100%;min-width:0}.filter-bar .push-right[data-v-9b1602a9]{margin-left:auto}}.mt-16[data-v-9b1602a9]{margin-top:16px}.table-card[data-v-9b1602a9]{flex:1;min-height:0;overflow:hidden}.table-card[data-v-9b1602a9] .el-card__body{flex-direction:column;height:100%;display:flex}.table-wrap[data-v-9b1602a9]{flex:1;min-height:0}.pagination-bar[data-v-9b1602a9]{flex-shrink:0;justify-content:space-between;align-items:center;margin-top:16px;display:flex}
@@ -1,2 +0,0 @@
1
- import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Q as s,Tt as c,V as l,Wt as u,Z as d,a as f,at as ee,et as p,fn as m,ht as h,it as g,j as _,k as v,ln as te,mt as y,nt as b,sn as ne,vt as x,w as S}from"./router-DI9ZLaCn.js";import{t as C}from"./index-BKnCp9qM.js";import{p as w,s as T,u as re,v as ie,y as ae}from"./format-DbT9vkcP.js";import{t as oe}from"./useToast-PFDoTWpf.js";l(),x(),u();var se={class:`service-status-page`},ce={class:`flex-between`},le={class:`flex-gap-8`},E={class:`flex-gap-8`},D={class:`gantt-wrap`},O={key:0,class:`gantt`},ue={class:`gantt-row gantt-head`},de={class:`col-cells`},fe=[`title`],pe={class:`cell-head-date`},me={class:`col-name`},he=[`title`,`onClick`],ge=[`title`],k={class:`col-cells`},A=[`title`],j={key:1,class:`gantt-empty`},M=36e5,N=24,P=`#909399`,F=C(n({__name:`ServiceStatusView`,setup(n){let{toast:l}=oe(),{copyWithToast:u}=ie(),{loadError:x,run:C}=ae(`延迟数据加载失败,请重试`),F=c([]),I=c(!0),L=c(!1),R=c(null),z=c(!1),B=c(!1),V,H,U=c(G()),W=c(new Map);function G(){let e=new Date,t=new Date(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours()).getTime();return Array.from({length:N},(e,n)=>t-(23-n)*M)}let K=e=>{let t=new Date(e);return Number.isNaN(t.getTime())?`-`:`${t.getFullYear()}-${w(t.getMonth()+1)}-${w(t.getDate())} ${w(t.getHours())}:00`},_e=i(()=>U.value.map(e=>{let t=new Date(e),n=w(t.getHours());return{start:e,dateLabel:`${w(t.getMonth()+1)}-${w(t.getDate())}`,hourLabel:n,fullLabel:`${K(e)} - ${n}:59`}})),ve=[103,194,58],q=[230,162,60],ye=[245,108,108],be=i(()=>{let e=[];for(let t of W.value.values())for(let n of t.values())n.avgLatencyMs!==null&&e.push(n.avgLatencyMs);if(e.length===0)return{min:0,max:0};let t=e[0],n=e[0];for(let r of e)r<t&&(t=r),r>n&&(n=r);return{min:t,max:n}}),J=e=>{let{min:t,max:n}=be.value,r=n===t?0:(e-t)/(n-t),[i,a]=r<=.5?[ve,q]:[q,ye],o=r<=.5?r*2:(r-.5)*2,s=i.map((e,t)=>Math.round(e+(a[t]-e)*o));return`rgba(${String(s[0])}, ${String(s[1])}, ${String(s[2])}, 0.9)`},Y=(e,t)=>{let n=`${K(t)} - ${w(new Date(t+M).getHours())}:00`;return e===void 0||e.total===0?`${n}\n无探测数据`:`${n}\n平均延迟 ${T(e.avgLatencyMs)}\n成功 ${String(e.success)} / 失败 ${String(e.failed)}`},X=i(()=>Se.value.map(e=>{let t=W.value.get(e.model),n=U.value.map(e=>{let n=t?.get(e);return n!==void 0&&n.failed>0?{start:e,className:`cell--down`,style:{backgroundColor:P},title:Y(n,e)}:n===void 0||n.avgLatencyMs===null?{start:e,className:`cell--empty`,style:{},title:Y(n,e)}:{start:e,className:``,style:{backgroundColor:J(n.avgLatencyMs)},title:Y(n,e)}});return{model:e.model,avg24h:e.avg24h,statusTitle:[e.avg24h===null?`最近 24 小时无成功探测记录`:`最近 24 小时成功探测平均延迟 ${T(e.avg24h)}`,e.lastLatencyMs==null?`最近一次探测:无成功延迟记录`:`最近一次探测延迟 ${T(e.lastLatencyMs)}`].join(`
2
- `),cells:n}})),xe=(e,t)=>e===null&&t===null?0:e===null?1:t===null?-1:e-t,Se=i(()=>[...F.value].sort((e,t)=>{let n=e.lastOk===!1;if(n!==(t.lastOk===!1))return n?1:-1;let r=xe(e.avg24h,t.avg24h);return r===0?e.model.localeCompare(t.model):r})),Z=async e=>{if(e.length===0){W.value=new Map;return}let t=await Promise.all(e.map(async e=>{try{let t=await f.get(`/api/latency/trend?model=${encodeURIComponent(e)}&granularity=hour`);return[e,new Map((t.buckets??[]).map(e=>[e.bucketStart,e]))]}catch{return[e,new Map]}}));W.value=new Map(t)},Q=async()=>{let e=await f.get(`/api/latency/history`);return F.value=e.models??[],L.value=e.running,R.value=e.lastRunAt,e},$=()=>C(async()=>{try{await Q(),U.value=G(),await Z(F.value.map(e=>e.model))}finally{I.value=!1}}),Ce=()=>$(),we=()=>{B.value?V=window.setInterval(()=>void $(),5e3):V!==void 0&&(window.clearInterval(V),V=void 0)},Te=async()=>{z.value=!0;try{await f.post(`/api/latency/run`)}catch(e){l(e.message,`error`),z.value=!1;return}H=window.setInterval(async()=>{try{(await Q()).running||(window.clearInterval(H),H=void 0,z.value=!1,U.value=G(),await Z(F.value.map(e=>e.model)))}catch{}},2e3)};return d(()=>{$()}),s(()=>{V!==void 0&&window.clearInterval(V),H!==void 0&&window.clearInterval(H)}),(n,i)=>{let s=g(`el-button`),c=g(`el-alert`),l=g(`el-tag`),d=g(`el-checkbox`),f=g(`el-empty`),C=g(`el-card`),w=ee(`loading`);return p(),r(`div`,se,[o(x)?(p(),e(c,{key:0,title:o(x),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:y(()=>[t(s,{size:`small`,onClick:Ce},{default:y(()=>[...i[1]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0),t(C,{shadow:`never`,class:`main-card`},{header:y(()=>[v(`div`,ce,[v(`div`,le,[i[3]||=v(`span`,{class:`fw-600`},`服务状态`,-1),L.value?(p(),e(l,{key:0,type:`warning`,size:`small`},{default:y(()=>[...i[2]||=[a(`测试进行中`,-1)]]),_:1})):R.value?(p(),e(l,{key:1,type:`info`,size:`small`},{default:y(()=>[a(` 上次测试 `+m(o(re)(R.value)),1)]),_:1})):_(``,!0)]),v(`div`,E,[t(d,{modelValue:B.value,"onUpdate:modelValue":i[0]||=e=>B.value=e,onChange:we},{default:y(()=>[...i[4]||=[a(` 自动刷新(5s) `,-1)]]),_:1},8,[`modelValue`]),t(s,{loading:z.value,onClick:Te},{default:y(()=>[...i[5]||=[a(` 延迟测试 `,-1)]]),_:1},8,[`loading`])])])]),default:y(()=>[i[9]||=v(`div`,{class:`legend`},[v(`span`,{class:`legend-text`},`延迟`),v(`span`,{class:`legend-text`},`低`),v(`span`,{class:`legend-gradient`}),v(`span`,{class:`legend-text`},`高`),v(`span`,{class:`legend-swatch legend-swatch--down`}),v(`span`,{class:`legend-text`},`该小时有失败探测`),v(`span`,{class:`legend-swatch legend-swatch--empty`}),v(`span`,{class:`legend-text`},`无探测数据`)],-1),h((p(),r(`div`,D,[i[8]||=v(`div`,{class:`muted-sm hint`},` 右侧 24 格为最近 24 小时(每格 1 小时,本地整点对齐,最右格为当前小时)。 格子底色为当小时成功探测的平均延迟,全表统一色标(本期最快→最慢 绿→红); 当小时存在失败探测即视为不可用,显示灰色。 行按 24h 平均延迟升序,最近一次探测失败的模型沉底。 `,-1),X.value.length>0?(p(),r(`div`,O,[v(`div`,ue,[i[6]||=v(`div`,{class:`col-name`},`模型名称`,-1),i[7]||=v(`div`,{class:`col-status`},`状态`,-1),v(`div`,de,[(p(!0),r(S,null,b(_e.value,e=>(p(),r(`div`,{key:e.start,class:`cell cell--head`,title:e.fullLabel},[v(`span`,pe,m(e.dateLabel),1),v(`span`,null,m(e.hourLabel),1)],8,fe))),128))])]),(p(!0),r(S,null,b(X.value,e=>(p(),r(`div`,{key:e.model,class:`gantt-row`},[v(`div`,me,[v(`span`,{class:`copy-text model-name`,title:e.model,onClick:t=>o(u)(e.model)},m(e.model),9,he)]),v(`div`,{class:`col-status`,title:e.statusTitle},m(o(T)(e.avg24h)),9,ge),v(`div`,k,[(p(!0),r(S,null,b(e.cells,e=>(p(),r(`div`,{key:e.start,class:ne([`cell`,e.className]),style:te(e.style),title:e.title},null,14,A))),128))])]))),128))])):(p(),r(`div`,j,[t(f,{description:`暂无延迟数据,点击「延迟测试」开始`,"image-size":80})]))])),[[w,I.value]])]),_:1})])}}}),[[`__scopeId`,`data-v-95ae284d`]]);export{F as default};
@@ -1 +0,0 @@
1
- .switch-divider[data-v-fb084a91],.cpa-divider[data-v-72b7f80b]{margin:16px 0}.mono[data-v-72b7f80b]{font-family:var(--el-font-family-mono,ui-monospace, monospace)}.ml-8[data-v-72b7f80b]{margin-left:8px}.mb-16[data-v-af77e8e0]{margin-bottom:16px}.mt-8[data-v-af77e8e0]{margin-top:8px}.version-row[data-v-af77e8e0]{align-items:center;gap:8px;margin-bottom:8px;display:flex}.version-label[data-v-af77e8e0]{color:var(--el-text-color-secondary);font-size:13px}.version-actions[data-v-af77e8e0]{gap:8px;margin-top:12px;display:flex}.settings-tabs[data-v-f66f6c37] .el-tabs__content{overflow:visible}.save-bar[data-v-f66f6c37]{justify-content:center;padding:8px 0;display:flex;position:sticky;bottom:0}.login-row[data-v-f66f6c37]{flex-wrap:wrap;gap:8px;display:flex}.monitor-row[data-v-f66f6c37]{justify-content:space-between;align-items:center;gap:24px;display:flex}.monitor-title[data-v-f66f6c37]{margin-bottom:4px;font-weight:600}
@@ -1 +0,0 @@
1
- import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Q as s,Tt as c,V as l,Wt as u,Z as d,a as f,at as p,et as m,fn as h,ht as g,it as _,j as v,k as y,mt as b,n as x,nt as S,vt as C,w}from"./router-DI9ZLaCn.js";import{n as T,t as E}from"./index-BKnCp9qM.js";import{n as D,t as O}from"./useManagerApi-l9V9LoLa.js";import{t as k}from"./config-DXHhKDw-.js";import{u as A,v as j,y as M}from"./format-DbT9vkcP.js";import{t as N}from"./useToast-PFDoTWpf.js";import{n as P,t as F}from"./version-DegxwpkG.js";l(),u(),C();var I={class:`flex-between`},L={class:`muted-sm mb-8`},R={class:`switch-row`},z={class:`switch-info`},B={class:`switch-title`},V={class:`switch-row`},H={class:`switch-info`},U={class:`switch-title`},W={class:`switch-row`},G={class:`switch-info`},K={class:`switch-title`},q=E(n({__name:`HarnessSwitches`,setup(n){let{toast:i}=N(),o=c(!0),s=c(!1),l=c(null),u=c(null),f=c(null),x=c(null),S=c(`success`),C=async e=>{e||(l.value?s.value=!0:o.value=!0);try{l.value=await O.harness(),u.value=null}catch(t){e||(u.value=t.message)}finally{e||(o.value=!1,s.value=!1)}};d(()=>C(!1));let E={claudeCode:{label:`Claude Code`,file:`~/.claude/settings.json`,toggle:O.setClaudeCode},codex:{label:`Codex CLI`,file:`~/.codex/config.toml`,toggle:O.setCodex},dsh:{label:`DeepSeek Harness`,file:`~/.dsh/settings.yaml`,toggle:O.setDsh}},D=async(e,t)=>{if(!l.value||f.value)return;let n=E[e],r=t?`确定开启 ${n.label} 代理?将改写 ${n.file}(开启前自动备份,关闭时从备份还原)。`:`确定关闭 ${n.label} 代理?将从备份还原 ${n.file}(无备份时移除代理相关配置)。`;try{await T.confirm(r,t?`开启确认`:`关闭确认`,{confirmButtonText:t?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}f.value=e;try{let e=await n.toggle(t);x.value=e.note??null,S.value=t?`success`:`info`,i(t?`已开启代理`:`已关闭代理`,`success`)}catch(e){i(e.message||`操作失败`,`error`)}finally{f.value=null,await C(!0)}};return(n,i)=>{let c=_(`el-button`),d=_(`el-alert`),T=_(`el-tag`),E=_(`el-switch`),O=_(`el-divider`),k=_(`el-empty`),A=_(`el-card`),j=p(`loading`);return g((m(),e(A,{shadow:`never`},{header:b(()=>[y(`div`,I,[i[7]||=y(`span`,{class:`fw-600`},`代理开关`,-1),t(c,{loading:s.value,onClick:i[0]||=e=>C(!1)},{default:b(()=>[...i[6]||=[a(`刷新`,-1)]]),_:1},8,[`loading`])])]),default:b(()=>[l.value?(m(),r(w,{key:0},[y(`div`,L,` 将本机 CLI 工具的流量一键指向本机网关(`+h(l.value.gatewayBase)+`)。 开启前自动备份原配置为 *.ellm-bak(保留最早的原始备份),关闭时从备份还原。 `,1),x.value?(m(),e(d,{key:0,title:x.value,type:S.value,"show-icon":``,class:`mb-8`,onClose:i[1]||=e=>x.value=null},null,8,[`title`,`type`])):v(``,!0),y(`div`,R,[y(`div`,z,[y(`div`,B,[i[8]||=a(` Claude Code `,-1),t(T,{type:l.value.claudeCode?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(l.value.claudeCode?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),i[9]||=y(`div`,{class:`switch-desc`},[a(` 写入 `),y(`code`,null,`~/.claude/settings.json`),a(` 的 env.ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN, 鉴权取网关配置的 masterKey(未设置将开启失败);其余字段原样保留,重启 Claude Code 会话后生效。 `)],-1)]),t(E,{"model-value":l.value.claudeCode,loading:f.value===`claudeCode`,onChange:i[2]||=e=>D(`claudeCode`,!!e)},null,8,[`model-value`,`loading`])]),t(O,{class:`switch-divider`}),y(`div`,V,[y(`div`,H,[y(`div`,U,[i[10]||=a(` Codex CLI `,-1),t(T,{type:l.value.codex?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(l.value.codex?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),i[11]||=y(`div`,{class:`switch-desc`},[a(` 写入 `),y(`code`,null,`~/.codex/config.toml`),a(` 的 model_provider 与 [model_providers.ellm-proxy] 段 (保留用户注释与排版);开启后需按提示设置环境变量 ELLM_PROXY_API_KEY 供 Codex 鉴权。 `)],-1)]),t(E,{"model-value":l.value.codex,loading:f.value===`codex`,onChange:i[3]||=e=>D(`codex`,!!e)},null,8,[`model-value`,`loading`])]),t(O,{class:`switch-divider`}),y(`div`,W,[y(`div`,G,[y(`div`,K,[i[12]||=a(` DeepSeek Harness `,-1),t(T,{type:l.value.dsh?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(l.value.dsh?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),i[13]||=y(`div`,{class:`switch-desc`},[a(` 写入 `),y(`code`,null,`~/.dsh/settings.yaml`),a(` 的 llm-deepseek.baseURL 与 `),y(`code`,null,`~/.dsh/.credentials.yaml`),a(` 的 DEEPSEEK_API_KEY(取网关 masterKey,未设置则写占位值);模型请在 dsh 内选择与网关部署名一致的模型。 dsh 为 developer preview,配置格式可能随版本变化。 `)],-1)]),t(E,{"model-value":l.value.dsh,loading:f.value===`dsh`,onChange:i[4]||=e=>D(`dsh`,!!e)},null,8,[`model-value`,`loading`])])],64)):(m(),e(k,{key:1,description:u.value||`暂无开关状态`},{default:b(()=>[t(c,{type:`primary`,onClick:i[5]||=e=>C(!1)},{default:b(()=>[...i[14]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1})),[[j,o.value]])}}}),[[`__scopeId`,`data-v-fb084a91`]]);l(),u(),C();var J={class:`flex-between`},Y={class:`muted-sm mb-8`},ee={class:`switch-row`},X={class:`switch-info`},Z={class:`switch-title`},Q={class:`switch-desc`},te={class:`mono`},ne={class:`switch-row`},re=E(n({__name:`CpaSettings`,setup(n){let{toast:o}=N(),{copyWithToast:l}=j(),u=c(!0),f=c(!1),x=c(!1),S=c(null),C=c(null),E=c(null),D=c(`success`),k=c(`auto`),M=c(!1),P=i(()=>S.value?S.value.running?`运行中`:S.value.enabled?`已开启(未运行)`:`已停止`:``),F=i(()=>A(S.value?.startedAt??null)),I=i(()=>{let e=S.value?.credential;if(e){let t=typeof e.nickname==`string`?e.nickname:``,n=typeof e.enterpriseName==`string`?e.enterpriseName:``,r=e.tokenExpired===!0?`token 已过期(将自动刷新)`:`token 有效`;return`${[t,n].filter(e=>e!==``).join(` / `)||`已读取`}(${r})`}return S.value?.credentialError?S.value.credentialError:S.value?.running?`未上报`:`—`}),L=e=>Number.isInteger(e)?String(e):e.toFixed(2),R=i(()=>{let e=S.value?.usage;if(!e)return`—`;let t=typeof e.unit==`string`&&e.unit!==``?e.unit:`credits`;return`${`剩余 ${L(e.remain)} / ${L(e.total)} ${t}`}${typeof e.subscriptionName==`string`&&e.subscriptionName!==``?`(${e.subscriptionName})`:``}`}),z=async e=>{e||(S.value?f.value=!0:u.value=!0);try{S.value=await O.cpa(),C.value=null,M.value||(k.value=S.value.credSource??`auto`)}catch(t){e||(C.value=t.message)}finally{e||(u.value=!1,f.value=!1)}},B=()=>{M.value=!0},V=async()=>{S.value&&await l(S.value.baseUrl)},H=null;d(()=>{z(!1),H=window.setInterval(()=>{document.hidden||x.value||S.value===null||z(!0)},5e3)}),s(()=>{H!==null&&window.clearInterval(H)});let U=async e=>{if(!S.value||x.value)return;let t=!!e,n=t?`确定开启 CPA 代理?将在 127.0.0.1:${S.value.port} 启动常驻代理进程;若配置中缺少指向它的供应商,会自动补一条(从代理拉取模型清单)。`:`确定关闭 CPA 代理?将停止代理进程(供应商配置保留,模型请求将不可用)。`;try{await T.confirm(n,t?`开启确认`:`关闭确认`,{confirmButtonText:t?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}x.value=!0;try{let e=await O.setCpaEnabled(t,t?k.value:void 0);E.value=e.note??null,D.value=t?`success`:`info`,o(t?`已开启 CPA 代理`:`已关闭 CPA 代理`,`success`)}catch(e){o(e.message||`操作失败`,`error`)}finally{x.value=!1,await z(!0)}};return(n,i)=>{let o=_(`el-button`),s=_(`el-alert`),c=_(`el-tag`),l=_(`el-switch`),d=_(`el-divider`),T=_(`el-descriptions-item`),O=_(`el-descriptions`),A=_(`el-option`),j=_(`el-select`),M=_(`el-empty`),N=_(`el-card`),L=p(`loading`);return g((m(),e(N,{shadow:`never`},{header:b(()=>[y(`div`,J,[i[5]||=y(`span`,{class:`fw-600`},`CPA 代理(CodeBuddy / WorkBuddy 订阅)`,-1),t(o,{loading:f.value,onClick:i[0]||=e=>z(!1)},{default:b(()=>[...i[4]||=[a(`刷新`,-1)]]),_:1},8,[`loading`])])]),default:b(()=>[S.value?(m(),r(w,{key:0},[y(`div`,Y,[i[6]||=a(` 通过本机 CPA 代理复用已登录的 CodeBuddy / WorkBuddy 订阅,在 `,-1),y(`code`,null,h(S.value.baseUrl),1),i[7]||=a(` 暴露 OpenAI 兼容接口,由 ezllm 主进程守护; 开启后自动补供应商配置(缺则添加),网关即可路由 cb/* 模型。 `,-1)]),E.value?(m(),e(s,{key:0,title:E.value,type:D.value,"show-icon":``,class:`mb-8`,onClose:i[1]||=e=>E.value=null},null,8,[`title`,`type`])):v(``,!0),y(`div`,ee,[y(`div`,X,[y(`div`,Z,[i[8]||=a(` 一键开启 `,-1),t(c,{type:S.value.running?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(P.value),1)]),_:1},8,[`type`])]),y(`div`,Q,[i[9]||=a(` 开启后在 `,-1),y(`code`,null,`127.0.0.1:`+h(S.value.port),1),i[10]||=a(` 启动常驻代理(随 ezllm 启动自动恢复); 关闭只停进程、不删供应商配置。需先在本机完成 CodeBuddy 桌面端或 JetBrains IDE 登录。 `,-1)])]),t(l,{"model-value":S.value.enabled,loading:x.value,onChange:U},null,8,[`model-value`,`loading`])]),t(d,{class:`cpa-divider`}),t(O,{column:1,size:`small`,border:``},{default:b(()=>[t(T,{label:`运行状态`},{default:b(()=>[S.value.running?(m(),r(w,{key:0},[a(`运行中(pid `+h(S.value.pid)+`,`+h(F.value)+` 启动)`,1)],64)):(m(),r(w,{key:1},[a(`未运行`)],64))]),_:1}),t(T,{label:`接入地址`},{default:b(()=>[y(`span`,te,h(S.value.baseUrl),1),t(o,{link:``,size:`small`,class:`ml-8`,onClick:V},{default:b(()=>[...i[11]||=[a(`复制`,-1)]]),_:1})]),_:1}),t(T,{label:`上游地址`},{default:b(()=>[a(h(S.value.upstream||`—`),1)]),_:1}),t(T,{label:`登录凭据`},{default:b(()=>[a(h(I.value),1)]),_:1}),t(T,{label:`账号额度`},{default:b(()=>[a(h(R.value),1)]),_:1}),t(T,{label:`供应商配置`},{default:b(()=>[S.value.provider.configured?(m(),r(w,{key:0},[a(` 已配置(`+h(S.value.provider.name)+`,`+h(S.value.provider.modelCount)+` 个模型) `,1)],64)):S.value.provider.configError?(m(),r(w,{key:1},[a(h(S.value.provider.configError),1)],64)):(m(),r(w,{key:2},[a(`未配置(开启时自动添加)`)],64))]),_:1}),t(T,{label:`运行日志`},{default:b(()=>[a(h(S.value.logFiles.out),1)]),_:1})]),_:1}),t(d,{class:`cpa-divider`}),y(`div`,ne,[i[12]||=y(`div`,{class:`switch-info`},[y(`div`,{class:`switch-title`},`凭据来源`),y(`div`,{class:`switch-desc`},` 默认「自动」:桌面端登录文件优先、回落 JetBrains IDE 登录态;以 IDE 登录为准时可切「JetBrains 优先」。 运行中不可改(先关闭代理再调整,下次开启生效)。 `)],-1),t(j,{modelValue:k.value,"onUpdate:modelValue":i[2]||=e=>k.value=e,style:{width:`190px`},disabled:x.value||S.value.running,onChange:B},{default:b(()=>[t(A,{label:`自动`,value:`auto`}),t(A,{label:`JetBrains 优先`,value:`jetbrains`})]),_:1},8,[`modelValue`,`disabled`])])],64)):(m(),e(M,{key:1,description:C.value||`暂无 CPA 状态`},{default:b(()=>[t(o,{type:`primary`,onClick:i[3]||=e=>z(!1)},{default:b(()=>[...i[13]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1})),[[L,u.value]])}}}),[[`__scopeId`,`data-v-72b7f80b`]]);l(),u(),C();var ie={class:`service-settings`},ae={class:`flex-between`},oe={key:0,class:`switch-row`},se={class:`switch-info`},ce={class:`switch-title`},le={key:0,class:`switch-row`},ue={class:`switch-info`},de={class:`switch-title`},fe={class:`switch-desc`},pe={key:0,class:`version-block`},me={class:`version-row`},he={class:`muted-sm`},ge={key:0,class:`muted-sm`},_e={key:1,class:`muted-sm`},ve={class:`muted-sm`},$={class:`version-actions`},ye=E(n({__name:`ServiceUpdateSettings`,setup(n){let{toast:o}=N(),l=c(!0),u=c(!1),f=c(null),x=c(null),S=c(null),C=c(null),E=c(null),k=c(!1),A=c(!1),j=c(null),M=null;s(()=>M?.abort());let I=async e=>{if(!e){if(u.value)return;u.value=!0}try{let[e,t]=await Promise.allSettled([O.autostart(),O.update()]);f.value=e.status===`fulfilled`?e.value:null,x.value=e.status===`rejected`?e.reason?.message:null,S.value=t.status===`fulfilled`?t.value:null,C.value=t.status===`rejected`?t.reason?.message:null}finally{l.value=!1,u.value=!1}};d(()=>I(!1));let L=e=>e?new Date(e).toLocaleString():``,R=i(()=>S.value?.lastCheck?.currentVersion??null),z=i(()=>F(R.value)),B=i(()=>S.value?.lastCheck?.latestVersion??null),V=i(()=>S.value?.lastCheck?.hasUpdate===!0),H=i(()=>{let e=S.value?.lastCheck?.checkedAt;return e?new Date(e).toLocaleString():null}),U=i(()=>{let e=S.value?.lastApply;if(!e)return null;let t=L(e.appliedAt);return`${e.fromVersion} → ${e.toVersion}${t?`(${t})`:``}`}),W=async e=>{if(!f.value||E.value)return;let t=e?`确定开启开机自启?将注册登录触发的自启项(登录时自动恢复服务)。`:`确定关闭开机自启?将移除自启项,且此后首次启动不再自动注册。`;try{await T.confirm(t,e?`开启确认`:`关闭确认`,{confirmButtonText:e?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}E.value=`autostart`;try{let t=await O.setAutostart(e);t.note?o(t.note,`success`):o(e?`开机自启已开启`:`开机自启已关闭`,`success`)}catch(e){o(e.message||`操作失败`,`error`)}finally{E.value=null,await I(!0)}},G=async e=>{if(!S.value||E.value)return;let t=e?`确定开启自动更新?将每小时检查 npm 源,发现新版本自动安装并重启服务。`:`确定关闭自动更新?不再自动检查(手动检查更新不受影响)。`;try{await T.confirm(t,e?`开启确认`:`关闭确认`,{confirmButtonText:e?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}E.value=`updateEnabled`;try{let t=await O.setUpdateEnabled(e);t.note&&o(t.note,`success`)}catch(e){o(e.message||`操作失败`,`error`)}finally{E.value=null,await I(!0)}},K=async()=>{k.value=!0;try{let e=await O.checkUpdate();j.value=e.hasUpdate?`发现新版本 ${e.latestVersion}(当前 ${e.currentVersion}):点击「立即更新」即可安装(服务自动重启,期间管理台短暂不可访问)`:`已是最新版本 ${e.currentVersion}(检查于 ${L(e.checkedAt)})`,await I(!0)}catch(e){o(e.message||`检查更新失败`,`error`)}finally{k.value=!1}},q=async()=>{try{await T.confirm(`确定更新到 ${B.value}?服务会自动重启并在启动时安装新版本:重启期间管理台短暂不可访问(预计 1~3 分钟),更新完成后自动恢复。`,`更新确认`,{confirmButtonText:`立即更新`,cancelButtonText:`取消`,type:`warning`})}catch{return}A.value=!0;let e=new AbortController;M=e;try{let t=await O.update(),n=await O.applyUpdate();if(!n.updated){j.value=`已是最新版本 ${n.toVersion}`;return}j.value=`正在重启服务并安装 ${n.toVersion}(预计 1~3 分钟):重启期间管理台短暂不可访问,完成后这里会自动显示结果。`;let r=await D({targetVersion:n.toVersion,sinceAppliedAt:t.lastApply?.appliedAt??null,signal:e.signal});if(e.signal.aborted)return;r&&!r.error?(o(`已更新到 ${r.toVersion}`,`success`),j.value=`已更新 ${r.fromVersion} → ${r.toVersion},服务已在新版本上运行。`):r?.error?(o(`更新失败:${r.error}`,`error`),j.value=P(r.error)):j.value=`更新仍在进行(安装耗时较长):稍后刷新页面查看最新状态。`}catch(e){o(e.message||`更新失败`,`error`)}finally{A.value=!1,M===e&&(M=null),e.signal.aborted||await I(!0)}};return(n,i)=>{let o=_(`el-button`),s=_(`el-tag`),c=_(`el-switch`),d=_(`el-empty`),T=_(`el-card`),D=_(`el-link`),O=_(`el-alert`),M=p(`loading`);return g((m(),r(`div`,ie,[t(T,{shadow:`never`,class:`mb-16`},{header:b(()=>[y(`div`,ae,[i[7]||=y(`span`,{class:`fw-600`},`开机自启`,-1),t(o,{loading:u.value,onClick:i[0]||=e=>I(!1)},{default:b(()=>[...i[6]||=[a(`刷新`,-1)]]),_:1},8,[`loading`])])]),default:b(()=>[f.value?(m(),r(`div`,oe,[y(`div`,se,[y(`div`,ce,[i[8]||=a(` 登录时自动启动服务 `,-1),t(s,{type:f.value.enabled?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(f.value.enabled?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),i[9]||=y(`div`,{class:`switch-desc`},[a(` 登录操作系统时自动启动服务(无需管理员权限)。 关闭后首次启动 `),y(`code`,null,`ezllm`),a(` 也不会再自动注册,重新开启即可解除。 `)],-1)]),t(c,{"model-value":f.value.enabled,loading:E.value===`autostart`,onChange:i[1]||=e=>W(!!e)},null,8,[`model-value`,`loading`])])):(m(),e(d,{key:1,description:x.value||`暂无自启状态`},{default:b(()=>[t(o,{type:`primary`,onClick:i[2]||=e=>I(!1)},{default:b(()=>[...i[10]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1}),t(T,{shadow:`never`,class:`mb-16`},{header:b(()=>[...i[11]||=[y(`div`,{class:`flex-between`},[y(`span`,{class:`fw-600`},`自动更新`)],-1)]]),default:b(()=>[S.value?(m(),r(`div`,le,[y(`div`,ue,[y(`div`,de,[i[12]||=a(` 自动检查并安装新版本 `,-1),t(s,{type:S.value.enabled?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(S.value.enabled?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),y(`div`,fe,[S.value.supported?(m(),r(w,{key:1},[a(` 每小时检查 npm 源,发现新版本自动重启服务并在启动时安装(更新期间服务短暂中断); 关闭后仍可在下方手动检查与更新。 `)],64)):(m(),r(w,{key:0},[a(` 当前为源码运行模式,更新功能不可用(仅 npm 全局安装的包支持自动更新)。 `)],64))])]),S.value.supported?(m(),e(c,{key:0,"model-value":S.value.enabled,loading:E.value===`updateEnabled`,onChange:i[3]||=e=>G(!!e)},null,8,[`model-value`,`loading`])):v(``,!0)])):(m(),e(d,{key:1,description:C.value||`暂无更新状态`},{default:b(()=>[t(o,{type:`primary`,onClick:i[4]||=e=>I(!1)},{default:b(()=>[...i[13]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1}),t(T,{shadow:`never`},{header:b(()=>[...i[14]||=[y(`div`,{class:`flex-between`},[y(`span`,{class:`fw-600`},`版本信息`)],-1)]]),default:b(()=>[S.value?(m(),r(`div`,pe,[y(`div`,me,[i[18]||=y(`span`,{class:`version-label`},`当前版本`,-1),t(s,{size:`small`},{default:b(()=>[a(h(R.value||`未知`),1)]),_:1}),z.value?(m(),e(s,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:b(()=>[...i[15]||=[a(`本地构建`,-1)]]),_:1})):v(``,!0),B.value?(m(),r(w,{key:1},[i[17]||=y(`span`,{class:`version-label`},`最新版本`,-1),t(s,{type:V.value?`warning`:`success`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(B.value),1)]),_:1},8,[`type`]),V.value?(m(),e(s,{key:0,type:`warning`,size:`small`,"disable-transitions":``},{default:b(()=>[...i[16]||=[a(`发现新版本`,-1)]]),_:1})):v(``,!0)],64)):v(``,!0)]),y(`div`,he,[a(` 上次检查:`+h(H.value||`尚未检查`)+` `,1),S.value.updating?(m(),r(w,{key:0},[a(` · 更新执行中...`)],64)):v(``,!0)]),S.value.supported?v(``,!0):(m(),r(`div`,ge,`源码运行模式:手动检查与更新不可用。`)),U.value?(m(),r(`div`,_e,`上次更新:`+h(U.value),1)):v(``,!0),y(`div`,ve,[i[20]||=a(` npm 包主页:`,-1),t(D,{type:`primary`,href:`https://www.npmjs.com/package/ezllm`,target:`_blank`},{default:b(()=>[...i[19]||=[a(`npmjs.com/package/ezllm`,-1)]]),_:1})]),y(`div`,$,[t(o,{loading:k.value,disabled:!S.value.supported||S.value.updating,onClick:K},{default:b(()=>[a(h(k.value?`检查中...`:`检查更新`),1)]),_:1},8,[`loading`,`disabled`]),V.value&&S.value.supported?(m(),e(o,{key:0,type:`primary`,loading:A.value,disabled:S.value.updating,onClick:q},{default:b(()=>[a(h(A.value?`更新中...`:`立即更新到 ${B.value}`),1)]),_:1},8,[`loading`,`disabled`])):v(``,!0)]),j.value?(m(),e(O,{key:2,title:j.value,type:`info`,"show-icon":``,class:`mt-8`,onClose:i[5]||=e=>j.value=null},null,8,[`title`])):v(``,!0)])):(m(),e(d,{key:1,description:`更新状态不可用`}))]),_:1})])),[[M,l.value]])}}}),[[`__scopeId`,`data-v-af77e8e0`]]);l(),C(),u();var be={class:`flex-col-gap`},xe={class:`flex-between`},Se={class:`muted-sm`},Ce={class:`login-row`},we={class:`muted-sm`},Te={class:`flex-between`},Ee={class:`monitor-row`},De={class:`save-bar`},Oe=E(n({__name:`SettingsView`,setup(n){let{toast:s}=N(),{copyWithToast:l}=j(),u=k(),C=c(`basic`),T=c(!0),E=c(!1),D=c(``),O=async()=>{D.value&&await l(D.value)},A=c(29770),P=c(null),F=c(!0),I=c(``),L=c(``),R=i(()=>D.value.trim()!==``||I.value!==``&&L.value!==``),z=c(!1),B=c(60),V=[{label:`10分钟`,value:10},{label:`30分钟`,value:30},{label:`1小时`,value:60},{label:`2小时`,value:120},{label:`5小时`,value:300},{label:`8小时`,value:480},{label:`12小时`,value:720},{label:`24小时`,value:1440}],{loadError:H,run:U}=M(`设置加载失败,请重试`),W=()=>U(async()=>{try{await u.load(),D.value=u.config.masterKey||``,A.value=u.config.port??29770;let e=u.config[`web-ui`]?.[`login-account`];I.value=e?.username||``,L.value=e?.password||``,F.value=u.config.allowLan!==!1;let t=u.config.latencyTest;z.value=t?.enabled===!0,B.value=t?.intervalMinutes??60;try{let e=await f.get(`/api/status`);P.value=e.listenPort}catch{P.value=null}}finally{T.value=!1}}),G=async()=>{if(I.value.trim()!==``||L.value!==``){if(I.value.trim()===``||L.value===``){s(`用户名和密码需同时填写`,`error`);return}if(L.value.length<6){s(`密码至少 6 位`,`error`);return}}E.value=!0;let e=z.value&&u.config.latencyTest?.enabled!==!0;try{let t=await u.update(e=>{e.masterKey=D.value.trim(),e.port=A.value,e.allowLan=F.value,e.latencyTest={enabled:z.value,intervalMinutes:B.value},e[`web-ui`]??={},e[`web-ui`][`login-account`]??={},e[`web-ui`][`login-account`].username=I.value.trim(),e[`web-ui`][`login-account`].password=L.value});await x(!0),s(`设置已保存并生效`,`success`),e&&s(`已开启自动测试:服务将定期直连所有上游发送探测请求,有少量 token 消耗`,`warning`),t.restartHint&&s(t.restartHint,`warning`)}catch(e){s(e.message,`error`)}finally{E.value=!1}};return d(W),(n,i)=>{let s=_(`el-button`),c=_(`el-alert`),l=_(`el-tag`),u=_(`el-input`),d=_(`el-form-item`),f=_(`el-input-number`),x=_(`el-form`),k=_(`el-card`),j=_(`el-switch`),M=_(`el-divider`),N=_(`el-option`),U=_(`el-select`),K=_(`el-tab-pane`),J=_(`el-tabs`),Y=p(`loading`);return m(),e(J,{modelValue:C.value,"onUpdate:modelValue":i[7]||=e=>C.value=e,class:`settings-tabs`},{default:b(()=>[t(K,{label:`基本设置`,name:`basic`},{default:b(()=>[g((m(),r(`div`,be,[o(H)?(m(),e(c,{key:0,title:o(H),type:`error`,"show-icon":``,closable:!1},{default:b(()=>[t(s,{size:`small`,onClick:W},{default:b(()=>[...i[8]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):v(``,!0),t(k,{shadow:`never`},{header:b(()=>[y(`div`,xe,[i[10]||=y(`span`,{class:`fw-600`},`网关访问`,-1),t(l,{type:`success`},{default:b(()=>[...i[9]||=[a(`运行中`,-1)]]),_:1})])]),default:b(()=>[t(x,{"label-position":`top`},{default:b(()=>[t(d,{label:`API 密钥 (masterKey)`},{default:b(()=>[t(u,{modelValue:D.value,"onUpdate:modelValue":i[0]||=e=>D.value=e,placeholder:`sk-1234`,clearable:``},{append:b(()=>[t(s,{onClick:O},{default:b(()=>[...i[11]||=[a(`复制`,-1)]]),_:1})]),_:1},8,[`modelValue`]),i[12]||=y(`div`,{class:`muted-sm`},`客户端请求 /v1/* 时的认证密钥(Bearer <masterKey>;留空 = 本地放行)`,-1)]),_:1}),t(d,{label:`监听端口 (port)`},{default:b(()=>[t(f,{modelValue:A.value,"onUpdate:modelValue":i[1]||=e=>A.value=e,min:1,max:65535,step:1,style:{width:`220px`}},null,8,[`modelValue`]),y(`div`,Se,[i[14]||=a(` 网关与管理台 API 的监听端口,保存后重启生效 `,-1),P.value===null?v(``,!0):(m(),r(w,{key:0},[i[13]||=a(` ;服务上报的端口 `,-1),y(`b`,null,h(P.value),1)],64))])]),_:1})]),_:1})]),_:1}),t(k,{shadow:`never`},{header:b(()=>[...i[15]||=[y(`span`,{class:`fw-600`},`安全与登录`,-1)]]),default:b(()=>[t(x,{"label-position":`top`},{default:b(()=>[t(d,{label:`管理台登录账号`},{default:b(()=>[y(`div`,Ce,[t(u,{modelValue:I.value,"onUpdate:modelValue":i[2]||=e=>I.value=e,placeholder:`用户名`,style:{width:`200px`}},null,8,[`modelValue`]),t(u,{modelValue:L.value,"onUpdate:modelValue":i[3]||=e=>L.value=e,type:`password`,placeholder:`密码(至少 6 位)`,"show-password":``,style:{width:`200px`}},null,8,[`modelValue`])]),i[16]||=y(`div`,{class:`muted-sm`},` 管理台登录凭证;留空 = 免登录直接访问(仅本机使用时推荐)。 修改后立即生效,需用新账号重新登录 `,-1)]),_:1}),t(d,{label:`允许局域网访问 (allowLan)`},{default:b(()=>[t(j,{modelValue:F.value,"onUpdate:modelValue":i[4]||=e=>F.value=e},null,8,[`modelValue`]),y(`div`,we,[i[17]||=a(` 开启 = 绑定全部网卡,局域网内设备可访问;关闭 = 仅本机 127.0.0.1。保存后需重启生效 `,-1),R.value?v(``,!0):(m(),r(w,{key:0},[a(` ;未设置任何凭据(密钥与登录账号皆无)时始终仅绑本机 `)],64))])]),_:1})]),_:1})]),_:1}),t(k,{shadow:`never`},{header:b(()=>[y(`div`,Te,[i[18]||=y(`span`,{class:`fw-600`},`模型服务监控`,-1),t(l,{type:z.value?`success`:`info`,size:`small`,"disable-transitions":``},{default:b(()=>[a(h(z.value?`已开启`:`未开启`),1)]),_:1},8,[`type`])])]),default:b(()=>[y(`div`,Ee,[i[19]||=y(`div`,{class:`monitor-info`},[y(`div`,{class:`monitor-title`},`自动测试模型服务状态`),y(`div`,{class:`muted-sm`},` 按设定间隔自动直连所有上游模型发送极小探测请求(max_tokens: 1,有少量 token 消耗); 测试结果展示在「服务状态」页面 `)],-1),t(j,{modelValue:z.value,"onUpdate:modelValue":i[5]||=e=>z.value=e},null,8,[`modelValue`])]),z.value?(m(),r(w,{key:0},[t(M,{style:{margin:`12px 0`}}),t(x,{"label-position":`top`},{default:b(()=>[t(d,{label:`测试间隔`,style:{"margin-bottom":`0`}},{default:b(()=>[t(U,{modelValue:B.value,"onUpdate:modelValue":i[6]||=e=>B.value=e,style:{width:`220px`}},{default:b(()=>[(m(),r(w,null,S(V,e=>t(N,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`]),i[20]||=y(`div`,{class:`muted-sm`},`自动测试的执行间隔,保存后即时生效(无需重启)`,-1)]),_:1})]),_:1})],64)):v(``,!0)]),_:1}),y(`div`,De,[t(s,{type:`primary`,size:`large`,loading:E.value,disabled:E.value||o(H)!==null,onClick:G},{default:b(()=>[a(h(E.value?`保存中...`:`保存设置`),1)]),_:1},8,[`loading`,`disabled`])])])),[[Y,T.value]])]),_:1}),t(K,{label:`代理开关`,name:`harness`,lazy:``},{default:b(()=>[t(q)]),_:1}),t(K,{label:`CPA`,name:`cpa`,lazy:``},{default:b(()=>[t(re)]),_:1}),t(K,{label:`服务与更新`,name:`service`,lazy:``},{default:b(()=>[t(ye)]),_:1})]),_:1},8,[`modelValue`])}}}),[[`__scopeId`,`data-v-f66f6c37`]]);export{Oe as default};
@@ -1 +0,0 @@
1
- .setup-wrap[data-v-852bbcb1]{justify-content:center;align-items:center;min-height:100vh;display:flex}.setup-card[data-v-852bbcb1]{border-radius:16px;width:520px;max-width:92vw;box-shadow:0 12px 40px #1f23291a}.setup-brand[data-v-852bbcb1]{justify-content:center;align-items:center;gap:10px;margin-top:8px;display:flex}.setup-title[data-v-852bbcb1]{color:var(--el-text-color-primary);font-size:20px;font-weight:700}.setup-sub[data-v-852bbcb1]{text-align:center;color:var(--el-text-color-secondary);margin:6px 0 24px;font-size:13px}.account-row[data-v-852bbcb1]{gap:12px;width:100%;display:flex}.label-hint[data-v-852bbcb1]{color:#909399;font-size:12px;font-weight:400;line-height:1.4;display:block}.full-width[data-v-852bbcb1]{width:100%}.mb-16[data-v-852bbcb1]{margin-bottom:16px}
@@ -1 +0,0 @@
1
- import{A as e,F as t,I as n,M as r,P as i,S as a,Tt as o,V as s,Z as c,a as l,et as u,ft as d,it as f,j as p,k as m,m as h,mt as g,n as _,r as v,u as y,vt as b}from"./router-DI9ZLaCn.js";import{t as x}from"./message-C1fkA9sE.js";import{t as S}from"./index-BKnCp9qM.js";import{t as C}from"./clipboard-JYWVdyjq.js";s(),h(),b();var w={class:`setup-wrap`},T={class:`account-row`},E=S(n({__name:`SetupView`,setup(n){let s=y(),h=o(!1),b=o(``),S=!1,E=o(``),D=o(``),O=o(!1),k=o(``);c(async()=>{!(await _()).masterKeySet&&h.value&&A()});function A(){b.value=(()=>{let e=new Uint8Array(32);crypto.getRandomValues(e);let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)})(),S=!0}d(h,e=>{e?b.value.trim()===``&&A():S&&=(b.value=``,!1)});async function j(){await C(b.value)?x.success(`已复制到剪贴板`):x.error(`复制失败,请手动选择复制`)}async function M(){k.value=``;let e=h.value?`server`:`local`,t=b.value.trim(),n=E.value.trim()!==``||D.value!==``;if(h.value&&t===``){k.value=`服务器部署必须设置主密钥,防止 /v1 网关被他人盗用`;return}if(h.value&&!n){k.value=`服务器部署必须设置登录账号密码,防止管理台被陌生人登录`;return}if(n){if(E.value.trim()===``||D.value===``){k.value=`用户名和密码需同时填写`;return}if(D.value.length<6){k.value=`密码至少 6 位`;return}}O.value=!0;try{let r=t===``?null:await l.post(`/api/setup/master-key`,{mode:`custom`,masterKey:t}),i=await l.post(`/api/setup/finish`,{deployment:e,...n?{username:E.value.trim(),password:D.value}:{}});v(e,n),x.success(n?`初始化完成,请使用新账号登录`:`初始化完成,免登录进入管理台`);let a=r?.restartHint??i.restartHint;a&&x({message:a,type:`warning`,duration:8e3}),await s.push(n?`/login`:`/`)}catch(e){k.value=e.message||`保存失败`}finally{O.value=!1}}return(n,o)=>{let s=f(`el-checkbox`),c=f(`el-alert`),l=f(`el-button`),d=f(`el-input`),_=f(`el-form-item`),v=f(`el-form`),y=f(`el-card`);return u(),r(`div`,w,[t(y,{shadow:`never`,class:`setup-card`},{default:g(()=>[o[10]||=m(`div`,{class:`setup-brand`},[m(`span`,{class:`brand-mark`},`EZ`),m(`span`,{class:`setup-title`},`初始化 EZLLM`)],-1),o[11]||=m(`p`,{class:`setup-sub`},`首次使用前完成部署形态与访问凭据的配置`,-1),t(s,{modelValue:h.value,"onUpdate:modelValue":o[0]||=e=>h.value=e,class:`mb-16`},{default:g(()=>[...o[4]||=[i(` 允许其他设备访问本服务(局域网 / 公网部署) `,-1)]]),_:1},8,[`modelValue`]),h.value?(u(),e(c,{key:0,type:`warning`,"show-icon":``,closable:!1,title:`服务将对网络中的其他设备可见,请务必保留主密钥并修改默认账号`,class:`mb-16`})):p(``,!0),t(v,{"label-position":`top`,onSubmit:a(M,[`prevent`])},{default:g(()=>[t(_,null,{label:g(()=>[...o[5]||=[i(` API 主密钥(本地部署可留空) `,-1),m(`span`,{class:`label-hint`},`调用 /v1/* 时的 Bearer Token;留空 = 不启用鉴权,且未设登录账号时服务仅本机可访问`,-1)]]),default:g(()=>[t(d,{modelValue:b.value,"onUpdate:modelValue":o[1]||=e=>b.value=e,placeholder:`已设置主密钥,留空保持不变`,clearable:``},{append:g(()=>[t(l,{onClick:A},{default:g(()=>[...o[6]||=[i(`生成`,-1)]]),_:1}),t(l,{disabled:!b.value,onClick:j},{default:g(()=>[...o[7]||=[i(`复制`,-1)]]),_:1},8,[`disabled`])]),_:1},8,[`modelValue`])]),_:1}),t(_,null,{label:g(()=>[...o[8]||=[i(` 管理台登录(可选) `,-1),m(`span`,{class:`label-hint`},`不填 = 免登录直接进管理台(纯本机使用);勾选上方后必须填写`,-1)]]),default:g(()=>[m(`div`,T,[t(d,{modelValue:E.value,"onUpdate:modelValue":o[2]||=e=>E.value=e,placeholder:`用户名`,clearable:``},null,8,[`modelValue`]),t(d,{modelValue:D.value,"onUpdate:modelValue":o[3]||=e=>D.value=e,type:`password`,"show-password":``,placeholder:`密码(至少 6 位)`},null,8,[`modelValue`])])]),_:1}),k.value?(u(),e(c,{key:0,title:k.value,type:`error`,"show-icon":``,closable:!1,class:`mb-16`},null,8,[`title`])):p(``,!0),t(l,{type:`primary`,class:`full-width`,loading:O.value,onClick:M},{default:g(()=>[...o[9]||=[i(` 完成初始化 `,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})])}}}),[[`__scopeId`,`data-v-852bbcb1`]]);export{E as default};
@@ -1 +0,0 @@
1
- import{Tt as e,vt as t}from"./router-DI9ZLaCn.js";import{t as n}from"./clipboard-JYWVdyjq.js";import{t as r}from"./useToast-PFDoTWpf.js";t();function i(t=`加载失败,请稍后重试`){let n=e(null);async function r(e){n.value=null;try{return await e(),!0}catch(e){return n.value=e?.message||t,!1}}return{loadError:n,run:r}}function a(){let{toast:e}=r();async function t(t,r=`已复制到剪贴板`){let i=await n(t);return i?e(r,`success`):e(`复制失败`,`error`),i}return{copyWithToast:t}}var o=e=>String(e).padStart(2,`0`),s=e=>{let t=e=>`${e.getFullYear()}-${o(e.getMonth()+1)}-${o(e.getDate())}`,n=new Date,r=new Date(n),i=n;if(e!==`today`){if(e===`yesterday`)r.setDate(n.getDate()-1),i=r;else if(e===`beforeYesterday`)r.setDate(n.getDate()-2),i=r;else if(e===`last3days`)r.setDate(n.getDate()-2);else if(e===`week`)r.setDate(n.getDate()-(n.getDay()+6)%7);else if(e===`month`)r.setDate(1);else return null}return[t(r),t(i)]},c=e=>{if(e.name)return e.name;if(e.alias)return e.alias;let t=e.apiKey||``;if(!t)return`-`;if(t.length<=8)return t;let n=Math.min(6,Math.floor(t.length/4));return`${t.substring(0,n)}...${t.substring(t.length-n)}`},l=e=>{if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?`-`:`${t.getFullYear()}-${o(t.getMonth()+1)}-${o(t.getDate())} ${o(t.getHours())}:${o(t.getMinutes())}:${o(t.getSeconds())}`},u=e=>e?typeof e==`string`?e:JSON.stringify(e,null,2):`-`,d=e=>{if(!e)return`-`;try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}},f=e=>{let t=e??0;return(Number.isFinite(t)?t:0).toLocaleString()},p=({protocol:e,hostname:t,port:n})=>`${e===`https:`?`https:`:`http:`}//${t}${n?`:${n}`:``}`,m=e=>e==null||e<=0?`-`:e>=1e3?(e/1e3).toFixed(2)+`s`:Math.round(e)+`ms`,h=e=>e==null?`-`:e<1e3?`${String(e)}ms`:`${(e/1e3).toFixed(1)}s`,g=e=>{let t=e.input_tokens||0,n=e.cache_read_tokens||0;return t<=0?`-`:(n/t*100).toFixed(1)+`%`},_=(e,t=262144)=>{let n=e??``;return n.length<=t?n:`${n.slice(0,t)}\n\n…(已省略 ${(n.length-t).toLocaleString()} 字符以保持流畅,完整内容请点上方「复制」按钮)`},v=e=>{let t=(e||``).trim();return t?t.length>8?`${t.slice(0,8)}…`:t:`-`},y=e=>e.client||e.user_agent||`-`,b=e=>e.user_agent?`${e.user_agent}(点击复制)`:`${e.client??`-`}(点击复制)`,x=e=>{let t=(e||``).split(`,`).map(e=>e.trim()).filter(Boolean).sort();return t.length===0?`-`:t.length<=2?t.join(`, `):`${t.slice(0,2).join(`, `)} +${t.length-2}`},S=e=>x(e),C=e=>x(e);export{_,C as a,f as c,d,S as f,v as g,s as h,b as i,u as l,c as m,g as n,m as o,o as p,y as r,h as s,p as t,l as u,a as v,i as y};
@@ -1 +0,0 @@
1
- import{O as e,Tt as t,V as n,vt as r}from"./router-DI9ZLaCn.js";import{r as i}from"./index-BKnCp9qM.js";import{t as a}from"./config-DXHhKDw-.js";function o(e,...t){console.warn(e,...t)}r(),n();var s=i(`providers`,()=>{let n=a(),r=e(()=>n.providers),i=e(()=>n.loading),s=e(()=>n.providerCount),c=e(()=>n.totalModelCount),l=t([]);function u(){try{let e=localStorage.getItem(`provider_order`);if(!e)return;let t=JSON.parse(e);if(!Array.isArray(t))return;l.value=t}catch{}}function d(){try{localStorage.setItem(`provider_order`,JSON.stringify(l.value))}catch(e){o(`[ezllm] 供应商卡片顺序持久化失败(本次会话内仍生效,刷新后回退):${e instanceof Error?e.message:String(e)}`)}}let f=e(()=>{let e=l.value.map(e=>r.value.find(t=>t.name===e)).filter(e=>!!e);for(let t of r.value)e.find(e=>e.name===t.name)||e.push(t);let t=e.map(e=>e.name);(t.length!==l.value.length||t.some((e,t)=>l.value[t]!==e))&&(l.value=t,d());let n=e=>e.enabled!==!1;return[...e.filter(n),...e.filter(e=>!n(e))]});function p(e){l.value=e.map(e=>e.name),d()}function m(e){l.value=[e,...l.value.filter(t=>t!==e)],d()}async function h(){u(),await n.load()}async function g(e){let t=n.config.providers;n.config.providers=e;try{return await n.save()}catch(e){throw n.config.providers=t,e}}async function _(e){return await g(r.value.filter(t=>t.name!==e.name))}async function v(e){return await g(r.value.map(t=>({...t,models:(t.models??[]).filter(t=>t.modelName!==e)})))}return{suppliers:r,loading:i,orderedProviders:f,providerCount:s,totalModelCount:c,loadProviders:h,saveProviders:g,deleteProvider:_,deleteModel:v,reorderProviders:p,moveProviderToTop:m}});export{s as t};
@@ -1 +0,0 @@
1
- import{s as e}from"./router-DI9ZLaCn.js";var t=`/api/service`,n=`/api/harness`,r=`${t}/managed`,i=`${t}/cpa`,a={processes:()=>e.get(`${t}/processes`).then(e=>e.processes),autostart:()=>e.get(`${t}/autostart`),setAutostart:n=>e.post(`${t}/autostart`,{enabled:n}),update:()=>e.get(`${t}/update`),setUpdateEnabled:n=>e.post(`${t}/update/enabled`,{enabled:n}),checkUpdate:()=>e.post(`${t}/update/check`),applyUpdate:()=>e.post(`${t}/update/apply`),managedServices:()=>e.get(r),createManagedService:t=>e.post(r,t),updateManagedService:(t,n)=>e.put(`${r}/${encodeURIComponent(t)}`,n),removeManagedService:t=>e.del(`${r}/${encodeURIComponent(t)}`),startManagedService:t=>e.post(`${r}/${encodeURIComponent(t)}/start`),stopManagedService:t=>e.post(`${r}/${encodeURIComponent(t)}/stop`),restartManagedService:t=>e.post(`${r}/${encodeURIComponent(t)}/restart`),cpa:()=>e.get(i),setCpaEnabled:(t,n)=>e.post(`${i}/enabled`,n===void 0?{enabled:t}:{enabled:t,credSource:n}),harness:()=>e.get(n),setClaudeCode:t=>e.post(`${n}/claude-code`,{enabled:t}),setCodex:t=>e.post(`${n}/codex`,{enabled:t}),setDsh:t=>e.post(`${n}/dsh`,{enabled:t})};async function o(e){let{targetVersion:t,sinceAppliedAt:n,timeoutMs:r=6e5,pollMs:i=3e3,signal:o}=e,s=Date.now()+r;for(;;){if(o?.aborted||Date.now()>=s||(await new Promise(e=>setTimeout(e,i)),o?.aborted))return null;let e=null;try{e=await a.update()}catch{continue}let r=e.lastApply;if(r&&r.toVersion===t&&(r.appliedAt??0)>(n??0))return r;if(Date.now()>=s)return null}}export{o as n,a as t};
@@ -1 +0,0 @@
1
- import{t as e}from"./message-C1fkA9sE.js";function t(){function t(t,n=`success`){e({message:t,type:n,duration:n===`warning`?8e3:3e3})}return{toast:t}}export{t};
@@ -1 +0,0 @@
1
- function e(e){return`更新失败:${e}(更新未生效,服务仍在旧版本运行)`}function t(e){return typeof e==`string`&&/-\d{4}\.\d{1,2}\.\d{1,2}-\d{1,2}\.\d{1,2}\.\d{1,2}$/.test(e)}export{e as n,t};