Skip to content

feat(plugin-sdk): add typed presentation command actions#88721

Merged
steipete merged 4 commits into
mainfrom
codex/typed-presentation-command-actions
May 31, 2026
Merged

feat(plugin-sdk): add typed presentation command actions#88721
steipete merged 4 commits into
mainfrom
codex/typed-presentation-command-actions

Conversation

@steipete

Copy link
Copy Markdown
Contributor

Summary

  • Add typed MessagePresentationAction command/callback controls to core payload normalization, the message tool schema, runtime plan types, and plugin SDK exports.
  • Refactor Codex command menus to emit core-owned native slash command actions, with channel plugins only mapping actions they can preserve.
  • Update Telegram, Discord, Slack, Mattermost, Microsoft Teams, and Feishu renderers/tests so command actions, opaque callbacks, approvals, and unsupported controls keep the right ownership boundary.
  • Document action-first message presentation semantics and refresh the plugin SDK API baseline.

Real behavior proof

Behavior addressed: Core owns native slash command presentation actions; message channel plugins map typed command/callback actions only when they can preserve semantics.
Real environment tested: Local source checkout on macOS, Node/pnpm repo toolchain; prior delegated Testbox pnpm check:changed also run.
Exact steps or command run after this patch: node scripts/run-vitest.mjs src/interactive/payload.test.ts src/channels/plugins/outbound/interactive.test.ts src/agents/tools/message-tool.test.ts src/auto-reply/reply/commands-diagnostics.test.ts extensions/codex/src/command-plugins-management.test.ts extensions/codex/src/commands.test.ts extensions/telegram/src/button-types.test.ts extensions/telegram/src/bot.test.ts extensions/telegram/src/bot.create-telegram-bot.test.ts extensions/discord/src/shared-interactive.test.ts extensions/discord/src/monitor/monitor.test.ts extensions/slack/src/shared-interactive.test.ts extensions/mattermost/src/channel.test.ts extensions/msteams/src/welcome-card.test.ts extensions/feishu/src/channel.test.ts extensions/feishu/src/outbound.test.ts; pnpm tsgo:core; pnpm tsgo:extensions; pnpm tsgo:extensions:test; pnpm lint:core; pnpm lint:extensions; pnpm docs:list; pnpm docs:check-mdx; pnpm plugin-sdk:api:gen; pnpm plugin-sdk:api:check; /Users/steipete/Projects/agent-skills/skills/autoreview/scripts/autoreview --mode local; pnpm build; git diff --check.
Evidence after fix: Focused representative Vitest pass completed 10 shards / 649 tests; autoreview returned clean with no accepted/actionable findings; build completed successfully.
Observed result after fix: Typed command actions survive through core and capable channels; opaque callbacks are not reinterpreted as native commands/approvals; unsupported channel controls fall back to visible text instead of dispatching the wrong action.
What was not tested: No live Telegram/Discord/Slack/Mattermost/Feishu/Microsoft Teams workspace click-through was run in this branch.

Verification

  • node scripts/run-vitest.mjs src/interactive/payload.test.ts src/channels/plugins/outbound/interactive.test.ts src/agents/tools/message-tool.test.ts src/auto-reply/reply/commands-diagnostics.test.ts extensions/codex/src/command-plugins-management.test.ts extensions/codex/src/commands.test.ts extensions/telegram/src/button-types.test.ts extensions/telegram/src/bot.test.ts extensions/telegram/src/bot.create-telegram-bot.test.ts extensions/discord/src/shared-interactive.test.ts extensions/discord/src/monitor/monitor.test.ts extensions/slack/src/shared-interactive.test.ts extensions/mattermost/src/channel.test.ts extensions/msteams/src/welcome-card.test.ts extensions/feishu/src/channel.test.ts extensions/feishu/src/outbound.test.ts
  • pnpm tsgo:core
  • pnpm tsgo:extensions
  • pnpm tsgo:extensions:test
  • pnpm lint:core
  • pnpm lint:extensions
  • pnpm docs:list
  • pnpm docs:check-mdx
  • pnpm plugin-sdk:api:gen
  • pnpm plugin-sdk:api:check
  • /Users/steipete/Projects/agent-skills/skills/autoreview/scripts/autoreview --mode local
  • pnpm build
  • git diff --check

