Files
codex_backend/codexClient.cjs.md
T
2026-05-24 22:53:05 +09:00

5.2 KiB
Raw Blame History

codexClient.cjs 说明

文件作用

这个文件是后端与本机 Codex CLI / @openai/codex-sdk 的适配层。它负责检查登录状态、启动登录、退出登录、构造 Codex 请求线程、执行普通回复和流式回复,并把这些能力导出给 Express 路由使用。

主要常量和状态

  • PROJECT_ROOT:项目根目录。
  • CODEX_WORKSPACE:专门给 Codex SDK 使用的工作目录 .codex-chat-workspace
  • DEFAULT_MODEL:来自环境变量 CODEX_MODEL 的默认模型。
  • DEFAULT_REASONING_EFFORT:来自环境变量 CODEX_REASONING_EFFORT 的默认推理强度。
  • AUTH_STATUS_CACHE_MS:登录状态缓存时间。
  • sdkPromise:缓存动态导入的 Codex SDK。
  • authStatusCache:缓存最近一次登录状态。
  • loginState:保存当前或最近一次登录命令的运行状态和日志。

文件加载时会创建 CODEX_WORKSPACE 目录。

主要函数

getCodexBin()

查找 Codex CLI 可执行文件。优先使用项目内 node_modules/.bin/codex,找不到时回退到全局 codex 命令。

getCodexHomeHint()

返回 Codex 本地配置目录提示。优先使用 CODEX_HOME 环境变量,否则使用用户目录下的 .codex

appendLoginLine(chunk)

把登录命令输出追加到 loginState.lines。它会跳过空行,并且只保留最近 120 行,避免日志无限增长。

runCodexCommand(args, options)

执行 Codex CLI 命令的通用封装:

  • 使用 spawn 启动命令。
  • CODEX_WORKSPACE 下运行。
  • 收集 stdout 和 stderr。
  • 支持传入 stdin。
  • 支持超时,超时后终止子进程。
  • 最终返回退出码、信号、输出和错误对象。

它主要用于登录状态检查和退出登录。

loadCodexSdk()

动态导入 @openai/codex-sdk,并用 sdkPromise 缓存导入结果,避免重复加载。

normalizeInput(input)

清洗前端传入的消息数组:

  • 只保留对象类型且有字符串 role 的项。
  • content 转为字符串。
  • 去掉空内容消息。

roleTitle(role)

把请求角色转换成写入提示词的标题:

  • developersystem 显示为开发者指令。
  • assistant 显示为 assistant。
  • 其他角色显示为 user。

buildCodexPrompt(input)

把结构化消息数组转换成单个 Codex prompt

  • 先标准化输入。
  • 将每条消息转换成 ### 角色标题 加正文的文本块。
  • 在开头加入本地网页聊天工具的约束说明。
  • 要求模型只回复最后一条 user 消息,不混入其他会话上下文。

normalizeModel(model)

合并请求体模型名和环境变量默认模型,并返回修剪后的字符串。

normalizeReasoningEffort(value)

校验推理强度,只允许 minimallowmediumhighxhigh。非法值会回退到 medium

createThreadOptions(body)

创建 Codex SDK thread 运行选项:

  • 使用只读沙箱。
  • 禁用审批。
  • 固定工作目录为 CODEX_WORKSPACE
  • 跳过 Git 仓库检查。
  • 禁用网络和 Web 搜索。
  • 透传推理强度和可选模型。

这些设置降低本地聊天代理对用户文件和网络的影响范围。

createCodexClient()

创建 Codex SDK 客户端,并关闭原始 agent reasoning 输出,让前端只展示面向用户的最终回答。

hasUsableAuth(status)

判断 Codex 是否可用:既要安装 CLI,也要处于已登录状态。

getAuthStatus(options)

检查 Codex 登录状态:

  • 默认使用短期缓存,force 为真时强制刷新。
  • 执行 codex login status
  • 根据退出码判断是否已登录。
  • 返回安装状态、登录状态、认证模式输出、提示消息、Codex home 和检查时间。

ensureLoggedIn()

在执行聊天请求前校验 Codex 可用性。CLI 未安装时抛出 503 错误;未登录时抛出 401 错误。

startLogin(options)

启动 Codex 登录流程:

  • 如果已有登录进程在跑,直接返回当前登录状态。
  • 默认启动 codex login
  • deviceAuth 为真时追加 --device-auth
  • 保存进程 pid、开始时间、结束时间、退出码、信号和输出日志。
  • 登录进程结束后清空认证状态缓存。

getLoginState()

返回当前登录状态快照,供前端轮询展示。

logoutCodex()

执行 codex logout,清空认证状态缓存,并返回命令结果。

runCodexOnce(body, signal)

执行一次性聊天请求:

  • 先确认 Codex 已登录。
  • buildCodexPrompt 生成 prompt。
  • prompt 为空时抛出 400 错误。
  • 创建 Codex client 和 thread。
  • 调用 thread.run(prompt, { signal })
  • 返回最终文本、thread id 和 usage。

runCodexStream(body, signal, handlers)

执行流式聊天请求:

  • 校验登录和 prompt。
  • 调用 thread.runStreamed(prompt, { signal })
  • 遍历 SDK 返回的事件流。
  • 对 agent message 计算增量文本,并调用 handlers.onDelta(delta)
  • 记录 turn.completed 的 usage。
  • 遇到 SDK 错误事件时抛出后端错误。
  • 返回完整文本、thread id 和 usage。

导出接口

该文件导出:

  • getAuthStatus
  • getLoginState
  • logoutCodex
  • runCodexOnce
  • runCodexStream
  • startLogin

这些函数由 server/index.cjs 的 API 路由调用。