Skip to content

[Feature]: Feishu card action handler discards action.option, action.options, and action.form_value #42754

Description

@littleWalikrence

Summary

Extract action.option, action.options, and action.form_value from Feishu card action callbacks in handleFeishuCardAction, so plugins can receive dropdown selections, multi-select choices, and form submissions.

Problem to solve

handleFeishuCardAction in extensions/feishu/src/card-action.ts only reads action.value from Feishu card callbacks. However, Feishu card components place their interaction data in separate fields depending on the component type:

Component Data field Currently extracted?
button action.value (with .command or .text) ✅ Yes
select_static (dropdown) action.option Discarded
checkbox / multi-select action.options Discarded
form submission action.form_value Discarded

The root cause is that FeishuCardActionEvent type definition only models action.value and action.tag:

// card-action.ts line 13-16
action: {
  value: Record<string, unknown>;
  tag: string;
};

The actual Feishu callback payload includes option, options, and form_value fields that are silently dropped at the TypeScript type level. This means plugin developers cannot receive dropdown selections, multi-select choices, or form submissions from Feishu interactive cards.

The only workaround is replacing all dropdowns with button matrices encoding state into value.command, which significantly degrades UX for selections with many options.

Proposed solution

Extend FeishuCardActionEvent to include the missing fields and update the content extraction logic (~30 lines, fully backward-compatible):

  1. Type definition — add option?: string, options?: string[], form_value?: Record<string, unknown> to action
  2. Extraction logic — check for option/options/form_value before falling through to the existing value.text/value.command path
  3. Content format — merge the new fields with the existing value object into a single JSON string

Existing button flows (value.text and value.command) are completely unaffected — the new extraction only activates when option, options, or form_value are present.

Before (select_static — agent receives useless static value):

Agent receives: {"field":"model_selection"}
// The actual selection "gpt-4o" in action.option is lost

After (select_static — agent receives complete data):

Agent receives: {"field":"model_selection","option":"gpt-4o"}

Alternatives considered

Button matrix workaround: Replace all select_static dropdowns with button groups, encoding state into value.command. This works but degrades UX significantly when there are many options (>5), and cannot support multi-select or form submission scenarios at all.

Plugin-level HTTP callback proxy: Use registerHttpRoute to self-host a card callback endpoint. This requires extra infrastructure configuration (Feishu app "card request URL" setting) and complex message injection logic via before_prompt_build, making it fragile and hard to maintain.

Impact

  • Affected: All Feishu channel plugin developers using interactive cards with dropdowns, multi-select, or forms
  • Severity: Blocks workflow — cannot build approval flows, configuration selectors, or form-based interactions via Feishu cards
  • Frequency: Always — 100% of select_static/checkbox/form callbacks lose data
  • Consequence: Developers must degrade UX (button-only workarounds) or build complex plugin-level HTTP proxies to work around a ~30-line fix in core

Evidence/examples

The same gap was fixed in official Feishu SDKs:

  • larksuite/oapi-sdk-python PR #75 — added form_value to Action class
  • larksuite/oapi-sdk-java Issue #118 — reported missing card callback fields

The community feishu-interactive-cards skill works around this by using button-only cards with all state encoded in value, confirming that select_static is unusable through the current handler.

Additional information

I'm happy to submit a PR for this. The change is small (~30 lines code + ~50 lines tests in bot.card-action.test.ts) and fully backward-compatible with existing button-based card interactions.

AI-assisted analysis (Claude via Cursor), verified against current main branch source code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.clownfishTracked by Clownfish automationenhancementNew feature or requestimpact:data-lossCan lose, corrupt, or silently drop user/session/config data.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions