Skip to content

Commit 43121fb

Browse files
committed
fix: guard provider-prefixed delivery targets
1 parent 2218ce4 commit 43121fb

44 files changed

Lines changed: 753 additions & 25 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Docs: https://docs.openclaw.ai
3838
- Cron: make scheduler reload schedule comparison tolerate malformed persisted jobs, so one bad cron entry no longer aborts the whole tick. Fixes #75886. Thanks @samfox-ai.
3939
- Doctor/channels: warn after migrations when default Telegram or Discord accounts have no configured token and their env fallback (`TELEGRAM_BOT_TOKEN` or `DISCORD_BOT_TOKEN`) is unavailable, with secret-safe migration docs for checking state-dir `.env`. Fixes #74298. Thanks @lolaopenclaw.
4040
- Gateway/diagnostics: keep idle liveness samples in telemetry instead of visible warning logs unless diagnostic work is active, waiting, or queued. Thanks @vincentkoc.
41+
- Channels/cron: reject provider-prefixed targets for the wrong channel and let prefixed announce targets such as `telegram:123` select their channel when delivery falls back to `last`, so Telegram IDs cannot be coerced into WhatsApp phone numbers. Fixes #56839. Thanks @bencoremans.
4142
- Control UI/chat: keep live replies visible when a raw session alias such as `main` sends the chat turn but Gateway emits events under the canonical session key for the same run. Fixes #73716. Thanks @teebes.
4243
- CLI/models: reject `--agent` on `openclaw models set` and `set-image` instead of silently writing agent-scoped requests to global model defaults. Fixes #68391. Thanks @derrickabellard.
4344
- CLI: stop treating the legacy singular `openclaw tool ...` token as a plugin id under restrictive `plugins.allow`, so it falls through as a normal unknown/reserved command instead of suggesting a stale allowlist entry. Fixes #64732. Thanks @efe-arv, @SweetSophia, and @hashtag1974.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
0f9284c6349bf03d3d89c1d25031031840dae4ade032622ca212240ed19829f6 plugin-sdk-api-baseline.json
2-
33706cf425386717973cc87357ae5e0df432dd5a519b4faea8b38e21d7daae78 plugin-sdk-api-baseline.jsonl
1+
1fbd0ea7f65901d96653458ba414f9ac69dc0142ff3772e48d63de8b9fa5567f plugin-sdk-api-baseline.json
2+
2d29f4e632b05bd365f414096c87a2a3d9718f13fdbf9538824cb32db2902436 plugin-sdk-api-baseline.jsonl

docs/automation/cron-jobs.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ Before an isolated cron run enters the agent runner, OpenClaw checks reachable l
158158

159159
Use `--announce --channel telegram --to "-1001234567890"` for channel delivery. For Telegram forum topics, use `-1001234567890:topic:123`; direct RPC/config callers may also pass `delivery.threadId` as a string or number. Slack/Discord/Mattermost targets should use explicit prefixes (`channel:<id>`, `user:<id>`). Matrix room IDs are case-sensitive; use the exact room ID or `room:!room:server` form from Matrix.
160160

161+
When announce delivery uses `channel: "last"` or omits `channel`, a provider-prefixed target such as `telegram:123` can select the channel before cron falls back to session history or a single configured channel. Only prefixes advertised by the loaded plugin are provider selectors. If `delivery.channel` is explicit, the target prefix must name the same provider; for example, `channel: "whatsapp"` with `to: "telegram:123"` is rejected instead of letting WhatsApp interpret the Telegram ID as a phone number. Target-kind and service prefixes such as `channel:<id>`, `user:<id>`, `imessage:<handle>`, and `sms:<number>` remain channel-owned target syntax, not provider selectors.
162+
161163
For isolated jobs, chat delivery is shared. If a chat route is available, the agent can use the `message` tool even when the job uses `--no-deliver`. If the agent sends to the configured/current target, OpenClaw skips the fallback announce. Otherwise `announce`, `webhook`, and `none` only control what the runner does with the final reply after the agent turn.
162164

163165
When an agent creates an isolated reminder from an active chat, OpenClaw stores the preserved live delivery target for the fallback announce route. Internal session keys may be lowercase; provider delivery targets are not reconstructed from those keys when current chat context is available.

