@erdoai/ui 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +10 -4043
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,4043 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (!config) {
|
|
11
|
-
throw new Error("useErdoConfig must be used within an ErdoProvider");
|
|
12
|
-
}
|
|
13
|
-
return config;
|
|
14
|
-
}
|
|
15
|
-
function useErdoConfigOptional() {
|
|
16
|
-
return useContext(ErdoContext);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// src/components/error-boundary.tsx
|
|
20
|
-
import React2 from "react";
|
|
21
|
-
var ErrorBoundary = class extends React2.Component {
|
|
22
|
-
constructor(props) {
|
|
23
|
-
super(props);
|
|
24
|
-
this.state = { hasError: false };
|
|
25
|
-
}
|
|
26
|
-
static getDerivedStateFromError(_) {
|
|
27
|
-
return { hasError: true };
|
|
28
|
-
}
|
|
29
|
-
componentDidCatch(error, errorInfo) {
|
|
30
|
-
console.error("ErrorBoundary caught an error:", error, errorInfo);
|
|
31
|
-
}
|
|
32
|
-
render() {
|
|
33
|
-
if (this.state.hasError) {
|
|
34
|
-
return this.props.fallback;
|
|
35
|
-
}
|
|
36
|
-
return this.props.children;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// src/components/ui/chart.tsx
|
|
41
|
-
import * as React3 from "react";
|
|
42
|
-
import * as RechartsPrimitive from "recharts";
|
|
43
|
-
|
|
44
|
-
// src/lib/utils.ts
|
|
45
|
-
import { clsx } from "clsx";
|
|
46
|
-
import { twMerge } from "tailwind-merge";
|
|
47
|
-
function cn(...inputs) {
|
|
48
|
-
return twMerge(clsx(inputs));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// src/components/ui/chart.tsx
|
|
52
|
-
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
53
|
-
var THEMES = { light: "", dark: ".dark" };
|
|
54
|
-
var ChartContext = React3.createContext(null);
|
|
55
|
-
function useChart() {
|
|
56
|
-
const context = React3.useContext(ChartContext);
|
|
57
|
-
if (!context) {
|
|
58
|
-
throw new Error("useChart must be used within a <ChartContainer />");
|
|
59
|
-
}
|
|
60
|
-
return context;
|
|
61
|
-
}
|
|
62
|
-
function ChartContainer({
|
|
63
|
-
id,
|
|
64
|
-
className,
|
|
65
|
-
children,
|
|
66
|
-
config,
|
|
67
|
-
debounceResize = false,
|
|
68
|
-
...props
|
|
69
|
-
}) {
|
|
70
|
-
const uniqueId = React3.useId();
|
|
71
|
-
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
72
|
-
return /* @__PURE__ */ jsx2(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxs(
|
|
73
|
-
"div",
|
|
74
|
-
{
|
|
75
|
-
"data-slot": "chart",
|
|
76
|
-
"data-chart": chartId,
|
|
77
|
-
className: cn(
|
|
78
|
-
"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
|
|
79
|
-
className
|
|
80
|
-
),
|
|
81
|
-
...props,
|
|
82
|
-
children: [
|
|
83
|
-
/* @__PURE__ */ jsx2(ChartStyle, { id: chartId, config }),
|
|
84
|
-
/* @__PURE__ */ jsx2(RechartsPrimitive.ResponsiveContainer, { debounce: debounceResize ? 200 : 0, children })
|
|
85
|
-
]
|
|
86
|
-
}
|
|
87
|
-
) });
|
|
88
|
-
}
|
|
89
|
-
var ChartStyle = ({ id, config }) => {
|
|
90
|
-
const colorConfig = Object.entries(config).filter(([, config2]) => config2.theme || config2.color);
|
|
91
|
-
if (!colorConfig.length) {
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
return /* @__PURE__ */ jsx2(
|
|
95
|
-
"style",
|
|
96
|
-
{
|
|
97
|
-
dangerouslySetInnerHTML: {
|
|
98
|
-
__html: Object.entries(THEMES).map(
|
|
99
|
-
([theme, prefix]) => `
|
|
100
|
-
${prefix} [data-chart=${id}] {
|
|
101
|
-
${colorConfig.map(([key, itemConfig]) => {
|
|
102
|
-
const color = itemConfig.theme?.[theme] || itemConfig.color;
|
|
103
|
-
return color ? ` --color-${key}: ${color};` : null;
|
|
104
|
-
}).join("\n")}
|
|
105
|
-
}
|
|
106
|
-
`
|
|
107
|
-
).join("\n")
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
);
|
|
111
|
-
};
|
|
112
|
-
var ChartTooltip = RechartsPrimitive.Tooltip;
|
|
113
|
-
function ChartTooltipContent({
|
|
114
|
-
active,
|
|
115
|
-
payload,
|
|
116
|
-
className,
|
|
117
|
-
indicator = "dot",
|
|
118
|
-
hideLabel = false,
|
|
119
|
-
hideIndicator = false,
|
|
120
|
-
label,
|
|
121
|
-
labelFormatter,
|
|
122
|
-
labelClassName,
|
|
123
|
-
formatter,
|
|
124
|
-
color,
|
|
125
|
-
nameKey,
|
|
126
|
-
labelKey
|
|
127
|
-
}) {
|
|
128
|
-
const { config } = useChart();
|
|
129
|
-
const tooltipLabel = React3.useMemo(() => {
|
|
130
|
-
if (hideLabel || !payload?.length) {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
const [item] = payload;
|
|
134
|
-
const key = `${labelKey || item?.dataKey || item?.name || "value"}`;
|
|
135
|
-
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
136
|
-
const value = !labelKey && typeof label === "string" ? config[label]?.label || label : itemConfig?.label;
|
|
137
|
-
if (labelFormatter) {
|
|
138
|
-
return /* @__PURE__ */ jsx2("div", { className: cn("font-medium", labelClassName), children: labelFormatter(value, payload) });
|
|
139
|
-
}
|
|
140
|
-
if (!value) {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
return /* @__PURE__ */ jsx2("div", { className: cn("font-medium", labelClassName), children: value });
|
|
144
|
-
}, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);
|
|
145
|
-
if (!active || !payload?.length) {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
const nestLabel = payload.length === 1 && indicator !== "dot";
|
|
149
|
-
return /* @__PURE__ */ jsxs(
|
|
150
|
-
"div",
|
|
151
|
-
{
|
|
152
|
-
className: cn(
|
|
153
|
-
"border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl",
|
|
154
|
-
className
|
|
155
|
-
),
|
|
156
|
-
children: [
|
|
157
|
-
!nestLabel ? tooltipLabel : null,
|
|
158
|
-
/* @__PURE__ */ jsx2("div", { className: "grid gap-1.5", children: payload.map((item, index) => {
|
|
159
|
-
const key = `${nameKey || item.name || item.dataKey || "value"}`;
|
|
160
|
-
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
161
|
-
const indicatorColor = color || item.payload.fill || item.color;
|
|
162
|
-
return /* @__PURE__ */ jsx2(
|
|
163
|
-
"div",
|
|
164
|
-
{
|
|
165
|
-
className: cn(
|
|
166
|
-
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
|
|
167
|
-
indicator === "dot" && "items-center"
|
|
168
|
-
),
|
|
169
|
-
children: formatter && item?.value !== void 0 && item.name ? formatter(item.value, item.name, item, index, item.payload) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
170
|
-
itemConfig?.icon ? /* @__PURE__ */ jsx2(itemConfig.icon, {}) : !hideIndicator && /* @__PURE__ */ jsx2(
|
|
171
|
-
"div",
|
|
172
|
-
{
|
|
173
|
-
className: cn(
|
|
174
|
-
"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
|
|
175
|
-
{
|
|
176
|
-
"h-2.5 w-2.5": indicator === "dot",
|
|
177
|
-
"w-1": indicator === "line",
|
|
178
|
-
"w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
|
|
179
|
-
"my-0.5": nestLabel && indicator === "dashed"
|
|
180
|
-
}
|
|
181
|
-
),
|
|
182
|
-
style: {
|
|
183
|
-
"--color-bg": indicatorColor,
|
|
184
|
-
"--color-border": indicatorColor
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
),
|
|
188
|
-
/* @__PURE__ */ jsxs(
|
|
189
|
-
"div",
|
|
190
|
-
{
|
|
191
|
-
className: cn(
|
|
192
|
-
"flex flex-1 justify-between leading-none",
|
|
193
|
-
nestLabel ? "items-end" : "items-center"
|
|
194
|
-
),
|
|
195
|
-
children: [
|
|
196
|
-
/* @__PURE__ */ jsxs("div", { className: "grid gap-1.5", children: [
|
|
197
|
-
nestLabel ? tooltipLabel : null,
|
|
198
|
-
/* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: itemConfig?.label || item.name })
|
|
199
|
-
] }),
|
|
200
|
-
item.value && /* @__PURE__ */ jsx2("span", { className: "text-foreground font-mono font-medium tabular-nums", children: item.value.toLocaleString() })
|
|
201
|
-
]
|
|
202
|
-
}
|
|
203
|
-
)
|
|
204
|
-
] })
|
|
205
|
-
},
|
|
206
|
-
item.dataKey
|
|
207
|
-
);
|
|
208
|
-
}) })
|
|
209
|
-
]
|
|
210
|
-
}
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
var ChartLegend = RechartsPrimitive.Legend;
|
|
214
|
-
function ChartLegendContent({
|
|
215
|
-
className,
|
|
216
|
-
hideIcon = false,
|
|
217
|
-
payload,
|
|
218
|
-
verticalAlign = "bottom",
|
|
219
|
-
nameKey
|
|
220
|
-
}) {
|
|
221
|
-
const { config } = useChart();
|
|
222
|
-
if (!payload?.length) {
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
return /* @__PURE__ */ jsx2(
|
|
226
|
-
"div",
|
|
227
|
-
{
|
|
228
|
-
className: cn(
|
|
229
|
-
"flex items-center justify-center gap-4",
|
|
230
|
-
verticalAlign === "top" ? "pb-3" : "pt-3",
|
|
231
|
-
className
|
|
232
|
-
),
|
|
233
|
-
children: payload.map((item) => {
|
|
234
|
-
const key = `${nameKey || item.dataKey || "value"}`;
|
|
235
|
-
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
236
|
-
return /* @__PURE__ */ jsxs(
|
|
237
|
-
"div",
|
|
238
|
-
{
|
|
239
|
-
className: cn(
|
|
240
|
-
"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3"
|
|
241
|
-
),
|
|
242
|
-
children: [
|
|
243
|
-
itemConfig?.icon && !hideIcon ? /* @__PURE__ */ jsx2(itemConfig.icon, {}) : /* @__PURE__ */ jsx2(
|
|
244
|
-
"div",
|
|
245
|
-
{
|
|
246
|
-
className: "h-2 w-2 shrink-0 rounded-[2px]",
|
|
247
|
-
style: {
|
|
248
|
-
backgroundColor: item.color
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
),
|
|
252
|
-
itemConfig?.label
|
|
253
|
-
]
|
|
254
|
-
},
|
|
255
|
-
item.value
|
|
256
|
-
);
|
|
257
|
-
})
|
|
258
|
-
}
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
function getPayloadConfigFromPayload(config, payload, key) {
|
|
262
|
-
if (typeof payload !== "object" || payload === null) {
|
|
263
|
-
return void 0;
|
|
264
|
-
}
|
|
265
|
-
const payloadPayload = "payload" in payload && typeof payload.payload === "object" && payload.payload !== null ? payload.payload : void 0;
|
|
266
|
-
let configLabelKey = key;
|
|
267
|
-
if (key in payload && typeof payload[key] === "string") {
|
|
268
|
-
configLabelKey = payload[key];
|
|
269
|
-
} else if (payloadPayload && key in payloadPayload && typeof payloadPayload[key] === "string") {
|
|
270
|
-
configLabelKey = payloadPayload[key];
|
|
271
|
-
}
|
|
272
|
-
return configLabelKey in config ? config[configLabelKey] : config[key];
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// src/lib/formatters.ts
|
|
276
|
-
import { format as d3Format } from "d3-format";
|
|
277
|
-
import { utcFormat as d3UtcFormat } from "d3-time-format";
|
|
278
|
-
import { parse as dateParse, isValid } from "date-fns";
|
|
279
|
-
function formatValue(value, format, valueType) {
|
|
280
|
-
if (value === null || value === void 0) {
|
|
281
|
-
return "";
|
|
282
|
-
}
|
|
283
|
-
if (valueType === "date") {
|
|
284
|
-
const dateValue = parseToDate(value);
|
|
285
|
-
if (dateValue && format) {
|
|
286
|
-
try {
|
|
287
|
-
let normalizedFormat = format;
|
|
288
|
-
if (format === "%Y%m%d") {
|
|
289
|
-
normalizedFormat = "%Y-%m-%d";
|
|
290
|
-
} else if (format === "%d%m%Y") {
|
|
291
|
-
normalizedFormat = "%d-%m-%Y";
|
|
292
|
-
} else if (format === "%m%d%Y") {
|
|
293
|
-
normalizedFormat = "%m-%d-%Y";
|
|
294
|
-
}
|
|
295
|
-
const allDirectives = normalizedFormat.match(/%./g) || [];
|
|
296
|
-
const validDirectiveChars = "aAbBcdejHILmMpSUwWxXyYZ%";
|
|
297
|
-
const hasInvalidDirectives = allDirectives.some((directive) => {
|
|
298
|
-
const char = directive.charAt(1);
|
|
299
|
-
return !validDirectiveChars.includes(char);
|
|
300
|
-
});
|
|
301
|
-
if (hasInvalidDirectives || allDirectives.length === 0) {
|
|
302
|
-
console.warn(`Invalid date format directives in: ${format}. Using default format.`);
|
|
303
|
-
return dateValue.toISOString().split("T")[0];
|
|
304
|
-
}
|
|
305
|
-
const utcFormatter = d3UtcFormat(normalizedFormat);
|
|
306
|
-
return utcFormatter(dateValue);
|
|
307
|
-
} catch (error) {
|
|
308
|
-
console.warn(`Invalid date format: ${format}. Error: ${error}. Falling back to default.`);
|
|
309
|
-
return dateValue.toISOString().split("T")[0];
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (dateValue) {
|
|
313
|
-
const isoString = dateValue.toISOString();
|
|
314
|
-
if (isoString.endsWith("T00:00:00.000Z")) {
|
|
315
|
-
return isoString.split("T")[0];
|
|
316
|
-
}
|
|
317
|
-
return dateValue.toISOString().replace("T", " ").replace(".000Z", " UTC");
|
|
318
|
-
}
|
|
319
|
-
return String(value);
|
|
320
|
-
}
|
|
321
|
-
if (valueType === "number") {
|
|
322
|
-
const numValue = typeof value === "string" ? parseFloat(value.replace(/,/g, "")) : value;
|
|
323
|
-
if (isNaN(numValue)) {
|
|
324
|
-
return String(value);
|
|
325
|
-
}
|
|
326
|
-
let normalizedFormat = format;
|
|
327
|
-
if (format) {
|
|
328
|
-
normalizedFormat = format.replace(/(\.\d+)f%/, "$1%");
|
|
329
|
-
}
|
|
330
|
-
if (!normalizedFormat) {
|
|
331
|
-
if (Math.abs(numValue) >= 1e3) {
|
|
332
|
-
return d3Format(",.0f")(numValue);
|
|
333
|
-
} else if (Math.abs(numValue) >= 100) {
|
|
334
|
-
return d3Format(".1f")(numValue);
|
|
335
|
-
} else if (Math.abs(numValue) >= 10) {
|
|
336
|
-
return d3Format(".2f")(numValue);
|
|
337
|
-
} else if (Math.abs(numValue) >= 1) {
|
|
338
|
-
return d3Format(".3f")(numValue);
|
|
339
|
-
} else {
|
|
340
|
-
return d3Format(".3g")(numValue);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
if (normalizedFormat.includes("%")) {
|
|
344
|
-
if (numValue >= 0 && numValue <= 1) {
|
|
345
|
-
return d3Format(normalizedFormat)(numValue);
|
|
346
|
-
}
|
|
347
|
-
return d3Format(normalizedFormat)(numValue / 100);
|
|
348
|
-
}
|
|
349
|
-
try {
|
|
350
|
-
return d3Format(normalizedFormat)(numValue);
|
|
351
|
-
} catch (error) {
|
|
352
|
-
console.warn(
|
|
353
|
-
`Error formatting number with format '${normalizedFormat}': ${error}. Falling back to default.`
|
|
354
|
-
);
|
|
355
|
-
if (Math.abs(numValue) >= 1e3) {
|
|
356
|
-
return d3Format(",.0f")(numValue);
|
|
357
|
-
} else if (Math.abs(numValue) >= 1) {
|
|
358
|
-
return d3Format(".2f")(numValue);
|
|
359
|
-
} else {
|
|
360
|
-
return d3Format(".3g")(numValue);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
return String(value);
|
|
365
|
-
}
|
|
366
|
-
function parseToDate(value) {
|
|
367
|
-
if (!value) return null;
|
|
368
|
-
if (value instanceof Date) {
|
|
369
|
-
return isValid(value) ? value : null;
|
|
370
|
-
}
|
|
371
|
-
if (typeof value === "number") {
|
|
372
|
-
const date2 = new Date(value);
|
|
373
|
-
return isValid(date2) ? date2 : null;
|
|
374
|
-
}
|
|
375
|
-
if (typeof value === "string") {
|
|
376
|
-
const dateOnlyRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
377
|
-
if (dateOnlyRegex.test(value)) {
|
|
378
|
-
const date2 = /* @__PURE__ */ new Date(value + "T00:00:00.000Z");
|
|
379
|
-
if (isValid(date2)) {
|
|
380
|
-
return date2;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
const formats = [
|
|
384
|
-
"yyyy-MM-dd",
|
|
385
|
-
"yyyyMMdd",
|
|
386
|
-
"yyyy-MM-dd'T'HH:mm:ss",
|
|
387
|
-
"yyyyMMddHHmmss",
|
|
388
|
-
"MM/dd/yyyy",
|
|
389
|
-
"dd/MM/yyyy"
|
|
390
|
-
];
|
|
391
|
-
for (const format of formats) {
|
|
392
|
-
const parsed = dateParse(value, format, /* @__PURE__ */ new Date());
|
|
393
|
-
if (isValid(parsed)) {
|
|
394
|
-
return parsed;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
const date = new Date(value);
|
|
399
|
-
if (isValid(date)) {
|
|
400
|
-
return date;
|
|
401
|
-
}
|
|
402
|
-
return null;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// src/hooks/use-chart-zoom.ts
|
|
406
|
-
import { useState, useCallback, useMemo as useMemo2 } from "react";
|
|
407
|
-
function useChartZoom({ onZoomChange } = {}) {
|
|
408
|
-
const [zoomState, setZoomState] = useState({
|
|
409
|
-
refAreaLeft: null,
|
|
410
|
-
refAreaRight: null,
|
|
411
|
-
refAreaTop: null,
|
|
412
|
-
refAreaBottom: null,
|
|
413
|
-
zooming: false
|
|
414
|
-
});
|
|
415
|
-
const [customDomain, setCustomDomain] = useState({
|
|
416
|
-
x: [null, null],
|
|
417
|
-
y: [null, null]
|
|
418
|
-
});
|
|
419
|
-
const handleZoomStart = useCallback((e) => {
|
|
420
|
-
if (!e?.xValue || !e?.yValue) return;
|
|
421
|
-
setZoomState((prev) => ({
|
|
422
|
-
...prev,
|
|
423
|
-
refAreaLeft: e.xValue,
|
|
424
|
-
refAreaTop: e.yValue,
|
|
425
|
-
zooming: true
|
|
426
|
-
}));
|
|
427
|
-
}, []);
|
|
428
|
-
const handleZoomMove = useCallback(
|
|
429
|
-
(e) => {
|
|
430
|
-
if (!e?.xValue || !e?.yValue || !zoomState.zooming) return;
|
|
431
|
-
setZoomState((prev) => ({
|
|
432
|
-
...prev,
|
|
433
|
-
refAreaRight: e.xValue,
|
|
434
|
-
refAreaBottom: e.yValue
|
|
435
|
-
}));
|
|
436
|
-
},
|
|
437
|
-
[zoomState.zooming]
|
|
438
|
-
);
|
|
439
|
-
const handleZoomEnd = useCallback(() => {
|
|
440
|
-
if (!zoomState.refAreaLeft || !zoomState.refAreaRight || !zoomState.refAreaTop || !zoomState.refAreaBottom) {
|
|
441
|
-
setZoomState({
|
|
442
|
-
refAreaLeft: null,
|
|
443
|
-
refAreaRight: null,
|
|
444
|
-
refAreaTop: null,
|
|
445
|
-
refAreaBottom: null,
|
|
446
|
-
zooming: false
|
|
447
|
-
});
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
const [left, right] = [
|
|
451
|
-
Math.min(zoomState.refAreaLeft, zoomState.refAreaRight),
|
|
452
|
-
Math.max(zoomState.refAreaLeft, zoomState.refAreaRight)
|
|
453
|
-
];
|
|
454
|
-
const [bottom, top] = [
|
|
455
|
-
Math.min(zoomState.refAreaTop, zoomState.refAreaBottom),
|
|
456
|
-
Math.max(zoomState.refAreaTop, zoomState.refAreaBottom)
|
|
457
|
-
];
|
|
458
|
-
const newDomain = {
|
|
459
|
-
x: [left, right],
|
|
460
|
-
y: [bottom, top]
|
|
461
|
-
};
|
|
462
|
-
setCustomDomain(newDomain);
|
|
463
|
-
onZoomChange?.(newDomain);
|
|
464
|
-
setZoomState({
|
|
465
|
-
refAreaLeft: null,
|
|
466
|
-
refAreaRight: null,
|
|
467
|
-
refAreaTop: null,
|
|
468
|
-
refAreaBottom: null,
|
|
469
|
-
zooming: false
|
|
470
|
-
});
|
|
471
|
-
}, [zoomState, onZoomChange]);
|
|
472
|
-
const handleResetZoom = useCallback(() => {
|
|
473
|
-
const resetDomain = {
|
|
474
|
-
x: [null, null],
|
|
475
|
-
y: [null, null]
|
|
476
|
-
};
|
|
477
|
-
setCustomDomain(resetDomain);
|
|
478
|
-
onZoomChange?.(resetDomain);
|
|
479
|
-
}, [onZoomChange]);
|
|
480
|
-
const handlers = useMemo2(
|
|
481
|
-
() => ({
|
|
482
|
-
onZoomStart: handleZoomStart,
|
|
483
|
-
onZoomMove: handleZoomMove,
|
|
484
|
-
onZoomEnd: handleZoomEnd,
|
|
485
|
-
onResetZoom: handleResetZoom
|
|
486
|
-
}),
|
|
487
|
-
[handleZoomStart, handleZoomMove, handleZoomEnd, handleResetZoom]
|
|
488
|
-
);
|
|
489
|
-
return {
|
|
490
|
-
zoomState,
|
|
491
|
-
customDomain,
|
|
492
|
-
handlers
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
// src/components/charts/chart.tsx
|
|
497
|
-
import { useToPng } from "@hugocxl/react-to-image";
|
|
498
|
-
import { Download } from "lucide-react";
|
|
499
|
-
import { useCallback as useCallback2, useEffect, useMemo as useMemo3, useState as useState2 } from "react";
|
|
500
|
-
import { CartesianGrid, Label, ReferenceArea, XAxis, YAxis } from "recharts";
|
|
501
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
502
|
-
function formatDomain(axis) {
|
|
503
|
-
const ret = {
|
|
504
|
-
max: null,
|
|
505
|
-
min: null
|
|
506
|
-
};
|
|
507
|
-
if (axis.maxValue) {
|
|
508
|
-
if (axis.type === "number") {
|
|
509
|
-
const parsedValue = parseFloat(axis.maxValue);
|
|
510
|
-
if (!isNaN(parsedValue)) {
|
|
511
|
-
ret.max = parsedValue;
|
|
512
|
-
} else {
|
|
513
|
-
console.warn(`Error parsing max value ${axis.maxValue}. Falling back to default.`);
|
|
514
|
-
}
|
|
515
|
-
} else if (axis.type === "date") {
|
|
516
|
-
if (typeof axis.maxValue === "string" && /^\d{4}-\d{2}-\d{2}$/.test(axis.maxValue)) {
|
|
517
|
-
ret.max = (/* @__PURE__ */ new Date(axis.maxValue + "T00:00:00.000Z")).getTime();
|
|
518
|
-
} else {
|
|
519
|
-
ret.max = new Date(axis.maxValue).getTime();
|
|
520
|
-
}
|
|
521
|
-
} else {
|
|
522
|
-
ret.max = axis.maxValue;
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
if (axis.minValue) {
|
|
526
|
-
if (axis.type === "number") {
|
|
527
|
-
const parsedValue = parseFloat(axis.minValue);
|
|
528
|
-
if (!isNaN(parsedValue)) {
|
|
529
|
-
ret.min = parsedValue;
|
|
530
|
-
} else {
|
|
531
|
-
console.warn(`Error parsing min value ${axis.minValue}. Falling back to default.`);
|
|
532
|
-
}
|
|
533
|
-
} else if (axis.type === "date") {
|
|
534
|
-
if (typeof axis.minValue === "string" && /^\d{4}-\d{2}-\d{2}$/.test(axis.minValue)) {
|
|
535
|
-
ret.min = (/* @__PURE__ */ new Date(axis.minValue + "T00:00:00.000Z")).getTime();
|
|
536
|
-
} else {
|
|
537
|
-
ret.min = new Date(axis.minValue).getTime();
|
|
538
|
-
}
|
|
539
|
-
} else {
|
|
540
|
-
ret.min = axis.minValue;
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
return ret;
|
|
544
|
-
}
|
|
545
|
-
function formatTick(value, format, type) {
|
|
546
|
-
return formatValue(value, format, type);
|
|
547
|
-
}
|
|
548
|
-
function ChartContent({
|
|
549
|
-
title,
|
|
550
|
-
subtitle,
|
|
551
|
-
data,
|
|
552
|
-
displayConfig,
|
|
553
|
-
dataConfig,
|
|
554
|
-
ChartComponent,
|
|
555
|
-
PointComponent,
|
|
556
|
-
disableAnimation,
|
|
557
|
-
onZoomChange,
|
|
558
|
-
stacked,
|
|
559
|
-
enableDownload = true,
|
|
560
|
-
onDownloadSuccess,
|
|
561
|
-
onDownloadError
|
|
562
|
-
}) {
|
|
563
|
-
const {
|
|
564
|
-
zoomState,
|
|
565
|
-
customDomain: zoomDomain,
|
|
566
|
-
handlers
|
|
567
|
-
} = useChartZoom({
|
|
568
|
-
onZoomChange
|
|
569
|
-
});
|
|
570
|
-
const handlePngSuccess = useCallback2(
|
|
571
|
-
(dataUrl) => {
|
|
572
|
-
const fileName = `${title.toLowerCase().replace(/\s+/g, "-")}.png`;
|
|
573
|
-
const link = document.createElement("a");
|
|
574
|
-
link.download = fileName;
|
|
575
|
-
link.href = dataUrl;
|
|
576
|
-
link.click();
|
|
577
|
-
onDownloadSuccess?.(fileName);
|
|
578
|
-
},
|
|
579
|
-
[title, onDownloadSuccess]
|
|
580
|
-
);
|
|
581
|
-
const handlePngError = useCallback2(
|
|
582
|
-
(error) => {
|
|
583
|
-
console.error("Error converting chart to image:", error);
|
|
584
|
-
onDownloadError?.(error);
|
|
585
|
-
},
|
|
586
|
-
[onDownloadError]
|
|
587
|
-
);
|
|
588
|
-
const [{ isLoading: isDownloading }, convertToPng, chartRef] = useToPng({
|
|
589
|
-
onSuccess: handlePngSuccess,
|
|
590
|
-
onError: handlePngError
|
|
591
|
-
});
|
|
592
|
-
const handleDownload = useCallback2(async () => {
|
|
593
|
-
convertToPng();
|
|
594
|
-
}, [convertToPng]);
|
|
595
|
-
const xDomains = useMemo3(() => formatDomain(dataConfig.xAxis), [dataConfig.xAxis]);
|
|
596
|
-
const yDomains = useMemo3(
|
|
597
|
-
() => dataConfig.yAxes.map((axis) => formatDomain(axis)),
|
|
598
|
-
[dataConfig.yAxes]
|
|
599
|
-
);
|
|
600
|
-
const chartData = useMemo3(() => {
|
|
601
|
-
if (!data) return [];
|
|
602
|
-
if (dataConfig.chartType === "histogram") {
|
|
603
|
-
return data.map((item) => ({
|
|
604
|
-
[dataConfig.xAxis.key]: (item.binStart + item.binEnd) / 2,
|
|
605
|
-
frequency: item.frequency,
|
|
606
|
-
binStart: item.binStart,
|
|
607
|
-
binEnd: item.binEnd
|
|
608
|
-
}));
|
|
609
|
-
} else if (dataConfig.xAxis.type === "number") {
|
|
610
|
-
return data.filter((item) => !isNaN(item[dataConfig.xAxis.key]));
|
|
611
|
-
} else if (dataConfig.xAxis.type === "date") {
|
|
612
|
-
return data.filter((item) => !isNaN(item[dataConfig.xAxis.key]));
|
|
613
|
-
}
|
|
614
|
-
return data;
|
|
615
|
-
}, [data, dataConfig.xAxis.key, dataConfig.chartType, dataConfig.xAxis.type]);
|
|
616
|
-
const calculateDataBounds = useCallback2((data2, key) => {
|
|
617
|
-
if (!data2?.length) return { min: null, max: null };
|
|
618
|
-
const values = data2.map((item) => Number(item[key])).filter((v) => !isNaN(v));
|
|
619
|
-
return {
|
|
620
|
-
min: Math.min(...values),
|
|
621
|
-
max: Math.max(...values)
|
|
622
|
-
};
|
|
623
|
-
}, []);
|
|
624
|
-
const finalDomains = useMemo3(
|
|
625
|
-
() => ({
|
|
626
|
-
x: zoomDomain.x[0] !== null && zoomDomain.x[1] !== null ? [zoomDomain.x[0], zoomDomain.x[1]] : (() => {
|
|
627
|
-
if (xDomains.min !== null && xDomains.max !== null) {
|
|
628
|
-
return [xDomains.min, xDomains.max];
|
|
629
|
-
}
|
|
630
|
-
const bounds = calculateDataBounds(chartData, dataConfig.xAxis.key);
|
|
631
|
-
return [bounds.min ?? "auto", bounds.max ?? "auto"];
|
|
632
|
-
})(),
|
|
633
|
-
y: dataConfig.yAxes.map((axis, index) => {
|
|
634
|
-
if (zoomDomain.y[0] !== null && zoomDomain.y[1] !== null) {
|
|
635
|
-
return [zoomDomain.y[0], zoomDomain.y[1]];
|
|
636
|
-
}
|
|
637
|
-
const seriesForAxis = dataConfig.series.filter((s) => (s.axisIndex || 0) === index);
|
|
638
|
-
const dataBounds = seriesForAxis.reduce(
|
|
639
|
-
(acc, series) => {
|
|
640
|
-
const bounds = calculateDataBounds(chartData, series.key);
|
|
641
|
-
return {
|
|
642
|
-
min: acc.min === null ? bounds.min : bounds.min === null ? acc.min : Math.min(acc.min, bounds.min),
|
|
643
|
-
max: acc.max === null ? bounds.max : bounds.max === null ? acc.max : Math.max(acc.max, bounds.max)
|
|
644
|
-
};
|
|
645
|
-
},
|
|
646
|
-
{ min: null, max: null }
|
|
647
|
-
);
|
|
648
|
-
if (axis.type === "number" && axis.maxValue) {
|
|
649
|
-
const maxValue = parseFloat(axis.maxValue);
|
|
650
|
-
if (dataBounds.max === null || maxValue <= dataBounds.max * 1.5) {
|
|
651
|
-
return [
|
|
652
|
-
yDomains[index].min ?? dataBounds.min ?? "auto",
|
|
653
|
-
yDomains[index].max ?? dataBounds.max ?? "auto"
|
|
654
|
-
];
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
return [
|
|
658
|
-
yDomains[index].min ?? dataBounds.min ?? "auto",
|
|
659
|
-
yDomains[index].max ?? dataBounds.max ?? "auto"
|
|
660
|
-
];
|
|
661
|
-
})
|
|
662
|
-
}),
|
|
663
|
-
[
|
|
664
|
-
zoomDomain.x,
|
|
665
|
-
zoomDomain.y,
|
|
666
|
-
xDomains,
|
|
667
|
-
yDomains,
|
|
668
|
-
dataConfig.series,
|
|
669
|
-
dataConfig.yAxes,
|
|
670
|
-
dataConfig.xAxis.key,
|
|
671
|
-
chartData,
|
|
672
|
-
calculateDataBounds
|
|
673
|
-
]
|
|
674
|
-
);
|
|
675
|
-
const tooltipFormatter = useCallback2(
|
|
676
|
-
(value, name, props) => {
|
|
677
|
-
if (props.dataKey === dataConfig.xAxis.key) {
|
|
678
|
-
return formatTick(value, dataConfig.xAxis.format, dataConfig.xAxis.type);
|
|
679
|
-
}
|
|
680
|
-
const originalSeries = dataConfig.series.find((s) => s.key === props.dataKey);
|
|
681
|
-
const displayName = originalSeries?.name || String(name).replace(/^dataset_\d+_/, "");
|
|
682
|
-
if (dataConfig.chartType === "histogram") {
|
|
683
|
-
const item = props.payload;
|
|
684
|
-
if (item.binStart !== void 0) {
|
|
685
|
-
const formattedStart = formatTick(
|
|
686
|
-
item.binStart,
|
|
687
|
-
dataConfig.xAxis.format,
|
|
688
|
-
dataConfig.xAxis.type
|
|
689
|
-
);
|
|
690
|
-
const formattedEnd = formatTick(
|
|
691
|
-
item.binEnd,
|
|
692
|
-
dataConfig.xAxis.format,
|
|
693
|
-
dataConfig.xAxis.type
|
|
694
|
-
);
|
|
695
|
-
return `Count: ${value} (${formattedStart} - ${formattedEnd})`;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
return `${displayName}: ${value}`;
|
|
699
|
-
},
|
|
700
|
-
[dataConfig.xAxis, dataConfig.series, dataConfig.chartType]
|
|
701
|
-
);
|
|
702
|
-
const [hasAnimated, setHasAnimated] = useState2(false);
|
|
703
|
-
useEffect(() => {
|
|
704
|
-
const timer = setTimeout(() => {
|
|
705
|
-
setHasAnimated(true);
|
|
706
|
-
}, 1700);
|
|
707
|
-
return () => clearTimeout(timer);
|
|
708
|
-
}, []);
|
|
709
|
-
const shouldDisableAnimation = useMemo3(() => {
|
|
710
|
-
if (disableAnimation) return true;
|
|
711
|
-
if ((data?.length || 0) > 100) return true;
|
|
712
|
-
if (hasAnimated) return true;
|
|
713
|
-
return false;
|
|
714
|
-
}, [disableAnimation, data?.length, hasAnimated]);
|
|
715
|
-
return /* @__PURE__ */ jsxs2("div", { className: "items-center mt-0 flex flex-col gap-0", children: [
|
|
716
|
-
/* @__PURE__ */ jsxs2("div", { className: "w-full items-center mb-2 relative", children: [
|
|
717
|
-
/* @__PURE__ */ jsx3("h2", { className: "text-center text-base pt-0 mt-0 mb-2", children: title }),
|
|
718
|
-
enableDownload && /* @__PURE__ */ jsx3(
|
|
719
|
-
"button",
|
|
720
|
-
{
|
|
721
|
-
onClick: handleDownload,
|
|
722
|
-
disabled: isDownloading,
|
|
723
|
-
className: "text-sm text-gray-500 hover:text-gray-700 disabled:opacity-50 h-8 absolute right-0 top-[-5px] px-2 py-1 border rounded hover:bg-gray-50",
|
|
724
|
-
title: "Download chart as PNG",
|
|
725
|
-
children: /* @__PURE__ */ jsx3(Download, { className: "w-4 h-4" })
|
|
726
|
-
}
|
|
727
|
-
)
|
|
728
|
-
] }),
|
|
729
|
-
subtitle && /* @__PURE__ */ jsx3("p", { className: "text-center text-sm text-muted-foreground mb-2", children: subtitle }),
|
|
730
|
-
/* @__PURE__ */ jsx3(
|
|
731
|
-
ChartContainer,
|
|
732
|
-
{
|
|
733
|
-
ref: chartRef,
|
|
734
|
-
config: displayConfig,
|
|
735
|
-
className: "w-full mb-4 border border-accent p-4 rounded-md",
|
|
736
|
-
debounceResize: true,
|
|
737
|
-
children: /* @__PURE__ */ jsxs2(
|
|
738
|
-
ChartComponent,
|
|
739
|
-
{
|
|
740
|
-
accessibilityLayer: true,
|
|
741
|
-
data: chartData,
|
|
742
|
-
isAnimationActive: !shouldDisableAnimation,
|
|
743
|
-
onMouseDown: handlers.onZoomStart,
|
|
744
|
-
onMouseMove: handlers.onZoomMove,
|
|
745
|
-
onMouseUp: handlers.onZoomEnd,
|
|
746
|
-
onDoubleClick: handlers.onResetZoom,
|
|
747
|
-
style: {
|
|
748
|
-
userSelect: "none",
|
|
749
|
-
cursor: "crosshair"
|
|
750
|
-
},
|
|
751
|
-
children: [
|
|
752
|
-
/* @__PURE__ */ jsx3(CartesianGrid, { vertical: false }),
|
|
753
|
-
/* @__PURE__ */ jsx3(
|
|
754
|
-
XAxis,
|
|
755
|
-
{
|
|
756
|
-
dataKey: dataConfig.xAxis.key,
|
|
757
|
-
domain: finalDomains.x,
|
|
758
|
-
type: dataConfig.xAxis.type === "date" || !dataConfig.xAxis.type ? "number" : dataConfig.xAxis.type,
|
|
759
|
-
tickFormatter: (value) => {
|
|
760
|
-
return formatTick(value, dataConfig.xAxis.format, dataConfig.xAxis.type);
|
|
761
|
-
},
|
|
762
|
-
tickLine: false,
|
|
763
|
-
tickMargin: 10,
|
|
764
|
-
height: 50,
|
|
765
|
-
axisLine: false,
|
|
766
|
-
allowDataOverflow: true,
|
|
767
|
-
children: /* @__PURE__ */ jsx3(
|
|
768
|
-
Label,
|
|
769
|
-
{
|
|
770
|
-
value: dataConfig.xAxis.label,
|
|
771
|
-
position: "bottom",
|
|
772
|
-
offset: -10,
|
|
773
|
-
style: { textAnchor: "middle" }
|
|
774
|
-
}
|
|
775
|
-
)
|
|
776
|
-
}
|
|
777
|
-
),
|
|
778
|
-
dataConfig.yAxes.map((yAxis, index) => /* @__PURE__ */ jsx3(
|
|
779
|
-
YAxis,
|
|
780
|
-
{
|
|
781
|
-
yAxisId: index,
|
|
782
|
-
orientation: index === 0 ? "left" : "right",
|
|
783
|
-
domain: stacked ? void 0 : finalDomains.y[index],
|
|
784
|
-
type: yAxis.type === "date" || !yAxis.type ? "number" : yAxis.type,
|
|
785
|
-
tickFormatter: (value) => formatTick(value, yAxis.format, yAxis.type),
|
|
786
|
-
allowDataOverflow: true,
|
|
787
|
-
children: /* @__PURE__ */ jsx3(
|
|
788
|
-
Label,
|
|
789
|
-
{
|
|
790
|
-
value: yAxis.label,
|
|
791
|
-
position: index === 0 ? "insideLeft" : "insideRight",
|
|
792
|
-
angle: -90,
|
|
793
|
-
style: { textAnchor: "middle" }
|
|
794
|
-
}
|
|
795
|
-
)
|
|
796
|
-
},
|
|
797
|
-
`y-axis-${index}`
|
|
798
|
-
)),
|
|
799
|
-
/* @__PURE__ */ jsx3(
|
|
800
|
-
ChartTooltip,
|
|
801
|
-
{
|
|
802
|
-
content: (props) => /* @__PURE__ */ jsx3(
|
|
803
|
-
ChartTooltipContent,
|
|
804
|
-
{
|
|
805
|
-
...props,
|
|
806
|
-
formatter: tooltipFormatter,
|
|
807
|
-
labelFormatter: (label, payload) => {
|
|
808
|
-
if (payload && payload.length > 0) {
|
|
809
|
-
const xValue = payload[0].payload[dataConfig.xAxis.key];
|
|
810
|
-
const formattedValue = formatTick(
|
|
811
|
-
xValue,
|
|
812
|
-
dataConfig.xAxis.format,
|
|
813
|
-
dataConfig.xAxis.type
|
|
814
|
-
);
|
|
815
|
-
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col", children: [
|
|
816
|
-
/* @__PURE__ */ jsx3("span", { children: dataConfig.xAxis.label }),
|
|
817
|
-
/* @__PURE__ */ jsx3("span", { className: "font-mono tabular-nums", children: formattedValue })
|
|
818
|
-
] });
|
|
819
|
-
}
|
|
820
|
-
return label;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
)
|
|
824
|
-
}
|
|
825
|
-
),
|
|
826
|
-
/* @__PURE__ */ jsx3(ChartLegend, { content: (props) => /* @__PURE__ */ jsx3(ChartLegendContent, { ...props }), verticalAlign: "top" }),
|
|
827
|
-
dataConfig.series.map((series) => /* @__PURE__ */ jsx3(
|
|
828
|
-
PointComponent,
|
|
829
|
-
{
|
|
830
|
-
dataKey: series.key,
|
|
831
|
-
yAxisId: series.axisIndex || 0,
|
|
832
|
-
fill: series.color || "blue",
|
|
833
|
-
stroke: series.color || "blue",
|
|
834
|
-
dot: {
|
|
835
|
-
fill: series.color || "blue",
|
|
836
|
-
stroke: series.color || "blue"
|
|
837
|
-
},
|
|
838
|
-
radius: 4,
|
|
839
|
-
name: series.name,
|
|
840
|
-
isAnimationActive: !shouldDisableAnimation,
|
|
841
|
-
animationDuration: 1500,
|
|
842
|
-
animationBegin: 0,
|
|
843
|
-
stackId: dataConfig.chartType === "bar" && stacked ? "stack" : void 0
|
|
844
|
-
},
|
|
845
|
-
`${series.key}-${stacked ? "stacked" : "unstacked"}`
|
|
846
|
-
)),
|
|
847
|
-
zoomState.refAreaLeft && zoomState.refAreaRight && zoomState.refAreaTop && zoomState.refAreaBottom && /* @__PURE__ */ jsx3(
|
|
848
|
-
ReferenceArea,
|
|
849
|
-
{
|
|
850
|
-
x1: zoomState.refAreaLeft,
|
|
851
|
-
x2: zoomState.refAreaRight,
|
|
852
|
-
y1: zoomState.refAreaTop,
|
|
853
|
-
y2: zoomState.refAreaBottom,
|
|
854
|
-
strokeOpacity: 0.2,
|
|
855
|
-
stroke: "currentColor",
|
|
856
|
-
fill: "currentColor",
|
|
857
|
-
fillOpacity: 0.02,
|
|
858
|
-
style: { pointerEvents: "none" }
|
|
859
|
-
}
|
|
860
|
-
)
|
|
861
|
-
]
|
|
862
|
-
}
|
|
863
|
-
)
|
|
864
|
-
}
|
|
865
|
-
),
|
|
866
|
-
zoomDomain.x[0] !== null && /* @__PURE__ */ jsx3(
|
|
867
|
-
"button",
|
|
868
|
-
{
|
|
869
|
-
onClick: handlers.onResetZoom,
|
|
870
|
-
className: "text-sm text-gray-500 hover:text-gray-700 mt-2 px-3 py-1 border rounded hover:bg-gray-50",
|
|
871
|
-
children: "Reset Zoom"
|
|
872
|
-
}
|
|
873
|
-
)
|
|
874
|
-
] });
|
|
875
|
-
}
|
|
876
|
-
function Chart(props) {
|
|
877
|
-
return /* @__PURE__ */ jsx3(ErrorBoundary, { fallback: /* @__PURE__ */ jsx3("div", { className: "text-red-500", children: "Failed to load chart" }), children: /* @__PURE__ */ jsx3(ChartContent, { ...props }) });
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
// src/components/charts/bar-chart.tsx
|
|
881
|
-
import { Bar, BarChart as RechartsBarChart } from "recharts";
|
|
882
|
-
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
883
|
-
function BarChart(props) {
|
|
884
|
-
return /* @__PURE__ */ jsx4(Chart, { ...props, ChartComponent: RechartsBarChart, PointComponent: Bar });
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
// src/components/charts/line-chart.tsx
|
|
888
|
-
import { Line, LineChart as RechartsLineChart } from "recharts";
|
|
889
|
-
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
890
|
-
function LineChart(props) {
|
|
891
|
-
return /* @__PURE__ */ jsx5(Chart, { ...props, ChartComponent: RechartsLineChart, PointComponent: Line });
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
// src/components/charts/pie-chart.tsx
|
|
895
|
-
import { useMemo as useMemo4 } from "react";
|
|
896
|
-
import { Cell, Legend as Legend2, Pie, PieChart as RechartsPieChart, Tooltip as Tooltip2 } from "recharts";
|
|
897
|
-
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
898
|
-
var generateColorVariation = (baseColor, index, total) => {
|
|
899
|
-
let r = parseInt(baseColor.slice(1, 3), 16) / 255;
|
|
900
|
-
let g = parseInt(baseColor.slice(3, 5), 16) / 255;
|
|
901
|
-
let b = parseInt(baseColor.slice(5, 7), 16) / 255;
|
|
902
|
-
const max = Math.max(r, g, b);
|
|
903
|
-
const min = Math.min(r, g, b);
|
|
904
|
-
let h, s, l = (max + min) / 2;
|
|
905
|
-
if (max === min) {
|
|
906
|
-
h = s = 0;
|
|
907
|
-
} else {
|
|
908
|
-
const d = max - min;
|
|
909
|
-
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
910
|
-
switch (max) {
|
|
911
|
-
case r:
|
|
912
|
-
h = (g - b) / d + (g < b ? 6 : 0);
|
|
913
|
-
break;
|
|
914
|
-
case g:
|
|
915
|
-
h = (b - r) / d + 2;
|
|
916
|
-
break;
|
|
917
|
-
case b:
|
|
918
|
-
h = (r - g) / d + 4;
|
|
919
|
-
break;
|
|
920
|
-
default:
|
|
921
|
-
h = 0;
|
|
922
|
-
}
|
|
923
|
-
h /= 6;
|
|
924
|
-
}
|
|
925
|
-
const progress = index / total;
|
|
926
|
-
const hue = h * 360 + (progress * 40 - 20);
|
|
927
|
-
const saturation = Math.min(100, s * 100 + progress * 25);
|
|
928
|
-
const lightness = Math.max(35, Math.min(65, l * 100 - progress * 20));
|
|
929
|
-
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
|
|
930
|
-
};
|
|
931
|
-
function PieChartContent({ title, subtitle, data, displayConfig, dataConfig }) {
|
|
932
|
-
const baseColor = dataConfig.series[0]?.color || "blue";
|
|
933
|
-
const pieData = useMemo4(() => {
|
|
934
|
-
return data.reduce((acc, item) => {
|
|
935
|
-
dataConfig.series.forEach((series) => {
|
|
936
|
-
const prefixedKey = series.key;
|
|
937
|
-
const name = String(item[dataConfig.xAxis.key] || "Unknown");
|
|
938
|
-
const value = parseFloat(item[prefixedKey] || "0");
|
|
939
|
-
if (!isNaN(value)) {
|
|
940
|
-
acc.push({
|
|
941
|
-
name,
|
|
942
|
-
value,
|
|
943
|
-
seriesId: prefixedKey,
|
|
944
|
-
// For pie charts, we want to use the category name (medium) as the display name
|
|
945
|
-
// instead of the series name (Users)
|
|
946
|
-
displayName: name
|
|
947
|
-
});
|
|
948
|
-
}
|
|
949
|
-
});
|
|
950
|
-
return acc;
|
|
951
|
-
}, []).sort((a, b) => b.value - a.value);
|
|
952
|
-
}, [data, dataConfig.series, dataConfig.xAxis.key]);
|
|
953
|
-
return /* @__PURE__ */ jsxs3("div", { className: "items-center", children: [
|
|
954
|
-
/* @__PURE__ */ jsx6("h2", { className: "text-center text-base mb-2", children: title }),
|
|
955
|
-
subtitle && /* @__PURE__ */ jsx6("p", { className: "text-center text-sm text-muted-foreground mb-2", children: subtitle }),
|
|
956
|
-
/* @__PURE__ */ jsx6(
|
|
957
|
-
ChartContainer,
|
|
958
|
-
{
|
|
959
|
-
config: displayConfig,
|
|
960
|
-
className: "w-full mb-4 border border-accent rounded-md",
|
|
961
|
-
children: /* @__PURE__ */ jsxs3(RechartsPieChart, { width: 400, height: 400, children: [
|
|
962
|
-
/* @__PURE__ */ jsx6(
|
|
963
|
-
Pie,
|
|
964
|
-
{
|
|
965
|
-
data: pieData,
|
|
966
|
-
dataKey: "value",
|
|
967
|
-
nameKey: "displayName",
|
|
968
|
-
cx: "50%",
|
|
969
|
-
cy: "50%",
|
|
970
|
-
outerRadius: 150,
|
|
971
|
-
label: (props) => `${props.displayName}: ${props.value}%`,
|
|
972
|
-
children: pieData.map((_entry, index) => /* @__PURE__ */ jsx6(
|
|
973
|
-
Cell,
|
|
974
|
-
{
|
|
975
|
-
fill: index === 0 ? baseColor : generateColorVariation(baseColor, index, pieData.length)
|
|
976
|
-
},
|
|
977
|
-
`cell-${index}`
|
|
978
|
-
))
|
|
979
|
-
}
|
|
980
|
-
),
|
|
981
|
-
/* @__PURE__ */ jsx6(Tooltip2, { formatter: (value, name) => [`${value}%`, name] }),
|
|
982
|
-
/* @__PURE__ */ jsx6(Legend2, {})
|
|
983
|
-
] })
|
|
984
|
-
}
|
|
985
|
-
)
|
|
986
|
-
] });
|
|
987
|
-
}
|
|
988
|
-
function PieChart(props) {
|
|
989
|
-
return /* @__PURE__ */ jsx6(ErrorBoundary, { fallback: /* @__PURE__ */ jsx6("div", { className: "text-red-500", children: "Failed to load chart" }), children: /* @__PURE__ */ jsx6(PieChartContent, { ...props }) });
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
// src/components/charts/scatter-chart.tsx
|
|
993
|
-
import { Scatter, ScatterChart as RechartsScatterChart } from "recharts";
|
|
994
|
-
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
995
|
-
function ScatterChart(props) {
|
|
996
|
-
return /* @__PURE__ */ jsx7(Chart, { ...props, ChartComponent: RechartsScatterChart, PointComponent: Scatter });
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
// src/components/charts/heatmap-chart.tsx
|
|
1000
|
-
import { Scatter as Scatter2, ScatterChart as RechartsScatterChart2 } from "recharts";
|
|
1001
|
-
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1002
|
-
var HeatmapCell = (props) => {
|
|
1003
|
-
const { cx, cy, payload, xAxis, yAxis } = props;
|
|
1004
|
-
const value = payload.value || payload.z || 0;
|
|
1005
|
-
const intensity = Math.min(1, Math.max(0, value / 100));
|
|
1006
|
-
const color = `hsl(${240 - intensity * 240}, 70%, 50%)`;
|
|
1007
|
-
const cellWidth = xAxis.scale.bandwidth ? xAxis.scale.bandwidth() : 20;
|
|
1008
|
-
const cellHeight = yAxis.scale.bandwidth ? yAxis.scale.bandwidth() : 20;
|
|
1009
|
-
return /* @__PURE__ */ jsx8(
|
|
1010
|
-
"rect",
|
|
1011
|
-
{
|
|
1012
|
-
x: cx - cellWidth / 2,
|
|
1013
|
-
y: cy - cellHeight / 2,
|
|
1014
|
-
width: cellWidth,
|
|
1015
|
-
height: cellHeight,
|
|
1016
|
-
fill: color,
|
|
1017
|
-
fillOpacity: 0.8,
|
|
1018
|
-
stroke: "#fff",
|
|
1019
|
-
strokeWidth: 1
|
|
1020
|
-
}
|
|
1021
|
-
);
|
|
1022
|
-
};
|
|
1023
|
-
var HeatmapScatter = (props) => {
|
|
1024
|
-
return /* @__PURE__ */ jsx8(Scatter2, { ...props, shape: HeatmapCell });
|
|
1025
|
-
};
|
|
1026
|
-
function HeatmapChart(props) {
|
|
1027
|
-
return /* @__PURE__ */ jsx8(Chart, { ...props, ChartComponent: RechartsScatterChart2, PointComponent: HeatmapScatter });
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
// src/components/charts/dataset-chart.tsx
|
|
1031
|
-
import isEqual from "lodash/isEqual";
|
|
1032
|
-
import { parse as dateParse2, isValid as isValid2 } from "date-fns";
|
|
1033
|
-
import React5, { useEffect as useEffect2, useMemo as useMemo5, useRef, useState as useState3 } from "react";
|
|
1034
|
-
import { useDeepCompareMemo } from "use-deep-compare";
|
|
1035
|
-
|
|
1036
|
-
// src/hooks/use-dataset-contents.ts
|
|
1037
|
-
import { useQuery, useQueries } from "@tanstack/react-query";
|
|
1038
|
-
async function fetchDatasetContents(config, slug, _invocationId) {
|
|
1039
|
-
if (config.dataFetcher) {
|
|
1040
|
-
return config.dataFetcher.fetchDatasetContents(slug, _invocationId);
|
|
1041
|
-
}
|
|
1042
|
-
let url;
|
|
1043
|
-
const headers = {
|
|
1044
|
-
"Content-Type": "application/json"
|
|
1045
|
-
};
|
|
1046
|
-
if (config.sessionToken) {
|
|
1047
|
-
url = `${config.baseUrl}/datasets/${encodeURIComponent(slug)}/query-with-session?limit=1000`;
|
|
1048
|
-
headers["Authorization"] = `Bearer ${config.sessionToken}`;
|
|
1049
|
-
} else {
|
|
1050
|
-
url = `${config.baseUrl}/datasets/${encodeURIComponent(slug)}/query?limit=1000`;
|
|
1051
|
-
if (config.authToken) {
|
|
1052
|
-
headers["Authorization"] = `Bearer ${config.authToken}`;
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
const response = await fetch(url, { headers });
|
|
1056
|
-
if (!response.ok) {
|
|
1057
|
-
throw new Error(`Failed to fetch dataset contents: ${response.statusText}`);
|
|
1058
|
-
}
|
|
1059
|
-
const result = await response.json();
|
|
1060
|
-
if (!result.Columns || !result.Rows || result.Columns.length === 0) {
|
|
1061
|
-
return [];
|
|
1062
|
-
}
|
|
1063
|
-
return result.Rows.map((row) => {
|
|
1064
|
-
const obj = {};
|
|
1065
|
-
result.Columns.forEach((col, index) => {
|
|
1066
|
-
obj[col] = row[index];
|
|
1067
|
-
});
|
|
1068
|
-
return obj;
|
|
1069
|
-
});
|
|
1070
|
-
}
|
|
1071
|
-
function useDatasetContents(datasetSlug, invocationId) {
|
|
1072
|
-
const config = useErdoConfig();
|
|
1073
|
-
return useQuery({
|
|
1074
|
-
queryKey: ["datasetContents", datasetSlug, invocationId],
|
|
1075
|
-
queryFn: () => fetchDatasetContents(config, datasetSlug, invocationId),
|
|
1076
|
-
enabled: !!datasetSlug && !!invocationId
|
|
1077
|
-
});
|
|
1078
|
-
}
|
|
1079
|
-
function useMultipleDatasetContents(datasetSlugs, invocationId) {
|
|
1080
|
-
const config = useErdoConfig();
|
|
1081
|
-
return useQueries({
|
|
1082
|
-
queries: datasetSlugs.map((slug) => ({
|
|
1083
|
-
queryKey: ["datasetContents", slug, invocationId],
|
|
1084
|
-
queryFn: () => fetchDatasetContents(config, slug, invocationId),
|
|
1085
|
-
enabled: !!slug && !!invocationId
|
|
1086
|
-
}))
|
|
1087
|
-
});
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
// src/lib/dataset-key-resolver.ts
|
|
1091
|
-
function toSnakeCase(str) {
|
|
1092
|
-
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`).replace(/^_/, "");
|
|
1093
|
-
}
|
|
1094
|
-
function resolveKeyFromData(dataRows, configKey) {
|
|
1095
|
-
if (!dataRows.length) return configKey;
|
|
1096
|
-
const sampleRow = dataRows[0];
|
|
1097
|
-
if (sampleRow[configKey] !== void 0) {
|
|
1098
|
-
return configKey;
|
|
1099
|
-
}
|
|
1100
|
-
const lowerKey = configKey.toLowerCase();
|
|
1101
|
-
if (sampleRow[lowerKey] !== void 0) {
|
|
1102
|
-
return lowerKey;
|
|
1103
|
-
}
|
|
1104
|
-
const snakeKey = toSnakeCase(configKey);
|
|
1105
|
-
if (sampleRow[snakeKey] !== void 0) {
|
|
1106
|
-
return snakeKey;
|
|
1107
|
-
}
|
|
1108
|
-
const normalizedConfigKey = configKey.toLowerCase().replace(/_/g, "");
|
|
1109
|
-
const matchingKey = Object.keys(sampleRow).find(
|
|
1110
|
-
(k) => k.toLowerCase().replace(/_/g, "") === normalizedConfigKey
|
|
1111
|
-
);
|
|
1112
|
-
return matchingKey || configKey;
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
// src/components/charts/dataset-chart.tsx
|
|
1116
|
-
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1117
|
-
function getDateFormats() {
|
|
1118
|
-
return ["yyyy-MM-dd", "yyyyMMdd", "yyyy-MM-dd'T'HH:mm:ss", "yyyyMMddHHmmss"];
|
|
1119
|
-
}
|
|
1120
|
-
function parseDate(value) {
|
|
1121
|
-
if (!value) return null;
|
|
1122
|
-
if (typeof value === "string") {
|
|
1123
|
-
const dateOnlyRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
1124
|
-
if (dateOnlyRegex.test(value)) {
|
|
1125
|
-
const date2 = /* @__PURE__ */ new Date(value + "T00:00:00.000Z");
|
|
1126
|
-
if (isValid2(date2)) {
|
|
1127
|
-
return date2.getTime();
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
const formats = getDateFormats();
|
|
1131
|
-
for (const format of formats) {
|
|
1132
|
-
const parsed = dateParse2(value, format, /* @__PURE__ */ new Date());
|
|
1133
|
-
if (isValid2(parsed)) {
|
|
1134
|
-
return parsed.getTime();
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
const date = new Date(value);
|
|
1139
|
-
if (isValid2(date)) {
|
|
1140
|
-
return date.getTime();
|
|
1141
|
-
}
|
|
1142
|
-
return null;
|
|
1143
|
-
}
|
|
1144
|
-
function getValue(row, key, type, arrayIndex) {
|
|
1145
|
-
const rawValue = key === "index" && row[key] === void 0 ? arrayIndex : row[key];
|
|
1146
|
-
const value = type === "date" ? parseDate(rawValue) : type === "number" ? parseFloat(rawValue) : rawValue;
|
|
1147
|
-
return value;
|
|
1148
|
-
}
|
|
1149
|
-
function getValueType(key, xAxis, yAxes) {
|
|
1150
|
-
if (key === xAxis.key) return xAxis.type || "category";
|
|
1151
|
-
const yAxis = yAxes.find((axis) => axis.key === key);
|
|
1152
|
-
if (yAxis) return yAxis.type || "number";
|
|
1153
|
-
return "category";
|
|
1154
|
-
}
|
|
1155
|
-
function applySortConditions(data, xAxis, yAxes, sortConditions) {
|
|
1156
|
-
if (!sortConditions || sortConditions.length === 0) return data;
|
|
1157
|
-
return [...data].sort((a, b) => {
|
|
1158
|
-
for (const sortCond of sortConditions) {
|
|
1159
|
-
const valueType = getValueType(sortCond.key, xAxis, yAxes);
|
|
1160
|
-
const aVal = getValue(a, sortCond.key, valueType, a.index);
|
|
1161
|
-
const bVal = getValue(b, sortCond.key, valueType, b.index);
|
|
1162
|
-
if (aVal === bVal) continue;
|
|
1163
|
-
const comparison = (() => {
|
|
1164
|
-
if (typeof aVal === "number" && typeof bVal === "number") {
|
|
1165
|
-
return aVal - bVal;
|
|
1166
|
-
}
|
|
1167
|
-
if (aVal instanceof Date && bVal instanceof Date) {
|
|
1168
|
-
return aVal.getTime() - bVal.getTime();
|
|
1169
|
-
}
|
|
1170
|
-
return String(aVal).localeCompare(String(bVal));
|
|
1171
|
-
})();
|
|
1172
|
-
return sortCond.direction === "asc" ? comparison : -comparison;
|
|
1173
|
-
}
|
|
1174
|
-
return 0;
|
|
1175
|
-
});
|
|
1176
|
-
}
|
|
1177
|
-
function sampleData(data, targetPoints) {
|
|
1178
|
-
const step = Math.ceil(data.length / targetPoints);
|
|
1179
|
-
const sampledData = [data[0]];
|
|
1180
|
-
for (let i = step; i < data.length - 1; i += step) {
|
|
1181
|
-
sampledData.push(data[i]);
|
|
1182
|
-
}
|
|
1183
|
-
if (sampledData[sampledData.length - 1] !== data[data.length - 1]) {
|
|
1184
|
-
sampledData.push(data[data.length - 1]);
|
|
1185
|
-
}
|
|
1186
|
-
return sampledData;
|
|
1187
|
-
}
|
|
1188
|
-
function aggregateData(data, xKey, series, targetPoints, xAxis, yAxes, sortConditions) {
|
|
1189
|
-
const groups = data.reduce(
|
|
1190
|
-
(acc, item) => {
|
|
1191
|
-
const key = item[xKey];
|
|
1192
|
-
if (!acc[key]) {
|
|
1193
|
-
acc[key] = [];
|
|
1194
|
-
}
|
|
1195
|
-
acc[key].push(item);
|
|
1196
|
-
return acc;
|
|
1197
|
-
},
|
|
1198
|
-
{}
|
|
1199
|
-
);
|
|
1200
|
-
const groupEntries = Object.entries(groups);
|
|
1201
|
-
if (groupEntries.length > targetPoints) {
|
|
1202
|
-
const step = Math.ceil(groupEntries.length / targetPoints);
|
|
1203
|
-
const aggregatedData2 = groupEntries.reduce(
|
|
1204
|
-
(acc, [key, items], index) => {
|
|
1205
|
-
const binIndex = Math.floor(index / step);
|
|
1206
|
-
if (!acc[binIndex]) {
|
|
1207
|
-
acc[binIndex] = { key, items: [] };
|
|
1208
|
-
}
|
|
1209
|
-
acc[binIndex].items.push(...items);
|
|
1210
|
-
return acc;
|
|
1211
|
-
},
|
|
1212
|
-
[]
|
|
1213
|
-
).map(({ key, items }) => ({
|
|
1214
|
-
[xKey]: key,
|
|
1215
|
-
...series.reduce(
|
|
1216
|
-
(acc, s) => {
|
|
1217
|
-
const values = items.map((item) => parseFloat(item[s.key])).filter((v) => !isNaN(v));
|
|
1218
|
-
acc[s.key] = values.length ? values.reduce((a, b) => a + b, 0) / values.length : null;
|
|
1219
|
-
return acc;
|
|
1220
|
-
},
|
|
1221
|
-
{}
|
|
1222
|
-
)
|
|
1223
|
-
}));
|
|
1224
|
-
if (sortConditions && sortConditions.length > 0) {
|
|
1225
|
-
return applySortConditions(aggregatedData2, xAxis, yAxes, sortConditions);
|
|
1226
|
-
}
|
|
1227
|
-
return aggregatedData2;
|
|
1228
|
-
}
|
|
1229
|
-
const aggregatedData = groupEntries.map(([key, items]) => {
|
|
1230
|
-
const seriesValues = series.reduce(
|
|
1231
|
-
(acc, s) => {
|
|
1232
|
-
const values = items.map((item) => parseFloat(item[s.key])).filter((v) => !isNaN(v));
|
|
1233
|
-
acc[s.key] = values.length ? values.reduce((a, b) => a + b, 0) / values.length : null;
|
|
1234
|
-
return acc;
|
|
1235
|
-
},
|
|
1236
|
-
{}
|
|
1237
|
-
);
|
|
1238
|
-
const total = Object.values(seriesValues).filter((v) => v !== null).reduce((sum, v) => sum + v, 0);
|
|
1239
|
-
return {
|
|
1240
|
-
[xKey]: key,
|
|
1241
|
-
...seriesValues,
|
|
1242
|
-
index: total
|
|
1243
|
-
// Add index as the total
|
|
1244
|
-
};
|
|
1245
|
-
});
|
|
1246
|
-
if (sortConditions && sortConditions.length > 0) {
|
|
1247
|
-
return applySortConditions(aggregatedData, xAxis, yAxes, sortConditions);
|
|
1248
|
-
}
|
|
1249
|
-
return aggregatedData;
|
|
1250
|
-
}
|
|
1251
|
-
function binData(data, xKey, series, targetPoints) {
|
|
1252
|
-
const xValues = data.map((d) => parseFloat(d[xKey])).filter((x) => !isNaN(x));
|
|
1253
|
-
const min = Math.min(...xValues);
|
|
1254
|
-
const max = Math.max(...xValues);
|
|
1255
|
-
const binSize = (max - min) / targetPoints;
|
|
1256
|
-
const bins = Array.from({ length: targetPoints }, (_, i) => ({
|
|
1257
|
-
binStart: min + i * binSize,
|
|
1258
|
-
binEnd: min + (i + 1) * binSize,
|
|
1259
|
-
count: 0,
|
|
1260
|
-
seriesValues: series.reduce((acc, s) => {
|
|
1261
|
-
acc[s.key] = [];
|
|
1262
|
-
return acc;
|
|
1263
|
-
}, {})
|
|
1264
|
-
}));
|
|
1265
|
-
data.forEach((item) => {
|
|
1266
|
-
const x = parseFloat(item[xKey]);
|
|
1267
|
-
if (isNaN(x)) return;
|
|
1268
|
-
const binIndex = Math.min(Math.floor((x - min) / binSize), targetPoints - 1);
|
|
1269
|
-
bins[binIndex].count++;
|
|
1270
|
-
series.forEach((s) => {
|
|
1271
|
-
const value = parseFloat(item[s.key]);
|
|
1272
|
-
if (!isNaN(value)) {
|
|
1273
|
-
bins[binIndex].seriesValues[s.key].push(value);
|
|
1274
|
-
}
|
|
1275
|
-
});
|
|
1276
|
-
});
|
|
1277
|
-
return bins.map(
|
|
1278
|
-
(bin) => ({
|
|
1279
|
-
[xKey]: (bin.binStart + bin.binEnd) / 2,
|
|
1280
|
-
...series.reduce(
|
|
1281
|
-
(acc, s) => {
|
|
1282
|
-
const values = bin.seriesValues[s.key];
|
|
1283
|
-
acc[s.key] = values.length ? values.reduce((a, b) => a + b, 0) / values.length : null;
|
|
1284
|
-
return acc;
|
|
1285
|
-
},
|
|
1286
|
-
{}
|
|
1287
|
-
),
|
|
1288
|
-
count: bin.count,
|
|
1289
|
-
// Add index as total of all series values
|
|
1290
|
-
index: series.reduce((total, s) => {
|
|
1291
|
-
const values = bin.seriesValues[s.key];
|
|
1292
|
-
const avg = values.length ? values.reduce((a, b) => a + b, 0) / values.length : 0;
|
|
1293
|
-
return total + avg;
|
|
1294
|
-
}, 0)
|
|
1295
|
-
})
|
|
1296
|
-
).filter((bin) => series.some((s) => bin[s.key] !== null));
|
|
1297
|
-
}
|
|
1298
|
-
function binHistogramData(data, xKey, _series, initialBinCount, xAxis) {
|
|
1299
|
-
const values = data.map((d, i) => {
|
|
1300
|
-
const val = getValue(d, xKey, xAxis.type || "number", i);
|
|
1301
|
-
return typeof val === "number" ? val : parseFloat(val);
|
|
1302
|
-
}).filter((x) => !isNaN(x));
|
|
1303
|
-
const min = Math.min(...values);
|
|
1304
|
-
const max = Math.max(...values);
|
|
1305
|
-
const range = max - min;
|
|
1306
|
-
const binSize = range / initialBinCount;
|
|
1307
|
-
const bins = Array.from({ length: initialBinCount }, (_, i) => ({
|
|
1308
|
-
binStart: Number((min + i * binSize).toFixed(2)),
|
|
1309
|
-
binEnd: Number((min + (i + 1) * binSize).toFixed(2)),
|
|
1310
|
-
frequency: 0,
|
|
1311
|
-
[xKey]: Number((min + (i + 0.5) * binSize).toFixed(2))
|
|
1312
|
-
// Midpoint for display
|
|
1313
|
-
}));
|
|
1314
|
-
values.forEach((value) => {
|
|
1315
|
-
const binIndex = Math.min(Math.floor((value - min) / binSize), initialBinCount - 1);
|
|
1316
|
-
bins[binIndex].frequency++;
|
|
1317
|
-
});
|
|
1318
|
-
const nonEmptyBins = bins.filter((bin) => bin.frequency > 0);
|
|
1319
|
-
const emptyBinPercentage = (bins.length - nonEmptyBins.length) / bins.length * 100;
|
|
1320
|
-
if (emptyBinPercentage > 30) {
|
|
1321
|
-
return binHistogramData(data, xKey, _series, Math.floor(initialBinCount / 2), xAxis);
|
|
1322
|
-
}
|
|
1323
|
-
return nonEmptyBins;
|
|
1324
|
-
}
|
|
1325
|
-
function applyFilters(data, filters, resolvedSeriesKey, resolvedXAxisKey) {
|
|
1326
|
-
if (!filters || filters.length === 0) return data;
|
|
1327
|
-
return data.filter((item) => {
|
|
1328
|
-
return filters.every((filter) => {
|
|
1329
|
-
let actualKey = filter.key;
|
|
1330
|
-
if (resolvedSeriesKey && filter.key.toLowerCase() === resolvedSeriesKey.toLowerCase()) {
|
|
1331
|
-
actualKey = resolvedSeriesKey;
|
|
1332
|
-
} else if (resolvedXAxisKey && filter.key.toLowerCase() === resolvedXAxisKey.toLowerCase()) {
|
|
1333
|
-
actualKey = resolvedXAxisKey;
|
|
1334
|
-
}
|
|
1335
|
-
const itemValue = item[actualKey];
|
|
1336
|
-
const filterValues = Array.isArray(filter.value) ? filter.value : [filter.value];
|
|
1337
|
-
switch (filter.operator) {
|
|
1338
|
-
case "equals":
|
|
1339
|
-
return filterValues.some((v) => String(itemValue) === String(v));
|
|
1340
|
-
case "not_equals":
|
|
1341
|
-
return filterValues.every((v) => String(itemValue) !== String(v));
|
|
1342
|
-
case "greater_than":
|
|
1343
|
-
return parseFloat(String(itemValue)) > parseFloat(String(filterValues[0]));
|
|
1344
|
-
case "less_than":
|
|
1345
|
-
return parseFloat(String(itemValue)) < parseFloat(String(filterValues[0]));
|
|
1346
|
-
case "contains":
|
|
1347
|
-
return String(itemValue).toLowerCase().includes(String(filterValues[0]).toLowerCase());
|
|
1348
|
-
case "between":
|
|
1349
|
-
if (filterValues.length === 2) {
|
|
1350
|
-
const numValue = parseFloat(String(itemValue));
|
|
1351
|
-
const minValue = parseFloat(String(filterValues[0]));
|
|
1352
|
-
const maxValue = parseFloat(String(filterValues[1]));
|
|
1353
|
-
return numValue >= minValue && numValue <= maxValue;
|
|
1354
|
-
}
|
|
1355
|
-
return true;
|
|
1356
|
-
default:
|
|
1357
|
-
return true;
|
|
1358
|
-
}
|
|
1359
|
-
});
|
|
1360
|
-
});
|
|
1361
|
-
}
|
|
1362
|
-
var DatasetChart = React5.memo(
|
|
1363
|
-
function DatasetChart2({
|
|
1364
|
-
chartType,
|
|
1365
|
-
title,
|
|
1366
|
-
invocationId,
|
|
1367
|
-
datasetSlugs,
|
|
1368
|
-
xAxis,
|
|
1369
|
-
yAxes,
|
|
1370
|
-
series,
|
|
1371
|
-
dataReduction = { strategy: "none", target_points: 1e3 },
|
|
1372
|
-
stacked,
|
|
1373
|
-
sort,
|
|
1374
|
-
onScrollUpdate
|
|
1375
|
-
}) {
|
|
1376
|
-
const datasetResults = useMultipleDatasetContents(datasetSlugs, invocationId);
|
|
1377
|
-
const isLoading = datasetResults.some((q) => q.isLoading);
|
|
1378
|
-
const rawData = datasetResults.map((r) => r.data);
|
|
1379
|
-
const datasetData = useDeepCompareMemo(() => {
|
|
1380
|
-
return rawData.map((d) => d || []);
|
|
1381
|
-
}, [rawData]);
|
|
1382
|
-
const { resolvedXAxisKey, resolvedSeriesKeys } = useMemo5(() => {
|
|
1383
|
-
const firstDataset = datasetData.find((d) => d.length > 0) || [];
|
|
1384
|
-
return {
|
|
1385
|
-
resolvedXAxisKey: resolveKeyFromData(firstDataset, xAxis.key),
|
|
1386
|
-
resolvedSeriesKeys: series.map((s) => ({
|
|
1387
|
-
...s,
|
|
1388
|
-
resolvedKey: resolveKeyFromData(firstDataset, s.key)
|
|
1389
|
-
}))
|
|
1390
|
-
};
|
|
1391
|
-
}, [datasetData, xAxis.key, series]);
|
|
1392
|
-
const defaultSortedData = useMemo5(() => {
|
|
1393
|
-
const mergedDataMap = datasetData.reduce(
|
|
1394
|
-
(acc, rawData2, datasetIndex) => {
|
|
1395
|
-
const datasetSeries = series.filter((s) => s.datasetSlug === datasetSlugs[datasetIndex]);
|
|
1396
|
-
datasetSeries.forEach((s) => {
|
|
1397
|
-
const resolvedSeriesKey = resolvedSeriesKeys.find((rs) => rs.datasetSlug === s.datasetSlug && rs.key === s.key)?.resolvedKey || s.key;
|
|
1398
|
-
const filteredData = s.filters ? applyFilters(rawData2, s.filters, resolvedSeriesKey, resolvedXAxisKey) : rawData2;
|
|
1399
|
-
filteredData.forEach((row, arrayIndex) => {
|
|
1400
|
-
const xValue = getValue(row, resolvedXAxisKey, xAxis.type || "category", arrayIndex);
|
|
1401
|
-
if (xValue === null || xValue === void 0 || xAxis.type === "number" && isNaN(xValue)) {
|
|
1402
|
-
return;
|
|
1403
|
-
}
|
|
1404
|
-
const key = xAxis.type === "number" || xAxis.type === "date" ? xValue.toString() : typeof xValue === "object" ? xValue.toString() : String(xValue);
|
|
1405
|
-
if (!acc.has(key)) {
|
|
1406
|
-
acc.set(key, { [xAxis.key]: xValue });
|
|
1407
|
-
}
|
|
1408
|
-
const dsIndex = datasetSlugs.findIndex((slug) => slug === s.datasetSlug);
|
|
1409
|
-
const prefixedKey = `dataset_${dsIndex}_series_${series.indexOf(s)}_${s.key}`;
|
|
1410
|
-
const seriesValue = row[resolvedSeriesKey];
|
|
1411
|
-
acc.get(key)[prefixedKey] = seriesValue;
|
|
1412
|
-
});
|
|
1413
|
-
});
|
|
1414
|
-
return acc;
|
|
1415
|
-
},
|
|
1416
|
-
/* @__PURE__ */ new Map()
|
|
1417
|
-
);
|
|
1418
|
-
const mergedData = Array.from(mergedDataMap.values());
|
|
1419
|
-
if (sort && sort.length > 0) {
|
|
1420
|
-
return mergedData;
|
|
1421
|
-
}
|
|
1422
|
-
return mergedData.sort((a, b) => {
|
|
1423
|
-
if (xAxis.type === "date") {
|
|
1424
|
-
return a[xAxis.key] - b[xAxis.key];
|
|
1425
|
-
}
|
|
1426
|
-
const aVal = parseFloat(a[xAxis.key]);
|
|
1427
|
-
const bVal = parseFloat(b[xAxis.key]);
|
|
1428
|
-
if (isNaN(aVal) || isNaN(bVal)) {
|
|
1429
|
-
return String(a[xAxis.key]).localeCompare(String(b[xAxis.key]));
|
|
1430
|
-
}
|
|
1431
|
-
return aVal - bVal;
|
|
1432
|
-
});
|
|
1433
|
-
}, [datasetData, series, datasetSlugs, resolvedSeriesKeys, resolvedXAxisKey, xAxis, sort]);
|
|
1434
|
-
const prefixedSeries = useMemo5(() => {
|
|
1435
|
-
return series.map((s, index) => {
|
|
1436
|
-
const datasetIndex = datasetSlugs.findIndex((slug) => slug === s.datasetSlug);
|
|
1437
|
-
return {
|
|
1438
|
-
...s,
|
|
1439
|
-
key: `dataset_${datasetIndex}_series_${index}_${s.key}`
|
|
1440
|
-
};
|
|
1441
|
-
});
|
|
1442
|
-
}, [series, datasetSlugs]);
|
|
1443
|
-
const displayConfig = useMemo5(() => {
|
|
1444
|
-
return {
|
|
1445
|
-
[xAxis.key]: {
|
|
1446
|
-
label: xAxis.label,
|
|
1447
|
-
format: xAxis.format,
|
|
1448
|
-
type: xAxis.type
|
|
1449
|
-
},
|
|
1450
|
-
...prefixedSeries.reduce(
|
|
1451
|
-
(acc, s) => {
|
|
1452
|
-
acc[s.key] = {
|
|
1453
|
-
label: s.name,
|
|
1454
|
-
color: s.color
|
|
1455
|
-
};
|
|
1456
|
-
return acc;
|
|
1457
|
-
},
|
|
1458
|
-
{}
|
|
1459
|
-
),
|
|
1460
|
-
...chartType === "histogram" ? {
|
|
1461
|
-
frequency: {
|
|
1462
|
-
label: yAxes[0]?.label || "Frequency",
|
|
1463
|
-
color: prefixedSeries[0]?.color || "#2563eb"
|
|
1464
|
-
}
|
|
1465
|
-
} : {}
|
|
1466
|
-
};
|
|
1467
|
-
}, [xAxis, prefixedSeries, chartType, yAxes]);
|
|
1468
|
-
const dataConfig = useMemo5(() => {
|
|
1469
|
-
if (!xAxis.key || !prefixedSeries.length) {
|
|
1470
|
-
return null;
|
|
1471
|
-
}
|
|
1472
|
-
return {
|
|
1473
|
-
chartType,
|
|
1474
|
-
xAxis,
|
|
1475
|
-
yAxes: chartType === "histogram" ? yAxes.map((axis) => ({
|
|
1476
|
-
...axis,
|
|
1477
|
-
key: "frequency",
|
|
1478
|
-
// Map to our frequency key
|
|
1479
|
-
minValue: axis.minValue || "0"
|
|
1480
|
-
// Ensure we have a minimum of 0 if not specified
|
|
1481
|
-
})) : yAxes,
|
|
1482
|
-
series: chartType === "histogram" ? [
|
|
1483
|
-
{
|
|
1484
|
-
key: "frequency",
|
|
1485
|
-
name: yAxes[0]?.label || "Frequency",
|
|
1486
|
-
color: series[0]?.color || "#2563eb"
|
|
1487
|
-
}
|
|
1488
|
-
] : prefixedSeries
|
|
1489
|
-
};
|
|
1490
|
-
}, [xAxis, yAxes, series, prefixedSeries, chartType]);
|
|
1491
|
-
let ChartComponent = null;
|
|
1492
|
-
switch (chartType) {
|
|
1493
|
-
case "bar":
|
|
1494
|
-
ChartComponent = BarChart;
|
|
1495
|
-
break;
|
|
1496
|
-
case "line":
|
|
1497
|
-
ChartComponent = LineChart;
|
|
1498
|
-
break;
|
|
1499
|
-
case "pie":
|
|
1500
|
-
ChartComponent = PieChart;
|
|
1501
|
-
break;
|
|
1502
|
-
case "scatter":
|
|
1503
|
-
ChartComponent = ScatterChart;
|
|
1504
|
-
break;
|
|
1505
|
-
case "histogram":
|
|
1506
|
-
ChartComponent = BarChart;
|
|
1507
|
-
break;
|
|
1508
|
-
case "heatmap":
|
|
1509
|
-
ChartComponent = HeatmapChart;
|
|
1510
|
-
break;
|
|
1511
|
-
}
|
|
1512
|
-
const hasUpdated = useRef(false);
|
|
1513
|
-
useEffect2(() => {
|
|
1514
|
-
if (hasUpdated.current || !onScrollUpdate) {
|
|
1515
|
-
return;
|
|
1516
|
-
}
|
|
1517
|
-
if (!isLoading && displayConfig && dataConfig && defaultSortedData.length) {
|
|
1518
|
-
onScrollUpdate();
|
|
1519
|
-
setTimeout(() => onScrollUpdate(), 250);
|
|
1520
|
-
hasUpdated.current = true;
|
|
1521
|
-
}
|
|
1522
|
-
}, [onScrollUpdate, isLoading, displayConfig, dataConfig, defaultSortedData.length]);
|
|
1523
|
-
const [currentZoom, setCurrentZoom] = useState3({
|
|
1524
|
-
x: [null, null],
|
|
1525
|
-
y: [null, null]
|
|
1526
|
-
});
|
|
1527
|
-
const { processedData, dataReductionInfo } = useMemo5(() => {
|
|
1528
|
-
if (isLoading || !defaultSortedData.length) {
|
|
1529
|
-
return { processedData: [], dataReductionInfo: null };
|
|
1530
|
-
}
|
|
1531
|
-
if (chartType === "histogram") {
|
|
1532
|
-
const binCount = dataReduction.target_points || 20;
|
|
1533
|
-
const processedData2 = binHistogramData(
|
|
1534
|
-
defaultSortedData,
|
|
1535
|
-
resolvedXAxisKey,
|
|
1536
|
-
prefixedSeries,
|
|
1537
|
-
binCount,
|
|
1538
|
-
xAxis
|
|
1539
|
-
);
|
|
1540
|
-
return {
|
|
1541
|
-
processedData: processedData2,
|
|
1542
|
-
dataReductionInfo: null
|
|
1543
|
-
};
|
|
1544
|
-
}
|
|
1545
|
-
let workingData = defaultSortedData;
|
|
1546
|
-
if (currentZoom.x[0] !== null || currentZoom.y[0] !== null) {
|
|
1547
|
-
workingData = defaultSortedData.filter((item) => {
|
|
1548
|
-
if (currentZoom.x[0] !== null && currentZoom.x[1] !== null) {
|
|
1549
|
-
const xValue = parseFloat(item[xAxis.key]);
|
|
1550
|
-
if (isNaN(xValue) || xValue < currentZoom.x[0] || xValue > currentZoom.x[1]) {
|
|
1551
|
-
return false;
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
if (currentZoom.y[0] !== null && currentZoom.y[1] !== null) {
|
|
1555
|
-
for (const s of prefixedSeries) {
|
|
1556
|
-
const yValue = parseFloat(item[s.key]);
|
|
1557
|
-
if (!isNaN(yValue)) {
|
|
1558
|
-
if (yValue < currentZoom.y[0] || yValue > currentZoom.y[1]) {
|
|
1559
|
-
return false;
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
return true;
|
|
1565
|
-
});
|
|
1566
|
-
}
|
|
1567
|
-
if (workingData.length <= dataReduction.target_points && (!sort || sort.length === 0)) {
|
|
1568
|
-
return {
|
|
1569
|
-
processedData: workingData,
|
|
1570
|
-
dataReductionInfo: null
|
|
1571
|
-
};
|
|
1572
|
-
}
|
|
1573
|
-
let reducedData;
|
|
1574
|
-
let method = "";
|
|
1575
|
-
switch (dataReduction.strategy) {
|
|
1576
|
-
case "sample":
|
|
1577
|
-
reducedData = sampleData(workingData, dataReduction.target_points);
|
|
1578
|
-
method = "sampled";
|
|
1579
|
-
if (sort && sort.length > 0) {
|
|
1580
|
-
reducedData = applySortConditions(reducedData, xAxis, yAxes, sort);
|
|
1581
|
-
}
|
|
1582
|
-
break;
|
|
1583
|
-
case "aggregate":
|
|
1584
|
-
reducedData = aggregateData(
|
|
1585
|
-
workingData,
|
|
1586
|
-
resolvedXAxisKey,
|
|
1587
|
-
prefixedSeries,
|
|
1588
|
-
dataReduction.target_points,
|
|
1589
|
-
xAxis,
|
|
1590
|
-
yAxes,
|
|
1591
|
-
sort
|
|
1592
|
-
);
|
|
1593
|
-
method = "aggregated";
|
|
1594
|
-
break;
|
|
1595
|
-
case "bin":
|
|
1596
|
-
reducedData = binData(
|
|
1597
|
-
workingData,
|
|
1598
|
-
resolvedXAxisKey,
|
|
1599
|
-
prefixedSeries,
|
|
1600
|
-
dataReduction.target_points
|
|
1601
|
-
);
|
|
1602
|
-
method = "binning";
|
|
1603
|
-
if (sort && sort.length > 0) {
|
|
1604
|
-
reducedData = applySortConditions(reducedData, xAxis, yAxes, sort);
|
|
1605
|
-
}
|
|
1606
|
-
break;
|
|
1607
|
-
default:
|
|
1608
|
-
if (workingData.length < 1e3) {
|
|
1609
|
-
reducedData = workingData;
|
|
1610
|
-
} else {
|
|
1611
|
-
reducedData = sampleData(workingData, dataReduction.target_points);
|
|
1612
|
-
method = "sampled";
|
|
1613
|
-
}
|
|
1614
|
-
if (sort && sort.length > 0) {
|
|
1615
|
-
reducedData = applySortConditions(reducedData, xAxis, yAxes, sort);
|
|
1616
|
-
}
|
|
1617
|
-
}
|
|
1618
|
-
let dataReductionInfo2 = null;
|
|
1619
|
-
if (workingData.length !== reducedData.length) {
|
|
1620
|
-
dataReductionInfo2 = `${method} ${workingData.length.toLocaleString()} \u2192 ${reducedData.length.toLocaleString()} points`;
|
|
1621
|
-
}
|
|
1622
|
-
return {
|
|
1623
|
-
processedData: reducedData,
|
|
1624
|
-
dataReductionInfo: dataReductionInfo2
|
|
1625
|
-
};
|
|
1626
|
-
}, [
|
|
1627
|
-
defaultSortedData,
|
|
1628
|
-
dataReduction,
|
|
1629
|
-
chartType,
|
|
1630
|
-
isLoading,
|
|
1631
|
-
currentZoom.x,
|
|
1632
|
-
currentZoom.y,
|
|
1633
|
-
prefixedSeries,
|
|
1634
|
-
sort,
|
|
1635
|
-
xAxis,
|
|
1636
|
-
yAxes,
|
|
1637
|
-
resolvedXAxisKey
|
|
1638
|
-
]);
|
|
1639
|
-
if (!ChartComponent) {
|
|
1640
|
-
console.error("No chart component found");
|
|
1641
|
-
return null;
|
|
1642
|
-
}
|
|
1643
|
-
if (isLoading) {
|
|
1644
|
-
return /* @__PURE__ */ jsx9("div", { children: "Loading..." });
|
|
1645
|
-
}
|
|
1646
|
-
if (!defaultSortedData.length) {
|
|
1647
|
-
return /* @__PURE__ */ jsx9("div", { children: "Unable to display chart - no data available" });
|
|
1648
|
-
}
|
|
1649
|
-
if (!dataConfig) {
|
|
1650
|
-
return /* @__PURE__ */ jsx9("div", { children: "Invalid chart configuration" });
|
|
1651
|
-
}
|
|
1652
|
-
return /* @__PURE__ */ jsx9(
|
|
1653
|
-
ChartComponent,
|
|
1654
|
-
{
|
|
1655
|
-
data: processedData,
|
|
1656
|
-
displayConfig,
|
|
1657
|
-
stacked,
|
|
1658
|
-
dataConfig,
|
|
1659
|
-
title,
|
|
1660
|
-
subtitle: dataReductionInfo || void 0,
|
|
1661
|
-
disableAnimation: processedData.length > 100,
|
|
1662
|
-
onZoomChange: setCurrentZoom
|
|
1663
|
-
}
|
|
1664
|
-
);
|
|
1665
|
-
},
|
|
1666
|
-
(prevProps, nextProps) => {
|
|
1667
|
-
return isEqual(prevProps, nextProps);
|
|
1668
|
-
}
|
|
1669
|
-
);
|
|
1670
|
-
|
|
1671
|
-
// src/components/content/text-content.tsx
|
|
1672
|
-
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1673
|
-
function TextContent({ content, className }) {
|
|
1674
|
-
if (!content?.length) return null;
|
|
1675
|
-
return /* @__PURE__ */ jsx10("div", { className: className || "prose dark:prose-invert max-w-4xl w-full leading-normal", children: /* @__PURE__ */ jsx10("p", { style: { whiteSpace: "pre-wrap" }, children: content }) });
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
// src/components/content/json-content.tsx
|
|
1679
|
-
import { useMemo as useMemo6 } from "react";
|
|
1680
|
-
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1681
|
-
function parseJsonContent(content) {
|
|
1682
|
-
const chunks = [];
|
|
1683
|
-
let remaining = content;
|
|
1684
|
-
while (remaining.length > 0) {
|
|
1685
|
-
const jsonStart = remaining.indexOf("{");
|
|
1686
|
-
const jsonArrayStart = remaining.indexOf("[");
|
|
1687
|
-
let start = -1;
|
|
1688
|
-
let isObject = true;
|
|
1689
|
-
if (jsonStart >= 0 && (jsonArrayStart < 0 || jsonStart < jsonArrayStart)) {
|
|
1690
|
-
start = jsonStart;
|
|
1691
|
-
isObject = true;
|
|
1692
|
-
} else if (jsonArrayStart >= 0) {
|
|
1693
|
-
start = jsonArrayStart;
|
|
1694
|
-
isObject = false;
|
|
1695
|
-
}
|
|
1696
|
-
if (start < 0) {
|
|
1697
|
-
if (remaining.trim()) {
|
|
1698
|
-
chunks.push({ type: "text", content: remaining });
|
|
1699
|
-
}
|
|
1700
|
-
break;
|
|
1701
|
-
}
|
|
1702
|
-
if (start > 0) {
|
|
1703
|
-
const textBefore = remaining.slice(0, start);
|
|
1704
|
-
if (textBefore.trim()) {
|
|
1705
|
-
chunks.push({ type: "text", content: textBefore });
|
|
1706
|
-
}
|
|
1707
|
-
}
|
|
1708
|
-
let depth = 0;
|
|
1709
|
-
let end = start;
|
|
1710
|
-
const openChar = isObject ? "{" : "[";
|
|
1711
|
-
const closeChar = isObject ? "}" : "]";
|
|
1712
|
-
for (let i = start; i < remaining.length; i++) {
|
|
1713
|
-
if (remaining[i] === openChar) depth++;
|
|
1714
|
-
if (remaining[i] === closeChar) depth--;
|
|
1715
|
-
if (depth === 0) {
|
|
1716
|
-
end = i + 1;
|
|
1717
|
-
break;
|
|
1718
|
-
}
|
|
1719
|
-
}
|
|
1720
|
-
const jsonStr = remaining.slice(start, end);
|
|
1721
|
-
try {
|
|
1722
|
-
const parsed = JSON.parse(jsonStr);
|
|
1723
|
-
chunks.push({ type: "json", content: parsed });
|
|
1724
|
-
} catch {
|
|
1725
|
-
chunks.push({ type: "text", content: jsonStr });
|
|
1726
|
-
}
|
|
1727
|
-
remaining = remaining.slice(end);
|
|
1728
|
-
}
|
|
1729
|
-
return chunks;
|
|
1730
|
-
}
|
|
1731
|
-
function getStyleClass(style) {
|
|
1732
|
-
switch (style) {
|
|
1733
|
-
case "muted":
|
|
1734
|
-
return "text-gray-500";
|
|
1735
|
-
case "error":
|
|
1736
|
-
return "text-red-500";
|
|
1737
|
-
case "warning":
|
|
1738
|
-
return "text-yellow-600";
|
|
1739
|
-
case "success":
|
|
1740
|
-
return "text-green-600";
|
|
1741
|
-
default:
|
|
1742
|
-
return "";
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
function JsonContent({ content, className }) {
|
|
1746
|
-
const contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
1747
|
-
const chunks = useMemo6(() => parseJsonContent(contentStr), [contentStr]);
|
|
1748
|
-
if (!contentStr?.length) return null;
|
|
1749
|
-
return /* @__PURE__ */ jsx11("div", { className: className || "prose dark:prose-invert leading-normal", children: chunks.map((chunk, index) => {
|
|
1750
|
-
if (chunk.type === "json") {
|
|
1751
|
-
const json = chunk.content;
|
|
1752
|
-
if (json.message && typeof json.message === "string") {
|
|
1753
|
-
return /* @__PURE__ */ jsx11("p", { className: getStyleClass(json.style), children: json.message }, index);
|
|
1754
|
-
}
|
|
1755
|
-
return /* @__PURE__ */ jsx11(
|
|
1756
|
-
"pre",
|
|
1757
|
-
{
|
|
1758
|
-
className: "bg-gray-100 dark:bg-gray-800 p-3 rounded overflow-x-auto text-sm",
|
|
1759
|
-
children: JSON.stringify(json, null, 2)
|
|
1760
|
-
},
|
|
1761
|
-
index
|
|
1762
|
-
);
|
|
1763
|
-
}
|
|
1764
|
-
return /* @__PURE__ */ jsx11("p", { children: chunk.content }, index);
|
|
1765
|
-
}) });
|
|
1766
|
-
}
|
|
1767
|
-
|
|
1768
|
-
// src/components/content/chart-content.tsx
|
|
1769
|
-
import { useMemo as useMemo7 } from "react";
|
|
1770
|
-
import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1771
|
-
function ChartContent2({ config, data, className }) {
|
|
1772
|
-
const chartProps = useMemo7(() => {
|
|
1773
|
-
if (!config?.chart_type || !config?.chart_title || !config?.series?.length || !config?.y_axes?.length) {
|
|
1774
|
-
return null;
|
|
1775
|
-
}
|
|
1776
|
-
return {
|
|
1777
|
-
chartType: config.chart_type,
|
|
1778
|
-
title: config.chart_title,
|
|
1779
|
-
xAxis: {
|
|
1780
|
-
label: config.x_axis.axis_label,
|
|
1781
|
-
key: config.x_axis.key,
|
|
1782
|
-
maxValue: config.x_axis.max_value,
|
|
1783
|
-
minValue: config.x_axis.min_value,
|
|
1784
|
-
type: config.x_axis.value_type,
|
|
1785
|
-
format: config.x_axis.format
|
|
1786
|
-
},
|
|
1787
|
-
yAxes: config.y_axes.map((axis) => ({
|
|
1788
|
-
label: axis.axis_label,
|
|
1789
|
-
key: axis.key,
|
|
1790
|
-
maxValue: axis.max_value,
|
|
1791
|
-
minValue: axis.min_value,
|
|
1792
|
-
type: axis.value_type,
|
|
1793
|
-
format: axis.format
|
|
1794
|
-
})),
|
|
1795
|
-
series: config.series.map((s) => ({
|
|
1796
|
-
key: s.key,
|
|
1797
|
-
name: s.series_name,
|
|
1798
|
-
color: s.color,
|
|
1799
|
-
axisIndex: s.axis_index,
|
|
1800
|
-
filters: s.filters
|
|
1801
|
-
})),
|
|
1802
|
-
dataReduction: config.data_reduction,
|
|
1803
|
-
stacked: config.stacked,
|
|
1804
|
-
sort: config.sort
|
|
1805
|
-
};
|
|
1806
|
-
}, [config]);
|
|
1807
|
-
if (!chartProps) {
|
|
1808
|
-
return /* @__PURE__ */ jsx12("div", { className: "text-red-500", children: "Invalid chart configuration" });
|
|
1809
|
-
}
|
|
1810
|
-
if (!data || data.length === 0) {
|
|
1811
|
-
return /* @__PURE__ */ jsx12("div", { className: "text-gray-500", children: "No data available for chart" });
|
|
1812
|
-
}
|
|
1813
|
-
let ChartComponent = null;
|
|
1814
|
-
switch (chartProps.chartType) {
|
|
1815
|
-
case "bar":
|
|
1816
|
-
case "histogram":
|
|
1817
|
-
ChartComponent = BarChart;
|
|
1818
|
-
break;
|
|
1819
|
-
case "line":
|
|
1820
|
-
ChartComponent = LineChart;
|
|
1821
|
-
break;
|
|
1822
|
-
case "pie":
|
|
1823
|
-
ChartComponent = PieChart;
|
|
1824
|
-
break;
|
|
1825
|
-
case "scatter":
|
|
1826
|
-
ChartComponent = ScatterChart;
|
|
1827
|
-
break;
|
|
1828
|
-
case "heatmap":
|
|
1829
|
-
ChartComponent = HeatmapChart;
|
|
1830
|
-
break;
|
|
1831
|
-
}
|
|
1832
|
-
if (!ChartComponent) {
|
|
1833
|
-
return /* @__PURE__ */ jsxs4("div", { className: "text-red-500", children: [
|
|
1834
|
-
"Unsupported chart type: ",
|
|
1835
|
-
chartProps.chartType
|
|
1836
|
-
] });
|
|
1837
|
-
}
|
|
1838
|
-
const displayConfig = {
|
|
1839
|
-
[chartProps.xAxis.key]: {
|
|
1840
|
-
label: chartProps.xAxis.label,
|
|
1841
|
-
format: chartProps.xAxis.format,
|
|
1842
|
-
type: chartProps.xAxis.type
|
|
1843
|
-
},
|
|
1844
|
-
...chartProps.series.reduce(
|
|
1845
|
-
(acc, s) => {
|
|
1846
|
-
acc[s.key] = {
|
|
1847
|
-
label: s.name,
|
|
1848
|
-
color: s.color
|
|
1849
|
-
};
|
|
1850
|
-
return acc;
|
|
1851
|
-
},
|
|
1852
|
-
{}
|
|
1853
|
-
)
|
|
1854
|
-
};
|
|
1855
|
-
const dataConfig = {
|
|
1856
|
-
chartType: chartProps.chartType,
|
|
1857
|
-
xAxis: chartProps.xAxis,
|
|
1858
|
-
yAxes: chartProps.yAxes,
|
|
1859
|
-
series: chartProps.series
|
|
1860
|
-
};
|
|
1861
|
-
return /* @__PURE__ */ jsx12("div", { className: className || "w-full max-w-3xl", children: /* @__PURE__ */ jsx12(
|
|
1862
|
-
ChartComponent,
|
|
1863
|
-
{
|
|
1864
|
-
title: chartProps.title,
|
|
1865
|
-
data,
|
|
1866
|
-
displayConfig,
|
|
1867
|
-
dataConfig,
|
|
1868
|
-
stacked: chartProps.stacked,
|
|
1869
|
-
disableAnimation: data.length > 100
|
|
1870
|
-
}
|
|
1871
|
-
) });
|
|
1872
|
-
}
|
|
1873
|
-
|
|
1874
|
-
// src/components/content/table-content.tsx
|
|
1875
|
-
import { useMemo as useMemo8 } from "react";
|
|
1876
|
-
import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1877
|
-
function TableContent({ title, columns, data, className, maxRows = 100 }) {
|
|
1878
|
-
const displayData = useMemo8(() => {
|
|
1879
|
-
if (!data || data.length === 0) return [];
|
|
1880
|
-
return maxRows ? data.slice(0, maxRows) : data;
|
|
1881
|
-
}, [data, maxRows]);
|
|
1882
|
-
if (!columns || columns.length === 0) {
|
|
1883
|
-
return /* @__PURE__ */ jsx13("div", { className: "text-gray-500", children: "No columns defined" });
|
|
1884
|
-
}
|
|
1885
|
-
if (!data || data.length === 0) {
|
|
1886
|
-
return /* @__PURE__ */ jsx13("div", { className: "text-gray-500", children: "No data available" });
|
|
1887
|
-
}
|
|
1888
|
-
return /* @__PURE__ */ jsxs5("div", { className: className || "w-full max-w-4xl", children: [
|
|
1889
|
-
title && /* @__PURE__ */ jsx13("h3", { className: "text-lg font-medium mb-2", children: title }),
|
|
1890
|
-
/* @__PURE__ */ jsx13("div", { className: "overflow-x-auto border rounded-md", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-sm", children: [
|
|
1891
|
-
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsx13("tr", { className: "border-b bg-gray-50 dark:bg-gray-800", children: columns.map((col) => /* @__PURE__ */ jsx13(
|
|
1892
|
-
"th",
|
|
1893
|
-
{
|
|
1894
|
-
className: "px-4 py-2 text-left font-medium text-gray-700 dark:text-gray-300",
|
|
1895
|
-
children: col.column_name
|
|
1896
|
-
},
|
|
1897
|
-
col.key
|
|
1898
|
-
)) }) }),
|
|
1899
|
-
/* @__PURE__ */ jsx13("tbody", { children: displayData.map((row, rowIndex) => /* @__PURE__ */ jsx13(
|
|
1900
|
-
"tr",
|
|
1901
|
-
{
|
|
1902
|
-
className: "border-b last:border-b-0 hover:bg-gray-50 dark:hover:bg-gray-800/50",
|
|
1903
|
-
children: columns.map((col) => /* @__PURE__ */ jsx13("td", { className: "px-4 py-2 text-gray-900 dark:text-gray-100", children: formatValue(row[col.key], col.format, col.value_type) }, col.key))
|
|
1904
|
-
},
|
|
1905
|
-
rowIndex
|
|
1906
|
-
)) })
|
|
1907
|
-
] }) }),
|
|
1908
|
-
data.length > maxRows && /* @__PURE__ */ jsxs5("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
1909
|
-
"Showing ",
|
|
1910
|
-
maxRows,
|
|
1911
|
-
" of ",
|
|
1912
|
-
data.length,
|
|
1913
|
-
" rows"
|
|
1914
|
-
] })
|
|
1915
|
-
] });
|
|
1916
|
-
}
|
|
1917
|
-
|
|
1918
|
-
// src/components/content/content.tsx
|
|
1919
|
-
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1920
|
-
function Content({ item, className, components }) {
|
|
1921
|
-
const uiContentType = typeof item.ui_content_type === "object" && item.ui_content_type?.Valid ? item.ui_content_type.String : typeof item.ui_content_type === "string" ? item.ui_content_type : item.content_type;
|
|
1922
|
-
const contentStr = typeof item.content === "string" ? item.content : JSON.stringify(item.content);
|
|
1923
|
-
switch (uiContentType) {
|
|
1924
|
-
case "text":
|
|
1925
|
-
case "thinking":
|
|
1926
|
-
case "redacted_thinking": {
|
|
1927
|
-
const TextComponent = components?.text || TextContent;
|
|
1928
|
-
return /* @__PURE__ */ jsx14(TextComponent, { content: contentStr, className });
|
|
1929
|
-
}
|
|
1930
|
-
case "json":
|
|
1931
|
-
case "codegen_json": {
|
|
1932
|
-
const JsonComponent = components?.json || JsonContent;
|
|
1933
|
-
return /* @__PURE__ */ jsx14(JsonComponent, { content: item.content, className });
|
|
1934
|
-
}
|
|
1935
|
-
case "chart":
|
|
1936
|
-
case "ui_generation": {
|
|
1937
|
-
if (item.chartConfig && item.chartData) {
|
|
1938
|
-
const ChartComponent = components?.chart || ChartContent2;
|
|
1939
|
-
return /* @__PURE__ */ jsx14(ChartComponent, { config: item.chartConfig, data: item.chartData, className });
|
|
1940
|
-
}
|
|
1941
|
-
try {
|
|
1942
|
-
const parsed = typeof item.content === "string" ? JSON.parse(item.content) : item.content;
|
|
1943
|
-
if (parsed.children) {
|
|
1944
|
-
return renderNodes(parsed.children, className, components);
|
|
1945
|
-
}
|
|
1946
|
-
const JsonComponent = components?.json || JsonContent;
|
|
1947
|
-
return /* @__PURE__ */ jsx14(JsonComponent, { content: item.content, className });
|
|
1948
|
-
} catch {
|
|
1949
|
-
const JsonComponent = components?.json || JsonContent;
|
|
1950
|
-
return /* @__PURE__ */ jsx14(JsonComponent, { content: item.content, className });
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
case "table": {
|
|
1954
|
-
if (item.tableColumns && item.tableData) {
|
|
1955
|
-
const TableComponent = components?.table || TableContent;
|
|
1956
|
-
return /* @__PURE__ */ jsx14(
|
|
1957
|
-
TableComponent,
|
|
1958
|
-
{
|
|
1959
|
-
columns: item.tableColumns,
|
|
1960
|
-
data: item.tableData,
|
|
1961
|
-
className
|
|
1962
|
-
}
|
|
1963
|
-
);
|
|
1964
|
-
}
|
|
1965
|
-
const JsonComponent = components?.json || JsonContent;
|
|
1966
|
-
return /* @__PURE__ */ jsx14(JsonComponent, { content: item.content, className });
|
|
1967
|
-
}
|
|
1968
|
-
case "log":
|
|
1969
|
-
case "codeexec_output": {
|
|
1970
|
-
return /* @__PURE__ */ jsx14("pre", { className: className || "bg-gray-100 dark:bg-gray-800 p-3 rounded text-sm overflow-x-auto", children: contentStr });
|
|
1971
|
-
}
|
|
1972
|
-
// Skip these types
|
|
1973
|
-
case "bot_invocation":
|
|
1974
|
-
case "bot_invocation_result":
|
|
1975
|
-
case "tool_invocation":
|
|
1976
|
-
case "tool_result":
|
|
1977
|
-
case "security_check_json":
|
|
1978
|
-
return null;
|
|
1979
|
-
default: {
|
|
1980
|
-
const TextComponent = components?.text || TextContent;
|
|
1981
|
-
return /* @__PURE__ */ jsx14(TextComponent, { content: contentStr, className });
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
function renderNodes(nodes, className, components) {
|
|
1986
|
-
if (!nodes || !Array.isArray(nodes)) return null;
|
|
1987
|
-
return nodes.map((node, index) => {
|
|
1988
|
-
if (!node?._type) return null;
|
|
1989
|
-
switch (node._type) {
|
|
1990
|
-
case "Chart": {
|
|
1991
|
-
const ChartComponent = components?.chart || ChartContent2;
|
|
1992
|
-
const config = node.content;
|
|
1993
|
-
return /* @__PURE__ */ jsx14("div", { className: "my-4", children: /* @__PURE__ */ jsx14(
|
|
1994
|
-
ChartComponent,
|
|
1995
|
-
{
|
|
1996
|
-
config: {
|
|
1997
|
-
chart_type: config.chart_type,
|
|
1998
|
-
chart_title: config.chart_title,
|
|
1999
|
-
x_axis: config.x_axis,
|
|
2000
|
-
y_axes: config.y_axes,
|
|
2001
|
-
series: config.series,
|
|
2002
|
-
data_reduction: config.data_reduction,
|
|
2003
|
-
stacked: config.stacked,
|
|
2004
|
-
sort: config.sort
|
|
2005
|
-
},
|
|
2006
|
-
data: [],
|
|
2007
|
-
className
|
|
2008
|
-
}
|
|
2009
|
-
) }, `chart-${index}`);
|
|
2010
|
-
}
|
|
2011
|
-
case "Table": {
|
|
2012
|
-
const TableComponent = components?.table || TableContent;
|
|
2013
|
-
const config = node.content;
|
|
2014
|
-
return /* @__PURE__ */ jsx14("div", { className: "my-4", children: /* @__PURE__ */ jsx14(
|
|
2015
|
-
TableComponent,
|
|
2016
|
-
{
|
|
2017
|
-
title: config.table_title,
|
|
2018
|
-
columns: config.columns,
|
|
2019
|
-
data: [],
|
|
2020
|
-
className
|
|
2021
|
-
}
|
|
2022
|
-
) }, `table-${index}`);
|
|
2023
|
-
}
|
|
2024
|
-
case "TextMarkdown": {
|
|
2025
|
-
const TextComponent = components?.text || TextContent;
|
|
2026
|
-
return /* @__PURE__ */ jsx14("div", { className: "my-2", children: /* @__PURE__ */ jsx14(TextComponent, { content: node.content?.text || "", className }) }, `text-${index}`);
|
|
2027
|
-
}
|
|
2028
|
-
case "Suggestions": {
|
|
2029
|
-
const suggestions = node.content?.suggestions || [];
|
|
2030
|
-
if (!suggestions.length) return null;
|
|
2031
|
-
return /* @__PURE__ */ jsx14("div", { className: "flex flex-col gap-2 my-4", children: suggestions.map((suggestion, i) => /* @__PURE__ */ jsx14(
|
|
2032
|
-
"button",
|
|
2033
|
-
{
|
|
2034
|
-
className: "text-left px-3 py-2 bg-gray-100 dark:bg-gray-800 rounded hover:bg-gray-200 dark:hover:bg-gray-700 text-sm",
|
|
2035
|
-
children: suggestion
|
|
2036
|
-
},
|
|
2037
|
-
i
|
|
2038
|
-
)) }, `suggestions-${index}`);
|
|
2039
|
-
}
|
|
2040
|
-
default:
|
|
2041
|
-
return null;
|
|
2042
|
-
}
|
|
2043
|
-
});
|
|
2044
|
-
}
|
|
2045
|
-
|
|
2046
|
-
// src/components/content/markdown-content.tsx
|
|
2047
|
-
import ReactMarkdown from "react-markdown";
|
|
2048
|
-
import remarkGfm from "remark-gfm";
|
|
2049
|
-
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
2050
|
-
function MarkdownContent({ text, className }) {
|
|
2051
|
-
if (!text?.length) return null;
|
|
2052
|
-
return /* @__PURE__ */ jsx15("div", { className: cn("prose dark:prose-invert leading-tight", className), children: /* @__PURE__ */ jsx15(ReactMarkdown, { remarkPlugins: [remarkGfm], children: text }) });
|
|
2053
|
-
}
|
|
2054
|
-
|
|
2055
|
-
// src/hooks/use-invocation.ts
|
|
2056
|
-
import { useState as useState4, useCallback as useCallback3, useRef as useRef2 } from "react";
|
|
2057
|
-
function extractResultFromEvents(events) {
|
|
2058
|
-
const result = {
|
|
2059
|
-
success: true,
|
|
2060
|
-
messages: [],
|
|
2061
|
-
events,
|
|
2062
|
-
steps: []
|
|
2063
|
-
};
|
|
2064
|
-
for (const event of events) {
|
|
2065
|
-
const eventType = event.type;
|
|
2066
|
-
switch (eventType) {
|
|
2067
|
-
case "invocation_started":
|
|
2068
|
-
if (event.payload && typeof event.payload === "object") {
|
|
2069
|
-
const payload = event.payload;
|
|
2070
|
-
result.invocationId = payload.invocation_id;
|
|
2071
|
-
result.botId = payload.bot_id;
|
|
2072
|
-
}
|
|
2073
|
-
break;
|
|
2074
|
-
case "message":
|
|
2075
|
-
case "message_content":
|
|
2076
|
-
if (event.payload && typeof event.payload === "object") {
|
|
2077
|
-
const payload = event.payload;
|
|
2078
|
-
if (payload.role && payload.content) {
|
|
2079
|
-
result.messages.push({
|
|
2080
|
-
role: payload.role,
|
|
2081
|
-
content: payload.content
|
|
2082
|
-
});
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
break;
|
|
2086
|
-
case "step_started":
|
|
2087
|
-
if (event.payload && typeof event.payload === "object") {
|
|
2088
|
-
const payload = event.payload;
|
|
2089
|
-
result.steps.push({
|
|
2090
|
-
key: payload.step_key || "",
|
|
2091
|
-
action: payload.action || "",
|
|
2092
|
-
status: "running"
|
|
2093
|
-
});
|
|
2094
|
-
}
|
|
2095
|
-
break;
|
|
2096
|
-
case "step_completed":
|
|
2097
|
-
if (event.payload && typeof event.payload === "object") {
|
|
2098
|
-
const payload = event.payload;
|
|
2099
|
-
const stepKey = payload.step_key;
|
|
2100
|
-
const step = result.steps.find((s) => s.key === stepKey);
|
|
2101
|
-
if (step) {
|
|
2102
|
-
step.status = "completed";
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
break;
|
|
2106
|
-
case "step_error":
|
|
2107
|
-
if (event.payload && typeof event.payload === "object") {
|
|
2108
|
-
const payload = event.payload;
|
|
2109
|
-
const stepKey = payload.step_key;
|
|
2110
|
-
const step = result.steps.find((s) => s.key === stepKey);
|
|
2111
|
-
if (step) {
|
|
2112
|
-
step.status = "failed";
|
|
2113
|
-
}
|
|
2114
|
-
}
|
|
2115
|
-
break;
|
|
2116
|
-
case "result":
|
|
2117
|
-
if (event.payload && typeof event.payload === "object") {
|
|
2118
|
-
result.result = event.payload;
|
|
2119
|
-
}
|
|
2120
|
-
break;
|
|
2121
|
-
case "error":
|
|
2122
|
-
result.success = false;
|
|
2123
|
-
if (event.payload && typeof event.payload === "object") {
|
|
2124
|
-
const payload = event.payload;
|
|
2125
|
-
result.error = payload.message || payload.error || "Unknown error";
|
|
2126
|
-
} else if (typeof event.payload === "string") {
|
|
2127
|
-
result.error = event.payload;
|
|
2128
|
-
}
|
|
2129
|
-
break;
|
|
2130
|
-
case "invocation_completed":
|
|
2131
|
-
break;
|
|
2132
|
-
}
|
|
2133
|
-
}
|
|
2134
|
-
return result;
|
|
2135
|
-
}
|
|
2136
|
-
function useInvocation(options = {}) {
|
|
2137
|
-
const config = useErdoConfig();
|
|
2138
|
-
const [result, setResult] = useState4(null);
|
|
2139
|
-
const [isStreaming, setIsStreaming] = useState4(false);
|
|
2140
|
-
const [error, setError] = useState4(null);
|
|
2141
|
-
const abortControllerRef = useRef2(null);
|
|
2142
|
-
const cancel = useCallback3(() => {
|
|
2143
|
-
if (abortControllerRef.current) {
|
|
2144
|
-
abortControllerRef.current.abort();
|
|
2145
|
-
abortControllerRef.current = null;
|
|
2146
|
-
}
|
|
2147
|
-
}, []);
|
|
2148
|
-
const invoke = useCallback3(
|
|
2149
|
-
async (botKey, params) => {
|
|
2150
|
-
if (!config.client) {
|
|
2151
|
-
throw new Error(
|
|
2152
|
-
"ErdoClient not configured in provider. Pass a client to ErdoProvider config to use useInvocation."
|
|
2153
|
-
);
|
|
2154
|
-
}
|
|
2155
|
-
cancel();
|
|
2156
|
-
abortControllerRef.current = new AbortController();
|
|
2157
|
-
setIsStreaming(true);
|
|
2158
|
-
setError(null);
|
|
2159
|
-
setResult(null);
|
|
2160
|
-
try {
|
|
2161
|
-
const events = [];
|
|
2162
|
-
for await (const event of config.client.invokeStream(botKey, params)) {
|
|
2163
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
2164
|
-
break;
|
|
2165
|
-
}
|
|
2166
|
-
events.push(event);
|
|
2167
|
-
options.onEvent?.(event);
|
|
2168
|
-
const currentResult = extractResultFromEvents(events);
|
|
2169
|
-
setResult(currentResult);
|
|
2170
|
-
}
|
|
2171
|
-
const finalResult = extractResultFromEvents(events);
|
|
2172
|
-
setResult(finalResult);
|
|
2173
|
-
options.onFinish?.(finalResult);
|
|
2174
|
-
return finalResult;
|
|
2175
|
-
} catch (e) {
|
|
2176
|
-
const err = e instanceof Error ? e : new Error(String(e));
|
|
2177
|
-
setError(err);
|
|
2178
|
-
options.onError?.(err);
|
|
2179
|
-
throw err;
|
|
2180
|
-
} finally {
|
|
2181
|
-
setIsStreaming(false);
|
|
2182
|
-
abortControllerRef.current = null;
|
|
2183
|
-
}
|
|
2184
|
-
},
|
|
2185
|
-
[config.client, options, cancel]
|
|
2186
|
-
);
|
|
2187
|
-
return { result, isStreaming, error, invoke, cancel };
|
|
2188
|
-
}
|
|
2189
|
-
|
|
2190
|
-
// src/lib/parse-json.ts
|
|
2191
|
-
var parsingSymbol = /* @__PURE__ */ Symbol("parsing");
|
|
2192
|
-
var JSONStreamParser = class {
|
|
2193
|
-
result;
|
|
2194
|
-
stack;
|
|
2195
|
-
key;
|
|
2196
|
-
state;
|
|
2197
|
-
stringBuffer;
|
|
2198
|
-
numberBuffer;
|
|
2199
|
-
quoteBuffer;
|
|
2200
|
-
escapeNext;
|
|
2201
|
-
unicode;
|
|
2202
|
-
isInTripleQuotes;
|
|
2203
|
-
constructor() {
|
|
2204
|
-
this.result = void 0;
|
|
2205
|
-
this.stack = [];
|
|
2206
|
-
this.key = void 0;
|
|
2207
|
-
this.state = "START";
|
|
2208
|
-
this.stringBuffer = "";
|
|
2209
|
-
this.numberBuffer = "";
|
|
2210
|
-
this.quoteBuffer = "";
|
|
2211
|
-
this.escapeNext = false;
|
|
2212
|
-
this.unicode = "";
|
|
2213
|
-
this.isInTripleQuotes = false;
|
|
2214
|
-
}
|
|
2215
|
-
reset() {
|
|
2216
|
-
this.result = void 0;
|
|
2217
|
-
this.stack = [];
|
|
2218
|
-
this.key = void 0;
|
|
2219
|
-
this.state = "START";
|
|
2220
|
-
this.stringBuffer = "";
|
|
2221
|
-
this.numberBuffer = "";
|
|
2222
|
-
this.quoteBuffer = "";
|
|
2223
|
-
this.escapeNext = false;
|
|
2224
|
-
this.unicode = "";
|
|
2225
|
-
this.isInTripleQuotes = false;
|
|
2226
|
-
}
|
|
2227
|
-
parse(jsonString) {
|
|
2228
|
-
this.reset();
|
|
2229
|
-
return this.add(jsonString);
|
|
2230
|
-
}
|
|
2231
|
-
add(chunk) {
|
|
2232
|
-
for (let i = 0; i < chunk.length; i++) {
|
|
2233
|
-
const char = chunk[i];
|
|
2234
|
-
this.processChar(char);
|
|
2235
|
-
}
|
|
2236
|
-
return this.result;
|
|
2237
|
-
}
|
|
2238
|
-
processChar(char) {
|
|
2239
|
-
switch (this.state) {
|
|
2240
|
-
case "START":
|
|
2241
|
-
this.handleStartState(char);
|
|
2242
|
-
break;
|
|
2243
|
-
case "IN_OBJECT":
|
|
2244
|
-
this.handleObjectState(char);
|
|
2245
|
-
break;
|
|
2246
|
-
case "IN_ARRAY":
|
|
2247
|
-
this.handleArrayState(char);
|
|
2248
|
-
break;
|
|
2249
|
-
case "IN_OBJECT_KEY":
|
|
2250
|
-
this.handleObjectKeyState(char);
|
|
2251
|
-
break;
|
|
2252
|
-
case "AFTER_KEY":
|
|
2253
|
-
this.handleAfterKeyState(char);
|
|
2254
|
-
break;
|
|
2255
|
-
case "IN_OBJECT_VALUE":
|
|
2256
|
-
this.handleObjectValueState(char);
|
|
2257
|
-
break;
|
|
2258
|
-
case "IN_STRING":
|
|
2259
|
-
this.handleStringState(char);
|
|
2260
|
-
break;
|
|
2261
|
-
case "IN_NUMBER":
|
|
2262
|
-
this.handleNumberState(char);
|
|
2263
|
-
break;
|
|
2264
|
-
case "IN_TRUE":
|
|
2265
|
-
this.handleLiteralState(char, "true");
|
|
2266
|
-
break;
|
|
2267
|
-
case "IN_FALSE":
|
|
2268
|
-
this.handleLiteralState(char, "false");
|
|
2269
|
-
break;
|
|
2270
|
-
case "IN_NULL":
|
|
2271
|
-
this.handleLiteralState(char, "null");
|
|
2272
|
-
break;
|
|
2273
|
-
case "IN_UNICODE":
|
|
2274
|
-
this.handleUnicodeState(char);
|
|
2275
|
-
break;
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
handleStartState(char) {
|
|
2279
|
-
if (char === "{") {
|
|
2280
|
-
this.startObject();
|
|
2281
|
-
} else if (char === "[") {
|
|
2282
|
-
this.startArray();
|
|
2283
|
-
} else if (!this.isWhitespace(char)) {
|
|
2284
|
-
throw this.error("must start with { or [", "start");
|
|
2285
|
-
}
|
|
2286
|
-
}
|
|
2287
|
-
error(message, currentRecordType) {
|
|
2288
|
-
return new Error(`Invalid JSON in ${currentRecordType}: ${message}`);
|
|
2289
|
-
}
|
|
2290
|
-
handleObjectState(char) {
|
|
2291
|
-
if (char === "}") {
|
|
2292
|
-
this.endObject();
|
|
2293
|
-
} else if (char === '"') {
|
|
2294
|
-
this.state = "IN_OBJECT_KEY";
|
|
2295
|
-
this.stringBuffer = "";
|
|
2296
|
-
this.key = void 0;
|
|
2297
|
-
this.quoteBuffer = "";
|
|
2298
|
-
} else if (char === ",") {
|
|
2299
|
-
this.key = void 0;
|
|
2300
|
-
} else if (!this.isWhitespace(char)) {
|
|
2301
|
-
throw this.error(`Invalid character in object: ${char}`, "object");
|
|
2302
|
-
}
|
|
2303
|
-
}
|
|
2304
|
-
handleArrayState(char) {
|
|
2305
|
-
if (char === "]") {
|
|
2306
|
-
this.endArray();
|
|
2307
|
-
} else if (char === ",") {
|
|
2308
|
-
} else if (!this.isWhitespace(char)) {
|
|
2309
|
-
this.startValue(char);
|
|
2310
|
-
}
|
|
2311
|
-
}
|
|
2312
|
-
handleObjectKeyState(char) {
|
|
2313
|
-
if (char === '"') {
|
|
2314
|
-
this.state = "AFTER_KEY";
|
|
2315
|
-
this.key = this.stringBuffer;
|
|
2316
|
-
this.stringBuffer = "";
|
|
2317
|
-
} else {
|
|
2318
|
-
this.stringBuffer += char;
|
|
2319
|
-
this.updateValueInParent(this.stringBuffer);
|
|
2320
|
-
}
|
|
2321
|
-
}
|
|
2322
|
-
handleAfterKeyState(char) {
|
|
2323
|
-
if (char === ":") {
|
|
2324
|
-
this.state = "IN_OBJECT_VALUE";
|
|
2325
|
-
} else if (this.isWhitespace(char)) {
|
|
2326
|
-
} else if (!this.isWhitespace(char)) {
|
|
2327
|
-
this.key = this.key + char;
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2330
|
-
handleObjectValueState(char) {
|
|
2331
|
-
if (!this.isWhitespace(char)) {
|
|
2332
|
-
this.startValue(char);
|
|
2333
|
-
}
|
|
2334
|
-
}
|
|
2335
|
-
handleStringState(char) {
|
|
2336
|
-
if (this.escapeNext) {
|
|
2337
|
-
this.handleEscapeChar(char);
|
|
2338
|
-
} else if (char === "\\") {
|
|
2339
|
-
this.escapeNext = true;
|
|
2340
|
-
} else if (char === '"') {
|
|
2341
|
-
this.quoteBuffer += '"';
|
|
2342
|
-
if (this.stringBuffer === "" && this.quoteBuffer === '""') {
|
|
2343
|
-
this.quoteBuffer = "";
|
|
2344
|
-
this.isInTripleQuotes = true;
|
|
2345
|
-
} else if (this.stringBuffer && this.quoteBuffer === '"""') {
|
|
2346
|
-
this.quoteBuffer = "";
|
|
2347
|
-
this.isInTripleQuotes = false;
|
|
2348
|
-
this.stringBuffer = this.stringBuffer.replace(/^\n+/, "").replace(/\n+$/, "").trim();
|
|
2349
|
-
this.endString();
|
|
2350
|
-
return;
|
|
2351
|
-
}
|
|
2352
|
-
} else {
|
|
2353
|
-
if (this.quoteBuffer) {
|
|
2354
|
-
if (this.quoteBuffer === '"' && !this.isInTripleQuotes) {
|
|
2355
|
-
this.quoteBuffer = "";
|
|
2356
|
-
this.endString();
|
|
2357
|
-
this.processChar(char);
|
|
2358
|
-
return;
|
|
2359
|
-
} else if (this.quoteBuffer === '"""' && this.isInTripleQuotes) {
|
|
2360
|
-
this.quoteBuffer = "";
|
|
2361
|
-
this.isInTripleQuotes = false;
|
|
2362
|
-
this.endString();
|
|
2363
|
-
this.processChar(char);
|
|
2364
|
-
return;
|
|
2365
|
-
}
|
|
2366
|
-
this.stringBuffer += this.quoteBuffer;
|
|
2367
|
-
this.quoteBuffer = "";
|
|
2368
|
-
}
|
|
2369
|
-
this.stringBuffer += char;
|
|
2370
|
-
this.updateValueInParent(this.stringBuffer);
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
handleNumberState(char) {
|
|
2374
|
-
if (char.match(/[0-9.eE+-]/)) {
|
|
2375
|
-
this.numberBuffer += char;
|
|
2376
|
-
this.updateValueInParent(parseFloat(this.numberBuffer));
|
|
2377
|
-
} else {
|
|
2378
|
-
this.endNumber();
|
|
2379
|
-
this.processChar(char);
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
2382
|
-
handleLiteralState(char, literal) {
|
|
2383
|
-
const expected = literal[this.stringBuffer.length];
|
|
2384
|
-
if (char === expected) {
|
|
2385
|
-
this.stringBuffer += char;
|
|
2386
|
-
if (this.stringBuffer === literal) {
|
|
2387
|
-
this.endLiteral(literal);
|
|
2388
|
-
} else {
|
|
2389
|
-
this.updateValueInParent(this.stringBuffer);
|
|
2390
|
-
}
|
|
2391
|
-
} else {
|
|
2392
|
-
throw this.error(`Invalid literal: expected ${literal}`, "literal");
|
|
2393
|
-
}
|
|
2394
|
-
}
|
|
2395
|
-
handleUnicodeState(char) {
|
|
2396
|
-
this.unicode += char;
|
|
2397
|
-
if (this.unicode.length === 4) {
|
|
2398
|
-
const codePoint = parseInt(this.unicode, 16);
|
|
2399
|
-
this.stringBuffer += String.fromCharCode(codePoint);
|
|
2400
|
-
this.unicode = "";
|
|
2401
|
-
this.state = "IN_STRING";
|
|
2402
|
-
}
|
|
2403
|
-
}
|
|
2404
|
-
handleEscapeChar(char) {
|
|
2405
|
-
switch (char) {
|
|
2406
|
-
case '"':
|
|
2407
|
-
case "\\":
|
|
2408
|
-
case "/":
|
|
2409
|
-
this.stringBuffer += char;
|
|
2410
|
-
break;
|
|
2411
|
-
case "b":
|
|
2412
|
-
this.stringBuffer += "\b";
|
|
2413
|
-
break;
|
|
2414
|
-
case "f":
|
|
2415
|
-
this.stringBuffer += "\f";
|
|
2416
|
-
break;
|
|
2417
|
-
case "n":
|
|
2418
|
-
this.stringBuffer += "\n";
|
|
2419
|
-
break;
|
|
2420
|
-
case "r":
|
|
2421
|
-
this.stringBuffer += "\r";
|
|
2422
|
-
break;
|
|
2423
|
-
case "t":
|
|
2424
|
-
this.stringBuffer += " ";
|
|
2425
|
-
break;
|
|
2426
|
-
case "u":
|
|
2427
|
-
this.unicode = "";
|
|
2428
|
-
this.state = "IN_UNICODE";
|
|
2429
|
-
break;
|
|
2430
|
-
case "`":
|
|
2431
|
-
this.stringBuffer += "`";
|
|
2432
|
-
break;
|
|
2433
|
-
default:
|
|
2434
|
-
throw this.error("Invalid escape character", "string");
|
|
2435
|
-
}
|
|
2436
|
-
this.escapeNext = false;
|
|
2437
|
-
}
|
|
2438
|
-
startObject() {
|
|
2439
|
-
const newObject = {
|
|
2440
|
-
[parsingSymbol]: true
|
|
2441
|
-
};
|
|
2442
|
-
this.addValueToParent(newObject);
|
|
2443
|
-
this.stack.push({ value: newObject, key: this.key });
|
|
2444
|
-
this.key = void 0;
|
|
2445
|
-
this.state = "IN_OBJECT";
|
|
2446
|
-
}
|
|
2447
|
-
endObject() {
|
|
2448
|
-
const { value: completedObject, key: parentKey, index: parentIndex } = this.stack.pop();
|
|
2449
|
-
delete completedObject[parsingSymbol];
|
|
2450
|
-
if (this.stack.length === 0) {
|
|
2451
|
-
this.state = "END";
|
|
2452
|
-
this.result = { ...completedObject };
|
|
2453
|
-
} else {
|
|
2454
|
-
const { value: parent } = this.stack[this.stack.length - 1];
|
|
2455
|
-
if (Array.isArray(parent)) {
|
|
2456
|
-
if (parentIndex !== void 0) {
|
|
2457
|
-
parent[parentIndex] = { ...completedObject };
|
|
2458
|
-
} else {
|
|
2459
|
-
parent[parent.length - 1] = { ...completedObject };
|
|
2460
|
-
}
|
|
2461
|
-
} else if (parentKey !== void 0) {
|
|
2462
|
-
parent[parentKey] = {
|
|
2463
|
-
...completedObject
|
|
2464
|
-
};
|
|
2465
|
-
} else {
|
|
2466
|
-
throw this.error("Key is undefined", "object");
|
|
2467
|
-
}
|
|
2468
|
-
this.state = this.getParentState();
|
|
2469
|
-
}
|
|
2470
|
-
}
|
|
2471
|
-
startArray() {
|
|
2472
|
-
const newArray = [];
|
|
2473
|
-
newArray[parsingSymbol] = true;
|
|
2474
|
-
this.addValueToParent(newArray);
|
|
2475
|
-
this.stack.push({ value: newArray, key: this.key, index: 0 });
|
|
2476
|
-
this.key = void 0;
|
|
2477
|
-
this.state = "IN_ARRAY";
|
|
2478
|
-
}
|
|
2479
|
-
endArray() {
|
|
2480
|
-
const { value: completedArray, key: parentKey, index: parentIndex } = this.stack.pop();
|
|
2481
|
-
delete completedArray[parsingSymbol];
|
|
2482
|
-
if (this.stack.length === 0) {
|
|
2483
|
-
this.state = "END";
|
|
2484
|
-
if (Array.isArray(completedArray)) {
|
|
2485
|
-
this.result = [...completedArray];
|
|
2486
|
-
} else {
|
|
2487
|
-
throw this.error("Expected array at root level", "array");
|
|
2488
|
-
}
|
|
2489
|
-
} else {
|
|
2490
|
-
const { value: parent } = this.stack[this.stack.length - 1];
|
|
2491
|
-
if (Array.isArray(parent)) {
|
|
2492
|
-
if (parentIndex !== void 0) {
|
|
2493
|
-
parent[parentIndex] = Array.isArray(completedArray) ? [...completedArray] : completedArray;
|
|
2494
|
-
} else {
|
|
2495
|
-
parent[parent.length - 1] = Array.isArray(completedArray) ? [...completedArray] : completedArray;
|
|
2496
|
-
}
|
|
2497
|
-
} else if (parentKey !== void 0) {
|
|
2498
|
-
parent[parentKey] = Array.isArray(completedArray) ? [...completedArray] : completedArray;
|
|
2499
|
-
}
|
|
2500
|
-
this.state = this.getParentState();
|
|
2501
|
-
}
|
|
2502
|
-
}
|
|
2503
|
-
startValue(char) {
|
|
2504
|
-
if (char === '"') {
|
|
2505
|
-
this.state = "IN_STRING";
|
|
2506
|
-
this.stringBuffer = "";
|
|
2507
|
-
this.quoteBuffer = "";
|
|
2508
|
-
this.addValueToParent("");
|
|
2509
|
-
} else if (char.match(/[0-9-]/)) {
|
|
2510
|
-
this.state = "IN_NUMBER";
|
|
2511
|
-
this.numberBuffer = char;
|
|
2512
|
-
this.addValueToParent(parseFloat(char));
|
|
2513
|
-
} else if (char === "t") {
|
|
2514
|
-
this.state = "IN_TRUE";
|
|
2515
|
-
this.stringBuffer = "t";
|
|
2516
|
-
this.addValueToParent("t");
|
|
2517
|
-
} else if (char === "f") {
|
|
2518
|
-
this.state = "IN_FALSE";
|
|
2519
|
-
this.stringBuffer = "f";
|
|
2520
|
-
this.addValueToParent("f");
|
|
2521
|
-
} else if (char === "n") {
|
|
2522
|
-
this.state = "IN_NULL";
|
|
2523
|
-
this.stringBuffer = "n";
|
|
2524
|
-
this.addValueToParent("n");
|
|
2525
|
-
} else if (char === "{") {
|
|
2526
|
-
this.startObject();
|
|
2527
|
-
} else if (char === "[") {
|
|
2528
|
-
this.startArray();
|
|
2529
|
-
} else {
|
|
2530
|
-
throw this.error(`Invalid value start: ${char}`, "value");
|
|
2531
|
-
}
|
|
2532
|
-
}
|
|
2533
|
-
endString() {
|
|
2534
|
-
const value = this.stringBuffer;
|
|
2535
|
-
this.stringBuffer = "";
|
|
2536
|
-
this.updateValueInParent(value);
|
|
2537
|
-
this.state = this.getParentState();
|
|
2538
|
-
}
|
|
2539
|
-
endNumber() {
|
|
2540
|
-
const number = parseFloat(this.numberBuffer);
|
|
2541
|
-
this.updateValueInParent(number);
|
|
2542
|
-
this.numberBuffer = "";
|
|
2543
|
-
this.state = this.getParentState();
|
|
2544
|
-
}
|
|
2545
|
-
endLiteral(literal) {
|
|
2546
|
-
let value;
|
|
2547
|
-
switch (literal) {
|
|
2548
|
-
case "true":
|
|
2549
|
-
value = true;
|
|
2550
|
-
break;
|
|
2551
|
-
case "false":
|
|
2552
|
-
value = false;
|
|
2553
|
-
break;
|
|
2554
|
-
case "null":
|
|
2555
|
-
value = null;
|
|
2556
|
-
break;
|
|
2557
|
-
default:
|
|
2558
|
-
throw this.error("Invalid literal", "literal");
|
|
2559
|
-
}
|
|
2560
|
-
this.updateValueInParent(value);
|
|
2561
|
-
this.stringBuffer = "";
|
|
2562
|
-
this.state = this.getParentState();
|
|
2563
|
-
}
|
|
2564
|
-
addValueToParent(value) {
|
|
2565
|
-
if (this.stack.length === 0) {
|
|
2566
|
-
this.result = value;
|
|
2567
|
-
} else {
|
|
2568
|
-
const stackItem = this.stack[this.stack.length - 1];
|
|
2569
|
-
const { value: parent } = stackItem;
|
|
2570
|
-
if (Array.isArray(parent)) {
|
|
2571
|
-
parent.push(value);
|
|
2572
|
-
if (stackItem.index !== void 0) {
|
|
2573
|
-
stackItem.index++;
|
|
2574
|
-
}
|
|
2575
|
-
} else if (this.state === "IN_OBJECT_KEY") {
|
|
2576
|
-
this.key = value;
|
|
2577
|
-
parent[this.key] = "";
|
|
2578
|
-
} else {
|
|
2579
|
-
if (this.key === void 0) {
|
|
2580
|
-
throw this.error("Key is undefined", "object");
|
|
2581
|
-
}
|
|
2582
|
-
parent[this.key] = value;
|
|
2583
|
-
}
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
updateValueInParent(value) {
|
|
2587
|
-
if (this.stack.length === 0) {
|
|
2588
|
-
this.result = value;
|
|
2589
|
-
} else {
|
|
2590
|
-
const stackItem = this.stack[this.stack.length - 1];
|
|
2591
|
-
const { value: parent } = stackItem;
|
|
2592
|
-
if (Array.isArray(parent)) {
|
|
2593
|
-
if (stackItem.index !== void 0) {
|
|
2594
|
-
parent[stackItem.index - 1] = value;
|
|
2595
|
-
} else {
|
|
2596
|
-
parent[parent.length - 1] = value;
|
|
2597
|
-
}
|
|
2598
|
-
} else if (this.key !== void 0) {
|
|
2599
|
-
parent[this.key] = value;
|
|
2600
|
-
} else if (this.state !== "IN_OBJECT_KEY") {
|
|
2601
|
-
throw this.error("Key is undefined", "object");
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
isWhitespace(char) {
|
|
2606
|
-
return char === " " || char === " " || char === "\n" || char === "\r";
|
|
2607
|
-
}
|
|
2608
|
-
getParentState() {
|
|
2609
|
-
if (this.stack.length === 0) {
|
|
2610
|
-
return "END";
|
|
2611
|
-
}
|
|
2612
|
-
return Array.isArray(this.stack[this.stack.length - 1].value) ? "IN_ARRAY" : "IN_OBJECT";
|
|
2613
|
-
}
|
|
2614
|
-
};
|
|
2615
|
-
function parseCompleteJson(content) {
|
|
2616
|
-
const trimmedContent = content.trim();
|
|
2617
|
-
try {
|
|
2618
|
-
return JSON.parse(trimmedContent);
|
|
2619
|
-
} catch (_e) {
|
|
2620
|
-
try {
|
|
2621
|
-
const parser = new JSONStreamParser();
|
|
2622
|
-
const result = parser.parse(trimmedContent);
|
|
2623
|
-
return result;
|
|
2624
|
-
} catch (e) {
|
|
2625
|
-
console.log("content", trimmedContent);
|
|
2626
|
-
console.error("Error parsing JSON", e);
|
|
2627
|
-
return null;
|
|
2628
|
-
}
|
|
2629
|
-
}
|
|
2630
|
-
}
|
|
2631
|
-
function isWhitespaceChar(char) {
|
|
2632
|
-
return char === " " || char === "\n" || char === " " || char === "\r";
|
|
2633
|
-
}
|
|
2634
|
-
function findNextChar(content, index) {
|
|
2635
|
-
if (index >= content.length - 1) {
|
|
2636
|
-
return "";
|
|
2637
|
-
}
|
|
2638
|
-
for (let i = index + 1; i < content.length; i++) {
|
|
2639
|
-
if (!isWhitespaceChar(content[i])) {
|
|
2640
|
-
return content[i];
|
|
2641
|
-
}
|
|
2642
|
-
}
|
|
2643
|
-
return "";
|
|
2644
|
-
}
|
|
2645
|
-
function parseMixedJson(content) {
|
|
2646
|
-
if (typeof content !== "string") {
|
|
2647
|
-
return content;
|
|
2648
|
-
}
|
|
2649
|
-
const chunks = [];
|
|
2650
|
-
const codeBlockRegex = /```json\s*\n([\s\S]*?)(?:(?:\n)?```|$)/g;
|
|
2651
|
-
const hasCodeBlocks = codeBlockRegex.test(content);
|
|
2652
|
-
codeBlockRegex.lastIndex = 0;
|
|
2653
|
-
if (hasCodeBlocks) {
|
|
2654
|
-
let lastIndex = 0;
|
|
2655
|
-
let match;
|
|
2656
|
-
while ((match = codeBlockRegex.exec(content)) !== null) {
|
|
2657
|
-
const textBefore = content.substring(lastIndex, match.index).trim();
|
|
2658
|
-
if (textBefore) {
|
|
2659
|
-
chunks.push({ content: textBefore, type: "text" });
|
|
2660
|
-
}
|
|
2661
|
-
const jsonStr = match[1];
|
|
2662
|
-
try {
|
|
2663
|
-
const parsed = JSON.parse(jsonStr);
|
|
2664
|
-
chunks.push({ content: parsed, type: "json" });
|
|
2665
|
-
} catch (_e) {
|
|
2666
|
-
try {
|
|
2667
|
-
const parser = new JSONStreamParser();
|
|
2668
|
-
const parsed = parser.parse(jsonStr);
|
|
2669
|
-
if (parsed) {
|
|
2670
|
-
chunks.push({ content: parsed, type: "json" });
|
|
2671
|
-
} else {
|
|
2672
|
-
chunks.push({ content: match[0], type: "text" });
|
|
2673
|
-
}
|
|
2674
|
-
} catch (_fuzzyError) {
|
|
2675
|
-
chunks.push({ content: match[0], type: "text" });
|
|
2676
|
-
}
|
|
2677
|
-
}
|
|
2678
|
-
lastIndex = match.index + match[0].length;
|
|
2679
|
-
}
|
|
2680
|
-
const remainingText = content.substring(lastIndex).trim();
|
|
2681
|
-
if (remainingText) {
|
|
2682
|
-
chunks.push({ content: remainingText, type: "text" });
|
|
2683
|
-
}
|
|
2684
|
-
} else {
|
|
2685
|
-
let currentChunk = "";
|
|
2686
|
-
let jsonParser = null;
|
|
2687
|
-
let isInJson = false;
|
|
2688
|
-
let errorCount = 0;
|
|
2689
|
-
for (let i = 0; i < content.length; i++) {
|
|
2690
|
-
const char = content[i];
|
|
2691
|
-
const nextChar = findNextChar(content, i);
|
|
2692
|
-
if (!isInJson && (char === "{" && nextChar === '"' || char === "[" && nextChar === "{")) {
|
|
2693
|
-
if (currentChunk.trim()) {
|
|
2694
|
-
chunks.push({ content: currentChunk.trim(), type: "text" });
|
|
2695
|
-
}
|
|
2696
|
-
isInJson = true;
|
|
2697
|
-
jsonParser = new JSONStreamParser();
|
|
2698
|
-
currentChunk = "";
|
|
2699
|
-
}
|
|
2700
|
-
if (isInJson) {
|
|
2701
|
-
let result;
|
|
2702
|
-
try {
|
|
2703
|
-
result = jsonParser.add(char);
|
|
2704
|
-
} catch (e) {
|
|
2705
|
-
console.log("currentChunk", currentChunk);
|
|
2706
|
-
console.log("currentResult", jsonParser?.result);
|
|
2707
|
-
console.warn("Error parsing JSON", e);
|
|
2708
|
-
if (errorCount > 3) {
|
|
2709
|
-
throw e;
|
|
2710
|
-
}
|
|
2711
|
-
errorCount++;
|
|
2712
|
-
continue;
|
|
2713
|
-
}
|
|
2714
|
-
currentChunk += char;
|
|
2715
|
-
if (jsonParser.state === "END") {
|
|
2716
|
-
chunks.push({ content: result, type: "json" });
|
|
2717
|
-
isInJson = false;
|
|
2718
|
-
jsonParser = null;
|
|
2719
|
-
currentChunk = "";
|
|
2720
|
-
}
|
|
2721
|
-
} else {
|
|
2722
|
-
currentChunk += char;
|
|
2723
|
-
}
|
|
2724
|
-
}
|
|
2725
|
-
if (currentChunk.trim()) {
|
|
2726
|
-
chunks.push({ content: currentChunk.trim(), type: "text" });
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
return chunks;
|
|
2730
|
-
}
|
|
2731
|
-
function isParsingComplete(value) {
|
|
2732
|
-
return value && typeof value === "object" && !value[parsingSymbol];
|
|
2733
|
-
}
|
|
2734
|
-
function isParsingInProgress(value) {
|
|
2735
|
-
return value && typeof value === "object" && value[parsingSymbol] === true;
|
|
2736
|
-
}
|
|
2737
|
-
|
|
2738
|
-
// src/lib/sse-types.ts
|
|
2739
|
-
function isJsonLike(contentType, uiContentType) {
|
|
2740
|
-
return contentType === "json" || uiContentType === "json";
|
|
2741
|
-
}
|
|
2742
|
-
var InvocationStatus = /* @__PURE__ */ ((InvocationStatus2) => {
|
|
2743
|
-
InvocationStatus2["Pending"] = "pending";
|
|
2744
|
-
InvocationStatus2["Running"] = "running";
|
|
2745
|
-
InvocationStatus2["Success"] = "success";
|
|
2746
|
-
InvocationStatus2["Error"] = "error";
|
|
2747
|
-
InvocationStatus2["RequiresInfo"] = "requires info";
|
|
2748
|
-
InvocationStatus2["GoToStep"] = "go to step";
|
|
2749
|
-
InvocationStatus2["Skipped"] = "skipped";
|
|
2750
|
-
InvocationStatus2["Break"] = "break";
|
|
2751
|
-
return InvocationStatus2;
|
|
2752
|
-
})(InvocationStatus || {});
|
|
2753
|
-
var ExecutionStatus = /* @__PURE__ */ ((ExecutionStatus2) => {
|
|
2754
|
-
ExecutionStatus2["Initializing"] = "initializing";
|
|
2755
|
-
ExecutionStatus2["Running"] = "running";
|
|
2756
|
-
ExecutionStatus2["ProcessingDatasets"] = "processing datasets";
|
|
2757
|
-
ExecutionStatus2["Completed"] = "completed";
|
|
2758
|
-
ExecutionStatus2["Failed"] = "failed";
|
|
2759
|
-
return ExecutionStatus2;
|
|
2760
|
-
})(ExecutionStatus || {});
|
|
2761
|
-
|
|
2762
|
-
// src/lib/handle-sse-event.ts
|
|
2763
|
-
function getEntityType(entity) {
|
|
2764
|
-
if (!entity) throw new Error("Entity is null");
|
|
2765
|
-
if (!("_type" in entity)) throw new Error(`Entity ${JSON.stringify(entity)} is missing _type`);
|
|
2766
|
-
return entity._type;
|
|
2767
|
-
}
|
|
2768
|
-
function getLastMessageContent(message) {
|
|
2769
|
-
if (message.contents.length === 0) {
|
|
2770
|
-
return null;
|
|
2771
|
-
}
|
|
2772
|
-
return message.contents[message.contents.length - 1] || null;
|
|
2773
|
-
}
|
|
2774
|
-
function getFirstMessageContent(message) {
|
|
2775
|
-
if (message.contents.length === 0) {
|
|
2776
|
-
return null;
|
|
2777
|
-
}
|
|
2778
|
-
return message.contents[0] || null;
|
|
2779
|
-
}
|
|
2780
|
-
function getMessage(currentEntity, id) {
|
|
2781
|
-
const entityType = getEntityType(currentEntity);
|
|
2782
|
-
switch (entityType) {
|
|
2783
|
-
case "message":
|
|
2784
|
-
return currentEntity;
|
|
2785
|
-
case "step":
|
|
2786
|
-
const step = currentEntity;
|
|
2787
|
-
if (id) {
|
|
2788
|
-
const existingMessage = step.eventsByID[id]?.Message;
|
|
2789
|
-
if (existingMessage) {
|
|
2790
|
-
return existingMessage;
|
|
2791
|
-
}
|
|
2792
|
-
return createMessage({}, "", id, {});
|
|
2793
|
-
}
|
|
2794
|
-
const eventKeys = Object.keys(step.eventsByID);
|
|
2795
|
-
const eventKeysRev = eventKeys.reverse();
|
|
2796
|
-
for (const ek of eventKeysRev) {
|
|
2797
|
-
const event = step.eventsByID[ek];
|
|
2798
|
-
if (!event) continue;
|
|
2799
|
-
if (event.Message) {
|
|
2800
|
-
return event.Message;
|
|
2801
|
-
}
|
|
2802
|
-
}
|
|
2803
|
-
throw new Error("Unable to find message for step");
|
|
2804
|
-
default:
|
|
2805
|
-
throw new Error(`Unable to have messages on entity type ${entityType}`);
|
|
2806
|
-
}
|
|
2807
|
-
}
|
|
2808
|
-
function getContent(currentEntity, id) {
|
|
2809
|
-
const entityType = getEntityType(currentEntity);
|
|
2810
|
-
switch (entityType) {
|
|
2811
|
-
case "message_content":
|
|
2812
|
-
return currentEntity;
|
|
2813
|
-
case "output_content":
|
|
2814
|
-
return currentEntity;
|
|
2815
|
-
case "message":
|
|
2816
|
-
return getMessageContent(currentEntity, id);
|
|
2817
|
-
case "output":
|
|
2818
|
-
return getStepOutputContent(currentEntity, id);
|
|
2819
|
-
case "step":
|
|
2820
|
-
const output = getStepOutput(currentEntity, id);
|
|
2821
|
-
if (!output) return null;
|
|
2822
|
-
return getStepOutputContent(output, id);
|
|
2823
|
-
default:
|
|
2824
|
-
return null;
|
|
2825
|
-
}
|
|
2826
|
-
}
|
|
2827
|
-
function getMessageContent(currentEntity, id) {
|
|
2828
|
-
const entityType = getEntityType(currentEntity);
|
|
2829
|
-
switch (entityType) {
|
|
2830
|
-
case "message_content":
|
|
2831
|
-
return currentEntity;
|
|
2832
|
-
case "message":
|
|
2833
|
-
const message = getMessage(currentEntity);
|
|
2834
|
-
if (!message) {
|
|
2835
|
-
throw new Error("Unable to find message to add content to");
|
|
2836
|
-
}
|
|
2837
|
-
if (id) {
|
|
2838
|
-
return message.contentsByID[id];
|
|
2839
|
-
}
|
|
2840
|
-
return getLastMessageContent(message);
|
|
2841
|
-
default:
|
|
2842
|
-
throw new Error(`Unable to have message content on entity type ${entityType}`);
|
|
2843
|
-
}
|
|
2844
|
-
}
|
|
2845
|
-
function getStepOutputContent(currentEntity, id) {
|
|
2846
|
-
const entityType = getEntityType(currentEntity);
|
|
2847
|
-
switch (entityType) {
|
|
2848
|
-
case "output_content":
|
|
2849
|
-
return currentEntity;
|
|
2850
|
-
case "output":
|
|
2851
|
-
const output = currentEntity;
|
|
2852
|
-
if (id) {
|
|
2853
|
-
return output.contentsByID[id] || null;
|
|
2854
|
-
}
|
|
2855
|
-
if (output.contents.length <= 0) {
|
|
2856
|
-
return null;
|
|
2857
|
-
}
|
|
2858
|
-
const lastContent = output.contents[output.contents.length - 1];
|
|
2859
|
-
return lastContent || null;
|
|
2860
|
-
case "step":
|
|
2861
|
-
const stepOutput = getStepOutput(currentEntity, id);
|
|
2862
|
-
if (!stepOutput) {
|
|
2863
|
-
return null;
|
|
2864
|
-
}
|
|
2865
|
-
return getStepOutputContent(stepOutput);
|
|
2866
|
-
case "invocation":
|
|
2867
|
-
if (!id) {
|
|
2868
|
-
return null;
|
|
2869
|
-
}
|
|
2870
|
-
const outputEvent = currentEntity.eventsByID[id];
|
|
2871
|
-
if (!outputEvent || !outputEvent.Output) {
|
|
2872
|
-
return null;
|
|
2873
|
-
}
|
|
2874
|
-
return getStepOutputContent(outputEvent.Output);
|
|
2875
|
-
default:
|
|
2876
|
-
throw new Error(`Unable to have output content on entity type ${entityType}`);
|
|
2877
|
-
}
|
|
2878
|
-
}
|
|
2879
|
-
function getBotInvocation(currentEntity, id) {
|
|
2880
|
-
const entityType = getEntityType(currentEntity);
|
|
2881
|
-
let invocation = null;
|
|
2882
|
-
switch (entityType) {
|
|
2883
|
-
case "invocation":
|
|
2884
|
-
return currentEntity;
|
|
2885
|
-
case "message_content":
|
|
2886
|
-
invocation = currentEntity.botInvocation || null;
|
|
2887
|
-
if (!invocation) {
|
|
2888
|
-
throw new Error("Unable to find bot invocation for message content");
|
|
2889
|
-
}
|
|
2890
|
-
if (id && invocation.bot_invocation.id !== id) {
|
|
2891
|
-
throw new Error("Unable to find bot invocation for message content - mismatched ID");
|
|
2892
|
-
}
|
|
2893
|
-
return invocation;
|
|
2894
|
-
case "message":
|
|
2895
|
-
invocation = getFirstMessageContent(currentEntity)?.botInvocation || null;
|
|
2896
|
-
if (!invocation) {
|
|
2897
|
-
throw new Error("Unable to find bot invocation for message");
|
|
2898
|
-
}
|
|
2899
|
-
if (id && invocation.bot_invocation.id !== id) {
|
|
2900
|
-
throw new Error("Unable to find bot invocation for message - mismatched ID");
|
|
2901
|
-
}
|
|
2902
|
-
return invocation;
|
|
2903
|
-
case "output_content":
|
|
2904
|
-
return currentEntity.botInvocation || null;
|
|
2905
|
-
default:
|
|
2906
|
-
throw new Error(`Unable to have bot invocation on entity type ${entityType}`);
|
|
2907
|
-
}
|
|
2908
|
-
}
|
|
2909
|
-
function getStepOutput(currentEntity, id) {
|
|
2910
|
-
const entityType = getEntityType(currentEntity);
|
|
2911
|
-
switch (entityType) {
|
|
2912
|
-
case "output":
|
|
2913
|
-
return currentEntity;
|
|
2914
|
-
case "step":
|
|
2915
|
-
const step = currentEntity;
|
|
2916
|
-
if (id) {
|
|
2917
|
-
const existingOutput = step.eventsByID[id]?.Output;
|
|
2918
|
-
if (!existingOutput) {
|
|
2919
|
-
throw new Error("Unable to find output with id " + id);
|
|
2920
|
-
}
|
|
2921
|
-
return existingOutput;
|
|
2922
|
-
}
|
|
2923
|
-
const eventKeys = Object.keys(step.eventsByID);
|
|
2924
|
-
const eventKeysRev = eventKeys.reverse();
|
|
2925
|
-
for (const ek of eventKeysRev) {
|
|
2926
|
-
const event = step.eventsByID[ek];
|
|
2927
|
-
if (!event) continue;
|
|
2928
|
-
if (event.Output) {
|
|
2929
|
-
return event.Output;
|
|
2930
|
-
}
|
|
2931
|
-
}
|
|
2932
|
-
throw new Error("Unable to find output for step");
|
|
2933
|
-
case "invocation":
|
|
2934
|
-
if (!id) {
|
|
2935
|
-
throw new Error("Unable to find output for invocation without ID");
|
|
2936
|
-
}
|
|
2937
|
-
const invocation = currentEntity;
|
|
2938
|
-
return invocation.eventsByID[id]?.Output || null;
|
|
2939
|
-
default:
|
|
2940
|
-
throw new Error(`Unable to have step outputs on entity type ${entityType}`);
|
|
2941
|
-
}
|
|
2942
|
-
}
|
|
2943
|
-
function getResultHandler(currentEntity, id) {
|
|
2944
|
-
const entityType = getEntityType(currentEntity);
|
|
2945
|
-
switch (entityType) {
|
|
2946
|
-
case "result_handler":
|
|
2947
|
-
return currentEntity;
|
|
2948
|
-
case "step":
|
|
2949
|
-
if (!id) {
|
|
2950
|
-
throw new Error("Unable to have result handlers on step without ID");
|
|
2951
|
-
}
|
|
2952
|
-
const event = currentEntity.eventsByID[id];
|
|
2953
|
-
if (!event || !event.type || event.type !== "result_handler" || !event.ResultHandler) {
|
|
2954
|
-
throw new Error(
|
|
2955
|
-
`Unable to find result handler with id ${id} on step ${currentEntity.id}`
|
|
2956
|
-
);
|
|
2957
|
-
}
|
|
2958
|
-
return event.ResultHandler;
|
|
2959
|
-
default:
|
|
2960
|
-
throw new Error(`Unable to have result handlers on entity type ${entityType}`);
|
|
2961
|
-
}
|
|
2962
|
-
}
|
|
2963
|
-
function getStep(currentEntity, id) {
|
|
2964
|
-
const entityType = getEntityType(currentEntity);
|
|
2965
|
-
let botInvocation = null;
|
|
2966
|
-
switch (entityType) {
|
|
2967
|
-
case "step":
|
|
2968
|
-
if (currentEntity.id === id || !id) {
|
|
2969
|
-
return currentEntity;
|
|
2970
|
-
}
|
|
2971
|
-
throw new Error("Unable to find step on step with id " + id);
|
|
2972
|
-
case "invocation":
|
|
2973
|
-
if (!id) {
|
|
2974
|
-
throw new Error("Unable to have steps on bot invocation without ID");
|
|
2975
|
-
}
|
|
2976
|
-
botInvocation = currentEntity;
|
|
2977
|
-
const event = botInvocation.eventsByID[id];
|
|
2978
|
-
if (!event) {
|
|
2979
|
-
throw new Error("Unable to find step on invocation with id " + id);
|
|
2980
|
-
}
|
|
2981
|
-
if (!event.Step) {
|
|
2982
|
-
throw new Error("Unable to find step on invocation with id " + id);
|
|
2983
|
-
}
|
|
2984
|
-
return event.Step;
|
|
2985
|
-
case "result_handler":
|
|
2986
|
-
if (!id) {
|
|
2987
|
-
throw new Error("Unable to have steps on result handler without ID");
|
|
2988
|
-
}
|
|
2989
|
-
const resultHandler = currentEntity;
|
|
2990
|
-
const resultHandlerEvent = resultHandler.eventsByID[id];
|
|
2991
|
-
if (!resultHandlerEvent) {
|
|
2992
|
-
throw new Error("Unable to find step on result handler with id " + id);
|
|
2993
|
-
}
|
|
2994
|
-
if (!resultHandlerEvent.Step) {
|
|
2995
|
-
throw new Error("Unable to find step on result handler with id " + id);
|
|
2996
|
-
}
|
|
2997
|
-
return resultHandlerEvent.Step;
|
|
2998
|
-
default:
|
|
2999
|
-
throw new Error(`Unable to have steps on entity type ${entityType}`);
|
|
3000
|
-
}
|
|
3001
|
-
}
|
|
3002
|
-
var EntityNotFoundError = class extends Error {
|
|
3003
|
-
};
|
|
3004
|
-
function findNextEntity(currentEntity, path, entityIds) {
|
|
3005
|
-
let nextEntity = null;
|
|
3006
|
-
const pathKey = path[0];
|
|
3007
|
-
const pathID = path[1];
|
|
3008
|
-
entityIds[pathKey] = pathID;
|
|
3009
|
-
try {
|
|
3010
|
-
switch (pathKey) {
|
|
3011
|
-
case "message":
|
|
3012
|
-
nextEntity = getMessage(currentEntity, pathID);
|
|
3013
|
-
break;
|
|
3014
|
-
case "content":
|
|
3015
|
-
nextEntity = getMessageContent(currentEntity, pathID);
|
|
3016
|
-
break;
|
|
3017
|
-
case "step":
|
|
3018
|
-
nextEntity = getStep(currentEntity, pathID);
|
|
3019
|
-
break;
|
|
3020
|
-
case "output":
|
|
3021
|
-
nextEntity = getStepOutput(currentEntity, pathID);
|
|
3022
|
-
break;
|
|
3023
|
-
case "output_content":
|
|
3024
|
-
nextEntity = getStepOutputContent(currentEntity, pathID);
|
|
3025
|
-
break;
|
|
3026
|
-
case "invocation":
|
|
3027
|
-
nextEntity = getBotInvocation(currentEntity, pathID);
|
|
3028
|
-
break;
|
|
3029
|
-
case "result_handler":
|
|
3030
|
-
nextEntity = getResultHandler(currentEntity, pathID);
|
|
3031
|
-
break;
|
|
3032
|
-
}
|
|
3033
|
-
} catch (error) {
|
|
3034
|
-
console.error("error finding next entity");
|
|
3035
|
-
console.log("path", path);
|
|
3036
|
-
console.log("currentEntity", currentEntity);
|
|
3037
|
-
throw error;
|
|
3038
|
-
}
|
|
3039
|
-
if (!nextEntity) {
|
|
3040
|
-
console.log("path", path);
|
|
3041
|
-
console.log("currentEntity", currentEntity);
|
|
3042
|
-
console.log("nextEntity", nextEntity);
|
|
3043
|
-
throw new EntityNotFoundError(`Unable to find next entity for path ${path.join("/")}`);
|
|
3044
|
-
}
|
|
3045
|
-
return nextEntity;
|
|
3046
|
-
}
|
|
3047
|
-
function createMessage(event, threadID, pathID, _entityIds) {
|
|
3048
|
-
const payload = event.payload;
|
|
3049
|
-
return {
|
|
3050
|
-
_type: "message",
|
|
3051
|
-
message: {
|
|
3052
|
-
id: pathID,
|
|
3053
|
-
thread_id: threadID,
|
|
3054
|
-
author_id: payload.author_id || "app",
|
|
3055
|
-
author_entity_type: payload.author_entity_type || "app",
|
|
3056
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3057
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3058
|
-
role: payload.role || "assistant",
|
|
3059
|
-
avatar: "/teams/erdo.svg"
|
|
3060
|
-
},
|
|
3061
|
-
state: "in_progress",
|
|
3062
|
-
contents: [],
|
|
3063
|
-
contentsByID: {},
|
|
3064
|
-
contentIDToIdx: {}
|
|
3065
|
-
};
|
|
3066
|
-
}
|
|
3067
|
-
function createMessageContent(event, entityIds) {
|
|
3068
|
-
return {
|
|
3069
|
-
_type: "message_content",
|
|
3070
|
-
id: event.metadata.message_content_id,
|
|
3071
|
-
message_id: entityIds["message"],
|
|
3072
|
-
content_type: event.metadata.content_type,
|
|
3073
|
-
created_by_invocation_id: event.metadata.invocation_id,
|
|
3074
|
-
invocation_id: event.metadata.invocation_id,
|
|
3075
|
-
state: "in_progress",
|
|
3076
|
-
user_visibility: event.metadata.user_visibility ?? "visible",
|
|
3077
|
-
bot_visibility: event.metadata.bot_visibility ?? "visible",
|
|
3078
|
-
content: "",
|
|
3079
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3080
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3081
|
-
content_params: { RawMessage: null, Valid: false },
|
|
3082
|
-
history_content_type: event.metadata?.history_content_type ? { String: event.metadata.history_content_type, Valid: true } : { String: "", Valid: false },
|
|
3083
|
-
ui_content_type: event.metadata?.ui_content_type ? { String: event.metadata.ui_content_type, Valid: true } : { String: "", Valid: false }
|
|
3084
|
-
};
|
|
3085
|
-
}
|
|
3086
|
-
function createMessageContentFromResult(event, entityIds) {
|
|
3087
|
-
const uiContentType = event.metadata?.ui_content_type;
|
|
3088
|
-
const payloadContent = typeof event.payload === "string" ? event.payload : event.payload.content || event.payload;
|
|
3089
|
-
let parsedJson = null;
|
|
3090
|
-
if (isJsonLike(event.metadata.content_type, uiContentType)) {
|
|
3091
|
-
parsedJson = parseMixedJson(payloadContent);
|
|
3092
|
-
}
|
|
3093
|
-
return {
|
|
3094
|
-
_type: "message_content",
|
|
3095
|
-
id: event.metadata.message_content_id,
|
|
3096
|
-
message_id: entityIds["message"],
|
|
3097
|
-
content: payloadContent,
|
|
3098
|
-
content_type: event.metadata.content_type,
|
|
3099
|
-
created_by_invocation_id: event.metadata.invocation_id,
|
|
3100
|
-
invocation_id: event.metadata.invocation_id,
|
|
3101
|
-
state: "completed",
|
|
3102
|
-
user_visibility: event.metadata.visibility || "visible",
|
|
3103
|
-
bot_visibility: "visible",
|
|
3104
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3105
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3106
|
-
content_params: { RawMessage: null, Valid: false },
|
|
3107
|
-
history_content_type: event.metadata?.history_content_type ? { String: event.metadata.history_content_type, Valid: true } : { String: "", Valid: false },
|
|
3108
|
-
ui_content_type: uiContentType ? { String: uiContentType, Valid: true } : { String: "", Valid: false },
|
|
3109
|
-
parsedJson
|
|
3110
|
-
};
|
|
3111
|
-
}
|
|
3112
|
-
function createStep(event, pathID, entityIds) {
|
|
3113
|
-
const payload = event.payload;
|
|
3114
|
-
return {
|
|
3115
|
-
_type: "step",
|
|
3116
|
-
id: pathID,
|
|
3117
|
-
invocation_id: entityIds.invocation || "",
|
|
3118
|
-
step_id: payload.step_id || "",
|
|
3119
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3120
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3121
|
-
current_status_id: "",
|
|
3122
|
-
path: { String: "", Valid: false },
|
|
3123
|
-
action_type: { String: payload.action_type, Valid: true },
|
|
3124
|
-
key: { String: payload.key, Valid: true },
|
|
3125
|
-
bot_id: payload.bot_id,
|
|
3126
|
-
result_handler_id: "",
|
|
3127
|
-
step_order: { Int32: payload.step_order, Valid: true },
|
|
3128
|
-
output_content_type: { String: payload.content_type, Valid: true },
|
|
3129
|
-
execution_mode: { String: payload.execution_mode, Valid: true },
|
|
3130
|
-
output_behaviour: { String: payload.output_behaviour, Valid: true },
|
|
3131
|
-
user_output_visibility: { String: event.metadata.visibility || "visible", Valid: true },
|
|
3132
|
-
output_channels: payload.output_channels || [],
|
|
3133
|
-
running_message: { String: "", Valid: false },
|
|
3134
|
-
finished_message: { String: "", Valid: false },
|
|
3135
|
-
depends_on: [],
|
|
3136
|
-
eventsByID: {},
|
|
3137
|
-
currentStatus: null
|
|
3138
|
-
};
|
|
3139
|
-
}
|
|
3140
|
-
function createResultHandler(event, pathID, _parentStep) {
|
|
3141
|
-
const payload = event.payload;
|
|
3142
|
-
return {
|
|
3143
|
-
_type: "result_handler",
|
|
3144
|
-
id: pathID,
|
|
3145
|
-
invocation_id: event.metadata.invocation_id || "",
|
|
3146
|
-
result_handler_id: payload.result_handler_id || pathID,
|
|
3147
|
-
step_invocation_id: payload.step_invocation_id || "",
|
|
3148
|
-
type: payload.type || "",
|
|
3149
|
-
if_conditions: payload.if_conditions || {},
|
|
3150
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3151
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3152
|
-
output_content_type: payload.output_content_type || "",
|
|
3153
|
-
result_handler_order: payload.result_handler_order || 0,
|
|
3154
|
-
eventsByID: {}
|
|
3155
|
-
};
|
|
3156
|
-
}
|
|
3157
|
-
function createStepOutput(event, pathID, parentStep) {
|
|
3158
|
-
return {
|
|
3159
|
-
_type: "output",
|
|
3160
|
-
id: pathID,
|
|
3161
|
-
step_id: parentStep.step_id,
|
|
3162
|
-
output: {
|
|
3163
|
-
id: pathID,
|
|
3164
|
-
invocation_id: event.metadata?.invocation_id,
|
|
3165
|
-
path: event.metadata.path,
|
|
3166
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3167
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
3168
|
-
},
|
|
3169
|
-
state: "in_progress",
|
|
3170
|
-
contents: [],
|
|
3171
|
-
contentsByID: {},
|
|
3172
|
-
contentIDToIdx: {}
|
|
3173
|
-
};
|
|
3174
|
-
}
|
|
3175
|
-
function createStepOutputContent(event, pathID, entityIds, visibility = null) {
|
|
3176
|
-
return {
|
|
3177
|
-
_type: "output_content",
|
|
3178
|
-
id: pathID,
|
|
3179
|
-
output_id: entityIds["output"],
|
|
3180
|
-
content: "",
|
|
3181
|
-
content_type: event.metadata.content_type,
|
|
3182
|
-
state: "in_progress",
|
|
3183
|
-
invocation_id: event.metadata.invocation_id,
|
|
3184
|
-
user_visibility: visibility ?? event.metadata.user_visibility ?? "visible",
|
|
3185
|
-
bot_visibility: event.metadata.bot_visibility ?? "visible",
|
|
3186
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3187
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3188
|
-
content_params: { RawMessage: null, Valid: false },
|
|
3189
|
-
history_content_type: event.metadata.history_content_type ? { String: event.metadata.history_content_type, Valid: true } : { String: "", Valid: false },
|
|
3190
|
-
ui_content_type: event.metadata.ui_content_type ? { String: event.metadata.ui_content_type, Valid: true } : { String: "", Valid: false },
|
|
3191
|
-
output: null
|
|
3192
|
-
};
|
|
3193
|
-
}
|
|
3194
|
-
function createStepOutputContentFromResult(event, pathID, entityIds, visibility = null) {
|
|
3195
|
-
let parsedJson = null;
|
|
3196
|
-
const uiContentType = event.metadata?.ui_content_type;
|
|
3197
|
-
if (isJsonLike(event.metadata.content_type, uiContentType)) {
|
|
3198
|
-
parsedJson = parseMixedJson(event.payload);
|
|
3199
|
-
}
|
|
3200
|
-
return {
|
|
3201
|
-
_type: "output_content",
|
|
3202
|
-
id: pathID,
|
|
3203
|
-
output_id: entityIds["output"],
|
|
3204
|
-
content: event.payload,
|
|
3205
|
-
content_type: event.metadata.content_type,
|
|
3206
|
-
state: "completed",
|
|
3207
|
-
invocation_id: event.metadata.invocation_id,
|
|
3208
|
-
parsedJson,
|
|
3209
|
-
user_visibility: visibility || event.metadata.visibility || "visible",
|
|
3210
|
-
bot_visibility: "visible",
|
|
3211
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3212
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3213
|
-
content_params: { RawMessage: null, Valid: false },
|
|
3214
|
-
history_content_type: event.metadata?.history_content_type ? { String: event.metadata.history_content_type, Valid: true } : { String: "", Valid: false },
|
|
3215
|
-
ui_content_type: uiContentType ? { String: uiContentType, Valid: true } : { String: "", Valid: false },
|
|
3216
|
-
output: null
|
|
3217
|
-
};
|
|
3218
|
-
}
|
|
3219
|
-
function createBotInvocation(event, _pathID, _entityIds) {
|
|
3220
|
-
return {
|
|
3221
|
-
_type: "invocation",
|
|
3222
|
-
bot_invocation: {
|
|
3223
|
-
id: event.payload.invocation_id,
|
|
3224
|
-
bot_id: event.payload.bot_id,
|
|
3225
|
-
bot_name: event.payload.bot_name,
|
|
3226
|
-
created_by_user_id: event.payload.created_by_user_id,
|
|
3227
|
-
current_state_id: "",
|
|
3228
|
-
parent_invocation_id: "",
|
|
3229
|
-
branch_init_state_id: "",
|
|
3230
|
-
current_status_id: "",
|
|
3231
|
-
organization_id: "",
|
|
3232
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3233
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
3234
|
-
},
|
|
3235
|
-
eventsByID: {},
|
|
3236
|
-
currentStatus: null,
|
|
3237
|
-
current_status: null,
|
|
3238
|
-
step_invocations: [],
|
|
3239
|
-
step_invocation_states: [],
|
|
3240
|
-
resources: [],
|
|
3241
|
-
outputs: [],
|
|
3242
|
-
statuses: []
|
|
3243
|
-
};
|
|
3244
|
-
}
|
|
3245
|
-
function createStatus(event, _entityIds) {
|
|
3246
|
-
const payload = event.payload;
|
|
3247
|
-
return {
|
|
3248
|
-
_type: "status",
|
|
3249
|
-
id: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3250
|
-
status: payload.status,
|
|
3251
|
-
message: {
|
|
3252
|
-
String: payload.message,
|
|
3253
|
-
Valid: true
|
|
3254
|
-
},
|
|
3255
|
-
Details: payload
|
|
3256
|
-
};
|
|
3257
|
-
}
|
|
3258
|
-
function createStepInvocationEvent(step) {
|
|
3259
|
-
return {
|
|
3260
|
-
id: step.id,
|
|
3261
|
-
type: "step",
|
|
3262
|
-
created_at: step.created_at,
|
|
3263
|
-
_type: "invocation_event",
|
|
3264
|
-
Output: null,
|
|
3265
|
-
Message: null,
|
|
3266
|
-
Status: null,
|
|
3267
|
-
ResultHandler: null,
|
|
3268
|
-
Step: step
|
|
3269
|
-
};
|
|
3270
|
-
}
|
|
3271
|
-
function createOutputInvocationEvent(output) {
|
|
3272
|
-
return {
|
|
3273
|
-
id: output.output.id,
|
|
3274
|
-
type: "output",
|
|
3275
|
-
created_at: output.output.created_at,
|
|
3276
|
-
_type: "invocation_event",
|
|
3277
|
-
Output: output,
|
|
3278
|
-
Message: null,
|
|
3279
|
-
Status: null,
|
|
3280
|
-
ResultHandler: null,
|
|
3281
|
-
Step: null
|
|
3282
|
-
};
|
|
3283
|
-
}
|
|
3284
|
-
function createStatusInvocationEvent(status) {
|
|
3285
|
-
return {
|
|
3286
|
-
id: status.id,
|
|
3287
|
-
type: "status",
|
|
3288
|
-
created_at: status.created_at,
|
|
3289
|
-
_type: "invocation_event",
|
|
3290
|
-
Status: status,
|
|
3291
|
-
Output: null,
|
|
3292
|
-
Message: null,
|
|
3293
|
-
ResultHandler: null,
|
|
3294
|
-
Step: null
|
|
3295
|
-
};
|
|
3296
|
-
}
|
|
3297
|
-
function createMessageInvocationEvent(message) {
|
|
3298
|
-
return {
|
|
3299
|
-
id: message.message.id,
|
|
3300
|
-
type: "message",
|
|
3301
|
-
created_at: message.message.created_at,
|
|
3302
|
-
_type: "invocation_event",
|
|
3303
|
-
Output: null,
|
|
3304
|
-
Message: message,
|
|
3305
|
-
Status: null,
|
|
3306
|
-
ResultHandler: null,
|
|
3307
|
-
Step: null
|
|
3308
|
-
};
|
|
3309
|
-
}
|
|
3310
|
-
function createResultHandlerInvocationEvent(resultHandler) {
|
|
3311
|
-
return {
|
|
3312
|
-
id: resultHandler.id,
|
|
3313
|
-
type: "result_handler",
|
|
3314
|
-
created_at: resultHandler.created_at,
|
|
3315
|
-
_type: "invocation_event",
|
|
3316
|
-
Output: null,
|
|
3317
|
-
Message: null,
|
|
3318
|
-
Status: null,
|
|
3319
|
-
ResultHandler: resultHandler,
|
|
3320
|
-
Step: null
|
|
3321
|
-
};
|
|
3322
|
-
}
|
|
3323
|
-
function handleIncrementalMixedJsonParsing(outputContent, content) {
|
|
3324
|
-
if (!outputContent.content) {
|
|
3325
|
-
outputContent.content = "";
|
|
3326
|
-
}
|
|
3327
|
-
if (outputContent.user_visibility !== "visible" || !isJsonLike(outputContent.content_type, outputContent.ui_content_type.String)) {
|
|
3328
|
-
outputContent.content += content;
|
|
3329
|
-
return { ...outputContent };
|
|
3330
|
-
}
|
|
3331
|
-
if (!outputContent.parsedJson) {
|
|
3332
|
-
outputContent.parsedJson = [];
|
|
3333
|
-
}
|
|
3334
|
-
if (typeof content === "object") {
|
|
3335
|
-
outputContent.content += JSON.stringify(content);
|
|
3336
|
-
outputContent.parsedJson = [...outputContent.parsedJson, content];
|
|
3337
|
-
return { ...outputContent };
|
|
3338
|
-
}
|
|
3339
|
-
if (!outputContent._jsonParser) {
|
|
3340
|
-
outputContent._isInJson = false;
|
|
3341
|
-
}
|
|
3342
|
-
if (!outputContent._charBuffer) {
|
|
3343
|
-
outputContent._charBuffer = "";
|
|
3344
|
-
}
|
|
3345
|
-
for (const char of content) {
|
|
3346
|
-
outputContent.content += char;
|
|
3347
|
-
if (!outputContent._isInJson && char === "{") {
|
|
3348
|
-
outputContent._charBuffer = "{";
|
|
3349
|
-
continue;
|
|
3350
|
-
}
|
|
3351
|
-
if (outputContent._charBuffer && isWhitespaceChar(char)) {
|
|
3352
|
-
outputContent._charBuffer += char;
|
|
3353
|
-
continue;
|
|
3354
|
-
}
|
|
3355
|
-
if (!outputContent._isInJson && outputContent._charBuffer?.match(/^\s*{\s*$/) && char === '"') {
|
|
3356
|
-
outputContent._isInJson = true;
|
|
3357
|
-
outputContent._jsonParser = new JSONStreamParser();
|
|
3358
|
-
const result = outputContent._jsonParser.add("{");
|
|
3359
|
-
const newContent = {
|
|
3360
|
-
content: result,
|
|
3361
|
-
type: "json"
|
|
3362
|
-
};
|
|
3363
|
-
if (!outputContent._currentContent?.content) {
|
|
3364
|
-
outputContent._currentContent = newContent;
|
|
3365
|
-
outputContent.parsedJson = [...outputContent.parsedJson, newContent];
|
|
3366
|
-
} else if (outputContent._currentContent.content.match(/^\s*{$/)) {
|
|
3367
|
-
outputContent._currentContent = newContent;
|
|
3368
|
-
outputContent.parsedJson[outputContent.parsedJson.length - 1] = newContent;
|
|
3369
|
-
} else {
|
|
3370
|
-
outputContent._currentContent.content = outputContent._currentContent.content.replace(/{$/, "");
|
|
3371
|
-
outputContent._currentContent = newContent;
|
|
3372
|
-
outputContent.parsedJson = [...outputContent.parsedJson, newContent];
|
|
3373
|
-
}
|
|
3374
|
-
}
|
|
3375
|
-
if (outputContent._isInJson) {
|
|
3376
|
-
try {
|
|
3377
|
-
const result = outputContent._jsonParser.add(char);
|
|
3378
|
-
outputContent._currentContent.content = result;
|
|
3379
|
-
if (outputContent._jsonParser.state === "END") {
|
|
3380
|
-
outputContent._isInJson = false;
|
|
3381
|
-
outputContent._currentContent = void 0;
|
|
3382
|
-
}
|
|
3383
|
-
} catch (e) {
|
|
3384
|
-
console.log("content", content);
|
|
3385
|
-
console.log("currentContent", outputContent.content);
|
|
3386
|
-
console.error("Error incrementally parsing JSON", e);
|
|
3387
|
-
}
|
|
3388
|
-
} else {
|
|
3389
|
-
if (!outputContent._currentContent) {
|
|
3390
|
-
outputContent._currentContent = {
|
|
3391
|
-
content: outputContent._charBuffer || "",
|
|
3392
|
-
type: "text"
|
|
3393
|
-
};
|
|
3394
|
-
outputContent.parsedJson = [...outputContent.parsedJson, outputContent._currentContent];
|
|
3395
|
-
}
|
|
3396
|
-
outputContent._currentContent.content += outputContent._charBuffer + char;
|
|
3397
|
-
}
|
|
3398
|
-
outputContent._charBuffer = "";
|
|
3399
|
-
}
|
|
3400
|
-
return { ...outputContent };
|
|
3401
|
-
}
|
|
3402
|
-
function appendContentToMessageContent(messageContent, content) {
|
|
3403
|
-
return handleIncrementalMixedJsonParsing(messageContent, content);
|
|
3404
|
-
}
|
|
3405
|
-
function appendContentToStepOutputContent(stepOutputContent, content) {
|
|
3406
|
-
return handleIncrementalMixedJsonParsing(stepOutputContent, content);
|
|
3407
|
-
}
|
|
3408
|
-
function addUpdateEntity(parentEntity, childEntity) {
|
|
3409
|
-
const parentEntityType = getEntityType(parentEntity);
|
|
3410
|
-
switch (parentEntityType) {
|
|
3411
|
-
case "message":
|
|
3412
|
-
return addUpdateToMessage(parentEntity, childEntity);
|
|
3413
|
-
case "message_content":
|
|
3414
|
-
return addUpdateToMessageContent(parentEntity, childEntity);
|
|
3415
|
-
case "step":
|
|
3416
|
-
return addUpdateToStep(parentEntity, childEntity);
|
|
3417
|
-
case "output":
|
|
3418
|
-
return addUpdateToStepOutput(parentEntity, childEntity);
|
|
3419
|
-
case "output_content":
|
|
3420
|
-
return addUpdateToStepOutputContent(parentEntity, childEntity);
|
|
3421
|
-
case "invocation":
|
|
3422
|
-
return addUpdateToInvocation(parentEntity, childEntity);
|
|
3423
|
-
case "result_handler":
|
|
3424
|
-
return addUpdateToResultHandler(parentEntity, childEntity);
|
|
3425
|
-
default:
|
|
3426
|
-
throw new Error(`Unable to add update entity for entity type ${parentEntityType}`);
|
|
3427
|
-
}
|
|
3428
|
-
}
|
|
3429
|
-
function addUpdateEntities(parentEntity, childEntities) {
|
|
3430
|
-
for (const childEntity of childEntities) {
|
|
3431
|
-
parentEntity = addUpdateEntity(parentEntity, childEntity);
|
|
3432
|
-
}
|
|
3433
|
-
return parentEntity;
|
|
3434
|
-
}
|
|
3435
|
-
function addUpdateToMessage(parentEntity, childEntity) {
|
|
3436
|
-
const message = getMessage(parentEntity);
|
|
3437
|
-
if (!message) {
|
|
3438
|
-
throw new Error("Unable to find message to add content to");
|
|
3439
|
-
}
|
|
3440
|
-
const childEntityType = getEntityType(childEntity);
|
|
3441
|
-
let content = null;
|
|
3442
|
-
switch (childEntityType) {
|
|
3443
|
-
case "message_content":
|
|
3444
|
-
content = childEntity;
|
|
3445
|
-
if (!message.contentsByID[content.id]) {
|
|
3446
|
-
message.contentIDToIdx = {
|
|
3447
|
-
...message.contentIDToIdx,
|
|
3448
|
-
[content.id]: message.contents.length
|
|
3449
|
-
};
|
|
3450
|
-
message.contents = [...message.contents, content];
|
|
3451
|
-
} else {
|
|
3452
|
-
message.contents[message.contentIDToIdx[content.id]] = content;
|
|
3453
|
-
}
|
|
3454
|
-
message.contentsByID = {
|
|
3455
|
-
...message.contentsByID,
|
|
3456
|
-
[content.id]: content
|
|
3457
|
-
};
|
|
3458
|
-
return { ...message };
|
|
3459
|
-
case "invocation":
|
|
3460
|
-
const invocation = childEntity;
|
|
3461
|
-
if (message.contents.length === 0) {
|
|
3462
|
-
throw new Error("Unable to find message content to add invocation to");
|
|
3463
|
-
}
|
|
3464
|
-
content = addUpdateToMessageContent(message.contents[0], invocation);
|
|
3465
|
-
return addUpdateToMessage(message, content);
|
|
3466
|
-
case "step":
|
|
3467
|
-
if (message.contents.length === 0) {
|
|
3468
|
-
throw new Error("Unable to find message content to add content to");
|
|
3469
|
-
}
|
|
3470
|
-
content = message.contents[0];
|
|
3471
|
-
if (!content) {
|
|
3472
|
-
throw new Error("Unable to find message content to add content to");
|
|
3473
|
-
}
|
|
3474
|
-
const botInvocation = getBotInvocation(content);
|
|
3475
|
-
if (!botInvocation) {
|
|
3476
|
-
throw new Error("Unable to find bot invocation to add content to");
|
|
3477
|
-
}
|
|
3478
|
-
content.botInvocation = addUpdateToInvocation(botInvocation, childEntity);
|
|
3479
|
-
return addUpdateToMessage(message, content);
|
|
3480
|
-
default:
|
|
3481
|
-
throw new Error(`Unable to add update message child for child type ${childEntityType}`);
|
|
3482
|
-
}
|
|
3483
|
-
}
|
|
3484
|
-
function addUpdateToMessageContent(parentEntity, childEntity) {
|
|
3485
|
-
const messageContent = getMessageContent(parentEntity);
|
|
3486
|
-
if (!messageContent) {
|
|
3487
|
-
throw new Error("Unable to find message content to add content to");
|
|
3488
|
-
}
|
|
3489
|
-
const childEntityType = getEntityType(childEntity);
|
|
3490
|
-
switch (childEntityType) {
|
|
3491
|
-
case "invocation":
|
|
3492
|
-
messageContent.botInvocation = childEntity;
|
|
3493
|
-
return { ...messageContent };
|
|
3494
|
-
case "step":
|
|
3495
|
-
const botInvocation = messageContent.botInvocation;
|
|
3496
|
-
if (!botInvocation) {
|
|
3497
|
-
throw new Error("Unable to find bot invocation to add content to");
|
|
3498
|
-
}
|
|
3499
|
-
messageContent.botInvocation = addUpdateToInvocation(botInvocation, childEntity);
|
|
3500
|
-
return { ...messageContent };
|
|
3501
|
-
default:
|
|
3502
|
-
throw new Error(
|
|
3503
|
-
`Unable to add update message content child for child type ${childEntityType}`
|
|
3504
|
-
);
|
|
3505
|
-
}
|
|
3506
|
-
}
|
|
3507
|
-
function addUpdateToStep(parentEntity, childEntity) {
|
|
3508
|
-
const step = getStep(parentEntity);
|
|
3509
|
-
if (!step) {
|
|
3510
|
-
throw new Error("Unable to find bot invocation to add step to");
|
|
3511
|
-
}
|
|
3512
|
-
const childEntityType = getEntityType(childEntity);
|
|
3513
|
-
let invocationEvent = null;
|
|
3514
|
-
switch (childEntityType) {
|
|
3515
|
-
case "output":
|
|
3516
|
-
const output = childEntity;
|
|
3517
|
-
invocationEvent = createOutputInvocationEvent(output);
|
|
3518
|
-
step.eventsByID = {
|
|
3519
|
-
...step.eventsByID,
|
|
3520
|
-
[output.output.id]: invocationEvent
|
|
3521
|
-
};
|
|
3522
|
-
return { ...step };
|
|
3523
|
-
case "message":
|
|
3524
|
-
const message = childEntity;
|
|
3525
|
-
invocationEvent = createMessageInvocationEvent(message);
|
|
3526
|
-
step.eventsByID = {
|
|
3527
|
-
...step.eventsByID,
|
|
3528
|
-
[message.message.id]: invocationEvent
|
|
3529
|
-
};
|
|
3530
|
-
return { ...step };
|
|
3531
|
-
case "status":
|
|
3532
|
-
const status = childEntity;
|
|
3533
|
-
invocationEvent = createStatusInvocationEvent(status);
|
|
3534
|
-
step.eventsByID = {
|
|
3535
|
-
...step.eventsByID,
|
|
3536
|
-
[status.id]: invocationEvent
|
|
3537
|
-
};
|
|
3538
|
-
return { ...step };
|
|
3539
|
-
case "result_handler":
|
|
3540
|
-
const resultHandler = childEntity;
|
|
3541
|
-
invocationEvent = createResultHandlerInvocationEvent(resultHandler);
|
|
3542
|
-
step.eventsByID = {
|
|
3543
|
-
...step.eventsByID,
|
|
3544
|
-
[resultHandler.id]: invocationEvent
|
|
3545
|
-
};
|
|
3546
|
-
return { ...step };
|
|
3547
|
-
default:
|
|
3548
|
-
throw new Error(`Unable to add update step for entity type ${childEntityType}`);
|
|
3549
|
-
}
|
|
3550
|
-
}
|
|
3551
|
-
function addUpdateToStepOutput(parentEntity, childEntity) {
|
|
3552
|
-
const stepOutput = getStepOutput(parentEntity);
|
|
3553
|
-
if (!stepOutput) {
|
|
3554
|
-
throw new Error("Unable to find step output to add content to");
|
|
3555
|
-
}
|
|
3556
|
-
const childEntityType = getEntityType(childEntity);
|
|
3557
|
-
switch (childEntityType) {
|
|
3558
|
-
case "output_content":
|
|
3559
|
-
const outputContent = childEntity;
|
|
3560
|
-
if (!stepOutput.contentsByID[outputContent.id]) {
|
|
3561
|
-
stepOutput.contentIDToIdx = {
|
|
3562
|
-
...stepOutput.contentIDToIdx,
|
|
3563
|
-
[outputContent.id]: stepOutput.contents.length
|
|
3564
|
-
};
|
|
3565
|
-
stepOutput.contents = [...stepOutput.contents, outputContent];
|
|
3566
|
-
} else {
|
|
3567
|
-
stepOutput.contents[stepOutput.contentIDToIdx[outputContent.id]] = outputContent;
|
|
3568
|
-
}
|
|
3569
|
-
stepOutput.contentsByID = {
|
|
3570
|
-
...stepOutput.contentsByID,
|
|
3571
|
-
[outputContent.id]: outputContent
|
|
3572
|
-
};
|
|
3573
|
-
return { ...stepOutput };
|
|
3574
|
-
default:
|
|
3575
|
-
throw new Error(`Unable to add update output for entity type ${childEntityType}`);
|
|
3576
|
-
}
|
|
3577
|
-
}
|
|
3578
|
-
function addUpdateToStepOutputContent(parentEntity, childEntity) {
|
|
3579
|
-
const stepOutputContent = getStepOutputContent(parentEntity);
|
|
3580
|
-
if (!stepOutputContent) {
|
|
3581
|
-
throw new Error("Unable to find step output content to add content to");
|
|
3582
|
-
}
|
|
3583
|
-
const childEntityType = getEntityType(childEntity);
|
|
3584
|
-
switch (childEntityType) {
|
|
3585
|
-
case "invocation":
|
|
3586
|
-
stepOutputContent.botInvocation = childEntity;
|
|
3587
|
-
return { ...stepOutputContent };
|
|
3588
|
-
case "step":
|
|
3589
|
-
const botInvocation = stepOutputContent.botInvocation;
|
|
3590
|
-
if (!botInvocation) {
|
|
3591
|
-
throw new Error("Unable to find bot invocation to add content to");
|
|
3592
|
-
}
|
|
3593
|
-
stepOutputContent.botInvocation = addUpdateToInvocation(botInvocation, childEntity);
|
|
3594
|
-
return { ...stepOutputContent };
|
|
3595
|
-
default:
|
|
3596
|
-
throw new Error(
|
|
3597
|
-
`Unable to add update step output content for entity type ${childEntityType}`
|
|
3598
|
-
);
|
|
3599
|
-
}
|
|
3600
|
-
}
|
|
3601
|
-
function addUpdateToInvocation(parentEntity, childEntity) {
|
|
3602
|
-
const botInvocation = getBotInvocation(parentEntity);
|
|
3603
|
-
if (!botInvocation) {
|
|
3604
|
-
throw new Error("Unable to find bot invocation to add content to");
|
|
3605
|
-
}
|
|
3606
|
-
const childEntityType = getEntityType(childEntity);
|
|
3607
|
-
let invocationEvent;
|
|
3608
|
-
switch (childEntityType) {
|
|
3609
|
-
case "step":
|
|
3610
|
-
const step = childEntity;
|
|
3611
|
-
invocationEvent = createStepInvocationEvent(step);
|
|
3612
|
-
botInvocation.eventsByID = {
|
|
3613
|
-
...botInvocation.eventsByID,
|
|
3614
|
-
[step.id]: invocationEvent
|
|
3615
|
-
};
|
|
3616
|
-
return { ...botInvocation };
|
|
3617
|
-
case "output":
|
|
3618
|
-
const output = childEntity;
|
|
3619
|
-
invocationEvent = createOutputInvocationEvent(output);
|
|
3620
|
-
botInvocation.eventsByID = {
|
|
3621
|
-
...botInvocation.eventsByID,
|
|
3622
|
-
[output.output.id]: invocationEvent
|
|
3623
|
-
};
|
|
3624
|
-
return { ...botInvocation };
|
|
3625
|
-
case "status":
|
|
3626
|
-
const status = childEntity;
|
|
3627
|
-
invocationEvent = createStatusInvocationEvent(status);
|
|
3628
|
-
botInvocation.eventsByID = {
|
|
3629
|
-
...botInvocation.eventsByID,
|
|
3630
|
-
[status.id]: invocationEvent
|
|
3631
|
-
};
|
|
3632
|
-
return { ...botInvocation };
|
|
3633
|
-
default:
|
|
3634
|
-
throw new Error(`Unable to add update invocation for entity type ${childEntityType}`);
|
|
3635
|
-
}
|
|
3636
|
-
}
|
|
3637
|
-
function addUpdateToResultHandler(parentEntity, childEntity) {
|
|
3638
|
-
const resultHandler = getResultHandler(parentEntity);
|
|
3639
|
-
if (!resultHandler) {
|
|
3640
|
-
throw new Error("Unable to find result handler to add content to");
|
|
3641
|
-
}
|
|
3642
|
-
const childEntityType = getEntityType(childEntity);
|
|
3643
|
-
let invocationEvent = null;
|
|
3644
|
-
switch (childEntityType) {
|
|
3645
|
-
case "step":
|
|
3646
|
-
const step = childEntity;
|
|
3647
|
-
invocationEvent = createStepInvocationEvent(step);
|
|
3648
|
-
if (!resultHandler.eventsByID) {
|
|
3649
|
-
resultHandler.eventsByID = {};
|
|
3650
|
-
}
|
|
3651
|
-
resultHandler.eventsByID = {
|
|
3652
|
-
...resultHandler.eventsByID,
|
|
3653
|
-
[step.id]: invocationEvent
|
|
3654
|
-
};
|
|
3655
|
-
return { ...resultHandler };
|
|
3656
|
-
case "output":
|
|
3657
|
-
const output = childEntity;
|
|
3658
|
-
invocationEvent = createOutputInvocationEvent(output);
|
|
3659
|
-
if (!resultHandler.eventsByID) {
|
|
3660
|
-
resultHandler.eventsByID = {};
|
|
3661
|
-
}
|
|
3662
|
-
resultHandler.eventsByID = {
|
|
3663
|
-
...resultHandler.eventsByID,
|
|
3664
|
-
[output.output.id]: invocationEvent
|
|
3665
|
-
};
|
|
3666
|
-
return { ...resultHandler };
|
|
3667
|
-
case "status":
|
|
3668
|
-
const status = childEntity;
|
|
3669
|
-
invocationEvent = createStatusInvocationEvent(status);
|
|
3670
|
-
if (!resultHandler.eventsByID) {
|
|
3671
|
-
resultHandler.eventsByID = {};
|
|
3672
|
-
}
|
|
3673
|
-
resultHandler.eventsByID = {
|
|
3674
|
-
...resultHandler.eventsByID,
|
|
3675
|
-
[status.id]: invocationEvent
|
|
3676
|
-
};
|
|
3677
|
-
return { ...resultHandler };
|
|
3678
|
-
default:
|
|
3679
|
-
throw new Error(`Unable to add update to result handler for entity type ${childEntityType}`);
|
|
3680
|
-
}
|
|
3681
|
-
}
|
|
3682
|
-
function getIsEventTypeCreatingEvent(eventType) {
|
|
3683
|
-
return eventType === "bot started" || eventType === "bot resumed" || eventType === "message created" || eventType === "create message content" || eventType === "message content result" || eventType === "step started" || eventType === "result handler started" || eventType === "state created" || eventType === "step output created" || eventType === "create step output content" || eventType === "step output content result" || eventType === "log";
|
|
3684
|
-
}
|
|
3685
|
-
function handleSSEEvent(eventType, event, path, threadID, activeMessagesByID, currentEntity = null, parents = [], entityIds = {}) {
|
|
3686
|
-
if (!currentEntity) {
|
|
3687
|
-
if (Object.keys(activeMessagesByID).length > 0) {
|
|
3688
|
-
let _message;
|
|
3689
|
-
let messageId;
|
|
3690
|
-
if (path.length >= 2 && path[0] === "message") {
|
|
3691
|
-
messageId = path[1];
|
|
3692
|
-
_message = activeMessagesByID[messageId];
|
|
3693
|
-
if (!_message) {
|
|
3694
|
-
_message = Object.values(activeMessagesByID)[0];
|
|
3695
|
-
messageId = Object.keys(activeMessagesByID)[0];
|
|
3696
|
-
}
|
|
3697
|
-
} else {
|
|
3698
|
-
_message = Object.values(activeMessagesByID)[Object.values(activeMessagesByID).length - 1];
|
|
3699
|
-
messageId = Object.keys(activeMessagesByID)[Object.keys(activeMessagesByID).length - 1];
|
|
3700
|
-
}
|
|
3701
|
-
entityIds["message"] = messageId;
|
|
3702
|
-
if (path.length <= 2 && eventType === "message finished") {
|
|
3703
|
-
return null;
|
|
3704
|
-
}
|
|
3705
|
-
if (path[0] !== "content") {
|
|
3706
|
-
if (Object.keys(_message.contentsByID).length > 0 && event.metadata.message_content_id) {
|
|
3707
|
-
const _messageContentId = event.metadata.message_content_id;
|
|
3708
|
-
const _messageContent = _message.contentsByID[_messageContentId];
|
|
3709
|
-
if (_messageContent) {
|
|
3710
|
-
currentEntity = _messageContent;
|
|
3711
|
-
}
|
|
3712
|
-
}
|
|
3713
|
-
}
|
|
3714
|
-
if (!currentEntity) {
|
|
3715
|
-
currentEntity = _message;
|
|
3716
|
-
} else {
|
|
3717
|
-
parents = [_message];
|
|
3718
|
-
}
|
|
3719
|
-
}
|
|
3720
|
-
}
|
|
3721
|
-
if (path.length <= 2 && getIsEventTypeCreatingEvent(eventType)) {
|
|
3722
|
-
const pathID = path[1];
|
|
3723
|
-
let res = [];
|
|
3724
|
-
let message, messageContent, rootMessage, rootMessageContent, newContent;
|
|
3725
|
-
switch (eventType) {
|
|
3726
|
-
case "bot started":
|
|
3727
|
-
case "bot resumed":
|
|
3728
|
-
if (!currentEntity) {
|
|
3729
|
-
throw new Error("Unable to find message to add content to");
|
|
3730
|
-
}
|
|
3731
|
-
const botInvocation = createBotInvocation(event, pathID, entityIds);
|
|
3732
|
-
if (currentEntity._type === "message_content") {
|
|
3733
|
-
messageContent = currentEntity;
|
|
3734
|
-
if (!messageContent.id) {
|
|
3735
|
-
throw new Error("Unable to find message content id");
|
|
3736
|
-
}
|
|
3737
|
-
rootMessage = activeMessagesByID[messageContent.message_id];
|
|
3738
|
-
if (!rootMessage) {
|
|
3739
|
-
throw new Error("Unable to find message to add content to");
|
|
3740
|
-
}
|
|
3741
|
-
rootMessageContent = getMessageContent(rootMessage, messageContent.id);
|
|
3742
|
-
if (!rootMessageContent) {
|
|
3743
|
-
throw new Error("Unable to find message content to add content to");
|
|
3744
|
-
}
|
|
3745
|
-
const updatedMessageContent = addUpdateToMessageContent(
|
|
3746
|
-
rootMessageContent,
|
|
3747
|
-
botInvocation
|
|
3748
|
-
);
|
|
3749
|
-
activeMessagesByID[messageContent.message_id] = {
|
|
3750
|
-
...addUpdateToMessage(rootMessage, updatedMessageContent)
|
|
3751
|
-
};
|
|
3752
|
-
}
|
|
3753
|
-
res.push(botInvocation);
|
|
3754
|
-
break;
|
|
3755
|
-
case "message created":
|
|
3756
|
-
activeMessagesByID[pathID] = createMessage(event, threadID, pathID, entityIds);
|
|
3757
|
-
if (!currentEntity) {
|
|
3758
|
-
return null;
|
|
3759
|
-
}
|
|
3760
|
-
return null;
|
|
3761
|
-
case "create message content":
|
|
3762
|
-
if (!currentEntity) {
|
|
3763
|
-
throw new Error("Unable to find message to add content to");
|
|
3764
|
-
}
|
|
3765
|
-
newContent = createMessageContent(event, entityIds);
|
|
3766
|
-
if (currentEntity._type === "output") {
|
|
3767
|
-
message = currentEntity;
|
|
3768
|
-
res.push(createStepOutputContent(event, pathID, entityIds, "hidden"));
|
|
3769
|
-
let messageId = event.payload.message_id;
|
|
3770
|
-
if (!messageId) {
|
|
3771
|
-
messageId = parents[0].message.id;
|
|
3772
|
-
}
|
|
3773
|
-
rootMessage = activeMessagesByID[messageId];
|
|
3774
|
-
if (!rootMessage) {
|
|
3775
|
-
throw new Error("Unable to find message to add content to");
|
|
3776
|
-
}
|
|
3777
|
-
} else if (currentEntity._type === "message_content") {
|
|
3778
|
-
message = currentEntity;
|
|
3779
|
-
rootMessage = activeMessagesByID[message.message_id];
|
|
3780
|
-
if (!rootMessage) {
|
|
3781
|
-
throw new Error("Unable to find message to add content to");
|
|
3782
|
-
}
|
|
3783
|
-
} else {
|
|
3784
|
-
if (currentEntity._type !== "message") {
|
|
3785
|
-
throw new Error(
|
|
3786
|
-
`Incorrect path? Cannot add content to non-message entity: ${currentEntity._type}`
|
|
3787
|
-
);
|
|
3788
|
-
}
|
|
3789
|
-
message = currentEntity;
|
|
3790
|
-
rootMessage = activeMessagesByID[message.message.id];
|
|
3791
|
-
if (!rootMessage) {
|
|
3792
|
-
throw new Error("Unable to find message to add content to");
|
|
3793
|
-
}
|
|
3794
|
-
res.push(newContent);
|
|
3795
|
-
}
|
|
3796
|
-
activeMessagesByID[rootMessage.message.id] = {
|
|
3797
|
-
...addUpdateToMessage(rootMessage, newContent)
|
|
3798
|
-
};
|
|
3799
|
-
break;
|
|
3800
|
-
case "message content result":
|
|
3801
|
-
if (!currentEntity) {
|
|
3802
|
-
throw new Error("Unable to find message to add content to");
|
|
3803
|
-
}
|
|
3804
|
-
let parentMessage = null;
|
|
3805
|
-
if (currentEntity._type === "output") {
|
|
3806
|
-
res.push(createStepOutputContentFromResult(event, pathID, entityIds, "hidden"));
|
|
3807
|
-
let messageId = event.payload.message_id || entityIds["message"];
|
|
3808
|
-
if (messageId) {
|
|
3809
|
-
parentMessage = parents.find(
|
|
3810
|
-
(parent) => parent.message.id === messageId
|
|
3811
|
-
);
|
|
3812
|
-
} else {
|
|
3813
|
-
parentMessage = parents[0];
|
|
3814
|
-
}
|
|
3815
|
-
rootMessage = activeMessagesByID[messageId];
|
|
3816
|
-
if (!rootMessage) {
|
|
3817
|
-
throw new Error("Unable to find message to add content to");
|
|
3818
|
-
}
|
|
3819
|
-
} else if (currentEntity._type === "message_content") {
|
|
3820
|
-
parentMessage = parents[0];
|
|
3821
|
-
rootMessage = activeMessagesByID[parentMessage.message.id];
|
|
3822
|
-
if (!rootMessage) {
|
|
3823
|
-
throw new Error("Unable to find message to add content to");
|
|
3824
|
-
}
|
|
3825
|
-
} else {
|
|
3826
|
-
if (currentEntity._type !== "message") {
|
|
3827
|
-
throw new Error(
|
|
3828
|
-
`Incorrect path? Cannot add content to non-message entity: ${currentEntity._type}`
|
|
3829
|
-
);
|
|
3830
|
-
}
|
|
3831
|
-
parentMessage = currentEntity;
|
|
3832
|
-
rootMessage = activeMessagesByID[parentMessage.message.id];
|
|
3833
|
-
if (!rootMessage) {
|
|
3834
|
-
throw new Error("Unable to find message to add content to");
|
|
3835
|
-
}
|
|
3836
|
-
}
|
|
3837
|
-
const messageContentId = event.metadata.message_content_id;
|
|
3838
|
-
if (!messageContentId) {
|
|
3839
|
-
throw new Error("Unable to find message content id");
|
|
3840
|
-
}
|
|
3841
|
-
let newMessageContentContent = getMessageContent(parentMessage, messageContentId);
|
|
3842
|
-
if (newMessageContentContent) {
|
|
3843
|
-
newMessageContentContent.state = "completed";
|
|
3844
|
-
const payloadContent = typeof event.payload === "string" ? event.payload : event.payload.content || event.payload;
|
|
3845
|
-
newMessageContentContent.content = payloadContent;
|
|
3846
|
-
activeMessagesByID[rootMessage.message.id] = {
|
|
3847
|
-
...addUpdateToMessage(rootMessage, newMessageContentContent)
|
|
3848
|
-
};
|
|
3849
|
-
if (currentEntity._type === "message" || currentEntity._type === "message_content") {
|
|
3850
|
-
res.push(newMessageContentContent);
|
|
3851
|
-
}
|
|
3852
|
-
} else {
|
|
3853
|
-
newMessageContentContent = createMessageContentFromResult(event, entityIds);
|
|
3854
|
-
activeMessagesByID[rootMessage.message.id] = {
|
|
3855
|
-
...addUpdateToMessage(rootMessage, newMessageContentContent)
|
|
3856
|
-
};
|
|
3857
|
-
if (currentEntity._type === "message" || currentEntity._type === "message_content") {
|
|
3858
|
-
res.push(newMessageContentContent);
|
|
3859
|
-
}
|
|
3860
|
-
}
|
|
3861
|
-
break;
|
|
3862
|
-
case "step started":
|
|
3863
|
-
res.push(createStep(event, pathID, entityIds));
|
|
3864
|
-
break;
|
|
3865
|
-
case "result handler started":
|
|
3866
|
-
res.push(createResultHandler(event, pathID, currentEntity));
|
|
3867
|
-
break;
|
|
3868
|
-
case "step output created":
|
|
3869
|
-
res.push(createStepOutput(event, pathID, currentEntity));
|
|
3870
|
-
break;
|
|
3871
|
-
case "create step output content":
|
|
3872
|
-
res.push(createStepOutputContent(event, pathID, entityIds));
|
|
3873
|
-
break;
|
|
3874
|
-
case "step output content result":
|
|
3875
|
-
res.push(createStepOutputContentFromResult(event, pathID, entityIds));
|
|
3876
|
-
break;
|
|
3877
|
-
case "log":
|
|
3878
|
-
return null;
|
|
3879
|
-
default:
|
|
3880
|
-
throw new Error(`Unable to handle create event type ${eventType}`);
|
|
3881
|
-
}
|
|
3882
|
-
if (!res.length) return null;
|
|
3883
|
-
if (!currentEntity) {
|
|
3884
|
-
return res[0];
|
|
3885
|
-
}
|
|
3886
|
-
if (currentEntity._type === "message_content" && res.length === 1 && res[0]._type === "message_content") {
|
|
3887
|
-
return res[0];
|
|
3888
|
-
}
|
|
3889
|
-
return addUpdateEntities(currentEntity, res);
|
|
3890
|
-
}
|
|
3891
|
-
if (!currentEntity) {
|
|
3892
|
-
throw new Error("No first message has been created, so cannot handle amend events");
|
|
3893
|
-
}
|
|
3894
|
-
if (path.length <= 1) {
|
|
3895
|
-
let content = null;
|
|
3896
|
-
try {
|
|
3897
|
-
content = getContent(currentEntity);
|
|
3898
|
-
} catch (err) {
|
|
3899
|
-
}
|
|
3900
|
-
switch (eventType) {
|
|
3901
|
-
case "message content delta":
|
|
3902
|
-
if (!content) {
|
|
3903
|
-
throw new Error("Unable to find message content");
|
|
3904
|
-
}
|
|
3905
|
-
let newContent = null;
|
|
3906
|
-
let messageContent = null;
|
|
3907
|
-
let parentMessage = null;
|
|
3908
|
-
if (currentEntity._type === "output_content") {
|
|
3909
|
-
const outputContent = currentEntity;
|
|
3910
|
-
newContent = appendContentToStepOutputContent(outputContent, event.payload);
|
|
3911
|
-
const messageContentId = event.metadata.message_content_id;
|
|
3912
|
-
if (!messageContentId) {
|
|
3913
|
-
throw new Error("Unable to find message content id from entity ids");
|
|
3914
|
-
}
|
|
3915
|
-
const messageId = entityIds["message"];
|
|
3916
|
-
parentMessage = parents.find(
|
|
3917
|
-
(parent) => parent.message.id === messageId
|
|
3918
|
-
);
|
|
3919
|
-
if (!parentMessage) {
|
|
3920
|
-
throw new Error("Unable to find message to add content to");
|
|
3921
|
-
}
|
|
3922
|
-
messageContent = getMessageContent(parentMessage, messageContentId);
|
|
3923
|
-
} else {
|
|
3924
|
-
messageContent = content;
|
|
3925
|
-
parentMessage = parents[parents.length - 1];
|
|
3926
|
-
if (!parentMessage) {
|
|
3927
|
-
throw new Error("Unable to find message to add content to");
|
|
3928
|
-
}
|
|
3929
|
-
if (parentMessage._type !== "message") {
|
|
3930
|
-
throw new Error("Unable to find message to add content to - not a message");
|
|
3931
|
-
}
|
|
3932
|
-
}
|
|
3933
|
-
if (!messageContent) {
|
|
3934
|
-
throw new Error("Unable to find message content");
|
|
3935
|
-
}
|
|
3936
|
-
const rootMessage = activeMessagesByID[parentMessage.message.id];
|
|
3937
|
-
if (!rootMessage) {
|
|
3938
|
-
throw new Error("Unable to find message to add content to");
|
|
3939
|
-
}
|
|
3940
|
-
const newMessageContent = appendContentToMessageContent(
|
|
3941
|
-
messageContent,
|
|
3942
|
-
event.payload
|
|
3943
|
-
);
|
|
3944
|
-
activeMessagesByID[rootMessage.message.id] = {
|
|
3945
|
-
...addUpdateToMessage(rootMessage, newMessageContent)
|
|
3946
|
-
};
|
|
3947
|
-
if (currentEntity._type === "message_content") {
|
|
3948
|
-
newContent = newMessageContent;
|
|
3949
|
-
}
|
|
3950
|
-
return newContent;
|
|
3951
|
-
case "step output content delta":
|
|
3952
|
-
return appendContentToStepOutputContent(
|
|
3953
|
-
content,
|
|
3954
|
-
event.payload
|
|
3955
|
-
);
|
|
3956
|
-
case "status":
|
|
3957
|
-
if (currentEntity._type === "step") {
|
|
3958
|
-
currentEntity.currentStatus = createStatus(event, entityIds);
|
|
3959
|
-
}
|
|
3960
|
-
if (currentEntity._type === "invocation") {
|
|
3961
|
-
currentEntity.currentStatus = createStatus(event, entityIds);
|
|
3962
|
-
}
|
|
3963
|
-
return addUpdateEntity(currentEntity, createStatus(event, entityIds));
|
|
3964
|
-
case "result":
|
|
3965
|
-
return null;
|
|
3966
|
-
case "message finished":
|
|
3967
|
-
return null;
|
|
3968
|
-
case "step output finished":
|
|
3969
|
-
return null;
|
|
3970
|
-
case "step result":
|
|
3971
|
-
return null;
|
|
3972
|
-
case "error":
|
|
3973
|
-
return null;
|
|
3974
|
-
case "dataset created":
|
|
3975
|
-
return null;
|
|
3976
|
-
case "log":
|
|
3977
|
-
return null;
|
|
3978
|
-
default:
|
|
3979
|
-
throw new Error(`Unable to handle event type ${eventType}`);
|
|
3980
|
-
}
|
|
3981
|
-
}
|
|
3982
|
-
const nextPath = path.slice(2);
|
|
3983
|
-
const nextEntity = findNextEntity(currentEntity, path, entityIds);
|
|
3984
|
-
const updatedEntity = handleSSEEvent(
|
|
3985
|
-
eventType,
|
|
3986
|
-
event,
|
|
3987
|
-
nextPath,
|
|
3988
|
-
threadID,
|
|
3989
|
-
activeMessagesByID,
|
|
3990
|
-
nextEntity,
|
|
3991
|
-
[...parents, currentEntity],
|
|
3992
|
-
entityIds
|
|
3993
|
-
);
|
|
3994
|
-
if (updatedEntity) {
|
|
3995
|
-
return addUpdateEntity(currentEntity, { ...updatedEntity });
|
|
3996
|
-
}
|
|
3997
|
-
return currentEntity;
|
|
3998
|
-
}
|
|
3999
|
-
export {
|
|
4000
|
-
BarChart,
|
|
4001
|
-
Chart,
|
|
4002
|
-
ChartContainer,
|
|
4003
|
-
ChartContent2 as ChartContent,
|
|
4004
|
-
ChartLegend,
|
|
4005
|
-
ChartLegendContent,
|
|
4006
|
-
ChartStyle,
|
|
4007
|
-
ChartTooltip,
|
|
4008
|
-
ChartTooltipContent,
|
|
4009
|
-
Content,
|
|
4010
|
-
DatasetChart,
|
|
4011
|
-
ErdoProvider,
|
|
4012
|
-
ErrorBoundary,
|
|
4013
|
-
ExecutionStatus,
|
|
4014
|
-
HeatmapChart,
|
|
4015
|
-
InvocationStatus,
|
|
4016
|
-
JSONStreamParser,
|
|
4017
|
-
JsonContent,
|
|
4018
|
-
LineChart,
|
|
4019
|
-
MarkdownContent,
|
|
4020
|
-
PieChart,
|
|
4021
|
-
ScatterChart,
|
|
4022
|
-
TableContent,
|
|
4023
|
-
TextContent,
|
|
4024
|
-
cn,
|
|
4025
|
-
formatValue,
|
|
4026
|
-
handleIncrementalMixedJsonParsing,
|
|
4027
|
-
handleSSEEvent,
|
|
4028
|
-
isJsonLike,
|
|
4029
|
-
isParsingComplete,
|
|
4030
|
-
isParsingInProgress,
|
|
4031
|
-
isWhitespaceChar,
|
|
4032
|
-
parseCompleteJson,
|
|
4033
|
-
parseMixedJson,
|
|
4034
|
-
parseToDate,
|
|
4035
|
-
resolveKeyFromData,
|
|
4036
|
-
toSnakeCase,
|
|
4037
|
-
useChartZoom,
|
|
4038
|
-
useDatasetContents,
|
|
4039
|
-
useErdoConfig,
|
|
4040
|
-
useErdoConfigOptional,
|
|
4041
|
-
useInvocation,
|
|
4042
|
-
useMultipleDatasetContents
|
|
4043
|
-
};
|
|
1
|
+
import*as H from'react';import H__default,{createContext,useMemo,useRef,useEffect,useState,useContext,useCallback}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import*as X from'recharts';import {Bar,BarChart,Line,LineChart,Scatter,ScatterChart,CartesianGrid,XAxis,Label,YAxis,ReferenceArea,PieChart,Pie,Cell,Tooltip,Legend}from'recharts';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {format}from'd3-format';import {utcFormat}from'd3-time-format';import {isValid,parse}from'date-fns';import {useToPng}from'@hugocxl/react-to-image';import {Download}from'lucide-react';import Rn from'lodash/isEqual';import {useDeepCompareMemo}from'use-deep-compare';import {useQueries,useQuery}from'@tanstack/react-query';import Zn from'react-markdown';import zn from'remark-gfm';var At=createContext(null);function re({children:t,config:e}){return jsx(At.Provider,{value:e,children:t})}function Z(){let t=useContext(At);if(!t)throw new Error("useErdoConfig must be used within an ErdoProvider");return t}function ae(){return useContext(At)}var z=class extends H__default.Component{constructor(e){super(e),this.state={hasError:false};}static getDerivedStateFromError(e){return {hasError:true}}componentDidCatch(e,n){console.error("ErrorBoundary caught an error:",e,n);}render(){return this.state.hasError?this.props.fallback:this.props.children}};function A(...t){return twMerge(clsx(t))}var We={light:"",dark:".dark"},se=H.createContext(null);function oe(){let t=H.useContext(se);if(!t)throw new Error("useChart must be used within a <ChartContainer />");return t}function pt({id:t,className:e,children:n,config:a,debounceResize:r=false,...s}){let o=H.useId(),i=`chart-${t||o.replace(/:/g,"")}`;return jsx(se.Provider,{value:{config:a},children:jsxs("div",{"data-slot":"chart","data-chart":i,className:A("[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",e),...s,children:[jsx(ie,{id:i,config:a}),jsx(X.ResponsiveContainer,{debounce:r?200:0,children:n})]})})}var ie=({id:t,config:e})=>{let n=Object.entries(e).filter(([,a])=>a.theme||a.color);return n.length?jsx("style",{dangerouslySetInnerHTML:{__html:Object.entries(We).map(([a,r])=>`
|
|
2
|
+
${r} [data-chart=${t}] {
|
|
3
|
+
${n.map(([s,o])=>{let i=o.theme?.[a]||o.color;return i?` --color-${s}: ${i};`:null}).join(`
|
|
4
|
+
`)}
|
|
5
|
+
}
|
|
6
|
+
`).join(`
|
|
7
|
+
`)}}):null},Jt=X.Tooltip;function $t({active:t,payload:e,className:n,indicator:a="dot",hideLabel:r=false,hideIndicator:s=false,label:o,labelFormatter:i,labelClassName:l,formatter:p,color:u,nameKey:d,labelKey:c}){let{config:m}=oe(),f=H.useMemo(()=>{if(r||!e?.length)return null;let[y]=e,w=`${c||y?.dataKey||y?.name||"value"}`,I=Ut(m,y,w),_=!c&&typeof o=="string"?m[o]?.label||o:I?.label;return i?jsx("div",{className:A("font-medium",l),children:i(_,e)}):_?jsx("div",{className:A("font-medium",l),children:_}):null},[o,i,e,r,l,m,c]);if(!t||!e?.length)return null;let g=e.length===1&&a!=="dot";return jsxs("div",{className:A("border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl",n),children:[g?null:f,jsx("div",{className:"grid gap-1.5",children:e.map((y,w)=>{let I=`${d||y.name||y.dataKey||"value"}`,_=Ut(m,y,I),V=u||y.payload.fill||y.color;return jsx("div",{className:A("[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",a==="dot"&&"items-center"),children:p&&y?.value!==void 0&&y.name?p(y.value,y.name,y,w,y.payload):jsxs(Fragment,{children:[_?.icon?jsx(_.icon,{}):!s&&jsx("div",{className:A("shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",{"h-2.5 w-2.5":a==="dot","w-1":a==="line","w-0 border-[1.5px] border-dashed bg-transparent":a==="dashed","my-0.5":g&&a==="dashed"}),style:{"--color-bg":V,"--color-border":V}}),jsxs("div",{className:A("flex flex-1 justify-between leading-none",g?"items-end":"items-center"),children:[jsxs("div",{className:"grid gap-1.5",children:[g?f:null,jsx("span",{className:"text-muted-foreground",children:_?.label||y.name})]}),y.value&&jsx("span",{className:"text-foreground font-mono font-medium tabular-nums",children:y.value.toLocaleString()})]})]})},y.dataKey)})})]})}var Ft=X.Legend;function jt({className:t,hideIcon:e=false,payload:n,verticalAlign:a="bottom",nameKey:r}){let{config:s}=oe();return n?.length?jsx("div",{className:A("flex items-center justify-center gap-4",a==="top"?"pb-3":"pt-3",t),children:n.map(o=>{let i=`${r||o.dataKey||"value"}`,l=Ut(s,o,i);return jsxs("div",{className:A("[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3"),children:[l?.icon&&!e?jsx(l.icon,{}):jsx("div",{className:"h-2 w-2 shrink-0 rounded-[2px]",style:{backgroundColor:o.color}}),l?.label]},o.value)})}):null}function Ut(t,e,n){if(typeof e!="object"||e===null)return;let a="payload"in e&&typeof e.payload=="object"&&e.payload!==null?e.payload:void 0,r=n;return n in e&&typeof e[n]=="string"?r=e[n]:a&&n in a&&typeof a[n]=="string"&&(r=a[n]),r in t?t[r]:t[n]}function gt(t,e,n){if(t==null)return "";if(n==="date"){let a=le(t);if(a&&e)try{let r=e;e==="%Y%m%d"?r="%Y-%m-%d":e==="%d%m%Y"?r="%d-%m-%Y":e==="%m%d%Y"&&(r="%m-%d-%Y");let s=r.match(/%./g)||[],o="aAbBcdejHILmMpSUwWxXyYZ%";return s.some(p=>{let u=p.charAt(1);return !o.includes(u)})||s.length===0?(console.warn(`Invalid date format directives in: ${e}. Using default format.`),a.toISOString().split("T")[0]):utcFormat(r)(a)}catch(r){return console.warn(`Invalid date format: ${e}. Error: ${r}. Falling back to default.`),a.toISOString().split("T")[0]}if(a){let r=a.toISOString();return r.endsWith("T00:00:00.000Z")?r.split("T")[0]:a.toISOString().replace("T"," ").replace(".000Z"," UTC")}return String(t)}if(n==="number"){let a=typeof t=="string"?parseFloat(t.replace(/,/g,"")):t;if(isNaN(a))return String(t);let r=e;if(e&&(r=e.replace(/(\.\d+)f%/,"$1%")),!r)return Math.abs(a)>=1e3?format(",.0f")(a):Math.abs(a)>=100?format(".1f")(a):Math.abs(a)>=10?format(".2f")(a):Math.abs(a)>=1?format(".3f")(a):format(".3g")(a);if(r.includes("%"))return a>=0&&a<=1?format(r)(a):format(r)(a/100);try{return format(r)(a)}catch(s){return console.warn(`Error formatting number with format '${r}': ${s}. Falling back to default.`),Math.abs(a)>=1e3?format(",.0f")(a):Math.abs(a)>=1?format(".2f")(a):format(".3g")(a)}}return String(t)}function le(t){if(!t)return null;if(t instanceof Date)return isValid(t)?t:null;if(typeof t=="number"){let n=new Date(t);return isValid(n)?n:null}if(typeof t=="string"){if(/^\d{4}-\d{2}-\d{2}$/.test(t)){let r=new Date(t+"T00:00:00.000Z");if(isValid(r))return r}let a=["yyyy-MM-dd","yyyyMMdd","yyyy-MM-dd'T'HH:mm:ss","yyyyMMddHHmmss","MM/dd/yyyy","dd/MM/yyyy"];for(let r of a){let s=parse(t,r,new Date);if(isValid(s))return s}}let e=new Date(t);return isValid(e)?e:null}function xt({onZoomChange:t}={}){let[e,n]=useState({refAreaLeft:null,refAreaRight:null,refAreaTop:null,refAreaBottom:null,zooming:false}),[a,r]=useState({x:[null,null],y:[null,null]}),s=useCallback(u=>{!u?.xValue||!u?.yValue||n(d=>({...d,refAreaLeft:u.xValue,refAreaTop:u.yValue,zooming:true}));},[]),o=useCallback(u=>{!u?.xValue||!u?.yValue||!e.zooming||n(d=>({...d,refAreaRight:u.xValue,refAreaBottom:u.yValue}));},[e.zooming]),i=useCallback(()=>{if(!e.refAreaLeft||!e.refAreaRight||!e.refAreaTop||!e.refAreaBottom){n({refAreaLeft:null,refAreaRight:null,refAreaTop:null,refAreaBottom:null,zooming:false});return}let[u,d]=[Math.min(e.refAreaLeft,e.refAreaRight),Math.max(e.refAreaLeft,e.refAreaRight)],[c,m]=[Math.min(e.refAreaTop,e.refAreaBottom),Math.max(e.refAreaTop,e.refAreaBottom)],f={x:[u,d],y:[c,m]};r(f),t?.(f),n({refAreaLeft:null,refAreaRight:null,refAreaTop:null,refAreaBottom:null,zooming:false});},[e,t]),l=useCallback(()=>{let u={x:[null,null],y:[null,null]};r(u),t?.(u);},[t]),p=useMemo(()=>({onZoomStart:s,onZoomMove:o,onZoomEnd:i,onResetZoom:l}),[s,o,i,l]);return {zoomState:e,customDomain:a,handlers:p}}function de(t){let e={max:null,min:null};if(t.maxValue)if(t.type==="number"){let n=parseFloat(t.maxValue);isNaN(n)?console.warn(`Error parsing max value ${t.maxValue}. Falling back to default.`):e.max=n;}else t.type==="date"?typeof t.maxValue=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(t.maxValue)?e.max=new Date(t.maxValue+"T00:00:00.000Z").getTime():e.max=new Date(t.maxValue).getTime():e.max=t.maxValue;if(t.minValue)if(t.type==="number"){let n=parseFloat(t.minValue);isNaN(n)?console.warn(`Error parsing min value ${t.minValue}. Falling back to default.`):e.min=n;}else t.type==="date"?typeof t.minValue=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(t.minValue)?e.min=new Date(t.minValue+"T00:00:00.000Z").getTime():e.min=new Date(t.minValue).getTime():e.min=t.minValue;return e}function tt(t,e,n){return gt(t,e,n)}function rn({title:t,subtitle:e,data:n,displayConfig:a,dataConfig:r,ChartComponent:s,PointComponent:o,disableAnimation:i,onZoomChange:l,stacked:p,enableDownload:u=true,onDownloadSuccess:d,onDownloadError:c}){let{zoomState:m,customDomain:f,handlers:g}=xt({onZoomChange:l}),y=useCallback(h=>{let v=`${t.toLowerCase().replace(/\s+/g,"-")}.png`,x=document.createElement("a");x.download=v,x.href=h,x.click(),d?.(v);},[t,d]),w=useCallback(h=>{console.error("Error converting chart to image:",h),c?.(h);},[c]),[{isLoading:I},_,V]=useToPng({onSuccess:y,onError:w}),T=useCallback(async()=>{_();},[_]),k=useMemo(()=>de(r.xAxis),[r.xAxis]),J=useMemo(()=>r.yAxes.map(h=>de(h)),[r.yAxes]),N=useMemo(()=>n?r.chartType==="histogram"?n.map(h=>({[r.xAxis.key]:(h.binStart+h.binEnd)/2,frequency:h.frequency,binStart:h.binStart,binEnd:h.binEnd})):r.xAxis.type==="number"?n.filter(h=>!isNaN(h[r.xAxis.key])):r.xAxis.type==="date"?n.filter(h=>!isNaN(h[r.xAxis.key])):n:[],[n,r.xAxis.key,r.chartType,r.xAxis.type]),ct=useCallback((h,v)=>{if(!h?.length)return {min:null,max:null};let x=h.map(S=>Number(S[v])).filter(S=>!isNaN(S));return {min:Math.min(...x),max:Math.max(...x)}},[]),dt=useMemo(()=>({x:f.x[0]!==null&&f.x[1]!==null?[f.x[0],f.x[1]]:(()=>{if(k.min!==null&&k.max!==null)return [k.min,k.max];let h=ct(N,r.xAxis.key);return [h.min??"auto",h.max??"auto"]})(),y:r.yAxes.map((h,v)=>{if(f.y[0]!==null&&f.y[1]!==null)return [f.y[0],f.y[1]];let S=r.series.filter(D=>(D.axisIndex||0)===v).reduce((D,L)=>{let P=ct(N,L.key);return {min:D.min===null?P.min:P.min===null?D.min:Math.min(D.min,P.min),max:D.max===null?P.max:P.max===null?D.max:Math.max(D.max,P.max)}},{min:null,max:null});if(h.type==="number"&&h.maxValue){let D=parseFloat(h.maxValue);if(S.max===null||D<=S.max*1.5)return [J[v].min??S.min??"auto",J[v].max??S.max??"auto"]}return [J[v].min??S.min??"auto",J[v].max??S.max??"auto"]})}),[f.x,f.y,k,J,r.series,r.yAxes,r.xAxis.key,N,ct]),Mt=useCallback((h,v,x)=>{if(x.dataKey===r.xAxis.key)return tt(h,r.xAxis.format,r.xAxis.type);let D=r.series.find(L=>L.key===x.dataKey)?.name||String(v).replace(/^dataset_\d+_/,"");if(r.chartType==="histogram"){let L=x.payload;if(L.binStart!==void 0){let P=tt(L.binStart,r.xAxis.format,r.xAxis.type),Pt=tt(L.binEnd,r.xAxis.format,r.xAxis.type);return `Count: ${h} (${P} - ${Pt})`}}return `${D}: ${h}`},[r.xAxis,r.series,r.chartType]),[b,C]=useState(false);useEffect(()=>{let h=setTimeout(()=>{C(true);},1700);return ()=>clearTimeout(h)},[]);let R=useMemo(()=>!!(i||(n?.length||0)>100||b),[i,n?.length,b]);return jsxs("div",{className:"items-center mt-0 flex flex-col gap-0",children:[jsxs("div",{className:"w-full items-center mb-2 relative",children:[jsx("h2",{className:"text-center text-base pt-0 mt-0 mb-2",children:t}),u&&jsx("button",{onClick:T,disabled:I,className:"text-sm text-gray-500 hover:text-gray-700 disabled:opacity-50 h-8 absolute right-0 top-[-5px] px-2 py-1 border rounded hover:bg-gray-50",title:"Download chart as PNG",children:jsx(Download,{className:"w-4 h-4"})})]}),e&&jsx("p",{className:"text-center text-sm text-muted-foreground mb-2",children:e}),jsx(pt,{ref:V,config:a,className:"w-full mb-4 border border-accent p-4 rounded-md",debounceResize:true,children:jsxs(s,{accessibilityLayer:true,data:N,isAnimationActive:!R,onMouseDown:g.onZoomStart,onMouseMove:g.onZoomMove,onMouseUp:g.onZoomEnd,onDoubleClick:g.onResetZoom,style:{userSelect:"none",cursor:"crosshair"},children:[jsx(CartesianGrid,{vertical:false}),jsx(XAxis,{dataKey:r.xAxis.key,domain:dt.x,type:r.xAxis.type==="date"||!r.xAxis.type?"number":r.xAxis.type,tickFormatter:h=>tt(h,r.xAxis.format,r.xAxis.type),tickLine:false,tickMargin:10,height:50,axisLine:false,allowDataOverflow:true,children:jsx(Label,{value:r.xAxis.label,position:"bottom",offset:-10,style:{textAnchor:"middle"}})}),r.yAxes.map((h,v)=>jsx(YAxis,{yAxisId:v,orientation:v===0?"left":"right",domain:p?void 0:dt.y[v],type:h.type==="date"||!h.type?"number":h.type,tickFormatter:x=>tt(x,h.format,h.type),allowDataOverflow:true,children:jsx(Label,{value:h.label,position:v===0?"insideLeft":"insideRight",angle:-90,style:{textAnchor:"middle"}})},`y-axis-${v}`)),jsx(Jt,{content:h=>jsx($t,{...h,formatter:Mt,labelFormatter:(v,x)=>{if(x&&x.length>0){let S=x[0].payload[r.xAxis.key],D=tt(S,r.xAxis.format,r.xAxis.type);return jsxs("div",{className:"flex flex-col",children:[jsx("span",{children:r.xAxis.label}),jsx("span",{className:"font-mono tabular-nums",children:D})]})}return v}})}),jsx(Ft,{content:h=>jsx(jt,{...h}),verticalAlign:"top"}),r.series.map(h=>jsx(o,{dataKey:h.key,yAxisId:h.axisIndex||0,fill:h.color||"blue",stroke:h.color||"blue",dot:{fill:h.color||"blue",stroke:h.color||"blue"},radius:4,name:h.name,isAnimationActive:!R,animationDuration:1500,animationBegin:0,stackId:r.chartType==="bar"&&p?"stack":void 0},`${h.key}-${p?"stacked":"unstacked"}`)),m.refAreaLeft&&m.refAreaRight&&m.refAreaTop&&m.refAreaBottom&&jsx(ReferenceArea,{x1:m.refAreaLeft,x2:m.refAreaRight,y1:m.refAreaTop,y2:m.refAreaBottom,strokeOpacity:.2,stroke:"currentColor",fill:"currentColor",fillOpacity:.02,style:{pointerEvents:"none"}})]})}),f.x[0]!==null&&jsx("button",{onClick:g.onResetZoom,className:"text-sm text-gray-500 hover:text-gray-700 mt-2 px-3 py-1 border rounded hover:bg-gray-50",children:"Reset Zoom"})]})}function $(t){return jsx(z,{fallback:jsx("div",{className:"text-red-500",children:"Failed to load chart"}),children:jsx(rn,{...t})})}function Y(t){return jsx($,{...t,ChartComponent:BarChart,PointComponent:Bar})}function et(t){return jsx($,{...t,ChartComponent:LineChart,PointComponent:Line})}var yn=(t,e,n)=>{let a=parseInt(t.slice(1,3),16)/255,r=parseInt(t.slice(3,5),16)/255,s=parseInt(t.slice(5,7),16)/255,o=Math.max(a,r,s),i=Math.min(a,r,s),l,p,u=(o+i)/2;if(o===i)l=p=0;else {let g=o-i;switch(p=u>.5?g/(2-o-i):g/(o+i),o){case a:l=(r-s)/g+(r<s?6:0);break;case r:l=(s-a)/g+2;break;case s:l=(a-r)/g+4;break;default:l=0;}l/=6;}let d=e/n,c=l*360+(d*40-20),m=Math.min(100,p*100+d*25),f=Math.max(35,Math.min(65,u*100-d*20));return `hsl(${c}, ${m}%, ${f}%)`};function bn({title:t,subtitle:e,data:n,displayConfig:a,dataConfig:r}){let s=r.series[0]?.color||"blue",o=useMemo(()=>n.reduce((i,l)=>(r.series.forEach(p=>{let u=p.key,d=String(l[r.xAxis.key]||"Unknown"),c=parseFloat(l[u]||"0");isNaN(c)||i.push({name:d,value:c,seriesId:u,displayName:d});}),i),[]).sort((i,l)=>l.value-i.value),[n,r.series,r.xAxis.key]);return jsxs("div",{className:"items-center",children:[jsx("h2",{className:"text-center text-base mb-2",children:t}),e&&jsx("p",{className:"text-center text-sm text-muted-foreground mb-2",children:e}),jsx(pt,{config:a,className:"w-full mb-4 border border-accent rounded-md",children:jsxs(PieChart,{width:400,height:400,children:[jsx(Pie,{data:o,dataKey:"value",nameKey:"displayName",cx:"50%",cy:"50%",outerRadius:150,label:i=>`${i.displayName}: ${i.value}%`,children:o.map((i,l)=>jsx(Cell,{fill:l===0?s:yn(s,l,o.length)},`cell-${l}`))}),jsx(Tooltip,{formatter:(i,l)=>[`${i}%`,l]}),jsx(Legend,{})]})})]})}function nt(t){return jsx(z,{fallback:jsx("div",{className:"text-red-500",children:"Failed to load chart"}),children:jsx(bn,{...t})})}function rt(t){return jsx($,{...t,ChartComponent:ScatterChart,PointComponent:Scatter})}var kn=t=>{let{cx:e,cy:n,payload:a,xAxis:r,yAxis:s}=t,o=a.value||a.z||0,l=`hsl(${240-Math.min(1,Math.max(0,o/100))*240}, 70%, 50%)`,p=r.scale.bandwidth?r.scale.bandwidth():20,u=s.scale.bandwidth?s.scale.bandwidth():20;return jsx("rect",{x:e-p/2,y:n-u/2,width:p,height:u,fill:l,fillOpacity:.8,stroke:"#fff",strokeWidth:1})},wn=t=>jsx(Scatter,{...t,shape:kn});function at(t){return jsx($,{...t,ChartComponent:ScatterChart,PointComponent:wn})}async function fe(t,e,n){if(t.dataFetcher)return t.dataFetcher.fetchDatasetContents(e,n);let a,r={"Content-Type":"application/json"};t.sessionToken?(a=`${t.baseUrl}/datasets/${encodeURIComponent(e)}/query-with-session?limit=1000`,r.Authorization=`Bearer ${t.sessionToken}`):(a=`${t.baseUrl}/datasets/${encodeURIComponent(e)}/query?limit=1000`,t.authToken&&(r.Authorization=`Bearer ${t.authToken}`));let s=await fetch(a,{headers:r});if(!s.ok)throw new Error(`Failed to fetch dataset contents: ${s.statusText}`);let o=await s.json();return !o.Columns||!o.Rows||o.Columns.length===0?[]:o.Rows.map(i=>{let l={};return o.Columns.forEach((p,u)=>{l[p]=i[u];}),l})}function ge(t,e){let n=Z();return useQuery({queryKey:["datasetContents",t,e],queryFn:()=>fe(n,t,e),enabled:!!t&&!!e})}function kt(t,e){let n=Z();return useQueries({queries:t.map(a=>({queryKey:["datasetContents",a,e],queryFn:()=>fe(n,a,e),enabled:!!a&&!!e}))})}function me(t){return t.replace(/[A-Z]/g,e=>`_${e.toLowerCase()}`).replace(/^_/,"")}function wt(t,e){if(!t.length)return e;let n=t[0];if(n[e]!==void 0)return e;let a=e.toLowerCase();if(n[a]!==void 0)return a;let r=me(e);if(n[r]!==void 0)return r;let s=e.toLowerCase().replace(/_/g,"");return Object.keys(n).find(i=>i.toLowerCase().replace(/_/g,"")===s)||e}function Pn(){return ["yyyy-MM-dd","yyyyMMdd","yyyy-MM-dd'T'HH:mm:ss","yyyyMMddHHmmss"]}function Vn(t){if(!t)return null;if(typeof t=="string"){if(/^\d{4}-\d{2}-\d{2}$/.test(t)){let r=new Date(t+"T00:00:00.000Z");if(isValid(r))return r.getTime()}let a=Pn();for(let r of a){let s=parse(t,r,new Date);if(isValid(s))return s.getTime()}}let e=new Date(t);return isValid(e)?e.getTime():null}function Et(t,e,n,a){let r=e==="index"&&t[e]===void 0?a:t[e];return n==="date"?Vn(r):n==="number"?parseFloat(r):r}function An(t,e,n){if(t===e.key)return e.type||"category";let a=n.find(r=>r.key===t);return a?a.type||"number":"category"}function yt(t,e,n,a){return !a||a.length===0?t:[...t].sort((r,s)=>{for(let o of a){let i=An(o.key,e,n),l=Et(r,o.key,i,r.index),p=Et(s,o.key,i,s.index);if(l===p)continue;let u=typeof l=="number"&&typeof p=="number"?l-p:l instanceof Date&&p instanceof Date?l.getTime()-p.getTime():String(l).localeCompare(String(p));return o.direction==="asc"?u:-u}return 0})}function he(t,e){let n=Math.ceil(t.length/e),a=[t[0]];for(let r=n;r<t.length-1;r+=n)a.push(t[r]);return a[a.length-1]!==t[t.length-1]&&a.push(t[t.length-1]),a}function Un(t,e,n,a,r,s,o){let i=t.reduce((u,d)=>{let c=d[e];return u[c]||(u[c]=[]),u[c].push(d),u},{}),l=Object.entries(i);if(l.length>a){let u=Math.ceil(l.length/a),d=l.reduce((c,[m,f],g)=>{let y=Math.floor(g/u);return c[y]||(c[y]={key:m,items:[]}),c[y].items.push(...f),c},[]).map(({key:c,items:m})=>({[e]:c,...n.reduce((f,g)=>{let y=m.map(w=>parseFloat(w[g.key])).filter(w=>!isNaN(w));return f[g.key]=y.length?y.reduce((w,I)=>w+I,0)/y.length:null,f},{})}));return o&&o.length>0?yt(d,r,s,o):d}let p=l.map(([u,d])=>{let c=n.reduce((f,g)=>{let y=d.map(w=>parseFloat(w[g.key])).filter(w=>!isNaN(w));return f[g.key]=y.length?y.reduce((w,I)=>w+I,0)/y.length:null,f},{}),m=Object.values(c).filter(f=>f!==null).reduce((f,g)=>f+g,0);return {[e]:u,...c,index:m}});return o&&o.length>0?yt(p,r,s,o):p}function Jn(t,e,n,a){let r=t.map(p=>parseFloat(p[e])).filter(p=>!isNaN(p)),s=Math.min(...r),i=(Math.max(...r)-s)/a,l=Array.from({length:a},(p,u)=>({binStart:s+u*i,binEnd:s+(u+1)*i,count:0,seriesValues:n.reduce((d,c)=>(d[c.key]=[],d),{})}));return t.forEach(p=>{let u=parseFloat(p[e]);if(isNaN(u))return;let d=Math.min(Math.floor((u-s)/i),a-1);l[d].count++,n.forEach(c=>{let m=parseFloat(p[c.key]);isNaN(m)||l[d].seriesValues[c.key].push(m);});}),l.map(p=>({[e]:(p.binStart+p.binEnd)/2,...n.reduce((u,d)=>{let c=p.seriesValues[d.key];return u[d.key]=c.length?c.reduce((m,f)=>m+f,0)/c.length:null,u},{}),count:p.count,index:n.reduce((u,d)=>{let c=p.seriesValues[d.key],m=c.length?c.reduce((f,g)=>f+g,0)/c.length:0;return u+m},0)})).filter(p=>n.some(u=>p[u.key]!==null))}function ye(t,e,n,a,r){let s=t.map((m,f)=>{let g=Et(m,e,r.type||"number",f);return typeof g=="number"?g:parseFloat(g)}).filter(m=>!isNaN(m)),o=Math.min(...s),p=(Math.max(...s)-o)/a,u=Array.from({length:a},(m,f)=>({binStart:Number((o+f*p).toFixed(2)),binEnd:Number((o+(f+1)*p).toFixed(2)),frequency:0,[e]:Number((o+(f+.5)*p).toFixed(2))}));s.forEach(m=>{let f=Math.min(Math.floor((m-o)/p),a-1);u[f].frequency++;});let d=u.filter(m=>m.frequency>0);return (u.length-d.length)/u.length*100>30?ye(t,e,n,Math.floor(a/2),r):d}function $n(t,e,n,a){return !e||e.length===0?t:t.filter(r=>e.every(s=>{let o=s.key;n&&s.key.toLowerCase()===n.toLowerCase()?o=n:a&&s.key.toLowerCase()===a.toLowerCase()&&(o=a);let i=r[o],l=Array.isArray(s.value)?s.value:[s.value];switch(s.operator){case "equals":return l.some(p=>String(i)===String(p));case "not_equals":return l.every(p=>String(i)!==String(p));case "greater_than":return parseFloat(String(i))>parseFloat(String(l[0]));case "less_than":return parseFloat(String(i))<parseFloat(String(l[0]));case "contains":return String(i).toLowerCase().includes(String(l[0]).toLowerCase());case "between":if(l.length===2){let p=parseFloat(String(i)),u=parseFloat(String(l[0])),d=parseFloat(String(l[1]));return p>=u&&p<=d}return true;default:return true}}))}var be=H__default.memo(function({chartType:e,title:n,invocationId:a,datasetSlugs:r,xAxis:s,yAxes:o,series:i,dataReduction:l={strategy:"none",target_points:1e3},stacked:p,sort:u,onScrollUpdate:d}){let c=kt(r,a),m=c.some(b=>b.isLoading),f=c.map(b=>b.data),g=useDeepCompareMemo(()=>f.map(b=>b||[]),[f]),{resolvedXAxisKey:y,resolvedSeriesKeys:w}=useMemo(()=>{let b=g.find(C=>C.length>0)||[];return {resolvedXAxisKey:wt(b,s.key),resolvedSeriesKeys:i.map(C=>({...C,resolvedKey:wt(b,C.key)}))}},[g,s.key,i]),I=useMemo(()=>{let b=g.reduce((R,h,v)=>(i.filter(S=>S.datasetSlug===r[v]).forEach(S=>{let D=w.find(P=>P.datasetSlug===S.datasetSlug&&P.key===S.key)?.resolvedKey||S.key;(S.filters?$n(h,S.filters,D,y):h).forEach((P,Pt)=>{let W=Et(P,y,s.type||"category",Pt);if(W==null||s.type==="number"&&isNaN(W))return;let Vt=s.type==="number"||s.type==="date"||typeof W=="object"?W.toString():String(W);R.has(Vt)||R.set(Vt,{[s.key]:W});let Ve=`dataset_${r.findIndex(Ue=>Ue===S.datasetSlug)}_series_${i.indexOf(S)}_${S.key}`,Ae=P[D];R.get(Vt)[Ve]=Ae;});}),R),new Map),C=Array.from(b.values());return u&&u.length>0?C:C.sort((R,h)=>{if(s.type==="date")return R[s.key]-h[s.key];let v=parseFloat(R[s.key]),x=parseFloat(h[s.key]);return isNaN(v)||isNaN(x)?String(R[s.key]).localeCompare(String(h[s.key])):v-x})},[g,i,r,w,y,s,u]),_=useMemo(()=>i.map((b,C)=>{let R=r.findIndex(h=>h===b.datasetSlug);return {...b,key:`dataset_${R}_series_${C}_${b.key}`}}),[i,r]),V=useMemo(()=>({[s.key]:{label:s.label,format:s.format,type:s.type},..._.reduce((b,C)=>(b[C.key]={label:C.name,color:C.color},b),{}),...e==="histogram"?{frequency:{label:o[0]?.label||"Frequency",color:_[0]?.color||"#2563eb"}}:{}}),[s,_,e,o]),T=useMemo(()=>!s.key||!_.length?null:{chartType:e,xAxis:s,yAxes:e==="histogram"?o.map(b=>({...b,key:"frequency",minValue:b.minValue||"0"})):o,series:e==="histogram"?[{key:"frequency",name:o[0]?.label||"Frequency",color:i[0]?.color||"#2563eb"}]:_},[s,o,i,_,e]),k=null;switch(e){case "bar":k=Y;break;case "line":k=et;break;case "pie":k=nt;break;case "scatter":k=rt;break;case "histogram":k=Y;break;case "heatmap":k=at;break}let J=useRef(false);useEffect(()=>{J.current||!d||!m&&V&&T&&I.length&&(d(),setTimeout(()=>d(),250),J.current=true);},[d,m,V,T,I.length]);let[N,ct]=useState({x:[null,null],y:[null,null]}),{processedData:dt,dataReductionInfo:Mt}=useMemo(()=>{if(m||!I.length)return {processedData:[],dataReductionInfo:null};if(e==="histogram"){let v=l.target_points||20;return {processedData:ye(I,y,_,v,s),dataReductionInfo:null}}let b=I;if((N.x[0]!==null||N.y[0]!==null)&&(b=I.filter(v=>{if(N.x[0]!==null&&N.x[1]!==null){let x=parseFloat(v[s.key]);if(isNaN(x)||x<N.x[0]||x>N.x[1])return false}if(N.y[0]!==null&&N.y[1]!==null)for(let x of _){let S=parseFloat(v[x.key]);if(!isNaN(S)&&(S<N.y[0]||S>N.y[1]))return false}return true})),b.length<=l.target_points&&(!u||u.length===0))return {processedData:b,dataReductionInfo:null};let C,R="";switch(l.strategy){case "sample":C=he(b,l.target_points),R="sampled",u&&u.length>0&&(C=yt(C,s,o,u));break;case "aggregate":C=Un(b,y,_,l.target_points,s,o,u),R="aggregated";break;case "bin":C=Jn(b,y,_,l.target_points),R="binning",u&&u.length>0&&(C=yt(C,s,o,u));break;default:b.length<1e3?C=b:(C=he(b,l.target_points),R="sampled"),u&&u.length>0&&(C=yt(C,s,o,u));}let h=null;return b.length!==C.length&&(h=`${R} ${b.length.toLocaleString()} \u2192 ${C.length.toLocaleString()} points`),{processedData:C,dataReductionInfo:h}},[I,l,e,m,N.x,N.y,_,u,s,o,y]);return k?m?jsx("div",{children:"Loading..."}):I.length?T?jsx(k,{data:dt,displayConfig:V,stacked:p,dataConfig:T,title:n,subtitle:Mt||void 0,disableAnimation:dt.length>100,onZoomChange:ct}):jsx("div",{children:"Invalid chart configuration"}):jsx("div",{children:"Unable to display chart - no data available"}):(console.error("No chart component found"),null)},(t,e)=>Rn(t,e));function ot({content:t,className:e}){return t?.length?jsx("div",{className:e||"prose dark:prose-invert max-w-4xl w-full leading-normal",children:jsx("p",{style:{whiteSpace:"pre-wrap"},children:t})}):null}function jn(t){let e=[],n=t;for(;n.length>0;){let a=n.indexOf("{"),r=n.indexOf("["),s=-1,o=true;if(a>=0&&(r<0||a<r)?(s=a,o=true):r>=0&&(s=r,o=false),s<0){n.trim()&&e.push({type:"text",content:n});break}if(s>0){let c=n.slice(0,s);c.trim()&&e.push({type:"text",content:c});}let i=0,l=s,p=o?"{":"[",u=o?"}":"]";for(let c=s;c<n.length;c++)if(n[c]===p&&i++,n[c]===u&&i--,i===0){l=c+1;break}let d=n.slice(s,l);try{let c=JSON.parse(d);e.push({type:"json",content:c});}catch{e.push({type:"text",content:d});}n=n.slice(l);}return e}function Ln(t){switch(t){case "muted":return "text-gray-500";case "error":return "text-red-500";case "warning":return "text-yellow-600";case "success":return "text-green-600";default:return ""}}function Q({content:t,className:e}){let n=typeof t=="string"?t:JSON.stringify(t,null,2),a=useMemo(()=>jn(n),[n]);return n?.length?jsx("div",{className:e||"prose dark:prose-invert leading-normal",children:a.map((r,s)=>{if(r.type==="json"){let o=r.content;return o.message&&typeof o.message=="string"?jsx("p",{className:Ln(o.style),children:o.message},s):jsx("pre",{className:"bg-gray-100 dark:bg-gray-800 p-3 rounded overflow-x-auto text-sm",children:JSON.stringify(o,null,2)},s)}return jsx("p",{children:r.content},s)})}):null}function bt({config:t,data:e,className:n}){let a=useMemo(()=>!t?.chart_type||!t?.chart_title||!t?.series?.length||!t?.y_axes?.length?null:{chartType:t.chart_type,title:t.chart_title,xAxis:{label:t.x_axis.axis_label,key:t.x_axis.key,maxValue:t.x_axis.max_value,minValue:t.x_axis.min_value,type:t.x_axis.value_type,format:t.x_axis.format},yAxes:t.y_axes.map(i=>({label:i.axis_label,key:i.key,maxValue:i.max_value,minValue:i.min_value,type:i.value_type,format:i.format})),series:t.series.map(i=>({key:i.key,name:i.series_name,color:i.color,axisIndex:i.axis_index,filters:i.filters})),dataReduction:t.data_reduction,stacked:t.stacked,sort:t.sort},[t]);if(!a)return jsx("div",{className:"text-red-500",children:"Invalid chart configuration"});if(!e||e.length===0)return jsx("div",{className:"text-gray-500",children:"No data available for chart"});let r=null;switch(a.chartType){case "bar":case "histogram":r=Y;break;case "line":r=et;break;case "pie":r=nt;break;case "scatter":r=rt;break;case "heatmap":r=at;break}if(!r)return jsxs("div",{className:"text-red-500",children:["Unsupported chart type: ",a.chartType]});let s={[a.xAxis.key]:{label:a.xAxis.label,format:a.xAxis.format,type:a.xAxis.type},...a.series.reduce((i,l)=>(i[l.key]={label:l.name,color:l.color},i),{})},o={chartType:a.chartType,xAxis:a.xAxis,yAxes:a.yAxes,series:a.series};return jsx("div",{className:n||"w-full max-w-3xl",children:jsx(r,{title:a.title,data:e,displayConfig:s,dataConfig:o,stacked:a.stacked,disableAnimation:e.length>100})})}function _t({title:t,columns:e,data:n,className:a,maxRows:r=100}){let s=useMemo(()=>!n||n.length===0?[]:r?n.slice(0,r):n,[n,r]);return !e||e.length===0?jsx("div",{className:"text-gray-500",children:"No columns defined"}):!n||n.length===0?jsx("div",{className:"text-gray-500",children:"No data available"}):jsxs("div",{className:a||"w-full max-w-4xl",children:[t&&jsx("h3",{className:"text-lg font-medium mb-2",children:t}),jsx("div",{className:"overflow-x-auto border rounded-md",children:jsxs("table",{className:"w-full text-sm",children:[jsx("thead",{children:jsx("tr",{className:"border-b bg-gray-50 dark:bg-gray-800",children:e.map(o=>jsx("th",{className:"px-4 py-2 text-left font-medium text-gray-700 dark:text-gray-300",children:o.column_name},o.key))})}),jsx("tbody",{children:s.map((o,i)=>jsx("tr",{className:"border-b last:border-b-0 hover:bg-gray-50 dark:hover:bg-gray-800/50",children:e.map(l=>jsx("td",{className:"px-4 py-2 text-gray-900 dark:text-gray-100",children:gt(o[l.key],l.format,l.value_type)},l.key))},i))})]})}),n.length>r&&jsxs("p",{className:"text-sm text-gray-500 mt-2",children:["Showing ",r," of ",n.length," rows"]})]})}function Ce({item:t,className:e,components:n}){let a=typeof t.ui_content_type=="object"&&t.ui_content_type?.Valid?t.ui_content_type.String:typeof t.ui_content_type=="string"?t.ui_content_type:t.content_type,r=typeof t.content=="string"?t.content:JSON.stringify(t.content);switch(a){case "text":case "thinking":case "redacted_thinking":{let s=n?.text||ot;return jsx(s,{content:r,className:e})}case "json":case "codegen_json":{let s=n?.json||Q;return jsx(s,{content:t.content,className:e})}case "chart":case "ui_generation":{if(t.chartConfig&&t.chartData){let s=n?.chart||bt;return jsx(s,{config:t.chartConfig,data:t.chartData,className:e})}try{let s=typeof t.content=="string"?JSON.parse(t.content):t.content;if(s.children)return qn(s.children,e,n);let o=n?.json||Q;return jsx(o,{content:t.content,className:e})}catch{let s=n?.json||Q;return jsx(s,{content:t.content,className:e})}}case "table":{if(t.tableColumns&&t.tableData){let o=n?.table||_t;return jsx(o,{columns:t.tableColumns,data:t.tableData,className:e})}let s=n?.json||Q;return jsx(s,{content:t.content,className:e})}case "log":case "codeexec_output":return jsx("pre",{className:e||"bg-gray-100 dark:bg-gray-800 p-3 rounded text-sm overflow-x-auto",children:r});case "bot_invocation":case "bot_invocation_result":case "tool_invocation":case "tool_result":case "security_check_json":return null;default:{let s=n?.text||ot;return jsx(s,{content:r,className:e})}}}function qn(t,e,n){return !t||!Array.isArray(t)?null:t.map((a,r)=>{if(!a?._type)return null;switch(a._type){case "Chart":{let s=n?.chart||bt,o=a.content;return jsx("div",{className:"my-4",children:jsx(s,{config:{chart_type:o.chart_type,chart_title:o.chart_title,x_axis:o.x_axis,y_axes:o.y_axes,series:o.series,data_reduction:o.data_reduction,stacked:o.stacked,sort:o.sort},data:[],className:e})},`chart-${r}`)}case "Table":{let s=n?.table||_t,o=a.content;return jsx("div",{className:"my-4",children:jsx(s,{title:o.table_title,columns:o.columns,data:[],className:e})},`table-${r}`)}case "TextMarkdown":{let s=n?.text||ot;return jsx("div",{className:"my-2",children:jsx(s,{content:a.content?.text||"",className:e})},`text-${r}`)}case "Suggestions":{let s=a.content?.suggestions||[];return s.length?jsx("div",{className:"flex flex-col gap-2 my-4",children:s.map((o,i)=>jsx("button",{className:"text-left px-3 py-2 bg-gray-100 dark:bg-gray-800 rounded hover:bg-gray-200 dark:hover:bg-gray-700 text-sm",children:o},i))},`suggestions-${r}`):null}default:return null}})}function xe({text:t,className:e}){return t?.length?jsx("div",{className:A("prose dark:prose-invert leading-tight",e),children:jsx(Zn,{remarkPlugins:[zn],children:t})}):null}function ke(t){let e={success:true,messages:[],events:t,steps:[]};for(let n of t)switch(n.type){case "invocation_started":if(n.payload&&typeof n.payload=="object"){let r=n.payload;e.invocationId=r.invocation_id,e.botId=r.bot_id;}break;case "message":case "message_content":if(n.payload&&typeof n.payload=="object"){let r=n.payload;r.role&&r.content&&e.messages.push({role:r.role,content:r.content});}break;case "step_started":if(n.payload&&typeof n.payload=="object"){let r=n.payload;e.steps.push({key:r.step_key||"",action:r.action||"",status:"running"});}break;case "step_completed":if(n.payload&&typeof n.payload=="object"){let s=n.payload.step_key,o=e.steps.find(i=>i.key===s);o&&(o.status="completed");}break;case "step_error":if(n.payload&&typeof n.payload=="object"){let s=n.payload.step_key,o=e.steps.find(i=>i.key===s);o&&(o.status="failed");}break;case "result":n.payload&&typeof n.payload=="object"&&(e.result=n.payload);break;case "error":if(e.success=false,n.payload&&typeof n.payload=="object"){let r=n.payload;e.error=r.message||r.error||"Unknown error";}else typeof n.payload=="string"&&(e.error=n.payload);break;}return e}function we(t={}){let e=Z(),[n,a]=useState(null),[r,s]=useState(false),[o,i]=useState(null),l=useRef(null),p=useCallback(()=>{l.current&&(l.current.abort(),l.current=null);},[]),u=useCallback(async(d,c)=>{if(!e.client)throw new Error("ErdoClient not configured in provider. Pass a client to ErdoProvider config to use useInvocation.");p(),l.current=new AbortController,s(true),i(null),a(null);try{let m=[];for await(let g of e.client.invokeStream(d,c)){if(l.current?.signal.aborted)break;m.push(g),t.onEvent?.(g);let y=ke(m);a(y);}let f=ke(m);return a(f),t.onFinish?.(f),f}catch(m){let f=m instanceof Error?m:new Error(String(m));throw i(f),t.onError?.(f),f}finally{s(false),l.current=null;}},[e.client,t,p]);return {result:n,isStreaming:r,error:o,invoke:u,cancel:p}}var it=Symbol("parsing"),K=class{result;stack;key;state;stringBuffer;numberBuffer;quoteBuffer;escapeNext;unicode;isInTripleQuotes;constructor(){this.result=void 0,this.stack=[],this.key=void 0,this.state="START",this.stringBuffer="",this.numberBuffer="",this.quoteBuffer="",this.escapeNext=false,this.unicode="",this.isInTripleQuotes=false;}reset(){this.result=void 0,this.stack=[],this.key=void 0,this.state="START",this.stringBuffer="",this.numberBuffer="",this.quoteBuffer="",this.escapeNext=false,this.unicode="",this.isInTripleQuotes=false;}parse(e){return this.reset(),this.add(e)}add(e){for(let n=0;n<e.length;n++){let a=e[n];this.processChar(a);}return this.result}processChar(e){switch(this.state){case "START":this.handleStartState(e);break;case "IN_OBJECT":this.handleObjectState(e);break;case "IN_ARRAY":this.handleArrayState(e);break;case "IN_OBJECT_KEY":this.handleObjectKeyState(e);break;case "AFTER_KEY":this.handleAfterKeyState(e);break;case "IN_OBJECT_VALUE":this.handleObjectValueState(e);break;case "IN_STRING":this.handleStringState(e);break;case "IN_NUMBER":this.handleNumberState(e);break;case "IN_TRUE":this.handleLiteralState(e,"true");break;case "IN_FALSE":this.handleLiteralState(e,"false");break;case "IN_NULL":this.handleLiteralState(e,"null");break;case "IN_UNICODE":this.handleUnicodeState(e);break}}handleStartState(e){if(e==="{")this.startObject();else if(e==="[")this.startArray();else if(!this.isWhitespace(e))throw this.error("must start with { or [","start")}error(e,n){return new Error(`Invalid JSON in ${n}: ${e}`)}handleObjectState(e){if(e==="}")this.endObject();else if(e==='"')this.state="IN_OBJECT_KEY",this.stringBuffer="",this.key=void 0,this.quoteBuffer="";else if(e===",")this.key=void 0;else if(!this.isWhitespace(e))throw this.error(`Invalid character in object: ${e}`,"object")}handleArrayState(e){e==="]"?this.endArray():e===","||this.isWhitespace(e)||this.startValue(e);}handleObjectKeyState(e){e==='"'?(this.state="AFTER_KEY",this.key=this.stringBuffer,this.stringBuffer=""):(this.stringBuffer+=e,this.updateValueInParent(this.stringBuffer));}handleAfterKeyState(e){e===":"?this.state="IN_OBJECT_VALUE":this.isWhitespace(e)||this.isWhitespace(e)||(this.key=this.key+e);}handleObjectValueState(e){this.isWhitespace(e)||this.startValue(e);}handleStringState(e){if(this.escapeNext)this.handleEscapeChar(e);else if(e==="\\")this.escapeNext=true;else if(e==='"'){if(this.quoteBuffer+='"',this.stringBuffer===""&&this.quoteBuffer==='""')this.quoteBuffer="",this.isInTripleQuotes=true;else if(this.stringBuffer&&this.quoteBuffer==='"""'){this.quoteBuffer="",this.isInTripleQuotes=false,this.stringBuffer=this.stringBuffer.replace(/^\n+/,"").replace(/\n+$/,"").trim(),this.endString();return}}else {if(this.quoteBuffer){if(this.quoteBuffer==='"'&&!this.isInTripleQuotes){this.quoteBuffer="",this.endString(),this.processChar(e);return}else if(this.quoteBuffer==='"""'&&this.isInTripleQuotes){this.quoteBuffer="",this.isInTripleQuotes=false,this.endString(),this.processChar(e);return}this.stringBuffer+=this.quoteBuffer,this.quoteBuffer="";}this.stringBuffer+=e,this.updateValueInParent(this.stringBuffer);}}handleNumberState(e){e.match(/[0-9.eE+-]/)?(this.numberBuffer+=e,this.updateValueInParent(parseFloat(this.numberBuffer))):(this.endNumber(),this.processChar(e));}handleLiteralState(e,n){let a=n[this.stringBuffer.length];if(e===a)this.stringBuffer+=e,this.stringBuffer===n?this.endLiteral(n):this.updateValueInParent(this.stringBuffer);else throw this.error(`Invalid literal: expected ${n}`,"literal")}handleUnicodeState(e){if(this.unicode+=e,this.unicode.length===4){let n=parseInt(this.unicode,16);this.stringBuffer+=String.fromCharCode(n),this.unicode="",this.state="IN_STRING";}}handleEscapeChar(e){switch(e){case '"':case "\\":case "/":this.stringBuffer+=e;break;case "b":this.stringBuffer+="\b";break;case "f":this.stringBuffer+="\f";break;case "n":this.stringBuffer+=`
|
|
8
|
+
`;break;case "r":this.stringBuffer+="\r";break;case "t":this.stringBuffer+=" ";break;case "u":this.unicode="",this.state="IN_UNICODE";break;case "`":this.stringBuffer+="`";break;default:throw this.error("Invalid escape character","string")}this.escapeNext=false;}startObject(){let e={[it]:true};this.addValueToParent(e),this.stack.push({value:e,key:this.key}),this.key=void 0,this.state="IN_OBJECT";}endObject(){let{value:e,key:n,index:a}=this.stack.pop();if(delete e[it],this.stack.length===0)this.state="END",this.result={...e};else {let{value:r}=this.stack[this.stack.length-1];if(Array.isArray(r))a!==void 0?r[a]={...e}:r[r.length-1]={...e};else if(n!==void 0)r[n]={...e};else throw this.error("Key is undefined","object");this.state=this.getParentState();}}startArray(){let e=[];e[it]=true,this.addValueToParent(e),this.stack.push({value:e,key:this.key,index:0}),this.key=void 0,this.state="IN_ARRAY";}endArray(){let{value:e,key:n,index:a}=this.stack.pop();if(delete e[it],this.stack.length===0)if(this.state="END",Array.isArray(e))this.result=[...e];else throw this.error("Expected array at root level","array");else {let{value:r}=this.stack[this.stack.length-1];Array.isArray(r)?a!==void 0?r[a]=Array.isArray(e)?[...e]:e:r[r.length-1]=Array.isArray(e)?[...e]:e:n!==void 0&&(r[n]=Array.isArray(e)?[...e]:e),this.state=this.getParentState();}}startValue(e){if(e==='"')this.state="IN_STRING",this.stringBuffer="",this.quoteBuffer="",this.addValueToParent("");else if(e.match(/[0-9-]/))this.state="IN_NUMBER",this.numberBuffer=e,this.addValueToParent(parseFloat(e));else if(e==="t")this.state="IN_TRUE",this.stringBuffer="t",this.addValueToParent("t");else if(e==="f")this.state="IN_FALSE",this.stringBuffer="f",this.addValueToParent("f");else if(e==="n")this.state="IN_NULL",this.stringBuffer="n",this.addValueToParent("n");else if(e==="{")this.startObject();else if(e==="[")this.startArray();else throw this.error(`Invalid value start: ${e}`,"value")}endString(){let e=this.stringBuffer;this.stringBuffer="",this.updateValueInParent(e),this.state=this.getParentState();}endNumber(){let e=parseFloat(this.numberBuffer);this.updateValueInParent(e),this.numberBuffer="",this.state=this.getParentState();}endLiteral(e){let n;switch(e){case "true":n=true;break;case "false":n=false;break;case "null":n=null;break;default:throw this.error("Invalid literal","literal")}this.updateValueInParent(n),this.stringBuffer="",this.state=this.getParentState();}addValueToParent(e){if(this.stack.length===0)this.result=e;else {let n=this.stack[this.stack.length-1],{value:a}=n;if(Array.isArray(a))a.push(e),n.index!==void 0&&n.index++;else if(this.state==="IN_OBJECT_KEY")this.key=e,a[this.key]="";else {if(this.key===void 0)throw this.error("Key is undefined","object");a[this.key]=e;}}}updateValueInParent(e){if(this.stack.length===0)this.result=e;else {let n=this.stack[this.stack.length-1],{value:a}=n;if(Array.isArray(a))n.index!==void 0?a[n.index-1]=e:a[a.length-1]=e;else if(this.key!==void 0)a[this.key]=e;else if(this.state!=="IN_OBJECT_KEY")throw this.error("Key is undefined","object")}}isWhitespace(e){return e===" "||e===" "||e===`
|
|
9
|
+
`||e==="\r"}getParentState(){return this.stack.length===0?"END":Array.isArray(this.stack[this.stack.length-1].value)?"IN_ARRAY":"IN_OBJECT"}};function Qn(t){let e=t.trim();try{return JSON.parse(e)}catch{try{return new K().parse(e)}catch(a){return console.log("content",e),console.error("Error parsing JSON",a),null}}}function Dt(t){return t===" "||t===`
|
|
10
|
+
`||t===" "||t==="\r"}function Gn(t,e){if(e>=t.length-1)return "";for(let n=e+1;n<t.length;n++)if(!Dt(t[n]))return t[n];return ""}function Bt(t){if(typeof t!="string")return t;let e=[],n=/```json\s*\n([\s\S]*?)(?:(?:\n)?```|$)/g,a=n.test(t);if(n.lastIndex=0,a){let r=0,s;for(;(s=n.exec(t))!==null;){let i=t.substring(r,s.index).trim();i&&e.push({content:i,type:"text"});let l=s[1];try{let p=JSON.parse(l);e.push({content:p,type:"json"});}catch{try{let d=new K().parse(l);d?e.push({content:d,type:"json"}):e.push({content:s[0],type:"text"});}catch{e.push({content:s[0],type:"text"});}}r=s.index+s[0].length;}let o=t.substring(r).trim();o&&e.push({content:o,type:"text"});}else {let r="",s=null,o=false,i=0;for(let l=0;l<t.length;l++){let p=t[l],u=Gn(t,l);if(!o&&(p==="{"&&u==='"'||p==="["&&u==="{")&&(r.trim()&&e.push({content:r.trim(),type:"text"}),o=true,s=new K,r=""),o){let d;try{d=s.add(p);}catch(c){if(console.log("currentChunk",r),console.log("currentResult",s?.result),console.warn("Error parsing JSON",c),i>3)throw c;i++;continue}r+=p,s.state==="END"&&(e.push({content:d,type:"json"}),o=false,s=null,r="");}else r+=p;}r.trim()&&e.push({content:r.trim(),type:"text"});}return e}function Xn(t){return t&&typeof t=="object"&&!t[it]}function tr(t){return t&&typeof t=="object"&&t[it]===true}function Ct(t,e){return t==="json"||e==="json"}var Ie=(l=>(l.Pending="pending",l.Running="running",l.Success="success",l.Error="error",l.RequiresInfo="requires info",l.GoToStep="go to step",l.Skipped="skipped",l.Break="break",l))(Ie||{}),Ee=(s=>(s.Initializing="initializing",s.Running="running",s.ProcessingDatasets="processing datasets",s.Completed="completed",s.Failed="failed",s))(Ee||{});function O(t){if(!t)throw new Error("Entity is null");if(!("_type"in t))throw new Error(`Entity ${JSON.stringify(t)} is missing _type`);return t._type}function er(t){return t.contents.length===0?null:t.contents[t.contents.length-1]||null}function nr(t){return t.contents.length===0?null:t.contents[0]||null}function Yt(t,e){let n=O(t);switch(n){case "message":return t;case "step":let a=t;if(e){let o=a.eventsByID[e]?.Message;return o||Te({},"",e)}let s=Object.keys(a.eventsByID).reverse();for(let o of s){let i=a.eventsByID[o];if(i&&i.Message)return i.Message}throw new Error("Unable to find message for step");default:throw new Error(`Unable to have messages on entity type ${n}`)}}function rr(t,e){switch(O(t)){case "message_content":return t;case "output_content":return t;case "message":return lt(t,e);case "output":return ut(t,e);case "step":let a=Ot(t,e);return a?ut(a,e):null;default:return null}}function lt(t,e){let n=O(t);switch(n){case "message_content":return t;case "message":let a=Yt(t);if(!a)throw new Error("Unable to find message to add content to");return e?a.contentsByID[e]:er(a);default:throw new Error(`Unable to have message content on entity type ${n}`)}}function ut(t,e){let n=O(t);switch(n){case "output_content":return t;case "output":let a=t;return e?a.contentsByID[e]||null:a.contents.length<=0?null:a.contents[a.contents.length-1]||null;case "step":let s=Ot(t,e);return s?ut(s):null;case "invocation":if(!e)return null;let o=t.eventsByID[e];return !o||!o.Output?null:ut(o.Output);default:throw new Error(`Unable to have output content on entity type ${n}`)}}function Qt(t,e){let n=O(t),a=null;switch(n){case "invocation":return t;case "message_content":if(a=t.botInvocation||null,!a)throw new Error("Unable to find bot invocation for message content");if(e&&a.bot_invocation.id!==e)throw new Error("Unable to find bot invocation for message content - mismatched ID");return a;case "message":if(a=nr(t)?.botInvocation||null,!a)throw new Error("Unable to find bot invocation for message");if(e&&a.bot_invocation.id!==e)throw new Error("Unable to find bot invocation for message - mismatched ID");return a;case "output_content":return t.botInvocation||null;default:throw new Error(`Unable to have bot invocation on entity type ${n}`)}}function Ot(t,e){let n=O(t);switch(n){case "output":return t;case "step":let a=t;if(e){let i=a.eventsByID[e]?.Output;if(!i)throw new Error("Unable to find output with id "+e);return i}let s=Object.keys(a.eventsByID).reverse();for(let i of s){let l=a.eventsByID[i];if(l&&l.Output)return l.Output}throw new Error("Unable to find output for step");case "invocation":if(!e)throw new Error("Unable to find output for invocation without ID");return t.eventsByID[e]?.Output||null;default:throw new Error(`Unable to have step outputs on entity type ${n}`)}}function Be(t,e){let n=O(t);switch(n){case "result_handler":return t;case "step":if(!e)throw new Error("Unable to have result handlers on step without ID");let a=t.eventsByID[e];if(!a||!a.type||a.type!=="result_handler"||!a.ResultHandler)throw new Error(`Unable to find result handler with id ${e} on step ${t.id}`);return a.ResultHandler;default:throw new Error(`Unable to have result handlers on entity type ${n}`)}}function Oe(t,e){let n=O(t),a=null;switch(n){case "step":if(t.id===e||!e)return t;throw new Error("Unable to find step on step with id "+e);case "invocation":if(!e)throw new Error("Unable to have steps on bot invocation without ID");a=t;let r=a.eventsByID[e];if(!r)throw new Error("Unable to find step on invocation with id "+e);if(!r.Step)throw new Error("Unable to find step on invocation with id "+e);return r.Step;case "result_handler":if(!e)throw new Error("Unable to have steps on result handler without ID");let o=t.eventsByID[e];if(!o)throw new Error("Unable to find step on result handler with id "+e);if(!o.Step)throw new Error("Unable to find step on result handler with id "+e);return o.Step;default:throw new Error(`Unable to have steps on entity type ${n}`)}}var Zt=class extends Error{};function ar(t,e,n){let a=null,r=e[0],s=e[1];n[r]=s;try{switch(r){case "message":a=Yt(t,s);break;case "content":a=lt(t,s);break;case "step":a=Oe(t,s);break;case "output":a=Ot(t,s);break;case "output_content":a=ut(t,s);break;case "invocation":a=Qt(t,s);break;case "result_handler":a=Be(t,s);break}}catch(o){throw console.error("error finding next entity"),console.log("path",e),console.log("currentEntity",t),o}if(!a)throw console.log("path",e),console.log("currentEntity",t),console.log("nextEntity",a),new Zt(`Unable to find next entity for path ${e.join("/")}`);return a}function Te(t,e,n,a){let r=t.payload;return {_type:"message",message:{id:n,thread_id:e,author_id:r.author_id||"app",author_entity_type:r.author_entity_type||"app",created_at:new Date().toISOString(),updated_at:new Date().toISOString(),role:r.role||"assistant",avatar:"/teams/erdo.svg"},state:"in_progress",contents:[],contentsByID:{},contentIDToIdx:{}}}function sr(t,e){return {_type:"message_content",id:t.metadata.message_content_id,message_id:e.message,content_type:t.metadata.content_type,created_by_invocation_id:t.metadata.invocation_id,invocation_id:t.metadata.invocation_id,state:"in_progress",user_visibility:t.metadata.user_visibility??"visible",bot_visibility:t.metadata.bot_visibility??"visible",content:"",created_at:new Date().toISOString(),updated_at:new Date().toISOString(),content_params:{RawMessage:null,Valid:false},history_content_type:t.metadata?.history_content_type?{String:t.metadata.history_content_type,Valid:true}:{String:"",Valid:false},ui_content_type:t.metadata?.ui_content_type?{String:t.metadata.ui_content_type,Valid:true}:{String:"",Valid:false}}}function or(t,e){let n=t.metadata?.ui_content_type,a=typeof t.payload=="string"?t.payload:t.payload.content||t.payload,r=null;return Ct(t.metadata.content_type,n)&&(r=Bt(a)),{_type:"message_content",id:t.metadata.message_content_id,message_id:e.message,content:a,content_type:t.metadata.content_type,created_by_invocation_id:t.metadata.invocation_id,invocation_id:t.metadata.invocation_id,state:"completed",user_visibility:t.metadata.visibility||"visible",bot_visibility:"visible",created_at:new Date().toISOString(),updated_at:new Date().toISOString(),content_params:{RawMessage:null,Valid:false},history_content_type:t.metadata?.history_content_type?{String:t.metadata.history_content_type,Valid:true}:{String:"",Valid:false},ui_content_type:n?{String:n,Valid:true}:{String:"",Valid:false},parsedJson:r}}function ir(t,e,n){let a=t.payload;return {_type:"step",id:e,invocation_id:n.invocation||"",step_id:a.step_id||"",created_at:new Date().toISOString(),updated_at:new Date().toISOString(),current_status_id:"",path:{String:"",Valid:false},action_type:{String:a.action_type,Valid:true},key:{String:a.key,Valid:true},bot_id:a.bot_id,result_handler_id:"",step_order:{Int32:a.step_order,Valid:true},output_content_type:{String:a.content_type,Valid:true},execution_mode:{String:a.execution_mode,Valid:true},output_behaviour:{String:a.output_behaviour,Valid:true},user_output_visibility:{String:t.metadata.visibility||"visible",Valid:true},output_channels:a.output_channels||[],running_message:{String:"",Valid:false},finished_message:{String:"",Valid:false},depends_on:[],eventsByID:{},currentStatus:null}}function lr(t,e,n){let a=t.payload;return {_type:"result_handler",id:e,invocation_id:t.metadata.invocation_id||"",result_handler_id:a.result_handler_id||e,step_invocation_id:a.step_invocation_id||"",type:a.type||"",if_conditions:a.if_conditions||{},created_at:new Date().toISOString(),updated_at:new Date().toISOString(),output_content_type:a.output_content_type||"",result_handler_order:a.result_handler_order||0,eventsByID:{}}}function ur(t,e,n){return {_type:"output",id:e,step_id:n.step_id,output:{id:e,invocation_id:t.metadata?.invocation_id,path:t.metadata.path,created_at:new Date().toISOString(),updated_at:new Date().toISOString()},state:"in_progress",contents:[],contentsByID:{},contentIDToIdx:{}}}function Re(t,e,n,a=null){return {_type:"output_content",id:e,output_id:n.output,content:"",content_type:t.metadata.content_type,state:"in_progress",invocation_id:t.metadata.invocation_id,user_visibility:a??t.metadata.user_visibility??"visible",bot_visibility:t.metadata.bot_visibility??"visible",created_at:new Date().toISOString(),updated_at:new Date().toISOString(),content_params:{RawMessage:null,Valid:false},history_content_type:t.metadata.history_content_type?{String:t.metadata.history_content_type,Valid:true}:{String:"",Valid:false},ui_content_type:t.metadata.ui_content_type?{String:t.metadata.ui_content_type,Valid:true}:{String:"",Valid:false},output:null}}function Ne(t,e,n,a=null){let r=null,s=t.metadata?.ui_content_type;return Ct(t.metadata.content_type,s)&&(r=Bt(t.payload)),{_type:"output_content",id:e,output_id:n.output,content:t.payload,content_type:t.metadata.content_type,state:"completed",invocation_id:t.metadata.invocation_id,parsedJson:r,user_visibility:a||t.metadata.visibility||"visible",bot_visibility:"visible",created_at:new Date().toISOString(),updated_at:new Date().toISOString(),content_params:{RawMessage:null,Valid:false},history_content_type:t.metadata?.history_content_type?{String:t.metadata.history_content_type,Valid:true}:{String:"",Valid:false},ui_content_type:s?{String:s,Valid:true}:{String:"",Valid:false},output:null}}function cr(t,e,n){return {_type:"invocation",bot_invocation:{id:t.payload.invocation_id,bot_id:t.payload.bot_id,bot_name:t.payload.bot_name,created_by_user_id:t.payload.created_by_user_id,current_state_id:"",parent_invocation_id:"",branch_init_state_id:"",current_status_id:"",organization_id:"",created_at:new Date().toISOString(),updated_at:new Date().toISOString()},eventsByID:{},currentStatus:null,current_status:null,step_invocations:[],step_invocation_states:[],resources:[],outputs:[],statuses:[]}}function qt(t,e){let n=t.payload;return {_type:"status",id:new Date().toISOString(),status:n.status,message:{String:n.message,Valid:true},Details:n}}function Me(t){return {id:t.id,type:"step",created_at:t.created_at,_type:"invocation_event",Output:null,Message:null,Status:null,ResultHandler:null,Step:t}}function Gt(t){return {id:t.output.id,type:"output",created_at:t.output.created_at,_type:"invocation_event",Output:t,Message:null,Status:null,ResultHandler:null,Step:null}}function Xt(t){return {id:t.id,type:"status",created_at:t.created_at,_type:"invocation_event",Status:t,Output:null,Message:null,ResultHandler:null,Step:null}}function dr(t){return {id:t.message.id,type:"message",created_at:t.message.created_at,_type:"invocation_event",Output:null,Message:t,Status:null,ResultHandler:null,Step:null}}function pr(t){return {id:t.id,type:"result_handler",created_at:t.created_at,_type:"invocation_event",Output:null,Message:null,Status:null,ResultHandler:t,Step:null}}function te(t,e){if(t.content||(t.content=""),t.user_visibility!=="visible"||!Ct(t.content_type,t.ui_content_type.String))return t.content+=e,{...t};if(t.parsedJson||(t.parsedJson=[]),typeof e=="object")return t.content+=JSON.stringify(e),t.parsedJson=[...t.parsedJson,e],{...t};t._jsonParser||(t._isInJson=false),t._charBuffer||(t._charBuffer="");for(let n of e){if(t.content+=n,!t._isInJson&&n==="{"){t._charBuffer="{";continue}if(t._charBuffer&&Dt(n)){t._charBuffer+=n;continue}if(!t._isInJson&&t._charBuffer?.match(/^\s*{\s*$/)&&n==='"'){t._isInJson=true,t._jsonParser=new K;let r={content:t._jsonParser.add("{"),type:"json"};t._currentContent?.content?t._currentContent.content.match(/^\s*{$/)?(t._currentContent=r,t.parsedJson[t.parsedJson.length-1]=r):(t._currentContent.content=t._currentContent.content.replace(/{$/,""),t._currentContent=r,t.parsedJson=[...t.parsedJson,r]):(t._currentContent=r,t.parsedJson=[...t.parsedJson,r]);}if(t._isInJson)try{let a=t._jsonParser.add(n);t._currentContent.content=a,t._jsonParser.state==="END"&&(t._isInJson=!1,t._currentContent=void 0);}catch(a){console.log("content",e),console.log("currentContent",t.content),console.error("Error incrementally parsing JSON",a);}else t._currentContent||(t._currentContent={content:t._charBuffer||"",type:"text"},t.parsedJson=[...t.parsedJson,t._currentContent]),t._currentContent.content+=t._charBuffer+n;t._charBuffer="";}return {...t}}function fr(t,e){return te(t,e)}function De(t,e){return te(t,e)}function zt(t,e){let n=O(t);switch(n){case "message":return q(t,e);case "message_content":return ee(t,e);case "step":return mr(t,e);case "output":return hr(t,e);case "output_content":return yr(t,e);case "invocation":return Tt(t,e);case "result_handler":return br(t,e);default:throw new Error(`Unable to add update entity for entity type ${n}`)}}function gr(t,e){for(let n of e)t=zt(t,n);return t}function q(t,e){let n=Yt(t);if(!n)throw new Error("Unable to find message to add content to");let a=O(e),r=null;switch(a){case "message_content":return r=e,n.contentsByID[r.id]?n.contents[n.contentIDToIdx[r.id]]=r:(n.contentIDToIdx={...n.contentIDToIdx,[r.id]:n.contents.length},n.contents=[...n.contents,r]),n.contentsByID={...n.contentsByID,[r.id]:r},{...n};case "invocation":let s=e;if(n.contents.length===0)throw new Error("Unable to find message content to add invocation to");return r=ee(n.contents[0],s),q(n,r);case "step":if(n.contents.length===0)throw new Error("Unable to find message content to add content to");if(r=n.contents[0],!r)throw new Error("Unable to find message content to add content to");let o=Qt(r);if(!o)throw new Error("Unable to find bot invocation to add content to");return r.botInvocation=Tt(o,e),q(n,r);default:throw new Error(`Unable to add update message child for child type ${a}`)}}function ee(t,e){let n=lt(t);if(!n)throw new Error("Unable to find message content to add content to");let a=O(e);switch(a){case "invocation":return n.botInvocation=e,{...n};case "step":let r=n.botInvocation;if(!r)throw new Error("Unable to find bot invocation to add content to");return n.botInvocation=Tt(r,e),{...n};default:throw new Error(`Unable to add update message content child for child type ${a}`)}}function mr(t,e){let n=Oe(t);if(!n)throw new Error("Unable to find bot invocation to add step to");let a=O(e),r=null;switch(a){case "output":let s=e;return r=Gt(s),n.eventsByID={...n.eventsByID,[s.output.id]:r},{...n};case "message":let o=e;return r=dr(o),n.eventsByID={...n.eventsByID,[o.message.id]:r},{...n};case "status":let i=e;return r=Xt(i),n.eventsByID={...n.eventsByID,[i.id]:r},{...n};case "result_handler":let l=e;return r=pr(l),n.eventsByID={...n.eventsByID,[l.id]:r},{...n};default:throw new Error(`Unable to add update step for entity type ${a}`)}}function hr(t,e){let n=Ot(t);if(!n)throw new Error("Unable to find step output to add content to");let a=O(e);switch(a){case "output_content":let r=e;return n.contentsByID[r.id]?n.contents[n.contentIDToIdx[r.id]]=r:(n.contentIDToIdx={...n.contentIDToIdx,[r.id]:n.contents.length},n.contents=[...n.contents,r]),n.contentsByID={...n.contentsByID,[r.id]:r},{...n};default:throw new Error(`Unable to add update output for entity type ${a}`)}}function yr(t,e){let n=ut(t);if(!n)throw new Error("Unable to find step output content to add content to");let a=O(e);switch(a){case "invocation":return n.botInvocation=e,{...n};case "step":let r=n.botInvocation;if(!r)throw new Error("Unable to find bot invocation to add content to");return n.botInvocation=Tt(r,e),{...n};default:throw new Error(`Unable to add update step output content for entity type ${a}`)}}function Tt(t,e){let n=Qt(t);if(!n)throw new Error("Unable to find bot invocation to add content to");let a=O(e),r;switch(a){case "step":let s=e;return r=Me(s),n.eventsByID={...n.eventsByID,[s.id]:r},{...n};case "output":let o=e;return r=Gt(o),n.eventsByID={...n.eventsByID,[o.output.id]:r},{...n};case "status":let i=e;return r=Xt(i),n.eventsByID={...n.eventsByID,[i.id]:r},{...n};default:throw new Error(`Unable to add update invocation for entity type ${a}`)}}function br(t,e){let n=Be(t);if(!n)throw new Error("Unable to find result handler to add content to");let a=O(e),r=null;switch(a){case "step":let s=e;return r=Me(s),n.eventsByID||(n.eventsByID={}),n.eventsByID={...n.eventsByID,[s.id]:r},{...n};case "output":let o=e;return r=Gt(o),n.eventsByID||(n.eventsByID={}),n.eventsByID={...n.eventsByID,[o.output.id]:r},{...n};case "status":let i=e;return r=Xt(i),n.eventsByID||(n.eventsByID={}),n.eventsByID={...n.eventsByID,[i.id]:r},{...n};default:throw new Error(`Unable to add update to result handler for entity type ${a}`)}}function _r(t){return t==="bot started"||t==="bot resumed"||t==="message created"||t==="create message content"||t==="message content result"||t==="step started"||t==="result handler started"||t==="state created"||t==="step output created"||t==="create step output content"||t==="step output content result"||t==="log"}function Pe(t,e,n,a,r,s=null,o=[],i={}){if(!s&&Object.keys(r).length>0){let d,c;if(n.length>=2&&n[0]==="message"?(c=n[1],d=r[c],d||(d=Object.values(r)[0],c=Object.keys(r)[0])):(d=Object.values(r)[Object.values(r).length-1],c=Object.keys(r)[Object.keys(r).length-1]),i.message=c,n.length<=2&&t==="message finished")return null;if(n[0]!=="content"&&Object.keys(d.contentsByID).length>0&&e.metadata.message_content_id){let m=e.metadata.message_content_id,f=d.contentsByID[m];f&&(s=f);}s?o=[d]:s=d;}if(n.length<=2&&_r(t)){let d=n[1],c=[],m,f,g,y,w;switch(t){case "bot started":case "bot resumed":if(!s)throw new Error("Unable to find message to add content to");let I=cr(e);if(s._type==="message_content"){if(f=s,!f.id)throw new Error("Unable to find message content id");if(g=r[f.message_id],!g)throw new Error("Unable to find message to add content to");if(y=lt(g,f.id),!y)throw new Error("Unable to find message content to add content to");let k=ee(y,I);r[f.message_id]={...q(g,k)};}c.push(I);break;case "message created":return r[d]=Te(e,a,d),null;case "create message content":if(!s)throw new Error("Unable to find message to add content to");if(w=sr(e,i),s._type==="output"){m=s,c.push(Re(e,d,i,"hidden"));let k=e.payload.message_id;if(k||(k=o[0].message.id),g=r[k],!g)throw new Error("Unable to find message to add content to")}else if(s._type==="message_content"){if(m=s,g=r[m.message_id],!g)throw new Error("Unable to find message to add content to")}else {if(s._type!=="message")throw new Error(`Incorrect path? Cannot add content to non-message entity: ${s._type}`);if(m=s,g=r[m.message.id],!g)throw new Error("Unable to find message to add content to");c.push(w);}r[g.message.id]={...q(g,w)};break;case "message content result":if(!s)throw new Error("Unable to find message to add content to");let _=null;if(s._type==="output"){c.push(Ne(e,d,i,"hidden"));let k=e.payload.message_id||i.message;if(k?_=o.find(J=>J.message.id===k):_=o[0],g=r[k],!g)throw new Error("Unable to find message to add content to")}else if(s._type==="message_content"){if(_=o[0],g=r[_.message.id],!g)throw new Error("Unable to find message to add content to")}else {if(s._type!=="message")throw new Error(`Incorrect path? Cannot add content to non-message entity: ${s._type}`);if(_=s,g=r[_.message.id],!g)throw new Error("Unable to find message to add content to")}let V=e.metadata.message_content_id;if(!V)throw new Error("Unable to find message content id");let T=lt(_,V);if(T){T.state="completed";let k=typeof e.payload=="string"?e.payload:e.payload.content||e.payload;T.content=k,r[g.message.id]={...q(g,T)},(s._type==="message"||s._type==="message_content")&&c.push(T);}else T=or(e,i),r[g.message.id]={...q(g,T)},(s._type==="message"||s._type==="message_content")&&c.push(T);break;case "step started":c.push(ir(e,d,i));break;case "result handler started":c.push(lr(e,d));break;case "step output created":c.push(ur(e,d,s));break;case "create step output content":c.push(Re(e,d,i));break;case "step output content result":c.push(Ne(e,d,i));break;case "log":return null;default:throw new Error(`Unable to handle create event type ${t}`)}return c.length?!s||s._type==="message_content"&&c.length===1&&c[0]._type==="message_content"?c[0]:gr(s,c):null}if(!s)throw new Error("No first message has been created, so cannot handle amend events");if(n.length<=1){let d=null;try{d=rr(s);}catch{}switch(t){case "message content delta":if(!d)throw new Error("Unable to find message content");let c=null,m=null,f=null;if(s._type==="output_content"){c=De(s,e.payload);let I=e.metadata.message_content_id;if(!I)throw new Error("Unable to find message content id from entity ids");let _=i.message;if(f=o.find(V=>V.message.id===_),!f)throw new Error("Unable to find message to add content to");m=lt(f,I);}else {if(m=d,f=o[o.length-1],!f)throw new Error("Unable to find message to add content to");if(f._type!=="message")throw new Error("Unable to find message to add content to - not a message")}if(!m)throw new Error("Unable to find message content");let g=r[f.message.id];if(!g)throw new Error("Unable to find message to add content to");let y=fr(m,e.payload);return r[g.message.id]={...q(g,y)},s._type==="message_content"&&(c=y),c;case "step output content delta":return De(d,e.payload);case "status":return s._type==="step"&&(s.currentStatus=qt(e)),s._type==="invocation"&&(s.currentStatus=qt(e)),zt(s,qt(e));case "result":return null;case "message finished":return null;case "step output finished":return null;case "step result":return null;case "error":return null;case "dataset created":return null;case "log":return null;default:throw new Error(`Unable to handle event type ${t}`)}}let l=n.slice(2),p=ar(s,n,i),u=Pe(t,e,l,a,r,p,[...o,s],i);return u?zt(s,{...u}):s}export{Y as BarChart,$ as Chart,pt as ChartContainer,bt as ChartContent,Ft as ChartLegend,jt as ChartLegendContent,ie as ChartStyle,Jt as ChartTooltip,$t as ChartTooltipContent,Ce as Content,be as DatasetChart,re as ErdoProvider,z as ErrorBoundary,Ee as ExecutionStatus,at as HeatmapChart,Ie as InvocationStatus,K as JSONStreamParser,Q as JsonContent,et as LineChart,xe as MarkdownContent,nt as PieChart,rt as ScatterChart,_t as TableContent,ot as TextContent,A as cn,gt as formatValue,te as handleIncrementalMixedJsonParsing,Pe as handleSSEEvent,Ct as isJsonLike,Xn as isParsingComplete,tr as isParsingInProgress,Dt as isWhitespaceChar,Qn as parseCompleteJson,Bt as parseMixedJson,le as parseToDate,wt as resolveKeyFromData,me as toSnakeCase,xt as useChartZoom,ge as useDatasetContents,Z as useErdoConfig,ae as useErdoConfigOptional,we as useInvocation,kt as useMultipleDatasetContents};
|