@minded-ai/mindedjs 1.0.80-beta.8 → 1.0.80

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.
Files changed (81) hide show
  1. package/dist/agent.d.ts +5 -4
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +81 -53
  4. package/dist/agent.js.map +1 -1
  5. package/dist/cli/index.js +0 -0
  6. package/dist/edges/createLogicalRouter.d.ts +1 -1
  7. package/dist/edges/createLogicalRouter.d.ts.map +1 -1
  8. package/dist/edges/createLogicalRouter.js +5 -16
  9. package/dist/edges/createLogicalRouter.js.map +1 -1
  10. package/dist/edges/edgeFactory.d.ts.map +1 -1
  11. package/dist/edges/edgeFactory.js +2 -4
  12. package/dist/edges/edgeFactory.js.map +1 -1
  13. package/dist/events/AgentEvents.d.ts +12 -8
  14. package/dist/events/AgentEvents.d.ts.map +1 -1
  15. package/dist/events/AgentEvents.js +1 -0
  16. package/dist/events/AgentEvents.js.map +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/nodes/addAppToolNode.d.ts.map +1 -1
  22. package/dist/nodes/addAppToolNode.js +9 -1
  23. package/dist/nodes/addAppToolNode.js.map +1 -1
  24. package/dist/nodes/addHumanInTheLoopNode.d.ts.map +1 -1
  25. package/dist/nodes/addHumanInTheLoopNode.js +3 -2
  26. package/dist/nodes/addHumanInTheLoopNode.js.map +1 -1
  27. package/dist/nodes/addJumpToNode.d.ts +1 -1
  28. package/dist/nodes/addJumpToNode.d.ts.map +1 -1
  29. package/dist/nodes/addJumpToNode.js +2 -2
  30. package/dist/nodes/addJumpToNode.js.map +1 -1
  31. package/dist/nodes/addPromptNode.d.ts.map +1 -1
  32. package/dist/nodes/addPromptNode.js +10 -1
  33. package/dist/nodes/addPromptNode.js.map +1 -1
  34. package/dist/nodes/addToolNode.js +1 -1
  35. package/dist/nodes/addToolNode.js.map +1 -1
  36. package/dist/nodes/addToolRunNode.d.ts.map +1 -1
  37. package/dist/nodes/addToolRunNode.js +2 -1
  38. package/dist/nodes/addToolRunNode.js.map +1 -1
  39. package/dist/nodes/addTriggerNode.js +1 -1
  40. package/dist/nodes/addTriggerNode.js.map +1 -1
  41. package/dist/types/Agent.types.d.ts +25 -13
  42. package/dist/types/Agent.types.d.ts.map +1 -1
  43. package/dist/types/Agent.types.js +9 -7
  44. package/dist/types/Agent.types.js.map +1 -1
  45. package/dist/types/Flows.types.d.ts +5 -1
  46. package/dist/types/Flows.types.d.ts.map +1 -1
  47. package/dist/types/Flows.types.js +6 -1
  48. package/dist/types/Flows.types.js.map +1 -1
  49. package/dist/types/LangGraph.types.d.ts +3 -45
  50. package/dist/types/LangGraph.types.d.ts.map +1 -1
  51. package/dist/types/LangGraph.types.js +0 -5
  52. package/dist/types/LangGraph.types.js.map +1 -1
  53. package/dist/utils/history.d.ts +3 -0
  54. package/dist/utils/history.d.ts.map +1 -0
  55. package/dist/utils/history.js +12 -0
  56. package/dist/utils/history.js.map +1 -0
  57. package/package.json +5 -8
  58. package/src/agent.ts +112 -60
  59. package/src/edges/createLogicalRouter.ts +5 -18
  60. package/src/edges/edgeFactory.ts +2 -4
  61. package/src/events/AgentEvents.ts +11 -8
  62. package/src/index.ts +8 -1
  63. package/src/nodes/addAppToolNode.ts +10 -2
  64. package/src/nodes/addHumanInTheLoopNode.ts +3 -2
  65. package/src/nodes/addJumpToNode.ts +3 -9
  66. package/src/nodes/addPromptNode.ts +10 -2
  67. package/src/nodes/addToolNode.ts +1 -1
  68. package/src/nodes/addToolRunNode.ts +2 -2
  69. package/src/nodes/addTriggerNode.ts +1 -1
  70. package/src/types/Agent.types.ts +28 -14
  71. package/src/types/Flows.types.ts +6 -1
  72. package/src/types/LangGraph.types.ts +2 -10
  73. package/src/utils/history.ts +9 -0
  74. package/dist/guidelines/guidelinesManager.d.ts +0 -37
  75. package/dist/guidelines/guidelinesManager.d.ts.map +0 -1
  76. package/dist/guidelines/guidelinesManager.js +0 -172
  77. package/dist/guidelines/guidelinesManager.js.map +0 -1
  78. package/dist/utils/extractToolMemoryResponse.d.ts +0 -4
  79. package/dist/utils/extractToolMemoryResponse.d.ts.map +0 -1
  80. package/dist/utils/extractToolMemoryResponse.js +0 -16
  81. package/dist/utils/extractToolMemoryResponse.js.map +0 -1
