feat: 支持将第三方本地 CLI 注册为 provider(而非只能配置 HTTP 模型 API)
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 401
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
### 使用场景 / Use case
想接入一个**第三方本地 CLI** 作为 Cindy 的模型后端,例如:
- 本地 agent wrapper(把自有脚本包装成可被 Cindy 调用的后端)
- 本地 LLM CLI / 自定义协议的代理进程
- 需要受控本地执行、不愿为此暴露 HTTP 端口的团队内部工具
### 当前问题 / Current limitation
目前自定义 provider 完全是 **HTTP endpoint 形态**:`packages/model-providers/src/types.ts` 里 `CustomProviderRuntimeConfig` 必填 `baseUrl`,`wireProtocol` 只能是 `anthropic-messages` / `openai-responses` / `openai-chat` 三者之一;`CustomProviderConfig.runtimes` 按 agent(claude-code / codex / pi)分别配置各自的 baseUrl / 模型 / headers。
所谓"本地模型"支持,本质上是把 Ollama / LM Studio 等当成 `127.0.0.1` 上的 loopback HTTP 来用(`managedOllamaProvider.ts` 只是拼出一个 loopback `baseUrl` + `wireProtocol`,并不负责拉起进程)。仓库里**没有任何"本地可执行文件 / 子进程"形态的 provider**。
因此想接入本地 CLI,只能先把它包成一个 OpenAI-compatible HTTP 服务、在本地监听某个端口,再回头填 `baseUrl`:
- 用户得自己写/维护一个 HTTP 适配层,纯 CLI 工具也要为此起服务;
- 进程生命周期(启动、保活、崩溃重建)要用户自己管;
- 多个 CLI 时端口分配、健康探活都要手搓。
### 期望方案 / Proposed solution
支持**定义一个第三方本地 CLI 作为 provider / 模型后端**,由客户端直接以可信方式拉起并与它对话,而不强制用户先暴露一个 HTTP 端口。具体形态(草案,待讨论):
- 在 provider 配置里新增一种**本地 CLI 类型**(区别于现有的 URL 类型),至少包含:可信绝对路径、固定的 argv 前缀、必要的环境变量、输入输出协议(stdio / 类 OpenAI)。
- **安全优先**:可执行文件应由主进程拥有并 vet(例如文件选择 + 探测 + 持久化"已批准身份"),renderer 不直接下发命令文本;binary 变更后触发重新审批。避免做成 free-text command 字段直接执行。
- 复用现有 provider 消费链路:`buildUserProvider` 把它展开成与内置厂商同形状的 `Provider`,进入同一 active-catalog,供路由 / 选择器 / `listProviders` 统一消费;模型选择、工具调用、流式等能力按 CLI 实际支持情况声明。
### 已考虑的替代方案 / Alternatives considered
- **自己写 OpenAI-compatible HTTP wrapper**:当前唯一可行路径,门槛高、要自己管进程生命周期,正是本 issue 想消除的负担。 - **Ollama / LM Studio loopback 预设**:只适用于"本身就提供 OpenAI 兼容 HTTP 服务"的工具,且服务仍要用户自己起。
- **给 provider 配置加 free-text `command` 字段直接执行**:不符合"renderer 不能传任意 command"的安全基线,容易变成任意命令执行入口,不建议。
### 关联代码
- `packages/model-providers/src/types.ts`(`CustomProviderConfig` / `CustomProviderRuntimeConfig` / `ProviderWireProtocol`)
- `packages/model-providers/src/user-provider.ts`(`buildUserProvider`)
- `apps/desktop/src/main/local-model-runtime/managedOllamaProvider.ts`(现有 loopback HTTP 形态的"本地模型")
Contributor guide
Research direction
Start with packages/model-providers/src/types.ts and packages/model-providers/src/user-provider.ts, then compare the loopback approach in apps/desktop/src/main/local-model-runtime/managedOllamaProvider.ts. Clarify the approved-binary and stdio/protocol design before implementation; done means a vetted local CLI can enter the active provider catalog without requiring a user-managed HTTP wrapper.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron, typescript
- Domain
- backend-api-design, cli, desktop, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100