@webmcp-auto-ui/agent 2.5.25 → 2.5.26
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/package.json +1 -1
- package/src/autoui-server.ts +17 -0
- package/src/diagnostics.ts +6 -6
- package/src/discovery-cache.ts +17 -3
- package/src/index.ts +3 -3
- package/src/loop.ts +27 -22
- package/src/providers/wasm.ts +185 -345
- package/src/recipes/_generated.ts +273 -0
- package/src/recipes/canary-data.md +50 -0
- package/src/recipes/canary-display.md +99 -0
- package/src/recipes/canary-middle.md +32 -0
- package/src/recipes/hummingbird-data.md +32 -0
- package/src/recipes/hummingbird-display.md +36 -0
- package/src/recipes/hummingbird-middle.md +18 -0
- package/src/tool-layers.ts +303 -31
- package/src/types.ts +6 -1
- package/tests/loop.test.ts +2 -2
- package/src/providers/gemma.worker.legacy.ts +0 -123
- package/src/providers/litert.worker.ts +0 -294
- package/src/recipes/widgets/actions.md +0 -28
- package/src/recipes/widgets/alert.md +0 -27
- package/src/recipes/widgets/cards.md +0 -41
- package/src/recipes/widgets/carousel.md +0 -39
- package/src/recipes/widgets/chart-rich.md +0 -51
- package/src/recipes/widgets/chart.md +0 -32
- package/src/recipes/widgets/code.md +0 -21
- package/src/recipes/widgets/d3.md +0 -36
- package/src/recipes/widgets/data-table.md +0 -46
- package/src/recipes/widgets/gallery.md +0 -39
- package/src/recipes/widgets/grid-data.md +0 -57
- package/src/recipes/widgets/hemicycle.md +0 -43
- package/src/recipes/widgets/js-sandbox.md +0 -32
- package/src/recipes/widgets/json-viewer.md +0 -27
- package/src/recipes/widgets/kv.md +0 -31
- package/src/recipes/widgets/list.md +0 -24
- package/src/recipes/widgets/log.md +0 -39
- package/src/recipes/widgets/map.md +0 -49
- package/src/recipes/widgets/profile.md +0 -49
- package/src/recipes/widgets/recipe-browser.md +0 -102
- package/src/recipes/widgets/sankey.md +0 -54
- package/src/recipes/widgets/stat-card.md +0 -43
- package/src/recipes/widgets/stat.md +0 -35
- package/src/recipes/widgets/tags.md +0 -30
- package/src/recipes/widgets/text.md +0 -19
- package/src/recipes/widgets/timeline.md +0 -38
- package/src/recipes/widgets/trombinoscope.md +0 -39
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LiteRT Worker — MediaPipe LlmInference backend
|
|
3
|
-
* Uses @mediapipe/tasks-genai with WebGPU for Gemma 4 models
|
|
4
|
-
*
|
|
5
|
-
* Messages IN: { type: 'init', model?: string }
|
|
6
|
-
* { type: 'chat', id: string, prompt: string, maxTokens?: number, temperature?: number, topK?: number }
|
|
7
|
-
* { type: 'abort', id: string }
|
|
8
|
-
* Messages OUT: { type: 'progress', progress: number, status: string, loaded?: number, total?: number }
|
|
9
|
-
* { type: 'ready' }
|
|
10
|
-
* { type: 'token', id: string, token: string }
|
|
11
|
-
* { type: 'done', id: string, text: string, stats?: { tokensPerSec: number, totalTokens: number, latencyMs: number } }
|
|
12
|
-
* { type: 'error', id: string | null, message: string }
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* CRITICAL POLYFILL for module workers.
|
|
17
|
-
*
|
|
18
|
-
* @mediapipe/tasks-genai loads WASM support scripts with this runtime check:
|
|
19
|
-
*
|
|
20
|
-
* async function lr(url) {
|
|
21
|
-
* if (typeof importScripts !== "function") {
|
|
22
|
-
* document.createElement("script") … // crashes in a worker (no DOM)
|
|
23
|
-
* }
|
|
24
|
-
* try { importScripts(url) } catch (e) {
|
|
25
|
-
* if (!(e instanceof TypeError)) throw e;
|
|
26
|
-
* await self.import(url); // dynamic-import fallback
|
|
27
|
-
* }
|
|
28
|
-
* }
|
|
29
|
-
*
|
|
30
|
-
* In ES module workers `importScripts` is undefined, so the library falls
|
|
31
|
-
* into the DOM branch and crashes. We install a stub that throws TypeError
|
|
32
|
-
* so the library takes the worker branch and reaches `self.import()` which
|
|
33
|
-
* works perfectly in module workers.
|
|
34
|
-
*
|
|
35
|
-
* This works because `lr()` checks `typeof importScripts` at CALL TIME (when
|
|
36
|
-
* FilesetResolver.forGenAiTasks() runs), not at module parse time. The
|
|
37
|
-
* polyfill is set up synchronously at module load, well before any API call.
|
|
38
|
-
*/
|
|
39
|
-
if (typeof (globalThis as any).importScripts !== 'function') {
|
|
40
|
-
(globalThis as any).importScripts = (..._args: string[]) => {
|
|
41
|
-
throw new TypeError('importScripts is not supported in module workers');
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
// MediaPipe falls back to `self.import(url)` which doesn't exist in Chrome.
|
|
45
|
-
// Provide it as an alias to dynamic `import()`.
|
|
46
|
-
if (typeof (self as any).import !== 'function') {
|
|
47
|
-
(self as any).import = (url: string) => import(/* @vite-ignore */ url);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
import { FilesetResolver, LlmInference } from '@mediapipe/tasks-genai';
|
|
51
|
-
|
|
52
|
-
const LITERT_MODELS: Record<string, { repo: string; file: string }> = {
|
|
53
|
-
'gemma-e2b': { repo: 'litert-community/gemma-4-E2B-it-litert-lm', file: 'gemma-4-E2B-it-web.task' },
|
|
54
|
-
'gemma-e4b': { repo: 'litert-community/gemma-4-E4B-it-litert-lm', file: 'gemma-4-E4B-it-web.task' },
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
let inference: LlmInference | null = null;
|
|
58
|
-
let cancelRequested = false;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Download model with OPFS caching, returning a ReadableStream.
|
|
62
|
-
* Follows the same streaming pattern as the official MediaPipe sample:
|
|
63
|
-
* the stream reader is passed directly to LlmInference as modelAssetBuffer
|
|
64
|
-
* to avoid buffering multi-GB models entirely in RAM.
|
|
65
|
-
*/
|
|
66
|
-
async function getModelStream(
|
|
67
|
-
url: string,
|
|
68
|
-
filename: string,
|
|
69
|
-
progressCb: (p: number, loaded: number, total: number) => void,
|
|
70
|
-
): Promise<ReadableStream<Uint8Array>> {
|
|
71
|
-
const root = await navigator.storage.getDirectory();
|
|
72
|
-
const modelsDir = await root.getDirectoryHandle('webmcp-models', { create: true });
|
|
73
|
-
|
|
74
|
-
// ── OPFS cache hit ───────────────────────────────────────────────
|
|
75
|
-
try {
|
|
76
|
-
const cached = await modelsDir.getFileHandle(filename);
|
|
77
|
-
const file = await cached.getFile();
|
|
78
|
-
// Verify the file is complete (size file stores expected size)
|
|
79
|
-
try {
|
|
80
|
-
const sizeHandle = await modelsDir.getFileHandle(filename + '_size');
|
|
81
|
-
const sizeFile = await sizeHandle.getFile();
|
|
82
|
-
const expectedSize = parseInt(await sizeFile.text());
|
|
83
|
-
if (file.size !== expectedSize) {
|
|
84
|
-
// Corrupt cache — remove and re-download
|
|
85
|
-
await modelsDir.removeEntry(filename);
|
|
86
|
-
await modelsDir.removeEntry(filename + '_size');
|
|
87
|
-
throw new Error('cache size mismatch');
|
|
88
|
-
}
|
|
89
|
-
} catch {
|
|
90
|
-
// No size file but model exists — use it (legacy cache)
|
|
91
|
-
}
|
|
92
|
-
progressCb(1, file.size, file.size);
|
|
93
|
-
return file.stream() as ReadableStream<Uint8Array>;
|
|
94
|
-
} catch {
|
|
95
|
-
// Cache miss — download from network
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// ── Network download ─────────────────────────────────────────────
|
|
99
|
-
// HEAD request first to get content-length for progress
|
|
100
|
-
let expectedSize = 0;
|
|
101
|
-
try {
|
|
102
|
-
const head = await fetch(url, { method: 'HEAD' });
|
|
103
|
-
if (head.ok) expectedSize = parseInt(head.headers.get('content-length') ?? '0', 10);
|
|
104
|
-
} catch { /* non-fatal */ }
|
|
105
|
-
|
|
106
|
-
const response = await fetch(url);
|
|
107
|
-
if (!response.ok) throw new Error(`Download failed: ${response.status} ${response.statusText}`);
|
|
108
|
-
if (!response.body) throw new Error('Response body is null');
|
|
109
|
-
|
|
110
|
-
const total = expectedSize || parseInt(response.headers.get('content-length') ?? '0', 10);
|
|
111
|
-
|
|
112
|
-
// Tee: one stream for consumer, one for background OPFS caching
|
|
113
|
-
const [streamForConsumer, streamForCache] = response.body.tee();
|
|
114
|
-
|
|
115
|
-
// Background cache (non-blocking, fire-and-forget)
|
|
116
|
-
(async () => {
|
|
117
|
-
try {
|
|
118
|
-
// Write expected size first
|
|
119
|
-
const sizeHandle = await modelsDir.getFileHandle(filename + '_size', { create: true });
|
|
120
|
-
const sizeWritable = await sizeHandle.createWritable();
|
|
121
|
-
await sizeWritable.write(new TextEncoder().encode(String(total)));
|
|
122
|
-
await sizeWritable.close();
|
|
123
|
-
|
|
124
|
-
const handle = await modelsDir.getFileHandle(filename, { create: true });
|
|
125
|
-
const writable = await handle.createWritable();
|
|
126
|
-
await streamForCache.pipeTo(writable);
|
|
127
|
-
} catch {
|
|
128
|
-
// OPFS write failure is non-fatal — model still usable from stream
|
|
129
|
-
try {
|
|
130
|
-
await modelsDir.removeEntry(filename).catch(() => {});
|
|
131
|
-
await modelsDir.removeEntry(filename + '_size').catch(() => {});
|
|
132
|
-
} catch { /* ignore cleanup errors */ }
|
|
133
|
-
}
|
|
134
|
-
})();
|
|
135
|
-
|
|
136
|
-
// Wrap with progress reporting
|
|
137
|
-
let loaded = 0;
|
|
138
|
-
const progressTransform = new TransformStream<Uint8Array, Uint8Array>({
|
|
139
|
-
transform(chunk, controller) {
|
|
140
|
-
loaded += chunk.length;
|
|
141
|
-
progressCb(total > 0 ? loaded / total : 0, loaded, total);
|
|
142
|
-
controller.enqueue(chunk);
|
|
143
|
-
},
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
return streamForConsumer.pipeThrough(progressTransform);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
self.onmessage = async (e: MessageEvent) => {
|
|
150
|
-
const { type, id, model: modelId, prompt } = e.data as {
|
|
151
|
-
type: string; id?: string; model?: string; prompt?: string;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
if (type === 'init') {
|
|
155
|
-
try {
|
|
156
|
-
const key = modelId ?? 'gemma-e2b';
|
|
157
|
-
const { repo, file } = LITERT_MODELS[key] ?? LITERT_MODELS['gemma-e2b'];
|
|
158
|
-
const url = `https://huggingface.co/${repo}/resolve/main/${file}`;
|
|
159
|
-
|
|
160
|
-
self.postMessage({ type: 'progress', progress: 0, status: 'downloading', loaded: 0, total: 0 });
|
|
161
|
-
|
|
162
|
-
const modelStream = await getModelStream(url, file, (p, loaded, total) => {
|
|
163
|
-
self.postMessage({ type: 'progress', progress: p, status: 'downloading', loaded, total });
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
self.postMessage({ type: 'progress', progress: 1, status: 'initializing', loaded: 0, total: 0 });
|
|
167
|
-
|
|
168
|
-
// Resolve the GenAI WASM fileset from CDN (pinned version).
|
|
169
|
-
// Second arg = true → use the ES module variant (genai_wasm_module_internal.js)
|
|
170
|
-
// so that `self.import()` works correctly in the module worker fallback path.
|
|
171
|
-
const genaiFileset = await FilesetResolver.forGenAiTasks(
|
|
172
|
-
'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai@0.10.27/wasm',
|
|
173
|
-
/* useModuleVariant */ true,
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
// WebGPU device is required for LiteRT models
|
|
177
|
-
const gpuDevice = await LlmInference.createWebGpuDevice();
|
|
178
|
-
|
|
179
|
-
// Pass stream reader as modelAssetBuffer — same pattern as the official
|
|
180
|
-
// MediaPipe sample (avoids buffering the entire model in RAM).
|
|
181
|
-
// The MediaPipe API accepts ReadableStreamDefaultReader in this slot.
|
|
182
|
-
inference = await LlmInference.createFromOptions(genaiFileset, {
|
|
183
|
-
baseOptions: {
|
|
184
|
-
modelAssetBuffer: modelStream.getReader() as unknown as Uint8Array,
|
|
185
|
-
delegate: 'GPU',
|
|
186
|
-
},
|
|
187
|
-
gpuOptions: { device: gpuDevice },
|
|
188
|
-
maxTokens: 8192,
|
|
189
|
-
temperature: 0.7,
|
|
190
|
-
topK: 40,
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
self.postMessage({ type: 'ready' });
|
|
194
|
-
} catch (err) {
|
|
195
|
-
self.postMessage({ type: 'error', id: null, message: String(err) });
|
|
196
|
-
}
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (type === 'chat' && id && prompt) {
|
|
201
|
-
if (!inference) {
|
|
202
|
-
self.postMessage({ type: 'error', id, message: 'Model not initialized' });
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const maxTokens = (e.data as { maxTokens?: number }).maxTokens;
|
|
207
|
-
const temperature = (e.data as { temperature?: number }).temperature;
|
|
208
|
-
const topK = (e.data as { topK?: number }).topK;
|
|
209
|
-
|
|
210
|
-
if (maxTokens !== undefined || temperature !== undefined || topK !== undefined) {
|
|
211
|
-
try {
|
|
212
|
-
await inference.setOptions({
|
|
213
|
-
...(maxTokens !== undefined ? { maxTokens } : {}),
|
|
214
|
-
...(temperature !== undefined ? { temperature } : {}),
|
|
215
|
-
...(topK !== undefined ? { topK } : {}),
|
|
216
|
-
});
|
|
217
|
-
} catch {
|
|
218
|
-
// setOptions failure is non-fatal — use defaults
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
cancelRequested = false;
|
|
223
|
-
let fullText = '';
|
|
224
|
-
let tokenCount = 0;
|
|
225
|
-
const t0 = performance.now();
|
|
226
|
-
|
|
227
|
-
try {
|
|
228
|
-
const result = await inference.generateResponse(prompt, (partialResult: string, done: boolean) => {
|
|
229
|
-
if (cancelRequested) {
|
|
230
|
-
inference?.cancelProcessing();
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
fullText += partialResult;
|
|
235
|
-
tokenCount++;
|
|
236
|
-
self.postMessage({ type: 'token', id, token: partialResult });
|
|
237
|
-
|
|
238
|
-
if (done) {
|
|
239
|
-
const latencyMs = performance.now() - t0;
|
|
240
|
-
self.postMessage({
|
|
241
|
-
type: 'done',
|
|
242
|
-
id,
|
|
243
|
-
text: fullText,
|
|
244
|
-
stats: {
|
|
245
|
-
tokensPerSec: tokenCount / (latencyMs / 1000),
|
|
246
|
-
totalTokens: tokenCount,
|
|
247
|
-
latencyMs,
|
|
248
|
-
},
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// Fallback if the streaming callback didn't fire 'done'
|
|
254
|
-
if (result && !fullText) {
|
|
255
|
-
fullText = result;
|
|
256
|
-
const latencyMs = performance.now() - t0;
|
|
257
|
-
self.postMessage({
|
|
258
|
-
type: 'done',
|
|
259
|
-
id,
|
|
260
|
-
text: fullText,
|
|
261
|
-
stats: {
|
|
262
|
-
tokensPerSec: tokenCount / (latencyMs / 1000),
|
|
263
|
-
totalTokens: tokenCount,
|
|
264
|
-
latencyMs,
|
|
265
|
-
},
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
} catch (err) {
|
|
269
|
-
const msg = String(err);
|
|
270
|
-
if (cancelRequested || msg.includes('cancel')) {
|
|
271
|
-
const latencyMs = performance.now() - t0;
|
|
272
|
-
self.postMessage({
|
|
273
|
-
type: 'done',
|
|
274
|
-
id,
|
|
275
|
-
text: fullText,
|
|
276
|
-
stats: {
|
|
277
|
-
tokensPerSec: tokenCount > 0 ? tokenCount / (latencyMs / 1000) : 0,
|
|
278
|
-
totalTokens: tokenCount,
|
|
279
|
-
latencyMs,
|
|
280
|
-
},
|
|
281
|
-
});
|
|
282
|
-
} else {
|
|
283
|
-
self.postMessage({ type: 'error', id, message: msg });
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (type === 'abort' && id) {
|
|
290
|
-
cancelRequested = true;
|
|
291
|
-
inference?.cancelProcessing();
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: actions
|
|
3
|
-
description: Row of action buttons
|
|
4
|
-
group: simple
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- buttons
|
|
9
|
-
properties:
|
|
10
|
-
buttons:
|
|
11
|
-
type: array
|
|
12
|
-
items:
|
|
13
|
-
type: object
|
|
14
|
-
required:
|
|
15
|
-
- label
|
|
16
|
-
properties:
|
|
17
|
-
label:
|
|
18
|
-
type: string
|
|
19
|
-
primary:
|
|
20
|
-
type: boolean
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## When to use
|
|
24
|
-
Offer action choices to the user — confirmation, navigation, or selection among multiple options.
|
|
25
|
-
|
|
26
|
-
## How to use
|
|
27
|
-
1. Identify the relevant actions based on context
|
|
28
|
-
2. Call `autoui_webmcp_widget_display('actions', { buttons: [{ label: 'Confirm', primary: true }, { label: 'Cancel' }] })`
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: alert
|
|
3
|
-
description: System alert or notification
|
|
4
|
-
group: simple
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- title
|
|
9
|
-
properties:
|
|
10
|
-
title:
|
|
11
|
-
type: string
|
|
12
|
-
message:
|
|
13
|
-
type: string
|
|
14
|
-
level:
|
|
15
|
-
type: string
|
|
16
|
-
enum:
|
|
17
|
-
- info
|
|
18
|
-
- warn
|
|
19
|
-
- error
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## When to use
|
|
23
|
-
Signal important information, a warning, or an error to the user. Useful after an action that requires attention (e.g. threshold exceeded, operation failed).
|
|
24
|
-
|
|
25
|
-
## How to use
|
|
26
|
-
1. Determine the alert level based on context ('info', 'warn', 'error')
|
|
27
|
-
2. Call `autoui_webmcp_widget_display('alert', { title: 'Quota exceeded', message: 'Storage usage is above 90%', level: 'warn' })`
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: cards
|
|
3
|
-
description: Card grid with title, description, and tags
|
|
4
|
-
group: rich
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- cards
|
|
9
|
-
properties:
|
|
10
|
-
title:
|
|
11
|
-
type: string
|
|
12
|
-
cards:
|
|
13
|
-
type: array
|
|
14
|
-
items:
|
|
15
|
-
type: object
|
|
16
|
-
required:
|
|
17
|
-
- title
|
|
18
|
-
properties:
|
|
19
|
-
title:
|
|
20
|
-
type: string
|
|
21
|
-
description:
|
|
22
|
-
type: string
|
|
23
|
-
subtitle:
|
|
24
|
-
type: string
|
|
25
|
-
tags:
|
|
26
|
-
type: array
|
|
27
|
-
items:
|
|
28
|
-
type: string
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## When to use
|
|
32
|
-
Display a collection of rich items — products, articles, projects, events. Each card combines a title, description, and tags. Prefer `list` for simple items without structure.
|
|
33
|
-
|
|
34
|
-
## How to use
|
|
35
|
-
1. Retrieve the collection via MCP
|
|
36
|
-
2. Call `autoui_webmcp_widget_display('cards', { title: 'Active projects', cards: [{ title: 'UI Redesign', description: 'Migration to Svelte 5', subtitle: 'Q2 2024', tags: ['frontend', 'high priority'] }] })`
|
|
37
|
-
|
|
38
|
-
## Common mistakes
|
|
39
|
-
- NEVER fabricate image URLs for the `image` field. Use ONLY the URLs returned by MCP tools. If no URL is available, do not include an image field — the widget renders correctly without it.
|
|
40
|
-
- STRICTLY FORBIDDEN: placeholder URLs (`via.placeholder.com`, `placehold.co`, `dummyimage.com`, `?text=...`). Omit the `image` field rather than using a placeholder.
|
|
41
|
-
- Always provide a `title` for each card
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: carousel
|
|
3
|
-
description: Slide carousel (images or content)
|
|
4
|
-
group: media
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- slides
|
|
9
|
-
properties:
|
|
10
|
-
title:
|
|
11
|
-
type: string
|
|
12
|
-
slides:
|
|
13
|
-
type: array
|
|
14
|
-
items:
|
|
15
|
-
type: object
|
|
16
|
-
properties:
|
|
17
|
-
src:
|
|
18
|
-
type: string
|
|
19
|
-
title:
|
|
20
|
-
type: string
|
|
21
|
-
subtitle:
|
|
22
|
-
type: string
|
|
23
|
-
content:
|
|
24
|
-
type: string
|
|
25
|
-
autoPlay:
|
|
26
|
-
type: boolean
|
|
27
|
-
interval:
|
|
28
|
-
type: number
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## When to use
|
|
32
|
-
For sequential content browsing — presentations, step-by-step tutorials, narrative galleries. Prefer `gallery` for an overview in grid layout.
|
|
33
|
-
|
|
34
|
-
## How to use
|
|
35
|
-
1. Retrieve or compose the slides
|
|
36
|
-
2. Call `autoui_webmcp_widget_display('carousel', { title: 'Presentation', slides: [{ title: 'Step 1', content: 'Project introduction...' }, { title: 'Step 2', src: 'https://...', subtitle: 'Architecture' }], autoPlay: false })`
|
|
37
|
-
|
|
38
|
-
## Common mistakes
|
|
39
|
-
- Never fabricate image URLs for `src` — only use URLs returned by MCP tools
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: chart-rich
|
|
3
|
-
description: Advanced multi-type chart (bar, line, area, pie)
|
|
4
|
-
group: rich
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- data
|
|
9
|
-
properties:
|
|
10
|
-
title:
|
|
11
|
-
type: string
|
|
12
|
-
type:
|
|
13
|
-
type: string
|
|
14
|
-
enum:
|
|
15
|
-
- bar
|
|
16
|
-
- line
|
|
17
|
-
- area
|
|
18
|
-
- pie
|
|
19
|
-
- donut
|
|
20
|
-
labels:
|
|
21
|
-
type: array
|
|
22
|
-
items:
|
|
23
|
-
type: string
|
|
24
|
-
data:
|
|
25
|
-
type: array
|
|
26
|
-
items:
|
|
27
|
-
type: object
|
|
28
|
-
required:
|
|
29
|
-
- values
|
|
30
|
-
properties:
|
|
31
|
-
label:
|
|
32
|
-
type: string
|
|
33
|
-
values:
|
|
34
|
-
type: array
|
|
35
|
-
items:
|
|
36
|
-
type: number
|
|
37
|
-
color:
|
|
38
|
-
type: string
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## When to use
|
|
42
|
-
For multi-series charts or types other than simple bars (lines, areas, pies, donuts). Prefer `chart` for a basic single-series bar chart.
|
|
43
|
-
|
|
44
|
-
## How to use
|
|
45
|
-
1. Fetch data via MCP
|
|
46
|
-
2. Structure into series with `labels` (X axis) and `data` (value series)
|
|
47
|
-
3. Call `autoui_webmcp_widget_display('chart-rich', { title: 'Monthly Trend', type: 'line', labels: ['Jan', 'Feb', 'Mar'], data: [{ label: '2024', values: [10, 20, 15], color: '#4CAF50' }] })`
|
|
48
|
-
|
|
49
|
-
## Common mistakes
|
|
50
|
-
- The number of `values` in each series must match the number of `labels`
|
|
51
|
-
- Do not confuse with `chart` (simple widget) — `chart-rich` uses a different data format
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: chart
|
|
3
|
-
description: Simple bar chart
|
|
4
|
-
group: simple
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- bars
|
|
9
|
-
properties:
|
|
10
|
-
title:
|
|
11
|
-
type: string
|
|
12
|
-
bars:
|
|
13
|
-
type: array
|
|
14
|
-
items:
|
|
15
|
-
type: array
|
|
16
|
-
items:
|
|
17
|
-
- type: string
|
|
18
|
-
- type: number
|
|
19
|
-
minItems: 2
|
|
20
|
-
maxItems: 2
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## When to use
|
|
24
|
-
Use for a quick bar chart with simple categorical data. Prefer `chart-rich` for multi-series charts, line charts, or pie charts.
|
|
25
|
-
|
|
26
|
-
## How to use
|
|
27
|
-
1. Fetch the data via MCP (e.g. counts by category)
|
|
28
|
-
2. Format as an array of `[label, value]` pairs
|
|
29
|
-
3. Call `autoui_webmcp_widget_display('chart', { title: 'Sales by region', bars: [['North', 150], ['South', 230], ['East', 180]] })`
|
|
30
|
-
|
|
31
|
-
## Common mistakes
|
|
32
|
-
- Swapping label and value in pairs — the format is `[string, number]`, not `[number, string]`
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: code
|
|
3
|
-
description: Code block with syntax highlighting
|
|
4
|
-
group: simple
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- content
|
|
9
|
-
properties:
|
|
10
|
-
lang:
|
|
11
|
-
type: string
|
|
12
|
-
content:
|
|
13
|
-
type: string
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## When to use
|
|
17
|
-
Display source code, snippets, shell commands, or any monospace-formatted output. Specify `lang` to enable syntax highlighting.
|
|
18
|
-
|
|
19
|
-
## How to use
|
|
20
|
-
1. Fetch or generate the code based on the request
|
|
21
|
-
2. Call `autoui_webmcp_widget_display('code', { lang: 'python', content: 'def hello():\n print("Hello")' })`
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: d3
|
|
3
|
-
description: D3.js visualization with presets (heatmap, radial, treemap, force)
|
|
4
|
-
group: advanced
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- preset
|
|
9
|
-
- data
|
|
10
|
-
properties:
|
|
11
|
-
title:
|
|
12
|
-
type: string
|
|
13
|
-
preset:
|
|
14
|
-
type: string
|
|
15
|
-
enum:
|
|
16
|
-
- hex-heatmap
|
|
17
|
-
- radial
|
|
18
|
-
- treemap
|
|
19
|
-
- force
|
|
20
|
-
data:
|
|
21
|
-
type: object
|
|
22
|
-
config:
|
|
23
|
-
type: object
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## When to use
|
|
27
|
-
For advanced visualizations not covered by other widgets — hexagonal heatmaps, radial charts, hierarchical treemaps, force graphs. Choose the preset based on the data type.
|
|
28
|
-
|
|
29
|
-
## How to use
|
|
30
|
-
1. Retrieve data via MCP
|
|
31
|
-
2. Choose the appropriate preset: `hex-heatmap` for spatial density, `radial` for cyclical data, `treemap` for hierarchies, `force` for relationship graphs
|
|
32
|
-
3. Call `autoui_webmcp_widget_display('d3', { title: 'Budget breakdown', preset: 'treemap', data: { name: 'Budget', children: [{ name: 'R&D', value: 500 }, { name: 'Marketing', value: 300 }] } })`
|
|
33
|
-
|
|
34
|
-
## Common mistakes
|
|
35
|
-
- The structure of `data` depends on the chosen preset — consult the preset documentation
|
|
36
|
-
- Do not confuse with `chart-rich` which is simpler but covers bar/line/pie
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: data-table
|
|
3
|
-
description: Sortable data table with configurable columns
|
|
4
|
-
group: rich
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- rows
|
|
9
|
-
properties:
|
|
10
|
-
title:
|
|
11
|
-
type: string
|
|
12
|
-
columns:
|
|
13
|
-
type: array
|
|
14
|
-
items:
|
|
15
|
-
type: object
|
|
16
|
-
required:
|
|
17
|
-
- key
|
|
18
|
-
- label
|
|
19
|
-
properties:
|
|
20
|
-
key:
|
|
21
|
-
type: string
|
|
22
|
-
label:
|
|
23
|
-
type: string
|
|
24
|
-
align:
|
|
25
|
-
type: string
|
|
26
|
-
enum:
|
|
27
|
-
- left
|
|
28
|
-
- center
|
|
29
|
-
- right
|
|
30
|
-
rows:
|
|
31
|
-
type: array
|
|
32
|
-
items:
|
|
33
|
-
type: object
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## When to use
|
|
37
|
-
Display tabular data with multiple columns — query results, record lists, inventories. Prefer `kv` for a single entity, `list` for a single column.
|
|
38
|
-
|
|
39
|
-
## How to use
|
|
40
|
-
1. Fetch data via MCP (e.g. SQL result, list of objects)
|
|
41
|
-
2. Optional: define `columns` to control column order and labels
|
|
42
|
-
3. Call `autoui_webmcp_widget_display('data-table', { title: 'Users', columns: [{ key: 'name', label: 'Name' }, { key: 'email', label: 'Email' }], rows: [{ name: 'Alice', email: 'alice@ex.com' }] })`
|
|
43
|
-
|
|
44
|
-
## Common mistakes
|
|
45
|
-
- Forgetting that `rows` is an array of objects (not an array of arrays)
|
|
46
|
-
- Defining `columns.key` values that do not match the keys in the `rows` objects
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
widget: gallery
|
|
3
|
-
description: Image gallery in grid layout
|
|
4
|
-
group: media
|
|
5
|
-
schema:
|
|
6
|
-
type: object
|
|
7
|
-
required:
|
|
8
|
-
- images
|
|
9
|
-
properties:
|
|
10
|
-
title:
|
|
11
|
-
type: string
|
|
12
|
-
images:
|
|
13
|
-
type: array
|
|
14
|
-
items:
|
|
15
|
-
type: object
|
|
16
|
-
required:
|
|
17
|
-
- src
|
|
18
|
-
properties:
|
|
19
|
-
src:
|
|
20
|
-
type: string
|
|
21
|
-
alt:
|
|
22
|
-
type: string
|
|
23
|
-
caption:
|
|
24
|
-
type: string
|
|
25
|
-
columns:
|
|
26
|
-
type: number
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## When to use
|
|
30
|
-
Display a collection of images in a grid — photo gallery, image search results, portfolio. Prefer `carousel` for sequential browsing.
|
|
31
|
-
|
|
32
|
-
## How to use
|
|
33
|
-
1. Retrieve image URLs via MCP (never fabricate URLs)
|
|
34
|
-
2. Call `autoui_webmcp_widget_display('gallery', { title: 'Site photos', images: [{ src: 'https://...', alt: 'Main view', caption: 'North facade' }], columns: 3 })`
|
|
35
|
-
|
|
36
|
-
## Common mistakes
|
|
37
|
-
- NEVER fabricate image URLs — only use those returned by MCP tools
|
|
38
|
-
- STRICTLY FORBIDDEN: placeholder URLs (`via.placeholder.com`, `placehold.co`, `dummyimage.com`, `?text=...`, `example.com/image.jpg`). If no real image is available, do NOT display a gallery — use a `text` or `cards` widget without an image instead
|
|
39
|
-
- Always provide an `alt` for accessibility
|