@karoc/dsh-proxy 0.1.3 → 0.1.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/CHANGELOG.md +79 -0
- package/CONTRIBUTING.md +3 -2
- package/README.md +33 -14
- package/README.zh.md +15 -10
- package/cordis.patch.yml +2 -1
- package/lib/client.js +3 -3
- package/lib/index.js +1 -1
- package/package.json +48 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,84 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.4] - 2026-09-25
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **DSH 0.1.7 icon rename (upstream commit `4937343a5e`, released from
|
|
8
|
+
`0.1.7-alpha.1`).** `IconChevronDownOutline14`, `IconGlobeOutline14` and
|
|
9
|
+
`IconLinkOutline14` no longer exist in `dsh-client-ui-primitives` — the size
|
|
10
|
+
suffix moved into each artwork's default and the name now carries the stroke
|
|
11
|
+
weight — so all three resolved to `undefined` and the Settings → Smoothly
|
|
12
|
+
Proxy section crashed on render (`React error #130`,
|
|
13
|
+
`slot entry crashed in 'settings.section'`). `src/client/ProxySection.tsx`
|
|
14
|
+
now imports the `*Regular` variants the built-in pages use. Rendered sizes: the chevron and the globe
|
|
15
|
+
stay 14 px (their artwork defaults); only the link moves from 14 px to its
|
|
16
|
+
16 px artwork default. **Support floor:** the client half requires dsh ≥ 0.1.7
|
|
17
|
+
**since v0.1.4** — **v0.1.3 remains the release for 0.1.2–0.1.6**.
|
|
18
|
+
|
|
19
|
+
- **Loopback was only recognised as the literal `127.0.0.1`.** The routing guard
|
|
20
|
+
was `/^(127\.0\.0\.1|localhost|::1|0\.0\.0\.0)$/`, so every other address in the
|
|
21
|
+
`127.0.0.0/8` block (e.g. `127.0.0.2`, used by interface aliases and some
|
|
22
|
+
container setups) was sent to the **upstream proxy** when it was listed in
|
|
23
|
+
`proxiedHosts` — contradicting the documented "loopback targets are always
|
|
24
|
+
direct" guarantee. The guard now matches the whole `127/8` block. The spec
|
|
25
|
+
assertion that was supposed to pin this was **vacuous** (it asserted the
|
|
26
|
+
loopback hosts against a `proxiedHosts` list that did not contain them, so it
|
|
27
|
+
returned "direct" for the unlisted-host reason and would have stayed green with
|
|
28
|
+
the guard deleted) — it now lists them, adds a positive control, and covers
|
|
29
|
+
`127.0.0.2`; verified red against the old guard before the fix.
|
|
30
|
+
- Dropped the dead `@deepseek-ai/dsh-client-runtime/client` entry from the
|
|
31
|
+
bundler externals and the client-boot spec: that package no longer ships with
|
|
32
|
+
DSH and nothing imports it (same stale reference as the `dsh.client.inject`
|
|
33
|
+
row removed above).
|
|
34
|
+
|
|
35
|
+
### Tests
|
|
36
|
+
|
|
37
|
+
- **`npm run verify:all` — every gate, one command, bound to the commit.**
|
|
38
|
+
It runs script syntax, the spec suite, the guarantee gate, the negative
|
|
39
|
+
controls and the release gate, and writes `{ts, commit, node, steps[]}` to the
|
|
40
|
+
gitignored `lib/verify-report.json`. `npm run verify:fresh` FAILS when HEAD no
|
|
41
|
+
longer matches the recorded commit — because a green claim is only as good as
|
|
42
|
+
the commit it was measured on, and this repo deliberately re-points tags for
|
|
43
|
+
unpublished versions. A failed step is a failed verification, never an
|
|
44
|
+
"unknown".
|
|
45
|
+
- **Negative controls, now part of `npm test`** (`npm run test:controls`).
|
|
46
|
+
A gate nobody has seen fail is not evidence, so `scripts/test-negative-controls.mjs`
|
|
47
|
+
clones the committed tree per scenario, injects ONE defect, and asserts the
|
|
48
|
+
gate fails with the documented message: a dirty tree, a removed CHANGELOG
|
|
49
|
+
entry, a deleted release tag, a removed build artifact, and a guarantee row
|
|
50
|
+
whose pinning assertion no longer exists — plus a positive control (an
|
|
51
|
+
unmutated clone must pass both gates). 5/5 mutations caught.
|
|
52
|
+
- **Guarantee gate, now part of `npm test`.** `docs/guarantees.md` lists this
|
|
53
|
+
plugin's negative guarantees and names the assertion label that pins each one;
|
|
54
|
+
`scripts/check-guarantees.mjs` fails the suite when a label disappears (12 rows
|
|
55
|
+
today, and the selector must exist in `scripts/*.spec.mjs`). Verified by
|
|
56
|
+
negative control: pointing a row at a non-existent label makes the gate FAIL.
|
|
57
|
+
The routing guard that shipped matching only the literal `127.0.0.1` stayed
|
|
58
|
+
invisible for months precisely because the assertion meant to pin it could not
|
|
59
|
+
fail — the gate plus the `127/8` assertion close that class of defect.
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- **The dsh floor is now declared, not just documented.** `package.json`
|
|
64
|
+
declares an optional peer dependency
|
|
65
|
+
`@deepseek-ai/dsh-client-ui-settings: ">=0.1.7-rc.1"`. The gate that reads it ships from **DSH 0.1.7-rc.1** on — it
|
|
66
|
+
compares every `@deepseek-ai/dsh*` peer against the running runtime and refuses
|
|
67
|
+
a plugin the runtime fails, printing the `dsh plugin allow-version` remedy.
|
|
68
|
+
Runtimes older than that gate evaluate **no** peers
|
|
69
|
+
and refuse nothing: on 0.1.2–0.1.6 the client half cannot render (the
|
|
70
|
+
`*Regular` icon names arrived in 0.1.7-alpha.1), so **v0.1.3 remains the
|
|
71
|
+
release for 0.1.2–0.1.6** — the 0.1.7 alphas have those icons and work. It is
|
|
72
|
+
marked `peerDependenciesMeta.optional` because the host supplies that package
|
|
73
|
+
at runtime, so npm installs nothing extra. Note the prerelease rule the range encodes (measured with the semver DSH
|
|
74
|
+
actually resolves — 7.8.5): `>=0.1.7` and `^0.1.7` do **not** match a
|
|
75
|
+
`0.1.7-rc.N` runtime, hence the explicit `-rc.1` floor. semver 7.7.4 answers
|
|
76
|
+
`true` for the caret form.
|
|
77
|
+
- Removed the stale `@deepseek-ai/dsh-client-runtime` entry from
|
|
78
|
+
`dsh.client.inject`: that package no longer ships with DSH (11 versions exist on npm, but `latest`
|
|
79
|
+
is still the historical `0.0.1-rc.1` and nothing in the harness tree provides
|
|
80
|
+
it), and the loader silently ignored the unresolvable row.
|
|
81
|
+
|
|
3
82
|
## [0.1.3]
|
|
4
83
|
|
|
5
84
|
- **Brand name**: Smoothly Proxy / 思磨力代理插件 — the plugin's user-visible
|
package/CONTRIBUTING.md
CHANGED
|
@@ -8,7 +8,8 @@ model-provider proxying.
|
|
|
8
8
|
```sh
|
|
9
9
|
pnpm install # dev deps (tsdown, typescript, react types)
|
|
10
10
|
pnpm typecheck # tsc --noEmit
|
|
11
|
-
pnpm test #
|
|
11
|
+
pnpm test # node --test: proxy-core (13 scenarios) + host-route /
|
|
12
|
+
# client-boot / cordis-mount specs (no external network)
|
|
12
13
|
pnpm bundle # emit lib/index.js + lib/client.js
|
|
13
14
|
```
|
|
14
15
|
|
|
@@ -24,7 +25,7 @@ To see the plugin live in the GUI, link it into a profile:
|
|
|
24
25
|
```jsonc
|
|
25
26
|
// ~/.dsh/profiles/web/package.json
|
|
26
27
|
"dependencies": { "@karoc/dsh-proxy": "link:/path/to/dsh-proxy", ... },
|
|
27
|
-
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", ..., "dsh-proxy"] } }
|
|
28
|
+
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", ..., "@karoc/dsh-proxy"] } }
|
|
28
29
|
```
|
|
29
30
|
|
|
30
31
|
Then `cd ~/.dsh/profiles/web && pnpm install` and **restart `dsh web`**
|
package/README.md
CHANGED
|
@@ -29,12 +29,15 @@ desktop shell had.
|
|
|
29
29
|
|
|
30
30
|
## What it adds
|
|
31
31
|
|
|
32
|
-
A new Settings section, **「思磨力代理 / Smoothly Proxy
|
|
33
|
-
built-in **Models** and
|
|
32
|
+
A new Settings section, **「思磨力代理 / Smoothly Proxy」** (nav order 25), placed
|
|
33
|
+
after the built-in **Models** page and, when that plugin is installed, the
|
|
34
|
+
external **Model reasoning** page. It shows:
|
|
34
35
|
|
|
35
36
|
- an **upstream proxy card**: enable toggle, protocol selector (HTTP / HTTPS /
|
|
36
37
|
SOCKS5), host, port, optional username/password, and a **Test connection**
|
|
37
|
-
button
|
|
38
|
+
button (a SOCKS5 handshake for SOCKS5, a `CONNECT` probe for HTTP; an HTTPS
|
|
39
|
+
upstream is only checked for TCP reachability — its TLS handshake is not
|
|
40
|
+
verified);
|
|
38
41
|
- a **model providers** list — hosts read from your dsh `settings.yaml`
|
|
39
42
|
(`llm-deepseek.baseURL`, `llm-pi-ai.providers.<n>.baseURL`, any `llm-*`
|
|
40
43
|
namespace), labeled with the friendly display name where available;
|
|
@@ -119,8 +122,8 @@ A git install runs the package's `prepare` script to build the bundle. pnpm ≥
|
|
|
119
122
|
Bump to the newest release with pnpm update (or re-add to pick up a newer git ref):
|
|
120
123
|
|
|
121
124
|
```sh
|
|
122
|
-
dsh plugin --profile web update dsh-proxy
|
|
123
|
-
# or, if the dependency spec is pinned: dsh plugin --profile web add dsh-proxy
|
|
125
|
+
dsh plugin --profile web update @karoc/dsh-proxy
|
|
126
|
+
# or, if the dependency spec is pinned: dsh plugin --profile web add @karoc/dsh-proxy
|
|
124
127
|
```
|
|
125
128
|
|
|
126
129
|
Then **restart `dsh web`** so the new client bundle loads.
|
|
@@ -128,7 +131,7 @@ Then **restart `dsh web`** so the new client bundle loads.
|
|
|
128
131
|
### Removing
|
|
129
132
|
|
|
130
133
|
```sh
|
|
131
|
-
dsh plugin --profile web remove dsh-proxy
|
|
134
|
+
dsh plugin --profile web remove @karoc/dsh-proxy
|
|
132
135
|
```
|
|
133
136
|
|
|
134
137
|
This removes both the dependency and its bundle layer from the `web` profile. Restart `dsh web` for the section to disappear.
|
|
@@ -149,7 +152,8 @@ src/client/index.ts # client apply: register settings.section (id dsh-proxy)
|
|
|
149
152
|
src/client/ProxySection.tsx # the settings page (upstream card + host lists)
|
|
150
153
|
src/client/styles.ts # design-token styles (--dsw-alias-*) + injection
|
|
151
154
|
src/client/locales.ts # en/zh copy
|
|
152
|
-
scripts
|
|
155
|
+
scripts/*.spec.mjs # behavioral tests: proxy-core.ts (13 scenarios) plus
|
|
156
|
+
# host route / client boot / cordis mount — no network
|
|
153
157
|
```
|
|
154
158
|
|
|
155
159
|
### The /proxy/api route
|
|
@@ -157,7 +161,7 @@ scripts/proxy-core.spec.mjs # behavioral tests (13 scenarios, no network)
|
|
|
157
161
|
The host half serves the settings page over a same-origin HTTP route (the
|
|
158
162
|
built-in `/api` prefix is reserved for the gateway, so this uses `/proxy/api`):
|
|
159
163
|
|
|
160
|
-
- `GET /proxy/api` → `{ upstream, proxiedHosts, knownHosts, hosts, providers, port }`
|
|
164
|
+
- `GET /proxy/api` → `{ ok, upstream, proxiedHosts, knownHosts, hosts, providers, port }`
|
|
161
165
|
- `POST /proxy/api` `{ op: 'save', upstream, proxiedHosts }` → sanitized + persisted config
|
|
162
166
|
- `POST /proxy/api` `{ op: 'test', upstream }` → `{ ok, detail }`
|
|
163
167
|
- `POST /proxy/api` `{ op: 'persist' }` → merge observed hosts into `knownHosts`
|
|
@@ -167,7 +171,9 @@ built-in `/api` prefix is reserved for the gateway, so this uses `/proxy/api`):
|
|
|
167
171
|
```sh
|
|
168
172
|
pnpm install
|
|
169
173
|
pnpm bundle # emits lib/index.js + lib/client.js
|
|
170
|
-
pnpm
|
|
174
|
+
pnpm typecheck # tsc --noEmit
|
|
175
|
+
pnpm test # node --test: proxy-core (13 scenarios) + host-route /
|
|
176
|
+
# client-boot / cordis-mount specs (no network)
|
|
171
177
|
pnpm release:check # release gate: docs/changelog/tag/tree/build/registry must all pass
|
|
172
178
|
pnpm publish # runs the gate (prepack/prepublishOnly), then postpublish verifies the live release
|
|
173
179
|
```
|
|
@@ -189,18 +195,31 @@ module table; everything else is inlined.
|
|
|
189
195
|
- `npm`/`pnpm` install/update traffic goes through the proxy like everything
|
|
190
196
|
else; toggling a host **related to install/update** takes effect on the next
|
|
191
197
|
install/update (already-in-flight operations keep their environment).
|
|
198
|
+
- **A SOCKS5 upstream only carries HTTPS targets.** SOCKS5 has no absolute-URI
|
|
199
|
+
HTTP mode, so a selected plain `http://` host falls back to direct through a
|
|
200
|
+
SOCKS5 upstream (the settings page states the same thing).
|
|
192
201
|
- **Section nav icon is shell-assigned, not plugin-assigned.** The built-in
|
|
193
202
|
`ui-settings-general` `SettingsRoot.tsx` `navIcon(id)` maps known ids and
|
|
194
203
|
falls back to a gear for every other id — including this section's
|
|
195
204
|
`dsh-proxy`. The `settings.section` registration has no icon field, so an
|
|
196
205
|
external plugin cannot set it without patching the shell. When DSH exposes a
|
|
197
|
-
per-section icon, use `
|
|
206
|
+
per-section icon, use `IconGlobeOutlineRegular` from `dsh-client-ui-primitives`
|
|
198
207
|
for this section.
|
|
199
|
-
- **
|
|
208
|
+
- **Requires dsh ≥ 0.1.7 since v0.1.4 — v0.1.3 remains the release for
|
|
209
|
+
0.1.2–0.1.6.** DSH 0.1.7 renamed the icon exports (`IconX14` → `IconXRegular`,
|
|
210
|
+
the stroke-weight naming; upstream commit `4937343a5e`), so this section
|
|
211
|
+
imports the `*Regular` variants. The floor is declared as an **optional peer
|
|
212
|
+
dependency** on `@deepseek-ai/dsh-client-ui-settings`, which the dsh ≥ 0.1.7
|
|
213
|
+
compatibility gate compares against the running dsh version — a mismatch
|
|
214
|
+
refuses the bundle and names the exact `dsh plugin allow-version` remedy.
|
|
215
|
+
dsh < 0.1.7 predates that gate, so those runtimes still load this plugin and
|
|
216
|
+
render a broken section — install v0.1.3 there.
|
|
217
|
+
- **Install it the official way.** The loader
|
|
200
218
|
entry name, bundle registration id, and host plugin name are all
|
|
201
|
-
`@karoc/dsh-proxy` (matching the npm package name).
|
|
202
|
-
|
|
203
|
-
`
|
|
219
|
+
`@karoc/dsh-proxy` (matching the npm package name). A hand-written `link:`
|
|
220
|
+
dependency only counts once the package manager has materialized it under the
|
|
221
|
+
profile's `node_modules` and the profile lists it in `dsh.profile.bundles` —
|
|
222
|
+
install via `dsh plugin --profile web add @karoc/dsh-proxy` (npm) or
|
|
204
223
|
`dsh plugin --profile web add link:/path/to/dsh-proxy` (source), then restart
|
|
205
224
|
`dsh web`.
|
|
206
225
|
- The desktop shell (`dsh-desktop`) keeps its own proxy and tray settings
|
package/README.zh.md
CHANGED
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
|
|
17
17
|
## 它新增了什么
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
一个新的设置项 **「思磨力代理 / Smoothly Proxy」**(导航顺序 25),排在内置 **Models** 页以及(若装了该插件)外部 **Model reasoning** 页之后,包含:
|
|
20
20
|
|
|
21
|
-
- **上游代理卡片**:启用开关、协议选择(HTTP / HTTPS / SOCKS5
|
|
21
|
+
- **上游代理卡片**:启用开关、协议选择(HTTP / HTTPS / SOCKS5)、主机、端口、可选用户名/密码,以及**测试连接**按钮(SOCKS5 上游走 SOCKS5 握手、HTTP 上游走 `CONNECT` 探测;HTTPS 上游只验证 TCP 可达——不校验其 TLS 握手);
|
|
22
22
|
- **模型提供方**列表——从你的 dsh `settings.yaml` 读取的主机(`llm-deepseek.baseURL`、`llm-pi-ai.providers.<n>.baseURL`、任意 `llm-*` 命名空间),有友好显示名时以显示名标注;
|
|
23
23
|
- **其它已观测主机**列表——代理在流量中见过的主机(含 `registry.npmjs.org` 等安装/更新流量),持久化进 `proxy.json` 以跨重启保留;
|
|
24
24
|
- **搜索框**——输入时按主机 / 名称过滤上面两个列表。
|
|
@@ -93,8 +93,8 @@ git 安装会运行包的 `prepare` 脚本构建 bundle。pnpm ≥ 10 需要先
|
|
|
93
93
|
用 pnpm update 升到最新版(或重 `add` 以拉取更新的 git ref):
|
|
94
94
|
|
|
95
95
|
```sh
|
|
96
|
-
dsh plugin --profile web update dsh-proxy
|
|
97
|
-
# 或,若依赖规格被 pin 住:dsh plugin --profile web add dsh-proxy
|
|
96
|
+
dsh plugin --profile web update @karoc/dsh-proxy
|
|
97
|
+
# 或,若依赖规格被 pin 住:dsh plugin --profile web add @karoc/dsh-proxy
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
然后**重启 `dsh web`** 以加载新客户端 bundle。
|
|
@@ -102,7 +102,7 @@ dsh plugin --profile web update dsh-proxy
|
|
|
102
102
|
### 卸载
|
|
103
103
|
|
|
104
104
|
```sh
|
|
105
|
-
dsh plugin --profile web remove dsh-proxy
|
|
105
|
+
dsh plugin --profile web remove @karoc/dsh-proxy
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
同时从 `web` profile 移除依赖与 bundle 层。重启 `dsh web` 后该设置项消失。
|
|
@@ -120,14 +120,15 @@ src/client/index.ts # client apply:注册 settings.section(id dsh-proxy)
|
|
|
120
120
|
src/client/ProxySection.tsx # 设置页(上游卡片 + 主机列表)
|
|
121
121
|
src/client/styles.ts # design-token 样式(--dsw-alias-*)+ 注入
|
|
122
122
|
src/client/locales.ts # en/zh 文案
|
|
123
|
-
scripts
|
|
123
|
+
scripts/*.spec.mjs # 行为测试:proxy-core.ts(13 场景)+ host route / client
|
|
124
|
+
# boot / cordis mount,全程无外部网络
|
|
124
125
|
```
|
|
125
126
|
|
|
126
127
|
### /proxy/api 路由
|
|
127
128
|
|
|
128
129
|
host 半区用同源 HTTP 路由为设置页供数(内置 `/api` 前缀被 gateway 占用,故用 `/proxy/api`):
|
|
129
130
|
|
|
130
|
-
- `GET /proxy/api` → `{ upstream, proxiedHosts, knownHosts, hosts, providers, port }`
|
|
131
|
+
- `GET /proxy/api` → `{ ok, upstream, proxiedHosts, knownHosts, hosts, providers, port }`
|
|
131
132
|
- `POST /proxy/api` `{ op: 'save', upstream, proxiedHosts }` → 清洗后持久化的配置
|
|
132
133
|
- `POST /proxy/api` `{ op: 'test', upstream }` → `{ ok, detail }`
|
|
133
134
|
- `POST /proxy/api` `{ op: 'persist' }` → 把观测主机并入 `knownHosts`
|
|
@@ -137,7 +138,9 @@ host 半区用同源 HTTP 路由为设置页供数(内置 `/api` 前缀被 gat
|
|
|
137
138
|
```sh
|
|
138
139
|
pnpm install
|
|
139
140
|
pnpm bundle # 产出 lib/index.js + lib/client.js
|
|
140
|
-
pnpm
|
|
141
|
+
pnpm typecheck # tsc --noEmit
|
|
142
|
+
pnpm test # node --test:proxy-core(13 场景)+ host-route /
|
|
143
|
+
# client-boot / cordis-mount,无外部网络
|
|
141
144
|
pnpm release:check # 发布门禁:文档/changelog/tag/工作区/构建/registry 全过
|
|
142
145
|
pnpm publish # 跑门禁(prepack/prepublishOnly),随后 postpublish 验证线上发布
|
|
143
146
|
```
|
|
@@ -148,8 +151,10 @@ bundle 把平台包(`react`、`@deepseek-ai/cordis`、`@deepseek-ai/dsh-client
|
|
|
148
151
|
|
|
149
152
|
- **代理是进程级出站点,不是模型逐请求读的开关。** 它通过把进程的 `HTTP(S)_PROXY` 指向自身来实现。本插件 host `apply()` 之后 dsh 发起的请求(任何子进程、以及 global dispatcher 仍是惰性的 undici fetch)会走代理。若某个 dsh 内部 fetch 在插件加载前就已实体化了 dispatcher,可能不会走它——文档化的解法是重启 dsh(桌面壳通过 spawn dsh 前设环境变量来施加同样的边界)。
|
|
150
153
|
- `npm`/`pnpm` 安装/更新流量与其它一样走代理;改动**与安装/更新相关的主机**会在下次安装/更新时生效(已在进行的操作保留其环境)。
|
|
151
|
-
-
|
|
152
|
-
-
|
|
154
|
+
- **SOCKS5 上游只承载 HTTPS 目标。** SOCKS5 没有 absolute-URI 的 HTTP 模式,因此选中的纯 `http://` 主机会退回直连(设置页也写明了这一点)。
|
|
155
|
+
- **设置页导航图标由壳分配,插件无法自定义。** 内置 `ui-settings-general` 的 `SettingsRoot.tsx` `navIcon(id)` 只映射已知 id,其它 id(包括本节的 `dsh-proxy`)一律齿轮。`settings.section` 注册没有 icon 字段,外部插件不 patch 壳就改不了。等 DSH 开放每节图标后,本节建议用 `dsh-client-ui-primitives` 的 `IconGlobeOutlineRegular`。
|
|
156
|
+
- **本节自 v0.1.4 起要求 dsh ≥ 0.1.7(0.1.2–0.1.6 请用 v0.1.3)。** DSH 0.1.7 改了图标导出名(`IconX14` → `IconXRegular`,尺寸后缀并入 artwork 默认值、名字改为承载笔画权重;上游 commit `4937343a5e`),本节现在导入 `*Regular` 变体。该下限已声明为对 `@deepseek-ai/dsh-client-ui-settings` 的**可选 peer 依赖**,由 dsh ≥ 0.1.7 的兼容门禁按运行时版本判定(不匹配则拒绝加载该 bundle,并给出 `dsh plugin allow-version` 的具体解法)。0.1.7 之前的 dsh 没有这道门禁,仍会加载本插件并渲染出坏掉的分区——那些运行时请用 v0.1.3。
|
|
157
|
+
- **需以官方方式安装才生效。** loader entry 名、bundle 注册 id、host 插件名三者均为 `@karoc/dsh-proxy`(与 npm 包名一致)。手写 `link:` 依赖只有在包管理器把它落到 profile 的 `node_modules` 下、且 profile 的 `dsh.profile.bundles` 列出它之后才算数——请用 `dsh plugin --profile web add @karoc/dsh-proxy`(npm)或 `dsh plugin --profile web add link:/path/to/dsh-proxy`(源码)安装,然后重启 `dsh web`。
|
|
153
158
|
- 桌面壳(`dsh-desktop`)保留自己的代理与托盘设置窗口——本插件是独立抽取,不是替代品。两者可共存(例如把 `dsh-proxy` 装进壳的 profile,同时获得 dsh 内设置页)。
|
|
154
159
|
|
|
155
160
|
## License
|
package/cordis.patch.yml
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Bundle layer applied when a profile lists this package. The row names the
|
|
2
2
|
# package so the host loader resolves the node half and client-modules serves
|
|
3
|
-
# exports["./client"] at /plugins/dsh-proxy/client.js
|
|
3
|
+
# exports["./client"] at /plugins/@karoc/dsh-proxy/client.js (the browser row
|
|
4
|
+
# id is the package name, not the runtime plugin id). The host half starts the
|
|
4
5
|
# loopback forward proxy and registers /proxy/api; the client half registers
|
|
5
6
|
# the settings.section settings page. The loader entry `name` must equal the
|
|
6
7
|
# npm package name (@karoc/dsh-proxy) — client-modules resolves it as a
|
package/lib/client.js
CHANGED
|
@@ -76,7 +76,7 @@ window.__ModuleLoader__.load({
|
|
|
76
76
|
onClick: () => {
|
|
77
77
|
setOpen((v) => !v);
|
|
78
78
|
},
|
|
79
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: matched?.label ?? t("protocolHttp") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
79
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: matched?.label ?? t("protocolHttp") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {})]
|
|
80
80
|
})
|
|
81
81
|
});
|
|
82
82
|
}
|
|
@@ -370,7 +370,7 @@ window.__ModuleLoader__.load({
|
|
|
370
370
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("proxiedHostsHint") }),
|
|
371
371
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
372
372
|
className: "dsh-proxy-search",
|
|
373
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
373
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconGlobeOutlineRegular, {}),
|
|
374
374
|
placeholder: t("searchPlaceholder"),
|
|
375
375
|
value: query,
|
|
376
376
|
onChange: (e) => {
|
|
@@ -427,7 +427,7 @@ window.__ModuleLoader__.load({
|
|
|
427
427
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
428
428
|
variant: "outline",
|
|
429
429
|
size: "md",
|
|
430
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
430
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutlineRegular, {}),
|
|
431
431
|
disabled: testing || !enabled,
|
|
432
432
|
onClick: () => {
|
|
433
433
|
test();
|
package/lib/index.js
CHANGED
|
@@ -34,7 +34,7 @@ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
34
34
|
* * the proxy itself uses raw net/http (never undici's env-proxy), so it can
|
|
35
35
|
* never route its own outbound connections back through itself.
|
|
36
36
|
*/
|
|
37
|
-
const LOOPBACK = /^(127
|
|
37
|
+
const LOOPBACK = /^(127\.\d{1,3}\.\d{1,3}\.\d{1,3}|localhost|::1|0\.0\.0\.0)$/i;
|
|
38
38
|
/** Upstream proxy protocol, defaulting to http (legacy configs have no field). */
|
|
39
39
|
function upstreamProtocol(cfg) {
|
|
40
40
|
return String(cfg?.upstream?.protocol || "http").toLowerCase();
|
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@karoc/dsh-proxy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Smoothly Proxy (思磨力代理插件): external DeepSeek Harness plugin — a model-provider forward proxy with per-host routing and a Settings page.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
|
|
8
|
+
".": {
|
|
9
|
+
"default": "./lib/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./client": {
|
|
12
|
+
"default": "./lib/client.js"
|
|
13
|
+
},
|
|
10
14
|
"./package.json": "./package.json"
|
|
11
15
|
},
|
|
12
16
|
"files": [
|
|
@@ -20,11 +24,12 @@
|
|
|
20
24
|
"LICENSE"
|
|
21
25
|
],
|
|
22
26
|
"dsh": {
|
|
23
|
-
"bundle": {
|
|
27
|
+
"bundle": {
|
|
28
|
+
"patch": "./cordis.patch.yml"
|
|
29
|
+
},
|
|
24
30
|
"client": {
|
|
25
31
|
"inject": [
|
|
26
32
|
"@deepseek-ai/dsh-client-locale",
|
|
27
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
28
33
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
29
34
|
"@deepseek-ai/dsh-client-ui-slots",
|
|
30
35
|
"@deepseek-ai/dsh-client-ui-primitives"
|
|
@@ -36,21 +41,43 @@
|
|
|
36
41
|
"bundle": "tsdown --config ./tsdown.config.ts",
|
|
37
42
|
"prepare": "tsdown --config ./tsdown.config.ts",
|
|
38
43
|
"typecheck": "tsc --noEmit",
|
|
39
|
-
"test": "node --test scripts/proxy-core.spec.mjs scripts/host-route.spec.mjs scripts/client-boot.spec.mjs scripts/cordis-mount.spec.mjs",
|
|
44
|
+
"test": "node --test scripts/proxy-core.spec.mjs scripts/host-route.spec.mjs scripts/client-boot.spec.mjs scripts/cordis-mount.spec.mjs && node scripts/check-guarantees.mjs && node scripts/test-negative-controls.mjs",
|
|
40
45
|
"accept": "node scripts/accept-gui.mjs && node scripts/verify-tooltip.mjs",
|
|
41
46
|
"release:check": "node scripts/release-check.mjs",
|
|
42
47
|
"prepack": "node scripts/release-check.mjs",
|
|
43
48
|
"prepublishOnly": "node scripts/release-check.mjs && tsdown --config ./tsdown.config.ts",
|
|
44
|
-
"postpublish": "node scripts/post-publish-check.mjs"
|
|
49
|
+
"postpublish": "node scripts/post-publish-check.mjs",
|
|
50
|
+
"verify:guarantees": "node scripts/check-guarantees.mjs",
|
|
51
|
+
"test:controls": "node scripts/test-negative-controls.mjs",
|
|
52
|
+
"verify:all": "node scripts/verify-all.mjs",
|
|
53
|
+
"verify:fresh": "node scripts/verify-all.mjs --check-fresh"
|
|
45
54
|
},
|
|
46
|
-
"engines": {
|
|
47
|
-
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=18"
|
|
57
|
+
},
|
|
58
|
+
"keywords": [
|
|
59
|
+
"deepseek-harness",
|
|
60
|
+
"dsh",
|
|
61
|
+
"plugin",
|
|
62
|
+
"proxy",
|
|
63
|
+
"model-provider",
|
|
64
|
+
"settings",
|
|
65
|
+
"smoothly-proxy",
|
|
66
|
+
"sp"
|
|
67
|
+
],
|
|
48
68
|
"author": "karoc",
|
|
49
69
|
"license": "MIT",
|
|
50
|
-
"repository": {
|
|
51
|
-
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": "git+https://github.com/karoc/dsh-proxy.git"
|
|
73
|
+
},
|
|
74
|
+
"bugs": {
|
|
75
|
+
"url": "https://github.com/karoc/dsh-proxy/issues"
|
|
76
|
+
},
|
|
52
77
|
"homepage": "https://github.com/karoc/dsh-proxy",
|
|
53
|
-
"publishConfig": {
|
|
78
|
+
"publishConfig": {
|
|
79
|
+
"access": "public"
|
|
80
|
+
},
|
|
54
81
|
"devDependencies": {
|
|
55
82
|
"@types/node": "^22.0.0",
|
|
56
83
|
"@types/react": "~18.3.1",
|
|
@@ -58,5 +85,13 @@
|
|
|
58
85
|
"tsdown": "^0.22.0",
|
|
59
86
|
"typescript": "^5.6.0"
|
|
60
87
|
},
|
|
61
|
-
"peerDependencies": {
|
|
88
|
+
"peerDependencies": {
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.1",
|
|
90
|
+
"react": "^18.2.0"
|
|
91
|
+
},
|
|
92
|
+
"peerDependenciesMeta": {
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-settings": {
|
|
94
|
+
"optional": true
|
|
95
|
+
}
|
|
96
|
+
}
|
|
62
97
|
}
|