所有页面
本页内容

config.json

config.json 是中继自己的配置文件:其中有它的端口、谁可以访问它、访问令牌、决定一轮何时算作卡住的计时器,以及可选的隧道和预览通道。oar setup 会创建它。设置向导不会询问的所有内容,都由你手动编辑。

你在网页界面中设置的大部分内容不在这个文件中。见网页界面中的设置与环境变量。

文件在哪里 #

安装方式 路径
在 macOS、Linux 和 WSL 上全局安装 ~/.oar/config.json
在 Windows 上全局安装 %APPDATA%\oar\config.json
设置了 OAR_STATE_ROOT 的全局安装 该文件夹中的 config.json
git 检出 检出目录中的 server/config.json

OAR_STATE_ROOT 会移动全局安装的整个状态文件夹(配置文件、数据和日志);见 OAR 在哪里保存它的文件。

COPILOT_WEB_RELAY_CONFIG 让中继使用某一个文件,无论它在哪里,但仅限于不通过 oar 自己的启动器启动中继的情况:node server/server.js,或 oar copilot(当该文件存在时)。oar setup、oar start、oar restart 和服务始终使用该安装自己的 config.json,不管这个变量怎么写。在没有 server/config.json 的检出中,oar copilot 会改为在 ~/.config/copilot-remote 中创建它的文件(在 Windows 上为 %LOCALAPPDATA%\copilot-remote)。见环境变量。

中继会让该文件只有其所有者可读(在 macOS 和 Linux 上为模式 0600),因为它以明文保存访问令牌。请像对待密码一样对待它的副本。

谁写入它 #

  • oar setup 写入令牌、localhostOnly 和 port,其他每个键都保持原样。它创建的文件,或缺少以下键的文件,还会得到 pollIntervalMs、processingTimeoutMs(600000)和 conversationSessionMode。见 oar setup 和首次运行。
  • 中继在你从 Settings(设置)安装或更新提供商 CLI 时写入 cliBinaries。它只更改这一个键。如果它无法把文件读取为 JSON,它会拒绝写入,并只为正在运行的进程保留该绑定。
  • 中继在启动时若不存在该文件,会创建它,其中有空的 authToken、端口 3333、localhostOnly: true、pollIntervalMs 和 conversationSessionMode。它还会删除旧版本遗留的 features 键(见已弃用、被忽略和内部使用的键)。
  • 你,用任意文本编辑器。

手动编辑 #

该文件是一个 JSON 对象。你省略的键取其默认值,而 previews 这样的嵌套块会作为一个整体读取。编辑后,重启中继:中继只在启动时读取一次该文件。 你保存文件时,正在运行的中继所持有的任何内容都不会改变。用 oar restart(全局安装)重启,或用对话 ⋯ 菜单中的 🌄 Restart web relay(重启网页中继)重启。

  • 未知的键会被忽略并保留。设置向导和中继自己的写入都会把它留在原处。
  • 无效的 JSON 不会让中继停止。它会记录 Failed to read config.json, using defaults.,并以默认值运行:端口 3333、仅本机,以及一个随机令牌,每次启动都是新的,并打印在日志中。在你修好文件之前,你保存的令牌不再有效。第二个读取者,即选择数据文件夹的那一个,会退回到默认文件夹。中继不会动这个损坏的文件。
  • 错误的值按键逐个处理。下文的默认值是计时器或限制缺失或无法使用时中继所用的值。隧道和预览通道会保持关闭并记录原因;中继本身继续运行。
  • 命令行在一次运行中优先于文件:node server/server.js 上的 --token <value> 和 --port <number>(oar copilot 也会传递它们;oar start 不会)会覆盖 authToken 和 port,并且永远不会保存到文件中。不是 1 到 65535 之间数字的 --port 会被忽略并给出警告。

不要对不是有效 JSON 的文件运行 oar setup

oar setup 会把它无法解析的文件当作不存在。然后它会用一个新令牌写一个新的 config.json 覆盖它,旧文件中的其他每个键都会丢失。请先修好 JSON。对你手动编辑的文件保留一份副本。

网络与访问 #

