@axiom-lattice/react-sdk 2.1.107 → 2.1.109

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
@@ -1557,6 +1557,23 @@ var DEFAULT_MIDDLEWARE_TYPES = [
1557
1557
  { id: "update_entry", name: "update_entry", description: "Update an existing entry" },
1558
1558
  { id: "delete_entry", name: "delete_entry", description: "Delete an entry from a collection" }
1559
1559
  ]
1560
+ },
1561
+ {
1562
+ type: "eval",
1563
+ name: "Agent Eval",
1564
+ description: "Governance and testing: design test suites, run evaluations, analyze results. Best paired with the Skill plugin.",
1565
+ schema: {
1566
+ type: "object",
1567
+ title: "Agent Eval Configuration",
1568
+ description: "Enable agent evaluation capabilities",
1569
+ properties: {}
1570
+ },
1571
+ defaultConfig: {},
1572
+ tools: [
1573
+ { id: "read_eval", name: "read_eval", description: "Read-only: list/get projects, suites, cases, runs, results, reports" },
1574
+ { id: "manage_eval", name: "manage_eval", description: "Create, update, delete eval projects, suites, and test cases" },
1575
+ { id: "run_eval", name: "run_eval", description: "Start, abort, status, and resume evaluation runs" }
1576
+ ]
1560
1577
  }
1561
1578
  ];
