@minded-ai/mindedjs 1.0.115 → 1.0.117
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 +31 -158
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +39 -160
- package/dist/agent.js.map +1 -1
- package/dist/events/AgentEvents.d.ts +1 -0
- package/dist/events/AgentEvents.d.ts.map +1 -1
- package/dist/platform/mindedConnection.d.ts.map +1 -1
- package/dist/platform/mindedConnection.js +34 -0
- package/dist/platform/mindedConnection.js.map +1 -1
- package/dist/platform/mindedConnectionTypes.d.ts +8 -1
- package/dist/platform/mindedConnectionTypes.d.ts.map +1 -1
- package/dist/platform/mindedConnectionTypes.js +1 -0
- package/dist/platform/mindedConnectionTypes.js.map +1 -1
- package/dist/toolsLibrary/classifier.d.ts +82 -0
- package/dist/toolsLibrary/classifier.d.ts.map +1 -0
- package/dist/toolsLibrary/classifier.js +223 -0
- package/dist/toolsLibrary/classifier.js.map +1 -0
- package/dist/toolsLibrary/index.d.ts +2 -0
- package/dist/toolsLibrary/index.d.ts.map +1 -1
- package/dist/toolsLibrary/index.js +2 -0
- package/dist/toolsLibrary/index.js.map +1 -1
- package/dist/types/Flows.types.d.ts +6 -0
- package/dist/types/Flows.types.d.ts.map +1 -1
- package/dist/types/Flows.types.js.map +1 -1
- package/docs/SUMMARY.md +1 -0
- package/docs/tooling/classifier.md +217 -0
- package/package.json +2 -2
- package/src/agent.ts +42 -160
- package/src/events/AgentEvents.ts +1 -0
- package/src/platform/mindedConnection.ts +14 -13
- package/src/platform/mindedConnectionTypes.ts +8 -2
- package/src/toolsLibrary/classifier.ts +273 -0
- package/src/toolsLibrary/index.ts +2 -0
- package/src/types/Flows.types.ts +6 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Classifier Tool
|
|
2
|
+
|
|
3
|
+
The classifier tool is a powerful utility in the MindedJS SDK that allows you to categorize text content using AI. It's available both as a tool that can be used in flows and as standalone utility functions that can be imported and used anywhere in your code.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The classifier tool provides:
|
|
8
|
+
|
|
9
|
+
- **Single-label classification**: Categorize content into one class
|
|
10
|
+
- **Multi-label classification**: Categorize content into multiple classes
|
|
11
|
+
- **Conversation classification**: Specialized classification for chat conversations
|
|
12
|
+
- **Configurable output formats**: JSON or plain text
|
|
13
|
+
- **Error handling with fallback defaults**
|
|
14
|
+
- **Confidence scoring**
|
|
15
|
+
|
|
16
|
+
## Using as a Tool
|
|
17
|
+
|
|
18
|
+
### In Flows
|
|
19
|
+
|
|
20
|
+
You can use the classifier tool in your flows by referencing `minded-classifier`:
|
|
21
|
+
|
|
22
|
+
```yaml
|
|
23
|
+
- id: classifyUserIntent
|
|
24
|
+
type: tool
|
|
25
|
+
toolName: minded-classifier
|
|
26
|
+
prompt: |
|
|
27
|
+
Classify the user's message into one of these categories:
|
|
28
|
+
- Technical Issue: Problems with the system
|
|
29
|
+
- Billing: Payment or pricing questions
|
|
30
|
+
- Feature Request: Asking for new features
|
|
31
|
+
|
|
32
|
+
Content: "{{userMessage}}"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Tool Parameters
|
|
36
|
+
|
|
37
|
+
| Parameter | Type | Description | Required |
|
|
38
|
+
| ------------- | ---------------- | ------------------------------------------------------ | -------- |
|
|
39
|
+
| content | string | The text content to classify | Yes |
|
|
40
|
+
| classes | array | Classes to classify into (strings, tuples, or objects) | No\* |
|
|
41
|
+
| systemPrompt | string | Custom system prompt for classification | No |
|
|
42
|
+
| includeReason | boolean | Whether to include reasoning (default: true) | No |
|
|
43
|
+
| outputFormat | 'json' \| 'text' | Output format (default: 'json') | No |
|
|
44
|
+
| defaultClass | string | Fallback class if classification fails | No |
|
|
45
|
+
| defaultReason | string | Fallback reason if classification fails | No |
|
|
46
|
+
|
|
47
|
+
\*Classes can be provided in the tool parameters or stored in agent memory
|
|
48
|
+
|
|
49
|
+
## Using as a Utility
|
|
50
|
+
|
|
51
|
+
### Import the Utilities
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { toolsLibrary } from '@minded-ai/mindedjs';
|
|
55
|
+
|
|
56
|
+
const { classify, createClassifier, createConversationClassifier, multiClassify } = toolsLibrary.tools['minded-classifier'];
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Direct Classification
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const result = await classify(
|
|
63
|
+
"I can't access my account",
|
|
64
|
+
{
|
|
65
|
+
classes: [
|
|
66
|
+
{ name: 'Technical', description: 'Technical issues' },
|
|
67
|
+
{ name: 'Account', description: 'Account access problems' },
|
|
68
|
+
],
|
|
69
|
+
includeReason: true,
|
|
70
|
+
},
|
|
71
|
+
agent.llm,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
console.log(result);
|
|
75
|
+
// { class: 'Account', reason: 'User cannot access their account', confidence: 0.95 }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Create Reusable Classifiers
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// Simple classifier with string classes
|
|
82
|
+
const sentimentClassifier = createClassifier(['positive', 'negative', 'neutral']);
|
|
83
|
+
|
|
84
|
+
// Classifier with descriptions
|
|
85
|
+
const intentClassifier = createClassifier([
|
|
86
|
+
['greeting', 'User is greeting or saying hello'],
|
|
87
|
+
['question', 'User is asking a question'],
|
|
88
|
+
['complaint', 'User is complaining or expressing dissatisfaction'],
|
|
89
|
+
['goodbye', 'User is saying goodbye or ending conversation'],
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
// Use the classifier
|
|
93
|
+
const sentiment = await sentimentClassifier('This is amazing!', agent.llm);
|
|
94
|
+
const intent = await intentClassifier('Hello there!', agent.llm);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Conversation Classification
|
|
98
|
+
|
|
99
|
+
For classifying entire conversations:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const conversationClassifier = createConversationClassifier([
|
|
103
|
+
{ name: 'Resolved', description: 'Issue was resolved successfully' },
|
|
104
|
+
{ name: 'Escalated', description: 'Needs escalation to human agent' },
|
|
105
|
+
{ name: 'Pending', description: 'Awaiting more information' },
|
|
106
|
+
]);
|
|
107
|
+
|
|
108
|
+
const result = await conversationClassifier(messages, agent.llm);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Multi-Label Classification
|
|
112
|
+
|
|
113
|
+
When content can belong to multiple categories:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const topics = await multiClassify(
|
|
117
|
+
'The app crashes on login and the UI looks outdated',
|
|
118
|
+
{
|
|
119
|
+
classes: [
|
|
120
|
+
{ name: 'Bug', description: 'Software bugs or crashes' },
|
|
121
|
+
{ name: 'UI/UX', description: 'User interface issues' },
|
|
122
|
+
{ name: 'Authentication', description: 'Login or auth problems' },
|
|
123
|
+
],
|
|
124
|
+
maxClasses: 3,
|
|
125
|
+
},
|
|
126
|
+
agent.llm,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
console.log(topics);
|
|
130
|
+
// [
|
|
131
|
+
// { class: 'Bug', reason: 'App crashes', confidence: 0.9 },
|
|
132
|
+
// { class: 'Authentication', reason: 'Login issues', confidence: 0.85 },
|
|
133
|
+
// { class: 'UI/UX', reason: 'Outdated UI', confidence: 0.7 }
|
|
134
|
+
// ]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Configuration Options
|
|
138
|
+
|
|
139
|
+
### ClassifierConfig Interface
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
interface ClassifierConfig {
|
|
143
|
+
classes: ClassDefinition[];
|
|
144
|
+
systemPrompt?: string;
|
|
145
|
+
outputFormat?: 'json' | 'text';
|
|
146
|
+
includeReason?: boolean;
|
|
147
|
+
defaultClass?: string;
|
|
148
|
+
defaultReason?: string;
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Class Definition Formats
|
|
153
|
+
|
|
154
|
+
Classes can be defined in multiple ways:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// Simple strings
|
|
158
|
+
['positive', 'negative', 'neutral'][
|
|
159
|
+
// Tuples with descriptions
|
|
160
|
+
(['technical', 'Technical problems'], ['billing', 'Payment issues'])
|
|
161
|
+
][
|
|
162
|
+
// Objects
|
|
163
|
+
({ name: 'urgent', description: 'Requires immediate attention' }, { name: 'normal', description: 'Standard priority' })
|
|
164
|
+
];
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Example: Customer Support Bot
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { Agent, toolsLibrary } from '@minded-ai/mindedjs';
|
|
171
|
+
import { z } from 'zod';
|
|
172
|
+
|
|
173
|
+
const classifierTool = toolsLibrary.tools['minded-classifier'].default;
|
|
174
|
+
|
|
175
|
+
const agent = new Agent({
|
|
176
|
+
memorySchema: z.object({
|
|
177
|
+
ticketPriority: z.string().optional(),
|
|
178
|
+
ticketCategory: z.string().optional(),
|
|
179
|
+
}),
|
|
180
|
+
config: {
|
|
181
|
+
flows: ['./flows'],
|
|
182
|
+
llm: { provider: 'openai', model: 'gpt-4' },
|
|
183
|
+
},
|
|
184
|
+
tools: [classifierTool],
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Create specialized classifiers
|
|
188
|
+
const priorityClassifier = createClassifier([
|
|
189
|
+
['urgent', 'Requires immediate attention'],
|
|
190
|
+
['high', 'Important but not critical'],
|
|
191
|
+
['normal', 'Standard priority'],
|
|
192
|
+
['low', 'Can be handled later'],
|
|
193
|
+
]);
|
|
194
|
+
|
|
195
|
+
const categoryClassifier = createClassifier([
|
|
196
|
+
['technical', 'Technical issues or bugs'],
|
|
197
|
+
['billing', 'Payment and subscription issues'],
|
|
198
|
+
['feature', 'Feature requests'],
|
|
199
|
+
['other', 'General inquiries'],
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
// Use in message handler
|
|
203
|
+
agent.on('message', async (message) => {
|
|
204
|
+
const [priority, category] = await Promise.all([
|
|
205
|
+
priorityClassifier(message.content, agent.llm),
|
|
206
|
+
categoryClassifier(message.content, agent.llm),
|
|
207
|
+
]);
|
|
208
|
+
|
|
209
|
+
// Update agent memory
|
|
210
|
+
await agent.updateMemory({
|
|
211
|
+
ticketPriority: priority.class,
|
|
212
|
+
ticketCategory: category.class,
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@minded-ai/mindedjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.117",
|
|
4
4
|
"description": "MindedJS is a TypeScript library for building agents.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -66,4 +66,4 @@
|
|
|
66
66
|
"uuid": "^11.1.0",
|
|
67
67
|
"ws": "^8.15.1"
|
|
68
68
|
}
|
|
69
|
-
}
|
|
69
|
+
}
|
package/src/agent.ts
CHANGED
|
@@ -180,6 +180,11 @@ export class Agent {
|
|
|
180
180
|
await this.restoreCheckpoint(restoreCheckpointMessage.sessionId, restoreCheckpointMessage.checkpointId);
|
|
181
181
|
return { success: true };
|
|
182
182
|
});
|
|
183
|
+
|
|
184
|
+
mindedConnection.on(mindedConnectionSocketMessageType.SDK_VERSION_MISMATCH, (data) => {
|
|
185
|
+
logger.warn(`\x1b[33mMindedJS SDK outdated, we recommend upgrading ${data.currentVersion}->${data.requiredVersion}\x1b[0m`);
|
|
186
|
+
logger.warn(`\x1b[33mnpm install @minded-ai/mindedjs / yarn upgrade @minded-ai/mindedjs\x1b[0m`);
|
|
187
|
+
});
|
|
183
188
|
}
|
|
184
189
|
|
|
185
190
|
const [, flows, playbooks] = await Promise.all([this.loadSecrets(), this.loadFlows(config.flows), loadPlaybooks(config.playbooks)]);
|
|
@@ -466,6 +471,11 @@ export class Agent {
|
|
|
466
471
|
let messages: Array<BaseMessage> = [];
|
|
467
472
|
let memoryUpdate = {};
|
|
468
473
|
let sessionType: SessionType = SessionType.TEXT;
|
|
474
|
+
|
|
475
|
+
// Get the current state early to access memory for TRIGGER_EVENT
|
|
476
|
+
const langraphConfig = this.getLangraphConfig(sessionId);
|
|
477
|
+
const state = await this.compiledGraph.getState(langraphConfig);
|
|
478
|
+
|
|
469
479
|
if (triggerName === KnownTriggerNames.DASHBOARD_MESSAGE || triggerName === KnownTriggerNames.VOICE_MESSAGE) {
|
|
470
480
|
// Parse attachments if present
|
|
471
481
|
const attachmentsString = parseAttachments(triggerBody);
|
|
@@ -479,6 +489,7 @@ export class Agent {
|
|
|
479
489
|
triggerName,
|
|
480
490
|
triggerBody,
|
|
481
491
|
sessionId,
|
|
492
|
+
state: state.values,
|
|
482
493
|
});
|
|
483
494
|
if (results.length === 0) {
|
|
484
495
|
if (appName) {
|
|
@@ -503,8 +514,6 @@ export class Agent {
|
|
|
503
514
|
}
|
|
504
515
|
|
|
505
516
|
logger.info({ msg: '[Trigger] Received', triggerName, triggerBody, sessionId });
|
|
506
|
-
const langraphConfig = this.getLangraphConfig(sessionId || uuidv4());
|
|
507
|
-
const state = await this.compiledGraph.getState(langraphConfig);
|
|
508
517
|
const suffixes = Object.values(internalNodesSuffix);
|
|
509
518
|
let nodeToBeInvoked =
|
|
510
519
|
state.next.length > 0
|
|
@@ -570,185 +579,58 @@ export class Agent {
|
|
|
570
579
|
}
|
|
571
580
|
|
|
572
581
|
/**
|
|
573
|
-
* Register an event handler for
|
|
582
|
+
* Register an event handler for agent events. Multiple handlers can be registered for the same event.
|
|
574
583
|
*
|
|
575
|
-
*
|
|
576
|
-
* agent execution, such as trigger events, memory updates, or custom application events.
|
|
577
|
-
* Multiple handlers can be registered for the same event type and will be executed in the order they are registered.
|
|
578
|
-
*
|
|
579
|
-
* ## Available Event Types
|
|
584
|
+
* ## Available Events
|
|
580
585
|
*
|
|
581
586
|
* ### INIT
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
*
|
|
585
|
-
* **
|
|
586
|
-
* ```typescript
|
|
587
|
-
* {
|
|
588
|
-
* state: { // Full initial agent state
|
|
589
|
-
* messages: BaseMessage[]; // Empty array - no messages yet
|
|
590
|
-
* memory: Memory; // Initial memory state (from your schema defaults)
|
|
591
|
-
* triggerInvocations: Array<...>; // Empty array - no triggers invoked yet
|
|
592
|
-
* triggerMetadata: null; // No trigger metadata initially
|
|
593
|
-
* history: HistoryStep[]; // Empty array - no flow history yet
|
|
594
|
-
* sessionId: string; // Session identifier (generated or provided)
|
|
595
|
-
* sessionType: SessionType; // Type of session (TEXT, VOICE, etc.)
|
|
596
|
-
* }
|
|
597
|
-
* }
|
|
598
|
-
* ```
|
|
599
|
-
*
|
|
600
|
-
* **Expected Output:** `void` - Handlers are used for side effects like logging, setup, or initialization tasks
|
|
601
|
-
*
|
|
602
|
-
* **Common Use Cases:**
|
|
603
|
-
* - Session logging and analytics tracking
|
|
604
|
-
* - Resource initialization for new sessions
|
|
605
|
-
* - State validation and verification
|
|
606
|
-
* - External service setup and configuration
|
|
607
|
-
* - Session routing and management
|
|
608
|
-
* - Debugging and troubleshooting
|
|
587
|
+
* Fired when a new session starts.
|
|
588
|
+
* - **Input:** `{ state: AgentState }` - Initial agent state with empty messages/history
|
|
589
|
+
* - **Output:** `void`
|
|
590
|
+
* - **Use for:** Session logging, resource initialization, analytics
|
|
609
591
|
*
|
|
610
592
|
* ### AI_MESSAGE
|
|
611
|
-
*
|
|
612
|
-
*
|
|
613
|
-
* **
|
|
614
|
-
*
|
|
615
|
-
* {
|
|
616
|
-
* message: string; // The AI-generated message content
|
|
617
|
-
* state: { // Full agent state
|
|
618
|
-
* messages: BaseMessage[]; // Conversation messages
|
|
619
|
-
* memory: Memory; // Current memory state (your defined memory schema)
|
|
620
|
-
* triggerInvocations: Array<...>; // Trigger invocation history
|
|
621
|
-
* triggerMetadata: {...} | null; // Current trigger metadata
|
|
622
|
-
* history: HistoryStep[]; // Flow execution history with detailed step information
|
|
623
|
-
* sessionId: string; // Session identifier
|
|
624
|
-
* }
|
|
625
|
-
* }
|
|
626
|
-
* ```
|
|
627
|
-
*
|
|
628
|
-
* **Expected Output:** `void` - Handlers are used for side effects like sending messages to UI
|
|
629
|
-
*
|
|
630
|
-
* **Common Use Cases:**
|
|
631
|
-
* - Real-time chat UI updates with session context
|
|
632
|
-
* - Logging AI responses for analytics or debugging
|
|
633
|
-
* - Message formatting and transformation
|
|
634
|
-
* - Notifications and alerts based on AI responses
|
|
635
|
-
* - Session-based message routing
|
|
593
|
+
* Fired when AI generates a message for the user.
|
|
594
|
+
* - **Input:** `{ message: string, state: AgentState }` - AI message and current state
|
|
595
|
+
* - **Output:** `void`
|
|
596
|
+
* - **Use for:** Sending to UI, logging responses, notifications
|
|
636
597
|
*
|
|
637
598
|
* ### TRIGGER_EVENT
|
|
638
|
-
*
|
|
639
|
-
*
|
|
640
|
-
*
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
649
|
-
* **Expected Output:** One of three possible return types:
|
|
650
|
-
*
|
|
651
|
-
* 1. **Provide Initial State:**
|
|
652
|
-
* ```typescript
|
|
653
|
-
* {
|
|
654
|
-
* messages?: BaseMessage[]; // Initial messages for the conversation
|
|
655
|
-
* memory?: Memory; // Initial memory state
|
|
656
|
-
* sessionId?: string; // Session ID for persistence (resumes existing sessions)
|
|
657
|
-
* }
|
|
658
|
-
* ```
|
|
659
|
-
*
|
|
660
|
-
* 2. **Disqualify the Trigger:**
|
|
661
|
-
* ```typescript
|
|
662
|
-
* false // Rejects/disqualifies the trigger from processing
|
|
663
|
-
* ```
|
|
664
|
-
*
|
|
665
|
-
* 3. **Qualify without Initial State:**
|
|
666
|
-
* ```typescript
|
|
667
|
-
* void // Qualifies the trigger but provides no initial state
|
|
668
|
-
* ```
|
|
669
|
-
*
|
|
670
|
-
* **Common Use Cases:**
|
|
671
|
-
* - Input validation and trigger qualification
|
|
672
|
-
* - Data transformation into standardized formats
|
|
673
|
-
* - Context setting with initial memory state
|
|
674
|
-
* - Access control and business rule enforcement
|
|
675
|
-
* - Routing logic for different trigger types
|
|
676
|
-
*
|
|
677
|
-
* @template E - The event type, constrained to known agent event types
|
|
678
|
-
* @param event - The name of the event to listen for
|
|
679
|
-
* @param handler - The function to call when the event is emitted
|
|
599
|
+
* Fired when a trigger executes. Allows qualifying/transforming trigger inputs.
|
|
600
|
+
* - **Input:** `{ triggerName: string, triggerBody: any }`
|
|
601
|
+
* - **Output Options:**
|
|
602
|
+
* - `{ messages?, memory?, sessionId? }` - Provide initial state
|
|
603
|
+
* - `false` - Disqualify the trigger
|
|
604
|
+
* - `void` - Qualify without initial state
|
|
605
|
+
* - **Use for:** Input validation, data transformation, access control
|
|
606
|
+
*
|
|
607
|
+
* @template E - The event type
|
|
608
|
+
* @param event - Event name to listen for
|
|
609
|
+
* @param handler - Function to call when event fires
|
|
680
610
|
*
|
|
681
611
|
* @example
|
|
682
612
|
* ```typescript
|
|
683
|
-
* //
|
|
613
|
+
* // Session initialization
|
|
684
614
|
* agent.on('INIT', async ({ state }) => {
|
|
685
|
-
* logger.info({ msg: '
|
|
686
|
-
*
|
|
687
|
-
* logger.info({ msg: 'Initial memory:', memory: state.memory });
|
|
688
|
-
*
|
|
689
|
-
* // Setup session-specific resources
|
|
690
|
-
* await initializeSessionResources(state.sessionId);
|
|
691
|
-
*
|
|
692
|
-
* // Log session start for analytics
|
|
693
|
-
* await logSessionStart({
|
|
694
|
-
* sessionId: state.sessionId,
|
|
695
|
-
* sessionType: state.sessionType,
|
|
696
|
-
* timestamp: new Date(),
|
|
697
|
-
* });
|
|
615
|
+
* logger.info({ msg: 'Session started', sessionId: state.sessionId });
|
|
616
|
+
* await initializeResources(state.sessionId);
|
|
698
617
|
* });
|
|
699
618
|
*
|
|
700
|
-
* //
|
|
619
|
+
* // Handle AI messages
|
|
701
620
|
* agent.on('AI_MESSAGE', async ({ message, state }) => {
|
|
702
|
-
*
|
|
703
|
-
* logger.info({ msg: 'Current memory:', output: state.memory });
|
|
704
|
-
* logger.info({ msg: 'Session ID:', output: state.sessionId });
|
|
705
|
-
*
|
|
706
|
-
* // Send to user interface with session context
|
|
707
|
-
* await sendMessageToUser(message, state.sessionId);
|
|
708
|
-
*
|
|
709
|
-
* // Send via WebSocket
|
|
710
|
-
* await websocket.send(JSON.stringify({
|
|
711
|
-
* type: 'ai_message',
|
|
712
|
-
* content: message,
|
|
713
|
-
* sessionId: state.sessionId,
|
|
714
|
-
* memory: state.memory
|
|
715
|
-
* }));
|
|
621
|
+
* await sendToUI(message, state.sessionId);
|
|
716
622
|
* });
|
|
717
623
|
*
|
|
718
|
-
* //
|
|
624
|
+
* // Validate and transform triggers
|
|
719
625
|
* agent.on('TRIGGER_EVENT', async ({ triggerName, triggerBody }) => {
|
|
720
|
-
*
|
|
721
|
-
* if (!isValidInput(triggerBody)) {
|
|
722
|
-
* return false; // Disqualify the trigger
|
|
723
|
-
* }
|
|
724
|
-
*
|
|
725
|
-
* // Business hours check
|
|
726
|
-
* if (triggerName === 'supportRequest' && !isBusinessHours()) {
|
|
727
|
-
* return false;
|
|
728
|
-
* }
|
|
626
|
+
* if (!isValid(triggerBody)) return false;
|
|
729
627
|
*
|
|
730
628
|
* return {
|
|
731
|
-
* memory: {
|
|
732
|
-
* messages: [new HumanMessage('
|
|
733
|
-
* sessionId: triggerBody.userId
|
|
629
|
+
* memory: { validated: true },
|
|
630
|
+
* messages: [new HumanMessage('Request received')],
|
|
631
|
+
* sessionId: triggerBody.userId
|
|
734
632
|
* };
|
|
735
633
|
* });
|
|
736
|
-
*
|
|
737
|
-
* // TRIGGER_EVENT Event Handler - Data Transformation
|
|
738
|
-
* agent.on('TRIGGER_EVENT', async ({ triggerName, triggerBody }) => {
|
|
739
|
-
* if (triggerName === 'emailTrigger') {
|
|
740
|
-
* // Transform email data into structured format
|
|
741
|
-
* const parsedEmail = parseEmailContent(triggerBody);
|
|
742
|
-
*
|
|
743
|
-
* return {
|
|
744
|
-
* memory: {
|
|
745
|
-
* emailSubject: parsedEmail.subject,
|
|
746
|
-
* senderEmail: parsedEmail.from
|
|
747
|
-
* },
|
|
748
|
-
* messages: [new HumanMessage(parsedEmail.content)],
|
|
749
|
-
* };
|
|
750
|
-
* }
|
|
751
|
-
* });
|
|
752
634
|
* ```
|
|
753
635
|
*/
|
|
754
636
|
// Public API for registering event listeners
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { io, Socket } from 'socket.io-client';
|
|
2
|
-
import {
|
|
3
|
-
mindedConnectionSocketMessageType,
|
|
4
|
-
mindedConnectionSocketMessageTypeMap,
|
|
5
|
-
} from './mindedConnectionTypes';
|
|
2
|
+
import { mindedConnectionSocketMessageType, mindedConnectionSocketMessageTypeMap } from './mindedConnectionTypes';
|
|
6
3
|
import { stringify } from 'flatted';
|
|
7
4
|
import { getConfig } from './config';
|
|
8
5
|
import { logger } from '../utils/logger';
|
|
9
6
|
import { wait } from '../utils/wait';
|
|
7
|
+
import * as packageJson from '../../package.json';
|
|
10
8
|
|
|
11
9
|
// Module-level singleton state
|
|
12
10
|
let socket: Socket | null = null;
|
|
@@ -28,20 +26,13 @@ export const on = <E extends keyof mindedConnectionSocketMessageTypeMap>(
|
|
|
28
26
|
listeners[event].push(callback);
|
|
29
27
|
};
|
|
30
28
|
|
|
31
|
-
export const emit = <E extends keyof mindedConnectionSocketMessageTypeMap>(
|
|
32
|
-
event: E,
|
|
33
|
-
message: mindedConnectionSocketMessageTypeMap[E]
|
|
34
|
-
) => {
|
|
29
|
+
export const emit = <E extends keyof mindedConnectionSocketMessageTypeMap>(event: E, message: mindedConnectionSocketMessageTypeMap[E]) => {
|
|
35
30
|
if (socket) {
|
|
36
31
|
socket.emit(event, message);
|
|
37
32
|
}
|
|
38
33
|
};
|
|
39
34
|
|
|
40
|
-
export const awaitEmit = async <T, R>(
|
|
41
|
-
event: mindedConnectionSocketMessageType,
|
|
42
|
-
message: T,
|
|
43
|
-
timeoutMs: number = 5000
|
|
44
|
-
): Promise<R> => {
|
|
35
|
+
export const awaitEmit = async <T, R>(event: mindedConnectionSocketMessageType, message: T, timeoutMs: number = 5000): Promise<R> => {
|
|
45
36
|
if (!socket) {
|
|
46
37
|
throw new Error('Socket is not connected');
|
|
47
38
|
}
|
|
@@ -81,6 +72,15 @@ const waitForConnection = async (): Promise<void> => {
|
|
|
81
72
|
}
|
|
82
73
|
};
|
|
83
74
|
|
|
75
|
+
const getSdkVersion = (): string => {
|
|
76
|
+
try {
|
|
77
|
+
return packageJson.version;
|
|
78
|
+
} catch {
|
|
79
|
+
logger.warn('Could not determine SDK version');
|
|
80
|
+
return 'unknown';
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
84
|
const connect = async (token: string): Promise<void> => {
|
|
85
85
|
const { isDeployed, baseUrl } = getConfig();
|
|
86
86
|
return new Promise<void>((resolve, reject) => {
|
|
@@ -89,6 +89,7 @@ const connect = async (token: string): Promise<void> => {
|
|
|
89
89
|
query: {
|
|
90
90
|
isDeployedAgent: isDeployed,
|
|
91
91
|
token,
|
|
92
|
+
sdkVersion: getSdkVersion(),
|
|
92
93
|
},
|
|
93
94
|
});
|
|
94
95
|
|
|
@@ -39,7 +39,7 @@ export enum mindedConnectionSocketMessageType {
|
|
|
39
39
|
TIMER_TRIGGER = 'timer-trigger',
|
|
40
40
|
RETELL_CALL = 'retell-call',
|
|
41
41
|
RETELL_GET_CALL = 'retell-get-call',
|
|
42
|
-
|
|
42
|
+
SDK_VERSION_MISMATCH = 'sdk-version-mismatch',
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export type mindedConnectionSocketMessageTypeMap = {
|
|
@@ -67,6 +67,7 @@ export type mindedConnectionSocketMessageTypeMap = {
|
|
|
67
67
|
[mindedConnectionSocketMessageType.RESTORE_CHECKPOINT]: RestoreCheckpointRequest;
|
|
68
68
|
[mindedConnectionSocketMessageType.RETELL_CALL]: RetellCall;
|
|
69
69
|
[mindedConnectionSocketMessageType.RETELL_GET_CALL]: RetellGetCall;
|
|
70
|
+
[mindedConnectionSocketMessageType.SDK_VERSION_MISMATCH]: SdkVersionMismatchMessage;
|
|
70
71
|
[mindedConnectionSocketMessageType.UPDATE_STATE]: UpdateStateRequest;
|
|
71
72
|
};
|
|
72
73
|
|
|
@@ -234,7 +235,12 @@ export interface RetellGetCallResponse extends BaseSdkConnectionSocketMessageRes
|
|
|
234
235
|
error?: string;
|
|
235
236
|
}
|
|
236
237
|
|
|
238
|
+
export interface SdkVersionMismatchMessage extends BasemindedConnectionSocketMessage {
|
|
239
|
+
type: mindedConnectionSocketMessageType.SDK_VERSION_MISMATCH;
|
|
240
|
+
currentVersion: string;
|
|
241
|
+
requiredVersion: string;
|
|
242
|
+
}
|
|
237
243
|
export interface UpdateStateRequest extends BasemindedConnectionSocketMessage {
|
|
238
244
|
sessionId: string;
|
|
239
245
|
state: Partial<typeof stateAnnotation.State>;
|
|
240
|
-
}
|
|
246
|
+
}
|