Skip to content

Latest commit

 

History

History
235 lines (193 loc) · 11.3 KB

File metadata and controls

235 lines (193 loc) · 11.3 KB

架构设计

本文描述 Codex Theme Studio的运行边界、模块模型和兼容策略。产品总览见 README,好友通讯见 好友与宠物串门

设计原则

  1. Codex 安装包保持不变,不解包、不重签、不替换资源。
  2. 浏览器只提交受约束的数据,不拥有任意文件、shell、CSS 或 JavaScript 能力。
  3. 所有主题输出由 Helper 确定性生成,输入相同则输出相同。
  4. DOM 增强找不到目标时必须降级,不能阻止背景和基础颜色工作。
  5. 应用、暂停和 renderer 重建都必须可重复执行。

分层

Browser Studio
    │ token-protected localhost JSON API
    ▼
Local HTTP server
    ├── ThemeSchema   字段白名单与范围验证
    ├── ThemeStore    JSON / 图片原子存储
    ├── RuntimeState  当前主题与 CDP 会话
    └── ThemeSupervisor
            ├── CodexAppController
            ├── CDP discovery / evaluate
            ├── deterministic ThemeRenderer
            └── NativePetBridge
                        │
                        ├── Codex main renderer
                        └── Codex avatar-overlay renderer

Codex pet runtime
    │ authenticated REST + cursor-based long polling
    ▼
Companion Service (separate project)
    └── users / friendships / visits / events

Browser Studio

  • 在 Studio 中央区域按 Codex 视口比例等比适配;默认基线为 1512×944,应用后同步实际 renderer 视口与 sidebar/main/composer 矩形。
  • 本地解码图片和提取调色板。
  • 维护未保存 draft、当前选择模块与交互状态。
  • 只调用主题 CRUD、状态、应用和暂停等固定 API。

Local HTTP server

  • 只监听 127.0.0.1
  • 静态页面不需要令牌,但 API 必须同时通过 token、Host、Origin 和 Fetch Metadata 校验。
  • 没有文件浏览、通用命令或通用 CDP evaluate 路由。

ThemeStore

  • 读取内置主题和用户主题,内置主题只读。
  • 检查 ID、真实路径、图片签名、大小和后缀。
  • 创建主题时先写临时目录,再原子 rename;更新用户主题时通过临时目录和备份目录原位替换,ID 保持不变。
  • 无效或半写入主题在列表阶段被忽略。

ThemeSupervisor

  • 串行化应用与暂停操作,避免并发重启/注入。
  • 复用已有受管理 CDP 会话;必要时请求一次正常重启。
  • 监控 renderer target,发现新 target 时检查主题标记并补注入。
  • 保存当前主题 ID、CDP 端口、实测布局和受限原生 UI 快照,以便 Helper 自身重启后继续恢复。

Companion Service

  • 是独立项目、独立进程和独立数据目录,不由本地 Helper 代理。
  • Codex pet runtime 直接使用服务地址和设备 Bearer 令牌通讯。
  • 主题只保存服务开关和根地址,令牌按地址隔离保存在 Codex 本地存储。
  • 提供设备身份、好友关系、在线心跳、串门状态机与有界事件长轮询。
  • 服务不可用时只降级好友能力,不影响主题应用和本地访客状态机。

Pet Care Runtime

  • pet-care.mjs 是独立、纯函数可测试的本机成长状态机,不依赖主题文件或好友服务。
  • pet-profile.json 只保存成长开关、状态徽标开关和每日目标;实际等级、经验、四项状态、冷却与连续陪伴保存在 Codex renderer 的 pet-care:v1 本地记录。
  • 每两小时结算一次温和状态变化,最多补算 24 小时;没有后台计时器,也没有省电模式。
  • 原生 avatar-overlay 只监听官方宠物点击并发送“摸摸”命令,不阻止 Codex 原事件,也不修改 React 私有状态。
  • 好友来访互动只在本机追加陪伴经验;服务端仍只负责好友与串门事实。

主题模型

主题 Schema 版本当前为 1。核心结构:

