@datatechsolutions/ui 2.11.42 → 2.11.44

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.
@@ -8,7 +8,7 @@ import { Position, NodeResizer, MarkerType, useReactFlow, getBezierPath, BaseEdg
8
8
  import '@xyflow/react/dist/style.css';
9
9
  import { create } from 'zustand';
10
10
  import { PlusIcon, XMarkIcon } from '@heroicons/react/24/solid';
11
- import { Bars2Icon, CursorArrowRaysIcon, HandRaisedIcon, MagnifyingGlassPlusIcon, MagnifyingGlassMinusIcon, ArrowsPointingInIcon, ArrowUturnLeftIcon, ArrowUturnRightIcon, MapIcon, EllipsisHorizontalIcon, Squares2X2Icon, ArrowsRightLeftIcon, CommandLineIcon, ExclamationTriangleIcon, CpuChipIcon, TrashIcon, WrenchScrewdriverIcon, NewspaperIcon, ChartBarIcon, CloudIcon, ScaleIcon, AdjustmentsHorizontalIcon, CircleStackIcon, PlayIcon, StopIcon, ArrowsPointingOutIcon, CodeBracketIcon, GlobeAltIcon, DocumentTextIcon, ArrowPathIcon, BookOpenIcon, ChatBubbleLeftRightIcon, QuestionMarkCircleIcon, AdjustmentsVerticalIcon, Square3Stack3DIcon, DocumentMagnifyingGlassIcon, ListBulletIcon, PlayCircleIcon, PencilSquareIcon, ServerStackIcon, KeyIcon, RectangleGroupIcon, ChevronDownIcon, ChevronUpIcon, PresentationChartBarIcon, ChartPieIcon, ChartBarSquareIcon, CurrencyDollarIcon, ShieldCheckIcon, ClipboardDocumentCheckIcon, FireIcon, ShoppingBagIcon, UsersIcon, BuildingStorefrontIcon, PencilIcon, DocumentDuplicateIcon, ClipboardDocumentIcon, ClipboardIcon, PlusIcon as PlusIcon$1, XMarkIcon as XMarkIcon$1 } from '@heroicons/react/24/outline';
11
+ import { Bars2Icon, CursorArrowRaysIcon, HandRaisedIcon, MagnifyingGlassPlusIcon, MagnifyingGlassMinusIcon, ArrowsPointingInIcon, ArrowUturnLeftIcon, ArrowUturnRightIcon, MapIcon, EllipsisHorizontalIcon, Squares2X2Icon, ArrowsRightLeftIcon, CommandLineIcon, ExclamationTriangleIcon, CpuChipIcon, TrashIcon, WrenchScrewdriverIcon, NewspaperIcon, ChartBarIcon, CloudIcon, ScaleIcon, AdjustmentsHorizontalIcon, CircleStackIcon, PlayIcon, StopIcon, ArrowsPointingOutIcon, CodeBracketIcon, GlobeAltIcon, DocumentTextIcon, ArrowPathIcon, BookOpenIcon, ChatBubbleLeftRightIcon, QuestionMarkCircleIcon, AdjustmentsVerticalIcon, Square3Stack3DIcon, DocumentMagnifyingGlassIcon, ListBulletIcon, PlayCircleIcon, PencilSquareIcon, ServerStackIcon, KeyIcon, RectangleGroupIcon, ChevronDownIcon, ChevronUpIcon, PresentationChartBarIcon, ChartPieIcon, ChartBarSquareIcon, CurrencyDollarIcon, ShieldCheckIcon, ClipboardDocumentCheckIcon, FireIcon, ShoppingBagIcon, UsersIcon, BuildingStorefrontIcon, PencilIcon, DocumentDuplicateIcon, ClipboardDocumentIcon, ClipboardIcon, PlusIcon as PlusIcon$1, XMarkIcon as XMarkIcon$1, TableCellsIcon, FunnelIcon, Cog6ToothIcon, VariableIcon, MagnifyingGlassIcon, CheckIcon } from '@heroicons/react/24/outline';
12
12
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
13
13
 
14
14
  var DEFAULT_PASTE_OFFSET = 40;
@@ -1153,6 +1153,481 @@ function getEntityHandleColor(entityKey) {
1153
1153
  function getEntityMinimapColor(entityKey) {
1154
1154
  return presetFromKey(entityKey).minimapColor;
1155
1155
  }
1156
+ var DATASOURCE_LOGOS = {
1157
+ bigquery: "/logos/datasources/bigquery.svg",
1158
+ postgres: "/logos/datasources/postgres.svg",
1159
+ snowflake: "/logos/datasources/snowflake.svg",
1160
+ mongodb: "/logos/datasources/mongodb.svg",
1161
+ redis: "/logos/datasources/redis.svg",
1162
+ mysql: "/logos/datasources/mysql.svg",
1163
+ clickhouse: "/logos/datasources/clickhouse.svg",
1164
+ elasticsearch: "/logos/datasources/elasticsearch.svg",
1165
+ duckdb: "/logos/datasources/duckdb.svg",
1166
+ sqlite: "/logos/datasources/sqlite.svg",
1167
+ mariadb: "/logos/datasources/mariadb.svg",
1168
+ oracle: "/logos/datasources/oracle.svg",
1169
+ mssql: "/logos/datasources/mssql.svg",
1170
+ sqlserver: "/logos/datasources/mssql.svg",
1171
+ cassandra: "/logos/datasources/cassandra.svg",
1172
+ dynamodb: "/logos/datasources/dynamodb.svg",
1173
+ cockroach: "/logos/datasources/cockroachdb.svg",
1174
+ supabase: "/logos/datasources/supabase.svg",
1175
+ firebase: "/logos/datasources/firebase.svg",
1176
+ neo4j: "/logos/datasources/neo4j.svg"
1177
+ };
1178
+ function getDatasourceLogo(datasourceId, dialect) {
1179
+ const search = (dialect ?? datasourceId).toLowerCase();
1180
+ for (const [key, url] of Object.entries(DATASOURCE_LOGOS)) {
1181
+ if (search.includes(key)) return url;
1182
+ }
1183
+ return null;
1184
+ }
1185
+ var TYPE_COLORS = {
1186
+ string: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
1187
+ varchar: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
1188
+ text: "bg-gray-500/10 text-gray-500 dark:text-gray-400",
1189
+ integer: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
1190
+ int: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
1191
+ bigint: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
1192
+ number: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
1193
+ decimal: "bg-indigo-500/10 text-indigo-600 dark:text-indigo-400",
1194
+ float: "bg-indigo-500/10 text-indigo-600 dark:text-indigo-400",
1195
+ boolean: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
1196
+ date: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
1197
+ timestamp: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
1198
+ datetime: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
1199
+ json: "bg-violet-500/10 text-violet-600 dark:text-violet-400",
1200
+ jsonb: "bg-violet-500/10 text-violet-600 dark:text-violet-400",
1201
+ uuid: "bg-teal-500/10 text-teal-600 dark:text-teal-400",
1202
+ array: "bg-pink-500/10 text-pink-600 dark:text-pink-400"
1203
+ };
1204
+ var SIDEBAR_SECTIONS = [
1205
+ { id: "connection", label: "Connection", icon: CircleStackIcon },
1206
+ { id: "table", label: "Table", icon: TableCellsIcon },
1207
+ { id: "columns", label: "Columns", icon: TableCellsIcon },
1208
+ { id: "filters", label: "Filters", icon: FunnelIcon },
1209
+ { id: "output", label: "Output", icon: Cog6ToothIcon }
1210
+ ];
1211
+ function DatasourceNodeConfigForm({
1212
+ open,
1213
+ nodeId,
1214
+ config,
1215
+ onSave,
1216
+ onCancel,
1217
+ datasources,
1218
+ onLoadTables,
1219
+ onLoadSchema
1220
+ }) {
1221
+ const t = useTranslations("agents.workflow.datasourceNodeConfig");
1222
+ const [activeSectionId, setActiveSectionId] = useState("connection");
1223
+ const [selectedDatasourceId, setSelectedDatasourceId] = useState(config.datasourceId ?? "");
1224
+ const [selectedTable, setSelectedTable] = useState(config.table ?? "");
1225
+ const [availableTables, setAvailableTables] = useState([]);
1226
+ const [availableColumns, setAvailableColumns] = useState([]);
1227
+ const [selectedColumns, setSelectedColumns] = useState([...config.selectedColumns ?? []]);
1228
+ const [outputVariable, setOutputVariable] = useState(config.outputVariable);
1229
+ const [limit, setLimit] = useState(config.limit);
1230
+ const [filterVariables, setFilterVariables] = useState({ ...config.filterVariables });
1231
+ const [tableSearch, setTableSearch] = useState("");
1232
+ const [columnSearch, setColumnSearch] = useState("");
1233
+ const allColumnNames = availableColumns.map((column) => column.name);
1234
+ const allSelected = selectedColumns.length > 0 && selectedColumns.length === allColumnNames.length;
1235
+ const selectedDatasource = datasources.find((datasource) => datasource.id === selectedDatasourceId);
1236
+ const filteredTables = useMemo(
1237
+ () => tableSearch ? availableTables.filter((table) => table.toLowerCase().includes(tableSearch.toLowerCase())) : availableTables,
1238
+ [availableTables, tableSearch]
1239
+ );
1240
+ const filteredColumns = useMemo(
1241
+ () => columnSearch ? availableColumns.filter((column) => column.name.toLowerCase().includes(columnSearch.toLowerCase())) : availableColumns,
1242
+ [availableColumns, columnSearch]
1243
+ );
1244
+ const loadTables = useCallback(async (datasourceId) => {
1245
+ if (!datasourceId) {
1246
+ setAvailableTables([]);
1247
+ return;
1248
+ }
1249
+ const tables = await onLoadTables(datasourceId);
1250
+ setAvailableTables(tables);
1251
+ }, [onLoadTables]);
1252
+ const loadSchema = useCallback(async (datasourceId, table) => {
1253
+ if (!datasourceId || !table) {
1254
+ setAvailableColumns([]);
1255
+ return;
1256
+ }
1257
+ const columns = await onLoadSchema(datasourceId, table);
1258
+ setAvailableColumns(columns);
1259
+ }, [onLoadSchema]);
1260
+ useEffect(() => {
1261
+ if (selectedDatasourceId) loadTables(selectedDatasourceId);
1262
+ }, [selectedDatasourceId, loadTables]);
1263
+ useEffect(() => {
1264
+ if (selectedDatasourceId && selectedTable) loadSchema(selectedDatasourceId, selectedTable);
1265
+ }, [selectedDatasourceId, selectedTable, loadSchema]);
1266
+ const handleDatasourceChange = (datasourceId) => {
1267
+ setSelectedDatasourceId(datasourceId);
1268
+ setSelectedTable("");
1269
+ setAvailableTables([]);
1270
+ setAvailableColumns([]);
1271
+ setSelectedColumns([]);
1272
+ setFilterVariables({});
1273
+ setTableSearch("");
1274
+ setColumnSearch("");
1275
+ };
1276
+ const handleTableChange = (table) => {
1277
+ setSelectedTable(table);
1278
+ setAvailableColumns([]);
1279
+ setSelectedColumns([]);
1280
+ setFilterVariables({});
1281
+ setColumnSearch("");
1282
+ };
1283
+ const handleToggleColumn = (columnName) => {
1284
+ setSelectedColumns(
1285
+ (previous) => previous.includes(columnName) ? previous.filter((name) => name !== columnName) : [...previous, columnName]
1286
+ );
1287
+ };
1288
+ const handleAddFilter = () => {
1289
+ setFilterVariables((previous) => ({ ...previous, [`field_${Object.keys(previous).length}`]: "" }));
1290
+ };
1291
+ const handleUpdateFilterVariable = (oldKey, newKey) => {
1292
+ setFilterVariables((previous) => {
1293
+ const updated = { ...previous };
1294
+ const value = updated[oldKey] ?? "";
1295
+ delete updated[oldKey];
1296
+ updated[newKey] = value;
1297
+ return updated;
1298
+ });
1299
+ };
1300
+ const handleUpdateFilterField = (key, newValue) => {
1301
+ setFilterVariables((previous) => ({ ...previous, [key]: newValue }));
1302
+ };
1303
+ const handleRemoveFilter = (key) => {
1304
+ setFilterVariables((previous) => {
1305
+ const updated = { ...previous };
1306
+ delete updated[key];
1307
+ return updated;
1308
+ });
1309
+ };
1310
+ const handleSave = () => {
1311
+ const cleanedFilters = {};
1312
+ for (const [key, value] of Object.entries(filterVariables)) {
1313
+ if (key.trim() && value.trim()) cleanedFilters[key.trim()] = value.trim();
1314
+ }
1315
+ onSave({
1316
+ ...config,
1317
+ datasourceId: selectedDatasourceId,
1318
+ dialect: selectedDatasource?.dialect ?? "",
1319
+ table: selectedTable,
1320
+ selectedColumns,
1321
+ outputVariable: outputVariable.trim(),
1322
+ limit,
1323
+ filterVariables: cleanedFilters
1324
+ });
1325
+ };
1326
+ const filterEntries = Object.entries(filterVariables);
1327
+ const canSave = selectedDatasourceId && selectedTable && selectedColumns.length > 0;
1328
+ function renderSection() {
1329
+ switch (activeSectionId) {
1330
+ case "connection":
1331
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1332
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("datasourceHelp") }),
1333
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: datasources.map((datasource) => {
1334
+ const isSelected = datasource.id === selectedDatasourceId;
1335
+ const logo2 = getDatasourceLogo(datasource.id, datasource.dialect);
1336
+ return /* @__PURE__ */ jsxs(
1337
+ "button",
1338
+ {
1339
+ type: "button",
1340
+ onClick: () => {
1341
+ handleDatasourceChange(datasource.id);
1342
+ setActiveSectionId("table");
1343
+ },
1344
+ className: `flex items-center gap-3 rounded-xl border px-3 py-2.5 text-left transition-all ${isSelected ? "border-cyan-500/50 bg-cyan-500/5 ring-1 ring-cyan-500/20 dark:border-cyan-400/40 dark:bg-cyan-400/5" : "border-gray-200 bg-white hover:border-gray-300 hover:shadow-sm dark:border-white/10 dark:bg-white/[0.03] dark:hover:border-white/20"}`,
1345
+ children: [
1346
+ /* @__PURE__ */ jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center", children: logo2 ? /* @__PURE__ */ jsx("img", { src: logo2, alt: datasource.dialect, className: "h-7 w-7" }) : /* @__PURE__ */ jsx(ServerStackIcon, { className: "h-6 w-6 text-gray-400" }) }),
1347
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1348
+ /* @__PURE__ */ jsx("p", { className: "truncate text-xs font-semibold text-gray-900 dark:text-white", children: datasource.name }),
1349
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: datasource.dialect })
1350
+ ] }),
1351
+ isSelected && /* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4 shrink-0 text-cyan-500 dark:text-cyan-400" })
1352
+ ]
1353
+ },
1354
+ datasource.id
1355
+ );
1356
+ }) })
1357
+ ] });
1358
+ case "table":
1359
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1360
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("tableHelp") }),
1361
+ !selectedDatasourceId ? /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-xs text-gray-400", children: t("selectDatasource") }) : /* @__PURE__ */ jsxs("div", { className: "liquid-surface rounded-xl border border-white/30 dark:border-white/10", children: [
1362
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-gray-200/50 px-3 py-2 dark:border-white/5", children: [
1363
+ /* @__PURE__ */ jsx(MagnifyingGlassIcon, { className: "h-3.5 w-3.5 text-gray-400" }),
1364
+ /* @__PURE__ */ jsx(
1365
+ "input",
1366
+ {
1367
+ type: "text",
1368
+ value: tableSearch,
1369
+ onChange: (event) => setTableSearch(event.target.value),
1370
+ placeholder: t("selectTable"),
1371
+ className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
1372
+ }
1373
+ ),
1374
+ availableTables.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400", children: availableTables.length })
1375
+ ] }),
1376
+ /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-y-auto p-1", children: [
1377
+ filteredTables.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-[10px] text-gray-400", children: t("noColumnsAvailable") }),
1378
+ filteredTables.map((table) => {
1379
+ const isSelected = table === selectedTable;
1380
+ return /* @__PURE__ */ jsxs(
1381
+ "button",
1382
+ {
1383
+ type: "button",
1384
+ onClick: () => {
1385
+ handleTableChange(table);
1386
+ setActiveSectionId("columns");
1387
+ },
1388
+ className: `flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-xs transition-colors ${isSelected ? "bg-cyan-500/10 font-semibold text-cyan-700 dark:text-cyan-300" : "text-gray-700 hover:bg-gray-100/60 dark:text-gray-300 dark:hover:bg-white/5"}`,
1389
+ children: [
1390
+ /* @__PURE__ */ jsx(TableCellsIcon, { className: "h-3.5 w-3.5 shrink-0 text-gray-400" }),
1391
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: table }),
1392
+ isSelected && /* @__PURE__ */ jsx(CheckIcon, { className: "ml-auto h-3.5 w-3.5 shrink-0 text-cyan-500" })
1393
+ ]
1394
+ },
1395
+ table
1396
+ );
1397
+ })
1398
+ ] })
1399
+ ] })
1400
+ ] });
1401
+ case "columns":
1402
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1403
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1404
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
1405
+ selectedColumns.length,
1406
+ "/",
1407
+ availableColumns.length,
1408
+ " selected"
1409
+ ] }),
1410
+ /* @__PURE__ */ jsx(
1411
+ "button",
1412
+ {
1413
+ type: "button",
1414
+ onClick: () => setSelectedColumns(allSelected ? [] : [...allColumnNames]),
1415
+ disabled: availableColumns.length === 0,
1416
+ className: "text-[10px] font-semibold text-cyan-600 hover:text-cyan-700 disabled:opacity-40 dark:text-cyan-400",
1417
+ children: allSelected ? t("deselectAll") : t("selectAll")
1418
+ }
1419
+ )
1420
+ ] }),
1421
+ !selectedTable ? /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-xs text-gray-400", children: t("selectTable") }) : /* @__PURE__ */ jsxs("div", { className: "liquid-surface rounded-xl border border-white/30 dark:border-white/10", children: [
1422
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-gray-200/50 px-3 py-2 dark:border-white/5", children: [
1423
+ /* @__PURE__ */ jsx(MagnifyingGlassIcon, { className: "h-3.5 w-3.5 text-gray-400" }),
1424
+ /* @__PURE__ */ jsx(
1425
+ "input",
1426
+ {
1427
+ type: "text",
1428
+ value: columnSearch,
1429
+ onChange: (event) => setColumnSearch(event.target.value),
1430
+ placeholder: "Search columns...",
1431
+ className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
1432
+ }
1433
+ )
1434
+ ] }),
1435
+ /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-y-auto p-1", children: [
1436
+ filteredColumns.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-[10px] text-gray-400", children: t("noColumnsAvailable") }),
1437
+ filteredColumns.map((column) => {
1438
+ const isSelected = selectedColumns.includes(column.name);
1439
+ const typeColor = TYPE_COLORS[column.type.toLowerCase()] ?? TYPE_COLORS.string;
1440
+ return /* @__PURE__ */ jsxs(
1441
+ "button",
1442
+ {
1443
+ type: "button",
1444
+ onClick: () => handleToggleColumn(column.name),
1445
+ className: `flex w-full items-center gap-2 rounded-lg px-3 py-1.5 text-left transition-colors ${isSelected ? "bg-cyan-500/8 dark:bg-cyan-400/5" : "hover:bg-gray-100/60 dark:hover:bg-white/5"}`,
1446
+ children: [
1447
+ /* @__PURE__ */ jsx("div", { className: `flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors ${isSelected ? "border-cyan-500 bg-cyan-500 dark:border-cyan-400 dark:bg-cyan-400" : "border-gray-300 dark:border-gray-600"}`, children: isSelected && /* @__PURE__ */ jsx(CheckIcon, { className: "h-2.5 w-2.5 text-white" }) }),
1448
+ /* @__PURE__ */ jsxs("span", { className: "flex-1 truncate text-xs text-gray-900 dark:text-white", children: [
1449
+ column.name,
1450
+ column.nullable && /* @__PURE__ */ jsx("span", { className: "ml-1 text-[9px] text-gray-400", children: "?" })
1451
+ ] }),
1452
+ /* @__PURE__ */ jsx("span", { className: `shrink-0 rounded-full px-1.5 py-0.5 text-[9px] font-medium ${typeColor}`, children: column.type })
1453
+ ]
1454
+ },
1455
+ column.name
1456
+ );
1457
+ })
1458
+ ] })
1459
+ ] })
1460
+ ] });
1461
+ case "filters":
1462
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1463
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1464
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("filtersHelp") }),
1465
+ /* @__PURE__ */ jsxs(
1466
+ "button",
1467
+ {
1468
+ type: "button",
1469
+ onClick: handleAddFilter,
1470
+ className: "flex items-center gap-1 text-[10px] font-semibold text-cyan-600 hover:text-cyan-700 dark:text-cyan-400",
1471
+ children: [
1472
+ /* @__PURE__ */ jsx(PlusIcon$1, { className: "h-3 w-3" }),
1473
+ t("addFilter")
1474
+ ]
1475
+ }
1476
+ )
1477
+ ] }),
1478
+ filterEntries.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 py-8", children: [
1479
+ /* @__PURE__ */ jsx(FunnelIcon, { className: "h-8 w-8 text-gray-300 dark:text-gray-600" }),
1480
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400", children: "No filters configured" }),
1481
+ /* @__PURE__ */ jsxs(
1482
+ "button",
1483
+ {
1484
+ type: "button",
1485
+ onClick: handleAddFilter,
1486
+ className: "flex items-center gap-1 rounded-lg bg-cyan-500/10 px-3 py-1.5 text-[10px] font-semibold text-cyan-600 hover:bg-cyan-500/15 dark:text-cyan-400",
1487
+ children: [
1488
+ /* @__PURE__ */ jsx(PlusIcon$1, { className: "h-3 w-3" }),
1489
+ t("addFilter")
1490
+ ]
1491
+ }
1492
+ )
1493
+ ] }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: filterEntries.map(([variableName, columnName], index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-xl border border-gray-200 bg-white px-3 py-2 dark:border-white/10 dark:bg-white/[0.03]", children: [
1494
+ /* @__PURE__ */ jsxs(
1495
+ "select",
1496
+ {
1497
+ value: columnName,
1498
+ onChange: (event) => handleUpdateFilterField(variableName, event.target.value),
1499
+ className: "flex-1 rounded bg-transparent text-xs text-gray-900 outline-none dark:text-white",
1500
+ children: [
1501
+ /* @__PURE__ */ jsx("option", { value: "", children: t("columnName") }),
1502
+ availableColumns.map((column) => /* @__PURE__ */ jsx("option", { value: column.name, children: column.name }, column.name))
1503
+ ]
1504
+ }
1505
+ ),
1506
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold text-gray-400", children: "=" }),
1507
+ /* @__PURE__ */ jsx(
1508
+ "input",
1509
+ {
1510
+ type: "text",
1511
+ value: variableName,
1512
+ onChange: (event) => handleUpdateFilterVariable(variableName, event.target.value),
1513
+ placeholder: t("variableReference"),
1514
+ className: "flex-1 bg-transparent text-xs text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
1515
+ }
1516
+ ),
1517
+ /* @__PURE__ */ jsx(
1518
+ "button",
1519
+ {
1520
+ type: "button",
1521
+ onClick: () => handleRemoveFilter(variableName),
1522
+ className: "shrink-0 rounded-md p-1 text-gray-400 transition-colors hover:bg-red-50 hover:text-red-500 dark:hover:bg-red-900/20",
1523
+ children: /* @__PURE__ */ jsx(XMarkIcon$1, { className: "h-3 w-3" })
1524
+ }
1525
+ )
1526
+ ] }, index)) })
1527
+ ] });
1528
+ case "output":
1529
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
1530
+ /* @__PURE__ */ jsxs("div", { children: [
1531
+ /* @__PURE__ */ jsx("label", { className: "mb-1.5 block text-xs font-medium text-gray-700 dark:text-gray-300", children: t("outputVariableLabel") }),
1532
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[10px] text-gray-500 dark:text-gray-400", children: t("outputVariableHelp") }),
1533
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-xl border border-gray-200 bg-white px-3 py-2.5 dark:border-white/10 dark:bg-white/[0.03]", children: [
1534
+ /* @__PURE__ */ jsx(VariableIcon, { className: "h-4 w-4 text-gray-400" }),
1535
+ /* @__PURE__ */ jsx(
1536
+ "input",
1537
+ {
1538
+ type: "text",
1539
+ value: outputVariable,
1540
+ onChange: (event) => setOutputVariable(event.target.value),
1541
+ placeholder: "datasourceResult",
1542
+ className: "flex-1 bg-transparent text-sm text-gray-900 outline-none placeholder:text-gray-400 dark:text-white dark:placeholder:text-gray-500"
1543
+ }
1544
+ )
1545
+ ] })
1546
+ ] }),
1547
+ /* @__PURE__ */ jsxs("div", { children: [
1548
+ /* @__PURE__ */ jsx("label", { className: "mb-1.5 block text-xs font-medium text-gray-700 dark:text-gray-300", children: t("limitLabel") }),
1549
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[10px] text-gray-500 dark:text-gray-400", children: t("limitHelp") }),
1550
+ /* @__PURE__ */ jsx(
1551
+ "input",
1552
+ {
1553
+ type: "number",
1554
+ value: limit,
1555
+ onChange: (event) => setLimit(Math.max(1, Number.parseInt(event.target.value, 10) || 1)),
1556
+ min: 1,
1557
+ max: 1e4,
1558
+ className: "w-32 rounded-xl border border-gray-200 bg-white px-3 py-2.5 text-sm text-gray-900 outline-none focus:border-cyan-400 dark:border-white/10 dark:bg-white/[0.03] dark:text-white"
1559
+ }
1560
+ )
1561
+ ] }),
1562
+ selectedDatasource && selectedTable && /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-cyan-500/20 bg-cyan-500/5 p-3 dark:border-cyan-400/15 dark:bg-cyan-400/5", children: [
1563
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-cyan-600 dark:text-cyan-400 mb-2", children: "Summary" }),
1564
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1 text-xs text-gray-600 dark:text-gray-300", children: [
1565
+ /* @__PURE__ */ jsxs("p", { children: [
1566
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "Source:" }),
1567
+ " ",
1568
+ selectedDatasource.name,
1569
+ " (",
1570
+ selectedDatasource.dialect,
1571
+ ")"
1572
+ ] }),
1573
+ /* @__PURE__ */ jsxs("p", { children: [
1574
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "Table:" }),
1575
+ " ",
1576
+ selectedTable
1577
+ ] }),
1578
+ /* @__PURE__ */ jsxs("p", { children: [
1579
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "Columns:" }),
1580
+ " ",
1581
+ selectedColumns.length,
1582
+ " of ",
1583
+ availableColumns.length
1584
+ ] }),
1585
+ /* @__PURE__ */ jsxs("p", { children: [
1586
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "Filters:" }),
1587
+ " ",
1588
+ filterEntries.length
1589
+ ] }),
1590
+ /* @__PURE__ */ jsxs("p", { children: [
1591
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "Limit:" }),
1592
+ " ",
1593
+ limit
1594
+ ] }),
1595
+ /* @__PURE__ */ jsxs("p", { children: [
1596
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "Output:" }),
1597
+ " ",
1598
+ outputVariable || "\u2014"
1599
+ ] })
1600
+ ] })
1601
+ ] })
1602
+ ] });
1603
+ default:
1604
+ return null;
1605
+ }
1606
+ }
1607
+ const logo = getDatasourceLogo(selectedDatasourceId, selectedDatasource?.dialect);
1608
+ return /* @__PURE__ */ jsx(
1609
+ GlassModal,
1610
+ {
1611
+ open,
1612
+ onClose: onCancel,
1613
+ title: selectedDatasource?.name ?? t("datasourceLabel"),
1614
+ subtitle: selectedTable ? `${selectedDatasource?.dialect} \xB7 ${selectedTable}` : void 0,
1615
+ icon: logo ? /* @__PURE__ */ jsx("img", { src: logo, alt: "", className: "h-5 w-5" }) : /* @__PURE__ */ jsx(ServerStackIcon, { className: "h-5 w-5 text-white" }),
1616
+ gradient: "from-cyan-500 to-blue-600",
1617
+ maxWidth: "3xl",
1618
+ sidebar: {
1619
+ sections: SIDEBAR_SECTIONS,
1620
+ activeSectionId,
1621
+ onSectionChange: setActiveSectionId
1622
+ },
1623
+ footer: /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 px-6 py-3", children: [
1624
+ /* @__PURE__ */ jsx(Button, { outline: true, onClick: onCancel, children: t("cancel") }),
1625
+ /* @__PURE__ */ jsx(Button, { color: "cyan", onClick: handleSave, disabled: !canSave, children: t("save") })
1626
+ ] }),
1627
+ children: renderSection()
1628
+ }
1629
+ );
1630
+ }
1156
1631
  function LangChainIcon({ className }) {
1157
1632
  return /* @__PURE__ */ jsx("svg", { role: "img", viewBox: "0 0 24 24", fill: "currentColor", className, "aria-label": "LangChain", children: /* @__PURE__ */ jsx("path", { d: "M6.0988 5.9175C2.7359 5.9175 0 8.6462 0 12s2.736 6.0825 6.0988 6.0825h11.8024C21.2641 18.0825 24 15.3538 24 12s-2.736-6.0825-6.0988-6.0825ZM5.9774 7.851c.493.0124 1.02.2496 1.273.6228.3673.4592.4778 1.0668.8944 1.4932.5604.6118 1.199 1.1505 1.7161 1.802.4892.5954.8386 1.2937 1.1436 1.9975.1244.2335.1257.5202.31.7197.0908.1204.5346.4483.4383.5645.0555.1204.4702.286.3263.4027-.1944.04-.4129.0476-.5616-.1074-.0549.126-.183.0596-.2819.0432a4 4 0 0 0-.025.0736c-.3288.0219-.5754-.3126-.732-.565-.3111-.168-.6642-.2702-.982-.446-.0182.2895.0452.6485-.231.8353-.014.5565.8436.0656.9222.4804-.061.0067-.1286-.0095-.1774.0373-.2239.2172-.4805-.1645-.7385-.007-.3464.174-.3808.3161-.8096.352-.0237-.0359-.0143-.0592.0059-.0811.1207-.1399.1295-.3046.3356-.3643-.2122-.0334-.3899.0833-.5686.1757-.2323.095-.2304-.2141-.5878.0164-.0396-.0322-.0208-.0615.0018-.0864.0908-.1107.2102-.127.345-.1208-.663-.3686-.9751.4507-1.2813.0432-.092.0243-.1265.1068-.1845.1652-.05-.0548-.0123-.1212-.0099-.1857-.0598-.028-.1356-.041-.1179-.1366-.1171-.0395-.1988.0295-.286.0952-.0787-.0608.0532-.1492.0776-.2125.0702-.1216.23-.025.3111-.1126.2306-.1308.552.0814.8155.0455.203.0255.4544-.1825.3526-.39-.2171-.2767-.179-.6386-.1839-.9695-.0268-.1929-.491-.4382-.6252-.6462-.1659-.1873-.295-.4047-.4243-.6182-.4666-.9008-.3198-2.0584-.9077-2.8947-.266.1466-.6125.0774-.8418-.119-.1238.1125-.1292.2598-.139.4161-.297-.2962-.2593-.8559-.022-1.1855.0969-.1302.2127-.2373.342-.3316.0292-.0213.0391-.0419.0385-.0747.1174-.5267.5764-.7391 1.0694-.7267m12.4071.46c.5575 0 1.0806.2159 1.474.6082s.61.9145.61 1.4704c0 .556-.2167 1.078-.61 1.4698v.0006l-.902.8995a2.08 2.08 0 0 1-.8597.5166l-.0164.0047-.0058.0164a2.05 2.05 0 0 1-.474.7308l-.9018.8995c-.3934.3924-.917.6083-1.4745.6083s-1.0806-.216-1.474-.6083c-.813-.8107-.813-2.1294 0-2.9402l.9019-.8995a2.056 2.056 0 0 1 .858-.5143l.017-.0053.0058-.0158a2.07 2.07 0 0 1 .4752-.7337l.9018-.8995c.3934-.3924.9171-.6083 1.4745-.6083zm0 .8965a1.18 1.18 0 0 0-.8388.3462l-.9018.8995a1.181 1.181 0 0 0-.3427.9252l.0053.0572c.0323.2652.149.5044.3374.6917.13.1296.2733.2114.4471.2686a.9.9 0 0 1 .014.1582.884.884 0 0 1-.2609.6304l-.0554.0554c-.3013-.1028-.5525-.253-.7794-.4792a2.06 2.06 0 0 1-.5761-1.0968l-.0099-.0578-.0461.0368a1.1 1.1 0 0 0-.0876.0794l-.9024.8995c-.4623.461-.4623 1.212 0 1.673.2311.2305.535.346.8394.3461.3043 0 .6077-.1156.8388-.3462l.9019-.8995c.4623-.461.4623-1.2113 0-1.673a1.17 1.17 0 0 0-.4367-.2749 1 1 0 0 1-.014-.1611c0-.2591.1023-.505.2901-.6923.3019.1028.57.2694.7962.495.3007.2999.4994.679.5756 1.0968l.0105.0578.0455-.0373a1.1 1.1 0 0 0 .0887-.0794l.902-.8996c.4622-.461.4628-1.2124 0-1.6735a1.18 1.18 0 0 0-.8395-.3462Zm-9.973 5.1567-.0006.0006c-.0793.3078-.1048.8318-.506.847-.033.1776.1228.2445.2655.1874.141-.0645.2081.0508.2557.1657.2177.0317.5394-.0725.5516-.3298-.325-.1867-.4253-.5418-.5662-.8709" }) });
1158
1633
  }
