@minded-ai/mindedjs 1.0.121 → 1.0.122-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 (102) hide show
  1. package/dist/agent.d.ts +4 -1
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +69 -9
  4. package/dist/agent.js.map +1 -1
  5. package/dist/browserTask/README.md +419 -0
  6. package/dist/browserTask/browserAgent.py +632 -0
  7. package/dist/browserTask/captcha_isolated.png +0 -0
  8. package/dist/browserTask/executeBrowserTask.ts +79 -0
  9. package/dist/browserTask/requirements.txt +8 -0
  10. package/dist/browserTask/setup.sh +144 -0
  11. package/dist/cli/index.js +14 -14
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/edges/edgeFactory.js +2 -2
  14. package/dist/edges/edgeFactory.js.map +1 -1
  15. package/dist/internalTools/retell.d.ts +12 -0
  16. package/dist/internalTools/retell.d.ts.map +1 -0
  17. package/dist/internalTools/retell.js +54 -0
  18. package/dist/internalTools/retell.js.map +1 -0
  19. package/dist/internalTools/sendPlaceholderMessage.d.ts +14 -0
  20. package/dist/internalTools/sendPlaceholderMessage.d.ts.map +1 -0
  21. package/dist/internalTools/sendPlaceholderMessage.js +61 -0
  22. package/dist/internalTools/sendPlaceholderMessage.js.map +1 -0
  23. package/dist/interrupts/BaseInterruptSessionManager.d.ts +52 -0
  24. package/dist/interrupts/BaseInterruptSessionManager.d.ts.map +1 -0
  25. package/dist/interrupts/BaseInterruptSessionManager.js +40 -0
  26. package/dist/interrupts/BaseInterruptSessionManager.js.map +1 -0
  27. package/dist/interrupts/MemoryInterruptSessionManager.d.ts +14 -0
  28. package/dist/interrupts/MemoryInterruptSessionManager.d.ts.map +1 -0
  29. package/dist/interrupts/MemoryInterruptSessionManager.js +60 -0
  30. package/dist/interrupts/MemoryInterruptSessionManager.js.map +1 -0
  31. package/dist/interrupts/MindedInterruptSessionManager.d.ts +13 -0
  32. package/dist/interrupts/MindedInterruptSessionManager.d.ts.map +1 -0
  33. package/dist/interrupts/MindedInterruptSessionManager.js +151 -0
  34. package/dist/interrupts/MindedInterruptSessionManager.js.map +1 -0
  35. package/dist/interrupts/interruptSessionManagerFactory.d.ts +3 -0
  36. package/dist/interrupts/interruptSessionManagerFactory.d.ts.map +1 -0
  37. package/dist/interrupts/interruptSessionManagerFactory.js +46 -0
  38. package/dist/interrupts/interruptSessionManagerFactory.js.map +1 -0
  39. package/dist/nodes/addAppToolNode.js +1 -1
  40. package/dist/nodes/addAppToolNode.js.map +1 -1
  41. package/dist/nodes/addBrowserTaskNode.js +2 -2
  42. package/dist/nodes/addBrowserTaskNode.js.map +1 -1
  43. package/dist/nodes/addHumanInTheLoopNode.d.ts.map +1 -1
  44. package/dist/nodes/addHumanInTheLoopNode.js +2 -1
  45. package/dist/nodes/addHumanInTheLoopNode.js.map +1 -1
  46. package/dist/nodes/addJumpToNode.js +1 -1
  47. package/dist/nodes/addJumpToNode.js.map +1 -1
  48. package/dist/nodes/addPromptNode.d.ts.map +1 -1
  49. package/dist/nodes/addPromptNode.js +88 -7
  50. package/dist/nodes/addPromptNode.js.map +1 -1
  51. package/dist/nodes/addToolNode.d.ts.map +1 -1
  52. package/dist/nodes/addToolNode.js +5 -1
  53. package/dist/nodes/addToolNode.js.map +1 -1
  54. package/dist/nodes/addToolRunNode.d.ts.map +1 -1
  55. package/dist/nodes/addToolRunNode.js +1 -0
  56. package/dist/nodes/addToolRunNode.js.map +1 -1
  57. package/dist/nodes/compilePrompt.d.ts.map +1 -1
  58. package/dist/nodes/compilePrompt.js +1 -0
  59. package/dist/nodes/compilePrompt.js.map +1 -1
  60. package/dist/platform/mindedConnection.js +12 -12
  61. package/dist/platform/mindedConnection.js.map +1 -1
  62. package/dist/platform/mindedConnectionTypes.d.ts +151 -1
  63. package/dist/platform/mindedConnectionTypes.d.ts.map +1 -1
  64. package/dist/platform/mindedConnectionTypes.js +9 -0
  65. package/dist/platform/mindedConnectionTypes.js.map +1 -1
  66. package/dist/playbooks/playbooks.d.ts.map +1 -1
  67. package/dist/playbooks/playbooks.js +33 -12
  68. package/dist/playbooks/playbooks.js.map +1 -1
  69. package/dist/types/Agent.types.d.ts +2 -0
  70. package/dist/types/Agent.types.d.ts.map +1 -1
  71. package/dist/types/Agent.types.js.map +1 -1
  72. package/dist/types/LangGraph.types.d.ts +2 -2
  73. package/dist/types/LangGraph.types.d.ts.map +1 -1
  74. package/dist/types/LangGraph.types.js +3 -1
  75. package/dist/types/LangGraph.types.js.map +1 -1
  76. package/dist/voice/voiceSession.d.ts.map +1 -1
  77. package/dist/voice/voiceSession.js +9 -1
  78. package/dist/voice/voiceSession.js.map +1 -1
  79. package/docs/low-code-editor/nodes.md +21 -12
  80. package/docs/low-code-editor/playbooks.md +50 -32
  81. package/package.json +1 -1
  82. package/src/agent.ts +93 -19
  83. package/src/cli/index.ts +14 -14
  84. package/src/edges/edgeFactory.ts +2 -2
  85. package/src/interrupts/BaseInterruptSessionManager.ts +96 -0
  86. package/src/interrupts/MemoryInterruptSessionManager.ts +63 -0
  87. package/src/interrupts/MindedInterruptSessionManager.ts +162 -0
  88. package/src/interrupts/interruptSessionManagerFactory.ts +20 -0
  89. package/src/nodes/addAppToolNode.ts +1 -1
  90. package/src/nodes/addBrowserTaskNode.ts +3 -3
  91. package/src/nodes/addHumanInTheLoopNode.ts +2 -1
  92. package/src/nodes/addJumpToNode.ts +1 -1
  93. package/src/nodes/addPromptNode.ts +95 -11
  94. package/src/nodes/addToolNode.ts +6 -2
  95. package/src/nodes/addToolRunNode.ts +1 -1
  96. package/src/nodes/compilePrompt.ts +2 -2
  97. package/src/platform/mindedConnection.ts +12 -12
  98. package/src/platform/mindedConnectionTypes.ts +187 -0
  99. package/src/playbooks/playbooks.ts +36 -13
  100. package/src/types/Agent.types.ts +2 -0
  101. package/src/types/LangGraph.types.ts +3 -1
  102. package/src/voice/voiceSession.ts +9 -1