package/src/agent.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Flow, NodeType, Node, EdgeType, KnownTriggerNames, TriggerType, VoiceTriggerNode } from './types/Flows.types';
1
+ import { Flow, NodeType, Node, EdgeType, KnownTriggerNames, TriggerType, VoiceTriggerNode, internalNodesSuffix } from './types/Flows.types';
2
2
 
3
3
  import { Tool } from './types/Tools.types';
4
4
  import { v4 as uuidv4 } from 'uuid';
@@ -15,7 +15,15 @@ import { InvokeMessage, MindedConnectionSocketMessageType } from './platform/min
15
15
  import * as fs from 'fs';
16
16
  import * as path from 'path';
17
17
  import * as yaml from 'js-yaml';
18
- import { AgentInvokeParams, FlowHistoryType, MindedSDKConfig, SessionType, TriggerInvocationHistory } from './types/Agent.types';
18
+ import {
19
+ AgentInvokeParams,
20
+ AppTrigggerHistoryStep,
21
+ TriggerHistoryStep,
22
+ HistoryStepType,
23
+ MindedSDKConfig,
24
+ SessionType,
25
+ HistoryStep,
26
+ } from './types/Agent.types';
19
27
  import { createLlmInstance } from './llm/createLlmInstance';
20
28
  import { createCheckpointSaver } from './checkpointer/checkpointSaverFactory';
21
29
  import { getConfig } from './platform/config';
@@ -27,6 +35,7 @@ import { BaseVoiceMessage, OnVoiceAudioOut } from './platform/mindedConnectionTy
27
35
  import { PIIGateway, PIIGatewayInstance } from './platform/piiGateway';
28
36
  import { logger } from './utils/logger';
29
37
  import { loadPlaybooks, Playbook } from './playbooks/playbooks';
38
+ import { createHistoryStep } from './utils/history';
30
39
 
