@webmcp-auto-ui/agent 2.5.21 → 2.5.22

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.21",
3
+ "version": "2.5.22",
4
4
  "description": "LLM agent loop + remote/WASM/local providers + MCP wrapper",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
@@ -22,11 +22,15 @@ export function runDiagnostics(
22
22
  layers: ToolLayer[],
23
23
  tools: ProviderTool[],
24
24
  systemPrompt: string,
25
- schemaOptions?: { sanitize?: boolean; flatten?: boolean; strict?: boolean },
25
+ schemaOptions?: { sanitize?: boolean; flatten?: boolean; strict?: boolean; providerKind?: 'remote' | 'wasm' | 'gemma' | 'local' },
26
26
  /** Original (pre-sanitize) tools — used for check #5 to detect patchable schemas */
27
27
  rawTools?: ProviderTool[],
28
28
  ): Diagnostic[] {
29
29
  const diagnostics: Diagnostic[] = [];
30
+ // Gemma uses a native tool-declaration format that ignores JSON-Schema features
31
+ // like additionalProperties, oneOf/anyOf/$ref, strict mode, etc.
32
+ // Skip schema-schema checks for Gemma — they produce noise without actionable value.
33
+ const skipSchemaChecks = schemaOptions?.providerKind === 'gemma';
30
34
 
31
35
  // 1. Tool name hygiene — check for residual "mcp"/"server" noise in prefixes
32
36
  for (const layer of layers) {
@@ -63,7 +67,9 @@ export function runDiagnostics(
63
67
  }
64
68
 
65
69
  // 3. Schema depth warning for Gemma when flatten is OFF
66
- if (schemaOptions && !schemaOptions.flatten) {
70
+ // Skipped entirely for Gemma provider — its native format ignores schema structure beyond one level,
71
+ // so the "flatten" toggle has no effect there.
72
+ if (!skipSchemaChecks && schemaOptions && !schemaOptions.flatten) {
67
73
  for (const tool of tools) {
68
74
  const schema = tool.input_schema as Record<string, unknown>;
69
75
  if (hasNestedObjects(schema)) {
@@ -105,16 +111,19 @@ export function runDiagnostics(
105
111
 
106
112
  // 5. Strict mode — schemas that were auto-patched
107
113
  // Must run on raw (pre-sanitize) schemas; sanitized tools will never show patches.
108
- const checkTools = rawTools ?? tools;
109
- for (const tool of checkTools) {
110
- const { patches } = sanitizeSchemaWithReport(tool.input_schema as JsonSchema);
111
- if (patches.length > 0) {
112
- diagnostics.push({
113
- severity: 'warning',
114
- title: `Schema patched: ${tool.name}`,
115
- detail: `${patches.length} correction(s) for strict mode: ${patches.map(p => p.path).join(', ')}. additionalProperties: false added automatically.`,
116
- codeFix: `Add "additionalProperties": false to the MCP server schema for ${tool.name}.`,
117
- });
114
+ // Skipped for Gemma it doesn't use additionalProperties/strict mode at all.
115
+ if (!skipSchemaChecks) {
116
+ const checkTools = rawTools ?? tools;
117
+ for (const tool of checkTools) {
118
+ const { patches } = sanitizeSchemaWithReport(tool.input_schema as JsonSchema);
119
+ if (patches.length > 0) {
120
+ diagnostics.push({
121
+ severity: 'warning',
122
+ title: `Schema patched: ${tool.name}`,
123
+ detail: `${patches.length} correction(s) for strict mode: ${patches.map(p => p.path).join(', ')}. additionalProperties: false added automatically.`,
124
+ codeFix: `Add "additionalProperties": false to the MCP server schema for ${tool.name}.`,
125
+ });
126
+ }
118
127
  }
119
128
  }
120
129
 
@@ -112,9 +112,12 @@ export class DiscoveryCache {
112
112
  }
113
113
 
114
114
  case 'get_recipe': {
115
- const name = (params.name ?? '') as string;
116
- const recipe = cache.recipes.find(r => r.name.toLowerCase() === name.toLowerCase());
117
- if (!recipe) return JSON.stringify({ error: `Recipe "${name}" not found` });
115
+ const key = String(params.name ?? params.id ?? '').toLowerCase();
116
+ const recipe = cache.recipes.find(r =>
117
+ (r.name?.toLowerCase() === key) ||
118
+ ((r as Record<string, unknown>).id as string | undefined)?.toLowerCase() === key
119
+ );
120
+ if (!recipe) return JSON.stringify({ error: `Recipe "${key}" not found` });
118
121
  return JSON.stringify(recipe);
119
122
  }
120
123
 
@@ -260,8 +260,6 @@ export class WasmProvider implements LLMProvider {
260
260
  let lastToken = '';
261
261
  let repeatCount = 0;
262
262
  const MAX_REPEATS = 20;
263
- // P2 fix: track if we have a complete tool call to enable early cancellation
264
- let hasCompleteToolCall = false;
265
263
  const TOOL_CALL_MAX_CHARS = 3000;
266
264
 
267
265
  const result = await this.inference.generateResponse(prompt, (partialResult: string, _done: boolean) => {
@@ -297,18 +295,6 @@ export class WasmProvider implements LLMProvider {
297
295
  }
298
296
  }
299
297
 
300
- // Cancel immediately after complete tool call — don't let Gemma hallucinate
301
- if (!hasCompleteToolCall && fullText.includes('<tool_call|>')) {
302
- hasCompleteToolCall = true;
303
- // Check if there's a new tool_call opening after the last closing
304
- const lastEnd = fullText.lastIndexOf('<tool_call|>');
305
- const afterEnd = fullText.slice(lastEnd + '<tool_call|>'.length);
306
- if (!afterEnd.includes('<|tool_call>')) {
307
- // No new tool call — cancel immediately
308
- this.inference?.cancelProcessing();
309
- return;
310
- }
311
- }
312
298
  // Safety: if text grows way too long, force cancel
313
299
  if (fullText.length > TOOL_CALL_MAX_CHARS * 2) {
314
300
  this.inference?.cancelProcessing();