{
  "schemaVersion": 1,
  "id": "quiet-orbit-ab12cd34",
  "name": "Quiet Orbit",
  "palette": {
    "accent": "#73DACA",
    "secondary": "#8AA7FF",
    "surface": "#12151A",
    "text": "#EEF2F5"
  },
  "material": {
    "glassOpacity": 0.82,
    "blur": 20,
    "radius": 16,
    "backdropDim": 0.28
  },
  "composition": {
    "positionX": 50,
    "positionY": 50,
    "scale": "cover"
  },
  "copy": {
    "kicker": "CODING WITH CONTEXT",
    "headline": "今天想构建什么?",
    "subtitle": "主题定义保持简单,体验保持完整。"
  },
  "welcome": {
    "placement": "native",
    "positionX": 50,
    "positionY": 22,
    "alignment": "center",
    "visibility": {
      "icon": true,
      "copy": true,
      "cards": [true, true, true, true]
    },
    "modules": {
      "icon": { "offsetX": 0, "offsetY": 0 },
      "copy": { "offsetX": 0, "offsetY": 0 },
      "cards": { "offsetX": 0, "offsetY": 0 }
    },
    "cardLabels": null,
    "cardIcons": ["native", "native", "native", "native"]
  },
  "sidebar": {
    "brand": "Codex",
    "visibility": {
      "newTask": true,
      "scheduled": true,
      "plugins": true,
      "sites": true,
      "pullRequests": true,
      "chat": true
    },
    "actions": {
      "newTask": { "label": null, "icon": "native" },
      "plugins": { "label": "我的扩展", "icon": "sparkles" }
    }
  },
  "composer": {
    "style": "glass",
    "glowIntensity": 0.7,
    "imageOpacity": 0.28
  },
  "shell": {
    "preset": "classic-blue",
    "title": "Codex 2007",
    "topbar": { "visible": true },
    "petDock": { "visible": true, "width": 20, "title": "Codex 宠物", "placeholder": "将 Codex 宠物拖到这里" },
    "statusbar": { "visible": false, "text": "Codex 已就绪" }
  },
  "surfaces": {
    "chrome": "#2E82E6", "chromeHighlight": "#EAF6FF", "panel": "#EDF7FF", "panelAlt": "#DCEEFF",
    "border": "#72A8D8", "code": "#F4FAFF", "inlineCode": "#DDEEFF"
  },
  "typography": { "ui": "classic", "code": "classic-mono", "scale": 1 },
  "hero": "hero.webp"
}

welcome.modules 使用相对 Codex 主内容区的百分比偏移,因此同一主题能随窗口尺寸缩放。Studio 0.3 不再编辑旧版整组欢迎区位移;加载到编辑器时会回到 native,再应用独立模块偏移。Renderer 仍接受旧字段,保证磁盘上的旧主题可被读取和暂停。

cardLabelsnull 时保留 Codex 原生卡片文本;存在时可包含 0 到 4 项,并与 visibility.cardscardIcons 等长。Renderer 优先读取卡片按钮的 aria-labelledby,避免依赖不稳定的嵌套层级。图标 key、侧边栏入口配置和输入框样式均经过 Schema 白名单校验。

Studio 预览模型

Studio 中央画布使用 CSS Grid 提供可用区域,预览则按 Codex 视口宽高比取 contain 尺寸。默认采用实测的 1512 × 944,应用主题后从注入结果读取当前 renderer 的 window.innerWidth / innerHeight,并在监控探针中持续采集 sidebar、main 和 composer 的 getBoundingClientRect()。暂停主题后的探针会额外采集原生快捷卡片矩形、默认标签,以及首页、四张卡片和六个侧边栏入口的 SVG viewBox 与白名单绘制属性;快照写入 RuntimeState,Studio 用安全 DOM API 重建 SVG。Studio 使用这些矩形设置横纵容器比例,装饰性窗口栏不再占用 main 高度。拖拽和 renderer 注入都使用真实主内容区宽高百分比,因此改变 Studio 面板、浏览器尺寸或 Codex 窗口后不会产生横向或纵向漂移。指针按下只建立拖拽候选,超过 6px(触摸为 9px)才捕获移动;偏移会吸附原点,并限制在主内容区和输入框上方的安全范围内。

