合并 AI 设计多会话客户端
Some checks failed
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled

整合 Enter 发送与多会话交互,保留服务端持久 Conversation Session,并补齐迁移、回归、Electron E2E 与 canonical 文档。
This commit is contained in:
2026-08-11 16:18:52 +08:00
32 changed files with 2417 additions and 804 deletions

View File

@@ -0,0 +1,43 @@
# ADR-001: AI 绘画 Workspace / Conversation 状态归属
## Status
Accepted
## Date
2026-08-11
## Context
旧客户端把一个 AI 绘画 Workspace 等同于一条持续对话,并由客户端按 Workspace 创建和回收临时 Agent Session。多会话产品模型要求同一设计项目内存在多条独立对话同时保留项目级生成任务与资产。继续沿用旧 Session 所有权会让注销时的远端 DELETE 破坏 Conversation 的持久上下文。
## Decision
- Workspace 持有项目身份、Conversation 列表、生成任务和资产。
- Conversation 持有消息、Brief、Quote、`turnRevision` 以及服务端持久 Agent Gateway Session 的绑定。
- 新建 Conversation 不创建新 Workspace切换 Conversation 只读取该对话并重连其事件流,项目级任务和资产保持可见。
- Conversation 异步与流式更新必须同时校验 Workspace + Conversation 身份Task 更新按 Workspace 归并。
- 客户端不创建、旋转或在注销/退出时 DELETE 服务端持久 Conversation Session。终端清理只关闭本地流、清除本机 Session-id 缓存和本地凭据;后续访问重新从 Conversation API 读取 Session。
- 未打包的本地开发适配器把旧单会话 schema v2 迁移为带默认 Conversation 的 schema v3该适配器不得成为打包应用的云端失败回退。
## Rationale
该分层与用户可见的“一个设计项目,多条独立会话,共享生成结果”一致,并让 Session 生命周期由持久化 Conversation 的服务端权威管理。Workspace + Conversation 双重身份和 generation/revision 防护可以阻止切换过程中的迟到异步结果污染当前对话。
## Consequences
- 客户端发布前必须先部署服务端迁移 `0033` 与多 Conversation API。
- 退出登录不会删除远端 Conversation Session服务端继续通过认证与授权控制访问。
- Renderer、Host API、云端适配器和本地开发适配器都必须保持相同的 Workspace / Conversation / Task 所有权语义。
- Conversation 数量增长后可能需要分页和搜索;当前侧栏只内联展示近期会话。
## Supersedes
- 旧的未文档化“每个 Workspace 由客户端创建并在注销时删除临时事件 Session”实现。
## Related
- `498089401708dc08123141891dba9b54e47cefea`
- `03dae62cf35d643bba253d1013579cc3f4f528e4`
- `.project-docs/30-worklog/tasks/20260806-design-multisession-ui-4e7d.md`

View File

@@ -4,6 +4,7 @@
| ID | Decision | Status | Date | Applies To | Detail |
|---|---|---|---|---|---|
| ADR-001 | AI 绘画采用 Workspace / Conversation / Task 分层状态与服务端持久 Conversation Session | Accepted | 2026-08-11 | AI 绘画客户端、Main 适配器、Works Square API | `adr-001-ai-design-conversation-ownership.md` |
## Superseded Decisions

View File

