Route Codex message tool replies back to WebChat and TUI#81586
Conversation
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. by source inspection. Current main sends targetless WebChat/TUI Codex Real behavior proof Next step before merge Security Review detailsBest possible solution: Land the guarded current-run sink after maintainer review, keeping WebChat/TUI internal-only while explicit channel sends remain on the normal outbound path. Do we have a high-confidence way to reproduce the issue? Yes by source inspection. Current main sends targetless WebChat/TUI Codex Is this the best way to solve the issue? Yes. The PR’s guarded internal-source sink is narrower than changing Codex delivery defaults or making WebChat/TUI generic outbound channels, and it preserves explicit route behavior. What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against faa443a45220. |
|
Added the real behavior proof section with copied local runtime output from the production message-action, embedded payload, and transcript mirror path. The Real behavior proof check is now green on the current head @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
I also ran a real OpenClaw smoke against Pash's local dev agent, using this PR branch as a separate loopback Gateway and a TUI-mode client. Shape tested:
Evidence from the session trajectory: The mirrored session transcript then recorded a That proves the failing targetless Re-review progress:
|
b96b5ec to
1ca3f48
Compare
|
Rebased this onto current The conflict was only in the now-upstreamed live profile lint helper, so I skipped the old lint-only follow-up commit and kept the internal UI message sink as a single feature commit on top of Local rebase validation: The Real behavior proof check is green again on the rebased head. @clawsweeper re-review |
e1b42de to
0269444
Compare
|
Rebased once more onto current This rebase had one changelog conflict; I kept both the new Codex startup fix entry from Local validation on the latest head: GitHub now reports the PR as mergeable again and the fresh checks are running. @clawsweeper re-review |
0269444 to
c87f148
Compare
|
Rebased again after This was another changelog-only conflict; I kept the new GitHub reports the PR as mergeable again and fresh CI is running on the new head. @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Patched the CI-only The failing test already proved the Validation before pushing Fresh CI is running on the new head. @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
dab02f0 to
2def23b
Compare
2def23b to
3ce4a87
Compare
|
Reconciled the latest force-pushed PR head The remaining conflict was in Local validation: GitHub now reports the PR as mergeable again; fresh CI is running on |
|
Latest head @clawsweeper re-review |
|
🦞🧹 Reason: re-review requires an open issue or PR. |
Codex harness sessions intentionally route source-visible replies through
tools.message. That is the right contract for Codex: the model decides what to send to the user, and OpenClaw records that send as the visible reply. External channels already had normal outbound targets, but WebChat and the TUI are internal UI surfaces for the current run, not reusable message channels. In a Codex-bound direct UI session that leftmessage.sendwith no target, so the tool failed withAction send requires a targetwhile the normal final answer was suppressed.This PR adds the missing current-run internal UI sink. When a
message_tool_onlyrun originates from WebChat or the TUI, a targetlessmessage.sendsatisfies that same active turn, records a source reply, and mirrors the text into session history so reloads show the assistant reply. Explicit channel and target sends still use the existing outbound routing path. WebChat and the TUI still do not inheritlastChannel, and they are not made into generic targetable outbound channels for cron or background sends.This replaces the stopgap in #81110. That PR correctly identified the collision between Codex message-tool delivery and internal WebChat, but it fixes the symptom by skipping the Codex
message_tool_onlydefault for internal WebChat and letting automatic final delivery take over. That makes the failing WebChat path visible again, but it routes around the Codex harness contract, does not give the TUI the same principled current-run sink, and leaves the tool path itself unable to satisfy a source-visible internal UI reply.The better fix is to keep Codex harness behavior intact and teach the message tool how to deliver to the current internal UI run when, and only when, the run already declares that as its source-visible reply sink. That preserves external channel behavior, avoids accidental
lastChanneldelivery, keeps WebChat and the TUI non-targetable as outbound destinations, and makes the observed failure shape succeed instead of bypassing it.Real behavior proof
tools.messagereplies from a message-tool-only internal WebChat/TUI run should satisfy the active UI turn, suppress the private final text, and mirror the visible reply to session history.ws://127.0.0.1:18891, realmaindev agent,openai/gpt-5.5, Codex app-server runtime, and a Codex-bound throwaway internal UI session.chat.sendturn to the bound session, and forced the model to callmessage.sendwith onlyactionandmessage, with notarget,channel,to,channelId, or fallback route fields.target=current-run, persisted a delivery mirror, and a freshchat.historyreadback contained the visible assistant text.