Repository navigation
fix(chat): use the bound transport’s listener health in Settings - #6021
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; declaration_source=runtime_reported; model=gpt-6.1-sol; provider=OpenAI; reasoning_effort=xhigh
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
已配置本地会话服务的用户,在 Settings → Lark 查看每个 App 的监听连接状态。
同一个外部服务正在启动时,旧版本会借用过期的 Lark“已停止”状态;缺少状态时还会显示“启动中”。修复后读取该服务自己的缓存状态,无法确认时明确显示“连接尚未确认”。
真实 HTTP 与打包界面验证了状态按服务分别显示,读取失败后能恢复;界面没有把监听状态当作任务完成或发送成功。
本 PR 不安装或启动服务,不改变凭据、工作区授权、消息执行或结果回传规则。
各个服务安装后的真实监听和原渠道结果回传仍须独立验收;本次隔离验证不代表它们已完成。
改动思路
监听健康是服务观察值,适合在现有扩展的读模型内投影;Core 继续负责绑定和授权,不新增生命周期或第二个决策源。
本 PR 交付已有 Settings 页面可用的准确状态读回;真实服务安装、监听与结果回传属于后续部署验收。
入口仍是已有 Settings → Lark 页面与私聊连接 GET。Core 绑定、项目权限、会话和回传继续由现有 owner 决定。新增 helper 只按绑定的 transport_ref 选择观察源:已有外部服务用自己的可选缓存 health_snapshot,默认 Lark 用原监听缓存。读取失败时返回 unknown,下一次已有刷新能恢复;不复制监听状态、不创建重试任务。此处 Python 属于已有扩展的 IO/投影边界,没有必要增加平行 TypeScript 决策源。状态来源修复不是新增的默认关闭功能;原来缺失状态显示启动中,现在明确显示未确认,这个默认变化已在中英文 RFC 披露。
具体改动
评审 head:e782d6e0f43b6136f37e0060066e479396fb482b;独立对照 base:ce0ed6e25558b37df45487d7319bbf44b2fa0dc4。完整四文件 +106/-1:扩展 API +23/-1,现有 HTTP 测试 +63,RFC 英文 +12/中文 +8;没有新增服务、配置开关、持久字段或生成产物。
关键代码讲解
loopx/extensions/lark/private_conversation_api.py:14的_private_listener_status:从现有精确 transport registry 取 provider,调用可选缓存快照。provider 存在但 hook 缺失、抛错或格式不合法时不会借用 Lark 的旧状态。仅接受现有六个标签;其它值返回 unknown。日志只写异常类型,响应不包含其它 provider 字段或异常消息。loopx/extensions/lark/private_conversation_api.py:34的_private_conversations:保留原绑定、工作区、executor、grant、Agent 目标和待回复计数,只替换 listener_status 的来源。apps/presentation/dashboard/src/features/personal-workspace/private-conversation-panel.tsx与请求 schema 在 base/head 的源码哈希相同;原 listenerLabel 已有“连接尚未确认 / Connection unconfirmed”,用户不需要新输入或多一步授权。
判据采用本仓库已接受的 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,固定在 ce0ed6e,以改动前文本判断新增段落;原段落没有编号,以下为评审定位标签,未新增 RFC 要求:
- CORE-OWNERSHIP:Core 继续拥有身份、会话上下文与撤销;真实 HTTP/绑定回归通过。
- SCOPE-EXCLUSION:观察值不授予 Goal、portfolio 或 peer 权限;重复读取不改绑定、不新建 Session、不发 provider 写操作。
- EXTENSION-PLACEMENT:复用扩展 HTTP composition 与 provider-neutral Core owner;没有第二个授权源。
- SOURCE-LIVE-SEPARATION:源码与合成服务的浏览器验证交付本次可见读回修复;各服务安装后的监听和回传仍保留为单独验收,不能用本轮代替。
对主干的风险
最主要的回归方向是外部服务观察失败后,显示了其它监听器的过期正常或停止状态。本轮独立运行 83 项绑定、transport composition 与私聊原生测试,全部通过。同一真实 HTTP 回归在 immutable base 失败(stopped 而非 starting),在 head 通过;六标签、空/错误类型、缺 hook、异常、缺 Lark 观察与无写副作用都有覆盖。
TypeScript noEmit、生产 Chat 构建、Ruff 与全树 semantic-vocabulary-drift smoke 通过。开发期语义 advisory 没发现支持语法内的新候选,未命名 tuple 另由人工与既有 UI 标签逐项核对。聚焦 mypy 在 base/head 都失败:11 个 attr-defined 诊断逐条相同,仅行号偏移,均为原 mixin 请求 hook 声明问题;没有把它报告成通过。
用 exact-head 编译产物在 Ego Lite 运行 Settings 旅程,受影响状态和项目列表接真实隔离 HTTP/Core store,provider cache 和其它工作区 API 为合成夹具。观察了 listening → 快照异常/未确认 → listening → 重载恢复,绑定与副作用不变;查看了包含 App、工作区、权限、executor、状态与后续操作的目标视口。早期夹具缺项目响应导致旧 UI 报错,补上真实项目 GET 后完成同一恢复路径,未修改产品代码。没有查询或等待 CI;没有安装或验证真实账户、手机、模型和消息回传。第三方 hook 必须遵守缓存/不做网络调用的契约,本轮不证明任意 provider 实现合规。
我的整体评价
APPROVE。这是 justified_increment:已有用户入口真正得到准确可恢复的读回,边界完整,但父级长期会话/真实回传验收仍开放。生产机制与原问题相称,既有 Core/设置页面均复用。按相邻边界做了未来改动检查:小 helper 集中唯一真实 caller 的状态选择足够;另建状态服务或为仅一个投影增加跨语言框架会扩大维护成本,当前无必要。保留默认 Lark 路径与可选 hook 兼容,不新增授权或迁移。作者账户不能提交正式自批准,此 COMMENTED review 只记录精确 head 的批准结论;是否合并仍由维护者和原生资格检查单独决定。
English verdict: APPROVE - head e782d6e. Exact-provider cached listener status replaces stale cross-provider/default-starting inference; 83 native tests and immutable base/head regression, compiled Settings failure/recovery/reload, Ruff and semantic smoke passed. The same 11 pre-existing mypy diagnostics remain; installed/live-provider qualification is separate.
The private-conversation Settings endpoint enumerates all native bindings, but previously read only Lark listener health and defaulted missing observations to
starting. A locally installed transport could therefore keep receiving messages while Settings stayed “Starting”, or inherit a stale Lark row with the same transport ref.Read the exact host-composed provider’s optional cached
health_snapshot()first. Project only the existing listener statuses; absent, malformed or failed observations becomeunknown, which the existing bilingual UI renders as connection unconfirmed. Keep default Lark health, binding grants and delivery accounting unchanged. The hook belongs to the installed transport; it introduces no new capability or authority owner and performs no HTTP registration or credential discovery.Validation:
npm ci --ignore-scriptspassed.