flavor-code 1.2.7 → 1.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +405 -369
- package/README.zh-CN.md +387 -356
- package/dist/agent/loop.d.ts +4 -0
- package/dist/agent/types.d.ts +10 -0
- package/dist/{app-R3SDG2OH.js → app-USAFQVSX.js} +379 -12
- package/dist/{chunk-NVLYFU6P.js → chunk-F2HMO5Q2.js} +28 -11
- package/dist/{chunk-WN2EZV3Y.js → chunk-G32MCAZA.js} +1 -1
- package/dist/{chunk-N2S7USST.js → chunk-RQTYHUMK.js} +2 -1
- package/dist/{chunk-5RHJ3PQN.js → chunk-WGYNTR4Q.js} +1834 -495
- package/dist/{chunk-HFR2WS6T.js → chunk-XFCJXRJ2.js} +18 -5
- package/dist/{claude-ink-WPWPEL5A.js → claude-ink-ORUA7GWG.js} +2 -2
- package/dist/cli.js +9 -8
- package/dist/config/protected-file.d.ts +6 -0
- package/dist/config/schema.d.ts +2 -0
- package/dist/context/manager.d.ts +2 -0
- package/dist/context/workspace-instructions.d.ts +10 -0
- package/dist/desktop/main.js +12736 -5178
- package/dist/desktop/pixel-worker.js +73 -0
- package/dist/desktop/preload.cjs +80 -2
- package/dist/desktop-renderer/assets/index-D-s27J39.js +151 -0
- package/dist/desktop-renderer/assets/index-DMZBSGrp.css +1 -0
- package/dist/desktop-renderer/index.html +3 -4
- package/dist/harness/local.d.ts +4 -1
- package/dist/jobs/registry.d.ts +48 -0
- package/dist/{load-XC5JYYBQ.js → load-6ZMEBHSG.js} +1 -1
- package/dist/models/anthropic.d.ts +4 -0
- package/dist/permissions/engine.d.ts +7 -0
- package/dist/production.d.ts +13 -1
- package/dist/sdk/index.js +4 -4
- package/dist/terminal/service.d.ts +57 -0
- package/dist/tools/files.d.ts +10 -0
- package/dist/tools/jobs.d.ts +4 -0
- package/dist/tools/runtime.d.ts +2 -0
- package/dist/tools/shell.d.ts +13 -3
- package/dist/tools/terminal.d.ts +3 -0
- package/dist/tools/types.d.ts +76 -4
- package/dist/tools/web.d.ts +53 -0
- package/package.json +13 -2
- package//346/212/200/346/234/257/346/226/271/346/241/210/346/212/245/345/221/212.md +752 -1
- package/dist/desktop-renderer/assets/index-CLrVaR9H.js +0 -143
- package/dist/desktop-renderer/assets/index-Cm_ktmXm.css +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# flavor-code 技术方案报告
|
|
2
2
|
|
|
3
|
-
> 版本:1.2.
|
|
3
|
+
> 版本:1.2.9 | 语言:TypeScript | 运行时:Node.js ≥20 | 包管理器:npm
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -109,6 +109,36 @@
|
|
|
109
109
|
- [35.5 上下文管理与会话持久化](#355-上下文管理与会话持久化)
|
|
110
110
|
- [35.6 安全边界与限制](#356-安全边界与限制)
|
|
111
111
|
- [35.7 文件地图速查](#357-文件地图速查)
|
|
112
|
+
- [36. D2C:设计稿到代码(Design to Code)](#36-d2c设计稿到代码design-to-code)
|
|
113
|
+
- [36.1 通俗理解:从设计稿到能跑的页面](#361-通俗理解从设计稿到能跑的页面)
|
|
114
|
+
- [36.2 产品流程:导入、生成、评测、审阅、联调](#362-产品流程导入生成评测审阅联调)
|
|
115
|
+
- [36.3 差异引擎与评分体系](#363-差异引擎与评分体系)
|
|
116
|
+
- [36.4 前端项目运行器与快照采集](#364-前端项目运行器与快照采集)
|
|
117
|
+
- [36.5 人工审阅与接口联调(1.2.3)](#365-人工审阅与接口联调123)
|
|
118
|
+
- [36.6 桌面端视图与权限边界](#366-桌面端视图与权限边界)
|
|
119
|
+
- [36.7 安全边界与限制](#367-安全边界与限制)
|
|
120
|
+
- [36.8 文件地图速查](#368-文件地图速查)
|
|
121
|
+
- [37. E2E:从粗需求到可验收成果物](#37-e2e从粗需求到可验收成果物)
|
|
122
|
+
- [37.1 通俗理解:从一个想法到一个能验收的产品](#371-通俗理解从一个想法到一个能验收的产品)
|
|
123
|
+
- [37.2 产品定位与模块边界](#372-产品定位与模块边界)
|
|
124
|
+
- [37.3 前置产品阶段:PRD 与交互原型](#373-前置产品阶段prd-与交互原型)
|
|
125
|
+
- [37.4 交互原型沙箱预览](#374-交互原型沙箱预览)
|
|
126
|
+
- [37.5 接口联调与真实后端](#375-接口联调与真实后端)
|
|
127
|
+
- [37.6 多模态自主交互审阅](#376-多模态自主交互审阅)
|
|
128
|
+
- [37.7 质量门与交付](#377-质量门与交付)
|
|
129
|
+
- [37.8 安全边界与限制](#378-安全边界与限制)
|
|
130
|
+
- [37.9 文件地图速查](#379-文件地图速查)
|
|
131
|
+
- [38. 1.2.9 运行时生产力与原生 Web 能力](#38-129-运行时生产力与原生-web-能力)
|
|
132
|
+
- [38.1 总体架构](#381-总体架构)
|
|
133
|
+
- [38.2 分层项目指令](#382-分层项目指令)
|
|
134
|
+
- [38.3 成果物汇总与文件版本保护](#383-成果物汇总与文件版本保护)
|
|
135
|
+
- [38.4 标准工具输出与 Presentation 协议](#384-标准工具输出与-presentation-协议)
|
|
136
|
+
- [38.5 Job 注册表与后台 Shell](#385-job-注册表与后台-shell)
|
|
137
|
+
- [38.6 持久 PTY](#386-持久-pty)
|
|
138
|
+
- [38.7 桌面状态与 D2C/E2E 进程生命周期](#387-桌面状态与-d2ce2e-进程生命周期)
|
|
139
|
+
- [38.8 原生 WebSearch 与 WebFetch](#388-原生-websearch-与-webfetch)
|
|
140
|
+
- [38.9 安全边界](#389-安全边界)
|
|
141
|
+
- [38.10 文件地图与验证](#3810-文件地图与验证)
|
|
112
142
|
|
|
113
143
|
---
|
|
114
144
|
|
|
@@ -206,6 +236,25 @@
|
|
|
206
236
|
- **命中率日志默认开启** — usage 日志默认写入 `.flavor/usage.jsonl`,不再依赖 `FLAVOR_DEBUG_USAGE`(该变量退化为仅控制 stderr 镜像);每条日志携带 `sessionId`,每个新 session(含清空上下文)覆盖上一次的文件,始终只反映当前会话
|
|
207
237
|
- 新增 2 个滚动断点测试与标记预算淘汰测试,既有 fork 边界与 tool 消息映射断言同步更新
|
|
208
238
|
|
|
239
|
+
**1.2.3 新增:**
|
|
240
|
+
|
|
241
|
+
- **D2C 设计稿到代码(Electron 专属)** — 导入 Pixso 导出的 HTML 设计稿,Agent 按 `d2c-pixso` 技能生成 Vue 3 / React 实现后,**实际运行**项目并对「设计稿渲染」与「实现页面」做像素级差异评估,输出结构化报告与视觉还原度评分,详见第 36 章
|
|
242
|
+
- **人工审阅与接口联调** — 首次视觉评测后停止自动修复进入人工审阅:差异逐条/批量通过或退回(退回项可附加要求触发模块级 AI 修复);全部通过后导入 Swagger 2.0 / OpenAPI 3.x,自动匹配模块与接口出入参,生成 Axios client、绑定计划和 Express mock server,并支持基于 `interaction-manifest.json` 的可交互联调验收
|
|
243
|
+
- **两个桌面端专属 Agent 工具** — `D2cImport`(校验并导入 Pixso 导出目录、写 manifest)、`D2cCompare`(支持项目目录 / localhost URL / HTML 文件三种来源,自动装依赖、起 Vite dev server、渲染快照、diff、评分并推送 `d2c-report` 桌面事件);CLI 场景下明确报"仅桌面端支持"
|
|
244
|
+
- **纯逻辑差异引擎 `src/d2c/`** — 颜色计算(CIE76 ΔE)、元素对齐、逐元素 diff、加权评分(layout 30% / color 20% / typography 15% / content 20% / pixel 15%)与报告装配,无 Electron 依赖;像素对比在 worker thread 中执行
|
|
245
|
+
- **D2C 工作流状态机** — 任务状态写入 `.flavor/d2c/<task>/workflow.json`:`visual-review → api-mapping → integrating → interaction-review → completed`,审阅决策可跨报告继承
|
|
246
|
+
- **桌面端 D2C 视图** — 创建态(任务名、框架选择、一键导入并开始)与结果工作台(三栏:任务/报告目录、证据画布、问题队列),叠加/拉帘/闪烁/热力图模式、SVG 标注层、差异标尺与活动流进度展示
|
|
247
|
+
- 新增 `docs/specs/2026-08-09-d2c-design-to-code.md` 与 `docs/specs/2026-08-10-d2c-review-and-integration.md` 规范文档及 `tests/d2c/`、`tests/desktop/d2c-*.test.ts` 全套测试
|
|
248
|
+
|
|
249
|
+
**1.2.3 新增(E2E 扩展):**
|
|
250
|
+
|
|
251
|
+
- **E2E 端到端交付(Electron 专属)** — 把 D2C 从"设计稿到代码"升级为"粗需求 → PRD → 交互设计 → D2C 视觉还原 → 接口联调 → 多模态自主验收 → 评分交付"的完整链路,产品一级模块命名为 E2E,D2C 只负责第 04 阶段视觉还原,详见第 37 章
|
|
252
|
+
- **双入口** — "从需求开始"(输入任务名与粗需求,自动识别技术栈,生成并审阅 PRD、可交互原型,确认后自动导入进入 D2C)与"已有设计稿"(保留 Pixso HTML 导入,从 D2C 视觉还原开始)兼容并行
|
|
253
|
+
- **多模态自主交互审阅** — "模型规划 + 确定性执行"双层结构:嵌入式执行器逐页恢复基准状态并采集页面截图/可操作 DOM,多模态模型规划完整用户旅程,执行器真实执行点击/输入/断言并采集 API 证据,模型不能直接宣布通过
|
|
254
|
+
- **Python FastAPI 真实后端** — 默认后端从 Express mock 升级为可运行的真实 Python FastAPI 服务(SQLite 持久化、`/_e2e/health` 健康检查、`/_e2e/reset` 场景重置),"从需求开始"的任务自动生成 `product/openapi.json` 契约并产出 `server/main.py`、`server/requirements.txt`
|
|
255
|
+
- **原型沙箱预览** — 只监听 `127.0.0.1` 的静态服务器 + 严格 CSP + sandbox iframe,确认设计基线前可安全地交互体验原型;拒绝路径穿越、切换工作区/退出时自动停止
|
|
256
|
+
- 新增 `docs/specs/2026-08-12-e2e-requirement-to-delivery.md` 规范文档及 `tests/d2c/product.test.ts`、`tests/d2c/interaction-review.test.ts`、`tests/desktop/e2e-shell.test.ts`、`tests/desktop/d2c-product-preview.test.ts` 等测试
|
|
257
|
+
|
|
209
258
|
### 2.2 非目标(明确排除)
|
|
210
259
|
|
|
211
260
|
- 全局用户画像、云端记忆同步和团队自动同步
|
|
@@ -4795,3 +4844,705 @@ block.type === "text"
|
|
|
4795
4844
|
| `src/context/manager.ts` | `cloneModelContent()`:上下文快照时深拷贝混合内容块 |
|
|
4796
4845
|
| `tests/session/assets.test.ts` | SessionAssetStore 单元测试 |
|
|
4797
4846
|
| `tests/ui/clipboard-image.test.ts` | 剪贴板图片读取单元测试 |
|
|
4847
|
+
|
|
4848
|
+
---
|
|
4849
|
+
|
|
4850
|
+
## 36. D2C:设计稿到代码(Design to Code)
|
|
4851
|
+
|
|
4852
|
+
### 36.1 通俗理解:从设计稿到能跑的页面
|
|
4853
|
+
|
|
4854
|
+
设计师在 Pixso 里画好页面后,导出的是一堆 HTML/CSS。过去要把这些设计稿变成可运行的 Vue/React 代码,全靠工程师手工对照还原,再靠人眼逐屏核对"像不像"。
|
|
4855
|
+
|
|
4856
|
+
1.2.3 在 **Electron 桌面端**提供了一条自动化闭环:
|
|
4857
|
+
|
|
4858
|
+
1. **导入**:在桌面端侧栏的 D2C 模块填写任务名、选择目标框架(Vue 3 / React),点击"导入 HTML 并开始 D2C",主进程弹出目录选择对话框,选中 Pixso 导出的 HTML 目录后校验并复制到 `.flavor/d2c/<task>/design/`
|
|
4859
|
+
2. **生成**:渲染端组装任务 prompt(含 task、入口 HTML、所选框架)投递给当前会话,Agent 依据用户自行导入的 D2C 技能(SOP)在 `src/d2c-output/<task>/` 生成可运行的 Vite 项目
|
|
4860
|
+
3. **评测**:Agent 调用 `D2cCompare`,系统**实际运行**实现项目(自动装依赖 + 起 Vite dev server),对"设计稿渲染"与"运行中的实现页面"做像素级差异评估,输出结构化报告(区域偏移量、色值偏差、字体差异)与视觉还原度相似度评分
|
|
4861
|
+
4. **审阅**:桌面端收到 `d2c-report` 事件自动切换到 D2C 视图,以叠加/拉帘/闪烁等模式对比两侧截图,问题列表按严重度排序,逐条通过或退回并触发模块级修复
|
|
4862
|
+
5. **联调**:全部差异通过后导入 Swagger 2.0 / OpenAPI 3.x 文档,自动匹配页面模块与接口出入参,生成 Axios client 与 Express mock server,基于 `interaction-manifest.json` 在 Electron 内嵌的实时页面上执行可交互验收
|
|
4863
|
+
|
|
4864
|
+
D2C 是端到端模块(非单纯对比工具),且对比逻辑与框架无关——Vue 与 React 项目共用同一条 Vite 运行路径。
|
|
4865
|
+
|
|
4866
|
+
### 36.2 产品流程:导入、生成、评测、审阅、联调
|
|
4867
|
+
|
|
4868
|
+
```text
|
|
4869
|
+
用户填写任务名 + 选择框架
|
|
4870
|
+
→ 点击"导入 HTML 并开始 D2C"(目录选择成功即派发实现任务,不再要求第二次点击)
|
|
4871
|
+
→ 任务执行期间停留在 D2C 模块,展示"已导入 → 生成中 → 完成后自动评测"进度
|
|
4872
|
+
→ Agent 生成实现并调用 D2cCompare { task, implementation }
|
|
4873
|
+
→ D2cCompare 完成两侧渲染快照、diff、评分,关闭自启的 dev server,
|
|
4874
|
+
写报告并推送 d2c-report 桌面事件
|
|
4875
|
+
→ 渲染端自动切换到 D2C 结果工作台(只有选中已有报告或新报告到达后才进入)
|
|
4876
|
+
→ 人工审阅:visual-review → api-mapping → integrating → interaction-review → completed
|
|
4877
|
+
```
|
|
4878
|
+
|
|
4879
|
+
`D2cCompare` 的 `implementation` 支持三种来源:
|
|
4880
|
+
|
|
4881
|
+
- **前端项目目录**(首选):识别 Vite 项目(package.json 含 vite 依赖),缺 `node_modules` 时自动 `npm install`,直接拉起 `node node_modules/vite/bin/vite.js` dev server
|
|
4882
|
+
- **已启动服务的 `http(s)://` localhost URL**:仅允许 `localhost` / `127.0.0.1` / `::1`
|
|
4883
|
+
- **本地 HTML 文件路径**:位于工作区内、以 `.html` 结尾
|
|
4884
|
+
|
|
4885
|
+
多页设计稿:导入时发现每个 HTML 文件,`index.html` 保持在首位,并在 manifest 中记录稳定的 page id、label 与相对路径;一次 `D2cCompare` 调用按对应 Vite HTML 条目(`index.html` 映射到 `/`,其余保留相对路径)评测所有页面,同批次报告共享 batch id、独立存储,渲染端按页加载 PNG 证据。
|
|
4886
|
+
|
|
4887
|
+
### 36.3 差异引擎与评分体系
|
|
4888
|
+
|
|
4889
|
+
`src/d2c/` 是纯逻辑差异引擎,无 Electron 依赖:
|
|
4890
|
+
|
|
4891
|
+
```text
|
|
4892
|
+
types.ts D2cElementSnapshot / D2cPageSnapshot / D2cReport / 阈值常量
|
|
4893
|
+
color.ts hex/rgb 解析、sRGB→Lab、CIE76 ΔE
|
|
4894
|
+
align.ts 元素对齐:文本签名精确匹配 → 剩余按标签/内容类型/IoU 综合匹配
|
|
4895
|
+
diff.ts 几何、颜色、字体、文本和图片类型差异
|
|
4896
|
+
score.ts 加权评分 + 等级
|
|
4897
|
+
report.ts 报告装配 + Agent 可读文本摘要(Top N 问题)
|
|
4898
|
+
pixel.ts 像素对比(PNG 解码 + pixelmatch),尺寸/像素上限校验
|
|
4899
|
+
pixel-worker.ts 在 worker thread 中执行同步解码与 pixelmatch,避免阻塞主线程
|
|
4900
|
+
```
|
|
4901
|
+
|
|
4902
|
+
**评分定义:**
|
|
4903
|
+
|
|
4904
|
+
- `S_layout = 1 − Σ(area_i·p_i)/Σ(area_i)`,`p_i = clamp(maxOffset/8, 0, 1)`,area 加权遍历匹配元素;缺失元素与裁剪到设计画布内的多余元素按面积占比以 p=1 计入
|
|
4905
|
+
- `S_color = 1 − 色差面积/总面积`(匹配元素中 ΔE>3 的 color/backgroundColor)
|
|
4906
|
+
- `S_typography` = 含文本匹配元素中 font-size/weight/family 全一致占比
|
|
4907
|
+
- `S_content` = 匹配元素中文本/图片语义一致占比,并计入缺失或多余的内容元素
|
|
4908
|
+
- `S_pixel = 1 − pixelmatch 不一致像素占比`(两张截图 pad 到同尺寸后比较)
|
|
4909
|
+
- 权重为 layout 30%、color 20%、typography 15%、content 20%、pixel 15%;pixel 不可用时其余权重归一化。总分四舍五入到 0.1;错误文本最高 94.9,设计侧图片缺失最高 89.9。等级:≥95 像素级还原、≥90 优秀、≥80 合格、<80 需修复
|
|
4910
|
+
|
|
4911
|
+
**Report v2 与验收语义:** 报告不是单一分数,而是"评测有效性 → 视觉还原度 → 修复优先级"三层结论:
|
|
4912
|
+
|
|
4913
|
+
- `validity.status`: `valid | warning | invalid`;检查两侧 viewport/DPR、字体、图片、页面裁剪和截图尺寸。关键条件不成立时不得给出正式通过结论,`invalid` 报告不显示 confidence 徽章与等级,主结果是"评测未完成"
|
|
4914
|
+
- `confidence`: `high | medium | low`,由 validity checks 计算并说明原因
|
|
4915
|
+
- `verdict`: `pass | conditional | fail | invalid`;错误文本、关键图片缺失等硬门槛会限制最高等级
|
|
4916
|
+
- 每个问题包含稳定 fingerprint、影响分、期望/实际矩形、内容差异、DOM selector 与局部证据坐标;旧 schema 1 报告可读取并在内存中升级
|
|
4917
|
+
|
|
4918
|
+
**性能与缓存:** 同一运行时内按 task、设计 hash 和 viewport 缓存最多三份设计稿快照,重复修复评测只重新采集实现;依赖缺失时 npm 离线优先并关闭 audit/fund 网络请求;首次实现和修复均批量处理高影响问题,默认最多执行三次比较(首次评测加两轮集中修复),达到 90 分或有效通过后立即结束。缓存不跨进程持久化。
|
|
4919
|
+
|
|
4920
|
+
### 36.4 前端项目运行器与快照采集
|
|
4921
|
+
|
|
4922
|
+
**前端项目运行器(`src/d2c/runner.ts`,仅被 D2cCompare 使用)**
|
|
4923
|
+
|
|
4924
|
+
`runFrontendProject(projectDir, options?): Promise<{ url, stop() }>`:
|
|
4925
|
+
|
|
4926
|
+
- 前置校验:目录经 `realpath` 后位于工作区内、含 `package.json`(依赖含 vite)、`node_modules/vite/bin/vite.js` 存在或可安装;不区分 Vue/React
|
|
4927
|
+
- `node_modules` 缺失时先执行 `npm install`(一次性子进程,超时 8 分钟);**不继承父进程 `npm_config_allow_scripts`**(npm 11 会把它当作项目级 CLI 策略,`true` 会导致 `EALLOWSCRIPTS`)
|
|
4928
|
+
- 显式 `spawn("node", [node_modules/vite/bin/vite.js, "--host", "127.0.0.1"])`,不使用 Electron 主进程的 `process.execPath`;就绪判定不依赖 Vite 打印 URL——先选可用 loopback 端口并以显式 strict port 启动,带单次请求超时地 fetch 探活直至返回非 5xx(整体超时默认 60 秒)
|
|
4929
|
+
- 依赖安装失败时在 `D2cCompare` 错误中包含 npm stdout/stderr 的有界尾部;子进程提前退出与超时报错也带 ANSI-free 输出尾部
|
|
4930
|
+
- `stop()`:SIGTERM → 3 秒宽限 → SIGKILL,终止完整进程树;`D2cCompare` 在 finally 中调用,工具 `AbortSignal` 传递到依赖安装、探活、页面采集和像素对比
|
|
4931
|
+
|
|
4932
|
+
**快照采集(注入式 `D2cCaptureService`)**
|
|
4933
|
+
|
|
4934
|
+
```ts
|
|
4935
|
+
interface D2cCaptureService {
|
|
4936
|
+
capture(source: D2cCaptureSource, viewport?: { width: number; height: number }):
|
|
4937
|
+
Promise<CapturedPage>; // { width, height, elements, screenshotPng, diagnostics }
|
|
4938
|
+
}
|
|
4939
|
+
```
|
|
4940
|
+
|
|
4941
|
+
桌面端实现(`src/desktop/d2c-capture.ts`):隐藏、无框、以内容区尺寸为准的 `BrowserWindow`(`nodeIntegration: false, contextIsolation: true, sandbox: true`),两段式采集——先按默认视口测量页面自然尺寸(上限 4096),再按目标视口(实现页强制用设计稿尺寸)注入采集脚本并 `capturePage()`。采集脚本只收录可见且有直接文本、图片或非透明背景/边框的元素(面积 ≥ 16px²),降低包装节点噪声;采集前等待 `document.fonts.ready`、可见图片 `decode()` 并注入禁用动画/过渡样式。URL 来源仅允许 `http(s)://127.0.0.1|localhost`;文件来源必须位于工作区内。
|
|
4942
|
+
|
|
4943
|
+
像素比较在 worker thread 中执行(`pixel-worker-client.ts` → `pixel-worker.ts`)。解码前后都校验尺寸,总像素上限 8,388,608,PNG 上限 32 MiB,避免压缩 PNG 解码膨胀;报告 IPC 同样拒绝超过上限的图片。采集器把最近模块边界(`data-d2c-module`)写入元素快照和报告,用于模块级修复。
|
|
4944
|
+
|
|
4945
|
+
### 36.5 人工审阅与接口联调(1.2.3)
|
|
4946
|
+
|
|
4947
|
+
**状态模型(`.flavor/d2c/<task>/workflow.json`)**
|
|
4948
|
+
|
|
4949
|
+
```text
|
|
4950
|
+
visual-review -> api-mapping -> integrating -> interaction-review -> completed
|
|
4951
|
+
^ | | |
|
|
4952
|
+
|--- repair ----| | auto + manual
|
|
4953
|
+
| failed / withdrawn
|
|
4954
|
+
```
|
|
4955
|
+
|
|
4956
|
+
- 每个问题由 `pageId + fingerprint` 标识,决策为 `pending | accepted | needs-fix`,采用原子替换和单任务写锁
|
|
4957
|
+
- 新报告到达时,同 fingerprint 且问题签名未变化的 accepted 决策可继承;已消失问题视为已解决;`invalid` 报告不能进入接口阶段
|
|
4958
|
+
- 没有差异或所有当前差异 accepted 后进入 `api-mapping`
|
|
4959
|
+
|
|
4960
|
+
**模块级修复:** 新生成项目必须包含 `d2c.modules.json`,每个模块声明稳定 id、标签和源码文件;组件根节点使用 `data-d2c-module`。修复提示词包含问题证据、用户要求、模块 id 和允许修改的源码文件;没有模块元数据时回退为页面级模块并明确列出输出项目目录。修复后仍执行整页视觉评测,以发现布局回归。
|
|
4961
|
+
|
|
4962
|
+
**OpenAPI 归一化与匹配(`src/d2c/openapi.ts`):**
|
|
4963
|
+
|
|
4964
|
+
- 接受 UTF-8 JSON,最大 8 MiB;支持 Swagger 2.0、OpenAPI 3.0/3.1 和文档内 JSON Pointer `$ref`;不执行 Swagger 中的任意脚本,不解析远程 `$ref`
|
|
4965
|
+
- 归一化 method、path、operationId、tags、参数、request body、2xx response 和示例
|
|
4966
|
+
- 根据模块 id/label/keywords/dataNeeds/actions 与 operationId/tags/summary/path 确定性打分;高置信且第一、第二候选有明显间隔时自动确认,其余标记 `needs-confirmation`,用户确认结果持久化
|
|
4967
|
+
|
|
4968
|
+
**生成物(`src/d2c-output/<task>/`,`src/d2c/integration.ts`):**
|
|
4969
|
+
|
|
4970
|
+
```text
|
|
4971
|
+
src/api/http.js # Axios instance 与统一错误模型
|
|
4972
|
+
src/api/d2c-api.js # operation 封装
|
|
4973
|
+
src/api/d2c-bindings.json # 模块/接口/字段绑定
|
|
4974
|
+
mock/server.mjs # Express mock server
|
|
4975
|
+
```
|
|
4976
|
+
|
|
4977
|
+
同时安全合并项目 `package.json` 的 `axios`、`express` 和 `mock` script;生成文件可重复执行且结果稳定。Mock 仅绑定 `127.0.0.1` 使用动态端口,启动前按需安装依赖并探测 `/_d2c/health`,重复启动返回现有实例、停止幂等,切换工作区或退出桌面应用时终止进程树。
|
|
4978
|
+
|
|
4979
|
+
**可交互联调验收(`src/d2c/interaction.ts` + `src/desktop/d2c-interaction-runner.ts`):**
|
|
4980
|
+
|
|
4981
|
+
Pixso 导出目录可携带 `interaction-manifest.json`(`deterministic: true`,场景由 click/fill/hover/key 动作与 visible/text/attribute/class/count 断言组成,每页最多 100 个场景、每场景最多 500 步)。Flavor Code 校验该文件,在实时实现上执行场景,检查可见结果并记录 XHR/fetch 请求。自动验收只统计发往当前任务 Express mock origin 的 XHR/fetch——页面完全没有真实 API 请求时,不能把静态交互误判为联调通过。只有自动交互检查通过且用户标记人工验收完成后,任务才进入 `completed`。
|
|
4982
|
+
|
|
4983
|
+
### 36.6 桌面端视图与权限边界
|
|
4984
|
+
|
|
4985
|
+
**渲染端视图:** `app.tsx` view 联合类型增加 `"d2c"`,侧栏入口命名 "D2C";收到 `d2c-report` 事件自动切换。`d2c-viewer.tsx` 包含:
|
|
4986
|
+
|
|
4987
|
+
- 创建态:任务名输入、框架选择(Vue 3 / React)、"导入 HTML 并开始 D2C";只有消息提交成功才进入 pending,会话 busy 时禁止再次派发
|
|
4988
|
+
- 结果工作台三栏结构:左侧任务/报告目录,中间证据画布,右侧问题队列;报告列表按页显示 validity、官方分数或"未完成"与问题数
|
|
4989
|
+
- 对比模式:叠加、拉帘、闪烁、设计、实现、热力图;拉帘可拖动,闪烁支持按住按钮或 `B` 键临时切换
|
|
4990
|
+
- 画布:25%–400% 缩放、适应窗口、100% 像素、滚轮/按钮缩放、拖拽平移,模式切换不丢失观察位置;点击问题自动缩放居中,设计框青色、实现框琥珀色,测量线表达 dx/dy/dw/dh
|
|
4991
|
+
- 差异标尺固定在画布右缘,按页面纵向位置显示问题密度和严重度;问题卡显示设计/实现局部裁剪、期望/实际数值、影响分与 selector,支持复制修复描述
|
|
4992
|
+
- 右侧面板在保留质量检查器视觉语言的基础上增加 `视觉审阅`、`接口联调` 两个 tab:审阅顶部显示待审/通过/退回计数与批量动作;接口 tab 在视觉审阅完成前锁定并说明原因
|
|
4993
|
+
- 性能:原图只保留一份 DOM 图像节点/模式,问题列表虚拟化或分批渲染,交互期间只更新 transform/clip-path CSS 变量,拖拽和滚轮使用 requestAnimationFrame,尊重 `prefers-reduced-motion`
|
|
4994
|
+
|
|
4995
|
+
**执行性能与实时可见性:** D2C 等待页不展示无法由真实事件支撑的百分比。执行页把当前任务与 `session-output` 关联,按模型思考、文件读取、代码写入、命令执行和 `D2cCompare` 工具调用形成最近活动流(最多 12 项);评测工具另行发送依赖准备、预览启动、设计稿快照、实现快照、像素对比和报告写入等内部阶段。执行页使用"分析设计 → 生成代码 → 视觉评测"的真实阶段导航,提供中断入口。
|
|
4996
|
+
|
|
4997
|
+
**Electron D2C authorization profile:** 只有新发起的 D2C 生成轮次由渲染端标记 `d2c` 权限 profile;主进程拥有该标记,在 `session.submit` 前激活、整轮保持(含子 Agent 与 steering 消息)、`finally` 中恢复。CLI、RPC、VS Code 与普通 Electron 会话永不激活。profile 激活期间工作区内读、写、移动、Shell、网络/MCP 调用和未知工具免审批运行;**显式删除仍需要审批**(`Delete`、`RemoveTool` 及可识别的 `rm`/`rmdir`/`del`/`Remove-Item`/`git rm`/`git clean`),移动不算删除。该 profile 不是无限制文件系统访问——工作区外绝对路径、符号链接逃逸、子 Agent 委托违规与系统级破坏性命令直接拒绝,`auto` 模式下删除请求绕过模型权限分类器,只能由用户批准。
|
|
4998
|
+
|
|
4999
|
+
**工具注入接缝:** `ProductionRuntimeOptions` 新增 `extraTools?: readonly ToolDefinition<unknown>[]`,并入 tools 数组;桌面端在 `main.ts` 构造 controller 时传入 `createD2cTools(workspace, { capture })`。
|
|
5000
|
+
|
|
5001
|
+
**桌面端 IPC:** channels 为 `desktop:d2c-import`、`desktop:d2c-list-reports`、`desktop:d2c-get-report`;`FlavorDesktopApi` 增加 `importD2cDesign(task)` / `listD2cReports()` / `getD2cReport(task, reportId?)`;`DesktopEvent` 增加 `{ type: "d2c-report", payload: { task, reportId, total, grade } }`。`d2cImport` 由主进程 handler 打开目录对话框并复用 `importDesign`;报告图片经主进程读取后以 data URL 返回,渲染进程不直接访问文件路径。
|
|
5002
|
+
|
|
5003
|
+
### 36.7 安全边界与限制
|
|
5004
|
+
|
|
5005
|
+
| 层面 | 措施 |
|
|
5006
|
+
|------|------|
|
|
5007
|
+
| **输入校验** | 工具输入经 zod 校验;task 名限 `^[a-z0-9][a-z0-9-]{0,63}$`,reportId 限 `run-YYYYMMDD-HHMMSS[-N]`;viewport 宽高必须同时提供且像素数 ≤ 8,388,608 |
|
|
5008
|
+
| **路径约束** | 实现来源路径 `realpath` 后校验位于工作区内,符号链接逃逸拒绝;导入源与目标设计目录不得重叠 |
|
|
5009
|
+
| **隐藏窗口** | 禁用 nodeIntegration;导航和重定向只允许初始本地文件或 localhost 来源;`setWindowOpenHandler` 拒绝弹窗、阻止下载 |
|
|
5010
|
+
| **运行器** | 只执行两条固定命令(工作区内 `npm install` 与 `node node_modules/vite/bin/vite.js`),不接受任意命令拼接;对比结束(含异常路径)必须关闭自启服务器 |
|
|
5011
|
+
| **报告与图片** | 报告 data URL 只包含经过 PNG 签名、尺寸与像素上限校验的内容;report.json 上限 2 MiB;采集脚本为静态字符串常量,不接受用户输入拼接 |
|
|
5012
|
+
| **原子写入** | 设计导入和报告写入使用同父目录临时目录 + rename 发布;manifest 保存设计内容 hash,报告保存对应 hash,重导入后旧报告可识别 |
|
|
5013
|
+
| **联调安全** | 预览与测试导航只能停留在生成项目的 loopback origin;内嵌页面使用 iframe,不能访问 Electron preload bridge;禁止弹窗、webview、远程 frame origin 和非 loopback 预览 URL;切换工作区或退出应用时同时终止预览与 mock 进程树 |
|
|
5014
|
+
|
|
5015
|
+
当前不支持:Pixso API 直连与设计稿图层语义解析(只消费导出的 HTML);动画、交互态、多视口/响应式断点对比;CLI 终端下的渲染对比(无 Chromium 宿主);差异驱动的自动修复循环 UI(Agent 凭报告文本自行迭代,不做专门编排)。
|
|
5016
|
+
|
|
5017
|
+
### 36.8 文件地图速查
|
|
5018
|
+
|
|
5019
|
+
| 路径 | 职责 |
|
|
5020
|
+
|------|------|
|
|
5021
|
+
| `src/d2c/types.ts` | D2cElementSnapshot / D2cPageSnapshot / D2cReport / 阈值常量(geometryTolerancePx=2、fullPenaltyPx=8、colorDeltaE=3、iouMin=0.3) |
|
|
5022
|
+
| `src/d2c/color.ts` | hex/rgb 解析、sRGB→Lab、CIE76 ΔE |
|
|
5023
|
+
| `src/d2c/align.ts` | 元素对齐:文本签名精确匹配 → 剩余按标签/内容类型/IoU 综合匹配 |
|
|
5024
|
+
| `src/d2c/diff.ts` | 几何、颜色、字体、文本和图片类型差异计算 |
|
|
5025
|
+
| `src/d2c/score.ts` | 加权评分(layout 30% / color 20% / typography 15% / content 20% / pixel 15%)与等级 |
|
|
5026
|
+
| `src/d2c/report.ts` | 报告装配(Report v2)+ Agent 可读文本摘要(Top N 问题) |
|
|
5027
|
+
| `src/d2c/pixel.ts` | PNG 签名/尺寸校验、像素上限、pixelmatch 像素对比 |
|
|
5028
|
+
| `src/d2c/pixel-worker.ts` / `pixel-worker-client.ts` | 在 worker thread 执行同步 PNG 解码与 pixelmatch |
|
|
5029
|
+
| `src/d2c/store.ts` | `.flavor/d2c` 目录读写:manifest、设计导入、报告列举/加载/落盘 |
|
|
5030
|
+
| `src/d2c/runner.ts` | 前端项目运行器:装依赖 / 起 vite dev server / 探活 / 关闭进程树 |
|
|
5031
|
+
| `src/d2c/tools.ts` | `createD2cTools(workspace, { capture? })`:D2cImport / D2cCompare 工具 |
|
|
5032
|
+
| `src/d2c/skill-template.ts` | D2C 工作流参考模板(Vue/React 两套项目 SOP),仅供测试校验,系统不写入工作区 |
|
|
5033
|
+
| `src/d2c/workflow.ts` / `workflow-shared.ts` | 工作流状态机(visual-review → … → completed)、审阅决策继承、修复 prompt 组装 |
|
|
5034
|
+
| `src/d2c/openapi.ts` | Swagger 2.0 / OpenAPI 3.x 归一化、模块↔接口确定性匹配 |
|
|
5035
|
+
| `src/d2c/integration.ts` | Axios client / API 封装 / 绑定计划 / Express mock server 代码生成 |
|
|
5036
|
+
| `src/d2c/mock-runner.ts` | Express mock 生命周期:动态端口、健康探测、重复启动复用、幂等停止 |
|
|
5037
|
+
| `src/d2c/interaction.ts` | `interaction-manifest.json` 校验与场景执行(click/fill/hover/key + 断言)、API 请求统计 |
|
|
5038
|
+
| `src/d2c/modules.ts` | `d2c.modules.json` 模块契约校验与源码文件安全约束 |
|
|
5039
|
+
| `src/desktop/d2c-capture.ts` | Electron 隐藏窗口两段式快照采集(尺寸测量 + 注入采集脚本 + capturePage) |
|
|
5040
|
+
| `src/desktop/d2c-interaction-runner.ts` | 桌面端交互场景驱动:内嵌实时页面执行 + 诊断收集 |
|
|
5041
|
+
| `src/desktop/contracts.ts` / `preload.ts` | D2C 三个 IPC channel 的 Zod 契约与 preload API |
|
|
5042
|
+
| `src/desktop/renderer/d2c-viewer.tsx` | D2C 视图:创建态 + 三栏结果工作台 + 视觉审阅/接口联调 tab |
|
|
5043
|
+
| `src/desktop/renderer/d2c-canvas.ts` | 证据画布:对比模式、缩放/平移、SVG 标注层、差异标尺 |
|
|
5044
|
+
| `src/desktop/renderer/d2c-progress.ts` | 执行活动流与阶段导航的进度组件 |
|
|
5045
|
+
| `tests/d2c/*.test.ts` | 引擎(color/align/diff/score/report/pixel)、store、runner、tools、workflow、openapi、integration、interaction、mock-runner、modules 与 fixture-suite 测试 |
|
|
5046
|
+
| `tests/desktop/d2c-capture.test.ts` 等 | 桌面端 capture / viewer / canvas / progress / workflow-controller 测试 |
|
|
5047
|
+
|
|
5048
|
+
---
|
|
5049
|
+
|
|
5050
|
+
## 37. E2E:从粗需求到可验收成果物
|
|
5051
|
+
|
|
5052
|
+
### 37.1 通俗理解:从一个想法到一个能验收的产品
|
|
5053
|
+
|
|
5054
|
+
把 D2C 想象成"照着一张贴好的设计图把页面写出来"。它很擅长,但它默认设计图已经存在、产品想做什么已经想清楚了。真实世界往往不是这样——你只有一个模糊的想法,连页面长什么样、要哪些接口都还没定。
|
|
5055
|
+
|
|
5056
|
+
**E2E(End-to-End,端到端交付)就是把"从想法到可验收产品"的全过程自动化**:你输入一段粗需求(比如"做一个带筛选和分页的订单管理后台"),Flavor Code 依次帮你产出 PRD、可点击的交互原型、还原设计稿的代码、能跑的真实后端,最后让多模态模型像测试工程师一样把产品从头到尾点一遍,给出评分和交付结论。
|
|
5057
|
+
|
|
5058
|
+
```text
|
|
5059
|
+
E2E
|
|
5060
|
+
├─ 01 粗需求输入 ← 你只说想做什么
|
|
5061
|
+
├─ 02 PRD 产品定义 ← 生成产品需求文档,等你看
|
|
5062
|
+
├─ 03 视觉与交互确认 ← 生成可点击原型,等你看
|
|
5063
|
+
├─ 04 D2C 视觉还原 ← 设计稿变可运行代码(第 36 章)
|
|
5064
|
+
├─ 05 Swagger / OpenAPI 联调
|
|
5065
|
+
├─ 06 多模态自主验收 ← 模型规划 + 确定性执行
|
|
5066
|
+
└─ 07 评分与成果物交付 ← 通过质量门才算完成
|
|
5067
|
+
```
|
|
5068
|
+
|
|
5069
|
+
关键思想是**显式阶段门**:PRD 没确认,不许画原型;原型没确认,不许写代码。每一步都有"确认/退回"的闸门,避免未经确认的产品假设一路污染到实现——这比一次性的黑盒生成更符合真实团队的工作方式,也更容易人工介入纠偏。
|
|
5070
|
+
|
|
5071
|
+
### 37.2 产品定位与模块边界
|
|
5072
|
+
|
|
5073
|
+
| 概念 | 范围 |
|
|
5074
|
+
|------|------|
|
|
5075
|
+
| **E2E** | 完整交付链路(七段轨道),Electron 侧栏一级模块,工作台标题、创建任务、阶段导航均使用 E2E |
|
|
5076
|
+
| **D2C** | 只负责第 04 段"设计稿 → 视觉还原代码",是 E2E 的一个子阶段 |
|
|
5077
|
+
|
|
5078
|
+
- 面向用户的入口是 `E2eViewer`(`src/desktop/renderer/e2e-viewer.tsx`),当前复用成熟的 `d2c-viewer.tsx` 实现并显式导出,让桌面信息架构可以独立演进
|
|
5079
|
+
- 为避免迁移破坏,内部 `D2c*` 类型、`d2c-*` IPC 事件、`.flavor/d2c/<task>` 目录与 `D2cViewer` 兼容导出**暂不重命名**;旧任务无需迁移即可在 E2E 工作台打开
|
|
5080
|
+
- 新状态与 prompt 逻辑位于 `src/d2c/product.ts`,**无 Electron 依赖**;不向 CLI 注册 E2E 命令,不改变现有 CLI 命令或输出
|
|
5081
|
+
|
|
5082
|
+
**两个创建入口:**
|
|
5083
|
+
|
|
5084
|
+
1. **从需求开始**:只输入任务名与粗需求,不要求用户选择技术栈。默认前端 Vue 3、服务端 Python;若需求原文明确写了 React、Next.js、Java、FastAPI 等,则自动识别并覆盖对应默认值。随后依次生成 PRD → 审阅/退回 → 生成交互原型 → 审阅/退回 → 自动导入并进入 D2C 视觉还原。
|
|
5085
|
+
2. **已有设计稿**:保留 Pixso HTML 导入能力,明确提示"从 D2C 视觉还原开始",允许跳过前 3 段。
|
|
5086
|
+
|
|
5087
|
+
技术栈识别结果写入 `product-plan.json`,区分"默认值"与"需求明示"来源(`frontendSource`/`backendSource`);旧计划没有该字段时按原 `framework` 推导前端、按 Python 推导服务端。D2C 兼容的 `framework` 字段仍只使用 `vue | react`,不改变既有 IPC 与 CLI schema。
|
|
5088
|
+
|
|
5089
|
+
### 37.3 前置产品阶段:PRD 与交互原型
|
|
5090
|
+
|
|
5091
|
+
**状态模型(`.flavor/d2c/<task>/product-plan.json`,schema 1):**
|
|
5092
|
+
|
|
5093
|
+
```text
|
|
5094
|
+
prd-generating → prd-review → design-generating → design-review → ready-for-d2c
|
|
5095
|
+
↑ ↑
|
|
5096
|
+
退回修改 退回修改
|
|
5097
|
+
```
|
|
5098
|
+
|
|
5099
|
+
- `prd-generating`:创建任务后,渲染端用 `buildD2cPrdPrompt` 组装 prompt 投递给会话,Agent 只允许写 `product/prd.md`
|
|
5100
|
+
- `prd-review`:PRD 生成后(按文件 hash 变化自动发现),工作台展示 Markdown,用户**确认 PRD,生成交互稿**或**退回修改**(退回必填意见,反馈注入下一轮 prompt)
|
|
5101
|
+
- `design-generating`:用 `buildD2cDesignPrompt` 让 Agent 生成 `product/prototype/index.html`、本地 assets、`interaction-manifest.json` 和 `product/openapi.json`
|
|
5102
|
+
- `design-review`:原型与交互清单齐全且清单通过严格校验后进入;用户可在沙箱预览中直接体验原型,确认后 `importDesign` 自动导入设计基线进入 D2C
|
|
5103
|
+
- `ready-for-d2c`:设计已确认,等待/继续 D2C 视觉还原
|
|
5104
|
+
|
|
5105
|
+
**工件结构(沿用既有任务根目录):**
|
|
5106
|
+
|
|
5107
|
+
```text
|
|
5108
|
+
.flavor/d2c/<task>/
|
|
5109
|
+
product-plan.json
|
|
5110
|
+
product/
|
|
5111
|
+
prd.md
|
|
5112
|
+
prototype/
|
|
5113
|
+
index.html
|
|
5114
|
+
interaction-manifest.json
|
|
5115
|
+
assets/*
|
|
5116
|
+
openapi.json
|
|
5117
|
+
```
|
|
5118
|
+
|
|
5119
|
+
**PRD 要求:** 目标用户、问题、范围/非范围、用户故事、页面/状态、交互规则、数据/API 假设、可逐条验证的验收标准、风险和未决问题;明确区分事实、合理假设与待确认项,不得伪造指标或接口。
|
|
5120
|
+
|
|
5121
|
+
**交互清单(`interaction-manifest.json`)是后续自动验收的行为契约:**
|
|
5122
|
+
|
|
5123
|
+
- 必须以**完整用户旅程**组织,而不是控件抽样:列表页覆盖"输入条件 → 查询 → 断言 → 重置 → 恢复断言 → 翻页";导航覆盖实际点击入口与二/三级菜单;表单覆盖必填校验、完整输入、提交、成功/失败反馈与关闭恢复
|
|
5124
|
+
- 每个点击/输入/选择/按键动作后必须有可观察的状态、URL、数据或 API 后置条件;只 hover、只输入不提交不算完整验收
|
|
5125
|
+
- 原生支持 `open`(路由切换)、`blur`(失焦校验)、`hidden`(不可见断言)、`not-exists`(DOM 移除断言)等步骤,Electron 执行器必须真实执行,不能在导入时静默删除或弱化
|
|
5126
|
+
|
|
5127
|
+
**契约归一化:** 模型常见但语义明确的清单写法在严格校验前归一化——API 路径数组转 `requireApi` 布尔值、`{ action: "expect", type }` 转 `{ expect }`、误写在 `action` 中的断言转 `{ expect }`、`attribute` 转 `name`、hash URL 补全当前页面入口;无法安全推导的字段仍必须拒绝。清单校验通过后才能进入设计评审并展示确认按钮,用户确认设计时把归一化后的清单重新落盘,保证后续导入、可视回放与自主验收读取同一份可执行契约。
|
|
5128
|
+
|
|
5129
|
+
**Windows 持久化细节:** 同一 `product-plan.json` 的进程内写入串行、临时文件名唯一;Windows 拒绝 `rename-over-existing`(`EPERM`/`EACCES`/`EBUSY`/`EEXIST`)时回退为覆盖复制并清理临时文件。原型只有 `index.html`、尚无交互清单时属于半成品,轮询不得递增 revision 或反复写 plan。E2E/D2C 权限配置下的 PRD、原型和实现生成是内部产物任务,不参与通用长期记忆自动提取;生成完成后不得因 `Stop` 收尾钩子超时而误报失败。
|
|
5130
|
+
|
|
5131
|
+
### 37.4 交互原型沙箱预览
|
|
5132
|
+
|
|
5133
|
+
`src/desktop/d2c-product-preview.ts` 提供设计评审阶段的原型预览:
|
|
5134
|
+
|
|
5135
|
+
- 只监听 `127.0.0.1` 的**临时端口**静态服务器;root 限制在推导出的 prototype 目录,`realpath` 后校验仍在根内,拒绝路径穿越与 `\0` 注入
|
|
5136
|
+
- 响应带 `cache-control: no-store`、`nosniff` 与严格 CSP(`script-src 'self' 'unsafe-inline'`、`connect-src 'none'`、`object-src 'none'`、`base-uri 'none'`、`form-action 'none'`)
|
|
5137
|
+
- 渲染端用 **sandbox iframe** 内嵌预览(仅加 `allow-same-origin` 使登录态 `sessionStorage` 可用),与 Electron 父页面 origin 隔离;切换工作区或退出应用时停止服务
|
|
5138
|
+
- 预览保持设计契约使用的 `1280 × 800` 桌面视口再按工作台可用区域等比缩放,禁止窄栏触发被测应用的移动端断点
|
|
5139
|
+
|
|
5140
|
+
### 37.5 接口联调与真实后端
|
|
5141
|
+
|
|
5142
|
+
"从需求开始"的接口契约属于 E2E 自身成果物:
|
|
5143
|
+
|
|
5144
|
+
- 设计阶段优先生成 `product/openapi.json`;旧任务没有该文件时,Electron 根据已确认 PRD 来源和 `d2c.modules.json` **自动生成 OpenAPI 3.1 契约并完成确定性映射**,不弹出文件选择器(`buildD2cProductOpenApi` 为每个模块生成 GET/POST 端点)
|
|
5145
|
+
- Swagger/OpenAPI 手动上传仅作为"已有设计稿"或覆盖默认契约的入口
|
|
5146
|
+
- 默认 Python 方案在联调生成阶段同时产出 `server/main.py`、`server/requirements.txt` 与运行说明
|
|
5147
|
+
- 生成的真实后端是 **FastAPI + SQLAlchemy**:默认 SQLite(`DATABASE_URL` 可迁移 MySQL/PostgreSQL),提供 `/_e2e/health` 健康检查与 `/_e2e/reset` 场景重置接口(`FLAVOR_E2E_ALLOW_RESET=1` 且 `X-Flavor-E2E: reset` 头才生效,用于每个自动化场景前恢复基准状态)
|
|
5148
|
+
- 联调服务只绑定 `127.0.0.1` 动态端口,`mock-runner.ts` 负责依赖安装、健康探测、重复启动复用与幂等停止;自动验收只统计发往当前任务 mock origin 的 XHR/fetch,页面完全没有真实 API 请求时不能把静态交互误判为联调通过
|
|
5149
|
+
|
|
5150
|
+
### 37.6 多模态自主交互审阅
|
|
5151
|
+
|
|
5152
|
+
自动验收采用"**模型规划 + 确定性执行**"的双层结构(`src/d2c/interaction-review.ts` + `src/desktop/d2c-embedded-runner.ts`):
|
|
5153
|
+
|
|
5154
|
+
1. **嵌入式执行器采集**:逐页恢复基准状态,采集页面截图、标题/正文、标题层级及带稳定 selector 的可操作 DOM,同时保留 PRD、已确认 interaction manifest 与 API 映射作为上下文
|
|
5155
|
+
- 受保护业务路由直达登录页属于合法鉴权跳转:执行器用本次导航唯一标记确认 iframe 已加载,不要求重定向后 URL 与请求 URL 完全相等
|
|
5156
|
+
- 若采集目标因未登录落到登录页,执行器必须从已确认交互契约中选择包含目标路由证据的安全导航前缀,仅执行登录与菜单导航抵达目标页,禁止用登录页截图冒充业务页面
|
|
5157
|
+
2. **多模态模型规划**:先判断页面真实类型(表单/大屏/详情/向导/编辑器/混合,不预设分页列表)、用户目标、深层路径和风险,再生成完整用户旅程;计划只能使用已观察页面,必须包含 action、可观察后置断言和业务语义
|
|
5158
|
+
3. **严格校验**:计划经过 schema、路径(不得逃逸观察页面集、不得遗漏已观察页面)、数量(≤100 旅程)、唯一性(无重复 scenario id)与完整性(每个旅程至少一个 action 且末步为 expect)校验;selector 用 `#id`/`[attr=value]` 稳定定位符与观察 DOM 交叉验证
|
|
5159
|
+
4. **契约合并**:模型计划与已确认设计契约合并(`mergeInteractionManifests`),不能删除原有场景;执行器负责真实点击、输入、选择、导航、断言与 API 证据采集,**多模态模型不能直接宣布通过**
|
|
5160
|
+
- 点击目标未出现在当前列表页时,执行器可识别通用上一页/下一页控件并有限遍历分页;只允许无副作用的分页导航,不能猜测或强制触发业务提交
|
|
5161
|
+
5. **降级策略**:未配置多模态模型时继续执行原有确定性契约(旧 D2C/CLI 行为不变);观察或规划失败时明确标记"自主规划失败"、保存诊断文件,继续可视化执行已确认的确定性契约,**不得把降级结果伪装成自主审阅成功**;瞬时网络失败或 408/429/5xx 允许一次有限重试且不泄露密钥
|
|
5162
|
+
6. **证据落盘**:自主计划与执行结果分别落盘(`evidenceMode: contract | autonomous | contract-fallback`),便于 CR、复盘与重现
|
|
5163
|
+
|
|
5164
|
+
### 37.7 质量门与交付
|
|
5165
|
+
|
|
5166
|
+
- **多模态质量评测**(`src/d2c/judge.ts` + `src/desktop/d2c-judge-client.ts`):对实现页面输出 `visualScore`(视觉)与 `interactionScore`(交互)双维度评分,可配置模型协议/地址/密钥/通过阈值
|
|
5167
|
+
- **视觉采集等待**:必须等待可见的 `aria-busy`、骨架屏与 loading 状态结束后才允许评分;页面在就绪时限内未稳定时标记评测未完成并输出"页面未就绪"诊断,不允许拿两个相同骨架屏得出高分
|
|
5168
|
+
- **交付门槛**:最终交付状态必须**同时满足**自动验收通过(`interaction.automated.passed === true`)、人工确认(`manualDecision === accepted`)与质量门通过(`quality.verdict === pass`)——AI 质量评测可以对未确认版本做诊断评分,但诊断评分不得绕过交付门槛
|
|
5169
|
+
- 工作台持续展示七段 E2E 交付轨道,D2C 阶段使用独立强调色;报告态阶段导航将视觉审阅标为"04 D2C 视觉还原",接口联调、自主验收与交付归为后续 E2E 阶段
|
|
5170
|
+
|
|
5171
|
+
### 37.8 安全边界与限制
|
|
5172
|
+
|
|
5173
|
+
| 层面 | 措施 |
|
|
5174
|
+
|------|------|
|
|
5175
|
+
| **原型预览** | 只监听 127.0.0.1 临时端口;root 限制 prototype 目录;`realpath` 防符号链接逃逸;严格 CSP + sandbox iframe;`connect-src 'none'` 禁止原型联网 |
|
|
5176
|
+
| **IPC 白名单** | 新增通道(创建产品/读取/决策/预览启停)均在 `channels.ts` 显式白名单,输入经 Zod 校验;所有路径由 task 推导,渲染端不能传任意文件路径或 URL |
|
|
5177
|
+
| **重置接口** | `/_e2e/reset` 仅在 `FLAVOR_E2E_ALLOW_RESET=1` 且带 `X-Flavor-E2E: reset` 头时生效,且只恢复生成的开发数据库 |
|
|
5178
|
+
| **权限配置** | E2E/D2C 权限 profile 激活期间工作区操作免审批,但显式删除仍要求审批;工作区外绝对路径、符号链接逃逸、系统级破坏性命令直接拒绝;PRD/原型/实现生成不参与长期记忆自动提取 |
|
|
5179
|
+
| **真实后端** | 联调服务只绑定 loopback 动态端口;内嵌页面 iframe 不能访问 preload bridge;切换工作区或退出时终止预览与后端进程树 |
|
|
5180
|
+
|
|
5181
|
+
当前不支持:Pixso/Figma API 直连(未来以 `DesignArtifactProvider` 适配器接入,当前以本地交互 HTML 为确定性内置 provider);动画、多视口/响应式断点对比;CLI 终端下的 E2E 流程(Electron 专属)。
|
|
5182
|
+
|
|
5183
|
+
### 37.9 文件地图速查
|
|
5184
|
+
|
|
5185
|
+
| 路径 | 职责 |
|
|
5186
|
+
|------|------|
|
|
5187
|
+
| `src/d2c/product.ts` | E2E 前置阶段:product-plan schema 1、技术栈识别、工件发现/归一化、PRD/设计两阶段 prompt、OpenAPI 自动生成、Windows 持久化兼容 |
|
|
5188
|
+
| `src/d2c/interaction.ts` | `interaction-manifest.json` schema 与校验(open/click/fill/select/hover/blur/key/wait/wait-for + visible/hidden/not-exists/text/…/url/request 断言)、API 请求统计 |
|
|
5189
|
+
| `src/d2c/interaction-review.ts` | 多模态自主审阅:页面观察模型、计划 schema 与严格校验、selector 存在性验证、契约合并、规划 prompt |
|
|
5190
|
+
| `src/desktop/d2c-product-preview.ts` | 原型沙箱预览静态服务器(loopback + CSP + 路径穿越防护) |
|
|
5191
|
+
| `src/desktop/d2c-embedded-runner.ts` | 嵌入式验收执行器:基准状态恢复、iframe 驱动、真实点击/输入/断言、API 证据采集、`/_e2e/reset` 场景重置 |
|
|
5192
|
+
| `src/d2c/judge.ts` / `src/desktop/d2c-judge-client.ts` | 多模态质量门:视觉/交互双维评分、verdict、诊断降级 |
|
|
5193
|
+
| `src/d2c/integration.ts` | Python FastAPI 服务端代码生成(`/_e2e/health`、`/_e2e/reset`)与 Axios client 生成 |
|
|
5194
|
+
| `src/d2c/mock-runner.ts` | 联调后端生命周期:动态端口、依赖安装、健康探测、重复启动复用、幂等停止 |
|
|
5195
|
+
| `src/desktop/runtime-controller.ts` | `createD2cProduct` / `decideD2cProduct` / `startD2cProductPreview` 等控制器与 OpenAPI 自动准备 |
|
|
5196
|
+
| `src/desktop/channels.ts` / `contracts.ts` / `preload.ts` | E2E 新增 IPC 通道白名单、Zod 契约与 preload API |
|
|
5197
|
+
| `src/desktop/renderer/e2e-viewer.tsx` | Electron 产品入口,复用 `d2c-viewer.tsx` 并导出 `E2eViewer` |
|
|
5198
|
+
| `src/desktop/renderer/d2c-viewer.tsx` | E2E 工作台:七段轨道、双入口、PRD/设计审阅、原型预览 iframe、D2C 子模块 |
|
|
5199
|
+
| `tests/d2c/product.test.ts` | product-plan 状态机、技术栈识别、工件发现、退回反馈、两阶段 prompt 纯逻辑测试 |
|
|
5200
|
+
| `tests/d2c/interaction-review.test.ts` | 自主计划校验(逃逸/遗漏/重复/不完整)、契约合并 |
|
|
5201
|
+
| `tests/desktop/e2e-shell.test.ts` | E2E 一级入口、七段流程、D2C 子模块标识、双入口、sandbox iframe 与确认门 |
|
|
5202
|
+
| `tests/desktop/d2c-product-preview.test.ts` | 原型预览服务器:loopback、HTML/资源响应、CSP、路径穿越 |
|
|
5203
|
+
|
|
5204
|
+
---
|
|
5205
|
+
|
|
5206
|
+
## 38. 1.2.9 运行时生产力与原生 Web 能力
|
|
5207
|
+
|
|
5208
|
+
1.2.9 把原先分散在文件工具、Shell、D2C runner 和 UI 中的“上下文发现、长进程管理、结果展示”收拢为公共运行时能力,并加入无需 MCP 的原生 `WebSearch` / `WebFetch`。这些能力同时服务主 Agent、子 Agent、CLI 和 Electron;VS Code 继续通过同一个生产运行时获得能力。
|
|
5209
|
+
|
|
5210
|
+
### 38.1 总体架构
|
|
5211
|
+
|
|
5212
|
+
```mermaid
|
|
5213
|
+
flowchart LR
|
|
5214
|
+
M["模型工具调用"] --> R["ToolRuntime\n校验·权限·Hook·输出协议"]
|
|
5215
|
+
R --> F["文件工具\n观察版本·原子替换"]
|
|
5216
|
+
R --> J["JobRegistry\n后台 Shell·任务控制"]
|
|
5217
|
+
R --> P["TerminalService\n持久 PTY"]
|
|
5218
|
+
R --> W["WebSearch / WebFetch\n联网与 SSRF 防护"]
|
|
5219
|
+
F --> E["AgentEvent"]
|
|
5220
|
+
J --> E
|
|
5221
|
+
P --> E
|
|
5222
|
+
W --> E
|
|
5223
|
+
E --> C["模型上下文"]
|
|
5224
|
+
E --> U["CLI / Electron Presentation"]
|
|
5225
|
+
J --> D["桌面 Job 状态条"]
|
|
5226
|
+
I["WorkspaceInstructions"] --> C
|
|
5227
|
+
MP["ManagedProcess"] --> D2C["D2C 预览 / E2E 后端"]
|
|
5228
|
+
```
|
|
5229
|
+
|
|
5230
|
+
设计原则:
|
|
5231
|
+
|
|
5232
|
+
1. **工具结果只有一个事实源**:`output` 保存结构化真值,模型文本与 UI 展示都由它派生。
|
|
5233
|
+
2. **长进程必须有所有者**:主 Agent 与各子 Agent 只能读取、等待或终止自己的 Job/终端。
|
|
5234
|
+
3. **自动能力不增加用户负担**:项目规则、成果物汇总、版本冲突检测和 D2C 生命周期不需要新命令。
|
|
5235
|
+
4. **网络能力仍经过权限系统**:原生不等于绕过审批,`WebSearch` / `WebFetch` 仍属于 `network` 类别。
|
|
5236
|
+
|
|
5237
|
+
### 38.2 分层项目指令
|
|
5238
|
+
|
|
5239
|
+
#### 解决的问题
|
|
5240
|
+
|
|
5241
|
+
大型仓库通常不是一份根目录说明就能覆盖全部约定。例如根目录要求“所有代码必须测试”,`src/payments/AGENTS.md` 还可能要求“金额必须用整数分保存”。如果只在启动时读取根规则,Agent 进入子目录后容易遗漏局部约定。
|
|
5242
|
+
|
|
5243
|
+
`WorkspaceInstructions` 会读取以下文件:
|
|
5244
|
+
|
|
5245
|
+
```text
|
|
5246
|
+
<workspace>/AGENTS.md
|
|
5247
|
+
<workspace>/CLAUDE.md
|
|
5248
|
+
<workspace>/AGENTS.local.md
|
|
5249
|
+
<workspace>/CLAUDE.local.md
|
|
5250
|
+
<workspace>/src/AGENTS.md
|
|
5251
|
+
<workspace>/src/payments/AGENTS.local.md
|
|
5252
|
+
...
|
|
5253
|
+
```
|
|
5254
|
+
|
|
5255
|
+
- 根目录文件在首次模型调用前进入稳定系统提示词,可参与 Prompt Cache。
|
|
5256
|
+
- 成功执行带路径的工具后,从工作区根目录走到目标文件所在目录,按“根 → 子目录”顺序发现规则。
|
|
5257
|
+
- 同目录普通文件先于 `.local.md`;`.local.md` 用于个人或当前工作区补充,而不是替换父级规则。
|
|
5258
|
+
- 每个 Agent 所有者分别去重;内容变化后会重新注入,未变化的文件不会反复消耗上下文。
|
|
5259
|
+
- 单文件最多 64 KiB,总计最多 256 KiB;超预算时优先保留更靠近目标文件的规则。
|
|
5260
|
+
- 指令文件经过 `realpath` 校验,指向工作区外部的符号链接不会被读取。
|
|
5261
|
+
|
|
5262
|
+
#### 用户怎么使用
|
|
5263
|
+
|
|
5264
|
+
在适用目录创建文件即可,不需要修改 Flavor 配置:
|
|
5265
|
+
|
|
5266
|
+
```markdown
|
|
5267
|
+
<!-- src/payments/AGENTS.md -->
|
|
5268
|
+
# Payments rules
|
|
5269
|
+
|
|
5270
|
+
- 金额一律使用整数分,禁止浮点数。
|
|
5271
|
+
- 修改结算逻辑后运行 payments 集成测试。
|
|
5272
|
+
```
|
|
5273
|
+
|
|
5274
|
+
之后直接说“修改 `src/payments/refund.ts` 的退款逻辑”。Agent 首次访问该路径后会自动收到这份规则。规则刚被人工修改时,Agent 下一次访问同目录文件会获得新内容。
|
|
5275
|
+
|
|
5276
|
+
### 38.3 成果物汇总与文件版本保护
|
|
5277
|
+
|
|
5278
|
+
#### 每轮成果物汇总
|
|
5279
|
+
|
|
5280
|
+
`AgentLoop` 收集成功工具结果中的 `file-change` presentation,并在正常回合完成前发送:
|
|
5281
|
+
|
|
5282
|
+
```ts
|
|
5283
|
+
{
|
|
5284
|
+
type: "deliverables",
|
|
5285
|
+
files: [
|
|
5286
|
+
{ path: "src/a.ts", operation: "update", added: 8, removed: 3 }
|
|
5287
|
+
]
|
|
5288
|
+
}
|
|
5289
|
+
```
|
|
5290
|
+
|
|
5291
|
+
同一文件在一轮中被多次修改时只显示一次,新增/删除行数累加;多文件 `ApplyPatch` 的关联文件也会被纳入。CLI 与 Electron 都从结构化事件渲染,不依赖模型在最终回答中“记得”列文件。
|
|
5292
|
+
|
|
5293
|
+
CLI 将该事件渲染为独立的 `CHANGESET` 收据,而不是紧贴正文的普通文本:
|
|
5294
|
+
|
|
5295
|
+
```text
|
|
5296
|
+
┌─ CHANGESET · 3 FILES
|
|
5297
|
+
│ UPDATE +26 -1 CHANGELOG.md
|
|
5298
|
+
│ CREATE +12 -0 src/new.ts
|
|
5299
|
+
│ DELETE +0 -4 src/old.ts
|
|
5300
|
+
└─ +38 -5
|
|
5301
|
+
```
|
|
5302
|
+
|
|
5303
|
+
- 路径优先相对当前工作区展示,避免 `C:\Users\...` 等绝对路径抢占终端宽度;窄终端由 Ink 在末尾截断。
|
|
5304
|
+
- `CREATE` 使用绿色、`UPDATE` 使用青色、`DELETE` 使用红色,增减行数也分别使用绿/红语义色;外框使用独立紫色,与 Web、Job、Command 收据形成稳定区分。
|
|
5305
|
+
- 单个收据最多列出前 8 个文件;超出时页脚显示 `Showing 8 of N`。总增删行数始终基于全部文件计算,不因折叠而失真。
|
|
5306
|
+
- 收据带一个底部空行,使后续 token usage 或 Agent 最终回答不会与文件清单粘连。
|
|
5307
|
+
- transcript 同时保留纯文本 `details` 作为旧渲染器和会话恢复的兼容后备;CLI 已渲染结构化 `changeset` 时会抑制这份后备文本,避免重复显示。
|
|
5308
|
+
|
|
5309
|
+
**使用方式:** 无需操作。让 Agent 正常使用 `Write`、`Edit`、`ApplyPatch` 修改文件,回合结束查看 `CHANGESET · N FILES` 收据即可;文件超过 8 个时以页脚总数为准。
|
|
5310
|
+
|
|
5311
|
+
#### 读后写版本保护
|
|
5312
|
+
|
|
5313
|
+
`FileObservationStore` 在 `Read` 成功后记录由设备号、inode、大小、修改时间和状态变更时间组成的版本。修改流程为:
|
|
5314
|
+
|
|
5315
|
+
```text
|
|
5316
|
+
Read/准备修改 → 记录 expectedVersion → 执行可选预览 Hook
|
|
5317
|
+
→ 写临时文件 → 再次比较版本 → 原子 rename
|
|
5318
|
+
```
|
|
5319
|
+
|
|
5320
|
+
- 如果 IDE、格式化器或另一个 Agent 在此期间改了文件,工具返回 `Stale file`,不会覆盖新内容。
|
|
5321
|
+
- `Write`、`Edit`、`ApplyPatch` 都在最终替换前复验。
|
|
5322
|
+
- 多文件补丁先完成全部 Hook,再统一复验全部目标,避免已经写完第一个文件才发现第二个文件过期。
|
|
5323
|
+
- 成功写入后刷新观察版本,允许同一 Agent 继续修改。
|
|
5324
|
+
|
|
5325
|
+
**冲突后的使用方式:** 让 Agent“重新读取冲突文件,基于最新内容重新应用修改”。不要要求它绕过版本检查。
|
|
5326
|
+
|
|
5327
|
+
### 38.4 标准工具输出与 Presentation 协议
|
|
5328
|
+
|
|
5329
|
+
`ToolDefinition<Input, Output>` 新增四个可选扩展点:
|
|
5330
|
+
|
|
5331
|
+
| 字段 | 消费者 | 作用 |
|
|
5332
|
+
|------|--------|------|
|
|
5333
|
+
| `outputSchema` | ToolRuntime | 校验工具真正返回的结构,失败时产生 `invalid_output` |
|
|
5334
|
+
| `renderForModel` | 模型上下文 | 把结构化结果转成稳定、节省 Token 的文本,再应用结果预算 |
|
|
5335
|
+
| `presentCall` | CLI / Electron | 工具刚开始时展示标题、命令、URL 或运行态 |
|
|
5336
|
+
| `presentResult` | CLI / Electron | 工具完成后展示终端、Web、通用摘要或文件 Diff |
|
|
5337
|
+
|
|
5338
|
+
`ToolResult` 的职责分离为:
|
|
5339
|
+
|
|
5340
|
+
- `output`:经过 Schema 校验的结构化真值;
|
|
5341
|
+
- `content`:提供给模型的有界文本;
|
|
5342
|
+
- `presentation`:与 React/Ink 无关的 renderer-neutral 描述;
|
|
5343
|
+
- `additionalContext`:工具成功后发现、需要在下一次模型调用前注入的上下文。
|
|
5344
|
+
|
|
5345
|
+
工具作者可以这样接入:
|
|
5346
|
+
|
|
5347
|
+
```ts
|
|
5348
|
+
const LookupTool: ToolDefinition<{ id: string }, { name: string; score: number }> = {
|
|
5349
|
+
name: "Lookup",
|
|
5350
|
+
description: "Look up one record",
|
|
5351
|
+
inputSchema: z.object({ id: z.string() }),
|
|
5352
|
+
outputSchema: z.object({ name: z.string(), score: z.number() }),
|
|
5353
|
+
paths: () => [],
|
|
5354
|
+
presentCall: (input) => ({ kind: "generic", title: "Lookup", summary: input.id }),
|
|
5355
|
+
renderForModel: (output) => `${output.name}: ${output.score}`,
|
|
5356
|
+
presentResult: (output) => ({ kind: "generic", title: output.name, summary: String(output.score) }),
|
|
5357
|
+
execute: async (input) => loadRecord(input.id),
|
|
5358
|
+
};
|
|
5359
|
+
```
|
|
5360
|
+
|
|
5361
|
+
旧工具不声明这些字段时继续使用原有 JSON/string 序列化和 presentation,保持插件与 MCP 兼容。
|
|
5362
|
+
|
|
5363
|
+
### 38.5 Job 注册表与后台 Shell
|
|
5364
|
+
|
|
5365
|
+
#### Job 状态模型
|
|
5366
|
+
|
|
5367
|
+
每个 Job 包含:`id`、`kind`、`owner`、`label`、`state`、创建/更新时间、退出码、错误、累计输出字符数和截断标记。状态只允许:
|
|
5368
|
+
|
|
5369
|
+
```text
|
|
5370
|
+
running → completed | failed | cancelled
|
|
5371
|
+
```
|
|
5372
|
+
|
|
5373
|
+
每个 Job 默认保留最近 200,000 个输出字符;注册表默认保留 100 个运行中/最近任务,达到上限时优先淘汰最早完成的任务。
|
|
5374
|
+
|
|
5375
|
+
#### 后台启动命令
|
|
5376
|
+
|
|
5377
|
+
普通前台调用保持不变:
|
|
5378
|
+
|
|
5379
|
+
```json
|
|
5380
|
+
{ "command": "npm", "args": ["test"], "cwd": "." }
|
|
5381
|
+
```
|
|
5382
|
+
|
|
5383
|
+
长服务设置 `background: true`,工具立即返回 `jobId`:
|
|
5384
|
+
|
|
5385
|
+
```json
|
|
5386
|
+
{
|
|
5387
|
+
"command": "npm",
|
|
5388
|
+
"args": ["run", "dev"],
|
|
5389
|
+
"cwd": ".",
|
|
5390
|
+
"background": true
|
|
5391
|
+
}
|
|
5392
|
+
```
|
|
5393
|
+
|
|
5394
|
+
典型控制流程:
|
|
5395
|
+
|
|
5396
|
+
1. `JobList {}`:查看当前所有者的任务与状态。
|
|
5397
|
+
2. `JobRead { "id": "job-...", "cursor": 0 }`:读取输出并保存返回的 `cursor`。
|
|
5398
|
+
3. 再次 `JobRead` 时传入上次 cursor,只获取新增输出。
|
|
5399
|
+
4. `JobWait { "id": "job-..." }`:需要命令结束后才能继续时等待终态。
|
|
5400
|
+
5. `JobKill { "id": "job-..." }`:终止任务及其进程树。
|
|
5401
|
+
|
|
5402
|
+
用户通常只需说:“在后台运行 `npm run dev`,读取日志直到服务就绪;完成检查后停止它。”
|
|
5403
|
+
|
|
5404
|
+
CLI 将所有 Job 操作统一显示为“运行收据”,而不是普通工具行:`JOB · RUNNING/COMPLETED/FAILED/CANCELLED` 使用琥珀/绿/红/灰状态色边界,随后展示任务 ID、类型和命令标签;`JobRead` / `JobKill` 增加独立 `LOG` 区,阶段分隔行、普通输出和 stderr/ERR 使用不同强调层级;底部集中展示退出码、cursor 和截断状态。CLI 只展示最近 12 行日志并明确省略数量,`JobList` 最多展示最近 8 项,避免后台输出淹没对话。收据结束后留一行空白,Agent 正文回到主内容基线。后台进程退出码非 0 时,Registry 直接将 Job 标为 `failed`,不再产生“completed 但 exit 1”的矛盾状态。
|
|
5405
|
+
|
|
5406
|
+
前台 Shell 使用同一视觉语法但命名为“命令收据”:`COMMAND · RUNNING/COMPLETED/FAILED/CANCELLED` 的状态色与 Job 一致,命令行单独展示;stdout 进入 `OUTPUT` 区,stderr 进入红色 `ERROR` 区,底部显示退出码和运行时截断标记。CLI 最多显示 16 行输出;超出时同时保留前 8 行和后 8 行,在中间明确显示省略行数,因此 `git log` 的最近提交和 `git show --stat` 的标题、统计尾部都不会丢失。每行在窄终端单行截断,收据结束后留一行再进入 Agent 正文。持久 PTY 复用布局但标为 `TERMINAL`,避免把多轮交互会话误解成一次性命令。
|
|
5407
|
+
|
|
5408
|
+
Windows 下 `cmd.exe` 的内置错误信息可能跟随系统 OEM 代码页,直接按 UTF-8 读取会产生 `����`。Shell 在执行用户命令前无输出地切换到代码页 65001;前台结果保留原始字节,先严格校验 UTF-8,失败时在 Windows 自动使用 GB18030 解码。后台 Job 使用自适应流式解码器,能够识别 UTF-8/GB18030,并正确处理中文或 emoji 被拆到相邻数据块的情况。调用命令时仍需保持参数化形式,例如 `{ "command": "npm", "args": ["view", "node", "dist-tags", "--json"] }`,不要把整行命令放进 `command` 字段。
|
|
5409
|
+
|
|
5410
|
+
### 38.6 持久 PTY
|
|
5411
|
+
|
|
5412
|
+
后台 Shell 适合“启动后只看日志”的服务;需要 REPL、数据库 CLI、安装器提问或连续输入时,应使用持久 PTY。实现基于 `node-pty`,Windows 使用 ConPTY,Unix 使用系统伪终端,不会静默降级成普通管道。
|
|
5413
|
+
|
|
5414
|
+
工具序列:
|
|
5415
|
+
|
|
5416
|
+
```text
|
|
5417
|
+
TerminalOpen → TerminalWrite → TerminalRead ─┬→ TerminalWrite(继续交互)
|
|
5418
|
+
├→ TerminalResize
|
|
5419
|
+
└→ TerminalClose
|
|
5420
|
+
```
|
|
5421
|
+
|
|
5422
|
+
参数示例:
|
|
5423
|
+
|
|
5424
|
+
```json
|
|
5425
|
+
// 1. 打开终端
|
|
5426
|
+
{ "cwd": ".", "columns": 120, "rows": 32 }
|
|
5427
|
+
|
|
5428
|
+
// 2. 输入命令并回车
|
|
5429
|
+
{ "id": "term-...", "data": "python", "enter": true }
|
|
5430
|
+
|
|
5431
|
+
// 3. 增量读取输出
|
|
5432
|
+
{ "id": "term-...", "cursor": 0 }
|
|
5433
|
+
|
|
5434
|
+
// 4. 继续向同一进程输入
|
|
5435
|
+
{ "id": "term-...", "data": "print(6 * 7)", "enter": true }
|
|
5436
|
+
|
|
5437
|
+
// 5. 调整尺寸或关闭
|
|
5438
|
+
{ "id": "term-...", "columns": 160, "rows": 40 }
|
|
5439
|
+
{ "id": "term-..." }
|
|
5440
|
+
```
|
|
5441
|
+
|
|
5442
|
+
`TerminalList {}` 可找回当前所有者打开的终端。终端工作目录必须位于工作区内;单终端保留最近 200,000 个字符;Runtime dispose 时所有终端都会关闭,关联 Job 同步进入终态。
|
|
5443
|
+
|
|
5444
|
+
### 38.7 桌面状态与 D2C/E2E 进程生命周期
|
|
5445
|
+
|
|
5446
|
+
#### Electron Job 状态
|
|
5447
|
+
|
|
5448
|
+
生产 Runtime 暴露 `jobs.list()` 与 `jobs.subscribe()`。`DesktopRuntimeController` 在会话建立时订阅,在切换会话或释放 Runtime 时退订;Job 启动、输出、完成或取消都会发布新的 `DesktopSnapshot.jobs`。标题栏只显示正在运行的数量,完整状态仍可通过 Job 工具读取。
|
|
5449
|
+
|
|
5450
|
+
**使用方式:** 在 Electron 中让 Agent 启动后台 Shell 或 PTY,标题栏会自动出现“N 个后台任务”;任务结束后提示自动消失。
|
|
5451
|
+
|
|
5452
|
+
#### D2C/E2E 生命周期收敛
|
|
5453
|
+
|
|
5454
|
+
`ManagedProcess` 统一承担:
|
|
5455
|
+
|
|
5456
|
+
- stdout/stderr 尾部保留;
|
|
5457
|
+
- 正常退出、启动错误和退出码观察;
|
|
5458
|
+
- 幂等 `stop()`;
|
|
5459
|
+
- 先温和终止、超时后强制终止进程树。
|
|
5460
|
+
|
|
5461
|
+
`d2c/runner.ts` 的 Vite 预览和 `d2c/mock-runner.ts` 的 Express/FastAPI 后端已迁移到该底座,对外 `RunningProject` / `D2cRunningMock` 契约不变。
|
|
5462
|
+
|
|
5463
|
+
**使用方式:** 用户仍在 Electron E2E/D2C 工作台点击启动、停止预览或后端,无需学习新命令;改变仅体现在退出更可靠、重复停止安全、应用关闭时不残留子进程。
|
|
5464
|
+
|
|
5465
|
+
### 38.8 原生 WebSearch 与 WebFetch
|
|
5466
|
+
|
|
5467
|
+
#### WebSearch
|
|
5468
|
+
|
|
5469
|
+
输入:
|
|
5470
|
+
|
|
5471
|
+
```json
|
|
5472
|
+
{ "query": "TypeScript 7 migration official", "maxResults": 8 }
|
|
5473
|
+
```
|
|
5474
|
+
|
|
5475
|
+
- `query` 必填,1–1,000 字符;
|
|
5476
|
+
- `maxResults` 默认 8,范围 1–20;
|
|
5477
|
+
- 默认 Provider 优先使用无需 API Key 的 DuckDuckGo Lite;连接失败、HTTP 非 2xx 或解析不到结果时自动降级到 Bing;
|
|
5478
|
+
- Bing 中转链接会解码为真实目标 URL,方便后续直接交给 `WebFetch`;
|
|
5479
|
+
- 输出统一为 `{ query, results: [{ title, url, snippet }] }`;
|
|
5480
|
+
- `WebSearchProvider` 可注入,后续可替换为企业搜索或带密钥 Provider,而不改变工具协议。
|
|
5481
|
+
|
|
5482
|
+
CLI 不把搜索结果渲染成普通正文,而是使用“证据夹层”:蓝灰色左边界和 `WEB SEARCH · N RESULTS` 标签标明工具数据;查询词单独成行;最多展示前 5 条,每条按真实搜索排名显示两行“标题 + 去除查询参数后的紧凑来源”;底部显示 `Showing 5 of N`。证据块比回答正文多缩进两格,并在结束后保留一行空白,最终回答回到主内容基线。窄终端中标题和来源单行截断,不让长 URL 冲散信息层级。
|
|
5483
|
+
|
|
5484
|
+
用户可直接说:“使用 WebSearch 搜索 TypeScript 7 的官方迁移文档,只保留最相关的 5 条。”搜索只返回摘要;需要阅读全文时继续调用 `WebFetch`。
|
|
5485
|
+
|
|
5486
|
+
#### WebFetch
|
|
5487
|
+
|
|
5488
|
+
输入:
|
|
5489
|
+
|
|
5490
|
+
```json
|
|
5491
|
+
{
|
|
5492
|
+
"url": "https://www.typescriptlang.org/docs/",
|
|
5493
|
+
"timeoutMs": 30000,
|
|
5494
|
+
"maxBytes": 2097152
|
|
5495
|
+
}
|
|
5496
|
+
```
|
|
5497
|
+
|
|
5498
|
+
- 只允许 HTTP(S),只允许标准 Web 端口 80/443;
|
|
5499
|
+
- 默认超时 30 秒,最大 120 秒;
|
|
5500
|
+
- 默认响应上限 2 MiB,最大 10 MiB;
|
|
5501
|
+
- 最多跟随 5 次重定向,每一跳重新执行安全校验;
|
|
5502
|
+
- JSON/纯文本按文本返回,HTML 会去掉脚本、样式和标签并转换成稳定可读文本;
|
|
5503
|
+
- 输出包含最终 URL、HTTP 状态、Content-Type、正文和 `truncated` 标记。
|
|
5504
|
+
- 兼容 Clash/TUN 常见的 Fake-IP DNS:域名解析得到 `198.18.0.0/15` 时可作为代理承载地址连接;URL 直接填写该网段仍会被拦截。
|
|
5505
|
+
|
|
5506
|
+
用户可直接说:“用 WebFetch 读取这个 URL,提取安装步骤并注明页面地址。”
|
|
5507
|
+
|
|
5508
|
+
### 38.9 安全边界
|
|
5509
|
+
|
|
5510
|
+
| 风险 | 防护 |
|
|
5511
|
+
|------|------|
|
|
5512
|
+
| Web 工具绕过授权 | `WebSearch` / `WebFetch` 注册为 `network` 工具;默认模式需要用户审批,子 Agent 按 bubble 策略上报 |
|
|
5513
|
+
| SSRF 访问本机或云元数据 | 拒绝 URL credentials、localhost、环回、私网、链路本地、CGNAT、组播、未指定、文档保留地址,以及映射到非公网目标的 IPv4-mapped IPv6 |
|
|
5514
|
+
| Clash/TUN Fake-IP 被误判 | `198.18.0.0/15` 仅在“域名 DNS 解析结果”位置作为代理承载地址放行;字面 IP URL 仍拒绝,其他私网与特殊地址规则不放宽 |
|
|
5515
|
+
| DNS 校验后换地址 | 解析并校验全部地址,然后直接连接已验证 IP,同时保留原 Host header 和 TLS server name |
|
|
5516
|
+
| 重定向跳入私网 | 每次重定向重新解析、重新校验地址和端口 |
|
|
5517
|
+
| 无限下载或慢响应 | 总超时、响应字节上限、工具结果上下文预算 |
|
|
5518
|
+
| Agent 操作他人后台任务 | Job 和终端按 `ownerId` 校验;主 Agent 与 `subagent:<taskId>` 隔离 |
|
|
5519
|
+
| 终端逃逸工作区 | `cwd` 解析后必须仍在 workspace;Shell/PTY 继续经过现有权限引擎 |
|
|
5520
|
+
| Runtime 退出残留进程 | JobRegistry、TerminalService、ManagedProcess 均提供幂等 dispose/stop 和进程树终止 |
|
|
5521
|
+
|
|
5522
|
+
注意:Web 页面内容是不可信输入,只能作为外部资料,不能覆盖系统提示、项目指令或权限规则。原生 Web 工具解决的是“可控地联网”,不是把网页提升为可信指令。
|
|
5523
|
+
|
|
5524
|
+
### 38.10 文件地图与验证
|
|
5525
|
+
|
|
5526
|
+
| 路径 | 职责 |
|
|
5527
|
+
|------|------|
|
|
5528
|
+
| `src/context/workspace-instructions.ts` | 分层 AGENTS/CLAUDE 发现、预算、digest 去重、realpath 边界 |
|
|
5529
|
+
| `src/tools/files.ts` | `FileObservationStore`、写前版本复验、多文件补丁安全 |
|
|
5530
|
+
| `src/tools/types.ts` / `runtime.ts` | 泛型输出、Schema 校验、模型渲染、Presentation、附加上下文 |
|
|
5531
|
+
| `src/agent/loop.ts` / `types.ts` | 工具上下文注入、所有者透传、deliverables 聚合事件 |
|
|
5532
|
+
| `src/jobs/registry.ts` | Job 状态、所有权、游标输出、等待/取消、数量限制 |
|
|
5533
|
+
| `src/jobs/managed-process.ts` | D2C/E2E 共用子进程生命周期 |
|
|
5534
|
+
| `src/tools/shell.ts` / `jobs.ts` | 后台 Shell 与 JobList/Read/Wait/Kill 工具 |
|
|
5535
|
+
| `src/terminal/service.ts` / `src/tools/terminal.ts` | node-pty 会话及 Terminal 六个工具 |
|
|
5536
|
+
| `src/tools/web.ts` | WebSearch、WebFetch、HTML 文本化与 SSRF 防护 |
|
|
5537
|
+
| `src/desktop/runtime-controller.ts` / `contracts.ts` | Job 快照订阅和桌面契约 |
|
|
5538
|
+
| `src/desktop/renderer/app.tsx` / `styles.css` | 桌面 Job 状态条和通用 Presentation |
|
|
5539
|
+
| `src/d2c/runner.ts` / `mock-runner.ts` | D2C/E2E ManagedProcess 迁移 |
|
|
5540
|
+
|
|
5541
|
+
对应测试位于 `tests/context/workspace-instructions.test.ts`、`tests/tools/files.test.ts`、`tests/tools/runtime.test.ts`、`tests/jobs/registry.test.ts`、`tests/tools/shell.test.ts`、`tests/terminal/service.test.ts`、`tests/tools/web.test.ts`、`tests/agent/loop.test.ts`、`tests/ui/transcript.test.ts` 和桌面控制器测试。发布前验证命令:
|
|
5542
|
+
|
|
5543
|
+
```bash
|
|
5544
|
+
npm test
|
|
5545
|
+
npm run typecheck
|
|
5546
|
+
npm run vscode:typecheck
|
|
5547
|
+
npm run build
|
|
5548
|
+
```
|