dsh-codearts 1.1.4 → 1.2.1
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 +64 -0
- package/lib/bin.mjs +2 -2
- package/lib/client/index.d.cts +19 -0
- package/lib/client/index.js +635 -90
- package/lib/index.d.mts +5 -1
- package/lib/index.mjs +142 -25
- package/lib/{usage-B0NfG8vZ.mjs → usage-05PgtUIP.mjs} +7 -0
- package/package.json +1 -1
package/lib/index.d.mts
CHANGED
|
@@ -1572,10 +1572,14 @@ declare const name = "llm-codearts";
|
|
|
1572
1572
|
declare const inject: string[];
|
|
1573
1573
|
/** Settings namespace owning the configuration card. */
|
|
1574
1574
|
declare const CODEARTS_SETTINGS_NS: SettingsNamespace;
|
|
1575
|
-
/** Plugin configuration
|
|
1575
|
+
/** Plugin configuration. */
|
|
1576
1576
|
interface Config {
|
|
1577
1577
|
/** Allowlist of CodeArts model ids offered in the model pickers. */
|
|
1578
1578
|
enabledModels?: string[];
|
|
1579
|
+
/** 对话输入框下方那行「积分 N」是否显示。缺省 = 显示(老配置不改行为)。 */
|
|
1580
|
+
showCreditDock?: boolean;
|
|
1581
|
+
/** 等上游开流时那行「排队第 N 位」是否显示。缺省 = 显示。 */
|
|
1582
|
+
showQueueDock?: boolean;
|
|
1579
1583
|
}
|
|
1580
1584
|
declare const Config: z<Config>;
|
|
1581
1585
|
declare function apply(ctx: Context, rawConfig: Config): void;
|
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 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-
|
|
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-05PgtUIP.mjs";
|
|
2
2
|
import { i as lazyApi, r as createProvider } from "./models-CgKCibpk.mjs";
|
|
3
3
|
import z from "@deepseek-ai/schemastery";
|
|
4
4
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
@@ -1404,6 +1404,11 @@ const CODEARTS_CLAIM_PATH = "/api/codearts/claim";
|
|
|
1404
1404
|
const CODEARTS_REFRESH_MODELS_PATH = "/api/codearts/refresh-models";
|
|
1405
1405
|
/** GET /api/codearts/queue — 上游排队位置(只在等开流期间有值,底部积分条旁边展示)。 */
|
|
1406
1406
|
const CODEARTS_QUEUE_PATH = "/api/codearts/queue";
|
|
1407
|
+
/**
|
|
1408
|
+
* GET/POST /api/codearts/dock — 对话底部那一行的显隐开关。
|
|
1409
|
+
* GET 给当前值与 writable,POST 收 `{credits?, queue?}` 写进 settings。
|
|
1410
|
+
*/
|
|
1411
|
+
const CODEARTS_DOCK_PATH = "/api/codearts/dock";
|
|
1407
1412
|
/** 最近出站请求的**形状**摘要(只有 role 名与计数,不含内容),排障用。 */
|
|
1408
1413
|
const CODEARTS_DEBUG_PATH = "/api/codearts/debug";
|
|
1409
1414
|
/**
|
|
@@ -1422,6 +1427,7 @@ function selectionOf(models, enabled, writable) {
|
|
|
1422
1427
|
benefit: m.benefit,
|
|
1423
1428
|
blocked: m.blocked,
|
|
1424
1429
|
ratio: m.ratio,
|
|
1430
|
+
supportsImages: m.supportsImages,
|
|
1425
1431
|
enabled: restricted ? allowed.has(m.id) : true
|
|
1426
1432
|
})),
|
|
1427
1433
|
restricted,
|
|
@@ -1438,10 +1444,32 @@ function choicesOf(deps) {
|
|
|
1438
1444
|
name: m.name,
|
|
1439
1445
|
benefit,
|
|
1440
1446
|
blocked: isBenefitBlocked(m.id),
|
|
1447
|
+
...ratio === void 0 ? {} : { ratio },
|
|
1448
|
+
...m.supportsImages === true ? { supportsImages: true } : {}
|
|
1449
|
+
};
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
/**
|
|
1453
|
+
* 目录 -> 底栏/卡片用的模型徽章。
|
|
1454
|
+
*
|
|
1455
|
+
* 倍率在这里就算好(`creditRatioLabel`:福利恒为 `x0.00`),客户端拿到的是可以直接
|
|
1456
|
+
* 印出来的字符串 —— 底栏那一行要把它作为独立的一段,所以不能只给带尾巴的名字。
|
|
1457
|
+
*/
|
|
1458
|
+
function modelBadgesOf(models) {
|
|
1459
|
+
return models.map((m) => {
|
|
1460
|
+
const ratio = creditRatioLabel(m.ratio, isBenefitModel(m.id));
|
|
1461
|
+
return {
|
|
1462
|
+
id: m.id,
|
|
1463
|
+
name: m.name,
|
|
1441
1464
|
...ratio === void 0 ? {} : { ratio }
|
|
1442
1465
|
};
|
|
1443
1466
|
});
|
|
1444
1467
|
}
|
|
1468
|
+
/** 开关的默认值:没有 settings provider(或老配置没这两个键)时保持原有行为 —— 都显示。 */
|
|
1469
|
+
const DEFAULT_DOCK_FLAGS = {
|
|
1470
|
+
credits: true,
|
|
1471
|
+
queue: true
|
|
1472
|
+
};
|
|
1445
1473
|
/**
|
|
1446
1474
|
* 把逐账号的领取结果汇总成一条:HTTP 层只看 ok,卡片看 results 逐号展示。
|
|
1447
1475
|
* 有一个号失败就算整批 ok=false,但别的号领到的结果照样在 results 里。
|
|
@@ -1563,11 +1591,15 @@ function usageOf(deps) {
|
|
|
1563
1591
|
*
|
|
1564
1592
|
* 积分是「锦上添花」:拉不到也绝不能把状态接口本身拖垮,所以失败一律降级成
|
|
1565
1593
|
* `creditsError` 交给卡片显示原因(超时由注入方在自己的闭包里保证)。
|
|
1594
|
+
*
|
|
1595
|
+
* `force` 是给对话底部弹层那个「刷新积分」按钮用的:不强制的话它会命中 60 秒缓存,
|
|
1596
|
+
* 按钮点了数字不动 —— 那还不如不给这个按钮。
|
|
1566
1597
|
*/
|
|
1567
|
-
async function creditsOf(deps) {
|
|
1568
|
-
|
|
1598
|
+
async function creditsOf(deps, force) {
|
|
1599
|
+
const load = force ? deps.refreshCredits ?? deps.credits : deps.credits;
|
|
1600
|
+
if (load === void 0) return {};
|
|
1569
1601
|
try {
|
|
1570
|
-
const entries = await
|
|
1602
|
+
const entries = await load();
|
|
1571
1603
|
const primary = entries.find((entry) => entry.credits !== void 0) ?? entries[0];
|
|
1572
1604
|
return {
|
|
1573
1605
|
...primary?.credits === void 0 ? {} : { credits: primary.credits },
|
|
@@ -1578,14 +1610,12 @@ async function creditsOf(deps) {
|
|
|
1578
1610
|
return { creditsError: safeMessage(error) };
|
|
1579
1611
|
}
|
|
1580
1612
|
}
|
|
1581
|
-
async function buildStatus(deps) {
|
|
1582
|
-
const models = deps.models()
|
|
1583
|
-
id: m.id,
|
|
1584
|
-
name: m.name
|
|
1585
|
-
}));
|
|
1613
|
+
async function buildStatus(deps, force = false) {
|
|
1614
|
+
const models = modelBadgesOf(deps.models());
|
|
1586
1615
|
const accounts = await deps.store.list();
|
|
1587
1616
|
const cred = await deps.store.current();
|
|
1588
1617
|
const usage = usageOf(deps);
|
|
1618
|
+
const dock = deps.dock === void 0 ? {} : { dock: deps.dock() };
|
|
1589
1619
|
const piAi = await probePiAiCompat();
|
|
1590
1620
|
const compat = piAi === void 0 ? {} : { piAiError: piAi };
|
|
1591
1621
|
if (accounts.length === 0 || cred === void 0) return {
|
|
@@ -1593,6 +1623,7 @@ async function buildStatus(deps) {
|
|
|
1593
1623
|
models,
|
|
1594
1624
|
accounts,
|
|
1595
1625
|
usage,
|
|
1626
|
+
...dock,
|
|
1596
1627
|
...compat
|
|
1597
1628
|
};
|
|
1598
1629
|
const usable = accounts.some(accountUsable);
|
|
@@ -1601,7 +1632,8 @@ async function buildStatus(deps) {
|
|
|
1601
1632
|
...cred.storedAt === void 0 ? {} : { storedAt: cred.storedAt },
|
|
1602
1633
|
models,
|
|
1603
1634
|
accounts,
|
|
1604
|
-
usage
|
|
1635
|
+
usage,
|
|
1636
|
+
...dock
|
|
1605
1637
|
};
|
|
1606
1638
|
if (!usable) return {
|
|
1607
1639
|
status: "expired",
|
|
@@ -1612,7 +1644,7 @@ async function buildStatus(deps) {
|
|
|
1612
1644
|
status: "signed-in",
|
|
1613
1645
|
...identity,
|
|
1614
1646
|
...compat,
|
|
1615
|
-
...await creditsOf(deps)
|
|
1647
|
+
...await creditsOf(deps, force)
|
|
1616
1648
|
};
|
|
1617
1649
|
}
|
|
1618
1650
|
/** GET /api/codearts/status */
|
|
@@ -1627,12 +1659,65 @@ function statusHandler(deps) {
|
|
|
1627
1659
|
return;
|
|
1628
1660
|
}
|
|
1629
1661
|
try {
|
|
1630
|
-
json(res, 200, await buildStatus(deps));
|
|
1662
|
+
json(res, 200, await buildStatus(deps, new URL(req.url ?? "", "http://localhost").searchParams.get("force") === "1"));
|
|
1631
1663
|
} catch (error) {
|
|
1632
1664
|
json(res, 500, { error: safeMessage(error) });
|
|
1633
1665
|
}
|
|
1634
1666
|
};
|
|
1635
1667
|
}
|
|
1668
|
+
/**
|
|
1669
|
+
* GET/POST /api/codearts/dock — 对话底部那一行的显隐开关读写。
|
|
1670
|
+
*
|
|
1671
|
+
* 和 enabled-models 同一套规矩:GET 给当前值 + writable,POST 只收布尔、
|
|
1672
|
+
* 没接 settings provider 时回 403 让卡片把勾选框置灰。
|
|
1673
|
+
*/
|
|
1674
|
+
function dockHandler(deps) {
|
|
1675
|
+
return async (req, res) => {
|
|
1676
|
+
if (!loopbackRequest(req)) {
|
|
1677
|
+
json(res, 403, { error: "request-not-trusted" });
|
|
1678
|
+
return;
|
|
1679
|
+
}
|
|
1680
|
+
const current = deps.dock?.() ?? DEFAULT_DOCK_FLAGS;
|
|
1681
|
+
if (req.method === "GET") {
|
|
1682
|
+
json(res, 200, {
|
|
1683
|
+
dock: current,
|
|
1684
|
+
writable: deps.setDock !== void 0
|
|
1685
|
+
});
|
|
1686
|
+
return;
|
|
1687
|
+
}
|
|
1688
|
+
if (req.method === "POST") {
|
|
1689
|
+
if (deps.setDock === void 0) {
|
|
1690
|
+
json(res, 403, { error: "dock-not-writable" });
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
const type = req.headers["content-type"];
|
|
1694
|
+
if (typeof type !== "string" || !type.trim().toLowerCase().startsWith("application/json")) {
|
|
1695
|
+
json(res, 415, { error: "content-type must be application/json" });
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
try {
|
|
1699
|
+
const body = JSON.parse(await readBody(req));
|
|
1700
|
+
const touched = ["credits", "queue"].filter((key) => body[key] !== void 0);
|
|
1701
|
+
if (touched.length === 0 || touched.some((key) => typeof body[key] !== "boolean")) {
|
|
1702
|
+
json(res, 400, { error: "expected {\"credits\"?: boolean, \"queue\"?: boolean}" });
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
if (!await deps.setDock(Object.fromEntries(touched.map((key) => [key, body[key]])))) {
|
|
1706
|
+
json(res, 403, { error: "dock-not-writable" });
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
json(res, 200, {
|
|
1710
|
+
dock: deps.dock?.() ?? DEFAULT_DOCK_FLAGS,
|
|
1711
|
+
writable: true
|
|
1712
|
+
});
|
|
1713
|
+
} catch (error) {
|
|
1714
|
+
json(res, 500, { error: safeMessage(error) });
|
|
1715
|
+
}
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
json(res, 405, { error: "method not allowed" });
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1636
1721
|
/** GET /api/codearts/models — currently offered model ids (honours allowlist). */
|
|
1637
1722
|
function modelsHandler(deps) {
|
|
1638
1723
|
return async (req, res) => {
|
|
@@ -1644,10 +1729,7 @@ function modelsHandler(deps) {
|
|
|
1644
1729
|
json(res, 403, { error: "request-not-trusted" });
|
|
1645
1730
|
return;
|
|
1646
1731
|
}
|
|
1647
|
-
json(res, 200, { models: filterEnabledModels(deps.models(), deps.enabledModels?.())
|
|
1648
|
-
id: m.id,
|
|
1649
|
-
name: m.name
|
|
1650
|
-
})) });
|
|
1732
|
+
json(res, 200, { models: modelBadgesOf(filterEnabledModels(deps.models(), deps.enabledModels?.())) });
|
|
1651
1733
|
};
|
|
1652
1734
|
}
|
|
1653
1735
|
/**
|
|
@@ -1935,6 +2017,11 @@ function registerCodeArtsStatusRoute(ctx, deps) {
|
|
|
1935
2017
|
path: CODEARTS_QUEUE_PATH,
|
|
1936
2018
|
handler: queueHandler(deps)
|
|
1937
2019
|
});
|
|
2020
|
+
const disposeDock = ctx.webServer.register({
|
|
2021
|
+
kind: "exact",
|
|
2022
|
+
path: CODEARTS_DOCK_PATH,
|
|
2023
|
+
handler: dockHandler(deps)
|
|
2024
|
+
});
|
|
1938
2025
|
const disposeDebug = ctx.webServer.register({
|
|
1939
2026
|
kind: "exact",
|
|
1940
2027
|
path: CODEARTS_DEBUG_PATH,
|
|
@@ -1951,6 +2038,7 @@ function registerCodeArtsStatusRoute(ctx, deps) {
|
|
|
1951
2038
|
disposeClaim();
|
|
1952
2039
|
disposeRefresh();
|
|
1953
2040
|
disposeQueue();
|
|
2041
|
+
disposeDock();
|
|
1954
2042
|
disposeDebug();
|
|
1955
2043
|
for (const s of activeLogins.values()) s.close();
|
|
1956
2044
|
activeLogins.clear();
|
|
@@ -2115,7 +2203,11 @@ function unwrapConfig(value) {
|
|
|
2115
2203
|
for (const [key, field] of Object.entries(value)) out[key] = unwrapVolatileValue(field);
|
|
2116
2204
|
return out;
|
|
2117
2205
|
}
|
|
2118
|
-
const Config = z.object({
|
|
2206
|
+
const Config = z.object({
|
|
2207
|
+
enabledModels: z.array(z.string()).description("Model ids offered in the model pickers (empty means every model)").volatile(),
|
|
2208
|
+
showCreditDock: z.boolean().default(true).description("Show the remaining-credits line under the chat input box").volatile(),
|
|
2209
|
+
showQueueDock: z.boolean().default(true).description("Show the upstream queue position under the chat input box").volatile()
|
|
2210
|
+
});
|
|
2119
2211
|
function settingsCompatNamespace(ctx) {
|
|
2120
2212
|
return resolveSettingsNamespaceCompat(ctx, ctx.get("settings"), CODEARTS_SETTINGS_NS);
|
|
2121
2213
|
}
|
|
@@ -2187,6 +2279,19 @@ function apply(ctx, rawConfig) {
|
|
|
2187
2279
|
await settings.update(settingsCompatNamespace(ctx), { enabledModels: [...ids] });
|
|
2188
2280
|
return true;
|
|
2189
2281
|
};
|
|
2282
|
+
const dock = () => ({
|
|
2283
|
+
credits: current().showCreditDock !== false,
|
|
2284
|
+
queue: current().showQueueDock !== false
|
|
2285
|
+
});
|
|
2286
|
+
const setDock = async (patch) => {
|
|
2287
|
+
const settings = ctx.get("settings");
|
|
2288
|
+
if (settings === void 0) return false;
|
|
2289
|
+
await settings.update(settingsCompatNamespace(ctx), {
|
|
2290
|
+
...patch.credits === void 0 ? {} : { showCreditDock: patch.credits },
|
|
2291
|
+
...patch.queue === void 0 ? {} : { showQueueDock: patch.queue }
|
|
2292
|
+
});
|
|
2293
|
+
return true;
|
|
2294
|
+
};
|
|
2190
2295
|
/** 手动「刷新模型列表」的预算:三路来源各打一次,比每小时的后台刷新更该给足时间。 */
|
|
2191
2296
|
const MANUAL_REFRESH_MS = 6e4;
|
|
2192
2297
|
ctx.inject(["webServer"], (webCtx) => registerCodeArtsStatusRoute(webCtx, {
|
|
@@ -2200,6 +2305,12 @@ function apply(ctx, rawConfig) {
|
|
|
2200
2305
|
queue: () => queue.snapshot(),
|
|
2201
2306
|
recentRequests: () => recentRequestShapes(),
|
|
2202
2307
|
credits: (signal) => loadCredits(signal),
|
|
2308
|
+
refreshCredits: (signal) => {
|
|
2309
|
+
credits.invalidate();
|
|
2310
|
+
return loadCredits(signal);
|
|
2311
|
+
},
|
|
2312
|
+
dock,
|
|
2313
|
+
setDock,
|
|
2203
2314
|
claim: async (accountId) => {
|
|
2204
2315
|
const ids = accountId === void 0 ? await store.ids() : [accountId];
|
|
2205
2316
|
if (ids.length === 0) return {
|
|
@@ -2281,6 +2392,7 @@ function apply(ctx, rawConfig) {
|
|
|
2281
2392
|
shim.close().catch(() => {});
|
|
2282
2393
|
});
|
|
2283
2394
|
const CATALOG_REFRESH_MS = 36e5;
|
|
2395
|
+
const CATALOG_EMPTY_RETRY_MS = 6e4;
|
|
2284
2396
|
const abort = new AbortController();
|
|
2285
2397
|
const discover = async () => {
|
|
2286
2398
|
if (stopped) return;
|
|
@@ -2295,13 +2407,18 @@ function apply(ctx, rawConfig) {
|
|
|
2295
2407
|
ctx.logger.debug("dsh-codearts: model discovery failed; keeping the current catalog", error);
|
|
2296
2408
|
}
|
|
2297
2409
|
};
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2410
|
+
let discoveryTimer;
|
|
2411
|
+
/** 自我重排的发现循环:目录为空时加快到每分钟,有货后回到每小时。 */
|
|
2412
|
+
const discoverLoop = async () => {
|
|
2413
|
+
await discover();
|
|
2414
|
+
if (stopped) return;
|
|
2415
|
+
const delay = catalog.current().length === 0 ? CATALOG_EMPTY_RETRY_MS : CATALOG_REFRESH_MS;
|
|
2416
|
+
discoveryTimer = setTimeout(() => void discoverLoop(), delay);
|
|
2417
|
+
discoveryTimer.unref?.();
|
|
2418
|
+
};
|
|
2419
|
+
ctx.effect(() => () => {
|
|
2420
|
+
abort.abort();
|
|
2421
|
+
if (discoveryTimer !== void 0) clearTimeout(discoveryTimer);
|
|
2305
2422
|
});
|
|
2306
2423
|
const shim = createCodeArtsShim({
|
|
2307
2424
|
store,
|
|
@@ -2314,7 +2431,7 @@ function apply(ctx, rawConfig) {
|
|
|
2314
2431
|
usage.load().catch(() => {});
|
|
2315
2432
|
shim.ready.then(async () => {
|
|
2316
2433
|
if (stopped) return;
|
|
2317
|
-
|
|
2434
|
+
discoverLoop();
|
|
2318
2435
|
const incompatible = await probePiAiCompat();
|
|
2319
2436
|
if (incompatible !== void 0) ctx.logger.error(`dsh-codearts: ${incompatible}`);
|
|
2320
2437
|
const codearts = createCodeArtsAdapter({
|
|
@@ -905,6 +905,13 @@ const FALLBACK_CODEARTS_MODELS = [
|
|
|
905
905
|
name: "DeepSeek-V4.1-Flash",
|
|
906
906
|
contextWindow: 131072,
|
|
907
907
|
maxTokens: 65536,
|
|
908
|
+
supportsImages: false
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
id: "deepseek-v4.1-flash-1017",
|
|
912
|
+
name: "DeepSeek-V4.1-Flash-1017",
|
|
913
|
+
contextWindow: 1048576,
|
|
914
|
+
maxTokens: 65536,
|
|
908
915
|
supportsImages: true
|
|
909
916
|
},
|
|
910
917
|
{
|
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
|
|
5
|
+
"version": "1.2.1",
|
|
6
6
|
"packageManager": "pnpm@11.24.0",
|
|
7
7
|
"author": "elegant01",
|
|
8
8
|
"keywords": [
|