fix(codex): 在回合结束前发送生成图片 - #190
Open
zpdg wants to merge 1 commit into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves the Codex agent experience by delivering imagegen outputs to Feishu as soon as the generated image files become stable on disk, instead of waiting for the Codex turn to fully complete.
Changes:
- Add a
GeneratedImageDeliverywatcher that polls the active Codex thread’sgenerated_images/<thread-id>/directory and sends stable images during the run (with safety checks, dedupe, and a max-per-run cap). - Expose
getGeneratedImagesDir()as an optional AgentAdapter capability and implement it for the Codex adapter (supporting configured home, profile-local home, inheritedCODEX_HOME, and default home). - Wire the watcher into the IM run loop and add unit tests for directory resolution and delivery behavior (including symlink escape rejection and ambiguous failure handling).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/bot/generated-image-delivery.test.ts | Adds unit coverage for polling/stability, per-thread isolation, symlink escape protection, and non-retry failure notice behavior. |
| tests/unit/agent/codex-generated-images-dir.test.ts | Verifies Codex generated images directory resolution across config/env/profile scenarios. |
| src/bot/generated-image-delivery.ts | Introduces the polling-based delivery implementation with containment checks, file type/size gating, stability detection, and dedupe. |
| src/bot/channel.ts | Integrates fast-path image delivery into Codex runs and adds a Codex instruction to avoid double-sending via tools/CLI. |
| src/agent/types.ts | Extends the adapter interface with an optional generated-images directory hint. |
| src/agent/codex/adapter.ts | Implements getGeneratedImagesDir() consistent with how CODEX_HOME is configured for the Codex process. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+153
to
+156
| for (const entry of entries) { | ||
| if (this.delivered.size >= this.maxImages) return; | ||
| if (!entry.isFile() || !IMAGE_EXTENSIONS.has(extname(entry.name).toLowerCase())) continue; | ||
| const candidatePath = resolve(threadDir, entry.name); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
Codex 通过
imagegen生成图片后,文件会先写入$CODEX_HOME/generated_images/<thread-id>/。当前 Bridge 在 Codex 回合仍在运行时没有把这些文件发送到飞书的路径,因此图片即使已经生成完毕,也可能继续等待模型后续响应、网络重试或整个回合结束。在网络不稳定或图片工具结果较大时,这段额外等待可能从数秒扩大到数分钟。一次实际排查中,图片已经落盘,但直到约 47 分钟后才被发送;瓶颈发生在图片生成之后,而不是图片生成本身。
根因
现有 Codex 适配器会处理文本和命令执行事件,但不会在运行过程中把
generated_images中的新文件交给 channel 层。channel 层因此无法在图片准备好时直接调用已有的图片发送接口,只能依赖 Codex 后续行为或最终输出。修改内容
generated_images目录,兼容显式codexHome、profile 隔离目录、CODEX_HOME和默认用户目录。lark-cli导致重复。安全与去重
realpath做根目录和 thread 目录的路径包含检查。generated_images的目录或文件。与 #113 的区别
#113 从最终 Markdown 回复中提取并发送工作区产物,执行时机在 Agent 产生最终输出之后。本 PR 针对 Codex 的
generated_images/<thread-id>,在回合结束前即可发送稳定的图片文件,因此能覆盖“图片已生成,但后续 Codex 响应或网络重试仍然很慢”的场景。如果未来合并 #113,两个发送路径应统一去重语义,避免同一图片同时被快速路径和最终 Markdown 路径发送。
验证
pnpm test:93 个测试文件、560 项测试全部通过。pnpm typecheck:通过。pnpm build:通过。git diff --check:通过。dist/cli.js与本分支源码构建产物逐字节一致。12:03:57.767,回合结束时间为12:04:00.878,提前约 3.1 秒,仅发送一次。12:07:11.921,回合结束时间为12:08:44.389,提前约 92.5 秒,仅发送一次。影响范围
该快速发送路径仅对能提供
generated_images目录的 Codex 适配器启用;Claude 和其他未实现该可选能力的 Agent 行为不变。