1562
1579
  var DEFAULT_CONFIG = {
@@ -2080,6 +2097,8 @@ function AgentThreadProvider({
2080
2097
  const chunkMessageMerger = (0, import_react7.useRef)((0, import_client_sdk3.createSimpleMessageMerger)());
2081
2098
  const lastAgentStateCreatedAtRef = (0, import_react7.useRef)(null);
2082
2099
  const streamEndedByInterruptRef = (0, import_react7.useRef)(false);
2100
+ const currentThreadIdRef = (0, import_react7.useRef)(threadId);
2101
+ currentThreadIdRef.current = threadId;
2083
2102
  const messageCountRef = (0, import_react7.useRef)(0);
2084
2103
  const onToolCompletedRef = (0, import_react7.useRef)(onToolCompleted);
2085
2104
  onToolCompletedRef.current = onToolCompleted;
@@ -2192,22 +2211,25 @@ function AgentThreadProvider({
2192
2211
  console.error("Failed to parse todo list from chunk", e);
2193
2212
  }
2194
2213
  }
2195
- const updatedMessages = chunkMessageMerger.current.getMessages();
2196
2214
  const isStopSignal = interrupt !== void 0 || anyChunk.type === "message_failed";
2197
2215
  if (isStopSignal) {
2198
- setState((prev) => ({
2199
- ...prev,
2200
- todos: todos || prev.todos,
2201
- messages: updatedMessages,
2202
- isLoading: false,
2203
- interrupts: interrupt ? [interrupt] : void 0
2204
- }));
2216
+ setState((prev) => {
2217
+ if (currentThreadIdRef.current !== threadId) return prev;
2218
+ return {
2219
+ ...prev,
2220
+ todos: todos || prev.todos,
2221
+ messages: chunkMessageMerger.current.getMessages(),
2222
+ isLoading: false,
2223
+ interrupts: interrupt ? [interrupt] : void 0
2224
+ };
2225
+ });
2205
2226
  } else {
2206
2227
  startTransition(() => {
2228
+ if (currentThreadIdRef.current !== threadId) return;
2207
2229
  setState((prev) => ({
2208
2230
  ...prev,
2209
2231
  todos: todos || prev.todos,
2210
- messages: updatedMessages,
2232
+ messages: chunkMessageMerger.current.getMessages(),
2211
2233
  isLoading: true,
2212
2234
  interrupts: void 0
2213
2235
  }));
@@ -2468,7 +2490,7 @@ function AgentThreadProvider({
2468
2490
  stopStreamingRef.current();
2469
2491
  stopStreamingRef.current = null;
2470
2492
  }
2471
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
2493
+ setState((prev) => ({ ...prev, messages: [], isLoading: true, error: null }));
2472
2494
  try {
2473
2495
  const agentState = await client.getAgentState(threadId);
2474
2496
  const currentCreatedAt = agentState?.createdAt;
@@ -2589,6 +2611,20 @@ function AgentThreadProvider({
2589
2611
  }
2590
2612
  }
2591
2613
  }, [stopStreaming, assistantId, threadId, client]);
2614
+ (0, import_react7.useLayoutEffect)(() => {
2615
+ if (threadId && state.threadId !== threadId) {
2616
+ chunkMessageMerger.current.reset();
2617
+ setState((prev) => ({
2618
+ ...prev,
2619
+ threadId,
2620
+ messages: [],
2621
+ agentState: null,
2622
+ interrupts: void 0,
2623
+ isLoading: true,
2624
+ error: null
2625
+ }));
2626
+ }
2627
+ }, [threadId, state.threadId]);
2592
2628
  (0, import_react7.useEffect)(() => {
2593
2629
  if (threadId && clientAssistantId === assistantId) {
2594
2630
  lastAgentStateCreatedAtRef.current = null;
@@ -6794,6 +6830,55 @@ var useStyles5 = (0, import_antd_style8.createStyles)(({ css, token }) => ({
6794
6830
  flex-direction: column;
6795
6831
  gap: 4px;
6796
6832
  `,
6833
+ titleRow: css`
6834
+ display: flex;
6835
+ align-items: center;
6836
+ gap: 8px;
6837
+ `,
6838
+ tabs: css`
6839
+ margin-top: 12px;
6840
+
6841
+ .ant-tabs-nav {
6842
+ margin-bottom: 0;
6843
+
6844
+ &::before {
6845
+ border-bottom: none;
6846
+ }
6847
+ }
6848
+
6849
+ .ant-tabs-tab {
6850
+ padding: 4px 10px;
6851
+ margin: 0 2px 0 0;
6852
+ border-radius: 9999px;
6853
+ transition: background-color 0.15s ease;
6854
+ font-size: 13px;
6855
+
6856
+ &:hover {
6857
+ background-color: ${token.colorFillTertiary};
6858
+ }
6859
+
6860
+ .ant-tabs-tab-btn {
6861
+ font-size: 13px;
6862
+ }
6863
+ }
6864
+
6865
+ .ant-tabs-tab + .ant-tabs-tab {
6866
+ margin-left: 2px;
6867
+ }
6868
+
6869
+ .ant-tabs-tab-active {
6870
+ background-color: ${token.colorFillSecondary};
6871
+
6872
+ .ant-tabs-tab-btn {
6873
+ color: ${token.colorText};
6874
+ font-weight: 500;
6875
+ }
6876
+ }
6877
+
6878
+ .ant-tabs-ink-bar {
6879
+ display: none;
6880
+ }
6881
+ `,
6797
6882
  title: css`
6798
6883
  margin: 0;
6799
6884
  font-size: 24px;
@@ -6846,6 +6931,8 @@ var useStyles5 = (0, import_antd_style8.createStyles)(({ css, token }) => ({
6846
6931
  var EntityListShell = ({
6847
6932
  title,
6848
6933
  subtitle,
6934
+ titleBefore,
6935
+ titleAfter,
6849
6936
  headerLeft,
6850
6937
  headerRight,
6851
6938
  loading,
@@ -6858,7 +6945,10 @@ var EntityListShell = ({
6858
6945
  children,
6859
6946
  itemCount,
6860
6947
  itemName,
6861
- className
6948
+ className,
6949
+ tabs,
6950
+ activeTab,
6951
+ onTabChange
6862
6952
  }) => {
6863
6953
  const { styles } = useStyles5();
6864
6954
  const { token } = import_antd12.theme.useToken();
@@ -6866,8 +6956,21 @@ var EntityListShell = ({
6866
6956
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `${styles.container} ${className || ""}`, children: [
6867
6957
  /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: styles.header, children: [
6868
6958
  /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: styles.headerLeft, children: [
6869
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h1", { className: styles.title, children: title }),
6870
- resolvedSubtitle && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: styles.subtitle, children: resolvedSubtitle })
6959
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: styles.titleRow, children: [
6960
+ titleBefore,
6961
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h1", { className: styles.title, children: title }),
6962
+ titleAfter
6963
+ ] }),
6964
+ resolvedSubtitle && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: styles.subtitle, children: resolvedSubtitle }),
6965
+ tabs && tabs.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: styles.tabs, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6966
+ import_antd11.Tabs,
6967
+ {
6968
+ type: "line",
6969
+ activeKey: activeTab,
6970
+ onChange: (key) => onTabChange?.(key),
6971
+ items: tabs.map((t) => ({ key: t.key, label: t.label }))
6972
+ }
6973
+ ) })
6871
6974
  ] }),
6872
6975
  (headerLeft || headerRight) && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: styles.headerRight, children: [
6873
6976
  headerLeft,
@@ -6986,6 +7089,8 @@ var EntityListView = ({
6986
7089
  keyExtractor,
6987
7090
  title,
6988
7091
  itemName,
7092
+ titleBefore,
7093
+ titleAfter,
6989
7094
  renderIcon,
6990
7095
  renderPrimary,
6991
7096
  renderSecondary,
@@ -7008,7 +7113,10 @@ var EntityListView = ({
7008
7113
  renderEmpty,
7009
7114
  renderGridItem,
7010
7115
  renderListItem,
7011
- className
7116
+ className,
7117
+ tabs,
7118
+ activeTab,
7119
+ onTabChange
7012
7120
  }) => {
7013
7121
  const [viewMode, setViewMode] = (0, import_react29.useState)(defaultViewMode);
7014
7122
  const { styles } = useStyles7();
@@ -7033,8 +7141,13 @@ var EntityListView = ({
7033
7141
  emptyTitle,
7034
7142
  emptyDescription,
7035
7143
  renderEmpty,
7144
+ titleBefore,
7145
+ titleAfter,
7036
7146
  headerLeft,
7037
7147
  headerRight: headerRightContent,
7148
+ tabs,
7149
+ activeTab,
7150
+ onTabChange,
7038
7151
  children: null
7039
7152
  }
7040
7153
  );
@@ -7047,9 +7160,14 @@ var EntityListView = ({
7047
7160
  itemName,
7048
7161
  loading,
7049
7162
  isEmpty: false,
7163
+ titleBefore,
7164
+ titleAfter,
7050
7165
  headerLeft,
7051
7166
  headerRight: headerRightContent,
7052
7167
  className,
7168
+ tabs,
7169
+ activeTab,
7170
+ onTabChange,
7053
7171
  children: viewMode === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: styles.grid, children: [
7054
7172
  hasCreate && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EntityCreateTrigger, { viewMode: "grid", label: createLabel, onClick: onCreateClick }),
7055
7173
  items.map((item) => {
@@ -8488,7 +8606,7 @@ var ConnectionConfigDrawerContent = ({
8488
8606
  itemName: "connection",
8489
8607
  items: configs,
8490
8608
  loading,
8491
- headerLeft: onBack ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_antd15.Button, { type: "text", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { fontSize: 16 }, children: "\u2190" }), onClick: onBack, style: { marginRight: 8 }, children: "Back" }) : void 0,
8609
+ titleBefore: onBack ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_antd15.Button, { type: "text", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { fontSize: 16 }, children: "\u2190" }), onClick: onBack }) : void 0,
8492
8610
  keyExtractor: (c) => c.id,
8493
8611
  onItemClick: handleEdit,
8494
8612
  renderIcon: () => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { color: "#6366f1" }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Plug2, { size: 20 }) }),
@@ -8830,12 +8948,25 @@ var ConnectionFormModal = ({
8830
8948
  // src/components/Chat/ConnectionsHub.tsx
8831
8949
  var import_jsx_runtime28 = require("react/jsx-runtime");
8832
8950
  var { Text: Text7 } = import_antd16.Typography;
8951
+ function categorize(types) {
8952
+ const connections = [];
8953
+ const tools = [];
8954
+ for (const t of types) {
8955
+ if (t.connectionSchema) {
8956
+ connections.push(t);
8957
+ } else {
8958
+ tools.push(t);
8959
+ }
8960
+ }
8961
+ return { connections, tools };
8962
+ }
8833
8963
  var ConnectionsHub = () => {
8834
8964
  const api = useApi();
8835
8965
  const { config } = useLatticeChatShellContext();
8836
- const [types, setTypes] = (0, import_react34.useState)([]);
8966
+ const [allTypes, setAllTypes] = (0, import_react34.useState)([]);
8837
8967
  const [loading, setLoading] = (0, import_react34.useState)(true);
8838
8968
  const [selectedType, setSelectedType] = (0, import_react34.useState)(null);
8969
+ const [activeTab, setActiveTab] = (0, import_react34.useState)("connections");
8839
8970
  const fetchedRef = (0, import_react34.useRef)(false);
8840
8971
  (0, import_react34.useEffect)(() => {
8841
8972
  if (fetchedRef.current) return;
@@ -8843,39 +8974,79 @@ var ConnectionsHub = () => {
8843
8974
  const endpoint = config.middlewareTypesEndpoint || "/api/middleware-types";
8844
8975
  api.get(endpoint).then((data) => {
8845
8976
  if (Array.isArray(data)) {
8846
- setTypes(data.filter((t) => t.connectionSchema));
8977
+ setAllTypes(data);
8847
8978
  }
8848
- }).catch(() => setTypes([])).finally(() => setLoading(false));
8979
+ }).catch(() => setAllTypes([])).finally(() => setLoading(false));
8849
8980
  }, []);
8981
+ const { connections, tools } = (0, import_react34.useMemo)(() => categorize(allTypes), [allTypes]);
8982
+ const visibleItems = (0, import_react34.useMemo)(() => {
8983
+ switch (activeTab) {
8984
+ case "all":
8985
+ return allTypes;
8986
+ case "connections":
8987
+ return connections;
8988
+ case "tools":
8989
+ return tools;
8990
+ }
8991
+ }, [activeTab, allTypes, connections, tools]);
8992
+ const handleItemClick = (t) => {
8993
+ if (t.connectionSchema) {
8994
+ setSelectedType(t.type);
8995
+ }
8996
+ };
8997
+ const emptyState = (0, import_react34.useMemo)(() => {
8998
+ switch (activeTab) {
8999
+ case "connections":
9000
+ return { title: "No connection plugins", description: "No plugins with connection management registered" };
9001
+ case "tools":
9002
+ return { title: "No tool plugins", description: "No tool-only plugins registered" };
9003
+ default:
9004
+ return { title: "No plugins", description: "No plugins registered" };
9005
+ }
9006
+ }, [activeTab]);
8850
9007
  if (selectedType) {
8851
9008
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8852
9009
  ConnectionConfigDrawerContent,
8853
9010
  {
8854
9011
  connectionType: selectedType,
8855
- title: types.find((t) => t.type === selectedType)?.name,
9012
+ title: allTypes.find((t) => t.type === selectedType)?.name,
8856
9013
  onBack: () => setSelectedType(null)
8857
9014
  }
8858
9015
  );
8859
9016
  }
9017
+ const renderFooter = (t) => {
9018
+ if (t.connectionSchema) {
9019
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: { fontSize: 11, color: "#999" }, children: [
9020
+ t.connectionSchema.hasTest && "test",
9021
+ t.connectionSchema.hasDiscover && "discover"
9022
+ ].filter(Boolean).join(" \xB7 ") || "connection" });
9023
+ }
9024
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_antd16.Tag, { style: { fontSize: 10, lineHeight: "16px", padding: "0 6px" }, children: "tool" });
9025
+ };
9026
+ const tabs = [
9027
+ { key: "all", label: `All (${allTypes.length})` },
9028
+ { key: "connections", label: `Connections (${connections.length})` },
9029
+ { key: "tools", label: `Tools (${tools.length})` }
9030
+ ];
8860
9031
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8861
9032
  EntityListView,
8862
9033
  {
8863
9034
  title: "Plugins",
8864
9035
  itemName: "plugin",
8865
- items: types,
9036
+ items: visibleItems,
8866
9037
  loading,
8867
9038
  keyExtractor: (t) => t.type,
8868
- renderIcon: (t) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: { fontSize: 20, fontWeight: 600, color: "#6366f1" }, children: t.name.charAt(0).toUpperCase() }),
9039
+ tabs,
9040
+ activeTab,
9041
+ onTabChange: (key) => setActiveTab(key),
9042
+ renderIcon: (t) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: { fontSize: 20, fontWeight: 600, color: t.connectionSchema ? "#6366f1" : "#8c8c8c" }, children: t.name.charAt(0).toUpperCase() }),
8869
9043
  renderPrimary: (t) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Text7, { strong: true, style: { fontSize: 14 }, children: t.name }),
8870
9044
  renderSecondary: (t) => t.description || void 0,
8871
- renderFooter: (t) => t.connectionSchema ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: { fontSize: 11, color: "#999" }, children: [
8872
- t.connectionSchema.hasTest && "test",
8873
- t.connectionSchema.hasDiscover && "discover"
8874
- ].filter(Boolean).join(" \xB7 ") || "connection" }) : void 0,
8875
- onItemClick: (t) => setSelectedType(t.type),
9045
+ renderFooter,
9046
+ onItemClick: handleItemClick,
8876
9047
  emptyIcon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { style: { fontSize: 48, opacity: 0.3 }, children: "\u{1F50C}" }),
8877
- emptyTitle: "No connection types configured",
8878
- emptyDescription: "Register a plugin with connection capabilities to see it here",
9048
+ emptyTitle: emptyState.title,
9049
+ emptyDescription: emptyState.description,
8879
9050
  showViewToggle: false
8880
9051
  }
8881
9052
  );
@@ -13684,6 +13855,16 @@ var useStyles10 = (0, import_antd_style13.createStyles)(({ token, css }) => ({
13684
13855
  body: css`
13685
13856
  flex: 1;
13686
13857
  overflow: auto;
13858
+ & .ant-table-row .entry-row-actions {
13859
+ opacity: 0;
13860
+ transition: opacity 0.15s;
13861
+ @media (hover: none) {
13862
+ opacity: 1;
13863
+ }
13864
+ }
13865
+ & .ant-table-row:hover .entry-row-actions {
13866
+ opacity: 1;
13867
+ }
13687
13868
  `,
13688
13869
  countTag: css`
13689
13870
  font-size: 12px;
@@ -13699,6 +13880,37 @@ var useStyles10 = (0, import_antd_style13.createStyles)(({ token, css }) => ({
13699
13880
  justify-content: center;
13700
13881
  padding: 48px 0;
13701
13882
  gap: 8px;
13883
+ `,
13884
+ contentClamp: css`
13885
+ display: -webkit-box;
13886
+ -webkit-box-orient: vertical;
13887
+ overflow: hidden;
13888
+ line-height: 1.55;
13889
+ font-size: 13px;
13890
+ word-break: break-word;
13891
+ `,
13892
+ expandToggle: css`
13893
+ display: inline-flex;
13894
+ align-items: center;
13895
+ gap: 2px;
13896
+ font-size: 12px;
13897
+ color: ${token.colorPrimary};
13898
+ cursor: pointer;
13899
+ user-select: none;
13900
+ margin-top: 2px;
13901
+ line-height: 1;
13902
+ padding: 1px 4px;
13903
+ border-radius: 4px;
13904
+ transition: background 0.15s;
13905
+ &:hover {
13906
+ background: ${token.colorPrimaryBg};
13907
+ }
13908
+ `,
13909
+ expandedRow: css`
13910
+ & td {
13911
+ background: ${token.colorPrimaryBg} !important;
13912
+ transition: background 0.25s;
13913
+ }
13702
13914
  `
13703
13915
  }));
13704
13916
  var CollectionEntryTable = ({
@@ -13716,7 +13928,17 @@ var CollectionEntryTable = ({
13716
13928
  const [confirmLoading, setConfirmLoading] = (0, import_react47.useState)(false);
13717
13929
  const [searchQuery, setSearchQuery] = (0, import_react47.useState)("");
13718
13930
  const [searchResults, setSearchResults] = (0, import_react47.useState)(null);
13931
+ const [loadError, setLoadError] = (0, import_react47.useState)(false);
13932
+ const [expandedIds, setExpandedIds] = (0, import_react47.useState)(/* @__PURE__ */ new Set());
13719
13933
  const [form] = import_antd29.Form.useForm();
13934
+ const toggleExpand = (id) => {
13935
+ setExpandedIds((prev) => {
13936
+ const next = new Set(prev);
13937
+ if (next.has(id)) next.delete(id);
13938
+ else next.add(id);
13939
+ return next;
13940
+ });
13941
+ };
13720
13942
  const fetchEntries = (0, import_react47.useCallback)(async () => {
13721
13943
  if (!collectionName) return;
13722
13944
  setIsLoading(true);
@@ -13725,7 +13947,10 @@ var CollectionEntryTable = ({
13725
13947
  setEntries(res.data?.records || []);
13726
13948
  setSearchResults(null);
13727
13949
  setSearchQuery("");
13950
+ setLoadError(false);
13728
13951
  } catch {
13952
+ setLoadError(true);
13953
+ import_antd29.message.error("Failed to load entries");
13729
13954
  } finally {
13730
13955
  setIsLoading(false);
13731
13956
  }
@@ -13741,6 +13966,7 @@ var CollectionEntryTable = ({
13741
13966
  (0, import_react47.useEffect)(() => {
13742
13967
  fetchCollection();
13743
13968
  fetchEntries();
13969
+ setExpandedIds(/* @__PURE__ */ new Set());
13744
13970
  }, [fetchCollection, fetchEntries]);
13745
13971
  const handleSearch = async (q) => {
13746
13972
  doBackendSearch(q);
@@ -13774,6 +14000,13 @@ var CollectionEntryTable = ({
13774
14000
  setSearchResults(null);
13775
14001
  fetchEntries();
13776
14002
  };
14003
+ const refreshCurrentView = () => {
14004
+ if (searchResults !== null) {
14005
+ doBackendSearch();
14006
+ } else {
14007
+ fetchEntries();
14008
+ }
14009
+ };
13777
14010
  const fields = collection?.schema?.fields || [];
13778
14011
  const hasSearch = searchResults !== null;
13779
14012
  const displayEntries = searchResults || entries;
@@ -13810,12 +14043,14 @@ var CollectionEntryTable = ({
13810
14043
  ] })
13811
14044
  ] }),
13812
14045
  filterIcon: (f) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.Search, { size: 13, style: { color: f ? "#6366f1" : "#d1d5db" } }),
13813
- filtered: columnFilters[fieldKey] !== void 0
14046
+ filtered: columnFilters[fieldKey] !== void 0,
14047
+ filteredValue: columnFilters[fieldKey] !== void 0 ? [columnFilters[fieldKey]] : null
13814
14048
  });
13815
14049
  const enumFilter = (fieldKey, values) => ({
13816
14050
  filters: values.map((v) => ({ text: v, value: v })),
13817
14051
  filterIcon: (f) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.Search, { size: 13, style: { color: f ? "#6366f1" : "#d1d5db" } }),
13818
14052
  filtered: columnFilters[fieldKey] !== void 0,
14053
+ filteredValue: columnFilters[fieldKey] !== void 0 ? [columnFilters[fieldKey]] : null,
13819
14054
  onFilter: (value, _record) => {
13820
14055
  return true;
13821
14056
  },
@@ -13857,9 +14092,43 @@ var CollectionEntryTable = ({
13857
14092
  title: "Content",
13858
14093
  dataIndex: "content",
13859
14094
  key: "content",
13860
- ellipsis: true,
14095
+ ellipsis: false,
13861
14096
  ...textFilter("content"),
13862
- render: (text) => text ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { style: { lineHeight: 1.5 }, children: text.length > 120 ? text.slice(0, 120) + "\u2026" : text }) : null
14097
+ render: (text, record) => {
14098
+ if (!text) return null;
14099
+ const MAX = 120;
14100
+ const isLong = text.length > MAX;
14101
+ const expanded = isLong && expandedIds.has(record.id);
14102
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { children: [
14103
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
14104
+ "div",
14105
+ {
14106
+ className: styles.contentClamp,
14107
+ style: {
14108
+ WebkitLineClamp: expanded ? "unset" : 2
14109
+ },
14110
+ children: text
14111
+ }
14112
+ ),
14113
+ isLong && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
14114
+ "a",
14115
+ {
14116
+ className: styles.expandToggle,
14117
+ onClick: (e) => {
14118
+ e.stopPropagation();
14119
+ toggleExpand(record.id);
14120
+ },
14121
+ children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
14122
+ "\u6536\u8D77 ",
14123
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.ChevronUp, { size: 12 })
14124
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
14125
+ "\u5C55\u5F00 ",
14126
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.ChevronDown, { size: 12 })
14127
+ ] })
14128
+ }
14129
+ )
14130
+ ] });
14131
+ }
13863
14132
  },