@@ -2838,7 +3313,7 @@ var NoteFlowNode = memo(function NoteFlowNode2({ data, selected }) {
2838
3313
  }
2839
3314
  );
2840
3315
  });
2841
- var DATASOURCE_LOGOS = {
3316
+ var DATASOURCE_LOGOS2 = {
2842
3317
  bigquery: "/logos/datasources/bigquery.svg",
2843
3318
  postgres: "/logos/datasources/postgres.svg",
2844
3319
  snowflake: "/logos/datasources/snowflake.svg",
@@ -2860,9 +3335,9 @@ var DATASOURCE_LOGOS = {
2860
3335
  firebase: "/logos/datasources/firebase.svg",
2861
3336
  neo4j: "/logos/datasources/neo4j.svg"
2862
3337
  };
2863
- function getDatasourceLogo(datasourceId, dialect) {
3338
+ function getDatasourceLogo2(datasourceId, dialect) {
2864
3339
  const search = (dialect ?? datasourceId).toLowerCase();
2865
- for (const [key, url] of Object.entries(DATASOURCE_LOGOS)) {
3340
+ for (const [key, url] of Object.entries(DATASOURCE_LOGOS2)) {
2866
3341
  if (search.includes(key)) return url;
2867
3342
  }
2868
3343
  return null;
@@ -2889,7 +3364,7 @@ var DatasourceFlowNode = memo(function DatasourceFlowNode2({ id, data, selected
2889
3364
  }
2890
3365
  const columnCount = config.selectedColumns?.length ?? 0;
2891
3366
  const filterCount = config.filterVariables ? Object.keys(config.filterVariables).length : 0;
2892
- const logo = getDatasourceLogo(config.datasourceId, config.dialect);
3367
+ const logo = getDatasourceLogo2(config.datasourceId, config.dialect);
2893
3368
  const content = /* @__PURE__ */ jsxs(NodeCard, { compact: isCompact, selected, nodeType: "datasource", children: [
2894
3369
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
2895
3370
  /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
@@ -4857,328 +5332,6 @@ function EntityNodeConfigForm({ config, entities = [], onSave, onCancel }) {
4857
5332
  ] })
4858
5333
  ] });
4859
5334
  }
4860
- var COLUMN_TYPE_BADGE_COLORS = {
4861
- string: "bg-gray-100 text-gray-600 dark:bg-gray-500/20 dark:text-gray-300",
4862
- varchar: "bg-gray-100 text-gray-600 dark:bg-gray-500/20 dark:text-gray-300",
4863
- text: "bg-gray-100 text-gray-600 dark:bg-gray-500/20 dark:text-gray-300",
4864
- integer: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4865
- int: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4866
- bigint: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4867
- number: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4868
- decimal: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4869
- float: "bg-blue-100 text-blue-600 dark:bg-blue-500/20 dark:text-blue-300",
4870
- boolean: "bg-green-100 text-green-600 dark:bg-green-500/20 dark:text-green-300",
4871
- date: "bg-amber-100 text-amber-600 dark:bg-amber-500/20 dark:text-amber-300",
4872
- timestamp: "bg-amber-100 text-amber-600 dark:bg-amber-500/20 dark:text-amber-300",
4873
- datetime: "bg-amber-100 text-amber-600 dark:bg-amber-500/20 dark:text-amber-300",
4874
- json: "bg-purple-100 text-purple-600 dark:bg-purple-500/20 dark:text-purple-300",
4875
- jsonb: "bg-purple-100 text-purple-600 dark:bg-purple-500/20 dark:text-purple-300",
4876
- uuid: "bg-teal-100 text-teal-600 dark:bg-teal-500/20 dark:text-teal-300"
4877
- };
4878
- function DatasourceNodeConfigForm({
4879
- nodeId,
4880
- config,
4881
- onSave,
4882
- onCancel,
4883
- datasources,
4884
- onLoadTables,
4885
- onLoadSchema
4886
- }) {
4887
- const t = useTranslations("agents.workflow.datasourceNodeConfig");
4888
- const [selectedDatasourceId, setSelectedDatasourceId] = useState(config.datasourceId ?? "");
4889
- const [selectedTable, setSelectedTable] = useState(config.table ?? "");
4890
- const [availableTables, setAvailableTables] = useState([]);
4891
- const [availableColumns, setAvailableColumns] = useState([]);
4892
- const [selectedColumns, setSelectedColumns] = useState([...config.selectedColumns ?? []]);
4893
- const [outputVariable, setOutputVariable] = useState(config.outputVariable);
4894
- const [limit, setLimit] = useState(config.limit);
4895
- const [filterVariables, setFilterVariables] = useState({ ...config.filterVariables });
4896
- const allColumnNames = availableColumns.map((column) => column.name);
4897
- const allSelected = selectedColumns.length > 0 && selectedColumns.length === allColumnNames.length;
4898
- const selectedDatasource = datasources.find((datasource) => datasource.id === selectedDatasourceId);
4899
- const loadTables = useCallback(async (datasourceId) => {
4900
- if (!datasourceId) {
4901
- setAvailableTables([]);
4902
- return;
4903
- }
4904
- const tables = await onLoadTables(datasourceId);
4905
- setAvailableTables(tables);
4906
- }, [onLoadTables]);
4907
- const loadSchema = useCallback(async (datasourceId, table) => {
4908
- if (!datasourceId || !table) {
4909
- setAvailableColumns([]);
4910
- return;
4911
- }
4912
- const columns = await onLoadSchema(datasourceId, table);
4913
- setAvailableColumns(columns);
4914
- }, [onLoadSchema]);
4915
- useEffect(() => {
4916
- if (selectedDatasourceId) {
4917
- loadTables(selectedDatasourceId);
4918
- }
4919
- }, [selectedDatasourceId, loadTables]);
4920
- useEffect(() => {
4921
- if (selectedDatasourceId && selectedTable) {
4922
- loadSchema(selectedDatasourceId, selectedTable);
4923
- }
4924
- }, [selectedDatasourceId, selectedTable, loadSchema]);
4925
- const handleDatasourceChange = (datasourceId) => {
4926
- setSelectedDatasourceId(datasourceId);
4927
- setSelectedTable("");
4928
- setAvailableTables([]);
4929
- setAvailableColumns([]);
4930
- setSelectedColumns([]);
4931
- setFilterVariables({});
4932
- };
4933
- const handleTableChange = (table) => {
4934
- setSelectedTable(table);
4935
- setAvailableColumns([]);
4936
- setSelectedColumns([]);
4937
- setFilterVariables({});
4938
- };
4939
- const handleToggleSelectAll = () => {
4940
- if (allSelected) {
4941
- setSelectedColumns([]);
4942
- } else {
4943
- setSelectedColumns([...allColumnNames]);
4944
- }
4945
- };
4946
- const handleToggleColumn = (columnName) => {
4947
- setSelectedColumns(
4948
- (previous) => previous.includes(columnName) ? previous.filter((name) => name !== columnName) : [...previous, columnName]
4949
- );
4950
- };
4951
- const handleAddFilter = () => {
4952
- setFilterVariables((previous) => ({ ...previous, "": "" }));
4953
- };
4954
- const handleUpdateFilterVariable = (oldKey, newKey) => {
4955
- setFilterVariables((previous) => {
4956
- const updated = { ...previous };
4957
- const value = updated[oldKey] ?? "";
4958
- delete updated[oldKey];
4959
- updated[newKey] = value;
4960
- return updated;
4961
- });
4962
- };
4963
- const handleUpdateFilterField = (key, newValue) => {
4964
- setFilterVariables((previous) => ({ ...previous, [key]: newValue }));
4965
- };
4966
- const handleRemoveFilter = (key) => {
4967
- setFilterVariables((previous) => {
4968
- const updated = { ...previous };
4969
- delete updated[key];
4970
- return updated;
4971
- });
4972
- };
4973
- const handleSave = () => {
4974
- const cleanedFilters = {};
4975
- for (const [key, value] of Object.entries(filterVariables)) {
4976
- if (key.trim() && value.trim()) {
4977
- cleanedFilters[key.trim()] = value.trim();
4978
- }
4979
- }
4980
- onSave({
4981
- ...config,
4982
- datasourceId: selectedDatasourceId,
4983
- dialect: selectedDatasource?.dialect ?? "",
4984
- table: selectedTable,
4985
- selectedColumns,
4986
- outputVariable: outputVariable.trim(),
4987
- limit,
4988
- filterVariables: cleanedFilters
4989
- });
4990
- };
4991
- const filterEntries = Object.entries(filterVariables);
4992
- return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
4993
- /* @__PURE__ */ jsxs("div", { children: [
4994
- /* @__PURE__ */ jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("datasourceLabel") }),
4995
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("datasourceHelp") }),
4996
- /* @__PURE__ */ jsxs(
4997
- "select",
4998
- {
4999
- value: selectedDatasourceId,
5000
- onChange: (event) => handleDatasourceChange(event.target.value),
5001
- className: "w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white",
5002
- children: [
5003
- /* @__PURE__ */ jsx("option", { value: "", children: t("selectDatasource") }),
5004
- datasources.map((datasource) => /* @__PURE__ */ jsxs("option", { value: datasource.id, children: [
5005
- datasource.name,
5006
- " (",
5007
- datasource.dialect,
5008
- ")"
5009
- ] }, datasource.id))
5010
- ]
5011
- }
5012
- ),
5013
- selectedDatasource && /* @__PURE__ */ jsx("div", { className: "mt-2 flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-300", children: selectedDatasource.dialect }) })
5014
- ] }),
5015
- /* @__PURE__ */ jsxs("div", { children: [
5016
- /* @__PURE__ */ jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("tableLabel") }),
5017
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("tableHelp") }),
5018
- /* @__PURE__ */ jsxs(
5019
- "select",
5020
- {
5021
- value: selectedTable,
5022
- onChange: (event) => handleTableChange(event.target.value),
5023
- disabled: !selectedDatasourceId,
5024
- className: "w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-400/20 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-white",
5025
- children: [
5026
- /* @__PURE__ */ jsx("option", { value: "", children: t("selectTable") }),
5027
- availableTables.map((table) => /* @__PURE__ */ jsx("option", { value: table, children: table }, table))
5028
- ]
5029
- }
5030
- )
5031
- ] }),
5032
- /* @__PURE__ */ jsxs("div", { children: [
5033
- /* @__PURE__ */ jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("outputVariableLabel") }),
5034
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("outputVariableHelp") }),
5035
- /* @__PURE__ */ jsx(
5036
- "input",
5037
- {
5038
- type: "text",
5039
- value: outputVariable,
5040
- onChange: (event) => setOutputVariable(event.target.value),
5041
- placeholder: "datasourceResult",
5042
- className: "w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 placeholder-gray-400 outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
5043
- }
5044
- )
5045
- ] }),
5046
- /* @__PURE__ */ jsxs("div", { children: [
5047
- /* @__PURE__ */ jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300", children: t("limitLabel") }),
5048
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("limitHelp") }),
5049
- /* @__PURE__ */ jsx(
5050
- "input",
5051
- {
5052
- type: "number",
5053
- value: limit,
5054
- onChange: (event) => setLimit(Math.max(1, Number.parseInt(event.target.value, 10) || 1)),
5055
- min: 1,
5056
- max: 1e4,
5057
- className: "w-32 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white"
5058
- }
5059
- )
5060
- ] }),
5061
- /* @__PURE__ */ jsxs("div", { children: [
5062
- /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
5063
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: t("columnsLabel") }),
5064
- /* @__PURE__ */ jsx(
5065
- "button",
5066
- {
5067
- type: "button",
5068
- onClick: handleToggleSelectAll,
5069
- disabled: availableColumns.length === 0,
5070
- className: "text-xs font-medium text-indigo-600 hover:text-indigo-700 disabled:cursor-not-allowed disabled:opacity-50 dark:text-indigo-400 dark:hover:text-indigo-300",
5071
- children: allSelected ? t("deselectAll") : t("selectAll")
5072
- }
5073
- )
5074
- ] }),
5075
- selectedColumns.length === 0 && availableColumns.length > 0 && /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-amber-600 dark:text-amber-400", children: t("noColumnsSelected") }),
5076
- /* @__PURE__ */ jsxs("div", { className: "max-h-48 space-y-1 overflow-y-auto rounded-lg border border-gray-200 p-2 dark:border-gray-700", children: [
5077
- availableColumns.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-2 py-2 text-xs text-gray-500 dark:text-gray-400", children: t("noColumnsAvailable") }),
5078
- availableColumns.map((column) => {
5079
- const isSelected = selectedColumns.includes(column.name);
5080
- const typeBadgeColor = COLUMN_TYPE_BADGE_COLORS[column.type.toLowerCase()] ?? COLUMN_TYPE_BADGE_COLORS.string;
5081
- return /* @__PURE__ */ jsxs(
5082
- "label",
5083
- {
5084
- className: `flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 transition-colors ${isSelected ? "bg-indigo-50 dark:bg-indigo-500/10" : "hover:bg-gray-50 dark:hover:bg-gray-800"}`,
5085
- children: [
5086
- /* @__PURE__ */ jsx(
5087
- "input",
5088
- {
5089
- type: "checkbox",
5090
- checked: isSelected,
5091
- onChange: () => handleToggleColumn(column.name),
5092
- className: "h-3.5 w-3.5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:border-gray-600"
5093
- }
5094
- ),
5095
- /* @__PURE__ */ jsxs("span", { className: "flex-1 text-xs font-medium text-gray-900 dark:text-white", children: [
5096
- column.name,
5097
- column.nullable && /* @__PURE__ */ jsx("span", { className: "ml-1 text-[9px] text-gray-400 dark:text-gray-500", children: "?" })
5098
- ] }),
5099
- /* @__PURE__ */ jsx("span", { className: `rounded-full px-1.5 py-0.5 text-[9px] font-medium ${typeBadgeColor}`, children: column.type })
5100
- ]
5101
- },
5102
- column.name
5103
- );
5104
- })
5105
- ] })
5106
- ] }),
5107
- /* @__PURE__ */ jsxs("div", { children: [
5108
- /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
5109
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: t("filtersLabel") }),
5110
- /* @__PURE__ */ jsxs(
5111
- "button",
5112
- {
5113
- type: "button",
5114
- onClick: handleAddFilter,
5115
- className: "flex items-center gap-1 text-xs font-medium text-indigo-600 hover:text-indigo-700 dark:text-indigo-400 dark:hover:text-indigo-300",
5116
- children: [
5117
- /* @__PURE__ */ jsx(PlusIcon$1, { className: "h-3 w-3" }),
5118
- t("addFilter")
5119
- ]
5120
- }
5121
- )
5122
- ] }),
5123
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs text-gray-500 dark:text-gray-400", children: t("filtersHelp") }),
5124
- filterEntries.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-2", children: filterEntries.map(([variableName, columnName], index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
5125
- /* @__PURE__ */ jsxs(
5126
- "select",
5127
- {
5128
- value: columnName,
5129
- onChange: (event) => handleUpdateFilterField(variableName, event.target.value),
5130
- className: "flex-1 rounded-lg border border-gray-300 bg-white px-2 py-1.5 text-xs text-gray-900 outline-none focus:border-indigo-400 focus:ring-1 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white",
5131
- children: [
5132
- /* @__PURE__ */ jsx("option", { value: "", children: t("columnName") }),
5133
- availableColumns.map((column) => /* @__PURE__ */ jsx("option", { value: column.name, children: column.name }, column.name))
5134
- ]
5135
- }
5136
- ),
5137
- /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: "=" }),
5138
- /* @__PURE__ */ jsx(
5139
- "input",
5140
- {
5141
- type: "text",
5142
- value: variableName,
5143
- onChange: (event) => handleUpdateFilterVariable(variableName, event.target.value),
5144
- placeholder: t("variableReference"),
5145
- className: "flex-1 rounded-lg border border-gray-300 bg-white px-2 py-1.5 text-xs text-gray-900 placeholder-gray-400 outline-none focus:border-indigo-400 focus:ring-1 focus:ring-indigo-400/20 dark:border-gray-600 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
5146
- }
5147
- ),
5148
- /* @__PURE__ */ jsx(
5149
- "button",
5150
- {
5151
- type: "button",
5152
- onClick: () => handleRemoveFilter(variableName),
5153
- className: "rounded-md p-1 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20",
5154
- children: /* @__PURE__ */ jsx(XMarkIcon$1, { className: "h-3.5 w-3.5" })
5155
- }
5156
- )
5157
- ] }, index)) })
5158
- ] }),
5159
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 border-t border-gray-200 pt-4 dark:border-gray-700", children: [
5160
- /* @__PURE__ */ jsx(
5161
- "button",
5162
- {
5163
- type: "button",
5164
- onClick: onCancel,
5165
- className: "rounded-lg border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-800",
5166
- children: t("cancel")
5167
- }
5168
- ),
5169
- /* @__PURE__ */ jsx(
5170
- "button",
5171
- {
5172
- type: "button",
5173
- onClick: handleSave,
5174
- disabled: !selectedDatasourceId || !selectedTable || selectedColumns.length === 0,
5175
- className: "rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-indigo-500 dark:hover:bg-indigo-600",
5176
- children: t("save")
5177
- }
5178
- )
5179
- ] })
5180
- ] });
5181
- }
5182
5335
  var GROUP_COLOR_OPTIONS = [
5183
5336
  { value: "indigo", ring: "ring-indigo-500", fill: "bg-indigo-500" },
5184
5337
  { value: "teal", ring: "ring-teal-500", fill: "bg-teal-500" },
@@ -5540,18 +5693,8 @@ function LogicNodeModal({ onSave, entities = [], datasources = [], onLoadTables,
5540
5693
  case "iteration_start":
5541
5694
  return /* @__PURE__ */ jsx(IterationStartNodeConfigForm, { config, onSave: handleSave, onCancel: closeModal });
5542
5695
  case "datasource":
5543
- return /* @__PURE__ */ jsx(
5544
- DatasourceNodeConfigForm,
5545
- {
5546
- nodeId,
5547
- config,
5548
- onSave: handleSave,
5549
- onCancel: closeModal,
5550
- datasources,
5551
- onLoadTables: onLoadTables ?? (async () => []),
5552
- onLoadSchema: onLoadSchema ?? (async () => [])
5553
- }
5554
- );
5696
+ return null;
5697
+ // Datasource uses its own GlassModal with sidebar — rendered separately
5555
5698
  case "entity":
5556
5699
  return /* @__PURE__ */ jsx(EntityNodeConfigForm, { config, entities, onSave: handleSave, onCancel: closeModal });
5557
5700
  case "group":
@@ -5983,6 +6126,9 @@ function WorkflowCanvasInner({
5983
6126
  agentTools = [],
5984
6127
  rules,
5985
6128
  entities = [],
6129
+ datasources = [],
6130
+ onLoadTables,
6131
+ onLoadSchema,
5986
6132
  initialGraph,
5987
6133
  onGraphChange,
5988
6134
  onEditTool,
@@ -7339,7 +7485,7 @@ function WorkflowCanvasInner({
7339
7485
  const handleEdgeClick = useCallback(() => {
7340
7486
  closeContextMenu();
7341
7487
  }, [closeContextMenu]);
7342
- useMemo(() => {
7488
+ const editingLogicNode = useMemo(() => {
7343
7489
  if (!editingLogicNodeId) return null;
7344
7490
  const node = nodes.find((matchingNode) => matchingNode.id === editingLogicNodeId);
7345
7491
  if (!node) return null;
@@ -7515,6 +7661,22 @@ function WorkflowCanvasInner({
7515
7661
  },
7516
7662
  entities: allEntities
7517
7663
  }
7664
+ ),
7665
+ editingLogicNode?.config?.type === "datasource" && /* @__PURE__ */ jsx(
7666
+ DatasourceNodeConfigForm,
7667
+ {
7668
+ open: true,
7669
+ nodeId: editingLogicNode.nodeId,
7670
+ config: editingLogicNode.config,
7671
+ onSave: (updatedConfig) => {
7672
+ handleSaveLogicNodeConfig(editingLogicNode.nodeId, updatedConfig);
7673
+ setEditingLogicNodeId(null);
7674
+ },
7675
+ onCancel: () => setEditingLogicNodeId(null),
7676
+ datasources,
7677
+ onLoadTables: onLoadTables ?? (async () => []),
7678
+ onLoadSchema: onLoadSchema ?? (async () => [])
7679
+ }
7518
7680
  )
7519
7681
  ] });
7520
7682
  }
@@ -7653,5 +7815,5 @@ function Workspace({
7653
7815
  }
7654
7816
 
7655
7817
  export { AgentFlowNode, AgentToolFlowNode, AnswerFlowNode, AnthropicIcon, CATEGORY_COLORS, CATEGORY_PILL_COLORS, CodeFlowNode, CrewAIIcon, DocumentExtractorFlowNode, EndFlowNode, EntityFlowNode, FRAMEWORK_META, GoogleADKIcon, GroupFlowNode, HttpRequestFlowNode, ICON_MAP, IfElseFlowNode, IterationFlowNode, IterationStartFlowNode, KnowledgeBaseFlowNode, LOGIC_ICON_MAP, LOGIC_NODE_BADGE_COLORS, LOGIC_NODE_GRADIENTS, LOGIC_NODE_HANDLE_COLORS, LangChainIcon, ListOperatorFlowNode, LogicNodeModal, MINIMAP_NODE_COLORS, ModelProviderFlowNode, NODE_EXECUTION_ACCENT_COLORS, NodeCard, NodeContextMenu, NoteFlowNode, OpenAIIcon, PanelContextMenu, ParameterExtractorFlowNode, QuestionClassifierFlowNode, RuleFlowNode, SelectionContextMenu, StartFlowNode, StrandsIcon, TemplateTransformFlowNode, ToolFlowNode, VariableAggregatorFlowNode, VariableAssignerFlowNode, WorkflowBuilderProvider, WorkflowCanvas, Workspace, getCompatibleModels, getDefaultFrameworkForModel, getEntityBadgeColor, getEntityGradient, getEntityHandleColor, getEntityIcon, getEntityMinimapColor, getFrameworkMeta, getNodeExecutionAccent, getNodeExecutionAccentRgb, isFrameworkCompatibleWithProviders, isModelCompatibleWithFramework, useModalStore, useWorkflowBuilderClient, useWorkflowBuilderClientOptional, useWorkflowStore };
7656
- //# sourceMappingURL=chunk-HRQPV3H3.mjs.map
7657
- //# sourceMappingURL=chunk-HRQPV3H3.mjs.map
7818
+ //# sourceMappingURL=chunk-IWATRHQP.mjs.map
7819
+ //# sourceMappingURL=chunk-IWATRHQP.mjs.map