@webmcp-auto-ui/agent 2.5.6 → 2.5.8

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webmcp-auto-ui/agent",
3
- "version": "2.5.6",
3
+ "version": "2.5.8",
4
4
  "description": "LLM agent loop + Anthropic/Gemma LiteRT providers + MCP wrapper",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
package/src/loop.ts CHANGED
@@ -476,7 +476,49 @@ export async function runAgentLoop(
476
476
  const id = (block.input as Record<string, unknown>).id as string;
477
477
  const actionParams = (block.input as Record<string, unknown>).params as Record<string, unknown> | undefined;
478
478
  switch (action) {
479
- case 'clear': callbacks.onClear?.(); break;
479
+ case 'clear':
480
+ callbacks.onClear?.();
481
+ // Strip old widget_display / render_* tool calls AND their
482
+ // matching tool_result blocks from the messages array so the
483
+ // LLM no longer sees them in context and cannot re-create
484
+ // the cleared widgets.
485
+ {
486
+ const strippedIds = new Set<string>();
487
+ // Pass 1: collect IDs of widget tool_use blocks
488
+ for (const msg of messages) {
489
+ if (msg.role !== 'assistant' || !Array.isArray(msg.content)) continue;
490
+ for (const b of msg.content as ContentBlock[]) {
491
+ if (b.type !== 'tool_use') continue;
492
+ const tu = b as { type: 'tool_use'; id: string; name: string };
493
+ if (tu.name.includes('widget_display') || tu.name.startsWith('render_')) {
494
+ strippedIds.add(tu.id);
495
+ }
496
+ }
497
+ }
498
+ // Pass 2: strip tool_use and matching tool_result blocks
499
+ if (strippedIds.size > 0) {
500
+ for (const msg of messages) {
501
+ if (!Array.isArray(msg.content)) continue;
502
+ msg.content = (msg.content as ContentBlock[]).filter(b => {
503
+ if (b.type === 'tool_use') {
504
+ return !strippedIds.has((b as { type: 'tool_use'; id: string }).id);
505
+ }
506
+ if (b.type === 'tool_result') {
507
+ return !strippedIds.has((b as { type: 'tool_result'; tool_use_id: string }).tool_use_id);
508
+ }
509
+ return true;
510
+ });
511
+ }
512
+ // Remove messages with empty content arrays (orphaned after stripping)
513
+ let i = messages.length;
514
+ while (i-- > 0) {
515
+ const c = messages[i].content;
516
+ if (Array.isArray(c) && c.length === 0) messages.splice(i, 1);
517
+ }
518
+ }
519
+ hasRendered = false;
520
+ }
521
+ break;
480
522
  case 'update': callbacks.onUpdate?.(id, actionParams ?? {}); break;
481
523
  case 'move': callbacks.onMove?.(id, (actionParams?.x ?? (block.input as any).x) as number, (actionParams?.y ?? (block.input as any).y) as number); break;
482
524
  case 'resize': callbacks.onResize?.(id, (actionParams?.width ?? (block.input as any).width) as number, (actionParams?.height ?? (block.input as any).height) as number); break;
@@ -22,13 +22,12 @@ export function registerRecipes(recipes: Recipe[]): void {
22
22
  /**
23
23
  * Filter recipes that match at least one of the given server names.
24
24
  * Uses substring matching: recipe server "tricoteuses" matches connected server
25
- * "Tricoteuses - Moulineuse" or "tricoteuses-mcp".
25
+ * "Tricoteuses" or "tricoteuses-mcp".
26
26
  */
27
27
  // Known aliases: servers that are the same but have different names
28
28
  const SERVER_ALIASES: Record<string, string[]> = {
29
- 'tricoteuses': ['moulineuse', 'code4code', 'mcp.code4code.eu'],
30
- 'moulineuse': ['tricoteuses', 'code4code', 'mcp.code4code.eu'],
31
- 'code4code': ['tricoteuses', 'moulineuse', 'mcp.code4code.eu'],
29
+ 'tricoteuses': ['code4code', 'mcp.code4code.eu'],
30
+ 'code4code': ['tricoteuses', 'mcp.code4code.eu'],
32
31
  };
33
32
 
34
33
  export function filterRecipesByServer(recipes: Recipe[], serverNames: string[]): Recipe[] {
@@ -39,7 +38,7 @@ export function filterRecipesByServer(recipes: Recipe[], serverNames: string[]):
39
38
  const lower = name.toLowerCase();
40
39
  expanded.add(lower);
41
40
  for (const alias of SERVER_ALIASES[lower] ?? []) expanded.add(alias);
42
- // Also add parts of compound names ("Tricoteuses - Moulineuse" → tricoteuses, moulineuse)
41
+ // Also add parts of compound names ("Tricoteuses - code4code" → tricoteuses, code4code)
43
42
  for (const part of lower.split(/[\s,\-–]+/)) {
44
43
  if (part.length > 2) {
45
44
  expanded.add(part);
@@ -80,7 +79,7 @@ export function formatMcpRecipesForPrompt(recipes: McpRecipe[]): string {
80
79
  return recipes.map(r => {
81
80
  const id = r.name ?? '';
82
81
  const desc = r.description ?? '';
83
- // If name is missing or looks like a prefix ("moulineuse: undefined"), use description as display
82
+ // If name is missing or looks like a prefix ("tricoteuses: undefined"), use description as display
84
83
  if (!id || id.includes('undefined')) {
85
84
  return `- ${desc}`;
86
85
  }
@@ -740,7 +740,7 @@ component("gallery", {
740
740
 
741
741
  ## Erreurs courantes
742
742
 
743
- - **Inventer des URLs placeholder** (\`https://example.com/image.jpg\`) — strictement INTERDIT
743
+ - **Inventer des URLs placeholder** (\`https://example.com/image.jpg\`, \`via.placeholder.com\`, \`placehold.co\`, \`dummyimage.com\`, \`?text=...\`) — strictement INTERDIT. Si aucune image réelle n'est retournée par l'API, ne PAS afficher de galerie.
744
744
  - **Oublier de verifier** que le champ image existe dans les donnees retournees (certains objets Met Museum n'ont pas de \`primaryImage\`)
745
745
  - **Utiliser \`text\` pour afficher des URLs** au lieu de \`gallery\` — les images doivent etre rendues visuellement
746
746
  - **Ne pas adapter la taille** : iNaturalist retourne des thumbnails "square" par defaut, remplacer par "medium" ou "large" dans l'URL
@@ -80,7 +80,7 @@ component("gallery", {
80
80
 
81
81
  ## Erreurs courantes
82
82
 
83
- - **Inventer des URLs placeholder** (`https://example.com/image.jpg`) — strictement INTERDIT
83
+ - **Inventer des URLs placeholder** (`https://example.com/image.jpg`, `via.placeholder.com`, `placehold.co`, `dummyimage.com`, `?text=...`) — strictement INTERDIT. Si aucune image réelle n'est retournée par l'API, ne PAS afficher de galerie.
84
84
  - **Oublier de verifier** que le champ image existe dans les donnees retournees (certains objets Met Museum n'ont pas de `primaryImage`)
85
85
  - **Utiliser `text` pour afficher des URLs** au lieu de `gallery` — les images doivent etre rendues visuellement
86
86
  - **Ne pas adapter la taille** : iNaturalist retourne des thumbnails "square" par defaut, remplacer par "medium" ou "large" dans l'URL
@@ -36,5 +36,6 @@ Pour afficher une collection d'éléments riches — produits, articles, projets
36
36
  2. Appeler `autoui_webmcp_widget_display('cards', { title: 'Projets actifs', cards: [{ title: 'Refonte UI', description: 'Migration vers Svelte 5', subtitle: 'Q2 2024', tags: ['frontend', 'priorité haute'] }] })`
37
37
 
38
38
  ## Erreurs courantes
39
- - Ne JAMAIS inventer d'URLs d'images pour le champ `image`. Utiliser UNIQUEMENT les URLs retournées par les outils MCP (query_sql, search_recipes, etc.). Si aucune URL n'est disponible, ne pas inclure de champ image.
39
+ - Ne JAMAIS inventer d'URLs d'images pour le champ `image`. Utiliser UNIQUEMENT les URLs retournées par les outils MCP. Si aucune URL n'est disponible, ne pas inclure de champ image — le widget s'affiche correctement sans.
40
+ - STRICTEMENT INTERDIT : URLs placeholder (`via.placeholder.com`, `placehold.co`, `dummyimage.com`, `?text=...`). Omettre le champ `image` plutôt que de mettre un placeholder.
40
41
  - Toujours fournir un `title` pour chaque carte
@@ -35,4 +35,5 @@ Pour afficher une collection d'images en grille — galerie photo, résultats de
35
35
 
36
36
  ## Erreurs courantes
37
37
  - Ne JAMAIS fabriquer d'URLs d'images — utiliser uniquement celles retournées par les outils MCP
38
+ - STRICTEMENT INTERDIT : URLs placeholder (`via.placeholder.com`, `placehold.co`, `dummyimage.com`, `?text=...`, `example.com/image.jpg`). Si aucune image réelle n'est disponible, ne PAS afficher de galerie — utiliser un widget `text` ou `cards` sans image à la place
38
39
  - Toujours fournir un `alt` pour l'accessibilité