@acorex/connectivity 20.7.4 → 20.7.5

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.
@@ -12019,10 +12019,19 @@ class AXCWorkflowEngine {
12019
12019
  const firstStepId = firstActivity?.id || 'root';
12020
12020
  // Extract correlationId from input if provided (remove it from input to avoid pollution)
12021
12021
  const correlationId = request.input?.['correlationId'] || null;
12022
+ const entityRefId = request.input?.['refId'] || null;
12023
+ const entityRefType = request.input?.['refType'] || null;
12022
12024
  const workflowInput = { ...request.input };
12023
12025
  if (correlationId && workflowInput['correlationId']) {
12024
12026
  delete workflowInput['correlationId'];
12025
12027
  }
12028
+ // Remove refId and refType from workflow input (they're stored in instance metadata)
12029
+ if (entityRefId && workflowInput['refId']) {
12030
+ delete workflowInput['refId'];
12031
+ }
12032
+ if (entityRefType && workflowInput['refType']) {
12033
+ delete workflowInput['refType'];
12034
+ }
12026
12035
  // Create workflow state
12027
12036
  const workflowState = {
12028
12037
  id: `state-${instanceId}`,
@@ -12076,10 +12085,23 @@ class AXCWorkflowEngine {
12076
12085
  incidentCount: 0,
12077
12086
  createdAt: now,
12078
12087
  updatedAt: now,
12079
- finishedAt: null
12088
+ finishedAt: null,
12089
+ // Store entity reference for work item creation
12090
+ entityRefId: entityRefId || null,
12091
+ entityRefType: entityRefType || null,
12080
12092
  };
12081
12093
  // Store instance in IndexedDB
12082
12094
  await this.db.instances.add(instance, instance.id);
12095
+ console.log(`[AXCWorkflowEngine] 💾 Stored workflow instance:`, {
12096
+ id: instance.id,
12097
+ definitionId: instance.definitionId,
12098
+ name: instance.name,
12099
+ correlationId: instance.correlationId,
12100
+ entityRefId: instance.entityRefId,
12101
+ entityRefType: instance.entityRefType,
12102
+ status: instance.status,
12103
+ subStatus: instance.subStatus,
12104
+ });
12083
12105
  // 🎯 Also store in entity service for entity-based access
12084
12106
  await this.saveInstanceToEntityService(instance);
12085
12107
  // Convert to instance state for response (async - needs bookmark lookup)
@@ -12088,7 +12110,8 @@ class AXCWorkflowEngine {
12088
12110
  let currentActivity = firstActivity;
12089
12111
  let executionCount = 0;
12090
12112
  const maxExecutions = 500; // Prevent infinite loops
12091
- let lastActivityOutput = undefined;
12113
+ let lastActivityOutput = state.lastActivityOutput;
12114
+ let activityOutputs = { ...(state.activityOutputs || {}) };
12092
12115
  while (currentActivity && executionCount < maxExecutions) {
12093
12116
  executionCount++;
12094
12117
  // Activity name is the registry key (e.g., 'workflow-activity:show-toast')
@@ -12111,11 +12134,24 @@ class AXCWorkflowEngine {
12111
12134
  });
12112
12135
  // Only create workitem for human-task
12113
12136
  if (pendingTask.taskType === 'human-task') {
12137
+ console.log(`[AXCWorkflowEngine] 👤 Creating work item for human-task activity:`, {
12138
+ instanceId,
12139
+ activityId: currentActivity.id,
12140
+ bookmarkId,
12141
+ activityName: activityDef?.name,
12142
+ instanceEntityRefId: instance.entityRefId,
12143
+ instanceEntityRefType: instance.entityRefType,
12144
+ });
12114
12145
  await this.createWorkItemFromBookmark(instanceId, currentActivity.id, bookmarkId, activityDef);
12115
12146
  }
12147
+ else {
12148
+ console.log(`[AXCWorkflowEngine] ⏭️ Skipping work item creation (taskType: ${pendingTask.taskType}, not human-task)`);
12149
+ }
12116
12150
  // Update state to suspended (waiting for frontend)
12117
12151
  state = {
12118
12152
  ...state,
12153
+ activityOutputs,
12154
+ lastActivityOutput,
12119
12155
  status: pendingTask.taskType == 'human-task' ? 'suspended' : 'running',
12120
12156
  currentStepId: currentActivity.id,
12121
12157
  };
@@ -12125,13 +12161,18 @@ class AXCWorkflowEngine {
12125
12161
  instanceId: instanceId,
12126
12162
  state,
12127
12163
  pendingTask,
12128
- lastActivityOutput
12164
+ activityOutputs,
12165
+ lastActivityOutput,
12129
12166
  };
12130
12167
  }
12131
12168
  // Backend activity → execute it
12132
12169
  console.log(`[AXCWorkflowEngine] ⚙️ Executing backend activity '${currentActivity.name || currentActivity.id}' (${activityType})`);
12133
12170
  const executionResult = await this.executeBackendActivityLocally(currentActivity, { ...state.variables, ...state.input }, state);
12134
12171
  lastActivityOutput = executionResult.output;
12172
+ activityOutputs = {
12173
+ ...activityOutputs,
12174
+ [currentActivity.id]: executionResult.output,
12175
+ };
12135
12176
  // Update variables with output
12136
12177
  state = {
12137
12178
  ...state,
@@ -12140,6 +12181,8 @@ class AXCWorkflowEngine {
12140
12181
  //TODO need here!
12141
12182
  ...executionResult.output
12142
12183
  },
12184
+ activityOutputs,
12185
+ lastActivityOutput,
12143
12186
  currentStepId: currentActivity.id,
12144
12187
  lastUpdated: new Date()
12145
12188
  };
@@ -12160,7 +12203,9 @@ class AXCWorkflowEngine {
12160
12203
  return {
12161
12204
  instanceId: instanceId,
12162
12205
  state,
12163
- pendingTask: null
12206
+ pendingTask: null,
12207
+ activityOutputs,
12208
+ lastActivityOutput,
12164
12209
  };
12165
12210
  }
12166
12211
  // Find next activity
@@ -12193,13 +12238,16 @@ class AXCWorkflowEngine {
12193
12238
  ...state,
12194
12239
  status: 'completed',
12195
12240
  currentStepId: undefined,
12196
- output: state.variables
12241
+ output: state.variables,
12242
+ activityOutputs,
12243
+ lastActivityOutput,
12197
12244
  };
12198
12245
  await this.updateInstanceFromState(instanceId, state);
12199
12246
  return {
12200
12247
  instanceId: instanceId,
12201
12248
  state: state,
12202
12249
  pendingTask: null,
12250
+ activityOutputs,
12203
12251
  lastActivityOutput: lastActivityOutput
12204
12252
  };
12205
12253
  }
@@ -12262,6 +12310,12 @@ class AXCWorkflowEngine {
12262
12310
  // Apply frontend outputs into workflow state
12263
12311
  // Merge userInput into variables (not as separate keys)
12264
12312
  const userInput = request.userInput || {};
12313
+ let activityOutputs = { ...(state.activityOutputs || {}) };
12314
+ let lastActivityOutput = userInput;
12315
+ activityOutputs = {
12316
+ ...activityOutputs,
12317
+ [request.stepId]: userInput,
12318
+ };
12265
12319
  state = {
12266
12320
  ...state,
12267
12321
  variables: {
@@ -12269,6 +12323,8 @@ class AXCWorkflowEngine {
12269
12323
  ...userInput, // Merge userInput directly into variables
12270
12324
  [`${request.stepId}_outcome`]: request.outcome, // Keep outcome for reference
12271
12325
  },
12326
+ activityOutputs,
12327
+ lastActivityOutput,
12272
12328
  lastUpdated: new Date()
12273
12329
  };
12274
12330
  // Find next activity based on outcome from frontend
@@ -12281,7 +12337,9 @@ class AXCWorkflowEngine {
12281
12337
  ...state,
12282
12338
  status: 'completed',
12283
12339
  currentStepId: undefined,
12284
- output: state.variables
12340
+ output: state.variables,
12341
+ activityOutputs,
12342
+ lastActivityOutput,
12285
12343
  };
12286
12344
  console.log('[AXCWorkflowExecutionService] 📝 Updating instance to completed state');
12287
12345
  await this.updateInstanceFromState(request.instanceId, state);
@@ -12335,6 +12393,8 @@ class AXCWorkflowEngine {
12335
12393
  // - ui-activity: running (workflow manager will execute it immediately)
12336
12394
  state = {
12337
12395
  ...state,
12396
+ activityOutputs,
12397
+ lastActivityOutput,
12338
12398
  status: taskType === 'human-task' ? 'suspended' : 'running',
12339
12399
  currentStepId: currentActivity.id,
12340
12400
  };
@@ -12350,6 +12410,11 @@ class AXCWorkflowEngine {
12350
12410
  // Backend activity → execute it
12351
12411
  console.log(`[AXCWorkflowEngine] ⚙️ Executing backend activity '${currentActivity.name || currentActivity.id}' (${activityType})`);
12352
12412
  const executionResult = await this.executeBackendActivityLocally(currentActivity, { ...state.variables, ...state.input }, state);
12413
+ lastActivityOutput = executionResult.output;
12414
+ activityOutputs = {
12415
+ ...activityOutputs,
12416
+ [currentActivity.id]: executionResult.output,
12417
+ };
12353
12418
  // Update variables with output
12354
12419
  state = {
12355
12420
  ...state,
@@ -12357,6 +12422,8 @@ class AXCWorkflowEngine {
12357
12422
  ...state.variables,
12358
12423
  ...executionResult.output
12359
12424
  },
12425
+ activityOutputs,
12426
+ lastActivityOutput,
12360
12427
  currentStepId: currentActivity.id,
12361
12428
  lastUpdated: new Date()
12362
12429
  };
@@ -12371,7 +12438,9 @@ class AXCWorkflowEngine {
12371
12438
  ...state,
12372
12439
  status: 'completed',
12373
12440
  currentStepId: undefined,
12374
- output: state.variables
12441
+ output: state.variables,
12442
+ activityOutputs,
12443
+ lastActivityOutput,
12375
12444
  };
12376
12445
  await this.updateInstanceFromState(request.instanceId, state);
12377
12446
  return {
@@ -12411,7 +12480,9 @@ class AXCWorkflowEngine {
12411
12480
  ...state,
12412
12481
  status: 'completed',
12413
12482
  currentStepId: undefined,
12414
- output: state.variables
12483
+ output: state.variables,
12484
+ activityOutputs,
12485
+ lastActivityOutput,
12415
12486
  };
12416
12487
  await this.updateInstanceFromState(request.instanceId, state);
12417
12488
  return {
@@ -12921,12 +12992,26 @@ class AXCWorkflowEngine {
12921
12992
  */
12922
12993
  async createWorkItemFromBookmark(instanceId, activityId, bookmarkId, activityDef) {
12923
12994
  try {
12995
+ console.log(`[AXCWorkflowEngine] 📋 createWorkItemFromBookmark called:`, {
12996
+ instanceId,
12997
+ activityId,
12998
+ bookmarkId,
12999
+ activityDefName: activityDef?.name,
13000
+ });
12924
13001
  // Get workflow instance to get workflow name
12925
13002
  const instance = await this.db.instances.get(instanceId);
12926
13003
  if (!instance) {
12927
13004
  console.warn(`[AXCWorkflowEngine] ⚠️ Instance ${instanceId} not found, skipping work item creation`);
12928
13005
  return;
12929
13006
  }
13007
+ console.log(`[AXCWorkflowEngine] 📦 Workflow instance found:`, {
13008
+ id: instance.id,
13009
+ definitionId: instance.definitionId,
13010
+ name: instance.name,
13011
+ correlationId: instance.correlationId,
13012
+ entityRefId: instance.entityRefId,
13013
+ entityRefType: instance.entityRefType,
13014
+ });
12930
13015
  // Get bookmark to extract taskToken
12931
13016
  const bookmark = await this.db.bookmarks.get(bookmarkId);
12932
13017
  let taskToken = null;
@@ -12942,11 +13027,25 @@ class AXCWorkflowEngine {
12942
13027
  // Get workflow definition to get workflow title
12943
13028
  const workflowDef = await this.getDefinition(instance.definitionId || instance.name || '');
12944
13029
  const workflowTitle = workflowDef?.title || instance.name || 'Workflow';
13030
+ console.log(`[AXCWorkflowEngine] 📖 Workflow definition:`, {
13031
+ definitionId: instance.definitionId,
13032
+ name: instance.name,
13033
+ workflowTitle,
13034
+ workflowDefFound: !!workflowDef,
13035
+ });
12945
13036
  // Get activity definition for title
12946
13037
  const activityTitle = activityDef?.title || activityId;
12947
13038
  // Create a meaningful title
12948
13039
  const workItemTitle = `${workflowTitle} - ${activityTitle}`;
12949
13040
  const now = new Date().toISOString();
13041
+ // Extract entity reference from instance
13042
+ const entityRefId = instance.entityRefId || null;
13043
+ const entityRefType = instance.entityRefType || null;
13044
+ console.log(`[AXCWorkflowEngine] 🏷️ Entity reference:`, {
13045
+ entityRefId,
13046
+ entityRefType,
13047
+ hasEntityRef: !!(entityRefId && entityRefType),
13048
+ });
12950
13049
  // Create work item
12951
13050
  const workItem = {
12952
13051
  id: AXPDataGenerator.uuid(),
@@ -12961,8 +13060,8 @@ class AXCWorkflowEngine {
12961
13060
  priority: 'Normal',
12962
13061
  assignedUserId: null, // Will be assigned later
12963
13062
  correlationId: instance.correlationId || null,
12964
- entityRefId: instance.entityRefId || null,
12965
- entityRefType: instance.entityRefType || null,
13063
+ entityRefId: entityRefId,
13064
+ entityRefType: entityRefType,
12966
13065
  createdAt: now,
12967
13066
  updatedAt: now,
12968
13067
  };
@@ -12971,13 +13070,146 @@ class AXCWorkflowEngine {
12971
13070
  workItem.taskToken = taskToken;
12972
13071
  }
12973
13072
  await this.entityStorageService.insertOne('WorkflowManagement.WorkItem', workItem);
12974
- console.log(`[AXCWorkflowEngine] ✅ Created work item: ${workItem.id} for bookmark ${bookmarkId} with title: ${workItemTitle}`);
13073
+ console.log(`[AXCWorkflowEngine] ✅ Created work item:`, {
13074
+ id: workItem.id,
13075
+ instanceId: instanceId,
13076
+ bookmarkId: bookmarkId,
13077
+ activityNodeId: activityId,
13078
+ title: workItemTitle,
13079
+ entityRefId: workItem.entityRefId,
13080
+ entityRefType: workItem.entityRefType,
13081
+ status: workItem.status,
13082
+ priority: workItem.priority,
13083
+ assignedUserId: workItem.assignedUserId,
13084
+ createdAt: workItem.createdAt,
13085
+ });
13086
+ // 🎯 Try to set assignedUserId from entity data if entityRefId is available
13087
+ // COMMENTED FOR TESTING: Allow all tasks to appear in task board
13088
+ // if (entityRefId && entityRefType && !workItem.assignedUserId) {
13089
+ // try {
13090
+ // await this.updateWorkItemAssigneeFromEntity(workItem.id, entityRefType, entityRefId);
13091
+ // } catch (error) {
13092
+ // console.warn(`[AXCWorkflowEngine] ⚠️ Failed to set assignee from entity data:`, error);
13093
+ // // Continue without assignee - can be set later
13094
+ // }
13095
+ // }
12975
13096
  }
12976
13097
  catch (error) {
12977
13098
  console.error(`[AXCWorkflowEngine] ❌ Failed to create work item for bookmark ${bookmarkId}:`, error);
12978
13099
  // Don't fail workflow execution if work item creation fails
12979
13100
  }
12980
13101
  }
13102
+ /**
13103
+ * Update work items entity reference after entity is created.
13104
+ */
13105
+ async updateWorkItemsEntityRef(instanceId, entityRefId, entityRefType) {
13106
+ try {
13107
+ console.log(`[AXCWorkflowEngine] 🔄 Updating work items entity reference:`, {
13108
+ instanceId,
13109
+ entityRefId,
13110
+ entityRefType,
13111
+ });
13112
+ // Query all work items for this instance
13113
+ const workItems = await this.entityStorageService.query('WorkflowManagement.WorkItem', {
13114
+ skip: 0,
13115
+ take: 1000,
13116
+ filter: {
13117
+ logic: 'and',
13118
+ filters: [
13119
+ {
13120
+ field: 'instanceId',
13121
+ operator: { type: 'equal' },
13122
+ value: instanceId,
13123
+ },
13124
+ ],
13125
+ },
13126
+ });
13127
+ console.log(`[AXCWorkflowEngine] 📦 Found ${workItems.items?.length || 0} work items to update`);
13128
+ // Update each work item
13129
+ for (const workItem of workItems.items || []) {
13130
+ if (!workItem.entityRefId || !workItem.entityRefType) {
13131
+ const updatedWorkItem = {
13132
+ ...workItem,
13133
+ entityRefId,
13134
+ entityRefType,
13135
+ updatedAt: new Date().toISOString(),
13136
+ };
13137
+ await this.entityStorageService.updateOne('WorkflowManagement.WorkItem', workItem.id, updatedWorkItem);
13138
+ console.log(`[AXCWorkflowEngine] ✅ Updated work item ${workItem.id} with entity reference:`, {
13139
+ workItemId: workItem.id,
13140
+ entityRefId,
13141
+ entityRefType,
13142
+ });
13143
+ // Also try to set assignee from entity data
13144
+ // COMMENTED FOR TESTING: Allow all tasks to appear in task board
13145
+ // if (!workItem.assignedUserId) {
13146
+ // try {
13147
+ // await this.updateWorkItemAssigneeFromEntity(workItem.id, entityRefType, entityRefId);
13148
+ // } catch (error) {
13149
+ // console.warn(`[AXCWorkflowEngine] ⚠️ Failed to set assignee for work item ${workItem.id}:`, error);
13150
+ // }
13151
+ // }
13152
+ }
13153
+ }
13154
+ }
13155
+ catch (error) {
13156
+ console.error(`[AXCWorkflowEngine] ❌ Failed to update work items entity reference:`, error);
13157
+ // Don't fail workflow execution if update fails
13158
+ }
13159
+ }
13160
+ /**
13161
+ * Update work item assignee from entity data (e.g., employee.manager.userId for leave requests).
13162
+ */
13163
+ async updateWorkItemAssigneeFromEntity(workItemId, entityRefType, entityRefId) {
13164
+ try {
13165
+ console.log(`[AXCWorkflowEngine] 👤 Setting assignee from entity data:`, {
13166
+ workItemId,
13167
+ entityRefType,
13168
+ entityRefId,
13169
+ });
13170
+ // Load entity data
13171
+ const entityData = await this.entityStorageService.getOne(entityRefType, entityRefId);
13172
+ if (!entityData) {
13173
+ console.warn(`[AXCWorkflowEngine] ⚠️ Entity data not found: ${entityRefType}:${entityRefId}`);
13174
+ return;
13175
+ }
13176
+ // Extract assignee based on entity type
13177
+ let assignedUserId = null;
13178
+ // For leave requests: use employee.manager.userId
13179
+ if (entityRefType === 'HumanCapitalManagement.LeaveRequest') {
13180
+ assignedUserId = entityData.employee?.manager?.userId || entityData.employeeId || null;
13181
+ console.log(`[AXCWorkflowEngine] 📋 Leave request assignee:`, {
13182
+ employeeId: entityData.employeeId,
13183
+ managerUserId: entityData.employee?.manager?.userId,
13184
+ assignedUserId,
13185
+ });
13186
+ }
13187
+ // Update work item if assignee found
13188
+ if (assignedUserId) {
13189
+ const workItem = await this.entityStorageService.getOne('WorkflowManagement.WorkItem', workItemId);
13190
+ if (workItem) {
13191
+ const updatedWorkItem = {
13192
+ ...workItem,
13193
+ assignedUserId,
13194
+ assignedAt: new Date().toISOString(),
13195
+ updatedAt: new Date().toISOString(),
13196
+ };
13197
+ await this.entityStorageService.updateOne('WorkflowManagement.WorkItem', workItemId, updatedWorkItem);
13198
+ console.log(`[AXCWorkflowEngine] ✅ Updated work item assignee:`, {
13199
+ workItemId,
13200
+ assignedUserId,
13201
+ });
13202
+ }
13203
+ }
13204
+ else {
13205
+ console.log(`[AXCWorkflowEngine] ℹ️ No assignee found for entity ${entityRefType}:${entityRefId}`);
13206
+ }
13207
+ }
13208
+ catch (error) {
13209
+ console.warn(`[AXCWorkflowEngine] ⚠️ Failed to set assignee from entity data:`, error);
13210
+ // Don't fail if assignee update fails
13211
+ }
13212
+ }
12981
13213
  /**
12982
13214
  * Consume (mark as consumed) a bookmark for a workflow instance.
12983
13215
  *
@@ -13051,7 +13283,12 @@ class AXCWorkflowEngine {
13051
13283
  }
13052
13284
  // Extract state from workflowState (ERD: WORKFLOW_INSTANCE_STATE)
13053
13285
  // Properties map to variables
13054
- const variables = state.properties || {};
13286
+ const properties = (state.properties || {});
13287
+ const { __activityOutputs, __lastActivityOutput, ...variables } = properties;
13288
+ const activityOutputs = __activityOutputs && typeof __activityOutputs === 'object'
13289
+ ? __activityOutputs
13290
+ : {};
13291
+ const lastActivityOutput = __lastActivityOutput;
13055
13292
  const input = state.input || {};
13056
13293
  const output = state.output || {};
13057
13294
  // Normalize dates (instance.updatedAt is always string in AXPWorkflowInstance)
@@ -13064,6 +13301,8 @@ class AXCWorkflowEngine {
13064
13301
  status,
13065
13302
  currentStepId,
13066
13303
  variables,
13304
+ activityOutputs,
13305
+ lastActivityOutput,
13067
13306
  input,
13068
13307
  output,
13069
13308
  lastUpdated
@@ -13119,7 +13358,11 @@ class AXCWorkflowEngine {
13119
13358
  instance.workflowState.subStatus = subStatus;
13120
13359
  instance.workflowState.input = instanceState.input || {};
13121
13360
  instance.workflowState.output = instanceState.output || {};
13122
- instance.workflowState.properties = instanceState.variables || {};
13361
+ instance.workflowState.properties = {
13362
+ ...(instanceState.variables || {}),
13363
+ __activityOutputs: instanceState.activityOutputs || {},
13364
+ __lastActivityOutput: instanceState.lastActivityOutput,
13365
+ };
13123
13366
  instance.workflowState.updatedAt = now;
13124
13367
  if (instanceState.status === 'completed' || instanceState.status === 'error') {
13125
13368
  instance.workflowState.finishedAt = now;
@@ -13261,6 +13504,12 @@ class AXCWorkflowEngine {
13261
13504
  const connections = workflow.graph.connections || [];
13262
13505
  // Apply frontend output to workflow state
13263
13506
  const output = request.output || {};
13507
+ let activityOutputs = { ...(state.activityOutputs || {}) };
13508
+ let lastActivityOutput = output;
13509
+ activityOutputs = {
13510
+ ...activityOutputs,
13511
+ [request.activityNode]: output,
13512
+ };
13264
13513
  state = {
13265
13514
  ...state,
13266
13515
  variables: {
@@ -13268,8 +13517,43 @@ class AXCWorkflowEngine {
13268
13517
  ...output, // Merge frontend output into variables
13269
13518
  [`${request.activityNode}_outcome`]: request.outcome, // Keep outcome for reference
13270
13519
  },
13520
+ activityOutputs,
13521
+ lastActivityOutput,
13271
13522
  lastUpdated: new Date(),
13272
13523
  };
13524
+ // 🎯 Update entityRefId and entityRefType if entity was created
13525
+ // Check if this activity created an entity (workflow-activity:create-entity)
13526
+ const completedActivity = this.findActivityInGraph(workflow.graph, request.activityNode);
13527
+ if (completedActivity?.name === 'workflow-activity:create-entity' && output['id']) {
13528
+ // Extract entity type from activity inputs
13529
+ const entityModule = completedActivity.inputs?.module || '';
13530
+ const entityName = completedActivity.inputs?.entity || '';
13531
+ const entityType = entityModule && entityName ? `${entityModule}.${entityName}` : null;
13532
+ const entityId = output['id'];
13533
+ console.log(`[AXCWorkflowEngine] 🔗 Entity created in workflow:`, {
13534
+ activityNode: request.activityNode,
13535
+ entityId,
13536
+ entityType,
13537
+ entityModule,
13538
+ entityName,
13539
+ });
13540
+ if (entityId && entityType) {
13541
+ // Update workflow instance with entity reference
13542
+ const instance = await this.db.instances.get(request.instanceId);
13543
+ if (instance) {
13544
+ instance.entityRefId = entityId;
13545
+ instance.entityRefType = entityType;
13546
+ await this.db.instances.put(instance, instance.id);
13547
+ console.log(`[AXCWorkflowEngine] ✅ Updated workflow instance with entity reference:`, {
13548
+ instanceId: request.instanceId,
13549
+ entityRefId: entityId,
13550
+ entityRefType: entityType,
13551
+ });
13552
+ // Update all work items for this instance with entity reference
13553
+ await this.updateWorkItemsEntityRef(request.instanceId, entityId, entityType);
13554
+ }
13555
+ }
13556
+ }
13273
13557
  // Find next activity based on outcome from frontend
13274
13558
  const nextConnection = connections.find((conn) => conn.source.activtyName === request.activityNode &&
13275
13559
  (conn.source.port === request.outcome || (!conn.source.port && request.outcome === 'Done')));
@@ -13304,7 +13588,7 @@ class AXCWorkflowEngine {
13304
13588
  await this.updateInstanceFromState(request.instanceId, state);
13305
13589
  throw new Error(`Next activity '${nextConnection.target.activtyName}' not found in workflow graph`);
13306
13590
  }
13307
- let lastActivityOutput = undefined;
13591
+ // `activityOutputs` and `lastActivityOutput` are tracked and persisted in `state`.
13308
13592
  while (currentActivity && executionCount < maxExecutions) {
13309
13593
  executionCount++;
13310
13594
  // Map activity name (registry key) to activity type
@@ -13332,6 +13616,8 @@ class AXCWorkflowEngine {
13332
13616
  // Update state (suspended for human-task, running for ui-activity)
13333
13617
  state = {
13334
13618
  ...state,
13619
+ activityOutputs,
13620
+ lastActivityOutput,
13335
13621
  status: pendingTask.taskType === 'human-task' ? 'suspended' : 'running',
13336
13622
  currentStepId: currentActivity.id,
13337
13623
  };
@@ -13348,6 +13634,10 @@ class AXCWorkflowEngine {
13348
13634
  console.log(`[AXCWorkflowEngine] ⚙️ Executing backend activity '${currentActivity.name || currentActivity.id}' (${activityType})`);
13349
13635
  const executionResult = await this.executeBackendActivityLocally(currentActivity, { ...state.variables, ...state.input }, state);
13350
13636
  lastActivityOutput = executionResult.output;
13637
+ activityOutputs = {
13638
+ ...activityOutputs,
13639
+ [currentActivity.id]: executionResult.output,
13640
+ };
13351
13641
  // Update variables with output
13352
13642
  state = {
13353
13643
  ...state,
@@ -13355,6 +13645,8 @@ class AXCWorkflowEngine {
13355
13645
  ...state.variables,
13356
13646
  ...executionResult.output,
13357
13647
  },
13648
+ activityOutputs,
13649
+ lastActivityOutput,
13358
13650
  currentStepId: currentActivity.id,
13359
13651
  lastUpdated: new Date(),
13360
13652
  };
@@ -13370,6 +13662,8 @@ class AXCWorkflowEngine {
13370
13662
  status: 'completed',
13371
13663
  currentStepId: undefined,
13372
13664
  output: state.variables,
13665
+ activityOutputs,
13666
+ lastActivityOutput,
13373
13667
  };
13374
13668
  await this.updateInstanceFromState(request.instanceId, state);
13375
13669
  return {
@@ -13410,6 +13704,8 @@ class AXCWorkflowEngine {
13410
13704
  status: 'completed',
13411
13705
  currentStepId: undefined,
13412
13706
  output: state.variables,
13707
+ activityOutputs,
13708
+ lastActivityOutput,
13413
13709
  };
13414
13710
  await this.updateInstanceFromState(request.instanceId, state);
13415
13711
  return {