@dan-ai-studio/dshopencodego 0.1.20 → 0.1.22
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/README.en.md +2 -1
- package/README.md +2 -1
- package/icon.svg +11 -0
- package/lib/client.js +6 -6
- package/lib/index.js +25 -9
- package/lib/types/adapter.js +32 -3
- package/lib/types/catalog/constants.d.ts +3 -1
- package/lib/types/catalog/constants.js +3 -1
- package/lib/types/catalog/index.d.ts +1 -1
- package/lib/types/catalog/index.js +1 -1
- package/lib/types/catalog/reading.d.ts +3 -1
- package/lib/types/catalog/reading.js +4 -2
- package/lib/types/go-limits.js +1 -1
- package/lib/types/index.d.ts +3 -3
- package/lib/types/index.js +4 -4
- package/lib/types/session-header.d.ts +5 -3
- package/lib/types/session-header.js +8 -4
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +31 -28
package/README.en.md
CHANGED
|
@@ -83,7 +83,8 @@ Configuration lives in the profile's `cordis.patch.yml`:
|
|
|
83
83
|
config:
|
|
84
84
|
enabled: true # false withdraws the route only
|
|
85
85
|
apiKeyEnv: OPENCODE_GO_API_KEY # default
|
|
86
|
-
baseURL: https://opencode.ai/
|
|
86
|
+
baseURL: https://opencode.ai/inference/go/v1 # default (OpenCode Go endpoint, 37 subscription models)
|
|
87
|
+
# or https://opencode.ai/inference/v1 (Console main endpoint, 86 pay-as-you-go/free models)
|
|
87
88
|
refreshMinutes: 60 # live catalog TTL
|
|
88
89
|
modelVisibility: # per-model switches (deprecated default off)
|
|
89
90
|
glm-5: true
|
package/README.md
CHANGED
|
@@ -83,7 +83,8 @@ DSH 桌面端是 Electron 壳 + 完整的 dsh Web 应用,本插件对它同样
|
|
|
83
83
|
config:
|
|
84
84
|
enabled: true # false 仅撤下路由,插件保持挂载
|
|
85
85
|
apiKeyEnv: OPENCODE_GO_API_KEY # 默认值
|
|
86
|
-
baseURL: https://opencode.ai/
|
|
86
|
+
baseURL: https://opencode.ai/inference/go/v1 # 默认值(OpenCode Go 端点,37 个订阅模型)
|
|
87
|
+
# 也可指定为 https://opencode.ai/inference/v1(Console 主端点,包含 86 个按量/免费模型)
|
|
87
88
|
refreshMinutes: 60 # 目录缓存时长
|
|
88
89
|
modelVisibility: # 逐模型开关(弃用模型默认关闭)
|
|
89
90
|
glm-5: true
|
package/icon.svg
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="OpenCode Go">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#1f6feb"/>
|
|
5
|
+
<stop offset="1" stop-color="#0d4196"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<rect x="1.5" y="1.5" width="61" height="61" rx="14" fill="url(#bg)" stroke="#0a2f6b" stroke-width="3"/>
|
|
9
|
+
<path d="M20 21.5 33.5 32 20 42.5" fill="none" stroke="#ffffff" stroke-width="5.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
10
|
+
<path d="M33 21.5 46.5 32 33 42.5" fill="none" stroke="#9ecbff" stroke-width="5.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
11
|
+
</svg>
|
package/lib/client.js
CHANGED
|
@@ -453,16 +453,16 @@ function inputModalityLabels(model, t) {
|
|
|
453
453
|
return (model.inputModalities ?? []).map((modality) => t(MODALITY_KEYS[modality]));
|
|
454
454
|
}
|
|
455
455
|
|
|
456
|
-
// plugin-css
|
|
456
|
+
// plugin-css:D:\prj\dshopencodego\src\client\section.module.css
|
|
457
457
|
var id = "@dan-ai-studio/dshopencodego/section.module.css";
|
|
458
458
|
if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")) {
|
|
459
459
|
const style = document.createElement("style");
|
|
460
460
|
style.dataset.plugin = "@dan-ai-studio/dshopencodego";
|
|
461
461
|
style.dataset.pluginCss = id;
|
|
462
|
-
style.textContent = ".
|
|
462
|
+
style.textContent = "._6tq0da_root{color:var(--dsw-alias-label-primary);flex-direction:column;gap:1.25rem;display:flex}._6tq0da_title{margin:0;font-size:1.05rem}._6tq0da_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.8rem}._6tq0da_warn{color:var(--dsw-alias-state-warn-primary);margin:0;font-size:.8rem}._6tq0da_ok{color:var(--dsw-alias-state-success-primary);font-size:.8rem}._6tq0da_block{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:.6rem;flex-direction:column;gap:.5rem;padding:.85rem;display:flex}._6tq0da_row{flex-wrap:wrap;align-items:center;gap:.5rem;display:flex}._6tq0da_row>strong{margin-right:auto}._6tq0da_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);min-width:10rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;flex:14rem;padding:.35rem .5rem;font-size:.85rem}._6tq0da_button{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;padding:.35rem .7rem;font-size:.8rem}._6tq0da_button:disabled{color:var(--dsw-alias-state-idle-primary);cursor:default}._6tq0da_number{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:5rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}._6tq0da_select{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:100%;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}._6tq0da_list{flex-direction:column;display:flex}._6tq0da_item{border-top:1px solid var(--dsw-alias-border-l1);align-items:flex-start;gap:.5rem;padding:.45rem .15rem;display:flex}._6tq0da_item input[type=checkbox]{accent-color:var(--dsw-alias-brand-primary);margin-top:.15rem}._6tq0da_itemBody{flex-direction:column;gap:.15rem;min-width:0;display:flex}._6tq0da_itemMain{flex-wrap:wrap;align-items:baseline;gap:.6rem;display:flex}._6tq0da_itemMeta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:.75rem;font-size:.75rem;display:flex}._6tq0da_itemModalities{color:var(--dsw-alias-label-secondary);font-size:.75rem}._6tq0da_name{color:var(--dsw-alias-label-primary)}._6tq0da_mono{color:var(--dsw-alias-label-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._6tq0da_badge{color:var(--dsw-alias-brand-primary)}";
|
|
463
463
|
document.head.appendChild(style);
|
|
464
464
|
}
|
|
465
|
-
var section_default = { "
|
|
465
|
+
var section_default = { "item": "_6tq0da_item", "root": "_6tq0da_root", "input": "_6tq0da_input", "row": "_6tq0da_row", "itemMain": "_6tq0da_itemMain", "warn": "_6tq0da_warn", "badge": "_6tq0da_badge", "title": "_6tq0da_title", "block": "_6tq0da_block", "itemModalities": "_6tq0da_itemModalities", "mono": "_6tq0da_mono", "button": "_6tq0da_button", "hint": "_6tq0da_hint", "select": "_6tq0da_select", "name": "_6tq0da_name", "itemMeta": "_6tq0da_itemMeta", "list": "_6tq0da_list", "ok": "_6tq0da_ok", "itemBody": "_6tq0da_itemBody", "number": "_6tq0da_number" };
|
|
466
466
|
|
|
467
467
|
// src/client/Section.tsx
|
|
468
468
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -954,16 +954,16 @@ function Section({ controller, t, getLocale }) {
|
|
|
954
954
|
// src/client/UsagePill.tsx
|
|
955
955
|
var import_react2 = require("react");
|
|
956
956
|
|
|
957
|
-
// plugin-css
|
|
957
|
+
// plugin-css:D:\prj\dshopencodego\src\client\pill.module.css
|
|
958
958
|
var id2 = "@dan-ai-studio/dshopencodego/pill.module.css";
|
|
959
959
|
if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]")) {
|
|
960
960
|
const style = document.createElement("style");
|
|
961
961
|
style.dataset.plugin = "@dan-ai-studio/dshopencodego";
|
|
962
962
|
style.dataset.pluginCss = id2;
|
|
963
|
-
style.textContent = ".
|
|
963
|
+
style.textContent = ".y-bZgq_root{align-items:center;display:inline-flex;position:relative}.y-bZgq_trigger{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;white-space:nowrap;border-radius:999px;padding:.35rem .6rem;font-size:.8rem;line-height:1}.y-bZgq_trigger:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.y-bZgq_panel{z-index:20;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-overlay);width:18rem;color:var(--dsw-alias-label-primary);border-radius:.6rem;flex-direction:column;gap:.6rem;padding:.75rem .85rem;display:flex;position:absolute;bottom:calc(100% + .5rem);right:0;box-shadow:0 8px 24px #0000002e}.y-bZgq_window{flex-direction:column;gap:.25rem;display:flex}.y-bZgq_row{justify-content:space-between;gap:.5rem;font-size:.85rem;display:flex}.y-bZgq_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.75rem}.y-bZgq_progress{width:100%;height:.35rem;accent-color:var(--dsw-alias-brand-primary)}.y-bZgq_limited{color:var(--dsw-alias-state-warn-primary);font-size:.75rem}.y-bZgq_warning{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-label-primary);border-radius:.4rem;padding:.4rem .5rem;font-size:.75rem}.y-bZgq_retry{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;align-self:flex-start;padding:.25rem .5rem;font-size:.75rem}.y-bZgq_local{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:.2rem;padding-top:.5rem;display:flex}";
|
|
964
964
|
document.head.appendChild(style);
|
|
965
965
|
}
|
|
966
|
-
var pill_default = { "
|
|
966
|
+
var pill_default = { "hint": "y-bZgq_hint", "panel": "y-bZgq_panel", "warning": "y-bZgq_warning", "local": "y-bZgq_local", "progress": "y-bZgq_progress", "limited": "y-bZgq_limited", "retry": "y-bZgq_retry", "root": "y-bZgq_root", "trigger": "y-bZgq_trigger", "window": "y-bZgq_window", "row": "y-bZgq_row" };
|
|
967
967
|
|
|
968
968
|
// src/client/UsagePill.tsx
|
|
969
969
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
package/lib/index.js
CHANGED
|
@@ -73,7 +73,8 @@ import { attributionHeaders as attributionHeaders3, LlmError as LlmError4 } from
|
|
|
73
73
|
// src/catalog/constants.ts
|
|
74
74
|
var PROVIDER_ID = "opencode-go";
|
|
75
75
|
var DISPLAY_NAME = "OpenCode Go";
|
|
76
|
-
var DEFAULT_BASE_URL = "https://opencode.ai/
|
|
76
|
+
var DEFAULT_BASE_URL = "https://opencode.ai/inference/go/v1";
|
|
77
|
+
var CONSOLE_BASE_URL = "https://opencode.ai/inference/v1";
|
|
77
78
|
var MODEL_METADATA_URL = "https://models.dev/api.json";
|
|
78
79
|
var MODEL_METADATA_PROVIDER = "opencode-go";
|
|
79
80
|
var METADATA_FETCH_TIMEOUT_MS = 1e4;
|
|
@@ -1347,7 +1348,7 @@ var SEED_QUOTAS = {
|
|
|
1347
1348
|
"deepseek-v4-flash-vision-exp": { monthlyUsd: 15, monthlyRequests: 32500 },
|
|
1348
1349
|
"hy4-preview": { monthlyUsd: 30, monthlyRequests: 6770 },
|
|
1349
1350
|
"hy3": { monthlyUsd: 60, monthlyRequests: 21500 },
|
|
1350
|
-
|
|
1351
|
+
// 注意:space-bunny-free 并不在 Go 端点支持的 37 个模型列表中(请求会返回 400 错误),已依据 R-B4 予以剔除
|
|
1351
1352
|
"grok-4.7": { monthlyUsd: 15, monthlyRequests: 845 },
|
|
1352
1353
|
"grok-4.6": { monthlyUsd: 15, monthlyRequests: 845 },
|
|
1353
1354
|
"gpt-6-luna": { monthlyUsd: 15, monthlyRequests: 21130 },
|
|
@@ -1396,12 +1397,15 @@ function sortModels(models, now = Date.now()) {
|
|
|
1396
1397
|
import { randomUUID } from "node:crypto";
|
|
1397
1398
|
import { attributionHeaders as attributionHeaders4 } from "@deepseek-ai/dsh-llm";
|
|
1398
1399
|
var SESSION_HEADER = "x-opencode-session";
|
|
1400
|
+
var SESSION_AFFINITY_HEADER = "x-session-affinity";
|
|
1399
1401
|
function opencodeSessionValue(sessionId) {
|
|
1400
1402
|
return sessionId !== void 0 && sessionId.length > 0 ? sessionId : randomUUID();
|
|
1401
1403
|
}
|
|
1402
1404
|
function providerHeaders(sessionId) {
|
|
1405
|
+
const session = opencodeSessionValue(sessionId);
|
|
1403
1406
|
return {
|
|
1404
|
-
[SESSION_HEADER]:
|
|
1407
|
+
[SESSION_HEADER]: session,
|
|
1408
|
+
[SESSION_AFFINITY_HEADER]: session,
|
|
1405
1409
|
...attributionHeaders4()
|
|
1406
1410
|
};
|
|
1407
1411
|
}
|
|
@@ -1417,6 +1421,14 @@ function withModelLimit(model, limits) {
|
|
|
1417
1421
|
maxTokens: limit.maxTokens ?? model.maxTokens
|
|
1418
1422
|
};
|
|
1419
1423
|
}
|
|
1424
|
+
function stopSequencesFor(model, stop) {
|
|
1425
|
+
if (stop === void 0) return void 0;
|
|
1426
|
+
if (model.api === "openai-completions") return stop;
|
|
1427
|
+
throw new LlmError8(
|
|
1428
|
+
`opencode-go model "${model.id}" speaks ${model.api}, which has no stop-sequence parameter this adapter can reach; drop GenerateOptions.stop for this model`,
|
|
1429
|
+
"UNSUPPORTED_OPTION"
|
|
1430
|
+
);
|
|
1431
|
+
}
|
|
1420
1432
|
var OpencodeGoAdapter = class extends LlmAdapter {
|
|
1421
1433
|
cache;
|
|
1422
1434
|
options;
|
|
@@ -1538,12 +1550,10 @@ var OpencodeGoAdapter = class extends LlmAdapter {
|
|
|
1538
1550
|
async *streamWithSnapshot(options, config, snapshot) {
|
|
1539
1551
|
var _stack = [];
|
|
1540
1552
|
try {
|
|
1541
|
-
if (options.stop !== void 0) {
|
|
1542
|
-
throw new LlmError8("dshopencodego does not support GenerateOptions.stop", "UNSUPPORTED_OPTION");
|
|
1543
|
-
}
|
|
1544
1553
|
const facts = snapshot.facts.get(options.model);
|
|
1545
1554
|
if (facts === void 0) throw new LlmError8(`opencode-go has no model "${options.model}"`, "UNKNOWN_MODEL");
|
|
1546
1555
|
const model = withModelLimit(toPiModel(facts, config.baseURL), config.modelLimits);
|
|
1556
|
+
const stop = stopSequencesFor(model, options.stop);
|
|
1547
1557
|
const ceiling = config.modelLimits[model.id]?.maxTokens;
|
|
1548
1558
|
const maxTokens = options.maxTokens === void 0 || ceiling === null || ceiling === void 0 ? options.maxTokens : Math.min(options.maxTokens, ceiling);
|
|
1549
1559
|
const apiKey = await this.options.resolveApiKey();
|
|
@@ -1579,6 +1589,10 @@ var OpencodeGoAdapter = class extends LlmAdapter {
|
|
|
1579
1589
|
...reasoning === void 0 || reasoning === "off" ? {} : { reasoning },
|
|
1580
1590
|
...options.temperature === void 0 ? {} : { temperature: options.temperature },
|
|
1581
1591
|
...maxTokens === void 0 ? {} : { maxTokens },
|
|
1592
|
+
// `samplingParams` is merged into the request body as-is by the
|
|
1593
|
+
// OpenAI-compatible adapters, and `stop` is Chat Completions' own
|
|
1594
|
+
// stop-sequence field — the one place this control reaches the wire.
|
|
1595
|
+
...stop === void 0 ? {} : { samplingParams: { stop: [...stop] } },
|
|
1582
1596
|
...options.sessionId === void 0 ? {} : { sessionId: String(options.sessionId) },
|
|
1583
1597
|
signal: watchdog.signal,
|
|
1584
1598
|
// The gateway refuses a request without `x-opencode-session`; the
|
|
@@ -1858,7 +1872,7 @@ import { RemoteError, TypertRemoteService } from "@deepseek-ai/dsh-typert-protoc
|
|
|
1858
1872
|
import { LlmError as LlmError9 } from "@deepseek-ai/dsh-llm";
|
|
1859
1873
|
|
|
1860
1874
|
// src/catalog/reading.ts
|
|
1861
|
-
function catalogReading(snapshot, visibility, listingFailure) {
|
|
1875
|
+
function catalogReading(snapshot, visibility, listingFailure, now) {
|
|
1862
1876
|
const documentQuotas = snapshot.documentQuotas;
|
|
1863
1877
|
const rows = [
|
|
1864
1878
|
...[...snapshot.facts.values()].map((fact) => {
|
|
@@ -1892,7 +1906,7 @@ function catalogReading(snapshot, visibility, listingFailure) {
|
|
|
1892
1906
|
const models = rows.map((row) => ({ ...row, recommended: recommended.has(row.id) }));
|
|
1893
1907
|
const enabled = models.filter((model) => isModelEnabled(model, visibility)).length;
|
|
1894
1908
|
return {
|
|
1895
|
-
models: sortModels(models),
|
|
1909
|
+
models: sortModels(models, now),
|
|
1896
1910
|
stale: !snapshot.live,
|
|
1897
1911
|
...!snapshot.live && listingFailure !== void 0 ? { error: listingFailure } : {},
|
|
1898
1912
|
fetchedAtMs: snapshot.fetchedAtMs,
|
|
@@ -2185,7 +2199,7 @@ function apply(ctx, raw) {
|
|
|
2185
2199
|
const undiscover = ctx.llm.registerModelDiscovery(name, async (request) => {
|
|
2186
2200
|
if (request.provider !== PROVIDER_ID && !(request.baseURL ?? "").includes("opencode.ai")) {
|
|
2187
2201
|
throw new LlmError12(
|
|
2188
|
-
"dshopencodego discovers only OpenCode
|
|
2202
|
+
"dshopencodego discovers only OpenCode Go/Console endpoints; enter this provider's models by hand",
|
|
2189
2203
|
"DISCOVERY_UNSUPPORTED"
|
|
2190
2204
|
);
|
|
2191
2205
|
}
|
|
@@ -2210,6 +2224,7 @@ function apply(ctx, raw) {
|
|
|
2210
2224
|
ctx.logger.info(`dshopencodego: route "${PROVIDER_ID}" registered as ${DISPLAY_NAME}`);
|
|
2211
2225
|
}
|
|
2212
2226
|
export {
|
|
2227
|
+
CONSOLE_BASE_URL,
|
|
2213
2228
|
Config,
|
|
2214
2229
|
DEFAULT_API_KEY_ENV,
|
|
2215
2230
|
DEFAULT_BASE_URL,
|
|
@@ -2218,6 +2233,7 @@ export {
|
|
|
2218
2233
|
OpencodeGoCatalog,
|
|
2219
2234
|
PROVIDER_ID,
|
|
2220
2235
|
PlainConfig,
|
|
2236
|
+
SESSION_AFFINITY_HEADER,
|
|
2221
2237
|
SESSION_HEADER,
|
|
2222
2238
|
apply,
|
|
2223
2239
|
assertBaseURL,
|
package/lib/types/adapter.js
CHANGED
|
@@ -90,6 +90,31 @@ function withModelLimit(model, limits) {
|
|
|
90
90
|
maxTokens: limit.maxTokens ?? model.maxTokens,
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Resolve one request's stop sequences against the model's protocol.
|
|
95
|
+
*
|
|
96
|
+
* The seam's stop control reaches a route only through the provider's own
|
|
97
|
+
* field, and pi-ai models none: its Anthropic options carry no stop sequences
|
|
98
|
+
* and that adapter ignores `samplingParams`, and its Responses options define
|
|
99
|
+
* no stop-sequence parameter at all. Only the OpenAI-compatible adapters merge
|
|
100
|
+
* arbitrary body fields, and `stop` is exactly the field Chat Completions
|
|
101
|
+
* defines, so a completions model can honor it. Every other protocol refuses:
|
|
102
|
+
* silently dropping the sequences would let a caller believe generation halts
|
|
103
|
+
* at a string the model never sees.
|
|
104
|
+
* @param model - the exact model this request will use.
|
|
105
|
+
* @param stop - the caller's stop sequences, when it named any.
|
|
106
|
+
* @returns the sequences to send, or undefined when the caller named none.
|
|
107
|
+
* @throws {LlmError} `UNSUPPORTED_OPTION` for a protocol with no reachable
|
|
108
|
+
* stop-sequence parameter.
|
|
109
|
+
*/
|
|
110
|
+
function stopSequencesFor(model, stop) {
|
|
111
|
+
if (stop === undefined)
|
|
112
|
+
return undefined;
|
|
113
|
+
if (model.api === 'openai-completions')
|
|
114
|
+
return stop;
|
|
115
|
+
throw new LlmError(`opencode-go model "${model.id}" speaks ${model.api}, which has no stop-sequence parameter this adapter can reach;`
|
|
116
|
+
+ ' drop GenerateOptions.stop for this model', 'UNSUPPORTED_OPTION');
|
|
117
|
+
}
|
|
93
118
|
/**
|
|
94
119
|
* The single `opencode-go` route's adapter.
|
|
95
120
|
*
|
|
@@ -238,13 +263,13 @@ export class OpencodeGoAdapter extends LlmAdapter {
|
|
|
238
263
|
async *streamWithSnapshot(options, config, snapshot) {
|
|
239
264
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
240
265
|
try {
|
|
241
|
-
if (options.stop !== undefined) {
|
|
242
|
-
throw new LlmError('dshopencodego does not support GenerateOptions.stop', 'UNSUPPORTED_OPTION');
|
|
243
|
-
}
|
|
244
266
|
const facts = snapshot.facts.get(options.model);
|
|
245
267
|
if (facts === undefined)
|
|
246
268
|
throw new LlmError(`opencode-go has no model "${options.model}"`, 'UNKNOWN_MODEL');
|
|
247
269
|
const model = withModelLimit(toPiModel(facts, config.baseURL), config.modelLimits);
|
|
270
|
+
// Resolved before the first await so an unsupported protocol fails the
|
|
271
|
+
// request before any credential is read or any byte is sent.
|
|
272
|
+
const stop = stopSequencesFor(model, options.stop);
|
|
248
273
|
// `defaultMaxTokens` already carries the route's ceiling for a caller that
|
|
249
274
|
// names none, so only a caller's own cap travels, clamped by a configured
|
|
250
275
|
// per-model ceiling when one exists.
|
|
@@ -287,6 +312,10 @@ export class OpencodeGoAdapter extends LlmAdapter {
|
|
|
287
312
|
...reasoning === undefined || reasoning === 'off' ? {} : { reasoning },
|
|
288
313
|
...options.temperature === undefined ? {} : { temperature: options.temperature },
|
|
289
314
|
...maxTokens === undefined ? {} : { maxTokens },
|
|
315
|
+
// `samplingParams` is merged into the request body as-is by the
|
|
316
|
+
// OpenAI-compatible adapters, and `stop` is Chat Completions' own
|
|
317
|
+
// stop-sequence field — the one place this control reaches the wire.
|
|
318
|
+
...stop === undefined ? {} : { samplingParams: { stop: [...stop] } },
|
|
290
319
|
...options.sessionId === undefined ? {} : { sessionId: String(options.sessionId) },
|
|
291
320
|
signal: watchdog.signal,
|
|
292
321
|
// The gateway refuses a request without `x-opencode-session`; the
|
|
@@ -4,7 +4,9 @@ export declare const PROVIDER_ID = "opencode-go";
|
|
|
4
4
|
/** Selector label for the route. */
|
|
5
5
|
export declare const DISPLAY_NAME = "OpenCode Go";
|
|
6
6
|
/** Gateway base URL; `/models` and `/usage` hang off it. */
|
|
7
|
-
export declare const DEFAULT_BASE_URL = "https://opencode.ai/
|
|
7
|
+
export declare const DEFAULT_BASE_URL = "https://opencode.ai/inference/go/v1";
|
|
8
|
+
/** Console base URL (on-demand / free models, pay-as-you-go). */
|
|
9
|
+
export declare const CONSOLE_BASE_URL = "https://opencode.ai/inference/v1";
|
|
8
10
|
/** Online model metadata: capability, lifecycle, and pricing per model id. */
|
|
9
11
|
export declare const MODEL_METADATA_URL = "https://models.dev/api.json";
|
|
10
12
|
/** The models.dev provider key this plugin reads. */
|
|
@@ -4,7 +4,9 @@ export const PROVIDER_ID = 'opencode-go';
|
|
|
4
4
|
/** Selector label for the route. */
|
|
5
5
|
export const DISPLAY_NAME = 'OpenCode Go';
|
|
6
6
|
/** Gateway base URL; `/models` and `/usage` hang off it. */
|
|
7
|
-
export const DEFAULT_BASE_URL = 'https://opencode.ai/
|
|
7
|
+
export const DEFAULT_BASE_URL = 'https://opencode.ai/inference/go/v1';
|
|
8
|
+
/** Console base URL (on-demand / free models, pay-as-you-go). */
|
|
9
|
+
export const CONSOLE_BASE_URL = 'https://opencode.ai/inference/v1';
|
|
8
10
|
/** Online model metadata: capability, lifecycle, and pricing per model id. */
|
|
9
11
|
export const MODEL_METADATA_URL = 'https://models.dev/api.json';
|
|
10
12
|
/** The models.dev provider key this plugin reads. */
|
|
@@ -23,7 +23,7 @@ import type { LlmDiscoveredModel } from '@deepseek-ai/dsh-llm';
|
|
|
23
23
|
import type { GoDoc } from './go-doc.ts';
|
|
24
24
|
import type { ModelDefaults, ModelFacts } from './metadata.ts';
|
|
25
25
|
import type { GoQuota } from '../go-limits.ts';
|
|
26
|
-
export { PROVIDER_ID, DISPLAY_NAME, DEFAULT_BASE_URL } from './constants.ts';
|
|
26
|
+
export { PROVIDER_ID, DISPLAY_NAME, DEFAULT_BASE_URL, CONSOLE_BASE_URL } from './constants.ts';
|
|
27
27
|
export { readModelIds, fetchModelIds } from './gateway.ts';
|
|
28
28
|
export { readOnlineMetadata, toPiModel, modelBaseURL } from './metadata.ts';
|
|
29
29
|
export type { ModelFacts, OnlineMetadata, ModelDefaults } from './metadata.ts';
|
|
@@ -29,7 +29,7 @@ import { fetchModelIds } from "./gateway.js";
|
|
|
29
29
|
import { fetchGoDocument, GO_DOC_URLS } from "./go-doc.js";
|
|
30
30
|
import { readBoundedJson } from "./json-response.js";
|
|
31
31
|
import { readOnlineMetadata, toPiModel } from "./metadata.js";
|
|
32
|
-
export { PROVIDER_ID, DISPLAY_NAME, DEFAULT_BASE_URL } from "./constants.js";
|
|
32
|
+
export { PROVIDER_ID, DISPLAY_NAME, DEFAULT_BASE_URL, CONSOLE_BASE_URL } from "./constants.js";
|
|
33
33
|
export { readModelIds, fetchModelIds } from "./gateway.js";
|
|
34
34
|
export { readOnlineMetadata, toPiModel, modelBaseURL } from "./metadata.js";
|
|
35
35
|
export { decideProtocol, inferProtocol, protocolOfNpm } from "./protocol.js";
|
|
@@ -40,7 +40,9 @@ export interface CatalogReading {
|
|
|
40
40
|
* @param snapshot - the catalog snapshot, live or retained.
|
|
41
41
|
* @param visibility - per-model switches; absent entries keep the default.
|
|
42
42
|
* @param listingFailure - the failure message when the listing failed.
|
|
43
|
+
* @param now - the clock the "newly shipped" ordering reads; injected so a
|
|
44
|
+
* reading is a pure function of its inputs rather than of the wall clock.
|
|
43
45
|
* @returns the reading, with unconfigurable ids kept visible so the page can
|
|
44
46
|
* explain them instead of hiding them.
|
|
45
47
|
*/
|
|
46
|
-
export declare function catalogReading(snapshot: CatalogSnapshot, visibility: Readonly<Record<string, boolean>>, listingFailure?: string): CatalogReading;
|
|
48
|
+
export declare function catalogReading(snapshot: CatalogSnapshot, visibility: Readonly<Record<string, boolean>>, listingFailure?: string, now?: number): CatalogReading;
|
|
@@ -16,10 +16,12 @@ import { goQuotaFor } from "../go-limits.js";
|
|
|
16
16
|
* @param snapshot - the catalog snapshot, live or retained.
|
|
17
17
|
* @param visibility - per-model switches; absent entries keep the default.
|
|
18
18
|
* @param listingFailure - the failure message when the listing failed.
|
|
19
|
+
* @param now - the clock the "newly shipped" ordering reads; injected so a
|
|
20
|
+
* reading is a pure function of its inputs rather than of the wall clock.
|
|
19
21
|
* @returns the reading, with unconfigurable ids kept visible so the page can
|
|
20
22
|
* explain them instead of hiding them.
|
|
21
23
|
*/
|
|
22
|
-
export function catalogReading(snapshot, visibility, listingFailure) {
|
|
24
|
+
export function catalogReading(snapshot, visibility, listingFailure, now) {
|
|
23
25
|
const documentQuotas = snapshot.documentQuotas;
|
|
24
26
|
const rows = [
|
|
25
27
|
...[...snapshot.facts.values()].map(fact => {
|
|
@@ -55,7 +57,7 @@ export function catalogReading(snapshot, visibility, listingFailure) {
|
|
|
55
57
|
const models = rows.map(row => ({ ...row, recommended: recommended.has(row.id) }));
|
|
56
58
|
const enabled = models.filter(model => isModelEnabled(model, visibility)).length;
|
|
57
59
|
return {
|
|
58
|
-
models: sortModels(models),
|
|
60
|
+
models: sortModels(models, now),
|
|
59
61
|
stale: !snapshot.live,
|
|
60
62
|
...!snapshot.live && listingFailure !== undefined ? { error: listingFailure } : {},
|
|
61
63
|
fetchedAtMs: snapshot.fetchedAtMs,
|
package/lib/types/go-limits.js
CHANGED
|
@@ -58,7 +58,7 @@ export const SEED_QUOTAS = {
|
|
|
58
58
|
'deepseek-v4-flash-vision-exp': { monthlyUsd: 15, monthlyRequests: 32_500 },
|
|
59
59
|
'hy4-preview': { monthlyUsd: 30, monthlyRequests: 6_770 },
|
|
60
60
|
'hy3': { monthlyUsd: 60, monthlyRequests: 21_500 },
|
|
61
|
-
|
|
61
|
+
// 注意:space-bunny-free 并不在 Go 端点支持的 37 个模型列表中(请求会返回 400 错误),已依据 R-B4 予以剔除
|
|
62
62
|
'grok-4.7': { monthlyUsd: 15, monthlyRequests: 845 },
|
|
63
63
|
'grok-4.6': { monthlyUsd: 15, monthlyRequests: 845 },
|
|
64
64
|
'gpt-6-luna': { monthlyUsd: 15, monthlyRequests: 21_130 },
|
package/lib/types/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* config:
|
|
20
20
|
* enabled: true # false withdraws the route only
|
|
21
21
|
* apiKeyEnv: OPENCODE_GO_API_KEY # default
|
|
22
|
-
* baseURL: https://opencode.ai/
|
|
22
|
+
* baseURL: https://opencode.ai/inference/go/v1 # default
|
|
23
23
|
* refreshMinutes: 60 # live catalog TTL
|
|
24
24
|
* modelProtocols: # last-resort protocol override
|
|
25
25
|
* some-model: openai-responses
|
|
@@ -35,10 +35,10 @@ declare module '@deepseek-ai/cordis' {
|
|
|
35
35
|
}
|
|
36
36
|
export { OpencodeGoAdapter } from './adapter.ts';
|
|
37
37
|
export type { OpencodeGoAdapterOptions, OpencodeGoImageAccess } from './adapter.ts';
|
|
38
|
-
export { DEFAULT_BASE_URL, DISPLAY_NAME, PROVIDER_ID, OpencodeGoCatalog, discoverCatalogModels } from './catalog/index.ts';
|
|
38
|
+
export { DEFAULT_BASE_URL, CONSOLE_BASE_URL, DISPLAY_NAME, PROVIDER_ID, OpencodeGoCatalog, discoverCatalogModels } from './catalog/index.ts';
|
|
39
39
|
export { Config, PlainConfig, assertBaseURL, DEFAULT_API_KEY_ENV } from './config.ts';
|
|
40
40
|
export type { OpencodeGoConfig } from './config.ts';
|
|
41
|
-
export { SESSION_HEADER, opencodeSessionValue, providerHeaders } from './session-header.ts';
|
|
41
|
+
export { SESSION_HEADER, SESSION_AFFINITY_HEADER, opencodeSessionValue, providerHeaders } from './session-header.ts';
|
|
42
42
|
export { isModelEnabled, sortModels } from './models.ts';
|
|
43
43
|
export type { ModelSummary } from './models.ts';
|
|
44
44
|
export declare const name = "dshopencodego";
|
package/lib/types/index.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* config:
|
|
20
20
|
* enabled: true # false withdraws the route only
|
|
21
21
|
* apiKeyEnv: OPENCODE_GO_API_KEY # default
|
|
22
|
-
* baseURL: https://opencode.ai/
|
|
22
|
+
* baseURL: https://opencode.ai/inference/go/v1 # default
|
|
23
23
|
* refreshMinutes: 60 # live catalog TTL
|
|
24
24
|
* modelProtocols: # last-resort protocol override
|
|
25
25
|
* some-model: openai-responses
|
|
@@ -38,9 +38,9 @@ import { registerRemotes } from "./remotes.js";
|
|
|
38
38
|
import { OpencodeGoCatalogService } from "./catalog/service.js";
|
|
39
39
|
import { OpencodeGoUsageService, UsageMeter } from "./usage/index.js";
|
|
40
40
|
export { OpencodeGoAdapter } from "./adapter.js";
|
|
41
|
-
export { DEFAULT_BASE_URL, DISPLAY_NAME, PROVIDER_ID, OpencodeGoCatalog, discoverCatalogModels } from "./catalog/index.js";
|
|
41
|
+
export { DEFAULT_BASE_URL, CONSOLE_BASE_URL, DISPLAY_NAME, PROVIDER_ID, OpencodeGoCatalog, discoverCatalogModels } from "./catalog/index.js";
|
|
42
42
|
export { Config, PlainConfig, assertBaseURL, DEFAULT_API_KEY_ENV } from "./config.js";
|
|
43
|
-
export { SESSION_HEADER, opencodeSessionValue, providerHeaders } from "./session-header.js";
|
|
43
|
+
export { SESSION_HEADER, SESSION_AFFINITY_HEADER, opencodeSessionValue, providerHeaders } from "./session-header.js";
|
|
44
44
|
export { isModelEnabled, sortModels } from "./models.js";
|
|
45
45
|
export const name = 'dshopencodego';
|
|
46
46
|
export const inject = ['llm'];
|
|
@@ -166,7 +166,7 @@ export function apply(ctx, raw) {
|
|
|
166
166
|
syncRoute();
|
|
167
167
|
const undiscover = ctx.llm.registerModelDiscovery(name, async (request) => {
|
|
168
168
|
if (request.provider !== PROVIDER_ID && !(request.baseURL ?? '').includes('opencode.ai')) {
|
|
169
|
-
throw new LlmError('dshopencodego discovers only OpenCode
|
|
169
|
+
throw new LlmError('dshopencodego discovers only OpenCode Go/Console endpoints; enter this provider\'s models by hand', 'DISCOVERY_UNSUPPORTED');
|
|
170
170
|
}
|
|
171
171
|
return discoverCatalogModels(adapter.catalogOf(current()));
|
|
172
172
|
});
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
/** Header name the gateway requires. */
|
|
19
19
|
export declare const SESSION_HEADER = "x-opencode-session";
|
|
20
|
+
/** Session affinity header for gateway routing and prompt caching. */
|
|
21
|
+
export declare const SESSION_AFFINITY_HEADER = "x-session-affinity";
|
|
20
22
|
/**
|
|
21
23
|
* The header value for one request.
|
|
22
24
|
* @param sessionId - the request's session id, if it names one.
|
|
@@ -27,9 +29,9 @@ export declare function opencodeSessionValue(sessionId: string | undefined): str
|
|
|
27
29
|
* Every header one provider request carries.
|
|
28
30
|
*
|
|
29
31
|
* The attribution `user-agent` is Harness-owned and always present; the session
|
|
30
|
-
*
|
|
31
|
-
* never win, because the gateway's routing decision must follow
|
|
32
|
-
* not a deployment string.
|
|
32
|
+
* and affinity headers are added on top of it. A caller-supplied header of the
|
|
33
|
+
* same name can never win, because the gateway's routing decision must follow
|
|
34
|
+
* the session, not a deployment string.
|
|
33
35
|
* @param sessionId - the request's session id, if it names one.
|
|
34
36
|
* @returns headers for the pi-ai request options.
|
|
35
37
|
*/
|
|
@@ -19,6 +19,8 @@ import { randomUUID } from 'node:crypto';
|
|
|
19
19
|
import { attributionHeaders } from '@deepseek-ai/dsh-llm';
|
|
20
20
|
/** Header name the gateway requires. */
|
|
21
21
|
export const SESSION_HEADER = 'x-opencode-session';
|
|
22
|
+
/** Session affinity header for gateway routing and prompt caching. */
|
|
23
|
+
export const SESSION_AFFINITY_HEADER = 'x-session-affinity';
|
|
22
24
|
/**
|
|
23
25
|
* The header value for one request.
|
|
24
26
|
* @param sessionId - the request's session id, if it names one.
|
|
@@ -31,15 +33,17 @@ export function opencodeSessionValue(sessionId) {
|
|
|
31
33
|
* Every header one provider request carries.
|
|
32
34
|
*
|
|
33
35
|
* The attribution `user-agent` is Harness-owned and always present; the session
|
|
34
|
-
*
|
|
35
|
-
* never win, because the gateway's routing decision must follow
|
|
36
|
-
* not a deployment string.
|
|
36
|
+
* and affinity headers are added on top of it. A caller-supplied header of the
|
|
37
|
+
* same name can never win, because the gateway's routing decision must follow
|
|
38
|
+
* the session, not a deployment string.
|
|
37
39
|
* @param sessionId - the request's session id, if it names one.
|
|
38
40
|
* @returns headers for the pi-ai request options.
|
|
39
41
|
*/
|
|
40
42
|
export function providerHeaders(sessionId) {
|
|
43
|
+
const session = opencodeSessionValue(sessionId);
|
|
41
44
|
return {
|
|
42
|
-
[SESSION_HEADER]:
|
|
45
|
+
[SESSION_HEADER]: session,
|
|
46
|
+
[SESSION_AFFINITY_HEADER]: session,
|
|
43
47
|
...attributionHeaders(),
|
|
44
48
|
};
|
|
45
49
|
}
|
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dan-ai-studio/dshopencodego",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"description": "OpenCode Go provider for DeepSeek Harness: live gateway catalog, per-conversation session header, usage",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"icon": "./icon.svg",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
9
10
|
"url": "git+https://github.com/dan-ai-studio/dshopencodego.git"
|
|
@@ -14,7 +15,7 @@
|
|
|
14
15
|
},
|
|
15
16
|
"engines": {
|
|
16
17
|
"node": "^22.19.0 || >=24.0.0",
|
|
17
|
-
"dsh": ">=0.1.7-alpha.1 <0.2.0 || >=0.2.0-rc.1 <0.3.0"
|
|
18
|
+
"dsh": ">=0.1.7-alpha.1 <0.2.0 || >=0.2.0-rc.1 <0.2.1 || >=0.2.1-alpha.1 <0.3.0"
|
|
18
19
|
},
|
|
19
20
|
"main": "./lib/index.js",
|
|
20
21
|
"types": "./lib/types/index.d.ts",
|
|
@@ -27,11 +28,14 @@
|
|
|
27
28
|
"types": "./lib/types/client/index.d.ts",
|
|
28
29
|
"default": "./lib/client.js"
|
|
29
30
|
},
|
|
31
|
+
"./locale/*.json": "./locale/*.json",
|
|
30
32
|
"./package.json": "./package.json"
|
|
31
33
|
},
|
|
32
34
|
"files": [
|
|
33
35
|
"lib",
|
|
34
36
|
"cordis.patch.yml",
|
|
37
|
+
"icon.svg",
|
|
38
|
+
"locale",
|
|
35
39
|
"README.md",
|
|
36
40
|
"README.en.md",
|
|
37
41
|
"LICENSE"
|
|
@@ -63,11 +67,11 @@
|
|
|
63
67
|
"prepack": "npm run build"
|
|
64
68
|
},
|
|
65
69
|
"dependencies": {
|
|
66
|
-
"@deepseek-ai/schemastery": "
|
|
67
|
-
"@earendil-works/pi-ai": "0.
|
|
70
|
+
"@deepseek-ai/schemastery": "~3.18.5-alpha.2",
|
|
71
|
+
"@earendil-works/pi-ai": "~1.0.2"
|
|
68
72
|
},
|
|
69
73
|
"peerDependencies": {
|
|
70
|
-
"@deepseek-ai/cordis": "4.0.2 || 4.0.3 || 4.0.4",
|
|
74
|
+
"@deepseek-ai/cordis": "4.0.2 || 4.0.3 || 4.0.4 || 4.0.5-alpha.1 || 4.0.5-alpha.2",
|
|
71
75
|
"@deepseek-ai/dsh-api-remotes": ">=0.1.7-alpha.1 <0.2.0 || >=0.2.0-rc.1 <0.3.0",
|
|
72
76
|
"@deepseek-ai/dsh-attachment": ">=0.1.7-alpha.1 <0.2.0 || >=0.2.0-rc.1 <0.3.0",
|
|
73
77
|
"@deepseek-ai/dsh-brand": ">=0.1.7-alpha.1 <0.2.0 || >=0.2.0-rc.1 <0.3.0",
|
|
@@ -107,29 +111,28 @@
|
|
|
107
111
|
}
|
|
108
112
|
},
|
|
109
113
|
"devDependencies": {
|
|
110
|
-
"@deepseek-ai/cordis": "4.0.
|
|
111
|
-
"@deepseek-ai/dsh-api-remotes": "0.2.
|
|
112
|
-
"@deepseek-ai/dsh-attachment": "0.2.
|
|
113
|
-
"@deepseek-ai/dsh-brand": "0.2.
|
|
114
|
-
"@deepseek-ai/dsh-client-locale": "0.2.
|
|
115
|
-
"@deepseek-ai/dsh-client-store": "0.2.
|
|
116
|
-
"@deepseek-ai/dsh-client-ui-conversation": "
|
|
117
|
-
"@deepseek-ai/dsh-client-ui-model-selection": "0.2.
|
|
118
|
-
"@deepseek-ai/dsh-client-ui-renderer": "
|
|
119
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.2.
|
|
120
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.2.
|
|
121
|
-
"@deepseek-ai/dsh-credentials": "0.2.
|
|
122
|
-
"@deepseek-ai/dsh-fs": "0.2.
|
|
123
|
-
"@deepseek-ai/dsh-
|
|
124
|
-
"@deepseek-ai/dsh-
|
|
125
|
-
"@deepseek-ai/dsh-
|
|
126
|
-
"@deepseek-ai/dsh-
|
|
127
|
-
"@deepseek-ai/dsh-
|
|
128
|
-
"@deepseek-ai/dsh-
|
|
129
|
-
"@deepseek-ai/dsh-
|
|
130
|
-
"@deepseek-ai/dsh-
|
|
131
|
-
"@deepseek-ai/dsh-typert-
|
|
132
|
-
"@deepseek-ai/dsh-typert-registry": "^0.2.0-rc.2",
|
|
114
|
+
"@deepseek-ai/cordis": "4.0.5-alpha.2",
|
|
115
|
+
"@deepseek-ai/dsh-api-remotes": "0.2.1-alpha.3",
|
|
116
|
+
"@deepseek-ai/dsh-attachment": "0.2.1-alpha.3",
|
|
117
|
+
"@deepseek-ai/dsh-brand": "0.2.1-alpha.3",
|
|
118
|
+
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.3",
|
|
119
|
+
"@deepseek-ai/dsh-client-store": "0.2.1-alpha.3",
|
|
120
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.3",
|
|
121
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "0.2.1-alpha.3",
|
|
122
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.3",
|
|
123
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.1-alpha.3",
|
|
124
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.3",
|
|
125
|
+
"@deepseek-ai/dsh-credentials": "0.2.1-alpha.3",
|
|
126
|
+
"@deepseek-ai/dsh-fs": "0.2.1-alpha.3",
|
|
127
|
+
"@deepseek-ai/dsh-launch-environment": "0.2.1-alpha.3",
|
|
128
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.3",
|
|
129
|
+
"@deepseek-ai/dsh-sandbox": "0.2.1-alpha.3",
|
|
130
|
+
"@deepseek-ai/dsh-scope": "0.2.1-alpha.3",
|
|
131
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.3",
|
|
132
|
+
"@deepseek-ai/dsh-settings": "0.2.1-alpha.3",
|
|
133
|
+
"@deepseek-ai/dsh-timeout": "0.2.1-alpha.3",
|
|
134
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.3",
|
|
135
|
+
"@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.3",
|
|
133
136
|
"@testing-library/dom": "^10.4.1",
|
|
134
137
|
"@testing-library/react": "^16.3.0",
|
|
135
138
|
"@types/node": "^22.20.0",
|