@axiom-lattice/react-sdk 2.1.11 → 2.1.13

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
@@ -59,7 +59,6 @@ function useChat(threadId, options = {}) {
59
59
  messages: options.initialMessages || [],
60
60
  isLoading: false,
61
61
  error: null,
62
- streamingMessage: null,
63
62
  interrupts: void 0,
64
63
  ...options.enableReturnStateWhenStreamCompleted ? { agentState: null } : {}
65
64
  });
@@ -137,7 +136,7 @@ function useChat(threadId, options = {}) {
137
136
  stopStreamingRef.current = null;
138
137
  }
139
138
  const { input, command, streaming = true } = data;
140
- const { message: message4, files, ...rest } = input || {};
139
+ const { message: message5, files, ...rest } = input || {};
141
140
  setState((prev) => ({
142
141
  ...prev,
143
142
  isLoading: true,
@@ -146,7 +145,7 @@ function useChat(threadId, options = {}) {
146
145
  }));
147
146
  const userMessage = {
148
147
  id: Date.now().toString(),
149
- content: message4 || command?.resume?.message || "",
148
+ content: message5 || command?.resume?.message || "",
150
149
  files,
151
150
  role: "human"
152
151
  };
@@ -367,7 +366,9 @@ import {
367
366
  useEffect as useEffect3,
368
367
  useRef as useRef2
369
368
  } from "react";
370
- import { createSimpleMessageMerger as createSimpleMessageMerger2 } from "@axiom-lattice/client-sdk";
369
+ import {
370
+ createSimpleMessageMerger as createSimpleMessageMerger2
371
+ } from "@axiom-lattice/client-sdk";
371
372
  import { jsx as jsx2 } from "react/jsx-runtime";
372
373
  var AgentThreadContext = createContext2(
373
374
  null
@@ -390,10 +391,17 @@ function AgentThreadProvider({
390
391
  messages: options.initialMessages || [],
391
392
  isLoading: false,
392
393
  error: null,
393
- streamingMessage: null,
394
394
  interrupts: void 0,
395
395
  agentState: null
396
396
  });
397
+ useEffect3(() => {
398
+ setState((prev) => ({
399
+ ...prev,
400
+ assistantId: clientAssistantId,
401
+ tenantId,
402
+ threadId
403
+ }));
404
+ }, [clientAssistantId, tenantId, threadId]);
397
405
  const stopStreamingRef = useRef2(null);
398
406
  const chunkMessageMerger = useRef2(createSimpleMessageMerger2());
399
407
  const lastAgentStateCreatedAtRef = useRef2(null);
@@ -460,8 +468,7 @@ function AgentThreadProvider({
460
468
  ...prev,
461
469
  todos: todos || prev.todos,
462
470
  messages: updatedMessages,
463
- isLoading: true,
464
- streamingMessage: null
471
+ isLoading: true
465
472
  }));
466
473
  },
467
474
  []
