L4.2 : paramètre application sur les outils AD et workflow (D26)
L'application venait de WMS_APPLICATION (partagée par tous les profils) : le MCP n'interrogeait que EasyWMS, alors que CustomApp porte le spécifique client (153 workflows CST_ sur ce tenant) et que 9 applications sont déclarées par Application/GetAll. Paramètre application (défaut : l'application du profil, comportement inchangé sans lui) sur get_ad_elements, search_ad_elements, get_ad_element_details, search_workflows, get_workflow_details, list_workflow_categories. Clés de cache : ad-service passe par (application, type), workflow-service par application — sans quoi un appel CustomApp polluerait le cache EasyWMS. L'invalidation reste l'abonnement onSwitch (D8), le chargement reste paresseux (aucun préchargement des 9 applications, D10). list_workflow_categories s'adosse à Application/GetAll (liste allégée en cache : le blob data de chaque application pèse ~100 Ko) ; get_application_summary regroupe par application et ne détaille que les entrées en cache (D24), workflows compris. Acté en D26 ; CLAUDE.md mis à jour (Caches, AD), L4.2 retiré de la ROADMAP. Vérifications rejouées via le protocole (LIMAGRAIN / LIMAGRAI2512), requêtes séquentielles : - search_workflows(CST_, application:CustomApp) -> 5 objets peuplés dont CST_SendRejectContainersToPK ([Workflow] Successfully cached 153 workflows for "CustomApp"). - get_ad_elements(Workflow, application:CustomApp) -> count 153, éléments CST_* ([AD] Successfully cached 153 CustomApp::Workflow). - Séquence EasyWMS -> CustomApp -> EasyWMS sur search_workflows : 4012 vs 153, retour en cache hit ([Workflow] Using cached data for "EasyWMS"), aucune pollution ; get_application_summary montre les deux caches (workflowCachesByApplication EasyWMS 4012 / CustomApp 153). - Sans paramètre application -> comportement inchangé (W1 = W3). - switch_wms_profile EUROTRAFIC puis retour -> [Workflow] Cache cleared, [AD] All caches invalidated, [EntityResolver] Cache cleared ; summary vide. - list_workflow_categories -> 9 applications, comptes réels des applications chargées. Baseline : tools/list 23 (les 23 noms répondent), resources 6, rejet D23 d'un paramètre inconnu OK (search_workflows/applikation), npm test 4/4 exit 0. Anomalie hors périmètre consignée dans ROADMAP.md : get_workflow_details peut dépasser le seuil de rejet client (~101 800 caractères mesurés sur CST_SendRejectContainersToPK), comportement antérieur au lot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+49
-20
@@ -12,7 +12,7 @@ function listTools() {
|
||||
return [
|
||||
{
|
||||
name: 'search_workflows',
|
||||
description: 'Search workflows by name, description, or code. Returns matching workflows with metadata. Workflows are lazy-loaded from API on first request and cached for 1 hour.',
|
||||
description: 'Search workflows by name. Returns matching workflows with metadata. Workflows are lazy-loaded from API on first request and cached for 1 hour, per application. Client-specific workflows (CST_* prefix) live in the "CustomApp" application — pass application: "CustomApp" to search them.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
@@ -23,26 +23,34 @@ function listTools() {
|
||||
},
|
||||
category: {
|
||||
type: 'string',
|
||||
description: 'Filter by applicationName — the only grouping the AD API provides (workflows have no category field). All workflows of the active application share the same value (e.g. "EasyWMS").',
|
||||
description: 'Filter by the applicationName field of the returned workflows (workflows have no category field). Since `application` selects which application is fetched, all its workflows share the same applicationName — prefer `application` to change scope; `category` only narrows within the fetched set.',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum results to return (default: 50)',
|
||||
default: 50,
|
||||
},
|
||||
application: {
|
||||
type: 'string',
|
||||
description: 'AD application whose workflows are searched (default: the active profile\'s application, usually EasyWMS). Client-specific workflows live in "CustomApp". Full list via list_workflow_categories.',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'get_workflow_details',
|
||||
description: 'Get full details of a specific workflow by ID or code',
|
||||
description: 'Get full details of a specific workflow by ID or name',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
workflow_id: {
|
||||
type: 'string',
|
||||
description: 'Workflow ID or code',
|
||||
description: 'Workflow ID or exact name',
|
||||
},
|
||||
application: {
|
||||
type: 'string',
|
||||
description: 'AD application the workflow belongs to (default: the active profile\'s application, usually EasyWMS). Client-specific workflows (CST_*) live in "CustomApp".',
|
||||
},
|
||||
},
|
||||
required: ['workflow_id'],
|
||||
@@ -50,11 +58,16 @@ function listTools() {
|
||||
},
|
||||
{
|
||||
name: 'list_workflow_categories',
|
||||
description: 'List workflow groupings by applicationName. Workflows have no category field in the AD API — applicationName is the only grouping available, and all workflows of the active application share the same value.',
|
||||
description: 'List the AD applications declared on the tenant (Application/GetAll) with their workflow counts where already loaded. Workflows have no category field — the application is the only grouping. Use the `application` parameter of the workflow/AD tools to query a specific one (e.g. "CustomApp" for client-specific CST_* workflows).',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {},
|
||||
properties: {
|
||||
application: {
|
||||
type: 'string',
|
||||
description: 'Load and count the workflows of this application (default: the active profile\'s application). Other applications are listed without loading them.',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -98,17 +111,18 @@ async function executeTool(name, args) {
|
||||
* Tool: search_workflows
|
||||
*/
|
||||
async function searchWorkflows(args) {
|
||||
const { query, category, limit = 50 } = args;
|
||||
const { query, category, limit = 50, application } = args;
|
||||
|
||||
console.error(`[WorkflowTools] Searching workflows: query="${query}", category="${category}", limit=${limit}`);
|
||||
console.error(`[WorkflowTools] Searching workflows: query="${query}", category="${category}", limit=${limit}, application=${application || '(profil)'}`);
|
||||
|
||||
const results = await workflowService.searchWorkflows(query, category, limit);
|
||||
const results = await workflowService.searchWorkflows(query, category, limit, application);
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: 'text',
|
||||
text: JSON.stringify({
|
||||
success: true,
|
||||
...(application ? { application } : {}),
|
||||
count: results.length,
|
||||
// Clés réelles de l'API AD (minuscules, cf. D5) : id, name, version,
|
||||
// applicationName, commonInfo. Pas de code/category/description.
|
||||
@@ -133,11 +147,11 @@ async function searchWorkflows(args) {
|
||||
* Tool: get_workflow_details
|
||||
*/
|
||||
async function getWorkflowDetails(args) {
|
||||
const { workflow_id } = args;
|
||||
const { workflow_id, application } = args;
|
||||
|
||||
console.error(`[WorkflowTools] Getting workflow details: ${workflow_id}`);
|
||||
console.error(`[WorkflowTools] Getting workflow details: ${workflow_id} (application: ${application || '(profil)'})`);
|
||||
|
||||
const workflow = await workflowService.getWorkflowDetails(workflow_id);
|
||||
const workflow = await workflowService.getWorkflowDetails(workflow_id, application);
|
||||
|
||||
return {
|
||||
content: [{
|
||||
@@ -154,22 +168,37 @@ async function getWorkflowDetails(args) {
|
||||
* Tool: list_workflow_categories
|
||||
*/
|
||||
async function listWorkflowCategories(args) {
|
||||
console.error('[WorkflowTools] Listing workflow categories');
|
||||
const { application } = args || {};
|
||||
|
||||
const categories = await workflowService.listWorkflowCategories();
|
||||
const stats = await workflowService.getWorkflowStats();
|
||||
console.error(`[WorkflowTools] Listing applications (workflow groupings), application=${application || '(profil)'}`);
|
||||
|
||||
// La liste vient d'Application/GetAll (9 applications sur le tenant mesuré),
|
||||
// pas des applicationName du seul cache actif (D26). Seule l'application
|
||||
// demandée (ou celle du profil) est chargée — pas de préchargement des
|
||||
// autres (D10) : leurs comptes n'apparaissent que si déjà en cache.
|
||||
const applications = await workflowService.fetchApplications();
|
||||
const stats = await workflowService.getWorkflowStats(application);
|
||||
const cacheStatus = workflowService.getCacheStatus();
|
||||
|
||||
const enriched = applications.map(a => ({
|
||||
name: a.name,
|
||||
version: a.version,
|
||||
...(cacheStatus[a.name]
|
||||
? { workflowCount: cacheStatus[a.name].count, cacheAge: cacheStatus[a.name].age }
|
||||
: { workflowCount: null }),
|
||||
}));
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: 'text',
|
||||
text: JSON.stringify({
|
||||
success: true,
|
||||
note: 'Workflows have no category field in the AD API — these are the distinct applicationName values, the only grouping available. All workflows of the active application share the same value.',
|
||||
totalCategories: categories.length,
|
||||
categories,
|
||||
stats: {
|
||||
note: 'Workflows have no category field in the AD API — the application is the only grouping. workflowCount is only known for applications already loaded (lazy loading); pass application to search_workflows/get_ad_elements to load one.',
|
||||
totalApplications: applications.length,
|
||||
applications: enriched,
|
||||
loaded: {
|
||||
application: stats.application,
|
||||
totalWorkflows: stats.total,
|
||||
categoryCounts: stats.categoryCounts,
|
||||
cacheAge: stats.cacheAge
|
||||
}
|
||||
}, null, 2)
|
||||
|
||||
Reference in New Issue
Block a user