@webmcp-auto-ui/agent 2.5.22 → 2.5.23

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/diagnostics.ts +49 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webmcp-auto-ui/agent",
3
- "version": "2.5.22",
3
+ "version": "2.5.23",
4
4
  "description": "LLM agent loop + remote/WASM/local providers + MCP wrapper",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
@@ -4,7 +4,7 @@ import type { ToolLayer } from './tool-layers.js';
4
4
  import type { ProviderTool } from './types.js';
5
5
  import { sanitizeServerName } from './tool-layers.js';
6
6
  import { sanitizeSchemaWithReport } from '@webmcp-auto-ui/core';
7
- import type { JsonSchema } from '@webmcp-auto-ui/core';
7
+ import type { JsonSchema, SchemaPatch } from '@webmcp-auto-ui/core';
8
8
 
9
9
  export interface Diagnostic {
10
10
  severity: 'error' | 'warning';
@@ -117,11 +117,45 @@ export function runDiagnostics(
117
117
  for (const tool of checkTools) {
118
118
  const { patches } = sanitizeSchemaWithReport(tool.input_schema as JsonSchema);
119
119
  if (patches.length > 0) {
120
+ const addedPatches = patches.filter((p: SchemaPatch) => p.type === 'additionalProperties');
121
+ const removedPatches = patches.filter((p: SchemaPatch) => p.type === 'removed');
122
+
123
+ // Dedupe paths (with multiplier) for additionalProperties patches
124
+ const addedPathsFmt = formatCounted(addedPatches.map(p => p.path));
125
+ // Dedupe "keyword@path" entries for removed patches
126
+ const removedEntriesFmt = formatCounted(
127
+ removedPatches.map(p => `${p.keyword ?? 'unknown'}@${p.path}`),
128
+ );
129
+ const removedKeywords = Array.from(
130
+ new Set(removedPatches.map(p => p.keyword).filter((k): k is string => !!k)),
131
+ );
132
+
133
+ const detailParts: string[] = [];
134
+ if (addedPatches.length > 0) {
135
+ detailParts.push(
136
+ `${addedPatches.length} correction(s) for strict mode at ${addedPathsFmt}: additionalProperties: false added automatically.`,
137
+ );
138
+ }
139
+ if (removedPatches.length > 0) {
140
+ detailParts.push(
141
+ `${removedPatches.length} keyword(s) removed for strict mode: ${removedEntriesFmt}.`,
142
+ );
143
+ }
144
+
145
+ let codeFix: string;
146
+ if (addedPatches.length > 0 && removedPatches.length === 0) {
147
+ codeFix = `Add "additionalProperties": false to the MCP server schema for ${tool.name}.`;
148
+ } else if (removedPatches.length > 0 && addedPatches.length === 0) {
149
+ codeFix = `Remove unsupported JSON Schema keywords (${removedKeywords.join(', ')}) from the MCP server schema for ${tool.name}, or accept that Claude strict mode will ignore them.`;
150
+ } else {
151
+ codeFix = `Add "additionalProperties": false and remove unsupported keywords (${removedKeywords.join(', ')}) from the MCP server schema for ${tool.name}.`;
152
+ }
153
+
120
154
  diagnostics.push({
121
155
  severity: 'warning',
122
156
  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}.`,
157
+ detail: detailParts.join(' '),
158
+ codeFix,
125
159
  });
126
160
  }
127
161
  }
@@ -130,6 +164,18 @@ export function runDiagnostics(
130
164
  return diagnostics;
131
165
  }
132
166
 
167
+ /**
168
+ * Dedupe a list of entries and format with a count multiplier when > 1.
169
+ * ["a", "a", "b"] → "a ×2, b"
170
+ */
171
+ function formatCounted(entries: string[]): string {
172
+ const counts = new Map<string, number>();
173
+ for (const e of entries) counts.set(e, (counts.get(e) ?? 0) + 1);
174
+ return Array.from(counts.entries())
175
+ .map(([entry, n]) => (n > 1 ? `${entry} ×${n}` : entry))
176
+ .join(', ');
177
+ }
178
+
133
179
  /** Check if a JSON schema has nested object properties (depth > 1) */
134
180
  function hasNestedObjects(schema: Record<string, unknown>): boolean {
135
181
  const props = schema.properties as Record<string, Record<string, unknown>> | undefined;