Signs in to Huawei Cloud CodeArts (华为云码道, the CodeArts Agent coding plans: Trial,
personal and enterprise credit plans) and serves its models — GLM, DeepSeek, openPangu and
more — in OpenCode and magpie. Provider id: codearts.
Unofficial. This package is not affiliated with, authorized or endorsed by Huawei, Huawei Cloud or CodeArts; their names and marks belong to their owners. It talks to the non-public APIs the CodeArts client uses and identifies itself the way that client does (including claiming the daily free benefit and check-in), which may not be allowed by Huawei Cloud's terms of service, and those APIs may change at any time. Use it at your own risk, including the risk of restrictions on your account.
magpie plugin add @magpie-community/opencode-codearts-auth
magpie plugin login codeartsor install it from magpie's Plugins tab and sign in there.
Sign in with Huawei Cloud opens Huawei Cloud's consent page. The plugin listens on a
loopback port (127.0.0.1, ≥ 10000) for the redirect and exchanges the code at Huawei Cloud
STS — a PKCE flow whose token requests carry an ES256 DPoP proof, as the CodeArts client does.
STS answers with temporary AK/SK/security-token credentials and a refresh token. The callback
server takes one GET to /oauth/callback, exactly; one that comes back without a code (the
portal's error) fails the sign-in at once.
Where it is kept: the whole credential (AK/SK/security token, expiry, refresh token, the
PKCE verifier and the DPoP private key) is a JSON string in the account's access field, in
magpie's (or OpenCode's) own account store. auth.refresh renews it 30 minutes before it
expires, reusing the same verifier and DPoP key; a stale credential met on a request
(401, APIG.0602) is renewed once and the request sent again. A refresh token is spent once
per account, however many loaders ask; a renewal that only fails for now (STS unreachable)
answers 503 and keeps the sign-in, and only one STS turns away for good marks it.
The card's name: the account is shown by its phone number (138****8000, masked the way
the other magpie cards mask theirs), read once after signing in from Huawei Cloud IAM —
GET https://iam.cn-north-4.myhuaweicloud.com/v3.0/OS-USER/users/{principal_id}, signed with
the same temporary credentials — and kept on the credential as user_phone. The refresh token
names the signer only by IAM's own ids (hw12323, and the URN
iam::<domain>:user:<name>), which read as an ID nobody can tell apart from another account's;
the account name is the fallback when the phone can't be read, and the URN never is.
accountId is the account's identity — the URN, as before — and it never changes: magpie
keys the user's own name for the account, its proxy, model picks and a gateway key's list by
it, so a re-sign-in and a renewal give the same value back. The card's name is usage's user,
which shows user_phone once a sign-in or renewal has read it. IAM is not one of the hosts the plugin signs forwarded requests for
(SIGNED_HOSTS): the one phone read is made by the plugin itself, for that one URL.
The account's live list: CodeArts' builtin models, plus the free models of its daily benefit
once today's benefit has been claimed (POST /api/v1/benefit/claim, once a Beijing day, as the
client does; a benefit not found on a day not yet claimed claims it too). Each model's credit
rate (the client's 「消耗系数」) is reported as magpie's rate,
with its reasoning flag and limits, from the account's main agent (build) model list. Before
signing in, a short built-in catalog stands in.
- Every request is signed with Huawei's SDK-HMAC-SHA256 using the temporary credentials, and
only for CodeArts' own two hosts,
snap-access.cn-north-4.myhuaweicloud.comandopengw.developer.huaweicloud.com: a request anywhere else (an overriddenapi) is refused before the credentials leave, and no signed or token request follows a redirect. - The gateway allows 3 concurrent sessions per account and tells them apart by
x-ot-session-id; the plugin sends one stable session id per account (and a fresh trace per request) like the client, keeps at most 3 chats in flight per account, retriesTM.00001041with backoff, and waits in the gateway's own queue (429+queue-status: queued) the way the client does. Only then does magpie get a429. Since 0.2.3, when magpie has another candidate after this request (x-magpie-fallback: 1), a queued request leaves the queue at once and answers503with the queue'sRetry-After("CodeArts queued the request; try again in 20s"), and magpie asks the next. - Chats always go upstream as streams — CodeArts meters only streamed answers — and are folded
back into one
chat.completionwhen the caller asked for JSON. thinking: { type: "enabled" }is sent unless the caller set it, so the reasoning lands inreasoning_contentandcontentis only the reply.- Errors the gateway puts inside a
200stream (spent quota, unknown model) come back as429/400/502with the vendor's words. Thecodearts/prefix is stripped and output budgets are clamped to 65536. - CodeArts takes tool names of up to 64 characters. A longer one (an MCP tool such as
mcp__plugin_android-emulator_android-emulator__android_discover_project) goes as its first 55 characters,_and 8 hex of its SHA-256, and the tool calls in the answer, streamed or not, carry the agent's own name again. - Every model is listed as text only (
modalities.input: ["text"],image: false): CodeArts answers an image withInferHub.001001020.406"The request model is not multimodal". Since 0.2.4 magpie is told so, and describes an image for the model or leaves it out. That refusal, inside a200or with any status, comes back as a400, not a502an agent would ask again.
- Usage: the credit buckets of
snap-manager/v1/statistics/plugin(only the package total pauses the account; the basic / on-demand / bonus buckets are shown aside) and the free daily token pool. - When each credit batch expires is read from the CodeArts console's own calls
(
snap-manager/v1/package/credit/page,v1/ops/credit/*); when those can't be read, the plugin falls back to a small ledger of the check-ins it claimed,~/.config/magpie/codearts-checkins.json(orMAGPIE_CODEARTS_LEDGER). This part is still being checked against more accounts — trust the CodeArts console where they differ. auth.checkin: the client's 「限时福利 → 每日领取」 —GET /v1/ops/delivery?channel=IDE,POST /v1/ops/claim, thenPOST /v1/ops/confirmwhen the claim answers an id. A claim whose confirm failed is kept in that ledger for the day and confirmed at the next check-in; one the client leaves unconfirmed (id: null) never is. Turn on Auto check-in for CodeArts under Settings → Usage → Plugins.
| Option | Default | What it does |
|---|---|---|
maxInflight |
3 |
chats in flight per account; it can only lower the vendor's cap of 3 sessions |
retryBudgetMs |
150000 |
how long to retry TM.00001041 before answering 429 |
retryDelays |
[2000,4000,6000,8000,10000] |
retry waits in ms (the last repeats) |
queueBudgetMs |
300000 |
how long to wait in the gateway's queue |
thinking |
true |
false stops adding thinking: { type: "enabled" } |
First written by yuweihao17; this version carries the fixes of yuweihao17/codearts#8. It builds on the measurements and code of HuHong-Tao and ReachForStar, and on the CodeArts channel of Ebony-Vinyl/dsh-our-free-model.
接入**华为云码道(CodeArts Agent)**的编码套餐(体验版、个人与企业积分套餐),在 OpenCode 和
magpie 里使用其 GLM、DeepSeek、openPangu 等模型。provider id:codearts。
非官方插件:与华为、华为云及 CodeArts(码道)没有任何关联,也未获其授权或认可。插件调用的是 码道客户端使用的非公开接口,并以与官方客户端相同的方式标识自己(含自动领取每日免费权益与签到), 这可能不符合华为云的服务条款,接口也可能随时变更。使用风险(包括账号受限)由使用者自行承担。
- 登录:华为云 OAuth(PKCE + DPoP),本机
127.0.0.1(端口 ≥ 10000)接收回调,向 STS 换取临时 AK/SK/security-token;回调只接受精确的/oauth/callbackGET,回调不带 code(portal 报错)时立即判定登录失败。完整凭据(含 refresh_token、PKCE verifier、DPoP 私钥)以 JSON 存在账号的access字段里,保存在 magpie / OpenCode 自己的账号存储中;过期前 30 分钟自动续期,请求遇到临时凭据 过期时就地续期并重发一次。同一账号的 refresh_token 只用一次;续期只是暂时失败(如 STS 连不上)时返回503并保留登录,只有被 STS 明确拒绝才标记需要重新登录。账号标识取自 refresh_token,重复登录不会多出账号。 - 模型:账号实时的内置模型列表;领取当日免费权益成功后,再加上免费模型(每个北京自然日领一次,与
客户端一致;当天还没领取时遇到
benefit not found也会先领取再重发)。每个模型的「消耗系数」作为 magpie 的倍率上报,来自账号主智能体(build)的模型列表。 - 请求:SDK-HMAC-SHA256 签名,只签给码道自己的两个主机(
snap-access.cn-north-4.myhuaweicloud.com、opengw.developer.huaweicloud.com),发往其他地址(如改过的api)的请求在凭据发出前就被拒绝,签名请求和令牌请求都不跟随重定向;像客户端一样发送x-ot-session-id会话头(每账号一个会话),账号内 在途请求不超过 3 个,TM.00001041退避重试,网关排队时按客户端的方式等待(0.2.3 起,magpie 在这个请求之后还有别的账号、供应商或路由组成员时(x-magpie-fallback: 1),排队的请求立即退出队列并以503加队列的Retry-After回答,magpie 随即改问下一个);总是以流式请求上游(码道 只对流式回答计量积分),调用方要非流式时折叠回 JSON;默认注入thinking: { type: "enabled" },思考与 正文分开;200 里内嵌的错误换算为429/400/502并带厂商原话;码道只接受不超过 64 个字符的工具名, 更长的(如 MCP 工具名)发出时缩为前 55 个字符 +_+ 8 位 SHA-256,回答(流式与非流式)里的工具调用再换回原名。 0.2.4 起所有模型都声明为只收文本(码道对图片回InferHub.001001020.406「The request model is not multimodal」), magpie 会替模型描述图片或把图片略去;这个拒绝不论放在 200 里还是带别的状态码,都换算为400,而不是让智能体反复重试的502。 - 用量与签到:总积分决定账号是否可用,其余积分桶只做明细;另有每日免费额度窗口。各批积分的到期
时间读自码道控制台同一批接口,读不到时退回插件的签到账本
~/.config/magpie/codearts-checkins.json(这部分仍在用更多账号验证,请以控制台为准)。auth.checkin与客户端「限时福利 → 每日领取」一致 (插件领取后确认失败的,当天记在签到账本里,下次签到时补确认;客户端本就不确认的id: null领取不会被确认), 在 设置 → 用量 → Plugins 打开「每日自动签到」即可。 - 致谢:原作者 yuweihao17;HuHong-Tao、ReachForStar 的 实测与实现;Ebony-Vinyl/dsh-our-free-model。
MIT — see LICENSE.