Skip to content

fix(chat): complete ACP initialization before session creation - #6314

Merged
huangruiteng merged 3 commits into
mainfrom
codex/fix-qoder-acp-initialized
Oct 13, 2026
Merged

huangruiteng merged 3 commits into
mainfrom
codex/fix-qoder-acp-initialized

Conversation

@NIU-123370

@NIU-123370 NIU-123370 commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Goal and source

Fix a Qoder ACP session-creation timeout reproduced during first real use of the LoopX Chat custom-Agent path.

Gap

The observed Qoder ACP provider waits for an initialized compatibility notification before session/new. Its first authenticated session also took longer than the previous 30-second default.

The earlier revision unconditionally raised every caller-provided session timeout to 45 seconds. That changed an explicit timeout from an upper bound into a lower bound.

Delivered behavior

  • Send the observed provider-compatibility initialized notification after ACP initialization and before session creation or recovery. This is not described as a universal ACP v1 requirement.
  • When no startup timeout is configured, retain a 30-second initialize default and use a 45-second ACP session creation/recovery default.
  • When a caller explicitly configures --startup-timeout-seconds or startup_timeout_sec, preserve that value as the upper bound for initialize, session/new, session/load, and session/resume.
  • Keep the existing offline ACP smoke focused on notification ordering and add focused timeout-policy tests.

Validation

  • uv run --extra test python -m pytest -q tests/test_chat_acp_startup_timeout.py tests/test_chat_path_redaction.py tests/test_chat_queue_preparation.py — 56 passed.
  • uv run --extra test python examples/loopx-chat-acp-adapter-smoke.py — passed.
  • Ruff on all changed Python paths — passed.
  • examples/control_plane/control-plane-maintainability-ratchet-smoke.py — passed.
  • Public/private boundary scan — passed.
  • Focused negative coverage proves explicit short limits reject session/new, session/load, and session/resume, reap the peer process, and do not persist a Chat Session. Default and explicitly larger windows accept the same delayed peer.
  • Full risk-selected premerge was also attempted against upstream/main; direct diff/compile and public-boundary checks passed. Three unrelated repository checks did not qualify this old PR baseline: missing npm dev dependencies and existing CLI-output baseline drift.

The earlier real authenticated Qoder evidence remains: ACP session creation through ACPStdioAdapter succeeded in about 32.25 seconds, and the custom endpoint succeeded through ChatRuntimeController.open_session. No credentials, session content, local paths, or generated logs are included.

Future-facing refactor

The existing shared ACP adapter remains the correct transport owner. The bounded companion change separates default policy from explicit caller authority without adding a provider-name heuristic or a parallel timeout owner.

@NIU-123370
NIU-123370 force-pushed the codex/fix-qoder-acp-initialized branch from f1e1feb to fcb19a0 Compare October 12, 2026 12:38
Signed-off-by: The one -Niu <191000457+NIU-123370@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · xhigh

动机

通过本地已注册 ACP Agent 创建或恢复 Chat 会话的操作者及设置启动超时的调用方。 一些 provider 需要会话前通知且创建耗时超过默认30秒,原路径在真实首次使用报告超时;原调用方的 startup_timeout_sec 对 initialize 和会话阶段分别生效。 当前 head 在会话前发通知,并给 new/load/resume 至少45秒;合成慢启动及通知依赖路径可以创建和恢复,但显式较短上限也被覆盖。 本 PR 不新增凭据、工作区写权限、任意命令启动、持续 daemon 或真正 Qoder/模型计费资格。

改动思路

共享 ACP adapter 是已有 transport owner;默认或 provider 启动策略与调用方显式上限应分开,保留配置的拒绝边界。initialized 不能被说成所有 ACP v1 provider 都必需的协议通知。 本 PR 应交付已有 ACP 创建/恢复的兼容修复和有界默认启动策略,同时保留显式调用方上限、协议错误与清理;不需要广泛前端或语言重写。

