dsh-codearts 1.1.0 → 1.1.3

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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,53 @@
3
3
  本文件记录本插件的重要改动。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
4
4
  版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
5
5
 
6
+ ## [1.1.3] - 2026-10-26
7
+
8
+ ### 修复
9
+
10
+ - **与 billion-context 同用时账号被永久禁用,报「当前没有可用账号」(issue #1)**:
11
+ billion-context 拦下 SDK-HMAC-SHA256 签名请求做压缩、找不到重签凭据时在本地回 403
12
+ (`signed_request_requires_resign`),插件把它当凭据失效,账号被禁用且没有任何恢复
13
+ 路径。现在按 body 里的拒签标记识别这类本地拦截:不再禁用账号,直接回 400(宿主不会
14
+ 再拿它重试 5 次),报错里给出 `resign.passthrough` 的配置方法。带标记的 401/403 之外
15
+ 的真凭据失效行为不变。
16
+ - **重新登录救不回被禁用的账号**:`disabled` 以前只能靠重启清掉,`pool.sync()` 对同一
17
+ userId 保留运行时状态。现在登录成功(OAuth 与手工贴 token 两条路)会调用池的
18
+ `revive()`,清掉该账号的禁用/冷却/错误计数。
19
+ - **「没有可用账号」不再一概而论**:一个账号都选不出来时,报错分清原因——全禁用(401,
20
+ 附各号最后错误并提示重新登录)、全在冷却(429,附剩余秒数)、本地并发槽位全满
21
+ (429,说明每账号 2 个在飞上限)。
22
+ - **已登录却报「积分不可用:statistics HTTP 0 Failed to parse URL from [object
23
+ Request]」(模型清单同时变空,issue #2)**:出网原本是 `fetch(new Request(url, ...), {signal})`
24
+ ——邻居插件(如 IP 池出口路由)会把 `globalThis.fetch` 换成它自己那份 undici 的
25
+ fetch,而 `globalThis.Request` 还是另一份实例。undici 用 `instanceof` 认自己的
26
+ Request,认不出就当 URL 字符串处理,于是每条请求在出网之前抛错(HTTP 0)。现在
27
+ `Request` 只当签名的载体,出网统一走 `dispatch()`:交「字符串 URL + 已展开的普通
28
+ 头 + 原字节请求体」,7 处调用点一并收口。
29
+ - **选中 CodeArts 模型后每条消息都「本轮运行失败:Cannot read properties of undefined
30
+ (reading 'length')」(issue #2)**:`@earendil-works/pi-ai` 过去只写在 `peerDependencies`
31
+ (`>=0.84.2 <2.0.0`),区间不会被安装流程强制满足;插件自己没有 `node_modules` 时
32
+ import 直接落到 profile 顶层被别的插件 hoist 上来的旧版。旧版的 `estimateMessageTokens`
33
+ 没有 `role:"system"` 分支,而宿主(`dsh-llm-pi-ai` 0.2.1-rc.2 起)会把系统提示折叠成
34
+ 一条 content 为**字符串**的 system 消息交给 provider —— 字符串被按字符遍历,读到
35
+ `block.name.length` 就崩,且崩在出网之前。现在 pi-ai 移进 `dependencies`(`^1.3.0`,
36
+ 自带一份),并在启动时探测这份能不能估折叠后的 system 消息:不满足就在日志和积分
37
+ 卡片上明说「pi-ai 不兼容,需要 >= 1.3.0」,不再让每条消息各自崩在一个看不懂的
38
+ TypeError 上。
39
+
40
+ ## [1.1.1] - 2026-10-22
41
+
42
+ ### 修复
43
+
44
+ - **带思考档位的模型(GLM-5.2 / GLM-5.2-ArkTS-SPARK)每轮必失败,报
45
+ `Message role cannot empty`**:1.1.0 给这些模型声明了 `reasoning`,宿主 pi-ai 于是
46
+ 把系统提示从 `role:"system"` 换成 OpenAI 的新叫法 `role:"developer"` 发出来,
47
+ 华为网关只认 system/user/assistant/tool,认不出来就回这一句黑话。出口处统一把
48
+ `developer` 归一回 `system`,与档位无关(Default/High/Max 之前都必现)。
49
+ - 新增 `GET /api/codearts/debug`:回最近 8 次出站请求的**形状**摘要(消息条数、
50
+ 每条的 role 名、工具数),只含 role 名不含任何内容。上游的参数错误全是同一句
51
+ 黑话,没有这个就分不清是宿主发的还是插件拼的。
52
+
6
53
  ## [1.1.0] - 2026-10-21
7
54
 
8
55
  ### 新增
package/lib/bin.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { F as codeartsAccountsPath, M as isBenefitModel, N as CodeArtsAccountStore, d as fetchCallerIdentity, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker } from "./usage-Cie0IlC4.mjs";
2
+ import { I as codeartsAccountsPath, M as isBenefitModel, N as CodeArtsAccountStore, d as fetchCallerIdentity, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker } from "./usage-5YK7bW-e.mjs";
3
3
  import { existsSync, statSync } from "node:fs";
4
4
  //#region src/version.ts
5
- const CODEARTS_VERSION = "1.1.0";
5
+ const CODEARTS_VERSION = "1.1.3";
6
6
  //#endregion
7
7
  //#region src/bin.ts
8
8
  /**
@@ -33,70 +33,70 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
33
33
  document.head.appendChild(tag);
34
34
  }
35
35
  var CodeArtsPluginCard_module_css_default = {
36
- "accountRowActions": "xoziZG_accountRowActions",
37
- "accountHint": "xoziZG_accountHint",
38
- "choiceRow": "xoziZG_choiceRow",
39
- "manualSummary": "xoziZG_manualSummary",
40
- "accountCard": "xoziZG_accountCard",
41
- "modelName": "xoziZG_modelName",
42
- "name": "xoziZG_name",
43
- "tabs": "xoziZG_tabs",
44
- "actions": "xoziZG_actions",
45
- "accountToolbar": "xoziZG_accountToolbar",
46
- "creditRow": "xoziZG_creditRow",
47
- "modelRequests": "xoziZG_modelRequests",
48
- "usageBar": "xoziZG_usageBar",
49
- "manual": "xoziZG_manual",
50
- "error": "xoziZG_error",
51
- "meta": "xoziZG_meta",
52
- "accountEntry": "xoziZG_accountEntry",
53
- "area": "xoziZG_area",
54
- "tabPanel": "xoziZG_tabPanel",
55
- "card": "xoziZG_card",
56
- "field": "xoziZG_field",
36
+ "choices": "xoziZG_choices",
37
+ "claimAllRow": "xoziZG_claimAllRow",
38
+ "fieldLabel": "xoziZG_fieldLabel",
39
+ "balanceUnit": "xoziZG_balanceUnit",
57
40
  "check": "xoziZG_check",
58
41
  "usageFill": "xoziZG_usageFill",
59
- "creditHint": "xoziZG_creditHint",
60
42
  "modelShare": "xoziZG_modelShare",
61
- "barFill": "xoziZG_barFill",
62
- "body": "xoziZG_body",
43
+ "bar": "xoziZG_bar",
44
+ "balance": "xoziZG_balance",
45
+ "link": "xoziZG_link",
46
+ "tabPanel": "xoziZG_tabPanel",
63
47
  "headText": "xoziZG_headText",
64
- "creditLink": "xoziZG_creditLink",
65
- "desc": "xoziZG_desc",
66
48
  "balanceRow": "xoziZG_balanceRow",
67
- "choices": "xoziZG_choices",
68
- "sectionHead": "xoziZG_sectionHead",
49
+ "card": "xoziZG_card",
69
50
  "manualForm": "xoziZG_manualForm",
70
- "avatar": "xoziZG_avatar",
71
- "expiryLabel": "xoziZG_expiryLabel",
72
- "updated": "xoziZG_updated",
73
- "balanceUnit": "xoziZG_balanceUnit",
74
- "accountInfo": "xoziZG_accountInfo",
51
+ "name": "xoziZG_name",
52
+ "creditRow": "xoziZG_creditRow",
53
+ "creditLink": "xoziZG_creditLink",
54
+ "tabs": "xoziZG_tabs",
55
+ "body": "xoziZG_body",
56
+ "count": "xoziZG_count",
57
+ "accountHint": "xoziZG_accountHint",
58
+ "meta": "xoziZG_meta",
75
59
  "sectionLabel": "xoziZG_sectionLabel",
60
+ "manual": "xoziZG_manual",
61
+ "creditFooter": "xoziZG_creditFooter",
62
+ "creditHint": "xoziZG_creditHint",
63
+ "modelChart": "xoziZG_modelChart",
64
+ "accountCard": "xoziZG_accountCard",
76
65
  "danger": "xoziZG_danger",
77
- "expiryRow": "xoziZG_expiryRow",
78
- "statusLine": "xoziZG_statusLine",
79
- "section": "xoziZG_section",
80
- "link": "xoziZG_link",
81
- "modelFill": "xoziZG_modelFill",
82
- "accountName": "xoziZG_accountName",
83
- "modelRow": "xoziZG_modelRow",
84
- "modelTrack": "xoziZG_modelTrack",
85
- "hint": "xoziZG_hint",
66
+ "accountToolbar": "xoziZG_accountToolbar",
67
+ "modelTokens": "xoziZG_modelTokens",
68
+ "manualSummary": "xoziZG_manualSummary",
86
69
  "balanceMeta": "xoziZG_balanceMeta",
87
- "count": "xoziZG_count",
88
- "modelChart": "xoziZG_modelChart",
89
- "accountRow": "xoziZG_accountRow",
90
- "creditRows": "xoziZG_creditRows",
91
70
  "header": "xoziZG_header",
92
- "claimAllRow": "xoziZG_claimAllRow",
93
- "creditBlock": "xoziZG_creditBlock",
94
- "modelTokens": "xoziZG_modelTokens",
95
- "balance": "xoziZG_balance",
71
+ "sectionHead": "xoziZG_sectionHead",
72
+ "accountEntry": "xoziZG_accountEntry",
73
+ "hint": "xoziZG_hint",
74
+ "error": "xoziZG_error",
75
+ "modelName": "xoziZG_modelName",
76
+ "field": "xoziZG_field",
77
+ "avatar": "xoziZG_avatar",
78
+ "modelTrack": "xoziZG_modelTrack",
79
+ "usageBar": "xoziZG_usageBar",
80
+ "updated": "xoziZG_updated",
81
+ "modelRow": "xoziZG_modelRow",
82
+ "expiryRow": "xoziZG_expiryRow",
83
+ "actions": "xoziZG_actions",
84
+ "accountRowActions": "xoziZG_accountRowActions",
85
+ "accountRow": "xoziZG_accountRow",
86
+ "accountInfo": "xoziZG_accountInfo",
87
+ "modelRequests": "xoziZG_modelRequests",
88
+ "modelFill": "xoziZG_modelFill",
89
+ "desc": "xoziZG_desc",
96
90
  "accountNameRow": "xoziZG_accountNameRow",
97
- "bar": "xoziZG_bar",
98
- "creditFooter": "xoziZG_creditFooter",
99
- "fieldLabel": "xoziZG_fieldLabel"
91
+ "area": "xoziZG_area",
92
+ "creditBlock": "xoziZG_creditBlock",
93
+ "expiryLabel": "xoziZG_expiryLabel",
94
+ "accountName": "xoziZG_accountName",
95
+ "section": "xoziZG_section",
96
+ "choiceRow": "xoziZG_choiceRow",
97
+ "barFill": "xoziZG_barFill",
98
+ "statusLine": "xoziZG_statusLine",
99
+ "creditRows": "xoziZG_creditRows"
100
100
  };
101
101
  //#endregion
102
102
  //#region src/client/CodeArtsPluginCard.tsx
@@ -879,311 +879,318 @@ function CodeArtsPluginCard({ t }) {
879
879
  })]
880
880
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
881
881
  className: CodeArtsPluginCard_module_css_default.body,
882
- children: [signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
883
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
884
- className: CodeArtsPluginCard_module_css_default.tabs,
885
- items: tabs,
886
- value: activeTab,
887
- onChange: setTab,
888
- label: t("tabsLabel")
882
+ children: [
883
+ status?.piAiError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
884
+ className: CodeArtsPluginCard_module_css_default.error,
885
+ children: status.piAiError
889
886
  }),
890
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
891
- id: panelId("accounts"),
892
- labelledBy: tabId("accounts"),
893
- active: activeTab === "accounts",
894
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
895
- className: CodeArtsPluginCard_module_css_default.section,
896
- children: [
897
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
898
- className: CodeArtsPluginCard_module_css_default.sectionHead,
899
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
900
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
901
- children: t("accountsTitle")
902
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
903
- className: CodeArtsPluginCard_module_css_default.count,
904
- children: accounts.length
905
- })]
906
- }),
907
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
908
- className: CodeArtsPluginCard_module_css_default.accountToolbar,
909
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
910
- variant: "outline",
911
- size: "sm",
912
- "aria-expanded": manualOpen,
913
- disabled: busy,
914
- onClick: () => setManualOpen((open) => !open),
915
- children: t("pasteTokenAdd")
916
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
917
- variant: "primary",
918
- size: "sm",
919
- disabled: busy || loginPending,
920
- onClick: () => void startOAuthLogin(),
921
- children: loginPending ? t("signingIn") : t("addAccount")
922
- })]
923
- }),
924
- loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
925
- className: CodeArtsPluginCard_module_css_default.hint,
926
- children: [
927
- t("openManually"),
928
- " ",
929
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
930
- className: CodeArtsPluginCard_module_css_default.link,
931
- href: loginUrl,
932
- target: "_blank",
933
- rel: "noreferrer",
934
- children: loginUrl
935
- })
936
- ]
937
- }),
938
- manualOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
939
- className: CodeArtsPluginCard_module_css_default.manualForm,
940
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ManualTokenForm, {
941
- t,
942
- token,
943
- label,
944
- busy,
945
- onToken: setToken,
946
- onLabel: setLabel,
947
- onSubmit: (e) => void saveToken(e)
948
- })
949
- }),
950
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
951
- className: CodeArtsPluginCard_module_css_default.accountCard,
952
- children: [
953
- accounts.map((account) => {
954
- const accountLine = accountMeta(account);
955
- const credit = creditFor(account.id);
956
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
957
- className: CodeArtsPluginCard_module_css_default.accountEntry,
958
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
959
- className: CodeArtsPluginCard_module_css_default.accountRow,
960
- children: [
961
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
962
- className: CodeArtsPluginCard_module_css_default.avatar,
963
- "aria-hidden": "true",
964
- children: Array.from(accountName(account))[0] ?? "*"
965
- }),
966
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
967
- className: CodeArtsPluginCard_module_css_default.accountInfo,
968
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
969
- className: CodeArtsPluginCard_module_css_default.accountNameRow,
970
- children: [
971
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
972
- className: CodeArtsPluginCard_module_css_default.accountName,
973
- children: accountName(account)
974
- }),
975
- account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
976
- !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") })
977
- ]
978
- }), accountLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
979
- className: CodeArtsPluginCard_module_css_default.meta,
980
- children: accountLine
981
- })]
982
- }),
983
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
984
- className: CodeArtsPluginCard_module_css_default.accountRowActions,
985
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
986
- variant: "outline",
987
- size: "sm",
988
- className: CodeArtsPluginCard_module_css_default.danger,
989
- disabled: busy,
990
- onClick: () => void removeAccount(account.id),
991
- children: t("accountRemove")
992
- })
993
- })
994
- ]
995
- }), credit !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditBlock, {
996
- credits: credit.credits,
997
- error: credit.creditsError,
998
- t,
999
- onClaim: () => void claim(account.id),
1000
- claiming: claimingId === account.id || claimingId === CLAIM_ALL,
1001
- claimResult: claimResults[account.id] ?? null,
1002
- justClaimed: claimedIds[account.id] === true
1003
- })]
1004
- }, account.id);
1005
- }),
1006
- accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1007
- className: CodeArtsPluginCard_module_css_default.claimAllRow,
1008
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1009
- variant: "outline",
1010
- size: "sm",
1011
- disabled: claimingId !== null,
1012
- onClick: () => void claim(),
1013
- children: claimingId === CLAIM_ALL ? t("claimPending") : t("claimAll")
1014
- })
1015
- }),
1016
- accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1017
- className: CodeArtsPluginCard_module_css_default.accountHint,
1018
- children: t("accountsRotateHint")
1019
- })
1020
- ]
1021
- }),
1022
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1023
- className: CodeArtsPluginCard_module_css_default.actions,
1024
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1025
- variant: "outline",
1026
- size: "sm",
1027
- className: CodeArtsPluginCard_module_css_default.danger,
1028
- disabled: busy,
1029
- onClick: () => void clearToken(),
1030
- children: t("clearToken")
1031
- })
1032
- })
1033
- ]
1034
- })
1035
- }),
1036
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
1037
- id: panelId("models"),
1038
- labelledBy: tabId("models"),
1039
- active: activeTab === "models",
1040
- children: selection ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1041
- className: CodeArtsPluginCard_module_css_default.section,
1042
- children: [
1043
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1044
- className: CodeArtsPluginCard_module_css_default.sectionHead,
1045
- children: [
1046
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
887
+ signedIn ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
888
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
889
+ className: CodeArtsPluginCard_module_css_default.tabs,
890
+ items: tabs,
891
+ value: activeTab,
892
+ onChange: setTab,
893
+ label: t("tabsLabel")
894
+ }),
895
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
896
+ id: panelId("accounts"),
897
+ labelledBy: tabId("accounts"),
898
+ active: activeTab === "accounts",
899
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
900
+ className: CodeArtsPluginCard_module_css_default.section,
901
+ children: [
902
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
903
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
904
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1047
905
  className: CodeArtsPluginCard_module_css_default.sectionLabel,
1048
- children: t("modelsTitle")
1049
- }),
1050
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
906
+ children: t("accountsTitle")
907
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1051
908
  className: CodeArtsPluginCard_module_css_default.count,
1052
- children: t("selectedCount", {
1053
- n: draft.length,
1054
- total: all
1055
- })
1056
- }),
1057
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
909
+ children: accounts.length
910
+ })]
911
+ }),
912
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
913
+ className: CodeArtsPluginCard_module_css_default.accountToolbar,
914
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1058
915
  variant: "outline",
1059
916
  size: "sm",
1060
- disabled: refreshing,
1061
- onClick: () => void refreshCatalog(),
1062
- children: refreshing ? t("refreshing") : t("refreshModels")
917
+ "aria-expanded": manualOpen,
918
+ disabled: busy,
919
+ onClick: () => setManualOpen((open) => !open),
920
+ children: t("pasteTokenAdd")
921
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
922
+ variant: "primary",
923
+ size: "sm",
924
+ disabled: busy || loginPending,
925
+ onClick: () => void startOAuthLogin(),
926
+ children: loginPending ? t("signingIn") : t("addAccount")
927
+ })]
928
+ }),
929
+ loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
930
+ className: CodeArtsPluginCard_module_css_default.hint,
931
+ children: [
932
+ t("openManually"),
933
+ " ",
934
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
935
+ className: CodeArtsPluginCard_module_css_default.link,
936
+ href: loginUrl,
937
+ target: "_blank",
938
+ rel: "noreferrer",
939
+ children: loginUrl
940
+ })
941
+ ]
942
+ }),
943
+ manualOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
944
+ className: CodeArtsPluginCard_module_css_default.manualForm,
945
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ManualTokenForm, {
946
+ t,
947
+ token,
948
+ label,
949
+ busy,
950
+ onToken: setToken,
951
+ onLabel: setLabel,
952
+ onSubmit: (e) => void saveToken(e)
1063
953
  })
1064
- ]
1065
- }),
1066
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1067
- className: CodeArtsPluginCard_module_css_default.hint,
1068
- children: selection.restricted ? t("optionalModelsHint") : t("optionalModelsAllHint")
1069
- }),
1070
- blockedCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1071
- className: CodeArtsPluginCard_module_css_default.hint,
1072
- children: t("benefitBlockedHint", { n: blockedCount })
1073
- }),
1074
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1075
- className: CodeArtsPluginCard_module_css_default.choices,
1076
- children: selection.choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1077
- className: CodeArtsPluginCard_module_css_default.choiceRow,
954
+ }),
955
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
956
+ className: CodeArtsPluginCard_module_css_default.accountCard,
1078
957
  children: [
1079
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1080
- className: CodeArtsPluginCard_module_css_default.check,
1081
- checked: draft.includes(choice.id),
1082
- disabled: !selection.writable || savingModels,
1083
- onChange: (on) => setModel(choice.id, on),
1084
- label: modelName(choice)
958
+ accounts.map((account) => {
959
+ const accountLine = accountMeta(account);
960
+ const credit = creditFor(account.id);
961
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
962
+ className: CodeArtsPluginCard_module_css_default.accountEntry,
963
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
964
+ className: CodeArtsPluginCard_module_css_default.accountRow,
965
+ children: [
966
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
967
+ className: CodeArtsPluginCard_module_css_default.avatar,
968
+ "aria-hidden": "true",
969
+ children: Array.from(accountName(account))[0] ?? "*"
970
+ }),
971
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
972
+ className: CodeArtsPluginCard_module_css_default.accountInfo,
973
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
974
+ className: CodeArtsPluginCard_module_css_default.accountNameRow,
975
+ children: [
976
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
977
+ className: CodeArtsPluginCard_module_css_default.accountName,
978
+ children: accountName(account)
979
+ }),
980
+ account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
981
+ !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") })
982
+ ]
983
+ }), accountLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
984
+ className: CodeArtsPluginCard_module_css_default.meta,
985
+ children: accountLine
986
+ })]
987
+ }),
988
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
989
+ className: CodeArtsPluginCard_module_css_default.accountRowActions,
990
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
991
+ variant: "outline",
992
+ size: "sm",
993
+ className: CodeArtsPluginCard_module_css_default.danger,
994
+ disabled: busy,
995
+ onClick: () => void removeAccount(account.id),
996
+ children: t("accountRemove")
997
+ })
998
+ })
999
+ ]
1000
+ }), credit !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditBlock, {
1001
+ credits: credit.credits,
1002
+ error: credit.creditsError,
1003
+ t,
1004
+ onClaim: () => void claim(account.id),
1005
+ claiming: claimingId === account.id || claimingId === CLAIM_ALL,
1006
+ claimResult: claimResults[account.id] ?? null,
1007
+ justClaimed: claimedIds[account.id] === true
1008
+ })]
1009
+ }, account.id);
1085
1010
  }),
1086
- choice.benefit === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1087
- tone: choice.blocked === true ? "warning" : "success",
1088
- children: choice.blocked === true ? t("benefitBlocked") : t("benefit")
1011
+ accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1012
+ className: CodeArtsPluginCard_module_css_default.claimAllRow,
1013
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1014
+ variant: "outline",
1015
+ size: "sm",
1016
+ disabled: claimingId !== null,
1017
+ onClick: () => void claim(),
1018
+ children: claimingId === CLAIM_ALL ? t("claimPending") : t("claimAll")
1019
+ })
1089
1020
  }),
1090
- choice.ratio !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1091
- tone: "quiet",
1092
- children: choice.ratio
1021
+ accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1022
+ className: CodeArtsPluginCard_module_css_default.accountHint,
1023
+ children: t("accountsRotateHint")
1093
1024
  })
1094
1025
  ]
1095
- }, choice.id))
1096
- }),
1097
- selection.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1098
- className: CodeArtsPluginCard_module_css_default.actions,
1099
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1100
- variant: "outline",
1101
- size: "sm",
1102
- disabled: draft.length === all,
1103
- onClick: () => {
1104
- setSavedModels(false);
1105
- setModelError(null);
1106
- setDraft(selection.choices.map((c) => c.id));
1107
- },
1108
- children: t("selectAll")
1109
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1110
- variant: "primary",
1111
- size: "sm",
1112
- disabled: !dirty || savingModels,
1113
- onClick: () => void saveModels(),
1114
- children: savingModels ? t("saving") : savedModels && !dirty ? t("saved") : t("saveModels")
1115
- })]
1116
- }),
1117
- modelError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1118
- className: CodeArtsPluginCard_module_css_default.error,
1119
- children: modelError
1120
- })
1121
- ]
1122
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1123
- className: CodeArtsPluginCard_module_css_default.hint,
1124
- children: t("modelsLoading")
1125
- })
1126
- }),
1127
- status?.usage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
1128
- id: panelId("usage"),
1129
- labelledBy: tabId("usage"),
1130
- active: activeTab === "usage",
1131
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, {
1132
- usage: status.usage,
1133
- accounts,
1134
- t
1135
- })
1136
- })
1137
- ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1138
- className: CodeArtsPluginCard_module_css_default.section,
1139
- children: [
1140
- expired && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1141
- className: CodeArtsPluginCard_module_css_default.hint,
1142
- children: t("expiredHint")
1143
- }),
1144
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1145
- className: CodeArtsPluginCard_module_css_default.actions,
1146
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1147
- variant: "primary",
1148
- disabled: busy || loginPending,
1149
- onClick: () => void startOAuthLogin(),
1150
- children: loginPending ? t("signingIn") : t("signIn")
1026
+ }),
1027
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1028
+ className: CodeArtsPluginCard_module_css_default.actions,
1029
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1030
+ variant: "outline",
1031
+ size: "sm",
1032
+ className: CodeArtsPluginCard_module_css_default.danger,
1033
+ disabled: busy,
1034
+ onClick: () => void clearToken(),
1035
+ children: t("clearToken")
1036
+ })
1037
+ })
1038
+ ]
1151
1039
  })
1152
1040
  }),
1153
- loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1154
- className: CodeArtsPluginCard_module_css_default.hint,
1155
- children: [
1156
- t("openManually"),
1157
- " ",
1158
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1159
- className: CodeArtsPluginCard_module_css_default.link,
1160
- href: loginUrl,
1161
- target: "_blank",
1162
- rel: "noreferrer",
1163
- children: loginUrl
1164
- })
1165
- ]
1041
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
1042
+ id: panelId("models"),
1043
+ labelledBy: tabId("models"),
1044
+ active: activeTab === "models",
1045
+ children: selection ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1046
+ className: CodeArtsPluginCard_module_css_default.section,
1047
+ children: [
1048
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1049
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
1050
+ children: [
1051
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1052
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1053
+ children: t("modelsTitle")
1054
+ }),
1055
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1056
+ className: CodeArtsPluginCard_module_css_default.count,
1057
+ children: t("selectedCount", {
1058
+ n: draft.length,
1059
+ total: all
1060
+ })
1061
+ }),
1062
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1063
+ variant: "outline",
1064
+ size: "sm",
1065
+ disabled: refreshing,
1066
+ onClick: () => void refreshCatalog(),
1067
+ children: refreshing ? t("refreshing") : t("refreshModels")
1068
+ })
1069
+ ]
1070
+ }),
1071
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1072
+ className: CodeArtsPluginCard_module_css_default.hint,
1073
+ children: selection.restricted ? t("optionalModelsHint") : t("optionalModelsAllHint")
1074
+ }),
1075
+ blockedCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1076
+ className: CodeArtsPluginCard_module_css_default.hint,
1077
+ children: t("benefitBlockedHint", { n: blockedCount })
1078
+ }),
1079
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1080
+ className: CodeArtsPluginCard_module_css_default.choices,
1081
+ children: selection.choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1082
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1083
+ children: [
1084
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1085
+ className: CodeArtsPluginCard_module_css_default.check,
1086
+ checked: draft.includes(choice.id),
1087
+ disabled: !selection.writable || savingModels,
1088
+ onChange: (on) => setModel(choice.id, on),
1089
+ label: modelName(choice)
1090
+ }),
1091
+ choice.benefit === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1092
+ tone: choice.blocked === true ? "warning" : "success",
1093
+ children: choice.blocked === true ? t("benefitBlocked") : t("benefit")
1094
+ }),
1095
+ choice.ratio !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1096
+ tone: "quiet",
1097
+ children: choice.ratio
1098
+ })
1099
+ ]
1100
+ }, choice.id))
1101
+ }),
1102
+ selection.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1103
+ className: CodeArtsPluginCard_module_css_default.actions,
1104
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1105
+ variant: "outline",
1106
+ size: "sm",
1107
+ disabled: draft.length === all,
1108
+ onClick: () => {
1109
+ setSavedModels(false);
1110
+ setModelError(null);
1111
+ setDraft(selection.choices.map((c) => c.id));
1112
+ },
1113
+ children: t("selectAll")
1114
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1115
+ variant: "primary",
1116
+ size: "sm",
1117
+ disabled: !dirty || savingModels,
1118
+ onClick: () => void saveModels(),
1119
+ children: savingModels ? t("saving") : savedModels && !dirty ? t("saved") : t("saveModels")
1120
+ })]
1121
+ }),
1122
+ modelError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1123
+ className: CodeArtsPluginCard_module_css_default.error,
1124
+ children: modelError
1125
+ })
1126
+ ]
1127
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1128
+ className: CodeArtsPluginCard_module_css_default.hint,
1129
+ children: t("modelsLoading")
1130
+ })
1166
1131
  }),
1167
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
1168
- className: CodeArtsPluginCard_module_css_default.manual,
1169
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
1170
- className: CodeArtsPluginCard_module_css_default.manualSummary,
1171
- children: t("manualToken")
1172
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ManualTokenForm, {
1173
- t,
1174
- token,
1175
- label,
1176
- busy,
1177
- onToken: setToken,
1178
- onLabel: setLabel,
1179
- onSubmit: (e) => void saveToken(e)
1180
- })]
1132
+ status?.usage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabPanel, {
1133
+ id: panelId("usage"),
1134
+ labelledBy: tabId("usage"),
1135
+ active: activeTab === "usage",
1136
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, {
1137
+ usage: status.usage,
1138
+ accounts,
1139
+ t
1140
+ })
1181
1141
  })
1182
- ]
1183
- }), msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1184
- className: CodeArtsPluginCard_module_css_default.error,
1185
- children: msg
1186
- })]
1142
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1143
+ className: CodeArtsPluginCard_module_css_default.section,
1144
+ children: [
1145
+ expired && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1146
+ className: CodeArtsPluginCard_module_css_default.hint,
1147
+ children: t("expiredHint")
1148
+ }),
1149
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1150
+ className: CodeArtsPluginCard_module_css_default.actions,
1151
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1152
+ variant: "primary",
1153
+ disabled: busy || loginPending,
1154
+ onClick: () => void startOAuthLogin(),
1155
+ children: loginPending ? t("signingIn") : t("signIn")
1156
+ })
1157
+ }),
1158
+ loginUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1159
+ className: CodeArtsPluginCard_module_css_default.hint,
1160
+ children: [
1161
+ t("openManually"),
1162
+ " ",
1163
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1164
+ className: CodeArtsPluginCard_module_css_default.link,
1165
+ href: loginUrl,
1166
+ target: "_blank",
1167
+ rel: "noreferrer",
1168
+ children: loginUrl
1169
+ })
1170
+ ]
1171
+ }),
1172
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
1173
+ className: CodeArtsPluginCard_module_css_default.manual,
1174
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
1175
+ className: CodeArtsPluginCard_module_css_default.manualSummary,
1176
+ children: t("manualToken")
1177
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ManualTokenForm, {
1178
+ t,
1179
+ token,
1180
+ label,
1181
+ busy,
1182
+ onToken: setToken,
1183
+ onLabel: setLabel,
1184
+ onSubmit: (e) => void saveToken(e)
1185
+ })]
1186
+ })
1187
+ ]
1188
+ }),
1189
+ msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1190
+ className: CodeArtsPluginCard_module_css_default.error,
1191
+ children: msg
1192
+ })
1193
+ ]
1187
1194
  })]
1188
1195
  });
1189
1196
  }
package/lib/index.d.mts CHANGED
@@ -421,6 +421,14 @@ declare class CodeArtsAccountPool {
421
421
  noteConcurrencyCap(id: string): void;
422
422
  /** 凭据失效等硬错误:直接停用,等用户重新登录。 */
423
423
  disable(id: string, reason: string): void;
424
+ /**
425
+ * 用户重新登录(凭据已换新)后调用:把账号从禁用/冷却里捞出来。
426
+ *
427
+ * `sync()` 只对齐成员、特意保留运行时状态(account-pool 不读凭据文档),所以
428
+ * 「同一账号重新登录」不会自动清掉 disabled —— 以前只能靠重启(见 issue #1)。
429
+ * 登录成功的语义就是「这个号现在该能用了」,由登录路径显式调这里复位。
430
+ */
431
+ revive(id: string): void;
424
432
  /** 上游 5xx / 软限流:短时冷却。 */
425
433
  cooldown(id: string, ms: number, reason: string): void;
426
434
  /** 累计错误;达到阈值就冷却。 */
package/lib/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as filterEnabledModels, C as rateLimitFrame, D as FALLBACK_CODEARTS_MODELS, E as CodeArtsCatalog, F as codeartsAccountsPath, I as codeartsAuthPath, L as startLogin, M as isBenefitModel, N as CodeArtsAccountStore, O as clearBenefitBlocked, P as CodeArtsCredentialStore, S as prepareChatBody, T as upstreamErrorMessage, _ as isQueueableRate, a as SNAP_HOST, b as maxTokensCeilingFor, c as claimDailyWelfare, d as fetchCallerIdentity, f as fetchModels, g as isParamInvalidFrame, h as isConcurrencyCap, i as refreshCatalog, j as isBenefitBlocked, k as creditRatioLabel, l as clearQueueStatus, m as fetchWelfareCampaigns, n as codeartsUsagePath, o as canonicalModel, p as fetchQueueStatus, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as degradeTokenCeiling, v as isTpmLimit, w as signedGet, x as pickDailyWelfareCampaign, y as isWelfareClaimedStatus } from "./usage-Cie0IlC4.mjs";
1
+ import { A as filterEnabledModels, C as rateLimitFrame, D as FALLBACK_CODEARTS_MODELS, E as CodeArtsCatalog, F as MANUAL_ACCOUNT_ID, I as codeartsAccountsPath, L as codeartsAuthPath, M as isBenefitModel, N as CodeArtsAccountStore, O as clearBenefitBlocked, P as CodeArtsCredentialStore, R as startLogin, S as prepareChatBody, T as upstreamErrorMessage, _ as isQueueableRate, a as SNAP_HOST, b as maxTokensCeilingFor, c as claimDailyWelfare, d as fetchCallerIdentity, f as fetchModels, g as isParamInvalidFrame, h as isConcurrencyCap, i as refreshCatalog, j as isBenefitBlocked, k as creditRatioLabel, l as clearQueueStatus, m as fetchWelfareCampaigns, n as codeartsUsagePath, o as canonicalModel, p as fetchQueueStatus, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as degradeTokenCeiling, v as isTpmLimit, w as signedGet, x as pickDailyWelfareCampaign, y as isWelfareClaimedStatus } from "./usage-5YK7bW-e.mjs";
2
2
  import z from "@deepseek-ai/schemastery";
3
3
  import { randomBytes, timingSafeEqual } from "node:crypto";
4
4
  import { createServer } from "node:http";
@@ -106,6 +106,22 @@ var CodeArtsAccountPool = class {
106
106
  account.disabled = true;
107
107
  account.lastError = reason;
108
108
  }
109
+ /**
110
+ * 用户重新登录(凭据已换新)后调用:把账号从禁用/冷却里捞出来。
111
+ *
112
+ * `sync()` 只对齐成员、特意保留运行时状态(account-pool 不读凭据文档),所以
113
+ * 「同一账号重新登录」不会自动清掉 disabled —— 以前只能靠重启(见 issue #1)。
114
+ * 登录成功的语义就是「这个号现在该能用了」,由登录路径显式调这里复位。
115
+ */
116
+ revive(id) {
117
+ const account = this.accounts.get(id);
118
+ if (account === void 0) return;
119
+ account.disabled = false;
120
+ account.coolUntil = 0;
121
+ account.cappedUntil = 0;
122
+ account.errorCount = 0;
123
+ account.lastError = void 0;
124
+ }
109
125
  /** 上游 5xx / 软限流:短时冷却。 */
110
126
  cooldown(id, ms, reason) {
111
127
  const account = this.accounts.get(id);
@@ -706,6 +722,56 @@ var CodeArtsPiAiAdapter = class extends PiAiAdapter {
706
722
  }
707
723
  };
708
724
  //#endregion
725
+ //#region src/pi-ai-compat.ts
726
+ /**
727
+ * `@earendil-works/pi-ai` 运行时自检。
728
+ *
729
+ * 本插件编译时对齐的是 1.3.0,而宿主(`dsh-llm-pi-ai` 0.2.1-rc.2 起)会先把系统提示
730
+ * 折叠成一条 `role:"system"`、`content` 为**字符串**的消息,再交给 provider。1.3.0 之前
731
+ * 的 `estimateMessageTokens` 没有 system 分支:字符串内容被按字符遍历,每个"块"是单个
732
+ * 字符,`block.name` 为 undefined,于是每条消息都死在
733
+ * `Cannot read properties of undefined (reading 'length')` 上 —— 而且是在出网之前,
734
+ * 用户只看得到一句「本轮运行失败」。
735
+ *
736
+ * 什么时候会拿到旧的那份:profile 顶层被别的插件 hoist 了一个低版本,而本插件的依赖
737
+ * 没落地到自己的 `node_modules`。1.1.3 起 `@earendil-works/pi-ai` 已从 peerDependencies
738
+ * 移进 dependencies,区间真正生效;这里再探测一次,把「版本不兼容」明说,而不是让
739
+ * 每条消息各自崩在一个看不懂的 TypeError 上。
740
+ *
741
+ * 探测用能力而不是版本号:不依赖 package.json 能不能读到,也对未来的版本漂移免疫。
742
+ *
743
+ * @module dsh-codearts/pi-ai-compat
744
+ */
745
+ /** 折叠后的系统消息要能被估token;从这一版起才支持。 */
746
+ const MIN_PI_AI_VERSION = "1.3.0";
747
+ let probe;
748
+ /** 不兼容时的说明;兼容时 undefined。结果只算一次(模块加载后版本不会再变)。 */
749
+ function probePiAiCompat() {
750
+ probe ??= runProbe();
751
+ return probe;
752
+ }
753
+ async function runProbe() {
754
+ const hint = `需要 @earendil-works/pi-ai >= ${MIN_PI_AI_VERSION},请重装 dsh-codearts(1.1.3 起它自带这份依赖),或把 profile 顶层那份升级到同一区间`;
755
+ let estimate;
756
+ try {
757
+ ({estimateMessageTokens: estimate} = await import("@earendil-works/pi-ai/utils/estimate"));
758
+ } catch (error) {
759
+ return `pi-ai 不兼容:读不到 @earendil-works/pi-ai/utils/estimate(${messageOf(error)})。${hint}`;
760
+ }
761
+ if (typeof estimate !== "function") return `pi-ai 不兼容:这份 @earendil-works/pi-ai 没有 estimateMessageTokens。${hint}`;
762
+ try {
763
+ estimate({
764
+ role: "system",
765
+ content: "probe"
766
+ });
767
+ } catch (error) {
768
+ return `pi-ai 不兼容:这份 @earendil-works/pi-ai 处理不了宿主折叠出的 system 消息(${messageOf(error)}),每条请求都会在出网前失败。${hint}`;
769
+ }
770
+ }
771
+ function messageOf(error) {
772
+ return error instanceof Error ? error.message : String(error);
773
+ }
774
+ //#endregion
709
775
  //#region src/loopback.ts
710
776
  /**
711
777
  * Shared loopback gates for the plugin's local HTTP surfaces: the loopback
@@ -816,6 +882,40 @@ function queuedMessage(model, gate) {
816
882
  const upstream = gate.message.trim();
817
883
  return `${upstream === "" ? `上游排队中:${model} 第 ${gate.position} 位(共 ${gate.length} 条)` : upstream} 插件没有一直等下去,请稍后重试。`;
818
884
  }
885
+ /**
886
+ * 「一个账号都选不出来」时的报错:把真实原因说清 —— 是禁用(附最后错误)、冷却
887
+ * (附剩余秒数),还是本地槽位全满。以前三种都回同一句「没有可用账号」,禁用那
888
+ * 种还把真因(比如 billion-context 本地拒签的 403)整个吞掉(issue #1)。
889
+ *
890
+ * 全部被禁用时回 401(宿主只自动重试 429,401 一次就把「去重新登录」说清);
891
+ * 只要还有会自己恢复的(冷却/槽位满)就回 429,宿主重试有概率直接救回来。
892
+ */
893
+ function noAccountError(accounts) {
894
+ const now = Date.now();
895
+ const disabled = accounts.filter((a) => a.disabled);
896
+ const cooling = accounts.filter((a) => !a.disabled && now < a.coolUntil);
897
+ const busy = accounts.filter((a) => !a.disabled && now >= a.coolUntil);
898
+ const parts = [];
899
+ if (disabled.length > 0) {
900
+ const reasons = disabled.map((a) => a.lastError === void 0 ? a.id : `${a.id}(${a.lastError.slice(0, 120)})`).join("、");
901
+ parts.push(`${disabled.length} 个被禁用:${reasons}——请到设置卡片重新登录(若在用 billion-context,先检查它的 resign 配置)`);
902
+ }
903
+ if (cooling.length > 0) {
904
+ const secs = Math.max(1, Math.ceil((Math.min(...cooling.map((a) => a.coolUntil)) - now) / 1e3));
905
+ parts.push(`${cooling.length} 个在短时冷却中(约 ${secs} 秒后恢复)`);
906
+ }
907
+ if (busy.length > 0) parts.push(`${busy.length} 个的本地并发槽位已满(每账号最多 ${busy[0]?.maxConcurrent ?? 2} 个在飞请求),等几秒再发`);
908
+ const message = `codearts 当前没有可用账号:${parts.join(";")}`;
909
+ return disabled.length === accounts.length ? {
910
+ status: 401,
911
+ kind: "session_dead",
912
+ message
913
+ } : {
914
+ status: 429,
915
+ kind: "soft_rate",
916
+ message
917
+ };
918
+ }
819
919
  function readBody$1(req) {
820
920
  return new Promise((resolve, reject) => {
821
921
  const chunks = [];
@@ -835,7 +935,6 @@ function readBody$1(req) {
835
935
  }
836
936
  /** 一次请求最多试几个账号(与 Go 参考的 MaxRotate 一致)。 */
837
937
  const MAX_ROTATE = 3;
838
- /** 一次请求最多把 max_tokens 降几档(65536 → 32768 → 16384 → 8192)。 */
839
938
  const MAX_CEILING_HEALS = 3;
840
939
  /**
841
940
  * 所有账号都撞上并发上限时,回落到「在同一账号上原地重发」的预算。
@@ -855,6 +954,35 @@ const SERVER_COOLDOWN_MS = 3e4;
855
954
  /** 零散错误累计到阈值后冷却该账号。 */
856
955
  const ERROR_COOLDOWN_MS = 6e4;
857
956
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
957
+ const recentShapes = [];
958
+ /** 最近的请求形状,最新在前。 */
959
+ function recentRequestShapes() {
960
+ return [...recentShapes].reverse();
961
+ }
962
+ function noteRequestShape(raw, model) {
963
+ let parsed;
964
+ try {
965
+ parsed = JSON.parse(raw);
966
+ } catch {
967
+ return;
968
+ }
969
+ if (parsed === null || typeof parsed !== "object") return;
970
+ const list = Array.isArray(parsed.messages) ? parsed.messages : [];
971
+ const roles = list.map((message) => {
972
+ if (message === null || typeof message !== "object") return "";
973
+ const role = message.role;
974
+ return typeof role === "string" ? role : "";
975
+ });
976
+ recentShapes.push({
977
+ at: Date.now(),
978
+ model,
979
+ messages: list.length,
980
+ roles,
981
+ emptyRoleAt: roles.map((role, index) => role === "" ? index : -1).filter((index) => index >= 0),
982
+ tools: Array.isArray(parsed.tools) ? parsed.tools.length : 0
983
+ });
984
+ if (recentShapes.length > 8) recentShapes.shift();
985
+ }
858
986
  function createCodeArtsShim(options) {
859
987
  const { store, catalog } = options;
860
988
  const logger = options.logger;
@@ -1050,6 +1178,7 @@ function createCodeArtsShim(options) {
1050
1178
  if (typeof inbound.model === "string") contextWindow = contextWindowFor(canonicalModel(inbound.model));
1051
1179
  } catch {}
1052
1180
  const checked = prepareChatBody(raw, contextWindow);
1181
+ noteRequestShape(raw, checked.model);
1053
1182
  if (checked.error !== void 0) {
1054
1183
  writeOpenAIError(res, 400, "context_overflow", checked.error);
1055
1184
  return;
@@ -1170,7 +1299,8 @@ function createCodeArtsShim(options) {
1170
1299
  }
1171
1300
  }
1172
1301
  if (lastKind === void 0) {
1173
- writeOpenAIError(res, 429, "soft_rate", "codearts 当前没有可用账号(全部被禁用或冷却中),请稍后重试");
1302
+ const none = noAccountError(pool.list());
1303
+ writeOpenAIError(res, none.status, none.kind, none.message);
1174
1304
  return;
1175
1305
  }
1176
1306
  const explanation = upstreamErrorMessage(lastMessage, lastStatus);
@@ -1272,6 +1402,8 @@ const CODEARTS_CLAIM_PATH = "/api/codearts/claim";
1272
1402
  const CODEARTS_REFRESH_MODELS_PATH = "/api/codearts/refresh-models";
1273
1403
  /** GET /api/codearts/queue — 上游排队位置(只在等开流期间有值,底部积分条旁边展示)。 */
1274
1404
  const CODEARTS_QUEUE_PATH = "/api/codearts/queue";
1405
+ /** 最近出站请求的**形状**摘要(只有 role 名与计数,不含内容),排障用。 */
1406
+ const CODEARTS_DEBUG_PATH = "/api/codearts/debug";
1275
1407
  /**
1276
1408
  * 由完整目录 + 已存 enabled 计算 selection。
1277
1409
  * - enabled 为空/未存 => 全部勾选(restricted=false)
@@ -1452,11 +1584,14 @@ async function buildStatus(deps) {
1452
1584
  const accounts = await deps.store.list();
1453
1585
  const cred = await deps.store.current();
1454
1586
  const usage = usageOf(deps);
1587
+ const piAi = await probePiAiCompat();
1588
+ const compat = piAi === void 0 ? {} : { piAiError: piAi };
1455
1589
  if (accounts.length === 0 || cred === void 0) return {
1456
1590
  status: "signed-out",
1457
1591
  models,
1458
1592
  accounts,
1459
- usage
1593
+ usage,
1594
+ ...compat
1460
1595
  };
1461
1596
  const usable = accounts.some(accountUsable);
1462
1597
  const identity = {
@@ -1468,11 +1603,13 @@ async function buildStatus(deps) {
1468
1603
  };
1469
1604
  if (!usable) return {
1470
1605
  status: "expired",
1471
- ...identity
1606
+ ...identity,
1607
+ ...compat
1472
1608
  };
1473
1609
  return {
1474
1610
  status: "signed-in",
1475
1611
  ...identity,
1612
+ ...compat,
1476
1613
  ...await creditsOf(deps)
1477
1614
  };
1478
1615
  }
@@ -1582,6 +1719,7 @@ function tokenPostHandler(deps) {
1582
1719
  }
1583
1720
  const label = typeof body?.label === "string" && body.label.trim() !== "" ? body.label.trim() : void 0;
1584
1721
  await deps.store.set(token, label);
1722
+ deps.reviveAccount?.(MANUAL_ACCOUNT_ID);
1585
1723
  json(res, 200, await buildStatus(deps));
1586
1724
  } catch (error) {
1587
1725
  json(res, 500, { error: safeMessage(error) });
@@ -1725,6 +1863,20 @@ function queueHandler(deps) {
1725
1863
  json(res, 200, { queue: deps.queue?.() ?? [] });
1726
1864
  };
1727
1865
  }
1866
+ /** GET /api/codearts/debug — 最近出站请求的形状摘要(只有 role 名与计数)。 */
1867
+ function debugHandler(deps) {
1868
+ return async (req, res) => {
1869
+ if (req.method !== "GET") {
1870
+ json(res, 405, { error: "method not allowed" });
1871
+ return;
1872
+ }
1873
+ if (!loopbackRequest(req)) {
1874
+ json(res, 403, { error: "request-not-trusted" });
1875
+ return;
1876
+ }
1877
+ json(res, 200, { requests: deps.recentRequests?.() ?? [] });
1878
+ };
1879
+ }
1728
1880
  /** Mount the status / models / token routes. */
1729
1881
  function registerCodeArtsStatusRoute(ctx, deps) {
1730
1882
  ctx.effect(() => {
@@ -1781,6 +1933,11 @@ function registerCodeArtsStatusRoute(ctx, deps) {
1781
1933
  path: CODEARTS_QUEUE_PATH,
1782
1934
  handler: queueHandler(deps)
1783
1935
  });
1936
+ const disposeDebug = ctx.webServer.register({
1937
+ kind: "exact",
1938
+ path: CODEARTS_DEBUG_PATH,
1939
+ handler: debugHandler(deps)
1940
+ });
1784
1941
  return () => {
1785
1942
  disposeStatus();
1786
1943
  disposeModels();
@@ -1792,6 +1949,7 @@ function registerCodeArtsStatusRoute(ctx, deps) {
1792
1949
  disposeClaim();
1793
1950
  disposeRefresh();
1794
1951
  disposeQueue();
1952
+ disposeDebug();
1795
1953
  for (const s of activeLogins.values()) s.close();
1796
1954
  activeLogins.clear();
1797
1955
  };
@@ -1831,6 +1989,8 @@ function loginStartHandler(deps, active, recent) {
1831
1989
  const identity = await probeIdentity(token);
1832
1990
  const id = await deps.store.upsertFromOAuth(token, void 0, identity ?? void 0);
1833
1991
  if (identity !== null && id !== identity.userId) await deps.store.adoptIdentity(id, identity);
1992
+ deps.reviveAccount?.(id);
1993
+ if (identity !== null && identity.userId !== id) deps.reviveAccount?.(identity.userId);
1834
1994
  recordLoginOutcome(recent, session.url, "done");
1835
1995
  } catch {
1836
1996
  recordLoginOutcome(recent, session.url, "error");
@@ -2033,8 +2193,10 @@ function apply(ctx, rawConfig) {
2033
2193
  enabledModels,
2034
2194
  setEnabledModels,
2035
2195
  pool: () => pool.list(),
2196
+ reviveAccount: (id) => pool.revive(id),
2036
2197
  usage: () => usage.snapshot(),
2037
2198
  queue: () => queue.snapshot(),
2199
+ recentRequests: () => recentRequestShapes(),
2038
2200
  credits: (signal) => loadCredits(signal),
2039
2201
  claim: async (accountId) => {
2040
2202
  const ids = accountId === void 0 ? await store.ids() : [accountId];
@@ -2148,9 +2310,11 @@ function apply(ctx, rawConfig) {
2148
2310
  logger: ctx.logger
2149
2311
  });
2150
2312
  usage.load().catch(() => {});
2151
- shim.ready.then(() => {
2313
+ shim.ready.then(async () => {
2152
2314
  if (stopped) return;
2153
2315
  discover();
2316
+ const incompatible = await probePiAiCompat();
2317
+ if (incompatible !== void 0) ctx.logger.error(`dsh-codearts: ${incompatible}`);
2154
2318
  const codearts = createCodeArtsAdapter({
2155
2319
  shim,
2156
2320
  catalog,
@@ -1246,6 +1246,7 @@ var upstream_exports = /* @__PURE__ */ __exportAll({
1246
1246
  isConcurrencyCap: () => isConcurrencyCap,
1247
1247
  isParamInvalidFrame: () => isParamInvalidFrame,
1248
1248
  isQueueableRate: () => isQueueableRate,
1249
+ isResignRefusal: () => isResignRefusal,
1249
1250
  isTpmLimit: () => isTpmLimit,
1250
1251
  isWelfareClaimedStatus: () => isWelfareClaimedStatus,
1251
1252
  maxTokensCeilingFor: () => maxTokensCeilingFor,
@@ -1476,6 +1477,10 @@ function prepareChatBody(rawJson, contextWindow = 0) {
1476
1477
  "stream_options",
1477
1478
  "reasoning_effort"
1478
1479
  ]) if (parsed[key] !== void 0) body[key] = parsed[key];
1480
+ if (Array.isArray(body.messages)) body.messages = body.messages.map((message) => message?.role === "developer" ? {
1481
+ ...message,
1482
+ role: "system"
1483
+ } : message);
1479
1484
  if (body.stream_options === void 0 || typeof body.stream_options !== "object") body.stream_options = { include_usage: true };
1480
1485
  else body.stream_options.include_usage = true;
1481
1486
  if (body.max_tokens === void 0 && typeof parsed.max_completion_tokens === "number") body.max_tokens = parsed.max_completion_tokens;
@@ -1592,6 +1597,7 @@ function rateLimitFrame(text) {
1592
1597
  * 让人以为是自己配错了。默认分支仍保留原始信息,便于排查。
1593
1598
  */
1594
1599
  function upstreamErrorMessage(message, status = 0) {
1600
+ if (isResignRefusal(message)) return "本地代理 billion-context 拦下了这条签名请求(它拿不到 CodeArts 凭据做重签,在本地直接拒了),不是你的账号问题:请在 ~/.config/billion-context/billion-context.json 加上 \"resign\": { \"sdk-hmac-sha256\": { \"passthrough\": true } } 后重启 DSH,或为它配置重签凭据。";
1595
1601
  if (MODEL_RATE_CODE.test(message) || MODEL_RATE_TEXT.test(message)) return "华为侧该模型当前请求过多(共享 TPM 超限),不是你的账号或插件问题。稍后重试,或临时改用 GLM-5.2 / GLM-5.3。";
1596
1602
  if (message.includes("TM.00001041")) return "CodeArts 免费档同时只允许 3 个会话,当前槽位一直占满(被打断的会话约 1 分钟才释放)。请稍后重试。";
1597
1603
  if (isBenefitMissing("", message)) return "这个模型属于限时福利,当前福利通道不可用(不是账号问题)。可以刷新模型列表,改用非福利模型。";
@@ -1610,8 +1616,18 @@ const BENEFIT_MISSING_CODE = "InferHub.4004.200";
1610
1616
  function isBenefitMissing(code, message) {
1611
1617
  return code === "InferHub.4004.200" || message.toLowerCase().includes("benefit not found");
1612
1618
  }
1619
+ /**
1620
+ * 本地代理「拒签」标记:billion-context 这类宿主层代理拦截出站请求做上下文压缩,
1621
+ * 碰到 SDK-HMAC-SHA256 签名请求要用 CodeArts 凭据重签;找不到凭据时在**本地**回
1622
+ * 403(根本没出网),body 里带这两个标记。这不是凭据失效 —— 归 session_dead 会把
1623
+ * 账号永久禁用(见 issue #1)。
1624
+ */
1625
+ function isResignRefusal(message) {
1626
+ return message.includes("signed_request_requires_resign") || message.includes("bili_resign_unavailable");
1627
+ }
1613
1628
  function classify(status, message) {
1614
1629
  const m = message.toLowerCase();
1630
+ if (isResignRefusal(message)) return "client";
1615
1631
  if (status === 401 || status === 403) return "session_dead";
1616
1632
  if (status === 402) return "hard_credit";
1617
1633
  if (status === 429) return "soft_rate";
@@ -1621,6 +1637,34 @@ function classify(status, message) {
1621
1637
  if (m.includes("tpm") || m.includes("并发")) return "soft_rate";
1622
1638
  return "client";
1623
1639
  }
1640
+ /**
1641
+ * 出网唯一入口:**只把 URL 字符串和普通 init 交给 fetch,绝不把 Request 对象交出去**。
1642
+ *
1643
+ * 邻居插件会换掉 `globalThis.fetch`(例如 IP 池出口路由直接把 undici 模块自带的
1644
+ * fetch 装成全局)。这时 `globalThis.Request` 还是另一份实例,而 undici 的 fetch
1645
+ * 用 `instanceof` 认自己的 Request:不是自己那份就当 URL 字符串处理,报
1646
+ * `Failed to parse URL from [object Request]`,而且是 HTTP 0(根本没出网)。
1647
+ * 所以 Request 只当签名的载体(signer 要读写它的头部),发出去时拆回纯数据。
1648
+ *
1649
+ * 头部按 forEach 展开会全部变成小写名 —— 签名侧本来也按小写规范化,HTTP 头大小写
1650
+ * 不敏感,上游不受影响。
1651
+ *
1652
+ * @param req 已签好名的请求
1653
+ * @param body 原始请求体;GET/DELETE 传 undefined(带空 body 的 GET 会被 fetch 直接拒)
1654
+ * @param signal 中止信号
1655
+ */
1656
+ async function dispatch(req, body, signal) {
1657
+ const headers = {};
1658
+ req.headers.forEach((value, key) => {
1659
+ headers[key] = value;
1660
+ });
1661
+ return fetch(req.url, {
1662
+ method: req.method,
1663
+ headers,
1664
+ ...body === void 0 ? {} : { body },
1665
+ ...signal === void 0 ? {} : { signal }
1666
+ });
1667
+ }
1624
1668
  const enc = new TextEncoder();
1625
1669
  function openAIData(obj) {
1626
1670
  return enc.encode(`data: ${JSON.stringify(obj)}\n\n`);
@@ -1668,7 +1712,7 @@ async function chatStream(credential, prepared, signal) {
1668
1712
  }
1669
1713
  let resp;
1670
1714
  try {
1671
- resp = await fetch(req, { signal });
1715
+ resp = await dispatch(req, bodyBuf, signal);
1672
1716
  } catch (err) {
1673
1717
  const message = err instanceof Error ? err.message : String(err);
1674
1718
  if (signal?.aborted === true) return {
@@ -1851,7 +1895,7 @@ async function signedGet(url, credential, agentType, signal) {
1851
1895
  });
1852
1896
  let resp;
1853
1897
  try {
1854
- resp = await fetch(req, { signal });
1898
+ resp = await dispatch(req, void 0, signal);
1855
1899
  } catch (error) {
1856
1900
  return {
1857
1901
  ok: false,
@@ -2040,7 +2084,7 @@ async function fetchThinkingVariants(credential, modelIds, signal) {
2040
2084
  secretAccessKey: credential.secretAccessKey,
2041
2085
  securityToken: credential.securityToken
2042
2086
  });
2043
- const resp = await fetch(req, { signal });
2087
+ const resp = await dispatch(req, bodyBuf, signal);
2044
2088
  if (!resp.ok) {
2045
2089
  const text = await resp.text().catch(() => "");
2046
2090
  throw new Error(`thinking-variants HTTP ${resp.status} ${text.slice(0, 200)}`);
@@ -2086,7 +2130,7 @@ async function fetchQueueStatus(credential, chatId, model, signal) {
2086
2130
  secretAccessKey: credential.secretAccessKey,
2087
2131
  securityToken: credential.securityToken
2088
2132
  });
2089
- const resp = await fetch(req, { signal });
2133
+ const resp = await dispatch(req, void 0, signal);
2090
2134
  if (!resp.ok) {
2091
2135
  const text = await resp.text().catch(() => "");
2092
2136
  throw new Error(`queue status HTTP ${resp.status} ${text.slice(0, 200)}`);
@@ -2124,7 +2168,7 @@ async function clearQueueStatus(credential, chatId, model, signal) {
2124
2168
  secretAccessKey: credential.secretAccessKey,
2125
2169
  securityToken: credential.securityToken
2126
2170
  });
2127
- const resp = await fetch(req, { signal });
2171
+ const resp = await dispatch(req, void 0, signal);
2128
2172
  if (!resp.ok) {
2129
2173
  const text = await resp.text().catch(() => "");
2130
2174
  throw new Error(`queue clear HTTP ${resp.status} ${text.slice(0, 200)}`);
@@ -2234,7 +2278,7 @@ async function claimBenefit(credential, abort) {
2234
2278
  secretAccessKey: credential.secretAccessKey,
2235
2279
  securityToken: credential.securityToken
2236
2280
  });
2237
- const resp = await fetch(req, { signal: abort });
2281
+ const resp = await dispatch(req, bodyBuf, abort);
2238
2282
  const raw = await resp.text().catch(() => "");
2239
2283
  if (!resp.ok) throw new Error(`claim benefit failed: ${resp.status} ${raw.slice(0, 200)}`);
2240
2284
  let json;
@@ -2306,7 +2350,7 @@ async function welfareRequest(url, method, credential, body, signal) {
2306
2350
  });
2307
2351
  let resp;
2308
2352
  try {
2309
- resp = await fetch(req, { signal });
2353
+ resp = await dispatch(req, body === void 0 ? void 0 : bodyBuf, signal);
2310
2354
  } catch (error) {
2311
2355
  return {
2312
2356
  ok: false,
@@ -2736,4 +2780,4 @@ function sumOf(store) {
2736
2780
  return out;
2737
2781
  }
2738
2782
  //#endregion
2739
- export { filterEnabledModels as A, rateLimitFrame as C, FALLBACK_CODEARTS_MODELS as D, CodeArtsCatalog as E, codeartsAccountsPath as F, codeartsAuthPath as I, startLogin as L, isBenefitModel as M, CodeArtsAccountStore as N, clearBenefitBlocked as O, CodeArtsCredentialStore as P, prepareChatBody as S, upstreamErrorMessage as T, isQueueableRate as _, SNAP_HOST as a, maxTokensCeilingFor as b, claimDailyWelfare as c, fetchCallerIdentity as d, fetchModels as f, isParamInvalidFrame as g, isConcurrencyCap as h, refreshCatalog as i, isBenefitBlocked as j, creditRatioLabel as k, clearQueueStatus as l, fetchWelfareCampaigns as m, codeartsUsagePath as n, canonicalModel as o, fetchQueueStatus as p, discoverModels as r, chatStream as s, CodeArtsUsageTracker as t, degradeTokenCeiling as u, isTpmLimit as v, signedGet as w, pickDailyWelfareCampaign as x, isWelfareClaimedStatus as y };
2783
+ export { filterEnabledModels as A, rateLimitFrame as C, FALLBACK_CODEARTS_MODELS as D, CodeArtsCatalog as E, MANUAL_ACCOUNT_ID as F, codeartsAccountsPath as I, codeartsAuthPath as L, isBenefitModel as M, CodeArtsAccountStore as N, clearBenefitBlocked as O, CodeArtsCredentialStore as P, startLogin as R, prepareChatBody as S, upstreamErrorMessage as T, isQueueableRate as _, SNAP_HOST as a, maxTokensCeilingFor as b, claimDailyWelfare as c, fetchCallerIdentity as d, fetchModels as f, isParamInvalidFrame as g, isConcurrencyCap as h, refreshCatalog as i, isBenefitBlocked as j, creditRatioLabel as k, clearQueueStatus as l, fetchWelfareCampaigns as m, codeartsUsagePath as n, canonicalModel as o, fetchQueueStatus as p, discoverModels as r, chatStream as s, CodeArtsUsageTracker as t, degradeTokenCeiling as u, isTpmLimit as v, signedGet as w, pickDailyWelfareCampaign as x, isWelfareClaimedStatus as y };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "dsh-codearts",
3
3
  "displayName": "DSH CodeArts Connect",
4
4
  "description": "把华为云 CodeArts 接入 DeepSeek Harness —— 内置 OAuth2 登录(PKCE + DPoP),登录后即可在 DSH 对话窗口使用 CodeArts 的模型。",
5
- "version": "1.1.0",
5
+ "version": "1.1.3",
6
6
  "packageManager": "pnpm@11.24.0",
7
7
  "author": "elegant01",
8
8
  "keywords": [
@@ -82,6 +82,9 @@
82
82
  "platform": "web"
83
83
  }
84
84
  },
85
+ "dependencies": {
86
+ "@earendil-works/pi-ai": "^1.3.0"
87
+ },
85
88
  "peerDependencies": {
86
89
  "@deepseek-ai/cordis": "^4.0.2",
87
90
  "@deepseek-ai/dsh-atomic-write": ">=0.1.2-rc.1 <0.3.0-0",
@@ -92,7 +95,6 @@
92
95
  "@deepseek-ai/dsh-llm-pi-ai": ">=0.1.2-rc.1 <0.3.0-0",
93
96
  "@deepseek-ai/dsh-settings": ">=0.1.2-rc.1 <0.3.0-0",
94
97
  "@deepseek-ai/schemastery": "^3.18.2",
95
- "@earendil-works/pi-ai": ">=0.84.2 <2.0.0",
96
98
  "react": "^18.2.0"
97
99
  },
98
100
  "devDependencies": {