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