独立产品依据为 docs/guides/personal-workspace-trial-guide.md,冻结修订 323c3053128e41e16df27e6b6498f83c37e81f5e 的 4. 多 Agent:已注册 ACP stdio endpoint 保留现有只读与预览确认边界;也检查同修订的 Chat continuation/recovery 和现有 controller → adapter 参数来源。判定以实际新建/恢复/失败边界为准,不以 author 的已认证 Qoder 成功报告代替独立执行。

ACP v1 Initialization 规定先完成 initialize 协商,没有列出 initialized 必需通知;Extensibility 的自定义方法/通知使用 _ 前缀并建议协商。官方 Python SDK bdb9ac7054fb2df76a922b60b356c3c65f8a8a64 的 router 也没有该通用 route,unknown notification 记录异常而不中断连接。因此可以讨论特定 provider 的兼容需要,不能以 smoke 新断言证明它是所有 ACP 的协议义务;本轮没有据此虚构 standard provider 连接失败。

具体改动

精确 head 297019c16c3c66f88479ad4141338cc2dda66d64;全 PR 2 文件 +16/-3:生产 chat_acp.py +10/-3,现有 smoke +6。完整差异、初始化/请求/清理与 runtime/HTTP 调用方均已读。

  • ACPStdioAdapter.start 在成功协议版本协商后、new/load/resume 前 _notify("initialized", {}),无 request id。错误版本仍在通知和 Session 请求前拒绝;现有 recovery 能力分支、Session ID 一致性和权限拒绝不改。
  • 新常量 ACP_SESSION_STARTUP_TIMEOUT_FLOOR_SEC=45.0 用于三个会话分支;initialize 仍用 caller 值,idle/hard Turn 超时及 graceful process close 仍是原 owner。smoke 的合成 provider 在 new 前检查通知,保护其特定顺序。
  • [P1] 会话阶段覆盖调用方显式启动上限。 chat_acp.py:158 无条件 max(startup_timeout_sec, 45),所以显式短值与默认值无法区分。独立相同真实 stdio/HTTP 场景:服务和 adapter 明确设 startup_timeout_sec=0.1,provider 的 session/new 在0.4秒才回应;冻结 base 拒绝并关闭子进程,当前 head 成功创建持久会话201。不是仅看到计时更长:原来被预算拒绝的业务效果现在被接受。initialize 超时仍按0.1秒拒绝,使同一个设置在不同启动阶段含义分裂;一般较慢 endpoint 最多占用新的45秒而无法按调用方短限快速失败。请将较大的默认/provider 策略与显式上限分开,保留显式短配置,说明影响 new/load/resume。回归要同时证明31秒默认需求可成功、显式短限拒绝无 Session/进程遗留,以及更长配置原样保留。
  • [P2] 修正通用协议表述和兼容性证据。 body 目前把 initialized 称作 ACP 必需。请明确是观察到的 provider 兼容行为,并对 standard/no-notification-requirement peer 保留测试;不要把 provider 行为复制进 fake 然后称协议 conformance,或凭 Agent 名 substring 判定。若需要额外能力选择,放在已有 provider/negotiation owner;这不是要求新建通用框架。

对主干的风险

独立匹配 base/head 10 场景真实 stdin/stdout 子进程:通知依赖 new/load/resume 从协议拒绝到成功并实际 prompt 回答;standard tolerant peer 均成功;错误版本、无 recovery 能力、恢复错误 Session ID、initialize timeout 仍拒绝且自有子进程关闭。31.1 秒 session 响应在默认30秒的基线拒绝、当前成功,证明 floor 的有用方向;显式0.1秒场景证明它同时更改已配置的拒绝边界。所有子进程 lifetime 检查是自己的合成 fixture,不执行用户 provider。

