dsh-codearts 1.2.9 → 1.2.11
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 +29 -0
- package/lib/bin.mjs +1 -4
- package/lib/client/index.d.cts +45 -0
- package/lib/client/index.js +530 -198
- package/lib/index.d.mts +75 -1
- package/lib/index.mjs +280 -26
- package/lib/{usage-B2LNsUuR.mjs → version-Dq3wXMop.mjs} +176 -13
- package/package.json +1 -1
|
@@ -565,7 +565,9 @@ function summarizeAccount(id, cred) {
|
|
|
565
565
|
...cred.expiration === void 0 ? {} : { expiration: cred.expiration },
|
|
566
566
|
...cred.storedAt === void 0 ? {} : { storedAt: cred.storedAt },
|
|
567
567
|
stale: cred.stale === true,
|
|
568
|
-
signable: typeof cred.accessKeyId === "string" && cred.accessKeyId !== "" && typeof cred.secretAccessKey === "string" && cred.secretAccessKey !== ""
|
|
568
|
+
signable: typeof cred.accessKeyId === "string" && cred.accessKeyId !== "" && typeof cred.secretAccessKey === "string" && cred.secretAccessKey !== "",
|
|
569
|
+
paused: cred.paused === true,
|
|
570
|
+
pinned: cred.pinned === true
|
|
569
571
|
};
|
|
570
572
|
}
|
|
571
573
|
/**
|
|
@@ -840,6 +842,58 @@ var CodeArtsAccountStore = class {
|
|
|
840
842
|
doc.order = doc.order.filter((existing) => existing !== id);
|
|
841
843
|
await this.persistDoc();
|
|
842
844
|
}
|
|
845
|
+
/**
|
|
846
|
+
* 暂停 / 恢复一个账号。
|
|
847
|
+
*
|
|
848
|
+
* 只改标记,不碰凭证:恢复时不需要重新登录。重新装配槽位是因为 AccountSlot
|
|
849
|
+
* 缓存的 `_cred` 是旧对象,续期回写会把它盖回来 —— 换了对象,续期写到新文档里。
|
|
850
|
+
*/
|
|
851
|
+
async setPaused(id, paused) {
|
|
852
|
+
await this.loaded();
|
|
853
|
+
const doc = this._doc;
|
|
854
|
+
const cred = doc.accounts[id];
|
|
855
|
+
if (cred === void 0) return false;
|
|
856
|
+
doc.accounts[id] = {
|
|
857
|
+
...cred,
|
|
858
|
+
paused
|
|
859
|
+
};
|
|
860
|
+
this._slots.get(id)?.invalidate();
|
|
861
|
+
this._slots.set(id, new AccountSlot(doc.accounts[id], this.persisterFor(id)));
|
|
862
|
+
await this.persistDoc();
|
|
863
|
+
return true;
|
|
864
|
+
}
|
|
865
|
+
/** 置顶 / 取消置顶:只改变轮转先后,不绕过冷却与并发上限。 */
|
|
866
|
+
async setPinned(id, pinned) {
|
|
867
|
+
await this.loaded();
|
|
868
|
+
const doc = this._doc;
|
|
869
|
+
const cred = doc.accounts[id];
|
|
870
|
+
if (cred === void 0) return false;
|
|
871
|
+
doc.accounts[id] = {
|
|
872
|
+
...cred,
|
|
873
|
+
pinned
|
|
874
|
+
};
|
|
875
|
+
this._slots.get(id)?.invalidate();
|
|
876
|
+
this._slots.set(id, new AccountSlot(doc.accounts[id], this.persisterFor(id)));
|
|
877
|
+
await this.persistDoc();
|
|
878
|
+
return true;
|
|
879
|
+
}
|
|
880
|
+
/** shim 用:参与轮转的账号 id(排除用户暂停的)。 */
|
|
881
|
+
async dispatchIds() {
|
|
882
|
+
const paused = new Set(await this.pausedIds());
|
|
883
|
+
return (await this.ids()).filter((id) => !paused.has(id));
|
|
884
|
+
}
|
|
885
|
+
/** 被用户暂停的账号 id(账号池据此保留状态但不派活)。 */
|
|
886
|
+
async pausedIds() {
|
|
887
|
+
await this.loaded();
|
|
888
|
+
const doc = this._doc;
|
|
889
|
+
return (await this.ids()).filter((id) => doc.accounts[id]?.paused === true);
|
|
890
|
+
}
|
|
891
|
+
/** 置顶账号的 id 列表(给账号池排序用)。 */
|
|
892
|
+
async pinnedIds() {
|
|
893
|
+
await this.loaded();
|
|
894
|
+
const doc = this._doc;
|
|
895
|
+
return (await this.ids()).filter((id) => doc.accounts[id]?.pinned === true);
|
|
896
|
+
}
|
|
843
897
|
/** 清空全部账号(整体登出)。 */
|
|
844
898
|
async clear() {
|
|
845
899
|
await this.loaded();
|
|
@@ -2405,6 +2459,7 @@ async function fetchModels(credential, signal) {
|
|
|
2405
2459
|
return {
|
|
2406
2460
|
...model,
|
|
2407
2461
|
...thinking === void 0 ? {} : { thinking },
|
|
2462
|
+
contextWindowKnown: model.contextWindow > 0,
|
|
2408
2463
|
contextWindow: model.contextWindow > 0 ? model.contextWindow : UNKNOWN_CONTEXT_WINDOW,
|
|
2409
2464
|
maxTokens: Math.min(model.maxTokens > 0 ? model.maxTokens : UNKNOWN_MAX_TOKENS, maxTokensCeilingFor(model.id))
|
|
2410
2465
|
};
|
|
@@ -2742,6 +2797,21 @@ function codeartsUsagePath(home) {
|
|
|
2742
2797
|
const base = home ?? process.env.DSH_HOME ?? join(homedir(), ".dsh");
|
|
2743
2798
|
return join(base, ".codearts-usage.json");
|
|
2744
2799
|
}
|
|
2800
|
+
/** 首字延迟分桶的上界(毫秒);落进最后一档表示「超过 30 秒」。 */
|
|
2801
|
+
const TTFT_BUCKETS_MS = [
|
|
2802
|
+
200,
|
|
2803
|
+
500,
|
|
2804
|
+
1e3,
|
|
2805
|
+
2e3,
|
|
2806
|
+
3e3,
|
|
2807
|
+
5e3,
|
|
2808
|
+
8e3,
|
|
2809
|
+
12e3,
|
|
2810
|
+
2e4,
|
|
2811
|
+
3e4
|
|
2812
|
+
];
|
|
2813
|
+
/** 直方图桶数(含溢出档)。 */
|
|
2814
|
+
const TTFT_BUCKET_COUNT = TTFT_BUCKETS_MS.length + 1;
|
|
2745
2815
|
function emptyTotals() {
|
|
2746
2816
|
return {
|
|
2747
2817
|
requests: 0,
|
|
@@ -2847,6 +2917,22 @@ function normalizeStore(store) {
|
|
|
2847
2917
|
}
|
|
2848
2918
|
return out;
|
|
2849
2919
|
}
|
|
2920
|
+
/** 计数表(失败类别 / 账号失败数)补齐:只留正数,空表给 undefined。 */
|
|
2921
|
+
function normalizeCounts(raw) {
|
|
2922
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
2923
|
+
const out = {};
|
|
2924
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
2925
|
+
const count = positiveInt(value);
|
|
2926
|
+
if (count > 0) out[key] = count;
|
|
2927
|
+
}
|
|
2928
|
+
return Object.keys(out).length === 0 ? void 0 : out;
|
|
2929
|
+
}
|
|
2930
|
+
/** 首字延迟直方图补齐到固定桶数;旧账本/脏数组一律按空表。 */
|
|
2931
|
+
function normalizeBuckets(raw) {
|
|
2932
|
+
if (!Array.isArray(raw)) return void 0;
|
|
2933
|
+
const out = Array.from({ length: TTFT_BUCKET_COUNT }, (_, index) => positiveInt(raw[index]));
|
|
2934
|
+
return out.some((count) => count > 0) ? out : void 0;
|
|
2935
|
+
}
|
|
2850
2936
|
/**
|
|
2851
2937
|
* 用量账本。
|
|
2852
2938
|
*
|
|
@@ -2885,17 +2971,19 @@ var CodeArtsUsageTracker = class {
|
|
|
2885
2971
|
if (parsed.version !== 1 || typeof parsed.days !== "object" || parsed.days === null) return;
|
|
2886
2972
|
for (const [date, day] of Object.entries(parsed.days)) {
|
|
2887
2973
|
if (typeof day !== "object" || day === null) continue;
|
|
2888
|
-
const
|
|
2889
|
-
const
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2974
|
+
const stored = day;
|
|
2975
|
+
const restored = {
|
|
2976
|
+
models: normalizeStore(stored.models),
|
|
2977
|
+
accounts: normalizeStore(stored.accounts)
|
|
2978
|
+
};
|
|
2979
|
+
if (stored.hours !== void 0) restored.hours = normalizeStore(stored.hours);
|
|
2980
|
+
const failures = normalizeCounts(stored.failures);
|
|
2981
|
+
if (failures !== void 0) restored.failures = failures;
|
|
2982
|
+
const failuresByAccount = normalizeCounts(stored.failuresByAccount);
|
|
2983
|
+
if (failuresByAccount !== void 0) restored.failuresByAccount = failuresByAccount;
|
|
2984
|
+
const ttft = normalizeBuckets(stored.ttft);
|
|
2985
|
+
if (ttft !== void 0) restored.ttft = ttft;
|
|
2986
|
+
this.days.set(date, restored);
|
|
2899
2987
|
}
|
|
2900
2988
|
this.prune(this.now());
|
|
2901
2989
|
} catch {
|
|
@@ -2951,6 +3039,42 @@ var CodeArtsUsageTracker = class {
|
|
|
2951
3039
|
return day.hours;
|
|
2952
3040
|
}
|
|
2953
3041
|
/**
|
|
3042
|
+
* 记一次失败请求。
|
|
3043
|
+
*
|
|
3044
|
+
* 只在「这次请求最终回给用户一个错误」时调用一次 —— 插件内部换号重试不算失败,
|
|
3045
|
+
* 否则一个排队重试就能把失败率刷成好几倍。`kind` 用 shim 的失败出口标识。
|
|
3046
|
+
*/
|
|
3047
|
+
noteFailure(kind, accountId, at = this.now()) {
|
|
3048
|
+
if (kind === "") return;
|
|
3049
|
+
const day = this.day(localDateKey(at));
|
|
3050
|
+
day.failures ??= {};
|
|
3051
|
+
day.failures[kind] = (day.failures[kind] ?? 0) + 1;
|
|
3052
|
+
if (accountId !== void 0 && accountId !== "") {
|
|
3053
|
+
day.failuresByAccount ??= {};
|
|
3054
|
+
day.failuresByAccount[accountId] = (day.failuresByAccount[accountId] ?? 0) + 1;
|
|
3055
|
+
}
|
|
3056
|
+
this.lastAt = at;
|
|
3057
|
+
this.prune(at);
|
|
3058
|
+
this.scheduleSave();
|
|
3059
|
+
}
|
|
3060
|
+
/**
|
|
3061
|
+
* 记一次首字延迟(毫秒),落进直方图。
|
|
3062
|
+
*
|
|
3063
|
+
* 从请求进入 shim 算起,到上游第一帧真的写给 DSH 为止 —— 排队和换号的时间都算进去,
|
|
3064
|
+
* 因为那正是用户盯着转圈等掉的时长。
|
|
3065
|
+
*/
|
|
3066
|
+
noteLatency(ms, at = this.now()) {
|
|
3067
|
+
if (!Number.isFinite(ms) || ms < 0) return;
|
|
3068
|
+
const day = this.day(localDateKey(at));
|
|
3069
|
+
day.ttft ??= new Array(TTFT_BUCKET_COUNT).fill(0);
|
|
3070
|
+
let index = TTFT_BUCKETS_MS.findIndex((limit) => ms <= limit);
|
|
3071
|
+
if (index < 0) index = TTFT_BUCKET_COUNT - 1;
|
|
3072
|
+
day.ttft[index] += 1;
|
|
3073
|
+
this.lastAt = at;
|
|
3074
|
+
this.prune(at);
|
|
3075
|
+
this.scheduleSave();
|
|
3076
|
+
}
|
|
3077
|
+
/**
|
|
2954
3078
|
* 丢弃保留期之外的天(按日期键比较即可,YYYY-MM-DD 是字典序)。
|
|
2955
3079
|
*
|
|
2956
3080
|
* 顺带把两天之前的**小时桶**清掉:逐小时数据只有「今天按小时」在画,留着只是
|
|
@@ -2975,6 +3099,10 @@ var CodeArtsUsageTracker = class {
|
|
|
2975
3099
|
if (date >= cutoff) mergeTotals(last30, totals);
|
|
2976
3100
|
}
|
|
2977
3101
|
const models = today?.models ?? {};
|
|
3102
|
+
const failuresByKind = today?.failures ?? {};
|
|
3103
|
+
const ttft = today?.ttft ?? [];
|
|
3104
|
+
const p50 = percentileOf(ttft, .5);
|
|
3105
|
+
const p95 = percentileOf(ttft, .95);
|
|
2978
3106
|
return {
|
|
2979
3107
|
today: {
|
|
2980
3108
|
...emptyTotals(),
|
|
@@ -2982,6 +3110,17 @@ var CodeArtsUsageTracker = class {
|
|
|
2982
3110
|
},
|
|
2983
3111
|
allTime,
|
|
2984
3112
|
last30,
|
|
3113
|
+
failuresToday: {
|
|
3114
|
+
total: Object.values(failuresByKind).reduce((sum, count) => sum + count, 0),
|
|
3115
|
+
byKind: { ...failuresByKind }
|
|
3116
|
+
},
|
|
3117
|
+
failuresByAccountToday: { ...today?.failuresByAccount ?? {} },
|
|
3118
|
+
latencyToday: {
|
|
3119
|
+
samples: ttft.reduce((sum, count) => sum + count, 0),
|
|
3120
|
+
...p50.value === void 0 ? {} : { p50: p50.value },
|
|
3121
|
+
...p95.value === void 0 ? {} : { p95: p95.value },
|
|
3122
|
+
overflow: p95.overflow
|
|
3123
|
+
},
|
|
2985
3124
|
byModelToday: Object.entries(models).map(([id, totals]) => ({
|
|
2986
3125
|
id,
|
|
2987
3126
|
totals: { ...totals }
|
|
@@ -3051,5 +3190,29 @@ function sumOf(store) {
|
|
|
3051
3190
|
for (const totals of Object.values(store)) mergeTotals(out, totals);
|
|
3052
3191
|
return out;
|
|
3053
3192
|
}
|
|
3193
|
+
/**
|
|
3194
|
+
* 直方图分位。
|
|
3195
|
+
*
|
|
3196
|
+
* 返回的是「落进的那一档的上界」而不是精确毫秒 —— 界面上显示 `≤200ms` 这种口径,
|
|
3197
|
+
* 比伪造一个精确值诚实。落进溢出档时 `value` 缺省、`overflow` 为真。
|
|
3198
|
+
*/
|
|
3199
|
+
function percentileOf(buckets, ratio) {
|
|
3200
|
+
const total = buckets.reduce((sum, count) => sum + count, 0);
|
|
3201
|
+
if (total === 0) return { overflow: false };
|
|
3202
|
+
const target = Math.ceil(total * ratio);
|
|
3203
|
+
let seen = 0;
|
|
3204
|
+
for (let index = 0; index < buckets.length; index += 1) {
|
|
3205
|
+
seen += buckets[index] ?? 0;
|
|
3206
|
+
if (seen < target) continue;
|
|
3207
|
+
return index < TTFT_BUCKETS_MS.length ? {
|
|
3208
|
+
value: TTFT_BUCKETS_MS[index],
|
|
3209
|
+
overflow: false
|
|
3210
|
+
} : { overflow: true };
|
|
3211
|
+
}
|
|
3212
|
+
return { overflow: true };
|
|
3213
|
+
}
|
|
3214
|
+
//#endregion
|
|
3215
|
+
//#region src/version.ts
|
|
3216
|
+
const CODEARTS_VERSION = "1.2.11";
|
|
3054
3217
|
//#endregion
|
|
3055
|
-
export {
|
|
3218
|
+
export { signedGet as A, markModelUnavailable as B, isTpmLimit as C, pickDailyWelfareCampaign as D, modelUnavailableReasonText as E, creditRatioLabel as F, codeartsAccountsPath as G, CodeArtsAccountStore as H, filterEnabledModels as I, startLogin as J, codeartsAuthPath as K, forgetModelUnavailable as L, CodeArtsCatalog as M, FALLBACK_CODEARTS_MODELS as N, prepareChatBody as O, clearBenefitBlocked as P, isBenefitBlocked as R, isQueueableRate as S, maxTokensCeilingFor as T, CodeArtsCredentialStore as U, modelUnavailableReason as V, MANUAL_ACCOUNT_ID as W, isConcurrencyCap as _, refreshCatalog as a, isNotMultimodal as b, chatStream as c, degradeTokenCeiling as d, fetchCallerIdentity as f, firstFrameError as g, fetchWelfareCampaigns as h, discoverModels as i, upstreamErrorMessage as j, rateLimitFrame as k, claimDailyWelfare as l, fetchQueueStatus as m, CodeArtsUsageTracker as n, SNAP_HOST as o, fetchModels as p, credentialFromOAuth as q, codeartsUsagePath as r, canonicalModel as s, CODEARTS_VERSION as t, clearQueueStatus as u, isIamTokenError as v, isWelfareClaimedStatus as w, isParamInvalidFrame as x, isModelNotAccessible as y, isBenefitModel as z };
|
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.2.
|
|
5
|
+
"version": "1.2.11",
|
|
6
6
|
"packageManager": "pnpm@11.24.0",
|
|
7
7
|
"author": "elegant01",
|
|
8
8
|
"keywords": [
|