Persist room-event observations as durable bare user transcript rows and carry an ambient transcript watermark through session state so Telegram chat windows only include the unpersisted gap.
Fixes#99257
Fail closed when managed OpenAI OAuth refresh fails instead of silently falling back to stale external Codex CLI credentials.
Make managed provider OAuth authoritative after bootstrap, preserve API-key and non-OpenAI external CLI behavior, and surface targeted re-auth guidance without exposing profile IDs in group/channel replies.
Fixes#99120.
Co-authored-by: Eva <239388517+100yenadmin@users.noreply.github.com>
* fix(interactive): preserve button command values in fallback text for degraded approval UX
* fix(interactive): keep callback values private in fallback text and narrow Feishu interactive detection
- P1: Skip rendering action.type === "callback" values in
renderMessagePresentationFallbackText to avoid leaking opaque
channel/plugin data into user-visible text. Command and legacy
values are still rendered.
- P2: Replace hasMessagePresentationBlocks/hasInteractiveReplyBlocks
with isMessagePresentationInteractiveBlock so Feishu comment
guidance only appears when the presentation actually contains
buttons or selects, not for text-only blocks.
- Update tests: callback button now shows label-only; all 137 tests pass.
* fix(interactive): only render typed command values in fallback text, keep legacy value private
* fix(feishu): gate document-comment command guidance on actual command action
* docs(message-presentation): document command/callback value fallback visibility
* fix(feishu): omit command guidance when URL overrides fallback command text
* docs: regenerate docs_map.md
* fix(interactive): exclude disabled buttons from fallback command rendering and guidance
* fix(interactive): extract hasRenderedCommandAction, exclude disabled buttons from command fallback
* fix(feishu): preserve command guidance marker through core presentation rendering
* fix(feishu): type-narrow channelData.feishu with isRecord before reading rendered-command marker
* fix(feishu): move hasRenderedCommandAction from public SDK into Feishu plugin as local helper
Keep the helper local to the only caller (Feishu outbound) instead of
adding a new public plugin SDK API contract. The shared fallback renderer
in renderMessagePresentationFallbackText already inlines the same
command-visibility logic; a local helper is sufficient for the Feishu
comment-thread guidance gate.
* refactor(feishu): tighten fallback command marker
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(config/sessions): narrow reply-session initialization revision to identity fields
The initialization guard compared the full persisted session entry, so
background touches to updatedAt, heartbeat timestamps, context-budget
metadata, etc. produced false-positive stale-snapshot conflicts and the
"reply session initialization conflicted" error.
Only sessionId and sessionFile matter for detecting a session rotation.
Narrow the revision to those identity fields and add a regression test.
Fixes#98672
* fix(config/sessions): merge current metadata when reply-init identity guard passes
* fix(config/sessions): preserve only snapshot-drifted metadata in reply-init commit
* fix: preserve cleared reply-session metadata
* fix: allow same-session reply initialization drift
---------
Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com>
Co-authored-by: Josh Lehman <josh@martian.engineering>
Summary:
- The branch updates agent tool-result truncation so live prompt projection protects trailing fresh tool-resul ... ges under the aggregate cap, adds a bounded aggregate elision marker, and extends focused truncation tests.
- PR surface: Source +54, Tests +124. Total +178 across 2 files.
- Reproducibility: yes. source-level: the linked issues give a deterministic saturated-history prompt projecti ... clear tool-result text to empty. I did not run a live WebChat or Discord session in this read-only review.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head 50069fdd6f.
- Required merge gates passed before the squash merge.
Prepared head SHA: 50069fdd6f
Review: https://github.com/openclaw/openclaw/pull/98955#issuecomment-4862947669
Co-authored-by: momothemage <niuzhengnan@163.com>
Approved-by: momothemage
Cron jobs run in the session they were created from unless the job explicitly requests an isolated fresh session.
Co-authored-by: Peter Steinberger <58493+steipete@users.noreply.github.com>
* fix(anthropic): restore Fable 5 Vertex simple completions
* test(agents): satisfy custom API model types
* test(ci): route reliability test from temp helper
* test(agents): satisfy custom API model types
* fix(agents): fail fast with attributable reason after MCP stdio session dies mid-run
Wires MCP Client onclose/onerror during bundle-mcp session creation so a
crashed/exited server flips session.connected instead of staying stale.
Next tool/resource/prompt call throws a domain-specific 'is disconnected'
error immediately instead of surfacing the SDK's generic 'Not connected'.
A disconnected reused session is retired and rebuilt fresh on the next
catalog pass rather than reused, since the SDK chains onclose/onerror
cumulatively on repeat connect() and the stdio transport never clears its
read buffer on an unexpected exit.
* fix(agents): retire a reused MCP session that dies mid-refresh, not just pre-refresh
codex review found: the catch-path retirement in getCatalog()'s per-server
task only covered two cases (fresh session that never connected this pass,
and a non-reused session that failed for any reason) - a reused session
that was healthy when this pass started but disconnects mid-refresh (child
process dies between ensureSessionConnected() returning and
listAllToolsBestEffort() finishing) hit neither branch, so onclose flipped
connected=false but the dead session object stayed in the map until the
next catalog rebuild happened to notice it. Added the missing branch plus
a regression test that kills the child process mid tools/list on a reused
session and asserts the session is purged from the map within the same
refresh (not just fail-fast on tool calls, which already worked).
* fix(agents): retire a dead reused MCP session even across overlapping catalog generations
codex round-2 review found: the mid-refresh retirement branch still
skipped when sharedWithNewerGeneration was true, which protects a
still-alive session another generation is actively using - but once
onclose flips session.connected=false, the transport is dead for every
generation sharing that object, so that guard no longer applies.
Simplified to a single !session.connected branch that always retires
(retireSessionIfCurrent already no-ops safely if a newer generation
replaced the map entry), and dropped the now-write-only
connectedForCatalog local it replaced.
* test(scripts): allow MCP SDK callback suppressions
* fix(agents): retire closed MCP sessions
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Makes native iMessage polls behave correctly end to end.
What changed:
- Inbound polls render with a numbered-options vote cue so the agent casts a native vote instead of answering the poll in prose.
- poll-vote resolves the poll reference from pollId/pollGuid/messageId and now defaults to the current inbound poll message when the model omits it; still errors when no reference exists.
- poll-vote echo suppression is session-scoped, so the redundant spoken answer is dropped across the separate poll and comment runs.
- A poll's inline-reply caption is folded (not delivered as a standalone question) only when the poll creator and reply sender are both known and equal; unknown/mismatched sender falls through to the normal inbound decision gate, so no inbound reply is silently dropped.
Evidence:
- 64 passing tests in the poll suites (poll-comment, poll-render, actions), incl. sender fail-closed regressions; pnpm build clean.
- Two Codex autoreviews clean (patch is correct); ClawSweeper re-review rated it platinum hermit.
- Live-verified on macOS 26.4.1 on the deployed gateway: poll "What color pill?" -> native vote delivered with a 7333-byte payload, caption folded, zero echo.
Note: vote delivery also depends on the imsg vote-stamp fix (openclaw/imsg#150); OpenClaw ships ahead of imsg per owner decision.
* fix(fal): route grok-imagine and nano-banana-2-lite edits to correct endpoints
The fal image-generation provider appends '/image-to-image' to any model
that isn't 'openai/gpt-image-*' or 'fal-ai/nano-banana-*' when reference
images are supplied. That's wrong for two models fal serves:
- `xai/grok-imagine-image`: fal 404s on '/image-to-image'. The real edit
endpoint is '/quality/edit'. The endpoint also expects lowercase
resolution values ('1k'/'2k' only) and a distinct aspect_ratio enum.
- `google/nano-banana-2-lite`: fal 404s on '/image-to-image'. The real
edit endpoint is '/edit'. The endpoint does not accept a 'resolution'
parameter.
Add schema entries for both models so ensureFalModelPath and
applyFalImageGeometry pick the right suffix and body shape. Introduce
resolution allowlist support ('resolutions: readonly string[]') and
lowercase transform ('resolutionCase: "lower"') on the schema; existing
schemas keep their behaviour (nb2 still forwards uppercase resolution
unchanged; flux/gpt-image/nb2/krea untouched). Refactor
ensureFalModelPath to consult schema.appendEditPath instead of hardcoded
prefix checks so future models only need a schema entry.
Tested:
- Existing 49 fal unit tests still pass; added 9 new tests covering the
two new endpoints and their guard conditions (32 -> 34 tests in the
image-generation-provider suite).
- Live fal.ai calls confirm both endpoints return 200 with real
reference images; the buggy old URLs still return 404.
* fix(fal): preserve standard edit routing
* fix(image): apply inferred resolution per model
* fix(image): preserve provider reference limits
* fix(image): resolve reference limits per model
* fix(fal): preserve nano banana family limits
* test(ios): stub generated file list helper
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>