@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.js CHANGED
@@ -31,14 +31,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ AgentConversations: () => AgentConversations,
34
35
  AgentThreadProvider: () => AgentThreadProvider,
36
+ AssistantContext: () => AssistantContext,
37
+ AssistantContextProvider: () => AssistantContextProvider,
35
38
  AxiomLatticeProvider: () => AxiomLatticeProvider,
36
39
  ChatUIContext: () => ChatUIContext,
37
40
  ChatUIContextProvider: () => ChatUIContextProvider,
38
41
  Chating: () => Chating,
39
42
  ColumnLayout: () => ColumnLayout,
43
+ ConversationContext: () => ConversationContext,
44
+ ConversationContextProvider: () => ConversationContextProvider,
40
45
  FileExplorer: () => FileExplorer,
41
46
  LatticeChat: () => LatticeChat,
47
+ LatticeChatShell: () => LatticeChatShell,
48
+ LatticeChatShellContext: () => LatticeChatShellContext,
49
+ LatticeChatShellContextProvider: () => LatticeChatShellContextProvider,
42
50
  MDMermaid: () => MDMermaid,
43
51
  MDResponse: () => MDResponse,
44
52
  MDViewFormItem: () => MDViewFormItem,
@@ -49,10 +57,12 @@ __export(index_exports, {
49
57
  useAgentGraph: () => useAgentGraph,
50
58
  useAgentState: () => useAgentState,
51
59
  useAgentThreadContext: () => useAgentThreadContext,
60
+ useAssistantContext: () => useAssistantContext,
52
61
  useAxiomLattice: () => useAxiomLattice,
53
62
  useChat: () => useChat,
54
63
  useChatUIContext: () => useChatUIContext,
55
- useThread: () => useThread
64
+ useConversationContext: () => useConversationContext,
65
+ useLatticeChatShellContext: () => useLatticeChatShellContext
56
66
  });
57
67
  module.exports = __toCommonJS(index_exports);
58
68
 
@@ -111,7 +121,6 @@ function useChat(threadId, options = {}) {
111
121
  messages: options.initialMessages || [],
112
122
  isLoading: false,
113
123
  error: null,
114
- streamingMessage: null,
115
124
  interrupts: void 0,
116
125
  ...options.enableReturnStateWhenStreamCompleted ? { agentState: null } : {}
117
126
  });
@@ -189,7 +198,7 @@ function useChat(threadId, options = {}) {
189
198
  stopStreamingRef.current = null;
190
199
  }
191
200
  const { input, command, streaming = true } = data;
192
- const { message: message4, files, ...rest } = input || {};
201
+ const { message: message5, files, ...rest } = input || {};
193
202
  setState((prev) => ({
194
203
  ...prev,
195
204
  isLoading: true,
@@ -198,7 +207,7 @@ function useChat(threadId, options = {}) {
198
207
  }));
199
208
  const userMessage = {
200
209
  id: Date.now().toString(),
201
- content: message4 || command?.resume?.message || "",
210
+ content: message5 || command?.resume?.message || "",
202
211
  files,
203
212
  role: "human"
204
213
  };
@@ -435,10 +444,17 @@ function AgentThreadProvider({
435
444
  messages: options.initialMessages || [],
436
445
  isLoading: false,
437
446
  error: null,
438
- streamingMessage: null,
439
447
  interrupts: void 0,
440
448
  agentState: null
441
449
  });
450
+ (0, import_react3.useEffect)(() => {
451
+ setState((prev) => ({
452
+ ...prev,
453
+ assistantId: clientAssistantId,
454
+ tenantId,
455
+ threadId
456
+ }));
457
+ }, [clientAssistantId, tenantId, threadId]);
442
458
  const stopStreamingRef = (0, import_react3.useRef)(null);
443
459
  const chunkMessageMerger = (0, import_react3.useRef)((0, import_client_sdk3.createSimpleMessageMerger)());
444
460
  const lastAgentStateCreatedAtRef = (0, import_react3.useRef)(null);
@@ -505,8 +521,7 @@ function AgentThreadProvider({
505
521
  ...prev,
506
522
  todos: todos || prev.todos,
507
523
  messages: updatedMessages,
508
- isLoading: true,
509
- streamingMessage: null
524
+ isLoading: true
510
525
  }));
511
526
  },
512
527
  []