另用实际 serve_chat 注册 endpoint、POST /api/chat/sessions 和实际 ChatSessionStore 做匹配 HTTP 对照:通知需要的 endpoint 基线424/current201;短限的 endpoint 基线400/current201。API 返回真实 Session、保存真实记录,合成只在上游协议 peer;静态资源使用显式测试 override,仅资格化当前 backend/API,没有宣称当前 packaged UI或 installed App 更新。此 PR 没有 UI改动,源默认/权限消费者都沿现有入口。前轮 #6315 模型选择的变化不包含在本头,也不继承其 verdict。

当前 ACP smoke、Ruff、semantic advisory 及 native premerge 5 direct +3 selected 通过;没有 CI查询。首次私有 probe 的 chmod相对路径及不存在 close 方法造成 setup失败,修正为真实 close_session 后重新完整跑匹配矩阵,原失败留证,不算产品缺陷或已通过覆盖。作者真实 Qoder约32.25秒及 controller成功仍是作者报告;本轮不借用凭据运行真实 Qoder、不跑付费模型。

新增数字常量是 provider启动策略,不是新状态 vocabulary。默认变化应由共享 timeout/provider owner公开,而不能把 caller 明确值静默抬高。已有 ACP关闭与请求错误 owner、read_only capability、权限cancelled response 和未知endpoint拒绝保持;通知和 timeout 不授予 execute。相邻精简应让默认策略与已配置限额语义分离,无需扩大重构或新增权限开关。

我的整体评价

REQUEST_CHANGES。通知需要的 provider 和默认慢启动方向有实际价值,显式上限的接受/拒绝契约仍被改变。共享 ACP adapter 是已有 transport owner;默认或 provider 启动策略与调用方显式上限应分开,保留配置的拒绝边界。initialized 不能被说成所有 ACP v1 provider 都必需的协议通知。 本 PR 应交付已有 ACP 创建/恢复的兼容修复和有界默认启动策略,同时保留显式调用方上限、协议错误与清理;不需要广泛前端或语言重写。 最小修复是同一 adapter/caller 参数 owner 保留显式短限并分离默认策略,补同源正反例;不要仅提高更多超时来资格化稳定工作。协议表述修正为非阻断建议,不能冒称通用 v1义务;真实 Qoder后续采用继续保持证据边界。本轮不合并或升级运行环境。

English verdict: REQUEST_CHANGES - 297019c; max(requested startup timeout,45s) overrides explicit caller session-phase limits, turning the same bounded HTTP/stdio refusal into an accepted durable Session. Ten matched base/head cases qualify notification-dependent recovery and31.1s default startup, but the short-limit invariant fails. Required local checks pass; initialized is not a universal ACP v1 requirement.

Signed-off-by: sakurahello1 <201035361+sakurahello1@users.noreply.github.com>
Signed-off-by: sakurahello1 <201035361+sakurahello1@users.noreply.github.com>
@NIU-123370

Copy link
Copy Markdown
Contributor Author

Addressed the exact-head review on new head 6bfdb64c7d70d508cef6fcc982cf047b3588a8c3.

  • Removed the unconditional max(configured, 45s) behavior.
  • An omitted timeout now keeps the 30s initialize default and uses a 45s ACP session default.
  • An explicitly configured timeout remains the upper bound for initialize/new/load/resume.
  • Corrected the PR wording: initialized is an observed provider-compatibility notification, not a universal ACP v1 requirement.
  • Added focused positive/negative coverage, including process cleanup and no persisted Session on timeout.

Validation: 56 focused pytest cases, ACP adapter smoke, Ruff, maintainability ratchet, and public/private scan passed. Please re-review the updated head.

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · xhigh

动机

通过已注册 ACP Agent 开始或恢复普通 Chat 对话的用户,以及显式设置启动上限的调用方。 相同31.1秒会话响应在基线超时,新 head 返回会话并可回答;旧版在显式0.1秒上限下接受0.35秒响应,新 head 拒绝且不保存新会话。 默认首次使用和兼容恢复可以完成,调用方明确的短限重新成为拒绝边界;原界面不增加配置步骤。 本 PR 不授予执行或写入权限,不新增账户和后台调度,也不证明真实 Qoder、付费模型或长期稳定性。

