Repository navigation
feat(chat): open the selected original steward from App Conversation - #7320
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
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 (host execution observation unavailable: session_not_found).
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
已有私聊管家的本人,在 App 打开「对话」时需要继续同一段工作。
以前每次打开 App「对话」都会进入普通管家,需要再去设置寻找原会话;现在明确选过来源后,入口直接打开该来源的原会话,失效时停在可恢复页面。
真实 HTTP 与打包页面验证了来源选择、原历史读取、失效拒绝和清除恢复,单纯打开入口不创建会话、不调用模型。
本次不宣称完成概览快捷提问、附件及回复线程的全量同步,也不代原 Bot 执行业务或重放失败请求。
概览快捷提问仍是普通管家路径,完整跨端关系和真实安装采用还需在原同步工作项继续验收。
原有「继续原会话」能手动进入,但需要反复寻找来源;按最近活动或列表第一项自动选,又会把多个合法管家中的选择意图猜错。本增量把已知意图保留下来,允许已获授权的 Agent 直接应用来源,无需再索取一次确认;不知道选哪个时才需要一次真实选择。
改动思路
来源选择是无法从多个合法绑定推导的人类意图,放在既有 Core 绑定集;身份核验与 Session 发现复用原所有者,界面只投影结果,失败不启动替代执行。
本 PR 交付 App「对话」入口和可撤销的来源选择;概览快捷提问仍走既有普通管家路径,完整跨端同步留在原有同一工作项。
绑定表示既有私聊受众,Session 表示其持久对话。新字段只决定从哪个绑定进入,不改变受众、工作区权限、执行者和模型。Settings 先写入当前 revision 的来源选择;默认入口再经过原身份和工作区校验,取已有 Session,随后复用原队列。加载时普通输入框不挂载,失败则停在恢复页面;已打开的原会话不随之后的偏好修改而漂移。取消选择只退回普通入口,不解绑任何来源。
下表是 b400aa5 的源码路径说明,不代替执行证据:
| 入口状态 | 结果 | 失败与恢复 |
|---|---|---|
| 未选择来源 | 原普通管家 | 损坏配置拒绝冒充未选择 |
| 已选择原来源 | 其已有 Session | 身份/会话失效时阻止进入,重试或清除 |
| Goal、显式会话、远端 | 保留原范围 | 不读取默认来源来覆盖 |
具体改动
独立规格依据为 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,spec_revision 为 06f51b7e43adc546b16b6b2590d9bd2ea27bae31;该 RFC 在本 PR 的补充文字是待交付增量说明,未当成其自身已通过的验收依据。上述无编号原文约束用下列描述性 criterion_id 对应:
| criterion_id | 本 head 处置 |
|---|---|
| existing-private-binding | implemented:复用已有私聊绑定与发现所有者 |
| fresh-source-authority | implemented:当前 revision、身份、工作区核验 |
| original-session-no-fallback | implemented:原 Session,无隐式新建或同伴回退 |
| scope-and-recovery | implemented:局部入口、冷 Goal 保留、失效清除 |
| complete-cross-channel-relations | deferred:原同步工作继续覆盖概览与完整附件/回复关系 |
关键代码讲解
- planConversationBinding 在原 CAS 发布计划中新增选择操作:非空值必须是已验证的本人私聊管家;同一选择幂等,清除不依赖来源在线。完整绑定行不变,解绑后保留失效的选择标识以避免悄悄切到另一个来源。
- app_steward_target 对未选择的旧配置也走同一纯 Core 校验;已选择时复用 local_sessions 的完整 Session 清单与来源证明,再在锁内复核偏好。这里不创建 Session 或调用模型。
- AppStewardEntry 把加载、普通和不可用作为局部界面状态。请求超时/卸载会取消;只有返回严格成对的空值才显示普通输入框,否则打开明确目标或恢复页面。
- DashboardPage 等待状态目录再核对 Goal,修复冷链接被空占位数据清除的问题;默认包装仅限本机无绑定的「对话」,晚到响应还需通过当前 URL 的范围核对。Settings 的按钮名称也明确为 App「对话」,避免把概览快捷提问误说成已同步。
文本改动 +428/-25,另有十张合成场景截图。主要新增生产块是小型入口组件和既有适配器的来源选择/读取;测试复用真实 HTTP、Core 与隔离 SQLite。未提交打包缓存、账号数据或私有运行材料。
对主干的风险
未发现阻塞项。最重要的回归风险是原来源失效后仍出现可发送的普通管家,或者冷 Goal 被默认来源劫走。前者由精确选择、原 Core 权限校验及普通组件不挂载共同阻止;新建同伴、旧 revision、身份改变、原 Session 关闭与解绑均经真实 HTTP 走过。恢复验证包含身份恢复后仍回到同一原 Session,以及失效行消失后在 Settings 清除选择。后者通过同一合成环境的不可变安装基线对比验证:9b8adda2f04c285d1c13ecc90b3abba93202ebee 冷打开 goal-a 实际清除了 Goal;当前包保留 goal-a,双方都是未选择来源且默认入口读取次数为零。
旧的未选择安装保持普通历史与原执行路径,只增加一次有界发现读取;旧绑定集不需要迁移。前后端随包交付,持久绑定状态跨升级保留,因此继续接受字段缺省;不接受半空目标 DTO。发现和选择不增加 Session、消息、模型调用、配额或监听消费者。显式打开的原 Session 也不会被之后更改的入口偏好替换。
33 个 Core 用例、41 个 Python 绑定用例、两条真实 HTTP/Core 旅程、生产前端构建和类型检查通过。最终本地 premerge 的自动部分全部通过;CLI 总结果仍是 manual_review_required,十个二进制图片项已单独检查像素、来源与 PNG 元数据,未把它伪报成自动通过。早先旧 bundle、无效 settings URL 和过期 DOM 引用的探测失败保留,最终使用正确构建与真实入口验证,未删断言或重放真实业务。按本次策略未查询、轮询或等待远端 CI。
语义与 CI 对齐
本次 extend_vocabulary 扩展既有 conversation-binding 所有者;没有新增共享 actor/lifecycle。局部 React 状态不是共享语义注册项,完整语义 canary 通过。增量探测未发现支持的多值载体,但它不证明不存在新语义;这里另行核对了字段、操作、调用者与权限边界。来源选择是强制路由意图,不是任务执行、重试、结算或授权指令。
我的整体评价
APPROVE,交付判断为 justified_increment。长程维度 improved:重复进入能接回原对话,失败和原执行归属不被隐藏或重放;用户体验 improved:既有来源无需重复录入,已知授权无需再确认,未知来源只做一次选择。机制成本与该重复入口问题相称;保留旧持久状态兼容,采用既有所有者比新增管家身份、消费者或授权库更小。
已检查完整桌面页面、390px 窄屏、展开长报告及连接失效后的恢复页面;来源与下一步操作可一起辨认,长正文留在原阅读器,错误可见且可恢复。
尚未在本评审中验证真实账号安装后的入口采用与完整跨端附件、回复线程关系;本地浏览器使用合成来源和真实打包页面。
已逐张核对十张公开图的合成数据与元数据,最终重拍并查看三张来源选择/失效图;长报告与冷 Goal 图复用时核对了对应阅读器、布局和路由未因最后文案变化而改变。余下最强验证缺口是合并安装后的真实账号采用,随后应在原服务独立读回。完整跨端同步、长时断线恢复和外部消息关系仍未由这个本地增量证明,原工作继续保留。评审仅对 b400aa58562dcd28a33afbd94a9e8c8618490ed8 有效,合并前必须再读 head 和其他有效审查。
English verdict: APPROVE for b400aa58562dcd28a33afbd94a9e8c8618490ed8 as a justified, reversible App Conversation entry increment. Existing Core source authority, Session discovery and execution owners are reused; no blocking finding. Local real HTTP/Core and packaged-browser evidence covers selection, failure/clear recovery and a failing immutable cold-Goal baseline. Full external synchronization and installed account adoption remain explicitly unqualified here. No remote CI consulted under the current policy.
Goal And Delivered Outcome
The local App Chat entry currently opens an ordinary steward conversation even when the owner already has a private steward connected. This increment lets the owner choose one existing connection in Settings and opens its verified original Session from the App Conversation entry. It does not infer a choice between multiple stewards.
The same journey exposed a cold-link defect: the bundled placeholder could clear a valid Goal before its status directory arrived. Goal selection now waits for that directory, preventing a cold Goal link from entering the default steward.
main; this is a bounded conversation-entry increment, not closure of the complete App/messaging synchronization program.Author Declaration
Scope And Continuation
Core stores one optional
app_steward_binding_idbeside the existing bindings. Selection is separate from audience, managed identity and execution grants. The existing local Session selector, composer and queue are reused; discovery creates no Session, consumer or model work. Removed/replaced selections remain unavailable until recovery or an explicit clear, including when their row is gone from Settings.This is independently reversible by clearing the entry preference. Existing ordinary history remains separate. The useful delivered boundary is the App Conversation entry and its source chooser; overview quick prompts, complete reply/thread/attachment relations and full installed external synchronization remain with the existing RFC program. No new follow-up task or authority store is introduced.
Validation
b400aa58562dcd28a33afbd94a9e8c8618490ed8. Final refinement narrows the source-choice label to App Conversation and adds real HTTP coverage for a newly connected peer and a closed original Session. Three source-choice/recovery images were refreshed.manual_review_required, not an automatic success.npm run smoke:app-stewardandnpm run smoke:bound-conversation: real Chat HTTP, Core and isolated SQLite authority; only provider identity/model are synthetic9b8adda2f04c285d1c13ecc90b3abba93202ebeeloses cold Goal selection; the same fixture/backend boundary at this head retains the Goal. Both are unselected and issue zero default-entry readsOpening/selection alone retained the captured native-model call count. Synthetic Web and source inputs each produced one response in their original Session. No live business request was replayed. Local validation does not certify full installed cross-channel delivery, and no CI was queried under the managed review policy.
Frontend / Visual Evidence
UI impact: changed. The source choice sits beside Continue original conversation, with its selected/clear state in the same row; narrow screens stack the controls. Existing notification and monitoring details remain in their existing sections. No new help paragraph was added to each connection. Failure removes the ordinary composer and keeps retry/settings available; a removed selection can still be cleared. The long report remains readable in its existing standalone reader. A cold Goal first frame was also inspected with its animation clock paused.
Before — unselected ordinary conversation (packaged synthetic fixture):
After — original source history and one composer:
Source choice, narrow/error states and populated reading
Type Of Change / LoopX Area
Boundary Checklist