* fix (Computer Use) Stabilize Codex Computer Use readiness
Co-authored-by: Ben Badejo <188106718+bdjben@users.noreply.github.com>
* fix (Computer Use) Stabilize Codex Computer Use readiness
* fix (Computer Use) Stabilize Codex Computer Use readiness
* fix (Computer Use) Stabilize Codex Computer Use readiness
* fix(clawsweeper): address review for automerge-openclaw-openclaw-103331 (1)
* fix (Computer Use) Stabilize Codex Computer Use readiness
---------
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Ben Badejo <188106718+bdjben@users.noreply.github.com>
The Codex app-server projector now caps native tool output at 10k chars before it reaches OpenClaw's replayable surfaces (transcript tool results, trajectory output, progress text, streamed delta accumulation, MCP/dynamic tool text), with an explicit truncation notice carrying the original length. Assistant-item echo suppression is scoped to raw-lane promotions with bounded multi-shape signatures: typed agentMessage finals are never content-filtered (verbatim tool-output answers are preserved), fine-grained streams cannot evict the start-summary signature, and the post-truncation prefix freeze from main is restored so surrogate-boundary cuts cannot corrupt echo matching. This closes the projector-side replay amplification from #99465; native/provider-side replay budgets remain tracked in #99551.
Fixes#99465
Thanks to Eva (@100yenadmin) for the contribution.
* fix(codex-dynamic-tools): use truncateUtf16Safe for notice text truncation
* fix(codex): keep dynamic tool text UTF-16 safe
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Adds client-capability-gated tool availability: gateway clients declare
capabilities at connect (new inline-widgets cap), chat.send stamps them into
the run context, and every tool assembly path (embedded runner, queued
followups, Codex app-server harness, plugin-only construction plans) drops
tools whose requiredClientCaps the originating client did not declare. The
Canvas plugin ships the first such tool, show_widget: agents pass SVG or an
HTML fragment plus a title; the plugin hosts it as a bounded, retention-scoped
Canvas document and returns the existing canvas preview handle, which web chat
renders as a sandboxed iframe fitted to the widget's reported content height.
Widget frames never get allow-same-origin (per-preview sandbox ceiling,
including the sidebar path) and the Canvas host serves widget documents with a
CSP sandbox header so direct navigation runs in an opaque origin. Verified
live end-to-end on a Testbox with gpt-5.5 (screenshots on the PR). CLI-backed
model backends do not carry client caps yet and stay fail-closed (#102577).
Closes#101790
* fix(codex): use truncateUtf16Safe for tool transcript output truncation
Replace naive .slice(0, N) with truncateUtf16Safe() in event-projector
tool transcript output text to prevent surrogate pair splitting.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(codex): keep streamed output utf16-safe
* refactor(codex): use plugin sdk text runtime
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(codex): use truncateUtf16Safe for attempt notification text truncation
.slice(0, 237) on notification text can split surrogate pairs from
CJK characters or emoji in agent output, producing U+FFFD in Codex
desktop notifications.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(codex): cover UTF-16-safe attempt previews
* test(codex): assign notification coverage to a shard
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat(codex): scope app-server rate limits to the physical client
Replace the process-global rate-limit cache with a WeakMap keyed by the
physical app-server client, tracking per-limitId revisions. Rolling
account/rateLimits/updated notifications merge sparsely per the protocol
contract (credits/individualLimit/planType survive nulls), and
usage-limit errors only trust a snapshot for auth-profile blocking when
the same client observed a primary update during the failing turn's
startup. Fixes cross-client rate-limit bleed in usage-limit error
messages. A new client-runtime module installs the
account/chatgptAuthTokens/refresh handler and the rate-limit observer
once per physical client, replacing per-start inline handlers in
shared-client, run-attempt, and side-question.
* refactor(codex): split thread/resume subscription safety into thread-resume
Move the thread/resume request out of thread-lifecycle into a dedicated
thread-resume module that retires the exact physical client when resume
acceptance is indeterminate: only a structured RPC rejection proves
Codex holds no subscription, so any other failure abandons the client
instead of returning it to the shared pool. Resume responses naming a
different thread now fail closed (assertCodexThreadResumeSubscription),
and the fresh-thread fallback requires a released subscription unless
the resume was a proven RPC rejection.
* refactor(codex): replace client-factory positional DI with shared-client factory
Delete the lazy positional-argument CodexAppServerClientFactory and use
the options-object factory type exported from shared-client. Callers in
run-attempt, compact, bounded-turn, provider-capabilities, and the
web-search provider now default to getLeasedSharedCodexAppServerClient
directly; the lazy indirection was ineffective because those modules
already import shared-client statically.
* feat(codex): route app-server turn traffic through a keyed turn router
Install one turn router per physical app-server client and replace the
broad per-attempt notification/request fanout with explicit per-thread
routes. Attempt startup reserves the thread route (before thread/resume
on the resume path, so early notifications buffer instead of racing),
run-attempt activates it with receive-time, queued, and request
handlers, arms the route before turn/start, binds the accepted turn id
to flush buffered traffic in wire order, and releases the route on
cleanup. Requests for a pending turn wait for binding instead of being
auto-declined, native turn completion waits use route state instead of
scanning buffered notifications, and correlation readers now match the
canonical v2 wire shapes only (top-level threadId, nested turn.id). The
unscoped response-delta lease-count attribution and its client API are
deleted along with the retired correlation predicates.
* test(codex): reset the shared binding store between thread-lifecycle tests
SQLite bindings are keyed by session identity rather than the per-test
temp dir, so earlier tests leaked resumable threads into fresh-start
expectations. The old silent resume-failure fallback masked the leak;
subscription safety surfaces it.
* test(codex): reset the binding store between delivery-hint iterations
The loop reuses one session identity across iterations, so the previous
iteration's thread would resume against a harness that cannot serve it.
* refactor(codex): raise app-server floor to 0.142 and drop range-compat protocol paths
* refactor(codex): model subagent mirror state as one map
* style(codex): format event-projector
* test(codex): drop unused shared-client test import
* refactor(codex): drop v1-era notification field aliases
* fix(codex): teach models to load deferred native spawn_agent via tool_search
* docs(codex): realign harness config tables
* docs(changelog): note Codex app-server protocol update