Repository navigation
fix(desktop): share the machine Core and original steward across App entrypoints - #7328
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent · GPT-6 · OpenAI · self_reported
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
已有 Bot 的用户打开桌面 App 或在概览提问时,需要看到并继续同一份原管家对话与委派。
原来窗口默认另起服务,概览还会发送到普通管家;结果看似回答成功,原会话却没有这条请求。改后普通窗口使用机器服务,概览与对话共用已选原来源。
合成真实 Core 的对照中,同一概览提问在基线原会话出现零次,在当前实现中恰好出现一次;排队追问与中断也由同一原 Session 处理。
本增量不合并不同私聊历史、不扩大权限,不宣称完成长文附件、回复关系和游标同步。
原生安装、重开和原服务身份仍需在采用阶段独立读回;完整双端同步与首次常驻安装资格继续保留。
改动思路
本次最小可用修复同时覆盖两个真实入口:原生窗口先连接既有机器 Core,概览和对话再从同一个 Core 解析原来源。只改前端会留下原生独立存储,只改端口又会留下概览普通会话。复制历史、增加同步桥或服务注册框架会带来第二份状态和维护成本,因此没有采用。
绑定、权限、Session 与排队规则继续由 Core 持有;前端只派生读取状态,原生 supervisor 只处理已核验服务和自己真正拥有的子进程。必需的身份或服务失败会阻止该操作,但不会阻断无关 Goal 导航。来源选择继续归Core,前端只派生展示,原生supervisor只拥有自己的子进程。
交付默认服务与概览原来源路径,并完成隔离后端验证;随后由既有同步验收完成安装与读回。
这是当前 PR 保留机制的决定性理由:共享已有 owner,不把投影变成执行权威。已存在的来源选择直接复用,普通使用没有增加确认轮次;开发者隔离才需要明确环境选择。
| 场景 | 旧路径 | 当前路径 |
|---|---|---|
| 普通 App 启动 | 私有端口与独立服务 | 机器8766/8767,核验后复用 |
| 已选原来源的概览提问 | 普通管家 | 原 binding 与 Session |
| 来源不可用 | 概览可能绕过 | 禁止发送,重试或会话设置 |
| 排队后中断 | 活动控件可能被隐藏 | 保留活动回合,使用原会话 key |
此表是对 56dd9dc76b2594a6894eeb9c779530ea0520ebd3 源码的说明,执行证据另见下文。
具体改动
规范依据为 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,修订 ea1421812bab0c12da858a4216c6b9270ce16572。依据采用修改前的原会话、拒绝回退、路由隔离和队列语义;本 PR 新增的桌面交付检查点是披露未闭资格,不是重写规范来证明实现。
映射标签 original-private-entry、source-failure、route-isolation、single-core-queue 已实现,分别由原 Session HTTP 读回、拒绝与恢复、显式 Goal 路由、排队中断验证。installed-delivery 延后至采用阶段完成实际安装、重开和原服务读回;完整附件、回复关系与游标同步仍在现有同步验收中,不由本次合并关闭。
关键代码讲解
ServiceEndpoints::for_window把普通窗口默认值改为机器端点,只有明确的1才分配私有端点;非法值在启动前拒绝。lib.rs的普通发布入口实际调用它,避免只修测试工具或浏览器。connect_service沿用运行时指纹、外来进程拒绝和标准 LaunchAgent 归属。新增已声明但未加载的检查,防止原服务暂不可用时转为默认空存储。ServiceSet::recover_exited以真实 owned 子进程作为恢复依据,两种端点模式均保留恢复;借用服务没有 owned child,不能因此取得停止或重启权。测试保留健康 peer、冻结身份、占用拒绝和恢复间隔。useAppStewardTarget提取既有只读解析,路由或来源变化立即使旧读取失效;请求有五秒边界,失败不等于没有选择。Conversation 与 overview 共用它。PersonalGoalHome仅在本机未绑定管家概览启用解析,原 Goal/project/显式绑定/受管/远端只读路径保留。entryGate禁止未核验发送和恢复,PersonalWorkspacePage继续复用原历史、composer 和 Core 队列。概览托盘保留 pending 回合,取消与中断使用实际 conversationKey;设置文案同步为整个 App 管家。
全差异为16个文件、260增73删,其中四张图为合成产物,没有运行日志、存储副本或私有状态。局部维护改进是把单入口解析提为共享 hook,并把恢复规则收敛到已有 owned 集合,而非增加新的执行抽象。
对主干的风险
最强反例是浏览器测试通过,但实际原生窗口仍另起 Core。本次源码检查覆盖了 run -> for_window -> connect_service,原生185项测试和真实子进程测试验证默认/拒绝/拥有权,但安装态仍须采用后另行读回,不能用截图代替。对外来监听器、已卸载声明或撤权来源均保留错误与恢复,不自动选择另一存储,不回放效果未知的回合。
不可用原来源的生产前端检查确认输入与发送禁用,普通委派入口被隐藏;恢复仍回到同一 target。相同概览提问的不可变基线在原 Session 中为零,当前恰好一次;原普通会话未被混入。显式 Goal 对照保持原导航和 Session 数量。忙时第二条消息排队后仍可看到中断,原 Core 最终只执行一次追问。
本地验证包括生产前端类型检查/构建、app-steward 和 bound-conversation HTTP smokes、原生完整串行套件185通过/12明确忽略、Rust格式、双语RFC及边界检查。初次并行原生测试遭遇私有合成端口已占用,并由 fixture mutex 污染产生两个后续失败;保留该记录,未声称修复主机端口竞争。当前完整串行测试保留所有断言并覆盖被暴露的拥有权拒绝分支。首次合成等待还曾触发 idle timeout,修正托盘后以新的明确场景完成排队和交互中断,不将旧失败改称通过。
预合并执行10个catalog、8个风险smoke及文本边界,自动失败为零;总状态仍是四张二进制图片需人工审查。现已逐图检查像素、合成来源和PNG chunks,无文本元数据或私人内容,不能把二进制跳过当作自动隐私通过。最初默认注册表扫描还包含无关旧Goal权威错误;另用隔离空注册表只验证本差异文本,未把它称为生产Goal健康。原生App已通过本地打包和ad-hoc签名,预览未公证的限制保留。按当前策略没有读取、等待或引用远端CI。
语义与 CI 对齐
本次复用既有Core binding/Session/queue和原生进程拥有权,不新增共享状态词汇或控制面义务。新 gate 是派生UI状态,环境变量仅选端点,不授予数据或工具权限;私有端口本身不代表数据隔离。默认变化在README和双语RFC明示,Goal配额、调度、Agent提示与权限契约均无改动。当前CI策略为不观察远端,资格来自以上本地实证和独立评审。
我的整体评价
我认可这是有实际价值且可回滚的完整修复切片,结论为 APPROVE。长程工作层面,原 Session、队列与已有交办重新进入同一读取/执行路径,减少隐藏承诺和重复请求的机会;此结论不扩展为长期产出或模型效果提升。体验层面,普通任务复用已知选择,额外确认轮次为零,失败可以在原位置恢复,未牺牲既有项目或受众隔离。
整页检查确认概览保留工作板,原会话标题与输入框同屏;不可用态在输入框旁提供重试,隐藏未核验来源的委派控件。窄屏保留同样层级和恢复入口。另实查390×844的展开托盘,调整/中断、排队回执与输入框同时可见,活动列表在有界区域滚动。
这些截图使用合成数据和生产前端,不能替代安装态原生 App、真实消息或完整附件阅读资格。
260行新增的主要成本用于复用而非复制owner,旧普通路径与明确开发隔离都有当前调用者,不需要保留额外协议版本兼容层。原生首次常驻安装与完整双端媒体关系继续由现有验收持有;原历史不擅自删除、合并或称为自动补办完成。head 56dd9dc76b2594a6894eeb9c779530ea0520ebd3 的资格覆盖此有界增量,仍需实际安装态完成后再关闭相关交付要求。
English verdict: APPROVE for 56dd9dc76b2594a6894eeb9c779530ea0520ebd3 as a justified original-service routing increment. Normal native startup reuses the machine Core; overview and Conversation share the exact original source, queue and refusal boundary. No blocking finding. Local production HTTP/Core, browser counterfactuals and185 native tests cover the changed invariants; four visual holds were manually inspected. Installed adoption, complete media/history synchronization and first persistent installation remain separate qualifications. Remote CI was not consulted.
Problem and behavior
Opening the packaged App allocated a private Core service pair, so the App could display different conversation and delegation history from an existing machine Bot service. The overview composer also bypassed the selected original steward even when the Conversation tab used it.
Normal App windows now use the same machine Status/Chat endpoints as the CLI/browser. Existing qualified services and their LaunchAgent remain the owner. A declared but unloaded service produces a recovery error instead of an empty default store. Explicit private endpoints remain a developer opt-in and require a disposable data root. Recovery follows actual owned children in both modes; closing a window never stops a borrowed service.
Overview and Conversation reuse one read-only original-source resolver. Overview keeps its work board while its composer, quick prompts, queue and interrupt operate on the selected original Session. Pending/failed discovery disables input and hides misleading ordinary delegation controls; retry and settings stay available. Explicit Goal, project, bound, remote and read-only routes keep their existing ownership.
Validation and boundary
Reviewed source:
56dd9dc76b2594a6894eeb9c779530ea0520ebd3. Production frontend build/type check, app-steward and bound-conversation smokes passed. Native library tests: 185 passed, 12 explicitly ignored. The initial parallel run hit an ephemeral-port fixture collision; the complete final serial suite passed. No CI fetched or awaited under the current review policy.Real disposable HTTP/Core plus Ego browser checks cover original overview send, queued follow-up, visible interrupt, unavailable-source refusal/recovery and explicit Goal parity. The immutable baseline sends the same overview quick prompt to the ordinary manager: the original Session receives zero messages. This head routes it exactly once to the original Session without changing the ordinary transcript. The busy queue/interrupt check also completes once through Core. An initial synthetic wait hit its idle timeout and remains a failed attempt; the corrected interactive queue case passed.
Premerge ran 10 catalog canaries, 8 risk-profile smokes and boundary checks with zero automated failures. Its four binary-image holds were inspected manually: synthetic fixtures only, no private content, and PNG chunks contain no textual metadata. Text scan and bilingual RFC check passed. The routine default-registry scan also exposed unrelated legacy Goal authority errors; a separate disposable-registry check qualifies only this diff's public text boundary.
The screenshots are production frontend/disposable Core evidence, not installed native App acceptance. Native installation, reopen and original-service readback follow adoption. Full attachment/reply/cursor synchronization and persistent service installation on a fresh machine remain separately tracked and unqualified; this PR adds no new queue, consumer, source authority or permission.
Visual evidence
Before — overview uses the ordinary manager:
After — overview retains its board and uses the selected original Session:
Unavailable — input and ordinary delegation fallback are blocked:
中文说明
默认 App、网页与飞书复用同一机器 Core;窗口不再默认另起空存储。概览和对话共用已选原管家来源,发送、排队、中断及委派受众继续由原 Core 持有。来源未核验时禁用输入并提供重试,不回退到另一份管家。保留私聊和项目权限边界;完整历史附件同步与首次常驻安装仍不由此增量宣称完成。