Repository navigation
Releases: Asaiuta/dsh-custom-header
Release list
0.4.1 — Zen 免费档工具桩改为追加,不再吞掉调用方工具
-
修复:
opencodeZenFree把整个tools数组替换成两个桩,免费档会话因此拿不到自己的工具。
Zen 免费档的门只要求「提供」bash与read两个名字(各自带非空 parameters
schema),并不要求它们是仅有的工具——但 0.4.0 的实现是tools: [bashStub, readStub]
于是每一次
*-free请求都只带这两个桩出网,调用方(DSH)原有 50 个工具全被丢掉。
实测后果三类,全部同源:
① 会猜名字的模型照旧能干完活——它从系统提示里认出ops_bash/ff_read并直接调用
(观察到 502 / 449 / 73 次工具调用的会话);因为 DSH 按名字派发,工具并未「没注册」;
② 照桩文案办事的模型直接拒答——它认定自己没有任何可用工具,0 次调用
(session-1f6c6fbe、session-74289305都回「## 结论:本次会话无法执行该分析」);
③ 去调桩名bash的模型撞上unknown tool "bash"——这正是此前排查到的
「DSH 里 bash 失效」34 次未知工具事件的上游来源,不是模型凭空乱调。
由于模型是否「敢猜」随采样而变,表现为非确定性:同一份配置有时能干、有时摆烂。 -
行为变更:
patchOpencodeZenFreeBody改为追加——保留调用方tools,按名补齐缺失的桩;
调用方已提供同名工具时不重复插入(既不产生重名条目,也不覆盖调用方自己的 schema)。
ZEN_TOOL_STUB文案保持不变:它的职责是压制对bash这个 DSH 并不提供的名字的调用,
问题从来不是这句话,而是它当时是模型唯一能看到的东西。 -
新增命名导出
ZEN_TOOL_STUB/ZEN_BASH_TOOL_NAME/ZEN_READ_TOOL_NAME,供测试与外部核查引用。 -
设置页
opencodeZenFree帮助文案(中/英)补一句:工具桩是追加而非取代。 -
tests/smoke.mjs新增场景 10(16 条断言):调用方工具被保留、桩被追加、无重名、stream
仍被强制、桩的描述与 schema 未变、调用方已提供read时不重复且其 schema 生效、
非免费模型与开关关闭时请求体原样透传,以及rewriteOpencodeZenUrl的纯函数边界
(/zen→/inference、/zen根、/zen/go、其它主机、非 zen 路径)。
反向对照已验证该场景对旧实现报FAIL s10 caller tools preserved — bash,read。
0.4.0 — 传输层回到 fetch 中间件管道
- 传输层回到 fetch 中间件管道。 0.2.0 把插件改成了持有 provider 路由的
原生LlmAdapter(ctx.llm.registerAdapter),但那个扩展点是按路由独占的:
想给已被别的插件持有的 provider(如llm-pi-ai的ziyong/moonshotai)
注入客户端签名,注册直接抛DUPLICATE_ADAPTER,宿主也没有「嫁接」到别人
适配器上的通道;llm/stream瀑布又改不了 HTTP 头。本插件的意图恰恰是
「让我发往自己网关的请求看起来像客户端 X」——无论这些请求来自哪个插件——
所以回到不持有任何路由的 fetch 层:globalThis.fetch上一条 DSH 专用
symbol 键控(Symbol.for("dsh-custom-header.fetch.pipeline.v1"))的中间件链,
所有 provider 的请求都从链上流过。这不是回退到 0.1.3:0.3.0 的设置平面
(ConfigSchema全 volatile、场景向导配置页、无 default 导出修复、lockfile
修复)全部保留,只换传输实现。 - 四个中间件(优先级升序):
url-rewrite(5) →header-strip(6) →
header-inject(7) →body-patch(8)。每个都按需重读一份快照,快照由
loader/volatile-update刷新——设置页保存对下一次请求即生效,不重挂插件。 - 统一主机门控(行为变更):fetch 层识别请求只能靠 URL,永远看不到它属于
哪个 provider,因此gatewayHosts成为唯一的安全边界——所有预设(包括
codex_official等固定预设,0.1.x 里它们全局注入)都只作用于命中白名单
主机的请求;白名单为空即完全无操作。resolveProfileForUrl统一实现该规则。 - 配置面收窄:删除适配器时代字段
providers/openaiProviders/
baseUrl/openaiBaseUrl/apiKey(provider 路由不再由本插件持有,网关
URL 由 provider 自身配置决定)。gatewayHosts从「仅 auto 生效」升格为中心开关。 - 会话 id 恢复按对话隔离:
llm/stream包装器把GenerateOptions.sessionId
经 AsyncLocalStorage 传给 fetch 层(session-context.ts回归);
x-opencode-session/X-Claude-Code-Session-Id/ bodymetadata.user_id
均按会话惰性分配缓存,非 LLM 请求退回进程级 default 会话。 - opencode Zen 免费层移植到 fetch 层:
body-patch中间件先读请求体里的
模型 id,命中免费模型(*-free/big-pickle/grok-code)时把/zen
改写到/inference并补bash/read工具桩——URL 改写住在 body-patch
而不是 url-rewrite,正因为判定需要模型 id。 - 删除
opencodeFreeModels(额外免费模型 id 列表):实际用不上,0.4.0
未发布、无兼容负担;isOpencodeFreeModel改为只认内置免费 id。 - 403 诊断保留:
llm/stream观察器区分 Cloudflare HTML 边缘拦截与 JSON
client_restriction拒绝。 - 代码组织:恢复
fetch-pipeline.ts/session-context.ts/
header-inject.ts;重写url-rewrite.ts(新增UrlRewriteContext/
withUrl等)与body-patch.ts(新增createBodyPatchMiddleware,保留
patchAnthropicMessagesPayload);删除adapter.ts/adapter-common.ts/
adapter-openai.ts/serialize.ts/serialize-openai.ts/sse.ts/
sse-openai.ts。 - 字段改名(按日常读法):
autoHosts→gatewayHosts(网关主机)、
autoCodexProfile→codexFallback(Codex 兜底)、claudeSystemMode→
claudeSystemBlock、codexVersion→codexCliVersion;配置页为
opencodeClient/opencodeProject补上专属提示(原来错用版本提示)。
0.4.0 未发布过,未做旧名兼容。 - 配置页重排为「导航栏 + 三个固定页」(外壳参考
dsh-any-background的
设置分节:左侧 158px 导航栏与滑动指示条、品牌块、页面切换动画、卡片;
≤620px 收成顶部横条)。起因是场景向导的一个真实缺陷:字段按overridden
分区(「也已设置,但不属于当前场景」),而overridden在暂存时就为真,
于是编辑claudeSystemBlock这类当前场景不列的字段时,正在编辑的行会从
「全部设置」折叠区跳到页外——行在手下跑掉。新布局里每个字段有唯一
归属页,切页不再重新归类任何行:- 身份与网关(
gatewayHosts/codexFallback/claudeSystemBlock)——
顶部仍是场景选择器,选中场景只暂存profile; - 版本与请求头(8 个版本/头字段);
- 高级(
extraHeaders/urlRewrites)。
随之删除scenarios.ts的fields/ScenarioFields/scenarioFields、
fields.tsx的GROUPS导出与「也已设置」分区;styles.ts与
index.tsx按新外壳重写(导出NAV_ITEM_H/NAV_GAP供指示条定位),
locales.ts(中英)新增brandTag/nav*/overline*/desc*并清掉
死键。
- 身份与网关(
- 配置页随配置面同步:删除网关端点分组与
apiKey密钥行(连带
SettingsSecretField用法与 secret 字段类型);fields.tsx/
scenarios.ts/locales.ts(中英)同步。 - 冒烟测试回归并扩展:
tests/smoke.mjs9 场景 31 断言(新增「固定预设同样
受gatewayHosts门控」);支持SMOKE_LIB环境变量指向临时构建产物,
便于在桌面端运行(插件被挂载监视)时不碰lib/验证构建。 - README(中 / 英)重写「为什么回到 fetch / 工作机制 / 配置 / 配置页 /
已知残留」章节。