@@ -10,6 +10,9 @@
| 提交绑定 | 云端成功上传响应 | Main → submission binding v2 | 只持久化成功的 app/version/review/hash落盘失败返回固定告警但不反转提交 |
| 运营发布 | Works Square 审核与交付 | 公共 `play_url` | 客户端只消费服务端发布结果;真实 Builder → OSS/CDN 生产链仍待整链验收 |
| 真机预览 | 项目空间 | Main → Owner preview / `play_url` | 核对 app、version、release 和同源 HTTPS`runtime_url` 仅一版本兼容回退 |
| 设计会话创建/切换 | AI 绘画页面或侧栏 | Renderer API → Main → Workspace Conversation API | 新会话属于现有 Workspace读取独立消息、Brief、Quote 和 `turnRevision` |
| 设计消息与确认 | 当前 Conversation | Main → 持久 Agent Gateway Session → Conversation 快照 | 请求和流式结果同时绑定 Workspace + Conversation |
| 设计任务同步 | 任一 Conversation 的事件流 / REST | Renderer Workspace 任务列表 | Task 和 Asset 按 Workspace 归并,切换 Conversation 后仍可见 |
## State Ownership
@@ -17,13 +20,17 @@
- 项目内 `.niancode/project.json` 保存 `ProjectType`Main 在配置写入和目录复用时保持其不可变,并在打包时重新读取校验。
- Renderer 仅持有短效公开会话状态、提交展示状态和安全投影后的公共播放/短时预览 URL。
- 旧 schema v1 `submitted` 记录迁移并保留;旧 `armed``waiting_for_package``waiting_for_login``uploading``failed` 归一为 `legacy_retired`,不再启动 watcher 或上传任务。
- AI 绘画 Conversation 持有消息、Brief、Quote、`turnRevision` 和服务端 Session 绑定Workspace 持有 Conversation 列表、生成任务和资产。
- 本地开发适配器将旧单会话 schema v2 原子迁移为带默认 Conversation 的 schema v3打包应用不使用该本地适配器作为云端失败回退。
- 注销和退出会关闭本地事件流并清除本机 Conversation Session-id 缓存;服务端持久 Session 保留,下一次访问从 Conversation API 重新读取。
## External Interfaces
- Works Square 项目创建、版本上传、构建状态、Owner 状态与 Release preview API。
- 本机 Host API 的发布与真机预览路由;发布路由要求 Renderer capability。
- 服务端安全投影后的公共 `play_url`;只接受同源 HTTPS、精确 App 路径和可信版本状态。
- Works Square Workspace/Conversation API、每个 Conversation 的 Agent Gateway Session 与单次 WebSocket ticket。
## Last Updated
2026-08-10
2026-08-11

View File

@@ -11,6 +11,13 @@
| `electron/services/works-submission-binding.ts` | submission binding v2 持久化与旧 schema 迁移 | 旧中间态终止为 `legacy_retired`;文件名暂作安装兼容 |
| `electron/api/works-play-url.ts` | 公共播放与 Owner preview URL 的共享安全校验 | 公共 `play_url` 必须同源 HTTPS 且精确匹配 App 路径 |
| `electron/api/routes/device-preview.ts` | 精确提交版本的待审/已发布真机预览解析 | 待审使用短时 Release preview已发布优先 `play_url` |
| `shared/image-workspace.ts` | AI 绘画 Workspace、Conversation、Task、Asset 与事件共享契约 | Conversation 状态与 Workspace 任务归属必须分离 |
| `electron/api/routes/image-workspace.ts` | AI 绘画 Host API 与本地事件流投影 | Renderer 只通过该路由访问 Main-owned workspace adapter |
| `electron/image-workspace/works-square-workspace.ts` | Works Square 多 Conversation 云端适配器与 Gateway 事件映射 | 使用服务端持久 Session本地清理不 DELETE 远端 Session |
| `electron/image-workspace/local-workspace.ts` | 未打包开发模式的本地 Workspace 适配器和 v2→v3 迁移 | 仅开发使用,不得成为打包回退 |
| `src/stores/image-workspace.ts` | 当前 Workspace/Conversation、项目任务及流式更新状态 | 异步结果按 Workspace + Conversation generation/revision 防护 |
| `src/pages/ImageCanvas/index.tsx` | Conversation 对话、Quote 确认、统一任务列表与新会话入口 | Enter 发送、Shift+Enter 换行、IME 保护 |
| `src/components/layout/ImageWorkspaceSidebar.tsx` | Workspace 与近期 Conversation 切换/创建 | 切换会话不清空项目级任务 |
## Dependency Direction
@@ -22,7 +29,9 @@
- `electron/api/routes/works.ts` 同时承担发布 capability、上游安全投影和错误脱敏变更时必须验证未在拒绝前读取凭据或项目文件。
- `works-cloud-deploy.json` 是兼容文件名;不得因名称重新引入自动部署协调语义。
- `runtime_url` 是一个客户端版本的迁移回退;删除前必须确认服务端和存量数据稳定提供 `play_url`
- 多 Conversation 事件处理必须区分对话快照与 Workspace 任务更新;不得用任务时间戳推进 Conversation 流水位,也不得让旧会话的迟到流覆盖当前会话。
- `closeEventSessions` 只负责本地流和缓存生命周期;远端 Conversation Session 是服务端持久资源。
## Last Updated
2026-08-10
2026-08-11

