* fix(cron): cap trigger script tool access
Persist the creator tool cap for any cron job with a trigger script and pass it to the headless trigger runtime. System event and command payloads retain the cap across cron updates.
* fix(cron): persist trigger tool cap for systemEvent and command payloads
The creator tool cap is stamped on systemEvent and command payloads whenever a
cron job carries a trigger script, but the SQLite codec dropped
payload.toolsAllow for those kinds. After a gateway restart the reloaded job
carried no cap and the trigger regained the full coding surface. Persist and
restore toolsAllow through the existing payload_tools_allow_json column for all
payload kinds, and add restart-aware round-trip coverage.
* ci: re-trigger workflows (transient self-hosted runner flake)
* fix(cron): use expectDefined for store test job access
* refactor(cron): hoist cron tool types, payload merge, and wire types into companion modules
Keeps the oversized cron files at or below their baseline line counts for the
changed-file TypeScript LOC ratchet on main. No behavior change.
* fix(cron): retain freshly stamped cap markers
* test(ci): align compact shard count
* fix(cron): make trigger cap updates atomic
* fix(cron): preserve explicit cap provenance
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
- session_end with a provably different nextSessionKey (dashboard "New Chat",
fork child) no longer permanently retires the still-live parent Codex
binding; same-key rollovers, unknown-key ends, and terminal ends retire as
before (#106778)
- mirrored session-history reads treat well-formed non-Codex transcripts as an
empty mirror instead of a read failure, so codex harness hooks stop warning
on every non-Codex model run; corrupted session headers stay on the warn
path (#106556)
* 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(tlon): keep fragment image URLs as media
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
* test(tlon): prove fragment image media send path
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
* test(tlon): remove mocked fragment outbound proof
Keep the PR evidence scoped to the helper-level regression test until live Tlon proof is available. The mocked outbound test was not sufficient for the reviewer-requested live behavior proof and triggered serialized-state review noise.
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
* docs: refresh docs map for CI
Regenerate docs/docs_map.md after syncing with upstream/main so the docs map check passes on this PR branch.
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
* fix(tlon): constrain fragment image URL matching
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
* fix(tlon): harden image URL classification
Co-authored-by: VectorPeak <garrufariw@gmail.com>
---------
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Co-authored-by: VectorPeak <VectorPeak@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(github-copilot): reject unsupported OAuth enterprise domain before refresh and model routing
Legacy github-copilot OAuth credentials can carry a non-github.com
enterpriseUrl. The token-refresh path templated it into the endpoint and
sent the bearer refresh token there with no allowlist, and the model
routing path derived a base URL from the same credential, so an unexpired
credential kept routing its access token to that origin without ever
reaching a refresh.
A persisted credential origin that is not on the Copilot host allowlist
is now rejected before any request is issued and before any model URL is
produced. Because an off-allowlist origin means the stored access token
may itself have been minted by that origin, the credential is refused as
a whole rather than coerced to github.com: modifyModels withholds the
github-copilot models so the token has no route, and its proxy-ep is
never trusted. Login rejects an unsupported host up front, so every path
that turns a domain into a bearer-bearing URL validates first.
formatAuthDoctorHint guides affected users to re-authenticate, mirroring
the qwen-portal hint. Supported hosts are unchanged: github.com and
*.ghe.com data-residency tenants still route and refresh as before.
The allowlist plus a new isSupportedGithubCopilotDomain predicate move to
a dependency-free plugin-sdk leaf so the core OAuth runtime can share them
without closing a module cycle; plugin-sdk/provider-auth re-exports
normalizeGithubCopilotDomain, so the plugin-owned GitHub Copilot provider
keeps its existing import.
Fixes#103078.
* fix(github-copilot): resolve provider auth base conflict
* fix(github-copilot): resolve provider auth base conflict
* fix(github-copilot): validate token proxy endpoint
* fix(github-copilot): remove stale helper import
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>