这解决的是已有聊天入口的首次使用与恢复失败:用户不必为原本能在三十到四十五秒内启动的 Agent 反复重试;明确设置短等待的调用方仍能拒绝超过预算的会话。没有以测试数或账户可用标志代替真实请求结果。

改动思路

共享 ACP adapter 持有启动等待策略,既有 CLI/HTTP/controller 保留调用方意图与 Session 生命周期;Python 属于稳定 transport IO,不增加平行控制面 owner。 当前 PR 交付已有会话的通知兼容及默认/显式启动等待修复;不扩展到模型发现、账户认证或整个恢复体系。

先保留原调用方的“未配置”和“明确配置”区别,再由已有 adapter 选择阶段默认值。仅添加通知仍无法处理默认三十秒以上的首次启动;统一改成四十五秒又会覆盖调用方上限,旧版正是这样。当前方案不用 Agent 名称匹配或另一套配置 owner,亦无数据迁移。把默认策略与显式上限分离是本次相关、有界的精简;继续抽 helper 或引入 provider 框架没有当前必要性。

具体改动

精确 head 6bfdb64c7d70d508cef6fcc982cf047b3588a8c3,基线 323c3053128e41e16df27e6b6498f83c37e81f5e;完整七文件 +217/-16 均已读。另独立比较旧评审 head 297019c16c3c66f88479ad4141338cc2dda66d64 到当前的修复,而不是沿用原结论。

关键代码讲解

  • ACPStdioAdapter.start(loopx/chat_acp.py)用 None 选择 initialize 30 秒、new/load/resume 45 秒;明确配置值原样用于各阶段。协商版本通过后发送无 request id 的 initialized,错误版本、错误恢复 Session ID 和请求超时仍沿已有清理分支拒绝。
  • ChatRuntimeController.__init__/_start_adapter(loopx/chat_runtime.py)保留 Codex 的数值30秒,将原始 None 或明确值交给 Kiro/custom ACP;现有 SessionStore 仍在成功取得会话之后落盘。不是另建 actor、额度或权限 owner。
  • register_chat_and_dashboard_commands(support_control_chat.py)不再把省略参数提前补为30秒,现有 help 说明 Codex30/ACP会话45的默认差异;handle_support_control_command(support_control.py)继续保留已有 CLI 显式值0.1秒下限并向 serve_chat 传递省略值。
  • chat_server.py 仅同步已有服务参数类型/默认值,前端代码没有改变。现有 ACP smoke 增加该兼容通知顺序,新增 startup timeout 测试覆盖显式 new/load/resume 拒绝、进程回收和失败不保存 Session。

独立接受依据为 docs/guides/personal-workspace-trial-guide.md,冻结修订 323c3053128e41e16df27e6b6498f83c37e81f5e 的 4. 多 Agent:PW-4-ACP 已注册 stdio endpoint 的真实 CLI/HTTP、打包页发送及重启恢复成立;PW-4-READ-ONLY 原客户端 fs/terminal=false、权限请求取消与预览确认边界保持。另逐项核验旧评审5492365612要求的显式上限、默认慢启动、较长配置、三种会话分支及清理,当前均有独立对照。

ACP Initialization要求先 initialize 协商;没有把 initialized 列为通用必需通知。Extensibility另有扩展命名规则。因此本次仅按观察到的 provider 兼容行为核验;作者已修正表述。无需通知的标准容忍 peer 仍通过,不能据此宣称所有 ACP 实现都已认证。

对主干的风险

