dsh-provider-proxy 0.6.1 → 0.7.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 CHANGED
@@ -40,7 +40,7 @@ dsh plugin --profile web add dsh-provider-proxy
40
40
  | IP / 主机 | 只填 IPv4、IPv6 或 ASCII 域名;不要带协议前缀、端口、路径或凭据。IDN 需先转 punycode |
41
41
  | 端口 | 1–65535 的整数 |
42
42
  | 用户名 | 可选(与密码成对填写) |
43
- | 密码 | 可选(与用户名成对填写)。作为代理认证口令发给代理(`HTTP` / `HTTPS` / `SOCKS5` 均支持) |
43
+ | 密码 | 可选(与用户名成对填写)。作为代理认证口令发给代理(`HTTP` / `HTTPS` / `SOCKS5` 均支持)。默认隐藏,可用密码框内右侧的眼睛图标临时查看,切换不会改写或保存密码 |
44
44
 
45
45
  同一个代理要给多张卡片用时,只在页面顶部的 **默认代理** 区块填一次,再在每张卡片勾上 **使用默认代理**。
46
46
  勾上之后该卡片的传输字段(类型 / 主机 / 端口 / 用户名 / 密码)**整体**取自默认区块,卡片不再显示这些输入框,
@@ -69,7 +69,9 @@ Host catalog 是否列出某个 provider(`live`)不影响已保存路由的
69
69
  协议 / 主机 / 端口 / 用户名 / 密码,并且是**一次**写入(不是五个字段各写一次)。显式写出的 `:80` / `:443`
70
70
  会保留;完全没写端口时保持「未配置」,不会自动补默认端口。
71
71
  - **设为默认代理**(卡片上,仅在该卡片有自己的端点时出现):把它当前的端点一次性提升为顶部的默认端点。
72
- - **所有 provider 使用默认代理**(默认区块里):一条批量写把每张卡片都指向默认端点;默认端点不可用时按钮禁用。
72
+ 如果默认端点已配置且有卡片正在继承,会先弹确认框;取消后不写入、不改草稿。
73
+ - **所有 provider 使用默认代理(N)**(默认区块里):N 是全部 provider 的数量,不受过滤框影响。
74
+ 一条批量写把每张卡片都指向默认端点;默认端点不可用时按钮禁用。
73
75
  - **最近一次调用**:卡片头上会显示「最近成功 3 分钟前」,失败时显示「最近失败 ECONNREFUSED」。
74
76
  命中计数只说明这条路由被用过,这一行说明它**现在是否还工作**。已启用但还没代理过请求的路由显示
75
77
  「尚无代理记录」;**测试按钮不计入**——它证明的是「代理这一跳通」,不是「这条路由承载过真实流量」,两者混在一起会让这一行的含义不可信。
@@ -100,6 +102,11 @@ Host catalog 是否列出某个 provider(`live`)不影响已保存路由的
100
102
  已经在 `providers` 里配过代理的条目即使暂时不激活也仍然保留,避免已保存的设置悄悄消失;
101
103
  catalog 的 `live` 只影响未配置 provider 是否出现在列表里,不参与已保存卡片的状态判定。
102
104
 
105
+ 如果 Host 目录读取成功,但某个**已保存**的 provider 完全没有出现在目录里,页面不会隐藏它,
106
+ 而是在「连接诊断」里列出这些 provider,并说明代理配置仍会保留。目录读取中或读取失败时不会显示
107
+ 这条提示,避免把所有已保存 provider 误报为缺失。`live: false` 只表示目录中存在但当前未激活,
108
+ 不算缺失。
109
+
103
110
  保存立即对新请求生效,不需要重启;正在进行中的流会继续用它启动时的那条连接。
104
111
 
105
112
  设置写入失败时,字段会回滚,并在页面顶部显示「保存失败:<字段> — <原因>」和关闭按钮;下一次成功写入或点击关闭后消失。多次失败只保留最新一条。写入成功与失败的诊断都不会包含密码值,密码字段固定显示「值已隐藏」。
@@ -199,7 +206,7 @@ catalog 的 `live` 只影响未配置 provider 是否出现在列表里,不参
199
206
 
200
207
  ```sh
201
208
  npm run build # 构建 lib/index.js 与 lib/client.js
202
- npm test # 248 个用例,跑的是构建产物
209
+ npm test # 274 个用例,跑的是构建产物
203
210
  npm run typecheck # 类型检查(仅覆盖 src/)
204
211
  npm run verify # 上面三件事,按顺序
205
212
  ```
package/lib/client.js CHANGED
@@ -39,13 +39,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
39
39
  var require_client = __commonJS({
40
40
  "src/client.css"(exports, module2) {
41
41
  "use strict";
42
- var __dshMap = { "root": "bcf3ba25_root", "lead": "86cd7a9a_lead", "empty": "4ec3d74d_empty", "card": "61dfce67_card", "cardActive": "56b6c433_cardActive", "cardRejected": "24b300e2_cardRejected", "defaultCard": "665ef72b_defaultCard", "defaultLead": "351db191_defaultLead", "cardHead": "9ee651d9_cardHead", "cardTitles": "bb118443_cardTitles", "name": "a1b940d4_name", "id": "1870f756_id", "pillOn": "e9cfdcad_pillOn", "pillLive": "3d3b7405_pillLive", "pillOff": "a517f862_pillOff", "pillRejected": "3e11f4ea_pillRejected", "toggle": "31ab2dc8_toggle", "field": "52ffb01c_field", "label": "b8d05488_label", "hint": "d8b3bd46_hint", "input": "0b74e44b_input", "testButton": "47b71ed7_testButton", "diag": "f395d2a5_diag", "diagSummary": "84895b20_diagSummary", "diagList": "9ecca3cd_diagList" };
42
+ var __dshMap = { "root": "b4bf55bf_root", "lead": "03b72018_lead", "empty": "9a9a9c27_empty", "card": "6d6907d5_card", "cardActive": "a287416b_cardActive", "cardRejected": "aabaa9b3_cardRejected", "defaultCard": "ebf26189_defaultCard", "defaultLead": "5b9e9eb5_defaultLead", "cardHead": "a3319282_cardHead", "cardTitles": "6f64c28d_cardTitles", "name": "847f7e47_name", "id": "7864474d_id", "pillOn": "7ed5399b_pillOn", "pillLive": "0ccb6da5_pillLive", "pillOff": "3accadc4_pillOff", "pillRejected": "86897991_pillRejected", "toggle": "81025292_toggle", "field": "5e2577de_field", "label": "d9087e9b_label", "hint": "aae2a8a2_hint", "input": "feb8c902_input", "passwordToggle": "5645283d_passwordToggle", "testButton": "de8ca09a_testButton", "diag": "4ad17b9d_diag", "diagSummary": "b2f0759b_diagSummary", "diagList": "f49699bb_diagList" };
43
43
  var __dshStyles = globalThis.__dshPluginStyles || (globalThis.__dshPluginStyles = /* @__PURE__ */ new Set());
44
44
  if (!__dshStyles.has("dsh-provider-proxy/client.css")) {
45
45
  __dshStyles.add("dsh-provider-proxy/client.css");
46
46
  __dshStyle = document.createElement("style");
47
47
  __dshStyle.setAttribute("data-plugin-css", "dsh-provider-proxy/client.css");
48
- __dshStyle.textContent = '/* dsh-provider-proxy \u2014 provider proxy settings page.\n Tokens only: no literal colours, matching the shared --dsw-* system. */\n\n.bcf3ba25_root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 640px;\n}\n\n.86cd7a9a_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.4ec3d74d_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.61dfce67_card,\n.56b6c433_cardActive,\n.24b300e2_cardRejected {\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.56b6c433_cardActive {\n border-color: var(--dsw-alias-state-success-primary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n/* An enabled route the Host refused: never dress it as active. */\n.24b300e2_cardRejected {\n border-color: var(--dsw-alias-state-error-primary, #f85149);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n/* ---- shared default endpoint ---- */\n\n/* A distinct outer layer, so it reads as "one setting for the page" rather than\n as one more provider card. */\n.665ef72b_defaultCard {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px 16px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-2);\n}\n\n.351db191_defaultLead {\n margin: -2px 0 0;\n font-size: 11px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n}\n\n.9ee651d9_cardHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.bb118443_cardTitles {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n}\n\n.a1b940d4_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.1870f756_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.e9cfdcad_pillOn,\n.3d3b7405_pillLive,\n.a517f862_pillOff,\n.3e11f4ea_pillRejected {\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.e9cfdcad_pillOn {\n background: var(--dsw-alias-state-success-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.3d3b7405_pillLive {\n border: 1px solid var(--dsw-alias-border-l2);\n color: var(--dsw-alias-label-secondary);\n}\n\n.a517f862_pillOff {\n color: var(--dsw-alias-state-idle-primary);\n}\n\n.3e11f4ea_pillRejected {\n border: 1px solid var(--dsw-alias-state-error-primary, #f85149);\n color: var(--dsw-alias-state-error-primary, #f85149);\n}\n\n/* ---- toggle ---- */\n\n.31ab2dc8_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.31ab2dc8_toggle input {\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n/* ---- fields ---- */\n\n.52ffb01c_field {\n display: grid;\n grid-template-columns: 96px 1fr;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n}\n\n.b8d05488_label {\n color: var(--dsw-alias-label-secondary);\n}\n\n.d8b3bd46_hint {\n grid-column: 2;\n margin-top: -2px;\n font-size: 11px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.0b74e44b_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/* The base look of every input is INLINE too, so these three state rules only\n ever take effect as author-important declarations \u2014 same reason as the\n self-check button above. `cursor` has no inline base and needs none, and the\n hover border uses `l3` because `l1`\u2192`l2` is a 4%\u219210% black step nobody can\n see. */\n\n.0b74e44b_input:hover:not(:disabled) {\n border-color: var(--dsw-alias-border-l3) !important;\n}\n\n.0b74e44b_input:focus {\n border-color: var(--dsw-alias-brand-primary) !important;\n}\n\n.0b74e44b_input:disabled {\n color: var(--dsw-alias-state-idle-primary) !important;\n background: var(--dsw-alias-bg-layer-2) !important;\n cursor: not-allowed;\n}\n\n/* ---- self-check ---- */\n\n/* The hover state is the one thing an inline style cannot express, which is why\n this element carries a class at all. Layout stays inline.\n\n Two traps, both hit before this comment existed:\n - `!important` is load-bearing: the base border and background are INLINE, and\n the cascade sorts a style attribute after every author rule, so a plain\n declaration here would ship, match, and still lose.\n - the TOKENS must be visible ones. `bg-layer-1/2/3` all resolve to\n `neutral-bluish-00` in the light theme, so a layer swap is a no-op there, and\n `border-l1`\u2192`l2` is 4%\u219210% black on a 1px line. The app\'s own hovers use\n `interactive-bg-hover`; using it here is what makes the feedback exist. */\n.47b71ed7_testButton {\n transition: border-color 120ms ease, background 120ms ease;\n}\n\n.47b71ed7_testButton:hover:not(:disabled) {\n border-color: var(--dsw-alias-border-l3) !important;\n background: var(--dsw-alias-interactive-bg-hover) !important;\n}\n\n/* ---- diagnostics ---- */\n\n.f395d2a5_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.84895b20_diagSummary {\n cursor: pointer;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.9ecca3cd_diagList {\n margin: 6px 0 0;\n padding-left: 18px;\n font-family: ui-monospace, monospace;\n word-break: break-all;\n}\n';
48
+ __dshStyle.textContent = '/* dsh-provider-proxy \u2014 provider proxy settings page.\n Tokens only: no literal colours, matching the shared --dsw-* system. */\n\n.b4bf55bf_root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 640px;\n}\n\n.03b72018_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.9a9a9c27_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.6d6907d5_card,\n.a287416b_cardActive,\n.aabaa9b3_cardRejected {\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.a287416b_cardActive {\n border-color: var(--dsw-alias-state-success-primary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n/* An enabled route the Host refused: never dress it as active. */\n.aabaa9b3_cardRejected {\n border-color: var(--dsw-alias-state-error-primary, #f85149);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n/* ---- shared default endpoint ---- */\n\n/* A distinct outer layer, so it reads as "one setting for the page" rather than\n as one more provider card. */\n.ebf26189_defaultCard {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px 16px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-2);\n}\n\n.5b9e9eb5_defaultLead {\n margin: -2px 0 0;\n font-size: 11px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n}\n\n.a3319282_cardHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.6f64c28d_cardTitles {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n}\n\n.847f7e47_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.7864474d_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.7ed5399b_pillOn,\n.0ccb6da5_pillLive,\n.3accadc4_pillOff,\n.86897991_pillRejected {\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.7ed5399b_pillOn {\n background: var(--dsw-alias-state-success-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.0ccb6da5_pillLive {\n border: 1px solid var(--dsw-alias-border-l2);\n color: var(--dsw-alias-label-secondary);\n}\n\n.3accadc4_pillOff {\n color: var(--dsw-alias-state-idle-primary);\n}\n\n.86897991_pillRejected {\n border: 1px solid var(--dsw-alias-state-error-primary, #f85149);\n color: var(--dsw-alias-state-error-primary, #f85149);\n}\n\n/* ---- toggle ---- */\n\n.81025292_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.81025292_toggle input {\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n/* ---- fields ---- */\n\n.5e2577de_field {\n display: grid;\n grid-template-columns: 96px 1fr;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n}\n\n.d9087e9b_label {\n color: var(--dsw-alias-label-secondary);\n}\n\n.aae2a8a2_hint {\n grid-column: 2;\n margin-top: -2px;\n font-size: 11px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.feb8c902_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/* The base look of every input is INLINE too, so these three state rules only\n ever take effect as author-important declarations \u2014 same reason as the\n self-check button above. `cursor` has no inline base and needs none, and the\n hover border uses `l3` because `l1`\u2192`l2` is a 4%\u219210% black step nobody can\n see. */\n\n.feb8c902_input:hover:not(:disabled) {\n border-color: var(--dsw-alias-border-l3) !important;\n}\n\n.feb8c902_input:focus {\n border-color: var(--dsw-alias-brand-primary) !important;\n}\n\n.feb8c902_input:disabled {\n color: var(--dsw-alias-state-idle-primary) !important;\n background: var(--dsw-alias-bg-layer-2) !important;\n cursor: not-allowed;\n}\n\n/* The icon sits inside the input, so its hover/focus feedback must be local\n and must outrank the transparent inline base. */\n.5645283d_passwordToggle {\n transition: background 120ms ease, color 120ms ease;\n}\n\n.5645283d_passwordToggle:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover) !important;\n color: var(--dsw-alias-label-primary) !important;\n}\n\n.5645283d_passwordToggle:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* ---- self-check ---- */\n\n/* The hover state is the one thing an inline style cannot express, which is why\n this element carries a class at all. Layout stays inline.\n\n Two traps, both hit before this comment existed:\n - `!important` is load-bearing: the base border and background are INLINE, and\n the cascade sorts a style attribute after every author rule, so a plain\n declaration here would ship, match, and still lose.\n - the TOKENS must be visible ones. `bg-layer-1/2/3` all resolve to\n `neutral-bluish-00` in the light theme, so a layer swap is a no-op there, and\n `border-l1`\u2192`l2` is 4%\u219210% black on a 1px line. The app\'s own hovers use\n `interactive-bg-hover`; using it here is what makes the feedback exist. */\n.de8ca09a_testButton {\n transition: border-color 120ms ease, background 120ms ease;\n}\n\n.de8ca09a_testButton:hover:not(:disabled) {\n border-color: var(--dsw-alias-border-l3) !important;\n background: var(--dsw-alias-interactive-bg-hover) !important;\n}\n\n/* ---- diagnostics ---- */\n\n.4ad17b9d_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.b2f0759b_diagSummary {\n cursor: pointer;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.f49699bb_diagList {\n margin: 6px 0 0;\n padding-left: 18px;\n font-family: ui-monospace, monospace;\n word-break: break-all;\n}\n';
49
49
  document.head.appendChild(__dshStyle);
50
50
  }
51
51
  var __dshStyle;
@@ -357,7 +357,7 @@ async function fetchCatalog() {
357
357
  };
358
358
  }
359
359
  }
360
- return { rows, hits, problems, lastUse };
360
+ return { rows, publishedRows: rows, hits, problems, lastUse };
361
361
  }
362
362
  var CATALOG_REFRESH_MS = 1e4;
363
363
  var catalogPoll;
@@ -540,6 +540,29 @@ var S = {
540
540
  fontSize: "12px",
541
541
  cursor: "pointer"
542
542
  },
