From ef10360758802e66aa5c4251cce3902eb842200d Mon Sep 17 00:00:00 2001 From: Tanmay Nilesh Shinde Date: Sat, 17 Oct 2026 11:54:09 +0530 Subject: [PATCH 1/3] fix(desktop): skip approval small-print when reason repeats the badge label --- desktop/src/features/chat/ApprovalCard.tsx | 23 ++++++++++++---------- desktop/src/features/chat/approvalRisk.ts | 14 +++++++++++++ desktop/tests/approvalRisk.test.ts | 16 ++++++++++++++- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/desktop/src/features/chat/ApprovalCard.tsx b/desktop/src/features/chat/ApprovalCard.tsx index 8ab6e1f8..1bbf8869 100644 --- a/desktop/src/features/chat/ApprovalCard.tsx +++ b/desktop/src/features/chat/ApprovalCard.tsx @@ -27,7 +27,7 @@ import { cn, humanize, truncate } from '@/lib/utils' import { ActionPreview } from './ActionPreview' import { hostOf, refLabel } from './cards/bits' import { toolMeta } from './toolMeta' -import { approvalRisk, type RiskLabel } from './approvalRisk' +import { approvalRisk, approvalCardReason, type RiskLabel } from './approvalRisk' const STATUS_TEXT: Partial> = { allow: 'You allowed this once', @@ -159,6 +159,17 @@ export function ApprovalCard({ (c) => c !== 'allow' && c !== 'deny' && c !== 'allow_task' && !single ) + const reason = approvalCardReason(approval.reason, risk.label) + const smallPrint = + (command && 'It runs on this computer with your permissions, in this folder:') || + purpose || + reason || + (meta.done ? ( + <> + {meta.done} using {approval.name} + + ) : null) + return ( {approval.warning} )} -

- {(command && 'It runs on this computer with your permissions, in this folder:') || - purpose || - approval.reason?.trim() || ( - <> - {meta.done} using {approval.name} - - )} -

+ {smallPrint &&

{smallPrint}

} {command && (
diff --git a/desktop/src/features/chat/approvalRisk.ts b/desktop/src/features/chat/approvalRisk.ts index b09d83f9..759fc4a6 100644 --- a/desktop/src/features/chat/approvalRisk.ts +++ b/desktop/src/features/chat/approvalRisk.ts @@ -168,3 +168,17 @@ function isEmailSendingTool(name: string): boolean { if (tokens.some((t) => /^(draft|drafts)$/.test(t))) return false return isEmailTool(name) && tokens.some((t) => /^(send|sends|sending|sent|reply|forward)$/.test(t)) } + +/** + * Pick the small-print reason for an approval card (#409). + * Skips the reason when it matches the badge label after trimming and ignoring case, + * avoiding duplicate lines such as a [Signs up] badge followed by "Signs up" in small print. + */ +export function approvalCardReason(reason?: string | null, badgeLabel?: string | null): string | null { + const trimmed = reason?.trim() + if (!trimmed) return null + if (badgeLabel && trimmed.toLowerCase() === badgeLabel.trim().toLowerCase()) { + return null + } + return trimmed +} diff --git a/desktop/tests/approvalRisk.test.ts b/desktop/tests/approvalRisk.test.ts index dea85068..89ab8608 100644 --- a/desktop/tests/approvalRisk.test.ts +++ b/desktop/tests/approvalRisk.test.ts @@ -3,7 +3,7 @@ // Run with `npm test` (no Electron needed). import assert from 'node:assert/strict' import { test } from 'node:test' -import { approvalRisk } from '../src/features/chat/approvalRisk.ts' +import { approvalRisk, approvalCardReason } from '../src/features/chat/approvalRisk.ts' const email = (name: string, body: string, reason = 'mcp_mailer: Send an email to one address') => ({ risk: 'send' as const, @@ -200,3 +200,17 @@ test('a priced subscribe button still reads as a purchase', () => { assert.equal(w.label, 'Purchase') assert.equal(w.verb, 'make a purchase') }) + +// #409: the small-print reason skips the reason when it matches the badge label, +// so a free Subscribe card doesn't repeat "Signs up" twice. +test('approval card small print skips the reason when it repeats the badge label (#409)', () => { + assert.equal(approvalCardReason('Signs up', 'Signs up'), null) + assert.equal(approvalCardReason(' signs up ', 'Signs up'), null) + assert.equal(approvalCardReason('Purchase', 'Purchase'), null) + assert.equal(approvalCardReason('Deletes', 'Deletes'), null) + assert.equal(approvalCardReason('Unlocks a door', 'Home security'), 'Unlocks a door') + assert.equal(approvalCardReason('Send payment', 'Purchase'), 'Send payment') + assert.equal(approvalCardReason('', 'Signs up'), null) + assert.equal(approvalCardReason(undefined, 'Signs up'), null) +}) + From 7e92e6e76d06387226e3a00a1fb8bcaeba02c714 Mon Sep 17 00:00:00 2001 From: itsskofficial Date: Sat, 17 Oct 2026 20:18:33 +0530 Subject: [PATCH 2/3] chore(changes): add the changelog entry for #409 --- changes/409.fixed.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changes/409.fixed.md diff --git a/changes/409.fixed.md b/changes/409.fixed.md new file mode 100644 index 00000000..de56694d --- /dev/null +++ b/changes/409.fixed.md @@ -0,0 +1,3 @@ +**An approval card no longer says the same thing twice.** When Sentient asked to click a free "Subscribe" button, the +card showed "Signs up" both as its label and again in the line below. Now that line is left out when it only repeats +the label. From 5c4027a9d5c46195248eaf091aaeb2118836c00b Mon Sep 17 00:00:00 2001 From: itsskofficial Date: Sat, 17 Oct 2026 20:23:05 +0530 Subject: [PATCH 3/3] chore(changes): word the #409 entry for what the card shows --- changes/409.fixed.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/changes/409.fixed.md b/changes/409.fixed.md index de56694d..c1796d33 100644 --- a/changes/409.fixed.md +++ b/changes/409.fixed.md @@ -1,3 +1,2 @@ **An approval card no longer says the same thing twice.** When Sentient asked to click a free "Subscribe" button, the -card showed "Signs up" both as its label and again in the line below. Now that line is left out when it only repeats -the label. +card showed "Signs up" both as its label and again in the line below. Now it says it once.