@minded-ai/mindedjs 1.0.108 → 1.0.109-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 (112) hide show
  1. package/dist/agent.d.ts +12 -12
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +37 -13
  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.d.ts +1 -11
  9. package/dist/browserTask/executeBrowserTask.d.ts.map +1 -1
  10. package/dist/browserTask/executeBrowserTask.js +67 -170
  11. package/dist/browserTask/executeBrowserTask.js.map +1 -1
  12. package/dist/browserTask/executeBrowserTask.ts +79 -0
  13. package/dist/browserTask/requirements.txt +8 -0
  14. package/dist/browserTask/setup.sh +144 -0
  15. package/dist/cli/index.js +103 -1
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/edges/createLogicalRouter.d.ts +3 -1
  18. package/dist/edges/createLogicalRouter.d.ts.map +1 -1
  19. package/dist/edges/createLogicalRouter.js +41 -2
  20. package/dist/edges/createLogicalRouter.js.map +1 -1
  21. package/dist/edges/edgeFactory.d.ts.map +1 -1
  22. package/dist/edges/edgeFactory.js +7 -7
  23. package/dist/edges/edgeFactory.js.map +1 -1
  24. package/dist/events/AgentEvents.d.ts +19 -1
  25. package/dist/events/AgentEvents.d.ts.map +1 -1
  26. package/dist/events/AgentEvents.js +2 -0
  27. package/dist/events/AgentEvents.js.map +1 -1
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +4 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/internalTools/timer.d.ts +3 -3
  33. package/dist/internalTools/timer.d.ts.map +1 -1
  34. package/dist/internalTools/timer.js +3 -3
  35. package/dist/internalTools/timer.js.map +1 -1
  36. package/dist/nodes/addBrowserTaskNode.d.ts +1 -3
  37. package/dist/nodes/addBrowserTaskNode.d.ts.map +1 -1
  38. package/dist/nodes/addBrowserTaskNode.js +54 -186
  39. package/dist/nodes/addBrowserTaskNode.js.map +1 -1
  40. package/dist/nodes/nodeFactory.js +1 -1
  41. package/dist/nodes/nodeFactory.js.map +1 -1
  42. package/docs/SUMMARY.md +8 -4
  43. package/docs/low-code-editor/edges.md +4 -0
  44. package/docs/sdk/debugging.md +342 -0
  45. package/docs/{platform → sdk}/events.md +168 -1
  46. package/package.json +12 -5
  47. package/dist/nodes/addBrowserTaskRunNode.d.ts +0 -13
  48. package/dist/nodes/addBrowserTaskRunNode.d.ts.map +0 -1
  49. package/dist/nodes/addBrowserTaskRunNode.js +0 -130
  50. package/dist/nodes/addBrowserTaskRunNode.js.map +0 -1
  51. package/src/agent.ts +0 -928
  52. package/src/browserTask/executeBrowserTask.ts +0 -213
  53. package/src/checkpointer/checkpointSaverFactory.ts +0 -18
  54. package/src/cli/index.ts +0 -170
  55. package/src/cli/lambdaHandlerTemplate.ts +0 -45
  56. package/src/edges/createDirectEdge.ts +0 -16
  57. package/src/edges/createLogicalRouter.ts +0 -114
  58. package/src/edges/createPromptRouter.ts +0 -218
  59. package/src/edges/edgeFactory.ts +0 -141
  60. package/src/events/AgentEvents.ts +0 -47
  61. package/src/events/index.ts +0 -3
  62. package/src/index.ts +0 -70
  63. package/src/interfaces/zendesk.ts +0 -157
  64. package/src/internalTools/appActionRunnerTool.ts +0 -68
  65. package/src/internalTools/documentExtraction/documentExtraction.ts +0 -809
  66. package/src/internalTools/documentExtraction/types.ts +0 -59
  67. package/src/internalTools/libraryActionRunnerTool.ts +0 -63
  68. package/src/internalTools/retell.ts +0 -28
  69. package/src/internalTools/sendPlaceholderMessage.ts +0 -27
  70. package/src/internalTools/timer.ts +0 -137
  71. package/src/llm/createLlmInstance.ts +0 -33
  72. package/src/nodes/addAppToolNode.ts +0 -106
  73. package/src/nodes/addBrowserTaskNode.ts +0 -231
  74. package/src/nodes/addBrowserTaskRunNode.ts +0 -144
  75. package/src/nodes/addHumanInTheLoopNode.ts +0 -25
  76. package/src/nodes/addJumpToNode.ts +0 -25
  77. package/src/nodes/addJunctionNode.ts +0 -20
  78. package/src/nodes/addPromptNode.ts +0 -119
  79. package/src/nodes/addToolNode.ts +0 -72
  80. package/src/nodes/addToolRunNode.ts +0 -76
  81. package/src/nodes/addTriggerNode.ts +0 -27
  82. package/src/nodes/nodeFactory.ts +0 -57
  83. package/src/platform/config.ts +0 -77
  84. package/src/platform/mindedCheckpointSaver.ts +0 -146
  85. package/src/platform/mindedConnection.ts +0 -199
  86. package/src/platform/mindedConnectionTypes.ts +0 -220
  87. package/src/platform/models/mindedChatOpenAI.ts +0 -49
  88. package/src/platform/models/parallelWrapper.ts +0 -141
  89. package/src/platform/piiGateway/gateway.ts +0 -103
  90. package/src/platform/piiGateway/index.ts +0 -5
  91. package/src/platform/piiGateway/types.ts +0 -29
  92. package/src/platform/utils/parseAttachments.ts +0 -56
  93. package/src/playbooks/playbooks.ts +0 -209
  94. package/src/toolsLibrary/index.ts +0 -6
  95. package/src/toolsLibrary/parseDocument.ts +0 -136
  96. package/src/triggers/triggerTypeToDefaultMessage.ts +0 -9
  97. package/src/types/Agent.types.ts +0 -67
  98. package/src/types/Flows.types.ts +0 -200
  99. package/src/types/LLM.types.ts +0 -15
  100. package/src/types/LangGraph.types.ts +0 -53
  101. package/src/types/Platform.types.ts +0 -1
  102. package/src/types/Tools.types.ts +0 -31
  103. package/src/types/Voice.types.ts +0 -4
  104. package/src/utils/extractStateMemoryResponse.ts +0 -16
  105. package/src/utils/history.ts +0 -9
  106. package/src/utils/logger.ts +0 -22
  107. package/src/utils/wait.ts +0 -1
  108. package/src/voice/elevenLabsUtils.ts +0 -81
  109. package/src/voice/voiceSession.ts +0 -294
  110. /package/docs/{platform → sdk}/logging.md +0 -0
  111. /package/docs/{platform → sdk}/memory.md +0 -0
  112. /package/docs/{platform → sdk}/parallel-llm.md +0 -0
@@ -1,59 +0,0 @@
1
- import { ZodType as ZodSchema, ZodTypeAny } from 'zod';
2
-
3
- export interface DocumentProcessorConfig {
4
- llamaCloudApiKey?: string;
5
- useBase64?: boolean;
6
- maxImageWidth?: number;
7
- imageQuality?: number;
8
- }
9
- export interface DocumentExtractionOptions {
10
- documentPath?: string;
11
- documentContent?: Buffer | string;
12
- documentUrl?: string;
13
- schema?: ZodSchema<any> | ZodTypeAny;
14
- llmConfig?: {
15
- model?: string;
16
- temperature?: number;
17
- };
18
- systemPrompt?: string;
19
- }
20
- export interface DocumentProcessingResult<T = any> {
21
- data: T;
22
- metadata: {
23
- fileSize?: number;
24
- fileType: string;
25
- processingTime: number;
26
- contentLength: number;
27
- };
28
- }
29
- export const SUPPORTED_DOCUMENT_TYPES = [
30
- // Images
31
- '.jpg',
32
- '.jpeg',
33
- '.png',
34
- '.gif',
35
- '.bmp',
36
- '.webp',
37
- '.tiff',
38
- // Documents
39
- '.pdf',
40
- '.doc',
41
- '.docx',
42
- '.txt',
43
- '.rtf',
44
- '.odt',
45
- // Spreadsheets
46
- '.xls',
47
- '.xlsx',
48
- '.csv',
49
- '.ods',
50
- // Presentations
51
- '.ppt',
52
- '.pptx',
53
- '.odp',
54
- // Other formats
55
- '.html',
56
- '.htm',
57
- '.md',
58
- '.xml',
59
- ];
@@ -1,63 +0,0 @@
1
- import { Tool, ToolExecuteInput } from '../types/Tools.types';
2
- import { tools } from '../toolsLibrary';
3
- import { logger } from '../utils/logger';
4
-
5
- const libraryActionRunnerToolCreator = (actionKey: string, nodeTitle: string): Tool<any, any> => {
6
- // Find the corresponding library tool by key name (e.g., "parseDocument")
7
- const libraryTool = (tools as any)[actionKey];
8
-
9
- if (!libraryTool?.default) {
10
- throw new Error(`Library tool '${actionKey}' not found in toolsLibrary`);
11
- }
12
-
13
- if (!libraryTool.schema) {
14
- throw new Error(`Schema not found for library tool '${actionKey}'. Make sure the tool exports a 'schema' object.`);
15
- }
16
-
17
- const zodSchema = libraryTool.schema;
18
-
19
- // Create a description using the library tool's own description
20
- const description = libraryTool.default.description || `Run ${nodeTitle} action from Minded Tools library.`;
21
-
22
- const tool = {
23
- name: nodeTitle,
24
- description,
25
- input: zodSchema,
26
- execute: async ({ input, state, agent }: ToolExecuteInput<typeof zodSchema>) => {
27
- try {
28
- // Find the corresponding library tool
29
- const libraryTool = Object.values(tools).find((toolModule) => toolModule.default && toolModule.default.name === actionKey);
30
-
31
- if (!libraryTool?.default) {
32
- throw new Error(`Library tool '${actionKey}' not found in toolsLibrary`);
33
- }
34
-
35
- logger.debug({
36
- msg: `[Tool] Executing library tool`,
37
- toolName: actionKey,
38
- nodeTitle,
39
- });
40
-
41
- // Execute the library tool directly
42
- const result = await libraryTool.default.execute({ input, state, agent });
43
-
44
- return {
45
- state: result?.state,
46
- result: result?.result,
47
- };
48
- } catch (error) {
49
- logger.error({
50
- msg: `[Tool] Error executing library tool`,
51
- error,
52
- toolName: actionKey,
53
- nodeTitle,
54
- });
55
- throw error;
56
- }
57
- },
58
- };
59
-
60
- return tool;
61
- };
62
-
63
- export default libraryActionRunnerToolCreator;
@@ -1,28 +0,0 @@
1
- import * as mindedConnection from '../platform/mindedConnection';
2
- import { mindedConnectionSocketMessageType, TimerResetResponse, RetellGetCallResponse } from '../platform/mindedConnectionTypes';
3
-
4
- export async function retellCall({
5
- sessionId,
6
- callName,
7
- callAgentId,
8
- vars = {},
9
- }: {
10
- sessionId: string;
11
- callName: string;
12
- callAgentId: string;
13
- vars?: Record<string, any>;
14
- }): Promise<TimerResetResponse> {
15
- return await mindedConnection.awaitEmit(mindedConnectionSocketMessageType.RETELL_CALL, {
16
- sessionId,
17
- callName,
18
- callAgentId,
19
- vars,
20
- });
21
- }
22
-
23
- export async function retellGetCall({ sessionId, callId }: { sessionId: string; callId: string }): Promise<RetellGetCallResponse> {
24
- return await mindedConnection.awaitEmit(mindedConnectionSocketMessageType.RETELL_GET_CALL, {
25
- sessionId,
26
- callId,
27
- });
28
- }
@@ -1,27 +0,0 @@
1
- import * as mindedConnection from '../platform/mindedConnection';
2
- import { mindedConnectionSocketMessageType } from '../platform/mindedConnectionTypes';
3
-
4
- /**
5
- * Send a placeholder message to the dashboard voice session.
6
- * This is typically used for voice sessions to provide immediate feedback to users.
7
- *
8
- * @param params - The parameters for sending the placeholder message
9
- * @param params.sessionId - The session ID of the voice session
10
- * @param params.message - The placeholder message to send
11
- * @throws {Error} When the Minded connection is not established
12
- */
13
- export async function sendPlaceholderMessage(params: { sessionId: string; message: string }): Promise<void> {
14
- const { sessionId, message } = params;
15
-
16
- if (!mindedConnection.isConnected()) {
17
- throw new Error('Minded connection is not established when trying to send placeholder message');
18
- }
19
-
20
- const connection = mindedConnection;
21
- connection.emit(mindedConnectionSocketMessageType.DASHBOARD_VOICE_PLACEHOLDER_MESSAGES, {
22
- sessionId,
23
- message,
24
- timestamp: Date.now(),
25
- type: mindedConnectionSocketMessageType.DASHBOARD_VOICE_PLACEHOLDER_MESSAGES,
26
- });
27
- }
@@ -1,137 +0,0 @@
1
- import * as mindedConnection from '../platform/mindedConnection';
2
- import { mindedConnectionSocketMessageType, TimerResetResponse, TimerCancelResponse } from '../platform/mindedConnectionTypes';
3
-
4
- // Store timer handlers by timer name
5
- export const timerHandlers = new Map<string, Array<{
6
- handler: (params: { sessionId: string; payload: Record<string, any> }) => void | Promise<void>;
7
- }>>();
8
-
9
- /**
10
- * Reset or set a timer for a specific session.
11
- * When the timer expires, all registered timer handlers will be called.
12
- *
13
- * @param params - The timer configuration
14
- * @param params.sessionId - The session ID to associate the timer with
15
- * @param params.seconds - Number of seconds until the timer expires
16
- * @param params.timerName - Unique name for this timer (used for cancellation and identification)
17
- * @param params.eventArgs - Additional data to pass to the timer handler when it triggers
18
- * @returns Promise resolving to timer reset response
19
- * @throws {Error} When the Minded connection is not established
20
- *
21
- * @example
22
- * ```typescript
23
- * import { resetTimer } from '@minded-ai/mindedjs';
24
- *
25
- * // Set a timer to follow up in 10 seconds
26
- * await resetTimer({
27
- * sessionId: 'session-123',
28
- * seconds: 10,
29
- * timerName: 'followup',
30
- * payload: {
31
- * message: 'Are you still there?'
32
- * }
33
- * });
34
- * ```
35
- */
36
- export async function resetTimer({
37
- sessionId,
38
- seconds,
39
- timerName,
40
- payload = {}
41
- }: {
42
- sessionId: string;
43
- seconds: number;
44
- timerName: string;
45
- payload?: Record<string, any>;
46
- }): Promise<TimerResetResponse> {
47
- return await mindedConnection.awaitEmit(mindedConnectionSocketMessageType.TIMER_RESET, {
48
- sessionId,
49
- seconds,
50
- timerName,
51
- eventArgs: payload,
52
- });
53
- }
54
-
55
- /**
56
- * Cancel an existing timer for a specific session.
57
- *
58
- * @param sessionId - The session ID the timer is associated with
59
- * @param timerName - The name of the timer to cancel
60
- * @returns Promise resolving to timer cancel response
61
- * @throws {Error} When the Minded connection is not established
62
- *
63
- * @example
64
- * ```typescript
65
- * import { cancelTimer } from '@minded-ai/mindedjs';
66
- *
67
- * // Cancel a previously set timer
68
- * await cancelTimer('session-123', 'followup');
69
- * ```
70
- */
71
- export async function cancelTimer(sessionId: string, timerName: string): Promise<TimerCancelResponse> {
72
- if (!mindedConnection.isConnected()) {
73
- throw new Error('Minded connection is not established when trying to cancel timer');
74
- }
75
- return await mindedConnection.awaitEmit(mindedConnectionSocketMessageType.TIMER_CANCEL, {
76
- sessionId,
77
- timerName,
78
- });
79
- }
80
-
81
- /**
82
- * Register a handler for timer trigger events for a specific timer name.
83
- * The handler will be called when the specified timer expires for any session.
84
- *
85
- * @param params - The configuration for the timer handler
86
- * @param params.timerName - The name of the timer to handle
87
- * @param params.handler - Function to call when the timer triggers
88
- *
89
- * @example
90
- * ```typescript
91
- * import { onTimer } from '@minded-ai/mindedjs';
92
- *
93
- * // Register a handler for the 'followup' timer
94
- * onTimer({
95
- * timerName: 'followup',
96
- * handler: async ({ sessionId, payload }) => {
97
- * console.log(`Followup timer triggered for session ${sessionId}`);
98
- *
99
- * // Handle the followup timer
100
- * await agent.invoke({
101
- * triggerName: 'timerFollowup',
102
- * triggerBody: { message: payload.message },
103
- * sessionId
104
- * });
105
- * }
106
- * });
107
- * ```
108
- */
109
- export function onTimer({
110
- timerName,
111
- handler
112
- }: {
113
- timerName: string;
114
- handler: (params: { sessionId: string; payload: Record<string, any> }) => void | Promise<void>;
115
- }): void {
116
- // Initialize handlers array for this timer name if it doesn't exist
117
- if (!timerHandlers.has(timerName)) {
118
- timerHandlers.set(timerName, []);
119
- }
120
-
121
- // Add the handler to the array for this timer name
122
- const handlers = timerHandlers.get(timerName)!;
123
- handlers.push({ handler });
124
- }
125
-
126
- mindedConnection.on(mindedConnectionSocketMessageType.TIMER_TRIGGER, async (timerTriggerMessage) => {
127
- // Get handlers for the specific timer name
128
- const handlers = timerHandlers.get(timerTriggerMessage.timerName) || [];
129
-
130
- // Call all handlers registered for this timer name
131
- for (const { handler } of handlers) {
132
- await handler({
133
- sessionId: timerTriggerMessage.sessionId,
134
- payload: timerTriggerMessage.eventArgs,
135
- });
136
- }
137
- });
@@ -1,33 +0,0 @@
1
- import { LLMConfig, LLMProviders, LLMProvider } from '../types/LLM.types';
2
- import { createParallelWrapper, BaseParallelChatFields } from '../platform/models/parallelWrapper';
3
-
4
- export const createLlmInstance = (llmConfig: LLMConfig) => {
5
- const { name, properties } = llmConfig;
6
- const LLMClass = LLMProviders[name as LLMProvider];
7
- if (!LLMClass) {
8
- throw new Error(`Unsupported LLM provider: ${name}`);
9
- }
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;
33
- };
@@ -1,106 +0,0 @@
1
- import { AppToolNode, NodeType } from '../types/Flows.types';
2
- import { tool as langchainTool } from '@langchain/core/tools';
3
- import { PreCompiledGraph, stateAnnotation } from '../types/LangGraph.types';
4
- import { SystemMessage } from '@langchain/core/messages';
5
- import { RunnableLike } from '@langchain/core/runnables';
6
- import { z } from 'zod';
7
- import { LLMProviders } from '../types/LLM.types';
8
- import { AppActionInvocationHistoryStep } from '../types/Agent.types';
9
- import { Agent } from '../agent';
10
- import { logger } from '../utils/logger';
11
- import { compilePlaybooks } from '../playbooks/playbooks';
12
- import { createHistoryStep } from '../utils/history';
13
- import { Tool } from '../types/Tools.types';
14
-
15
- export const addAppToolNode = async ({
16
- graph,
17
- node,
18
- llm,
19
- agent,
20
- tools,
21
- }: {
22
- graph: PreCompiledGraph;
23
- node: AppToolNode;
24
- llm: (typeof LLMProviders)[keyof typeof LLMProviders];
25
- agent: Agent;
26
- tools: Tool<any, any>[];
27
- }) => {
28
- const cleanedParameters = Object.fromEntries(Object.entries(node.parameters || {}).filter(([, value]) => value !== ''));
29
-
30
- // Find the tool from the tools array by name
31
- const appRunnerTool = tools.find((tool) => tool.name === node.displayName);
32
-
33
- if (!appRunnerTool) {
34
- throw new Error(`Tool not found for node: ${node.displayName}`);
35
- }
36
-
37
- const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
38
- logger.debug({ msg: `[Node] Executing tool node`, node: appRunnerTool.name });
39
-
40
- const executeWrapper = async (input: z.infer<typeof appRunnerTool.input>) => {
41
- try {
42
- const response = await appRunnerTool.execute({ input, state, agent });
43
- return response || {};
44
- } catch (error) {
45
- logger.error({ msg: `[Node] Error executing tool`, error, node: node.name });
46
- throw error;
47
- }
48
- };
49
- const tool = langchainTool(executeWrapper, {
50
- name: appRunnerTool.name,
51
- description: appRunnerTool.description,
52
- schema: appRunnerTool.input,
53
- });
54
- // Get compiled playbooks with proper parameters
55
- const playbookParams = {
56
- ...state.memory, // Spread memory fields at the top level
57
- currentTime: new Date().toISOString(),
58
- };
59
- const compiledPlaybooks = compilePlaybooks(agent.playbooks, playbookParams) || '';
60
-
61
- const message = `${compiledPlaybooks ? compiledPlaybooks + '\n\n' : ''}
62
- Additional context:
63
- previous messages are available for context.
64
- Your goal is execute the tool with the correct parameters, some of them already chosen by the user and the rest should be generated.
65
- You have 4 things to base your parameters on:
66
- - Previous messages
67
- - Parameters manually configured by the user (if any)
68
- - User instructions for choosing tool parameters that are not set by the user (if any)
69
- - Workflow memory
70
- Parameters manually configured by the user are:
71
- ${JSON.stringify(cleanedParameters)}
72
- User instructions for choosing tool parameters are:
73
- ${node.prompt ? `${node.prompt}` : 'no instructions set by the user'}
74
- Workflow memory is:
75
- ${JSON.stringify(state.memory)}
76
- `;
77
- const AIToolCallMessage = await llm
78
- .bindTools([tool], {
79
- tool_choice: tool.name,
80
- })
81
- .invoke([...state.messages, new SystemMessage(message)]);
82
- AIToolCallMessage.tool_calls[0].args = {
83
- ...AIToolCallMessage.tool_calls[0].args,
84
- ...cleanedParameters, //user set parameters have priority over ai generated parameters
85
- };
86
- const toolCallMessage = await tool.invoke(AIToolCallMessage.tool_calls[0]);
87
- AIToolCallMessage.additional_kwargs = {
88
- mindedMetadata: {
89
- nodeType: NodeType.APP_TOOL,
90
- },
91
- };
92
- return {
93
- goto: null,
94
- messages: [AIToolCallMessage, toolCallMessage],
95
- history: createHistoryStep<AppActionInvocationHistoryStep>(state.history, {
96
- type: NodeType.APP_TOOL,
97
- nodeId: node.name,
98
- nodeDisplayName: node.displayName!,
99
- raw: AIToolCallMessage.tool_calls[0],
100
- appName: node.appName,
101
- messageIds: [AIToolCallMessage.id!],
102
- }),
103
- };
104
- };
105
- graph.addNode(node.name, callback);
106
- };
@@ -1,231 +0,0 @@
1
- import { RunnableLike } from '@langchain/core/runnables';
2
- import { BrowserTaskNode, NodeType } from '../types/Flows.types';
3
- import { PreCompiledGraph, stateAnnotation } from '../types/LangGraph.types';
4
- import { HistoryStep } from '../types/Agent.types';
5
- import { logger } from '../utils/logger';
6
- import { createHistoryStep } from '../utils/history';
7
- import { AIMessage, SystemMessage } from '@langchain/core/messages';
8
- import { v4 as uuidv4 } from 'uuid';
9
- import { Agent } from '../agent';
10
- import { createCloudTask, waitForLiveUrl } from '../browserTask/executeBrowserTask';
11
- import { tool as langchainTool } from '@langchain/core/tools';
12
- import { z } from 'zod';
13
- import { LLMProviders } from '../types/LLM.types';
14
- import { compilePlaybooks } from '../playbooks/playbooks';
15
- import * as ejs from 'ejs';
16
-
17
- /**
18
- * Compile prompt with parameters using EJS and placeholder replacement
19
- */
20
- function compilePrompt(prompt: string, params: Record<string, any> = {}): string {
21
- try {
22
- // First, render with EJS
23
- let compiledPrompt = ejs.render(prompt, params);
24
-
25
- // Then, replace placeholders in {} format
26
- compiledPrompt = replacePlaceholders(compiledPrompt, params);
27
-
28
- return compiledPrompt;
29
- } catch (error) {
30
- logger.error({ message: 'Error compiling prompt', error });
31
- return prompt; // Return uncompiled if there's an error
32
- }
33
- }
34
-
35
- /**
36
- * Replace placeholders in {key} format
37
- */
38
- function replacePlaceholders(text: string, params: Record<string, any>): string {
39
- return text.replace(/\{([^}]+)\}/g, (match, key) => {
40
- const keys = key.split('.');
41
- let value: any = params;
42
-
43
- for (const k of keys) {
44
- if (value && typeof value === 'object' && k in value) {
45
- value = value[k];
46
- } else {
47
- return match; // Return original if key not found
48
- }
49
- }
50
-
51
- return String(value);
52
- });
53
- }
54
-
55
- type AddBrowserTaskNodeParams = {
56
- graph: PreCompiledGraph;
57
- node: BrowserTaskNode;
58
- agent: Agent;
59
- llm: (typeof LLMProviders)[keyof typeof LLMProviders];
60
- };
61
-
62
- export const addBrowserTaskNode = async ({ graph, node, agent, llm }: AddBrowserTaskNodeParams) => {
63
- const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
64
- logger.info({ msg: `Executing browser task node ${node.displayName}`, prompt: node.prompt });
65
-
66
- // Create Zod schema from inputSchema
67
- const schemaFields: Record<string, z.ZodTypeAny> = {};
68
- if (node.inputSchema) {
69
- for (const field of node.inputSchema) {
70
- let fieldSchema: z.ZodTypeAny;
71
-
72
- if (field.type === 'string') {
73
- fieldSchema = z.string();
74
- } else if (field.type === 'number') {
75
- fieldSchema = z.number();
76
- } else {
77
- fieldSchema = z.string(); // Default to string
78
- }
79
-
80
- if (field.description) {
81
- fieldSchema = fieldSchema.describe(field.description);
82
- }
83
-
84
- if (field.required === false) {
85
- fieldSchema = fieldSchema.optional();
86
- }
87
-
88
- schemaFields[field.name] = fieldSchema;
89
- }
90
- }
91
-
92
- const zodSchema = z.object(schemaFields);
93
-
94
- // Create langchain tool
95
- const tool = langchainTool(() => {}, {
96
- name: 'browser-task',
97
- description: node.prompt,
98
- schema: zodSchema,
99
- });
100
-
101
- // Get compiled playbooks
102
- const playbookParams = {
103
- ...state.memory,
104
- state,
105
- currentTime: new Date().toISOString(),
106
- };
107
- const compiledPlaybooks = compilePlaybooks(agent.playbooks, playbookParams) || '';
108
-
109
- const systemPrompt = `${compiledPlaybooks ? compiledPlaybooks + '\n\n' : ''}
110
- Additional context:
111
- - workflow memory: ${JSON.stringify(state.memory)}`;
112
-
113
- try {
114
- // Use LLM to generate tool call
115
- const AIToolCallMessage: AIMessage = await llm
116
- .bindTools([tool], {
117
- tool_choice: tool.name,
118
- })
119
- .invoke([...state.messages, new SystemMessage(systemPrompt)]);
120
-
121
- if (!AIToolCallMessage.tool_calls || AIToolCallMessage.tool_calls.length === 0) {
122
- throw new Error('No tool calls generated by LLM');
123
- }
124
-
125
- const toolCall = AIToolCallMessage.tool_calls[0];
126
- const inputParams = toolCall.args || {};
127
-
128
- // Prepare parameters for prompt compilation
129
- const promptParams = {
130
- input: inputParams,
131
- state,
132
- currentTime: new Date().toISOString(),
133
- };
134
-
135
- // Compile the prompt with parameters
136
- const compiledPrompt = compilePrompt(node.prompt, promptParams);
137
-
138
- // Build the full prompt with compiled content
139
- const fullPrompt = `
140
- Follow the instructions. Any retrieved data should be printed as string and not saved to a file.
141
-
142
- # Task instructions:
143
- ${compiledPrompt}
144
-
145
- ${Object.keys(inputParams).length > 0 ? `# Input parameters:\n${JSON.stringify(inputParams, null, 2)}\n\n` : ''}
146
- ${state.memory ? `# Task context:\n${JSON.stringify(state.memory)}\n\n` : ''}
147
- `;
148
-
149
- // Create the browser task in the cloud
150
- const taskId = await createCloudTask(fullPrompt, node.model);
151
- logger.debug({ msg: 'Browser task created', taskId });
152
-
153
- // Wait for live_url to become available
154
- const taskDetails = await waitForLiveUrl(taskId);
155
- logger.debug({ msg: 'Live URL available', taskId, liveUrl: taskDetails.live_url });
156
-
157
- // Update the tool call with taskId and other metadata
158
- const updatedToolCall = {
159
- ...toolCall,
160
- args: {
161
- ...inputParams,
162
- taskId,
163
- prompt: fullPrompt,
164
- },
165
- };
166
-
167
- const toolCallingMessage = new AIMessage({
168
- id: AIToolCallMessage.id,
169
- content: AIToolCallMessage.content,
170
- tool_calls: [updatedToolCall],
171
- additional_kwargs: {
172
- mindedMetadata: {
173
- nodeType: NodeType.BROWSER_TASK,
174
- nodeDisplayName: node.displayName,
175
- taskId,
176
- liveUrl: taskDetails.live_url,
177
- },
178
- },
179
- });
180
-
181
- return {
182
- history: createHistoryStep<HistoryStep>(state.history, {
183
- type: NodeType.BROWSER_TASK,
184
- nodeId: node.name,
185
- nodeDisplayName: node.displayName,
186
- raw: { taskId, liveUrl: taskDetails.live_url, inputParams },
187
- messageIds: [toolCallingMessage.id!],
188
- }),
189
- messages: [toolCallingMessage],
190
- };
191
- } catch (error: any) {
192
- logger.error(`Error creating browser task node ${node.displayName}: ${error}`);
193
-
194
- const errorMessageId = uuidv4();
195
- const errorToolCallId = uuidv4();
196
-
197
- const toolCallingMessage = new AIMessage({
198
- id: errorMessageId,
199
- content: '',
200
- tool_calls: [
201
- {
202
- id: errorToolCallId,
203
- name: 'browser-task',
204
- args: {
205
- error: error.message,
206
- },
207
- },
208
- ],
209
- additional_kwargs: {
210
- mindedMetadata: {
211
- nodeType: NodeType.BROWSER_TASK,
212
- nodeDisplayName: node.displayName,
213
- error: error.message,
214
- },
215
- },
216
- });
217
-
218
- return {
219
- history: createHistoryStep<HistoryStep>(state.history, {
220
- type: NodeType.BROWSER_TASK,
221
- nodeId: node.name,
222
- nodeDisplayName: node.displayName,
223
- raw: error,
224
- messageIds: [errorMessageId],
225
- }),
226
- messages: [toolCallingMessage],
227
- };
228
- }
229
- };
230
- graph.addNode(node.name, callback);
231
- };