31
40
  type CreateAgentParams<Memory> = {
32
41
  memorySchema: z.ZodSchema;
@@ -58,7 +67,7 @@ export class Agent {
58
67
  private memorySchema: z.ZodSchema;
59
68
  private flows!: Flow[];
60
69
  public tools!: Tool<any, any>[];
61
- public llm!: BaseLanguageModel;
70
+ private llm!: BaseLanguageModel;
62
71
  public mindedConnection: MindedConnection | null = null;
63
72
  // Langgraph memory saver. In memory for local development, Custom for Platform
64
73
  private checkpointer!: BaseCheckpointSaver;
@@ -89,6 +98,7 @@ export class Agent {
89
98
 
90
99
  private initialized = false;
91
100
  private initPromise: Promise<void> | null = null;
101
+ private startingNodeId: string | null = null;
92
102
  public voiceSessions: Map<string, VoiceSession> = new Map();
93
103
 
94
104
  /**
@@ -284,10 +294,12 @@ export class Agent {
284
294
  // Add edge from start to first node if no triggers exist
285
295
  const hasTrigger = nodes.some((node) => node.type === NodeType.TRIGGER && node.triggerType !== TriggerType.MANUAL);
286
296
  if (!hasTrigger && nodes.length > 0) {
297
+ this.startingNodeId = nodes[0].name;
287
298
  graph.addEdge('__start__', nodes[0].name as any);
288
299
  } else {
289
300
  nodes.forEach((node) => {
290
301
  if (node.type === NodeType.TRIGGER && node.triggerType !== TriggerType.MANUAL) {
302
+ this.startingNodeId = node.name;
291
303
  graph.addEdge('__start__', node.name as any);
292
304
  }
293
305
  });
@@ -322,7 +334,6 @@ export class Agent {
322
334
  memory: initialMemory,
323
335
  triggerMetadata: null,
324
336
  history: [],
325
- triggerInvocations: [] as Array<TriggerInvocationHistory>,
326
337
  sessionId: state.sessionId || uuidv4(), // Preserve existing sessionId or generate new one
327
338
  sessionType: state.sessionType || SessionType.TEXT,
328
339
  };
@@ -335,6 +346,33 @@ export class Agent {
335
346
  return initialState;
336
347
  }
337
348
 
349
+ private createTriggerHistoryStep(
350
+ currentHistory: HistoryStep[],
351
+ nodeId: string,
352
+ messageIds: string[],
353
+ triggerName: string,
354
+ triggerBody: any,
355
+ appName?: string,
356
+ ): HistoryStep {
357
+ const baseStep = {
358
+ nodeId: nodeId,
359
+ nodeDisplayName: triggerName,
360
+ raw: triggerBody,
361
+ messageIds,
362
+ } as HistoryStep;
363
+
364
+ return appName
365
+ ? createHistoryStep<AppTrigggerHistoryStep>(currentHistory, {
366
+ ...baseStep,
367
+ type: HistoryStepType.APP_TRIGGER_NODE,
368
+ appName,
369
+ })
370
+ : createHistoryStep<TriggerHistoryStep>(currentHistory, {
371
+ ...baseStep,
372
+ type: HistoryStepType.TRIGGER_NODE,
373
+ });
374
+ }
375
+
338
376
  /**
339
377
  * Invoke a trigger to start agent execution with the specified parameters.
340
378
  *
@@ -364,69 +402,83 @@ export class Agent {
364
402
  * ```
365
403
  */
366
404
  public async invoke({ triggerBody, triggerName, sessionId, appName }: AgentInvokeParams) {
367
- await this.waitForInitialization();
368
- let messages: Array<BaseMessage> = [];
369
- let memoryUpdate = {};
370
- let sessionType: SessionType = SessionType.TEXT;
371
405
  sessionId = sessionId ?? uuidv4();
372
- if (triggerName === KnownTriggerNames.DASHBOARD_MESSAGE || triggerName === KnownTriggerNames.VOICE_MESSAGE) {
373
- if (!triggerBody.content) {
374
- throw new Error(`Trigger body content is required for ${JSON.stringify(triggerBody)}`);
375
- }
376
- messages.push(new HumanMessage(triggerBody.content));
377
- sessionType = triggerName === KnownTriggerNames.VOICE_MESSAGE ? SessionType.VOICE : SessionType.TEXT;
378
- } else {
379
- const results = await this.emit(AgentEvents.TRIGGER_EVENT, {
380
- triggerName,
381
- triggerBody,
382
- sessionId,
383
- });
384
- if (results.length === 0) {
385
- if (appName) {
386
- messages = triggerTypeToDefaultMessage[appName]?.[triggerName]?.(triggerBody) ?? [new HumanMessage(JSON.stringify(triggerBody))];
387
- } else {
388
- messages = [new HumanMessage(JSON.stringify(triggerBody))];
406
+ try {
407
+ await this.waitForInitialization();
408
+ let messages: Array<BaseMessage> = [];
409
+ let memoryUpdate = {};
410
+ let sessionType: SessionType = SessionType.TEXT;
411
+ if (triggerName === KnownTriggerNames.DASHBOARD_MESSAGE || triggerName === KnownTriggerNames.VOICE_MESSAGE) {
412
+ if (!triggerBody.content) {
413
+ throw new Error(`Trigger body content is required for ${JSON.stringify(triggerBody)}`);
389
414
  }
415
+ messages = [new HumanMessage({ content: triggerBody.content, id: uuidv4() })];
416
+ sessionType = triggerName === KnownTriggerNames.VOICE_MESSAGE ? SessionType.VOICE : SessionType.TEXT;
390
417
  } else {
391
- const handlerResult = results.find((r) => r !== undefined);
392
- if (handlerResult) {
393
- if (!handlerResult.isQualified) {
394
- logger.info(`Trigger ${triggerName} was disqualified`);
395
- return;
418
+ const results = await this.emit(AgentEvents.TRIGGER_EVENT, {
419
+ triggerName,
420
+ triggerBody,
421
+ sessionId,
422
+ });
423
+ if (results.length === 0) {
424
+ if (appName) {
425
+ messages = triggerTypeToDefaultMessage[appName]?.[triggerName]?.(triggerBody) ?? [
426
+ new HumanMessage({ content: JSON.stringify(triggerBody), id: uuidv4() }),
427
+ ];
428
+ } else {
429
+ messages = [new HumanMessage({ content: JSON.stringify(triggerBody), id: uuidv4() })];
430
+ }
431
+ } else {
432
+ const handlerResult = results.find((r) => r !== undefined);
433
+ if (handlerResult) {
434
+ if (!handlerResult.isQualified) {
435
+ logger.info(`Trigger ${triggerName} was disqualified`);
436
+ return;
437
+ }
438
+ memoryUpdate = handlerResult.memory || {};
439
+ messages = handlerResult.messages ?? [];
440
+ sessionId = handlerResult.sessionId ?? sessionId;
396
441
  }
397
- memoryUpdate = handlerResult.memory || {};
398
- messages = handlerResult.messages ?? [];
399
- sessionId = handlerResult.sessionId ?? sessionId;
400
442
  }
401
443
  }
402
- }
403
444
 
404
- const triggerInvocation = { appName, triggerName, triggerBody };
405
- const history = [
406
- {
407
- type: FlowHistoryType.TRIGGER_INVOCATION,
408
- ...triggerInvocation,
409
- },
410
- ];
411
- logger.info(`Invoking trigger ${triggerName} with session ${sessionId}`);
412
- const langraphConfig = this.getLangraphConfig(sessionId || uuidv4());
413
- const state = await this.compiledGraph.getState(langraphConfig);
414
- let res;
415
- // Resume interruption
416
- if (state.tasks?.[0]?.interrupts?.length > 0) {
417
- res = await this.compiledGraph.invoke(
418
- new Command({
419
- resume: { memory: memoryUpdate, messages, history, triggerInvocations: [triggerInvocation], sessionId, sessionType },
420
- }),
421
- langraphConfig,
422
- );
423
- } else {
424
- res = await this.compiledGraph.invoke(
425
- { messages, memory: memoryUpdate, history, triggerInvocations: [triggerInvocation], sessionId, sessionType },
426
- langraphConfig,
445
+ logger.info(`Invoking trigger ${triggerName} with session ${sessionId}`);
446
+ const langraphConfig = this.getLangraphConfig(sessionId || uuidv4());
447
+ const state = await this.compiledGraph.getState(langraphConfig);
448
+ const suffixes = Object.values(internalNodesSuffix);
449
+ let nodeToBeInvoked = state.next.length > 0 ? state.next[0] : this.startingNodeId!;
450
+ nodeToBeInvoked = nodeToBeInvoked.replace(new RegExp(suffixes.join('|'), 'g'), '');
451
+ const historyStep = this.createTriggerHistoryStep(
452
+ state.values.history,
453
+ nodeToBeInvoked,
454
+ messages.map((m) => m.id!),
455
+ triggerName,
456
+ triggerBody,
457
+ appName,
427
458
  );
459
+
460
+ let res;
461
+ // Resume interruption
462
+ if (state.tasks?.[0]?.interrupts?.length > 0) {
463
+ res = await this.compiledGraph.invoke(
464
+ new Command({
465
+ resume: { memory: memoryUpdate, messages, history: historyStep, sessionId, sessionType },
466
+ }),
467
+ langraphConfig,
468
+ );
469
+ } else {
470
+ res = await this.compiledGraph.invoke(
471
+ { messages, memory: memoryUpdate, history: historyStep, sessionId, sessionType },
472
+ langraphConfig,
473
+ );
474
+ }
475
+ return res;
476
+ } catch (error) {
477
+ logger.error({ message: 'Invoke error', error, sessionId });
478
+ const state = await this.compiledGraph.getState(this.getLangraphConfig(sessionId));
479
+ this.emit(AgentEvents.ERROR, { error: error instanceof Error ? error : new Error(JSON.stringify(error)), state: state.values });
480
+ throw error;
428
481
  }
429
- return res;
430
482
  }
431
483
 
432
484
  /**
@@ -450,7 +502,7 @@ export class Agent {
450
502
  * memory: Memory; // Initial memory state (from your schema defaults)
451
503
  * triggerInvocations: Array<...>; // Empty array - no triggers invoked yet
452
504
  * triggerMetadata: null; // No trigger metadata initially
453
- * history: FlowHistory[]; // Empty array - no flow history yet
505
+ * history: HistoryStep[]; // Empty array - no flow history yet
454
506
  * sessionId: string; // Session identifier (generated or provided)
455
507
  * sessionType: SessionType; // Type of session (TEXT, VOICE, etc.)
456
508
  * }
@@ -479,7 +531,7 @@ export class Agent {
479
531
  * memory: Memory; // Current memory state (your defined memory schema)
480
532
  * triggerInvocations: Array<...>; // Trigger invocation history
481
533
  * triggerMetadata: {...} | null; // Current trigger metadata
482
- * history: FlowHistory[]; // Flow execution history
534
+ * history: HistoryStep[]; // Flow execution history with detailed step information
483
535
  * sessionId: string; // Session identifier
484
536
  * }
485
537
  * }
@@ -10,12 +10,7 @@ export const createLogicalRouter = ({ edges }: { edges: LogicalConditionEdge[] }
10
10
  return async (state: typeof stateAnnotation.State) => {
11
11
  logger.debug(`Evaluating logical conditions for ${edges.length} edges`);
12
12
 
13
- // Separate regular conditions from "else" conditions
14
- const regularEdges = edges.filter(edge => edge.condition.trim() !== 'else');
15
- const elseEdges = edges.filter(edge => edge.condition.trim() === 'else');
16
-
17
- // First, evaluate all regular conditions
18
- for (const edge of regularEdges) {
13
+ for (const edge of edges) {
19
14
  try {
20
15
  // Customer is responsible for providing valid JavaScript syntax
21
16
  // We execute their condition in a sandboxed VM with timeout protection
@@ -58,11 +53,12 @@ export const createLogicalRouter = ({ edges }: { edges: LogicalConditionEdge[] }
58
53
  new Promise((_, reject) => setTimeout(() => reject(new Error('Condition execution timeout')), CONDITION_TIMEOUT)),
59
54
  ]);
60
55
 
61
- if (result === true) {
56
+ if (result) {
62
57
  logger.info(`Condition matched for edge ${edge.source} → ${edge.target}`);
63
58
  return edge.target;
64
59
  }
65
60
 
61
+ logger.debug(`Condition not matched for edge ${edge.source} → ${edge.target}`);
66
62
  } catch (error) {
67
63
  // Provide detailed error information back to the customer
68
64
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -82,17 +78,8 @@ export const createLogicalRouter = ({ edges }: { edges: LogicalConditionEdge[] }
82
78
  }
83
79
  }
84
80
 
85
- // If no regular conditions matched, check for "else" conditions
86
- if (elseEdges.length > 0) {
87
- logger.info(`No regular conditions matched, evaluating ${elseEdges.length} else condition(s)`);
88
- // Return the first "else" condition's target
89
- const elseEdge = elseEdges[0];
90
- logger.info(`Else condition matched for edge ${elseEdge.source} → ${elseEdge.target}`);
91
- return elseEdge.target;
92
- }
93
-
94
81
  // If no conditions matched or all failed, return to the source node
95
- logger.info('No conditions matched');
96
- return null;
82
+ logger.info(`No conditions matched, returning to source: ${edges[0].source}`);
83
+ return edges[0].source;
97
84
  };
98
85
  };
@@ -46,7 +46,7 @@ export const edgeFactory = ({
46
46
  if (edgesBySource.logical.length > 0) {
47
47
  const logicalRouter = createLogicalRouter({ edges: edgesBySource.logical });
48
48
  const result = await logicalRouter(state);
49
- if (result) {
49
+ if (result && result !== edgesBySource.logical[0].source) {
50
50
  return result;
51
51
  } else {
52
52
  logger.debug('No logical conditions matched, continuing to prompt conditions');
@@ -68,9 +68,7 @@ export const edgeFactory = ({
68
68
  }
69
69
 
70
70
  // Fallback: stay at current source node
71
- const source = originalNode?.name || sourceNode;
72
- logger.info(`No conditions matched, returning to source: ${source}`);
73
- return source;
71
+ return sourceNode;
74
72
  };
75
73
  };
76
74
 
@@ -1,29 +1,31 @@
1
1
  import { BaseMessage } from '@langchain/core/messages';
2
- import { FlowHistory } from '../types/Agent.types';
3
- import { createStateAnnotation } from '../types/LangGraph.types';
2
+ import { HistoryStep } from '../types/Agent.types';
3
+ import { State } from '../types/LangGraph.types';
4
4
 
5
5
  export enum AgentEvents {
6
6
  INIT = 'INIT',
7
7
  AI_MESSAGE = 'AI_MESSAGE',
8
8
  TRIGGER_EVENT = 'TRIGGER_EVENT',
9
+ ERROR = 'ERROR',
9
10
  }
10
11
 
11
- // Helper type to get the state type with proper memory typing
12
- type StateWithMemory<Memory> = ReturnType<typeof createStateAnnotation<Memory>>['State'];
13
-
14
12
  export type AgentEventRequestPayloads<Memory> = {
15
13
  [AgentEvents.INIT]: {
16
- state: StateWithMemory<Memory>;
14
+ state: State<Memory>;
17
15
  };
18
16
  [AgentEvents.AI_MESSAGE]: {
19
17
  message: string;
20
- state: StateWithMemory<Memory>;
18
+ state: State<Memory>;
21
19
  };
22
20
  [AgentEvents.TRIGGER_EVENT]: {
23
21
  triggerName: string;
24
22
  triggerBody: any;
25
23
  sessionId?: string;
26
24
  };
25
+ [AgentEvents.ERROR]: {
26
+ error: Error;
27
+ state?: State<Memory>;
28
+ };
27
29
  };
28
30
 
29
31
  export type AgentEventResponsePayloads<Memory> = {
@@ -33,7 +35,8 @@ export type AgentEventResponsePayloads<Memory> = {
33
35
  isQualified: boolean;
34
36
  messages?: BaseMessage[];
35
37
  memory?: Memory;
36
- history?: FlowHistory[];
38
+ history?: HistoryStep[];
37
39
  sessionId?: string;
38
40
  };
41
+ [AgentEvents.ERROR]: void;
39
42
  };
package/src/index.ts CHANGED
@@ -35,7 +35,14 @@ export {
35
35
  KnownTriggerNames,
36
36
  } from './types/Flows.types';
37
37
  export type { Tool, ToolExecuteInput } from './types/Tools.types';
38
- export { FlowHistoryType, FlowHistory, TriggerInvocationHistory, AppActionInvocationHistory, SessionType } from './types/Agent.types';
38
+ export {
39
+ HistoryStepType,
40
+ HistoryStep,
41
+ TriggerHistoryStep,
42
+ AppActionInvocationHistoryStep,
43
+ CustomActionInvocationHistoryStep,
44
+ SessionType,
45
+ } from './types/Agent.types';
39
46
  export type { AgentInvokeParams, MindedSDKConfig } from './types/Agent.types';
40
47
  export type { Environment } from './types/Platform.types';
41
48
  export type { State } from './types/LangGraph.types';
@@ -6,10 +6,11 @@ import { RunnableLike } from '@langchain/core/runnables';
6
6
  import { z } from 'zod';
7
7
  import { LLMProviders } from '../types/LLM.types';
8
8
  import { getAppActionRunnerTool } from '../internalTools/appActionRunnerTool';
9
- import { FlowHistoryType } from '../types/Agent.types';
9
+ import { AppActionInvocationHistoryStep, HistoryStepType } from '../types/Agent.types';
10
10
  import { Agent } from '../agent';
11
11
  import { logger } from '../utils/logger';
12
12
  import { compilePlaybooks } from '../playbooks/playbooks';
13
+ import { createHistoryStep } from '../utils/history';
13
14
 
14
15
  export const addAppToolNode = async ({
15
16
  graph,
@@ -80,7 +81,14 @@ export const addAppToolNode = async ({
80
81
  };
81
82
  return {
82
83
  messages: [AIToolCallMessage, toolCallMessage],
83
- history: [{ type: FlowHistoryType.APP_ACTION_INVOCATION, nodeTitle: node.displayName }],
84
+ history: createHistoryStep<AppActionInvocationHistoryStep>(state.history, {
85
+ type: HistoryStepType.APP_ACTION_NODE,
86
+ nodeId: node.name,
87
+ nodeDisplayName: node.displayName!,
88
+ raw: AIToolCallMessage.tool_calls[0],
89
+ appName: node.appName,
90
+ messageIds: [AIToolCallMessage.id!],
91
+ }),
84
92
  };
85
93
  };
86
94
  graph.addNode(node.name, callback);
@@ -2,13 +2,14 @@ import { interrupt } from '@langchain/langgraph';
2
2
  import { PreCompiledGraph, stateAnnotation } from '../types/LangGraph.types';
3
3
  import { RunnableLike } from '@langchain/core/runnables';
4
4
  import { logger } from '../utils/logger';
5
+ import { internalNodesSuffix } from '../types/Flows.types';
5
6
 
6
7
  type AddHumanInTheLoopNodeParams = {
7
8
  graph: PreCompiledGraph;
8
9
  attachedToNodeName: string;
9
10
  };
10
11
 
11
- export const buildHumanInTheLoopNodeName = (nodeName: string) => `${nodeName}_humanInTheLoop`;
12
+ export const buildHumanInTheLoopNodeName = (nodeName: string) => `${nodeName}${internalNodesSuffix.HUMAN_IN_THE_LOOP}`;
12
13
 
13
14
  export const addHumanInTheLoopNode = async ({ graph, attachedToNodeName }: AddHumanInTheLoopNodeParams) => {
14
15
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
@@ -19,6 +20,6 @@ export const addHumanInTheLoopNode = async ({ graph, attachedToNodeName }: AddHu
19
20
  return value;
20
21
  }
21
22
  };
22
- graph.addNode(`${attachedToNodeName}_humanInTheLoop`, callback);
23
+ graph.addNode(buildHumanInTheLoopNodeName(attachedToNodeName), callback);
23
24
  graph.addEdge(attachedToNodeName as any, buildHumanInTheLoopNodeName(attachedToNodeName) as any);
24
25
  };
@@ -3,19 +3,13 @@ import { PreCompiledGraph } from '../types/LangGraph.types';
3
3
  import { JumpToNode } from '../types/Flows.types';
4
4
  import { logger } from '../utils/logger';
5
5
 
6
- export const addJumpToNode = async ({
7
- graph,
8
- node,
9
- }: {
10
- graph: PreCompiledGraph;
11
- node: JumpToNode;
12
- }) => {
6
+ export const addJumpToNode = async ({ graph, node }: { graph: PreCompiledGraph; node: JumpToNode }) => {
13
7
  const callback: RunnableLike = async () => {
14
- logger.info(`Executing jump node ${node.name} – jumping to ${node.targetNodeId}`);
8
+ logger.info(`Executing jump node ${node.displayName} – jumping to ${node.targetNodeId}`);
15
9
  // No state modifications are necessary; control flow is handled via edges.
16
10
  return;
17
11
  };
18
12
 
19
13
  graph.addNode(node.name, callback);
20
14
  graph.addEdge(node.name as any, node.targetNodeId as any);
21
- };
15
+ };
@@ -7,12 +7,13 @@ import { SystemMessage, AIMessage, ToolMessage } from '@langchain/core/messages'
7
7
  import { Tool } from '../types/Tools.types';
8
8
  import { tool as langchainTool } from '@langchain/core/tools';
9
9
  import { AgentEventRequestPayloads, AgentEvents } from '../events/AgentEvents';
10
- import { EmitSignature } from '../types/Agent.types';
10
+ import { EmitSignature, HistoryStepType, HistoryStep } from '../types/Agent.types';
11
11
  import { createLlmInstance } from '../llm/createLlmInstance';
12
12
  import extractToolStateResponse from '../utils/extractStateMemoryResponse';
13
13
  import { Agent } from '../agent';
14
14
  import { logger } from '../utils/logger';
15
15
  import { compilePlaybooks } from '../playbooks/playbooks';
16
+ import { createHistoryStep } from '../utils/history';
16
17
 
17
18
  type AddPromptNodeParams = {
18
19
  graph: PreCompiledGraph;
@@ -25,7 +26,7 @@ type AddPromptNodeParams = {
25
26
 
26
27
  export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: AddPromptNodeParams) => {
27
28
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
28
- logger.info(`Executing prompt node ${node.name}`);
29
+ logger.info(`Executing prompt node ${node.displayName}`);
29
30
  const llmToUse = node.llmConfig ? createLlmInstance(node.llmConfig) : llm;
30
31
 
31
32
  const globalTools = tools
@@ -102,6 +103,13 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
102
103
  }
103
104
 
104
105
  return {
106
+ history: createHistoryStep<HistoryStep>(state.history, {
107
+ type: HistoryStepType.PROMPT_NODE,
108
+ nodeId: node.name,
109
+ nodeDisplayName: node.displayName,
110
+ raw: result.content,
111
+ messageIds: [result.id!],
112
+ }),
105
113
  messages: [result],
106
114
  };
107
115
  };
@@ -28,7 +28,7 @@ export const addToolNode = async ({
28
28
  throw new Error(`Tool not found: ${toolNode.toolName} in node ${node.name}`);
29
29
  }
30
30
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
31
- logger.info(`Executing tool node ${toolNode.name}`);
31
+ logger.info(`Executing tool node ${toolNode.displayName}`);
32
32
 
33
33
  const tool = langchainTool(() => {}, {
34
34
  name: matchedTool.name,
@@ -2,7 +2,7 @@ import { PreCompiledGraph, stateAnnotation } from '../types/LangGraph.types';
2
2
  import { RunnableLike } from '@langchain/core/runnables';
3
3
  import { Tool } from '../types/Tools.types';
4
4
  import { LLMProviders } from '../types/LLM.types';
5
- import { ToolNode } from '../types/Flows.types';
5
+ import { internalNodesSuffix, ToolNode } from '../types/Flows.types';
6
6
  import { tool as langchainTool } from '@langchain/core/tools';
7
7
  import { ToolMessage } from '@langchain/core/messages';
8
8
  import { z } from 'zod';
@@ -19,7 +19,7 @@ type AddToolRunNodeParams = {
19
19
  agent: Agent;
20
20
  };
21
21
 
22
- export const buildToolRunNodeName = (nodeName: string) => `${nodeName}_toolRun`;
22
+ export const buildToolRunNodeName = (nodeName: string) => `${nodeName}${internalNodesSuffix.TOOL_RUN}`;
23
23
 
24
24
  export const addToolRunNode = async ({ graph, tools, toolNode, attachedToNodeName, agent }: AddToolRunNodeParams) => {
25
25
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
@@ -5,7 +5,7 @@ import { logger } from '../utils/logger';
5
5
 
6
6
  export const addTriggerNode = async ({ graph, node }: { graph: PreCompiledGraph; node: TriggerNode }) => {
7
7
  const callback: RunnableLike = async () => {
8
- logger.info(`Executing trigger node ${node.name}`);
8
+ logger.info(`Executing trigger node ${node.displayName}`);
9
9
  return;
10
10
  };
11
11
 
@@ -30,26 +30,40 @@ export interface AgentInvokeParams {
30
30
  appName?: string;
31
31
  }
32
32
 
33
- export enum FlowHistoryType {
34
- TRIGGER_INVOCATION = 'triggerInvocation',
35
- APP_ACTION_INVOCATION = 'appActionInvocation',
33
+ export enum HistoryStepType {
34
+ APP_TRIGGER_NODE = 'appTriggerNode',
35
+ TRIGGER_NODE = 'triggerNode',
36
+ APP_ACTION_NODE = 'appActionNode',
37
+ CUSTOM_ACTION_NODE = 'customActionNode',
38
+ PROMPT_NODE = 'promptNode',
36
39
  }
37
40
 
38
- export interface FlowHistory {
39
- type: FlowHistoryType;
41
+ export interface HistoryStep {
42
+ type: HistoryStepType;
43
+ step: number;
44
+ raw: any;
45
+ nodeId: string;
46
+ nodeDisplayName: string;
47
+ messageIds?: string[];
40
48
  }
41
49
 
42
- export interface TriggerInvocationHistory extends FlowHistory {
43
- type: FlowHistoryType.TRIGGER_INVOCATION;
44
- appName?: string;
45
- triggerName: string;
46
- triggerBody: any;
50
+ export interface AppTrigggerHistoryStep extends HistoryStep {
51
+ type: HistoryStepType.APP_TRIGGER_NODE;
52
+ appName: string;
47
53
  }
48
54
 
49
- export interface AppActionInvocationHistory extends FlowHistory {
50
- type: FlowHistoryType.APP_ACTION_INVOCATION;
51
- nodeTitle: string;
52
- };
55
+ export interface TriggerHistoryStep extends HistoryStep {
56
+ type: HistoryStepType.TRIGGER_NODE;
57
+ }
58
+
59
+ export interface AppActionInvocationHistoryStep extends HistoryStep {
60
+ type: HistoryStepType.APP_ACTION_NODE;
61
+ appName: string;
62
+ }
63
+
64
+ export interface CustomActionInvocationHistoryStep extends HistoryStep {
65
+ type: HistoryStepType.CUSTOM_ACTION_NODE;
66
+ }
53
67
 
54
68
  export enum SessionType {
55
69
  VOICE = 'voice',
@@ -25,7 +25,7 @@ export interface BaseNode {
25
25
  position?: Position;
26
26
  humanInTheLoop?: boolean;
27
27
  canStayOnNode?: boolean;
28
- displayName?: string;
28
+ displayName: string;
29
29
  }
30
30
 
31
31
  export enum TriggerType {
@@ -177,3 +177,8 @@ export enum KnownTriggerNames {
177
177
  DASHBOARD_MESSAGE = 'dashboard_message',
178
178
  VOICE_MESSAGE = 'voice_message',
179
179
  }
180
+
181
+ export enum internalNodesSuffix {
182
+ HUMAN_IN_THE_LOOP = '_humanInTheLoop',
183
+ TOOL_RUN = '_toolRun',
184
+ }
@@ -1,6 +1,6 @@
1
1
  import { BaseMessage } from '@langchain/core/messages';
2
2
  import { Annotation, CompiledStateGraph, StateGraph } from '@langchain/langgraph';
3
- import { FlowHistory, SessionType, TriggerInvocationHistory } from './Agent.types';
3
+ import { HistoryStep, SessionType } from './Agent.types';
4
4
 
5
5
  export const createStateAnnotation = <Memory = any>() =>
6
6
  Annotation.Root({
@@ -25,15 +25,7 @@ export const createStateAnnotation = <Memory = any>() =>
25
25
  default: () => ({} as Memory),
26
26
  reducer: (a, b) => ({ ...a, ...b }),
27
27
  }),
28
- triggerInvocations: Annotation<Array<TriggerInvocationHistory>>({
29
- default: () => [],
30
- reducer: (a, b) => a.concat(b),
31
- }),
32
- triggerMetadata: Annotation<{
33
- name: string;
34
- triggerBody: any;
35
- } | null>,
36
- history: Annotation<Array<FlowHistory>>({
28
+ history: Annotation<Array<HistoryStep>>({
37
29
  default: () => [],
38
30
  reducer: (a, b) => a.concat(b),
39
31
  }),
@@ -0,0 +1,9 @@
1
+ import { HistoryStep } from '../types/Agent.types';
2
+
3
+ export const createHistoryStep = <T extends HistoryStep>(currentHistory: HistoryStep[], stepPayload: Omit<T, 'step'>): HistoryStep => {
4
+ const lastHistoryStep = currentHistory?.[currentHistory?.length - 1];
5
+ return {
6
+ ...stepPayload,
7
+ step: lastHistoryStep?.step + 1 || 0,
8
+ } as HistoryStep;
9
+ };