@axiom-lattice/react-sdk 2.1.12 → 2.1.14

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
@@ -198,7 +198,7 @@ function useChat(threadId, options = {}) {
198
198
  stopStreamingRef.current = null;
199
199
  }
200
200
  const { input, command, streaming = true } = data;
201
- const { message: message4, files, ...rest } = input || {};
201
+ const { message: message5, files, ...rest } = input || {};
202
202
  setState((prev) => ({
203
203
  ...prev,
204
204
  isLoading: true,
@@ -207,7 +207,7 @@ function useChat(threadId, options = {}) {
207
207
  }));
208
208
  const userMessage = {
209
209
  id: Date.now().toString(),
210
- content: message4 || command?.resume?.message || "",
210
+ content: message5 || command?.resume?.message || "",
211
211
  files,
212
212
  role: "human"
213
213
  };
@@ -536,7 +536,7 @@ function AgentThreadProvider({
536
536
  stopStreamingRef.current = null;
537
537
  }
538
538
  const { input, command, streaming = true } = data;
539
- const { message: message4, files, ...rest } = input || {};
539
+ const { message: message5, files, ...rest } = input || {};
540
540
  setState((prev) => ({
541
541
  ...prev,
542
542
  isLoading: true,
@@ -544,7 +544,7 @@ function AgentThreadProvider({
544
544
  }));
545
545
  const userMessage = {
546
546
  id: Date.now().toString(),
547
- content: message4 || command?.resume?.message || "",
547
+ content: message5 || command?.resume?.message || "",
548
548
  files,
549
549
  role: "human"
550
550
  };
@@ -1610,11 +1610,11 @@ var ConfirmFeedback = ({
1610
1610
  data,
1611
1611
  interactive = true
1612
1612
  }) => {
1613
- const { message: message4, type, config, feedback, options } = data ?? {};
1613
+ const { message: message5, type, config, feedback, options } = data ?? {};
1614
1614
  const { sendMessage } = useAgentChat();
1615
1615
  const [clicked, setClicked] = (0, import_react9.useState)(false);
1616
1616
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_antd.Space, { direction: "vertical", style: { width: "100%" }, children: [
1617
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MDResponse, { content: message4 }),
1617
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MDResponse, { content: message5 }),
1618
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)(
1619
1619
  import_antd.Button,
1620
1620
  {
@@ -1696,7 +1696,7 @@ var import_icons = require("@ant-design/icons");
1696
1696
  var import_jsx_runtime8 = require("react/jsx-runtime");
1697
1697
  var { Text: Text2 } = import_antd2.Typography;
1698
1698
  var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = true }) => {
1699
- const { dataSource, message: message4 } = data ?? {};
1699
+ const { dataSource, message: message5 } = data ?? {};
1700
1700
  const [expandedRowKeys, setExpandedRowKeys] = (0, import_react10.useState)([]);
1701
1701
  const { openSideApp } = useChatUIContext();
1702
1702
  const processedData = dataSource?.map((item, index) => ({
@@ -1780,7 +1780,7 @@ var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = t
1780
1780
  {
1781
1781
  size: "small",
1782
1782
  title: () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_antd2.Flex, { justify: "space-between", align: "center", children: [
1783
- /* @__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 || "" }) }),
1784
1784
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_antd2.Space, { children: [
1785
1785
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1786
1786
  import_antd2.Button,
@@ -1801,8 +1801,8 @@ var GenericDataTable = ({ data, interactive = true, default_open_in_side_app = t
1801
1801
  onClick: () => {
1802
1802
  openSideApp({
1803
1803
  component_key: "generic_data_table",
1804
- message: message4 || "",
1805
- data: { dataSource, message: message4 }
1804
+ message: message5 || "",
1805
+ data: { dataSource, message: message5 }
1806
1806
  });
1807
1807
  },
1808
1808
  children: [
@@ -2707,7 +2707,7 @@ var AttachmentsCard = ({
2707
2707
  columns = 1,
2708
2708
  showDownloadButton = false
2709
2709
  }) => {
2710
- const { Text: Text11 } = import_antd8.Typography;
2710
+ const { Text: Text12 } = import_antd8.Typography;
2711
2711
  const [showAll, setShowAll] = (0, import_react12.useState)(false);
2712
2712
  const { openSideApp } = useChatUIContext();
2713
2713
  const getStyles = () => {
@@ -2782,7 +2782,7 @@ var AttachmentsCard = ({
2782
2782
  );
2783
2783
  };
2784
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)(
2785
- Text11,
2785
+ Text12,
2786
2786
  {
2787
2787
  type: "secondary",
2788
2788
  style: {
@@ -2854,7 +2854,7 @@ var AttachmentsCard = ({
2854
2854
  }
2855
2855
  ),
2856
2856
  item.files && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { paddingLeft: "12px" }, children: [
2857
- /* @__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: [
2858
2858
  "\u5305\u542B\u6587\u4EF6(",
2859
2859
  item.files.length,
2860
2860
  ")"
@@ -3504,7 +3504,7 @@ var import_ErrorBoundary = __toESM(require("antd/es/alert/ErrorBoundary"));
3504
3504
  var import_react15 = require("react");
3505
3505
  var import_jsx_runtime23 = require("react/jsx-runtime");
3506
3506
  var LazyBubble = ({
3507
- message: message4,
3507
+ message: message5,
3508
3508
  renderContent,
3509
3509
  autoLoadRightPanel
3510
3510
  }) => {
@@ -3535,10 +3535,10 @@ var LazyBubble = ({
3535
3535
  autoLoadRightPanel?.();
3536
3536
  }, []);
3537
3537
  const getPlaceholder = () => {
3538
- 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;
3539
3539
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { height: `${estimatedHeight}px`, minHeight: "50px" } });
3540
3540
  };
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(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() }) });
3542
3542
  };
3543
3543
  var MemoizedBubbleList = (0, import_react15.memo)(
3544
3544
  ({
@@ -3569,8 +3569,8 @@ var MessageList = ({
3569
3569
  messageLengthRef.current = messages?.length;
3570
3570
  }
3571
3571
  }, [messages?.length]);
3572
- const renderContent = (0, import_react15.useCallback)((message4) => {
3573
- const { content } = message4;
3572
+ const renderContent = (0, import_react15.useCallback)((message5) => {
3573
+ const { content } = message5;
3574
3574
  try {
3575
3575
  const json = JSON.parse(content);
3576
3576
  if (json.action && json.message) {
@@ -3578,7 +3578,7 @@ var MessageList = ({
3578
3578
  }
3579
3579
  } catch (error) {
3580
3580
  }
3581
- const tool_calls_md = message4.tool_calls?.map((tool_call) => {
3581
+ const tool_calls_md = message5.tool_calls?.map((tool_call) => {
3582
3582
  return `\`\`\`tool_call
3583
3583
  ${JSON.stringify(tool_call)}
3584
3584
  \`\`\``;
@@ -3587,17 +3587,17 @@ ${JSON.stringify(tool_call)}
3587
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 }) });
3588
3588
  }, []);
3589
3589
  const items = (0, import_react15.useMemo)(
3590
- () => messages.map((message4, index) => ({
3591
- key: message4.id,
3592
- role: message4.role,
3590
+ () => messages.map((message5, index) => ({
3591
+ key: message5.id,
3592
+ role: message5.role,
3593
3593
  typing: false,
3594
3594
  content: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3595
3595
  LazyBubble,
3596
3596
  {
3597
- message: message4,
3597
+ message: message5,
3598
3598
  renderContent,
3599
3599
  autoLoadRightPanel: () => {
3600
- const { content, role: role2 } = message4;
3600
+ const { content, role: role2 } = message5;
3601
3601
  const isNewAddedMessage = messageLengthRef.current > 1 && messageLengthRef.current + 1 === messages.length;
3602
3602
  if (index === messages.length - 1 && isNewAddedMessage && role2 === "ai") {
3603
3603
  try {
@@ -4412,6 +4412,9 @@ var LatticeChatShellContext = (0, import_react19.createContext)({
4412
4412
  updateConfigValue: () => {
4413
4413
  },
4414
4414
  resetConfig: () => {
4415
+ },
4416
+ settingsModalOpen: false,
4417
+ setSettingsModalOpen: () => {
4415
4418
  }
4416
4419
  });
4417
4420
  var LatticeChatShellContextProvider = ({
@@ -4435,6 +4438,7 @@ var LatticeChatShellContextProvider = ({
4435
4438
  return { ...DEFAULT_CONFIG, ...initialConfig };
4436
4439
  }, [persistToLocalStorage, localStorageKey, initialConfig]);
4437
4440
  const [config, setConfig] = (0, import_react19.useState)(loadInitialConfig);
4441
+ const [settingsModalOpen, setSettingsModalOpen] = (0, import_react19.useState)(false);
4438
4442
  const saveToLocalStorage = (0, import_react19.useCallback)(
4439
4443
  (newConfig) => {
4440
4444
  if (persistToLocalStorage && typeof window !== "undefined") {
@@ -4479,7 +4483,9 @@ var LatticeChatShellContextProvider = ({
4479
4483
  config,
4480
4484
  updateConfig,
4481
4485
  updateConfigValue,
4482
- resetConfig
4486
+ resetConfig,
4487
+ settingsModalOpen,
4488
+ setSettingsModalOpen
4483
4489
  },
4484
4490
  children
4485
4491
  }
@@ -4704,22 +4710,30 @@ var AssistantContextProvider = ({
4704
4710
  }
4705
4711
  }, [autoLoad, listAssistants]);
4706
4712
  (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
+ if (state.assistants.length > 0) {
4714
+ const isCurrentAssistantValid = state.currentAssistant && state.assistants.some((a) => a.id === state.currentAssistant?.id);
4715
+ if (!isCurrentAssistantValid) {
4716
+ if (initialAssistantId) {
4717
+ const assistant = state.assistants.find(
4718
+ (a) => a.id === initialAssistantId
4719
+ );
4720
+ if (assistant) {
4721
+ setState((prev) => ({
4722
+ ...prev,
4723
+ currentAssistant: assistant
4724
+ }));
4725
+ } else {
4726
+ setState((prev) => ({
4727
+ ...prev,
4728
+ currentAssistant: prev.assistants[0]
4729
+ }));
4730
+ }
4731
+ } else {
4713
4732
  setState((prev) => ({
4714
4733
  ...prev,
4715
- currentAssistant: assistant
4734
+ currentAssistant: prev.assistants[0]
4716
4735
  }));
4717
4736
  }
4718
- } else {
4719
- setState((prev) => ({
4720
- ...prev,
4721
- currentAssistant: prev.assistants[0]
4722
- }));
4723
4737
  }
4724
4738
  }
4725
4739
  }, [initialAssistantId, state.assistants, state.currentAssistant]);
@@ -5266,13 +5280,15 @@ var ChatSidebar = ({
5266
5280
  }) => {
5267
5281
  const { styles } = useStyles3();
5268
5282
  const { setMenuCollapsed, menuCollapsed } = useChatUIContext();
5283
+ const { setSettingsModalOpen } = useLatticeChatShellContext();
5269
5284
  const handleToggleCollapse = () => {
5270
5285
  setMenuCollapsed(!menuCollapsed);
5271
5286
  };
5272
5287
  const handleSettingsClick = () => {
5288
+ setSettingsModalOpen(true);
5273
5289
  onSettingsClick?.();
5274
5290
  };
5275
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.sidebar, children: [
5291
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_jsx_runtime37.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.sidebar, children: [
5276
5292
  !menuCollapsed && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.content, children: [
5277
5293
  /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: styles.section, children: [
5278
5294
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: styles.sectionTitle, children: "Assistants" }),
@@ -5306,7 +5322,7 @@ var ChatSidebar = ({
5306
5322
  }
5307
5323
  )
5308
5324
  ] })
5309
- ] });
5325
+ ] }) });
5310
5326
  };
5311
5327
 
5312
5328
  // src/components/Chat/LatticeChatView.tsx
@@ -5340,10 +5356,1347 @@ var LatticeChatView = (props) => {
5340
5356
  ) : null;
5341
5357
  };
5342
5358
 
5343
- // src/components/Chat/LatticeChatShell.tsx
5359
+ // src/components/Chat/SettingsModal.tsx
5360
+ var import_react23 = require("react");
5361
+ var import_antd25 = require("antd");
5362
+ var import_icons14 = require("@ant-design/icons");
5363
+ var import_antd_style11 = require("antd-style");
5344
5364
  var import_jsx_runtime39 = require("react/jsx-runtime");
5345
- var LatticeChatShell = (props) => {
5346
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LatticeChatShellContextProvider, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(AssistantContextProvider, { autoLoad: true, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ConversationContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LatticeChatView, {}) }) }) });
5365
+ var { Text: Text11, Title: Title2 } = import_antd25.Typography;
5366
+ var { TextArea } = import_antd25.Input;
5367
+ var useStyles4 = (0, import_antd_style11.createStyles)(({ token, css }) => ({
5368
+ // settingsModal: css`
5369
+ // .ant-modal {
5370
+ // max-width: 100vw !important;
5371
+ // width: 100vw !important;
5372
+ // margin: 0 !important;
5373
+ // top: 0 !important;
5374
+ // padding-bottom: 0 !important;
5375
+ // }
5376
+ // .ant-modal-content {
5377
+ // padding: 0;
5378
+ // height: 100vh;
5379
+ // max-height: 100vh;
5380
+ // border-radius: 0;
5381
+ // overflow: hidden;
5382
+ // width: 100%;
5383
+ // }
5384
+ // .ant-modal-body {
5385
+ // padding: 0;
5386
+ // height: 100%;
5387
+ // display: flex;
5388
+ // overflow: hidden;
5389
+ // width: 100%;
5390
+ // }
5391
+ // `,
5392
+ tabsContainer: css`
5393
+ height: 100vh;
5394
+ display: flex;
5395
+ flex-direction: column;
5396
+ overflow: hidden;
5397
+
5398
+ .ant-tabs {
5399
+ height: 100%;
5400
+ display: flex;
5401
+ flex-direction: column;
5402
+ }
5403
+
5404
+ .ant-tabs-content-holder {
5405
+ flex: 1;
5406
+ overflow: hidden;
5407
+ }
5408
+
5409
+ .ant-tabs-content {
5410
+ height: 100%;
5411
+ }
5412
+
5413
+ .ant-tabs-tabpane {
5414
+ height: 100%;
5415
+ overflow: hidden;
5416
+ }
5417
+
5418
+ .ant-tabs-nav {
5419
+ margin: 0;
5420
+ padding: 0 ${token.paddingLG}px;
5421
+ background: ${token.colorBgContainer};
5422
+ border-bottom: 1px solid ${token.colorBorder};
5423
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5424
+ }
5425
+
5426
+ .ant-tabs-tab {
5427
+ padding: ${token.paddingMD}px ${token.paddingLG}px;
5428
+ margin: ${token.paddingSM}px ${token.marginXS}px 0 0;
5429
+ border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0;
5430
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5431
+
5432
+ &:hover {
5433
+ background: ${token.colorFillTertiary};
5434
+ }
5435
+
5436
+ &.ant-tabs-tab-active {
5437
+ background: ${token.colorBgContainer};
5438
+ border-bottom-color: ${token.colorBgContainer};
5439
+ }
5440
+ }
5441
+ `,
5442
+ tabContent: css`
5443
+ height: 100%;
5444
+ display: flex;
5445
+ flex-direction: column;
5446
+ overflow: hidden;
5447
+ background: linear-gradient(
5448
+ 135deg,
5449
+ ${token.colorBgLayout} 0%,
5450
+ ${token.colorFillQuaternary} 100%
5451
+ );
5452
+ `,
5453
+ sidebar: css`
5454
+ width: 280px;
5455
+ background: linear-gradient(
5456
+ 180deg,
5457
+ ${token.colorBgContainer} 0%,
5458
+ ${token.colorFillQuaternary} 100%
5459
+ );
5460
+ border-right: 1px solid ${token.colorBorder};
5461
+ display: flex;
5462
+ flex-direction: column;
5463
+ overflow-y: auto;
5464
+ flex-shrink: 0;
5465
+ box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);
5466
+
5467
+ /* Custom scrollbar */
5468
+ &::-webkit-scrollbar {
5469
+ width: 8px;
5470
+ }
5471
+
5472
+ &::-webkit-scrollbar-track {
5473
+ background: transparent;
5474
+ }
5475
+
5476
+ &::-webkit-scrollbar-thumb {
5477
+ background: ${token.colorBorder};
5478
+ border-radius: 4px;
5479
+ transition: background 0.2s;
5480
+
5481
+ &:hover {
5482
+ background: ${token.colorBorderSecondary};
5483
+ }
5484
+ }
5485
+ `,
5486
+ sidebarHeader: css`
5487
+ padding: ${token.paddingXL}px ${token.paddingLG}px;
5488
+ border-bottom: 1px solid ${token.colorBorder};
5489
+ background: linear-gradient(
5490
+ 135deg,
5491
+ ${token.colorPrimaryBg} 0%,
5492
+ ${token.colorBgContainer} 100%
5493
+ );
5494
+ position: sticky;
5495
+ top: 0;
5496
+ z-index: 10;
5497
+ backdrop-filter: blur(10px);
5498
+ `,
5499
+ sidebarTitle: css`
5500
+ font-size: ${token.fontSizeXL}px;
5501
+ font-weight: 700;
5502
+ background: linear-gradient(
5503
+ 135deg,
5504
+ ${token.colorPrimary} 0%,
5505
+ ${token.colorPrimaryHover} 100%
5506
+ );
5507
+ -webkit-background-clip: text;
5508
+ -webkit-text-fill-color: transparent;
5509
+ background-clip: text;
5510
+ margin: 0;
5511
+ letter-spacing: -0.5px;
5512
+ `,
5513
+ menuItem: css`
5514
+ padding: ${token.paddingMD}px ${token.paddingLG}px;
5515
+ margin: ${token.marginXS}px ${token.paddingSM}px;
5516
+ cursor: pointer;
5517
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5518
+ border-radius: ${token.borderRadiusLG}px;
5519
+ display: flex;
5520
+ align-items: center;
5521
+ gap: ${token.marginMD}px;
5522
+ position: relative;
5523
+ overflow: hidden;
5524
+
5525
+ &::before {
5526
+ content: "";
5527
+ position: absolute;
5528
+ left: 0;
5529
+ top: 0;
5530
+ bottom: 0;
5531
+ width: 3px;
5532
+ background: ${token.colorPrimary};
5533
+ transform: scaleY(0);
5534
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5535
+ border-radius: 0 2px 2px 0;
5536
+ }
5537
+
5538
+ &:hover {
5539
+ background: ${token.colorFillTertiary};
5540
+ transform: translateX(4px);
5541
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
5542
+ }
5543
+
5544
+ &.active {
5545
+ background: linear-gradient(
5546
+ 135deg,
5547
+ ${token.colorPrimaryBg} 0%,
5548
+ ${token.colorFillTertiary} 100%
5549
+ );
5550
+ color: ${token.colorPrimary};
5551
+ box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
5552
+ transform: translateX(4px);
5553
+
5554
+ &::before {
5555
+ transform: scaleY(1);
5556
+ }
5557
+
5558
+ .menuItemIcon {
5559
+ transform: scale(1.1);
5560
+ }
5561
+ }
5562
+ `,
5563
+ menuItemIcon: css`
5564
+ font-size: 18px;
5565
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5566
+ display: flex;
5567
+ align-items: center;
5568
+ justify-content: center;
5569
+ width: 24px;
5570
+ height: 24px;
5571
+ `,
5572
+ menuItemText: css`
5573
+ font-size: ${token.fontSize}px;
5574
+ font-weight: 600;
5575
+ letter-spacing: 0.2px;
5576
+ `,
5577
+ content: css`
5578
+ flex: 1;
5579
+ display: flex;
5580
+ flex-direction: column;
5581
+ overflow: hidden;
5582
+ width: 100%;
5583
+ min-width: 0;
5584
+ `,
5585
+ contentHeader: css`
5586
+ padding: ${token.paddingLG}px ${token.paddingXL * 2}px;
5587
+ background: ${token.colorBgContainer};
5588
+ border-bottom: 1px solid ${token.colorBorder};
5589
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5590
+ position: sticky;
5591
+ top: 0;
5592
+ z-index: 5;
5593
+ backdrop-filter: blur(10px);
5594
+ display: flex;
5595
+ justify-content: space-between;
5596
+ align-items: center;
5597
+ gap: ${token.marginLG}px;
5598
+ `,
5599
+ contentHeaderLeft: css`
5600
+ flex: 1;
5601
+ `,
5602
+ contentHeaderRight: css`
5603
+ display: flex;
5604
+ gap: ${token.marginMD}px;
5605
+ flex-shrink: 0;
5606
+ `,
5607
+ contentTitle: css`
5608
+ font-size: ${token.fontSizeHeading3}px;
5609
+ font-weight: 700;
5610
+ color: ${token.colorTextHeading};
5611
+ margin: 0 0 ${token.marginSM}px 0;
5612
+ letter-spacing: -0.5px;
5613
+ `,
5614
+ contentDescription: css`
5615
+ color: ${token.colorTextSecondary};
5616
+ font-size: ${token.fontSize}px;
5617
+ margin: 0;
5618
+ line-height: 1.6;
5619
+ `,
5620
+ contentBody: css`
5621
+ flex: 1;
5622
+ overflow-y: auto;
5623
+ padding: ${token.paddingXL * 2}px ${token.paddingXL * 2}px;
5624
+ background: transparent;
5625
+
5626
+ /* Custom scrollbar */
5627
+ &::-webkit-scrollbar {
5628
+ width: 8px;
5629
+ }
5630
+
5631
+ &::-webkit-scrollbar-track {
5632
+ background: transparent;
5633
+ }
5634
+
5635
+ &::-webkit-scrollbar-thumb {
5636
+ background: ${token.colorBorder};
5637
+ border-radius: 4px;
5638
+ transition: background 0.2s;
5639
+
5640
+ &:hover {
5641
+ background: ${token.colorBorderSecondary};
5642
+ }
5643
+ }
5644
+ `,
5645
+ formContainer: css`
5646
+ width: 100%;
5647
+ max-width: 100%;
5648
+ `,
5649
+ formLabel: css`
5650
+ font-weight: 600;
5651
+ color: ${token.colorTextHeading};
5652
+ margin-bottom: ${token.marginMD}px;
5653
+ display: block;
5654
+ font-size: ${token.fontSize}px;
5655
+ `,
5656
+ formDescription: css`
5657
+ color: ${token.colorTextSecondary};
5658
+ font-size: ${token.fontSizeSM}px;
5659
+ margin-top: ${token.marginSM}px;
5660
+ line-height: 1.6;
5661
+ `,
5662
+ card: css`
5663
+ background: ${token.colorBgContainer};
5664
+ border: 1px solid ${token.colorBorder};
5665
+ border-radius: ${token.borderRadiusLG}px;
5666
+ padding: ${token.paddingXL}px;
5667
+ margin-bottom: ${token.marginLG}px;
5668
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5669
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5670
+
5671
+ &:hover {
5672
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
5673
+ transform: translateY(-2px);
5674
+ border-color: ${token.colorPrimary};
5675
+ }
5676
+ `,
5677
+ alertCard: css`
5678
+ border-radius: ${token.borderRadiusLG}px;
5679
+ margin-bottom: ${token.marginLG}px;
5680
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
5681
+ border: 1px solid ${token.colorBorder};
5682
+ `,
5683
+ textArea: css`
5684
+ border-radius: ${token.borderRadius}px;
5685
+ border: 1px solid ${token.colorBorder};
5686
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
5687
+
5688
+ &:hover {
5689
+ border-color: ${token.colorPrimaryHover};
5690
+ }
5691
+
5692
+ &:focus {
5693
+ border-color: ${token.colorPrimary};
5694
+ box-shadow: 0 0 0 2px ${token.colorPrimaryBg};
5695
+ }
5696
+ `,
5697
+ connectionStatus: css`
5698
+ display: flex;
5699
+ align-items: center;
5700
+ gap: ${token.marginXS}px;
5701
+ margin-left: ${token.marginSM}px;
5702
+ `,
5703
+ addServerModal: css`
5704
+ .ant-modal-body {
5705
+ padding: ${token.paddingXL}px;
5706
+ }
5707
+ `
5708
+ }));
5709
+ var SETTINGS_MENU_ITEMS = [
5710
+ {
5711
+ key: "environment",
5712
+ label: "Environment Variables",
5713
+ icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_icons14.EnvironmentOutlined, {})
5714
+ },
5715
+ {
5716
+ key: "models",
5717
+ label: "Model Configuration",
5718
+ icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_icons14.ApiOutlined, {})
5719
+ }
5720
+ ];
5721
+ var SettingsModal = ({
5722
+ open,
5723
+ onClose
5724
+ }) => {
5725
+ const { styles } = useStyles4();
5726
+ const { config: shellConfig, updateConfigValue } = useLatticeChatShellContext();
5727
+ const [connections, setConnections] = (0, import_react23.useState)(() => {
5728
+ if (typeof window !== "undefined") {
5729
+ try {
5730
+ const stored = localStorage.getItem("lattice_server_connections");
5731
+ if (stored) {
5732
+ const parsed = JSON.parse(stored);
5733
+ return parsed;
5734
+ }
5735
+ } catch (error) {
5736
+ console.warn("Failed to load connections from localStorage:", error);
5737
+ }
5738
+ }
5739
+ if (shellConfig.baseURL) {
5740
+ return [
5741
+ {
5742
+ id: "default",
5743
+ name: "Default",
5744
+ url: shellConfig.baseURL
5745
+ }
5746
+ ];
5747
+ }
5748
+ return [];
5749
+ });
5750
+ const [serverConfigs, setServerConfigs] = (0, import_react23.useState)({});
5751
+ const connectionsRef = (0, import_react23.useRef)(connections);
5752
+ (0, import_react23.useEffect)(() => {
5753
+ connectionsRef.current = connections;
5754
+ }, [connections]);
5755
+ const [activeTabKey, setActiveTabKey] = (0, import_react23.useState)(
5756
+ connections.length > 0 ? connections[0].id : ""
5757
+ );
5758
+ const [activeMenu, setActiveMenu] = (0, import_react23.useState)("environment");
5759
+ const [loading, setLoading] = (0, import_react23.useState)(false);
5760
+ const [showAddServerModal, setShowAddServerModal] = (0, import_react23.useState)(false);
5761
+ const [newServerUrl, setNewServerUrl] = (0, import_react23.useState)("");
5762
+ const [newServerName, setNewServerName] = (0, import_react23.useState)("");
5763
+ const [newServerApiKey, setNewServerApiKey] = (0, import_react23.useState)("");
5764
+ const [addingServer, setAddingServer] = (0, import_react23.useState)(false);
5765
+ const saveConnections = (newConnections) => {
5766
+ setConnections(newConnections);
5767
+ if (typeof window !== "undefined") {
5768
+ try {
5769
+ localStorage.setItem(
5770
+ "lattice_server_connections",
5771
+ JSON.stringify(newConnections)
5772
+ );
5773
+ } catch (error) {
5774
+ console.warn("Failed to save connections to localStorage:", error);
5775
+ }
5776
+ }
5777
+ };
5778
+ const initializeServerConfig = (serverId) => {
5779
+ if (!serverConfigs[serverId]) {
5780
+ setServerConfigs((prev) => ({
5781
+ ...prev,
5782
+ [serverId]: {
5783
+ envText: "",
5784
+ models: [
5785
+ {
5786
+ key: "",
5787
+ model: "",
5788
+ provider: "openai",
5789
+ streaming: false,
5790
+ apiKey: "",
5791
+ baseURL: ""
5792
+ }
5793
+ ]
5794
+ }
5795
+ }));
5796
+ }
5797
+ };
5798
+ const checkConnection = async (serverId) => {
5799
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5800
+ if (!connection) return;
5801
+ const url = connection.url;
5802
+ if (!url) {
5803
+ updateConnectionStatus(serverId, { connected: false });
5804
+ return;
5805
+ }
5806
+ try {
5807
+ updateConnectionStatus(serverId, { connecting: true, error: "" });
5808
+ const controller = new AbortController();
5809
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
5810
+ const headers = {};
5811
+ if (connection.apiKey) {
5812
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5813
+ }
5814
+ const response = await fetch(`${url}/api/config`, {
5815
+ method: "GET",
5816
+ signal: controller.signal,
5817
+ headers
5818
+ });
5819
+ clearTimeout(timeoutId);
5820
+ if (response.ok) {
5821
+ setConnections(
5822
+ (prev) => prev.map(
5823
+ (conn) => conn.id === serverId ? { ...conn, connected: true, connecting: false, error: "" } : { ...conn, connected: false, connecting: false }
5824
+ )
5825
+ );
5826
+ if (url !== shellConfig.baseURL) {
5827
+ updateConfigValue("baseURL", url);
5828
+ }
5829
+ } else {
5830
+ updateConnectionStatus(serverId, {
5831
+ connected: false,
5832
+ connecting: false,
5833
+ error: "Server returned an error"
5834
+ });
5835
+ }
5836
+ } catch (error) {
5837
+ if (error.name === "AbortError") {
5838
+ updateConnectionStatus(serverId, {
5839
+ connected: false,
5840
+ connecting: false,
5841
+ error: "Connection timeout"
5842
+ });
5843
+ } else {
5844
+ updateConnectionStatus(serverId, {
5845
+ connected: false,
5846
+ connecting: false,
5847
+ error: error.message || "Failed to connect to server"
5848
+ });
5849
+ }
5850
+ }
5851
+ };
5852
+ const updateConnectionStatus = (serverId, updates) => {
5853
+ setConnections(
5854
+ (prev) => prev.map(
5855
+ (conn) => conn.id === serverId ? { ...conn, ...updates } : conn
5856
+ )
5857
+ );
5858
+ };
5859
+ const loadCurrentConfig = async (serverId) => {
5860
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5861
+ if (!connection || !connection.connected) return;
5862
+ const url = connection.url;
5863
+ if (!url) return;
5864
+ try {
5865
+ const headers = {};
5866
+ if (connection.apiKey) {
5867
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5868
+ }
5869
+ const response = await fetch(`${url}/api/config`, {
5870
+ headers
5871
+ });
5872
+ if (response.ok) {
5873
+ const data = await response.json();
5874
+ if (data.success && data.data) {
5875
+ const lines = [];
5876
+ const configData = data.data;
5877
+ if (configData.port !== void 0) {
5878
+ lines.push(`PORT=${configData.port}`);
5879
+ }
5880
+ if (configData.queueServiceType) {
5881
+ lines.push(`QUEUE_SERVICE_TYPE=${configData.queueServiceType}`);
5882
+ }
5883
+ if (configData.redisUrl) {
5884
+ lines.push(`REDIS_URL=${configData.redisUrl}`);
5885
+ }
5886
+ if (configData.redisPassword) {
5887
+ lines.push(`REDIS_PASSWORD=`);
5888
+ }
5889
+ if (configData.queueName) {
5890
+ lines.push(`QUEUE_NAME=${configData.queueName}`);
5891
+ }
5892
+ setServerConfigs((prev) => ({
5893
+ ...prev,
5894
+ [serverId]: {
5895
+ ...prev[serverId],
5896
+ envText: lines.join("\n")
5897
+ }
5898
+ }));
5899
+ }
5900
+ }
5901
+ } catch (error) {
5902
+ console.error("Failed to load configuration:", error);
5903
+ import_antd25.message.error("Failed to load current configuration");
5904
+ }
5905
+ };
5906
+ const loadModelsConfig = async (serverId) => {
5907
+ const connection = connectionsRef.current.find((c) => c.id === serverId);
5908
+ if (!connection || !connection.connected) return;
5909
+ const url = connection.url;
5910
+ if (!url) return;
5911
+ try {
5912
+ const headers = {};
5913
+ if (connection.apiKey) {
5914
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
5915
+ }
5916
+ const response = await fetch(`${url}/api/models`, {
5917
+ headers
5918
+ });
5919
+ if (response.ok) {
5920
+ const data = await response.json();
5921
+ if (data.success && data.data && Array.isArray(data.data)) {
5922
+ if (data.data.length > 0) {
5923
+ setServerConfigs((prev) => ({
5924
+ ...prev,
5925
+ [serverId]: {
5926
+ ...prev[serverId],
5927
+ models: data.data
5928
+ }
5929
+ }));
5930
+ } else {
5931
+ setServerConfigs((prev) => ({
5932
+ ...prev,
5933
+ [serverId]: {
5934
+ ...prev[serverId],
5935
+ models: [
5936
+ {
5937
+ key: "",
5938
+ model: "",
5939
+ provider: "openai",
5940
+ streaming: false,
5941
+ apiKey: "",
5942
+ baseURL: ""
5943
+ }
5944
+ ]
5945
+ }
5946
+ }));
5947
+ }
5948
+ }
5949
+ }
5950
+ } catch (error) {
5951
+ console.error("Failed to load models configuration:", error);
5952
+ }
5953
+ };
5954
+ (0, import_react23.useEffect)(() => {
5955
+ if (open && activeTabKey) {
5956
+ initializeServerConfig(activeTabKey);
5957
+ const connection = connections.find((c) => c.id === activeTabKey);
5958
+ if (connection && !connection.connected && !connection.connecting) {
5959
+ checkConnection(activeTabKey);
5960
+ }
5961
+ }
5962
+ }, [open, activeTabKey]);
5963
+ (0, import_react23.useEffect)(() => {
5964
+ if (open && activeTabKey) {
5965
+ const connection = connections.find((c) => c.id === activeTabKey);
5966
+ if (connection?.connected) {
5967
+ if (activeMenu === "environment") {
5968
+ loadCurrentConfig(activeTabKey);
5969
+ } else if (activeMenu === "models") {
5970
+ loadModelsConfig(activeTabKey);
5971
+ }
5972
+ }
5973
+ }
5974
+ }, [open, activeTabKey, activeMenu]);
5975
+ const handleAddServer = async () => {
5976
+ if (!newServerUrl.trim()) {
5977
+ import_antd25.message.error("Please enter a server URL");
5978
+ return;
5979
+ }
5980
+ let normalizedUrl = newServerUrl.trim();
5981
+ if (!normalizedUrl.startsWith("http://") && !normalizedUrl.startsWith("https://")) {
5982
+ normalizedUrl = `http://${normalizedUrl}`;
5983
+ }
5984
+ const serverName = newServerName.trim() || normalizedUrl.replace(/^https?:\/\//, "");
5985
+ const newConnection = {
5986
+ id: `conn_${Date.now()}`,
5987
+ name: serverName,
5988
+ url: normalizedUrl,
5989
+ apiKey: newServerApiKey.trim() || void 0,
5990
+ connected: false
5991
+ };
5992
+ setAddingServer(true);
5993
+ const newConnections = [...connections, newConnection];
5994
+ saveConnections(newConnections);
5995
+ setActiveTabKey(newConnection.id);
5996
+ initializeServerConfig(newConnection.id);
5997
+ await checkConnection(newConnection.id);
5998
+ setAddingServer(false);
5999
+ setShowAddServerModal(false);
6000
+ setNewServerUrl("");
6001
+ setNewServerName("");
6002
+ setNewServerApiKey("");
6003
+ import_antd25.message.success("Server added successfully");
6004
+ };
6005
+ const handleDeleteServer = (serverId) => {
6006
+ const newConnections = connections.filter((c) => c.id !== serverId);
6007
+ saveConnections(newConnections);
6008
+ setServerConfigs((prev) => {
6009
+ const newConfigs = { ...prev };
6010
+ delete newConfigs[serverId];
6011
+ return newConfigs;
6012
+ });
6013
+ if (activeTabKey === serverId) {
6014
+ if (newConnections.length > 0) {
6015
+ setActiveTabKey(newConnections[0].id);
6016
+ } else {
6017
+ setActiveTabKey("");
6018
+ }
6019
+ }
6020
+ import_antd25.message.success("Server deleted");
6021
+ };
6022
+ const handleTabChange = (newTabKey) => {
6023
+ setConnections(
6024
+ (prev) => prev.map(
6025
+ (conn) => conn.id === newTabKey ? conn : { ...conn, connected: false, connecting: false }
6026
+ // Disconnect others
6027
+ )
6028
+ );
6029
+ setActiveTabKey(newTabKey);
6030
+ };
6031
+ const handleSave = async () => {
6032
+ const connection = connections.find((c) => c.id === activeTabKey);
6033
+ if (!connection || !connection.connected) {
6034
+ import_antd25.message.error("Please connect to a server first");
6035
+ return;
6036
+ }
6037
+ const url = connection.url;
6038
+ if (!url) {
6039
+ import_antd25.message.error("Please connect to a server first");
6040
+ return;
6041
+ }
6042
+ try {
6043
+ setLoading(true);
6044
+ const config = serverConfigs[activeTabKey];
6045
+ if (activeMenu === "environment") {
6046
+ const configObj = {};
6047
+ const lines = config.envText.split("\n");
6048
+ for (const line of lines) {
6049
+ const trimmedLine = line.trim();
6050
+ if (!trimmedLine || trimmedLine.startsWith("#")) {
6051
+ continue;
6052
+ }
6053
+ const equalIndex = trimmedLine.indexOf("=");
6054
+ if (equalIndex === -1) {
6055
+ continue;
6056
+ }
6057
+ const key = trimmedLine.substring(0, equalIndex).trim();
6058
+ const value = trimmedLine.substring(equalIndex + 1).trim();
6059
+ if (!key) {
6060
+ continue;
6061
+ }
6062
+ const upperKey = key.toUpperCase();
6063
+ if (upperKey === "PORT") {
6064
+ if (value) {
6065
+ configObj.port = Number(value);
6066
+ }
6067
+ } else if (upperKey === "QUEUE_SERVICE_TYPE") {
6068
+ if (value) {
6069
+ configObj.queueServiceType = value;
6070
+ }
6071
+ } else if (upperKey === "REDIS_URL") {
6072
+ if (value) {
6073
+ configObj.redisUrl = value;
6074
+ }
6075
+ } else if (upperKey === "REDIS_PASSWORD") {
6076
+ if (value) {
6077
+ configObj.redisPassword = value;
6078
+ }
6079
+ } else if (upperKey === "QUEUE_NAME") {
6080
+ if (value) {
6081
+ configObj.queueName = value;
6082
+ }
6083
+ } else {
6084
+ if (value) {
6085
+ configObj[key] = value;
6086
+ }
6087
+ }
6088
+ }
6089
+ const headers = {
6090
+ "Content-Type": "application/json"
6091
+ };
6092
+ if (connection.apiKey) {
6093
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
6094
+ }
6095
+ const response = await fetch(`${url}/api/config`, {
6096
+ method: "PUT",
6097
+ headers,
6098
+ body: JSON.stringify({ config: configObj })
6099
+ });
6100
+ const data = await response.json();
6101
+ if (response.ok && data.success) {
6102
+ if (data.requiresRestart && data.requiresRestart.length > 0) {
6103
+ import_antd25.message.warning(
6104
+ `Configuration saved. Please restart the server for ${data.requiresRestart.join(
6105
+ ", "
6106
+ )} to take effect.`,
6107
+ 5
6108
+ );
6109
+ } else {
6110
+ import_antd25.message.success("Configuration saved and applied successfully");
6111
+ }
6112
+ if (data.warnings && data.warnings.length > 0) {
6113
+ data.warnings.forEach((warning) => {
6114
+ import_antd25.message.warning(warning, 5);
6115
+ });
6116
+ }
6117
+ onClose();
6118
+ } else {
6119
+ import_antd25.message.error(data.error || "Failed to save configuration");
6120
+ }
6121
+ } else if (activeMenu === "models") {
6122
+ const validModels = config.models.filter(
6123
+ (m) => m.key && m.model && m.provider
6124
+ );
6125
+ const headers = {
6126
+ "Content-Type": "application/json"
6127
+ };
6128
+ if (connection.apiKey) {
6129
+ headers["Authorization"] = `Bearer ${connection.apiKey}`;
6130
+ }
6131
+ const response = await fetch(`${url}/api/models`, {
6132
+ method: "PUT",
6133
+ headers,
6134
+ body: JSON.stringify({ models: validModels })
6135
+ });
6136
+ const data = await response.json();
6137
+ if (response.ok && data.success) {
6138
+ import_antd25.message.success(
6139
+ "Model configuration saved and registered successfully"
6140
+ );
6141
+ onClose();
6142
+ } else {
6143
+ import_antd25.message.error(data.error || "Failed to save model configuration");
6144
+ }
6145
+ }
6146
+ } catch (error) {
6147
+ console.error("Failed to save configuration:", error);
6148
+ import_antd25.message.error(error.message || "Failed to save configuration");
6149
+ } finally {
6150
+ setLoading(false);
6151
+ }
6152
+ };
6153
+ const renderEnvironmentSettings = (serverId) => {
6154
+ const config = serverConfigs[serverId] || { envText: "", models: [] };
6155
+ const setEnvText = (text) => {
6156
+ setServerConfigs((prev) => ({
6157
+ ...prev,
6158
+ [serverId]: {
6159
+ ...prev[serverId],
6160
+ envText: text
6161
+ }
6162
+ }));
6163
+ };
6164
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.formContainer, children: [
6165
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6166
+ import_antd25.Alert,
6167
+ {
6168
+ message: "Configuration Effect",
6169
+ description: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6170
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { marginBottom: 8 }, children: [
6171
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6172
+ import_icons14.CheckCircleOutlined,
6173
+ {
6174
+ style: { color: "#52c41a", marginRight: 8 }
6175
+ }
6176
+ ),
6177
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("strong", { children: "Immediately effective:" }),
6178
+ " QUEUE_SERVICE_TYPE, REDIS_URL, REDIS_PASSWORD, QUEUE_NAME"
6179
+ ] }),
6180
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6181
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_icons14.ReloadOutlined, { style: { color: "#faad14", marginRight: 8 } }),
6182
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("strong", { children: "Requires restart:" }),
6183
+ " PORT (server must be restarted to change port)"
6184
+ ] })
6185
+ ] }),
6186
+ type: "info",
6187
+ showIcon: true,
6188
+ className: styles.alertCard
6189
+ }
6190
+ ),
6191
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { style: { marginBottom: 24 }, children: /* @__PURE__ */ (0, import_jsx_runtime39.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." }) }),
6192
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6193
+ TextArea,
6194
+ {
6195
+ value: config.envText,
6196
+ onChange: (e) => setEnvText(e.target.value),
6197
+ placeholder: `PORT=4001
6198
+ QUEUE_SERVICE_TYPE=redis
6199
+ REDIS_URL=redis://localhost:6379
6200
+ REDIS_PASSWORD=
6201
+ QUEUE_NAME=tasks`,
6202
+ rows: 18,
6203
+ className: styles.textArea,
6204
+ style: {
6205
+ fontFamily: "SF Mono, Monaco, Inconsolata, Roboto Mono, monospace",
6206
+ fontSize: 13,
6207
+ padding: "16px",
6208
+ lineHeight: 1.6
6209
+ }
6210
+ }
6211
+ )
6212
+ ] });
6213
+ };
6214
+ const renderModelSettings = (serverId) => {
6215
+ const config = serverConfigs[serverId] || {
6216
+ envText: "",
6217
+ models: [
6218
+ {
6219
+ key: "",
6220
+ model: "",
6221
+ provider: "openai",
6222
+ streaming: false,
6223
+ apiKey: "",
6224
+ baseURL: ""
6225
+ }
6226
+ ]
6227
+ };
6228
+ const handleModelChange = (index, field, value) => {
6229
+ const newModels = [...config.models];
6230
+ newModels[index] = { ...newModels[index], [field]: value };
6231
+ setServerConfigs((prev) => ({
6232
+ ...prev,
6233
+ [serverId]: {
6234
+ ...prev[serverId],
6235
+ models: newModels
6236
+ }
6237
+ }));
6238
+ };
6239
+ const handleAddModel = () => {
6240
+ setServerConfigs((prev) => ({
6241
+ ...prev,
6242
+ [serverId]: {
6243
+ ...prev[serverId],
6244
+ models: [
6245
+ ...config.models,
6246
+ {
6247
+ key: "",
6248
+ model: "",
6249
+ provider: "openai",
6250
+ streaming: false,
6251
+ apiKey: "",
6252
+ baseURL: ""
6253
+ }
6254
+ ]
6255
+ }
6256
+ }));
6257
+ };
6258
+ const handleRemoveModel = (index) => {
6259
+ if (config.models.length > 1) {
6260
+ setServerConfigs((prev) => ({
6261
+ ...prev,
6262
+ [serverId]: {
6263
+ ...prev[serverId],
6264
+ models: config.models.filter((_, i) => i !== index)
6265
+ }
6266
+ }));
6267
+ }
6268
+ };
6269
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.formContainer, children: [
6270
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { style: { marginBottom: 32 }, children: /* @__PURE__ */ (0, import_jsx_runtime39.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." }) }),
6271
+ config.models.map((model, index) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.card, children: [
6272
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
6273
+ "div",
6274
+ {
6275
+ style: {
6276
+ display: "flex",
6277
+ justifyContent: "space-between",
6278
+ alignItems: "center",
6279
+ marginBottom: 24,
6280
+ paddingBottom: 20,
6281
+ borderBottom: "1px solid rgba(0, 0, 0, 0.06)"
6282
+ },
6283
+ children: [
6284
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6285
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(Text11, { strong: true, style: { fontSize: 16 }, children: [
6286
+ "Model ",
6287
+ index + 1
6288
+ ] }),
6289
+ model.key && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
6290
+ Text11,
6291
+ {
6292
+ type: "secondary",
6293
+ style: { marginLeft: 8, fontSize: 12 },
6294
+ children: [
6295
+ "(",
6296
+ model.key,
6297
+ ")"
6298
+ ]
6299
+ }
6300
+ )
6301
+ ] }),
6302
+ config.models.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6303
+ import_antd25.Button,
6304
+ {
6305
+ type: "text",
6306
+ danger: true,
6307
+ size: "small",
6308
+ onClick: () => handleRemoveModel(index),
6309
+ style: {
6310
+ borderRadius: 6,
6311
+ transition: "all 0.2s"
6312
+ },
6313
+ children: "Remove"
6314
+ }
6315
+ )
6316
+ ]
6317
+ }
6318
+ ),
6319
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_antd25.Space, { direction: "vertical", style: { width: "100%" }, size: "large", children: [
6320
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6321
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formLabel, children: "Key *" }),
6322
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6323
+ import_antd25.Input,
6324
+ {
6325
+ placeholder: "e.g., default, gpt-4, claude",
6326
+ value: model.key,
6327
+ onChange: (e) => handleModelChange(index, "key", e.target.value),
6328
+ style: { height: 40 }
6329
+ }
6330
+ ),
6331
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formDescription, children: "Unique identifier for this model" })
6332
+ ] }),
6333
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6334
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formLabel, children: "Provider *" }),
6335
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6336
+ import_antd25.Select,
6337
+ {
6338
+ style: { width: "100%", height: 40 },
6339
+ value: model.provider,
6340
+ onChange: (value) => handleModelChange(index, "provider", value),
6341
+ options: [
6342
+ { label: "OpenAI", value: "openai" },
6343
+ { label: "Azure", value: "azure" },
6344
+ { label: "DeepSeek", value: "deepseek" },
6345
+ { label: "SiliconCloud", value: "siliconcloud" },
6346
+ { label: "VolcEngine", value: "volcengine" }
6347
+ ]
6348
+ }
6349
+ )
6350
+ ] }),
6351
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6352
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formLabel, children: "Model Name *" }),
6353
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6354
+ import_antd25.Input,
6355
+ {
6356
+ placeholder: "e.g., gpt-4, claude-3-opus, kimi-k2-250905",
6357
+ value: model.model,
6358
+ onChange: (e) => handleModelChange(index, "model", e.target.value),
6359
+ style: { height: 40 }
6360
+ }
6361
+ )
6362
+ ] }),
6363
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6364
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formLabel, children: "API Key" }),
6365
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6366
+ import_antd25.Input.Password,
6367
+ {
6368
+ placeholder: "Enter your API key",
6369
+ value: model.apiKey,
6370
+ onChange: (e) => handleModelChange(index, "apiKey", e.target.value),
6371
+ style: { height: 40 }
6372
+ }
6373
+ ),
6374
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formDescription, children: "API key for the model provider. Leave empty to use environment variable." })
6375
+ ] }),
6376
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6377
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formLabel, children: "Base URL" }),
6378
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6379
+ import_antd25.Input,
6380
+ {
6381
+ placeholder: "e.g., https://api.openai.com/v1",
6382
+ value: model.baseURL,
6383
+ onChange: (e) => handleModelChange(index, "baseURL", e.target.value),
6384
+ style: { height: 40 }
6385
+ }
6386
+ ),
6387
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formDescription, children: "Optional custom base URL for the API" })
6388
+ ] }),
6389
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_antd25.Space, { children: [
6390
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6391
+ import_antd25.Switch,
6392
+ {
6393
+ checked: model.streaming,
6394
+ onChange: (checked) => handleModelChange(index, "streaming", checked)
6395
+ }
6396
+ ),
6397
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { children: "Enable Streaming" })
6398
+ ] }) }),
6399
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { display: "flex", gap: 20 }, children: [
6400
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { flex: 1 }, children: [
6401
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formLabel, children: "Max Tokens" }),
6402
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6403
+ import_antd25.Input,
6404
+ {
6405
+ type: "number",
6406
+ placeholder: "e.g., 4096",
6407
+ value: model.maxTokens,
6408
+ onChange: (e) => handleModelChange(
6409
+ index,
6410
+ "maxTokens",
6411
+ e.target.value ? Number(e.target.value) : void 0
6412
+ ),
6413
+ style: { height: 40 }
6414
+ }
6415
+ )
6416
+ ] }),
6417
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { flex: 1 }, children: [
6418
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { className: styles.formLabel, children: "Temperature" }),
6419
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6420
+ import_antd25.Input,
6421
+ {
6422
+ type: "number",
6423
+ step: "0.1",
6424
+ placeholder: "e.g., 0.7",
6425
+ value: model.temperature,
6426
+ onChange: (e) => handleModelChange(
6427
+ index,
6428
+ "temperature",
6429
+ e.target.value ? Number(e.target.value) : void 0
6430
+ ),
6431
+ style: { height: 40 }
6432
+ }
6433
+ )
6434
+ ] })
6435
+ ] })
6436
+ ] })
6437
+ ] }, index)),
6438
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6439
+ import_antd25.Button,
6440
+ {
6441
+ type: "dashed",
6442
+ onClick: handleAddModel,
6443
+ block: true,
6444
+ size: "large",
6445
+ style: { marginTop: 24, height: 48 },
6446
+ children: "+ Add Model"
6447
+ }
6448
+ )
6449
+ ] });
6450
+ };
6451
+ const renderContent = (serverId) => {
6452
+ switch (activeMenu) {
6453
+ case "environment":
6454
+ return renderEnvironmentSettings(serverId);
6455
+ case "models":
6456
+ return renderModelSettings(serverId);
6457
+ default:
6458
+ return null;
6459
+ }
6460
+ };
6461
+ const activeMenuItem = SETTINGS_MENU_ITEMS.find(
6462
+ (item) => item.key === activeMenu
6463
+ );
6464
+ const currentConnection = connections.find((c) => c.id === activeTabKey);
6465
+ const renderTabLabel = (connection) => {
6466
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { display: "flex", alignItems: "center" }, children: [
6467
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6468
+ import_icons14.CloudServerOutlined,
6469
+ {
6470
+ style: {
6471
+ marginRight: 8,
6472
+ color: connection.connected ? "#52c41a" : connection.connecting ? "#1890ff" : "#d9d9d9"
6473
+ }
6474
+ }
6475
+ ),
6476
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: connection.name }),
6477
+ connection.connected && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6478
+ import_icons14.CheckCircleFilled,
6479
+ {
6480
+ style: { color: "#52c41a", fontSize: 12, marginLeft: 8 }
6481
+ }
6482
+ ),
6483
+ connection.error && !connection.connecting && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6484
+ import_icons14.CloseCircleFilled,
6485
+ {
6486
+ style: { color: "#ff4d4f", fontSize: 12, marginLeft: 8 }
6487
+ }
6488
+ )
6489
+ ] });
6490
+ };
6491
+ const tabItems = connections.map((connection) => ({
6492
+ key: connection.id,
6493
+ label: renderTabLabel(connection),
6494
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: styles.tabContent, children: connection.connected ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_jsx_runtime39.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { style: { display: "flex", height: "100%" }, children: [
6495
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: styles.sidebar, children: SETTINGS_MENU_ITEMS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
6496
+ "div",
6497
+ {
6498
+ className: `${styles.menuItem} ${activeMenu === item.key ? "active" : ""}`,
6499
+ onClick: () => setActiveMenu(item.key),
6500
+ children: [
6501
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: styles.menuItemIcon, children: item.icon }),
6502
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: styles.menuItemText, children: item.label })
6503
+ ]
6504
+ },
6505
+ item.key
6506
+ )) }),
6507
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.content, children: [
6508
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.contentHeader, children: [
6509
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.contentHeaderLeft, children: [
6510
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Title2, { level: 3, className: styles.contentTitle, children: activeMenuItem?.label }),
6511
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(Text11, { className: styles.contentDescription, children: [
6512
+ activeMenu === "environment" && "Manage environment variables for the gateway server",
6513
+ activeMenu === "models" && "Configure and register model lattices for use by agents"
6514
+ ] })
6515
+ ] }),
6516
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.contentHeaderRight, children: [
6517
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd25.Button, { onClick: onClose, children: "Cancel" }),
6518
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6519
+ import_antd25.Button,
6520
+ {
6521
+ type: "primary",
6522
+ icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_icons14.SaveOutlined, {}),
6523
+ onClick: handleSave,
6524
+ loading,
6525
+ children: "Save Configuration"
6526
+ }
6527
+ )
6528
+ ] })
6529
+ ] }),
6530
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: styles.contentBody, children: renderContent(connection.id) })
6531
+ ] })
6532
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6533
+ "div",
6534
+ {
6535
+ style: {
6536
+ flex: 1,
6537
+ display: "flex",
6538
+ alignItems: "center",
6539
+ justifyContent: "center",
6540
+ flexDirection: "column",
6541
+ gap: 16,
6542
+ padding: 48
6543
+ },
6544
+ children: connection.connecting ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
6545
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_icons14.LinkOutlined, { style: { fontSize: 64, color: "#1890ff" }, spin: true }),
6546
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Title2, { level: 4, children: "Connecting..." }),
6547
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(Text11, { type: "secondary", style: { textAlign: "center" }, children: [
6548
+ "Connecting to ",
6549
+ connection.url
6550
+ ] })
6551
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
6552
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_icons14.LinkOutlined, { style: { fontSize: 64, color: "#d9d9d9" } }),
6553
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Title2, { level: 4, type: "secondary", children: connection.error || "Not Connected" }),
6554
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6555
+ Text11,
6556
+ {
6557
+ type: "secondary",
6558
+ style: { textAlign: "center", maxWidth: 400 },
6559
+ children: connection.error ? `Failed to connect to ${connection.url}. Please check the server URL and try again.` : `Click "Reconnect" to connect to ${connection.url}`
6560
+ }
6561
+ ),
6562
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6563
+ import_antd25.Button,
6564
+ {
6565
+ type: "primary",
6566
+ icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_icons14.LinkOutlined, {}),
6567
+ onClick: () => checkConnection(connection.id),
6568
+ loading: connection.connecting,
6569
+ style: { marginTop: 16 },
6570
+ children: "Reconnect"
6571
+ }
6572
+ )
6573
+ ] })
6574
+ }
6575
+ ) }),
6576
+ closable: connections.length > 1
6577
+ }));
6578
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
6579
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6580
+ import_antd25.Drawer,
6581
+ {
6582
+ open,
6583
+ onClose,
6584
+ footer: null,
6585
+ width: "100%",
6586
+ title: "Settings",
6587
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6588
+ import_antd25.Tabs,
6589
+ {
6590
+ activeKey: activeTabKey,
6591
+ onChange: handleTabChange,
6592
+ type: "editable-card",
6593
+ onEdit: (targetKey, action) => {
6594
+ if (action === "add") {
6595
+ setShowAddServerModal(true);
6596
+ } else if (action === "remove") {
6597
+ handleDeleteServer(targetKey);
6598
+ }
6599
+ },
6600
+ items: tabItems,
6601
+ addIcon: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
6602
+ "div",
6603
+ {
6604
+ style: {
6605
+ display: "flex",
6606
+ alignItems: "center",
6607
+ gap: 4,
6608
+ padding: "4px 8px"
6609
+ },
6610
+ children: [
6611
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_icons14.PlusOutlined, {}),
6612
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: "Add Server" })
6613
+ ]
6614
+ }
6615
+ )
6616
+ }
6617
+ ) })
6618
+ }
6619
+ ),
6620
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6621
+ import_antd25.Modal,
6622
+ {
6623
+ title: "Add New Server",
6624
+ open: showAddServerModal,
6625
+ onOk: handleAddServer,
6626
+ onCancel: () => {
6627
+ setShowAddServerModal(false);
6628
+ setNewServerUrl("");
6629
+ setNewServerName("");
6630
+ setNewServerApiKey("");
6631
+ },
6632
+ confirmLoading: addingServer,
6633
+ className: styles.addServerModal,
6634
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_antd25.Space, { direction: "vertical", style: { width: "100%" }, size: "large", children: [
6635
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6636
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "Server Name" }),
6637
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6638
+ import_antd25.Input,
6639
+ {
6640
+ placeholder: "e.g., Production Server",
6641
+ value: newServerName,
6642
+ onChange: (e) => setNewServerName(e.target.value),
6643
+ onPressEnter: handleAddServer
6644
+ }
6645
+ ),
6646
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Optional: Leave empty to use URL as name" })
6647
+ ] }),
6648
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6649
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "Server URL *" }),
6650
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6651
+ import_antd25.Input,
6652
+ {
6653
+ placeholder: "e.g., http://localhost:4001",
6654
+ value: newServerUrl,
6655
+ onChange: (e) => setNewServerUrl(e.target.value),
6656
+ onPressEnter: handleAddServer
6657
+ }
6658
+ ),
6659
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Enter the full URL of the gateway server" })
6660
+ ] }),
6661
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
6662
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { strong: true, style: { display: "block", marginBottom: 8 }, children: "API Key" }),
6663
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6664
+ import_antd25.Input.Password,
6665
+ {
6666
+ placeholder: "Optional: Enter API key for authentication",
6667
+ value: newServerApiKey,
6668
+ onChange: (e) => setNewServerApiKey(e.target.value),
6669
+ onPressEnter: handleAddServer
6670
+ }
6671
+ ),
6672
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text11, { type: "secondary", style: { fontSize: 12, marginTop: 4 }, children: "Optional: API key for server authentication" })
6673
+ ] })
6674
+ ] })
6675
+ }
6676
+ )
6677
+ ] });
6678
+ };
6679
+
6680
+ // src/components/Chat/AgentServerSetting.tsx
6681
+ var import_jsx_runtime40 = require("react/jsx-runtime");
6682
+ var AgentServerSetting = () => {
6683
+ const { settingsModalOpen, setSettingsModalOpen } = useLatticeChatShellContext();
6684
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
6685
+ SettingsModal,
6686
+ {
6687
+ open: settingsModalOpen,
6688
+ onClose: () => setSettingsModalOpen(false)
6689
+ }
6690
+ );
6691
+ };
6692
+
6693
+ // src/components/Chat/LatticeChatShell.tsx
6694
+ var import_jsx_runtime41 = require("react/jsx-runtime");
6695
+ var LatticeChatShell = (props) => {
6696
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(LatticeChatShellContextProvider, { ...props, children: [
6697
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(AssistantContextProvider, { autoLoad: true, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ConversationContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(LatticeChatView, {}) }) }),
6698
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(AgentServerSetting, {})
6699
+ ] });
5347
6700
  };
5348
6701
  // Annotate the CommonJS export names for ESM import in node:
5349
6702
  0 && (module.exports = {