ezllm 0.0.37 → 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 (45) hide show
  1. package/README.md +59 -18
  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 +79 -77
  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-Bzngu7qF.js → LoginView-CwH6eISd.js} +1 -1
  10. package/dist/web-ui/assets/LogsView-CGgzVbGZ.js +5 -0
  11. package/dist/web-ui/assets/{ManagedServicesView-5QT_g-5a.js → ManagedServicesView-BvzeGhcb.js} +2 -2
  12. package/dist/web-ui/assets/PluginsView-CNDVeVj8.js +2 -0
  13. package/dist/web-ui/assets/PluginsView-zyTILSF1.css +1 -0
  14. package/dist/web-ui/assets/ProvidersView-DTIx2VSi.js +14 -0
  15. package/dist/web-ui/assets/{ServiceStatusView--D1wfNAZ.js → ServiceStatusView-BvuFCgT-.js} +2 -2
  16. package/dist/web-ui/assets/SettingsView-CB_w0Y2E.css +1 -0
  17. package/dist/web-ui/assets/SettingsView-W9bjQ9ly.js +1 -0
  18. package/dist/web-ui/assets/{SetupView-DcThD5bd.js → SetupView-D5KYolFQ.js} +1 -1
  19. package/dist/web-ui/assets/{config-B8sfBKCc.js → config-CX31TfJ4.js} +1 -1
  20. package/dist/web-ui/assets/format-7jzqzMS_.js +1 -0
  21. package/dist/web-ui/assets/{index-CZeCUjra.js → index-D6ydfwRk.js} +1 -1
  22. package/dist/web-ui/assets/{message-sILMvZIb.js → message-B022-tc2.js} +1 -1
  23. package/dist/web-ui/assets/providers-C6QKdfzy.js +1 -0
  24. package/dist/web-ui/assets/{router-BUuAm5No.js → router-Daxct41S.js} +2 -2
  25. package/dist/web-ui/assets/src-DLq1gsLr.js +1 -0
  26. package/dist/web-ui/assets/updateNote-CttDt8SZ.js +1 -0
  27. package/dist/web-ui/assets/useCopyToast-0dz9T4-H.js +1 -0
  28. package/dist/web-ui/assets/useManagerApi-DdgACgsq.js +1 -0
  29. package/dist/web-ui/assets/{useQuickRangeFilter-Bg2q_vMO.js → useQuickRangeFilter-D8oTOMUp.js} +1 -1
  30. package/dist/web-ui/assets/useToast-nQZ8k6t7.js +1 -0
  31. package/dist/web-ui/index.html +3 -3
  32. package/package.json +4 -1
  33. package/dist/cpa.js +0 -15
  34. package/dist/web-ui/assets/DashboardView-BzKKC4LZ.js +0 -1
  35. package/dist/web-ui/assets/LayoutView-BLjO8ed9.css +0 -1
  36. package/dist/web-ui/assets/LayoutView-BzBSYjz8.js +0 -1
  37. package/dist/web-ui/assets/LogsView-C2cZgB5T.js +0 -5
  38. package/dist/web-ui/assets/ProvidersView-BPOzev6x.js +0 -14
  39. package/dist/web-ui/assets/SettingsView-DygfiGG8.css +0 -1
  40. package/dist/web-ui/assets/SettingsView-XXHJh2h8.js +0 -1
  41. package/dist/web-ui/assets/format-CO5kjbrg.js +0 -1
  42. package/dist/web-ui/assets/providers-dvoMyAle.js +0 -1
  43. package/dist/web-ui/assets/useManagerApi-XPGaswMw.js +0 -1
  44. package/dist/web-ui/assets/useToast-BscapoHF.js +0 -1
  45. 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-BUuAm5No.js";import{t as C}from"./useManagerApi-XPGaswMw.js";import{t as w}from"./providers-dvoMyAle.js";import{C as T,f as E,n as D,p as O,r as k,t as A,u as j,w as M}from"./format-CO5kjbrg.js";import{n as N,t as re}from"./useQuickRangeFilter-Bg2q_vMO.js";x();function ie(e){let{loadError:t,run:n}=M(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 ae={class:`flex-col-gap`},oe={class:`kv-grid`},se={class:`kv-label`},ce={class:`kv-value`},le=[`onClick`],ue={class:`kv-item kv-span-2`},de={class:`kv-value`},fe={key:1,class:`kv-unit`},pe={class:`kv-item`},me={class:`kv-value`},he={class:`kv-unit`},ge={class:`kv-item`},_e={class:`kv-value`},ve={class:`flex-between card-header-wrap`},ye={class:`flex-gap-8`},be={class:`usage-grid`},xe={class:`usage-cell`},Se={class:`usage-num orange`},Ce={class:`usage-cell`},we={class:`usage-num blue`},Te={class:`usage-cell`},Ee={class:`usage-num green`},De={class:`usage-cell`},Oe={class:`usage-num purple`},ke={class:`usage-cell`},Ae={class:`usage-num purple`},je={key:0,class:`usage-cell`},Me={class:`usage-num gray`},Ne={class:`usage-cell`},Pe={class:`usage-num blue`},Fe={class:`usage-cell`},Ie=[`title`],Le={class:`usage-cell`},Re=[`title`],ze={key:0},Be=[`onClick`],Ve=[`title`],He=[`title`],P=n({__name:`DashboardView`,setup(n){let l=w(),{copyWithToast:u}=T(),{loadError:x,track:M,retry:P}=ie(),Ue={local:`本机 API 地址`,lan:`局域网地址`,other:`API 地址`},F=c(null),I=c(!0),L=c(``),{rangeKey:R,dateRange:z,onRangeChange:We}=re(()=>B(),`today`),Ge=()=>{R.value=``,B()},Ke=i(()=>{let e=new Set;for(let t of l.suppliers)for(let n of t.models)e.add(n.modelName);if(F.value?.models)for(let t of F.value.models)e.add(t.model);return[...e].sort()}),qe=N(),B=M(async()=>{let e=qe();I.value=!0;try{let t=new URLSearchParams;L.value&&t.set(`model`,L.value),z.value?.length===2&&(t.set(`startDate`,z.value[0]),t.set(`endDate`,z.value[1]));let n=t.toString(),r=await f.get(`/api/usage${n?`?${n}`:``}`);if(!e())return;F.value=r}catch(t){if(!e())return;throw t}finally{e()&&(I.value=!1)}}),Je=N(),V=M(async()=>{let e=Je();try{await Promise.all([B(),l.loadProviders()])}catch(t){if(!e())return;throw t}finally{e()&&(I.value=!1)}}),Ye=()=>P(V),H=window.location.hostname,U=Number(window.location.port)||null,W=i(()=>k({protocol:window.location.protocol,hostname:H,port:U})),G=c(null),K=c(null),q=c(!1),J=c(!0),Y=c(Date.now()),X=c(null),Z=c([]),Q=i(()=>X.value??U),Xe=e=>k({protocol:`http:`,hostname:e,port:Q.value}),Ze=i(()=>H===`127.0.0.1`||H===`::1`||H===`localhost`?`local`:Z.value.includes(H)?`lan`:`other`),$=i(()=>Q.value?Z.value.map(Xe).filter(e=>e!==W.value):[]),Qe=i(()=>{let e=Q.value?Xe(`127.0.0.1`):``;return e!==``&&e!==W.value?e:``}),$e=i(()=>{let e=[];return Ze.value===`lan`?e.push({label:`局域网地址`,values:[W.value,...$.value]}):(e.push({label:Ue[Ze.value],values:[W.value]}),$.value.length>0&&e.push({label:`局域网地址`,values:$.value})),Qe.value!==``&&e.push({label:`本机 API 地址`,values:[Qe.value]}),e.map((t,n)=>({...t,span2:e.length%2==1&&n===e.length-1}))}),et=async()=>{let[e,t]=await Promise.allSettled([C.processes(),f.get(`/api/status`)]);if(J.value=!1,e.status===`fulfilled`&&(G.value=e.value[0]??null),t.status===`rejected`){K.value=null,q.value=!0;return}let n=t.value?.masterKey;K.value=typeof n==`string`?n:null,q.value=typeof n!=`string`;let r=t.value?.listenPort;X.value=typeof r==`number`&&r>0?r:null;let i=t.value?.lanAddresses;Z.value=Array.isArray(i)?i.filter(e=>typeof e==`string`):[],Y.value=Date.now()},tt=e=>{if(!e.startedAt)return`-`;let t=Math.max(0,Math.floor((Y.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(` `)},nt=i(()=>q.value?`获取失败,请刷新重试`:K.value===null?`-`:`未设置(/v1 免鉴权)`),rt;return d(()=>{V(),et(),rt=window.setInterval(et,1e4)}),s(()=>window.clearInterval(rt)),(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`),T=g(`el-table`),k=g(`el-empty`),M=ee(`loading`);return m(),r(`div`,ae,[o(x)?(m(),e(c,{key:0,title:o(x),type:`error`,"show-icon":``,closable:!1},{default:y(()=>[t(s,{size:`small`,onClick:Ye},{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`,oe,[(m(!0),r(S,null,b($e.value,e=>(m(),r(`div`,{key:e.label+e.values[0],class:ne([`kv-item`,{"kv-span-2":e.span2}])},[v(`div`,se,h(e.label),1),v(`div`,ce,[(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,le)]))),128))])],2))),128)),v(`div`,ue,[i[6]||=v(`div`,{class:`kv-label`},`API 密钥`,-1),v(`div`,de,[K.value?(m(),r(`span`,{key:0,class:`copy-text`,onClick:i[0]||=e=>o(u)(K.value)},h(K.value),1)):_(``,!0),K.value?(m(),r(`span`,fe,`(/v1 需 Bearer 认证)`)):(m(),r(S,{key:2},[a(h(nt.value),1)],64))])]),v(`div`,pe,[i[9]||=v(`div`,{class:`kv-label`},`运行状态`,-1),v(`div`,me,[G.value?(m(),r(S,{key:0},[i[7]||=v(`span`,{class:`status-dot running`},null,-1),i[8]||=a(`运行中 `,-1),v(`span`,he,`PID `+h(G.value.pid??`-`),1)],64)):(m(),r(S,{key:1},[a(`-`)],64))])]),v(`div`,ge,[i[10]||=v(`div`,{class:`kv-label`},`运行时长`,-1),v(`div`,_e,h(G.value?tt(G.value):`-`),1)])])),[[M,I.value||J.value]])]),_:1}),F.value?(m(),e(l,{key:1,shadow:`never`},{header:y(()=>[v(`div`,ve,[i[12]||=v(`span`,{class:`fw-600`},`用量统计`,-1),v(`div`,ye,[t(f,{modelValue:L.value,"onUpdate:modelValue":i[1]||=e=>L.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`220px`},onChange:o(B)},{default:y(()=>[(m(!0),r(S,null,b(Ke.value,t=>(m(),e(d,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`,`onChange`]),t(f,{modelValue:o(R),"onUpdate:modelValue":i[2]||=e=>p(R)?R.value=e:null,placeholder:`时间范围`,clearable:``,style:{width:`130px`},onChange:o(We)},{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(z),"onUpdate:modelValue":i[3]||=e=>p(z)?z.value=e:null,type:`daterange`,"range-separator":`至`,"start-placeholder":`开始日期`,"end-placeholder":`结束日期`,"value-format":`YYYY-MM-DD`,style:{width:`260px`},onChange:Ge},null,8,[`modelValue`]),t(s,{loading:I.value,onClick:o(B)},{default:y(()=>[...i[11]||=[a(`刷新`,-1)]]),_:1},8,[`loading`,`onClick`])])])]),default:y(()=>[v(`div`,be,[v(`div`,xe,[v(`div`,Se,h(o(E)(F.value.total.total_tokens)),1),i[13]||=v(`div`,{class:`usage-label`},`总 Token`,-1)]),v(`div`,Ce,[v(`div`,we,h(o(E)(F.value.total.input_tokens)),1),i[14]||=v(`div`,{class:`usage-label`},`输入 Token`,-1)]),v(`div`,Te,[v(`div`,Ee,h(o(E)(F.value.total.output_tokens)),1),i[15]||=v(`div`,{class:`usage-label`},`输出 Token`,-1)]),v(`div`,De,[v(`div`,Oe,h(o(E)(F.value.total.cache_read_tokens)),1),i[16]||=v(`div`,{class:`usage-label`},`缓存读取`,-1)]),v(`div`,ke,[v(`div`,Ae,h(F.value.total.cache_rate==null?`-`:F.value.total.cache_rate+`%`),1),i[17]||=v(`div`,{class:`usage-label`},`缓存命中率`,-1)]),F.value.logStorageMB==null?_(``,!0):(m(),r(`div`,je,[v(`div`,Me,h(F.value.logStorageMB),1),i[18]||=v(`div`,{class:`usage-label`},`数据目录占用 (MB)`,-1)])),v(`div`,Ne,[v(`div`,Pe,h(o(j)(F.value.total.avg_duration)),1),i[19]||=v(`div`,{class:`usage-label`},`平均耗时`,-1)]),v(`div`,Fe,[v(`div`,{class:`usage-num blue`,title:o(D)},h(o(j)(F.value.total.avg_ttft)),9,Ie),i[20]||=v(`div`,{class:`usage-label`},`平均首 Token`,-1)]),v(`div`,Le,[v(`div`,{class:`usage-num green`,title:o(A)},h(o(O)(F.value.total.tps)),9,Re),i[21]||=v(`div`,{class:`usage-label`},`平均生成速度`,-1)])]),F.value.models?.length?(m(),r(`div`,ze,[i[22]||=v(`div`,{class:`section-title`},`模型用量`,-1),t(T,{data:F.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,Be)]),_: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(j)(e.avg_duration)),1)]),_:1}),t(w,{label:`速度`,width:`130`,align:`center`},{default:y(({row:e})=>[v(`div`,{title:o(A)},h(o(O)(e.tps)),9,Ve),e.avg_ttft==null?_(``,!0):(m(),r(`div`,{key:0,class:`cell-sub`,title:o(D)},` 首 `+h(o(j)(e.avg_ttft)),9,He))]),_:1}),t(w,{label:`总 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(E)(e.total_tokens)),1)]),_:1}),t(w,{label:`输入 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(E)(e.input_tokens)),1)]),_:1}),t(w,{label:`输出 Token`,width:`140`,align:`center`},{default:y(({row:e})=>[a(h(o(E)(e.output_tokens)),1)]),_:1}),t(w,{label:`缓存读取`,width:`130`,align:`center`},{default:y(({row:e})=>[a(h(o(E)(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(k,{key:1,description:`暂无调用记录`,"image-size":60}))]),_:1})):_(``,!0)])}}});export{P 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-BUuAm5No.js";import{m as D}from"./message-sILMvZIb.js";import{n as O,t as k}from"./index-CZeCUjra.js";import{n as A,t as j}from"./useManagerApi-XPGaswMw.js";import{t as M}from"./useToast-BscapoHF.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-BUuAm5No.js";import{R as k,S as te}from"./message-sILMvZIb.js";import{n as A,t as j}from"./index-CZeCUjra.js";import{t as M}from"./providers-dvoMyAle.js";import{C as N,S as P,_ as F,a as I,c as L,f as R,g as z,h as B,i as ne,l as V,m as H,n as re,o as ie,p as ae,s as U,t as oe,u as W,w as se,x as ce}from"./format-CO5kjbrg.js";import{t as le}from"./useToast-BscapoHF.js";import{n as ue,t as de}from"./useQuickRangeFilter-Bg2q_vMO.js";u(),T(),d();var fe={class:`detail-content`},pe={key:0,class:`ip-link`},G={class:`ip-pop`},me={class:`ip-pop-row`},K={key:0,class:`ip-pop-row`},q={key:1,class:`ip-pop-error`},J={key:2},he=[`href`],ge={key:1},_e={key:1},Y=[`title`],ve=[`title`],ye={class:`error-text`},be={class:`pane-bar`},X={class:`json-block`},xe={class:`pane-bar`},Se={class:`json-block`},Z={class:`pane-bar`},Ce={class:`json-block`},Q={class:`pane-bar`},we={class:`json-block`},Te={class:`pane-bar`},$={class:`json-block`},Ee={class:`pane-bar`},De={class:`json-block`},Oe={class:`pane-bar`},ke={class:`json-block`},Ae={class:`pane-bar`},je={class:`json-block`},Me=j(r({__name:`LogDetailDialog`,setup(t,{expose:r}){let{copyWithToast:c}=N(),{loadError:u,run:d}=se(),f=l(!1),m=l(null),_=l(!1),S=l(`info`),w=l(!1),T=l(null),D=ue(),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(()=>H(m.value?.response?.inbound_request)),j=a(()=>H(m.value?.response?.upstream_request)),M=a(()=>z(m.value?.response?.upstream_response_text)),F=a(()=>(m.value?.response?.upstream_stream_frames||[]).join(`
2
-
3
- `)),I=a(()=>H(m.value?.response?.client_response)),L=a(()=>(m.value?.response?.client_stream_frames||[]).join(`
4
-
5
- `)),V=a(()=>H(m.value?.request)),ie=a(()=>H(m.value?.response)),U=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`),N=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`,fe,[m.value?(h(),e(N,{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(B)(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`,pe,[n(D,{placement:`right`,width:`240`,trigger:`click`,onShow:r[0]||=e=>U(m.value)},{reference:C(()=>[x(`span`,null,g(m.value.ip),1)]),default:C(()=>[v((h(),i(`div`,G,[m.value._ipInfo?(h(),i(E,{key:0},[x(`div`,me,[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`,K,[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`,q,g(m.value._ipInfoError),1)):(h(),i(`span`,J,`查询中...`)),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,he)])),[[H,w.value]])]),_:1})])):(h(),i(`span`,ge,`-`))]),_: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`,_e,`-`)):(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(R)(m.value.input_tokens??0)),1)]),_:1}),n(d,{label:`输出 Token`},{default:C(()=>[o(g(s(R)(m.value.output_tokens??0)),1)]),_:1}),n(d,{label:`缓存读取`},{default:C(()=>[o(g(s(R)(m.value.cache_read_tokens??0)),1)]),_:1}),n(d,{label:`请求耗时`},{default:C(()=>[o(g(s(W)(m.value.duration)),1)]),_:1}),n(d,{label:`缓存命中率`},{default:C(()=>[o(g(s(ne)(m.value)),1)]),_:1}),n(d,{label:`首 Token`},{default:C(()=>[x(`span`,{title:s(re)},g(s(W)(m.value.ttft)),9,Y)]),_:1}),n(d,{label:`生成速度`},{default:C(()=>[x(`span`,{title:s(oe)},g(s(ae)(m.value.tps)),9,ve)]),_:1}),m.value.error?(h(),e(d,{key:0,label:`错误`,span:2},{default:C(()=>[x(`span`,ye,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`,be,[n(a,{size:`small`,class:`copy-btn`,onClick:r[2]||=e=>s(c)(A.value)},{default:C(()=>[...r[15]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,X,g(s(P)(A.value)),1)]),_:1}),n(k,{lazy:``,label:`转发上游的请求`,name:`upstreamReq`},{default:C(()=>[x(`div`,xe,[n(a,{size:`small`,class:`copy-btn`,onClick:r[3]||=e=>s(c)(j.value)},{default:C(()=>[...r[16]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,Se,g(s(P)(j.value)),1)]),_:1}),m.value.response.upstream_response_text?(h(),e(k,{key:0,lazy:``,label:`上游响应(原始)`,name:`upstreamRes`},{default:C(()=>[x(`div`,Z,[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`,Ce,g(s(P)(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`,Q,[n(a,{size:`small`,class:`copy-btn`,onClick:r[5]||=e=>s(c)(F.value)},{default:C(()=>[...r[18]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,we,g(s(P)(F.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`,Te,[n(a,{size:`small`,class:`copy-btn`,onClick:r[6]||=e=>s(c)(I.value)},{default:C(()=>[...r[19]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,$,g(s(P)(I.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`,Ee,[n(a,{size:`small`,class:`copy-btn`,onClick:r[7]||=e=>s(c)(L.value)},{default:C(()=>[...r[20]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,De,g(s(P)(L.value)),1)]),_:1},8,[`label`])):b(``,!0)],64)):(h(),i(E,{key:1},[n(k,{lazy:``,label:`请求体`,name:`request`},{default:C(()=>[x(`div`,Oe,[n(a,{size:`small`,class:`copy-btn`,onClick:r[8]||=e=>s(c)(V.value)},{default:C(()=>[...r[21]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,ke,g(s(P)(V.value)),1)]),_:1}),n(k,{lazy:``,label:`响应体`,name:`response`},{default:C(()=>[x(`div`,Ae,[n(a,{size:`small`,class:`copy-btn`,onClick:r[9]||=e=>s(c)(ie.value)},{default:C(()=>[...r[22]||=[o(` 复制 `,-1)]]),_:1})]),x(`pre`,je,g(s(P)(ie.value)),1)]),_:1})],64))]),_:1},8,[`modelValue`])):b(``,!0)])),[[H,_.value]])]),_:1},8,[`modelValue`])}}}),[[`__scopeId`,`data-v-7e1ff197`]]);u(),T(),d(),S();var Ne={class:`session-table`},Pe={class:`group-detail`},Fe={class:`cell-sub`},Ie=[`title`],Le=[`title`],Re={key:0,class:`detail-error`},ze={class:`detail-footer`},Be={class:`detail-count`},Ve=[`title`,`onClick`],He={class:`cell-sub`},Ue={class:`cell-sub`},We=50,Ge=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}=N(),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(We)};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`,Ne,[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:``,class:`dense-table`,onExpandChange:te,onRowClick:j},{default:C(()=>[n(l,{type:`expand`},{default:C(({row:t})=>[x(`div`,Pe,[v((h(),e(p,{data:O(t).items,size:`small`,stripe:``,class:`dense-table`},{default:C(()=>[n(l,{label:`时间`,width:`96`,align:`center`},{default:C(({row:e})=>[x(`div`,null,g(s(L)(e.time)),1),x(`div`,Fe,g(s(V)(e.time)),1)]),_:1}),n(l,{prop:`model`,label:`模型`,"min-width":`150`,align:`center`,"show-overflow-tooltip":``}),n(l,{label:`客户端`,"min-width":`96`,align:`center`,"show-overflow-tooltip":``},{default:C(({row:e})=>[o(g(s(I)(e)),1)]),_:1}),n(l,{label:`状态`,width:`60`,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:`84`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.input_tokens??0)),1)]),_:1}),n(l,{label:`输出`,width:`78`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.output_tokens??0)),1)]),_:1}),n(l,{label:`缓存读取`,width:`84`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.cache_read_tokens??0)),1)]),_:1}),n(l,{label:`缓存命中率`,width:`88`,align:`center`},{default:C(({row:e})=>[o(g(s(ne)(e)),1)]),_:1}),n(l,{label:`请求耗时`,width:`74`,align:`center`},{default:C(({row:e})=>[o(g(s(W)(e.duration)),1)]),_:1}),n(l,{label:`速度`,width:`96`,align:`center`},{default:C(({row:e})=>[x(`div`,{title:s(oe)},g(s(ae)(e.tps)),9,Ie),e.ttft==null?b(``,!0):(h(),i(`div`,{key:0,class:`cell-sub`,title:s(re)},` 首 `+g(s(W)(e.ttft)),9,Le))]),_:1}),n(l,{label:`详情`,width:`52`,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`,Re,[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`,ze,[x(`span`,Be,`已显示 `+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:`100`,align:`center`},{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(ce)(t.session_id)),9,Ve)):(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:`70`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.calls)),1)]),_:1}),n(l,{label:`模型`,"min-width":`150`,align:`center`,"show-overflow-tooltip":``},{default:C(({row:e})=>[o(g(s(F)(e.models)),1)]),_:1}),n(l,{label:`客户端`,"min-width":`130`,align:`center`,"show-overflow-tooltip":``},{default:C(({row:e})=>[o(g(s(U)(e.clients)),1)]),_:1}),n(l,{label:`输入`,width:`100`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.input_tokens)),1)]),_:1}),n(l,{label:`输出`,width:`90`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.output_tokens)),1)]),_:1}),n(l,{label:`缓存读取`,width:`100`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.cache_read_tokens)),1)]),_:1}),n(l,{label:`首次请求`,width:`96`,align:`center`},{default:C(({row:e})=>[x(`div`,null,g(s(L)(e.first_time)),1),x(`div`,He,g(s(V)(e.first_time)),1)]),_:1}),n(l,{label:`最后请求`,width:`96`,align:`center`},{default:C(({row:e})=>[x(`div`,null,g(s(L)(e.last_time)),1),x(`div`,Ue,g(s(V)(e.last_time)),1)]),_:1})]),_:1},8,[`data`])),[[E,r.loading]]):(h(),e(_,{key:1,description:`当前筛选下没有日志`}))])}}}),[[`__scopeId`,`data-v-1a4244ff`]]);u(),T(),S(),d();var Ke={class:`logs-page`},qe={class:`filter-bar`},Je={class:`table-wrap`},Ye=[`onClick`],Xe={key:1},Ze={class:`cell-sub`},Qe=[`title`,`onClick`],$e={key:1},et=[`title`,`onClick`],tt={key:1},nt=[`title`],rt=[`title`],it={class:`pagination-bar`},at=j(r({__name:`LogsView`,setup(t){let r=M(),{toast:c}=le(),{copyWithToast:u}=N(),{loadError:d,run:_}=se(),{rangeKey:S,dateRange:T,setRange:O,onRangeChange:j}=de(()=>$()),P=l(`2xx`),F=l(``),z=l(``),B=l(``),H=l(`session`),U=l([]),fe=l([]),pe=l(null),G=l(0),me=l(0),K=l(1),q=l(20),J=l(!1),he=l(null),ge=e=>{he.value?.open(e)},_e=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()}),Y=l([]),ve=a(()=>{let e=new Set(Y.value);for(let t of U.value)t.client&&e.add(t.client);return[...e].sort()}),ye=async()=>{try{let e=await p.get(`/api/logs/clients`);Y.value=e.clients||[]}catch{Y.value=[]}},be=e=>{S.value=``,T.value=e||null,$()},X=()=>{let e={};T.value&&T.value.length===2&&(e.startDate=T.value[0],e.endDate=T.value[1]),P.value&&(e.status=P.value),F.value&&(e.model=F.value),z.value&&(e.client=z.value);let t=B.value.trim();return t&&(e.sessionId=t),e},xe=a(()=>X()),Se=ue(),Z=()=>_(async()=>{let e=Se();J.value=!0;try{let t={...X(),page:String(K.value),pageSize:String(q.value)};if(H.value===`session`){let n=new URLSearchParams(t).toString(),r=await p.get(`/api/logs/sessions?`+n);if(!e())return;fe.value=r.groups||[],pe.value=r.noSession??null,G.value=r.total||0,me.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||[],G.value=r.total||0}}catch(t){if(!e())return;throw t}finally{e()&&(J.value=!1)}}),Ce=e=>{H.value!==e&&(H.value=e,K.value=1,q.value=H.value===`session`?20:50,Z())},Q=l(!1),we=a(()=>H.value===`session`?me.value:G.value),Te=async()=>{if(Q.value||we.value===0)return;let e=H.value===`session`?`(按筛选行数计,含「无 Session」组)`:``;try{await A.confirm(`将永久清理当前筛选条件下的 ${we.value} 条日志${e},清理后不可恢复,请谨慎操作!`,`清理确认`,{confirmButtonText:`确认清理`,cancelButtonText:`取消`,type:`warning`})}catch{return}Q.value=!0;try{let e=new URLSearchParams(X()).toString(),t=await p.post(`/api/logs/clear?`+e,{});c(`已清理 ${t.deleted??0} 条日志`,`success`),K.value>1&&(K.value=1),Z()}catch(e){c(e.message||`清理失败`,`error`)}finally{Q.value=!1}},$=()=>{K.value=1,ye(),Z()},Ee=()=>{S.value=`today`,T.value=null,P.value=`2xx`,F.value=``,z.value=``,B.value=``,K.value=1,q.value=H.value===`session`?20:50,O(`today`)};return f(()=>{r.loadProviders().catch(()=>{}),ye(),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`),N=y(`el-table-column`),se=y(`el-tag`),le=y(`el-table`),ue=y(`el-pagination`),de=ee(`loading`);return h(),i(`div`,Ke,[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:Z},{default:C(()=>[...r[10]||=[o(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):b(``,!0),n(M,{shadow:`never`},{default:C(()=>[x(`div`,qe,[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:be},null,8,[`modelValue`]),n(f,{modelValue:P.value,"onUpdate:modelValue":r[2]||=e=>P.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:F.value,"onUpdate:modelValue":r[3]||=e=>F.value=e,placeholder:`全部模型`,clearable:``,filterable:``,style:{width:`176px`},onChange:$},{default:C(()=>[(h(!0),i(E,null,w(_e.value,t=>(h(),e(l,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`]),n(f,{modelValue:z.value,"onUpdate:modelValue":r[4]||=e=>z.value=e,placeholder:`全部客户端`,clearable:``,filterable:``,style:{width:`130px`},onChange:$},{default:C(()=>[(h(!0),i(E,null,w(ve.value,t=>(h(),e(l,{key:t,label:t,value:t},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`]),n(_,{modelValue:B.value,"onUpdate:modelValue":r[5]||=e=>B.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:H.value===`session`?`primary`:`default`,icon:s(te),"aria-label":`按会话分组`,onClick:r[6]||=e=>Ce(`session`)},null,8,[`type`,`icon`])]),_:1}),n(O,{content:`列表`,placement:`top`,"show-after":300},{default:C(()=>[n(a,{type:H.value===`list`?`primary`:`default`,icon:s(k),"aria-label":`列表视图`,onClick:r[7]||=e=>Ce(`list`)},null,8,[`type`,`icon`])]),_:1})]),_:1}),n(a,{type:`primary`,onClick:$},{default:C(()=>[...r[11]||=[o(`搜索`,-1)]]),_:1}),n(a,{onClick:Ee},{default:C(()=>[...r[12]||=[o(`重置`,-1)]]),_:1})])]),_:1}),n(M,{shadow:`never`,class:`mt-16 table-card`},{default:C(()=>[x(`div`,Je,[H.value===`list`?v((h(),e(le,{key:0,data:U.value,stripe:``,height:`100%`,class:`dense-table`},{default:C(()=>[n(N,{prop:`id`,label:`ID`,width:`66`,align:`center`},{default:C(({row:e})=>[e.id==null?(h(),i(`span`,Xe,`-`)):(h(),i(`span`,{key:0,class:`request-id`,title:`点击复制(日志 id 同时是响应头 x-request-id,可用于关联控制台日志与检索)`,onClick:t=>s(u)(String(e.id))},g(e.id),9,Ye))]),_:1}),n(N,{prop:`time`,label:`时间`,width:`96`,align:`center`},{default:C(({row:e})=>[x(`div`,null,g(s(L)(e.time)),1),x(`div`,Ze,g(s(V)(e.time)),1)]),_:1}),n(N,{prop:`model`,label:`模型`,"min-width":`150`,align:`center`,"show-overflow-tooltip":``}),n(N,{label:`客户端`,"min-width":`96`,align:`center`},{default:C(({row:e})=>[e.client||e.user_agent?(h(),i(`span`,{key:0,class:`request-id`,title:s(ie)(e),onClick:t=>s(u)(e.user_agent||e.client)},g(s(I)(e)),9,Qe)):(h(),i(`span`,$e,`-`))]),_:1}),n(N,{label:`Session`,width:`88`,align:`center`},{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(ce)(e.session_id)),9,et)):(h(),i(`span`,tt,`-`))]),_:1}),n(N,{label:`输入`,width:`84`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.input_tokens??0)),1)]),_:1}),n(N,{label:`输出`,width:`78`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.output_tokens??0)),1)]),_:1}),n(N,{label:`缓存读取`,width:`84`,align:`center`},{default:C(({row:e})=>[o(g(s(R)(e.cache_read_tokens??0)),1)]),_:1}),n(N,{label:`缓存命中率`,width:`88`,align:`center`},{default:C(({row:e})=>[x(`span`,null,g(s(ne)(e)),1)]),_:1}),n(N,{label:`请求耗时`,width:`74`,align:`center`},{default:C(({row:e})=>[o(g(s(W)(e.duration)),1)]),_:1}),n(N,{label:`速度`,width:`96`,align:`center`},{default:C(({row:e})=>[x(`div`,{title:s(oe)},g(s(ae)(e.tps)),9,nt),e.ttft==null?b(``,!0):(h(),i(`div`,{key:0,class:`cell-sub`,title:s(re)},`首 `+g(s(W)(e.ttft)),9,rt))]),_:1}),n(N,{prop:`status`,label:`状态`,width:`60`,align:`center`},{default:C(({row:e})=>[n(se,{size:`small`,type:e.status>=400?`danger`:e.status>=300?`warning`:`success`},{default:C(()=>[o(g(e.status),1)]),_:2},1032,[`type`])]),_:1}),n(N,{label:`详情`,width:`52`,align:`center`,fixed:`right`},{default:C(({row:e})=>[n(a,{link:``,type:`primary`,onClick:t=>ge(e)},{default:C(()=>[...r[13]||=[o(`查看`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`])),[[de,J.value]]):b(``,!0),H.value===`session`?(h(),e(Ge,{key:1,groups:fe.value,"no-session":pe.value,loading:J.value,"filter-params":xe.value,onOpenDetail:ge},null,8,[`groups`,`no-session`,`loading`,`filter-params`])):b(``,!0)]),x(`div`,it,[n(a,{type:`danger`,plain:``,size:`small`,loading:Q.value,disabled:we.value===0,onClick:Te},{default:C(()=>[...r[14]||=[o(`清理已筛选日志`,-1)]]),_:1},8,[`loading`,`disabled`]),n(ue,{class:`push-right`,"current-page":K.value,"onUpdate:currentPage":r[8]||=e=>K.value=e,"page-size":q.value,"onUpdate:pageSize":r[9]||=e=>q.value=e,total:G.value,"page-sizes":[20,50,100,200],layout:`total, sizes, prev, pager, next`,onCurrentChange:Z,onSizeChange:Z},null,8,[`current-page`,`page-size`,`total`])])]),_:1}),n(Me,{ref_key:`logDetailRef`,ref:he},null,512)])}}}),[[`__scopeId`,`data-v-8caf26b0`]]);export{at as default};