feat(plugin-sdk): add presentation and skills runtime contracts

This commit is contained in:
Peter Steinberger
2026-04-21 21:17:41 +01:00
parent 78030d0d52
commit d7a173e60e
9 changed files with 62 additions and 19 deletions

View File

@@ -1,2 +1,2 @@
f135ddc1802b7f8b2d29bf495fd0ac1f497a89bab8164ca8c7c8f18efc010e6e plugin-sdk-api-baseline.json
a47d06095ec5c3701a94888a11e89700d8a8511db46fa3122fb9407e160707b6 plugin-sdk-api-baseline.jsonl
cfeee4630cb43ffc4d702f207d28d35962c6458aa8fd2b1671c35e0be158bb35 plugin-sdk-api-baseline.json
af4fbf19861c6ec000b41ac5a3ded597700e45bb15f8b1d74bb2d1f550bd09b6 plugin-sdk-api-baseline.jsonl

View File

@@ -1251,16 +1251,19 @@ Compatibility note:
## Message tool schemas
Plugins should own channel-specific `describeMessageTool(...)` schema
contributions. Keep provider-specific fields in the plugin, not in shared core.
contributions for non-message primitives such as reactions, reads, and polls.
Shared send presentation should use the generic `MessagePresentation` contract
instead of provider-native button, component, block, or card fields.
For shared portable schema fragments, reuse the generic helpers exported through
`openclaw/plugin-sdk/channel-actions`:
Send-capable plugins declare what they can render through message capabilities:
- `createMessageToolButtonsSchema()` for button-grid style payloads
- `createMessageToolCardSchema()` for structured card payloads
- `presentation` for semantic presentation blocks (`text`, `context`, `divider`, `buttons`, `select`)
- `delivery-pin` for pinned-delivery requests
If a schema shape only makes sense for one provider, define it in that plugin's
own source instead of promoting it into the shared SDK.
Core decides whether to render the presentation natively or degrade it to text.
Do not expose provider-native UI escape hatches from the generic message tool.
Deprecated SDK helpers for legacy native schemas remain exported for existing
third-party plugins, but new plugins should not use them.
## Channel target resolution

View File

@@ -109,13 +109,13 @@ explicitly promotes one as public.
| `plugin-sdk/allowlist-config-edit` | Allowlist config edit/read helpers |
| `plugin-sdk/group-access` | Shared group-access decision helpers |
| `plugin-sdk/direct-dm` | Shared direct-DM auth/guard helpers |
| `plugin-sdk/interactive-runtime` | Interactive reply payload normalization/reduction helpers |
| `plugin-sdk/interactive-runtime` | Semantic message presentation, delivery, and legacy interactive reply helpers |
| `plugin-sdk/channel-inbound` | Compatibility barrel for inbound debounce, mention matching, mention-policy helpers, and envelope helpers |
| `plugin-sdk/channel-mention-gating` | Narrow mention-policy helpers without the broader inbound runtime surface |
| `plugin-sdk/channel-location` | Channel location context and formatting helpers |
| `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` | `createMessageToolButtonsSchema`, `createMessageToolCardSchema` |
| `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-contract` | Channel contract types |
| `plugin-sdk/channel-feedback` | Feedback/reaction wiring |

View File

@@ -321,6 +321,10 @@
"types": "./dist/plugin-sdk/plugin-runtime.d.ts",
"default": "./dist/plugin-sdk/plugin-runtime.js"
},
"./plugin-sdk/skills-runtime": {
"types": "./dist/plugin-sdk/skills-runtime.d.ts",
"default": "./dist/plugin-sdk/skills-runtime.js"
},
"./plugin-sdk/channel-secret-basic-runtime": {
"types": "./dist/plugin-sdk/channel-secret-basic-runtime.d.ts",
"default": "./dist/plugin-sdk/channel-secret-basic-runtime.js"

View File

@@ -66,6 +66,7 @@
"simple-completion-runtime",
"speech-core",
"plugin-runtime",
"skills-runtime",
"channel-secret-basic-runtime",
"channel-secret-runtime",
"channel-secret-tts-runtime",

View File

@@ -1,3 +1,7 @@
import { Type } from "@sinclair/typebox";
import type { TSchema } from "@sinclair/typebox";
import { stringEnum as createStringEnum } from "../agents/schema/typebox.js";
export {
createUnionActionGate,
listTokenSourcedAccounts,
@@ -20,11 +24,11 @@ export { withNormalizedTimestamp } from "../agents/date-time.js";
export { assertMediaNotDataUrl } from "../agents/sandbox-paths.js";
export { resolvePollMaxSelections } from "../polls.js";
export { optionalStringEnum, stringEnum } from "../agents/schema/typebox.js";
import { Type } from "@sinclair/typebox";
import type { TSchema } from "@sinclair/typebox";
import { stringEnum as createStringEnum } from "../agents/schema/typebox.js";
/** Schema helper for channels that expose button rows on the shared `message` tool. */
/**
* @deprecated Use semantic `presentation` capabilities instead of exposing
* provider-native button schemas through the shared message tool.
*/
export function createMessageToolButtonsSchema(): TSchema {
return Type.Optional(
Type.Array(
@@ -42,7 +46,10 @@ export function createMessageToolButtonsSchema(): TSchema {
);
}
/** Schema helper for channels that accept provider-native card payloads. */
/**
* @deprecated Use semantic `presentation` capabilities instead of exposing
* provider-native card schemas through the shared message tool.
*/
export function createMessageToolCardSchema(): TSchema {
return Type.Optional(
Type.Object(

View File

@@ -7,11 +7,29 @@ export type {
InteractiveReplyOption,
InteractiveReplySelectBlock,
InteractiveReplyTextBlock,
MessagePresentation,
MessagePresentationBlock,
MessagePresentationButton,
MessagePresentationButtonStyle,
MessagePresentationButtonsBlock,
MessagePresentationContextBlock,
MessagePresentationDividerBlock,
MessagePresentationOption,
MessagePresentationSelectBlock,
MessagePresentationTextBlock,
MessagePresentationTone,
ReplyPayloadDelivery,
ReplyPayloadDeliveryPin,
} from "../interactive/payload.js";
export {
hasInteractiveReplyBlocks,
hasMessagePresentationBlocks,
hasReplyChannelData,
hasReplyContent,
interactiveReplyToPresentation,
normalizeMessagePresentation,
normalizeInteractiveReply,
presentationToInteractiveReply,
renderMessagePresentationFallbackText,
resolveInteractiveTextFallback,
} from "../interactive/payload.js";

View File

@@ -0,0 +1,7 @@
export {
bumpSkillsSnapshotVersion,
getSkillsSnapshotVersion,
registerSkillsChangeListener,
shouldRefreshSnapshotForVersion,
type SkillsChangeEvent,
} from "../agents/skills/refresh-state.js";

View File

@@ -501,7 +501,12 @@ describe("plugin-sdk subpath exports", () => {
],
});
expectSourceMentions("account-helpers", ["createAccountListHelpers"]);
expectSourceMentions("channel-actions", ["optionalStringEnum", "stringEnum"]);
expectSourceMentions("channel-actions", [
"optionalStringEnum",
"stringEnum",
"createMessageToolButtonsSchema",
"createMessageToolCardSchema",
]);
expectSourceContract("channel-secret-basic-runtime", {
mentions: [
"collectSimpleChannelFieldAssignments",
@@ -750,8 +755,6 @@ describe("plugin-sdk subpath exports", () => {
"buildChannelKeyCandidates",
"buildMessagingTarget",
"createDirectTextMediaOutbound",
"createMessageToolButtonsSchema",
"createMessageToolCardSchema",
"createScopedAccountReplyToModeResolver",
"createStaticReplyToModeResolver",
"createTopLevelChannelReplyToModeResolver",