drizzle-cube 0.4.4 → 0.4.7
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 +8 -4
- package/dist/adapters/express/index.d.ts +7 -0
- package/dist/adapters/express/index.js +189 -139
- package/dist/adapters/fastify/index.cjs +8 -4
- package/dist/adapters/fastify/index.d.ts +7 -0
- package/dist/adapters/fastify/index.js +209 -150
- package/dist/adapters/handler-D6l8AbJV.cjs +7 -0
- package/dist/adapters/handler-DsNgnIPK.js +458 -0
- package/dist/adapters/hono/index.cjs +8 -4
- package/dist/adapters/hono/index.d.ts +7 -0
- package/dist/adapters/hono/index.js +202 -144
- package/dist/adapters/{mcp-transport-BqLo4hKi.cjs → mcp-transport-BB998cy5.cjs} +21 -21
- package/dist/adapters/{mcp-transport-YHDZWKOi.js → mcp-transport-DFTCWene.js} +4 -0
- package/dist/adapters/nextjs/index.cjs +7 -3
- package/dist/adapters/nextjs/index.d.ts +14 -0
- package/dist/adapters/nextjs/index.js +220 -144
- package/dist/client/charts.js +13 -13
- package/dist/client/chunks/{RetentionCombinedChart-BK8N-MOQ.js → RetentionCombinedChart-CEI8KQ3t.js} +2 -2
- package/dist/client/chunks/{RetentionCombinedChart-BK8N-MOQ.js.map → RetentionCombinedChart-CEI8KQ3t.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-CNBmAGAO.js → analysis-builder-Dn8xpgPQ.js} +6 -6
- package/dist/client/chunks/{analysis-builder-CNBmAGAO.js.map → analysis-builder-Dn8xpgPQ.js.map} +1 -1
- package/dist/client/chunks/{analysis-builder-shared-INGGwyTG.js → analysis-builder-shared-D3xYzXlh.js} +2 -2
- package/dist/client/chunks/{analysis-builder-shared-INGGwyTG.js.map → analysis-builder-shared-D3xYzXlh.js.map} +1 -1
- package/dist/client/chunks/{chart-activity-grid-DvgTYQaE.js → chart-activity-grid-DStNr34n.js} +2 -2
- package/dist/client/chunks/{chart-activity-grid-DvgTYQaE.js.map → chart-activity-grid-DStNr34n.js.map} +1 -1
- package/dist/client/chunks/{chart-area-BKjd_STS.js → chart-area-QKKboTbq.js} +3 -3
- package/dist/client/chunks/{chart-area-BKjd_STS.js.map → chart-area-QKKboTbq.js.map} +1 -1
- package/dist/client/chunks/{chart-bar-DBI41w05.js → chart-bar-HpXF42H1.js} +2 -2
- package/dist/client/chunks/{chart-bar-DBI41w05.js.map → chart-bar-HpXF42H1.js.map} +1 -1
- package/dist/client/chunks/{chart-bubble-BD-1kneU.js → chart-bubble-Bf42A1-B.js} +2 -2
- package/dist/client/chunks/{chart-bubble-BD-1kneU.js.map → chart-bubble-Bf42A1-B.js.map} +1 -1
- package/dist/client/chunks/{chart-config-markdown-6fsr-U6_.js → chart-config-markdown-BXKL5TbQ.js} +8 -1
- package/dist/client/chunks/{chart-config-markdown-6fsr-U6_.js.map → chart-config-markdown-BXKL5TbQ.js.map} +1 -1
- package/dist/client/chunks/{chart-data-table-B74HLpAx.js → chart-data-table-Ch_1c1Zo.js} +2 -2
- package/dist/client/chunks/{chart-data-table-B74HLpAx.js.map → chart-data-table-Ch_1c1Zo.js.map} +1 -1
- package/dist/client/chunks/{chart-funnel-DQ9cW6j9.js → chart-funnel-C9kenCpp.js} +2 -2
- package/dist/client/chunks/{chart-funnel-DQ9cW6j9.js.map → chart-funnel-C9kenCpp.js.map} +1 -1
- package/dist/client/chunks/{chart-heat-map-CpIr4tbs.js → chart-heat-map-CYGemyPB.js} +2 -2
- package/dist/client/chunks/{chart-heat-map-CpIr4tbs.js.map → chart-heat-map-CYGemyPB.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-delta-DPcSazD3.js → chart-kpi-delta-CWCmi8vL.js} +3 -3
- package/dist/client/chunks/{chart-kpi-delta-DPcSazD3.js.map → chart-kpi-delta-CWCmi8vL.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-number-D62PzKZ1.js → chart-kpi-number-C-5m3qt5.js} +2 -2
- package/dist/client/chunks/{chart-kpi-number-D62PzKZ1.js.map → chart-kpi-number-C-5m3qt5.js.map} +1 -1
- package/dist/client/chunks/{chart-kpi-text-B6Z5tFV1.js → chart-kpi-text--t4ibPmx.js} +3 -3
- package/dist/client/chunks/{chart-kpi-text-B6Z5tFV1.js.map → chart-kpi-text--t4ibPmx.js.map} +1 -1
- package/dist/client/chunks/{chart-line-Ds4BYA0K.js → chart-line-C7YcMWBw.js} +3 -3
- package/dist/client/chunks/{chart-line-Ds4BYA0K.js.map → chart-line-C7YcMWBw.js.map} +1 -1
- package/dist/client/chunks/chart-markdown-Du4Z2iqK.js +2695 -0
- package/dist/client/chunks/chart-markdown-Du4Z2iqK.js.map +1 -0
- package/dist/client/chunks/{chart-pie-BBrLh0iU.js → chart-pie-C4SuxKSN.js} +2 -2
- package/dist/client/chunks/{chart-pie-BBrLh0iU.js.map → chart-pie-C4SuxKSN.js.map} +1 -1
- package/dist/client/chunks/{chart-radar-vr5FgjHT.js → chart-radar-BW3Z_-Ly.js} +2 -2
- package/dist/client/chunks/{chart-radar-vr5FgjHT.js.map → chart-radar-BW3Z_-Ly.js.map} +1 -1
- package/dist/client/chunks/{chart-radial-bar-BV_3Nm5P.js → chart-radial-bar-0Fa3aeP5.js} +2 -2
- package/dist/client/chunks/{chart-radial-bar-BV_3Nm5P.js.map → chart-radial-bar-0Fa3aeP5.js.map} +1 -1
- package/dist/client/chunks/{chart-sankey-CHROzr4S.js → chart-sankey-DBghfbg1.js} +2 -2
- package/dist/client/chunks/{chart-sankey-CHROzr4S.js.map → chart-sankey-DBghfbg1.js.map} +1 -1
- package/dist/client/chunks/{chart-scatter-DbRTU3FG.js → chart-scatter-DOVu1TNq.js} +2 -2
- package/dist/client/chunks/{chart-scatter-DbRTU3FG.js.map → chart-scatter-DOVu1TNq.js.map} +1 -1
- package/dist/client/chunks/{chart-sunburst-B-aPUzYL.js → chart-sunburst-LfNthFlZ.js} +2 -2
- package/dist/client/chunks/{chart-sunburst-B-aPUzYL.js.map → chart-sunburst-LfNthFlZ.js.map} +1 -1
- package/dist/client/chunks/{chart-tree-map-qY148fiC.js → chart-tree-map-DZtQPyWX.js} +2 -2
- package/dist/client/chunks/{chart-tree-map-qY148fiC.js.map → chart-tree-map-DZtQPyWX.js.map} +1 -1
- package/dist/client/chunks/{chartConfigRegistry-Di34paQH.js → chartConfigRegistry-C5dZm-ZK.js} +2 -2
- package/dist/client/chunks/{chartConfigRegistry-Di34paQH.js.map → chartConfigRegistry-C5dZm-ZK.js.map} +1 -1
- package/dist/client/chunks/{charts-core-T8UglYyq.js → charts-core-DmGfleFz.js} +199 -187
- package/dist/client/chunks/{charts-core-T8UglYyq.js.map → charts-core-DmGfleFz.js.map} +1 -1
- package/dist/client/chunks/{charts-loader-YnhJHubD.js → charts-loader-DcFWOUeV.js} +21 -21
- package/dist/client/chunks/{charts-loader-YnhJHubD.js.map → charts-loader-DcFWOUeV.js.map} +1 -1
- package/dist/client/chunks/{components-D0i1yQsk.js → components-Bdt1AmzS.js} +3521 -3369
- package/dist/client/chunks/components-Bdt1AmzS.js.map +1 -0
- package/dist/client/components/AgenticNotebook/AgentChatPanel.d.ts +8 -0
- package/dist/client/components/AgenticNotebook/ChatInput.d.ts +14 -0
- package/dist/client/components/AgenticNotebook/ChatMessage.d.ts +7 -0
- package/dist/client/components/AgenticNotebook/NotebookCanvas.d.ts +3 -0
- package/dist/client/components/AgenticNotebook/NotebookMarkdownBlock.d.ts +12 -0
- package/dist/client/components/AgenticNotebook/NotebookPortletBlock.d.ts +12 -0
- package/dist/client/components/AgenticNotebook/index.d.ts +34 -0
- package/dist/client/components/DashboardPortletCard.d.ts +3 -2
- package/dist/client/components.js +1 -1
- package/dist/client/hooks/dashboard/layoutUtils.d.ts +7 -0
- package/dist/client/hooks/dashboard/useDashboardController.d.ts +53 -0
- package/dist/client/hooks/dashboard/useGridLayoutEngine.d.ts +10 -0
- package/dist/client/hooks/dashboard/useRowLayoutEngine.d.ts +18 -0
- package/dist/client/hooks/useAgentChat.d.ts +36 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +923 -187
- package/dist/client/index.js.map +1 -1
- package/dist/client/stores/notebookStore.d.ts +152 -0
- package/dist/client/styles.css +1 -1
- package/dist/client/utils.js +4 -4
- package/dist/client-bundle-stats.html +1 -1
- package/dist/server/index.cjs +101 -91
- package/dist/server/index.d.ts +155 -0
- package/dist/server/index.js +4423 -3609
- package/package.json +7 -1
- package/dist/client/chunks/chart-markdown-Rq6ORisB.js +0 -276
- package/dist/client/chunks/chart-markdown-Rq6ORisB.js.map +0 -1
- package/dist/client/chunks/components-D0i1yQsk.js.map +0 -1
|
@@ -1,57 +1,58 @@
|
|
|
1
|
-
import { S as D, v as
|
|
2
|
-
import { formatErrorResponse as
|
|
3
|
-
const N = function(
|
|
1
|
+
import { S as D, v as K, b as x, a as T, n as V, p as z, w as _, d as B, i as j, M as F, c as U, e as E, s as P } from "../mcp-transport-DFTCWene.js";
|
|
2
|
+
import { formatErrorResponse as d, formatCubeResponse as A, handleBatchRequest as X, formatMetaResponse as G, formatSqlResponse as I, handleDryRun as M } from "../utils.js";
|
|
3
|
+
const N = function(i, k, R) {
|
|
4
4
|
const {
|
|
5
|
-
cubes:
|
|
6
|
-
drizzle:
|
|
7
|
-
schema:
|
|
8
|
-
extractSecurityContext:
|
|
5
|
+
cubes: S,
|
|
6
|
+
drizzle: O,
|
|
7
|
+
schema: J,
|
|
8
|
+
extractSecurityContext: p,
|
|
9
9
|
engineType: L,
|
|
10
|
-
cors:
|
|
11
|
-
basePath:
|
|
12
|
-
bodyLimit:
|
|
10
|
+
cors: q,
|
|
11
|
+
basePath: m = "/cubejs-api/v1",
|
|
12
|
+
bodyLimit: g = 10485760,
|
|
13
13
|
// 10MB
|
|
14
|
-
cache:
|
|
15
|
-
mcp:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
cache: H,
|
|
15
|
+
mcp: b = { enabled: !0 },
|
|
16
|
+
agent: f
|
|
17
|
+
} = k;
|
|
18
|
+
if (!S || S.length === 0)
|
|
19
|
+
return R(new Error("At least one cube must be provided in the cubes array"));
|
|
20
|
+
q && i.register(import("@fastify/cors"), q), i.addHook("onRequest", async (t, r) => {
|
|
21
|
+
t.method === "POST" && (t.body = void 0);
|
|
21
22
|
});
|
|
22
23
|
const c = new D({
|
|
23
|
-
drizzle:
|
|
24
|
-
schema:
|
|
24
|
+
drizzle: O,
|
|
25
|
+
schema: J,
|
|
25
26
|
engineType: L,
|
|
26
|
-
cache:
|
|
27
|
+
cache: H
|
|
27
28
|
});
|
|
28
|
-
if (
|
|
29
|
-
c.registerCube(
|
|
30
|
-
}),
|
|
31
|
-
bodyLimit:
|
|
29
|
+
if (S.forEach((t) => {
|
|
30
|
+
c.registerCube(t);
|
|
31
|
+
}), i.post(`${m}/load`, {
|
|
32
|
+
bodyLimit: g,
|
|
32
33
|
schema: {
|
|
33
34
|
body: {
|
|
34
35
|
type: "object",
|
|
35
36
|
additionalProperties: !0
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
|
-
}, async (
|
|
39
|
+
}, async (t, r) => {
|
|
39
40
|
try {
|
|
40
|
-
const e =
|
|
41
|
+
const e = t.body, a = e.query || e, n = await p(t), o = c.validateQuery(a);
|
|
41
42
|
if (!o.isValid)
|
|
42
|
-
return
|
|
43
|
+
return r.status(400).send(d(
|
|
43
44
|
`Query validation failed: ${o.errors.join(", ")}`,
|
|
44
45
|
400
|
|
45
46
|
));
|
|
46
|
-
const
|
|
47
|
-
return
|
|
47
|
+
const s = t.headers["x-cache-control"] === "no-cache", l = await c.executeMultiCubeQuery(a, n, { skipCache: s });
|
|
48
|
+
return A(a, l, c);
|
|
48
49
|
} catch (e) {
|
|
49
|
-
return
|
|
50
|
+
return t.log.error(e, "Query execution error"), r.status(500).send(d(
|
|
50
51
|
e instanceof Error ? e.message : "Query execution failed",
|
|
51
52
|
500
|
|
52
53
|
));
|
|
53
54
|
}
|
|
54
|
-
}),
|
|
55
|
+
}), i.get(`${m}/load`, {
|
|
55
56
|
schema: {
|
|
56
57
|
querystring: {
|
|
57
58
|
type: "object",
|
|
@@ -61,34 +62,34 @@ const N = function(n, O, E) {
|
|
|
61
62
|
required: ["query"]
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
|
-
}, async (
|
|
65
|
+
}, async (t, r) => {
|
|
65
66
|
try {
|
|
66
|
-
const { query: e } =
|
|
67
|
+
const { query: e } = t.query;
|
|
67
68
|
let a;
|
|
68
69
|
try {
|
|
69
70
|
a = JSON.parse(e);
|
|
70
71
|
} catch {
|
|
71
|
-
return
|
|
72
|
+
return r.status(400).send(d(
|
|
72
73
|
"Invalid JSON in query parameter",
|
|
73
74
|
400
|
|
74
75
|
));
|
|
75
76
|
}
|
|
76
|
-
const
|
|
77
|
+
const n = await p(t), o = c.validateQuery(a);
|
|
77
78
|
if (!o.isValid)
|
|
78
|
-
return
|
|
79
|
+
return r.status(400).send(d(
|
|
79
80
|
`Query validation failed: ${o.errors.join(", ")}`,
|
|
80
81
|
400
|
|
81
82
|
));
|
|
82
|
-
const
|
|
83
|
-
return
|
|
83
|
+
const s = t.headers["x-cache-control"] === "no-cache", l = await c.executeMultiCubeQuery(a, n, { skipCache: s });
|
|
84
|
+
return A(a, l, c);
|
|
84
85
|
} catch (e) {
|
|
85
|
-
return
|
|
86
|
+
return t.log.error(e, "Query execution error"), r.status(500).send(d(
|
|
86
87
|
e instanceof Error ? e.message : "Query execution failed",
|
|
87
88
|
500
|
|
88
89
|
));
|
|
89
90
|
}
|
|
90
|
-
}),
|
|
91
|
-
bodyLimit:
|
|
91
|
+
}), i.post(`${m}/batch`, {
|
|
92
|
+
bodyLimit: g,
|
|
92
93
|
schema: {
|
|
93
94
|
body: {
|
|
94
95
|
type: "object",
|
|
@@ -101,68 +102,68 @@ const N = function(n, O, E) {
|
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
}
|
|
104
|
-
}, async (
|
|
105
|
+
}, async (t, r) => {
|
|
105
106
|
try {
|
|
106
|
-
const { queries: e } =
|
|
107
|
+
const { queries: e } = t.body;
|
|
107
108
|
if (!e || !Array.isArray(e))
|
|
108
|
-
return
|
|
109
|
+
return r.status(400).send(d(
|
|
109
110
|
'Request body must contain a "queries" array',
|
|
110
111
|
400
|
|
111
112
|
));
|
|
112
113
|
if (e.length === 0)
|
|
113
|
-
return
|
|
114
|
+
return r.status(400).send(d(
|
|
114
115
|
"Queries array cannot be empty",
|
|
115
116
|
400
|
|
116
117
|
));
|
|
117
|
-
const a = await
|
|
118
|
-
return await
|
|
118
|
+
const a = await p(t), n = t.headers["x-cache-control"] === "no-cache";
|
|
119
|
+
return await X(e, a, c, { skipCache: n });
|
|
119
120
|
} catch (e) {
|
|
120
|
-
return
|
|
121
|
+
return t.log.error(e, "Batch execution error"), r.status(500).send(d(
|
|
121
122
|
e instanceof Error ? e.message : "Batch execution failed",
|
|
122
123
|
500
|
|
123
124
|
));
|
|
124
125
|
}
|
|
125
|
-
}),
|
|
126
|
+
}), i.get(`${m}/meta`, async (t, r) => {
|
|
126
127
|
try {
|
|
127
128
|
const e = c.getMetadata();
|
|
128
|
-
return
|
|
129
|
+
return G(e);
|
|
129
130
|
} catch (e) {
|
|
130
|
-
return
|
|
131
|
+
return t.log.error(e, "Metadata error"), r.status(500).send(d(
|
|
131
132
|
e instanceof Error ? e.message : "Failed to fetch metadata",
|
|
132
133
|
500
|
|
133
134
|
));
|
|
134
135
|
}
|
|
135
|
-
}),
|
|
136
|
-
bodyLimit:
|
|
136
|
+
}), i.post(`${m}/sql`, {
|
|
137
|
+
bodyLimit: g,
|
|
137
138
|
schema: {
|
|
138
139
|
body: {
|
|
139
140
|
type: "object",
|
|
140
141
|
additionalProperties: !0
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
|
-
}, async (
|
|
144
|
+
}, async (t, r) => {
|
|
144
145
|
try {
|
|
145
|
-
const e =
|
|
146
|
-
if (!
|
|
147
|
-
return
|
|
148
|
-
`Query validation failed: ${
|
|
146
|
+
const e = t.body, a = await p(t), n = c.validateQuery(e);
|
|
147
|
+
if (!n.isValid)
|
|
148
|
+
return r.status(400).send(d(
|
|
149
|
+
`Query validation failed: ${n.errors.join(", ")}`,
|
|
149
150
|
400
|
|
150
151
|
));
|
|
151
152
|
const o = e.measures?.[0] || e.dimensions?.[0];
|
|
152
153
|
if (!o)
|
|
153
|
-
return
|
|
154
|
+
return r.status(400).send(d(
|
|
154
155
|
"No measures or dimensions specified",
|
|
155
156
|
400
|
|
156
157
|
));
|
|
157
|
-
const
|
|
158
|
-
return
|
|
158
|
+
const s = o.split(".")[0], l = await c.generateSQL(s, e, a);
|
|
159
|
+
return I(e, l);
|
|
159
160
|
} catch (e) {
|
|
160
|
-
return
|
|
161
|
+
return t.log.error(e, "SQL generation error"), r.status(500).send(d(
|
|
161
162
|
e instanceof Error ? e.message : "SQL generation failed",
|
|
162
163
|
500
|
|
163
164
|
));
|
|
164
165
|
}
|
|
165
|
-
}),
|
|
166
|
+
}), i.get(`${m}/sql`, {
|
|
166
167
|
schema: {
|
|
167
168
|
querystring: {
|
|
168
169
|
type: "object",
|
|
@@ -172,47 +173,47 @@ const N = function(n, O, E) {
|
|
|
172
173
|
required: ["query"]
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
|
-
}, async (
|
|
176
|
+
}, async (t, r) => {
|
|
176
177
|
try {
|
|
177
|
-
const { query: e } =
|
|
178
|
+
const { query: e } = t.query, a = JSON.parse(e), n = await p(t), o = c.validateQuery(a);
|
|
178
179
|
if (!o.isValid)
|
|
179
|
-
return
|
|
180
|
+
return r.status(400).send(d(
|
|
180
181
|
`Query validation failed: ${o.errors.join(", ")}`,
|
|
181
182
|
400
|
|
182
183
|
));
|
|
183
|
-
const
|
|
184
|
-
if (!
|
|
185
|
-
return
|
|
184
|
+
const s = a.measures?.[0] || a.dimensions?.[0];
|
|
185
|
+
if (!s)
|
|
186
|
+
return r.status(400).send(d(
|
|
186
187
|
"No measures or dimensions specified",
|
|
187
188
|
400
|
|
188
189
|
));
|
|
189
|
-
const
|
|
190
|
-
return
|
|
190
|
+
const l = s.split(".")[0], y = await c.generateSQL(l, a, n);
|
|
191
|
+
return I(a, y);
|
|
191
192
|
} catch (e) {
|
|
192
|
-
return
|
|
193
|
+
return t.log.error(e, "SQL generation error"), r.status(500).send(d(
|
|
193
194
|
e instanceof Error ? e.message : "SQL generation failed",
|
|
194
195
|
500
|
|
195
196
|
));
|
|
196
197
|
}
|
|
197
|
-
}),
|
|
198
|
-
bodyLimit:
|
|
198
|
+
}), i.post(`${m}/dry-run`, {
|
|
199
|
+
bodyLimit: g,
|
|
199
200
|
schema: {
|
|
200
201
|
body: {
|
|
201
202
|
type: "object",
|
|
202
203
|
additionalProperties: !0
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
|
-
}, async (
|
|
206
|
+
}, async (t, r) => {
|
|
206
207
|
try {
|
|
207
|
-
const e =
|
|
208
|
-
return await
|
|
208
|
+
const e = t.body, a = e.query || e, n = await p(t);
|
|
209
|
+
return await M(a, n, c);
|
|
209
210
|
} catch (e) {
|
|
210
|
-
return
|
|
211
|
+
return t.log.error(e, "Dry-run error"), r.status(400).send({
|
|
211
212
|
error: e instanceof Error ? e.message : "Dry-run validation failed",
|
|
212
213
|
valid: !1
|
|
213
214
|
});
|
|
214
215
|
}
|
|
215
|
-
}),
|
|
216
|
+
}), i.get(`${m}/dry-run`, {
|
|
216
217
|
schema: {
|
|
217
218
|
querystring: {
|
|
218
219
|
type: "object",
|
|
@@ -222,142 +223,200 @@ const N = function(n, O, E) {
|
|
|
222
223
|
required: ["query"]
|
|
223
224
|
}
|
|
224
225
|
}
|
|
225
|
-
}, async (
|
|
226
|
+
}, async (t, r) => {
|
|
226
227
|
try {
|
|
227
|
-
const { query: e } =
|
|
228
|
-
return await
|
|
228
|
+
const { query: e } = t.query, a = JSON.parse(e), n = await p(t);
|
|
229
|
+
return await M(a, n, c);
|
|
229
230
|
} catch (e) {
|
|
230
|
-
return
|
|
231
|
+
return t.log.error(e, "Dry-run error"), r.status(400).send({
|
|
231
232
|
error: e instanceof Error ? e.message : "Dry-run validation failed",
|
|
232
233
|
valid: !1
|
|
233
234
|
});
|
|
234
235
|
}
|
|
235
|
-
}),
|
|
236
|
-
bodyLimit:
|
|
236
|
+
}), i.post(`${m}/explain`, {
|
|
237
|
+
bodyLimit: g,
|
|
237
238
|
schema: {
|
|
238
239
|
body: {
|
|
239
240
|
type: "object",
|
|
240
241
|
additionalProperties: !0
|
|
241
242
|
}
|
|
242
243
|
}
|
|
243
|
-
}, async (
|
|
244
|
+
}, async (t, r) => {
|
|
244
245
|
try {
|
|
245
|
-
const e =
|
|
246
|
-
return
|
|
247
|
-
error: `Query validation failed: ${
|
|
246
|
+
const e = t.body, a = e.query || e, n = e.options || {}, o = await p(t), s = c.validateQuery(a);
|
|
247
|
+
return s.isValid ? await c.explainQuery(a, o, n) : r.status(400).send({
|
|
248
|
+
error: `Query validation failed: ${s.errors.join(", ")}`
|
|
248
249
|
});
|
|
249
250
|
} catch (e) {
|
|
250
|
-
return
|
|
251
|
+
return t.log.error(e, "Explain error"), r.status(500).send({
|
|
251
252
|
error: e instanceof Error ? e.message : "Explain query failed"
|
|
252
253
|
});
|
|
253
254
|
}
|
|
254
|
-
}),
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
255
|
+
}), f && i.post(`${m}/agent/chat`, {
|
|
256
|
+
bodyLimit: g,
|
|
257
|
+
schema: {
|
|
258
|
+
body: {
|
|
259
|
+
type: "object",
|
|
260
|
+
additionalProperties: !0
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}, async (t, r) => {
|
|
264
|
+
try {
|
|
265
|
+
const { handleAgentChat: e } = await import("../handler-DsNgnIPK.js"), a = t.body, { message: n, sessionId: o } = a;
|
|
266
|
+
if (!n || typeof n != "string")
|
|
267
|
+
return r.status(400).send({ error: "message is required and must be a string" });
|
|
268
|
+
let s = (f.apiKey || "").trim();
|
|
269
|
+
if (f.allowClientApiKey) {
|
|
270
|
+
const y = t.headers["x-agent-api-key"];
|
|
271
|
+
y && (s = y.trim());
|
|
272
|
+
}
|
|
273
|
+
if (!s)
|
|
274
|
+
return r.status(401).send({
|
|
275
|
+
error: "No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header."
|
|
276
|
+
});
|
|
277
|
+
const l = await p(t);
|
|
278
|
+
r.raw.writeHead(200, {
|
|
279
|
+
"Content-Type": "text/event-stream",
|
|
280
|
+
"Cache-Control": "no-cache",
|
|
281
|
+
Connection: "keep-alive"
|
|
282
|
+
});
|
|
283
|
+
try {
|
|
284
|
+
const y = e({
|
|
285
|
+
message: n,
|
|
286
|
+
sessionId: o,
|
|
287
|
+
semanticLayer: c,
|
|
288
|
+
securityContext: l,
|
|
289
|
+
agentConfig: f,
|
|
290
|
+
apiKey: s
|
|
291
|
+
});
|
|
292
|
+
for await (const u of y)
|
|
293
|
+
r.raw.write(`data: ${JSON.stringify(u)}
|
|
294
|
+
|
|
295
|
+
`);
|
|
296
|
+
} catch (y) {
|
|
297
|
+
const u = {
|
|
298
|
+
type: "error",
|
|
299
|
+
data: { message: y instanceof Error ? y.message : "Stream failed" }
|
|
300
|
+
};
|
|
301
|
+
r.raw.write(`data: ${JSON.stringify(u)}
|
|
302
|
+
|
|
303
|
+
`);
|
|
304
|
+
} finally {
|
|
305
|
+
r.raw.end();
|
|
306
|
+
}
|
|
307
|
+
} catch (e) {
|
|
308
|
+
if (t.log.error(e, "Agent chat error"), !r.raw.headersSent)
|
|
309
|
+
return r.status(500).send({
|
|
310
|
+
error: e instanceof Error ? e.message : "Agent chat failed"
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}), b.enabled !== !1) {
|
|
314
|
+
const t = b.basePath ?? "/mcp";
|
|
315
|
+
i.post(`${t}`, {
|
|
316
|
+
bodyLimit: g,
|
|
258
317
|
schema: {
|
|
259
318
|
body: {
|
|
260
319
|
type: "object",
|
|
261
320
|
additionalProperties: !0
|
|
262
321
|
}
|
|
263
322
|
}
|
|
264
|
-
}, async (
|
|
265
|
-
const a =
|
|
266
|
-
|
|
267
|
-
|
|
323
|
+
}, async (r, e) => {
|
|
324
|
+
const a = K(
|
|
325
|
+
r.headers.origin,
|
|
326
|
+
b.allowedOrigins ? { allowedOrigins: b.allowedOrigins } : {}
|
|
268
327
|
);
|
|
269
328
|
if (!a.valid)
|
|
270
|
-
return e.status(403).send(
|
|
271
|
-
const
|
|
272
|
-
if (!
|
|
273
|
-
return e.status(400).send(
|
|
274
|
-
const o =
|
|
329
|
+
return e.status(403).send(x(null, -32600, a.reason));
|
|
330
|
+
const n = r.headers.accept;
|
|
331
|
+
if (!T(n))
|
|
332
|
+
return e.status(400).send(x(null, -32600, "Accept header must include both application/json and text/event-stream"));
|
|
333
|
+
const o = V(r.headers);
|
|
275
334
|
if (!o.ok)
|
|
276
335
|
return e.status(426).send({
|
|
277
336
|
error: "Unsupported MCP protocol version",
|
|
278
337
|
supported: o.supported
|
|
279
338
|
});
|
|
280
|
-
const
|
|
281
|
-
if (!
|
|
282
|
-
return e.status(400).send(
|
|
283
|
-
const
|
|
339
|
+
const s = z(r.body);
|
|
340
|
+
if (!s)
|
|
341
|
+
return e.status(400).send(x(null, -32600, "Invalid JSON-RPC 2.0 request"));
|
|
342
|
+
const l = _(n), y = s.method === "initialize";
|
|
284
343
|
try {
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
344
|
+
const u = await B(
|
|
345
|
+
s.method,
|
|
346
|
+
s.params,
|
|
288
347
|
{
|
|
289
348
|
semanticLayer: c,
|
|
290
|
-
extractSecurityContext:
|
|
291
|
-
rawRequest:
|
|
349
|
+
extractSecurityContext: p,
|
|
350
|
+
rawRequest: r,
|
|
292
351
|
rawResponse: e,
|
|
293
352
|
negotiatedProtocol: o.negotiated
|
|
294
353
|
}
|
|
295
354
|
);
|
|
296
|
-
if (
|
|
355
|
+
if (j(s))
|
|
297
356
|
return e.status(202).send();
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
const
|
|
301
|
-
if (
|
|
302
|
-
const
|
|
303
|
-
e.header("Content-Type", "text/event-stream").header("Cache-Control", "no-cache").header("Connection", "keep-alive").send(`id: ${
|
|
357
|
+
const v = y && u && typeof u == "object" && "sessionId" in u ? u.sessionId : void 0;
|
|
358
|
+
v && e.header(F, v);
|
|
359
|
+
const C = U(s.id ?? null, u);
|
|
360
|
+
if (l) {
|
|
361
|
+
const w = E();
|
|
362
|
+
e.header("Content-Type", "text/event-stream").header("Cache-Control", "no-cache").header("Connection", "keep-alive").send(`id: ${w}
|
|
304
363
|
|
|
305
|
-
${
|
|
364
|
+
${P(C, w)}`);
|
|
306
365
|
return;
|
|
307
366
|
}
|
|
308
|
-
return e.send(
|
|
309
|
-
} catch (
|
|
310
|
-
if (
|
|
311
|
-
return
|
|
312
|
-
|
|
313
|
-
const
|
|
314
|
-
if (
|
|
315
|
-
const
|
|
316
|
-
e.header("Content-Type", "text/event-stream").header("Cache-Control", "no-cache").header("Connection", "keep-alive").send(`id: ${
|
|
367
|
+
return e.send(C);
|
|
368
|
+
} catch (u) {
|
|
369
|
+
if (j(s))
|
|
370
|
+
return r.log.error(u, "MCP notification processing error"), e.status(202).send();
|
|
371
|
+
r.log.error(u, "MCP RPC error");
|
|
372
|
+
const v = u?.code ?? -32603, C = u?.data, w = u.message || "MCP request failed", Q = x(s.id ?? null, v, w, C);
|
|
373
|
+
if (l) {
|
|
374
|
+
const $ = E();
|
|
375
|
+
e.header("Content-Type", "text/event-stream").header("Cache-Control", "no-cache").header("Connection", "keep-alive").send(`id: ${$}
|
|
317
376
|
|
|
318
|
-
${
|
|
377
|
+
${P(Q, $)}`);
|
|
319
378
|
return;
|
|
320
379
|
}
|
|
321
|
-
return e.send(
|
|
380
|
+
return e.send(Q);
|
|
322
381
|
}
|
|
323
|
-
}),
|
|
324
|
-
const a =
|
|
382
|
+
}), i.get(`${t}`, async (r, e) => {
|
|
383
|
+
const a = E();
|
|
325
384
|
e.raw.writeHead(200, {
|
|
326
385
|
"Content-Type": "text/event-stream",
|
|
327
386
|
"Cache-Control": "no-cache",
|
|
328
387
|
Connection: "keep-alive"
|
|
329
|
-
}), e.raw.write(
|
|
388
|
+
}), e.raw.write(P({
|
|
330
389
|
jsonrpc: "2.0",
|
|
331
390
|
method: "mcp/ready",
|
|
332
391
|
params: { protocol: "streamable-http" }
|
|
333
392
|
}, a, 15e3));
|
|
334
|
-
const
|
|
393
|
+
const n = setInterval(() => {
|
|
335
394
|
e.raw.write(`: keep-alive
|
|
336
395
|
|
|
337
396
|
`);
|
|
338
397
|
}, 15e3);
|
|
339
|
-
|
|
340
|
-
clearInterval(
|
|
398
|
+
r.raw.on("close", () => {
|
|
399
|
+
clearInterval(n);
|
|
341
400
|
});
|
|
342
|
-
}),
|
|
401
|
+
}), i.delete(`${t}`, async (r, e) => e.status(405).send({ error: "Session termination not supported" }));
|
|
343
402
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
const a =
|
|
347
|
-
return
|
|
348
|
-
}),
|
|
403
|
+
i.setErrorHandler(async (t, r, e) => {
|
|
404
|
+
r.log.error(t, "Fastify cube adapter error"), e.statusCode < 400 && e.status(500);
|
|
405
|
+
const a = t instanceof Error ? t : String(t);
|
|
406
|
+
return d(a, e.statusCode);
|
|
407
|
+
}), R();
|
|
349
408
|
};
|
|
350
|
-
async function
|
|
351
|
-
await h.register(N,
|
|
409
|
+
async function Z(h, i) {
|
|
410
|
+
await h.register(N, i);
|
|
352
411
|
}
|
|
353
|
-
function
|
|
354
|
-
const
|
|
412
|
+
function ee(h) {
|
|
413
|
+
const i = require("fastify")({
|
|
355
414
|
logger: !0
|
|
356
415
|
});
|
|
357
|
-
return
|
|
416
|
+
return i.register(N, h), i;
|
|
358
417
|
}
|
|
359
418
|
export {
|
|
360
|
-
|
|
419
|
+
ee as createCubeApp,
|
|
361
420
|
N as cubePlugin,
|
|
362
|
-
|
|
421
|
+
Z as registerCubeRoutes
|
|
363
422
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";var j=Object.create;var T=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var D=Object.getPrototypeOf,U=Object.prototype.hasOwnProperty;var P=(a,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of z(t))!U.call(a,e)&&e!==n&&T(a,e,{get:()=>t[e],enumerable:!(s=O(t,e))||s.enumerable});return a};var L=(a,t,n)=>(n=a!=null?j(D(a)):{},P(t||!a||!a.__esModule?T(n,"default",{value:a,enumerable:!0}):n,a));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("./mcp-transport-BB998cy5.cjs"),q=require("./utils.cjs");function Y(a){if(a.length===0)return"No cubes are currently available.";const t=["## Available Cubes",""];for(const n of a){if(t.push(`### ${n.name}`),n.description&&t.push(n.description),n.measures&&n.measures.length>0){t.push(""),t.push("**Measures:**");for(const s of n.measures){const e=s.description?` - ${s.description}`:"";t.push(`- \`${n.name}.${s.name}\` (${s.type})${e}`)}}if(n.dimensions&&n.dimensions.length>0){t.push(""),t.push("**Dimensions:**");for(const s of n.dimensions){const e=s.description?` - ${s.description}`:"";t.push(`- \`${n.name}.${s.name}\` (${s.type})${e}`)}}if(n.relationships&&n.relationships.length>0){t.push(""),t.push("**Joins:**");for(const s of n.relationships)t.push(`- → \`${s.targetCube}\` (${s.relationship})`)}t.push("")}return t.join(`
|
|
2
|
+
`)}function b(a){return a.messages.map(t=>t.content.text).join(`
|
|
3
|
+
|
|
4
|
+
`)}function F(a){return["# Drizzle Cube Analytics Agent","","You are an analytics agent that helps users explore and visualize data.","You have access to a semantic layer with cubes (data models) that you can query.","","## Your Workflow","","1. **Discover** available cubes using `discover_cubes` to understand the data","2. **Explain your approach** by calling `add_markdown` to describe what you plan to analyze and why","3. **Query** data using `execute_query` with properly structured queries","4. **Explain results** by calling `add_markdown` to describe what the data shows, key insights, and methodology","5. **Visualize** results by calling `add_portlet` to add charts/tables to the notebook","","## Important Guidelines","","- ALWAYS discover cubes first before attempting queries","- Use `add_portlet` to create visualizations after getting query results","- Use `add_markdown` to explain your findings, methodology, and insights","- Choose appropriate chart types: bar for categories, line for trends, table for detailed data","- When showing data, always add both a portlet (visualization) and markdown (explanation)","- If a query fails, explain the error and try an alternative approach","","## Output Format Rules","","### CRITICAL: Always think before acting","- EVERY single turn MUST begin with a text message (1-2 sentences) BEFORE any tool calls. This is your #1 rule — never violate it.","- This applies to EVERY turn, including turns where you are adding visualizations or explanations to the notebook.",`- Even when adding multiple portlets/markdowns in sequence, each turn must start with text like "Now I'll add the productivity chart." or "Next, let me visualize the department breakdown."`,'- Example good turn: "Let me discover what data is available." → discover_cubes',`- Example good turn: "I'll add a bar chart showing the top employees." → add_markdown → add_portlet`,"- Example bad turn: (no text) → add_portlet ← NEVER do this","","### Text vs Notebook","- ALL analysis, findings, methodology, and insights MUST go through `add_markdown` tool calls — never in your text responses","- Your text responses must be 1-2 short sentences (under 50 words) summarizing what you are about to do next — status updates only","- Never use markdown formatting (headers, bullets, bold, code blocks) in text responses — plain sentences only","","### Notebook content rules","- Before each `add_portlet`, ALWAYS call `add_markdown` first to explain WHY you are adding this visualization and what it shows","- Before calling `add_portlet`, verify the query is valid: all fields in `order` must also appear in `measures` or `dimensions`",'- Never put data tables in markdown blocks — use `add_portlet` with chartType "table" instead',"- Think out loud in the notebook: use `add_markdown` to share your reasoning at each step so users can follow along","","---","",b(f.MCP_GUIDE_PROMPT),"","---","",b(f.QUERY_RULES_PROMPT),"","---","",b(f.QUERY_BUILDING_PROMPT),"","---","",b(f.DATE_FILTERING_PROMPT),"","---","",Y(a)].join(`
|
|
5
|
+
`)}function J(){return[{name:"discover_cubes",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.",input_schema:{type:"object",properties:{topic:{type:"string",description:'Keyword to search (e.g., "sales", "employees")'},intent:{type:"string",description:'Natural language goal (e.g., "analyze productivity trends")'},limit:{type:"number",description:"Max results (default: 10)"},minScore:{type:"number",description:"Min relevance 0-1 (default: 0.1)"}}}},{name:"get_cube_metadata",description:"Get full metadata for all registered cubes including all measures, dimensions, types, and relationships. Use this for detailed schema information.",input_schema:{type:"object",properties:{}}},{name:"execute_query",description:"Execute a semantic query and return data results. The query follows the Cube.js query format with measures, dimensions, filters, timeDimensions, order, and limit.",input_schema:{type:"object",properties:{measures:{type:"array",items:{type:"string"},description:'Aggregation measures (e.g., ["Employees.count"])'},dimensions:{type:"array",items:{type:"string"},description:'Grouping dimensions (e.g., ["Employees.name"])'},filters:{type:"array",items:{type:"object",properties:{member:{type:"string"},operator:{type:"string"},values:{type:"array",items:{}}},required:["member","operator"]},description:"Filter conditions"},timeDimensions:{type:"array",items:{type:"object",properties:{dimension:{type:"string"},granularity:{type:"string"},dateRange:{}},required:["dimension"]},description:"Time dimensions with optional granularity"},order:{type:"object",description:'Sort order (e.g., {"Employees.count": "desc"})'},limit:{type:"number",description:"Row limit"}}}},{name:"add_portlet",description:"Add a chart or table visualization to the notebook. The query is validated before adding — if invalid, an error is returned so you can fix the query. The portlet fetches its own data - you do NOT need to pass data to it.",input_schema:{type:"object",properties:{title:{type:"string",description:"Title for the visualization"},query:{type:"string",description:"JSON string of the CubeQuery to visualize"},chartType:{type:"string",enum:["bar","line","area","pie","scatter","radar","bubble","table","number","funnel","heatmap","sankey","retention"],description:"Chart type to render"},chartConfig:{type:"object",properties:{xAxis:{type:"array",items:{type:"string"}},yAxis:{type:"array",items:{type:"string"}},series:{type:"array",items:{type:"string"}},sizeField:{type:"string"},colorField:{type:"string"}},description:"Chart axis configuration"},displayConfig:{type:"object",properties:{showLegend:{type:"boolean"},showGrid:{type:"boolean"},showTooltip:{type:"boolean"},stacked:{type:"boolean"},orientation:{type:"string",enum:["horizontal","vertical"]}},description:"Chart display configuration"}},required:["title","query","chartType"]}},{name:"add_markdown",description:"Add an explanation or analysis text block to the notebook. Use markdown formatting. Use this to explain findings, methodology, and insights alongside visualizations.",input_schema:{type:"object",properties:{title:{type:"string",description:"Optional title for the text block"},content:{type:"string",description:"Markdown content to display"}},required:["content"]}}]}function B(a){const{semanticLayer:t,securityContext:n}=a,s=new Map;return s.set("discover_cubes",async e=>{const r=await q.handleDiscover(t,{topic:e.topic,intent:e.intent,limit:e.limit,minScore:e.minScore});return{result:JSON.stringify(r,null,2)}}),s.set("get_cube_metadata",async()=>{const e=t.getMetadata();return{result:JSON.stringify(e,null,2)}}),s.set("execute_query",async e=>{try{const r={measures:e.measures,dimensions:e.dimensions,filters:e.filters,timeDimensions:e.timeDimensions,order:e.order,limit:e.limit},i=await q.handleLoad(t,n,{query:r});return{result:JSON.stringify({rowCount:i.data.length,data:i.data,annotation:i.annotation},null,2)}}catch(r){return{result:`Query execution failed: ${r instanceof Error?r.message:"Unknown error"}`,isError:!0}}}),s.set("add_portlet",async e=>{let r;try{r=JSON.parse(e.query)}catch{return{result:"Invalid query: could not parse JSON string. Ensure `query` is a valid JSON string.",isError:!0}}const i=t.validateQuery(r);if(!i.isValid)return{result:`Invalid query — fix these errors and retry:
|
|
6
|
+
${i.errors.join(`
|
|
7
|
+
`)}`,isError:!0};const y=`portlet-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,_={id:y,title:e.title,query:e.query,chartType:e.chartType,chartConfig:e.chartConfig,displayConfig:e.displayConfig};return{result:`Portlet "${e.title}" added to notebook (id: ${y}, chart: ${e.chartType}). [Reminder: in your next response, start with a brief sentence about what you will do next BEFORE making any tool calls.]`,sideEffect:{type:"add_portlet",data:_}}}),s.set("add_markdown",async e=>{const r=`markdown-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,i={id:r,title:e.title,content:e.content};return{result:`Markdown block added to notebook (id: ${r}). [Reminder: in your next response, start with a brief sentence about what you will do next BEFORE making any tool calls.]`,sideEffect:{type:"add_markdown",data:i}}}),s}async function*G(a){const{message:t,sessionId:n,semanticLayer:s,securityContext:e,agentConfig:r,apiKey:i}=a;let y;try{const l=await import("@anthropic-ai/sdk");y=l.default||l.Anthropic||l}catch{yield{type:"error",data:{message:"@anthropic-ai/sdk is required. Install it with: npm install @anthropic-ai/sdk"}};return}const _=new y({apiKey:i}),C=J(),R=B({semanticLayer:s,securityContext:e}),S=s.getMetadata(),$=F(S),A=r.model||"claude-sonnet-4-6",I=r.maxTurns||25,N=r.maxTokens||4096,w=[{role:"user",content:t}];try{for(let l=0;l<I;l++){const M=await _.messages.create({model:A,max_tokens:N,system:$,tools:C,messages:w,stream:!0}),u=[];let x=-1,m="",k="";for await(const d of M)switch(d.type){case"content_block_start":{x++;const o=d.content_block;o.type==="tool_use"?(u.push({type:"tool_use",id:o.id,name:o.name,input:{}}),m="",yield{type:"tool_use_start",data:{id:o.id,name:o.name,input:void 0}}):o.type==="text"&&u.push({type:"text",text:""});break}case"content_block_delta":{const o=d.delta;if(o.type==="text_delta"&&o.text){const h=u[x];h&&(h.text=(h.text||"")+o.text),yield{type:"text_delta",data:o.text}}else o.type==="input_json_delta"&&o.partial_json&&(m+=o.partial_json);break}case"content_block_stop":{const o=u[x];if(o?.type==="tool_use"&&m){try{o.input=JSON.parse(m)}catch{o.input={}}m=""}break}case"message_delta":{const o=d.delta;o.stop_reason&&(k=o.stop_reason);break}}if(w.push({role:"assistant",content:u}),k!=="tool_use")break;const g=[];for(const d of u){if(d.type!=="tool_use")continue;const o=d.name,h=d.input||{},p=d.id,v=R.get(o);if(!v){g.push({type:"tool_result",tool_use_id:p,content:`Unknown tool: ${o}`,is_error:!0}),yield{type:"tool_use_result",data:{id:p,name:o,result:`Unknown tool: ${o}`}};continue}try{const c=await v(h);c.sideEffect&&(yield c.sideEffect),g.push({type:"tool_result",tool_use_id:p,content:c.result,...c.isError?{is_error:!0}:{}}),yield{type:"tool_use_result",data:{id:p,name:o,result:c.result}}}catch(c){const E=c instanceof Error?c.message:"Tool execution failed";g.push({type:"tool_result",tool_use_id:p,content:E,is_error:!0}),yield{type:"tool_use_result",data:{id:p,name:o,result:E}}}}yield{type:"turn_complete",data:{}},w.push({role:"user",content:g})}yield{type:"done",data:{sessionId:n||""}}}catch(l){yield{type:"error",data:{message:l instanceof Error?l.message:"Agent execution failed"}}}}exports.handleAgentChat=G;
|