@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,141 +0,0 @@
1
- import { BaseChatModel } from '@langchain/core/language_models/chat_models';
2
- import { BaseMessage } from '@langchain/core/messages';
3
- import { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';
4
- import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
5
- import { logger } from '../../utils/logger';
6
-
7
- export interface BaseParallelChatFields {
8
- /**
9
- * Number of parallel requests to make. Defaults to 1 (no parallelization).
10
- * When > 1, multiple identical requests are sent and the fastest response is used.
11
- */
12
- numParallelRequests?: number;
13
-
14
- /**
15
- * Whether to log timing information for parallel requests
16
- */
17
- logTimings?: boolean;
18
- }
19
-
20
- /**
21
- * Creates a wrapped version of a chat model with parallel request capabilities
22
- */
23
- export function createParallelWrapper<T extends BaseChatModel>(model: T, fields?: BaseParallelChatFields): T {
24
- const numParallelRequests = fields?.numParallelRequests || 1;
25
- const logTimings = fields?.logTimings || false;
26
-
27
- // If parallel requests are disabled, return the original model
28
- if (numParallelRequests <= 1) {
29
- return model;
30
- }
31
-
32
- // Helper function that returns a promise that resolves with the second fulfilled promise
33
- const promiseSecondFulfillment = <T>(promises: Promise<T>[]): Promise<T> => {
34
- return new Promise((resolve) => {
35
- let fulfillCount = 0;
36
-
37
- for (const p of promises) {
38
- Promise.resolve(p)
39
- .then((value) => {
40
- fulfillCount++;
41
- if (fulfillCount === 2) {
42
- resolve(value);
43
- }
44
- })
45
- .catch(() => {
46
- // Ignoring rejections for second fulfillment tracking
47
- });
48
- }
49
- });
50
- };
51
-
52
- // Store original methods
53
- const originalGenerate = model._generate.bind(model);
54
- const originalStream = model._streamResponseChunks.bind(model);
55
-
56
- // Override _generate
57
- model._generate = async function (messages: BaseMessage[], options?: any, runManager?: CallbackManagerForLLMRun): Promise<ChatResult> {
58
- const startTime = Date.now();
59
-
60
- // Create array of identical requests
61
- const requests = Array.from({ length: numParallelRequests }, () => originalGenerate(messages, options, runManager));
62
-
63
- let fastestRequestTime = 0;
64
- let secondFastestRequestTime = 0;
65
-
66
- // Race all requests and return the fastest
67
- const racePromise = Promise.race(requests).then((result) => {
68
- fastestRequestTime = (Date.now() - startTime) / 1000.0;
69
-
70
- if (logTimings) {
71
- logger.debug({
72
- msg: '[Model] Fastest request completed',
73
- requestTime: fastestRequestTime,
74
- numParallelRequests: numParallelRequests,
75
- });
76
- }
77
-
78
- return result;
79
- });
80
-
81
- // Track second fastest if we have 3+ requests
82
- if (requests.length >= 3) {
83
- promiseSecondFulfillment(requests)
84
- .then(() => {
85
- secondFastestRequestTime = (Date.now() - startTime) / 1000.0;
86
- })
87
- .catch(() => {
88
- // Ignore errors in timing tracking
89
- });
90
- }
91
-
92
- // Track all completion times if we have 2+ requests
93
- if (requests.length >= 2 && logTimings) {
94
- Promise.all(requests)
95
- .then(() => {
96
- const allFinishTime = (Date.now() - startTime) / 1000.0;
97
- const timeSaved = allFinishTime - fastestRequestTime;
98
- const timeSavedFromSecond = secondFastestRequestTime > 0 ? secondFastestRequestTime - fastestRequestTime : 0;
99
-
100
- logger.debug({
101
- msg: '[Model] Time saved using parallel requests',
102
- fastestRequestTime,
103
- secondFastestRequestTime: secondFastestRequestTime || 'N/A',
104
- allFinishTime,
105
- timeSaved,
106
- timeSavedFromSecond,
107
- numParallelRequests: numParallelRequests,
108
- });
109
- })
110
- .catch(() => {
111
- // Ignore errors in timing tracking
112
- });
113
- }
114
-
115
- return racePromise;
116
- };
117
-
118
- // Override _streamResponseChunks
119
- model._streamResponseChunks = async function* (
120
- messages: BaseMessage[],
121
- options?: any,
122
- runManager?: CallbackManagerForLLMRun,
123
- ): AsyncGenerator<ChatGenerationChunk> {
124
- // For streaming, we'll use the original implementation
125
- // Parallel streaming is more complex and may not provide the same benefits
126
- if (numParallelRequests > 1 && logTimings) {
127
- logger.debug({
128
- msg: '[Model] Streaming mode - using single request',
129
- reason: 'Parallel streaming not implemented',
130
- });
131
- }
132
-
133
- yield* originalStream(messages, options, runManager);
134
- };
135
-
136
- // Add properties for testing
137
- (model as any).numParallelRequests = numParallelRequests;
138
- (model as any).logTimings = logTimings;
139
-
140
- return model;
141
- }
@@ -1,103 +0,0 @@
1
- import { v4 as uuidv4 } from 'uuid';
2
- import * as mindedConnection from '../mindedConnection';
3
- import { mindedConnectionSocketMessageType, OnPiiHttpRequest, OnPiiHttpResponse } from '../mindedConnectionTypes';
4
- import { HttpRequestConfig, HttpResponse, PIIGatewayInstance } from './types';
5
- import { logger } from '../../utils/logger';
6
-
7
- export class PIIGateway implements PIIGatewayInstance {
8
- constructor() {
9
- // No longer needs mindedConnection as parameter
10
- }
11
-
12
- private async makeRequest<T = any>(
13
- sessionId: string,
14
- method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS',
15
- url: string,
16
- data?: any,
17
- config?: HttpRequestConfig,
18
- ): Promise<HttpResponse<T>> {
19
- if (!mindedConnection.isConnected()) {
20
- throw new Error('Minded connection is not established. PII-secured HTTP requests require a connection to the Minded platform.');
21
- }
22
-
23
- try {
24
- const requestId = uuidv4();
25
- const requestPayload: OnPiiHttpRequest = {
26
- type: mindedConnectionSocketMessageType.PII_HTTP_REQUEST,
27
- requestId,
28
- method,
29
- url,
30
- headers: config?.headers as Record<string, string>,
31
- params: config?.params,
32
- data,
33
- sessionId,
34
- };
35
-
36
- const response = await mindedConnection.awaitEmit<OnPiiHttpRequest, OnPiiHttpResponse>(
37
- mindedConnectionSocketMessageType.PII_HTTP_REQUEST,
38
- requestPayload,
39
- 30000, // 30 second timeout for HTTP requests
40
- );
41
-
42
- if (response.error) {
43
- throw new Error(`HTTP request failed: ${response.error}`);
44
- }
45
-
46
- // Verify that the response requestId matches our request
47
- if (response.requestId && response.requestId !== requestId) {
48
- logger.warn(`Response requestId (${response.requestId}) does not match request requestId (${requestId})`);
49
- }
50
-
51
- // Return generic HttpResponse format
52
- return {
53
- data: response.data,
54
- status: response.status || 200,
55
- statusText: response.statusText || 'OK',
56
- headers: response.headers || {},
57
- config: config || {},
58
- };
59
- } catch (error) {
60
- logger.error({ msg: 'Secure HTTP request failed', error });
61
- return {
62
- data: undefined as T,
63
- status: 500,
64
- statusText: 'Internal Server Error',
65
- headers: {},
66
- config: config || {},
67
- };
68
- }
69
- }
70
-
71
- async get<T = any>(sessionId: string, url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
72
- return this.makeRequest<T>(sessionId, 'GET', url, undefined, config);
73
- }
74
-
75
- async post<T = any>(sessionId: string, url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
76
- return this.makeRequest<T>(sessionId, 'POST', url, data, config);
77
- }
78
-
79
- async put<T = any>(sessionId: string, url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
80
- return this.makeRequest<T>(sessionId, 'PUT', url, data, config);
81
- }
82
-
83
- async delete<T = any>(sessionId: string, url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
84
- return this.makeRequest<T>(sessionId, 'DELETE', url, undefined, config);
85
- }
86
-
87
- async patch<T = any>(sessionId: string, url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
88
- return this.makeRequest<T>(sessionId, 'PATCH', url, data, config);
89
- }
90
-
91
- async head<T = any>(sessionId: string, url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
92
- return this.makeRequest<T>(sessionId, 'HEAD', url, undefined, config);
93
- }
94
-
95
- async options<T = any>(sessionId: string, url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>> {
96
- return this.makeRequest<T>(sessionId, 'OPTIONS', url, undefined, config);
97
- }
98
-
99
- async request<T = any>(sessionId: string, config: HttpRequestConfig): Promise<HttpResponse<T>> {
100
- const method = (config.method?.toUpperCase() || 'GET') as any;
101
- return this.makeRequest<T>(sessionId, method, config.url || '', config.data, config);
102
- }
103
- }
@@ -1,5 +0,0 @@
1
- // Export types
2
- export type { HttpRequestConfig, HttpResponse, PIIGatewayInstance } from './types';
3
-
4
- // Export core gateway class and creation function
5
- export { PIIGateway } from './gateway';
@@ -1,29 +0,0 @@
1
- // Generic HTTP types (library-agnostic)
2
- export interface HttpRequestConfig {
3
- method?: string;
4
- url?: string;
5
- headers?: Record<string, string>;
6
- params?: Record<string, any>;
7
- data?: any;
8
- timeout?: number;
9
- [key: string]: any; // Allow additional properties for extensibility
10
- }
11
-
12
- export interface HttpResponse<T = any> {
13
- data: T;
14
- status: number;
15
- statusText: string;
16
- headers: Record<string, string>;
17
- config: HttpRequestConfig;
18
- }
19
-
20
- export interface PIIGatewayInstance {
21
- get<T = any>(sessionId: string, url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
22
- post<T = any>(sessionId: string, url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
23
- put<T = any>(sessionId: string, url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
24
- delete<T = any>(sessionId: string, url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
25
- patch<T = any>(sessionId: string, url: string, data?: any, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
26
- head<T = any>(sessionId: string, url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
27
- options<T = any>(sessionId: string, url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
28
- request<T = any>(sessionId: string, config: HttpRequestConfig): Promise<HttpResponse<T>>;
29
- }
@@ -1,56 +0,0 @@
1
- /**
2
- * Parses attachments from a trigger body and formats them as a string
3
- * @param triggerBody - The trigger body containing potential attachments
4
- * @returns Formatted string of attachments or empty string if no attachments
5
- */
6
- export const parseAttachments = (triggerBody: any): string => {
7
- // Check if triggerBody has attachments in meta
8
- const attachments = triggerBody?.meta?.attachments;
9
-
10
- if (!attachments || !Array.isArray(attachments) || attachments.length === 0) {
11
- return '';
12
- }
13
-
14
- // Format attachments
15
- const attachmentStrings = attachments
16
- .map((attachment: any) => {
17
- const lines: string[] = [];
18
-
19
- if (attachment.originalname) {
20
- lines.push(`originalName: ${attachment.originalname}`);
21
- } else if (attachment.name) {
22
- lines.push(`originalName: ${attachment.name}`);
23
- }
24
-
25
- if (attachment.path) {
26
- lines.push(`localPath: ${attachment.path}`);
27
- }
28
-
29
- return lines.join('\n');
30
- })
31
- .filter((str) => str.length > 0);
32
-
33
- if (attachmentStrings.length === 0) {
34
- return '';
35
- }
36
-
37
- return 'Attachments:\n' + attachmentStrings.join('\n\n');
38
- };
39
-
40
- /**
41
- * Combines content with attachments string
42
- * @param content - The main content string
43
- * @param attachmentsString - The formatted attachments string
44
- * @returns Combined content with attachments
45
- */
46
- export const combineContentWithAttachments = (content: string, attachmentsString: string): string => {
47
- if (!attachmentsString) {
48
- return content;
49
- }
50
-
51
- if (!content) {
52
- return attachmentsString;
53
- }
54
-
55
- return `${content}\n${attachmentsString}`;
56
- };
@@ -1,209 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import * as yaml from 'js-yaml';
4
- import * as ejs from 'ejs';
5
- import * as mindedConnection from '../platform/mindedConnection';
6
- import { mindedConnectionSocketMessageType } from '../platform/mindedConnectionTypes';
7
- import { getConfig } from '../platform/config';
8
- import { logger } from '../utils/logger';
9
- import { OutputBlockData } from '@editorjs/editorjs';
10
-
11
- export type Playbook = {
12
- id: string;
13
- name: string;
14
- blocks: OutputBlockData[];
15
- };
16
-
17
- /**
18
- * Convert EditorJS blocks to markdown
19
- */
20
- function editorJsToMarkdown(blocks: OutputBlockData[]): string {
21
- if (!blocks || blocks.length === 0) {
22
- return '';
23
- }
24
-
25
- return blocks
26
- .map((block) => {
27
- try {
28
- switch (block.type) {
29
- case 'header': {
30
- const level = block.data?.level || 1;
31
- const headerPrefix = '#'.repeat(level);
32
- return `${headerPrefix} ${block.data?.text || ''}`;
33
- }
34
-
35
- case 'paragraph': {
36
- return block.data?.text || '';
37
- }
38
-
39
- case 'list': {
40
- const items = block.data?.items || [];
41
- const style = block.data?.style || 'unordered';
42
- return items
43
- .map((item: string, index: number) => {
44
- if (style === 'ordered') {
45
- return `${index + 1}. ${item}`;
46
- } else {
47
- return `- ${item}`;
48
- }
49
- })
50
- .join('\n');
51
- }
52
-
53
- case 'quote': {
54
- const text = block.data?.text || '';
55
- const caption = block.data?.caption ? `\n*${block.data.caption}*` : '';
56
- return `> ${text}${caption}`;
57
- }
58
-
59
- case 'code': {
60
- const code = block.data?.code || '';
61
- return `\`\`\`\n${code}\n\`\`\``;
62
- }
63
-
64
- case 'delimiter': {
65
- return '---';
66
- }
67
-
68
- default: {
69
- logger.warn(`Unknown playbook block type: ${block.type}`);
70
- return '';
71
- }
72
- }
73
- } catch (error) {
74
- logger.error({ message: 'Error converting EditorJS blocks to markdown', error, block });
75
- throw error;
76
- }
77
- })
78
- .join('\n\n');
79
- }
80
-
81
- /**
82
- * Load playbooks from directories or platform
83
- */
84
- export async function loadPlaybooks(playbooksDirectories?: string[]): Promise<Playbook[]> {
85
- const { env, isDeployed } = getConfig();
86
- let playbooks: Playbook[] = [];
87
-
88
- if (['sandbox-staging', 'sandbox'].includes(env) && isDeployed && mindedConnection.isConnected()) {
89
- // Load from platform
90
- const response = await mindedConnection.awaitEmit<object, { playbooks?: Playbook[]; error?: string }>(
91
- mindedConnectionSocketMessageType.GET_PLAYBOOKS,
92
- {},
93
- );
94
-
95
- if (response?.error) {
96
- throw new Error(`Failed to load playbooks from platform: ${response.error}`);
97
- }
98
-
99
- playbooks = response?.playbooks || [];
100
- } else if (playbooksDirectories) {
101
- // Load from directories
102
- playbooks = loadPlaybooksFromDirectories(playbooksDirectories);
103
- }
104
-
105
- return playbooks;
106
- }
107
-
108
- /**
109
- * Load playbooks from local directories
110
- */
111
- function loadPlaybooksFromDirectories(directories: string[]): Playbook[] {
112
- const playbooks: Playbook[] = [];
113
-
114
- for (const directory of directories) {
115
- if (!fs.existsSync(directory)) {
116
- logger.info(`Playbooks directory does not exist: ${directory}`);
117
- continue;
118
- }
119
-
120
- const files = getAllYamlFiles(directory);
121
-
122
- for (const file of files) {
123
- try {
124
- const fileContent = fs.readFileSync(file, 'utf8');
125
- const playbook = yaml.load(fileContent) as Playbook;
126
-
127
- if (playbook && playbook.name && playbook.blocks) {
128
- playbooks.push(playbook);
129
- logger.info(`Loaded playbook: ${playbook.name} from ${file}`);
130
- } else {
131
- logger.warn(`Invalid playbook structure in ${file}`);
132
- }
133
- } catch (error) {
134
- logger.error(`Failed to load playbook file ${file}: ${error}`);
135
- }
136
- }
137
- }
138
-
139
- return playbooks;
140
- }
141
-
142
- /**
143
- * Recursively get all YAML files in a directory
144
- */
145
- function getAllYamlFiles(dir: string): string[] {
146
- const files: string[] = [];
147
- const entries = fs.readdirSync(dir, { withFileTypes: true });
148
-
149
- for (const entry of entries) {
150
- const fullPath = path.join(dir, entry.name);
151
- if (entry.isDirectory()) {
152
- files.push(...getAllYamlFiles(fullPath));
153
- } else if (entry.name.endsWith('.yaml') || entry.name.endsWith('.yml')) {
154
- files.push(fullPath);
155
- }
156
- }
157
-
158
- return files;
159
- }
160
-
161
- /**
162
- * Compile playbooks into a single string with EJS and placeholders
163
- */
164
- export function compilePlaybooks(playbooks: Playbook[], params: Record<string, any> = {}): string {
165
- if (playbooks.length === 0) {
166
- return '';
167
- }
168
-
169
- // Combine all playbooks into sections
170
- const sections = playbooks.map((playbook) => {
171
- const markdownContent = editorJsToMarkdown(playbook.blocks);
172
- return `# ${playbook.name}\n${markdownContent}`;
173
- });
174
-
175
- const combinedPlaybooks = sections.join('\n\n');
176
-
177
- try {
178
- // First, render with EJS
179
- let compiledPlaybooks = ejs.render(combinedPlaybooks, params);
180
-
181
- // Then, replace placeholders in {} format
182
- compiledPlaybooks = replacePlaceholders(compiledPlaybooks, params);
183
-
184
- return compiledPlaybooks;
185
- } catch (error) {
186
- logger.error({ message: 'Error compiling playbooks', error });
187
- return combinedPlaybooks; // Return uncompiled if there's an error
188
- }
189
- }
190
-
191
- /**
192
- * Replace placeholders in {key} format
193
- */
194
- function replacePlaceholders(text: string, params: Record<string, any>): string {
195
- return text.replace(/\{([^}]+)\}/g, (match, key) => {
196
- const keys = key.split('.');
197
- let value: any = params;
198
-
199
- for (const k of keys) {
200
- if (value && typeof value === 'object' && k in value) {
201
- value = value[k];
202
- } else {
203
- return match; // Return original if key not found
204
- }
205
- }
206
-
207
- return String(value);
208
- });
209
- }
@@ -1,6 +0,0 @@
1
- import * as parseDocument from './parseDocument';
2
-
3
- // Export all tools as a collection for easy discovery
4
- export const tools = {
5
- 'minded-parse-documents': parseDocument,
6
- };
@@ -1,136 +0,0 @@
1
- import { z } from 'zod';
2
- import { Tool } from '../types/Tools.types';
3
- import { extractFromDocument } from '../internalTools/documentExtraction/documentExtraction';
4
- import { logger } from '../utils/logger';
5
-
6
- // Schema for the tool - these are the parameters that can be inferred by LLM
7
- export const schema = z.object({
8
- // Document source parameters - only one should be provided based on loadFrom setting
9
- documentPath: z.string().optional().nullable().describe('Path to the document file to parse (when loadFrom is "path")'),
10
- documentContent: z
11
- .union([z.instanceof(Buffer), z.string()])
12
- .optional()
13
- .nullable()
14
- .describe('Document content as Buffer or string (when loadFrom is "buffer" or "string")'),
15
- documentUrl: z.string().optional().nullable().describe('URL to fetch the document from (when loadFrom is "url")'),
16
-
17
- // Processing parameters - these can be predefined in the UI
18
- extractRaw: z.boolean().optional().nullable().describe('Extract raw text without AI processing'),
19
- schema: z.any().optional().nullable().describe('Zod schema for structured data extraction (when not extracting raw)'),
20
-
21
- // Load source indicator - this would be set from UI
22
- loadFrom: z.enum(['url', 'path', 'buffer', 'string']).optional().nullable().describe('Source type for the document'),
23
- systemPrompt: z.string().optional().nullable().describe('Prompt for guiding extraction (when not using schema or extracting raw)'),
24
- });
25
-
26
- const parseDocumentTool: Tool<typeof schema, any> = {
27
- name: 'minded-parse-documents',
28
- description:
29
- 'Parse and extract data from documents (PDFs, images, Word docs, etc.). Supports multiple input sources (URL, file path, buffer, or string) and can extract raw text, structured data with a schema, or unstructured data with a prompt. Parameters can be predefined in the flow configuration.',
30
- input: schema,
31
- isGlobal: false,
32
- execute: async ({ input, state, agent }) => {
33
- // The input here will be the combined input from both LLM and UI properties
34
- const combinedInput = input as z.infer<typeof schema>;
35
-
36
- logger.info({
37
- msg: '*Action: Parse document*',
38
- sessionId: state.sessionId,
39
- loadFrom: combinedInput.loadFrom,
40
- hasPath: !!combinedInput.documentPath,
41
- hasContent: !!combinedInput.documentContent,
42
- hasUrl: !!combinedInput.documentUrl,
43
- hasSchema: !!combinedInput.schema,
44
- hasPrompt: !!combinedInput.systemPrompt,
45
- extractRaw: combinedInput.extractRaw,
46
- });
47
-
48
- try {
49
- // Validate document source based on loadFrom parameter
50
- if (combinedInput.loadFrom) {
51
- switch (combinedInput.loadFrom) {
52
- case 'url':
53
- if (!combinedInput.documentUrl) {
54
- throw new Error('documentUrl is required when loadFrom is "url"');
55
- }
56
- break;
57
- case 'path':
58
- if (!combinedInput.documentPath) {
59
- throw new Error('documentPath is required when loadFrom is "path"');
60
- }
61
- break;
62
- case 'buffer':
63
- case 'string':
64
- if (!combinedInput.documentContent) {
65
- throw new Error('documentContent is required when loadFrom is "buffer" or "string"');
66
- }
67
- break;
68
- }
69
- } else {
70
- // Fallback to original validation if loadFrom is not specified
71
- if (!combinedInput.documentPath && !combinedInput.documentContent && !combinedInput.documentUrl) {
72
- throw new Error('At least one document source must be provided: documentPath, documentContent, or documentUrl');
73
- }
74
- }
75
-
76
- // Prepare extraction options, filtering out null/undefined values
77
- const extractionOptions: Parameters<typeof extractFromDocument>[0] = {};
78
-
79
- if (combinedInput.documentPath) {
80
- extractionOptions.documentPath = combinedInput.documentPath;
81
- }
82
- if (combinedInput.documentContent) {
83
- extractionOptions.documentContent = combinedInput.documentContent;
84
- }
85
- if (combinedInput.documentUrl) {
86
- extractionOptions.documentUrl = combinedInput.documentUrl;
87
- }
88
-
89
- // Only include LLM if not extracting raw text
90
- if (!combinedInput.extractRaw) {
91
- extractionOptions.llm = agent.llm;
92
-
93
- // Include schema or system prompt if provided
94
- if (combinedInput.schema) {
95
- extractionOptions.schema = combinedInput.schema;
96
- } else if (combinedInput.systemPrompt) {
97
- extractionOptions.systemPrompt = combinedInput.systemPrompt;
98
- }
99
- }
100
-
101
- // Extract from document using the SDK's document extraction capabilities
102
- const result = await extractFromDocument(extractionOptions);
103
-
104
- // Return only the extracted data, not the metadata as requested
105
- return {
106
- result: result.data,
107
- state: {
108
- memory: {
109
- lastParsedDocument: {
110
- source: combinedInput.documentPath || combinedInput.documentUrl || 'content',
111
- extractedAt: new Date().toISOString(),
112
- extractedRaw: !!combinedInput.extractRaw,
113
- },
114
- },
115
- },
116
- };
117
- } catch (error) {
118
- logger.error({
119
- msg: 'Failed to parse document',
120
- sessionId: state.sessionId,
121
- error: error instanceof Error ? error.message : String(error),
122
- });
123
-
124
- return {
125
- result: `Failed to parse document: ${error instanceof Error ? error.message : String(error)}`,
126
- state: {
127
- memory: {
128
- documentParsingError: error instanceof Error ? error.message : String(error),
129
- },
130
- },
131
- };
132
- }
133
- },
134
- };
135
-
136
- export default parseDocumentTool;