merge: isolate concurrent OpenCode chat runs

This commit is contained in:
2026-08-17 22:28:19 +08:00
34 changed files with 5159 additions and 434 deletions

View File

@@ -4,6 +4,7 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
## Integrated Through
- `6504073`: AI Programming now isolates prompt lifecycle, loading and errors by OpenCode Session. Main serializes only runtime/configuration acceptance, verifies project Agent content against an owned fresh runtime generation before execution, and returns typed terminal pending responses without automatically restarting, reloading or disposing the shared runtime. A run that receives no explicit busy/assistant/terminal acknowledgement within 10 seconds ends only that Session and is never replayed automatically. The application-side isolation is verified; real bundled OpenCode/provider two-Session execution concurrency is not claimed.
- Project-cover source commit `145a6ce571d646325092d1e722282babea503954` from feature task `20260817-project-cover-upload-a6a98e56`, integrated by task `20260813-sync-push-main-9c2f71`. First submission now requires a bounded PNG/JPEG/WebP cover, shows preview/file/reselect feedback, and sends metadata plus cover through Main-owned `POST /api/projects/with-cover`; conflicts stop before version upload and existing draft/published projects remain version-only. The matching Works Square server source is `407c883` (local merge `0cedfc4`). No client package, production deployment, or real-account smoke occurred.
- `3b37ac3` / `55e61b7`: macOS Robot hotspot discovery performs one bounded worker-thread rescan after an empty or SSID-redacted CoreWLAN result; persistent SSID redaction maps to the existing permission error instead of a misleading empty-device state, while firmware and the open `Xiaozhi-*` contract remain unchanged.
- `f5d47c8` / `b6148a5`: AI Programming voice capture is available after an Agent is selected but before the lazy first OpenCode session exists; transcription fills the composer draft without creating an empty session, while runtime, loading, transcribing, busy, and recording guards remain unchanged.
@@ -42,7 +43,7 @@ Makelore 在会话恢复、登录和刷新后由 Electron Main 请求 Works `/ap
AI 学习现在是已启用顶层模块。Renderer 浏览 Works 课程、提交单课生成需求、显示任务进度并打开已安装课程;材料上传经 Main IPC 严格投影,需求最多 4,000 字,文件最多 5 个、单个 50 MiB、总计 150 MiB。Main 持有 Works Token、生成/课程下载/Agent/ASR/课堂 runtime 访问和按认证身份派生的不透明账号分区;账号切换、注销或 epoch 变化会隐藏旧本地课程、关闭旧 player server 并丢弃迟到结果。课程归档最大 512 MiB,只允许同 Works origin、最多 5 跳且不携带资源 Bearer 的下载重定向,按服务端声明大小与 SHA-256 校验后原子安装并在播放前再次校验。安装期和 player server 只允许 MIME/扩展匹配的被动图片、音视频和字体;同源 HTML/SVG/XML/脚本/PDF 被拒绝,运行时响应带 nosniff/sandbox CSP/CORP/no-store。只有显式 `readClassroom` 会注册课程;Agent/runtime 先验证调用前既存 active registration,再用无副作用 resolver 核对本地 aggregate/module,不能靠自身请求注册。HTTP URL/cookie 由短效 nonce 保护;iframe bridge 校验精确 source/origin,只允许初始 player 文档,二次导航后永久关闭。课程 aggregate `contentHash` 是云端权益/进度身份,模块 hash 只作为受控上下文。打包必须提供由固定清单与 SHA-256 验证的 OpenMAIC production Stage 产物;当前客户端自动化不等同于真实 Works 课程服务、生产播放器产物或签名安装包验收。
AI 编程首次发送在新建 OpenCode session 已知为空时不再等待冗余历史读取,prompt 可直接进入 Host API;普通历史会话仍刷新消息。Main AI proxy 只把明确的上游分组饱和投影为当前 OpenCode 的终止状态,配额耗尽保持独立终止态,通用限速继续保留 `429`。上下文压缩以每个 Session 的持久时间线事件呈现:自动与手动压缩使用不同文案,运行态原位弱化显示,完成后静态保留并可从历史恢复;`session.compacted` 只完成对应事件,只有真实 idle 才结束 run 和释放排队消息。
AI 编程首次发送在新建 OpenCode session 已知为空时不再等待冗余历史读取,prompt 可直接进入 Host API;普通历史会话仍刷新消息。每个 Session 独立持有 run、loading、error 与内部队列;一个 Session 的回复或终止不会锁住、改写或重放另一个 Session。Host 接受或用户消息落库不算启动确认,只有明确 busy/retry、assistant、question、permission 或 typed terminal event 才确认/终结启动;独立的 10 秒 watchdog 到期时仅以 `SESSION_START_UNCONFIRMED` 终止该 Session。Main 以 runtime generation provenance、Agent 内容 fingerprint 和 live registry id 共同验证项目 Agent,provider/runtime 或 Agent 未应用时在执行前返回 typed `409` 且 `promptSent:false`。普通 message、command、summarize 和后台 provider sync 不自动重启、reload 或 dispose 共享 runtime;只有显式用户 apply/lifecycle 操作可以推进运行时刷新。Main AI proxy 只把明确的上游分组饱和投影为当前 OpenCode 的终止状态,配额耗尽保持独立终止态,通用限速继续保留 `429`。上下文压缩以每个 Session 的持久时间线事件呈现:自动与手动压缩使用不同文案,运行态原位弱化显示,完成后静态保留并可从历史恢复;`session.compacted` 只完成对应事件,只有真实 idle 才结束 run 和释放排队消息。
Updater 仍由 Electron Main 选择目标 feed、记录原始诊断并保持失败语义。正式稳定源缺少对应平台 manifest 时,设置页只显示一条简洁中文提示并允许重试,不把缺包误报为已是最新版,也不向普通界面暴露堆栈、URL、路径或错误码;签名产物发布和真实升级安装仍属于外部 Release Gate。
@@ -50,6 +51,7 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选
## Recently Completed
- 2026-08-17: Integrated application-side multi-Session isolation for AI Programming. Session A may remain busy while Session B is independently accepted or terminally rejected; errors, startup deadlines and uncertain-failure cleanup stay Session-scoped. Main now fail-closes stale Agent/provider runtime state before execution, applies bounded manager/project FIFO acceptance with revocable timeouts, and never refreshes the shared runtime automatically from ordinary execution paths. Full unit, typecheck, lint, build, focused Electron E2E and independent Sol review passed; a real paid-provider/bundled-runtime concurrency smoke remains pending.
- 2026-08-17: Replaced the temporary coverless-first-create fallback with a required PNG/JPEG/WebP picker, preview, file name, reselect action, Renderer/Main signature and size validation, and one Main-owned multipart metadata-plus-cover create request. Create conflicts fail before version upload; existing project metadata and covers remain unchanged.
- 2026-08-17: Corrected macOS Robot hotspot discovery after a system-visible `Xiaozhi-*` report. CoreWLAN now gets one bounded retry when its first result is empty or all SSIDs are unavailable; a persistent non-empty redacted result becomes the existing safe permission state. Open-only filtering, firmware, Host/Renderer contracts, exact-current-SSID verification, and the system-Wi-Fi fallback are unchanged; signed-package physical smoke remains pending.
- 2026-08-17: Created merge commit `4013edc` for the reviewed per-user module-entry policy source tip `3b799af`. Main exposes only four booleans from `/api/auth/me`; missing fields remain enabled, `design` maps to `painting`, disabled root/deep/alias routes stop before module initialization, Code provider startup waits for policy hydration, terminal `401` clears both session layers, and global settings remains reachable.
@@ -109,6 +111,8 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选
- 客户端对最终构建字节的 loopback 检查没有可信 receipt,且不复刻生产 opaque-origin;服务端必须独立重算 source/built/contract、校验不可变 Release,人工审核仍不可绕过。如未来需要不可绕过的 runtime gate,必须引入可信 verifier 并绑定精确构建产物。
- AI proxy 的明确饱和 `429 → 400` 是与当前 OpenCode 重试契约匹配的内部投影;升级 OpenCode 或上游饱和错误文案变化时必须复核。不得把通用 `429` 或仅含 `rate_limit_exceeded` 的响应误分类为终止饱和。
- AI 编程压缩事件必须按 Session、run token、runtime generation 与 native Part/event identity 关联;`session.compacted` 不等于 `session.idle`,历史 hydration 不得把 completed 降回 running,失败或中止必须清理本 run 的未完成事件。
- AI 编程多 Session 隔离只证明应用提交、状态、错误、超时和队列互不污染,不证明 bundled OpenCode 或真实 provider 会并行执行两个模型 turn。任何产品或性能结论都必须保留上游可能串行、限流或拒绝的边界。
- 项目 Agent 与 provider/runtime freshness 必须在 Main 的 bounded acceptance 临界区内验证。普通 message、command、summarize 和后台同步不得自动重启、reload 或 dispose 共享 runtime;同 id 不能证明同内容已经加载,attached/unknown runtime generation 必须 fail closed。
- AI 绘画单图选择器仍精确匹配 quick reply `从作品列表选择图片`,用途再从当前 Brief medium 推断;本地化或协议文案变化可能破坏入口。扩展更多素材输入前应升级为结构化 action/purpose。
- Updater 源码错误提示不能代替发布正式签名产物;稳定 feed 缺 manifest 必须保持失败,Renderer 不得展示原始堆栈、URL、路径或错误码。升级链只有在旧版本完成发现、下载、重启和安装 smoke 后才可视为生产就绪。