Skip to content

本地 Alpine Codex 文件系统浏览与管理 - #435

Open
henryz78 wants to merge 3 commits into
omnimind-ai:mainfrom
henryz78:codex/alpine-filesystem-browser
Open

本地 Alpine Codex 文件系统浏览与管理#435
henryz78 wants to merge 3 commits into
omnimind-ai:mainfrom
henryz78:codex/alpine-filesystem-browser

Conversation

@henryz78

Copy link
Copy Markdown
Contributor

功能

为本地 Alpine Codex 增加完整文件系统管理入口:

  • / 浏览 Alpine / PRoot 文件系统
  • 支持 /root/etc/usr/workspace 及挂载目录
  • 文本文件读取、编辑与保存
  • 新建文件和目录
  • 重命名、移动与递归删除
  • 复制 Linux 绝对路径
  • 显示权限、大小和软链接目标
  • 从 Codex 设置页直接进入文件系统管理

实现

  • 文件操作通过 TerminalManager 在 Alpine 内执行,保持 PRoot 挂载及软链接语义
  • Flutter 与原生层通过独立 MethodChannel 通信
  • 文件名和列表字段使用 Base64 编码传输,兼容中文及特殊字符
  • 文本保存使用应用缓存临时文件传入 Alpine,避免 Shell 参数长度限制
  • 单文件编辑上限为 1 MB,超出时只读预览前 1 MB

改动范围

仅涉及本地 Alpine 文件管理及 Codex 设置入口,不修改 Agent provider、远程 Bridge 和模型配置逻辑。

验证

  • Flutter 定向静态分析:通过
  • Alpine 文件系统 Flutter 页面测试:2/2 通过
  • Codex 相关 Flutter 回归测试:16/16 通过
  • Kotlin AlpineFileSystemServiceTest:通过
  • :app:testDevelopStandardDebugUnitTest 定向任务:通过

Windows 环境下 prepareEmbeddedTerminalRuntime 的 tar 解包存在上游路径兼容问题,定向 Android 测试通过跳过该解包任务执行。

@XuYouo XuYouo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

结论:Request changes。当前实现存在三处可能造成不可逆数据破坏的问题:非 UTF-8/二进制文件会被有损解码后重新写回;路径规范化会改写合法 Linux 文件名并可能操作错误目标;重命名冲突会静默覆盖或把源项移入已有目录。另外,目录软链接无法正确浏览,目录请求也存在旧响应覆盖新路径状态的竞态。请修复这些问题,并补充二进制/非法 UTF-8、尾随空格与反斜杠文件名、重命名冲突、目录软链接及乱序响应测试。

已独立验证:Flutter 页面测试 2/2 通过、相关 Dart 定向分析无问题、:app:testDevelopStandardDebugUnitTest 通过、git diff --check 通过;这些检查不覆盖下述运行时数据安全问题。

Comment thread app/src/main/java/cn/com/omnimind/bot/terminal/AlpineFileSystemService.kt Outdated
Comment thread app/src/main/java/cn/com/omnimind/bot/terminal/AlpineFileSystemService.kt Outdated
Comment thread app/src/main/java/cn/com/omnimind/bot/terminal/AlpineFileSystemService.kt Outdated
Comment thread app/src/main/java/cn/com/omnimind/bot/terminal/AlpineFileSystemService.kt Outdated
Comment thread ui/lib/features/home/pages/codex/alpine_file_system_page.dart Outdated
@henryz78

Copy link
Copy Markdown
Contributor Author

已按 Review 逐项修复,提交:e4ee4873

  • 文件读取改为严格 UTF-8 解码;NUL、非法 UTF-8、软链接和超过 1 MB 的文件只读,原生写入前也会再次校验现有文件,避免有损写回。
  • 路径不再 trim(),也不再把反斜杠替换为 /;保留 Linux 文件名中的尾随空格和反斜杠。
  • 移动/重命名会检测已有文件、目录及断链软链接,使用 mv -n,冲突时保留源项并返回错误。
  • 目录列表使用 find -H,可跟随作为入口的目录软链接,同时保留目录内软链接元数据。
  • Flutter 目录加载增加 generation 校验,旧请求响应不会覆盖当前路径状态。
  • 补充了二进制、非法 UTF-8、尾随空格、反斜杠、重命名冲突、目录软链接和乱序响应测试。

本地验证:

  • Alpine 文件系统页面 + Codex 远程工作区浏览器测试:9/9 通过
  • Dart 定向分析:No issues found
  • AlpineFileSystemServiceTest:通过
  • git diff --check:通过

@XuYouo

XuYouo commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the follow-up fixes. I re-reviewed the latest head, and the five issues from the previous review appear to be addressed. Two remaining filesystem-safety blockers still prevent merging:

  1. createFile uses [ -e "$target" ] || : > "$target". For a broken symlink, -e is false and the redirection follows the symlink, creating or truncating its target outside the selected directory. I reproduced this locally. Please treat any existing directory entry, including a broken symlink, as a collision (for example, check -e or -L) before redirecting, and add a regression test.

  2. Native decodeField decodes arbitrary Base64 filename bytes directly to a UTF-8 String. Malformed UTF-8 is replaced lossily, so an invalid-byte filename can alias a real filename containing U+FFFD. Because destructive operations later send that lossy string back as the path, selecting one entry can operate on the other. Please retain an opaque Base64/raw path token as the operation identifier, or strictly reject non-UTF-8 names and disable mutations for them. Add a collision test covering invalid UTF-8 bytes versus a literal replacement-character filename.

Once these two cases are fixed and covered, this should be ready for another review.

@henryz78

Copy link
Copy Markdown
Contributor Author

Addressed both remaining blockers in efbade83.

  1. createFile now treats -e or -L as a collision, so broken symlinks are rejected before redirection. The actual creation also runs with shell noclobber (set -C) to avoid truncating an entry created during the check/create window.
  2. Base64 path and name fields now use strict UTF-8 decoding. Entries containing malformed UTF-8 bytes retain only opaque Base64 identity/display tokens, have an empty operation path, are marked unreadable/unwritable, and expose no open/copy/rename/delete actions in Flutter. A valid filename containing literal U+FFFD remains a separate operable entry.

Regression coverage added for:

  • broken-symlink collision and noclobber file creation;
  • invalid byte 0xFF versus a literal U+FFFD filename at both native parsing and Flutter interaction layers.

Verification:

  • Alpine filesystem + Codex workspace Flutter tests: 10/10 passed
  • targeted Dart analysis: no issues found
  • AlpineFileSystemServiceTest: passed
  • git diff --check: passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants