dsh-composer-ux 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [0.1.5] — 2026-09-13
6
+
7
+ ### 新增
8
+ - **按 baseURL 识别 OpenCode 路由**:自动匹配(「作用路由」留空)原先只看路由名是否以 `opencode` 开头,因此自建别名路由(例如 `go: { baseURL: https://opencode.ai/zen/go/v1 }`)拿不到请求头。现在改为「名字前缀 **或** baseURL 主机是 `opencode.ai`(含子域)」两者取或——内置 `opencode-go` 仍走名字那条(它的 baseURL 由 pi-ai 目录内置,配置里读不到),自建别名走 URL 那条。
9
+ - 仿冒主机不匹配:`https://opencode.ai.evil.example/v1` 若只做子串判断会误伤,因此改为解析 URL 后比较主机名(解析失败才退回子串)。
10
+ - 设置页「作用路由」的说明与占位符同步更新;无命中时「状态」行会写出实际的匹配规则。
11
+
12
+ ### 测试
13
+ - `test/host-header-mirror.mjs` 新增 3 组(9 项):按 URL 命中别名路由 / 子域命中 / 非 OpenCode 路由不动 / 仿冒主机不写入 / 显式名单优先 / URL 非法时子串回退。**35 passed, 0 failed**。
14
+
5
15
  ## [0.1.4] — 2026-09-13
6
16
 
7
17
  ### 文档
package/README.md CHANGED
@@ -76,7 +76,10 @@ OpenCode 的接口要求客户端在每次请求里带上一个稳定的会话 I
76
76
  - **设置页位置**:设置 → 输入体验 → 「OpenCode 请求头」(折叠栏目):开关 / 头名 / 值 / 作用路由,附一行宿主半回写的「状态」。
77
77
  - **落点**:`llm-pi-ai` 的 provider profile —— `providers.<路由>.headers.<头名>`。这是 DSH 里唯一受支持的出网请求头入口:它作为 pi-ai 的 `optionsHeaders` **最后合并**(能覆盖默认头),且该适配器每次请求都重读配置,所以改完**下一次请求即生效**,不用重启、不用手工改 `settings.yaml`。
78
78
  - **写入方式**:`settings.mutate` 的路径寻址——只动我们那一个键,绝不重述或删除你写在同一个 profile 里的其它字段(`models` / `apiKeyEnv` / 其它 headers 都不碰)。
79
- - **只写已存在的路由**:profile 的 `models` 是必填项,凭空造一个只有 headers 的路由会让整份配置校验失败;所以「作用路由」留空时只匹配 `providers` 里以 `opencode` 开头的路由,显式写了名单也只保留其中**已存在**的。
79
+ - **目标路由怎么选**:profile 的 `models` 是必填项,凭空造一个只有 headers 的路由会让整份配置校验失败,所以只写**已存在**的路由。判据:
80
+ - 「作用路由」**留空**时自动匹配——路由名以 `opencode` 开头(DSH 内置的 `opencode-go` 走这条,它的 baseURL 由 pi-ai 目录内置、配置里读不到),**或**该路由的 `baseURL` 主机是 `opencode.ai`(含子域)。后一条是为自建别名路由准备的:例如把 OpenCode 端点配成 `go: { baseURL: https://opencode.ai/zen/go/v1 }`,名字里没有 opencode 也能被认出来。
81
+ - 「作用路由」**填了名单**时只看名单(逗号或空格分隔),且只保留其中确实存在的路由。
82
+ - 判据只看主机名:`https://opencode.ai.evil.example/v1` 这类仿冒主机不会被匹配。
80
83
  - **撤销**:关栏目开关、关插件总开关、或改头名,都会自动清掉此前写入的那一个键;并且只清「值等于当前配置值或记账值」的,用户自己手写的同名头不会被误删。
81
84
  - **值**:所有对话共用同一个值(栏目里可改、可「重新生成」);第一次启用若留空,会自动生成一个 UUID 并保存沿用。OpenCode 文档原话是要「每段对话」一个 ID——按会话变化的头 DSH 的配置层做不到(`llm/stream` 钩子被设计成只能读不能改,`GenerateOptions` 里没有 `headers` 字段),所以这里退一步用固定值。已知代价:所有对话挤同一个上游(没有负载分散);单段对话内的缓存命中不受影响。另外它**不保证**缓存一定命中(还取决于上游模型与网关策略)。
82
85
  - **自校验**:写入前用与 llm-pi-ai 相同的规则(`new Headers()`)校验头名与头值;非法值被拒绝,原因写进栏目的「状态」行,而不是把整条路由弄坏。
package/lib/client.js CHANGED
@@ -1487,9 +1487,9 @@ function SettingsSection({ useLive, actions }) {
1487
1487
  TextFieldRow,
1488
1488
  {
1489
1489
  title: "\u4F5C\u7528\u8DEF\u7531",
1490
- desc: "\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D opencode \u7CFB\u8DEF\u7531",
1490
+ desc: "\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D OpenCode \u8DEF\u7531\uFF08\u540D\u5B57\u4EE5 opencode \u5F00\u5934\uFF0C\u6216 baseURL \u6307\u5411 opencode.ai\uFF09",
1491
1491
  value: settings.headerRoutes,
1492
- placeholder: "\u7559\u7A7A = \u81EA\u52A8\uFF08opencode*\uFF09",
1492
+ placeholder: "\u7559\u7A7A = \u81EA\u52A8\uFF08opencode* \u6216 opencode.ai \u7AEF\u70B9\uFF09",
1493
1493
  maxLength: HEADER_VALUE_MAX,
1494
1494
  onChange: (next) => {
1495
1495
  actions.setField(HEADER_ROUTES_FIELD, next);