@seed-ship/mcp-ui-solid 4.3.9 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +124 -6
- package/dist/components/ChatPrompt.cjs +71 -53
- package/dist/components/ChatPrompt.cjs.map +1 -1
- package/dist/components/ChatPrompt.d.ts +37 -2
- package/dist/components/ChatPrompt.d.ts.map +1 -1
- package/dist/components/ChatPrompt.js +72 -54
- package/dist/components/ChatPrompt.js.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/services/chat-bus.cjs +3 -2
- package/dist/services/chat-bus.cjs.map +1 -1
- package/dist/services/chat-bus.d.ts +3 -2
- package/dist/services/chat-bus.d.ts.map +1 -1
- package/dist/services/chat-bus.js +3 -2
- package/dist/services/chat-bus.js.map +1 -1
- package/dist/types/chat-bus.d.ts +125 -24
- package/dist/types/chat-bus.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ChatPrompt.test.tsx +122 -0
- package/src/components/ChatPrompt.tsx +70 -15
- package/src/index.ts +1 -0
- package/src/services/chat-bus.test.ts +10 -8
- package/src/services/chat-bus.ts +7 -4
- package/src/types/chat-bus.ts +126 -24
- package/tsconfig.tsbuildinfo +1 -1
package/src/types/chat-bus.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* See CHANGELOG for breaking changes on experimental types.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { JSX } from 'solid-js'
|
|
9
10
|
import type { UIComponent, UILayout } from './index'
|
|
10
11
|
|
|
11
12
|
// ─── Event Base ──────────────────────────────────────────────
|
|
@@ -97,15 +98,44 @@ export interface ChatCommands {
|
|
|
97
98
|
/**
|
|
98
99
|
* Show a ChatPrompt (choice, confirm, form) above the input (C4).
|
|
99
100
|
*
|
|
100
|
-
* **
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
101
|
+
* **No default handler in v5.0.0 / v5.1.0.** `showChatPrompt` is a command
|
|
102
|
+
* *name*, not a default implementation — mcp-ui ships `ChatPrompt` (the
|
|
103
|
+
* presentation component) and the bus (event/command plumbing), but the
|
|
104
|
+
* handler that threads a Promise resolver through the SolidJS lifecycle is
|
|
105
|
+
* the consumer's responsibility. Every host app calls
|
|
106
|
+
* `bus.commands.handle('showChatPrompt', (config, signal?) => { ... })`.
|
|
105
107
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
108
|
+
* ### Implementer contract
|
|
109
|
+
*
|
|
110
|
+
* A conforming handler MUST:
|
|
111
|
+
*
|
|
112
|
+
* 1. Return a `Promise<ChatPromptResponse>`.
|
|
113
|
+
* 2. Resolve the Promise from the `ChatPrompt` component's `onSubmit`
|
|
114
|
+
* (explicit answer) or from `onDismiss` (dismissed flag true).
|
|
115
|
+
* 3. If a `signal` is provided:
|
|
116
|
+
* - If `signal.aborted` is already `true`, reject with
|
|
117
|
+
* `new DOMException('Prompt aborted', 'AbortError')` synchronously
|
|
118
|
+
* (or via `Promise.reject`) and do NOT show the UI.
|
|
119
|
+
* - Otherwise, register `signal.addEventListener('abort', () =>
|
|
120
|
+
* reject(new DOMException('Prompt aborted', 'AbortError')))` and
|
|
121
|
+
* clean up the listener on resolve/dismiss.
|
|
122
|
+
* 4. Enforce re-entrance policy — if a previous prompt is still active
|
|
123
|
+
* when a new one arrives, the recommended behavior is auto-reject the
|
|
124
|
+
* previous Promise with a custom error (e.g. `PromptReplacedError`).
|
|
125
|
+
* Alternatives: FIFO queue, or throw synchronously.
|
|
126
|
+
*
|
|
127
|
+
* The `DOMException('AbortError')` shape is the Web Platform convention
|
|
128
|
+
* (matches `fetch()`, `Response.body.cancel()`, `WritableStream.abort()`).
|
|
129
|
+
* Consumers branching on the error can do
|
|
130
|
+
* `catch (err) { if (err.name === 'AbortError') return; throw err }`.
|
|
131
|
+
*
|
|
132
|
+
* ### Planned primitive (v5.2.0)
|
|
133
|
+
*
|
|
134
|
+
* A `createChatPromptController(setActivePrompt)` helper will centralise
|
|
135
|
+
* the resolver lifecycle + abort + re-entrance logic once, so consumers
|
|
136
|
+
* can write `bus.commands.handle('showChatPrompt', ctrl.handle)` instead
|
|
137
|
+
* of threading a `let chatPromptResolver` closure by hand. Design doc:
|
|
138
|
+
* `docs/2026/r&d/mcpui-v5.1.0-consensus.md`.
|
|
109
139
|
*/
|
|
110
140
|
showChatPrompt: (config: ChatPromptConfig, signal?: AbortSignal) => Promise<ChatPromptResponse>
|
|
111
141
|
/** Dismiss the active ChatPrompt */
|
|
@@ -208,21 +238,95 @@ export interface ChatPromptConfig {
|
|
|
208
238
|
config: ChoicePromptConfig | ConfirmPromptConfig | FormPromptConfig
|
|
209
239
|
}
|
|
210
240
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
241
|
+
/**
|
|
242
|
+
* A single choice option. The generic `TMeta` parameter flows through the
|
|
243
|
+
* whole `ChoicePromptConfig<TMeta>` shape so consumers can strongly-type
|
|
244
|
+
* their metadata in `optionRenderer` without casting.
|
|
245
|
+
*
|
|
246
|
+
* @since v4.3.9 (metadata), v5.1.0 (generic TMeta + optionRenderer typing)
|
|
247
|
+
*/
|
|
248
|
+
export interface ChoiceOption<TMeta = Record<string, unknown>> {
|
|
249
|
+
value: string
|
|
250
|
+
label: string
|
|
251
|
+
icon?: string
|
|
252
|
+
description?: string
|
|
253
|
+
/**
|
|
254
|
+
* Free-form metadata (confidence, source, tags, ...).
|
|
255
|
+
* Opaque to the default renderer — use `optionRenderer` to display it.
|
|
256
|
+
* Preserved through `showChatPrompt → ChatPromptResponse` roundtrip.
|
|
257
|
+
* @since v4.3.9
|
|
258
|
+
*/
|
|
259
|
+
metadata?: TMeta
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export interface ChoicePromptConfig<TMeta = Record<string, unknown>> {
|
|
263
|
+
options: Array<ChoiceOption<TMeta>>
|
|
225
264
|
layout?: 'horizontal' | 'vertical' | 'grid'
|
|
265
|
+
/**
|
|
266
|
+
* Optional render prop for custom option bodies (badges, confidence
|
|
267
|
+
* indicators, rich layouts). Replaces the default `label + icon +
|
|
268
|
+
* description` body. mcp-ui still wraps the returned JSX in a `<button>`
|
|
269
|
+
* with the `onClick` handler, keyboard support, and focus styles — only
|
|
270
|
+
* the *content* of the button is yours.
|
|
271
|
+
*
|
|
272
|
+
* @param option The full `ChoiceOption` including strongly-typed `metadata`.
|
|
273
|
+
* @param index Zero-based position in the `options` array.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```tsx
|
|
277
|
+
* interface ConfBadgeMeta { confidence: number; source: string }
|
|
278
|
+
*
|
|
279
|
+
* bus.commands.exec('showChatPrompt', {
|
|
280
|
+
* type: 'choice',
|
|
281
|
+
* title: 'Pick an intent',
|
|
282
|
+
* config: {
|
|
283
|
+
* layout: 'vertical',
|
|
284
|
+
* options: [
|
|
285
|
+
* { value: 'a', label: 'Immobilier', metadata: { confidence: 0.9, source: 'llm' } },
|
|
286
|
+
* { value: 'b', label: 'Santé', metadata: { confidence: 0.4, source: 'llm' } },
|
|
287
|
+
* ],
|
|
288
|
+
* optionRenderer: (opt: ChoiceOption<ConfBadgeMeta>) => (
|
|
289
|
+
* <div>
|
|
290
|
+
* {opt.label}
|
|
291
|
+
* <span class="ml-2 text-xs">
|
|
292
|
+
* ({Math.round((opt.metadata?.confidence ?? 0) * 100)}%)
|
|
293
|
+
* </span>
|
|
294
|
+
* </div>
|
|
295
|
+
* ),
|
|
296
|
+
* },
|
|
297
|
+
* } as ChatPromptConfig)
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* ### ⚠️ Accessibility
|
|
301
|
+
* Do NOT return `<button>`, `<a href>`, or other interactive elements from
|
|
302
|
+
* `optionRenderer`. mcp-ui already wraps the content in a `<button>`, and
|
|
303
|
+
* nested interactive elements break screen-reader semantics, keyboard
|
|
304
|
+
* focus order, and click-through behaviour.
|
|
305
|
+
*
|
|
306
|
+
* ### ⚠️ Stale closures
|
|
307
|
+
* `optionRenderer` is called once per option per render. If you capture
|
|
308
|
+
* SolidJS signals inside the closure, wrap the access in a thunk so the
|
|
309
|
+
* framework tracks the dependency correctly. Don't destructure signal
|
|
310
|
+
* values into locals outside reactive scopes.
|
|
311
|
+
*
|
|
312
|
+
* @since v5.1.0
|
|
313
|
+
*/
|
|
314
|
+
optionRenderer?: (option: ChoiceOption<TMeta>, index: number) => JSX.Element
|
|
315
|
+
/**
|
|
316
|
+
* Custom Tailwind classes appended to each option button (after mcp-ui's
|
|
317
|
+
* defaults). Escape hatch for colour/border/radius tweaks that don't
|
|
318
|
+
* warrant a full `optionRenderer`.
|
|
319
|
+
*
|
|
320
|
+
* @since v5.1.0
|
|
321
|
+
*/
|
|
322
|
+
buttonClass?: string
|
|
323
|
+
/**
|
|
324
|
+
* Custom Tailwind classes appended to the options container (the
|
|
325
|
+
* flex/grid wrapper that lays out the buttons).
|
|
326
|
+
*
|
|
327
|
+
* @since v5.1.0
|
|
328
|
+
*/
|
|
329
|
+
containerClass?: string
|
|
226
330
|
}
|
|
227
331
|
|
|
228
332
|
export interface ConfirmPromptConfig {
|
|
@@ -471,8 +575,6 @@ export interface ClarificationEvent {
|
|
|
471
575
|
options: Array<{
|
|
472
576
|
value: string
|
|
473
577
|
label: string
|
|
474
|
-
/** @deprecated Use metadata.file_id instead. Will be removed in v5.0.0. */
|
|
475
|
-
file_id?: number
|
|
476
578
|
/**
|
|
477
579
|
* Free-form metadata (confidence, source, tags, ...).
|
|
478
580
|
* Opaque to mcp-ui — host apps pass it through as-is.
|