13864
14133
  ...fields.map((f) => ({
13865
14134
  title: f.key,
@@ -13884,9 +14153,9 @@ var CollectionEntryTable = ({
13884
14153
  title: "",
13885
14154
  key: "actions",
13886
14155
  width: 64,
13887
- render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_antd29.Space, { size: 0, children: [
14156
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_antd29.Space, { size: 0, className: "entry-row-actions", onClick: (e) => e.stopPropagation(), children: [
13888
14157
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Button, { type: "text", size: "small", style: iconMuted, onClick: () => handleEdit(record), children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.Pencil, { size: 14 }) }),
13889
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Popconfirm, { title: "Delete?", onConfirm: () => handleDelete(record.id), okText: "Delete", okType: "danger", placement: "left", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Button, { type: "text", size: "small", danger: true, style: { opacity: 0.4 }, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.Trash2, { size: 14 }) }) })
14158
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Popconfirm, { title: "Delete?", onConfirm: () => handleDelete(record.id), okText: "Delete", okType: "danger", placement: "left", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Button, { type: "text", size: "small", danger: true, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.Trash2, { size: 14 }) }) })
13890
14159
  ] })
13891
14160
  }
13892
14161
  ];
@@ -13904,7 +14173,7 @@ var CollectionEntryTable = ({
13904
14173
  try {
13905
14174
  await del(`/api/collections/${collectionName}/entries/${id}`);
13906
14175
  import_antd29.message.success("Deleted");
13907
- fetchEntries();
14176
+ refreshCurrentView();
13908
14177
  } catch (err) {
13909
14178
  import_antd29.message.error(err?.message || "Failed");
13910
14179
  }
@@ -13919,9 +14188,10 @@ var CollectionEntryTable = ({
13919
14188
  if (v !== void 0 && v !== "") metadata[k] = v;
13920
14189
  }
13921
14190
  editingEntry ? await put(`/api/collections/${collectionName}/entries/${editingEntry.id}`, { content, metadata }) : await post(`/api/collections/${collectionName}/entries`, { content, metadata });
14191
+ import_antd29.message.success(editingEntry ? "Entry updated" : "Entry created");
13922
14192
  setModalOpen(false);
13923
14193
  form.resetFields();
13924
- fetchEntries();
14194
+ refreshCurrentView();
13925
14195
  } catch (err) {
13926
14196
  if (err?.errorFields) return;
13927
14197
  import_antd29.message.error(err?.message || "Failed");
@@ -13935,7 +14205,7 @@ var CollectionEntryTable = ({
13935
14205
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.toolbarLeft, children: [
13936
14206
  onBack && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Button, { type: "text", size: "small", icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.ArrowLeft, { size: 16 }), onClick: onBack }),
13937
14207
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text17, { strong: true, style: { fontSize: 14 }, children: collection?.label || collectionName }),
13938
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: styles.countTag, children: displayEntries.length }),
14208
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Tooltip, { title: hasSearch && displayEntries.length >= 50 ? "Semantic search returns at most 50 results" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: styles.countTag, children: hasSearch && displayEntries.length >= 50 ? "50+" : displayEntries.length }) }),
13939
14209
  hasSearch && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Tag, { color: "blue", style: { margin: 0 }, children: "semantic" })