543
+ /** The reveal/hide control sits inside the password field's right edge. */
544
+ passwordControl: {
545
+ position: "relative",
546
+ minWidth: "0"
547
+ },
548
+ passwordToggle: {
549
+ position: "absolute",
550
+ top: "50%",
551
+ right: "4px",
552
+ display: "flex",
553
+ alignItems: "center",
554
+ justifyContent: "center",
555
+ width: "26px",
556
+ height: "26px",
557
+ padding: "0",
558
+ border: "0",
559
+ borderRadius: "6px",
560
+ background: "transparent",
561
+ color: "var(--dsw-alias-label-secondary)",
562
+ lineHeight: "1",
563
+ transform: "translateY(-50%)",
564
+ cursor: "pointer"
565
+ },
543
566
  testResult: {
544
567
  // A flex row so the target can drop onto its own line: the container was a
545
568
  // plain span, where `flexBasis: 100%` does nothing and the target ran into
@@ -566,6 +589,10 @@ var S = {
566
589
  diagProblem: {
567
590
  color: "var(--dsw-alias-state-error-primary, #f85149)"
568
591
  },
592
+ /** Informational catalogue mismatch: not a rejected route, so no error red. */
593
+ diagNote: {
594
+ color: "var(--dsw-alias-label-secondary)"
595
+ },
569
596
  advanced: {
570
597
  marginTop: "4px",
571
598
  fontSize: "12px"
@@ -693,6 +720,7 @@ function renderPage(ctx) {
693
720
  void fetchCatalog().then((catalog) => catalogueSetter?.(catalog)).catch((error) => {
694
721
  catalogueSetter?.({
695
722
  rows: [],
723
+ publishedRows: [],
696
724
  hits: {},
697
725
  problems: {},
698
726
  lastUse: {},
@@ -701,6 +729,7 @@ function renderPage(ctx) {
701
729
  });
702
730
  return {
703
731
  rows: void 0,
732
+ publishedRows: void 0,
704
733
  hits: {},
705
734
  problems: {},
706
735
  lastUse: {},
@@ -710,6 +739,7 @@ function renderPage(ctx) {
710
739
  });
711
740
  catalogueSetter = (catalog) => setState({
712
741
  rows: catalog.rows,
742
+ publishedRows: catalog.publishedRows,
713
743
  hits: catalog.hits,
714
744
  problems: catalog.problems,
715
745
  lastUse: catalog.lastUse,
@@ -718,6 +748,7 @@ function renderPage(ctx) {
718
748
  });
719
749
  touchCatalogPolling();
720
750
  const published = state.rows ?? [];
751
+ const publishedRows = state.publishedRows ?? [];
721
752
  const hits = state.hits ?? {};
722
753
  const lastUse = state.lastUse ?? {};
723
754
  const lastUseText = (id) => {
@@ -731,7 +762,14 @@ function renderPage(ctx) {
731
762
  const problemLines = Object.entries(problems).map(
732
763
  ([id, message]) => h("li", { key: `p:${id}`, style: S.diagProblem }, `${id}\uFF1A${message}`)
733
764
  );
734
- const problemCount = problemLines.length;
765
+ const publishedIds = new Set(publishedRows.map((row) => row.id));
766
+ const missingFromCatalog = state.pending === true || state.error !== void 0 ? [] : Object.keys(configured).filter((id) => !publishedIds.has(id)).sort();
767
+ const catalogueMismatchLine = missingFromCatalog.length === 0 ? void 0 : h(
768
+ "li",
769
+ { key: "catalogue-mismatch", style: S.diagNote },
770
+ `${t.catalogueMismatch}${missingFromCatalog.join("\u3001")}${t.catalogueMismatchSuffix}`
771
+ );
772
+ const problemCount = problemLines.length + (catalogueMismatchLine === void 0 ? 0 : 1);
735
773
  note(
736
774
  `provider \u5217\u8868\uFF1A\u6765\u81EA Host \u5171 ${published.length} \u4E2A\uFF08${published.map((r) => r.id).join("\u3001") || "\u65E0"}\uFF09`
737
775
  );
@@ -741,6 +779,45 @@ function renderPage(ctx) {
741
779
  const [defaultDraft, setDefaultDraft] = (React.useState ?? ((v) => [v, () => {
742
780
  }]))({});
743
781
  const editDefault = (field2, value) => setDefaultDraft((current) => ({ ...current, [field2]: value }));
782
+ const [passwordVisible, setPasswordVisible] = (React.useState ?? ((v) => [v, () => {
783
+ }]))({});
784
+ const [defaultPasswordVisible, setDefaultPasswordVisible] = (React.useState ?? ((v) => [v, () => {
785
+ }]))(false);
786
+ const togglePassword = (id) => setPasswordVisible((current) => ({ ...current, [id]: current[id] !== true }));
787
+ const toggleDefaultPassword = () => setDefaultPasswordVisible((current) => current !== true);
788
+ const passwordToggle = (visible, onToggle) => h(
789
+ "button",
790
+ {
791
+ className: import_client.default.passwordToggle,
792
+ style: S.passwordToggle,
793
+ type: "button",
794
+ "aria-label": visible ? t.hidePassword : t.showPassword,
795
+ "aria-pressed": visible,
796
+ title: visible ? t.hidePassword : t.showPassword,
797
+ onClick: onToggle
798
+ },
799
+ h(
800
+ "svg",
801
+ {
802
+ width: 16,
803
+ height: 16,
804
+ viewBox: "0 0 24 24",
805
+ fill: "none",
806
+ stroke: "currentColor",
807
+ strokeWidth: 2,
808
+ strokeLinecap: "round",
809
+ strokeLinejoin: "round",
810
+ "aria-hidden": "true",
811
+ focusable: "false"
812
+ },
813
+ h("path", {
814
+ key: "eye",
815
+ d: "M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z"
816
+ }),
817
+ h("circle", { key: "pupil", cx: 12, cy: 12, r: 3 }),
818
+ visible ? h("path", { key: "slash", d: "m3 3 18 18" }) : null
819
+ )
820
+ );
744
821
  const [globalDraft, setGlobalDraft] = (React.useState ?? ((v) => [v, () => {
745
822
  }]))({});
746
823
  const editGlobal = (field2, value) => setGlobalDraft((current) => ({ ...current, [field2]: value }));
@@ -924,6 +1001,9 @@ function renderPage(ctx) {
924
1001
  );
925
1002
  };
926
1003
  const promoteToDefault = (id) => {
1004
+ if (defaultComplete && inheritingIds().length > 0 && globalThis.window?.confirm?.(t.confirmPromoteToDefault) !== true) {
1005
+ return;
1006
+ }
927
1007
  const route = view({ ...configured[id], ...draft[id] });
928
1008
  applyDefaultUrl({
929
1009
  protocol: route.protocol,
@@ -945,7 +1025,7 @@ function renderPage(ctx) {
945
1025
  saveMany(
946
1026
  "\0default\0applyAll",
947
1027
  ids.map((id) => ({ op: "set", path: ["providers", id, "useDefault"], value: true })),
948
- "\u6240\u6709 provider \u7684 useDefault",
1028
+ `\u6240\u6709 provider \u7684 useDefault\uFF08${ids.length} \u4E2A\uFF09`,
949
1029
  () => setDraft((current) => {
950
1030
  const next = { ...current };
951
1031
  for (const id of ids) {
@@ -1065,21 +1145,26 @@ function renderPage(ctx) {
1065
1145
  h("input", {
1066
1146
  className: import_client.default.input,
1067
1147
  style: S.input,
1068
- autocomplete: "off",
1148
+ autoComplete: "off",
1069
1149
  value: defaultView.username,
1070
1150
  onChange: (event) => bindDefault("username")(event.target.value)
1071
1151
  })
1072
1152
  ),
1073
1153
  field(
1074
1154
  t.password,
1075
- h("input", {
1076
- className: import_client.default.input,
1077
- style: S.input,
1078
- type: "password",
1079
- autocomplete: "off",
1080
- value: defaultView.password,
1081
- onChange: (event) => bindDefault("password")(event.target.value)
1082
- }),
1155
+ h(
1156
+ "div",
1157
+ { style: S.passwordControl },
1158
+ h("input", {
1159
+ className: import_client.default.input,
1160
+ style: { ...S.input, paddingRight: "36px" },
1161
+ type: defaultPasswordVisible === true ? "text" : "password",
1162
+ autoComplete: "off",
1163
+ value: defaultView.password,
1164
+ onChange: (event) => bindDefault("password")(event.target.value)
1165
+ }),
1166
+ passwordToggle(defaultPasswordVisible === true, toggleDefaultPassword)
1167
+ ),
1083
1168
  t.passwordHintProxy
1084
1169
  ),
1085
1170
  // Bulk opt-in, in ONE write: a per-card walk would rebuild the table N times.
@@ -1097,7 +1182,7 @@ function renderPage(ctx) {
1097
1182
  disabled: !defaultComplete || rows.length === 0,
1098
1183
  onClick: applyDefaultToAll
1099
1184
  },
1100
- t.applyDefaultAll
1185
+ `${t.applyDefaultAll}\uFF08${rows.length}\uFF09`
1101
1186
  )
1102
1187
  )
1103
1188
  );
@@ -1274,7 +1359,7 @@ function renderPage(ctx) {
1274
1359
  h("input", {
1275
1360
  className: import_client.default.input,
1276
1361
  style: S.input,
1277
- autocomplete: "off",
1362
+ autoComplete: "off",
1278
1363
  value: route.username,
1279
1364
  onChange: (event) => bind(row.id, "username")(event.target.value)
1280
1365
  })
@@ -1286,14 +1371,19 @@ function renderPage(ctx) {
1286
1371
  // config; the diagnostics only ever surface a credential-free origin.
1287
1372
  field(
1288
1373
  t.password,
1289
- h("input", {
1290
- className: import_client.default.input,
1291
- style: S.input,
1292
- type: "password",
1293
- autocomplete: "off",
1294
- value: route.password,
1295
- onChange: (event) => bind(row.id, "password")(event.target.value)
1296
- }),
1374
+ h(
1375
+ "div",
1376
+ { style: S.passwordControl },
1377
+ h("input", {
1378
+ className: import_client.default.input,
1379
+ style: { ...S.input, paddingRight: "36px" },
1380
+ type: passwordVisible[row.id] === true ? "text" : "password",
1381
+ autoComplete: "off",
1382
+ value: route.password,
1383
+ onChange: (event) => bind(row.id, "password")(event.target.value)
1384
+ }),
1385
+ passwordToggle(passwordVisible[row.id] === true, () => togglePassword(row.id))
1386
+ ),
1297
1387
  route.protocol === "socks5" ? t.passwordHint : t.passwordHintProxy
1298
1388
  )
1299
1389
  ];
@@ -1567,6 +1657,7 @@ function renderPage(ctx) {
1567
1657
  { className: import_client.default.diagList, style: { margin: "6px 0 0", paddingLeft: "18px" } },
1568
1658
  ...problemCount === 0 && diagnostics.length === 0 && savedNote === void 0 ? [h("li", { key: "none" }, t.diagPending)] : [
1569
1659
  ...problemLines,
1660
+ ...catalogueMismatchLine === void 0 ? [] : [catalogueMismatchLine],
1570
1661
  ...savedNote === void 0 ? [] : [h("li", { key: "saved" }, savedNote)],
1571
1662
  ...diagnostics.map((line, index) => h("li", { key: `d${index}` }, line))
1572
1663
  ]
@@ -1596,6 +1687,9 @@ var EN = {
1596
1687
  port: "Port",
1597
1688
  username: "Username",
1598
1689
  password: "Password",
1690
+ showPassword: "Show",
1691
+ hidePassword: "Hide",
1692
+ confirmPromoteToDefault: "The default proxy is already in use by one or more providers. Replace it with this card's endpoint?",
1599
1693
  hostHint: "Only an IPv4, IPv6, or domain name is allowed. A full proxy URL (socks5://user:pass@host:1080) can be pasted instead \u2014 it is split into the fields.",
1600
1694
  passwordHint: "Sent to the SOCKS5 proxy for authentication; stored with this setting.",
1601
1695
  passwordHintProxy: "Sent to the proxy as an authentication password; stored with this setting.",
@@ -1647,6 +1741,8 @@ var EN = {
1647
1741
  notConfigured: "not configured",
1648
1742
  diagnostics: "Connection diagnostics",
1649
1743
  diagPending: "(collecting\u2026)",
1744
+ catalogueMismatch: "Saved but not listed by the Host catalogue: ",
1745
+ catalogueMismatchSuffix: ". Their proxy settings are kept.",
1650
1746
  saveFailedPrefix: "Save failed: ",
1651
1747
  close: "Close"
1652
1748
  };
@@ -1672,6 +1768,9 @@ var ZH = {
1672
1768
  port: "\u7AEF\u53E3",
1673
1769
  username: "\u7528\u6237\u540D",
1674
1770
  password: "\u5BC6\u7801",
1771
+ showPassword: "\u663E\u793A",
1772
+ hidePassword: "\u9690\u85CF",
1773
+ confirmPromoteToDefault: "\u5DF2\u6709 provider \u6B63\u5728\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406\u3002\u8981\u7528\u8FD9\u5F20\u5361\u7247\u7684\u7AEF\u70B9\u8986\u76D6\u5B83\u5417\uFF1F",
1675
1774
  hostHint: "\u53EA\u5141\u8BB8\u586B\u5199 IPv4\u3001IPv6 \u6216\u57DF\u540D\uFF1B\u4E5F\u53EF\u4EE5\u76F4\u63A5\u7C98\u8D34\u5B8C\u6574\u4EE3\u7406 URL\uFF08\u5982 socks5://user:pass@host:1080\uFF09\uFF0C\u4F1A\u81EA\u52A8\u62C6\u5206\u5230\u5404\u5B57\u6BB5\u3002",
1676
1775
  passwordHint: "\u4EC5\u4F5C\u4E3A SOCKS5 \u8BA4\u8BC1\u53E3\u4EE4\u53D1\u9001\u7ED9\u4EE3\u7406\uFF1B\u968F\u8BE5\u8BBE\u7F6E\u4E00\u8D77\u4FDD\u5B58\u3002",
1677
1776
  passwordHintProxy: "\u4F5C\u4E3A\u4EE3\u7406\u8BA4\u8BC1\u53E3\u4EE4\u53D1\u9001\u7ED9\u4EE3\u7406\uFF1B\u968F\u8BE5\u8BBE\u7F6E\u4E00\u8D77\u4FDD\u5B58\u3002",
@@ -1723,6 +1822,8 @@ var ZH = {
1723
1822
  notConfigured: "\u672A\u914D\u7F6E",
1724
1823
  diagnostics: "\u8FDE\u63A5\u8BCA\u65AD",
1725
1824
  diagPending: "\uFF08\u6B63\u5728\u6536\u96C6\u2026\uFF09",
1825
+ catalogueMismatch: "\u5DF2\u4FDD\u5B58\u4F46\u672A\u51FA\u73B0\u5728 Host \u76EE\u5F55\u4E2D\u7684 provider\uFF1A",
1826
+ catalogueMismatchSuffix: "\u3002\u4EE3\u7406\u914D\u7F6E\u4ECD\u4F1A\u4FDD\u7559\u3002",
1726
1827
  saveFailedPrefix: "\u4FDD\u5B58\u5931\u8D25\uFF1A",
1727
1828
  close: "\u5173\u95ED"
1728
1829
  };
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", "../src/host-rules.ts", "../src/proxy-address.ts"],
4
- "sourcesContent": ["\nvar __dshMap = {\"root\":\"bcf3ba25_root\",\"lead\":\"86cd7a9a_lead\",\"empty\":\"4ec3d74d_empty\",\"card\":\"61dfce67_card\",\"cardActive\":\"56b6c433_cardActive\",\"cardRejected\":\"24b300e2_cardRejected\",\"defaultCard\":\"665ef72b_defaultCard\",\"defaultLead\":\"351db191_defaultLead\",\"cardHead\":\"9ee651d9_cardHead\",\"cardTitles\":\"bb118443_cardTitles\",\"name\":\"a1b940d4_name\",\"id\":\"1870f756_id\",\"pillOn\":\"e9cfdcad_pillOn\",\"pillLive\":\"3d3b7405_pillLive\",\"pillOff\":\"a517f862_pillOff\",\"pillRejected\":\"3e11f4ea_pillRejected\",\"toggle\":\"31ab2dc8_toggle\",\"field\":\"52ffb01c_field\",\"label\":\"b8d05488_label\",\"hint\":\"d8b3bd46_hint\",\"input\":\"0b74e44b_input\",\"testButton\":\"47b71ed7_testButton\",\"diag\":\"f395d2a5_diag\",\"diagSummary\":\"84895b20_diagSummary\",\"diagList\":\"9ecca3cd_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.bcf3ba25_root {\\n display: flex;\\n flex-direction: column;\\n gap: 12px;\\n max-width: 640px;\\n}\\n\\n.86cd7a9a_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.4ec3d74d_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.61dfce67_card,\\n.56b6c433_cardActive,\\n.24b300e2_cardRejected {\\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.56b6c433_cardActive {\\n border-color: var(--dsw-alias-state-success-primary);\\n background: var(--dsw-alias-bg-layer-2);\\n}\\n\\n/* An enabled route the Host refused: never dress it as active. */\\n.24b300e2_cardRejected {\\n border-color: var(--dsw-alias-state-error-primary, #f85149);\\n background: var(--dsw-alias-bg-layer-2);\\n}\\n\\n/* ---- shared default endpoint ---- */\\n\\n/* A distinct outer layer, so it reads as \\\"one setting for the page\\\" rather than\\n as one more provider card. */\\n.665ef72b_defaultCard {\\n display: flex;\\n flex-direction: column;\\n gap: 10px;\\n padding: 14px 16px;\\n border: 1px solid var(--dsw-alias-border-l2);\\n border-radius: 10px;\\n background: var(--dsw-alias-bg-layer-2);\\n}\\n\\n.351db191_defaultLead {\\n margin: -2px 0 0;\\n font-size: 11px;\\n line-height: 1.5;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.9ee651d9_cardHead {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n gap: 12px;\\n}\\n\\n.bb118443_cardTitles {\\n display: flex;\\n align-items: baseline;\\n gap: 8px;\\n min-width: 0;\\n}\\n\\n.a1b940d4_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.1870f756_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.e9cfdcad_pillOn,\\n.3d3b7405_pillLive,\\n.a517f862_pillOff,\\n.3e11f4ea_pillRejected {\\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.e9cfdcad_pillOn {\\n background: var(--dsw-alias-state-success-primary);\\n color: var(--dsw-alias-bg-base);\\n}\\n\\n.3d3b7405_pillLive {\\n border: 1px solid var(--dsw-alias-border-l2);\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.a517f862_pillOff {\\n color: var(--dsw-alias-state-idle-primary);\\n}\\n\\n.3e11f4ea_pillRejected {\\n border: 1px solid var(--dsw-alias-state-error-primary, #f85149);\\n color: var(--dsw-alias-state-error-primary, #f85149);\\n}\\n\\n/* ---- toggle ---- */\\n\\n.31ab2dc8_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.31ab2dc8_toggle input {\\n accent-color: var(--dsw-alias-brand-primary);\\n cursor: pointer;\\n}\\n\\n/* ---- fields ---- */\\n\\n.52ffb01c_field {\\n display: grid;\\n grid-template-columns: 96px 1fr;\\n align-items: center;\\n gap: 10px;\\n font-size: 12px;\\n}\\n\\n.b8d05488_label {\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.d8b3bd46_hint {\\n grid-column: 2;\\n margin-top: -2px;\\n font-size: 11px;\\n color: var(--dsw-alias-state-warn-primary);\\n}\\n\\n.0b74e44b_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/* The base look of every input is INLINE too, so these three state rules only\\n ever take effect as author-important declarations \u2014 same reason as the\\n self-check button above. `cursor` has no inline base and needs none, and the\\n hover border uses `l3` because `l1`\u2192`l2` is a 4%\u219210% black step nobody can\\n see. */\\n\\n.0b74e44b_input:hover:not(:disabled) {\\n border-color: var(--dsw-alias-border-l3) !important;\\n}\\n\\n.0b74e44b_input:focus {\\n border-color: var(--dsw-alias-brand-primary) !important;\\n}\\n\\n.0b74e44b_input:disabled {\\n color: var(--dsw-alias-state-idle-primary) !important;\\n background: var(--dsw-alias-bg-layer-2) !important;\\n cursor: not-allowed;\\n}\\n\\n/* ---- self-check ---- */\\n\\n/* The hover state is the one thing an inline style cannot express, which is why\\n this element carries a class at all. Layout stays inline.\\n\\n Two traps, both hit before this comment existed:\\n - `!important` is load-bearing: the base border and background are INLINE, and\\n the cascade sorts a style attribute after every author rule, so a plain\\n declaration here would ship, match, and still lose.\\n - the TOKENS must be visible ones. `bg-layer-1/2/3` all resolve to\\n `neutral-bluish-00` in the light theme, so a layer swap is a no-op there, and\\n `border-l1`\u2192`l2` is 4%\u219210% black on a 1px line. The app's own hovers use\\n `interactive-bg-hover`; using it here is what makes the feedback exist. */\\n.47b71ed7_testButton {\\n transition: border-color 120ms ease, background 120ms ease;\\n}\\n\\n.47b71ed7_testButton:hover:not(:disabled) {\\n border-color: var(--dsw-alias-border-l3) !important;\\n background: var(--dsw-alias-interactive-bg-hover) !important;\\n}\\n\\n/* ---- diagnostics ---- */\\n\\n.f395d2a5_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.84895b20_diagSummary {\\n cursor: pointer;\\n color: var(--dsw-alias-state-warn-primary);\\n}\\n\\n.9ecca3cd_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\nimport { deadRuleEntries } from './host-rules.js'\r\nimport { defaultProxyProblem, proxyHostProblem } from './proxy-address.js'\r\n\r\ntype Protocol = 'http' | 'https' | 'socks5'\r\n\r\ntype RouteValue = {\r\n enabled: boolean\r\n useDefault: boolean\r\n protocol: Protocol\r\n host: string\r\n port: number\r\n username: string\r\n password: string\r\n onlyHosts: string\r\n bypassHosts: string\r\n testTarget: 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: () => '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 const byId = new Map<string, ProviderRow>()\r\n for (const row of published) {\r\n byId.set(row.id, row)\r\n if (row.live) rows.set(row.id, row)\r\n }\r\n for (const id of Object.keys(configured)) {\r\n if (rows.has(id)) continue\r\n // A saved route must stay visible, but switching the proxy ON does not make\r\n // its provider live. `live` comes from the Host catalogue exclusively; using\r\n // `route.enabled` here made a card flip between \"offline\" and \"proxied\" as\r\n // the user toggled the switch, while no provider became available at all.\r\n const known = byId.get(id)\r\n rows.set(id, { id, name: known?.name ?? id, live: known?.live === 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/** Where the Host runs a per-provider connection self-check. */\r\nconst TEST_PATH = '/dsh-provider-proxy/test'\r\n\r\n/**\r\n * Latency bands for the self-check result, in milliseconds.\r\n *\r\n * The colour is decoration, never information: the numeric value is always\r\n * printed, so an unknown theme token (which resolves to `unset`) costs colour,\r\n * never the reading. The `var(..., fallback)` form keeps the colours visible even\r\n * if the theme renames the token.\r\n */\r\nconst LATENCY_FAST_MS = 500\r\nconst LATENCY_SLOW_MS = 1500\r\n/** The schema default for `testUrl`; also what \"Restore default\" writes. */\r\nconst DEFAULT_TEST_URL = 'https://api.ipify.org?format=json'\r\nconst MAX_TEST_URLS = 5\r\n\r\nfunction latencyColor(ms: unknown): string {\r\n if (typeof ms !== 'number' || !Number.isFinite(ms)) return 'var(--dsw-alias-label-secondary)'\r\n if (ms <= LATENCY_FAST_MS) return 'var(--dsw-alias-state-success-primary, #2ea043)'\r\n if (ms <= LATENCY_SLOW_MS) return 'var(--dsw-alias-state-warn-primary, #d29922)'\r\n return 'var(--dsw-alias-state-error-primary, #f85149)'\r\n}\r\n\r\n/** Normalize the Host's self-check payload into the shape the card renders. */\r\nfunction testResultFrom(body: any, strings: Record<string, string>): Record<string, unknown> {\r\n const ok = body?.ok === true\r\n return {\r\n pending: false,\r\n ok,\r\n ms: typeof body?.ms === 'number' && Number.isFinite(body.ms) ? body.ms : undefined,\r\n ip: typeof body?.exitIp === 'string' && body.exitIp.length > 0 ? body.exitIp : undefined,\r\n status:\r\n typeof body?.status === 'number' && Number.isInteger(body.status) ? body.status : undefined,\r\n target: typeof body?.target === 'string' && body.target.length > 0 ? body.target : undefined,\r\n targetSource:\r\n body?.targetSource === 'route' || body?.targetSource === 'upstream'\r\n ? body.targetSource\r\n : body?.targetSource === 'testUrl'\r\n ? 'testUrl'\r\n : undefined,\r\n cached: body?.cached === true,\r\n // The Host probes a target the way routing would: a loopback/private upstream\r\n // (or a bypassHosts match) is reached DIRECT, not through the proxy. The card\r\n // says so, so a green check is not read as \"the proxy works\".\r\n direct: body?.viaProxy === false,\r\n error: ok\r\n ? undefined\r\n : typeof body?.error === 'string' && body.error.length > 0\r\n ? body.error\r\n : strings.testFailed,\r\n }\r\n}\r\n\r\n/** Split `testUrl` the same way the Host does: commas or whitespace. */\r\nfunction splitTestUrls(raw: string): string[] {\r\n return raw\r\n .split(/[,\\s]+/)\r\n .map(entry => entry.trim())\r\n .filter(entry => entry.length > 0)\r\n}\r\n\r\n/**\r\n * Hint-only validation for `testUrl`.\r\n *\r\n * The Host does not refuse malformed candidates; it simply fails that check.\r\n * The page therefore warns without blocking the write, so a user can still save\r\n * a value the Host accepts (including an empty string, which means \"use the\r\n * built-in default\").\r\n */\r\nfunction testUrlHint(raw: string, t: Record<string, string>): string | undefined {\r\n const entries = splitTestUrls(raw)\r\n if (entries.length === 0) return t.testUrlEmptyHint\r\n const invalid = entries.filter(entry => !isAbsoluteHttpUrl(entry))\r\n if (invalid.length > 0) return t.testUrlInvalidHint\r\n if (entries.length > MAX_TEST_URLS) return t.testUrlTooManyHint\r\n return undefined\r\n}\r\n\r\nfunction isAbsoluteHttpUrl(value: string): boolean {\r\n try {\r\n const url = new URL(value)\r\n return (url.protocol === 'http:' || url.protocol === 'https:') && url.hostname.length > 0\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * Where the check's target came from, in the card's own words.\r\n *\r\n * The target is NOT always the top-level `testUrl`: a route's own\r\n * `testTarget` wins, then the provider's REAL upstream, and only a provider\r\n * that publishes none falls back to `testUrl`. Saying so is what explains why\r\n * editing `testUrl` changed one card and not another.\r\n */\r\nfunction targetSourceSuffix(\r\n result: { targetSource?: unknown },\r\n t: Record<string, string>,\r\n): string {\r\n switch (result.targetSource) {\r\n case 'route':\r\n return t.targetSourceRoute\r\n case 'upstream':\r\n return t.targetSourceUpstream\r\n case 'testUrl':\r\n return t.targetSourceTestUrl\r\n default:\r\n return ''\r\n }\r\n}\r\n\r\n/**\r\n * Remove values and URL credentials from text that will be shown to the user.\r\n *\r\n * Settings errors may quote the rejected value. A password field must never\r\n * echo that value, even inside an otherwise useful error message, so exact\r\n * known secrets are replaced before anything is rendered or written to the\r\n * diagnostics panel.\r\n */\r\nfunction redactSensitiveText(text: string, secrets: readonly unknown[] = []): string {\r\n let safe = text\r\n for (const secret of secrets) {\r\n if (typeof secret !== 'string' || secret.length === 0) continue\r\n safe = safe.split(secret).join('***')\r\n }\r\n // A URL in an error may carry userinfo and query/fragment values even when\r\n // the individual secret is not known to this call.\r\n safe = safe.replace(/\\b([a-z][a-z0-9+.-]*:\\/\\/)[^/@\\s]+@/gi, '$1')\r\n safe = safe.replace(/([?&#])[^\\s\"'<>]*/g, '$1')\r\n return safe.length > 500 ? `${safe.slice(0, 500)}\u2026` : safe\r\n}\r\n\r\n/** Values that may be echoed by a failed multi-field write. */\r\nfunction secretsFromOps(ops: readonly any[]): string[] {\r\n const out: string[] = []\r\n for (const op of ops) {\r\n const field = op?.path?.[op.path.length - 1]\r\n if (field === 'password' && typeof op?.value === 'string' && op.value.length > 0) {\r\n out.push(op.value)\r\n }\r\n }\r\n return out\r\n}\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: ((catalog: Catalog) => void) | undefined = () => {}\r\n\r\n/** How one provider's last proxied request ended, as the Host recorded it. */\r\ntype LastUse = {\r\n /** When the most recent proxied request BEGAN. */\r\n startedAt?: number\r\n /** When the last request that FINISHED ended; paired with `ok`/`code`. */\r\n at?: number\r\n ok?: boolean\r\n code?: string\r\n}\r\n\r\n/** What the Host endpoint publishes: provider rows, hit counts, rejected routes. */\r\ntype Catalog = {\r\n rows: ProviderRow[]\r\n hits: Record<string, number>\r\n problems: Record<string, string>\r\n lastUse: Record<string, LastUse>\r\n /** Set when the FIRST read failed; a later successful poll clears it. */\r\n error?: string\r\n}\r\n\r\n/**\r\n * A coarse \"how long ago\", for the last-use line.\r\n *\r\n * Deliberately coarse: the page only re-reads the catalogue every 10 s, so a\r\n * second-precision string would look stale on its own and mean nothing.\r\n */\r\nfunction relativeTime(at: number, t: Record<string, string>): string {\r\n const seconds = Math.max(0, Math.round((Date.now() - at) / 1000))\r\n if (seconds < 60) return t.justNow\r\n const minutes = Math.floor(seconds / 60)\r\n if (minutes < 60) return `${minutes}${t.minutesAgo}`\r\n const hours = Math.floor(minutes / 60)\r\n if (hours < 24) return `${hours}${t.hoursAgo}`\r\n return `${Math.floor(hours / 24)}${t.daysAgo}`\r\n}\r\n\r\n/** Read the Host's provider catalogue. Same-origin, so no token is needed. */\r\nasync function fetchCatalog(): Promise<Catalog> {\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 const rows = 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 // The Host counts requests it routed through each provider's proxy. Anything\r\n // malformed is dropped rather than rendered, so a bad payload cannot put a\r\n // non-numeric string on the page.\r\n const hits: Record<string, number> = {}\r\n const published = body?.hits\r\n if (published !== null && typeof published === 'object') {\r\n for (const [id, count] of Object.entries(published)) {\r\n if (typeof count === 'number' && Number.isFinite(count)) hits[id] = count\r\n }\r\n }\r\n // A route the Host REFUSED (a bad port, half-filled credentials) is absent from\r\n // the provider list entirely, so this map is the only place that says why it is\r\n // missing. The Host already stripped the log prefix from it.\r\n const problems: Record<string, string> = {}\r\n const rejected = body?.problems\r\n if (rejected !== null && typeof rejected === 'object') {\r\n for (const [id, message] of Object.entries(rejected)) {\r\n if (typeof message === 'string' && message.length > 0) problems[id] = message\r\n }\r\n }\r\n // The last-use record: when each provider's most recent proxied request\r\n // began, and \u2014 separately \u2014 how the last request that FINISHED ended. Anything\r\n // malformed is dropped rather than rendered, so a bad payload cannot put a\r\n // non-numeric timestamp on the page. An entry carrying only `startedAt` is\r\n // kept: it is a request still in flight, and the page says when it was started.\r\n const lastUse: Record<string, LastUse> = {}\r\n const publishedLastUse = body?.lastUse\r\n if (publishedLastUse !== null && typeof publishedLastUse === 'object') {\r\n for (const [id, raw] of Object.entries(publishedLastUse)) {\r\n const entry = raw as LastUse | undefined\r\n if (entry === null || typeof entry !== 'object') continue\r\n const at = typeof entry.at === 'number' && Number.isFinite(entry.at) ? entry.at : undefined\r\n const startedAt =\r\n typeof entry.startedAt === 'number' && Number.isFinite(entry.startedAt)\r\n ? entry.startedAt\r\n : undefined\r\n if (at === undefined && startedAt === undefined) continue\r\n lastUse[id] = {\r\n ...(startedAt === undefined ? {} : { startedAt }),\r\n ...(at === undefined ? {} : { at }),\r\n ...(typeof entry.ok === 'boolean' ? { ok: entry.ok } : {}),\r\n ...(typeof entry.code === 'string' && entry.code.length > 0 ? { code: entry.code } : {}),\r\n }\r\n }\r\n }\r\n return { rows, hits, problems, lastUse }\r\n}\r\n\r\n/**\r\n * Catalogue polling while the page is open.\r\n *\r\n * The catalogue (published rows, hit counts, rejected routes) is fetched once at\r\n * mount and would otherwise stay a snapshot for the page's lifetime: the hit\r\n * counter never moves, and a route the Host starts or stops refusing stays\r\n * invisible. One shared interval re-fetches it every CATALOG_REFRESH_MS.\r\n *\r\n * `touchCatalogPolling` runs on every render. Writing the module-level timestamp\r\n * there is deliberately not treated as a render side effect: it is idempotent,\r\n * re-enters nothing (unlike a setState during render), and it is the only signal\r\n * that the page is still alive. A page that stops rendering \u2014 a closed panel \u2014\r\n * goes stale, and the next tick cancels the interval instead of fetching for\r\n * nobody. A failed poll is swallowed: the page keeps its last data, and the\r\n * mount-time fetch already reports a broken endpoint in the diagnostics.\r\n */\r\nconst CATALOG_REFRESH_MS = 10_000\r\nlet catalogPoll: ReturnType<typeof setInterval> | undefined\r\nlet catalogTouchedAt = 0\r\n\r\nfunction touchCatalogPolling(): void {\r\n catalogTouchedAt = Date.now()\r\n if (catalogPoll !== undefined) return\r\n catalogPoll = setInterval(() => {\r\n if (Date.now() - catalogTouchedAt > CATALOG_REFRESH_MS * 2 + 1_000) {\r\n clearInterval(catalogPoll)\r\n catalogPoll = undefined\r\n return\r\n }\r\n void fetchCatalog()\r\n .then(catalog => catalogueSetter?.(catalog))\r\n .catch(() => undefined)\r\n }, CATALOG_REFRESH_MS)\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 useDefault: route?.useDefault === 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 onlyHosts: route?.onlyHosts ?? '',\r\n bypassHosts: route?.bypassHosts ?? '',\r\n testTarget: route?.testTarget ?? '',\r\n }\r\n}\r\n\r\n/** Drop the brackets WHATWG URL keeps on an IPv6 literal host. */\r\nfunction unbracket(hostname: string): string {\r\n return hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname\r\n}\r\n\r\n/**\r\n * Split a pasted full proxy URL into route fields, or `undefined` when the text\r\n * is not one.\r\n *\r\n * `socks5` is a NON-special scheme, so WHATWG URL still parses its userinfo and\r\n * port (verified), but three quirks are handled here:\r\n * - the userinfo is NOT percent-decoded by the parser, so it is decoded here;\r\n * - an IPv6 literal comes back bracketed, and the host field wants it bare;\r\n * - a DEFAULT port is stripped by WHATWG for http/https; the original text is\r\n * consulted so an explicitly written :80/:443 is preserved, while an absent\r\n * port still stays 0 (\"not configured\") instead of being invented.\r\n */\r\nfunction explicitPortOf(text: string): number {\r\n const authority = text.slice(text.indexOf('://') + 3).split(/[/?#]/, 1)[0]\r\n const hostPort = authority.slice(authority.lastIndexOf('@') + 1)\r\n const match = /^\\[[^\\]]+\\]:(\\d+)$/.exec(hostPort) ?? /^[^:]+:(\\d+)$/.exec(hostPort)\r\n if (match === null) return 0\r\n const port = Number.parseInt(match[1], 10)\r\n return Number.isNaN(port) ? 0 : port\r\n}\r\n\r\nfunction splitProxyUrl(text: string): Partial<RouteValue> | undefined {\r\n const trimmed = text.trim()\r\n if (!/^[a-z][a-z0-9+.-]*:\\/\\//i.test(trimmed)) return undefined\r\n let url: URL\r\n try {\r\n url = new URL(trimmed)\r\n } catch {\r\n return undefined\r\n }\r\n const scheme = url.protocol.slice(0, -1).toLowerCase()\r\n // `socks://` is a common spelling this plugin does not accept on its own;\r\n // normalizing it here means a pasted alias still lands on the supported\r\n // transport instead of being rejected later.\r\n const protocol = scheme === 'socks' ? 'socks5' : scheme\r\n if (!PROTOCOLS.includes(protocol as Protocol)) return undefined\r\n if (url.hostname.length === 0) return undefined\r\n const decode = (value: string): string => {\r\n try {\r\n return decodeURIComponent(value)\r\n } catch {\r\n return value\r\n }\r\n }\r\n const parsedPort = url.port.length > 0\r\n ? Number.parseInt(url.port, 10)\r\n : explicitPortOf(trimmed)\r\n return {\r\n protocol: protocol as Protocol,\r\n host: unbracket(url.hostname),\r\n port: Number.isNaN(parsedPort) ? 0 : parsedPort,\r\n username: decode(url.username),\r\n password: decode(url.password),\r\n }\r\n}\r\n\r\n/**\r\n * Pending writes, one debounced timer per provider+field.\r\n *\r\n * Every keystroke of an input fires `bind`, and the Host rebuilds its whole\r\n * proxy table on each settings write (`loader/volatile-update` \u2192 `rebuild()`).\r\n * Writing per keystroke therefore churns a dispatcher generation per character \u2014\r\n * and, worse, a half-typed credential (\"username without a password\") hits the\r\n * Host guards between keystrokes, so the route is refused for an instant and a\r\n * misleading problem is recorded. Only the LAST value of a burst needs to reach\r\n * the Host; the draft already gives the control its instant feedback.\r\n *\r\n * Module-level, so the timers survive a re-render (each pass rebuilds `save`)\r\n * and a page unmount: a write that was already promised still lands.\r\n */\r\nconst WRITE_DELAY_MS = 300\r\ntype PendingWrite = { timer?: ReturnType<typeof setTimeout>; flush: () => Promise<void> }\r\nconst pendingWrites = new Map<string, PendingWrite>()\r\n\r\n/**\r\n * Writes are serialized so a test can await every write it flushed without\r\n * racing the settings revision fence. A run handles its own failures, so the\r\n * tail never rejects the next write.\r\n */\r\nlet writeQueue: Promise<void> = Promise.resolve()\r\nfunction enqueueWrite(run: () => Promise<void>): Promise<void> {\r\n const next = writeQueue.then(run, run)\r\n writeQueue = next.catch(() => undefined)\r\n return next\r\n}\r\n\r\n/** Schedule one debounced write; `flush` runs it immediately and only once. */\r\nfunction scheduleWrite(key: string, run: () => Promise<void>): void {\r\n const pending = pendingWrites.get(key)\r\n if (pending?.timer !== undefined) clearTimeout(pending.timer)\r\n const entry: PendingWrite = {\r\n flush: () => {\r\n if (entry.timer !== undefined) clearTimeout(entry.timer)\r\n pendingWrites.delete(key)\r\n return enqueueWrite(run)\r\n },\r\n }\r\n entry.timer = setTimeout(() => { void entry.flush() }, WRITE_DELAY_MS)\r\n pendingWrites.set(key, entry)\r\n}\r\n\r\n/**\r\n * A self-check result belongs to the configuration it was measured against.\r\n * Every relevant edit bumps this counter; a response that started under an older\r\n * generation is discarded instead of being pasted onto the new settings.\r\n */\r\nconst testGeneration = new Map<string, number>()\r\nconst TEST_RELEVANT_FIELDS = new Set([\r\n 'protocol',\r\n 'host',\r\n 'port',\r\n 'username',\r\n 'password',\r\n 'onlyHosts',\r\n 'bypassHosts',\r\n 'testTarget',\r\n 'useDefault',\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 /** An enabled route the Host refused: active-looking styling would be a lie. */\r\n cardRejected: {\r\n borderColor: 'var(--dsw-alias-state-error-primary, #f85149)',\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 hits: {\r\n flex: 'none',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n whiteSpace: 'nowrap',\r\n },\r\n testRow: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '10px',\r\n flexWrap: 'wrap',\r\n },\r\n testButton: {\r\n padding: '5px 12px',\r\n border: '1px solid var(--dsw-alias-border-l1)',\r\n borderRadius: '6px',\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 cursor: 'pointer',\r\n },\r\n testResult: {\r\n // A flex row so the target can drop onto its own line: the container was a\r\n // plain span, where `flexBasis: 100%` does nothing and the target ran into\r\n // the \"cached\" label.\r\n display: 'flex',\r\n flexWrap: 'wrap',\r\n alignItems: 'baseline',\r\n columnGap: '6px',\r\n rowGap: '2px',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n wordBreak: 'break-all',\r\n },\r\n /**\r\n * A failed check is the answer, not decoration: it takes the error colour and\r\n * a heavier weight, unlike the latency band colour which only tints a number\r\n * that is printed anyway.\r\n */\r\n testFailure: {\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n fontWeight: '500',\r\n },\r\n /** A rejected route is a failure of the settings, not a warning about them. */\r\n diagProblem: {\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n },\r\n advanced: {\r\n marginTop: '4px',\r\n fontSize: '12px',\r\n },\r\n advancedSummary: {\r\n cursor: 'pointer',\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 pillRejected: {\r\n border: '1px solid var(--dsw-alias-state-error-primary, #f85149)',\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n },\r\n /**\r\n * The shared default endpoint sits on its own layer so it reads as global\r\n * rather than as one more provider card \u2014 the mistake it exists to prevent is\r\n * a user typing the same address into every card.\r\n */\r\n defaultCard: {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '10px',\r\n padding: '14px 16px',\r\n border: '1px solid var(--dsw-alias-border-l2)',\r\n borderRadius: '10px',\r\n background: 'var(--dsw-alias-bg-layer-2)',\r\n },\r\n defaultLead: {\r\n margin: '-2px 0 0',\r\n fontSize: '11px',\r\n lineHeight: '1.5',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n },\r\n inheritNote: {\r\n margin: '0',\r\n fontSize: '11px',\r\n lineHeight: '1.5',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n },\r\n /** The default is not configured: an answer, so it takes the error colour. */\r\n inheritWarning: {\r\n margin: '0',\r\n fontSize: '11px',\r\n lineHeight: '1.5',\r\n fontWeight: '500',\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n },\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 diag: {\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 hint: {\r\n gridColumn: '2',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\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 fetchCatalog()\r\n .then(catalog => catalogueSetter?.(catalog))\r\n .catch((error: any) => {\r\n catalogueSetter?.({\r\n rows: [],\r\n hits: {},\r\n problems: {},\r\n lastUse: {},\r\n error: String(error?.message ?? error),\r\n })\r\n })\r\n return {\r\n rows: undefined as ProviderRow[] | undefined,\r\n hits: {} as Record<string, number>,\r\n problems: {} as Record<string, string>,\r\n lastUse: {} as Record<string, LastUse>,\r\n error: undefined as string | undefined,\r\n pending: true,\r\n }\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 = catalog =>\r\n setState({\r\n rows: catalog.rows,\r\n hits: catalog.hits,\r\n problems: catalog.problems,\r\n lastUse: catalog.lastUse,\r\n error: catalog.error,\r\n pending: false,\r\n })\r\n // Keeps the catalogue (rows, hit counts, rejected routes) current while the\r\n // page is open; see the function's own notes for the staleness handling.\r\n touchCatalogPolling()\r\n\r\n const published = state.rows ?? []\r\n const hits = state.hits ?? {}\r\n const lastUse = state.lastUse ?? {}\r\n\r\n /**\r\n * The one-line last-use summary for a card, or `undefined` when the route has\r\n * never carried a request. `hits` says the route HAS been used; this says\r\n * whether it still works \u2014 the question a silently stalled proxy raises.\r\n *\r\n * A success or failure uses `at`, the time the last request FINISHED \u2014 the\r\n * time its outcome belongs to. A request that has only STARTED uses\r\n * `startedAt`, so a still-in-flight call cannot make the page claim an outcome\r\n * it does not have yet.\r\n */\r\n const lastUseText = (id: string): string | undefined => {\r\n const use = lastUse[id]\r\n if (use === undefined) return undefined\r\n if (use.ok === true) return `${t.recentOk}${relativeTime(use.at ?? use.startedAt ?? Date.now(), t)}`\r\n if (use.ok === false) return `${t.recentFail}${use.code ?? 'ERROR'}`\r\n return `${t.recentStarted}${relativeTime(use.startedAt ?? use.at ?? Date.now(), t)}`\r\n }\r\n // Rendered straight from state rather than through `note()`: `diagnostics` is\r\n // cleared at the start of every render, so a note written when the catalog\r\n // arrives would not survive to the next pass.\r\n const problems = state.problems ?? {}\r\n const problemLines = Object.entries(problems).map(([id, message]) =>\r\n h('li', { key: `p:${id}`, style: S.diagProblem }, `${id}\uFF1A${message}`),\r\n )\r\n const problemCount = problemLines.length\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 /**\r\n * The shared default endpoint gets its own draft for the same reason a card\r\n * does: its controls must show an edit before the debounced write lands.\r\n *\r\n * It is deliberately NOT stored under a sentinel key inside `draft`:\r\n * `knownProviders` unions the stored config with the draft to build the card\r\n * list, so such a key would surface as a phantom provider with no name.\r\n */\r\n const [defaultDraft, setDefaultDraft] = (React.useState ?? ((v: any) => [v, () => {}]))({})\r\n const editDefault = (field: string, value: unknown) =>\r\n setDefaultDraft((current: any) => ({ ...current, [field]: value }))\r\n\r\n /**\r\n * The advanced global fields live outside `draft` on purpose: `draft` is keyed\r\n * by provider id, and a sentinel would surface as a phantom provider row.\r\n */\r\n const [globalDraft, setGlobalDraft] = (React.useState ?? ((v: any) => [v, () => {}]))({})\r\n const editGlobal = (field: string, value: unknown) =>\r\n setGlobalDraft((current: any) => ({ ...current, [field]: value }))\r\n\r\n /** The latest refused write, shown above the cards instead of in the fold. */\r\n const [saveError, setSaveError] = (React.useState ?? ((v: any) => [v, () => {}]))(undefined)\r\n /** The latest accepted write, rendered in the diagnostics on the next pass. */\r\n const [savedNote, setSavedNote] = (React.useState ?? ((v: any) => [v, () => {}]))(undefined)\r\n\r\n // Self-check outcomes keyed by provider id: `{ pending: true }` while the Host\r\n // is testing, then the normalized result the card renders.\r\n const [tests, setTests] = (React.useState ?? ((v: any) => [v, () => {}]))({})\r\n\r\n /** Drop results for these providers and invalidate any response in flight. */\r\n const invalidateTests = (ids: readonly string[]): void => {\r\n if (ids.length === 0) return\r\n for (const id of ids) {\r\n testGeneration.set(id, (testGeneration.get(id) ?? 0) + 1)\r\n }\r\n setTests((current: any) => {\r\n let changed = false\r\n const next = { ...current }\r\n for (const id of ids) {\r\n if (next[id] === undefined) continue\r\n delete next[id]\r\n changed = true\r\n }\r\n return changed ? next : current\r\n })\r\n }\r\n\r\n /**\r\n * The list filter. Purely a view concern: it hides cards, it never touches a\r\n * saved setting, so a page with no filter one day still shows every route.\r\n */\r\n const [filter, setFilter] = (React.useState ?? ((v: any) => [v, () => {}]))('')\r\n\r\n /**\r\n * Run the Host's self-check for one provider.\r\n *\r\n * The check is not routed traffic, so it never changes the hit count; the count\r\n * on the card is read at mount and stays put until the page reloads.\r\n *\r\n * Pending writes for this provider (and the shared default it may inherit) are\r\n * flushed before the request: the Host reads the saved settings, not the draft,\r\n * so testing inside the 300 ms debounce would otherwise test the old endpoint.\r\n */\r\n const runTest = (id: string): void => {\r\n const generation = (testGeneration.get(id) ?? 0) + 1\r\n testGeneration.set(id, generation)\r\n setTests((current: any) => ({ ...current, [id]: { pending: true } }))\r\n void (async () => {\r\n try {\r\n for (const [key, entry] of [...pendingWrites]) {\r\n if (\r\n key.startsWith(`${id}\\u0000`) ||\r\n key.startsWith('\\u0000default\\u0000') ||\r\n key.startsWith('\\u0000global\\u0000')\r\n ) {\r\n void entry.flush()\r\n }\r\n }\r\n await writeQueue\r\n if (testGeneration.get(id) !== generation) return\r\n const response = await globalThis.fetch(TEST_PATH, {\r\n method: 'POST',\r\n headers: { 'content-type': 'application/json', accept: 'application/json' },\r\n body: JSON.stringify({ provider: id }),\r\n })\r\n const body = await response.json()\r\n if (testGeneration.get(id) !== generation) return\r\n setTests((current: any) => ({ ...current, [id]: testResultFrom(body, t) }))\r\n } catch (error: any) {\r\n if (testGeneration.get(id) !== generation) return\r\n setTests((current: any) => ({\r\n ...current,\r\n [id]: { pending: false, ok: false, error: String(error?.message ?? error) },\r\n }))\r\n }\r\n })()\r\n }\r\n\r\n const rows = knownProviders({ ...configured, ...draft }, published)\r\n\r\n /** Cards whose effective endpoint comes from the shared default. */\r\n const inheritingIds = (): string[] =>\r\n rows\r\n .filter(row => view({ ...configured[row.id], ...draft[row.id] }).useDefault === true)\r\n .map(row => row.id)\r\n\r\n /**\r\n * Persist one field, debounced per `key`: a burst of edits to the same control\r\n * collapses into ONE write carrying the last value. The control already shows\r\n * the new value via the draft, so this only has to succeed quietly; a refusal\r\n * is reported in the diagnostics and undone by `onRefused`.\r\n */\r\n const save = (\r\n key: string,\r\n path: unknown[],\r\n label: string,\r\n value: unknown,\r\n onRefused: () => void,\r\n ) => {\r\n const field = path[path.length - 1]\r\n const secret = field === 'password' && typeof value === 'string' ? value : undefined\r\n const safeLabel = secret === undefined ? label : `${label}\uFF08\u503C\u5DF2\u9690\u85CF\uFF09`\r\n scheduleWrite(key, () =>\r\n writeConfig(ctx, [{ op: 'set', path, value }])\r\n .then(() => {\r\n setSaveError(undefined)\r\n setSavedNote(secret === undefined ? `\u5DF2\u4FDD\u5B58 ${label}` : `\u5DF2\u4FDD\u5B58 ${safeLabel}`)\r\n })\r\n .catch((error: any) => {\r\n const message = redactSensitiveText(String(error?.message ?? error), [\r\n ...(secret === undefined ? [] : [secret]),\r\n ])\r\n setSavedNote(undefined)\r\n setSaveError({ label: safeLabel, message })\r\n onRefused()\r\n }),\r\n )\r\n }\r\n\r\n /**\r\n * Undo ONE refused field in a card's draft.\r\n *\r\n * Only that field is dropped. Other fields of the same provider may hold edits\r\n * that are still pending or already accepted \u2014 dropping the whole draft entry\r\n * would throw away values the Host never objected to. An entry left empty by\r\n * the removal is dropped entirely, so it cannot keep a phantom row alive.\r\n */\r\n const rollbackRouteField = (id: string, field: string): void => {\r\n setDraft((current: any) => {\r\n const entry = current[id]\r\n if (entry === undefined || entry[field] === undefined) return current\r\n const nextEntry = { ...entry }\r\n delete nextEntry[field]\r\n const next = { ...current }\r\n if (Object.keys(nextEntry).length === 0) delete next[id]\r\n else next[id] = nextEntry\r\n return next\r\n })\r\n }\r\n\r\n /** One card 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 if (TEST_RELEVANT_FIELDS.has(field)) invalidateTests([id])\r\n save(`${id}\\u0000${field}`, ['providers', id, field], `${id}.${field}`, value, () =>\r\n rollbackRouteField(id, field),\r\n )\r\n }\r\n\r\n /** One default-block control: same contract, addressed at `defaultProxy`. */\r\n const bindDefault = (field: string) => (value: unknown) => {\r\n editDefault(field, value)\r\n invalidateTests(inheritingIds())\r\n save(`\\u0000default\\u0000${field}`, ['defaultProxy', field], `defaultProxy.${field}`, value, () => {\r\n // Same rule as a card field: drop only this field, and only if the draft\r\n // still holds it, so an already-accepted sibling edit is never discarded.\r\n setDefaultDraft((current: any) => {\r\n if (current[field] === undefined) return current\r\n const next = { ...current }\r\n delete next[field]\r\n return next\r\n })\r\n })\r\n }\r\n\r\n /** One advanced global control: draft, invalidate every check, persist. */\r\n const bindGlobal = (field: 'testUrl' | 'localDirect') => (value: unknown) => {\r\n editGlobal(field, value)\r\n invalidateTests(rows.map(row => row.id))\r\n save(`\\u0000global\\u0000${field}`, [field], field, value, () => {\r\n setGlobalDraft((current: any) => {\r\n if (current[field] === undefined) return current\r\n const next = { ...current }\r\n delete next[field]\r\n return next\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * One debounced write carrying SEVERAL edits at once.\r\n *\r\n * Used for a pasted proxy URL: five separate writes would each rebuild the\r\n * Host's whole proxy table, and a half-applied paste (credentials without the\r\n * host, say) would hit the credential guards mid-burst \u2014 the same trap the\r\n * per-field debounce exists to avoid.\r\n */\r\n const saveMany = (key: string, ops: unknown[], label: string, onRefused: () => void) => {\r\n const secrets = secretsFromOps(ops as any[])\r\n const hidesValues = (ops as any[]).some(op => op?.path?.[op.path.length - 1] === 'password')\r\n const safeLabel = hidesValues ? `${label}\uFF08\u503C\u5DF2\u9690\u85CF\uFF09` : label\r\n scheduleWrite(key, () =>\r\n writeConfig(ctx, ops)\r\n .then(() => {\r\n setSaveError(undefined)\r\n setSavedNote(`\u5DF2\u4FDD\u5B58 ${safeLabel}`)\r\n })\r\n .catch((error: any) => {\r\n const message = redactSensitiveText(String(error?.message ?? error), secrets)\r\n setSavedNote(undefined)\r\n setSaveError({ label: safeLabel, message })\r\n onRefused()\r\n }),\r\n )\r\n }\r\n\r\n /** Undo one set of pasted fields in a card's draft. */\r\n const rollbackRouteFields = (id: string, fields: readonly string[]): void => {\r\n setDraft((current: any) => {\r\n const entry = current[id]\r\n if (entry === undefined) return current\r\n const nextEntry = { ...entry }\r\n for (const field of fields) delete nextEntry[field]\r\n const next = { ...current }\r\n if (Object.keys(nextEntry).length === 0) delete next[id]\r\n else next[id] = nextEntry\r\n return next\r\n })\r\n }\r\n\r\n /** Apply a parsed proxy URL to one card: one draft update, one write. */\r\n const applyCardUrl = (id: string, parts: Record<string, unknown>): void => {\r\n setDraft((current: any) => ({ ...current, [id]: { ...current[id], ...parts } }))\r\n invalidateTests([id])\r\n const fields = Object.keys(parts)\r\n saveMany(\r\n `${id}\\u0000*paste`,\r\n fields.map(field => ({ op: 'set', path: ['providers', id, field], value: parts[field] })),\r\n `${id}.*\uFF08\u7C98\u8D34\u4EE3\u7406 URL\uFF09`,\r\n () => rollbackRouteFields(id, fields),\r\n )\r\n }\r\n\r\n /** Apply a parsed proxy URL to the shared default endpoint. */\r\n const applyDefaultUrl = (parts: Record<string, unknown>): void => {\r\n setDefaultDraft((current: any) => ({ ...current, ...parts }))\r\n invalidateTests(inheritingIds())\r\n const fields = Object.keys(parts)\r\n saveMany(\r\n '\\u0000default\\u0000*paste',\r\n fields.map(field => ({ op: 'set', path: ['defaultProxy', field], value: parts[field] })),\r\n '\u9ED8\u8BA4\u4EE3\u7406\uFF08\u7C98\u8D34\u4EE3\u7406 URL\uFF09',\r\n () => {\r\n setDefaultDraft((current: any) => {\r\n const next = { ...current }\r\n for (const field of fields) delete next[field]\r\n return next\r\n })\r\n },\r\n )\r\n }\r\n\r\n /**\r\n * Promote a card's own endpoint to the shared default.\r\n *\r\n * The reduced form of \"copy this card to another\": once the endpoint lives in\r\n * the default block, every other card opts in with one switch, so a\r\n * multi-select picker would be a second way to do the same thing.\r\n */\r\n const promoteToDefault = (id: string): void => {\r\n const route = view({ ...configured[id], ...draft[id] })\r\n applyDefaultUrl({\r\n protocol: route.protocol,\r\n host: route.host.trim(),\r\n port: route.port,\r\n username: route.username,\r\n password: route.password,\r\n })\r\n }\r\n\r\n /** Point every card at the default endpoint, in one write. */\r\n const applyDefaultToAll = (): void => {\r\n const ids = rows.map(row => row.id)\r\n if (ids.length === 0) return\r\n setDraft((current: any) => {\r\n const next = { ...current }\r\n for (const id of ids) next[id] = { ...next[id], useDefault: true }\r\n return next\r\n })\r\n invalidateTests(ids)\r\n saveMany(\r\n '\\u0000default\\u0000applyAll',\r\n ids.map(id => ({ op: 'set', path: ['providers', id, 'useDefault'], value: true })),\r\n '\u6240\u6709 provider \u7684 useDefault',\r\n () =>\r\n setDraft((current: any) => {\r\n const next = { ...current }\r\n for (const id of ids) {\r\n const entry = next[id]\r\n if (entry === undefined || entry.useDefault === undefined) continue\r\n const nextEntry = { ...entry }\r\n delete nextEntry.useDefault\r\n if (Object.keys(nextEntry).length === 0) delete next[id]\r\n else next[id] = nextEntry\r\n }\r\n return next\r\n }),\r\n )\r\n }\r\n\r\n /**\r\n * A paste handler for any proxy-address field.\r\n *\r\n * Only a RECOGNISED proxy URL is intercepted; anything else falls through to\r\n * the browser so a pasted bare host still lands in the field normally.\r\n */\r\n const onProxyUrlPaste =\r\n (apply: (parts: Record<string, unknown>) => void) =>\r\n (event: any): void => {\r\n const text = event?.clipboardData?.getData?.('text')\r\n if (typeof text !== 'string') return\r\n const parts = splitProxyUrl(text)\r\n if (parts === undefined) return\r\n event.preventDefault?.()\r\n apply(parts)\r\n }\r\n\r\n const field = (label: string, control: unknown, hint?: string, hintError?: boolean): 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 {\r\n className: styles.hint,\r\n style: {\r\n gridColumn: '2',\r\n fontSize: '11px',\r\n // A warning that a value can never work is an answer, not\r\n // decoration \u2014 same rule as the failed self-check text.\r\n ...(hintError === true\r\n ? { color: 'var(--dsw-alias-state-error-primary, #f85149)' }\r\n : {}),\r\n },\r\n },\r\n hint,\r\n ),\r\n )\r\n\r\n /**\r\n * The shared endpoint block, always rendered.\r\n *\r\n * It is the only place the address can be entered, so hiding it until some\r\n * card opts in would leave no way to configure it in the first place.\r\n */\r\n const storedDefault = (snapshot.value?.defaultProxy ?? {}) as Partial<RouteValue>\r\n const defaultView = view({ ...storedDefault, ...defaultDraft })\r\n // The SAME predicate the Host applies, imported rather than re-written: a\r\n // browser copy that only checked \"host non-empty and port in range\" called\r\n // `https://1.2.3.4` complete and enabled the bulk button, while the Host refused\r\n // every route pointed at it.\r\n //\r\n // The REASON is kept as well as the verdict: the block refuses for several\r\n // reasons (no host, a scheme-carrying host, a bad port, a half-filled\r\n // credential), and a card that said \"missing host or port\" for all of them sent\r\n // the user to the one field that was already correct.\r\n const defaultWhy = defaultProxyProblem(defaultView)\r\n // An empty optional block is \"not configured\", not a typed mistake. Only an\r\n // invalid NON-empty host gets the error colour under the input.\r\n const defaultHostWhy = defaultView.host.trim().length === 0\r\n ? undefined\r\n : proxyHostProblem(defaultView.host)\r\n const defaultComplete = defaultWhy === undefined\r\n const defaultOrigin = `${defaultView.protocol}://${defaultView.host}:${defaultView.port}`\r\n const defaultBlock = h(\r\n 'div',\r\n { className: styles.defaultCard, style: S.defaultCard, key: 'default-proxy' },\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 }, t.defaultTitle),\r\n ),\r\n h(\r\n 'span',\r\n {\r\n className: defaultComplete ? styles.pillOn : styles.pillOff,\r\n style: { ...S.pill, ...(defaultComplete ? S.pillOn : S.pillOff) },\r\n },\r\n defaultComplete ? t.complete : t.notConfigured,\r\n ),\r\n ),\r\n h('p', { className: styles.defaultLead, style: S.defaultLead }, t.defaultLead),\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 value: defaultView.protocol,\r\n onChange: (event: any) => bindDefault('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 ),\r\n field(\r\n t.host,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: '127.0.0.1',\r\n value: defaultView.host,\r\n onChange: (event: any) => bindDefault('host')(event.target.value),\r\n // Same convenience as the cards: a full URL fills the whole block.\r\n onPaste: onProxyUrlPaste(applyDefaultUrl),\r\n }),\r\n defaultHostWhy ?? t.hostHint,\r\n defaultHostWhy !== undefined,\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 type: 'number',\r\n min: 1,\r\n max: 65535,\r\n placeholder: '7890',\r\n value: defaultView.port === 0 ? '' : String(defaultView.port),\r\n onChange: (event: any) => {\r\n const parsed = Number.parseInt(event.target.value, 10)\r\n bindDefault('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 autocomplete: 'off',\r\n value: defaultView.username,\r\n onChange: (event: any) => bindDefault('username')(event.target.value),\r\n }),\r\n ),\r\n field(\r\n t.password,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n type: 'password',\r\n autocomplete: 'off',\r\n value: defaultView.password,\r\n onChange: (event: any) => bindDefault('password')(event.target.value),\r\n }),\r\n t.passwordHintProxy,\r\n ),\r\n // Bulk opt-in, in ONE write: a per-card walk would rebuild the table N times.\r\n // Disabled while the default configuration is incomplete, because pointing every card at an\r\n // empty endpoint would just refuse them all.\r\n h(\r\n 'div',\r\n { style: S.testRow, key: 'default:apply' },\r\n h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: S.testButton,\r\n type: 'button',\r\n disabled: !defaultComplete || rows.length === 0,\r\n onClick: applyDefaultToAll,\r\n },\r\n t.applyDefaultAll,\r\n ),\r\n ),\r\n )\r\n\r\n const storedTestUrl =\r\n typeof snapshot.value?.testUrl === 'string' ? snapshot.value.testUrl : DEFAULT_TEST_URL\r\n const storedLocalDirect = snapshot.value?.localDirect !== false\r\n const globalTestUrl = typeof globalDraft.testUrl === 'string' ? globalDraft.testUrl : storedTestUrl\r\n const globalLocalDirect =\r\n typeof globalDraft.localDirect === 'boolean' ? globalDraft.localDirect : storedLocalDirect\r\n const globalTestUrlHint = testUrlHint(globalTestUrl, t)\r\n const globalBlock = h(\r\n 'details',\r\n {\r\n className: styles.diag,\r\n style: {\r\n ...S.diag,\r\n marginTop: '0',\r\n },\r\n key: 'global-settings',\r\n },\r\n h('summary', { className: styles.diagSummary }, t.globalTitle),\r\n h('p', { className: styles.defaultLead, style: S.defaultLead }, t.globalLead),\r\n h(\r\n 'label',\r\n { className: styles.field, style: S.field },\r\n h('span', { className: styles.label, style: S.label }, t.testUrl),\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n value: globalTestUrl,\r\n onChange: (event: any) => bindGlobal('testUrl')(event.target.value),\r\n }),\r\n globalTestUrlHint === undefined\r\n ? h('span', { style: S.hint }, t.testUrlHint)\r\n : h(\r\n 'span',\r\n {\r\n className: styles.hint,\r\n style: {\r\n ...S.hint,\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n },\r\n },\r\n globalTestUrlHint,\r\n ),\r\n ),\r\n h(\r\n 'div',\r\n { style: S.testRow },\r\n h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: S.testButton,\r\n type: 'button',\r\n onClick: () => bindGlobal('testUrl')(DEFAULT_TEST_URL),\r\n },\r\n t.restoreDefaultTestUrl,\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: globalLocalDirect,\r\n onChange: (event: any) => bindGlobal('localDirect')(event.target.checked === true),\r\n }),\r\n h('span', null, t.localDirect),\r\n ),\r\n h(\r\n 'p',\r\n { style: S.hint },\r\n globalLocalDirect ? t.localDirectOnHint : t.localDirectOffHint,\r\n ),\r\n )\r\n\r\n const query = filter.trim().toLowerCase()\r\n const shown =\r\n query.length === 0\r\n ? rows\r\n : rows.filter(row => `${row.id} ${row.name}`.toLowerCase().includes(query))\r\n const filterRow =\r\n rows.length === 0\r\n ? null\r\n : field(\r\n t.filterLabel,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: t.filterPlaceholder,\r\n value: filter,\r\n onChange: (event: any) => setFilter(event.target.value),\r\n }),\r\n )\r\n\r\n // The empty slot answers three different questions: still loading, the read\r\n // failed, or truly nothing to show. Only the last is the empty message.\r\n // With saved cards present, a failed first read is reported above them instead.\r\n const catalogueStatus = rows.length === 0\r\n ? state.pending\r\n ? { text: t.catalogueLoading, error: false }\r\n : state.error !== undefined\r\n ? { text: `${t.catalogueError}${state.error}`, error: true }\r\n : undefined\r\n : undefined\r\n const catalogueNotice =\r\n state.error !== undefined && rows.length > 0\r\n ? h(\r\n 'p',\r\n { key: 'catalogue-error', style: S.inheritWarning },\r\n `${t.catalogueStale}${state.error}`,\r\n )\r\n : null\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[] = shown.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: catalogueStatus?.error === true\r\n ? 'var(--dsw-alias-state-error-primary, #f85149)'\r\n : 'var(--dsw-alias-state-idle-primary)',\r\n ...(catalogueStatus?.error === true ? { fontWeight: '500' } : {}),\r\n },\r\n },\r\n catalogueStatus?.text ?? (query.length > 0 ? t.noMatch : t.empty),\r\n ),\r\n ]\r\n : shown.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 // The endpoint controls are editable whether or not the route is on: the\r\n // point of the self-check below is to verify a setting BEFORE switching\r\n // it on, which is impossible if the fields can only be typed into while\r\n // traffic is already flowing through them. `enabled` gates routing only.\r\n // The line exists only once a route has actually carried a request, so an\r\n // ENABLED route with no record yet says so \u2014 otherwise a missing line is\r\n // indistinguishable from the feature not existing. A disabled route stays\r\n // silent: it cannot have a record, and saying so on every off card is noise.\r\n const lastText = lastUseText(row.id) ?? (route.enabled ? t.noRecord : undefined)\r\n const result = tests[row.id]\r\n // Rule entries that can never match: flagged under the input instead of\r\n // failing silently \u2014 a dead `onlyHosts` entry means fail-closed sends\r\n // the traffic DIRECT while the user believes it is proxied.\r\n const onlyDead = deadRuleEntries(route.onlyHosts)\r\n const bypassDead = deadRuleEntries(route.bypassHosts)\r\n const useDefault = route.useDefault === true\r\n // Whether this card has an endpoint worth checking: an inheriting card\r\n // depends on the shared default being configured, an own-endpoint card on\r\n // its host and port being complete. Mirrors the Host's own build gate.\r\n const endpointStored = route.useDefault\r\n ? defaultComplete\r\n : route.host.trim().length > 0 &&\r\n Number.isInteger(route.port) &&\r\n route.port >= 1 &&\r\n route.port <= 65535\r\n const showTest = route.enabled || endpointStored\r\n // The Host's recorded problem is authoritative (it also covers dispatcher\r\n // construction); until the next catalogue poll, the shared predicate can\r\n // already prove the common endpoint mistakes. An unused route is never\r\n // \"rejected\" \u2014 it has not asked for anything yet.\r\n const problemText = ((): string | undefined => {\r\n const recorded = problems[row.id]\r\n if (recorded !== undefined) return recorded\r\n if (useDefault) return defaultComplete ? undefined : `${t.defaultMissing}${defaultWhy}`\r\n return route.enabled ? defaultProxyProblem(route) : undefined\r\n })()\r\n const rejected = route.enabled && problemText !== undefined\r\n // Built once and either rendered (this route carries its own address) or\r\n // replaced by a one-line note (it inherits the shared default), so a card\r\n // can never show an input that does not apply to it.\r\n const endpointFields = [\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 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 placeholder: '127.0.0.1',\r\n value: route.host,\r\n onChange: (event: any) => bind(row.id, 'host')(event.target.value),\r\n // A pasted full proxy URL fills every transport field at once.\r\n onPaste: onProxyUrlPaste(parts => applyCardUrl(row.id, parts)),\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 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 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 // Every transport accepts a password: SOCKS5 hands it to\r\n // Socks5ProxyAgent as an option, HTTP/HTTPS embed it in the proxy URL\r\n // userinfo (undici turns that into Proxy-Authorization). It is stored on\r\n // the route, so it lands in the settings file with the rest of the\r\n // config; the diagnostics only ever surface a credential-free origin.\r\n field(\r\n t.password,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\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 route.protocol === 'socks5' ? t.passwordHint : t.passwordHintProxy,\r\n ),\r\n ]\r\n // The pill describes the ROUTE, never provider availability: a saved\r\n // route can outlive the Host directory, and whether that directory lists\r\n // it must not make the proxy switch read as \"offline\" or \"proxied\".\r\n const pill = rejected\r\n ? { className: styles.pillRejected, style: { ...S.pill, ...S.pillRejected }, text: t.rejected }\r\n : route.enabled\r\n ? { className: styles.pillOn, style: { ...S.pill, ...S.pillOn }, text: t.on }\r\n : { className: styles.pillLive, style: { ...S.pill, ...S.pillLive }, text: t.off }\r\n return h(\r\n 'section',\r\n {\r\n className: rejected ? styles.cardRejected : route.enabled ? styles.cardActive : styles.card,\r\n style: rejected\r\n ? { ...S.card, ...S.cardRejected }\r\n : route.enabled\r\n ? { ...S.card, ...S.cardActive }\r\n : 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 // A disabled route can never have hits, so \"0\" there would only add\r\n // noise; the count shows once the route is on (or has counted).\r\n route.enabled || (hits[row.id] ?? 0) > 0\r\n ? h(\r\n 'span',\r\n { style: S.hits },\r\n `${t.hitCountPrefix}${hits[row.id] ?? 0}${t.hitCountSuffix}`,\r\n )\r\n : null,\r\n // The last-use line. A failure takes the error colour, same rule as\r\n // a failed self-check: it is an answer, not decoration.\r\n lastText === undefined\r\n ? null\r\n : h(\r\n 'span',\r\n {\r\n style: {\r\n ...S.hits,\r\n ...(lastUse[row.id]?.ok === false ? S.inheritWarning : {}),\r\n },\r\n },\r\n lastText,\r\n ),\r\n ),\r\n h('span', { className: pill.className, style: pill.style }, pill.text),\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 // Opting into the shared endpoint. The card then shows the address it\r\n // will actually use \u2014 or, when the default is not configured, why the\r\n // route is refused \u2014 instead of a set of empty inputs the user never\r\n // filled and cannot interpret.\r\n h(\r\n 'label',\r\n { className: styles.toggle, style: S.toggle, key: `${row.id}:usedefault` },\r\n h('input', {\r\n type: 'checkbox',\r\n checked: useDefault,\r\n onChange: (event: any) => bind(row.id, 'useDefault')(event.target.checked === true),\r\n }),\r\n h('span', null, t.useDefault),\r\n ),\r\n problemText !== undefined\r\n ? h('p', { key: `${row.id}:problem`, style: S.inheritWarning }, problemText)\r\n : useDefault\r\n ? h(\r\n 'p',\r\n { key: `${row.id}:inherit`, style: S.inheritNote },\r\n `${t.inheritingDefault}${defaultOrigin}`,\r\n )\r\n : null,\r\n ...(useDefault ? [] : endpointFields),\r\n // The self-check is offered whenever there is something to check: an\r\n // enabled route (the Host's table carries it, and a rejected one still\r\n // reports WHY), or a disabled one whose endpoint is already complete \u2014\r\n // the Host builds that one for the check alone. A disabled route with\r\n // no endpoint has nothing to test and would only answer \"not enabled\".\r\n showTest\r\n ? h(\r\n 'div',\r\n { style: S.testRow, key: `${row.id}:test` },\r\n // A check on a route that is still off is a trial run, and it says\r\n // so \u2014 otherwise the result reads as though the route were live.\r\n route.enabled ? null : h('span', { style: S.testResult }, t.testDisabledNote),\r\n h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: S.testButton,\r\n type: 'button',\r\n disabled: result?.pending === true,\r\n onClick: () => runTest(row.id),\r\n },\r\n result?.pending === true ? t.testRunning : t.testButton,\r\n ),\r\n result?.pending === false\r\n ? h(\r\n 'div',\r\n { style: S.testResult },\r\n result.ok === true\r\n ? [\r\n // The band colour belongs to the LATENCY alone. The\r\n // status sits beside it in the plain label colour:\r\n // colouring the whole line made a successful check\r\n // over 1500 ms read as a failure.\r\n h(\r\n 'span',\r\n { key: 'lat', style: { color: latencyColor(result.ms) } },\r\n `\u2713 ${typeof result.ms === 'number' ? result.ms : '\u2014'} ms`,\r\n ),\r\n typeof result.status === 'number'\r\n ? h(\r\n 'span',\r\n { key: 'status' },\r\n `HTTP ${result.status}`,\r\n )\r\n : null,\r\n result.ip === undefined\r\n ? null\r\n : h('span', { key: 'ip' }, `${t.exitIpLabel}${result.ip}`),\r\n result.direct === true\r\n ? h('span', { key: 'direct' }, t.directLabel)\r\n : null,\r\n result.cached === true\r\n ? h('span', { key: 'cached' }, t.cachedLabel)\r\n : null,\r\n result.target === undefined\r\n ? null\r\n : h(\r\n 'span',\r\n {\r\n key: 'target',\r\n style: {\r\n flexBasis: '100%',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n wordBreak: 'break-all',\r\n },\r\n },\r\n `${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}`,\r\n ),\r\n ]\r\n : [\r\n h('span', { key: 'err', style: S.testFailure }, `\u2717 ${result.error}`),\r\n typeof result.status === 'number'\r\n ? h('span', { key: 'status' }, `HTTP ${result.status}`)\r\n : null,\r\n result.target === undefined\r\n ? null\r\n : h(\r\n 'span',\r\n {\r\n key: 'target',\r\n style: {\r\n flexBasis: '100%',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n wordBreak: 'break-all',\r\n },\r\n },\r\n `${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}`,\r\n ),\r\n ],\r\n )\r\n : null,\r\n // Promote this card's endpoint to the shared default. Offered only\r\n // when the card carries its OWN endpoint: an inheriting card would\r\n // just be copying the default onto itself.\r\n endpointStored && !useDefault\r\n ? h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: S.testButton,\r\n type: 'button',\r\n onClick: () => promoteToDefault(row.id),\r\n },\r\n t.setAsDefault,\r\n )\r\n : null,\r\n )\r\n : null,\r\n // Target-host rules, collapsed so the common case stays one short card.\r\n h(\r\n 'details',\r\n { style: S.advanced, key: `${row.id}:rules` },\r\n h('summary', { style: S.advancedSummary }, t.advanced),\r\n field(\r\n t.onlyHosts,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: 'api.example.com',\r\n value: route.onlyHosts,\r\n onChange: (event: any) => bind(row.id, 'onlyHosts')(event.target.value),\r\n }),\r\n onlyDead.length === 0 ? t.onlyHostsHint : `${t.ruleDeadHint}${onlyDead.join('\u3001')}`,\r\n onlyDead.length > 0,\r\n ),\r\n field(\r\n t.bypassHosts,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: 'localhost',\r\n value: route.bypassHosts,\r\n onChange: (event: any) => bind(row.id, 'bypassHosts')(event.target.value),\r\n }),\r\n bypassDead.length === 0 ? t.bypassHostsHint : `${t.ruleDeadHint}${bypassDead.join('\u3001')}`,\r\n bypassDead.length > 0,\r\n ),\r\n // The self-check target: empty uses the top-level testUrl, set makes\r\n // this card's Test request this URL \u2014 a real upstream proves the whole\r\n // path, not just the proxy hop.\r\n field(\r\n t.testTarget,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: 'https://api.example.com',\r\n value: route.testTarget,\r\n onChange: (event: any) => bind(row.id, 'testTarget')(event.target.value),\r\n }),\r\n t.testTargetHint,\r\n ),\r\n ),\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 saveError === undefined\r\n ? null\r\n : h(\r\n 'div',\r\n {\r\n role: 'alert',\r\n key: 'save-error',\r\n style: {\r\n display: 'flex',\r\n alignItems: 'flex-start',\r\n justifyContent: 'space-between',\r\n gap: '10px',\r\n padding: '8px 10px',\r\n border: '1px solid var(--dsw-alias-state-error-primary, #f85149)',\r\n borderRadius: '8px',\r\n background: 'var(--dsw-alias-bg-layer-1)',\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n fontSize: '12px',\r\n fontWeight: '500',\r\n wordBreak: 'break-all',\r\n },\r\n },\r\n h('span', null, `${t.saveFailedPrefix}${saveError.label} \u2014 ${saveError.message}`),\r\n h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: { ...S.testButton, flex: 'none' },\r\n type: 'button',\r\n onClick: () => setSaveError(undefined),\r\n },\r\n t.close,\r\n ),\r\n ),\r\n defaultBlock,\r\n globalBlock,\r\n catalogueNotice,\r\n filterRow,\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 // The count is the only visible signal while the panel is collapsed: a\r\n // rejected route is not a page that refuses to render, it is one that\r\n // quietly does nothing.\r\n h(\r\n 'summary',\r\n { className: styles.diagSummary },\r\n problemCount === 0 ? t.diagnostics : `${t.diagnostics} (${problemCount})`,\r\n ),\r\n h(\r\n 'ul',\r\n { className: styles.diagList, style: { margin: '6px 0 0', paddingLeft: '18px' } },\r\n ...(problemCount === 0 && diagnostics.length === 0 && savedNote === undefined\r\n ? [h('li', { key: 'none' }, t.diagPending)]\r\n : [\r\n ...problemLines,\r\n ...(savedNote === undefined ? [] : [h('li', { key: 'saved' }, savedNote)]),\r\n ...diagnostics.map((line, index) => h('li', { key: `d${index}` }, line)),\r\n ]),\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. Requests to loopback or private addresses (localhost, 127.x, private ranges) go direct by default; set the top-level localDirect to false to proxy them instead \u2014 a forward proxy normally cannot reach your own machine.',\r\n empty: 'No providers found yet.',\r\n catalogueLoading: 'Loading providers\u2026',\r\n catalogueError: 'Could not load the provider list: ',\r\n catalogueStale: 'Could not load the provider list; showing the saved configuration: ',\r\n useProxy: 'Use a proxy for this provider',\r\n useDefault: 'Use the default proxy',\r\n defaultTitle: 'Default proxy',\r\n defaultLead: 'One endpoint, reused by every provider that turns on \"Use the default proxy\". The status only reports configuration completeness; use the Test button on a card to verify reachability.',\r\n inheritingDefault: 'Using the default proxy: ',\r\n defaultMissing: 'The default proxy configuration is incomplete, so this provider is not proxied: ',\r\n filterLabel: 'Filter',\r\n filterPlaceholder: 'Filter by name or id\u2026',\r\n noMatch: 'No provider matches the filter.',\r\n setAsDefault: 'Set as the default proxy',\r\n applyDefaultAll: 'Use the default proxy for all providers',\r\n protocol: 'Type',\r\n host: 'IP / host',\r\n port: 'Port',\r\n username: 'Username',\r\n password: 'Password',\r\n hostHint: 'Only an IPv4, IPv6, or domain name is allowed. A full proxy URL (socks5://user:pass@host:1080) can be pasted instead \u2014 it is split into the fields.',\r\n passwordHint: 'Sent to the SOCKS5 proxy for authentication; stored with this setting.',\r\n passwordHintProxy: 'Sent to the proxy as an authentication password; stored with this setting.',\r\n hitCountPrefix: '',\r\n hitCountSuffix: ' proxied',\r\n recentOk: 'last ok ',\r\n recentFail: 'last failure ',\r\n recentStarted: 'last call ',\r\n noRecord: 'no proxied request yet',\r\n justNow: 'just now',\r\n minutesAgo: ' min ago',\r\n hoursAgo: ' h ago',\r\n daysAgo: ' d ago',\r\n testButton: 'Test',\r\n testRunning: 'Testing\u2026',\r\n testDisabledNote: 'Not enabled \u2014 test only: ',\r\n testFailed: 'Test failed',\r\n exitIpLabel: 'exit IP ',\r\n directLabel: 'direct (not through the proxy)',\r\n cachedLabel: 'cached',\r\n testTargetLabel: 'Target: ',\r\n targetSourceRoute: \" (this card's own target)\",\r\n targetSourceUpstream: \" (this provider's real upstream)\",\r\n targetSourceTestUrl: ' (global self-check URL)',\r\n globalTitle: 'Global settings (advanced)',\r\n globalLead: 'These fields are saved with the plugin rather than per provider. Leave testUrl empty to use the built-in default; comma/space separated candidates are tried in order and only the first 5 are used. localDirect is on by default; turn it off only when the proxy itself is a loopback or private target.',\r\n testUrl: 'Self-check URL',\r\n testUrlHint: 'Comma/space separated; http(s) URLs in the order they should be tried.',\r\n testUrlEmptyHint: 'Empty means the Host uses its built-in default URL.',\r\n testUrlInvalidHint: 'Some candidates are not absolute http(s) URLs. They are saved, but those checks will fail.',\r\n testUrlTooManyHint: 'More than 5 candidates are listed; only the first 5 take effect.',\r\n restoreDefaultTestUrl: 'Restore default',\r\n localDirect: 'Loopback / private targets go direct',\r\n localDirectOnHint: 'On: localhost, 127.x and private ranges bypass the proxy.',\r\n localDirectOffHint: 'Off: loopback/private targets also use the proxy. Enable only when the proxy itself is the target.',\r\n advanced: 'Advanced: target host rules',\r\n onlyHosts: 'Proxy only',\r\n onlyHostsHint: 'Comma/space separated; when set, only requests to these hosts are proxied (suffix match, * for all).',\r\n bypassHosts: 'Bypass',\r\n bypassHostsHint: 'Comma/space separated; requests to these hosts go direct, taking priority.',\r\n ruleDeadHint: 'These entries never match \u2014 use bare host names (no port, scheme or path); a wildcard must be `*` or start with `*.`: ',\r\n testTarget: 'Self-check target',\r\n testTargetHint: 'Empty uses the top-level testUrl; when set, this card\\'s Test requests this URL instead \u2014 point it at a real upstream to verify the end-to-end path.',\r\n socks5Hint: 'SOCKS5 tunnels the connection; the proxy resolves the target host name.',\r\n on: 'proxied',\r\n rejected: 'config rejected',\r\n off: 'direct',\r\n complete: 'complete',\r\n notConfigured: 'not configured',\r\n diagnostics: 'Connection diagnostics',\r\n diagPending: '(collecting\u2026)',\r\n saveFailedPrefix: 'Save failed: ',\r\n close: 'Close',\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\u6307\u5411\u672C\u673A\u6216\u5185\u7F51\u5730\u5740\uFF08localhost\u3001127.x\u3001\u79C1\u6709\u7F51\u6BB5\uFF09\u7684\u8BF7\u6C42\u9ED8\u8BA4\u76F4\u8FDE\uFF0C\u9876\u5C42 localDirect \u8BBE\u4E3A false \u65F6\u6062\u590D\u8D70\u4EE3\u7406\u2014\u2014\u6B63\u5411\u4EE3\u7406\u901A\u5E38\u591F\u4E0D\u5230\u4F60\u81EA\u5DF1\u7684\u673A\u5668\u3002',\r\n empty: '\u6CA1\u6709\u68C0\u6D4B\u5230\u4EFB\u4F55 provider\u3002',\r\n catalogueLoading: '\u6B63\u5728\u8BFB\u53D6 provider \u5217\u8868\u2026',\r\n catalogueError: '\u8BFB\u53D6 provider \u5217\u8868\u5931\u8D25\uFF1A',\r\n catalogueStale: 'provider \u5217\u8868\u8BFB\u53D6\u5931\u8D25\uFF0C\u4E0B\u9762\u663E\u793A\u7684\u662F\u5DF2\u4FDD\u5B58\u7684\u914D\u7F6E\uFF1A',\r\n useProxy: '\u4E3A\u8BE5 provider \u542F\u7528\u4EE3\u7406',\r\n useDefault: '\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406',\r\n defaultTitle: '\u9ED8\u8BA4\u4EE3\u7406',\r\n defaultLead: '\u4E3A\u52FE\u9009\u300C\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406\u300D\u7684 provider \u590D\u7528\u7684\u7AEF\u70B9\uFF0C\u53EA\u586B\u4E00\u6B21\u3002\u72B6\u6001\u53EA\u8868\u793A\u914D\u7F6E\u662F\u5426\u5B8C\u6574\uFF1B\u4EE3\u7406\u662F\u5426\u53EF\u8FBE\u8BF7\u7528\u5361\u7247\u4E0A\u7684\u300C\u6D4B\u8BD5\u300D\u9A8C\u8BC1\u3002',\r\n inheritingDefault: '\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406\uFF1A',\r\n defaultMissing: '\u9876\u5C42\u9ED8\u8BA4\u4EE3\u7406\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u8BE5 provider \u4E0D\u4F1A\u8D70\u4EE3\u7406\uFF1A',\r\n filterLabel: '\u8FC7\u6EE4',\r\n filterPlaceholder: '\u6309\u540D\u79F0\u6216 id \u8FC7\u6EE4\u2026',\r\n noMatch: '\u6CA1\u6709\u5339\u914D\u7684 provider\u3002',\r\n setAsDefault: '\u8BBE\u4E3A\u9ED8\u8BA4\u4EE3\u7406',\r\n applyDefaultAll: '\u6240\u6709 provider \u4F7F\u7528\u9ED8\u8BA4\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\u5141\u8BB8\u586B\u5199 IPv4\u3001IPv6 \u6216\u57DF\u540D\uFF1B\u4E5F\u53EF\u4EE5\u76F4\u63A5\u7C98\u8D34\u5B8C\u6574\u4EE3\u7406 URL\uFF08\u5982 socks5://user:pass@host:1080\uFF09\uFF0C\u4F1A\u81EA\u52A8\u62C6\u5206\u5230\u5404\u5B57\u6BB5\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 passwordHintProxy: '\u4F5C\u4E3A\u4EE3\u7406\u8BA4\u8BC1\u53E3\u4EE4\u53D1\u9001\u7ED9\u4EE3\u7406\uFF1B\u968F\u8BE5\u8BBE\u7F6E\u4E00\u8D77\u4FDD\u5B58\u3002',\r\n hitCountPrefix: '\u5DF2\u4EE3\u7406 ',\r\n hitCountSuffix: ' \u6B21',\r\n recentOk: '\u6700\u8FD1\u6210\u529F ',\r\n recentFail: '\u6700\u8FD1\u5931\u8D25 ',\r\n recentStarted: '\u6700\u8FD1\u8C03\u7528 ',\r\n noRecord: '\u5C1A\u65E0\u4EE3\u7406\u8BB0\u5F55',\r\n justNow: '\u521A\u521A',\r\n minutesAgo: ' \u5206\u949F\u524D',\r\n hoursAgo: ' \u5C0F\u65F6\u524D',\r\n daysAgo: ' \u5929\u524D',\r\n testButton: '\u6D4B\u8BD5',\r\n testRunning: '\u6D4B\u8BD5\u4E2D\u2026',\r\n testDisabledNote: '\u672A\u542F\u7528\uFF0C\u4EC5\u6D4B\u8BD5\uFF1A',\r\n testFailed: '\u6D4B\u8BD5\u5931\u8D25',\r\n exitIpLabel: '\u51FA\u53E3 IP ',\r\n directLabel: '\u76F4\u8FDE\uFF08\u672A\u7ECF\u8FC7\u4EE3\u7406\uFF09',\r\n cachedLabel: '\u7F13\u5B58',\r\n testTargetLabel: '\u76EE\u6807 ',\r\n targetSourceRoute: '\uFF08\u672C\u5361\u7247\u81EA\u68C0\u76EE\u6807\uFF09',\r\n targetSourceUpstream: '\uFF08\u8BE5 provider \u7684\u771F\u5B9E\u4E0A\u6E38\uFF09',\r\n targetSourceTestUrl: '\uFF08\u5168\u5C40\u81EA\u68C0\u5730\u5740\uFF09',\r\n globalTitle: '\u5168\u5C40\u8BBE\u7F6E\uFF08\u9AD8\u7EA7\uFF09',\r\n globalLead: '\u8FD9\u91CC\u7684\u4E24\u9879\u5C5E\u4E8E\u63D2\u4EF6\u5168\u5C40\u8BBE\u7F6E\u3002testUrl \u7559\u7A7A\u65F6 Host \u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u503C\uFF1B\u591A\u4E2A\u5019\u9009\u7528\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF0C\u6309\u987A\u5E8F\u56DE\u9000\uFF0C\u53EA\u6709\u524D 5 \u4E2A\u751F\u6548\u3002localDirect \u9ED8\u8BA4\u5F00\u542F\uFF1B\u53EA\u6709\u4EE3\u7406\u672C\u8EAB\u5C31\u662F\u672C\u673A\u6216\u5185\u7F51\u76EE\u6807\u65F6\u624D\u9700\u8981\u5173\u95ED\u3002',\r\n testUrl: '\u81EA\u68C0\u5730\u5740',\r\n testUrlHint: '\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u6309\u987A\u5E8F\u5C1D\u8BD5\u7684 http(s) URL\u3002',\r\n testUrlEmptyHint: '\u7559\u7A7A\u65F6 Host \u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u5730\u5740\u3002',\r\n testUrlInvalidHint: '\u90E8\u5206\u5019\u9009\u4E0D\u662F\u7EDD\u5BF9\u7684 http(s) URL\u3002\u4ECD\u4F1A\u4FDD\u5B58\uFF0C\u4F46\u8FD9\u4E9B\u5019\u9009\u4F1A\u6D4B\u8BD5\u5931\u8D25\u3002',\r\n testUrlTooManyHint: '\u5019\u9009\u8D85\u8FC7 5 \u4E2A\uFF0C\u53EA\u6709\u524D 5 \u4E2A\u751F\u6548\u3002',\r\n restoreDefaultTestUrl: '\u6062\u590D\u9ED8\u8BA4',\r\n localDirect: '\u672C\u673A / \u5185\u7F51\u76EE\u6807\u76F4\u8FDE',\r\n localDirectOnHint: '\u5F00\u542F\uFF1Alocalhost\u3001127.x \u4E0E\u79C1\u6709\u7F51\u6BB5\u7ED5\u8FC7\u4EE3\u7406\u3002',\r\n localDirectOffHint: '\u5173\u95ED\uFF1A\u672C\u673A / \u5185\u7F51\u76EE\u6807\u4E5F\u8D70\u4EE3\u7406\uFF1B\u4EC5\u5728\u4EE3\u7406\u672C\u8EAB\u5C31\u662F\u76EE\u6807\u65F6\u4F7F\u7528\u3002',\r\n advanced: '\u9AD8\u7EA7\uFF1A\u76EE\u6807\u57DF\u540D\u89C4\u5219',\r\n onlyHosts: '\u4EC5\u8D70\u4EE3\u7406',\r\n onlyHostsHint: '\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u975E\u7A7A\u65F6\u53EA\u6709\u5339\u914D\u8FD9\u4E9B\u4E3B\u673A\u7684\u8BF7\u6C42\u8D70\u4EE3\u7406\uFF08\u540E\u7F00\u5339\u914D\uFF0C* \u8868\u793A\u5168\u90E8\uFF09\u3002',\r\n bypassHosts: '\u76F4\u8FDE',\r\n bypassHostsHint: '\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u5339\u914D\u8FD9\u4E9B\u4E3B\u673A\u7684\u8BF7\u6C42\u76F4\u8FDE\uFF0C\u4F18\u5148\u4E8E\u4E0A\u4E00\u9879\u3002',\r\n ruleDeadHint: '\u4EE5\u4E0B\u6761\u76EE\u6C38\u8FDC\u5339\u914D\u4E0D\u4E0A\u2014\u2014\u89C4\u5219\u53EA\u8BA4\u4E3B\u673A\u540D\uFF08\u4E0D\u8981\u5E26\u7AEF\u53E3\u3001\u534F\u8BAE\u524D\u7F00\u6216\u8DEF\u5F84\uFF09\uFF0C\u901A\u914D\u7B26\u53EA\u80FD\u662F\u5355\u72EC\u7684 * \u6216\u4EE5 *. \u5F00\u5934\uFF1A',\r\n testTarget: '\u81EA\u68C0\u76EE\u6807',\r\n testTargetHint: '\u7559\u7A7A\u7528\u9876\u5C42 testUrl\uFF1B\u586B\u5199\u540E\u8BE5\u5361\u7247\u7684\u300C\u6D4B\u8BD5\u300D\u6539\u4E3A\u8BF7\u6C42\u8FD9\u4E2A\u5730\u5740\uFF0C\u53EF\u62FF\u771F\u5B9E\u4E0A\u6E38\u9A8C\u8BC1\u7AEF\u5230\u7AEF\u8DEF\u5F84\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 rejected: '\u914D\u7F6E\u88AB\u62D2',\r\n off: '\u76F4\u8FDE',\r\n complete: '\u914D\u7F6E\u5B8C\u6574',\r\n notConfigured: '\u672A\u914D\u7F6E',\r\n diagnostics: '\u8FDE\u63A5\u8BCA\u65AD',\r\n diagPending: '\uFF08\u6B63\u5728\u6536\u96C6\u2026\uFF09',\r\n saveFailedPrefix: '\u4FDD\u5B58\u5931\u8D25\uFF1A',\r\n close: '\u5173\u95ED',\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", "/**\r\n * Target-host rule parsing shared by the Host matcher and the settings page.\r\n *\r\n * This module deliberately has no undici import: the browser bundle imports it\r\n * too, and the two halves must agree on what an entry means before either can\r\n * safely warn about an entry that will never match.\r\n */\r\n\r\n/** Split a host-rule string into raw, non-empty tokens. */\r\nexport function splitHostRules(raw: string): string[] {\r\n return raw\r\n .split(/[,\\s]+/)\r\n .map(entry => entry.trim())\r\n .filter(entry => entry.length > 0)\r\n}\r\n\r\n/**\r\n * Normalize one raw rule for suffix matching.\r\n *\r\n * A leading `.` or `*.` is dropped: both spellings mean \"this host and its\r\n * subdomains\". Lower-casing belongs here as well, because the Host compares\r\n * against a WHATWG hostname that is already lower-cased.\r\n */\r\nexport function normalizeHostRule(raw: string): string {\r\n return raw.trim().replace(/^\\*?\\./, '').toLowerCase()\r\n}\r\n\r\n/** Split and normalize a host-rule string into matchable entries. */\r\nexport function parseHostList(raw: string): string[] {\r\n return splitHostRules(raw)\r\n .map(normalizeHostRule)\r\n .filter(entry => entry.length > 0)\r\n}\r\n\r\n/**\r\n * Whether a host is covered by one rule list.\r\n *\r\n * `*` matches everything; otherwise a rule matches the host itself or any\r\n * subdomain of it (`example.com` covers `api.example.com`).\r\n */\r\nexport function hostMatches(host: string, rules: readonly string[]): boolean {\r\n for (const rule of rules) {\r\n if (rule === '*') return true\r\n if (host === rule || host.endsWith(`.${rule}`)) return true\r\n }\r\n return false\r\n}\r\n\r\n/** Whether a raw token is a bracketed IPv6 literal, e.g. `[::1]`. */\r\nfunction isBracketedIpv6(token: string): boolean {\r\n return /^\\[[0-9a-f:.]+\\]$/i.test(token)\r\n}\r\n\r\n/** Whether a raw token can never match the Host's hostname comparison. */\r\nexport function hostRuleProblem(raw: string): string | undefined {\r\n const token = raw.trim()\r\n if (token.length === 0) return undefined\r\n // A bare `*.` normalizes to an empty string and disappears from the match\r\n // list entirely; report it rather than silently accepting a no-op.\r\n if (token === '*.' || normalizeHostRule(token).length === 0) return '\u7A7A\u901A\u914D\u7B26'\r\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(token)) return '\u5E26\u534F\u8BAE\u524D\u7F00'\r\n if (token.includes('/')) return '\u5E26\u8DEF\u5F84'\r\n // Host compares hostnames, never `host:port`; a bracketed IPv6 literal is the\r\n // one legitimate colon in a hostname.\r\n if (token.includes(':') && !isBracketedIpv6(token)) return '\u5E26\u7AEF\u53E3\u6216\u975E\u6CD5\u5192\u53F7'\r\n // Host strips only a leading `.`/`*.`; any other `*` cannot be a hostname.\r\n const withoutLeadingWildcard = token.replace(/^\\*\\./, '')\r\n if (withoutLeadingWildcard.includes('*') && token !== '*') return '\u6742\u6563\u901A\u914D\u7B26'\r\n return undefined\r\n}\r\n\r\n/** Every raw token that will never match, in the order it was typed. */\r\nexport function deadRuleEntries(raw: string): string[] {\r\n return splitHostRules(raw).filter(entry => hostRuleProblem(entry) !== undefined)\r\n}\r\n", "/**\n * The proxy-endpoint usability predicate, in ONE place.\n *\n * This lives in its own module \u2014 free of Node and schemastery imports \u2014 so the\n * BROWSER half can import the very same rule the Host applies. It exists because\n * the browser used to keep its own weaker copy that checked only \"host non-empty\n * and port in range\": against `https://1.2.3.4` that copy lit the default block\n * green and enabled the bulk \"use the default\" button, while the Host refused\n * every route that pointed at it (a host carrying a scheme or path is rejected by\n * `normalizeRoute`). One predicate, imported by both halves, cannot disagree\n * with itself.\n */\nexport interface ProxyEndpoint {\n /**\n * Proxy host or IP, without scheme, port, or path.\n *\n * Optional because the browser calls this with whatever the settings document\n * currently holds, which mid-edit is not yet a complete endpoint.\n */\n host?: string\n /** Proxy port. 0 means \"not configured\". */\n port?: number\n /**\n * Credential parts, if the endpoint carries any. A HALF-filled pair is a\n * problem, the same way it is on the route itself \u2014 see below.\n */\n username?: string\n password?: string\n}\n\nconst PROXY_HOST_INVALID = '\u4EE3\u7406\u5730\u5740\u53EA\u80FD\u586B IPv4\u3001IPv6 \u6216\u57DF\u540D'\nconst IPV4 = /^(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$/\nconst DOMAIN = /^(?=.*[a-z])(?=.{1,253}$)(?!.*\\.\\d+$)[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?)*$/i\nconst IPV6_CHARS = /^[0-9a-f:.]+$/i\n\n/**\n * Accept exactly one of: IPv4, IPv6, or a DNS host name. The field carries the\n * proxy address only; a port, scheme, path, credential, or other URL text belongs\n * in its own field and is rejected here.\n */\nexport function proxyHostProblem(rawHost?: string): string | undefined {\n const host = (rawHost ?? '').trim().replace(/\\.$/, '')\n if (host.length === 0) return '\u672A\u586B\u5199\u4EE3\u7406\u5730\u5740'\n if (IPV4.test(host)) return undefined\n\n // A colon or bracket means the value is claiming to be IPv6. Validate it as\n // an IPv6 literal; never fall back to accepting the text as a host name.\n if (host.includes(':') || host.startsWith('[')) {\n const literal = host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host\n if (!IPV6_CHARS.test(literal)) return PROXY_HOST_INVALID\n try {\n new URL(`http://[${literal}]:1`)\n return undefined\n } catch {\n return PROXY_HOST_INVALID\n }\n }\n\n return DOMAIN.test(host) ? undefined : PROXY_HOST_INVALID\n}\n\n/**\n * Why this endpoint cannot carry a request, or `undefined` when it can.\n *\n * The host and port checks mirror `normalizeRoute` exactly, so the browser's\n * verdict and the Host's are the same verdict. The credential pairing check\n * mirrors the guards in `buildRouteEntry`, which is what makes this predicate a\n * truthful preview of whether a route that opts into the default will actually be\n * built: without it, a default carrying `alice` and no password lit the block\n * green and enabled the bulk button, and every card it pointed at was then\n * refused by the credential guard with `entries.size === 0`.\n *\n * Tolerates a partial object (`{}`, `host: undefined`) rather than throwing: the\n * browser calls this with whatever the settings document currently holds, which\n * during a half-typed edit is not yet a complete endpoint.\n */\nexport function defaultProxyProblem(endpoint: ProxyEndpoint): string | undefined {\n const hostProblem = proxyHostProblem(endpoint.host)\n if (hostProblem !== undefined) return hostProblem\n // `?? 0` rather than a throw: an absent port is \"not configured\", which is the\n // same thing 0 already means everywhere else in this plugin.\n const port = endpoint.port ?? 0\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n return '\u4EE3\u7406\u7AEF\u53E3\u65E0\u6548\uFF08\u9700\u4E3A 1-65535 \u7684\u6574\u6570\uFF09'\n }\n // \"Both or neither\", exactly as `buildRouteEntry` enforces per transport. The\n // wording stays transport-neutral here because the default block carries a\n // protocol the user may still change; the route-level guards spell out the\n // protocol-specific reason once it is pinned. The Host trims the username\n // before its guards, so this predicate must trim it too; the password is not\n // trimmed by either side.\n const hasUser = (endpoint.username ?? '').trim().length > 0\n const hasPassword = (endpoint.password ?? '').length > 0\n if (hasUser !== hasPassword) {\n return hasUser\n ? '\u914D\u7F6E\u4E86\u4EE3\u7406\u7528\u6237\u540D\u4F46\u6CA1\u6709\u5BC6\u7801\uFF1B\u8BF7\u8865\u5168\u5BC6\u7801\u6216\u6E05\u7A7A\u7528\u6237\u540D'\n : '\u914D\u7F6E\u4E86\u4EE3\u7406\u5BC6\u7801\u4F46\u6CA1\u6709\u7528\u6237\u540D\uFF1B\u8BF7\u8865\u5168\u7528\u6237\u540D\u6216\u6E05\u7A7A\u5BC6\u7801'\n }\n return undefined\n}\n"],
5
- "mappings": "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",
6
- "names": ["module", "field", "body", "apply", "styles"]
4
+ "sourcesContent": ["\nvar __dshMap = {\"root\":\"b4bf55bf_root\",\"lead\":\"03b72018_lead\",\"empty\":\"9a9a9c27_empty\",\"card\":\"6d6907d5_card\",\"cardActive\":\"a287416b_cardActive\",\"cardRejected\":\"aabaa9b3_cardRejected\",\"defaultCard\":\"ebf26189_defaultCard\",\"defaultLead\":\"5b9e9eb5_defaultLead\",\"cardHead\":\"a3319282_cardHead\",\"cardTitles\":\"6f64c28d_cardTitles\",\"name\":\"847f7e47_name\",\"id\":\"7864474d_id\",\"pillOn\":\"7ed5399b_pillOn\",\"pillLive\":\"0ccb6da5_pillLive\",\"pillOff\":\"3accadc4_pillOff\",\"pillRejected\":\"86897991_pillRejected\",\"toggle\":\"81025292_toggle\",\"field\":\"5e2577de_field\",\"label\":\"d9087e9b_label\",\"hint\":\"aae2a8a2_hint\",\"input\":\"feb8c902_input\",\"passwordToggle\":\"5645283d_passwordToggle\",\"testButton\":\"de8ca09a_testButton\",\"diag\":\"4ad17b9d_diag\",\"diagSummary\":\"b2f0759b_diagSummary\",\"diagList\":\"f49699bb_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.b4bf55bf_root {\\n display: flex;\\n flex-direction: column;\\n gap: 12px;\\n max-width: 640px;\\n}\\n\\n.03b72018_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.9a9a9c27_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.6d6907d5_card,\\n.a287416b_cardActive,\\n.aabaa9b3_cardRejected {\\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.a287416b_cardActive {\\n border-color: var(--dsw-alias-state-success-primary);\\n background: var(--dsw-alias-bg-layer-2);\\n}\\n\\n/* An enabled route the Host refused: never dress it as active. */\\n.aabaa9b3_cardRejected {\\n border-color: var(--dsw-alias-state-error-primary, #f85149);\\n background: var(--dsw-alias-bg-layer-2);\\n}\\n\\n/* ---- shared default endpoint ---- */\\n\\n/* A distinct outer layer, so it reads as \\\"one setting for the page\\\" rather than\\n as one more provider card. */\\n.ebf26189_defaultCard {\\n display: flex;\\n flex-direction: column;\\n gap: 10px;\\n padding: 14px 16px;\\n border: 1px solid var(--dsw-alias-border-l2);\\n border-radius: 10px;\\n background: var(--dsw-alias-bg-layer-2);\\n}\\n\\n.5b9e9eb5_defaultLead {\\n margin: -2px 0 0;\\n font-size: 11px;\\n line-height: 1.5;\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.a3319282_cardHead {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n gap: 12px;\\n}\\n\\n.6f64c28d_cardTitles {\\n display: flex;\\n align-items: baseline;\\n gap: 8px;\\n min-width: 0;\\n}\\n\\n.847f7e47_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.7864474d_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.7ed5399b_pillOn,\\n.0ccb6da5_pillLive,\\n.3accadc4_pillOff,\\n.86897991_pillRejected {\\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.7ed5399b_pillOn {\\n background: var(--dsw-alias-state-success-primary);\\n color: var(--dsw-alias-bg-base);\\n}\\n\\n.0ccb6da5_pillLive {\\n border: 1px solid var(--dsw-alias-border-l2);\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.3accadc4_pillOff {\\n color: var(--dsw-alias-state-idle-primary);\\n}\\n\\n.86897991_pillRejected {\\n border: 1px solid var(--dsw-alias-state-error-primary, #f85149);\\n color: var(--dsw-alias-state-error-primary, #f85149);\\n}\\n\\n/* ---- toggle ---- */\\n\\n.81025292_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.81025292_toggle input {\\n accent-color: var(--dsw-alias-brand-primary);\\n cursor: pointer;\\n}\\n\\n/* ---- fields ---- */\\n\\n.5e2577de_field {\\n display: grid;\\n grid-template-columns: 96px 1fr;\\n align-items: center;\\n gap: 10px;\\n font-size: 12px;\\n}\\n\\n.d9087e9b_label {\\n color: var(--dsw-alias-label-secondary);\\n}\\n\\n.aae2a8a2_hint {\\n grid-column: 2;\\n margin-top: -2px;\\n font-size: 11px;\\n color: var(--dsw-alias-state-warn-primary);\\n}\\n\\n.feb8c902_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/* The base look of every input is INLINE too, so these three state rules only\\n ever take effect as author-important declarations \u2014 same reason as the\\n self-check button above. `cursor` has no inline base and needs none, and the\\n hover border uses `l3` because `l1`\u2192`l2` is a 4%\u219210% black step nobody can\\n see. */\\n\\n.feb8c902_input:hover:not(:disabled) {\\n border-color: var(--dsw-alias-border-l3) !important;\\n}\\n\\n.feb8c902_input:focus {\\n border-color: var(--dsw-alias-brand-primary) !important;\\n}\\n\\n.feb8c902_input:disabled {\\n color: var(--dsw-alias-state-idle-primary) !important;\\n background: var(--dsw-alias-bg-layer-2) !important;\\n cursor: not-allowed;\\n}\\n\\n/* The icon sits inside the input, so its hover/focus feedback must be local\\n and must outrank the transparent inline base. */\\n.5645283d_passwordToggle {\\n transition: background 120ms ease, color 120ms ease;\\n}\\n\\n.5645283d_passwordToggle:hover:not(:disabled) {\\n background: var(--dsw-alias-interactive-bg-hover) !important;\\n color: var(--dsw-alias-label-primary) !important;\\n}\\n\\n.5645283d_passwordToggle:focus-visible {\\n outline: 2px solid var(--dsw-alias-brand-primary);\\n outline-offset: 1px;\\n}\\n\\n/* ---- self-check ---- */\\n\\n/* The hover state is the one thing an inline style cannot express, which is why\\n this element carries a class at all. Layout stays inline.\\n\\n Two traps, both hit before this comment existed:\\n - `!important` is load-bearing: the base border and background are INLINE, and\\n the cascade sorts a style attribute after every author rule, so a plain\\n declaration here would ship, match, and still lose.\\n - the TOKENS must be visible ones. `bg-layer-1/2/3` all resolve to\\n `neutral-bluish-00` in the light theme, so a layer swap is a no-op there, and\\n `border-l1`\u2192`l2` is 4%\u219210% black on a 1px line. The app's own hovers use\\n `interactive-bg-hover`; using it here is what makes the feedback exist. */\\n.de8ca09a_testButton {\\n transition: border-color 120ms ease, background 120ms ease;\\n}\\n\\n.de8ca09a_testButton:hover:not(:disabled) {\\n border-color: var(--dsw-alias-border-l3) !important;\\n background: var(--dsw-alias-interactive-bg-hover) !important;\\n}\\n\\n/* ---- diagnostics ---- */\\n\\n.4ad17b9d_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.b2f0759b_diagSummary {\\n cursor: pointer;\\n color: var(--dsw-alias-state-warn-primary);\\n}\\n\\n.f49699bb_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\nimport { deadRuleEntries } from './host-rules.js'\r\nimport { defaultProxyProblem, proxyHostProblem } from './proxy-address.js'\r\n\r\ntype Protocol = 'http' | 'https' | 'socks5'\r\n\r\ntype RouteValue = {\r\n enabled: boolean\r\n useDefault: boolean\r\n protocol: Protocol\r\n host: string\r\n port: number\r\n username: string\r\n password: string\r\n onlyHosts: string\r\n bypassHosts: string\r\n testTarget: 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: () => '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 const byId = new Map<string, ProviderRow>()\r\n for (const row of published) {\r\n byId.set(row.id, row)\r\n if (row.live) rows.set(row.id, row)\r\n }\r\n for (const id of Object.keys(configured)) {\r\n if (rows.has(id)) continue\r\n // A saved route must stay visible, but switching the proxy ON does not make\r\n // its provider live. `live` comes from the Host catalogue exclusively; using\r\n // `route.enabled` here made a card flip between \"offline\" and \"proxied\" as\r\n // the user toggled the switch, while no provider became available at all.\r\n const known = byId.get(id)\r\n rows.set(id, { id, name: known?.name ?? id, live: known?.live === 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/** Where the Host runs a per-provider connection self-check. */\r\nconst TEST_PATH = '/dsh-provider-proxy/test'\r\n\r\n/**\r\n * Latency bands for the self-check result, in milliseconds.\r\n *\r\n * The colour is decoration, never information: the numeric value is always\r\n * printed, so an unknown theme token (which resolves to `unset`) costs colour,\r\n * never the reading. The `var(..., fallback)` form keeps the colours visible even\r\n * if the theme renames the token.\r\n */\r\nconst LATENCY_FAST_MS = 500\r\nconst LATENCY_SLOW_MS = 1500\r\n/** The schema default for `testUrl`; also what \"Restore default\" writes. */\r\nconst DEFAULT_TEST_URL = 'https://api.ipify.org?format=json'\r\nconst MAX_TEST_URLS = 5\r\n\r\nfunction latencyColor(ms: unknown): string {\r\n if (typeof ms !== 'number' || !Number.isFinite(ms)) return 'var(--dsw-alias-label-secondary)'\r\n if (ms <= LATENCY_FAST_MS) return 'var(--dsw-alias-state-success-primary, #2ea043)'\r\n if (ms <= LATENCY_SLOW_MS) return 'var(--dsw-alias-state-warn-primary, #d29922)'\r\n return 'var(--dsw-alias-state-error-primary, #f85149)'\r\n}\r\n\r\n/** Normalize the Host's self-check payload into the shape the card renders. */\r\nfunction testResultFrom(body: any, strings: Record<string, string>): Record<string, unknown> {\r\n const ok = body?.ok === true\r\n return {\r\n pending: false,\r\n ok,\r\n ms: typeof body?.ms === 'number' && Number.isFinite(body.ms) ? body.ms : undefined,\r\n ip: typeof body?.exitIp === 'string' && body.exitIp.length > 0 ? body.exitIp : undefined,\r\n status:\r\n typeof body?.status === 'number' && Number.isInteger(body.status) ? body.status : undefined,\r\n target: typeof body?.target === 'string' && body.target.length > 0 ? body.target : undefined,\r\n targetSource:\r\n body?.targetSource === 'route' || body?.targetSource === 'upstream'\r\n ? body.targetSource\r\n : body?.targetSource === 'testUrl'\r\n ? 'testUrl'\r\n : undefined,\r\n cached: body?.cached === true,\r\n // The Host probes a target the way routing would: a loopback/private upstream\r\n // (or a bypassHosts match) is reached DIRECT, not through the proxy. The card\r\n // says so, so a green check is not read as \"the proxy works\".\r\n direct: body?.viaProxy === false,\r\n error: ok\r\n ? undefined\r\n : typeof body?.error === 'string' && body.error.length > 0\r\n ? body.error\r\n : strings.testFailed,\r\n }\r\n}\r\n\r\n/** Split `testUrl` the same way the Host does: commas or whitespace. */\r\nfunction splitTestUrls(raw: string): string[] {\r\n return raw\r\n .split(/[,\\s]+/)\r\n .map(entry => entry.trim())\r\n .filter(entry => entry.length > 0)\r\n}\r\n\r\n/**\r\n * Hint-only validation for `testUrl`.\r\n *\r\n * The Host does not refuse malformed candidates; it simply fails that check.\r\n * The page therefore warns without blocking the write, so a user can still save\r\n * a value the Host accepts (including an empty string, which means \"use the\r\n * built-in default\").\r\n */\r\nfunction testUrlHint(raw: string, t: Record<string, string>): string | undefined {\r\n const entries = splitTestUrls(raw)\r\n if (entries.length === 0) return t.testUrlEmptyHint\r\n const invalid = entries.filter(entry => !isAbsoluteHttpUrl(entry))\r\n if (invalid.length > 0) return t.testUrlInvalidHint\r\n if (entries.length > MAX_TEST_URLS) return t.testUrlTooManyHint\r\n return undefined\r\n}\r\n\r\nfunction isAbsoluteHttpUrl(value: string): boolean {\r\n try {\r\n const url = new URL(value)\r\n return (url.protocol === 'http:' || url.protocol === 'https:') && url.hostname.length > 0\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * Where the check's target came from, in the card's own words.\r\n *\r\n * The target is NOT always the top-level `testUrl`: a route's own\r\n * `testTarget` wins, then the provider's REAL upstream, and only a provider\r\n * that publishes none falls back to `testUrl`. Saying so is what explains why\r\n * editing `testUrl` changed one card and not another.\r\n */\r\nfunction targetSourceSuffix(\r\n result: { targetSource?: unknown },\r\n t: Record<string, string>,\r\n): string {\r\n switch (result.targetSource) {\r\n case 'route':\r\n return t.targetSourceRoute\r\n case 'upstream':\r\n return t.targetSourceUpstream\r\n case 'testUrl':\r\n return t.targetSourceTestUrl\r\n default:\r\n return ''\r\n }\r\n}\r\n\r\n/**\r\n * Remove values and URL credentials from text that will be shown to the user.\r\n *\r\n * Settings errors may quote the rejected value. A password field must never\r\n * echo that value, even inside an otherwise useful error message, so exact\r\n * known secrets are replaced before anything is rendered or written to the\r\n * diagnostics panel.\r\n */\r\nfunction redactSensitiveText(text: string, secrets: readonly unknown[] = []): string {\r\n let safe = text\r\n for (const secret of secrets) {\r\n if (typeof secret !== 'string' || secret.length === 0) continue\r\n safe = safe.split(secret).join('***')\r\n }\r\n // A URL in an error may carry userinfo and query/fragment values even when\r\n // the individual secret is not known to this call.\r\n safe = safe.replace(/\\b([a-z][a-z0-9+.-]*:\\/\\/)[^/@\\s]+@/gi, '$1')\r\n safe = safe.replace(/([?&#])[^\\s\"'<>]*/g, '$1')\r\n return safe.length > 500 ? `${safe.slice(0, 500)}\u2026` : safe\r\n}\r\n\r\n/** Values that may be echoed by a failed multi-field write. */\r\nfunction secretsFromOps(ops: readonly any[]): string[] {\r\n const out: string[] = []\r\n for (const op of ops) {\r\n const field = op?.path?.[op.path.length - 1]\r\n if (field === 'password' && typeof op?.value === 'string' && op.value.length > 0) {\r\n out.push(op.value)\r\n }\r\n }\r\n return out\r\n}\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: ((catalog: Catalog) => void) | undefined = () => {}\r\n\r\n/** How one provider's last proxied request ended, as the Host recorded it. */\r\ntype LastUse = {\r\n /** When the most recent proxied request BEGAN. */\r\n startedAt?: number\r\n /** When the last request that FINISHED ended; paired with `ok`/`code`. */\r\n at?: number\r\n ok?: boolean\r\n code?: string\r\n}\r\n\r\n/** What the Host endpoint publishes: provider rows, hit counts, rejected routes. */\r\ntype Catalog = {\r\n rows: ProviderRow[]\r\n /**\r\n * Exactly what the Host published, before `knownProviders` merges saved\r\n * routes in. N7 must compare against this set: comparing against `rows`\r\n * would make every saved provider look published.\r\n */\r\n publishedRows: ProviderRow[]\r\n hits: Record<string, number>\r\n problems: Record<string, string>\r\n lastUse: Record<string, LastUse>\r\n /** Set when the FIRST read failed; a later successful poll clears it. */\r\n error?: string\r\n}\r\n\r\n/**\r\n * A coarse \"how long ago\", for the last-use line.\r\n *\r\n * Deliberately coarse: the page only re-reads the catalogue every 10 s, so a\r\n * second-precision string would look stale on its own and mean nothing.\r\n */\r\nfunction relativeTime(at: number, t: Record<string, string>): string {\r\n const seconds = Math.max(0, Math.round((Date.now() - at) / 1000))\r\n if (seconds < 60) return t.justNow\r\n const minutes = Math.floor(seconds / 60)\r\n if (minutes < 60) return `${minutes}${t.minutesAgo}`\r\n const hours = Math.floor(minutes / 60)\r\n if (hours < 24) return `${hours}${t.hoursAgo}`\r\n return `${Math.floor(hours / 24)}${t.daysAgo}`\r\n}\r\n\r\n/** Read the Host's provider catalogue. Same-origin, so no token is needed. */\r\nasync function fetchCatalog(): Promise<Catalog> {\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 const rows = 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 // The Host counts requests it routed through each provider's proxy. Anything\r\n // malformed is dropped rather than rendered, so a bad payload cannot put a\r\n // non-numeric string on the page.\r\n const hits: Record<string, number> = {}\r\n const published = body?.hits\r\n if (published !== null && typeof published === 'object') {\r\n for (const [id, count] of Object.entries(published)) {\r\n if (typeof count === 'number' && Number.isFinite(count)) hits[id] = count\r\n }\r\n }\r\n // A route the Host REFUSED (a bad port, half-filled credentials) is absent from\r\n // the provider list entirely, so this map is the only place that says why it is\r\n // missing. The Host already stripped the log prefix from it.\r\n const problems: Record<string, string> = {}\r\n const rejected = body?.problems\r\n if (rejected !== null && typeof rejected === 'object') {\r\n for (const [id, message] of Object.entries(rejected)) {\r\n if (typeof message === 'string' && message.length > 0) problems[id] = message\r\n }\r\n }\r\n // The last-use record: when each provider's most recent proxied request\r\n // began, and \u2014 separately \u2014 how the last request that FINISHED ended. Anything\r\n // malformed is dropped rather than rendered, so a bad payload cannot put a\r\n // non-numeric timestamp on the page. An entry carrying only `startedAt` is\r\n // kept: it is a request still in flight, and the page says when it was started.\r\n const lastUse: Record<string, LastUse> = {}\r\n const publishedLastUse = body?.lastUse\r\n if (publishedLastUse !== null && typeof publishedLastUse === 'object') {\r\n for (const [id, raw] of Object.entries(publishedLastUse)) {\r\n const entry = raw as LastUse | undefined\r\n if (entry === null || typeof entry !== 'object') continue\r\n const at = typeof entry.at === 'number' && Number.isFinite(entry.at) ? entry.at : undefined\r\n const startedAt =\r\n typeof entry.startedAt === 'number' && Number.isFinite(entry.startedAt)\r\n ? entry.startedAt\r\n : undefined\r\n if (at === undefined && startedAt === undefined) continue\r\n lastUse[id] = {\r\n ...(startedAt === undefined ? {} : { startedAt }),\r\n ...(at === undefined ? {} : { at }),\r\n ...(typeof entry.ok === 'boolean' ? { ok: entry.ok } : {}),\r\n ...(typeof entry.code === 'string' && entry.code.length > 0 ? { code: entry.code } : {}),\r\n }\r\n }\r\n }\r\n return { rows, publishedRows: rows, hits, problems, lastUse }\r\n}\r\n\r\n/**\r\n * Catalogue polling while the page is open.\r\n *\r\n * The catalogue (published rows, hit counts, rejected routes) is fetched once at\r\n * mount and would otherwise stay a snapshot for the page's lifetime: the hit\r\n * counter never moves, and a route the Host starts or stops refusing stays\r\n * invisible. One shared interval re-fetches it every CATALOG_REFRESH_MS.\r\n *\r\n * `touchCatalogPolling` runs on every render. Writing the module-level timestamp\r\n * there is deliberately not treated as a render side effect: it is idempotent,\r\n * re-enters nothing (unlike a setState during render), and it is the only signal\r\n * that the page is still alive. A page that stops rendering \u2014 a closed panel \u2014\r\n * goes stale, and the next tick cancels the interval instead of fetching for\r\n * nobody. A failed poll is swallowed: the page keeps its last data, and the\r\n * mount-time fetch already reports a broken endpoint in the diagnostics.\r\n */\r\nconst CATALOG_REFRESH_MS = 10_000\r\nlet catalogPoll: ReturnType<typeof setInterval> | undefined\r\nlet catalogTouchedAt = 0\r\n\r\nfunction touchCatalogPolling(): void {\r\n catalogTouchedAt = Date.now()\r\n if (catalogPoll !== undefined) return\r\n catalogPoll = setInterval(() => {\r\n if (Date.now() - catalogTouchedAt > CATALOG_REFRESH_MS * 2 + 1_000) {\r\n clearInterval(catalogPoll)\r\n catalogPoll = undefined\r\n return\r\n }\r\n void fetchCatalog()\r\n .then(catalog => catalogueSetter?.(catalog))\r\n .catch(() => undefined)\r\n }, CATALOG_REFRESH_MS)\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 useDefault: route?.useDefault === 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 onlyHosts: route?.onlyHosts ?? '',\r\n bypassHosts: route?.bypassHosts ?? '',\r\n testTarget: route?.testTarget ?? '',\r\n }\r\n}\r\n\r\n/** Drop the brackets WHATWG URL keeps on an IPv6 literal host. */\r\nfunction unbracket(hostname: string): string {\r\n return hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname\r\n}\r\n\r\n/**\r\n * Split a pasted full proxy URL into route fields, or `undefined` when the text\r\n * is not one.\r\n *\r\n * `socks5` is a NON-special scheme, so WHATWG URL still parses its userinfo and\r\n * port (verified), but three quirks are handled here:\r\n * - the userinfo is NOT percent-decoded by the parser, so it is decoded here;\r\n * - an IPv6 literal comes back bracketed, and the host field wants it bare;\r\n * - a DEFAULT port is stripped by WHATWG for http/https; the original text is\r\n * consulted so an explicitly written :80/:443 is preserved, while an absent\r\n * port still stays 0 (\"not configured\") instead of being invented.\r\n */\r\nfunction explicitPortOf(text: string): number {\r\n const authority = text.slice(text.indexOf('://') + 3).split(/[/?#]/, 1)[0]\r\n const hostPort = authority.slice(authority.lastIndexOf('@') + 1)\r\n const match = /^\\[[^\\]]+\\]:(\\d+)$/.exec(hostPort) ?? /^[^:]+:(\\d+)$/.exec(hostPort)\r\n if (match === null) return 0\r\n const port = Number.parseInt(match[1], 10)\r\n return Number.isNaN(port) ? 0 : port\r\n}\r\n\r\nfunction splitProxyUrl(text: string): Partial<RouteValue> | undefined {\r\n const trimmed = text.trim()\r\n if (!/^[a-z][a-z0-9+.-]*:\\/\\//i.test(trimmed)) return undefined\r\n let url: URL\r\n try {\r\n url = new URL(trimmed)\r\n } catch {\r\n return undefined\r\n }\r\n const scheme = url.protocol.slice(0, -1).toLowerCase()\r\n // `socks://` is a common spelling this plugin does not accept on its own;\r\n // normalizing it here means a pasted alias still lands on the supported\r\n // transport instead of being rejected later.\r\n const protocol = scheme === 'socks' ? 'socks5' : scheme\r\n if (!PROTOCOLS.includes(protocol as Protocol)) return undefined\r\n if (url.hostname.length === 0) return undefined\r\n const decode = (value: string): string => {\r\n try {\r\n return decodeURIComponent(value)\r\n } catch {\r\n return value\r\n }\r\n }\r\n const parsedPort = url.port.length > 0\r\n ? Number.parseInt(url.port, 10)\r\n : explicitPortOf(trimmed)\r\n return {\r\n protocol: protocol as Protocol,\r\n host: unbracket(url.hostname),\r\n port: Number.isNaN(parsedPort) ? 0 : parsedPort,\r\n username: decode(url.username),\r\n password: decode(url.password),\r\n }\r\n}\r\n\r\n/**\r\n * Pending writes, one debounced timer per provider+field.\r\n *\r\n * Every keystroke of an input fires `bind`, and the Host rebuilds its whole\r\n * proxy table on each settings write (`loader/volatile-update` \u2192 `rebuild()`).\r\n * Writing per keystroke therefore churns a dispatcher generation per character \u2014\r\n * and, worse, a half-typed credential (\"username without a password\") hits the\r\n * Host guards between keystrokes, so the route is refused for an instant and a\r\n * misleading problem is recorded. Only the LAST value of a burst needs to reach\r\n * the Host; the draft already gives the control its instant feedback.\r\n *\r\n * Module-level, so the timers survive a re-render (each pass rebuilds `save`)\r\n * and a page unmount: a write that was already promised still lands.\r\n */\r\nconst WRITE_DELAY_MS = 300\r\ntype PendingWrite = { timer?: ReturnType<typeof setTimeout>; flush: () => Promise<void> }\r\nconst pendingWrites = new Map<string, PendingWrite>()\r\n\r\n/**\r\n * Writes are serialized so a test can await every write it flushed without\r\n * racing the settings revision fence. A run handles its own failures, so the\r\n * tail never rejects the next write.\r\n */\r\nlet writeQueue: Promise<void> = Promise.resolve()\r\nfunction enqueueWrite(run: () => Promise<void>): Promise<void> {\r\n const next = writeQueue.then(run, run)\r\n writeQueue = next.catch(() => undefined)\r\n return next\r\n}\r\n\r\n/** Schedule one debounced write; `flush` runs it immediately and only once. */\r\nfunction scheduleWrite(key: string, run: () => Promise<void>): void {\r\n const pending = pendingWrites.get(key)\r\n if (pending?.timer !== undefined) clearTimeout(pending.timer)\r\n const entry: PendingWrite = {\r\n flush: () => {\r\n if (entry.timer !== undefined) clearTimeout(entry.timer)\r\n pendingWrites.delete(key)\r\n return enqueueWrite(run)\r\n },\r\n }\r\n entry.timer = setTimeout(() => { void entry.flush() }, WRITE_DELAY_MS)\r\n pendingWrites.set(key, entry)\r\n}\r\n\r\n/**\r\n * A self-check result belongs to the configuration it was measured against.\r\n * Every relevant edit bumps this counter; a response that started under an older\r\n * generation is discarded instead of being pasted onto the new settings.\r\n */\r\nconst testGeneration = new Map<string, number>()\r\nconst TEST_RELEVANT_FIELDS = new Set([\r\n 'protocol',\r\n 'host',\r\n 'port',\r\n 'username',\r\n 'password',\r\n 'onlyHosts',\r\n 'bypassHosts',\r\n 'testTarget',\r\n 'useDefault',\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 /** An enabled route the Host refused: active-looking styling would be a lie. */\r\n cardRejected: {\r\n borderColor: 'var(--dsw-alias-state-error-primary, #f85149)',\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 hits: {\r\n flex: 'none',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n whiteSpace: 'nowrap',\r\n },\r\n testRow: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '10px',\r\n flexWrap: 'wrap',\r\n },\r\n testButton: {\r\n padding: '5px 12px',\r\n border: '1px solid var(--dsw-alias-border-l1)',\r\n borderRadius: '6px',\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 cursor: 'pointer',\r\n },\r\n /** The reveal/hide control sits inside the password field's right edge. */\r\n passwordControl: {\r\n position: 'relative',\r\n minWidth: '0',\r\n },\r\n passwordToggle: {\r\n position: 'absolute',\r\n top: '50%',\r\n right: '4px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n width: '26px',\r\n height: '26px',\r\n padding: '0',\r\n border: '0',\r\n borderRadius: '6px',\r\n background: 'transparent',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n lineHeight: '1',\r\n transform: 'translateY(-50%)',\r\n cursor: 'pointer',\r\n },\r\n testResult: {\r\n // A flex row so the target can drop onto its own line: the container was a\r\n // plain span, where `flexBasis: 100%` does nothing and the target ran into\r\n // the \"cached\" label.\r\n display: 'flex',\r\n flexWrap: 'wrap',\r\n alignItems: 'baseline',\r\n columnGap: '6px',\r\n rowGap: '2px',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n wordBreak: 'break-all',\r\n },\r\n /**\r\n * A failed check is the answer, not decoration: it takes the error colour and\r\n * a heavier weight, unlike the latency band colour which only tints a number\r\n * that is printed anyway.\r\n */\r\n testFailure: {\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n fontWeight: '500',\r\n },\r\n /** A rejected route is a failure of the settings, not a warning about them. */\r\n diagProblem: {\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n },\r\n /** Informational catalogue mismatch: not a rejected route, so no error red. */\r\n diagNote: {\r\n color: 'var(--dsw-alias-label-secondary)',\r\n },\r\n advanced: {\r\n marginTop: '4px',\r\n fontSize: '12px',\r\n },\r\n advancedSummary: {\r\n cursor: 'pointer',\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 pillRejected: {\r\n border: '1px solid var(--dsw-alias-state-error-primary, #f85149)',\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n },\r\n /**\r\n * The shared default endpoint sits on its own layer so it reads as global\r\n * rather than as one more provider card \u2014 the mistake it exists to prevent is\r\n * a user typing the same address into every card.\r\n */\r\n defaultCard: {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '10px',\r\n padding: '14px 16px',\r\n border: '1px solid var(--dsw-alias-border-l2)',\r\n borderRadius: '10px',\r\n background: 'var(--dsw-alias-bg-layer-2)',\r\n },\r\n defaultLead: {\r\n margin: '-2px 0 0',\r\n fontSize: '11px',\r\n lineHeight: '1.5',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n },\r\n inheritNote: {\r\n margin: '0',\r\n fontSize: '11px',\r\n lineHeight: '1.5',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n },\r\n /** The default is not configured: an answer, so it takes the error colour. */\r\n inheritWarning: {\r\n margin: '0',\r\n fontSize: '11px',\r\n lineHeight: '1.5',\r\n fontWeight: '500',\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n },\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 diag: {\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 hint: {\r\n gridColumn: '2',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\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 fetchCatalog()\r\n .then(catalog => catalogueSetter?.(catalog))\r\n .catch((error: any) => {\r\n catalogueSetter?.({\r\n rows: [],\r\n publishedRows: [],\r\n hits: {},\r\n problems: {},\r\n lastUse: {},\r\n error: String(error?.message ?? error),\r\n })\r\n })\r\n return {\r\n rows: undefined as ProviderRow[] | undefined,\r\n publishedRows: undefined as ProviderRow[] | undefined,\r\n hits: {} as Record<string, number>,\r\n problems: {} as Record<string, string>,\r\n lastUse: {} as Record<string, LastUse>,\r\n error: undefined as string | undefined,\r\n pending: true,\r\n }\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 = catalog =>\r\n setState({\r\n rows: catalog.rows,\r\n publishedRows: catalog.publishedRows,\r\n hits: catalog.hits,\r\n problems: catalog.problems,\r\n lastUse: catalog.lastUse,\r\n error: catalog.error,\r\n pending: false,\r\n })\r\n // Keeps the catalogue (rows, hit counts, rejected routes) current while the\r\n // page is open; see the function's own notes for the staleness handling.\r\n touchCatalogPolling()\r\n\r\n const published = state.rows ?? []\r\n const publishedRows = state.publishedRows ?? []\r\n const hits = state.hits ?? {}\r\n const lastUse = state.lastUse ?? {}\r\n\r\n /**\r\n * The one-line last-use summary for a card, or `undefined` when the route has\r\n * never carried a request. `hits` says the route HAS been used; this says\r\n * whether it still works \u2014 the question a silently stalled proxy raises.\r\n *\r\n * A success or failure uses `at`, the time the last request FINISHED \u2014 the\r\n * time its outcome belongs to. A request that has only STARTED uses\r\n * `startedAt`, so a still-in-flight call cannot make the page claim an outcome\r\n * it does not have yet.\r\n */\r\n const lastUseText = (id: string): string | undefined => {\r\n const use = lastUse[id]\r\n if (use === undefined) return undefined\r\n if (use.ok === true) return `${t.recentOk}${relativeTime(use.at ?? use.startedAt ?? Date.now(), t)}`\r\n if (use.ok === false) return `${t.recentFail}${use.code ?? 'ERROR'}`\r\n return `${t.recentStarted}${relativeTime(use.startedAt ?? use.at ?? Date.now(), t)}`\r\n }\r\n // Rendered straight from state rather than through `note()`: `diagnostics` is\r\n // cleared at the start of every render, so a note written when the catalog\r\n // arrives would not survive to the next pass.\r\n const problems = state.problems ?? {}\r\n const problemLines = Object.entries(problems).map(([id, message]) =>\r\n h('li', { key: `p:${id}`, style: S.diagProblem }, `${id}\uFF1A${message}`),\r\n )\r\n const publishedIds = new Set(publishedRows.map((row: ProviderRow) => row.id))\r\n const missingFromCatalog =\r\n state.pending === true || state.error !== undefined\r\n ? []\r\n : Object.keys(configured)\r\n .filter(id => !publishedIds.has(id))\r\n .sort()\r\n const catalogueMismatchLine =\r\n missingFromCatalog.length === 0\r\n ? undefined\r\n : h(\r\n 'li',\r\n { key: 'catalogue-mismatch', style: S.diagNote },\r\n `${t.catalogueMismatch}${missingFromCatalog.join('\u3001')}${t.catalogueMismatchSuffix}`,\r\n )\r\n const problemCount = problemLines.length + (catalogueMismatchLine === undefined ? 0 : 1)\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 /**\r\n * The shared default endpoint gets its own draft for the same reason a card\r\n * does: its controls must show an edit before the debounced write lands.\r\n *\r\n * It is deliberately NOT stored under a sentinel key inside `draft`:\r\n * `knownProviders` unions the stored config with the draft to build the card\r\n * list, so such a key would surface as a phantom provider with no name.\r\n */\r\n const [defaultDraft, setDefaultDraft] = (React.useState ?? ((v: any) => [v, () => {}]))({})\r\n const editDefault = (field: string, value: unknown) =>\r\n setDefaultDraft((current: any) => ({ ...current, [field]: value }))\r\n\r\n /**\r\n * Whether each password input is temporarily shown as plain text.\r\n *\r\n * Provider cards are keyed by id; the shared default has its own state so a\r\n * real provider named `default` cannot collide with it. This is view state\r\n * only: it is deliberately not persisted and never written to the settings.\r\n */\r\n const [passwordVisible, setPasswordVisible] = (React.useState ?? ((v: any) => [v, () => {}]))({})\r\n const [defaultPasswordVisible, setDefaultPasswordVisible] = (React.useState ?? ((v: any) => [v, () => {}]))(false)\r\n const togglePassword = (id: string): void =>\r\n setPasswordVisible((current: any) => ({ ...current, [id]: current[id] !== true }))\r\n const toggleDefaultPassword = (): void =>\r\n setDefaultPasswordVisible((current: boolean) => current !== true)\r\n const passwordToggle = (visible: boolean, onToggle: () => void): unknown =>\r\n h(\r\n 'button',\r\n {\r\n className: styles.passwordToggle,\r\n style: S.passwordToggle,\r\n type: 'button',\r\n 'aria-label': visible ? t.hidePassword : t.showPassword,\r\n 'aria-pressed': visible,\r\n title: visible ? t.hidePassword : t.showPassword,\r\n onClick: onToggle,\r\n },\r\n h(\r\n 'svg',\r\n {\r\n width: 16,\r\n height: 16,\r\n viewBox: '0 0 24 24',\r\n fill: 'none',\r\n stroke: 'currentColor',\r\n strokeWidth: 2,\r\n strokeLinecap: 'round',\r\n strokeLinejoin: 'round',\r\n 'aria-hidden': 'true',\r\n focusable: 'false',\r\n },\r\n h('path', {\r\n key: 'eye',\r\n d: 'M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z',\r\n }),\r\n h('circle', { key: 'pupil', cx: 12, cy: 12, r: 3 }),\r\n visible ? h('path', { key: 'slash', d: 'm3 3 18 18' }) : null,\r\n ),\r\n )\r\n\r\n /**\r\n * The advanced global fields live outside `draft` on purpose: `draft` is keyed\r\n * by provider id, and a sentinel would surface as a phantom provider row.\r\n */\r\n const [globalDraft, setGlobalDraft] = (React.useState ?? ((v: any) => [v, () => {}]))({})\r\n const editGlobal = (field: string, value: unknown) =>\r\n setGlobalDraft((current: any) => ({ ...current, [field]: value }))\r\n\r\n /** The latest refused write, shown above the cards instead of in the fold. */\r\n const [saveError, setSaveError] = (React.useState ?? ((v: any) => [v, () => {}]))(undefined)\r\n /** The latest accepted write, rendered in the diagnostics on the next pass. */\r\n const [savedNote, setSavedNote] = (React.useState ?? ((v: any) => [v, () => {}]))(undefined)\r\n\r\n // Self-check outcomes keyed by provider id: `{ pending: true }` while the Host\r\n // is testing, then the normalized result the card renders.\r\n const [tests, setTests] = (React.useState ?? ((v: any) => [v, () => {}]))({})\r\n\r\n /** Drop results for these providers and invalidate any response in flight. */\r\n const invalidateTests = (ids: readonly string[]): void => {\r\n if (ids.length === 0) return\r\n for (const id of ids) {\r\n testGeneration.set(id, (testGeneration.get(id) ?? 0) + 1)\r\n }\r\n setTests((current: any) => {\r\n let changed = false\r\n const next = { ...current }\r\n for (const id of ids) {\r\n if (next[id] === undefined) continue\r\n delete next[id]\r\n changed = true\r\n }\r\n return changed ? next : current\r\n })\r\n }\r\n\r\n /**\r\n * The list filter. Purely a view concern: it hides cards, it never touches a\r\n * saved setting, so a page with no filter one day still shows every route.\r\n */\r\n const [filter, setFilter] = (React.useState ?? ((v: any) => [v, () => {}]))('')\r\n\r\n /**\r\n * Run the Host's self-check for one provider.\r\n *\r\n * The check is not routed traffic, so it never changes the hit count; the count\r\n * on the card is read at mount and stays put until the page reloads.\r\n *\r\n * Pending writes for this provider (and the shared default it may inherit) are\r\n * flushed before the request: the Host reads the saved settings, not the draft,\r\n * so testing inside the 300 ms debounce would otherwise test the old endpoint.\r\n */\r\n const runTest = (id: string): void => {\r\n const generation = (testGeneration.get(id) ?? 0) + 1\r\n testGeneration.set(id, generation)\r\n setTests((current: any) => ({ ...current, [id]: { pending: true } }))\r\n void (async () => {\r\n try {\r\n for (const [key, entry] of [...pendingWrites]) {\r\n if (\r\n key.startsWith(`${id}\\u0000`) ||\r\n key.startsWith('\\u0000default\\u0000') ||\r\n key.startsWith('\\u0000global\\u0000')\r\n ) {\r\n void entry.flush()\r\n }\r\n }\r\n await writeQueue\r\n if (testGeneration.get(id) !== generation) return\r\n const response = await globalThis.fetch(TEST_PATH, {\r\n method: 'POST',\r\n headers: { 'content-type': 'application/json', accept: 'application/json' },\r\n body: JSON.stringify({ provider: id }),\r\n })\r\n const body = await response.json()\r\n if (testGeneration.get(id) !== generation) return\r\n setTests((current: any) => ({ ...current, [id]: testResultFrom(body, t) }))\r\n } catch (error: any) {\r\n if (testGeneration.get(id) !== generation) return\r\n setTests((current: any) => ({\r\n ...current,\r\n [id]: { pending: false, ok: false, error: String(error?.message ?? error) },\r\n }))\r\n }\r\n })()\r\n }\r\n\r\n const rows = knownProviders({ ...configured, ...draft }, published)\r\n\r\n /** Cards whose effective endpoint comes from the shared default. */\r\n const inheritingIds = (): string[] =>\r\n rows\r\n .filter(row => view({ ...configured[row.id], ...draft[row.id] }).useDefault === true)\r\n .map(row => row.id)\r\n\r\n /**\r\n * Persist one field, debounced per `key`: a burst of edits to the same control\r\n * collapses into ONE write carrying the last value. The control already shows\r\n * the new value via the draft, so this only has to succeed quietly; a refusal\r\n * is reported in the diagnostics and undone by `onRefused`.\r\n */\r\n const save = (\r\n key: string,\r\n path: unknown[],\r\n label: string,\r\n value: unknown,\r\n onRefused: () => void,\r\n ) => {\r\n const field = path[path.length - 1]\r\n const secret = field === 'password' && typeof value === 'string' ? value : undefined\r\n const safeLabel = secret === undefined ? label : `${label}\uFF08\u503C\u5DF2\u9690\u85CF\uFF09`\r\n scheduleWrite(key, () =>\r\n writeConfig(ctx, [{ op: 'set', path, value }])\r\n .then(() => {\r\n setSaveError(undefined)\r\n setSavedNote(secret === undefined ? `\u5DF2\u4FDD\u5B58 ${label}` : `\u5DF2\u4FDD\u5B58 ${safeLabel}`)\r\n })\r\n .catch((error: any) => {\r\n const message = redactSensitiveText(String(error?.message ?? error), [\r\n ...(secret === undefined ? [] : [secret]),\r\n ])\r\n setSavedNote(undefined)\r\n setSaveError({ label: safeLabel, message })\r\n onRefused()\r\n }),\r\n )\r\n }\r\n\r\n /**\r\n * Undo ONE refused field in a card's draft.\r\n *\r\n * Only that field is dropped. Other fields of the same provider may hold edits\r\n * that are still pending or already accepted \u2014 dropping the whole draft entry\r\n * would throw away values the Host never objected to. An entry left empty by\r\n * the removal is dropped entirely, so it cannot keep a phantom row alive.\r\n */\r\n const rollbackRouteField = (id: string, field: string): void => {\r\n setDraft((current: any) => {\r\n const entry = current[id]\r\n if (entry === undefined || entry[field] === undefined) return current\r\n const nextEntry = { ...entry }\r\n delete nextEntry[field]\r\n const next = { ...current }\r\n if (Object.keys(nextEntry).length === 0) delete next[id]\r\n else next[id] = nextEntry\r\n return next\r\n })\r\n }\r\n\r\n /** One card 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 if (TEST_RELEVANT_FIELDS.has(field)) invalidateTests([id])\r\n save(`${id}\\u0000${field}`, ['providers', id, field], `${id}.${field}`, value, () =>\r\n rollbackRouteField(id, field),\r\n )\r\n }\r\n\r\n /** One default-block control: same contract, addressed at `defaultProxy`. */\r\n const bindDefault = (field: string) => (value: unknown) => {\r\n editDefault(field, value)\r\n invalidateTests(inheritingIds())\r\n save(`\\u0000default\\u0000${field}`, ['defaultProxy', field], `defaultProxy.${field}`, value, () => {\r\n // Same rule as a card field: drop only this field, and only if the draft\r\n // still holds it, so an already-accepted sibling edit is never discarded.\r\n setDefaultDraft((current: any) => {\r\n if (current[field] === undefined) return current\r\n const next = { ...current }\r\n delete next[field]\r\n return next\r\n })\r\n })\r\n }\r\n\r\n /** One advanced global control: draft, invalidate every check, persist. */\r\n const bindGlobal = (field: 'testUrl' | 'localDirect') => (value: unknown) => {\r\n editGlobal(field, value)\r\n invalidateTests(rows.map(row => row.id))\r\n save(`\\u0000global\\u0000${field}`, [field], field, value, () => {\r\n setGlobalDraft((current: any) => {\r\n if (current[field] === undefined) return current\r\n const next = { ...current }\r\n delete next[field]\r\n return next\r\n })\r\n })\r\n }\r\n\r\n /**\r\n * One debounced write carrying SEVERAL edits at once.\r\n *\r\n * Used for a pasted proxy URL: five separate writes would each rebuild the\r\n * Host's whole proxy table, and a half-applied paste (credentials without the\r\n * host, say) would hit the credential guards mid-burst \u2014 the same trap the\r\n * per-field debounce exists to avoid.\r\n */\r\n const saveMany = (key: string, ops: unknown[], label: string, onRefused: () => void) => {\r\n const secrets = secretsFromOps(ops as any[])\r\n const hidesValues = (ops as any[]).some(op => op?.path?.[op.path.length - 1] === 'password')\r\n const safeLabel = hidesValues ? `${label}\uFF08\u503C\u5DF2\u9690\u85CF\uFF09` : label\r\n scheduleWrite(key, () =>\r\n writeConfig(ctx, ops)\r\n .then(() => {\r\n setSaveError(undefined)\r\n setSavedNote(`\u5DF2\u4FDD\u5B58 ${safeLabel}`)\r\n })\r\n .catch((error: any) => {\r\n const message = redactSensitiveText(String(error?.message ?? error), secrets)\r\n setSavedNote(undefined)\r\n setSaveError({ label: safeLabel, message })\r\n onRefused()\r\n }),\r\n )\r\n }\r\n\r\n /** Undo one set of pasted fields in a card's draft. */\r\n const rollbackRouteFields = (id: string, fields: readonly string[]): void => {\r\n setDraft((current: any) => {\r\n const entry = current[id]\r\n if (entry === undefined) return current\r\n const nextEntry = { ...entry }\r\n for (const field of fields) delete nextEntry[field]\r\n const next = { ...current }\r\n if (Object.keys(nextEntry).length === 0) delete next[id]\r\n else next[id] = nextEntry\r\n return next\r\n })\r\n }\r\n\r\n /** Apply a parsed proxy URL to one card: one draft update, one write. */\r\n const applyCardUrl = (id: string, parts: Record<string, unknown>): void => {\r\n setDraft((current: any) => ({ ...current, [id]: { ...current[id], ...parts } }))\r\n invalidateTests([id])\r\n const fields = Object.keys(parts)\r\n saveMany(\r\n `${id}\\u0000*paste`,\r\n fields.map(field => ({ op: 'set', path: ['providers', id, field], value: parts[field] })),\r\n `${id}.*\uFF08\u7C98\u8D34\u4EE3\u7406 URL\uFF09`,\r\n () => rollbackRouteFields(id, fields),\r\n )\r\n }\r\n\r\n /** Apply a parsed proxy URL to the shared default endpoint. */\r\n const applyDefaultUrl = (parts: Record<string, unknown>): void => {\r\n setDefaultDraft((current: any) => ({ ...current, ...parts }))\r\n invalidateTests(inheritingIds())\r\n const fields = Object.keys(parts)\r\n saveMany(\r\n '\\u0000default\\u0000*paste',\r\n fields.map(field => ({ op: 'set', path: ['defaultProxy', field], value: parts[field] })),\r\n '\u9ED8\u8BA4\u4EE3\u7406\uFF08\u7C98\u8D34\u4EE3\u7406 URL\uFF09',\r\n () => {\r\n setDefaultDraft((current: any) => {\r\n const next = { ...current }\r\n for (const field of fields) delete next[field]\r\n return next\r\n })\r\n },\r\n )\r\n }\r\n\r\n /**\r\n * Promote a card's own endpoint to the shared default.\r\n *\r\n * The reduced form of \"copy this card to another\": once the endpoint lives in\r\n * the default block, every other card opts in with one switch, so a\r\n * multi-select picker would be a second way to do the same thing.\r\n */\r\n const promoteToDefault = (id: string): void => {\r\n if (\r\n defaultComplete &&\r\n inheritingIds().length > 0 &&\r\n globalThis.window?.confirm?.(t.confirmPromoteToDefault) !== true\r\n ) {\r\n return\r\n }\r\n const route = view({ ...configured[id], ...draft[id] })\r\n applyDefaultUrl({\r\n protocol: route.protocol,\r\n host: route.host.trim(),\r\n port: route.port,\r\n username: route.username,\r\n password: route.password,\r\n })\r\n }\r\n\r\n /** Point every card at the default endpoint, in one write. */\r\n const applyDefaultToAll = (): void => {\r\n const ids = rows.map(row => row.id)\r\n if (ids.length === 0) return\r\n setDraft((current: any) => {\r\n const next = { ...current }\r\n for (const id of ids) next[id] = { ...next[id], useDefault: true }\r\n return next\r\n })\r\n invalidateTests(ids)\r\n saveMany(\r\n '\\u0000default\\u0000applyAll',\r\n ids.map(id => ({ op: 'set', path: ['providers', id, 'useDefault'], value: true })),\r\n `\u6240\u6709 provider \u7684 useDefault\uFF08${ids.length} \u4E2A\uFF09`,\r\n () =>\r\n setDraft((current: any) => {\r\n const next = { ...current }\r\n for (const id of ids) {\r\n const entry = next[id]\r\n if (entry === undefined || entry.useDefault === undefined) continue\r\n const nextEntry = { ...entry }\r\n delete nextEntry.useDefault\r\n if (Object.keys(nextEntry).length === 0) delete next[id]\r\n else next[id] = nextEntry\r\n }\r\n return next\r\n }),\r\n )\r\n }\r\n\r\n /**\r\n * A paste handler for any proxy-address field.\r\n *\r\n * Only a RECOGNISED proxy URL is intercepted; anything else falls through to\r\n * the browser so a pasted bare host still lands in the field normally.\r\n */\r\n const onProxyUrlPaste =\r\n (apply: (parts: Record<string, unknown>) => void) =>\r\n (event: any): void => {\r\n const text = event?.clipboardData?.getData?.('text')\r\n if (typeof text !== 'string') return\r\n const parts = splitProxyUrl(text)\r\n if (parts === undefined) return\r\n event.preventDefault?.()\r\n apply(parts)\r\n }\r\n\r\n const field = (label: string, control: unknown, hint?: string, hintError?: boolean): 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 {\r\n className: styles.hint,\r\n style: {\r\n gridColumn: '2',\r\n fontSize: '11px',\r\n // A warning that a value can never work is an answer, not\r\n // decoration \u2014 same rule as the failed self-check text.\r\n ...(hintError === true\r\n ? { color: 'var(--dsw-alias-state-error-primary, #f85149)' }\r\n : {}),\r\n },\r\n },\r\n hint,\r\n ),\r\n )\r\n\r\n /**\r\n * The shared endpoint block, always rendered.\r\n *\r\n * It is the only place the address can be entered, so hiding it until some\r\n * card opts in would leave no way to configure it in the first place.\r\n */\r\n const storedDefault = (snapshot.value?.defaultProxy ?? {}) as Partial<RouteValue>\r\n const defaultView = view({ ...storedDefault, ...defaultDraft })\r\n // The SAME predicate the Host applies, imported rather than re-written: a\r\n // browser copy that only checked \"host non-empty and port in range\" called\r\n // `https://1.2.3.4` complete and enabled the bulk button, while the Host refused\r\n // every route pointed at it.\r\n //\r\n // The REASON is kept as well as the verdict: the block refuses for several\r\n // reasons (no host, a scheme-carrying host, a bad port, a half-filled\r\n // credential), and a card that said \"missing host or port\" for all of them sent\r\n // the user to the one field that was already correct.\r\n const defaultWhy = defaultProxyProblem(defaultView)\r\n // An empty optional block is \"not configured\", not a typed mistake. Only an\r\n // invalid NON-empty host gets the error colour under the input.\r\n const defaultHostWhy = defaultView.host.trim().length === 0\r\n ? undefined\r\n : proxyHostProblem(defaultView.host)\r\n const defaultComplete = defaultWhy === undefined\r\n const defaultOrigin = `${defaultView.protocol}://${defaultView.host}:${defaultView.port}`\r\n const defaultBlock = h(\r\n 'div',\r\n { className: styles.defaultCard, style: S.defaultCard, key: 'default-proxy' },\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 }, t.defaultTitle),\r\n ),\r\n h(\r\n 'span',\r\n {\r\n className: defaultComplete ? styles.pillOn : styles.pillOff,\r\n style: { ...S.pill, ...(defaultComplete ? S.pillOn : S.pillOff) },\r\n },\r\n defaultComplete ? t.complete : t.notConfigured,\r\n ),\r\n ),\r\n h('p', { className: styles.defaultLead, style: S.defaultLead }, t.defaultLead),\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 value: defaultView.protocol,\r\n onChange: (event: any) => bindDefault('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 ),\r\n field(\r\n t.host,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: '127.0.0.1',\r\n value: defaultView.host,\r\n onChange: (event: any) => bindDefault('host')(event.target.value),\r\n // Same convenience as the cards: a full URL fills the whole block.\r\n onPaste: onProxyUrlPaste(applyDefaultUrl),\r\n }),\r\n defaultHostWhy ?? t.hostHint,\r\n defaultHostWhy !== undefined,\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 type: 'number',\r\n min: 1,\r\n max: 65535,\r\n placeholder: '7890',\r\n value: defaultView.port === 0 ? '' : String(defaultView.port),\r\n onChange: (event: any) => {\r\n const parsed = Number.parseInt(event.target.value, 10)\r\n bindDefault('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 autoComplete: 'off',\r\n value: defaultView.username,\r\n onChange: (event: any) => bindDefault('username')(event.target.value),\r\n }),\r\n ),\r\n field(\r\n t.password,\r\n h(\r\n 'div',\r\n { style: S.passwordControl },\r\n h('input', {\r\n className: styles.input,\r\n style: { ...S.input, paddingRight: '36px' },\r\n type: defaultPasswordVisible === true ? 'text' : 'password',\r\n autoComplete: 'off',\r\n value: defaultView.password,\r\n onChange: (event: any) => bindDefault('password')(event.target.value),\r\n }),\r\n passwordToggle(defaultPasswordVisible === true, toggleDefaultPassword),\r\n ),\r\n t.passwordHintProxy,\r\n ),\r\n // Bulk opt-in, in ONE write: a per-card walk would rebuild the table N times.\r\n // Disabled while the default configuration is incomplete, because pointing every card at an\r\n // empty endpoint would just refuse them all.\r\n h(\r\n 'div',\r\n { style: S.testRow, key: 'default:apply' },\r\n h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: S.testButton,\r\n type: 'button',\r\n disabled: !defaultComplete || rows.length === 0,\r\n onClick: applyDefaultToAll,\r\n },\r\n `${t.applyDefaultAll}\uFF08${rows.length}\uFF09`,\r\n ),\r\n ),\r\n )\r\n\r\n const storedTestUrl =\r\n typeof snapshot.value?.testUrl === 'string' ? snapshot.value.testUrl : DEFAULT_TEST_URL\r\n const storedLocalDirect = snapshot.value?.localDirect !== false\r\n const globalTestUrl = typeof globalDraft.testUrl === 'string' ? globalDraft.testUrl : storedTestUrl\r\n const globalLocalDirect =\r\n typeof globalDraft.localDirect === 'boolean' ? globalDraft.localDirect : storedLocalDirect\r\n const globalTestUrlHint = testUrlHint(globalTestUrl, t)\r\n const globalBlock = h(\r\n 'details',\r\n {\r\n className: styles.diag,\r\n style: {\r\n ...S.diag,\r\n marginTop: '0',\r\n },\r\n key: 'global-settings',\r\n },\r\n h('summary', { className: styles.diagSummary }, t.globalTitle),\r\n h('p', { className: styles.defaultLead, style: S.defaultLead }, t.globalLead),\r\n h(\r\n 'label',\r\n { className: styles.field, style: S.field },\r\n h('span', { className: styles.label, style: S.label }, t.testUrl),\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n value: globalTestUrl,\r\n onChange: (event: any) => bindGlobal('testUrl')(event.target.value),\r\n }),\r\n globalTestUrlHint === undefined\r\n ? h('span', { style: S.hint }, t.testUrlHint)\r\n : h(\r\n 'span',\r\n {\r\n className: styles.hint,\r\n style: {\r\n ...S.hint,\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n },\r\n },\r\n globalTestUrlHint,\r\n ),\r\n ),\r\n h(\r\n 'div',\r\n { style: S.testRow },\r\n h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: S.testButton,\r\n type: 'button',\r\n onClick: () => bindGlobal('testUrl')(DEFAULT_TEST_URL),\r\n },\r\n t.restoreDefaultTestUrl,\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: globalLocalDirect,\r\n onChange: (event: any) => bindGlobal('localDirect')(event.target.checked === true),\r\n }),\r\n h('span', null, t.localDirect),\r\n ),\r\n h(\r\n 'p',\r\n { style: S.hint },\r\n globalLocalDirect ? t.localDirectOnHint : t.localDirectOffHint,\r\n ),\r\n )\r\n\r\n const query = filter.trim().toLowerCase()\r\n const shown =\r\n query.length === 0\r\n ? rows\r\n : rows.filter(row => `${row.id} ${row.name}`.toLowerCase().includes(query))\r\n const filterRow =\r\n rows.length === 0\r\n ? null\r\n : field(\r\n t.filterLabel,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: t.filterPlaceholder,\r\n value: filter,\r\n onChange: (event: any) => setFilter(event.target.value),\r\n }),\r\n )\r\n\r\n // The empty slot answers three different questions: still loading, the read\r\n // failed, or truly nothing to show. Only the last is the empty message.\r\n // With saved cards present, a failed first read is reported above them instead.\r\n const catalogueStatus = rows.length === 0\r\n ? state.pending\r\n ? { text: t.catalogueLoading, error: false }\r\n : state.error !== undefined\r\n ? { text: `${t.catalogueError}${state.error}`, error: true }\r\n : undefined\r\n : undefined\r\n const catalogueNotice =\r\n state.error !== undefined && rows.length > 0\r\n ? h(\r\n 'p',\r\n { key: 'catalogue-error', style: S.inheritWarning },\r\n `${t.catalogueStale}${state.error}`,\r\n )\r\n : null\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[] = shown.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: catalogueStatus?.error === true\r\n ? 'var(--dsw-alias-state-error-primary, #f85149)'\r\n : 'var(--dsw-alias-state-idle-primary)',\r\n ...(catalogueStatus?.error === true ? { fontWeight: '500' } : {}),\r\n },\r\n },\r\n catalogueStatus?.text ?? (query.length > 0 ? t.noMatch : t.empty),\r\n ),\r\n ]\r\n : shown.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 // The endpoint controls are editable whether or not the route is on: the\r\n // point of the self-check below is to verify a setting BEFORE switching\r\n // it on, which is impossible if the fields can only be typed into while\r\n // traffic is already flowing through them. `enabled` gates routing only.\r\n // The line exists only once a route has actually carried a request, so an\r\n // ENABLED route with no record yet says so \u2014 otherwise a missing line is\r\n // indistinguishable from the feature not existing. A disabled route stays\r\n // silent: it cannot have a record, and saying so on every off card is noise.\r\n const lastText = lastUseText(row.id) ?? (route.enabled ? t.noRecord : undefined)\r\n const result = tests[row.id]\r\n // Rule entries that can never match: flagged under the input instead of\r\n // failing silently \u2014 a dead `onlyHosts` entry means fail-closed sends\r\n // the traffic DIRECT while the user believes it is proxied.\r\n const onlyDead = deadRuleEntries(route.onlyHosts)\r\n const bypassDead = deadRuleEntries(route.bypassHosts)\r\n const useDefault = route.useDefault === true\r\n // Whether this card has an endpoint worth checking: an inheriting card\r\n // depends on the shared default being configured, an own-endpoint card on\r\n // its host and port being complete. Mirrors the Host's own build gate.\r\n const endpointStored = route.useDefault\r\n ? defaultComplete\r\n : route.host.trim().length > 0 &&\r\n Number.isInteger(route.port) &&\r\n route.port >= 1 &&\r\n route.port <= 65535\r\n const showTest = route.enabled || endpointStored\r\n // The Host's recorded problem is authoritative (it also covers dispatcher\r\n // construction); until the next catalogue poll, the shared predicate can\r\n // already prove the common endpoint mistakes. An unused route is never\r\n // \"rejected\" \u2014 it has not asked for anything yet.\r\n const problemText = ((): string | undefined => {\r\n const recorded = problems[row.id]\r\n if (recorded !== undefined) return recorded\r\n if (useDefault) return defaultComplete ? undefined : `${t.defaultMissing}${defaultWhy}`\r\n return route.enabled ? defaultProxyProblem(route) : undefined\r\n })()\r\n const rejected = route.enabled && problemText !== undefined\r\n // Built once and either rendered (this route carries its own address) or\r\n // replaced by a one-line note (it inherits the shared default), so a card\r\n // can never show an input that does not apply to it.\r\n const endpointFields = [\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 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 placeholder: '127.0.0.1',\r\n value: route.host,\r\n onChange: (event: any) => bind(row.id, 'host')(event.target.value),\r\n // A pasted full proxy URL fills every transport field at once.\r\n onPaste: onProxyUrlPaste(parts => applyCardUrl(row.id, parts)),\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 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 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 // Every transport accepts a password: SOCKS5 hands it to\r\n // Socks5ProxyAgent as an option, HTTP/HTTPS embed it in the proxy URL\r\n // userinfo (undici turns that into Proxy-Authorization). It is stored on\r\n // the route, so it lands in the settings file with the rest of the\r\n // config; the diagnostics only ever surface a credential-free origin.\r\n field(\r\n t.password,\r\n h(\r\n 'div',\r\n { style: S.passwordControl },\r\n h('input', {\r\n className: styles.input,\r\n style: { ...S.input, paddingRight: '36px' },\r\n type: passwordVisible[row.id] === true ? 'text' : '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 passwordToggle(passwordVisible[row.id] === true, () => togglePassword(row.id)),\r\n ),\r\n route.protocol === 'socks5' ? t.passwordHint : t.passwordHintProxy,\r\n ),\r\n ]\r\n // The pill describes the ROUTE, never provider availability: a saved\r\n // route can outlive the Host directory, and whether that directory lists\r\n // it must not make the proxy switch read as \"offline\" or \"proxied\".\r\n const pill = rejected\r\n ? { className: styles.pillRejected, style: { ...S.pill, ...S.pillRejected }, text: t.rejected }\r\n : route.enabled\r\n ? { className: styles.pillOn, style: { ...S.pill, ...S.pillOn }, text: t.on }\r\n : { className: styles.pillLive, style: { ...S.pill, ...S.pillLive }, text: t.off }\r\n return h(\r\n 'section',\r\n {\r\n className: rejected ? styles.cardRejected : route.enabled ? styles.cardActive : styles.card,\r\n style: rejected\r\n ? { ...S.card, ...S.cardRejected }\r\n : route.enabled\r\n ? { ...S.card, ...S.cardActive }\r\n : 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 // A disabled route can never have hits, so \"0\" there would only add\r\n // noise; the count shows once the route is on (or has counted).\r\n route.enabled || (hits[row.id] ?? 0) > 0\r\n ? h(\r\n 'span',\r\n { style: S.hits },\r\n `${t.hitCountPrefix}${hits[row.id] ?? 0}${t.hitCountSuffix}`,\r\n )\r\n : null,\r\n // The last-use line. A failure takes the error colour, same rule as\r\n // a failed self-check: it is an answer, not decoration.\r\n lastText === undefined\r\n ? null\r\n : h(\r\n 'span',\r\n {\r\n style: {\r\n ...S.hits,\r\n ...(lastUse[row.id]?.ok === false ? S.inheritWarning : {}),\r\n },\r\n },\r\n lastText,\r\n ),\r\n ),\r\n h('span', { className: pill.className, style: pill.style }, pill.text),\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 // Opting into the shared endpoint. The card then shows the address it\r\n // will actually use \u2014 or, when the default is not configured, why the\r\n // route is refused \u2014 instead of a set of empty inputs the user never\r\n // filled and cannot interpret.\r\n h(\r\n 'label',\r\n { className: styles.toggle, style: S.toggle, key: `${row.id}:usedefault` },\r\n h('input', {\r\n type: 'checkbox',\r\n checked: useDefault,\r\n onChange: (event: any) => bind(row.id, 'useDefault')(event.target.checked === true),\r\n }),\r\n h('span', null, t.useDefault),\r\n ),\r\n problemText !== undefined\r\n ? h('p', { key: `${row.id}:problem`, style: S.inheritWarning }, problemText)\r\n : useDefault\r\n ? h(\r\n 'p',\r\n { key: `${row.id}:inherit`, style: S.inheritNote },\r\n `${t.inheritingDefault}${defaultOrigin}`,\r\n )\r\n : null,\r\n ...(useDefault ? [] : endpointFields),\r\n // The self-check is offered whenever there is something to check: an\r\n // enabled route (the Host's table carries it, and a rejected one still\r\n // reports WHY), or a disabled one whose endpoint is already complete \u2014\r\n // the Host builds that one for the check alone. A disabled route with\r\n // no endpoint has nothing to test and would only answer \"not enabled\".\r\n showTest\r\n ? h(\r\n 'div',\r\n { style: S.testRow, key: `${row.id}:test` },\r\n // A check on a route that is still off is a trial run, and it says\r\n // so \u2014 otherwise the result reads as though the route were live.\r\n route.enabled ? null : h('span', { style: S.testResult }, t.testDisabledNote),\r\n h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: S.testButton,\r\n type: 'button',\r\n disabled: result?.pending === true,\r\n onClick: () => runTest(row.id),\r\n },\r\n result?.pending === true ? t.testRunning : t.testButton,\r\n ),\r\n result?.pending === false\r\n ? h(\r\n 'div',\r\n { style: S.testResult },\r\n result.ok === true\r\n ? [\r\n // The band colour belongs to the LATENCY alone. The\r\n // status sits beside it in the plain label colour:\r\n // colouring the whole line made a successful check\r\n // over 1500 ms read as a failure.\r\n h(\r\n 'span',\r\n { key: 'lat', style: { color: latencyColor(result.ms) } },\r\n `\u2713 ${typeof result.ms === 'number' ? result.ms : '\u2014'} ms`,\r\n ),\r\n typeof result.status === 'number'\r\n ? h(\r\n 'span',\r\n { key: 'status' },\r\n `HTTP ${result.status}`,\r\n )\r\n : null,\r\n result.ip === undefined\r\n ? null\r\n : h('span', { key: 'ip' }, `${t.exitIpLabel}${result.ip}`),\r\n result.direct === true\r\n ? h('span', { key: 'direct' }, t.directLabel)\r\n : null,\r\n result.cached === true\r\n ? h('span', { key: 'cached' }, t.cachedLabel)\r\n : null,\r\n result.target === undefined\r\n ? null\r\n : h(\r\n 'span',\r\n {\r\n key: 'target',\r\n style: {\r\n flexBasis: '100%',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n wordBreak: 'break-all',\r\n },\r\n },\r\n `${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}`,\r\n ),\r\n ]\r\n : [\r\n h('span', { key: 'err', style: S.testFailure }, `\u2717 ${result.error}`),\r\n typeof result.status === 'number'\r\n ? h('span', { key: 'status' }, `HTTP ${result.status}`)\r\n : null,\r\n result.target === undefined\r\n ? null\r\n : h(\r\n 'span',\r\n {\r\n key: 'target',\r\n style: {\r\n flexBasis: '100%',\r\n fontSize: '11px',\r\n color: 'var(--dsw-alias-label-secondary)',\r\n wordBreak: 'break-all',\r\n },\r\n },\r\n `${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}`,\r\n ),\r\n ],\r\n )\r\n : null,\r\n // Promote this card's endpoint to the shared default. Offered only\r\n // when the card carries its OWN endpoint: an inheriting card would\r\n // just be copying the default onto itself.\r\n endpointStored && !useDefault\r\n ? h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: S.testButton,\r\n type: 'button',\r\n onClick: () => promoteToDefault(row.id),\r\n },\r\n t.setAsDefault,\r\n )\r\n : null,\r\n )\r\n : null,\r\n // Target-host rules, collapsed so the common case stays one short card.\r\n h(\r\n 'details',\r\n { style: S.advanced, key: `${row.id}:rules` },\r\n h('summary', { style: S.advancedSummary }, t.advanced),\r\n field(\r\n t.onlyHosts,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: 'api.example.com',\r\n value: route.onlyHosts,\r\n onChange: (event: any) => bind(row.id, 'onlyHosts')(event.target.value),\r\n }),\r\n onlyDead.length === 0 ? t.onlyHostsHint : `${t.ruleDeadHint}${onlyDead.join('\u3001')}`,\r\n onlyDead.length > 0,\r\n ),\r\n field(\r\n t.bypassHosts,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: 'localhost',\r\n value: route.bypassHosts,\r\n onChange: (event: any) => bind(row.id, 'bypassHosts')(event.target.value),\r\n }),\r\n bypassDead.length === 0 ? t.bypassHostsHint : `${t.ruleDeadHint}${bypassDead.join('\u3001')}`,\r\n bypassDead.length > 0,\r\n ),\r\n // The self-check target: empty uses the top-level testUrl, set makes\r\n // this card's Test request this URL \u2014 a real upstream proves the whole\r\n // path, not just the proxy hop.\r\n field(\r\n t.testTarget,\r\n h('input', {\r\n className: styles.input,\r\n style: S.input,\r\n placeholder: 'https://api.example.com',\r\n value: route.testTarget,\r\n onChange: (event: any) => bind(row.id, 'testTarget')(event.target.value),\r\n }),\r\n t.testTargetHint,\r\n ),\r\n ),\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 saveError === undefined\r\n ? null\r\n : h(\r\n 'div',\r\n {\r\n role: 'alert',\r\n key: 'save-error',\r\n style: {\r\n display: 'flex',\r\n alignItems: 'flex-start',\r\n justifyContent: 'space-between',\r\n gap: '10px',\r\n padding: '8px 10px',\r\n border: '1px solid var(--dsw-alias-state-error-primary, #f85149)',\r\n borderRadius: '8px',\r\n background: 'var(--dsw-alias-bg-layer-1)',\r\n color: 'var(--dsw-alias-state-error-primary, #f85149)',\r\n fontSize: '12px',\r\n fontWeight: '500',\r\n wordBreak: 'break-all',\r\n },\r\n },\r\n h('span', null, `${t.saveFailedPrefix}${saveError.label} \u2014 ${saveError.message}`),\r\n h(\r\n 'button',\r\n {\r\n className: styles.testButton,\r\n style: { ...S.testButton, flex: 'none' },\r\n type: 'button',\r\n onClick: () => setSaveError(undefined),\r\n },\r\n t.close,\r\n ),\r\n ),\r\n defaultBlock,\r\n globalBlock,\r\n catalogueNotice,\r\n filterRow,\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 // The count is the only visible signal while the panel is collapsed: a\r\n // rejected route is not a page that refuses to render, it is one that\r\n // quietly does nothing.\r\n h(\r\n 'summary',\r\n { className: styles.diagSummary },\r\n problemCount === 0 ? t.diagnostics : `${t.diagnostics} (${problemCount})`,\r\n ),\r\n h(\r\n 'ul',\r\n { className: styles.diagList, style: { margin: '6px 0 0', paddingLeft: '18px' } },\r\n ...(problemCount === 0 && diagnostics.length === 0 && savedNote === undefined\r\n ? [h('li', { key: 'none' }, t.diagPending)]\r\n : [\r\n ...problemLines,\r\n ...(catalogueMismatchLine === undefined ? [] : [catalogueMismatchLine]),\r\n ...(savedNote === undefined ? [] : [h('li', { key: 'saved' }, savedNote)]),\r\n ...diagnostics.map((line, index) => h('li', { key: `d${index}` }, line)),\r\n ]),\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. Requests to loopback or private addresses (localhost, 127.x, private ranges) go direct by default; set the top-level localDirect to false to proxy them instead \u2014 a forward proxy normally cannot reach your own machine.',\r\n empty: 'No providers found yet.',\r\n catalogueLoading: 'Loading providers\u2026',\r\n catalogueError: 'Could not load the provider list: ',\r\n catalogueStale: 'Could not load the provider list; showing the saved configuration: ',\r\n useProxy: 'Use a proxy for this provider',\r\n useDefault: 'Use the default proxy',\r\n defaultTitle: 'Default proxy',\r\n defaultLead: 'One endpoint, reused by every provider that turns on \"Use the default proxy\". The status only reports configuration completeness; use the Test button on a card to verify reachability.',\r\n inheritingDefault: 'Using the default proxy: ',\r\n defaultMissing: 'The default proxy configuration is incomplete, so this provider is not proxied: ',\r\n filterLabel: 'Filter',\r\n filterPlaceholder: 'Filter by name or id\u2026',\r\n noMatch: 'No provider matches the filter.',\r\n setAsDefault: 'Set as the default proxy',\r\n applyDefaultAll: 'Use the default proxy for all providers',\r\n protocol: 'Type',\r\n host: 'IP / host',\r\n port: 'Port',\r\n username: 'Username',\r\n password: 'Password',\r\n showPassword: 'Show',\r\n hidePassword: 'Hide',\r\n confirmPromoteToDefault:\r\n 'The default proxy is already in use by one or more providers. Replace it with this card\\'s endpoint?',\r\n hostHint: 'Only an IPv4, IPv6, or domain name is allowed. A full proxy URL (socks5://user:pass@host:1080) can be pasted instead \u2014 it is split into the fields.',\r\n passwordHint: 'Sent to the SOCKS5 proxy for authentication; stored with this setting.',\r\n passwordHintProxy: 'Sent to the proxy as an authentication password; stored with this setting.',\r\n hitCountPrefix: '',\r\n hitCountSuffix: ' proxied',\r\n recentOk: 'last ok ',\r\n recentFail: 'last failure ',\r\n recentStarted: 'last call ',\r\n noRecord: 'no proxied request yet',\r\n justNow: 'just now',\r\n minutesAgo: ' min ago',\r\n hoursAgo: ' h ago',\r\n daysAgo: ' d ago',\r\n testButton: 'Test',\r\n testRunning: 'Testing\u2026',\r\n testDisabledNote: 'Not enabled \u2014 test only: ',\r\n testFailed: 'Test failed',\r\n exitIpLabel: 'exit IP ',\r\n directLabel: 'direct (not through the proxy)',\r\n cachedLabel: 'cached',\r\n testTargetLabel: 'Target: ',\r\n targetSourceRoute: \" (this card's own target)\",\r\n targetSourceUpstream: \" (this provider's real upstream)\",\r\n targetSourceTestUrl: ' (global self-check URL)',\r\n globalTitle: 'Global settings (advanced)',\r\n globalLead: 'These fields are saved with the plugin rather than per provider. Leave testUrl empty to use the built-in default; comma/space separated candidates are tried in order and only the first 5 are used. localDirect is on by default; turn it off only when the proxy itself is a loopback or private target.',\r\n testUrl: 'Self-check URL',\r\n testUrlHint: 'Comma/space separated; http(s) URLs in the order they should be tried.',\r\n testUrlEmptyHint: 'Empty means the Host uses its built-in default URL.',\r\n testUrlInvalidHint: 'Some candidates are not absolute http(s) URLs. They are saved, but those checks will fail.',\r\n testUrlTooManyHint: 'More than 5 candidates are listed; only the first 5 take effect.',\r\n restoreDefaultTestUrl: 'Restore default',\r\n localDirect: 'Loopback / private targets go direct',\r\n localDirectOnHint: 'On: localhost, 127.x and private ranges bypass the proxy.',\r\n localDirectOffHint: 'Off: loopback/private targets also use the proxy. Enable only when the proxy itself is the target.',\r\n advanced: 'Advanced: target host rules',\r\n onlyHosts: 'Proxy only',\r\n onlyHostsHint: 'Comma/space separated; when set, only requests to these hosts are proxied (suffix match, * for all).',\r\n bypassHosts: 'Bypass',\r\n bypassHostsHint: 'Comma/space separated; requests to these hosts go direct, taking priority.',\r\n ruleDeadHint: 'These entries never match \u2014 use bare host names (no port, scheme or path); a wildcard must be `*` or start with `*.`: ',\r\n testTarget: 'Self-check target',\r\n testTargetHint: 'Empty uses the top-level testUrl; when set, this card\\'s Test requests this URL instead \u2014 point it at a real upstream to verify the end-to-end path.',\r\n socks5Hint: 'SOCKS5 tunnels the connection; the proxy resolves the target host name.',\r\n on: 'proxied',\r\n rejected: 'config rejected',\r\n off: 'direct',\r\n complete: 'complete',\r\n notConfigured: 'not configured',\r\n diagnostics: 'Connection diagnostics',\r\n diagPending: '(collecting\u2026)',\r\n catalogueMismatch: 'Saved but not listed by the Host catalogue: ',\r\n catalogueMismatchSuffix: '. Their proxy settings are kept.',\r\n saveFailedPrefix: 'Save failed: ',\r\n close: 'Close',\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\u6307\u5411\u672C\u673A\u6216\u5185\u7F51\u5730\u5740\uFF08localhost\u3001127.x\u3001\u79C1\u6709\u7F51\u6BB5\uFF09\u7684\u8BF7\u6C42\u9ED8\u8BA4\u76F4\u8FDE\uFF0C\u9876\u5C42 localDirect \u8BBE\u4E3A false \u65F6\u6062\u590D\u8D70\u4EE3\u7406\u2014\u2014\u6B63\u5411\u4EE3\u7406\u901A\u5E38\u591F\u4E0D\u5230\u4F60\u81EA\u5DF1\u7684\u673A\u5668\u3002',\r\n empty: '\u6CA1\u6709\u68C0\u6D4B\u5230\u4EFB\u4F55 provider\u3002',\r\n catalogueLoading: '\u6B63\u5728\u8BFB\u53D6 provider \u5217\u8868\u2026',\r\n catalogueError: '\u8BFB\u53D6 provider \u5217\u8868\u5931\u8D25\uFF1A',\r\n catalogueStale: 'provider \u5217\u8868\u8BFB\u53D6\u5931\u8D25\uFF0C\u4E0B\u9762\u663E\u793A\u7684\u662F\u5DF2\u4FDD\u5B58\u7684\u914D\u7F6E\uFF1A',\r\n useProxy: '\u4E3A\u8BE5 provider \u542F\u7528\u4EE3\u7406',\r\n useDefault: '\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406',\r\n defaultTitle: '\u9ED8\u8BA4\u4EE3\u7406',\r\n defaultLead: '\u4E3A\u52FE\u9009\u300C\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406\u300D\u7684 provider \u590D\u7528\u7684\u7AEF\u70B9\uFF0C\u53EA\u586B\u4E00\u6B21\u3002\u72B6\u6001\u53EA\u8868\u793A\u914D\u7F6E\u662F\u5426\u5B8C\u6574\uFF1B\u4EE3\u7406\u662F\u5426\u53EF\u8FBE\u8BF7\u7528\u5361\u7247\u4E0A\u7684\u300C\u6D4B\u8BD5\u300D\u9A8C\u8BC1\u3002',\r\n inheritingDefault: '\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406\uFF1A',\r\n defaultMissing: '\u9876\u5C42\u9ED8\u8BA4\u4EE3\u7406\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u8BE5 provider \u4E0D\u4F1A\u8D70\u4EE3\u7406\uFF1A',\r\n filterLabel: '\u8FC7\u6EE4',\r\n filterPlaceholder: '\u6309\u540D\u79F0\u6216 id \u8FC7\u6EE4\u2026',\r\n noMatch: '\u6CA1\u6709\u5339\u914D\u7684 provider\u3002',\r\n setAsDefault: '\u8BBE\u4E3A\u9ED8\u8BA4\u4EE3\u7406',\r\n applyDefaultAll: '\u6240\u6709 provider \u4F7F\u7528\u9ED8\u8BA4\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 showPassword: '\u663E\u793A',\r\n hidePassword: '\u9690\u85CF',\r\n confirmPromoteToDefault: '\u5DF2\u6709 provider \u6B63\u5728\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406\u3002\u8981\u7528\u8FD9\u5F20\u5361\u7247\u7684\u7AEF\u70B9\u8986\u76D6\u5B83\u5417\uFF1F',\r\n hostHint: '\u53EA\u5141\u8BB8\u586B\u5199 IPv4\u3001IPv6 \u6216\u57DF\u540D\uFF1B\u4E5F\u53EF\u4EE5\u76F4\u63A5\u7C98\u8D34\u5B8C\u6574\u4EE3\u7406 URL\uFF08\u5982 socks5://user:pass@host:1080\uFF09\uFF0C\u4F1A\u81EA\u52A8\u62C6\u5206\u5230\u5404\u5B57\u6BB5\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 passwordHintProxy: '\u4F5C\u4E3A\u4EE3\u7406\u8BA4\u8BC1\u53E3\u4EE4\u53D1\u9001\u7ED9\u4EE3\u7406\uFF1B\u968F\u8BE5\u8BBE\u7F6E\u4E00\u8D77\u4FDD\u5B58\u3002',\r\n hitCountPrefix: '\u5DF2\u4EE3\u7406 ',\r\n hitCountSuffix: ' \u6B21',\r\n recentOk: '\u6700\u8FD1\u6210\u529F ',\r\n recentFail: '\u6700\u8FD1\u5931\u8D25 ',\r\n recentStarted: '\u6700\u8FD1\u8C03\u7528 ',\r\n noRecord: '\u5C1A\u65E0\u4EE3\u7406\u8BB0\u5F55',\r\n justNow: '\u521A\u521A',\r\n minutesAgo: ' \u5206\u949F\u524D',\r\n hoursAgo: ' \u5C0F\u65F6\u524D',\r\n daysAgo: ' \u5929\u524D',\r\n testButton: '\u6D4B\u8BD5',\r\n testRunning: '\u6D4B\u8BD5\u4E2D\u2026',\r\n testDisabledNote: '\u672A\u542F\u7528\uFF0C\u4EC5\u6D4B\u8BD5\uFF1A',\r\n testFailed: '\u6D4B\u8BD5\u5931\u8D25',\r\n exitIpLabel: '\u51FA\u53E3 IP ',\r\n directLabel: '\u76F4\u8FDE\uFF08\u672A\u7ECF\u8FC7\u4EE3\u7406\uFF09',\r\n cachedLabel: '\u7F13\u5B58',\r\n testTargetLabel: '\u76EE\u6807 ',\r\n targetSourceRoute: '\uFF08\u672C\u5361\u7247\u81EA\u68C0\u76EE\u6807\uFF09',\r\n targetSourceUpstream: '\uFF08\u8BE5 provider \u7684\u771F\u5B9E\u4E0A\u6E38\uFF09',\r\n targetSourceTestUrl: '\uFF08\u5168\u5C40\u81EA\u68C0\u5730\u5740\uFF09',\r\n globalTitle: '\u5168\u5C40\u8BBE\u7F6E\uFF08\u9AD8\u7EA7\uFF09',\r\n globalLead: '\u8FD9\u91CC\u7684\u4E24\u9879\u5C5E\u4E8E\u63D2\u4EF6\u5168\u5C40\u8BBE\u7F6E\u3002testUrl \u7559\u7A7A\u65F6 Host \u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u503C\uFF1B\u591A\u4E2A\u5019\u9009\u7528\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF0C\u6309\u987A\u5E8F\u56DE\u9000\uFF0C\u53EA\u6709\u524D 5 \u4E2A\u751F\u6548\u3002localDirect \u9ED8\u8BA4\u5F00\u542F\uFF1B\u53EA\u6709\u4EE3\u7406\u672C\u8EAB\u5C31\u662F\u672C\u673A\u6216\u5185\u7F51\u76EE\u6807\u65F6\u624D\u9700\u8981\u5173\u95ED\u3002',\r\n testUrl: '\u81EA\u68C0\u5730\u5740',\r\n testUrlHint: '\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u6309\u987A\u5E8F\u5C1D\u8BD5\u7684 http(s) URL\u3002',\r\n testUrlEmptyHint: '\u7559\u7A7A\u65F6 Host \u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u5730\u5740\u3002',\r\n testUrlInvalidHint: '\u90E8\u5206\u5019\u9009\u4E0D\u662F\u7EDD\u5BF9\u7684 http(s) URL\u3002\u4ECD\u4F1A\u4FDD\u5B58\uFF0C\u4F46\u8FD9\u4E9B\u5019\u9009\u4F1A\u6D4B\u8BD5\u5931\u8D25\u3002',\r\n testUrlTooManyHint: '\u5019\u9009\u8D85\u8FC7 5 \u4E2A\uFF0C\u53EA\u6709\u524D 5 \u4E2A\u751F\u6548\u3002',\r\n restoreDefaultTestUrl: '\u6062\u590D\u9ED8\u8BA4',\r\n localDirect: '\u672C\u673A / \u5185\u7F51\u76EE\u6807\u76F4\u8FDE',\r\n localDirectOnHint: '\u5F00\u542F\uFF1Alocalhost\u3001127.x \u4E0E\u79C1\u6709\u7F51\u6BB5\u7ED5\u8FC7\u4EE3\u7406\u3002',\r\n localDirectOffHint: '\u5173\u95ED\uFF1A\u672C\u673A / \u5185\u7F51\u76EE\u6807\u4E5F\u8D70\u4EE3\u7406\uFF1B\u4EC5\u5728\u4EE3\u7406\u672C\u8EAB\u5C31\u662F\u76EE\u6807\u65F6\u4F7F\u7528\u3002',\r\n advanced: '\u9AD8\u7EA7\uFF1A\u76EE\u6807\u57DF\u540D\u89C4\u5219',\r\n onlyHosts: '\u4EC5\u8D70\u4EE3\u7406',\r\n onlyHostsHint: '\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u975E\u7A7A\u65F6\u53EA\u6709\u5339\u914D\u8FD9\u4E9B\u4E3B\u673A\u7684\u8BF7\u6C42\u8D70\u4EE3\u7406\uFF08\u540E\u7F00\u5339\u914D\uFF0C* \u8868\u793A\u5168\u90E8\uFF09\u3002',\r\n bypassHosts: '\u76F4\u8FDE',\r\n bypassHostsHint: '\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u5339\u914D\u8FD9\u4E9B\u4E3B\u673A\u7684\u8BF7\u6C42\u76F4\u8FDE\uFF0C\u4F18\u5148\u4E8E\u4E0A\u4E00\u9879\u3002',\r\n ruleDeadHint: '\u4EE5\u4E0B\u6761\u76EE\u6C38\u8FDC\u5339\u914D\u4E0D\u4E0A\u2014\u2014\u89C4\u5219\u53EA\u8BA4\u4E3B\u673A\u540D\uFF08\u4E0D\u8981\u5E26\u7AEF\u53E3\u3001\u534F\u8BAE\u524D\u7F00\u6216\u8DEF\u5F84\uFF09\uFF0C\u901A\u914D\u7B26\u53EA\u80FD\u662F\u5355\u72EC\u7684 * \u6216\u4EE5 *. \u5F00\u5934\uFF1A',\r\n testTarget: '\u81EA\u68C0\u76EE\u6807',\r\n testTargetHint: '\u7559\u7A7A\u7528\u9876\u5C42 testUrl\uFF1B\u586B\u5199\u540E\u8BE5\u5361\u7247\u7684\u300C\u6D4B\u8BD5\u300D\u6539\u4E3A\u8BF7\u6C42\u8FD9\u4E2A\u5730\u5740\uFF0C\u53EF\u62FF\u771F\u5B9E\u4E0A\u6E38\u9A8C\u8BC1\u7AEF\u5230\u7AEF\u8DEF\u5F84\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 rejected: '\u914D\u7F6E\u88AB\u62D2',\r\n off: '\u76F4\u8FDE',\r\n complete: '\u914D\u7F6E\u5B8C\u6574',\r\n notConfigured: '\u672A\u914D\u7F6E',\r\n diagnostics: '\u8FDE\u63A5\u8BCA\u65AD',\r\n diagPending: '\uFF08\u6B63\u5728\u6536\u96C6\u2026\uFF09',\r\n catalogueMismatch: '\u5DF2\u4FDD\u5B58\u4F46\u672A\u51FA\u73B0\u5728 Host \u76EE\u5F55\u4E2D\u7684 provider\uFF1A',\r\n catalogueMismatchSuffix: '\u3002\u4EE3\u7406\u914D\u7F6E\u4ECD\u4F1A\u4FDD\u7559\u3002',\r\n saveFailedPrefix: '\u4FDD\u5B58\u5931\u8D25\uFF1A',\r\n close: '\u5173\u95ED',\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", "/**\r\n * Target-host rule parsing shared by the Host matcher and the settings page.\r\n *\r\n * This module deliberately has no undici import: the browser bundle imports it\r\n * too, and the two halves must agree on what an entry means before either can\r\n * safely warn about an entry that will never match.\r\n */\r\n\r\n/** Split a host-rule string into raw, non-empty tokens. */\r\nexport function splitHostRules(raw: string): string[] {\r\n return raw\r\n .split(/[,\\s]+/)\r\n .map(entry => entry.trim())\r\n .filter(entry => entry.length > 0)\r\n}\r\n\r\n/**\r\n * Normalize one raw rule for suffix matching.\r\n *\r\n * A leading `.` or `*.` is dropped: both spellings mean \"this host and its\r\n * subdomains\". Lower-casing belongs here as well, because the Host compares\r\n * against a WHATWG hostname that is already lower-cased.\r\n */\r\nexport function normalizeHostRule(raw: string): string {\r\n return raw.trim().replace(/^\\*?\\./, '').toLowerCase()\r\n}\r\n\r\n/** Split and normalize a host-rule string into matchable entries. */\r\nexport function parseHostList(raw: string): string[] {\r\n return splitHostRules(raw)\r\n .map(normalizeHostRule)\r\n .filter(entry => entry.length > 0)\r\n}\r\n\r\n/**\r\n * Whether a host is covered by one rule list.\r\n *\r\n * `*` matches everything; otherwise a rule matches the host itself or any\r\n * subdomain of it (`example.com` covers `api.example.com`).\r\n */\r\nexport function hostMatches(host: string, rules: readonly string[]): boolean {\r\n for (const rule of rules) {\r\n if (rule === '*') return true\r\n if (host === rule || host.endsWith(`.${rule}`)) return true\r\n }\r\n return false\r\n}\r\n\r\n/** Whether a raw token is a bracketed IPv6 literal, e.g. `[::1]`. */\r\nfunction isBracketedIpv6(token: string): boolean {\r\n return /^\\[[0-9a-f:.]+\\]$/i.test(token)\r\n}\r\n\r\n/** Whether a raw token can never match the Host's hostname comparison. */\r\nexport function hostRuleProblem(raw: string): string | undefined {\r\n const token = raw.trim()\r\n if (token.length === 0) return undefined\r\n // A bare `*.` normalizes to an empty string and disappears from the match\r\n // list entirely; report it rather than silently accepting a no-op.\r\n if (token === '*.' || normalizeHostRule(token).length === 0) return '\u7A7A\u901A\u914D\u7B26'\r\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(token)) return '\u5E26\u534F\u8BAE\u524D\u7F00'\r\n if (token.includes('/')) return '\u5E26\u8DEF\u5F84'\r\n // Host compares hostnames, never `host:port`; a bracketed IPv6 literal is the\r\n // one legitimate colon in a hostname.\r\n if (token.includes(':') && !isBracketedIpv6(token)) return '\u5E26\u7AEF\u53E3\u6216\u975E\u6CD5\u5192\u53F7'\r\n // Host strips only a leading `.`/`*.`; any other `*` cannot be a hostname.\r\n const withoutLeadingWildcard = token.replace(/^\\*\\./, '')\r\n if (withoutLeadingWildcard.includes('*') && token !== '*') return '\u6742\u6563\u901A\u914D\u7B26'\r\n return undefined\r\n}\r\n\r\n/** Every raw token that will never match, in the order it was typed. */\r\nexport function deadRuleEntries(raw: string): string[] {\r\n return splitHostRules(raw).filter(entry => hostRuleProblem(entry) !== undefined)\r\n}\r\n", "/**\n * The proxy-endpoint usability predicate, in ONE place.\n *\n * This lives in its own module \u2014 free of Node and schemastery imports \u2014 so the\n * BROWSER half can import the very same rule the Host applies. It exists because\n * the browser used to keep its own weaker copy that checked only \"host non-empty\n * and port in range\": against `https://1.2.3.4` that copy lit the default block\n * green and enabled the bulk \"use the default\" button, while the Host refused\n * every route that pointed at it (a host carrying a scheme or path is rejected by\n * `normalizeRoute`). One predicate, imported by both halves, cannot disagree\n * with itself.\n */\nexport interface ProxyEndpoint {\n /**\n * Proxy host or IP, without scheme, port, or path.\n *\n * Optional because the browser calls this with whatever the settings document\n * currently holds, which mid-edit is not yet a complete endpoint.\n */\n host?: string\n /** Proxy port. 0 means \"not configured\". */\n port?: number\n /**\n * Credential parts, if the endpoint carries any. A HALF-filled pair is a\n * problem, the same way it is on the route itself \u2014 see below.\n */\n username?: string\n password?: string\n}\n\nconst PROXY_HOST_INVALID = '\u4EE3\u7406\u5730\u5740\u53EA\u80FD\u586B IPv4\u3001IPv6 \u6216\u57DF\u540D'\nconst IPV4 = /^(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$/\nconst DOMAIN = /^(?=.*[a-z])(?=.{1,253}$)(?!.*\\.\\d+$)[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?)*$/i\nconst IPV6_CHARS = /^[0-9a-f:.]+$/i\n\n/**\n * Accept exactly one of: IPv4, IPv6, or a DNS host name. The field carries the\n * proxy address only; a port, scheme, path, credential, or other URL text belongs\n * in its own field and is rejected here.\n */\nexport function proxyHostProblem(rawHost?: string): string | undefined {\n const host = (rawHost ?? '').trim().replace(/\\.$/, '')\n if (host.length === 0) return '\u672A\u586B\u5199\u4EE3\u7406\u5730\u5740'\n if (IPV4.test(host)) return undefined\n\n // A colon or bracket means the value is claiming to be IPv6. Validate it as\n // an IPv6 literal; never fall back to accepting the text as a host name.\n if (host.includes(':') || host.startsWith('[')) {\n const literal = host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host\n if (!IPV6_CHARS.test(literal)) return PROXY_HOST_INVALID\n try {\n new URL(`http://[${literal}]:1`)\n return undefined\n } catch {\n return PROXY_HOST_INVALID\n }\n }\n\n return DOMAIN.test(host) ? undefined : PROXY_HOST_INVALID\n}\n\n/**\n * Why this endpoint cannot carry a request, or `undefined` when it can.\n *\n * The host and port checks mirror `normalizeRoute` exactly, so the browser's\n * verdict and the Host's are the same verdict. The credential pairing check\n * mirrors the guards in `buildRouteEntry`, which is what makes this predicate a\n * truthful preview of whether a route that opts into the default will actually be\n * built: without it, a default carrying `alice` and no password lit the block\n * green and enabled the bulk button, and every card it pointed at was then\n * refused by the credential guard with `entries.size === 0`.\n *\n * Tolerates a partial object (`{}`, `host: undefined`) rather than throwing: the\n * browser calls this with whatever the settings document currently holds, which\n * during a half-typed edit is not yet a complete endpoint.\n */\nexport function defaultProxyProblem(endpoint: ProxyEndpoint): string | undefined {\n const hostProblem = proxyHostProblem(endpoint.host)\n if (hostProblem !== undefined) return hostProblem\n // `?? 0` rather than a throw: an absent port is \"not configured\", which is the\n // same thing 0 already means everywhere else in this plugin.\n const port = endpoint.port ?? 0\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n return '\u4EE3\u7406\u7AEF\u53E3\u65E0\u6548\uFF08\u9700\u4E3A 1-65535 \u7684\u6574\u6570\uFF09'\n }\n // \"Both or neither\", exactly as `buildRouteEntry` enforces per transport. The\n // wording stays transport-neutral here because the default block carries a\n // protocol the user may still change; the route-level guards spell out the\n // protocol-specific reason once it is pinned. The Host trims the username\n // before its guards, so this predicate must trim it too; the password is not\n // trimmed by either side.\n const hasUser = (endpoint.username ?? '').trim().length > 0\n const hasPassword = (endpoint.password ?? '').length > 0\n if (hasUser !== hasPassword) {\n return hasUser\n ? '\u914D\u7F6E\u4E86\u4EE3\u7406\u7528\u6237\u540D\u4F46\u6CA1\u6709\u5BC6\u7801\uFF1B\u8BF7\u8865\u5168\u5BC6\u7801\u6216\u6E05\u7A7A\u7528\u6237\u540D'\n : '\u914D\u7F6E\u4E86\u4EE3\u7406\u5BC6\u7801\u4F46\u6CA1\u6709\u7528\u6237\u540D\uFF1B\u8BF7\u8865\u5168\u7528\u6237\u540D\u6216\u6E05\u7A7A\u5BC6\u7801'\n }\n return undefined\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["module", "field", "styles", "body", "apply"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-provider-proxy",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "DSH 插件:在设置里为每个已启用的 provider 单独配置正向代理(类型 + IP + 端口),未配置的 provider 与其它流量保持直连。",
5
5
  "keywords": [
6
6
  "dsh",