drizzle-cube 0.4.20 → 0.4.21
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/adapters/anthropic-BTkjgFpT.cjs +1 -0
- package/dist/adapters/anthropic-CTu9E801.js +126 -0
- package/dist/adapters/express/index.cjs +6 -6
- package/dist/adapters/express/index.js +119 -116
- package/dist/adapters/fastify/index.cjs +6 -6
- package/dist/adapters/fastify/index.js +113 -110
- package/dist/adapters/google-BAK9pnQf.cjs +2 -0
- package/dist/adapters/google-DficVAsJ.js +146 -0
- package/dist/adapters/{handler-CbDMdSY5.js → handler-9Rdn7zM2.js} +534 -461
- package/dist/adapters/handler-B-tEntiU.cjs +39 -0
- package/dist/adapters/hono/index.cjs +6 -6
- package/dist/adapters/hono/index.js +199 -196
- package/dist/adapters/index-BIMhF5KZ.cjs +23 -0
- package/dist/adapters/index-BgCeQBuN.cjs +2 -0
- package/dist/adapters/index-C45_meK_.js +719 -0
- package/dist/adapters/index-CFEJ62GJ.js +5337 -0
- package/dist/adapters/nextjs/index.cjs +5 -5
- package/dist/adapters/nextjs/index.js +245 -242
- package/dist/adapters/openai-CUSRuKTk.js +131 -0
- package/dist/adapters/openai-mLo2MCat.cjs +1 -0
- package/dist/client/components/AgenticNotebook/AgentChatPanel.d.ts +3 -0
- package/dist/client/components/AgenticNotebook/index.d.ts +6 -0
- package/dist/client/hooks/useAgentChat.d.ts +6 -0
- package/dist/client/index.js +730 -697
- package/dist/client/index.js.map +1 -1
- package/dist/client/styles.css +1 -1
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/anthropic-BTkjgFpT.cjs +1 -0
- package/dist/server/anthropic-CTu9E801.js +126 -0
- package/dist/server/google-BAK9pnQf.cjs +2 -0
- package/dist/server/google-DficVAsJ.js +146 -0
- package/dist/server/index-BIMhF5KZ.cjs +23 -0
- package/dist/server/index-BgCeQBuN.cjs +2 -0
- package/dist/server/index-C45_meK_.js +719 -0
- package/dist/server/index-CFEJ62GJ.js +5337 -0
- package/dist/server/index.cjs +48 -46
- package/dist/server/index.d.ts +37 -10
- package/dist/server/index.js +1974 -1901
- package/dist/server/openai-CUSRuKTk.js +131 -0
- package/dist/server/openai-mLo2MCat.cjs +1 -0
- package/package.json +12 -2
- package/dist/adapters/handler-DtdjM1Vx.cjs +0 -37
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import { h as
|
|
2
|
-
import { handleDiscover as
|
|
3
|
-
function
|
|
4
|
-
if (
|
|
1
|
+
import { h as j, Q as U, j as Z, D as G } from "./mcp-transport-m1X1GtwG.js";
|
|
2
|
+
import { handleDiscover as K, handleLoad as W } from "./utils.js";
|
|
3
|
+
function X(d) {
|
|
4
|
+
if (d.length === 0)
|
|
5
5
|
return "No cubes are currently available.";
|
|
6
|
-
const
|
|
7
|
-
for (const a of
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
for (const
|
|
11
|
-
const
|
|
12
|
-
|
|
6
|
+
const s = ["## Available Cubes", ""];
|
|
7
|
+
for (const a of d) {
|
|
8
|
+
if (s.push(`### ${a.name}`), a.description && s.push(a.description), a.measures && a.measures.length > 0) {
|
|
9
|
+
s.push(""), s.push("**Measures:**");
|
|
10
|
+
for (const o of a.measures) {
|
|
11
|
+
const y = o.description ? ` - ${o.description}` : "";
|
|
12
|
+
s.push(`- \`${a.name}.${o.name}\` (${o.type})${y}`);
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
if (a.dimensions && a.dimensions.length > 0) {
|
|
16
|
-
|
|
17
|
-
for (const
|
|
18
|
-
const
|
|
19
|
-
|
|
16
|
+
s.push(""), s.push("**Dimensions:**");
|
|
17
|
+
for (const o of a.dimensions) {
|
|
18
|
+
const y = o.description ? ` - ${o.description}` : "";
|
|
19
|
+
s.push(`- \`${a.name}.${o.name}\` (${o.type})${y}`);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
if (a.relationships && a.relationships.length > 0) {
|
|
23
|
-
|
|
24
|
-
for (const
|
|
25
|
-
|
|
23
|
+
s.push(""), s.push("**Joins:**");
|
|
24
|
+
for (const o of a.relationships)
|
|
25
|
+
s.push(`- → \`${o.targetCube}\` (${o.relationship})`);
|
|
26
26
|
}
|
|
27
|
-
a.meta?.eventStream && (
|
|
27
|
+
a.meta?.eventStream && (s.push(""), s.push("**Event Stream:** Yes (supports funnel, flow, retention queries)"), a.meta.eventStream.bindingKey && s.push(`- Binding key: \`${a.name}.${a.meta.eventStream.bindingKey}\``), a.meta.eventStream.timeDimension && s.push(`- Time dimension: \`${a.name}.${a.meta.eventStream.timeDimension}\``)), s.push("");
|
|
28
28
|
}
|
|
29
|
-
return
|
|
29
|
+
return s.join(`
|
|
30
30
|
`);
|
|
31
31
|
}
|
|
32
|
-
function I(
|
|
33
|
-
return
|
|
32
|
+
function I(d) {
|
|
33
|
+
return d.messages.map((s) => s.content.text).join(`
|
|
34
34
|
|
|
35
35
|
`);
|
|
36
36
|
}
|
|
37
|
-
function
|
|
37
|
+
function J(d) {
|
|
38
38
|
return [
|
|
39
39
|
"# Drizzle Cube Analytics Agent",
|
|
40
40
|
"",
|
|
@@ -43,20 +43,24 @@ function W(l) {
|
|
|
43
43
|
"",
|
|
44
44
|
"## Your Workflow",
|
|
45
45
|
"",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
46
|
+
"For EACH insight, follow this cycle — do NOT batch all queries first:",
|
|
47
|
+
"",
|
|
48
|
+
"1. **Discover** available cubes using `discover_cubes` (once at the start)",
|
|
49
|
+
"2. **For each analysis point**, repeat this cycle:",
|
|
50
|
+
" a. `execute_query` — get the data",
|
|
51
|
+
" b. `add_markdown` — explain the results and insight",
|
|
52
|
+
" c. `add_portlet` — visualize the results",
|
|
53
|
+
"",
|
|
54
|
+
"Call all three (query → markdown → portlet) in a single turn before moving on to the next analysis.",
|
|
55
|
+
"Do NOT run multiple queries first and add charts later — the user sees results in real-time.",
|
|
51
56
|
"",
|
|
52
57
|
"## Important Guidelines",
|
|
53
58
|
"",
|
|
54
59
|
"- ALWAYS discover cubes first before attempting queries",
|
|
55
|
-
"- Field names MUST be `CubeName.fieldName` (e.g. `PullRequests.count`, `Teams.name`). NEVER use just the cube name as a field — `PullRequests.PullRequests`
|
|
56
|
-
"-
|
|
57
|
-
"-
|
|
60
|
+
"- Field names MUST be `CubeName.fieldName` with a DOT separator (e.g. `PullRequests.count`, `Teams.name`). NEVER use underscores, NEVER use just the cube name as a field — `PullRequests.PullRequests` and `Teams_count` are WRONG.",
|
|
61
|
+
"- Order keys MUST be one of the measures or dimensions already listed in that query. You CANNOT order by a field that is not in measures or dimensions — add it to measures first, or remove it from order.",
|
|
62
|
+
"- After EVERY `execute_query`, IMMEDIATELY call `add_markdown` and `add_portlet` in the SAME turn — never defer visualizations to a later turn",
|
|
58
63
|
"- Choose appropriate chart types: bar for categories, line for trends, table for detailed data",
|
|
59
|
-
"- When showing data, always add both a portlet (visualization) and markdown (explanation)",
|
|
60
64
|
"- If a query fails, explain the error and try an alternative approach",
|
|
61
65
|
"",
|
|
62
66
|
"## Output Format Rules",
|
|
@@ -160,19 +164,19 @@ function W(l) {
|
|
|
160
164
|
"",
|
|
161
165
|
"---",
|
|
162
166
|
"",
|
|
163
|
-
I(
|
|
167
|
+
I(j),
|
|
164
168
|
"",
|
|
165
169
|
"---",
|
|
166
170
|
"",
|
|
167
|
-
I(
|
|
171
|
+
I(U),
|
|
168
172
|
"",
|
|
169
173
|
"---",
|
|
170
174
|
"",
|
|
171
|
-
I(
|
|
175
|
+
I(Z),
|
|
172
176
|
"",
|
|
173
177
|
"---",
|
|
174
178
|
"",
|
|
175
|
-
I(
|
|
179
|
+
I(G),
|
|
176
180
|
"",
|
|
177
181
|
"---",
|
|
178
182
|
"",
|
|
@@ -226,11 +230,11 @@ function W(l) {
|
|
|
226
230
|
"",
|
|
227
231
|
"---",
|
|
228
232
|
"",
|
|
229
|
-
|
|
233
|
+
X(d)
|
|
230
234
|
].join(`
|
|
231
235
|
`);
|
|
232
236
|
}
|
|
233
|
-
const
|
|
237
|
+
const Q = {
|
|
234
238
|
label: "Bar Chart",
|
|
235
239
|
description: "Compare values across categories",
|
|
236
240
|
useCase: "Best for comparing discrete categories, showing rankings, or displaying changes over time",
|
|
@@ -296,7 +300,7 @@ const X = {
|
|
|
296
300
|
description: "Number formatting for right Y-axis"
|
|
297
301
|
}
|
|
298
302
|
]
|
|
299
|
-
},
|
|
303
|
+
}, ee = {
|
|
300
304
|
label: "Line Chart",
|
|
301
305
|
description: "Show trends and changes over time",
|
|
302
306
|
useCase: "Best for continuous data, trends, time series, and showing relationships between multiple series",
|
|
@@ -379,7 +383,7 @@ const X = {
|
|
|
379
383
|
description: "Number formatting for right Y-axis"
|
|
380
384
|
}
|
|
381
385
|
]
|
|
382
|
-
},
|
|
386
|
+
}, te = {
|
|
383
387
|
label: "Area Chart",
|
|
384
388
|
description: "Emphasize magnitude of change over time",
|
|
385
389
|
useCase: "Best for showing cumulative totals, volume changes, or stacked comparisons over time",
|
|
@@ -451,7 +455,7 @@ const X = {
|
|
|
451
455
|
description: "Number formatting for right Y-axis"
|
|
452
456
|
}
|
|
453
457
|
]
|
|
454
|
-
},
|
|
458
|
+
}, se = {
|
|
455
459
|
label: "Pie Chart",
|
|
456
460
|
description: "Show proportions of a whole",
|
|
457
461
|
useCase: "Best for showing percentage distribution or composition of a total (limit to 5-7 slices)",
|
|
@@ -485,7 +489,7 @@ const X = {
|
|
|
485
489
|
description: "Number formatting for values"
|
|
486
490
|
}
|
|
487
491
|
]
|
|
488
|
-
},
|
|
492
|
+
}, ae = {
|
|
489
493
|
label: "Scatter Plot",
|
|
490
494
|
description: "Reveal correlations between variables",
|
|
491
495
|
useCase: "Best for identifying patterns, correlations, outliers, and relationships between two measures",
|
|
@@ -533,7 +537,7 @@ const X = {
|
|
|
533
537
|
description: "Number formatting for Y-axis"
|
|
534
538
|
}
|
|
535
539
|
]
|
|
536
|
-
},
|
|
540
|
+
}, ie = {
|
|
537
541
|
label: "Bubble Chart",
|
|
538
542
|
description: "Compare three dimensions of data",
|
|
539
543
|
useCase: "Best for showing relationships between three variables (X, Y, and size), market analysis",
|
|
@@ -599,7 +603,7 @@ const X = {
|
|
|
599
603
|
description: "Number formatting for Y-axis and values"
|
|
600
604
|
}
|
|
601
605
|
]
|
|
602
|
-
},
|
|
606
|
+
}, oe = {
|
|
603
607
|
label: "Radar Chart",
|
|
604
608
|
description: "Compare multiple metrics across categories",
|
|
605
609
|
useCase: "Best for multivariate comparisons, performance metrics, strengths/weaknesses analysis",
|
|
@@ -638,7 +642,7 @@ const X = {
|
|
|
638
642
|
description: "Number formatting for values"
|
|
639
643
|
}
|
|
640
644
|
]
|
|
641
|
-
},
|
|
645
|
+
}, re = {
|
|
642
646
|
label: "Radial Bar Chart",
|
|
643
647
|
description: "Circular progress and KPI visualization",
|
|
644
648
|
useCase: "Best for showing progress toward goals, KPIs, or comparing percentages in a compact form",
|
|
@@ -670,7 +674,7 @@ const X = {
|
|
|
670
674
|
description: "Number formatting for values"
|
|
671
675
|
}
|
|
672
676
|
]
|
|
673
|
-
},
|
|
677
|
+
}, ne = {
|
|
674
678
|
label: "TreeMap",
|
|
675
679
|
description: "Visualize hierarchical data with nested rectangles",
|
|
676
680
|
useCase: "Best for showing part-to-whole relationships in hierarchical data, disk usage, budget allocation",
|
|
@@ -712,7 +716,7 @@ const X = {
|
|
|
712
716
|
}
|
|
713
717
|
],
|
|
714
718
|
clickableElements: { cell: !0 }
|
|
715
|
-
},
|
|
719
|
+
}, le = {
|
|
716
720
|
label: "Data Table",
|
|
717
721
|
description: "Display detailed tabular data",
|
|
718
722
|
useCase: "Best for precise values, detailed analysis, sortable/filterable data exploration",
|
|
@@ -735,7 +739,7 @@ const X = {
|
|
|
735
739
|
description: "Number formatting for numeric values"
|
|
736
740
|
}
|
|
737
741
|
]
|
|
738
|
-
},
|
|
742
|
+
}, de = {
|
|
739
743
|
label: "Activity Grid",
|
|
740
744
|
description: "GitHub-style activity grid showing temporal patterns across different time scales",
|
|
741
745
|
useCase: "Best for visualizing activity patterns over time. Supports hour (3hr blocks × days), day (days × weeks), week (weeks × months), month (months × quarters), and quarter (quarters × years) granularities",
|
|
@@ -769,9 +773,9 @@ const X = {
|
|
|
769
773
|
description: "Automatically size blocks to fill portlet width and height while maintaining aspect ratio"
|
|
770
774
|
}
|
|
771
775
|
],
|
|
772
|
-
validate: (
|
|
773
|
-
const { dateField:
|
|
774
|
-
return !
|
|
776
|
+
validate: (d) => {
|
|
777
|
+
const { dateField: s, valueField: a } = d;
|
|
778
|
+
return !s || Array.isArray(s) && s.length === 0 ? {
|
|
775
779
|
isValid: !1,
|
|
776
780
|
message: "Time dimension is required for activity grid"
|
|
777
781
|
} : !a || Array.isArray(a) && a.length === 0 ? {
|
|
@@ -780,7 +784,7 @@ const X = {
|
|
|
780
784
|
} : { isValid: !0 };
|
|
781
785
|
},
|
|
782
786
|
clickableElements: { cell: !0 }
|
|
783
|
-
},
|
|
787
|
+
}, pe = {
|
|
784
788
|
label: "KPI Number",
|
|
785
789
|
description: "Display key performance indicators as large numbers",
|
|
786
790
|
useCase: "Perfect for showing important metrics like revenue, user count, or other key business metrics in a prominent, easy-to-read format",
|
|
@@ -850,7 +854,7 @@ const X = {
|
|
|
850
854
|
}
|
|
851
855
|
],
|
|
852
856
|
displayOptions: ["hideHeader"]
|
|
853
|
-
},
|
|
857
|
+
}, ue = {
|
|
854
858
|
label: "KPI Delta",
|
|
855
859
|
description: "Display change between latest and previous values with trend indicators",
|
|
856
860
|
useCase: "Perfect for showing performance changes over time, such as revenue growth, user acquisition changes, or other metrics where the trend and delta are more important than the absolute value",
|
|
@@ -938,11 +942,11 @@ const X = {
|
|
|
938
942
|
}
|
|
939
943
|
],
|
|
940
944
|
displayOptions: ["hideHeader"],
|
|
941
|
-
validate: (
|
|
945
|
+
validate: (d) => !d.yAxis || Array.isArray(d.yAxis) && d.yAxis.length === 0 ? {
|
|
942
946
|
isValid: !1,
|
|
943
947
|
message: "A measure is required for KPI Delta charts"
|
|
944
948
|
} : { isValid: !0 }
|
|
945
|
-
},
|
|
949
|
+
}, ce = {
|
|
946
950
|
label: "KPI Text",
|
|
947
951
|
description: "Display key performance indicators as customizable text",
|
|
948
952
|
useCase: "Perfect for showing metrics with custom formatting, combining multiple values, or displaying contextual KPI information using templates",
|
|
@@ -984,7 +988,7 @@ const X = {
|
|
|
984
988
|
}
|
|
985
989
|
],
|
|
986
990
|
displayOptions: ["hideHeader"]
|
|
987
|
-
},
|
|
991
|
+
}, me = {
|
|
988
992
|
label: "Markdown",
|
|
989
993
|
description: "Display custom markdown content with formatting",
|
|
990
994
|
useCase: "Perfect for adding documentation, notes, section headers, instructions, or formatted text to dashboards",
|
|
@@ -1076,7 +1080,7 @@ Use --- for horizontal rules.`,
|
|
|
1076
1080
|
description: "Add an accent-colored border on one side of the content"
|
|
1077
1081
|
}
|
|
1078
1082
|
]
|
|
1079
|
-
},
|
|
1083
|
+
}, ye = {
|
|
1080
1084
|
label: "Funnel Chart",
|
|
1081
1085
|
description: "Show conversion through sequential steps",
|
|
1082
1086
|
useCase: "Best for visualizing user journey funnels, sales pipelines, or multi-step processes",
|
|
@@ -1163,7 +1167,7 @@ Use --- for horizontal rules.`,
|
|
|
1163
1167
|
description: "Display 90th percentile time to convert"
|
|
1164
1168
|
}
|
|
1165
1169
|
]
|
|
1166
|
-
},
|
|
1170
|
+
}, he = {
|
|
1167
1171
|
label: "Sankey Chart",
|
|
1168
1172
|
description: "Show flow between states or steps",
|
|
1169
1173
|
useCase: "Best for visualizing user journey flows, path analysis, or state transitions",
|
|
@@ -1219,7 +1223,7 @@ Use --- for horizontal rules.`,
|
|
|
1219
1223
|
description: "Hide the statistics footer below the chart"
|
|
1220
1224
|
}
|
|
1221
1225
|
]
|
|
1222
|
-
},
|
|
1226
|
+
}, fe = {
|
|
1223
1227
|
label: "Sunburst Chart",
|
|
1224
1228
|
description: "Show hierarchical flow as radial rings",
|
|
1225
1229
|
useCase: "Best for visualizing forward paths from a starting event in a compact radial layout",
|
|
@@ -1264,7 +1268,7 @@ Use --- for horizontal rules.`,
|
|
|
1264
1268
|
description: "Hide the statistics footer below the chart"
|
|
1265
1269
|
}
|
|
1266
1270
|
]
|
|
1267
|
-
},
|
|
1271
|
+
}, be = {
|
|
1268
1272
|
label: "Heatmap",
|
|
1269
1273
|
description: "Visualize intensity across two dimensions",
|
|
1270
1274
|
useCase: "Best for showing patterns in matrix data like correlations, schedules, or category comparisons",
|
|
@@ -1335,8 +1339,8 @@ Use --- for horizontal rules.`,
|
|
|
1335
1339
|
description: "Number formatting for cell values and legend"
|
|
1336
1340
|
}
|
|
1337
1341
|
],
|
|
1338
|
-
validate: (
|
|
1339
|
-
},
|
|
1342
|
+
validate: (d) => d.xAxis?.length ? d.yAxis?.length ? d.valueField?.length ? { isValid: !0 } : { isValid: !1, message: "Value measure required" } : { isValid: !1, message: "Y-axis dimension required" } : { isValid: !1, message: "X-axis dimension required" }
|
|
1343
|
+
}, ge = {
|
|
1340
1344
|
label: "Retention Matrix",
|
|
1341
1345
|
// RetentionHeatmap auto-configures from the retention data structure
|
|
1342
1346
|
// No drop zones needed as the chart maps directly to cohort × period matrix
|
|
@@ -1360,7 +1364,7 @@ Use --- for horizontal rules.`,
|
|
|
1360
1364
|
],
|
|
1361
1365
|
description: "Cohort retention matrix visualization",
|
|
1362
1366
|
useCase: "Visualize user retention over time by cohort"
|
|
1363
|
-
},
|
|
1367
|
+
}, xe = {
|
|
1364
1368
|
label: "Retention Chart",
|
|
1365
1369
|
// RetentionCombinedChart auto-configures from the retention data structure
|
|
1366
1370
|
// No drop zones needed as the chart maps directly to retention result data
|
|
@@ -1403,7 +1407,7 @@ Use --- for horizontal rules.`,
|
|
|
1403
1407
|
],
|
|
1404
1408
|
description: "Combined retention visualization with line chart and heatmap modes",
|
|
1405
1409
|
useCase: "Visualize user retention over time with optional breakdown segmentation"
|
|
1406
|
-
},
|
|
1410
|
+
}, we = {
|
|
1407
1411
|
label: "Box Plot",
|
|
1408
1412
|
description: "Show statistical distribution (median, IQR, whiskers) across categories",
|
|
1409
1413
|
useCase: "Best for P&L spread per symbol, trade size distribution, latency distribution across platforms",
|
|
@@ -1436,7 +1440,7 @@ Use --- for horizontal rules.`,
|
|
|
1436
1440
|
description: "Number formatting for the value axis"
|
|
1437
1441
|
}
|
|
1438
1442
|
]
|
|
1439
|
-
},
|
|
1443
|
+
}, ke = {
|
|
1440
1444
|
label: "Waterfall Chart",
|
|
1441
1445
|
description: "Show cumulative effect of sequential positive and negative values",
|
|
1442
1446
|
useCase: "Best for P&L decomposition, cash flow analysis, budget variance, or any sequential contribution breakdown",
|
|
@@ -1491,7 +1495,7 @@ Use --- for horizontal rules.`,
|
|
|
1491
1495
|
description: "Number formatting for the Y-axis"
|
|
1492
1496
|
}
|
|
1493
1497
|
]
|
|
1494
|
-
},
|
|
1498
|
+
}, ve = {
|
|
1495
1499
|
label: "Candlestick Chart",
|
|
1496
1500
|
description: "Financial candlestick chart showing open/close body and high/low wicks",
|
|
1497
1501
|
useCase: "Best for EOD quotes (bid/ask spread per date/symbol), markout distribution bands, or OHLC price data",
|
|
@@ -1556,7 +1560,7 @@ Use --- for horizontal rules.`,
|
|
|
1556
1560
|
description: "Number formatting for the price axis"
|
|
1557
1561
|
}
|
|
1558
1562
|
]
|
|
1559
|
-
},
|
|
1563
|
+
}, Ce = {
|
|
1560
1564
|
label: "Measure Profile",
|
|
1561
1565
|
description: "Plot N measures as sequential X-axis points to visualise a profile or shape across intervals",
|
|
1562
1566
|
useCase: "Best for markout interval analysis (e.g. avgMinus2m → avgAtEvent → avgPlus2h), metric profiles, or any pattern across ordered measures",
|
|
@@ -1621,7 +1625,7 @@ Use --- for horizontal rules.`,
|
|
|
1621
1625
|
description: "Number formatting for the Y-axis"
|
|
1622
1626
|
}
|
|
1623
1627
|
]
|
|
1624
|
-
},
|
|
1628
|
+
}, Te = {
|
|
1625
1629
|
label: "Gauge Chart",
|
|
1626
1630
|
description: "Half-circle arc gauge for a single KPI value versus a maximum target",
|
|
1627
1631
|
useCase: "Best for high-water marks vs equity, margin utilisation, or any single value progress toward a goal",
|
|
@@ -1680,133 +1684,133 @@ Use --- for horizontal rules.`,
|
|
|
1680
1684
|
description: "Number formatting for the displayed value and axis labels"
|
|
1681
1685
|
}
|
|
1682
1686
|
]
|
|
1683
|
-
},
|
|
1684
|
-
bar:
|
|
1685
|
-
line:
|
|
1686
|
-
area:
|
|
1687
|
-
pie:
|
|
1688
|
-
scatter:
|
|
1689
|
-
bubble:
|
|
1690
|
-
radar:
|
|
1691
|
-
radialBar:
|
|
1692
|
-
treemap:
|
|
1693
|
-
table:
|
|
1694
|
-
activityGrid:
|
|
1695
|
-
kpiNumber:
|
|
1696
|
-
kpiDelta:
|
|
1697
|
-
kpiText:
|
|
1698
|
-
markdown:
|
|
1699
|
-
funnel:
|
|
1700
|
-
sankey:
|
|
1701
|
-
sunburst:
|
|
1702
|
-
heatmap:
|
|
1703
|
-
retentionHeatmap:
|
|
1704
|
-
retentionCombined:
|
|
1705
|
-
boxPlot:
|
|
1706
|
-
waterfall:
|
|
1707
|
-
candlestick:
|
|
1708
|
-
measureProfile:
|
|
1709
|
-
gauge:
|
|
1687
|
+
}, R = {
|
|
1688
|
+
bar: Q,
|
|
1689
|
+
line: ee,
|
|
1690
|
+
area: te,
|
|
1691
|
+
pie: se,
|
|
1692
|
+
scatter: ae,
|
|
1693
|
+
bubble: ie,
|
|
1694
|
+
radar: oe,
|
|
1695
|
+
radialBar: re,
|
|
1696
|
+
treemap: ne,
|
|
1697
|
+
table: le,
|
|
1698
|
+
activityGrid: de,
|
|
1699
|
+
kpiNumber: pe,
|
|
1700
|
+
kpiDelta: ue,
|
|
1701
|
+
kpiText: ce,
|
|
1702
|
+
markdown: me,
|
|
1703
|
+
funnel: ye,
|
|
1704
|
+
sankey: he,
|
|
1705
|
+
sunburst: fe,
|
|
1706
|
+
heatmap: be,
|
|
1707
|
+
retentionHeatmap: ge,
|
|
1708
|
+
retentionCombined: xe,
|
|
1709
|
+
boxPlot: we,
|
|
1710
|
+
waterfall: ke,
|
|
1711
|
+
candlestick: ve,
|
|
1712
|
+
measureProfile: Ce,
|
|
1713
|
+
gauge: Te
|
|
1710
1714
|
};
|
|
1711
|
-
function
|
|
1712
|
-
const
|
|
1713
|
-
if (!
|
|
1715
|
+
function Ae(d, s, a) {
|
|
1716
|
+
const o = R[d];
|
|
1717
|
+
if (!o)
|
|
1714
1718
|
return { isValid: !0, errors: [] };
|
|
1715
|
-
if (
|
|
1719
|
+
if (o.skipQuery)
|
|
1716
1720
|
return { isValid: !0, errors: [] };
|
|
1717
|
-
const
|
|
1718
|
-
for (const
|
|
1719
|
-
if (!
|
|
1720
|
-
const e =
|
|
1721
|
+
const y = [];
|
|
1722
|
+
for (const h of o.dropZones) {
|
|
1723
|
+
if (!h.mandatory) continue;
|
|
1724
|
+
const e = s?.[h.key];
|
|
1721
1725
|
if (!(Array.isArray(e) ? e.length > 0 : !!e)) {
|
|
1722
|
-
const r =
|
|
1723
|
-
|
|
1724
|
-
`chartConfig.${
|
|
1726
|
+
const r = h.acceptTypes?.join("/") ?? "fields";
|
|
1727
|
+
y.push(
|
|
1728
|
+
`chartConfig.${h.key} is required for ${d} chart (${h.label}). Accepts: ${r}.`
|
|
1725
1729
|
);
|
|
1726
1730
|
}
|
|
1727
1731
|
}
|
|
1728
|
-
if (
|
|
1729
|
-
const
|
|
1730
|
-
if (!(Array.isArray(
|
|
1731
|
-
const
|
|
1732
|
-
|
|
1732
|
+
if (d === "bar") {
|
|
1733
|
+
const h = s?.xAxis;
|
|
1734
|
+
if (!(Array.isArray(h) ? h.length > 0 : !!h)) {
|
|
1735
|
+
const n = a.dimensions ?? [], r = a.timeDimensions ?? [];
|
|
1736
|
+
n.length > 0 || r.length > 0 ? y.push(
|
|
1733
1737
|
"chartConfig.xAxis is required for bar charts. Put a dimension in xAxis so bars have category labels."
|
|
1734
|
-
) :
|
|
1738
|
+
) : y.push(
|
|
1735
1739
|
'Bar charts need an xAxis dimension for category labels. Add a dimension to the query or use "table" chart type instead.'
|
|
1736
1740
|
);
|
|
1737
1741
|
}
|
|
1738
1742
|
}
|
|
1739
|
-
if (
|
|
1740
|
-
const
|
|
1741
|
-
Array.isArray(
|
|
1742
|
-
),
|
|
1743
|
-
|
|
1744
|
-
`chartConfig.series must not contain the same field as xAxis (found: ${
|
|
1743
|
+
if (s?.xAxis && s?.series) {
|
|
1744
|
+
const h = new Set(
|
|
1745
|
+
Array.isArray(s.xAxis) ? s.xAxis : [s.xAxis]
|
|
1746
|
+
), n = (Array.isArray(s.series) ? s.series : [s.series]).filter((r) => h.has(r));
|
|
1747
|
+
n.length > 0 && y.push(
|
|
1748
|
+
`chartConfig.series must not contain the same field as xAxis (found: ${n.join(", ")}). The series field is only for splitting into grouped/stacked sub-series by a DIFFERENT dimension. Remove the duplicate from series.`
|
|
1745
1749
|
);
|
|
1746
1750
|
}
|
|
1747
|
-
return { isValid:
|
|
1751
|
+
return { isValid: y.length === 0, errors: y };
|
|
1748
1752
|
}
|
|
1749
|
-
function
|
|
1750
|
-
const
|
|
1751
|
-
if (!
|
|
1752
|
-
return
|
|
1753
|
-
const
|
|
1754
|
-
for (const
|
|
1755
|
-
const
|
|
1756
|
-
if (Array.isArray(
|
|
1757
|
-
const
|
|
1758
|
-
if (
|
|
1759
|
-
if (
|
|
1760
|
-
const
|
|
1761
|
-
for (const
|
|
1762
|
-
if (
|
|
1763
|
-
const
|
|
1764
|
-
Array.isArray(
|
|
1753
|
+
function De(d, s, a) {
|
|
1754
|
+
const o = R[d];
|
|
1755
|
+
if (!o)
|
|
1756
|
+
return s ?? {};
|
|
1757
|
+
const y = { ...s }, h = a.measures ?? [], e = a.dimensions ?? [], r = (a.timeDimensions ?? []).map((t) => t.dimension);
|
|
1758
|
+
for (const t of o.dropZones) {
|
|
1759
|
+
const m = y[t.key];
|
|
1760
|
+
if (Array.isArray(m) ? m.length > 0 : !!m) continue;
|
|
1761
|
+
const l = t.acceptTypes ?? [];
|
|
1762
|
+
if (t.key === "sizeField" || t.key === "colorField") {
|
|
1763
|
+
if (l.includes("measure")) {
|
|
1764
|
+
const x = /* @__PURE__ */ new Set();
|
|
1765
|
+
for (const A of o.dropZones) {
|
|
1766
|
+
if (A.key === t.key) continue;
|
|
1767
|
+
const C = y[A.key];
|
|
1768
|
+
Array.isArray(C) ? C.forEach((T) => x.add(T)) : typeof C == "string" && x.add(C);
|
|
1765
1769
|
}
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1770
|
+
const D = h.filter((A) => !x.has(A));
|
|
1771
|
+
D.length > 0 && (y[t.key] = D[0]);
|
|
1768
1772
|
}
|
|
1769
1773
|
continue;
|
|
1770
1774
|
}
|
|
1771
|
-
const
|
|
1772
|
-
if (
|
|
1773
|
-
let
|
|
1774
|
-
if (
|
|
1775
|
-
const
|
|
1776
|
-
Array.isArray(
|
|
1775
|
+
const i = [];
|
|
1776
|
+
if (l.includes("dimension") && i.push(...e), l.includes("timeDimension") && i.push(...r), l.includes("measure") && i.push(...h), i.length === 0) continue;
|
|
1777
|
+
let g = i;
|
|
1778
|
+
if (t.key === "series") {
|
|
1779
|
+
const x = new Set(
|
|
1780
|
+
Array.isArray(y.xAxis) ? y.xAxis : y.xAxis ? [y.xAxis] : []
|
|
1777
1781
|
);
|
|
1778
|
-
if (
|
|
1782
|
+
if (g = i.filter((D) => !x.has(D)), g.length === 0) continue;
|
|
1779
1783
|
}
|
|
1780
|
-
const b =
|
|
1781
|
-
|
|
1784
|
+
const b = t.maxItems ?? 1 / 0, u = g.slice(0, b);
|
|
1785
|
+
u.length > 0 && (y[t.key] = u);
|
|
1782
1786
|
}
|
|
1783
|
-
return
|
|
1787
|
+
return y;
|
|
1784
1788
|
}
|
|
1785
|
-
function
|
|
1786
|
-
const
|
|
1789
|
+
function Se(d) {
|
|
1790
|
+
const s = [`
|
|
1787
1791
|
Chart config requirements by type:`];
|
|
1788
|
-
for (const a of
|
|
1789
|
-
const
|
|
1790
|
-
if (!
|
|
1791
|
-
const
|
|
1792
|
-
if (r.length === 0 && !
|
|
1793
|
-
|
|
1792
|
+
for (const a of d) {
|
|
1793
|
+
const o = R[a];
|
|
1794
|
+
if (!o) continue;
|
|
1795
|
+
const y = o.description ?? "", h = o.useCase ?? "", e = [y, h].filter(Boolean).join(". "), n = e ? ` — ${e}.` : "", r = o.dropZones.filter((m) => m.mandatory);
|
|
1796
|
+
if (r.length === 0 && !o.skipQuery) {
|
|
1797
|
+
s.push(` ${a}${n} chartConfig auto-inferred from query.`);
|
|
1794
1798
|
continue;
|
|
1795
1799
|
}
|
|
1796
|
-
if (
|
|
1797
|
-
|
|
1800
|
+
if (o.skipQuery) {
|
|
1801
|
+
s.push(` ${a}${n} No query needed.`);
|
|
1798
1802
|
continue;
|
|
1799
1803
|
}
|
|
1800
|
-
const
|
|
1801
|
-
const
|
|
1802
|
-
return `${
|
|
1804
|
+
const t = r.map((m) => {
|
|
1805
|
+
const p = m.acceptTypes?.join("/") ?? "any", l = m.maxItems ? ` (max ${m.maxItems})` : "";
|
|
1806
|
+
return `${m.key}=[${p}]${l}`;
|
|
1803
1807
|
});
|
|
1804
|
-
|
|
1808
|
+
s.push(` ${a}${n} Requires ${t.join(", ")}.`);
|
|
1805
1809
|
}
|
|
1806
|
-
return
|
|
1810
|
+
return s.join(`
|
|
1807
1811
|
`);
|
|
1808
1812
|
}
|
|
1809
|
-
const
|
|
1813
|
+
const L = [
|
|
1810
1814
|
"bar",
|
|
1811
1815
|
"line",
|
|
1812
1816
|
"area",
|
|
@@ -1826,13 +1830,13 @@ const N = [
|
|
|
1826
1830
|
"boxPlot",
|
|
1827
1831
|
"markdown"
|
|
1828
1832
|
];
|
|
1829
|
-
function
|
|
1833
|
+
function Fe() {
|
|
1830
1834
|
return [
|
|
1831
1835
|
// Tool 1: discover_cubes
|
|
1832
1836
|
{
|
|
1833
1837
|
name: "discover_cubes",
|
|
1834
1838
|
description: "Search for available data cubes by topic or intent. Call this FIRST to understand what data is available. Returns cube names, measures, dimensions, and relationships.",
|
|
1835
|
-
|
|
1839
|
+
parameters: {
|
|
1836
1840
|
type: "object",
|
|
1837
1841
|
properties: {
|
|
1838
1842
|
topic: { type: "string", description: 'Keyword to search (e.g., "sales", "employees")' },
|
|
@@ -1846,7 +1850,7 @@ function De() {
|
|
|
1846
1850
|
{
|
|
1847
1851
|
name: "get_cube_metadata",
|
|
1848
1852
|
description: "Get full metadata for all registered cubes including all measures, dimensions, types, and relationships. Use this for detailed schema information.",
|
|
1849
|
-
|
|
1853
|
+
parameters: {
|
|
1850
1854
|
type: "object",
|
|
1851
1855
|
properties: {}
|
|
1852
1856
|
}
|
|
@@ -1855,7 +1859,7 @@ function De() {
|
|
|
1855
1859
|
{
|
|
1856
1860
|
name: "execute_query",
|
|
1857
1861
|
description: "Execute a semantic query and return data results. Supports standard queries (measures/dimensions) and analysis modes (funnel/flow/retention). Only provide ONE mode per call.",
|
|
1858
|
-
|
|
1862
|
+
parameters: {
|
|
1859
1863
|
type: "object",
|
|
1860
1864
|
properties: {
|
|
1861
1865
|
measures: {
|
|
@@ -1896,7 +1900,7 @@ function De() {
|
|
|
1896
1900
|
},
|
|
1897
1901
|
order: {
|
|
1898
1902
|
type: "object",
|
|
1899
|
-
description: 'Sort order
|
|
1903
|
+
description: 'Sort order. Keys MUST be a measure or dimension from this query in "CubeName.fieldName" format, values are "asc" or "desc". Example: {"Teams.count": "desc"}. WRONG: {"Teams_count": "desc"}'
|
|
1900
1904
|
},
|
|
1901
1905
|
limit: {
|
|
1902
1906
|
type: "number",
|
|
@@ -1978,9 +1982,9 @@ function De() {
|
|
|
1978
1982
|
{
|
|
1979
1983
|
name: "add_portlet",
|
|
1980
1984
|
description: `Add a chart visualization to the notebook.
|
|
1981
|
-
` +
|
|
1985
|
+
` + Se(L) + `
|
|
1982
1986
|
The query is validated before adding. The portlet fetches its own data.`,
|
|
1983
|
-
|
|
1987
|
+
parameters: {
|
|
1984
1988
|
type: "object",
|
|
1985
1989
|
properties: {
|
|
1986
1990
|
title: { type: "string", description: "Title for the visualization" },
|
|
@@ -1990,7 +1994,7 @@ The query is validated before adding. The portlet fetches its own data.`,
|
|
|
1990
1994
|
},
|
|
1991
1995
|
chartType: {
|
|
1992
1996
|
type: "string",
|
|
1993
|
-
enum:
|
|
1997
|
+
enum: L,
|
|
1994
1998
|
description: "Chart type to render"
|
|
1995
1999
|
},
|
|
1996
2000
|
chartConfig: {
|
|
@@ -2023,7 +2027,7 @@ The query is validated before adding. The portlet fetches its own data.`,
|
|
|
2023
2027
|
{
|
|
2024
2028
|
name: "add_markdown",
|
|
2025
2029
|
description: "Add an explanation or analysis text block to the notebook. Use markdown formatting. Use this to explain findings, methodology, and insights alongside visualizations.",
|
|
2026
|
-
|
|
2030
|
+
parameters: {
|
|
2027
2031
|
type: "object",
|
|
2028
2032
|
properties: {
|
|
2029
2033
|
title: { type: "string", description: "Optional title for the text block" },
|
|
@@ -2036,7 +2040,7 @@ The query is validated before adding. The portlet fetches its own data.`,
|
|
|
2036
2040
|
{
|
|
2037
2041
|
name: "save_as_dashboard",
|
|
2038
2042
|
description: "Convert the current notebook analysis into a persistent dashboard. Constructs a professional DashboardConfig with proper grid layout, section headers (markdown portlets), and dashboard-level filters. Call this when the user asks to save/export the notebook as a dashboard.",
|
|
2039
|
-
|
|
2043
|
+
parameters: {
|
|
2040
2044
|
type: "object",
|
|
2041
2045
|
properties: {
|
|
2042
2046
|
title: { type: "string", description: "Dashboard title" },
|
|
@@ -2050,7 +2054,7 @@ The query is validated before adding. The portlet fetches its own data.`,
|
|
|
2050
2054
|
title: { type: "string", description: "Portlet title" },
|
|
2051
2055
|
chartType: {
|
|
2052
2056
|
type: "string",
|
|
2053
|
-
enum:
|
|
2057
|
+
enum: L,
|
|
2054
2058
|
description: 'Chart type. Use "markdown" for section headers.'
|
|
2055
2059
|
},
|
|
2056
2060
|
query: {
|
|
@@ -2121,81 +2125,135 @@ The query is validated before adding. The portlet fetches its own data.`,
|
|
|
2121
2125
|
}
|
|
2122
2126
|
];
|
|
2123
2127
|
}
|
|
2124
|
-
function
|
|
2125
|
-
const { semanticLayer:
|
|
2126
|
-
|
|
2127
|
-
const
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2128
|
+
function Ee(d) {
|
|
2129
|
+
const { semanticLayer: s, securityContext: a } = d, o = /* @__PURE__ */ new Map();
|
|
2130
|
+
o.set("discover_cubes", async (e) => {
|
|
2131
|
+
const r = {
|
|
2132
|
+
cubes: (await K(s, {
|
|
2133
|
+
topic: e.topic,
|
|
2134
|
+
intent: e.intent,
|
|
2135
|
+
limit: e.limit,
|
|
2136
|
+
minScore: e.minScore
|
|
2137
|
+
})).cubes.map((t) => ({
|
|
2138
|
+
cube: t.cube,
|
|
2139
|
+
title: t.title,
|
|
2140
|
+
description: t.description,
|
|
2141
|
+
relevanceScore: t.relevanceScore,
|
|
2142
|
+
suggestedMeasures: t.suggestedMeasures,
|
|
2143
|
+
suggestedDimensions: t.suggestedDimensions,
|
|
2144
|
+
capabilities: t.capabilities,
|
|
2145
|
+
// Only include analysisConfig if advanced modes are available, and only the essentials
|
|
2146
|
+
...t.capabilities.funnel || t.capabilities.flow || t.capabilities.retention ? {
|
|
2147
|
+
analysisConfig: {
|
|
2148
|
+
candidateBindingKeys: t.analysisConfig?.candidateBindingKeys?.map((m) => m.dimension) ?? [],
|
|
2149
|
+
candidateTimeDimensions: t.analysisConfig?.candidateTimeDimensions?.map((m) => m.dimension) ?? [],
|
|
2150
|
+
...t.analysisConfig?.candidateEventDimensions?.length ? { candidateEventDimensions: t.analysisConfig.candidateEventDimensions.map((m) => m.dimension) } : {}
|
|
2151
|
+
}
|
|
2152
|
+
} : {}
|
|
2153
|
+
// querySchemas and hints are omitted — already in the system prompt
|
|
2154
|
+
}))
|
|
2155
|
+
};
|
|
2156
|
+
return { result: JSON.stringify(r) + `
|
|
2157
|
+
[IMPORTANT: Your next response MUST start with a brief text message BEFORE any tool calls.]` };
|
|
2158
|
+
}), o.set("get_cube_metadata", async () => {
|
|
2159
|
+
const e = s.getMetadata();
|
|
2160
|
+
return { result: JSON.stringify(e) };
|
|
2137
2161
|
});
|
|
2138
|
-
const
|
|
2139
|
-
for (const e of
|
|
2140
|
-
|
|
2141
|
-
measures: (e.measures || []).map((
|
|
2142
|
-
dimensions: (e.dimensions || []).map((
|
|
2162
|
+
const y = /* @__PURE__ */ new Map();
|
|
2163
|
+
for (const e of s.getMetadata())
|
|
2164
|
+
y.set(e.name, {
|
|
2165
|
+
measures: (e.measures || []).map((n) => n.name),
|
|
2166
|
+
dimensions: (e.dimensions || []).map((n) => n.name)
|
|
2143
2167
|
});
|
|
2144
|
-
const
|
|
2145
|
-
const r =
|
|
2146
|
-
return !
|
|
2168
|
+
const h = (e, n) => {
|
|
2169
|
+
const r = y.get(e), t = n === "measures" ? r?.measures : r?.dimensions;
|
|
2170
|
+
return !t || t.length === 0 ? "" : ` Available ${n}: ${t.slice(0, 5).map((m) => `"${m}"`).join(", ")}`;
|
|
2147
2171
|
};
|
|
2148
|
-
return
|
|
2172
|
+
return o.set("execute_query", async (e) => {
|
|
2149
2173
|
try {
|
|
2150
|
-
const
|
|
2151
|
-
if (!Array.isArray(
|
|
2152
|
-
const
|
|
2153
|
-
for (const b of
|
|
2174
|
+
const n = (p, l) => {
|
|
2175
|
+
if (!Array.isArray(p)) return;
|
|
2176
|
+
const i = [], g = [];
|
|
2177
|
+
for (const b of p) {
|
|
2154
2178
|
if (typeof b != "string") {
|
|
2155
|
-
|
|
2179
|
+
g.push(b);
|
|
2156
2180
|
continue;
|
|
2157
2181
|
}
|
|
2158
|
-
const
|
|
2159
|
-
if (
|
|
2160
|
-
|
|
2182
|
+
const u = b.split(".");
|
|
2183
|
+
if (u.length === 1) {
|
|
2184
|
+
i.push(`"${b}" is not valid — must be "CubeName.fieldName".${h(b, l)}`);
|
|
2161
2185
|
continue;
|
|
2162
2186
|
}
|
|
2163
|
-
if (
|
|
2164
|
-
const
|
|
2165
|
-
|
|
2187
|
+
if (u.length === 3 && u[0] === u[1]) {
|
|
2188
|
+
const x = `${u[0]}.${u[2]}`;
|
|
2189
|
+
g.push(x);
|
|
2166
2190
|
continue;
|
|
2167
2191
|
}
|
|
2168
|
-
if (
|
|
2169
|
-
|
|
2192
|
+
if (u.length === 2 && u[0] === u[1]) {
|
|
2193
|
+
i.push(`"${b}" is WRONG — "${u[0]}" is the cube name, not a ${l.replace(/s$/, "")}.${h(u[0], l)}`);
|
|
2170
2194
|
continue;
|
|
2171
2195
|
}
|
|
2172
|
-
|
|
2196
|
+
g.push(b);
|
|
2173
2197
|
}
|
|
2174
|
-
if (
|
|
2175
|
-
throw new Error(`Invalid ${
|
|
2176
|
-
${
|
|
2198
|
+
if (i.length > 0)
|
|
2199
|
+
throw new Error(`Invalid ${l}:
|
|
2200
|
+
${i.join(`
|
|
2177
2201
|
`)}`);
|
|
2178
|
-
return
|
|
2202
|
+
return g;
|
|
2179
2203
|
};
|
|
2180
|
-
e.measures =
|
|
2181
|
-
const r = (
|
|
2182
|
-
const
|
|
2183
|
-
return
|
|
2204
|
+
e.measures = n(e.measures, "measures") ?? e.measures, e.dimensions = n(e.dimensions, "dimensions") ?? e.dimensions;
|
|
2205
|
+
const r = (p) => {
|
|
2206
|
+
const l = p.split(".");
|
|
2207
|
+
return l.length === 3 && l[0] === l[1] ? `${l[0]}.${l[2]}` : p;
|
|
2184
2208
|
};
|
|
2185
2209
|
if (Array.isArray(e.filters))
|
|
2186
|
-
for (const
|
|
2187
|
-
typeof
|
|
2210
|
+
for (const p of e.filters)
|
|
2211
|
+
typeof p.member == "string" && (p.member = r(p.member));
|
|
2188
2212
|
if (Array.isArray(e.timeDimensions))
|
|
2189
|
-
for (const
|
|
2190
|
-
typeof
|
|
2213
|
+
for (const p of e.timeDimensions)
|
|
2214
|
+
typeof p.dimension == "string" && (p.dimension = r(p.dimension));
|
|
2215
|
+
if (Array.isArray(e.order)) {
|
|
2216
|
+
const p = {};
|
|
2217
|
+
for (const l of e.order)
|
|
2218
|
+
l && typeof l == "object" && Object.assign(p, l);
|
|
2219
|
+
e.order = p;
|
|
2220
|
+
}
|
|
2191
2221
|
if (e.order && typeof e.order == "object" && !Array.isArray(e.order)) {
|
|
2192
|
-
const
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2222
|
+
const p = /* @__PURE__ */ new Set([
|
|
2223
|
+
...Array.isArray(e.measures) ? e.measures : [],
|
|
2224
|
+
...Array.isArray(e.dimensions) ? e.dimensions : []
|
|
2225
|
+
]), l = {};
|
|
2226
|
+
for (const [i, g] of Object.entries(e.order)) {
|
|
2227
|
+
const b = r(i);
|
|
2228
|
+
if (p.has(b)) {
|
|
2229
|
+
l[b] = g;
|
|
2230
|
+
continue;
|
|
2231
|
+
}
|
|
2232
|
+
if (!i.includes(".") && i.includes("_")) {
|
|
2233
|
+
const u = i.replace(/_/g, "."), x = r(u);
|
|
2234
|
+
if (p.has(x)) {
|
|
2235
|
+
l[x] = g;
|
|
2236
|
+
continue;
|
|
2237
|
+
}
|
|
2238
|
+
const D = [...p].find((A) => {
|
|
2239
|
+
const C = A.split(".")[1];
|
|
2240
|
+
return C && (i.endsWith(`_${C}`) || i.endsWith(`.${C}`));
|
|
2241
|
+
});
|
|
2242
|
+
if (D) {
|
|
2243
|
+
l[D] = g;
|
|
2244
|
+
continue;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
p.size > 0 && !p.has(b) || (l[b] = g);
|
|
2248
|
+
}
|
|
2249
|
+
if (Object.keys(l).length === 0 && p.size > 0) {
|
|
2250
|
+
const i = Array.isArray(e.measures) ? e.measures[0] : void 0;
|
|
2251
|
+
i && (l[i] = "desc");
|
|
2252
|
+
}
|
|
2253
|
+
e.order = l;
|
|
2196
2254
|
}
|
|
2197
|
-
let
|
|
2198
|
-
e.funnel ?
|
|
2255
|
+
let t;
|
|
2256
|
+
e.funnel ? t = { funnel: e.funnel } : e.flow ? t = { flow: e.flow } : e.retention ? t = { retention: e.retention } : t = {
|
|
2199
2257
|
measures: e.measures,
|
|
2200
2258
|
dimensions: e.dimensions,
|
|
2201
2259
|
filters: e.filters,
|
|
@@ -2203,15 +2261,16 @@ ${n.join(`
|
|
|
2203
2261
|
order: e.order,
|
|
2204
2262
|
limit: e.limit
|
|
2205
2263
|
};
|
|
2206
|
-
const
|
|
2264
|
+
const m = await W(s, a, { query: t });
|
|
2207
2265
|
return {
|
|
2208
2266
|
result: JSON.stringify({
|
|
2209
|
-
rowCount:
|
|
2210
|
-
data:
|
|
2211
|
-
annotation:
|
|
2212
|
-
}
|
|
2267
|
+
rowCount: m.data.length,
|
|
2268
|
+
data: m.data,
|
|
2269
|
+
annotation: m.annotation
|
|
2270
|
+
}) + `
|
|
2271
|
+
[IMPORTANT: Your next response MUST start with a brief text message BEFORE any tool calls. Now call add_markdown and add_portlet to visualize these results.]`
|
|
2213
2272
|
};
|
|
2214
|
-
} catch (
|
|
2273
|
+
} catch (n) {
|
|
2215
2274
|
const r = {
|
|
2216
2275
|
measures: e.measures,
|
|
2217
2276
|
dimensions: e.dimensions,
|
|
@@ -2224,97 +2283,97 @@ ${n.join(`
|
|
|
2224
2283
|
...e.retention ? { retention: e.retention } : {}
|
|
2225
2284
|
};
|
|
2226
2285
|
return {
|
|
2227
|
-
result: `Query execution failed: ${
|
|
2286
|
+
result: `Query execution failed: ${n instanceof Error ? n.message : "Unknown error"}
|
|
2228
2287
|
|
|
2229
2288
|
Attempted query:
|
|
2230
2289
|
${JSON.stringify(r, null, 2)}`,
|
|
2231
2290
|
isError: !0
|
|
2232
2291
|
};
|
|
2233
2292
|
}
|
|
2234
|
-
}),
|
|
2293
|
+
}), o.set("add_portlet", async (e) => {
|
|
2235
2294
|
const r = {
|
|
2236
2295
|
number: "kpiNumber",
|
|
2237
2296
|
retention: "retentionHeatmap"
|
|
2238
2297
|
}[e.chartType] ?? e.chartType;
|
|
2239
|
-
let
|
|
2298
|
+
let t;
|
|
2240
2299
|
try {
|
|
2241
|
-
|
|
2300
|
+
t = JSON.parse(e.query);
|
|
2242
2301
|
} catch {
|
|
2243
2302
|
return {
|
|
2244
2303
|
result: "Invalid query: could not parse JSON string. Ensure `query` is a valid JSON string.",
|
|
2245
2304
|
isError: !0
|
|
2246
2305
|
};
|
|
2247
2306
|
}
|
|
2248
|
-
const
|
|
2249
|
-
if (!
|
|
2307
|
+
const m = s.validateQuery(t);
|
|
2308
|
+
if (!m.isValid)
|
|
2250
2309
|
return {
|
|
2251
2310
|
result: `Invalid query — fix these errors and retry:
|
|
2252
|
-
${
|
|
2311
|
+
${m.errors.join(`
|
|
2253
2312
|
`)}
|
|
2254
2313
|
|
|
2255
2314
|
Attempted query:
|
|
2256
|
-
${JSON.stringify(
|
|
2315
|
+
${JSON.stringify(t, null, 2)}`,
|
|
2257
2316
|
isError: !0
|
|
2258
2317
|
};
|
|
2259
|
-
const
|
|
2260
|
-
let
|
|
2261
|
-
if (
|
|
2262
|
-
|
|
2318
|
+
const p = !!(t.funnel || t.flow || t.retention);
|
|
2319
|
+
let l;
|
|
2320
|
+
if (p)
|
|
2321
|
+
l = e.chartConfig ?? {};
|
|
2263
2322
|
else {
|
|
2264
|
-
const b =
|
|
2265
|
-
if (!
|
|
2323
|
+
const b = De(r, e.chartConfig, t), u = Ae(r, b, t);
|
|
2324
|
+
if (!u.isValid)
|
|
2266
2325
|
return {
|
|
2267
2326
|
result: `Chart config invalid — fix these errors and retry:
|
|
2268
|
-
${
|
|
2327
|
+
${u.errors.join(`
|
|
2269
2328
|
`)}`,
|
|
2270
2329
|
isError: !0
|
|
2271
2330
|
};
|
|
2272
|
-
|
|
2331
|
+
l = b;
|
|
2273
2332
|
}
|
|
2274
|
-
const
|
|
2275
|
-
id:
|
|
2333
|
+
const i = `portlet-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, g = {
|
|
2334
|
+
id: i,
|
|
2276
2335
|
title: e.title,
|
|
2277
2336
|
query: e.query,
|
|
2278
2337
|
chartType: r,
|
|
2279
|
-
chartConfig:
|
|
2338
|
+
chartConfig: l,
|
|
2280
2339
|
displayConfig: e.displayConfig
|
|
2281
2340
|
};
|
|
2282
2341
|
return {
|
|
2283
|
-
result: `Portlet "${e.title}" added to notebook (id: ${
|
|
2284
|
-
sideEffect: { type: "add_portlet", data:
|
|
2342
|
+
result: `Portlet "${e.title}" added to notebook (id: ${i}, chart: ${r}). [Reminder: in your next response, start with a brief sentence about what you will do next BEFORE making any tool calls.]`,
|
|
2343
|
+
sideEffect: { type: "add_portlet", data: g }
|
|
2285
2344
|
};
|
|
2286
|
-
}),
|
|
2287
|
-
const
|
|
2288
|
-
id:
|
|
2345
|
+
}), o.set("add_markdown", async (e) => {
|
|
2346
|
+
const n = `markdown-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, r = e.content || e.text || e.markdown || "", t = {
|
|
2347
|
+
id: n,
|
|
2289
2348
|
title: e.title,
|
|
2290
|
-
content:
|
|
2349
|
+
content: r
|
|
2291
2350
|
};
|
|
2292
2351
|
return {
|
|
2293
|
-
result: `Markdown block added to notebook (id: ${
|
|
2294
|
-
sideEffect: { type: "add_markdown", data:
|
|
2352
|
+
result: `Markdown block added to notebook (id: ${n}). [Reminder: in your next response, start with a brief sentence about what you will do next BEFORE making any tool calls.]`,
|
|
2353
|
+
sideEffect: { type: "add_markdown", data: t }
|
|
2295
2354
|
};
|
|
2296
|
-
}),
|
|
2355
|
+
}), o.set("save_as_dashboard", async (e) => {
|
|
2297
2356
|
try {
|
|
2298
|
-
const
|
|
2299
|
-
if (!
|
|
2357
|
+
const n = e.portlets;
|
|
2358
|
+
if (!n || n.length === 0)
|
|
2300
2359
|
return { result: "Dashboard must contain at least one portlet.", isError: !0 };
|
|
2301
2360
|
const r = [];
|
|
2302
|
-
for (const
|
|
2303
|
-
if (
|
|
2304
|
-
const b =
|
|
2361
|
+
for (const i of n) {
|
|
2362
|
+
if (i.chartType === "markdown") continue;
|
|
2363
|
+
const b = i.query;
|
|
2305
2364
|
if (!b) {
|
|
2306
|
-
r.push(`Portlet "${
|
|
2365
|
+
r.push(`Portlet "${i.title}": missing query`);
|
|
2307
2366
|
continue;
|
|
2308
2367
|
}
|
|
2309
|
-
let
|
|
2368
|
+
let u;
|
|
2310
2369
|
try {
|
|
2311
|
-
|
|
2370
|
+
u = JSON.parse(b);
|
|
2312
2371
|
} catch {
|
|
2313
|
-
r.push(`Portlet "${
|
|
2372
|
+
r.push(`Portlet "${i.title}": invalid JSON query`);
|
|
2314
2373
|
continue;
|
|
2315
2374
|
}
|
|
2316
|
-
const
|
|
2317
|
-
|
|
2375
|
+
const x = s.validateQuery(u);
|
|
2376
|
+
x.isValid || r.push(`Portlet "${i.title}": ${x.errors.join(", ")}`);
|
|
2318
2377
|
}
|
|
2319
2378
|
if (r.length > 0)
|
|
2320
2379
|
return {
|
|
@@ -2323,318 +2382,332 @@ ${r.join(`
|
|
|
2323
2382
|
`)}`,
|
|
2324
2383
|
isError: !0
|
|
2325
2384
|
};
|
|
2326
|
-
const
|
|
2327
|
-
portlets:
|
|
2328
|
-
const
|
|
2329
|
-
let
|
|
2385
|
+
const t = {
|
|
2386
|
+
portlets: n.map((i) => {
|
|
2387
|
+
const g = i.chartType, b = g === "markdown", u = b ? "query" : i.analysisType || "query", x = u === "funnel" ? "funnel" : u === "flow" ? "flow" : u === "retention" ? "retention" : "query", D = i.query || "{}";
|
|
2388
|
+
let A;
|
|
2330
2389
|
try {
|
|
2331
|
-
|
|
2390
|
+
A = JSON.parse(D);
|
|
2332
2391
|
} catch {
|
|
2333
|
-
|
|
2392
|
+
A = {};
|
|
2334
2393
|
}
|
|
2335
|
-
const
|
|
2394
|
+
const C = {
|
|
2336
2395
|
version: 1,
|
|
2337
|
-
analysisType:
|
|
2396
|
+
analysisType: x,
|
|
2338
2397
|
activeView: "chart",
|
|
2339
2398
|
charts: {
|
|
2340
|
-
[
|
|
2341
|
-
chartType:
|
|
2342
|
-
chartConfig:
|
|
2343
|
-
displayConfig:
|
|
2399
|
+
[x]: {
|
|
2400
|
+
chartType: g,
|
|
2401
|
+
chartConfig: i.chartConfig || {},
|
|
2402
|
+
displayConfig: i.displayConfig || {}
|
|
2344
2403
|
}
|
|
2345
2404
|
},
|
|
2346
|
-
query: b ? {} :
|
|
2405
|
+
query: b ? {} : A
|
|
2347
2406
|
};
|
|
2348
2407
|
return {
|
|
2349
|
-
id:
|
|
2350
|
-
title:
|
|
2351
|
-
analysisConfig:
|
|
2352
|
-
dashboardFilterMapping:
|
|
2353
|
-
w:
|
|
2354
|
-
h:
|
|
2355
|
-
x:
|
|
2356
|
-
y:
|
|
2408
|
+
id: i.id,
|
|
2409
|
+
title: i.title,
|
|
2410
|
+
analysisConfig: C,
|
|
2411
|
+
dashboardFilterMapping: i.dashboardFilterMapping,
|
|
2412
|
+
w: i.w,
|
|
2413
|
+
h: i.h,
|
|
2414
|
+
x: i.x,
|
|
2415
|
+
y: i.y
|
|
2357
2416
|
};
|
|
2358
2417
|
}),
|
|
2359
2418
|
filters: e.filters,
|
|
2360
2419
|
colorPalette: e.colorPalette
|
|
2361
|
-
},
|
|
2420
|
+
}, m = e.title, p = t.portlets.length, l = t.filters?.length || 0;
|
|
2362
2421
|
return {
|
|
2363
|
-
result: `Dashboard "${
|
|
2422
|
+
result: `Dashboard "${m}" created with ${p} portlets and ${l} filters.`,
|
|
2364
2423
|
sideEffect: {
|
|
2365
2424
|
type: "dashboard_saved",
|
|
2366
2425
|
data: {
|
|
2367
|
-
title:
|
|
2426
|
+
title: m,
|
|
2368
2427
|
description: e.description,
|
|
2369
|
-
dashboardConfig:
|
|
2428
|
+
dashboardConfig: t
|
|
2370
2429
|
}
|
|
2371
2430
|
}
|
|
2372
2431
|
};
|
|
2373
|
-
} catch (
|
|
2432
|
+
} catch (n) {
|
|
2374
2433
|
return {
|
|
2375
|
-
result: `Failed to save dashboard: ${
|
|
2434
|
+
result: `Failed to save dashboard: ${n instanceof Error ? n.message : "Unknown error"}`,
|
|
2376
2435
|
isError: !0
|
|
2377
2436
|
};
|
|
2378
2437
|
}
|
|
2379
|
-
}),
|
|
2438
|
+
}), o;
|
|
2439
|
+
}
|
|
2440
|
+
async function Ve(d, s, a) {
|
|
2441
|
+
switch (d) {
|
|
2442
|
+
case "anthropic": {
|
|
2443
|
+
const { AnthropicProvider: o } = await import("./anthropic-CTu9E801.js");
|
|
2444
|
+
return new o(s);
|
|
2445
|
+
}
|
|
2446
|
+
case "openai": {
|
|
2447
|
+
const { OpenAIProvider: o } = await import("./openai-CUSRuKTk.js");
|
|
2448
|
+
return new o(s, a);
|
|
2449
|
+
}
|
|
2450
|
+
case "google": {
|
|
2451
|
+
const { GoogleProvider: o } = await import("./google-DficVAsJ.js");
|
|
2452
|
+
return new o(s);
|
|
2453
|
+
}
|
|
2454
|
+
default:
|
|
2455
|
+
throw new Error(
|
|
2456
|
+
`Unknown LLM provider: "${d}". Supported providers: anthropic, openai, google`
|
|
2457
|
+
);
|
|
2458
|
+
}
|
|
2380
2459
|
}
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2460
|
+
const Oe = {
|
|
2461
|
+
anthropic: "claude-sonnet-4-6",
|
|
2462
|
+
openai: "gpt-4.1-mini",
|
|
2463
|
+
google: "gemini-3-flash-preview"
|
|
2464
|
+
};
|
|
2465
|
+
async function* Ie(d) {
|
|
2466
|
+
const { message: s, history: a, semanticLayer: o, securityContext: y, agentConfig: h, apiKey: e } = d, n = d.sessionId || crypto.randomUUID(), r = h.observability, t = crypto.randomUUID(), m = Date.now(), p = d.providerOverride || h.provider || "anthropic", l = d.modelOverride || h.model || Oe[p] || "claude-sonnet-4-6", i = d.baseURLOverride || h.baseURL, g = h.maxTurns || 25, b = h.maxTokens || 4096;
|
|
2467
|
+
let u;
|
|
2384
2468
|
try {
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
);
|
|
2389
|
-
y = f.default || f.Anthropic || f;
|
|
2390
|
-
} catch {
|
|
2391
|
-
yield {
|
|
2469
|
+
u = await Ve(p, e, { baseURL: i });
|
|
2470
|
+
} catch (f) {
|
|
2471
|
+
console.error(`[agent] Failed to create ${p} provider:`, f), yield {
|
|
2392
2472
|
type: "error",
|
|
2393
2473
|
data: {
|
|
2394
|
-
message:
|
|
2474
|
+
message: f instanceof Error ? f.message : "Failed to initialize LLM provider"
|
|
2395
2475
|
}
|
|
2396
2476
|
};
|
|
2397
2477
|
return;
|
|
2398
2478
|
}
|
|
2399
|
-
const
|
|
2400
|
-
let
|
|
2401
|
-
|
|
2479
|
+
const x = Fe(), D = Ee({ semanticLayer: o, securityContext: y }), A = o.getMetadata();
|
|
2480
|
+
let C = J(A);
|
|
2481
|
+
d.systemContext && (C += `
|
|
2402
2482
|
|
|
2403
2483
|
## User Context
|
|
2404
2484
|
|
|
2405
|
-
${
|
|
2406
|
-
const g = u.model || "claude-sonnet-4-6", A = u.maxTurns || 25, C = u.maxTokens || 4096;
|
|
2485
|
+
${d.systemContext}`);
|
|
2407
2486
|
try {
|
|
2408
2487
|
r?.onChatStart?.({
|
|
2409
|
-
traceId:
|
|
2410
|
-
sessionId:
|
|
2411
|
-
message:
|
|
2412
|
-
model:
|
|
2488
|
+
traceId: t,
|
|
2489
|
+
sessionId: n,
|
|
2490
|
+
message: s,
|
|
2491
|
+
model: l,
|
|
2413
2492
|
historyLength: a?.length ?? 0
|
|
2414
2493
|
});
|
|
2415
2494
|
} catch {
|
|
2416
2495
|
}
|
|
2417
|
-
const
|
|
2496
|
+
const T = [];
|
|
2418
2497
|
if (a && a.length > 0) {
|
|
2419
2498
|
for (const f of a)
|
|
2420
2499
|
if (f.role === "user")
|
|
2421
|
-
|
|
2500
|
+
T.push({ role: "user", content: f.content });
|
|
2422
2501
|
else if (f.role === "assistant") {
|
|
2423
|
-
const
|
|
2424
|
-
if (f.content &&
|
|
2502
|
+
const O = [];
|
|
2503
|
+
if (f.content && O.push({ type: "text", text: f.content }), f.toolCalls && f.toolCalls.length > 0) {
|
|
2425
2504
|
for (const w of f.toolCalls)
|
|
2426
|
-
|
|
2505
|
+
O.push({
|
|
2427
2506
|
type: "tool_use",
|
|
2428
2507
|
id: w.id,
|
|
2429
2508
|
name: w.name,
|
|
2430
2509
|
input: w.input || {}
|
|
2431
2510
|
});
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2511
|
+
T.push({ role: "assistant", content: O });
|
|
2512
|
+
const v = f.toolCalls.map((w) => ({
|
|
2513
|
+
toolUseId: w.id,
|
|
2514
|
+
toolName: w.name,
|
|
2515
|
+
content: typeof w.result == "string" ? w.result : JSON.stringify(w.result ?? ""),
|
|
2516
|
+
isError: w.status === "error"
|
|
2517
|
+
})), S = u.formatToolResults(v);
|
|
2518
|
+
if (Array.isArray(S))
|
|
2519
|
+
for (const w of S)
|
|
2520
|
+
T.push(w);
|
|
2521
|
+
else
|
|
2522
|
+
T.push(S);
|
|
2523
|
+
} else O.length > 0 && T.push({ role: "assistant", content: f.content });
|
|
2442
2524
|
}
|
|
2443
2525
|
}
|
|
2444
|
-
|
|
2445
|
-
let
|
|
2526
|
+
T.push({ role: "user", content: s });
|
|
2527
|
+
let P = 0;
|
|
2446
2528
|
try {
|
|
2447
|
-
for (let f = 0; f <
|
|
2448
|
-
|
|
2449
|
-
const
|
|
2450
|
-
model:
|
|
2451
|
-
|
|
2452
|
-
system:
|
|
2453
|
-
tools:
|
|
2454
|
-
messages:
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
for await (const
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
const
|
|
2464
|
-
|
|
2529
|
+
for (let f = 0; f < g; f++) {
|
|
2530
|
+
P = f + 1;
|
|
2531
|
+
const O = await u.createStream({
|
|
2532
|
+
model: l,
|
|
2533
|
+
maxTokens: b,
|
|
2534
|
+
system: C,
|
|
2535
|
+
tools: x,
|
|
2536
|
+
messages: T
|
|
2537
|
+
}), v = [];
|
|
2538
|
+
let S = "", w = "", _, Y;
|
|
2539
|
+
const B = Date.now();
|
|
2540
|
+
let N = !1;
|
|
2541
|
+
for await (const V of u.parseStreamEvents(O)) {
|
|
2542
|
+
const c = V;
|
|
2543
|
+
switch (c.type) {
|
|
2544
|
+
case "text_delta": {
|
|
2545
|
+
const k = v[v.length - 1];
|
|
2546
|
+
k && k.type === "text" ? k.text = (k.text || "") + c.text : v.push({ type: "text", text: c.text }), yield { type: "text_delta", data: c.text };
|
|
2547
|
+
break;
|
|
2548
|
+
}
|
|
2549
|
+
case "tool_use_start": {
|
|
2550
|
+
if (N && S) {
|
|
2551
|
+
const k = v[v.length - 1];
|
|
2552
|
+
if (k?.type === "tool_use")
|
|
2553
|
+
try {
|
|
2554
|
+
k.input = JSON.parse(S);
|
|
2555
|
+
} catch {
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
v.push({ type: "tool_use", id: c.id, name: c.name, input: {}, ...c.metadata ? { metadata: c.metadata } : {} }), S = "", N = !0, yield {
|
|
2465
2559
|
type: "tool_use_start",
|
|
2466
|
-
data: { id:
|
|
2467
|
-
}
|
|
2560
|
+
data: { id: c.id, name: c.name, input: void 0 }
|
|
2561
|
+
};
|
|
2468
2562
|
break;
|
|
2469
2563
|
}
|
|
2470
|
-
case "
|
|
2471
|
-
|
|
2472
|
-
if (p.type === "text_delta" && p.text) {
|
|
2473
|
-
const D = w[q];
|
|
2474
|
-
D && (D.text = (D.text || "") + p.text), yield { type: "text_delta", data: p.text };
|
|
2475
|
-
} else p.type === "input_json_delta" && p.partial_json && (V += p.partial_json);
|
|
2564
|
+
case "tool_input_delta": {
|
|
2565
|
+
S += c.json;
|
|
2476
2566
|
break;
|
|
2477
2567
|
}
|
|
2478
|
-
case "
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2568
|
+
case "tool_use_end": {
|
|
2569
|
+
if (c.id && c.input) {
|
|
2570
|
+
const k = v.find((F) => F.type === "tool_use" && F.id === c.id);
|
|
2571
|
+
k && (k.input = c.input);
|
|
2572
|
+
} else if (N) {
|
|
2573
|
+
const k = v[v.length - 1];
|
|
2574
|
+
if (k?.type === "tool_use" && S) {
|
|
2575
|
+
try {
|
|
2576
|
+
k.input = JSON.parse(S);
|
|
2577
|
+
} catch {
|
|
2578
|
+
k.input = {};
|
|
2579
|
+
}
|
|
2580
|
+
S = "";
|
|
2485
2581
|
}
|
|
2486
|
-
|
|
2582
|
+
N = !1;
|
|
2487
2583
|
}
|
|
2488
2584
|
break;
|
|
2489
2585
|
}
|
|
2490
|
-
case "
|
|
2491
|
-
|
|
2492
|
-
p?.usage?.input_tokens != null && (L = p.usage.input_tokens);
|
|
2493
|
-
break;
|
|
2494
|
-
}
|
|
2495
|
-
case "message_delta": {
|
|
2496
|
-
const p = v.delta, D = v.usage;
|
|
2497
|
-
D?.output_tokens != null && (M = D.output_tokens), p.stop_reason && (O = p.stop_reason);
|
|
2586
|
+
case "message_meta": {
|
|
2587
|
+
c.inputTokens != null && (_ = c.inputTokens), c.outputTokens != null && (Y = c.outputTokens), c.stopReason && (w = c.stopReason);
|
|
2498
2588
|
break;
|
|
2499
2589
|
}
|
|
2500
2590
|
}
|
|
2591
|
+
}
|
|
2501
2592
|
try {
|
|
2502
2593
|
r?.onGenerationEnd?.({
|
|
2503
|
-
traceId:
|
|
2594
|
+
traceId: t,
|
|
2504
2595
|
turn: f,
|
|
2505
|
-
model:
|
|
2506
|
-
stopReason:
|
|
2507
|
-
inputTokens:
|
|
2508
|
-
outputTokens:
|
|
2509
|
-
durationMs: Date.now() -
|
|
2596
|
+
model: l,
|
|
2597
|
+
stopReason: w,
|
|
2598
|
+
inputTokens: _,
|
|
2599
|
+
outputTokens: Y,
|
|
2600
|
+
durationMs: Date.now() - B,
|
|
2601
|
+
input: T,
|
|
2602
|
+
output: v
|
|
2510
2603
|
});
|
|
2511
2604
|
} catch {
|
|
2512
2605
|
}
|
|
2513
|
-
if (
|
|
2606
|
+
if (T.push({ role: "assistant", content: v }), !u.shouldContinue(w))
|
|
2514
2607
|
break;
|
|
2515
|
-
const
|
|
2516
|
-
for (const
|
|
2517
|
-
if (
|
|
2518
|
-
const
|
|
2519
|
-
if (
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
content: `Unknown tool: ${
|
|
2524
|
-
|
|
2608
|
+
const q = [];
|
|
2609
|
+
for (const V of v) {
|
|
2610
|
+
if (V.type !== "tool_use") continue;
|
|
2611
|
+
const c = V.name, k = V.input || {}, F = V.id, $ = D.get(c);
|
|
2612
|
+
if (!$) {
|
|
2613
|
+
q.push({
|
|
2614
|
+
toolUseId: F,
|
|
2615
|
+
toolName: c,
|
|
2616
|
+
content: `Unknown tool: ${c}`,
|
|
2617
|
+
isError: !0
|
|
2525
2618
|
}), yield {
|
|
2526
2619
|
type: "tool_use_result",
|
|
2527
|
-
data: { id:
|
|
2620
|
+
data: { id: F, name: c, result: `Unknown tool: ${c}`, isError: !0 }
|
|
2528
2621
|
};
|
|
2529
2622
|
continue;
|
|
2530
2623
|
}
|
|
2531
|
-
const
|
|
2624
|
+
const z = Date.now();
|
|
2532
2625
|
try {
|
|
2533
|
-
const
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
content:
|
|
2538
|
-
...
|
|
2626
|
+
const E = await $(k);
|
|
2627
|
+
E.sideEffect && (yield E.sideEffect), q.push({
|
|
2628
|
+
toolUseId: F,
|
|
2629
|
+
toolName: c,
|
|
2630
|
+
content: E.result,
|
|
2631
|
+
...E.isError ? { isError: !0 } : {}
|
|
2539
2632
|
}), yield {
|
|
2540
2633
|
type: "tool_use_result",
|
|
2541
|
-
data: { id:
|
|
2634
|
+
data: { id: F, name: c, result: E.result, ...E.isError ? { isError: !0 } : {} }
|
|
2542
2635
|
};
|
|
2543
2636
|
try {
|
|
2544
2637
|
r?.onToolEnd?.({
|
|
2545
|
-
traceId:
|
|
2638
|
+
traceId: t,
|
|
2546
2639
|
turn: f,
|
|
2547
|
-
toolName:
|
|
2548
|
-
toolUseId:
|
|
2549
|
-
isError: !!
|
|
2550
|
-
durationMs: Date.now() -
|
|
2640
|
+
toolName: c,
|
|
2641
|
+
toolUseId: F,
|
|
2642
|
+
isError: !!E.isError,
|
|
2643
|
+
durationMs: Date.now() - z
|
|
2551
2644
|
});
|
|
2552
2645
|
} catch {
|
|
2553
2646
|
}
|
|
2554
|
-
} catch (
|
|
2555
|
-
const
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
content:
|
|
2560
|
-
|
|
2647
|
+
} catch (E) {
|
|
2648
|
+
const H = E instanceof Error ? E.message : "Tool execution failed";
|
|
2649
|
+
q.push({
|
|
2650
|
+
toolUseId: F,
|
|
2651
|
+
toolName: c,
|
|
2652
|
+
content: H,
|
|
2653
|
+
isError: !0
|
|
2561
2654
|
}), yield {
|
|
2562
2655
|
type: "tool_use_result",
|
|
2563
|
-
data: { id:
|
|
2656
|
+
data: { id: F, name: c, result: H, isError: !0 }
|
|
2564
2657
|
};
|
|
2565
2658
|
try {
|
|
2566
2659
|
r?.onToolEnd?.({
|
|
2567
|
-
traceId:
|
|
2660
|
+
traceId: t,
|
|
2568
2661
|
turn: f,
|
|
2569
|
-
toolName:
|
|
2570
|
-
toolUseId:
|
|
2662
|
+
toolName: c,
|
|
2663
|
+
toolUseId: F,
|
|
2571
2664
|
isError: !0,
|
|
2572
|
-
durationMs: Date.now() -
|
|
2665
|
+
durationMs: Date.now() - z
|
|
2573
2666
|
});
|
|
2574
2667
|
} catch {
|
|
2575
2668
|
}
|
|
2576
2669
|
}
|
|
2577
2670
|
}
|
|
2578
|
-
yield { type: "turn_complete", data: {} }
|
|
2671
|
+
yield { type: "turn_complete", data: {} };
|
|
2672
|
+
const M = u.formatToolResults(q);
|
|
2673
|
+
if (Array.isArray(M))
|
|
2674
|
+
for (const V of M)
|
|
2675
|
+
T.push(V);
|
|
2676
|
+
else
|
|
2677
|
+
T.push(M);
|
|
2579
2678
|
}
|
|
2580
2679
|
try {
|
|
2581
2680
|
r?.onChatEnd?.({
|
|
2582
|
-
traceId:
|
|
2583
|
-
sessionId:
|
|
2584
|
-
totalTurns:
|
|
2585
|
-
durationMs: Date.now() -
|
|
2681
|
+
traceId: t,
|
|
2682
|
+
sessionId: n,
|
|
2683
|
+
totalTurns: P,
|
|
2684
|
+
durationMs: Date.now() - m
|
|
2586
2685
|
});
|
|
2587
2686
|
} catch {
|
|
2588
2687
|
}
|
|
2589
2688
|
yield {
|
|
2590
2689
|
type: "done",
|
|
2591
|
-
data: { sessionId:
|
|
2690
|
+
data: { sessionId: n || "", traceId: t }
|
|
2592
2691
|
};
|
|
2593
2692
|
} catch (f) {
|
|
2594
2693
|
try {
|
|
2595
2694
|
r?.onChatEnd?.({
|
|
2596
|
-
traceId:
|
|
2597
|
-
sessionId:
|
|
2695
|
+
traceId: t,
|
|
2696
|
+
sessionId: n,
|
|
2598
2697
|
totalTurns: 0,
|
|
2599
|
-
durationMs: Date.now() -
|
|
2698
|
+
durationMs: Date.now() - m,
|
|
2600
2699
|
error: f instanceof Error ? f.message : "Unknown error"
|
|
2601
2700
|
});
|
|
2602
2701
|
} catch {
|
|
2603
2702
|
}
|
|
2604
|
-
yield {
|
|
2703
|
+
console.error(`[agent] Chat error (provider=${p}, model=${l}):`, f), yield {
|
|
2605
2704
|
type: "error",
|
|
2606
2705
|
data: {
|
|
2607
|
-
message:
|
|
2706
|
+
message: u.formatError(f)
|
|
2608
2707
|
}
|
|
2609
2708
|
};
|
|
2610
2709
|
}
|
|
2611
2710
|
}
|
|
2612
|
-
function Fe(l) {
|
|
2613
|
-
if (!l || !(l instanceof Error))
|
|
2614
|
-
return "Something went wrong. Please try again.";
|
|
2615
|
-
const t = l.message || "", a = {
|
|
2616
|
-
overloaded_error: "The AI service is temporarily overloaded. Please try again in a moment.",
|
|
2617
|
-
rate_limit_error: "Too many requests. Please wait a moment and try again.",
|
|
2618
|
-
api_error: "The AI service encountered an error. Please try again.",
|
|
2619
|
-
authentication_error: "Authentication failed. Please check your API key configuration.",
|
|
2620
|
-
invalid_request_error: "There was a problem with the request. Please try again."
|
|
2621
|
-
}, i = l;
|
|
2622
|
-
if (i.status || i.type) {
|
|
2623
|
-
const d = i.error?.type || i.type || "";
|
|
2624
|
-
if (a[d])
|
|
2625
|
-
return a[d];
|
|
2626
|
-
}
|
|
2627
|
-
if (t.startsWith("{") || t.startsWith("Error: {")) {
|
|
2628
|
-
try {
|
|
2629
|
-
const d = JSON.parse(t.replace(/^Error:\s*/, "")), u = d.error?.type || d.type || "";
|
|
2630
|
-
if (a[u])
|
|
2631
|
-
return a[u];
|
|
2632
|
-
} catch {
|
|
2633
|
-
}
|
|
2634
|
-
return "The AI service encountered an error. Please try again.";
|
|
2635
|
-
}
|
|
2636
|
-
return t;
|
|
2637
|
-
}
|
|
2638
2711
|
export {
|
|
2639
|
-
|
|
2712
|
+
Ie as handleAgentChat
|
|
2640
2713
|
};
|