docs/channels/channel-routing.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ host configuration.
2121
- **AgentId**: an isolated workspace + session store (“brain”).
2222
- **SessionKey**: the bucket key used to store context and control concurrency.
2323

24+
## Outbound target prefixes
25+
26+
Explicit outbound targets may include a provider prefix, such as `telegram:123` or `tg:123`. Core treats that prefix as a channel-selection hint only when the selected channel is `last` or otherwise unresolved, and only when the loaded plugin advertises that prefix. If the caller already selected an explicit channel, the provider prefix must match that channel; cross-channel combinations such as WhatsApp delivery to `telegram:123` fail before plugin-specific target normalization.
27+
28+
Target-kind and service prefixes such as `channel:<id>`, `user:<id>`, `room:<id>`, `thread:<id>`, `imessage:<handle>`, and `sms:<number>` stay inside the selected channel's grammar. They do not select the provider by themselves.
29+
2430
## Session key shapes (examples)
2531

2632
Direct messages collapse to the agent’s **main** session by default:

docs/channels/synology-chat.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ Examples:
110110
```bash
111111
openclaw message send --channel synology-chat --target 123456 --text "Hello from OpenClaw"
112112
openclaw message send --channel synology-chat --target synology-chat:123456 --text "Hello again"
113+
openclaw message send --channel synology-chat --target synology:123456 --text "Short prefix"
113114
```
114115

115116
Media sends are supported by URL-based file delivery.

docs/cli/cron.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Run `openclaw cron --help` for the full command surface. See [Cron jobs](/automa
3535

3636
`openclaw cron list` and `openclaw cron show <job-id>` preview the resolved delivery route. For `channel: "last"`, the preview shows whether the route resolved from the main or current session, or will fail closed.
3737

38+
Provider-prefixed targets can disambiguate unresolved announce channels. For example, `to: "telegram:123"` selects Telegram when `delivery.channel` is omitted or `last`. Only prefixes advertised by the loaded plugin are provider selectors. If `delivery.channel` is explicit, the prefix must match that channel; `channel: "whatsapp"` with `to: "telegram:123"` is rejected. Service prefixes such as `imessage:` and `sms:` remain channel-owned target syntax.
39+
3840
<Note>
3941
Isolated `cron add` jobs default to `--announce` delivery. Use `--no-deliver` to keep output internal. `--deliver` remains as a deprecated alias for `--announce`.
4042
</Note>

extensions/bluebubbles/src/channel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export const bluebubblesPlugin: ChannelPlugin<ResolvedBlueBubblesAccount, BlueBu
129129
},
130130
},
131131
messaging: {
132+
targetPrefixes: ["bluebubbles"],
132133
normalizeTarget: normalizeBlueBubblesMessagingTarget,
133134
inferTargetChatType: ({ to }) => inferBlueBubblesTargetChatType(to),
134135
resolveOutboundSessionRoute: (params) => resolveBlueBubblesOutboundSessionRoute(params),

extensions/discord/src/channel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ export const discordPlugin: ChannelPlugin<ResolvedDiscordAccount, DiscordProbe>
218218
],
219219
},
220220
messaging: {
221+
targetPrefixes: ["discord"],
221222
normalizeTarget: normalizeDiscordMessagingTarget,
222223
resolveInboundConversation: ({ from, to, conversationId, isGroup }) =>
223224
resolveDiscordInboundConversation({ from, to, conversationId, isGroup }),

extensions/feishu/src/channel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,7 @@ export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount, FeishuProbeResul
11541154
setup: feishuSetupAdapter,
11551155
setupWizard: feishuSetupWizard,
11561156
messaging: {
1157+
targetPrefixes: ["feishu", "lark"],
11571158
normalizeTarget: (raw) => normalizeFeishuTarget(raw) ?? undefined,
11581159
resolveDeliveryTarget: ({ conversationId, parentConversationId }) => {
11591160
const directId = parseFeishuDirectConversationId(conversationId);

extensions/googlechat/src/channel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export const googlechatPlugin = createChatChannelPlugin({
144144
},
145145
groups: googlechatGroupsAdapter,
146146
messaging: {
147+
targetPrefixes: ["googlechat", "google-chat", "gchat"],
147148
normalizeTarget: normalizeGoogleChatTarget,
148149
targetResolver: {
149150
looksLikeId: (raw, normalized) => {

0 commit comments

Comments
 (0)