最强反例仍是“默认修好了,显式预算却失效”。同一独立 peer/驱动在冻结基线、旧297及当前6bf各执行 16 场景:通知依赖的 new/load/resume 从基线拒绝到当前成功并回答;默认31.1秒响应从基线超时到当前成功;明确0.1秒对0.35秒响应,旧版三个分支均接受,当前三个分支均拒绝。0.7秒配置、标准容忍 peer、initialize 短限、错误版本和错误恢复 ID 的原行为保持,所有自有子进程均清理。这里测的是请求阶段接受/拒绝;关闭进程的已有宽限也占墙钟时间,不承诺整个函数在0.1秒内返回。

再用真正 loopx chat CLI、生产 serve_chat、controller 和 ChatSessionStore 做三版本默认/显式短限、兼容/标准 peer 的 12 项 HTTP 对照。当前默认201,短限400且零新 Session;旧版同短限却201。基线兼容 peer 的协议拒绝发生在较晚 timeout 之前,保留其424优先顺序,未把错误码归一化成“都是失败”。打包页面通过既有 Runtime 下拉和 Enter 发消息,再优雅重启独立服务,实际 session/load 后沿同一 local/upstream Session 完成第二个 Turn,旧消息仍可见。

源码检查为 56 项 startup/redaction/queue +346 项既有 adapter/CORS/startup-isolation,合计402通过、无跳过;ACP smoke、Ruff、diff语义 advisory→完整 vocabulary/registry census、maintainability 通过。精确基线的原生 premerge 5 direct +5 selected 及公共边界检查通过,无 failure/manual hold;CQR cqr_787bc1095d93fffd0994 精确七文件 pass,未由评审者修改产品代码。按配置没有查询或等待 CI。

私有 HTTP 驱动最初错误排列重叠拒绝优先级、重复创建已存在夹具目录,以及浏览器等待使用了过严的正文重复计数,均留有失败记录。修正观测/夹具后才资格化;浏览器已有请求已完成,没有重复发送以刷绿。作者旧 canary 的依赖/旧基线失败仍属于原报告,不冒充本轮通过或被抹除。

语义与 CI 对齐

新增数字默认与可选参数属于原 transport 的局部策略,不是新状态闭集、共享 actor 生命周期或权限契约。默认变化已在 body/help 说明,调用方上限是机器拒绝条件。所有共享消费者已按显式/省略和非 ACP 分支核验;这里没有新 default-off 能力,不能凭空宣称一个不存在的隔离开关。现有 Chat 指令、权限、quota/scheduler 都未改变。

我的整体评价

APPROVE。本次有界启动修复达成,不继承旧 verdict。用户体验方向为 improved:原入口可以得到有用回答,重启恢复保留同一会话,不新增手工配置步骤。长程方向为 accepted_tradeoff:减少已复现的默认误超时,保留明确上限与清理,但无响应 ACP 的默认会话阶段最多多等15秒;这不等于 Agent 运算更快。实际用户成功率、长期成本和稳定性没有测量,不从402测试或两次回答推算收益。

此次采用收到的评审经验只是把普通任务走到打包页面、真实后台和恢复读回;不会把恢复 RFC 的全部未来验收加给这个 transport 修复,更不宣称 memory 导致评审质量提升。真实 Qoder 的32.25秒成功仍是作者报告,本轮没有借账户、付费模型、原生 OS App 或 native Windows 资格。严格拒绝未知通知的其他 peer 也未独立认证。当前无需阻断修改;批准与旧 review closeout、合并及本机升级分别读回,批准不授予这些操作权限。

English verdict: APPROVE - 6bfdb64; the explicit startup limit regression is repaired while omitted ACP session startup remains bounded at45s. Independent16-case base/prior/head stdio and12 real CLI/HTTP comparisons preserve timeout refusals, cleanup and recovery;402 tests, built Chat conversation/restart and native premerge pass. Default failed-session waiting may increase15s; actual Qoder/model-account and long-run utility remain unqualified.

@huangruiteng
huangruiteng merged commit 4180b71 into main Oct 13, 2026
25 of 30 checks passed
@huangruiteng
huangruiteng deleted the codex/fix-qoder-acp-initialized branch October 13, 2026 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants