drizzle-cube 0.4.15 → 0.4.17

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.
Files changed (45) hide show
  1. package/dist/adapters/express/index.cjs +1 -1
  2. package/dist/adapters/express/index.js +1 -1
  3. package/dist/adapters/fastify/index.cjs +1 -1
  4. package/dist/adapters/fastify/index.js +1 -1
  5. package/dist/adapters/handler-C1rOM9M_.cjs +25 -0
  6. package/dist/adapters/{handler-DZnCbydH.js → handler-nTycPMWF.js} +347 -265
  7. package/dist/adapters/hono/index.cjs +1 -1
  8. package/dist/adapters/hono/index.js +1 -1
  9. package/dist/adapters/nextjs/index.cjs +1 -1
  10. package/dist/adapters/nextjs/index.js +1 -1
  11. package/dist/client/charts.js +2 -2
  12. package/dist/client/chunks/{analysis-builder-C5e52Z3p.js → analysis-builder-3z9fHE2F.js} +5 -5
  13. package/dist/client/chunks/{analysis-builder-C5e52Z3p.js.map → analysis-builder-3z9fHE2F.js.map} +1 -1
  14. package/dist/client/chunks/{analysis-builder-shared-EnM-8plh.js → analysis-builder-shared-Da-vlQa_.js} +2 -2
  15. package/dist/client/chunks/{analysis-builder-shared-EnM-8plh.js.map → analysis-builder-shared-Da-vlQa_.js.map} +1 -1
  16. package/dist/client/chunks/{chart-data-table-D5G8nMnb.js → chart-data-table-BsAjHe7o.js} +2 -2
  17. package/dist/client/chunks/{chart-data-table-D5G8nMnb.js.map → chart-data-table-BsAjHe7o.js.map} +1 -1
  18. package/dist/client/chunks/{chart-kpi-delta-Dgg2eYRl.js → chart-kpi-delta-DUD3f8vL.js} +3 -3
  19. package/dist/client/chunks/{chart-kpi-delta-Dgg2eYRl.js.map → chart-kpi-delta-DUD3f8vL.js.map} +1 -1
  20. package/dist/client/chunks/{chart-kpi-number-DkoO99c1.js → chart-kpi-number-iJh-PzsM.js} +2 -2
  21. package/dist/client/chunks/{chart-kpi-number-DkoO99c1.js.map → chart-kpi-number-iJh-PzsM.js.map} +1 -1
  22. package/dist/client/chunks/{chart-kpi-text-1O6_lmz7.js → chart-kpi-text-x6pV9v9Q.js} +2 -2
  23. package/dist/client/chunks/{chart-kpi-text-1O6_lmz7.js.map → chart-kpi-text-x6pV9v9Q.js.map} +1 -1
  24. package/dist/client/chunks/{charts-loader-AW3T1nv5.js → charts-loader-B3tt5oKG.js} +5 -5
  25. package/dist/client/chunks/{charts-loader-AW3T1nv5.js.map → charts-loader-B3tt5oKG.js.map} +1 -1
  26. package/dist/client/chunks/{components-BkeSy9xv.js → components-CMGGxqOB.js} +4 -4
  27. package/dist/client/chunks/{components-BkeSy9xv.js.map → components-CMGGxqOB.js.map} +1 -1
  28. package/dist/client/chunks/{icons-DAeqv1iX.js → icons-M7shurcH.js} +172 -160
  29. package/dist/client/chunks/icons-M7shurcH.js.map +1 -0
  30. package/dist/client/components/AgenticNotebook/AgentChatPanel.d.ts +6 -0
  31. package/dist/client/components/AgenticNotebook/index.d.ts +6 -0
  32. package/dist/client/components.js +1 -1
  33. package/dist/client/hooks/useAgentChat.d.ts +2 -2
  34. package/dist/client/icons/types.d.ts +2 -0
  35. package/dist/client/icons.js +1 -1
  36. package/dist/client/index.js +707 -675
  37. package/dist/client/index.js.map +1 -1
  38. package/dist/client/utils.js +3 -3
  39. package/dist/client-bundle-stats.html +1 -1
  40. package/dist/server/index.cjs +36 -36
  41. package/dist/server/index.d.ts +45 -0
  42. package/dist/server/index.js +1291 -1209
  43. package/package.json +1 -1
  44. package/dist/adapters/handler-ZDYlokiM.cjs +0 -25
  45. package/dist/client/chunks/icons-DAeqv1iX.js.map +0 -1
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("express"),M=require("cors"),c=require("../mcp-transport-8u9G5oNa.cjs"),n=require("../utils.cjs");function $(g){const{cubes:h,drizzle:w,schema:P,extractSecurityContext:y,engineType:A,cors:x,basePath:f="/cubejs-api/v1",jsonLimit:S="10mb",cache:H,mcp:v={enabled:!0},agent:j}=g;if(!h||h.length===0)throw new Error("At least one cube must be provided in the cubes array");const d=R.Router();x&&d.use(M(x)),d.use(R.json({limit:S})),d.use(R.urlencoded({extended:!0,limit:S}));const u=new c.SemanticLayerCompiler({drizzle:w,schema:P,engineType:A,cache:H});if(h.forEach(r=>{u.registerCube(r)}),d.post(`${f}/load`,async(r,t)=>{try{const e=r.body.query||r.body,o=await y(r,t),s=u.validateQuery(e);if(!s.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${s.errors.join(", ")}`,400));const a=r.headers["x-cache-control"]==="no-cache",i=await u.executeMultiCubeQuery(e,o,{skipCache:a});t.json(n.formatCubeResponse(e,i,u))}catch(e){console.error("Query execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),d.get(`${f}/load`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json(n.formatErrorResponse("Query parameter is required",400));let o;try{o=JSON.parse(e)}catch{return t.status(400).json(n.formatErrorResponse("Invalid JSON in query parameter",400))}const s=await y(r,t),a=u.validateQuery(o);if(!a.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const i=r.headers["x-cache-control"]==="no-cache",m=await u.executeMultiCubeQuery(o,s,{skipCache:i});t.json(n.formatCubeResponse(o,m,u))}catch(e){console.error("Query execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),d.post(`${f}/batch`,async(r,t)=>{try{const{queries:e}=r.body;if(!e||!Array.isArray(e))return t.status(400).json(n.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return t.status(400).json(n.formatErrorResponse("Queries array cannot be empty",400));const o=await y(r,t),s=r.headers["x-cache-control"]==="no-cache",a=await n.handleBatchRequest(e,o,u,{skipCache:s});t.json(a)}catch(e){console.error("Batch execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),d.get(`${f}/meta`,(r,t)=>{try{const e=u.getMetadata();t.json(n.formatMetaResponse(e))}catch(e){console.error("Metadata error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),d.post(`${f}/sql`,async(r,t)=>{try{const e=r.body,o=await y(r,t),s=u.validateQuery(e);if(!s.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${s.errors.join(", ")}`,400));const a=e.measures?.[0]||e.dimensions?.[0];if(!a)return t.status(400).json(n.formatErrorResponse("No measures or dimensions specified",400));const i=a.split(".")[0],m=await u.generateSQL(i,e,o);t.json(n.formatSqlResponse(e,m))}catch(e){console.error("SQL generation error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),d.get(`${f}/sql`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json(n.formatErrorResponse("Query parameter is required",400));const o=JSON.parse(e),s=await y(r,t),a=u.validateQuery(o);if(!a.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const i=o.measures?.[0]||o.dimensions?.[0];if(!i)return t.status(400).json(n.formatErrorResponse("No measures or dimensions specified",400));const m=i.split(".")[0],p=await u.generateSQL(m,o,s);t.json(n.formatSqlResponse(o,p))}catch(e){console.error("SQL generation error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),d.post(`${f}/dry-run`,async(r,t)=>{try{const e=r.body.query||r.body,o=await y(r,t),s=await n.handleDryRun(e,o,u);t.json(s)}catch(e){console.error("Dry-run error:",e),t.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),d.get(`${f}/dry-run`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json({error:"Query parameter is required",valid:!1});const o=JSON.parse(e),s=await y(r,t),a=await n.handleDryRun(o,s,u);t.json(a)}catch(e){console.error("Dry-run error:",e),t.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),d.post(`${f}/explain`,async(r,t)=>{try{const e=r.body.query||r.body,o=r.body.options||{},s=await y(r,t),a=u.validateQuery(e);if(!a.isValid)return t.status(400).json({error:`Query validation failed: ${a.errors.join(", ")}`});const i=await u.explainQuery(e,s,o);t.json(i)}catch(e){console.error("Explain error:",e),t.status(500).json({error:e instanceof Error?e.message:"Explain query failed"})}}),j&&d.post(`${f}/agent/chat`,async(r,t)=>{try{const{handleAgentChat:e}=await Promise.resolve().then(()=>require("../handler-ZDYlokiM.cjs")),{message:o,sessionId:s,history:a}=r.body;if(!o||typeof o!="string")return t.status(400).json({error:"message is required and must be a string"});let i=(j.apiKey||"").trim();if(j.allowClientApiKey){const p=r.headers["x-agent-api-key"];p&&(i=p.trim())}if(!i)return t.status(401).json({error:"No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header."});const m=await y(r,t);t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});try{const p=e({message:o,sessionId:s,history:a,semanticLayer:u,securityContext:m,agentConfig:j,apiKey:i});for await(const l of p)t.write(`data: ${JSON.stringify(l)}
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("express"),M=require("cors"),c=require("../mcp-transport-8u9G5oNa.cjs"),n=require("../utils.cjs");function $(g){const{cubes:h,drizzle:w,schema:P,extractSecurityContext:y,engineType:A,cors:x,basePath:f="/cubejs-api/v1",jsonLimit:S="10mb",cache:H,mcp:v={enabled:!0},agent:j}=g;if(!h||h.length===0)throw new Error("At least one cube must be provided in the cubes array");const d=R.Router();x&&d.use(M(x)),d.use(R.json({limit:S})),d.use(R.urlencoded({extended:!0,limit:S}));const u=new c.SemanticLayerCompiler({drizzle:w,schema:P,engineType:A,cache:H});if(h.forEach(r=>{u.registerCube(r)}),d.post(`${f}/load`,async(r,t)=>{try{const e=r.body.query||r.body,o=await y(r,t),s=u.validateQuery(e);if(!s.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${s.errors.join(", ")}`,400));const a=r.headers["x-cache-control"]==="no-cache",i=await u.executeMultiCubeQuery(e,o,{skipCache:a});t.json(n.formatCubeResponse(e,i,u))}catch(e){console.error("Query execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),d.get(`${f}/load`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json(n.formatErrorResponse("Query parameter is required",400));let o;try{o=JSON.parse(e)}catch{return t.status(400).json(n.formatErrorResponse("Invalid JSON in query parameter",400))}const s=await y(r,t),a=u.validateQuery(o);if(!a.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const i=r.headers["x-cache-control"]==="no-cache",m=await u.executeMultiCubeQuery(o,s,{skipCache:i});t.json(n.formatCubeResponse(o,m,u))}catch(e){console.error("Query execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),d.post(`${f}/batch`,async(r,t)=>{try{const{queries:e}=r.body;if(!e||!Array.isArray(e))return t.status(400).json(n.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return t.status(400).json(n.formatErrorResponse("Queries array cannot be empty",400));const o=await y(r,t),s=r.headers["x-cache-control"]==="no-cache",a=await n.handleBatchRequest(e,o,u,{skipCache:s});t.json(a)}catch(e){console.error("Batch execution error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),d.get(`${f}/meta`,(r,t)=>{try{const e=u.getMetadata();t.json(n.formatMetaResponse(e))}catch(e){console.error("Metadata error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),d.post(`${f}/sql`,async(r,t)=>{try{const e=r.body,o=await y(r,t),s=u.validateQuery(e);if(!s.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${s.errors.join(", ")}`,400));const a=e.measures?.[0]||e.dimensions?.[0];if(!a)return t.status(400).json(n.formatErrorResponse("No measures or dimensions specified",400));const i=a.split(".")[0],m=await u.generateSQL(i,e,o);t.json(n.formatSqlResponse(e,m))}catch(e){console.error("SQL generation error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),d.get(`${f}/sql`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json(n.formatErrorResponse("Query parameter is required",400));const o=JSON.parse(e),s=await y(r,t),a=u.validateQuery(o);if(!a.isValid)return t.status(400).json(n.formatErrorResponse(`Query validation failed: ${a.errors.join(", ")}`,400));const i=o.measures?.[0]||o.dimensions?.[0];if(!i)return t.status(400).json(n.formatErrorResponse("No measures or dimensions specified",400));const m=i.split(".")[0],p=await u.generateSQL(m,o,s);t.json(n.formatSqlResponse(o,p))}catch(e){console.error("SQL generation error:",e),t.status(500).json(n.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),d.post(`${f}/dry-run`,async(r,t)=>{try{const e=r.body.query||r.body,o=await y(r,t),s=await n.handleDryRun(e,o,u);t.json(s)}catch(e){console.error("Dry-run error:",e),t.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),d.get(`${f}/dry-run`,async(r,t)=>{try{const e=r.query.query;if(!e)return t.status(400).json({error:"Query parameter is required",valid:!1});const o=JSON.parse(e),s=await y(r,t),a=await n.handleDryRun(o,s,u);t.json(a)}catch(e){console.error("Dry-run error:",e),t.status(400).json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),d.post(`${f}/explain`,async(r,t)=>{try{const e=r.body.query||r.body,o=r.body.options||{},s=await y(r,t),a=u.validateQuery(e);if(!a.isValid)return t.status(400).json({error:`Query validation failed: ${a.errors.join(", ")}`});const i=await u.explainQuery(e,s,o);t.json(i)}catch(e){console.error("Explain error:",e),t.status(500).json({error:e instanceof Error?e.message:"Explain query failed"})}}),j&&d.post(`${f}/agent/chat`,async(r,t)=>{try{const{handleAgentChat:e}=await Promise.resolve().then(()=>require("../handler-C1rOM9M_.cjs")),{message:o,sessionId:s,history:a}=r.body;if(!o||typeof o!="string")return t.status(400).json({error:"message is required and must be a string"});let i=(j.apiKey||"").trim();if(j.allowClientApiKey){const p=r.headers["x-agent-api-key"];p&&(i=p.trim())}if(!i)return t.status(401).json({error:"No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header."});const m=await y(r,t);t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});try{const p=e({message:o,sessionId:s,history:a,semanticLayer:u,securityContext:m,agentConfig:j,apiKey:i});for await(const l of p)t.write(`data: ${JSON.stringify(l)}
2
2
 
3
3
  `)}catch(p){const l={type:"error",data:{message:p instanceof Error?p.message:"Stream failed"}};t.write(`data: ${JSON.stringify(l)}
4
4
 
@@ -198,7 +198,7 @@ function W(h) {
198
198
  }
199
199
  }), j && c.post(`${p}/agent/chat`, async (r, t) => {
200
200
  try {
201
- const { handleAgentChat: e } = await import("../handler-DZnCbydH.js"), { message: o, sessionId: a, history: n } = r.body;
201
+ const { handleAgentChat: e } = await import("../handler-nTycPMWF.js"), { message: o, sessionId: a, history: n } = r.body;
202
202
  if (!o || typeof o != "string")
203
203
  return t.status(400).json({ error: "message is required and must be a string" });
204
204
  let s = (j.apiKey || "").trim();
@@ -1,4 +1,4 @@
1
- "use strict";var O=Object.create;var j=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var L=Object.getPrototypeOf,D=Object.prototype.hasOwnProperty;var H=(p,n,b,C)=>{if(n&&typeof n=="object"||typeof n=="function")for(let h of J(n))!D.call(p,h)&&h!==b&&j(p,h,{get:()=>n[h],enumerable:!(C=k(n,h))||C.enumerable});return p};var T=(p,n,b)=>(b=p!=null?O(L(p)):{},H(n||!p||!p.__esModule?j(b,"default",{value:p,enumerable:!0}):b,p));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("../mcp-transport-8u9G5oNa.cjs"),a=require("../utils.cjs"),q=function(n,b,C){const{cubes:h,drizzle:I,schema:A,extractSecurityContext:m,engineType:M,cors:P,basePath:g="/cubejs-api/v1",bodyLimit:v=10485760,cache:N,mcp:R={enabled:!0},agent:w}=b;if(!h||h.length===0)return C(new Error("At least one cube must be provided in the cubes array"));P&&n.register(import("@fastify/cors"),P),n.addHook("onRequest",async(r,t)=>{r.method==="POST"&&(r.body=void 0)});const d=new u.SemanticLayerCompiler({drizzle:I,schema:A,engineType:M,cache:N});if(h.forEach(r=>{d.registerCube(r)}),n.post(`${g}/load`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,s=await m(r),i=d.validateQuery(o);if(!i.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=r.headers["x-cache-control"]==="no-cache",y=await d.executeMultiCubeQuery(o,s,{skipCache:c});return a.formatCubeResponse(o,y,d)}catch(e){return r.log.error(e,"Query execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),n.get(`${g}/load`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query;let o;try{o=JSON.parse(e)}catch{return t.status(400).send(a.formatErrorResponse("Invalid JSON in query parameter",400))}const s=await m(r),i=d.validateQuery(o);if(!i.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=r.headers["x-cache-control"]==="no-cache",y=await d.executeMultiCubeQuery(o,s,{skipCache:c});return a.formatCubeResponse(o,y,d)}catch(e){return r.log.error(e,"Query execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),n.post(`${g}/batch`,{bodyLimit:v,schema:{body:{type:"object",required:["queries"],properties:{queries:{type:"array",items:{type:"object"}}}}}},async(r,t)=>{try{const{queries:e}=r.body;if(!e||!Array.isArray(e))return t.status(400).send(a.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return t.status(400).send(a.formatErrorResponse("Queries array cannot be empty",400));const o=await m(r),s=r.headers["x-cache-control"]==="no-cache";return await a.handleBatchRequest(e,o,d,{skipCache:s})}catch(e){return r.log.error(e,"Batch execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),n.get(`${g}/meta`,async(r,t)=>{try{const e=d.getMetadata();return a.formatMetaResponse(e)}catch(e){return r.log.error(e,"Metadata error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),n.post(`${g}/sql`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=await m(r),s=d.validateQuery(e);if(!s.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${s.errors.join(", ")}`,400));const i=e.measures?.[0]||e.dimensions?.[0];if(!i)return t.status(400).send(a.formatErrorResponse("No measures or dimensions specified",400));const c=i.split(".")[0],y=await d.generateSQL(c,e,o);return a.formatSqlResponse(e,y)}catch(e){return r.log.error(e,"SQL generation error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),n.get(`${g}/sql`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query,o=JSON.parse(e),s=await m(r),i=d.validateQuery(o);if(!i.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=o.measures?.[0]||o.dimensions?.[0];if(!c)return t.status(400).send(a.formatErrorResponse("No measures or dimensions specified",400));const y=c.split(".")[0],E=await d.generateSQL(y,o,s);return a.formatSqlResponse(o,E)}catch(e){return r.log.error(e,"SQL generation error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),n.post(`${g}/dry-run`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,s=await m(r);return await a.handleDryRun(o,s,d)}catch(e){return r.log.error(e,"Dry-run error"),t.status(400).send({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),n.get(`${g}/dry-run`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query,o=JSON.parse(e),s=await m(r);return await a.handleDryRun(o,s,d)}catch(e){return r.log.error(e,"Dry-run error"),t.status(400).send({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),n.post(`${g}/explain`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,s=e.options||{},i=await m(r),c=d.validateQuery(o);return c.isValid?await d.explainQuery(o,i,s):t.status(400).send({error:`Query validation failed: ${c.errors.join(", ")}`})}catch(e){return r.log.error(e,"Explain error"),t.status(500).send({error:e instanceof Error?e.message:"Explain query failed"})}}),w&&n.post(`${g}/agent/chat`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const{handleAgentChat:e}=await Promise.resolve().then(()=>require("../handler-ZDYlokiM.cjs")),o=r.body,{message:s,sessionId:i,history:c}=o;if(!s||typeof s!="string")return t.status(400).send({error:"message is required and must be a string"});let y=(w.apiKey||"").trim();if(w.allowClientApiKey){const l=r.headers["x-agent-api-key"];l&&(y=l.trim())}if(!y)return t.status(401).send({error:"No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header."});const E=await m(r);t.raw.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});try{const l=e({message:s,sessionId:i,history:c,semanticLayer:d,securityContext:E,agentConfig:w,apiKey:y});for await(const f of l)t.raw.write(`data: ${JSON.stringify(f)}
1
+ "use strict";var O=Object.create;var j=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var L=Object.getPrototypeOf,D=Object.prototype.hasOwnProperty;var H=(p,n,b,C)=>{if(n&&typeof n=="object"||typeof n=="function")for(let h of J(n))!D.call(p,h)&&h!==b&&j(p,h,{get:()=>n[h],enumerable:!(C=k(n,h))||C.enumerable});return p};var T=(p,n,b)=>(b=p!=null?O(L(p)):{},H(n||!p||!p.__esModule?j(b,"default",{value:p,enumerable:!0}):b,p));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("../mcp-transport-8u9G5oNa.cjs"),a=require("../utils.cjs"),q=function(n,b,C){const{cubes:h,drizzle:I,schema:A,extractSecurityContext:m,engineType:M,cors:P,basePath:g="/cubejs-api/v1",bodyLimit:v=10485760,cache:N,mcp:R={enabled:!0},agent:w}=b;if(!h||h.length===0)return C(new Error("At least one cube must be provided in the cubes array"));P&&n.register(import("@fastify/cors"),P),n.addHook("onRequest",async(r,t)=>{r.method==="POST"&&(r.body=void 0)});const d=new u.SemanticLayerCompiler({drizzle:I,schema:A,engineType:M,cache:N});if(h.forEach(r=>{d.registerCube(r)}),n.post(`${g}/load`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,s=await m(r),i=d.validateQuery(o);if(!i.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=r.headers["x-cache-control"]==="no-cache",y=await d.executeMultiCubeQuery(o,s,{skipCache:c});return a.formatCubeResponse(o,y,d)}catch(e){return r.log.error(e,"Query execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),n.get(`${g}/load`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query;let o;try{o=JSON.parse(e)}catch{return t.status(400).send(a.formatErrorResponse("Invalid JSON in query parameter",400))}const s=await m(r),i=d.validateQuery(o);if(!i.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=r.headers["x-cache-control"]==="no-cache",y=await d.executeMultiCubeQuery(o,s,{skipCache:c});return a.formatCubeResponse(o,y,d)}catch(e){return r.log.error(e,"Query execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Query execution failed",500))}}),n.post(`${g}/batch`,{bodyLimit:v,schema:{body:{type:"object",required:["queries"],properties:{queries:{type:"array",items:{type:"object"}}}}}},async(r,t)=>{try{const{queries:e}=r.body;if(!e||!Array.isArray(e))return t.status(400).send(a.formatErrorResponse('Request body must contain a "queries" array',400));if(e.length===0)return t.status(400).send(a.formatErrorResponse("Queries array cannot be empty",400));const o=await m(r),s=r.headers["x-cache-control"]==="no-cache";return await a.handleBatchRequest(e,o,d,{skipCache:s})}catch(e){return r.log.error(e,"Batch execution error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Batch execution failed",500))}}),n.get(`${g}/meta`,async(r,t)=>{try{const e=d.getMetadata();return a.formatMetaResponse(e)}catch(e){return r.log.error(e,"Metadata error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"Failed to fetch metadata",500))}}),n.post(`${g}/sql`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=await m(r),s=d.validateQuery(e);if(!s.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${s.errors.join(", ")}`,400));const i=e.measures?.[0]||e.dimensions?.[0];if(!i)return t.status(400).send(a.formatErrorResponse("No measures or dimensions specified",400));const c=i.split(".")[0],y=await d.generateSQL(c,e,o);return a.formatSqlResponse(e,y)}catch(e){return r.log.error(e,"SQL generation error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),n.get(`${g}/sql`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query,o=JSON.parse(e),s=await m(r),i=d.validateQuery(o);if(!i.isValid)return t.status(400).send(a.formatErrorResponse(`Query validation failed: ${i.errors.join(", ")}`,400));const c=o.measures?.[0]||o.dimensions?.[0];if(!c)return t.status(400).send(a.formatErrorResponse("No measures or dimensions specified",400));const y=c.split(".")[0],E=await d.generateSQL(y,o,s);return a.formatSqlResponse(o,E)}catch(e){return r.log.error(e,"SQL generation error"),t.status(500).send(a.formatErrorResponse(e instanceof Error?e.message:"SQL generation failed",500))}}),n.post(`${g}/dry-run`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,s=await m(r);return await a.handleDryRun(o,s,d)}catch(e){return r.log.error(e,"Dry-run error"),t.status(400).send({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),n.get(`${g}/dry-run`,{schema:{querystring:{type:"object",properties:{query:{type:"string"}},required:["query"]}}},async(r,t)=>{try{const{query:e}=r.query,o=JSON.parse(e),s=await m(r);return await a.handleDryRun(o,s,d)}catch(e){return r.log.error(e,"Dry-run error"),t.status(400).send({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1})}}),n.post(`${g}/explain`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const e=r.body,o=e.query||e,s=e.options||{},i=await m(r),c=d.validateQuery(o);return c.isValid?await d.explainQuery(o,i,s):t.status(400).send({error:`Query validation failed: ${c.errors.join(", ")}`})}catch(e){return r.log.error(e,"Explain error"),t.status(500).send({error:e instanceof Error?e.message:"Explain query failed"})}}),w&&n.post(`${g}/agent/chat`,{bodyLimit:v,schema:{body:{type:"object",additionalProperties:!0}}},async(r,t)=>{try{const{handleAgentChat:e}=await Promise.resolve().then(()=>require("../handler-C1rOM9M_.cjs")),o=r.body,{message:s,sessionId:i,history:c}=o;if(!s||typeof s!="string")return t.status(400).send({error:"message is required and must be a string"});let y=(w.apiKey||"").trim();if(w.allowClientApiKey){const l=r.headers["x-agent-api-key"];l&&(y=l.trim())}if(!y)return t.status(401).send({error:"No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header."});const E=await m(r);t.raw.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});try{const l=e({message:s,sessionId:i,history:c,semanticLayer:d,securityContext:E,agentConfig:w,apiKey:y});for await(const f of l)t.raw.write(`data: ${JSON.stringify(f)}
2
2
 
3
3
  `)}catch(l){const f={type:"error",data:{message:l instanceof Error?l.message:"Stream failed"}};t.raw.write(`data: ${JSON.stringify(f)}
4
4
 
@@ -262,7 +262,7 @@ const N = function(i, k, R) {
262
262
  }
263
263
  }, async (t, r) => {
264
264
  try {
265
- const { handleAgentChat: e } = await import("../handler-DZnCbydH.js"), a = t.body, { message: n, sessionId: s, history: o } = a;
265
+ const { handleAgentChat: e } = await import("../handler-nTycPMWF.js"), a = t.body, { message: n, sessionId: s, history: o } = a;
266
266
  if (!n || typeof n != "string")
267
267
  return r.status(400).send({ error: "message is required and must be a string" });
268
268
  let l = (v.apiKey || "").trim();
@@ -0,0 +1,25 @@
1
+ "use strict";var U=Object.create;var $=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var K=Object.getPrototypeOf,W=Object.prototype.hasOwnProperty;var X=(i,t,a,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of G(t))!W.call(i,e)&&e!==a&&$(i,e,{get:()=>t[e],enumerable:!(s=Z(t,e))||s.enumerable});return i};var J=(i,t,a)=>(a=i!=null?U(K(i)):{},X(t||!i||!i.__esModule?$(a,"default",{value:i,enumerable:!0}):a,i));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const q=require("./mcp-transport-8u9G5oNa.cjs"),B=require("./utils.cjs");function Q(i){if(i.length===0)return"No cubes are currently available.";const t=["## Available Cubes",""];for(const a of i){if(t.push(`### ${a.name}`),a.description&&t.push(a.description),a.measures&&a.measures.length>0){t.push(""),t.push("**Measures:**");for(const s of a.measures){const e=s.description?` - ${s.description}`:"";t.push(`- \`${a.name}.${s.name}\` (${s.type})${e}`)}}if(a.dimensions&&a.dimensions.length>0){t.push(""),t.push("**Dimensions:**");for(const s of a.dimensions){const e=s.description?` - ${s.description}`:"";t.push(`- \`${a.name}.${s.name}\` (${s.type})${e}`)}}if(a.relationships&&a.relationships.length>0){t.push(""),t.push("**Joins:**");for(const s of a.relationships)t.push(`- → \`${s.targetCube}\` (${s.relationship})`)}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("")}return t.join(`
2
+ `)}function I(i){return i.messages.map(t=>t.content.text).join(`
3
+
4
+ `)}function ee(i){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","- Field names MUST be `CubeName.fieldName` (e.g. `PullRequests.count`, `Teams.name`). NEVER use just the cube name as a field — `PullRequests.PullRequests` is WRONG.","- 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 charts in sequence, each turn must start with a brief status like "Now I'll chart the productivity breakdown." or "Next, let me show the department comparison."`,'- Example good turn: "Let me see what data is available." → discover_cubes',`- Example good turn: "I'll add a 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","- Write text responses as a friendly analyst would — use plain business language the user understands",'- NEVER mention internal terms like "cube", "query syntax", "field names", "measures", "dimensions", "portlet", "prefix format", or tool names in text responses','- Instead of "Let me correct the query syntax and retry" → "Let me fix that and try again"',`- Instead of "I'll query the PullRequests cube" → "I'll look at the pull request data"`,`- Instead of "Adding a portlet with the results" → "Here's a chart of the results"`,"","### 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","- NEVER use emojis in text responses or markdown content — no 📊, 📈, ✅, 🔍, etc. Write in plain, professional language.","","## Chart Selection Guide","","Choose the chart type that best communicates the answer to the user's question. Think about what the data represents and what insight the user needs — do NOT default to the first option in this table. Consider the number of data points, whether values are categorical or temporal, and whether the user is comparing, trending, or summarizing.","","| Intent / Data Shape | Chart Type |","|---|---|","| Compare discrete categories or rankings | `bar` |","| Trend over time (one or few series) | `line` |","| Trend over time showing volume/magnitude | `area` |","| Part-of-whole breakdown | `pie` (≤7 slices) |","| Correlation between two measures | `scatter` |","| Correlation with size/color third dimension | `bubble` |","| Intensity across two categorical dimensions | `heatmap` |","| Multi-variable comparison across categories | `radar` |","| Distribution/spread of values | `boxPlot` |","| Detailed row-level data or many columns | `table` |","| Single headline number — ONLY when user explicitly asks for a KPI card or single number | `kpiNumber` |","| Headline metric with period-over-period change — ONLY when user asks about change in a single metric | `kpiDelta` |","","Analysis-mode-specific chart types (require the corresponding analysis mode):","","| Analysis Mode | Chart Type | Description |","|---|---|---|","| Funnel | `funnel` | Sequential step conversion bars with conversion rates |","| Flow | `sankey` | Flow diagram showing paths between states/steps |","| Flow | `sunburst` | Radial rings showing forward paths from a starting event |","| Retention | `retentionHeatmap` | Cohort × period retention matrix |","| Retention | `retentionCombined` | Retention with line chart, heatmap, or combined modes |","",'**Chart selection priorities:** Default to `bar` for categories, `line` for time series, `table` for exploratory data. Use `kpiNumber`/`kpiDelta` only as a last resort — they are appropriate only when the user explicitly asks for a single headline number or KPI card. If the query returns multiple rows or the user asks a general question like "show me revenue", prefer `bar` or `table` over `kpiNumber`.',"","## Chart Axis Configuration Rules","","**Bar charts MUST have an xAxis.** Put a dimension in `chartConfig.xAxis` so bars have category labels. If your query has no dimensions, add one or use `table` instead.","","**Never duplicate xAxis in series.** Putting the same dimension in both `xAxis` and `series` creates a sparse, broken-looking chart. The `series` field is ONLY for splitting bars into grouped/stacked sub-series by a SECOND dimension.","","Correct bar chart examples:",'- Categories only: `xAxis: ["Cube.category"], yAxis: ["Cube.count"]` — no series needed','- Grouped bars: `xAxis: ["Cube.category"], yAxis: ["Cube.count"], series: ["Cube.status"]` — series is a DIFFERENT dimension','- Multiple measures: `xAxis: ["Cube.category"], yAxis: ["Cube.count", "Cube.total"]` — each measure becomes a bar group',"","Wrong:",'- `xAxis: [], yAxis: ["Cube.avg1", "Cube.avg2"]` — missing xAxis, bars have no labels','- `xAxis: ["Cube.size"], series: ["Cube.size"]` — same field in both, creates sparse chart',"","## Analysis Mode Decision Tree","","The default mode is **query** (standard measures/dimensions). Switch to a special mode only when the user's question matches:","",'- **Funnel mode** — "What is the conversion rate from step A → B → C?"'," - Requires: an event-stream cube with `capabilities.funnel = true` from `discover_cubes`"," - Execute: `execute_query` with `funnel` param:",' `{ bindingKey: "Events.userId", timeDimension: "Events.timestamp", steps: [{ name: "Signup", filter: { member: "Events.eventName", operator: "equals", values: ["signup"] }}, { name: "Purchase", filter: { member: "Events.eventName", operator: "equals", values: ["purchase"] }}] }`',' - Visualize: `add_portlet` with `chartType: "funnel"` and `query` as JSON string containing `{ "funnel": { ... } }`',"",'- **Flow mode** — "What paths do users take after signup?"'," - Requires: `capabilities.flow = true` from `discover_cubes`"," - Execute: `execute_query` with `flow` param:",' `{ bindingKey: "Events.userId", timeDimension: "Events.timestamp", eventDimension: "Events.eventName", startingStep: { name: "Signup", filter: { member: "Events.eventName", operator: "equals", values: ["signup"] }}, stepsBefore: 0, stepsAfter: 3 }`',' - Visualize: `add_portlet` with `chartType: "sankey"` (or `"sunburst"`) and `query` as JSON string containing `{ "flow": { ... } }`',"",'- **Retention mode** — "What % of users come back after 7 days?"'," - Requires: `capabilities.retention = true` from `discover_cubes`"," - Execute: `execute_query` with `retention` param:",' `{ timeDimension: "Events.timestamp", bindingKey: "Events.userId", dateRange: { start: "2024-01-01", end: "2024-03-31" }, granularity: "week", periods: 8, retentionType: "classic" }`',' - Visualize: `add_portlet` with `chartType: "retentionCombined"` (or `"retentionHeatmap"`) and `query` as JSON string containing `{ "retention": { ... } }`',"","Before using funnel/flow/retention, check the `capabilities` object returned by `discover_cubes`. If the required capability is `false`, explain to the user that the data model does not support that analysis mode.","","Event-stream cubes are marked in the Available Cubes section below with **Event Stream: Yes** and list their binding key and time dimension.","","---","",I(q.MCP_GUIDE_PROMPT),"","---","",I(q.QUERY_RULES_PROMPT),"","---","",I(q.QUERY_BUILDING_PROMPT),"","---","",I(q.DATE_FILTERING_PROMPT),"","---","","## Save as Dashboard","","When the user asks to save, export, or convert the notebook into a dashboard, use the `save_as_dashboard` tool.","","### Layout Rules","- Dashboard grid is 12 columns wide","- KPI cards: w=3, h=3 — place at the top in a row of 4","- Overview charts (bar, line, area): w=6, h=4","- Wide charts (heatmap, table): w=12, h=5","- Section headers (markdown): w=12, h=1","","### Section Headers",'Use `chartType: "markdown"` portlets as section headers to organize the dashboard:',"```json","{",' "id": "header-overview",',' "title": "Overview",',' "chartType": "markdown",',' "displayConfig": {',' "content": "## Overview",',' "hideHeader": true,',' "transparentBackground": true,',' "autoHeight": true'," },",' "w": 12, "h": 1, "x": 0, "y": 0',"}","```","","### Dashboard Filters","- ALWAYS include a universal date filter with `isUniversalTime: true`","- Add dimension filters for key fields used across portlets (e.g., department, status, region)",'- Use human-readable labels (e.g., "Department" not "Employees.departmentName")',"- Map filters to portlets using `dashboardFilterMapping` — list the filter IDs that apply","- When promoting a hardcoded filter to a dashboard filter, REMOVE that filter from the portlet query","","### Analysis Types",'- Standard query portlets: `analysisType: "query"` (default)','- Funnel portlets: `analysisType: "funnel"`, query contains `{ "funnel": {...} }`, chartType `"funnel"`','- Flow portlets: `analysisType: "flow"`, query contains `{ "flow": {...} }`, chartType `"sankey"` or `"sunburst"`','- Retention portlets: `analysisType: "retention"`, query contains `{ "retention": {...} }`, chartType `"retentionHeatmap"` or `"retentionCombined"`',"","### CRITICAL: Only use portlets from the notebook","- ONLY include portlets that you already added to the notebook via `add_portlet` during this conversation","- Do NOT invent new queries or charts that were not part of the analysis — the dashboard is a direct conversion of the notebook","- Reuse the exact same queries, chart types, and chart configs from the notebook portlets","- Arrange the existing portlets in a sensible layout (KPIs at top, charts in middle, tables at bottom)","- You may add section header markdown portlets to organize the layout, but do not add new data portlets","","---","",Q(i)].join(`
5
+ `)}const te={label:"Bar Chart",description:"Compare values across categories",useCase:"Best for comparing discrete categories, showing rankings, or displaying changes over time",clickableElements:{bar:!0},dropZones:[{key:"xAxis",label:"X-Axis (Categories)",description:"Dimensions and time dimensions for grouping",mandatory:!1,acceptTypes:["dimension","timeDimension"],emptyText:"Drop dimensions & time dimensions here"},{key:"yAxis",label:"Y-Axis (Values)",description:"Measures for bar heights",mandatory:!0,acceptTypes:["measure"],emptyText:"Drop measures here",enableDualAxis:!0},{key:"series",label:"Series (Split into Multiple Series)",description:"Dimensions to create separate data series",mandatory:!1,acceptTypes:["dimension"],emptyText:"Drop dimensions here to split data into series"}],displayOptions:["showLegend","showGrid","showTooltip","hideHeader"],displayOptionsConfig:[{key:"stackType",label:"Stacking",type:"select",defaultValue:"none",options:[{value:"none",label:"None"},{value:"normal",label:"Stacked"},{value:"percent",label:"Stacked 100%"}],description:"How to stack multiple bar series"},{key:"target",label:"Target Values",type:"string",placeholder:"e.g., 100 or 50,75 for spread",description:"Single value or comma-separated values to spread across X-axis"},{key:"leftYAxisFormat",label:"Left Y-Axis Format",type:"axisFormat",description:"Number formatting for left Y-axis"},{key:"rightYAxisFormat",label:"Right Y-Axis Format",type:"axisFormat",description:"Number formatting for right Y-axis"}]},ae={label:"Line Chart",description:"Show trends and changes over time",useCase:"Best for continuous data, trends, time series, and showing relationships between multiple series",clickableElements:{point:!0},dropZones:[{key:"xAxis",label:"X-Axis (Time/Categories)",description:"Time dimensions or dimensions for X-axis",mandatory:!0,acceptTypes:["dimension","timeDimension"],emptyText:"Drop time dimensions or dimensions here"},{key:"yAxis",label:"Y-Axis (Values)",description:"Measures for line values",mandatory:!0,acceptTypes:["measure"],emptyText:"Drop measures here",enableDualAxis:!0},{key:"series",label:"Series (Multiple Lines)",description:"Dimensions to create separate lines",mandatory:!1,acceptTypes:["dimension"],emptyText:"Drop dimensions here for multiple lines"}],displayOptions:["showLegend","showGrid","showTooltip","hideHeader"],displayOptionsConfig:[{key:"connectNulls",label:"Connect Nulls",type:"boolean",defaultValue:!1,description:"Draw continuous line through missing data points"},{key:"target",label:"Target Values",type:"string",placeholder:"e.g., 100 or 50,75 for spread",description:"Single value or comma-separated values to spread across X-axis"},{key:"priorPeriodStyle",label:"Prior Period Line Style",type:"select",defaultValue:"dashed",options:[{value:"dashed",label:"Dashed"},{value:"dotted",label:"Dotted"},{value:"solid",label:"Solid"}],description:"Line style for prior period in comparison mode"},{key:"priorPeriodOpacity",label:"Prior Period Opacity",type:"number",defaultValue:.5,min:.1,max:1,step:.1,description:"Opacity for prior period lines (0.1 to 1)"},{key:"leftYAxisFormat",label:"Left Y-Axis Format",type:"axisFormat",description:"Number formatting for left Y-axis"},{key:"rightYAxisFormat",label:"Right Y-Axis Format",type:"axisFormat",description:"Number formatting for right Y-axis"}]},se={label:"Area Chart",description:"Emphasize magnitude of change over time",useCase:"Best for showing cumulative totals, volume changes, or stacked comparisons over time",dropZones:[{key:"xAxis",label:"X-Axis (Time/Categories)",description:"Time dimensions or dimensions for X-axis",mandatory:!0,acceptTypes:["dimension","timeDimension"],emptyText:"Drop time dimensions or dimensions here"},{key:"yAxis",label:"Y-Axis (Values)",description:"Measures for area values",mandatory:!0,acceptTypes:["measure"],emptyText:"Drop measures here",enableDualAxis:!0},{key:"series",label:"Series (Stack Areas)",description:"Dimensions to create stacked areas",mandatory:!1,acceptTypes:["dimension"],emptyText:"Drop dimensions here for stacked areas"}],displayOptions:["showLegend","showGrid","showTooltip","hideHeader"],displayOptionsConfig:[{key:"stackType",label:"Stacking",type:"select",defaultValue:"none",options:[{value:"none",label:"None"},{value:"normal",label:"Stacked"},{value:"percent",label:"Stacked 100%"}],description:"How to stack multiple area series"},{key:"connectNulls",label:"Connect Nulls",type:"boolean",defaultValue:!1,description:"Draw continuous line through missing data points"},{key:"target",label:"Target Values",type:"string",placeholder:"e.g., 100 or 50,75 for spread",description:"Single value or comma-separated values to spread across X-axis"},{key:"leftYAxisFormat",label:"Left Y-Axis Format",type:"axisFormat",description:"Number formatting for left Y-axis"},{key:"rightYAxisFormat",label:"Right Y-Axis Format",type:"axisFormat",description:"Number formatting for right Y-axis"}]},ie={label:"Pie Chart",description:"Show proportions of a whole",useCase:"Best for showing percentage distribution or composition of a total (limit to 5-7 slices)",clickableElements:{slice:!0},dropZones:[{key:"xAxis",label:"Categories",description:"Dimension for pie slices",mandatory:!0,maxItems:1,acceptTypes:["dimension"],emptyText:"Drop a dimension for categories"},{key:"yAxis",label:"Values",description:"Measure for slice sizes",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure for values"}],displayOptions:["showLegend","showTooltip","hideHeader"],displayOptionsConfig:[{key:"leftYAxisFormat",label:"Value Format",type:"axisFormat",description:"Number formatting for values"}]},oe={label:"Scatter Plot",description:"Reveal correlations between variables",useCase:"Best for identifying patterns, correlations, outliers, and relationships between two measures",dropZones:[{key:"xAxis",label:"X-Axis",description:"Measure or dimension for X position",mandatory:!0,maxItems:1,acceptTypes:["dimension","timeDimension","measure"],emptyText:"Drop a field for X-axis"},{key:"yAxis",label:"Y-Axis",description:"Measure for Y position",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure for Y-axis"},{key:"series",label:"Series (Color Groups)",description:"Dimension to color points by category",mandatory:!1,maxItems:1,acceptTypes:["dimension"],emptyText:"Drop a dimension to color points"}],displayOptions:["showLegend","showGrid","showTooltip","hideHeader"],displayOptionsConfig:[{key:"xAxisFormat",label:"X-Axis Format",type:"axisFormat",description:"Number formatting for X-axis"},{key:"leftYAxisFormat",label:"Y-Axis Format",type:"axisFormat",description:"Number formatting for Y-axis"}]},re={label:"Bubble Chart",description:"Compare three dimensions of data",useCase:"Best for showing relationships between three variables (X, Y, and size), market analysis",dropZones:[{key:"xAxis",label:"X-Axis",description:"Horizontal axis position",mandatory:!0,maxItems:1,acceptTypes:["dimension","timeDimension","measure"],emptyText:"Drop a field for X-axis position"},{key:"yAxis",label:"Y-Axis",description:"Vertical axis position",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure for Y-axis position"},{key:"sizeField",label:"Bubble Radius",description:"Size of bubbles based on this measure",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure for bubble size"},{key:"series",label:"Bubble Labels",description:"Field to use for bubble labels and identification",mandatory:!0,maxItems:1,acceptTypes:["dimension"],emptyText:"Drop a dimension for bubble labels"},{key:"colorField",label:"Bubble Colour",description:"Color bubbles by this field (optional)",mandatory:!1,maxItems:1,acceptTypes:["dimension","measure"],emptyText:"Drop a field for bubble color (optional)"}],displayOptions:["showLegend","showGrid","showTooltip","minBubbleSize","maxBubbleSize","bubbleOpacity","hideHeader"],displayOptionsConfig:[{key:"xAxisFormat",label:"X-Axis Format",type:"axisFormat",description:"Number formatting for X-axis"},{key:"leftYAxisFormat",label:"Y-Axis Format",type:"axisFormat",description:"Number formatting for Y-axis and values"}]},ne={label:"Radar Chart",description:"Compare multiple metrics across categories",useCase:"Best for multivariate comparisons, performance metrics, strengths/weaknesses analysis",dropZones:[{key:"xAxis",label:"Axes (Categories)",description:"Dimensions for radar axes",mandatory:!0,acceptTypes:["dimension"],emptyText:"Drop dimensions for radar axes"},{key:"yAxis",label:"Values",description:"Measures for radar values",mandatory:!0,acceptTypes:["measure"],emptyText:"Drop measures for values"},{key:"series",label:"Series (Multiple Shapes)",description:"Dimensions to create multiple radar shapes",mandatory:!1,acceptTypes:["dimension"],emptyText:"Drop dimensions for multiple shapes"}],displayOptions:["showLegend","showGrid","showTooltip","hideHeader"],displayOptionsConfig:[{key:"leftYAxisFormat",label:"Value Format",type:"axisFormat",description:"Number formatting for values"}]},le={label:"Radial Bar Chart",description:"Circular progress and KPI visualization",useCase:"Best for showing progress toward goals, KPIs, or comparing percentages in a compact form",dropZones:[{key:"xAxis",label:"Categories",description:"Dimensions for radial segments",mandatory:!0,acceptTypes:["dimension"],emptyText:"Drop dimensions for categories"},{key:"yAxis",label:"Values",description:"Measures for radial bar lengths",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure for values"}],displayOptions:["showLegend","showTooltip","hideHeader"],displayOptionsConfig:[{key:"leftYAxisFormat",label:"Value Format",type:"axisFormat",description:"Number formatting for values"}]},de={label:"TreeMap",description:"Visualize hierarchical data with nested rectangles",useCase:"Best for showing part-to-whole relationships in hierarchical data, disk usage, budget allocation",dropZones:[{key:"xAxis",label:"Categories",description:"Dimensions for treemap rectangles",mandatory:!0,acceptTypes:["dimension"],emptyText:"Drop dimensions for categories"},{key:"yAxis",label:"Size",description:"Measure for rectangle sizes",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure for size"},{key:"series",label:"Color Groups",description:"Dimension to color rectangles by category",mandatory:!1,maxItems:1,acceptTypes:["dimension"],emptyText:"Drop a dimension for color grouping"}],displayOptions:["showLegend","showTooltip","hideHeader"],displayOptionsConfig:[{key:"leftYAxisFormat",label:"Value Format",type:"axisFormat",description:"Number formatting for size values"}],clickableElements:{cell:!0}},pe={label:"Data Table",description:"Display detailed tabular data",useCase:"Best for precise values, detailed analysis, sortable/filterable data exploration",dropZones:[{key:"xAxis",label:"Columns",description:"All fields to display as columns",mandatory:!1,acceptTypes:["dimension","timeDimension","measure"],emptyText:"Drop fields to display as columns (or leave empty for all)"}],displayOptions:["hideHeader"],displayOptionsConfig:[{key:"leftYAxisFormat",label:"Value Format",type:"axisFormat",description:"Number formatting for numeric values"}]},ue={label:"Activity Grid",description:"GitHub-style activity grid showing temporal patterns across different time scales",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",dropZones:[{key:"dateField",label:"Time Dimension",description:"Time field that determines grid structure (granularity affects layout)",mandatory:!0,maxItems:1,acceptTypes:["timeDimension"],emptyText:"Drop a time dimension (granularity affects grid structure)"},{key:"valueField",label:"Activity Measure",description:"Measure used for activity intensity (color coding)",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure for activity intensity"}],displayOptions:["showLabels","showTooltip","hideHeader"],displayOptionsConfig:[{key:"fitToWidth",label:"Fit to Width",type:"boolean",defaultValue:!1,description:"Automatically size blocks to fill portlet width and height while maintaining aspect ratio"}],validate:i=>{const{dateField:t,valueField:a}=i;return!t||Array.isArray(t)&&t.length===0?{isValid:!1,message:"Time dimension is required for activity grid"}:!a||Array.isArray(a)&&a.length===0?{isValid:!1,message:"Activity measure is required for intensity mapping"}:{isValid:!0}},clickableElements:{cell:!0}},ce={label:"KPI Number",description:"Display key performance indicators as large numbers",useCase:"Perfect for showing important metrics like revenue, user count, or other key business metrics in a prominent, easy-to-read format",dropZones:[{key:"yAxis",label:"Value",description:"Measure to display as KPI number",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure here"}],displayOptionsConfig:[{key:"target",label:"Target Value",type:"string",placeholder:"e.g., 100",description:"Target value to compare against (first value used if multiple provided)"},{key:"prefix",label:"Prefix",type:"string",placeholder:"e.g., $, €, #",description:"Text to display before the number"},{key:"suffix",label:"Suffix",type:"string",placeholder:"e.g., %, units, items",description:"Text to display after the number"},{key:"decimals",label:"Decimal Places",type:"number",defaultValue:0,min:0,max:10,step:1,description:"Number of decimal places to display"},{key:"valueColorIndex",label:"Value Color",type:"paletteColor",defaultValue:0,description:"Color from the dashboard palette for the KPI value text"},{key:"useLastCompletePeriod",label:"Use Last Complete Period",type:"boolean",defaultValue:!0,description:"Exclude current incomplete period from aggregation (e.g., partial week/month)"},{key:"skipLastPeriod",label:"Skip Last Period",type:"boolean",defaultValue:!1,description:"Always exclude the last period regardless of completeness"}],displayOptions:["hideHeader"]},me={label:"KPI Delta",description:"Display change between latest and previous values with trend indicators",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",dropZones:[{key:"yAxis",label:"Value",description:"Measure to track changes for",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure here"},{key:"xAxis",label:"Dimension (optional)",description:"Dimension for ordering data (typically time)",mandatory:!1,maxItems:1,acceptTypes:["dimension","timeDimension"],emptyText:"Drop a dimension for ordering"}],displayOptionsConfig:[{key:"prefix",label:"Prefix",type:"string",placeholder:"e.g., $, €, #",description:"Text to display before the number"},{key:"suffix",label:"Suffix",type:"string",placeholder:"e.g., %, units, items",description:"Text to display after the number"},{key:"decimals",label:"Decimal Places",type:"number",defaultValue:1,min:0,max:10,step:1,description:"Number of decimal places to display"},{key:"positiveColorIndex",label:"Positive Change Color",type:"paletteColor",defaultValue:2,description:"Color for positive changes (increases)"},{key:"negativeColorIndex",label:"Negative Change Color",type:"paletteColor",defaultValue:3,description:"Color for negative changes (decreases)"},{key:"showHistogram",label:"Show Variance Histogram",type:"boolean",defaultValue:!0,description:"Display historical variance chart below the delta"},{key:"useLastCompletePeriod",label:"Use Last Complete Period",type:"boolean",defaultValue:!0,description:"Exclude current incomplete period from delta calculation (e.g., partial week/month)"},{key:"skipLastPeriod",label:"Skip Last Period",type:"boolean",defaultValue:!1,description:"Always exclude the last period regardless of completeness"}],displayOptions:["hideHeader"],validate:i=>!i.yAxis||Array.isArray(i.yAxis)&&i.yAxis.length===0?{isValid:!1,message:"A measure is required for KPI Delta charts"}:{isValid:!0}},ye={label:"KPI Text",description:"Display key performance indicators as customizable text",useCase:"Perfect for showing metrics with custom formatting, combining multiple values, or displaying contextual KPI information using templates",dropZones:[{key:"yAxis",label:"Value",description:"Measure to display in the KPI text template",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure here"}],displayOptionsConfig:[{key:"template",label:"Text Template",type:"string",placeholder:"e.g., Total Revenue: ${value}",description:"Template for displaying the text. Use ${value} to insert the measure value."},{key:"decimals",label:"Decimal Places",type:"number",defaultValue:0,min:0,max:10,step:1,description:"Number of decimal places to display for numeric values"},{key:"valueColorIndex",label:"Value Color",type:"paletteColor",defaultValue:0,description:"Color from the dashboard palette for the KPI value text"}],displayOptions:["hideHeader"]},he={label:"Markdown",description:"Display custom markdown content with formatting",useCase:"Perfect for adding documentation, notes, section headers, instructions, or formatted text to dashboards",skipQuery:!0,dropZones:[],displayOptionsConfig:[{key:"content",label:"Markdown Content",type:"string",placeholder:`# Welcome
6
+
7
+ Add your **markdown** content here:
8
+
9
+ - Lists with bullets
10
+ - [Links](https://example.com)
11
+ - *Italic* and **bold** text
12
+
13
+ ---
14
+
15
+ Use --- for horizontal rules.`,description:"Enter markdown text. Supports headers (#), bold (**text**), italic (*text*), links ([text](url)), lists (- item), and horizontal rules (---)."},{key:"accentColorIndex",label:"Accent Color",type:"paletteColor",defaultValue:0,description:"Color from the dashboard palette for headers, bullets, and links"},{key:"fontSize",label:"Font Size",type:"select",defaultValue:"medium",options:[{value:"small",label:"Small"},{value:"medium",label:"Medium"},{value:"large",label:"Large"}],description:"Overall text size for the markdown content"},{key:"alignment",label:"Text Alignment",type:"select",defaultValue:"left",options:[{value:"left",label:"Left"},{value:"center",label:"Center"},{value:"right",label:"Right"}],description:"Horizontal alignment of the markdown content"},{key:"hideHeader",label:"Hide Header",type:"boolean",defaultValue:!0,description:"Hide the portlet header bar (title and action buttons)"},{key:"transparentBackground",label:"Transparent Background",type:"boolean",defaultValue:!1,description:"Remove card background, border, and shadow for seamless integration as section headers"},{key:"autoHeight",label:"Auto Height",type:"boolean",defaultValue:!0,description:"In row and mobile layouts, size to markdown content instead of fixed row height"},{key:"accentBorder",label:"Accent Border",type:"select",defaultValue:"none",options:[{value:"none",label:"None"},{value:"left",label:"Left"},{value:"top",label:"Top"},{value:"bottom",label:"Bottom"}],description:"Add an accent-colored border on one side of the content"}]},fe={label:"Funnel Chart",description:"Show conversion through sequential steps",useCase:"Best for visualizing user journey funnels, sales pipelines, or multi-step processes",dropZones:[{key:"xAxis",label:"Step Name",description:"Step names (auto-populated from funnel steps)",mandatory:!1,maxItems:1,acceptTypes:["dimension"],emptyText:"Steps defined in funnel config"},{key:"yAxis",label:"Step Count",description:"Count at each step (auto-calculated)",mandatory:!1,maxItems:1,acceptTypes:["measure"],emptyText:"Counts calculated from funnel execution"}],displayOptions:["hideHeader"],displayOptionsConfig:[{key:"funnelStyle",label:"Funnel Style",type:"buttonGroup",defaultValue:"bars",options:[{value:"bars",label:"Bars"},{value:"funnel",label:"Funnel"}],description:"Visualization style"},{key:"funnelOrientation",label:"Orientation",type:"buttonGroup",defaultValue:"horizontal",options:[{value:"horizontal",label:"Horizontal"},{value:"vertical",label:"Vertical"}]},{key:"hideSummaryFooter",label:"Hide Summary Footer",type:"boolean",defaultValue:!1,description:"Hide the summary footer showing steps count and overall conversion"},{key:"showFunnelConversion",label:"Show Conversion Rate",type:"boolean",defaultValue:!0,description:"Display step-to-step conversion percentage"},{key:"showFunnelAvgTime",label:"Show Avg Time",type:"boolean",defaultValue:!1,description:"Display average time to convert"},{key:"showFunnelMedianTime",label:"Show Median Time",type:"boolean",defaultValue:!1,description:"Display median time to convert"},{key:"showFunnelP90Time",label:"Show P90 Time",type:"boolean",defaultValue:!1,description:"Display 90th percentile time to convert"}]},be={label:"Sankey Chart",description:"Show flow between states or steps",useCase:"Best for visualizing user journey flows, path analysis, or state transitions",dropZones:[{key:"xAxis",label:"Event Type",description:"Event dimension that categorizes flow nodes",mandatory:!1,maxItems:1,acceptTypes:["dimension"],emptyText:"Auto-populated from flow config"},{key:"yAxis",label:"Flow Count",description:"Count of entities following each path",mandatory:!1,maxItems:1,acceptTypes:["measure"],emptyText:"Calculated from flow execution"}],displayOptions:["hideHeader"],displayOptionsConfig:[{key:"linkOpacity",label:"Link Opacity",type:"buttonGroup",defaultValue:"0.5",options:[{value:"0.3",label:"Light"},{value:"0.5",label:"Medium"},{value:"0.7",label:"Dark"}],description:"Opacity of flow links"},{key:"showNodeLabels",label:"Show Node Labels",type:"boolean",defaultValue:!0,description:"Display labels on flow nodes"},{key:"hideSummaryFooter",label:"Hide Summary Footer",type:"boolean",defaultValue:!0,description:"Hide the statistics footer below the chart"}]},ge={label:"Sunburst Chart",description:"Show hierarchical flow as radial rings",useCase:"Best for visualizing forward paths from a starting event in a compact radial layout",dropZones:[{key:"xAxis",label:"Event Type",description:"Event dimension that categorizes flow nodes",mandatory:!1,maxItems:1,acceptTypes:["dimension"],emptyText:"Auto-populated from flow config"},{key:"yAxis",label:"Flow Count",description:"Count of entities following each path",mandatory:!1,maxItems:1,acceptTypes:["measure"],emptyText:"Calculated from flow execution"}],displayOptions:["hideHeader"],displayOptionsConfig:[{key:"innerRadius",label:"Inner Radius",type:"number",defaultValue:40,min:0,max:100,step:10,description:"Size of the center hole (0 for full circle)"},{key:"hideSummaryFooter",label:"Hide Summary Footer",type:"boolean",defaultValue:!0,description:"Hide the statistics footer below the chart"}]},xe={label:"Heatmap",description:"Visualize intensity across two dimensions",useCase:"Best for showing patterns in matrix data like correlations, schedules, or category comparisons",dropZones:[{key:"xAxis",label:"Columns (X-Axis)",description:"Dimension for column categories",mandatory:!0,maxItems:1,acceptTypes:["dimension"],emptyText:"Drop one dimension here"},{key:"yAxis",label:"Rows (Y-Axis)",description:"Dimension for row categories",mandatory:!0,maxItems:1,acceptTypes:["dimension"],emptyText:"Drop one dimension here"},{key:"valueField",label:"Value (Color Intensity)",description:"Measure that determines cell color",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop one measure here"}],displayOptions:["showLegend","showTooltip"],displayOptionsConfig:[{key:"showLabels",label:"Show Cell Values",type:"boolean",defaultValue:!1,description:"Display values inside each cell"},{key:"cellShape",label:"Cell Shape",type:"select",defaultValue:"rect",options:[{value:"rect",label:"Rectangle"},{value:"circle",label:"Circle"}]},{key:"xAxisFormat",label:"X-Axis Format",type:"axisFormat",description:"Number formatting for X-axis labels"},{key:"yAxisFormat",label:"Y-Axis Format",type:"axisFormat",description:"Number formatting for Y-axis labels"},{key:"valueFormat",label:"Value Format",type:"axisFormat",description:"Number formatting for cell values and legend"}],validate:i=>i.xAxis?.length?i.yAxis?.length?i.valueField?.length?{isValid:!0}:{isValid:!1,message:"Value measure required"}:{isValid:!1,message:"Y-axis dimension required"}:{isValid:!1,message:"X-axis dimension required"}},we={label:"Retention Matrix",dropZones:[],displayOptionsConfig:[{key:"showLegend",label:"Show Legend",type:"boolean",defaultValue:!0,description:"Show the color intensity legend"},{key:"showTooltip",label:"Show Tooltip",type:"boolean",defaultValue:!0,description:"Show tooltip on hover with detailed stats"}],description:"Cohort retention matrix visualization",useCase:"Visualize user retention over time by cohort"},ke={label:"Retention Chart",dropZones:[],displayOptionsConfig:[{key:"retentionDisplayMode",label:"Display Mode",type:"select",defaultValue:"line",options:[{value:"line",label:"Line Chart"},{value:"heatmap",label:"Heatmap Table"},{value:"combined",label:"Combined"}],description:"Choose how to visualize retention data"},{key:"showLegend",label:"Show Legend",type:"boolean",defaultValue:!0,description:"Show the legend for breakdown segments"},{key:"showGrid",label:"Show Grid",type:"boolean",defaultValue:!0,description:"Show grid lines on the chart"},{key:"showTooltip",label:"Show Tooltip",type:"boolean",defaultValue:!0,description:"Show tooltip on hover with detailed stats"}],description:"Combined retention visualization with line chart and heatmap modes",useCase:"Visualize user retention over time with optional breakdown segmentation"},ve={label:"Box Plot",description:"Show statistical distribution (median, IQR, whiskers) across categories",useCase:"Best for P&L spread per symbol, trade size distribution, latency distribution across platforms",displayOptions:["hideHeader"],dropZones:[{key:"xAxis",label:"X-Axis (Groups)",description:"Dimension to group boxes by (e.g. symbol, platform)",mandatory:!0,maxItems:1,acceptTypes:["dimension","timeDimension"],emptyText:"Drop a dimension here"},{key:"yAxis",label:"Y-Axis (Measures)",description:"Drop 1 measure for auto mode, 3 for avg/stddev/median mode, or 5 for min/q1/median/q3/max mode",mandatory:!0,maxItems:5,acceptTypes:["measure"],emptyText:"Drop 1, 3, or 5 measures here"}],displayOptionsConfig:[{key:"leftYAxisFormat",label:"Y-Axis Format",type:"axisFormat",description:"Number formatting for the value axis"}]},Ce={label:"Waterfall Chart",description:"Show cumulative effect of sequential positive and negative values",useCase:"Best for P&L decomposition, cash flow analysis, budget variance, or any sequential contribution breakdown",clickableElements:{bar:!0},displayOptions:["showTooltip","hideHeader"],dropZones:[{key:"xAxis",label:"X-Axis (Categories)",description:"Dimension labels for each bar segment (e.g. symbol, transaction type)",mandatory:!0,maxItems:1,acceptTypes:["dimension","timeDimension"],emptyText:"Drop a dimension here"},{key:"yAxis",label:"Y-Axis (Value)",description:"Single measure whose values are summed cumulatively",mandatory:!0,maxItems:1,acceptTypes:["measure"],emptyText:"Drop a measure here"}],displayOptionsConfig:[{key:"showTotal",label:"Show Total Bar",type:"boolean",defaultValue:!0,description:"Append a final bar showing the running total"},{key:"showConnectorLine",label:"Show Connector Line",type:"boolean",defaultValue:!0,description:"Draw a dashed step-line connecting bar tops"},{key:"showDataLabels",label:"Show Data Labels",type:"boolean",defaultValue:!1,description:"Display the value above each bar segment"},{key:"leftYAxisFormat",label:"Y-Axis Format",type:"axisFormat",description:"Number formatting for the Y-axis"}]},Te={label:"Candlestick Chart",description:"Financial candlestick chart showing open/close body and high/low wicks",useCase:"Best for EOD quotes (bid/ask spread per date/symbol), markout distribution bands, or OHLC price data",clickableElements:{bar:!0},displayOptions:["hideHeader"],dropZones:[{key:"xAxis",label:"X-Axis (Time / Category)",description:"Time dimension or category for each candle (e.g. date, symbol)",mandatory:!0,maxItems:1,acceptTypes:["timeDimension","dimension"],emptyText:"Drop a time or dimension here"},{key:"yAxis",label:"OHLC Measures (open, close, high, low)",description:"Drop 2–4 measures in order: open, close, high, low (OHLC mode). For range mode drop 2: high, low.",mandatory:!0,acceptTypes:["measure"],emptyText:"Drop 2+ measures here"}],displayOptionsConfig:[{key:"rangeMode",label:"Chart Mode",type:"select",defaultValue:"ohlc",options:[{value:"ohlc",label:"OHLC (open, close, high, low)"},{value:"range",label:"Range (high, low / bid, ask)"}],description:"OHLC: 4 measures. Range: 2 measures (high + low)."},{key:"bullColor",label:"Bullish Colour",type:"color",defaultValue:"#22c55e",description:"Candle colour when close ≥ open"},{key:"bearColor",label:"Bearish Colour",type:"color",defaultValue:"#ef4444",description:"Candle colour when close < open"},{key:"showWicks",label:"Show Wicks",type:"boolean",defaultValue:!0,description:"Draw high/low wicks above and below the body"},{key:"leftYAxisFormat",label:"Y-Axis Format",type:"axisFormat",description:"Number formatting for the price axis"}]},Ae={label:"Measure Profile",description:"Plot N measures as sequential X-axis points to visualise a profile or shape across intervals",useCase:"Best for markout interval analysis (e.g. avgMinus2m → avgAtEvent → avgPlus2h), metric profiles, or any pattern across ordered measures",displayOptions:["showLegend","showTooltip","hideHeader"],dropZones:[{key:"yAxis",label:"Measures (X-Axis Order)",description:"Add 2 or more measures — they become the X-axis categories in the order listed",mandatory:!0,acceptTypes:["measure"],emptyText:"Drop 2+ measures here (displayed left → right)"},{key:"series",label:"Series (Split into Multiple Lines)",description:"Dimension to split data into separate profile lines (e.g. symbol, platform)",mandatory:!1,maxItems:1,acceptTypes:["dimension"],emptyText:"Drop a dimension here to create multiple lines"}],displayOptionsConfig:[{key:"showReferenceLineAtZero",label:"Show Zero Reference Line",type:"boolean",defaultValue:!0,description:"Draw a dashed line at Y = 0"},{key:"showDataLabels",label:"Show Data Labels",type:"boolean",defaultValue:!1,description:"Display value at each data point"},{key:"showLegend",label:"Show Legend",type:"boolean",defaultValue:!0,description:"Show series legend (only visible with a Series dimension)"},{key:"lineType",label:"Line Interpolation",type:"select",defaultValue:"monotone",options:[{value:"monotone",label:"Smooth (monotone)"},{value:"linear",label:"Linear"},{value:"step",label:"Step"}],description:"How data points are connected"},{key:"leftYAxisFormat",label:"Y-Axis Format",type:"axisFormat",description:"Number formatting for the Y-axis"}]},De={label:"Gauge Chart",description:"Half-circle arc gauge for a single KPI value versus a maximum target",useCase:"Best for high-water marks vs equity, margin utilisation, or any single value progress toward a goal",clickableElements:{},displayOptions:["hideHeader"],dropZones:[{key:"yAxis",label:"Value Measure",description:"Current value to display on the gauge (e.g. current equity, margin used)",mandatory:!0,maxItems:2,acceptTypes:["measure"],emptyText:"Drop 1 measure here (optional 2nd for dynamic max)"}],displayOptionsConfig:[{key:"minValue",label:"Minimum Value",type:"number",defaultValue:0,description:"Lower bound of the gauge arc (default 0)"},{key:"maxValue",label:"Maximum Value (static)",type:"number",description:"Upper bound of the gauge. Leave empty to use yAxis[1] or default 100"},{key:"thresholds",label:"Threshold Bands",type:"string",placeholder:'[{"value":0.33,"color":"#22c55e"},{"value":0.66,"color":"#f59e0b"},{"value":1,"color":"#ef4444"}]',description:"Array of {value (0–1 fraction), color} bands shown as outer arc markers"},{key:"showCenterLabel",label:"Show Centre Label",type:"boolean",defaultValue:!0,description:"Display current value and field name in the centre of the gauge"},{key:"showPercentage",label:"Show as Percentage",type:"boolean",defaultValue:!1,description:"Display value as % of max instead of raw number"},{key:"leftYAxisFormat",label:"Value Format",type:"axisFormat",description:"Number formatting for the displayed value and axis labels"}]},L={bar:te,line:ae,area:se,pie:ie,scatter:oe,bubble:re,radar:ne,radialBar:le,treemap:de,table:pe,activityGrid:ue,kpiNumber:ce,kpiDelta:me,kpiText:ye,markdown:he,funnel:fe,sankey:be,sunburst:ge,heatmap:xe,retentionHeatmap:we,retentionCombined:ke,boxPlot:ve,waterfall:Ce,candlestick:Te,measureProfile:Ae,gauge:De};function Se(i,t,a){const s=L[i];if(!s)return{isValid:!0,errors:[]};if(s.skipQuery)return{isValid:!0,errors:[]};const e=[];for(const o of s.dropZones){if(!o.mandatory)continue;const l=t?.[o.key];if(!(Array.isArray(l)?l.length>0:!!l)){const u=o.acceptTypes?.join("/")??"fields";e.push(`chartConfig.${o.key} is required for ${i} chart (${o.label}). Accepts: ${u}.`)}}if(i==="bar"){const o=t?.xAxis;if(!(Array.isArray(o)?o.length>0:!!o)){const d=a.dimensions??[],u=a.timeDimensions??[];d.length>0||u.length>0?e.push("chartConfig.xAxis is required for bar charts. Put a dimension in xAxis so bars have category labels."):e.push('Bar charts need an xAxis dimension for category labels. Add a dimension to the query or use "table" chart type instead.')}}if(t?.xAxis&&t?.series){const o=new Set(Array.isArray(t.xAxis)?t.xAxis:[t.xAxis]),d=(Array.isArray(t.series)?t.series:[t.series]).filter(u=>o.has(u));d.length>0&&e.push(`chartConfig.series must not contain the same field as xAxis (found: ${d.join(", ")}). The series field is only for splitting into grouped/stacked sub-series by a DIFFERENT dimension. Remove the duplicate from series.`)}return{isValid:e.length===0,errors:e}}function Fe(i,t,a){const s=L[i];if(!s)return t??{};const e={...t},o=a.measures??[],l=a.dimensions??[],u=(a.timeDimensions??[]).map(p=>p.dimension);for(const p of s.dropZones){const m=e[p.key];if(Array.isArray(m)?m.length>0:!!m)continue;const b=p.acceptTypes??[];if(p.key==="sizeField"||p.key==="colorField"){if(b.includes("measure")){const g=new Set;for(const S of s.dropZones){if(S.key===p.key)continue;const x=e[S.key];Array.isArray(x)?x.forEach(V=>g.add(V)):typeof x=="string"&&g.add(x)}const C=o.filter(S=>!g.has(S));C.length>0&&(e[p.key]=C[0])}continue}const y=[];if(b.includes("dimension")&&y.push(...l),b.includes("timeDimension")&&y.push(...u),b.includes("measure")&&y.push(...o),y.length===0)continue;let f=y;if(p.key==="series"){const g=new Set(Array.isArray(e.xAxis)?e.xAxis:e.xAxis?[e.xAxis]:[]);if(f=y.filter(C=>!g.has(C)),f.length===0)continue}const v=p.maxItems??1/0,D=f.slice(0,v);D.length>0&&(e[p.key]=D)}return e}function _e(i){const t=[`
16
+ Chart config requirements by type:`];for(const a of i){const s=L[a];if(!s)continue;const e=s.description??"",o=s.useCase??"",l=[e,o].filter(Boolean).join(". "),d=l?` — ${l}.`:"",u=s.dropZones.filter(m=>m.mandatory);if(u.length===0&&!s.skipQuery){t.push(` ${a}${d} chartConfig auto-inferred from query.`);continue}if(s.skipQuery){t.push(` ${a}${d} No query needed.`);continue}const p=u.map(m=>{const n=m.acceptTypes?.join("/")??"any",b=m.maxItems?` (max ${m.maxItems})`:"";return`${m.key}=[${n}]${b}`});t.push(` ${a}${d} Requires ${p.join(", ")}.`)}return t.join(`
17
+ `)}const P=["bar","line","area","pie","scatter","radar","bubble","table","kpiNumber","kpiDelta","funnel","heatmap","sankey","sunburst","retentionHeatmap","retentionCombined","boxPlot","markdown"];function Ve(){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. Supports standard queries (measures/dimensions) and analysis modes (funnel/flow/retention). Only provide ONE mode per call.",input_schema:{type:"object",properties:{measures:{type:"array",items:{type:"string",pattern:"^[A-Z][a-zA-Z0-9]*\\.[a-zA-Z][a-zA-Z0-9]*$"},description:'Aggregation measures — MUST be "CubeName.measureName" format (e.g., ["PullRequests.count", "Issues.openCount"]). NEVER use just the cube name.'},dimensions:{type:"array",items:{type:"string",pattern:"^[A-Z][a-zA-Z0-9]*\\.[a-zA-Z][a-zA-Z0-9]*$"},description:'Grouping dimensions — MUST be "CubeName.dimensionName" format (e.g., ["Teams.name", "Employees.department"]). NEVER use just the cube 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"},funnel:{type:"object",properties:{bindingKey:{type:"string",description:'Entity binding key (e.g., "Events.userId")'},timeDimension:{type:"string",description:'Time dimension (e.g., "Events.timestamp")'},steps:{type:"array",items:{type:"object",properties:{name:{type:"string"},filter:{},timeToConvert:{type:"string",description:'ISO 8601 duration (e.g., "P7D")'}},required:["name"]},description:"Funnel steps (min 2)"},includeTimeMetrics:{type:"boolean"},globalTimeWindow:{type:"string"}},required:["bindingKey","timeDimension","steps"],description:"Funnel analysis config. When provided, measures/dimensions are ignored."},flow:{type:"object",properties:{bindingKey:{type:"string"},timeDimension:{type:"string"},eventDimension:{type:"string",description:"Dimension whose values become node labels"},startingStep:{type:"object",properties:{name:{type:"string"},filter:{}},required:["name"]},stepsBefore:{type:"number",description:"Steps before starting step (0-5)"},stepsAfter:{type:"number",description:"Steps after starting step (0-5)"},entityLimit:{type:"number"},outputMode:{type:"string",enum:["sankey","sunburst"]}},required:["bindingKey","timeDimension","eventDimension","startingStep"],description:"Flow analysis config. When provided, measures/dimensions are ignored."},retention:{type:"object",properties:{timeDimension:{type:"string"},bindingKey:{type:"string"},dateRange:{type:"object",properties:{start:{type:"string",description:"YYYY-MM-DD"},end:{type:"string",description:"YYYY-MM-DD"}},required:["start","end"]},granularity:{type:"string",enum:["day","week","month"]},periods:{type:"number"},retentionType:{type:"string",enum:["classic","rolling"]},cohortFilters:{},activityFilters:{},breakdownDimensions:{type:"array",items:{type:"string"}}},required:["timeDimension","bindingKey","dateRange","granularity","periods"],description:"Retention analysis config. When provided, measures/dimensions are ignored."}}}},{name:"add_portlet",description:`Add a chart visualization to the notebook.
18
+ `+_e(P)+`
19
+ The query is validated before adding. The portlet fetches its own data.`,input_schema:{type:"object",properties:{title:{type:"string",description:"Title for the visualization"},query:{type:"string",description:'JSON string of the query. Standard: {"measures":[...],"dimensions":[...]}. Funnel: {"funnel":{"bindingKey":"...","timeDimension":"...","steps":[...]}}. Flow: {"flow":{"bindingKey":"...","timeDimension":"...","eventDimension":"...","startingStep":{...}}}. Retention: {"retention":{"timeDimension":"...","bindingKey":"...","dateRange":{"start":"...","end":"..."},"granularity":"...","periods":N}}.'},chartType:{type:"string",enum:P,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"]}},{name:"save_as_dashboard",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.",input_schema:{type:"object",properties:{title:{type:"string",description:"Dashboard title"},description:{type:"string",description:"Optional dashboard description"},portlets:{type:"array",items:{type:"object",properties:{id:{type:"string",description:"Unique portlet ID"},title:{type:"string",description:"Portlet title"},chartType:{type:"string",enum:P,description:'Chart type. Use "markdown" for section headers.'},query:{type:"string",description:"JSON string of the query. Omit or leave empty for markdown portlets."},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",description:"Chart display configuration (for markdown: { content, hideHeader, transparentBackground, autoHeight })"},dashboardFilterMapping:{type:"array",items:{type:"string"},description:"Array of dashboard filter IDs that apply to this portlet"},analysisType:{type:"string",enum:["query","funnel","flow","retention"],description:'Analysis type (default: "query")'},w:{type:"number",description:"Grid width (1-12)"},h:{type:"number",description:"Grid height in row units"},x:{type:"number",description:"Grid x position (0-11)"},y:{type:"number",description:"Grid y position"}},required:["id","title","chartType","w","h","x","y"]},description:"Array of portlet configurations for the dashboard"},filters:{type:"array",items:{type:"object",properties:{id:{type:"string",description:"Unique filter ID"},label:{type:"string",description:"Display label for the filter"},filter:{type:"object",properties:{member:{type:"string"},operator:{type:"string"},values:{type:"array",items:{}}},required:["member","operator"],description:"The filter definition"},isUniversalTime:{type:"boolean",description:"When true, applies to all time dimensions in portlets"}},required:["id","label","filter"]},description:"Dashboard-level filters"},colorPalette:{type:"string",description:"Color palette name"}},required:["title","portlets"]}}]}function Ee(i){const{semanticLayer:t,securityContext:a}=i,s=new Map;return s.set("discover_cubes",async e=>{const o=await B.handleDiscover(t,{topic:e.topic,intent:e.intent,limit:e.limit,minScore:e.minScore});return{result:JSON.stringify(o,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 o=(u,p)=>{if(!Array.isArray(u))return;const m=u.filter(n=>typeof n=="string"&&!n.includes("."));if(m.length>0)throw new Error(`Invalid ${p}: ${m.map(n=>`"${n}"`).join(", ")}. All ${p} must use "CubeName.fieldName" format (e.g., "PullRequests.count", "Teams.name"). Use discover_cubes or get_cube_metadata to find valid field names.`)};o(e.measures,"measures"),o(e.dimensions,"dimensions");let l;e.funnel?l={funnel:e.funnel}:e.flow?l={flow:e.flow}:e.retention?l={retention:e.retention}:l={measures:e.measures,dimensions:e.dimensions,filters:e.filters,timeDimensions:e.timeDimensions,order:e.order,limit:e.limit};const d=await B.handleLoad(t,a,{query:l});return{result:JSON.stringify({rowCount:d.data.length,data:d.data,annotation:d.annotation},null,2)}}catch(o){return{result:`Query execution failed: ${o instanceof Error?o.message:"Unknown error"}`,isError:!0}}}),s.set("add_portlet",async e=>{const l={number:"kpiNumber",retention:"retentionHeatmap"}[e.chartType]??e.chartType;let d;try{d=JSON.parse(e.query)}catch{return{result:"Invalid query: could not parse JSON string. Ensure `query` is a valid JSON string.",isError:!0}}const u=t.validateQuery(d);if(!u.isValid)return{result:`Invalid query — fix these errors and retry:
20
+ ${u.errors.join(`
21
+ `)}`,isError:!0};const p=!!(d.funnel||d.flow||d.retention);let m;if(p)m=e.chartConfig??{};else{const y=Fe(l,e.chartConfig,d),f=Se(l,y,d);if(!f.isValid)return{result:`Chart config invalid — fix these errors and retry:
22
+ ${f.errors.join(`
23
+ `)}`,isError:!0};m=y}const n=`portlet-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,b={id:n,title:e.title,query:e.query,chartType:l,chartConfig:m,displayConfig:e.displayConfig};return{result:`Portlet "${e.title}" added to notebook (id: ${n}, chart: ${l}). [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:b}}}),s.set("add_markdown",async e=>{const o=`markdown-${Date.now()}-${Math.random().toString(36).slice(2,7)}`,l={id:o,title:e.title,content:e.content};return{result:`Markdown block added to notebook (id: ${o}). [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:l}}}),s.set("save_as_dashboard",async e=>{try{const o=e.portlets;if(!o||o.length===0)return{result:"Dashboard must contain at least one portlet.",isError:!0};const l=[];for(const n of o){if(n.chartType==="markdown")continue;const y=n.query;if(!y){l.push(`Portlet "${n.title}": missing query`);continue}let f;try{f=JSON.parse(y)}catch{l.push(`Portlet "${n.title}": invalid JSON query`);continue}const v=t.validateQuery(f);v.isValid||l.push(`Portlet "${n.title}": ${v.errors.join(", ")}`)}if(l.length>0)return{result:`Dashboard has invalid portlets — fix these errors and retry:
24
+ ${l.join(`
25
+ `)}`,isError:!0};const d={portlets:o.map(n=>{const b=n.chartType,y=b==="markdown",f=y?"query":n.analysisType||"query",v=f==="funnel"?"funnel":f==="flow"?"flow":f==="retention"?"retention":"query",D=n.query||"{}";let g;try{g=JSON.parse(D)}catch{g={}}const C={version:1,analysisType:v,activeView:"chart",charts:{[v]:{chartType:b,chartConfig:n.chartConfig||{},displayConfig:n.displayConfig||{}}},query:y?{}:g};return{id:n.id,title:n.title,analysisConfig:C,dashboardFilterMapping:n.dashboardFilterMapping,w:n.w,h:n.h,x:n.x,y:n.y}}),filters:e.filters,colorPalette:e.colorPalette},u=e.title,p=d.portlets.length,m=d.filters?.length||0;return{result:`Dashboard "${u}" created with ${p} portlets and ${m} filters.`,sideEffect:{type:"dashboard_saved",data:{title:u,description:e.description,dashboardConfig:d}}}}catch(o){return{result:`Failed to save dashboard: ${o instanceof Error?o.message:"Unknown error"}`,isError:!0}}}),s}async function*qe(i){const{message:t,history:a,semanticLayer:s,securityContext:e,agentConfig:o,apiKey:l}=i,d=i.sessionId||crypto.randomUUID(),u=o.observability,p=crypto.randomUUID(),m=Date.now();let n;try{const c=await import("@anthropic-ai/sdk");n=c.default||c.Anthropic||c}catch{yield{type:"error",data:{message:"@anthropic-ai/sdk is required. Install it with: npm install @anthropic-ai/sdk"}};return}const b=new n({apiKey:l}),y=Ve(),f=Ee({semanticLayer:s,securityContext:e}),v=s.getMetadata(),D=ee(v),g=o.model||"claude-sonnet-4-6",C=o.maxTurns||25,S=o.maxTokens||4096;try{u?.onChatStart?.({traceId:p,sessionId:d,message:t,model:g,historyLength:a?.length??0})}catch{}const x=[];if(a&&a.length>0){for(const c of a)if(c.role==="user")x.push({role:"user",content:c.content});else if(c.role==="assistant"){const F=[];if(c.content&&F.push({type:"text",text:c.content}),c.toolCalls&&c.toolCalls.length>0){for(const h of c.toolCalls)F.push({type:"tool_use",id:h.id,name:h.name,input:h.input||{}});x.push({role:"assistant",content:F}),x.push({role:"user",content:c.toolCalls.map(h=>({type:"tool_result",tool_use_id:h.id,content:typeof h.result=="string"?h.result:JSON.stringify(h.result??""),...h.status==="error"?{is_error:!0}:{}}))})}else F.length>0&&x.push({role:"assistant",content:c.content})}}x.push({role:"user",content:t});let V=0;try{for(let c=0;c<C;c++){V=c+1;const F=await b.messages.create({model:g,max_tokens:S,system:D,tools:y,messages:x,stream:!0}),h=[];let O=-1,_="",N="",R,M;const j=Date.now();for await(const w of F)switch(w.type){case"content_block_start":{O++;const r=w.content_block;r.type==="tool_use"?(h.push({type:"tool_use",id:r.id,name:r.name,input:{}}),_="",yield{type:"tool_use_start",data:{id:r.id,name:r.name,input:void 0}}):r.type==="text"&&h.push({type:"text",text:""});break}case"content_block_delta":{const r=w.delta;if(r.type==="text_delta"&&r.text){const T=h[O];T&&(T.text=(T.text||"")+r.text),yield{type:"text_delta",data:r.text}}else r.type==="input_json_delta"&&r.partial_json&&(_+=r.partial_json);break}case"content_block_stop":{const r=h[O];if(r?.type==="tool_use"&&_){try{r.input=JSON.parse(_)}catch{r.input={}}_=""}break}case"message_start":{const r=w.message;r?.usage?.input_tokens!=null&&(R=r.usage.input_tokens);break}case"message_delta":{const r=w.delta,T=w.usage;T?.output_tokens!=null&&(M=T.output_tokens),r.stop_reason&&(N=r.stop_reason);break}}try{u?.onGenerationEnd?.({traceId:p,turn:c,model:g,stopReason:N,inputTokens:R,outputTokens:M,durationMs:Date.now()-j})}catch{}if(x.push({role:"assistant",content:h}),N!=="tool_use")break;const E=[];for(const w of h){if(w.type!=="tool_use")continue;const r=w.name,T=w.input||{},A=w.id,Y=f.get(r);if(!Y){E.push({type:"tool_result",tool_use_id:A,content:`Unknown tool: ${r}`,is_error:!0}),yield{type:"tool_use_result",data:{id:A,name:r,result:`Unknown tool: ${r}`,isError:!0}};continue}const z=Date.now();try{const k=await Y(T);k.sideEffect&&(yield k.sideEffect),E.push({type:"tool_result",tool_use_id:A,content:k.result,...k.isError?{is_error:!0}:{}}),yield{type:"tool_use_result",data:{id:A,name:r,result:k.result,...k.isError?{isError:!0}:{}}};try{u?.onToolEnd?.({traceId:p,turn:c,toolName:r,toolUseId:A,isError:!!k.isError,durationMs:Date.now()-z})}catch{}}catch(k){const H=k instanceof Error?k.message:"Tool execution failed";E.push({type:"tool_result",tool_use_id:A,content:H,is_error:!0}),yield{type:"tool_use_result",data:{id:A,name:r,result:H,isError:!0}};try{u?.onToolEnd?.({traceId:p,turn:c,toolName:r,toolUseId:A,isError:!0,durationMs:Date.now()-z})}catch{}}}yield{type:"turn_complete",data:{}},x.push({role:"user",content:E})}try{u?.onChatEnd?.({traceId:p,sessionId:d,totalTurns:V,durationMs:Date.now()-m})}catch{}yield{type:"done",data:{sessionId:d||"",traceId:p}}}catch(c){try{u?.onChatEnd?.({traceId:p,sessionId:d,totalTurns:0,durationMs:Date.now()-m,error:c instanceof Error?c.message:"Unknown error"})}catch{}yield{type:"error",data:{message:Ie(c)}}}}function Ie(i){if(!i||!(i instanceof Error))return"Something went wrong. Please try again.";const t=i.message||"",a={overloaded_error:"The AI service is temporarily overloaded. Please try again in a moment.",rate_limit_error:"Too many requests. Please wait a moment and try again.",api_error:"The AI service encountered an error. Please try again.",authentication_error:"Authentication failed. Please check your API key configuration.",invalid_request_error:"There was a problem with the request. Please try again."},s=i;if(s.status||s.type){const e=s.error?.type||s.type||"";if(a[e])return a[e]}if(t.startsWith("{")||t.startsWith("Error: {")){try{const e=JSON.parse(t.replace(/^Error:\s*/,"")),o=e.error?.type||e.type||"";if(a[o])return a[o]}catch{}return"The AI service encountered an error. Please try again."}return t}exports.handleAgentChat=qe;