13940
14210
  ] }),
13941
14211
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.toolbarRight, children: [
@@ -13954,9 +14224,11 @@ var CollectionEntryTable = ({
13954
14224
  style: { width: 200 },
13955
14225
  placeholder: "Semantic search\u2026",
13956
14226
  value: searchQuery,
13957
- onChange: (e) => setSearchQuery(e.target.value),
14227
+ onChange: (e) => {
14228
+ setSearchQuery(e.target.value);
14229
+ if (!e.target.value) doBackendSearch("");
14230
+ },
13958
14231
  onSearch: handleSearch,
13959
- onClear: clearFilters,
13960
14232
  allowClear: true,
13961
14233
  loading: searching
13962
14234
  }
@@ -13974,8 +14246,19 @@ var CollectionEntryTable = ({
13974
14246
  loading: isLoading,
13975
14247
  size: "small",
13976
14248
  pagination: false,
14249
+ rowClassName: (record) => expandedIds.has(record.id) ? styles.expandedRow : "",
14250
+ onRow: (record) => ({
14251
+ onClick: () => handleEdit(record),
14252
+ style: { cursor: "pointer" }
14253
+ }),
13977
14254
  showHeader: displayEntries.length > 0,
13978
- locale: { emptyText: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.emptyWrap, children: [
14255
+ locale: { emptyText: loadError ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.emptyWrap, children: [
14256
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text17, { type: "secondary", children: "Failed to load entries" }),
14257
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Button, { size: "small", onClick: fetchEntries, children: "Retry" })
14258
+ ] }) : hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.emptyWrap, children: [
14259
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text17, { type: "secondary", children: "No matching entries" }),
14260
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Button, { size: "small", onClick: clearFilters, children: "Clear search & filters" })
14261
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: styles.emptyWrap, children: [
13979
14262
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Text17, { type: "secondary", children: "No entries yet" }),
13980
14263
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Button, { type: "primary", size: "small", icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react18.Plus, { size: 14 }), onClick: handleAdd, children: "Add your first entry" })
13981
14264
  ] }) }
