fix(feishu): add one-click card callback repair

This commit is contained in:
xmanrui 2026-08-21 13:43:02 +08:00
parent 0e62c69382
commit c1a3b0cf97
24 changed files with 3601 additions and 248 deletions

View file

@ -0,0 +1,38 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import {
cardActionProbeCard,
menuCard,
} from '../../../src/channels/feishu/feishu-cards.mjs';
function buttons(value, result = []) {
if (Array.isArray(value)) {
for (const item of value) buttons(item, result);
return result;
}
if (!value || typeof value !== 'object') return result;
if (value.tag === 'button') result.push(value);
for (const child of Object.values(value)) buttons(child, result);
return result;
}
test('menu exposes repair as number-only text instead of a callback button', () => {
const card = JSON.parse(menuCard());
assert.match(JSON.stringify(card), /6 · 修复卡片按钮/);
const actions = buttons(card).flatMap((button) => (
button.behaviors?.map((behavior) => behavior?.value?.action) ?? []
));
assert.deepEqual(actions, ['sessions', 'workspaces', 'new', 'status', 'help']);
assert.equal(actions.includes('repair'), false);
});
test('card-action probe carries only its action and opaque nonce', () => {
const nonce = '0123456789abcdef0123456789abcdef';
const card = JSON.parse(cardActionProbeCard(nonce));
const probe = buttons(card)[0];
assert.deepEqual(probe.behaviors, [{
type: 'callback',
value: { action: 'repair_verify', nonce },
}]);
assert.throws(() => cardActionProbeCard('{{client_id}}'), /safe card-action probe nonce/);
});