fix(v2/approvals): render correct title + selected label after click

Approval cards bypass the deliverMessage path that populates
pending_questions, so the post-click lookup found nothing and the
card edit fell back to " Question" + the raw option value
("approve"/"reject"). Store title and normalized options on
pending_approvals as well, and look up either table via a shared
getAskQuestionRender helper so the chat-sdk post-click edit and the
Discord interaction callback render the per-card title and the
selectedLabel (e.g. " Approved").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Koshkoshinsk
2026-04-14 15:30:42 +00:00
parent 42467d796d
commit 2df81e0b32
6 changed files with 50 additions and 17 deletions

View File

@@ -21,7 +21,7 @@ import {
import { log } from '../log.js';
import { SqliteStateAdapter } from '../state-sqlite.js';
import { registerWebhookAdapter } from '../webhook-server.js';
import { getPendingQuestion } from '../db/sessions.js';
import { getAskQuestionRender } from '../db/sessions.js';
import { normalizeOptions, type NormalizedOption } from './ask-question.js';
import type { ChannelAdapter, ChannelSetup, ConversationConfig, InboundMessage } from './adapter.js';
@@ -244,10 +244,10 @@ export function createChatSdkBridge(config: ChatSdkBridgeConfig): ChannelAdapter
const selectedOption = event.value || '';
const userId = event.user?.userId || '';
// Look up the pending question BEFORE dispatching onAction (which deletes it).
const pq = getPendingQuestion(questionId);
const title = pq?.title ?? '❓ Question';
const matched = pq?.options.find((o) => o.value === selectedOption);
// Resolve render metadata BEFORE dispatching onAction (which deletes the row).
const render = getAskQuestionRender(questionId);
const title = render?.title ?? '❓ Question';
const matched = render?.options.find((o) => o.value === selectedOption);
const selectedLabel = matched?.selectedLabel ?? selectedOption ?? '(clicked)';
// Update the card to show the selected answer and remove buttons
@@ -519,9 +519,9 @@ async function handleForwardedEvent(
const originalEmbeds =
((interaction.message as Record<string, unknown>)?.embeds as Array<Record<string, unknown>>) || [];
const originalDescription = (originalEmbeds[0]?.description as string) || '';
const pq = questionId ? getPendingQuestion(questionId) : undefined;
const cardTitle = pq?.title ?? ((originalEmbeds[0]?.title as string) || '❓ Question');
const matchedOpt = pq?.options.find((o) => o.value === selectedOption);
const render = questionId ? getAskQuestionRender(questionId) : undefined;
const cardTitle = render?.title ?? ((originalEmbeds[0]?.title as string) || '❓ Question');
const matchedOpt = render?.options.find((o) => o.value === selectedOption);
const selectedLabel = matchedOpt?.selectedLabel ?? selectedOption ?? customId;
try {
await fetch(`https://discord.com/api/v10/interactions/${interactionId}/${interactionToken}/callback`, {