feat(web): introduce initial external Web workbench framework - #326
feat(web): introduce initial external Web workbench framework#326somewan820 wants to merge 8 commits into
Conversation
tt-a1i
left a comment
There was a problem hiding this comment.
基于 exact head 01faec23264d0a6b205acfc1e30a308004f5b102 请求修改。方向有价值,但当前存在可复现的运行时阻塞:
/api/prompt在 Pi preflight 前即发布prompt_accepted并返回202 accepted:true;即使运行时明确拒绝,客户端仍收到 accepted。accepted receipt 必须证明 admission,而不是仅证明 Host 收到请求。sendPrompt()等待前一 admission 后才读取this.runtime。请求在 Session A 排队、等待期间切换到 B 时,会实际投递到 B,但 trace 仍属于 A。命令必须绑定请求时的 runtime/session,或在 admission barrier 后按 expected session fail closed。- 每个 AgentSessionRuntime 都安装一个进程全局 Undici dispatcher。切换后释放新 runtime 的 lease,会让全局 dispatcher 继续指向已关闭实例;已复现后续 fetch 失败
UND_ERR_DESTROYED。该资源应由整个 Web 进程统一拥有。 - Web capability registry 以进程级
kind -> provider存储,没有 Session/runtime provenance;保留旧 runtime 时可把旧 Session 的 Subagent/Background Terminal 状态投影到当前 Session。 - 文档承诺 cursor/Last-Event-ID、gap detection 与
409 RESYNC_REQUIRED,实现却在每次 SSE 连接无条件重放最近 200 条,客户端既不提交 cursor,也不在正常 EOF 重连,可能重复、静默丢失或永久陈旧。 - Session 索引、message parts 聚合、SSE client/queue/backpressure 没有完整硬上限,与本 PR 自己的 bounded protocol/host 契约不符。
- UI 从结果文字中的
fail/error/uncertain猜 canonical 状态;历史 Session “只读”、短期 token exchange 等文档表述也与实现不一致。 - Issue #325 将视觉 polish、移动端和交互一致性列为后续工作,但第二提交又扩大到主题、动画和名为“编辑”实为重发的交互;建议缩小或拆分,避免框架 PR 同时承担大面积产品 polish。
验证:bun run check 通过;Web 16/16;完整 Node 1102 通过、1 跳过;Vitest 30/30。另有三个独立最小复现确认 false accepted、A->B prompt 错投和 closed global dispatcher。测试绿不能覆盖这些并发/恢复缺口。建议保持 Pi-native:不新增第二套 runtime,只收紧现有 Host、AgentSessionRuntime、SSE 和 projection 的权威边界。
|
已在 exact head
提交拆分:
验证: 旧 review 绑定 |
|
自审补充:在前三个 review 修复提交之后,又确认并修复了一个 fail-closed 异常路径。若底层 prompt operation 正常 settle、但 Pi 从未调用
当前 exact head 为 |
Add the local Web entrypoint, workspace and session UI, runtime event projection, dispatcher lifecycle leases, and metadata persistence. Clean obsolete UI and unused code, fix concurrent prompt attribution and atomic writes, and add regression coverage and development documentation. Refs openpi-dev#325
- pi.dev-style engineering grid background with paper reading lane - frosted-glass sidebar, hover transitions, menu/dialog motion - landing OpenPI brand animation (tetromino assembly, collision, sink) - favicon from pi.dev - protocol projection keeps toolCallId/isError/details/custom messages - subagent/workflow activity cards + live capability chips - tool lines with icons and summaries, step grouping, thinking timer - message copy/edit actions, turn rail navigation, stick-to-bottom - settings: language + theme (PI grid / clean white / midnight) - CJK bold markdown extension; vm-based app render smoke test
Wait for Pi preflight before accepting prompts, fail closed across session replacement, and keep the process dispatcher alive until every runtime lease releases it.
Bind capability providers to their owning Pi session and enforce bounded session, entry, message-part, event, client, and queue projections.
Return prompt receipts only after admission, bound SSE clients and queues, replay from cursors with explicit resync, and render canonical runtime states without text guessing.
Fail closed when a prompt operation settles without invoking Pi's admission callback instead of inferring acceptance from operation completion.
e7ec5f1 to
b0dac01
Compare
|
@somewan820 已在你最新的 当前 exact head:
麻烦你重点复核最终方案是否保持了原始产品意图:Pi 仍是 Session/模型/执行事实来源;Web 只做有界投影与串行控制;prompt/Session epoch、SSE cursor、metadata transaction、Host lease/shutdown 的 fail-closed 边界;以及 theme/settings/edit 等额外复杂度的收窄。 你是 PR 作者,GitHub 不能用自己的 approve 满足独立审批门槛;请先回复确认或指出异议,之后由另一位有 write 权限的 reviewer 完成正式 approve。 |
|
已基于 exact head 确认最终方案保持了原始 Pi-native 产品意图:
本地验证: 我确认没有异议。作为 PR 作者不提交自我 approval,请由另一位有 write 权限的 reviewer 完成独立 approval。 |
Problem
OpenPI needs a first local external Web workbench without creating a second agent runtime or weakening Pi's Session, model, trust, tool, extension, and lifecycle ownership. The original implementation established the product surface, but prompt admission, retained runtime provenance, metadata concurrency, SSE recovery, shutdown, resource bounds, and browser state still had race and fail-open paths.
Closes #325
Value
Delivers a usable local Web workbench whose browser-visible state remains a bounded projection of authoritative Pi state. Prompts cannot cross Session boundaries, a second Host cannot concurrently mutate the Web Session store, reconnects cannot silently skip state, and shutdown cannot release ownership while an admitted metadata mutation is still running.
Approach
openpi webprocess with PiAgentSessionRuntimeas the execution authority; do not add another provider stack, Session store, orchestration layer, or persistent Web preference system.SessionManager; expose only typed, bounded activity summaries without private transcript or output payloads.409 RESYNC_REQUIRED; stale same-epoch snapshot responses cannot overwrite newer state..openpi-web-host.artifacts/container. Ordinary Session files are not scanned or counted; artifact and stale-fence caps fail closed with explicit operator recovery instructions.sessionStorageand clear the address bar. Render remote Markdown images as inert links and keep the Host loopback-only.npm packinstallations run independently of the source checkout.Validation
bun run checkbun run test: Node 1224 passed, 1 skipped; Vitest 30 passedgit diff --check upstream/main2614b9b(mainat push time); GitHub reportsMERGEABLEwith no code conflictnpm pack-> install ->openpi web --no-open: passed; packaged/and/marked.jsreturned successfully1280x800and mobile390x844New-head GitHub CI is required; local validation is not a substitute for protected checks or independent approval.
Impact