Skip to content

fix(discord): keep components schema optional in message tool#54800

Closed
artwalker wants to merge 1 commit into
openclaw:mainfrom
artwalker:fix/discord-components-optional
Closed

fix(discord): keep components schema optional in message tool#54800
artwalker wants to merge 1 commit into
openclaw:mainfrom
artwalker:fix/discord-components-optional

Conversation

@artwalker

Copy link
Copy Markdown
Contributor

Summary

  • Problem: Discord components property is incorrectly required in the message tool schema, causing validation failures on plain file attachment sends (must have required property 'components').
  • Why it matters: Breaks all Discord file attachment attempts — agents cannot send PDFs/images without providing an empty components: {} workaround.
  • What changed: Moved Type.Optional() into createDiscordMessageToolComponentsSchema() factory function (matching createMessageToolButtonsSchema() pattern from fix: make buttons schema optional in message tool #54418). Also fixed identical double-wrap on Mattermost's buttons call site missed in fix: make buttons schema optional in message tool #54418.
  • What did NOT change: No changes to component rendering, Discord message dispatch, or other channel plugins.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Integrations

Linked Issue/PR

Root Cause / Regression History (if applicable)

  • Root cause: createDiscordMessageToolComponentsSchema() returns Type.Object(...) without Type.Optional(). The call site wraps with Type.Optional(), but this marker is lost when properties are merged into the final Type.Object() via mergeToolSchemaProperties + buildMessageToolSchemaFromActions.
  • Missing detection / guardrail: No integration-level test for components optionality in the merged message tool schema.
  • Prior context: fix: make buttons schema optional in message tool #54418 fixed the identical issue for buttons by moving Type.Optional() into createMessageToolButtonsSchema(). The Discord components and Mattermost buttons call sites were not updated.

Regression Test Plan (if applicable)

  • Coverage level:
    • Unit test
  • Target test: src/agents/tools/message-tool.test.ts, extensions/discord/src/channel-actions.test.ts
  • Scenario: Discord components must NOT appear in required array of merged message tool schema.
  • New test: "keeps components schema optional so plain sends do not require components"

User-visible / Behavior Changes

  • Discord file attachment sends no longer require an empty components: {} workaround.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Steps

  1. Configure Discord channel
  2. Have agent send a file via message(action: "send", media: "/path/to/file.pdf")
  3. Before fix: must have required property 'components'. After fix: sends successfully.

Evidence

  • Failing test/log before + passing after (52 tests pass across 3 test files)

Human Verification (required)

  • Verified: components not in required array, test mock updated to match real signature, Mattermost double-wrap fixed
  • Edge cases: Double-optional wrapping (TypeBox handles gracefully but unnecessary)
  • Not verified: Live Discord file send (schema-only fix, no runtime logic change)

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • Revert the single commit.
  • Watch for: Discord components not rendering (unlikely — only optionality changed, not structure).

Risks and Mitigations

  • Risk: Other plugins may have the same double-wrap pattern.
    • Mitigation: Searched all call sites — only Mattermost had this issue, fixed in this PR.

🤖 This PR was AI-assisted (Claude Code). All changes were reviewed, tested, and verified by the author.

@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord channel: mattermost Channel integration: mattermost agents Agent runtime and tooling size: S labels Mar 26, 2026
@greptile-apps

greptile-apps Bot commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a schema validation bug where Discord components and Mattermost buttons were incorrectly treated as required fields in the merged message tool schema. The root cause was that createDiscordMessageToolComponentsSchema() returned a bare Type.Object(...) and the outer Type.Optional() at the call site was silently dropped during mergeToolSchemaProperties / buildMessageToolSchemaFromActions. The fix moves Type.Optional() inside the factory function — consistent with the established pattern already used by createMessageToolButtonsSchema() and createMessageToolCardSchema().\n\nKey changes:\n- extensions/discord/src/message-tool-schema.ts: createDiscordMessageToolComponentsSchema() now wraps the return value in Type.Optional().\n- extensions/discord/src/channel-actions.ts: Removes the now-redundant outer Type.Optional() at the call site.\n- extensions/mattermost/src/channel.ts: Removes the same redundant outer Type.Optional() from the buttons call site (which was already correct in createMessageToolButtonsSchema() itself).\n- src/agents/tools/message-tool.test.ts: Updates the local mock createDiscordMessageToolComponentsSchema() to match the real function's new signature, and adds a regression test asserting components does not appear in the merged schema's required array.

Confidence Score: 5/5

Safe to merge — minimal, targeted schema fix with no runtime logic changes and a new regression test covering the corrected behavior.

The fix is a one-line structural change per file that follows an already-established and tested pattern (createMessageToolButtonsSchema). The new test directly validates the invariant that components is not required, the mock was updated to match the real signature, and no rendering logic or dispatch paths were touched. No other call sites remain with the same double-wrap pattern.

No files require special attention.

Important Files Changed

Filename Overview
extensions/discord/src/message-tool-schema.ts Wraps return value of createDiscordMessageToolComponentsSchema() in Type.Optional(), fixing the root cause of the required-field bug.
extensions/discord/src/channel-actions.ts Removes now-redundant outer Type.Optional() wrapper at the components call site.
extensions/mattermost/src/channel.ts Removes now-redundant outer Type.Optional() wrapper from the buttons call site, since createMessageToolButtonsSchema() already returns Type.Optional() internally.
src/agents/tools/message-tool.test.ts Updates local mock to return Type.Optional(...) matching the real function, and adds a regression test asserting components is absent from the required array.

Reviews (1): Last reviewed commit: "fix(discord): keep components schema opt..." | Re-trigger Greptile

The `components` property contributed by the Discord channel plugin
was incorrectly treated as required in the merged message tool schema,
causing validation failures on plain file attachment sends:

  Validation failed for tool "message":
    - components: must have required property 'components'

Root cause: `createDiscordMessageToolComponentsSchema()` returned a
bare `Type.Object(...)`. Although the call site in channel-actions.ts
wrapped it with `Type.Optional()`, the optional marker was lost during
schema property merging into the final `Type.Object()` — the same
issue fixed for `buttons` in openclaw#54418.

Fix: Move `Type.Optional()` into the factory function itself (matching
the pattern of `createMessageToolButtonsSchema()` and
`createMessageToolCardSchema()`), and remove the now-redundant outer
wrapper at the call site.

Also fixes the same double-wrap on Mattermost's `buttons` call site
that was missed in openclaw#54418.

Fixes openclaw#54763

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@artwalker
artwalker force-pushed the fix/discord-components-optional branch from 78bfae8 to cf77487 Compare April 1, 2026 23:53
@artwalker

Copy link
Copy Markdown
Contributor Author

Closing because the message-tool surface this PR patched has since been refactored on main. Discord no longer exposes the old inline components schema from describeMessageTool; the current channel action discovery advertises the presentation capability instead, so the original optional-components schema fix no longer applies cleanly. If the plain-send regression reappears, it should be reproed and fixed against the current presentation path.

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: mattermost Channel integration: mattermost size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

message tool incorrectly requires components for file attachments

1 participant