From 5b3bb2635a7a155a35ce71c28e44818a617e207f Mon Sep 17 00:00:00 2001
From: yoruuuchan <1587761204@qq.com>
Date: Thu, 29 Oct 2026 13:04:11 +0900
Subject: [PATCH 01/11] =?UTF-8?q?feat(providers):=20add=20CodeArts=20(?=
=?UTF-8?q?=E7=A0=81=E9=81=93)=20adapter?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 11 +-
README_EN.md | 11 +-
changelog/unreleased/codearts-provider.md | 7 +
docs/ARCHITECTURE_SUMMARY.md | 5 +-
frontend/src/components/AddAccountModal.tsx | 16 +-
frontend/src/i18n/messages.ts | 8 +-
frontend/src/lib/provider.ts | 8 +
internal/app/app.go | 2 +
internal/providers/codearts/NOTICE | 26 +
internal/providers/codearts/catalog.go | 460 +++++++++++++++++
internal/providers/codearts/chat.go | 296 +++++++++++
internal/providers/codearts/checkin.go | 222 ++++++++
internal/providers/codearts/client.go | 485 ++++++++++++++++++
internal/providers/codearts/codearts_test.go | 387 ++++++++++++++
internal/providers/codearts/constants.go | 83 +++
internal/providers/codearts/credential.go | 300 +++++++++++
internal/providers/codearts/doc.go | 73 +++
internal/providers/codearts/dpop.go | 123 +++++
internal/providers/codearts/errors.go | 128 +++++
internal/providers/codearts/import.go | 23 +
internal/providers/codearts/oauth.go | 374 ++++++++++++++
internal/providers/codearts/payload.go | 305 +++++++++++
internal/providers/codearts/quota.go | 246 +++++++++
.../providers/codearts/s04_interfaces_test.go | 60 +++
internal/providers/codearts/signer.go | 120 +++++
internal/providers/codearts/sse.go | 458 +++++++++++++++++
internal/providers/registry.go | 31 +-
...hart-B-HmzR8M.js => AreaChart-C0mk2RpN.js} | 2 +-
.../static/assets/CartesianChart-C36ZX62E.js | 21 +
.../static/assets/CartesianChart-D9Qz51Q6.js | 21 -
...hart-B2R12QhR.js => CostChart-DBx6RL9U.js} | 2 +-
...-BKHIKlZl.js => LiveSparkline-D4Z7e4mF.js} | 2 +-
...t-C_J3rzAT.js => TrafficChart-BU-PbGSj.js} | 2 +-
.../webui/static/assets/XAxis-CcjVCtOa.js | 33 --
.../webui/static/assets/XAxis-hz2I6mvW.js | 33 ++
.../webui/static/assets/index-C-bfWHJD.css | 2 +
.../webui/static/assets/index-C5LslQI9.js | 96 ----
.../webui/static/assets/index-CfDkOa9Q.css | 2 -
.../webui/static/assets/index-DksXuUH8.js | 96 ++++
internal/webui/static/index.html | 4 +-
40 files changed, 4404 insertions(+), 180 deletions(-)
create mode 100644 changelog/unreleased/codearts-provider.md
create mode 100644 internal/providers/codearts/NOTICE
create mode 100644 internal/providers/codearts/catalog.go
create mode 100644 internal/providers/codearts/chat.go
create mode 100644 internal/providers/codearts/checkin.go
create mode 100644 internal/providers/codearts/client.go
create mode 100644 internal/providers/codearts/codearts_test.go
create mode 100644 internal/providers/codearts/constants.go
create mode 100644 internal/providers/codearts/credential.go
create mode 100644 internal/providers/codearts/doc.go
create mode 100644 internal/providers/codearts/dpop.go
create mode 100644 internal/providers/codearts/errors.go
create mode 100644 internal/providers/codearts/import.go
create mode 100644 internal/providers/codearts/oauth.go
create mode 100644 internal/providers/codearts/payload.go
create mode 100644 internal/providers/codearts/quota.go
create mode 100644 internal/providers/codearts/s04_interfaces_test.go
create mode 100644 internal/providers/codearts/signer.go
create mode 100644 internal/providers/codearts/sse.go
rename internal/webui/static/assets/{AreaChart-B-HmzR8M.js => AreaChart-C0mk2RpN.js} (60%)
create mode 100644 internal/webui/static/assets/CartesianChart-C36ZX62E.js
delete mode 100644 internal/webui/static/assets/CartesianChart-D9Qz51Q6.js
rename internal/webui/static/assets/{CostChart-B2R12QhR.js => CostChart-DBx6RL9U.js} (93%)
rename internal/webui/static/assets/{LiveSparkline-BKHIKlZl.js => LiveSparkline-D4Z7e4mF.js} (73%)
rename internal/webui/static/assets/{TrafficChart-C_J3rzAT.js => TrafficChart-BU-PbGSj.js} (73%)
delete mode 100644 internal/webui/static/assets/XAxis-CcjVCtOa.js
create mode 100644 internal/webui/static/assets/XAxis-hz2I6mvW.js
create mode 100644 internal/webui/static/assets/index-C-bfWHJD.css
delete mode 100644 internal/webui/static/assets/index-C5LslQI9.js
delete mode 100644 internal/webui/static/assets/index-CfDkOa9Q.css
create mode 100644 internal/webui/static/assets/index-DksXuUH8.js
diff --git a/README.md b/README.md
index 70130faf..4f79840d 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
**把你自己的登录态,变成一个本机 OpenAI 兼容 API**
-接入 **Qoder(国际版 / 国内版)**、**WorkBuddy(国际版 / 国内版)**、**Trae 国内版 Work**,以及实验性的 **Devin** 和 **Command Code**。
+接入 **Qoder(国际版 / 国内版)**、**WorkBuddy(国际版 / 国内版)**、**Trae 国内版 Work**,以及实验性的 **Devin**、**Command Code** 和 **华为云码道 CodeArts**。
用 Docker 部署,在 Web 控制台管理账号,再通过兼容 API 接入客户端。
@@ -26,9 +26,10 @@
- **兼容接口**:Chat Completions、Responses、Anthropic Messages 和模型列表,支持流式回复与函数工具调用。
- **多账号调度**:轮询、加权轮询、顺序填满,以及可选的同供应商最早到期优先(FEFO);保留自动选号、会话粘性、并发限制、冷却与故障切换。
- **统一控制台**:管理账号、模型、客户端密钥、代理设置,查看额度和请求日志。
+- **华为云码道(实验性)**:OAuth PKCE 登录后直连 snap-access 的 OpenAI 兼容接口,支持流式与工具调用,并读取套餐积分 / token 计量。
- **Docker 运维**:持久化账号数据;可选安装宿主机更新器,在控制台下载更新、确认升级和回滚。
-Qoder 国内版、WorkBuddy、Trae 的适配代码已实现,真账号验收仍未完成;Devin 与 Command Code 为实验性接入,不承诺生产可用。托管更新的真实升级 / 回滚验收也尚未完成。Kimi Code(中国区)已完成单账号端到端验收:设备码登录、模型发现、三种接口的对话 / 流式 / 工具调用 / 视觉,以及额度读取;多账号行为只有自动化测试覆盖。
+Qoder 国内版、WorkBuddy、Trae 的适配代码已实现,真账号验收仍未完成;Devin、Command Code 与华为云码道 CodeArts 为实验性接入,不承诺生产可用。托管更新的真实升级 / 回滚验收也尚未完成。Kimi Code(中国区)已完成单账号端到端验收:设备码登录、模型发现、三种接口的对话 / 流式 / 工具调用 / 视觉,以及额度读取;多账号行为只有自动化测试覆盖。码道 CodeArts 的 OAuth 登录、模型发现、对话与签到按上游协议实现,但真实账号端到端验收和签到验收仍待完成。
## 快速开始
@@ -63,7 +64,7 @@ API Key: <在 API keys 页面创建的客户端密钥>
{if(e??=10,n??=r===10?`s`:`,`,typeof n!=`function`&&(!(r%1)&&(n=Zf(n)).precision==null&&(n.trim=!0),n=lp(n)),e===1/0)return n;let o=Math.max(1,r*e/t.ticks().length);return e=>{let t=e/a(Math.round(i(e)));return t*r {var i=typeof l==`function`?l(e.value,r):e.value;return p===`width`?eE(eS(i,{fontSize:t,letterSpacing:n}),m,d):eS(i,{fontSize:t,letterSpacing:n})[p]},g=i[0],_=i[1],v=i.length>=2&&g!=null&&_!=null?le(_.coordinate-g.coordinate):1,y=tE(a,v,p);return c===`equidistantPreserveStart`?iE(v,y,h,i,o):c===`equidistantPreserveEnd`?aE(v,y,h,i,o):(f=c===`preserveStart`||c===`preserveStartEnd`?fE(v,y,h,i,o,c===`preserveStartEnd`):dE(v,y,h,i,o),f.filter(e=>e.isShow))}var mE=e=>{var t=e.ticks,n=e.label,r=e.labelGapWithTick,i=r===void 0?5:r,a=e.tickSize,o=a===void 0?0:a,s=e.tickMargin,c=s===void 0?0:s,l=0;if(t){Array.from(t).forEach(e=>{if(e){var t=e.getBoundingClientRect();t.width>l&&(l=t.width)}});var u=n?n.getBoundingClientRect().width:0,d=o+c,f=l+d+u+(n?i:0);return Math.round(f)}return 0},hE=e=>{var t=e.ticks,n=e.label,r=e.labelGapWithTick,i=r===void 0?5:r,a=e.tickSize,o=a===void 0?0:a,s=e.tickMargin,c=s===void 0?0:s,l=0;if(t){Array.from(t).forEach(e=>{if(e){var t=e.getBoundingClientRect();t.height>l&&(l=t.height)}});var u=n?n.getBoundingClientRect().height:0,d=o+c,f=l+d+u+(n?i:0);return Math.round(f)}return 0},gE=aa({name:`renderedTicks`,initialState:{xAxis:{},yAxis:{}},reducers:{setRenderedTicks:(e,t)=>{var n=t.payload,r=n.axisType,i=n.axisId,a=n.ticks;e[r][i]=B(a)},removeRenderedTicks:(e,t)=>{var n=t.payload,r=n.axisType,i=n.axisId;delete e[r][i]}}}),_E=gE.actions,vE=_E.setRenderedTicks,yE=_E.removeRenderedTicks,bE=gE.reducer,xE=[`axisLine`,`width`,`height`,`className`,`hide`,`ticks`,`axisType`,`axisId`];function SE(e,t){return DE(e)||EE(e,t)||wE(e,t)||CE()}function CE(){throw TypeError(`Invalid attempt to destructure non-iterable instance.
+In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function wE(e,t){if(e){if(typeof e==`string`)return TE(e,t);var n={}.toString.call(e).slice(8,-1);return n===`Object`&&e.constructor&&(n=e.constructor.name),n===`Map`||n===`Set`?Array.from(e):n===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?TE(e,t):void 0}}function TE(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n {if(e??=10,n??=r===10?`s`:`,`,typeof n!=`function`&&(!(r%1)&&(n=Yf(n)).precision==null&&(n.trim=!0),n=sp(n)),e===1/0)return n;let o=Math.max(1,r*e/t.ticks().length);return e=>{let t=e/a(Math.round(i(e)));return t*r0){for(var n,r,i=0,a=e[0].length,o;i0){for(var n=0,r=e[t[0]],i,a=r.length;n0)||!((a=(i=e[t[0]]).length)>0))){for(var n=0,r=1,i,a,o;r`radius`in e&&`startAngle`in e&&`endAngle`in e,At=(e,t)=>{if(!e||typeof e==`function`||typeof e==`boolean`)return null;var n=e;if((0,s.isValidElement)(e)&&(n=e.props),typeof n!=`object`&&typeof n!=`function`)return null;var r={};return Object.keys(n).forEach(e=>{l(e)&&typeof n[e]==`function`&&(r[e]=t||(t=>n[e](n,t)))}),r},jt=(e,t,n)=>r=>(e(t,n,r),null),Mt=(e,t,n)=>{if(e===null||typeof e!=`object`&&typeof e!=`function`)return null;var r=null;return Object.keys(e).forEach(i=>{var a=e[i];l(i)&&typeof a==`function`&&(r||={},r[i]=jt(a,t,n))}),r};function Nt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Pt(e){for(var t=1;tc||a===0)return null;var l=Sl(t),u=l.startAngle,d=l.endAngle,f=o,p;if(u<=d){for(;f>d;)f-=360;for(;f=u&&f<=d}else{for(;f>u;)f-=360;for(;f0))return[];if(e===t)return[e];let r=t=t)&&(n=t);else{let r=-1;for(let i of e)(i=t(i,++r,e))!=null&&(n=i)&&(n=i)}return n}function pd(e,t){let n;if(t===void 0)for(let t of e)t!=null&&(n>t||n===void 0&&t>=t)&&(n=t);else{let r=-1;for(let i of e)(i=t(i,++r,e))!=null&&(n>i||n===void 0&&i>=i)&&(n=i)}return n}function md(e,t,n=0,r=1/0,i){if(t=Math.floor(t),n=Math.floor(Math.max(0,n)),r=Math.floor(Math.min(e.length-1,r)),!(n<=t&&t<=r))return e;for(i=i===void 0?id:rd(i);r>n;){if(r-n>600){let a=r-n+1,o=t-n+1,s=Math.log(a),c=.5*Math.exp(2*s/3),l=.5*Math.sqrt(s*c*(a-c)/a)*(o-a/2<0?-1:1),u=Math.max(n,Math.floor(t-o*c/a+l)),d=Math.min(r,Math.floor(t+(a-o)*c/a+l));md(e,t,u,d,i)}let a=e[t],o=n,s=r;for(hd(e,n,t),i(e[r],a)>0&&hd(e,n,r);o0;)--s}i(e[n],a)===0?hd(e,n,s):(++s,hd(e,s,r)),s<=t&&(n=s+1),t<=s&&(r=s-1)}return e}function hd(e,t,n){let r=e[t];e[t]=e[n],e[n]=r}function gd(e,t,n){if(e=Float64Array.from(Yu(e,n)),!(!(r=e.length)||isNaN(t=+t))){if(t<=0||r<2)return pd(e);if(t>=1)return fd(e);var r,i=(r-1)*t,a=Math.floor(i),o=fd(md(e,a).subarray(0,a+1));return o+(pd(e.subarray(a+1))-o)*(i-a)}}function _d(e,t,n=Ju){if(!(!(r=e.length)||isNaN(t=+t))){if(t<=0||r<2)return+n(e[0],0,e);if(t>=1)return+n(e[r-1],r-1,e);var r,i=(r-1)*t,a=Math.floor(i),o=+n(e[a],a,e);return o+(+n(e[a+1],a+1,e)-o)*(i-a)}}function vd(e,t,n){e=+e,t=+t,n=(i=arguments.length)<2?(t=e,e=0,1):i<3?1:+n;for(var r=-1,i=Math.max(0,Math.ceil((t-e)/n))|0,a=Array(i);++r>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):n===8?Jd(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):n===4?Jd(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=Fd.exec(e))?new Zd(t[1],t[2],t[3],1):(t=Id.exec(e))?new Zd(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=Ld.exec(e))?Jd(t[1],t[2],t[3],t[4]):(t=Rd.exec(e))?Jd(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=zd.exec(e))?af(t[1],t[2]/100,t[3]/100,1):(t=Bd.exec(e))?af(t[1],t[2]/100,t[3]/100,t[4]):Vd.hasOwnProperty(e)?qd(Vd[e]):e===`transparent`?new Zd(NaN,NaN,NaN,0):null}function qd(e){return new Zd(e>>16&255,e>>8&255,e&255,1)}function Jd(e,t,n,r){return r<=0&&(e=t=n=NaN),new Zd(e,t,n,r)}function Yd(e){return e instanceof Od||(e=Kd(e)),e?(e=e.rgb(),new Zd(e.r,e.g,e.b,e.opacity)):new Zd}function Xd(e,t,n,r){return arguments.length===1?Yd(e):new Zd(e,t,n,r??1)}function Zd(e,t,n,r){this.r=+e,this.g=+t,this.b=+n,this.opacity=+r}Ed(Zd,Xd,Dd(Od,{brighter(e){return e=e==null?Ad:Ad**+e,new Zd(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?kd:kd**+e,new Zd(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new Zd(nf(this.r),nf(this.g),nf(this.b),tf(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Qd,formatHex:Qd,formatHex8:$d,formatRgb:ef,toString:ef}));function Qd(){return`#${rf(this.r)}${rf(this.g)}${rf(this.b)}`}function $d(){return`#${rf(this.r)}${rf(this.g)}${rf(this.b)}${rf((isNaN(this.opacity)?1:this.opacity)*255)}`}function ef(){let e=tf(this.opacity);return`${e===1?`rgb(`:`rgba(`}${nf(this.r)}, ${nf(this.g)}, ${nf(this.b)}${e===1?`)`:`, ${e})`}`}function tf(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function nf(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function rf(e){return e=nf(e),(e<16?`0`:``)+e.toString(16)}function af(e,t,n,r){return r<=0?e=t=n=NaN:n<=0||n>=1?e=t=NaN:t<=0&&(e=NaN),new cf(e,t,n,r)}function of(e){if(e instanceof cf)return new cf(e.h,e.s,e.l,e.opacity);if(e instanceof Od||(e=Kd(e)),!e)return new cf;if(e instanceof cf)return e;e=e.rgb();var t=e.r/255,n=e.g/255,r=e.b/255,i=Math.min(t,n,r),a=Math.max(t,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=t===a?(n-r)/s+(n