#630·evolver

feat: support custom headers in LLM runner (EVOLVER_LLM_HEADERS)

Author: chliuqiCreated Sep 17, 2026Updated Sep 17, 2026

问题

内置的 llm runner(llmRunner.js)在 complete() 函数中硬编码了 HTTP 请求头:

  • "" + + "" + + "javascript headers: { 'content-type': 'application/json', authorization: Bearer \ },
  • "" + + "" + + "" +

某些 OpenAI 兼容的 API 提供商需要额外的请求头来进行路由/认证。例如,OpenCode Go 需要 + "" + x-opencode-session + "" + 头来进行请求路由:

  • "" + + "" + + "json { "error": { "type": "MissingSessionID", "message": "Request is missing x-opencode-session and cannot be routed efficiently." } }
  • "" + + "" + + "" +

没有这个头,API 会返回 400 Bad Request。

建议方案

通过环境变量 + "" + EVOLVER_LLM_HEADERS + "" + 支持自定义请求头:

简单格式(单个头):

  • "" + + "" + + "ash export EVOLVER_LLM_HEADERS='x-opencode-session:evolver-autoexec-12345'
  • "" + + "" + + "" +

JSON 格式(多个头):

  • "" + + "" + + "ash export EVOLVER_LLM_HEADERS='{"x-opencode-session":"evolver-12345","user-agent":"my-agent/1.0"}'
  • "" + + "" + + "" +

实现建议

在 + "" + eadLlmRunnerConfig() + "" + 中解析 + "" + EVOLVER_LLM_HEADERS + "" + 并合并到请求头:

  • "" + + "" + + "javascript // readLlmRunnerConfig const rawHeaders = env['EVOLVER_LLM_HEADERS'] ?? ''; const extraHeaders = rawHeaders.startsWith('{') ? JSON.parse(rawHeaders) : Object.fromEntries(rawHeaders.split(',').map(h => h.split(':').map(s => s.trim())));

return { apiKey, baseUrl, model, maxTurns, maxFileBytes, extraHeaders };

// complete() const response = await fetchFn(\/chat/completions, { method: 'POST', headers: { 'content-type': 'application/json', authorization: \Bearer \, ...config.extraHeaders, }, body: JSON.stringify({ model: config.model, messages, tools: TOOLS, tool_choice: 'auto' }), signal, });

  • "" + + "" + + "" +

临时解决方案

目前使用本地代理来添加所需的请求头,然后转发到上游 API。这虽然可行,但增加了一个额外的进程和网络跳转。

环境信息


Problem

The built-in llm runner (llmRunner.js) hardcodes HTTP headers in the complete() function:

  • "" + + "" + + "javascript headers: { 'content-type': 'application/json', authorization: \Bearer \ },
  • "" + + "" + + "" +

Some OpenAI-compatible API providers require additional headers for routing/authentication. For example, OpenCode Go requires + "" + x-opencode-session + "" + for request routing:

  • "" + + "" + + "json { "error": { "type": "MissingSessionID", "message": "Request is missing x-opencode-session and cannot be routed efficiently." } }
  • "" + + "" + + "" +

Without this header, the API returns 400 Bad Request.

Proposed Solution

Add support for custom headers via environment variable + "" + EVOLVER_LLM_HEADERS + "" + :

Simple format (single header):

  • "" + + "" + + "ash export EVOLVER_LLM_HEADERS='x-opencode-session:evolver-autoexec-12345'
  • "" + + "" + + "" +

JSON format (multiple headers):

  • "" + + "" + + "ash export EVOLVER_LLM_HEADERS='{"x-opencode-session":"evolver-12345","user-agent":"my-agent/1.0"}'
  • "" + + "" + + "" +

Implementation

In + "" + eadLlmRunnerConfig() + "" + , parse + "" + EVOLVER_LLM_HEADERS + "" + and merge into request headers:

  • "" + + "" + + "javascript // readLlmRunnerConfig const rawHeaders = env['EVOLVER_LLM_HEADERS'] ?? ''; const extraHeaders = rawHeaders.startsWith('{') ? JSON.parse(rawHeaders) : Object.fromEntries(rawHeaders.split(',').map(h => h.split(':').map(s => s.trim())));

return { apiKey, baseUrl, model, maxTurns, maxFileBytes, extraHeaders };

// complete() const response = await fetchFn(\/chat/completions, { method: 'POST', headers: { 'content-type': 'application/json', authorization: \Bearer \, ...config.extraHeaders, }, body: JSON.stringify({ model: config.model, messages, tools: TOOLS, tool_choice: 'auto' }), signal, });

  • "" + + "" + + "" +

Workaround

Currently using a local proxy that adds the required header before forwarding to the upstream API. This works but adds an extra process and network hop.

Environment