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