@fusedashlabs/ui9000-workspace
Version:
UI9000 workspace MCP. One tool, show_workspace, draws a chart from your table. Set TYPESAFE_API_KEY to let Jev choose the chart.
436 lines (435 loc) • 21.5 kB
TypeScript
/**
* Visual families for the widgets charts.
*
* `show_workspace` asks Jev for a class, then a drawing inside that class.
* A named chart in that class is drawn. A named chart in another class waits
* for the user. When Jev does not answer, `decide()` still picks the chart.
* Many widgets draw the same columns with a different mark. This file records
* that: bar is the comparison main, and the same category + metric can also
* be a lollipop, a line, or an area when the `when` holds.
*
* It does not add charts to the frozen 20-id engine catalog.
*/
export type ChartRole = {
/** widgets component id (`metadata.json` `id`). */
id: string;
/** FuseDash `chartType` keys this component already renders. */
chartTypeKeys: readonly string[];
/** What this drawing is for. */
role: string;
/** Columns or payload this drawing needs. */
data: string;
/** What the mark encodes. */
visual: string;
};
export type ChartAlternative = {
id: string;
/** When this drawing is a faithful reading of the family's data. */
when: string;
};
export type ChartFamily = {
id: string;
/** The question the family answers. */
question: string;
/** Shared data shape. */
data: string;
/** The chart the engine should select for this question. */
main: string;
/** Other drawings of the same data. Closest substitutes first. */
alternatives: readonly ChartAlternative[];
};
export declare const CHART_ROLES: {
readonly 'bar-chart': {
readonly id: "bar-chart";
readonly chartTypeKeys: readonly ["barChart", "barGrouped", "barStacked", "cumulativeBar", "barHorizontal", "barHorizontalGrouped", "barHorizontalStacked"];
readonly role: "Compare discrete groups on one metric.";
readonly data: "Category, one number, optional second category as a series.";
readonly visual: "Bar length. Vertical or horizontal; plain, grouped, stacked, or with a cumulative line.";
};
readonly lollipop: {
readonly id: "lollipop";
readonly chartTypeKeys: readonly ["lollipopChart", "lollipopGroupedChart", "lollipopStackedChart"];
readonly role: "Same comparison as a bar, drawn as a stem and a dot.";
readonly data: "Category, one number, optional series.";
readonly visual: "Stem length plus a head. Vertical or horizontal; plain, grouped, or stacked.";
};
readonly 'line-chart': {
readonly id: "line-chart";
readonly chartTypeKeys: readonly ["lineChart", "lineGroupedChart"];
readonly role: "Show how a metric moves along an ordered axis.";
readonly data: "Ordered x (time or sequence) and a number, optional series.";
readonly visual: "Connected points. One line, or one line per series.";
};
readonly 'area-chart': {
readonly id: "area-chart";
readonly chartTypeKeys: readonly ["areaChart", "areaStackedChart"];
readonly role: "Same ordered series as a line, with the region under the line filled.";
readonly data: "Ordered x and a number, optional series.";
readonly visual: "Filled area. Grouped or stacked.";
};
readonly 'area-grouped-bar-chart': {
readonly id: "area-grouped-bar-chart";
readonly chartTypeKeys: readonly ["areaGroupedBarChart"];
readonly role: "Compare groups with bars and overlay an area or line on the same categories.";
readonly data: "Category, a bar metric, and a second series for the overlay.";
readonly visual: "Grouped bars plus an area or line. Vertical only.";
};
readonly 'radial-bar-chart': {
readonly id: "radial-bar-chart";
readonly chartTypeKeys: readonly ["radialBarChart"];
readonly role: "Compare a few categories by ring length instead of a bar.";
readonly data: "Category and one number. Few categories.";
readonly visual: "One ring per category over a 270° sweep.";
};
readonly 'polar-area-chart': {
readonly id: "polar-area-chart";
readonly chartTypeKeys: readonly ["polarAreaChart"];
readonly role: "Compare a few categories by wedge radius.";
readonly data: "Category and one number, optional group.";
readonly visual: "Coxcomb slices. Radius is the metric, not the share of a whole.";
};
readonly 'pie-chart': {
readonly id: "pie-chart";
readonly chartTypeKeys: readonly ["pieChart"];
readonly role: "Show each category as a share of a total.";
readonly data: "Categories whose metric sums to a whole. Low cardinality.";
readonly visual: "Full disc. Angle is the share.";
};
readonly 'donut-chart': {
readonly id: "donut-chart";
readonly chartTypeKeys: readonly ["donutChart"];
readonly role: "Same shares as a pie, with a hole in the middle.";
readonly data: "Same as pie: categories that sum to a whole.";
readonly visual: "Ring. Angle is the share.";
};
readonly 'treemap-chart': {
readonly id: "treemap-chart";
readonly chartTypeKeys: readonly ["treemapChart"];
readonly role: "Show magnitude, or a share of a total, as tile area. A second category nests tiles.";
readonly data: "Category and a number. Optional subgroup for one card per group.";
readonly visual: "Area-proportional tiles. Color follows magnitude.";
};
readonly 'histogram-chart': {
readonly id: "histogram-chart";
readonly chartTypeKeys: readonly ["histogramChart"];
readonly role: "Show the shape of one numeric variable.";
readonly data: "Numeric samples, binned. Optional series stacks the bins.";
readonly visual: "Adjacent bars along a linear x-axis.";
};
readonly 'box-plot-chart': {
readonly id: "box-plot-chart";
readonly chartTypeKeys: readonly ["boxplotChart"];
readonly role: "Summarize a numeric sample per category: median, quartiles, outliers.";
readonly data: "Numeric samples, split by a category.";
readonly visual: "Box, whiskers, and outlier points. Vertical or horizontal.";
};
readonly 'violin-chart': {
readonly id: "violin-chart";
readonly chartTypeKeys: readonly ["violinChart"];
readonly role: "Show the density of a numeric sample per category, with a box inside.";
readonly data: "Numeric samples, split by a category.";
readonly visual: "Kernel density plus a box overlay.";
};
readonly 'scatter-plot-chart': {
readonly id: "scatter-plot-chart";
readonly chartTypeKeys: readonly ["scatterplotChart", "qqPlot"];
readonly role: "Show the relationship between two numbers. Also a QQ plot of quantiles.";
readonly data: "Numeric x, numeric y, optional group.";
readonly visual: "One point per row. Color marks the group.";
};
readonly 'bubble-chart': {
readonly id: "bubble-chart";
readonly chartTypeKeys: readonly ["bubbleChart"];
readonly role: "Same two-number relationship as a scatter, with a third number as size.";
readonly data: "Numeric x, numeric y, a size number, optional group.";
readonly visual: "Point radius from the absolute size. Color marks the group.";
};
readonly 'matrix-chart': {
readonly id: "matrix-chart";
readonly chartTypeKeys: readonly ["matrixChart"];
readonly role: "Show the metric at each pair of categories.";
readonly data: "Row category, column category, one number.";
readonly visual: "Cell color on a sequential palette.";
};
readonly 'punchcard-chart': {
readonly id: "punchcard-chart";
readonly chartTypeKeys: readonly ["punchcardChart"];
readonly role: "Same two-category grid as a matrix, drawn as dots.";
readonly data: "Row category, column category, one number.";
readonly visual: "Dot size (and position) encodes the metric.";
};
readonly 'radar-chart': {
readonly id: "radar-chart";
readonly chartTypeKeys: readonly ["radarChart", "radarGroupedChart"];
readonly role: "Compare one or a few entities across several metrics on a shared scale.";
readonly data: "Few entities, several numeric axes.";
readonly visual: "Polygon on a polar grid. One shape, or one per series.";
};
readonly 'parallel-coordinates-chart': {
readonly id: "parallel-coordinates-chart";
readonly chartTypeKeys: readonly ["parallelCoordinatesChart"];
readonly role: "Compare many records across several numeric dimensions.";
readonly data: "Many rows. Every numeric column is an axis.";
readonly visual: "One polyline per record. Color follows the active axis.";
};
readonly 'sankey-chart': {
readonly id: "sankey-chart";
readonly chartTypeKeys: readonly ["sankeyChart"];
readonly role: "Show how much moves from a source category to a target category.";
readonly data: "Source, target, and a value.";
readonly visual: "Nodes and value-coloured ribbons.";
};
readonly 'waterfall-chart': {
readonly id: "waterfall-chart";
readonly chartTypeKeys: readonly ["waterfallChart"];
readonly role: "Show how signed steps add up to a total.";
readonly data: "Ordered categories and a signed delta, or a running level.";
readonly visual: "Floating bars. Vertical or horizontal.";
};
readonly 'map-chart': {
readonly id: "map-chart";
readonly chartTypeKeys: readonly ["mapChart", "UniversalMap"];
readonly role: "Place a metric on geography.";
readonly data: "Region id or lat/lng, optional magnitude.";
readonly visual: "Choropleth fill, bubbles, or spikes on a map.";
};
readonly 'network-graph': {
readonly id: "network-graph";
readonly chartTypeKeys: readonly ["networkGraphChart"];
readonly role: "Show what is connected to what.";
readonly data: "Nodes and links.";
readonly visual: "Force layout. Node size from a value, color from a category.";
};
readonly 'kpi-widget': {
readonly id: "kpi-widget";
readonly chartTypeKeys: readonly ["KPI", "KPIs"];
readonly role: "State a headline card: one number, its change, current versus previous, or the high and low of a category.";
readonly data: "One metric. A change, a previous period, or a category for high and low, when that reading was asked.";
readonly visual: "Cards, not a plot.";
};
readonly 'status-gauge-widget': {
readonly id: "status-gauge-widget";
readonly chartTypeKeys: readonly ["statusGaugeWidget"];
readonly role: "State one health score as a dial, plus the measures behind it.";
readonly data: "A health or condition score that already exists, plus at least one other measure. Optional unit, status, min, and max.";
readonly visual: "Semicircular health gauge and KPI cards with ticked range bars.";
};
readonly 'step-line-chart': {
readonly id: "step-line-chart";
readonly chartTypeKeys: readonly ["stepLineChart", "ksPlotChart", "rocCurveChart"];
readonly role: "Show a metric that holds until the next x. Also KS and ROC reference overlays.";
readonly data: "Ordered x and a number, optional series. KS/ROC add a reference curve.";
readonly visual: "Step line. `ksPlotChart` draws the ideal curve; `rocCurveChart` draws the diagonal.";
};
readonly 'spark-line-chart': {
readonly id: "spark-line-chart";
readonly chartTypeKeys: readonly ["sparkLineChart"];
readonly role: "Compact reading of a datetime series.";
readonly data: "Datetime x and a number, optional series.";
readonly visual: "Line with axes and a crosshair.";
};
readonly 'spark-area-chart': {
readonly id: "spark-area-chart";
readonly chartTypeKeys: readonly ["sparkAreaChart"];
readonly role: "Compact datetime series with the region under the line filled.";
readonly data: "Datetime x and a number, optional series.";
readonly visual: "Line filled to y = 0.";
};
readonly 'scatter-sparkline-chart': {
readonly id: "scatter-sparkline-chart";
readonly chartTypeKeys: readonly ["scatterSparklineChart"];
readonly role: "Datetime series as a line, with the underlying points still visible.";
readonly data: "Datetime x, a number, and the raw points.";
readonly visual: "Aggregated line with gradient fill plus jittered markers.";
};
readonly 'partial-dependence-chart': {
readonly id: "partial-dependence-chart";
readonly chartTypeKeys: readonly ["partialDependenceChart"];
readonly role: "Show how a model prediction moves as one feature changes.";
readonly data: "Feature values, ICE curves, and their average.";
readonly visual: "Faint ICE lines under a dashed average.";
};
readonly 'bias-variance-tradeoff-chart': {
readonly id: "bias-variance-tradeoff-chart";
readonly chartTypeKeys: readonly ["biasVarianceTradeoffChart"];
readonly role: "Show bias, variance, and total error against model complexity.";
readonly data: "Complexity on x and the three error curves.";
readonly visual: "Fixed diagnostic lines, not a general series.";
};
readonly 'gini-impurity-entropy-chart': {
readonly id: "gini-impurity-entropy-chart";
readonly chartTypeKeys: readonly ["giniImpurityEntropyChart"];
readonly role: "Show impurity of a binary split across the class probability.";
readonly data: "Probability p, and the entropy / Gini / misclassification curves.";
readonly visual: "Fixed diagnostic curves, optional split annotations.";
};
};
export type ChartId = keyof typeof CHART_ROLES;
export declare const CHART_FAMILIES: readonly [{
readonly id: "category-magnitude";
readonly question: "How do discrete groups compare on one metric?";
readonly data: "One category, one number, optional second category as a series.";
readonly main: "bar-chart";
readonly alternatives: readonly [{
readonly id: "lollipop";
readonly when: "Same axes. Prefer it when a stem and a dot stay readable.";
}, {
readonly id: "line-chart";
readonly when: "The category has an order (time or sequence), so the slope means something.";
}, {
readonly id: "area-chart";
readonly when: "The category is ordered and the fill should show volume, not only the slope.";
}, {
readonly id: "area-grouped-bar-chart";
readonly when: "The same categories need bars and an area or line overlay together.";
}, {
readonly id: "radial-bar-chart";
readonly when: "Few categories, and ring length is the comparison.";
}, {
readonly id: "polar-area-chart";
readonly when: "Few categories, and wedge radius is the comparison. Not a share of a whole.";
}];
}, {
readonly id: "part-to-whole";
readonly question: "What share of a total does each category take?";
readonly data: "Categories whose metric sums to a whole. Low cardinality.";
readonly main: "pie-chart";
readonly alternatives: readonly [{
readonly id: "donut-chart";
readonly when: "Same slices. The hole is only a drawing change.";
}, {
readonly id: "treemap-chart";
readonly when: "Area should carry the share, or a second category nests tiles inside each group.";
}];
}, {
readonly id: "ordered-series";
readonly question: "How does a metric move along an ordered axis?";
readonly data: "Ordered x (time or sequence) and a number, optional series.";
readonly main: "line-chart";
readonly alternatives: readonly [{
readonly id: "area-chart";
readonly when: "Same line. The fill shows volume under it.";
}, {
readonly id: "step-line-chart";
readonly when: "The value holds until the next x, or the chart is a KS / ROC overlay.";
}, {
readonly id: "spark-line-chart";
readonly when: "The x is datetime and the reading should stay compact.";
}, {
readonly id: "spark-area-chart";
readonly when: "Compact datetime series with a fill to zero.";
}, {
readonly id: "scatter-sparkline-chart";
readonly when: "The datetime line should keep the raw points visible.";
}, {
readonly id: "bar-chart";
readonly when: "The ordered x is a short list of categories and the reading is a comparison, not a slope.";
}];
}, {
readonly id: "distribution";
readonly question: "What shape does a numeric variable take?";
readonly data: "Numeric samples. Optional category that splits the sample.";
readonly main: "histogram-chart";
readonly alternatives: readonly [{
readonly id: "box-plot-chart";
readonly when: "The sample is split by category and the reading is quartiles and outliers.";
}, {
readonly id: "violin-chart";
readonly when: "The sample is split by category and the reading is the density, not only the bins.";
}];
}, {
readonly id: "two-measures";
readonly question: "How do two numeric measures relate?";
readonly data: "Numeric x, numeric y, optional group.";
readonly main: "scatter-plot-chart";
readonly alternatives: readonly [{
readonly id: "bubble-chart";
readonly when: "A third number should set the point size.";
}];
}, {
readonly id: "two-way-magnitude";
readonly question: "What is the metric at each pair of categories?";
readonly data: "Row category, column category, one number.";
readonly main: "matrix-chart";
readonly alternatives: readonly [{
readonly id: "punchcard-chart";
readonly when: "The same grid should be dots sized by the metric, not colored cells.";
}];
}, {
readonly id: "many-metrics";
readonly question: "How does an entity compare across several metrics?";
readonly data: "Several numeric measures. One profile, or many records.";
readonly main: "radar-chart";
readonly alternatives: readonly [{
readonly id: "parallel-coordinates-chart";
readonly when: "There are many records, not one or a few profiles.";
}];
}, {
readonly id: "flow";
readonly question: "How much moves from a source category to a target category?";
readonly data: "Source, target, and a value.";
readonly main: "sankey-chart";
readonly alternatives: readonly [];
}, {
readonly id: "contribution";
readonly question: "How do signed steps add up to a total?";
readonly data: "Ordered categories and a signed delta, or a running level.";
readonly main: "waterfall-chart";
readonly alternatives: readonly [];
}, {
readonly id: "spatial";
readonly question: "Where is the metric?";
readonly data: "Region id or lat/lng, optional magnitude.";
readonly main: "map-chart";
readonly alternatives: readonly [];
}, {
readonly id: "graph";
readonly question: "What is connected to what?";
readonly data: "Nodes and links.";
readonly main: "network-graph";
readonly alternatives: readonly [];
}, {
readonly id: "headline";
readonly question: "What headline card fits: one number, its change, current versus previous, or the high and low category?";
readonly data: "One metric. Optional change, previous period, or a category that splits high and low.";
readonly main: "kpi-widget";
readonly alternatives: readonly [{
readonly id: "status-gauge-widget";
readonly when: "At least two measures, and one of them is already a health or condition score. The dial is that score. Do not invent it.";
}];
}, {
readonly id: "model-dependence";
readonly question: "How does a model prediction move as one feature changes?";
readonly data: "Feature values and ICE curves.";
readonly main: "partial-dependence-chart";
readonly alternatives: readonly [];
}, {
readonly id: "model-error";
readonly question: "How do bias and variance trade off against complexity?";
readonly data: "Complexity and the bias, variance, and total-error curves.";
readonly main: "bias-variance-tradeoff-chart";
readonly alternatives: readonly [];
}, {
readonly id: "model-impurity";
readonly question: "How impure is a binary split across the class probability?";
readonly data: "Class probability and the impurity curves.";
readonly main: "gini-impurity-entropy-chart";
readonly alternatives: readonly [];
}];
export declare function chartRole(id: string): ChartRole | undefined;
/** Words for a chart. The component id stays on the spec. */
export declare function chartName(id: string): string;
/** Name plus what the drawing shows, so a reply never says `bar-chart`. */
export declare function chartLabel(id: string): string;
/** Families where this chart is the main drawing or an alternative. */
export declare function familiesForChart(id: string): ChartFamily[];
export type ChartDrawings = {
family: ChartFamily;
main: ChartRole;
alternatives: ChartRole[];
};
/**
* The main chart and the other drawings of the same data.
* Looks up the family whose `main` is this id.
*/
export declare function drawingsFor(mainId: string): ChartDrawings | undefined;