L2.1 : résout entity_type via l'API Metadata (D21)

Context.{entity_type} attend le TableName du Metadata, pas le nom
d'entité de l'AD (Container -> Containers, mais Alias -> Alias) : un nom
faux partait en HTTP 500 de compilation LINQ. Nouveau service
entity-resolver.js : table Name|TableName (insensible à la casse) ->
TableName, agrégée sur les applications déployées (via
GET /configuration/applications — les applications sans contexte
requêtable n'y figurent pas et n'apportent 0 entité Metadata), cache TTL
partagé, invalidation par onSwitch (D8). Branché dans wms-query-service
(query/count/schema/search) et call_query_api.

Nom inconnu -> échec avant tout appel réseau de requête, suggestions
proches + renvoi vers get_entity_metadata. Metadata injoignable -> le
nom passe tel quel avec un warning dans la réponse.

Mesures (LIMAGRAIN, via le protocole) :
- query_wms_entities("Container", limit 1) -> succès, 1 ligne, résolu
  Containers
- query_wms_entities("Alias") -> succès, invariant (pas de pluriel)
- query_wms_entities("Item") -> "Item" n'existe pas dans le modèle
  Reading. Proches : RFMenuItems, Sites. 288 entités disponibles —
  aucune ligne [API] POST dans stderr
- count_wms_entities("Product") -> 51160
- get_entity_schema("Container") et call_query_api("Container") : mêmes
  résolutions
- 288 TableName distincts sur 5 applications, aucun conflit
  Name -> TableName (mesuré le 24/08/2026)

Docs : D21 dans DECISIONS.md ; CLAUDE.md (piège retiré des points
ouverts, liste d'entités corrigée Aliases -> Alias, entity-resolver dans
la structure) ; exemple singulier/pluriel dans wms://query-examples ;
ROADMAP allégée (cause racine + L2.1 + L3.3 livrés).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Arthur Ria
2026-08-24 17:28:27 +02:00
parent 8c5792da52
commit cb625a7918
8 changed files with 276 additions and 75 deletions
+9 -2
View File
@@ -1,4 +1,5 @@
const apiService = require('../services/api-service').getInstance();
const entityResolver = require('../services/entity-resolver');
/**
* Tools MCP pour interagir avec les APIs WMS
@@ -18,7 +19,7 @@ function listTools() {
properties: {
entity_type: {
type: 'string',
description: 'Type d\'entité (Containers, Stocks, ProductLocations, Tasks, Products, Accounts, Suppliers, Kits, Aliases, InboundOrders, Receptions, OutboundOrders)',
description: 'Type d\'entité — nom AD (Container) ou TableName (Containers), insensible à la casse, résolu via l\'API Metadata. Ex: Containers, Stocks, ProductLocations, Tasks, Products, Accounts, Suppliers, Kits, Alias, InboundOrders, Receptions, OutboundOrders. Liste complète via get_entity_metadata.',
},
expression: {
type: 'string',
@@ -85,8 +86,12 @@ async function callQueryAPI(args) {
const { entity_type, expression = 'z => z', filter, limit = 100 } = args;
try {
// Résolution Name/TableName -> TableName (D21) — échec avant appel réseau
// sur nom inconnu.
const { tableName, warning } = await entityResolver.resolveEntityType(entity_type);
// Expression = Context.Entity + optional Where + OrderBy (required by EF when Take is used)
let linqExpression = `Context.${entity_type}`;
let linqExpression = `Context.${tableName}`;
if (filter) {
const whereExpr = /^\s*\w+\s*=>/.test(filter) ? filter : `z => ${filter}`;
linqExpression += `.Where(${whereExpr})`;
@@ -106,6 +111,8 @@ async function callQueryAPI(args) {
{
success: true,
entityType: entity_type,
resolvedTableName: tableName,
...(warning ? { warning } : {}),
result,
},
null,