@tangle-network/sandbox-ui 0.72.0 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/WorkflowGraph-64XJBIW2.js +555 -0
- package/dist/{chunk-34F66QTV.js → chunk-VXGI2XUK.js} +89 -54
- package/dist/globals.css +108 -9
- package/dist/styles.css +108 -9
- package/dist/workflows.d.ts +38 -11
- package/dist/workflows.js +5 -5
- package/package.json +1 -1
- package/dist/WorkflowGraph-M5ZOY43R.js +0 -328
package/dist/workflows.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildWorkflowGraph
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VXGI2XUK.js";
|
|
4
4
|
import "./chunk-U67V476Y.js";
|
|
5
5
|
|
|
6
6
|
// src/workflows/WorkflowGraphLazy.tsx
|
|
@@ -26,7 +26,7 @@ function retryImport(factory, retries = 2, delayMs = 350) {
|
|
|
26
26
|
function lazyWorkflowGraph() {
|
|
27
27
|
return lazy(
|
|
28
28
|
() => retryImport(
|
|
29
|
-
() => import("./WorkflowGraph-
|
|
29
|
+
() => import("./WorkflowGraph-64XJBIW2.js").then((m) => ({ default: m.WorkflowGraph }))
|
|
30
30
|
)
|
|
31
31
|
);
|
|
32
32
|
}
|
|
@@ -50,18 +50,18 @@ function GraphFallback({
|
|
|
50
50
|
className: `overflow-auto rounded-lg border border-border bg-background p-2 ${className ?? ""}`,
|
|
51
51
|
children: [
|
|
52
52
|
/* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-between gap-2", children: [
|
|
53
|
-
/* @__PURE__ */ jsx("p", { className: "text-
|
|
53
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: "Couldn't render the graph \u2014 showing the definition." }),
|
|
54
54
|
/* @__PURE__ */ jsx(
|
|
55
55
|
"button",
|
|
56
56
|
{
|
|
57
57
|
type: "button",
|
|
58
58
|
onClick: onRetry,
|
|
59
|
-
className: "shrink-0 rounded border border-border px-1.5 py-0.5 text-
|
|
59
|
+
className: "shrink-0 rounded border border-border px-1.5 py-0.5 text-muted-foreground text-xs transition hover:text-foreground",
|
|
60
60
|
children: "Retry"
|
|
61
61
|
}
|
|
62
62
|
)
|
|
63
63
|
] }),
|
|
64
|
-
/* @__PURE__ */ jsx("pre", { className: "text-
|
|
64
|
+
/* @__PURE__ */ jsx("pre", { className: "text-foreground text-xs", children: /* @__PURE__ */ jsx("code", { children: yaml }) })
|
|
65
65
|
]
|
|
66
66
|
}
|
|
67
67
|
);
|
package/package.json
CHANGED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ProviderIcon
|
|
3
|
-
} from "./chunk-GTJ5PSK5.js";
|
|
4
|
-
import {
|
|
5
|
-
buildWorkflowGraph,
|
|
6
|
-
providerLabel
|
|
7
|
-
} from "./chunk-34F66QTV.js";
|
|
8
|
-
import "./chunk-U67V476Y.js";
|
|
9
|
-
|
|
10
|
-
// src/workflows/WorkflowGraph.tsx
|
|
11
|
-
import {
|
|
12
|
-
Background,
|
|
13
|
-
Controls,
|
|
14
|
-
Handle,
|
|
15
|
-
Position,
|
|
16
|
-
ReactFlow,
|
|
17
|
-
useEdgesState,
|
|
18
|
-
useNodesState
|
|
19
|
-
} from "@xyflow/react";
|
|
20
|
-
import "@xyflow/react/dist/style.css";
|
|
21
|
-
import {
|
|
22
|
-
useCallback,
|
|
23
|
-
useEffect,
|
|
24
|
-
useMemo,
|
|
25
|
-
useState
|
|
26
|
-
} from "react";
|
|
27
|
-
|
|
28
|
-
// src/workflows/flow-graph.ts
|
|
29
|
-
function buildFlowGraph(yaml, nodeState) {
|
|
30
|
-
const graph = buildWorkflowGraph(yaml, {
|
|
31
|
-
reserveRunState: nodeState !== void 0
|
|
32
|
-
});
|
|
33
|
-
return {
|
|
34
|
-
error: graph.error,
|
|
35
|
-
nodes: graph.nodes.map(
|
|
36
|
-
(n) => ({
|
|
37
|
-
id: n.id,
|
|
38
|
-
type: "wfNode",
|
|
39
|
-
position: n.position,
|
|
40
|
-
data: nodeState?.[n.id] ? { ...n.data, state: nodeState[n.id] } : n.data
|
|
41
|
-
})
|
|
42
|
-
),
|
|
43
|
-
edges: graph.edges.map((e) => ({
|
|
44
|
-
id: e.id,
|
|
45
|
-
source: e.source,
|
|
46
|
-
target: e.target,
|
|
47
|
-
sourceHandle: e.sourceHandle,
|
|
48
|
-
type: "smoothstep"
|
|
49
|
-
}))
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function sameRunState(a, b) {
|
|
53
|
-
if (a === b) return true;
|
|
54
|
-
if (!a || !b) return false;
|
|
55
|
-
const aKeys = Object.keys(a);
|
|
56
|
-
const bKeys = Object.keys(b);
|
|
57
|
-
if (aKeys.length !== bKeys.length) return false;
|
|
58
|
-
return aKeys.every((k) => a[k] === b[k]);
|
|
59
|
-
}
|
|
60
|
-
function mergeRunState(prev, baseDataById, nodeState) {
|
|
61
|
-
return prev.map((n) => {
|
|
62
|
-
const base = baseDataById.get(n.id) ?? n.data;
|
|
63
|
-
const s = nodeState?.[n.id];
|
|
64
|
-
const nextData = s ? { ...base, state: s } : base;
|
|
65
|
-
return sameRunState(n.data.state, nextData.state) ? n : { ...n, data: nextData };
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// src/workflows/format.ts
|
|
70
|
-
function fmtDuration(ms) {
|
|
71
|
-
if (ms === void 0 || !Number.isFinite(ms) || ms < 0) return void 0;
|
|
72
|
-
if (ms < 1e3) return `${Math.round(ms)}ms`;
|
|
73
|
-
const s = ms / 1e3;
|
|
74
|
-
if (s < 60) return `${s.toFixed(1)}s`;
|
|
75
|
-
const totalSeconds = Math.round(s);
|
|
76
|
-
return `${Math.floor(totalSeconds / 60)}m${totalSeconds % 60}s`;
|
|
77
|
-
}
|
|
78
|
-
function fmtCost(usd) {
|
|
79
|
-
if (usd === void 0 || !Number.isFinite(usd) || usd < 0) return void 0;
|
|
80
|
-
if (usd === 0) return "$0";
|
|
81
|
-
return usd < 0.01 ? `$${usd.toFixed(4)}` : `$${usd.toFixed(2)}`;
|
|
82
|
-
}
|
|
83
|
-
function clampPreview(text, max = 200) {
|
|
84
|
-
return text.length > max ? `${text.slice(0, max)}\u2026` : text;
|
|
85
|
-
}
|
|
86
|
-
function fmtTokens(input, output) {
|
|
87
|
-
const valid = (n) => n !== void 0 && Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
88
|
-
const i = valid(input);
|
|
89
|
-
const o = valid(output);
|
|
90
|
-
if (i === void 0 && o === void 0) return void 0;
|
|
91
|
-
return `${i ?? 0}/${o ?? 0} tok`;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// src/workflows/WorkflowGraph.tsx
|
|
95
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
96
|
-
function useColorMode() {
|
|
97
|
-
const [mode, setMode] = useState(
|
|
98
|
-
() => typeof document !== "undefined" && document.documentElement.classList.contains("dark") ? "dark" : "light"
|
|
99
|
-
);
|
|
100
|
-
useEffect(() => {
|
|
101
|
-
const el = document.documentElement;
|
|
102
|
-
const update = () => setMode(el.classList.contains("dark") ? "dark" : "light");
|
|
103
|
-
update();
|
|
104
|
-
const observer = new MutationObserver(update);
|
|
105
|
-
observer.observe(el, { attributes: true, attributeFilter: ["class"] });
|
|
106
|
-
return () => observer.disconnect();
|
|
107
|
-
}, []);
|
|
108
|
-
return mode;
|
|
109
|
-
}
|
|
110
|
-
var TONE_CARD = {
|
|
111
|
-
trigger: "border-primary/60 bg-primary/5",
|
|
112
|
-
structural: "border-accent-yellow/50 bg-accent-yellow/5",
|
|
113
|
-
action: "border-border bg-card"
|
|
114
|
-
};
|
|
115
|
-
var TONE_DOT = {
|
|
116
|
-
trigger: "bg-primary",
|
|
117
|
-
structural: "bg-accent-yellow",
|
|
118
|
-
action: "bg-text-muted"
|
|
119
|
-
};
|
|
120
|
-
var HANDLE_CLASS = "!h-2 !w-2 !min-w-0 !border-0 !bg-transparent opacity-0";
|
|
121
|
-
var STATUS_LABEL = {
|
|
122
|
-
queued: "Queued",
|
|
123
|
-
running: "Running",
|
|
124
|
-
succeeded: "Done",
|
|
125
|
-
failed: "Failed"
|
|
126
|
-
};
|
|
127
|
-
var STATUS_BADGE = {
|
|
128
|
-
queued: "bg-background-tertiary text-text-muted",
|
|
129
|
-
running: "bg-primary/15 text-primary",
|
|
130
|
-
succeeded: "bg-green-600/10 text-green-600",
|
|
131
|
-
failed: "bg-red-500/10 text-red-400"
|
|
132
|
-
};
|
|
133
|
-
function statusBorder(status) {
|
|
134
|
-
switch (status) {
|
|
135
|
-
case "running":
|
|
136
|
-
return "border-primary ring-2 ring-primary/40 animate-pulse";
|
|
137
|
-
case "succeeded":
|
|
138
|
-
return "border-green-500";
|
|
139
|
-
case "failed":
|
|
140
|
-
return "border-red-500";
|
|
141
|
-
default:
|
|
142
|
-
return "opacity-70";
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
function MetaChip({ children }) {
|
|
146
|
-
return /* @__PURE__ */ jsx("span", { className: "rounded bg-background-tertiary px-1.5 py-0.5 text-[10px] text-text-muted", children });
|
|
147
|
-
}
|
|
148
|
-
function WorkflowNode({ data }) {
|
|
149
|
-
const d = data;
|
|
150
|
-
const state = d.state;
|
|
151
|
-
const model = state?.model ?? d.model;
|
|
152
|
-
const duration = fmtDuration(state?.durationMs);
|
|
153
|
-
const cost = fmtCost(state?.costUsd);
|
|
154
|
-
const tokens = fmtTokens(state?.inputTokens, state?.outputTokens);
|
|
155
|
-
const errorText = state?.error ? clampPreview(state.error) : void 0;
|
|
156
|
-
const outputText = state?.outputPreview ? clampPreview(state.outputPreview) : void 0;
|
|
157
|
-
return /* @__PURE__ */ jsxs(
|
|
158
|
-
"div",
|
|
159
|
-
{
|
|
160
|
-
className: `relative w-[240px] rounded-lg border px-3 py-2 shadow-sm transition-colors ${TONE_CARD[d.tone]} ${state ? statusBorder(state.status) : ""}`,
|
|
161
|
-
children: [
|
|
162
|
-
!d.isRoot && /* @__PURE__ */ jsx(
|
|
163
|
-
Handle,
|
|
164
|
-
{
|
|
165
|
-
type: "target",
|
|
166
|
-
position: Position.Top,
|
|
167
|
-
className: HANDLE_CLASS
|
|
168
|
-
}
|
|
169
|
-
),
|
|
170
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
171
|
-
/* @__PURE__ */ jsx(
|
|
172
|
-
"span",
|
|
173
|
-
{
|
|
174
|
-
"aria-hidden": "true",
|
|
175
|
-
className: `h-2 w-2 shrink-0 rounded-full ${TONE_DOT[d.tone]}`
|
|
176
|
-
}
|
|
177
|
-
),
|
|
178
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium text-[12px] text-text", children: d.title }),
|
|
179
|
-
state ? /* @__PURE__ */ jsx(
|
|
180
|
-
"span",
|
|
181
|
-
{
|
|
182
|
-
className: `ml-auto rounded px-1.5 py-0.5 text-[10px] ${STATUS_BADGE[state.status]}`,
|
|
183
|
-
children: STATUS_LABEL[state.status]
|
|
184
|
-
}
|
|
185
|
-
) : d.badge && /* @__PURE__ */ jsx("span", { className: "ml-auto rounded bg-background-tertiary px-1.5 py-0.5 text-[10px] text-text-muted", children: d.badge })
|
|
186
|
-
] }),
|
|
187
|
-
d.subtitle && /* @__PURE__ */ jsx(
|
|
188
|
-
"p",
|
|
189
|
-
{
|
|
190
|
-
className: "mt-1 truncate text-[11px] text-text-muted",
|
|
191
|
-
title: d.subtitle,
|
|
192
|
-
children: d.subtitle
|
|
193
|
-
}
|
|
194
|
-
),
|
|
195
|
-
(model || cost || duration || tokens || state) && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 flex flex-wrap items-center gap-1", children: [
|
|
196
|
-
d.kind && d.tone === "action" && /* @__PURE__ */ jsx(MetaChip, { children: d.kind }),
|
|
197
|
-
model && /* @__PURE__ */ jsx(MetaChip, { children: model }),
|
|
198
|
-
cost && /* @__PURE__ */ jsx(MetaChip, { children: cost }),
|
|
199
|
-
duration && /* @__PURE__ */ jsx(MetaChip, { children: duration }),
|
|
200
|
-
tokens && /* @__PURE__ */ jsx(MetaChip, { children: tokens })
|
|
201
|
-
] }),
|
|
202
|
-
state?.status === "failed" && errorText && /* @__PURE__ */ jsx(
|
|
203
|
-
"p",
|
|
204
|
-
{
|
|
205
|
-
className: "mt-1.5 line-clamp-2 text-[10px] text-red-400",
|
|
206
|
-
title: errorText,
|
|
207
|
-
children: errorText
|
|
208
|
-
}
|
|
209
|
-
),
|
|
210
|
-
outputText && state?.status !== "failed" && /* @__PURE__ */ jsx(
|
|
211
|
-
"p",
|
|
212
|
-
{
|
|
213
|
-
className: "mt-1.5 line-clamp-2 text-[10px] text-text-muted",
|
|
214
|
-
title: outputText,
|
|
215
|
-
children: outputText
|
|
216
|
-
}
|
|
217
|
-
),
|
|
218
|
-
d.provider && /* @__PURE__ */ jsxs("span", { className: "mt-1.5 inline-flex items-center gap-1 rounded bg-background-tertiary px-1.5 py-0.5 text-[10px] text-text-muted", children: [
|
|
219
|
-
/* @__PURE__ */ jsx(
|
|
220
|
-
ProviderIcon,
|
|
221
|
-
{
|
|
222
|
-
id: d.provider,
|
|
223
|
-
displayName: providerLabel(d.provider),
|
|
224
|
-
size: 12,
|
|
225
|
-
className: "rounded-[2px]"
|
|
226
|
-
}
|
|
227
|
-
),
|
|
228
|
-
providerLabel(d.provider)
|
|
229
|
-
] }),
|
|
230
|
-
/* @__PURE__ */ jsx(
|
|
231
|
-
Handle,
|
|
232
|
-
{
|
|
233
|
-
type: "source",
|
|
234
|
-
id: "out",
|
|
235
|
-
position: Position.Bottom,
|
|
236
|
-
className: HANDLE_CLASS
|
|
237
|
-
}
|
|
238
|
-
),
|
|
239
|
-
d.hasBranches && /* @__PURE__ */ jsx(
|
|
240
|
-
Handle,
|
|
241
|
-
{
|
|
242
|
-
type: "source",
|
|
243
|
-
id: "branch",
|
|
244
|
-
position: Position.Right,
|
|
245
|
-
className: HANDLE_CLASS
|
|
246
|
-
}
|
|
247
|
-
)
|
|
248
|
-
]
|
|
249
|
-
}
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
var NODE_TYPES = { wfNode: WorkflowNode };
|
|
253
|
-
function WorkflowGraph({
|
|
254
|
-
yaml,
|
|
255
|
-
variant = "full",
|
|
256
|
-
className,
|
|
257
|
-
nodeState,
|
|
258
|
-
onNodeClick
|
|
259
|
-
}) {
|
|
260
|
-
const colorMode = useColorMode();
|
|
261
|
-
const hasRunOverlay = nodeState !== void 0;
|
|
262
|
-
const structural = useMemo(
|
|
263
|
-
() => buildFlowGraph(yaml, hasRunOverlay ? {} : void 0),
|
|
264
|
-
[yaml, hasRunOverlay]
|
|
265
|
-
);
|
|
266
|
-
const [nodes, setNodes, onNodesChange] = useNodesState(structural.nodes);
|
|
267
|
-
const [edges, setEdges, onEdgesChange] = useEdgesState(structural.edges);
|
|
268
|
-
useEffect(() => {
|
|
269
|
-
setNodes(structural.nodes);
|
|
270
|
-
setEdges(structural.edges);
|
|
271
|
-
}, [structural, setNodes, setEdges]);
|
|
272
|
-
useEffect(() => {
|
|
273
|
-
const baseById = new Map(structural.nodes.map((n) => [n.id, n.data]));
|
|
274
|
-
setNodes((prev) => mergeRunState(prev, baseById, nodeState));
|
|
275
|
-
}, [nodeState, structural, setNodes]);
|
|
276
|
-
const handleNodeClick = useCallback(
|
|
277
|
-
(_event, node) => {
|
|
278
|
-
onNodeClick?.(node.id, node.data);
|
|
279
|
-
},
|
|
280
|
-
[onNodeClick]
|
|
281
|
-
);
|
|
282
|
-
if (structural.error || structural.nodes.length === 0) {
|
|
283
|
-
return /* @__PURE__ */ jsx(
|
|
284
|
-
"div",
|
|
285
|
-
{
|
|
286
|
-
className: `flex items-center justify-center rounded-lg border border-border border-dashed p-4 text-center text-text-muted text-xs ${className ?? ""}`,
|
|
287
|
-
children: structural.error ?? "Nothing to show"
|
|
288
|
-
}
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
const isPreview = variant === "preview";
|
|
292
|
-
return /* @__PURE__ */ jsx("div", { className: `wf-graph ${className ?? ""}`, children: /* @__PURE__ */ jsxs(
|
|
293
|
-
ReactFlow,
|
|
294
|
-
{
|
|
295
|
-
nodes,
|
|
296
|
-
edges,
|
|
297
|
-
onNodesChange,
|
|
298
|
-
onEdgesChange,
|
|
299
|
-
nodeTypes: NODE_TYPES,
|
|
300
|
-
colorMode,
|
|
301
|
-
onNodeClick: onNodeClick ? handleNodeClick : void 0,
|
|
302
|
-
fitView: true,
|
|
303
|
-
fitViewOptions: { padding: 0.2 },
|
|
304
|
-
proOptions: { hideAttribution: true },
|
|
305
|
-
nodesDraggable: !isPreview,
|
|
306
|
-
nodesConnectable: false,
|
|
307
|
-
deleteKeyCode: null,
|
|
308
|
-
edgesReconnectable: false,
|
|
309
|
-
elementsSelectable: !isPreview,
|
|
310
|
-
edgesFocusable: false,
|
|
311
|
-
zoomOnScroll: false,
|
|
312
|
-
zoomOnPinch: true,
|
|
313
|
-
zoomOnDoubleClick: !isPreview,
|
|
314
|
-
panOnDrag: true,
|
|
315
|
-
preventScrolling: false,
|
|
316
|
-
minZoom: 0.2,
|
|
317
|
-
maxZoom: 1.5,
|
|
318
|
-
children: [
|
|
319
|
-
/* @__PURE__ */ jsx(Background, { gap: 16 }),
|
|
320
|
-
/* @__PURE__ */ jsx(Controls, { showInteractive: false, position: "bottom-right" })
|
|
321
|
-
]
|
|
322
|
-
}
|
|
323
|
-
) });
|
|
324
|
-
}
|
|
325
|
-
export {
|
|
326
|
-
WorkflowGraph,
|
|
327
|
-
WorkflowNode
|
|
328
|
-
};
|