@@ -13996,7 +14279,7 @@ var CollectionEntryTable = ({
13996
14279
  destroyOnClose: true,
13997
14280
  children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_antd29.Form, { form, layout: "vertical", style: { marginTop: 8 }, children: [
13998
14281
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Form.Item, { name: "content", label: "Content", rules: [{ required: true }], children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Input.TextArea, { rows: 4, placeholder: "Text content to index\u2026" }) }),
13999
- fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Form.Item, { name: f.key, label: f.key, rules: f.required ? [{ required: true }] : [], children: f.type === "enum" && f.enumValues ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Select, { placeholder: f.key, allowClear: true, options: f.enumValues.map((v) => ({ value: v, label: v })) }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Input, { placeholder: f.key }) }, f.key))
14282
+ fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Form.Item, { name: f.key, label: f.key, rules: f.required ? [{ required: true }] : [], children: f.type === "enum" && f.enumValues ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Select, { placeholder: f.key, allowClear: true, options: f.enumValues.map((v) => ({ value: v, label: v })) }) : f.type === "number" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.InputNumber, { style: { width: "100%" }, placeholder: f.key }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_antd29.Input, { placeholder: f.key }) }, f.key))
14000
14283
  ] })
14001
14284
  }
14002
14285
  )
@@ -14149,7 +14432,7 @@ var CollectionsPanel = () => {
14149
14432
  title: "",
14150
14433
  key: "actions",
14151
14434
  width: 100,
14152
- render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_antd30.Space, { children: [
14435
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_antd30.Space, { onClick: (e) => e.stopPropagation(), children: [
14153
14436
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_antd30.Tooltip, { title: "Edit", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
14154
14437
  import_antd30.Button,
14155
14438
  {
@@ -14781,6 +15064,9 @@ var ClarifyFeedback = ({
14781
15064
  if (currentQuestion.type === "file_upload") {
14782
15065
  return !!(answer?.filePath && answer.filePath.trim() !== "");
14783
15066
  }
15067
+ if (currentQuestion.type === "input") {
15068
+ return !!(answer?.otherText && answer.otherText.trim() !== "");
15069
+ }
14784
15070
  const hasSelection = answer?.selectedOptions?.length > 0;
14785
15071
  const hasOtherText = answer?.otherText?.trim() !== "";
14786
15072
  return hasSelection || hasOtherText;
@@ -14943,16 +15229,58 @@ var ClarifyFeedback = ({
14943
15229
  ]
14944
15230
  }
14945
15231
  )
14946
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
14947
- import_antd33.Checkbox.Group,
15232
+ ] }) : currentQuestion.type === "input" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
15233
+ import_antd33.Input,
14948
15234
  {
14949
- value: currentAnswer.selectedOptions,
14950
- onChange: (values) => handleOptionChange(values),
15235
+ placeholder: "Enter your answer...",
15236
+ value: currentAnswer.otherText,
15237
+ onChange: (e) => handleOtherTextChange(e.target.value),
14951
15238
  disabled: !interactive || submitted,
14952
- style: { display: "flex", flexDirection: "column", gap: 4 },
14953
- children: currentQuestion.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_antd33.Checkbox, { value: option, style: { fontSize: 14 }, children: option }, option))
15239
+ style: { fontSize: 14 }
14954
15240
  }
14955
- ) }),
15241
+ ) : /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
15242
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
15243
+ import_antd33.Checkbox.Group,
15244
+ {
15245
+ value: currentAnswer.selectedOptions,
15246
+ onChange: (values) => handleOptionChange(values),
15247
+ disabled: !interactive || submitted,
15248
+ style: { display: "flex", flexDirection: "column", gap: 4 },
15249
+ children: currentQuestion.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_antd33.Checkbox, { value: option, style: { fontSize: 14 }, children: option }, option))
15250
+ }
15251
+ ),
15252
+ currentQuestion.allowOther && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { style: { marginTop: 8 }, children: [
15253
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
15254
+ import_antd33.Checkbox,
15255
+ {
15256
+ checked: currentAnswer.selectedOptions.includes("__other__"),
15257
+ onChange: (e) => {
15258
+ const current = currentAnswer.selectedOptions || [];
15259
+ if (e.target.checked) {
15260
+ handleOptionChange([...current, "__other__"]);
15261
+ } else {
15262
+ handleOptionChange(current.filter((o) => o !== "__other__"));
15263
+ handleOtherTextChange("");
15264
+ }
15265
+ },
15266
+ disabled: !interactive || submitted,
15267
+ style: { fontSize: 14 },
15268
+ children: "Other (please specify)"
15269
+ }
15270
+ ),
15271
+ currentAnswer.selectedOptions.includes("__other__") && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
15272
+ import_antd33.Input,
15273
+ {
15274
+ size: "small",
15275
+ placeholder: "Enter your answer...",
15276
+ value: currentAnswer.otherText,
15277
+ onChange: (e) => handleOtherTextChange(e.target.value),
15278
+ disabled: !interactive || submitted,
15279
+ style: { fontSize: 14, marginTop: 8, marginLeft: 24, width: "calc(100% - 24px)" }
15280
+ }
15281
+ )
15282
+ ] })
15283
+ ] }) }),
14956
15284
  /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
