Skip to content

toCardKit2 does not convert wide_screen_mode to width_mode, causing fixed-width cards in CardKit #487

@HarryLee1900

Description

@HarryLee1900

Summary

toCardKit2() in src/card/builder.ts converts v1-format cards to CardKit v2 format, but it copies the original card.config as-is — including the deprecated v1 field wide_screen_mode: true. In CardKit v2 context, wide_screen_mode is silently ignored (the correct field is width_mode: 'fill'), causing all cards to render as fixed-width (~600px) instead of filling the chat window.

Root Cause

The four card builder functions (buildThinkingCard, buildStreamingCard, buildCompleteCard, buildConfirmCard) all produce v1-format cards:

{
  config: { wide_screen_mode: true, update_multi: true, locales: ['zh_cn', 'en_us'] },
  elements: [...],
  // No version 2 schema: no "schema" field, no "body" wrapper
}

These cards are sent through the CardKit API via toCardKit2():

export function toCardKit2(card: FeishuCard) {
  const result = {
    schema: '2.0',
    config: card.config,
    body: { elements: card.elements },
  };
  if (card.header) result.header = card.header;
  return result;
}

This correctly:

  • Adds schema: '2.0'
  • Moves elements into body.elements

But it:

  • ❌ Copies card.config as-is, carrying the v1-only field wide_screen_mode: true into a v2 schema context
  • ❌ Does not add the v2-equivalent field width_mode: 'fill'

According to Feishu card documentation, wide_screen_mode is a deprecated legacy field and does not appear in the official specs. The correct field in v2 is width_mode: 'fill'.

Expected Behavior

Cards sent through the CardKit API should render at full chat-window width (width_mode: 'fill').

Actual Behavior

Cards render at a fixed width (~600px), because wide_screen_mode: true is silently ignored in v2 CardKit context.

Impact

All interactive message cards created through the CardKit streaming/update path (thinking cards, streaming cards, complete cards, confirm cards) are fixed-width instead of filling the available space.

Suggested Fix

In toCardKit2(), migrate the legacy config key when converting to v2:

export function toCardKit2(card: FeishuCard) {
  const config = card.config ? { ...card.config } : {};
  // v1 → v2 config key migration
  if (config.wide_screen_mode === true) {
    config.width_mode = 'fill' as any;
    delete config.wide_screen_mode;
  }
  const result = {
    schema: '2.0',
    config,
    body: { elements: card.elements },
  };
  if (card.header) result.header = card.header;
  return result;
}

Additionally, buildStreamingPreAnswerCard() already uses schema: '2.0' and body: { elements } directly (bypassing toCardKit2), but its config also does not include width_mode: 'fill'. It should be added there as well for consistency.

Additional Note

The FeishuCard type definition uses wide_screen_mode: boolean. Consider updating it to also accept width_mode for v2 compatibility.

Environment

  • Package: @larksuite/openclaw-lark
  • Version: 2026.4.1 (main branch)
  • CardKit API: client.cardkit.v1.*

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmessagingsrc/messaging/ + src/card/ — message rendering, cards, streamingtrackedIssue is being tracked by the team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions