@minded-ai/mindedjs 1.0.102 → 1.0.103-beta-1

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 (170) hide show
  1. package/dist/agent.d.ts +4 -1
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +76 -30
  4. package/dist/agent.js.map +1 -1
  5. package/dist/checkpointer/checkpointSaverFactory.js +1 -1
  6. package/dist/checkpointer/checkpointSaverFactory.js.map +1 -1
  7. package/dist/cli/index.js +12 -12
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/edges/createDirectEdge.d.ts +1 -2
  10. package/dist/edges/createDirectEdge.d.ts.map +1 -1
  11. package/dist/edges/createDirectEdge.js +2 -6
  12. package/dist/edges/createDirectEdge.js.map +1 -1
  13. package/dist/edges/createLogicalRouter.d.ts.map +1 -1
  14. package/dist/edges/createLogicalRouter.js +6 -23
  15. package/dist/edges/createLogicalRouter.js.map +1 -1
  16. package/dist/edges/createPromptRouter.d.ts.map +1 -1
  17. package/dist/edges/createPromptRouter.js +6 -12
  18. package/dist/edges/createPromptRouter.js.map +1 -1
  19. package/dist/edges/edgeFactory.d.ts.map +1 -1
  20. package/dist/edges/edgeFactory.js +3 -8
  21. package/dist/edges/edgeFactory.js.map +1 -1
  22. package/dist/index.d.ts +0 -4
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -6
  25. package/dist/index.js.map +1 -1
  26. package/dist/interrupts/BaseInterruptSessionManager.d.ts +51 -0
  27. package/dist/interrupts/BaseInterruptSessionManager.d.ts.map +1 -0
  28. package/dist/interrupts/BaseInterruptSessionManager.js +39 -0
  29. package/dist/interrupts/BaseInterruptSessionManager.js.map +1 -0
  30. package/dist/interrupts/InterruptSessionManager.types.d.ts +36 -0
  31. package/dist/interrupts/InterruptSessionManager.types.d.ts.map +1 -0
  32. package/dist/interrupts/InterruptSessionManager.types.js +40 -0
  33. package/dist/interrupts/InterruptSessionManager.types.js.map +1 -0
  34. package/dist/interrupts/MemoryInterruptSessionManager.d.ts +14 -0
  35. package/dist/interrupts/MemoryInterruptSessionManager.d.ts.map +1 -0
  36. package/dist/interrupts/MemoryInterruptSessionManager.js +56 -0
  37. package/dist/interrupts/MemoryInterruptSessionManager.js.map +1 -0
  38. package/dist/interrupts/MindedInterruptSessionManager.d.ts +13 -0
  39. package/dist/interrupts/MindedInterruptSessionManager.d.ts.map +1 -0
  40. package/dist/interrupts/MindedInterruptSessionManager.js +156 -0
  41. package/dist/interrupts/MindedInterruptSessionManager.js.map +1 -0
  42. package/dist/interrupts/interruptSessionManagerFactory.d.ts +3 -0
  43. package/dist/interrupts/interruptSessionManagerFactory.d.ts.map +1 -0
  44. package/dist/interrupts/interruptSessionManagerFactory.js +56 -0
  45. package/dist/interrupts/interruptSessionManagerFactory.js.map +1 -0
  46. package/dist/llm/createLlmInstance.d.ts +1 -1
  47. package/dist/llm/createLlmInstance.d.ts.map +1 -1
  48. package/dist/llm/createLlmInstance.js +1 -18
  49. package/dist/llm/createLlmInstance.js.map +1 -1
  50. package/dist/nodes/addAppToolNode.d.ts.map +1 -1
  51. package/dist/nodes/addAppToolNode.js +4 -5
  52. package/dist/nodes/addAppToolNode.js.map +1 -1
  53. package/dist/nodes/addHumanInTheLoopNode.d.ts.map +1 -1
  54. package/dist/nodes/addHumanInTheLoopNode.js +3 -2
  55. package/dist/nodes/addHumanInTheLoopNode.js.map +1 -1
  56. package/dist/nodes/addJumpToNode.d.ts.map +1 -1
  57. package/dist/nodes/addJumpToNode.js +1 -2
  58. package/dist/nodes/addJumpToNode.js.map +1 -1
  59. package/dist/nodes/addJunctionNode.d.ts.map +1 -1
  60. package/dist/nodes/addJunctionNode.js +0 -1
  61. package/dist/nodes/addJunctionNode.js.map +1 -1
  62. package/dist/nodes/addPromptNode.d.ts.map +1 -1
  63. package/dist/nodes/addPromptNode.js +61 -7
  64. package/dist/nodes/addPromptNode.js.map +1 -1
  65. package/dist/nodes/addToolNode.js +4 -2
  66. package/dist/nodes/addToolNode.js.map +1 -1
  67. package/dist/nodes/addToolRunNode.d.ts.map +1 -1
  68. package/dist/nodes/addToolRunNode.js +2 -2
  69. package/dist/nodes/addToolRunNode.js.map +1 -1
  70. package/dist/nodes/addTriggerNode.d.ts.map +1 -1
  71. package/dist/nodes/addTriggerNode.js +1 -2
  72. package/dist/nodes/addTriggerNode.js.map +1 -1
  73. package/dist/nodes/nodeFactory.d.ts.map +1 -1
  74. package/dist/nodes/nodeFactory.js +0 -4
  75. package/dist/nodes/nodeFactory.js.map +1 -1
  76. package/dist/platform/mindedChatOpenAI.d.ts +5 -0
  77. package/dist/platform/mindedChatOpenAI.d.ts.map +1 -0
  78. package/dist/platform/{models/mindedChatOpenAI.js → mindedChatOpenAI.js} +1 -10
  79. package/dist/platform/mindedChatOpenAI.js.map +1 -0
  80. package/dist/platform/mindedConnection.d.ts.map +1 -1
  81. package/dist/platform/mindedConnection.js +12 -12
  82. package/dist/platform/mindedConnection.js.map +1 -1
  83. package/dist/platform/mindedConnectionTypes.d.ts +151 -1
  84. package/dist/platform/mindedConnectionTypes.d.ts.map +1 -1
  85. package/dist/platform/mindedConnectionTypes.js +9 -0
  86. package/dist/platform/mindedConnectionTypes.js.map +1 -1
  87. package/dist/playbooks/playbooks.js +4 -4
  88. package/dist/playbooks/playbooks.js.map +1 -1
  89. package/dist/types/Agent.types.d.ts +2 -0
  90. package/dist/types/Agent.types.d.ts.map +1 -1
  91. package/dist/types/Agent.types.js.map +1 -1
  92. package/dist/types/Flows.types.d.ts +3 -18
  93. package/dist/types/Flows.types.d.ts.map +1 -1
  94. package/dist/types/Flows.types.js +0 -2
  95. package/dist/types/Flows.types.js.map +1 -1
  96. package/dist/types/LLM.types.d.ts.map +1 -1
  97. package/dist/types/LLM.types.js +1 -1
  98. package/dist/types/LLM.types.js.map +1 -1
  99. package/dist/types/LangGraph.types.d.ts +2 -4
  100. package/dist/types/LangGraph.types.d.ts.map +1 -1
  101. package/dist/types/LangGraph.types.js +2 -5
  102. package/dist/types/LangGraph.types.js.map +1 -1
  103. package/dist/utils/logger.d.ts.map +1 -1
  104. package/dist/utils/logger.js +2 -1
  105. package/dist/utils/logger.js.map +1 -1
  106. package/dist/voice/voiceSession.d.ts.map +1 -1
  107. package/dist/voice/voiceSession.js +17 -16
  108. package/dist/voice/voiceSession.js.map +1 -1
  109. package/docs/SUMMARY.md +0 -1
  110. package/docs/getting-started/installation.md +0 -42
  111. package/docs/low-code-editor/nodes.md +0 -27
  112. package/docs/low-code-editor/tools.md +0 -32
  113. package/package.json +2 -3
  114. package/src/agent.ts +93 -32
  115. package/src/checkpointer/checkpointSaverFactory.ts +1 -1
  116. package/src/cli/index.ts +12 -12
  117. package/src/edges/createDirectEdge.ts +2 -7
  118. package/src/edges/createLogicalRouter.ts +6 -23
  119. package/src/edges/createPromptRouter.ts +6 -13
  120. package/src/edges/edgeFactory.ts +4 -20
  121. package/src/index.ts +0 -6
  122. package/src/interrupts/BaseInterruptSessionManager.ts +94 -0
  123. package/src/interrupts/MemoryInterruptSessionManager.ts +57 -0
  124. package/src/interrupts/MindedInterruptSessionManager.ts +155 -0
  125. package/src/interrupts/interruptSessionManagerFactory.ts +20 -0
  126. package/src/llm/createLlmInstance.ts +2 -25
  127. package/src/nodes/addAppToolNode.ts +4 -5
  128. package/src/nodes/addHumanInTheLoopNode.ts +3 -3
  129. package/src/nodes/addJumpToNode.ts +1 -2
  130. package/src/nodes/addJunctionNode.ts +0 -1
  131. package/src/nodes/addPromptNode.ts +65 -10
  132. package/src/nodes/addToolNode.ts +4 -4
  133. package/src/nodes/addToolRunNode.ts +2 -4
  134. package/src/nodes/addTriggerNode.ts +1 -2
  135. package/src/nodes/nodeFactory.ts +1 -5
  136. package/src/platform/mindedChatOpenAI.ts +19 -0
  137. package/src/platform/mindedConnection.ts +15 -25
  138. package/src/platform/mindedConnectionTypes.ts +188 -1
  139. package/src/playbooks/playbooks.ts +4 -4
  140. package/src/types/Agent.types.ts +2 -0
  141. package/src/types/Flows.types.ts +1 -17
  142. package/src/types/LLM.types.ts +5 -5
  143. package/src/types/LangGraph.types.ts +2 -5
  144. package/src/utils/logger.ts +2 -1
  145. package/src/voice/voiceSession.ts +17 -16
  146. package/dist/browserTask/executeBrowserTask.d.ts +0 -12
  147. package/dist/browserTask/executeBrowserTask.d.ts.map +0 -1
  148. package/dist/browserTask/executeBrowserTask.js +0 -181
  149. package/dist/browserTask/executeBrowserTask.js.map +0 -1
  150. package/dist/nodes/addBrowserTaskNode.d.ts +0 -13
  151. package/dist/nodes/addBrowserTaskNode.d.ts.map +0 -1
  152. package/dist/nodes/addBrowserTaskNode.js +0 -230
  153. package/dist/nodes/addBrowserTaskNode.js.map +0 -1
  154. package/dist/nodes/addBrowserTaskRunNode.d.ts +0 -13
  155. package/dist/nodes/addBrowserTaskRunNode.d.ts.map +0 -1
  156. package/dist/nodes/addBrowserTaskRunNode.js +0 -126
  157. package/dist/nodes/addBrowserTaskRunNode.js.map +0 -1
  158. package/dist/platform/models/mindedChatOpenAI.d.ts +0 -20
  159. package/dist/platform/models/mindedChatOpenAI.d.ts.map +0 -1
  160. package/dist/platform/models/mindedChatOpenAI.js.map +0 -1
  161. package/dist/platform/models/parallelWrapper.d.ts +0 -17
  162. package/dist/platform/models/parallelWrapper.d.ts.map +0 -1
  163. package/dist/platform/models/parallelWrapper.js +0 -105
  164. package/dist/platform/models/parallelWrapper.js.map +0 -1
  165. package/docs/platform/parallel-llm.md +0 -242
  166. package/src/browserTask/executeBrowserTask.ts +0 -213
  167. package/src/nodes/addBrowserTaskNode.ts +0 -229
  168. package/src/nodes/addBrowserTaskRunNode.ts +0 -142
  169. package/src/platform/models/mindedChatOpenAI.ts +0 -49
  170. package/src/platform/models/parallelWrapper.ts +0 -141
@@ -0,0 +1,94 @@
1
+ import { State } from '../types/LangGraph.types';
2
+ import { GraphInterrupt } from '@langchain/langgraph';
3
+ import { logger } from '../utils/logger';
4
+
5
+ export enum InterruptType {
6
+ NEW_TRIGGERS = 'NEW_TRIGGERS',
7
+ HUMAN_IN_THE_LOOP = 'HUMAN_IN_THE_LOOP',
8
+ }
9
+
10
+ export interface QueuedMessage {
11
+ triggerBody: any;
12
+ triggerName: string;
13
+ appName?: string;
14
+ }
15
+
16
+ // export interface UpdateStateObject {
17
+ // memory: any;
18
+ // messages: any[];
19
+ // history: any[];
20
+ // sessionId: string;
21
+ // sessionType: SessionType;
22
+ // }
23
+ export interface InterruptPayload {
24
+ type: InterruptType.NEW_TRIGGERS;
25
+ updateStateObject?: Partial<State>;
26
+ id?: string;
27
+ }
28
+
29
+ export interface InterruptSessionManager {
30
+ isProcessed(sessionId: string): boolean | Promise<boolean>;
31
+ /**
32
+ * Atomically attempts to acquire a lock for the given session.
33
+ * This method should only succeed if the session is not already being processed.
34
+ *
35
+ * @param sessionId - The session ID to lock
36
+ * @returns true if the lock was successfully acquired, false if the session is already locked
37
+ */
38
+ lock(sessionId: string): boolean | Promise<boolean>;
39
+ release(sessionId: string): void | Promise<void>;
40
+ enqueueMessage(sessionId: string, message: QueuedMessage): void | Promise<void>;
41
+ dequeueAll(sessionId: string): QueuedMessage[] | Promise<QueuedMessage[]>;
42
+ dequeue(sessionId: string): QueuedMessage | null | Promise<QueuedMessage | null>;
43
+ checkQueueAndInterrupt(sessionId: string, updateStateObject?: Partial<State>): Promise<boolean>;
44
+ }
45
+
46
+ export abstract class BaseInterruptSessionManager implements InterruptSessionManager {
47
+ // Abstract methods that subclasses must implement for queue management
48
+ abstract isProcessed(sessionId: string): boolean | Promise<boolean>;
49
+ /**
50
+ * Atomically attempts to acquire a lock for the given session.
51
+ * This method should only succeed if the session is not already being processed.
52
+ * Implementations must ensure this operation is atomic to prevent race conditions.
53
+ *
54
+ * @param sessionId - The session ID to lock
55
+ * @returns true if the lock was successfully acquired, false if the session is already locked
56
+ */
57
+ abstract lock(sessionId: string): boolean | Promise<boolean>;
58
+ abstract release(sessionId: string): void | Promise<void>;
59
+ abstract enqueueMessage(sessionId: string, message: QueuedMessage): void | Promise<void>;
60
+ abstract dequeueAll(sessionId: string): QueuedMessage[] | Promise<QueuedMessage[]>;
61
+ abstract dequeue(sessionId: string): QueuedMessage | null | Promise<QueuedMessage | null>;
62
+
63
+ // Abstract method to check if queue has messages - this is the only queue-specific part
64
+ protected abstract hasQueuedMessages(sessionId: string): boolean | Promise<boolean>;
65
+ protected abstract getQueuedMessages(sessionId: string): QueuedMessage[] | Promise<QueuedMessage[]>;
66
+
67
+ // Common implementation of checkQueueAndInterrupt
68
+ async checkQueueAndInterrupt(sessionId: string, updateStateObject?: Partial<State>): Promise<boolean> {
69
+ if (await this.hasQueuedMessages(sessionId)) {
70
+ logger.trace({ message: 'graph has queued messagess, interrupting graph', sessionId });
71
+
72
+ // Interrupt the graph with NEW_TRIGGERS flag and optional updateStateObject
73
+ const interruptPayload: InterruptPayload = { type: InterruptType.NEW_TRIGGERS };
74
+ if (updateStateObject) {
75
+ interruptPayload.updateStateObject = {
76
+ messages: updateStateObject.messages,
77
+ memory: updateStateObject.memory,
78
+ history: updateStateObject.history,
79
+ sessionId: updateStateObject.sessionId,
80
+ sessionType: updateStateObject.sessionType,
81
+ };
82
+ }
83
+
84
+ throw new GraphInterrupt([
85
+ {
86
+ value: interruptPayload,
87
+ when: 'during',
88
+ resumable: true,
89
+ },
90
+ ]);
91
+ }
92
+ return false;
93
+ }
94
+ }
@@ -0,0 +1,57 @@
1
+ import { BaseInterruptSessionManager, QueuedMessage } from './BaseInterruptSessionManager';
2
+
3
+ export class MemoryInterruptSessionManager extends BaseInterruptSessionManager {
4
+ private sessionProcessing: Map<string, boolean> = new Map();
5
+ private sessionMessageQueues: Map<string, QueuedMessage[]> = new Map();
6
+
7
+ isProcessed(sessionId: string): boolean {
8
+ return this.sessionProcessing.get(sessionId) || false;
9
+ }
10
+
11
+ lock(sessionId: string): boolean {
12
+ const isCurrentlyProcessed = this.sessionProcessing.get(sessionId) || false;
13
+ if (isCurrentlyProcessed) {
14
+ return false; // Could not acquire lock
15
+ }
16
+ this.sessionProcessing.set(sessionId, true);
17
+ return true; // Successfully acquired lock
18
+ }
19
+
20
+ release(sessionId: string): void {
21
+ this.sessionProcessing.delete(sessionId);
22
+ }
23
+
24
+ enqueueMessage(sessionId: string, message: QueuedMessage): void {
25
+ if (!this.sessionMessageQueues.has(sessionId)) {
26
+ this.sessionMessageQueues.set(sessionId, []);
27
+ }
28
+ this.sessionMessageQueues.get(sessionId)!.push(message);
29
+ }
30
+
31
+ dequeueAll(sessionId: string): QueuedMessage[] {
32
+ const messages = this.sessionMessageQueues.get(sessionId) || [];
33
+ const result = [...messages];
34
+ this.sessionMessageQueues.set(sessionId, []);
35
+ return result;
36
+ }
37
+
38
+ dequeue(sessionId: string): QueuedMessage | null {
39
+ const messages = this.sessionMessageQueues.get(sessionId) || [];
40
+ if (messages.length === 0) {
41
+ return null;
42
+ }
43
+ const firstMessage = messages.shift()!;
44
+ this.sessionMessageQueues.set(sessionId, messages);
45
+ return firstMessage;
46
+ }
47
+
48
+ // Implementation of abstract methods from BaseInterruptSessionManager
49
+ protected hasQueuedMessages(sessionId: string): boolean {
50
+ const queue = this.sessionMessageQueues.get(sessionId) || [];
51
+ return queue.length > 0;
52
+ }
53
+
54
+ protected getQueuedMessages(sessionId: string): QueuedMessage[] {
55
+ return this.sessionMessageQueues.get(sessionId) || [];
56
+ }
57
+ }
@@ -0,0 +1,155 @@
1
+ import { BaseInterruptSessionManager, QueuedMessage } from './BaseInterruptSessionManager';
2
+ import * as mindedConnection from '../platform/mindedConnection';
3
+ import {
4
+ mindedConnectionSocketMessageType,
5
+ InterruptSessionIsProcessedRequest,
6
+ InterruptSessionIsProcessedResponse,
7
+ InterruptSessionLockRequest,
8
+ InterruptSessionLockResponse,
9
+ InterruptSessionReleaseRequest,
10
+ InterruptSessionReleaseResponse,
11
+ InterruptSessionEnqueueRequest,
12
+ InterruptSessionEnqueueResponse,
13
+ InterruptSessionDequeueAllRequest,
14
+ InterruptSessionDequeueAllResponse,
15
+ InterruptSessionDequeueRequest,
16
+ InterruptSessionDequeueResponse,
17
+ InterruptSessionHasMessagesRequest,
18
+ InterruptSessionHasMessagesResponse,
19
+ InterruptSessionGetMessagesRequest,
20
+ InterruptSessionGetMessagesResponse,
21
+ } from '../platform/mindedConnectionTypes';
22
+
23
+ export class MindedInterruptSessionManager extends BaseInterruptSessionManager {
24
+ constructor() {
25
+ super();
26
+ }
27
+
28
+ async isProcessed(sessionId: string): Promise<boolean> {
29
+ try {
30
+ const response = await mindedConnection.awaitEmit<InterruptSessionIsProcessedRequest, InterruptSessionIsProcessedResponse>(
31
+ mindedConnectionSocketMessageType.INTERRUPT_SESSION_IS_PROCESSED,
32
+ {
33
+ type: mindedConnectionSocketMessageType.INTERRUPT_SESSION_IS_PROCESSED,
34
+ sessionId,
35
+ },
36
+ );
37
+ return response.isProcessed ?? false;
38
+ } catch (error) {
39
+ console.error('Error checking if session is processed:', error);
40
+ return false;
41
+ }
42
+ }
43
+
44
+ async lock(sessionId: string): Promise<boolean> {
45
+ try {
46
+ const response = await mindedConnection.awaitEmit<InterruptSessionLockRequest, InterruptSessionLockResponse>(
47
+ mindedConnectionSocketMessageType.INTERRUPT_SESSION_LOCK,
48
+ {
49
+ type: mindedConnectionSocketMessageType.INTERRUPT_SESSION_LOCK,
50
+ sessionId,
51
+ },
52
+ );
53
+ return response.lockAcquired ?? false;
54
+ } catch (error) {
55
+ console.error('Error locking session:', error);
56
+ return false;
57
+ }
58
+ }
59
+
60
+ async release(sessionId: string): Promise<void> {
61
+ try {
62
+ await mindedConnection.awaitEmit<InterruptSessionReleaseRequest, InterruptSessionReleaseResponse>(
63
+ mindedConnectionSocketMessageType.INTERRUPT_SESSION_RELEASE,
64
+ {
65
+ type: mindedConnectionSocketMessageType.INTERRUPT_SESSION_RELEASE,
66
+ sessionId,
67
+ },
68
+ );
69
+ } catch (error) {
70
+ console.error('Error releasing session:', error);
71
+ throw error;
72
+ }
73
+ }
74
+
75
+ async enqueueMessage(sessionId: string, message: QueuedMessage): Promise<void> {
76
+ try {
77
+ await mindedConnection.awaitEmit<InterruptSessionEnqueueRequest, InterruptSessionEnqueueResponse>(
78
+ mindedConnectionSocketMessageType.INTERRUPT_SESSION_ENQUEUE,
79
+ {
80
+ type: mindedConnectionSocketMessageType.INTERRUPT_SESSION_ENQUEUE,
81
+ sessionId,
82
+ message,
83
+ },
84
+ );
85
+ } catch (error) {
86
+ console.error('Error enqueuing message:', error);
87
+ throw error;
88
+ }
89
+ }
90
+
91
+ async dequeueAll(sessionId: string): Promise<QueuedMessage[]> {
92
+ try {
93
+ const response = await mindedConnection.awaitEmit<InterruptSessionDequeueAllRequest, InterruptSessionDequeueAllResponse>(
94
+ mindedConnectionSocketMessageType.INTERRUPT_SESSION_DEQUEUE_ALL,
95
+ {
96
+ type: mindedConnectionSocketMessageType.INTERRUPT_SESSION_DEQUEUE_ALL,
97
+ sessionId,
98
+ },
99
+ );
100
+ return response.messages ?? [];
101
+ } catch (error) {
102
+ console.error('Error dequeuing all messages:', error);
103
+ return [];
104
+ }
105
+ }
106
+
107
+ async dequeue(sessionId: string): Promise<QueuedMessage | null> {
108
+ try {
109
+ const response = await mindedConnection.awaitEmit<InterruptSessionDequeueRequest, InterruptSessionDequeueResponse>(
110
+ mindedConnectionSocketMessageType.INTERRUPT_SESSION_DEQUEUE,
111
+ {
112
+ type: mindedConnectionSocketMessageType.INTERRUPT_SESSION_DEQUEUE,
113
+ sessionId,
114
+ },
115
+ );
116
+ return response.message ?? null;
117
+ } catch (error) {
118
+ console.error('Error dequeuing message:', error);
119
+ return null;
120
+ }
121
+ }
122
+
123
+ // Implementation of abstract methods from BaseInterruptSessionManager
124
+ protected async hasQueuedMessages(sessionId: string): Promise<boolean> {
125
+ try {
126
+ const response = await mindedConnection.awaitEmit<InterruptSessionHasMessagesRequest, InterruptSessionHasMessagesResponse>(
127
+ mindedConnectionSocketMessageType.INTERRUPT_SESSION_HAS_MESSAGES,
128
+ {
129
+ type: mindedConnectionSocketMessageType.INTERRUPT_SESSION_HAS_MESSAGES,
130
+ sessionId,
131
+ },
132
+ );
133
+ return response.hasMessages ?? false;
134
+ } catch (error) {
135
+ console.error('Error checking if session has messages:', error);
136
+ return false;
137
+ }
138
+ }
139
+
140
+ protected async getQueuedMessages(sessionId: string): Promise<QueuedMessage[]> {
141
+ try {
142
+ const response = await mindedConnection.awaitEmit<InterruptSessionGetMessagesRequest, InterruptSessionGetMessagesResponse>(
143
+ mindedConnectionSocketMessageType.INTERRUPT_SESSION_GET_MESSAGES,
144
+ {
145
+ type: mindedConnectionSocketMessageType.INTERRUPT_SESSION_GET_MESSAGES,
146
+ sessionId,
147
+ },
148
+ );
149
+ return response.messages ?? [];
150
+ } catch (error) {
151
+ console.error('Error getting queued messages:', error);
152
+ return [];
153
+ }
154
+ }
155
+ }
@@ -0,0 +1,20 @@
1
+ import { InterruptSessionManager } from './BaseInterruptSessionManager';
2
+ import { MemoryInterruptSessionManager } from './MemoryInterruptSessionManager';
3
+ import { MindedInterruptSessionManager } from './MindedInterruptSessionManager';
4
+ import * as mindedConnection from '../platform/mindedConnection';
5
+ import { getConfig } from '../platform/config';
6
+ import { logger } from '../utils/logger';
7
+
8
+ export function createInterruptSessionManager(): InterruptSessionManager {
9
+ const { runLocally } = getConfig();
10
+ if (runLocally) {
11
+ logger.info({ message: 'Using memory interrupt session manager' });
12
+ return new MemoryInterruptSessionManager();
13
+ } else {
14
+ if (!mindedConnection.isConnected()) {
15
+ throw new Error('MindedConnection is required for platform interrupt session manager');
16
+ }
17
+ logger.info({ message: 'Using Minded interrupt session manager' });
18
+ return new MindedInterruptSessionManager();
19
+ }
20
+ }
@@ -1,5 +1,4 @@
1
- import { LLMConfig, LLMProviders, LLMProvider } from '../types/LLM.types';
2
- import { createParallelWrapper, BaseParallelChatFields } from '../platform/models/parallelWrapper';
1
+ import { LLMConfig, LLMProviders, LLMProvider } from "../types/LLM.types";
3
2
 
