diff --git a/CLAUDE.md b/CLAUDE.md index d930553..240573c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -106,7 +106,11 @@ serveur au démarrage. [MONITORING.md](MONITORING.md) §2. 3. **Un outil ne plante jamais le serveur.** Toute erreur revient en réponse structurée `{ success: false, error, tool }` avec `isError: true` — le - wrapper est dans le handler `tools/call` de `src/index.js`. + wrapper est dans le handler `tools/call` de `src/index.js`. Les enveloppes + construites **localement** dans `src/tools/` portent le champ `tool` elles + aussi : le wrapper ne les voit pas, et une erreur sans `tool` sort du + contrat. Les champs supplémentaires utiles (`warning` de résolution, + `profiles`, `hint`…) viennent après. 4. **Messages d'erreur actionnables.** Ils sont lus par Claude, pas par un humain : dire quoi faire ensuite (« appelez `switch_wms_profile` », « profils disponibles : … »). diff --git a/ROADMAP.md b/ROADMAP.md index df15cfc..6adfd18 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -96,12 +96,6 @@ rejet client (~70 000 caractères, D24) : | `get_workflow_details(CST_SendRejectContainersToPK)` | ~101 800 | | `call_query_api("Products", query_type: 1, limit: 1)` — **une seule ligne** Writing | **95 288** | -### L5.3 — Champ `tool` absent des erreurs construites localement - -Les `catch` locaux d'`api-tools.js` renvoient `{ success: false, error }` sans -le champ `tool` du contrat (convention 3) — antérieur au lot 4. Balayer tous -les modules d'outils pour le même motif. - ### L5.4 — Rendre les autres applications découvrables depuis `search_workflows` Cas réel (25/08/2026, session Cowork sur LIMAGRAIN) : une session cherchant diff --git a/src/tools/api-tools.js b/src/tools/api-tools.js index d289504..14b6521 100644 --- a/src/tools/api-tools.js +++ b/src/tools/api-tools.js @@ -169,6 +169,7 @@ async function callQueryAPI(args) { { success: false, error: err.message, + tool: 'call_query_api', ...(resolution?.warning ? { warning: resolution.warning } : {}), }, null, @@ -215,6 +216,7 @@ async function executeCommand(args) { { success: false, error: err.message, + tool: 'execute_command', }, null, 2 diff --git a/src/tools/log-tools.js b/src/tools/log-tools.js index c151347..7cc88e5 100644 --- a/src/tools/log-tools.js +++ b/src/tools/log-tools.js @@ -113,7 +113,7 @@ async function listLogFiles() { return { content: [{ type: 'text', - text: JSON.stringify({ success: false, error: err.message }, null, 2), + text: JSON.stringify({ success: false, error: err.message, tool: 'list_log_files' }, null, 2), }], isError: true, }; @@ -156,6 +156,7 @@ async function readRecentLogs(args) { { success: false, error: err.message, + tool: 'read_recent_logs', }, null, 2 @@ -225,6 +226,7 @@ async function searchLogs(args) { { success: false, error: err.message, + tool: 'search_logs', }, null, 2 diff --git a/src/tools/metadata-tools.js b/src/tools/metadata-tools.js index 7fe7d38..9ae1131 100644 --- a/src/tools/metadata-tools.js +++ b/src/tools/metadata-tools.js @@ -109,6 +109,7 @@ async function getEntityMetadata(args) { text: JSON.stringify({ success: false, error: `No entity matching "${entity_name}" found`, + tool: 'get_entity_metadata', availableCount: Array.isArray(entities) ? entities.length : '?', hint: 'Call get_entity_metadata without entity_name to see all entities', }, null, 2), @@ -150,7 +151,7 @@ async function getEntityMetadata(args) { return { content: [{ type: 'text', - text: JSON.stringify({ success: false, error: err.message }, null, 2), + text: JSON.stringify({ success: false, error: err.message, tool: 'get_entity_metadata' }, null, 2), }], isError: true, }; @@ -193,7 +194,7 @@ async function genericSearch(args) { return { content: [{ type: 'text', - text: JSON.stringify({ success: false, error: err.message }, null, 2), + text: JSON.stringify({ success: false, error: err.message, tool: 'generic_search' }, null, 2), }], isError: true, }; diff --git a/src/tools/profile-tools.js b/src/tools/profile-tools.js index 4cd8466..9d0013f 100644 --- a/src/tools/profile-tools.js +++ b/src/tools/profile-tools.js @@ -110,6 +110,7 @@ function getCurrentProfileTool() { text: JSON.stringify({ success: false, error: err.message, + tool: 'get_current_wms_profile', profiles: profileManager.listProfiles(), }, null, 2), }], @@ -127,6 +128,7 @@ function switchProfileTool(args) { text: JSON.stringify({ success: false, error: 'Missing "profile" argument', + tool: 'switch_wms_profile', profiles: profileManager.listProfiles(), }, null, 2), }], @@ -156,6 +158,7 @@ function switchProfileTool(args) { text: JSON.stringify({ success: false, error: err.message, + tool: 'switch_wms_profile', profiles: profileManager.listProfiles(), }, null, 2), }],