Files
accounted/extensions/general/mcp-server/widgets/index.ts
T
0f7625535b feat(mcp): drag-and-drop SIE import card: exact bytes via tools/call, no model in the byte path (#1957)
E2E #6: the flow ordered SIE-first correctly, but the agent never
discovered gnubok_create_sie_upload, ran a local preflight, and sent the
user to the web wizard again; it also rendered a duplicate generic bank
card before the Swedbank-specific one.

1. New sie-drop widget (ui://sie-drop/app.html), rendered
   definition-level by gnubok_create_sie_upload: the user drags the
   .se/.sie file onto the card, the widget reads the EXACT bytes
   (FileReader), computes sha256 (WebCrypto), calls
   gnubok_sie_preflight via tools/call with file_content_base64 +
   sha256, shows the verdict, and on Importera stages
   gnubok_import_sie with the preflight's mappings. No network from
   the iframe, no model reproduction: byte path goes through the host
   bridge only, narrated into chat via ui/updateContext.

2. The inline size cap now applies only WITHOUT sha256: a hash-verified
   payload is byte-exact by proof, so the widget's 100 KB+ base64
   passes while unhashed model-retyped content stays refused.

3. Discovery + ordering fixes: create_sie_upload/preflight/import
   descriptions name the card path explicitly; create_company's
   history_note points at the card; connect_bank description says pass
   bank on the FIRST call when the user has named it (the duplicate
   generic card came from a bare call followed by the nudged retry).

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 17:06:30 +02:00

22 lines
653 B
TypeScript

import type { UiWidget } from './types'
import { receiptMatcherWidget } from './receipt-matcher'
import { vatReviewWidget } from './vat-review'
import { pendingOperationsWidget } from './pending-operations'
import { connectCardWidget } from './connect-card'
import { sieDropWidget } from './sie-drop'
export const uiWidgets: UiWidget[] = [
receiptMatcherWidget,
vatReviewWidget,
pendingOperationsWidget,
connectCardWidget,
sieDropWidget,
]
export function findUiWidget(uri: string): UiWidget | null {
return uiWidgets.find((w) => w.uri === uri) ?? null
}
export type { UiWidget } from './types'
export { WIDGET_MIME_TYPE } from './types'