View File

@@ -16,6 +16,9 @@ Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展
| Submission Binding | 保存云端已接受的精确 app/version/review/hash 绑定 | schema v2 只记录成功提交;旧中间态迁移为 `legacy_retired`,不恢复后台任务 |
| Play URL Projection | 校验服务端公共播放地址 | 只接受同源 HTTPS 和精确 `/apps/{app_id}/`;优先 `play_url``runtime_url` 仅一版本回退 |
| Device Preview | 核对本地绑定、远端版本和 Release | 待审使用短时 Owner preview已发布使用安全投影后的 `play_url` |
| AI Design Workspace | 保存项目身份、Conversation 列表、生成任务和资产 | 任务和资产在切换 Conversation 后继续可见 |
| AI Design Conversation | 保存消息、Brief、Quote、`turnRevision` 与服务端 Agent Session 绑定 | 同一 Workspace 内互相隔离Session 由服务端持久化 |
| AI Design Event Routing | Main 云端适配器 → Host API/SSE → Renderer store | Conversation 更新按 Workspace + Conversation 路由;任务更新按 Workspace 归并 |
## Important Boundaries
@@ -27,11 +30,14 @@ Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展
- 公共播放投影只有在上游 `playable === true`、版本名非空且 URL 通过同源 HTTPS、无 userinfo/loopback、长度、精确路径和无 query/fragment 校验时才可播放;不可信数据 fail closed。
- Renderer 只能获得安全状态字段和可展示的播放/短时预览 URL不得持有发布凭据、归档路径或自动部署状态。
- 落盘文件名 `works-cloud-deploy.json` 仅为已安装客户端的数据兼容;领域模型和代码接口是 submission binding不表示仍存在 cloud deployment coordinator。
- AI 绘画中,一个 Workspace 可包含多条 Conversation消息、Brief、Quote 和 `turnRevision` 属于 Conversation生成任务和资产属于 Workspace。新建 Conversation 不得隐式创建新 Workspace。
- 每条 Conversation 复用服务端持久 Agent Gateway Session。客户端不得在注销或退出时 DELETE 该 Session只关闭本地事件流并清除本机 Session-id 缓存,重新访问时从 Conversation API 刷新。
- Renderer 的异步与流式状态必须同时校验 Workspace + Conversation 身份;项目任务事件只按 Workspace 归并,避免切换会话时丢失任务或接收迟到消息。
## Related Decisions
- 当前长期边界记录于 README、集成任务 `20260807-integrate-login-client-a4f8`、源任务 `20260810-static-release-only-a91c` 及本次 Integration Gate后续如改变唯一入口、凭据所有权或重新引入客户端部署协调器应新增 ADR。
- 当前长期边界记录于 README、ADR-001、集成任务 `20260807-integrate-login-client-a4f8`、源任务 `20260810-static-release-only-a91c` 及本次 Integration Gate后续如改变唯一入口、凭据所有权、Conversation 状态归属或重新引入客户端部署协调器,应新增 ADR。
## Last Updated
2026-08-10
2026-08-11

View File

