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

171 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)`
把请求角色转换成写入提示词的标题:
- `developer``system` 显示为开发者指令。
- `assistant` 显示为 assistant。
- 其他角色显示为 user。
### `buildCodexPrompt(input)`
把结构化消息数组转换成单个 Codex prompt
- 先标准化输入。
- 将每条消息转换成 `### 角色标题` 加正文的文本块。
- 在开头加入本地网页聊天工具的约束说明。
- 要求模型只回复最后一条 user 消息,不混入其他会话上下文。
### `normalizeModel(model)`
合并请求体模型名和环境变量默认模型,并返回修剪后的字符串。
### `normalizeReasoningEffort(value)`
校验推理强度,只允许 `minimal``low``medium``high``xhigh`。非法值会回退到 `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 路由调用。