@@ -476,16 +483,15 @@ function AgentThreadProvider({
476
483
  stopStreamingRef.current = null;
477
484
  }
478
485
  const { input, command, streaming = true } = data;
479
- const { message: message4, files, ...rest } = input || {};
486
+ const { message: message5, files, ...rest } = input || {};
480
487
  setState((prev) => ({
481
488
  ...prev,
482
489
  isLoading: true,
483
- error: null,
484
- streamingMessage: null
490
+ error: null
485
491
  }));
486
492
  const userMessage = {
487
493
  id: Date.now().toString(),
488
- content: message4 || command?.resume?.message || "",
494
+ content: message5 || command?.resume?.message || "",
489
495
  files,
490
496
  role: "human"
491
497
  };
@@ -524,8 +530,7 @@ function AgentThreadProvider({
524
530
  setState((prev) => ({
525
531
  ...prev,
526
532
  isLoading: false,
527
- error,
528
- streamingMessage: null
533
+ error
529
534
  }));
530
535
  stopStreamingRef.current = null;
531
536
  }
@@ -575,111 +580,148 @@ function AgentThreadProvider({
575
580
  setState((prev) => ({
576
581
  ...prev,
577
582
  messages: currentMessages,
578
- isLoading: false,
579
- streamingMessage: null
583
+ isLoading: false
580
584
  }));
581
585
  }
582
586
  }, []);
583
- const loadMessages = useCallback2(
584
- async (limit) => {
587
+ const resumeStream = useCallback2(
588
+ (messageId) => {
585
589
  if (!threadId) {
586
- return;
590
+ throw new Error("Thread ID is required to resume stream");
591
+ }
592
+ let targetMessageId;
593
+ if (messageId) {
594
+ targetMessageId = messageId;
595
+ } else {
596
+ const messages = chunkMessageMerger.current.getMessages();
597
+ const lastMessage = messages[messages.length - 1];
598
+ if (!lastMessage) {
599
+ throw new Error(
600
+ "No message ID provided and no messages found in context"
601
+ );
602
+ }
603
+ targetMessageId = lastMessage.id;
587
604
  }
588
605
  if (stopStreamingRef.current) {
589
606
  stopStreamingRef.current();
590
607
  stopStreamingRef.current = null;
591
608
  }
592
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
593
- try {
594
- const agentState = await client.getAgentState(threadId);
595
- const currentCreatedAt = agentState?.createdAt;
596
- const needsUpdate = !lastAgentStateCreatedAtRef.current || currentCreatedAt !== lastAgentStateCreatedAtRef.current;
597
- if (currentCreatedAt) {
598
- lastAgentStateCreatedAtRef.current = currentCreatedAt;
599
- }
600
- let needUpdateFields = {};
601
- let fetchedMessages = [];
602
- needUpdateFields.agentState = agentState;
603
- needUpdateFields.todos = agentState?.values?.todos;
604
- const interrupts = agentState?.tasks?.flatMap(
605
- (task) => {
606
- return task.interrupts.map((interrupt) => {
607
- return {
608
- id: interrupt.id,
609
- value: interrupt.value,
610
- role: "ai",
611
- type: "interrupt"
612
- };
613
- });
609
+ setState((prev) => ({
610
+ ...prev,
611
+ isLoading: true,
612
+ error: null
613
+ }));
614
+ const resumeStreamOptions = {
615
+ threadId,
616
+ messageId: targetMessageId,
617
+ knownContent: "",
618
+ pollInterval: options.resumeStreamPollInterval || 100
619
+ };
620
+ const stopResumeStream = client.resumeStream(
621
+ resumeStreamOptions,
622
+ handleStreamEvent,
623
+ async () => {
624
+ setState((prev) => ({
625
+ ...prev,
626
+ isLoading: false
627
+ }));
628
+ if (options.enableReturnStateWhenStreamCompleted) {
629
+ await fetchAndUpdateAgentState(threadId);
614
630
  }
615
- );
616
- needUpdateFields.interrupts = interrupts;
617
- fetchedMessages = await client.getMessages({ threadId });
618
- needUpdateFields.messages = fetchedMessages;
619
- chunkMessageMerger.current.reset();
620
- chunkMessageMerger.current.initialMessages(fetchedMessages);
621
- setState((prev) => ({
622
- ...prev,
623
- ...needUpdateFields,
624
- isLoading: false
625
- }));
626
- if (options.enableResumeStream && fetchedMessages.length > 0) {
627
- const lastMessage = fetchedMessages[fetchedMessages.length - 1];
628
- chunkMessageMerger.current.removeMessageById(lastMessage.id);
629
- const stopResumeStream = client.resumeStream(
630
- {
631
- threadId,
632
- messageId: lastMessage.id,
633
- knownContent: "",
634
- pollInterval: options.resumeStreamPollInterval || 100
635
- },
636
- handleStreamEvent,
637
- async () => {
638
- setState((prev) => ({
639
- ...prev,
640
- isLoading: false
641
- }));
642
- if (options.enableReturnStateWhenStreamCompleted) {
643
- await fetchAndUpdateAgentState(threadId);
644
- }
645
- stopStreamingRef.current = null;
646
- },
647
- (error) => {
648
- console.error("Resume stream error:", error);
649
- setState((prev) => ({
650
- ...prev,
651
- error
652
- }));
653
- stopStreamingRef.current = null;
654
- }
655
- );
656
- stopStreamingRef.current = stopResumeStream;
631
+ stopStreamingRef.current = null;
632
+ },
633
+ (error) => {
634
+ console.error("Resume stream error:", error);
635
+ setState((prev) => ({
636
+ ...prev,
637
+ isLoading: false,
638
+ error
639
+ }));
640
+ stopStreamingRef.current = null;
657
641
  }
658
- } catch (error) {
659
- setState((prev) => ({
660
- ...prev,
661
- isLoading: false,
662
- error: error instanceof Error ? error : new Error(String(error))
663
- }));
664
- }
642
+ );
643
+ stopStreamingRef.current = stopResumeStream;
644
+ return stopResumeStream;
665
645
  },
666
646
  [
667
647
  client,
668
648
  threadId,
669
- options.enableResumeStream,
670
649
  options.resumeStreamPollInterval,
650
+ options.enableReturnStateWhenStreamCompleted,
671
651
  handleStreamEvent,
672
652
  fetchAndUpdateAgentState
673
653
  ]
674
654
  );
655
+ const loadMessages = useCallback2(async () => {
656
+ if (!threadId) {
657
+ return;
658
+ }
659
+ if (stopStreamingRef.current) {
660
+ stopStreamingRef.current();
661
+ stopStreamingRef.current = null;
662
+ }
663
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
664
+ try {
665
+ const agentState = await client.getAgentState(threadId);
666
+ const currentCreatedAt = agentState?.createdAt;
667
+ const needsUpdate = !lastAgentStateCreatedAtRef.current || currentCreatedAt !== lastAgentStateCreatedAtRef.current;
668
+ if (currentCreatedAt) {
669
+ lastAgentStateCreatedAtRef.current = currentCreatedAt;
670
+ }
671
+ let needUpdateFields = {};
672
+ let fetchedMessages = [];
673
+ needUpdateFields.agentState = agentState;
674
+ needUpdateFields.todos = agentState?.values?.todos;
675
+ const interrupts = agentState?.tasks?.flatMap(
676
+ (task) => {
677
+ return task.interrupts.map((interrupt) => {
678
+ return {
679
+ id: interrupt.id,
680
+ value: interrupt.value,
681
+ role: "ai",
682
+ type: "interrupt"
683
+ };
684
+ });
685
+ }
686
+ );
687
+ needUpdateFields.interrupts = interrupts;
688
+ fetchedMessages = await client.getMessages({ threadId });
689
+ needUpdateFields.messages = fetchedMessages;
690
+ chunkMessageMerger.current.reset();
691
+ chunkMessageMerger.current.initialMessages(fetchedMessages);
692
+ setState((prev) => ({
693
+ ...prev,
694
+ ...needUpdateFields,
695
+ isLoading: false
696
+ }));
697
+ if (options.enableResumeStream && fetchedMessages.length > 0) {
698
+ const lastMessage = fetchedMessages[fetchedMessages.length - 1];
699
+ chunkMessageMerger.current.removeMessageById(lastMessage.id);
700
+ resumeStream(lastMessage.id);
701
+ }
702
+ } catch (error) {
703
+ setState((prev) => ({
704
+ ...prev,
705
+ isLoading: false,
706
+ error: error instanceof Error ? error : new Error(String(error))
707
+ }));
708
+ }
709
+ }, [
710
+ client,
711
+ threadId,
712
+ options.enableResumeStream,
713
+ options.resumeStreamPollInterval,
714
+ handleStreamEvent,
715
+ fetchAndUpdateAgentState,
716
+ resumeStream
717
+ ]);
675
718
  const clearMessages = useCallback2(() => {
676
719
  chunkMessageMerger.current.reset();
677
720
  lastAgentStateCreatedAtRef.current = null;
678
721
  setState((prev) => ({
679
722
  ...prev,
680
723
  messages: [],
681
- interrupts: void 0,
682
- streamingMessage: null
724
+ interrupts: void 0
683
725
  }));
684
726
  }, []);
685
727
  const clearError = useCallback2(() => {
@@ -706,6 +748,7 @@ function AgentThreadProvider({
706
748
  state,
707
749
  sendMessage,
708
750
  stopStreaming,
751
+ resumeStream,
709
752
  loadMessages,
710
753
  clearMessages,
711
754
  clearError
@@ -729,147 +772,20 @@ function useAgentChat(options) {
729
772
  ...context.state,
730
773
  sendMessage: context.sendMessage,
731
774
  stopStreaming: context.stopStreaming,
775
+ resumeStream: context.resumeStream,
732
776
  loadMessages: context.loadMessages,
733
777
  clearMessages: context.clearMessages,
734
778
  clearError: context.clearError
735
779
  };
736
780
  }
737
781
 
738
- // src/hooks/useThread.ts
739
- import { useState as useState4, useCallback as useCallback3 } from "react";
740
- function useThread() {
741
- const client = useAxiomLattice();
742
- const [state, setState] = useState4({
743
- threads: [],
744
- currentThread: null,
745
- isLoading: false,
746
- error: null
747
- });
748
- const createThread = useCallback3(
749
- async (options = {}) => {
750
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
751
- try {
752
- const threadId = await client.createThread(options);
753
- const thread = await client.getThread(threadId);
754
- setState((prev) => ({
755
- ...prev,
756
- threads: [...prev.threads, thread],
757
- currentThread: thread,
758
- isLoading: false
759
- }));
760
- return threadId;
761
- } catch (error) {
762
- setState((prev) => ({
763
- ...prev,
764
- isLoading: false,
765
- error: error instanceof Error ? error : new Error(String(error))
766
- }));
767
- throw error;
768
- }
769
- },
770
- [client]
771
- );
772
- const getThread = useCallback3(
773
- async (threadId) => {
774
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
775
- try {
776
- const thread = await client.getThread(threadId);
777
- setState((prev) => ({
778
- ...prev,
779
- isLoading: false
780
- }));
781
- return thread;
782
- } catch (error) {
783
- setState((prev) => ({
784
- ...prev,
785
- isLoading: false,
786
- error: error instanceof Error ? error : new Error(String(error))
787
- }));
788
- throw error;
789
- }
790
- },
791
- [client]
792
- );
793
- const listThreads = useCallback3(
794
- async (limit, offset) => {
795
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
796
- try {
797
- const threads = await client.listThreads({ limit, offset });
798
- setState((prev) => ({
799
- ...prev,
800
- threads,
801
- isLoading: false
802
- }));
803
- } catch (error) {
804
- setState((prev) => ({
805
- ...prev,
806
- isLoading: false,
807
- error: error instanceof Error ? error : new Error(String(error))
808
- }));
809
- }
810
- },
811
- [client]
812
- );
813
- const deleteThread = useCallback3(
814
- async (threadId) => {
815
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
816
- try {
817
- await client.deleteThread(threadId);
818
- setState((prev) => ({
819
- ...prev,
820
- threads: prev.threads.filter((t) => t.id !== threadId),
821
- currentThread: prev.currentThread?.id === threadId ? null : prev.currentThread,
822
- isLoading: false
823
- }));
824
- } catch (error) {
825
- setState((prev) => ({
826
- ...prev,
827
- isLoading: false,
828
- error: error instanceof Error ? error : new Error(String(error))
829
- }));
830
- throw error;
831
- }
832
- },
833
- [client]
834
- );
835
- const selectThread = useCallback3(
836
- async (threadId) => {
837
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
838
- try {
839
- const thread = await client.getThread(threadId);
840
- setState((prev) => ({
841
- ...prev,
842
- currentThread: thread,
843
- isLoading: false
844
- }));
845
- } catch (error) {
846
- setState((prev) => ({
847
- ...prev,
848
- isLoading: false,
849
- error: error instanceof Error ? error : new Error(String(error))
850
- }));
851
- throw error;
852
- }
853
- },
854
- [client]
855
- );
856
- return {
857
- ...state,
858
- createThread,
859
- getThread,
860
- listThreads,
861
- deleteThread,
862
- selectThread
863
- };
864
- }
865
-
866
782
  // src/hooks/useAgentState.ts
867
- import { useState as useState5, useCallback as useCallback4, useEffect as useEffect5, useRef as useRef3 } from "react";
783
+ import { useState as useState4, useCallback as useCallback3, useEffect as useEffect4, useRef as useRef3 } from "react";
868
784
  function useAgentState(threadId, options = {}) {
869
785
  const client = useAxiomLattice();
870
- const [agentState, setAgentState] = useState5(null);
871
- const [isLoading, setIsLoading] = useState5(false);
872
- const [error, setError] = useState5(null);
786
+ const [agentState, setAgentState] = useState4(null);
787
+ const [isLoading, setIsLoading] = useState4(false);
788
+ const [error, setError] = useState4(null);
873
789
  const pollingIntervalRef = useRef3(null);
874
790
  const pollingTimeoutRef = useRef3(null);
875
791
  const {
@@ -877,7 +793,7 @@ function useAgentState(threadId, options = {}) {
877
793
  // 2 seconds by default
878
794
  autoStart = true
879
795
  } = options;
880
- const fetchAgentState = useCallback4(async () => {
796
+ const fetchAgentState = useCallback3(async () => {
881
797
  if (!threadId) {
882
798
  return;
883
799
  }
@@ -892,7 +808,7 @@ function useAgentState(threadId, options = {}) {
892
808
  setIsLoading(false);
893
809
  }
894
810
  }, [client, threadId]);
895
- const startPolling = useCallback4(() => {
811
+ const startPolling = useCallback3(() => {
896
812
  if (!threadId) {
897
813
  return;
898
814
  }
@@ -913,17 +829,17 @@ function useAgentState(threadId, options = {}) {
913
829
  };
914
830
  poll();
915
831
  }, [threadId, pollingInterval, fetchAgentState]);
916
- const stopPolling = useCallback4(() => {
832
+ const stopPolling = useCallback3(() => {
917
833
  pollingIntervalRef.current = null;
918
834
  if (pollingTimeoutRef.current) {
919
835
  clearTimeout(pollingTimeoutRef.current);
920
836
  pollingTimeoutRef.current = null;
921
837
  }
922
838
  }, []);
923
- const refresh = useCallback4(async () => {
839
+ const refresh = useCallback3(async () => {
924
840
  await fetchAgentState();
925
841
  }, [fetchAgentState]);
926
- useEffect5(() => {
842
+ useEffect4(() => {
927
843
  if (threadId && autoStart) {
928
844
  startPolling();
929
845
  } else {
@@ -944,13 +860,13 @@ function useAgentState(threadId, options = {}) {
944
860
  }
945
861
 
946
862
  // src/hooks/useAgentGraph.ts
947
- import { useState as useState6, useCallback as useCallback5 } from "react";
863
+ import { useState as useState5, useCallback as useCallback4 } from "react";
948
864
  function useAgentGraph() {
949
865
  const client = useAxiomLattice();
950
- const [graphImage, setGraphImage] = useState6(null);
951
- const [isLoading, setIsLoading] = useState6(false);
952
- const [error, setError] = useState6(null);
953
- const fetchGraph = useCallback5(async () => {
866
+ const [graphImage, setGraphImage] = useState5(null);
867
+ const [isLoading, setIsLoading] = useState5(false);
868
+ const [error, setError] = useState5(null);
869
+ const fetchGraph = useCallback4(async () => {
954
870
  setIsLoading(true);
955
871
  setError(null);
956
872
  try {
@@ -974,7 +890,7 @@ function useAgentGraph() {
974
890
  export * from "@axiom-lattice/protocols";
975
891
 
976
892
  // src/components/Chat/ChatUIContext.tsx
977
- import { createContext as createContext3, useCallback as useCallback6, useContext as useContext3, useState as useState7 } from "react";
893
+ import { createContext as createContext3, useCallback as useCallback5, useContext as useContext3, useState as useState6 } from "react";
978
894
  import { jsx as jsx3 } from "react/jsx-runtime";
979
895
  var ChatUIContext = createContext3({
980
896
  sideAppVisible: false,
@@ -989,22 +905,26 @@ var ChatUIContext = createContext3({
989
905
  openSideApp: () => {
990
906
  },
991
907
  closeSideApp: () => {
908
+ },
909
+ menuCollapsed: false,
910
+ setMenuCollapsed: () => {
992
911
  }
993
912
  });
994
913
  var ChatUIContextProvider = ({
995
914
  children
996
915
  }) => {
997
- const [sideAppVisible, setSideAppVisible] = useState7(false);
998
- const [sideAppSize, setSideAppSize] = useState7("large");
999
- const [sideAppSelectedCard, setSideAppSelectedCard] = useState7(null);
1000
- const openSideApp = useCallback6(
916
+ const [sideAppVisible, setSideAppVisible] = useState6(false);
917
+ const [sideAppSize, setSideAppSize] = useState6("large");
918
+ const [sideAppSelectedCard, setSideAppSelectedCard] = useState6(null);
919
+ const [menuCollapsed, setMenuCollapsed] = useState6(false);
920
+ const openSideApp = useCallback5(
1001
921
  (card) => {
1002
922
  setSideAppSelectedCard(card);
1003
923
  setSideAppVisible(true);
1004
924
  },
1005
925
  [setSideAppSelectedCard, setSideAppVisible]
1006
926
  );
1007
- const closeSideApp = useCallback6(() => {
927
+ const closeSideApp = useCallback5(() => {
1008
928
  setSideAppSelectedCard(null);
1009
929
  setSideAppVisible(false);
1010
930
  }, [setSideAppSelectedCard, setSideAppVisible]);
@@ -1019,7 +939,9 @@ var ChatUIContextProvider = ({
1019
939
  sideAppSelectedCard,
1020
940
  setSideAppSelectedCard,
1021
941
  openSideApp,
1022
- closeSideApp
942
+ closeSideApp,
943
+ menuCollapsed,
944
+ setMenuCollapsed
1023
945
  },
1024
946
  children
1025
947
  }
@@ -1044,7 +966,6 @@ var useStyle = createStyles(({ token, css }) => {
1044
966
  position: relative;
1045
967
  overflow: hidden;
1046
968
  padding: 16px;
1047
- padding-top: 2px;
1048
969
  gap: 16px;
1049
970
 
1050
971
  .ant-prompts {
@@ -1053,7 +974,7 @@ var useStyle = createStyles(({ token, css }) => {
1053
974
  `,
1054
975
  menu: css`
1055
976
  background: ${token.colorBgContainer}90;
1056
- width: 280px;
977
+ width: 240px;
1057
978
  display: flex;
1058
979
  flex-direction: column;
1059
980
  flex-shrink: 0;
@@ -1171,6 +1092,17 @@ var useStyle = createStyles(({ token, css }) => {
1171
1092
  min-width: 200px;
1172
1093
  max-width: 466px;
1173
1094
  }
1095
+ .ant-bubble-content-updating {
1096
+ background-image: linear-gradient(
1097
+ 90deg,
1098
+ #ff6b23 0%,
1099
+ #af3cb8 31%,
1100
+ #53b6ff 89%
1101
+ );
1102
+ background-size: 100% 2px;
1103
+ background-repeat: no-repeat;
1104
+ background-position: bottom;
1105
+ }
1174
1106
  `,
1175
1107
  detailPanel: css`
1176
1108
  display: flex;
@@ -1305,10 +1237,25 @@ var useStyle = createStyles(({ token, css }) => {
1305
1237
 
1306
1238
  // src/components/Chat/ColumnLayout.tsx
1307
1239
  import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
1308
- var ColumnLayout = ({ left, right }) => {
1240
+ var ColumnLayout = ({
1241
+ left,
1242
+ right,
1243
+ logo,
1244
+ menu
1245
+ }) => {
1309
1246
  const { styles } = useStyle();
1310
- const { sideAppVisible, sideAppSize, sideAppSelectedCard } = useChatUIContext();
1247
+ const { sideAppVisible, sideAppSize, sideAppSelectedCard, menuCollapsed } = useChatUIContext();
1311
1248
  return /* @__PURE__ */ jsxs("div", { className: `fina_chat ${styles.layout}`, children: [
1249
+ menu && /* @__PURE__ */ jsxs(
1250
+ "div",
1251
+ {
1252
+ className: `${styles.menu} ${"open"} ${menuCollapsed ? "collapsed" : ""}`,
1253
+ children: [
1254
+ logo,
1255
+ menu
1256
+ ]
1257
+ }
1258
+ ),
1312
1259
  /* @__PURE__ */ jsx4("div", { className: `${styles.mainContent} ${sideAppVisible ? "open" : ""}`, children: /* @__PURE__ */ jsx4("div", { className: `${styles.chat}`, children: left }) }),
1313
1260
  /* @__PURE__ */ jsxs(
1314
1261
  "div",
@@ -1333,20 +1280,20 @@ import {
1333
1280
 
1334
1281
  // src/components/GenUI/elements/confirm_feedback.tsx
1335
1282
  import { Button, Space, Typography } from "antd";
1336
- import { useState as useState9 } from "react";
1283
+ import { useState as useState8 } from "react";
1337
1284
 
1338
1285
  // src/components/GenUI/MDResponse.tsx
1339
1286
  import ReactMarkdown from "react-markdown";
1340
1287
  import { Prism } from "react-syntax-highlighter";
1341
1288
  import { dark } from "react-syntax-highlighter/dist/cjs/styles/prism";
1342
1289
  import remarkGfm from "remark-gfm";
1343
- import { useMemo as useMemo2, useRef as useRef5, useState as useState8 } from "react";
1290
+ import { useMemo as useMemo2, useRef as useRef5, useState as useState7 } from "react";
1344
1291
  import { createStyles as createStyles2 } from "antd-style";
1345
1292
  import rehypeRaw from "rehype-raw";
1346
1293
 
1347
1294
  // src/components/GenUI/MDMermaid.tsx
1348
1295
  import mermaid from "mermaid";
1349
- import { useEffect as useEffect6, useRef as useRef4 } from "react";
1296
+ import { useEffect as useEffect5, useRef as useRef4 } from "react";
1350
1297
  import { v4 } from "uuid";
1351
1298
  import { jsx as jsx5 } from "react/jsx-runtime";
1352
1299
  var MDMermaid = ({ children = [] }) => {
@@ -1354,7 +1301,7 @@ var MDMermaid = ({ children = [] }) => {
1354
1301
  const code = String(children);
1355
1302
  const target = useRef4(null);
1356
1303
  const targetInternal = useRef4(null);
1357
- useEffect6(() => {
1304
+ useEffect5(() => {
1358
1305
  if (target.current && code) {
1359
1306
  mermaid.initialize({
1360
1307
  startOnLoad: true,
@@ -1584,8 +1531,8 @@ var MDViewFormItem = ({ value }) => {
1584
1531
  };
1585
1532
  var IFrameCard = ({ src }) => {
1586
1533
  const containerRef = useRef5(null);
1587
- const [width, setWidth] = useState8("640px");
1588
- const [height, setHeight] = useState8("320px");
1534
+ const [width, setWidth] = useState7("640px");
1535
+ const [height, setHeight] = useState7("320px");
1589
1536
  const valid_images = [
1590
1537
  "jpg",
1591
1538
  "jpeg",
@@ -1615,11 +1562,11 @@ var ConfirmFeedback = ({
1615
1562
  data,
1616
1563
  interactive = true
1617
1564
  }) => {
1618
- const { message: message4, type, config, feedback, options } = data ?? {};
1565
+ const { message: message5, type, config, feedback, options } = data ?? {};
1619
1566
  const { sendMessage } = useAgentChat();
1620
- const [clicked, setClicked] = useState9(false);
1567
+ const [clicked, setClicked] = useState8(false);
1621
1568
  return /* @__PURE__ */ jsxs2(Space, { direction: "vertical", style: { width: "100%" }, children: [
1622
- /* @__PURE__ */ jsx7(MDResponse, { content: message4 }),
1569
+ /* @__PURE__ */ jsx7(MDResponse, { content: message5 }),
1623
1570
  options ? /* @__PURE__ */ jsx7(Space, { style: { justifyContent: "flex-end", width: "100%" }, children: options?.map((option) => /* @__PURE__ */ jsx7(
1624
1571
  Button,
1625
1572
  {
@@ -1696,13 +1643,13 @@ var ConfirmFeedback = ({
1696
1643
 
1697
1644
  // src/components/GenUI/elements/generic_data_table.tsx
1698
1645
  import { Table, Typography as Typography2, Button as Button2, Flex, Space as Space2 } from "antd";
1699
- import { useState as useState10 } from "react";
1646
+ import { useState as useState9 } from "react";
1700
1647
  import { DownloadOutlined, ExpandAltOutlined } from "@ant-design/icons";
1701
1648
  import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
1702
1649
  var { Text: Text2 } = Typography2;
1703
1650
  var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = true }) => {
1704
- const { dataSource, message: message4 } = data ?? {};
1705
- const [expandedRowKeys, setExpandedRowKeys] = useState10([]);
1651
+ const { dataSource, message: message5 } = data ?? {};
1652
+ const [expandedRowKeys, setExpandedRowKeys] = useState9([]);
1706
1653
  const { openSideApp } = useChatUIContext();
1707
1654
  const processedData = dataSource?.map((item, index) => ({
1708
1655
  ...item,
@@ -1785,7 +1732,7 @@ var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = t
1785
1732
  {
1786
1733
  size: "small",
1787
1734
  title: () => /* @__PURE__ */ jsxs3(Flex, { justify: "space-between", align: "center", children: [
1788
- /* @__PURE__ */ jsx8(Space2, { children: /* @__PURE__ */ jsx8(Text2, { strong: true, style: { fontSize: 16 }, children: message4 || "" }) }),
1735
+ /* @__PURE__ */ jsx8(Space2, { children: /* @__PURE__ */ jsx8(Text2, { strong: true, style: { fontSize: 16 }, children: message5 || "" }) }),
1789
1736
  /* @__PURE__ */ jsxs3(Space2, { children: [
1790
1737
  /* @__PURE__ */ jsx8(
1791
1738
  Button2,
@@ -1806,8 +1753,8 @@ var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = t
1806
1753
  onClick: () => {
1807
1754
  openSideApp({
1808
1755
  component_key: "generic_data_table",
1809
- message: message4 || "",
1810
- data: { dataSource, message: message4 }
1756
+ message: message5 || "",
1757
+ data: { dataSource, message: message5 }
1811
1758
  });
1812
1759
  },
1813
1760
  children: [
@@ -2319,7 +2266,7 @@ var WriteTodos = ({
2319
2266
  };
2320
2267
 
2321
2268
  // src/components/GenUI/FileExplorer.tsx
2322
- import { useState as useState11, useEffect as useEffect7, useMemo as useMemo3 } from "react";
2269
+ import { useState as useState10, useEffect as useEffect6, useMemo as useMemo3 } from "react";
2323
2270
  import { Splitter, Tree, Empty, Button as Button3, Tooltip, message } from "antd";
2324
2271
  import {
2325
2272
  FolderOutlined,
@@ -2565,17 +2512,17 @@ var FileExplorer = ({
2565
2512
  }) => {
2566
2513
  const { files } = data ?? {};
2567
2514
  const { styles, cx } = useStyles2();
2568
- const [fileList, setFileList] = useState11([]);
2569
- const [selectedKey, setSelectedKey] = useState11("");
2570
- const [expandedKeys, setExpandedKeys] = useState11([]);
2571
- const [copied, setCopied] = useState11(false);
2572
- useEffect7(() => {
2515
+ const [fileList, setFileList] = useState10([]);
2516
+ const [selectedKey, setSelectedKey] = useState10("");
2517
+ const [expandedKeys, setExpandedKeys] = useState10([]);
2518
+ const [copied, setCopied] = useState10(false);
2519
+ useEffect6(() => {
2573
2520
  if (copied) {
2574
2521
  const timer = setTimeout(() => setCopied(false), 2e3);
2575
2522
  return () => clearTimeout(timer);
2576
2523
  }
2577
2524
  }, [copied]);
2578
- useEffect7(() => {
2525
+ useEffect6(() => {
2579
2526
  let list = [];
2580
2527
  if (Array.isArray(files)) {
2581
2528
  list = files;
@@ -2595,7 +2542,7 @@ var FileExplorer = ({
2595
2542
  () => buildTreeData(fileList, expandedKeys),
2596
2543
  [fileList, expandedKeys]
2597
2544
  );
2598
- useEffect7(() => {
2545
+ useEffect6(() => {
2599
2546
  if (treeData.length > 0 && expandedKeys.length === 0) {
2600
2547
  const getAllKeys = (nodes) => {
2601
2548
  let keys = [];
@@ -2733,7 +2680,7 @@ import {
2733
2680
  Button as Button4
2734
2681
  } from "antd";
2735
2682
  import dayjs from "dayjs";
2736
- import { useState as useState12 } from "react";
2683
+ import { useState as useState11 } from "react";
2737
2684
  import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
2738
2685
  var AttachmentsCard = ({
2739
2686
  data,
@@ -2742,8 +2689,8 @@ var AttachmentsCard = ({
2742
2689
  columns = 1,
2743
2690
  showDownloadButton = false
2744
2691
  }) => {
2745
- const { Text: Text11 } = Typography7;
2746
- const [showAll, setShowAll] = useState12(false);
2692
+ const { Text: Text12 } = Typography7;
2693
+ const [showAll, setShowAll] = useState11(false);
2747
2694
  const { openSideApp } = useChatUIContext();
2748
2695
  const getStyles = () => {
2749
2696
  switch (size) {
@@ -2817,7 +2764,7 @@ var AttachmentsCard = ({
2817
2764
  );
2818
2765
  };
2819
2766
  const renderFileDescription = (item) => /* @__PURE__ */ jsx16(Space7, { direction: "vertical", size: size === "small" ? 2 : 4, children: /* @__PURE__ */ jsx16(Space7, { children: /* @__PURE__ */ jsx16(
2820
- Text11,
2767
+ Text12,
2821
2768
  {
2822
2769
  type: "secondary",
2823
2770
  style: {
@@ -2889,7 +2836,7 @@ var AttachmentsCard = ({
2889
2836
  }
2890
2837
  ),
2891
2838
  item.files && /* @__PURE__ */ jsxs9("div", { style: { paddingLeft: "12px" }, children: [
2892
- /* @__PURE__ */ jsxs9(Text11, { type: "secondary", style: { fontSize: "12px" }, children: [
2839
+ /* @__PURE__ */ jsxs9(Text12, { type: "secondary", style: { fontSize: "12px" }, children: [
2893
2840
  "\u5305\u542B\u6587\u4EF6(",
2894
2841
  item.files.length,
2895
2842
  ")"
@@ -2924,14 +2871,14 @@ var AttachmentsCard = ({
2924
2871
 
2925
2872
  // src/components/GenUI/elements/attachments_viewer_side_app.tsx
2926
2873
  import { Button as Button5, Empty as Empty2, Skeleton } from "antd";
2927
- import { useState as useState13 } from "react";
2874
+ import { useState as useState12 } from "react";
2928
2875
  import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
2929
2876
  function AttachmentsViewerSideApp({
2930
2877
  data,
2931
2878
  component_key
2932
2879
  }) {
2933
- const [fileUri, setFileUri] = useState13();
2934
- const [loading, setLoading] = useState13(true);
2880
+ const [fileUri, setFileUri] = useState12();
2881
+ const [loading, setLoading] = useState12(true);
2935
2882
  const { file_id } = data ?? {};
2936
2883
  if (loading) {
2937
2884
  return /* @__PURE__ */ jsx17(Skeleton, { active: true });
@@ -2994,7 +2941,7 @@ function AttachmentsViewerSideApp({
2994
2941
  import { Button as Button6, Space as Space8, Typography as Typography8 } from "antd";
2995
2942
 
2996
2943
  // src/components/GenUI/elements/ContentPreviewCollapse.tsx
2997
- import { useRef as useRef6, useState as useState14, useEffect as useEffect9, useCallback as useCallback7 } from "react";
2944
+ import { useRef as useRef6, useState as useState13, useEffect as useEffect8, useCallback as useCallback6 } from "react";
2998
2945
  import { Collapse as Collapse4 } from "antd";
2999
2946
  import { createStyles as createStyles6 } from "antd-style";
3000
2947
  import { DownOutlined as DownOutlined2, UpOutlined } from "@ant-design/icons";
@@ -3064,18 +3011,18 @@ var ContentPreviewCollapse = ({
3064
3011
  showAllText = "Show all content",
3065
3012
  showLessText = "Show less"
3066
3013
  }) => {
3067
- const [showFullContent, setShowFullContent] = useState14(false);
3068
- const [isOverflowing, setIsOverflowing] = useState14(false);
3014
+ const [showFullContent, setShowFullContent] = useState13(false);
3015
+ const [isOverflowing, setIsOverflowing] = useState13(false);
3069
3016
  const contentRef = useRef6(null);
3070
3017
  const showShadow = isOverflowing && !showFullContent;
3071
3018
  const { styles, cx } = useStyle4({ showShadow });
3072
- const checkOverflow = useCallback7(() => {
3019
+ const checkOverflow = useCallback6(() => {
3073
3020
  if (contentRef.current) {
3074
3021
  const scrollHeight = contentRef.current.scrollHeight;
3075
3022
  setIsOverflowing(scrollHeight > collapsedMaxHeight);
3076
3023
  }
3077
3024
  }, [collapsedMaxHeight]);
3078
- useEffect9(() => {
3025
+ useEffect8(() => {
3079
3026
  const element = contentRef.current;
3080
3027
  if (!element) return;
3081
3028
  checkOverflow();
@@ -3267,8 +3214,7 @@ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
3267
3214
  var { Text: Text8 } = Typography10;
3268
3215
  var useStyle5 = createStyles7(({ token, css }) => ({
3269
3216
  card: css`
3270
- max-width: 600px;
3271
- background: ${token.colorBgContainer};
3217
+ background: rgba(0, 0, 0, 0.02);
3272
3218
  border: 1px solid ${token.colorBorderSecondary};
3273
3219
  border-radius: 16px;
3274
3220
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
@@ -3278,17 +3224,17 @@ var useStyle5 = createStyles7(({ token, css }) => ({
3278
3224
  &:hover {
3279
3225
  border-color: ${token.colorPrimary};
3280
3226
  box-shadow: 0 8px 24px rgba(24, 144, 255, 0.12);
3281
- transform: translateX(4px);
3227
+ // transform: translateX(4px);
3282
3228
  }
3283
3229
  &::before {
3284
3230
  content: "";
3285
3231
  position: absolute;
3286
3232
  top: 0;
3287
3233
  left: 0;
3288
- bottom: 0;
3289
- width: 4px;
3234
+ right: 0;
3235
+ height: 4px;
3290
3236
  background: linear-gradient(
3291
- 180deg,
3237
+ 90deg,
3292
3238
  ${token.colorPrimary} 0%,
3293
3239
  ${token.colorPrimaryHover} 100%
3294
3240
  );
@@ -3390,14 +3336,34 @@ var useStyle5 = createStyles7(({ token, css }) => ({
3390
3336
  color: ${token.colorTextTertiary};
3391
3337
  font-size: 14px;
3392
3338
  transition: all 0.2s ease;
3393
- `
3394
- }));
3395
- var TaskCard = ({
3396
- data,
3397
- component_key,
3398
- interactive = true
3399
- }) => {
3400
- const { styles } = useStyle5();
3339
+ `,
3340
+ responseSection: css`
3341
+ margin-top: 16px;
3342
+ margin-bottom: 16px;
3343
+ padding-top: 16px;
3344
+ border-top: 1px solid ${token.colorBorderSecondary};
3345
+ `,
3346
+ responseHeader: css`
3347
+ font-size: 13px;
3348
+ font-weight: 600;
3349
+ color: ${token.colorTextSecondary};
3350
+ margin-bottom: 12px;
3351
+ text-transform: uppercase;
3352
+ letter-spacing: 0.5px;
3353
+ `,
3354
+ responseContent: css`
3355
+ padding: 12px;
3356
+ background: ${token.colorFillAlter};
3357
+ border-radius: 8px;
3358
+ border: 1px solid ${token.colorBorderSecondary};
3359
+ `
3360
+ }));
3361
+ var TaskCard = ({
3362
+ data,
3363
+ component_key,
3364
+ interactive = true
3365
+ }) => {
3366
+ const { styles } = useStyle5();
3401
3367
  const toolCallData = data;
3402
3368
  const { openSideApp } = useChatUIContext();
3403
3369
  if (!toolCallData) {
@@ -3405,6 +3371,7 @@ var TaskCard = ({
3405
3371
  }
3406
3372
  const { description, subagent_type, assignee } = toolCallData?.args || {};
3407
3373
  const status = toolCallData.status || "pending";
3374
+ const response = toolCallData.response || null;
3408
3375
  const { threadId } = useAgentChat();
3409
3376
  const subagent_thread_id = (threadId || "") + "____" + subagent_type + "_" + toolCallData.id;
3410
3377
  const getStatusConfig = (status2) => {
@@ -3434,6 +3401,7 @@ var TaskCard = ({
3434
3401
  }
3435
3402
  };
3436
3403
  const statusConfig = getStatusConfig(status);
3404
+ const showResponse = status === "success" && response;
3437
3405
  const handleCardClick = () => {
3438
3406
  openSideApp({
3439
3407
  component_key: "task",
@@ -3494,7 +3462,18 @@ var TaskCard = ({
3494
3462
  )
3495
3463
  ] }),
3496
3464
  interactive && /* @__PURE__ */ jsx22(RightOutlined2, { className: styles.actionIcon })
3497
- ] })
3465
+ ] }),
3466
+ showResponse && /* @__PURE__ */ jsxs14(
3467
+ "div",
3468
+ {
3469
+ className: styles.responseSection,
3470
+ onClick: (e) => e.stopPropagation(),
3471
+ children: [
3472
+ /* @__PURE__ */ jsx22(Text8, { className: styles.responseHeader, children: "Response" }),
3473
+ /* @__PURE__ */ jsx22("div", { className: styles.responseContent, children: /* @__PURE__ */ jsx22(MDResponse, { content: response }) })
3474
+ ]
3475
+ }
3476
+ )
3498
3477
  ] })
3499
3478
  }
3500
3479
  );
@@ -3521,22 +3500,22 @@ import { Space as Space10 } from "antd";
3521
3500
  import ErrorBoundary from "antd/es/alert/ErrorBoundary";
3522
3501
  import {
3523
3502
  memo,
3524
- useCallback as useCallback8,
3525
- useEffect as useEffect10,
3503
+ useCallback as useCallback7,
3504
+ useEffect as useEffect9,
3526
3505
  useMemo as useMemo4,
3527
3506
  useRef as useRef7,
3528
- useState as useState15
3507
+ useState as useState14
3529
3508
  } from "react";
3530
3509
  import { jsx as jsx23 } from "react/jsx-runtime";
3531
3510
  var LazyBubble = ({
3532
- message: message4,
3511
+ message: message5,
3533
3512
  renderContent,
3534
3513
  autoLoadRightPanel
3535
3514
  }) => {
3536
3515
  const ref = useRef7(null);
3537
- const [isVisible, setIsVisible] = useState15(false);
3538
- const [wasEverVisible, setWasEverVisible] = useState15(false);
3539
- useEffect10(() => {
3516
+ const [isVisible, setIsVisible] = useState14(false);
3517
+ const [wasEverVisible, setWasEverVisible] = useState14(false);
3518
+ useEffect9(() => {
3540
3519
  const observer = new IntersectionObserver(
3541
3520
  ([entry]) => {
3542
3521
  const visible = entry.isIntersecting;
@@ -3556,14 +3535,14 @@ var LazyBubble = ({
3556
3535
  }
3557
3536
  };
3558
3537
  }, [wasEverVisible]);
3559
- useEffect10(() => {
3538
+ useEffect9(() => {
3560
3539
  autoLoadRightPanel?.();
3561
3540
  }, []);
3562
3541
  const getPlaceholder = () => {
3563
- const estimatedHeight = message4.content ? Math.min(100, message4.content.length / 5) : 100;
3542
+ const estimatedHeight = message5.content ? Math.min(100, message5.content.length / 5) : 100;
3564
3543
  return /* @__PURE__ */ jsx23("div", { style: { height: `${estimatedHeight}px`, minHeight: "50px" } });
3565
3544
  };
3566
- return /* @__PURE__ */ jsx23(ErrorBoundary, { children: /* @__PURE__ */ jsx23("div", { ref, style: { width: "100%" }, children: isVisible || wasEverVisible ? renderContent(message4) : getPlaceholder() }) });
3545
+ return /* @__PURE__ */ jsx23(ErrorBoundary, { children: /* @__PURE__ */ jsx23("div", { ref, style: { width: "100%" }, children: isVisible || wasEverVisible ? renderContent(message5) : getPlaceholder() }) });
3567
3546
  };
3568
3547
  var MemoizedBubbleList = memo(
3569
3548
  ({
@@ -3589,13 +3568,13 @@ var MessageList = ({
3589
3568
  const { styles } = useStyle();
3590
3569
  const { openSideApp } = useChatUIContext();
3591
3570
  const messageLengthRef = useRef7(messages?.length ?? 0);
3592
- useEffect10(() => {
3571
+ useEffect9(() => {
3593
3572
  if (messages?.length) {
3594
3573
  messageLengthRef.current = messages?.length;
3595
3574
  }
3596
3575
  }, [messages?.length]);
3597
- const renderContent = useCallback8((message4) => {
3598
- const { content } = message4;
3576
+ const renderContent = useCallback7((message5) => {
3577
+ const { content } = message5;
3599
3578
  try {
3600
3579
  const json = JSON.parse(content);
3601
3580
  if (json.action && json.message) {
@@ -3603,7 +3582,7 @@ var MessageList = ({
3603
3582
  }
3604
3583
  } catch (error) {
3605
3584
  }
3606
- const tool_calls_md = message4.tool_calls?.map((tool_call) => {
3585
+ const tool_calls_md = message5.tool_calls?.map((tool_call) => {
3607
3586
  return `\`\`\`tool_call
3608
3587
  ${JSON.stringify(tool_call)}
3609
3588
  \`\`\``;
@@ -3612,17 +3591,17 @@ ${JSON.stringify(tool_call)}
3612
3591
  return /* @__PURE__ */ jsx23(Space10, { direction: "vertical", style: { width: "100%" }, children: /* @__PURE__ */ jsx23(MDResponse, { content: content_md }) });
3613
3592
  }, []);
3614
3593
  const items = useMemo4(
3615
- () => messages.map((message4, index) => ({
3616
- key: message4.id,
3617
- role: message4.role,
3594
+ () => messages.map((message5, index) => ({
3595
+ key: message5.id,
3596
+ role: message5.role,
3618
3597
  typing: false,
3619
3598
  content: /* @__PURE__ */ jsx23(
3620
3599
  LazyBubble,
3621
3600
  {
3622
- message: message4,
3601
+ message: message5,
3623
3602
  renderContent,
3624
3603
  autoLoadRightPanel: () => {
3625
- const { content, role: role2 } = message4;
3604
+ const { content, role: role2 } = message5;
3626
3605
  const isNewAddedMessage = messageLengthRef.current > 1 && messageLengthRef.current + 1 === messages.length;
3627
3606
  if (index === messages.length - 1 && isNewAddedMessage && role2 === "ai") {
3628
3607
  try {
@@ -3695,7 +3674,7 @@ import {
3695
3674
  Button as Button10,
3696
3675
  message as message3
3697
3676
  } from "antd";
3698
- import React6, { useEffect as useEffect11, useRef as useRef8, useState as useState16 } from "react";
3677
+ import React6, { useEffect as useEffect10, useRef as useRef8, useState as useState15 } from "react";
3699
3678
 
3700
3679
  // src/components/GenUI/HITLContainer.tsx
3701
3680
  import {
@@ -3875,8 +3854,8 @@ var AgentHeader = (props) => {
3875
3854
  style: { padding: 8 },
3876
3855
  variant: "borderless",
3877
3856
  description,
3878
- icon: /* @__PURE__ */ jsx27(Avatar2, { src: avatar || "/images/avatar.jpeg", size: 48 }),
3879
- title: name || "Fina",
3857
+ icon: avatar ? /* @__PURE__ */ jsx27(Avatar2, { src: avatar, size: 48 }) : /* @__PURE__ */ jsx27(Avatar2, { size: 48, children: name?.charAt(0).toUpperCase() }),
3858
+ title: name ? name : void 0,
3880
3859
  extra: /* @__PURE__ */ jsxs16(Space12, { children: [
3881
3860
  extra,
3882
3861
  /* @__PURE__ */ jsx27(TodoProgress, {}),
@@ -3913,10 +3892,10 @@ var Chating = ({
3913
3892
  showHITL = true,
3914
3893
  showRefreshButton = false
3915
3894
  }) => {
3916
- const [content, setContent] = useState16("");
3917
- const [attachedFiles, setAttachedFiles] = useState16([]);
3895
+ const [content, setContent] = useState15("");
3896
+ const [attachedFiles, setAttachedFiles] = useState15([]);
3918
3897
  const { styles } = useStyle();
3919
- const [headerOpen, setHeaderOpen] = useState16(false);
3898
+ const [headerOpen, setHeaderOpen] = useState15(false);
3920
3899
  const attachmentsRef = useRef8(null);
3921
3900
  const senderRef = React6.useRef(null);
3922
3901
  const {
@@ -3930,7 +3909,7 @@ var Chating = ({
3930
3909
  tenantId,
3931
3910
  clearError
3932
3911
  } = useAgentChat();
3933
- useEffect11(() => {
3912
+ useEffect10(() => {
3934
3913
  regsiterElement("action_show_attachments_uploader", {
3935
3914
  card_view: () => null,
3936
3915
  action: (data) => {
@@ -4221,7 +4200,7 @@ var regsiterElement = (language, ElementMeta) => {
4221
4200
  // src/components/Chat/SideAppViewBrowser.tsx
4222
4201
  import { Button as Button11, Tabs } from "antd";
4223
4202
  import { createStyles as createStyles9 } from "antd-style";
4224
- import { useEffect as useEffect12, useState as useState17 } from "react";
4203
+ import { useEffect as useEffect11, useState as useState16 } from "react";
4225
4204
  import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
4226
4205
  var useStyle7 = createStyles9(({ token, css }) => {
4227
4206
  return {
@@ -4256,10 +4235,10 @@ var SideAppViewBrowser = () => {
4256
4235
  openSideApp,
4257
4236
  closeSideApp
4258
4237
  } = useChatUIContext();
4259
- const [activeKey, setActiveKey] = useState17(
4238
+ const [activeKey, setActiveKey] = useState16(
4260
4239
  JSON.stringify(sideAppSelectedCard)
4261
4240
  );
4262
- const [items, setItems] = useState17([]);
4241
+ const [items, setItems] = useState16([]);
4263
4242
  const add = (key, label, children) => {
4264
4243
  const newActiveKey = key;
4265
4244
  const newPanes = [...items];
@@ -4295,7 +4274,7 @@ var SideAppViewBrowser = () => {
4295
4274
  remove(targetKey);
4296
4275
  }
4297
4276
  };
4298
- useEffect12(() => {
4277
+ useEffect11(() => {
4299
4278
  const SideAppView = getElement(sideAppSelectedCard?.component_key).side_app_view || EmptySideAppView;
4300
4279
  const key = JSON.stringify(sideAppSelectedCard);
4301
4280
  if (items.find((item) => item.key === key)) {
@@ -4400,7 +4379,7 @@ var SideAppViewBrowser = () => {
4400
4379
  // src/components/Chat/LatticeChat.tsx
4401
4380
  import { jsx as jsx31 } from "react/jsx-runtime";
4402
4381
  var LatticeChat = (props) => {
4403
- const { assistant_id, thread_id, ...chatingProps } = props;
4382
+ const { assistant_id, thread_id = "", menu, ...chatingProps } = props;
4404
4383
  return /* @__PURE__ */ jsx31(
4405
4384
  AgentThreadProvider,
4406
4385
  {
@@ -4414,7 +4393,8 @@ var LatticeChat = (props) => {
4414
4393
  children: /* @__PURE__ */ jsx31(ChatUIContextProvider, { children: /* @__PURE__ */ jsx31(
4415
4394
  ColumnLayout,
4416
4395
  {
4417
- left: /* @__PURE__ */ jsx31(Chating, { ...chatingProps }),
4396
+ menu,
4397
+ left: thread_id ? /* @__PURE__ */ jsx31(Chating, { ...chatingProps }) : /* @__PURE__ */ jsx31("div", { children: "\u9700\u8981\u5148\u521B\u5EFA\u4F1A\u8BDD" }),
4418
4398
  right: /* @__PURE__ */ jsx31(SideAppViewBrowser, {})
4419
4399
  }
4420
4400
  ) })
@@ -4422,26 +4402,2356 @@ var LatticeChat = (props) => {
4422
4402
  );
4423
4403
  };
4424
4404
 
4425
- // src/components/Chat/AgentConversations.tsx
4405
+ // src/components/Chat/ConversationContext.tsx
4426
4406
  import {
4427
- CodeOutlined as CodeOutlined4,
4428
- FileImageOutlined as FileImageOutlined3,
4429
- FileSearchOutlined,
4430
- SignatureOutlined
4431
- } from "@ant-design/icons";
4432
- import { Conversations } from "@ant-design/x";
4433
- import { theme } from "antd";
4434
- import { useState as useState18 } from "react";
4407
+ createContext as createContext6,
4408
+ useCallback as useCallback10,
4409
+ useContext as useContext6,
4410
+ useEffect as useEffect13,
4411
+ useMemo as useMemo7,
4412
+ useRef as useRef10,
4413
+ useState as useState19
4414
+ } from "react";
4415
+
4416
+ // src/components/Chat/AssistantContext.tsx
4417
+ import {
4418
+ createContext as createContext5,
4419
+ useCallback as useCallback9,
4420
+ useContext as useContext5,
4421
+ useEffect as useEffect12,
4422
+ useMemo as useMemo6,
4423
+ useRef as useRef9,
4424
+ useState as useState18
4425
+ } from "react";
4426
+ import {
4427
+ Client as Client2
4428
+ } from "@axiom-lattice/client-sdk";
4429
+
4430
+ // src/components/Chat/LatticeChatShellContext.tsx
4431
+ import {
4432
+ createContext as createContext4,
4433
+ useCallback as useCallback8,
4434
+ useContext as useContext4,
4435
+ useState as useState17
4436
+ } from "react";
4435
4437
  import { jsx as jsx32 } from "react/jsx-runtime";
4438
+ var DEFAULT_CONFIG = {
4439
+ baseURL: "http://localhost:4001",
4440
+ apiKey: "",
4441
+ transport: "sse",
4442
+ timeout: 3e5,
4443
+ headers: {}
4444
+ };
4445
+ var LatticeChatShellContext = createContext4({
4446
+ config: DEFAULT_CONFIG,
4447
+ updateConfig: () => {
4448
+ },
4449
+ updateConfigValue: () => {
4450
+ },
4451
+ resetConfig: () => {
4452
+ }
4453
+ });
4454
+ var LatticeChatShellContextProvider = ({
4455
+ children,
4456
+ initialConfig = {},
4457
+ persistToLocalStorage = false,
4458
+ localStorageKey = "lattice_chat_shell_config"
4459
+ }) => {
4460
+ const loadInitialConfig = useCallback8(() => {
4461
+ if (persistToLocalStorage && typeof window !== "undefined") {
4462
+ try {
4463
+ const stored = localStorage.getItem(localStorageKey);
4464
+ if (stored) {
4465
+ const parsed = JSON.parse(stored);
4466
+ return { ...DEFAULT_CONFIG, ...parsed, ...initialConfig };
4467
+ }
4468
+ } catch (error) {
4469
+ console.warn("Failed to load config from localStorage:", error);
4470
+ }
4471
+ }
4472
+ return { ...DEFAULT_CONFIG, ...initialConfig };
4473
+ }, [persistToLocalStorage, localStorageKey, initialConfig]);
4474
+ const [config, setConfig] = useState17(loadInitialConfig);
4475
+ const saveToLocalStorage = useCallback8(
4476
+ (newConfig) => {
4477
+ if (persistToLocalStorage && typeof window !== "undefined") {
4478
+ try {
4479
+ localStorage.setItem(localStorageKey, JSON.stringify(newConfig));
4480
+ } catch (error) {
4481
+ console.warn("Failed to save config to localStorage:", error);
4482
+ }
4483
+ }
4484
+ },
4485
+ [persistToLocalStorage, localStorageKey]
4486
+ );
4487
+ const updateConfig = useCallback8(
4488
+ (updates) => {
4489
+ setConfig((prev) => {
4490
+ const newConfig = { ...prev, ...updates };
4491
+ saveToLocalStorage(newConfig);
4492
+ return newConfig;
4493
+ });
4494
+ },
4495
+ [saveToLocalStorage]
4496
+ );
4497
+ const updateConfigValue = useCallback8(
4498
+ (key, value) => {
4499
+ setConfig((prev) => {
4500
+ const newConfig = { ...prev, [key]: value };
4501
+ saveToLocalStorage(newConfig);
4502
+ return newConfig;
4503
+ });
4504
+ },
4505
+ [saveToLocalStorage]
4506
+ );
4507
+ const resetConfig = useCallback8(() => {
4508
+ const defaultConfig = { ...DEFAULT_CONFIG, ...initialConfig };
4509
+ setConfig(defaultConfig);
4510
+ saveToLocalStorage(defaultConfig);
4511
+ }, [initialConfig, saveToLocalStorage]);
4512
+ return /* @__PURE__ */ jsx32(
4513
+ LatticeChatShellContext.Provider,
4514
+ {
4515
+ value: {
4516
+ config,
4517
+ updateConfig,
4518
+ updateConfigValue,
4519
+ resetConfig
4520
+ },
4521
+ children
4522
+ }
4523
+ );
4524
+ };
4525
+ var useLatticeChatShellContext = () => {
4526
+ const context = useContext4(LatticeChatShellContext);
4527
+ if (!context) {
4528
+ throw new Error(
4529
+ "useLatticeChatShellContext must be used within a LatticeChatShellContextProvider"
4530
+ );
4531
+ }
4532
+ return context;
4533
+ };
4534
+
4535
+ // src/components/Chat/AssistantContext.tsx
4536
+ import { jsx as jsx33 } from "react/jsx-runtime";
4537
+ var AssistantContext = createContext5({
4538
+ assistants: [],
4539
+ currentAssistant: null,
4540
+ isLoading: false,
4541
+ error: null,
4542
+ listAssistants: async () => {
4543
+ },
4544
+ getAssistant: async () => {
4545
+ throw new Error("Not implemented");
4546
+ },
4547
+ createAssistant: async () => {
4548
+ throw new Error("Not implemented");
4549
+ },
4550
+ updateAssistant: async () => {
4551
+ throw new Error("Not implemented");
4552
+ },
4553
+ deleteAssistant: async () => {
4554
+ },
4555
+ selectAssistant: async () => {
4556
+ },
4557
+ clearCurrentAssistant: () => {
4558
+ },
4559
+ refresh: async () => {
4560
+ }
4561
+ });
4562
+ var AssistantContextProvider = ({
4563
+ children,
4564
+ autoLoad = true,
4565
+ initialAssistantId = null
4566
+ }) => {
4567
+ const {
4568
+ config: { baseURL, apiKey = "", transport = "sse" }
4569
+ } = useLatticeChatShellContext();
4570
+ const client = useMemo6(
4571
+ () => new Client2({
4572
+ baseURL,
4573
+ apiKey,
4574
+ assistantId: "",
4575
+ transport
4576
+ }),
4577
+ [baseURL, apiKey, transport]
4578
+ );
4579
+ const [state, setState] = useState18({
4580
+ assistants: [],
4581
+ currentAssistant: null,
4582
+ isLoading: false,
4583
+ error: null
4584
+ });
4585
+ const assistantsRef = useRef9([]);
4586
+ useEffect12(() => {
4587
+ assistantsRef.current = state.assistants;
4588
+ }, [state.assistants]);
4589
+ const listAssistants = useCallback9(async () => {
4590
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4591
+ try {
4592
+ const assistants = await client.assistants.list();
4593
+ setState((prev) => ({
4594
+ ...prev,
4595
+ assistants,
4596
+ isLoading: false
4597
+ }));
4598
+ } catch (error) {
4599
+ setState((prev) => ({
4600
+ ...prev,
4601
+ isLoading: false,
4602
+ error: error instanceof Error ? error : new Error(String(error))
4603
+ }));
4604
+ }
4605
+ }, [client]);
4606
+ const getAssistant = useCallback9(
4607
+ async (id) => {
4608
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4609
+ try {
4610
+ const assistant = await client.assistants.get(id);
4611
+ setState((prev) => ({
4612
+ ...prev,
4613
+ // Update assistant in list if it exists
4614
+ assistants: prev.assistants.map((a) => a.id === id ? assistant : a),
4615
+ isLoading: false
4616
+ }));
4617
+ return assistant;
4618
+ } catch (error) {
4619
+ setState((prev) => ({
4620
+ ...prev,
4621
+ isLoading: false,
4622
+ error: error instanceof Error ? error : new Error(String(error))
4623
+ }));
4624
+ throw error;
4625
+ }
4626
+ },
4627
+ [client]
4628
+ );
4629
+ const createAssistant = useCallback9(
4630
+ async (options) => {
4631
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4632
+ try {
4633
+ const newAssistant = await client.assistants.create(options);
4634
+ setState((prev) => ({
4635
+ ...prev,
4636
+ assistants: [...prev.assistants, newAssistant],
4637
+ isLoading: false
4638
+ }));
4639
+ return newAssistant;
4640
+ } catch (error) {
4641
+ setState((prev) => ({
4642
+ ...prev,
4643
+ isLoading: false,
4644
+ error: error instanceof Error ? error : new Error(String(error))
4645
+ }));
4646
+ throw error;
4647
+ }
4648
+ },
4649
+ [client]
4650
+ );
4651
+ const updateAssistant = useCallback9(
4652
+ async (id, options) => {
4653
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4654
+ try {
4655
+ const updatedAssistant = await client.assistants.update(id, options);
4656
+ setState((prev) => ({
4657
+ ...prev,
4658
+ assistants: prev.assistants.map(
4659
+ (a) => a.id === id ? updatedAssistant : a
4660
+ ),
4661
+ currentAssistant: prev.currentAssistant?.id === id ? updatedAssistant : prev.currentAssistant,
4662
+ isLoading: false
4663
+ }));
4664
+ return updatedAssistant;
4665
+ } catch (error) {
4666
+ setState((prev) => ({
4667
+ ...prev,
4668
+ isLoading: false,
4669
+ error: error instanceof Error ? error : new Error(String(error))
4670
+ }));
4671
+ throw error;
4672
+ }
4673
+ },
4674
+ [client]
4675
+ );
4676
+ const deleteAssistant = useCallback9(
4677
+ async (id) => {
4678
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4679
+ try {
4680
+ await client.assistants.delete(id);
4681
+ setState((prev) => ({
4682
+ ...prev,
4683
+ assistants: prev.assistants.filter((a) => a.id !== id),
4684
+ currentAssistant: prev.currentAssistant?.id === id ? null : prev.currentAssistant,
4685
+ isLoading: false
4686
+ }));
4687
+ } catch (error) {
4688
+ setState((prev) => ({
4689
+ ...prev,
4690
+ isLoading: false,
4691
+ error: error instanceof Error ? error : new Error(String(error))
4692
+ }));
4693
+ throw error;
4694
+ }
4695
+ },
4696
+ [client]
4697
+ );
4698
+ const selectAssistant = useCallback9(
4699
+ async (id) => {
4700
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4701
+ try {
4702
+ const assistant = assistantsRef.current.find((a) => a.id === id);
4703
+ if (!assistant) {
4704
+ const fetchedAssistant = await client.assistants.get(id);
4705
+ setState((prev) => ({
4706
+ ...prev,
4707
+ assistants: [...prev.assistants, fetchedAssistant],
4708
+ currentAssistant: fetchedAssistant,
4709
+ isLoading: false
4710
+ }));
4711
+ } else {
4712
+ setState((prev) => ({
4713
+ ...prev,
4714
+ currentAssistant: assistant,
4715
+ isLoading: false
4716
+ }));
4717
+ }
4718
+ } catch (error) {
4719
+ setState((prev) => ({
4720
+ ...prev,
4721
+ isLoading: false,
4722
+ error: error instanceof Error ? error : new Error(String(error))
4723
+ }));
4724
+ throw error;
4725
+ }
4726
+ },
4727
+ [client]
4728
+ );
4729
+ const clearCurrentAssistant = useCallback9(() => {
4730
+ setState((prev) => ({
4731
+ ...prev,
4732
+ currentAssistant: null
4733
+ }));
4734
+ }, []);
4735
+ const refresh = useCallback9(async () => {
4736
+ await listAssistants();
4737
+ }, [listAssistants]);
4738
+ useEffect12(() => {
4739
+ if (autoLoad) {
4740
+ listAssistants();
4741
+ }
4742
+ }, [autoLoad, listAssistants]);
4743
+ useEffect12(() => {
4744
+ if (state.assistants.length > 0 && !state.currentAssistant) {
4745
+ if (initialAssistantId) {
4746
+ const assistant = state.assistants.find(
4747
+ (a) => a.id === initialAssistantId
4748
+ );
4749
+ if (assistant) {
4750
+ setState((prev) => ({
4751
+ ...prev,
4752
+ currentAssistant: assistant
4753
+ }));
4754
+ }
4755
+ } else {
4756
+ setState((prev) => ({
4757
+ ...prev,
4758
+ currentAssistant: prev.assistants[0]
4759
+ }));
4760
+ }
4761
+ }
4762
+ }, [initialAssistantId, state.assistants, state.currentAssistant]);
4763
+ return /* @__PURE__ */ jsx33(
4764
+ AssistantContext.Provider,
4765
+ {
4766
+ value: {
4767
+ ...state,
4768
+ listAssistants,
4769
+ getAssistant,
4770
+ createAssistant,
4771
+ updateAssistant,
4772
+ deleteAssistant,
4773
+ selectAssistant,
4774
+ clearCurrentAssistant,
4775
+ refresh
4776
+ },
4777
+ children
4778
+ }
4779
+ );
4780
+ };
4781
+ var useAssistantContext = () => {
4782
+ const context = useContext5(AssistantContext);
4783
+ if (!context) {
4784
+ throw new Error(
4785
+ "useAssistantContext must be used within an AssistantContextProvider"
4786
+ );
4787
+ }
4788
+ return context;
4789
+ };
4790
+
4791
+ // src/components/Chat/ConversationContext.tsx
4792
+ import { Client as Client3 } from "@axiom-lattice/client-sdk";
4793
+ import { jsx as jsx34 } from "react/jsx-runtime";
4794
+ var ConversationContext = createContext6({
4795
+ assistantId: null,
4796
+ thread: null,
4797
+ threadId: null,
4798
+ threads: [],
4799
+ isLoading: false,
4800
+ error: null,
4801
+ setThread: () => {
4802
+ },
4803
+ selectThread: () => {
4804
+ },
4805
+ createThread: async () => {
4806
+ throw new Error("Not implemented");
4807
+ },
4808
+ listThreads: async () => [],
4809
+ updateThread: async () => {
4810
+ },
4811
+ getThreadById: () => null,
4812
+ deleteThread: async () => {
4813
+ },
4814
+ clearThread: () => {
4815
+ },
4816
+ refresh: async () => {
4817
+ }
4818
+ });
4819
+ function convertThreadToConversationThread(thread, label) {
4820
+ return {
4821
+ id: thread.id,
4822
+ label: label || thread.metadata?.label || new Date(thread.createdAt).toLocaleString()
4823
+ };
4824
+ }
4825
+ function getThreadMetadata(label) {
4826
+ return label ? { label } : {};
4827
+ }
4828
+ var ConversationContextProvider = ({
4829
+ children
4830
+ }) => {
4831
+ const { currentAssistant } = useAssistantContext();
4832
+ const assistantId = currentAssistant?.id || null;
4833
+ const {
4834
+ config: { baseURL, apiKey = "", transport = "sse" }
4835
+ } = useLatticeChatShellContext();
4836
+ const client = useMemo7(
4837
+ () => new Client3({
4838
+ baseURL,
4839
+ apiKey,
4840
+ assistantId: assistantId || "",
4841
+ transport
4842
+ }),
4843
+ [baseURL, apiKey, assistantId, transport]
4844
+ );
4845
+ const [threads, setThreads] = useState19([]);
4846
+ const [threadId, setThreadId] = useState19(null);
4847
+ const [isLoading, setIsLoading] = useState19(false);
4848
+ const [error, setError] = useState19(null);
4849
+ const loadedAssistantIdRef = useRef10(null);
4850
+ const prevAssistantIdRef = useRef10(null);
4851
+ const isLoadingRef = useRef10(false);
4852
+ const clientRef = useRef10(client);
4853
+ useEffect13(() => {
4854
+ clientRef.current = client;
4855
+ }, [client]);
4856
+ const loadThreads = useCallback10(async () => {
4857
+ const currentClient = clientRef.current;
4858
+ if (!assistantId || !currentClient.assistantId) {
4859
+ setThreads([]);
4860
+ loadedAssistantIdRef.current = null;
4861
+ return;
4862
+ }
4863
+ if (isLoadingRef.current && loadedAssistantIdRef.current === assistantId) {
4864
+ return;
4865
+ }
4866
+ isLoadingRef.current = true;
4867
+ setIsLoading(true);
4868
+ setError(null);
4869
+ try {
4870
+ const apiThreads = await currentClient.threads.list();
4871
+ const conversationThreads = apiThreads.map(
4872
+ (t) => convertThreadToConversationThread(t)
4873
+ );
4874
+ if (conversationThreads.length === 0) {
4875
+ try {
4876
+ const apiThread = await currentClient.threads.create({
4877
+ metadata: getThreadMetadata()
4878
+ });
4879
+ const newThread = convertThreadToConversationThread(apiThread);
4880
+ setThreads([newThread]);
4881
+ setThreadId(newThread.id);
4882
+ } catch (createErr) {
4883
+ const createError = createErr instanceof Error ? createErr : new Error(String(createErr));
4884
+ setError(createError);
4885
+ console.error("Failed to create initial thread:", createError);
4886
+ setThreads([]);
4887
+ }
4888
+ } else {
4889
+ setThreads(conversationThreads);
4890
+ setThreadId((currentThreadId) => {
4891
+ if (!currentThreadId) {
4892
+ const latestThread = conversationThreads[conversationThreads.length - 1];
4893
+ return latestThread.id;
4894
+ }
4895
+ const threadExists = conversationThreads.some(
4896
+ (t) => t.id === currentThreadId
4897
+ );
4898
+ if (!threadExists) {
4899
+ const latestThread = conversationThreads[conversationThreads.length - 1];
4900
+ return latestThread.id;
4901
+ }
4902
+ return currentThreadId;
4903
+ });
4904
+ }
4905
+ loadedAssistantIdRef.current = assistantId;
4906
+ } catch (err) {
4907
+ const error2 = err instanceof Error ? err : new Error(String(err));
4908
+ setError(error2);
4909
+ console.error("Failed to load threads:", error2);
4910
+ } finally {
4911
+ setIsLoading(false);
4912
+ isLoadingRef.current = false;
4913
+ }
4914
+ }, [assistantId]);
4915
+ useEffect13(() => {
4916
+ const currentClient = clientRef.current;
4917
+ const prevAssistantId = prevAssistantIdRef.current;
4918
+ const assistantChanged = prevAssistantId !== assistantId;
4919
+ if (assistantId && currentClient.assistantId === assistantId) {
4920
+ if (assistantChanged) {
4921
+ setThreadId(null);
4922
+ prevAssistantIdRef.current = assistantId;
4923
+ }
4924
+ if (loadedAssistantIdRef.current !== assistantId) {
4925
+ loadThreads();
4926
+ }
4927
+ } else {
4928
+ setThreadId(null);
4929
+ setThreads([]);
4930
+ loadedAssistantIdRef.current = null;
4931
+ prevAssistantIdRef.current = null;
4932
+ }
4933
+ }, [assistantId, loadThreads]);
4934
+ const thread = useMemo7(() => {
4935
+ if (!assistantId || !threadId) {
4936
+ return null;
4937
+ }
4938
+ return threads.find((t) => t.id === threadId) || null;
4939
+ }, [assistantId, threadId, threads]);
4940
+ const setThread = useCallback10((newThread) => {
4941
+ if (newThread) {
4942
+ setThreadId(newThread.id);
4943
+ } else {
4944
+ setThreadId(null);
4945
+ }
4946
+ }, []);
4947
+ const selectThread = useCallback10(
4948
+ (targetThreadId) => {
4949
+ const foundThread = threads.find((t) => t.id === targetThreadId);
4950
+ if (foundThread) {
4951
+ setThreadId(targetThreadId);
4952
+ }
4953
+ },
4954
+ [threads]
4955
+ );
4956
+ const createThread = useCallback10(
4957
+ async (label) => {
4958
+ if (!assistantId || !client.assistantId) {
4959
+ throw new Error("No assistant selected");
4960
+ }
4961
+ setIsLoading(true);
4962
+ setError(null);
4963
+ try {
4964
+ const apiThread = await client.threads.create({
4965
+ metadata: getThreadMetadata(label)
4966
+ });
4967
+ const newThread = convertThreadToConversationThread(apiThread, label);
4968
+ await loadThreads();
4969
+ setThreadId(newThread.id);
4970
+ return newThread;
4971
+ } catch (err) {
4972
+ const error2 = err instanceof Error ? err : new Error(String(err));
4973
+ setError(error2);
4974
+ throw error2;
4975
+ } finally {
4976
+ setIsLoading(false);
4977
+ }
4978
+ },
4979
+ [assistantId, client, loadThreads]
4980
+ );
4981
+ const listThreads = useCallback10(async () => {
4982
+ if (!assistantId || !client.assistantId) {
4983
+ return [];
4984
+ }
4985
+ setIsLoading(true);
4986
+ setError(null);
4987
+ try {
4988
+ const apiThreads = await client.threads.list();
4989
+ const conversationThreads = apiThreads.map(
4990
+ (t) => convertThreadToConversationThread(t)
4991
+ );
4992
+ setThreads(conversationThreads);
4993
+ return conversationThreads;
4994
+ } catch (err) {
4995
+ const error2 = err instanceof Error ? err : new Error(String(err));
4996
+ setError(error2);
4997
+ return threads;
4998
+ } finally {
4999
+ setIsLoading(false);
5000
+ }
5001
+ }, [assistantId, client, threads]);
5002
+ const updateThread = useCallback10(
5003
+ async (newThread) => {
5004
+ if (!assistantId || !client.assistantId) {
5005
+ throw new Error("No assistant selected");
5006
+ }
5007
+ setIsLoading(true);
5008
+ setError(null);
5009
+ try {
5010
+ await client.threads.update(newThread.id, {
5011
+ metadata: getThreadMetadata(newThread.label)
5012
+ });
5013
+ await loadThreads();
5014
+ } catch (err) {
5015
+ const error2 = err instanceof Error ? err : new Error(String(err));
5016
+ setError(error2);
5017
+ throw error2;
5018
+ } finally {
5019
+ setIsLoading(false);
5020
+ }
5021
+ },
5022
+ [assistantId, client, loadThreads]
5023
+ );
5024
+ const getThreadById = useCallback10(
5025
+ (targetThreadId) => {
5026
+ return threads.find((t) => t.id === targetThreadId) || null;
5027
+ },
5028
+ [threads]
5029
+ );
5030
+ const deleteThread = useCallback10(
5031
+ async (targetThreadId) => {
5032
+ if (!assistantId || !client.assistantId) {
5033
+ throw new Error("No assistant selected");
5034
+ }
5035
+ setIsLoading(true);
5036
+ setError(null);
5037
+ try {
5038
+ await client.threads.delete(targetThreadId);
5039
+ await loadThreads();
5040
+ if (targetThreadId === threadId) {
5041
+ setThreadId(null);
5042
+ }
5043
+ } catch (err) {
5044
+ const error2 = err instanceof Error ? err : new Error(String(err));
5045
+ setError(error2);
5046
+ throw error2;
5047
+ } finally {
5048
+ setIsLoading(false);
5049
+ }
5050
+ },
5051
+ [threadId, assistantId, client, loadThreads]
5052
+ );
5053
+ const clearThread = useCallback10(() => {
5054
+ setThreadId(null);
5055
+ }, []);
5056
+ return /* @__PURE__ */ jsx34(
5057
+ ConversationContext.Provider,
5058
+ {
5059
+ value: {
5060
+ assistantId,
5061
+ thread,
5062
+ threadId,
5063
+ threads,
5064
+ isLoading,
5065
+ error,
5066
+ setThread,
5067
+ selectThread,
5068
+ createThread,
5069
+ listThreads,
5070
+ updateThread,
5071
+ getThreadById,
5072
+ deleteThread,
5073
+ clearThread,
5074
+ refresh: loadThreads
5075
+ },
5076
+ children
5077
+ }
5078
+ );
5079
+ };
5080
+ var useConversationContext = () => {
5081
+ const context = useContext6(ConversationContext);
5082
+ if (!context) {
5083
+ throw new Error(
5084
+ "useConversationContext must be used within a ConversationContextProvider"
5085
+ );
5086
+ }
5087
+ return context;
5088
+ };
5089
+
5090
+ // src/components/Chat/AgentConversations.tsx
5091
+ import { Conversations } from "@ant-design/x";
5092
+ import { theme } from "antd";
5093
+ import { useMemo as useMemo8 } from "react";
5094
+ import { jsx as jsx35 } from "react/jsx-runtime";
5095
+ var AgentConversations = () => {
5096
+ const { token } = theme.useToken();
5097
+ const { currentAssistant } = useAssistantContext();
5098
+ const {
5099
+ assistantId,
5100
+ thread,
5101
+ selectThread,
5102
+ createThread,
5103
+ listThreads,
5104
+ threads
5105
+ } = useConversationContext();
5106
+ const style = {
5107
+ width: "100%",
5108
+ background: "transparent",
5109
+ borderRadius: token.borderRadius
5110
+ };
5111
+ const threadItems = useMemo8(() => {
5112
+ return threads || [];
5113
+ }, [threads]);
5114
+ const items = threadItems.map((thread2) => ({
5115
+ key: thread2.id,
5116
+ label: thread2.label
5117
+ }));
5118
+ const newChatClick = async () => {
5119
+ if (!assistantId) {
5120
+ return;
5121
+ }
5122
+ await createThread();
5123
+ };
5124
+ return /* @__PURE__ */ jsx35(
5125
+ Conversations,
5126
+ {
5127
+ creation: {
5128
+ onClick: newChatClick
5129
+ },
5130
+ items,
5131
+ activeKey: thread?.id,
5132
+ style,
5133
+ groupable: true,
5134
+ onActiveChange: (key) => {
5135
+ selectThread(key);
5136
+ }
5137
+ }
5138
+ );
5139
+ };
5140
+
5141
+ // src/components/Chat/ChatSidebar.tsx
5142
+ import { useState as useState21 } from "react";
5143
+ import { Divider as Divider2 } from "antd";
5144
+ import {
5145
+ MenuFoldOutlined,
5146
+ MenuUnfoldOutlined,
5147
+ SettingOutlined
5148
+ } from "@ant-design/icons";
5149
+
5150
+ // src/components/Chat/AssistantList.tsx
5151
+ import { Conversations as Conversations2 } from "@ant-design/x";
5152
+ import { Avatar as Avatar3, theme as theme2 } from "antd";
5153
+ import { jsx as jsx36 } from "react/jsx-runtime";
5154
+ var AssistantList = () => {
5155
+ const { token } = theme2.useToken();
5156
+ const { assistants, selectAssistant, currentAssistant } = useAssistantContext();
5157
+ const style = {
5158
+ width: "100%",
5159
+ background: "transparent",
5160
+ borderRadius: token.borderRadius
5161
+ };
5162
+ const items = assistants.map((assistant) => ({
5163
+ key: assistant.id,
5164
+ label: assistant.name,
5165
+ icon: /* @__PURE__ */ jsx36(
5166
+ Avatar3,
5167
+ {
5168
+ size: "small",
5169
+ style: {
5170
+ backgroundColor: token.colorFillSecondary,
5171
+ color: token.colorText
5172
+ },
5173
+ children: assistant.name.charAt(0).toUpperCase()
5174
+ }
5175
+ )
5176
+ }));
5177
+ return /* @__PURE__ */ jsx36(
5178
+ Conversations2,
5179
+ {
5180
+ items,
5181
+ activeKey: currentAssistant?.id,
5182
+ style,
5183
+ onActiveChange: (key) => {
5184
+ selectAssistant(key);
5185
+ }
5186
+ }
5187
+ );
5188
+ };
5189
+
5190
+ // src/components/Chat/ChatSidebar.tsx
5191
+ import { createStyles as createStyles11 } from "antd-style";
5192
+
5193
+ // src/components/Chat/SettingsModal.tsx
5194
+ import { useState as useState20, useEffect as useEffect14, useRef as useRef11 } from "react";
5195
+ import {
5196
+ Modal,
5197
+ Input,
5198
+ Button as Button12,
5199
+ message as message4,
5200
+ Typography as Typography13,
5201
+ Alert as Alert3,
5202
+ Select,
5203
+ Switch,
5204
+ Space as Space13,
5205
+ Tabs as Tabs2,
5206
+ Drawer
5207
+ } from "antd";
5208
+ import {
5209
+ SaveOutlined,
5210
+ EnvironmentOutlined,
5211
+ ReloadOutlined as ReloadOutlined2,
5212
+ CheckCircleOutlined as CheckCircleOutlined4,
5213
+ ApiOutlined,
5214
+ LinkOutlined,
5215
+ CheckCircleFilled,
5216
+ CloseCircleFilled,
5217
+ PlusOutlined,
5218
+ CloudServerOutlined
5219
+ } from "@ant-design/icons";
5220
+ import { createStyles as createStyles10 } from "antd-style";
5221
+ import { Fragment as Fragment5, jsx as jsx37, jsxs as jsxs19 } from "react/jsx-runtime";
5222
+ var { Text: Text11, Title: Title2 } = Typography13;
5223
+ var { TextArea } = Input;
5224
+ var useStyles3 = createStyles10(({ token, css }) => ({
5225
+ // settingsModal: css`
5226
+ // .ant-modal {
5227
+ // max-width: 100vw !important;
5228
+ // width: 100vw !important;
5229
+ // margin: 0 !important;
5230
+ // top: 0 !important;
5231
+ // padding-bottom: 0 !important;
5232
+ // }
5233
+ // .ant-modal-content {
5234
+ // padding: 0;
5235
+ // height: 100vh;
5236
+ // max-height: 100vh;
5237
+ // border-radius: 0;
5238
+ // overflow: hidden;
5239
+ // width: 100%;
5240
+ // }
5241
+ // .ant-modal-body {
5242
+ // padding: 0;
5243
+ // height: 100%;
5244
+ // display: flex;
5245
+ // overflow: hidden;
5246
+ // width: 100%;
5247
+ // }
5248
+ // `,
5249
+ tabsContainer: css`
5250
+ height: 100vh;
5251
+ display: flex;
5252
+ flex-direction: column;
5253
+ overflow: hidden;
5254
+
5255
+ .ant-tabs {
5256
+ height: 100%;
5257
+ display: flex;
5258
+ flex-direction: column;
5259
+ }
5260
+
5261
+ .ant-tabs-content-holder {
5262
+ flex: 1;
5263
+ overflow: hidden;
5264
+ }
5265
+
5266
+ .ant-tabs-content {
5267
+ height: 100%;
5268
+ }
5269
+
5270
+ .ant-tabs-tabpane {
5271
+ height: 100%;
5272
+ overflow: hidden;
5273
+ }
5274
+
5275
+ .ant-tabs-nav {
5276
+ margin: 0;
5277
+ padding: 0 ${token.paddingLG}px;
5278
+ background: ${token.colorBgContainer};
5279
+ border-bottom: 1px solid ${token.colorBorder};
5280
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5281
+ }
5282
+
5283
+ .ant-tabs-tab {
5284
+ padding: ${token.paddingMD}px ${token.paddingLG}px;
5285
+ margin: ${token.paddingSM}px ${token.marginXS}px 0 0;
5286
+ border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0;
5287
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5288
+
5289
+ &:hover {
5290
+ background: ${token.colorFillTertiary};
5291
+ }
5292
+
5293
+ &.ant-tabs-tab-active {
5294
+ background: ${token.colorBgContainer};
5295
+ border-bottom-color: ${token.colorBgContainer};
5296
+ }
5297
+ }
5298
+ `,
5299
+ tabContent: css`
5300
+ height: 100%;
5301
+ display: flex;
5302
+ flex-direction: column;
5303
+ overflow: hidden;
5304
+ background: linear-gradient(
5305
+ 135deg,
5306
+ ${token.colorBgLayout} 0%,
5307
+ ${token.colorFillQuaternary} 100%
5308
+ );
5309
+ `,
5310
+ sidebar: css`
5311
+ width: 280px;
5312
+ background: linear-gradient(
5313
+ 180deg,
5314
+ ${token.colorBgContainer} 0%,
5315
+ ${token.colorFillQuaternary} 100%
5316
+ );
5317
+ border-right: 1px solid ${token.colorBorder};
5318
+ display: flex;
5319
+ flex-direction: column;
5320
+ overflow-y: auto;
5321
+ flex-shrink: 0;
5322
+ box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);
5323
+
5324
+ /* Custom scrollbar */
5325
+ &::-webkit-scrollbar {
5326
+ width: 8px;
5327
+ }
5328
+
5329
+ &::-webkit-scrollbar-track {
5330
+ background: transparent;
5331
+ }
5332
+
5333
+ &::-webkit-scrollbar-thumb {
5334
+ background: ${token.colorBorder};
5335
+ border-radius: 4px;
5336
+ transition: background 0.2s;
5337
+
5338
+ &:hover {
5339
+ background: ${token.colorBorderSecondary};
5340
+ }
5341
+ }
5342
+ `,
5343
+ sidebarHeader: css`
5344
+ padding: ${token.paddingXL}px ${token.paddingLG}px;
5345
+ border-bottom: 1px solid ${token.colorBorder};
5346
+ background: linear-gradient(
5347
+ 135deg,
5348
+ ${token.colorPrimaryBg} 0%,
5349
+ ${token.colorBgContainer} 100%
5350
+ );
5351
+ position: sticky;
5352
+ top: 0;
5353
+ z-index: 10;
5354
+ backdrop-filter: blur(10px);
5355
+ `,
5356
+ sidebarTitle: css`
5357
+ font-size: ${token.fontSizeXL}px;
5358
+ font-weight: 700;
5359
+ background: linear-gradient(
5360
+ 135deg,
5361
+ ${token.colorPrimary} 0%,
5362
+ ${token.colorPrimaryHover} 100%
5363
+ );
5364
+ -webkit-background-clip: text;
5365
+ -webkit-text-fill-color: transparent;
5366
+ background-clip: text;
5367
+ margin: 0;
5368
+ letter-spacing: -0.5px;
5369
+ `,
5370
+ menuItem: css`
5371
+ padding: ${token.paddingMD}px ${token.paddingLG}px;
5372
+ margin: ${token.marginXS}px ${token.paddingSM}px;
5373
+ cursor: pointer;
5374
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5375
+ border-radius: ${token.borderRadiusLG}px;
5376
+ display: flex;
5377
+ align-items: center;
5378
+ gap: ${token.marginMD}px;
5379
+ position: relative;
5380
+ overflow: hidden;
5381
+
5382
+ &::before {
5383
+ content: "";
5384
+ position: absolute;
5385
+ left: 0;
5386
+ top: 0;
5387
+ bottom: 0;
5388
+ width: 3px;
5389
+ background: ${token.colorPrimary};
5390
+ transform: scaleY(0);
5391
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5392
+ border-radius: 0 2px 2px 0;
5393
+ }
5394
+
5395
+ &:hover {
5396
+ background: ${token.colorFillTertiary};
5397
+ transform: translateX(4px);
5398
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
5399
+ }
5400
+
5401
+ &.active {
5402
+ background: linear-gradient(
5403
+ 135deg,
5404
+ ${token.colorPrimaryBg} 0%,
5405
+ ${token.colorFillTertiary} 100%
5406
+ );
5407
+ color: ${token.colorPrimary};
5408
+ box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
5409
+ transform: translateX(4px);
5410
+
5411
+ &::before {
5412
+ transform: scaleY(1);
5413
+ }
5414
+
5415
+ .menuItemIcon {
5416
+ transform: scale(1.1);
5417
+ }
5418
+ }
5419
+ `,
5420
+ menuItemIcon: css`
5421
+ font-size: 18px;
5422
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5423
+ display: flex;
5424
+ align-items: center;
5425
+ justify-content: center;
5426
+ width: 24px;
5427
+ height: 24px;
5428
+ `,
5429
+ menuItemText: css`
5430
+ font-size: ${token.fontSize}px;
5431
+ font-weight: 600;
5432
+ letter-spacing: 0.2px;
5433
+ `,
5434
+ content: css`
5435
+ flex: 1;
5436
+ display: flex;
5437
+ flex-direction: column;
5438
+ overflow: hidden;
5439
+ width: 100%;
5440
+ min-width: 0;
5441
+ `,
5442
+ contentHeader: css`
5443
+ padding: ${token.paddingLG}px ${token.paddingXL * 2}px;
5444
+ background: ${token.colorBgContainer};
5445
+ border-bottom: 1px solid ${token.colorBorder};
5446
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5447
+ position: sticky;
5448
+ top: 0;
5449
+ z-index: 5;
5450
+ backdrop-filter: blur(10px);
5451
+ display: flex;
5452
+ justify-content: space-between;
5453
+ align-items: center;
5454
+ gap: ${token.marginLG}px;
5455
+ `,
5456
+ contentHeaderLeft: css`
5457
+ flex: 1;
5458
+ `,
5459
+ contentHeaderRight: css`
5460
+ display: flex;
5461
+ gap: ${token.marginMD}px;
5462
+ flex-shrink: 0;
5463
+ `,
5464
+ contentTitle: css`
5465
+ font-size: ${token.fontSizeHeading3}px;
5466
+ font-weight: 700;
5467
+ color: ${token.colorTextHeading};
5468
+ margin: 0 0 ${token.marginSM}px 0;
5469
+ letter-spacing: -0.5px;
5470
+ `,
5471
+ contentDescription: css`
5472
+ color: ${token.colorTextSecondary};
5473
+ font-size: ${token.fontSize}px;
5474
+ margin: 0;
5475
+ line-height: 1.6;
5476
+ `,
5477
+ contentBody: css`
5478
+ flex: 1;
5479
+ overflow-y: auto;
5480
+ padding: ${token.paddingXL * 2}px ${token.paddingXL * 2}px;
5481
+ background: transparent;
5482
+
5483
+ /* Custom scrollbar */
5484
+ &::-webkit-scrollbar {
5485
+ width: 8px;
5486
+ }
5487
+
5488
+ &::-webkit-scrollbar-track {
5489
+ background: transparent;
5490
+ }
5491
+
5492
+ &::-webkit-scrollbar-thumb {
5493
+ background: ${token.colorBorder};
5494
+ border-radius: 4px;
5495
+ transition: background 0.2s;
5496
+
5497
+ &:hover {
5498
+ background: ${token.colorBorderSecondary};
5499
+ }
5500
+ }
5501
+ `,
5502
+ formContainer: css`
5503
+ width: 100%;
5504
+ max-width: 100%;
5505
+ `,
5506
+ formLabel: css`
5507
+ font-weight: 600;
5508
+ color: ${token.colorTextHeading};
5509
+ margin-bottom: ${token.marginMD}px;
5510
+ display: block;
5511
+ font-size: ${token.fontSize}px;
5512
+ `,
5513
+ formDescription: css`
5514
+ color: ${token.colorTextSecondary};
5515
+ font-size: ${token.fontSizeSM}px;
5516
+ margin-top: ${token.marginSM}px;
5517
+ line-height: 1.6;
5518
+ `,
5519
+ card: css`
5520
+ background: ${token.colorBgContainer};
5521
+ border: 1px solid ${token.colorBorder};
5522
+ border-radius: ${token.borderRadiusLG}px;
5523
+ padding: ${token.paddingXL}px;
5524
+ margin-bottom: ${token.marginLG}px;
5525
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5526
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5527
+
5528
+ &:hover {
5529
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
5530
+ transform: translateY(-2px);
5531
+ border-color: ${token.colorPrimary};
5532
+ }
5533
+ `,
5534
+ alertCard: css`
5535
+ border-radius: ${token.borderRadiusLG}px;
5536
+ margin-bottom: ${token.marginLG}px;
5537
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5538
+ border: 1px solid ${token.colorBorder};
5539
+ `,
5540
+ textArea: css`
5541
+ border-radius: ${token.borderRadius}px;
5542
+ border: 1px solid ${token.colorBorder};
5543
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5544
+
5545
+ &:hover {
5546
+ border-color: ${token.colorPrimaryHover};
5547
+ }
5548
+
5549
+ &:focus {
5550
+ border-color: ${token.colorPrimary};
5551
+ box-shadow: 0 0 0 2px ${token.colorPrimaryBg};
5552
+ }
5553
+ `,
5554
+ connectionStatus: css`
5555
+ display: flex;
5556
+ align-items: center;
5557
+ gap: ${token.marginXS}px;
5558
+ margin-left: ${token.marginSM}px;
5559
+ `,
5560
+ addServerModal: css`
5561
+ .ant-modal-body {
5562
+ padding: ${token.paddingXL}px;
5563
+ }
5564
+ `
5565
+ }));
5566
+ var SETTINGS_MENU_ITEMS = [
5567
+ {
5568
+ key: "environment",
5569
+ label: "Environment Variables",
5570
+ icon: /* @__PURE__ */ jsx37(EnvironmentOutlined, {})
5571
+ },
5572
+ {
5573
+ key: "models",
5574
+ label: "Model Configuration",
5575
+ icon: /* @__PURE__ */ jsx37(ApiOutlined, {})
5576
+ }
5577
+ ];
5578
+ var SettingsModal = ({
5579
+ open,
5580
+ onClose
5581
+ }) => {
5582
+ const { styles } = useStyles3();
5583
+ const { config: shellConfig, updateConfigValue } = useLatticeChatShellContext();
5584
+ const [connections, setConnections] = useState20(() => {
5585
+ if (typeof window !== "undefined") {
5586
+ try {
5587
+ const stored = localStorage.getItem("lattice_server_connections");
5588
+ if (stored) {
5589
+ const parsed = JSON.parse(stored);
5590
+ return parsed;
5591
+ }
5592
+ } catch (error) {
5593
+ console.warn("Failed to load connections from localStorage:", error);
5594
+ }
5595
+ }
5596
+ if (shellConfig.baseURL) {
5597
+ return [
5598
+ {
5599
+ id: "default",
5600
+ name: "Default",
5601
+ url: shellConfig.baseURL
5602
+ }
5603
+ ];
5604
+ }
5605
+ return [];
5606
+ });
5607
+ const [serverConfigs, setServerConfigs] = useState20({});
5608
+ const connectionsRef = useRef11(connections);
5609
+ useEffect14(() => {
5610
+ connectionsRef.current = connections;
5611
+ }, [connections]);
5612
+ const [activeTabKey, setActiveTabKey] = useState20(
5613
+ connections.length > 0 ? connections[0].id : ""
5614
+ );
5615
+ const [activeMenu, setActiveMenu] = useState20("environment");
5616
+ const [loading, setLoading] = useState20(false);
5617
+ const [showAddServerModal, setShowAddServerModal] = useState20(false);
5618
+ const [newServerUrl, setNewServerUrl] = useState20("");
5619
+ const [newServerName, setNewServerName] = useState20("");
5620
+ const [newServerApiKey, setNewServerApiKey] = useState20("");
5621
+ const [addingServer, setAddingServer] = useState20(false);
5622
+ const saveConnections = (newConnections) => {
5623
+ setConnections(newConnections);
5624
+ if (typeof window !== "undefined") {
5625
+ try {
5626
+ localStorage.setItem(
5627
+ "lattice_server_connections",
5628
+ JSON.stringify(newConnections)
5629
+ );
5630
+ } catch (error) {
5631
+ console.warn("Failed to save connections to localStorage:", error);
5632
+ }
5633
+ }
5634
+ };
5635
+ const initializeServerConfig = (serverId) => {
5636
+ if (!serverConfigs[serverId]) {
5637
+ setServerConfigs((prev) => ({
5638
+ ...prev,
5639
+ [serverId]: {
5640
+ envText: "",
5641
+ models: [
5642
+ {
5643
+ key: "",
5644
+ model: "",
5645
+ provider: "openai",
5646
+ streaming: false,
5647
+ apiKey: "",
5648
+ baseURL: ""
5649
+ }
5650
+ ]
5651
+ }
5652
+ }));
5653
+ }
5654
+ };
5655
+ const checkConnection = async (serverId) => {
5656
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5657
+ if (!connection) return;
5658
+ const url = connection.url;
5659
+ if (!url) {
5660
+ updateConnectionStatus(serverId, { connected: false });
5661
+ return;
5662
+ }
5663
+ try {
5664
+ updateConnectionStatus(serverId, { connecting: true, error: "" });
5665
+ const controller = new AbortController();
5666
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
5667
+ const headers = {};
5668
+ if (connection.apiKey) {
5669
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5670
+ }
5671
+ const response = await fetch(`${url}/api/config`, {
5672
+ method: "GET",
5673
+ signal: controller.signal,
5674
+ headers
5675
+ });
5676
+ clearTimeout(timeoutId);
5677
+ if (response.ok) {
5678
+ updateConnectionStatus(serverId, {
5679
+ connected: true,
5680
+ connecting: false,
5681
+ error: ""
5682
+ });
5683
+ if (url !== shellConfig.baseURL) {
5684
+ updateConfigValue("baseURL", url);
5685
+ }
5686
+ } else {
5687
+ updateConnectionStatus(serverId, {
5688
+ connected: false,
5689
+ connecting: false,
5690
+ error: "Server returned an error"
5691
+ });
5692
+ }
5693
+ } catch (error) {
5694
+ if (error.name === "AbortError") {
5695
+ updateConnectionStatus(serverId, {
5696
+ connected: false,
5697
+ connecting: false,
5698
+ error: "Connection timeout"
5699
+ });
5700
+ } else {
5701
+ updateConnectionStatus(serverId, {
5702
+ connected: false,
5703
+ connecting: false,
5704
+ error: error.message || "Failed to connect to server"
5705
+ });
5706
+ }
5707
+ }
5708
+ };
5709
+ const updateConnectionStatus = (serverId, updates) => {
5710
+ setConnections(
5711
+ (prev) => prev.map(
5712
+ (conn) => conn.id === serverId ? { ...conn, ...updates } : conn
5713
+ )
5714
+ );
5715
+ };
5716
+ const loadCurrentConfig = async (serverId) => {
5717
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5718
+ if (!connection || !connection.connected) return;
5719
+ const url = connection.url;
5720
+ if (!url) return;
5721
+ try {
5722
+ const headers = {};
5723
+ if (connection.apiKey) {
5724
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5725
+ }
5726
+ const response = await fetch(`${url}/api/config`, {
5727
+ headers
5728
+ });
5729
+ if (response.ok) {
5730
+ const data = await response.json();
5731
+ if (data.success && data.data) {
5732
+ const lines = [];
5733
+ const configData = data.data;
5734
+ if (configData.port !== void 0) {
5735
+ lines.push(`PORT=${configData.port}`);
5736
+ }
5737
+ if (configData.queueServiceType) {
5738
+ lines.push(`QUEUE_SERVICE_TYPE=${configData.queueServiceType}`);
5739
+ }
5740
+ if (configData.redisUrl) {
5741
+ lines.push(`REDIS_URL=${configData.redisUrl}`);
5742
+ }
5743
+ if (configData.redisPassword) {
5744
+ lines.push(`REDIS_PASSWORD=`);
5745
+ }
5746
+ if (configData.queueName) {
5747
+ lines.push(`QUEUE_NAME=${configData.queueName}`);
5748
+ }
5749
+ setServerConfigs((prev) => ({
5750
+ ...prev,
5751
+ [serverId]: {
5752
+ ...prev[serverId],
5753
+ envText: lines.join("\n")
5754
+ }
5755
+ }));
5756
+ }
5757
+ }
5758
+ } catch (error) {
5759
+ console.error("Failed to load configuration:", error);
5760
+ message4.error("Failed to load current configuration");
5761
+ }
5762
+ };
5763
+ const loadModelsConfig = async (serverId) => {
5764
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5765
+ if (!connection || !connection.connected) return;
5766
+ const url = connection.url;
5767
+ if (!url) return;
5768
+ try {
5769
+ const headers = {};
5770
+ if (connection.apiKey) {
5771
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5772
+ }
5773
+ const response = await fetch(`${url}/api/models`, {
5774
+ headers
5775
+ });
5776
+ if (response.ok) {
5777
+ const data = await response.json();
5778
+ if (data.success && data.data && Array.isArray(data.data)) {
5779
+ if (data.data.length > 0) {
5780
+ setServerConfigs((prev) => ({
5781
+ ...prev,
5782
+ [serverId]: {
5783
+ ...prev[serverId],
5784
+ models: data.data
5785
+ }
5786
+ }));
5787
+ } else {
5788
+ setServerConfigs((prev) => ({
5789
+ ...prev,
5790
+ [serverId]: {
5791
+ ...prev[serverId],
5792
+ models: [
5793
+ {
5794
+ key: "",
5795
+ model: "",
5796
+ provider: "openai",
5797
+ streaming: false,
5798
+ apiKey: "",
5799
+ baseURL: ""
5800
+ }
5801
+ ]
5802
+ }
5803
+ }));
5804
+ }
5805
+ }
5806
+ }
5807
+ } catch (error) {
5808
+ console.error("Failed to load models configuration:", error);
5809
+ }
5810
+ };
5811
+ useEffect14(() => {
5812
+ if (open && activeTabKey) {
5813
+ initializeServerConfig(activeTabKey);
5814
+ const connection = connections.find((c) => c.id === activeTabKey);
5815
+ if (connection && !connection.connected && !connection.connecting) {
5816
+ checkConnection(activeTabKey);
5817
+ }
5818
+ }
5819
+ }, [open, activeTabKey]);
5820
+ useEffect14(() => {
5821
+ if (open && activeTabKey) {
5822
+ const connection = connections.find((c) => c.id === activeTabKey);
5823
+ if (connection?.connected) {
5824
+ if (activeMenu === "environment") {
5825
+ loadCurrentConfig(activeTabKey);
5826
+ } else if (activeMenu === "models") {
5827
+ loadModelsConfig(activeTabKey);
5828
+ }
5829
+ }
5830
+ }
5831
+ }, [open, activeTabKey, activeMenu]);
5832
+ const handleAddServer = async () => {
5833
+ if (!newServerUrl.trim()) {
5834
+ message4.error("Please enter a server URL");
5835
+ return;
5836
+ }
5837
+ let normalizedUrl = newServerUrl.trim();
5838
+ if (!normalizedUrl.startsWith("http://") && !normalizedUrl.startsWith("https://")) {
5839
+ normalizedUrl = `http://${normalizedUrl}`;
5840
+ }
5841
+ const serverName = newServerName.trim() || normalizedUrl.replace(/^https?:\/\//, "");
5842
+ const newConnection = {
5843
+ id: `conn_${Date.now()}`,
5844
+ name: serverName,
5845
+ url: normalizedUrl,
5846
+ apiKey: newServerApiKey.trim() || void 0,
5847
+ connected: false
5848
+ };
5849
+ setAddingServer(true);
5850
+ const newConnections = [...connections, newConnection];
5851
+ saveConnections(newConnections);
5852
+ setActiveTabKey(newConnection.id);
5853
+ initializeServerConfig(newConnection.id);
5854
+ await checkConnection(newConnection.id);
5855
+ setAddingServer(false);
5856
+ setShowAddServerModal(false);
5857
+ setNewServerUrl("");
5858
+ setNewServerName("");
5859
+ setNewServerApiKey("");
5860
+ message4.success("Server added successfully");
5861
+ };
5862
+ const handleDeleteServer = (serverId) => {
5863
+ const newConnections = connections.filter((c) => c.id !== serverId);
5864
+ saveConnections(newConnections);
5865
+ setServerConfigs((prev) => {
5866
+ const newConfigs = { ...prev };
5867
+ delete newConfigs[serverId];
5868
+ return newConfigs;
5869
+ });
5870
+ if (activeTabKey === serverId) {
5871
+ if (newConnections.length > 0) {
5872
+ setActiveTabKey(newConnections[0].id);
5873
+ } else {
5874
+ setActiveTabKey("");
5875
+ }
5876
+ }
5877
+ message4.success("Server deleted");
5878
+ };
5879
+ const handleSave = async () => {
5880
+ const connection = connections.find((c) => c.id === activeTabKey);
5881
+ if (!connection || !connection.connected) {
5882
+ message4.error("Please connect to a server first");
5883
+ return;
5884
+ }
5885
+ const url = connection.url;
5886
+ if (!url) {
5887
+ message4.error("Please connect to a server first");
5888
+ return;
5889
+ }
5890
+ try {
5891
+ setLoading(true);
5892
+ const config = serverConfigs[activeTabKey];
5893
+ if (activeMenu === "environment") {
5894
+ const configObj = {};
5895
+ const lines = config.envText.split("\n");
5896
+ for (const line of lines) {
5897
+ const trimmedLine = line.trim();
5898
+ if (!trimmedLine || trimmedLine.startsWith("#")) {
5899
+ continue;
5900
+ }
5901
+ const equalIndex = trimmedLine.indexOf("=");
5902
+ if (equalIndex === -1) {
5903
+ continue;
5904
+ }
5905
+ const key = trimmedLine.substring(0, equalIndex).trim();
5906
+ const value = trimmedLine.substring(equalIndex + 1).trim();
5907
+ if (!key) {
5908
+ continue;
5909
+ }
5910
+ const upperKey = key.toUpperCase();
5911
+ if (upperKey === "PORT") {
5912
+ if (value) {
5913
+ configObj.port = Number(value);
5914
+ }
5915
+ } else if (upperKey === "QUEUE_SERVICE_TYPE") {
5916
+ if (value) {
5917
+ configObj.queueServiceType = value;
5918
+ }
5919
+ } else if (upperKey === "REDIS_URL") {
5920
+ if (value) {
5921
+ configObj.redisUrl = value;
5922
+ }
5923
+ } else if (upperKey === "REDIS_PASSWORD") {
5924
+ if (value) {
5925
+ configObj.redisPassword = value;
5926
+ }
5927
+ } else if (upperKey === "QUEUE_NAME") {
5928
+ if (value) {
5929
+ configObj.queueName = value;
5930
+ }
5931
+ } else {
5932
+ if (value) {
5933
+ configObj[key] = value;
5934
+ }
5935
+ }
5936
+ }
5937
+ const headers = {
5938
+ "Content-Type": "application/json"
5939
+ };
5940
+ if (connection.apiKey) {
5941
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5942
+ }
5943
+ const response = await fetch(`${url}/api/config`, {
5944
+ method: "PUT",
5945
+ headers,
5946
+ body: JSON.stringify({ config: configObj })
5947
+ });
5948
+ const data = await response.json();
5949
+ if (response.ok && data.success) {
5950
+ if (data.requiresRestart && data.requiresRestart.length > 0) {
5951
+ message4.warning(
5952
+ `Configuration saved. Please restart the server for ${data.requiresRestart.join(
5953
+ ", "
5954
+ )} to take effect.`,
5955
+ 5
5956
+ );
5957
+ } else {
5958
+ message4.success("Configuration saved and applied successfully");
5959
+ }
5960
+ if (data.warnings && data.warnings.length > 0) {
5961
+ data.warnings.forEach((warning) => {
5962
+ message4.warning(warning, 5);
5963
+ });
5964
+ }
5965
+ onClose();
5966
+ } else {
5967
+ message4.error(data.error || "Failed to save configuration");
5968
+ }
5969
+ } else if (activeMenu === "models") {
5970
+ const validModels = config.models.filter(
5971
+ (m) => m.key && m.model && m.provider
5972
+ );
5973
+ const headers = {
5974
+ "Content-Type": "application/json"
5975
+ };
5976
+ if (connection.apiKey) {
5977
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5978
+ }
5979
+ const response = await fetch(`${url}/api/models`, {
5980
+ method: "PUT",
5981
+ headers,
5982
+ body: JSON.stringify({ models: validModels })
5983
+ });
5984
+ const data = await response.json();
5985
+ if (response.ok && data.success) {
5986
+ message4.success(
5987
+ "Model configuration saved and registered successfully"
5988
+ );
5989
+ onClose();
5990
+ } else {
5991
+ message4.error(data.error || "Failed to save model configuration");
5992
+ }
5993
+ }
5994
+ } catch (error) {
5995
+ console.error("Failed to save configuration:", error);
5996
+ message4.error(error.message || "Failed to save configuration");
5997
+ } finally {
5998
+ setLoading(false);
5999
+ }
6000
+ };
6001
+ const renderEnvironmentSettings = (serverId) => {
6002
+ const config = serverConfigs[serverId] || { envText: "", models: [] };
6003
+ const setEnvText = (text) => {
6004
+ setServerConfigs((prev) => ({
6005
+ ...prev,
6006
+ [serverId]: {
6007
+ ...prev[serverId],
6008
+ envText: text
6009
+ }
6010
+ }));
6011
+ };
6012
+ return /* @__PURE__ */ jsxs19("div", { className: styles.formContainer, children: [
6013
+ /* @__PURE__ */ jsx37(
6014
+ Alert3,
6015
+ {
6016
+ message: "Configuration Effect",
6017
+ description: /* @__PURE__ */ jsxs19("div", { children: [
6018
+ /* @__PURE__ */ jsxs19("div", { style: { marginBottom: 8 }, children: [
6019
+ /* @__PURE__ */ jsx37(
6020
+ CheckCircleOutlined4,
6021
+ {
6022
+ style: { color: "#52c41a", marginRight: 8 }
6023
+ }
6024
+ ),
6025
+ /* @__PURE__ */ jsx37("strong", { children: "Immediately effective:" }),
6026
+ " QUEUE_SERVICE_TYPE, REDIS_URL, REDIS_PASSWORD, QUEUE_NAME"
6027
+ ] }),
6028
+ /* @__PURE__ */ jsxs19("div", { children: [
6029
+ /* @__PURE__ */ jsx37(ReloadOutlined2, { style: { color: "#faad14", marginRight: 8 } }),
6030
+ /* @__PURE__ */ jsx37("strong", { children: "Requires restart:" }),
6031
+ " PORT (server must be restarted to change port)"
6032
+ ] })
6033
+ ] }),
6034
+ type: "info",
6035
+ showIcon: true,
6036
+ className: styles.alertCard
6037
+ }
6038
+ ),
6039
+ /* @__PURE__ */ jsx37("div", { style: { marginBottom: 24 }, children: /* @__PURE__ */ jsx37(Text11, { type: "secondary", style: { fontSize: 14, lineHeight: 1.6 }, children: "Configure environment variables in .env format (key=value). One variable per line. Leave password fields empty to keep current values." }) }),
6040
+ /* @__PURE__ */ jsx37(
6041
+ TextArea,
6042
+ {
6043
+ value: config.envText,
6044
+ onChange: (e) => setEnvText(e.target.value),
6045
+ placeholder: `PORT=4001
6046
+ QUEUE_SERVICE_TYPE=redis
6047
+ REDIS_URL=redis://localhost:6379
6048
+ REDIS_PASSWORD=
6049
+ QUEUE_NAME=tasks`,
6050
+ rows: 18,
6051
+ className: styles.textArea,
6052
+ style: {
6053
+ fontFamily: "SF Mono, Monaco, Inconsolata, Roboto Mono, monospace",
6054
+ fontSize: 13,
6055
+ padding: "16px",
6056
+ lineHeight: 1.6
6057
+ }
6058
+ }
6059
+ )
6060
+ ] });
6061
+ };
6062
+ const renderModelSettings = (serverId) => {
6063
+ const config = serverConfigs[serverId] || {
6064
+ envText: "",
6065
+ models: [
6066
+ {
6067
+ key: "",
6068
+ model: "",
6069
+ provider: "openai",
6070
+ streaming: false,
6071
+ apiKey: "",
6072
+ baseURL: ""
6073
+ }
6074
+ ]
6075
+ };
6076
+ const handleModelChange = (index, field, value) => {
6077
+ const newModels = [...config.models];
6078
+ newModels[index] = { ...newModels[index], [field]: value };
6079
+ setServerConfigs((prev) => ({
6080
+ ...prev,
6081
+ [serverId]: {
6082
+ ...prev[serverId],
6083
+ models: newModels
6084
+ }
6085
+ }));
6086
+ };
6087
+ const handleAddModel = () => {
6088
+ setServerConfigs((prev) => ({
6089
+ ...prev,
6090
+ [serverId]: {
6091
+ ...prev[serverId],
6092
+ models: [
6093
+ ...config.models,
6094
+ {
6095
+ key: "",
6096
+ model: "",
6097
+ provider: "openai",
6098
+ streaming: false,
6099
+ apiKey: "",
6100
+ baseURL: ""
6101
+ }
6102
+ ]
6103
+ }
6104
+ }));
6105
+ };
6106
+ const handleRemoveModel = (index) => {
6107
+ if (config.models.length > 1) {
6108
+ setServerConfigs((prev) => ({
6109
+ ...prev,
6110
+ [serverId]: {
6111
+ ...prev[serverId],
6112
+ models: config.models.filter((_, i) => i !== index)
6113
+ }
6114
+ }));
6115
+ }
6116
+ };
6117
+ return /* @__PURE__ */ jsxs19("div", { className: styles.formContainer, children: [
6118
+ /* @__PURE__ */ jsx37("div", { style: { marginBottom: 32 }, children: /* @__PURE__ */ jsx37(Text11, { type: "secondary", style: { fontSize: 14, lineHeight: 1.6 }, children: "Configure model lattices. Each model will be registered with the provided key and can be used by agents." }) }),
6119
+ config.models.map((model, index) => /* @__PURE__ */ jsxs19("div", { className: styles.card, children: [
6120
+ /* @__PURE__ */ jsxs19(
6121
+ "div",
6122
+ {
6123
+ style: {
6124
+ display: "flex",
6125
+ justifyContent: "space-between",
6126
+ alignItems: "center",
6127
+ marginBottom: 24,
6128
+ paddingBottom: 20,
6129
+ borderBottom: "1px solid rgba(0, 0, 0, 0.06)"
6130
+ },
6131
+ children: [
6132
+ /* @__PURE__ */ jsxs19("div", { children: [
6133
+ /* @__PURE__ */ jsxs19(Text11, { strong: true, style: { fontSize: 16 }, children: [
6134
+ "Model ",
6135
+ index + 1
6136
+ ] }),
6137
+ model.key && /* @__PURE__ */ jsxs19(
6138
+ Text11,
6139
+ {
6140
+ type: "secondary",
6141
+ style: { marginLeft: 8, fontSize: 12 },
6142
+ children: [
6143
+ "(",
6144
+ model.key,
6145
+ ")"
6146
+ ]
6147
+ }
6148
+ )
6149
+ ] }),
6150
+ config.models.length > 1 && /* @__PURE__ */ jsx37(
6151
+ Button12,
6152
+ {
6153
+ type: "text",
6154
+ danger: true,
6155
+ size: "small",
6156
+ onClick: () => handleRemoveModel(index),
6157
+ style: {
6158
+ borderRadius: 6,
6159
+ transition: "all 0.2s"
6160
+ },
6161
+ children: "Remove"
6162
+ }
6163
+ )
6164
+ ]
6165
+ }
6166
+ ),
6167
+ /* @__PURE__ */ jsxs19(Space13, { direction: "vertical", style: { width: "100%" }, size: "large", children: [
6168
+ /* @__PURE__ */ jsxs19("div", { children: [
6169
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formLabel, children: "Key *" }),
6170
+ /* @__PURE__ */ jsx37(
6171
+ Input,
6172
+ {
6173
+ placeholder: "e.g., default, gpt-4, claude",
6174
+ value: model.key,
6175
+ onChange: (e) => handleModelChange(index, "key", e.target.value),
6176
+ style: { height: 40 }
6177
+ }
6178
+ ),
6179
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formDescription, children: "Unique identifier for this model" })
6180
+ ] }),
6181
+ /* @__PURE__ */ jsxs19("div", { children: [
6182
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formLabel, children: "Provider *" }),
6183
+ /* @__PURE__ */ jsx37(
6184
+ Select,
6185
+ {
6186
+ style: { width: "100%", height: 40 },
6187
+ value: model.provider,
6188
+ onChange: (value) => handleModelChange(index, "provider", value),
6189
+ options: [
6190
+ { label: "OpenAI", value: "openai" },
6191
+ { label: "Azure", value: "azure" },
6192
+ { label: "DeepSeek", value: "deepseek" },
6193
+ { label: "SiliconCloud", value: "siliconcloud" },
6194
+ { label: "VolcEngine", value: "volcengine" }
6195
+ ]
6196
+ }
6197
+ )
6198
+ ] }),
6199
+ /* @__PURE__ */ jsxs19("div", { children: [
6200
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formLabel, children: "Model Name *" }),
6201
+ /* @__PURE__ */ jsx37(
6202
+ Input,
6203
+ {
6204
+ placeholder: "e.g., gpt-4, claude-3-opus, kimi-k2-250905",
6205
+ value: model.model,
6206
+ onChange: (e) => handleModelChange(index, "model", e.target.value),
6207
+ style: { height: 40 }
6208
+ }
6209
+ )
6210
+ ] }),
6211
+ /* @__PURE__ */ jsxs19("div", { children: [
6212
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formLabel, children: "API Key" }),
6213
+ /* @__PURE__ */ jsx37(
6214
+ Input.Password,
6215
+ {
6216
+ placeholder: "Enter your API key",
6217
+ value: model.apiKey,
6218
+ onChange: (e) => handleModelChange(index, "apiKey", e.target.value),
6219
+ style: { height: 40 }
6220
+ }
6221
+ ),
6222
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formDescription, children: "API key for the model provider. Leave empty to use environment variable." })
6223
+ ] }),
6224
+ /* @__PURE__ */ jsxs19("div", { children: [
6225
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formLabel, children: "Base URL" }),
6226
+ /* @__PURE__ */ jsx37(
6227
+ Input,
6228
+ {
6229
+ placeholder: "e.g., https://api.openai.com/v1",
6230
+ value: model.baseURL,
6231
+ onChange: (e) => handleModelChange(index, "baseURL", e.target.value),
6232
+ style: { height: 40 }
6233
+ }
6234
+ ),
6235
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formDescription, children: "Optional custom base URL for the API" })
6236
+ ] }),
6237
+ /* @__PURE__ */ jsx37("div", { children: /* @__PURE__ */ jsxs19(Space13, { children: [
6238
+ /* @__PURE__ */ jsx37(
6239
+ Switch,
6240
+ {
6241
+ checked: model.streaming,
6242
+ onChange: (checked) => handleModelChange(index, "streaming", checked)
6243
+ }
6244
+ ),
6245
+ /* @__PURE__ */ jsx37(Text11, { children: "Enable Streaming" })
6246
+ ] }) }),
6247
+ /* @__PURE__ */ jsxs19("div", { style: { display: "flex", gap: 20 }, children: [
6248
+ /* @__PURE__ */ jsxs19("div", { style: { flex: 1 }, children: [
6249
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formLabel, children: "Max Tokens" }),
6250
+ /* @__PURE__ */ jsx37(
6251
+ Input,
6252
+ {
6253
+ type: "number",
6254
+ placeholder: "e.g., 4096",
6255
+ value: model.maxTokens,
6256
+ onChange: (e) => handleModelChange(
6257
+ index,
6258
+ "maxTokens",
6259
+ e.target.value ? Number(e.target.value) : void 0
6260
+ ),
6261
+ style: { height: 40 }
6262
+ }
6263
+ )
6264
+ ] }),
6265
+ /* @__PURE__ */ jsxs19("div", { style: { flex: 1 }, children: [
6266
+ /* @__PURE__ */ jsx37(Text11, { className: styles.formLabel, children: "Temperature" }),
6267
+ /* @__PURE__ */ jsx37(
6268
+ Input,
6269
+ {
6270
+ type: "number",
6271
+ step: "0.1",
6272
+ placeholder: "e.g., 0.7",
6273
+ value: model.temperature,
6274
+ onChange: (e) => handleModelChange(
6275
+ index,
6276
+ "temperature",
6277
+ e.target.value ? Number(e.target.value) : void 0
6278
+ ),
6279
+ style: { height: 40 }
6280
+ }
6281
+ )
6282
+ ] })
6283
+ ] })
6284
+ ] })
6285
+ ] }, index)),
6286
+ /* @__PURE__ */ jsx37(
6287
+ Button12,
6288
+ {
6289
+ type: "dashed",
6290
+ onClick: handleAddModel,
6291
+ block: true,
6292
+ size: "large",
6293
+ style: { marginTop: 24, height: 48 },
6294
+ children: "+ Add Model"
6295
+ }
6296
+ )
6297
+ ] });
6298
+ };
6299
+ const renderContent = (serverId) => {
6300
+ switch (activeMenu) {
6301
+ case "environment":
6302
+ return renderEnvironmentSettings(serverId);
6303
+ case "models":
6304
+ return renderModelSettings(serverId);
6305
+ default:
6306
+ return null;
6307
+ }
6308
+ };
6309
+ const activeMenuItem = SETTINGS_MENU_ITEMS.find(
6310
+ (item) => item.key === activeMenu
6311
+ );
6312
+ const currentConnection = connections.find((c) => c.id === activeTabKey);
6313
+ const renderTabLabel = (connection) => {
6314
+ return /* @__PURE__ */ jsxs19("div", { style: { display: "flex", alignItems: "center" }, children: [
6315
+ /* @__PURE__ */ jsx37(
6316
+ CloudServerOutlined,
6317
+ {
6318
+ style: {
6319
+ marginRight: 8,
6320
+ color: connection.connected ? "#52c41a" : connection.connecting ? "#1890ff" : "#d9d9d9"
6321
+ }
6322
+ }
6323
+ ),
6324
+ /* @__PURE__ */ jsx37("span", { children: connection.name }),
6325
+ connection.connected && /* @__PURE__ */ jsx37(
6326
+ CheckCircleFilled,
6327
+ {
6328
+ style: { color: "#52c41a", fontSize: 12, marginLeft: 8 }
6329
+ }
6330
+ ),
6331
+ connection.error && !connection.connecting && /* @__PURE__ */ jsx37(
6332
+ CloseCircleFilled,
6333
+ {
6334
+ style: { color: "#ff4d4f", fontSize: 12, marginLeft: 8 }
6335
+ }
6336
+ )
6337
+ ] });
6338
+ };
6339
+ const tabItems = connections.map((connection) => ({
6340
+ key: connection.id,
6341
+ label: renderTabLabel(connection),
6342
+ children: /* @__PURE__ */ jsx37("div", { className: styles.tabContent, children: connection.connected ? /* @__PURE__ */ jsx37(Fragment5, { children: /* @__PURE__ */ jsxs19("div", { style: { display: "flex", height: "100%" }, children: [
6343
+ /* @__PURE__ */ jsx37("div", { className: styles.sidebar, children: SETTINGS_MENU_ITEMS.map((item) => /* @__PURE__ */ jsxs19(
6344
+ "div",
6345
+ {
6346
+ className: `${styles.menuItem} ${activeMenu === item.key ? "active" : ""}`,
6347
+ onClick: () => setActiveMenu(item.key),
6348
+ children: [
6349
+ /* @__PURE__ */ jsx37("span", { className: styles.menuItemIcon, children: item.icon }),
6350
+ /* @__PURE__ */ jsx37("span", { className: styles.menuItemText, children: item.label })
6351
+ ]
6352
+ },
6353
+ item.key
6354
+ )) }),
6355
+ /* @__PURE__ */ jsxs19("div", { className: styles.content, children: [
6356
+ /* @__PURE__ */ jsxs19("div", { className: styles.contentHeader, children: [
6357
+ /* @__PURE__ */ jsxs19("div", { className: styles.contentHeaderLeft, children: [
6358
+ /* @__PURE__ */ jsx37(Title2, { level: 3, className: styles.contentTitle, children: activeMenuItem?.label }),
6359
+ /* @__PURE__ */ jsxs19(Text11, { className: styles.contentDescription, children: [
6360
+ activeMenu === "environment" && "Manage environment variables for the gateway server",
6361
+ activeMenu === "models" && "Configure and register model lattices for use by agents"
6362
+ ] })
6363
+ ] }),
6364
+ /* @__PURE__ */ jsxs19("div", { className: styles.contentHeaderRight, children: [
6365
+ /* @__PURE__ */ jsx37(Button12, { onClick: onClose, children: "Cancel" }),
6366
+ /* @__PURE__ */ jsx37(
6367
+ Button12,
6368
+ {
6369
+ type: "primary",
6370
+ icon: /* @__PURE__ */ jsx37(SaveOutlined, {}),
6371
+ onClick: handleSave,
6372
+ loading,
6373
+ children: "Save Configuration"
6374
+ }
6375
+ )
6376
+ ] })
6377
+ ] }),
6378
+ /* @__PURE__ */ jsx37("div", { className: styles.contentBody, children: renderContent(connection.id) })
6379
+ ] })
6380
+ ] }) }) : /* @__PURE__ */ jsx37(
6381
+ "div",
6382
+ {
6383
+ style: {
6384
+ flex: 1,
6385
+ display: "flex",
6386
+ alignItems: "center",
6387
+ justifyContent: "center",
6388
+ flexDirection: "column",
6389
+ gap: 16,
6390
+ padding: 48
6391
+ },
6392
+ children: connection.connecting ? /* @__PURE__ */ jsxs19(Fragment5, { children: [
6393
+ /* @__PURE__ */ jsx37(LinkOutlined, { style: { fontSize: 64, color: "#1890ff" }, spin: true }),
6394
+ /* @__PURE__ */ jsx37(Title2, { level: 4, children: "Connecting..." }),
6395
+ /* @__PURE__ */ jsxs19(Text11, { type: "secondary", style: { textAlign: "center" }, children: [
6396
+ "Connecting to ",
6397
+ connection.url
6398
+ ] })
6399
+ ] }) : /* @__PURE__ */ jsxs19(Fragment5, { children: [
6400
+ /* @__PURE__ */ jsx37(LinkOutlined, { style: { fontSize: 64, color: "#d9d9d9" } }),
6401
+ /* @__PURE__ */ jsx37(Title2, { level: 4, type: "secondary", children: connection.error || "Not Connected" }),
6402
+ /* @__PURE__ */ jsx37(
6403
+ Text11,
6404
+ {
6405
+ type: "secondary",
6406
+ style: { textAlign: "center", maxWidth: 400 },
6407
+ children: connection.error ? `Failed to connect to ${connection.url}. Please check the server URL and try again.` : `Click "Reconnect" to connect to ${connection.url}`
6408
+ }
6409
+ ),
6410
+ /* @__PURE__ */ jsx37(
6411
+ Button12,
6412
+ {
6413
+ type: "primary",
6414
+ icon: /* @__PURE__ */ jsx37(LinkOutlined, {}),
6415
+ onClick: () => checkConnection(connection.id),
6416
+ loading: connection.connecting,
6417
+ style: { marginTop: 16 },
6418
+ children: "Reconnect"
6419
+ }
6420
+ )
6421
+ ] })
6422
+ }
6423
+ ) }),
6424
+ closable: connections.length > 1
6425
+ }));
6426
+ return /* @__PURE__ */ jsxs19(Fragment5, { children: [
6427
+ /* @__PURE__ */ jsx37(
6428
+ Drawer,
6429
+ {
6430
+ open,
6431
+ onClose,
6432
+ footer: null,
6433
+ width: "100%",
6434
+ title: "Settings",
6435
+ children: /* @__PURE__ */ jsx37("div", { children: /* @__PURE__ */ jsx37(
6436
+ Tabs2,
6437
+ {
6438
+ activeKey: activeTabKey,
6439
+ onChange: setActiveTabKey,
6440
+ type: "editable-card",
6441
+ onEdit: (targetKey, action) => {
6442
+ if (action === "add") {
6443
+ setShowAddServerModal(true);
6444
+ } else if (action === "remove") {
6445
+ handleDeleteServer(targetKey);
6446
+ }
6447
+ },
6448
+ items: tabItems,
6449
+ addIcon: /* @__PURE__ */ jsxs19(
6450
+ "div",
6451
+ {
6452
+ style: {
6453
+ display: "flex",
6454
+ alignItems: "center",
6455
+ gap: 4,
6456
+ padding: "4px 8px"
6457
+ },
6458
+ children: [
6459
+ /* @__PURE__ */ jsx37(PlusOutlined, {}),
6460
+ /* @__PURE__ */ jsx37("span", { children: "Add Server" })
6461
+ ]
6462
+ }
6463
+ )
6464
+ }
6465
+ ) })
6466
+ }
6467
+ ),
6468
+ /* @__PURE__ */ jsx37(
6469
+ Modal,
6470
+ {
6471
+ title: "Add New Server",
6472
+ open: showAddServerModal,
6473
+ onOk: handleAddServer,
6474
+ onCancel: () => {
6475
+ setShowAddServerModal(false);
6476
+ setNewServerUrl("");
6477
+ setNewServerName("");
6478
+ setNewServerApiKey("");
6479
+ },
6480
+ confirmLoading: addingServer,
6481
+ className: styles.addServerModal,
6482
+ children: /* @__PURE__ */ jsxs19(Space13, { direction: "vertical", style: { width: "100%" }, size: "large", children: [
6483
+ /* @__PURE__ */ jsxs19("div", { children: [
6484
+ /* @__PURE__ */ jsx37(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "Server Name" }),
6485
+ /* @__PURE__ */ jsx37(
6486
+ Input,
6487
+ {
6488
+ placeholder: "e.g., Production Server",
6489
+ value: newServerName,
6490
+ onChange: (e) => setNewServerName(e.target.value),
6491
+ onPressEnter: handleAddServer
6492
+ }
6493
+ ),
6494
+ /* @__PURE__ */ jsx37(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Optional: Leave empty to use URL as name" })
6495
+ ] }),
6496
+ /* @__PURE__ */ jsxs19("div", { children: [
6497
+ /* @__PURE__ */ jsx37(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "Server URL *" }),
6498
+ /* @__PURE__ */ jsx37(
6499
+ Input,
6500
+ {
6501
+ placeholder: "e.g., http://localhost:4001",
6502
+ value: newServerUrl,
6503
+ onChange: (e) => setNewServerUrl(e.target.value),
6504
+ onPressEnter: handleAddServer
6505
+ }
6506
+ ),
6507
+ /* @__PURE__ */ jsx37(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Enter the full URL of the gateway server" })
6508
+ ] }),
6509
+ /* @__PURE__ */ jsxs19("div", { children: [
6510
+ /* @__PURE__ */ jsx37(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "API Key" }),
6511
+ /* @__PURE__ */ jsx37(
6512
+ Input.Password,
6513
+ {
6514
+ placeholder: "Optional: Enter API key for authentication",
6515
+ value: newServerApiKey,
6516
+ onChange: (e) => setNewServerApiKey(e.target.value),
6517
+ onPressEnter: handleAddServer
6518
+ }
6519
+ ),
6520
+ /* @__PURE__ */ jsx37(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Optional: API key for server authentication" })
6521
+ ] })
6522
+ ] })
6523
+ }
6524
+ )
6525
+ ] });
6526
+ };
6527
+
6528
+ // src/components/Chat/ChatSidebar.tsx
6529
+ import { Fragment as Fragment6, jsx as jsx38, jsxs as jsxs20 } from "react/jsx-runtime";
6530
+ var useStyles4 = createStyles11(({ token, css }) => ({
6531
+ sidebar: css`
6532
+ display: flex;
6533
+ flex-direction: column;
6534
+ height: 100%;
6535
+ width: 100%;
6536
+ position: relative;
6537
+ background: transparent;
6538
+ border-radius: ${token.borderRadiusLG}px;
6539
+ overflow: hidden;
6540
+ `,
6541
+ content: css`
6542
+ flex: 1;
6543
+ overflow-y: auto;
6544
+ overflow-x: hidden;
6545
+ padding: ${token.paddingMD}px ${token.paddingSM}px;
6546
+ padding-bottom: ${token.paddingLG}px;
6547
+
6548
+ /* Custom scrollbar styling */
6549
+ &::-webkit-scrollbar {
6550
+ width: 6px;
6551
+ }
6552
+
6553
+ &::-webkit-scrollbar-track {
6554
+ background: transparent;
6555
+ }
6556
+
6557
+ &::-webkit-scrollbar-thumb {
6558
+ background: ${token.colorBorder};
6559
+ border-radius: 3px;
6560
+
6561
+ &:hover {
6562
+ background: ${token.colorBorderSecondary};
6563
+ }
6564
+ }
6565
+ `,
6566
+ section: css`
6567
+ margin-bottom: ${token.marginLG}px;
6568
+
6569
+ &:last-child {
6570
+ margin-bottom: 0;
6571
+ }
6572
+ `,
6573
+ sectionTitle: css`
6574
+ font-size: ${token.fontSizeSM}px;
6575
+ font-weight: 600;
6576
+ color: ${token.colorTextSecondary};
6577
+ text-transform: uppercase;
6578
+ letter-spacing: 0.5px;
6579
+ padding: 0 ${token.paddingXS}px;
6580
+ margin-bottom: ${token.marginSM}px;
6581
+ `,
6582
+ footer: css`
6583
+ display: flex;
6584
+ justify-content: center;
6585
+ align-items: center;
6586
+ padding: ${token.paddingSM}px;
6587
+ background: transparent;
6588
+ border-top: 1px solid ${token.colorBorderSecondary};
6589
+ gap: ${token.marginXS}px;
6590
+ flex-shrink: 0;
6591
+ position: relative;
6592
+
6593
+ &::before {
6594
+ content: "";
6595
+ position: absolute;
6596
+ top: 0;
6597
+ left: 0;
6598
+ right: 0;
6599
+ height: 1px;
6600
+ background: linear-gradient(
6601
+ 90deg,
6602
+ transparent,
6603
+ ${token.colorBorder},
6604
+ transparent
6605
+ );
6606
+ }
6607
+ `,
6608
+ actionButton: css`
6609
+ display: flex;
6610
+ align-items: center;
6611
+ justify-content: center;
6612
+ width: 36px;
6613
+ height: 36px;
6614
+ border-radius: ${token.borderRadius}px;
6615
+ border: none;
6616
+ background: ${token.colorBgContainer};
6617
+ color: ${token.colorTextSecondary};
6618
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
6619
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
6620
+
6621
+ &:hover {
6622
+ background: ${token.colorPrimaryBg};
6623
+ color: ${token.colorPrimary};
6624
+ transform: translateY(-1px);
6625
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.08);
6626
+ }
6627
+
6628
+ &:active {
6629
+ transform: translateY(0);
6630
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
6631
+ }
6632
+
6633
+ .anticon {
6634
+ font-size: 16px;
6635
+ }
6636
+ `,
6637
+ divider: css`
6638
+ margin: ${token.marginMD}px 0;
6639
+ border-color: ${token.colorBorderSecondary};
6640
+ `
6641
+ }));
6642
+ var ChatSidebar = ({
6643
+ onSettingsClick,
6644
+ defaultCollapsed = false
6645
+ }) => {
6646
+ const { styles } = useStyles4();
6647
+ const { setMenuCollapsed, menuCollapsed } = useChatUIContext();
6648
+ const [settingsModalOpen, setSettingsModalOpen] = useState21(false);
6649
+ const handleToggleCollapse = () => {
6650
+ setMenuCollapsed(!menuCollapsed);
6651
+ };
6652
+ const handleSettingsClick = () => {
6653
+ setSettingsModalOpen(true);
6654
+ onSettingsClick?.();
6655
+ };
6656
+ return /* @__PURE__ */ jsxs20(Fragment6, { children: [
6657
+ /* @__PURE__ */ jsxs20("div", { className: styles.sidebar, children: [
6658
+ !menuCollapsed && /* @__PURE__ */ jsxs20("div", { className: styles.content, children: [
6659
+ /* @__PURE__ */ jsxs20("div", { className: styles.section, children: [
6660
+ /* @__PURE__ */ jsx38("div", { className: styles.sectionTitle, children: "Assistants" }),
6661
+ /* @__PURE__ */ jsx38(AssistantList, {})
6662
+ ] }),
6663
+ /* @__PURE__ */ jsx38(Divider2, { className: styles.divider }),
6664
+ /* @__PURE__ */ jsxs20("div", { className: styles.section, children: [
6665
+ /* @__PURE__ */ jsx38("div", { className: styles.sectionTitle, children: "Threads" }),
6666
+ /* @__PURE__ */ jsx38(AgentConversations, {})
6667
+ ] })
6668
+ ] }),
6669
+ /* @__PURE__ */ jsxs20("div", { className: styles.footer, children: [
6670
+ /* @__PURE__ */ jsx38(
6671
+ "button",
6672
+ {
6673
+ className: styles.actionButton,
6674
+ onClick: handleToggleCollapse,
6675
+ title: menuCollapsed ? "Expand sidebar" : "Collapse sidebar",
6676
+ "aria-label": menuCollapsed ? "Expand sidebar" : "Collapse sidebar",
6677
+ children: menuCollapsed ? /* @__PURE__ */ jsx38(MenuUnfoldOutlined, {}) : /* @__PURE__ */ jsx38(MenuFoldOutlined, {})
6678
+ }
6679
+ ),
6680
+ !menuCollapsed && /* @__PURE__ */ jsx38(
6681
+ "button",
6682
+ {
6683
+ className: styles.actionButton,
6684
+ onClick: handleSettingsClick,
6685
+ title: "Settings",
6686
+ "aria-label": "Settings",
6687
+ children: /* @__PURE__ */ jsx38(SettingOutlined, {})
6688
+ }
6689
+ )
6690
+ ] })
6691
+ ] }),
6692
+ /* @__PURE__ */ jsx38(
6693
+ SettingsModal,
6694
+ {
6695
+ open: settingsModalOpen,
6696
+ onClose: () => setSettingsModalOpen(false)
6697
+ }
6698
+ )
6699
+ ] });
6700
+ };
6701
+
6702
+ // src/components/Chat/LatticeChatView.tsx
6703
+ import { jsx as jsx39 } from "react/jsx-runtime";
6704
+ var LatticeChatView = (props) => {
6705
+ const { assistantId, thread } = useConversationContext();
6706
+ const { currentAssistant } = useAssistantContext();
6707
+ const {
6708
+ config: { baseURL }
6709
+ } = useLatticeChatShellContext();
6710
+ return assistantId && thread ? /* @__PURE__ */ jsx39(
6711
+ AxiomLatticeProvider,
6712
+ {
6713
+ config: {
6714
+ baseURL,
6715
+ apiKey: "",
6716
+ assistantId,
6717
+ transport: "sse"
6718
+ },
6719
+ children: /* @__PURE__ */ jsx39(
6720
+ LatticeChat,
6721
+ {
6722
+ thread_id: thread?.id,
6723
+ assistant_id: assistantId,
6724
+ name: currentAssistant?.name,
6725
+ description: currentAssistant?.description,
6726
+ menu: /* @__PURE__ */ jsx39(ChatSidebar, {})
6727
+ }
6728
+ )
6729
+ }
6730
+ ) : null;
6731
+ };
6732
+
6733
+ // src/components/Chat/LatticeChatShell.tsx
6734
+ import { jsx as jsx40 } from "react/jsx-runtime";
6735
+ var LatticeChatShell = (props) => {
6736
+ return /* @__PURE__ */ jsx40(LatticeChatShellContextProvider, { ...props, children: /* @__PURE__ */ jsx40(AssistantContextProvider, { autoLoad: true, children: /* @__PURE__ */ jsx40(ConversationContextProvider, { children: /* @__PURE__ */ jsx40(LatticeChatView, {}) }) }) });
6737
+ };
4436
6738
  export {
6739
+ AgentConversations,
4437
6740
  AgentThreadProvider,
6741
+ AssistantContext,
6742
+ AssistantContextProvider,
4438
6743
  AxiomLatticeProvider,
4439
6744
  ChatUIContext,
4440
6745
  ChatUIContextProvider,
4441
6746
  Chating,
4442
6747
  ColumnLayout,
6748
+ ConversationContext,
6749
+ ConversationContextProvider,
4443
6750
  FileExplorer,
4444
6751
  LatticeChat,
6752
+ LatticeChatShell,
6753
+ LatticeChatShellContext,
6754
+ LatticeChatShellContextProvider,
4445
6755
  MDMermaid,
4446
6756
  MDResponse,
4447
6757
  MDViewFormItem,
@@ -4452,9 +6762,11 @@ export {
4452
6762
  useAgentGraph,
4453
6763
  useAgentState,
4454
6764
  useAgentThreadContext,
6765
+ useAssistantContext,
4455
6766
  useAxiomLattice,
4456
6767
  useChat,
4457
6768
  useChatUIContext,
4458
- useThread
6769
+ useConversationContext,
6770
+ useLatticeChatShellContext
4459
6771
  };
4460
6772
  //# sourceMappingURL=index.mjs.map