Known proof gap: pnpm check:changed via delegated Testbox failed on an unrelated current-main type fixture: src/agents/acp-spawn.test.ts(984,15): 'thinking' does not exist.... Testbox id: tbx_01ksz72h2jk9hm9tx9jggqxyxz; run: https://github.com/openclaw/openclaw/actions/runs/26715332777.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: discord Channel integration: discord channel: mattermost Channel integration: mattermost channel: msteams Channel integration: msteams channel: slack Channel integration: slack channel: telegram Channel integration: telegram agents Agent runtime and tooling channel: feishu Channel integration: feishu extensions: codex size: XL maintainer Maintainer-authored PR labels May 31, 2026
@clawsweeper

clawsweeper Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed May 31, 2026, 1:34 PM ET / 17:34 UTC.

Summary
Review failed before ClawSweeper could summarize the requested change.

PR surface: Source +377, Tests +754, Docs +14, Generated 0. Total +1145 across 41 files.

Reproducibility: unclear. The review failed before ClawSweeper could establish a reproduction path.

Review metrics: none identified.

Merge readiness
Overall: 🌊 off-meta tidepool
Proof: 🌊 off-meta tidepool
Patch quality: 🌊 off-meta tidepool
Result: rating does not apply to this item.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] No close action taken because the review did not complete.

Maintainer options:

  1. Decide the mitigation before merge
    Retry the Codex review after fixing the execution failure.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] Review did not complete, so no work-lane recommendation was made.
Review details

Best possible solution:

Retry the Codex review after fixing the execution failure.

Do we have a high-confidence way to reproduce the issue?

Unclear. The review failed before ClawSweeper could establish a reproduction path.

Is this the best way to solve the issue?

Unclear. Retry the review first so ClawSweeper can evaluate the actual issue and fix direction.

AGENTS.md: unclear because the file could not be read completely.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 1a65425a6eab.

Label changes

Label changes:

  • add rating: 🌊 off-meta tidepool: Overall readiness is 🌊 off-meta tidepool; proof is 🌊 off-meta tidepool and patch quality is 🌊 off-meta tidepool.

Label justifications:

  • rating: 🌊 off-meta tidepool: Overall readiness is 🌊 off-meta tidepool; proof is 🌊 off-meta tidepool and patch quality is 🌊 off-meta tidepool.
Evidence reviewed

PR surface:

Source +377, Tests +754, Docs +14, Generated 0. Total +1145 across 41 files.

View PR surface stats
Area Files Added Removed Net
Source 23 509 132 +377
Tests 16 776 22 +754
Docs 1 18 4 +14
Config 0 0 0 0
Generated 1 2 2 0
Other 0 0 0 0
Total 41 1305 160 +1145

What I checked:

  • failure reason: timeout.
  • codex failure detail: Codex review failed for this PR: spawnSync codex ETIMEDOUT.
  • codex stdout: Per-item Codex failure; continuing with the rest of the shard.

Likely related people:

  • unknown: Codex failed before it could trace repository history. (role: review did not complete; confidence: low)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete
steipete force-pushed the codex/typed-presentation-command-actions branch from 18836de to fea05cd Compare May 31, 2026 17:27

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18836de8ed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +293 to 299
const callbackData = resolveSlackControlValue(button);
const value =
button.value && isWithinSlackLimit(button.value, SLACK_BUTTON_VALUE_MAX)
? button.value
callbackData && isWithinSlackLimit(callbackData, SLACK_BUTTON_VALUE_MAX)
? callbackData
: undefined;
const url =
button.url && isWithinSlackLimit(button.url, SLACK_BUTTON_URL_MAX) ? button.url : undefined;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve fallback for unrenderable Slack command buttons

When a presentation contains any renderable text/title block plus a buttons block whose buttons use action: { type: "command" }, resolveSlackControlValue() returns undefined for non-approval commands, this branch drops the button, and Slack renderPresentation still succeeds because the text block produced Block Kit output. Core then strips the presentation instead of running the text fallback, so Slack users see the surrounding text but not the available action labels; add a fallback block for dropped controls or decline rendering when controls cannot be represented.

Useful? React with 👍 / 👎.

