feat(deepseek-harness): 通过 reasoningEffort 支持 Thinking 档位选择 - #53
Conversation
Project DeepSeek Harness reasoning efforts into the Harness Model catalog (thinkingOptions, supportedThinkingOptionIds) and wire thinking.select to sessions.selectModel with exact readback confirmation. Creation accepts thinkingOptionId; Model switches fall back to the route default effort.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
There was a problem hiding this comment.
🟡 Changes recommended
There are confirmed correctness/input-validation issues in the DeepSeek model catalog and session creation path that can cause schema parse failures or allow invalid Thinking option IDs through.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR completes DeepSeek Harness “Thinking” option support by projecting Host-provided reasoning.efforts into the adapter’s model catalog and wiring reasoningEffort through session creation/resume and runtime thinking.select configuration, aligning DeepSeek behavior with other adapters in the workspace.
Changes:
- Expand DeepSeek model catalog normalization to advertise
thinkingOptions, per-modelsupportedThinkingOptionIds, and a deriveddefaultThinkingOptionId. - Enable
selectThinkingOptioncapability and implementthinking.selectby callingsessions.selectModel(..., reasoningEffort)with fail-closed readback verification. - Update/extend adapter tests and the fake Host fixture to model default
reasoningEffortbehavior and validate state publication semantics.
File summaries
| File | Description |
|---|---|
| packages/adapters/deepseek-harness/test/deepseek-harness-adapter.test.ts | Updates the fake Host and adds focused tests for Thinking catalog/state/selection behavior. |
| packages/adapters/deepseek-harness/src/model-catalog.ts | Projects Host reasoning metadata into the harness model catalog (thinking options + defaults). |
| packages/adapters/deepseek-harness/src/deepseek-harness-adapter.ts | Enables Thinking selection capability, reads current reasoningEffort, publishes Thinking state, and implements thinking.select. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| ...(model.reasoning && model.reasoning.efforts.length > 0 | ||
| ? { supportedThinkingOptionIds: model.reasoning.efforts.map((effort) => effort.id) } | ||
| : {}), |
| await this.#connection.client.sessions.selectModel({ | ||
| sessionId: sessionId as SessionId, | ||
| provider: requested.provider, | ||
| model: requested.model, | ||
| provider: target.provider, | ||
| model: target.model, | ||
| ...(input.thinkingOptionId ? { reasoningEffort: input.thinkingOptionId } : {}), |
| const defaultEffort = MODEL_GROUPS.find((group) => group.id === provider)?.models.find( | ||
| (candidate) => candidate.id === model, | ||
| )?.reasoning.defaultEffort; |
背景
README 能力矩阵把 DeepSeek Harness 的 模型 / Thinking 档位选择 标为 🚧。模型切换原本已可用,但 Thinking 档位仍被硬编码禁用:adapter 报告
selectThinkingOption: false、目录固定为thinkingOptions: [],且open()会拒绝thinkingOptionId。DeepSeek Harness Host 协议早已提供所需能力;本 PR 仅将既有协议字段接入 adapter,沿用 Pi 与 Claude Code 已采用的模式。
版本 / 对接点(已核验)
main@64ae4c3(v0.3.5 之后)@deepseek-ai/dsh-host-apiproxy0.1.0-rc.6(见package-lock.json;adapter 也声明完全相同的版本)sessions.selectModel({ sessionId, provider, model, reasoningEffort? })—— 自 rc.6 起可用ModelCatalogModel.reasoning?: ModelReasoning { efforts: { id, name, description? }[], defaultEffort? }—— 自 rc.6 起可用sessions.models→ModelSelection.reasoningEffort?: string@deepseek-ai/dsh0.1.1-rc.2(字段完全一致,向后兼容 rc.6)dsh-llm-deepseek按顺序公开off / low / high / max;off映射为thinking: disabled;省略档位时保留部署默认值(high);锁定 Thinking 的部署仅公开off改动
model-catalog.ts—— 将每个模型的reasoning.efforts投影为目录的thinkingOptions(并集,保留 adapter 顺序)和每个模型的supportedThinkingOptionIds;从当前选择或默认模型的reasoning.defaultEffort推导defaultThinkingOptionId,避免未显式指定档位时错误落到第一个公开的off选项。新增normalizeDeepSeekThinkingOptions()/parseDeepSeekThinkingOptionId()均采用 fail-closed 策略:无法识别的 effort id 会被丢弃,不进行猜测。deepseek-harness-adapter.tsselectThinkingOption: true(inspect 与 session capabilities)thinking.select:使用当前 provider/model 加reasoningEffort调用sessions.selectModel,再通过sessions.models回读并要求精确匹配后才发布状态(fail-closed,与#selectModel保持一致)model.select有意省略reasoningEffort,使模型切换回退到目标模型自己的默认档位;随后从回读值刷新effectiveThinkingOptionIdopen({ kind: "create", thinkingOptionId })不再拒绝该参数;未显式给出model时,会先读取 Host 默认选择,再带档位执行选择initialState、readSnapshot()与选择事件均携带effectiveThinkingOptionId+availableThinkingOptionssessions.models.current快照;历史请求头仍只归属于各自的历史 TurnselectModel现在会像 DSH 一样物化每个模型的默认档位;新增 5 个聚焦用例,覆盖目录公开/默认值、创建时指定档位、恢复会话后的选择与发布、当前配置与历史配置的区分,以及 Thinking 回读不匹配时不发布状态。验证
npm run typecheck✅npx vitest run --config tests/vitest.config.js packages/adapters/deepseek-harness→ 27 passed(22 个既有 + 5 个新增)✅npx prettier --check packages/adapters/deepseek-harness✅npx eslint packages/adapters/deepseek-harness✅node tools/check-boundaries.mjs✅合入后,README 能力矩阵中 DeepSeek Harness 的 模型 / Thinking 档位选择 可由 🚧 更新为 ✅。