feat: support custom instance icons and refresh release

This commit is contained in:
shiyue
2026-08-25 22:11:07 +08:00
parent bd20a79d4b
commit 05480e511d
20 changed files with 1104 additions and 23 deletions

View File

@@ -0,0 +1,57 @@
# 实例自定义图标调研记录
## 已知需求
- 同一套 cc-web 部署到多台机器时,需要通过不同图标快速区分实例。
- 用户希望在设置中自行选择图标。
- 自定义结果在拉取最新版后必须保留。
## 待确认事实
- 当前默认图标的所有消费点。
- 设置页和设置 API 的扩展模式。
- 项目现有的 Git 外置运行数据目录与备份方式。
- 相关测试框架和浏览器缓存策略。
## 代码库初步事实
- 项目为无框架的 Node.js 单体:`server.js` 提供服务,`public/app.js``public/index.html``public/style.css` 构成主界面。
- 默认浏览器/PWA 图标均为 Git 跟踪文件:`public/favicon.ico``favicon-32x32.png``apple-touch-icon.png``icon-192.png``icon-512.png`,直接替换它们会在升级时产生冲突或被覆盖,因此不能作为实例自定义存储。
- 设置入口位于 `public/index.html`,设置页 HTML 由 `public/app.js` 中的构建函数生成;已有“外观”子页,可复用其导航卡和设置状态样式。
- 回归入口为 `npm run regression`,项目还包含多个 `scripts/*-unit.js` 与浏览器集成脚本,适合增加聚焦回归脚本并挂入总回归。
- 首轮本地全文检索被仓库中的大文本记录污染;后续必须收窄到 `server.js``public/``scripts/`,并用精确标识符核验行号。
## 图标与存储入口
- `public/index.html` 的浏览器图标链接位于 head登录页 Logo 使用 `icon-192.png``public/app.js` 的通知图标和重新渲染的登录框也直接使用 `/icon-192.png``public/sw.js` 的通知默认值同样硬编码该路径。
- 这意味着仅改 favicon 不足以形成一致的实例身份,至少应统一浏览器页签、登录 Logo 与通知图标Web App Manifest 的静态图标是否能动态化需按 PWA 缓存边界保守处理。
- 服务端已经支持 `CC_WEB_CONFIG_DIR`,默认指向仓库内 `config/`;测试通常把它指向临时目录。实例图标应落在该目录,生产可用外置目录,默认仓库内目录则通过精确 `.gitignore` 规则保护。
- `.gitignore` 已逐项忽略多种 `config/*.json` 运行配置,但尚无实例图标规则;需要在保留用户现有修改的前提下追加精确规则,不能把整个 `config/` 忽略。
## 选定方案
- 浏览器端把用户选择的 PNG/JPEG/WebP 居中裁剪并规范化为 512×512 PNG服务端只接受并验证 512×512 PNG最大 4 MiB。
- 运行文件固定为 `CONFIG_DIR/instance-icon.png`,不保存用户文件名或可控路径;通过临时文件 + rename 原子替换。
- 统一公开读取 URL 为 `/api/instance-icon`,默认返回现有 `icon-192.png`;配置接口返回基于内容哈希的 version前端以查询参数刷新缓存。
- 写入和恢复接口使用现有 Bearer token读取图标与 Manifest 公开,保证登录页也能显示。
- 提供动态 `/api/site.webmanifest`:无自定义时保留原 192/512 图标,有自定义时声明 512 图标。已安装 PWA 的操作系统缓存不承诺立即刷新。
- `.gitignore` 只追加 `config/instance-icon.png` 与原子临时文件规则,保留现有用户改动和其他配置可见性。
## 工作区隔离注意
- `.gitignore` 的既有修改位于暂存区(`git status` 第一列为 `M`),普通 `git diff` 不显示;本功能只能在工作树中追加精确规则,不能改写或取消暂存的用户内容。
- `server.js` 的配置目录在启动时统一创建实例图标常量可与其他配置路径集中定义HTTP 路由可复用附件接口的 `extractBearerToken`/`activeTokens` 鉴权方式。
- 现有静态服务会对所有 public 资源返回 no-store但动态实例图标仍需显式 `nosniff` 与内容版本,避免不同响应路径的缓存语义分叉。
## 并发写入归因修正
- 被中断的实现代理仍有一个已进入执行阶段的工具调用完成落盘:新增了 `scripts/regression.js` 的 219 行聚焦回归、服务端大小常量和路径骨架,并提前推进一次 TODO CSV。
- 因此聚焦测试不是 HEAD 预置而是该代理的有效测试产出主线程保留测试、合并重复常量并承担后续实现。CSV 的第 4/5 阶段状态在代码落下后重新与真实结果对齐。
## 主线程代码审查
- 写接口只接受鉴权后的 512×512 PNG路径完全由服务端固定配置读取、图标读取和 Manifest 无敏感内容,可供登录前消费。
- 默认与自定义图标都设置 `nosniff`;默认 ETag 使用实际文件哈希,自定义 ETag 使用内容版本,拉取新版默认资产后不会错误返回旧图 304。
- 客户端裁剪取短边居中后绘制到 512×512不拉伸上传失败不调用 apply因此保留旧实例图标。
- 现有聚焦回归验证真实子进程和临时 CONFIG_DIR并由 `withServer` 负责停止服务;测试临时目录清理可作为非阻断维护改进继续审查。
- 动态 favicon 的源图片在默认态为 192px、自定义态为 512pxhead 上固定 `sizes` 声明可能与默认资源自然尺寸不一致;应在最终审查中确认是否移除固定 sizes 更稳妥。

