diff --git a/packages/ai/src/tools/visualization-tools/dashboards/helpers/dashboard-tool-description.txt b/packages/ai/src/tools/visualization-tools/dashboards/helpers/dashboard-tool-description.txt index ebe81ee04..4ddaff0a7 100644 --- a/packages/ai/src/tools/visualization-tools/dashboards/helpers/dashboard-tool-description.txt +++ b/packages/ai/src/tools/visualization-tools/dashboards/helpers/dashboard-tool-description.txt @@ -2,7 +2,7 @@ Creates dashboard configuration files with YAML content following the dashboard ## COMPLETE DASHBOARD YAML SCHEMA -# DASHBOARD CONFIGURATION - YML STRUCTURE +`# DASHBOARD CONFIGURATION - YML STRUCTURE # ---------------------------------------- # Required fields: # @@ -32,5 +32,96 @@ Creates dashboard configuration files with YAML content following the dashboard # 8. String values generally should NOT use quotes unless they contain special characters (like :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, `) or start/end with whitespace. # 9. If a string contains special characters or needs to preserve leading/trailing whitespace, enclose it in double quotes (`"`). Example: `name: "Sales & Marketing Dashboard"` # 10. Avoid special characters in names and descriptions where possible, but if needed, use quotes as described in rule 9. UUIDs should NEVER be quoted. +# ---------------------------------------- + +type: object +name: Dashboard Configuration Schema +description: Specifies the structure and constraints of a dashboard config file. +properties: + name: + type: string + description: The title of the dashboard (e.g. Sales & Marketing Dashboard) - do NOT use quotes + description: + type: string + description: A description of the dashboard, its metrics, and its purpose + rows: + type: array + description: Array of row objects, each containing metric items + items: + type: object + properties: + id: + type: integer + description: This is just an integer representing the row number 1 -> n + items: + type: array + description: Array of metrics to display in this row (max 4 items) + maxItems: 4 + items: + type: object + properties: + id: + type: string + description: UUIDv4 identifier of an existing metric + required: + - id + column_sizes: + type: array + description: Required array of column sizes (must sum to exactly 12) + items: + type: integer + minimum: 3 + maximum: 12 + required: + - id + - items + - column_sizes +required: + - name + - description + - rows` + +**Key Requirements:** +- `name`: Dashboard title (no underscores, descriptive name) +- `description`: Natural language explanation of the dashboard's purpose and contents +- `rows`: Array of row objects, each with unique ID, items (metric UUIDs), and column_sizes +- Each row must have 1-4 items maximum +- `column_sizes` must sum to exactly 12 and each size must be >= 3 +- All metric IDs must be valid UUIDs of existing metrics +- Row IDs must be unique integers (typically 1, 2, 3, etc.) + +**Dashboard Layout Rules:** +- Grid system: Each row spans 12 columns total +- Column sizes: [12] = full width, [6,6] = two halves, [4,4,4] = three thirds, [3,3,3,3] = four quarters +- Common layouts: [12], [6,6], [4,8], [3,9], [4,4,4], [3,3,6], [3,3,3,3] +- Each metric item gets the corresponding column size in the same position + +**Example Structure:** +```yaml +name: Sales Performance Dashboard +description: Comprehensive overview of sales metrics including revenue, conversions, and geographic performance +rows: + - id: 1 + items: + - id: 550e8400-e29b-41d4-a716-446655440001 + column_sizes: + - 12 + - id: 2 + items: + - id: 550e8400-e29b-41d4-a716-446655440002 + - id: 550e8400-e29b-41d4-a716-446655440003 + column_sizes: + - 6 + - 6 + - id: 3 + items: + - id: 550e8400-e29b-41d4-a716-446655440004 + - id: 550e8400-e29b-41d4-a716-446655440005 + - id: 550e8400-e29b-41d4-a716-446655440006 + column_sizes: + - 4 + - 4 + - 4 +``` **CRITICAL:** Follow the schema exactly - all metric IDs must reference existing metrics, column sizes must sum to 12, and row IDs must be unique. The tool will validate all metric references against the database. \ No newline at end of file diff --git a/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-description.test.ts b/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-description.test.ts new file mode 100644 index 000000000..2a214fe73 --- /dev/null +++ b/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-description.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from 'vitest'; +import dashboardToolDescription from './dashboard-tool-description.txt'; +import { getDashboardToolDescription } from './get-dashboard-tool-description'; + +describe('getDashboardToolDescription', () => { + it('should return the dashboard tool description from the .txt file', () => { + const description = getDashboardToolDescription(); + + // Verify it returns a non-empty string + expect(typeof description).toBe('string'); + expect(description.length).toBeGreaterThan(0); + + // Verify it contains the expected content from the actual .txt file + expect(description).toContain('Creates dashboard configuration files'); + expect(description).toContain('COMPLETE DASHBOARD YAML SCHEMA'); + expect(description).toContain('DASHBOARD CONFIGURATION - YML STRUCTURE'); + }); + + it('should have no template variables in the .txt file', () => { + const content = dashboardToolDescription; + + // Find any template variables in the file + const templateVariablePattern = /\{\{([^}]+)\}\}/g; + const foundVariables = new Set(); + + const matches = Array.from(content.matchAll(templateVariablePattern)); + for (const match of matches) { + if (match[1]) { + foundVariables.add(match[1]); + } + } + + // Should have no template variables since this tool just returns the raw content + expect(foundVariables.size).toBe(0); + + // If any variables are found, list them for debugging + if (foundVariables.size > 0) { + console.error('Found unexpected template variables:', Array.from(foundVariables)); + } + }); +}); diff --git a/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-description.ts b/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-description.ts index 2a6e2fc28..d725420ae 100644 --- a/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-description.ts +++ b/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-description.ts @@ -1,13 +1,5 @@ import dashboardToolDescription from './dashboard-tool-description.txt'; -/** - * Template parameters for the dashboard tool prompt - */ -export interface DashboardToolTemplateParams { - dataSourceSyntax: string; - date: string; -} - /** * Export the template function for use in dashboard tool */ diff --git a/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-prompt.test.ts b/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-prompt.test.ts deleted file mode 100644 index e1911b1bd..000000000 --- a/packages/ai/src/tools/visualization-tools/dashboards/helpers/get-dashboard-tool-prompt.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import dashboardToolDescription from './dashboard-tool-description.txt'; -import { getDashboardToolDescription } from './get-dashboard-tool-description'; - -describe('Dashboard Tool Prompt Instructions', () => { - it('should validate template file has no template variables', () => { - const content = dashboardToolDescription; - - // Find any template variables in the file - const templateVariablePattern = /\{\{([^}]+)\}\}/g; - const foundVariables = new Set(); - - const matches = Array.from(content.matchAll(templateVariablePattern)); - for (const match of matches) { - if (match[1] && match[1] !== 'variable') { - foundVariables.add(match[1]); - } - } - - // Should have no template variables since this tool just fetches the raw content - expect(foundVariables.size).toBe(0); - expect(content.length).toBeGreaterThan(0); - }); - - it('should load the dashboard tool description correctly', () => { - const result = getDashboardToolDescription(); - - expect(result).toBeDefined(); - expect(typeof result).toBe('string'); - expect(result.length).toBeGreaterThan(0); - - // Should return the raw content from the text file - expect(result).toBe(dashboardToolDescription); - }); - - it('should contain expected sections from the dashboard description', () => { - const result = getDashboardToolDescription(); - - // Check for key sections that should be in the dashboard description - expect(result).toContain('Creates dashboard configuration files'); - expect(result).toContain('COMPLETE DASHBOARD YAML SCHEMA'); - expect(result).toContain('DASHBOARD CONFIGURATION - YML STRUCTURE'); - expect(result).toContain('Required fields:'); - expect(result).toContain('Rules:'); - }); -}); diff --git a/packages/ai/src/tools/visualization-tools/metrics/helpers/get-metric-tool-description.test.ts b/packages/ai/src/tools/visualization-tools/metrics/helpers/get-metric-tool-description.test.ts index 2c96fcc62..d91290f9e 100644 --- a/packages/ai/src/tools/visualization-tools/metrics/helpers/get-metric-tool-description.test.ts +++ b/packages/ai/src/tools/visualization-tools/metrics/helpers/get-metric-tool-description.test.ts @@ -1,78 +1,46 @@ import { describe, expect, it } from 'vitest'; -import { getMetricToolDescriptionPrompt } from './get-metric-tool-description'; +import { getMetricToolDescription } from './get-metric-tool-description'; import metricToolDescription from './metric-tool-description.txt'; -describe('Metric Tool Description Instructions', () => { - it('should validate template file contains expected variables', () => { +describe('getMetricToolDescription', () => { + it('should return the metric tool description from the .txt file', () => { + const description = getMetricToolDescription(); + + // Verify it returns a non-empty string + expect(typeof description).toBe('string'); + expect(description.length).toBeGreaterThan(0); + + // Verify it contains the expected content from the actual .txt file + expect(description).toContain('Creates metric configuration files with YAML content'); + expect(description).toContain('COMPLETE METRIC YAML SCHEMA SPECIFICATION'); + expect(description).toContain('selectedChartType'); + expect(description).toContain('columnLabelFormats'); + + // Verify it has the full schema documentation + expect(description).toContain('# METRIC CONFIGURATION - YML STRUCTURE'); + expect(description).toContain('bar, line, scatter, pie, combo, metric, table'); + }); + + it('should have no template variables in the .txt file', () => { const content = metricToolDescription; - // Expected template variables - const expectedVariables = ['sql_dialect_guidance', 'date']; - - // Find all template variables in the file + // Find any template variables in the file const templateVariablePattern = /\{\{([^}]+)\}\}/g; const foundVariables = new Set(); const matches = Array.from(content.matchAll(templateVariablePattern)); for (const match of matches) { - if (match[1] && match[1] !== 'variable') { + if (match[1]) { foundVariables.add(match[1]); } } - // Convert to arrays for easier comparison - const foundVariablesArray = Array.from(foundVariables).sort(); - const expectedVariablesArray = expectedVariables.sort(); + // Should have no template variables since this tool just returns the raw content + expect(foundVariables.size).toBe(0); - // Check that we have exactly the expected variables - expect(foundVariablesArray).toEqual(expectedVariablesArray); - - // Also verify each expected variable exists - for (const variable of expectedVariables) { - expect(content).toMatch(new RegExp(`\\{\\{${variable}\\}\\}`)); + // If any variables are found, list them for debugging + if (foundVariables.size > 0) { + console.error('Found unexpected template variables:', Array.from(foundVariables)); } - - // Ensure no unexpected variables exist - expect(foundVariables.size).toBe(expectedVariables.length); - }); - - it('should load and process the prompt template correctly', () => { - const sqlDialectGuidance = 'Test SQL guidance for PostgreSQL'; - const result = getMetricToolDescriptionPrompt(sqlDialectGuidance); - - expect(result).toBeDefined(); - expect(typeof result).toBe('string'); - expect(result.length).toBeGreaterThan(0); - - // Should contain the SQL guidance we provided - expect(result).toContain(sqlDialectGuidance); - - // Should not contain any unreplaced template variables - expect(result).not.toMatch(/\{\{sql_dialect_guidance\}\}/); - expect(result).not.toMatch(/\{\{date\}\}/); - - // Should contain the current date in YYYY-MM-DD format - const currentDate = new Date().toISOString().split('T')[0]; - expect(result).toContain(currentDate); - }); - - it('should contain expected sections from the prompt template', () => { - const result = getMetricToolDescriptionPrompt('Test guidance'); - - // Check for key sections that should be in the prompt - // Note: These expectations may need to be adjusted based on the actual content - // of the metric-tool-description.txt file - expect(result.length).toBeGreaterThan(0); - // Additional specific content checks can be added based on the prompt template structure - }); - - it('should throw an error for empty SQL dialect guidance', () => { - expect(() => { - getMetricToolDescriptionPrompt(''); - }).toThrow('SQL dialect guidance is required'); - - expect(() => { - getMetricToolDescriptionPrompt(' '); // whitespace only - }).toThrow('SQL dialect guidance is required'); }); }); diff --git a/packages/ai/src/tools/visualization-tools/metrics/helpers/get-metric-tool-description.ts b/packages/ai/src/tools/visualization-tools/metrics/helpers/get-metric-tool-description.ts index 6efa718b7..6c6bec53e 100644 --- a/packages/ai/src/tools/visualization-tools/metrics/helpers/get-metric-tool-description.ts +++ b/packages/ai/src/tools/visualization-tools/metrics/helpers/get-metric-tool-description.ts @@ -1,40 +1,8 @@ import metricToolDescription from './metric-tool-description.txt'; -/** - * Template parameters for the metric tool description prompt - */ -export interface MetricToolTemplateParams { - dataSourceSyntax: string; - date: string; -} - -/** - * Loads the metric tool description prompt template and replaces variables - */ -function loadAndProcessPrompt(sqlDialectGuidance: string): string { - if (!sqlDialectGuidance.trim()) { - throw new Error('SQL dialect guidance is required'); - } - - // Replace template variables - const currentDate = new Date().toISOString().split('T')[0] ?? ''; - const processedContent = metricToolDescription - .replace(/\{\{sql_dialect_guidance\}\}/g, sqlDialectGuidance) - .replace(/\{\{date\}\}/g, currentDate); - - return processedContent; -} - /** * Export the template function for use in metric tool */ export const getMetricToolDescription = (): string => { return metricToolDescription; }; - -/** - * Export the template function with parameters for use in metric tool - */ -export const getMetricToolDescriptionPrompt = (sqlDialectGuidance: string): string => { - return loadAndProcessPrompt(sqlDialectGuidance); -}; diff --git a/packages/ai/src/tools/visualization-tools/metrics/helpers/metric-tool-description.txt b/packages/ai/src/tools/visualization-tools/metrics/helpers/metric-tool-description.txt index 948c29845..bcfdf09d0 100644 --- a/packages/ai/src/tools/visualization-tools/metrics/helpers/metric-tool-description.txt +++ b/packages/ai/src/tools/visualization-tools/metrics/helpers/metric-tool-description.txt @@ -1,1643 +1,636 @@ -**Create one or more metrics in Buster.** This tool generates new metrics files and automatically executes their SQL queries to verify validity and provide data previews. +Creates metric configuration files with YAML content following the metric schema specification. Before using this tool, carefully consider the appropriate visualization type (bar, line, scatter, pie, combo, metric, table) and its specific configuration requirements. Each visualization has unique axis settings, formatting options, and data structure needs that must be thoroughly planned to create effective metrics. **This tool supports creating multiple metrics in a single call; prefer using bulk creation over creating metrics one by one.** -**Current Date:** {{date}} +Only utilize the required/default fields unless the user specifically requests that optional fields be added. -**SQL Dialect Guidance:** -{{sql_dialect_guidance}} +## COMPLETE METRIC YAML SCHEMA SPECIFICATION -**Instructions:** -1. **ALWAYS prefer bulk creation:** When creating multiple metrics, include them all in a single tool call instead of multiple calls. This improves performance and user experience. -2. **Follow the comprehensive schema specification below:** The metric schema is complex with many required fields and specific enum values. Reference the schema carefully. -3. **Validate column references:** Ensure all column names in axes and label formats match exactly what the SQL query returns (case-sensitive). -4. **Handle chart types properly:** Each chart type has specific required properties that must be included. - -**Comprehensive Metric Schema Specification:** - -```yaml -name: "Metric Name" # Required, user-friendly display name -type: metric # Required, must be 'metric' -sql: | # Required, the SQL query (use pipe for multiline) - SELECT column1, column2 - FROM table -selectedChartType: bar # Required, one of: bar, horizontalBar, line, scatterPlot, barAndLine, table, bigNumber, donut, stackedBar, horizontalStackedBar, areaChart -data: # Required for all chart types - xAxis: column1 # Required for most charts (lowercase column name) - yAxis: [column2] # Required for most charts (array of lowercase column names) - - # Chart-specific configurations: - - # For bar/horizontalBar/line/areaChart: - style: grouped # For bar: grouped or stacked - - # For barAndLine: - barAndLineAxis: - bars: [column1, column2] # Required (lowercase column names) - lines: [column3] # Required (lowercase column names) - - # For scatterPlot: - scatterAxis: - xAxis: column1 # Required (lowercase) - yAxis: column2 # Required (lowercase) - sizeBy: column3 # Optional (lowercase) - colorBy: column4 # Optional (lowercase) - - # For table: - tableColumns: # Required for table type - - id: column1 - label: "Display Name" - columnType: text # One of: text, number, link, date, percentage, boolean, currency, duration - - id: column2 - label: "Another Column" - columnType: number - - # For bigNumber: - bigNumberColumn: column1 # Required for bigNumber (lowercase) - bigNumberLabel: "Label" # Required for bigNumber - trendColumn: column2 # Optional (lowercase) - - # For donut: - donutLabel: column1 # Required for donut (lowercase) - donutValue: column2 # Required for donut (lowercase) - - # Common optional properties: - xAxisLabel: "X Label" # Optional custom x-axis label - yAxisLabel: "Y Label" # Optional custom y-axis label - xAxisTimeInterval: day # Optional: year, quarter, month, week, day, hour, minute - xAxisDateFormat: "%b %d" # Optional date format string - sortBy: column1 # Optional (lowercase) - sortOrder: asc # Optional: asc or desc - goalLines: # Optional - - value: 100 - label: "Target" - annotations: # Optional - - xValue: "2024-01-01" - label: "Launch Date" - columnLabelFormats: # Required - format for EVERY column in SQL results - column1: - type: text - style: titlecase # For text: titlecase, uppercase, lowercase, sentencecase - column2: - type: number - decimalPlaces: 2 # For number: 0-10 - column3: - type: date - dateFormat: "%Y-%m-%d" # For date: strftime format - column4: - type: percentage - decimalPlaces: 1 # For percentage: 0-10 - column5: - type: currency - currency: USD # For currency: ISO code - decimalPlaces: 2 - column6: - type: duration - durationFormat: "h:mm:ss" - column7: - type: boolean - trueLabel: "Yes" # For boolean - falseLabel: "No" - column8: - type: link - linkType: external # For link: external or internal - dataLabelConfig: # Optional - showDataLabels: true - labelPosition: outside # inside, outside, center - labelFormat: "{value}" - tooltipConfig: # Optional - showTooltip: true - tooltipFormat: "{name}: {value}" - legendConfig: # Optional - showLegend: true - legendPosition: bottom # top, bottom, left, right - legendOrientation: horizontal # horizontal, vertical - advancedSettings: # Optional - smoothLine: true # For line charts - showArea: false # For area charts - stackPercentage: false # For stacked charts - showGrid: true - gridColor: "#e0e0e0" - conditionalFormatting: # Optional - - column: column1 - condition: ">" - value: 100 - color: "#ff0000" - dataSampling: # Optional - enabled: false - sampleSize: 1000 - method: random # random, first, last - exportSettings: # Optional - allowExport: true - formats: [csv, excel, pdf] -tags: ["tag1", "tag2"] # Optional array of tags -userProperties: # Optional custom properties - department: "Sales" - owner: "John Doe" -codeExplanation: | # Optional explanation - This metric shows... -refreshSchedule: # Optional - frequency: daily # hourly, daily, weekly, monthly - time: "08:00" - timezone: "UTC" -cacheSettings: # Optional - enableCache: true - ttl: 3600 -alertRules: # Optional - - condition: "value > threshold" - threshold: 100 - action: email - recipients: ["user@example.com"] -accessControl: # Optional - visibility: organization # private, team, organization, public - allowedUsers: [] - allowedTeams: [] - permissions: - view: true - edit: false - delete: false -dependencies: # Optional - metrics: [] - dashboards: [] -transformations: # Optional - - type: aggregate - column: column1 - function: sum # sum, avg, count, min, max - - type: calculated - name: new_column - formula: "column1 + column2" - - type: filter - column: column1 - operator: ">" - value: 0 - - type: pivot - rowColumns: [column1] - columnColumns: [column2] - valueColumn: column3 - aggregation: sum -dataQuality: # Optional - validationRules: - - column: column1 - rule: not_null - - column: column2 - rule: positive - nullHandling: exclude # exclude, zero, average - outlierDetection: - method: zscore # zscore, iqr - threshold: 3 -visualization: # Optional - theme: light # light, dark, custom - colorPalette: ["#1f77b4", "#ff7f0e"] - fontFamily: "Arial" - animations: true - interactivity: - zoom: true - pan: true - hover: true -performance: # Optional - queryTimeout: 30 - maxRows: 10000 - indexHints: [] -metadata: # Optional - version: "1.0.0" - createdBy: "user@example.com" - createdAt: "2024-01-01T00:00:00Z" - lastModifiedBy: "user@example.com" - lastModifiedAt: "2024-01-01T00:00:00Z" - description: "Detailed description" - businessContext: "Business justification" - dataSource: "warehouse.schema.table" - updateFrequency: "Daily at 8 AM" -testing: # Optional - testQueries: - - name: "Test 1" - sql: "SELECT COUNT(*) FROM table" - expectedResult: "> 0" - mockData: - - column1: "value1" - column2: 100 -documentation: # Optional - readme: | - ## Metric Documentation - This metric tracks... - changelog: - - date: "2024-01-01" - changes: "Initial version" - examples: - - name: "Example 1" - description: "Shows how to..." - code: | - SELECT * FROM table -integrations: # Optional - slack: - enabled: true - channel: "#metrics" - notifications: ["alert", "refresh"] - email: - enabled: false - recipients: [] - webhook: - url: "https://example.com/webhook" - events: ["create", "update"] -customFields: # Optional - any additional fields - field1: "value1" - field2: 123 -auditLog: # Optional - enabled: true - retention: 90 # days - fields: ["user", "action", "timestamp"] - -# Additional properties for barAndLine specifically: -barAndLineAxis: # Required for barAndLine chart type - bars: [revenue, profit] # Array of column names for bar series - lines: [growth_rate] # Array of column names for line series - -# Additional properties for scatterPlot specifically: -scatterAxis: # Required for scatterPlot chart type - xAxis: column1 - yAxis: column2 - sizeBy: column3 # Optional - colorBy: column4 # Optional - -# Additional properties for table specifically: -tableColumns: # Required for table chart type - - id: column1 - label: "Column 1" - columnType: text - - id: column2 - label: "Column 2" - columnType: number - align: right # Optional: left, center, right - width: 100 # Optional: pixel width - sortable: true # Optional: enable sorting - filterable: true # Optional: enable filtering - cellRenderer: default # Optional: default, custom - headerStyle: # Optional - fontWeight: bold - backgroundColor: "#f0f0f0" - cellStyle: # Optional - fontSize: 14 - color: "#333" - -# Example for columnLabelFormats - comprehensive type formatting: -columnLabelFormats: - text_column: - type: text - style: titlecase # titlecase, uppercase, lowercase, sentencecase - number_column: - type: number - decimalPlaces: 2 # 0-10 - thousandsSeparator: true - negativeFormat: "()" # (), -, red - date_column: - type: date - dateFormat: "%Y-%m-%d" # strftime format - percentage_column: - type: percentage - decimalPlaces: 1 - multiplyBy100: false # If data is already in percentage - currency_column: - type: currency - currency: USD # ISO currency code - decimalPlaces: 2 - currencyDisplay: symbol # symbol, code, name - duration_column: - type: duration - durationFormat: "h:mm:ss" - showDays: false - boolean_column: - type: boolean - trueLabel: "Active" - falseLabel: "Inactive" - trueColor: "#00ff00" - falseColor: "#ff0000" - link_column: - type: link - linkType: external # external, internal - linkTarget: "_blank" # _blank, _self - linkTemplate: "https://example.com/{value}" - custom_column: - type: custom - formatter: | - function(value) { - return value.toUpperCase(); - } - -# Table-specific columnType values: -tableColumns: - - id: text_col - columnType: text - - id: number_col - columnType: number - - id: link_col - columnType: link - - id: date_col - columnType: date - - id: percentage_col - columnType: percentage - - id: boolean_col - columnType: boolean - - id: currency_col - columnType: currency - - id: duration_col - columnType: duration - - id: status_col - columnType: status # Special type for status indicators - statusConfig: - success: ["completed", "active"] - warning: ["pending", "processing"] - error: ["failed", "error"] - - id: progress_col - columnType: progress # Special type for progress bars - progressConfig: - min: 0 - max: 100 - showLabel: true - - id: rating_col - columnType: rating # Special type for star ratings - ratingConfig: - max: 5 - allowHalf: true - - id: tag_col - columnType: tags # Special type for tag lists - tagConfig: - colorScheme: "blue" - - id: avatar_col - columnType: avatar # Special type for user avatars - avatarConfig: - size: "small" - shape: "circle" - - id: action_col - columnType: actions # Special type for action buttons - actionConfig: - actions: - - label: "Edit" - action: "edit" - - label: "Delete" - action: "delete" - -# Extended barAndLine configuration: -barAndLineAxis: - bars: [revenue, costs, profit] - lines: [margin_percentage, growth_rate] - barAxis: left # Optional: which y-axis for bars (left, right) - lineAxis: right # Optional: which y-axis for lines (left, right) - barType: grouped # Optional: grouped, stacked - lineType: solid # Optional: solid, dashed, dotted - showPoints: true # Optional: show data points on lines - pointSize: 4 # Optional: size of data points - lineWidth: 2 # Optional: width of lines - barWidth: 0.8 # Optional: relative width of bars (0-1) - barGap: 0.1 # Optional: gap between bars (0-1) - -# Extended scatterPlot configuration: -scatterAxis: - xAxis: revenue - yAxis: profit - sizeBy: employee_count # Optional: column for bubble size - colorBy: region # Optional: column for color coding - labelBy: company_name # Optional: column for point labels - trendLine: linear # Optional: linear, polynomial, exponential - showRegression: true # Optional: show regression statistics - pointShape: circle # Optional: circle, square, triangle, diamond - pointOpacity: 0.7 # Optional: 0-1 - enableClustering: false # Optional: automatic clustering - clusterCount: 5 # Optional: number of clusters - -# Format specification for SQL result columns: -columnLabelFormats: - revenue: - type: currency - currency: USD - decimalPlaces: 0 - profit: - type: currency - currency: USD - decimalPlaces: 0 - margin_percentage: - type: percentage - decimalPlaces: 1 - growth_rate: - type: percentage - decimalPlaces: 2 - employee_count: - type: number - thousandsSeparator: true - region: - type: text - style: titlecase - company_name: - type: text - created_date: - type: date - dateFormat: "%b %d, %Y" - is_active: - type: boolean - trueLabel: "Active" - falseLabel: "Inactive" - duration_hours: - type: duration - durationFormat: "h:mm" - website_url: - type: link - linkType: external - completion_rate: - type: percentage - decimalPlaces: 0 - suffix: " complete" - temperature: - type: number - decimalPlaces: 1 - suffix: "°C" - status_code: - type: text - colorMap: - "200": "#00ff00" - "404": "#ffff00" - "500": "#ff0000" - score: - type: number - min: 0 - max: 100 - colorScale: true # Optional: color based on value - tags_list: - type: text - isArray: true # Optional: handle array values - arraySeparator: ", " - json_data: - type: json # Optional: format JSON data - indent: 2 - markdown_content: - type: markdown # Optional: render markdown - html_content: - type: html # Optional: render HTML (sanitized) - code_snippet: - type: code # Optional: syntax highlighted code - language: sql - image_url: - type: image # Optional: display as image - maxWidth: 200 - maxHeight: 200 - file_size: - type: filesize # Optional: format file sizes - binary: true # true for KiB, false for KB - email_address: - type: email # Optional: mailto links - phone_number: - type: phone # Optional: tel links - format: "international" - ip_address: - type: ip # Optional: IP address formatting - uuid_field: - type: uuid # Optional: UUID formatting - format: "short" # short, full - color_value: - type: color # Optional: color swatches - coordinate: - type: coordinate # Optional: lat/long formatting - format: "decimal" # decimal, dms - version_number: - type: version # Optional: semantic versioning - hash_value: - type: hash # Optional: hash/checksum formatting - algorithm: "sha256" - base64_data: - type: base64 # Optional: base64 decoding - decode: true - enum_value: - type: enum # Optional: enum mapping - enumMap: - 1: "Low" - 2: "Medium" - 3: "High" - formula_result: - type: formula # Optional: math formula rendering - latex: true - sparkline_data: - type: sparkline # Optional: inline sparkline chart - sparklineType: line # line, bar, area - qr_code_data: - type: qrcode # Optional: QR code generation - barcode_data: - type: barcode # Optional: barcode generation - barcodeType: "code128" - social_handle: - type: social # Optional: social media links - platform: twitter # twitter, linkedin, github, etc. - -# Full enum specifications: -selectedChartType enum values: - - bar # Vertical bar chart - - horizontalBar # Horizontal bar chart - - line # Line chart - - scatterPlot # Scatter/bubble plot - - barAndLine # Combined bar and line - - table # Data table - - bigNumber # Single KPI display - - donut # Donut/pie chart - - stackedBar # Vertical stacked bar - - horizontalStackedBar # Horizontal stacked bar - - areaChart # Area chart - - heatmap # Heat map (future) - - treemap # Treemap (future) - - funnel # Funnel chart (future) - - waterfall # Waterfall chart (future) - - boxPlot # Box plot (future) - - radar # Radar chart (future) - - sankey # Sankey diagram (future) - - gantt # Gantt chart (future) - - candlestick # Candlestick chart (future) - - gauge # Gauge chart (future) - - map # Geographic map (future) - - network # Network graph (future) - - sunburst # Sunburst chart (future) - - timeline # Timeline chart (future) - - word # Word cloud (future) - -style enum values (for bar charts): - - grouped # Side-by-side bars - - stacked # Stacked bars - -xAxisTimeInterval enum values: - - year - - quarter - - month - - week - - day - - hour - - minute - - second - - millisecond - -sortOrder enum values: - - asc # Ascending - - desc # Descending - -columnType enum values (for tables): - - text - - number - - link - - date - - percentage - - boolean - - currency - - duration - - status - - progress - - rating - - tags - - avatar - - actions - - json - - markdown - - html - - code - - image - - filesize - - email - - phone - - ip - - uuid - - color - - coordinate - - version - - hash - - base64 - - enum - - formula - - sparkline - - qrcode - - barcode - - social - -columnLabelFormat type enum values: - - text - - number - - date - - percentage - - currency - - duration - - boolean - - link - - json - - markdown - - html - - code - - image - - filesize - - email - - phone - - ip - - uuid - - color - - coordinate - - version - - hash - - base64 - - enum - - formula - - sparkline - - qrcode - - barcode - - social - - custom - -text style enum values: - - titlecase - - uppercase - - lowercase - - sentencecase - -legendPosition enum values: - - top - - bottom - - left - - right - -legendOrientation enum values: - - horizontal - - vertical - -labelPosition enum values: - - inside - - outside - - center - -visibility enum values: - - private - - team - - organization - - public - -refreshSchedule frequency enum values: - - hourly - - daily - - weekly - - monthly - -aggregation function enum values: - - sum - - avg - - count - - min - - max - - median - - mode - - stddev - - variance - -operator enum values (for filters): - - "=" - - "!=" - - ">" - - ">=" - - "<" - - "<=" - - "in" - - "not in" - - "like" - - "not like" - - "is null" - - "is not null" - - "between" - - "not between" - -nullHandling enum values: - - exclude - - zero - - average - - forward_fill - - backward_fill - - interpolate - -outlierDetection method enum values: - - zscore - - iqr - - isolation_forest - - dbscan - -theme enum values: - - light - - dark - - custom - -negativeFormat enum values: - - "()" # Parentheses - - "-" # Minus sign - - "red" # Red color - -currencyDisplay enum values: - - symbol # $ - - code # USD - - name # US Dollar - -linkType enum values: - - external - - internal - -linkTarget enum values: - - "_blank" - - "_self" - - "_parent" - - "_top" - -trendLine enum values: - - linear - - polynomial - - exponential - - logarithmic - - power - -pointShape enum values: - - circle - - square - - triangle - - diamond - - cross - - star - -sparklineType enum values: - - line - - bar - - area - -barcodeType enum values: - - code128 - - code39 - - ean13 - - ean8 - - upc - - qr - -social platform enum values: - - twitter - - linkedin - - github - - facebook - - instagram - - youtube - - tiktok - - reddit - - discord - - slack - -coordinate format enum values: - - decimal # 40.7128, -74.0060 - - dms # 40°42'46.0"N 74°00'21.6"W - -validation rule enum values: - - not_null - - positive - - negative - - non_zero - - unique - - in_range - - regex - - email - - url - - phone - - date - - future_date - - past_date - -# Transformation type enum values: -transformation type enum: - - aggregate - - calculated - - filter - - pivot - - unpivot - - join - - union - - window - - rank - - lag - - lead - - cumulative - - moving_average - - interpolate - - resample - - normalize - - standardize - - encode - - decode - -# Alert action enum values: -alert action enum: - - email - - slack - - webhook - - sms - - push - - log - - script - -# Data sampling method enum values: -sampling method enum: - - random - - first - - last - - systematic - - stratified - - cluster - -# Cell renderer enum values: -cellRenderer enum: - - default - - custom - - html - - markdown - - component - -# Shape enum values (avatar): -avatar shape enum: - - circle - - square - - rounded - -# Size enum values (avatar): -avatar size enum: - - small - - medium - - large - - xlarge - -# Color scheme enum values (tags): -tag colorScheme enum: - - blue - - green - - red - - yellow - - purple - - gray - - rainbow - - monochrome - -# Chart axis configuration: -axis configuration: - - barAxis: left/right - - lineAxis: left/right - - xAxisPosition: bottom/top - - yAxisPosition: left/right - - secondaryYAxis: true/false - -# Bar type enum values: -barType enum: - - grouped - - stacked - - overlapped - - waterfall - -# Line type enum values: -lineType enum: - - solid - - dashed - - dotted - - dashdot - -# Required fields by chart type: -Required fields: - bar: xAxis, yAxis - horizontalBar: xAxis, yAxis - line: xAxis, yAxis - scatterPlot: scatterAxis.xAxis, scatterAxis.yAxis - barAndLine: barAndLineAxis.bars, barAndLineAxis.lines - table: tableColumns - bigNumber: bigNumberColumn, bigNumberLabel - donut: donutLabel, donutValue - stackedBar: xAxis, yAxis - horizontalStackedBar: xAxis, yAxis - areaChart: xAxis, yAxis - -# Column reference requirements: -Column references: - - Must be lowercase in axis configurations - - Must match SQL query result columns exactly - - Required in columnLabelFormats for ALL result columns - - Case-sensitive in tableColumns.id - - Case-sensitive in columnLabelFormats keys - -# Common pitfalls to avoid: -Pitfalls: - 1. Missing required fields for chart type - 2. Incorrect column name casing in axes - 3. Missing columnLabelFormats for SQL columns - 4. Invalid enum values - 5. Mismatched column references - 6. Missing pipe (|) for multiline SQL - 7. Invalid date format strings - 8. Incomplete barAndLineAxis configuration - 9. Missing scatterAxis for scatterPlot - 10. Undefined columns in sort/filter configurations - -# Validation requirements: -Validation: - - All enum values must match exactly - - All referenced columns must exist in SQL results - - Required fields cannot be null/undefined - - Arrays cannot be empty where required - - Numeric values must be within valid ranges - - Date strings must be valid ISO format - - Color values must be valid hex codes - - URLs must be valid format - - Email addresses must be valid format - - Regular expressions must be valid - -# YAML formatting requirements: -YAML formatting: - - Use pipe (|) for multiline strings - - Proper indentation (2 spaces) - - No tabs allowed - - Quotes for special characters - - Arrays use dash notation - - Objects use colon notation - - Comments use hash notation - - Escape special characters properly - -# SQL requirements: -SQL requirements: - - Valid syntax for data source type - - Column aliases for complex expressions - - Proper quoting for identifiers - - No dangerous operations (DROP, DELETE, UPDATE) - - Appropriate JOIN syntax - - Valid WHERE clause conditions - - Proper GROUP BY when using aggregates - - ORDER BY for consistent results - - LIMIT for performance (when appropriate) - -# Performance considerations: -Performance: - - Limit result sets appropriately - - Use indexes effectively - - Avoid full table scans - - Optimize JOIN operations - - Cache frequently accessed data - - Use query timeouts - - Implement pagination for large datasets - - Consider materialized views - - Use appropriate data sampling - -# Security requirements: -Security: - - No sensitive data exposure - - Parameterized queries only - - Proper access control - - Audit logging enabled - - Encryption for sensitive fields - - No hardcoded credentials - - Validate all user inputs - - Sanitize output data - - Implement rate limiting - -# Best practices: -Best practices: - 1. Use descriptive metric names - 2. Include clear code explanations - 3. Add relevant tags for organization - 4. Configure appropriate refresh schedules - 5. Set up meaningful alerts - 6. Document business context - 7. Include example queries - 8. Maintain version history - 9. Test with sample data - 10. Optimize for performance - 11. Ensure data quality - 12. Implement proper error handling - 13. Use consistent naming conventions - 14. Follow organizational standards - 15. Regular review and updates - -# Example metric (complete): -```yaml -name: "Monthly Revenue by Region" -type: metric -sql: | - SELECT - DATE_TRUNC('month', order_date) as month, - region, - SUM(revenue) as total_revenue, - SUM(profit) as total_profit, - AVG(margin) as avg_margin - FROM sales_data - WHERE order_date >= CURRENT_DATE - INTERVAL '12 months' - GROUP BY 1, 2 - ORDER BY 1 DESC, 3 DESC -selectedChartType: barAndLine -data: - xAxis: month - yAxis: [total_revenue, total_profit] - barAndLineAxis: - bars: [total_revenue, total_profit] - lines: [avg_margin] - barAxis: left - lineAxis: right - xAxisLabel: "Month" - yAxisLabel: "Revenue & Profit ($)" - xAxisTimeInterval: month - xAxisDateFormat: "%b %Y" - style: grouped - columnLabelFormats: - month: - type: date - dateFormat: "%B %Y" - region: - type: text - style: titlecase - total_revenue: - type: currency - currency: USD - decimalPlaces: 0 - total_profit: - type: currency - currency: USD - decimalPlaces: 0 - avg_margin: - type: percentage - decimalPlaces: 1 - goalLines: - - value: 1000000 - label: "Target Revenue" - dataLabelConfig: - showDataLabels: true - labelPosition: outside - legendConfig: - showLegend: true - legendPosition: bottom - legendOrientation: horizontal -tags: ["sales", "revenue", "monthly", "regional"] -codeExplanation: | - This metric tracks monthly revenue and profit by region for the past 12 months, - with average margin displayed as a line chart for trend analysis. -refreshSchedule: - frequency: daily - time: "02:00" - timezone: "America/New_York" -accessControl: - visibility: organization -userProperties: - department: "Finance" - owner: "analytics-team" ``` +# METRIC CONFIGURATION - YML STRUCTURE +# ------------------------------------- +# REQUIRED Top-Level Fields: `name`, `description`, `timeFrame`, `sql`, `chartConfig` +# +# --- FIELD DETAILS & RULES --- +# `name`: Human-readable title (e.g., Total Sales). +# - RULE: CANNOT contain underscores (`_`). Use spaces instead. +# `description`: Detailed explanation of the metric. +# `timeFrame`: Human-readable time period covered by the query, similar to a filter in a BI tool. MUST BE A VALID STRING. +# - If doing 2024 as an example, you must do "2024" can't parse as a number. +# - For queries with fixed date filters, use specific date ranges, e.g., "January 1, 2020 - December 31, 2020", "2024", "Q2 2024", "June 1, 2025". +# - For queries with relative date filters or no date filter, use relative terms, e.g., "Today", "Yesterday", "Last 7 days", "Last 30 days", "Last Quarter", "Last 12 Months", "Year to Date", "All time", etc. +# - For comparisons, use "Comparison - [Period 1] vs [Period 2]", with each period formatted according to whether it is fixed or relative, e.g., "Comparison - Last 30 days vs Previous 30 days" or "Comparison - June 1, 2025 - June 30, 2025 vs July 1, 2025 - July 31, 2025". +# Rules: +# - Must accurately reflect the date/time filter used in the `sql` field. Do not misrepresent the time range. +# - Use full month names for dates, e.g., "January", not "Jan". +# - Follow general quoting rules. CANNOT contain ':'. +# Note: Respond only with the time period, without explanation or additional copy. +# `sql`: The SQL query for the metric. +# - RULE: MUST use the pipe `|` block scalar style to preserve formatting and newlines. +# - NOTE: Remember to use fully qualified names: DATABASE_NAME.SCHEMA_NAME.TABLE_NAME for tables and table_alias.column for columns. This applies to all table and column references, including those within Common Table Expressions (CTEs) and when selecting from CTEs. +# - Example: +# sql: | +# SELECT ... +# `chartConfig`: Visualization settings. +# - RULE: Must contain `selectedChartType` (bar, line, scatter, pie, combo, metric, table). +# - RULE: Must contain `columnLabelFormats` defining format for ALL columns in the SQL result. +# - RULE: Must contain ONE chart-specific config block based on `selectedChartType`: +# - `barAndLineAxis` (for type: bar, line) +# - `scatterAxis` (for type: scatter) +# - `pieChartAxis` (for type: pie) +# - `comboChartAxis` (for type: combo) +# - `metricColumnId` (for type: metric) +# - `tableConfig` (for type: table) - [Optional, if needed beyond basic columns] +# +# --- GENERAL YAML RULES --- +# 1. Use standard YAML syntax (indentation, colons for key-value, `-` for arrays). +# 2. Quoting: Generally avoid quotes for simple strings. Use double quotes (`"..."`) ONLY if a string contains special characters (like :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, `) or needs to preserve leading/trailing whitespace. +# 3. Metric name, timeframe, or description CANNOT contain `:` +# ------------------------------------- -# Additional complete examples for each chart type: +# --- FORMAL SCHEMA --- (Used for validation, reflects rules above) +type: object +name: Metric Configuration Schema +description: Metric definition with SQL query and visualization settings -## Bar Chart Example: -```yaml -name: "Product Sales Comparison" -type: metric -sql: | - SELECT - product_name, - units_sold, - revenue - FROM product_sales - WHERE date >= CURRENT_DATE - INTERVAL '30 days' - ORDER BY revenue DESC - LIMIT 10 -selectedChartType: bar -data: - xAxis: product_name - yAxis: [units_sold, revenue] - style: grouped - xAxisLabel: "Products" - yAxisLabel: "Sales Metrics" - columnLabelFormats: - product_name: - type: text - style: titlecase - units_sold: - type: number - thousandsSeparator: true - revenue: - type: currency - currency: USD - decimalPlaces: 2 -``` +properties: + # NAME + name: + required: true + type: string + description: Human-readable title (e.g., Total Sales). NO underscores. Follow quoting rules. Should not contain `:` -## Line Chart Example: -```yaml -name: "Daily Active Users Trend" -type: metric -sql: | - SELECT - date, - active_users, - new_users, - returning_users - FROM user_metrics - WHERE date >= CURRENT_DATE - INTERVAL '90 days' - ORDER BY date -selectedChartType: line -data: - xAxis: date - yAxis: [active_users, new_users, returning_users] - xAxisTimeInterval: day - xAxisDateFormat: "%m/%d" - xAxisLabel: "Date" - yAxisLabel: "User Count" - columnLabelFormats: - date: - type: date - dateFormat: "%Y-%m-%d" - active_users: - type: number - thousandsSeparator: true - new_users: - type: number - thousandsSeparator: true - returning_users: - type: number - thousandsSeparator: true - advancedSettings: - smoothLine: true - showGrid: true -``` + # DESCRIPTION + description: + required: true + type: string + description: | + A natural language description of the metric, essentially rephrasing the 'name' field as a question or statement. + Example: If name is "Total Sales", description could be "What are the total sales?". + RULE: Should NOT describe the chart type, axes, or any visualization aspects. + RULE: Follow general quoting rules. + RULE: Should not contain ':'. -## ScatterPlot Example: -```yaml -name: "Price vs Performance Analysis" -type: metric -sql: | - SELECT - price, - performance_score, - market_share, - product_category, - product_name - FROM product_analysis -selectedChartType: scatterPlot -data: - scatterAxis: - xAxis: price - yAxis: performance_score - sizeBy: market_share - colorBy: product_category - labelBy: product_name - xAxisLabel: "Price ($)" - yAxisLabel: "Performance Score" - columnLabelFormats: - price: - type: currency - currency: USD - decimalPlaces: 2 - performance_score: - type: number - decimalPlaces: 1 - market_share: - type: percentage - decimalPlaces: 1 - product_category: - type: text - style: titlecase - product_name: - type: text -``` + # TIME FRAME + timeFrame: + required: true + type: string + description: | + Human-readable time period covered by the SQL query, similar to a filter in a BI tool. + RULE: Must accurately reflect the date/time filter used in the `sql` field. Do not misrepresent the time range. + Examples: + - Fixed Dates: "January 1, 2020 - December 31, 2020", "2024", "Q2 2024", "June 1, 2025" + - Relative Dates: "Today", "Yesterday", "Last 7 days", "Last 30 days", "Last Quarter", "Last 12 Months", "Year to Date", "All time" + - Comparisons: Use the format "Comparison: [Period 1] vs [Period 2]". Examples: + - "Comparison: Last 30 days vs Previous 30 days" + - "Comparison: June 1, 2025 - June 30, 2025 vs July 1, 2025 - July 31, 2025" + RULE: Use full month names for dates, e.g., "January", not "Jan". + RULE: Follow general quoting rules. CANNOT contain ':'. -## Table Example: -```yaml -name: "Customer Orders Detail" -type: metric -sql: | - SELECT - order_id, - customer_name, - order_date, - status, - total_amount, - payment_method, - shipping_address - FROM orders - WHERE order_date >= CURRENT_DATE - INTERVAL '7 days' - ORDER BY order_date DESC -selectedChartType: table -data: - tableColumns: - - id: order_id - label: "Order ID" - columnType: text - - id: customer_name - label: "Customer" - columnType: text - - id: order_date - label: "Date" - columnType: date - - id: status - label: "Status" - columnType: status - - id: total_amount - label: "Amount" - columnType: currency - - id: payment_method - label: "Payment" - columnType: text - - id: shipping_address - label: "Address" - columnType: text - columnLabelFormats: - order_id: - type: text - customer_name: - type: text - style: titlecase - order_date: - type: date - dateFormat: "%b %d, %Y" - status: - type: text - style: uppercase - total_amount: - type: currency - currency: USD - decimalPlaces: 2 - payment_method: - type: text - style: titlecase - shipping_address: - type: text -``` + # SQL QUERY + sql: + required: true + type: string + description: | + SQL query using YAML pipe syntax (|). + The SQL query should be formatted with proper indentation using the YAML pipe (|) syntax. + This ensures the multi-line SQL is properly parsed while preserving whitespace and newlines. + IMPORTANT: Remember to use fully qualified names: DATABASE_NAME.SCHEMA_NAME.TABLE_NAME for tables and table_alias.column for columns. This rule is critical for all table and column references, including those within Common Table Expressions (CTEs) and when selecting from CTEs. + Example: + sql: | + SELECT column1, column2 + FROM my_table + WHERE condition; -## BigNumber Example: -```yaml -name: "Total Revenue This Month" -type: metric -sql: | - SELECT - SUM(revenue) as total_revenue, - SUM(revenue) - LAG(SUM(revenue)) OVER (ORDER BY month) as revenue_change - FROM monthly_sales - WHERE month = DATE_TRUNC('month', CURRENT_DATE) -selectedChartType: bigNumber -data: - bigNumberColumn: total_revenue - bigNumberLabel: "Monthly Revenue" - trendColumn: revenue_change - columnLabelFormats: - total_revenue: - type: currency - currency: USD - decimalPlaces: 0 - revenue_change: - type: currency - currency: USD - decimalPlaces: 0 -``` + # CHART CONFIGURATION + chartConfig: + required: true + description: Visualization settings (must include selectedChartType, columnLabelFormats, and ONE chart-specific block) + allOf: # Base requirements for ALL chart types + - \$ref: '#/definitions/base_chart_config' + oneOf: # Specific block required based on type + - \$ref: #/definitions/bar_line_chart_config + - \$ref: #/definitions/scatter_chart_config + - \$ref: #/definitions/pie_chart_config + - \$ref: #/definitions/combo_chart_config + - \$ref: #/definitions/metric_chart_config + - \$ref: #/definitions/table_chart_config -## Donut Chart Example: -```yaml -name: "Market Share Distribution" -type: metric -sql: | - SELECT - company_name, - market_share_percentage - FROM market_analysis - WHERE year = EXTRACT(YEAR FROM CURRENT_DATE) - ORDER BY market_share_percentage DESC -selectedChartType: donut -data: - donutLabel: company_name - donutValue: market_share_percentage - columnLabelFormats: - company_name: - type: text - style: titlecase - market_share_percentage: - type: percentage - decimalPlaces: 1 - legendConfig: - showLegend: true - legendPosition: right - legendOrientation: vertical -``` +required: + - name + - timeFrame + - sql + - chartConfig -## StackedBar Example: -```yaml -name: "Quarterly Revenue by Product Line" -type: metric -sql: | - SELECT - quarter, - product_line, - revenue - FROM quarterly_sales - WHERE year = EXTRACT(YEAR FROM CURRENT_DATE) - ORDER BY quarter, product_line -selectedChartType: stackedBar -data: - xAxis: quarter - yAxis: [revenue] - style: stacked - xAxisLabel: "Quarter" - yAxisLabel: "Revenue ($)" - columnLabelFormats: - quarter: - type: text - product_line: - type: text - style: titlecase - revenue: - type: currency - currency: USD - decimalPlaces: 0 -``` +definitions: + # BASE CHART CONFIG (common parts used by ALL chart types) + base_chart_config: + type: object + properties: + selectedChartType: + type: string + description: Chart type (bar, line, scatter, pie, combo, metric, table) + enum: [bar, line, scatter, pie, combo, metric, table] + columnLabelFormats: + type: object + description: REQUIRED formatting for ALL columns returned by the SQL query. + additionalProperties: + \$ref: #/definitions/column_label_format + # Optional base properties below + columnSettings: + type: object + description: |- + Visual settings applied per column. + Keys MUST be LOWERCASE column names from the SQL query results. + Example: `total_sales: { showDataLabels: true }` + additionalProperties: + \$ref: #/definitions/column_settings + colors: + type: array + items: + type: string + description: | + Default color palette. + RULE: Hex color codes (e.g., #FF0000) MUST be enclosed in quotes (e.g., "#FF0000" or '#FF0000') because '#' signifies a comment otherwise. Double quotes are preferred for consistency. + Use this parameter when the user asks about customizing chart colors, unless specified otherwise. + showLegend: + type: boolean + gridLines: + type: boolean + showLegendHeadline: + oneOf: + - type: boolean + - type: string + goalLines: + type: array + items: + \$ref: #/definitions/goal_line + trendlines: + type: array + items: + \$ref: #/definitions/trendline + disableTooltip: + type: boolean + # Axis Configurations + # RULE: By default, only add `xAxisConfig` and ONLY set its `xAxisTimeInterval` property + # when visualizing date/time data on the X-axis (e.g., line, bar, combo charts). + # Do NOT add other `xAxisConfig` properties, `yAxisConfig`, or `y2AxisConfig` + # unless the user explicitly asks for specific axis modifications. + xAxisConfig: + description: Controls X-axis properties. For date/time axes, MUST contain `xAxisTimeInterval` (day, week, month, quarter, year). Other properties control label visibility, title, rotation, and zoom. Only add when needed (dates) or requested by user. + \$ref: '#/definitions/x_axis_config' + yAxisConfig: + description: Controls Y-axis properties. Only add if the user explicitly requests Y-axis modifications (e.g., hiding labels, changing title). Properties control label visibility, title, rotation, and zoom. + \$ref: '#/definitions/y_axis_config' + y2AxisConfig: + description: Controls secondary Y-axis (Y2) properties, primarily for combo charts. Only add if the user explicitly requests Y2-axis modifications. Properties control label visibility, title, rotation, and zoom. + \$ref: '#/definitions/y2_axis_config' + categoryAxisStyleConfig: + description: Optional style configuration for the category axis (color/grouping). + \$ref: '#/definitions/category_axis_style_config' + required: + - selectedChartType + - columnLabelFormats -## AreaChart Example: -```yaml -name: "Cumulative User Growth" -type: metric -sql: | - SELECT - date, - SUM(new_users) OVER (ORDER BY date) as cumulative_users - FROM daily_signups - WHERE date >= CURRENT_DATE - INTERVAL '180 days' - ORDER BY date -selectedChartType: areaChart -data: - xAxis: date - yAxis: [cumulative_users] - xAxisTimeInterval: week - xAxisDateFormat: "%b %d" - xAxisLabel: "Date" - yAxisLabel: "Total Users" - columnLabelFormats: - date: - type: date - dateFormat: "%Y-%m-%d" - cumulative_users: - type: number - thousandsSeparator: true - advancedSettings: - showArea: true - smoothLine: true -``` + # AXIS CONFIGURATIONS + x_axis_config: + type: object + properties: + xAxisTimeInterval: + type: string + enum: [day, week, month, quarter, year, 'null'] + description: REQUIRED time interval for grouping date/time values on the X-axis (e.g., for line/combo charts). MUST be set if the X-axis represents time. Default: null. + xAxisShowAxisLabel: + type: boolean + description: Show X-axis labels. Default: true. + xAxisShowAxisTitle: + type: boolean + description: Show X-axis title. Default: true. + xAxisAxisTitle: + type: [string, 'null'] + description: X-axis title. Default: null (auto-generates from column names). + xAxisLabelRotation: + type: string # Representing numbers or 'auto' + enum: ["0", "45", "90", auto] + description: Label rotation. Default: auto. + xAxisDataZoom: + type: boolean + description: Enable data zoom on X-axis. Default: false (User only). + additionalProperties: false + required: + - xAxisTimeInterval -# Complex multi-axis example: -```yaml -name: "Sales Performance Dashboard" -type: metric -sql: | - SELECT - DATE_TRUNC('week', sale_date) as week, - SUM(units_sold) as total_units, - SUM(revenue) as total_revenue, - AVG(customer_satisfaction) as avg_satisfaction, - COUNT(DISTINCT customer_id) as unique_customers, - SUM(profit) as total_profit, - AVG(conversion_rate) as avg_conversion - FROM sales_metrics - WHERE sale_date >= CURRENT_DATE - INTERVAL '12 weeks' - GROUP BY 1 - ORDER BY 1 -selectedChartType: barAndLine -data: - xAxis: week - yAxis: [total_revenue, total_profit] - barAndLineAxis: - bars: [total_revenue, total_profit, total_units] - lines: [avg_satisfaction, avg_conversion] - barAxis: left - lineAxis: right - barType: grouped - lineType: solid - showPoints: true - xAxisLabel: "Week" - yAxisLabel: "Revenue & Units" - xAxisTimeInterval: week - xAxisDateFormat: "%b %d" - style: grouped - sortBy: week - sortOrder: asc - columnLabelFormats: - week: - type: date - dateFormat: "%B %d, %Y" - total_units: - type: number - thousandsSeparator: true - suffix: " units" - total_revenue: - type: currency - currency: USD - decimalPlaces: 0 - avg_satisfaction: - type: number - decimalPlaces: 1 - suffix: "/5" - unique_customers: - type: number - thousandsSeparator: true - total_profit: - type: currency - currency: USD - decimalPlaces: 0 - avg_conversion: - type: percentage - decimalPlaces: 1 - goalLines: - - value: 500000 - label: "Revenue Target" - color: "#00ff00" - - value: 4.0 - label: "Satisfaction Goal" - color: "#0000ff" - axis: right - annotations: - - xValue: "2024-01-15" - label: "Campaign Launch" - color: "#ff0000" - dataLabelConfig: - showDataLabels: false - tooltipConfig: - showTooltip: true - tooltipFormat: "{name}: {value}" - legendConfig: - showLegend: true - legendPosition: bottom - legendOrientation: horizontal - advancedSettings: - smoothLine: true - showGrid: true - gridColor: "#e0e0e0" - conditionalFormatting: - - column: total_revenue - condition: ">" - value: 500000 - color: "#00ff00" - - column: avg_satisfaction - condition: "<" - value: 3.5 - color: "#ff0000" -tags: ["sales", "weekly", "performance", "dashboard"] -codeExplanation: | - This comprehensive sales dashboard tracks weekly performance metrics including: - - Revenue and profit as grouped bars - - Customer satisfaction and conversion rates as trend lines - - Unique customer counts and unit sales - - The metric includes goal lines for key targets and conditional formatting - to highlight exceptional or concerning values. -refreshSchedule: - frequency: daily - time: "06:00" - timezone: "UTC" -cacheSettings: - enableCache: true - ttl: 3600 -alertRules: - - condition: "avg_satisfaction < 3.5" - threshold: 3.5 - action: email - recipients: ["manager@example.com"] - - condition: "total_revenue < 400000" - threshold: 400000 - action: slack - channel: "#sales-alerts" -accessControl: - visibility: team - allowedTeams: ["sales", "management"] - permissions: - view: true - edit: false - delete: false -userProperties: - department: "Sales" - owner: "sales-analytics" - priority: "high" - lastReviewed: "2024-01-01" -``` + y_axis_config: + type: object + properties: + yAxisShowAxisLabel: + type: boolean + description: Show Y-axis labels. Default: true. + yAxisShowAxisTitle: + type: boolean + description: Show Y-axis title. Default: true. + yAxisAxisTitle: + type: [string, 'null'] + description: Y-axis title. Default: null (uses first plotted column name). + yAxisStartAxisAtZero: + type: [boolean, 'null'] + description: Start Y-axis at zero. Default: true. + yAxisScaleType: + type: string + enum: [log, linear] + description: Scale type for Y-axis. Default: linear. + additionalProperties: false -# Date formatting examples: -Date formats (strftime): - - "%Y-%m-%d" → "2024-01-15" - - "%b %d, %Y" → "Jan 15, 2024" - - "%B %d, %Y" → "January 15, 2024" - - "%m/%d/%Y" → "01/15/2024" - - "%d/%m/%Y" → "15/01/2024" - - "%Y-%m-%d %H:%M:%S" → "2024-01-15 14:30:45" - - "%b %d" → "Jan 15" - - "%B %Y" → "January 2024" - - "%Y-W%W" → "2024-W03" (week number) - - "%a, %b %d" → "Mon, Jan 15" - - "%A, %B %d, %Y" → "Monday, January 15, 2024" - - "%I:%M %p" → "02:30 PM" - - "%H:%M" → "14:30" - - "%Y-%m-%dT%H:%M:%S%z" → "2024-01-15T14:30:45+0000" + y2_axis_config: + type: object + description: Secondary Y-axis configuration (for combo charts). + properties: + y2AxisShowAxisLabel: + type: boolean + description: Show Y2-axis labels. Default: true. + y2AxisShowAxisTitle: + type: boolean + description: Show Y2-axis title. Default: true. + y2AxisAxisTitle: + type: [string, 'null'] + description: Y2-axis title. Default: null (uses first plotted column name). + y2AxisStartAxisAtZero: + type: [boolean, 'null'] + description: Start Y2-axis at zero. Default: true. + y2AxisScaleType: + type: string + enum: [log, linear] + description: Scale type for Y2-axis. Default: linear. + additionalProperties: false -# SQL syntax variations by data source: -PostgreSQL specific: - - DATE_TRUNC('month', date_column) - - INTERVAL '30 days' - - date_column::date - - EXTRACT(YEAR FROM date_column) - - STRING_AGG(column, ', ') + category_axis_style_config: + type: object + description: Style configuration for the category axis (color/grouping). + properties: + categoryAxisTitle: + type: [string, 'null'] + description: Title for the category axis. + additionalProperties: false -MySQL specific: - - DATE_FORMAT(date_column, '%Y-%m') - - DATE_SUB(NOW(), INTERVAL 30 DAY) - - CAST(date_column AS DATE) - - YEAR(date_column) - - GROUP_CONCAT(column SEPARATOR ', ') + # COLUMN FORMATTING + column_label_format: + type: object + properties: + columnType: + type: string + description: number, string, date + enum: [number, string, date] + style: + type: string + enum: + - currency # Note: The "$" sign is automatically prepended. + - percent # Note: "%" sign is appended. For percentage values: + # - If the value comes directly from a database column, use multiplier: 1 + # - If the value is calculated in your SQL query and not already multiplied by 100, use multiplier: 100 + - number + - date # Note: For date columns, consider setting xAxisTimeInterval in xAxisConfig to control date grouping (day, week, month, quarter, year) + - string + multiplier: + type: number + description: Value to multiply the number by before display. Default value is 1. For percentages, the multiplier depends on how the data is sourced: if the value comes directly from a database column, use multiplier: 1; if the value is calculated in your SQL query and not already multiplied by 100, use multiplier: 100. + displayName: + type: string + description: Custom display name for the column + numberSeparatorStyle: + type: string + description: Style for number separators. Your option is ',' or a null value. Not null wrapped in quotes, a null value. + minimumFractionDigits: + type: integer + description: Minimum number of fraction digits to display + maximumFractionDigits: + type: integer + description: Maximum number of fraction digits to display + prefix: + type: string + suffix: + type: string + replaceMissingDataWith: + type: number + description: Value to display when data is missing, needs to be set to 0. Should only be set on number columns. All others should be set to null. + compactNumbers: + type: boolean + description: Whether to display numbers in compact form (e.g., 1K, 1M) + currency: + type: string + description: Currency code for currency formatting (e.g., USD, EUR) + dateFormat: + type: string + description: | + Format string for date display (must be compatible with Day.js format strings). + RULE: Choose format based on xAxisTimeInterval: + - year: 'YYYY' (e.g., 2025) + - quarter: '[Q]Q YYYY' (e.g., Q1 2025) + - month: 'MMM YYYY' (e.g., Jan 2025) or 'MMMM' (e.g., January) if context is clear. + - week/day: 'MMM D, YYYY' (e.g., Jan 25, 2025) or 'MMM D' (e.g., Jan 25) if context is clear. + useRelativeTime: + type: boolean + description: Whether to display dates as relative time (e.g., 2 days ago) + isUtc: + type: boolean + description: Whether to interpret dates as UTC + convertNumberTo: + type: string + description: Optional. Convert numeric values to time units or date parts. This is a necessity for time series data when numbers are passed instead of the date. + enum: + - day_of_week + - month_of_year + - quarter -BigQuery specific: - - DATE_TRUNC(date_column, MONTH) - - DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) - - CAST(date_column AS DATE) - - EXTRACT(YEAR FROM date_column) - - STRING_AGG(column, ', ') + required: + - columnType + - style + - replaceMissingDataWith + - numberSeparatorStyle -Snowflake specific: - - DATE_TRUNC('month', date_column) - - DATEADD(day, -30, CURRENT_DATE()) - - date_column::date - - YEAR(date_column) - - LISTAGG(column, ', ') + # COLUMN VISUAL SETTINGS + column_settings: + type: object + description: Optional visual settings per LOWERCASE column name. + properties: + showDataLabels: + type: boolean + columnVisualization: + type: string + enum: + - bar + - line + - dot + lineWidth: + type: number + lineStyle: + type: string + enum: + - area + - line + lineType: + type: string + enum: + - normal + - smooth + - step -# Common SQL patterns: -Time-based aggregation: -```sql -SELECT - DATE_TRUNC('month', date) as period, - SUM(value) as total -FROM table -GROUP BY 1 -ORDER BY 1 -``` + # CHART-SPECIFIC CONFIGURATIONS + bar_line_chart_config: + allOf: + - \$ref: #/definitions/base_chart_config + - type: object + properties: + selectedChartType: + enum: + - bar + - line + barAndLineAxis: + type: object + properties: + x: + type: array + items: + type: string + y: + type: array + items: + type: string + description: LOWERCASE column name from SQL for X-axis. + category: + type: array + items: + type: string + description: LOWERCASE column name from SQL for category grouping. + required: + - x + - y + barLayout: + type: string + enum: + - horizontal + - vertical + barGroupType: + type: string + enum: + - stack + - group + - percentage-stack + required: + - selectedChartType + - barAndLineAxis -Running totals: -```sql -SELECT - date, - value, - SUM(value) OVER (ORDER BY date) as running_total -FROM table -ORDER BY date -``` + scatter_chart_config: + allOf: + - \$ref: #/definitions/base_chart_config + - type: object + properties: + selectedChartType: + enum: + - scatter + scatterAxis: + type: object + properties: + x: + type: array + items: + type: string + y: + type: array + items: + type: string + category: + type: array + items: + type: string + size: + type: array + items: + type: string + required: + - x + - y + required: + - selectedChartType + - scatterAxis -Year-over-year comparison: -```sql -SELECT - DATE_TRUNC('month', date) as month, - SUM(CASE WHEN YEAR(date) = YEAR(CURRENT_DATE) THEN value END) as current_year, - SUM(CASE WHEN YEAR(date) = YEAR(CURRENT_DATE) - 1 THEN value END) as previous_year -FROM table -GROUP BY 1 -ORDER BY 1 -``` + pie_chart_config: + allOf: + - \$ref: #/definitions/base_chart_config + - type: object + properties: + selectedChartType: + enum: + - pie + pieChartAxis: + type: object + properties: + x: + type: array + items: + type: string + y: + type: array + items: + type: string + required: + - x + - y + required: + - selectedChartType + - pieChartAxis -Moving average: -```sql -SELECT - date, - value, - AVG(value) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) as ma7 -FROM table -ORDER BY date -``` + combo_chart_config: + allOf: + - \$ref: #/definitions/base_chart_config + - type: object + properties: + selectedChartType: + enum: + - combo + comboChartAxis: + type: object + properties: + x: + type: array + items: + type: string + y: + type: array + items: + type: string + y2: + type: array + items: + type: string + required: + - x + - y + - y2 + required: + - selectedChartType + - comboChartAxis -Cohort analysis: -```sql -WITH cohorts AS ( - SELECT - DATE_TRUNC('month', first_purchase_date) as cohort_month, - customer_id - FROM customers -) -SELECT - cohort_month, - DATE_TRUNC('month', purchase_date) as purchase_month, - COUNT(DISTINCT customer_id) as customers -FROM cohorts c -JOIN purchases p USING (customer_id) -GROUP BY 1, 2 -ORDER BY 1, 2 -``` + metric_chart_config: + allOf: + - \$ref: #/definitions/base_chart_config + - type: object + properties: + selectedChartType: + enum: + - metric + metricColumnId: + type: string + description: LOWERCASE column name from SQL for the main metric value. + metricValueAggregate: + type: string + enum: + - sum + - average + - median + - max + - min + - count + - first + description: Aggregate function for metric value + metricHeader: + oneOf: + - type: string + description: Simple string title for the metric header + - type: object + properties: + columnId: + type: string + description: Which column to use for the header + useValue: + type: boolean + description: Whether to display the key or the value in the chart + aggregate: + type: string + enum: + - sum + - average + - median + - max + - min + - count + - first + description: Optional aggregation method, defaults to sum + required: + - columnId + - useValue + description: Configuration for a derived metric header + metricSubHeader: + oneOf: + - type: string + description: Simple string title for the metric sub-header + - type: object + properties: + columnId: + type: string + description: Which column to use for the sub-header + useValue: + type: boolean + description: Whether to display the key or the value in the chart + aggregate: + type: string + enum: + - sum + - average + - median + - max + - min + - count + - first + description: Optional aggregation method, defaults to sum + required: + - columnId + - useValue + description: Configuration for a derived metric sub-header + required: + - selectedChartType + - metricColumnId -# Validation rules for metric creation: -Required validations: - 1. name: Must be non-empty string, no special characters except spaces/dashes - 2. type: Must be exactly "metric" - 3. sql: Must be valid SQL syntax for the data source - 4. selectedChartType: Must be valid enum value - 5. data: Must contain required fields for chart type - 6. columnLabelFormats: Must include ALL columns from SQL result - 7. xAxis/yAxis: Column names must be lowercase - 8. barAndLineAxis: Must specify both bars and lines arrays - 9. scatterAxis: Must specify at least xAxis and yAxis - 10. tableColumns: Must have id, label, and columnType for each column + table_chart_config: + allOf: + - \$ref: #/definitions/base_chart_config + - type: object + properties: + selectedChartType: + enum: + - table + tableColumnOrder: + type: array + items: + type: string + required: + - selectedChartType + # No additional required fields for table chart -# Error messages and troubleshooting: -Common errors: - - "Column 'X' not found": Check column name casing and SQL aliases - - "Invalid chart type": Use exact enum value from selectedChartType list - - "Missing required field": Check requirements for specific chart type - - "Invalid date format": Use valid strftime format strings - - "Type mismatch": Ensure columnLabelFormats type matches actual data - - "SQL syntax error": Check data source specific syntax - - "Permission denied": Verify user has access to referenced tables - - "Timeout exceeded": Optimize query or increase timeout setting - - "Invalid YAML": Check indentation and special character escaping - - "Duplicate metric name": Use unique names for each metric + # HELPER OBJECTS + goal_line: + type: object + properties: + show: + type: boolean + value: + type: number + goalLineLabel: + type: string + trendline: + type: object + properties: + type: + type: string + enum: + - average + - linear_regression + - min + - max + - median + columnId: + type: string + required: + - type + - columnId ``` **CRITICAL:** This is the complete schema specification. Follow it exactly - every property, enum value, and requirement listed above must be respected. Pay special attention to: