@minded-ai/mindedjs 1.0.102 → 1.0.103-beta-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +4 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +76 -30
- package/dist/agent.js.map +1 -1
- package/dist/checkpointer/checkpointSaverFactory.js +1 -1
- package/dist/checkpointer/checkpointSaverFactory.js.map +1 -1
- package/dist/cli/index.js +12 -12
- package/dist/cli/index.js.map +1 -1
- package/dist/edges/createDirectEdge.d.ts +1 -2
- package/dist/edges/createDirectEdge.d.ts.map +1 -1
- package/dist/edges/createDirectEdge.js +2 -6
- package/dist/edges/createDirectEdge.js.map +1 -1
- package/dist/edges/createLogicalRouter.d.ts.map +1 -1
- package/dist/edges/createLogicalRouter.js +6 -23
- package/dist/edges/createLogicalRouter.js.map +1 -1
- package/dist/edges/createPromptRouter.d.ts.map +1 -1
- package/dist/edges/createPromptRouter.js +6 -12
- package/dist/edges/createPromptRouter.js.map +1 -1
- package/dist/edges/edgeFactory.d.ts.map +1 -1
- package/dist/edges/edgeFactory.js +3 -8
- package/dist/edges/edgeFactory.js.map +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -6
- package/dist/index.js.map +1 -1
- package/dist/interrupts/BaseInterruptSessionManager.d.ts +51 -0
- package/dist/interrupts/BaseInterruptSessionManager.d.ts.map +1 -0
- package/dist/interrupts/BaseInterruptSessionManager.js +39 -0
- package/dist/interrupts/BaseInterruptSessionManager.js.map +1 -0
- package/dist/interrupts/InterruptSessionManager.types.d.ts +36 -0
- package/dist/interrupts/InterruptSessionManager.types.d.ts.map +1 -0
- package/dist/interrupts/InterruptSessionManager.types.js +40 -0
- package/dist/interrupts/InterruptSessionManager.types.js.map +1 -0
- package/dist/interrupts/MemoryInterruptSessionManager.d.ts +14 -0
- package/dist/interrupts/MemoryInterruptSessionManager.d.ts.map +1 -0
- package/dist/interrupts/MemoryInterruptSessionManager.js +56 -0
- package/dist/interrupts/MemoryInterruptSessionManager.js.map +1 -0
- package/dist/interrupts/MindedInterruptSessionManager.d.ts +13 -0
- package/dist/interrupts/MindedInterruptSessionManager.d.ts.map +1 -0
- package/dist/interrupts/MindedInterruptSessionManager.js +156 -0
- package/dist/interrupts/MindedInterruptSessionManager.js.map +1 -0
- package/dist/interrupts/interruptSessionManagerFactory.d.ts +3 -0
- package/dist/interrupts/interruptSessionManagerFactory.d.ts.map +1 -0
- package/dist/interrupts/interruptSessionManagerFactory.js +56 -0
- package/dist/interrupts/interruptSessionManagerFactory.js.map +1 -0
- package/dist/llm/createLlmInstance.d.ts +1 -1
- package/dist/llm/createLlmInstance.d.ts.map +1 -1
- package/dist/llm/createLlmInstance.js +1 -18
- package/dist/llm/createLlmInstance.js.map +1 -1
- package/dist/nodes/addAppToolNode.d.ts.map +1 -1
- package/dist/nodes/addAppToolNode.js +4 -5
- package/dist/nodes/addAppToolNode.js.map +1 -1
- package/dist/nodes/addHumanInTheLoopNode.d.ts.map +1 -1
- package/dist/nodes/addHumanInTheLoopNode.js +3 -2
- package/dist/nodes/addHumanInTheLoopNode.js.map +1 -1
- package/dist/nodes/addJumpToNode.d.ts.map +1 -1
- package/dist/nodes/addJumpToNode.js +1 -2
- package/dist/nodes/addJumpToNode.js.map +1 -1
- package/dist/nodes/addJunctionNode.d.ts.map +1 -1
- package/dist/nodes/addJunctionNode.js +0 -1
- package/dist/nodes/addJunctionNode.js.map +1 -1
- package/dist/nodes/addPromptNode.d.ts.map +1 -1
- package/dist/nodes/addPromptNode.js +61 -7
- package/dist/nodes/addPromptNode.js.map +1 -1
- package/dist/nodes/addToolNode.js +4 -2
- package/dist/nodes/addToolNode.js.map +1 -1
- package/dist/nodes/addToolRunNode.d.ts.map +1 -1
- package/dist/nodes/addToolRunNode.js +2 -2
- package/dist/nodes/addToolRunNode.js.map +1 -1
- package/dist/nodes/addTriggerNode.d.ts.map +1 -1
- package/dist/nodes/addTriggerNode.js +1 -2
- package/dist/nodes/addTriggerNode.js.map +1 -1
- package/dist/nodes/nodeFactory.d.ts.map +1 -1
- package/dist/nodes/nodeFactory.js +0 -4
- package/dist/nodes/nodeFactory.js.map +1 -1
- package/dist/platform/mindedChatOpenAI.d.ts +5 -0
- package/dist/platform/mindedChatOpenAI.d.ts.map +1 -0
- package/dist/platform/{models/mindedChatOpenAI.js → mindedChatOpenAI.js} +1 -10
- package/dist/platform/mindedChatOpenAI.js.map +1 -0
- package/dist/platform/mindedConnection.d.ts.map +1 -1
- package/dist/platform/mindedConnection.js +12 -12
- package/dist/platform/mindedConnection.js.map +1 -1
- package/dist/platform/mindedConnectionTypes.d.ts +151 -1
- package/dist/platform/mindedConnectionTypes.d.ts.map +1 -1
- package/dist/platform/mindedConnectionTypes.js +9 -0
- package/dist/platform/mindedConnectionTypes.js.map +1 -1
- package/dist/playbooks/playbooks.js +4 -4
- package/dist/playbooks/playbooks.js.map +1 -1
- package/dist/types/Agent.types.d.ts +2 -0
- package/dist/types/Agent.types.d.ts.map +1 -1
- package/dist/types/Agent.types.js.map +1 -1
- package/dist/types/Flows.types.d.ts +3 -18
- package/dist/types/Flows.types.d.ts.map +1 -1
- package/dist/types/Flows.types.js +0 -2
- package/dist/types/Flows.types.js.map +1 -1
- package/dist/types/LLM.types.d.ts.map +1 -1
- package/dist/types/LLM.types.js +1 -1
- package/dist/types/LLM.types.js.map +1 -1
- package/dist/types/LangGraph.types.d.ts +2 -4
- package/dist/types/LangGraph.types.d.ts.map +1 -1
- package/dist/types/LangGraph.types.js +2 -5
- package/dist/types/LangGraph.types.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/voice/voiceSession.d.ts.map +1 -1
- package/dist/voice/voiceSession.js +17 -16
- package/dist/voice/voiceSession.js.map +1 -1
- package/docs/SUMMARY.md +0 -1
- package/docs/getting-started/installation.md +0 -42
- package/docs/low-code-editor/nodes.md +0 -27
- package/docs/low-code-editor/tools.md +0 -32
- package/package.json +2 -3
- package/src/agent.ts +93 -32
- package/src/checkpointer/checkpointSaverFactory.ts +1 -1
- package/src/cli/index.ts +12 -12
- package/src/edges/createDirectEdge.ts +2 -7
- package/src/edges/createLogicalRouter.ts +6 -23
- package/src/edges/createPromptRouter.ts +6 -13
- package/src/edges/edgeFactory.ts +4 -20
- package/src/index.ts +0 -6
- package/src/interrupts/BaseInterruptSessionManager.ts +94 -0
- package/src/interrupts/MemoryInterruptSessionManager.ts +57 -0
- package/src/interrupts/MindedInterruptSessionManager.ts +155 -0
- package/src/interrupts/interruptSessionManagerFactory.ts +20 -0
- package/src/llm/createLlmInstance.ts +2 -25
- package/src/nodes/addAppToolNode.ts +4 -5
- package/src/nodes/addHumanInTheLoopNode.ts +3 -3
- package/src/nodes/addJumpToNode.ts +1 -2
- package/src/nodes/addJunctionNode.ts +0 -1
- package/src/nodes/addPromptNode.ts +65 -10
- package/src/nodes/addToolNode.ts +4 -4
- package/src/nodes/addToolRunNode.ts +2 -4
- package/src/nodes/addTriggerNode.ts +1 -2
- package/src/nodes/nodeFactory.ts +1 -5
- package/src/platform/mindedChatOpenAI.ts +19 -0
- package/src/platform/mindedConnection.ts +15 -25
- package/src/platform/mindedConnectionTypes.ts +188 -1
- package/src/playbooks/playbooks.ts +4 -4
- package/src/types/Agent.types.ts +2 -0
- package/src/types/Flows.types.ts +1 -17
- package/src/types/LLM.types.ts +5 -5
- package/src/types/LangGraph.types.ts +2 -5
- package/src/utils/logger.ts +2 -1
- package/src/voice/voiceSession.ts +17 -16
- package/dist/browserTask/executeBrowserTask.d.ts +0 -12
- package/dist/browserTask/executeBrowserTask.d.ts.map +0 -1
- package/dist/browserTask/executeBrowserTask.js +0 -181
- package/dist/browserTask/executeBrowserTask.js.map +0 -1
- package/dist/nodes/addBrowserTaskNode.d.ts +0 -13
- package/dist/nodes/addBrowserTaskNode.d.ts.map +0 -1
- package/dist/nodes/addBrowserTaskNode.js +0 -230
- package/dist/nodes/addBrowserTaskNode.js.map +0 -1
- package/dist/nodes/addBrowserTaskRunNode.d.ts +0 -13
- package/dist/nodes/addBrowserTaskRunNode.d.ts.map +0 -1
- package/dist/nodes/addBrowserTaskRunNode.js +0 -126
- package/dist/nodes/addBrowserTaskRunNode.js.map +0 -1
- package/dist/platform/models/mindedChatOpenAI.d.ts +0 -20
- package/dist/platform/models/mindedChatOpenAI.d.ts.map +0 -1
- package/dist/platform/models/mindedChatOpenAI.js.map +0 -1
- package/dist/platform/models/parallelWrapper.d.ts +0 -17
- package/dist/platform/models/parallelWrapper.d.ts.map +0 -1
- package/dist/platform/models/parallelWrapper.js +0 -105
- package/dist/platform/models/parallelWrapper.js.map +0 -1
- package/docs/platform/parallel-llm.md +0 -242
- package/src/browserTask/executeBrowserTask.ts +0 -213
- package/src/nodes/addBrowserTaskNode.ts +0 -229
- package/src/nodes/addBrowserTaskRunNode.ts +0 -142
- package/src/platform/models/mindedChatOpenAI.ts +0 -49
- package/src/platform/models/parallelWrapper.ts +0 -141
package/src/agent.ts
CHANGED
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
import { createLlmInstance } from './llm/createLlmInstance';
|
|
27
27
|
import { createCheckpointSaver } from './checkpointer/checkpointSaverFactory';
|
|
28
28
|
import { getConfig } from './platform/config';
|
|
29
|
+
import { InterruptSessionManager, InterruptType } from './interrupts/BaseInterruptSessionManager';
|
|
30
|
+
import { createInterruptSessionManager } from './interrupts/interruptSessionManagerFactory';
|
|
29
31
|
import { BaseMessage, HumanMessage } from '@langchain/core/messages';
|
|
30
32
|
import triggerTypeToDefaultMessage from './triggers/triggerTypeToDefaultMessage';
|
|
31
33
|
import appActionRunnerToolCreator from './internalTools/appActionRunnerTool';
|
|
@@ -43,6 +45,7 @@ type CreateAgentParams<Memory> = {
|
|
|
43
45
|
tools: Tool<any, Memory>[];
|
|
44
46
|
platformToken?: string;
|
|
45
47
|
memorySaver?: BaseCheckpointSaver;
|
|
48
|
+
interruptSessionManager?: InterruptSessionManager;
|
|
46
49
|
};
|
|
47
50
|
|
|
48
51
|
/**
|
|
@@ -75,6 +78,8 @@ export class Agent {
|
|
|
75
78
|
|
|
76
79
|
// Langgraph memory saver. In memory for local development, Custom for Platform
|
|
77
80
|
private checkpointer!: BaseCheckpointSaver;
|
|
81
|
+
// Interrupt session manager. In memory for local development, Custom for Platform
|
|
82
|
+
public interruptSessionManager!: InterruptSessionManager;
|
|
78
83
|
// Langgraph compiled graph
|
|
79
84
|
public compiledGraph!: CompiledGraph;
|
|
80
85
|
// Cache for secrets to avoid repeated API calls
|
|
@@ -145,7 +150,7 @@ export class Agent {
|
|
|
145
150
|
|
|
146
151
|
private async init(params: CreateAgentParams<z.infer<typeof this.memorySchema>>): Promise<void> {
|
|
147
152
|
try {
|
|
148
|
-
const { config, tools, memorySaver } = params;
|
|
153
|
+
const { config, tools, memorySaver, interruptSessionManager } = params;
|
|
149
154
|
const { runLocally } = getConfig();
|
|
150
155
|
if (!runLocally) {
|
|
151
156
|
await mindedConnection.start();
|
|
@@ -178,6 +183,7 @@ export class Agent {
|
|
|
178
183
|
const appActionsRunnerTools = this.initAppActionsRunnerTools();
|
|
179
184
|
this.tools = [...tools, ...appActionsRunnerTools];
|
|
180
185
|
this.checkpointer = memorySaver || createCheckpointSaver();
|
|
186
|
+
this.interruptSessionManager = interruptSessionManager || createInterruptSessionManager();
|
|
181
187
|
|
|
182
188
|
// call here methods that needs environment variables to be loaded
|
|
183
189
|
this.llm = createLlmInstance(config.llm);
|
|
@@ -298,17 +304,9 @@ export class Agent {
|
|
|
298
304
|
|
|
299
305
|
// Add edge from start to first node if no triggers exist
|
|
300
306
|
const hasTrigger = nodes.some((node) => node.type === NodeType.TRIGGER && node.triggerType !== TriggerType.MANUAL);
|
|
301
|
-
if (!hasTrigger) {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (mainFlow && mainFlow.nodes.length > 0) {
|
|
305
|
-
this.startingNodeId = mainFlow.nodes[0].name;
|
|
306
|
-
graph.addEdge('__start__', mainFlow.nodes[0].name as any);
|
|
307
|
-
} else if (nodes.length > 0) {
|
|
308
|
-
// Fallback to first node if Main flow not found
|
|
309
|
-
this.startingNodeId = nodes[0].name;
|
|
310
|
-
graph.addEdge('__start__', nodes[0].name as any);
|
|
311
|
-
}
|
|
307
|
+
if (!hasTrigger && nodes.length > 0) {
|
|
308
|
+
this.startingNodeId = nodes[0].name;
|
|
309
|
+
graph.addEdge('__start__', nodes[0].name as any);
|
|
312
310
|
} else {
|
|
313
311
|
nodes.forEach((node) => {
|
|
314
312
|
if (node.type === NodeType.TRIGGER && node.triggerType !== TriggerType.MANUAL) {
|
|
@@ -350,7 +348,6 @@ export class Agent {
|
|
|
350
348
|
sessionId: state.sessionId || uuidv4(), // Preserve existing sessionId or generate new one
|
|
351
349
|
sessionType: state.sessionType || SessionType.TEXT,
|
|
352
350
|
overrideStartFromNodeId: null,
|
|
353
|
-
goto: null,
|
|
354
351
|
};
|
|
355
352
|
|
|
356
353
|
// Emit INIT event with the initial state
|
|
@@ -416,10 +413,24 @@ export class Agent {
|
|
|
416
413
|
* });
|
|
417
414
|
* ```
|
|
418
415
|
*/
|
|
419
|
-
public async invoke({ triggerBody, triggerName, sessionId, appName }: AgentInvokeParams) {
|
|
416
|
+
public async invoke({ triggerBody, triggerName, sessionId, appName, bypassSessionCheck }: AgentInvokeParams): Promise<any> {
|
|
420
417
|
sessionId = sessionId ?? uuidv4();
|
|
421
418
|
try {
|
|
422
419
|
await this.waitForInitialization();
|
|
420
|
+
|
|
421
|
+
// Try to acquire lock atomically (unless bypassing session check)
|
|
422
|
+
if (!bypassSessionCheck && !(await this.interruptSessionManager.lock(sessionId))) {
|
|
423
|
+
// Could not acquire lock, session is being processed - enqueue the message
|
|
424
|
+
logger.info({ message: 'Enqueuing message', sessionId, triggerBody, triggerName, appName });
|
|
425
|
+
await this.interruptSessionManager.enqueueMessage(sessionId, {
|
|
426
|
+
triggerBody,
|
|
427
|
+
triggerName,
|
|
428
|
+
appName,
|
|
429
|
+
});
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
// Session lock acquired, proceed with processing
|
|
433
|
+
|
|
423
434
|
let messages: Array<BaseMessage> = [];
|
|
424
435
|
let memoryUpdate = {};
|
|
425
436
|
let sessionType: SessionType = SessionType.TEXT;
|
|
@@ -447,7 +458,8 @@ export class Agent {
|
|
|
447
458
|
const handlerResult = results.find((r) => r !== undefined);
|
|
448
459
|
if (handlerResult) {
|
|
449
460
|
if (!handlerResult.isQualified) {
|
|
450
|
-
logger.
|
|
461
|
+
logger.info({ message: `Trigger ${triggerName} was disqualified` });
|
|
462
|
+
await this.interruptSessionManager.release(sessionId);
|
|
451
463
|
return;
|
|
452
464
|
}
|
|
453
465
|
memoryUpdate = handlerResult.memory || {};
|
|
@@ -457,7 +469,7 @@ export class Agent {
|
|
|
457
469
|
}
|
|
458
470
|
}
|
|
459
471
|
|
|
460
|
-
logger.info({
|
|
472
|
+
logger.info({ message: 'Invoking trigger', triggerName, sessionId, triggerBody });
|
|
461
473
|
const langraphConfig = this.getLangraphConfig(sessionId || uuidv4());
|
|
462
474
|
const state = await this.compiledGraph.getState(langraphConfig);
|
|
463
475
|
const suffixes = Object.values(internalNodesSuffix);
|
|
@@ -479,13 +491,37 @@ export class Agent {
|
|
|
479
491
|
|
|
480
492
|
let res;
|
|
481
493
|
// Resume interruption
|
|
482
|
-
if (state.tasks?.[
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
494
|
+
if (state.tasks?.[state.tasks.length - 1]?.interrupts?.length > 0) {
|
|
495
|
+
const lastTask = state.tasks[state.tasks.length - 1];
|
|
496
|
+
const interrupt = lastTask.interrupts[0];
|
|
497
|
+
const interruptValue = (interrupt as any).value;
|
|
498
|
+
|
|
499
|
+
if (interruptValue?.type === InterruptType.HUMAN_IN_THE_LOOP) {
|
|
500
|
+
// For HUMAN_IN_THE_LOOP, use resume with the full object
|
|
501
|
+
res = await this.compiledGraph.invoke(
|
|
502
|
+
new Command({
|
|
503
|
+
resume: { memory: memoryUpdate, messages, history: historyStep, sessionId, sessionType, overrideStartFromNodeId: null },
|
|
504
|
+
}),
|
|
505
|
+
langraphConfig,
|
|
506
|
+
);
|
|
507
|
+
} else if (interruptValue?.type === InterruptType.NEW_TRIGGERS) {
|
|
508
|
+
// For NEW_TRIGGERS, check if there's an updateStateObject to apply first
|
|
509
|
+
const finalState = { memory: memoryUpdate, messages, history: [historyStep], sessionId, sessionType };
|
|
510
|
+
if (interruptValue.updateStateObject) {
|
|
511
|
+
finalState.messages = [...interruptValue.updateStateObject.messages, ...messages];
|
|
512
|
+
finalState.history = [...(interruptValue.updateStateObject.history || []), historyStep];
|
|
513
|
+
//add handlers for other state fields as needed
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Then use update with the full object and empty resume
|
|
517
|
+
res = await this.compiledGraph.invoke(
|
|
518
|
+
new Command({
|
|
519
|
+
update: finalState,
|
|
520
|
+
resume: '',
|
|
521
|
+
}),
|
|
522
|
+
langraphConfig,
|
|
523
|
+
);
|
|
524
|
+
}
|
|
489
525
|
} else if (state.values.overrideStartFromNodeId) {
|
|
490
526
|
res = await this.compiledGraph.invoke(
|
|
491
527
|
new Command({
|
|
@@ -507,14 +543,39 @@ export class Agent {
|
|
|
507
543
|
langraphConfig,
|
|
508
544
|
);
|
|
509
545
|
}
|
|
546
|
+
|
|
547
|
+
const nextMessage = await this.interruptSessionManager.dequeue(sessionId);
|
|
548
|
+
if (nextMessage) {
|
|
549
|
+
// Dequeue the first message and process it recursively
|
|
550
|
+
// Recursively process the next message with bypass flag
|
|
551
|
+
const invokeParams: AgentInvokeParams = {
|
|
552
|
+
triggerBody: nextMessage.triggerBody,
|
|
553
|
+
triggerName: nextMessage.triggerName,
|
|
554
|
+
sessionId: sessionId,
|
|
555
|
+
bypassSessionCheck: true,
|
|
556
|
+
};
|
|
557
|
+
if (nextMessage.appName) {
|
|
558
|
+
invokeParams.appName = nextMessage.appName;
|
|
559
|
+
}
|
|
560
|
+
logger.info({ message: 'Invoking next message in the queue', invokeParams });
|
|
561
|
+
return await this.invoke(invokeParams);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Release the session lock
|
|
565
|
+
await this.interruptSessionManager.release(sessionId);
|
|
566
|
+
|
|
510
567
|
return res;
|
|
511
568
|
} catch (error: any) {
|
|
512
569
|
logger.error({
|
|
513
|
-
|
|
570
|
+
message: 'Invoke error',
|
|
514
571
|
errorMessage: error.message,
|
|
515
572
|
stack: error.stack,
|
|
516
573
|
sessionId,
|
|
517
574
|
});
|
|
575
|
+
|
|
576
|
+
// Release the session lock on error
|
|
577
|
+
await this.interruptSessionManager.release(sessionId);
|
|
578
|
+
|
|
518
579
|
const state = await this.compiledGraph.getState(this.getLangraphConfig(sessionId));
|
|
519
580
|
this.emit(AgentEvents.ERROR, { error: error instanceof Error ? error : new Error(JSON.stringify(error)), state: state.values });
|
|
520
581
|
throw error;
|
|
@@ -744,7 +805,7 @@ export class Agent {
|
|
|
744
805
|
// Skip secret loading in local development
|
|
745
806
|
const { runLocally } = getConfig();
|
|
746
807
|
if (runLocally) {
|
|
747
|
-
logger.
|
|
808
|
+
logger.info({ message: 'Running locally - skipping secret loading' });
|
|
748
809
|
return {};
|
|
749
810
|
}
|
|
750
811
|
if (!mindedConnection.isConnected()) {
|
|
@@ -771,10 +832,10 @@ export class Agent {
|
|
|
771
832
|
const secrets = response.secrets || {};
|
|
772
833
|
|
|
773
834
|
// Load secrets into process.env
|
|
835
|
+
logger.debug(`Loading ${Object.keys(secrets).length} secrets into environment variables`);
|
|
774
836
|
Object.entries(secrets).forEach(([key, value]) => {
|
|
775
837
|
process.env[key] = value;
|
|
776
838
|
});
|
|
777
|
-
logger.debug(`[Agent] Loaded ${Object.keys(secrets).length} secrets from platform`);
|
|
778
839
|
|
|
779
840
|
// Cache the secrets for future requests
|
|
780
841
|
this.secretsCache = secrets;
|
|
@@ -790,7 +851,7 @@ export class Agent {
|
|
|
790
851
|
}
|
|
791
852
|
|
|
792
853
|
private setupVoice(): void {
|
|
793
|
-
logger.info('
|
|
854
|
+
logger.info({ message: 'Setting up voice' });
|
|
794
855
|
if (!mindedConnection.isConnected()) {
|
|
795
856
|
throw new Error('Minded connection is required');
|
|
796
857
|
}
|
|
@@ -813,7 +874,7 @@ export class Agent {
|
|
|
813
874
|
voiceSession.sendAudio(audioMessage.audioData);
|
|
814
875
|
} else {
|
|
815
876
|
logger.trace({
|
|
816
|
-
message: '
|
|
877
|
+
message: 'Audio received; voice session not found for sessionId',
|
|
817
878
|
sessionId: audioMessage.sessionId,
|
|
818
879
|
activeSessions: Array.from(this.voiceSessions.keys()),
|
|
819
880
|
});
|
|
@@ -823,13 +884,13 @@ export class Agent {
|
|
|
823
884
|
// Hangup / end session handler
|
|
824
885
|
connection.on(mindedConnectionSocketMessageType.DASHBOARD_VOICE_SESSION_END, (message) => {
|
|
825
886
|
const hangup = message as BaseVoiceMessage;
|
|
826
|
-
logger.debug({ message: '
|
|
887
|
+
logger.debug({ message: 'Dashboard eneded voice session', sessionId: hangup.sessionId });
|
|
827
888
|
const voiceSession = this.voiceSessions.get(hangup.sessionId);
|
|
828
889
|
if (voiceSession) {
|
|
829
890
|
voiceSession.hangup();
|
|
830
891
|
} else {
|
|
831
892
|
logger.trace({
|
|
832
|
-
message: '
|
|
893
|
+
message: 'Session ended; voice session not found for sessionId',
|
|
833
894
|
sessionId: hangup.sessionId,
|
|
834
895
|
activeSessions: this.voiceSessions.keys(),
|
|
835
896
|
});
|
|
@@ -856,7 +917,7 @@ export class Agent {
|
|
|
856
917
|
voiceId: voiceTrigger.voiceId,
|
|
857
918
|
});
|
|
858
919
|
await voiceSession.init();
|
|
859
|
-
logger.debug({ message: '
|
|
920
|
+
logger.debug({ message: 'Voice session initialized', sessionId: params.sessionId });
|
|
860
921
|
this.voiceSessions.set(params.sessionId, voiceSession);
|
|
861
922
|
|
|
862
923
|
// Emit voice session start event
|
|
@@ -884,7 +945,7 @@ export class Agent {
|
|
|
884
945
|
To be used by the Lambda wrapper to restore checkpoints
|
|
885
946
|
*/
|
|
886
947
|
public async restoreCheckpoint(sessionId: string, checkpointId: string): Promise<void> {
|
|
887
|
-
logger.info({
|
|
948
|
+
logger.info({ message: 'Restoring checkpoint', sessionId, checkpointId });
|
|
888
949
|
const langraphConfig = this.getLangraphConfig(sessionId, checkpointId);
|
|
889
950
|
await this.compiledGraph.invoke(
|
|
890
951
|
new Command({
|
package/src/cli/index.ts
CHANGED
|
@@ -19,7 +19,7 @@ function setToken(token: string): void {
|
|
|
19
19
|
if (!fs.existsSync(envPath)) {
|
|
20
20
|
// Create .env file with the token
|
|
21
21
|
fs.writeFileSync(envPath, tokenLine + '\n');
|
|
22
|
-
logger.info(`Created ${envPath} and added token`);
|
|
22
|
+
logger.info({ message: `Created ${envPath} and added token` });
|
|
23
23
|
} else {
|
|
24
24
|
// Read existing .env file
|
|
25
25
|
const envContent = fs.readFileSync(envPath, 'utf8');
|
|
@@ -29,12 +29,12 @@ function setToken(token: string): void {
|
|
|
29
29
|
// Replace existing token
|
|
30
30
|
const updatedContent = envContent.replace(/MINDED_CONNECTION_TOKEN=.*/, tokenLine);
|
|
31
31
|
fs.writeFileSync(envPath, updatedContent);
|
|
32
|
-
logger.info(`Updated MINDED_CONNECTION_TOKEN in ${envPath}`);
|
|
32
|
+
logger.info({ message: `Updated MINDED_CONNECTION_TOKEN in ${envPath}` });
|
|
33
33
|
} else {
|
|
34
34
|
// Append token to existing file
|
|
35
35
|
const newContent = envContent.endsWith('\n') ? envContent + tokenLine + '\n' : envContent + '\n' + tokenLine + '\n';
|
|
36
36
|
fs.writeFileSync(envPath, newContent);
|
|
37
|
-
logger.info(`Added MINDED_CONNECTION_TOKEN to ${envPath}`);
|
|
37
|
+
logger.info({ message: `Added MINDED_CONNECTION_TOKEN to ${envPath}` });
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -44,7 +44,7 @@ function generateLambdaHandler(): void {
|
|
|
44
44
|
|
|
45
45
|
// Check if minded.json exists
|
|
46
46
|
if (!fs.existsSync(mindedConfigPath)) {
|
|
47
|
-
logger.error('minded.json not found in the current directory');
|
|
47
|
+
logger.error({ message: 'minded.json not found in the current directory' });
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -54,14 +54,14 @@ function generateLambdaHandler(): void {
|
|
|
54
54
|
const configContent = fs.readFileSync(mindedConfigPath, 'utf8');
|
|
55
55
|
mindedConfig = JSON.parse(configContent);
|
|
56
56
|
} catch (error) {
|
|
57
|
-
logger.error('Failed to read or parse minded.json:', error);
|
|
57
|
+
logger.error({ message: 'Failed to read or parse minded.json:', error });
|
|
58
58
|
process.exit(1);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// Get the agent path
|
|
62
62
|
const agentPath = mindedConfig.agent;
|
|
63
63
|
if (!agentPath) {
|
|
64
|
-
logger.error('No agent path found in minded.json');
|
|
64
|
+
logger.error({ message: 'No agent path found in minded.json' });
|
|
65
65
|
process.exit(1);
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -91,7 +91,7 @@ function generateLambdaHandler(): void {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
if (!templateContent) {
|
|
94
|
-
logger.error('Could not find Lambda handler template file');
|
|
94
|
+
logger.error({ message: 'Could not find Lambda handler template file' });
|
|
95
95
|
process.exit(1);
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -102,10 +102,10 @@ function generateLambdaHandler(): void {
|
|
|
102
102
|
// Write the Lambda handler to index.ts at the root
|
|
103
103
|
const outputPath = path.join(process.cwd(), 'index.ts');
|
|
104
104
|
fs.writeFileSync(outputPath, templateContent);
|
|
105
|
-
logger.info(`Generated Lambda handler at ${outputPath}`);
|
|
105
|
+
logger.info({ message: `Generated Lambda handler at ${outputPath}` });
|
|
106
106
|
|
|
107
107
|
// Compile the index.ts file using TypeScript
|
|
108
|
-
logger.info('Compiling the Lambda handler...');
|
|
108
|
+
logger.info({ message: 'Compiling the Lambda handler...' });
|
|
109
109
|
|
|
110
110
|
try {
|
|
111
111
|
// Read tsconfig.json to get the outDir
|
|
@@ -138,7 +138,7 @@ function generateLambdaHandler(): void {
|
|
|
138
138
|
cwd: process.cwd(),
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
logger.info(`Successfully compiled Lambda handler to ${outDir}/index.js`);
|
|
141
|
+
logger.info({ message: `Successfully compiled Lambda handler to ${outDir}/index.js` });
|
|
142
142
|
} catch (compileError) {
|
|
143
143
|
logger.error({ message: 'Failed to compile Lambda handler', error: compileError });
|
|
144
144
|
}
|
|
@@ -155,14 +155,14 @@ function main() {
|
|
|
155
155
|
if (command === 'token') {
|
|
156
156
|
const token = args[1];
|
|
157
157
|
if (!token) {
|
|
158
|
-
logger.error('Please provide a token');
|
|
158
|
+
logger.error({ message: 'Please provide a token' });
|
|
159
159
|
process.exit(1);
|
|
160
160
|
}
|
|
161
161
|
setToken(token);
|
|
162
162
|
} else if (command === 'generate-lambda-ts-handler') {
|
|
163
163
|
generateLambdaHandler();
|
|
164
164
|
} else {
|
|
165
|
-
logger.error('Unknown command. Available commands: token, generate-lambda-ts-handler');
|
|
165
|
+
logger.error({ message: 'Unknown command. Available commands: token, generate-lambda-ts-handler' });
|
|
166
166
|
process.exit(1);
|
|
167
167
|
}
|
|
168
168
|
}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import { StepForwardEdge } from '../types/Flows.types';
|
|
2
|
-
import { stateAnnotation } from '../types/LangGraph.types';
|
|
3
2
|
import { logger } from '../utils/logger';
|
|
4
3
|
|
|
5
4
|
export const createDirectEdge = (edge: StepForwardEdge) => {
|
|
6
|
-
return async (
|
|
7
|
-
if (state.goto) {
|
|
8
|
-
console.log('Jumping to node', state.goto);
|
|
9
|
-
return state.goto;
|
|
10
|
-
}
|
|
5
|
+
return async () => {
|
|
11
6
|
// For direct edges, we just return the target of the first edge
|
|
12
7
|
// since there's no conditional logic needed
|
|
13
|
-
logger.info({
|
|
8
|
+
logger.info({ message: `Executing edge ${JSON.stringify(edge)}` });
|
|
14
9
|
return edge.target;
|
|
15
10
|
};
|
|
16
11
|
};
|
|
@@ -8,12 +8,7 @@ const CONDITION_TIMEOUT = 5000; // 5 seconds
|
|
|
8
8
|
|
|
9
9
|
export const createLogicalRouter = ({ edges }: { edges: LogicalConditionEdge[] }) => {
|
|
10
10
|
return async (state: typeof stateAnnotation.State) => {
|
|
11
|
-
logger.debug(
|
|
12
|
-
|
|
13
|
-
if (state.goto) {
|
|
14
|
-
console.log('Jumping to node', state.goto);
|
|
15
|
-
return state.goto;
|
|
16
|
-
}
|
|
11
|
+
logger.debug(`Evaluating logical conditions for ${edges.length} edges`);
|
|
17
12
|
|
|
18
13
|
// Separate regular conditions from "else" conditions
|
|
19
14
|
const regularEdges = edges.filter((edge) => edge.condition.trim() !== 'else');
|
|
@@ -64,16 +59,7 @@ export const createLogicalRouter = ({ edges }: { edges: LogicalConditionEdge[] }
|
|
|
64
59
|
]);
|
|
65
60
|
|
|
66
61
|
if (result === true) {
|
|
67
|
-
|
|
68
|
-
logger.info({ msg: `[Router] Stay at node ${edge.source}`, node: edge.source, condition: edge.condition });
|
|
69
|
-
} else {
|
|
70
|
-
logger.info({
|
|
71
|
-
msg: `[Router] Logical condition matched`,
|
|
72
|
-
transitionFrom: edge.source,
|
|
73
|
-
transitionTo: edge.target,
|
|
74
|
-
condition: edge.condition,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
62
|
+
logger.info({ message: `Condition matched for edge ${edge.source} → ${edge.target}` });
|
|
77
63
|
return edge.target;
|
|
78
64
|
}
|
|
79
65
|
} catch (error) {
|
|
@@ -82,7 +68,7 @@ export const createLogicalRouter = ({ edges }: { edges: LogicalConditionEdge[] }
|
|
|
82
68
|
const conditionPreview = edge.condition.length > 100 ? `${edge.condition.substring(0, 100)}...` : edge.condition;
|
|
83
69
|
|
|
84
70
|
logger.error({
|
|
85
|
-
|
|
71
|
+
message: `Error evaluating condition for edge ${edge.source} → ${edge.target}`,
|
|
86
72
|
condition: conditionPreview,
|
|
87
73
|
error: errorMessage,
|
|
88
74
|
edgeIndex: edges.indexOf(edge),
|
|
@@ -97,18 +83,15 @@ export const createLogicalRouter = ({ edges }: { edges: LogicalConditionEdge[] }
|
|
|
97
83
|
|
|
98
84
|
// If no regular conditions matched, check for "else" conditions
|
|
99
85
|
if (elseEdges.length > 0) {
|
|
86
|
+
logger.info({ message: `No regular conditions matched, evaluating ${elseEdges.length} else condition(s)` });
|
|
100
87
|
// Return the first "else" condition's target
|
|
101
88
|
const elseEdge = elseEdges[0];
|
|
102
|
-
logger.info({
|
|
103
|
-
msg: `[Router] Else condition matched`,
|
|
104
|
-
transitionFrom: elseEdge.source,
|
|
105
|
-
transitionTo: elseEdge.target,
|
|
106
|
-
});
|
|
89
|
+
logger.info({ message: `Else condition matched for edge ${elseEdge.source} → ${elseEdge.target}`, edge: elseEdge });
|
|
107
90
|
return elseEdge.target;
|
|
108
91
|
}
|
|
109
92
|
|
|
110
93
|
// If no conditions matched or all failed, return to the source node
|
|
111
|
-
logger.info({
|
|
94
|
+
logger.info({ message: 'No conditions matched' });
|
|
112
95
|
return null;
|
|
113
96
|
};
|
|
114
97
|
};
|
|
@@ -70,19 +70,11 @@ export const createPromptRouter = ({
|
|
|
70
70
|
currentNodeName?: string;
|
|
71
71
|
}) => {
|
|
72
72
|
return async (state: typeof stateAnnotation.State) => {
|
|
73
|
-
logger.
|
|
74
|
-
|
|
75
|
-
if (state.goto) {
|
|
76
|
-
console.log('Jumping to node', state.goto);
|
|
77
|
-
return state.goto;
|
|
78
|
-
}
|
|
73
|
+
logger.info({ message: `Executing prompt router. Edges: ${JSON.stringify(edges)}` });
|
|
79
74
|
|
|
80
75
|
// If canStayInCurrentNode is true and there are no edges, return current node immediately
|
|
81
76
|
if (canStayInCurrentNode && edges.length === 0 && currentNodeName) {
|
|
82
|
-
logger.info({
|
|
83
|
-
msg: `[Router] Stay at node, No edges available and canStayInCurrentNode==true`,
|
|
84
|
-
node: currentNodeName,
|
|
85
|
-
});
|
|
77
|
+
logger.info({ message: `No edges available and canStayInCurrentNode is true, staying in current node: ${currentNodeName}` });
|
|
86
78
|
return currentNodeName;
|
|
87
79
|
}
|
|
88
80
|
|
|
@@ -182,13 +174,14 @@ export const createPromptRouter = ({
|
|
|
182
174
|
|
|
183
175
|
const decision = validatedResponse.nextNodeId === currentNodeName ? 'stay in current node' : validatedResponse.nextNodeId;
|
|
184
176
|
const reasoning = includeReasoning && 'reasoning' in validatedResponse ? ` - Reasoning: ${validatedResponse.reasoning}` : '';
|
|
185
|
-
logger.
|
|
177
|
+
logger.info({ message: `Router decision: ${decision}`, reasoning });
|
|
186
178
|
|
|
187
179
|
return validatedResponse.nextNodeId;
|
|
188
180
|
} catch (error) {
|
|
189
181
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
190
182
|
logger.warn({
|
|
191
|
-
|
|
183
|
+
message: `Prompt router attempt ${attempts} failed`,
|
|
184
|
+
edge: edges,
|
|
192
185
|
error: lastError.message,
|
|
193
186
|
attempt: attempts,
|
|
194
187
|
maxRetries,
|
|
@@ -198,7 +191,7 @@ export const createPromptRouter = ({
|
|
|
198
191
|
// If all retries failed, return the first available edge as fallback
|
|
199
192
|
const fallbackNode = edges[0]?.target;
|
|
200
193
|
logger.error({
|
|
201
|
-
|
|
194
|
+
message: 'Prompt router reached max retries, using fallback',
|
|
202
195
|
fallbackNode,
|
|
203
196
|
lastError: lastError.message,
|
|
204
197
|
});
|
package/src/edges/edgeFactory.ts
CHANGED
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Edge,
|
|
3
|
-
EdgeType,
|
|
4
|
-
Node,
|
|
5
|
-
PromptConditionEdge,
|
|
6
|
-
LogicalConditionEdge,
|
|
7
|
-
StepForwardEdge,
|
|
8
|
-
NodeType,
|
|
9
|
-
ToolNode,
|
|
10
|
-
BrowserTaskNode,
|
|
11
|
-
} from '../types/Flows.types';
|
|
1
|
+
import { Edge, EdgeType, Node, PromptConditionEdge, LogicalConditionEdge, StepForwardEdge, NodeType, ToolNode } from '../types/Flows.types';
|
|
12
2
|
import { PreCompiledGraph } from '../types/LangGraph.types';
|
|
13
3
|
import { BaseLanguageModel } from '@langchain/core/language_models/base';
|
|
14
4
|
import { createPromptRouter } from './createPromptRouter';
|
|
@@ -16,7 +6,6 @@ import { createLogicalRouter } from './createLogicalRouter';
|
|
|
16
6
|
import { createDirectEdge } from './createDirectEdge';
|
|
17
7
|
import { addHumanInTheLoopNode, buildHumanInTheLoopNodeName } from '../nodes/addHumanInTheLoopNode';
|
|
18
8
|
import { addToolRunNode, buildToolRunNodeName } from '../nodes/addToolRunNode';
|
|
19
|
-
import { addBrowserTaskRunNode, buildBrowserTaskRunNodeName } from '../nodes/addBrowserTaskRunNode';
|
|
20
9
|
import { Tool } from '../types/Tools.types';
|
|
21
10
|
import { Agent } from '../agent';
|
|
22
11
|
import { logger } from '../utils/logger';
|
|
@@ -50,7 +39,7 @@ export const edgeFactory = ({
|
|
|
50
39
|
// Priority 1: Step forward edge (max 1)
|
|
51
40
|
if (edgesBySource.stepForward) {
|
|
52
41
|
const directRouter = createDirectEdge(edgesBySource.stepForward);
|
|
53
|
-
return await directRouter(
|
|
42
|
+
return await directRouter();
|
|
54
43
|
}
|
|
55
44
|
|
|
56
45
|
// Priority 2: Logical condition edges
|
|
@@ -60,7 +49,7 @@ export const edgeFactory = ({
|
|
|
60
49
|
if (result) {
|
|
61
50
|
return result;
|
|
62
51
|
} else {
|
|
63
|
-
logger.debug('No logical conditions matched, continuing to prompt conditions');
|
|
52
|
+
logger.debug({ message: 'No logical conditions matched, continuing to prompt conditions' });
|
|
64
53
|
}
|
|
65
54
|
}
|
|
66
55
|
|
|
@@ -80,7 +69,7 @@ export const edgeFactory = ({
|
|
|
80
69
|
|
|
81
70
|
// Fallback: stay at current source node
|
|
82
71
|
const source = originalNode?.name || sourceNode;
|
|
83
|
-
logger.info(`No conditions matched, returning to source: ${source}`);
|
|
72
|
+
logger.info({ message: `No conditions matched, returning to source: ${source}` });
|
|
84
73
|
return source;
|
|
85
74
|
};
|
|
86
75
|
};
|
|
@@ -103,11 +92,6 @@ export const edgeFactory = ({
|
|
|
103
92
|
effectiveSource = buildToolRunNodeName(source);
|
|
104
93
|
}
|
|
105
94
|
|
|
106
|
-
if (originalNode?.type === NodeType.BROWSER_TASK) {
|
|
107
|
-
addBrowserTaskRunNode({ graph, browserTaskNode: originalNode as BrowserTaskNode, attachedToNodeName: source, agent });
|
|
108
|
-
effectiveSource = buildBrowserTaskRunNodeName(source);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
95
|
// Create and add the combined conditional edge with original node reference
|
|
112
96
|
const combinedRouter = createCombinedRouter(effectiveSource, edgesBySource, originalNode);
|
|
113
97
|
graph.addConditionalEdges(effectiveSource as any, combinedRouter);
|
package/src/index.ts
CHANGED
|
@@ -7,12 +7,6 @@ import { resetTimer, cancelTimer, onTimer } from './internalTools/timer';
|
|
|
7
7
|
export type { ElevenLabsContext } from './types/Voice.types';
|
|
8
8
|
export { Agent, events, logger, sendPlaceholderMessage, resetTimer, cancelTimer, onTimer };
|
|
9
9
|
|
|
10
|
-
// Export LLM implementations
|
|
11
|
-
export { MindedChatOpenAI } from './platform/models/mindedChatOpenAI';
|
|
12
|
-
export { createParallelWrapper } from './platform/models/parallelWrapper';
|
|
13
|
-
export type { MindedChatOpenAIFields, BaseParallelChatFields } from './platform/models/mindedChatOpenAI';
|
|
14
|
-
export type { BaseParallelChatFields as ParallelWrapperFields } from './platform/models/parallelWrapper';
|
|
15
|
-
|
|
16
10
|
// HTTP module for PII masking - only public API
|
|
17
11
|
export type { PIIGatewayInstance, HttpRequestConfig, HttpResponse } from './platform/piiGateway';
|
|
18
12
|
|