@@ -9,17 +9,21 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
- `1a19ad9` / `f02e99e`:项目真机预览、待审 Release Owner preview 及集成提交。
- `493b31c`:客户端三类 `ProjectType`、小游戏/小程序受控发布模板与自定义项目发布隔离。
- `4df0477` / `8dd99c1`:客户端静态发布唯一链路、旧 Compose 协调链退役及安全边界补强。
- `4980894` / `03dae62`AI 绘画 Enter 发送及同一 Workspace 下的多 Conversation 客户端模型。
## Current Focus
客户端面向非专业用户提供“创建小游戏或小程序 → 项目配置中一键提交 → Main 安全打包上传 → 轮询云端构建 → 运营审核”的唯一创建者链路,并以项目级真机预览完成待审版本扫码验收;自定义和缺少类型字段的旧项目不提供该入口。已发布作品优先使用安全投影后的 `play_url``runtime_url` 仅保留一个客户端版本的兼容回退。
AI 绘画的一个 Workspace 可包含多条 Conversation。消息、Brief、Quote 和 `turnRevision` 随 Conversation 隔离;生成任务和资产保持 Workspace 级共享。每条 Conversation 使用服务端持久 Agent Gateway Session切换会话只重连对应事件流。
## Recently Completed
- 2026-08-08合并登录续期、一键发布和真机预览发布成功后保存精确 app/version/review 映射Renderer 不接触 Token、ZIP 或本地路径。
- 2026-08-08补齐跨平台 Electron E2E fixture、Windows ZIP 预检和异常成功响应安全投影。
- 2026-08-09新建项目支持小游戏、小程序和自定义三类不可变产品类型前两类生成固定 Vite 发布模板,自定义及缺少类型字段的旧项目不显示一键提交入口。
- 2026-08-10删除客户端旧 Compose deploy-check、watcher/arm/upload 协调和手工 ZIP 路由submission binding v2 保留旧 `submitted` 绑定并把旧中间态归一为 `legacy_retired`,同时补齐 Renderer capability、`play_url` 安全投影和本机绑定失败告警。
- 2026-08-11AI 绘画支持在同一设计项目内创建和切换多条独立 Conversation保留项目级任务/资产,并使用 Workspace + Conversation 身份保护异步与流式更新。退出时关闭本地流并清除本地 Session-id 缓存,不删除服务端持久 Conversation Session。
## In Progress
@@ -44,7 +48,9 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
- `works-cloud-deploy.json` 仅是已安装数据的兼容文件名,不代表客户端仍拥有自动部署协调器;旧中间态不得恢复为后台任务。
- 刷新凭据、发布 Token、ZIP、幂等键和重试只能由 Electron Main 持有。
- 本地 `projectType` 只决定产品分流和模板选择,不得作为授权依据或替代 Main/服务端的包体校验。
- AI 绘画消息、Brief、Quote 和 `turnRevision` 必须按 Workspace + Conversation 隔离;任务事件仍按 Workspace 归并,迟到的异步结果不得污染已切换的会话。
- 服务端持久 Conversation Session 不由客户端在注销或退出时删除Main 只关闭本地流、清除本机缓存并撤销本地凭据。
## Last Updated
2026-08-10
2026-08-11

View File

