Problem
internal/agent/glm.go and internal/agent/deepseek.go implement the native protocols for their respective providers:
glm.go:66 → https://open.bigmodel.cn/api/paas/v4/ (BigModel native, chat/completions)
deepseek.go:77 → https://api.deepseek.com (DeepSeek native, /v1/chat/completions)
But the actual deployment serves both models through Anthropic Messages API proxies:
- GLM →
https://open.bigmodel.cn/api/anthropic (x-api-key auth, anthropic-version: 2023-06-01)
- DeepSeek →
https://token.sensenova.cn (Authorization: Bearer, Sensenova-hosted)
These are separate billing/auth paths from the native endpoints.
Evidence
Discovered while running the self-development loop for #1:
- Calling
paas/v4/chat/completions with the GLM token returned 429 余额不足 — even though the same token works fine on the Anthropic-compat endpoint (used by the CLI itself).
- Calling
api.deepseek.com returned 401 — the DeepSeek key in use is actually a Sensenova token, valid only at token.sensenova.cn.
cmd/selfdev/main.go (landed in #3) demonstrates the working request shape for both proxies — same auth token, two different header conventions, Anthropic Messages request/response bodies.
Impact
The production conductor binary cannot run a real agent loop end-to-end. Planner/executor/reviewer calls will fail at the HTTP layer on day one in any environment that uses the proxy-based deployment.
Proposed fix
Rewrite glm.go and deepseek.go to call the Anthropic Messages API through their respective proxies:
- Change default
baseURL values:
glm.go: https://open.bigmodel.cn/api/anthropic
deepseek.go: https://token.sensenova.cn
- Request shape:
POST {baseURL}/v1/messages with body {model, max_tokens, messages: [{role, content}]}.
- Headers:
- Both:
anthropic-version: 2023-06-01, Content-Type: application/json
- GLM:
x-api-key: <token>
- DeepSeek:
Authorization: Bearer <token> (set both — Sensenova specifically wants Bearer)
- Response shape:
{content: [{type, text}], usage: {input_tokens, output_tokens}, stop_reason}.
- Drop the
choices[0].message parsing path; map content[0].text into the existing Response.Text.
Consider extracting a shared anthropicClient since both providers speak the same protocol — only the baseURL and auth header differ.
Test strategy
httptest mock that returns a Messages-format response; assert the agent extracts content[0].text correctly.
- Error mapping: 401/403 → blocked, 429 → retryable, 5xx → retryable.
- Keep the existing
BaseURL config override so tests still work.
Reference
- Working harness:
cmd/selfdev/main.go (already committed)
- Artifacts:
self-dev-artifacts/issue-1-planner-glm52.txt, self-dev-artifacts/issue-1-reviewer-deepseek.txt
Problem
internal/agent/glm.goandinternal/agent/deepseek.goimplement the native protocols for their respective providers:glm.go:66→https://open.bigmodel.cn/api/paas/v4/(BigModel native,chat/completions)deepseek.go:77→https://api.deepseek.com(DeepSeek native,/v1/chat/completions)But the actual deployment serves both models through Anthropic Messages API proxies:
https://open.bigmodel.cn/api/anthropic(x-api-keyauth,anthropic-version: 2023-06-01)https://token.sensenova.cn(Authorization: Bearer, Sensenova-hosted)These are separate billing/auth paths from the native endpoints.
Evidence
Discovered while running the self-development loop for #1:
paas/v4/chat/completionswith the GLM token returned429 余额不足— even though the same token works fine on the Anthropic-compat endpoint (used by the CLI itself).api.deepseek.comreturned401— the DeepSeek key in use is actually a Sensenova token, valid only attoken.sensenova.cn.cmd/selfdev/main.go(landed in #3) demonstrates the working request shape for both proxies — same auth token, two different header conventions, Anthropic Messages request/response bodies.Impact
The production
conductorbinary cannot run a real agent loop end-to-end. Planner/executor/reviewer calls will fail at the HTTP layer on day one in any environment that uses the proxy-based deployment.Proposed fix
Rewrite
glm.goanddeepseek.goto call the Anthropic Messages API through their respective proxies:baseURLvalues:glm.go:https://open.bigmodel.cn/api/anthropicdeepseek.go:https://token.sensenova.cnPOST {baseURL}/v1/messageswith body{model, max_tokens, messages: [{role, content}]}.anthropic-version: 2023-06-01,Content-Type: application/jsonx-api-key: <token>Authorization: Bearer <token>(set both — Sensenova specifically wants Bearer){content: [{type, text}], usage: {input_tokens, output_tokens}, stop_reason}.choices[0].messageparsing path; mapcontent[0].textinto the existingResponse.Text.Consider extracting a shared
anthropicClientsince both providers speak the same protocol — only the baseURL and auth header differ.Test strategy
httptestmock that returns a Messages-format response; assert the agent extractscontent[0].textcorrectly.BaseURLconfig override so tests still work.Reference
cmd/selfdev/main.go(already committed)self-dev-artifacts/issue-1-planner-glm52.txt,self-dev-artifacts/issue-1-reviewer-deepseek.txt