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.*
Summary
toCardKit2()insrc/card/builder.tsconverts v1-format cards to CardKit v2 format, but it copies the originalcard.configas-is — including the deprecated v1 fieldwide_screen_mode: true. In CardKit v2 context,wide_screen_modeis silently ignored (the correct field iswidth_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:These cards are sent through the CardKit API via
toCardKit2():This correctly:
schema: '2.0'elementsintobody.elementsBut it:
card.configas-is, carrying the v1-only fieldwide_screen_mode: trueinto a v2 schema contextwidth_mode: 'fill'According to Feishu card documentation,
wide_screen_modeis a deprecated legacy field and does not appear in the official specs. The correct field in v2 iswidth_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: trueis 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:Additionally,
buildStreamingPreAnswerCard()already usesschema: '2.0'andbody: { elements }directly (bypassingtoCardKit2), but its config also does not includewidth_mode: 'fill'. It should be added there as well for consistency.Additional Note
The
FeishuCardtype definition useswide_screen_mode: boolean. Consider updating it to also acceptwidth_modefor v2 compatibility.Environment
@larksuite/openclaw-lark2026.4.1(main branch)client.cardkit.v1.*