@mofeng2223/dsh-claude-provider 0.4.2 → 0.4.4
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.md +9 -13
- package/README.zh-CN.md +7 -11
- package/lib/client.js +57 -28
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,17 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
English | [简体中文](./README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
DSH Claude Provider adds a dedicated Claude configuration interface to DeepSeek Harness. You can add multiple Claude providers, choose reasoning levels for each model, and automatically fetch model lists and fill in capacity settings and reasoning presets for common Claude models, without editing `settings.yaml` manually.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
The plugin retains its dedicated Claude provider configuration page, so users do not need to edit `settings.yaml` manually. Anthropic-native model discovery, automatic defaults for common Claude models, and other features not yet available in DeepSeek Harness are also retained.
|
|
7
|
+
Compared with the official generic custom provider form, the plugin adds a dedicated Claude entry, five-level, four-level, and on/off reasoning presets, and automatic defaults for known Claude models. DeepSeek Harness handles the saved reasoning configuration natively.
|
|
10
8
|
|
|
11
9
|
## What this plugin does
|
|
12
10
|
|
|
13
11
|
1. **Adds a dedicated Claude provider type**
|
|
14
12
|
|
|
15
|
-
The Models settings page gains a separate **Claude Provider** form.
|
|
13
|
+
The Models settings page gains a separate **Claude Provider** form.
|
|
16
14
|
|
|
17
15
|
<p align="center">
|
|
18
16
|
<img src="./docs/images/provider-entry.en.jpg" alt="Add Claude Provider entry in DeepSeek Harness" width="580">
|
|
@@ -34,17 +32,15 @@ The plugin retains its dedicated Claude provider configuration page, so users do
|
|
|
34
32
|
|
|
35
33
|
New models default to five levels, and Claude providers default to High.
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
For adaptive thinking models, the plugin writes the selected level to DSH's native configuration when saved.
|
|
35
|
+
On save, the plugin writes each model's reasoning levels and adaptive thinking settings to DeepSeek Harness's native configuration.
|
|
40
36
|
|
|
41
37
|
<p align="center">
|
|
42
38
|
<img src="./docs/images/model-defaults.en.jpg" alt="Claude model capacity defaults and reasoning modes" width="580">
|
|
43
39
|
</p>
|
|
44
40
|
|
|
45
|
-
3. **
|
|
41
|
+
3. **Supports paginated Anthropic model discovery**
|
|
46
42
|
|
|
47
|
-
|
|
43
|
+
The plugin fetches model lists through an Anthropic-compatible `GET /v1/models` endpoint, follows the returned cursors to retrieve subsequent pages, and deduplicates the results.
|
|
48
44
|
|
|
49
45
|
4. **Fills known Claude model defaults after discovery**
|
|
50
46
|
|
|
@@ -58,7 +54,7 @@ The plugin retains its dedicated Claude provider configuration page, so users do
|
|
|
58
54
|
|
|
59
55
|
### Published package
|
|
60
56
|
|
|
61
|
-
|
|
57
|
+
For the browser interface, install the plugin into the Web profile:
|
|
62
58
|
|
|
63
59
|
```sh
|
|
64
60
|
npx @deepseek-ai/dsh plugin --profile web add @mofeng2223/dsh-claude-provider
|
|
@@ -68,7 +64,7 @@ Restart the corresponding DeepSeek Harness process after installation.
|
|
|
68
64
|
|
|
69
65
|
### From source
|
|
70
66
|
|
|
71
|
-
|
|
67
|
+
Clone, build, and package the repository first:
|
|
72
68
|
|
|
73
69
|
```sh
|
|
74
70
|
git clone https://github.com/MoFeng2223/dsh-claude-provider.git
|
|
@@ -91,7 +87,7 @@ npx @deepseek-ai/dsh plugin --profile web add ./dist/mofeng2223-dsh-claude-provi
|
|
|
91
87
|
npx @deepseek-ai/dsh plugin --profile web remove @mofeng2223/dsh-claude-provider
|
|
92
88
|
```
|
|
93
89
|
|
|
94
|
-
Uninstalling the plugin does not delete `~/.dsh/settings.yaml` or stored credentials. Existing Claude providers remain ordinary custom `anthropic-messages`
|
|
90
|
+
Uninstalling the plugin does not delete `~/.dsh/settings.yaml` or stored credentials. Existing Claude providers remain ordinary custom `anthropic-messages` providers, and their saved reasoning levels and adaptive thinking settings remain effective. The dedicated Claude add/edit interface, paginated model discovery, and automatic defaults are no longer available; the official model discovery feature remains available.
|
|
95
91
|
|
|
96
92
|
## License
|
|
97
93
|
|
package/README.zh-CN.md
CHANGED
|
@@ -2,17 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
[English](./README.md) | 简体中文
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
DSH Claude Provider 为 DeepSeek Harness 提供专用的 Claude 配置界面。你可以添加多个 Claude 提供方,为每个模型选择推理档位,并自动获取模型列表、填写常用 Claude 模型的容量和推理预设,无需手动编辑 `settings.yaml`。
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
插件仍保留专用的 Claude 提供方配置页面,用户无需手动编辑 `settings.yaml`。Anthropic 原生模型探测、常用 Claude 模型参数自动填写等官方尚未实现的功能也继续保留。
|
|
7
|
+
相比官方的通用自定义提供方配置,插件增加了独立的 Claude 入口、五档/四档/开关式推理预设,以及按已知 Claude 模型自动填写参数的功能。保存后的推理配置由 DeepSeek Harness 原生处理。
|
|
10
8
|
|
|
11
9
|
## 插件功能
|
|
12
10
|
|
|
13
11
|
1. **增加独立的 Claude 提供方类型**
|
|
14
12
|
|
|
15
|
-
模型设置页面会增加单独的“Claude
|
|
13
|
+
模型设置页面会增加单独的“Claude 提供方”表单。
|
|
16
14
|
|
|
17
15
|
<p align="center">
|
|
18
16
|
<img src="./docs/images/provider-entry.jpg" alt="DeepSeek Harness 中新增的 Claude 提供方入口" width="580">
|
|
@@ -34,17 +32,15 @@
|
|
|
34
32
|
|
|
35
33
|
新增模型默认使用五档,Claude 提供方默认选择 High。
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
对于 adaptive thinking 模型,插件会在保存时将所选档位写入 dsh 原生配置。
|
|
35
|
+
插件会在保存时将模型的推理档位和自适应思考设置写入 DeepSeek Harness 原生配置。
|
|
40
36
|
|
|
41
37
|
<p align="center">
|
|
42
38
|
<img src="./docs/images/model-defaults.jpg" alt="Claude 模型容量预填与思考模式设置" width="580">
|
|
43
39
|
</p>
|
|
44
40
|
|
|
45
|
-
3.
|
|
41
|
+
3. **支持 Anthropic 模型列表分页获取**
|
|
46
42
|
|
|
47
|
-
|
|
43
|
+
插件通过 Anthropic 兼容的 `GET /v1/models` 接口获取模型列表,并根据接口返回的游标继续读取后续页面、合并重复模型。
|
|
48
44
|
|
|
49
45
|
4. **探测后自动填写常用 Claude 模型参数**
|
|
50
46
|
|
|
@@ -91,7 +87,7 @@ npx @deepseek-ai/dsh plugin --profile web add ./dist/mofeng2223-dsh-claude-provi
|
|
|
91
87
|
npx @deepseek-ai/dsh plugin --profile web remove @mofeng2223/dsh-claude-provider
|
|
92
88
|
```
|
|
93
89
|
|
|
94
|
-
卸载插件不会删除 `~/.dsh/settings.yaml` 或已经保存的凭据。已有的 Claude 提供方会继续作为普通的 `anthropic-messages`
|
|
90
|
+
卸载插件不会删除 `~/.dsh/settings.yaml` 或已经保存的凭据。已有的 Claude 提供方会继续作为普通的 `anthropic-messages` 自定义提供方保留,已保存的推理档位和自适应思考配置仍然有效。卸载后将不再提供 Claude 专用的添加/编辑界面、分页模型探测和参数预填;官方的模型探测功能仍然可用。
|
|
95
91
|
|
|
96
92
|
## 许可证
|
|
97
93
|
|
package/lib/client.js
CHANGED
|
@@ -649,9 +649,9 @@ window.__ModuleLoader__.load({
|
|
|
649
649
|
const allVisibleCandidatesPicked = visibleCandidates.length > 0 && visibleCandidates.every((candidate) => picked.has(candidate.id));
|
|
650
650
|
const toggleVisibleCandidates = () => {
|
|
651
651
|
setPicked((current) => {
|
|
652
|
+
if (visibleCandidates.every((candidate) => current.has(candidate.id))) return /* @__PURE__ */ new Set();
|
|
652
653
|
const next = new Set(current);
|
|
653
|
-
|
|
654
|
-
else for (const candidate of visibleCandidates) next.add(candidate.id);
|
|
654
|
+
for (const candidate of visibleCandidates) next.add(candidate.id);
|
|
655
655
|
return next;
|
|
656
656
|
});
|
|
657
657
|
};
|
|
@@ -911,7 +911,8 @@ window.__ModuleLoader__.load({
|
|
|
911
911
|
settingsNs: entry.settingsNs,
|
|
912
912
|
settingsPath: [...entry.settingsPath],
|
|
913
913
|
active: active.has(entry.provider),
|
|
914
|
-
...entry.declared === void 0 ? {} : { declared: entry.declared }
|
|
914
|
+
...entry.declared === void 0 ? {} : { declared: entry.declared },
|
|
915
|
+
...entry.error === void 0 ? {} : { error: entry.error }
|
|
915
916
|
}));
|
|
916
917
|
for (const provider of registered) {
|
|
917
918
|
if (declared.has(provider.id)) continue;
|
|
@@ -1157,6 +1158,14 @@ window.__ModuleLoader__.load({
|
|
|
1157
1158
|
* credential seam with a raw regular expression the user cannot act on.
|
|
1158
1159
|
*/
|
|
1159
1160
|
const ROUTE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
1161
|
+
function isHttpUrl(value) {
|
|
1162
|
+
try {
|
|
1163
|
+
const protocol = new URL(value).protocol;
|
|
1164
|
+
return protocol === "http:" || protocol === "https:";
|
|
1165
|
+
} catch {
|
|
1166
|
+
return false;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1160
1169
|
/**
|
|
1161
1170
|
* Render the custom-provider creation card.
|
|
1162
1171
|
* @param props - existing routes, protocol choices, wire faces, and copy.
|
|
@@ -1186,11 +1195,13 @@ window.__ModuleLoader__.load({
|
|
|
1186
1195
|
const profileDisabled = disabled || committed;
|
|
1187
1196
|
const routeInvalid = route.length > 0 && !ROUTE_PATTERN.test(route);
|
|
1188
1197
|
const routeTaken = taken.includes(route);
|
|
1198
|
+
const normalizedBaseURL = baseURL.trim();
|
|
1199
|
+
const baseUrlInvalid = baseURL.length > 0 && !isHttpUrl(normalizedBaseURL);
|
|
1189
1200
|
const modelFailure = validateDeepSeekModels(models);
|
|
1190
1201
|
const keyFailure = apiKeyFailure(keyDraft);
|
|
1191
1202
|
const keyValue = keyDraft.trim();
|
|
1192
|
-
const ready = route.length > 0 && !routeInvalid && !routeTaken &&
|
|
1193
|
-
const hint = failure !== void 0 || ready || keyFailure !== void 0 || route.length === 0 || routeInvalid || routeTaken ? void 0 :
|
|
1203
|
+
const ready = route.length > 0 && !routeInvalid && !routeTaken && normalizedBaseURL.length > 0 && !baseUrlInvalid && models.length > 0 && modelFailure === void 0 && keyFailure === void 0;
|
|
1204
|
+
const hint = failure !== void 0 || ready || keyFailure !== void 0 || route.length === 0 || routeInvalid || routeTaken || baseUrlInvalid ? void 0 : normalizedBaseURL.length === 0 ? t("customNeedsBaseUrl") : modelFailure !== void 0 ? `${t("model")} ${String(modelFailure.index + 1)}: ${t(modelFailure.key)}` : t("customNeedsModels");
|
|
1194
1205
|
/** Perform the create, returning a failure message or undefined. */
|
|
1195
1206
|
const createOnce = async () => {
|
|
1196
1207
|
const keyRef = deriveKeyRef(route);
|
|
@@ -1200,7 +1211,7 @@ window.__ModuleLoader__.load({
|
|
|
1200
1211
|
...displayName.length === 0 ? {} : { displayName },
|
|
1201
1212
|
...storesKey ? { apiKeyEnv: keyRef } : {},
|
|
1202
1213
|
api: isAdaptiveClaude ? "anthropic-messages" : protocol,
|
|
1203
|
-
baseURL,
|
|
1214
|
+
baseURL: normalizedBaseURL,
|
|
1204
1215
|
models: models.map((model) => isAdaptiveClaude ? withNativeClaudeModel(model) : { ...model }),
|
|
1205
1216
|
...isAdaptiveClaude ? { reasoning: "high" } : {}
|
|
1206
1217
|
};
|
|
@@ -1306,12 +1317,17 @@ window.__ModuleLoader__.load({
|
|
|
1306
1317
|
value: baseURL,
|
|
1307
1318
|
placeholder: t("customBaseUrlPlaceholder"),
|
|
1308
1319
|
"aria-label": t("baseUrl"),
|
|
1320
|
+
"aria-invalid": baseUrlInvalid,
|
|
1309
1321
|
disabled: profileDisabled,
|
|
1310
1322
|
onChange: (event) => {
|
|
1311
1323
|
setBaseURL(event.target.value);
|
|
1312
1324
|
}
|
|
1313
1325
|
})]
|
|
1314
1326
|
}),
|
|
1327
|
+
baseUrlInvalid ? (0, react_jsx_runtime.jsx)("p", {
|
|
1328
|
+
className: ModelsSection_module_css_default["error"],
|
|
1329
|
+
children: t("customBaseUrlInvalid")
|
|
1330
|
+
}) : null,
|
|
1315
1331
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
1316
1332
|
className: ModelsSection_module_css_default["field"],
|
|
1317
1333
|
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
@@ -1361,11 +1377,11 @@ window.__ModuleLoader__.load({
|
|
|
1361
1377
|
onChange: setModels,
|
|
1362
1378
|
probe: {
|
|
1363
1379
|
settingsNs: NS$1,
|
|
1364
|
-
baseURL,
|
|
1380
|
+
baseURL: normalizedBaseURL,
|
|
1365
1381
|
api: protocol,
|
|
1366
1382
|
...keyValue.length === 0 ? {} : { apiKey: keyValue }
|
|
1367
1383
|
},
|
|
1368
|
-
probeBlocked: keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
|
|
1384
|
+
probeBlocked: baseUrlInvalid ? "customBaseUrlInvalid" : keyFailure === "keyBlank" ? "keyBlankNew" : keyFailure,
|
|
1369
1385
|
thinkingPresets: isAdaptiveClaude,
|
|
1370
1386
|
operations,
|
|
1371
1387
|
t,
|
|
@@ -2087,7 +2103,8 @@ window.__ModuleLoader__.load({
|
|
|
2087
2103
|
};
|
|
2088
2104
|
const anyUsable = state.rows.some(providerUsable);
|
|
2089
2105
|
const configured = state.rows.filter((row) => row.configured);
|
|
2090
|
-
const
|
|
2106
|
+
const configurable = state.rows.filter((row) => state.namespaces.has(row.entry.settingsNs));
|
|
2107
|
+
const addable = configurable.filter((row) => !row.configured);
|
|
2091
2108
|
const addTarget = adding ? editing : void 0;
|
|
2092
2109
|
const addNamespace = addTarget === void 0 ? void 0 : state.namespaces.get(addTarget.settingsNs);
|
|
2093
2110
|
const addRow = addTarget === void 0 ? void 0 : state.rows.find((row) => row.entry.provider === addTarget.provider);
|
|
@@ -2120,24 +2137,33 @@ window.__ModuleLoader__.load({
|
|
|
2120
2137
|
const namespace = state.namespaces.get(target.settingsNs);
|
|
2121
2138
|
/* v8 ignore next -- the join marks a row configured only when its namespace resolved */
|
|
2122
2139
|
if (namespace === void 0) return null;
|
|
2140
|
+
const error = row.entry.error === void 0 ? null : (0, react_jsx_runtime.jsx)("p", {
|
|
2141
|
+
role: "alert",
|
|
2142
|
+
className: ModelsSection_module_css_default["error"],
|
|
2143
|
+
children: row.entry.error
|
|
2144
|
+
});
|
|
2123
2145
|
if (needsSetup(row, anyUsable) && !dismissedSetup.has(row.entry.provider)) return (0, react_jsx_runtime.jsxs)("li", {
|
|
2124
2146
|
className: ModelsSection_module_css_default["setupCard"],
|
|
2125
|
-
children: [
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2147
|
+
children: [
|
|
2148
|
+
error,
|
|
2149
|
+
renderProviderEditor({
|
|
2150
|
+
target,
|
|
2151
|
+
namespace,
|
|
2152
|
+
schema,
|
|
2153
|
+
thinkingPresets: isClaudeProvider(row, state),
|
|
2154
|
+
operations,
|
|
2155
|
+
t,
|
|
2156
|
+
readOnly: !state.writable,
|
|
2157
|
+
onClose: (changed) => {
|
|
2158
|
+
closeSetup(changed, target);
|
|
2159
|
+
}
|
|
2160
|
+
}),
|
|
2161
|
+
renderSlot("settings.models.provider-card", {
|
|
2162
|
+
provider: row.entry,
|
|
2163
|
+
configured: row.configured,
|
|
2164
|
+
keyConfigured: keyConfiguredOf(row)
|
|
2165
|
+
}, { entryKey: row.entry.settingsNs })
|
|
2166
|
+
]
|
|
2141
2167
|
}, row.entry.provider);
|
|
2142
2168
|
const open = !adding && editing?.provider === row.entry.provider;
|
|
2143
2169
|
const adaptiveClaude = isClaudeProvider(row, state);
|
|
@@ -2202,6 +2228,7 @@ window.__ModuleLoader__.load({
|
|
|
2202
2228
|
}) : null]
|
|
2203
2229
|
})]
|
|
2204
2230
|
}),
|
|
2231
|
+
error,
|
|
2205
2232
|
renderSlot("settings.models.provider-card", {
|
|
2206
2233
|
provider: row.entry,
|
|
2207
2234
|
configured: row.configured,
|
|
@@ -2287,7 +2314,7 @@ window.__ModuleLoader__.load({
|
|
|
2287
2314
|
})
|
|
2288
2315
|
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
2289
2316
|
className: ModelsSection_module_css_default["addActions"],
|
|
2290
|
-
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
2317
|
+
children: [configurable.length > 0 && (0, react_jsx_runtime.jsxs)("button", {
|
|
2291
2318
|
type: "button",
|
|
2292
2319
|
className: ModelsSection_module_css_default["addButton"],
|
|
2293
2320
|
disabled: addable.length === 0 || !state.writable,
|
|
@@ -2301,7 +2328,7 @@ window.__ModuleLoader__.load({
|
|
|
2301
2328
|
setEditing(targetOf(first));
|
|
2302
2329
|
},
|
|
2303
2330
|
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }), t("add")]
|
|
2304
|
-
}), (0, react_jsx_runtime.jsxs)("button", {
|
|
2331
|
+
}), state.namespaces.has("llm-pi-ai") && (0, react_jsx_runtime.jsxs)("button", {
|
|
2305
2332
|
type: "button",
|
|
2306
2333
|
className: ModelsSection_module_css_default["addButton"],
|
|
2307
2334
|
disabled: protocols.length === 0 || !state.writable,
|
|
@@ -2315,7 +2342,7 @@ window.__ModuleLoader__.load({
|
|
|
2315
2342
|
}), (0, react_jsx_runtime.jsxs)("button", {
|
|
2316
2343
|
type: "button",
|
|
2317
2344
|
className: ModelsSection_module_css_default["addButton"],
|
|
2318
|
-
disabled: !state.namespaces.has(CLAUDE_PROVIDER_SETTINGS_NS) || !state.writable,
|
|
2345
|
+
disabled: !state.namespaces.has("llm-pi-ai") || !state.namespaces.has(CLAUDE_PROVIDER_SETTINGS_NS) || !state.writable,
|
|
2319
2346
|
onClick: () => {
|
|
2320
2347
|
setSavedTarget(void 0);
|
|
2321
2348
|
setAdding(false);
|
|
@@ -2894,6 +2921,7 @@ window.__ModuleLoader__.load({
|
|
|
2894
2921
|
customApi: "API protocol",
|
|
2895
2922
|
customApiUnset: "Not selected",
|
|
2896
2923
|
customNeedsBaseUrl: "A custom provider needs a base URL.",
|
|
2924
|
+
customBaseUrlInvalid: "Enter a valid HTTP or HTTPS URL.",
|
|
2897
2925
|
customNeedsModels: "A custom provider needs at least one model.",
|
|
2898
2926
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
2899
2927
|
settingsPathUnresolvable: "unresolvable settings path",
|
|
@@ -3009,6 +3037,7 @@ window.__ModuleLoader__.load({
|
|
|
3009
3037
|
customApi: "API 协议",
|
|
3010
3038
|
customApiUnset: "未选择",
|
|
3011
3039
|
customNeedsBaseUrl: "自定义提供方需要填写 API 地址。",
|
|
3040
|
+
customBaseUrlInvalid: "请输入有效的 HTTP 或 HTTPS 地址。",
|
|
3012
3041
|
customNeedsModels: "自定义提供方至少需要一个模型。",
|
|
3013
3042
|
customBaseUrlPlaceholder: "https://gateway.example/v1",
|
|
3014
3043
|
settingsPathUnresolvable: "无法解析设置路径",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mofeng2223/dsh-claude-provider",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "Custom Claude provider support for DeepSeek Harness 0.1.2",
|
|
3
|
+
"version": "0.4.4",
|
|
4
|
+
"description": "Custom Claude provider support for DeepSeek Harness 0.1.5-rc.2",
|
|
5
5
|
"author": "mofeng2223",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -60,6 +60,6 @@
|
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@deepseek-ai/dsh-client-ui-settings-models": "0.1.
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-settings-models": "0.1.5-rc.2"
|
|
64
64
|
}
|
|
65
65
|
}
|