@automattic/agenttic-client 0.1.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,2137 @@
1
+ import {
2
+ BarChart,
3
+ ChartBlock,
4
+ LineChart,
5
+ createChartBlock
6
+ } from "./chunk-LAB4XYXR.js";
7
+
8
+ // src/react/useClientContext.ts
9
+ import { useMemo } from "@wordpress/element";
10
+
11
+ // src/client/utils/logger.ts
12
+ var logger = (message, ...args) => {
13
+ if (isDebugEnabled()) {
14
+ console.log(`[agenttic-client] ${message}`, ...args);
15
+ }
16
+ };
17
+ function isDebugEnabled() {
18
+ return typeof globalThis !== "undefined" && "window" in globalThis && globalThis.window?.DEBUG === "agenttic-client";
19
+ }
20
+ function formatObject(obj) {
21
+ return JSON.stringify(obj, null, 2);
22
+ }
23
+ function log(message, ...args) {
24
+ console.log(`[agenttic-client] ${message}`, ...args);
25
+ }
26
+
27
+ // src/react/useClientContext.ts
28
+ function useClientContext(getClientContextCallback) {
29
+ const contextProvider = useMemo(() => {
30
+ if (!getClientContextCallback) {
31
+ return void 0;
32
+ }
33
+ const provider = {
34
+ getClientContext: () => {
35
+ try {
36
+ const context = getClientContextCallback();
37
+ return context || {};
38
+ } catch (error) {
39
+ logger("Error getting client context: %O", error);
40
+ return {};
41
+ }
42
+ }
43
+ };
44
+ return provider;
45
+ }, [getClientContextCallback]);
46
+ return contextProvider;
47
+ }
48
+
49
+ // src/react/useClientTools.ts
50
+ import { useCallback, useMemo as useMemo2 } from "@wordpress/element";
51
+ function useClientTools(getClientTools, executeTool) {
52
+ const stableGetAvailableTools = useCallback(async () => {
53
+ if (!getClientTools) {
54
+ return [];
55
+ }
56
+ try {
57
+ return await getClientTools();
58
+ } catch (error) {
59
+ logger("Error getting available tools: %O", error);
60
+ return [];
61
+ }
62
+ }, [getClientTools]);
63
+ const stableExecuteTool = useCallback(
64
+ async (toolId, args) => {
65
+ if (!executeTool) {
66
+ throw new Error("No executeTool callback provided");
67
+ }
68
+ try {
69
+ return await executeTool(toolId, args);
70
+ } catch (error) {
71
+ logger("Error executing tool %s: %O", toolId, error);
72
+ throw error;
73
+ }
74
+ },
75
+ [executeTool]
76
+ );
77
+ const toolProvider = useMemo2(() => {
78
+ if (!getClientTools) {
79
+ return void 0;
80
+ }
81
+ return {
82
+ getAvailableTools: stableGetAvailableTools,
83
+ executeTool: stableExecuteTool
84
+ };
85
+ }, [stableGetAvailableTools, stableExecuteTool, getClientTools]);
86
+ return toolProvider;
87
+ }
88
+
89
+ // src/react/useAgentChat.ts
90
+ import { useCallback as useCallback3, useEffect, useMemo as useMemo3, useRef, useState as useState2 } from "react";
91
+
92
+ // src/client/utils/core.ts
93
+ function generateRandomId() {
94
+ const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
95
+ let result = "";
96
+ for (let i = 0; i < 8; i++) {
97
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
98
+ }
99
+ return result;
100
+ }
101
+ function generateMessageId() {
102
+ return generateRandomId();
103
+ }
104
+ function createRequestId() {
105
+ return `req-${generateRandomId()}`;
106
+ }
107
+ function createTaskId() {
108
+ return `task-${generateRandomId()}`;
109
+ }
110
+ function createTextPart(text) {
111
+ return {
112
+ type: "text",
113
+ text
114
+ };
115
+ }
116
+ function createSendMessageRequest(params, method = "message/send") {
117
+ return {
118
+ jsonrpc: "2.0",
119
+ id: createRequestId(),
120
+ method,
121
+ params: {
122
+ id: params.id || createTaskId(),
123
+ ...params
124
+ }
125
+ };
126
+ }
127
+ function extractTextFromMessage(message) {
128
+ if (!message || !message.parts || !Array.isArray(message.parts)) {
129
+ return "";
130
+ }
131
+ return message.parts.filter((part) => part.type === "text").map((part) => part.text).join(" ");
132
+ }
133
+ function createToolDataPart(tool) {
134
+ return {
135
+ type: "data",
136
+ data: {
137
+ toolId: tool.id,
138
+ toolName: tool.name,
139
+ description: tool.description,
140
+ inputSchema: tool.input_schema
141
+ },
142
+ metadata: {}
143
+ };
144
+ }
145
+ function extractToolCallsFromMessage(message) {
146
+ if (!message || !message.parts || !Array.isArray(message.parts)) {
147
+ return [];
148
+ }
149
+ return message.parts.filter(
150
+ (part) => part.type === "data" && "toolCallId" in part.data && "toolId" in part.data && "arguments" in part.data
151
+ );
152
+ }
153
+ function createToolResultDataPart(toolCallId, toolId, result, error) {
154
+ return {
155
+ type: "data",
156
+ data: {
157
+ toolCallId,
158
+ toolId,
159
+ result
160
+ },
161
+ metadata: error ? { error } : void 0
162
+ };
163
+ }
164
+ function createContextDataPart(clientContext) {
165
+ return {
166
+ type: "data",
167
+ data: {
168
+ clientContext
169
+ },
170
+ metadata: {}
171
+ };
172
+ }
173
+ function createTextMessage(text) {
174
+ return {
175
+ role: "user",
176
+ parts: [createTextPart(text)],
177
+ kind: "message",
178
+ messageId: generateMessageId(),
179
+ metadata: {
180
+ timestamp: Date.now()
181
+ }
182
+ };
183
+ }
184
+ function createAgentTextMessage(text) {
185
+ return {
186
+ role: "agent",
187
+ parts: [createTextPart(text)],
188
+ kind: "message",
189
+ messageId: generateMessageId(),
190
+ metadata: {
191
+ timestamp: Date.now()
192
+ }
193
+ };
194
+ }
195
+ function processToolExecutionResult(executionResult) {
196
+ if (executionResult && typeof executionResult === "object" && "result" in executionResult) {
197
+ return {
198
+ result: executionResult.result,
199
+ returnToAgent: executionResult.returnToAgent !== false,
200
+ // Default to true
201
+ agentMessage: executionResult.agentMessage
202
+ // Pass through agentMessage if present
203
+ };
204
+ }
205
+ return {
206
+ result: executionResult,
207
+ returnToAgent: true
208
+ };
209
+ }
210
+ function createToolResultMessage(toolResults, historyDataParts = []) {
211
+ return {
212
+ role: "user",
213
+ kind: "message",
214
+ parts: [...historyDataParts, ...toolResults],
215
+ messageId: generateMessageId(),
216
+ metadata: {
217
+ timestamp: Date.now()
218
+ }
219
+ };
220
+ }
221
+
222
+ // src/client/utils/internal/messages.ts
223
+ async function enhanceMessageWithTools(message, toolProvider) {
224
+ if (!toolProvider) {
225
+ return message;
226
+ }
227
+ try {
228
+ const tools = await toolProvider.getAvailableTools();
229
+ if (tools.length === 0) {
230
+ return message;
231
+ }
232
+ const toolParts = tools.map(createToolDataPart);
233
+ return {
234
+ ...message,
235
+ parts: [...message.parts, ...toolParts]
236
+ };
237
+ } catch (error) {
238
+ logger("Warning: Failed to get tools: %s", error);
239
+ return message;
240
+ }
241
+ }
242
+ function enhanceMessageWithContext(message, contextProvider) {
243
+ if (!contextProvider) {
244
+ return message;
245
+ }
246
+ try {
247
+ const clientContext = contextProvider.getClientContext();
248
+ if (!clientContext || Object.keys(clientContext).length === 0) {
249
+ return message;
250
+ }
251
+ const contextPart = createContextDataPart(clientContext);
252
+ return {
253
+ ...message,
254
+ parts: [...message.parts, contextPart]
255
+ };
256
+ } catch (error) {
257
+ logger("Warning: Failed to get context: %s", error);
258
+ return message;
259
+ }
260
+ }
261
+ async function enhanceMessage(message, toolProvider, contextProvider) {
262
+ let enhancedMessage = await enhanceMessageWithTools(
263
+ message,
264
+ toolProvider
265
+ );
266
+ enhancedMessage = enhanceMessageWithContext(
267
+ enhancedMessage,
268
+ contextProvider
269
+ );
270
+ const { metadata, ...messageForAgent } = enhancedMessage;
271
+ return messageForAgent;
272
+ }
273
+
274
+ // src/client/utils/internal/streaming.ts
275
+ function parseStreamChunk(chunk, buffer = "") {
276
+ const events = [];
277
+ const currentStreamData = buffer + chunk;
278
+ let eventPayload = "";
279
+ let lastCompleteEventEnd = 0;
280
+ let searchStartIndex = 0;
281
+ while (searchStartIndex < currentStreamData.length) {
282
+ const newlineIndex = currentStreamData.indexOf(
283
+ "\n",
284
+ searchStartIndex
285
+ );
286
+ const line = newlineIndex === -1 ? currentStreamData.substring(searchStartIndex) : currentStreamData.substring(searchStartIndex, newlineIndex);
287
+ if (line.startsWith("data:")) {
288
+ if (eventPayload !== "") {
289
+ eventPayload += "\n";
290
+ }
291
+ eventPayload += line.substring(
292
+ line.startsWith("data: ") ? 6 : 5
293
+ );
294
+ } else if (line.trim() === "") {
295
+ if (eventPayload) {
296
+ try {
297
+ events.push(JSON.parse(eventPayload));
298
+ lastCompleteEventEnd = newlineIndex === -1 ? currentStreamData.length : newlineIndex + 1;
299
+ } catch (e) {
300
+ logger("Failed to parse SSE event: %o", e);
301
+ logger("Problematic payload: %s", eventPayload);
302
+ }
303
+ eventPayload = "";
304
+ }
305
+ }
306
+ if (newlineIndex === -1) {
307
+ searchStartIndex = currentStreamData.length;
308
+ } else {
309
+ searchStartIndex = newlineIndex + 1;
310
+ }
311
+ }
312
+ const nextBuffer = currentStreamData.substring(lastCompleteEventEnd);
313
+ return { events, nextBuffer };
314
+ }
315
+ async function* parseSSEStream(stream) {
316
+ const reader = stream.getReader();
317
+ const decoder = new TextDecoder();
318
+ let buffer = "";
319
+ try {
320
+ while (true) {
321
+ const { done, value } = await reader.read();
322
+ if (done) {
323
+ break;
324
+ }
325
+ const chunk = decoder.decode(value, { stream: true });
326
+ const { events, nextBuffer } = parseStreamChunk(chunk, buffer);
327
+ if (events && Array.isArray(events)) {
328
+ for (const event of events) {
329
+ if (event.error) {
330
+ throw new Error(
331
+ `Streaming error: ${event.error.message}`
332
+ );
333
+ }
334
+ if (event.result && event.result.status) {
335
+ const update = {
336
+ id: event.result.id,
337
+ status: event.result.status,
338
+ final: event.result.status.state === "completed" || event.result.status.state === "failed" || event.result.status.state === "canceled",
339
+ text: extractTextFromMessage(
340
+ event.result.status?.message || {
341
+ role: "agent",
342
+ parts: []
343
+ }
344
+ )
345
+ };
346
+ yield update;
347
+ }
348
+ }
349
+ }
350
+ buffer = nextBuffer;
351
+ }
352
+ } finally {
353
+ reader.releaseLock();
354
+ }
355
+ }
356
+
357
+ // src/client/utils/internal/errors.ts
358
+ function handleRequestError(error, timeoutId, operation = "request") {
359
+ clearTimeout(timeoutId);
360
+ logger("%s failed with error: %O", operation, error);
361
+ if (error instanceof Error) {
362
+ logger("Error message: %s", error.message);
363
+ logger("Error stack: %s", error.stack);
364
+ }
365
+ throw error;
366
+ }
367
+ function validateHttpResponse(response, operation = "request") {
368
+ if (!response.ok) {
369
+ throw new Error(`HTTP error! status: ${response.status}`);
370
+ }
371
+ }
372
+ function validateJsonRpcResponse(data, operation = "request") {
373
+ if (data.error) {
374
+ throw new Error(`A2A ${operation} error: ${data.error.message}`);
375
+ }
376
+ if (!data.result) {
377
+ throw new Error(`No result in ${operation} response`);
378
+ }
379
+ return data.result;
380
+ }
381
+ function validateStreamingResponse(response, operation = "streaming request") {
382
+ validateHttpResponse(response, operation);
383
+ if (!response.body) {
384
+ throw new Error(`No response body for ${operation}`);
385
+ }
386
+ }
387
+ function createTimeoutHandler(timeout, operation = "request") {
388
+ const controller = new AbortController();
389
+ const timeoutId = setTimeout(
390
+ () => controller.abort(),
391
+ timeout
392
+ );
393
+ return { timeoutId, controller };
394
+ }
395
+
396
+ // src/client/utils/internal/requests.ts
397
+ function constructAgentUrl(agentUrl, agentId) {
398
+ return `${agentUrl}/${agentId}`;
399
+ }
400
+ function logRequest(method, url, headers, body) {
401
+ logger("Request: %s %s", method, url);
402
+ logger("Headers: %o", headers);
403
+ if (body) {
404
+ logger("Body: %s", formatObject(body));
405
+ }
406
+ }
407
+ async function getHeaders(authProvider, isStreaming = false) {
408
+ const baseHeaders = {
409
+ "Content-Type": "application/json"
410
+ };
411
+ if (isStreaming) {
412
+ baseHeaders.Accept = "text/event-stream";
413
+ }
414
+ if (authProvider) {
415
+ const authHeaders = await authProvider();
416
+ return { ...baseHeaders, ...authHeaders };
417
+ }
418
+ return baseHeaders;
419
+ }
420
+ function createFetchOptions(headers, body, signal) {
421
+ return {
422
+ method: "POST",
423
+ headers,
424
+ body,
425
+ signal
426
+ };
427
+ }
428
+ async function prepareRequest(params, config, options, toolProvider, contextProvider, defaultSessionId) {
429
+ const { message, sessionId, taskId, metadata } = params;
430
+ const { agentId, agentUrl, authProvider, proxy } = config;
431
+ const { isStreaming = false } = options;
432
+ const effectiveSessionId = sessionId || defaultSessionId;
433
+ const fullAgentUrl = constructAgentUrl(agentUrl, agentId);
434
+ const enhancedMessage = await enhanceMessage(
435
+ message,
436
+ toolProvider,
437
+ contextProvider
438
+ );
439
+ const request = createSendMessageRequest(
440
+ {
441
+ id: taskId,
442
+ sessionId: effectiveSessionId,
443
+ message: enhancedMessage,
444
+ metadata
445
+ },
446
+ isStreaming ? "message/stream" : "message/send"
447
+ );
448
+ const headers = await getHeaders(authProvider, isStreaming);
449
+ logRequest("POST", fullAgentUrl, headers, request);
450
+ return {
451
+ request,
452
+ headers,
453
+ enhancedMessage,
454
+ effectiveSessionId,
455
+ fullAgentUrl
456
+ };
457
+ }
458
+ async function executeRequest(preparedRequest, config) {
459
+ const { request, headers, fullAgentUrl } = preparedRequest;
460
+ const { timeout } = config;
461
+ const { timeoutId, controller } = createTimeoutHandler(
462
+ timeout,
463
+ "request"
464
+ );
465
+ try {
466
+ const options = createFetchOptions(
467
+ headers,
468
+ JSON.stringify(request),
469
+ controller.signal
470
+ );
471
+ logger("Making request to %s with options: %O", fullAgentUrl, {
472
+ method: options.method,
473
+ headers: options.headers
474
+ });
475
+ const response = await fetch(fullAgentUrl, options);
476
+ clearTimeout(timeoutId);
477
+ validateHttpResponse(response, "request");
478
+ const data = await response.json();
479
+ logger(
480
+ "Response from %s: %d %O",
481
+ fullAgentUrl,
482
+ response.status,
483
+ formatObject(data)
484
+ );
485
+ return validateJsonRpcResponse(data, "request");
486
+ } catch (error) {
487
+ handleRequestError(error, timeoutId, "request");
488
+ }
489
+ }
490
+ async function* executeStreamingRequest(preparedRequest, config, options) {
491
+ const { request, headers, fullAgentUrl } = preparedRequest;
492
+ const {} = config;
493
+ const { streamingTimeout = 6e4 } = options;
494
+ const { timeoutId, controller } = createTimeoutHandler(
495
+ streamingTimeout,
496
+ "streaming request"
497
+ );
498
+ try {
499
+ const fetchOptions = createFetchOptions(
500
+ headers,
501
+ JSON.stringify(request),
502
+ controller.signal
503
+ );
504
+ const response = await fetch(fullAgentUrl, fetchOptions);
505
+ clearTimeout(timeoutId);
506
+ validateStreamingResponse(response, "streaming request");
507
+ yield* parseSSEStream(response.body);
508
+ } catch (error) {
509
+ handleRequestError(error, timeoutId, "streaming request");
510
+ }
511
+ }
512
+
513
+ // src/client/index.ts
514
+ var DEFAULT_TIMEOUT = 12e4;
515
+ async function executeToolCallBatch(toolCalls, toolProvider, messageId) {
516
+ const results = [];
517
+ const agentMessages = [];
518
+ let shouldReturnToAgent = false;
519
+ for (const toolCall of toolCalls) {
520
+ const { toolCallId, toolId, arguments: args } = toolCall.data;
521
+ try {
522
+ const executionResult = await toolProvider.executeTool(
523
+ toolId,
524
+ args,
525
+ messageId,
526
+ toolCallId
527
+ );
528
+ const { result, returnToAgent, agentMessage } = processToolExecutionResult(executionResult);
529
+ if (returnToAgent) {
530
+ shouldReturnToAgent = true;
531
+ }
532
+ if (agentMessage) {
533
+ agentMessages.push(createAgentTextMessage(agentMessage));
534
+ }
535
+ results.push(
536
+ createToolResultDataPart(
537
+ toolCallId,
538
+ toolId,
539
+ result
540
+ )
541
+ );
542
+ } catch (error) {
543
+ shouldReturnToAgent = true;
544
+ results.push(
545
+ createToolResultDataPart(
546
+ toolCallId,
547
+ toolId,
548
+ void 0,
549
+ error instanceof Error ? error.message : String(error)
550
+ )
551
+ );
552
+ }
553
+ }
554
+ return { results, shouldReturnToAgent, agentMessages };
555
+ }
556
+ function conversationHistoryToDataParts(conversationHistory) {
557
+ const historyParts = [];
558
+ for (const message of conversationHistory) {
559
+ for (const part of message.parts) {
560
+ if (part.type === "text") {
561
+ historyParts.push({
562
+ type: "data",
563
+ data: {
564
+ role: message.role,
565
+ text: part.text
566
+ }
567
+ });
568
+ } else if (part.type === "data") {
569
+ historyParts.push(part);
570
+ }
571
+ }
572
+ }
573
+ return historyParts;
574
+ }
575
+ async function continueTask(taskId, message, requestConfig, toolProvider, contextProvider, sessionId) {
576
+ const continueParams = {
577
+ message,
578
+ taskId,
579
+ sessionId: void 0
580
+ // Use task's session
581
+ };
582
+ const preparedRequest = await prepareRequest(
583
+ continueParams,
584
+ requestConfig,
585
+ { isStreaming: false },
586
+ toolProvider,
587
+ contextProvider,
588
+ sessionId
589
+ );
590
+ return await executeRequest(preparedRequest, requestConfig);
591
+ }
592
+ async function continueTaskStreamed(taskId, message, requestConfig, toolProvider, contextProvider, sessionId) {
593
+ const continueParams = {
594
+ message,
595
+ taskId,
596
+ sessionId: void 0
597
+ // Use task's session
598
+ };
599
+ const preparedRequest = await prepareRequest(
600
+ continueParams,
601
+ requestConfig,
602
+ { isStreaming: true },
603
+ toolProvider,
604
+ contextProvider,
605
+ sessionId
606
+ );
607
+ const stream = executeStreamingRequest(preparedRequest, requestConfig, {
608
+ isStreaming: true
609
+ });
610
+ return processAgentResponseStream(
611
+ stream,
612
+ toolProvider,
613
+ contextProvider,
614
+ requestConfig,
615
+ sessionId,
616
+ true,
617
+ // withHistory
618
+ []
619
+ // newConversationParts - empty for continueTask
620
+ );
621
+ }
622
+ async function* processAgentResponseStream(stream, toolProvider, contextProvider, requestConfig, sessionId, withHistory = true, newConversationParts = []) {
623
+ for await (const update of stream) {
624
+ yield update;
625
+ if (update.status.state === "input-required" && update.status.message && toolProvider) {
626
+ const toolCalls = extractToolCallsFromMessage(
627
+ update.status.message
628
+ );
629
+ if (toolCalls.length > 0) {
630
+ const toolResults = [];
631
+ let shouldReturnToAgent = false;
632
+ const toolParts = [];
633
+ const agentMessages = [];
634
+ for (const toolCall of toolCalls) {
635
+ const {
636
+ toolCallId,
637
+ toolId,
638
+ arguments: args
639
+ } = toolCall.data;
640
+ try {
641
+ const executionResult = await toolProvider.executeTool(
642
+ toolId,
643
+ args,
644
+ update.status?.message?.messageId,
645
+ toolCallId
646
+ );
647
+ const { result, returnToAgent, agentMessage } = processToolExecutionResult(executionResult);
648
+ if (returnToAgent) {
649
+ shouldReturnToAgent = true;
650
+ }
651
+ if (agentMessage) {
652
+ agentMessages.push(
653
+ createAgentTextMessage(agentMessage)
654
+ );
655
+ }
656
+ const toolResult = createToolResultDataPart(
657
+ toolCallId,
658
+ toolId,
659
+ result
660
+ );
661
+ toolResults.push(toolResult);
662
+ toolParts.push(toolResult);
663
+ } catch (error) {
664
+ const toolResult = createToolResultDataPart(
665
+ toolCallId,
666
+ toolId,
667
+ void 0,
668
+ error instanceof Error ? error.message : String(error)
669
+ );
670
+ toolResults.push(toolResult);
671
+ toolParts.push(toolResult);
672
+ }
673
+ }
674
+ newConversationParts.push(update.status.message);
675
+ if (shouldReturnToAgent) {
676
+ const historyDataParts = conversationHistoryToDataParts(newConversationParts);
677
+ const toolResultMessage = createToolResultMessage(
678
+ toolResults,
679
+ historyDataParts
680
+ );
681
+ yield {
682
+ id: update.id,
683
+ status: {
684
+ state: "working",
685
+ message: toolResultMessage
686
+ },
687
+ final: false,
688
+ text: ""
689
+ };
690
+ const continuedTaskStream = await continueTaskStreamed(
691
+ update.id,
692
+ toolResultMessage,
693
+ requestConfig,
694
+ toolProvider,
695
+ contextProvider,
696
+ sessionId
697
+ );
698
+ let continuedTaskUpdate = null;
699
+ for await (const streamUpdate of continuedTaskStream) {
700
+ if (!streamUpdate.final) {
701
+ yield streamUpdate;
702
+ } else {
703
+ continuedTaskUpdate = streamUpdate;
704
+ }
705
+ }
706
+ if (!continuedTaskUpdate) {
707
+ throw new Error(
708
+ "Continue task stream ended without final result"
709
+ );
710
+ }
711
+ let continuedToolCalls = continuedTaskUpdate.status?.message ? extractToolCallsFromMessage(
712
+ continuedTaskUpdate.status.message
713
+ ) : [];
714
+ if (toolResults.length > 0) {
715
+ newConversationParts.push({
716
+ role: "agent",
717
+ kind: "message",
718
+ parts: toolResults,
719
+ messageId: generateMessageId()
720
+ });
721
+ }
722
+ let finalTask = continuedTaskUpdate;
723
+ if (continuedToolCalls.length > 0) {
724
+ yield {
725
+ ...continuedTaskUpdate,
726
+ final: false,
727
+ text: extractTextFromMessage(
728
+ continuedTaskUpdate.status?.message || {
729
+ role: "agent",
730
+ kind: "message",
731
+ parts: [],
732
+ messageId: generateMessageId()
733
+ }
734
+ )
735
+ };
736
+ while (continuedToolCalls.length > 0) {
737
+ if (finalTask.status?.message) {
738
+ newConversationParts.push(
739
+ finalTask.status.message
740
+ );
741
+ }
742
+ const {
743
+ results: moreResults,
744
+ shouldReturnToAgent: moreShouldReturn
745
+ } = await executeToolCallBatch(
746
+ continuedToolCalls,
747
+ toolProvider,
748
+ finalTask.status?.message?.messageId
749
+ );
750
+ if (moreResults.length > 0) {
751
+ yield {
752
+ id: finalTask.id,
753
+ status: {
754
+ state: "working",
755
+ message: {
756
+ role: "agent",
757
+ kind: "message",
758
+ parts: moreResults,
759
+ messageId: generateMessageId()
760
+ }
761
+ // Simple message with just the results
762
+ },
763
+ final: false,
764
+ text: ""
765
+ };
766
+ }
767
+ if (moreShouldReturn) {
768
+ const moreHistoryDataParts = withHistory ? conversationHistoryToDataParts(
769
+ newConversationParts
770
+ ) : [];
771
+ const moreResultMessage = createToolResultMessage(
772
+ moreResults,
773
+ moreHistoryDataParts
774
+ );
775
+ const moreTaskStream = await continueTaskStreamed(
776
+ finalTask.id,
777
+ moreResultMessage,
778
+ requestConfig,
779
+ toolProvider,
780
+ contextProvider,
781
+ sessionId
782
+ );
783
+ let moreFinalTask = null;
784
+ for await (const streamUpdate of moreTaskStream) {
785
+ if (!streamUpdate.final) {
786
+ yield streamUpdate;
787
+ } else {
788
+ moreFinalTask = streamUpdate;
789
+ }
790
+ }
791
+ if (!moreFinalTask) {
792
+ throw new Error(
793
+ "Continue task stream ended without final result"
794
+ );
795
+ }
796
+ finalTask = moreFinalTask;
797
+ continuedToolCalls = finalTask.status?.message ? extractToolCallsFromMessage(
798
+ finalTask.status.message
799
+ ) : [];
800
+ if (continuedToolCalls.length > 0) {
801
+ yield {
802
+ id: finalTask.id,
803
+ status: finalTask.status,
804
+ final: false,
805
+ text: extractTextFromMessage(
806
+ finalTask.status?.message || {
807
+ role: "agent",
808
+ kind: "message",
809
+ parts: [],
810
+ messageId: generateMessageId()
811
+ }
812
+ )
813
+ };
814
+ }
815
+ } else {
816
+ break;
817
+ }
818
+ }
819
+ }
820
+ yield {
821
+ ...finalTask,
822
+ final: true,
823
+ text: extractTextFromMessage(
824
+ finalTask.status?.message || {
825
+ role: "agent",
826
+ kind: "message",
827
+ parts: [],
828
+ messageId: generateMessageId()
829
+ }
830
+ )
831
+ };
832
+ } else {
833
+ const enhancedMessage = {
834
+ ...update.status.message,
835
+ parts: toolParts
836
+ };
837
+ const enhancedUpdate = {
838
+ ...update,
839
+ status: {
840
+ ...update.status,
841
+ message: enhancedMessage
842
+ },
843
+ final: agentMessages.length === 0,
844
+ // Only final if no agent messages to follow
845
+ text: extractTextFromMessage(enhancedMessage)
846
+ };
847
+ yield enhancedUpdate;
848
+ if (agentMessages.length > 0) {
849
+ const combinedAgentText = agentMessages.map((msg) => extractTextFromMessage(msg)).join(" ");
850
+ const finalAgentMessage = createAgentTextMessage(combinedAgentText);
851
+ yield {
852
+ id: enhancedUpdate.id,
853
+ status: {
854
+ state: "completed",
855
+ message: finalAgentMessage
856
+ },
857
+ final: true,
858
+ text: combinedAgentText
859
+ };
860
+ }
861
+ }
862
+ }
863
+ }
864
+ }
865
+ }
866
+ function createClient(config) {
867
+ const {
868
+ agentId,
869
+ agentUrl,
870
+ authProvider,
871
+ defaultSessionId,
872
+ timeout = DEFAULT_TIMEOUT,
873
+ toolProvider,
874
+ contextProvider
875
+ } = config;
876
+ const requestConfig = {
877
+ agentId,
878
+ agentUrl,
879
+ authProvider,
880
+ timeout
881
+ };
882
+ return {
883
+ async sendMessage(params) {
884
+ const { withHistory = true } = params;
885
+ const sessionId = params.sessionId || defaultSessionId || void 0;
886
+ const newConversationParts = [];
887
+ newConversationParts.push(params.message);
888
+ const preparedRequest = await prepareRequest(
889
+ params,
890
+ requestConfig,
891
+ { isStreaming: false },
892
+ toolProvider,
893
+ contextProvider,
894
+ sessionId
895
+ );
896
+ let currentTask = await executeRequest(
897
+ preparedRequest,
898
+ requestConfig
899
+ );
900
+ const allToolParts = [];
901
+ const agentMessages = [];
902
+ while (currentTask.status.message && toolProvider) {
903
+ const toolCalls = extractToolCallsFromMessage(
904
+ currentTask.status.message
905
+ );
906
+ if (toolCalls.length === 0) {
907
+ break;
908
+ }
909
+ allToolParts.push(...toolCalls);
910
+ const toolResults = [];
911
+ let shouldReturnToAgent = false;
912
+ for (const toolCall of toolCalls) {
913
+ const {
914
+ toolCallId,
915
+ toolId,
916
+ arguments: args
917
+ } = toolCall.data;
918
+ try {
919
+ const executionResult = await toolProvider.executeTool(
920
+ toolId,
921
+ args
922
+ );
923
+ const { result, returnToAgent, agentMessage } = processToolExecutionResult(executionResult);
924
+ if (returnToAgent) {
925
+ shouldReturnToAgent = true;
926
+ }
927
+ if (agentMessage) {
928
+ agentMessages.push(
929
+ createAgentTextMessage(agentMessage)
930
+ );
931
+ }
932
+ const toolResult = createToolResultDataPart(
933
+ toolCallId,
934
+ toolId,
935
+ result
936
+ );
937
+ toolResults.push(toolResult);
938
+ allToolParts.push(toolResult);
939
+ } catch (error) {
940
+ const toolResult = createToolResultDataPart(
941
+ toolCallId,
942
+ toolId,
943
+ void 0,
944
+ error instanceof Error ? error.message : String(error)
945
+ );
946
+ toolResults.push(toolResult);
947
+ allToolParts.push(toolResult);
948
+ }
949
+ }
950
+ newConversationParts.push(currentTask.status.message);
951
+ if (shouldReturnToAgent) {
952
+ const toolResultMessage = createToolResultMessage(toolResults);
953
+ currentTask = await continueTask(
954
+ currentTask.id,
955
+ toolResultMessage,
956
+ requestConfig,
957
+ toolProvider,
958
+ contextProvider,
959
+ sessionId
960
+ );
961
+ } else {
962
+ break;
963
+ }
964
+ }
965
+ if (allToolParts.length > 0) {
966
+ if (currentTask.status?.message) {
967
+ const enhancedMessage = {
968
+ ...currentTask.status.message,
969
+ parts: allToolParts
970
+ };
971
+ currentTask = {
972
+ ...currentTask,
973
+ status: {
974
+ ...currentTask.status,
975
+ message: enhancedMessage
976
+ }
977
+ };
978
+ }
979
+ }
980
+ if (agentMessages.length > 0) {
981
+ const combinedAgentText = agentMessages.map((msg) => extractTextFromMessage(msg)).join(" ");
982
+ const finalAgentMessage = createAgentTextMessage(combinedAgentText);
983
+ return {
984
+ ...currentTask,
985
+ // Keep the enhanced message with tool results
986
+ // The agent message will be handled separately by the caller
987
+ text: combinedAgentText,
988
+ agentMessage: finalAgentMessage
989
+ // Add this for the caller to handle
990
+ };
991
+ }
992
+ return {
993
+ ...currentTask,
994
+ text: extractTextFromMessage(
995
+ currentTask.status?.message || {
996
+ role: "agent",
997
+ kind: "message",
998
+ parts: [],
999
+ messageId: generateMessageId()
1000
+ }
1001
+ )
1002
+ };
1003
+ },
1004
+ async *sendMessageStream(params) {
1005
+ const { withHistory = true } = params;
1006
+ const sessionId = params.sessionId || defaultSessionId || void 0;
1007
+ const newConversationParts = [];
1008
+ newConversationParts.push(params.message);
1009
+ const preparedRequest = await prepareRequest(
1010
+ params,
1011
+ requestConfig,
1012
+ { isStreaming: true, streamingTimeout: timeout },
1013
+ toolProvider,
1014
+ contextProvider,
1015
+ sessionId
1016
+ );
1017
+ const stream = executeStreamingRequest(
1018
+ preparedRequest,
1019
+ requestConfig,
1020
+ {
1021
+ isStreaming: true,
1022
+ streamingTimeout: timeout
1023
+ }
1024
+ );
1025
+ yield* processAgentResponseStream(
1026
+ stream,
1027
+ toolProvider,
1028
+ contextProvider,
1029
+ requestConfig,
1030
+ sessionId,
1031
+ withHistory,
1032
+ newConversationParts
1033
+ );
1034
+ },
1035
+ async continueTask(taskId, userInput, sessionId) {
1036
+ const userMessage = createTextMessage(userInput);
1037
+ const continuedTask = await continueTask(
1038
+ taskId,
1039
+ userMessage,
1040
+ requestConfig,
1041
+ toolProvider,
1042
+ contextProvider,
1043
+ sessionId
1044
+ );
1045
+ let currentTask = continuedTask;
1046
+ while (currentTask.status.state === "input-required" && currentTask.status.message && toolProvider) {
1047
+ const toolCalls = extractToolCallsFromMessage(
1048
+ currentTask.status.message
1049
+ );
1050
+ if (toolCalls.length === 0) {
1051
+ break;
1052
+ }
1053
+ const { results: toolResults, shouldReturnToAgent } = await executeToolCallBatch(toolCalls, toolProvider);
1054
+ if (shouldReturnToAgent) {
1055
+ const toolResultMessage = createToolResultMessage(toolResults);
1056
+ currentTask = await continueTask(
1057
+ currentTask.id,
1058
+ toolResultMessage,
1059
+ requestConfig,
1060
+ toolProvider,
1061
+ contextProvider,
1062
+ sessionId
1063
+ );
1064
+ } else {
1065
+ break;
1066
+ }
1067
+ }
1068
+ return {
1069
+ ...currentTask,
1070
+ text: extractTextFromMessage(
1071
+ currentTask.status?.message || {
1072
+ role: "agent",
1073
+ kind: "message",
1074
+ parts: [],
1075
+ messageId: generateMessageId()
1076
+ }
1077
+ )
1078
+ };
1079
+ },
1080
+ async getTask(taskId) {
1081
+ throw new Error("getTask not implemented yet");
1082
+ },
1083
+ async cancelTask(taskId) {
1084
+ throw new Error("cancelTask not implemented yet");
1085
+ }
1086
+ };
1087
+ }
1088
+
1089
+ // src/react/conversationStorage.ts
1090
+ var STORAGE_KEY = "a8c_agenttic_conversation_history";
1091
+ function extractStorableContent(message) {
1092
+ const textParts = message.parts.filter((part) => part.type === "text").map((part) => part.text).join("\n");
1093
+ const toolCalls = message.parts.filter(
1094
+ (part) => part.type === "data" && "toolCallId" in part.data && "arguments" in part.data
1095
+ ).map((part) => ({
1096
+ toolCallId: part.data.toolCallId,
1097
+ toolId: part.data.toolId,
1098
+ arguments: part.data.arguments
1099
+ }));
1100
+ const toolResults = message.parts.filter(
1101
+ (part) => part.type === "data" && "toolCallId" in part.data && "result" in part.data
1102
+ ).map((part) => ({
1103
+ toolCallId: part.data.toolCallId,
1104
+ result: part.data.result,
1105
+ error: part.data.error
1106
+ }));
1107
+ const hasToolInteractions = toolCalls.length > 0 || toolResults.length > 0;
1108
+ const storageRole = hasToolInteractions ? "agent" : message.role;
1109
+ const timestamp = message.metadata?.timestamp ?? Date.now();
1110
+ return {
1111
+ role: storageRole,
1112
+ content: textParts || "(No text content)",
1113
+ timestamp,
1114
+ ...toolCalls.length > 0 && { toolCalls },
1115
+ ...toolResults.length > 0 && { toolResults }
1116
+ };
1117
+ }
1118
+ function restoreMessage(stored) {
1119
+ const parts = [];
1120
+ if (stored.content && stored.content !== "(No text content)") {
1121
+ parts.push({
1122
+ type: "text",
1123
+ text: stored.content
1124
+ });
1125
+ }
1126
+ if (stored.toolCalls) {
1127
+ for (const toolCall of stored.toolCalls) {
1128
+ parts.push({
1129
+ type: "data",
1130
+ data: {
1131
+ toolCallId: toolCall.toolCallId,
1132
+ toolId: toolCall.toolId,
1133
+ arguments: toolCall.arguments
1134
+ }
1135
+ });
1136
+ }
1137
+ }
1138
+ if (stored.toolResults) {
1139
+ for (const toolResult of stored.toolResults) {
1140
+ parts.push({
1141
+ type: "data",
1142
+ data: {
1143
+ toolCallId: toolResult.toolCallId,
1144
+ result: toolResult.result,
1145
+ ...toolResult.error && { error: toolResult.error }
1146
+ }
1147
+ });
1148
+ }
1149
+ }
1150
+ return {
1151
+ role: stored.role,
1152
+ kind: "message",
1153
+ parts,
1154
+ messageId: generateMessageId(),
1155
+ metadata: {
1156
+ timestamp: stored.timestamp
1157
+ }
1158
+ };
1159
+ }
1160
+ var conversationCache = /* @__PURE__ */ new Map();
1161
+ var maxCacheSize = 50;
1162
+ async function storeConversation(sessionId, messages, conversationStorageKey) {
1163
+ const currentStorageKey = conversationStorageKey || sessionId;
1164
+ conversationCache.set(currentStorageKey, [...messages]);
1165
+ if (conversationCache.size > maxCacheSize) {
1166
+ const firstKey = conversationCache.keys().next().value;
1167
+ if (firstKey) {
1168
+ conversationCache.delete(firstKey);
1169
+ }
1170
+ }
1171
+ if (typeof sessionStorage === "undefined") {
1172
+ return;
1173
+ }
1174
+ try {
1175
+ const stored = {
1176
+ storageKey: currentStorageKey,
1177
+ messages: messages.map(extractStorableContent),
1178
+ lastUpdated: Date.now()
1179
+ };
1180
+ sessionStorage.setItem(
1181
+ `${STORAGE_KEY}_${currentStorageKey}`,
1182
+ JSON.stringify(stored)
1183
+ );
1184
+ } catch (error) {
1185
+ logger(
1186
+ "Failed to store conversation in sessionStorage for key %s: %O",
1187
+ currentStorageKey,
1188
+ error
1189
+ );
1190
+ }
1191
+ }
1192
+ async function loadConversation(sessionId, conversationStorageKey) {
1193
+ const currentStorageKey = conversationStorageKey || sessionId;
1194
+ if (conversationCache.has(currentStorageKey)) {
1195
+ return [...conversationCache.get(currentStorageKey)];
1196
+ }
1197
+ if (typeof sessionStorage === "undefined") {
1198
+ return [];
1199
+ }
1200
+ try {
1201
+ const stored = sessionStorage.getItem(
1202
+ `${STORAGE_KEY}_${currentStorageKey}`
1203
+ );
1204
+ if (stored) {
1205
+ const conversation = JSON.parse(stored);
1206
+ const messages = conversation.messages.map(restoreMessage);
1207
+ conversationCache.set(currentStorageKey, messages);
1208
+ return [...messages];
1209
+ }
1210
+ } catch (error) {
1211
+ logger(
1212
+ "Failed to load conversation from sessionStorage for key %s: %O",
1213
+ currentStorageKey,
1214
+ error
1215
+ );
1216
+ }
1217
+ return [];
1218
+ }
1219
+ async function clearConversation(sessionId, conversationStorageKey) {
1220
+ const currentStorageKey = conversationStorageKey || sessionId;
1221
+ conversationCache.delete(currentStorageKey);
1222
+ if (typeof sessionStorage === "undefined") {
1223
+ return;
1224
+ }
1225
+ try {
1226
+ sessionStorage.removeItem(`${STORAGE_KEY}_${currentStorageKey}`);
1227
+ } catch (error) {
1228
+ logger(
1229
+ "Failed to clear conversation from sessionStorage for key %s: %O",
1230
+ currentStorageKey,
1231
+ error
1232
+ );
1233
+ }
1234
+ }
1235
+
1236
+ // src/react/conversationUtils.ts
1237
+ function extractNewContentFromMessage(message) {
1238
+ const newParts = message.parts.filter((part) => {
1239
+ if (part.type === "text") {
1240
+ return true;
1241
+ }
1242
+ if (part.type === "data") {
1243
+ if ("role" in part.data && "text" in part.data) {
1244
+ return false;
1245
+ }
1246
+ if ("toolCallId" in part.data && "arguments" in part.data) {
1247
+ return true;
1248
+ }
1249
+ if ("toolCallId" in part.data && "result" in part.data) {
1250
+ return true;
1251
+ }
1252
+ return false;
1253
+ }
1254
+ return true;
1255
+ });
1256
+ return {
1257
+ ...message,
1258
+ parts: newParts,
1259
+ // Preserve metadata if it exists, otherwise add timestamp
1260
+ metadata: message.metadata || {
1261
+ timestamp: Date.now()
1262
+ }
1263
+ };
1264
+ }
1265
+ function conversationMessagesToDataParts(conversationMessages) {
1266
+ const historyParts = [];
1267
+ for (const message of conversationMessages) {
1268
+ for (const part of message.parts) {
1269
+ if (part.type === "text") {
1270
+ historyParts.push({
1271
+ type: "data",
1272
+ data: {
1273
+ role: message.role,
1274
+ text: part.text
1275
+ }
1276
+ });
1277
+ } else if (part.type === "data") {
1278
+ if ("role" in part.data && "text" in part.data) {
1279
+ continue;
1280
+ }
1281
+ if ("toolCallId" in part.data && "arguments" in part.data) {
1282
+ historyParts.push(part);
1283
+ continue;
1284
+ }
1285
+ if ("toolCallId" in part.data && "result" in part.data) {
1286
+ historyParts.push(part);
1287
+ continue;
1288
+ }
1289
+ }
1290
+ }
1291
+ }
1292
+ return historyParts;
1293
+ }
1294
+ function createTextMessageWithHistory(text, conversationMessages = []) {
1295
+ const historyParts = conversationMessagesToDataParts(conversationMessages);
1296
+ return {
1297
+ role: "user",
1298
+ parts: [
1299
+ ...historyParts,
1300
+ {
1301
+ type: "text",
1302
+ text
1303
+ }
1304
+ ],
1305
+ kind: "message",
1306
+ messageId: generateMessageId(),
1307
+ metadata: {
1308
+ timestamp: Date.now()
1309
+ }
1310
+ };
1311
+ }
1312
+ function extractToolResultsFromMessage(message) {
1313
+ if (!message?.parts) {
1314
+ return [];
1315
+ }
1316
+ return message.parts.filter(
1317
+ (part) => part.type === "data" && "toolCallId" in part.data && "result" in part.data
1318
+ );
1319
+ }
1320
+
1321
+ // src/react/agentManager.ts
1322
+ function createAgentManager() {
1323
+ const agents = /* @__PURE__ */ new Map();
1324
+ async function persistConversationHistory(key, messages) {
1325
+ const agent = agents.get(key);
1326
+ if (agent?.sessionId) {
1327
+ try {
1328
+ await storeConversation(
1329
+ agent.sessionId,
1330
+ messages,
1331
+ agent.conversationStorageKey
1332
+ );
1333
+ } catch (error) {
1334
+ log(
1335
+ `Failed to persist conversation history for agent ${key}:`,
1336
+ error
1337
+ );
1338
+ }
1339
+ }
1340
+ }
1341
+ return {
1342
+ async createAgent(key, config) {
1343
+ if (agents.has(key)) {
1344
+ return agents.get(key).client;
1345
+ }
1346
+ const client = createClient(config);
1347
+ const sessionId = config.sessionId || null;
1348
+ const conversationStorageKey = config.conversationStorageKey;
1349
+ let conversationHistory = [];
1350
+ if (sessionId) {
1351
+ try {
1352
+ conversationHistory = await loadConversation(
1353
+ sessionId,
1354
+ conversationStorageKey
1355
+ );
1356
+ } catch (error) {
1357
+ log(
1358
+ `Failed to load conversation history for agent ${key} with session ${sessionId}:`,
1359
+ error
1360
+ );
1361
+ }
1362
+ }
1363
+ const managedAgent = {
1364
+ client,
1365
+ sessionId,
1366
+ conversationStorageKey,
1367
+ conversationHistory
1368
+ };
1369
+ agents.set(key, managedAgent);
1370
+ return client;
1371
+ },
1372
+ getAgent(key) {
1373
+ const agent = agents.get(key);
1374
+ return agent?.client || null;
1375
+ },
1376
+ hasAgent(key) {
1377
+ return agents.has(key);
1378
+ },
1379
+ removeAgent(key) {
1380
+ return agents.delete(key);
1381
+ },
1382
+ async sendMessage(key, message, options = {}) {
1383
+ const managedAgent = agents.get(key);
1384
+ if (!managedAgent) {
1385
+ throw new Error(`Agent with key "${key}" not found`);
1386
+ }
1387
+ const { withHistory = true, ...otherOptions } = options;
1388
+ const { client, conversationHistory } = managedAgent;
1389
+ const messageObj = options.message || createTextMessageWithHistory(message, conversationHistory);
1390
+ const task = await client.sendMessage({
1391
+ message: messageObj,
1392
+ withHistory,
1393
+ ...otherOptions
1394
+ });
1395
+ let completeAgentMessage = null;
1396
+ if (task.status?.message) {
1397
+ const toolParts = task.status.message.parts.filter(
1398
+ (part) => part.type === "data" && "toolCallId" in part.data && ("arguments" in part.data || "result" in part.data)
1399
+ );
1400
+ const textParts = task.status.message.parts.filter(
1401
+ (part) => part.type === "text"
1402
+ );
1403
+ completeAgentMessage = {
1404
+ role: "agent",
1405
+ kind: "message",
1406
+ parts: [...toolParts, ...textParts],
1407
+ messageId: generateMessageId(),
1408
+ metadata: {
1409
+ timestamp: Date.now()
1410
+ }
1411
+ };
1412
+ }
1413
+ const newConversationHistory = [
1414
+ ...conversationHistory,
1415
+ // Store only the new content from the user message (without history parts)
1416
+ createTextMessage(message),
1417
+ // Add complete agent response with tool calls/results if present
1418
+ ...completeAgentMessage ? [extractNewContentFromMessage(completeAgentMessage)] : []
1419
+ ];
1420
+ let finalConversationHistory = newConversationHistory;
1421
+ if (task.agentMessage) {
1422
+ const separateAgentMessage = extractNewContentFromMessage(
1423
+ task.agentMessage
1424
+ );
1425
+ finalConversationHistory = [
1426
+ ...newConversationHistory,
1427
+ separateAgentMessage
1428
+ ];
1429
+ }
1430
+ managedAgent.conversationHistory = finalConversationHistory;
1431
+ if (withHistory) {
1432
+ await persistConversationHistory(
1433
+ key,
1434
+ finalConversationHistory
1435
+ );
1436
+ }
1437
+ return task;
1438
+ },
1439
+ async *sendMessageStream(key, message, options = {}) {
1440
+ const managedAgent = agents.get(key);
1441
+ if (!managedAgent) {
1442
+ throw new Error(`Agent with key "${key}" not found`);
1443
+ }
1444
+ const { withHistory = true, ...otherOptions } = options;
1445
+ const { client } = managedAgent;
1446
+ let currentConversationHistory = [
1447
+ ...managedAgent.conversationHistory
1448
+ ];
1449
+ let currentToolCallIds = [];
1450
+ const messageObj = options.message || createTextMessageWithHistory(
1451
+ message,
1452
+ currentConversationHistory
1453
+ );
1454
+ const userMessage = createTextMessage(message);
1455
+ currentConversationHistory = [
1456
+ ...currentConversationHistory,
1457
+ userMessage
1458
+ ];
1459
+ managedAgent.conversationHistory = currentConversationHistory;
1460
+ if (withHistory) {
1461
+ await persistConversationHistory(
1462
+ key,
1463
+ currentConversationHistory
1464
+ );
1465
+ }
1466
+ for await (const update of client.sendMessageStream({
1467
+ message: messageObj,
1468
+ withHistory,
1469
+ ...otherOptions
1470
+ })) {
1471
+ if (update.status?.state === "input-required" && update.status?.message) {
1472
+ const toolCalls = extractToolCallsFromMessage(
1473
+ update.status.message
1474
+ );
1475
+ currentToolCallIds = toolCalls.map(
1476
+ (call) => call.data.toolCallId
1477
+ );
1478
+ const toolMessage = extractNewContentFromMessage(
1479
+ update.status.message
1480
+ );
1481
+ currentConversationHistory = [
1482
+ ...currentConversationHistory,
1483
+ toolMessage
1484
+ ];
1485
+ managedAgent.conversationHistory = currentConversationHistory;
1486
+ if (withHistory) {
1487
+ await persistConversationHistory(
1488
+ key,
1489
+ currentConversationHistory
1490
+ );
1491
+ }
1492
+ }
1493
+ if (update.status?.state === "working" && update.status?.message && !update.final) {
1494
+ const allToolResults = extractToolResultsFromMessage(
1495
+ update.status.message
1496
+ );
1497
+ const currentToolResults = allToolResults.filter(
1498
+ (result) => currentToolCallIds.includes(
1499
+ result.data.toolCallId
1500
+ )
1501
+ );
1502
+ if (currentToolResults.length > 0) {
1503
+ const toolResultMessage = {
1504
+ role: "agent",
1505
+ kind: "message",
1506
+ parts: currentToolResults,
1507
+ messageId: generateMessageId()
1508
+ };
1509
+ currentConversationHistory = [
1510
+ ...currentConversationHistory,
1511
+ extractNewContentFromMessage(toolResultMessage)
1512
+ ];
1513
+ managedAgent.conversationHistory = currentConversationHistory;
1514
+ if (withHistory) {
1515
+ await persistConversationHistory(
1516
+ key,
1517
+ currentConversationHistory
1518
+ );
1519
+ }
1520
+ }
1521
+ }
1522
+ if (update.final && update.status?.state !== "input-required") {
1523
+ currentToolCallIds = [];
1524
+ let finalAgentMessage = null;
1525
+ if (update.status?.message) {
1526
+ finalAgentMessage = extractNewContentFromMessage(
1527
+ update.status.message
1528
+ );
1529
+ currentConversationHistory = [
1530
+ ...currentConversationHistory,
1531
+ finalAgentMessage
1532
+ ];
1533
+ managedAgent.conversationHistory = currentConversationHistory;
1534
+ if (withHistory) {
1535
+ await persistConversationHistory(
1536
+ key,
1537
+ currentConversationHistory
1538
+ );
1539
+ }
1540
+ }
1541
+ }
1542
+ yield update;
1543
+ }
1544
+ },
1545
+ async resetConversation(key) {
1546
+ const managedAgent = agents.get(key);
1547
+ if (!managedAgent) {
1548
+ throw new Error(`Agent with key "${key}" not found`);
1549
+ }
1550
+ managedAgent.conversationHistory = [];
1551
+ if (managedAgent.sessionId) {
1552
+ await clearConversation(
1553
+ managedAgent.sessionId,
1554
+ managedAgent.conversationStorageKey
1555
+ );
1556
+ }
1557
+ },
1558
+ getConversationHistory(key) {
1559
+ const managedAgent = agents.get(key);
1560
+ if (!managedAgent) {
1561
+ throw new Error(`Agent with key "${key}" not found`);
1562
+ }
1563
+ return [...managedAgent.conversationHistory];
1564
+ },
1565
+ clear() {
1566
+ agents.clear();
1567
+ }
1568
+ };
1569
+ }
1570
+ var globalAgentManager = createAgentManager();
1571
+ function getAgentManager() {
1572
+ return globalAgentManager;
1573
+ }
1574
+
1575
+ // src/utils/createMessageRenderer.tsx
1576
+ import Markdown from "react-markdown";
1577
+
1578
+ // src/markdown-extensions/index.ts
1579
+ import remarkGfm from "remark-gfm";
1580
+ function processMarkdownExtensions(extensions) {
1581
+ const components = {};
1582
+ const remarkPlugins = [];
1583
+ if (extensions?.charts?.enabled) {
1584
+ components.code = createChartBlock(extensions.charts.config);
1585
+ }
1586
+ if (extensions?.gfm?.enabled) {
1587
+ remarkPlugins.push(remarkGfm);
1588
+ }
1589
+ return { components, remarkPlugins };
1590
+ }
1591
+ function mergeMarkdownComponents(extensionComponents, userComponents = {}) {
1592
+ return {
1593
+ ...extensionComponents,
1594
+ ...userComponents
1595
+ };
1596
+ }
1597
+
1598
+ // src/utils/createMessageRenderer.tsx
1599
+ import { jsx } from "react/jsx-runtime";
1600
+ function createMessageRenderer(options = {}) {
1601
+ const { components = {}, extensions = {}, remarkPlugins = [] } = options;
1602
+ const processed = processMarkdownExtensions(extensions);
1603
+ const finalComponents = mergeMarkdownComponents(
1604
+ processed.components,
1605
+ components
1606
+ );
1607
+ const finalPlugins = [...processed.remarkPlugins, ...remarkPlugins];
1608
+ return function MessageRenderer({ children }) {
1609
+ return /* @__PURE__ */ jsx(
1610
+ Markdown,
1611
+ {
1612
+ components: finalComponents,
1613
+ remarkPlugins: finalPlugins,
1614
+ children
1615
+ }
1616
+ );
1617
+ };
1618
+ }
1619
+
1620
+ // src/message-actions/useMessageActions.ts
1621
+ import { useCallback as useCallback2, useState } from "react";
1622
+
1623
+ // src/message-actions/factories.tsx
1624
+ var createFeedbackActions = (config) => {
1625
+ const baseCondition = config.condition || (() => true);
1626
+ const feedbackByMessageId = {};
1627
+ const changeListeners = [];
1628
+ const notifyListeners = () => {
1629
+ changeListeners.forEach((listener) => listener());
1630
+ };
1631
+ const handleFeedback = async (messageId, feedback) => {
1632
+ feedbackByMessageId[messageId] = feedback;
1633
+ await config.onFeedback(messageId, feedback);
1634
+ notifyListeners();
1635
+ };
1636
+ return {
1637
+ getActionsForMessage: (message) => {
1638
+ if (!baseCondition(message)) {
1639
+ return [];
1640
+ }
1641
+ const feedbackState = feedbackByMessageId[message.id];
1642
+ const actions = [];
1643
+ if (feedbackState !== "down") {
1644
+ actions.push({
1645
+ id: "feedback-up",
1646
+ icon: config.icons.up,
1647
+ label: "Good response",
1648
+ onClick: async () => {
1649
+ await handleFeedback(message.id, "up");
1650
+ },
1651
+ tooltip: "This response was helpful",
1652
+ disabled: feedbackState === "up"
1653
+ });
1654
+ }
1655
+ if (feedbackState !== "up") {
1656
+ actions.push({
1657
+ id: "feedback-down",
1658
+ icon: config.icons.down,
1659
+ label: "Bad response",
1660
+ onClick: async () => {
1661
+ await handleFeedback(message.id, "down");
1662
+ },
1663
+ tooltip: "This response was not helpful",
1664
+ disabled: feedbackState === "down"
1665
+ });
1666
+ }
1667
+ return actions;
1668
+ },
1669
+ clearFeedback: (messageId) => {
1670
+ delete feedbackByMessageId[messageId];
1671
+ notifyListeners();
1672
+ },
1673
+ clearAllFeedback: () => {
1674
+ Object.keys(feedbackByMessageId).forEach((key) => {
1675
+ delete feedbackByMessageId[key];
1676
+ });
1677
+ notifyListeners();
1678
+ },
1679
+ onChange: (listener) => {
1680
+ changeListeners.push(listener);
1681
+ },
1682
+ offChange: (listener) => {
1683
+ const index = changeListeners.indexOf(listener);
1684
+ if (index > -1) {
1685
+ changeListeners.splice(index, 1);
1686
+ }
1687
+ }
1688
+ };
1689
+ };
1690
+
1691
+ // src/message-actions/useMessageActions.ts
1692
+ function useMessageActions() {
1693
+ const [registrations, setRegistrations] = useState([]);
1694
+ const registerMessageActions = useCallback2(
1695
+ (registration) => {
1696
+ setRegistrations((prev) => {
1697
+ const existingIndex = prev.findIndex(
1698
+ (r) => r.id === registration.id
1699
+ );
1700
+ if (existingIndex >= 0) {
1701
+ const updated = [...prev];
1702
+ updated[existingIndex] = registration;
1703
+ return updated;
1704
+ }
1705
+ return [...prev, registration];
1706
+ });
1707
+ },
1708
+ []
1709
+ );
1710
+ const unregisterMessageActions = useCallback2((id) => {
1711
+ setRegistrations((prev) => prev.filter((r) => r.id !== id));
1712
+ }, []);
1713
+ const clearAllMessageActions = useCallback2(() => {
1714
+ setRegistrations([]);
1715
+ }, []);
1716
+ return {
1717
+ registerMessageActions,
1718
+ unregisterMessageActions,
1719
+ clearAllMessageActions,
1720
+ createFeedbackActions,
1721
+ registrations
1722
+ };
1723
+ }
1724
+
1725
+ // src/message-actions/resolver.ts
1726
+ function resolveActionsForMessage(message, registrations) {
1727
+ const allActions = registrations.flatMap((reg) => {
1728
+ if (typeof reg.actions === "function") {
1729
+ return reg.actions(message);
1730
+ }
1731
+ return reg.actions;
1732
+ });
1733
+ const filteredActions = allActions.filter((action) => {
1734
+ if (action.condition && !action.condition(message)) {
1735
+ return false;
1736
+ }
1737
+ return true;
1738
+ }).map((action) => ({
1739
+ id: action.id,
1740
+ label: action.label,
1741
+ icon: action.icon,
1742
+ onClick: action.onClick,
1743
+ tooltip: action.tooltip,
1744
+ disabled: action.disabled || false
1745
+ }));
1746
+ return filteredActions;
1747
+ }
1748
+
1749
+ // src/react/useAgentChat.ts
1750
+ var sortUIMessagesByTime = (messages) => {
1751
+ return [...messages].sort((a, b) => a.timestamp - b.timestamp);
1752
+ };
1753
+ var transformClientMessageToUI = (clientMessage, messageActionsRegistrations = []) => {
1754
+ const hasToolContent = clientMessage.parts.some((part) => {
1755
+ if (part.type === "data") {
1756
+ const data = part.data;
1757
+ return data.toolCallId || data.toolId || data.result;
1758
+ }
1759
+ return false;
1760
+ });
1761
+ if (hasToolContent) {
1762
+ return null;
1763
+ }
1764
+ const content = clientMessage.parts.map((part) => {
1765
+ if (part.type === "text") {
1766
+ return {
1767
+ type: "text",
1768
+ text: part.text
1769
+ };
1770
+ }
1771
+ if (part.type === "file") {
1772
+ return {
1773
+ type: "image_url",
1774
+ image_url: part.file.uri || `data:${part.file.mimeType};base64,${part.file.bytes}`
1775
+ };
1776
+ }
1777
+ if (part.type === "data") {
1778
+ const data = part.data;
1779
+ if (data.component && data.componentProps) {
1780
+ return {
1781
+ type: "component",
1782
+ component: data.component,
1783
+ componentProps: data.componentProps
1784
+ };
1785
+ }
1786
+ return {
1787
+ type: "text",
1788
+ text: JSON.stringify(data)
1789
+ };
1790
+ }
1791
+ return {
1792
+ type: "text",
1793
+ text: "[Unsupported content]"
1794
+ };
1795
+ });
1796
+ const timestamp = clientMessage.metadata?.timestamp ?? Date.now();
1797
+ const uiMessage = {
1798
+ id: clientMessage.messageId,
1799
+ role: clientMessage.role === "agent" ? "agent" : "user",
1800
+ content,
1801
+ timestamp,
1802
+ archived: false,
1803
+ showIcon: clientMessage.role === "agent",
1804
+ icon: clientMessage.role === "agent" ? "assistant" : void 0
1805
+ };
1806
+ if (clientMessage.role === "agent" && messageActionsRegistrations.length > 0) {
1807
+ const resolvedActions = resolveActionsForMessage(
1808
+ uiMessage,
1809
+ messageActionsRegistrations
1810
+ );
1811
+ if (resolvedActions.length > 0) {
1812
+ uiMessage.actions = resolvedActions;
1813
+ }
1814
+ }
1815
+ return uiMessage;
1816
+ };
1817
+ var createNoOpContextProvider = () => ({
1818
+ getClientContext: () => ({})
1819
+ });
1820
+ var createNoOpToolProvider = () => ({
1821
+ getAvailableTools: async () => [],
1822
+ executeTool: async () => ({
1823
+ success: true,
1824
+ result: "No tools available"
1825
+ })
1826
+ });
1827
+ var validateAgentConfig = (config) => {
1828
+ const required = ["agentId", "agentUrl", "sessionId"];
1829
+ return required.every((key) => {
1830
+ const value = config[key];
1831
+ return typeof value === "string" && value.trim().length > 0;
1832
+ });
1833
+ };
1834
+ function useAgentChat(config) {
1835
+ const agentConfig = {
1836
+ agentId: config.agentId,
1837
+ agentUrl: config.agentUrl,
1838
+ sessionId: config.sessionId
1839
+ };
1840
+ const isValidConfig = validateAgentConfig(agentConfig);
1841
+ const [state, setState] = useState2({
1842
+ clientMessages: [],
1843
+ uiMessages: [],
1844
+ isProcessing: false,
1845
+ error: isValidConfig ? null : "Invalid agent configuration",
1846
+ suggestions: [],
1847
+ markdownComponents: {},
1848
+ markdownExtensions: {}
1849
+ });
1850
+ const {
1851
+ registerMessageActions,
1852
+ unregisterMessageActions,
1853
+ clearAllMessageActions,
1854
+ createFeedbackActions: createFeedbackActions2,
1855
+ registrations
1856
+ } = useMessageActions();
1857
+ const registrationsRef = useRef(registrations);
1858
+ useEffect(() => {
1859
+ registrationsRef.current = registrations;
1860
+ }, [registrations]);
1861
+ useEffect(() => {
1862
+ if (!isValidConfig) {
1863
+ return;
1864
+ }
1865
+ const initializeAgent = async () => {
1866
+ if (agentConfig.sessionId) {
1867
+ const agentManager = getAgentManager();
1868
+ const agentKey = `${agentConfig.agentId}-${agentConfig.sessionId}`;
1869
+ if (!agentManager.hasAgent(agentKey)) {
1870
+ await agentManager.createAgent(agentKey, {
1871
+ agentId: agentConfig.agentId,
1872
+ agentUrl: agentConfig.agentUrl,
1873
+ sessionId: agentConfig.sessionId,
1874
+ contextProvider: config.contextProvider || createNoOpContextProvider(),
1875
+ toolProvider: config.toolProvider || createNoOpToolProvider(),
1876
+ authProvider: config.authProvider
1877
+ });
1878
+ const clientHistory = agentManager.getConversationHistory(agentKey);
1879
+ setState((prev) => {
1880
+ const uiHistory = clientHistory.map(
1881
+ (msg) => transformClientMessageToUI(
1882
+ msg,
1883
+ registrationsRef.current
1884
+ )
1885
+ ).filter(
1886
+ (msg) => msg !== null
1887
+ );
1888
+ return {
1889
+ ...prev,
1890
+ clientMessages: clientHistory,
1891
+ uiMessages: uiHistory
1892
+ };
1893
+ });
1894
+ }
1895
+ }
1896
+ };
1897
+ initializeAgent();
1898
+ }, [
1899
+ agentConfig.sessionId,
1900
+ agentConfig.agentId,
1901
+ agentConfig.agentUrl,
1902
+ config.contextProvider,
1903
+ config.toolProvider,
1904
+ config.authProvider,
1905
+ isValidConfig
1906
+ ]);
1907
+ const onSubmit = useCallback3(
1908
+ async (message) => {
1909
+ if (!isValidConfig) {
1910
+ throw new Error("Invalid agent configuration");
1911
+ }
1912
+ const agentManager = getAgentManager();
1913
+ const agentKey = `${agentConfig.agentId}-${agentConfig.sessionId}`;
1914
+ const messageTimestamp = Date.now();
1915
+ const userMessage = {
1916
+ id: `user-${messageTimestamp}`,
1917
+ role: "user",
1918
+ content: [{ type: "text", text: message }],
1919
+ timestamp: messageTimestamp,
1920
+ archived: false,
1921
+ showIcon: false
1922
+ };
1923
+ setState((prev) => ({
1924
+ ...prev,
1925
+ uiMessages: [...prev.uiMessages, userMessage],
1926
+ isProcessing: true,
1927
+ error: null
1928
+ }));
1929
+ try {
1930
+ let lastUpdate = null;
1931
+ for await (const update of agentManager.sendMessageStream(
1932
+ agentKey,
1933
+ message
1934
+ )) {
1935
+ lastUpdate = update;
1936
+ }
1937
+ const updatedClientHistory = agentManager.getConversationHistory(agentKey);
1938
+ setState((prev) => {
1939
+ const transformedClientMessages = updatedClientHistory.map(
1940
+ (msg) => transformClientMessageToUI(
1941
+ msg,
1942
+ registrationsRef.current
1943
+ )
1944
+ ).filter((msg) => msg !== null);
1945
+ const clientMessageIds = new Set(
1946
+ updatedClientHistory.map((msg) => msg.messageId)
1947
+ );
1948
+ const uiOnlyMessages = prev.uiMessages.filter(
1949
+ (msg) => !clientMessageIds.has(msg.id) && msg.content[0]?.type === "component"
1950
+ );
1951
+ const mergedUIMessages = sortUIMessagesByTime([
1952
+ ...transformedClientMessages,
1953
+ ...uiOnlyMessages
1954
+ ]);
1955
+ return {
1956
+ ...prev,
1957
+ clientMessages: updatedClientHistory,
1958
+ uiMessages: mergedUIMessages,
1959
+ isProcessing: false
1960
+ };
1961
+ });
1962
+ } catch (error) {
1963
+ const errorMessage = error instanceof Error ? error.message : "Failed to send message";
1964
+ setState((prev) => ({
1965
+ ...prev,
1966
+ isProcessing: false,
1967
+ error: errorMessage
1968
+ }));
1969
+ throw error;
1970
+ }
1971
+ },
1972
+ [agentConfig.agentId, agentConfig.sessionId, isValidConfig]
1973
+ );
1974
+ const addMessage = useCallback3((message) => {
1975
+ setState((prev) => ({
1976
+ ...prev,
1977
+ uiMessages: sortUIMessagesByTime([...prev.uiMessages, message])
1978
+ }));
1979
+ }, []);
1980
+ const registerSuggestions = useCallback3((suggestions) => {
1981
+ setState((prev) => ({
1982
+ ...prev,
1983
+ suggestions
1984
+ }));
1985
+ }, []);
1986
+ const clearSuggestions = useCallback3(() => {
1987
+ setState((prev) => ({
1988
+ ...prev,
1989
+ suggestions: []
1990
+ }));
1991
+ }, []);
1992
+ const registerMarkdownComponents = useCallback3(
1993
+ (components) => {
1994
+ setState((prev) => {
1995
+ const updatedComponents = {
1996
+ ...prev.markdownComponents,
1997
+ ...components
1998
+ };
1999
+ const updatedUIMessages = prev.clientMessages.map(
2000
+ (msg) => transformClientMessageToUI(
2001
+ msg,
2002
+ registrationsRef.current
2003
+ )
2004
+ ).filter((msg) => msg !== null);
2005
+ const clientMessageIds = new Set(
2006
+ prev.clientMessages.map((msg) => msg.messageId)
2007
+ );
2008
+ const uiOnlyMessages = prev.uiMessages.filter(
2009
+ (msg) => !clientMessageIds.has(msg.id) && msg.content[0]?.type === "component"
2010
+ );
2011
+ const mergedUIMessages = sortUIMessagesByTime([
2012
+ ...updatedUIMessages,
2013
+ ...uiOnlyMessages
2014
+ ]);
2015
+ return {
2016
+ ...prev,
2017
+ markdownComponents: updatedComponents,
2018
+ uiMessages: mergedUIMessages
2019
+ };
2020
+ });
2021
+ },
2022
+ []
2023
+ );
2024
+ const registerMarkdownExtensions = useCallback3(
2025
+ (extensions) => {
2026
+ setState((prev) => {
2027
+ const updatedExtensions = {
2028
+ ...prev.markdownExtensions,
2029
+ ...extensions
2030
+ };
2031
+ const updatedUIMessages = prev.clientMessages.map(
2032
+ (msg) => transformClientMessageToUI(
2033
+ msg,
2034
+ registrationsRef.current
2035
+ )
2036
+ ).filter((msg) => msg !== null);
2037
+ const clientMessageIds = new Set(
2038
+ prev.clientMessages.map((msg) => msg.messageId)
2039
+ );
2040
+ const uiOnlyMessages = prev.uiMessages.filter(
2041
+ (msg) => !clientMessageIds.has(msg.id) && msg.content[0]?.type === "component"
2042
+ );
2043
+ const mergedUIMessages = sortUIMessagesByTime([
2044
+ ...updatedUIMessages,
2045
+ ...uiOnlyMessages
2046
+ ]);
2047
+ return {
2048
+ ...prev,
2049
+ markdownExtensions: updatedExtensions,
2050
+ uiMessages: mergedUIMessages
2051
+ };
2052
+ });
2053
+ },
2054
+ []
2055
+ );
2056
+ useEffect(() => {
2057
+ setState((prev) => {
2058
+ if (prev.clientMessages.length === 0) {
2059
+ return prev;
2060
+ }
2061
+ const updatedUIMessages = prev.clientMessages.map(
2062
+ (msg) => transformClientMessageToUI(msg, registrationsRef.current)
2063
+ ).filter((msg) => msg !== null);
2064
+ const clientMessageIds = new Set(
2065
+ prev.clientMessages.map((msg) => msg.messageId)
2066
+ );
2067
+ const uiOnlyMessages = prev.uiMessages.filter(
2068
+ (msg) => !clientMessageIds.has(msg.id) && msg.content[0]?.type === "component"
2069
+ );
2070
+ return {
2071
+ ...prev,
2072
+ uiMessages: sortUIMessagesByTime([
2073
+ ...updatedUIMessages,
2074
+ ...uiOnlyMessages
2075
+ ])
2076
+ };
2077
+ });
2078
+ }, [registrations]);
2079
+ const messageRenderer = useMemo3(
2080
+ () => createMessageRenderer({
2081
+ components: state.markdownComponents,
2082
+ extensions: state.markdownExtensions
2083
+ }),
2084
+ [state.markdownComponents, state.markdownExtensions]
2085
+ );
2086
+ return {
2087
+ // AgentUI props
2088
+ messages: state.uiMessages,
2089
+ isProcessing: state.isProcessing,
2090
+ error: state.error,
2091
+ onSubmit,
2092
+ suggestions: state.suggestions,
2093
+ messageRenderer,
2094
+ // UI management methods
2095
+ registerSuggestions,
2096
+ clearSuggestions,
2097
+ registerMarkdownComponents,
2098
+ registerMarkdownExtensions,
2099
+ // Message actions methods
2100
+ registerMessageActions,
2101
+ unregisterMessageActions,
2102
+ clearAllMessageActions,
2103
+ createFeedbackActions: createFeedbackActions2,
2104
+ // Tool integration
2105
+ addMessage
2106
+ };
2107
+ }
2108
+
2109
+ // src/client/types/index.ts
2110
+ var A2AErrorCodes = /* @__PURE__ */ ((A2AErrorCodes2) => {
2111
+ A2AErrorCodes2[A2AErrorCodes2["PARSE_ERROR"] = -32700] = "PARSE_ERROR";
2112
+ A2AErrorCodes2[A2AErrorCodes2["INVALID_REQUEST"] = -32600] = "INVALID_REQUEST";
2113
+ A2AErrorCodes2[A2AErrorCodes2["METHOD_NOT_FOUND"] = -32601] = "METHOD_NOT_FOUND";
2114
+ A2AErrorCodes2[A2AErrorCodes2["INVALID_PARAMS"] = -32602] = "INVALID_PARAMS";
2115
+ A2AErrorCodes2[A2AErrorCodes2["INTERNAL_ERROR"] = -32603] = "INTERNAL_ERROR";
2116
+ A2AErrorCodes2[A2AErrorCodes2["SERVER_ERROR"] = -32e3] = "SERVER_ERROR";
2117
+ return A2AErrorCodes2;
2118
+ })(A2AErrorCodes || {});
2119
+ export {
2120
+ A2AErrorCodes,
2121
+ BarChart,
2122
+ ChartBlock,
2123
+ LineChart,
2124
+ createClient,
2125
+ createFeedbackActions,
2126
+ createMessageRenderer,
2127
+ createRequestId,
2128
+ createTaskId,
2129
+ createTextMessage,
2130
+ extractTextFromMessage,
2131
+ extractToolCallsFromMessage,
2132
+ getAgentManager,
2133
+ useAgentChat,
2134
+ useClientContext,
2135
+ useClientTools,
2136
+ useMessageActions
2137
+ };