1. LLM seam 不是“封装 fetch”这么简单
Harness 需要一个统一消息与流式 chunk 词汇,让 loop 不知道当前 provider 是 DeepSeek、OpenAI-compatible 还是其他实现。Adapter 负责把统一请求翻译为 provider wire format,再把 SSE/stream 响应翻译回来。
2. DeepSeek Adapter 的责任边界
- 序列化 harness message/tool schema 到 DeepSeek chat-completions。
- 处理 reasoning content 与 tool-call 相关的 provider 约束。
- 解析 SSE,转换为统一 StreamChunk。
- 把 transport timeout、abort、malformed response 映射成稳定 LLM error。
- 每次操作重新解析动态设置/凭据,而不是启动时冻结。
3. Retry 为什么不该偷偷写在 adapter 内
如果 adapter 自己在一个 stream 调用里重试,session 看到的“一个 step = 一个模型请求”可能失真。DSH 倾向把 retry 放到持久 step 边界,使失败与重试可观察、可恢复。
4. 设计自己的 adapter 时的最小接口
interface LlmAdapter {
stream(req: ModelRequest, signal: AbortSignal): AsyncIterable<StreamChunk>
}
type StreamChunk =
| { kind: 'text'; delta: string }
| { kind: 'reasoning'; delta: string }
| { kind: 'tool-call'; id: string; name: string; argsDelta: string }
| { kind: 'finish'; reason: 'stop' | 'tool' | 'error' };