@@ -521,16 +536,15 @@ function AgentThreadProvider({
521
536
  stopStreamingRef.current = null;
522
537
  }
523
538
  const { input, command, streaming = true } = data;
524
- const { message: message4, files, ...rest } = input || {};
539
+ const { message: message5, files, ...rest } = input || {};
525
540
  setState((prev) => ({
526
541
  ...prev,
527
542
  isLoading: true,
528
- error: null,
529
- streamingMessage: null
543
+ error: null
530
544
  }));
531
545
  const userMessage = {
532
546
  id: Date.now().toString(),
533
- content: message4 || command?.resume?.message || "",
547
+ content: message5 || command?.resume?.message || "",
534
548
  files,
535
549
  role: "human"
536
550
  };
@@ -569,8 +583,7 @@ function AgentThreadProvider({
569
583
  setState((prev) => ({
570
584
  ...prev,
571
585
  isLoading: false,
572
- error,
573
- streamingMessage: null
586
+ error
574
587
  }));
575
588
  stopStreamingRef.current = null;
576
589
  }
@@ -620,111 +633,148 @@ function AgentThreadProvider({
620
633
  setState((prev) => ({
621
634
  ...prev,
622
635
  messages: currentMessages,
623
- isLoading: false,
624
- streamingMessage: null
636
+ isLoading: false
625
637
  }));
626
638
  }
627
639
  }, []);
628
- const loadMessages = (0, import_react3.useCallback)(
629
- async (limit) => {
640
+ const resumeStream = (0, import_react3.useCallback)(
641
+ (messageId) => {
630
642
  if (!threadId) {
631
- return;
643
+ throw new Error("Thread ID is required to resume stream");
644
+ }
645
+ let targetMessageId;
646
+ if (messageId) {
647
+ targetMessageId = messageId;
648
+ } else {
649
+ const messages = chunkMessageMerger.current.getMessages();
650
+ const lastMessage = messages[messages.length - 1];
651
+ if (!lastMessage) {
652
+ throw new Error(
653
+ "No message ID provided and no messages found in context"
654
+ );
655
+ }
656
+ targetMessageId = lastMessage.id;
632
657
  }
633
658
  if (stopStreamingRef.current) {
634
659
  stopStreamingRef.current();
635
660
  stopStreamingRef.current = null;
636
661
  }
637
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
638
- try {
639
- const agentState = await client.getAgentState(threadId);
640
- const currentCreatedAt = agentState?.createdAt;
641
- const needsUpdate = !lastAgentStateCreatedAtRef.current || currentCreatedAt !== lastAgentStateCreatedAtRef.current;
642
- if (currentCreatedAt) {
643
- lastAgentStateCreatedAtRef.current = currentCreatedAt;
644
- }
645
- let needUpdateFields = {};
646
- let fetchedMessages = [];
647
- needUpdateFields.agentState = agentState;
648
- needUpdateFields.todos = agentState?.values?.todos;
649
- const interrupts = agentState?.tasks?.flatMap(
650
- (task) => {
651
- return task.interrupts.map((interrupt) => {
652
- return {
653
- id: interrupt.id,
654
- value: interrupt.value,
655
- role: "ai",
656
- type: "interrupt"
657
- };
658
- });
662
+ setState((prev) => ({
663
+ ...prev,
664
+ isLoading: true,
665
+ error: null
666
+ }));
667
+ const resumeStreamOptions = {
668
+ threadId,
669
+ messageId: targetMessageId,
670
+ knownContent: "",
671
+ pollInterval: options.resumeStreamPollInterval || 100
672
+ };
673
+ const stopResumeStream = client.resumeStream(
674
+ resumeStreamOptions,
675
+ handleStreamEvent,
676
+ async () => {
677
+ setState((prev) => ({
678
+ ...prev,
679
+ isLoading: false
680
+ }));
681
+ if (options.enableReturnStateWhenStreamCompleted) {
682
+ await fetchAndUpdateAgentState(threadId);
659
683
  }
660
- );
661
- needUpdateFields.interrupts = interrupts;
662
- fetchedMessages = await client.getMessages({ threadId });
663
- needUpdateFields.messages = fetchedMessages;
664
- chunkMessageMerger.current.reset();
665
- chunkMessageMerger.current.initialMessages(fetchedMessages);
666
- setState((prev) => ({
667
- ...prev,
668
- ...needUpdateFields,
669
- isLoading: false
670
- }));
671
- if (options.enableResumeStream && fetchedMessages.length > 0) {
672
- const lastMessage = fetchedMessages[fetchedMessages.length - 1];
673
- chunkMessageMerger.current.removeMessageById(lastMessage.id);
674
- const stopResumeStream = client.resumeStream(
675
- {
676
- threadId,
677
- messageId: lastMessage.id,
678
- knownContent: "",
679
- pollInterval: options.resumeStreamPollInterval || 100
680
- },
681
- handleStreamEvent,
682
- async () => {
683
- setState((prev) => ({
684
- ...prev,
685
- isLoading: false
686
- }));
687
- if (options.enableReturnStateWhenStreamCompleted) {
688
- await fetchAndUpdateAgentState(threadId);
689
- }
690
- stopStreamingRef.current = null;
691
- },
692
- (error) => {
693
- console.error("Resume stream error:", error);
694
- setState((prev) => ({
695
- ...prev,
696
- error
697
- }));
698
- stopStreamingRef.current = null;
699
- }
700
- );
701
- stopStreamingRef.current = stopResumeStream;
684
+ stopStreamingRef.current = null;
685
+ },
686
+ (error) => {
687
+ console.error("Resume stream error:", error);
688
+ setState((prev) => ({
689
+ ...prev,
690
+ isLoading: false,
691
+ error
692
+ }));
693
+ stopStreamingRef.current = null;
702
694
  }
703
- } catch (error) {
704
- setState((prev) => ({
705
- ...prev,
706
- isLoading: false,
707
- error: error instanceof Error ? error : new Error(String(error))
708
- }));
709
- }
695
+ );
696
+ stopStreamingRef.current = stopResumeStream;
697
+ return stopResumeStream;
710
698
  },
711
699
  [
712
700
  client,
713
701
  threadId,
714
- options.enableResumeStream,
715
702
  options.resumeStreamPollInterval,
703
+ options.enableReturnStateWhenStreamCompleted,
716
704
  handleStreamEvent,
717
705
  fetchAndUpdateAgentState
718
706
  ]
719
707
  );
708
+ const loadMessages = (0, import_react3.useCallback)(async () => {
709
+ if (!threadId) {
710
+ return;
711
+ }
712
+ if (stopStreamingRef.current) {
713
+ stopStreamingRef.current();
714
+ stopStreamingRef.current = null;
715
+ }
716
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
717
+ try {
718
+ const agentState = await client.getAgentState(threadId);
719
+ const currentCreatedAt = agentState?.createdAt;
720
+ const needsUpdate = !lastAgentStateCreatedAtRef.current || currentCreatedAt !== lastAgentStateCreatedAtRef.current;
721
+ if (currentCreatedAt) {
722
+ lastAgentStateCreatedAtRef.current = currentCreatedAt;
723
+ }
724
+ let needUpdateFields = {};
725
+ let fetchedMessages = [];
726
+ needUpdateFields.agentState = agentState;
727
+ needUpdateFields.todos = agentState?.values?.todos;
728
+ const interrupts = agentState?.tasks?.flatMap(
729
+ (task) => {
730
+ return task.interrupts.map((interrupt) => {
731
+ return {
732
+ id: interrupt.id,
733
+ value: interrupt.value,
734
+ role: "ai",
735
+ type: "interrupt"
736
+ };
737
+ });
738
+ }
739
+ );
740
+ needUpdateFields.interrupts = interrupts;
741
+ fetchedMessages = await client.getMessages({ threadId });
742
+ needUpdateFields.messages = fetchedMessages;
743
+ chunkMessageMerger.current.reset();
744
+ chunkMessageMerger.current.initialMessages(fetchedMessages);
745
+ setState((prev) => ({
746
+ ...prev,
747
+ ...needUpdateFields,
748
+ isLoading: false
749
+ }));
750
+ if (options.enableResumeStream && fetchedMessages.length > 0) {
751
+ const lastMessage = fetchedMessages[fetchedMessages.length - 1];
752
+ chunkMessageMerger.current.removeMessageById(lastMessage.id);
753
+ resumeStream(lastMessage.id);
754
+ }
755
+ } catch (error) {
756
+ setState((prev) => ({
757
+ ...prev,
758
+ isLoading: false,
759
+ error: error instanceof Error ? error : new Error(String(error))
760
+ }));
761
+ }
762
+ }, [
763
+ client,
764
+ threadId,
765
+ options.enableResumeStream,
766
+ options.resumeStreamPollInterval,
767
+ handleStreamEvent,
768
+ fetchAndUpdateAgentState,
769
+ resumeStream
770
+ ]);
720
771
  const clearMessages = (0, import_react3.useCallback)(() => {
721
772
  chunkMessageMerger.current.reset();
722
773
  lastAgentStateCreatedAtRef.current = null;
723
774
  setState((prev) => ({
724
775
  ...prev,
725
776
  messages: [],
726
- interrupts: void 0,
727
- streamingMessage: null
777
+ interrupts: void 0
728
778
  }));
729
779
  }, []);
730
780
  const clearError = (0, import_react3.useCallback)(() => {
@@ -751,6 +801,7 @@ function AgentThreadProvider({
751
801
  state,
752
802
  sendMessage,
753
803
  stopStreaming,
804
+ resumeStream,
754
805
  loadMessages,
755
806
  clearMessages,
756
807
  clearError
@@ -774,155 +825,28 @@ function useAgentChat(options) {
774
825
  ...context.state,
775
826
  sendMessage: context.sendMessage,
776
827
  stopStreaming: context.stopStreaming,
828
+ resumeStream: context.resumeStream,
777
829
  loadMessages: context.loadMessages,
778
830
  clearMessages: context.clearMessages,
779
831
  clearError: context.clearError
780
832
  };
781
833
  }
782
834
 
783
- // src/hooks/useThread.ts
784
- var import_react4 = require("react");
785
- function useThread() {
786
- const client = useAxiomLattice();
787
- const [state, setState] = (0, import_react4.useState)({
788
- threads: [],
789
- currentThread: null,
790
- isLoading: false,
791
- error: null
792
- });
793
- const createThread = (0, import_react4.useCallback)(
794
- async (options = {}) => {
795
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
796
- try {
797
- const threadId = await client.createThread(options);
798
- const thread = await client.getThread(threadId);
799
- setState((prev) => ({
800
- ...prev,
801
- threads: [...prev.threads, thread],
802
- currentThread: thread,
803
- isLoading: false
804
- }));
805
- return threadId;
806
- } catch (error) {
807
- setState((prev) => ({
808
- ...prev,
809
- isLoading: false,
810
- error: error instanceof Error ? error : new Error(String(error))
811
- }));
812
- throw error;
813
- }
814
- },
815
- [client]
816
- );
817
- const getThread = (0, import_react4.useCallback)(
818
- async (threadId) => {
819
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
820
- try {
821
- const thread = await client.getThread(threadId);
822
- setState((prev) => ({
823
- ...prev,
824
- isLoading: false
825
- }));
826
- return thread;
827
- } catch (error) {
828
- setState((prev) => ({
829
- ...prev,
830
- isLoading: false,
831
- error: error instanceof Error ? error : new Error(String(error))
832
- }));
833
- throw error;
834
- }
835
- },
836
- [client]
837
- );
838
- const listThreads = (0, import_react4.useCallback)(
839
- async (limit, offset) => {
840
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
841
- try {
842
- const threads = await client.listThreads({ limit, offset });
843
- setState((prev) => ({
844
- ...prev,
845
- threads,
846
- isLoading: false
847
- }));
848
- } catch (error) {
849
- setState((prev) => ({
850
- ...prev,
851
- isLoading: false,
852
- error: error instanceof Error ? error : new Error(String(error))
853
- }));
854
- }
855
- },
856
- [client]
857
- );
858
- const deleteThread = (0, import_react4.useCallback)(
859
- async (threadId) => {
860
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
861
- try {
862
- await client.deleteThread(threadId);
863
- setState((prev) => ({
864
- ...prev,
865
- threads: prev.threads.filter((t) => t.id !== threadId),
866
- currentThread: prev.currentThread?.id === threadId ? null : prev.currentThread,
867
- isLoading: false
868
- }));
869
- } catch (error) {
870
- setState((prev) => ({
871
- ...prev,
872
- isLoading: false,
873
- error: error instanceof Error ? error : new Error(String(error))
874
- }));
875
- throw error;
876
- }
877
- },
878
- [client]
879
- );
880
- const selectThread = (0, import_react4.useCallback)(
881
- async (threadId) => {
882
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
883
- try {
884
- const thread = await client.getThread(threadId);
885
- setState((prev) => ({
886
- ...prev,
887
- currentThread: thread,
888
- isLoading: false
889
- }));
890
- } catch (error) {
891
- setState((prev) => ({
892
- ...prev,
893
- isLoading: false,
894
- error: error instanceof Error ? error : new Error(String(error))
895
- }));
896
- throw error;
897
- }
898
- },
899
- [client]
900
- );
901
- return {
902
- ...state,
903
- createThread,
904
- getThread,
905
- listThreads,
906
- deleteThread,
907
- selectThread
908
- };
909
- }
910
-
911
835
  // src/hooks/useAgentState.ts
912
- var import_react5 = require("react");
836
+ var import_react4 = require("react");
913
837
  function useAgentState(threadId, options = {}) {
914
838
  const client = useAxiomLattice();
915
- const [agentState, setAgentState] = (0, import_react5.useState)(null);
916
- const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
917
- const [error, setError] = (0, import_react5.useState)(null);
918
- const pollingIntervalRef = (0, import_react5.useRef)(null);
919
- const pollingTimeoutRef = (0, import_react5.useRef)(null);
839
+ const [agentState, setAgentState] = (0, import_react4.useState)(null);
840
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
841
+ const [error, setError] = (0, import_react4.useState)(null);
842
+ const pollingIntervalRef = (0, import_react4.useRef)(null);
843
+ const pollingTimeoutRef = (0, import_react4.useRef)(null);
920
844
  const {
921
845
  pollingInterval = 2e3,
922
846
  // 2 seconds by default
923
847
  autoStart = true
924
848
  } = options;
925
- const fetchAgentState = (0, import_react5.useCallback)(async () => {
849
+ const fetchAgentState = (0, import_react4.useCallback)(async () => {
926
850
  if (!threadId) {
927
851
  return;
928
852
  }
@@ -937,7 +861,7 @@ function useAgentState(threadId, options = {}) {
937
861
  setIsLoading(false);
938
862
  }
939
863
  }, [client, threadId]);
940
- const startPolling = (0, import_react5.useCallback)(() => {
864
+ const startPolling = (0, import_react4.useCallback)(() => {
941
865
  if (!threadId) {
942
866
  return;
943
867
  }
@@ -958,17 +882,17 @@ function useAgentState(threadId, options = {}) {
958
882
  };
959
883
  poll();
960
884
  }, [threadId, pollingInterval, fetchAgentState]);
961
- const stopPolling = (0, import_react5.useCallback)(() => {
885
+ const stopPolling = (0, import_react4.useCallback)(() => {
962
886
  pollingIntervalRef.current = null;
963
887
  if (pollingTimeoutRef.current) {
964
888
  clearTimeout(pollingTimeoutRef.current);
965
889
  pollingTimeoutRef.current = null;
966
890
  }
967
891
  }, []);
968
- const refresh = (0, import_react5.useCallback)(async () => {
892
+ const refresh = (0, import_react4.useCallback)(async () => {
969
893
  await fetchAgentState();
970
894
  }, [fetchAgentState]);
971
- (0, import_react5.useEffect)(() => {
895
+ (0, import_react4.useEffect)(() => {
972
896
  if (threadId && autoStart) {
973
897
  startPolling();
974
898
  } else {
@@ -989,13 +913,13 @@ function useAgentState(threadId, options = {}) {
989
913
  }
990
914
 
991
915
  // src/hooks/useAgentGraph.ts
992
- var import_react6 = require("react");
916
+ var import_react5 = require("react");
993
917
  function useAgentGraph() {
994
918
  const client = useAxiomLattice();
995
- const [graphImage, setGraphImage] = (0, import_react6.useState)(null);
996
- const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
997
- const [error, setError] = (0, import_react6.useState)(null);
998
- const fetchGraph = (0, import_react6.useCallback)(async () => {
919
+ const [graphImage, setGraphImage] = (0, import_react5.useState)(null);
920
+ const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
921
+ const [error, setError] = (0, import_react5.useState)(null);
922
+ const fetchGraph = (0, import_react5.useCallback)(async () => {
999
923
  setIsLoading(true);
1000
924
  setError(null);
1001
925
  try {
@@ -1019,9 +943,9 @@ function useAgentGraph() {
1019
943
  __reExport(index_exports, require("@axiom-lattice/protocols"), module.exports);
1020
944
 
1021
945
  // src/components/Chat/ChatUIContext.tsx
1022
- var import_react7 = require("react");
946
+ var import_react6 = require("react");
1023
947
  var import_jsx_runtime3 = require("react/jsx-runtime");
1024
- var ChatUIContext = (0, import_react7.createContext)({
948
+ var ChatUIContext = (0, import_react6.createContext)({
1025
949
  sideAppVisible: false,
1026
950
  setSideAppVisible: () => {
1027
951
  },
@@ -1034,22 +958,26 @@ var ChatUIContext = (0, import_react7.createContext)({
1034
958
  openSideApp: () => {
1035
959
  },
1036
960
  closeSideApp: () => {
961
+ },
962
+ menuCollapsed: false,
963
+ setMenuCollapsed: () => {
1037
964
  }
1038
965
  });
1039
966
  var ChatUIContextProvider = ({
1040
967
  children
1041
968
  }) => {
1042
- const [sideAppVisible, setSideAppVisible] = (0, import_react7.useState)(false);
1043
- const [sideAppSize, setSideAppSize] = (0, import_react7.useState)("large");
1044
- const [sideAppSelectedCard, setSideAppSelectedCard] = (0, import_react7.useState)(null);
1045
- const openSideApp = (0, import_react7.useCallback)(
969
+ const [sideAppVisible, setSideAppVisible] = (0, import_react6.useState)(false);
970
+ const [sideAppSize, setSideAppSize] = (0, import_react6.useState)("large");
971
+ const [sideAppSelectedCard, setSideAppSelectedCard] = (0, import_react6.useState)(null);
972
+ const [menuCollapsed, setMenuCollapsed] = (0, import_react6.useState)(false);
973
+ const openSideApp = (0, import_react6.useCallback)(
1046
974
  (card) => {
1047
975
  setSideAppSelectedCard(card);
1048
976
  setSideAppVisible(true);
1049
977
  },
1050
978
  [setSideAppSelectedCard, setSideAppVisible]
1051
979
  );
1052
- const closeSideApp = (0, import_react7.useCallback)(() => {
980
+ const closeSideApp = (0, import_react6.useCallback)(() => {
1053
981
  setSideAppSelectedCard(null);
1054
982
  setSideAppVisible(false);
1055
983
  }, [setSideAppSelectedCard, setSideAppVisible]);
@@ -1064,14 +992,16 @@ var ChatUIContextProvider = ({
1064
992
  sideAppSelectedCard,
1065
993
  setSideAppSelectedCard,
1066
994
  openSideApp,
1067
- closeSideApp
995
+ closeSideApp,
996
+ menuCollapsed,
997
+ setMenuCollapsed
1068
998
  },
1069
999
  children
1070
1000
  }
1071
1001
  );
1072
1002
  };
1073
1003
  var useChatUIContext = () => {
1074
- return (0, import_react7.useContext)(ChatUIContext);
1004
+ return (0, import_react6.useContext)(ChatUIContext);
1075
1005
  };
1076
1006
 
1077
1007
  // src/components/Chat/useStyle.tsx
@@ -1089,7 +1019,6 @@ var useStyle = (0, import_antd_style.createStyles)(({ token, css }) => {
1089
1019
  position: relative;
1090
1020
  overflow: hidden;
1091
1021
  padding: 16px;
1092
- padding-top: 2px;
1093
1022
  gap: 16px;
1094
1023
 
1095
1024
  .ant-prompts {
@@ -1098,7 +1027,7 @@ var useStyle = (0, import_antd_style.createStyles)(({ token, css }) => {
1098
1027
  `,
1099
1028
  menu: css`
1100
1029
  background: ${token.colorBgContainer}90;
1101
- width: 280px;
1030
+ width: 240px;
1102
1031
  display: flex;
1103
1032
  flex-direction: column;
1104
1033
  flex-shrink: 0;
@@ -1216,6 +1145,17 @@ var useStyle = (0, import_antd_style.createStyles)(({ token, css }) => {
1216
1145
  min-width: 200px;
1217
1146
  max-width: 466px;
1218
1147
  }
1148
+ .ant-bubble-content-updating {
1149
+ background-image: linear-gradient(
1150
+ 90deg,
1151
+ #ff6b23 0%,
1152
+ #af3cb8 31%,
1153
+ #53b6ff 89%
1154
+ );
1155
+ background-size: 100% 2px;
1156
+ background-repeat: no-repeat;
1157
+ background-position: bottom;
1158
+ }
1219
1159
  `,
1220
1160
  detailPanel: css`
1221
1161
  display: flex;
@@ -1350,10 +1290,25 @@ var useStyle = (0, import_antd_style.createStyles)(({ token, css }) => {
1350
1290
 
1351
1291
  // src/components/Chat/ColumnLayout.tsx
1352
1292
  var import_jsx_runtime4 = require("react/jsx-runtime");
1353
- var ColumnLayout = ({ left, right }) => {
1293
+ var ColumnLayout = ({
1294
+ left,
1295
+ right,
1296
+ logo,
1297
+ menu
1298
+ }) => {
1354
1299
  const { styles } = useStyle();
1355
- const { sideAppVisible, sideAppSize, sideAppSelectedCard } = useChatUIContext();
1300
+ const { sideAppVisible, sideAppSize, sideAppSelectedCard, menuCollapsed } = useChatUIContext();
1356
1301
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `fina_chat ${styles.layout}`, children: [
1302
+ menu && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1303
+ "div",
1304
+ {
1305
+ className: `${styles.menu} ${"open"} ${menuCollapsed ? "collapsed" : ""}`,
1306
+ children: [
1307
+ logo,
1308
+ menu
1309
+ ]
1310
+ }
1311
+ ),
1357
1312
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `${styles.mainContent} ${sideAppVisible ? "open" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `${styles.chat}`, children: left }) }),
1358
1313
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1359
1314
  "div",
@@ -1373,28 +1328,28 @@ var import_icons12 = require("@ant-design/icons");
1373
1328
 
1374
1329
  // src/components/GenUI/elements/confirm_feedback.tsx
1375
1330
  var import_antd = require("antd");
1376
- var import_react10 = require("react");
1331
+ var import_react9 = require("react");
1377
1332
 
1378
1333
  // src/components/GenUI/MDResponse.tsx
1379
1334
  var import_react_markdown = __toESM(require("react-markdown"));
1380
1335
  var import_react_syntax_highlighter = require("react-syntax-highlighter");
1381
1336
  var import_prism = require("react-syntax-highlighter/dist/cjs/styles/prism");
1382
1337
  var import_remark_gfm = __toESM(require("remark-gfm"));
1383
- var import_react9 = require("react");
1338
+ var import_react8 = require("react");
1384
1339
  var import_antd_style2 = require("antd-style");
1385
1340
  var import_rehype_raw = __toESM(require("rehype-raw"));
1386
1341
 
1387
1342
  // src/components/GenUI/MDMermaid.tsx
1388
1343
  var import_mermaid = __toESM(require("mermaid"));
1389
- var import_react8 = require("react");
1344
+ var import_react7 = require("react");
1390
1345
  var import_uuid = require("uuid");
1391
1346
  var import_jsx_runtime5 = require("react/jsx-runtime");
1392
1347
  var MDMermaid = ({ children = [] }) => {
1393
- const domId = (0, import_react8.useRef)(`dom${(0, import_uuid.v4)()}`);
1348
+ const domId = (0, import_react7.useRef)(`dom${(0, import_uuid.v4)()}`);
1394
1349
  const code = String(children);
1395
- const target = (0, import_react8.useRef)(null);
1396
- const targetInternal = (0, import_react8.useRef)(null);
1397
- (0, import_react8.useEffect)(() => {
1350
+ const target = (0, import_react7.useRef)(null);
1351
+ const targetInternal = (0, import_react7.useRef)(null);
1352
+ (0, import_react7.useEffect)(() => {
1398
1353
  if (target.current && code) {
1399
1354
  import_mermaid.default.initialize({
1400
1355
  startOnLoad: true,
@@ -1551,7 +1506,7 @@ var MDResponse = ({
1551
1506
  noGenUI
1552
1507
  }) => {
1553
1508
  const { styles } = useStyles();
1554
- const config = (0, import_react9.useMemo)(
1509
+ const config = (0, import_react8.useMemo)(
1555
1510
  () => ({
1556
1511
  components: {
1557
1512
  a({ node, ...props }) {
@@ -1623,9 +1578,9 @@ var MDViewFormItem = ({ value }) => {
1623
1578
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MDResponse, { content: value || "" });
1624
1579
  };
1625
1580
  var IFrameCard = ({ src }) => {
1626
- const containerRef = (0, import_react9.useRef)(null);
1627
- const [width, setWidth] = (0, import_react9.useState)("640px");
1628
- const [height, setHeight] = (0, import_react9.useState)("320px");
1581
+ const containerRef = (0, import_react8.useRef)(null);
1582
+ const [width, setWidth] = (0, import_react8.useState)("640px");
1583
+ const [height, setHeight] = (0, import_react8.useState)("320px");
1629
1584
  const valid_images = [
1630
1585
  "jpg",
1631
1586
  "jpeg",
@@ -1655,11 +1610,11 @@ var ConfirmFeedback = ({
1655
1610
  data,
1656
1611
  interactive = true
1657
1612
  }) => {
1658
- const { message: message4, type, config, feedback, options } = data ?? {};
1613
+ const { message: message5, type, config, feedback, options } = data ?? {};
1659
1614
  const { sendMessage } = useAgentChat();
1660
- const [clicked, setClicked] = (0, import_react10.useState)(false);
1615
+ const [clicked, setClicked] = (0, import_react9.useState)(false);
1661
1616
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_antd.Space, { direction: "vertical", style: { width: "100%" }, children: [
1662
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MDResponse, { content: message4 }),
1617
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MDResponse, { content: message5 }),
1663
1618
  options ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_antd.Space, { style: { justifyContent: "flex-end", width: "100%" }, children: options?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1664
1619
  import_antd.Button,
1665
1620
  {
@@ -1736,13 +1691,13 @@ var ConfirmFeedback = ({
1736
1691
 
1737
1692
  // src/components/GenUI/elements/generic_data_table.tsx
1738
1693
  var import_antd2 = require("antd");
1739
- var import_react11 = require("react");
1694
+ var import_react10 = require("react");
1740
1695
  var import_icons = require("@ant-design/icons");
1741
1696
  var import_jsx_runtime8 = require("react/jsx-runtime");
1742
1697
  var { Text: Text2 } = import_antd2.Typography;
1743
1698
  var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = true }) => {
1744
- const { dataSource, message: message4 } = data ?? {};
1745
- const [expandedRowKeys, setExpandedRowKeys] = (0, import_react11.useState)([]);
1699
+ const { dataSource, message: message5 } = data ?? {};
1700
+ const [expandedRowKeys, setExpandedRowKeys] = (0, import_react10.useState)([]);
1746
1701
  const { openSideApp } = useChatUIContext();
1747
1702
  const processedData = dataSource?.map((item, index) => ({
1748
1703
  ...item,
@@ -1825,7 +1780,7 @@ var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = t
1825
1780
  {
1826
1781
  size: "small",
1827
1782
  title: () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_antd2.Flex, { justify: "space-between", align: "center", children: [
1828
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_antd2.Space, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text2, { strong: true, style: { fontSize: 16 }, children: message4 || "" }) }),
1783
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_antd2.Space, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text2, { strong: true, style: { fontSize: 16 }, children: message5 || "" }) }),
1829
1784
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_antd2.Space, { children: [
1830
1785
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1831
1786
  import_antd2.Button,
@@ -1846,8 +1801,8 @@ var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = t
1846
1801
  onClick: () => {
1847
1802
  openSideApp({
1848
1803
  component_key: "generic_data_table",
1849
- message: message4 || "",
1850
- data: { dataSource, message: message4 }
1804
+ message: message5 || "",
1805
+ data: { dataSource, message: message5 }
1851
1806
  });
1852
1807
  },
1853
1808
  children: [
@@ -2351,7 +2306,7 @@ var WriteTodos = ({
2351
2306
  };
2352
2307
 
2353
2308
  // src/components/GenUI/FileExplorer.tsx
2354
- var import_react12 = require("react");
2309
+ var import_react11 = require("react");
2355
2310
  var import_antd7 = require("antd");
2356
2311
  var import_icons7 = require("@ant-design/icons");
2357
2312
  var import_antd_style5 = require("antd-style");
@@ -2583,17 +2538,17 @@ var FileExplorer = ({
2583
2538
  }) => {
2584
2539
  const { files } = data ?? {};
2585
2540
  const { styles, cx } = useStyles2();
2586
- const [fileList, setFileList] = (0, import_react12.useState)([]);
2587
- const [selectedKey, setSelectedKey] = (0, import_react12.useState)("");
2588
- const [expandedKeys, setExpandedKeys] = (0, import_react12.useState)([]);
2589
- const [copied, setCopied] = (0, import_react12.useState)(false);
2590
- (0, import_react12.useEffect)(() => {
2541
+ const [fileList, setFileList] = (0, import_react11.useState)([]);
2542
+ const [selectedKey, setSelectedKey] = (0, import_react11.useState)("");
2543
+ const [expandedKeys, setExpandedKeys] = (0, import_react11.useState)([]);
2544
+ const [copied, setCopied] = (0, import_react11.useState)(false);
2545
+ (0, import_react11.useEffect)(() => {
2591
2546
  if (copied) {
2592
2547
  const timer = setTimeout(() => setCopied(false), 2e3);
2593
2548
  return () => clearTimeout(timer);
2594
2549
  }
2595
2550
  }, [copied]);
2596
- (0, import_react12.useEffect)(() => {
2551
+ (0, import_react11.useEffect)(() => {
2597
2552
  let list = [];
2598
2553
  if (Array.isArray(files)) {
2599
2554
  list = files;
@@ -2609,11 +2564,11 @@ var FileExplorer = ({
2609
2564
  setSelectedKey(list[0].name);
2610
2565
  }
2611
2566
  }, [files]);
2612
- const treeData = (0, import_react12.useMemo)(
2567
+ const treeData = (0, import_react11.useMemo)(
2613
2568
  () => buildTreeData(fileList, expandedKeys),
2614
2569
  [fileList, expandedKeys]
2615
2570
  );
2616
- (0, import_react12.useEffect)(() => {
2571
+ (0, import_react11.useEffect)(() => {
2617
2572
  if (treeData.length > 0 && expandedKeys.length === 0) {
2618
2573
  const getAllKeys = (nodes) => {
2619
2574
  let keys = [];
@@ -2630,7 +2585,7 @@ var FileExplorer = ({
2630
2585
  setExpandedKeys(getAllKeys(treeData));
2631
2586
  }
2632
2587
  }, [treeData.length]);
2633
- const selectedFile = (0, import_react12.useMemo)(() => {
2588
+ const selectedFile = (0, import_react11.useMemo)(() => {
2634
2589
  return fileList.find((f) => f.name === selectedKey);
2635
2590
  }, [fileList, selectedKey]);
2636
2591
  const handleCopy = () => {
@@ -2743,7 +2698,7 @@ var FileExplorer = ({
2743
2698
  var import_x = require("@ant-design/x");
2744
2699
  var import_antd8 = require("antd");
2745
2700
  var import_dayjs = __toESM(require("dayjs"));
2746
- var import_react13 = require("react");
2701
+ var import_react12 = require("react");
2747
2702
  var import_jsx_runtime16 = require("react/jsx-runtime");
2748
2703
  var AttachmentsCard = ({
2749
2704
  data,
@@ -2752,8 +2707,8 @@ var AttachmentsCard = ({
2752
2707
  columns = 1,
2753
2708
  showDownloadButton = false
2754
2709
  }) => {
2755
- const { Text: Text11 } = import_antd8.Typography;
2756
- const [showAll, setShowAll] = (0, import_react13.useState)(false);
2710
+ const { Text: Text12 } = import_antd8.Typography;
2711
+ const [showAll, setShowAll] = (0, import_react12.useState)(false);
2757
2712
  const { openSideApp } = useChatUIContext();
2758
2713
  const getStyles = () => {
2759
2714
  switch (size) {
@@ -2827,7 +2782,7 @@ var AttachmentsCard = ({
2827
2782
  );
2828
2783
  };
2829
2784
  const renderFileDescription = (item) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_antd8.Space, { direction: "vertical", size: size === "small" ? 2 : 4, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_antd8.Space, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2830
- Text11,
2785
+ Text12,
2831
2786
  {
2832
2787
  type: "secondary",
2833
2788
  style: {
@@ -2899,7 +2854,7 @@ var AttachmentsCard = ({
2899
2854
  }
2900
2855
  ),
2901
2856
  item.files && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { paddingLeft: "12px" }, children: [
2902
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Text11, { type: "secondary", style: { fontSize: "12px" }, children: [
2857
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Text12, { type: "secondary", style: { fontSize: "12px" }, children: [
2903
2858
  "\u5305\u542B\u6587\u4EF6(",
2904
2859
  item.files.length,
2905
2860
  ")"
@@ -2934,14 +2889,14 @@ var AttachmentsCard = ({
2934
2889
 
2935
2890
  // src/components/GenUI/elements/attachments_viewer_side_app.tsx
2936
2891
  var import_antd9 = require("antd");
2937
- var import_react14 = require("react");
2892
+ var import_react13 = require("react");
2938
2893
  var import_jsx_runtime17 = require("react/jsx-runtime");
2939
2894
  function AttachmentsViewerSideApp({
2940
2895
  data,
2941
2896
  component_key
2942
2897
  }) {
2943
- const [fileUri, setFileUri] = (0, import_react14.useState)();
2944
- const [loading, setLoading] = (0, import_react14.useState)(true);
2898
+ const [fileUri, setFileUri] = (0, import_react13.useState)();
2899
+ const [loading, setLoading] = (0, import_react13.useState)(true);
2945
2900
  const { file_id } = data ?? {};
2946
2901
  if (loading) {
2947
2902
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_antd9.Skeleton, { active: true });
@@ -3004,7 +2959,7 @@ function AttachmentsViewerSideApp({
3004
2959
  var import_antd11 = require("antd");
3005
2960
 
3006
2961
  // src/components/GenUI/elements/ContentPreviewCollapse.tsx
3007
- var import_react15 = require("react");
2962
+ var import_react14 = require("react");
3008
2963
  var import_antd10 = require("antd");
3009
2964
  var import_antd_style6 = require("antd-style");
3010
2965
  var import_icons8 = require("@ant-design/icons");
@@ -3074,18 +3029,18 @@ var ContentPreviewCollapse = ({
3074
3029
  showAllText = "Show all content",
3075
3030
  showLessText = "Show less"
3076
3031
  }) => {
3077
- const [showFullContent, setShowFullContent] = (0, import_react15.useState)(false);
3078
- const [isOverflowing, setIsOverflowing] = (0, import_react15.useState)(false);
3079
- const contentRef = (0, import_react15.useRef)(null);
3032
+ const [showFullContent, setShowFullContent] = (0, import_react14.useState)(false);
3033
+ const [isOverflowing, setIsOverflowing] = (0, import_react14.useState)(false);
3034
+ const contentRef = (0, import_react14.useRef)(null);
3080
3035
  const showShadow = isOverflowing && !showFullContent;
3081
3036
  const { styles, cx } = useStyle4({ showShadow });
3082
- const checkOverflow = (0, import_react15.useCallback)(() => {
3037
+ const checkOverflow = (0, import_react14.useCallback)(() => {
3083
3038
  if (contentRef.current) {
3084
3039
  const scrollHeight = contentRef.current.scrollHeight;
3085
3040
  setIsOverflowing(scrollHeight > collapsedMaxHeight);
3086
3041
  }
3087
3042
  }, [collapsedMaxHeight]);
3088
- (0, import_react15.useEffect)(() => {
3043
+ (0, import_react14.useEffect)(() => {
3089
3044
  const element = contentRef.current;
3090
3045
  if (!element) return;
3091
3046
  checkOverflow();
@@ -3270,8 +3225,7 @@ var import_jsx_runtime22 = require("react/jsx-runtime");
3270
3225
  var { Text: Text8 } = import_antd13.Typography;
3271
3226
  var useStyle5 = (0, import_antd_style7.createStyles)(({ token, css }) => ({
3272
3227
  card: css`
3273
- max-width: 600px;
3274
- background: ${token.colorBgContainer};
3228
+ background: rgba(0, 0, 0, 0.02);
3275
3229
  border: 1px solid ${token.colorBorderSecondary};
3276
3230
  border-radius: 16px;
3277
3231
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
@@ -3281,17 +3235,17 @@ var useStyle5 = (0, import_antd_style7.createStyles)(({ token, css }) => ({
3281
3235
  &:hover {
3282
3236
  border-color: ${token.colorPrimary};
3283
3237
  box-shadow: 0 8px 24px rgba(24, 144, 255, 0.12);
3284
- transform: translateX(4px);
3238
+ // transform: translateX(4px);
3285
3239
  }
3286
3240
  &::before {
3287
3241
  content: "";
3288
3242
  position: absolute;
3289
3243
  top: 0;
3290
3244
  left: 0;
3291
- bottom: 0;
3292
- width: 4px;
3245
+ right: 0;
3246
+ height: 4px;
3293
3247
  background: linear-gradient(
3294
- 180deg,
3248
+ 90deg,
3295
3249
  ${token.colorPrimary} 0%,
3296
3250
  ${token.colorPrimaryHover} 100%
3297
3251
  );
@@ -3393,6 +3347,26 @@ var useStyle5 = (0, import_antd_style7.createStyles)(({ token, css }) => ({
3393
3347
  color: ${token.colorTextTertiary};
3394
3348
  font-size: 14px;
3395
3349
  transition: all 0.2s ease;
3350
+ `,
3351
+ responseSection: css`
3352
+ margin-top: 16px;
3353
+ margin-bottom: 16px;
3354
+ padding-top: 16px;
3355
+ border-top: 1px solid ${token.colorBorderSecondary};
3356
+ `,
3357
+ responseHeader: css`
3358
+ font-size: 13px;
3359
+ font-weight: 600;
3360
+ color: ${token.colorTextSecondary};
3361
+ margin-bottom: 12px;
3362
+ text-transform: uppercase;
3363
+ letter-spacing: 0.5px;
3364
+ `,
3365
+ responseContent: css`
3366
+ padding: 12px;
3367
+ background: ${token.colorFillAlter};
3368
+ border-radius: 8px;
3369
+ border: 1px solid ${token.colorBorderSecondary};
3396
3370
  `
3397
3371
  }));
3398
3372
  var TaskCard = ({
@@ -3408,6 +3382,7 @@ var TaskCard = ({
3408
3382
  }
3409
3383
  const { description, subagent_type, assignee } = toolCallData?.args || {};
3410
3384
  const status = toolCallData.status || "pending";
3385
+ const response = toolCallData.response || null;
3411
3386
  const { threadId } = useAgentChat();
3412
3387
  const subagent_thread_id = (threadId || "") + "____" + subagent_type + "_" + toolCallData.id;
3413
3388
  const getStatusConfig = (status2) => {
@@ -3437,6 +3412,7 @@ var TaskCard = ({
3437
3412
  }
3438
3413
  };
3439
3414
  const statusConfig = getStatusConfig(status);
3415
+ const showResponse = status === "success" && response;
3440
3416
  const handleCardClick = () => {
3441
3417
  openSideApp({
3442
3418
  component_key: "task",
@@ -3497,7 +3473,18 @@ var TaskCard = ({
3497
3473
  )
3498
3474
  ] }),
3499
3475
  interactive && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_icons9.RightOutlined, { className: styles.actionIcon })
3500
- ] })
3476
+ ] }),
3477
+ showResponse && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
3478
+ "div",
3479
+ {
3480
+ className: styles.responseSection,
3481
+ onClick: (e) => e.stopPropagation(),
3482
+ children: [
3483
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Text8, { className: styles.responseHeader, children: "Response" }),
3484
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: styles.responseContent, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MDResponse, { content: response }) })
3485
+ ]
3486
+ }
3487
+ )
3501
3488
  ] })
3502
3489
  }
3503
3490
  );
@@ -3514,17 +3501,17 @@ var import_x4 = require("@ant-design/x");
3514
3501
  var import_x2 = require("@ant-design/x");
3515
3502
  var import_antd14 = require("antd");
3516
3503
  var import_ErrorBoundary = __toESM(require("antd/es/alert/ErrorBoundary"));
3517
- var import_react16 = require("react");
3504
+ var import_react15 = require("react");
3518
3505
  var import_jsx_runtime23 = require("react/jsx-runtime");
3519
3506
  var LazyBubble = ({
3520
- message: message4,
3507
+ message: message5,
3521
3508
  renderContent,
3522
3509
  autoLoadRightPanel
3523
3510
  }) => {
3524
- const ref = (0, import_react16.useRef)(null);
3525
- const [isVisible, setIsVisible] = (0, import_react16.useState)(false);
3526
- const [wasEverVisible, setWasEverVisible] = (0, import_react16.useState)(false);
3527
- (0, import_react16.useEffect)(() => {
3511
+ const ref = (0, import_react15.useRef)(null);
3512
+ const [isVisible, setIsVisible] = (0, import_react15.useState)(false);
3513
+ const [wasEverVisible, setWasEverVisible] = (0, import_react15.useState)(false);
3514
+ (0, import_react15.useEffect)(() => {
3528
3515
  const observer = new IntersectionObserver(
3529
3516
  ([entry]) => {
3530
3517
  const visible = entry.isIntersecting;
@@ -3544,16 +3531,16 @@ var LazyBubble = ({
3544
3531
  }
3545
3532
  };
3546
3533
  }, [wasEverVisible]);
3547
- (0, import_react16.useEffect)(() => {
3534
+ (0, import_react15.useEffect)(() => {
3548
3535
  autoLoadRightPanel?.();
3549
3536
  }, []);
3550
3537
  const getPlaceholder = () => {
3551
- const estimatedHeight = message4.content ? Math.min(100, message4.content.length / 5) : 100;
3538
+ const estimatedHeight = message5.content ? Math.min(100, message5.content.length / 5) : 100;
3552
3539
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { height: `${estimatedHeight}px`, minHeight: "50px" } });
3553
3540
  };
3554
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_ErrorBoundary.default, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref, style: { width: "100%" }, children: isVisible || wasEverVisible ? renderContent(message4) : getPlaceholder() }) });
3541
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_ErrorBoundary.default, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref, style: { width: "100%" }, children: isVisible || wasEverVisible ? renderContent(message5) : getPlaceholder() }) });
3555
3542
  };
3556
- var MemoizedBubbleList = (0, import_react16.memo)(
3543
+ var MemoizedBubbleList = (0, import_react15.memo)(
3557
3544
  ({
3558
3545
  items,
3559
3546
  role,
@@ -3576,14 +3563,14 @@ var MessageList = ({
3576
3563
  }) => {
3577
3564
  const { styles } = useStyle();
3578
3565
  const { openSideApp } = useChatUIContext();
3579
- const messageLengthRef = (0, import_react16.useRef)(messages?.length ?? 0);
3580
- (0, import_react16.useEffect)(() => {
3566
+ const messageLengthRef = (0, import_react15.useRef)(messages?.length ?? 0);
3567
+ (0, import_react15.useEffect)(() => {
3581
3568
  if (messages?.length) {
3582
3569
  messageLengthRef.current = messages?.length;
3583
3570
  }
3584
3571
  }, [messages?.length]);
3585
- const renderContent = (0, import_react16.useCallback)((message4) => {
3586
- const { content } = message4;
3572
+ const renderContent = (0, import_react15.useCallback)((message5) => {
3573
+ const { content } = message5;
3587
3574
  try {
3588
3575
  const json = JSON.parse(content);
3589
3576
  if (json.action && json.message) {
@@ -3591,7 +3578,7 @@ var MessageList = ({
3591
3578
  }
3592
3579
  } catch (error) {
3593
3580
  }
3594
- const tool_calls_md = message4.tool_calls?.map((tool_call) => {
3581
+ const tool_calls_md = message5.tool_calls?.map((tool_call) => {
3595
3582
  return `\`\`\`tool_call
3596
3583
  ${JSON.stringify(tool_call)}
3597
3584
  \`\`\``;
@@ -3599,18 +3586,18 @@ ${JSON.stringify(tool_call)}
3599
3586
  const content_md = [content, ...tool_calls_md].join("\n");
3600
3587
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_antd14.Space, { direction: "vertical", style: { width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(MDResponse, { content: content_md }) });
3601
3588
  }, []);
3602
- const items = (0, import_react16.useMemo)(
3603
- () => messages.map((message4, index) => ({
3604
- key: message4.id,
3605
- role: message4.role,
3589
+ const items = (0, import_react15.useMemo)(
3590
+ () => messages.map((message5, index) => ({
3591
+ key: message5.id,
3592
+ role: message5.role,
3606
3593
  typing: false,
3607
3594
  content: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3608
3595
  LazyBubble,
3609
3596
  {
3610
- message: message4,
3597
+ message: message5,
3611
3598
  renderContent,
3612
3599
  autoLoadRightPanel: () => {
3613
- const { content, role: role2 } = message4;
3600
+ const { content, role: role2 } = message5;
3614
3601
  const isNewAddedMessage = messageLengthRef.current > 1 && messageLengthRef.current + 1 === messages.length;
3615
3602
  if (index === messages.length - 1 && isNewAddedMessage && role2 === "ai") {
3616
3603
  try {
@@ -3678,7 +3665,7 @@ ${JSON.stringify(tool_call)}
3678
3665
 
3679
3666
  // src/components/Chat/Chating.tsx
3680
3667
  var import_antd19 = require("antd");
3681
- var import_react18 = __toESM(require("react"));
3668
+ var import_react17 = __toESM(require("react"));
3682
3669
 
3683
3670
  // src/components/GenUI/HITLContainer.tsx
3684
3671
  var import_antd15 = require("antd");
@@ -3820,11 +3807,11 @@ var FileExplorerButton = ({}) => {
3820
3807
 
3821
3808
  // src/components/Chat/AgentHeader.tsx
3822
3809
  var import_x3 = require("@ant-design/x");
3823
- var import_react17 = require("react");
3810
+ var import_react16 = require("react");
3824
3811
  var import_jsx_runtime27 = require("react/jsx-runtime");
3825
3812
  var AgentHeader = (props) => {
3826
3813
  const { description, avatar, name, extra, extraMeta } = props;
3827
- const extraMetaComponents = (0, import_react17.useMemo)(() => {
3814
+ const extraMetaComponents = (0, import_react16.useMemo)(() => {
3828
3815
  if (extraMeta && extraMeta.length > 0) {
3829
3816
  return extraMeta.map((meta) => {
3830
3817
  const Element = getElement(meta.id)?.card_view;
@@ -3853,8 +3840,8 @@ var AgentHeader = (props) => {
3853
3840
  style: { padding: 8 },
3854
3841
  variant: "borderless",
3855
3842
  description,
3856
- icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_antd18.Avatar, { src: avatar || "/images/avatar.jpeg", size: 48 }),
3857
- title: name || "Fina",
3843
+ icon: avatar ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_antd18.Avatar, { src: avatar, size: 48 }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_antd18.Avatar, { size: 48, children: name?.charAt(0).toUpperCase() }),
3844
+ title: name ? name : void 0,
3858
3845
  extra: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_antd18.Space, { children: [
3859
3846
  extra,
3860
3847
  /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TodoProgress, {}),
@@ -3891,12 +3878,12 @@ var Chating = ({
3891
3878
  showHITL = true,
3892
3879
  showRefreshButton = false
3893
3880
  }) => {
3894
- const [content, setContent] = (0, import_react18.useState)("");
3895
- const [attachedFiles, setAttachedFiles] = (0, import_react18.useState)([]);
3881
+ const [content, setContent] = (0, import_react17.useState)("");
3882
+ const [attachedFiles, setAttachedFiles] = (0, import_react17.useState)([]);
3896
3883
  const { styles } = useStyle();
3897
- const [headerOpen, setHeaderOpen] = (0, import_react18.useState)(false);
3898
- const attachmentsRef = (0, import_react18.useRef)(null);
3899
- const senderRef = import_react18.default.useRef(null);
3884
+ const [headerOpen, setHeaderOpen] = (0, import_react17.useState)(false);
3885
+ const attachmentsRef = (0, import_react17.useRef)(null);
3886
+ const senderRef = import_react17.default.useRef(null);
3900
3887
  const {
3901
3888
  messages,
3902
3889
  sendMessage,
@@ -3908,7 +3895,7 @@ var Chating = ({
3908
3895
  tenantId,
3909
3896
  clearError
3910
3897
  } = useAgentChat();
3911
- (0, import_react18.useEffect)(() => {
3898
+ (0, import_react17.useEffect)(() => {
3912
3899
  regsiterElement("action_show_attachments_uploader", {
3913
3900
  card_view: () => null,
3914
3901
  action: (data) => {
@@ -4199,7 +4186,7 @@ var regsiterElement = (language, ElementMeta) => {
4199
4186
  // src/components/Chat/SideAppViewBrowser.tsx
4200
4187
  var import_antd21 = require("antd");
4201
4188
  var import_antd_style9 = require("antd-style");
4202
- var import_react19 = require("react");
4189
+ var import_react18 = require("react");
4203
4190
  var import_jsx_runtime30 = require("react/jsx-runtime");
4204
4191
  var useStyle7 = (0, import_antd_style9.createStyles)(({ token, css }) => {
4205
4192
  return {
@@ -4234,10 +4221,10 @@ var SideAppViewBrowser = () => {
4234
4221
  openSideApp,
4235
4222
  closeSideApp
4236
4223
  } = useChatUIContext();
4237
- const [activeKey, setActiveKey] = (0, import_react19.useState)(
4224
+ const [activeKey, setActiveKey] = (0, import_react18.useState)(
4238
4225
  JSON.stringify(sideAppSelectedCard)
4239
4226
  );
4240
- const [items, setItems] = (0, import_react19.useState)([]);
4227
+ const [items, setItems] = (0, import_react18.useState)([]);
4241
4228
  const add = (key, label, children) => {
4242
4229
  const newActiveKey = key;
4243
4230
  const newPanes = [...items];
@@ -4273,7 +4260,7 @@ var SideAppViewBrowser = () => {
4273
4260
  remove(targetKey);
4274
4261
  }
4275
4262
  };
4276
- (0, import_react19.useEffect)(() => {
4263
+ (0, import_react18.useEffect)(() => {
4277
4264
  const SideAppView = getElement(sideAppSelectedCard?.component_key).side_app_view || EmptySideAppView;
4278
4265
  const key = JSON.stringify(sideAppSelectedCard);
4279
4266
  if (items.find((item) => item.key === key)) {
@@ -4378,7 +4365,7 @@ var SideAppViewBrowser = () => {
4378
4365
  // src/components/Chat/LatticeChat.tsx
4379
4366
  var import_jsx_runtime31 = require("react/jsx-runtime");
4380
4367
  var LatticeChat = (props) => {
4381
- const { assistant_id, thread_id, ...chatingProps } = props;
4368
+ const { assistant_id, thread_id = "", menu, ...chatingProps } = props;
4382
4369
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4383
4370
  AgentThreadProvider,
4384
4371
  {
@@ -4392,7 +4379,8 @@ var LatticeChat = (props) => {
4392
4379
  children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ChatUIContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4393
4380
  ColumnLayout,
4394
4381
  {
4395
- left: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Chating, { ...chatingProps }),
4382
+ menu,
4383
+ left: thread_id ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Chating, { ...chatingProps }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { children: "\u9700\u8981\u5148\u521B\u5EFA\u4F1A\u8BDD" }),
4396
4384
  right: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SideAppViewBrowser, {})
4397
4385
  }
4398
4386
  ) })
@@ -4400,22 +4388,2307 @@ var LatticeChat = (props) => {
4400
4388
  );
4401
4389
  };
4402
4390
 
4403
- // src/components/Chat/AgentConversations.tsx
4404
- var import_icons13 = require("@ant-design/icons");
4405
- var import_x5 = require("@ant-design/x");
4406
- var import_antd22 = require("antd");
4391
+ // src/components/Chat/ConversationContext.tsx
4392
+ var import_react21 = require("react");
4393
+
4394
+ // src/components/Chat/AssistantContext.tsx
4407
4395
  var import_react20 = require("react");
4396
+ var import_client_sdk4 = require("@axiom-lattice/client-sdk");
4397
+
4398
+ // src/components/Chat/LatticeChatShellContext.tsx
4399
+ var import_react19 = require("react");
4408
4400
  var import_jsx_runtime32 = require("react/jsx-runtime");
4401
+ var DEFAULT_CONFIG = {
4402
+ baseURL: "http://localhost:4001",
4403
+ apiKey: "",
4404
+ transport: "sse",
4405
+ timeout: 3e5,
4406
+ headers: {}
4407
+ };
4408
+ var LatticeChatShellContext = (0, import_react19.createContext)({
4409
+ config: DEFAULT_CONFIG,
4410
+ updateConfig: () => {
4411
+ },
4412
+ updateConfigValue: () => {
4413
+ },
4414
+ resetConfig: () => {
4415
+ }
4416
+ });
4417
+ var LatticeChatShellContextProvider = ({
4418
+ children,
4419
+ initialConfig = {},
4420
+ persistToLocalStorage = false,
4421
+ localStorageKey = "lattice_chat_shell_config"
4422
+ }) => {
4423
+ const loadInitialConfig = (0, import_react19.useCallback)(() => {
4424
+ if (persistToLocalStorage && typeof window !== "undefined") {
4425
+ try {
4426
+ const stored = localStorage.getItem(localStorageKey);
4427
+ if (stored) {
4428
+ const parsed = JSON.parse(stored);
4429
+ return { ...DEFAULT_CONFIG, ...parsed, ...initialConfig };
4430
+ }
4431
+ } catch (error) {
4432
+ console.warn("Failed to load config from localStorage:", error);
4433
+ }
4434
+ }
4435
+ return { ...DEFAULT_CONFIG, ...initialConfig };
4436
+ }, [persistToLocalStorage, localStorageKey, initialConfig]);
4437
+ const [config, setConfig] = (0, import_react19.useState)(loadInitialConfig);
4438
+ const saveToLocalStorage = (0, import_react19.useCallback)(
4439
+ (newConfig) => {
4440
+ if (persistToLocalStorage && typeof window !== "undefined") {
4441
+ try {
4442
+ localStorage.setItem(localStorageKey, JSON.stringify(newConfig));
4443
+ } catch (error) {
4444
+ console.warn("Failed to save config to localStorage:", error);
4445
+ }
4446
+ }
4447
+ },
4448
+ [persistToLocalStorage, localStorageKey]
4449
+ );
4450
+ const updateConfig = (0, import_react19.useCallback)(
4451
+ (updates) => {
4452
+ setConfig((prev) => {
4453
+ const newConfig = { ...prev, ...updates };
4454
+ saveToLocalStorage(newConfig);
4455
+ return newConfig;
4456
+ });
4457
+ },
4458
+ [saveToLocalStorage]
4459
+ );
4460
+ const updateConfigValue = (0, import_react19.useCallback)(
4461
+ (key, value) => {
4462
+ setConfig((prev) => {
4463
+ const newConfig = { ...prev, [key]: value };
4464
+ saveToLocalStorage(newConfig);
4465
+ return newConfig;
4466
+ });
4467
+ },
4468
+ [saveToLocalStorage]
4469
+ );
4470
+ const resetConfig = (0, import_react19.useCallback)(() => {
4471
+ const defaultConfig = { ...DEFAULT_CONFIG, ...initialConfig };
4472
+ setConfig(defaultConfig);
4473
+ saveToLocalStorage(defaultConfig);
4474
+ }, [initialConfig, saveToLocalStorage]);
4475
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
4476
+ LatticeChatShellContext.Provider,
4477
+ {
4478
+ value: {
4479
+ config,
4480
+ updateConfig,
4481
+ updateConfigValue,
4482
+ resetConfig
4483
+ },
4484
+ children
4485
+ }
4486
+ );
4487
+ };
4488
+ var useLatticeChatShellContext = () => {
4489
+ const context = (0, import_react19.useContext)(LatticeChatShellContext);
4490
+ if (!context) {
4491
+ throw new Error(
4492
+ "useLatticeChatShellContext must be used within a LatticeChatShellContextProvider"
4493
+ );
4494
+ }
4495
+ return context;
4496
+ };
4497
+
4498
+ // src/components/Chat/AssistantContext.tsx
4499
+ var import_jsx_runtime33 = require("react/jsx-runtime");
4500
+ var AssistantContext = (0, import_react20.createContext)({
4501
+ assistants: [],
4502
+ currentAssistant: null,
4503
+ isLoading: false,
4504
+ error: null,
4505
+ listAssistants: async () => {
4506
+ },
4507
+ getAssistant: async () => {
4508
+ throw new Error("Not implemented");
4509
+ },
4510
+ createAssistant: async () => {
4511
+ throw new Error("Not implemented");
4512
+ },
4513
+ updateAssistant: async () => {
4514
+ throw new Error("Not implemented");
4515
+ },
4516
+ deleteAssistant: async () => {
4517
+ },
4518
+ selectAssistant: async () => {
4519
+ },
4520
+ clearCurrentAssistant: () => {
4521
+ },
4522
+ refresh: async () => {
4523
+ }
4524
+ });
4525
+ var AssistantContextProvider = ({
4526
+ children,
4527
+ autoLoad = true,
4528
+ initialAssistantId = null
4529
+ }) => {
4530
+ const {
4531
+ config: { baseURL, apiKey = "", transport = "sse" }
4532
+ } = useLatticeChatShellContext();
4533
+ const client = (0, import_react20.useMemo)(
4534
+ () => new import_client_sdk4.Client({
4535
+ baseURL,
4536
+ apiKey,
4537
+ assistantId: "",
4538
+ transport
4539
+ }),
4540
+ [baseURL, apiKey, transport]
4541
+ );
4542
+ const [state, setState] = (0, import_react20.useState)({
4543
+ assistants: [],
4544
+ currentAssistant: null,
4545
+ isLoading: false,
4546
+ error: null
4547
+ });
4548
+ const assistantsRef = (0, import_react20.useRef)([]);
4549
+ (0, import_react20.useEffect)(() => {
4550
+ assistantsRef.current = state.assistants;
4551
+ }, [state.assistants]);
4552
+ const listAssistants = (0, import_react20.useCallback)(async () => {
4553
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4554
+ try {
4555
+ const assistants = await client.assistants.list();
4556
+ setState((prev) => ({
4557
+ ...prev,
4558
+ assistants,
4559
+ isLoading: false
4560
+ }));
4561
+ } catch (error) {
4562
+ setState((prev) => ({
4563
+ ...prev,
4564
+ isLoading: false,
4565
+ error: error instanceof Error ? error : new Error(String(error))
4566
+ }));
4567
+ }
4568
+ }, [client]);
4569
+ const getAssistant = (0, import_react20.useCallback)(
4570
+ async (id) => {
4571
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4572
+ try {
4573
+ const assistant = await client.assistants.get(id);
4574
+ setState((prev) => ({
4575
+ ...prev,
4576
+ // Update assistant in list if it exists
4577
+ assistants: prev.assistants.map((a) => a.id === id ? assistant : a),
4578
+ isLoading: false
4579
+ }));
4580
+ return assistant;
4581
+ } catch (error) {
4582
+ setState((prev) => ({
4583
+ ...prev,
4584
+ isLoading: false,
4585
+ error: error instanceof Error ? error : new Error(String(error))
4586
+ }));
4587
+ throw error;
4588
+ }
4589
+ },
4590
+ [client]
4591
+ );
4592
+ const createAssistant = (0, import_react20.useCallback)(
4593
+ async (options) => {
4594
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4595
+ try {
4596
+ const newAssistant = await client.assistants.create(options);
4597
+ setState((prev) => ({
4598
+ ...prev,
4599
+ assistants: [...prev.assistants, newAssistant],
4600
+ isLoading: false
4601
+ }));
4602
+ return newAssistant;
4603
+ } catch (error) {
4604
+ setState((prev) => ({
4605
+ ...prev,
4606
+ isLoading: false,
4607
+ error: error instanceof Error ? error : new Error(String(error))
4608
+ }));
4609
+ throw error;
4610
+ }
4611
+ },
4612
+ [client]
4613
+ );
4614
+ const updateAssistant = (0, import_react20.useCallback)(
4615
+ async (id, options) => {
4616
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4617
+ try {
4618
+ const updatedAssistant = await client.assistants.update(id, options);
4619
+ setState((prev) => ({
4620
+ ...prev,
4621
+ assistants: prev.assistants.map(
4622
+ (a) => a.id === id ? updatedAssistant : a
4623
+ ),
4624
+ currentAssistant: prev.currentAssistant?.id === id ? updatedAssistant : prev.currentAssistant,
4625
+ isLoading: false
4626
+ }));
4627
+ return updatedAssistant;
4628
+ } catch (error) {
4629
+ setState((prev) => ({
4630
+ ...prev,
4631
+ isLoading: false,
4632
+ error: error instanceof Error ? error : new Error(String(error))
4633
+ }));
4634
+ throw error;
4635
+ }
4636
+ },
4637
+ [client]
4638
+ );
4639
+ const deleteAssistant = (0, import_react20.useCallback)(
4640
+ async (id) => {
4641
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4642
+ try {
4643
+ await client.assistants.delete(id);
4644
+ setState((prev) => ({
4645
+ ...prev,
4646
+ assistants: prev.assistants.filter((a) => a.id !== id),
4647
+ currentAssistant: prev.currentAssistant?.id === id ? null : prev.currentAssistant,
4648
+ isLoading: false
4649
+ }));
4650
+ } catch (error) {
4651
+ setState((prev) => ({
4652
+ ...prev,
4653
+ isLoading: false,
4654
+ error: error instanceof Error ? error : new Error(String(error))
4655
+ }));
4656
+ throw error;
4657
+ }
4658
+ },
4659
+ [client]
4660
+ );
4661
+ const selectAssistant = (0, import_react20.useCallback)(
4662
+ async (id) => {
4663
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
4664
+ try {
4665
+ const assistant = assistantsRef.current.find((a) => a.id === id);
4666
+ if (!assistant) {
4667
+ const fetchedAssistant = await client.assistants.get(id);
4668
+ setState((prev) => ({
4669
+ ...prev,
4670
+ assistants: [...prev.assistants, fetchedAssistant],
4671
+ currentAssistant: fetchedAssistant,
4672
+ isLoading: false
4673
+ }));
4674
+ } else {
4675
+ setState((prev) => ({
4676
+ ...prev,
4677
+ currentAssistant: assistant,
4678
+ isLoading: false
4679
+ }));
4680
+ }
4681
+ } catch (error) {
4682
+ setState((prev) => ({
4683
+ ...prev,
4684
+ isLoading: false,
4685
+ error: error instanceof Error ? error : new Error(String(error))
4686
+ }));
4687
+ throw error;
4688
+ }
4689
+ },
4690
+ [client]
4691
+ );
4692
+ const clearCurrentAssistant = (0, import_react20.useCallback)(() => {
4693
+ setState((prev) => ({
4694
+ ...prev,
4695
+ currentAssistant: null
4696
+ }));
4697
+ }, []);
4698
+ const refresh = (0, import_react20.useCallback)(async () => {
4699
+ await listAssistants();
4700
+ }, [listAssistants]);
4701
+ (0, import_react20.useEffect)(() => {
4702
+ if (autoLoad) {
4703
+ listAssistants();
4704
+ }
4705
+ }, [autoLoad, listAssistants]);
4706
+ (0, import_react20.useEffect)(() => {
4707
+ if (state.assistants.length > 0 && !state.currentAssistant) {
4708
+ if (initialAssistantId) {
4709
+ const assistant = state.assistants.find(
4710
+ (a) => a.id === initialAssistantId
4711
+ );
4712
+ if (assistant) {
4713
+ setState((prev) => ({
4714
+ ...prev,
4715
+ currentAssistant: assistant
4716
+ }));
4717
+ }
4718
+ } else {
4719
+ setState((prev) => ({
4720
+ ...prev,
4721
+ currentAssistant: prev.assistants[0]
4722
+ }));
4723
+ }
4724
+ }
4725
+ }, [initialAssistantId, state.assistants, state.currentAssistant]);
4726
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
4727
+ AssistantContext.Provider,
4728
+ {
4729
+ value: {
4730
+ ...state,
4731
+ listAssistants,
4732
+ getAssistant,
4733
+ createAssistant,
4734
+ updateAssistant,
4735
+ deleteAssistant,
4736
+ selectAssistant,
4737
+ clearCurrentAssistant,
4738
+ refresh
4739
+ },
4740
+ children
4741
+ }
4742
+ );
4743
+ };
4744
+ var useAssistantContext = () => {
4745
+ const context = (0, import_react20.useContext)(AssistantContext);
4746
+ if (!context) {
4747
+ throw new Error(
4748
+ "useAssistantContext must be used within an AssistantContextProvider"
4749
+ );
4750
+ }
4751
+ return context;
4752
+ };
4753
+
4754
+ // src/components/Chat/ConversationContext.tsx
4755
+ var import_client_sdk5 = require("@axiom-lattice/client-sdk");
4756
+ var import_jsx_runtime34 = require("react/jsx-runtime");
4757
+ var ConversationContext = (0, import_react21.createContext)({
4758
+ assistantId: null,
4759
+ thread: null,
4760
+ threadId: null,
4761
+ threads: [],
4762
+ isLoading: false,
4763
+ error: null,
4764
+ setThread: () => {
4765
+ },
4766
+ selectThread: () => {
4767
+ },
4768
+ createThread: async () => {
4769
+ throw new Error("Not implemented");
4770
+ },
4771
+ listThreads: async () => [],
4772
+ updateThread: async () => {
4773
+ },
4774
+ getThreadById: () => null,
4775
+ deleteThread: async () => {
4776
+ },
4777
+ clearThread: () => {
4778
+ },
4779
+ refresh: async () => {
4780
+ }
4781
+ });
4782
+ function convertThreadToConversationThread(thread, label) {
4783
+ return {
4784
+ id: thread.id,
4785
+ label: label || thread.metadata?.label || new Date(thread.createdAt).toLocaleString()
4786
+ };
4787
+ }
4788
+ function getThreadMetadata(label) {
4789
+ return label ? { label } : {};
4790
+ }
4791
+ var ConversationContextProvider = ({
4792
+ children
4793
+ }) => {
4794
+ const { currentAssistant } = useAssistantContext();
4795
+ const assistantId = currentAssistant?.id || null;
4796
+ const {
4797
+ config: { baseURL, apiKey = "", transport = "sse" }
4798
+ } = useLatticeChatShellContext();
4799
+ const client = (0, import_react21.useMemo)(
4800
+ () => new import_client_sdk5.Client({
4801
+ baseURL,
4802
+ apiKey,
4803
+ assistantId: assistantId || "",
4804
+ transport
4805
+ }),
4806
+ [baseURL, apiKey, assistantId, transport]
4807
+ );
4808
+ const [threads, setThreads] = (0, import_react21.useState)([]);
4809
+ const [threadId, setThreadId] = (0, import_react21.useState)(null);
4810
+ const [isLoading, setIsLoading] = (0, import_react21.useState)(false);
4811
+ const [error, setError] = (0, import_react21.useState)(null);
4812
+ const loadedAssistantIdRef = (0, import_react21.useRef)(null);
4813
+ const prevAssistantIdRef = (0, import_react21.useRef)(null);
4814
+ const isLoadingRef = (0, import_react21.useRef)(false);
4815
+ const clientRef = (0, import_react21.useRef)(client);
4816
+ (0, import_react21.useEffect)(() => {
4817
+ clientRef.current = client;
4818
+ }, [client]);
4819
+ const loadThreads = (0, import_react21.useCallback)(async () => {
4820
+ const currentClient = clientRef.current;
4821
+ if (!assistantId || !currentClient.assistantId) {
4822
+ setThreads([]);
4823
+ loadedAssistantIdRef.current = null;
4824
+ return;
4825
+ }
4826
+ if (isLoadingRef.current && loadedAssistantIdRef.current === assistantId) {
4827
+ return;
4828
+ }
4829
+ isLoadingRef.current = true;
4830
+ setIsLoading(true);
4831
+ setError(null);
4832
+ try {
4833
+ const apiThreads = await currentClient.threads.list();
4834
+ const conversationThreads = apiThreads.map(
4835
+ (t) => convertThreadToConversationThread(t)
4836
+ );
4837
+ if (conversationThreads.length === 0) {
4838
+ try {
4839
+ const apiThread = await currentClient.threads.create({
4840
+ metadata: getThreadMetadata()
4841
+ });
4842
+ const newThread = convertThreadToConversationThread(apiThread);
4843
+ setThreads([newThread]);
4844
+ setThreadId(newThread.id);
4845
+ } catch (createErr) {
4846
+ const createError = createErr instanceof Error ? createErr : new Error(String(createErr));
4847
+ setError(createError);
4848
+ console.error("Failed to create initial thread:", createError);
4849
+ setThreads([]);
4850
+ }
4851
+ } else {
4852
+ setThreads(conversationThreads);
4853
+ setThreadId((currentThreadId) => {
4854
+ if (!currentThreadId) {
4855
+ const latestThread = conversationThreads[conversationThreads.length - 1];
4856
+ return latestThread.id;
4857
+ }
4858
+ const threadExists = conversationThreads.some(
4859
+ (t) => t.id === currentThreadId
4860
+ );
4861
+ if (!threadExists) {
4862
+ const latestThread = conversationThreads[conversationThreads.length - 1];
4863
+ return latestThread.id;
4864
+ }
4865
+ return currentThreadId;
4866
+ });
4867
+ }
4868
+ loadedAssistantIdRef.current = assistantId;
4869
+ } catch (err) {
4870
+ const error2 = err instanceof Error ? err : new Error(String(err));
4871
+ setError(error2);
4872
+ console.error("Failed to load threads:", error2);
4873
+ } finally {
4874
+ setIsLoading(false);
4875
+ isLoadingRef.current = false;
4876
+ }
4877
+ }, [assistantId]);
4878
+ (0, import_react21.useEffect)(() => {
4879
+ const currentClient = clientRef.current;
4880
+ const prevAssistantId = prevAssistantIdRef.current;
4881
+ const assistantChanged = prevAssistantId !== assistantId;
4882
+ if (assistantId && currentClient.assistantId === assistantId) {
4883
+ if (assistantChanged) {
4884
+ setThreadId(null);
4885
+ prevAssistantIdRef.current = assistantId;
4886
+ }
4887
+ if (loadedAssistantIdRef.current !== assistantId) {
4888
+ loadThreads();
4889
+ }
4890
+ } else {
4891
+ setThreadId(null);
4892
+ setThreads([]);
4893
+ loadedAssistantIdRef.current = null;
4894
+ prevAssistantIdRef.current = null;
4895
+ }
4896
+ }, [assistantId, loadThreads]);
4897
+ const thread = (0, import_react21.useMemo)(() => {
4898
+ if (!assistantId || !threadId) {
4899
+ return null;
4900
+ }
4901
+ return threads.find((t) => t.id === threadId) || null;
4902
+ }, [assistantId, threadId, threads]);
4903
+ const setThread = (0, import_react21.useCallback)((newThread) => {
4904
+ if (newThread) {
4905
+ setThreadId(newThread.id);
4906
+ } else {
4907
+ setThreadId(null);
4908
+ }
4909
+ }, []);
4910
+ const selectThread = (0, import_react21.useCallback)(
4911
+ (targetThreadId) => {
4912
+ const foundThread = threads.find((t) => t.id === targetThreadId);
4913
+ if (foundThread) {
4914
+ setThreadId(targetThreadId);
4915
+ }
4916
+ },
4917
+ [threads]
4918
+ );
4919
+ const createThread = (0, import_react21.useCallback)(
4920
+ async (label) => {
4921
+ if (!assistantId || !client.assistantId) {
4922
+ throw new Error("No assistant selected");
4923
+ }
4924
+ setIsLoading(true);
4925
+ setError(null);
4926
+ try {
4927
+ const apiThread = await client.threads.create({
4928
+ metadata: getThreadMetadata(label)
4929
+ });
4930
+ const newThread = convertThreadToConversationThread(apiThread, label);
4931
+ await loadThreads();
4932
+ setThreadId(newThread.id);
4933
+ return newThread;
4934
+ } catch (err) {
4935
+ const error2 = err instanceof Error ? err : new Error(String(err));
4936
+ setError(error2);
4937
+ throw error2;
4938
+ } finally {
4939
+ setIsLoading(false);
4940
+ }
4941
+ },
4942
+ [assistantId, client, loadThreads]
4943
+ );
4944
+ const listThreads = (0, import_react21.useCallback)(async () => {
4945
+ if (!assistantId || !client.assistantId) {
4946
+ return [];
4947
+ }
4948
+ setIsLoading(true);
4949
+ setError(null);
4950
+ try {
4951
+ const apiThreads = await client.threads.list();
4952
+ const conversationThreads = apiThreads.map(
4953
+ (t) => convertThreadToConversationThread(t)
4954
+ );
4955
+ setThreads(conversationThreads);
4956
+ return conversationThreads;
4957
+ } catch (err) {
4958
+ const error2 = err instanceof Error ? err : new Error(String(err));
4959
+ setError(error2);
4960
+ return threads;
4961
+ } finally {
4962
+ setIsLoading(false);
4963
+ }
4964
+ }, [assistantId, client, threads]);
4965
+ const updateThread = (0, import_react21.useCallback)(
4966
+ async (newThread) => {
4967
+ if (!assistantId || !client.assistantId) {
4968
+ throw new Error("No assistant selected");
4969
+ }
4970
+ setIsLoading(true);
4971
+ setError(null);
4972
+ try {
4973
+ await client.threads.update(newThread.id, {
4974
+ metadata: getThreadMetadata(newThread.label)
4975
+ });
4976
+ await loadThreads();
4977
+ } catch (err) {
4978
+ const error2 = err instanceof Error ? err : new Error(String(err));
4979
+ setError(error2);
4980
+ throw error2;
4981
+ } finally {
4982
+ setIsLoading(false);
4983
+ }
4984
+ },
4985
+ [assistantId, client, loadThreads]
4986
+ );
4987
+ const getThreadById = (0, import_react21.useCallback)(
4988
+ (targetThreadId) => {
4989
+ return threads.find((t) => t.id === targetThreadId) || null;
4990
+ },
4991
+ [threads]
4992
+ );
4993
+ const deleteThread = (0, import_react21.useCallback)(
4994
+ async (targetThreadId) => {
4995
+ if (!assistantId || !client.assistantId) {
4996
+ throw new Error("No assistant selected");
4997
+ }
4998
+ setIsLoading(true);
4999
+ setError(null);
5000
+ try {
5001
+ await client.threads.delete(targetThreadId);
5002
+ await loadThreads();
5003
+ if (targetThreadId === threadId) {
5004
+ setThreadId(null);
5005
+ }
5006
+ } catch (err) {
5007
+ const error2 = err instanceof Error ? err : new Error(String(err));
5008
+ setError(error2);
5009
+ throw error2;
5010
+ } finally {
5011
+ setIsLoading(false);
5012
+ }
5013
+ },
5014
+ [threadId, assistantId, client, loadThreads]
5015
+ );
5016
+ const clearThread = (0, import_react21.useCallback)(() => {
5017
+ setThreadId(null);
5018
+ }, []);
5019
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
5020
+ ConversationContext.Provider,
5021
+ {
5022
+ value: {
5023
+ assistantId,
5024
+ thread,
5025
+ threadId,
5026
+ threads,
5027
+ isLoading,
5028
+ error,
5029
+ setThread,
5030
+ selectThread,
5031
+ createThread,
5032
+ listThreads,
5033
+ updateThread,
5034
+ getThreadById,
5035
+ deleteThread,
5036
+ clearThread,
5037
+ refresh: loadThreads
5038
+ },
5039
+ children
5040
+ }
5041
+ );
5042
+ };
5043
+ var useConversationContext = () => {
5044
+ const context = (0, import_react21.useContext)(ConversationContext);
5045
+ if (!context) {
5046
+ throw new Error(
5047
+ "useConversationContext must be used within a ConversationContextProvider"
5048
+ );
5049
+ }
5050
+ return context;
5051
+ };
5052
+
5053
+ // src/components/Chat/AgentConversations.tsx
5054
+ var import_x5 = require("@ant-design/x");
5055
+ var import_antd22 = require("antd");
5056
+ var import_react22 = require("react");
5057
+ var import_jsx_runtime35 = require("react/jsx-runtime");
5058
+ var AgentConversations = () => {
5059
+ const { token } = import_antd22.theme.useToken();
5060
+ const { currentAssistant } = useAssistantContext();
5061
+ const {
5062
+ assistantId,
5063
+ thread,
5064
+ selectThread,
5065
+ createThread,
5066
+ listThreads,
5067
+ threads
5068
+ } = useConversationContext();
5069
+ const style = {
5070
+ width: "100%",
5071
+ background: "transparent",
5072
+ borderRadius: token.borderRadius
5073
+ };
5074
+ const threadItems = (0, import_react22.useMemo)(() => {
5075
+ return threads || [];
5076
+ }, [threads]);
5077
+ const items = threadItems.map((thread2) => ({
5078
+ key: thread2.id,
5079
+ label: thread2.label
5080
+ }));
5081
+ const newChatClick = async () => {
5082
+ if (!assistantId) {
5083
+ return;
5084
+ }
5085
+ await createThread();
5086
+ };
5087
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
5088
+ import_x5.Conversations,
5089
+ {
5090
+ creation: {
5091
+ onClick: newChatClick
5092
+ },
5093
+ items,
5094
+ activeKey: thread?.id,
5095
+ style,
5096
+ groupable: true,
5097
+ onActiveChange: (key) => {
5098
+ selectThread(key);
5099
+ }
5100
+ }
5101
+ );
5102
+ };
5103
+
5104
+ // src/components/Chat/ChatSidebar.tsx
5105
+ var import_react24 = require("react");
5106
+ var import_antd25 = require("antd");
5107
+ var import_icons14 = require("@ant-design/icons");
5108
+
5109
+ // src/components/Chat/AssistantList.tsx
5110
+ var import_x6 = require("@ant-design/x");
5111
+ var import_antd23 = require("antd");
5112
+ var import_jsx_runtime36 = require("react/jsx-runtime");
5113
+ var AssistantList = () => {
5114
+ const { token } = import_antd23.theme.useToken();
5115
+ const { assistants, selectAssistant, currentAssistant } = useAssistantContext();
5116
+ const style = {
5117
+ width: "100%",
5118
+ background: "transparent",
5119
+ borderRadius: token.borderRadius
5120
+ };
5121
+ const items = assistants.map((assistant) => ({
5122
+ key: assistant.id,
5123
+ label: assistant.name,
5124
+ icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5125
+ import_antd23.Avatar,
5126
+ {
5127
+ size: "small",
5128
+ style: {
5129
+ backgroundColor: token.colorFillSecondary,
5130
+ color: token.colorText
5131
+ },
5132
+ children: assistant.name.charAt(0).toUpperCase()
5133
+ }
5134
+ )
5135
+ }));
5136
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5137
+ import_x6.Conversations,
5138
+ {
5139
+ items,
5140
+ activeKey: currentAssistant?.id,
5141
+ style,
5142
+ onActiveChange: (key) => {
5143
+ selectAssistant(key);
5144
+ }
5145
+ }
5146
+ );
5147
+ };
5148
+
5149
+ // src/components/Chat/ChatSidebar.tsx
5150
+ var import_antd_style11 = require("antd-style");
5151
+
5152
+ // src/components/Chat/SettingsModal.tsx
5153
+ var import_react23 = require("react");
5154
+ var import_antd24 = require("antd");
5155
+ var import_icons13 = require("@ant-design/icons");
5156
+ var import_antd_style10 = require("antd-style");
5157
+ var import_jsx_runtime37 = require("react/jsx-runtime");
5158
+ var { Text: Text11, Title: Title2 } = import_antd24.Typography;
5159
+ var { TextArea } = import_antd24.Input;
5160
+ var useStyles3 = (0, import_antd_style10.createStyles)(({ token, css }) => ({
5161
+ // settingsModal: css`
5162
+ // .ant-modal {
5163
+ // max-width: 100vw !important;
5164
+ // width: 100vw !important;
5165
+ // margin: 0 !important;
5166
+ // top: 0 !important;
5167
+ // padding-bottom: 0 !important;
5168
+ // }
5169
+ // .ant-modal-content {
5170
+ // padding: 0;
5171
+ // height: 100vh;
5172
+ // max-height: 100vh;
5173
+ // border-radius: 0;
5174
+ // overflow: hidden;
5175
+ // width: 100%;
5176
+ // }
5177
+ // .ant-modal-body {
5178
+ // padding: 0;
5179
+ // height: 100%;
5180
+ // display: flex;
5181
+ // overflow: hidden;
5182
+ // width: 100%;
5183
+ // }
5184
+ // `,
5185
+ tabsContainer: css`
5186
+ height: 100vh;
5187
+ display: flex;
5188
+ flex-direction: column;
5189
+ overflow: hidden;
5190
+
5191
+ .ant-tabs {
5192
+ height: 100%;
5193
+ display: flex;
5194
+ flex-direction: column;
5195
+ }
5196
+
5197
+ .ant-tabs-content-holder {
5198
+ flex: 1;
5199
+ overflow: hidden;
5200
+ }
5201
+
5202
+ .ant-tabs-content {
5203
+ height: 100%;
5204
+ }
5205
+
5206
+ .ant-tabs-tabpane {
5207
+ height: 100%;
5208
+ overflow: hidden;
5209
+ }
5210
+
5211
+ .ant-tabs-nav {
5212
+ margin: 0;
5213
+ padding: 0 ${token.paddingLG}px;
5214
+ background: ${token.colorBgContainer};
5215
+ border-bottom: 1px solid ${token.colorBorder};
5216
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5217
+ }
5218
+
5219
+ .ant-tabs-tab {
5220
+ padding: ${token.paddingMD}px ${token.paddingLG}px;
5221
+ margin: ${token.paddingSM}px ${token.marginXS}px 0 0;
5222
+ border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0;
5223
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5224
+
5225
+ &:hover {
5226
+ background: ${token.colorFillTertiary};
5227
+ }
5228
+
5229
+ &.ant-tabs-tab-active {
5230
+ background: ${token.colorBgContainer};
5231
+ border-bottom-color: ${token.colorBgContainer};
5232
+ }
5233
+ }
5234
+ `,
5235
+ tabContent: css`
5236
+ height: 100%;
5237
+ display: flex;
5238
+ flex-direction: column;
5239
+ overflow: hidden;
5240
+ background: linear-gradient(
5241
+ 135deg,
5242
+ ${token.colorBgLayout} 0%,
5243
+ ${token.colorFillQuaternary} 100%
5244
+ );
5245
+ `,
5246
+ sidebar: css`
5247
+ width: 280px;
5248
+ background: linear-gradient(
5249
+ 180deg,
5250
+ ${token.colorBgContainer} 0%,
5251
+ ${token.colorFillQuaternary} 100%
5252
+ );
5253
+ border-right: 1px solid ${token.colorBorder};
5254
+ display: flex;
5255
+ flex-direction: column;
5256
+ overflow-y: auto;
5257
+ flex-shrink: 0;
5258
+ box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);
5259
+
5260
+ /* Custom scrollbar */
5261
+ &::-webkit-scrollbar {
5262
+ width: 8px;
5263
+ }
5264
+
5265
+ &::-webkit-scrollbar-track {
5266
+ background: transparent;
5267
+ }
5268
+
5269
+ &::-webkit-scrollbar-thumb {
5270
+ background: ${token.colorBorder};
5271
+ border-radius: 4px;
5272
+ transition: background 0.2s;
5273
+
5274
+ &:hover {
5275
+ background: ${token.colorBorderSecondary};
5276
+ }
5277
+ }
5278
+ `,
5279
+ sidebarHeader: css`
5280
+ padding: ${token.paddingXL}px ${token.paddingLG}px;
5281
+ border-bottom: 1px solid ${token.colorBorder};
5282
+ background: linear-gradient(
5283
+ 135deg,
5284
+ ${token.colorPrimaryBg} 0%,
5285
+ ${token.colorBgContainer} 100%
5286
+ );
5287
+ position: sticky;
5288
+ top: 0;
5289
+ z-index: 10;
5290
+ backdrop-filter: blur(10px);
5291
+ `,
5292
+ sidebarTitle: css`
5293
+ font-size: ${token.fontSizeXL}px;
5294
+ font-weight: 700;
5295
+ background: linear-gradient(
5296
+ 135deg,
5297
+ ${token.colorPrimary} 0%,
5298
+ ${token.colorPrimaryHover} 100%
5299
+ );
5300
+ -webkit-background-clip: text;
5301
+ -webkit-text-fill-color: transparent;
5302
+ background-clip: text;
5303
+ margin: 0;
5304
+ letter-spacing: -0.5px;
5305
+ `,
5306
+ menuItem: css`
5307
+ padding: ${token.paddingMD}px ${token.paddingLG}px;
5308
+ margin: ${token.marginXS}px ${token.paddingSM}px;
5309
+ cursor: pointer;
5310
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5311
+ border-radius: ${token.borderRadiusLG}px;
5312
+ display: flex;
5313
+ align-items: center;
5314
+ gap: ${token.marginMD}px;
5315
+ position: relative;
5316
+ overflow: hidden;
5317
+
5318
+ &::before {
5319
+ content: "";
5320
+ position: absolute;
5321
+ left: 0;
5322
+ top: 0;
5323
+ bottom: 0;
5324
+ width: 3px;
5325
+ background: ${token.colorPrimary};
5326
+ transform: scaleY(0);
5327
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5328
+ border-radius: 0 2px 2px 0;
5329
+ }
5330
+
5331
+ &:hover {
5332
+ background: ${token.colorFillTertiary};
5333
+ transform: translateX(4px);
5334
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
5335
+ }
5336
+
5337
+ &.active {
5338
+ background: linear-gradient(
5339
+ 135deg,
5340
+ ${token.colorPrimaryBg} 0%,
5341
+ ${token.colorFillTertiary} 100%
5342
+ );
5343
+ color: ${token.colorPrimary};
5344
+ box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
5345
+ transform: translateX(4px);
5346
+
5347
+ &::before {
5348
+ transform: scaleY(1);
5349
+ }
5350
+
5351
+ .menuItemIcon {
5352
+ transform: scale(1.1);
5353
+ }
5354
+ }
5355
+ `,
5356
+ menuItemIcon: css`
5357
+ font-size: 18px;
5358
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5359
+ display: flex;
5360
+ align-items: center;
5361
+ justify-content: center;
5362
+ width: 24px;
5363
+ height: 24px;
5364
+ `,
5365
+ menuItemText: css`
5366
+ font-size: ${token.fontSize}px;
5367
+ font-weight: 600;
5368
+ letter-spacing: 0.2px;
5369
+ `,
5370
+ content: css`
5371
+ flex: 1;
5372
+ display: flex;
5373
+ flex-direction: column;
5374
+ overflow: hidden;
5375
+ width: 100%;
5376
+ min-width: 0;
5377
+ `,
5378
+ contentHeader: css`
5379
+ padding: ${token.paddingLG}px ${token.paddingXL * 2}px;
5380
+ background: ${token.colorBgContainer};
5381
+ border-bottom: 1px solid ${token.colorBorder};
5382
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5383
+ position: sticky;
5384
+ top: 0;
5385
+ z-index: 5;
5386
+ backdrop-filter: blur(10px);
5387
+ display: flex;
5388
+ justify-content: space-between;
5389
+ align-items: center;
5390
+ gap: ${token.marginLG}px;
5391
+ `,
5392
+ contentHeaderLeft: css`
5393
+ flex: 1;
5394
+ `,
5395
+ contentHeaderRight: css`
5396
+ display: flex;
5397
+ gap: ${token.marginMD}px;
5398
+ flex-shrink: 0;
5399
+ `,
5400
+ contentTitle: css`
5401
+ font-size: ${token.fontSizeHeading3}px;
5402
+ font-weight: 700;
5403
+ color: ${token.colorTextHeading};
5404
+ margin: 0 0 ${token.marginSM}px 0;
5405
+ letter-spacing: -0.5px;
5406
+ `,
5407
+ contentDescription: css`
5408
+ color: ${token.colorTextSecondary};
5409
+ font-size: ${token.fontSize}px;
5410
+ margin: 0;
5411
+ line-height: 1.6;
5412
+ `,
5413
+ contentBody: css`
5414
+ flex: 1;
5415
+ overflow-y: auto;
5416
+ padding: ${token.paddingXL * 2}px ${token.paddingXL * 2}px;
5417
+ background: transparent;
5418
+
5419
+ /* Custom scrollbar */
5420
+ &::-webkit-scrollbar {
5421
+ width: 8px;
5422
+ }
5423
+
5424
+ &::-webkit-scrollbar-track {
5425
+ background: transparent;
5426
+ }
5427
+
5428
+ &::-webkit-scrollbar-thumb {
5429
+ background: ${token.colorBorder};
5430
+ border-radius: 4px;
5431
+ transition: background 0.2s;
5432
+
5433
+ &:hover {
5434
+ background: ${token.colorBorderSecondary};
5435
+ }
5436
+ }
5437
+ `,
5438
+ formContainer: css`
5439
+ width: 100%;
5440
+ max-width: 100%;
5441
+ `,
5442
+ formLabel: css`
5443
+ font-weight: 600;
5444
+ color: ${token.colorTextHeading};
5445
+ margin-bottom: ${token.marginMD}px;
5446
+ display: block;
5447
+ font-size: ${token.fontSize}px;
5448
+ `,
5449
+ formDescription: css`
5450
+ color: ${token.colorTextSecondary};
5451
+ font-size: ${token.fontSizeSM}px;
5452
+ margin-top: ${token.marginSM}px;
5453
+ line-height: 1.6;
5454
+ `,
5455
+ card: css`
5456
+ background: ${token.colorBgContainer};
5457
+ border: 1px solid ${token.colorBorder};
5458
+ border-radius: ${token.borderRadiusLG}px;
5459
+ padding: ${token.paddingXL}px;
5460
+ margin-bottom: ${token.marginLG}px;
5461
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5462
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5463
+
5464
+ &:hover {
5465
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
5466
+ transform: translateY(-2px);
5467
+ border-color: ${token.colorPrimary};
5468
+ }
5469
+ `,
5470
+ alertCard: css`
5471
+ border-radius: ${token.borderRadiusLG}px;
5472
+ margin-bottom: ${token.marginLG}px;
5473
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5474
+ border: 1px solid ${token.colorBorder};
5475
+ `,
5476
+ textArea: css`
5477
+ border-radius: ${token.borderRadius}px;
5478
+ border: 1px solid ${token.colorBorder};
5479
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5480
+
5481
+ &:hover {
5482
+ border-color: ${token.colorPrimaryHover};
5483
+ }
5484
+
5485
+ &:focus {
5486
+ border-color: ${token.colorPrimary};
5487
+ box-shadow: 0 0 0 2px ${token.colorPrimaryBg};
5488
+ }
5489
+ `,
5490
+ connectionStatus: css`
5491
+ display: flex;
5492
+ align-items: center;
5493
+ gap: ${token.marginXS}px;
5494
+ margin-left: ${token.marginSM}px;
5495
+ `,
5496
+ addServerModal: css`
5497
+ .ant-modal-body {
5498
+ padding: ${token.paddingXL}px;
5499
+ }
5500
+ `
5501
+ }));
5502
+ var SETTINGS_MENU_ITEMS = [
5503
+ {
5504
+ key: "environment",
5505
+ label: "Environment Variables",
5506
+ icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons13.EnvironmentOutlined, {})
5507
+ },
5508
+ {
5509
+ key: "models",
5510
+ label: "Model Configuration",
5511
+ icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons13.ApiOutlined, {})
5512
+ }
5513
+ ];
5514
+ var SettingsModal = ({
5515
+ open,
5516
+ onClose
5517
+ }) => {
5518
+ const { styles } = useStyles3();
5519
+ const { config: shellConfig, updateConfigValue } = useLatticeChatShellContext();
5520
+ const [connections, setConnections] = (0, import_react23.useState)(() => {
5521
+ if (typeof window !== "undefined") {
5522
+ try {
5523
+ const stored = localStorage.getItem("lattice_server_connections");
5524
+ if (stored) {
5525
+ const parsed = JSON.parse(stored);
5526
+ return parsed;
5527
+ }
5528
+ } catch (error) {
5529
+ console.warn("Failed to load connections from localStorage:", error);
5530
+ }
5531
+ }
5532
+ if (shellConfig.baseURL) {
5533
+ return [
5534
+ {
5535
+ id: "default",
5536
+ name: "Default",
5537
+ url: shellConfig.baseURL
5538
+ }
5539
+ ];
5540
+ }
5541
+ return [];
5542
+ });
5543
+ const [serverConfigs, setServerConfigs] = (0, import_react23.useState)({});
5544
+ const connectionsRef = (0, import_react23.useRef)(connections);
5545
+ (0, import_react23.useEffect)(() => {
5546
+ connectionsRef.current = connections;
5547
+ }, [connections]);
5548
+ const [activeTabKey, setActiveTabKey] = (0, import_react23.useState)(
5549
+ connections.length > 0 ? connections[0].id : ""
5550
+ );
5551
+ const [activeMenu, setActiveMenu] = (0, import_react23.useState)("environment");
5552
+ const [loading, setLoading] = (0, import_react23.useState)(false);
5553
+ const [showAddServerModal, setShowAddServerModal] = (0, import_react23.useState)(false);
5554
+ const [newServerUrl, setNewServerUrl] = (0, import_react23.useState)("");
5555
+ const [newServerName, setNewServerName] = (0, import_react23.useState)("");
5556
+ const [newServerApiKey, setNewServerApiKey] = (0, import_react23.useState)("");
5557
+ const [addingServer, setAddingServer] = (0, import_react23.useState)(false);
5558
+ const saveConnections = (newConnections) => {
5559
+ setConnections(newConnections);
5560
+ if (typeof window !== "undefined") {
5561
+ try {
5562
+ localStorage.setItem(
5563
+ "lattice_server_connections",
5564
+ JSON.stringify(newConnections)
5565
+ );
5566
+ } catch (error) {
5567
+ console.warn("Failed to save connections to localStorage:", error);
5568
+ }
5569
+ }
5570
+ };
5571
+ const initializeServerConfig = (serverId) => {
5572
+ if (!serverConfigs[serverId]) {
5573
+ setServerConfigs((prev) => ({
5574
+ ...prev,
5575
+ [serverId]: {
5576
+ envText: "",
5577
+ models: [
5578
+ {
5579
+ key: "",
5580
+ model: "",
5581
+ provider: "openai",
5582
+ streaming: false,
5583
+ apiKey: "",
5584
+ baseURL: ""
5585
+ }
5586
+ ]
5587
+ }
5588
+ }));
5589
+ }
5590
+ };
5591
+ const checkConnection = async (serverId) => {
5592
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5593
+ if (!connection) return;
5594
+ const url = connection.url;
5595
+ if (!url) {
5596
+ updateConnectionStatus(serverId, { connected: false });
5597
+ return;
5598
+ }
5599
+ try {
5600
+ updateConnectionStatus(serverId, { connecting: true, error: "" });
5601
+ const controller = new AbortController();
5602
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
5603
+ const headers = {};
5604
+ if (connection.apiKey) {
5605
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5606
+ }
5607
+ const response = await fetch(`${url}/api/config`, {
5608
+ method: "GET",
5609
+ signal: controller.signal,
5610
+ headers
5611
+ });
5612
+ clearTimeout(timeoutId);
5613
+ if (response.ok) {
5614
+ updateConnectionStatus(serverId, {
5615
+ connected: true,
5616
+ connecting: false,
5617
+ error: ""
5618
+ });
5619
+ if (url !== shellConfig.baseURL) {
5620
+ updateConfigValue("baseURL", url);
5621
+ }
5622
+ } else {
5623
+ updateConnectionStatus(serverId, {
5624
+ connected: false,
5625
+ connecting: false,
5626
+ error: "Server returned an error"
5627
+ });
5628
+ }
5629
+ } catch (error) {
5630
+ if (error.name === "AbortError") {
5631
+ updateConnectionStatus(serverId, {
5632
+ connected: false,
5633
+ connecting: false,
5634
+ error: "Connection timeout"
5635
+ });
5636
+ } else {
5637
+ updateConnectionStatus(serverId, {
5638
+ connected: false,
5639
+ connecting: false,
5640
+ error: error.message || "Failed to connect to server"
5641
+ });
5642
+ }
5643
+ }
5644
+ };
5645
+ const updateConnectionStatus = (serverId, updates) => {
5646
+ setConnections(
5647
+ (prev) => prev.map(
5648
+ (conn) => conn.id === serverId ? { ...conn, ...updates } : conn
5649
+ )
5650
+ );
5651
+ };
5652
+ const loadCurrentConfig = async (serverId) => {
5653
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5654
+ if (!connection || !connection.connected) return;
5655
+ const url = connection.url;
5656
+ if (!url) return;
5657
+ try {
5658
+ const headers = {};
5659
+ if (connection.apiKey) {
5660
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5661
+ }
5662
+ const response = await fetch(`${url}/api/config`, {
5663
+ headers
5664
+ });
5665
+ if (response.ok) {
5666
+ const data = await response.json();
5667
+ if (data.success && data.data) {
5668
+ const lines = [];
5669
+ const configData = data.data;
5670
+ if (configData.port !== void 0) {
5671
+ lines.push(`PORT=${configData.port}`);
5672
+ }
5673
+ if (configData.queueServiceType) {
5674
+ lines.push(`QUEUE_SERVICE_TYPE=${configData.queueServiceType}`);
5675
+ }
5676
+ if (configData.redisUrl) {
5677
+ lines.push(`REDIS_URL=${configData.redisUrl}`);
5678
+ }
5679
+ if (configData.redisPassword) {
5680
+ lines.push(`REDIS_PASSWORD=`);
5681
+ }
5682
+ if (configData.queueName) {
5683
+ lines.push(`QUEUE_NAME=${configData.queueName}`);
5684
+ }
5685
+ setServerConfigs((prev) => ({
5686
+ ...prev,
5687
+ [serverId]: {
5688
+ ...prev[serverId],
5689
+ envText: lines.join("\n")
5690
+ }
5691
+ }));
5692
+ }
5693
+ }
5694
+ } catch (error) {
5695
+ console.error("Failed to load configuration:", error);
5696
+ import_antd24.message.error("Failed to load current configuration");
5697
+ }
5698
+ };
5699
+ const loadModelsConfig = async (serverId) => {
5700
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5701
+ if (!connection || !connection.connected) return;
5702
+ const url = connection.url;
5703
+ if (!url) return;
5704
+ try {
5705
+ const headers = {};
5706
+ if (connection.apiKey) {
5707
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5708
+ }
5709
+ const response = await fetch(`${url}/api/models`, {
5710
+ headers
5711
+ });
5712
+ if (response.ok) {
5713
+ const data = await response.json();
5714
+ if (data.success && data.data && Array.isArray(data.data)) {
5715
+ if (data.data.length > 0) {
5716
+ setServerConfigs((prev) => ({
5717
+ ...prev,
5718
+ [serverId]: {
5719
+ ...prev[serverId],
5720
+ models: data.data
5721
+ }
5722
+ }));
5723
+ } else {
5724
+ setServerConfigs((prev) => ({
5725
+ ...prev,
5726
+ [serverId]: {
5727
+ ...prev[serverId],
5728
+ models: [
5729
+ {
5730
+ key: "",
5731
+ model: "",
5732
+ provider: "openai",
5733
+ streaming: false,
5734
+ apiKey: "",
5735
+ baseURL: ""
5736
+ }
5737
+ ]
5738
+ }
5739
+ }));
5740
+ }
5741
+ }
5742
+ }
5743
+ } catch (error) {
5744
+ console.error("Failed to load models configuration:", error);
5745
+ }
5746
+ };
5747
+ (0, import_react23.useEffect)(() => {
5748
+ if (open && activeTabKey) {
5749
+ initializeServerConfig(activeTabKey);
5750
+ const connection = connections.find((c) => c.id === activeTabKey);
5751
+ if (connection && !connection.connected && !connection.connecting) {
5752
+ checkConnection(activeTabKey);
5753
+ }
5754
+ }
5755
+ }, [open, activeTabKey]);
5756
+ (0, import_react23.useEffect)(() => {
5757
+ if (open && activeTabKey) {
5758
+ const connection = connections.find((c) => c.id === activeTabKey);
5759
+ if (connection?.connected) {
5760
+ if (activeMenu === "environment") {
5761
+ loadCurrentConfig(activeTabKey);
5762
+ } else if (activeMenu === "models") {
5763
+ loadModelsConfig(activeTabKey);
5764
+ }
5765
+ }
5766
+ }
5767
+ }, [open, activeTabKey, activeMenu]);
5768
+ const handleAddServer = async () => {
5769
+ if (!newServerUrl.trim()) {
5770
+ import_antd24.message.error("Please enter a server URL");
5771
+ return;
5772
+ }
5773
+ let normalizedUrl = newServerUrl.trim();
5774
+ if (!normalizedUrl.startsWith("http://") && !normalizedUrl.startsWith("https://")) {
5775
+ normalizedUrl = `http://${normalizedUrl}`;
5776
+ }
5777
+ const serverName = newServerName.trim() || normalizedUrl.replace(/^https?:\/\//, "");
5778
+ const newConnection = {
5779
+ id: `conn_${Date.now()}`,
5780
+ name: serverName,
5781
+ url: normalizedUrl,
5782
+ apiKey: newServerApiKey.trim() || void 0,
5783
+ connected: false
5784
+ };
5785
+ setAddingServer(true);
5786
+ const newConnections = [...connections, newConnection];
5787
+ saveConnections(newConnections);
5788
+ setActiveTabKey(newConnection.id);
5789
+ initializeServerConfig(newConnection.id);
5790
+ await checkConnection(newConnection.id);
5791
+ setAddingServer(false);
5792
+ setShowAddServerModal(false);
5793
+ setNewServerUrl("");
5794
+ setNewServerName("");
5795
+ setNewServerApiKey("");
5796
+ import_antd24.message.success("Server added successfully");
5797
+ };
5798
+ const handleDeleteServer = (serverId) => {
5799
+ const newConnections = connections.filter((c) => c.id !== serverId);
5800
+ saveConnections(newConnections);
5801
+ setServerConfigs((prev) => {
5802
+ const newConfigs = { ...prev };
5803
+ delete newConfigs[serverId];
5804
+ return newConfigs;
5805
+ });
5806
+ if (activeTabKey === serverId) {
5807
+ if (newConnections.length > 0) {
5808
+ setActiveTabKey(newConnections[0].id);
5809
+ } else {
5810
+ setActiveTabKey("");
5811
+ }
5812
+ }
5813
+ import_antd24.message.success("Server deleted");
5814
+ };
5815
+ const handleSave = async () => {
5816
+ const connection = connections.find((c) => c.id === activeTabKey);
5817
+ if (!connection || !connection.connected) {
5818
+ import_antd24.message.error("Please connect to a server first");
5819
+ return;
5820
+ }
5821
+ const url = connection.url;
5822
+ if (!url) {
5823
+ import_antd24.message.error("Please connect to a server first");
5824
+ return;
5825
+ }
5826
+ try {
5827
+ setLoading(true);
5828
+ const config = serverConfigs[activeTabKey];
5829
+ if (activeMenu === "environment") {
5830
+ const configObj = {};
5831
+ const lines = config.envText.split("\n");
5832
+ for (const line of lines) {
5833
+ const trimmedLine = line.trim();
5834
+ if (!trimmedLine || trimmedLine.startsWith("#")) {
5835
+ continue;
5836
+ }
5837
+ const equalIndex = trimmedLine.indexOf("=");
5838
+ if (equalIndex === -1) {
5839
+ continue;
5840
+ }
5841
+ const key = trimmedLine.substring(0, equalIndex).trim();
5842
+ const value = trimmedLine.substring(equalIndex + 1).trim();
5843
+ if (!key) {
5844
+ continue;
5845
+ }
5846
+ const upperKey = key.toUpperCase();
5847
+ if (upperKey === "PORT") {
5848
+ if (value) {
5849
+ configObj.port = Number(value);
5850
+ }
5851
+ } else if (upperKey === "QUEUE_SERVICE_TYPE") {
5852
+ if (value) {
5853
+ configObj.queueServiceType = value;
5854
+ }
5855
+ } else if (upperKey === "REDIS_URL") {
5856
+ if (value) {
5857
+ configObj.redisUrl = value;
5858
+ }
5859
+ } else if (upperKey === "REDIS_PASSWORD") {
5860
+ if (value) {
5861
+ configObj.redisPassword = value;
5862
+ }
5863
+ } else if (upperKey === "QUEUE_NAME") {
5864
+ if (value) {
5865
+ configObj.queueName = value;
5866
+ }
5867
+ } else {
5868
+ if (value) {
5869
+ configObj[key] = value;
5870
+ }
5871
+ }
5872
+ }
5873
+ const headers = {
5874
+ "Content-Type": "application/json"
5875
+ };
5876
+ if (connection.apiKey) {
5877
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5878
+ }
5879
+ const response = await fetch(`${url}/api/config`, {
5880
+ method: "PUT",
5881
+ headers,
5882
+ body: JSON.stringify({ config: configObj })
5883
+ });
5884
+ const data = await response.json();
5885
+ if (response.ok && data.success) {
5886
+ if (data.requiresRestart && data.requiresRestart.length > 0) {
5887
+ import_antd24.message.warning(
5888
+ `Configuration saved. Please restart the server for ${data.requiresRestart.join(
5889
+ ", "
5890
+ )} to take effect.`,
5891
+ 5
5892
+ );
5893
+ } else {
5894
+ import_antd24.message.success("Configuration saved and applied successfully");
5895
+ }
5896
+ if (data.warnings && data.warnings.length > 0) {
5897
+ data.warnings.forEach((warning) => {
5898
+ import_antd24.message.warning(warning, 5);
5899
+ });
5900
+ }
5901
+ onClose();
5902
+ } else {
5903
+ import_antd24.message.error(data.error || "Failed to save configuration");
5904
+ }
5905
+ } else if (activeMenu === "models") {
5906
+ const validModels = config.models.filter(
5907
+ (m) => m.key && m.model && m.provider
5908
+ );
5909
+ const headers = {
5910
+ "Content-Type": "application/json"
5911
+ };
5912
+ if (connection.apiKey) {
5913
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5914
+ }
5915
+ const response = await fetch(`${url}/api/models`, {
5916
+ method: "PUT",
5917
+ headers,
5918
+ body: JSON.stringify({ models: validModels })
5919
+ });
5920
+ const data = await response.json();
5921
+ if (response.ok && data.success) {
5922
+ import_antd24.message.success(
5923
+ "Model configuration saved and registered successfully"
5924
+ );
5925
+ onClose();
5926
+ } else {
5927
+ import_antd24.message.error(data.error || "Failed to save model configuration");
5928
+ }
5929
+ }
5930
+ } catch (error) {
5931
+ console.error("Failed to save configuration:", error);
5932
+ import_antd24.message.error(error.message || "Failed to save configuration");
5933
+ } finally {
5934
+ setLoading(false);
5935
+ }
5936
+ };
5937
+ const renderEnvironmentSettings = (serverId) => {
5938
+ const config = serverConfigs[serverId] || { envText: "", models: [] };
5939
+ const setEnvText = (text) => {
5940
+ setServerConfigs((prev) => ({
5941
+ ...prev,
5942
+ [serverId]: {
5943
+ ...prev[serverId],
5944
+ envText: text
5945
+ }
5946
+ }));
5947
+ };
5948
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.formContainer, children: [
5949
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
5950
+ import_antd24.Alert,
5951
+ {
5952
+ message: "Configuration Effect",
5953
+ description: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
5954
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { marginBottom: 8 }, children: [
5955
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
5956
+ import_icons13.CheckCircleOutlined,
5957
+ {
5958
+ style: { color: "#52c41a", marginRight: 8 }
5959
+ }
5960
+ ),
5961
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("strong", { children: "Immediately effective:" }),
5962
+ " QUEUE_SERVICE_TYPE, REDIS_URL, REDIS_PASSWORD, QUEUE_NAME"
5963
+ ] }),
5964
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
5965
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons13.ReloadOutlined, { style: { color: "#faad14", marginRight: 8 } }),
5966
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("strong", { children: "Requires restart:" }),
5967
+ " PORT (server must be restarted to change port)"
5968
+ ] })
5969
+ ] }),
5970
+ type: "info",
5971
+ showIcon: true,
5972
+ className: styles.alertCard
5973
+ }
5974
+ ),
5975
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { style: { marginBottom: 24 }, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(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." }) }),
5976
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
5977
+ TextArea,
5978
+ {
5979
+ value: config.envText,
5980
+ onChange: (e) => setEnvText(e.target.value),
5981
+ placeholder: `PORT=4001
5982
+ QUEUE_SERVICE_TYPE=redis
5983
+ REDIS_URL=redis://localhost:6379
5984
+ REDIS_PASSWORD=
5985
+ QUEUE_NAME=tasks`,
5986
+ rows: 18,
5987
+ className: styles.textArea,
5988
+ style: {
5989
+ fontFamily: "SF Mono, Monaco, Inconsolata, Roboto Mono, monospace",
5990
+ fontSize: 13,
5991
+ padding: "16px",
5992
+ lineHeight: 1.6
5993
+ }
5994
+ }
5995
+ )
5996
+ ] });
5997
+ };
5998
+ const renderModelSettings = (serverId) => {
5999
+ const config = serverConfigs[serverId] || {
6000
+ envText: "",
6001
+ models: [
6002
+ {
6003
+ key: "",
6004
+ model: "",
6005
+ provider: "openai",
6006
+ streaming: false,
6007
+ apiKey: "",
6008
+ baseURL: ""
6009
+ }
6010
+ ]
6011
+ };
6012
+ const handleModelChange = (index, field, value) => {
6013
+ const newModels = [...config.models];
6014
+ newModels[index] = { ...newModels[index], [field]: value };
6015
+ setServerConfigs((prev) => ({
6016
+ ...prev,
6017
+ [serverId]: {
6018
+ ...prev[serverId],
6019
+ models: newModels
6020
+ }
6021
+ }));
6022
+ };
6023
+ const handleAddModel = () => {
6024
+ setServerConfigs((prev) => ({
6025
+ ...prev,
6026
+ [serverId]: {
6027
+ ...prev[serverId],
6028
+ models: [
6029
+ ...config.models,
6030
+ {
6031
+ key: "",
6032
+ model: "",
6033
+ provider: "openai",
6034
+ streaming: false,
6035
+ apiKey: "",
6036
+ baseURL: ""
6037
+ }
6038
+ ]
6039
+ }
6040
+ }));
6041
+ };
6042
+ const handleRemoveModel = (index) => {
6043
+ if (config.models.length > 1) {
6044
+ setServerConfigs((prev) => ({
6045
+ ...prev,
6046
+ [serverId]: {
6047
+ ...prev[serverId],
6048
+ models: config.models.filter((_, i) => i !== index)
6049
+ }
6050
+ }));
6051
+ }
6052
+ };
6053
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.formContainer, children: [
6054
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { style: { marginBottom: 32 }, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(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." }) }),
6055
+ config.models.map((model, index) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.card, children: [
6056
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
6057
+ "div",
6058
+ {
6059
+ style: {
6060
+ display: "flex",
6061
+ justifyContent: "space-between",
6062
+ alignItems: "center",
6063
+ marginBottom: 24,
6064
+ paddingBottom: 20,
6065
+ borderBottom: "1px solid rgba(0, 0, 0, 0.06)"
6066
+ },
6067
+ children: [
6068
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6069
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(Text11, { strong: true, style: { fontSize: 16 }, children: [
6070
+ "Model ",
6071
+ index + 1
6072
+ ] }),
6073
+ model.key && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
6074
+ Text11,
6075
+ {
6076
+ type: "secondary",
6077
+ style: { marginLeft: 8, fontSize: 12 },
6078
+ children: [
6079
+ "(",
6080
+ model.key,
6081
+ ")"
6082
+ ]
6083
+ }
6084
+ )
6085
+ ] }),
6086
+ config.models.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6087
+ import_antd24.Button,
6088
+ {
6089
+ type: "text",
6090
+ danger: true,
6091
+ size: "small",
6092
+ onClick: () => handleRemoveModel(index),
6093
+ style: {
6094
+ borderRadius: 6,
6095
+ transition: "all 0.2s"
6096
+ },
6097
+ children: "Remove"
6098
+ }
6099
+ )
6100
+ ]
6101
+ }
6102
+ ),
6103
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_antd24.Space, { direction: "vertical", style: { width: "100%" }, size: "large", children: [
6104
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6105
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formLabel, children: "Key *" }),
6106
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6107
+ import_antd24.Input,
6108
+ {
6109
+ placeholder: "e.g., default, gpt-4, claude",
6110
+ value: model.key,
6111
+ onChange: (e) => handleModelChange(index, "key", e.target.value),
6112
+ style: { height: 40 }
6113
+ }
6114
+ ),
6115
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formDescription, children: "Unique identifier for this model" })
6116
+ ] }),
6117
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6118
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formLabel, children: "Provider *" }),
6119
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6120
+ import_antd24.Select,
6121
+ {
6122
+ style: { width: "100%", height: 40 },
6123
+ value: model.provider,
6124
+ onChange: (value) => handleModelChange(index, "provider", value),
6125
+ options: [
6126
+ { label: "OpenAI", value: "openai" },
6127
+ { label: "Azure", value: "azure" },
6128
+ { label: "DeepSeek", value: "deepseek" },
6129
+ { label: "SiliconCloud", value: "siliconcloud" },
6130
+ { label: "VolcEngine", value: "volcengine" }
6131
+ ]
6132
+ }
6133
+ )
6134
+ ] }),
6135
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6136
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formLabel, children: "Model Name *" }),
6137
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6138
+ import_antd24.Input,
6139
+ {
6140
+ placeholder: "e.g., gpt-4, claude-3-opus, kimi-k2-250905",
6141
+ value: model.model,
6142
+ onChange: (e) => handleModelChange(index, "model", e.target.value),
6143
+ style: { height: 40 }
6144
+ }
6145
+ )
6146
+ ] }),
6147
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6148
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formLabel, children: "API Key" }),
6149
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6150
+ import_antd24.Input.Password,
6151
+ {
6152
+ placeholder: "Enter your API key",
6153
+ value: model.apiKey,
6154
+ onChange: (e) => handleModelChange(index, "apiKey", e.target.value),
6155
+ style: { height: 40 }
6156
+ }
6157
+ ),
6158
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formDescription, children: "API key for the model provider. Leave empty to use environment variable." })
6159
+ ] }),
6160
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6161
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formLabel, children: "Base URL" }),
6162
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6163
+ import_antd24.Input,
6164
+ {
6165
+ placeholder: "e.g., https://api.openai.com/v1",
6166
+ value: model.baseURL,
6167
+ onChange: (e) => handleModelChange(index, "baseURL", e.target.value),
6168
+ style: { height: 40 }
6169
+ }
6170
+ ),
6171
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formDescription, children: "Optional custom base URL for the API" })
6172
+ ] }),
6173
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_antd24.Space, { children: [
6174
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6175
+ import_antd24.Switch,
6176
+ {
6177
+ checked: model.streaming,
6178
+ onChange: (checked) => handleModelChange(index, "streaming", checked)
6179
+ }
6180
+ ),
6181
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { children: "Enable Streaming" })
6182
+ ] }) }),
6183
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", gap: 20 }, children: [
6184
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { flex: 1 }, children: [
6185
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formLabel, children: "Max Tokens" }),
6186
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6187
+ import_antd24.Input,
6188
+ {
6189
+ type: "number",
6190
+ placeholder: "e.g., 4096",
6191
+ value: model.maxTokens,
6192
+ onChange: (e) => handleModelChange(
6193
+ index,
6194
+ "maxTokens",
6195
+ e.target.value ? Number(e.target.value) : void 0
6196
+ ),
6197
+ style: { height: 40 }
6198
+ }
6199
+ )
6200
+ ] }),
6201
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { flex: 1 }, children: [
6202
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { className: styles.formLabel, children: "Temperature" }),
6203
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6204
+ import_antd24.Input,
6205
+ {
6206
+ type: "number",
6207
+ step: "0.1",
6208
+ placeholder: "e.g., 0.7",
6209
+ value: model.temperature,
6210
+ onChange: (e) => handleModelChange(
6211
+ index,
6212
+ "temperature",
6213
+ e.target.value ? Number(e.target.value) : void 0
6214
+ ),
6215
+ style: { height: 40 }
6216
+ }
6217
+ )
6218
+ ] })
6219
+ ] })
6220
+ ] })
6221
+ ] }, index)),
6222
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6223
+ import_antd24.Button,
6224
+ {
6225
+ type: "dashed",
6226
+ onClick: handleAddModel,
6227
+ block: true,
6228
+ size: "large",
6229
+ style: { marginTop: 24, height: 48 },
6230
+ children: "+ Add Model"
6231
+ }
6232
+ )
6233
+ ] });
6234
+ };
6235
+ const renderContent = (serverId) => {
6236
+ switch (activeMenu) {
6237
+ case "environment":
6238
+ return renderEnvironmentSettings(serverId);
6239
+ case "models":
6240
+ return renderModelSettings(serverId);
6241
+ default:
6242
+ return null;
6243
+ }
6244
+ };
6245
+ const activeMenuItem = SETTINGS_MENU_ITEMS.find(
6246
+ (item) => item.key === activeMenu
6247
+ );
6248
+ const currentConnection = connections.find((c) => c.id === activeTabKey);
6249
+ const renderTabLabel = (connection) => {
6250
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", alignItems: "center" }, children: [
6251
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6252
+ import_icons13.CloudServerOutlined,
6253
+ {
6254
+ style: {
6255
+ marginRight: 8,
6256
+ color: connection.connected ? "#52c41a" : connection.connecting ? "#1890ff" : "#d9d9d9"
6257
+ }
6258
+ }
6259
+ ),
6260
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { children: connection.name }),
6261
+ connection.connected && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6262
+ import_icons13.CheckCircleFilled,
6263
+ {
6264
+ style: { color: "#52c41a", fontSize: 12, marginLeft: 8 }
6265
+ }
6266
+ ),
6267
+ connection.error && !connection.connecting && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6268
+ import_icons13.CloseCircleFilled,
6269
+ {
6270
+ style: { color: "#ff4d4f", fontSize: 12, marginLeft: 8 }
6271
+ }
6272
+ )
6273
+ ] });
6274
+ };
6275
+ const tabItems = connections.map((connection) => ({
6276
+ key: connection.id,
6277
+ label: renderTabLabel(connection),
6278
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: styles.tabContent, children: connection.connected ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_jsx_runtime37.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", height: "100%" }, children: [
6279
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: styles.sidebar, children: SETTINGS_MENU_ITEMS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
6280
+ "div",
6281
+ {
6282
+ className: `${styles.menuItem} ${activeMenu === item.key ? "active" : ""}`,
6283
+ onClick: () => setActiveMenu(item.key),
6284
+ children: [
6285
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: styles.menuItemIcon, children: item.icon }),
6286
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: styles.menuItemText, children: item.label })
6287
+ ]
6288
+ },
6289
+ item.key
6290
+ )) }),
6291
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.content, children: [
6292
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.contentHeader, children: [
6293
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.contentHeaderLeft, children: [
6294
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Title2, { level: 3, className: styles.contentTitle, children: activeMenuItem?.label }),
6295
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(Text11, { className: styles.contentDescription, children: [
6296
+ activeMenu === "environment" && "Manage environment variables for the gateway server",
6297
+ activeMenu === "models" && "Configure and register model lattices for use by agents"
6298
+ ] })
6299
+ ] }),
6300
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.contentHeaderRight, children: [
6301
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_antd24.Button, { onClick: onClose, children: "Cancel" }),
6302
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6303
+ import_antd24.Button,
6304
+ {
6305
+ type: "primary",
6306
+ icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons13.SaveOutlined, {}),
6307
+ onClick: handleSave,
6308
+ loading,
6309
+ children: "Save Configuration"
6310
+ }
6311
+ )
6312
+ ] })
6313
+ ] }),
6314
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: styles.contentBody, children: renderContent(connection.id) })
6315
+ ] })
6316
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6317
+ "div",
6318
+ {
6319
+ style: {
6320
+ flex: 1,
6321
+ display: "flex",
6322
+ alignItems: "center",
6323
+ justifyContent: "center",
6324
+ flexDirection: "column",
6325
+ gap: 16,
6326
+ padding: 48
6327
+ },
6328
+ children: connection.connecting ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
6329
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons13.LinkOutlined, { style: { fontSize: 64, color: "#1890ff" }, spin: true }),
6330
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Title2, { level: 4, children: "Connecting..." }),
6331
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(Text11, { type: "secondary", style: { textAlign: "center" }, children: [
6332
+ "Connecting to ",
6333
+ connection.url
6334
+ ] })
6335
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
6336
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons13.LinkOutlined, { style: { fontSize: 64, color: "#d9d9d9" } }),
6337
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Title2, { level: 4, type: "secondary", children: connection.error || "Not Connected" }),
6338
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6339
+ Text11,
6340
+ {
6341
+ type: "secondary",
6342
+ style: { textAlign: "center", maxWidth: 400 },
6343
+ children: connection.error ? `Failed to connect to ${connection.url}. Please check the server URL and try again.` : `Click "Reconnect" to connect to ${connection.url}`
6344
+ }
6345
+ ),
6346
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6347
+ import_antd24.Button,
6348
+ {
6349
+ type: "primary",
6350
+ icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons13.LinkOutlined, {}),
6351
+ onClick: () => checkConnection(connection.id),
6352
+ loading: connection.connecting,
6353
+ style: { marginTop: 16 },
6354
+ children: "Reconnect"
6355
+ }
6356
+ )
6357
+ ] })
6358
+ }
6359
+ ) }),
6360
+ closable: connections.length > 1
6361
+ }));
6362
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
6363
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6364
+ import_antd24.Drawer,
6365
+ {
6366
+ open,
6367
+ onClose,
6368
+ footer: null,
6369
+ width: "100%",
6370
+ title: "Settings",
6371
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6372
+ import_antd24.Tabs,
6373
+ {
6374
+ activeKey: activeTabKey,
6375
+ onChange: setActiveTabKey,
6376
+ type: "editable-card",
6377
+ onEdit: (targetKey, action) => {
6378
+ if (action === "add") {
6379
+ setShowAddServerModal(true);
6380
+ } else if (action === "remove") {
6381
+ handleDeleteServer(targetKey);
6382
+ }
6383
+ },
6384
+ items: tabItems,
6385
+ addIcon: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
6386
+ "div",
6387
+ {
6388
+ style: {
6389
+ display: "flex",
6390
+ alignItems: "center",
6391
+ gap: 4,
6392
+ padding: "4px 8px"
6393
+ },
6394
+ children: [
6395
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons13.PlusOutlined, {}),
6396
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { children: "Add Server" })
6397
+ ]
6398
+ }
6399
+ )
6400
+ }
6401
+ ) })
6402
+ }
6403
+ ),
6404
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6405
+ import_antd24.Modal,
6406
+ {
6407
+ title: "Add New Server",
6408
+ open: showAddServerModal,
6409
+ onOk: handleAddServer,
6410
+ onCancel: () => {
6411
+ setShowAddServerModal(false);
6412
+ setNewServerUrl("");
6413
+ setNewServerName("");
6414
+ setNewServerApiKey("");
6415
+ },
6416
+ confirmLoading: addingServer,
6417
+ className: styles.addServerModal,
6418
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_antd24.Space, { direction: "vertical", style: { width: "100%" }, size: "large", children: [
6419
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6420
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "Server Name" }),
6421
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6422
+ import_antd24.Input,
6423
+ {
6424
+ placeholder: "e.g., Production Server",
6425
+ value: newServerName,
6426
+ onChange: (e) => setNewServerName(e.target.value),
6427
+ onPressEnter: handleAddServer
6428
+ }
6429
+ ),
6430
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Optional: Leave empty to use URL as name" })
6431
+ ] }),
6432
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6433
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "Server URL *" }),
6434
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6435
+ import_antd24.Input,
6436
+ {
6437
+ placeholder: "e.g., http://localhost:4001",
6438
+ value: newServerUrl,
6439
+ onChange: (e) => setNewServerUrl(e.target.value),
6440
+ onPressEnter: handleAddServer
6441
+ }
6442
+ ),
6443
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Enter the full URL of the gateway server" })
6444
+ ] }),
6445
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6446
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "API Key" }),
6447
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6448
+ import_antd24.Input.Password,
6449
+ {
6450
+ placeholder: "Optional: Enter API key for authentication",
6451
+ value: newServerApiKey,
6452
+ onChange: (e) => setNewServerApiKey(e.target.value),
6453
+ onPressEnter: handleAddServer
6454
+ }
6455
+ ),
6456
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Optional: API key for server authentication" })
6457
+ ] })
6458
+ ] })
6459
+ }
6460
+ )
6461
+ ] });
6462
+ };
6463
+
6464
+ // src/components/Chat/ChatSidebar.tsx
6465
+ var import_jsx_runtime38 = require("react/jsx-runtime");
6466
+ var useStyles4 = (0, import_antd_style11.createStyles)(({ token, css }) => ({
6467
+ sidebar: css`
6468
+ display: flex;
6469
+ flex-direction: column;
6470
+ height: 100%;
6471
+ width: 100%;
6472
+ position: relative;
6473
+ background: transparent;
6474
+ border-radius: ${token.borderRadiusLG}px;
6475
+ overflow: hidden;
6476
+ `,
6477
+ content: css`
6478
+ flex: 1;
6479
+ overflow-y: auto;
6480
+ overflow-x: hidden;
6481
+ padding: ${token.paddingMD}px ${token.paddingSM}px;
6482
+ padding-bottom: ${token.paddingLG}px;
6483
+
6484
+ /* Custom scrollbar styling */
6485
+ &::-webkit-scrollbar {
6486
+ width: 6px;
6487
+ }
6488
+
6489
+ &::-webkit-scrollbar-track {
6490
+ background: transparent;
6491
+ }
6492
+
6493
+ &::-webkit-scrollbar-thumb {
6494
+ background: ${token.colorBorder};
6495
+ border-radius: 3px;
6496
+
6497
+ &:hover {
6498
+ background: ${token.colorBorderSecondary};
6499
+ }
6500
+ }
6501
+ `,
6502
+ section: css`
6503
+ margin-bottom: ${token.marginLG}px;
6504
+
6505
+ &:last-child {
6506
+ margin-bottom: 0;
6507
+ }
6508
+ `,
6509
+ sectionTitle: css`
6510
+ font-size: ${token.fontSizeSM}px;
6511
+ font-weight: 600;
6512
+ color: ${token.colorTextSecondary};
6513
+ text-transform: uppercase;
6514
+ letter-spacing: 0.5px;
6515
+ padding: 0 ${token.paddingXS}px;
6516
+ margin-bottom: ${token.marginSM}px;
6517
+ `,
6518
+ footer: css`
6519
+ display: flex;
6520
+ justify-content: center;
6521
+ align-items: center;
6522
+ padding: ${token.paddingSM}px;
6523
+ background: transparent;
6524
+ border-top: 1px solid ${token.colorBorderSecondary};
6525
+ gap: ${token.marginXS}px;
6526
+ flex-shrink: 0;
6527
+ position: relative;
6528
+
6529
+ &::before {
6530
+ content: "";
6531
+ position: absolute;
6532
+ top: 0;
6533
+ left: 0;
6534
+ right: 0;
6535
+ height: 1px;
6536
+ background: linear-gradient(
6537
+ 90deg,
6538
+ transparent,
6539
+ ${token.colorBorder},
6540
+ transparent
6541
+ );
6542
+ }
6543
+ `,
6544
+ actionButton: css`
6545
+ display: flex;
6546
+ align-items: center;
6547
+ justify-content: center;
6548
+ width: 36px;
6549
+ height: 36px;
6550
+ border-radius: ${token.borderRadius}px;
6551
+ border: none;
6552
+ background: ${token.colorBgContainer};
6553
+ color: ${token.colorTextSecondary};
6554
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
6555
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
6556
+
6557
+ &:hover {
6558
+ background: ${token.colorPrimaryBg};
6559
+ color: ${token.colorPrimary};
6560
+ transform: translateY(-1px);
6561
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.08);
6562
+ }
6563
+
6564
+ &:active {
6565
+ transform: translateY(0);
6566
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
6567
+ }
6568
+
6569
+ .anticon {
6570
+ font-size: 16px;
6571
+ }
6572
+ `,
6573
+ divider: css`
6574
+ margin: ${token.marginMD}px 0;
6575
+ border-color: ${token.colorBorderSecondary};
6576
+ `
6577
+ }));
6578
+ var ChatSidebar = ({
6579
+ onSettingsClick,
6580
+ defaultCollapsed = false
6581
+ }) => {
6582
+ const { styles } = useStyles4();
6583
+ const { setMenuCollapsed, menuCollapsed } = useChatUIContext();
6584
+ const [settingsModalOpen, setSettingsModalOpen] = (0, import_react24.useState)(false);
6585
+ const handleToggleCollapse = () => {
6586
+ setMenuCollapsed(!menuCollapsed);
6587
+ };
6588
+ const handleSettingsClick = () => {
6589
+ setSettingsModalOpen(true);
6590
+ onSettingsClick?.();
6591
+ };
6592
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
6593
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: styles.sidebar, children: [
6594
+ !menuCollapsed && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: styles.content, children: [
6595
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: styles.section, children: [
6596
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: styles.sectionTitle, children: "Assistants" }),
6597
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(AssistantList, {})
6598
+ ] }),
6599
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_antd25.Divider, { className: styles.divider }),
6600
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: styles.section, children: [
6601
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: styles.sectionTitle, children: "Threads" }),
6602
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(AgentConversations, {})
6603
+ ] })
6604
+ ] }),
6605
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: styles.footer, children: [
6606
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
6607
+ "button",
6608
+ {
6609
+ className: styles.actionButton,
6610
+ onClick: handleToggleCollapse,
6611
+ title: menuCollapsed ? "Expand sidebar" : "Collapse sidebar",
6612
+ "aria-label": menuCollapsed ? "Expand sidebar" : "Collapse sidebar",
6613
+ children: menuCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_icons14.MenuUnfoldOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_icons14.MenuFoldOutlined, {})
6614
+ }
6615
+ ),
6616
+ !menuCollapsed && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
6617
+ "button",
6618
+ {
6619
+ className: styles.actionButton,
6620
+ onClick: handleSettingsClick,
6621
+ title: "Settings",
6622
+ "aria-label": "Settings",
6623
+ children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_icons14.SettingOutlined, {})
6624
+ }
6625
+ )
6626
+ ] })
6627
+ ] }),
6628
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
6629
+ SettingsModal,
6630
+ {
6631
+ open: settingsModalOpen,
6632
+ onClose: () => setSettingsModalOpen(false)
6633
+ }
6634
+ )
6635
+ ] });
6636
+ };
6637
+
6638
+ // src/components/Chat/LatticeChatView.tsx
6639
+ var import_jsx_runtime39 = require("react/jsx-runtime");
6640
+ var LatticeChatView = (props) => {
6641
+ const { assistantId, thread } = useConversationContext();
6642
+ const { currentAssistant } = useAssistantContext();
6643
+ const {
6644
+ config: { baseURL }
6645
+ } = useLatticeChatShellContext();
6646
+ return assistantId && thread ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6647
+ AxiomLatticeProvider,
6648
+ {
6649
+ config: {
6650
+ baseURL,
6651
+ apiKey: "",
6652
+ assistantId,
6653
+ transport: "sse"
6654
+ },
6655
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6656
+ LatticeChat,
6657
+ {
6658
+ thread_id: thread?.id,
6659
+ assistant_id: assistantId,
6660
+ name: currentAssistant?.name,
6661
+ description: currentAssistant?.description,
6662
+ menu: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ChatSidebar, {})
6663
+ }
6664
+ )
6665
+ }
6666
+ ) : null;
6667
+ };
6668
+
6669
+ // src/components/Chat/LatticeChatShell.tsx
6670
+ var import_jsx_runtime40 = require("react/jsx-runtime");
6671
+ var LatticeChatShell = (props) => {
6672
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(LatticeChatShellContextProvider, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(AssistantContextProvider, { autoLoad: true, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ConversationContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(LatticeChatView, {}) }) }) });
6673
+ };
4409
6674
  // Annotate the CommonJS export names for ESM import in node:
