From 7bdb42f26c60747fbabf3bb3a00e3df3477a46a3 Mon Sep 17 00:00:00 2001 From: brother7 <7brother7@gmail.com> Date: Mon, 7 Sep 2026 12:21:40 +0800 Subject: [PATCH] feat(design): integrate agent activity timeline --- .../adr-007-ai-design-living-form-v2.md | 11 ++ .project-docs/20-architecture/data-flow.md | 3 +- .project-docs/20-architecture/module-map.md | 10 +- .../20-architecture/system-overview.md | 7 +- .project-docs/30-worklog/current-state.md | 21 +++- ...7-design-agent-activity-client-b6d913e4.md | 103 ------------------ ...ntegrate-design-agent-activity-b7d3f1a8.md | 64 +++++++++++ .project-docs/40-domain/business-rules.md | 3 +- .../ImageCanvas/DesignConversationPane.tsx | 36 +++--- src/stores/image-workspace.ts | 3 +- tests/unit/image-canvas-page.test.tsx | 57 ++++++++++ tests/unit/image-workspace-store.test.ts | 58 ++++++++++ 12 files changed, 243 insertions(+), 133 deletions(-) delete mode 100644 .project-docs/30-worklog/tasks/20260907-design-agent-activity-client-b6d913e4.md create mode 100644 .project-docs/30-worklog/tasks/20260907-integrate-design-agent-activity-b7d3f1a8.md diff --git a/.project-docs/10-decisions/adr-007-ai-design-living-form-v2.md b/.project-docs/10-decisions/adr-007-ai-design-living-form-v2.md index 33ef7cd..8e7f8f4 100644 --- a/.project-docs/10-decisions/adr-007-ai-design-living-form-v2.md +++ b/.project-docs/10-decisions/adr-007-ai-design-living-form-v2.md @@ -4,6 +4,9 @@ Accepted / implemented +Amended on 2026-09-07 to define operation-scoped public activity as transient +presentation state beneath the matching optimistic user message. + ## Date 2026-08-30 @@ -27,6 +30,12 @@ versioned Design Specification and a persistent form throughout the design flow. - Every mutation carries stable command and semantic operation identities. An unknown transport result keeps the same command for replay; revision conflicts refresh canonical state without discarding local drafts. +- While a chat operation is pending, Electron Main may normalize the server's closed + `design.assistant.progress` lifecycle into fixed youth-safe stages, and Renderer + may show one transient activity panel beneath the matching optimistic user message. + Activity is not a canonical Turn, Current Specification state, assistant content, + or evidence that a change committed. Model chain-of-thought, prompts, Provider + responses, tool arguments, and unvalidated model text are never rendered. - Generation is a compile-and-confirm boundary. The server returns an immutable Quote for one exact Specification revision; the client displays the public output plan, warnings, expiry, and Token Point amount and confirms only the Quote ID. @@ -51,6 +60,8 @@ and uncertain retries auditable without exposing provider internals. old clients and V1 semantic writers receive no compatibility window. - Production database cutover, paid Provider activation, and real-account installed client smoke remain separate operator gates. +- Replayed activity and generic terminal Gateway events reconcile by the original + operation identity. They do not create another message, form, or retry intent. ## Supersedes diff --git a/.project-docs/20-architecture/data-flow.md b/.project-docs/20-architecture/data-flow.md index a4c2065..34a5e7f 100644 --- a/.project-docs/20-architecture/data-flow.md +++ b/.project-docs/20-architecture/data-flow.md @@ -30,6 +30,7 @@ | 客户端更新检查 | 设置页 | Renderer update store → IPC → Main AppUpdater → 目标 feed | Main 记录并重抛原始错误;Renderer 只显示去重、脱敏的单条提示,稳定源缺包不伪装为最新版 | | Design Workspace load | Canvas/Sidebar | Renderer Host API → Main-owned Works Square V2 adapter → current Workspace/Direction/Living Form projection | 一个 Workspace 公开一个 current Direction 与 persistent Agent Session;conversation timeline 是交互历史,不是独立 authority object | | Design input and reconciliation | Chat/direct edit/decision/proposal/lock/Asset binding/restore | Renderer draft → Main → `design.input.apply` → canonical Direction projection | 全部进入同一 reducer;accepted 前 draft 保持本地,revision conflict 刷新权威投影,unknown result 复用原 command/operation identity | +| Design activity and reply streaming | Direction Gateway journal | Main 固定活动阶段归一化 → Renderer operation-scoped activity;committed assistant delta → matching provisional assistant bubble → canonical Turn | `design.assistant.progress` 只显示在对应 optimistic user message 下方,不成为消息或右侧摘要;`design.assistant.delta` 只投影已提交回复。两者都按 Workspace、Direction、operation identity 和 replay cursor 收敛,均不改写 Specification | | 设计有限请求生命周期 | Renderer Workspace JSON 调用 / shared Works token refresh | Main deadline → Electron transport → safe-read-only Node fallback → Host API timeout envelope | 包括取凭据、请求头和响应 body 的完整生命周期最多 30 秒;超时 abort transport 并稳定返回 `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT`;透明 fallback 只允许 `GET`/`HEAD`/`OPTIONS`,mutation 不隐式重放 | | Design Asset binding | 当前 Workspace 已完成图片 / 本地上传 | canonical Asset → typed `asset_binding` input → Current Specification revision | 图片/视频用途由 Specification medium 和 binding role 决定;只提交真实 Workspace Asset identity,不使用本地路径或自然语言占位 | | Design Quote and confirmation | 当前 exact Specification revision | `design.quote.request` → immutable public Quote projection → `design.generation.confirm` with Quote ID | Renderer 只展示 output summary、warnings、expiry、Token Points;Provider Prompt/model/route/storage/internal billing 不下发或编辑 | @@ -81,4 +82,4 @@ ## Last Updated -2026-09-06 +2026-09-07 diff --git a/.project-docs/20-architecture/module-map.md b/.project-docs/20-architecture/module-map.md index e4d0d7c..0205339 100644 --- a/.project-docs/20-architecture/module-map.md +++ b/.project-docs/20-architecture/module-map.md @@ -35,11 +35,11 @@ | `electron/coding-runtime/pi/{extension-host,subagent,write-lease}.ts` / `electron/main/background-lifecycle.ts` | 必需 Makelore extension、显式安装且启用的 Device Package extensions、交互、子 Agent、同项目写租约与后台运行租约 | parent generation 加载完整 Main-selected extension 集;child 并发 4、单次最多 8、禁止递归;active/uncertain run 不因页面隐藏或确认超时被回收,所有 stop/replacement 必须有原因 | | `electron/main/updater.ts` | 目标 feed 解析、electron-updater 生命周期与原始诊断 | 缺少稳定 manifest 保持错误;事件/Promise 重复失败按检查实例去重 | | `src/components/settings/UpdateSettings.tsx` | 更新状态、重试与用户可读错误展示 | 只显示一条简洁中文提示;技术诊断统一回退到本地化通用文案 | -| `shared/image-workspace.ts` | AI Design V2 Workspace、Direction、Living Form、immutable Quote、Task、Asset 与事件共享契约 | Current Specification 是唯一语义权威;Task/Asset 属于独立 Workspace resource projection | +| `shared/image-workspace.ts` | AI Design V2 Workspace、Direction、Living Form、immutable Quote、Task、Asset 与事件共享契约 | Current Specification 是唯一语义权威;Task/Asset 属于独立 Workspace resource projection;public activity 是固定、operation-scoped presentation contract | | `electron/api/routes/image-workspace.ts` | AI 绘画 Host API 与本地事件流投影 | Renderer 只通过该路由访问 Main-owned workspace adapter | -| `electron/image-workspace/works-square-workspace.ts` | Works Square V2 adapter、stable command/operation IDs 与 Direction event mapping | unknown transport result 保留精确命令;Main 持有 token、ticket、WebSocket、retry classification 与 safe errors | -| `src/stores/image-workspace.ts` | Current Workspace/Direction/Living Form、local drafts、pending operations 与 Workspace resources | revision conflict 刷新 canonical state;event order/Task progress 不成为 Specification authority | -| `src/pages/ImageCanvas/{index,DesignConversationPane,DesignFormPane,DesignProductionPanel}.tsx` | 持久双栏 Canvas、conversation、Living Form、immutable Quote confirmation、Tasks 与 Assets | chat/direct edits/decisions/locks/bindings 使用同一 V2 reducer;确认只提交 Quote ID | +| `electron/image-workspace/works-square-workspace.ts` | Works Square V2 adapter、stable command/operation IDs 与 Direction event mapping | unknown transport result 保留精确命令;Main 持有 token、ticket、WebSocket、retry classification、safe errors,并把闭集 progress stage 归一为固定 youth-safe copy | +| `src/stores/image-workspace.ts` | Current Workspace/Direction/Living Form、local drafts、pending operations、operation activity 与 Workspace resources | revision conflict 刷新 canonical state;activity/delta/terminal event 按 Workspace、Direction 和 operation identity 收敛;event order/Task progress 不成为 Specification authority | +| `src/pages/ImageCanvas/{index,DesignConversationPane,DesignFormPane,DesignProductionPanel}.tsx` | 持久双栏 Canvas、conversation、operation-scoped AI activity、Living Form、immutable Quote confirmation、Tasks 与 Assets | chat/direct edits/decisions/locks/bindings 使用同一 V2 reducer;固定活动附着于对应 user bubble 且不成为对话或右侧摘要;确认只提交 Quote ID | | `src/components/layout/ImageWorkspaceSidebar.tsx` | Workspace 选择、创建与 Prompt Museum 入口 | 不再创建或选择嵌套 Conversation | | `shared/image-prompt-museum.ts` | Prompt Museum 列表、分类、详情、署名与分页共享 DTO | 客户端不包含内容数据集,只定义服务端字段契约 | | `electron/api/routes/image-prompt-museum.ts` | Main-owned Museum 列表/详情代理与 Works 登录态 | 仅 GET 固定路径和白名单查询;Renderer 不获得 Bearer Token | @@ -93,4 +93,4 @@ ## Last Updated -2026-09-06 +2026-09-07 diff --git a/.project-docs/20-architecture/system-overview.md b/.project-docs/20-architecture/system-overview.md index 806b876..d6c39f7 100644 --- a/.project-docs/20-architecture/system-overview.md +++ b/.project-docs/20-architecture/system-overview.md @@ -27,8 +27,8 @@ Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展 | Code-owned Official Project Plugins | Existing Account acquisition or system-included delivery → project enablement → effective parent snapshot | Data Service、Game Resource 与 Project Scaffold 都不要求 Agent assignment,项目启用后自动进入每个父 Agent;child 不继承 Plugin。三者不经过设备下载、更新、Beta 或 artifact 签名;Game Resource 的一次确认由 Main 提交一次、内部轮询并把全部终态输出自动写入冻结的原项目,恢复本地交付不得重新生成或计费;Project Scaffold 的 `.mjs` 仍只来自签名客户端固定资源。需要分配的 Marketplace 下载包保持原规则。 | | Device Packages | Conversation install tools → Main-owned inspect/preview/confirm/commit → immutable local generation → parent Skill/Pi-extension resources | 支持 npm、Git、绝对本地 Plugin 目录与 loose `SKILL.md`;没有可见安装入口、Account Library、Release、Admission 或 Marketplace Package Store。可执行 extension 与非空 Skill `scripts/` 拥有桌面用户权限,必须披露并独立确认;生命周期脚本禁用。每个 generation 包含所有显式安装且当前启用的 Skill/extension;新/idle parent 自动刷新,active parent 在 turn settled 后刷新,child 始终为空。 | | AI Design Workspace & Living Form | 一个 Workspace 的当前 Direction、Current Specification、持久 Agent Session、conversation timeline、Tasks 与 Assets | 自然对话是主创作面;Living Form 仅以“AI 已理解”的紧凑辅助摘要与可选手动调整投影服务端 Current Specification,Renderer 只持有草稿和已接受投影 | -| AI Design Input & Reconciliation | Chat、字段/集合编辑、decision、proposal、lock、Asset binding 与 restore | 全部进入同一 `design.input.apply` reducer;稳定 command/operation ID 支持 unknown-result 重放,revision conflict 刷新权威状态;待提交 chat 从同一 pending operation 临时投影,assistant delta 只能在匹配该 operation 的一个未完成助手气泡中临时绘制且不生成独立整理进度栏 | -| AI Design Gateway Routing | Main-owned Works Square V2 adapter 与 Direction event stream | Main 持有 Works Token、stream ticket、WebSocket、重试分类和错误脱敏;事件顺序与 Task progress 不构成 Specification 真值 | +| AI Design Input & Reconciliation | Chat、字段/集合编辑、decision、proposal、lock、Asset binding 与 restore | 全部进入同一 `design.input.apply` reducer;稳定 command/operation ID 支持 unknown-result 重放,revision conflict 刷新权威状态;待提交 chat 从同一 pending operation 临时投影,固定 public activity 附着于该用户消息,assistant delta 只进入匹配 operation 的一个未完成助手气泡 | +| AI Design Gateway Routing | Main-owned Works Square V2 adapter 与 Direction event stream | Main 持有 Works Token、stream ticket、WebSocket、重试分类和错误脱敏;Main 将闭集 `design.assistant.progress` 阶段归一为固定中文,不透传模型推理或任意服务端文案;事件顺序与 Task progress 不构成 Specification 真值 | | AI Design Quote & Task Controls | 精确 Specification revision 编译出的不可变 Quote 与 Workspace Tasks | 客户端只展示 public output summary、warnings、expiry 与 Token Points,并以 Quote ID 确认;Provider Prompt/model/route/storage/billing atoms 不下发 | | AI Design Assets | Workspace 已完成作品或本地上传的真实 Asset | Asset 通过 typed binding 写入 Specification;生成结果经 Main-owned asset download 保存 | | Prompt Museum | Canvas “获取灵感”页面 → Main Host API → Works Square | 服务端驱动的审核内容、筛选和分页;Renderer 不持有 Works Token 或内置数据集,“使用此 Prompt”只回填输入框 | @@ -94,6 +94,7 @@ Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展 - Renderer 的异步与流式结果必须核对 Workspace、Direction、revision 和 operation identity;Direction snapshot 是 Specification 真值,Task/Asset 事件只更新 Workspace resource projection。 - 待提交 chat 可以从现有 pending operation 立即投影为明确标注“发送中/正在确认”的用户气泡,但只有服务端 canonical turn 能进入对话历史;确定失败必须恢复原草稿,不能另建一套消息状态或新业务意图。 - `design.assistant.delta` 是未完成的传输状态,不是 canonical assistant turn。Renderer 只能把它临时绘制为与同一 pending chat identity 绑定的单个未完成助手气泡,并在该 operation 确定收敛后由 canonical turn 替换;不得持久化为第二条消息、伪装为已完成回复或创建独立整理进度栏。unknown outcome 保留原 identity 与已有片段,其他 operation 的更新不得全局清除它;右侧 Current Specification 继续呈现 AI 当前整理出的设计理解。重叠连接与重放 chunk 必须按连接 generation 和 `chunkIndex` 收敛。 +- `design.assistant.progress` 是与同一 pending chat identity 绑定的瞬时活动投影,可在 optimistic user bubble 下更新和折叠。它只能使用 Main 归一化的固定阶段,不得成为 conversation Turn、右侧 Current Specification 的副本、通用全局整理栏或 model chain-of-thought;终态事件按原 operation identity 收敛它。 - 确认生成只提交不可变 Quote ID。Task 事务已提交但事件迟到时可刷新 Workspace projection;Task progress 不得改写 Living Form 或授权新的生成操作。 - Updater feed 选择、原始错误日志、下载和安装生命周期只属于 Electron Main。Renderer 不得把缺失稳定 manifest 投影为“已是最新版”,也不得显示原始堆栈、URL、路径或错误码;并发检查共享同一错误事件时只发送一次错误状态,后续独立重试仍可重新报告。 - 图片与视频复用同一个单图来源选择器。图片 Brief 可从当前 Workspace 的已完成作品或本地上传中选择一张参考图继续生成;视频 Brief 使用同一入口绑定首帧。两条路径都必须通过现有 Workspace Asset 上传/选择契约提交一个真实 `attachmentAssetIds`,不得用本地路径或自然语言描述代替资产身份。 @@ -107,4 +108,4 @@ Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展 ## Last Updated -2026-09-06 +2026-09-07 diff --git a/.project-docs/30-worklog/current-state.md b/.project-docs/30-worklog/current-state.md index 1cd7092..10dc250 100644 --- a/.project-docs/30-worklog/current-state.md +++ b/.project-docs/30-worklog/current-state.md @@ -4,6 +4,23 @@ This file is the integrated default-branch snapshot. Feature tasks record progre ## Integrated Through +- AI Design operation activity source + `81b524a02c2cf51304090afa8fb89d27c72c5d2b` from task + `20260907-design-agent-activity-client-b6d913e4` is integrated by task + `20260907-integrate-design-agent-activity-b7d3f1a8`. Electron Main now + normalizes the server's four closed public stages into fixed youth-safe copy; + Renderer attaches one transient, update-in-place `AI 处理过程` panel to the exact + optimistic user message and collapses completed work without creating a chat Turn + or duplicating the right-side Current Specification. Workspace, Direction, + operation, pre-command turn sequence, connection generation, cursor, and terminal + events keep replay and stale results scoped; unknown outcomes retain the original + identity. Integration review additionally preserves prior completed/unknown activity + when a later chat starts and keeps each pending user's activity and provisional + reply together in visual order. Final committed assistant text continues through + the existing provisional assistant bubble and canonical Turn replacement. Focused verification passed 69 + tests, TypeScript, changed-file ESLint, and all Vite production targets. No server, + database, billing, Quote/Task, navigation, package, deployment, publication, or paid + Provider call changed. - Coding project setup UX source `8042d2be265e40288e628fcdc755e9f29151306b` from task `20260906-project-setup-ux-90fe6cf2` is integrated onto local `main` by task `20260906-integrate-project-setup-ux-4b7d2e91`. A Coding Conversation is @@ -719,7 +736,7 @@ This file is the integrated default-branch snapshot. Feature tasks record progre AI Design Canvas 现在默认以对话和一张持续可见的“我的创作”卡服务 8-16 岁创作者;专业字段矩阵收进按需打开的“精细调整”,移动端保持对话优先并只挂载一个卡片/底部面板。Creation Card、精细调整、Quote、Task 与结果提示都只投影权威状态,已知问题按 code 转成通俗中文,未知服务端或 Provider 文本不会直接显示。一个 Workspace 仍只公开一个 current Direction、一个 persistent Agent Session 和一个 Current Specification;conversation timeline 只记录交互历史。Chat、direct edits、decision responses、proposal acceptance、locks、Asset binding 与 restore 都通过 `design.input.apply` 进入同一服务端 reducer,Renderer drafts 在 accepted 前保持本地。Main 持有 Works Token、stream ticket、WebSocket、request deadline、stable command/operation IDs 与错误脱敏;unknown result 只能复用原 identity,结构化业务错误不得重放。Generation 由服务端对 exact Specification revision 编译 immutable Quote,客户端只展示 public output plan、warnings、expiry 与 Token Points,并以 Quote ID 调用 `design.generation.confirm`;Provider Prompt、model、route、storage 和 billing atoms 不进入 Renderer。Task/Asset events 独立收敛 Workspace resources,不改写 Living Form。Development 与 packaged builds 均使用 Works Square V2,V1 DTO、local semantic adapter、mutable Quote PATCH 与 editable provider Prompt 已移除。 -新提交的 Design chat 会立即从现有 pending operation 投影为带“发送中”或“正在确认”的临时用户气泡,服务端确认的 canonical turn 到达后再替换它;确定失败时原草稿重新出现在输入框。`design.assistant.delta` 只作为内部传输与收敛状态,不显示原始片段,也不在对话区生成独立整理进度栏;右侧 Current Specification 摘要继续承担“AI 当前听懂的内容”。重复连接和事件按 connection generation 与 `chunkIndex` 收敛。 +新提交的 Design chat 会立即从现有 pending operation 投影为带“发送中”或“正在确认”的临时用户气泡,服务端确认的 canonical turn 到达后再替换它;确定失败时原草稿重新出现在输入框。`design.assistant.progress` 经 Main 归一为固定通俗阶段,只在对应用户气泡下形成可更新、可折叠的“AI 处理过程”,不成为对话消息、右侧摘要或模型思考过程。`design.assistant.delta` 仅把已验证并提交的回复临时绘制为同一 operation 的未完成助手气泡,随后由 canonical turn 替换;不生成独立全局整理栏。右侧 Current Specification 摘要继续承担“AI 当前听懂的内容”。重复连接和事件按 connection generation、operation identity 与 `chunkIndex` 收敛。 Canvas 侧栏提供“获取灵感”进入 Prompt Museum。列表、筛选、分页、详情、作者/来源/许可证和图片地址全部由服务端经 Main-owned Host API 提供,客户端不打包静态数据集;服务端相对媒体只允许固定 `/api/image-prompt-museum/{entry}/media/{thumbnail|number}` 形状,并由 Main 注入 Works Bearer、执行一次 401 刷新、可信 raster MIME 与 10 MiB 上限后转为 Renderer data URL;credential-free HTTPS CDN 图片保持直连。图片失败只显示卡片内占位,不阻断卡片或详情;缺少来源 URL 时显示纯文本。“使用此 Prompt”只把原文带回当前 Canvas 输入框,不自动发送。该模块不是投稿、点赞、评论或排行榜社区。客户端契约已就绪,但不据此宣称 Works Square 内容后台和生产数据已经部署。`pnpm run dev` 现在默认使用云端 Canvas 适配器,本地适配器只能通过显式开发命令启用;产品 UI 只保留中文。 @@ -872,4 +889,4 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选 ## Last Updated -2026-09-06 +2026-09-07 diff --git a/.project-docs/30-worklog/tasks/20260907-design-agent-activity-client-b6d913e4.md b/.project-docs/30-worklog/tasks/20260907-design-agent-activity-client-b6d913e4.md deleted file mode 100644 index d8612d1..0000000 --- a/.project-docs/30-worklog/tasks/20260907-design-agent-activity-client-b6d913e4.md +++ /dev/null @@ -1,103 +0,0 @@ -# Task: Render AI Design agent activity progress - -## Identity - -- Task ID: 20260907-design-agent-activity-client-b6d913e4 -- Mode: Feature -- Branch: codex/20260907-design-agent-activity-client-b6d913e4-design-agent-activity-client -- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20260907-design-agent-activity-client-b6d913e4 -- Base commit: da29294979da4ce041edf992b590ee6ea170a44f -- Owner: codex-root -- Status: Ready for Integration - -## Scope - -- Consume operation-scoped AI Design activity events through the existing Main-owned - Works Square transport. -- Render one transient activity area attached to the optimistic user message, update - meaningful steps in place, and settle it correctly on final reply or terminal error. -- Cover reconnect/replay, transport-unknown, stale-operation, and compact responsive - presentation without duplicating the right-side Design summary. - -## Intent And Constraints - -- User messages remain immediately visible and final assistant replies remain normal - conversation content. -- Activity is presentation state, not canonical Design state or a durable chat bubble. -- Show at most a few youth-safe phase/action/outcome lines; never render raw reasoning, - tool arguments, prompts, provider output, or technical error details. -- Preserve stable operation identity across uncertain transport outcomes and ignore - progress that belongs to another Workspace/direction/operation. - -## Project Context Loaded - -- Project goal: a youth-friendly desktop creation flow with Electron Main as the only - network authority and server-owned Design Specification semantics. -- Current integrated focus: Living Form V2 and immediate optimistic user messages are - integrated; the experimental `050d78d` progress UI is not assumed present. -- Decisions: ADR-007 keeps Renderer drafts temporary and Gateway operations stable; - the activity view may observe events but cannot become another authority. -- Evidence/commitments: real paid Design production smoke remains separate and is not - claimed by this client presentation task. -- Relevant peers: the Enter-key E2E task is test-only; older generic-error tasks have - undefined scope. No semantic conflict was found. -- Likely modules: Main Workspace adapter/DTO mapping, Renderer store event reduction, - Design conversation pane, and focused unit/Electron E2E tests. -- Unknowns to resolve in source: current stream event DTO shape and the best existing - operation-to-optimistic-message association seam. -- Gate result: Passed. - -## Outcome - -- Added a dedicated `AI 处理过程` panel beneath the optimistic user message. Active - steps update in place; completed processing collapses into a compact, user-toggleable - summary while the final assistant reply continues to stream as normal conversation. -- Added Main-owned normalization for the four public progress stages. Main maps stages - to fixed youth-safe copy instead of trusting arbitrary server/provider text. -- Preserved exact operation association across optimistic, streaming, canonical, and - transport-unknown states by recording the pre-command turn sequence and matching the - earliest exact canonical user turn after that boundary. -- Added Gateway command terminal-event handling so accepted commands converge after a - polling disconnect. WebSocket-terminal-first races remain authoritative, stale - connections cannot mutate current state, duplicate chunks advance the replay cursor, - and late results from another Workspace cannot replace the active Workspace. -- Activity remains transient presentation state: it is filtered by Workspace and - direction, never becomes a chat message or right-side Design authority, and contains - no raw model reasoning, prompts, tool arguments, or technical provider output. - -## Verification - -- `pnpm exec vitest run tests/unit/image-workspace-store.test.ts - tests/unit/image-canvas-page.test.tsx - tests/unit/works-square-design-workspace.test.ts - tests/unit/image-workspace-route.test.ts` — 67 passed. -- `pnpm exec tsc --noEmit` — passed. -- Focused ESLint across all eight changed TypeScript/TSX files — passed. -- `pnpm run build:vite` — passed; only existing chunk-size, dynamic-import, and stale - Browserslist-data warnings were reported. -- `git diff --check` — passed. -- Independent client and lifecycle reviews were repeated after the terminal-race, - exact-turn-association, and Workspace A→B→A fixes — PASS; no reachable P1/P2 - remained. - -## Follow-ups - -- Add an explicit snapshot/cursor reseed contract for a Gateway `cursor expired` - response in a separate transport-resilience task. That pre-existing recovery gap is - broader than the AI activity presentation slice. - -## Promotion Candidates - -- Target canonical documents: ADR-007 and the client/Main transport architecture. -- Proposal: document operation-scoped AI activity as transient Renderer state fed by - Main-normalized public Gateway events; generic Gateway terminal events must settle - uncertain writes without changing operation identity. -- Evidence: fixed public stage projection, exact turn association, terminal/poll race - tests, stale-source and cross-Workspace tests, 67 passing focused tests, typecheck, - lint, and production build. -- Future impact: future Agents SDK lifecycle hooks can reuse the same UI seam, while - canonical Design state continues to come only from Workspace snapshots/events. -- Semantic conflicts: none identified; this preserves ADR-007's Main ownership and - temporary Renderer-state boundaries. -- Human confirmation required: yes, during a future integration-mode promotion to - canonical architecture documentation. diff --git a/.project-docs/30-worklog/tasks/20260907-integrate-design-agent-activity-b7d3f1a8.md b/.project-docs/30-worklog/tasks/20260907-integrate-design-agent-activity-b7d3f1a8.md new file mode 100644 index 0000000..670eb32 --- /dev/null +++ b/.project-docs/30-worklog/tasks/20260907-integrate-design-agent-activity-b7d3f1a8.md @@ -0,0 +1,64 @@ +# Task: Integrate AI Design agent activity UI + +## Identity + +- Task ID: 20260907-integrate-design-agent-activity-b7d3f1a8 +- Mode: Integration +- Branch: codex/20260907-integrate-design-agent-activity-b7d3f1a8-integrate-design-agent-activity +- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20260907-integrate-design-agent-activity-b7d3f1a8 +- Base commit: da29294979da4ce041edf992b590ee6ea170a44f +- Owner: codex-root +- Status: Ready for Integration + +## Scope + +- Integrate client source commit `81b524a02c2cf51304090afa8fb89d27c72c5d2b` from exact base `da29294979da4ce041edf992b590ee6ea170a44f`. +- Promote the operation-scoped AI Design activity projection into canonical client memory. +- Verify Main event normalization, Renderer reconciliation, conversation rendering, and existing Design streaming behavior. + +## Intent And Constraints + +- Render only the server's fixed public lifecycle stages beneath the matching optimistic user message. +- Keep `design.assistant.delta` as the single provisional assistant-text stream and the right-side Living Form as the Current Specification projection. +- Never render raw chain-of-thought, prompt/provider/tool payloads, or a duplicate global “整理进度” banner. +- Preserve stable operation identity and existing unknown-result reconciliation. +- Do not touch or adopt unrelated changes in the root worktree. + +## Outcome + +- Fast-forwarded the exact source commit from the recorded base without conflict. +- Integrated Main-normalized public Design activity, operation-scoped Renderer + reconciliation, terminal-event convergence, and the conversation-attached activity + panel while preserving optimistic user messages and canonical assistant replacement. +- Fixed two integration-review findings: a later chat no longer erases earlier + completed/unknown activity, and each pending operation now renders its user message, + activity, and provisional assistant stream as one ordered group. +- Promoted the accepted transient-activity boundary into ADR-007, architecture maps, + data flow, domain rules, and current integrated state. +- No server contract, database, billing, Quote/Task, navigation, package, deployment, + publication, or Provider behavior changed. + +## Verification + +- `pnpm exec vitest run tests/unit/image-workspace-store.test.ts + tests/unit/image-canvas-page.test.tsx + tests/unit/works-square-design-workspace.test.ts + tests/unit/image-workspace-route.test.ts` — 69 passed. +- `pnpm exec tsc --noEmit` — passed. +- Focused ESLint across all eight changed TypeScript/TSX files — passed. +- `pnpm run build:vite` — passed; only existing chunk-size, dynamic-import, and + stale Browserslist-data warnings were emitted. +- `git diff --check` — passed. +- Independent integration review — PASS after the two multi-operation findings were + fixed and covered. + +## Follow-ups + +- Add an explicit snapshot/cursor reseed contract for a Gateway `cursor expired` + response in a separate transport-resilience task. + +## Promotion Candidates + +- Applied: ADR-007, system overview, module map, data flow, domain rules, and current + integrated state now define operation-scoped public activity as transient + presentation rather than Design authority or model reasoning. diff --git a/.project-docs/40-domain/business-rules.md b/.project-docs/40-domain/business-rules.md index 59ea49f..7aafa36 100644 --- a/.project-docs/40-domain/business-rules.md +++ b/.project-docs/40-domain/business-rules.md @@ -125,6 +125,7 @@ - Direction projection 是 Specification 真值。event cursor、assistant delta、Task progress 与 Asset event 只用于传输/资源收敛,不得推进或覆盖 canonical specification revision。 - 用户提交 chat 后,客户端可以立即把同一个 pending operation 投影为临时用户气泡,并明确显示“发送中”或“正在确认”;只有服务端返回的 canonical turn 才进入 conversation timeline。确定失败时必须让原草稿重新可编辑,不得把临时投影持久化为第二条消息。 - `design.assistant.delta` 只用于未完成回复的传输和结果收敛,不得进入 canonical conversation timeline。客户端可以把它临时显示为与同一 pending chat identity 绑定的单个未完成助手气泡;确定收敛后必须由 canonical turn 替换,unknown outcome 则保留原 identity 与已有片段。不得把片段伪装为完成回复、持久化为第二条消息、因其他 operation 更新而全局清除,或另加独立的整理进度栏。AI 当前整理出的设计理解仍由右侧 Current Specification 投影承载;连接重叠或事件重放按 connection generation 与 `chunkIndex` 去重收敛。 +- `design.assistant.progress` 只能由 Main 把服务端闭集 stage 归一为固定、通俗的活动文案,并附着在同一 pending chat identity 的 optimistic user bubble 下。它是可更新、可折叠的瞬时 presentation state,不是消息、Current Specification、任务授权或模型思考过程;不得显示 chain-of-thought、prompt、Provider response、tool argument、任意服务端文案或未验证模型文本。终态、重连和重放必须按原 operation identity 收敛。 - Main 只向 Renderer 投影已知错误码的固定中文提示,未知上游错误文本必须脱敏为通用提示;Works Token、stream ticket、provider internals 留在 Main/服务端。 - AI 绘画 Workspace JSON 请求与 shared Works token refresh 必须覆盖取凭据、发请求和读取响应 body 的完整 30 秒 deadline;即使底层 transport 忽略 abort,调用方也必须确定性结束为 `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT` 并释放共同等待者。Electron-to-Node 透明 fallback 仅允许 `GET`/`HEAD`/`OPTIONS`;mutation 不得因 transport failure 被隐式重放,任何重试必须由上层显式幂等合同授权。 - `design.quote.request` 必须绑定 exact current Specification revision 并返回 immutable Quote;任何 production-meaning edit 都需要新 revision 与新 Quote。对话或 Current Specification 就绪态可以引导用户请求并查看 Quote,桌面端可定位到报价区、移动端可打开报价面板,但该动作不得创建 Task。 @@ -169,4 +170,4 @@ ## Last Reviewed -2026-09-06 +2026-09-07 diff --git a/src/pages/ImageCanvas/DesignConversationPane.tsx b/src/pages/ImageCanvas/DesignConversationPane.tsx index 63df463..fbf5dcb 100644 --- a/src/pages/ImageCanvas/DesignConversationPane.tsx +++ b/src/pages/ImageCanvas/DesignConversationPane.tsx @@ -172,6 +172,9 @@ export function DesignConversationPane({ const text = assistantStreams[message.operationId]?.trim(); return text ? [{ ...message, text }] : []; }); + const streamingReplyByOperationId = new Map( + streamingReplies.map((reply) => [reply.operationId, reply.text]), + ); const projectedDraft = chatDraft.trim() !== '' && pendingChatMessages.some((message) => message.message === chatDraft.trim()); const composerDraft = projectedDraft ? '' : chatDraft; @@ -290,6 +293,7 @@ export function DesignConversationPane({ {pendingChatMessages.map((message) => { const linkedActivity = activityByOperationId.get(message.operationId); + const streamingReply = streamingReplyByOperationId.get(message.operationId); return (
)} + {streamingReply && ( +