diff --git a/packages/mcp-workflow/src/routers/checkPropertiesFulfilledRouter.ts b/packages/mcp-workflow/src/routers/checkPropertiesFulfilledRouter.ts index ef6ae358..1f3b5c54 100644 --- a/packages/mcp-workflow/src/routers/checkPropertiesFulfilledRouter.ts +++ b/packages/mcp-workflow/src/routers/checkPropertiesFulfilledRouter.ts @@ -103,15 +103,18 @@ export class CheckPropertiesFulfilledRouter 0) { - this.logger.debug('Properties not fulfilled, routing to unfulfilled node', { - unfulfilledProperties, - targetNode: this.propertiesUnfulfilledNodeName, - totalRequired: Object.keys(this.requiredProperties).length, - }); + this.logger.debug( + `Properties not fulfilled, routing to ${this.propertiesUnfulfilledNodeName}`, + { + unfulfilledProperties, + targetNode: this.propertiesUnfulfilledNodeName, + totalRequired: Object.keys(this.requiredProperties).length, + } + ); return this.propertiesUnfulfilledNodeName; } - this.logger.debug('All properties fulfilled, routing to fulfilled node', { + this.logger.debug(`All properties fulfilled, routing to ${this.propertiesFulfilledNodeName}`, { targetNode: this.propertiesFulfilledNodeName, totalProperties: Object.keys(this.requiredProperties).length, }); diff --git a/packages/mobile-native-mcp-server/src/tools/workflow/sfmobile-native-project-manager/tool.ts b/packages/mobile-native-mcp-server/src/tools/workflow/sfmobile-native-project-manager/tool.ts index 6ef26d27..eb45302c 100644 --- a/packages/mobile-native-mcp-server/src/tools/workflow/sfmobile-native-project-manager/tool.ts +++ b/packages/mobile-native-mcp-server/src/tools/workflow/sfmobile-native-project-manager/tool.ts @@ -12,6 +12,7 @@ import { WorkflowStateManager, type Logger, type WorkflowEnvironment, + createWorkflowLogger, } from '@salesforce/magen-mcp-workflow'; import { mobileNativeWorkflow } from '../../../workflow/graph.js'; import { ORCHESTRATOR_TOOL } from './metadata.js'; @@ -24,6 +25,10 @@ import { ORCHESTRATOR_TOOL } from './metadata.js'; */ export class MobileNativeOrchestrator extends OrchestratorTool { constructor(server: McpServer, logger?: Logger, environment: WorkflowEnvironment = 'production') { + const mobileNativeOrchestratorToolLogger = + logger ?? createWorkflowLogger('MobileNativeOrchestratorTool'); + const mobileNativeWorkflowStateManagerLogger = + logger ?? createWorkflowLogger('MobileNativeWorkflowStateManager'); const config: OrchestratorConfig = { toolId: ORCHESTRATOR_TOOL.toolId, title: 'Salesforce Mobile Native Project Manager', @@ -32,9 +37,9 @@ export class MobileNativeOrchestrator extends OrchestratorTool { workflow: mobileNativeWorkflow, stateManager: new WorkflowStateManager({ environment, - logger, + logger: mobileNativeWorkflowStateManagerLogger, }), - logger, + logger: mobileNativeOrchestratorToolLogger, }; super(server, config); diff --git a/packages/mobile-native-mcp-server/src/workflow/nodes/checkAndroidSetupExtractedRouter.ts b/packages/mobile-native-mcp-server/src/workflow/nodes/checkAndroidSetupExtractedRouter.ts index b19519d5..4d7bc65a 100644 --- a/packages/mobile-native-mcp-server/src/workflow/nodes/checkAndroidSetupExtractedRouter.ts +++ b/packages/mobile-native-mcp-server/src/workflow/nodes/checkAndroidSetupExtractedRouter.ts @@ -31,7 +31,9 @@ export class CheckAndroidSetupExtractedRouter { execute = (state: State): string => { // Check if both androidHome and javaHome were extracted if (state.androidHome && state.javaHome) { - this.logger.info('Android setup successfully extracted, routing to platform check'); + this.logger.info( + `Android setup successfully extracted, routing to ${this.setupExtractedNodeName}` + ); return this.setupExtractedNodeName; } @@ -41,7 +43,7 @@ export class CheckAndroidSetupExtractedRouter { if (!state.javaHome) missingPaths.push('javaHome'); this.logger.warn( - `Android setup extraction failed. Missing: ${missingPaths.join(', ')}. Routing to failure.` + `Android setup extraction failed. Missing: ${missingPaths.join(', ')}. Routing to ${this.failureNodeName}.` ); return this.failureNodeName; }; diff --git a/packages/mobile-native-mcp-server/src/workflow/nodes/checkBuildSuccessfulRouter.ts b/packages/mobile-native-mcp-server/src/workflow/nodes/checkBuildSuccessfulRouter.ts index 5634cca6..2b6b0e9b 100644 --- a/packages/mobile-native-mcp-server/src/workflow/nodes/checkBuildSuccessfulRouter.ts +++ b/packages/mobile-native-mcp-server/src/workflow/nodes/checkBuildSuccessfulRouter.ts @@ -6,6 +6,7 @@ */ import { State } from '../metadata.js'; +import { createComponentLogger } from '@salesforce/magen-mcp-workflow'; /** * Router node that determines the next step based on build success status. @@ -19,6 +20,7 @@ export class CheckBuildSuccessfulRouter { private readonly deploymentNodeName: string; private readonly buildRecoveryNodeName: string; private readonly failureNodeName: string; + private readonly logger = createComponentLogger('CheckBuildSuccessfulRouter'); constructor(deploymentNodeName: string, buildRecoveryNodeName: string, failureNodeName: string) { this.deploymentNodeName = deploymentNodeName; @@ -29,6 +31,7 @@ export class CheckBuildSuccessfulRouter { execute = (state: State): string => { // If build was successful, proceed to deployment if (state.buildSuccessful) { + this.logger.info(`Build successful, routing to ${this.deploymentNodeName}`); return this.deploymentNodeName; } @@ -38,15 +41,18 @@ export class CheckBuildSuccessfulRouter { // If we've reached max retries, go to failure if (attemptCount >= maxRetries) { + this.logger.info(`Max retries ${maxRetries} reached, routing to ${this.failureNodeName}`); return this.failureNodeName; } // If we just came from recovery and it said it's not ready to retry, go to failure if (state.recoveryReadyForRetry === false) { + this.logger.info(`Recovery not ready to retry, routing to ${this.failureNodeName}`); return this.failureNodeName; } // Otherwise, attempt recovery + this.logger.info(`Attempting recovery, routing to ${this.buildRecoveryNodeName}`); return this.buildRecoveryNodeName; }; } diff --git a/packages/mobile-native-mcp-server/src/workflow/nodes/checkPlatformSetup.ts b/packages/mobile-native-mcp-server/src/workflow/nodes/checkPlatformSetup.ts index e153b94f..dabb7db9 100644 --- a/packages/mobile-native-mcp-server/src/workflow/nodes/checkPlatformSetup.ts +++ b/packages/mobile-native-mcp-server/src/workflow/nodes/checkPlatformSetup.ts @@ -87,6 +87,7 @@ export class PlatformCheckNode extends BaseNode { : undefined, }; } catch (error) { + this.logger.error(`Error executing platform check command: ${command}`, error as Error); const errorMessage = error instanceof Error ? error.message : `${error}`; return { validPlatformSetup: false, diff --git a/packages/mobile-native-mcp-server/src/workflow/nodes/checkPluginValidatedRouter.ts b/packages/mobile-native-mcp-server/src/workflow/nodes/checkPluginValidatedRouter.ts index 7081f6a6..6d067414 100644 --- a/packages/mobile-native-mcp-server/src/workflow/nodes/checkPluginValidatedRouter.ts +++ b/packages/mobile-native-mcp-server/src/workflow/nodes/checkPluginValidatedRouter.ts @@ -5,6 +5,7 @@ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT */ +import { createComponentLogger } from '@salesforce/magen-mcp-workflow'; import { State } from '../metadata.js'; /** @@ -13,6 +14,7 @@ import { State } from '../metadata.js'; export class CheckPluginValidatedRouter { private readonly pluginValidatedNodeName: string; private readonly invalidPluginNodeName: string; + private readonly logger = createComponentLogger('CheckPluginValidatedRouter'); /** * Creates a new CheckPluginValidatedRouter. @@ -26,6 +28,12 @@ export class CheckPluginValidatedRouter { } execute = (state: State): string => { - return state.validPluginSetup ? this.pluginValidatedNodeName : this.invalidPluginNodeName; + if (state.validPluginSetup === true) { + this.logger.info(`Plugin setup valid, routing to ${this.pluginValidatedNodeName}`); + return this.pluginValidatedNodeName; + } + + this.logger.info(`Plugin setup invalid, routing to ${this.invalidPluginNodeName}`); + return this.invalidPluginNodeName; }; } diff --git a/packages/mobile-native-mcp-server/src/workflow/nodes/checkProjectGenerationRouter.ts b/packages/mobile-native-mcp-server/src/workflow/nodes/checkProjectGenerationRouter.ts index 7f77470e..3afb06e0 100644 --- a/packages/mobile-native-mcp-server/src/workflow/nodes/checkProjectGenerationRouter.ts +++ b/packages/mobile-native-mcp-server/src/workflow/nodes/checkProjectGenerationRouter.ts @@ -38,7 +38,7 @@ export class CheckProjectGenerationRouter { if (hasProjectPath && !hasFatalErrors) { this.logger.info( - `Project generation successful at ${state.projectPath}, routing to build validation` + `Project generation successful at ${state.projectPath}, routing to ${this.successNodeName}` ); return this.successNodeName; } @@ -48,7 +48,9 @@ export class CheckProjectGenerationRouter { ? `Fatal errors occurred: ${state.workflowFatalErrorMessages?.join(', ')}` : 'Project path not set after generation'; - this.logger.warn(`Project generation failed. Reason: ${reason}. Routing to failure.`); + this.logger.warn( + `Project generation failed. Reason: ${reason}. Routing to ${this.failureNodeName}.` + ); return this.failureNodeName; }; } diff --git a/packages/mobile-native-mcp-server/src/workflow/nodes/checkSetupValidatedRouter.ts b/packages/mobile-native-mcp-server/src/workflow/nodes/checkSetupValidatedRouter.ts index c0a4f46f..116990f6 100644 --- a/packages/mobile-native-mcp-server/src/workflow/nodes/checkSetupValidatedRouter.ts +++ b/packages/mobile-native-mcp-server/src/workflow/nodes/checkSetupValidatedRouter.ts @@ -5,6 +5,7 @@ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT */ +import { createComponentLogger } from '@salesforce/magen-mcp-workflow'; import { State } from '../metadata.js'; /** @@ -15,6 +16,7 @@ export class CheckSetupValidatedRouter { private readonly setupValidatedNodeName: string; private readonly androidSetupNodeName: string; private readonly invalidSetupNodeName: string; + private readonly logger = createComponentLogger('CheckSetupValidatedRouter'); /** * Creates a new CheckSetupValidatedRouter. @@ -36,15 +38,23 @@ export class CheckSetupValidatedRouter { execute = (state: State): string => { // If platform setup is valid, proceed if (state.validPlatformSetup) { + this.logger.info(`Platform setup valid, routing to ${this.setupValidatedNodeName}`); return this.setupValidatedNodeName; } // If platform is Android and Android/Java paths are missing, route to Android setup if (state.platform === 'Android' && (!state.androidHome || !state.javaHome)) { + const missingSetup: string[] = []; + if (!state.androidHome) missingSetup.push('androidHome'); + if (!state.javaHome) missingSetup.push('javaHome'); + this.logger.info( + `Android setup missing ${missingSetup.join(', ')}, routing to ${this.androidSetupNodeName}` + ); return this.androidSetupNodeName; } // Otherwise, route to failure + this.logger.info(`Platform setup invalid, routing to ${this.invalidSetupNodeName}`); return this.invalidSetupNodeName; }; } diff --git a/packages/mobile-native-mcp-server/src/workflow/nodes/checkTemplatePropertiesFulfilledRouter.ts b/packages/mobile-native-mcp-server/src/workflow/nodes/checkTemplatePropertiesFulfilledRouter.ts index 3ab5b822..05c3f4f2 100644 --- a/packages/mobile-native-mcp-server/src/workflow/nodes/checkTemplatePropertiesFulfilledRouter.ts +++ b/packages/mobile-native-mcp-server/src/workflow/nodes/checkTemplatePropertiesFulfilledRouter.ts @@ -5,6 +5,7 @@ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT */ +import { createComponentLogger } from '@salesforce/magen-mcp-workflow'; import { State } from '../metadata.js'; /** @@ -17,7 +18,7 @@ import { State } from '../metadata.js'; export class CheckTemplatePropertiesFulfilledRouter { private readonly propertiesFulfilledNodeName: string; private readonly propertiesUnfulfilledNodeName: string; - + private readonly logger = createComponentLogger('CheckTemplatePropertiesFulfilledRouter'); /** * Creates a new CheckTemplatePropertiesFulfilledRouter. * @@ -37,6 +38,7 @@ export class CheckTemplatePropertiesFulfilledRouter { // If no template has been selected yet, we shouldn't be checking template properties // This is a safety check to prevent routing to project generation before template selection if (!state.selectedTemplate) { + this.logger.info(`No template selected, routing to ${this.propertiesUnfulfilledNodeName}`); return this.propertiesUnfulfilledNodeName; } @@ -45,11 +47,17 @@ export class CheckTemplatePropertiesFulfilledRouter { !state.templatePropertiesMetadata || Object.keys(state.templatePropertiesMetadata).length === 0 ) { + this.logger.info( + `No template properties defined, routing to ${this.propertiesFulfilledNodeName}` + ); return this.propertiesFulfilledNodeName; } // If templateProperties haven't been initialized, properties are unfulfilled if (!state.templateProperties) { + this.logger.info( + `Template properties not initialized, routing to ${this.propertiesUnfulfilledNodeName}` + ); return this.propertiesUnfulfilledNodeName; } @@ -57,10 +65,16 @@ export class CheckTemplatePropertiesFulfilledRouter { for (const [propertyName, metadata] of Object.entries(state.templatePropertiesMetadata)) { // If property is required and not present in templateProperties, it's unfulfilled if (metadata.required && !state.templateProperties[propertyName]) { + this.logger.info( + `Property ${propertyName} is required but not present in state.templateProperties["${propertyName}"], routing to ${this.propertiesUnfulfilledNodeName}` + ); return this.propertiesUnfulfilledNodeName; } } + this.logger.info( + `All template properties fulfilled, routing to ${this.propertiesFulfilledNodeName}` + ); return this.propertiesFulfilledNodeName; } } diff --git a/packages/mobile-native-mcp-server/src/workflow/nodes/templateSelection.ts b/packages/mobile-native-mcp-server/src/workflow/nodes/templateSelection.ts index c66cd64f..6634e5dd 100644 --- a/packages/mobile-native-mcp-server/src/workflow/nodes/templateSelection.ts +++ b/packages/mobile-native-mcp-server/src/workflow/nodes/templateSelection.ts @@ -32,6 +32,7 @@ export class TemplateSelectionNode extends AbstractToolNode { } if (!state.templateOptions) { + this.logger.error('Fatal error: No template is available to select.'); return { workflowFatalErrorMessages: ['No template options available for selection'], };