@datatechsolutions/ui 2.10.9 → 2.11.1
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/package.json +2 -1
- package/dist/astrlabe/contracts.d.mts +0 -293
- package/dist/astrlabe/contracts.d.ts +0 -293
- package/dist/astrlabe/contracts.js +0 -5
- package/dist/astrlabe/contracts.js.map +0 -1
- package/dist/astrlabe/contracts.mjs +0 -4
- package/dist/astrlabe/contracts.mjs.map +0 -1
- package/dist/astrlabe/graph-node.d.mts +0 -28
- package/dist/astrlabe/graph-node.d.ts +0 -28
- package/dist/astrlabe/graph-node.js +0 -27
- package/dist/astrlabe/graph-node.js.map +0 -1
- package/dist/astrlabe/graph-node.mjs +0 -6
- package/dist/astrlabe/graph-node.mjs.map +0 -1
- package/dist/astrlabe/index.d.mts +0 -707
- package/dist/astrlabe/index.d.ts +0 -707
- package/dist/astrlabe/index.js +0 -3248
- package/dist/astrlabe/index.js.map +0 -1
- package/dist/astrlabe/index.mjs +0 -2957
- package/dist/astrlabe/index.mjs.map +0 -1
- package/dist/astrlabe/utils.d.mts +0 -71
- package/dist/astrlabe/utils.d.ts +0 -71
- package/dist/astrlabe/utils.js +0 -31
- package/dist/astrlabe/utils.js.map +0 -1
- package/dist/astrlabe/utils.mjs +0 -6
- package/dist/astrlabe/utils.mjs.map +0 -1
- package/dist/astrlabe/workflow-canvas.d.mts +0 -5
- package/dist/astrlabe/workflow-canvas.d.ts +0 -5
- package/dist/astrlabe/workflow-canvas.js +0 -20
- package/dist/astrlabe/workflow-canvas.js.map +0 -1
- package/dist/astrlabe/workflow-canvas.mjs +0 -11
- package/dist/astrlabe/workflow-canvas.mjs.map +0 -1
- package/dist/astrlabe/workflow-preview-canvas.d.mts +0 -10
- package/dist/astrlabe/workflow-preview-canvas.d.ts +0 -10
- package/dist/astrlabe/workflow-preview-canvas.js +0 -28
- package/dist/astrlabe/workflow-preview-canvas.js.map +0 -1
- package/dist/astrlabe/workflow-preview-canvas.mjs +0 -26
- package/dist/astrlabe/workflow-preview-canvas.mjs.map +0 -1
- package/dist/chunk-3GDQP6AS.mjs +0 -15
- package/dist/chunk-3GDQP6AS.mjs.map +0 -1
- package/dist/chunk-3GE3MBUZ.js +0 -279
- package/dist/chunk-3GE3MBUZ.js.map +0 -1
- package/dist/chunk-55H6WZQP.js +0 -5
- package/dist/chunk-55H6WZQP.js.map +0 -1
- package/dist/chunk-7VJ7CMMT.mjs +0 -96
- package/dist/chunk-7VJ7CMMT.mjs.map +0 -1
- package/dist/chunk-AM2TTPYM.mjs +0 -189
- package/dist/chunk-AM2TTPYM.mjs.map +0 -1
- package/dist/chunk-BLNXRUC4.mjs +0 -276
- package/dist/chunk-BLNXRUC4.mjs.map +0 -1
- package/dist/chunk-D2JF6C3E.mjs +0 -46
- package/dist/chunk-D2JF6C3E.mjs.map +0 -1
- package/dist/chunk-DFR6CMJH.js +0 -197
- package/dist/chunk-DFR6CMJH.js.map +0 -1
- package/dist/chunk-JB6RNAD2.mjs +0 -4
- package/dist/chunk-JB6RNAD2.mjs.map +0 -1
- package/dist/chunk-LTWL7B4K.mjs +0 -7167
- package/dist/chunk-LTWL7B4K.mjs.map +0 -1
- package/dist/chunk-OZNTQROP.mjs +0 -39
- package/dist/chunk-OZNTQROP.mjs.map +0 -1
- package/dist/chunk-P4YYEM4B.js +0 -44
- package/dist/chunk-P4YYEM4B.js.map +0 -1
- package/dist/chunk-QWG2FMUN.mjs +0 -60
- package/dist/chunk-QWG2FMUN.mjs.map +0 -1
- package/dist/chunk-S3GAARSA.js +0 -7228
- package/dist/chunk-S3GAARSA.js.map +0 -1
- package/dist/chunk-S7KHTUHA.js +0 -65
- package/dist/chunk-S7KHTUHA.js.map +0 -1
- package/dist/chunk-UPTU224P.js +0 -23923
- package/dist/chunk-UPTU224P.js.map +0 -1
- package/dist/chunk-UZ3CMNUJ.js +0 -49
- package/dist/chunk-UZ3CMNUJ.js.map +0 -1
- package/dist/chunk-VUNV25KB.js +0 -18
- package/dist/chunk-VUNV25KB.js.map +0 -1
- package/dist/chunk-WURR63IK.mjs +0 -23189
- package/dist/chunk-WURR63IK.mjs.map +0 -1
- package/dist/chunk-YXN2K77G.js +0 -102
- package/dist/chunk-YXN2K77G.js.map +0 -1
- package/dist/entity-drawer-D2H7ugi9.d.mts +0 -31
- package/dist/entity-drawer-D2H7ugi9.d.ts +0 -31
- package/dist/index.d.mts +0 -4791
- package/dist/index.d.ts +0 -4791
- package/dist/index.js +0 -2893
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -8
- package/dist/index.mjs.map +0 -1
- package/dist/lib/i18n-context.d.mts +0 -36
- package/dist/lib/i18n-context.d.ts +0 -36
- package/dist/lib/i18n-context.js +0 -30
- package/dist/lib/i18n-context.js.map +0 -1
- package/dist/lib/i18n-context.mjs +0 -5
- package/dist/lib/i18n-context.mjs.map +0 -1
- package/dist/lib/router-context.d.mts +0 -35
- package/dist/lib/router-context.d.ts +0 -35
- package/dist/lib/router-context.js +0 -26
- package/dist/lib/router-context.js.map +0 -1
- package/dist/lib/router-context.mjs +0 -5
- package/dist/lib/router-context.mjs.map +0 -1
- package/dist/navigation-ANFMVDVW.mjs +0 -2445
- package/dist/navigation-ANFMVDVW.mjs.map +0 -1
- package/dist/navigation-JQ2TJKKI.js +0 -2447
- package/dist/navigation-JQ2TJKKI.js.map +0 -1
- package/dist/use-haptic-2SHBMEY5.js +0 -18
- package/dist/use-haptic-2SHBMEY5.js.map +0 -1
- package/dist/use-haptic-4UCNQATC.mjs +0 -5
- package/dist/use-haptic-4UCNQATC.mjs.map +0 -1
- package/dist/workflow-canvas-CGeuIgBQ.d.ts +0 -241
- package/dist/workflow-canvas-at3LMbkg.d.mts +0 -241
package/dist/astrlabe/index.mjs
DELETED
|
@@ -1,2957 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import '../chunk-JB6RNAD2.mjs';
|
|
3
|
-
export { topologicalSortAgents, validateWorkflowGraph } from '../chunk-BLNXRUC4.mjs';
|
|
4
|
-
import { Workspace, useDrawerStore, WorkspaceDrawer, CATEGORY_COLORS, CATEGORY_PILL_COLORS, ICON_MAP, WorkflowCanvas, getEntityIcon, getEntityGradient, useWorkflowStore, LOGIC_ICON_MAP, LOGIC_NODE_GRADIENTS, getFrameworkMeta, getCompatibleModels, isModelCompatibleWithFramework, FRAMEWORK_META } from '../chunk-LTWL7B4K.mjs';
|
|
5
|
-
export { AgentFlowNode, AgentToolFlowNode, AnswerFlowNode, AnthropicIcon, CodeFlowNode, CrewAIIcon, DocumentExtractorFlowNode, EndFlowNode, EntityFlowNode, FRAMEWORK_META, GoogleADKIcon, GroupFlowNode, HttpRequestFlowNode, IfElseFlowNode, IterationFlowNode, IterationStartFlowNode, KnowledgeBaseFlowNode, LOGIC_ICON_MAP, LOGIC_NODE_BADGE_COLORS, LOGIC_NODE_GRADIENTS, LOGIC_NODE_HANDLE_COLORS, LangChainIcon, ListOperatorFlowNode, LogicNodeDrawer, MINIMAP_NODE_COLORS, NodeCard, NodeContextMenu, NoteFlowNode, OpenAIIcon, PanelContextMenu, ParameterExtractorFlowNode, QuestionClassifierFlowNode, RuleFlowNode, SelectionContextMenu, StartFlowNode, StrandsIcon, TemplateTransformFlowNode, ToolFlowNode, VariableAggregatorFlowNode, VariableAssignerFlowNode, WorkflowBuilderProvider, Workspace, WorkspaceDrawer, getCompatibleModels, getDefaultFrameworkForModel, getEntityBadgeColor, getEntityGradient, getEntityHandleColor, getEntityIcon, getEntityMinimapColor, getFrameworkMeta, isModelCompatibleWithFramework, useDrawerStore, useWorkflowBuilderClient, useWorkflowBuilderClientOptional, useWorkflowStore } from '../chunk-LTWL7B4K.mjs';
|
|
6
|
-
import { FormInput, FormTextarea, Button, GlassFormModal, Input, DynamicIslandConfirm } from '../chunk-WURR63IK.mjs';
|
|
7
|
-
import '../chunk-QWG2FMUN.mjs';
|
|
8
|
-
import '../chunk-D2JF6C3E.mjs';
|
|
9
|
-
export { GraphNodeBadge, GraphNodeHeader, GraphNodeIconBubble, GraphNodeMeta } from '../chunk-OZNTQROP.mjs';
|
|
10
|
-
import { getAgentTier, createDefaultLogicNodeConfig } from '../chunk-AM2TTPYM.mjs';
|
|
11
|
-
export { applyDagreLayout, createDefaultLogicNodeConfig, getAgentTier } from '../chunk-AM2TTPYM.mjs';
|
|
12
|
-
import { useTranslations } from '../chunk-7VJ7CMMT.mjs';
|
|
13
|
-
import '../chunk-3GDQP6AS.mjs';
|
|
14
|
-
import { memo, useCallback, useState, useEffect, useMemo, useRef, Children } from 'react';
|
|
15
|
-
import { CpuChipIcon, ArrowPathRoundedSquareIcon, ArrowsPointingOutIcon, ArrowsPointingInIcon, BoltIcon, ClockIcon, CheckIcon, Cog6ToothIcon, CommandLineIcon, AdjustmentsHorizontalIcon, CircleStackIcon, TrashIcon, PlusIcon, XMarkIcon, EyeIcon, ArrowPathIcon, PlayIcon, StopIcon, XCircleIcon, CheckCircleIcon, VariableIcon, ChevronDownIcon, ChevronRightIcon, ExclamationCircleIcon, ClipboardDocumentIcon, ArrowDownTrayIcon, ArrowUpTrayIcon, ExclamationTriangleIcon } from '@heroicons/react/24/outline';
|
|
16
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
17
|
-
import { create } from 'zustand';
|
|
18
|
-
|
|
19
|
-
function AnthropicModelIcon({ className }) {
|
|
20
|
-
return /* @__PURE__ */ jsx("svg", { role: "img", viewBox: "0 0 24 24", fill: "currentColor", className, "aria-label": "Anthropic", children: /* @__PURE__ */ jsx("path", { d: "M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z" }) });
|
|
21
|
-
}
|
|
22
|
-
function AmazonNovaIcon({ className }) {
|
|
23
|
-
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", className, "aria-label": "Amazon Nova", children: [
|
|
24
|
-
/* @__PURE__ */ jsx("path", { d: "M12 2L3 20h3.5l1.8-4.5h7.4L17.5 20H21L12 2Zm-2.2 11L12 7.5l2.2 5.5H9.8Z", fill: "currentColor" }),
|
|
25
|
-
/* @__PURE__ */ jsx("path", { d: "M2 21c3.5 1.5 7.5 2 10 2s6.5-.5 10-2", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", fill: "none", opacity: "0.6" })
|
|
26
|
-
] });
|
|
27
|
-
}
|
|
28
|
-
function MetaLlamaIcon({ className }) {
|
|
29
|
-
return /* @__PURE__ */ jsx("svg", { role: "img", viewBox: "0 0 24 24", fill: "currentColor", className, "aria-label": "Meta", children: /* @__PURE__ */ jsx("path", { d: "M6.915 4.03c-1.968 0-3.683 1.28-4.871 3.113C.704 9.208 0 11.883 0 14.449c0 .706.07 1.369.21 1.973a6.624 6.624 0 0 0 .265.86 5.297 5.297 0 0 0 .371.761c.696 1.159 1.818 1.927 3.593 1.927 1.497 0 2.633-.671 3.965-2.444.76-1.012 1.144-1.626 2.663-4.32l.756-1.339.186-.325c.061.1.121.196.183.3l2.152 3.595c.724 1.21 1.665 2.556 2.47 3.314 1.046.987 1.992 1.22 3.06 1.22 1.075 0 1.876-.355 2.455-.843a3.743 3.743 0 0 0 .81-.973c.542-.939.861-2.127.861-3.745 0-2.72-.681-5.357-2.084-7.45-1.282-1.912-2.957-2.93-4.716-2.93-1.047 0-2.088.467-3.053 1.308-.652.57-1.257 1.29-1.82 2.05-.69-.875-1.335-1.547-1.958-2.056-1.182-.966-2.315-1.303-3.454-1.303zm10.16 2.053c1.147 0 2.188.758 2.992 1.999 1.132 1.748 1.647 4.195 1.647 6.4 0 1.548-.368 2.9-1.839 2.9-.58 0-1.027-.23-1.664-1.004-.496-.601-1.343-1.878-2.832-4.358l-.617-1.028a44.908 44.908 0 0 0-1.255-1.98c.07-.109.141-.224.211-.327 1.12-1.667 2.118-2.602 3.358-2.602zm-10.201.553c1.265 0 2.058.791 2.675 1.446.307.327.737.871 1.234 1.579l-1.02 1.566c-.757 1.163-1.882 3.017-2.837 4.338-1.191 1.649-1.81 1.817-2.486 1.817-.524 0-1.038-.237-1.383-.794-.263-.426-.464-1.13-.464-2.046 0-2.221.63-4.535 1.66-6.088.454-.687.964-1.226 1.533-1.533a2.264 2.264 0 0 1 1.088-.285z" }) });
|
|
30
|
-
}
|
|
31
|
-
function OpenAIModelIcon({ className }) {
|
|
32
|
-
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "currentColor", className, "aria-label": "OpenAI", children: /* @__PURE__ */ jsx("path", { d: "M14.949 6.547a3.94 3.94 0 0 0-.348-3.273 4.11 4.11 0 0 0-4.4-1.934A4.1 4.1 0 0 0 8.423.2 4.15 4.15 0 0 0 6.305.086a4.1 4.1 0 0 0-1.891.948 4.04 4.04 0 0 0-1.158 1.753 4.1 4.1 0 0 0-1.563.679A4 4 0 0 0 .554 4.72a3.99 3.99 0 0 0 .502 4.731 3.94 3.94 0 0 0 .346 3.274 4.11 4.11 0 0 0 4.402 1.933c.382.425.852.764 1.377.995.526.231 1.095.35 1.67.346 1.78.002 3.358-1.132 3.901-2.804a4.1 4.1 0 0 0 1.563-.68 4 4 0 0 0 1.14-1.253 3.99 3.99 0 0 0-.506-4.716m-6.097 8.406a3.05 3.05 0 0 1-1.945-.694l.096-.054 3.23-1.838a.53.53 0 0 0 .265-.455v-4.49l1.366.778q.02.011.025.035v3.722c-.003 1.653-1.361 2.992-3.037 2.996m-6.53-2.75a2.95 2.95 0 0 1-.36-2.01l.095.057L5.29 12.09a.53.53 0 0 0 .527 0l3.949-2.246v1.555a.05.05 0 0 1-.022.041L6.473 13.3c-1.454.826-3.311.335-4.15-1.098m-.85-6.94A3.02 3.02 0 0 1 3.07 3.949v3.785a.51.51 0 0 0 .262.451l3.93 2.237-1.366.779a.05.05 0 0 1-.048 0L2.585 9.342a2.98 2.98 0 0 1-1.113-4.094zm11.216 2.571L8.747 5.576l1.362-.776a.05.05 0 0 1 .048 0l3.265 1.86a3 3 0 0 1 1.173 1.207 2.96 2.96 0 0 1-.27 3.2 3.05 3.05 0 0 1-1.36.997V8.279a.52.52 0 0 0-.276-.445m1.36-2.015-.097-.057-3.226-1.855a.53.53 0 0 0-.53 0L6.249 6.153V4.598a.04.04 0 0 1 .019-.04L9.533 2.7a3.07 3.07 0 0 1 3.257.139c.474.325.843.778 1.066 1.303.223.526.289 1.103.191 1.664zM5.503 8.575 4.139 7.8a.05.05 0 0 1-.026-.037V4.049c0-.57.166-1.127.476-1.607s.752-.864 1.275-1.105a3.08 3.08 0 0 1 3.234.41l-.096.054-3.23 1.838a.53.53 0 0 0-.265.455zm.742-1.577 1.758-1 1.762 1v2l-1.755 1-1.762-1z" }) });
|
|
33
|
-
}
|
|
34
|
-
function GoogleGeminiIcon({ className }) {
|
|
35
|
-
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", className, "aria-label": "Google Gemini", children: [
|
|
36
|
-
/* @__PURE__ */ jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2Z", fill: "#4285F4", opacity: "0.15" }),
|
|
37
|
-
/* @__PURE__ */ jsx("path", { d: "M12 2.5c5.25 0 9.5 4.25 9.5 9.5s-4.25 9.5-9.5 9.5S2.5 17.25 2.5 12 6.75 2.5 12 2.5Z", stroke: "#4285F4", strokeWidth: "1", fill: "none" }),
|
|
38
|
-
/* @__PURE__ */ jsx("path", { d: "M12 7L8 12l4 5 4-5-4-5Z", fill: "#4285F4" }),
|
|
39
|
-
/* @__PURE__ */ jsx("path", { d: "M12 7L8 12l4 5", fill: "#34A853" })
|
|
40
|
-
] });
|
|
41
|
-
}
|
|
42
|
-
function getModelIcon(modelId) {
|
|
43
|
-
if (modelId.startsWith("anthropic.")) {
|
|
44
|
-
return { IconComponent: AnthropicModelIcon, color: "text-amber-600 dark:text-amber-400", providerLabel: "Anthropic" };
|
|
45
|
-
}
|
|
46
|
-
if (modelId.startsWith("amazon.")) {
|
|
47
|
-
return { IconComponent: AmazonNovaIcon, color: "text-orange-500 dark:text-orange-400", providerLabel: "Amazon" };
|
|
48
|
-
}
|
|
49
|
-
if (modelId.startsWith("meta.")) {
|
|
50
|
-
return { IconComponent: MetaLlamaIcon, color: "text-blue-500 dark:text-blue-400", providerLabel: "Meta" };
|
|
51
|
-
}
|
|
52
|
-
if (modelId.startsWith("google.")) {
|
|
53
|
-
return { IconComponent: GoogleGeminiIcon, color: "text-blue-500 dark:text-blue-400", providerLabel: "Google" };
|
|
54
|
-
}
|
|
55
|
-
if (modelId.startsWith("openai.")) {
|
|
56
|
-
return { IconComponent: OpenAIModelIcon, color: "text-emerald-500 dark:text-emerald-400", providerLabel: "OpenAI" };
|
|
57
|
-
}
|
|
58
|
-
return { IconComponent: AnthropicModelIcon, color: "text-gray-500 dark:text-gray-400", providerLabel: "Custom" };
|
|
59
|
-
}
|
|
60
|
-
function StatusBadge({ status }) {
|
|
61
|
-
const colorMap = {
|
|
62
|
-
pending: "bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300",
|
|
63
|
-
running: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300",
|
|
64
|
-
success: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300",
|
|
65
|
-
error: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300"
|
|
66
|
-
};
|
|
67
|
-
return /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-semibold ${colorMap[status] ?? colorMap.pending}`, children: status });
|
|
68
|
-
}
|
|
69
|
-
function formatDuration(ms) {
|
|
70
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
71
|
-
return `${(ms / 1e3).toFixed(2)}s`;
|
|
72
|
-
}
|
|
73
|
-
function isRecord(value) {
|
|
74
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
75
|
-
}
|
|
76
|
-
function OutputCard({ label, value }) {
|
|
77
|
-
const displayValue = typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
78
|
-
const isLong = typeof displayValue === "string" && displayValue.length > 120;
|
|
79
|
-
return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-white/20 bg-white/40 p-3 dark:border-white/10 dark:bg-white/5", children: [
|
|
80
|
-
/* @__PURE__ */ jsx("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400", children: label }),
|
|
81
|
-
isLong ? /* @__PURE__ */ jsx("pre", { className: "max-h-40 overflow-auto whitespace-pre-wrap text-xs text-gray-800 dark:text-gray-200", children: displayValue }) : /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 dark:text-white", children: displayValue })
|
|
82
|
-
] });
|
|
83
|
-
}
|
|
84
|
-
function AgentProfileHeader({ agent, models, t, selectedModelId, setSelectedModelId, selectedFramework, temperature, setTemperature, elo, setElo, onChanged }) {
|
|
85
|
-
const modelName = models.find((model) => model.id === selectedModelId)?.name ?? selectedModelId ?? "\u2014";
|
|
86
|
-
const avatarUrl = agent.avatar;
|
|
87
|
-
const frameworkMeta = getFrameworkMeta(selectedFramework);
|
|
88
|
-
const tierInfo = getEloTier(elo);
|
|
89
|
-
const difficultyConfig = {
|
|
90
|
-
beginner: { color: "bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-400", labelKey: "agentDrawer.tierBeginner" },
|
|
91
|
-
intermediate: { color: "bg-pink-100 text-pink-700 dark:bg-pink-900/30 dark:text-pink-400", labelKey: "agentDrawer.tierIntermediate" },
|
|
92
|
-
advanced: { color: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400", labelKey: "agentDrawer.tierAdvanced" },
|
|
93
|
-
expert: { color: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400", labelKey: "agentDrawer.tierExpert" }
|
|
94
|
-
};
|
|
95
|
-
const levelConfig = difficultyConfig[tierInfo.tierKey];
|
|
96
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative overflow-hidden bg-gradient-to-br from-indigo-500/20 via-purple-500/10 to-transparent px-6 pb-6 pt-4 dark:from-indigo-500/10 dark:via-purple-500/5", children: [
|
|
97
|
-
levelConfig && /* @__PURE__ */ jsx("div", { className: "mb-4 flex justify-center", children: /* @__PURE__ */ jsx("span", { className: `${levelConfig.color} rounded-full px-4 py-1.5 text-xs font-bold shadow-sm transition-colors`, children: t(levelConfig.labelKey) }) }),
|
|
98
|
-
/* @__PURE__ */ jsx("div", { className: "mb-4 flex justify-center", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
99
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-full bg-gradient-to-br from-purple-500 to-blue-500 opacity-40 blur-lg" }),
|
|
100
|
-
avatarUrl ? /* @__PURE__ */ jsx(
|
|
101
|
-
"img",
|
|
102
|
-
{
|
|
103
|
-
src: avatarUrl,
|
|
104
|
-
alt: agent.name,
|
|
105
|
-
loading: "lazy",
|
|
106
|
-
className: "relative h-20 w-20 rounded-full bg-white object-cover shadow-xl ring-4 ring-white dark:bg-gray-800 dark:ring-gray-800"
|
|
107
|
-
}
|
|
108
|
-
) : /* @__PURE__ */ jsx("div", { className: "relative flex h-20 w-20 items-center justify-center rounded-full bg-gradient-to-br from-indigo-400 to-purple-500 shadow-xl ring-4 ring-white dark:ring-gray-800", children: /* @__PURE__ */ jsx(CpuChipIcon, { className: "h-10 w-10 text-white" }) }),
|
|
109
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full bg-indigo-500 ring-2 ring-white dark:ring-gray-900", children: /* @__PURE__ */ jsx(CpuChipIcon, { className: "h-3.5 w-3.5 text-white" }) })
|
|
110
|
-
] }) }),
|
|
111
|
-
/* @__PURE__ */ jsx("h3", { className: "mb-2 text-center text-lg font-bold text-gray-900 dark:text-white", children: agent.name }),
|
|
112
|
-
agent.role && /* @__PURE__ */ jsx("div", { className: "mb-3 flex justify-center", children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-full bg-white/60 px-3 py-1.5 text-xs font-medium text-gray-600 ring-1 ring-gray-200/50 dark:bg-gray-800/60 dark:text-gray-400 dark:ring-gray-700/50", children: [
|
|
113
|
-
/* @__PURE__ */ jsxs("svg", { className: "h-3 w-3", fill: "currentColor", viewBox: "0 0 20 20", children: [
|
|
114
|
-
/* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M6 6V5a3 3 0 013-3h2a3 3 0 013 3v1h2a2 2 0 012 2v3.57A22.952 22.952 0 0110 13a22.95 22.95 0 01-8-1.43V8a2 2 0 012-2h2zm2-1a1 1 0 011-1h2a1 1 0 011 1v1H8V5zm1 5a1 1 0 011-1h.01a1 1 0 110 2H10a1 1 0 01-1-1z", clipRule: "evenodd" }),
|
|
115
|
-
/* @__PURE__ */ jsx("path", { d: "M2 13.692V16a2 2 0 002 2h12a2 2 0 002-2v-2.308A24.974 24.974 0 0110 15c-2.796 0-5.487-.46-8-1.308z" })
|
|
116
|
-
] }),
|
|
117
|
-
agent.role
|
|
118
|
-
] }) }),
|
|
119
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2", children: [
|
|
120
|
-
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1.5 rounded bg-white/50 px-2.5 py-1 text-[10px] text-gray-600 dark:bg-gray-800/50 dark:text-gray-400", children: [
|
|
121
|
-
/* @__PURE__ */ jsx(CpuChipIcon, { className: "h-3 w-3" }),
|
|
122
|
-
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: modelName })
|
|
123
|
-
] }),
|
|
124
|
-
elo != null && /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 rounded bg-white/50 px-2 py-1 text-[10px] text-gray-600 dark:bg-gray-800/50 dark:text-gray-400", children: [
|
|
125
|
-
/* @__PURE__ */ jsx("span", { className: "opacity-60", children: "ELO:" }),
|
|
126
|
-
/* @__PURE__ */ jsx("span", { className: "font-bold tabular-nums", children: elo })
|
|
127
|
-
] })
|
|
128
|
-
] }),
|
|
129
|
-
/* @__PURE__ */ jsx("div", { className: "mt-3 flex justify-center", children: /* @__PURE__ */ jsxs("span", { className: `inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-[10px] font-semibold ${frameworkMeta.badgeColor}`, children: [
|
|
130
|
-
/* @__PURE__ */ jsx(frameworkMeta.IconComponent, { className: "h-3.5 w-3.5" }),
|
|
131
|
-
frameworkMeta.label
|
|
132
|
-
] }) }),
|
|
133
|
-
/* @__PURE__ */ jsx(AgentCapabilityCard, { elo, setElo, models, selectedModelId, setSelectedModelId, temperature, setTemperature, onChanged, t }),
|
|
134
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center justify-center gap-2 text-[10px] text-gray-400 dark:text-gray-500", children: [
|
|
135
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
136
|
-
"v",
|
|
137
|
-
agent.activePromptVersion
|
|
138
|
-
] }),
|
|
139
|
-
/* @__PURE__ */ jsx("span", { children: "\xB7" }),
|
|
140
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
141
|
-
agent.promptCount,
|
|
142
|
-
" prompt",
|
|
143
|
-
agent.promptCount === 1 ? "" : "s"
|
|
144
|
-
] })
|
|
145
|
-
] })
|
|
146
|
-
] });
|
|
147
|
-
}
|
|
148
|
-
var MODEL_FAMILIES = {
|
|
149
|
-
anthropic: [
|
|
150
|
-
{ prefix: "anthropic.claude-haiku", maxTokens: 8192, contextWindow: "200K" },
|
|
151
|
-
{ prefix: "anthropic.claude-sonnet", maxTokens: 8192, contextWindow: "1M" },
|
|
152
|
-
{ prefix: "anthropic.claude-opus", maxTokens: 32768, contextWindow: "1M" }
|
|
153
|
-
],
|
|
154
|
-
amazon: [
|
|
155
|
-
{ prefix: "amazon.nova-lite", maxTokens: 5120, contextWindow: "300K" },
|
|
156
|
-
{ prefix: "amazon.nova-pro", maxTokens: 5120, contextWindow: "300K" }
|
|
157
|
-
],
|
|
158
|
-
google: [
|
|
159
|
-
{ prefix: "google.gemini-3-flash", maxTokens: 8192, contextWindow: "1M" },
|
|
160
|
-
{ prefix: "google.gemini-3-1-pro", maxTokens: 32768, contextWindow: "1M" }
|
|
161
|
-
],
|
|
162
|
-
meta: [
|
|
163
|
-
{ prefix: "meta.llama", maxTokens: 8192, contextWindow: "128K" }
|
|
164
|
-
],
|
|
165
|
-
openai: [
|
|
166
|
-
{ prefix: "openai.gpt-5-mini", maxTokens: 16384, contextWindow: "1M" },
|
|
167
|
-
{ prefix: "openai.gpt-5-v", maxTokens: 32768, contextWindow: "1M" }
|
|
168
|
-
]
|
|
169
|
-
};
|
|
170
|
-
function getProviderFromModelId(modelId) {
|
|
171
|
-
if (modelId.startsWith("anthropic.")) return "anthropic";
|
|
172
|
-
if (modelId.startsWith("amazon.")) return "amazon";
|
|
173
|
-
if (modelId.startsWith("meta.")) return "meta";
|
|
174
|
-
return "anthropic";
|
|
175
|
-
}
|
|
176
|
-
function getEloTier(elo) {
|
|
177
|
-
if (elo < 1200) return {
|
|
178
|
-
tierKey: "beginner",
|
|
179
|
-
autonomyKey: "autonomyLow",
|
|
180
|
-
color: "text-cyan-500",
|
|
181
|
-
barColor: "from-cyan-400 to-cyan-500",
|
|
182
|
-
autonomyPercent: 25,
|
|
183
|
-
costPerTask: "$0.005",
|
|
184
|
-
familyIndex: 0,
|
|
185
|
-
temperature: 0.7
|
|
186
|
-
};
|
|
187
|
-
if (elo < 1600) return {
|
|
188
|
-
tierKey: "intermediate",
|
|
189
|
-
autonomyKey: "autonomyMedium",
|
|
190
|
-
color: "text-pink-500",
|
|
191
|
-
barColor: "from-pink-400 to-pink-500",
|
|
192
|
-
autonomyPercent: 50,
|
|
193
|
-
costPerTask: "$0.15",
|
|
194
|
-
familyIndex: 1,
|
|
195
|
-
temperature: 0.5
|
|
196
|
-
};
|
|
197
|
-
if (elo < 2e3) return {
|
|
198
|
-
tierKey: "advanced",
|
|
199
|
-
autonomyKey: "autonomyHigh",
|
|
200
|
-
color: "text-amber-500",
|
|
201
|
-
barColor: "from-amber-400 to-amber-500",
|
|
202
|
-
autonomyPercent: 75,
|
|
203
|
-
costPerTask: "$0.50",
|
|
204
|
-
familyIndex: 1,
|
|
205
|
-
temperature: 0.4
|
|
206
|
-
};
|
|
207
|
-
return {
|
|
208
|
-
tierKey: "expert",
|
|
209
|
-
autonomyKey: "autonomyFull",
|
|
210
|
-
color: "text-emerald-500",
|
|
211
|
-
barColor: "from-emerald-400 to-emerald-500",
|
|
212
|
-
autonomyPercent: 100,
|
|
213
|
-
costPerTask: "$1.50",
|
|
214
|
-
familyIndex: 2,
|
|
215
|
-
temperature: 0.3
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
function AgentCapabilityCard({ elo, setElo, models, selectedModelId, setSelectedModelId, temperature, setTemperature, onChanged, t }) {
|
|
219
|
-
const tierInfo = getEloTier(elo);
|
|
220
|
-
const eloPercent = Math.min((elo - 800) / (2400 - 800) * 100, 100);
|
|
221
|
-
const provider = getProviderFromModelId(selectedModelId);
|
|
222
|
-
const family = MODEL_FAMILIES[provider] ?? MODEL_FAMILIES.anthropic;
|
|
223
|
-
const handleEloChange = useCallback((event) => {
|
|
224
|
-
const newElo = parseInt(event.target.value, 10);
|
|
225
|
-
setElo(newElo);
|
|
226
|
-
const newTier = getEloTier(newElo);
|
|
227
|
-
const modelIndex = Math.min(newTier.familyIndex, family.length - 1);
|
|
228
|
-
const targetPrefix = family[modelIndex].prefix;
|
|
229
|
-
const matchingModel = models.find((model) => model.id.startsWith(targetPrefix));
|
|
230
|
-
if (matchingModel) {
|
|
231
|
-
setSelectedModelId(matchingModel.id);
|
|
232
|
-
}
|
|
233
|
-
setTemperature(newTier.temperature);
|
|
234
|
-
onChanged();
|
|
235
|
-
}, [family, models, setSelectedModelId, setTemperature, onChanged]);
|
|
236
|
-
const handleAutonomyClick = useCallback((level) => {
|
|
237
|
-
const eloMap = { 25: 1e3, 50: 1400, 75: 1800, 100: 2200 };
|
|
238
|
-
const newElo = eloMap[level] ?? 1e3;
|
|
239
|
-
setElo(newElo);
|
|
240
|
-
const newTier = getEloTier(newElo);
|
|
241
|
-
const modelIndex = Math.min(newTier.familyIndex, family.length - 1);
|
|
242
|
-
const targetPrefix = family[modelIndex].prefix;
|
|
243
|
-
const matchingModel = models.find((model) => model.id.startsWith(targetPrefix));
|
|
244
|
-
if (matchingModel) {
|
|
245
|
-
setSelectedModelId(matchingModel.id);
|
|
246
|
-
}
|
|
247
|
-
setTemperature(newTier.temperature);
|
|
248
|
-
onChanged();
|
|
249
|
-
}, [family, models, setSelectedModelId, setTemperature, onChanged]);
|
|
250
|
-
const currentFamilyEntry = family.find((entry) => selectedModelId.startsWith(entry.prefix)) ?? family[0];
|
|
251
|
-
const currentModelName = models.find((model) => model.id === selectedModelId)?.name ?? selectedModelId;
|
|
252
|
-
return /* @__PURE__ */ jsxs("div", { className: "mx-4 mt-4 overflow-hidden rounded-xl border border-gray-200/30 bg-white/40 dark:border-white/10 dark:bg-white/5", children: [
|
|
253
|
-
/* @__PURE__ */ jsxs("div", { className: "px-4 pt-3 pb-2", children: [
|
|
254
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
|
|
255
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400", children: t("agentDrawer.capabilityRating") }),
|
|
256
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-1", children: [
|
|
257
|
-
/* @__PURE__ */ jsx("span", { className: `text-lg font-bold tabular-nums ${tierInfo.color}`, children: elo }),
|
|
258
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: "ELO" })
|
|
259
|
-
] })
|
|
260
|
-
] }),
|
|
261
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
262
|
-
/* @__PURE__ */ jsxs("div", { className: "absolute inset-x-0 top-1/2 h-2 -translate-y-1/2 overflow-hidden rounded-full bg-gray-200 dark:bg-gray-700", children: [
|
|
263
|
-
/* @__PURE__ */ jsx(
|
|
264
|
-
"div",
|
|
265
|
-
{
|
|
266
|
-
className: `h-full rounded-full bg-gradient-to-r ${tierInfo.barColor} transition-all duration-300`,
|
|
267
|
-
style: { width: `${eloPercent}%` }
|
|
268
|
-
}
|
|
269
|
-
),
|
|
270
|
-
[1200, 1600, 2e3].map((boundary) => /* @__PURE__ */ jsx(
|
|
271
|
-
"div",
|
|
272
|
-
{
|
|
273
|
-
className: "absolute top-0 h-full w-px bg-gray-400/40 dark:bg-gray-500/40",
|
|
274
|
-
style: { left: `${(boundary - 800) / (2400 - 800) * 100}%` }
|
|
275
|
-
},
|
|
276
|
-
boundary
|
|
277
|
-
))
|
|
278
|
-
] }),
|
|
279
|
-
/* @__PURE__ */ jsx(
|
|
280
|
-
"input",
|
|
281
|
-
{
|
|
282
|
-
type: "range",
|
|
283
|
-
min: "800",
|
|
284
|
-
max: "2400",
|
|
285
|
-
step: "50",
|
|
286
|
-
value: elo,
|
|
287
|
-
onChange: handleEloChange,
|
|
288
|
-
className: "relative z-10 h-5 w-full cursor-pointer appearance-none bg-transparent [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:shadow-lg dark:[&::-webkit-slider-thumb]:border-gray-900"
|
|
289
|
-
}
|
|
290
|
-
),
|
|
291
|
-
/* @__PURE__ */ jsx("style", { children: `input[type="range"]::-webkit-slider-thumb { background: ${elo < 1200 ? "#06b6d4" : elo < 1600 ? "#ec4899" : elo < 2e3 ? "#f59e0b" : "#10b981"}; box-shadow: 0 0 6px ${elo < 1200 ? "rgba(6,182,212,0.5)" : elo < 1600 ? "rgba(236,72,153,0.5)" : elo < 2e3 ? "rgba(245,158,11,0.5)" : "rgba(16,185,129,0.5)"}; }` })
|
|
292
|
-
] }),
|
|
293
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex justify-between text-[8px] text-gray-400 dark:text-gray-500", children: [
|
|
294
|
-
/* @__PURE__ */ jsx("span", { children: "800" }),
|
|
295
|
-
/* @__PURE__ */ jsx("span", { children: "1200" }),
|
|
296
|
-
/* @__PURE__ */ jsx("span", { children: "1600" }),
|
|
297
|
-
/* @__PURE__ */ jsx("span", { children: "2000" }),
|
|
298
|
-
/* @__PURE__ */ jsx("span", { children: "2400" })
|
|
299
|
-
] })
|
|
300
|
-
] }),
|
|
301
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-px border-t border-gray-200/30 bg-gray-200/30 dark:border-white/10 dark:bg-white/10", children: [
|
|
302
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white/60 px-3 py-2 dark:bg-gray-900/60", children: [
|
|
303
|
-
/* @__PURE__ */ jsx("p", { className: "text-[9px] text-gray-400 dark:text-gray-500", children: t("agentDrawer.model") }),
|
|
304
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs font-semibold text-gray-900 dark:text-white", children: currentModelName })
|
|
305
|
-
] }),
|
|
306
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white/60 px-3 py-2 dark:bg-gray-900/60", children: [
|
|
307
|
-
/* @__PURE__ */ jsx("p", { className: "text-[9px] text-gray-400 dark:text-gray-500", children: t("agentDrawer.maxTokens") }),
|
|
308
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-gray-900 dark:text-white", children: currentFamilyEntry.maxTokens.toLocaleString() })
|
|
309
|
-
] }),
|
|
310
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white/60 px-3 py-2 dark:bg-gray-900/60", children: [
|
|
311
|
-
/* @__PURE__ */ jsx("p", { className: "text-[9px] text-gray-400 dark:text-gray-500", children: t("agentDrawer.context") }),
|
|
312
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-gray-900 dark:text-white", children: currentFamilyEntry.contextWindow })
|
|
313
|
-
] }),
|
|
314
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white/60 px-3 py-2 dark:bg-gray-900/60", children: [
|
|
315
|
-
/* @__PURE__ */ jsx("p", { className: "text-[9px] text-gray-400 dark:text-gray-500", children: t("agentDrawer.temperature") }),
|
|
316
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-gray-900 dark:text-white", children: temperature.toFixed(2) })
|
|
317
|
-
] }),
|
|
318
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white/60 px-3 py-2 dark:bg-gray-900/60", children: [
|
|
319
|
-
/* @__PURE__ */ jsx("p", { className: "text-[9px] text-gray-400 dark:text-gray-500", children: t("agentDrawer.autonomy") }),
|
|
320
|
-
/* @__PURE__ */ jsx("p", { className: `text-xs font-semibold ${tierInfo.color}`, children: t(`agentDrawer.${tierInfo.autonomyKey}`) })
|
|
321
|
-
] }),
|
|
322
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-white/60 px-3 py-2 dark:bg-gray-900/60", children: [
|
|
323
|
-
/* @__PURE__ */ jsx("p", { className: "text-[9px] text-gray-400 dark:text-gray-500", children: t("agentDrawer.costPerTask") }),
|
|
324
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-gray-900 dark:text-white", children: tierInfo.costPerTask })
|
|
325
|
-
] })
|
|
326
|
-
] }),
|
|
327
|
-
/* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200/30 bg-white/60 px-4 py-2.5 dark:border-white/10 dark:bg-gray-900/60", children: [
|
|
328
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
|
|
329
|
-
/* @__PURE__ */ jsx("span", { className: "text-[9px] text-gray-400 dark:text-gray-500", children: t("agentDrawer.autonomyLevel") }),
|
|
330
|
-
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-semibold ${tierInfo.color}`, children: t(`agentDrawer.${tierInfo.autonomyKey}`) })
|
|
331
|
-
] }),
|
|
332
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-1", children: [
|
|
333
|
-
{ level: 25, label: "Low" },
|
|
334
|
-
{ level: 50, label: "Med" },
|
|
335
|
-
{ level: 75, label: "High" },
|
|
336
|
-
{ level: 100, label: "Full" }
|
|
337
|
-
].map(({ level }) => /* @__PURE__ */ jsx(
|
|
338
|
-
"button",
|
|
339
|
-
{
|
|
340
|
-
type: "button",
|
|
341
|
-
onClick: () => handleAutonomyClick(level),
|
|
342
|
-
className: `h-2 flex-1 rounded-full transition-all ${level <= tierInfo.autonomyPercent ? `bg-gradient-to-r ${tierInfo.barColor} hover:opacity-80` : "bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600"}`
|
|
343
|
-
},
|
|
344
|
-
level
|
|
345
|
-
)) }),
|
|
346
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex justify-between text-[7px] text-gray-400 dark:text-gray-500", children: [
|
|
347
|
-
/* @__PURE__ */ jsx("span", { children: t("agentDrawer.autonomyLow") }),
|
|
348
|
-
/* @__PURE__ */ jsx("span", { children: t("agentDrawer.autonomyMedium") }),
|
|
349
|
-
/* @__PURE__ */ jsx("span", { children: t("agentDrawer.autonomyHigh") }),
|
|
350
|
-
/* @__PURE__ */ jsx("span", { children: t("agentDrawer.autonomyFull") })
|
|
351
|
-
] })
|
|
352
|
-
] })
|
|
353
|
-
] });
|
|
354
|
-
}
|
|
355
|
-
function ConfigTab({ agent, models, t, selectedModelId, setSelectedModelId, selectedFramework, setSelectedFramework, temperature, setTemperature, dirty, markDirty, markSaved }) {
|
|
356
|
-
const [promptText, setPromptText] = useState(agent.systemPrompt ?? "");
|
|
357
|
-
const handleTemperatureChange = useCallback((event) => {
|
|
358
|
-
setTemperature(parseFloat(event.target.value));
|
|
359
|
-
markDirty();
|
|
360
|
-
}, []);
|
|
361
|
-
const handlePromptChange = useCallback((event) => {
|
|
362
|
-
setPromptText(event.target.value);
|
|
363
|
-
markDirty();
|
|
364
|
-
}, []);
|
|
365
|
-
const handleSave = useCallback(() => {
|
|
366
|
-
markSaved();
|
|
367
|
-
}, [markSaved]);
|
|
368
|
-
const temperaturePercent = temperature * 100;
|
|
369
|
-
const isPrecise = temperature <= 0.3;
|
|
370
|
-
const isBalanced = temperature > 0.3 && temperature <= 0.7;
|
|
371
|
-
const isCreative = temperature > 0.7;
|
|
372
|
-
const frameworkKeys = Object.keys(FRAMEWORK_META);
|
|
373
|
-
const compatibleModels = getCompatibleModels(models, selectedFramework);
|
|
374
|
-
const handleFrameworkChange = useCallback((newFramework) => {
|
|
375
|
-
setSelectedFramework(newFramework);
|
|
376
|
-
if (!isModelCompatibleWithFramework(selectedModelId, newFramework)) {
|
|
377
|
-
const compatible = getCompatibleModels(models, newFramework);
|
|
378
|
-
if (compatible.length > 0) {
|
|
379
|
-
setSelectedModelId(compatible[0].id);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
markDirty();
|
|
383
|
-
}, [selectedModelId, models, setSelectedFramework, setSelectedModelId, markDirty]);
|
|
384
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-5 p-4", children: [
|
|
385
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
386
|
-
/* @__PURE__ */ jsx("label", { className: "mb-2 block text-xs font-medium text-gray-500 dark:text-gray-400", children: t("agentDrawer.framework") }),
|
|
387
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: frameworkKeys.map((key) => {
|
|
388
|
-
const meta = FRAMEWORK_META[key];
|
|
389
|
-
const isSelected = key === selectedFramework;
|
|
390
|
-
const compatCount = getCompatibleModels(models, key).length;
|
|
391
|
-
return /* @__PURE__ */ jsxs(
|
|
392
|
-
"button",
|
|
393
|
-
{
|
|
394
|
-
type: "button",
|
|
395
|
-
onClick: () => handleFrameworkChange(key),
|
|
396
|
-
className: `inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[10px] font-semibold transition-all ${isSelected ? `${meta.badgeColor} ring-1 ring-current/20` : "bg-gray-100 text-gray-500 hover:bg-gray-200 dark:bg-white/5 dark:text-gray-400 dark:hover:bg-white/10"}`,
|
|
397
|
-
children: [
|
|
398
|
-
/* @__PURE__ */ jsx(meta.IconComponent, { className: "h-3.5 w-3.5" }),
|
|
399
|
-
meta.label,
|
|
400
|
-
/* @__PURE__ */ jsx("span", { className: "ml-0.5 text-[8px] opacity-60", children: compatCount })
|
|
401
|
-
]
|
|
402
|
-
},
|
|
403
|
-
key
|
|
404
|
-
);
|
|
405
|
-
}) })
|
|
406
|
-
] }),
|
|
407
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
408
|
-
/* @__PURE__ */ jsxs("label", { className: "mb-2 block text-xs font-medium text-gray-500 dark:text-gray-400", children: [
|
|
409
|
-
t("agentDrawer.model"),
|
|
410
|
-
compatibleModels.length < models.length && /* @__PURE__ */ jsxs("span", { className: "ml-1.5 text-[10px] font-normal text-gray-400 dark:text-gray-500", children: [
|
|
411
|
-
"(",
|
|
412
|
-
compatibleModels.length,
|
|
413
|
-
"/",
|
|
414
|
-
models.length,
|
|
415
|
-
")"
|
|
416
|
-
] })
|
|
417
|
-
] }),
|
|
418
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: models.map((model) => {
|
|
419
|
-
const isSelected = model.id === selectedModelId;
|
|
420
|
-
const isCompatible = isModelCompatibleWithFramework(model.id, selectedFramework);
|
|
421
|
-
const { IconComponent, color, providerLabel } = getModelIcon(model.id);
|
|
422
|
-
return /* @__PURE__ */ jsxs(
|
|
423
|
-
"button",
|
|
424
|
-
{
|
|
425
|
-
type: "button",
|
|
426
|
-
disabled: !isCompatible,
|
|
427
|
-
onClick: () => {
|
|
428
|
-
setSelectedModelId(model.id);
|
|
429
|
-
markDirty();
|
|
430
|
-
},
|
|
431
|
-
className: `flex items-center gap-2.5 rounded-xl border px-3 py-2.5 text-left transition-all ${!isCompatible ? "cursor-not-allowed border-gray-200/30 opacity-35 dark:border-white/5" : isSelected ? "border-indigo-500/50 bg-indigo-50/50 ring-1 ring-indigo-500/30 dark:border-indigo-400/40 dark:bg-indigo-500/10" : "border-gray-200/50 bg-gray-50/50 hover:border-gray-300 dark:border-white/10 dark:bg-white/5 dark:hover:border-white/20"}`,
|
|
432
|
-
children: [
|
|
433
|
-
/* @__PURE__ */ jsx(IconComponent, { className: `h-5 w-5 flex-shrink-0 ${isSelected && isCompatible ? color : "text-gray-400 dark:text-gray-500"}` }),
|
|
434
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
435
|
-
/* @__PURE__ */ jsx("p", { className: `truncate text-xs font-semibold ${isSelected && isCompatible ? "text-gray-900 dark:text-white" : "text-gray-600 dark:text-gray-300"}`, children: model.name }),
|
|
436
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-gray-400 dark:text-gray-500", children: providerLabel })
|
|
437
|
-
] })
|
|
438
|
-
]
|
|
439
|
-
},
|
|
440
|
-
model.id
|
|
441
|
-
);
|
|
442
|
-
}) })
|
|
443
|
-
] }),
|
|
444
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
445
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
|
|
446
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 dark:text-gray-400", children: t("agentDrawer.temperature") }),
|
|
447
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-bold tabular-nums text-gray-900 dark:text-white", children: temperature.toFixed(2) })
|
|
448
|
-
] }),
|
|
449
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
450
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 top-1/2 h-2 -translate-y-1/2 overflow-hidden rounded-full bg-gray-200 dark:bg-gray-700", children: /* @__PURE__ */ jsx(
|
|
451
|
-
"div",
|
|
452
|
-
{
|
|
453
|
-
className: "h-full rounded-full transition-all duration-300 ease-out",
|
|
454
|
-
style: {
|
|
455
|
-
width: `${temperaturePercent}%`,
|
|
456
|
-
background: `linear-gradient(90deg, #3b82f6, #8b5cf6 50%, #ec4899)`
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
) }),
|
|
460
|
-
/* @__PURE__ */ jsx(
|
|
461
|
-
"input",
|
|
462
|
-
{
|
|
463
|
-
type: "range",
|
|
464
|
-
min: "0",
|
|
465
|
-
max: "1",
|
|
466
|
-
step: "0.05",
|
|
467
|
-
value: temperature,
|
|
468
|
-
onChange: handleTemperatureChange,
|
|
469
|
-
className: "relative z-10 h-5 w-full cursor-pointer appearance-none bg-transparent [&::-webkit-slider-thumb]:h-5 [&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:shadow-lg dark:[&::-webkit-slider-thumb]:border-gray-900",
|
|
470
|
-
style: {
|
|
471
|
-
// Thumb color based on temperature zone
|
|
472
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
473
|
-
["--thumb-color"]: isPrecise ? "#3b82f6" : isBalanced ? "#8b5cf6" : "#ec4899"
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
),
|
|
477
|
-
/* @__PURE__ */ jsx("style", { children: `
|
|
478
|
-
input[type="range"]::-webkit-slider-thumb {
|
|
479
|
-
background: ${isPrecise ? "#3b82f6" : isBalanced ? "#8b5cf6" : "#ec4899"};
|
|
480
|
-
box-shadow: 0 0 8px ${isPrecise ? "rgba(59,130,246,0.5)" : isBalanced ? "rgba(139,92,246,0.5)" : "rgba(236,72,153,0.5)"};
|
|
481
|
-
}
|
|
482
|
-
` })
|
|
483
|
-
] }),
|
|
484
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center justify-between", children: [
|
|
485
|
-
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium transition-colors ${isPrecise ? "text-blue-500" : "text-gray-400 dark:text-gray-500"}`, children: t("agentDrawer.precise") }),
|
|
486
|
-
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium transition-colors ${isBalanced ? "text-purple-500" : "text-gray-400 dark:text-gray-500"}`, children: t("agentDrawer.balanced") }),
|
|
487
|
-
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium transition-colors ${isCreative ? "text-pink-500" : "text-gray-400 dark:text-gray-500"}`, children: t("agentDrawer.creative") })
|
|
488
|
-
] })
|
|
489
|
-
] }),
|
|
490
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
491
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
|
|
492
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 dark:text-gray-400", children: t("agentDrawer.systemPrompt") }),
|
|
493
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
494
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: [
|
|
495
|
-
promptText.length,
|
|
496
|
-
" chars"
|
|
497
|
-
] }),
|
|
498
|
-
dirty && /* @__PURE__ */ jsx(
|
|
499
|
-
"button",
|
|
500
|
-
{
|
|
501
|
-
type: "button",
|
|
502
|
-
onClick: handleSave,
|
|
503
|
-
className: "rounded-md bg-gradient-to-r from-indigo-500 to-purple-500 px-2.5 py-1 text-[10px] font-semibold text-white shadow-sm transition-all hover:from-indigo-600 hover:to-purple-600",
|
|
504
|
-
children: t("agentDrawer.save")
|
|
505
|
-
}
|
|
506
|
-
),
|
|
507
|
-
!dirty && promptText.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-emerald-500", children: t("agentDrawer.saved") })
|
|
508
|
-
] })
|
|
509
|
-
] }),
|
|
510
|
-
/* @__PURE__ */ jsx(
|
|
511
|
-
"textarea",
|
|
512
|
-
{
|
|
513
|
-
value: promptText,
|
|
514
|
-
onChange: handlePromptChange,
|
|
515
|
-
rows: 8,
|
|
516
|
-
className: "w-full resize-y rounded-lg border border-gray-200/50 bg-gray-50/50 px-3 py-2.5 font-mono text-xs leading-relaxed text-gray-700 outline-none transition-colors placeholder:text-gray-400 focus:border-indigo-300/50 focus:ring-1 focus:ring-indigo-300/30 dark:border-white/10 dark:bg-white/5 dark:text-gray-300 dark:placeholder:text-gray-500 dark:focus:border-indigo-500/30 dark:focus:ring-indigo-500/20",
|
|
517
|
-
placeholder: t("agentDrawer.systemPromptPlaceholder")
|
|
518
|
-
}
|
|
519
|
-
)
|
|
520
|
-
] })
|
|
521
|
-
] });
|
|
522
|
-
}
|
|
523
|
-
function ResultsTab({ agentId, t }) {
|
|
524
|
-
const nodeResults = useWorkflowStore((state) => state.nodeResults);
|
|
525
|
-
const agentResult = useMemo(() => {
|
|
526
|
-
return nodeResults[agentId] ?? null;
|
|
527
|
-
}, [nodeResults, agentId]);
|
|
528
|
-
if (!agentResult) {
|
|
529
|
-
return /* @__PURE__ */ jsx("div", { className: "flex flex-col items-center justify-center px-4 py-12 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: t("agentDrawer.noResults") }) });
|
|
530
|
-
}
|
|
531
|
-
const outputs = isRecord(agentResult.data) ? agentResult.data : null;
|
|
532
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-4", children: [
|
|
533
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
534
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
535
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500 dark:text-gray-400", children: t("agentDrawer.status") }),
|
|
536
|
-
/* @__PURE__ */ jsx(StatusBadge, { status: agentResult.status })
|
|
537
|
-
] }),
|
|
538
|
-
agentResult.durationMs != null && /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
|
|
539
|
-
t("agentDrawer.duration"),
|
|
540
|
-
": ",
|
|
541
|
-
formatDuration(agentResult.durationMs)
|
|
542
|
-
] })
|
|
543
|
-
] }),
|
|
544
|
-
agentResult.error && /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-red-200 bg-red-50 p-3 dark:border-red-900/30 dark:bg-red-900/10", children: /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-red-800 dark:text-red-300", children: agentResult.error }) }),
|
|
545
|
-
outputs && Object.keys(outputs).length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
546
|
-
/* @__PURE__ */ jsx("h4", { className: "text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400", children: t("agentDrawer.outputVariables") }),
|
|
547
|
-
Object.entries(outputs).map(([key, value]) => /* @__PURE__ */ jsx(OutputCard, { label: key, value }, key))
|
|
548
|
-
] })
|
|
549
|
-
] });
|
|
550
|
-
}
|
|
551
|
-
function AgentDrawer({ onSaved }) {
|
|
552
|
-
const t = useTranslations("agents.workflow");
|
|
553
|
-
const activeDrawer = useDrawerStore((s) => s.activeDrawer);
|
|
554
|
-
const agentData = useDrawerStore((s) => s.agentData);
|
|
555
|
-
const closeDrawer = useDrawerStore((s) => s.closeDrawer);
|
|
556
|
-
const open = activeDrawer === "agent";
|
|
557
|
-
const agent = agentData?.agent ?? null;
|
|
558
|
-
const models = agentData?.models ?? [];
|
|
559
|
-
const isCreateMode = agentData?.isCreateMode ?? false;
|
|
560
|
-
const [activeTab, setActiveTab] = useState("config");
|
|
561
|
-
const [selectedModelId, setSelectedModelId] = useState("");
|
|
562
|
-
const [selectedFramework, setSelectedFramework] = useState("custom");
|
|
563
|
-
const [temperature, setTemperature] = useState(0.7);
|
|
564
|
-
const [elo, setElo] = useState(1e3);
|
|
565
|
-
const [saved, setSaved] = useState(true);
|
|
566
|
-
const agentId = agent?.agentId ?? agent?.id ?? "";
|
|
567
|
-
useEffect(() => {
|
|
568
|
-
if (!agent) return;
|
|
569
|
-
setSelectedModelId(agent.modelId ?? models[0]?.id ?? "");
|
|
570
|
-
setSelectedFramework(String(agent.framework ?? "custom"));
|
|
571
|
-
setTemperature(agent.temperature ?? 0.7);
|
|
572
|
-
setElo(Number(agent.elo ?? 1e3));
|
|
573
|
-
setSaved(!isCreateMode);
|
|
574
|
-
setActiveTab("config");
|
|
575
|
-
}, [agentId]);
|
|
576
|
-
const dirty = !saved;
|
|
577
|
-
const markDirty = useCallback(() => setSaved(false), []);
|
|
578
|
-
const markSaved = useCallback(() => setSaved(true), []);
|
|
579
|
-
const handleClose = useCallback(() => {
|
|
580
|
-
closeDrawer();
|
|
581
|
-
}, [closeDrawer]);
|
|
582
|
-
const handleMarkSaved = useCallback(() => {
|
|
583
|
-
markSaved();
|
|
584
|
-
onSaved?.();
|
|
585
|
-
}, [markSaved, onSaved]);
|
|
586
|
-
if (!agent) return null;
|
|
587
|
-
const tabs = /* @__PURE__ */ jsx("div", { className: "flex border-b border-white/20 dark:border-white/10", children: ["config", "results"].map((tab) => /* @__PURE__ */ jsx(
|
|
588
|
-
"button",
|
|
589
|
-
{
|
|
590
|
-
type: "button",
|
|
591
|
-
onClick: () => setActiveTab(tab),
|
|
592
|
-
className: `flex-1 px-4 py-2 text-xs font-medium transition-colors ${activeTab === tab ? "border-b-2 border-blue-500 text-blue-600 dark:text-blue-400" : "text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"}`,
|
|
593
|
-
children: t(tab === "config" ? "agentDrawer.configTab" : "agentDrawer.resultsTab")
|
|
594
|
-
},
|
|
595
|
-
tab
|
|
596
|
-
)) });
|
|
597
|
-
return /* @__PURE__ */ jsxs(
|
|
598
|
-
WorkspaceDrawer,
|
|
599
|
-
{
|
|
600
|
-
open,
|
|
601
|
-
onClose: handleClose,
|
|
602
|
-
title: agent.name,
|
|
603
|
-
subtitle: agent.role ?? "",
|
|
604
|
-
gradient: "from-indigo-500 to-purple-600",
|
|
605
|
-
icon: /* @__PURE__ */ jsx(CpuChipIcon, { className: "h-6 w-6 text-white" }),
|
|
606
|
-
tabs,
|
|
607
|
-
children: [
|
|
608
|
-
/* @__PURE__ */ jsx(AgentProfileHeader, { agent, models, t, selectedModelId, setSelectedModelId, selectedFramework, temperature, setTemperature, elo, setElo, onChanged: markDirty }),
|
|
609
|
-
activeTab === "config" ? /* @__PURE__ */ jsx(ConfigTab, { agent, models, t, selectedModelId, setSelectedModelId, selectedFramework, setSelectedFramework: (fw) => setSelectedFramework(fw), temperature, setTemperature, dirty, markDirty, markSaved: handleMarkSaved }) : /* @__PURE__ */ jsx(ResultsTab, { agentId: agent.agentId, t })
|
|
610
|
-
]
|
|
611
|
-
}
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
var useSubworkflowStore = create((set) => ({
|
|
615
|
-
// State
|
|
616
|
-
tool: null,
|
|
617
|
-
open: false,
|
|
618
|
-
name: "",
|
|
619
|
-
category: "external",
|
|
620
|
-
description: "",
|
|
621
|
-
timeoutMs: 1e4,
|
|
622
|
-
retryCount: 0,
|
|
623
|
-
dirty: false,
|
|
624
|
-
// Actions
|
|
625
|
-
openDrawer: (tool) => set({
|
|
626
|
-
tool,
|
|
627
|
-
open: true,
|
|
628
|
-
name: tool.name ?? "",
|
|
629
|
-
category: tool.category ?? "external",
|
|
630
|
-
description: String(tool.description ?? ""),
|
|
631
|
-
timeoutMs: Number(tool.timeoutMs ?? 1e4),
|
|
632
|
-
retryCount: tool.retryCount ?? 0,
|
|
633
|
-
dirty: !tool.toolId
|
|
634
|
-
}),
|
|
635
|
-
closeDrawer: () => set({
|
|
636
|
-
tool: null,
|
|
637
|
-
open: false,
|
|
638
|
-
name: "",
|
|
639
|
-
category: "external",
|
|
640
|
-
description: "",
|
|
641
|
-
timeoutMs: 1e4,
|
|
642
|
-
retryCount: 0,
|
|
643
|
-
dirty: false
|
|
644
|
-
}),
|
|
645
|
-
setName: (name) => set({ name, dirty: true }),
|
|
646
|
-
setCategory: (category) => set({ category, dirty: true }),
|
|
647
|
-
setDescription: (description) => set({ description, dirty: true }),
|
|
648
|
-
setTimeoutMs: (timeoutMs) => set({ timeoutMs, dirty: true }),
|
|
649
|
-
setRetryCount: (retryCount) => set({ retryCount, dirty: true }),
|
|
650
|
-
markDirty: () => set({ dirty: true }),
|
|
651
|
-
markSaved: () => set({ dirty: false })
|
|
652
|
-
}));
|
|
653
|
-
var DEFAULT_SUBWORKFLOW_GRAPH = {
|
|
654
|
-
nodes: [
|
|
655
|
-
{ id: "start", type: "start", position: { x: 80, y: 200 }, data: { entityId: "start", label: "Start", config: { type: "start", inputVariables: [] } } },
|
|
656
|
-
{ id: "end", type: "end", position: { x: 600, y: 200 }, data: { entityId: "end", label: "End", config: { type: "end", outputVariables: [] } } }
|
|
657
|
-
],
|
|
658
|
-
edges: [
|
|
659
|
-
{ id: "e-start-end", source: "start", target: "end", sourceHandle: null, targetHandle: null }
|
|
660
|
-
],
|
|
661
|
-
viewport: { x: 0, y: 0, zoom: 0.85 }
|
|
662
|
-
};
|
|
663
|
-
function VariableChip({ name, type }) {
|
|
664
|
-
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-lg border border-teal-200/50 bg-teal-50/50 px-2 py-0.5 text-[10px] dark:border-teal-400/20 dark:bg-teal-400/10", children: [
|
|
665
|
-
/* @__PURE__ */ jsx("span", { className: "font-semibold text-teal-700 dark:text-teal-300", children: name }),
|
|
666
|
-
/* @__PURE__ */ jsxs("span", { className: "text-teal-500/60 dark:text-teal-400/50", children: [
|
|
667
|
-
": ",
|
|
668
|
-
type
|
|
669
|
-
] })
|
|
670
|
-
] });
|
|
671
|
-
}
|
|
672
|
-
function OutputChip({ name, type }) {
|
|
673
|
-
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-lg border border-violet-200/50 bg-violet-50/50 px-2 py-0.5 text-[10px] dark:border-violet-400/20 dark:bg-violet-400/10", children: [
|
|
674
|
-
/* @__PURE__ */ jsx("span", { className: "font-semibold text-violet-700 dark:text-violet-300", children: name }),
|
|
675
|
-
/* @__PURE__ */ jsxs("span", { className: "text-violet-500/60 dark:text-violet-400/50", children: [
|
|
676
|
-
": ",
|
|
677
|
-
type
|
|
678
|
-
] })
|
|
679
|
-
] });
|
|
680
|
-
}
|
|
681
|
-
function ConfigSection({ title, icon: Icon, defaultOpen = true, children }) {
|
|
682
|
-
const [open, setOpen] = useState(defaultOpen);
|
|
683
|
-
return /* @__PURE__ */ jsxs("div", { className: "border-b border-white/10", children: [
|
|
684
|
-
/* @__PURE__ */ jsxs(
|
|
685
|
-
"button",
|
|
686
|
-
{
|
|
687
|
-
type: "button",
|
|
688
|
-
onClick: () => setOpen(!open),
|
|
689
|
-
className: "flex w-full items-center gap-2 px-4 py-2.5 text-left hover:bg-white/5",
|
|
690
|
-
children: [
|
|
691
|
-
open ? /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-3 w-3 text-gray-400" }) : /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-gray-400" }),
|
|
692
|
-
/* @__PURE__ */ jsx(Icon, { className: "h-3 w-3 text-gray-400" }),
|
|
693
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400", children: title })
|
|
694
|
-
]
|
|
695
|
-
}
|
|
696
|
-
),
|
|
697
|
-
open && /* @__PURE__ */ jsx("div", { className: "px-4 pb-3", children })
|
|
698
|
-
] });
|
|
699
|
-
}
|
|
700
|
-
function SubworkflowDrawer({ onSaved, onMaximize }) {
|
|
701
|
-
const t = useTranslations("agents.workflow");
|
|
702
|
-
const tool = useSubworkflowStore((s) => s.tool);
|
|
703
|
-
const open = useSubworkflowStore((s) => s.open);
|
|
704
|
-
const name = useSubworkflowStore((s) => s.name);
|
|
705
|
-
const category = useSubworkflowStore((s) => s.category);
|
|
706
|
-
const description = useSubworkflowStore((s) => s.description);
|
|
707
|
-
const timeoutMs = useSubworkflowStore((s) => s.timeoutMs);
|
|
708
|
-
const retryCount = useSubworkflowStore((s) => s.retryCount);
|
|
709
|
-
const dirty = useSubworkflowStore((s) => s.dirty);
|
|
710
|
-
const setName = useSubworkflowStore((s) => s.setName);
|
|
711
|
-
const setCategory = useSubworkflowStore((s) => s.setCategory);
|
|
712
|
-
const setDescription = useSubworkflowStore((s) => s.setDescription);
|
|
713
|
-
const setTimeoutMs = useSubworkflowStore((s) => s.setTimeoutMs);
|
|
714
|
-
const setRetryCount = useSubworkflowStore((s) => s.setRetryCount);
|
|
715
|
-
const markDirty = useSubworkflowStore((s) => s.markDirty);
|
|
716
|
-
const markSaved = useSubworkflowStore((s) => s.markSaved);
|
|
717
|
-
const closeDrawer = useSubworkflowStore((s) => s.closeDrawer);
|
|
718
|
-
const isCreateMode = !tool?.toolId;
|
|
719
|
-
const initialGraph = useMemo(() => {
|
|
720
|
-
const config = tool?.config;
|
|
721
|
-
if (config?.type === "workflow" && config.graph) {
|
|
722
|
-
return config.graph;
|
|
723
|
-
}
|
|
724
|
-
return DEFAULT_SUBWORKFLOW_GRAPH;
|
|
725
|
-
}, [tool]);
|
|
726
|
-
const latestGraphRef = useMemo(() => ({ current: initialGraph }), [initialGraph]);
|
|
727
|
-
const handleGraphChange = useCallback((graph2) => {
|
|
728
|
-
latestGraphRef.current = graph2;
|
|
729
|
-
markDirty();
|
|
730
|
-
}, [latestGraphRef, markDirty]);
|
|
731
|
-
const handleSave = useCallback(() => {
|
|
732
|
-
markSaved();
|
|
733
|
-
if (tool) {
|
|
734
|
-
onSaved?.({
|
|
735
|
-
...tool,
|
|
736
|
-
name,
|
|
737
|
-
category,
|
|
738
|
-
description,
|
|
739
|
-
timeoutMs,
|
|
740
|
-
config: { type: "workflow", graph: latestGraphRef.current }
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
}, [tool, onSaved, name, category, description, timeoutMs, latestGraphRef, markSaved]);
|
|
744
|
-
if (!tool) return null;
|
|
745
|
-
const categoryKey = category ?? "external";
|
|
746
|
-
const gradient = tool.color ?? CATEGORY_COLORS[categoryKey] ?? CATEGORY_COLORS.external;
|
|
747
|
-
const categoryPill = CATEGORY_PILL_COLORS[categoryKey] ?? CATEGORY_PILL_COLORS.external;
|
|
748
|
-
const IconComponent = ICON_MAP[tool.icon ?? ""] ?? ArrowPathRoundedSquareIcon;
|
|
749
|
-
const graph = latestGraphRef.current;
|
|
750
|
-
const startNode = graph.nodes.find((n) => n.type === "start");
|
|
751
|
-
const endNode = graph.nodes.find((n) => n.type === "end");
|
|
752
|
-
const startConfig = startNode?.data?.config;
|
|
753
|
-
const endConfig = endNode?.data?.config;
|
|
754
|
-
const inputVariables = (startConfig?.inputVariables ?? []).map((v) => ({ name: v, type: "string" }));
|
|
755
|
-
const outputVariables = (endConfig?.outputVariables ?? []).map((v) => ({ name: v, type: "string" }));
|
|
756
|
-
return /* @__PURE__ */ jsx(
|
|
757
|
-
WorkspaceDrawer,
|
|
758
|
-
{
|
|
759
|
-
open,
|
|
760
|
-
onClose: closeDrawer,
|
|
761
|
-
title: isCreateMode ? t("subworkflowDrawer.createTitle") : name,
|
|
762
|
-
subtitle: t("subworkflowDrawer.subworkflow"),
|
|
763
|
-
gradient: "from-teal-500 to-cyan-600",
|
|
764
|
-
icon: /* @__PURE__ */ jsx(ArrowPathRoundedSquareIcon, { className: "h-6 w-6 text-white" }),
|
|
765
|
-
maxWidth: "max-w-6xl",
|
|
766
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex h-[80vh] min-h-[600px]", children: [
|
|
767
|
-
/* @__PURE__ */ jsxs("div", { className: "flex w-72 flex-shrink-0 flex-col overflow-y-auto border-r border-white/10", children: [
|
|
768
|
-
isCreateMode ? /* @__PURE__ */ jsxs("div", { className: "border-b border-white/10 bg-gradient-to-br from-teal-500/15 via-cyan-500/8 to-transparent px-4 py-4 dark:from-teal-500/8 dark:via-cyan-500/4", children: [
|
|
769
|
-
/* @__PURE__ */ jsx("label", { className: "mb-1 block text-[10px] font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400", children: t("subworkflowDrawer.name") }),
|
|
770
|
-
/* @__PURE__ */ jsx(
|
|
771
|
-
"input",
|
|
772
|
-
{
|
|
773
|
-
type: "text",
|
|
774
|
-
value: name,
|
|
775
|
-
onChange: (event) => setName(event.target.value),
|
|
776
|
-
placeholder: t("subworkflowDrawer.namePlaceholder"),
|
|
777
|
-
autoFocus: true,
|
|
778
|
-
className: "w-full rounded-lg border border-gray-200/50 bg-white/60 px-3 py-2 text-sm font-medium text-gray-900 outline-none placeholder:text-gray-400 focus:border-teal-300/50 focus:ring-1 focus:ring-teal-300/30 dark:border-white/10 dark:bg-white/5 dark:text-white dark:placeholder:text-gray-500"
|
|
779
|
-
}
|
|
780
|
-
),
|
|
781
|
-
/* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-1", children: ["external", "market", "data", "communication", "analytics"].map((cat) => /* @__PURE__ */ jsx(
|
|
782
|
-
"button",
|
|
783
|
-
{
|
|
784
|
-
type: "button",
|
|
785
|
-
onClick: () => setCategory(cat),
|
|
786
|
-
className: `rounded-full px-2 py-1 text-[9px] font-semibold transition-all ${cat === category ? `${CATEGORY_PILL_COLORS[cat] ?? CATEGORY_PILL_COLORS.external} ring-1 ring-current/20` : "bg-white/30 text-gray-500 hover:bg-white/50 dark:bg-white/5 dark:text-gray-400"}`,
|
|
787
|
-
children: cat
|
|
788
|
-
},
|
|
789
|
-
cat
|
|
790
|
-
)) })
|
|
791
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "border-b border-white/10 bg-gradient-to-br from-teal-500/15 via-cyan-500/8 to-transparent px-4 py-4 dark:from-teal-500/8 dark:via-cyan-500/4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
792
|
-
/* @__PURE__ */ jsx("div", { className: `flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br ${gradient} shadow-lg`, children: /* @__PURE__ */ jsx(IconComponent, { className: "h-5 w-5 text-white" }) }),
|
|
793
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
794
|
-
/* @__PURE__ */ jsx("h3", { className: "truncate text-sm font-bold text-gray-900 dark:text-white", children: name }),
|
|
795
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-wrap gap-1", children: [
|
|
796
|
-
/* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-teal-100 px-1.5 py-0.5 text-[8px] font-semibold text-teal-700 dark:bg-teal-400/15 dark:text-teal-400", children: t("subworkflowDrawer.subworkflow") }),
|
|
797
|
-
/* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-1.5 py-0.5 text-[8px] font-medium ${categoryPill}`, children: category })
|
|
798
|
-
] })
|
|
799
|
-
] }),
|
|
800
|
-
onMaximize && tool.toolId && /* @__PURE__ */ jsx(
|
|
801
|
-
"button",
|
|
802
|
-
{
|
|
803
|
-
type: "button",
|
|
804
|
-
onClick: () => onMaximize(tool.toolId),
|
|
805
|
-
title: t("subworkflowDrawer.openFullEditor"),
|
|
806
|
-
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-gray-400 transition-colors hover:bg-white/10 hover:text-teal-500 dark:hover:text-teal-400",
|
|
807
|
-
children: /* @__PURE__ */ jsx(ArrowsPointingOutIcon, { className: "h-4 w-4" })
|
|
808
|
-
}
|
|
809
|
-
)
|
|
810
|
-
] }) }),
|
|
811
|
-
/* @__PURE__ */ jsx("div", { className: "border-b border-white/10 px-4 py-3", children: /* @__PURE__ */ jsx(
|
|
812
|
-
"textarea",
|
|
813
|
-
{
|
|
814
|
-
value: description,
|
|
815
|
-
onChange: (event) => setDescription(event.target.value),
|
|
816
|
-
rows: 2,
|
|
817
|
-
placeholder: t("subworkflowDrawer.descriptionPlaceholder"),
|
|
818
|
-
className: "w-full resize-none rounded-lg border border-gray-200/50 bg-gray-50/50 px-2.5 py-2 text-[11px] leading-relaxed text-gray-700 outline-none placeholder:text-gray-400 focus:border-teal-300/50 dark:border-white/10 dark:bg-white/5 dark:text-gray-300 dark:placeholder:text-gray-500"
|
|
819
|
-
}
|
|
820
|
-
) }),
|
|
821
|
-
/* @__PURE__ */ jsx(ConfigSection, { title: t("subworkflowDrawer.inputVariables"), icon: ArrowsPointingInIcon, children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: inputVariables.length > 0 ? inputVariables.map((variable) => /* @__PURE__ */ jsx(VariableChip, { name: variable.name, type: variable.type }, variable.name)) : /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("subworkflowDrawer.noVariables") }) }) }),
|
|
822
|
-
/* @__PURE__ */ jsx(ConfigSection, { title: t("subworkflowDrawer.outputVariables"), icon: ArrowsPointingOutIcon, children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: outputVariables.length > 0 ? outputVariables.map((variable) => /* @__PURE__ */ jsx(OutputChip, { name: variable.name, type: variable.type }, variable.name)) : /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("subworkflowDrawer.noVariables") }) }) }),
|
|
823
|
-
/* @__PURE__ */ jsxs(ConfigSection, { title: t("subworkflowDrawer.executionSettings"), icon: BoltIcon, defaultOpen: false, children: [
|
|
824
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
825
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
|
|
826
|
-
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1 text-[10px] text-gray-600 dark:text-gray-400", children: [
|
|
827
|
-
/* @__PURE__ */ jsx(ClockIcon, { className: "h-3 w-3" }),
|
|
828
|
-
t("subworkflowDrawer.timeout")
|
|
829
|
-
] }),
|
|
830
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[10px] font-bold tabular-nums text-gray-900 dark:text-white", children: [
|
|
831
|
-
(timeoutMs / 1e3).toFixed(0),
|
|
832
|
-
"s"
|
|
833
|
-
] })
|
|
834
|
-
] }),
|
|
835
|
-
/* @__PURE__ */ jsx(
|
|
836
|
-
"input",
|
|
837
|
-
{
|
|
838
|
-
type: "range",
|
|
839
|
-
min: "1000",
|
|
840
|
-
max: "30000",
|
|
841
|
-
step: "1000",
|
|
842
|
-
value: timeoutMs,
|
|
843
|
-
onChange: (event) => setTimeoutMs(parseInt(event.target.value, 10)),
|
|
844
|
-
className: "h-3 w-full cursor-pointer appearance-none rounded-full bg-gray-200 dark:bg-gray-700 [&::-webkit-slider-thumb]:h-3 [&::-webkit-slider-thumb]:w-3 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-teal-500"
|
|
845
|
-
}
|
|
846
|
-
)
|
|
847
|
-
] }),
|
|
848
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
849
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
|
|
850
|
-
/* @__PURE__ */ jsx("label", { className: "text-[10px] text-gray-600 dark:text-gray-400", children: t("subworkflowDrawer.retries") }),
|
|
851
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold tabular-nums text-gray-900 dark:text-white", children: retryCount })
|
|
852
|
-
] }),
|
|
853
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-1", children: [0, 1, 2, 3].map((count) => /* @__PURE__ */ jsx(
|
|
854
|
-
"button",
|
|
855
|
-
{
|
|
856
|
-
type: "button",
|
|
857
|
-
onClick: () => setRetryCount(count),
|
|
858
|
-
className: `flex-1 rounded py-1 text-[10px] font-medium transition-all ${count === retryCount ? "bg-teal-500 text-white" : "bg-gray-100 text-gray-500 dark:bg-white/5 dark:text-gray-400"}`,
|
|
859
|
-
children: count
|
|
860
|
-
},
|
|
861
|
-
count
|
|
862
|
-
)) })
|
|
863
|
-
] })
|
|
864
|
-
] }),
|
|
865
|
-
/* @__PURE__ */ jsx("div", { className: "mt-auto border-t border-white/10 px-4 py-3", children: dirty ? /* @__PURE__ */ jsx(
|
|
866
|
-
"button",
|
|
867
|
-
{
|
|
868
|
-
type: "button",
|
|
869
|
-
onClick: handleSave,
|
|
870
|
-
disabled: isCreateMode && !name.trim(),
|
|
871
|
-
className: "w-full rounded-lg bg-gradient-to-r from-teal-500 to-cyan-500 py-2 text-xs font-semibold text-white shadow-sm transition-all hover:from-teal-600 hover:to-cyan-600 disabled:cursor-not-allowed disabled:opacity-40",
|
|
872
|
-
children: isCreateMode ? t("subworkflowDrawer.create") : t("subworkflowDrawer.save")
|
|
873
|
-
}
|
|
874
|
-
) : /* @__PURE__ */ jsx("div", { className: "text-center text-[10px] font-medium text-emerald-500", children: t("subworkflowDrawer.saved") }) })
|
|
875
|
-
] }),
|
|
876
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
|
|
877
|
-
WorkflowCanvas,
|
|
878
|
-
{
|
|
879
|
-
initialGraph,
|
|
880
|
-
agents: [],
|
|
881
|
-
models: [],
|
|
882
|
-
tools: [],
|
|
883
|
-
rules: [],
|
|
884
|
-
onGraphChange: handleGraphChange
|
|
885
|
-
}
|
|
886
|
-
) })
|
|
887
|
-
] })
|
|
888
|
-
}
|
|
889
|
-
);
|
|
890
|
-
}
|
|
891
|
-
function PipelineSettingsDrawer({ onSave }) {
|
|
892
|
-
const t = useTranslations("agents.workflow");
|
|
893
|
-
const activeDrawer = useDrawerStore((s) => s.activeDrawer);
|
|
894
|
-
const data = useDrawerStore((s) => s.pipelineSettingsData);
|
|
895
|
-
const closeDrawer = useDrawerStore((s) => s.closeDrawer);
|
|
896
|
-
const open = activeDrawer === "pipeline-settings";
|
|
897
|
-
const [nameValue, setNameValue] = useState("");
|
|
898
|
-
const [descriptionValue, setDescriptionValue] = useState("");
|
|
899
|
-
const [isSaving, setIsSaving] = useState(false);
|
|
900
|
-
useEffect(() => {
|
|
901
|
-
if (data) {
|
|
902
|
-
setNameValue(data.name);
|
|
903
|
-
setDescriptionValue(data.description);
|
|
904
|
-
}
|
|
905
|
-
}, [data]);
|
|
906
|
-
const handleSubmit = async (event) => {
|
|
907
|
-
event.preventDefault();
|
|
908
|
-
const trimmedName = nameValue.trim();
|
|
909
|
-
if (!trimmedName) return;
|
|
910
|
-
setIsSaving(true);
|
|
911
|
-
try {
|
|
912
|
-
await onSave(trimmedName, descriptionValue.trim());
|
|
913
|
-
closeDrawer();
|
|
914
|
-
} catch {
|
|
915
|
-
} finally {
|
|
916
|
-
setIsSaving(false);
|
|
917
|
-
}
|
|
918
|
-
};
|
|
919
|
-
return /* @__PURE__ */ jsx(
|
|
920
|
-
WorkspaceDrawer,
|
|
921
|
-
{
|
|
922
|
-
open,
|
|
923
|
-
onClose: closeDrawer,
|
|
924
|
-
title: t("pipelineSettings"),
|
|
925
|
-
subtitle: t("pipelineSettingsSubtitle"),
|
|
926
|
-
icon: /* @__PURE__ */ jsx(Cog6ToothIcon, { className: "h-5 w-5 text-white" }),
|
|
927
|
-
gradient: "from-indigo-500 to-purple-600",
|
|
928
|
-
children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [
|
|
929
|
-
/* @__PURE__ */ jsx(
|
|
930
|
-
FormInput,
|
|
931
|
-
{
|
|
932
|
-
label: t("pipelineName"),
|
|
933
|
-
value: nameValue,
|
|
934
|
-
onValueChange: setNameValue,
|
|
935
|
-
placeholder: t("pipelineNamePlaceholder"),
|
|
936
|
-
required: true
|
|
937
|
-
}
|
|
938
|
-
),
|
|
939
|
-
/* @__PURE__ */ jsx(
|
|
940
|
-
FormTextarea,
|
|
941
|
-
{
|
|
942
|
-
label: t("pipelineDescription"),
|
|
943
|
-
value: descriptionValue,
|
|
944
|
-
onValueChange: setDescriptionValue,
|
|
945
|
-
placeholder: t("pipelineDescriptionPlaceholder"),
|
|
946
|
-
rows: 4
|
|
947
|
-
}
|
|
948
|
-
),
|
|
949
|
-
/* @__PURE__ */ jsx("div", { className: "pt-2", children: /* @__PURE__ */ jsxs(
|
|
950
|
-
Button,
|
|
951
|
-
{
|
|
952
|
-
type: "submit",
|
|
953
|
-
color: "ios-glass-blue",
|
|
954
|
-
fullWidth: true,
|
|
955
|
-
loading: isSaving,
|
|
956
|
-
loadingText: t("saving"),
|
|
957
|
-
children: [
|
|
958
|
-
/* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" }),
|
|
959
|
-
t("saveSettings")
|
|
960
|
-
]
|
|
961
|
-
}
|
|
962
|
-
) })
|
|
963
|
-
] })
|
|
964
|
-
}
|
|
965
|
-
);
|
|
966
|
-
}
|
|
967
|
-
function onDragStart(event, nodeType, entityId, label, config) {
|
|
968
|
-
event.dataTransfer.setData("nodeType", nodeType);
|
|
969
|
-
event.dataTransfer.setData("entityId", entityId);
|
|
970
|
-
event.dataTransfer.setData("label", label);
|
|
971
|
-
if (config) {
|
|
972
|
-
event.dataTransfer.setData("config", config);
|
|
973
|
-
}
|
|
974
|
-
event.dataTransfer.effectAllowed = "move";
|
|
975
|
-
}
|
|
976
|
-
var LOGIC_NODE_ITEMS = [
|
|
977
|
-
// Control Flow
|
|
978
|
-
{ nodeType: "start", nameKey: "startNode", descriptionKey: "startNodeDescription", subcategory: "control_flow" },
|
|
979
|
-
{ nodeType: "end", nameKey: "endNode", descriptionKey: "endNodeDescription", subcategory: "control_flow" },
|
|
980
|
-
{ nodeType: "if_else", nameKey: "ifElseNode", descriptionKey: "ifElseNodeDescription", subcategory: "control_flow" },
|
|
981
|
-
{ nodeType: "iteration", nameKey: "iterationNode", descriptionKey: "iterationNodeDescription", subcategory: "control_flow" },
|
|
982
|
-
{ nodeType: "iteration_start", nameKey: "iterationStartNode", descriptionKey: "iterationStartNodeDescription", subcategory: "control_flow" },
|
|
983
|
-
{ nodeType: "group", nameKey: "groupNode", descriptionKey: "groupNodeDescription", subcategory: "control_flow" },
|
|
984
|
-
// Data Processing
|
|
985
|
-
{ nodeType: "code", nameKey: "codeNode", descriptionKey: "codeNodeDescription", subcategory: "data_processing" },
|
|
986
|
-
{ nodeType: "http_request", nameKey: "httpRequestNode", descriptionKey: "httpRequestNodeDescription", subcategory: "data_processing" },
|
|
987
|
-
{ nodeType: "template_transform", nameKey: "templateTransformNode", descriptionKey: "templateTransformNodeDescription", subcategory: "data_processing" },
|
|
988
|
-
{ nodeType: "variable_assigner", nameKey: "variableAssignerNode", descriptionKey: "variableAssignerNodeDescription", subcategory: "data_processing" },
|
|
989
|
-
{ nodeType: "variable_aggregator", nameKey: "variableAggregatorNode", descriptionKey: "variableAggregatorNodeDescription", subcategory: "data_processing" },
|
|
990
|
-
{ nodeType: "list_operator", nameKey: "listOperatorNode", descriptionKey: "listOperatorNodeDescription", subcategory: "data_processing" },
|
|
991
|
-
{ nodeType: "document_extractor", nameKey: "documentExtractorNode", descriptionKey: "documentExtractorNodeDescription", subcategory: "data_processing" },
|
|
992
|
-
{ nodeType: "datasource", nameKey: "datasourceNode", descriptionKey: "datasourceNodeDescription", subcategory: "data_processing" },
|
|
993
|
-
// AI/ML
|
|
994
|
-
{ nodeType: "knowledge_base", nameKey: "knowledgeBaseNode", descriptionKey: "knowledgeBaseNodeDescription", subcategory: "ai_ml" },
|
|
995
|
-
{ nodeType: "answer", nameKey: "answerNode", descriptionKey: "answerNodeDescription", subcategory: "ai_ml" },
|
|
996
|
-
{ nodeType: "question_classifier", nameKey: "questionClassifierNode", descriptionKey: "questionClassifierNodeDescription", subcategory: "ai_ml" },
|
|
997
|
-
{ nodeType: "parameter_extractor", nameKey: "parameterExtractorNode", descriptionKey: "parameterExtractorNodeDescription", subcategory: "ai_ml" },
|
|
998
|
-
// Annotation
|
|
999
|
-
{ nodeType: "note", nameKey: "noteNode", descriptionKey: "noteNodeDescription", subcategory: "annotation" }
|
|
1000
|
-
];
|
|
1001
|
-
var SUBCATEGORY_LABELS = {
|
|
1002
|
-
control_flow: "controlFlowSection",
|
|
1003
|
-
data_processing: "dataProcessingSection",
|
|
1004
|
-
ai_ml: "aiMlSection",
|
|
1005
|
-
annotation: "annotationSection"
|
|
1006
|
-
};
|
|
1007
|
-
function SectionHeader({ icon, title, colorClass, count, onAdd, addLabel, isOpen, onToggle }) {
|
|
1008
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2.5", children: [
|
|
1009
|
-
/* @__PURE__ */ jsxs(
|
|
1010
|
-
"button",
|
|
1011
|
-
{
|
|
1012
|
-
type: "button",
|
|
1013
|
-
onClick: onToggle,
|
|
1014
|
-
className: "flex flex-1 items-center gap-1.5 transition-colors",
|
|
1015
|
-
children: [
|
|
1016
|
-
/* @__PURE__ */ jsxs("span", { className: `flex items-center gap-1.5 text-[10px] font-semibold uppercase tracking-wider ${colorClass}`, children: [
|
|
1017
|
-
icon,
|
|
1018
|
-
title,
|
|
1019
|
-
count !== void 0 && /* @__PURE__ */ jsx("span", { className: "ml-1 rounded-full bg-gray-100 px-1.5 py-px text-[9px] font-medium text-gray-500 dark:bg-white/10 dark:text-gray-400", children: count })
|
|
1020
|
-
] }),
|
|
1021
|
-
/* @__PURE__ */ jsx(
|
|
1022
|
-
ChevronDownIcon,
|
|
1023
|
-
{
|
|
1024
|
-
className: `h-3 w-3 text-gray-400 transition-transform duration-200 ${isOpen ? "" : "-rotate-90"}`
|
|
1025
|
-
}
|
|
1026
|
-
)
|
|
1027
|
-
]
|
|
1028
|
-
}
|
|
1029
|
-
),
|
|
1030
|
-
onAdd ? /* @__PURE__ */ jsx(
|
|
1031
|
-
"button",
|
|
1032
|
-
{
|
|
1033
|
-
type: "button",
|
|
1034
|
-
onClick: onAdd,
|
|
1035
|
-
title: addLabel,
|
|
1036
|
-
className: `rounded-md p-1 transition-colors hover:bg-gray-100 dark:hover:bg-white/10 ${colorClass}`,
|
|
1037
|
-
children: /* @__PURE__ */ jsx(PlusIcon, { className: "h-3.5 w-3.5" })
|
|
1038
|
-
}
|
|
1039
|
-
) : null
|
|
1040
|
-
] });
|
|
1041
|
-
}
|
|
1042
|
-
function CollapsibleSection({ title, icon, colorClass, defaultOpen = true, count, onAdd, addLabel, children }) {
|
|
1043
|
-
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
1044
|
-
const safeChildren = Children.toArray(children);
|
|
1045
|
-
return /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200/40 dark:border-white/5", children: [
|
|
1046
|
-
/* @__PURE__ */ jsx(
|
|
1047
|
-
SectionHeader,
|
|
1048
|
-
{
|
|
1049
|
-
icon,
|
|
1050
|
-
title,
|
|
1051
|
-
colorClass,
|
|
1052
|
-
count,
|
|
1053
|
-
onAdd,
|
|
1054
|
-
addLabel,
|
|
1055
|
-
isOpen,
|
|
1056
|
-
onToggle: () => setIsOpen((previous) => !previous)
|
|
1057
|
-
}
|
|
1058
|
-
),
|
|
1059
|
-
isOpen ? /* @__PURE__ */ jsx("div", { className: "space-y-1.5 px-4 pb-3", children: safeChildren }) : null
|
|
1060
|
-
] });
|
|
1061
|
-
}
|
|
1062
|
-
function LogicNodeItemCard({ item, translationFunction }) {
|
|
1063
|
-
const IconComponent = LOGIC_ICON_MAP[item.nodeType];
|
|
1064
|
-
const gradient = LOGIC_NODE_GRADIENTS[item.nodeType] ?? "from-gray-400 to-gray-500";
|
|
1065
|
-
const defaultConfig = createDefaultLogicNodeConfig(item.nodeType);
|
|
1066
|
-
const configJson = defaultConfig ? JSON.stringify(defaultConfig) : void 0;
|
|
1067
|
-
return /* @__PURE__ */ jsxs(
|
|
1068
|
-
"div",
|
|
1069
|
-
{
|
|
1070
|
-
draggable: true,
|
|
1071
|
-
onDragStart: (event) => onDragStart(event, item.nodeType, item.nodeType, translationFunction(item.nameKey), configJson),
|
|
1072
|
-
className: "liquid-surface group flex items-center gap-2 rounded-lg px-3 py-2 transition-all cursor-grab hover:shadow-md active:cursor-grabbing",
|
|
1073
|
-
children: [
|
|
1074
|
-
/* @__PURE__ */ jsx("div", { className: `flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br ${gradient} shadow-sm`, children: IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: "h-3.5 w-3.5 text-white" }) }),
|
|
1075
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1076
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs font-medium text-gray-900 dark:text-white", children: translationFunction(item.nameKey) }),
|
|
1077
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-gray-400 dark:text-gray-500", children: translationFunction(item.descriptionKey) })
|
|
1078
|
-
] })
|
|
1079
|
-
]
|
|
1080
|
-
}
|
|
1081
|
-
);
|
|
1082
|
-
}
|
|
1083
|
-
function NodePalette({ agents, tools, agentTools = [], rules, entities = [], onCreateAgent, onCreateTool, onCreateAgentTool, onCreateRule, onCreateDatasource }) {
|
|
1084
|
-
const t = useTranslations("agents.workflow");
|
|
1085
|
-
const [searchQuery, setSearchQuery] = useState("");
|
|
1086
|
-
const normalizedQuery = searchQuery.toLowerCase().trim();
|
|
1087
|
-
const filteredAgents = useMemo(
|
|
1088
|
-
() => normalizedQuery ? agents.filter(
|
|
1089
|
-
(agent) => agent.name.toLowerCase().includes(normalizedQuery) || (agent.role ?? "").toLowerCase().includes(normalizedQuery)
|
|
1090
|
-
) : agents,
|
|
1091
|
-
[agents, normalizedQuery]
|
|
1092
|
-
);
|
|
1093
|
-
const filteredTools = useMemo(
|
|
1094
|
-
() => normalizedQuery ? tools.filter(
|
|
1095
|
-
(tool) => tool.name.toLowerCase().includes(normalizedQuery) || (tool.category ?? "").toLowerCase().includes(normalizedQuery)
|
|
1096
|
-
) : tools,
|
|
1097
|
-
[tools, normalizedQuery]
|
|
1098
|
-
);
|
|
1099
|
-
const filteredAgentTools = useMemo(
|
|
1100
|
-
() => normalizedQuery ? agentTools.filter(
|
|
1101
|
-
(agentTool) => agentTool.name.toLowerCase().includes(normalizedQuery) || (agentTool.category ?? "").toLowerCase().includes(normalizedQuery)
|
|
1102
|
-
) : agentTools,
|
|
1103
|
-
[agentTools, normalizedQuery]
|
|
1104
|
-
);
|
|
1105
|
-
const filteredRules = useMemo(
|
|
1106
|
-
() => normalizedQuery ? rules.filter(
|
|
1107
|
-
(rule) => rule.name.toLowerCase().includes(normalizedQuery)
|
|
1108
|
-
) : rules,
|
|
1109
|
-
[rules, normalizedQuery]
|
|
1110
|
-
);
|
|
1111
|
-
const entityTypes = useMemo(
|
|
1112
|
-
() => entities.map((entity) => ({
|
|
1113
|
-
id: entity.id,
|
|
1114
|
-
label: entity.label,
|
|
1115
|
-
description: entity.description,
|
|
1116
|
-
fieldCount: entity.fields.length,
|
|
1117
|
-
defaultLimit: entity.defaultLimit,
|
|
1118
|
-
fields: entity.fields
|
|
1119
|
-
})),
|
|
1120
|
-
[entities]
|
|
1121
|
-
);
|
|
1122
|
-
const filteredEntityTypes = useMemo(
|
|
1123
|
-
() => normalizedQuery ? entityTypes.filter(
|
|
1124
|
-
(entity) => entity.label.toLowerCase().includes(normalizedQuery) || entity.description.toLowerCase().includes(normalizedQuery) || entity.id.toLowerCase().includes(normalizedQuery)
|
|
1125
|
-
) : entityTypes,
|
|
1126
|
-
[entityTypes, normalizedQuery]
|
|
1127
|
-
);
|
|
1128
|
-
const filteredLogicItems = useMemo(
|
|
1129
|
-
() => normalizedQuery ? LOGIC_NODE_ITEMS.filter(
|
|
1130
|
-
(item) => t(item.nameKey).toLowerCase().includes(normalizedQuery) || t(item.descriptionKey).toLowerCase().includes(normalizedQuery)
|
|
1131
|
-
) : LOGIC_NODE_ITEMS,
|
|
1132
|
-
[normalizedQuery, t]
|
|
1133
|
-
);
|
|
1134
|
-
const groupedLogicItems = useMemo(() => {
|
|
1135
|
-
const groups = {
|
|
1136
|
-
control_flow: [],
|
|
1137
|
-
data_processing: [],
|
|
1138
|
-
ai_ml: [],
|
|
1139
|
-
annotation: []
|
|
1140
|
-
};
|
|
1141
|
-
for (const item of filteredLogicItems) {
|
|
1142
|
-
groups[item.subcategory].push(item);
|
|
1143
|
-
}
|
|
1144
|
-
return groups;
|
|
1145
|
-
}, [filteredLogicItems]);
|
|
1146
|
-
function renderLogicSubcategory(subcategory, items, isFirst) {
|
|
1147
|
-
if (items.length === 0) return null;
|
|
1148
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
1149
|
-
/* @__PURE__ */ jsx("p", { className: `${isFirst ? "mt-1" : "mt-2"} text-[9px] font-semibold uppercase tracking-wider text-gray-400 dark:text-gray-500`, children: t(SUBCATEGORY_LABELS[subcategory]) }),
|
|
1150
|
-
items.map((item) => /* @__PURE__ */ jsx(LogicNodeItemCard, { item, translationFunction: t }, item.nodeType))
|
|
1151
|
-
] }, subcategory);
|
|
1152
|
-
}
|
|
1153
|
-
return /* @__PURE__ */ jsxs("div", { className: "liquid-surface w-[260px] flex-shrink-0 overflow-y-auto rounded-none border-0 border-r border-gray-200/30 dark:border-white/5", children: [
|
|
1154
|
-
/* @__PURE__ */ jsxs("div", { className: "p-4 pb-2", children: [
|
|
1155
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400", children: t("palette") }),
|
|
1156
|
-
/* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(
|
|
1157
|
-
"input",
|
|
1158
|
-
{
|
|
1159
|
-
type: "text",
|
|
1160
|
-
value: searchQuery,
|
|
1161
|
-
onChange: (event) => setSearchQuery(event.target.value),
|
|
1162
|
-
placeholder: t("searchPalette"),
|
|
1163
|
-
className: "liquid-surface w-full rounded-lg px-2.5 py-1.5 text-[11px] text-gray-900 placeholder-gray-400 outline-none transition-colors focus:ring-1 focus:ring-indigo-300/40 dark:text-white dark:placeholder-gray-500 dark:focus:ring-indigo-500/20"
|
|
1164
|
-
}
|
|
1165
|
-
) })
|
|
1166
|
-
] }),
|
|
1167
|
-
/* @__PURE__ */ jsx(
|
|
1168
|
-
CollapsibleSection,
|
|
1169
|
-
{
|
|
1170
|
-
title: t("agentsSection"),
|
|
1171
|
-
icon: /* @__PURE__ */ jsx(CpuChipIcon, { className: "h-3 w-3" }),
|
|
1172
|
-
colorClass: "text-indigo-600 dark:text-indigo-400",
|
|
1173
|
-
onAdd: onCreateAgent,
|
|
1174
|
-
addLabel: t("newAgent"),
|
|
1175
|
-
children: filteredAgents.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("noAgents") }) : filteredAgents.map((agent) => /* @__PURE__ */ jsxs(
|
|
1176
|
-
"div",
|
|
1177
|
-
{
|
|
1178
|
-
draggable: true,
|
|
1179
|
-
onDragStart: (event) => onDragStart(event, "agent", agent.agentId, agent.name),
|
|
1180
|
-
className: "liquid-surface group flex items-center gap-2 rounded-lg px-3 py-2 transition-all cursor-grab hover:shadow-md active:cursor-grabbing",
|
|
1181
|
-
children: [
|
|
1182
|
-
/* @__PURE__ */ jsxs("div", { className: "relative flex-shrink-0", children: [
|
|
1183
|
-
agent.avatar ? /* @__PURE__ */ jsx("img", { src: agent.avatar, alt: agent.name, className: "h-7 w-7 rounded-full bg-white shadow-sm ring-1 ring-gray-200/50 dark:bg-gray-800 dark:ring-white/10" }) : /* @__PURE__ */ jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-full bg-gradient-to-br from-indigo-400 to-purple-500 shadow-sm", children: /* @__PURE__ */ jsx(CpuChipIcon, { className: "h-3.5 w-3.5 text-white" }) }),
|
|
1184
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -bottom-0.5 -right-0.5 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-indigo-500 ring-1.5 ring-white dark:ring-gray-900", children: /* @__PURE__ */ jsx(CpuChipIcon, { className: "h-2 w-2 text-white" }) })
|
|
1185
|
-
] }),
|
|
1186
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1187
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
1188
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs font-medium text-gray-900 dark:text-white", children: agent.name }),
|
|
1189
|
-
(() => {
|
|
1190
|
-
const tier = getAgentTier(Number(agent.elo ?? 0));
|
|
1191
|
-
return /* @__PURE__ */ jsx("span", { className: `shrink-0 rounded-full px-1.5 py-px text-[8px] font-bold ${tier.pillColor}`, children: t(`agentDrawer.tier${tier.key.charAt(0).toUpperCase()}${tier.key.slice(1)}`) });
|
|
1192
|
-
})()
|
|
1193
|
-
] }),
|
|
1194
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-gray-400 dark:text-gray-500", children: agent.role ?? agent.agentId })
|
|
1195
|
-
] })
|
|
1196
|
-
]
|
|
1197
|
-
},
|
|
1198
|
-
agent.agentId
|
|
1199
|
-
))
|
|
1200
|
-
}
|
|
1201
|
-
),
|
|
1202
|
-
/* @__PURE__ */ jsx(
|
|
1203
|
-
CollapsibleSection,
|
|
1204
|
-
{
|
|
1205
|
-
title: t("agentToolsSection"),
|
|
1206
|
-
icon: /* @__PURE__ */ jsx(CommandLineIcon, { className: "h-3 w-3" }),
|
|
1207
|
-
colorClass: "text-amber-600 dark:text-amber-400",
|
|
1208
|
-
onAdd: onCreateAgentTool,
|
|
1209
|
-
addLabel: t("newAgentTool"),
|
|
1210
|
-
children: filteredAgentTools.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("noAgentTools") }) : filteredAgentTools.map((agentTool) => /* @__PURE__ */ jsxs(
|
|
1211
|
-
"div",
|
|
1212
|
-
{
|
|
1213
|
-
draggable: true,
|
|
1214
|
-
onDragStart: (event) => onDragStart(event, "agent_tool", agentTool.agentToolId, agentTool.name),
|
|
1215
|
-
className: "liquid-surface group flex items-center gap-2 rounded-lg px-3 py-2 transition-all cursor-grab hover:shadow-md active:cursor-grabbing",
|
|
1216
|
-
children: [
|
|
1217
|
-
/* @__PURE__ */ jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br from-amber-400 to-orange-500 shadow-sm", children: /* @__PURE__ */ jsx(CommandLineIcon, { className: "h-3.5 w-3.5 text-white" }) }),
|
|
1218
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1219
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs font-medium text-gray-900 dark:text-white", children: agentTool.name }),
|
|
1220
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-gray-400 dark:text-gray-500", children: agentTool.category ?? "custom" })
|
|
1221
|
-
] }),
|
|
1222
|
-
!agentTool.enabled && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-gray-100 px-1.5 py-0.5 text-[9px] font-medium text-gray-500 dark:bg-white/10 dark:text-gray-400", children: "off" })
|
|
1223
|
-
]
|
|
1224
|
-
},
|
|
1225
|
-
agentTool.agentToolId
|
|
1226
|
-
))
|
|
1227
|
-
}
|
|
1228
|
-
),
|
|
1229
|
-
/* @__PURE__ */ jsx(
|
|
1230
|
-
CollapsibleSection,
|
|
1231
|
-
{
|
|
1232
|
-
title: t("subworkflowsSection"),
|
|
1233
|
-
icon: /* @__PURE__ */ jsx(ArrowPathRoundedSquareIcon, { className: "h-3 w-3" }),
|
|
1234
|
-
colorClass: "text-teal-600 dark:text-teal-400",
|
|
1235
|
-
onAdd: onCreateTool,
|
|
1236
|
-
addLabel: t("newSubworkflow"),
|
|
1237
|
-
children: filteredTools.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("noSubworkflows") }) : filteredTools.map((tool) => /* @__PURE__ */ jsxs(
|
|
1238
|
-
"div",
|
|
1239
|
-
{
|
|
1240
|
-
draggable: true,
|
|
1241
|
-
onDragStart: (event) => onDragStart(event, "tool", tool.toolId, tool.name),
|
|
1242
|
-
className: "liquid-surface group flex items-center gap-2 rounded-lg px-3 py-2 transition-all cursor-grab hover:shadow-md active:cursor-grabbing",
|
|
1243
|
-
children: [
|
|
1244
|
-
/* @__PURE__ */ jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br from-teal-400 to-emerald-500 shadow-sm", children: /* @__PURE__ */ jsx(ArrowPathRoundedSquareIcon, { className: "h-3.5 w-3.5 text-white" }) }),
|
|
1245
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1246
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs font-medium text-gray-900 dark:text-white", children: tool.name }),
|
|
1247
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-gray-400 dark:text-gray-500", children: tool.category })
|
|
1248
|
-
] }),
|
|
1249
|
-
!tool.enabled && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-gray-100 px-1.5 py-0.5 text-[9px] font-medium text-gray-500 dark:bg-white/10 dark:text-gray-400", children: "off" })
|
|
1250
|
-
]
|
|
1251
|
-
},
|
|
1252
|
-
tool.toolId
|
|
1253
|
-
))
|
|
1254
|
-
}
|
|
1255
|
-
),
|
|
1256
|
-
/* @__PURE__ */ jsx(
|
|
1257
|
-
CollapsibleSection,
|
|
1258
|
-
{
|
|
1259
|
-
title: t("rulesSection"),
|
|
1260
|
-
icon: /* @__PURE__ */ jsx(AdjustmentsHorizontalIcon, { className: "h-3 w-3" }),
|
|
1261
|
-
colorClass: "text-violet-600 dark:text-violet-400",
|
|
1262
|
-
onAdd: onCreateRule,
|
|
1263
|
-
addLabel: t("newRule"),
|
|
1264
|
-
children: filteredRules.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("noRules") }) : filteredRules.map((rule) => /* @__PURE__ */ jsxs(
|
|
1265
|
-
"div",
|
|
1266
|
-
{
|
|
1267
|
-
draggable: true,
|
|
1268
|
-
onDragStart: (event) => onDragStart(event, "rule", rule.ruleId, rule.name),
|
|
1269
|
-
className: "liquid-surface group flex items-center gap-2 rounded-lg px-3 py-2 transition-all cursor-grab hover:shadow-md active:cursor-grabbing",
|
|
1270
|
-
children: [
|
|
1271
|
-
/* @__PURE__ */ jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br from-violet-400 to-purple-500 shadow-sm", children: /* @__PURE__ */ jsx(AdjustmentsHorizontalIcon, { className: "h-3.5 w-3.5 text-white" }) }),
|
|
1272
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1273
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs font-medium text-gray-900 dark:text-white", children: rule.name }),
|
|
1274
|
-
/* @__PURE__ */ jsxs("p", { className: "truncate text-[10px] text-gray-400 dark:text-gray-500", children: [
|
|
1275
|
-
"P",
|
|
1276
|
-
String(rule.priority ?? "")
|
|
1277
|
-
] })
|
|
1278
|
-
] }),
|
|
1279
|
-
!rule.enabled && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-gray-100 px-1.5 py-0.5 text-[9px] font-medium text-gray-500 dark:bg-white/10 dark:text-gray-400", children: "off" })
|
|
1280
|
-
]
|
|
1281
|
-
},
|
|
1282
|
-
rule.ruleId
|
|
1283
|
-
))
|
|
1284
|
-
}
|
|
1285
|
-
),
|
|
1286
|
-
/* @__PURE__ */ jsx(
|
|
1287
|
-
CollapsibleSection,
|
|
1288
|
-
{
|
|
1289
|
-
title: t("dataSourcesSection"),
|
|
1290
|
-
icon: /* @__PURE__ */ jsx(CircleStackIcon, { className: "h-3 w-3" }),
|
|
1291
|
-
colorClass: "text-blue-600 dark:text-blue-400",
|
|
1292
|
-
count: filteredEntityTypes.length,
|
|
1293
|
-
onAdd: onCreateDatasource,
|
|
1294
|
-
addLabel: t("newDataSource"),
|
|
1295
|
-
children: filteredEntityTypes.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 dark:text-gray-500", children: t("noDataSources") }) : filteredEntityTypes.map((entity) => {
|
|
1296
|
-
const defaultConfig = JSON.stringify({
|
|
1297
|
-
type: "entity",
|
|
1298
|
-
entityMasterId: entity.id,
|
|
1299
|
-
selectedFields: entity.fields.map((field) => field.name),
|
|
1300
|
-
filterVariables: {},
|
|
1301
|
-
outputVariable: `${entity.label.replace(/\s+/g, "")}Data`,
|
|
1302
|
-
limit: entity.defaultLimit
|
|
1303
|
-
});
|
|
1304
|
-
const EntityIcon = getEntityIcon(entity.id);
|
|
1305
|
-
const entityGradient = getEntityGradient(entity.id);
|
|
1306
|
-
return /* @__PURE__ */ jsxs(
|
|
1307
|
-
"div",
|
|
1308
|
-
{
|
|
1309
|
-
draggable: true,
|
|
1310
|
-
onDragStart: (event) => onDragStart(event, "entity", entity.id, entity.label, defaultConfig),
|
|
1311
|
-
className: "liquid-surface group flex items-center gap-2 rounded-lg px-3 py-2 transition-all cursor-grab hover:shadow-md active:cursor-grabbing",
|
|
1312
|
-
children: [
|
|
1313
|
-
/* @__PURE__ */ jsx("div", { className: `flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br ${entityGradient} shadow-sm`, children: /* @__PURE__ */ jsx(EntityIcon, { className: "h-3.5 w-3.5 text-white" }) }),
|
|
1314
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1315
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs font-medium text-gray-900 dark:text-white", children: entity.label }),
|
|
1316
|
-
/* @__PURE__ */ jsxs("p", { className: "truncate text-[10px] text-gray-400 dark:text-gray-500", children: [
|
|
1317
|
-
entity.fieldCount,
|
|
1318
|
-
" ",
|
|
1319
|
-
t("entityFieldsLabel")
|
|
1320
|
-
] })
|
|
1321
|
-
] })
|
|
1322
|
-
]
|
|
1323
|
-
},
|
|
1324
|
-
entity.id
|
|
1325
|
-
);
|
|
1326
|
-
})
|
|
1327
|
-
}
|
|
1328
|
-
),
|
|
1329
|
-
/* @__PURE__ */ jsxs(
|
|
1330
|
-
CollapsibleSection,
|
|
1331
|
-
{
|
|
1332
|
-
title: t("logicSection"),
|
|
1333
|
-
icon: /* @__PURE__ */ jsx(BoltIcon, { className: "h-3 w-3" }),
|
|
1334
|
-
colorClass: "text-gray-600 dark:text-gray-400",
|
|
1335
|
-
count: filteredLogicItems.length,
|
|
1336
|
-
children: [
|
|
1337
|
-
renderLogicSubcategory("control_flow", groupedLogicItems.control_flow, true),
|
|
1338
|
-
renderLogicSubcategory("data_processing", groupedLogicItems.data_processing, false),
|
|
1339
|
-
renderLogicSubcategory("ai_ml", groupedLogicItems.ai_ml, false),
|
|
1340
|
-
renderLogicSubcategory("annotation", groupedLogicItems.annotation, false)
|
|
1341
|
-
]
|
|
1342
|
-
}
|
|
1343
|
-
)
|
|
1344
|
-
] });
|
|
1345
|
-
}
|
|
1346
|
-
function formatRelativeTime(dateString) {
|
|
1347
|
-
if (!dateString) return "";
|
|
1348
|
-
const date = new Date(dateString);
|
|
1349
|
-
const now = /* @__PURE__ */ new Date();
|
|
1350
|
-
const diffMs = now.getTime() - date.getTime();
|
|
1351
|
-
const diffMinutes = Math.floor(diffMs / 6e4);
|
|
1352
|
-
const diffHours = Math.floor(diffMs / 36e5);
|
|
1353
|
-
const diffDays = Math.floor(diffMs / 864e5);
|
|
1354
|
-
if (diffMinutes < 1) return "just now";
|
|
1355
|
-
if (diffMinutes < 60) return `${diffMinutes}m ago`;
|
|
1356
|
-
if (diffHours < 24) return `${diffHours}h ago`;
|
|
1357
|
-
return `${diffDays}d ago`;
|
|
1358
|
-
}
|
|
1359
|
-
function WorkflowListBar({
|
|
1360
|
-
workflows,
|
|
1361
|
-
activeWorkflowId,
|
|
1362
|
-
isLoading,
|
|
1363
|
-
onSelect,
|
|
1364
|
-
onCreate,
|
|
1365
|
-
onDelete,
|
|
1366
|
-
onConvertToSubworkflow
|
|
1367
|
-
}) {
|
|
1368
|
-
const tWorkflow = useTranslations("agents.workflow");
|
|
1369
|
-
if (isLoading) {
|
|
1370
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-1 pb-3", children: [
|
|
1371
|
-
/* @__PURE__ */ jsx("div", { className: "shimmer h-10 w-40 rounded-xl" }),
|
|
1372
|
-
/* @__PURE__ */ jsx("div", { className: "shimmer h-10 w-40 rounded-xl" })
|
|
1373
|
-
] });
|
|
1374
|
-
}
|
|
1375
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 overflow-x-auto px-1 pb-3 scrollbar-hide", children: [
|
|
1376
|
-
workflows.map((workflow) => {
|
|
1377
|
-
const isActive = workflow.id === activeWorkflowId;
|
|
1378
|
-
return /* @__PURE__ */ jsxs(
|
|
1379
|
-
"div",
|
|
1380
|
-
{
|
|
1381
|
-
role: "button",
|
|
1382
|
-
tabIndex: 0,
|
|
1383
|
-
onClick: () => onSelect(workflow),
|
|
1384
|
-
onKeyDown: (event) => {
|
|
1385
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
1386
|
-
event.preventDefault();
|
|
1387
|
-
onSelect(workflow);
|
|
1388
|
-
}
|
|
1389
|
-
},
|
|
1390
|
-
className: `liquid-surface group relative flex shrink-0 cursor-pointer items-center gap-2.5 rounded-xl px-3.5 py-2 text-left transition-all duration-200 ${isActive ? "liquid-surface-active" : "hover:shadow-md"}`,
|
|
1391
|
-
style: isActive ? { "--glass-accent": "99, 102, 241" } : void 0,
|
|
1392
|
-
children: [
|
|
1393
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
1394
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1395
|
-
/* @__PURE__ */ jsx("span", { className: `truncate text-sm font-medium ${isActive ? "text-indigo-700 dark:text-indigo-300" : "text-gray-700 dark:text-gray-300"}`, children: workflow.name }),
|
|
1396
|
-
/* @__PURE__ */ jsxs("span", { className: "shrink-0 rounded-full bg-gray-100 px-1.5 py-0.5 text-[10px] font-medium text-gray-500 dark:bg-gray-800 dark:text-gray-400", children: [
|
|
1397
|
-
"v",
|
|
1398
|
-
workflow.version
|
|
1399
|
-
] }),
|
|
1400
|
-
workflow.isDraft ? /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-amber-100 px-1.5 py-0.5 text-[10px] font-semibold text-amber-700 dark:bg-amber-900/30 dark:text-amber-300", children: tWorkflow("draftBadge") }) : /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-green-100 px-1.5 py-0.5 text-[10px] font-semibold text-green-700 dark:bg-green-900/30 dark:text-green-300", children: tWorkflow("published") })
|
|
1401
|
-
] }),
|
|
1402
|
-
/* @__PURE__ */ jsx("p", { className: "mt-0.5 text-[10px] text-gray-400 dark:text-gray-500", children: workflow.updatedAt ? formatRelativeTime(typeof workflow.updatedAt === "string" ? workflow.updatedAt : workflow.updatedAt.toISOString()) : "" })
|
|
1403
|
-
] }),
|
|
1404
|
-
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100", children: [
|
|
1405
|
-
onConvertToSubworkflow && /* @__PURE__ */ jsx(
|
|
1406
|
-
"button",
|
|
1407
|
-
{
|
|
1408
|
-
type: "button",
|
|
1409
|
-
onClick: (event) => {
|
|
1410
|
-
event.stopPropagation();
|
|
1411
|
-
onConvertToSubworkflow(workflow);
|
|
1412
|
-
},
|
|
1413
|
-
className: "rounded-md p-1 text-gray-400 transition-colors hover:bg-teal-50 hover:text-teal-600 dark:hover:bg-teal-950/30 dark:hover:text-teal-400",
|
|
1414
|
-
"aria-label": `${tWorkflow("convertToSubworkflow")} ${workflow.name}`,
|
|
1415
|
-
title: tWorkflow("convertToSubworkflow"),
|
|
1416
|
-
children: /* @__PURE__ */ jsx(ArrowPathRoundedSquareIcon, { className: "h-3.5 w-3.5" })
|
|
1417
|
-
}
|
|
1418
|
-
),
|
|
1419
|
-
workflows.length > 1 && /* @__PURE__ */ jsx(
|
|
1420
|
-
"button",
|
|
1421
|
-
{
|
|
1422
|
-
type: "button",
|
|
1423
|
-
onClick: (event) => {
|
|
1424
|
-
event.stopPropagation();
|
|
1425
|
-
onDelete(workflow.id, workflow.name);
|
|
1426
|
-
},
|
|
1427
|
-
className: "rounded-md p-1 text-gray-400 transition-colors hover:bg-red-50 hover:text-red-500 dark:hover:bg-red-950/30 dark:hover:text-red-400",
|
|
1428
|
-
"aria-label": `${tWorkflow("deleteWorkflow")} ${workflow.name}`,
|
|
1429
|
-
children: /* @__PURE__ */ jsx(TrashIcon, { className: "h-3.5 w-3.5" })
|
|
1430
|
-
}
|
|
1431
|
-
)
|
|
1432
|
-
] })
|
|
1433
|
-
]
|
|
1434
|
-
},
|
|
1435
|
-
workflow.id
|
|
1436
|
-
);
|
|
1437
|
-
}),
|
|
1438
|
-
/* @__PURE__ */ jsxs(
|
|
1439
|
-
"button",
|
|
1440
|
-
{
|
|
1441
|
-
type: "button",
|
|
1442
|
-
onClick: onCreate,
|
|
1443
|
-
className: "liquid-surface flex shrink-0 items-center gap-1.5 rounded-xl !border-dashed px-3 py-2 text-xs font-medium text-gray-500 transition-all hover:shadow-md hover:text-indigo-600 dark:text-gray-400 dark:hover:text-indigo-400",
|
|
1444
|
-
children: [
|
|
1445
|
-
/* @__PURE__ */ jsx(PlusIcon, { className: "h-3.5 w-3.5" }),
|
|
1446
|
-
tWorkflow("newWorkflow")
|
|
1447
|
-
]
|
|
1448
|
-
}
|
|
1449
|
-
)
|
|
1450
|
-
] });
|
|
1451
|
-
}
|
|
1452
|
-
function VersionHistoryPanel({
|
|
1453
|
-
open,
|
|
1454
|
-
onClose,
|
|
1455
|
-
workflowId,
|
|
1456
|
-
currentVersion,
|
|
1457
|
-
onPreview,
|
|
1458
|
-
onRestore,
|
|
1459
|
-
fetchVersions
|
|
1460
|
-
}) {
|
|
1461
|
-
const translations = useTranslations("agents.workflow.versionHistory");
|
|
1462
|
-
const [versions, setVersions] = useState([]);
|
|
1463
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
1464
|
-
const [loadError, setLoadError] = useState(null);
|
|
1465
|
-
const loadVersions = useCallback(async () => {
|
|
1466
|
-
if (!fetchVersions) return;
|
|
1467
|
-
setIsLoading(true);
|
|
1468
|
-
setLoadError(null);
|
|
1469
|
-
try {
|
|
1470
|
-
const fetchedVersions = await fetchVersions(workflowId);
|
|
1471
|
-
setVersions(fetchedVersions);
|
|
1472
|
-
} catch (error) {
|
|
1473
|
-
const errorMessage = error instanceof Error ? error.message : "Failed to load versions";
|
|
1474
|
-
setLoadError(errorMessage);
|
|
1475
|
-
} finally {
|
|
1476
|
-
setIsLoading(false);
|
|
1477
|
-
}
|
|
1478
|
-
}, [fetchVersions, workflowId]);
|
|
1479
|
-
useEffect(() => {
|
|
1480
|
-
if (open) {
|
|
1481
|
-
loadVersions();
|
|
1482
|
-
}
|
|
1483
|
-
}, [open, loadVersions]);
|
|
1484
|
-
const formatTimestamp2 = useCallback((timestamp) => {
|
|
1485
|
-
try {
|
|
1486
|
-
const date = new Date(timestamp);
|
|
1487
|
-
return new Intl.DateTimeFormat(void 0, {
|
|
1488
|
-
year: "numeric",
|
|
1489
|
-
month: "short",
|
|
1490
|
-
day: "numeric",
|
|
1491
|
-
hour: "2-digit",
|
|
1492
|
-
minute: "2-digit"
|
|
1493
|
-
}).format(date);
|
|
1494
|
-
} catch {
|
|
1495
|
-
return timestamp;
|
|
1496
|
-
}
|
|
1497
|
-
}, []);
|
|
1498
|
-
if (!open) return null;
|
|
1499
|
-
return /* @__PURE__ */ jsxs(
|
|
1500
|
-
"div",
|
|
1501
|
-
{
|
|
1502
|
-
className: "absolute right-0 top-0 z-40 flex h-full w-80 flex-col border-l border-gray-200 bg-white shadow-xl dark:border-gray-700 dark:bg-gray-900",
|
|
1503
|
-
"data-testid": "version-history-panel",
|
|
1504
|
-
children: [
|
|
1505
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 px-4 py-3 dark:border-gray-700", children: [
|
|
1506
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1507
|
-
/* @__PURE__ */ jsx(ClockIcon, { className: "h-5 w-5 text-gray-500 dark:text-gray-400" }),
|
|
1508
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: translations("title") })
|
|
1509
|
-
] }),
|
|
1510
|
-
/* @__PURE__ */ jsx(
|
|
1511
|
-
"button",
|
|
1512
|
-
{
|
|
1513
|
-
type: "button",
|
|
1514
|
-
onClick: onClose,
|
|
1515
|
-
className: "rounded-lg p-1 text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-800 dark:hover:text-gray-300",
|
|
1516
|
-
"data-testid": "version-history-close",
|
|
1517
|
-
children: /* @__PURE__ */ jsx(XMarkIcon, { className: "h-4 w-4" })
|
|
1518
|
-
}
|
|
1519
|
-
)
|
|
1520
|
-
] }),
|
|
1521
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
1522
|
-
isLoading && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", "data-testid": "version-history-loading", children: /* @__PURE__ */ jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-blue-500 border-t-transparent" }) }),
|
|
1523
|
-
loadError && /* @__PURE__ */ jsxs("div", { className: "px-4 py-8 text-center", "data-testid": "version-history-error", children: [
|
|
1524
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-red-500 dark:text-red-400", children: loadError }),
|
|
1525
|
-
/* @__PURE__ */ jsx(
|
|
1526
|
-
"button",
|
|
1527
|
-
{
|
|
1528
|
-
type: "button",
|
|
1529
|
-
onClick: loadVersions,
|
|
1530
|
-
className: "mt-2 text-xs text-blue-600 hover:underline dark:text-blue-400",
|
|
1531
|
-
children: translations("retry")
|
|
1532
|
-
}
|
|
1533
|
-
)
|
|
1534
|
-
] }),
|
|
1535
|
-
!isLoading && !loadError && versions.length === 0 && /* @__PURE__ */ jsxs("div", { className: "px-4 py-12 text-center", "data-testid": "version-history-empty", children: [
|
|
1536
|
-
/* @__PURE__ */ jsx(ClockIcon, { className: "mx-auto h-8 w-8 text-gray-300 dark:text-gray-600" }),
|
|
1537
|
-
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-gray-500 dark:text-gray-400", children: translations("noVersions") })
|
|
1538
|
-
] }),
|
|
1539
|
-
!isLoading && !loadError && versions.length > 0 && /* @__PURE__ */ jsx("div", { className: "divide-y divide-gray-100 dark:divide-gray-800", children: versions.map((version) => {
|
|
1540
|
-
const isCurrentVersion = version.version === currentVersion;
|
|
1541
|
-
return /* @__PURE__ */ jsxs(
|
|
1542
|
-
"div",
|
|
1543
|
-
{
|
|
1544
|
-
className: `px-4 py-3 transition-colors ${isCurrentVersion ? "bg-blue-50 dark:bg-blue-500/10" : "hover:bg-gray-50 dark:hover:bg-gray-800/50"}`,
|
|
1545
|
-
"data-testid": `version-entry-${version.version}`,
|
|
1546
|
-
children: [
|
|
1547
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1548
|
-
/* @__PURE__ */ jsxs("span", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: [
|
|
1549
|
-
"v",
|
|
1550
|
-
version.version
|
|
1551
|
-
] }),
|
|
1552
|
-
isCurrentVersion && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-blue-100 px-2 py-0.5 text-[10px] font-medium text-blue-700 dark:bg-blue-500/20 dark:text-blue-300", children: translations("current") })
|
|
1553
|
-
] }) }),
|
|
1554
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-1 text-xs text-gray-500 dark:text-gray-400", children: [
|
|
1555
|
-
/* @__PURE__ */ jsx("div", { children: formatTimestamp2(version.publishedAt) }),
|
|
1556
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-0.5", children: [
|
|
1557
|
-
translations("publishedBy"),
|
|
1558
|
-
": ",
|
|
1559
|
-
version.publishedBy
|
|
1560
|
-
] }),
|
|
1561
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-0.5", children: [
|
|
1562
|
-
version.nodeCount,
|
|
1563
|
-
" ",
|
|
1564
|
-
translations("nodes"),
|
|
1565
|
-
" / ",
|
|
1566
|
-
version.edgeCount,
|
|
1567
|
-
" ",
|
|
1568
|
-
translations("edges")
|
|
1569
|
-
] })
|
|
1570
|
-
] }),
|
|
1571
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex gap-2", children: [
|
|
1572
|
-
/* @__PURE__ */ jsxs(
|
|
1573
|
-
"button",
|
|
1574
|
-
{
|
|
1575
|
-
type: "button",
|
|
1576
|
-
onClick: () => onPreview(version),
|
|
1577
|
-
className: "inline-flex items-center gap-1 rounded-md border border-gray-300 px-2 py-1 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-100 dark:border-gray-600 dark:text-gray-400 dark:hover:bg-gray-700",
|
|
1578
|
-
"data-testid": `version-preview-${version.version}`,
|
|
1579
|
-
children: [
|
|
1580
|
-
/* @__PURE__ */ jsx(EyeIcon, { className: "h-3 w-3" }),
|
|
1581
|
-
translations("preview")
|
|
1582
|
-
]
|
|
1583
|
-
}
|
|
1584
|
-
),
|
|
1585
|
-
!isCurrentVersion && /* @__PURE__ */ jsxs(
|
|
1586
|
-
"button",
|
|
1587
|
-
{
|
|
1588
|
-
type: "button",
|
|
1589
|
-
onClick: () => onRestore(version),
|
|
1590
|
-
className: "inline-flex items-center gap-1 rounded-md border border-blue-300 px-2 py-1 text-xs font-medium text-blue-600 transition-colors hover:bg-blue-50 dark:border-blue-600 dark:text-blue-400 dark:hover:bg-blue-500/10",
|
|
1591
|
-
"data-testid": `version-restore-${version.version}`,
|
|
1592
|
-
children: [
|
|
1593
|
-
/* @__PURE__ */ jsx(ArrowPathIcon, { className: "h-3 w-3" }),
|
|
1594
|
-
translations("restore")
|
|
1595
|
-
]
|
|
1596
|
-
}
|
|
1597
|
-
)
|
|
1598
|
-
] })
|
|
1599
|
-
]
|
|
1600
|
-
},
|
|
1601
|
-
version.version
|
|
1602
|
-
);
|
|
1603
|
-
}) })
|
|
1604
|
-
] })
|
|
1605
|
-
]
|
|
1606
|
-
}
|
|
1607
|
-
);
|
|
1608
|
-
}
|
|
1609
|
-
var STATUS_CONFIG = {
|
|
1610
|
-
pending: {
|
|
1611
|
-
icon: ClockIcon,
|
|
1612
|
-
color: "text-gray-400 dark:text-gray-500",
|
|
1613
|
-
background: "bg-gray-100 dark:bg-gray-800",
|
|
1614
|
-
label: "pending"
|
|
1615
|
-
},
|
|
1616
|
-
running: {
|
|
1617
|
-
icon: SpinnerIcon,
|
|
1618
|
-
color: "text-blue-500 dark:text-blue-400",
|
|
1619
|
-
background: "bg-blue-50 dark:bg-blue-500/10",
|
|
1620
|
-
label: "running"
|
|
1621
|
-
},
|
|
1622
|
-
success: {
|
|
1623
|
-
icon: CheckCircleIcon,
|
|
1624
|
-
color: "text-green-500 dark:text-green-400",
|
|
1625
|
-
background: "bg-green-50 dark:bg-green-500/10",
|
|
1626
|
-
label: "success"
|
|
1627
|
-
},
|
|
1628
|
-
error: {
|
|
1629
|
-
icon: XCircleIcon,
|
|
1630
|
-
color: "text-red-500 dark:text-red-400",
|
|
1631
|
-
background: "bg-red-50 dark:bg-red-500/10",
|
|
1632
|
-
label: "error"
|
|
1633
|
-
}
|
|
1634
|
-
};
|
|
1635
|
-
function formatDuration2(durationMs) {
|
|
1636
|
-
if (durationMs < 1e3) {
|
|
1637
|
-
return `${durationMs}ms`;
|
|
1638
|
-
}
|
|
1639
|
-
const seconds = (durationMs / 1e3).toFixed(1);
|
|
1640
|
-
return `${seconds}s`;
|
|
1641
|
-
}
|
|
1642
|
-
function RunPanel({ open, onClose, onRun, onStop }) {
|
|
1643
|
-
const translations = useTranslations("agents.workflow.runPanel");
|
|
1644
|
-
const nodes = useWorkflowStore((state) => state.nodes);
|
|
1645
|
-
const isRunning = useWorkflowStore((state) => state.isRunning);
|
|
1646
|
-
const nodeResults = useWorkflowStore((state) => state.nodeResults);
|
|
1647
|
-
const startNode = nodes.find((node) => node.type === "start");
|
|
1648
|
-
const hasEndNode = nodes.some((node) => node.type === "end");
|
|
1649
|
-
const hasValidStartConfig = Boolean(
|
|
1650
|
-
startNode && typeof startNode.data === "object" && startNode.data !== null && "config" in startNode.data && startNode.data.config && typeof startNode.data.config.type === "string"
|
|
1651
|
-
);
|
|
1652
|
-
const canRun = hasValidStartConfig && hasEndNode;
|
|
1653
|
-
if (!open) return null;
|
|
1654
|
-
const executionNodes = nodes.filter((node) => node.type !== "note");
|
|
1655
|
-
return /* @__PURE__ */ jsxs(
|
|
1656
|
-
"div",
|
|
1657
|
-
{
|
|
1658
|
-
className: "absolute bottom-0 left-0 right-0 z-40 border-t border-gray-200 bg-white shadow-xl dark:border-gray-700 dark:bg-gray-900",
|
|
1659
|
-
"data-testid": "run-panel",
|
|
1660
|
-
children: [
|
|
1661
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-gray-100 px-4 py-2 dark:border-gray-800", children: [
|
|
1662
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1663
|
-
/* @__PURE__ */ jsx(PlayIcon, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" }),
|
|
1664
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: translations("title") }),
|
|
1665
|
-
isRunning && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 rounded-full bg-blue-100 px-2 py-0.5 text-[10px] font-medium text-blue-700 dark:bg-blue-500/20 dark:text-blue-300", children: [
|
|
1666
|
-
/* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 animate-pulse rounded-full bg-blue-500" }),
|
|
1667
|
-
translations("executing")
|
|
1668
|
-
] })
|
|
1669
|
-
] }),
|
|
1670
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1671
|
-
isRunning ? /* @__PURE__ */ jsxs(
|
|
1672
|
-
"button",
|
|
1673
|
-
{
|
|
1674
|
-
type: "button",
|
|
1675
|
-
onClick: onStop,
|
|
1676
|
-
className: "inline-flex items-center gap-1.5 rounded-lg bg-red-500 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-red-600",
|
|
1677
|
-
"data-testid": "run-panel-stop",
|
|
1678
|
-
children: [
|
|
1679
|
-
/* @__PURE__ */ jsx(StopIcon, { className: "h-3.5 w-3.5" }),
|
|
1680
|
-
translations("stop")
|
|
1681
|
-
]
|
|
1682
|
-
}
|
|
1683
|
-
) : /* @__PURE__ */ jsxs(
|
|
1684
|
-
"button",
|
|
1685
|
-
{
|
|
1686
|
-
type: "button",
|
|
1687
|
-
onClick: onRun,
|
|
1688
|
-
disabled: !canRun,
|
|
1689
|
-
className: "inline-flex items-center gap-1.5 rounded-lg bg-green-500 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-green-600 disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-green-500",
|
|
1690
|
-
"data-testid": "run-panel-run",
|
|
1691
|
-
children: [
|
|
1692
|
-
/* @__PURE__ */ jsx(PlayIcon, { className: "h-3.5 w-3.5" }),
|
|
1693
|
-
translations("run")
|
|
1694
|
-
]
|
|
1695
|
-
}
|
|
1696
|
-
),
|
|
1697
|
-
/* @__PURE__ */ jsx(
|
|
1698
|
-
"button",
|
|
1699
|
-
{
|
|
1700
|
-
type: "button",
|
|
1701
|
-
onClick: onClose,
|
|
1702
|
-
className: "rounded-lg p-1 text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-800 dark:hover:text-gray-300",
|
|
1703
|
-
"data-testid": "run-panel-close",
|
|
1704
|
-
children: /* @__PURE__ */ jsx(XMarkIcon, { className: "h-4 w-4" })
|
|
1705
|
-
}
|
|
1706
|
-
)
|
|
1707
|
-
] })
|
|
1708
|
-
] }),
|
|
1709
|
-
/* @__PURE__ */ jsx("div", { className: "max-h-48 overflow-y-auto px-4 py-2", children: executionNodes.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-4 text-center text-sm text-gray-500 dark:text-gray-400", children: translations("noNodes") }) : /* @__PURE__ */ jsx("div", { className: "space-y-1", children: executionNodes.map((node) => {
|
|
1710
|
-
const result = nodeResults[node.id];
|
|
1711
|
-
const status = result?.status ?? "pending";
|
|
1712
|
-
const statusConfig = STATUS_CONFIG[status];
|
|
1713
|
-
const StatusIconComponent = statusConfig.icon;
|
|
1714
|
-
const nodeLabel = typeof node.data === "object" && node.data !== null && "label" in node.data ? String(node.data.label) : node.id;
|
|
1715
|
-
return /* @__PURE__ */ jsxs(
|
|
1716
|
-
"div",
|
|
1717
|
-
{
|
|
1718
|
-
className: `flex items-center gap-3 rounded-lg px-3 py-2 ${statusConfig.background}`,
|
|
1719
|
-
"data-testid": `run-node-${node.id}`,
|
|
1720
|
-
children: [
|
|
1721
|
-
/* @__PURE__ */ jsx(StatusIconComponent, { className: `h-4 w-4 flex-shrink-0 ${statusConfig.color}` }),
|
|
1722
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1723
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1724
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-gray-900 dark:text-white", children: nodeLabel }),
|
|
1725
|
-
/* @__PURE__ */ jsx("span", { className: "rounded bg-gray-200 px-1.5 py-0.5 text-[10px] text-gray-500 dark:bg-gray-700 dark:text-gray-400", children: node.type })
|
|
1726
|
-
] }),
|
|
1727
|
-
result?.error && /* @__PURE__ */ jsx("p", { className: "mt-0.5 truncate text-xs text-red-500 dark:text-red-400", children: result.error })
|
|
1728
|
-
] }),
|
|
1729
|
-
result?.durationMs !== void 0 && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-xs text-gray-500 dark:text-gray-400", children: formatDuration2(result.durationMs) })
|
|
1730
|
-
]
|
|
1731
|
-
},
|
|
1732
|
-
node.id
|
|
1733
|
-
);
|
|
1734
|
-
}) }) })
|
|
1735
|
-
]
|
|
1736
|
-
}
|
|
1737
|
-
);
|
|
1738
|
-
}
|
|
1739
|
-
function SpinnerIcon({ className }) {
|
|
1740
|
-
return /* @__PURE__ */ jsxs(
|
|
1741
|
-
"svg",
|
|
1742
|
-
{
|
|
1743
|
-
className: `animate-spin ${className ?? ""}`,
|
|
1744
|
-
viewBox: "0 0 24 24",
|
|
1745
|
-
fill: "none",
|
|
1746
|
-
stroke: "currentColor",
|
|
1747
|
-
strokeWidth: 2,
|
|
1748
|
-
children: [
|
|
1749
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.25 }),
|
|
1750
|
-
/* @__PURE__ */ jsx("path", { d: "M12 2a10 10 0 0 1 10 10", strokeLinecap: "round" })
|
|
1751
|
-
]
|
|
1752
|
-
}
|
|
1753
|
-
);
|
|
1754
|
-
}
|
|
1755
|
-
function topologicalSort(nodes, edges) {
|
|
1756
|
-
const adjacencyList = /* @__PURE__ */ new Map();
|
|
1757
|
-
const inDegree = /* @__PURE__ */ new Map();
|
|
1758
|
-
for (const node of nodes) {
|
|
1759
|
-
adjacencyList.set(node.id, []);
|
|
1760
|
-
inDegree.set(node.id, 0);
|
|
1761
|
-
}
|
|
1762
|
-
for (const edge of edges) {
|
|
1763
|
-
const neighbors = adjacencyList.get(edge.source);
|
|
1764
|
-
if (neighbors) {
|
|
1765
|
-
neighbors.push(edge.target);
|
|
1766
|
-
}
|
|
1767
|
-
inDegree.set(edge.target, (inDegree.get(edge.target) ?? 0) + 1);
|
|
1768
|
-
}
|
|
1769
|
-
const queue = [];
|
|
1770
|
-
for (const [nodeId, degree] of inDegree.entries()) {
|
|
1771
|
-
if (degree === 0) {
|
|
1772
|
-
queue.push(nodeId);
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
const sorted = [];
|
|
1776
|
-
while (queue.length > 0) {
|
|
1777
|
-
const currentNodeId = queue.shift();
|
|
1778
|
-
sorted.push(currentNodeId);
|
|
1779
|
-
const neighbors = adjacencyList.get(currentNodeId) ?? [];
|
|
1780
|
-
for (const neighborId of neighbors) {
|
|
1781
|
-
const updatedDegree = (inDegree.get(neighborId) ?? 1) - 1;
|
|
1782
|
-
inDegree.set(neighborId, updatedDegree);
|
|
1783
|
-
if (updatedDegree === 0) {
|
|
1784
|
-
queue.push(neighborId);
|
|
1785
|
-
}
|
|
1786
|
-
}
|
|
1787
|
-
}
|
|
1788
|
-
for (const node of nodes) {
|
|
1789
|
-
if (!sorted.includes(node.id)) {
|
|
1790
|
-
sorted.push(node.id);
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
return sorted;
|
|
1794
|
-
}
|
|
1795
|
-
function inferVariables(config, nodeType) {
|
|
1796
|
-
if (!config) {
|
|
1797
|
-
return [];
|
|
1798
|
-
}
|
|
1799
|
-
const variables = [];
|
|
1800
|
-
switch (config.type) {
|
|
1801
|
-
case "start":
|
|
1802
|
-
for (const variableName of config.inputVariables) {
|
|
1803
|
-
if (variableName) {
|
|
1804
|
-
variables.push({ name: variableName, direction: "output", variableType: "any" });
|
|
1805
|
-
}
|
|
1806
|
-
}
|
|
1807
|
-
break;
|
|
1808
|
-
case "end":
|
|
1809
|
-
for (const variableName of config.outputVariables) {
|
|
1810
|
-
if (variableName) {
|
|
1811
|
-
variables.push({ name: variableName, direction: "input", variableType: "any" });
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
break;
|
|
1815
|
-
case "code":
|
|
1816
|
-
variables.push({ name: "code_input", direction: "input", variableType: config.language });
|
|
1817
|
-
variables.push({ name: "code_output", direction: "output", variableType: "any" });
|
|
1818
|
-
break;
|
|
1819
|
-
case "http_request":
|
|
1820
|
-
variables.push({ name: "url", direction: "input", variableType: "string" });
|
|
1821
|
-
variables.push({ name: "response", direction: "output", variableType: "object" });
|
|
1822
|
-
if (config.body) {
|
|
1823
|
-
variables.push({ name: "body", direction: "input", variableType: "string" });
|
|
1824
|
-
}
|
|
1825
|
-
break;
|
|
1826
|
-
case "template_transform":
|
|
1827
|
-
variables.push({ name: "template", direction: "input", variableType: "string" });
|
|
1828
|
-
if (config.outputVariable) {
|
|
1829
|
-
variables.push({ name: config.outputVariable, direction: "output", variableType: "string" });
|
|
1830
|
-
}
|
|
1831
|
-
break;
|
|
1832
|
-
case "if_else":
|
|
1833
|
-
for (const condition of config.conditions) {
|
|
1834
|
-
if (condition.variable) {
|
|
1835
|
-
variables.push({ name: condition.variable, direction: "input", variableType: "any" });
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1838
|
-
variables.push({ name: "true_branch", direction: "output", variableType: "boolean" });
|
|
1839
|
-
variables.push({ name: "false_branch", direction: "output", variableType: "boolean" });
|
|
1840
|
-
break;
|
|
1841
|
-
case "iteration":
|
|
1842
|
-
if (config.iteratorVariable) {
|
|
1843
|
-
variables.push({ name: config.iteratorVariable, direction: "input", variableType: "array" });
|
|
1844
|
-
}
|
|
1845
|
-
variables.push({ name: "iteration_item", direction: "output", variableType: "any" });
|
|
1846
|
-
variables.push({ name: "iteration_index", direction: "output", variableType: "number" });
|
|
1847
|
-
break;
|
|
1848
|
-
case "iteration_start":
|
|
1849
|
-
if (config.iteratorVariable) {
|
|
1850
|
-
variables.push({ name: config.iteratorVariable, direction: "input", variableType: "array" });
|
|
1851
|
-
}
|
|
1852
|
-
if (config.itemVariable) {
|
|
1853
|
-
variables.push({ name: config.itemVariable, direction: "output", variableType: "any" });
|
|
1854
|
-
}
|
|
1855
|
-
if (config.indexVariable) {
|
|
1856
|
-
variables.push({ name: config.indexVariable, direction: "output", variableType: "number" });
|
|
1857
|
-
}
|
|
1858
|
-
break;
|
|
1859
|
-
case "knowledge_base":
|
|
1860
|
-
variables.push({ name: "query", direction: "input", variableType: "string" });
|
|
1861
|
-
variables.push({ name: "results", direction: "output", variableType: "array" });
|
|
1862
|
-
break;
|
|
1863
|
-
case "answer":
|
|
1864
|
-
for (const variableName of config.outputVariables) {
|
|
1865
|
-
if (variableName) {
|
|
1866
|
-
variables.push({ name: variableName, direction: "output", variableType: "any" });
|
|
1867
|
-
}
|
|
1868
|
-
}
|
|
1869
|
-
if (config.outputTemplate) {
|
|
1870
|
-
variables.push({ name: "answer_template", direction: "input", variableType: "string" });
|
|
1871
|
-
}
|
|
1872
|
-
break;
|
|
1873
|
-
case "question_classifier":
|
|
1874
|
-
variables.push({ name: "question", direction: "input", variableType: "string" });
|
|
1875
|
-
for (const category of config.categories) {
|
|
1876
|
-
if (category.name) {
|
|
1877
|
-
variables.push({ name: `category_${category.name}`, direction: "output", variableType: "string" });
|
|
1878
|
-
}
|
|
1879
|
-
}
|
|
1880
|
-
break;
|
|
1881
|
-
case "parameter_extractor":
|
|
1882
|
-
variables.push({ name: "input_text", direction: "input", variableType: "string" });
|
|
1883
|
-
for (const parameter of config.parameters) {
|
|
1884
|
-
if (parameter.name) {
|
|
1885
|
-
variables.push({ name: parameter.name, direction: "output", variableType: parameter.type });
|
|
1886
|
-
}
|
|
1887
|
-
}
|
|
1888
|
-
break;
|
|
1889
|
-
case "variable_assigner":
|
|
1890
|
-
for (const assignment of config.assignments) {
|
|
1891
|
-
if (assignment.source) {
|
|
1892
|
-
variables.push({ name: assignment.source, direction: "input", variableType: "any" });
|
|
1893
|
-
}
|
|
1894
|
-
if (assignment.target) {
|
|
1895
|
-
variables.push({ name: assignment.target, direction: "output", variableType: "any" });
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
break;
|
|
1899
|
-
case "variable_aggregator":
|
|
1900
|
-
for (const variableName of config.inputVariables) {
|
|
1901
|
-
if (variableName) {
|
|
1902
|
-
variables.push({ name: variableName, direction: "input", variableType: "any" });
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
if (config.outputVariable) {
|
|
1906
|
-
variables.push({ name: config.outputVariable, direction: "output", variableType: config.aggregationMode });
|
|
1907
|
-
}
|
|
1908
|
-
break;
|
|
1909
|
-
case "document_extractor":
|
|
1910
|
-
variables.push({ name: "document", direction: "input", variableType: "file" });
|
|
1911
|
-
if (config.outputVariable) {
|
|
1912
|
-
variables.push({ name: config.outputVariable, direction: "output", variableType: config.extractionMode });
|
|
1913
|
-
}
|
|
1914
|
-
break;
|
|
1915
|
-
case "list_operator":
|
|
1916
|
-
if (config.inputVariable) {
|
|
1917
|
-
variables.push({ name: config.inputVariable, direction: "input", variableType: "array" });
|
|
1918
|
-
}
|
|
1919
|
-
if (config.outputVariable) {
|
|
1920
|
-
variables.push({ name: config.outputVariable, direction: "output", variableType: "array" });
|
|
1921
|
-
}
|
|
1922
|
-
if (config.condition) {
|
|
1923
|
-
variables.push({ name: "condition", direction: "input", variableType: "string" });
|
|
1924
|
-
}
|
|
1925
|
-
break;
|
|
1926
|
-
}
|
|
1927
|
-
return variables;
|
|
1928
|
-
}
|
|
1929
|
-
function VariableInspector({ open, onClose }) {
|
|
1930
|
-
const translations = useTranslations("agents.workflow.variableInspector");
|
|
1931
|
-
const nodes = useWorkflowStore((state) => state.nodes);
|
|
1932
|
-
const edges = useWorkflowStore((state) => state.edges);
|
|
1933
|
-
const [expandedNodes, setExpandedNodes] = useState(/* @__PURE__ */ new Set());
|
|
1934
|
-
const toggleNodeExpansion = useCallback((nodeId) => {
|
|
1935
|
-
setExpandedNodes((current) => {
|
|
1936
|
-
const updated = new Set(current);
|
|
1937
|
-
if (updated.has(nodeId)) {
|
|
1938
|
-
updated.delete(nodeId);
|
|
1939
|
-
} else {
|
|
1940
|
-
updated.add(nodeId);
|
|
1941
|
-
}
|
|
1942
|
-
return updated;
|
|
1943
|
-
});
|
|
1944
|
-
}, []);
|
|
1945
|
-
const nodeVariableEntries = useMemo(() => {
|
|
1946
|
-
const relevantNodes = nodes.filter((node) => node.type !== "note");
|
|
1947
|
-
const sortedNodeIds = topologicalSort(relevantNodes, edges);
|
|
1948
|
-
const entries = [];
|
|
1949
|
-
for (const nodeId of sortedNodeIds) {
|
|
1950
|
-
const node = relevantNodes.find((candidateNode) => candidateNode.id === nodeId);
|
|
1951
|
-
if (!node) continue;
|
|
1952
|
-
const nodeData = node.data;
|
|
1953
|
-
const config = nodeData?.config;
|
|
1954
|
-
const label = nodeData?.label ?? node.id;
|
|
1955
|
-
const nodeType = node.type ?? "unknown";
|
|
1956
|
-
const variables = inferVariables(config);
|
|
1957
|
-
entries.push({
|
|
1958
|
-
nodeId: node.id,
|
|
1959
|
-
nodeLabel: label,
|
|
1960
|
-
nodeType,
|
|
1961
|
-
variables
|
|
1962
|
-
});
|
|
1963
|
-
}
|
|
1964
|
-
return entries;
|
|
1965
|
-
}, [nodes, edges]);
|
|
1966
|
-
if (!open) return null;
|
|
1967
|
-
return /* @__PURE__ */ jsxs(
|
|
1968
|
-
"div",
|
|
1969
|
-
{
|
|
1970
|
-
className: "absolute right-0 top-0 z-40 flex h-full w-80 flex-col border-l border-gray-200 bg-white shadow-xl dark:border-gray-700 dark:bg-gray-900",
|
|
1971
|
-
"data-testid": "variable-inspector",
|
|
1972
|
-
children: [
|
|
1973
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 px-4 py-3 dark:border-gray-700", children: [
|
|
1974
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1975
|
-
/* @__PURE__ */ jsx(VariableIcon, { className: "h-5 w-5 text-gray-500 dark:text-gray-400" }),
|
|
1976
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: translations("title") })
|
|
1977
|
-
] }),
|
|
1978
|
-
/* @__PURE__ */ jsx(
|
|
1979
|
-
"button",
|
|
1980
|
-
{
|
|
1981
|
-
type: "button",
|
|
1982
|
-
onClick: onClose,
|
|
1983
|
-
className: "rounded-lg p-1 text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-800 dark:hover:text-gray-300",
|
|
1984
|
-
"data-testid": "variable-inspector-close",
|
|
1985
|
-
children: /* @__PURE__ */ jsx(XMarkIcon, { className: "h-4 w-4" })
|
|
1986
|
-
}
|
|
1987
|
-
)
|
|
1988
|
-
] }),
|
|
1989
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: nodeVariableEntries.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "px-4 py-12 text-center", "data-testid": "variable-inspector-empty", children: [
|
|
1990
|
-
/* @__PURE__ */ jsx(VariableIcon, { className: "mx-auto h-8 w-8 text-gray-300 dark:text-gray-600" }),
|
|
1991
|
-
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-gray-500 dark:text-gray-400", children: translations("noNodes") })
|
|
1992
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "divide-y divide-gray-100 dark:divide-gray-800", children: nodeVariableEntries.map((entry) => {
|
|
1993
|
-
const isExpanded = expandedNodes.has(entry.nodeId);
|
|
1994
|
-
const IconComponent = LOGIC_ICON_MAP[entry.nodeType];
|
|
1995
|
-
const gradient = LOGIC_NODE_GRADIENTS[entry.nodeType] ?? "from-gray-400 to-gray-500";
|
|
1996
|
-
const inputVariables = entry.variables.filter((variable) => variable.direction === "input");
|
|
1997
|
-
const outputVariables = entry.variables.filter((variable) => variable.direction === "output");
|
|
1998
|
-
return /* @__PURE__ */ jsxs("div", { "data-testid": `variable-node-${entry.nodeId}`, children: [
|
|
1999
|
-
/* @__PURE__ */ jsxs(
|
|
2000
|
-
"button",
|
|
2001
|
-
{
|
|
2002
|
-
type: "button",
|
|
2003
|
-
onClick: () => toggleNodeExpansion(entry.nodeId),
|
|
2004
|
-
className: "flex w-full items-center gap-2 px-4 py-2.5 text-left transition-colors hover:bg-gray-50 dark:hover:bg-gray-800/50",
|
|
2005
|
-
children: [
|
|
2006
|
-
isExpanded ? /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-3.5 w-3.5 flex-shrink-0 text-gray-400" }) : /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3.5 w-3.5 flex-shrink-0 text-gray-400" }),
|
|
2007
|
-
/* @__PURE__ */ jsx("div", { className: `flex h-5 w-5 flex-shrink-0 items-center justify-center rounded bg-gradient-to-br ${gradient}`, children: IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: "h-3 w-3 text-white" }) }),
|
|
2008
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-gray-900 dark:text-white", children: entry.nodeLabel }),
|
|
2009
|
-
/* @__PURE__ */ jsxs("span", { className: "ml-auto flex-shrink-0 text-[10px] text-gray-400 dark:text-gray-500", children: [
|
|
2010
|
-
entry.variables.length,
|
|
2011
|
-
" ",
|
|
2012
|
-
translations("variables")
|
|
2013
|
-
] })
|
|
2014
|
-
]
|
|
2015
|
-
}
|
|
2016
|
-
),
|
|
2017
|
-
isExpanded && /* @__PURE__ */ jsx("div", { className: "bg-gray-50/50 px-4 pb-2 dark:bg-gray-800/30", children: entry.variables.length === 0 ? /* @__PURE__ */ jsx("p", { className: "py-2 pl-9 text-xs italic text-gray-400 dark:text-gray-500", children: translations("noVariables") }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2018
|
-
inputVariables.length > 0 && /* @__PURE__ */ jsxs("div", { className: "pl-9 pt-1", children: [
|
|
2019
|
-
/* @__PURE__ */ jsx("div", { className: "mb-1 text-[10px] font-medium uppercase tracking-wider text-gray-400 dark:text-gray-500", children: translations("inputs") }),
|
|
2020
|
-
inputVariables.map((variable, index) => /* @__PURE__ */ jsxs(
|
|
2021
|
-
"div",
|
|
2022
|
-
{
|
|
2023
|
-
className: "flex items-center gap-2 py-0.5",
|
|
2024
|
-
children: [
|
|
2025
|
-
/* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-blue-400" }),
|
|
2026
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-700 dark:text-gray-300", children: variable.name }),
|
|
2027
|
-
/* @__PURE__ */ jsx("span", { className: "rounded bg-gray-200 px-1 py-0.5 text-[9px] text-gray-500 dark:bg-gray-700 dark:text-gray-400", children: variable.variableType })
|
|
2028
|
-
]
|
|
2029
|
-
},
|
|
2030
|
-
`${variable.name}-${index}`
|
|
2031
|
-
))
|
|
2032
|
-
] }),
|
|
2033
|
-
outputVariables.length > 0 && /* @__PURE__ */ jsxs("div", { className: "pl-9 pt-1", children: [
|
|
2034
|
-
/* @__PURE__ */ jsx("div", { className: "mb-1 text-[10px] font-medium uppercase tracking-wider text-gray-400 dark:text-gray-500", children: translations("outputs") }),
|
|
2035
|
-
outputVariables.map((variable, index) => /* @__PURE__ */ jsxs(
|
|
2036
|
-
"div",
|
|
2037
|
-
{
|
|
2038
|
-
className: "flex items-center gap-2 py-0.5",
|
|
2039
|
-
children: [
|
|
2040
|
-
/* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-green-400" }),
|
|
2041
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-700 dark:text-gray-300", children: variable.name }),
|
|
2042
|
-
/* @__PURE__ */ jsx("span", { className: "rounded bg-gray-200 px-1 py-0.5 text-[9px] text-gray-500 dark:bg-gray-700 dark:text-gray-400", children: variable.variableType })
|
|
2043
|
-
]
|
|
2044
|
-
},
|
|
2045
|
-
`${variable.name}-${index}`
|
|
2046
|
-
))
|
|
2047
|
-
] })
|
|
2048
|
-
] }) })
|
|
2049
|
-
] }, entry.nodeId);
|
|
2050
|
-
}) }) })
|
|
2051
|
-
]
|
|
2052
|
-
}
|
|
2053
|
-
);
|
|
2054
|
-
}
|
|
2055
|
-
function RunInputDialog({
|
|
2056
|
-
open,
|
|
2057
|
-
onClose,
|
|
2058
|
-
onRun
|
|
2059
|
-
}) {
|
|
2060
|
-
const t = useTranslations("agents.workflow.runInputDialog");
|
|
2061
|
-
const nodes = useWorkflowStore((state) => state.nodes);
|
|
2062
|
-
const [values, setValues] = useState({});
|
|
2063
|
-
const inputVariableNames = useMemo(() => {
|
|
2064
|
-
const storeStartNode = nodes.find((node) => node.type === "start");
|
|
2065
|
-
if (!storeStartNode || typeof storeStartNode.data !== "object" || storeStartNode.data === null) return [];
|
|
2066
|
-
if (!("config" in storeStartNode.data) || !storeStartNode.data.config) return [];
|
|
2067
|
-
const startConfig = storeStartNode.data.config;
|
|
2068
|
-
return startConfig.inputVariables ?? [];
|
|
2069
|
-
}, [nodes]);
|
|
2070
|
-
const handleValueChange = useCallback((variableName, variableValue) => {
|
|
2071
|
-
setValues((previous) => ({ ...previous, [variableName]: variableValue }));
|
|
2072
|
-
}, []);
|
|
2073
|
-
const handleSubmit = useCallback(() => {
|
|
2074
|
-
const inputVariables = {};
|
|
2075
|
-
for (const variableName of inputVariableNames) {
|
|
2076
|
-
inputVariables[variableName] = values[variableName] ?? "";
|
|
2077
|
-
}
|
|
2078
|
-
onRun(inputVariables);
|
|
2079
|
-
onClose();
|
|
2080
|
-
setValues({});
|
|
2081
|
-
}, [inputVariableNames, values, onRun, onClose]);
|
|
2082
|
-
const handleClose = useCallback(() => {
|
|
2083
|
-
onClose();
|
|
2084
|
-
setValues({});
|
|
2085
|
-
}, [onClose]);
|
|
2086
|
-
if (!open) return null;
|
|
2087
|
-
return /* @__PURE__ */ jsxs(
|
|
2088
|
-
GlassFormModal,
|
|
2089
|
-
{
|
|
2090
|
-
open,
|
|
2091
|
-
onClose: handleClose,
|
|
2092
|
-
title: t("title"),
|
|
2093
|
-
subtitle: t("subtitle"),
|
|
2094
|
-
maxWidth: "md",
|
|
2095
|
-
showFooter: false,
|
|
2096
|
-
children: [
|
|
2097
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: inputVariableNames.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-center text-sm text-gray-500 dark:text-gray-400", children: t("noInputs") }) : inputVariableNames.map((variableName) => /* @__PURE__ */ jsxs("div", { children: [
|
|
2098
|
-
/* @__PURE__ */ jsx("label", { className: "mb-1 block text-xs font-medium text-gray-700 dark:text-gray-300", children: variableName }),
|
|
2099
|
-
/* @__PURE__ */ jsx(
|
|
2100
|
-
Input,
|
|
2101
|
-
{
|
|
2102
|
-
value: values[variableName] ?? "",
|
|
2103
|
-
onChange: (event) => handleValueChange(variableName, event.target.value),
|
|
2104
|
-
placeholder: `${t("variableValue")}...`
|
|
2105
|
-
}
|
|
2106
|
-
)
|
|
2107
|
-
] }, variableName)) }),
|
|
2108
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center justify-end gap-2", children: [
|
|
2109
|
-
/* @__PURE__ */ jsx(Button, { size: "sm", plain: true, onClick: handleClose, children: t("cancel") }),
|
|
2110
|
-
/* @__PURE__ */ jsxs(Button, { size: "sm", gradient: true, onClick: handleSubmit, children: [
|
|
2111
|
-
/* @__PURE__ */ jsx(PlayIcon, { className: "h-3.5 w-3.5", "data-slot": "icon" }),
|
|
2112
|
-
t("run")
|
|
2113
|
-
] })
|
|
2114
|
-
] })
|
|
2115
|
-
]
|
|
2116
|
-
}
|
|
2117
|
-
);
|
|
2118
|
-
}
|
|
2119
|
-
var STATUS_STYLES = {
|
|
2120
|
-
completed: { icon: CheckCircleIcon, colorClass: "text-green-500" },
|
|
2121
|
-
failed: { icon: ExclamationCircleIcon, colorClass: "text-red-500" },
|
|
2122
|
-
running: { icon: ArrowPathIcon, colorClass: "text-blue-500 animate-spin" },
|
|
2123
|
-
pending: { icon: ClockIcon, colorClass: "text-gray-400" },
|
|
2124
|
-
success: { icon: CheckCircleIcon, colorClass: "text-green-500" },
|
|
2125
|
-
error: { icon: ExclamationCircleIcon, colorClass: "text-red-500" },
|
|
2126
|
-
skipped: { icon: ClockIcon, colorClass: "text-gray-400" }
|
|
2127
|
-
};
|
|
2128
|
-
function formatDuration3(durationMs) {
|
|
2129
|
-
if (durationMs === null) return "\u2014";
|
|
2130
|
-
if (durationMs < 1e3) return `${durationMs}ms`;
|
|
2131
|
-
return `${(durationMs / 1e3).toFixed(1)}s`;
|
|
2132
|
-
}
|
|
2133
|
-
function formatTimestamp(timestamp) {
|
|
2134
|
-
const date = new Date(timestamp);
|
|
2135
|
-
return date.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
2136
|
-
}
|
|
2137
|
-
function PreviewPanel({ open, onClose, workflowId, loadRuns }) {
|
|
2138
|
-
const t = useTranslations("agents.workflow.previewPanel");
|
|
2139
|
-
const [runs, setRuns] = useState([]);
|
|
2140
|
-
const [isLoadingRuns, setIsLoadingRuns] = useState(false);
|
|
2141
|
-
const [selectedRun, setSelectedRun] = useState(null);
|
|
2142
|
-
const [selectedNode, setSelectedNode] = useState(null);
|
|
2143
|
-
const isRunning = useWorkflowStore((state) => state.isRunning);
|
|
2144
|
-
const nodeResults = useWorkflowStore((state) => state.nodeResults);
|
|
2145
|
-
const refreshRuns = useCallback(async () => {
|
|
2146
|
-
setIsLoadingRuns(true);
|
|
2147
|
-
try {
|
|
2148
|
-
const workflowRuns = await loadRuns(workflowId);
|
|
2149
|
-
setRuns(workflowRuns);
|
|
2150
|
-
} finally {
|
|
2151
|
-
setIsLoadingRuns(false);
|
|
2152
|
-
}
|
|
2153
|
-
}, [loadRuns, workflowId]);
|
|
2154
|
-
useEffect(() => {
|
|
2155
|
-
if (open) void refreshRuns();
|
|
2156
|
-
}, [open, refreshRuns]);
|
|
2157
|
-
useEffect(() => {
|
|
2158
|
-
if (!isRunning && open) void refreshRuns();
|
|
2159
|
-
}, [isRunning, open, refreshRuns]);
|
|
2160
|
-
if (!open) return null;
|
|
2161
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2162
|
-
/* @__PURE__ */ jsx("div", { className: "fixed inset-x-0 top-[120px] bottom-0 z-40 bg-black/10 backdrop-blur-[1px]", onClick: onClose }),
|
|
2163
|
-
/* @__PURE__ */ jsxs("div", { className: "fixed right-0 top-[120px] bottom-0 z-50 w-96 overflow-hidden border-l border-white/20 bg-white/95 shadow-2xl backdrop-blur-xl dark:border-gray-700/50 dark:bg-gray-800/95", children: [
|
|
2164
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-gray-200/50 px-4 py-3 dark:border-gray-700/50", children: [
|
|
2165
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: t("title") }),
|
|
2166
|
-
/* @__PURE__ */ jsx(
|
|
2167
|
-
"button",
|
|
2168
|
-
{
|
|
2169
|
-
type: "button",
|
|
2170
|
-
onClick: onClose,
|
|
2171
|
-
className: "rounded-lg p-1 text-gray-400 hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-700 dark:hover:text-gray-300",
|
|
2172
|
-
children: /* @__PURE__ */ jsx(XMarkIcon, { className: "h-4 w-4" })
|
|
2173
|
-
}
|
|
2174
|
-
)
|
|
2175
|
-
] }),
|
|
2176
|
-
/* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [
|
|
2177
|
-
isRunning && /* @__PURE__ */ jsxs("div", { className: "border-b border-gray-200/50 px-4 py-3 dark:border-gray-700/50", children: [
|
|
2178
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
|
|
2179
|
-
/* @__PURE__ */ jsx(ArrowPathIcon, { className: "h-4 w-4 animate-spin text-blue-500" }),
|
|
2180
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-blue-600 dark:text-blue-400", children: t("activeRun") })
|
|
2181
|
-
] }),
|
|
2182
|
-
/* @__PURE__ */ jsx("div", { className: "max-h-60 space-y-1 overflow-y-auto", children: Object.entries(nodeResults).map(([nodeId, result]) => {
|
|
2183
|
-
const statusStyle = STATUS_STYLES[result.status] ?? STATUS_STYLES.pending;
|
|
2184
|
-
const StatusIcon = statusStyle.icon;
|
|
2185
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-lg px-2 py-1.5 text-xs hover:bg-gray-50 dark:hover:bg-gray-700/50", children: [
|
|
2186
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2187
|
-
/* @__PURE__ */ jsx(StatusIcon, { className: `h-3.5 w-3.5 ${statusStyle.colorClass}` }),
|
|
2188
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-gray-700 dark:text-gray-300", children: nodeId.slice(0, 8) })
|
|
2189
|
-
] }),
|
|
2190
|
-
result.durationMs !== void 0 && /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: formatDuration3(result.durationMs) })
|
|
2191
|
-
] }, nodeId);
|
|
2192
|
-
}) })
|
|
2193
|
-
] }),
|
|
2194
|
-
selectedNode && /* @__PURE__ */ jsxs("div", { className: "border-b border-gray-200/50 px-4 py-3 dark:border-gray-700/50", children: [
|
|
2195
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
|
|
2196
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-gray-900 dark:text-white", children: t("nodeDetail") }),
|
|
2197
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setSelectedNode(null), className: "text-[10px] text-gray-400 hover:text-gray-600 dark:hover:text-gray-300", children: t("close") })
|
|
2198
|
-
] }),
|
|
2199
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2 text-xs", children: [
|
|
2200
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
2201
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-500", children: t("status") }),
|
|
2202
|
-
/* @__PURE__ */ jsx("span", { className: STATUS_STYLES[selectedNode.status]?.colorClass ?? "text-gray-400", children: t(selectedNode.status) })
|
|
2203
|
-
] }),
|
|
2204
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
2205
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-500", children: t("duration") }),
|
|
2206
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-700 dark:text-gray-300", children: formatDuration3(selectedNode.durationMs) })
|
|
2207
|
-
] }),
|
|
2208
|
-
selectedNode.error && /* @__PURE__ */ jsxs("div", { children: [
|
|
2209
|
-
/* @__PURE__ */ jsx("span", { className: "text-red-500", children: t("error") }),
|
|
2210
|
-
/* @__PURE__ */ jsx("pre", { className: "mt-1 max-h-20 overflow-auto whitespace-pre-wrap rounded bg-red-50 p-2 text-[10px] text-red-700 dark:bg-red-900/20 dark:text-red-300", children: selectedNode.error })
|
|
2211
|
-
] }),
|
|
2212
|
-
Object.keys(selectedNode.outputs).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
2213
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-500", children: t("outputs") }),
|
|
2214
|
-
/* @__PURE__ */ jsx("pre", { className: "mt-1 max-h-32 overflow-auto whitespace-pre-wrap rounded bg-gray-50 p-2 text-[10px] text-gray-700 dark:bg-gray-700/50 dark:text-gray-300", children: JSON.stringify(selectedNode.outputs, null, 2) })
|
|
2215
|
-
] })
|
|
2216
|
-
] })
|
|
2217
|
-
] }),
|
|
2218
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-4 py-3", children: [
|
|
2219
|
-
/* @__PURE__ */ jsx("h4", { className: "mb-2 text-xs font-semibold text-gray-500 dark:text-gray-400", children: t("runHistory") }),
|
|
2220
|
-
isLoadingRuns && /* @__PURE__ */ jsx("div", { className: "space-y-2", children: [1, 2, 3].map((index) => /* @__PURE__ */ jsx("div", { className: "shimmer h-14 rounded-lg" }, index)) }),
|
|
2221
|
-
!isLoadingRuns && runs.length === 0 && /* @__PURE__ */ jsxs("div", { className: "py-8 text-center", children: [
|
|
2222
|
-
/* @__PURE__ */ jsx(ClockIcon, { className: "mx-auto mb-2 h-8 w-8 text-gray-300 dark:text-gray-600" }),
|
|
2223
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t("noRuns") }),
|
|
2224
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-[10px] text-gray-400 dark:text-gray-500", children: t("noRunsDescription") })
|
|
2225
|
-
] }),
|
|
2226
|
-
!isLoadingRuns && runs.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: runs.map((run) => {
|
|
2227
|
-
const statusStyle = STATUS_STYLES[run.status] ?? STATUS_STYLES.pending;
|
|
2228
|
-
const StatusIcon = statusStyle.icon;
|
|
2229
|
-
const isSelected = selectedRun?.id === run.id;
|
|
2230
|
-
return /* @__PURE__ */ jsxs(
|
|
2231
|
-
"button",
|
|
2232
|
-
{
|
|
2233
|
-
type: "button",
|
|
2234
|
-
onClick: () => {
|
|
2235
|
-
setSelectedRun(isSelected ? null : run);
|
|
2236
|
-
setSelectedNode(null);
|
|
2237
|
-
},
|
|
2238
|
-
className: `w-full rounded-lg border px-3 py-2.5 text-left transition-colors ${isSelected ? "border-blue-200 bg-blue-50/50 dark:border-blue-800 dark:bg-blue-900/20" : "border-gray-100 hover:border-gray-200 hover:bg-gray-50 dark:border-gray-700/50 dark:hover:border-gray-600 dark:hover:bg-gray-700/30"}`,
|
|
2239
|
-
children: [
|
|
2240
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2241
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2242
|
-
/* @__PURE__ */ jsx(StatusIcon, { className: `h-3.5 w-3.5 ${statusStyle.colorClass}` }),
|
|
2243
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-900 dark:text-white", children: formatTimestamp(run.createdAt) })
|
|
2244
|
-
] }),
|
|
2245
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400", children: formatDuration3(run.totalDurationMs) })
|
|
2246
|
-
] }),
|
|
2247
|
-
run.error && /* @__PURE__ */ jsx("p", { className: "mt-1 truncate text-[10px] text-red-500", children: run.error })
|
|
2248
|
-
]
|
|
2249
|
-
},
|
|
2250
|
-
run.id
|
|
2251
|
-
);
|
|
2252
|
-
}) }),
|
|
2253
|
-
selectedRun && selectedRun.nodeResults.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-1", children: [
|
|
2254
|
-
/* @__PURE__ */ jsx("h5", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-gray-400", children: "Nodes" }),
|
|
2255
|
-
selectedRun.nodeResults.map((nodeResult) => {
|
|
2256
|
-
const nodeStatusStyle = STATUS_STYLES[nodeResult.status] ?? STATUS_STYLES.pending;
|
|
2257
|
-
const NodeStatusIcon = nodeStatusStyle.icon;
|
|
2258
|
-
return /* @__PURE__ */ jsxs(
|
|
2259
|
-
"button",
|
|
2260
|
-
{
|
|
2261
|
-
type: "button",
|
|
2262
|
-
onClick: () => setSelectedNode(nodeResult),
|
|
2263
|
-
className: "flex w-full items-center justify-between rounded px-2 py-1.5 text-xs hover:bg-gray-50 dark:hover:bg-gray-700/50",
|
|
2264
|
-
children: [
|
|
2265
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2266
|
-
/* @__PURE__ */ jsx(NodeStatusIcon, { className: `h-3 w-3 ${nodeStatusStyle.colorClass}` }),
|
|
2267
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-700 dark:text-gray-300", children: nodeResult.nodeType })
|
|
2268
|
-
] }),
|
|
2269
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400", children: formatDuration3(nodeResult.durationMs) })
|
|
2270
|
-
]
|
|
2271
|
-
},
|
|
2272
|
-
nodeResult.nodeId
|
|
2273
|
-
);
|
|
2274
|
-
})
|
|
2275
|
-
] })
|
|
2276
|
-
] })
|
|
2277
|
-
] })
|
|
2278
|
-
] })
|
|
2279
|
-
] });
|
|
2280
|
-
}
|
|
2281
|
-
function SaveStatusBadge({ status }) {
|
|
2282
|
-
if (status === "saving") {
|
|
2283
|
-
return /* @__PURE__ */ jsx("span", { className: "animate-pulse text-[10px] text-gray-400 dark:text-gray-500", children: "\u2022" });
|
|
2284
|
-
}
|
|
2285
|
-
if (status === "saved") {
|
|
2286
|
-
return /* @__PURE__ */ jsx("span", { className: "text-[10px] text-green-500/60 dark:text-green-400/50", children: "\u2713" });
|
|
2287
|
-
}
|
|
2288
|
-
return null;
|
|
2289
|
-
}
|
|
2290
|
-
var AutoSaveWorkspace = memo(function AutoSaveWorkspace2({
|
|
2291
|
-
onAutoSaveGraph,
|
|
2292
|
-
onGraphSnapshot,
|
|
2293
|
-
...workspaceProps
|
|
2294
|
-
}) {
|
|
2295
|
-
const handleGraphChange = useCallback((graph) => {
|
|
2296
|
-
onGraphSnapshot?.(graph);
|
|
2297
|
-
onAutoSaveGraph(graph);
|
|
2298
|
-
}, [onAutoSaveGraph, onGraphSnapshot]);
|
|
2299
|
-
return /* @__PURE__ */ jsx(
|
|
2300
|
-
Workspace,
|
|
2301
|
-
{
|
|
2302
|
-
...workspaceProps,
|
|
2303
|
-
onGraphChange: handleGraphChange
|
|
2304
|
-
}
|
|
2305
|
-
);
|
|
2306
|
-
});
|
|
2307
|
-
function DynamicIslandConfirm2(props) {
|
|
2308
|
-
return /* @__PURE__ */ jsx(DynamicIslandConfirm, { ...props });
|
|
2309
|
-
}
|
|
2310
|
-
var JSON_PREVIEW_LINE_LIMIT = 50;
|
|
2311
|
-
function DslExportModal({ open, onClose, workflow, graph }) {
|
|
2312
|
-
const translations = useTranslations("agents.workflow.dsl.export");
|
|
2313
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
2314
|
-
const exportPayload = useMemo(() => ({
|
|
2315
|
-
name: workflow.name,
|
|
2316
|
-
description: workflow.description,
|
|
2317
|
-
version: workflow.version,
|
|
2318
|
-
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2319
|
-
graph: {
|
|
2320
|
-
nodes: graph.nodes,
|
|
2321
|
-
edges: graph.edges,
|
|
2322
|
-
viewport: graph.viewport
|
|
2323
|
-
}
|
|
2324
|
-
}), [workflow, graph]);
|
|
2325
|
-
const jsonString = useMemo(() => JSON.stringify(exportPayload, null, 2), [exportPayload]);
|
|
2326
|
-
const previewLines = useMemo(() => {
|
|
2327
|
-
const lines = jsonString.split("\n");
|
|
2328
|
-
if (lines.length <= JSON_PREVIEW_LINE_LIMIT) {
|
|
2329
|
-
return jsonString;
|
|
2330
|
-
}
|
|
2331
|
-
return lines.slice(0, JSON_PREVIEW_LINE_LIMIT).join("\n") + "\n...";
|
|
2332
|
-
}, [jsonString]);
|
|
2333
|
-
const handleCopyToClipboard = useCallback(async () => {
|
|
2334
|
-
try {
|
|
2335
|
-
await navigator.clipboard.writeText(jsonString);
|
|
2336
|
-
setIsCopied(true);
|
|
2337
|
-
setTimeout(() => setIsCopied(false), 2e3);
|
|
2338
|
-
} catch {
|
|
2339
|
-
const textArea = document.createElement("textarea");
|
|
2340
|
-
textArea.value = jsonString;
|
|
2341
|
-
document.body.appendChild(textArea);
|
|
2342
|
-
textArea.select();
|
|
2343
|
-
document.execCommand("copy");
|
|
2344
|
-
document.body.removeChild(textArea);
|
|
2345
|
-
setIsCopied(true);
|
|
2346
|
-
setTimeout(() => setIsCopied(false), 2e3);
|
|
2347
|
-
}
|
|
2348
|
-
}, [jsonString]);
|
|
2349
|
-
const handleDownloadJson = useCallback(() => {
|
|
2350
|
-
const blob = new Blob([jsonString], { type: "application/json" });
|
|
2351
|
-
const url = URL.createObjectURL(blob);
|
|
2352
|
-
const downloadLink = document.createElement("a");
|
|
2353
|
-
downloadLink.href = url;
|
|
2354
|
-
downloadLink.download = `${workflow.name}-v${workflow.version}.json`;
|
|
2355
|
-
document.body.appendChild(downloadLink);
|
|
2356
|
-
downloadLink.click();
|
|
2357
|
-
document.body.removeChild(downloadLink);
|
|
2358
|
-
URL.revokeObjectURL(url);
|
|
2359
|
-
}, [jsonString, workflow.name, workflow.version]);
|
|
2360
|
-
if (!open) return null;
|
|
2361
|
-
return /* @__PURE__ */ jsx(
|
|
2362
|
-
GlassFormModal,
|
|
2363
|
-
{
|
|
2364
|
-
open,
|
|
2365
|
-
onClose,
|
|
2366
|
-
title: translations("title"),
|
|
2367
|
-
subtitle: translations("description"),
|
|
2368
|
-
maxWidth: "2xl",
|
|
2369
|
-
showFooter: false,
|
|
2370
|
-
children: /* @__PURE__ */ jsxs("div", { "data-testid": "dsl-export-modal", children: [
|
|
2371
|
-
/* @__PURE__ */ jsx("div", { className: "border-b border-gray-200 px-1 py-4 dark:border-gray-700", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4 text-sm", children: [
|
|
2372
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2373
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-500 dark:text-gray-400", children: translations("workflowName") }),
|
|
2374
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium text-gray-900 dark:text-white", children: workflow.name })
|
|
2375
|
-
] }),
|
|
2376
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2377
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-500 dark:text-gray-400", children: translations("version") }),
|
|
2378
|
-
/* @__PURE__ */ jsxs("p", { className: "font-medium text-gray-900 dark:text-white", children: [
|
|
2379
|
-
"v",
|
|
2380
|
-
workflow.version
|
|
2381
|
-
] })
|
|
2382
|
-
] }),
|
|
2383
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2384
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-500 dark:text-gray-400", children: translations("nodes") }),
|
|
2385
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium text-gray-900 dark:text-white", children: graph.nodes.length })
|
|
2386
|
-
] }),
|
|
2387
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2388
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-500 dark:text-gray-400", children: translations("edges") }),
|
|
2389
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium text-gray-900 dark:text-white", children: graph.edges.length })
|
|
2390
|
-
] })
|
|
2391
|
-
] }) }),
|
|
2392
|
-
/* @__PURE__ */ jsxs("div", { className: "px-1 py-4", children: [
|
|
2393
|
-
/* @__PURE__ */ jsx("div", { className: "mb-2 text-xs font-medium uppercase tracking-wider text-gray-400 dark:text-gray-500", children: translations("preview") }),
|
|
2394
|
-
/* @__PURE__ */ jsx(
|
|
2395
|
-
"pre",
|
|
2396
|
-
{
|
|
2397
|
-
className: "max-h-64 overflow-auto rounded-lg border border-gray-200 bg-gray-50 p-3 text-xs text-gray-700 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300",
|
|
2398
|
-
"data-testid": "export-json-preview",
|
|
2399
|
-
children: previewLines
|
|
2400
|
-
}
|
|
2401
|
-
)
|
|
2402
|
-
] }),
|
|
2403
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-3 border-t border-gray-200 px-1 py-4 dark:border-gray-700", children: [
|
|
2404
|
-
/* @__PURE__ */ jsx(
|
|
2405
|
-
Button,
|
|
2406
|
-
{
|
|
2407
|
-
type: "button",
|
|
2408
|
-
onClick: handleCopyToClipboard,
|
|
2409
|
-
outline: true,
|
|
2410
|
-
size: "sm",
|
|
2411
|
-
"data-testid": "export-copy-button",
|
|
2412
|
-
children: isCopied ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2413
|
-
/* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4 text-green-500" }),
|
|
2414
|
-
translations("copied")
|
|
2415
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2416
|
-
/* @__PURE__ */ jsx(ClipboardDocumentIcon, { className: "h-4 w-4" }),
|
|
2417
|
-
translations("copyToClipboard")
|
|
2418
|
-
] })
|
|
2419
|
-
}
|
|
2420
|
-
),
|
|
2421
|
-
/* @__PURE__ */ jsxs(
|
|
2422
|
-
Button,
|
|
2423
|
-
{
|
|
2424
|
-
type: "button",
|
|
2425
|
-
onClick: handleDownloadJson,
|
|
2426
|
-
color: "ios-glass-blue",
|
|
2427
|
-
size: "sm",
|
|
2428
|
-
"data-testid": "export-download-button",
|
|
2429
|
-
children: [
|
|
2430
|
-
/* @__PURE__ */ jsx(ArrowDownTrayIcon, { className: "h-4 w-4" }),
|
|
2431
|
-
translations("downloadJson")
|
|
2432
|
-
]
|
|
2433
|
-
}
|
|
2434
|
-
)
|
|
2435
|
-
] })
|
|
2436
|
-
] })
|
|
2437
|
-
}
|
|
2438
|
-
);
|
|
2439
|
-
}
|
|
2440
|
-
function validateWorkflowJson(jsonString) {
|
|
2441
|
-
const errors = [];
|
|
2442
|
-
let parsed;
|
|
2443
|
-
try {
|
|
2444
|
-
parsed = JSON.parse(jsonString);
|
|
2445
|
-
} catch {
|
|
2446
|
-
return { isValid: false, errors: ["Invalid JSON format"], graph: null, nodeCount: 0, edgeCount: 0 };
|
|
2447
|
-
}
|
|
2448
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
2449
|
-
return { isValid: false, errors: ["Root must be a JSON object"], graph: null, nodeCount: 0, edgeCount: 0 };
|
|
2450
|
-
}
|
|
2451
|
-
const data = parsed;
|
|
2452
|
-
const graphData = data.graph ? data.graph : data;
|
|
2453
|
-
if (!Array.isArray(graphData.nodes)) {
|
|
2454
|
-
errors.push('Missing or invalid "nodes" array');
|
|
2455
|
-
}
|
|
2456
|
-
if (!Array.isArray(graphData.edges)) {
|
|
2457
|
-
errors.push('Missing or invalid "edges" array');
|
|
2458
|
-
}
|
|
2459
|
-
if (!graphData.viewport || typeof graphData.viewport !== "object") {
|
|
2460
|
-
errors.push('Missing or invalid "viewport" object');
|
|
2461
|
-
}
|
|
2462
|
-
if (errors.length > 0) {
|
|
2463
|
-
return { isValid: false, errors, graph: null, nodeCount: 0, edgeCount: 0 };
|
|
2464
|
-
}
|
|
2465
|
-
const nodes = graphData.nodes;
|
|
2466
|
-
const edges = graphData.edges;
|
|
2467
|
-
for (let index = 0; index < nodes.length; index++) {
|
|
2468
|
-
const node = nodes[index];
|
|
2469
|
-
if (!node.id || typeof node.id !== "string") {
|
|
2470
|
-
errors.push(`Node at index ${index}: missing or invalid "id"`);
|
|
2471
|
-
}
|
|
2472
|
-
if (!node.type || typeof node.type !== "string") {
|
|
2473
|
-
errors.push(`Node at index ${index}: missing or invalid "type"`);
|
|
2474
|
-
}
|
|
2475
|
-
if (!node.position || typeof node.position !== "object") {
|
|
2476
|
-
errors.push(`Node at index ${index}: missing or invalid "position"`);
|
|
2477
|
-
}
|
|
2478
|
-
}
|
|
2479
|
-
for (let index = 0; index < edges.length; index++) {
|
|
2480
|
-
const edge = edges[index];
|
|
2481
|
-
if (!edge.id || typeof edge.id !== "string") {
|
|
2482
|
-
errors.push(`Edge at index ${index}: missing or invalid "id"`);
|
|
2483
|
-
}
|
|
2484
|
-
if (!edge.source || typeof edge.source !== "string") {
|
|
2485
|
-
errors.push(`Edge at index ${index}: missing or invalid "source"`);
|
|
2486
|
-
}
|
|
2487
|
-
if (!edge.target || typeof edge.target !== "string") {
|
|
2488
|
-
errors.push(`Edge at index ${index}: missing or invalid "target"`);
|
|
2489
|
-
}
|
|
2490
|
-
}
|
|
2491
|
-
if (errors.length > 0) {
|
|
2492
|
-
return { isValid: false, errors, graph: null, nodeCount: nodes.length, edgeCount: edges.length };
|
|
2493
|
-
}
|
|
2494
|
-
const viewport = graphData.viewport;
|
|
2495
|
-
const graph = {
|
|
2496
|
-
nodes: nodes.map((node) => ({
|
|
2497
|
-
id: node.id,
|
|
2498
|
-
type: node.type,
|
|
2499
|
-
position: node.position,
|
|
2500
|
-
data: node.data ?? { entityId: "", label: "" }
|
|
2501
|
-
})),
|
|
2502
|
-
edges: edges.map((edge) => ({
|
|
2503
|
-
id: edge.id,
|
|
2504
|
-
source: edge.source,
|
|
2505
|
-
target: edge.target,
|
|
2506
|
-
sourceHandle: edge.sourceHandle ?? "default",
|
|
2507
|
-
targetHandle: edge.targetHandle ?? "default"
|
|
2508
|
-
})),
|
|
2509
|
-
viewport: {
|
|
2510
|
-
x: typeof viewport.x === "number" ? viewport.x : 0,
|
|
2511
|
-
y: typeof viewport.y === "number" ? viewport.y : 0,
|
|
2512
|
-
zoom: typeof viewport.zoom === "number" ? viewport.zoom : 1
|
|
2513
|
-
}
|
|
2514
|
-
};
|
|
2515
|
-
return { isValid: true, errors: [], graph, nodeCount: nodes.length, edgeCount: edges.length };
|
|
2516
|
-
}
|
|
2517
|
-
function DslImportModal({ open, onClose, onImport }) {
|
|
2518
|
-
const translations = useTranslations("agents.workflow.dsl.import");
|
|
2519
|
-
const fileInputRef = useRef(null);
|
|
2520
|
-
const [isDragActive, setIsDragActive] = useState(false);
|
|
2521
|
-
const [validationResult, setValidationResult] = useState(null);
|
|
2522
|
-
const [fileName, setFileName] = useState(null);
|
|
2523
|
-
const processFile = useCallback((file) => {
|
|
2524
|
-
setFileName(file.name);
|
|
2525
|
-
const reader = new FileReader();
|
|
2526
|
-
reader.onload = (event) => {
|
|
2527
|
-
const content = event.target?.result;
|
|
2528
|
-
if (typeof content === "string") {
|
|
2529
|
-
const result = validateWorkflowJson(content);
|
|
2530
|
-
setValidationResult(result);
|
|
2531
|
-
}
|
|
2532
|
-
};
|
|
2533
|
-
reader.readAsText(file);
|
|
2534
|
-
}, []);
|
|
2535
|
-
const handleDragOver = useCallback((event) => {
|
|
2536
|
-
event.preventDefault();
|
|
2537
|
-
setIsDragActive(true);
|
|
2538
|
-
}, []);
|
|
2539
|
-
const handleDragLeave = useCallback((event) => {
|
|
2540
|
-
event.preventDefault();
|
|
2541
|
-
setIsDragActive(false);
|
|
2542
|
-
}, []);
|
|
2543
|
-
const handleDrop = useCallback(
|
|
2544
|
-
(event) => {
|
|
2545
|
-
event.preventDefault();
|
|
2546
|
-
setIsDragActive(false);
|
|
2547
|
-
const files = event.dataTransfer.files;
|
|
2548
|
-
if (files.length > 0) {
|
|
2549
|
-
processFile(files[0]);
|
|
2550
|
-
}
|
|
2551
|
-
},
|
|
2552
|
-
[processFile]
|
|
2553
|
-
);
|
|
2554
|
-
const handleFileChange = useCallback(
|
|
2555
|
-
(event) => {
|
|
2556
|
-
const files = event.target.files;
|
|
2557
|
-
if (files && files.length > 0) {
|
|
2558
|
-
processFile(files[0]);
|
|
2559
|
-
}
|
|
2560
|
-
},
|
|
2561
|
-
[processFile]
|
|
2562
|
-
);
|
|
2563
|
-
const handleClickUpload = useCallback(() => {
|
|
2564
|
-
fileInputRef.current?.click();
|
|
2565
|
-
}, []);
|
|
2566
|
-
const handleImport = useCallback(() => {
|
|
2567
|
-
if (validationResult?.isValid && validationResult.graph) {
|
|
2568
|
-
onImport(validationResult.graph);
|
|
2569
|
-
onClose();
|
|
2570
|
-
}
|
|
2571
|
-
}, [validationResult, onImport, onClose]);
|
|
2572
|
-
const handleReset = useCallback(() => {
|
|
2573
|
-
setValidationResult(null);
|
|
2574
|
-
setFileName(null);
|
|
2575
|
-
if (fileInputRef.current) {
|
|
2576
|
-
fileInputRef.current.value = "";
|
|
2577
|
-
}
|
|
2578
|
-
}, []);
|
|
2579
|
-
if (!open) return null;
|
|
2580
|
-
return /* @__PURE__ */ jsx(
|
|
2581
|
-
GlassFormModal,
|
|
2582
|
-
{
|
|
2583
|
-
open,
|
|
2584
|
-
onClose,
|
|
2585
|
-
title: translations("title"),
|
|
2586
|
-
subtitle: translations("description"),
|
|
2587
|
-
maxWidth: "lg",
|
|
2588
|
-
showFooter: false,
|
|
2589
|
-
children: /* @__PURE__ */ jsxs("div", { "data-testid": "dsl-import-modal", children: [
|
|
2590
|
-
/* @__PURE__ */ jsx("div", { className: "px-1 py-2", children: !validationResult ? /* @__PURE__ */ jsxs(
|
|
2591
|
-
"div",
|
|
2592
|
-
{
|
|
2593
|
-
onDragOver: handleDragOver,
|
|
2594
|
-
onDragLeave: handleDragLeave,
|
|
2595
|
-
onDrop: handleDrop,
|
|
2596
|
-
onClick: handleClickUpload,
|
|
2597
|
-
className: `cursor-pointer rounded-xl border-2 border-dashed p-8 text-center transition-colors duration-200 ${isDragActive ? "border-blue-400 bg-blue-50 dark:border-blue-500 dark:bg-blue-500/10" : "border-gray-300 hover:border-gray-400 dark:border-gray-600 dark:hover:border-gray-500"}`,
|
|
2598
|
-
"data-testid": "import-dropzone",
|
|
2599
|
-
children: [
|
|
2600
|
-
/* @__PURE__ */ jsx(ArrowUpTrayIcon, { className: "mx-auto h-10 w-10 text-gray-400 dark:text-gray-500" }),
|
|
2601
|
-
/* @__PURE__ */ jsx("p", { className: "mt-3 text-sm font-medium text-gray-700 dark:text-gray-300", children: translations("dropzone") }),
|
|
2602
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-gray-500 dark:text-gray-400", children: translations("dropzoneHint") }),
|
|
2603
|
-
/* @__PURE__ */ jsx(
|
|
2604
|
-
"input",
|
|
2605
|
-
{
|
|
2606
|
-
ref: fileInputRef,
|
|
2607
|
-
type: "file",
|
|
2608
|
-
accept: ".json",
|
|
2609
|
-
onChange: handleFileChange,
|
|
2610
|
-
className: "hidden",
|
|
2611
|
-
"data-testid": "import-file-input"
|
|
2612
|
-
}
|
|
2613
|
-
)
|
|
2614
|
-
]
|
|
2615
|
-
}
|
|
2616
|
-
) : /* @__PURE__ */ jsxs("div", { "data-testid": "import-validation-result", children: [
|
|
2617
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center justify-between", children: [
|
|
2618
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: fileName }),
|
|
2619
|
-
/* @__PURE__ */ jsx(Button, { type: "button", plain: true, size: "sm", onClick: handleReset, children: translations("chooseAnother") })
|
|
2620
|
-
] }),
|
|
2621
|
-
validationResult.isValid ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-green-200 bg-green-50 p-4 dark:border-green-800 dark:bg-green-900/20", children: [
|
|
2622
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2623
|
-
/* @__PURE__ */ jsx(CheckCircleIcon, { className: "h-5 w-5 text-green-500" }),
|
|
2624
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-green-700 dark:text-green-400", children: translations("validationSuccess") })
|
|
2625
|
-
] }),
|
|
2626
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 grid grid-cols-2 gap-2 text-sm", children: [
|
|
2627
|
-
/* @__PURE__ */ jsxs("div", { className: "text-green-600 dark:text-green-400", children: [
|
|
2628
|
-
translations("nodes"),
|
|
2629
|
-
": ",
|
|
2630
|
-
validationResult.nodeCount
|
|
2631
|
-
] }),
|
|
2632
|
-
/* @__PURE__ */ jsxs("div", { className: "text-green-600 dark:text-green-400", children: [
|
|
2633
|
-
translations("edges"),
|
|
2634
|
-
": ",
|
|
2635
|
-
validationResult.edgeCount
|
|
2636
|
-
] })
|
|
2637
|
-
] })
|
|
2638
|
-
] }) : /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-red-200 bg-red-50 p-4 dark:border-red-800 dark:bg-red-900/20", children: [
|
|
2639
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2640
|
-
/* @__PURE__ */ jsx(ExclamationTriangleIcon, { className: "h-5 w-5 text-red-500" }),
|
|
2641
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-red-700 dark:text-red-400", children: translations("validationFailed") })
|
|
2642
|
-
] }),
|
|
2643
|
-
/* @__PURE__ */ jsx("ul", { className: "mt-2 space-y-1", children: validationResult.errors.map((validationError, index) => /* @__PURE__ */ jsx("li", { className: "text-xs text-red-600 dark:text-red-400", children: validationError }, index)) })
|
|
2644
|
-
] })
|
|
2645
|
-
] }) }),
|
|
2646
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-3 border-t border-gray-200 px-1 py-4 dark:border-gray-700", children: [
|
|
2647
|
-
/* @__PURE__ */ jsx(Button, { type: "button", onClick: onClose, outline: true, size: "sm", "data-testid": "import-cancel-button", children: translations("cancel") }),
|
|
2648
|
-
/* @__PURE__ */ jsxs(
|
|
2649
|
-
Button,
|
|
2650
|
-
{
|
|
2651
|
-
type: "button",
|
|
2652
|
-
onClick: handleImport,
|
|
2653
|
-
disabled: !validationResult?.isValid,
|
|
2654
|
-
color: "ios-glass-blue",
|
|
2655
|
-
size: "sm",
|
|
2656
|
-
"data-testid": "import-confirm-button",
|
|
2657
|
-
children: [
|
|
2658
|
-
/* @__PURE__ */ jsx(ArrowUpTrayIcon, { className: "h-4 w-4" }),
|
|
2659
|
-
translations("import")
|
|
2660
|
-
]
|
|
2661
|
-
}
|
|
2662
|
-
)
|
|
2663
|
-
] })
|
|
2664
|
-
] })
|
|
2665
|
-
}
|
|
2666
|
-
);
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
// src/astrlabe/store/selectors.ts
|
|
2670
|
-
var useCanUndo = () => useWorkflowStore((state) => state.past.length > 0);
|
|
2671
|
-
var useCanRedo = () => useWorkflowStore((state) => state.future.length > 0);
|
|
2672
|
-
var useHasCopied = () => useWorkflowStore((state) => state.clipboard !== null);
|
|
2673
|
-
var useContextMenu = () => useWorkflowStore((state) => state.contextMenu);
|
|
2674
|
-
var useEditingNodeId = () => useWorkflowStore((state) => state.editingNodeId);
|
|
2675
|
-
var useSelectedNodeCount = () => useWorkflowStore((state) => state.nodes.filter((node) => node.selected).length);
|
|
2676
|
-
var useIsRunning = () => useWorkflowStore((state) => state.isRunning);
|
|
2677
|
-
var useNodeResults = () => useWorkflowStore((state) => state.nodeResults);
|
|
2678
|
-
var DEFAULT_MAX_HISTORY = 50;
|
|
2679
|
-
function useUndoRedo(nodes, edges, setNodes, setEdges, maxHistory = DEFAULT_MAX_HISTORY) {
|
|
2680
|
-
const pastRef = useRef([]);
|
|
2681
|
-
const futureRef = useRef([]);
|
|
2682
|
-
const pastLengthRef = useRef(0);
|
|
2683
|
-
const futureLengthRef = useRef(0);
|
|
2684
|
-
const takeSnapshot = useCallback(() => {
|
|
2685
|
-
const snapshot = {
|
|
2686
|
-
nodes: nodes.map((node) => ({ ...node, data: { ...node.data } })),
|
|
2687
|
-
edges: edges.map((edge) => ({ ...edge }))
|
|
2688
|
-
};
|
|
2689
|
-
pastRef.current = [...pastRef.current.slice(-(maxHistory - 1)), snapshot];
|
|
2690
|
-
pastLengthRef.current = pastRef.current.length;
|
|
2691
|
-
futureRef.current = [];
|
|
2692
|
-
futureLengthRef.current = 0;
|
|
2693
|
-
}, [nodes, edges, maxHistory]);
|
|
2694
|
-
const undo = useCallback(() => {
|
|
2695
|
-
const past = pastRef.current;
|
|
2696
|
-
if (past.length === 0) return;
|
|
2697
|
-
const previous = past[past.length - 1];
|
|
2698
|
-
const remaining = past.slice(0, -1);
|
|
2699
|
-
const currentSnapshot = {
|
|
2700
|
-
nodes: nodes.map((node) => ({ ...node, data: { ...node.data } })),
|
|
2701
|
-
edges: edges.map((edge) => ({ ...edge }))
|
|
2702
|
-
};
|
|
2703
|
-
pastRef.current = remaining;
|
|
2704
|
-
pastLengthRef.current = remaining.length;
|
|
2705
|
-
futureRef.current = [...futureRef.current, currentSnapshot];
|
|
2706
|
-
futureLengthRef.current = futureRef.current.length;
|
|
2707
|
-
setNodes(previous.nodes);
|
|
2708
|
-
setEdges(previous.edges);
|
|
2709
|
-
}, [nodes, edges, setNodes, setEdges]);
|
|
2710
|
-
const redo = useCallback(() => {
|
|
2711
|
-
const future = futureRef.current;
|
|
2712
|
-
if (future.length === 0) return;
|
|
2713
|
-
const next = future[future.length - 1];
|
|
2714
|
-
const remaining = future.slice(0, -1);
|
|
2715
|
-
const currentSnapshot = {
|
|
2716
|
-
nodes: nodes.map((node) => ({ ...node, data: { ...node.data } })),
|
|
2717
|
-
edges: edges.map((edge) => ({ ...edge }))
|
|
2718
|
-
};
|
|
2719
|
-
futureRef.current = remaining;
|
|
2720
|
-
futureLengthRef.current = remaining.length;
|
|
2721
|
-
pastRef.current = [...pastRef.current, currentSnapshot];
|
|
2722
|
-
pastLengthRef.current = pastRef.current.length;
|
|
2723
|
-
setNodes(next.nodes);
|
|
2724
|
-
setEdges(next.edges);
|
|
2725
|
-
}, [nodes, edges, setNodes, setEdges]);
|
|
2726
|
-
return {
|
|
2727
|
-
undo,
|
|
2728
|
-
redo,
|
|
2729
|
-
canUndo: pastRef.current.length > 0,
|
|
2730
|
-
canRedo: futureRef.current.length > 0,
|
|
2731
|
-
takeSnapshot
|
|
2732
|
-
};
|
|
2733
|
-
}
|
|
2734
|
-
var PASTE_OFFSET = 40;
|
|
2735
|
-
function useClipboard(nodes, edges, setNodes, setEdges, takeSnapshot) {
|
|
2736
|
-
const clipboardRef = useRef(null);
|
|
2737
|
-
const copy = useCallback(() => {
|
|
2738
|
-
const selectedNodes = nodes.filter((node) => node.selected);
|
|
2739
|
-
if (selectedNodes.length === 0) return;
|
|
2740
|
-
const selectedNodeIds = new Set(selectedNodes.map((node) => node.id));
|
|
2741
|
-
const internalEdges = edges.filter(
|
|
2742
|
-
(edge) => selectedNodeIds.has(edge.source) && selectedNodeIds.has(edge.target)
|
|
2743
|
-
);
|
|
2744
|
-
clipboardRef.current = {
|
|
2745
|
-
nodes: selectedNodes.map((node) => ({ ...node, data: { ...node.data } })),
|
|
2746
|
-
edges: internalEdges.map((edge) => ({ ...edge }))
|
|
2747
|
-
};
|
|
2748
|
-
}, [nodes, edges]);
|
|
2749
|
-
const paste = useCallback(() => {
|
|
2750
|
-
const clipboard = clipboardRef.current;
|
|
2751
|
-
if (!clipboard || clipboard.nodes.length === 0) return;
|
|
2752
|
-
takeSnapshot();
|
|
2753
|
-
const idMapping = /* @__PURE__ */ new Map();
|
|
2754
|
-
clipboard.nodes.forEach((node) => {
|
|
2755
|
-
idMapping.set(node.id, crypto.randomUUID());
|
|
2756
|
-
});
|
|
2757
|
-
const pastedNodes = clipboard.nodes.map((node) => ({
|
|
2758
|
-
...node,
|
|
2759
|
-
id: idMapping.get(node.id) ?? crypto.randomUUID(),
|
|
2760
|
-
position: {
|
|
2761
|
-
x: node.position.x + PASTE_OFFSET,
|
|
2762
|
-
y: node.position.y + PASTE_OFFSET
|
|
2763
|
-
},
|
|
2764
|
-
selected: true,
|
|
2765
|
-
data: { ...node.data }
|
|
2766
|
-
}));
|
|
2767
|
-
const pastedEdges = clipboard.edges.map((edge) => ({
|
|
2768
|
-
...edge,
|
|
2769
|
-
id: crypto.randomUUID(),
|
|
2770
|
-
source: idMapping.get(edge.source) ?? edge.source,
|
|
2771
|
-
target: idMapping.get(edge.target) ?? edge.target
|
|
2772
|
-
}));
|
|
2773
|
-
setNodes((currentNodes) => [
|
|
2774
|
-
...currentNodes.map((node) => ({ ...node, selected: false })),
|
|
2775
|
-
...pastedNodes
|
|
2776
|
-
]);
|
|
2777
|
-
setEdges((currentEdges) => [...currentEdges, ...pastedEdges]);
|
|
2778
|
-
clipboardRef.current = {
|
|
2779
|
-
nodes: pastedNodes.map((node) => ({ ...node, data: { ...node.data } })),
|
|
2780
|
-
edges: pastedEdges.map((edge) => ({ ...edge }))
|
|
2781
|
-
};
|
|
2782
|
-
}, [setNodes, setEdges, takeSnapshot]);
|
|
2783
|
-
return {
|
|
2784
|
-
copy,
|
|
2785
|
-
paste,
|
|
2786
|
-
hasCopied: clipboardRef.current !== null && clipboardRef.current.nodes.length > 0
|
|
2787
|
-
};
|
|
2788
|
-
}
|
|
2789
|
-
var INPUT_TAGS = /* @__PURE__ */ new Set(["INPUT", "TEXTAREA", "SELECT"]);
|
|
2790
|
-
function isInputFocused() {
|
|
2791
|
-
const activeElement = document.activeElement;
|
|
2792
|
-
if (!activeElement) return false;
|
|
2793
|
-
return INPUT_TAGS.has(activeElement.tagName) || activeElement.isContentEditable;
|
|
2794
|
-
}
|
|
2795
|
-
function useCanvasShortcuts({
|
|
2796
|
-
undo,
|
|
2797
|
-
redo,
|
|
2798
|
-
copy,
|
|
2799
|
-
paste,
|
|
2800
|
-
canUndo,
|
|
2801
|
-
canRedo,
|
|
2802
|
-
selectAll,
|
|
2803
|
-
fitView
|
|
2804
|
-
}) {
|
|
2805
|
-
useEffect(() => {
|
|
2806
|
-
function handleKeyDown(event) {
|
|
2807
|
-
if (isInputFocused()) return;
|
|
2808
|
-
const isModifierPressed = event.metaKey || event.ctrlKey;
|
|
2809
|
-
if (!isModifierPressed) {
|
|
2810
|
-
if (event.key === "Escape") {
|
|
2811
|
-
selectAll();
|
|
2812
|
-
return;
|
|
2813
|
-
}
|
|
2814
|
-
return;
|
|
2815
|
-
}
|
|
2816
|
-
switch (event.key.toLowerCase()) {
|
|
2817
|
-
case "z": {
|
|
2818
|
-
if (event.shiftKey) {
|
|
2819
|
-
if (canRedo) {
|
|
2820
|
-
event.preventDefault();
|
|
2821
|
-
redo();
|
|
2822
|
-
}
|
|
2823
|
-
} else {
|
|
2824
|
-
if (canUndo) {
|
|
2825
|
-
event.preventDefault();
|
|
2826
|
-
undo();
|
|
2827
|
-
}
|
|
2828
|
-
}
|
|
2829
|
-
break;
|
|
2830
|
-
}
|
|
2831
|
-
case "y": {
|
|
2832
|
-
if (canRedo) {
|
|
2833
|
-
event.preventDefault();
|
|
2834
|
-
redo();
|
|
2835
|
-
}
|
|
2836
|
-
break;
|
|
2837
|
-
}
|
|
2838
|
-
case "c": {
|
|
2839
|
-
event.preventDefault();
|
|
2840
|
-
copy();
|
|
2841
|
-
break;
|
|
2842
|
-
}
|
|
2843
|
-
case "v": {
|
|
2844
|
-
event.preventDefault();
|
|
2845
|
-
paste();
|
|
2846
|
-
break;
|
|
2847
|
-
}
|
|
2848
|
-
case "a": {
|
|
2849
|
-
event.preventDefault();
|
|
2850
|
-
selectAll();
|
|
2851
|
-
break;
|
|
2852
|
-
}
|
|
2853
|
-
case "f": {
|
|
2854
|
-
if (event.shiftKey) {
|
|
2855
|
-
event.preventDefault();
|
|
2856
|
-
fitView();
|
|
2857
|
-
}
|
|
2858
|
-
break;
|
|
2859
|
-
}
|
|
2860
|
-
}
|
|
2861
|
-
}
|
|
2862
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
2863
|
-
return () => {
|
|
2864
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
2865
|
-
};
|
|
2866
|
-
}, [undo, redo, copy, paste, canUndo, canRedo, selectAll, fitView]);
|
|
2867
|
-
}
|
|
2868
|
-
var ALIGNMENT_THRESHOLD = 5;
|
|
2869
|
-
var DEFAULT_NODE_WIDTH = 200;
|
|
2870
|
-
var DEFAULT_NODE_HEIGHT = 60;
|
|
2871
|
-
function getNodeBounds(node) {
|
|
2872
|
-
const width = node.measured?.width ?? node.width ?? DEFAULT_NODE_WIDTH;
|
|
2873
|
-
const height = node.measured?.height ?? node.height ?? DEFAULT_NODE_HEIGHT;
|
|
2874
|
-
return {
|
|
2875
|
-
left: node.position.x,
|
|
2876
|
-
centerX: node.position.x + width / 2,
|
|
2877
|
-
right: node.position.x + width,
|
|
2878
|
-
top: node.position.y,
|
|
2879
|
-
centerY: node.position.y + height / 2,
|
|
2880
|
-
bottom: node.position.y + height
|
|
2881
|
-
};
|
|
2882
|
-
}
|
|
2883
|
-
function findAlignments(dragBounds, otherNodes) {
|
|
2884
|
-
let closestHorizontal = null;
|
|
2885
|
-
let closestVertical = null;
|
|
2886
|
-
let minHorizontalDistance = ALIGNMENT_THRESHOLD + 1;
|
|
2887
|
-
let minVerticalDistance = ALIGNMENT_THRESHOLD + 1;
|
|
2888
|
-
for (const otherNode of otherNodes) {
|
|
2889
|
-
const otherBounds = getNodeBounds(otherNode);
|
|
2890
|
-
const verticalChecks = [
|
|
2891
|
-
{ dragValue: dragBounds.left, otherValue: otherBounds.left },
|
|
2892
|
-
{ dragValue: dragBounds.left, otherValue: otherBounds.centerX },
|
|
2893
|
-
{ dragValue: dragBounds.left, otherValue: otherBounds.right },
|
|
2894
|
-
{ dragValue: dragBounds.centerX, otherValue: otherBounds.left },
|
|
2895
|
-
{ dragValue: dragBounds.centerX, otherValue: otherBounds.centerX },
|
|
2896
|
-
{ dragValue: dragBounds.centerX, otherValue: otherBounds.right },
|
|
2897
|
-
{ dragValue: dragBounds.right, otherValue: otherBounds.left },
|
|
2898
|
-
{ dragValue: dragBounds.right, otherValue: otherBounds.centerX },
|
|
2899
|
-
{ dragValue: dragBounds.right, otherValue: otherBounds.right }
|
|
2900
|
-
];
|
|
2901
|
-
for (const check of verticalChecks) {
|
|
2902
|
-
const distance = Math.abs(check.dragValue - check.otherValue);
|
|
2903
|
-
if (distance <= ALIGNMENT_THRESHOLD && distance < minVerticalDistance) {
|
|
2904
|
-
minVerticalDistance = distance;
|
|
2905
|
-
closestVertical = check.otherValue;
|
|
2906
|
-
}
|
|
2907
|
-
}
|
|
2908
|
-
const horizontalChecks = [
|
|
2909
|
-
{ dragValue: dragBounds.top, otherValue: otherBounds.top },
|
|
2910
|
-
{ dragValue: dragBounds.top, otherValue: otherBounds.centerY },
|
|
2911
|
-
{ dragValue: dragBounds.top, otherValue: otherBounds.bottom },
|
|
2912
|
-
{ dragValue: dragBounds.centerY, otherValue: otherBounds.top },
|
|
2913
|
-
{ dragValue: dragBounds.centerY, otherValue: otherBounds.centerY },
|
|
2914
|
-
{ dragValue: dragBounds.centerY, otherValue: otherBounds.bottom },
|
|
2915
|
-
{ dragValue: dragBounds.bottom, otherValue: otherBounds.top },
|
|
2916
|
-
{ dragValue: dragBounds.bottom, otherValue: otherBounds.centerY },
|
|
2917
|
-
{ dragValue: dragBounds.bottom, otherValue: otherBounds.bottom }
|
|
2918
|
-
];
|
|
2919
|
-
for (const check of horizontalChecks) {
|
|
2920
|
-
const distance = Math.abs(check.dragValue - check.otherValue);
|
|
2921
|
-
if (distance <= ALIGNMENT_THRESHOLD && distance < minHorizontalDistance) {
|
|
2922
|
-
minHorizontalDistance = distance;
|
|
2923
|
-
closestHorizontal = check.otherValue;
|
|
2924
|
-
}
|
|
2925
|
-
}
|
|
2926
|
-
}
|
|
2927
|
-
return { horizontal: closestHorizontal, vertical: closestVertical };
|
|
2928
|
-
}
|
|
2929
|
-
function useHelpLines() {
|
|
2930
|
-
const [helpLines, setHelpLines] = useState({
|
|
2931
|
-
horizontal: null,
|
|
2932
|
-
vertical: null
|
|
2933
|
-
});
|
|
2934
|
-
const createDragHandler = useCallback(
|
|
2935
|
-
(allNodes) => (_event, draggedNode, draggedNodes) => {
|
|
2936
|
-
const draggingNodeIds = new Set(
|
|
2937
|
-
draggedNodes.length > 0 ? draggedNodes.map((node) => node.id) : [draggedNode.id]
|
|
2938
|
-
);
|
|
2939
|
-
const dragBounds = getNodeBounds(draggedNode);
|
|
2940
|
-
const otherNodes = allNodes.filter((node) => !draggingNodeIds.has(node.id));
|
|
2941
|
-
setHelpLines(findAlignments(dragBounds, otherNodes));
|
|
2942
|
-
},
|
|
2943
|
-
[]
|
|
2944
|
-
);
|
|
2945
|
-
const onNodeDragStop = useCallback(() => {
|
|
2946
|
-
setHelpLines({ horizontal: null, vertical: null });
|
|
2947
|
-
}, []);
|
|
2948
|
-
return {
|
|
2949
|
-
helpLines,
|
|
2950
|
-
createDragHandler,
|
|
2951
|
-
onNodeDragStop
|
|
2952
|
-
};
|
|
2953
|
-
}
|
|
2954
|
-
|
|
2955
|
-
export { AgentDrawer, AmazonNovaIcon, AnthropicModelIcon, AutoSaveWorkspace, DslExportModal, DslImportModal, DynamicIslandConfirm2 as DynamicIslandConfirm, MetaLlamaIcon, NodePalette, PipelineSettingsDrawer, PreviewPanel, RunInputDialog, RunPanel, SaveStatusBadge, SubworkflowDrawer, VariableInspector, VersionHistoryPanel, WorkflowListBar, getModelIcon, useCanRedo, useCanUndo, useCanvasShortcuts, useClipboard, useContextMenu, useEditingNodeId, useHasCopied, useHelpLines, useIsRunning, useNodeResults, useSelectedNodeCount, useSubworkflowStore, useUndoRedo };
|
|
2956
|
-
//# sourceMappingURL=index.mjs.map
|
|
2957
|
-
//# sourceMappingURL=index.mjs.map
|