14957
15285
  import_antd33.Space,
14958
15286
  {
@@ -15319,7 +15647,7 @@ var ToolCard = ({
15319
15647
  size: "small",
15320
15648
  className: styles.card,
15321
15649
  bordered: false,
15322
- bodyStyle: { padding: "16px" },
15650
+ styles: { body: { padding: "16px" } },
15323
15651
  children: [
15324
15652
  /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: styles.header, children: [
15325
15653
  /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_antd35.Space, { align: "center", children: [
@@ -17824,11 +18152,13 @@ var MemoizedBubbleList = (0, import_react62.memo)(
17824
18152
  MemoizedBubbleList.displayName = "MemoizedBubbleList";
17825
18153
  var MessageList = ({
17826
18154
  messages,
17827
- className
18155
+ className,
18156
+ isLoading = false
17828
18157
  }) => {
17829
18158
  const { styles } = useStyle();
17830
18159
  const openSideApp = useSideAppOpener();
17831
- const deferredMessages = (0, import_react62.useDeferredValue)(messages);
18160
+ const rawDeferred = (0, import_react62.useDeferredValue)(messages);
18161
+ const deferredMessages = isLoading ? rawDeferred : messages;
17832
18162
  const messageLengthRef = (0, import_react62.useRef)(deferredMessages?.length ?? 0);
17833
18163
  (0, import_react62.useEffect)(() => {
17834
18164
  if (deferredMessages?.length) {
@@ -17927,6 +18257,30 @@ ${JSON.stringify(
17927
18257
  }
17928
18258
  };
17929
18259
  if (items.length === 0) {
18260
+ if (isLoading) {
18261
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { style: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center" }, children: [
18262
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("style", { children: `
18263
+ @keyframes msg-typing {
18264
+ 0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
18265
+ 30% { transform: translateY(-6px); opacity: 1; }
18266
+ }
18267
+ ` }),
18268
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { style: { display: "flex", gap: 6, padding: "12px 20px" }, children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
18269
+ "div",
18270
+ {
18271
+ style: {
18272
+ width: 8,
18273
+ height: 8,
18274
+ borderRadius: "50%",
18275
+ background: "linear-gradient(135deg, #6366f1, #a855f7)",
18276
+ animation: "msg-typing 1.2s ease-in-out infinite",
18277
+ animationDelay: `${i * 0.2}s`
18278
+ }
18279
+ },
18280
+ i
18281
+ )) })
18282
+ ] });
18283
+ }
17930
18284
  return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { style: { flex: 1 } });
17931
18285
  }
17932
18286
  return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
@@ -21061,6 +21415,7 @@ ${nextContent}`;
21061
21415
  MessageList,
21062
21416
  {
21063
21417
  messages,
21418
+ isLoading,
21064
21419
  className: `${styles.messages} ${isTransitioning ? styles.entering : ""}`
21065
21420
  }
21066
21421
  ),
@@ -27959,7 +28314,7 @@ function parseAgent(raw) {
27959
28314
  id: nid(label),
27960
28315
  type: "agent",
27961
28316
  name: label,
27962
- ref: typeof config.ref === "string" ? config.ref : label,
28317
+ ref: typeof config.ref === "string" ? config.ref : void 0,
27963
28318
  input: { template: String(config.prompt ?? "") },
27964
28319
  output: { key: label, schema: toSchema(config.output) },
27965
28320
  ask: config.ask === true,
@@ -28006,6 +28361,16 @@ function normalize(name, steps) {
28006
28361
  itemKey: "item",
28007
28362
  input: { template: String(config.map.each?.prompt ?? "") },
28008
28363
  output: { key, schema: toSchema(config.map.each?.output) },
28364
+ node: {
28365
+ type: "agent",
28366
+ ref: typeof config.map.each?.ref === "string" ? config.map.each.ref : "",
28367
+ input: { template: String(config.map.each?.prompt ?? "") }
28368
+ },
28369
+ config: {
28370
+ batchSize: Number(config.map.batch) || void 0,
28371
+ maxConcurrency: Number(config.map.concurrency) || void 0,
28372
+ innerConcurrency: Number(config.map.concurrency) || void 0
28373
+ },
28009
28374
  condition: config.map.if !== void 0 ? String(config.map.if) : void 0
28010
28375
  });
28011
28376
  const fromNodes = typeof prevId === "string" ? [prevId] : prevId;
@@ -28153,7 +28518,7 @@ var CIRCLE_SIZE = 72;
28153
28518
  var CIRCLE_BORDER = 3;
28154
28519
  var WorkflowNode = ({ data }) => {
28155
28520
  if (!data) return null;
28156
- const { nodeType, name, description, ref, outputKey, nodeSchema, config, status: termStatus, source, innerRef, reduceRef, inputTemplate, ask, condition, runState, pending } = data;
28521
+ const { nodeType, name, description, ref, refAgentName, refAgentType, refDeleted, outputKey, nodeSchema, config, status: termStatus, source, innerRef, inputTemplate, ask, condition, runState, pending } = data;
28157
28522
  const meta = TYPE_META[nodeType] || TYPE_META.agent;
28158
28523
  const termMeta = TERMINAL_STATUS_META[termStatus || ""] || TERMINAL_STATUS_META.__default;
28159
28524
  const ssc = runState ? STEP_STATUS_CONFIG[runState.status] || STEP_STATUS_CONFIG.running : null;
@@ -28253,6 +28618,7 @@ var WorkflowNode = ({ data }) => {
28253
28618
  boxShadow: cardShadow,
28254
28619
  border: `1px solid #e5e7eb`,
28255
28620
  borderLeft: `3px solid ${leftBorderColor}`,
28621
+ borderStyle: ref ? "dashed" : "solid",
28256
28622
  overflow: "hidden",
28257
28623
  transition: "all 0.2s ease",
28258
28624
  ...pending ? { opacity: 0.5, borderStyle: "dashed" } : {}
@@ -28344,8 +28710,17 @@ var WorkflowNode = ({ data }) => {
28344
28710
  }
28345
28711
  ),
28346
28712
  /* @__PURE__ */ (0, import_jsx_runtime116.jsxs)("div", { style: { display: "flex", gap: 4, marginTop: 6, flexWrap: "wrap" }, children: [
28347
- !hasRuntime && nodeType === "agent" && ref && /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_antd89.Tag, { color: "purple", style: { margin: 0, fontSize: 10, padding: "0 5px", lineHeight: "16px" }, children: ref }),
28348
- !hasRuntime && nodeType === "agent" && !ref && /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_antd89.Tag, { color: "default", style: { margin: 0, fontSize: 10, padding: "0 5px", lineHeight: "16px" }, children: "general" }),
28713
+ !hasRuntime && nodeType === "agent" && ref && /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_antd89.Tooltip, { title: refDeleted ? `Agent "${ref}" no longer exists` : `Delegated to agent: ${refAgentName ?? ref}`, children: /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
28714
+ import_antd89.Tag,
28715
+ {
28716
+ color: refDeleted ? "red" : "purple",
28717
+ style: { margin: 0, fontSize: 10, padding: "0 5px", lineHeight: "16px" },
28718
+ icon: /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_lucide_react34.Link2, { size: 10 }),
28719
+ children: refDeleted ? `[\u5DF2\u5220\u9664] ${ref}` : `\u2192 ${refAgentName ?? ref}`
28720
+ }
28721
+ ) }),
28722
+ !hasRuntime && nodeType === "agent" && ref && refAgentType && !refDeleted && /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_antd89.Tag, { style: { margin: 0, fontSize: 10, padding: "0 5px", lineHeight: "16px" }, children: refAgentType }),
28723
+ !hasRuntime && nodeType === "agent" && !ref && /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_antd89.Tag, { color: "default", style: { margin: 0, fontSize: 10, padding: "0 5px", lineHeight: "16px" }, children: "inline" }),
28349
28724
  ask && /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_antd89.Tooltip, { title: "This step requires human approval before continuing", children: /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
28350
28725
  "div",
28351
28726
  {
@@ -28397,10 +28772,6 @@ var WorkflowNode = ({ data }) => {
28397
28772
  "\xD7",
28398
28773
  innerConcurrency ?? 5
28399
28774
  ] }),
28400
- !hasRuntime && nodeType === "map" && reduceRef && /* @__PURE__ */ (0, import_jsx_runtime116.jsxs)(import_antd89.Tag, { color: "blue", style: { margin: 0, fontSize: 10, padding: "0 5px", lineHeight: "16px" }, children: [
28401
- "\u2193 ",
28402
- reduceRef
28403
- ] }),
28404
28775
  !hasRuntime && maxRetries ? /* @__PURE__ */ (0, import_jsx_runtime116.jsxs)(import_antd89.Tag, { style: { margin: 0, fontSize: 10, padding: "0 5px", lineHeight: "16px" }, children: [
28405
28776
  "\u21BB ",
28406
28777
  maxRetries
@@ -28659,19 +29030,22 @@ function StepDetailPopover({ step }) {
28659
29030
  function matchStepByName(steps, dslNode) {
28660
29031
  return steps.find((s) => s.stepName === dslNode.name) ?? null;
28661
29032
  }
28662
- function dslNodeToData(n, runState, pending) {
29033
+ function dslNodeToData(n, runState, pending, agentNameMap) {
29034
+ const refAgent = n.ref && agentNameMap ? agentNameMap.get(n.ref) : void 0;
28663
29035
  return {
28664
29036
  nodeType: n.type,
28665
29037
  name: n.name,
28666
29038
  description: n.description,
28667
29039
  ref: n.ref,
29040
+ refAgentName: refAgent?.name,
29041
+ refAgentType: refAgent?.type,
29042
+ refDeleted: n.ref && agentNameMap ? !refAgent : void 0,
28668
29043
  outputKey: n.output?.key,
28669
29044
  nodeSchema: n.output?.schema,
28670
29045
  config: n.config,
28671
29046
  status: n.status,
28672
29047
  source: n.source,
28673
29048
  innerRef: n.node?.ref,
28674
- reduceRef: n.reduce?.ref,
28675
29049
  inputTemplate: n.input?.template,
28676
29050
  ask: n.ask,
28677
29051
  condition: n.condition,
@@ -28719,7 +29093,7 @@ function GroupLabelNode() {
28719
29093
  }, children: "Parallel" })
28720
29094
  ] });
28721
29095
  }
28722
- function buildGraph(dsl) {
29096
+ function buildGraph(dsl, agentNameMap) {
28723
29097
  const canvasNodes = dsl.nodes;
28724
29098
  const canvasEdges = dsl.edges;
28725
29099
  const parallelGroups = resolveParallelGroups(canvasNodes);
@@ -28755,7 +29129,7 @@ function buildGraph(dsl) {
28755
29129
  id: n.id,
28756
29130
  type: "workflow",
28757
29131
  position: pos,
28758
- data: { ...dslNodeToData(n) }
29132
+ data: { ...dslNodeToData(n, void 0, void 0, agentNameMap) }
28759
29133
  };
28760
29134
  });
28761
29135
  for (const group of parallelGroups) {
@@ -28777,7 +29151,7 @@ function buildGraph(dsl) {
28777
29151
  id: child.id,
28778
29152
  type: "workflow",
28779
29153
  position: { x: childStartX + i * (NODE_WIDTH + NODE_GAP), y: childY },
28780
- data: { ...dslNodeToData(child), parallelGroup: true },
29154
+ data: { ...dslNodeToData(child, void 0, void 0, agentNameMap), parallelGroup: true },
28781
29155
  style: { zIndex: 2 }
28782
29156
  });
28783
29157
  }
@@ -28815,7 +29189,7 @@ function buildGraph(dsl) {
28815
29189
  }
28816
29190
  return { nodes: reactNodes, edges: reactEdges };
28817
29191
  }
28818
- function buildRuntimeGraph(dsl, steps) {
29192
+ function buildRuntimeGraph(dsl, steps, _unused, agentNameMap) {
28819
29193
  const canvasNodes = dsl.nodes;
28820
29194
  const canvasEdges = dsl.edges;
28821
29195
  const parallelGroups = resolveParallelGroups(canvasNodes);
@@ -28855,7 +29229,7 @@ function buildRuntimeGraph(dsl, steps) {
28855
29229
  type: "workflow",
28856
29230
  position: pos,
28857
29231
  style: isTerminal ? { width: NODE_WIDTH, height: NODE_HEIGHT } : void 0,
28858
- data: dslNodeToData(n, runState, !step && !isTerminal)
29232
+ data: dslNodeToData(n, runState, !step && !isTerminal, agentNameMap)
28859
29233
  };
28860
29234
  });
28861
29235
  for (const group of parallelGroups) {
@@ -28878,7 +29252,7 @@ function buildRuntimeGraph(dsl, steps) {
28878
29252
  id: child.id,
28879
29253
  type: "workflow",
28880
29254
  position: { x: childStartX + i * (NODE_WIDTH + NODE_GAP), y: childY },
28881
- data: { ...dslNodeToData(child, runState, !step), parallelGroup: true },
29255
+ data: { ...dslNodeToData(child, runState, !step, agentNameMap), parallelGroup: true },
28882
29256
  style: { zIndex: 2 }
28883
29257
  });