@@ -0,0 +1,67 @@
# Task: Merge all completed code into main
## Identity
- Task ID: 20260811-merge-all-code-a7c91e
- Mode: Integration
- Branch: main
- Worktree: D:\Datas\OthersProjects\makelore
- Base commit: 70e0f4054cf88029e3f2f4848e3d17ee3be70b7f
- Owner: codex
- Status: Completed
## Scope
- Integrate every completed local branch whose commits are not already contained by `main`.
- Merge `codex/20260806-design-multisession-ui-4e7d-design-multisession-ui`, which already contains the completed Enter-to-send commit from `codex/design-enter-send-b83f`.
- Preserve all behavior already integrated on `main`, resolve overlapping image-workspace changes semantically, and avoid merging stale or already-contained branches a second time.
- Promote the accepted multi-conversation client-state model into canonical project memory and verify the integrated result.
## Intent And Constraints
- Treat Git ancestry as the source of truth for merge scope: only two local branch tips are not contained by `main`, and the multi-session branch is a strict descendant of the Enter-to-send branch.
- Preserve Main/Host API ownership boundaries, project-scoped generation tasks, Conversation-scoped messages and streams, and the existing release/login behavior already on `main`.
- Do not resolve meaningful conflicts with blanket `ours`/`theirs`; combine both sides according to their domain ownership.
- Use the exact pnpm version pinned by `packageManager` and run focused tests before repository-level verification.
- Keep unrelated historical encoding damage and stale worktrees out of this integration.
## Plan
1. Inspect branch ancestry, overlapping paths, and merge-conflict semantics.
2. Merge the multi-session branch once; resolve conflicts while preserving both feature and integrated-main behavior.
3. Update task-scoped and canonical integration records.
4. Run focused AI Design tests, typecheck, lint, production build, and the full unit suite.
5. Obtain an independent read-only Sol review, finish drift checks, and commit the integration.
## Outcome
- Verified that `03dae62` is a descendant of `4980894`; merging the multi-session branch once integrates both completed branch tips without duplicating Enter-to-send.
- Resolved the only two textual conflicts in the Works Square AI Design adapter and its focused test. Human confirmation selected the persistent Conversation Session model: logout and shutdown close local streams and clear the local Session-id cache without deleting the server-owned Session.
- Integrated Conversation create/read/list routing, Conversation-scoped messages and streams, Workspace-scoped generation tasks, local schema v2-to-v3 migration, and the Canvas/sidebar create-and-switch interactions.
- Added focused API, route, adapter, migration, store, page, and sidebar regressions plus an Electron E2E that creates and switches Conversations while preserving project tasks and isolating messages.
- Updated README and canonical project memory, including ADR-001, architecture/data-flow/domain ownership, the production migration commitment, and stale production-verification state.
- Kept the two source-task records read-only in source commit history instead of copying them into the integration tree, as required by the current project-doc ownership gate.
## Verification
- Branch ancestry: `03dae62` contains `4980894`; no other local branch tip contains commits absent from the integrated merge scope.
- Focused AI Design regressions: 8 files / 116 tests passed.
- `pnpm run typecheck`: passed.
- Scoped ESLint over all changed TypeScript and TSX files: passed.
- `pnpm run build:vite`: passed; Renderer, Main, and Preload production compilation completed.
- New multi-conversation Electron E2E: 1 passed.
- `pnpm test`: 140/142 files and 1506/1508 tests passed. One failure is the pre-existing missing `.opencode/agent` fixture; the OpenCode port-release test timed out only in the parallel full run and passed alone.
- `pnpm run lint:check`: repository baseline remains red on the pre-existing `MainLayout.tsx` state-in-effect rule and unused `rerender` in `chat-command-dialogs.test.tsx`; changed-file ESLint is green.
- `pnpm run test:e2e`: 11 passed / 11 failed. The new multi-conversation spec passes; stale legacy selectors and a missing provider test IPC handler account for the remaining existing suite failures.
- `check_project_docs.py`, task-aware `check_doc_drift.py`, and `git diff --check`: passed.
- Independent final read-only Sol review: PASS with no blocking findings.
## Follow-ups
- Deploy and verify server migration `0033`, persistent Conversation Session creation, and multi-conversation APIs before releasing this client behavior to production.
- Repair the unrelated repository lint, missing youth-skill fixture, timing-sensitive OpenCode unit test, and stale legacy Electron E2E baseline in separate maintenance tasks.
- Tighten the global `creatingConversation` guard with a request generation/token if concurrent Workspace switching during Conversation creation becomes observable; the current edge case can briefly re-enable duplicate creation but does not overwrite data.
## Promotion Candidates
- None recorded.

View File

@@ -15,12 +15,17 @@
- 已发布作品优先读取 `play_url`,只有字段缺失时才使用一个客户端版本的 `runtime_url` 回退。公共播放 URL 必须是 Works Square 同源 HTTPS、无 userinfo/loopback、精确 `/apps/{encodeURIComponent(app_id)}/`、无 query/fragment且上游明确 `playable === true` 并提供非空版本名;否则按不可播放处理。
- `works-cloud-deploy.json` 仅是已安装客户端的数据兼容文件名,不表示客户端仍提供 cloud deployment coordinator。
- Works Square 会话按真实键盘、鼠标或触摸活动滑动续期,连续 7 天未使用才要求重新授权。
- 一个 AI 绘画 Workspace 可以包含多条独立 Conversation新建 Conversation 不得创建新 Workspace。
- Conversation 持有消息、Brief、Quote 和 `turnRevision`;生成任务和资产属于 Workspace切换 Conversation 后必须继续可见。
- 每条 Conversation 使用服务端持久 Agent Gateway Session。客户端注销或退出时只关闭本地流并清除本机 Session-id 缓存,不删除服务端 Session。
- Conversation 异步与流式更新必须同时核对 Workspace 和 Conversation 身份;任务事件按 Workspace 归并。
## Open Questions
- 生产整链需要真实账号、Builder、OSS immutable Release、CDN/Edge、运营审核、App 播放与监控环境完成最终验收;当前客户端验证不能替代该验收。
- 在一个客户端兼容版本且服务端与存量数据稳定提供 `play_url` 后,移除 `runtime_url` 回退。
- 多 Conversation 客户端发布前需确认服务端迁移 `0033`、Conversation API 与持久 Session 契约已经部署。
## Last Reviewed
2026-08-10
2026-08-11

