From ae9d642ba5f2dd1dc66b005e1ee369e5c1a660f8 Mon Sep 17 00:00:00 2001 From: bigduu Date: Wed, 15 Jul 2026 17:56:30 +0800 Subject: [PATCH] =?UTF-8?q?fix(feishu):=20schema-2.0=20dropped=20the=20v1?= =?UTF-8?q?=20action=20container=20=E2=80=94=20lay=20button=20rows=20out?= =?UTF-8?q?=20with=20column=5Fset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second real-API rejection the 2026-07-15 e2e caught (right after #3's body-nesting fix): sending a card with a tag:"action" row fails with 200861 'cards of schema V2 no longer support this capability: unsupported tag action'. Button rows are now a column_set with one weighted column per button (buttons keep the pinned behaviors/value.cb shape). Live-verified: the options-question card renders with working [OASIS]/[LAGOON] buttons. Claude-Session: https://claude.ai/code/session_014iw5PBsSzDFHus1GfkAK4y --- src/platforms/feishu/mod.rs | 55 ++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/platforms/feishu/mod.rs b/src/platforms/feishu/mod.rs index d3b2a20..8589a04 100644 --- a/src/platforms/feishu/mod.rs +++ b/src/platforms/feishu/mod.rs @@ -306,18 +306,21 @@ fn escape_feishu_markdown(text: &str) -> String { /// Builds a schema-2.0 interactive card: `config.update_multi:true`, a /// markdown body element (fixed `element_id:"main_text"`, escaped text), and -/// — when present — one `"action"` element per button row, per -/// `docs/feishu-adapter-plan.md` §2c outbound decision 2. The exact button -/// element wrapper (`tag:"action"` with a nested `"actions"` array) is this -/// adapter's own choice: the plan pins ONLY the `behaviors`/`value.cb` -/// shape, not the surrounding container, so this is the one place protocol -/// shape was inferred rather than verified — flagged in the task report. +/// — when present — one `column_set` element per button row (one column per +/// button), per `docs/feishu-adapter-plan.md` §2c outbound decision 2. The +/// plan pins ONLY the `behaviors`/`value.cb` shape, not the surrounding +/// container — the container is this adapter's choice, verified live. /// -/// Schema 2.0 nests `elements` under `body` — a TOP-LEVEL `elements` key is -/// the v1 location and the real API rejects it with -/// `200621 parse card json err: unknown property "elements" at path []` -/// (caught live in the 2026-07-15 real-device e2e; the wiremock tests can't -/// see this because they don't validate Feishu's card schema). +/// Both container choices here were dictated by the REAL API in the +/// 2026-07-15 real-device e2e (the wiremock tests can't see this because +/// they don't validate Feishu's card schema): +/// - `elements` must nest under `body` — the v1 top-level location is +/// rejected with `200621 parse card json err: unknown property +/// "elements" at path []`. +/// - the v1 `tag:"action"` row container is GONE in schema 2.0 — rejected +/// with `200861 cards of schema V2 no longer support this capability: +/// unsupported tag action`. Button rows are laid out with `column_set` +/// (a "weighted" column per button) instead. fn build_card(text: &str, buttons: Option<&[Vec