dsh-provider-proxy 0.2.0 → 0.3.0
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 +119 -116
- package/lib/client.js +28 -5
- package/lib/client.js.map +2 -2
- package/lib/index.js +26 -11
- package/lib/index.js.map +2 -2
- package/package.json +88 -72
package/README.md
CHANGED
|
@@ -1,116 +1,119 @@
|
|
|
1
|
-
# dsh-provider-proxy
|
|
2
|
-
|
|
3
|
-
给 **DeepSeek Harness**(`0.2.0-rc.1` 及以上)用的插件:在 **设置** 里为**每个 provider 单独配置**「这个 provider 要不要走代理」,填写代理类型 + IP/端口。只有被你打开开关的 provider 走代理,其余 provider 和 DSH 的其它流量保持原来的直连路径。
|
|
4
|
-
|
|
5
|
-
支持官方桌面版(DSH Desktop)与 `dsh web`。
|
|
6
|
-
|
|
7
|
-
## 安装
|
|
8
|
-
|
|
9
|
-
先确保已构建过产物(`lib/index.js`、`lib/client.js`):
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
npm install
|
|
13
|
-
npm run build
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
桌面版(**必须先完整打开一次桌面版以初始化 profile,然后完全退出**,否则安装命令会拒绝执行):
|
|
17
|
-
|
|
18
|
-
```sh
|
|
19
|
-
dsh plugin --profile desktop add
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Web:
|
|
23
|
-
|
|
24
|
-
```sh
|
|
25
|
-
dsh plugin --profile web add
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
安装后重启对应应用。设置项写在 `$DSH_HOME/profiles/<profile>/cordis.patch.yml`。
|
|
29
|
-
|
|
30
|
-
## 使用
|
|
31
|
-
|
|
32
|
-
打开 **设置**,左侧导航里会出现一项 **Provider 代理**(英文界面为 *Provider Proxy*)。
|
|
33
|
-
页面里每个 provider 一张卡片,各自独立配置:
|
|
34
|
-
|
|
35
|
-
| 字段 | 说明 |
|
|
36
|
-
| --- | --- |
|
|
37
|
-
| 开关 | 该 provider 是否走代理 |
|
|
38
|
-
| 类型 | `HTTP` / `HTTPS
|
|
39
|
-
| IP / 主机 | 只填主机名或 IP,不要带 `http://` 或路径 |
|
|
40
|
-
| 端口 | 1–65535 的整数 |
|
|
41
|
-
| 用户名 |
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
>
|
|
51
|
-
>
|
|
52
|
-
>
|
|
53
|
-
>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- `llm-
|
|
61
|
-
- `
|
|
62
|
-
- `
|
|
63
|
-
- `
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
npm run
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
1
|
+
# dsh-provider-proxy [](https://dsh.market/)
|
|
2
|
+
|
|
3
|
+
给 **DeepSeek Harness**(`0.2.0-rc.1` 及以上)用的插件:在 **设置** 里为**每个 provider 单独配置**「这个 provider 要不要走代理」,填写代理类型 + IP/端口。只有被你打开开关的 provider 走代理,其余 provider 和 DSH 的其它流量保持原来的直连路径。
|
|
4
|
+
|
|
5
|
+
支持官方桌面版(DSH Desktop)与 `dsh web`。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
先确保已构建过产物(`lib/index.js`、`lib/client.js`):
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install
|
|
13
|
+
npm run build
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
桌面版(**必须先完整打开一次桌面版以初始化 profile,然后完全退出**,否则安装命令会拒绝执行):
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
dsh plugin --profile desktop add dsh-provider-proxy
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Web:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
dsh plugin --profile web add dsh-provider-proxy
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
安装后重启对应应用。设置项写在 `$DSH_HOME/profiles/<profile>/cordis.patch.yml`。
|
|
29
|
+
|
|
30
|
+
## 使用
|
|
31
|
+
|
|
32
|
+
打开 **设置**,左侧导航里会出现一项 **Provider 代理**(英文界面为 *Provider Proxy*)。
|
|
33
|
+
页面里每个 provider 一张卡片,各自独立配置:
|
|
34
|
+
|
|
35
|
+
| 字段 | 说明 |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| 开关 | 该 provider 是否走代理 |
|
|
38
|
+
| 类型 | `HTTP` / `HTTPS` / `SOCKS5` |
|
|
39
|
+
| IP / 主机 | 只填主机名或 IP,不要带 `http://` 或路径 |
|
|
40
|
+
| 端口 | 1–65535 的整数 |
|
|
41
|
+
| 用户名 | 可选(SOCKS5 用,需与密码同时填写) |
|
|
42
|
+
| 密码 | 可选(SOCKS5 用)。作为 SOCKS5 认证口令发给代理 |
|
|
43
|
+
|
|
44
|
+
列表只包含**已激活**的 provider(`llm.listProviders()` 能列出的那些)。仅在配置里声明、
|
|
45
|
+
但没有实际注册的可配置 provider 不显示——它的请求根本不会被发出去。
|
|
46
|
+
已经在 `providers` 里配过代理的条目即使暂时不激活也仍然保留,避免已保存的设置悄悄消失。
|
|
47
|
+
|
|
48
|
+
保存立即对新请求生效,不需要重启;正在进行中的流会继续用它启动时的那条连接。
|
|
49
|
+
|
|
50
|
+
> **为什么是独立设置页,而不是内嵌在 Models 的 provider 卡片里?**
|
|
51
|
+
> 本插件最早按卡片内嵌(`settings.models.provider-card`)实现,但那个槽位是 keyed 的、
|
|
52
|
+
> 按 provider 命名空间派发,第三方注册在 0.2.0-rc.1 上始终匹配不上——不报错、不发请求、
|
|
53
|
+
> 界面上什么都不出现。独立分区(`settings.section`)是同一 profile 下
|
|
54
|
+
> `dsh-llm-retry-settings` 已被验证可用的机制。
|
|
55
|
+
|
|
56
|
+
## 它是怎么工作的
|
|
57
|
+
|
|
58
|
+
0.2.0 没有「给单个 provider 注入 transport」的官方口子,这是核对过源码的结论:
|
|
59
|
+
|
|
60
|
+
- `llm-deepseek` 直接调用全局 `fetch`,请求参数里没有 `dispatcher`;
|
|
61
|
+
- `llm-pi-ai` 走 pi-ai SDK 自己的 HTTP,DSH 无法配置;
|
|
62
|
+
- `LlmCallControls` 只有 `reasoningEffort` / `temperature` / `maxTokens` / `stop`;
|
|
63
|
+
- `llm/stream` 拦截的是**已解码的** `StreamChunk`,发生在 HTTP 之后;
|
|
64
|
+
- `ctx.web` 只服务 `web_search` / `web_fetch`,与 provider 流量无关;
|
|
65
|
+
- 官方的 `@deepseek-ai/dsh-http-proxy` 是**库**不是插件:`installGlobalProxy` 是模块私有函数,没有 service、没有 Config、只有从环境变量解析出的一份进程级策略。
|
|
66
|
+
|
|
67
|
+
所以请求在唯一还能拿到线索的地方被路由:`llm/stream` waterfall 的 `options.provider`。用一个 `AsyncLocalStorage` 把选中的 dispatcher 带到流上,再由一层很薄的 `globalThis.fetch` 包装把它交给 fetch。
|
|
68
|
+
|
|
69
|
+
两个关键点:
|
|
70
|
+
|
|
71
|
+
1. **每个 provider 各自持有一个 dispatcher**(而不是共用一个),所以即使两个 provider 指向同一个上游主机,也不可能互相串用对方的代理。
|
|
72
|
+
2. **流的惰性消费必须被处理**:adapter 的 HTTP 调用通常发生在后续的 `next()` 里,那时 `als.run()` 早已返回。所以每次迭代器的 `next/return/throw` 都会被重新包进作用域里 —— 这正是旧版实现在这里踩过的坑,仓库里有对应的回归测试。
|
|
73
|
+
|
|
74
|
+
代价是这一个全局 `fetch` 包装:作用域之外的行为与原生完全一致,作用域之内若调用方已经自带 `dispatcher` 也不会被覆盖。
|
|
75
|
+
|
|
76
|
+
## 已知限制
|
|
77
|
+
|
|
78
|
+
- **SOCKS5 由 `undici` 内置的 `Socks5ProxyAgent` 实现**(RFC 1928 / RFC 1929),API 稳定性标记为 *Experimental*;`undici` 若在未来移除,需要同步调整。
|
|
79
|
+
- **SOCKS5 的用户名必须与密码同时填写。** 只填用户名会被拒绝并给出提示,而不是静默降级为无认证——否则在强制认证的代理端,报错会指向代理而真正原因是设置缺项。
|
|
80
|
+
- **SOCKS5 不支持 `socks://` 别名与 SOCKS5 over TLS**(`proxyTls`)。
|
|
81
|
+
- **上游若绕过 `globalThis.fetch` 自行建连,则不受影响。** `llm-deepseek` 确认是调用时解析全局 `fetch`;`llm-pi-ai` 走外部 SDK,抓取 `fetch` 的时机未能在源码层面确证。
|
|
82
|
+
- **不支持 PAC**,也不读取系统代理设置。
|
|
83
|
+
- **不改写 `baseURL`** —— 反向代理/中转请直接在 provider 上配置。
|
|
84
|
+
- **代理不可达时**请求照常失败,DSH 既有的重试与错误码语义不变。
|
|
85
|
+
- **SOCKS5 代理密码以明文随设置写入 `cordis.patch.yml`。** 它只会作为选项传给 `Socks5ProxyAgent`,不会出现在日志或诊断报告里的代理 URL 中。
|
|
86
|
+
- **HTTP/HTTPS 代理仍只支持用户名**,密码只对 SOCKS5 生效。
|
|
87
|
+
|
|
88
|
+
## 如何验证代理确实生效
|
|
89
|
+
|
|
90
|
+
插件本身不显示出口 IP。可靠的判断方式是在代理端看日志,或临时把端口改成
|
|
91
|
+
一个没人监听的端口——如果请求失败并报 `ECONNREFUSED 127.0.0.1:<该端口>`,
|
|
92
|
+
就说明请求确实是被代理承载的(直连时报错会指向目标站点)。
|
|
93
|
+
|
|
94
|
+
仓库里的 `tests/proxy-routing-proof.test.ts` 就是用这个思路做的:起一个会记录
|
|
95
|
+
连接的假代理,断言「启用的路由收到 1 次连接、未配置的 provider 收到 0 次」。
|
|
96
|
+
|
|
97
|
+
## 开发
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
npm run build # 构建 lib/index.js 与 lib/client.js
|
|
101
|
+
npm test # 82 个用例,跑的是构建产物
|
|
102
|
+
npm run typecheck # 类型检查(仅覆盖 src/)
|
|
103
|
+
npm run verify # 上面三件事,按顺序
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`lib/` 是构建产物,不入库;包上的 `prepare` 脚本会在 `npm publish` 以及从 git
|
|
107
|
+
地址安装时自动重建。直接 `dsh plugin add <克隆目录>` 前请先执行
|
|
108
|
+
`npm install && npm run build`。
|
|
109
|
+
|
|
110
|
+
浏览器半必须输出 client module system 的 lazy-CJS factory 格式(脚本本身只注册工厂,所有副作用都在工厂闭包里执行),`scripts/build.mjs` 负责这件事,格式与 DSH 自带插件一致。
|
|
111
|
+
|
|
112
|
+
## 发布
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
npm run verify # 先确认全绿
|
|
116
|
+
npm version patch # 0.2.0 -> 0.2.1
|
|
117
|
+
npm publish
|
|
118
|
+
git push --follow-tags
|
|
119
|
+
```
|
package/lib/client.js
CHANGED
|
@@ -180,7 +180,7 @@ function view(route) {
|
|
|
180
180
|
host: route?.host ?? "",
|
|
181
181
|
port: route?.port ?? 0,
|
|
182
182
|
username: route?.username ?? "",
|
|
183
|
-
|
|
183
|
+
password: route?.password ?? ""
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
186
|
var diagnostics = [];
|
|
@@ -412,7 +412,7 @@ function renderPage(ctx) {
|
|
|
412
412
|
(protocol) => h("option", { key: protocol, value: protocol }, protocol.toUpperCase())
|
|
413
413
|
)
|
|
414
414
|
),
|
|
415
|
-
route.protocol === "socks5" ? t.
|
|
415
|
+
route.protocol === "socks5" ? t.socks5Hint : void 0
|
|
416
416
|
),
|
|
417
417
|
field(
|
|
418
418
|
t.host,
|
|
@@ -453,7 +453,26 @@ function renderPage(ctx) {
|
|
|
453
453
|
value: route.username,
|
|
454
454
|
onChange: (event) => bind(row.id, "username")(event.target.value)
|
|
455
455
|
})
|
|
456
|
-
)
|
|
456
|
+
),
|
|
457
|
+
// Only SOCKS5 authenticates in-band, so only SOCKS5 shows this field.
|
|
458
|
+
//
|
|
459
|
+
// The password is stored on the route and therefore written into the
|
|
460
|
+
// settings file with the rest of the config. It is handed to
|
|
461
|
+
// Socks5ProxyAgent as an option, never embedded in the proxy URL that
|
|
462
|
+
// the diagnostics surface.
|
|
463
|
+
route.protocol === "socks5" ? field(
|
|
464
|
+
t.password,
|
|
465
|
+
h("input", {
|
|
466
|
+
className: import_client.default.input,
|
|
467
|
+
style: S.input,
|
|
468
|
+
disabled,
|
|
469
|
+
type: "password",
|
|
470
|
+
autocomplete: "off",
|
|
471
|
+
value: route.password,
|
|
472
|
+
onChange: (event) => bind(row.id, "password")(event.target.value)
|
|
473
|
+
}),
|
|
474
|
+
t.passwordHint
|
|
475
|
+
) : void 0
|
|
457
476
|
);
|
|
458
477
|
});
|
|
459
478
|
return h(
|
|
@@ -492,8 +511,10 @@ var EN = {
|
|
|
492
511
|
host: "IP / host",
|
|
493
512
|
port: "Port",
|
|
494
513
|
username: "Username",
|
|
514
|
+
password: "Password",
|
|
495
515
|
hostHint: "Host or IP only, without scheme or path.",
|
|
496
|
-
|
|
516
|
+
passwordHint: "Sent to the SOCKS5 proxy for authentication; stored with this setting.",
|
|
517
|
+
socks5Hint: "SOCKS5 tunnels the connection; the proxy resolves the target host name.",
|
|
497
518
|
on: "proxied",
|
|
498
519
|
live: "active",
|
|
499
520
|
off: "direct",
|
|
@@ -508,8 +529,10 @@ var ZH = {
|
|
|
508
529
|
host: "IP / \u4E3B\u673A",
|
|
509
530
|
port: "\u7AEF\u53E3",
|
|
510
531
|
username: "\u7528\u6237\u540D",
|
|
532
|
+
password: "\u5BC6\u7801",
|
|
511
533
|
hostHint: "\u53EA\u586B\u4E3B\u673A\u540D\u6216 IP\uFF0C\u4E0D\u8981\u5E26\u534F\u8BAE\u524D\u7F00\u6216\u8DEF\u5F84\u3002",
|
|
512
|
-
|
|
534
|
+
passwordHint: "\u4EC5\u4F5C\u4E3A SOCKS5 \u8BA4\u8BC1\u53E3\u4EE4\u53D1\u9001\u7ED9\u4EE3\u7406\uFF1B\u968F\u8BE5\u8BBE\u7F6E\u4E00\u8D77\u4FDD\u5B58\u3002",
|
|
535
|
+
socks5Hint: "SOCKS5 \u4F1A\u5EFA\u7ACB\u96A7\u9053\uFF0C\u76EE\u6807\u57DF\u540D\u7531\u4EE3\u7406\u7AEF\u89E3\u6790\u3002",
|
|
513
536
|
on: "\u8D70\u4EE3\u7406",
|
|
514
537
|
live: "\u542F\u7528\u4E2D",
|
|
515
538
|
off: "\u76F4\u8FDE",
|
package/lib/client.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/client.css", "../src/client.ts"],
|
|
4
|
-
"sourcesContent": ["\nvar __dshMap = {\"root\":\"1b9ac577_root\",\"lead\":\"4a359f22_lead\",\"empty\":\"ffd21b3b_empty\",\"card\":\"16611c9b_card\",\"cardActive\":\"2d004466_cardActive\",\"cardHead\":\"640fee25_cardHead\",\"cardTitles\":\"f6fe8b3f_cardTitles\",\"name\":\"f9d2db09_name\",\"id\":\"c90ce2e0_id\",\"pillOn\":\"75541864_pillOn\",\"pillLive\":\"3097d90f_pillLive\",\"pillOff\":\"a58f86be_pillOff\",\"toggle\":\"e5b81c4b_toggle\",\"field\":\"f4d34839_field\",\"label\":\"a4061c91_label\",\"hint\":\"13bd3ec9_hint\",\"input\":\"851d7bd9_input\",\"diag\":\"f92a10d9_diag\",\"diagSummary\":\"5b66e072_diagSummary\",\"diagList\":\"dc8d3a6f_diagList\"};\nvar __dshStyles = (globalThis.__dshPluginStyles || (globalThis.__dshPluginStyles = new Set()));\nif (!__dshStyles.has(\"dsh-provider-proxy/client.css\")) {\n __dshStyles.add(\"dsh-provider-proxy/client.css\");\n var __dshStyle = document.createElement('style');\n __dshStyle.setAttribute('data-plugin-css', \"dsh-provider-proxy/client.css\");\n __dshStyle.textContent = \"/* dsh-provider-proxy \u2014 provider proxy settings page.\\n Tokens only: no literal colours, matching the shared --dsw-* system. */\\n\\n.1b9ac577_root {\\n display: flex;\\n flex-direction: column;\\n gap: 12px;\\n max-width: 640px;\\n}\\n\\n.4a359f22_lead {\\n margin: 0 0 4px;\\n font-size: 12px;\\n line-height: 1.6;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.ffd21b3b_empty {\\n margin: 0;\\n padding: 16px;\\n border: 1px dashed var(--dsw-alias-border-l1);\\n border-radius: 8px;\\n font-size: 12px;\\n text-align: center;\\n color: var(--dsw-alias-state-idle-primary);\\n}\\n\\n/* ---- provider card ---- */\\n\\n.16611c9b_card,\\n.2d004466_cardActive {\\n display: flex;\\n flex-direction: column;\\n gap: 10px;\\n padding: 12px 14px;\\n border: 1px solid var(--dsw-alias-border-l1);\\n border-radius: 10px;\\n background: var(--dsw-alias-bg-layer-1);\\n}\\n\\n.2d004466_cardActive {\\n border-color: var(--dsw-alias-state-success-primary);\\n background: var(--dsw-alias-bg-layer-2);\\n}\\n\\n.640fee25_cardHead {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n gap: 12px;\\n}\\n\\n.f6fe8b3f_cardTitles {\\n display: flex;\\n align-items: baseline;\\n gap: 8px;\\n min-width: 0;\\n}\\n\\n.f9d2db09_name {\\n overflow: hidden;\\n font-size: 13px;\\n font-weight: 600;\\n white-space: nowrap;\\n text-overflow: ellipsis;\\n color: var(--dsw-alias-label-primary);\\n}\\n\\n.c90ce2e0_id {\\n flex: none;\\n padding: 1px 6px;\\n border-radius: 4px;\\n background: var(--dsw-alias-bg-layer-2);\\n font-family: ui-monospace, monospace;\\n font-size: 11px;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n/* ---- status pill ---- */\\n\\n.75541864_pillOn,\\n.3097d90f_pillLive,\\n.a58f86be_pillOff {\\n flex: none;\\n padding: 2px 8px;\\n border-radius: 999px;\\n font-size: 11px;\\n font-weight: 500;\\n white-space: nowrap;\\n}\\n\\n.75541864_pillOn {\\n background: var(--dsw-alias-state-success-primary);\\n color: var(--dsw-alias-bg-base);\\n}\\n\\n.3097d90f_pillLive {\\n border: 1px solid var(--dsw-alias-border-l2);\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.a58f86be_pillOff {\\n color: var(--dsw-alias-state-idle-primary);\\n}\\n\\n/* ---- toggle ---- */\\n\\n.e5b81c4b_toggle {\\n display: flex;\\n align-items: center;\\n gap: 8px;\\n padding-top: 2px;\\n font-size: 12px;\\n color: var(--dsw-alias-label-primary);\\n cursor: pointer;\\n}\\n\\n.e5b81c4b_toggle input {\\n accent-color: var(--dsw-alias-brand-primary);\\n cursor: pointer;\\n}\\n\\n/* ---- fields ---- */\\n\\n.f4d34839_field {\\n display: grid;\\n grid-template-columns: 96px 1fr;\\n align-items: center;\\n gap: 10px;\\n font-size: 12px;\\n}\\n\\n.a4061c91_label {\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.13bd3ec9_hint {\\n grid-column: 2;\\n margin-top: -2px;\\n font-size: 11px;\\n color: var(--dsw-alias-state-warn-primary);\\n}\\n\\n.851d7bd9_input {\\n box-sizing: border-box;\\n width: 100%;\\n min-width: 0;\\n padding: 5px 8px;\\n border: 1px solid var(--dsw-alias-border-l1);\\n border-radius: 6px;\\n outline: none;\\n background: var(--dsw-alias-bg-layer-1);\\n color: var(--dsw-alias-label-primary);\\n font: inherit;\\n font-size: 12px;\\n transition: border-color 120ms ease, background 120ms ease;\\n}\\n\\n.851d7bd9_input:hover:not(:disabled) {\\n border-color: var(--dsw-alias-border-l2);\\n}\\n\\n.851d7bd9_input:focus {\\n border-color: var(--dsw-alias-brand-primary);\\n}\\n\\n.851d7bd9_input:disabled {\\n color: var(--dsw-alias-state-idle-primary);\\n background: var(--dsw-alias-bg-layer-2);\\n cursor: not-allowed;\\n}\\n\\n/* ---- diagnostics ---- */\\n\\n.f92a10d9_diag {\\n margin-top: 2px;\\n padding: 8px 10px;\\n border: 1px solid var(--dsw-alias-border-l1);\\n border-radius: 8px;\\n font-size: 11px;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.5b66e072_diagSummary {\\n cursor: pointer;\\n color: var(--dsw-alias-state-warn-primary);\\n}\\n\\n.dc8d3a6f_diagList {\\n margin: 6px 0 0;\\n padding-left: 18px;\\n font-family: ui-monospace, monospace;\\n word-break: break-all;\\n}\\n\";\n document.head.appendChild(__dshStyle);\n}\nmodule.exports = __dshMap;\nmodule.exports.default = __dshMap;\nmodule.exports.__esModule = true;\n", "/**\n * dsh-provider-proxy \u2014 browser half.\n *\n * Contributes ONE settings page (a `settings.section` list entry) that lists\n * every known provider with its proxy switch, type, host, port and username.\n *\n * This replaces an earlier attempt to render into each provider card on the\n * Models page (`settings.models.provider-card`). That seat is keyed and\n * dispatched per provider namespace, and a third-party registration never\n * matched it on this build: no error, no request, simply no output. A\n * `settings.section` entry is a plain list contribution with an `id`, which is\n * the shape the shipped `dsh-llm-retry-settings` plugin uses successfully in\n * this same desktop profile.\n *\n * The whole bundle runs inside the client module system's lazy-CJS factory:\n * executing the script only REGISTERS the factory, and every side effect\n * (including the CSS injection) happens at materialization.\n */\n\n// The CSS-Modules build turns this sheet into a hashed class map AND injects it\n// at materialization. The binding is what the component reads; importing it for\n// side effects only would leave `styles` undefined at render time.\nimport styles from './client.css'\n\ntype Protocol = 'http' | 'https' | 'socks5'\n\ntype RouteValue = {\n enabled: boolean\n protocol: Protocol\n host: string\n port: number\n username: string\n passwordRef: string\n}\n\n/** The provider rows we know about, and which of them are actually live. */\ntype ProviderRow = { id: string; name: string; live: boolean }\n\n/**\n * React, resolved from the client module table.\n *\n * React is NOT a Cordis service and is not reachable from `ctx` \u2014 reading it\n * there produced a silently null component. The module table is the only route:\n * the build leaves `react` external, so this compiles to a `require(\"react\")`\n * inside the factory closure, answered from the shell-seeded baseline.\n *\n * Resolved lazily on first render so merely REGISTERING the bundle \u2014 which is\n * all a script evaluation does \u2014 never materializes React.\n */\nlet ReactCache: unknown\n\nfunction react(): any {\n if (ReactCache === undefined) {\n ReactCache = ((): unknown => {\n try {\n return require('react')\n } catch {\n return (globalThis as Record<string, unknown>).React\n }\n })()\n }\n return ReactCache\n}\n\nconst PROTOCOLS: Protocol[] = ['http', 'https', 'socks5']\n\n/** Our own settings namespace; the profile entry id created by the bundle patch. */\nconst NAMESPACE = 'provider-proxy'\n\n/**\n * Cordis services this half needs.\n *\n * ONLY `slots` is declared. That is the complete set this release actually\n * offers on a client fiber: `layout, locale, sessions, slots, theme, timer,\n * uiWorkspace, workspaces`.\n *\n * A declared service that never arrives leaves the fiber PENDING forever, and\n * that is NOT a client-only failure \u2014 it is reported as\n * web boot: 1 entry did not activate\n * dsh-provider-proxy: pending (waiting for service: settingsScope)\n * which fails the whole Desktop boot. `settingsScope` and `configForms` were\n * both guessed and both are absent here, so neither may be declared.\n *\n * Settings are therefore reached through `ctx.get(name)` \u2014 the framework's own\n * non-throwing lookup \u2014 and the page degrades to read-only when it is absent.\n */\nconst PLUGINS = ['slots']\n\nexport const inject = PLUGINS\n\nexport function apply(ctx: any): void {\n // The settings shell declares `settings.section` on its own fiber, so\n // `slots.inject` waits for that declaration and the contribution is removed\n // when the panel is torn down.\n ctx.slots.inject('settings.section', () =>\n ctx.slots.register(\n {\n name: 'settings.section',\n id: NAMESPACE,\n order: 20,\n label: () => (localeOf(ctx) === 'zh' ? 'Provider \u4EE3\u7406' : 'Provider \u4EE3\u7406'),\n },\n () => renderPage(ctx),\n ),\n )\n}\n\n/**\n * Pick the dictionary.\n *\n * Chinese is the default, not English: this plugin is written for a\n * Chinese-speaking operator, and a page that renders in the wrong language is\n * worse than one that never matches the shell's locale.\n *\n * `ctx.locale` is not injected \u2014 declaring a service that this release does not\n * provide left the fiber PENDING and failed the whole Desktop boot \u2014 so the\n * locale is probed with the non-throwing `ctx.get`, then the browser's own\n * language, and only then English.\n */\nfunction localeOf(ctx: any): string {\n try {\n const service = optionalService(ctx, 'locale')\n const snapshot = service?.getSnapshot?.() ?? service?.getLocale?.()\n const id = typeof snapshot?.locale === 'string' ? snapshot.locale : undefined\n if (id !== undefined) return id.toLowerCase().startsWith('zh') ? 'zh' : 'en'\n } catch {\n // fall through to the browser language\n }\n const browser = globalThis.navigator?.language\n if (typeof browser === 'string' && browser.toLowerCase().startsWith('zh')) return 'zh'\n return browser === undefined ? 'zh' : 'en'\n}\n\n/**\n * Look a service up WITHOUT declaring it in `inject`.\n *\n * `ctx.get(name)` is the framework's own optional lookup: it returns undefined\n * instead of throwing, and \u2014 unlike a declared service \u2014 it cannot leave the\n * fiber PENDING. That is what makes an optional integration safe here: this\n * release has no settings service at all, so the page simply shows its fields\n * and reports that saving is unavailable.\n */\nfunction optionalService(ctx: any, ...names: string[]): any {\n for (const name of names) {\n try {\n const found = typeof ctx?.get === 'function' ? ctx.get(name) : undefined\n if (found !== undefined && found !== null) return found\n } catch {\n // try the next spelling\n }\n }\n return undefined\n}\n\n/** The settings form for this plugin's namespace, when one exists. */\nfunction formOf(ctx: any): any {\n const forms = optionalService(ctx, 'configForms', 'settingsScope')\n if (forms === undefined) return undefined\n try {\n if (typeof forms.get === 'function') return forms.get(NAMESPACE)\n // A settingsScope-style service is already bound to one namespace.\n if (typeof forms.getSnapshot === 'function' || typeof forms.bind === 'function') return forms\n } catch {\n return undefined\n }\n return undefined\n}\n\nfunction readConfig(ctx: any): { value: any; revision: number } {\n const form = formOf(ctx)\n if (form === undefined) return { value: {}, revision: 0 }\n try {\n const snapshot = form.getSnapshot?.()\n return {\n value: snapshot?.value ?? snapshot?.user ?? {},\n revision: snapshot?.revision ?? 0,\n }\n } catch {\n return { value: {}, revision: 0 }\n }\n}\n\nasync function writeConfig(ctx: any, ops: readonly unknown[]): Promise<void> {\n const form = formOf(ctx)\n if (typeof form?.mutate !== 'function') {\n throw new Error('dsh-provider-proxy: settings transport unavailable')\n }\n await form.mutate(ops as any[], readConfig(ctx).revision)\n}\n\n/**\n * The provider rows, read from the Host.\n *\n * This release exposes no client-facing LLM service, so the page cannot ask for\n * the directory itself. The Host serves it at this same-origin endpoint, where\n * `ctx.llm.listProviders()` / `listConfigurableProviders()` actually live. The\n * list is therefore automatic \u2014 the user never types a route id.\n *\n * Only ACTIVE routes are shown. A provider this deployment merely *offers* \u2014\n * declared but not registered, so nothing would ever be sent through it \u2014 is\n * not the user's business on this page, and listing it only invites them to\n * configure a proxy for a route that cannot be selected. A provider that is\n * already configured is kept regardless, so a saved setting never silently\n * disappears from view.\n */\nfunction knownProviders(configured: Record<string, RouteValue>, published: ProviderRow[]): ProviderRow[] {\n const rows = new Map<string, ProviderRow>()\n for (const row of published) {\n if (row.live) rows.set(row.id, row)\n }\n for (const [id, route] of Object.entries(configured)) {\n if (rows.has(id)) continue\n rows.set(id, { id, name: id, live: route?.enabled === true })\n }\n return [...rows.values()].sort(byName)\n}\n\n/**\n * Where the Host publishes the live provider catalogue.\n */\nconst CATALOG_PATH = '/dsh-provider-proxy/providers'\n\n/**\n * The setter the lazy catalogue initializer resolves through.\n *\n * It is republished after every render, so the newest one always wins, and a\n * promise that settles after an unmount writes to a harmless no-op.\n */\nlet catalogueSetter: ((rows: ProviderRow[]) => void) | undefined = () => {}\n\n/** Read the Host's provider catalogue. Same-origin, so no token is needed. */\nasync function fetchProviders(): Promise<ProviderRow[]> {\n const response = await globalThis.fetch(CATALOG_PATH, { headers: { accept: 'application/json' } })\n if (!response.ok) throw new Error(`Host answered ${response.status}`)\n const body = await response.json()\n const list = Array.isArray(body?.providers) ? body.providers : []\n return list\n .filter((row: any) => typeof row?.id === 'string' && row.id.length > 0)\n .map((row: any) => ({\n id: row.id,\n name: typeof row.name === 'string' && row.name.length > 0 ? row.name : row.id,\n live: row.live === true,\n }))\n}\n\nconst byName = (a: ProviderRow, b: ProviderRow): number => a.name.localeCompare(b.name)\n\nfunction view(route: Partial<RouteValue> | undefined): RouteValue {\n return {\n enabled: route?.enabled === true,\n protocol: PROTOCOLS.includes(route?.protocol as Protocol) ? (route!.protocol as Protocol) : 'http',\n host: route?.host ?? '',\n port: route?.port ?? 0,\n username: route?.username ?? '',\n passwordRef: route?.passwordRef ?? '',\n }\n}\n\n/** The provider directory, cached module-side. See renderPage. */\nlet directoryCache: ProviderRow[] | undefined\n\n/**\n * Everything the page learned about its own wiring, rendered verbatim.\n *\n * The browser side of a plugin has no other diagnostic channel \u2014 the Host log\n * never sees it \u2014 so a silent failure had to be diagnosed by inference. This\n * panel is what proved that `remote.settings` and `remote.llm` do not exist in\n * this release, and that the catalogue had to come from the Host endpoint.\n *\n * Cleared at the start of every render so the panel shows the CURRENT state\n * rather than an ever-growing log of the session.\n */\nlet diagnostics: string[] = []\n\nfunction note(message: string): void {\n if (!diagnostics.includes(message)) diagnostics.push(message)\n}\n\n/**\n * Layout constants, applied as INLINE styles.\n *\n * The page is rendered into the settings panel, and the CSS-Modules pipeline\n * that feeds the stylesheet has broken twice in ways that were invisible from\n * the source: the class map failed to bind at all, and a shared class prefix\n * silently merged two rules. Both left the page readable but laid out as one\n * unstyled block.\n *\n * Structure is therefore expressed as inline styles, which cannot be lost by\n * the bundle, and the stylesheet is kept for the purely decorative parts. A\n * theme token that is not defined simply resolves to `unset`, so an unknown\n * token costs colour, never layout.\n */\nconst S = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n gap: '12px',\n maxWidth: '720px',\n },\n card: {\n display: 'flex',\n flexDirection: 'column',\n gap: '12px',\n padding: '14px 16px',\n marginBottom: '12px',\n border: '1px solid var(--dsw-alias-border-l1)',\n borderRadius: '10px',\n background: 'var(--dsw-alias-bg-layer-1)',\n },\n cardActive: {\n borderColor: 'var(--dsw-alias-state-success-primary)',\n background: 'var(--dsw-alias-bg-layer-2)',\n },\n head: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '12px',\n },\n titles: { display: 'flex', alignItems: 'baseline', gap: '8px', minWidth: '0' },\n name: {\n fontSize: '14px',\n fontWeight: '600',\n color: 'var(--dsw-alias-label-primary)',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n id: {\n flex: 'none',\n padding: '1px 6px',\n borderRadius: '4px',\n background: 'var(--dsw-alias-bg-layer-2)',\n fontFamily: 'ui-monospace, monospace',\n fontSize: '11px',\n color: 'var(--dsw-alias-label-secondary)',\n },\n pill: {\n flex: 'none',\n padding: '2px 10px',\n borderRadius: '999px',\n fontSize: '11px',\n fontWeight: '500',\n whiteSpace: 'nowrap',\n },\n pillOn: {\n background: 'var(--dsw-alias-state-success-primary)',\n color: 'var(--dsw-alias-bg-base)',\n },\n pillLive: {\n border: '1px solid var(--dsw-alias-border-l2)',\n color: 'var(--dsw-alias-label-secondary)',\n },\n pillOff: { color: 'var(--dsw-alias-state-idle-primary)' },\n toggle: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n fontSize: '12px',\n color: 'var(--dsw-alias-label-primary)',\n },\n field: {\n display: 'grid',\n gridTemplateColumns: '88px 1fr',\n alignItems: 'center',\n gap: '10px',\n fontSize: '12px',\n },\n label: { color: 'var(--dsw-alias-label-secondary)' },\n input: {\n boxSizing: 'border-box',\n width: '100%',\n minWidth: '0',\n padding: '6px 8px',\n border: '1px solid var(--dsw-alias-border-l1)',\n borderRadius: '6px',\n outline: 'none',\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-primary)',\n font: 'inherit',\n fontSize: '12px',\n },\n} as const\n\nfunction renderPage(ctx: any): unknown {\n const React = react()\n if (React === undefined || typeof React.createElement !== 'function') return null\n\n const h = React.createElement\n const t = stringsFor(ctx)\n diagnostics = []\n\n // `useState` is only reached after the React check, so the early return above\n // cannot desync the hooks order.\n let snapshot: { value: any; revision: number }\n try {\n snapshot = readConfig(ctx)\n } catch {\n snapshot = { value: {}, revision: 0 }\n }\n const configured = (snapshot.value?.providers ?? {}) as Record<string, RouteValue>\n note(\n formOf(ctx) === undefined\n ? '\u8BBE\u7F6E\uFF1A\u672A\u627E\u5230 configForms \u670D\u52A1\uFF0C\u53EA\u80FD\u663E\u793A\u3001\u65E0\u6CD5\u4FDD\u5B58'\n : `\u8BBE\u7F6E\uFF1A\u6B63\u5E38\uFF08\u4FEE\u8BA2\u53F7 ${snapshot.revision}\uFF0C${Object.keys(configured).length} \u4E2A provider\uFF09`,\n )\n\n // The provider catalogue comes from the Host over a same-origin endpoint, so\n // it arrives asynchronously. The initial state is a LAZY initializer, so the\n // fetch starts from `useState(() => \u2026)` instead of by calling a setter during\n // render: a render must have no side effects, and doing so also shifted the\n // hook order between passes.\n const [state, setState] = (React.useState ?? ((fn: any) => [fn(), () => {}]))(() => {\n void fetchProviders()\n .then(rows => catalogueSetter?.(rows))\n .catch((error: any) => {\n note(`provider \u5217\u8868\u83B7\u53D6\u5931\u8D25\uFF1A${error?.message ?? error}`)\n catalogueSetter?.([])\n })\n return { rows: undefined as ProviderRow[] | undefined, pending: true }\n })\n // The setter is published right after the hook so the initializer's promise\n // can reach it. It is re-published on every render, so the latest wins.\n catalogueSetter = rows => setState({ rows, pending: false })\n\n const published = state.rows ?? []\n note(\n `provider \u5217\u8868\uFF1A\u6765\u81EA Host \u5171 ${published.length} \u4E2A\uFF08${published.map((r: ProviderRow) => r.id).join('\u3001') || '\u65E0'}\uFF09`,\n )\n // Local draft, layered over the stored config.\n //\n // Without it a checkbox does not change until the panel remounts: the value\n // is read from the settings store, which only updates when the page is\n // rebuilt. The draft makes the control respond immediately, then reconciles\n // with the store so a refused write is visible rather than silently lost.\n const [draft, setDraft] = (React.useState ?? ((v: any) => [v, () => {}]))({})\n const edit = (id: string, field: string, value: unknown) =>\n setDraft((current: any) => ({ ...current, [id]: { ...current[id], [field]: value } }))\n\n const rows = knownProviders({ ...configured, ...draft }, published)\n\n /**\n * Persist one field. The control is already showing the new value, so this\n * only has to succeed quietly; a refusal is reported in the diagnostics.\n */\n const save = (id: string, field: string, value: unknown) => {\n void writeConfig(ctx, [{ op: 'set', path: ['providers', id, field], value }])\n .then(() => {\n note(`\u5DF2\u4FDD\u5B58 ${id}.${field} = ${JSON.stringify(value)}`)\n })\n .catch((error: any) => {\n note(`\u4FDD\u5B58\u5931\u8D25 ${id}.${field}\uFF1A${error?.message ?? error}`)\n // Drop the optimistic value so the stored state shows through again.\n setDraft((current: any) => {\n const next = { ...current }\n delete next[id]\n return next\n })\n })\n }\n\n /** One control: update the draft instantly, persist in the background. */\n const bind = (id: string, field: string) => (value: unknown) => {\n edit(id, field, value)\n save(id, field, value)\n }\n\n const field = (label: string, control: unknown, hint?: string): unknown =>\n h(\n 'label',\n { className: styles.field, style: S.field, key: label },\n h('span', { className: styles.label, style: S.label }, label),\n control,\n hint === undefined\n ? null\n : h(\n 'span',\n { className: styles.hint, style: { gridColumn: '2', fontSize: '11px' } },\n hint,\n ),\n )\n\n // ALWAYS an array: a single element is not iterable, and spreading one threw\n // \"Spread syntax requires ...iterable[Symbol.iterator]\" on an empty list.\n const body: unknown[] = rows.length === 0\n ? [\n h(\n 'p',\n {\n className: styles.empty,\n key: 'empty',\n style: {\n margin: '0',\n padding: '16px',\n border: '1px dashed var(--dsw-alias-border-l1)',\n borderRadius: '8px',\n fontSize: '12px',\n textAlign: 'center',\n color: 'var(--dsw-alias-state-idle-primary)',\n },\n },\n t.empty,\n ),\n ]\n : rows.map(row => {\n // The MERGED value, so a just-typed value shows immediately.\n const route = view({ ...configured[row.id], ...draft[row.id] })\n const disabled = !route.enabled\n return h(\n 'section',\n {\n className: route.enabled ? styles.cardActive : styles.card,\n style: route.enabled ? { ...S.card, ...S.cardActive } : S.card,\n key: row.id,\n },\n h(\n 'header',\n { className: styles.cardHead, style: S.head },\n h(\n 'div',\n { className: styles.cardTitles, style: S.titles },\n h('span', { className: styles.name, style: S.name }, row.name),\n h('span', { className: styles.id, style: S.id }, row.id),\n ),\n h(\n 'span',\n {\n className: route.enabled ? styles.pillOn : row.live ? styles.pillLive : styles.pillOff,\n style: {\n ...S.pill,\n ...(route.enabled ? S.pillOn : row.live ? S.pillLive : S.pillOff),\n },\n },\n route.enabled ? t.on : row.live ? t.live : t.off,\n ),\n ),\n h(\n 'label',\n { className: styles.toggle, style: S.toggle },\n h('input', {\n type: 'checkbox',\n checked: route.enabled,\n onChange: (event: any) => bind(row.id, 'enabled')(event.target.checked === true),\n }),\n h('span', null, t.useProxy),\n ),\n field(\n t.protocol,\n h(\n 'select',\n {\n className: styles.input,\n style: S.input,\n disabled,\n value: route.protocol,\n onChange: (event: any) => bind(row.id, 'protocol')(event.target.value),\n },\n ...PROTOCOLS.map(protocol =>\n h('option', { key: protocol, value: protocol }, protocol.toUpperCase()),\n ),\n ),\n route.protocol === 'socks5' ? t.socks5Unsupported : undefined,\n ),\n field(\n t.host,\n h('input', {\n className: styles.input,\n style: S.input,\n disabled,\n placeholder: '127.0.0.1',\n value: route.host,\n onChange: (event: any) => bind(row.id, 'host')(event.target.value),\n }),\n t.hostHint,\n ),\n field(\n t.port,\n h('input', {\n className: styles.input,\n style: S.input,\n disabled,\n type: 'number',\n min: 1,\n max: 65535,\n placeholder: '7890',\n value: route.port === 0 ? '' : String(route.port),\n onChange: (event: any) => {\n const parsed = Number.parseInt(event.target.value, 10)\n bind(row.id, 'port')(Number.isNaN(parsed) ? 0 : parsed)\n },\n }),\n ),\n field(\n t.username,\n h('input', {\n className: styles.input,\n style: S.input,\n disabled,\n autocomplete: 'off',\n value: route.username,\n onChange: (event: any) => bind(row.id, 'username')(event.target.value),\n }),\n ),\n )\n })\n\n return h(\n 'div',\n { className: styles.root, style: S.root },\n h('p', { className: styles.lead, style: { margin: '0 0 4px', fontSize: '12px', lineHeight: '1.6', color: 'var(--dsw-alias-label-secondary)' } }, t.lead),\n ...body,\n h(\n 'details',\n {\n className: styles.diag,\n key: 'diag',\n style: {\n marginTop: '4px',\n padding: '8px 10px',\n border: '1px solid var(--dsw-alias-border-l1)',\n borderRadius: '8px',\n fontSize: '11px',\n color: 'var(--dsw-alias-label-secondary)',\n },\n },\n h('summary', { className: styles.diagSummary }, t.diagnostics),\n h(\n 'ul',\n { className: styles.diagList, style: { margin: '6px 0 0', paddingLeft: '18px' } },\n ...(diagnostics.length === 0\n ? [h('li', { key: 'none' }, t.diagPending)]\n : diagnostics.map((line, index) => h('li', { key: `d${index}` }, line))),\n ),\n ),\n )\n}\n\nconst EN = {\n lead: 'Route selected model providers through your own forward proxy. Other providers stay direct.',\n empty: 'No providers found yet.',\n useProxy: 'Use a proxy for this provider',\n protocol: 'Type',\n host: 'IP / host',\n port: 'Port',\n username: 'Username',\n hostHint: 'Host or IP only, without scheme or path.',\n socks5Unsupported: 'SOCKS5 is not implemented yet; use HTTP or HTTPS.',\n on: 'proxied',\n live: 'active',\n off: 'direct',\n diagnostics: 'Connection diagnostics',\n diagPending: '(collecting\u2026)',\n}\n\nconst ZH = {\n lead: '\u8BA9\u6307\u5B9A\u7684 provider \u8D70\u4F60\u81EA\u5DF1\u7684\u6B63\u5411\u4EE3\u7406\uFF0C\u5176\u5B83 provider \u4FDD\u6301\u76F4\u8FDE\u3002',\n empty: '\u6CA1\u6709\u68C0\u6D4B\u5230\u4EFB\u4F55 provider\u3002',\n useProxy: '\u4E3A\u8BE5 provider \u542F\u7528\u4EE3\u7406',\n protocol: '\u7C7B\u578B',\n host: 'IP / \u4E3B\u673A',\n port: '\u7AEF\u53E3',\n username: '\u7528\u6237\u540D',\n hostHint: '\u53EA\u586B\u4E3B\u673A\u540D\u6216 IP\uFF0C\u4E0D\u8981\u5E26\u534F\u8BAE\u524D\u7F00\u6216\u8DEF\u5F84\u3002',\n socks5Unsupported: 'SOCKS5 \u5C1A\u672A\u5B9E\u73B0\uFF0C\u8BF7\u6539\u7528 HTTP \u6216 HTTPS\u3002',\n on: '\u8D70\u4EE3\u7406',\n live: '\u542F\u7528\u4E2D',\n off: '\u76F4\u8FDE',\n diagnostics: '\u8FDE\u63A5\u8BCA\u65AD',\n diagPending: '\uFF08\u6B63\u5728\u6536\u96C6\u2026\uFF09',\n}\n\n/**\n * Pick the dictionary for this render.\n *\n * The shell's own locale dictionary wins when it carries a translated entry, so\n * the page follows the application language instead of second-guessing it.\n * Chinese is the fallback because that is the operator's language.\n */\nfunction stringsFor(ctx: any): Record<string, string> {\n const language = localeOf(ctx)\n const bundled = language === 'zh' ? ZH : EN\n const translated = ((): Record<string, string> | undefined => {\n try {\n const service = optionalService(ctx, 'locale')\n const bound = service?.bind?.('dshProviderProxy')\n const value = typeof bound === 'function' ? bound('title') : undefined\n if (typeof value === 'string' && value.length > 0) return { title: value } as never\n } catch {\n // no locale dictionary available\n }\n return undefined\n })()\n return { ...bundled, ...(translated ?? {}) }\n}\n\n/**\n * The client module system's resolver.\n *\n * The loader calls `factory(require)` and that parameter shadows Node's\n * `require` inside the emitted CJS, so this describes the module-table\n * resolver, not Node's.\n */\ndeclare function require(specifier: string): unknown\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\nvar __dshMap = {\"root\":\"1b9ac577_root\",\"lead\":\"4a359f22_lead\",\"empty\":\"ffd21b3b_empty\",\"card\":\"16611c9b_card\",\"cardActive\":\"2d004466_cardActive\",\"cardHead\":\"640fee25_cardHead\",\"cardTitles\":\"f6fe8b3f_cardTitles\",\"name\":\"f9d2db09_name\",\"id\":\"c90ce2e0_id\",\"pillOn\":\"75541864_pillOn\",\"pillLive\":\"3097d90f_pillLive\",\"pillOff\":\"a58f86be_pillOff\",\"toggle\":\"e5b81c4b_toggle\",\"field\":\"f4d34839_field\",\"label\":\"a4061c91_label\",\"hint\":\"13bd3ec9_hint\",\"input\":\"851d7bd9_input\",\"diag\":\"f92a10d9_diag\",\"diagSummary\":\"5b66e072_diagSummary\",\"diagList\":\"dc8d3a6f_diagList\"};\nvar __dshStyles = (globalThis.__dshPluginStyles || (globalThis.__dshPluginStyles = new Set()));\nif (!__dshStyles.has(\"dsh-provider-proxy/client.css\")) {\n __dshStyles.add(\"dsh-provider-proxy/client.css\");\n var __dshStyle = document.createElement('style');\n __dshStyle.setAttribute('data-plugin-css', \"dsh-provider-proxy/client.css\");\n __dshStyle.textContent = \"/* dsh-provider-proxy \u2014 provider proxy settings page.\\n Tokens only: no literal colours, matching the shared --dsw-* system. */\\n\\n.1b9ac577_root {\\n display: flex;\\n flex-direction: column;\\n gap: 12px;\\n max-width: 640px;\\n}\\n\\n.4a359f22_lead {\\n margin: 0 0 4px;\\n font-size: 12px;\\n line-height: 1.6;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.ffd21b3b_empty {\\n margin: 0;\\n padding: 16px;\\n border: 1px dashed var(--dsw-alias-border-l1);\\n border-radius: 8px;\\n font-size: 12px;\\n text-align: center;\\n color: var(--dsw-alias-state-idle-primary);\\n}\\n\\n/* ---- provider card ---- */\\n\\n.16611c9b_card,\\n.2d004466_cardActive {\\n display: flex;\\n flex-direction: column;\\n gap: 10px;\\n padding: 12px 14px;\\n border: 1px solid var(--dsw-alias-border-l1);\\n border-radius: 10px;\\n background: var(--dsw-alias-bg-layer-1);\\n}\\n\\n.2d004466_cardActive {\\n border-color: var(--dsw-alias-state-success-primary);\\n background: var(--dsw-alias-bg-layer-2);\\n}\\n\\n.640fee25_cardHead {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n gap: 12px;\\n}\\n\\n.f6fe8b3f_cardTitles {\\n display: flex;\\n align-items: baseline;\\n gap: 8px;\\n min-width: 0;\\n}\\n\\n.f9d2db09_name {\\n overflow: hidden;\\n font-size: 13px;\\n font-weight: 600;\\n white-space: nowrap;\\n text-overflow: ellipsis;\\n color: var(--dsw-alias-label-primary);\\n}\\n\\n.c90ce2e0_id {\\n flex: none;\\n padding: 1px 6px;\\n border-radius: 4px;\\n background: var(--dsw-alias-bg-layer-2);\\n font-family: ui-monospace, monospace;\\n font-size: 11px;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n/* ---- status pill ---- */\\n\\n.75541864_pillOn,\\n.3097d90f_pillLive,\\n.a58f86be_pillOff {\\n flex: none;\\n padding: 2px 8px;\\n border-radius: 999px;\\n font-size: 11px;\\n font-weight: 500;\\n white-space: nowrap;\\n}\\n\\n.75541864_pillOn {\\n background: var(--dsw-alias-state-success-primary);\\n color: var(--dsw-alias-bg-base);\\n}\\n\\n.3097d90f_pillLive {\\n border: 1px solid var(--dsw-alias-border-l2);\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.a58f86be_pillOff {\\n color: var(--dsw-alias-state-idle-primary);\\n}\\n\\n/* ---- toggle ---- */\\n\\n.e5b81c4b_toggle {\\n display: flex;\\n align-items: center;\\n gap: 8px;\\n padding-top: 2px;\\n font-size: 12px;\\n color: var(--dsw-alias-label-primary);\\n cursor: pointer;\\n}\\n\\n.e5b81c4b_toggle input {\\n accent-color: var(--dsw-alias-brand-primary);\\n cursor: pointer;\\n}\\n\\n/* ---- fields ---- */\\n\\n.f4d34839_field {\\n display: grid;\\n grid-template-columns: 96px 1fr;\\n align-items: center;\\n gap: 10px;\\n font-size: 12px;\\n}\\n\\n.a4061c91_label {\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.13bd3ec9_hint {\\n grid-column: 2;\\n margin-top: -2px;\\n font-size: 11px;\\n color: var(--dsw-alias-state-warn-primary);\\n}\\n\\n.851d7bd9_input {\\n box-sizing: border-box;\\n width: 100%;\\n min-width: 0;\\n padding: 5px 8px;\\n border: 1px solid var(--dsw-alias-border-l1);\\n border-radius: 6px;\\n outline: none;\\n background: var(--dsw-alias-bg-layer-1);\\n color: var(--dsw-alias-label-primary);\\n font: inherit;\\n font-size: 12px;\\n transition: border-color 120ms ease, background 120ms ease;\\n}\\n\\n.851d7bd9_input:hover:not(:disabled) {\\n border-color: var(--dsw-alias-border-l2);\\n}\\n\\n.851d7bd9_input:focus {\\n border-color: var(--dsw-alias-brand-primary);\\n}\\n\\n.851d7bd9_input:disabled {\\n color: var(--dsw-alias-state-idle-primary);\\n background: var(--dsw-alias-bg-layer-2);\\n cursor: not-allowed;\\n}\\n\\n/* ---- diagnostics ---- */\\n\\n.f92a10d9_diag {\\n margin-top: 2px;\\n padding: 8px 10px;\\n border: 1px solid var(--dsw-alias-border-l1);\\n border-radius: 8px;\\n font-size: 11px;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.5b66e072_diagSummary {\\n cursor: pointer;\\n color: var(--dsw-alias-state-warn-primary);\\n}\\n\\n.dc8d3a6f_diagList {\\n margin: 6px 0 0;\\n padding-left: 18px;\\n font-family: ui-monospace, monospace;\\n word-break: break-all;\\n}\\n\";\n document.head.appendChild(__dshStyle);\n}\nmodule.exports = __dshMap;\nmodule.exports.default = __dshMap;\nmodule.exports.__esModule = true;\n", "/**\r\n * dsh-provider-proxy \u2014 browser half.\r\n *\r\n * Contributes ONE settings page (a `settings.section` list entry) that lists\r\n * every known provider with its proxy switch, type, host, port and username.\r\n *\r\n * This replaces an earlier attempt to render into each provider card on the\r\n * Models page (`settings.models.provider-card`). That seat is keyed and\r\n * dispatched per provider namespace, and a third-party registration never\r\n * matched it on this build: no error, no request, simply no output. A\r\n * `settings.section` entry is a plain list contribution with an `id`, which is\r\n * the shape the shipped `dsh-llm-retry-settings` plugin uses successfully in\r\n * this same desktop profile.\r\n *\r\n * The whole bundle runs inside the client module system's lazy-CJS factory:\r\n * executing the script only REGISTERS the factory, and every side effect\r\n * (including the CSS injection) happens at materialization.\r\n */\r\n\r\n// The CSS-Modules build turns this sheet into a hashed class map AND injects it\r\n// at materialization. The binding is what the component reads; importing it for\r\n// side effects only would leave `styles` undefined at render time.\r\nimport styles from './client.css'\r\n\r\ntype Protocol = 'http' | 'https' | 'socks5'\r\n\r\ntype RouteValue = {\r\n enabled: boolean\r\n protocol: Protocol\r\n host: string\r\n port: number\r\n username: string\r\n password: string\r\n}\r\n\r\n/** The provider rows we know about, and which of them are actually live. */\r\ntype ProviderRow = { id: string; name: string; live: boolean }\r\n\r\n/**\r\n * React, resolved from the client module table.\r\n *\r\n * React is NOT a Cordis service and is not reachable from `ctx` \u2014 reading it\r\n * there produced a silently null component. The module table is the only route:\r\n * the build leaves `react` external, so this compiles to a `require(\"react\")`\r\n * inside the factory closure, answered from the shell-seeded baseline.\r\n *\r\n * Resolved lazily on first render so merely REGISTERING the bundle \u2014 which is\r\n * all a script evaluation does \u2014 never materializes React.\r\n */\r\nlet ReactCache: unknown\r\n\r\nfunction react(): any {\r\n if (ReactCache === undefined) {\r\n ReactCache = ((): unknown => {\r\n try {\r\n return require('react')\r\n } catch {\r\n return (globalThis as Record<string, unknown>).React\r\n }\r\n })()\r\n }\r\n return ReactCache\r\n}\r\n\r\nconst PROTOCOLS: Protocol[] = ['http', 'https', 'socks5']\r\n\r\n/** Our own settings namespace; the profile entry id created by the bundle patch. */\r\nconst NAMESPACE = 'provider-proxy'\r\n\r\n/**\r\n * Cordis services this half needs.\r\n *\r\n * ONLY `slots` is declared. That is the complete set this release actually\r\n * offers on a client fiber: `layout, locale, sessions, slots, theme, timer,\r\n * uiWorkspace, workspaces`.\r\n *\r\n * A declared service that never arrives leaves the fiber PENDING forever, and\r\n * that is NOT a client-only failure \u2014 it is reported as\r\n * web boot: 1 entry did not activate\r\n * dsh-provider-proxy: pending (waiting for service: settingsScope)\r\n * which fails the whole Desktop boot. `settingsScope` and `configForms` were\r\n * both guessed and both are absent here, so neither may be declared.\r\n *\r\n * Settings are therefore reached through `ctx.get(name)` \u2014 the framework's own\r\n * non-throwing lookup \u2014 and the page degrades to read-only when it is absent.\r\n */\r\nconst PLUGINS = ['slots']\r\n\r\nexport const inject = PLUGINS\r\n\r\nexport function apply(ctx: any): void {\r\n // The settings shell declares `settings.section` on its own fiber, so\r\n // `slots.inject` waits for that declaration and the contribution is removed\r\n // when the panel is torn down.\r\n ctx.slots.inject('settings.section', () =>\r\n ctx.slots.register(\r\n {\r\n name: 'settings.section',\r\n id: NAMESPACE,\r\n order: 20,\r\n label: () => (localeOf(ctx) === 'zh' ? 'Provider \u4EE3\u7406' : 'Provider \u4EE3\u7406'),\r\n },\r\n () => renderPage(ctx),\r\n ),\r\n )\r\n}\r\n\r\n/**\r\n * Pick the dictionary.\r\n *\r\n * Chinese is the default, not English: this plugin is written for a\r\n * Chinese-speaking operator, and a page that renders in the wrong language is\r\n * worse than one that never matches the shell's locale.\r\n *\r\n * `ctx.locale` is not injected \u2014 declaring a service that this release does not\r\n * provide left the fiber PENDING and failed the whole Desktop boot \u2014 so the\r\n * locale is probed with the non-throwing `ctx.get`, then the browser's own\r\n * language, and only then English.\r\n */\r\nfunction localeOf(ctx: any): string {\r\n try {\r\n const service = optionalService(ctx, 'locale')\r\n const snapshot = service?.getSnapshot?.() ?? service?.getLocale?.()\r\n const id = typeof snapshot?.locale === 'string' ? snapshot.locale : undefined\r\n if (id !== undefined) return id.toLowerCase().startsWith('zh') ? 'zh' : 'en'\r\n } catch {\r\n // fall through to the browser language\r\n }\r\n const browser = globalThis.navigator?.language\r\n if (typeof browser === 'string' && browser.toLowerCase().startsWith('zh')) return 'zh'\r\n return browser === undefined ? 'zh' : 'en'\r\n}\r\n\r\n/**\r\n * Look a service up WITHOUT declaring it in `inject`.\r\n *\r\n * `ctx.get(name)` is the framework's own optional lookup: it returns undefined\r\n * instead of throwing, and \u2014 unlike a declared service \u2014 it cannot leave the\r\n * fiber PENDING. That is what makes an optional integration safe here: this\r\n * release has no settings service at all, so the page simply shows its fields\r\n * and reports that saving is unavailable.\r\n */\r\nfunction optionalService(ctx: any, ...names: string[]): any {\r\n for (const name of names) {\r\n try {\r\n const found = typeof ctx?.get === 'function' ? ctx.get(name) : undefined\r\n if (found !== undefined && found !== null) return found\r\n } catch {\r\n // try the next spelling\r\n }\r\n }\r\n return undefined\r\n}\r\n\r\n/** The settings form for this plugin's namespace, when one exists. */\r\nfunction formOf(ctx: any): any {\r\n const forms = optionalService(ctx, 'configForms', 'settingsScope')\r\n if (forms === undefined) return undefined\r\n try {\r\n if (typeof forms.get === 'function') return forms.get(NAMESPACE)\r\n // A settingsScope-style service is already bound to one namespace.\r\n if (typeof forms.getSnapshot === 'function' || typeof forms.bind === 'function') return forms\r\n } catch {\r\n return undefined\r\n }\r\n return undefined\r\n}\r\n\r\nfunction readConfig(ctx: any): { value: any; revision: number } {\r\n const form = formOf(ctx)\r\n if (form === undefined) return { value: {}, revision: 0 }\r\n try {\r\n const snapshot = form.getSnapshot?.()\r\n return {\r\n value: snapshot?.value ?? snapshot?.user ?? {},\r\n revision: snapshot?.revision ?? 0,\r\n }\r\n } catch {\r\n return { value: {}, revision: 0 }\r\n }\r\n}\r\n\r\nasync function writeConfig(ctx: any, ops: readonly unknown[]): Promise<void> {\r\n const form = formOf(ctx)\r\n if (typeof form?.mutate !== 'function') {\r\n throw new Error('dsh-provider-proxy: settings transport unavailable')\r\n }\r\n await form.mutate(ops as any[], readConfig(ctx).revision)\r\n}\r\n\r\n/**\r\n * The provider rows, read from the Host.\r\n *\r\n * This release exposes no client-facing LLM service, so the page cannot ask for\r\n * the directory itself. The Host serves it at this same-origin endpoint, where\r\n * `ctx.llm.listProviders()` / `listConfigurableProviders()` actually live. The\r\n * list is therefore automatic \u2014 the user never types a route id.\r\n *\r\n * Only ACTIVE routes are shown. A provider this deployment merely *offers* \u2014\r\n * declared but not registered, so nothing would ever be sent through it \u2014 is\r\n * not the user's business on this page, and listing it only invites them to\r\n * configure a proxy for a route that cannot be selected. A provider that is\r\n * already configured is kept regardless, so a saved setting never silently\r\n * disappears from view.\r\n */\r\nfunction knownProviders(configured: Record<string, RouteValue>, published: ProviderRow[]): ProviderRow[] {\r\n const rows = new Map<string, ProviderRow>()\r\n for (const row of published) {\r\n if (row.live) rows.set(row.id, row)\r\n }\r\n for (const [id, route] of Object.entries(configured)) {\r\n if (rows.has(id)) continue\r\n rows.set(id, { id, name: id, live: route?.enabled === true })\r\n }\r\n return [...rows.values()].sort(byName)\r\n}\r\n\r\n/**\r\n * Where the Host publishes the live provider catalogue.\r\n */\r\nconst CATALOG_PATH = '/dsh-provider-proxy/providers'\r\n\r\n/**\r\n * The setter the lazy catalogue initializer resolves through.\r\n *\r\n * It is republished after every render, so the newest one always wins, and a\r\n * promise that settles after an unmount writes to a harmless no-op.\r\n */\r\nlet catalogueSetter: ((rows: ProviderRow[]) => void) | undefined = () => {}\r\n\r\n/** Read the Host's provider catalogue. Same-origin, so no token is needed. */\r\nasync function fetchProviders(): Promise<ProviderRow[]> {\r\n const response = await globalThis.fetch(CATALOG_PATH, { headers: { accept: 'application/json' } })\r\n if (!response.ok) throw new Error(`Host answered ${response.status}`)\r\n const body = await response.json()\r\n const list = Array.isArray(body?.providers) ? body.providers : []\r\n return list\r\n .filter((row: any) => typeof row?.id === 'string' && row.id.length > 0)\r\n .map((row: any) => ({\r\n id: row.id,\r\n name: typeof row.name === 'string' && row.name.length > 0 ? row.name : row.id,\r\n live: row.live === true,\r\n }))\r\n}\r\n\r\nconst byName = (a: ProviderRow, b: ProviderRow): number => a.name.localeCompare(b.name)\r\n\r\nfunction view(route: Partial<RouteValue> | undefined): RouteValue {\r\n return {\r\n enabled: route?.enabled === true,\r\n protocol: PROTOCOLS.includes(route?.protocol as Protocol) ? (route!.protocol as Protocol) : 'http',\r\n host: route?.host ?? '',\r\n port: route?.port ?? 0,\r\n username: route?.username ?? '',\r\n password: route?.password ?? '',\r\n }\r\n}\r\n\r\n/** The provider directory, cached module-side. See renderPage. */\r\nlet directoryCache: ProviderRow[] | undefined\r\n\r\n/**\r\n * Everything the page learned about its own wiring, rendered verbatim.\r\n *\r\n * The browser side of a plugin has no other diagnostic channel \u2014 the Host log\r\n * never sees it \u2014 so a silent failure had to be diagnosed by inference. This\r\n * panel is what proved that `remote.settings` and `remote.llm` do not exist in\r\n * this release, and that the catalogue had to come from the Host endpoint.\r\n *\r\n * Cleared at the start of every render so the panel shows the CURRENT state\r\n * rather than an ever-growing log of the session.\r\n */\r\nlet diagnostics: string[] = []\r\n\r\nfunction note(message: string): void {\r\n if (!diagnostics.includes(message)) diagnostics.push(message)\r\n}\r\n\r\n/**\r\n * Layout constants, applied as INLINE styles.\r\n *\r\n * The page is rendered into the settings panel, and the CSS-Modules pipeline\r\n * that feeds the stylesheet has broken twice in ways that were invisible from\r\n * the source: the class map failed to bind at all, and a shared class prefix\r\n * silently merged two rules. Both left the page readable but laid out as one\r\n * unstyled block.\r\n *\r\n * Structure is therefore expressed as inline styles, which cannot be lost by\r\n * the bundle, and the stylesheet is kept for the purely decorative parts. A\r\n * theme token that is not defined simply resolves to `unset`, so an unknown\r\n * token costs colour, never layout.\r\n */\r\nconst S = {\r\n root: {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '12px',\r\n maxWidth: '720px',\r\n },\r\n card: {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '12px',\r\n padding: '14px 16px',\r\n marginBottom: '12px',\r\n border: '1px solid var(--dsw-alias-border-l1)',\r\n borderRadius: '10px',\r\n background: 'var(--dsw-alias-bg-layer-1)',\r\n },\r\n cardActive: {\r\n borderColor: 'var(--dsw-alias-state-success-primary)',\r\n background: 'var(--dsw-alias-bg-layer-2)',\r\n },\r\n head: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n gap: '12px',\r\n },\r\n titles: { display: 'flex', alignItems: 'baseline', gap: '8px', minWidth: '0' },\r\n name: {\r\n fontSize: '14px',\r\n fontWeight: '600',\r\n color: 'var(--dsw-alias-label-primary)',\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis',\r\n whiteSpace: 'nowrap',\r\n },\r\n id: {\r\n flex: 'none',\r\n padding: '1px 6px',\r\n borderRadius: '4px',\r\n background: 'var(--dsw-alias-bg-layer-2)',\r\n fontFamily: 'ui-monospace, monospace',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n },\r\n pill: {\r\n flex: 'none',\r\n padding: '2px 10px',\r\n borderRadius: '999px',\r\n fontSize: '11px',\r\n fontWeight: '500',\r\n whiteSpace: 'nowrap',\r\n },\r\n pillOn: {\r\n background: 'var(--dsw-alias-state-success-primary)',\r\n color: 'var(--dsw-alias-bg-base)',\r\n },\r\n pillLive: {\r\n border: '1px solid var(--dsw-alias-border-l2)',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n },\r\n pillOff: { color: 'var(--dsw-alias-state-idle-primary)' },\r\n toggle: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '8px',\r\n fontSize: '12px',\r\n color: 'var(--dsw-alias-label-primary)',\r\n },\r\n field: {\r\n display: 'grid',\r\n gridTemplateColumns: '88px 1fr',\r\n alignItems: 'center',\r\n gap: '10px',\r\n fontSize: '12px',\r\n },\r\n label: { color: 'var(--dsw-alias-label-secondary)' },\r\n input: {\r\n boxSizing: 'border-box',\r\n width: '100%',\r\n minWidth: '0',\r\n padding: '6px 8px',\r\n border: '1px solid var(--dsw-alias-border-l1)',\r\n borderRadius: '6px',\r\n outline: 'none',\r\n background: 'var(--dsw-alias-bg-layer-1)',\r\n color: 'var(--dsw-alias-label-primary)',\r\n font: 'inherit',\r\n fontSize: '12px',\r\n },\r\n} as const\r\n\r\nfunction renderPage(ctx: any): unknown {\r\n const React = react()\r\n if (React === undefined || typeof React.createElement !== 'function') return null\r\n\r\n const h = React.createElement\r\n const t = stringsFor(ctx)\r\n diagnostics = []\r\n\r\n // `useState` is only reached after the React check, so the early return above\r\n // cannot desync the hooks order.\r\n let snapshot: { value: any; revision: number }\r\n try {\r\n snapshot = readConfig(ctx)\r\n } catch {\r\n snapshot = { value: {}, revision: 0 }\r\n }\r\n const configured = (snapshot.value?.providers ?? {}) as Record<string, RouteValue>\r\n note(\r\n formOf(ctx) === undefined\r\n ? '\u8BBE\u7F6E\uFF1A\u672A\u627E\u5230 configForms \u670D\u52A1\uFF0C\u53EA\u80FD\u663E\u793A\u3001\u65E0\u6CD5\u4FDD\u5B58'\r\n : `\u8BBE\u7F6E\uFF1A\u6B63\u5E38\uFF08\u4FEE\u8BA2\u53F7 ${snapshot.revision}\uFF0C${Object.keys(configured).length} \u4E2A provider\uFF09`,\r\n )\r\n\r\n // The provider catalogue comes from the Host over a same-origin endpoint, so\r\n // it arrives asynchronously. The initial state is a LAZY initializer, so the\r\n // fetch starts from `useState(() => \u2026)` instead of by calling a setter during\r\n // render: a render must have no side effects, and doing so also shifted the\r\n // hook order between passes.\r\n const [state, setState] = (React.useState ?? ((fn: any) => [fn(), () => {}]))(() => {\r\n void fetchProviders()\r\n .then(rows => catalogueSetter?.(rows))\r\n .catch((error: any) => {\r\n note(`provider \u5217\u8868\u83B7\u53D6\u5931\u8D25\uFF1A${error?.message ?? error}`)\r\n catalogueSetter?.([])\r\n })\r\n return { rows: undefined as ProviderRow[] | undefined, pending: true }\r\n })\r\n // The setter is published right after the hook so the initializer's promise\r\n // can reach it. It is re-published on every render, so the latest wins.\r\n catalogueSetter = rows => setState({ rows, pending: false })\r\n\r\n const published = state.rows ?? []\r\n note(\r\n `provider \u5217\u8868\uFF1A\u6765\u81EA Host \u5171 ${published.length} \u4E2A\uFF08${published.map((r: ProviderRow) => r.id).join('\u3001') || '\u65E0'}\uFF09`,\r\n )\r\n // Local draft, layered over the stored config.\r\n //\r\n // Without it a checkbox does not change until the panel remounts: the value\r\n // is read from the settings store, which only updates when the page is\r\n // rebuilt. The draft makes the control respond immediately, then reconciles\r\n // with the store so a refused write is visible rather than silently lost.\r\n const [draft, setDraft] = (React.useState ?? ((v: any) => [v, () => {}]))({})\r\n const edit = (id: string, field: string, value: unknown) =>\r\n setDraft((current: any) => ({ ...current, [id]: { ...current[id], [field]: value } }))\r\n\r\n const rows = knownProviders({ ...configured, ...draft }, published)\r\n\r\n /**\r\n * Persist one field. The control is already showing the new value, so this\r\n * only has to succeed quietly; a refusal is reported in the diagnostics.\r\n */\r\n const save = (id: string, field: string, value: unknown) => {\r\n void writeConfig(ctx, [{ op: 'set', path: ['providers', id, field], value }])\r\n .then(() => {\r\n note(`\u5DF2\u4FDD\u5B58 ${id}.${field} = ${JSON.stringify(value)}`)\r\n })\r\n .catch((error: any) => {\r\n note(`\u4FDD\u5B58\u5931\u8D25 ${id}.${field}\uFF1A${error?.message ?? error}`)\r\n // Drop the optimistic value so the stored state shows through again.\r\n setDraft((current: any) => {\r\n const next = { ...current }\r\n delete next[id]\r\n return next\r\n })\r\n })\r\n }\r\n\r\n /** One control: update the draft instantly, persist in the background. */\r\n const bind = (id: string, field: string) => (value: unknown) => {\r\n edit(id, field, value)\r\n save(id, field, value)\r\n }\r\n\r\n const field = (label: string, control: unknown, hint?: string): unknown =>\r\n h(\r\n 'label',\r\n { className: styles.field, style: S.field, key: label },\r\n h('span', { className: styles.label, style: S.label }, label),\r\n control,\r\n hint === undefined\r\n ? null\r\n : h(\r\n 'span',\r\n { className: styles.hint, style: { gridColumn: '2', fontSize: '11px' } },\r\n hint,\r\n ),\r\n )\r\n\r\n // ALWAYS an array: a single element is not iterable, and spreading one threw\r\n // \"Spread syntax requires ...iterable[Symbol.iterator]\" on an empty list.\r\n const body: unknown[] = rows.length === 0\r\n ? [\r\n h(\r\n 'p',\r\n {\r\n className: styles.empty,\r\n key: 'empty',\r\n style: {\r\n margin: '0',\r\n padding: '16px',\r\n border: '1px dashed var(--dsw-alias-border-l1)',\r\n borderRadius: '8px',\r\n fontSize: '12px',\r\n textAlign: 'center',\r\n color: 'var(--dsw-alias-state-idle-primary)',\r\n },\r\n },\r\n t.empty,\r\n ),\r\n ]\r\n : rows.map(row => {\r\n // The MERGED value, so a just-typed value shows immediately.\r\n const route = view({ ...configured[row.id], ...draft[row.id] })\r\n const disabled = !route.enabled\r\n return h(\r\n 'section',\r\n {\r\n className: route.enabled ? styles.cardActive : styles.card,\r\n style: route.enabled ? { ...S.card, ...S.cardActive } : S.card,\r\n key: row.id,\r\n },\r\n h(\r\n 'header',\r\n { className: styles.cardHead, style: S.head },\r\n h(\r\n 'div',\r\n { className: styles.cardTitles, style: S.titles },\r\n h('span', { className: styles.name, style: S.name }, row.name),\r\n h('span', { className: styles.id, style: S.id }, row.id),\r\n ),\r\n h(\r\n 'span',\r\n {\r\n className: route.enabled ? styles.pillOn : row.live ? styles.pillLive : styles.pillOff,\r\n style: {\r\n ...S.pill,\r\n ...(route.enabled ? S.pillOn : row.live ? S.pillLive : S.pillOff),\r\n },\r\n },\r\n route.enabled ? t.on : row.live ? t.live : t.off,\r\n ),\r\n ),\r\n h(\r\n 'label',\r\n { className: styles.toggle, style: S.toggle },\r\n h('input', {\r\n type: 'checkbox',\r\n checked: route.enabled,\r\n onChange: (event: any) => bind(row.id, 'enabled')(event.target.checked === true),\r\n }),\r\n h('span', null, t.useProxy),\r\n ),\r\n field(\r\n t.protocol,\r\n h(\r\n 'select',\r\n {\r\n className: styles.input,\r\n style: S.input,\r\n disabled,\r\n value: route.protocol,\r\n onChange: (event: any) => bind(row.id, 'protocol')(event.target.value),\r\n },\r\n ...PROTOCOLS.map(protocol =>\r\n h('option', { key: protocol, value: protocol }, protocol.toUpperCase()),\r\n ),\r\n ),\r\n route.protocol === 'socks5' ? t.socks5Hint : undefined,\r\n ),\r\n field(\r\n t.host,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n disabled,\r\n placeholder: '127.0.0.1',\r\n value: route.host,\r\n onChange: (event: any) => bind(row.id, 'host')(event.target.value),\r\n }),\r\n t.hostHint,\r\n ),\r\n field(\r\n t.port,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n disabled,\r\n type: 'number',\r\n min: 1,\r\n max: 65535,\r\n placeholder: '7890',\r\n value: route.port === 0 ? '' : String(route.port),\r\n onChange: (event: any) => {\r\n const parsed = Number.parseInt(event.target.value, 10)\r\n bind(row.id, 'port')(Number.isNaN(parsed) ? 0 : parsed)\r\n },\r\n }),\r\n ),\r\n field(\r\n t.username,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n disabled,\r\n autocomplete: 'off',\r\n value: route.username,\r\n onChange: (event: any) => bind(row.id, 'username')(event.target.value),\r\n }),\r\n ),\r\n // Only SOCKS5 authenticates in-band, so only SOCKS5 shows this field.\r\n //\r\n // The password is stored on the route and therefore written into the\r\n // settings file with the rest of the config. It is handed to\r\n // Socks5ProxyAgent as an option, never embedded in the proxy URL that\r\n // the diagnostics surface.\r\n route.protocol === 'socks5'\r\n ? field(\r\n t.password,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n disabled,\r\n type: 'password',\r\n autocomplete: 'off',\r\n value: route.password,\r\n onChange: (event: any) => bind(row.id, 'password')(event.target.value),\r\n }),\r\n t.passwordHint,\r\n )\r\n : undefined,\r\n )\r\n })\r\n\r\n return h(\r\n 'div',\r\n { className: styles.root, style: S.root },\r\n h('p', { className: styles.lead, style: { margin: '0 0 4px', fontSize: '12px', lineHeight: '1.6', color: 'var(--dsw-alias-label-secondary)' } }, t.lead),\r\n ...body,\r\n h(\r\n 'details',\r\n {\r\n className: styles.diag,\r\n key: 'diag',\r\n style: {\r\n marginTop: '4px',\r\n padding: '8px 10px',\r\n border: '1px solid var(--dsw-alias-border-l1)',\r\n borderRadius: '8px',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n },\r\n },\r\n h('summary', { className: styles.diagSummary }, t.diagnostics),\r\n h(\r\n 'ul',\r\n { className: styles.diagList, style: { margin: '6px 0 0', paddingLeft: '18px' } },\r\n ...(diagnostics.length === 0\r\n ? [h('li', { key: 'none' }, t.diagPending)]\r\n : diagnostics.map((line, index) => h('li', { key: `d${index}` }, line))),\r\n ),\r\n ),\r\n )\r\n}\r\n\r\nconst EN = {\r\n lead: 'Route selected model providers through your own forward proxy. Other providers stay direct.',\r\n empty: 'No providers found yet.',\r\n useProxy: 'Use a proxy for this provider',\r\n protocol: 'Type',\r\n host: 'IP / host',\r\n port: 'Port',\r\n username: 'Username',\r\n password: 'Password',\r\n hostHint: 'Host or IP only, without scheme or path.',\r\n passwordHint: 'Sent to the SOCKS5 proxy for authentication; stored with this setting.',\r\n socks5Hint: 'SOCKS5 tunnels the connection; the proxy resolves the target host name.',\r\n on: 'proxied',\r\n live: 'active',\r\n off: 'direct',\r\n diagnostics: 'Connection diagnostics',\r\n diagPending: '(collecting\u2026)',\r\n}\r\n\r\nconst ZH = {\r\n lead: '\u8BA9\u6307\u5B9A\u7684 provider \u8D70\u4F60\u81EA\u5DF1\u7684\u6B63\u5411\u4EE3\u7406\uFF0C\u5176\u5B83 provider \u4FDD\u6301\u76F4\u8FDE\u3002',\r\n empty: '\u6CA1\u6709\u68C0\u6D4B\u5230\u4EFB\u4F55 provider\u3002',\r\n useProxy: '\u4E3A\u8BE5 provider \u542F\u7528\u4EE3\u7406',\r\n protocol: '\u7C7B\u578B',\r\n host: 'IP / \u4E3B\u673A',\r\n port: '\u7AEF\u53E3',\r\n username: '\u7528\u6237\u540D',\r\n password: '\u5BC6\u7801',\r\n hostHint: '\u53EA\u586B\u4E3B\u673A\u540D\u6216 IP\uFF0C\u4E0D\u8981\u5E26\u534F\u8BAE\u524D\u7F00\u6216\u8DEF\u5F84\u3002',\r\n passwordHint: '\u4EC5\u4F5C\u4E3A SOCKS5 \u8BA4\u8BC1\u53E3\u4EE4\u53D1\u9001\u7ED9\u4EE3\u7406\uFF1B\u968F\u8BE5\u8BBE\u7F6E\u4E00\u8D77\u4FDD\u5B58\u3002',\r\n socks5Hint: 'SOCKS5 \u4F1A\u5EFA\u7ACB\u96A7\u9053\uFF0C\u76EE\u6807\u57DF\u540D\u7531\u4EE3\u7406\u7AEF\u89E3\u6790\u3002',\r\n on: '\u8D70\u4EE3\u7406',\r\n live: '\u542F\u7528\u4E2D',\r\n off: '\u76F4\u8FDE',\r\n diagnostics: '\u8FDE\u63A5\u8BCA\u65AD',\r\n diagPending: '\uFF08\u6B63\u5728\u6536\u96C6\u2026\uFF09',\r\n}\r\n\r\n/**\r\n * Pick the dictionary for this render.\r\n *\r\n * The shell's own locale dictionary wins when it carries a translated entry, so\r\n * the page follows the application language instead of second-guessing it.\r\n * Chinese is the fallback because that is the operator's language.\r\n */\r\nfunction stringsFor(ctx: any): Record<string, string> {\r\n const language = localeOf(ctx)\r\n const bundled = language === 'zh' ? ZH : EN\r\n const translated = ((): Record<string, string> | undefined => {\r\n try {\r\n const service = optionalService(ctx, 'locale')\r\n const bound = service?.bind?.('dshProviderProxy')\r\n const value = typeof bound === 'function' ? bound('title') : undefined\r\n if (typeof value === 'string' && value.length > 0) return { title: value } as never\r\n } catch {\r\n // no locale dictionary available\r\n }\r\n return undefined\r\n })()\r\n return { ...bundled, ...(translated ?? {}) }\r\n}\r\n\r\n/**\r\n * The client module system's resolver.\r\n *\r\n * The loader calls `factory(require)` and that parameter shadows Node's\r\n * `require` inside the emitted CJS, so this describes the module-table\r\n * resolver, not Node's.\r\n */\r\ndeclare function require(specifier: string): unknown\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["module", "rows", "field", "styles"]
|
|
7
7
|
}
|
package/lib/index.js
CHANGED
|
@@ -103,7 +103,7 @@ function acquireFetchRouter() {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
// src/proxy-table.ts
|
|
106
|
-
import { ProxyAgent } from "undici";
|
|
106
|
+
import { ProxyAgent, Socks5ProxyAgent } from "undici";
|
|
107
107
|
|
|
108
108
|
// src/config.ts
|
|
109
109
|
import { createRequire } from "node:module";
|
|
@@ -1010,8 +1010,8 @@ var ProviderProxyRoute = z.object({
|
|
|
1010
1010
|
port: z.number().default(0),
|
|
1011
1011
|
/** Optional proxy username. */
|
|
1012
1012
|
username: z.string().default(""),
|
|
1013
|
-
/**
|
|
1014
|
-
|
|
1013
|
+
/** SOCKS5 proxy password. Only used when `protocol` is `socks5`. */
|
|
1014
|
+
password: z.string().default("")
|
|
1015
1015
|
});
|
|
1016
1016
|
var Config = z.object({
|
|
1017
1017
|
/** Per-provider proxy routes, keyed by provider route id (e.g. `sensenova`). */
|
|
@@ -1042,7 +1042,21 @@ function proxyUrl(route) {
|
|
|
1042
1042
|
const host = route.host.includes(":") && !route.host.startsWith("[") ? `[${route.host}]` : route.host;
|
|
1043
1043
|
return `${route.protocol}://${auth}${host}:${route.port}`;
|
|
1044
1044
|
}
|
|
1045
|
-
|
|
1045
|
+
function displayOrigin(route, url) {
|
|
1046
|
+
if (route.protocol !== "socks5") return new URL(url).origin;
|
|
1047
|
+
const host = route.host.includes(":") && !route.host.startsWith("[") ? `[${route.host}]` : route.host;
|
|
1048
|
+
return `${route.protocol}://${host}:${route.port}`;
|
|
1049
|
+
}
|
|
1050
|
+
function createDispatcher(route, url, password) {
|
|
1051
|
+
if (route.protocol === "socks5") {
|
|
1052
|
+
const auth = {};
|
|
1053
|
+
if (route.username.length > 0) auth.username = route.username;
|
|
1054
|
+
if (password.length > 0) auth.password = password;
|
|
1055
|
+
return new Socks5ProxyAgent(url, auth);
|
|
1056
|
+
}
|
|
1057
|
+
return new ProxyAgent({ uri: url });
|
|
1058
|
+
}
|
|
1059
|
+
function createProxyTable(config) {
|
|
1046
1060
|
const entries = /* @__PURE__ */ new Map();
|
|
1047
1061
|
const problems = /* @__PURE__ */ new Map();
|
|
1048
1062
|
for (const [provider, raw] of Object.entries(config ?? {})) {
|
|
@@ -1054,21 +1068,22 @@ async function createProxyTable(config, options = {}) {
|
|
|
1054
1068
|
continue;
|
|
1055
1069
|
}
|
|
1056
1070
|
if (!route.enabled) continue;
|
|
1057
|
-
if (route.protocol === "socks5") {
|
|
1058
|
-
problems.set(
|
|
1071
|
+
if (route.protocol === "socks5" && route.username.length > 0 && route.password.length === 0) {
|
|
1072
|
+
problems.set(
|
|
1073
|
+
provider,
|
|
1074
|
+
"dsh-provider-proxy: SOCKS5 \u914D\u7F6E\u4E86\u7528\u6237\u540D\u4F46\u6CA1\u6709\u5BC6\u7801\uFF1B\u8BF7\u8865\u5168\u5BC6\u7801\u6216\u6E05\u7A7A\u7528\u6237\u540D"
|
|
1075
|
+
);
|
|
1059
1076
|
continue;
|
|
1060
1077
|
}
|
|
1061
|
-
const password = options.resolvePassword?.(provider, route.passwordRef);
|
|
1062
|
-
void password;
|
|
1063
1078
|
const url = proxyUrl(route);
|
|
1064
1079
|
let dispatcher;
|
|
1065
1080
|
try {
|
|
1066
|
-
dispatcher =
|
|
1081
|
+
dispatcher = createDispatcher(route, url, route.password);
|
|
1067
1082
|
} catch (error) {
|
|
1068
1083
|
problems.set(provider, error instanceof Error ? error.message : String(error));
|
|
1069
1084
|
continue;
|
|
1070
1085
|
}
|
|
1071
|
-
entries.set(provider, { provider, proxyOrigin:
|
|
1086
|
+
entries.set(provider, { provider, proxyOrigin: displayOrigin(route, url), dispatcher });
|
|
1072
1087
|
}
|
|
1073
1088
|
return { entries, problems };
|
|
1074
1089
|
}
|
|
@@ -1098,7 +1113,7 @@ function apply(ctx, config) {
|
|
|
1098
1113
|
} catch {
|
|
1099
1114
|
}
|
|
1100
1115
|
const rebuild = async () => {
|
|
1101
|
-
const next =
|
|
1116
|
+
const next = createProxyTable(plainProviders(config));
|
|
1102
1117
|
const previous = current;
|
|
1103
1118
|
current = next.entries;
|
|
1104
1119
|
problems = next.problems;
|