* fix(feishu): use message create_time instead of Date.now() for Timestamp field
When a message is sent offline and later retried by the Feishu client
upon reconnection, Date.now() captures the *delivery* time rather than
the *authoring* time. This causes downstream consumers to see a
timestamp that can be minutes or hours after the user actually composed
the message, leading to incorrect temporal semantics — for example, a
"delete this" command may target the wrong resource because the agent
believes the instruction was issued much later than it actually was.
Replace every Date.now() used for message timestamps with the original
create_time from the Feishu event payload (millisecond-epoch string),
falling back to Date.now() only when the field is absent. The
definition is also hoisted to the top of handleFeishuMessage so that
both the pending-history path and the main inbound-payload path share
the same authoritative value.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test(feishu): verify Timestamp uses message create_time
Add two test cases:
1. When create_time is present, Timestamp must equal the parsed value
2. When create_time is absent, Timestamp falls back to Date.now()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: revert unrelated formatting change to lifecycle.test.ts
This file was inadvertently formatted in a prior commit. Reverting to
match main and keep the PR scoped to the Feishu timestamp fix only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(feishu): use message create_time for inbound timestamps (#52809) (thanks @schumilin)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: George Zhang <georgezhangtj97@gmail.com>
* fix(feishu): close WebSocket connections on monitor stop/abort
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test(feishu): add WebSocket cleanup tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(feishu): close WebSocket connections on monitor stop (#52844) (thanks @schumilin)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: George Zhang <georgezhangtj97@gmail.com>
Groups configured with groupPolicy: open are expected to respond to all
messages. Previously, requireMention defaulted to true regardless of
groupPolicy, causing image (and other non-text) messages to be silently
dropped because they cannot carry @-mentions.
Fix: when groupPolicy is 'open' and requireMention is not explicitly
configured, resolve it to false instead of true. Users who want
mention-required behaviour in open groups can still set requireMention: true
explicitly.
Adds three regression tests covering the new default, explicit override, and
the unchanged allowlist-policy behaviour.
Closes#52553
When OpenClaw restarts under load, the Feishu bot-info probe
(`/open-apis/bot/v3/info`) can exceed the 10-second timeout due to
event-loop contention during channel initialization. This leaves
`botOpenId` empty, causing `checkBotMentioned()` to return `false`
for every group message — silently dropping them all while DMs
continue to work fine.
Two fixes:
1. **Increase startup probe timeout from 10s to 30s** and make it
configurable via `OPENCLAW_FEISHU_STARTUP_PROBE_TIMEOUT_MS` env var.
The previous 10s budget was too tight when multiple channels
(Slack, Discord, Feishu) initialize concurrently.
2. **Graceful degradation in `checkBotMentioned()`**: when `botOpenId`
is unknown, return `true` (assume mentioned) instead of `false`.
This prevents group messages from being silently discarded when the
probe fails for any reason. The trade-off is that the bot may
respond to non-@-mentioned messages temporarily until the next
successful probe, which is far preferable to total silence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The `createMessageToolCardSchema()` helper returned a bare `Type.Object()`
which TypeBox treats as required when merged into the parent tool schema via
`Type.Object({ card: ... })`. This caused schema validation to reject
media-only sends on Feishu and MSTeams with "must have required property
card", even though the implementation correctly treats card as optional.
Wrap the return value in `Type.Optional()` so the card field is excluded
from the JSON Schema `required` array. Fixes the catch-22 where omitting
card fails validation and including an empty card triggers the runtime
"does not support card with media" guard.
Closes#53697
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(plugins): enforce min host versions
* fix(plugins): tighten min host version validation
* chore(plugins): trim dead min host version code
* fix(plugins): handle malformed min host metadata
* fix(plugins): key manifest cache by host version
* fix(plugin-sdk): remove relative extension boundary escapes
* Gate new plugin-sdk subpaths on host version
* Add changelog entry for #51939
* Fix local staging for plugin-sdk host version gate
* Raise host floor for line and googlechat plugins
---------
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>