Skip to content

feat: support custom headers in LLM runner (EVOLVER_LLM_HEADERS) #630

Description

@chliuqi

问题

内置的 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions