Imported from john-walks-slow/cpa-adapter (
AGENTS.md). Install upstream withnpx skills add john-walks-slow/cpa-adapter. Copyright stays with the author.
cpa-adapter AGENTS.md
目标
CLIProxyAPI c-shared 插件:在 API 网关层为第三方模型提供中介适配。首批:
- reasoning_content adapter:DeepSeek thinking + tool call 时,给带 tool_calls 的 assistant 消息补
reasoning_content,消除The reasoning_content in the thinking mode must be passed back400 硬失败。 - agent_message adapter:Codex MultiAgentV2 投递给第三方 Responses provider 的
agent_messageitem,改写为标准message/role=user,让子代理能收到任务文本。 - image_message adapter:文本模型请求中的图像 part 替换为占位文本(strip),避免图像漏到不支持视觉的上游导致 400 硬失败。
地图
| 模块 | 职责 |
|---|---|
plugin/ |
主插件包(package main, c-shared 入口、生命周期、路由) |
plugin/config/ |
YAML 配置解析 + 默认值 + glob 匹配 |
plugin/adapter/ |
适配器注册表与三个 adapter 实现 |
plugin/docs/config.example.yaml |
配置示例 |
能力选型
- RequestNormalizer:唯一能看到"翻译后 provider payload"的插件钩子。所有 executor 走
sdktranslator.TranslateRequest→ 内建翻译 →hooks.NormalizeRequest。 - ManagementAPI:暴露
/v0/management/adapter/apply-count和/adapter/config用于可观测。 - 不启用 interceptor:在翻译后 payload 上做防御性补丁,不改源格式。
开发与调试
# 构建(单平台,需 CGO_ENABLED=1)
make build
# 或:CGO_ENABLED=1 go build -buildmode=c-shared -o bin/cpa-adapter.dll ./plugin
# 测试
make test # go test ./... -race
# Lint
make vet
规范
- 插件 ABI:
plugin/plugin.go中//export符号不可改名。 - RequestNormalizer 契约:返回空/nil body 表示 no-op(host 保留原 body);返回非空 body 表示替换。
- 幂等:adapter 必须对已转换的 payload 二次执行时返回 changed=false。
- 不伪装明文:opaque/encrypted 不可解析的内容保持原样,由上游显式拒绝;图像 strip 占位同样不伪装理解内容。
- 模型名匹配:用 glob + 配置 allowlist/exclude,避免误伤 OpenAI 原生路径。
关键设计决策
- 顺序执行:registry 先 reasoning_content → agent_message → image_message;每个 adapter 的输出喂给下一个。
- 保守默认:
reasoning_content.models=["deepseek*"],agent_message.exclude_models=["gpt-*"],image_message.models=["deepseek*"]+exclude_models=["gpt-*","claude-*","gemini-*"]。 - 复用最近 reasoning:与 host 的 kimi executor fallback 一致。
- 图像遍历可复用:
adapter/image_message.go的collectImageParts抽象为按 ToFormat 的遍历/收集结构(imageRef{path,kind}),strip 模式只写占位文本;describe 模式届时再补图像内容提取,不重写遍历层。