28884
29258
  }
@@ -28929,6 +29303,7 @@ var WorkflowCanvas = ({
28929
29303
  dsl,
28930
29304
  steps,
28931
29305
  assistantId,
29306
+ agentNameMap,
28932
29307
  onNodeClick,
28933
29308
  height = "100%"
28934
29309
  }) => {
@@ -28938,8 +29313,8 @@ var WorkflowCanvas = ({
28938
29313
  groupLabel: GroupLabelNode
28939
29314
  }), []);
28940
29315
  const { nodes: initialNodes, edges: initialEdges } = (0, import_react96.useMemo)(
28941
- () => isRuntime ? buildRuntimeGraph(dsl, steps) : buildGraph(dsl),
28942
- [dsl, steps, isRuntime]
29316
+ () => isRuntime ? buildRuntimeGraph(dsl, steps, void 0, agentNameMap) : buildGraph(dsl, agentNameMap),
29317
+ [dsl, steps, isRuntime, agentNameMap]
28943
29318
  );
28944
29319
  const [nodes, setNodes, onNodesChange] = (0, import_react97.useNodesState)(initialNodes);
28945
29320
  const [edges, setEdges, onEdgesChange] = (0, import_react97.useEdgesState)(initialEdges);
@@ -30625,6 +31000,7 @@ function WorkflowFlowInner({
30625
31000
  onCreate,
30626
31001
  onDelete,
30627
31002
  dsl,
31003
+ agentNameMap,
30628
31004
  onSpecClick,
30629
31005
  environmentConfig
30630
31006
  }) {
@@ -30652,7 +31028,7 @@ function WorkflowFlowInner({
30652
31028
  };
30653
31029
  return /* @__PURE__ */ (0, import_jsx_runtime125.jsx)("div", { style: { display: "flex", height: "100%", width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime125.jsxs)("div", { style: { flex: 1, position: "relative" }, children: [
30654
31030
  selected ? /* @__PURE__ */ (0, import_jsx_runtime125.jsxs)(import_jsx_runtime125.Fragment, { children: [
30655
- dsl ? /* @__PURE__ */ (0, import_jsx_runtime125.jsx)(WorkflowCanvas_default, { dsl }) : /* @__PURE__ */ (0, import_jsx_runtime125.jsx)("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime125.jsx)(import_antd96.Spin, { tip: "Loading workflow DSL..." }) }),
31031
+ dsl ? /* @__PURE__ */ (0, import_jsx_runtime125.jsx)(WorkflowCanvas_default, { dsl, agentNameMap }) : /* @__PURE__ */ (0, import_jsx_runtime125.jsx)("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime125.jsx)(import_antd96.Spin, { tip: "Loading workflow DSL..." }) }),
30656
31032
  !listOpen && /* @__PURE__ */ (0, import_jsx_runtime125.jsx)("div", { style: {
30657
31033
  position: "absolute",
30658
31034
  top: 12,
@@ -30900,12 +31276,18 @@ var WorkflowAutomationView = () => {
30900
31276
  const [dsl, setDsl] = (0, import_react105.useState)(null);
30901
31277
  const [graphDef, setGraphDef] = (0, import_react105.useState)(null);
30902
31278
  const [agentConfigs, setAgentConfigs] = (0, import_react105.useState)([]);
31279
+ const [agentNameMap, setAgentNameMap] = (0, import_react105.useState)(/* @__PURE__ */ new Map());
30903
31280
  const fetchAllAssistants = (0, import_react105.useCallback)(async () => {
30904
31281
  try {
30905
31282
  const res = await get("/api/assistants");
30906
31283
  if (res.success && res.data?.records) {
30907
31284
  const cfgs = [];
31285
+ const nameMap = /* @__PURE__ */ new Map();
30908
31286
  for (const a of res.data.records) {
31287
+ if (a.id && a.name) {
31288
+ const def = typeof a.graphDefinition === "object" && a.graphDefinition !== null ? a.graphDefinition : void 0;
31289
+ nameMap.set(a.id, { name: a.name, type: def?.type ?? "unknown" });
31290
+ }
30909
31291
  if (!a.graphDefinition) continue;
30910
31292
  if (typeof a.graphDefinition === "string") {
30911
31293
  try {
@@ -30917,6 +31299,7 @@ var WorkflowAutomationView = () => {
30917
31299
  }
30918
31300
  }
30919
31301
  setAgentConfigs(cfgs);
31302
+ setAgentNameMap(nameMap);
30920
31303
  }
30921
31304
  } catch {
30922
31305
  }
@@ -31153,6 +31536,7 @@ var WorkflowAutomationView = () => {
31153
31536
  onCreate: () => setCreateModalOpen(true),
31154
31537
  onDelete: handleDelete,
31155
31538
  dsl,
31539
+ agentNameMap,
31156
31540
  onSpecClick: () => setSpecModalOpen(true),
31157
31541
  environmentConfig
31158
31542
  }
@@ -32639,7 +33023,7 @@ var PersonalAssistantChannelModal = ({
32639
33023
  bindingsLoadIdRef.current = requestId;
32640
33024
  setBindingsLoading(true);
32641
33025
  try {
32642
- const res = await get(`/api/channel-bindings?channelInstallationId=${installationId}`);
33026
+ const res = await get(`/api/channel-bindings?channelInstallationId=${installationId}&agentId=${assistantId}`);
32643
33027
  if (bindingsLoadIdRef.current !== requestId) return;
32644
33028
  if (res.success) {
32645
33029
  setBindings(res.data?.records ?? []);
@@ -34435,11 +34819,8 @@ var WorkspaceResourceManager = ({
34435
34819
  }
34436
34820
  }, [fetchedCustomMenuItems]);
34437
34821
  const menuItems = (0, import_react115.useMemo)(() => {
34438
- const workspaceMenu = config.workspaceMenuItems?.length ? config.workspaceMenuItems : void 0;
34439
- if (workspaceMenu) {
34440
- return [...workspaceMenu].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
34441
- }
34442
- const merged = fetchedCustomMenuItems.length > 0 ? mergeMenuItems(DEFAULT_WORKSPACE_MENU_ITEMS, fetchedCustomMenuItems) : [...DEFAULT_WORKSPACE_MENU_ITEMS];
34822
+ const base = config.workspaceMenuItems?.length ? config.workspaceMenuItems : DEFAULT_WORKSPACE_MENU_ITEMS;
34823
+ const merged = fetchedCustomMenuItems.length > 0 ? mergeMenuItems([...base], fetchedCustomMenuItems) : [...base];
34443
34824
  return merged;
34444
34825
  }, [config.workspaceMenuItems, fetchedCustomMenuItems]);
34445
34826
  const getContextMenuItems = (0, import_react115.useCallback)(