View File

@@ -0,0 +1,27 @@
# 实例自定义图标进度
## 2026-08-25
- 已读取 `planning-with-files``todo-list-csv` 与 Trellis 工作流。
- 已确认 `home-cc-web` codebase-memory 索引状态为 ready。
- 已创建并启动 Trellis 任务 `08-25-instance-custom-icon`
- 已识别并保留与本任务无关的工作区改动:`.gitignore``README.md``config/cross-conversation-replies.json`
- 待办脚本首次使用项目内路径失败,已确定实际安装路径并写入错误记录。
- 独立计划审查已通过,无阻断问题。
- 并行 codebase-memory 查询因 transport closed 失败;索引此前已确认 ready改由两个只读代理串行使用 MCP 调研,主线程稍后做本地交叉验证。
- 前端只读调研完成并与本地精确检索交叉验证,结果已持久化到 Trellis research 文档。
- 服务端只读调研完成,确认可复用 `CC_WEB_CONFIG_DIR`、二进制图片上传、Bearer 鉴权与固定路径写入模式;结果已持久化。
- 已完成跨层数据流、HTTP 契约、持久化与错误语义设计,写入 Trellis `info.md`
- 已配置并验证 Trellis implement/check 上下文;实现代理已启动,正在按测试先行方式修改产品代码。
- Trellis 实现代理长时间无产品改动且未响应进度询问,已安全中断;主线程接手测试与实现。
- 实现代理的在途工具调用于中断后完成落盘,新增 `scripts/regression.js --target instance-icon` 的完整测试目标;实现前运行按预期失败,静态契约缺少 index/frontend/SW/server/style/gitignore 五类实现。
- 第一版代码已落下;首次验证发现服务端预置同名大小常量导致重复声明,语法检查已在集成测试前准确阻断,正在定向修正。
- 合并重复常量后,`node --check server.js``node --check public/app.js``node scripts/regression.js --target instance-icon` 均通过。
- 服务端 API、CONFIG_DIR 固定路径持久化、动态图标/Manifest、设置页裁剪上传/预览/恢复与全局消费点已实现;进入相关与全量回归。
- `instance-icon``frontend-asset-version` 聚焦回归与 `npm run regression` 全量回归通过;`git diff --check` 通过。
- `git check-ignore` 证明正式/临时实例图标文件由新增精确规则忽略,且 `git ls-files` 不跟踪它们;用户已暂存 `.gitignore` 改动与本功能工作树改动保持分层。
- Trellis Phase 2.2 独立审查无阻断/高/中风险发现;按唯一低风险建议移除动态图标 link 的固定 sizes避免默认 192px 与自定义 512px 共用时提示不准确。
- 用户要求取消后续额外审计,改为重新打包并将当前工作区全部修改统一提交、推送。
- 已复用本机 `@oven/bun-linux-x64-baseline` 重新执行 `npm run build:single-exe`,更新 `dist-exe/cc-web-bun-linux-x64-baseline.tar.gz`
- 发布校验通过:六项 JavaScript 语法检查无错误;打包后二进制的 MCP `initialize` 返回有效 JSON-RPCtar.gz 可读取;`git diff --check` 通过。
- 新发布包 SHA-256 为 `2fb1f0a55ada79420f9599584c53fd4c1d04fb2d05cf25c29cda2150e3b27a48`,大小 43,871,596 bytes。

