@webmcp-auto-ui/agent 2.5.38 → 2.5.40

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.38",
3
+ "version": "2.5.40",
4
4
  "description": "LLM agent loop + remote/WASM/local providers + MCP wrapper",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
@@ -106,7 +106,7 @@ schema:
106
106
  label:
107
107
  type: string
108
108
  value:
109
- type: string
109
+ type: [string, number]
110
110
  trend:
111
111
  type: string
112
112
  trendDir:
@@ -441,7 +441,7 @@ schema:
441
441
  label:
442
442
  type: string
443
443
  value:
444
- type: string
444
+ type: [string, number]
445
445
  stats:
446
446
  type: array
447
447
  items:
@@ -453,7 +453,7 @@ schema:
453
453
  label:
454
454
  type: string
455
455
  value:
456
- type: string
456
+ type: [string, number]
457
457
  ---
458
458
 
459
459
  ## When to use
@@ -849,7 +849,7 @@ schema:
849
849
  label:
850
850
  type: string
851
851
  value:
852
- type: string
852
+ type: [string, number]
853
853
  unit:
854
854
  type: string
855
855
  description: Unite affichee apres la valeur (ex "%", "km")
@@ -865,7 +865,7 @@ schema:
865
865
  type: string
866
866
  enum: [up, down, flat]
867
867
  previousValue:
868
- type: string
868
+ type: [string, number]
869
869
  variant:
870
870
  type: string
871
871
  enum: [default, success, warning, error, info]
@@ -883,7 +883,7 @@ schema:
883
883
  label:
884
884
  type: string
885
885
  value:
886
- type: string
886
+ type: [string, number]
887
887
  unit:
888
888
  type: string
889
889
  icon:
@@ -894,7 +894,7 @@ schema:
894
894
  type: string
895
895
  enum: [up, down, flat]
896
896
  previousValue:
897
- type: string
897
+ type: [string, number]
898
898
  variant:
899
899
  type: string
900
900
  enum: [default, success, warning, error, info]
@@ -145,6 +145,10 @@ export class DiscoveryCache {
145
145
  ((r as Record<string, unknown>).id as string | undefined)?.toLowerCase() === key
146
146
  );
147
147
  if (!recipe) return JSON.stringify({ error: `Recipe "${key}" not found` });
148
+ // Body is fetched lazily — fall through to live MCP dispatch when
149
+ // we only have name+description. Returning the metadata-only entry
150
+ // would feed the agent a body-less recipe and trigger fabrication.
151
+ if (!recipe.body) return null;
148
152
  return JSON.stringify(recipe);
149
153
  }
150
154
 
@@ -47,6 +47,8 @@ ${searchTools.join('\n')}
47
47
 
48
48
  FLEX picks the most relevant tool(s) and use it directly in STEP 3.
49
49
 
50
+ IMPORTANT — Recipe and tool indexes are in English. When the user writes in another language (French, Spanish, etc.), FLEX translates the keywords to English BEFORE calling search_recipes / search_tools. Example: user asks "biodiversité du Limousin" → search with "biodiversity", not "biodiversité". Empty results from a non-English keyword usually mean a language mismatch — FLEX retries in English before falling back to STEP 1c/1d or STEP 5.
51
+
50
52
  STEP 2 — FLEX ingests the recipe in its context
51
53
 
52
54
  ${getRecipes.join('\n')}
@@ -126,6 +126,8 @@ ${searchTools.join('\n')}
126
126
 
127
127
  FLEX picks the most relevant tool(s) and use it directly in STEP 3.
128
128
 
129
+ IMPORTANT — Recipe and tool indexes are in English. When the user writes in another language (French, Spanish, etc.), FLEX translates the keywords to English BEFORE calling search_recipes / search_tools. Example: user asks "biodiversité du Limousin" → search with "biodiversity", not "biodiversité". Empty results from a non-English keyword usually mean a language mismatch — FLEX retries in English before falling back to STEP 1c/1d or STEP 5.
130
+
129
131
  STEP 2 — FLEX ingests the recipe in its context
130
132
 
131
133
  ${getRecipes.join('\n')}
@@ -50,6 +50,8 @@ ${searchTools.join('\n')}
50
50
 