4
3
  export const createLlmInstance = (llmConfig: LLMConfig) => {
5
4
  const { name, properties } = llmConfig;
@@ -7,27 +6,5 @@ export const createLlmInstance = (llmConfig: LLMConfig) => {
7
6
  if (!LLMClass) {
8
7
  throw new Error(`Unsupported LLM provider: ${name}`);
9
8
  }
10
-
11
- // Create the base LLM instance
12
- const llmInstance = new LLMClass(properties);
13
-
14
- // Check if parallel configuration is present
15
- const hasParallelConfig = properties.numParallelRequests && properties.numParallelRequests > 1;
16
-
17
- // For MindedChatOpenAI, parallel functionality is handled on the backend
18
- if (name === 'MindedChatOpenAI') {
19
- return llmInstance;
20
- }
21
-
22
- // For other LLM providers, apply client-side parallel wrapper if configured
23
- if (hasParallelConfig) {
24
- const parallelOptions: BaseParallelChatFields = {
25
- numParallelRequests: properties.numParallelRequests,
26
- logTimings: properties.logTimings,
27
- };
28
-
29
- return createParallelWrapper(llmInstance, parallelOptions);
30
- }
31
-
32
- return llmInstance;
9
+ return new LLMClass(properties);
33
10
  };
@@ -26,14 +26,14 @@ export const addAppToolNode = async ({
26
26
  const cleanedParameters = Object.fromEntries(Object.entries(node.parameters || {}).filter(([, value]) => value !== ''));
27
27
  const appRunnerTool = getAppActionRunnerTool(node.displayName!);
28
28
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
29
- logger.debug({ msg: `[Node] Executing tool node`, node: appRunnerTool.name });
29
+ logger.info({ message: `Executing tool node ${appRunnerTool.name}` });
30
30
 
31
31
  const executeWrapper = async (input: z.infer<typeof appRunnerTool.input>) => {
32
32
  try {
33
33
  const response = await appRunnerTool.execute({ input, state, agent });
34
34
  return response || {};
35
35
  } catch (error) {
36
- logger.error({ msg: `[Node] Error executing tool`, error, node: node.name });
36
+ logger.error({ msg: 'Error executing tool', error });
37
37
  throw error;
38
38
  }
39
39
  };
@@ -75,12 +75,11 @@ export const addAppToolNode = async ({
75
75
  };
76
76
  const toolCallMessage = await tool.invoke(AIToolCallMessage.tool_calls[0]);
77
77
  AIToolCallMessage.additional_kwargs = {
78
- mindedMetadata: {
79
- nodeType: NodeType.APP_TOOL
78
+ appActionInvocation: {
79
+ nodeTitle: node.name,
80
80
  },
81
81
  };
82
82
  return {
83
- goto: null,
84
83
  messages: [AIToolCallMessage, toolCallMessage],
85
84
  history: createHistoryStep<AppActionInvocationHistoryStep>(state.history, {
86
85
  type: NodeType.APP_TOOL,
@@ -3,6 +3,7 @@ import { PreCompiledGraph, stateAnnotation } from '../types/LangGraph.types';
3
3
  import { RunnableLike } from '@langchain/core/runnables';
4
4
  import { logger } from '../utils/logger';
5
5
  import { internalNodesSuffix } from '../types/Flows.types';
6
+ import { InterruptType } from '../interrupts/BaseInterruptSessionManager';
6
7
 
7
8
  type AddHumanInTheLoopNodeParams = {
8
9
  graph: PreCompiledGraph;
@@ -13,10 +14,9 @@ export const buildHumanInTheLoopNodeName = (nodeName: string) => `${nodeName}${i
13
14
 
14
15
  export const addHumanInTheLoopNode = async ({ graph, attachedToNodeName }: AddHumanInTheLoopNodeParams) => {
15
16
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
16
- logger.debug({ msg: `[Node] Waiting for human input`, node: attachedToNodeName });
17
-
17
+ logger.info({ message: `Executing "human in the loop" node for the attached node${attachedToNodeName}` });
18
18
  if (state.messages[state.messages.length - 1].getType() === 'ai') {
19
- const value = interrupt('input from human in the loop');
19
+ const value = interrupt({ type: InterruptType.HUMAN_IN_THE_LOOP });
20
20
  return value;
21
21
  }
22
22
  };
@@ -7,10 +7,9 @@ import { createHistoryStep } from '../utils/history';
7
7
 
8
8
  export const addJumpToNode = async ({ graph, node }: { graph: PreCompiledGraph; node: JumpToNode }) => {
9
9
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
10
- logger.info(`Executing jump node ${node.displayName} – jumping to ${node.targetNodeId}`);
10
+ logger.info({ message: `Executing jump node ${node.displayName} – jumping to ${node.targetNodeId}` });
11
11
  // No state modifications are necessary; control flow is handled via edges.
12
12
  return {
13
- goto: null,
14
13
  history: createHistoryStep<HistoryStep>(state.history, {
15
14
  type: NodeType.JUMP_TO_NODE,
16
15
  nodeId: node.name,
@@ -7,7 +7,6 @@ import { HistoryStep } from '../types/Agent.types';
7
7
  export const addJunctionNode = ({ graph, node }: { graph: PreCompiledGraph; node: JunctionNode }) => {
8
8
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
9
9
  return {
10
- goto: null,
11
10
  history: createHistoryStep<HistoryStep>(state.history, {
12
11
  type: NodeType.JUNCTION,
13
12
  nodeId: node.name,
@@ -14,6 +14,9 @@ import { Agent } from '../agent';
14
14
  import { logger } from '../utils/logger';
15
15
  import { compilePlaybooks } from '../playbooks/playbooks';
16
16
  import { createHistoryStep } from '../utils/history';
17
+ import { wait } from '../utils/wait';
18
+ import { sendPlaceholderMessage } from '../internalTools/sendPlaceholderMessage';
19
+ import { v4 as uuidv4 } from 'uuid';
17
20
 
18
21
  type AddPromptNodeParams = {
19
22
  graph: PreCompiledGraph;
@@ -23,10 +26,12 @@ type AddPromptNodeParams = {
23
26
  emit: EmitSignature<any, keyof AgentEventRequestPayloads<any>>;
24
27
  agent: Agent;
25
28
  };
29
+ let shouldWait = true;
26
30
 
27
31
  export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: AddPromptNodeParams) => {
28
32
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
29
- logger.debug({ msg: `[Node] Executing prompt node`, node: node.displayName });
33
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
34
+ logger.info({ message: `Executing prompt node ${node.displayName}` });
30
35
  const llmToUse = node.llmConfig ? createLlmInstance(node.llmConfig) : llm;
31
36
 
32
37
  const globalTools = tools
@@ -50,9 +55,18 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
50
55
  ${state.memory ? `# Task context:\n${JSON.stringify(state.memory)}\n\n` : ''}
51
56
  ${compiledPlaybooks ? `# General guidelines:\n${compiledPlaybooks}\n\n` : ''}
52
57
  `;
58
+ if (true) {
59
+ logger.info({ msg: `waiting 15 seconds` });
60
+ shouldWait = false;
53
61
 
62
+ await sendPlaceholderMessage({ sessionId: state.sessionId, message: 'just a moment please... ' });
63
+ await wait(10000);
64
+ logger.info({ msg: `done waiting 15 seconds` });
65
+ } else {
66
+ logger.info({ msg: `not waiting` });
67
+ }
54
68
  const result: AIMessage = await llmToUse.bindTools(globalTools).invoke([...state.messages, new SystemMessage(message)]);
55
-
69
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
56
70
  // Check if the result contains tool calls
57
71
  if (result.tool_calls && result.tool_calls.length > 0) {
58
72
  // Execute the tools
@@ -61,12 +75,34 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
61
75
 
62
76
  for (const toolCall of result.tool_calls) {
63
77
  const matchedTool = globalTools.find((t) => t.name === toolCall.name);
64
- logger.info({ msg: `[Model] Calling tool`, tool: matchedTool?.name });
78
+ logger.info({ msg: `Model called tool ${matchedTool?.name}` });
65
79
  if (matchedTool) {
66
80
  try {
67
81
  // Invoke the LangChain tool directly
68
82
  const toolResult = await matchedTool.invoke(toolCall);
69
- logger.debug({ msg: `[Tool] Tool result`, tool: matchedTool?.name, result: toolResult });
83
+ //check for queue after tool call
84
+ const systemMessageId = uuidv4();
85
+
86
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId, {
87
+ messages: [
88
+ result,
89
+ toolResult,
90
+ new SystemMessage({
91
+ id: systemMessageId,
92
+ content:
93
+ 'you called tool when the user send a new message, Consider calling the function again after user message is processed',
94
+ }),
95
+ ],
96
+ history: [
97
+ createHistoryStep<HistoryStep>(state.history, {
98
+ type: NodeType.TOOL,
99
+ nodeId: node.name,
100
+ nodeDisplayName: node.displayName,
101
+ raw: toolResult,
102
+ messageIds: [toolResult.id!, systemMessageId],
103
+ }),
104
+ ],
105
+ });
70
106
  const toolStateUpdate = extractToolStateResponse(toolResult);
71
107
  // Properly merge memory and other state updates
72
108
  stateUpdates = {
@@ -75,8 +111,9 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
75
111
  memory: { ...(stateUpdates as any).memory, ...(toolStateUpdate as any).memory },
76
112
  };
77
113
  toolResults.push(toolResult);
78
- } catch (error) {
79
- logger.error({ msg: `[Tool] Error executing tool`, tool: toolCall.name, error });
114
+ } catch (error: any) {
115
+ if (error?.name === 'GraphInterrupt') throw error;
116
+ logger.error({ msg: `Error executing tool ${toolCall.name}:`, error });
80
117
  const errorMessage = new ToolMessage({
81
118
  content: JSON.stringify({ error: error instanceof Error ? error.message : String(error) }),
82
119
  tool_call_id: toolCall.id!,
@@ -84,14 +121,34 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
84
121
  toolResults.push(errorMessage);
85
122
  }
86
123
  } else {
87
- logger.error({ msg: `[Tool] Model called tool but it was not found`, tool: toolCall.name });
124
+ logger.error({ msg: `Model tried to call tool ${toolCall.name} but it was not found` });
88
125
  }
89
126
  }
90
127
 
128
+ // await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
129
+
91
130
  // Return the tool call message and tool results with state updates spread at top level
92
131
  return {
93
132
  ...stateUpdates,
94
133
  messages: [result, ...toolResults],
134
+ history: [
135
+ createHistoryStep<HistoryStep>(state.history, {
136
+ type: NodeType.TOOL,
137
+ nodeId: node.name,
138
+ nodeDisplayName: node.displayName,
139
+ raw: result,
140
+ messageIds: [result.id!],
141
+ }),
142
+ ...toolResults.map((toolResult) =>
143
+ createHistoryStep<HistoryStep>(state.history, {
144
+ type: NodeType.TOOL,
145
+ nodeId: node.name,
146
+ nodeDisplayName: node.displayName,
147
+ raw: toolResult,
148
+ messageIds: [toolResult.id!],
149
+ }),
150
+ ),
151
+ ],
95
152
  };
96
153
  }
97
154
 
@@ -100,11 +157,9 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
100
157
  message: result.content as string,
101
158
  state,
102
159
  });
103
- logger.info({ msg: `[Model] Response`, content: result.content });
160
+ console.log('AI Message', result.content);
104
161
  }
105
-
106
162
  return {
107
- goto: null,
108
163
  history: createHistoryStep<HistoryStep>(state.history, {
109
164
  type: NodeType.PROMPT_NODE,
110
165
  nodeId: node.name,
@@ -30,8 +30,8 @@ export const addToolNode = async ({
30
30
  throw new Error(`Tool not found: ${toolNode.toolName} in node ${node.name}`);
31
31
  }
32
32
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
33
- logger.debug({ msg: `[Node] Executing tool node`, node: toolNode.displayName });
34
-
33
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
34
+ logger.info({ message: `Executing tool node ${toolNode.displayName}` });
35
35
  const tool = langchainTool(() => {}, {
36
36
  name: matchedTool.name,
37
37
  description: matchedTool.description,
@@ -56,9 +56,9 @@ export const addToolNode = async ({
56
56
  tool_choice: tool.name,
57
57
  })
58
58
  .invoke([...state.messages, new SystemMessage(prompt)]);
59
-
59
+ logger.info({ message: 'after llm tool invoke' });
60
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
60
61
  return {
61
- goto: null,
62
62
  messages: [AIToolCallMessage],
63
63
  history: createHistoryStep<HistoryStep>(state.history, {
64
64
  type: NodeType.TOOL,
@@ -23,6 +23,7 @@ type AddToolRunNodeParams = {
23
23
 
24
24
  export const buildToolRunNodeName = (nodeName: string) => `${nodeName}${internalNodesSuffix.TOOL_RUN}`;
25
25
 
26
+ //you never want to interrupt here because of new triggers, as this node depends on the last message to be the tool call from the addToolNode, interrupting will add human message here
26
27
  export const addToolRunNode = async ({ graph, tools, toolNode, attachedToNodeName, agent }: AddToolRunNodeParams) => {
27
28
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
28
29
  const matchedTool = tools.find((tool) => tool.name === toolNode.toolName);
@@ -35,7 +36,7 @@ export const addToolRunNode = async ({ graph, tools, toolNode, attachedToNodeNam
35
36
  const response = await matchedTool.execute({ input, state, agent });
36
37
  return response || {};
37
38
  } catch (error) {
38
- logger.error({ msg: '[Tool] Error executing tool', error, node: toolNode.displayName });
39
+ logger.error({ msg: 'Error executing tool', error });
39
40
  throw error;
40
41
  }
41
42
  };
@@ -54,11 +55,8 @@ export const addToolRunNode = async ({ graph, tools, toolNode, attachedToNodeNam
54
55
 
55
56
  // Push the toolCallMessage into the messages array from toolStateUpdate
56
57
  const updatedMessages = [toolCallMessage, ...((toolStateUpdate as any).messages || [])];
57
-
58
58
  // Return the full state update from the tool with the updated messages
59
-
60
59
  return {
61
- goto: null,
62
60
  ...toolStateUpdate,
63
61
  messages: updatedMessages,
64
62
  history: createHistoryStep<HistoryStep>(state.history, {
@@ -7,10 +7,9 @@ import { createHistoryStep } from '../utils/history';
7
7
 
8
8
  export const addTriggerNode = async ({ graph, node }: { graph: PreCompiledGraph; node: TriggerNode }) => {
9
9
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
10
- logger.debug({ msg: `[Trigger] Executing trigger node`, node: node.displayName });
10
+ logger.info({ message: `Executing trigger node ${node.displayName}` });
11
11
  if (node.triggerType === TriggerType.MANUAL) {
12
12
  return {
13
- goto: null,
14
13
  history: createHistoryStep<HistoryStep>(state.history, {
15
14
  type: NodeType.TRIGGER,
16
15
  nodeId: node.name,
@@ -11,7 +11,6 @@ import { LLMProviders } from '../types/LLM.types';
11
11
  import { Agent } from '../agent';
12
12
  import { addJumpToNode } from './addJumpToNode';
13
13
  import { addJunctionNode } from './addJunctionNode';
14
- import { addBrowserTaskNode } from './addBrowserTaskNode';
15
14
 
16
15
  export const nodeFactory = ({
17
16
  graph,
@@ -48,10 +47,7 @@ export const nodeFactory = ({
48
47
  case NodeType.JUMP_TO_NODE:
49
48
  addJumpToNode({ graph, node });
50
49
  break;
51
- case NodeType.BROWSER_TASK:
52
- addBrowserTaskNode({ graph, node, agent, llm });
53
- break;
54
50
  default:
55
51
  throw new Error(`Unsupported node type: ${nodeType}`);
56
52
  }
57
- };
53
+ };