diff --git a/dist/commands/charts.js b/dist/commands/charts.js index 7d7bdc0..dc67e59 100644 --- a/dist/commands/charts.js +++ b/dist/commands/charts.js @@ -6,6 +6,66 @@ import { AmplitudeMcpClient } from "../mcp-client.js"; import { output } from "../utils/format.js"; import { extractMcpText, extractEditId } from "../utils/mcp-helpers.js"; import { handleError } from "../utils/errors.js"; +import { parseFilter, parseGroupBy, } from "../utils/filters.js"; +/** + * Build an eventsSegmentation definition from simple flags. + * The MCP query_dataset tool expects: + * { definition: { app, type, name, params: { range, events, metric, interval, ... } }, projectId } + * The `app` field and `projectId` are set by queryDataset() in mcp-client.ts, + * so we just need to build { type, name?, params }. + */ +function buildChartDefinition(opts) { + const metric = opts.metric || "uniques"; + const interval = opts.interval !== undefined ? parseInt(opts.interval, 10) : 1; + const countGroup = opts.countGroup || "User"; + const eventDef = { + event_type: opts.event, + filters: [], + group_by: [], + }; + // Parse per-event filters + if (opts.filter && opts.filter.length > 0) { + eventDef.filters = opts.filter.map((f) => parseFilter(f)); + } + // Parse per-event group-by + if (opts.groupBy && opts.groupBy.length > 0) { + eventDef.group_by = opts.groupBy.map((g) => parseGroupBy(g)); + } + const params = { + events: [eventDef], + metric, + interval, + countGroup, + groupBy: opts.groupBy && opts.groupBy.length > 0 + ? opts.groupBy.map((g) => parseGroupBy(g)) + : [], + segments: [{ conditions: [] }], + }; + // Date range — use range string or custom start/end + if (opts.range) { + params.range = opts.range; + } + else if (opts.start && opts.end) { + params.range = "custom"; + params.start = opts.start; + params.end = opts.end; + } + else if (opts.start || opts.end) { + params.range = "custom"; + if (opts.start) + params.start = opts.start; + if (opts.end) + params.end = opts.end; + } + const definition = { + type: "eventsSegmentation", + params, + }; + if (opts.name) { + definition.name = opts.name; + } + return definition; +} export function registerChartCommands(program) { const charts = program .command("charts") @@ -55,43 +115,79 @@ export function registerChartCommands(program) { }); charts .command("create") - .description("Create a chart from a JSON definition (reads from stdin or --definition)") - .option("--definition ", "Chart definition as JSON string") + .description("Create a chart from flags or a JSON definition") + // --- Raw JSON path --- + .option("--definition ", "Chart definition as JSON string (or pipe via stdin)") + // --- Flag-based path --- + .option("--event ", "Event type (e.g. _active, Purchase)") + .option("--metric ", "Metric: uniques (default), totals, average, pctdau, sums, value_avg", "uniques") + .option("--interval ", "Interval: 1=daily (default), 7=weekly, 30=monthly, 90=quarterly, -3600000=hourly", "1") + .option("--range ", 'Date range name e.g. "Last 30 Days"') + .option("--start ", "Start date (ISO or unix timestamp)") + .option("--end ", "End date (ISO or unix timestamp)") + .option("--filter ", 'Repeatable filter. Format: "user:country is US"', (v, acc) => { acc.push(v); return acc; }, []) + .option("--group-by ", 'Repeatable group-by. Format: "user:country"', (v, acc) => { acc.push(v); return acc; }, []) + .option("--count-group ", "Count group: User (default), Event, or custom", "User") + // --- Save options --- + .option("--save", "Save the chart permanently after querying") .option("--name ", "Chart name") .option("--description ", "Chart description") .option("-f, --format ", "Output format: json, compact, csv", "json") .action(async (opts) => { try { let definition; - if (opts.definition) { + if (opts.event) { + // Flag-based path + definition = buildChartDefinition({ + event: opts.event, + metric: opts.metric, + interval: opts.interval, + range: opts.range, + start: opts.start, + end: opts.end, + filter: opts.filter, + groupBy: opts.groupBy, + countGroup: opts.countGroup, + name: opts.name, + }); + } + else if (opts.definition) { definition = JSON.parse(opts.definition); } else { + // Try stdin const chunks = []; for await (const chunk of process.stdin) { chunks.push(chunk); } - definition = JSON.parse(Buffer.concat(chunks).toString("utf-8")); + const raw = Buffer.concat(chunks).toString("utf-8").trim(); + if (!raw) { + console.error("Error: Provide --event , --definition , or pipe JSON via stdin."); + process.exit(1); + } + definition = JSON.parse(raw); } const mcp = new AmplitudeMcpClient(); - console.error("Creating chart..."); - const result = await mcp.createChart(definition); - const resultText = extractMcpText(result); - if (opts.name) { - const editId = extractEditId(resultText); + console.error("Querying dataset..."); + const result = await mcp.queryDataset(definition); + const resultData = extractMcpText(result); + const shouldSave = opts.save || opts.name; + if (shouldSave) { + const editId = extractEditId(resultData); if (!editId) { - console.error("Error: Chart was created but no editId was returned. Cannot save with name."); - console.error("The chart data is printed below."); - output(resultText, opts.format); + console.error("Error: No editId returned from query_dataset. Cannot save chart."); + console.error("Query result:"); + output(resultData, opts.format); process.exit(1); } - console.error(`Saving chart as "${opts.name}"...`); - const saveResult = await mcp.saveChart(editId, opts.name, opts.description); + const chartName = opts.name || "Untitled Chart"; + console.error(`Saving chart as "${chartName}"...`); + const saveResult = await mcp.saveChart(editId, chartName, opts.description); output(extractMcpText(saveResult), opts.format); } else { - output(resultText, opts.format); - console.error("\nChart created but not named. Use --name 'Name' to save permanently."); + output(resultData, opts.format); + console.error("\nChart queried but not saved. Use --save --name 'Name' to save permanently."); } } catch (err) { diff --git a/dist/commands/charts.js.map b/dist/commands/charts.js.map index 17e98e8..ea0b783 100644 --- a/dist/commands/charts.js.map +++ b/dist/commands/charts.js.map @@ -1 +1 @@ -{"version":3,"file":"charts.js","sourceRoot":"","sources":["../../src/commands/charts.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"charts.js","sourceRoot":"","sources":["../../src/commands/charts.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/dashboards.js b/dist/commands/dashboards.js index 27652fb..f55e2a9 100644 --- a/dist/commands/dashboards.js +++ b/dist/commands/dashboards.js @@ -6,6 +6,24 @@ import { AmplitudeMcpClient } from "../mcp-client.js"; import { output } from "../utils/format.js"; import { extractMcpText } from "../utils/mcp-helpers.js"; import { handleError } from "../utils/errors.js"; +/** + * Build a rows layout array from a flat list of chart IDs. + * Lays out charts in rows of `cols` per row (default 2), width 6 each (total 12 columns). + */ +function buildRowsFromChartIds(chartIds, cols = 2) { + const itemWidth = Math.floor(12 / cols); + const rows = []; + for (let i = 0; i < chartIds.length; i += cols) { + const batch = chartIds.slice(i, i + cols); + const items = batch.map((chartId) => ({ + type: "chart", + chartId, + width: itemWidth, + })); + rows.push({ height: 500, items }); + } + return rows; +} export function registerDashboardCommands(program) { const dashboards = program .command("dashboards") @@ -41,23 +59,36 @@ export function registerDashboardCommands(program) { }); dashboards .command("create") - .description("Create a dashboard from a JSON definition (reads from stdin or --definition)") + .description("Create a dashboard from chart IDs or a JSON definition") .requiredOption("--name ", "Dashboard name") .option("--description ", "Dashboard description") - .option("--definition ", "Dashboard rows/layout as JSON string") + .option("--definition ", "Dashboard rows/layout as JSON string (or pipe via stdin)") + .option("--charts ", "List of saved chart IDs to include in the dashboard") + .option("--cols ", "Charts per row when using --charts (1-4, default 2)", "2") .option("-f, --format ", "Output format: json, compact, csv", "json") .action(async (opts) => { try { let rows; - if (opts.definition) { + if (opts.charts && opts.charts.length > 0) { + // Build layout from chart IDs + const cols = Math.max(1, Math.min(4, parseInt(opts.cols || "2", 10))); + rows = buildRowsFromChartIds(opts.charts, cols); + } + else if (opts.definition) { rows = JSON.parse(opts.definition); } else { + // Try stdin const chunks = []; for await (const chunk of process.stdin) { chunks.push(chunk); } - rows = JSON.parse(Buffer.concat(chunks).toString("utf-8")); + const raw = Buffer.concat(chunks).toString("utf-8").trim(); + if (!raw) { + console.error("Error: Provide --charts , --definition , or pipe JSON via stdin."); + process.exit(1); + } + rows = JSON.parse(raw); } if (!Array.isArray(rows)) { console.error("Error: Dashboard definition must be a JSON array of rows."); diff --git a/dist/commands/dashboards.js.map b/dist/commands/dashboards.js.map index d1b1ad7..c3525d1 100644 --- a/dist/commands/dashboards.js.map +++ b/dist/commands/dashboards.js.map @@ -1 +1 @@ -{"version":3,"file":"dashboards.js","sourceRoot":"","sources":["../../src/commands/dashboards.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"dashboards.js","sourceRoot":"","sources":["../../src/commands/dashboards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index d2f89fe..ce1275c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -20,6 +20,8 @@ import { registerDashboardCommands } from "./commands/dashboards.js"; import { registerExperimentCommands } from "./commands/experiments.js"; import { registerCallCommand } from "./commands/call.js"; import { registerToolsCommands } from "./commands/tools.js"; +import { registerFunnelCommand } from "./commands/funnel.js"; +import { registerRetentionCommand } from "./commands/retention.js"; const program = new Command(); program .name("amp") @@ -42,5 +44,7 @@ registerDashboardCommands(program); registerExperimentCommands(program); registerCallCommand(program); registerToolsCommands(program); +registerFunnelCommand(program); +registerRetentionCommand(program); program.parse(); //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map index 76e98e1..a5f2ee4 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CACV,gGAAgG,CACjG;KACA,OAAO,CAAC,WAAW,CAAC;KACpB,MAAM,CAAC,mBAAmB,EAAE,oDAAoD,CAAC,CAAC;AAErF,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,IAAI,CAAC,SAAS,CAAC;IACpD,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACpC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,OAAO,CAAC,KAAK,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CACV,gGAAgG,CACjG;KACA,OAAO,CAAC,WAAW,CAAC;KACpB,MAAM,CAAC,mBAAmB,EAAE,oDAAoD,CAAC,CAAC;AAErF,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,IAAI,CAAC,SAAS,CAAC;IACpD,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACpC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/mcp-client.d.ts b/dist/mcp-client.d.ts index 5bb05a3..b04c5bf 100644 --- a/dist/mcp-client.d.ts +++ b/dist/mcp-client.d.ts @@ -5,7 +5,7 @@ * * The MCP server exposes tools via JSON-RPC over HTTP (Streamable HTTP transport). */ -export declare const CLI_VERSION = "0.3.1"; +export declare const CLI_VERSION = "0.4.0"; export interface McpToolResult { content: Array<{ type: string; @@ -74,6 +74,7 @@ export declare class AmplitudeMcpClient { createChart(definition: Record, projectId?: string): Promise; /** * Save a chart from query_dataset results. + * The save_chart_edits MCP tool expects: { charts: [{ editId, name, description }] } */ saveChart(editId: string, name: string, description?: string): Promise; /** diff --git a/dist/mcp-client.js b/dist/mcp-client.js index fa2df2e..fe088e3 100644 --- a/dist/mcp-client.js +++ b/dist/mcp-client.js @@ -6,7 +6,7 @@ * The MCP server exposes tools via JSON-RPC over HTTP (Streamable HTTP transport). */ import { getAccessToken, getMcpBaseUrl, getOAuthConfig } from "./utils/oauth.js"; -export const CLI_VERSION = "0.3.1"; +export const CLI_VERSION = "0.4.0"; export class AmplitudeMcpClient { region; projectId; @@ -263,7 +263,12 @@ export class AmplitudeMcpClient { */ async queryDataset(definition, projectId) { const pid = projectId ?? (await this.getProjectId()); - const args = { definition }; + // MCP query_dataset expects definition.app to be set to the project ID + const def = { ...definition }; + if (pid && !def.app) { + def.app = pid; + } + const args = { definition: def }; if (pid) args.projectId = pid; return this.callTool("query_dataset", args); @@ -280,12 +285,15 @@ export class AmplitudeMcpClient { } /** * Save a chart from query_dataset results. + * The save_chart_edits MCP tool expects: { charts: [{ editId, name, description }] } */ async saveChart(editId, name, description) { return this.callTool("save_chart_edits", { - editId, - name, - ...(description && { description }), + charts: [{ + editId, + name, + description: description || "", + }], }); } /** diff --git a/dist/mcp-client.js.map b/dist/mcp-client.js.map index b03f8de..5a1b1fa 100644 --- a/dist/mcp-client.js.map +++ b/dist/mcp-client.js.map @@ -1 +1 @@ -{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../src/mcp-client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEjF,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAWnC,MAAM,OAAO,kBAAkB;IACrB,MAAM,CAAS;IACf,SAAS,CAAU;IACnB,eAAe,CAAU;IACzB,SAAS,CAAU;IACnB,WAAW,GAAG,KAAK,CAAC;IAE5B,YAAY,IAA8C;QACxD,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM;YACT,IAAI,EAAE,MAAM;gBACZ,OAAO,CAAC,GAAG,CAAC,gBAAgB;gBAC5B,KAAK,EAAE,MAAM;gBACb,IAAI,CAAC;QACP,IAAI,CAAC,SAAS;YACZ,IAAI,EAAE,SAAS;gBACf,OAAO,CAAC,GAAG,CAAC,oBAAoB;gBAChC,SAAS,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY;QAChB,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC;QAC1C,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO,IAAI,CAAC,eAAe,CAAC;QAEtD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC;YAC/D,IAAI,IAAI,EAAE,CAAC;gBACT,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAChC,MAAM,EAAE,GACN,MAAM,EAAE,KAAK;oBACb,MAAM,EAAE,SAAS;oBACjB,MAAM,EAAE,UAAU;oBAClB,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK;oBAC5B,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC5B,IAAI,EAAE,EAAE,CAAC;oBACP,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;oBAClC,OAAO,IAAI,CAAC,eAAe,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,aAAa;QACzB,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAE/C,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE3C,MAAM,IAAI,GAAG;YACX,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE;gBACN,eAAe,EAAE,YAAY;gBAC7B,YAAY,EAAE,EAAE;gBAChB,UAAU,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,WAAW,EAAE;aAC5D;SACF,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,MAAM,EAAE;YACxC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,MAAM,EAAE,qCAAqC;gBAC7C,aAAa,EAAE,UAAU,KAAK,EAAE;aACjC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACvD,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CACZ,QAAgB,EAChB,OAAgC,EAAE;QAElC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,sDAAsD;YACtD,IAAI,GAAG,YAAY,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC5E,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;gBAC3B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;gBACzB,OAAO,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAClD,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,QAAgB,EAChB,OAAgC,EAAE;QAElC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAE3B,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE3C,MAAM,IAAI,GAAG;YACX,OAAO,EAAE,KAAK;YACd,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,IAAI;aAChB;SACF,CAAC;QAEF,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,qCAAqC;YAC7C,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC,CAAC;QAEF,mDAAmD;QACnD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7C,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,MAAM,EAAE;YACxC,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,mCAAmC;QACnC,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACvD,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAE1D,0CAA0C;QAC1C,IAAI,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,8BAA8B;QAC9B,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAG/B,CAAC;QAEF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,IAAI,QAAQ,CAChB,MAAM,CAAC,KAAK,CAAC,IAAI,EACjB,MAAM,CAAC,KAAK,CAAC,OAAO,EACpB,QAAQ,CACT,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,gBAAgB,CAAC,GAAa;QAC1C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,QAAQ,GAAG,EAAE,CAAC;QAElB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACzB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAGjC,CAAC;YAEF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,MAAM,IAAI,QAAQ,CAChB,MAAM,CAAC,KAAK,CAAC,IAAI,EACjB,MAAM,CAAC,KAAK,CAAC,OAAO,EACpB,KAAK,CACN,CAAC;YACJ,CAAC;YAED,OAAO,MAAM,CAAC,MAAM,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,QAAQ;gBAAE,MAAM,GAAG,CAAC;YACvC,6BAA6B;YAC7B,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;aAC5C,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE3C,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,qCAAqC;YAC7C,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC,CAAC;QAEF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7C,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,MAAM,EAAE;YACxC,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,OAAO,EAAE,KAAK;gBACd,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,EAAE;aACX,CAAC;SACH,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACvD,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,yEAAyE;IAEzE;;OAEG;IACH,KAAK,CAAC,MAAM,CACV,KAAa,EACb,WAAsB,EACtB,KAAc;QAEd,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAC7B,KAAK;YACL,GAAG,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,CAAC;YACnC,GAAG,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,CAAC;SACxB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,QAAkB;QAChC,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,WAAmB;QACpC,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IACzD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAChB,UAAmC,EACnC,SAAkB;QAElB,MAAM,GAAG,GAAG,SAAS,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACrD,uEAAuE;QACvE,MAAM,GAAG,GAAG,EAAE,GAAG,UAAU,EAAE,CAAC;QAC9B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACpB,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,GAA4B,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;QAC1D,IAAI,GAAG;YAAE,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CACf,UAAmC,EACnC,SAAkB;QAElB,MAAM,GAAG,GAAG,SAAS,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACrD,MAAM,IAAI,GAA4B,EAAE,UAAU,EAAE,CAAC;QACrD,IAAI,GAAG;YAAE,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS,CACb,MAAc,EACd,IAAY,EACZ,WAAoB;QAEpB,OAAO,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE;YACvC,MAAM,EAAE,CAAC;oBACP,MAAM;oBACN,IAAI;oBACJ,WAAW,EAAE,WAAW,IAAI,EAAE;iBAC/B,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CACnB,IAAY,EACZ,IAAe,EACf,WAAoB;QAEpB,OAAO,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE;YACvC,IAAI;YACJ,IAAI;YACJ,GAAG,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,CAAC;SACpC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,SAAiB;QACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,sBAAsB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,OAAe;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,aAAuB;QAC1C,OAAO,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE;YACtC,aAAa;SACd,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,YAAoB;QACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE;YACvC,YAAY;SACb,CAAC,CAAC;IACL,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,KAAK;IAExB;IACA;IACA;IAHT,YACS,IAAY,EACZ,MAAc,EACd,IAAY;QAEnB,KAAK,CAAC,cAAc,IAAI,aAAa,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC;QAJjD,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QAGnB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"} \ No newline at end of file diff --git a/dist/utils/mcp-helpers.js b/dist/utils/mcp-helpers.js index 9e93ab8..695fbad 100644 --- a/dist/utils/mcp-helpers.js +++ b/dist/utils/mcp-helpers.js @@ -33,6 +33,8 @@ export function extractEditId(data) { const obj = data; if (typeof obj.editId === "string") return obj.editId; + if (typeof obj.chartEditId === "string") + return obj.chartEditId; if (typeof obj.edit_id === "string") return obj.edit_id; for (const key of Object.keys(obj)) { diff --git a/dist/utils/mcp-helpers.js.map b/dist/utils/mcp-helpers.js.map index e94b7a9..87496ce 100644 --- a/dist/utils/mcp-helpers.js.map +++ b/dist/utils/mcp-helpers.js.map @@ -1 +1 @@ -{"version":3,"file":"mcp-helpers.js","sourceRoot":"","sources":["../../src/utils/mcp-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAqB;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC;SAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAK,CAAC,CAAC;IAEvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC/D,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC5B,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC;QACtD,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,OAAO,CAAC;QACxD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACrB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;gBACjC,IAAI,KAAK;oBAAE,OAAO,KAAK,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"} \ No newline at end of file +{"version":3,"file":"mcp-helpers.js","sourceRoot":"","sources":["../../src/utils/mcp-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAqB;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC;SAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAK,CAAC,CAAC;IAEvB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC/D,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC5B,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC;QACtD,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,WAAW,CAAC;QAChE,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,OAAO,CAAC;QACxD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACrB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;gBACjC,IAAI,KAAK;oBAAE,OAAO,KAAK,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e7f14b6..af89bcb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "amplitude-cli", - "version": "0.3.2", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "amplitude-cli", - "version": "0.3.2", + "version": "0.4.0", "license": "MIT", "dependencies": { "commander": "^13.1.0" diff --git a/package.json b/package.json index 767b408..3efa7a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "amplitude-cli", - "version": "0.3.2", + "version": "0.4.0", "description": "CLI for Amplitude analytics via MCP server. OAuth only. Designed for AI agents and humans.", "type": "module", "bin": { diff --git a/src/commands/charts.ts b/src/commands/charts.ts index 7448996..95c4096 100644 --- a/src/commands/charts.ts +++ b/src/commands/charts.ts @@ -8,6 +8,86 @@ import { AmplitudeMcpClient } from "../mcp-client.js"; import { output, type OutputFormat } from "../utils/format.js"; import { extractMcpText, extractEditId } from "../utils/mcp-helpers.js"; import { handleError } from "../utils/errors.js"; +import { + parseFilter, + parseGroupBy, + buildDateRange, +} from "../utils/filters.js"; + +/** + * Build an eventsSegmentation definition from simple flags. + * The MCP query_dataset tool expects: + * { definition: { app, type, name, params: { range, events, metric, interval, ... } }, projectId } + * The `app` field and `projectId` are set by queryDataset() in mcp-client.ts, + * so we just need to build { type, name?, params }. + */ +function buildChartDefinition(opts: { + event: string; + metric?: string; + interval?: string; + range?: string; + start?: string; + end?: string; + filter?: string[]; + groupBy?: string[]; + countGroup?: string; + name?: string; +}): Record { + const metric = opts.metric || "uniques"; + const interval = opts.interval !== undefined ? parseInt(opts.interval, 10) : 1; + const countGroup = opts.countGroup || "User"; + + const eventDef: Record = { + event_type: opts.event, + filters: [] as unknown[], + group_by: [] as unknown[], + }; + + // Parse per-event filters + if (opts.filter && opts.filter.length > 0) { + eventDef.filters = opts.filter.map((f) => parseFilter(f)); + } + + // Parse per-event group-by + if (opts.groupBy && opts.groupBy.length > 0) { + eventDef.group_by = opts.groupBy.map((g) => parseGroupBy(g)); + } + + const params: Record = { + events: [eventDef], + metric, + interval, + countGroup, + groupBy: opts.groupBy && opts.groupBy.length > 0 + ? opts.groupBy.map((g) => parseGroupBy(g)) + : [], + segments: [{ conditions: [] }], + }; + + // Date range — use range string or custom start/end + if (opts.range) { + params.range = opts.range; + } else if (opts.start && opts.end) { + params.range = "custom"; + params.start = opts.start; + params.end = opts.end; + } else if (opts.start || opts.end) { + params.range = "custom"; + if (opts.start) params.start = opts.start; + if (opts.end) params.end = opts.end; + } + + const definition: Record = { + type: "eventsSegmentation", + params, + }; + + if (opts.name) { + definition.name = opts.name; + } + + return definition; +} export function registerChartCommands(program: Command): void { const charts = program @@ -59,8 +139,39 @@ export function registerChartCommands(program: Command): void { charts .command("create") - .description("Create a chart from a JSON definition (reads from stdin or --definition)") - .option("--definition ", "Chart definition as JSON string") + .description("Create a chart from flags or a JSON definition") + // --- Raw JSON path --- + .option("--definition ", "Chart definition as JSON string (or pipe via stdin)") + // --- Flag-based path --- + .option("--event ", "Event type (e.g. _active, Purchase)") + .option( + "--metric ", + "Metric: uniques (default), totals, average, pctdau, sums, value_avg", + "uniques" + ) + .option( + "--interval ", + "Interval: 1=daily (default), 7=weekly, 30=monthly, 90=quarterly, -3600000=hourly", + "1" + ) + .option("--range ", 'Date range name e.g. "Last 30 Days"') + .option("--start ", "Start date (ISO or unix timestamp)") + .option("--end ", "End date (ISO or unix timestamp)") + .option( + "--filter ", + 'Repeatable filter. Format: "user:country is US"', + (v: string, acc: string[]) => { acc.push(v); return acc; }, + [] as string[] + ) + .option( + "--group-by ", + 'Repeatable group-by. Format: "user:country"', + (v: string, acc: string[]) => { acc.push(v); return acc; }, + [] as string[] + ) + .option("--count-group ", "Count group: User (default), Event, or custom", "User") + // --- Save options --- + .option("--save", "Save the chart permanently after querying") .option("--name ", "Chart name") .option("--description ", "Chart description") .option("-f, --format ", "Output format: json, compact, csv", "json") @@ -68,36 +179,59 @@ export function registerChartCommands(program: Command): void { try { let definition: Record; - if (opts.definition) { + if (opts.event) { + // Flag-based path + definition = buildChartDefinition({ + event: opts.event, + metric: opts.metric, + interval: opts.interval, + range: opts.range, + start: opts.start, + end: opts.end, + filter: opts.filter, + groupBy: opts.groupBy, + countGroup: opts.countGroup, + name: opts.name, + }); + } else if (opts.definition) { definition = JSON.parse(opts.definition); } else { + // Try stdin const chunks: Buffer[] = []; for await (const chunk of process.stdin) { chunks.push(chunk as Buffer); } - definition = JSON.parse(Buffer.concat(chunks).toString("utf-8")); + const raw = Buffer.concat(chunks).toString("utf-8").trim(); + if (!raw) { + console.error("Error: Provide --event , --definition , or pipe JSON via stdin."); + process.exit(1); + } + definition = JSON.parse(raw); } const mcp = new AmplitudeMcpClient(); - console.error("Creating chart..."); - const result = await mcp.createChart(definition); - const resultText = extractMcpText(result); + console.error("Querying dataset..."); + const result = await mcp.queryDataset(definition); + const resultData = extractMcpText(result); + + const shouldSave = opts.save || opts.name; - if (opts.name) { - const editId = extractEditId(resultText); + if (shouldSave) { + const editId = extractEditId(resultData); if (!editId) { - console.error("Error: Chart was created but no editId was returned. Cannot save with name."); - console.error("The chart data is printed below."); - output(resultText, opts.format as OutputFormat); + console.error("Error: No editId returned from query_dataset. Cannot save chart."); + console.error("Query result:"); + output(resultData, opts.format as OutputFormat); process.exit(1); } - console.error(`Saving chart as "${opts.name}"...`); - const saveResult = await mcp.saveChart(editId, opts.name, opts.description); + const chartName = opts.name || "Untitled Chart"; + console.error(`Saving chart as "${chartName}"...`); + const saveResult = await mcp.saveChart(editId, chartName, opts.description); output(extractMcpText(saveResult), opts.format as OutputFormat); } else { - output(resultText, opts.format as OutputFormat); - console.error("\nChart created but not named. Use --name 'Name' to save permanently."); + output(resultData, opts.format as OutputFormat); + console.error("\nChart queried but not saved. Use --save --name 'Name' to save permanently."); } } catch (err) { handleError(err); diff --git a/src/commands/dashboards.ts b/src/commands/dashboards.ts index 4113119..0885252 100644 --- a/src/commands/dashboards.ts +++ b/src/commands/dashboards.ts @@ -9,6 +9,30 @@ import { output, type OutputFormat } from "../utils/format.js"; import { extractMcpText } from "../utils/mcp-helpers.js"; import { handleError } from "../utils/errors.js"; +/** + * Build a rows layout array from a flat list of chart IDs. + * Lays out charts in rows of `cols` per row (default 2), width 6 each (total 12 columns). + */ +function buildRowsFromChartIds( + chartIds: string[], + cols: number = 2 +): Record[] { + const itemWidth = Math.floor(12 / cols); + const rows: Record[] = []; + + for (let i = 0; i < chartIds.length; i += cols) { + const batch = chartIds.slice(i, i + cols); + const items = batch.map((chartId) => ({ + type: "chart", + chartId, + width: itemWidth, + })); + rows.push({ height: 500, items }); + } + + return rows; +} + export function registerDashboardCommands(program: Command): void { const dashboards = program .command("dashboards") @@ -45,23 +69,42 @@ export function registerDashboardCommands(program: Command): void { dashboards .command("create") - .description("Create a dashboard from a JSON definition (reads from stdin or --definition)") + .description("Create a dashboard from chart IDs or a JSON definition") .requiredOption("--name ", "Dashboard name") .option("--description ", "Dashboard description") - .option("--definition ", "Dashboard rows/layout as JSON string") + .option("--definition ", "Dashboard rows/layout as JSON string (or pipe via stdin)") + .option( + "--charts ", + "List of saved chart IDs to include in the dashboard" + ) + .option( + "--cols ", + "Charts per row when using --charts (1-4, default 2)", + "2" + ) .option("-f, --format ", "Output format: json, compact, csv", "json") .action(async (opts) => { try { let rows: unknown[]; - if (opts.definition) { + if (opts.charts && opts.charts.length > 0) { + // Build layout from chart IDs + const cols = Math.max(1, Math.min(4, parseInt(opts.cols || "2", 10))); + rows = buildRowsFromChartIds(opts.charts as string[], cols); + } else if (opts.definition) { rows = JSON.parse(opts.definition); } else { + // Try stdin const chunks: Buffer[] = []; for await (const chunk of process.stdin) { chunks.push(chunk as Buffer); } - rows = JSON.parse(Buffer.concat(chunks).toString("utf-8")); + const raw = Buffer.concat(chunks).toString("utf-8").trim(); + if (!raw) { + console.error("Error: Provide --charts , --definition , or pipe JSON via stdin."); + process.exit(1); + } + rows = JSON.parse(raw); } if (!Array.isArray(rows)) { diff --git a/src/commands/funnel.ts b/src/commands/funnel.ts new file mode 100644 index 0000000..4158f7e --- /dev/null +++ b/src/commands/funnel.ts @@ -0,0 +1,137 @@ +/** + * Top-level `amp funnel` command — build and query funnel charts. + * Friendlier alternative to `amp query funnel`. + */ + +import { Command } from "commander"; +import { AmplitudeMcpClient } from "../mcp-client.js"; +import { output, type OutputFormat } from "../utils/format.js"; +import { extractMcpText, extractEditId } from "../utils/mcp-helpers.js"; +import { handleError } from "../utils/errors.js"; +import { + parseFilter, + parseGroupBy, + buildDateRange, + parseConversionWindow, +} from "../utils/filters.js"; + +export function registerFunnelCommand(program: Command): void { + program + .command("funnel [steps...]") + .description( + 'Query a funnel chart. Pass event types as positional args.\n\n Example: amp funnel "Sign Up" "Add to Cart" "Purchase" --range "Last 30 Days"' + ) + .option( + "--conversion-window ", + 'Conversion window e.g. "7d", "24h", "30m"', + "7d" + ) + .option( + "--order ", + "Funnel order: this_order (default), any_order, exact_order", + "this_order" + ) + .option("--range ", 'Date range name e.g. "Last 30 Days"') + .option("--start ", "Start date (ISO or unix timestamp)") + .option("--end ", "End date (ISO or unix timestamp)") + .option( + "--filter ", + 'Repeatable filter. Format: "user:country is US"', + (v: string, acc: string[]) => { acc.push(v); return acc; }, + [] as string[] + ) + .option( + "--group-by ", + 'Repeatable group-by. Format: "user:country"', + (v: string, acc: string[]) => { acc.push(v); return acc; }, + [] as string[] + ) + .option("--count-group ", "Count group: User (default), Event, or custom", "User") + .option("--save", "Save the chart permanently after querying") + .option("--name ", "Chart name") + .option("--description ", "Chart description") + .option("-f, --format ", "Output format: json, compact, csv", "json") + .action(async (steps: string[], opts) => { + try { + if (!steps || steps.length < 2) { + console.error("Error: Funnel requires at least 2 event steps."); + console.error(" Example: amp funnel \"Sign Up\" \"Purchase\" --range \"Last 30 Days\""); + process.exit(1); + } + + const countGroup = opts.countGroup || "User"; + + // Build events array for funnel + const events = steps.map((step: string) => ({ + event_type: step, + filters: [] as unknown[], + group_by: [] as unknown[], + })); + + // Parse filters — apply to first event and segments + if (opts.filter && opts.filter.length > 0) { + const filters = opts.filter.map((f: string) => parseFilter(f)); + events[0].filters = filters; + } + + // Parse conversion window + const conversionWindow = parseConversionWindow(opts.conversionWindow || "7d"); + + const params: Record = { + events, + countGroup, + groupBy: opts.groupBy && opts.groupBy.length > 0 + ? opts.groupBy.map((g: string) => parseGroupBy(g)) + : [], + segments: [{ conditions: [] }], + order: opts.order || "this_order", + conversionWindow: conversionWindow, + }; + + // Date range + if (opts.range) { + params.range = opts.range; + } else if (opts.start && opts.end) { + params.range = "custom"; + params.start = opts.start; + params.end = opts.end; + } + + const definition: Record = { + type: "funnels", + params, + }; + + if (opts.name) { + definition.name = opts.name; + } + + const mcp = new AmplitudeMcpClient(); + + console.error(`Querying funnel (${steps.length} steps)...`); + const result = await mcp.queryDataset(definition); + const resultData = extractMcpText(result); + + const shouldSave = opts.save || opts.name; + + if (shouldSave) { + const editId = extractEditId(resultData); + if (!editId) { + console.error("Error: No editId returned from query_dataset. Cannot save chart."); + console.error("Query result:"); + output(resultData, opts.format as OutputFormat); + process.exit(1); + } + const chartName = opts.name || "Untitled Funnel"; + console.error(`Saving funnel as "${chartName}"...`); + const saveResult = await mcp.saveChart(editId, chartName, opts.description); + output(extractMcpText(saveResult), opts.format as OutputFormat); + } else { + output(resultData, opts.format as OutputFormat); + console.error("\nFunnel queried but not saved. Use --save --name 'Name' to save permanently."); + } + } catch (err) { + handleError(err); + } + }); +} diff --git a/src/commands/retention.ts b/src/commands/retention.ts new file mode 100644 index 0000000..ac7ef1f --- /dev/null +++ b/src/commands/retention.ts @@ -0,0 +1,144 @@ +/** + * Top-level `amp retention` command — build and query retention charts. + * Friendlier alternative to `amp query retention`. + */ + +import { Command } from "commander"; +import { AmplitudeMcpClient } from "../mcp-client.js"; +import { output, type OutputFormat } from "../utils/format.js"; +import { extractMcpText, extractEditId } from "../utils/mcp-helpers.js"; +import { handleError } from "../utils/errors.js"; +import { + parseFilter, + parseGroupBy, + buildDateRange, + parseBrackets, +} from "../utils/filters.js"; + +export function registerRetentionCommand(program: Command): void { + program + .command("retention") + .description( + 'Query a retention chart.\n\n Example: amp retention --start-event _new --return-event _active --range "Last 90 Days"' + ) + .requiredOption("--start-event ", "Starting event type (e.g. _new, Sign Up)") + .requiredOption("--return-event ", "Return event type (e.g. _active, Purchase)") + .option( + "--method ", + "Retention method: nday (default), rolling, bracket", + "nday" + ) + .option( + "--brackets ", + 'Bracket ranges for bracket method e.g. "0-1,1-5,5-12,12-21"' + ) + .option( + "--interval ", + "Interval: 1=daily (default), 7=weekly, 30=monthly", + "1" + ) + .option("--range ", 'Date range name e.g. "Last 90 Days"') + .option("--start ", "Start date (ISO or unix timestamp)") + .option("--end ", "End date (ISO or unix timestamp)") + .option( + "--filter ", + 'Repeatable filter. Format: "user:country is US"', + (v: string, acc: string[]) => { acc.push(v); return acc; }, + [] as string[] + ) + .option( + "--group-by ", + 'Repeatable group-by. Format: "user:country"', + (v: string, acc: string[]) => { acc.push(v); return acc; }, + [] as string[] + ) + .option("--count-group ", "Count group: User (default), Event, or custom", "User") + .option("--save", "Save the chart permanently after querying") + .option("--name ", "Chart name") + .option("--description ", "Chart description") + .option("-f, --format ", "Output format: json, compact, csv", "json") + .action(async (opts) => { + try { + const countGroup = opts.countGroup || "User"; + const interval = parseInt(opts.interval || "1", 10); + + const startEventDef: Record = { + event_type: opts.startEvent, + filters: [] as unknown[], + group_by: [] as unknown[], + }; + const retentionEventDef: Record = { + event_type: opts.returnEvent, + filters: [] as unknown[], + group_by: [] as unknown[], + }; + + // Parse filters — apply to startEvent + if (opts.filter && opts.filter.length > 0) { + startEventDef.filters = opts.filter.map((f: string) => parseFilter(f)); + } + + const params: Record = { + startEvent: startEventDef, + retentionEvents: [retentionEventDef], + retentionMethod: opts.method || "nday", + countGroup, + interval, + groupBy: opts.groupBy && opts.groupBy.length > 0 + ? opts.groupBy.map((g: string) => parseGroupBy(g)) + : [], + segments: [{ conditions: [] }], + }; + + // Brackets for bracket method + if (opts.method === "bracket" && opts.brackets) { + params.retentionBrackets = parseBrackets(opts.brackets); + } + + // Date range + if (opts.range) { + params.range = opts.range; + } else if (opts.start && opts.end) { + params.range = "custom"; + params.start = opts.start; + params.end = opts.end; + } + + const definition: Record = { + type: "retention", + params, + }; + + if (opts.name) { + definition.name = opts.name; + } + + const mcp = new AmplitudeMcpClient(); + + console.error(`Querying retention (${opts.startEvent} → ${opts.returnEvent})...`); + const result = await mcp.queryDataset(definition); + const resultData = extractMcpText(result); + + const shouldSave = opts.save || opts.name; + + if (shouldSave) { + const editId = extractEditId(resultData); + if (!editId) { + console.error("Error: No editId returned from query_dataset. Cannot save chart."); + console.error("Query result:"); + output(resultData, opts.format as OutputFormat); + process.exit(1); + } + const chartName = opts.name || "Untitled Retention"; + console.error(`Saving retention chart as "${chartName}"...`); + const saveResult = await mcp.saveChart(editId, chartName, opts.description); + output(extractMcpText(saveResult), opts.format as OutputFormat); + } else { + output(resultData, opts.format as OutputFormat); + console.error("\nRetention queried but not saved. Use --save --name 'Name' to save permanently."); + } + } catch (err) { + handleError(err); + } + }); +} diff --git a/src/index.ts b/src/index.ts index a6580ac..e53f342 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,6 +22,8 @@ import { registerDashboardCommands } from "./commands/dashboards.js"; import { registerExperimentCommands } from "./commands/experiments.js"; import { registerCallCommand } from "./commands/call.js"; import { registerToolsCommands } from "./commands/tools.js"; +import { registerFunnelCommand } from "./commands/funnel.js"; +import { registerRetentionCommand } from "./commands/retention.js"; const program = new Command(); @@ -50,5 +52,7 @@ registerDashboardCommands(program); registerExperimentCommands(program); registerCallCommand(program); registerToolsCommands(program); +registerFunnelCommand(program); +registerRetentionCommand(program); program.parse(); diff --git a/src/mcp-client.ts b/src/mcp-client.ts index 12b1134..a9cdfda 100644 --- a/src/mcp-client.ts +++ b/src/mcp-client.ts @@ -8,7 +8,7 @@ import { getAccessToken, getMcpBaseUrl, getOAuthConfig } from "./utils/oauth.js"; -export const CLI_VERSION = "0.3.2"; +export const CLI_VERSION = "0.4.0"; export interface McpToolResult { content: Array<{ @@ -340,7 +340,12 @@ export class AmplitudeMcpClient { projectId?: string ): Promise { const pid = projectId ?? (await this.getProjectId()); - const args: Record = { definition }; + // MCP query_dataset expects definition.app to be set to the project ID + const def = { ...definition }; + if (pid && !def.app) { + def.app = pid; + } + const args: Record = { definition: def }; if (pid) args.projectId = pid; return this.callTool("query_dataset", args); } @@ -360,6 +365,7 @@ export class AmplitudeMcpClient { /** * Save a chart from query_dataset results. + * The save_chart_edits MCP tool expects: { charts: [{ editId, name, description }] } */ async saveChart( editId: string, @@ -367,9 +373,11 @@ export class AmplitudeMcpClient { description?: string ): Promise { return this.callTool("save_chart_edits", { - editId, - name, - ...(description && { description }), + charts: [{ + editId, + name, + description: description || "", + }], }); } diff --git a/src/utils/filters.ts b/src/utils/filters.ts new file mode 100644 index 0000000..2913435 --- /dev/null +++ b/src/utils/filters.ts @@ -0,0 +1,168 @@ +/** + * Filter and group-by DSL parsers for Amplitude chart/funnel/retention commands. + * + * Filter format: ": [,value2,...]" + * Group-by format: ":" + */ + +export interface AmplitudeFilter { + group_type: string; + subprop_key: string; + subprop_op: string; + subprop_type: string; + subprop_value: string[]; +} + +export interface AmplitudeGroupBy { + type: string; + value: string; + group_type: string; +} + +const OPERATORS = [ + "is not", + "does not contain", + "greater or equal", + "less or equal", + "set is not", + "set is", + "contains", + "greater", + "less", + "is", +]; + +/** + * Parse a filter expression like "user:country is US" or "event:platform is iOS,Android" + */ +export function parseFilter(expr: string): AmplitudeFilter { + const trimmed = expr.trim(); + + // Find the scope prefix: "user:" or "event:" + const colonIdx = trimmed.indexOf(":"); + if (colonIdx === -1) { + throw new Error(`Invalid filter expression (missing scope): "${expr}"`); + } + + const scope = trimmed.slice(0, colonIdx).toLowerCase(); + if (scope !== "user" && scope !== "event") { + throw new Error(`Invalid filter scope "${scope}" — must be "user" or "event": "${expr}"`); + } + + const rest = trimmed.slice(colonIdx + 1); // everything after "user:" or "event:" + + // Find operator (try longest first to avoid partial matches) + let matchedOp: string | null = null; + let matchedIdx = -1; + + for (const op of OPERATORS) { + const idx = rest.indexOf(` ${op} `); + if (idx !== -1) { + matchedOp = op; + matchedIdx = idx; + break; + } + // Also handle operator at end (no trailing value, edge case) + const trailingIdx = rest.lastIndexOf(` ${op}`); + if (trailingIdx !== -1 && trailingIdx + 1 + op.length === rest.length) { + matchedOp = op; + matchedIdx = trailingIdx; + break; + } + } + + if (!matchedOp || matchedIdx === -1) { + throw new Error(`No valid operator found in filter expression: "${expr}". Supported operators: ${OPERATORS.join(", ")}`); + } + + const propKey = rest.slice(0, matchedIdx).trim(); + const valueStr = rest.slice(matchedIdx + 1 + matchedOp.length).trim(); + const values = valueStr ? valueStr.split(",").map((v) => v.trim()).filter(Boolean) : []; + + const group_type = scope === "user" ? "User" : "User"; // always "User" for group_type + const subprop_type = scope === "user" ? "user" : "event"; + + return { + group_type, + subprop_key: propKey, + subprop_op: matchedOp, + subprop_type, + subprop_value: values, + }; +} + +/** + * Parse a group-by expression like "user:country" or "event:platform" + */ +export function parseGroupBy(expr: string): AmplitudeGroupBy { + const trimmed = expr.trim(); + const colonIdx = trimmed.indexOf(":"); + if (colonIdx === -1) { + throw new Error(`Invalid group-by expression (missing scope): "${expr}"`); + } + + const scope = trimmed.slice(0, colonIdx).toLowerCase(); + if (scope !== "user" && scope !== "event") { + throw new Error(`Invalid group-by scope "${scope}" — must be "user" or "event": "${expr}"`); + } + + const propValue = trimmed.slice(colonIdx + 1); + + return { + type: scope, + value: propValue, + group_type: scope === "user" ? "User" : "Event", + }; +} + +/** + * Parse a conversion window like "7d" or "24h" into { value, unit } + */ +export function parseConversionWindow(duration: string): { value: number; unit: string } { + const match = duration.trim().match(/^(\d+)(d|h|m|w)$/i); + if (!match) { + throw new Error(`Invalid conversion window "${duration}". Expected format: "7d", "24h", "30m", "2w"`); + } + const value = parseInt(match[1], 10); + const suffix = match[2].toLowerCase(); + const unitMap: Record = { + h: "hour", + d: "day", + w: "week", + m: "month", + }; + return { value, unit: unitMap[suffix] }; +} + +/** + * Parse bracket ranges like "0-1,1-5,5-12,12-21" into [[0,1],[1,5],[5,12],[12,21]] + */ +export function parseBrackets(ranges: string): number[][] { + return ranges.split(",").map((range) => { + const parts = range.trim().split("-"); + if (parts.length !== 2) { + throw new Error(`Invalid bracket range "${range}". Expected format like "0-1"`); + } + return [parseInt(parts[0], 10), parseInt(parts[1], 10)]; + }); +} + +/** + * Build date_range object from --range or --start/--end flags + */ +export function buildDateRange( + range?: string, + start?: string, + end?: string +): Record | undefined { + if (range) { + return { type: "range", name: range }; + } + if (start || end) { + const obj: Record = { type: "custom" }; + if (start) obj.start = start; + if (end) obj.end = end; + return obj; + } + return undefined; +} diff --git a/src/utils/mcp-helpers.ts b/src/utils/mcp-helpers.ts index 4575ab5..31ed9eb 100644 --- a/src/utils/mcp-helpers.ts +++ b/src/utils/mcp-helpers.ts @@ -35,6 +35,7 @@ export function extractEditId(data: unknown): string | null { if (typeof data === "object" && data !== null) { const obj = data as Record; if (typeof obj.editId === "string") return obj.editId; + if (typeof obj.chartEditId === "string") return obj.chartEditId; if (typeof obj.edit_id === "string") return obj.edit_id; for (const key of Object.keys(obj)) { const val = obj[key];