View File

@@ -9,3 +9,6 @@
| `legacy_retired` | 旧自动部署中间态迁移后的终止状态 | 不恢复 watcher、登录等待或自动上传提示用户从项目配置重新提交 |
| `play_url` | 服务端为已发布作品提供的公共播放地址 | 客户端优先使用并执行同源 HTTPS、精确 App 路径和版本状态校验 |
| `runtime_url` | `play_url` 上线期间的旧公共播放字段 | 仅保留一个客户端版本的兼容回退,稳定迁移后删除 |
| AI Design Workspace | 一个 AI 绘画设计项目 | 持有 Conversation 列表、生成任务和资产;不是单条对话 |
| AI Design Conversation | Workspace 内一条独立设计对话 | 持有消息、Brief、Quote、`turnRevision` 和服务端持久 Agent Session 绑定 |
| Persistent Conversation Session | 服务端为 Conversation 持久保存的 Agent Gateway Session | 客户端只重连事件流,不在注销或退出时 DELETE |

View File

@@ -4,6 +4,7 @@ Use this index for searchable, traceable evidence records.
| Date | Topic | Status | Source | Detail |
|---|---|---|---|---|
| 2026-08-11 | AI 设计多会话客户端集成 | 本地功能验证通过;仓库基线仍有既有失败 | `30-worklog/tasks/20260811-merge-all-code-a7c91e.md``4980894``03dae62` | 8 files / 116 focused tests、typecheck、changed-file ESLint、production build 与新增 Electron E2E 通过;生产 migration 0033/API 尚待验收,全量 lint/unit/E2E 的既有失败已单独记录 |
| 2026-08-10 | 客户端静态发布唯一链路 | 本地验证通过 | `30-worklog/tasks/20260810-static-release-only-a91c.md``4df0477``8dd99c1` | 227 项聚焦回归、typecheck、Vite/Electron build、实际 Electron E2E 与 13 files / 21 tests 收集通过;不等同于真实生产部署验收 |
## When To Add Evidence

View File

@@ -6,6 +6,7 @@ Track future-facing memory: promised follow-ups, unfinished loops, timed checks,
|---|---|---|---|---|---|
| 2026-08-10 | 完成客户端提交到 App `play_url` 播放的真实生产整链验收 | 服务端 Builder、OSS immutable Release、CDN/Edge 与 App 消费链成组集成后 | 客户端/服务端集成 | Pending | 使用真实账号执行小游戏和小程序创建、提交、浏览器门禁、运营批准、CDN 发布、App 播放与监控核对 |
| 2026-08-10 | 删除客户端 `runtime_url` 兼容回退 | 一个客户端兼容版本结束,且服务端与存量数据稳定提供 `play_url` | 客户端 | Pending | 删除类型字段、读取分支和对应回归测试 |
| 2026-08-11 | 部署并验收 AI 绘画多 Conversation 服务端契约 | 发布包含多会话客户端之前 | 客户端/服务端集成 | Pending | 确认迁移 `0033`、Conversation list/create/read/turn/confirm API、持久 Agent Session 与事件字段已上线 |
## Use

View File

@@ -10,6 +10,7 @@ This is the integrated registry of stale or conflicting canonical memory. Update
## Missing Context
- 尚未验证真实生产环境是否已部署 Builder → OSS immutable Release → CDN/Edge也未完成运营审核到 App `play_url` 播放的真实整链证据;客户端本地与模拟上游验证不能替代该结论。
- 尚未验证生产 Works Square 已部署迁移 `0033`、多 Conversation API 与对应持久 Agent Session 契约;合并客户端代码不等同于具备生产发布条件。
## Feature Task Routing