键 类型 默认值 作用
authToken string 无:每次启动一个随机令牌 每个浏览器、worker 和 API 客户端用来登录的令牌。如果为空,中继每次启动都会生成一个随机令牌,打印到日志中,且不保存它。oar setup 会写入一个固定的令牌。
port number 3333 HTTP 和 WebSocket 端口,1 到 65535 之间的整数。
localhostOnly boolean true true 把中继绑定到 127.0.0.1,因此只有本机能访问它。任何其他值,包括 false、null、1 和 "yes",都会绑定到所有接口(0.0.0.0),让你的局域网可以访问它。只有 true 和文本 "true"(不区分大小写)算作开启;默认值只在该键缺失时适用。它不影响下文的隧道。
remotePath string "" 路径前缀,用于反向代理在子路径下提供中继的情况,例如 /oar。会补上开头的斜杠,去掉末尾的斜杠。中继会从传入请求中去掉该前缀,并把它加入登录 cookie 的路径、socket 路径,以及文件和分享链接的地址。
trustProxy Express trust proxy 值 "loopback" 哪些代理可以设置中继所信任的 X-Forwarded-* 标头。客户端地址(速率限制、登录锁定、分享访问日志)以及新分享链接的主机和协议都通过它读取,因此直接连接的客户端无法伪造它们。默认值适合同一台机器上的代理或隧道。当另一台主机上的代理转发到中继时,使用跳数(1)、地址或子网("10.0.0.0/8"),或它们的列表(反向代理)。
allowedOrigins string array [] 0.9.11 新增 除中继自身之外,实时 Socket.IO 连接所接受的额外浏览器来源(协议、主机,以及非默认的端口,例如 "https://relay.example.com")。改写 Host 标头的代理需要它。见反向代理。
publicHostnames string array [] 访问中继本身的主机名。预览通道会拒绝位于其中某个主机名上的 previews.publicBaseUrl(localhost 和 127.0.0.1 也一样),这样被预览的应用永远不会与中继共享登录 cookie。
tunnelMarkerHeaders string array [] 隧道边缘添加到流量中的额外标头名称。带有 cf-ray 或其中某个标头的请求无法访问会话 worker 路径(你自己的智能体的 worker 使用的 socket,它们只在本机运行)。cf-ray 始终在列表中。逗号分隔的字符串也可以。环境变量 COPILOT_TUNNEL_MARKER_HEADERS 中的名称(逗号分隔)会添加到这些名称中;这里的空列表不会关闭它们。
pushVapidSubject string mailto:copilot-remote@example.com 中继在 Web Push 请求中发给推送服务的联系地址(通知)。把它设为你自己的 mailto: 地址。
sharedPresenceMaxPerConversation number 200 一个分享对话链接最多计入的实时查看者数。至少为 1。达到上限时,空闲最久的查看者会被移除以腾出位置。
sharedPresenceMaxGlobal number 5000 总共最多计入的分享链接实时查看者数,规则相同。不会低于每个对话的上限。

关于首次连接、令牌和局域网访问,见首次运行。

轮次与计时器 #

键 类型 默认值 作用
processingTimeoutMs number,毫秒 600000 一轮在其 worker 没有任何活动迹象的情况下可以持续多久,之后中继会把它放回队列。它不是一轮时长的上限。0 或更小的值使用默认值。见一轮卡住时。
maxRequeueRetries number 5 一条消息最多可以尝试多少次,之后彻底失败。至少为 1。见重新排队。
contextIndicatorMode "default" 或 "bar" "default" 输入区如何以其上边缘的一条线显示上下文的占用程度。default 是一条全宽的线,颜色随上下文填满从绿色变为红色。bar 是同样的线,从左侧增长到已用上下文的比例。任何其他值,无论大小写,都视为 default。

单轮最长时长、后台任务超时和停滞监视不在这里:见一轮卡住时。

重启与关闭 #

这些键决定中继计划重启(🌄 Restart web relay)的方式。见重启与恢复。每个计时器的单位都是毫秒;0 或更小的值,或不是数字的值,使用默认值。

