Move the Codex-specific PreToolUse loop relay switch into the Codex
plugin, preserve policy relays, and cover both normal and side turns.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: marchpure <marchpure@users.noreply.github.com>
Adds a Discord Activities integration so an agent can show a self-contained
HTML widget to Discord users, opened as a sandboxed Activity inside the client.
Off by default: routes, the discord_widget tool, and the launch handler register
only when channels.discord.activities is configured. OAuth identifies the user
and gates on the account allowlist; widget lookup is capability- or
instance-validated; token exchange is rate-limited; widget HTML runs in a
no-network sandboxed iframe.
Phase 3 of #107237. Removes config.apply/config.patch/restart from the
regular-agent gateway tool (mirroring Phase 2's update.run removal); only
config.get and config.schema.lookup reads remain. Persistent config changes
and restarts now go exclusively through the human-approved openclaw
delegation path — closing the last unmediated agent config-write surface.
gateway stays owner-only/control-plane gated (config reads expose secrets and
host topology). Legacy setups can re-enable writes via the existing per-agent
tool allowlist; no new config key. Net -2271 LOC.
Refs #107237
New discovery.rs browses _openclaw-gw._tcp with a lifetime mdns-sd
browser, keeps a fullname-keyed snapshot (resolved updates replace,
goodbye/TTL removes), and mirrors the native clients' TXT contract and
direct-selection gate (resolved SRV endpoint routing; tailnetDns is a
hint only). The bootstrap page lists discovered gateways and connecting
navigates the dashboard WebView to the resolved endpoint, validated
against the live snapshot; remote selection cancels the local watchdog
so an in-flight local bootstrap cannot steal the WebView back.
* fix(codex): use structured turn status for aborts, repair tool schemas, relay native results to middleware
- turn aborts are detected from the correlated turn/completed status instead
of byte-matching private codex-rs prose; the <turn_aborted> marker remains a
non-terminal user-interrupt hint (tags only, wording-independent) because the
app-server collapses all abort reasons into "interrupted" (#99268)
- dynamic-tool schemas are repaired before projection via the shared OpenAI
normalizer: annotation nulls stripped, type:null inferred from object/array
shape hints; unrepairable null constraints stay quarantined instead of
widening the schema (#106277, #97913)
- Codex-native tool results now flow through agentToolResultMiddleware at the
post_tool_use relay boundary (observe-only: the Codex PostToolUse contract
cannot replace a native tool response) (#95597)
* test(codex): regenerate prompt snapshots for normalized dynamic-tool schemas
The shared OpenAI strict-compat normalization now runs on Codex dynamic tools,
so empty object schemas gain additionalProperties:false and required:[] in the
snapshot payloads, matching what the OpenAI provider family sends.
* refactor(tui): move last session state to sqlite
* chore: keep release notes in PR body
* test: update doctor migration fixture
* chore: satisfy dead code export gate
* feat(ui): add follow-up behavior setting (queue vs steer) for active runs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* default follow-up behavior to steer
Follow-ups sent while a run is active now steer into the running turn by
default; queue mode becomes the persisted opt-out. Offline/disconnected
sends still always queue.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(ui): steer active follow-ups by default
---------
Co-authored-by: openclaw-clawsweeper[bot] <openclaw-clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(config): reject zero-value resetArchiveRetention to prevent silent data loss
* fix: add braces to guard clauses for curly lint rule
* fix: normalize numeric values and cover pruneAfter fallback in migration
* fix: reject zero-value pruneAfter at schema level to close fallback gap
* fix: independently check and repair both retention fields in migration
* fix: split doctor diagnostics into field-specific rules and messages
* fix: remove unused local in migration test helper
* fix: repair 5 lint errors (curly braces, zero-fraction, narrow value)
* fix(doctor): rewrite zero resetArchiveRetention to false instead of deleting it
Deleting a zero resetArchiveRetention caused the runtime to fall back to
pruneAfter (default 30d), which contradicted the doctor output that
claimed archives would be kept indefinitely. Only an explicit false
value produces indefinite retention per the documented schema.
- P1: Rewrite zero resetArchiveRetention to false in the doctor
migration apply callback, matching the promised indefinite-retention
behavior.
- P3: Update the pruneAfter rule warning to describe eligible
stale/non-preserved session entries instead of "all sessions".
* fix(config): repair zero retention safely
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
* fix(config): warn before stripping JSON5 comments on config write
Add checkCommentLossWarning in json5-comments.ts to detect JSON5 comments
before config writes. Warn via deps.logger.warn for main config writes and
via options.warn for $include file writes. Both paths support skipOutputLogs
to suppress warnings during automated operations.
Fixes#105683
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(config): remove public warn callback, route through internal sink
Fixes#105683
- Remove warn field from exported ConfigWriteOptions (P1 merge-risk)
- Default checkCommentLossWarning to console.warn when no callback
- Move include warning after hash-conflict/rejection checks
- Update tests to spy on console.warn instead of custom callback
* fix(config): warn before stripping JSON5 comments
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
* refactor(plugin-sdk)!: delete the zero-consumer channel-ingress facade, AccessFacts projections, and dead dispatch aliases
* chore(plugin-sdk): refresh API baseline hash for the facade deletions
* fix(channels): drop dead AccessFacts field writes stranded by the facade deletion
* chore(plugin-sdk): refresh API baseline hash after rebase