@elqnt/agent-sdk 1.0.0

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/index.mjs ADDED
@@ -0,0 +1,615 @@
1
+ import { useState, useRef, useEffect, useCallback } from 'react';
2
+ import { useWebSocketChatBase } from '@elqnt/chat';
3
+
4
+ // src/hooks/useAgent/useAgent.ts
5
+ function useAgentChat(config) {
6
+ const {
7
+ agentId,
8
+ orgId,
9
+ serverBaseUrl,
10
+ userEmail,
11
+ features = {},
12
+ onMessage,
13
+ onConnect,
14
+ onDisconnect,
15
+ onToolCall,
16
+ autoReconnect = true,
17
+ reconnectDelay = 3e3,
18
+ debug = false
19
+ } = config;
20
+ const [messages, setMessages] = useState([]);
21
+ const [currentChat, setCurrentChat] = useState(void 0);
22
+ const [users, setUsers] = useState([]);
23
+ const [currentChatUser, setCurrentChatUser] = useState(void 0);
24
+ const [isWaiting, setIsWaiting] = useState(false);
25
+ const [isWaitingForAgent, setIsWaitingForAgent] = useState(false);
26
+ const [chatKey, setChatKey] = useState(void 0);
27
+ const onMessageRef = useRef(onMessage);
28
+ const onToolCallRef = useRef(onToolCall);
29
+ useEffect(() => {
30
+ onMessageRef.current = onMessage;
31
+ }, [onMessage]);
32
+ useEffect(() => {
33
+ onToolCallRef.current = onToolCall;
34
+ }, [onToolCall]);
35
+ const handleMessage = useCallback(
36
+ (event) => {
37
+ if (debug) {
38
+ console.log("[useAgentChat] Received event:", event.type, event);
39
+ }
40
+ switch (event.type) {
41
+ case "new_chat_created":
42
+ const newChatKey = event.data?.chatKey;
43
+ if (newChatKey) {
44
+ setChatKey(newChatKey);
45
+ }
46
+ break;
47
+ case "load_chat_response":
48
+ const chat = event.data?.chat;
49
+ if (chat) {
50
+ setCurrentChat(chat);
51
+ setChatKey(chat.key);
52
+ setMessages(chat.messages || []);
53
+ setUsers(chat.users || []);
54
+ const currentUser = chat.users?.find((u) => u.email === userEmail);
55
+ setCurrentChatUser(currentUser);
56
+ }
57
+ break;
58
+ case "message":
59
+ const message = event.message;
60
+ if (message) {
61
+ setMessages((prev) => [...prev, message]);
62
+ if (message.role === "ai") {
63
+ setIsWaiting(false);
64
+ }
65
+ }
66
+ break;
67
+ case "typing":
68
+ setIsWaiting(true);
69
+ break;
70
+ case "waiting_for_agent":
71
+ setIsWaitingForAgent(true);
72
+ break;
73
+ case "agent_chat_assigned":
74
+ setIsWaitingForAgent(false);
75
+ break;
76
+ case "chat_ended":
77
+ setChatKey(void 0);
78
+ setCurrentChat(void 0);
79
+ setMessages([]);
80
+ setUsers([]);
81
+ setCurrentChatUser(void 0);
82
+ setIsWaiting(false);
83
+ setIsWaitingForAgent(false);
84
+ break;
85
+ }
86
+ if (onMessageRef.current) {
87
+ onMessageRef.current(event);
88
+ }
89
+ },
90
+ [debug, userEmail]
91
+ );
92
+ const baseHook = useWebSocketChatBase({
93
+ serverBaseUrl,
94
+ orgId,
95
+ clientType: "customer",
96
+ product: "hub",
97
+ // Default product, can be made configurable
98
+ onMessage: handleMessage,
99
+ retryConfig: autoReconnect ? {
100
+ maxRetries: 10,
101
+ intervals: [reconnectDelay, reconnectDelay * 2, reconnectDelay * 3]
102
+ } : { maxRetries: 0 },
103
+ debug
104
+ });
105
+ useEffect(() => {
106
+ if (baseHook.connectionState === "connected" && onConnect) {
107
+ onConnect();
108
+ } else if (baseHook.connectionState === "disconnected" && onDisconnect) {
109
+ onDisconnect();
110
+ }
111
+ }, [baseHook.connectionState, onConnect, onDisconnect]);
112
+ const sendMessage = useCallback(
113
+ async (content, attachments) => {
114
+ if (!chatKey) {
115
+ throw new Error("No active chat session. Call startNewChat() first.");
116
+ }
117
+ if (!content.trim()) {
118
+ throw new Error("Message content cannot be empty.");
119
+ }
120
+ setIsWaiting(true);
121
+ const now = Date.now();
122
+ const event = {
123
+ type: "message",
124
+ orgId,
125
+ chatKey,
126
+ userId: userEmail,
127
+ message: {
128
+ id: `msg-${now}-${Math.random().toString(36).substr(2, 9)}`,
129
+ role: "user",
130
+ content,
131
+ time: now,
132
+ status: "sending",
133
+ senderId: userEmail,
134
+ createdAt: now,
135
+ attachments
136
+ },
137
+ data: {}
138
+ };
139
+ try {
140
+ await baseHook.sendMessage(event, userEmail);
141
+ } catch (error2) {
142
+ setIsWaiting(false);
143
+ throw error2;
144
+ }
145
+ },
146
+ [chatKey, orgId, userEmail, baseHook]
147
+ );
148
+ const startNewChat = useCallback(async () => {
149
+ if (debug) {
150
+ console.log("[useAgentChat] Starting new chat...");
151
+ }
152
+ if (!baseHook.isConnected) {
153
+ await baseHook.connect(userEmail);
154
+ }
155
+ const newChatKey = await baseHook.startNewChat(userEmail, {
156
+ agentId,
157
+ product: "hub"
158
+ });
159
+ setChatKey(newChatKey);
160
+ setMessages([]);
161
+ setUsers([]);
162
+ setIsWaiting(false);
163
+ setIsWaitingForAgent(false);
164
+ if (debug) {
165
+ console.log("[useAgentChat] New chat created:", newChatKey);
166
+ }
167
+ }, [agentId, userEmail, baseHook, debug]);
168
+ const endChat = useCallback(() => {
169
+ if (!chatKey) return;
170
+ const event = {
171
+ type: "end_chat",
172
+ orgId,
173
+ chatKey,
174
+ userId: userEmail,
175
+ data: {}
176
+ };
177
+ baseHook.sendMessage(event, userEmail);
178
+ setChatKey(void 0);
179
+ setMessages([]);
180
+ setCurrentChat(void 0);
181
+ setUsers([]);
182
+ setIsWaiting(false);
183
+ setIsWaitingForAgent(false);
184
+ }, [chatKey, orgId, userEmail, baseHook]);
185
+ const resetChat = useCallback(() => {
186
+ setChatKey(void 0);
187
+ setMessages([]);
188
+ setCurrentChat(void 0);
189
+ setUsers([]);
190
+ setCurrentChatUser(void 0);
191
+ setIsWaiting(false);
192
+ setIsWaitingForAgent(false);
193
+ }, []);
194
+ const clearError = useCallback(() => {
195
+ baseHook.clearError();
196
+ }, [baseHook]);
197
+ useEffect(() => {
198
+ baseHook.connect(userEmail).catch((error2) => {
199
+ console.error("[useAgentChat] Failed to auto-connect:", error2);
200
+ });
201
+ }, []);
202
+ const error = baseHook.error ? {
203
+ code: baseHook.error.code,
204
+ message: baseHook.error.message,
205
+ retryable: baseHook.error.retryable,
206
+ timestamp: baseHook.error.timestamp
207
+ } : void 0;
208
+ return {
209
+ // Chat state
210
+ messages,
211
+ currentChat,
212
+ users,
213
+ currentChatUser,
214
+ connectionState: baseHook.connectionState,
215
+ isConnected: baseHook.isConnected,
216
+ isWaiting,
217
+ isWaitingForAgent,
218
+ status: currentChat?.status,
219
+ chatKey,
220
+ error,
221
+ // Chat actions
222
+ sendMessage,
223
+ startNewChat,
224
+ endChat,
225
+ resetChat,
226
+ disconnect: baseHook.disconnect,
227
+ clearError
228
+ };
229
+ }
230
+ function useAgentTools(config = {}) {
231
+ const {
232
+ tools: initialTools = {},
233
+ onToolExecuted,
234
+ onToolError,
235
+ debug = false
236
+ } = config;
237
+ const [tools, setTools] = useState({});
238
+ const toolHandlersRef = useRef(initialTools);
239
+ const onToolExecutedRef = useRef(onToolExecuted);
240
+ const onToolErrorRef = useRef(onToolError);
241
+ useEffect(() => {
242
+ onToolExecutedRef.current = onToolExecuted;
243
+ }, [onToolExecuted]);
244
+ useEffect(() => {
245
+ onToolErrorRef.current = onToolError;
246
+ }, [onToolError]);
247
+ useEffect(() => {
248
+ toolHandlersRef.current = { ...toolHandlersRef.current, ...initialTools };
249
+ }, [initialTools]);
250
+ const executeClientTool = useCallback(
251
+ async (toolName, params) => {
252
+ const startTime = Date.now();
253
+ if (debug) {
254
+ console.log(`[useAgentTools] Executing tool: ${toolName}`, params);
255
+ }
256
+ const handler = toolHandlersRef.current[toolName];
257
+ if (!handler) {
258
+ const error = {
259
+ code: "TOOL_EXECUTION_FAILED",
260
+ message: `Tool handler not found: ${toolName}`,
261
+ retryable: false,
262
+ timestamp: Date.now(),
263
+ details: { toolName, params }
264
+ };
265
+ if (onToolErrorRef.current) {
266
+ onToolErrorRef.current(toolName, error);
267
+ }
268
+ throw new Error(error.message);
269
+ }
270
+ try {
271
+ const result = await handler(params);
272
+ const executionTime = Date.now() - startTime;
273
+ const executionResult = {
274
+ success: true,
275
+ result,
276
+ executionTime
277
+ };
278
+ if (debug) {
279
+ console.log(
280
+ `[useAgentTools] Tool executed successfully: ${toolName}`,
281
+ executionResult
282
+ );
283
+ }
284
+ if (onToolExecutedRef.current) {
285
+ onToolExecutedRef.current(toolName, executionResult);
286
+ }
287
+ return result;
288
+ } catch (error) {
289
+ const executionTime = Date.now() - startTime;
290
+ const agentError = {
291
+ code: "TOOL_EXECUTION_FAILED",
292
+ message: error instanceof Error ? error.message : "Tool execution failed",
293
+ retryable: true,
294
+ timestamp: Date.now(),
295
+ details: { toolName, params, error }
296
+ };
297
+ const executionResult = {
298
+ success: false,
299
+ error: agentError,
300
+ executionTime
301
+ };
302
+ if (debug) {
303
+ console.error(`[useAgentTools] Tool execution failed: ${toolName}`, agentError);
304
+ }
305
+ if (onToolErrorRef.current) {
306
+ onToolErrorRef.current(toolName, agentError);
307
+ }
308
+ if (onToolExecutedRef.current) {
309
+ onToolExecutedRef.current(toolName, executionResult);
310
+ }
311
+ throw agentError;
312
+ }
313
+ },
314
+ [debug]
315
+ );
316
+ const registerTool = useCallback(
317
+ (toolName, handler) => {
318
+ if (debug) {
319
+ console.log(`[useAgentTools] Registering tool: ${toolName}`);
320
+ }
321
+ toolHandlersRef.current[toolName] = handler;
322
+ setTools((prev) => ({
323
+ ...prev,
324
+ [toolName]: {
325
+ id: toolName,
326
+ name: toolName,
327
+ title: toolName,
328
+ description: `Custom tool: ${toolName}`,
329
+ inputSchema: { type: "object", properties: {} },
330
+ configSchema: { type: "object", properties: {} },
331
+ enabled: true,
332
+ isSystem: false,
333
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
334
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
335
+ }
336
+ }));
337
+ },
338
+ [debug]
339
+ );
340
+ const unregisterTool = useCallback(
341
+ (toolName) => {
342
+ if (debug) {
343
+ console.log(`[useAgentTools] Unregistering tool: ${toolName}`);
344
+ }
345
+ delete toolHandlersRef.current[toolName];
346
+ setTools((prev) => {
347
+ const newTools = { ...prev };
348
+ delete newTools[toolName];
349
+ return newTools;
350
+ });
351
+ },
352
+ [debug]
353
+ );
354
+ const hasToolHandler = useCallback((toolName) => {
355
+ return toolName in toolHandlersRef.current;
356
+ }, []);
357
+ return {
358
+ tools,
359
+ executeClientTool,
360
+ registerTool,
361
+ unregisterTool,
362
+ hasToolHandler
363
+ };
364
+ }
365
+
366
+ // src/hooks/useAgent/useAgent.ts
367
+ function useAgent(config) {
368
+ const {
369
+ agentId,
370
+ tools: toolHandlers = {},
371
+ initialMetadata = {},
372
+ onCSATSubmit,
373
+ debug = false
374
+ } = config;
375
+ const [agent, setAgent] = useState(void 0);
376
+ const [metadata, setMetadata] = useState(initialMetadata);
377
+ const [csatSurvey, setCSATSurvey] = useState(void 0);
378
+ const onCSATSubmitRef = useRef(onCSATSubmit);
379
+ useEffect(() => {
380
+ onCSATSubmitRef.current = onCSATSubmit;
381
+ }, [onCSATSubmit]);
382
+ const chatHook = useAgentChat({
383
+ ...config,
384
+ onMessage: (event) => {
385
+ if (event.type === "show_csat_survey") {
386
+ const survey = event.data?.survey;
387
+ if (survey) {
388
+ setCSATSurvey(survey);
389
+ }
390
+ }
391
+ if (event.type === "sync_metadata_response") {
392
+ const newMetadata = event.data?.metadata;
393
+ if (newMetadata) {
394
+ setMetadata((prev) => ({ ...prev, ...newMetadata }));
395
+ }
396
+ }
397
+ if (config.onMessage) {
398
+ config.onMessage(event);
399
+ }
400
+ },
401
+ onToolCall: (toolName, params) => {
402
+ if (toolsHook.hasToolHandler(toolName)) {
403
+ toolsHook.executeClientTool(toolName, params).then((result) => {
404
+ if (debug) {
405
+ console.log(`[useAgent] Tool executed: ${toolName}`, result);
406
+ }
407
+ const event = {
408
+ type: "tool_result",
409
+ orgId: config.orgId,
410
+ chatKey: chatHook.chatKey || "",
411
+ userId: config.userEmail,
412
+ data: {
413
+ toolName,
414
+ result,
415
+ success: true
416
+ }
417
+ };
418
+ chatHook.sendMessage(JSON.stringify(event));
419
+ }).catch((error) => {
420
+ console.error(`[useAgent] Tool execution failed: ${toolName}`, error);
421
+ const event = {
422
+ type: "tool_result",
423
+ orgId: config.orgId,
424
+ chatKey: chatHook.chatKey || "",
425
+ userId: config.userEmail,
426
+ data: {
427
+ toolName,
428
+ error: error.message,
429
+ success: false
430
+ }
431
+ };
432
+ chatHook.sendMessage(JSON.stringify(event));
433
+ });
434
+ }
435
+ if (config.onToolCall) {
436
+ config.onToolCall(toolName, params);
437
+ }
438
+ }
439
+ });
440
+ const toolsHook = useAgentTools({
441
+ tools: toolHandlers,
442
+ debug
443
+ });
444
+ const updateMetadata = useCallback(
445
+ (updates) => {
446
+ const newMetadata = { ...metadata, ...updates };
447
+ setMetadata(newMetadata);
448
+ if (chatHook.chatKey && chatHook.isConnected) {
449
+ const event = {
450
+ type: "update_metadata",
451
+ orgId: config.orgId,
452
+ chatKey: chatHook.chatKey,
453
+ userId: config.userEmail,
454
+ data: { metadata: newMetadata }
455
+ };
456
+ chatHook.sendMessage(JSON.stringify(event)).catch((error) => {
457
+ console.error("[useAgent] Failed to update metadata:", error);
458
+ });
459
+ }
460
+ },
461
+ [metadata, chatHook, config.orgId, config.userEmail]
462
+ );
463
+ const clearMetadata = useCallback(() => {
464
+ setMetadata({});
465
+ if (chatHook.chatKey && chatHook.isConnected) {
466
+ const event = {
467
+ type: "update_metadata",
468
+ orgId: config.orgId,
469
+ chatKey: chatHook.chatKey,
470
+ userId: config.userEmail,
471
+ data: { metadata: {} }
472
+ };
473
+ chatHook.sendMessage(JSON.stringify(event)).catch((error) => {
474
+ console.error("[useAgent] Failed to clear metadata:", error);
475
+ });
476
+ }
477
+ }, [chatHook, config.orgId, config.userEmail]);
478
+ const submitCSATResponse = useCallback(
479
+ (response) => {
480
+ if (!csatSurvey) {
481
+ console.warn("[useAgent] No CSAT survey available");
482
+ return;
483
+ }
484
+ const event = {
485
+ type: "csat_response",
486
+ orgId: config.orgId,
487
+ chatKey: chatHook.chatKey || "",
488
+ userId: config.userEmail,
489
+ data: {
490
+ response
491
+ }
492
+ };
493
+ chatHook.sendMessage(JSON.stringify(event)).then(() => {
494
+ setCSATSurvey(void 0);
495
+ if (onCSATSubmitRef.current) {
496
+ onCSATSubmitRef.current(response);
497
+ }
498
+ }).catch((error) => {
499
+ console.error("[useAgent] Failed to submit CSAT response:", error);
500
+ });
501
+ },
502
+ [csatSurvey, chatHook, config.orgId, config.userEmail]
503
+ );
504
+ const dismissCSAT = useCallback(() => {
505
+ setCSATSurvey(void 0);
506
+ }, []);
507
+ const logEvent = useCallback(
508
+ async (eventData) => {
509
+ if (!config.features?.analytics) {
510
+ return;
511
+ }
512
+ const event = {
513
+ type: "analytics_event",
514
+ orgId: config.orgId,
515
+ chatKey: chatHook.chatKey || "",
516
+ userId: config.userEmail,
517
+ data: {
518
+ ...eventData,
519
+ timestamp: Date.now(),
520
+ agentId
521
+ }
522
+ };
523
+ try {
524
+ await chatHook.sendMessage(JSON.stringify(event));
525
+ } catch (error) {
526
+ console.error("[useAgent] Failed to log analytics event:", error);
527
+ }
528
+ },
529
+ [config.features, config.orgId, config.userEmail, chatHook, agentId]
530
+ );
531
+ useEffect(() => {
532
+ setAgent({
533
+ id: agentId,
534
+ orgId: config.orgId,
535
+ product: "hub",
536
+ type: "react",
537
+ subType: "react",
538
+ name: agentId,
539
+ title: "AI Agent",
540
+ description: "AI-powered assistant",
541
+ status: "active",
542
+ version: "1.0.0",
543
+ provider: "azure-openai",
544
+ model: "gpt-4.1",
545
+ temperature: 0.7,
546
+ maxTokens: 4e3,
547
+ systemPrompt: "",
548
+ isDefault: false,
549
+ isPublic: false,
550
+ csatConfig: {
551
+ enabled: false,
552
+ survey: {
553
+ questions: [],
554
+ timeThreshold: 5,
555
+ closeOnResponse: true
556
+ }
557
+ },
558
+ handoffConfig: {
559
+ enabled: false,
560
+ triggerKeywords: [],
561
+ handoffMessage: ""
562
+ },
563
+ configSchema: {
564
+ type: "object",
565
+ properties: {}
566
+ },
567
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
568
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
569
+ createdBy: config.userEmail,
570
+ updatedBy: config.userEmail
571
+ });
572
+ }, [agentId, config.orgId]);
573
+ return {
574
+ // Agent info
575
+ agent,
576
+ // Chat functionality (from useAgentChat)
577
+ messages: chatHook.messages,
578
+ currentChat: chatHook.currentChat,
579
+ users: chatHook.users,
580
+ currentChatUser: chatHook.currentChatUser,
581
+ connectionState: chatHook.connectionState,
582
+ isConnected: chatHook.isConnected,
583
+ isWaiting: chatHook.isWaiting,
584
+ isWaitingForAgent: chatHook.isWaitingForAgent,
585
+ status: chatHook.status,
586
+ chatKey: chatHook.chatKey,
587
+ error: chatHook.error,
588
+ sendMessage: chatHook.sendMessage,
589
+ startNewChat: chatHook.startNewChat,
590
+ endChat: chatHook.endChat,
591
+ resetChat: chatHook.resetChat,
592
+ disconnect: chatHook.disconnect,
593
+ clearError: chatHook.clearError,
594
+ // Tools functionality (from useAgentTools)
595
+ tools: toolsHook.tools,
596
+ executeClientTool: toolsHook.executeClientTool,
597
+ registerTool: toolsHook.registerTool,
598
+ unregisterTool: toolsHook.unregisterTool,
599
+ hasToolHandler: toolsHook.hasToolHandler,
600
+ // Metadata management
601
+ metadata,
602
+ updateMetadata,
603
+ clearMetadata,
604
+ // CSAT
605
+ csatSurvey,
606
+ submitCSATResponse,
607
+ dismissCSAT,
608
+ // Analytics
609
+ logEvent
610
+ };
611
+ }
612
+
613
+ export { useAgent, useAgentChat, useAgentTools };
614
+ //# sourceMappingURL=index.mjs.map
615
+ //# sourceMappingURL=index.mjs.map