键 类型 默认值 作用
restartShutdownTimeoutMs number,毫秒 45000 重启等待正在运行的一轮结束的时长,超时则以 shutdown-timeout 失败放弃。
restartGracefulTimeoutMs number,毫秒 8000 中继等待正常停止的时长,之后强制重启。
restartSpawnTimeoutMs number,毫秒 18000 一次尝试等待重启或恢复阶段的时长,超时则算作失败(spawn-timeout)。
restartRebindTimeoutMs number,毫秒 20000 一次尝试在重启后等待会话重新绑定的时长(rebind-timeout)。
restartReadyCooldownMs number,毫秒 1000 重启报告就绪后,队列保持暂停的时长。
restartMaxAttempts number 3 重启在最终定论之前可以尝试的次数。至少为 1。
restartRetryBackoffMs number array,毫秒 [1000, 3000, 7000] 第 2、3 次及以后各次尝试之前的等待时间。当尝试次数多于条目数时,重复最后一个条目。不是正数的条目会被丢弃;结果为空时使用默认值。

内存 0.9.19 新增 #

键 类型 默认值 作用
heapLimitMb number,MB RAM 的 60%,2,048 到 8,192 中继的堆上限,是至少为 512 的整数。启动中继的每种方式都会读取它:oar start、systemd 服务、Windows 自启动和 CLI 扩展。从下次启动起生效。不是整数或小于 512 的值会被忽略,并在日志中记一行;超过机器 RAM 或容器内存限制的值会被降到该大小。NODE_OPTIONS 中的 --max-old-space-size,或启动 server.js 的 node 命令行上的该参数,优先于它。见中继内存耗尽。

工作区与数据 #

键 类型 默认值 作用
workspaceRootAllowList string array 未设置 对话可以在其中启动的绝对路径文件夹,连同其中的所有内容。未设置或为空时允许任何已存在的文件夹。不是已存在文件夹的条目会被记录并排除。设置了环境变量 COPILOT_WORKSPACE_ROOT_ALLOW_LIST 时,以它为准。见限制对话可以在哪里启动。
dataDir string 服务器旁边的 data/ 数据库和中继锁文件所在的位置,以及 0.9.17 新增 deepseek-claude,即 DeepSeek 对话的 Claude Code 状态。相对路径从存放 config.json 的文件夹算起。上传文件随它一起放到其中的 uploads/;只有使用服务器旁边默认 data/、且没有 COPILOT_WEB_RELAY_DATA_DIR 的中继,才把它们保存在服务器旁边的 uploads/ 中。设置了 COPILOT_WEB_RELAY_DATA_DIR 时,以它为准。oar start、oar restart 和 Linux systemd 服务总会设置它(设为 ~/.oar/data、%APPDATA%\oar\data 或你自己的值),因此对以这些方式启动的中继,这个键没有效果。它是给直接启动的检出用的。Windows 开机启动器只固定配置文件,不固定这个变量。

提供商 CLI #

键 类型 默认值 作用
cliBinaries object 由中继写入 提供商 CLI 的路径,按提供商:claude 和 grok。当从 Settings 进行的安装解析出路径时,中继会写入它,并在下次启动时使用,以便再次找到同一个程序。你可以手动设置路径。不是可执行文件的条目会被记录并忽略。其他名称,包括 copilot,都不会使用。
sdkPath string 自动检测 Copilot SDK 的 index.js 的路径。只有当 sdkPath 和 cliPath 都设置时,才会跳过对已安装 Copilot CLI 的搜索。单独设置时,它还告诉中继到哪里寻找扩展引擎的启动文件,即它旁边。
cliPath string 自动检测 Copilot CLI 运行时入口(app.js)的路径。与 sdkPath 一起使用。中继还会把它作为 CLI 程序交给它启动的 Copilot worker,除非环境中已经指定了一个。
sdkVersion string 找到的最新版本 一个确切版本,例如 1.0.63。此时对已安装 Copilot CLI 的搜索只接受该版本。当 sdkPath 和 cliPath 都设置时被忽略。

这些键在中继自己与已安装的 Copilot CLI 通信时起作用,例如导入已有的 Copilot 会话和列出模型。搜索会查找 Copilot CLI 的包缓存(COPILOT_PKG_DIR 会添加一个优先搜索的文件夹)。见 GitHub Copilot。

预览 #

previews 块会开启预览通道:一个使用自己端口和主机名的第二个监听器,用于发布本地开发服务器和文件夹。设置、主机名和前端代理见 preview 工具的页面。