4410
6675
  0 && (module.exports = {
6676
+ AgentConversations,
4411
6677
  AgentThreadProvider,
6678
+ AssistantContext,
6679
+ AssistantContextProvider,
4412
6680
  AxiomLatticeProvider,
4413
6681
  ChatUIContext,
4414
6682
  ChatUIContextProvider,
4415
6683
  Chating,
4416
6684
  ColumnLayout,
6685
+ ConversationContext,
6686
+ ConversationContextProvider,
4417
6687
  FileExplorer,
4418
6688
  LatticeChat,
6689
+ LatticeChatShell,
6690
+ LatticeChatShellContext,
6691
+ LatticeChatShellContextProvider,
4419
6692
  MDMermaid,
4420
6693
  MDResponse,
4421
6694
  MDViewFormItem,
@@ -4426,10 +6699,12 @@ var import_jsx_runtime32 = require("react/jsx-runtime");
4426
6699
  useAgentGraph,
4427
6700
  useAgentState,
4428
6701
  useAgentThreadContext,
6702
+ useAssistantContext,
4429
6703
  useAxiomLattice,
4430
6704
  useChat,
4431
6705
  useChatUIContext,
4432
- useThread,
6706
+ useConversationContext,
6707
+ useLatticeChatShellContext,
4433
6708
  ...require("@axiom-lattice/protocols")
4434
6709
  });
4435
6710
  //# sourceMappingURL=index.js.map