51
51
  FLEX picks the most relevant tool(s) and use it directly in STEP 3.
52
52
 
53
+ IMPORTANT — Recipe and tool indexes are in English. When the user writes in another language (French, Spanish, etc.), FLEX translates the keywords to English BEFORE calling search_recipes / search_tools. Example: user asks "biodiversité du Limousin" → search with "biodiversity", not "biodiversité". Empty results from a non-English keyword usually mean a language mismatch — FLEX retries in English before falling back to STEP 1c/1d or STEP 5.
54
+
53
55
  STEP 2 — FLEX ingests the recipe in its context
54
56
 
55
57
  ${getRecipes.join('\n')}
@@ -51,6 +51,8 @@ ${searchTools.join('\n')}
51
51
 
52
52
  FLEX picks the most relevant tool(s) and use it directly in STEP 3.
53
53
 
54
+ IMPORTANT — Recipe and tool indexes are in English. When the user writes in another language (French, Spanish, etc.), FLEX translates the keywords to English BEFORE calling search_recipes / search_tools. Example: user asks "biodiversité du Limousin" → search with "biodiversity", not "biodiversité". Empty results from a non-English keyword usually mean a language mismatch — FLEX retries in English before falling back to STEP 1c/1d or STEP 5.
55
+
54
56
  STEP 2 — FLEX ingests the recipe in its context
55
57
 
56
58
  ${getRecipes.join('\n')}
@@ -1,8 +1,15 @@
1
1
  // recipe-browser — pure utility functions for browsing/filtering/exporting recipes
2
2
 
3
3
  /**
4
- * Case-insensitive filter on name and description fields.
4
+ * Case-insensitive filter on name, description, server, and id fields.
5
5
  * Empty query returns all recipes.
6
+ *
7
+ * Match semantics: word-start. The query must start at a word boundary
8
+ * (start of string, after non-word char, or after a `\b`). This drops
9
+ * spurious substring matches like "hn" inside "technical" but keeps
10
+ * meaningful ones like "hn" inside "HN" (standalone abbreviation) or
11
+ * "hn-front-page" (id prefix). It also matches "hacker" inside
12
+ * "HackerNews" since "Hacker" begins at the start of the word.
6
13
  */
7
14
  export function filterRecipes<T extends { name: string; description?: string }>(
8
15
  recipes: T[],
@@ -10,14 +17,17 @@ export function filterRecipes<T extends { name: string; description?: string }>(
10
17
  ): T[] {
11
18
  const q = query.trim().toLowerCase();
12
19
  if (!q) return recipes;
20
+ const escaped = q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
21
+ const re = new RegExp(`\\b${escaped}`, 'i');
13
22
  return recipes.filter((r) => {
14
- const srv = ((r as Record<string, unknown>).server as string | undefined)
15
- ?? ((r as Record<string, unknown>).serverName as string | undefined)
16
- ?? '';
23
+ const obj = r as Record<string, unknown>;
24
+ const srv = (obj.server as string | undefined) ?? (obj.serverName as string | undefined) ?? '';
25
+ const id = (obj.id as string | undefined) ?? '';
17
26
  return (
18
- r.name.toLowerCase().includes(q) ||
19
- (r.description && r.description.toLowerCase().includes(q)) ||
20
- srv.toLowerCase().includes(q)
27
+ re.test(r.name) ||
28
+ (r.description ? re.test(r.description) : false) ||
29
+ re.test(srv) ||
30
+ re.test(id)
21
31
  );
22
32
  });
23
33
  }
@@ -35,6 +35,7 @@ export function parseRecipe(raw: string, fileKey?: string): Recipe {
35
35
  when: (frontmatter.when as string) ?? '',
36
36
  servers: parseStringArray(frontmatter.servers),
37
37
  body: body.trim(),
38
+ widget: frontmatter.widget as string | undefined,
38
39
  };
39
40
  }
40
41
 
@@ -11,6 +11,8 @@ export interface Recipe {
11
11
  when: string;
12
12
  servers?: string[];
13
13
  body: string;
14
+ /** Frontmatter `widget:` — when set, JSON example fences are widget params. */
15
+ widget?: string;
14
16
  }
15
17
 
16
18
  export interface McpRecipe {