键 类型 默认值 作用
previews.enabled boolean false 开启该通道。只有 true 算数。
previews.port number 中继 port + 1 预览监听器的端口。至少为 1024,且不能是中继的端口;0 会在每次启动时选一个空闲端口。
previews.bindHost string 127.0.0.1 监听器绑定的地址。不是环回地址的地址需要 previews.allowPublicBind。
previews.allowPublicBind boolean false 允许不是环回地址的 previews.bindHost。这样每个预览都可以不经前端代理从网络访问。
previews.publicBaseUrl string 无 该通道公开的 http(s) 地址。开启预览时必填。它的主机名必须与中继的不同(见 publicHostnames)。末尾的斜杠会被去掉。
previews.allowedTargetHosts string array [] 除本机之外,端口预览可以指向的主机,例如容器或虚拟机的地址。
previews.maxLive number 8 整个中继同时存在的预览最多数量。不是正整数的值使用 8。

如果在预览开启时其中某条规则不满足,中继会记录 PREVIEW LANE disabled 及原因,保持该通道关闭并继续运行。

以下环境变量会覆盖对应的键:COPILOT_PREVIEWS_ENABLED(1、true、0、false)、COPILOT_PREVIEWS_PORT、COPILOT_PREVIEWS_BIND_HOST、COPILOT_PREVIEWS_PUBLIC_BASE_URL 和 COPILOT_PREVIEWS_ALLOWED_TARGET_HOSTS(逗号分隔)。

隧道 #

有两种隧道可以从你的网络之外访问中继。它们相互独立,可以同时运行。两者默认都关闭,缺少必填值的托管隧道会保持关闭并记录原因。

sshTunnel #

通往你自己服务器的反向 SSH 隧道。见 SSH 隧道。

键 类型 默认值 作用
sshTunnel.mode "disabled" 或 "managed" "disabled" managed 让中继运行并重启该隧道。
sshTunnel.required boolean false 当托管隧道未连接时,包括首次连接之前以及缺少必填值时,中继会暂停从队列中取消息。
sshTunnel.user string 无 服务器上的 SSH 用户。托管时必填。
sshTunnel.host string 无 服务器的主机名或地址。托管时必填。
sshTunnel.remotePort number 无 在服务器上打开的端口(1 到 65535)。托管时必填。
sshTunnel.remoteBind "loopback" 或 "public" "loopback" 远程端口只在服务器本身上开放,还是在它的所有接口上开放。与 localhostOnly 无关。
sshTunnel.command string ssh SSH 程序。使用 PATH 上的名称或绝对路径:相对路径从中继的程序文件夹算起。
sshTunnel.identityFile string 无 要使用的私钥;~ 会被展开。没有它时,SSH 使用其代理或默认密钥。
sshTunnel.autoReclaimPort boolean true 当远程端口已被占用时,在服务器上运行清理并重试。只有 false 会关闭它。
sshTunnel.reclaimStaleSshSessions boolean false 作为该清理的一部分,同时结束你自己在服务器上什么都没运行的 SSH 会话。
sshTunnel.remoteCleanupCommand string 内置 在服务器上运行的你自己的清理命令,取代内置命令。

cloudflaredTunnel #

运行 Cloudflare 的 cloudflared,由你自己安装;OAR 不附带它。见 Cloudflare Tunnel。

键 类型 默认值 作用
cloudflaredTunnel.mode "disabled" 或 "managed" "disabled" managed 让中继运行 cloudflared。COPILOT_CLOUDFLARED_MODE 会覆盖它。
cloudflaredTunnel.required boolean false 当托管隧道未连接时,包括缺少必填值时,中继会暂停从队列中取消息。
cloudflaredTunnel.token string 无 你自己的 Cloudflare 隧道的令牌。托管时必填。COPILOT_CLOUDFLARED_TOKEN 会覆盖它。
cloudflaredTunnel.binary string cloudflared 程序,可以是绝对路径,或在 PATH 上查找的名称。COPILOT_CLOUDFLARED_BINARY 会覆盖它。
cloudflaredTunnel.extraArgs string array [] 添加在 cloudflared tunnel run --token <token> 之后的参数。

网页界面中的设置与环境变量 #

