Commit Graph
9396 Commits
Author SHA1 Message Date
Peter Steinberger ec45c317f5 fix(gateway): block trusted-proxy control-ui node bypass 2026-02-26 01:54:19 +01:00
codexGWandSamantha 6fb082e131 fix(typing): call markDispatchIdle in followup runner to prevent stuck indicator (#26881)
The followup runner (used for queued messages, inter-agent sends,
heartbeat followups, etc.) only called typing.markRunComplete() in
its finally block.  The typing controller requires BOTH markRunComplete
AND markDispatchIdle to trigger cleanup — but markDispatchIdle was
only wired through the buffered dispatcher path, which followup turns
bypass entirely.

This caused the typing indicator to persist indefinitely on channels
like Telegram when the agent replied with NO_REPLY or produced empty
payloads, because the keepalive loop was never stopped.

Adds markDispatchIdle() alongside markRunComplete() in the followup
runner's finally block, and four test cases covering NO_REPLY, empty
payloads, agent errors, and successful delivery.

Complements #26295 which addressed the channel-level callback layer.

Fixes #26595

Co-authored-by: Samantha <[email protected]>
2026-02-26 00:53:38 +00:00
Peter Steinberger 70e31c6f68 fix(gateway): harden hooks URL parsing (#26864) 2026-02-26 00:47:35 +00:00
Aleksandrs Tihenko c0026274d9 fix(auth): distinguish revoked API keys from transient auth errors (#25754)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8f9c07a200644284e11adae76368adab40c5fa4e
Co-authored-by: rrenamed <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
2026-02-25 19:47:16 -05:00
Peter Steinberger f312222159 test: preserve config exports in agent handler mock 2026-02-26 00:42:51 +00:00
Peter Steinberger aaeed3c4ea test(agents): add missing announce delivery regressions 2026-02-26 00:38:34 +00:00
Peter Steinberger 20c2db2103 refactor(gateway): split browser auth hardening paths 2026-02-26 01:37:00 +01:00
Peter Steinberger 8f8e46d898 refactor: unify reaction ingress policy guards across channels 2026-02-26 01:34:47 +01:00
4258a3307f refactor(agents): unify subagent announce delivery pipeline
Co-authored-by: Smith Labs <[email protected]>
Co-authored-by: Do Cao Hieu <[email protected]>
2026-02-26 00:30:44 +00:00
Peter Steinberger aedf62ac7e fix: harden discord and slack reaction ingress authorization 2026-02-26 01:26:47 +01:00
Peter Steinberger c736f11a16 fix(gateway): harden browser websocket auth chain 2026-02-26 01:22:49 +01:00
Peter Steinberger f41715a18f refactor(browser): split act route modules and dedupe path guards 2026-02-26 01:21:34 +01:00
Peter Steinberger 046feb6b0e refactor: simplify telegram event authorization flow 2026-02-26 01:14:05 +01:00
Peter Steinberger 496a76c03b fix(security): harden browser trace/download temp path handling 2026-02-26 01:04:05 +01:00
Peter Steinberger e56b0cf1a0 fix: enforce telegram reaction authorization 2026-02-26 01:03:03 +01:00
Peter Steinberger c6dfa26f03 refactor(signal): unify reaction auth flow and table-drive tests 2026-02-26 01:02:05 +01:00
Shakker a0a229a3bb Discord: align embed fallback in thread starter parsing 2026-02-25 23:58:42 +00:00
User 39cc547f74 fix(discord): include embed title in fallback text (#26907) 2026-02-25 23:58:42 +00:00
Peter Steinberger b090d6019b test(agent-runner): add overflow empty-payload regression coverage (#26905) 2026-02-25 23:57:58 +00:00
Peter Steinberger 42f455739f fix(security): clarify denyCommands exact-match guidance 2026-02-26 00:55:35 +01:00
Peter SteinbergerandMark Shields eb73e87f18 fix(session): prevent silent overflow on parent thread forks (#26912)
Lands #26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <[email protected]>
2026-02-25 23:54:02 +00:00
Peter Steinberger 8d1481cb4a fix(gateway): require pairing for unpaired operator device auth 2026-02-26 00:52:50 +01:00
Peter Steinberger 2aa7842ade fix(signal): enforce auth before reaction notification enqueue 2026-02-26 00:44:46 +01:00
Peter Steinberger ef326f5cd0 fix(browser): revalidate upload paths at use time 2026-02-26 00:40:56 +01:00
Youyou972andshakkernerd 15cfba7075 fix: cron model fallback to agent defaults when payload.model fails (#26717)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 06454bd55b44ea864c10ad828649b293946cea8d
Co-authored-by: Youyou972 <[email protected]>
Co-authored-by: shakkernerd <[email protected]>
Reviewed-by: @shakkernerd
2026-02-25 23:34:31 +00:00
Peter SteinbergerandSid 2011edc9e5 fix(gateway): preserve agentId through gateway send path
Landed from #23249 by @Sid-Qin.
Includes extra regression tests for agentId precedence + blank fallback.

Co-authored-by: Sid <[email protected]>
2026-02-25 23:31:35 +00:00
Peter Steinberger 125f4071bc fix(gateway): block agents.files symlink escapes 2026-02-26 00:31:08 +01:00
Shadow 975c9f4b54 Agents: emphasize config.schema usage 2026-02-25 09:45:39 -06:00
Ubuntu a182afcf97 style: expand curly braces per oxfmt 2026-02-25 14:49:21 +02:00
Ubuntu ae658aa84c style: add curly braces to satisfy eslint(curly) 2026-02-25 14:49:21 +02:00
Ubuntu 97eb5542e8 fix(typing): guard fireStart against post-close invocation
The existing `closed` flag in `createTypingCallbacks` guards
`onReplyStart` but not `fireStart` itself. If a keepalive tick is
already in-flight when `fireStop` sets `closed = true` and calls
`keepaliveLoop.stop()`, the running `onTick → fireStart` callback
still completes and sends a stale `sendChatAction('typing')` after
the reply message has been delivered.

On Telegram (which has no cancel-typing API), this causes the typing
indicator to linger ~5 seconds after the bot's message appears.

Add a `closed` early-return in `fireStart` as defense-in-depth so
that even an in-flight tick is suppressed once cleanup has started.
2026-02-25 14:49:21 +02:00
Nimrod GutmanandAyaan Zaidi b3f46f0e28 fix(test): stabilize low-mem parallel runner and cron session mock (#26324)
* fix(test): stabilize low-mem parallel lane and cron session mock

* feat(android): make QR scanning first-class onboarding

* docs(android): update README for native Android workflow

* fix(android): stabilize chat composer ime and tab layout

* fix(android): stabilize chat ime insets and tab bar

* fix(android): remove tab bar gap above system nav

* fix(android): harden scanned setup code parsing

* test(android): cover non-string setupCode QR payload

* fix(test): add changelog note for low-mem test runner (#26324) (thanks @ngutman)

---------

Co-authored-by: Ayaan Zaidi <[email protected]>
2026-02-25 12:16:17 +02:00
Nimrod Gutman a0fa283839 fix(discord): prevent stuck typing indicator 2026-02-25 10:21:52 +02:00
Ayaan Zaidi fb76e316fb fix(test): use valid brave ui_lang locale 2026-02-25 11:58:52 +05:30
Brian Mendonca 6bc7544a6a fix(telegram): fail closed on empty group allowFrom override 2026-02-25 11:54:27 +05:30
Peter Steinberger b247cd6d65 fix: harden Slack file-only fallback placeholder (#25181) (thanks @justinhuangcode) 2026-02-25 05:36:49 +00:00
justinhuangcodeandClaude Opus 4.6 a6337be3d1 refactor: use MAX_SLACK_MEDIA_FILES constant for file-only fallback
Replace the hardcoded limit of 5 with the existing
MAX_SLACK_MEDIA_FILES constant (8) from media.ts for consistency.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-25 05:36:49 +00:00
justinhuangcode def28a87b2 fix(slack): deliver file-only messages when all media downloads fail
When a Slack message contains only files/audio (no text) and every file
download fails, `resolveSlackMedia` returns null and `rawBody` becomes
empty, causing `prepareSlackMessage` to silently drop the message.

Build a fallback placeholder from the original file names so the agent
still receives the message, matching the pattern already used in
`resolveSlackThreadHistory` for file-only thread entries.

Closes #25064
2026-02-25 05:36:49 +00:00
byungsker 177386ed73 fix(tui): resolve wrong provider prefix when session has model without modelProvider (#25874)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f0953a72845fb3f9e8745cb6ab476cea7a5cd98b
Co-authored-by: lbo728 <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras
2026-02-25 00:36:27 -05:00
Peter Steinberger 52d933b3a9 refactor: replace bot.molt identifiers with ai.openclaw 2026-02-25 05:03:24 +00:00
GlucksbergandPeter Steinberger 6e97470515 fix(brave-search): clarify ui_lang and search_lang format requirements (#25130)
* fix(brave-search): swap ui_lang and search_lang formats (#23826)

* fix(web-search): normalize Brave ui_lang/search_lang params

---------

Co-authored-by: Peter Steinberger <[email protected]>
2026-02-25 04:59:38 +00:00
c1964e73a8 fix(discord): gate component command authorization for guild interactions (#26119)
* Discord: gate component command authorization

* test: cover allowlisted guild component authorization path (#26119) (thanks @bmendonca3)

---------

Co-authored-by: Brian Mendonca <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
2026-02-25 04:57:41 +00:00
David RudduckandPeter Steinberger 24a60799be fix(hooks): include guildId and channelName in message_received metadata (#26115)
* fix(hooks): include guildId and channelName in message_received metadata

The message_received hook (both plugin and internal) already exposes
sender identity fields (senderId, senderName, senderUsername, senderE164)
but omits the guild/channel context. Plugins that track per-channel
activity receive NULL values for channel identification.

Add guildId (ctx.GroupSpace) and channelName (ctx.GroupChannel) to the
metadata block in both the plugin hook and internal hook dispatch paths.
These properties are already populated by channel providers (e.g. Discord
sets GroupSpace to the guild ID and GroupChannel to #channel-name) and
used elsewhere in the codebase (channels/conversation-label.ts).

* test: cover guild/channel hook metadata propagation (#26115) (thanks @davidrudduck)

---------

Co-authored-by: Peter Steinberger <[email protected]>
2026-02-25 04:56:19 +00:00
2e84017f23 fix(markdown): require paired || delimiters for spoiler detection (#26105)
* fix(markdown): require paired || delimiters for spoiler detection

An unpaired || (odd count across all inline tokens) would open a
spoiler that never closes, causing closeRemainingStyles to extend it
to the end of the text. This made all content after an unpaired ||
appear as hidden/spoiler in Telegram.

Pre-count || delimiters across the entire inline token group and skip
spoiler injection entirely when the count is less than 2 or odd. This
prevents single | characters and unpaired || from triggering spoiler
formatting.

Closes #26068

Co-authored-by: Cursor <[email protected]>

* fix: preserve valid spoiler pairs with trailing unmatched delimiters (#26105) (thanks @Sid-Qin)

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
2026-02-25 04:54:51 +00:00
156f13aa64 fix(agents): continue fallback loop for unrecognized provider errors (#26106)
* fix(agents): continue fallback loop for unrecognized provider errors

When a provider returns an error that coerceToFailoverError cannot
classify (e.g., custom error messages without standard HTTP status
codes), the fallback loop threw immediately instead of trying the
next candidate. This caused fallback to stop after 2 models even
when 17 were configured.

Only rethrow unrecognized errors when they occur on the last
candidate. For intermediate candidates, record the error as an
attempt and continue to the next model.

Closes #25926

Co-authored-by: Cursor <[email protected]>

* test: cover unknown-error fallback telemetry and land #26106 (thanks @Sid-Qin)

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
2026-02-25 04:53:26 +00:00
f7de41ca20 fix(followup): fall back to dispatcher when same-channel origin routing fails (#26109)
* fix(followup): fall back to dispatcher when same-channel origin routing fails

When routeReply fails for an originating channel that matches the
session's messageProvider, the onBlockReply callback was created by
that same channel's handler and can safely deliver the reply.
Previously the payload was silently dropped on any routeReply failure,
causing Feishu DM replies to never reach the user.

Cross-channel fallback (origin ≠ provider) still drops the payload to
preserve origin isolation.

Closes #25767

Co-authored-by: Cursor <[email protected]>

* fix: allow same-channel followup fallback routing (#26109) (thanks @Sid-Qin)

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
2026-02-25 04:52:08 +00:00
Brian Mendonca 19d2a8998b security(line): cap unsigned webhook body read budget 2026-02-25 04:50:50 +00:00
Peter Steinberger 146c92069b fix: stabilize live docker test handling 2026-02-25 04:35:05 +00:00
Peter Steinberger 9beec48e9c refactor(agents): centralize model fallback resolution 2026-02-25 04:32:31 +00:00
Peter Steinberger dd6ad0da8c test(exec): stabilize Windows PATH prepend assertion 2026-02-25 04:29:48 +00:00