Comment on lines +188 to +190
const callbackDataKind = resolveDiscordSelectCallbackDataKind(block.options);
if (callbackDataKind === "mixed") {
continue;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve fallback for mixed Discord select actions

When a select mixes command and callback actions and the presentation also has a title or text block, this continue omits the select while buildDiscordPresentationComponents still returns the remaining blocks. The outbound core treats that as a successful render and removes the original presentation, so the select option labels never appear as fallback; this only falls back today when the mixed select is the only block.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the codex/typed-presentation-command-actions branch 2 times, most recently from 1060bc8 to 8f02083 Compare May 31, 2026 17:34
@clawsweeper clawsweeper Bot added the rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. label May 31, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f02083c49

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +44 to +45
if (button.action?.type === "callback") {
return undefined;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve fallback for unsupported Feishu callback buttons

When a presentation has a renderable Feishu button (for example a command or URL) plus a button.action of type callback, this branch makes the callback button unrenderable, but buildFeishuPresentationCardElements() still returns the other card elements. The rendered card is then sent as native channelData.feishu.card and the original presentation is stripped, so users see the command/URL button but never see the callback button label as fallback; only the all-callback case falls back today. Add a fallback element for omitted callback-action buttons or decline rendering the buttons block when any action is unsupported.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the codex/typed-presentation-command-actions branch from 8f02083 to e116ae7 Compare May 31, 2026 17:39

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e116ae7589

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +317 to +318
action: Type.Optional(presentationActionSchema),
value: Type.Optional(Type.String()),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require select options to include an action or value

When the message tool schema is shown to the agent, a select option with only label now validates because both action and value are optional. That payload is later normalized by normalizeOption(), which drops options where neither record.value nor an action-derived value exists, so an agent following this schema can produce a select whose options silently disappear instead of being rejected or corrected. Make the option schema require at least one of action or value now that value is no longer mandatory.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the codex/typed-presentation-command-actions branch from e116ae7 to f8c700f Compare May 31, 2026 17:44
@steipete

Copy link
Copy Markdown
Contributor Author

Verification before merge:

Behavior addressed: core now carries typed message presentation actions for native slash commands and callbacks; channel plugins map the actions they can preserve.
Real environment tested: local macOS checkout plus GitHub CI on PR head f8c700f.
Exact steps or command run after this patch:

  • node scripts/run-vitest.mjs src/plugin-sdk/approval-renderers.test.ts src/infra/exec-approval-reply.test.ts src/infra/plugin-approval-forwarder.test.ts src/auto-reply/reply/commands-diagnostics.test.ts extensions/telegram/src/bot.create-telegram-bot.test.ts
  • pnpm check:test-types
  • pnpm plugin-sdk:api:check
  • GitHub CI run: https://github.com/openclaw/openclaw/actions/runs/26719820729
    Evidence after fix: all PR checks completed successfully; mergeStateStatus=CLEAN.
    Observed result after fix: typed approval/presentation command expectations pass, SDK API baseline matches, and the PR is mergeable.
    What was not tested: live Telegram/Slack/Discord/Mattermost/Feishu/MSTeams round trips.

@steipete
steipete merged commit d641126 into main May 31, 2026
150 checks passed
@steipete
steipete deleted the codex/typed-presentation-command-actions branch May 31, 2026 17:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f8c700f4a7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +293 to 297
const callbackData = resolveSlackControlValue(button);
const value =
button.value && isWithinSlackLimit(button.value, SLACK_BUTTON_VALUE_MAX)
? button.value
callbackData && isWithinSlackLimit(callbackData, SLACK_BUTTON_VALUE_MAX)
? callbackData
: undefined;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Dispatch Slack callback actions to plugin handlers

When a presentation button uses action: { type: "callback" }, this now puts the opaque callback value into a Slack openclaw_reply_buttons_* action. I checked extensions/slack/src/monitor/events/interactions.block-actions.ts:929-945: reply action ids only run exec/plugin-binding approval handling and skip dispatchSlackPluginInteraction, so plugin callback actions from Slack presentations are never delivered to the plugin and instead fall through as a generic system event. This breaks the new documented callback-action contract for Slack buttons/selects that are meant to carry plugin data.

Useful? React with 👍 / 👎.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 1, 2026
)

* feat(plugin-sdk): add typed presentation command actions

* test: use shared env helper in telegram bot tests

* test: expect typed approval actions

* test: expect typed sdk approval actions
SYU8384 pushed a commit to SYU8384/openclaw that referenced this pull request Jun 3, 2026
)

* feat(plugin-sdk): add typed presentation command actions

* test: use shared env helper in telegram bot tests

* test: expect typed approval actions

* test: expect typed sdk approval actions
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
)

* feat(plugin-sdk): add typed presentation command actions

* test: use shared env helper in telegram bot tests

* test: expect typed approval actions

* test: expect typed sdk approval actions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: discord Channel integration: discord channel: feishu Channel integration: feishu channel: mattermost Channel integration: mattermost channel: msteams Channel integration: msteams channel: slack Channel integration: slack channel: telegram Channel integration: telegram docs Improvements or additions to documentation extensions: codex maintainer Maintainer-authored PR rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant