@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.
- package/dist/agent.d.ts +12 -12
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +37 -13
- package/dist/agent.js.map +1 -1
- package/dist/browserTask/README.md +419 -0
- package/dist/browserTask/browserAgent.py +632 -0
- package/dist/browserTask/captcha_isolated.png +0 -0
- package/dist/browserTask/executeBrowserTask.d.ts +1 -11
- package/dist/browserTask/executeBrowserTask.d.ts.map +1 -1
- package/dist/browserTask/executeBrowserTask.js +67 -170
- package/dist/browserTask/executeBrowserTask.js.map +1 -1
- package/dist/browserTask/executeBrowserTask.ts +79 -0
- package/dist/browserTask/requirements.txt +8 -0
- package/dist/browserTask/setup.sh +144 -0
- package/dist/cli/index.js +103 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/edges/createLogicalRouter.d.ts +3 -1
- package/dist/edges/createLogicalRouter.d.ts.map +1 -1
- package/dist/edges/createLogicalRouter.js +41 -2
- package/dist/edges/createLogicalRouter.js.map +1 -1
- package/dist/edges/edgeFactory.d.ts.map +1 -1
- package/dist/edges/edgeFactory.js +7 -7
- package/dist/edges/edgeFactory.js.map +1 -1
- package/dist/events/AgentEvents.d.ts +19 -1
- package/dist/events/AgentEvents.d.ts.map +1 -1
- package/dist/events/AgentEvents.js +2 -0
- package/dist/events/AgentEvents.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/internalTools/timer.d.ts +3 -3
- package/dist/internalTools/timer.d.ts.map +1 -1
- package/dist/internalTools/timer.js +3 -3
- package/dist/internalTools/timer.js.map +1 -1
- package/dist/nodes/addBrowserTaskNode.d.ts +1 -3
- package/dist/nodes/addBrowserTaskNode.d.ts.map +1 -1
- package/dist/nodes/addBrowserTaskNode.js +54 -186
- package/dist/nodes/addBrowserTaskNode.js.map +1 -1
- package/dist/nodes/nodeFactory.js +1 -1
- package/dist/nodes/nodeFactory.js.map +1 -1
- package/docs/SUMMARY.md +8 -4
- package/docs/low-code-editor/edges.md +4 -0
- package/docs/sdk/debugging.md +342 -0
- package/docs/{platform → sdk}/events.md +168 -1
- package/package.json +12 -5
- package/dist/nodes/addBrowserTaskRunNode.d.ts +0 -13
- package/dist/nodes/addBrowserTaskRunNode.d.ts.map +0 -1
- package/dist/nodes/addBrowserTaskRunNode.js +0 -130
- package/dist/nodes/addBrowserTaskRunNode.js.map +0 -1
- package/src/agent.ts +0 -928
- package/src/browserTask/executeBrowserTask.ts +0 -213
- package/src/checkpointer/checkpointSaverFactory.ts +0 -18
- package/src/cli/index.ts +0 -170
- package/src/cli/lambdaHandlerTemplate.ts +0 -45
- package/src/edges/createDirectEdge.ts +0 -16
- package/src/edges/createLogicalRouter.ts +0 -114
- package/src/edges/createPromptRouter.ts +0 -218
- package/src/edges/edgeFactory.ts +0 -141
- package/src/events/AgentEvents.ts +0 -47
- package/src/events/index.ts +0 -3
- package/src/index.ts +0 -70
- package/src/interfaces/zendesk.ts +0 -157
- package/src/internalTools/appActionRunnerTool.ts +0 -68
- package/src/internalTools/documentExtraction/documentExtraction.ts +0 -809
- package/src/internalTools/documentExtraction/types.ts +0 -59
- package/src/internalTools/libraryActionRunnerTool.ts +0 -63
- package/src/internalTools/retell.ts +0 -28
- package/src/internalTools/sendPlaceholderMessage.ts +0 -27
- package/src/internalTools/timer.ts +0 -137
- package/src/llm/createLlmInstance.ts +0 -33
- package/src/nodes/addAppToolNode.ts +0 -106
- package/src/nodes/addBrowserTaskNode.ts +0 -231
- package/src/nodes/addBrowserTaskRunNode.ts +0 -144
- package/src/nodes/addHumanInTheLoopNode.ts +0 -25
- package/src/nodes/addJumpToNode.ts +0 -25
- package/src/nodes/addJunctionNode.ts +0 -20
- package/src/nodes/addPromptNode.ts +0 -119
- package/src/nodes/addToolNode.ts +0 -72
- package/src/nodes/addToolRunNode.ts +0 -76
- package/src/nodes/addTriggerNode.ts +0 -27
- package/src/nodes/nodeFactory.ts +0 -57
- package/src/platform/config.ts +0 -77
- package/src/platform/mindedCheckpointSaver.ts +0 -146
- package/src/platform/mindedConnection.ts +0 -199
- package/src/platform/mindedConnectionTypes.ts +0 -220
- package/src/platform/models/mindedChatOpenAI.ts +0 -49
- package/src/platform/models/parallelWrapper.ts +0 -141
- package/src/platform/piiGateway/gateway.ts +0 -103
- package/src/platform/piiGateway/index.ts +0 -5
- package/src/platform/piiGateway/types.ts +0 -29
- package/src/platform/utils/parseAttachments.ts +0 -56
- package/src/playbooks/playbooks.ts +0 -209
- package/src/toolsLibrary/index.ts +0 -6
- package/src/toolsLibrary/parseDocument.ts +0 -136
- package/src/triggers/triggerTypeToDefaultMessage.ts +0 -9
- package/src/types/Agent.types.ts +0 -67
- package/src/types/Flows.types.ts +0 -200
- package/src/types/LLM.types.ts +0 -15
- package/src/types/LangGraph.types.ts +0 -53
- package/src/types/Platform.types.ts +0 -1
- package/src/types/Tools.types.ts +0 -31
- package/src/types/Voice.types.ts +0 -4
- package/src/utils/extractStateMemoryResponse.ts +0 -16
- package/src/utils/history.ts +0 -9
- package/src/utils/logger.ts +0 -22
- package/src/utils/wait.ts +0 -1
- package/src/voice/elevenLabsUtils.ts +0 -81
- package/src/voice/voiceSession.ts +0 -294
- /package/docs/{platform → sdk}/logging.md +0 -0
- /package/docs/{platform → sdk}/memory.md +0 -0
- /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,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,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;
|