一个将 Fitten Code 聊天请求转换为 OpenAI Chat Completions 风格接口的轻量代理服务。
- 提供
/v1/models和/v1/chat/completions兼容接口 - 支持非流式响应
- 支持 SSE 流式响应
- 支持
messages[].content字符串与分段数组输入 - 支持单张图片输入
- 支持 tool_calls / function calling 协议转换(上游 XML
<function_calls>→ OpenAI 标准tool_calls) - 统一错误结构,便于调用方处理
- 已支持:文本输入、流式输出、内容分段数组、单图输入
- 已支持:上游 XML
<function_calls>自动转换为 OpenAI 标准tool_calls(非流式 + 流式增量格式) - 已支持:请求体中的
assistant.tool_calls与role: "tool"消息整理进聊天输入 - 明确不支持:同一条消息中的多图输入
- 暂未实现:代理自己发起并执行 tools / function calling(2api 只做协议转换,执行由接入方 agent 完成)
- 暂未实现:embeddings 等扩展能力
当同一条消息包含多张图片时,服务会返回:
- HTTP 400
error.code = "multiple_images_not_supported"
npm install先复制环境变量示例文件,再填入自己的 Fitten 账号凭据:
# Linux / macOS
cp .env.example .env
# Windows
copy .env.example .env编辑 .env,填入 FITTEN_USERNAME 和 FITTEN_PASSWORD,然后启动:
npm start默认监听地址:http://localhost:3000
完整示例见 .env.example。
PORT:服务端口,默认3000FITTEN_BASE_URL:Fitten 服务地址,默认https://fc.fittenlab.cnDEFAULT_MODEL:默认模型名,默认fitten-codeFITTEN_USER_AGENT:上游请求使用的 User-Agent;留空时使用内置浏览器 UAFITTEN_REQUEST_TIMEOUT_MS:上游请求超时,默认120000FITTEN_ACCESS_TOKEN_REFRESH_MARGIN_MS:access token 提前续期窗口,默认60000MAX_IMAGE_BYTES:单张图片大小上限,默认5MBFITTEN_USERNAME:Fitten 登录账号FITTEN_PASSWORD:Fitten 登录密码
GET /GET /v1/models返回当前可用模型列表(标准 OpenAI 格式):
{
"object": "list",
"data": [
{
"id": "fitten-code",
"object": "model",
"created": 1700000000,
"owned_by": "fitten"
}
]
}POST /v1/chat/completions
Content-Type: application/json{
"model": "fitten-code",
"messages": [
{
"role": "system",
"content": "请完全使用中文回答。"
},
{
"role": "user",
"content": "你好,请只回复 ok"
}
],
"stream": false
}{
"model": "fitten-code",
"messages": [
{
"role": "user",
"content": "请分三行介绍一下这个代理的作用"
}
],
"stream": true,
"stream_options": {
"include_usage": true
}
}POST /v1/chat/completions
Content-Type: application/json
{
"model": "fitten-code",
"messages": [
{ "role": "system", "content": "你是助手" },
{ "role": "user", "content": "帮我查一下当前目录" }
],
"stream": false
}如果上游返回 XML <function_calls>,2api 会自动转成 OpenAI 标准 tool_calls 格式:
{
"id": "chatcmpl-xxx",
"object": "chat.completion",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "我来帮你查一下。",
"tool_calls": [{
"index": 0,
"id": "xml_tool_call_xxx_0",
"type": "function",
"function": {
"name": "run_terminal",
"arguments": "{\"command\":\"ls -la\"}"
}
}]
},
"finish_reason": "tool_calls"
}]
}流式请求同样支持 tool_calls 转换。当上游返回 XML <function_calls> 时,最后一个 SSE chunk 的 finish_reason 为 tool_calls,并包含 tool_calls 字段:
data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"xml_tool_call_xxx_0","type":"function","function":{"name":"run_terminal","arguments":"{\"command\":\"ls -la\"}"}}]},"finish_reason":"tool_calls"}]}{
"model": "fitten-code",
"messages": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "请描述这张图片里的主要内容"
},
{
"type": "input_image",
"image_url": {
"url": "https://example.com/demo.png"
}
}
]
}
],
"stream": false
}如果单条消息里同时放入多张图片,服务会直接返回 multiple_images_not_supported。
服务会先完成 Fitten 登录和会话准备,再将请求转换后发送到上游聊天接口,最后返回 OpenAI 风格响应。
非流式返回结构示例:
{
"id": "chatcmpl-xxx",
"object": "chat.completion",
"created": 1710000000,
"model": "fitten-code",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "ok"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 94,
"completion_tokens": 2,
"total_tokens": 96
}
}当 stream: true 时,返回 OpenAI 风格的 SSE 数据流。
图片输入仅支持单张图片,接受以下格式:
data:image/...;base64,...http://...https://...
限制说明:
- 单条消息最多一张图片
- 单张图片默认不超过
5MB - 非图片内容、空响应或不支持的协议会返回明确错误码
当前版本已知限制如下:
- 当前只实现
GET /v1/models和POST /v1/chat/completions - 默认会在缺失 system message 时自动补一条
请完全使用中文回答。 - 不支持同一条消息中的多图输入
- 不支持 embeddings
- 不支持文件上传
- 不支持跨实例共享会话缓存;当前 session cache 为进程内内存缓存
scripts/check-*.js主要是本地联调脚本,不属于离线可重复的单元测试- 不支持代理自己发起和执行 tools / function calling(2api 只做协议转换,执行由接入方 agent 完成)
服务会尽量返回统一的 OpenAI 风格错误结构:
{
"error": {
"message": "...",
"type": "invalid_request_error",
"code": "image_too_large",
"param": "messages.content.image_url"
}
}目前文档中明确列出的常见错误码包括:
multiple_images_not_supported:同一条消息中出现多张图片image_too_large:图片超过MAX_IMAGE_BYTES限制invalid_image_data_url:data:image/...Base64 数据不合法unsupported_image_url:图片 URL 不是data:image/...或http/httpsremote_image_fetch_failed:远程图片拉取失败remote_image_not_image:远程 URL 返回的内容不是图片remote_image_empty:远程图片响应为空invalid_credentials:Fitten 登录失败或账号密码无效login_failed:Fitten 登录接口返回了非预期失败invalid_upstream_json:上游返回了无法解析的 JSONinvalid_login_payload:登录成功响应缺少必要字段refresh_token_invalid:refresh token 无效refresh_user_not_found:refresh token 对应用户不存在refresh_access_token_failed:刷新 access token 失败refresh_token_unavailable:当前 session 中没有可用 refresh tokenupstream_timeout:上游请求超时client_closed_request:客户端提前断开连接upstream_unauthorized:上游返回 401upstream_request_failed:上游请求返回非预期状态码empty_upstream_response:上游返回了空响应internal_error:服务内部错误invalid_request:请求参数不合法
仓库提供了一组本地联调脚本,主要用于回归聊天主链路、图片边界与 tool_calls 协议转换。常用命令:
npm test
npm run check:proxy
npm run check:stream
npm run check:tool-calls
npm run check:image-boundaries
npm run check:all其中 npm test 当前主要做基础语法检查,已经覆盖 index.js、src/openai-request.js、src/message-content.js 和 src/streaming.js。
npm run check:tool-calls 会验证 XML <function_calls> → OpenAI tool_calls 的协议转换,包括非流式响应组装和流式增量 chunk 格式。
这些脚本依赖真实的 Fitten 凭据和外部网络环境,适合作为本地集成验证。
.
├─ index.js 入口:路由定义、请求重试与响应组装
├─ package.json
├─ README.md
├─ src/
│ ├─ errors.js 公共错误
│ ├─ fitten-meta.js Fitten 元数据生成
│ ├─ fitten-payloads.js 上游请求载荷构建
│ ├─ helpers.js 工具函数
│ ├─ message-content.js 消息归一化与图片处理
│ ├─ openai-request.js OpenAI 请求解析
│ ├─ parse-xml-tool-calls.js XML <function_calls> 解析器
│ ├─ session.js 会话管理与 token 刷新
│ └─ streaming.js 流式响应处理
└─ scripts/
└─ check-*.js 本地联调脚本