Initial commit
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
# 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 路由调用。
|
||||
Reference in New Issue
Block a user