feat: customize model provider requests
Model connections can now save bounded JSON request headers and top-level body fields. Direct requests and Continue support both; local OpenCode and DeepSeek Harness use only native header support, while the managed remote OpenCode gateway applies both. Runtime, protocol, and authentication fields keep precedence. Custom values are ordinary connection settings, not credential storage. This migrates Runtime settings from v20 to v21 and updates the DeepSeek control and managed Runtime ACP capabilities. Release note: 模型连接详情新增自定义请求头和请求体;直连与 Continue 支持两者,本地 OpenCode 和 DeepSeek Harness 仅应用原生支持的请求头,受管远程 OpenCode 支持两者,界面会明确提示生效范围。
This commit is contained in:
@@ -254,7 +254,9 @@ Store 是否已经提交为准,确定性完成新目录或恢复旧目录,
|
||||
| `goodbuddy/native/snapshot` | Main → Control Plane | 从无 Agent scope 的 Host Registry 读取有界的原生 Tool/Skill 元数据,排除 GoodBuddy 分配项与请求级代理 |
|
||||
| `goodbuddy/shutdown` | Main → Control Plane | 停止接收新请求并有序清理 |
|
||||
|
||||
Utility 启动控制协议使用版本 2,严格携带 `supportsImageInput` 与固定 8 MiB 帧上限;版本 1 或缺少该字段的启动消息失败关闭,不能让 Host 自行猜测模型能力。扩展版本独立于 ACP 版本。握手响应至少包含:
|
||||
Utility 启动控制协议使用版本 3,严格携带 `supportsImageInput`、模型连接的有界自定义
|
||||
Header 与固定 8 MiB 帧上限;旧版本或缺少必需字段的启动消息失败关闭,不能让 Host
|
||||
自行猜测模型能力。扩展版本独立于 ACP 版本。握手响应至少包含:
|
||||
|
||||
```ts
|
||||
type GoodBuddyHarnessCapabilities = {
|
||||
@@ -431,6 +433,9 @@ DeepSeek Harness 首版只使用符合下列边界的 GoodBuddy 模型连接:
|
||||
- 模型名称不限制为 DeepSeek 品牌,由所选 OpenAI 兼容服务决定。
|
||||
- 模型名称和服务地址由 Main 传入受控 Host。
|
||||
- 图片能力只读取所选 GoodBuddy 模型连接的 `supportsImageInput`;Main、Utility 启动配置、ACP 能力和 Pi-AI 模型输入模态必须使用同一个布尔值。
|
||||
- 模型连接的自定义 Header 通过 Utility 启动配置交给 Pi-AI Provider;Pi-AI 没有受支持的
|
||||
任意 Body 配置入口,因此 DeepSeek Harness 不接收自定义 Body。完整支持矩阵和合并规则
|
||||
见[模型连接请求定制](../model-connections/technical-design.md)。
|
||||
- API Key 继续保存在 GoodBuddy 加密设置中。
|
||||
- 启动环境提供的部署连接只由 Main 自动解析,不在 Renderer 中显示为可选来源。
|
||||
- 未显式指定 Harness 模型且没有可用的管理员预置连接时,Main 优先使用当前默认的兼容 GoodBuddy 模型连接;默认连接不兼容时使用首个兼容连接。只有不存在任何兼容连接时才提示用户前往模型或 Runtime 设置。
|
||||
|
||||
@@ -44,6 +44,7 @@ Task、Job、Subjob、Run 和 Subagent 的对象关系以
|
||||
|
||||
## 相关功能
|
||||
|
||||
- [模型连接请求定制](../model-connections/README.md):定义连接级 Header/Body、合并优先级和 Runtime 支持矩阵。
|
||||
- [本机工具环境](../local-tool-environment/README.md):为新进程提供 Node、Python 和 PATH。
|
||||
- [助手工作栏与执行空间](../assistant-workbar/prd.md):定义本机/SSH 执行位置和活动归属。
|
||||
- [远程主机与远程执行](../remote-host/README.md):定义当前托管 SSH Runtime 边界。
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# 模型连接请求定制
|
||||
|
||||
本功能负责 LLM 模型连接的自定义请求头和自定义请求体。用户可以在同一个连接中保存
|
||||
Provider 要求的附加元数据;GoodBuddy 只在直连链路或 Runtime 明确原生支持的链路中应用
|
||||
这些值,不为不支持的 Runtime 伪造透传能力。
|
||||
|
||||
## 文档导航
|
||||
|
||||
| 文档 | 权威职责 |
|
||||
| --- | --- |
|
||||
| [UI 设计](./ui-design.md) | 编辑入口、校验反馈、兼容性说明和无障碍行为 |
|
||||
| [技术设计](./technical-design.md) | 契约、持久化、合并优先级、Runtime 支持矩阵和验证 |
|
||||
| [功能进度](./progress.md) | 已验证实现、剩余工作和验证证据 |
|
||||
|
||||
本次改动是现有模型连接的有界扩展,不新增独立业务对象或工作流,因此不单独建立 PRD、
|
||||
User Stories 和逻辑设计;本页定义产品边界,技术设计定义唯一的请求合并规则。
|
||||
|
||||
## 术语
|
||||
|
||||
| 术语 | 定义 |
|
||||
| --- | --- |
|
||||
| 自定义请求头 | 用户为一个 LLM 模型连接保存的附加 HTTP Header 字符串映射 |
|
||||
| 自定义请求体 | 用户为一个 LLM 模型连接保存的附加 JSON 顶层字段 |
|
||||
| Runtime 字段 | GoodBuddy 或 Runtime 为模型、消息、工具、流式、认证和协议生成的字段 |
|
||||
| 直连 | GoodBuddy Main 直接向模型 Provider 发出请求 |
|
||||
| 受管远程 OpenCode | 模型请求通过 GoodBuddy Agent 的可信模型网关发出的远程 OpenCode |
|
||||
|
||||
## 产品边界
|
||||
|
||||
- 两项设置都位于“设置 → 模型连接 → LLM → 连接详情”底部,以 JSON 对象编辑。
|
||||
- 直连模型支持请求头和请求体,包括连接测试、文本、工具、摘要和图像生成请求。
|
||||
- Continue 原生支持请求头和请求体。
|
||||
- 本地 OpenCode 原生支持请求头,不使用自定义请求体。
|
||||
- DeepSeek Harness 的 Pi-AI Provider 原生支持请求头,不使用自定义请求体。
|
||||
- 受管远程 OpenCode 的可信模型网关支持请求头和请求体。
|
||||
- 使用 Runtime 自有配置时不引用 GoodBuddy 模型连接,因此不会应用连接级请求定制。
|
||||
- Runtime、协议和认证字段始终优先。用户不能用请求定制替换模型、消息、工具、流式或
|
||||
认证信息。
|
||||
- 自定义值作为普通连接设置保存。API Key 和其他密钥必须使用专用凭据字段,不应写入
|
||||
自定义请求头或请求体。
|
||||
|
||||
## 相关功能
|
||||
|
||||
- [直连模型 Agent](../direct-model-agent/README.md)
|
||||
- [DeepSeek Harness Runtime](../deepseek-harness/README.md)
|
||||
- [远程主机与远程执行](../remote-host/README.md)
|
||||
@@ -0,0 +1,38 @@
|
||||
# 模型连接请求定制进度
|
||||
|
||||
## 2026-09-03
|
||||
|
||||
### 已完成
|
||||
|
||||
- 模型连接设置、v20 → v21 迁移、公开与 resolved profile 已接入有界自定义 Header/Body。
|
||||
- 设置页已提供两个 JSON 编辑器、就地校验、保存阻止、普通设置存储提示和 Runtime 支持范围。
|
||||
- 直连连接测试、文本、工具、摘要和图像请求已统一采用 Runtime 优先的浅合并。
|
||||
- Continue 1.5.47 已通过原生 `requestOptions.headers` 与 `extraBodyProperties` 接入两项配置。
|
||||
- bundled OpenCode 已通过 Provider `options.headers` 接入 Header,并确认没有发送未支持的
|
||||
自定义 Body。
|
||||
- DeepSeek Harness 已通过控制协议 v3 把 Header 交给 Pi-AI Provider,没有接入未支持的
|
||||
自定义 Body。
|
||||
- Main 与 Agent 远程模型网关已接入 Prompt-scoped Header/Body;`runtime/acp` capability
|
||||
已提升为 v5。
|
||||
- 功能入口、支持矩阵、合并优先级、普通设置存储边界和协议版本已写入功能文档及双语
|
||||
`FEATURES`。
|
||||
|
||||
### 已验证
|
||||
|
||||
- `npm run typecheck`
|
||||
- `npm run lint`
|
||||
- 20 个聚焦测试文件:527 项通过,4 项按环境跳过。
|
||||
- 全量 `npm test`:326 个测试文件通过,8 个文件按环境跳过;3506 项通过,55 项跳过。
|
||||
- bundled OpenCode 与 Continue 分别对 loopback Provider 验证 Chat Completions 和
|
||||
Responses。4 项原生探针全部通过:两者都发送自定义 Header;Continue 发送自定义 Body;
|
||||
OpenCode 不发送不支持的 Body。
|
||||
- Main/Agent 远程网关测试验证了合并优先级、认证优先、profile digest 绑定和单次分发。
|
||||
- 三路清理审查完成;已复用共享协议路径、Header 规范化、ACP capability 常量和 JSON
|
||||
类型,并为 Renderer JSON 草稿增加解析前长度上限。
|
||||
|
||||
### 待验证
|
||||
|
||||
- 生产 `npm run build`。
|
||||
- 最小真实模型 Header/Body 探针。
|
||||
- DeepSeek Harness 真实 Provider Header 探针。
|
||||
- 当前源码 Agent bundle 在共享 Linux x64 Host 上的受管远程模型请求。
|
||||
@@ -0,0 +1,87 @@
|
||||
# 模型连接请求定制技术设计
|
||||
|
||||
## 1. 共享契约
|
||||
|
||||
`src/shared/model-request-customization.ts` 定义:
|
||||
|
||||
- `ModelRequestHeaders`:字符串到字符串的映射。
|
||||
- `ModelRequestBody`:顶层 JSON 对象。
|
||||
- 两个 Zod schema、统一边界和合并函数。
|
||||
|
||||
模型连接输入、公开设置、Main 内 resolved profile 和远程 Prompt profile 复用这些类型。
|
||||
Runtime 设置文件版本为 21;版本 20 迁移为两个空对象,不改变已有连接或凭据。
|
||||
|
||||
## 2. 边界
|
||||
|
||||
请求头最多 64 项;名称最长 128 字符,值最长 4096 字符。名称必须是合法 HTTP token,
|
||||
大小写归一后不能重复,值不能包含控制字符。
|
||||
|
||||
请求体编码后最多 64 KiB,最大深度 16、最大节点数 4096;对象或数组单层最多 256 项。
|
||||
键最长 256 字符,字符串值最长 32768 字符,数字必须有限。
|
||||
|
||||
下列请求头由认证、协议或传输层拥有,不能在连接中配置:
|
||||
|
||||
`Authorization`、`X-API-Key`、`API-Key`、`Content-Type`、`Content-Length`、`Host`、
|
||||
`Connection`、`Transfer-Encoding`、`User-Agent`、`Anthropic-Version`。
|
||||
|
||||
下列请求体顶层字段由 GoodBuddy 或 Runtime 拥有,不能在连接中配置:
|
||||
|
||||
`model`、`stream`、`messages`、`input`、`instructions`、`system`、`tools`、
|
||||
`tool_choice`、`parallel_tool_calls`、`max_tokens`、`max_output_tokens`、
|
||||
`stream_options`、`prompt`、`n`、`quality`、`response_format`。
|
||||
|
||||
## 3. 合并规则
|
||||
|
||||
请求头先装载用户值,再装载 Runtime 和协议值,最后注入认证值。名称比较不区分大小写,
|
||||
因此 Runtime、协议和认证值始终覆盖同名用户值。
|
||||
|
||||
请求体只做一次顶层浅合并:
|
||||
|
||||
```ts
|
||||
const providerBody = {
|
||||
...connection.requestBody,
|
||||
...runtimeBody
|
||||
}
|
||||
```
|
||||
|
||||
不递归合并嵌套对象。最终请求仍需通过现有协议策略和请求大小校验。
|
||||
|
||||
## 4. Runtime 支持矩阵
|
||||
|
||||
| 请求路径 | 自定义 Header | 自定义 Body | 实现边界 |
|
||||
| --- | --- | --- | --- |
|
||||
| GoodBuddy 直连 | 支持 | 支持 | Main 在连接测试、文本、工具、摘要和图像请求中合并 |
|
||||
| Continue | 支持 | 支持 | 使用 Continue 1.5.47 的 `requestOptions.headers` 与 `extraBodyProperties` |
|
||||
| 本地 OpenCode | 支持 | 不支持 | 使用 OpenCode Provider `options.headers`;不生成未证实的 Body 配置 |
|
||||
| DeepSeek Harness | 支持 | 不支持 | 使用 `dsh-llm-pi-ai` Provider 的 `headers`;Utility 控制协议 v3 传递 Header |
|
||||
| 受管远程 OpenCode | 支持 | 支持 | Agent Prompt profile 传到可信模型网关后合并 |
|
||||
| Runtime 自有配置 | 不适用 | 不适用 | 该模式不使用 GoodBuddy 模型连接 |
|
||||
|
||||
对不支持自定义 Body 的 Runtime,设置仍保留在连接上,切换回支持路径时继续生效;当前
|
||||
Runtime 不接收也不发送该 Body。
|
||||
|
||||
## 5. 远程模型网关
|
||||
|
||||
非空请求定制随 Prompt-scoped model profile 发送,不写入 Agent 环境、命令行或模型调用
|
||||
ledger。模型 profile digest 绑定规范化后的 Header 和 Body,但继续排除 API Key。
|
||||
|
||||
Main 网关和 Agent 网关都执行相同的可信 profile 合并、协议策略检查和最终 Body 大小检查。
|
||||
认证 Header 在请求摘要生成后注入,避免凭据进入摘要或 ledger。受管远程
|
||||
`runtime/acp` capability 为 v5;旧 v4 Agent 不能接收带请求定制的新 Prompt profile,
|
||||
由现有受管更新流程升级后再运行。
|
||||
|
||||
## 6. 凭据
|
||||
|
||||
API Key 继续由现有 Main 加密设置和 Prompt-scoped Agent 凭据路径管理。自定义 Header 和
|
||||
Body 是普通可见连接设置,不提供第二套通用秘密存储;UI 必须提示不要把密钥放入这两个
|
||||
JSON 对象,标准认证 Header 也由 schema 拒绝。
|
||||
|
||||
## 7. 验证
|
||||
|
||||
- 共享 schema:JSON 类型、边界、保留字段和优先级。
|
||||
- 设置存储:v20 → v21 迁移与 Header/Body round trip。
|
||||
- 直连:连接测试、流式文本、工具、摘要和图像请求。
|
||||
- Runtime:真实 bundled OpenCode/Continue 对 loopback Provider 的请求探针;DeepSeek
|
||||
Utility 启动配置和 Pi-AI Provider 配置。
|
||||
- 远程:Main/Agent 网关合并、认证优先级、摘要绑定、大小限制和不重放。
|
||||
- UI:默认值、保存、无效 JSON 保留和 Runtime 支持说明。
|
||||
@@ -0,0 +1,38 @@
|
||||
# 模型连接请求定制 UI 设计
|
||||
|
||||
本文件定义模型连接请求定制的界面行为。全局视觉、表单和无障碍规则继续以
|
||||
[`UI-DESIGN.md`](../../../UI-DESIGN.md) 为准。
|
||||
|
||||
## 信息架构
|
||||
|
||||
“自定义请求头”和“自定义请求体”位于当前 LLM 连接详情的最底部、连接兼容性摘要之前。
|
||||
它们不新增页签、弹窗或高级模式。每个编辑器使用可纵向调整大小的等宽文本域,默认值为
|
||||
`{}`。
|
||||
|
||||
## 编辑与保存
|
||||
|
||||
- 请求头接受 JSON 对象,所有值必须是字符串。
|
||||
- 请求体接受 JSON 对象,值必须是有界、可序列化的 JSON。
|
||||
- 用户输入在编辑时原样保留。JSON 语法、类型、大小或保留字段无效时,文本域显示
|
||||
`aria-invalid` 和就地错误;点击保存时阻止写入,并在现有设置错误区域显示对应连接。
|
||||
- 保存成功后,编辑器使用两个空格缩进重新格式化已保存对象。
|
||||
- 新连接从两个空对象开始。
|
||||
|
||||
## 兼容性说明
|
||||
|
||||
请求头说明明确列出直连、Continue、OpenCode 和 DeepSeek Harness 在原生支持范围内使用
|
||||
该值。请求体说明明确列出直连、Continue 和受管远程 OpenCode 支持,并说明本地
|
||||
OpenCode 与 DeepSeek Harness 不使用该值。
|
||||
|
||||
同一区域还必须说明:
|
||||
|
||||
- Runtime、协议和认证生成的字段优先。
|
||||
- 请求体只做顶层浅合并,不递归合并对象。
|
||||
- 自定义值按普通连接设置保存,不能用于保存 API Key 或其他密钥。
|
||||
|
||||
## 无障碍与键盘
|
||||
|
||||
- 每个文本域有稳定的可访问名称,并通过 `aria-describedby` 关联兼容性说明。
|
||||
- 无效状态不能只依赖颜色,必须同时提供错误文字和 `aria-invalid`。
|
||||
- 文本域遵循标准键盘编辑、选择、复制和粘贴行为;保存继续使用设置页唯一的主保存操作。
|
||||
- 焦点边框、字体、间距、颜色和深浅主题全部复用全局语义令牌。
|
||||
@@ -248,7 +248,9 @@ Execute 直接启动已签名 Runtime:
|
||||
- 托管 SSH 的生产 Prompt 从一开始就由 Agent 持有 ACP `ClientSideConnection`、原始
|
||||
Prompt Promise、Provider 轮次和 Runtime 进程。SSH relay 或 Desktop 进程不属于该
|
||||
Promise 的生命周期,因此正常退出、强制结束 Desktop 或本机网络中断后,Host 仍能继续
|
||||
后续模型/工具轮次。该路径要求 `runtime/acp` capability v4,即 Agent `0.11.14` 或更高。
|
||||
后续模型/工具轮次。该路径现在要求 `runtime/acp` capability v5;v5 同时保证 Agent
|
||||
能理解 Prompt-scoped 模型连接的自定义 Header/Body,旧 v4 Agent 由现有受管更新流程
|
||||
升级后再运行。
|
||||
- Agent 把 ACP session update、permission decision 和唯一 Prompt 终态写入有界语义
|
||||
transcript。Main 不恢复旧 JSON-RPC Promise,也不重发 `session/prompt`;Fresh Desktop
|
||||
只对同一 controller/binding/operation 执行 takeover、attach 和 ACK-exclusive page。
|
||||
|
||||
Reference in New Issue
Block a user