@lov3kaizen/agentsea-react 0.4.0 → 0.5.2

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 CHANGED
@@ -220,9 +220,807 @@ var useStreamingContent = () => {
220
220
  consumeStream
221
221
  };
222
222
  };
223
+
224
+ // src/useChat.ts
225
+ import { useState, useCallback, useRef, useEffect } from "react";
226
+
227
+ // src/types.ts
228
+ function generateId() {
229
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
230
+ }
231
+ function createMessage(role, content, options) {
232
+ return {
233
+ id: generateId(),
234
+ role,
235
+ content,
236
+ createdAt: /* @__PURE__ */ new Date(),
237
+ ...options
238
+ };
239
+ }
240
+
241
+ // src/adapters.ts
242
+ function createSSEAdapter() {
243
+ let eventSource = null;
244
+ let abortController = null;
245
+ let messageCallback = null;
246
+ let errorCallback = null;
247
+ let closeCallback = null;
248
+ let currentUrl = "";
249
+ let currentOptions = {};
250
+ return {
251
+ connect(url, options) {
252
+ currentUrl = url;
253
+ currentOptions = options || {};
254
+ abortController = new AbortController();
255
+ if (options?.signal) {
256
+ options.signal.addEventListener("abort", () => {
257
+ abortController?.abort();
258
+ });
259
+ }
260
+ return Promise.resolve();
261
+ },
262
+ async send(data) {
263
+ const response = await fetch(currentUrl, {
264
+ method: "POST",
265
+ headers: {
266
+ "Content-Type": "application/json",
267
+ Accept: "text/event-stream",
268
+ ...currentOptions.headers
269
+ },
270
+ body: JSON.stringify(data),
271
+ signal: abortController?.signal
272
+ });
273
+ if (!response.ok) {
274
+ const error = new Error(`HTTP error: ${response.status}`);
275
+ errorCallback?.(error);
276
+ return;
277
+ }
278
+ const reader = response.body?.getReader();
279
+ if (!reader) {
280
+ errorCallback?.(new Error("No response body"));
281
+ return;
282
+ }
283
+ const decoder = new TextDecoder();
284
+ let buffer = "";
285
+ try {
286
+ let reading = true;
287
+ while (reading) {
288
+ const { done, value } = await reader.read();
289
+ if (done) {
290
+ reading = false;
291
+ continue;
292
+ }
293
+ buffer += decoder.decode(value, { stream: true });
294
+ const lines = buffer.split("\n");
295
+ buffer = lines.pop() || "";
296
+ for (const line of lines) {
297
+ if (line.startsWith("data: ")) {
298
+ const eventData = line.slice(6);
299
+ if (eventData === "[DONE]") {
300
+ closeCallback?.();
301
+ return;
302
+ }
303
+ try {
304
+ const chunk = JSON.parse(eventData);
305
+ messageCallback?.(chunk);
306
+ } catch {
307
+ }
308
+ }
309
+ }
310
+ }
311
+ } catch (error) {
312
+ if (error.name !== "AbortError") {
313
+ errorCallback?.(error);
314
+ }
315
+ } finally {
316
+ closeCallback?.();
317
+ }
318
+ },
319
+ onMessage(callback) {
320
+ messageCallback = callback;
321
+ },
322
+ onError(callback) {
323
+ errorCallback = callback;
324
+ },
325
+ onClose(callback) {
326
+ closeCallback = callback;
327
+ },
328
+ close() {
329
+ abortController?.abort();
330
+ eventSource?.close();
331
+ eventSource = null;
332
+ }
333
+ };
334
+ }
335
+ function createHTTPStreamAdapter() {
336
+ let abortController = null;
337
+ let messageCallback = null;
338
+ let errorCallback = null;
339
+ let closeCallback = null;
340
+ let currentUrl = "";
341
+ let currentOptions = {};
342
+ return {
343
+ connect(url, options) {
344
+ currentUrl = url;
345
+ currentOptions = options || {};
346
+ abortController = new AbortController();
347
+ if (options?.signal) {
348
+ options.signal.addEventListener("abort", () => {
349
+ abortController?.abort();
350
+ });
351
+ }
352
+ return Promise.resolve();
353
+ },
354
+ async send(data) {
355
+ try {
356
+ const response = await fetch(currentUrl, {
357
+ method: "POST",
358
+ headers: {
359
+ "Content-Type": "application/json",
360
+ Accept: "application/x-ndjson",
361
+ ...currentOptions.headers
362
+ },
363
+ body: JSON.stringify(data),
364
+ signal: abortController?.signal
365
+ });
366
+ if (!response.ok) {
367
+ const error = new Error(`HTTP error: ${response.status}`);
368
+ errorCallback?.(error);
369
+ return;
370
+ }
371
+ const reader = response.body?.getReader();
372
+ if (!reader) {
373
+ errorCallback?.(new Error("No response body"));
374
+ return;
375
+ }
376
+ const decoder = new TextDecoder();
377
+ let buffer = "";
378
+ let reading = true;
379
+ while (reading) {
380
+ const { done, value } = await reader.read();
381
+ if (done) {
382
+ reading = false;
383
+ continue;
384
+ }
385
+ buffer += decoder.decode(value, { stream: true });
386
+ const lines = buffer.split("\n");
387
+ buffer = lines.pop() || "";
388
+ for (const line of lines) {
389
+ if (line.trim()) {
390
+ try {
391
+ const chunk = JSON.parse(line);
392
+ messageCallback?.(chunk);
393
+ } catch {
394
+ }
395
+ }
396
+ }
397
+ }
398
+ if (buffer.trim()) {
399
+ try {
400
+ const chunk = JSON.parse(buffer);
401
+ messageCallback?.(chunk);
402
+ } catch {
403
+ }
404
+ }
405
+ } catch (error) {
406
+ if (error.name !== "AbortError") {
407
+ errorCallback?.(error);
408
+ }
409
+ } finally {
410
+ closeCallback?.();
411
+ }
412
+ },
413
+ onMessage(callback) {
414
+ messageCallback = callback;
415
+ },
416
+ onError(callback) {
417
+ errorCallback = callback;
418
+ },
419
+ onClose(callback) {
420
+ closeCallback = callback;
421
+ },
422
+ close() {
423
+ abortController?.abort();
424
+ }
425
+ };
426
+ }
427
+ async function fetchChat(url, data, options) {
428
+ const response = await fetch(url, {
429
+ method: "POST",
430
+ headers: {
431
+ "Content-Type": "application/json",
432
+ ...options?.headers
433
+ },
434
+ body: JSON.stringify({ ...data, stream: false }),
435
+ signal: options?.signal
436
+ });
437
+ if (!response.ok) {
438
+ throw new Error(`HTTP error: ${response.status}`);
439
+ }
440
+ const result = await response.json();
441
+ return result.chunks || [result];
442
+ }
443
+ function getAdapter(type) {
444
+ if (typeof type === "object") {
445
+ return type;
446
+ }
447
+ return type === "sse" ? createSSEAdapter() : createHTTPStreamAdapter();
448
+ }
449
+
450
+ // src/useChat.ts
451
+ function useChat(config) {
452
+ const {
453
+ endpoint,
454
+ conversationId: initialConversationId,
455
+ agentId,
456
+ initialMessages = [],
457
+ adapter: adapterType = "sse",
458
+ headers = {},
459
+ onMessage,
460
+ onContentUpdate,
461
+ onToolApproval,
462
+ onError,
463
+ onComplete,
464
+ onThinking,
465
+ autoApprove = false,
466
+ maxRetries = 3
467
+ } = config;
468
+ const [messages, setMessages] = useState(initialMessages);
469
+ const [streamingContent, setStreamingContent] = useState("");
470
+ const [thinkingContent, setThinkingContent] = useState("");
471
+ const [activeToolCalls, setActiveToolCalls] = useState([]);
472
+ const [isLoading, setIsLoading] = useState(false);
473
+ const [isStreaming, setIsStreaming] = useState(false);
474
+ const [error, setError] = useState(null);
475
+ const adapterRef = useRef(getAdapter(adapterType));
476
+ const abortControllerRef = useRef(null);
477
+ const conversationIdRef = useRef(initialConversationId || generateId());
478
+ const pendingApprovalsRef = useRef(
479
+ /* @__PURE__ */ new Map()
480
+ );
481
+ const retryCountRef = useRef(0);
482
+ useEffect(() => {
483
+ return () => {
484
+ abortControllerRef.current?.abort();
485
+ adapterRef.current.close();
486
+ };
487
+ }, []);
488
+ const processChunk = useCallback(
489
+ (chunk) => {
490
+ switch (chunk.type) {
491
+ case "content":
492
+ if (chunk.delta) {
493
+ setStreamingContent((prev) => prev + chunk.content);
494
+ } else {
495
+ setStreamingContent(chunk.content);
496
+ }
497
+ onContentUpdate?.(chunk.content);
498
+ break;
499
+ case "thinking": {
500
+ if (chunk.delta) {
501
+ setThinkingContent((prev) => prev + chunk.content);
502
+ } else {
503
+ setThinkingContent(chunk.content);
504
+ }
505
+ const thinking = {
506
+ type: "thinking",
507
+ content: chunk.content,
508
+ isComplete: false
509
+ };
510
+ onThinking?.(thinking);
511
+ break;
512
+ }
513
+ case "tool_call":
514
+ setActiveToolCalls((prev) => {
515
+ const existing = prev.find((tc) => tc.id === chunk.toolCall.id);
516
+ if (existing) {
517
+ return prev.map(
518
+ (tc) => tc.id === chunk.toolCall.id ? chunk.toolCall : tc
519
+ );
520
+ }
521
+ return [...prev, chunk.toolCall];
522
+ });
523
+ if (chunk.toolCall.needsApproval && !autoApprove) {
524
+ onToolApproval?.(chunk.toolCall);
525
+ } else if (autoApprove && chunk.toolCall.needsApproval) {
526
+ pendingApprovalsRef.current.set(chunk.toolCall.id, {
527
+ toolCallId: chunk.toolCall.id,
528
+ approved: true
529
+ });
530
+ }
531
+ break;
532
+ case "tool_result":
533
+ setActiveToolCalls(
534
+ (prev) => prev.map(
535
+ (tc) => tc.id === chunk.toolCall.id ? { ...chunk.toolCall, state: "complete" } : tc
536
+ )
537
+ );
538
+ break;
539
+ case "tool_state":
540
+ setActiveToolCalls(
541
+ (prev) => prev.map(
542
+ (tc) => tc.id === chunk.toolCallId ? { ...tc, state: chunk.state } : tc
543
+ )
544
+ );
545
+ break;
546
+ case "done": {
547
+ setIsStreaming(false);
548
+ setIsLoading(false);
549
+ const finalContent = streamingContent;
550
+ const finalThinking = thinkingContent;
551
+ const finalToolCalls = [...activeToolCalls];
552
+ if (finalContent || finalToolCalls.length > 0) {
553
+ const assistantMessage = createMessage("assistant", finalContent, {
554
+ toolCalls: finalToolCalls.length > 0 ? finalToolCalls : void 0,
555
+ thinking: finalThinking ? { type: "thinking", content: finalThinking, isComplete: true } : void 0,
556
+ metadata: chunk.metadata
557
+ });
558
+ setMessages((prev) => [...prev, assistantMessage]);
559
+ onMessage?.(assistantMessage);
560
+ onComplete?.(assistantMessage);
561
+ }
562
+ setStreamingContent("");
563
+ setThinkingContent("");
564
+ setActiveToolCalls([]);
565
+ retryCountRef.current = 0;
566
+ break;
567
+ }
568
+ case "error": {
569
+ const err = new Error(chunk.error);
570
+ setError(err);
571
+ setIsStreaming(false);
572
+ setIsLoading(false);
573
+ onError?.(err);
574
+ break;
575
+ }
576
+ }
577
+ },
578
+ [
579
+ streamingContent,
580
+ thinkingContent,
581
+ activeToolCalls,
582
+ autoApprove,
583
+ onContentUpdate,
584
+ onThinking,
585
+ onToolApproval,
586
+ onMessage,
587
+ onComplete,
588
+ onError
589
+ ]
590
+ );
591
+ const sendMessage = useCallback(
592
+ async (content) => {
593
+ if (!content.trim()) return;
594
+ const userMessage = createMessage("user", content);
595
+ setMessages((prev) => [...prev, userMessage]);
596
+ setError(null);
597
+ setIsLoading(true);
598
+ setIsStreaming(true);
599
+ setStreamingContent("");
600
+ setThinkingContent("");
601
+ setActiveToolCalls([]);
602
+ abortControllerRef.current = new AbortController();
603
+ try {
604
+ const adapter = adapterRef.current;
605
+ await adapter.connect(endpoint, {
606
+ headers,
607
+ signal: abortControllerRef.current.signal
608
+ });
609
+ adapter.onMessage(processChunk);
610
+ adapter.onError((err) => {
611
+ setError(err);
612
+ setIsStreaming(false);
613
+ setIsLoading(false);
614
+ onError?.(err);
615
+ });
616
+ adapter.onClose(() => {
617
+ setIsStreaming(false);
618
+ });
619
+ const allMessages = [...messages, userMessage];
620
+ await adapter.send({
621
+ messages: allMessages,
622
+ conversationId: conversationIdRef.current,
623
+ agentId,
624
+ stream: true,
625
+ toolApprovals: Array.from(pendingApprovalsRef.current.values())
626
+ });
627
+ pendingApprovalsRef.current.clear();
628
+ } catch (err) {
629
+ const error2 = err;
630
+ if (error2.name !== "AbortError") {
631
+ setError(error2);
632
+ onError?.(error2);
633
+ if (retryCountRef.current < maxRetries) {
634
+ retryCountRef.current++;
635
+ setMessages((prev) => prev.slice(0, -1));
636
+ await sendMessage(content);
637
+ return;
638
+ }
639
+ }
640
+ setIsStreaming(false);
641
+ setIsLoading(false);
642
+ }
643
+ },
644
+ [endpoint, headers, agentId, messages, processChunk, onError, maxRetries]
645
+ );
646
+ const approveToolCall = useCallback((toolCallId) => {
647
+ pendingApprovalsRef.current.set(toolCallId, {
648
+ toolCallId,
649
+ approved: true
650
+ });
651
+ setActiveToolCalls(
652
+ (prev) => prev.map(
653
+ (tc) => tc.id === toolCallId ? { ...tc, state: "executing" } : tc
654
+ )
655
+ );
656
+ }, []);
657
+ const denyToolCall = useCallback(
658
+ (toolCallId, reason) => {
659
+ pendingApprovalsRef.current.set(toolCallId, {
660
+ toolCallId,
661
+ approved: false,
662
+ reason
663
+ });
664
+ setActiveToolCalls(
665
+ (prev) => prev.map(
666
+ (tc) => tc.id === toolCallId ? { ...tc, state: "approval-denied" } : tc
667
+ )
668
+ );
669
+ },
670
+ []
671
+ );
672
+ const stop = useCallback(() => {
673
+ abortControllerRef.current?.abort();
674
+ adapterRef.current.close();
675
+ setIsStreaming(false);
676
+ setIsLoading(false);
677
+ if (streamingContent) {
678
+ const partialMessage = createMessage("assistant", streamingContent, {
679
+ toolCalls: activeToolCalls.length > 0 ? activeToolCalls : void 0,
680
+ thinking: thinkingContent ? { type: "thinking", content: thinkingContent, isComplete: false } : void 0,
681
+ metadata: { finishReason: "stopped" }
682
+ });
683
+ setMessages((prev) => [...prev, partialMessage]);
684
+ }
685
+ setStreamingContent("");
686
+ setThinkingContent("");
687
+ setActiveToolCalls([]);
688
+ }, [streamingContent, thinkingContent, activeToolCalls]);
689
+ const clear = useCallback(() => {
690
+ stop();
691
+ setMessages([]);
692
+ setError(null);
693
+ conversationIdRef.current = generateId();
694
+ }, [stop]);
695
+ const reload = useCallback(async () => {
696
+ const lastUserMessageIndex = messages.map((m) => m.role).lastIndexOf("user");
697
+ if (lastUserMessageIndex === -1) return;
698
+ const lastUserMessage = messages[lastUserMessageIndex];
699
+ setMessages((prev) => prev.slice(0, lastUserMessageIndex));
700
+ await sendMessage(lastUserMessage.content);
701
+ }, [messages, sendMessage]);
702
+ return {
703
+ messages,
704
+ streamingContent,
705
+ thinkingContent,
706
+ activeToolCalls,
707
+ isLoading,
708
+ isStreaming,
709
+ error,
710
+ sendMessage,
711
+ approveToolCall,
712
+ denyToolCall,
713
+ stop,
714
+ clear,
715
+ reload,
716
+ setMessages
717
+ };
718
+ }
719
+
720
+ // src/useAgent.ts
721
+ import { useState as useState2, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect2 } from "react";
722
+ function useAgent(config) {
723
+ const {
724
+ endpoint,
725
+ agentId,
726
+ headers = {},
727
+ onStart,
728
+ onContentUpdate,
729
+ onToolApproval,
730
+ onError,
731
+ onComplete,
732
+ onThinking
733
+ } = config;
734
+ const [content, setContent] = useState2("");
735
+ const [thinkingContent, setThinkingContent] = useState2("");
736
+ const [activeToolCalls, setActiveToolCalls] = useState2([]);
737
+ const [isLoading, setIsLoading] = useState2(false);
738
+ const [isStreaming, setIsStreaming] = useState2(false);
739
+ const [error, setError] = useState2(null);
740
+ const [metadata, setMetadata] = useState2(
741
+ null
742
+ );
743
+ const abortControllerRef = useRef2(null);
744
+ const pendingApprovalsRef = useRef2(
745
+ /* @__PURE__ */ new Map()
746
+ );
747
+ useEffect2(() => {
748
+ return () => {
749
+ abortControllerRef.current?.abort();
750
+ };
751
+ }, []);
752
+ async function* executeStream(input, context) {
753
+ onStart?.();
754
+ setError(null);
755
+ setIsLoading(true);
756
+ setIsStreaming(true);
757
+ setContent("");
758
+ setThinkingContent("");
759
+ setActiveToolCalls([]);
760
+ setMetadata(null);
761
+ abortControllerRef.current = new AbortController();
762
+ try {
763
+ const response = await fetch(endpoint, {
764
+ method: "POST",
765
+ headers: {
766
+ "Content-Type": "application/json",
767
+ Accept: "text/event-stream",
768
+ ...headers
769
+ },
770
+ body: JSON.stringify({
771
+ input,
772
+ agentId,
773
+ context,
774
+ stream: true,
775
+ toolApprovals: Array.from(pendingApprovalsRef.current.values())
776
+ }),
777
+ signal: abortControllerRef.current.signal
778
+ });
779
+ if (!response.ok) {
780
+ throw new Error(`HTTP error: ${response.status}`);
781
+ }
782
+ const reader = response.body?.getReader();
783
+ if (!reader) {
784
+ throw new Error("No response body");
785
+ }
786
+ const decoder = new TextDecoder();
787
+ let buffer = "";
788
+ let accumulatedContent = "";
789
+ let accumulatedThinking = "";
790
+ let reading = true;
791
+ while (reading) {
792
+ const { done, value } = await reader.read();
793
+ if (done) {
794
+ reading = false;
795
+ continue;
796
+ }
797
+ buffer += decoder.decode(value, { stream: true });
798
+ const lines = buffer.split("\n");
799
+ buffer = lines.pop() || "";
800
+ for (const line of lines) {
801
+ if (line.startsWith("data: ")) {
802
+ const data = line.slice(6);
803
+ if (data === "[DONE]") {
804
+ setIsStreaming(false);
805
+ setIsLoading(false);
806
+ return;
807
+ }
808
+ try {
809
+ const chunk = JSON.parse(data);
810
+ switch (chunk.type) {
811
+ case "content":
812
+ if (chunk.delta) {
813
+ accumulatedContent += chunk.content;
814
+ } else {
815
+ accumulatedContent = chunk.content;
816
+ }
817
+ setContent(accumulatedContent);
818
+ onContentUpdate?.(chunk.content);
819
+ break;
820
+ case "thinking": {
821
+ if (chunk.delta) {
822
+ accumulatedThinking += chunk.content;
823
+ } else {
824
+ accumulatedThinking = chunk.content;
825
+ }
826
+ setThinkingContent(accumulatedThinking);
827
+ const thinking = {
828
+ type: "thinking",
829
+ content: chunk.content,
830
+ isComplete: false
831
+ };
832
+ onThinking?.(thinking);
833
+ break;
834
+ }
835
+ case "tool_call":
836
+ setActiveToolCalls((prev) => {
837
+ const existing = prev.find(
838
+ (tc) => tc.id === chunk.toolCall.id
839
+ );
840
+ if (existing) {
841
+ return prev.map(
842
+ (tc) => tc.id === chunk.toolCall.id ? chunk.toolCall : tc
843
+ );
844
+ }
845
+ return [...prev, chunk.toolCall];
846
+ });
847
+ if (chunk.toolCall.needsApproval) {
848
+ onToolApproval?.(chunk.toolCall);
849
+ }
850
+ break;
851
+ case "tool_result":
852
+ setActiveToolCalls(
853
+ (prev) => prev.map(
854
+ (tc) => tc.id === chunk.toolCall.id ? { ...chunk.toolCall, state: "complete" } : tc
855
+ )
856
+ );
857
+ break;
858
+ case "tool_state":
859
+ setActiveToolCalls(
860
+ (prev) => prev.map(
861
+ (tc) => tc.id === chunk.toolCallId ? { ...tc, state: chunk.state } : tc
862
+ )
863
+ );
864
+ break;
865
+ case "done":
866
+ setMetadata(chunk.metadata || null);
867
+ setIsStreaming(false);
868
+ setIsLoading(false);
869
+ break;
870
+ case "error": {
871
+ const err = new Error(chunk.error);
872
+ setError(err);
873
+ setIsStreaming(false);
874
+ setIsLoading(false);
875
+ onError?.(err);
876
+ break;
877
+ }
878
+ }
879
+ yield chunk;
880
+ } catch {
881
+ }
882
+ }
883
+ }
884
+ }
885
+ pendingApprovalsRef.current.clear();
886
+ } catch (err) {
887
+ const error2 = err;
888
+ if (error2.name !== "AbortError") {
889
+ setError(error2);
890
+ onError?.(error2);
891
+ }
892
+ setIsStreaming(false);
893
+ setIsLoading(false);
894
+ throw error2;
895
+ }
896
+ }
897
+ const execute = useCallback2(
898
+ async (input, context) => {
899
+ onStart?.();
900
+ setError(null);
901
+ setIsLoading(true);
902
+ setContent("");
903
+ setThinkingContent("");
904
+ setActiveToolCalls([]);
905
+ setMetadata(null);
906
+ abortControllerRef.current = new AbortController();
907
+ try {
908
+ const response = await fetch(endpoint, {
909
+ method: "POST",
910
+ headers: {
911
+ "Content-Type": "application/json",
912
+ ...headers
913
+ },
914
+ body: JSON.stringify({
915
+ input,
916
+ agentId,
917
+ context,
918
+ stream: false,
919
+ toolApprovals: Array.from(pendingApprovalsRef.current.values())
920
+ }),
921
+ signal: abortControllerRef.current.signal
922
+ });
923
+ if (!response.ok) {
924
+ throw new Error(`HTTP error: ${response.status}`);
925
+ }
926
+ const result = await response.json();
927
+ setContent(result.content);
928
+ setMetadata({
929
+ tokensUsed: result.metadata?.tokensUsed,
930
+ latencyMs: result.metadata?.latencyMs,
931
+ finishReason: result.finishReason
932
+ });
933
+ if (result.toolCalls) {
934
+ setActiveToolCalls(
935
+ result.toolCalls.map((tc) => ({
936
+ ...tc,
937
+ state: "complete"
938
+ }))
939
+ );
940
+ }
941
+ setIsLoading(false);
942
+ onComplete?.(result);
943
+ pendingApprovalsRef.current.clear();
944
+ return result;
945
+ } catch (err) {
946
+ const error2 = err;
947
+ if (error2.name !== "AbortError") {
948
+ setError(error2);
949
+ onError?.(error2);
950
+ }
951
+ setIsLoading(false);
952
+ return null;
953
+ }
954
+ },
955
+ [endpoint, headers, agentId, onStart, onComplete, onError]
956
+ );
957
+ const approveToolCall = useCallback2((toolCallId) => {
958
+ pendingApprovalsRef.current.set(toolCallId, {
959
+ toolCallId,
960
+ approved: true
961
+ });
962
+ setActiveToolCalls(
963
+ (prev) => prev.map(
964
+ (tc) => tc.id === toolCallId ? { ...tc, state: "executing" } : tc
965
+ )
966
+ );
967
+ }, []);
968
+ const denyToolCall = useCallback2(
969
+ (toolCallId, reason) => {
970
+ pendingApprovalsRef.current.set(toolCallId, {
971
+ toolCallId,
972
+ approved: false,
973
+ reason
974
+ });
975
+ setActiveToolCalls(
976
+ (prev) => prev.map(
977
+ (tc) => tc.id === toolCallId ? { ...tc, state: "approval-denied" } : tc
978
+ )
979
+ );
980
+ },
981
+ []
982
+ );
983
+ const stop = useCallback2(() => {
984
+ abortControllerRef.current?.abort();
985
+ setIsStreaming(false);
986
+ setIsLoading(false);
987
+ }, []);
988
+ const reset = useCallback2(() => {
989
+ stop();
990
+ setContent("");
991
+ setThinkingContent("");
992
+ setActiveToolCalls([]);
993
+ setError(null);
994
+ setMetadata(null);
995
+ pendingApprovalsRef.current.clear();
996
+ }, [stop]);
997
+ return {
998
+ execute,
999
+ executeStream,
1000
+ content,
1001
+ thinkingContent,
1002
+ activeToolCalls,
1003
+ isLoading,
1004
+ isStreaming,
1005
+ error,
1006
+ metadata,
1007
+ approveToolCall,
1008
+ denyToolCall,
1009
+ stop,
1010
+ reset
1011
+ };
1012
+ }
223
1013
  export {
224
1014
  AgentResponse,
225
1015
  StreamingResponse,
1016
+ createHTTPStreamAdapter,
1017
+ createMessage,
1018
+ createSSEAdapter,
1019
+ fetchChat,
1020
+ generateId,
1021
+ getAdapter,
1022
+ useAgent,
1023
+ useChat,
226
1024
  useFormattedContent,
227
1025
  useStreamingContent
228
1026
  };