网页界面中的设置不在这个文件中。 提供商开关和密钥、模型列表、单轮最长时长、后台任务超时和功能开关都保存在中继的数据库中,位于数据文件夹内。这个文件保存的是中继在数据库打开之前就需要的内容(数据文件夹、端口、令牌),以及关于这台机器的信息(CLI 路径、隧道)。界面写入这个文件的唯一内容是 cliBinaries。0.9.17 新增 DeepSeek 在这里也没有键:它的 API 密钥、基础 URL 和预算从 Settings → Providers → DeepSeek(设置 → 提供商 → DeepSeek)保存到数据库中。

环境变量。 完整列表见环境变量。当某个键存在对应的变量时,变量优先于文件:COPILOT_WEB_RELAY_DATA_DIR(dataDir)、COPILOT_WORKSPACE_ROOT_ALLOW_LIST、COPILOT_CLOUDFLARED_* 和 COPILOT_PREVIEWS_*(列在各自的章节中)。COPILOT_TUNNEL_MARKER_HEADERS 是例外:它的名称会添加到 tunnelMarkerHeaders 中。--token 和 --port 选项在一次运行中优先于两者。COPILOT_WEB_RELAY_CONFIG 本身见文件在哪里。

示例 #

所有值都是虚构的。删除你不用的块。

{
  "authToken": "0f3c1a9e-example-token-do-not-copy",
  "port": 3333,
  "localhostOnly": false,
  "remotePath": "",
  "trustProxy": "loopback",
  "allowedOrigins": [],
  "publicHostnames": ["relay.example.com"],
  "tunnelMarkerHeaders": ["x-edge-request-id"],
  "processingTimeoutMs": 600000,
  "maxRequeueRetries": 5,
  "contextIndicatorMode": "bar",
  "workspaceRootAllowList": ["/home/dev/projects", "/srv/sites"],
  "dataDir": "data",
  "cliBinaries": {
    "claude": "/home/dev/.local/bin/claude",
    "grok": "/home/dev/.grok/bin/grok"
  },
  "restartShutdownTimeoutMs": 45000,
  "restartGracefulTimeoutMs": 8000,
  "restartSpawnTimeoutMs": 18000,
  "restartRebindTimeoutMs": 20000,
  "restartReadyCooldownMs": 1000,
  "restartMaxAttempts": 3,
  "restartRetryBackoffMs": [1000, 3000, 7000],
  "previews": {
    "enabled": true,
    "port": 3334,
    "bindHost": "127.0.0.1",
    "allowPublicBind": false,
    "publicBaseUrl": "https://preview.example.com",
    "allowedTargetHosts": [],
    "maxLive": 8
  },
  "sshTunnel": {
    "mode": "managed",
    "required": false,
    "user": "ubuntu",
    "host": "vps.example.com",
    "remotePort": 4444,
    "remoteBind": "loopback",
    "identityFile": "~/.ssh/id_ed25519"
  },
  "cloudflaredTunnel": {
    "mode": "disabled",
    "token": "",
    "binary": "cloudflared",
    "extraArgs": []
  }
}

已弃用、被忽略和内部使用的键 #

如果你在文件中发现其中某个键,可以保留它,也可以删除它:

键 它是什么
features 已停用。功能开关现在保存在中继的数据库中,对应 Settings → Features(设置 → 功能)。启动时,中继会把它在这里找到的值复制到数据库中(除非数据库中已经保存了值),并从文件中删除该键。
sshTunnel.enabled、cloudflaredTunnel.enabled mode 的旧形式。true 表示 managed,并且只在 mode 不是 disabled 或 managed 时才会读取。
pollIntervalMs 会写入新文件,但中继不读取它。它没有效果。
conversationSessionMode isolated 或 shared。会写入新文件。中继会把该值存到每条会话记录上,并在其状态中报告,但 OAR 中没有任何东西会因这两个值而表现不同。它对你没有效果。
cliPort、model 只由一种需要你手动启动的独立模式使用(一个开发者应急入口;没有任何 oar 命令会启动它)。你用 oar start 启动的中继会忽略 model。它只为一件事读取 cliPort:预览通道永远不会选用那个端口。
host 只由连接到中继的程序(会话 worker 和 Copilot 扩展)读取,用来构建它们使用的地址;中继自己的监听器会忽略它(见 localhostOnly)。请省略它。