drizzle-cube 0.4.15 → 0.4.16
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/express/index.cjs +1 -1
- package/dist/adapters/express/index.js +1 -1
- package/dist/adapters/fastify/index.cjs +1 -1
- package/dist/adapters/fastify/index.js +1 -1
- package/dist/adapters/{handler-ZDYlokiM.cjs → handler-B6yAJw_O.cjs} +12 -12
- package/dist/adapters/{handler-DZnCbydH.js → handler-BmTtVoRu.js} +203 -194
- package/dist/adapters/hono/index.cjs +1 -1
- package/dist/adapters/hono/index.js +1 -1
- package/dist/adapters/nextjs/index.cjs +1 -1
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/server/index.cjs +40 -40
- package/dist/server/index.js +19 -10
- package/package.json +1 -1
|
@@ -7,22 +7,22 @@ function z(o) {
|
|
|
7
7
|
for (const a of o) {
|
|
8
8
|
if (t.push(`### ${a.name}`), a.description && t.push(a.description), a.measures && a.measures.length > 0) {
|
|
9
9
|
t.push(""), t.push("**Measures:**");
|
|
10
|
-
for (const
|
|
11
|
-
const e =
|
|
12
|
-
t.push(`- \`${a.name}.${
|
|
10
|
+
for (const s of a.measures) {
|
|
11
|
+
const e = s.description ? ` - ${s.description}` : "";
|
|
12
|
+
t.push(`- \`${a.name}.${s.name}\` (${s.type})${e}`);
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
if (a.dimensions && a.dimensions.length > 0) {
|
|
16
16
|
t.push(""), t.push("**Dimensions:**");
|
|
17
|
-
for (const
|
|
18
|
-
const e =
|
|
19
|
-
t.push(`- \`${a.name}.${
|
|
17
|
+
for (const s of a.dimensions) {
|
|
18
|
+
const e = s.description ? ` - ${s.description}` : "";
|
|
19
|
+
t.push(`- \`${a.name}.${s.name}\` (${s.type})${e}`);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
if (a.relationships && a.relationships.length > 0) {
|
|
23
23
|
t.push(""), t.push("**Joins:**");
|
|
24
|
-
for (const
|
|
25
|
-
t.push(`- → \`${
|
|
24
|
+
for (const s of a.relationships)
|
|
25
|
+
t.push(`- → \`${s.targetCube}\` (${s.relationship})`);
|
|
26
26
|
}
|
|
27
27
|
a.meta?.eventStream && (t.push(""), t.push("**Event Stream:** Yes (supports funnel, flow, retention queries)"), a.meta.eventStream.bindingKey && t.push(`- Binding key: \`${a.name}.${a.meta.eventStream.bindingKey}\``), a.meta.eventStream.timeDimension && t.push(`- Time dimension: \`${a.name}.${a.meta.eventStream.timeDimension}\``)), t.push("");
|
|
28
28
|
}
|
|
@@ -230,7 +230,7 @@ function H(o) {
|
|
|
230
230
|
].join(`
|
|
231
231
|
`);
|
|
232
232
|
}
|
|
233
|
-
const
|
|
233
|
+
const $ = {
|
|
234
234
|
label: "Bar Chart",
|
|
235
235
|
description: "Compare values across categories",
|
|
236
236
|
useCase: "Best for comparing discrete categories, showing rankings, or displaying changes over time",
|
|
@@ -296,7 +296,7 @@ const B = {
|
|
|
296
296
|
description: "Number formatting for right Y-axis"
|
|
297
297
|
}
|
|
298
298
|
]
|
|
299
|
-
},
|
|
299
|
+
}, B = {
|
|
300
300
|
label: "Line Chart",
|
|
301
301
|
description: "Show trends and changes over time",
|
|
302
302
|
useCase: "Best for continuous data, trends, time series, and showing relationships between multiple series",
|
|
@@ -451,7 +451,7 @@ const B = {
|
|
|
451
451
|
description: "Number formatting for right Y-axis"
|
|
452
452
|
}
|
|
453
453
|
]
|
|
454
|
-
},
|
|
454
|
+
}, Z = {
|
|
455
455
|
label: "Pie Chart",
|
|
456
456
|
description: "Show proportions of a whole",
|
|
457
457
|
useCase: "Best for showing percentage distribution or composition of a total (limit to 5-7 slices)",
|
|
@@ -485,7 +485,7 @@ const B = {
|
|
|
485
485
|
description: "Number formatting for values"
|
|
486
486
|
}
|
|
487
487
|
]
|
|
488
|
-
},
|
|
488
|
+
}, G = {
|
|
489
489
|
label: "Scatter Plot",
|
|
490
490
|
description: "Reveal correlations between variables",
|
|
491
491
|
useCase: "Best for identifying patterns, correlations, outliers, and relationships between two measures",
|
|
@@ -533,7 +533,7 @@ const B = {
|
|
|
533
533
|
description: "Number formatting for Y-axis"
|
|
534
534
|
}
|
|
535
535
|
]
|
|
536
|
-
},
|
|
536
|
+
}, U = {
|
|
537
537
|
label: "Bubble Chart",
|
|
538
538
|
description: "Compare three dimensions of data",
|
|
539
539
|
useCase: "Best for showing relationships between three variables (X, Y, and size), market analysis",
|
|
@@ -599,7 +599,7 @@ const B = {
|
|
|
599
599
|
description: "Number formatting for Y-axis and values"
|
|
600
600
|
}
|
|
601
601
|
]
|
|
602
|
-
},
|
|
602
|
+
}, K = {
|
|
603
603
|
label: "Radar Chart",
|
|
604
604
|
description: "Compare multiple metrics across categories",
|
|
605
605
|
useCase: "Best for multivariate comparisons, performance metrics, strengths/weaknesses analysis",
|
|
@@ -984,7 +984,7 @@ const B = {
|
|
|
984
984
|
}
|
|
985
985
|
],
|
|
986
986
|
displayOptions: ["hideHeader"]
|
|
987
|
-
},
|
|
987
|
+
}, se = {
|
|
988
988
|
label: "Markdown",
|
|
989
989
|
description: "Display custom markdown content with formatting",
|
|
990
990
|
useCase: "Perfect for adding documentation, notes, section headers, instructions, or formatted text to dashboards",
|
|
@@ -1076,7 +1076,7 @@ Use --- for horizontal rules.`,
|
|
|
1076
1076
|
description: "Add an accent-colored border on one side of the content"
|
|
1077
1077
|
}
|
|
1078
1078
|
]
|
|
1079
|
-
},
|
|
1079
|
+
}, ie = {
|
|
1080
1080
|
label: "Funnel Chart",
|
|
1081
1081
|
description: "Show conversion through sequential steps",
|
|
1082
1082
|
useCase: "Best for visualizing user journey funnels, sales pipelines, or multi-step processes",
|
|
@@ -1680,14 +1680,14 @@ Use --- for horizontal rules.`,
|
|
|
1680
1680
|
description: "Number formatting for the displayed value and axis labels"
|
|
1681
1681
|
}
|
|
1682
1682
|
]
|
|
1683
|
-
},
|
|
1684
|
-
bar:
|
|
1685
|
-
line:
|
|
1683
|
+
}, E = {
|
|
1684
|
+
bar: $,
|
|
1685
|
+
line: B,
|
|
1686
1686
|
area: j,
|
|
1687
|
-
pie:
|
|
1688
|
-
scatter:
|
|
1689
|
-
bubble:
|
|
1690
|
-
radar:
|
|
1687
|
+
pie: Z,
|
|
1688
|
+
scatter: G,
|
|
1689
|
+
bubble: U,
|
|
1690
|
+
radar: K,
|
|
1691
1691
|
radialBar: W,
|
|
1692
1692
|
treemap: X,
|
|
1693
1693
|
table: J,
|
|
@@ -1695,8 +1695,8 @@ Use --- for horizontal rules.`,
|
|
|
1695
1695
|
kpiNumber: ee,
|
|
1696
1696
|
kpiDelta: te,
|
|
1697
1697
|
kpiText: ae,
|
|
1698
|
-
markdown:
|
|
1699
|
-
funnel:
|
|
1698
|
+
markdown: se,
|
|
1699
|
+
funnel: ie,
|
|
1700
1700
|
sankey: oe,
|
|
1701
1701
|
sunburst: re,
|
|
1702
1702
|
heatmap: ne,
|
|
@@ -1709,27 +1709,27 @@ Use --- for horizontal rules.`,
|
|
|
1709
1709
|
gauge: ye
|
|
1710
1710
|
};
|
|
1711
1711
|
function he(o, t, a) {
|
|
1712
|
-
const
|
|
1713
|
-
if (!
|
|
1712
|
+
const s = E[o];
|
|
1713
|
+
if (!s)
|
|
1714
1714
|
return { isValid: !0, errors: [] };
|
|
1715
|
-
if (
|
|
1715
|
+
if (s.skipQuery)
|
|
1716
1716
|
return { isValid: !0, errors: [] };
|
|
1717
1717
|
const e = [];
|
|
1718
|
-
for (const
|
|
1719
|
-
if (!
|
|
1720
|
-
const r = t?.[
|
|
1718
|
+
for (const i of s.dropZones) {
|
|
1719
|
+
if (!i.mandatory) continue;
|
|
1720
|
+
const r = t?.[i.key];
|
|
1721
1721
|
if (!(Array.isArray(r) ? r.length > 0 : !!r)) {
|
|
1722
|
-
const
|
|
1722
|
+
const c = i.acceptTypes?.join("/") ?? "fields";
|
|
1723
1723
|
e.push(
|
|
1724
|
-
`chartConfig.${
|
|
1724
|
+
`chartConfig.${i.key} is required for ${o} chart (${i.label}). Accepts: ${c}.`
|
|
1725
1725
|
);
|
|
1726
1726
|
}
|
|
1727
1727
|
}
|
|
1728
1728
|
if (o === "bar") {
|
|
1729
|
-
const
|
|
1730
|
-
if (!(Array.isArray(
|
|
1731
|
-
const
|
|
1732
|
-
|
|
1729
|
+
const i = t?.xAxis;
|
|
1730
|
+
if (!(Array.isArray(i) ? i.length > 0 : !!i)) {
|
|
1731
|
+
const l = a.dimensions ?? [], c = a.timeDimensions ?? [];
|
|
1732
|
+
l.length > 0 || c.length > 0 ? e.push(
|
|
1733
1733
|
"chartConfig.xAxis is required for bar charts. Put a dimension in xAxis so bars have category labels."
|
|
1734
1734
|
) : e.push(
|
|
1735
1735
|
'Bar charts need an xAxis dimension for category labels. Add a dimension to the query or use "table" chart type instead.'
|
|
@@ -1737,48 +1737,48 @@ function he(o, t, a) {
|
|
|
1737
1737
|
}
|
|
1738
1738
|
}
|
|
1739
1739
|
if (t?.xAxis && t?.series) {
|
|
1740
|
-
const
|
|
1740
|
+
const i = new Set(
|
|
1741
1741
|
Array.isArray(t.xAxis) ? t.xAxis : [t.xAxis]
|
|
1742
|
-
),
|
|
1743
|
-
|
|
1744
|
-
`chartConfig.series must not contain the same field as xAxis (found: ${
|
|
1742
|
+
), l = (Array.isArray(t.series) ? t.series : [t.series]).filter((c) => i.has(c));
|
|
1743
|
+
l.length > 0 && e.push(
|
|
1744
|
+
`chartConfig.series must not contain the same field as xAxis (found: ${l.join(", ")}). The series field is only for splitting into grouped/stacked sub-series by a DIFFERENT dimension. Remove the duplicate from series.`
|
|
1745
1745
|
);
|
|
1746
1746
|
}
|
|
1747
1747
|
return { isValid: e.length === 0, errors: e };
|
|
1748
1748
|
}
|
|
1749
1749
|
function fe(o, t, a) {
|
|
1750
|
-
const
|
|
1751
|
-
if (!
|
|
1750
|
+
const s = E[o];
|
|
1751
|
+
if (!s)
|
|
1752
1752
|
return t ?? {};
|
|
1753
|
-
const e = { ...t },
|
|
1754
|
-
for (const
|
|
1755
|
-
const
|
|
1756
|
-
if (Array.isArray(
|
|
1757
|
-
const g =
|
|
1758
|
-
if (
|
|
1753
|
+
const e = { ...t }, i = a.measures ?? [], r = a.dimensions ?? [], c = (a.timeDimensions ?? []).map((u) => u.dimension);
|
|
1754
|
+
for (const u of s.dropZones) {
|
|
1755
|
+
const m = e[u.key];
|
|
1756
|
+
if (Array.isArray(m) ? m.length > 0 : !!m) continue;
|
|
1757
|
+
const g = u.acceptTypes ?? [];
|
|
1758
|
+
if (u.key === "sizeField" || u.key === "colorField") {
|
|
1759
1759
|
if (g.includes("measure")) {
|
|
1760
1760
|
const h = /* @__PURE__ */ new Set();
|
|
1761
|
-
for (const x of
|
|
1762
|
-
if (x.key ===
|
|
1763
|
-
const
|
|
1764
|
-
Array.isArray(
|
|
1761
|
+
for (const x of s.dropZones) {
|
|
1762
|
+
if (x.key === u.key) continue;
|
|
1763
|
+
const y = e[x.key];
|
|
1764
|
+
Array.isArray(y) ? y.forEach((A) => h.add(A)) : typeof y == "string" && h.add(y);
|
|
1765
1765
|
}
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1766
|
+
const p = i.filter((x) => !h.has(x));
|
|
1767
|
+
p.length > 0 && (e[u.key] = p[0]);
|
|
1768
1768
|
}
|
|
1769
1769
|
continue;
|
|
1770
1770
|
}
|
|
1771
1771
|
const f = [];
|
|
1772
|
-
if (g.includes("dimension") && f.push(...r), g.includes("timeDimension") && f.push(...
|
|
1772
|
+
if (g.includes("dimension") && f.push(...r), g.includes("timeDimension") && f.push(...c), g.includes("measure") && f.push(...i), f.length === 0) continue;
|
|
1773
1773
|
let b = f;
|
|
1774
|
-
if (
|
|
1774
|
+
if (u.key === "series") {
|
|
1775
1775
|
const h = new Set(
|
|
1776
1776
|
Array.isArray(e.xAxis) ? e.xAxis : e.xAxis ? [e.xAxis] : []
|
|
1777
1777
|
);
|
|
1778
|
-
if (b = f.filter((
|
|
1778
|
+
if (b = f.filter((p) => !h.has(p)), b.length === 0) continue;
|
|
1779
1779
|
}
|
|
1780
|
-
const w =
|
|
1781
|
-
C.length > 0 && (e[
|
|
1780
|
+
const w = u.maxItems ?? 1 / 0, C = b.slice(0, w);
|
|
1781
|
+
C.length > 0 && (e[u.key] = C);
|
|
1782
1782
|
}
|
|
1783
1783
|
return e;
|
|
1784
1784
|
}
|
|
@@ -1786,22 +1786,22 @@ function be(o) {
|
|
|
1786
1786
|
const t = [`
|
|
1787
1787
|
Chart config requirements by type:`];
|
|
1788
1788
|
for (const a of o) {
|
|
1789
|
-
const
|
|
1790
|
-
if (!
|
|
1791
|
-
const e =
|
|
1792
|
-
if (
|
|
1793
|
-
t.push(` ${a}${
|
|
1789
|
+
const s = E[a];
|
|
1790
|
+
if (!s) continue;
|
|
1791
|
+
const e = s.description ?? "", i = s.useCase ?? "", r = [e, i].filter(Boolean).join(". "), l = r ? ` — ${r}.` : "", c = s.dropZones.filter((m) => m.mandatory);
|
|
1792
|
+
if (c.length === 0 && !s.skipQuery) {
|
|
1793
|
+
t.push(` ${a}${l} chartConfig auto-inferred from query.`);
|
|
1794
1794
|
continue;
|
|
1795
1795
|
}
|
|
1796
|
-
if (
|
|
1797
|
-
t.push(` ${a}${
|
|
1796
|
+
if (s.skipQuery) {
|
|
1797
|
+
t.push(` ${a}${l} No query needed.`);
|
|
1798
1798
|
continue;
|
|
1799
1799
|
}
|
|
1800
|
-
const
|
|
1801
|
-
const
|
|
1802
|
-
return `${
|
|
1800
|
+
const u = c.map((m) => {
|
|
1801
|
+
const n = m.acceptTypes?.join("/") ?? "any", g = m.maxItems ? ` (max ${m.maxItems})` : "";
|
|
1802
|
+
return `${m.key}=[${n}]${g}`;
|
|
1803
1803
|
});
|
|
1804
|
-
t.push(` ${a}${
|
|
1804
|
+
t.push(` ${a}${l} Requires ${u.join(", ")}.`);
|
|
1805
1805
|
}
|
|
1806
1806
|
return t.join(`
|
|
1807
1807
|
`);
|
|
@@ -1860,13 +1860,13 @@ function ge() {
|
|
|
1860
1860
|
properties: {
|
|
1861
1861
|
measures: {
|
|
1862
1862
|
type: "array",
|
|
1863
|
-
items: { type: "string" },
|
|
1864
|
-
description: 'Aggregation measures (e.g., ["
|
|
1863
|
+
items: { type: "string", pattern: "^[A-Z][a-zA-Z0-9]*\\.[a-zA-Z][a-zA-Z0-9]*$" },
|
|
1864
|
+
description: 'Aggregation measures — MUST be "CubeName.measureName" format (e.g., ["PullRequests.count", "Issues.openCount"]). NEVER use just the cube name.'
|
|
1865
1865
|
},
|
|
1866
1866
|
dimensions: {
|
|
1867
1867
|
type: "array",
|
|
1868
|
-
items: { type: "string" },
|
|
1869
|
-
description: 'Grouping dimensions (e.g., ["
|
|
1868
|
+
items: { type: "string", pattern: "^[A-Z][a-zA-Z0-9]*\\.[a-zA-Z][a-zA-Z0-9]*$" },
|
|
1869
|
+
description: 'Grouping dimensions — MUST be "CubeName.dimensionName" format (e.g., ["Teams.name", "Employees.department"]). NEVER use just the cube name.'
|
|
1870
1870
|
},
|
|
1871
1871
|
filters: {
|
|
1872
1872
|
type: "array",
|
|
@@ -2122,22 +2122,31 @@ The query is validated before adding. The portlet fetches its own data.`,
|
|
|
2122
2122
|
];
|
|
2123
2123
|
}
|
|
2124
2124
|
function xe(o) {
|
|
2125
|
-
const { semanticLayer: t, securityContext: a } = o,
|
|
2126
|
-
return
|
|
2127
|
-
const
|
|
2125
|
+
const { semanticLayer: t, securityContext: a } = o, s = /* @__PURE__ */ new Map();
|
|
2126
|
+
return s.set("discover_cubes", async (e) => {
|
|
2127
|
+
const i = await Y(t, {
|
|
2128
2128
|
topic: e.topic,
|
|
2129
2129
|
intent: e.intent,
|
|
2130
2130
|
limit: e.limit,
|
|
2131
2131
|
minScore: e.minScore
|
|
2132
2132
|
});
|
|
2133
|
-
return { result: JSON.stringify(
|
|
2134
|
-
}),
|
|
2133
|
+
return { result: JSON.stringify(i, null, 2) };
|
|
2134
|
+
}), s.set("get_cube_metadata", async () => {
|
|
2135
2135
|
const e = t.getMetadata();
|
|
2136
2136
|
return { result: JSON.stringify(e, null, 2) };
|
|
2137
|
-
}),
|
|
2137
|
+
}), s.set("execute_query", async (e) => {
|
|
2138
2138
|
try {
|
|
2139
|
-
|
|
2140
|
-
|
|
2139
|
+
const i = (c, u) => {
|
|
2140
|
+
if (!Array.isArray(c)) return;
|
|
2141
|
+
const m = c.filter((n) => typeof n == "string" && !n.includes("."));
|
|
2142
|
+
if (m.length > 0)
|
|
2143
|
+
throw new Error(
|
|
2144
|
+
`Invalid ${u}: ${m.map((n) => `"${n}"`).join(", ")}. All ${u} must use "CubeName.fieldName" format (e.g., "PullRequests.count", "Teams.name"). Use discover_cubes or get_cube_metadata to find valid field names.`
|
|
2145
|
+
);
|
|
2146
|
+
};
|
|
2147
|
+
i(e.measures, "measures"), i(e.dimensions, "dimensions");
|
|
2148
|
+
let r;
|
|
2149
|
+
e.funnel ? r = { funnel: e.funnel } : e.flow ? r = { flow: e.flow } : e.retention ? r = { retention: e.retention } : r = {
|
|
2141
2150
|
measures: e.measures,
|
|
2142
2151
|
dimensions: e.dimensions,
|
|
2143
2152
|
filters: e.filters,
|
|
@@ -2145,48 +2154,48 @@ function xe(o) {
|
|
|
2145
2154
|
order: e.order,
|
|
2146
2155
|
limit: e.limit
|
|
2147
2156
|
};
|
|
2148
|
-
const
|
|
2157
|
+
const l = await M(t, a, { query: r });
|
|
2149
2158
|
return {
|
|
2150
2159
|
result: JSON.stringify({
|
|
2151
|
-
rowCount:
|
|
2152
|
-
data:
|
|
2153
|
-
annotation:
|
|
2160
|
+
rowCount: l.data.length,
|
|
2161
|
+
data: l.data,
|
|
2162
|
+
annotation: l.annotation
|
|
2154
2163
|
}, null, 2)
|
|
2155
2164
|
};
|
|
2156
|
-
} catch (
|
|
2165
|
+
} catch (i) {
|
|
2157
2166
|
return {
|
|
2158
|
-
result: `Query execution failed: ${
|
|
2167
|
+
result: `Query execution failed: ${i instanceof Error ? i.message : "Unknown error"}`,
|
|
2159
2168
|
isError: !0
|
|
2160
2169
|
};
|
|
2161
2170
|
}
|
|
2162
|
-
}),
|
|
2171
|
+
}), s.set("add_portlet", async (e) => {
|
|
2163
2172
|
const r = {
|
|
2164
2173
|
number: "kpiNumber",
|
|
2165
2174
|
retention: "retentionHeatmap"
|
|
2166
2175
|
}[e.chartType] ?? e.chartType;
|
|
2167
|
-
let
|
|
2176
|
+
let l;
|
|
2168
2177
|
try {
|
|
2169
|
-
|
|
2178
|
+
l = JSON.parse(e.query);
|
|
2170
2179
|
} catch {
|
|
2171
2180
|
return {
|
|
2172
2181
|
result: "Invalid query: could not parse JSON string. Ensure `query` is a valid JSON string.",
|
|
2173
2182
|
isError: !0
|
|
2174
2183
|
};
|
|
2175
2184
|
}
|
|
2176
|
-
const
|
|
2177
|
-
if (!
|
|
2185
|
+
const c = t.validateQuery(l);
|
|
2186
|
+
if (!c.isValid)
|
|
2178
2187
|
return {
|
|
2179
2188
|
result: `Invalid query — fix these errors and retry:
|
|
2180
|
-
${
|
|
2189
|
+
${c.errors.join(`
|
|
2181
2190
|
`)}`,
|
|
2182
2191
|
isError: !0
|
|
2183
2192
|
};
|
|
2184
|
-
const
|
|
2185
|
-
let
|
|
2186
|
-
if (
|
|
2187
|
-
|
|
2193
|
+
const u = !!(l.funnel || l.flow || l.retention);
|
|
2194
|
+
let m;
|
|
2195
|
+
if (u)
|
|
2196
|
+
m = e.chartConfig ?? {};
|
|
2188
2197
|
else {
|
|
2189
|
-
const f = fe(r, e.chartConfig,
|
|
2198
|
+
const f = fe(r, e.chartConfig, l), b = he(r, f, l);
|
|
2190
2199
|
if (!b.isValid)
|
|
2191
2200
|
return {
|
|
2192
2201
|
result: `Chart config invalid — fix these errors and retry:
|
|
@@ -2194,52 +2203,52 @@ ${b.errors.join(`
|
|
|
2194
2203
|
`)}`,
|
|
2195
2204
|
isError: !0
|
|
2196
2205
|
};
|
|
2197
|
-
|
|
2206
|
+
m = f;
|
|
2198
2207
|
}
|
|
2199
|
-
const
|
|
2200
|
-
id:
|
|
2208
|
+
const n = `portlet-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, g = {
|
|
2209
|
+
id: n,
|
|
2201
2210
|
title: e.title,
|
|
2202
2211
|
query: e.query,
|
|
2203
2212
|
chartType: r,
|
|
2204
|
-
chartConfig:
|
|
2213
|
+
chartConfig: m,
|
|
2205
2214
|
displayConfig: e.displayConfig
|
|
2206
2215
|
};
|
|
2207
2216
|
return {
|
|
2208
|
-
result: `Portlet "${e.title}" added to notebook (id: ${
|
|
2217
|
+
result: `Portlet "${e.title}" added to notebook (id: ${n}, chart: ${r}). [Reminder: in your next response, start with a brief sentence about what you will do next BEFORE making any tool calls.]`,
|
|
2209
2218
|
sideEffect: { type: "add_portlet", data: g }
|
|
2210
2219
|
};
|
|
2211
|
-
}),
|
|
2212
|
-
const
|
|
2213
|
-
id:
|
|
2220
|
+
}), s.set("add_markdown", async (e) => {
|
|
2221
|
+
const i = `markdown-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, r = {
|
|
2222
|
+
id: i,
|
|
2214
2223
|
title: e.title,
|
|
2215
2224
|
content: e.content
|
|
2216
2225
|
};
|
|
2217
2226
|
return {
|
|
2218
|
-
result: `Markdown block added to notebook (id: ${
|
|
2227
|
+
result: `Markdown block added to notebook (id: ${i}). [Reminder: in your next response, start with a brief sentence about what you will do next BEFORE making any tool calls.]`,
|
|
2219
2228
|
sideEffect: { type: "add_markdown", data: r }
|
|
2220
2229
|
};
|
|
2221
|
-
}),
|
|
2230
|
+
}), s.set("save_as_dashboard", async (e) => {
|
|
2222
2231
|
try {
|
|
2223
|
-
const
|
|
2224
|
-
if (!
|
|
2232
|
+
const i = e.portlets;
|
|
2233
|
+
if (!i || i.length === 0)
|
|
2225
2234
|
return { result: "Dashboard must contain at least one portlet.", isError: !0 };
|
|
2226
2235
|
const r = [];
|
|
2227
|
-
for (const
|
|
2228
|
-
if (
|
|
2229
|
-
const f =
|
|
2236
|
+
for (const n of i) {
|
|
2237
|
+
if (n.chartType === "markdown") continue;
|
|
2238
|
+
const f = n.query;
|
|
2230
2239
|
if (!f) {
|
|
2231
|
-
r.push(`Portlet "${
|
|
2240
|
+
r.push(`Portlet "${n.title}": missing query`);
|
|
2232
2241
|
continue;
|
|
2233
2242
|
}
|
|
2234
2243
|
let b;
|
|
2235
2244
|
try {
|
|
2236
2245
|
b = JSON.parse(f);
|
|
2237
2246
|
} catch {
|
|
2238
|
-
r.push(`Portlet "${
|
|
2247
|
+
r.push(`Portlet "${n.title}": invalid JSON query`);
|
|
2239
2248
|
continue;
|
|
2240
2249
|
}
|
|
2241
2250
|
const w = t.validateQuery(b);
|
|
2242
|
-
w.isValid || r.push(`Portlet "${
|
|
2251
|
+
w.isValid || r.push(`Portlet "${n.title}": ${w.errors.join(", ")}`);
|
|
2243
2252
|
}
|
|
2244
2253
|
if (r.length > 0)
|
|
2245
2254
|
return {
|
|
@@ -2248,70 +2257,70 @@ ${r.join(`
|
|
|
2248
2257
|
`)}`,
|
|
2249
2258
|
isError: !0
|
|
2250
2259
|
};
|
|
2251
|
-
const
|
|
2252
|
-
portlets:
|
|
2253
|
-
const g =
|
|
2260
|
+
const l = {
|
|
2261
|
+
portlets: i.map((n) => {
|
|
2262
|
+
const g = n.chartType, f = g === "markdown", b = f ? "query" : n.analysisType || "query", w = b === "funnel" ? "funnel" : b === "flow" ? "flow" : b === "retention" ? "retention" : "query", C = n.query || "{}";
|
|
2254
2263
|
let h;
|
|
2255
2264
|
try {
|
|
2256
2265
|
h = JSON.parse(C);
|
|
2257
2266
|
} catch {
|
|
2258
2267
|
h = {};
|
|
2259
2268
|
}
|
|
2260
|
-
const
|
|
2269
|
+
const p = {
|
|
2261
2270
|
version: 1,
|
|
2262
2271
|
analysisType: w,
|
|
2263
2272
|
activeView: "chart",
|
|
2264
2273
|
charts: {
|
|
2265
2274
|
[w]: {
|
|
2266
2275
|
chartType: g,
|
|
2267
|
-
chartConfig:
|
|
2268
|
-
displayConfig:
|
|
2276
|
+
chartConfig: n.chartConfig || {},
|
|
2277
|
+
displayConfig: n.displayConfig || {}
|
|
2269
2278
|
}
|
|
2270
2279
|
},
|
|
2271
2280
|
query: f ? {} : h
|
|
2272
2281
|
};
|
|
2273
2282
|
return {
|
|
2274
|
-
id:
|
|
2275
|
-
title:
|
|
2276
|
-
analysisConfig:
|
|
2277
|
-
dashboardFilterMapping:
|
|
2278
|
-
w:
|
|
2279
|
-
h:
|
|
2280
|
-
x:
|
|
2281
|
-
y:
|
|
2283
|
+
id: n.id,
|
|
2284
|
+
title: n.title,
|
|
2285
|
+
analysisConfig: p,
|
|
2286
|
+
dashboardFilterMapping: n.dashboardFilterMapping,
|
|
2287
|
+
w: n.w,
|
|
2288
|
+
h: n.h,
|
|
2289
|
+
x: n.x,
|
|
2290
|
+
y: n.y
|
|
2282
2291
|
};
|
|
2283
2292
|
}),
|
|
2284
2293
|
filters: e.filters,
|
|
2285
2294
|
colorPalette: e.colorPalette
|
|
2286
|
-
},
|
|
2295
|
+
}, c = e.title, u = l.portlets.length, m = l.filters?.length || 0;
|
|
2287
2296
|
return {
|
|
2288
|
-
result: `Dashboard "${
|
|
2297
|
+
result: `Dashboard "${c}" created with ${u} portlets and ${m} filters.`,
|
|
2289
2298
|
sideEffect: {
|
|
2290
2299
|
type: "dashboard_saved",
|
|
2291
2300
|
data: {
|
|
2292
|
-
title:
|
|
2301
|
+
title: c,
|
|
2293
2302
|
description: e.description,
|
|
2294
|
-
dashboardConfig:
|
|
2303
|
+
dashboardConfig: l
|
|
2295
2304
|
}
|
|
2296
2305
|
}
|
|
2297
2306
|
};
|
|
2298
|
-
} catch (
|
|
2307
|
+
} catch (i) {
|
|
2299
2308
|
return {
|
|
2300
|
-
result: `Failed to save dashboard: ${
|
|
2309
|
+
result: `Failed to save dashboard: ${i instanceof Error ? i.message : "Unknown error"}`,
|
|
2301
2310
|
isError: !0
|
|
2302
2311
|
};
|
|
2303
2312
|
}
|
|
2304
|
-
}),
|
|
2313
|
+
}), s;
|
|
2305
2314
|
}
|
|
2306
2315
|
async function* Ce(o) {
|
|
2307
|
-
const { message: t, sessionId: a, history:
|
|
2308
|
-
let
|
|
2316
|
+
const { message: t, sessionId: a, history: s, semanticLayer: e, securityContext: i, agentConfig: r, apiKey: l } = o;
|
|
2317
|
+
let c;
|
|
2309
2318
|
try {
|
|
2310
|
-
const
|
|
2319
|
+
const p = await import(
|
|
2311
2320
|
/* webpackIgnore: true */
|
|
2312
2321
|
"@anthropic-ai/sdk"
|
|
2313
2322
|
);
|
|
2314
|
-
|
|
2323
|
+
c = p.default || p.Anthropic || p;
|
|
2315
2324
|
} catch {
|
|
2316
2325
|
yield {
|
|
2317
2326
|
type: "error",
|
|
@@ -2321,97 +2330,97 @@ async function* Ce(o) {
|
|
|
2321
2330
|
};
|
|
2322
2331
|
return;
|
|
2323
2332
|
}
|
|
2324
|
-
const
|
|
2325
|
-
if (
|
|
2326
|
-
for (const
|
|
2327
|
-
if (
|
|
2328
|
-
h.push({ role: "user", content:
|
|
2329
|
-
else if (
|
|
2333
|
+
const u = new c({ apiKey: l }), m = ge(), n = xe({ semanticLayer: e, securityContext: i }), g = e.getMetadata(), f = H(g), b = r.model || "claude-sonnet-4-6", w = r.maxTurns || 25, C = r.maxTokens || 4096, h = [];
|
|
2334
|
+
if (s && s.length > 0) {
|
|
2335
|
+
for (const p of s)
|
|
2336
|
+
if (p.role === "user")
|
|
2337
|
+
h.push({ role: "user", content: p.content });
|
|
2338
|
+
else if (p.role === "assistant") {
|
|
2330
2339
|
const x = [];
|
|
2331
|
-
if (
|
|
2332
|
-
for (const
|
|
2340
|
+
if (p.content && x.push({ type: "text", text: p.content }), p.toolCalls && p.toolCalls.length > 0) {
|
|
2341
|
+
for (const y of p.toolCalls)
|
|
2333
2342
|
x.push({
|
|
2334
2343
|
type: "tool_use",
|
|
2335
|
-
id:
|
|
2336
|
-
name:
|
|
2337
|
-
input:
|
|
2344
|
+
id: y.id,
|
|
2345
|
+
name: y.name,
|
|
2346
|
+
input: y.input || {}
|
|
2338
2347
|
});
|
|
2339
2348
|
h.push({ role: "assistant", content: x }), h.push({
|
|
2340
2349
|
role: "user",
|
|
2341
|
-
content:
|
|
2350
|
+
content: p.toolCalls.map((y) => ({
|
|
2342
2351
|
type: "tool_result",
|
|
2343
|
-
tool_use_id:
|
|
2344
|
-
content: typeof
|
|
2345
|
-
...
|
|
2352
|
+
tool_use_id: y.id,
|
|
2353
|
+
content: typeof y.result == "string" ? y.result : JSON.stringify(y.result ?? ""),
|
|
2354
|
+
...y.status === "error" ? { is_error: !0 } : {}
|
|
2346
2355
|
}))
|
|
2347
2356
|
});
|
|
2348
|
-
} else x.length > 0 && h.push({ role: "assistant", content:
|
|
2357
|
+
} else x.length > 0 && h.push({ role: "assistant", content: p.content });
|
|
2349
2358
|
}
|
|
2350
2359
|
}
|
|
2351
2360
|
h.push({ role: "user", content: t });
|
|
2352
2361
|
try {
|
|
2353
|
-
for (let
|
|
2354
|
-
const x = await
|
|
2362
|
+
for (let p = 0; p < w; p++) {
|
|
2363
|
+
const x = await u.messages.create({
|
|
2355
2364
|
model: b,
|
|
2356
2365
|
max_tokens: C,
|
|
2357
2366
|
system: f,
|
|
2358
|
-
tools:
|
|
2367
|
+
tools: m,
|
|
2359
2368
|
messages: h,
|
|
2360
2369
|
stream: !0
|
|
2361
|
-
}),
|
|
2362
|
-
let A = -1, D = "",
|
|
2370
|
+
}), y = [];
|
|
2371
|
+
let A = -1, D = "", q = "";
|
|
2363
2372
|
for await (const k of x)
|
|
2364
2373
|
switch (k.type) {
|
|
2365
2374
|
case "content_block_start": {
|
|
2366
2375
|
A++;
|
|
2367
|
-
const
|
|
2368
|
-
|
|
2376
|
+
const d = k.content_block;
|
|
2377
|
+
d.type === "tool_use" ? (y.push({ type: "tool_use", id: d.id, name: d.name, input: {} }), D = "", yield {
|
|
2369
2378
|
type: "tool_use_start",
|
|
2370
|
-
data: { id:
|
|
2371
|
-
}) :
|
|
2379
|
+
data: { id: d.id, name: d.name, input: void 0 }
|
|
2380
|
+
}) : d.type === "text" && y.push({ type: "text", text: "" });
|
|
2372
2381
|
break;
|
|
2373
2382
|
}
|
|
2374
2383
|
case "content_block_delta": {
|
|
2375
|
-
const
|
|
2376
|
-
if (
|
|
2377
|
-
const S =
|
|
2378
|
-
S && (S.text = (S.text || "") +
|
|
2379
|
-
} else
|
|
2384
|
+
const d = k.delta;
|
|
2385
|
+
if (d.type === "text_delta" && d.text) {
|
|
2386
|
+
const S = y[A];
|
|
2387
|
+
S && (S.text = (S.text || "") + d.text), yield { type: "text_delta", data: d.text };
|
|
2388
|
+
} else d.type === "input_json_delta" && d.partial_json && (D += d.partial_json);
|
|
2380
2389
|
break;
|
|
2381
2390
|
}
|
|
2382
2391
|
case "content_block_stop": {
|
|
2383
|
-
const
|
|
2384
|
-
if (
|
|
2392
|
+
const d = y[A];
|
|
2393
|
+
if (d?.type === "tool_use" && D) {
|
|
2385
2394
|
try {
|
|
2386
|
-
|
|
2395
|
+
d.input = JSON.parse(D);
|
|
2387
2396
|
} catch {
|
|
2388
|
-
|
|
2397
|
+
d.input = {};
|
|
2389
2398
|
}
|
|
2390
2399
|
D = "";
|
|
2391
2400
|
}
|
|
2392
2401
|
break;
|
|
2393
2402
|
}
|
|
2394
2403
|
case "message_delta": {
|
|
2395
|
-
const
|
|
2396
|
-
|
|
2404
|
+
const d = k.delta;
|
|
2405
|
+
d.stop_reason && (q = d.stop_reason);
|
|
2397
2406
|
break;
|
|
2398
2407
|
}
|
|
2399
2408
|
}
|
|
2400
|
-
if (h.push({ role: "assistant", content:
|
|
2409
|
+
if (h.push({ role: "assistant", content: y }), q !== "tool_use")
|
|
2401
2410
|
break;
|
|
2402
2411
|
const F = [];
|
|
2403
|
-
for (const k of
|
|
2412
|
+
for (const k of y) {
|
|
2404
2413
|
if (k.type !== "tool_use") continue;
|
|
2405
|
-
const
|
|
2414
|
+
const d = k.name, S = k.input || {}, T = k.id, I = n.get(d);
|
|
2406
2415
|
if (!I) {
|
|
2407
2416
|
F.push({
|
|
2408
2417
|
type: "tool_result",
|
|
2409
2418
|
tool_use_id: T,
|
|
2410
|
-
content: `Unknown tool: ${
|
|
2419
|
+
content: `Unknown tool: ${d}`,
|
|
2411
2420
|
is_error: !0
|
|
2412
2421
|
}), yield {
|
|
2413
2422
|
type: "tool_use_result",
|
|
2414
|
-
data: { id: T, name:
|
|
2423
|
+
data: { id: T, name: d, result: `Unknown tool: ${d}`, isError: !0 }
|
|
2415
2424
|
};
|
|
2416
2425
|
continue;
|
|
2417
2426
|
}
|
|
@@ -2424,7 +2433,7 @@ async function* Ce(o) {
|
|
|
2424
2433
|
...v.isError ? { is_error: !0 } : {}
|
|
2425
2434
|
}), yield {
|
|
2426
2435
|
type: "tool_use_result",
|
|
2427
|
-
data: { id: T, name:
|
|
2436
|
+
data: { id: T, name: d, result: v.result, ...v.isError ? { isError: !0 } : {} }
|
|
2428
2437
|
};
|
|
2429
2438
|
} catch (v) {
|
|
2430
2439
|
const O = v instanceof Error ? v.message : "Tool execution failed";
|
|
@@ -2435,7 +2444,7 @@ async function* Ce(o) {
|
|
|
2435
2444
|
is_error: !0
|
|
2436
2445
|
}), yield {
|
|
2437
2446
|
type: "tool_use_result",
|
|
2438
|
-
data: { id: T, name:
|
|
2447
|
+
data: { id: T, name: d, result: O, isError: !0 }
|
|
2439
2448
|
};
|
|
2440
2449
|
}
|
|
2441
2450
|
}
|
|
@@ -2445,11 +2454,11 @@ async function* Ce(o) {
|
|
|
2445
2454
|
type: "done",
|
|
2446
2455
|
data: { sessionId: a || "" }
|
|
2447
2456
|
};
|
|
2448
|
-
} catch (
|
|
2457
|
+
} catch (p) {
|
|
2449
2458
|
yield {
|
|
2450
2459
|
type: "error",
|
|
2451
2460
|
data: {
|
|
2452
|
-
message: we(
|
|
2461
|
+
message: we(p)
|
|
2453
2462
|
}
|
|
2454
2463
|
};
|
|
2455
2464
|
}
|
|
@@ -2463,17 +2472,17 @@ function we(o) {
|
|
|
2463
2472
|
api_error: "The AI service encountered an error. Please try again.",
|
|
2464
2473
|
authentication_error: "Authentication failed. Please check your API key configuration.",
|
|
2465
2474
|
invalid_request_error: "There was a problem with the request. Please try again."
|
|
2466
|
-
},
|
|
2467
|
-
if (
|
|
2468
|
-
const e =
|
|
2475
|
+
}, s = o;
|
|
2476
|
+
if (s.status || s.type) {
|
|
2477
|
+
const e = s.error?.type || s.type || "";
|
|
2469
2478
|
if (a[e])
|
|
2470
2479
|
return a[e];
|
|
2471
2480
|
}
|
|
2472
2481
|
if (t.startsWith("{") || t.startsWith("Error: {")) {
|
|
2473
2482
|
try {
|
|
2474
|
-
const e = JSON.parse(t.replace(/^Error:\s*/, "")),
|
|
2475
|
-
if (a[
|
|
2476
|
-
return a[
|
|
2483
|
+
const e = JSON.parse(t.replace(/^Error:\s*/, "")), i = e.error?.type || e.type || "";
|
|
2484
|
+
if (a[i])
|
|
2485
|
+
return a[i];
|
|
2477
2486
|
} catch {
|
|
2478
2487
|
}
|
|
2479
2488
|
return "The AI service encountered an error. Please try again.";
|