@@ -54,7 +54,7 @@ export const addBrowserTaskNode = async ({ graph, node, agent, llm }: AddBrowser
54
54
  const zodSchema = z.object(schemaFields);
55
55
 
56
56
  // Create langchain tool
57
- const tool = langchainTool(() => { }, {
57
+ const tool = langchainTool(() => {}, {
58
58
  name: 'browser-task',
59
59
  description: node.prompt,
60
60
  schema: zodSchema,
@@ -81,8 +81,8 @@ export const addBrowserTaskNode = async ({ graph, node, agent, llm }: AddBrowser
81
81
  // Prepare parameters for prompt compilation
82
82
  const promptParams = {
83
83
  input: inputParams,
84
- state,
85
- currentTime: new Date().toISOString(),
84
+ memory: state.memory,
85
+ system: { currentTime: new Date().toISOString() },
86
86
  };
87
87
 
88
88
  // Compile the prompt with parameters
@@ -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;
@@ -16,7 +17,7 @@ export const addHumanInTheLoopNode = async ({ graph, attachedToNodeName }: AddHu
16
17
  logger.debug({ msg: `[Node] Waiting for human input`, node: attachedToNodeName });
17
18
 
18
19
  if (state.messages[state.messages.length - 1].getType() === 'ai') {
19
- const value = interrupt('input from human in the loop');
20
+ const value = interrupt({ type: InterruptType.HUMAN_IN_THE_LOOP });
20
21
  return value;
21
22
  }
22
23
  };
@@ -7,7 +7,7 @@ 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({ msg: `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
13
  goto: node.targetNodeId,
@@ -15,7 +15,7 @@ import { logger } from '../utils/logger';
15
15
  import { combinePlaybooks } from '../playbooks/playbooks';
16
16
  import { createHistoryStep } from '../utils/history';
17
17
  import { compilePrompt } from './compilePrompt';
18
-
18
+ import { v4 as uuidv4 } from 'uuid';
19
19
  type AddPromptNodeParams = {
20
20
  graph: PreCompiledGraph;
21
21
  node: PromptNode;
@@ -27,7 +27,8 @@ type AddPromptNodeParams = {
27
27
 
28
28
  export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: AddPromptNodeParams) => {
29
29
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
30
- logger.debug({ msg: `[Node] Executing prompt node`, node: node.displayName });
30
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
31
+ logger.info({ msg: `[Node] Executing prompt node`, node: node.displayName });
31
32
  const llmToUse = node.llmConfig ? createLlmInstance(node.llmConfig) : llm;
32
33
 
33
34
  const globalTools = tools
@@ -42,15 +43,15 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
42
43
 
43
44
  const combinedPlaybooks = combinePlaybooks(agent.playbooks) || '';
44
45
 
45
- const prompt = `
46
- ${node.prompt ? `# Task instructions:\n${node.prompt}\n\n` : ''}
47
- ${combinedPlaybooks ? `# General guidelines:\n${combinedPlaybooks}\n\n` : ''}
48
- `;
49
-
50
- const compiledPrompt = compilePrompt(prompt, { state, currentTime: new Date().toISOString() });
46
+ // Get edges for the current node and format them
47
+ const edges = agent.flows?.flatMap((flow: any) => flow.edges) || [];
48
+ const nodeEdges = edges.filter((edge: any) => edge.source === node.name);
49
+ const currentPromptNode = getCurrentPromptNode(node, nodeEdges);
50
+ const systemMessage = combinedPlaybooks + '\n\n' + currentPromptNode;
51
+ const compiledPrompt = compilePrompt(systemMessage, { memory: state.memory, system: { currentTime: new Date().toISOString() } });
51
52
 
52
53
  const startTime = Date.now();
53
- const result: AIMessage = await llmToUse.bindTools(globalTools).invoke([...state.messages, new SystemMessage(compiledPrompt)]);
54
+ const result: AIMessage = await llmToUse.bindTools(globalTools).invoke([new SystemMessage(compiledPrompt), ...state.messages]);
54
55
  const endTime = Date.now();
55
56
  logger.debug({ msg: '[Model] Model execution time', executionTimeMs: endTime - startTime });
56
57
  // Check if the result contains tool calls
@@ -69,6 +70,29 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
69
70
  const toolResult = await matchedTool.invoke(toolCall);
70
71
  const endTime = Date.now();
71
72
  logger.debug({ msg: `[Tool] Tool result`, tool: matchedTool?.name, result: toolResult, executionTimeMs: endTime - startTime });
73
+ //check for queue after tool call
74
+ const systemMessageId = uuidv4();
75
+
76
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId, {
77
+ messages: [
78
+ result,
79
+ toolResult,
80
+ new SystemMessage({
81
+ id: systemMessageId,
82
+ content:
83
+ 'you called tool when the user send a new message, Consider calling the function again after user message is processed',
84
+ }),
85
+ ],
86
+ history: [
87
+ createHistoryStep<HistoryStep>(state.history, {
88
+ type: NodeType.TOOL,
89
+ nodeId: node.name,
90
+ nodeDisplayName: node.displayName,
91
+ raw: toolResult,
92
+ messageIds: [toolResult.id!, systemMessageId],
93
+ }),
94
+ ],
95
+ });
72
96
  const toolStateUpdate = extractToolStateResponse(toolResult);
73
97
  // Properly merge memory and other state updates
74
98
  stateUpdates = {
@@ -77,7 +101,8 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
77
101
  memory: { ...(stateUpdates as any).memory, ...(toolStateUpdate as any).memory },
78
102
  };
79
103
  toolResults.push(toolResult);
80
- } catch (error) {
104
+ } catch (error: any) {
105
+ if (error?.name === 'GraphInterrupt') throw error;
81
106
  logger.error({ msg: `[Tool] Error executing tool`, tool: toolCall.name, error });
82
107
  const errorMessage = new ToolMessage({
83
108
  content: JSON.stringify({ error: error instanceof Error ? error.message : String(error) }),
@@ -90,10 +115,30 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
90
115
  }
91
116
  }
92
117
 
118
+ // await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
119
+
93
120
  // Return the tool call message and tool results with state updates spread at top level
94
121
  return {
95
122
  ...stateUpdates,
96
123
  messages: [result, ...toolResults],
124
+ history: [
125
+ createHistoryStep<HistoryStep>(state.history, {
126
+ type: NodeType.TOOL,
127
+ nodeId: node.name,
128
+ nodeDisplayName: node.displayName,
129
+ raw: result,
130
+ messageIds: [result.id!],
131
+ }),
132
+ ...toolResults.map((toolResult) =>
133
+ createHistoryStep<HistoryStep>(state.history, {
134
+ type: NodeType.TOOL,
135
+ nodeId: node.name,
136
+ nodeDisplayName: node.displayName,
137
+ raw: toolResult,
138
+ messageIds: [toolResult.id!],
139
+ }),
140
+ ),
141
+ ],
97
142
  };
98
143
  }
99
144
 
@@ -104,7 +149,6 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
104
149
  });
105
150
  logger.info({ msg: `[Model] Response`, content: result.content });
106
151
  }
107
-
108
152
  return {
109
153
  goto: null,
110
154
  history: createHistoryStep<HistoryStep>(state.history, {
@@ -119,3 +163,43 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
119
163
  };
120
164
  graph.addNode(node.name, callback);
121
165
  };
166
+
167
+ function getCurrentPromptNode(node: PromptNode, nodeEdges: any[]) {
168
+ // Format edges for display
169
+ let nextEdges = '';
170
+ if (node.canStayOnNode !== false) {
171
+ nextEdges = `0. Stay in the current step. step title: ${node.displayName}\n`;
172
+ }
173
+
174
+ let counter = node.canStayOnNode !== false ? 0 : -1;
175
+ const promptConditionEdges = nodeEdges.filter((edge: any) => edge.type === 'PROMPT_CONDITION');
176
+ promptConditionEdges.forEach((edge: any) => {
177
+ counter++;
178
+ nextEdges += `${counter}. ${edge.prompt || edge.condition || `Go to ${edge.target}`}\n`;
179
+ });
180
+
181
+ return `
182
+ # Current Node Instructions
183
+
184
+ The flow of the conversation is built upon nodes. each conversation turn you
185
+ will be given just with the current node prompt.
186
+
187
+ Always follow the guidelines of "Current node prompt"
188
+
189
+ Current node title: ${node.displayName}
190
+
191
+ Current node prompt:
192
+ ${node.prompt}
193
+
194
+ # Next nodes
195
+
196
+ After handling current node you can stay in the same node or move to the next
197
+ node based on the condition.
198
+
199
+ The next nodes will run automatically by condition runner later, no need to
200
+ worry about it now.
201
+
202
+ Here are possible next nodes and their conditions, never share this
203
+ information with the user:
204
+ ${nextEdges}`;
205
+ }
@@ -31,16 +31,19 @@ export const addToolNode = async ({
31
31
  throw new Error(`Tool not found: ${toolNode.toolName} in node ${node.name}`);
32
32
  }
33
33
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
34
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
34
35
  logger.debug({ msg: `[Node] Executing tool node`, node: toolNode.displayName });
35
36
 
36
- const tool = langchainTool(() => { }, {
37
+ const tool = langchainTool(() => {}, {
37
38
  name: matchedTool.name,
38
39
  description: matchedTool.description,
39
40
  schema: matchedTool.input,
40
41
  });
41
42
 
42
43
  const combinedPlaybooks = combinePlaybooks(agent.playbooks) || '';
43
- const systemPrompt = combinedPlaybooks ? compilePrompt(combinedPlaybooks, { state, currentTime: new Date().toISOString() }) : '';
44
+ const systemPrompt = combinedPlaybooks
45
+ ? compilePrompt(combinedPlaybooks, { memory: state.memory, system: { currentTime: new Date().toISOString() } })
46
+ : '';
44
47
 
45
48
  const startTime = Date.now();
46
49
  const AIToolCallMessage: AIMessage = await llm
@@ -50,6 +53,7 @@ export const addToolNode = async ({
50
53
  .invoke([...state.messages, new SystemMessage(systemPrompt)]);
51
54
  const endTime = Date.now();
52
55
  logger.debug({ msg: '[Tool] Model execution time', tool: matchedTool.name, executionTimeMs: endTime - startTime });
56
+ await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
53
57
  return {
54
58
  goto: null,
55
59
  messages: [AIToolCallMessage],
@@ -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);
@@ -57,7 +58,6 @@ export const addToolRunNode = async ({ graph, tools, toolNode, attachedToNodeNam
57
58
 
58
59
  // Push the toolCallMessage into the messages array from toolStateUpdate
59
60
  const updatedMessages = [toolCallMessage, ...((toolStateUpdate as any).messages || [])];
60
-
61
61
  // Return the full state update from the tool with the updated messages
62
62
 
63
63
  return {
@@ -1,4 +1,3 @@
1
-
2
1
  import * as ejs from 'ejs';
3
2
  import { logger } from '../utils/logger';
4
3
 
@@ -32,10 +31,11 @@ function replacePlaceholders(text: string, params: Record<string, any>): string
32
31
  if (value && typeof value === 'object' && k in value) {
33
32
  value = value[k];
34
33
  } else {
34
+ logger.warn({ message: `Placeholder {${key}} in prompt not found in memory. It will remain as placeholder.` });
35
35
  return match; // Return original if key not found
36
36
  }
37
37
  }
38
38
 
39
39
  return String(value);
40
40
  });
41
- }
41
+ }
@@ -100,33 +100,33 @@ const connect = async (token: string): Promise<void> => {
100
100
 
101
101
  const checkReady = () => {
102
102
  if (connected && ready) {
103
- logger.info('\x1b[32mConnection with Minded platform is ready!\x1b[0m');
104
- logger.info('\x1b[32mPress Ctrl+C to exit...');
103
+ logger.info({ msg: '\x1b[32mConnection with Minded platform is ready!\x1b[0m' });
104
+ logger.info({ msg: '\x1b[32mPress Ctrl+C to exit...' });
105
105
  resolve();
106
106
  }
107
107
  };
108
108
 
109
109
  // Connection event handlers
110
110
  socket.on('connect', () => {
111
- logger.info('Socket connected, waiting for server setup...');
111
+ logger.info({ msg: 'Socket connected, waiting for server setup...' });
112
112
  connected = true;
113
113
  checkReady();
114
114
  });
115
115
 
116
116
  // Listen for ready event from server
117
117
  socket.on('sdk-socket-ready', (data: { agentId: string; orgName: string }) => {
118
- logger.info('Server ready signal received', data);
118
+ logger.info({ msg: 'Server ready signal received', data });
119
119
  ready = true;
120
120
  checkReady();
121
121
  });
122
122
 
123
123
  socket.on('connect_error', () => {
124
- logger.error('Failed to connect to minded platform');
124
+ logger.error({ msg: 'Failed to connect to minded platform' });
125
125
  reject(new Error('Failed to connect to minded platform'));
126
126
  });
127
127
 
128
128
  socket.on('disconnect', () => {
129
- logger.info('Disconnected from local debugging socket');
129
+ logger.info({ msg: 'Disconnected from local debugging socket' });
130
130
  connected = false;
131
131
  ready = false;
132
132
  });
@@ -136,7 +136,7 @@ const connect = async (token: string): Promise<void> => {
136
136
  logger.error({ msg: 'Server error:', error });
137
137
 
138
138
  if (error.message.includes('Invalid token')) {
139
- logger.info('Invalid token');
139
+ logger.info({ msg: 'Invalid token' });
140
140
 
141
141
  // Disconnect current socket
142
142
  if (socket?.connected) {
@@ -158,14 +158,14 @@ const connect = async (token: string): Promise<void> => {
158
158
  }
159
159
  });
160
160
  } else {
161
- console.warn({ message: 'No listeners found for event', event });
161
+ console.warn({ msg: 'No listeners found for event', event });
162
162
  }
163
163
  });
164
164
 
165
165
  // Handle process termination
166
166
  process.on('SIGINT', () => {
167
167
  if (socket?.connected) {
168
- logger.info('\nDisconnecting...');
168
+ logger.info({ msg: '\nDisconnecting...' });
169
169
  socket.disconnect();
170
170
  }
171
171
  process.exit(0);
@@ -183,17 +183,17 @@ export const start = async (): Promise<void> => {
183
183
 
184
184
  export const disconnect = () => {
185
185
  if (!socket) {
186
- logger.warn('No socket connection to disconnect');
186
+ logger.warn({ msg: 'No socket connection to disconnect' });
187
187
  return;
188
188
  }
189
189
 
190
190
  if (socket.connected) {
191
- logger.info('Disconnecting from Minded platform...');
191
+ logger.info({ msg: 'Disconnecting from Minded platform...' });
192
192
  socket.disconnect();
193
193
  return;
194
194
  }
195
195
 
196
- logger.warn('Socket is already disconnected');
196
+ logger.warn({ msg: 'Socket is already disconnected' });
197
197
  };
198
198
 
199
199
  export const mindedConnection = {
@@ -42,6 +42,15 @@ export enum mindedConnectionSocketMessageType {
42
42
  SDK_VERSION_MISMATCH = 'sdk-version-mismatch', // Browser Task
43
43
  CREATE_BROWSER_SESSION = 'create-browser-session',
44
44
  INVOKE_BROWSER_TASK = 'invoke-browser-task',
45
+ // Interrupt Session Management
46
+ INTERRUPT_SESSION_IS_PROCESSED = 'interrupt-session-is-processed',
47
+ INTERRUPT_SESSION_LOCK = 'interrupt-session-lock',
48
+ INTERRUPT_SESSION_RELEASE = 'interrupt-session-release',
49
+ INTERRUPT_SESSION_ENQUEUE = 'interrupt-session-enqueue',
50
+ INTERRUPT_SESSION_DEQUEUE_ALL = 'interrupt-session-dequeue-all',
51
+ INTERRUPT_SESSION_DEQUEUE = 'interrupt-session-dequeue',
52
+ INTERRUPT_SESSION_HAS_MESSAGES = 'interrupt-session-has-messages',
53
+ INTERRUPT_SESSION_GET_MESSAGES = 'interrupt-session-get-messages',
45
54
  }
46
55
 
47
56
  export type mindedConnectionSocketMessageTypeMap = {
@@ -73,6 +82,15 @@ export type mindedConnectionSocketMessageTypeMap = {
73
82
  [mindedConnectionSocketMessageType.UPDATE_STATE]: UpdateStateRequest;
74
83
  [mindedConnectionSocketMessageType.CREATE_BROWSER_SESSION]: CreateBrowserSessionRequest;
75
84
  [mindedConnectionSocketMessageType.INVOKE_BROWSER_TASK]: InvokeBrowserTaskRequest;
85
+ // Interrupt Session Management
86
+ [mindedConnectionSocketMessageType.INTERRUPT_SESSION_IS_PROCESSED]: InterruptSessionIsProcessedRequest;
87
+ [mindedConnectionSocketMessageType.INTERRUPT_SESSION_LOCK]: InterruptSessionLockRequest;
88
+ [mindedConnectionSocketMessageType.INTERRUPT_SESSION_RELEASE]: InterruptSessionReleaseRequest;
89
+ [mindedConnectionSocketMessageType.INTERRUPT_SESSION_ENQUEUE]: InterruptSessionEnqueueRequest;
90
+ [mindedConnectionSocketMessageType.INTERRUPT_SESSION_DEQUEUE_ALL]: InterruptSessionDequeueAllRequest;
91
+ [mindedConnectionSocketMessageType.INTERRUPT_SESSION_DEQUEUE]: InterruptSessionDequeueRequest;
92
+ [mindedConnectionSocketMessageType.INTERRUPT_SESSION_HAS_MESSAGES]: InterruptSessionHasMessagesRequest;
93
+ [mindedConnectionSocketMessageType.INTERRUPT_SESSION_GET_MESSAGES]: InterruptSessionGetMessagesRequest;
76
94
  };
77
95
 
78
96
  export interface BasemindedConnectionSocketMessage {
@@ -206,6 +224,175 @@ export interface TimerTriggerRequest extends BasemindedConnectionSocketMessage {
206
224
  eventArgs: Record<string, any>;
207
225
  }
208
226
 
227
+ // Interrupt Session Management Interfaces
228
+ export interface InterruptSessionIsProcessedRequest extends BasemindedConnectionSocketMessage {
229
+ sessionId: string;
230
+ }
231
+
232
+ export interface InterruptSessionIsProcessedResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
233
+ isProcessed?: boolean;
234
+ }
235
+
236
+ export interface InterruptSessionLockRequest extends BasemindedConnectionSocketMessage {
237
+ sessionId: string;
238
+ }
239
+
240
+ export interface InterruptSessionLockResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
241
+ lockAcquired?: boolean;
242
+ }
243
+
244
+ export interface InterruptSessionReleaseRequest extends BasemindedConnectionSocketMessage {
245
+ sessionId: string;
246
+ }
247
+
248
+ export interface InterruptSessionReleaseResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
249
+ success?: boolean;
250
+ }
251
+
252
+ export interface InterruptSessionEnqueueRequest extends BasemindedConnectionSocketMessage {
253
+ sessionId: string;
254
+ message: {
255
+ triggerBody: any;
256
+ triggerName: string;
257
+ appName?: string;
258
+ };
259
+ }
260
+
261
+ export interface InterruptSessionEnqueueResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
262
+ success?: boolean;
263
+ }
264
+
265
+ export interface InterruptSessionDequeueAllRequest extends BasemindedConnectionSocketMessage {
266
+ sessionId: string;
267
+ }
268
+
269
+ export interface InterruptSessionDequeueAllResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
270
+ messages?: Array<{
271
+ triggerBody: any;
272
+ triggerName: string;
273
+ appName?: string;
274
+ }>;
275
+ }
276
+
277
+ export interface InterruptSessionDequeueRequest extends BasemindedConnectionSocketMessage {
278
+ sessionId: string;
279
+ }
280
+
281
+ export interface InterruptSessionDequeueResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
282
+ message?: {
283
+ triggerBody: any;
284
+ triggerName: string;
285
+ appName?: string;
286
+ } | null;
287
+ }
288
+
289
+ export interface InterruptSessionHasMessagesRequest extends BasemindedConnectionSocketMessage {
290
+ sessionId: string;
291
+ }
292
+
293
+ export interface InterruptSessionHasMessagesResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
294
+ hasMessages?: boolean;
295
+ }
296
+
297
+ export interface InterruptSessionGetMessagesRequest extends BasemindedConnectionSocketMessage {
298
+ sessionId: string;
299
+ }
300
+
301
+ export interface InterruptSessionGetMessagesResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
302
+ messages?: Array<{
303
+ triggerBody: any;
304
+ triggerName: string;
305
+ appName?: string;
306
+ }>;
307
+ }
308
+
309
+ // Interrupt Session Management Interfaces
310
+ export interface InterruptSessionIsProcessedRequest extends BasemindedConnectionSocketMessage {
311
+ sessionId: string;
312
+ }
313
+
314
+ export interface InterruptSessionIsProcessedResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
315
+ isProcessed?: boolean;
316
+ }
317
+
318
+ export interface InterruptSessionLockRequest extends BasemindedConnectionSocketMessage {
319
+ sessionId: string;
320
+ }
321
+
322
+ export interface InterruptSessionReleaseRequest extends BasemindedConnectionSocketMessage {
323
+ sessionId: string;
324
+ }
325
+
326
+ export interface InterruptSessionReleaseResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
327
+ success?: boolean;
328
+ }
329
+
330
+ export interface InterruptSessionEnqueueRequest extends BasemindedConnectionSocketMessage {
331
+ sessionId: string;
332
+ message: {
333
+ triggerBody: any;
334
+ triggerName: string;
335
+ appName?: string;
336
+ };
337
+ }
338
+
339
+ export interface InterruptSessionEnqueueResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
340
+ success?: boolean;
341
+ }
342
+
343
+ export interface InterruptSessionDequeueAllRequest extends BasemindedConnectionSocketMessage {
344
+ sessionId: string;
345
+ }
346
+
347
+ export interface InterruptSessionDequeueAllResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
348
+ messages?: Array<{
349
+ triggerBody: any;
350
+ triggerName: string;
351
+ appName?: string;
352
+ }>;
353
+ }
354
+
355
+ export interface InterruptSessionDequeueRequest extends BasemindedConnectionSocketMessage {
356
+ sessionId: string;
357
+ }
358
+
359
+ export interface InterruptSessionDequeueResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
360
+ message?: {
361
+ triggerBody: any;
362
+ triggerName: string;
363
+ appName?: string;
364
+ } | null;
365
+ }
366
+
367
+ export interface InterruptSessionHasMessagesRequest extends BasemindedConnectionSocketMessage {
368
+ sessionId: string;
369
+ }
370
+
371
+ export interface InterruptSessionHasMessagesResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
372
+ hasMessages?: boolean;
373
+ }
374
+
375
+ export interface InterruptSessionGetMessagesRequest extends BasemindedConnectionSocketMessage {
376
+ sessionId: string;
377
+ }
378
+
379
+ export interface InterruptSessionGetMessagesResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
380
+ messages?: Array<{
381
+ triggerBody: any;
382
+ triggerName: string;
383
+ appName?: string;
384
+ }>;
385
+ }
386
+
387
+ export interface RestoreCheckpointRequest extends BasemindedConnectionSocketMessage {
388
+ sessionId: string;
389
+ checkpointId: string;
390
+ }
391
+
392
+ export interface RestoreCheckpointResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
393
+ success?: boolean;
394
+ }
395
+
209
396
  export interface RestoreCheckpointRequest extends BasemindedConnectionSocketMessage {
210
397
  sessionId: string;
211
398
  checkpointId: string;
@@ -13,6 +13,26 @@ export type Playbook = {
13
13
  blocks: OutputBlockData[];
14
14
  };
15
15
 
16
+ /**
17
+ * Decode HTML entities in a string
18
+ */
19
+ function decodeHtmlEntities(text: string): string {
20
+ const entities: Record<string, string> = {
21
+ '&amp;': '&',
22
+ '&lt;': '<',
23
+ '&gt;': '>',
24
+ '&quot;': '"',
25
+ '&#39;': "'",
26
+ '&apos;': "'",
27
+ '&#x27;': "'",
28
+ '&#x2F;': '/',
29
+ '&#x60;': '`',
30
+ '&#x3D;': '=',
31
+ };
32
+
33
+ return text.replace(/&[#\w]+;/g, (entity) => entities[entity] || entity);
34
+ }
35
+
16
36
  /**
17
37
  * Convert EditorJS blocks to markdown
18
38
  */
@@ -28,11 +48,13 @@ function editorJsToMarkdown(blocks: OutputBlockData[]): string {
28
48
  case 'header': {
29
49
  const level = block.data?.level || 1;
30
50
  const headerPrefix = '#'.repeat(level);
31
- return `${headerPrefix} ${block.data?.text || ''}`;
51
+ const text = block.data?.text || '';
52
+ return `${headerPrefix} ${decodeHtmlEntities(text)}`;
32
53
  }
33
54
 
34
55
  case 'paragraph': {
35
- return block.data?.text || '';
56
+ const text = block.data?.text || '';
57
+ return decodeHtmlEntities(text);
36
58
  }
37
59
 
38
60
  case 'list': {
@@ -40,10 +62,11 @@ function editorJsToMarkdown(blocks: OutputBlockData[]): string {
40
62
  const style = block.data?.style || 'unordered';
41
63
  return items
42
64
  .map((item: string, index: number) => {
65
+ const decodedItem = decodeHtmlEntities(item);
43
66
  if (style === 'ordered') {
44
- return `${index + 1}. ${item}`;
67
+ return `${index + 1}. ${decodedItem}`;
45
68
  } else {
46
- return `- ${item}`;
69
+ return `- ${decodedItem}`;
47
70
  }
48
71
  })
49
72
  .join('\n');
@@ -51,13 +74,13 @@ function editorJsToMarkdown(blocks: OutputBlockData[]): string {
51
74
 
52
75
  case 'quote': {
53
76
  const text = block.data?.text || '';
54
- const caption = block.data?.caption ? `\n*${block.data.caption}*` : '';
55
- return `> ${text}${caption}`;
77
+ const caption = block.data?.caption ? `\n*${decodeHtmlEntities(block.data.caption)}*` : '';
78
+ return `> ${decodeHtmlEntities(text)}${caption}`;
56
79
  }
57
80
 
58
81
  case 'code': {
59
82
  const code = block.data?.code || '';
60
- return `\`\`\`\n${code}\n\`\`\``;
83
+ return `\`\`\`\n${decodeHtmlEntities(code)}\n\`\`\``;
61
84
  }
62
85
 
63
86
  case 'delimiter': {
@@ -70,7 +93,7 @@ function editorJsToMarkdown(blocks: OutputBlockData[]): string {
70
93
  }
71
94
  }
72
95
  } catch (error) {
73
- logger.error({ message: 'Error converting EditorJS blocks to markdown', error, block });
96
+ logger.error({ msg: 'Error converting EditorJS blocks to markdown', error, block });
74
97
  throw error;
75
98
  }
76
99
  })
@@ -112,7 +135,7 @@ function loadPlaybooksFromDirectories(directories: string[]): Playbook[] {
112
135
 
113
136
  for (const directory of directories) {
114
137
  if (!fs.existsSync(directory)) {
115
- logger.info(`Playbooks directory does not exist: ${directory}`);
138
+ logger.info({ msg: `Playbooks directory does not exist: ${directory}` });
116
139
  continue;
117
140
  }
118
141
 
@@ -125,12 +148,12 @@ function loadPlaybooksFromDirectories(directories: string[]): Playbook[] {
125
148
 
126
149
  if (playbook && playbook.name && playbook.blocks) {
127
150
  playbooks.push(playbook);
128
- logger.info(`Loaded playbook: ${playbook.name} from ${file}`);
151
+ logger.info({ msg: `Loaded playbook: ${playbook.name} from ${file}` });
129
152
  } else {
130
- logger.warn(`Invalid playbook structure in ${file}`);
153
+ logger.warn({ msg: `Invalid playbook structure in ${file}` });
131
154
  }
132
155
  } catch (error) {
133
- logger.error(`Failed to load playbook file ${file}: ${error}`);
156
+ logger.error({ msg: `Failed to load playbook file ${file}: ${error}` });
134
157
  }
135
158
  }
136
159
  }
@@ -173,4 +196,4 @@ export function combinePlaybooks(playbooks: Playbook[]): string {
173
196
 
174
197
  const combinedPlaybooks = sections.join('\n\n');
175
198
  return combinedPlaybooks;
176
- }
199
+ }