View File

@@ -0,0 +1,45 @@
# 实例自定义图标实施计划
## 目标
在设置页提供实例级图标选择能力,并让侧栏、浏览器页签等现有品牌图标消费点统一使用该图标。自定义图片与选择结果必须存放在 Git 管理之外,拉取/升级源码后仍保留。
## 验收边界
- 支持从本机选择常见栅格图上传,立即预览并保存。
- 支持恢复项目默认图标。
- 限制图片类型与大小,错误可理解且不破坏旧配置。
- 未配置时保持现有图标和行为,不引入升级迁移负担。
- 图标响应具备缓存更新机制;设置保存后当前页面可感知更新。
- 自定义文件和实例配置不进入 Git不被 `git pull` 覆盖。
## 阶段
| 步骤 | 状态 | 验收方式 |
|---|---|---|
| 1. 定位现有图标、设置和持久化链路 | DONE | 形成前后端入口、测试与数据目录清单 |
| 2. 明确实例级图标存储与兼容方案 | DONE | 记录接口、校验、缓存和升级兼容决策 |
| 3. 补充服务端配置、上传和图标响应回归测试 | DONE | 新测试先覆盖默认、上传、恢复、非法输入和持久化 |
| 4. 实现服务端实例图标持久化与接口 | DONE | 服务端测试通过,数据落在 Git 外置目录 |
| 5. 实现设置页图标选择、预览、恢复默认及全局应用 | DONE | 设置页可操作,现有图标消费点统一更新 |
| 6. 运行前后端测试与构建并修正问题 | DONE | 目标测试、完整相关测试和构建通过 |
| 7. 重新生成 CentOS 7 单文件发布包 | DONE | baseline Bun 构建成功,生成可执行文件与 tar.gz |
| 8. 验证发布包与工作区完整性 | DONE | 语法检查、MCP initialize 冒烟、归档读取和 diff 检查通过 |
| 9. 暂存并提交当前全部修改 | DONE | 按用户要求包含此前已暂存和本次全部修改 |
| 10. 推送到远端并核验结果 | DONE | 交付阶段推送 main 至 origin/main 并确认同步状态 |
## 设计原则
- 优先复用既有设置 API、数据目录与前端设置面板模式。
- 上传内容仅接受可安全解码/展示的图片类型,不允许用户控制落盘路径。
- 使用稳定的运行时 URL 暴露图标,并通过版本参数或响应缓存头避免旧图标残留。
- 不修改无关的用户工作区变更。
## 错误记录
| 错误 | 尝试 | 处理 |
|---|---:|---|
| 项目内不存在 `.codex/skills/todo-list-csv/scripts/todo_csv.py` | 1 | 改用技能实际安装路径 `/home/hdzx/.codex/skills/todo-list-csv/scripts/todo_csv.py` |
| 并行调用 codebase-memory 架构与两项检索时连接被关闭 | 1 | 停止并行压测;等待只读代理完成 MCP 检索后,用 `rg` 做行号交叉验证 |
| Trellis 实现代理长时间运行但未产生产品改动或状态回报 | 1 | 中断代理,主线程按已固化的 TDD 契约接手实现 |
| 服务端已有预置 `MAX_INSTANCE_ICON_SIZE`,首次实现重复声明导致语法错误,测试等待端口超时 | 1 | 定位并复用既有常量,先单独语法检查,再重跑聚焦测试 |