dsh-codearts 0.4.1 → 0.4.2
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/lib/bin.mjs +2 -2
- package/lib/client/index.d.cts +8 -2
- package/lib/client/index.js +78 -41
- package/lib/index.d.mts +14 -0
- package/lib/index.mjs +41 -16
- package/lib/{usage-D6EeUWiQ.mjs → usage-B4vQb1sP.mjs} +180 -1
- package/package.json +1 -1
package/lib/bin.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as
|
|
2
|
+
import { C as isBenefitModel, E as codeartsAccountsPath, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker, u as fetchCallerIdentity, w as CodeArtsAccountStore, x as FALLBACK_CODEARTS_MODELS } from "./usage-B4vQb1sP.mjs";
|
|
3
3
|
import { existsSync, statSync } from "node:fs";
|
|
4
4
|
//#region src/version.ts
|
|
5
|
-
const CODEARTS_VERSION = "0.4.
|
|
5
|
+
const CODEARTS_VERSION = "0.4.2";
|
|
6
6
|
//#endregion
|
|
7
7
|
//#region src/bin.ts
|
|
8
8
|
/**
|
package/lib/client/index.d.cts
CHANGED
|
@@ -67,8 +67,14 @@ interface CodeArtsSettingsKey {
|
|
|
67
67
|
creditsUnavailable: string;
|
|
68
68
|
creditsDock: string;
|
|
69
69
|
creditsDockTitle: string;
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
claimButton: string;
|
|
71
|
+
claimButtonDone: string;
|
|
72
|
+
claimPending: string;
|
|
73
|
+
claimHint: string;
|
|
74
|
+
claimDone: string;
|
|
75
|
+
claimAlready: string;
|
|
76
|
+
claimUnavailable: string;
|
|
77
|
+
claimFailed: string;
|
|
72
78
|
[key: string]: string;
|
|
73
79
|
}
|
|
74
80
|
//#endregion
|
package/lib/client/index.js
CHANGED
|
@@ -18,32 +18,32 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
|
|
|
18
18
|
document.head.appendChild(tag);
|
|
19
19
|
}
|
|
20
20
|
var CodeArtsPluginCard_module_css_default = {
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"error": "DZPfya_error",
|
|
21
|
+
"name": "DZPfya_name",
|
|
22
|
+
"actions": "DZPfya_actions",
|
|
24
23
|
"choiceRow": "DZPfya_choiceRow",
|
|
25
|
-
"fieldLabel": "DZPfya_fieldLabel",
|
|
26
|
-
"desc": "DZPfya_desc",
|
|
27
|
-
"card": "DZPfya_card",
|
|
28
|
-
"field": "DZPfya_field",
|
|
29
|
-
"header": "DZPfya_header",
|
|
30
|
-
"link": "DZPfya_link",
|
|
31
24
|
"manualSummary": "DZPfya_manualSummary",
|
|
32
|
-
"
|
|
33
|
-
"sectionLabel": "DZPfya_sectionLabel",
|
|
34
|
-
"headText": "DZPfya_headText",
|
|
35
|
-
"statusLine": "DZPfya_statusLine",
|
|
25
|
+
"field": "DZPfya_field",
|
|
36
26
|
"meta": "DZPfya_meta",
|
|
37
27
|
"headActions": "DZPfya_headActions",
|
|
38
|
-
"
|
|
28
|
+
"link": "DZPfya_link",
|
|
29
|
+
"manual": "DZPfya_manual",
|
|
30
|
+
"area": "DZPfya_area",
|
|
31
|
+
"headText": "DZPfya_headText",
|
|
39
32
|
"sectionHead": "DZPfya_sectionHead",
|
|
40
|
-
"
|
|
41
|
-
"actions": "DZPfya_actions",
|
|
42
|
-
"danger": "DZPfya_danger",
|
|
43
|
-
"count": "DZPfya_count",
|
|
33
|
+
"body": "DZPfya_body",
|
|
44
34
|
"hint": "DZPfya_hint",
|
|
35
|
+
"statusLine": "DZPfya_statusLine",
|
|
45
36
|
"choices": "DZPfya_choices",
|
|
46
|
-
"check": "DZPfya_check"
|
|
37
|
+
"check": "DZPfya_check",
|
|
38
|
+
"desc": "DZPfya_desc",
|
|
39
|
+
"count": "DZPfya_count",
|
|
40
|
+
"sectionLabel": "DZPfya_sectionLabel",
|
|
41
|
+
"fieldLabel": "DZPfya_fieldLabel",
|
|
42
|
+
"header": "DZPfya_header",
|
|
43
|
+
"card": "DZPfya_card",
|
|
44
|
+
"error": "DZPfya_error",
|
|
45
|
+
"danger": "DZPfya_danger",
|
|
46
|
+
"section": "DZPfya_section"
|
|
47
47
|
};
|
|
48
48
|
//#endregion
|
|
49
49
|
//#region src/client/CodeArtsPluginCard.tsx
|
|
@@ -84,21 +84,16 @@ function formatCredits(value) {
|
|
|
84
84
|
return Number.isFinite(value) ? new Intl.NumberFormat().format(Math.round(value)) : "0";
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
87
|
-
*
|
|
87
|
+
* 领取结果 → 文案。
|
|
88
88
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* `jumpToBrowser(INIT_CONFIG.personalUsageSettings, isOutSideOpen: true)`,URL 来自
|
|
92
|
-
* `vscode-codebot/product.json`)。也就是说积分的签到动作只在那一页上完成,AK/SK
|
|
93
|
-
* 网关那套(benefit/claim、statistics/plugin)里没有任何发积分的接口 —— 详见
|
|
94
|
-
* src/upstream.ts 的 claimBenefit:它开通的是「限时福利免费模型」渠道,不是积分。
|
|
89
|
+
* 本地状态(claimed/already/没有这个活动)用界面自己的话;只有 failed 才透出
|
|
90
|
+
* 上游给的 reason —— 那句往往才是排障要的东西(签名失败、404、非 JSON…)。
|
|
95
91
|
*/
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
window.open(`${CODEARTS_SIGN_IN_URL}?locale=${locale}`, "_blank", "noopener");
|
|
92
|
+
function claimText(data, t) {
|
|
93
|
+
if (data?.claimed === true) return t("claimDone", { amount: formatCredits(data.amount ?? 0) });
|
|
94
|
+
if (data?.state === "already") return t("claimAlready");
|
|
95
|
+
if (data?.state === "unavailable") return t("claimUnavailable");
|
|
96
|
+
return t("claimFailed", { message: typeof data?.message === "string" && data.message !== "" ? data.message : "request failed" });
|
|
102
97
|
}
|
|
103
98
|
/**
|
|
104
99
|
* 积分区块。
|
|
@@ -107,9 +102,10 @@ function openSignInPage() {
|
|
|
107
102
|
* 所以这里能直接显示账号总额度 —— 与下面的「本机用量」互补:一个是账号级、一个是
|
|
108
103
|
* 本机级。拉不到时显示原因(creditsError),不静默吞掉。
|
|
109
104
|
*/
|
|
110
|
-
function CreditsSection({ credits, error, t }) {
|
|
105
|
+
function CreditsSection({ credits, error, t, onClaim, claiming, claimResult, justClaimed }) {
|
|
111
106
|
if (credits === void 0 && error === void 0) return null;
|
|
112
107
|
const c = credits?.credits;
|
|
108
|
+
const claimedToday = justClaimed || credits?.welfare?.claimedToday === true;
|
|
113
109
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
114
110
|
className: CodeArtsPluginCard_module_css_default.section,
|
|
115
111
|
children: [
|
|
@@ -129,8 +125,9 @@ function CreditsSection({ credits, error, t }) {
|
|
|
129
125
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
130
126
|
variant: "outline",
|
|
131
127
|
size: "sm",
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
disabled: claiming || claimedToday,
|
|
129
|
+
onClick: onClaim,
|
|
130
|
+
children: claiming ? t("claimPending") : claimedToday ? t("claimButtonDone") : t("claimButton")
|
|
134
131
|
})]
|
|
135
132
|
})]
|
|
136
133
|
}),
|
|
@@ -140,7 +137,7 @@ function CreditsSection({ credits, error, t }) {
|
|
|
140
137
|
}),
|
|
141
138
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
142
139
|
className: CodeArtsPluginCard_module_css_default.hint,
|
|
143
|
-
children: t("
|
|
140
|
+
children: claimResult ?? t("claimHint")
|
|
144
141
|
}),
|
|
145
142
|
c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
146
143
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -311,6 +308,30 @@ function CodeArtsPluginCard({ t }) {
|
|
|
311
308
|
const [modelError, setModelError] = (0, react.useState)(null);
|
|
312
309
|
/** 账号身份是否展开:默认遮蔽(false = 显示 *******)。 */
|
|
313
310
|
const [accountsRevealed, setAccountsRevealed] = (0, react.useState)(false);
|
|
311
|
+
const [claiming, setClaiming] = (0, react.useState)(false);
|
|
312
|
+
const [claimResult, setClaimResult] = (0, react.useState)(null);
|
|
313
|
+
const [justClaimed, setJustClaimed] = (0, react.useState)(false);
|
|
314
|
+
/**
|
|
315
|
+
* 领一次每日签到积分。
|
|
316
|
+
*
|
|
317
|
+
* 除了这一次刚领成,「今天已领」都来自上游的福利活动状态(积分快照里的 welfare),
|
|
318
|
+
* 所以刷新、重开窗口都不会把按钮说错。领完不记日期:去重在上游按天做。
|
|
319
|
+
*/
|
|
320
|
+
async function claim() {
|
|
321
|
+
setClaiming(true);
|
|
322
|
+
try {
|
|
323
|
+
const data = await (await fetch("/api/codearts/claim", { method: "POST" })).json().catch(() => null);
|
|
324
|
+
setClaimResult(claimText(data, t));
|
|
325
|
+
if (data?.claimed === true) {
|
|
326
|
+
setJustClaimed(true);
|
|
327
|
+
await refresh();
|
|
328
|
+
}
|
|
329
|
+
} catch (error) {
|
|
330
|
+
setClaimResult(t("claimFailed", { message: error instanceof Error ? error.message : String(error) }));
|
|
331
|
+
} finally {
|
|
332
|
+
setClaiming(false);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
314
335
|
async function refresh() {
|
|
315
336
|
try {
|
|
316
337
|
const data = await (await fetch("/api/codearts/status", { headers: { Accept: "application/json" } })).json();
|
|
@@ -763,7 +784,11 @@ function CodeArtsPluginCard({ t }) {
|
|
|
763
784
|
signedIn && (status?.credits !== void 0 || status?.creditsError !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditsSection, {
|
|
764
785
|
credits: status?.credits,
|
|
765
786
|
error: status?.creditsError,
|
|
766
|
-
t
|
|
787
|
+
t,
|
|
788
|
+
onClaim: () => void claim(),
|
|
789
|
+
claiming,
|
|
790
|
+
claimResult,
|
|
791
|
+
justClaimed
|
|
767
792
|
}),
|
|
768
793
|
status?.usage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageSection, {
|
|
769
794
|
usage: status.usage,
|
|
@@ -930,8 +955,14 @@ const zh = {
|
|
|
930
955
|
creditsUnavailable: "积分不可用:{message}",
|
|
931
956
|
creditsDock: "积分 {remain}",
|
|
932
957
|
creditsDockTitle: "CodeArts 剩余积分 {remain} / {total}",
|
|
933
|
-
|
|
934
|
-
|
|
958
|
+
claimButton: "签到领积分",
|
|
959
|
+
claimButtonDone: "今日已领",
|
|
960
|
+
claimPending: "领取中…",
|
|
961
|
+
claimHint: "每天领一次 1000 积分,走官方福利中心接口(与客户端里那个「每日签到」同一件事)。",
|
|
962
|
+
claimDone: "已领取 {amount} 积分",
|
|
963
|
+
claimAlready: "今日已领,明天再来",
|
|
964
|
+
claimUnavailable: "这个账号当前没有可领的签到活动",
|
|
965
|
+
claimFailed: "领取失败:{message}"
|
|
935
966
|
};
|
|
936
967
|
const en = {
|
|
937
968
|
tabLabel: "CodeArts",
|
|
@@ -1000,8 +1031,14 @@ const en = {
|
|
|
1000
1031
|
creditsUnavailable: "Credits unavailable: {message}",
|
|
1001
1032
|
creditsDock: "Credits {remain}",
|
|
1002
1033
|
creditsDockTitle: "CodeArts credits left {remain} / {total}",
|
|
1003
|
-
|
|
1004
|
-
|
|
1034
|
+
claimButton: "Claim daily credits",
|
|
1035
|
+
claimButtonDone: "Claimed today",
|
|
1036
|
+
claimPending: "Claiming…",
|
|
1037
|
+
claimHint: "Claim 1,000 credits once a day through CodeArts’ welfare centre — the same check-in the official client does.",
|
|
1038
|
+
claimDone: "Claimed {amount} credits",
|
|
1039
|
+
claimAlready: "Already claimed today — come back tomorrow",
|
|
1040
|
+
claimUnavailable: "No check-in campaign available for this account",
|
|
1041
|
+
claimFailed: "Claim failed: {message}"
|
|
1005
1042
|
};
|
|
1006
1043
|
//#endregion
|
|
1007
1044
|
//#region src/client/index.tsx
|
package/lib/index.d.mts
CHANGED
|
@@ -581,10 +581,24 @@ interface CodeArtsTokenQuota {
|
|
|
581
581
|
/** 总额度。 */
|
|
582
582
|
quota: number;
|
|
583
583
|
}
|
|
584
|
+
/** 每日签到活动当前状态(来自福利中心 `/v1/ops/delivery`)。 */
|
|
585
|
+
interface CodeArtsDailyWelfare {
|
|
586
|
+
/** 上游说这条活动现在点得动吗。 */
|
|
587
|
+
claimable: boolean;
|
|
588
|
+
/**
|
|
589
|
+
* 「今天已经领过了」。单独判出来给卡片改按钮文案用 —— 不可领的原因有好几种
|
|
590
|
+
* (已领 / 要先去官网登录 / 账号没资格),只有这一种该把按钮变成「今日已领」。
|
|
591
|
+
*/
|
|
592
|
+
claimedToday: boolean;
|
|
593
|
+
/** 领一次给多少积分。 */
|
|
594
|
+
amount: number;
|
|
595
|
+
}
|
|
584
596
|
interface CodeArtsCreditSnapshot {
|
|
585
597
|
credits: CodeArtsCredits;
|
|
586
598
|
/** 拿不到(接口失败/不支持)时为 undefined,不影响积分本身。 */
|
|
587
599
|
tokens?: CodeArtsTokenQuota;
|
|
600
|
+
/** 没有这个活动(或账号是 token 套餐)时为 undefined。 */
|
|
601
|
+
welfare?: CodeArtsDailyWelfare;
|
|
588
602
|
}
|
|
589
603
|
/** 缓存里的一个结果:成功给值,失败给消息 —— 失败也要能被卡片看见。 */
|
|
590
604
|
type CodeArtsCreditState = {
|
package/lib/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as codeartsAccountsPath, S as
|
|
1
|
+
import { C as isBenefitModel, D as codeartsAuthPath, E as codeartsAccountsPath, O as startLogin, S as filterEnabledModels, T as CodeArtsCredentialStore, _ as pickDailyWelfareCampaign, a as SNAP_HOST, b as CodeArtsCatalog, c as claimDailyWelfare, d as fetchModels, f as fetchWelfareCampaigns, g as maxTokensCeilingFor, h as isWelfareClaimedStatus, i as refreshCatalog, l as degradeTokenCeiling, m as isParamInvalidFrame, n as codeartsUsagePath, o as canonicalModel, p as isConcurrencyCap, r as discoverModels, s as chatStream, t as CodeArtsUsageTracker, u as fetchCallerIdentity, v as prepareChatBody, w as CodeArtsAccountStore, x as FALLBACK_CODEARTS_MODELS, y as signedGet } from "./usage-B4vQb1sP.mjs";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
4
4
|
import { createServer } from "node:http";
|
|
@@ -273,18 +273,31 @@ function errorOf(action, result) {
|
|
|
273
273
|
* 它失败只让 `tokens` 缺席 —— 别让一个次要接口把主数字一起拖没。
|
|
274
274
|
*/
|
|
275
275
|
async function fetchCredits(credential, signal) {
|
|
276
|
-
const [statistics, balance] = await Promise.all([
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
276
|
+
const [statistics, balance, welfare] = await Promise.all([
|
|
277
|
+
signedGet(`${SNAP_HOST}${EP_STATISTICS_PLUGIN}`, credential, void 0, signal),
|
|
278
|
+
signedGet(`${BENEFIT_GATEWAY_HOST}${EP_TOKEN_BALANCE}`, credential, void 0, signal).catch(() => ({
|
|
279
|
+
ok: false,
|
|
280
|
+
status: 0,
|
|
281
|
+
message: "request failed"
|
|
282
|
+
})),
|
|
283
|
+
fetchWelfareCampaigns(credential, signal).then((campaigns) => {
|
|
284
|
+
const daily = pickDailyWelfareCampaign(campaigns);
|
|
285
|
+
if (daily === void 0) return void 0;
|
|
286
|
+
return {
|
|
287
|
+
claimable: daily.claimable,
|
|
288
|
+
claimedToday: !daily.claimable && isWelfareClaimedStatus(daily.status),
|
|
289
|
+
amount: daily.amount
|
|
290
|
+
};
|
|
291
|
+
}).catch(() => void 0)
|
|
292
|
+
]);
|
|
281
293
|
if (!statistics.ok) throw errorOf("statistics", statistics);
|
|
282
294
|
const credits = parseCreditStatistics(safeJson(statistics.text));
|
|
283
295
|
if (credits === void 0) throw new Error("statistics response carries no credit metrics");
|
|
284
296
|
const tokens = balance.ok ? parseTokenBalance(safeJson(balance.text)) : void 0;
|
|
285
297
|
return {
|
|
286
298
|
credits,
|
|
287
|
-
...tokens === void 0 ? {} : { tokens }
|
|
299
|
+
...tokens === void 0 ? {} : { tokens },
|
|
300
|
+
...welfare === void 0 ? {} : { welfare }
|
|
288
301
|
};
|
|
289
302
|
}
|
|
290
303
|
function safeJson(text) {
|
|
@@ -999,7 +1012,7 @@ const CODEARTS_LOGIN_PATH = "/api/codearts/login";
|
|
|
999
1012
|
const CODEARTS_LOGIN_STATUS_PATH = "/api/codearts/login/status";
|
|
1000
1013
|
/** 删除某个账号:DELETE /api/codearts/accounts?id=<accountId> */
|
|
1001
1014
|
const CODEARTS_ACCOUNTS_PATH = "/api/codearts/accounts";
|
|
1002
|
-
/** POST /api/codearts/claim —
|
|
1015
|
+
/** POST /api/codearts/claim — 领一次福利中心的每日签到积分(幂等由上游按天去重)。 */
|
|
1003
1016
|
const CODEARTS_CLAIM_PATH = "/api/codearts/claim";
|
|
1004
1017
|
/**
|
|
1005
1018
|
* 由完整目录 + 已存 enabled 计算 selection。
|
|
@@ -1333,7 +1346,7 @@ function accountsHandler(deps) {
|
|
|
1333
1346
|
}
|
|
1334
1347
|
};
|
|
1335
1348
|
}
|
|
1336
|
-
/** POST /api/codearts/claim —
|
|
1349
|
+
/** POST /api/codearts/claim — 领一次每日签到积分;未领到也回 200(看 claimed/state)。 */
|
|
1337
1350
|
function claimHandler(deps) {
|
|
1338
1351
|
return async (req, res) => {
|
|
1339
1352
|
if (req.method !== "POST") {
|
|
@@ -1350,14 +1363,13 @@ function claimHandler(deps) {
|
|
|
1350
1363
|
}
|
|
1351
1364
|
try {
|
|
1352
1365
|
const result = await deps.claim();
|
|
1353
|
-
|
|
1354
|
-
else json(res, 500, {
|
|
1355
|
-
ok: false,
|
|
1356
|
-
message: result.message
|
|
1357
|
-
});
|
|
1366
|
+
json(res, result.ok ? 200 : 500, result);
|
|
1358
1367
|
} catch (error) {
|
|
1359
1368
|
json(res, 500, {
|
|
1360
1369
|
ok: false,
|
|
1370
|
+
claimed: false,
|
|
1371
|
+
state: "failed",
|
|
1372
|
+
amount: 0,
|
|
1361
1373
|
message: safeMessage(error)
|
|
1362
1374
|
});
|
|
1363
1375
|
}
|
|
@@ -1654,16 +1666,29 @@ function apply(ctx, rawConfig) {
|
|
|
1654
1666
|
if (stored === void 0 || stored.stale === true) continue;
|
|
1655
1667
|
const resolved = await store.resolve(id);
|
|
1656
1668
|
if (resolved === void 0) continue;
|
|
1657
|
-
await
|
|
1658
|
-
|
|
1669
|
+
const outcome = await claimDailyWelfare(resolved, AbortSignal.timeout(2e4));
|
|
1670
|
+
if (outcome.state === "claimed") credits.invalidate();
|
|
1671
|
+
return {
|
|
1672
|
+
ok: outcome.state !== "failed",
|
|
1673
|
+
claimed: outcome.state === "claimed",
|
|
1674
|
+
state: outcome.state,
|
|
1675
|
+
amount: outcome.amount,
|
|
1676
|
+
message: outcome.message
|
|
1677
|
+
};
|
|
1659
1678
|
}
|
|
1660
1679
|
return {
|
|
1661
1680
|
ok: false,
|
|
1681
|
+
claimed: false,
|
|
1682
|
+
state: "failed",
|
|
1683
|
+
amount: 0,
|
|
1662
1684
|
message: "no usable credential"
|
|
1663
1685
|
};
|
|
1664
1686
|
} catch (error) {
|
|
1665
1687
|
return {
|
|
1666
1688
|
ok: false,
|
|
1689
|
+
claimed: false,
|
|
1690
|
+
state: "failed",
|
|
1691
|
+
amount: 0,
|
|
1667
1692
|
message: error instanceof Error ? error.message : String(error)
|
|
1668
1693
|
};
|
|
1669
1694
|
}
|
|
@@ -1168,13 +1168,17 @@ var upstream_exports = /* @__PURE__ */ __exportAll({
|
|
|
1168
1168
|
canonicalModel: () => canonicalModel,
|
|
1169
1169
|
chatStream: () => chatStream,
|
|
1170
1170
|
claimBenefit: () => claimBenefit,
|
|
1171
|
+
claimDailyWelfare: () => claimDailyWelfare,
|
|
1171
1172
|
degradeTokenCeiling: () => degradeTokenCeiling,
|
|
1172
1173
|
estimateTokens: () => estimateTokens,
|
|
1173
1174
|
fetchCallerIdentity: () => fetchCallerIdentity,
|
|
1174
1175
|
fetchModels: () => fetchModels,
|
|
1176
|
+
fetchWelfareCampaigns: () => fetchWelfareCampaigns,
|
|
1175
1177
|
isConcurrencyCap: () => isConcurrencyCap,
|
|
1176
1178
|
isParamInvalidFrame: () => isParamInvalidFrame,
|
|
1179
|
+
isWelfareClaimedStatus: () => isWelfareClaimedStatus,
|
|
1177
1180
|
maxTokensCeilingFor: () => maxTokensCeilingFor,
|
|
1181
|
+
pickDailyWelfareCampaign: () => pickDailyWelfareCampaign,
|
|
1178
1182
|
prepareChatBody: () => prepareChatBody,
|
|
1179
1183
|
signedGet: () => signedGet
|
|
1180
1184
|
});
|
|
@@ -1921,6 +1925,181 @@ async function claimBenefit(credential, abort) {
|
|
|
1921
1925
|
}
|
|
1922
1926
|
if (json.error_code !== "0000") throw new Error(`claim benefit rejected: ${json.error_code ?? "(no error_code)"} ${json.error_msg ?? ""}`.trim());
|
|
1923
1927
|
}
|
|
1928
|
+
/**
|
|
1929
|
+
* 福利中心(活动积分)接口:26.9.901 起应用内「每日签到领 1000 积分」走这套。
|
|
1930
|
+
*
|
|
1931
|
+
* host 与积分统计是同一个 snap-access 网关,路径前缀 `/v1/ops`,鉴权头对齐官方客户端
|
|
1932
|
+
* 的 `Pz()`(`x-auth-token` + `Agent-Type: PromptCenter`),再补上我们直连必须的
|
|
1933
|
+
* AK/SK 签名。三个实测出来的坑:
|
|
1934
|
+
*
|
|
1935
|
+
* 1. bundle 里 URL 有两套变体,带前缀的 `/PromptCenterService/v1/ops/*` 在这个网关上
|
|
1936
|
+
* 回 **404 APIG.0101(未发布)** —— 只有裸 `/v1/ops/*` 能用;
|
|
1937
|
+
* 2. 只带 `x-auth-token` 会被拒(`APIG.0301 decrypt token fail`);
|
|
1938
|
+
* 3. **业务失败也回 HTTP 200**,成败只看 body 的 `code`(0 才是成功)。
|
|
1939
|
+
* 今天已领时是 `code:40001 尚未到达权益刷新时间,暂时无法领取`。
|
|
1940
|
+
*
|
|
1941
|
+
* 领的是「活动」而不是额度:`/ops/delivery` 给活动清单(含 campaignId / status /
|
|
1942
|
+
* claimable),`/ops/claim` 按 campaignId 领。`idempotentKey` 上游不返回,官方客户端
|
|
1943
|
+
* 自己生成随机串(与 `x-snap-traceid` 同一个生成器),按天去重落在服务端。
|
|
1944
|
+
*/
|
|
1945
|
+
const EP_OPS_DELIVERY = "/v1/ops/delivery";
|
|
1946
|
+
const EP_OPS_CLAIM = "/v1/ops/claim";
|
|
1947
|
+
/** 每日签到活动的 type(实测为 campaignId 1,benefitAmount 1000 CREDIT)。 */
|
|
1948
|
+
const WELFARE_DAILY_TYPE = "USER_LOGIN";
|
|
1949
|
+
/** 上游按钮文案的状态机:这几个都表示「今天已经领过了」。 */
|
|
1950
|
+
const WELFARE_ALREADY_STATES = /* @__PURE__ */ new Set([
|
|
1951
|
+
"CLAIMED",
|
|
1952
|
+
"CONFIRMED",
|
|
1953
|
+
"CONSUMED"
|
|
1954
|
+
]);
|
|
1955
|
+
/** 活动状态是不是「今天已经领过了」(区别于「要先登录」「没资格」这些同样不可领的情况)。 */
|
|
1956
|
+
function isWelfareClaimedStatus(status) {
|
|
1957
|
+
return WELFARE_ALREADY_STATES.has(status);
|
|
1958
|
+
}
|
|
1959
|
+
/**
|
|
1960
|
+
* 「今日已领」的业务码。
|
|
1961
|
+
*
|
|
1962
|
+
* 这个分支不是冗余的:领取成功后的几十秒里 delivery 有可能还回一份**陈旧**的
|
|
1963
|
+
* `claimable:true / ELIGIBLE`(实测 2026-10-16,领完立刻读会看到),于是会真的
|
|
1964
|
+
* POST 第二次 —— 服务端按天去重回这个码,所以按「已领」处理,不能当失败。
|
|
1965
|
+
*/
|
|
1966
|
+
const WELFARE_CODE_NOT_YET = 40001;
|
|
1967
|
+
/** 福利接口的请求:签名 + 官方那套头,返回解析后的 body。 */
|
|
1968
|
+
async function welfareRequest(url, method, credential, body, signal) {
|
|
1969
|
+
const req = new Request(url, {
|
|
1970
|
+
method,
|
|
1971
|
+
headers: {
|
|
1972
|
+
"Content-Type": "application/json",
|
|
1973
|
+
"X-Language": "zh-cn",
|
|
1974
|
+
"x-snap-traceid": hex32(),
|
|
1975
|
+
"x-auth-token": credential.token,
|
|
1976
|
+
"Agent-Type": "PromptCenter",
|
|
1977
|
+
"X-Security-Token": credential.securityToken
|
|
1978
|
+
},
|
|
1979
|
+
...body === void 0 ? {} : { body }
|
|
1980
|
+
});
|
|
1981
|
+
const bodyBuf = Buffer.from(body ?? "");
|
|
1982
|
+
if (credential.accessKeyId !== void 0 && credential.secretAccessKey !== void 0) signRequest(req, bodyBuf, {
|
|
1983
|
+
accessKeyId: credential.accessKeyId,
|
|
1984
|
+
secretAccessKey: credential.secretAccessKey,
|
|
1985
|
+
securityToken: credential.securityToken
|
|
1986
|
+
});
|
|
1987
|
+
let resp;
|
|
1988
|
+
try {
|
|
1989
|
+
resp = await fetch(req, { signal });
|
|
1990
|
+
} catch (error) {
|
|
1991
|
+
return {
|
|
1992
|
+
ok: false,
|
|
1993
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
const text = await resp.text().catch(() => "");
|
|
1997
|
+
if (!resp.ok) return {
|
|
1998
|
+
ok: false,
|
|
1999
|
+
message: `HTTP ${resp.status} ${text.slice(0, 200)}`
|
|
2000
|
+
};
|
|
2001
|
+
let parsed;
|
|
2002
|
+
try {
|
|
2003
|
+
parsed = JSON.parse(text);
|
|
2004
|
+
} catch {
|
|
2005
|
+
return {
|
|
2006
|
+
ok: false,
|
|
2007
|
+
message: `unexpected non-JSON response: ${text.slice(0, 200)}`
|
|
2008
|
+
};
|
|
2009
|
+
}
|
|
2010
|
+
const envelope = asRecord(parsed);
|
|
2011
|
+
return {
|
|
2012
|
+
ok: true,
|
|
2013
|
+
code: typeof envelope.code === "number" ? envelope.code : -1,
|
|
2014
|
+
message: firstString(envelope.message),
|
|
2015
|
+
data: envelope.data
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
/** 活动清单(`GET /v1/ops/delivery?channel=IDE`)。 */
|
|
2019
|
+
async function fetchWelfareCampaigns(credential, signal) {
|
|
2020
|
+
const resp = await welfareRequest(`${SNAP_HOST}${EP_OPS_DELIVERY}?channel=IDE`, "GET", credential, void 0, signal);
|
|
2021
|
+
if (!resp.ok) throw new Error(`welfare delivery: ${resp.message}`);
|
|
2022
|
+
return asArray(asRecord(resp.data).items).flatMap((item) => {
|
|
2023
|
+
const raw = asRecord(item);
|
|
2024
|
+
const campaignId = typeof raw.campaignId === "number" ? raw.campaignId : NaN;
|
|
2025
|
+
if (Number.isFinite(campaignId) === false) return [];
|
|
2026
|
+
return [{
|
|
2027
|
+
campaignId,
|
|
2028
|
+
title: firstString(raw.title),
|
|
2029
|
+
type: firstString(raw.type),
|
|
2030
|
+
amount: typeof raw.benefitAmount === "number" ? raw.benefitAmount : 0,
|
|
2031
|
+
unit: firstString(raw.benefitUnit),
|
|
2032
|
+
claimable: raw.claimable === true,
|
|
2033
|
+
status: firstString(raw.status)
|
|
2034
|
+
}];
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2037
|
+
/**
|
|
2038
|
+
* 从活动清单里挑「每日签到」那条。
|
|
2039
|
+
*
|
|
2040
|
+
* 同一个 type 理论上可能有多条(上游换活动的时候),优先挑当前可领的那条。
|
|
2041
|
+
*/
|
|
2042
|
+
function pickDailyWelfareCampaign(campaigns) {
|
|
2043
|
+
const daily = campaigns.filter((c) => c.type === WELFARE_DAILY_TYPE && c.unit === "CREDIT");
|
|
2044
|
+
return daily.find((c) => c.claimable) ?? daily[0];
|
|
2045
|
+
}
|
|
2046
|
+
/**
|
|
2047
|
+
* 领一次每日签到积分。
|
|
2048
|
+
*
|
|
2049
|
+
* 不抛异常:这是卡片上一个按钮的后续,失败要变成能显示的文案而不是断掉的请求。
|
|
2050
|
+
*/
|
|
2051
|
+
async function claimDailyWelfare(credential, signal) {
|
|
2052
|
+
if (credential.accessKeyId === void 0 || credential.secretAccessKey === void 0) return {
|
|
2053
|
+
state: "failed",
|
|
2054
|
+
amount: 0,
|
|
2055
|
+
message: "no AK/SK to sign"
|
|
2056
|
+
};
|
|
2057
|
+
let campaigns;
|
|
2058
|
+
try {
|
|
2059
|
+
campaigns = await fetchWelfareCampaigns(credential, signal);
|
|
2060
|
+
} catch (error) {
|
|
2061
|
+
return {
|
|
2062
|
+
state: "failed",
|
|
2063
|
+
amount: 0,
|
|
2064
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2065
|
+
};
|
|
2066
|
+
}
|
|
2067
|
+
const target = pickDailyWelfareCampaign(campaigns);
|
|
2068
|
+
if (target === void 0) return {
|
|
2069
|
+
state: "unavailable",
|
|
2070
|
+
amount: 0,
|
|
2071
|
+
message: "no daily check-in campaign"
|
|
2072
|
+
};
|
|
2073
|
+
if (!target.claimable) return isWelfareClaimedStatus(target.status) ? {
|
|
2074
|
+
state: "already",
|
|
2075
|
+
amount: 0,
|
|
2076
|
+
message: ""
|
|
2077
|
+
} : {
|
|
2078
|
+
state: "unavailable",
|
|
2079
|
+
amount: 0,
|
|
2080
|
+
message: target.status
|
|
2081
|
+
};
|
|
2082
|
+
const resp = await welfareRequest(`${SNAP_HOST}${EP_OPS_CLAIM}`, "POST", credential, JSON.stringify({
|
|
2083
|
+
campaignId: target.campaignId,
|
|
2084
|
+
idempotentKey: hex32(),
|
|
2085
|
+
channel: "IDE"
|
|
2086
|
+
}), signal);
|
|
2087
|
+
if (!resp.ok) return {
|
|
2088
|
+
state: "failed",
|
|
2089
|
+
amount: 0,
|
|
2090
|
+
message: resp.message
|
|
2091
|
+
};
|
|
2092
|
+
if (resp.code === 0) return {
|
|
2093
|
+
state: "claimed",
|
|
2094
|
+
amount: target.amount,
|
|
2095
|
+
message: resp.message
|
|
2096
|
+
};
|
|
2097
|
+
return {
|
|
2098
|
+
state: resp.code === WELFARE_CODE_NOT_YET ? "already" : "failed",
|
|
2099
|
+
amount: 0,
|
|
2100
|
+
message: resp.message
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
1924
2103
|
//#endregion
|
|
1925
2104
|
//#region src/discovery.ts
|
|
1926
2105
|
/**
|
|
@@ -2225,4 +2404,4 @@ function sumOf(store) {
|
|
|
2225
2404
|
return out;
|
|
2226
2405
|
}
|
|
2227
2406
|
//#endregion
|
|
2228
|
-
export {
|
|
2407
|
+
export { isBenefitModel as C, codeartsAuthPath as D, codeartsAccountsPath as E, startLogin as O, filterEnabledModels as S, CodeArtsCredentialStore as T, pickDailyWelfareCampaign as _, SNAP_HOST as a, CodeArtsCatalog as b, claimDailyWelfare as c, fetchModels as d, fetchWelfareCampaigns as f, maxTokensCeilingFor as g, isWelfareClaimedStatus as h, refreshCatalog as i, degradeTokenCeiling as l, isParamInvalidFrame as m, codeartsUsagePath as n, canonicalModel as o, isConcurrencyCap as p, discoverModels as r, chatStream as s, CodeArtsUsageTracker as t, fetchCallerIdentity as u, prepareChatBody as v, CodeArtsAccountStore as w, FALLBACK_CODEARTS_MODELS as x, signedGet 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": "0.4.
|
|
5
|
+
"version": "0.4.2",
|
|
6
6
|
"author": "elegant01",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"dsh-plugin",
|