diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b394485a33..94af07e17e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Docs: https://docs.openclaw.ai ### Changes - Codex: add Computer Use setup for Codex-mode agents, including `/codex computer-use status/install`, marketplace discovery, optional auto-install, and fail-closed MCP server checks before Codex-mode turns start. Fixes #72094. (#71842) Thanks @pash-openai. +- Plugin SDK: expose shared channel route normalization, parser-driven target resolution, raw-target compact keys, parsed-target types, and route comparison helpers through `openclaw/plugin-sdk/channel-route`, switch native approval origin matching onto that route contract with optional delivery and match-only target normalization, and retire the internal channel-route shim behind dated compatibility aliases for legacy key/comparable-target helpers. Thanks @vincentkoc. - Matrix/streaming: stream tool-progress updates into live Matrix preview edits by default when preview streaming is active, with `streaming.preview.toolProgress: false` to keep answer previews while hiding interim tool lines. Thanks @gumadeiras. - Plugins/models: wire manifest `modelCatalog.aliases` and `modelCatalog.suppressions` into model-catalog planning and built-in model suppression, with OpenAI stale Spark suppression now declared in the plugin manifest before runtime fallback. Thanks @shakkernerd. - Channels/Yuanbao: register the Tencent Yuanbao external channel plugin (`openclaw-plugin-yuanbao`) in the official channel catalog, contract suites, and community plugin docs, with a new `docs/channels/yuanbao.md` quick-start guide for WebSocket bot DMs and group chats. (#72756) Thanks @loongfay. diff --git a/docs/plugins/compatibility.md b/docs/plugins/compatibility.md index fe336e65398..93949560efe 100644 --- a/docs/plugins/compatibility.md +++ b/docs/plugins/compatibility.md @@ -111,6 +111,8 @@ Current compatibility records include: `registerMemoryCapability` - legacy channel SDK helpers for native message schemas, mention gating, inbound envelope formatting, and approval capability nesting +- legacy channel route key and comparable-target helper aliases while plugins + move to `openclaw/plugin-sdk/channel-route` - activation hints that are being replaced by manifest contribution ownership - `setup-api` runtime fallback while setup descriptors move to cold `setup.requiresRuntime: false` metadata diff --git a/docs/plugins/sdk-channel-plugins.md b/docs/plugins/sdk-channel-plugins.md index 445e29af12c..16507e8fbc1 100644 --- a/docs/plugins/sdk-channel-plugins.md +++ b/docs/plugins/sdk-channel-plugins.md @@ -57,6 +57,15 @@ id, explicit `baseConversationId`, and any `parentConversationCandidates`. When you return `parentConversationCandidates`, keep them ordered from the narrowest parent to the broadest/base conversation. +Use `openclaw/plugin-sdk/channel-route` when plugin code needs to normalize +route-like fields, compare a child thread with its parent route, or build a +stable dedupe key from `{ channel, to, accountId, threadId }`. The helper +normalizes numeric thread ids the same way core does, so plugins should prefer +it over ad hoc `String(threadId)` comparisons. +Plugins with provider-specific target grammar can inject their parser into +`resolveChannelRouteTargetWithParser(...)` and still get the same route target +shape and thread fallback semantics core uses. + Bundled plugins that need the same parsing before the channel registry boots can also expose a top-level `session-key-api.ts` file with a matching `resolveSessionConversation(...)` export. Core uses that bootstrap-safe surface @@ -87,6 +96,8 @@ Most channel plugins do not need approval-specific code. - Use `approvalCapability.describeExecApprovalSetup` when the channel wants the disabled-path reply to explain the exact config knobs needed to enable native exec approvals. The hook receives `{ channel, channelLabel, accountId }`; named-account channels should render account-scoped paths such as `channels..accounts..execApprovals.*` instead of top-level defaults. - If a channel can infer stable owner-like DM identities from existing config, use `createResolvedApproverActionAuthAdapter` from `openclaw/plugin-sdk/approval-runtime` to restrict same-chat `/approve` without adding approval-specific core logic. - If a channel needs native approval delivery, keep channel code focused on target normalization plus transport/presentation facts. Use `createChannelExecApprovalProfile`, `createChannelNativeOriginTargetResolver`, `createChannelApproverDmTargetResolver`, and `createApproverRestrictedNativeApprovalCapability` from `openclaw/plugin-sdk/approval-runtime`. Put the channel-specific facts behind `approvalCapability.nativeRuntime`, ideally via `createChannelApprovalNativeRuntimeAdapter(...)` or `createLazyChannelApprovalNativeRuntimeAdapter(...)`, so core can assemble the handler and own request filtering, routing, dedupe, expiry, gateway subscription, and routed-elsewhere notices. `nativeRuntime` is split into a few smaller seams: +- `createChannelNativeOriginTargetResolver` uses the shared channel-route matcher by default for `{ to, accountId, threadId }` targets. Pass `targetsMatch` only when a channel has provider-specific equivalence rules, such as Slack timestamp prefix matching. +- Pass `normalizeTargetForMatch` to `createChannelNativeOriginTargetResolver` when the channel needs to canonicalize provider ids before the default route matcher or a custom `targetsMatch` callback runs, while preserving the original target for delivery. Use `normalizeTarget` only when the resolved delivery target itself should be canonicalized. - `availability` — whether the account is configured and whether a request should be handled - `presentation` — map the shared approval view model into pending/resolved/expired native payloads or final actions - `transport` — prepare targets plus send/update/delete native approval messages diff --git a/docs/plugins/sdk-migration.md b/docs/plugins/sdk-migration.md index 550829a5a5b..2dddf34fea1 100644 --- a/docs/plugins/sdk-migration.md +++ b/docs/plugins/sdk-migration.md @@ -322,6 +322,30 @@ releases. + + New channel route code should use `openclaw/plugin-sdk/channel-route`. + The older route-key and comparable-target names remain as compatibility + aliases during the migration window, but new plugins should use the route + names that describe the behavior directly: + + | Old helper | Modern helper | + | --- | --- | + | `channelRouteIdentityKey(...)` | `channelRouteDedupeKey(...)` | + | `channelRouteKey(...)` | `channelRouteCompactKey(...)` | + | `ComparableChannelTarget` | `ChannelRouteParsedTarget` | + | `resolveComparableTargetForChannel(...)` | `resolveRouteTargetForChannel(...)` | + | `resolveComparableTargetForLoadedChannel(...)` | `resolveRouteTargetForLoadedChannel(...)` | + | `comparableChannelTargetsMatch(...)` | `channelRouteTargetsMatchExact(...)` | + | `comparableChannelTargetsShareRoute(...)` | `channelRouteTargetsShareConversation(...)` | + + The modern route helpers normalize `{ channel, to, accountId, threadId }` + consistently across native approvals, reply suppression, inbound dedupe, + cron delivery, and session routing. If your plugin owns custom target + grammar, use `resolveChannelRouteTargetWithParser(...)` to adapt that + parser into the same route target contract. + + + ```bash pnpm build diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md index 4f1a64f3b88..f76359292a9 100644 --- a/docs/plugins/sdk-subpaths.md +++ b/docs/plugins/sdk-subpaths.md @@ -82,7 +82,8 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview) | `plugin-sdk/channel-logging` | Channel logging helpers for inbound drops and typing/ack failures | | `plugin-sdk/channel-send-result` | Reply result types | | `plugin-sdk/channel-actions` | Channel message-action helpers, plus deprecated native schema helpers kept for plugin compatibility | - | `plugin-sdk/channel-targets` | Target parsing/matching helpers | + | `plugin-sdk/channel-route` | Shared route normalization, parser-driven target resolution, thread-id stringification, dedupe/compact route keys, parsed-target types, and route/target comparison helpers | + | `plugin-sdk/channel-targets` | Target parsing helpers; route comparison callers should use `plugin-sdk/channel-route` | | `plugin-sdk/channel-contract` | Channel contract types | | `plugin-sdk/channel-feedback` | Feedback/reaction wiring | | `plugin-sdk/channel-secret-runtime` | Narrow secret-contract helpers such as `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment`, and secret target types |