编辑态只在 Studio DOM 上增加选择框、模块标签、拖拽光标和 contenteditable。主题保存后只保留白名单数据;干净预览和 Codex renderer 均不会收到这些编辑器装饰。

模块到 Codex DOM 的映射

Studio 模块 Renderer 目标 能力 降级行为
Sidebar .app-shell-left-panel 品牌字符、六个已知入口的名称、图标和显隐 未找到入口时跳过该入口
Icon [data-testid="home-icon"] 显隐、相对偏移 保留原生图标位置
Copy 原生 heading + 注入 kicker/subtitle 文案、对齐、显隐、相对偏移 保留背景和基础颜色
Cards home suggestions wrapper 四卡显隐、文本、相对偏移 未命中的卡片保留原生状态
Composer .composer-surface-chrome 玻璃、荧光边缘、图片覆盖、材质与颜色 图片缺失时退化为玻璃输入框
Native shell .app-header-tint + #ctm-native-commandbar + 原生左/右侧边栏 + 输出面板 换肤原生顶栏、右上角控件和面板;快捷栏按钮代理到原生侧边栏入口 未命中时保留 Codex 原生状态与功能
Native pet bridge 独立 avatar-overlay renderer + 主 renderer 的宠物中心入口 保留官方宠物,监听官方点击作为摸摸,在旁边显示成长状态与访客 sidecar 找不到原生 overlay 时成长面板仍可用,不伪造主宠物

只有非零模块偏移才写入覆盖 transform,避免破坏 Codex 图标自身可能存在的旋转或缩放。

Renderer 应用顺序

主题模式:

  1. 创建或更新唯一的 #codex-theme-studio-style
  2. 写入根主题标记,用于 probe 和幂等判断。
  3. 标记并换肤当前可见的原生顶栏控件、右侧边栏和输出面板;不改变原生点击与状态管理。
  4. 根据独立宠物档案挂载宠物中心,把成长摘要与访客状态同步给原生宠物 overlay;不创建自定义主宠物。
  5. 应用侧边栏品牌,以及入口名称、图标和显隐。
  6. 定位首页 heading,创建或复用 kicker/subtitle。
  7. 应用文案、对齐、模块显隐和卡片文本。
  8. 根据主内容区尺寸计算模块像素偏移,并通过有界周期刷新与 resize 监听在 DOM 重建后重新匹配。

pet-only 模式会先执行完整主题清理,再仅注入 #codex-pet-only-style、成长/好友运行时和原生宠物桥接,因此系统白色/黑色主题及 Codex 默认布局保持不变。暂停时只移除本项目创建的 style、属性和节点,并恢复记录过的原始文字;成长数据保留,重新启用后继续使用。

应用状态机

idle
  → loading-theme
  → locating-codex
  → stopping-codex       (仅第一次受管理会话)
  → launching-codex      (仅第一次受管理会话)
  → waiting-for-renderer
  → injecting
  → active

任意应用阶段 → error → retry
active → paused
active → injecting       (主题切换或 renderer 重建)

兼容策略

注入分为三级:

  1. 根层:页面背景、颜色变量和 color-scheme,最少依赖 DOM。
  2. 稳定表面:侧栏、main、composer、dialog 等已有语义类名或 role。
  3. 实验增强:首页文案、卡片、消息气泡与操作栏,允许局部降级。

每次注入返回 selector 命中统计。后续 0.5 会把统计扩展成可视化兼容性报告,并按 Codex 版本维护基线。

为什么不提供任意 CSS

主题文件是可导入资产。允许任意 CSS 会带来数据读取、界面覆盖、钓鱼和升级后不可控选择器等风险;允许任意 JavaScript 则直接突破 renderer 边界。因此当前 Schema 只暴露产品明确支持的 token 和布尔开关,由内部 renderer 映射到固定规则。