@sqlrooms/deck 0.29.0-rc.8 → 0.29.0-rc.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -6
- package/dist/DeckJsonMap.d.ts +2 -2
- package/dist/DeckJsonMap.d.ts.map +1 -1
- package/dist/DeckJsonMap.js +202 -19
- package/dist/DeckJsonMap.js.map +1 -1
- package/dist/DeckJsonMapSpec.d.ts +36 -36
- package/dist/DeckJsonMapSpec.d.ts.map +1 -1
- package/dist/DeckJsonMapSpec.js +1 -0
- package/dist/DeckJsonMapSpec.js.map +1 -1
- package/dist/MapSettings.d.ts.map +1 -1
- package/dist/MapSettings.js +202 -25
- package/dist/MapSettings.js.map +1 -1
- package/dist/ai.d.ts +55 -8
- package/dist/ai.d.ts.map +1 -1
- package/dist/ai.js +190 -41
- package/dist/ai.js.map +1 -1
- package/dist/block.d.ts +20 -0
- package/dist/block.d.ts.map +1 -0
- package/dist/block.js +119 -0
- package/dist/block.js.map +1 -0
- package/dist/dashboard.d.ts +2 -8
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +194 -289
- package/dist/dashboard.js.map +1 -1
- package/dist/dashboardConfig.d.ts +11 -3
- package/dist/dashboardConfig.d.ts.map +1 -1
- package/dist/dashboardConfig.js +82 -7
- package/dist/dashboardConfig.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/json/aggregateWaypoints.d.ts +14 -0
- package/dist/json/aggregateWaypoints.d.ts.map +1 -0
- package/dist/json/aggregateWaypoints.js +190 -0
- package/dist/json/aggregateWaypoints.js.map +1 -0
- package/dist/json/compileColorScale.d.ts +1 -1
- package/dist/json/compileColorScale.d.ts.map +1 -1
- package/dist/json/compileColorScale.js +42 -20
- package/dist/json/compileColorScale.js.map +1 -1
- package/dist/json/createDeckJsonConfiguration.d.ts.map +1 -1
- package/dist/json/createDeckJsonConfiguration.js +106 -8
- package/dist/json/createDeckJsonConfiguration.js.map +1 -1
- package/dist/json/defaultClasses.d.ts +5 -4
- package/dist/json/defaultClasses.d.ts.map +1 -1
- package/dist/json/defaultClasses.js +9 -4
- package/dist/json/defaultClasses.js.map +1 -1
- package/dist/json/extractColorScaleLegends.d.ts.map +1 -1
- package/dist/json/extractColorScaleLegends.js +43 -5
- package/dist/json/extractColorScaleLegends.js.map +1 -1
- package/dist/json/heatmapDefaults.d.ts +8 -0
- package/dist/json/heatmapDefaults.d.ts.map +1 -0
- package/dist/json/heatmapDefaults.js +14 -0
- package/dist/json/heatmapDefaults.js.map +1 -0
- package/dist/json/layerCompatibility.d.ts.map +1 -1
- package/dist/json/layerCompatibility.js +5 -1
- package/dist/json/layerCompatibility.js.map +1 -1
- package/dist/json/layers/DeckColumnLayer.d.ts +12 -0
- package/dist/json/layers/DeckColumnLayer.d.ts.map +1 -0
- package/dist/json/layers/DeckColumnLayer.js +26 -0
- package/dist/json/layers/DeckColumnLayer.js.map +1 -0
- package/dist/json/layers/DeckH3HexagonLayer.d.ts +37 -0
- package/dist/json/layers/DeckH3HexagonLayer.d.ts.map +1 -0
- package/dist/json/layers/DeckH3HexagonLayer.js +96 -0
- package/dist/json/layers/DeckH3HexagonLayer.js.map +1 -0
- package/dist/json/layers/DeckTripsLayer.d.ts +45 -0
- package/dist/json/layers/DeckTripsLayer.d.ts.map +1 -0
- package/dist/json/layers/DeckTripsLayer.js +169 -0
- package/dist/json/layers/DeckTripsLayer.js.map +1 -0
- package/dist/json/layers/index.d.ts +4 -0
- package/dist/json/layers/index.d.ts.map +1 -0
- package/dist/json/layers/index.js +4 -0
- package/dist/json/layers/index.js.map +1 -0
- package/dist/json/rewriteGeoArrowAccessors.d.ts.map +1 -1
- package/dist/json/rewriteGeoArrowAccessors.js +5 -0
- package/dist/json/rewriteGeoArrowAccessors.js.map +1 -1
- package/dist/mapConfigUtils.d.ts +102 -1
- package/dist/mapConfigUtils.d.ts.map +1 -1
- package/dist/mapConfigUtils.js +21 -3
- package/dist/mapConfigUtils.js.map +1 -1
- package/dist/mapLayerConfigUtils.d.ts +15 -0
- package/dist/mapLayerConfigUtils.d.ts.map +1 -1
- package/dist/mapLayerConfigUtils.js +109 -7
- package/dist/mapLayerConfigUtils.js.map +1 -1
- package/dist/prepare/detectGeometryColumn.d.ts +10 -1
- package/dist/prepare/detectGeometryColumn.d.ts.map +1 -1
- package/dist/prepare/detectGeometryColumn.js +48 -6
- package/dist/prepare/detectGeometryColumn.js.map +1 -1
- package/dist/prepare/wkbDecoder.d.ts.map +1 -1
- package/dist/prepare/wkbDecoder.js +88 -1
- package/dist/prepare/wkbDecoder.js.map +1 -1
- package/dist/prepare/wkbParser.d.ts +5 -0
- package/dist/prepare/wkbParser.d.ts.map +1 -1
- package/dist/prepare/wkbParser.js +24 -0
- package/dist/prepare/wkbParser.js.map +1 -1
- package/dist/types.d.ts +14 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/useDeckMapDatasets.d.ts +17 -0
- package/dist/useDeckMapDatasets.d.ts.map +1 -0
- package/dist/useDeckMapDatasets.js +69 -0
- package/dist/useDeckMapDatasets.js.map +1 -0
- package/dist/useDeckMapFitToBounds.d.ts +29 -0
- package/dist/useDeckMapFitToBounds.d.ts.map +1 -0
- package/dist/useDeckMapFitToBounds.js +333 -0
- package/dist/useDeckMapFitToBounds.js.map +1 -0
- package/package.json +7 -6
package/dist/ai.d.ts
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
import { type Tool } from 'ai';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { type CreateDashboardAgentToolOptions, type CreateDashboardAiToolsOptions,
|
|
4
|
-
export declare const DECK_MAP_AI_INSTRUCTIONS = "\nDeck map tools:\n- create_deck_map_config validates and returns a reusable native Deck JSON map config without requiring a dashboard artifact.\n- create_dashboard_map creates or updates an interactive map panel inside a dashboard from a native Deck JSON map config.\n- Use map tools when the user asks for a map, geospatial/spatial visualization, locations, longitude/latitude data, or geometry columns.\n- Author maps with config.spec.layers using Deck JSON layer classes in @@type, such as GeoArrowScatterplotLayer, GeoArrowHeatmapLayer, GeoArrowPolygonLayer, GeoArrowPathLayer, or GeoArrowArcLayer.\n- Bind layers to datasets with _sqlroomsBinding.dataset and put tableName or sqlQuery sources in config.datasets.\n- For data-driven color, use native Deck JSON accessors with {\"@@function\":\"colorScale\", \"field\":\"...\", \"type\":\"sequential\"|\"diverging\"|\"quantize\"|\"quantile\"|\"categorical\", \"scheme\":\"Viridis\", \"domain\":\"auto\"} on color properties such as getFillColor, getLineColor, getColor, getSourceColor, or getTargetColor.\n- Map panels default to a 100000-row runtime data limit; use config.dataPolicy.maxRows only when the map genuinely needs a panel-specific limit.\n- After calling create_dashboard_map, call list_dashboard_panels before your final response and check the map panel issue. If it has a render-error, repair the map config in place instead of saying the map is complete.\n";
|
|
3
|
+
import { DashboardAiAdapter, type CreateDashboardAgentToolOptions, type CreateDashboardAiToolsOptions, DatabaseAiAdapter, MosaicDashboardStoreState } from '@sqlrooms/mosaic';
|
|
4
|
+
export declare const DECK_MAP_AI_INSTRUCTIONS = "\nDeck map tools:\n- create_deck_map_config validates and returns a reusable native Deck JSON map config without requiring a dashboard artifact.\n- create_dashboard_map creates or updates an interactive map panel inside a dashboard from a native Deck JSON map config.\n- Use map tools when the user asks for a map, geospatial/spatial visualization, locations, longitude/latitude data, or geometry columns.\n- Author maps with config.spec.layers using Deck JSON layer classes in @@type, such as GeoArrowScatterplotLayer, GeoArrowHeatmapLayer, GeoArrowPolygonLayer, GeoArrowPathLayer, GeoArrowTripsLayer, GeoArrowArcLayer, or GeoArrowH3HexagonLayer.\n- LAYER SELECTION: Choose the layer type based on the geometry type in the data.\n IMPORTANT: Only create a layer if the table contains data suitable for that layer type, or if you can transform the data into the required format with a sqlQuery. Do NOT create a layer if the data is clearly incompatible (e.g. do not create a path layer from point-only data without aggregation, do not create a polygon layer from point coordinates, do not create an arc layer without origin-destination pairs).\n - Point data (lon/lat coordinates, point geometry): GeoArrowScatterplotLayer (Point layer), GeoArrowHeatmapLayer, GeoArrowColumnLayer. Requires rows with individual point positions \u2014 either separate longitude/latitude numeric columns, or a point geometry column. Each row represents one point on the map.\n - Polygon data (building footprints, boundaries, areas, parcels, zones): GeoArrowPolygonLayer or GeoArrowSolidPolygonLayer. Requires a geometry column containing polygon or multipolygon WKB/GeoArrow data. Typically loaded from GeoJSON/Shapefile/GeoParquet or produced by spatial queries. Do NOT use for point data.\n - Line data (roads, routes, paths, rivers): GeoArrowPathLayer. CRITICAL: GeoArrowPathLayer requires LineString geometry, NOT individual point rows. If the table has one row per waypoint (indicated by columns like path_id/route_id + order/sequence + lat/lon), you MUST aggregate them with a sqlQuery: \"SELECT path_id, label, ST_AsWKB(ST_MakeLine(LIST(ST_Point(lon, lat) ORDER BY waypoint_order))) AS geom FROM tableName GROUP BY path_id, label\". Set geometryColumn to \"geom\" and geometryEncodingHint to \"wkb\". If the table already has a geometry/geom column with linestring data, use it directly with tableName. NEVER pass raw waypoint rows to GeoArrowPathLayer \u2014 it will fail.\n - Animated trip data (routes with timestamps): GeoArrowTripsLayer. Same geometry requirements as GeoArrowPathLayer (LineString), plus a timestamps column. The sqlQuery MUST aggregate both the geometry and timestamps: \"SELECT path_id, label, ST_AsWKB(ST_MakeLine(LIST(ST_Point(lon, lat) ORDER BY waypoint_order))) AS geom, LIST(timestamp ORDER BY waypoint_order) AS timestamps FROM tableName GROUP BY path_id, label\". Set geometryColumn to \"geom\", geometryEncodingHint to \"wkb\", and _sqlroomsBinding.timestampColumn to \"timestamps\". The timestamps column must be a list of numbers (seconds) matching the order of waypoints in the linestring. Also set currentTime on the layer to control animation position. Do NOT use unless the data has or can produce both paths and ordered timestamps.\n- CRITICAL geometryColumn rule: The geometryColumn field (in datasets[id].geometryColumn, _sqlroomsBinding.geometryColumn, and fitToData.geometryColumn) MUST match the exact column alias that produces the WKB geometry in the sqlQuery output \u2014 typically the \"AS geom\" alias in ST_AsWKB(...) AS geom. It must NEVER be set to a GROUP BY key, an ID column, or any other non-geometry column. For example, if the sqlQuery is \"SELECT path_id, ST_AsWKB(ST_MakeLine(...)) AS geom ... GROUP BY path_id\", geometryColumn must be \"geom\" (the geometry output), NOT \"path_id\" (the grouping key). Setting geometryColumn to a non-geometry column will cause the layer to fail silently.\n - Arc data (origin-destination pairs): GeoArrowArcLayer. Requires two sets of coordinates per row (source and target). The table must have source_lon/source_lat AND target_lon/target_lat columns (or equivalent). The dataset source MUST use a sqlQuery that creates WKB geometry columns from lat/lon, for example: \"SELECT *, ST_AsWKB(ST_Point(source_lon, source_lat)) AS source_geom, ST_AsWKB(ST_Point(target_lon, target_lat)) AS target_geom FROM tableName\". Set sourceGeometryColumn to \"source_geom\" and targetGeometryColumn to \"target_geom\". Set geometryEncodingHint to \"wkb\". To render straight lines instead of arcs, set \"getHeight\": 0 on the layer. Do NOT use for data with only one set of coordinates per row. When the source data has H3 indices instead of lat/lon, convert H3 to coordinates using h3_cell_to_lng(h3_index) and h3_cell_to_lat(h3_index) (the H3 extension is pre-loaded at startup), for example: \"SELECT *, ST_AsWKB(ST_Point(h3_cell_to_lng(source_h3), h3_cell_to_lat(source_h3))) AS source_geom, ST_AsWKB(ST_Point(h3_cell_to_lng(target_h3), h3_cell_to_lat(target_h3))) AS target_geom FROM tableName\". Do NOT use h3_latlng() \u2014 it does not exist.\n - H3 hexagon data (h3 index column): GeoArrowH3HexagonLayer. Requires a column containing H3 string indices. Bind to dataset with _sqlroomsBinding.dataset. Set \"getHexagon\": \"@@=h3_column_name\" where h3_column_name is the column containing H3 string indices. Always include \"fitToData\": {\"dataset\": \"datasetId\"} so the map can zoom to the data extent. Do NOT use unless the table has an H3 index column. DuckDB H3 extension functions: h3_cell_to_lat(index), h3_cell_to_lng(index), h3_cell_to_latlng(index). Do NOT use h3_latlng(), h3_to_lat(), or other non-existent function names.\n- CRITICAL: The sqlQuery field must contain ONLY a single SELECT statement. NEVER put INSTALL, LOAD, CREATE, or other DDL/meta-commands in sqlQuery \u2014 they will fail because sqlQuery is wrapped in a subquery at runtime. Extensions like h3 and spatial are pre-loaded at startup.\n - GeoJSON files typically contain polygon or multipolygon features (boundaries, buildings, parcels); use GeoArrowPolygonLayer for these. If a GeoJSON file contains point features, use GeoArrowScatterplotLayer (Point layer) instead.\n- RADIUS AND WIDTH: For GeoArrowScatterplotLayer (Point layer) use getRadius with radiusUnits: \"pixels\" (typically 2\u20136 pixels); large radii cause overdraw and rendering lag, especially with many points. For GeoArrowColumnLayer use the \"radius\" property (NOT getRadius) \u2014 it sets column radius in meters; typical values are 20\u2013200 for city-scale data or smaller for dense datasets. Do NOT use getRadius or radiusUnits on column layers. For GeoArrowArcLayer, GeoArrowPathLayer, and GeoArrowTripsLayer use getWidth with widthUnits: \"pixels\" (typically 1\u20133 pixels).\n- HEATMAP: For GeoArrowHeatmapLayer, do NOT set colorRange manually. The UI provides a scheme selector that generates the correct color array. If you set colorRange to hand-picked RGB arrays, it will be out of sync with the scheme selector shown in the UI. Just omit colorRange entirely and let the default apply \u2014 users can change the scheme through the map settings panel.\n- ARC vs LINE: GeoArrowArcLayer renders curved 3D arcs by default. If the user asks for \"lines\" or \"straight connections\" between origin-destination pairs (not arcs), set \"getHeight\": 0 on the layer to render flat straight lines. Use arcs for flight routes or connections where the curve adds clarity; use flat lines for direct relationships, edges, or when the user explicitly requests lines.\n- ELEVATION: For extruded layers, getElevation with @@function \"scale\" passes the raw field value as meters. Use elevationScale on the layer to multiply values to a useful visual height. For example, if the field is \"floors\" (1-10), set elevationScale to 3 (meters per floor). Do NOT use negative values for elevation. Avoid using diverging scales for elevation. IMPORTANT: Keep elevation moderate \u2014 if extruded polygons or H3 hexagons are too tall, users can't see the tops when zoomed in. Prefer elevationScale values that produce heights of a few hundred meters at most for city-scale data. A good rule of thumb: the maximum elevation (field max \u00D7 elevationScale) should not exceed ~500m for typical zoom levels.\n- Bind layers to datasets with _sqlroomsBinding.dataset and put tableName or sqlQuery sources in config.datasets.\n- Each dataset in config.datasets should have a source.tableName or source.sqlQuery that describes the original table the map was authored against. At runtime, the dashboard's selected table (from the table selector) overrides the source table \u2014 when the user switches the active table, all map panels automatically update. If the new table lacks required columns, an incompatibility error is shown.\n- IMPORTANT: Always pass tableName in the create_dashboard_map tool params (the top-level tableName field). Use the table currently selected in the dashboard (dashboard.selectedTable from list_dashboard_panels). At runtime, the dashboard's selected table always overrides the authored table \u2014 this param only seeds the initial selection when no table is selected yet.\n- IMPORTANT: If you are creating a map layer for a table that is NOT the currently selected dashboard table, you MUST switch the dashboard's selected table to that dataset BEFORE or WHEN calling create_dashboard_map (pass the correct tableName). The map panel resolves data from the dashboard's active table \u2014 if you don't switch it, the layer will query the wrong table and fail.\n- IMPORTANT: When referencing tables in tableName or sqlQuery, use ONLY the bare table name (e.g. \"my_table\") or schema-qualified name (e.g. \"main.my_table\"). NEVER include the database/catalog prefix (e.g. do NOT use \"sqlrooms-cli.main.my_table\") \u2014 the catalog does not exist in the query execution context.\n- IMPORTANT: For point data with longitude/latitude columns, the dataset source MUST use a sqlQuery that creates a geometry column, for example: \"SELECT *, ST_AsWKB(ST_Point(\\\"Longitude\\\", \\\"Latitude\\\")) AS \\\"__sqlrooms_geom\\\" FROM tableName WHERE \\\"Longitude\\\" IS NOT NULL AND \\\"Latitude\\\" IS NOT NULL\". Set geometryColumn to the same name used in the AS clause (e.g. \"__sqlrooms_geom\") and geometryEncodingHint to \"wkb\".\n- IMPORTANT: When providing fitToData, it MUST be a flat object (NOT nested by dataset ID). Include either longitudeColumn+latitudeColumn (for point data with separate coordinate columns) OR geometryColumn (for data with a WKB geometry column like GeoJSON). For H3 hexagon layers, just specify the dataset: \"fitToData\": {\"dataset\": \"datasetId\"} \u2014 the H3 column is auto-detected from the layer binding. For GeoJSON/spatial files with a \"geom\" column, use: \"fitToData\": {\"dataset\": \"datasetId\", \"geometryColumn\": \"geom\"}. For point data use: \"fitToData\": {\"dataset\": \"datasetId\", \"longitudeColumn\": \"lon\", \"latitudeColumn\": \"lat\"}. NEVER nest fitToData as {\"datasetId\": {...}} \u2014 always use a flat object with \"dataset\" as a string field.\n- IMPORTANT: For GeoJSON or spatial files that already have a native geometry column (e.g. \"geometry\", \"geom\"), use the table directly with source.tableName (no sqlQuery needed), set the dataset's geometryColumn to \"geom\", set geometryEncodingHint to \"wkb\", and use fitToData with geometryColumn: {\"dataset\": \"datasetId\", \"geometryColumn\": \"geom\"}.\n- IMPORTANT: When a GeoJSON file (.geojson) is loaded as a table, DuckDB uses ST_Read to produce a table with a WKB \"geom\" column and all feature properties as columns. Use source.tableName, set geometryColumn to \"geom\" and geometryEncodingHint to \"wkb\". Use \"fitToData\": {\"dataset\": \"datasetId\", \"geometryColumn\": \"geom\"} to zoom to the data extent.\n- For data-driven color, use native Deck JSON accessors with {\"@@function\":\"colorScale\", \"field\":\"...\", \"type\":\"sequential\"|\"diverging\"|\"quantize\"|\"quantile\"|\"categorical\", \"scheme\":\"...\", \"domain\":\"auto\"} on color properties such as getFillColor, getLineColor, getColor, getSourceColor, or getTargetColor. Valid schemes: for \"categorical\" type use one of Accent, Dark2, Paired, Pastel1, Pastel2, Set1, Set2, Set3, Tableau10, Observable10, Category10. For \"sequential\" use Viridis, Inferno, Magma, Plasma, Turbo, Blues, Greens, Oranges, Reds, Purples, etc. For \"diverging\" use RdBu, Spectral, RdYlGn, BrBG, PiYG, etc. IMPORTANT: The colorScale \"field\" must reference a column that exists in the FINAL query output (after any GROUP BY aggregation). Do not reference columns that are lost during aggregation.\n- Map panels default to a 100000-row runtime data limit; use config.dataPolicy.maxRows only when the map genuinely needs a panel-specific limit.\n- Create maps with a SINGLE layer unless the user explicitly asks for multiple layers. If you think multiple layers would better serve the user's request, ask the user for confirmation before adding them.\n- IMPORTANT: Browsers limit the number of active WebGL contexts (typically 8\u201316 per page). Each map panel uses one context. Do NOT create more than 4\u20135 map panels in a single dashboard \u2014 exceeding the limit causes older maps to lose their rendering context and show errors. If the user asks for many datasets, prefer combining compatible layers into fewer maps rather than creating one map per dataset.\n- After calling create_dashboard_map, call list_dashboard_panels before your final response and check the map panel issue. If it has a render-error, repair the map config in place instead of saying the map is complete.\n- BASEMAPS: Do NOT use Mapbox basemap styles (mapbox://styles/...) \u2014 they require a Mapbox access token which is not available. The map uses CARTO basemaps by default (positron for light, dark-matter for dark theme) which work without any token. If you need to set a custom mapStyle, use free tile providers like CARTO (https://basemaps.cartocdn.com/gl/...) or other token-free MapLibre-compatible style URLs.\n";
|
|
5
|
+
/**
|
|
6
|
+
* Returns AI instructions for dashboards with Deck.gl map support.
|
|
7
|
+
* Provides guidance on when and how to use map visualizations.
|
|
8
|
+
*
|
|
9
|
+
* @returns Instructions string for AI agents
|
|
10
|
+
*/
|
|
5
11
|
export declare function getDashboardWithDeckMapAiInstructions(): string;
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Creates dashboard AI tools with built-in Deck.gl map support.
|
|
14
|
+
* Extends standard dashboard tools with map visualization capabilities.
|
|
15
|
+
*
|
|
16
|
+
* @param options - Dashboard AI tools configuration options
|
|
17
|
+
* @returns Record mapping tool names to tool instances, including map tools
|
|
18
|
+
*/
|
|
19
|
+
export declare function createDashboardWithDeckMapAiTools(options: CreateDashboardAiToolsOptions): Record<string, Tool>;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a dashboard agent tool with built-in Deck.gl map support.
|
|
22
|
+
* Extends the standard dashboard agent with map creation capabilities.
|
|
23
|
+
*
|
|
24
|
+
* @template TState - Store state type extending MosaicDashboardStoreState
|
|
25
|
+
* @param options - Dashboard agent configuration options
|
|
26
|
+
* @returns Dashboard agent tool with map support
|
|
27
|
+
*/
|
|
28
|
+
export declare function createDashboardAgentToolWithDeckMaps<TState extends MosaicDashboardStoreState>(options: CreateDashboardAgentToolOptions<TState>): Tool;
|
|
8
29
|
export declare const DeckMapDashboardConfigParameter: z.ZodObject<{
|
|
9
30
|
spec: z.ZodObject<{
|
|
10
31
|
initialViewState: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
@@ -154,15 +175,41 @@ export declare const DeckMapDashboardToolParameters: z.ZodObject<{
|
|
|
154
175
|
}, z.core.$loose>>;
|
|
155
176
|
settingsOpen: z.ZodOptional<z.ZodBoolean>;
|
|
156
177
|
}, z.core.$loose>;
|
|
157
|
-
artifactId: z.ZodOptional<z.ZodString>;
|
|
158
178
|
tableName: z.ZodOptional<z.ZodString>;
|
|
159
|
-
createArtifactIfMissing: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
160
179
|
panelId: z.ZodOptional<z.ZodString>;
|
|
161
180
|
reasoning: z.ZodString;
|
|
162
181
|
}, z.core.$strip>;
|
|
163
182
|
export type DeckMapDashboardToolParams = z.infer<typeof DeckMapDashboardToolParameters>;
|
|
183
|
+
/**
|
|
184
|
+
* Creates a dashboard-compatible Deck map panel from the native map config
|
|
185
|
+
* used by AI tools and embeddable map surfaces.
|
|
186
|
+
*/
|
|
187
|
+
export declare function createDeckMapPanelFromNativeConfig(params: Pick<DeckMapConfigToolParams, 'title' | 'config'>): any;
|
|
164
188
|
export declare function createDeckMapConfigTool(): Tool;
|
|
189
|
+
/**
|
|
190
|
+
* Creates AI tools for Deck.gl map configuration.
|
|
191
|
+
* Returns tools for creating and configuring Deck.gl map panels.
|
|
192
|
+
*
|
|
193
|
+
* @returns Record mapping tool names to map configuration tools
|
|
194
|
+
*/
|
|
165
195
|
export declare function createDeckMapAiTools(): Record<string, Tool>;
|
|
166
|
-
|
|
167
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Parameters for creating a Deck.gl map dashboard tool.
|
|
198
|
+
* Provides adapters for dashboard and database operations.
|
|
199
|
+
*/
|
|
200
|
+
export type CreateDeckMapDashboardToolParams = {
|
|
201
|
+
/** Dashboard adapter for adding and updating map panels */
|
|
202
|
+
dashboardAdapter: DashboardAiAdapter;
|
|
203
|
+
/** Database adapter for table validation */
|
|
204
|
+
databaseAdapter: DatabaseAiAdapter;
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Creates a tool for adding Deck.gl map panels to dashboards.
|
|
208
|
+
* Supports creating new map panels or updating existing ones with native Deck JSON configs.
|
|
209
|
+
*
|
|
210
|
+
* @param params - Parameters containing dashboard and database adapters
|
|
211
|
+
* @returns Tool instance for creating/updating Deck.gl map panels
|
|
212
|
+
*/
|
|
213
|
+
export declare function createDeckMapDashboardTool({ dashboardAdapter, databaseAdapter, }: CreateDeckMapDashboardToolParams): Tool;
|
|
214
|
+
export declare function createDeckMapDashboardAiTools(params: CreateDeckMapDashboardToolParams): Record<string, Tool>;
|
|
168
215
|
//# sourceMappingURL=ai.d.ts.map
|
package/dist/ai.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,IAAI,EAAC,MAAM,IAAI,CAAC;AACnC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,IAAI,EAAC,MAAM,IAAI,CAAC;AACnC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EACL,kBAAkB,EAIlB,KAAK,+BAA+B,EACpC,KAAK,6BAA6B,EAGlC,iBAAiB,EAGjB,yBAAyB,EAC1B,MAAM,kBAAkB,CAAC;AAyB1B,eAAO,MAAM,wBAAwB,41bAoCpC,CAAC;AAWF;;;;;GAKG;AACH,wBAAgB,qCAAqC,WAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,6BAA6B,GACrC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAKtB;AAED;;;;;;;GAOG;AACH,wBAAgB,oCAAoC,CAClD,MAAM,SAAS,yBAAyB,EACxC,OAAO,EAAE,+BAA+B,CAAC,MAAM,CAAC,GAAG,IAAI,CAWxD;AA0CD,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkB1C,CAAC;AAEH,MAAM,MAAM,gCAAgC,GAAG,CAAC,CAAC,KAAK,CACpD,OAAO,+BAA+B,CACvC,CAAC;AAEF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQtC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,2BAA2B,CACnC,CAAC;AAEF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBvC,CAAC;AAEL,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,8BAA8B,CACtC,CAAC;AAsGF;;;GAGG;AACH,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,IAAI,CAAC,uBAAuB,EAAE,OAAO,GAAG,QAAQ,CAAC,OAM1D;AAmBD,wBAAgB,uBAAuB,IAAI,IAAI,CAgC9C;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAI3D;AAED;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,2DAA2D;IAC3D,gBAAgB,EAAE,kBAAkB,CAAC;IACrC,4CAA4C;IAC5C,eAAe,EAAE,iBAAiB,CAAC;CACpC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,gBAAgB,EAChB,eAAe,GAChB,EAAE,gCAAgC,GAAG,IAAI,CAqEzC;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,gCAAgC,GACvC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAItB"}
|
package/dist/ai.js
CHANGED
|
@@ -1,36 +1,108 @@
|
|
|
1
1
|
import { tool } from 'ai';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import {
|
|
3
|
+
import { MAP_TOOL_KEY, createDashboardAgentTool, createDashboardAiTools as createMosaicDashboardAiTools, ensureTable, ensurePanel, } from '@sqlrooms/mosaic';
|
|
4
4
|
import { createDeckMapDashboardPanelConfig, DECK_MAP_DASHBOARD_PANEL_TYPE, } from './dashboardConfig';
|
|
5
|
+
import { quoteDeckMapSqlIdentifier } from './mapConfigUtils';
|
|
6
|
+
function splitIdentifierPathOutsideQuotes(input) {
|
|
7
|
+
const parts = [];
|
|
8
|
+
let current = '';
|
|
9
|
+
let inQuotes = false;
|
|
10
|
+
for (const ch of input) {
|
|
11
|
+
if (ch === '"')
|
|
12
|
+
inQuotes = !inQuotes;
|
|
13
|
+
if (ch === '.' && !inQuotes) {
|
|
14
|
+
parts.push(current);
|
|
15
|
+
current = '';
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
current += ch;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
parts.push(current);
|
|
22
|
+
return parts.filter(Boolean);
|
|
23
|
+
}
|
|
5
24
|
export const DECK_MAP_AI_INSTRUCTIONS = `
|
|
6
25
|
Deck map tools:
|
|
7
26
|
- create_deck_map_config validates and returns a reusable native Deck JSON map config without requiring a dashboard artifact.
|
|
8
27
|
- create_dashboard_map creates or updates an interactive map panel inside a dashboard from a native Deck JSON map config.
|
|
9
28
|
- Use map tools when the user asks for a map, geospatial/spatial visualization, locations, longitude/latitude data, or geometry columns.
|
|
10
|
-
- Author maps with config.spec.layers using Deck JSON layer classes in @@type, such as GeoArrowScatterplotLayer, GeoArrowHeatmapLayer, GeoArrowPolygonLayer, GeoArrowPathLayer, or
|
|
29
|
+
- Author maps with config.spec.layers using Deck JSON layer classes in @@type, such as GeoArrowScatterplotLayer, GeoArrowHeatmapLayer, GeoArrowPolygonLayer, GeoArrowPathLayer, GeoArrowTripsLayer, GeoArrowArcLayer, or GeoArrowH3HexagonLayer.
|
|
30
|
+
- LAYER SELECTION: Choose the layer type based on the geometry type in the data.
|
|
31
|
+
IMPORTANT: Only create a layer if the table contains data suitable for that layer type, or if you can transform the data into the required format with a sqlQuery. Do NOT create a layer if the data is clearly incompatible (e.g. do not create a path layer from point-only data without aggregation, do not create a polygon layer from point coordinates, do not create an arc layer without origin-destination pairs).
|
|
32
|
+
- Point data (lon/lat coordinates, point geometry): GeoArrowScatterplotLayer (Point layer), GeoArrowHeatmapLayer, GeoArrowColumnLayer. Requires rows with individual point positions — either separate longitude/latitude numeric columns, or a point geometry column. Each row represents one point on the map.
|
|
33
|
+
- Polygon data (building footprints, boundaries, areas, parcels, zones): GeoArrowPolygonLayer or GeoArrowSolidPolygonLayer. Requires a geometry column containing polygon or multipolygon WKB/GeoArrow data. Typically loaded from GeoJSON/Shapefile/GeoParquet or produced by spatial queries. Do NOT use for point data.
|
|
34
|
+
- Line data (roads, routes, paths, rivers): GeoArrowPathLayer. CRITICAL: GeoArrowPathLayer requires LineString geometry, NOT individual point rows. If the table has one row per waypoint (indicated by columns like path_id/route_id + order/sequence + lat/lon), you MUST aggregate them with a sqlQuery: "SELECT path_id, label, ST_AsWKB(ST_MakeLine(LIST(ST_Point(lon, lat) ORDER BY waypoint_order))) AS geom FROM tableName GROUP BY path_id, label". Set geometryColumn to "geom" and geometryEncodingHint to "wkb". If the table already has a geometry/geom column with linestring data, use it directly with tableName. NEVER pass raw waypoint rows to GeoArrowPathLayer — it will fail.
|
|
35
|
+
- Animated trip data (routes with timestamps): GeoArrowTripsLayer. Same geometry requirements as GeoArrowPathLayer (LineString), plus a timestamps column. The sqlQuery MUST aggregate both the geometry and timestamps: "SELECT path_id, label, ST_AsWKB(ST_MakeLine(LIST(ST_Point(lon, lat) ORDER BY waypoint_order))) AS geom, LIST(timestamp ORDER BY waypoint_order) AS timestamps FROM tableName GROUP BY path_id, label". Set geometryColumn to "geom", geometryEncodingHint to "wkb", and _sqlroomsBinding.timestampColumn to "timestamps". The timestamps column must be a list of numbers (seconds) matching the order of waypoints in the linestring. Also set currentTime on the layer to control animation position. Do NOT use unless the data has or can produce both paths and ordered timestamps.
|
|
36
|
+
- CRITICAL geometryColumn rule: The geometryColumn field (in datasets[id].geometryColumn, _sqlroomsBinding.geometryColumn, and fitToData.geometryColumn) MUST match the exact column alias that produces the WKB geometry in the sqlQuery output — typically the "AS geom" alias in ST_AsWKB(...) AS geom. It must NEVER be set to a GROUP BY key, an ID column, or any other non-geometry column. For example, if the sqlQuery is "SELECT path_id, ST_AsWKB(ST_MakeLine(...)) AS geom ... GROUP BY path_id", geometryColumn must be "geom" (the geometry output), NOT "path_id" (the grouping key). Setting geometryColumn to a non-geometry column will cause the layer to fail silently.
|
|
37
|
+
- Arc data (origin-destination pairs): GeoArrowArcLayer. Requires two sets of coordinates per row (source and target). The table must have source_lon/source_lat AND target_lon/target_lat columns (or equivalent). The dataset source MUST use a sqlQuery that creates WKB geometry columns from lat/lon, for example: "SELECT *, ST_AsWKB(ST_Point(source_lon, source_lat)) AS source_geom, ST_AsWKB(ST_Point(target_lon, target_lat)) AS target_geom FROM tableName". Set sourceGeometryColumn to "source_geom" and targetGeometryColumn to "target_geom". Set geometryEncodingHint to "wkb". To render straight lines instead of arcs, set "getHeight": 0 on the layer. Do NOT use for data with only one set of coordinates per row. When the source data has H3 indices instead of lat/lon, convert H3 to coordinates using h3_cell_to_lng(h3_index) and h3_cell_to_lat(h3_index) (the H3 extension is pre-loaded at startup), for example: "SELECT *, ST_AsWKB(ST_Point(h3_cell_to_lng(source_h3), h3_cell_to_lat(source_h3))) AS source_geom, ST_AsWKB(ST_Point(h3_cell_to_lng(target_h3), h3_cell_to_lat(target_h3))) AS target_geom FROM tableName". Do NOT use h3_latlng() — it does not exist.
|
|
38
|
+
- H3 hexagon data (h3 index column): GeoArrowH3HexagonLayer. Requires a column containing H3 string indices. Bind to dataset with _sqlroomsBinding.dataset. Set "getHexagon": "@@=h3_column_name" where h3_column_name is the column containing H3 string indices. Always include "fitToData": {"dataset": "datasetId"} so the map can zoom to the data extent. Do NOT use unless the table has an H3 index column. DuckDB H3 extension functions: h3_cell_to_lat(index), h3_cell_to_lng(index), h3_cell_to_latlng(index). Do NOT use h3_latlng(), h3_to_lat(), or other non-existent function names.
|
|
39
|
+
- CRITICAL: The sqlQuery field must contain ONLY a single SELECT statement. NEVER put INSTALL, LOAD, CREATE, or other DDL/meta-commands in sqlQuery — they will fail because sqlQuery is wrapped in a subquery at runtime. Extensions like h3 and spatial are pre-loaded at startup.
|
|
40
|
+
- GeoJSON files typically contain polygon or multipolygon features (boundaries, buildings, parcels); use GeoArrowPolygonLayer for these. If a GeoJSON file contains point features, use GeoArrowScatterplotLayer (Point layer) instead.
|
|
41
|
+
- RADIUS AND WIDTH: For GeoArrowScatterplotLayer (Point layer) use getRadius with radiusUnits: "pixels" (typically 2–6 pixels); large radii cause overdraw and rendering lag, especially with many points. For GeoArrowColumnLayer use the "radius" property (NOT getRadius) — it sets column radius in meters; typical values are 20–200 for city-scale data or smaller for dense datasets. Do NOT use getRadius or radiusUnits on column layers. For GeoArrowArcLayer, GeoArrowPathLayer, and GeoArrowTripsLayer use getWidth with widthUnits: "pixels" (typically 1–3 pixels).
|
|
42
|
+
- HEATMAP: For GeoArrowHeatmapLayer, do NOT set colorRange manually. The UI provides a scheme selector that generates the correct color array. If you set colorRange to hand-picked RGB arrays, it will be out of sync with the scheme selector shown in the UI. Just omit colorRange entirely and let the default apply — users can change the scheme through the map settings panel.
|
|
43
|
+
- ARC vs LINE: GeoArrowArcLayer renders curved 3D arcs by default. If the user asks for "lines" or "straight connections" between origin-destination pairs (not arcs), set "getHeight": 0 on the layer to render flat straight lines. Use arcs for flight routes or connections where the curve adds clarity; use flat lines for direct relationships, edges, or when the user explicitly requests lines.
|
|
44
|
+
- ELEVATION: For extruded layers, getElevation with @@function "scale" passes the raw field value as meters. Use elevationScale on the layer to multiply values to a useful visual height. For example, if the field is "floors" (1-10), set elevationScale to 3 (meters per floor). Do NOT use negative values for elevation. Avoid using diverging scales for elevation. IMPORTANT: Keep elevation moderate — if extruded polygons or H3 hexagons are too tall, users can't see the tops when zoomed in. Prefer elevationScale values that produce heights of a few hundred meters at most for city-scale data. A good rule of thumb: the maximum elevation (field max × elevationScale) should not exceed ~500m for typical zoom levels.
|
|
11
45
|
- Bind layers to datasets with _sqlroomsBinding.dataset and put tableName or sqlQuery sources in config.datasets.
|
|
12
|
-
-
|
|
46
|
+
- Each dataset in config.datasets should have a source.tableName or source.sqlQuery that describes the original table the map was authored against. At runtime, the dashboard's selected table (from the table selector) overrides the source table — when the user switches the active table, all map panels automatically update. If the new table lacks required columns, an incompatibility error is shown.
|
|
47
|
+
- IMPORTANT: Always pass tableName in the create_dashboard_map tool params (the top-level tableName field). Use the table currently selected in the dashboard (dashboard.selectedTable from list_dashboard_panels). At runtime, the dashboard's selected table always overrides the authored table — this param only seeds the initial selection when no table is selected yet.
|
|
48
|
+
- IMPORTANT: If you are creating a map layer for a table that is NOT the currently selected dashboard table, you MUST switch the dashboard's selected table to that dataset BEFORE or WHEN calling create_dashboard_map (pass the correct tableName). The map panel resolves data from the dashboard's active table — if you don't switch it, the layer will query the wrong table and fail.
|
|
49
|
+
- IMPORTANT: When referencing tables in tableName or sqlQuery, use ONLY the bare table name (e.g. "my_table") or schema-qualified name (e.g. "main.my_table"). NEVER include the database/catalog prefix (e.g. do NOT use "sqlrooms-cli.main.my_table") — the catalog does not exist in the query execution context.
|
|
50
|
+
- IMPORTANT: For point data with longitude/latitude columns, the dataset source MUST use a sqlQuery that creates a geometry column, for example: "SELECT *, ST_AsWKB(ST_Point(\\"Longitude\\", \\"Latitude\\")) AS \\"__sqlrooms_geom\\" FROM tableName WHERE \\"Longitude\\" IS NOT NULL AND \\"Latitude\\" IS NOT NULL". Set geometryColumn to the same name used in the AS clause (e.g. "__sqlrooms_geom") and geometryEncodingHint to "wkb".
|
|
51
|
+
- IMPORTANT: When providing fitToData, it MUST be a flat object (NOT nested by dataset ID). Include either longitudeColumn+latitudeColumn (for point data with separate coordinate columns) OR geometryColumn (for data with a WKB geometry column like GeoJSON). For H3 hexagon layers, just specify the dataset: "fitToData": {"dataset": "datasetId"} — the H3 column is auto-detected from the layer binding. For GeoJSON/spatial files with a "geom" column, use: "fitToData": {"dataset": "datasetId", "geometryColumn": "geom"}. For point data use: "fitToData": {"dataset": "datasetId", "longitudeColumn": "lon", "latitudeColumn": "lat"}. NEVER nest fitToData as {"datasetId": {...}} — always use a flat object with "dataset" as a string field.
|
|
52
|
+
- IMPORTANT: For GeoJSON or spatial files that already have a native geometry column (e.g. "geometry", "geom"), use the table directly with source.tableName (no sqlQuery needed), set the dataset's geometryColumn to "geom", set geometryEncodingHint to "wkb", and use fitToData with geometryColumn: {"dataset": "datasetId", "geometryColumn": "geom"}.
|
|
53
|
+
- IMPORTANT: When a GeoJSON file (.geojson) is loaded as a table, DuckDB uses ST_Read to produce a table with a WKB "geom" column and all feature properties as columns. Use source.tableName, set geometryColumn to "geom" and geometryEncodingHint to "wkb". Use "fitToData": {"dataset": "datasetId", "geometryColumn": "geom"} to zoom to the data extent.
|
|
54
|
+
- For data-driven color, use native Deck JSON accessors with {"@@function":"colorScale", "field":"...", "type":"sequential"|"diverging"|"quantize"|"quantile"|"categorical", "scheme":"...", "domain":"auto"} on color properties such as getFillColor, getLineColor, getColor, getSourceColor, or getTargetColor. Valid schemes: for "categorical" type use one of Accent, Dark2, Paired, Pastel1, Pastel2, Set1, Set2, Set3, Tableau10, Observable10, Category10. For "sequential" use Viridis, Inferno, Magma, Plasma, Turbo, Blues, Greens, Oranges, Reds, Purples, etc. For "diverging" use RdBu, Spectral, RdYlGn, BrBG, PiYG, etc. IMPORTANT: The colorScale "field" must reference a column that exists in the FINAL query output (after any GROUP BY aggregation). Do not reference columns that are lost during aggregation.
|
|
13
55
|
- Map panels default to a 100000-row runtime data limit; use config.dataPolicy.maxRows only when the map genuinely needs a panel-specific limit.
|
|
56
|
+
- Create maps with a SINGLE layer unless the user explicitly asks for multiple layers. If you think multiple layers would better serve the user's request, ask the user for confirmation before adding them.
|
|
57
|
+
- IMPORTANT: Browsers limit the number of active WebGL contexts (typically 8–16 per page). Each map panel uses one context. Do NOT create more than 4–5 map panels in a single dashboard — exceeding the limit causes older maps to lose their rendering context and show errors. If the user asks for many datasets, prefer combining compatible layers into fewer maps rather than creating one map per dataset.
|
|
14
58
|
- After calling create_dashboard_map, call list_dashboard_panels before your final response and check the map panel issue. If it has a render-error, repair the map config in place instead of saying the map is complete.
|
|
59
|
+
- BASEMAPS: Do NOT use Mapbox basemap styles (mapbox://styles/...) — they require a Mapbox access token which is not available. The map uses CARTO basemaps by default (positron for light, dark-matter for dark theme) which work without any token. If you need to set a custom mapStyle, use free tile providers like CARTO (https://basemaps.cartocdn.com/gl/...) or other token-free MapLibre-compatible style URLs.
|
|
15
60
|
`;
|
|
16
61
|
function createDeckMapDashboardExtraTools(extraTools) {
|
|
17
|
-
return (
|
|
18
|
-
...createDeckMapDashboardAiTools(
|
|
19
|
-
...(extraTools?.(
|
|
62
|
+
return (params) => ({
|
|
63
|
+
...createDeckMapDashboardAiTools(params),
|
|
64
|
+
...(extraTools?.(params) ?? {}),
|
|
20
65
|
});
|
|
21
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns AI instructions for dashboards with Deck.gl map support.
|
|
69
|
+
* Provides guidance on when and how to use map visualizations.
|
|
70
|
+
*
|
|
71
|
+
* @returns Instructions string for AI agents
|
|
72
|
+
*/
|
|
22
73
|
export function getDashboardWithDeckMapAiInstructions() {
|
|
23
|
-
return `${
|
|
74
|
+
return `${DECK_MAP_AI_INSTRUCTIONS.trim()}`;
|
|
24
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Creates dashboard AI tools with built-in Deck.gl map support.
|
|
78
|
+
* Extends standard dashboard tools with map visualization capabilities.
|
|
79
|
+
*
|
|
80
|
+
* @param options - Dashboard AI tools configuration options
|
|
81
|
+
* @returns Record mapping tool names to tool instances, including map tools
|
|
82
|
+
*/
|
|
25
83
|
export function createDashboardWithDeckMapAiTools(options) {
|
|
26
84
|
return createMosaicDashboardAiTools({
|
|
27
85
|
...options,
|
|
28
86
|
extraTools: createDeckMapDashboardExtraTools(options.extraTools),
|
|
29
87
|
});
|
|
30
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Creates a dashboard agent tool with built-in Deck.gl map support.
|
|
91
|
+
* Extends the standard dashboard agent with map creation capabilities.
|
|
92
|
+
*
|
|
93
|
+
* @template TState - Store state type extending MosaicDashboardStoreState
|
|
94
|
+
* @param options - Dashboard agent configuration options
|
|
95
|
+
* @returns Dashboard agent tool with map support
|
|
96
|
+
*/
|
|
31
97
|
export function createDashboardAgentToolWithDeckMaps(options) {
|
|
32
98
|
return createDashboardAgentTool({
|
|
33
99
|
...options,
|
|
100
|
+
additionalInstructions: [
|
|
101
|
+
options.additionalInstructions,
|
|
102
|
+
DECK_MAP_AI_INSTRUCTIONS.trim(),
|
|
103
|
+
]
|
|
104
|
+
.filter(Boolean)
|
|
105
|
+
.join('\n\n'),
|
|
34
106
|
extraTools: createDeckMapDashboardExtraTools(options.extraTools),
|
|
35
107
|
});
|
|
36
108
|
}
|
|
@@ -69,7 +141,7 @@ const DeckMapDataPolicyConfig = z.looseObject({
|
|
|
69
141
|
reason: z.string().optional(),
|
|
70
142
|
});
|
|
71
143
|
export const DeckMapDashboardConfigParameter = z.looseObject({
|
|
72
|
-
spec: DeckMapSpec.describe('Deck JSON map spec as an object. Use spec.layers[].@@type for layer classes such as GeoArrowScatterplotLayer, GeoArrowHeatmapLayer, GeoArrowPolygonLayer, GeoArrowPathLayer, or GeoArrowArcLayer.'),
|
|
144
|
+
spec: DeckMapSpec.describe('Deck JSON map spec as an object. Use spec.layers[].@@type for layer classes such as GeoArrowScatterplotLayer (Point layer), GeoArrowHeatmapLayer, GeoArrowPolygonLayer, GeoArrowPathLayer, or GeoArrowArcLayer.'),
|
|
73
145
|
datasets: z
|
|
74
146
|
.record(z.string(), DeckMapDatasetConfig)
|
|
75
147
|
.describe('Datasets keyed by dataset id. Layers bind to these ids through _sqlroomsBinding.dataset. Each dataset source may use tableName or sqlQuery.'),
|
|
@@ -89,19 +161,10 @@ export const DeckMapConfigToolParameters = z.object({
|
|
|
89
161
|
.describe('Brief rationale for creating the map config.'),
|
|
90
162
|
});
|
|
91
163
|
export const DeckMapDashboardToolParameters = DeckMapConfigToolParameters.extend({
|
|
92
|
-
artifactId: z
|
|
93
|
-
.string()
|
|
94
|
-
.optional()
|
|
95
|
-
.describe('Optional dashboard artifact ID. Defaults to current dashboard.'),
|
|
96
164
|
tableName: z
|
|
97
165
|
.string()
|
|
98
166
|
.optional()
|
|
99
167
|
.describe('Optional table name used only to select/resolve the target dashboard table. Data sources still come from config.datasets.'),
|
|
100
|
-
createArtifactIfMissing: z
|
|
101
|
-
.boolean()
|
|
102
|
-
.optional()
|
|
103
|
-
.default(true)
|
|
104
|
-
.describe('If true, create dashboard artifact if missing.'),
|
|
105
168
|
panelId: z
|
|
106
169
|
.string()
|
|
107
170
|
.optional()
|
|
@@ -110,20 +173,102 @@ export const DeckMapDashboardToolParameters = DeckMapConfigToolParameters.extend
|
|
|
110
173
|
.string()
|
|
111
174
|
.describe('Brief rationale for creating the map panel.'),
|
|
112
175
|
});
|
|
176
|
+
const DEFAULT_AI_GEOMETRY_COLUMN = '__sqlrooms_geom';
|
|
177
|
+
/**
|
|
178
|
+
* Normalizes an AI-generated map config to ensure dataset sources produce
|
|
179
|
+
* the expected geometry column when fitToData specifies coordinate columns
|
|
180
|
+
* but the dataset only uses a tableName without a sqlQuery.
|
|
181
|
+
*/
|
|
182
|
+
function normalizeAiMapConfig(config) {
|
|
183
|
+
const datasets = config.datasets;
|
|
184
|
+
let fitToData = config.fitToData;
|
|
185
|
+
// Fix common AI mistake: fitToData wrapped as { datasetId: { dataset, ... } }
|
|
186
|
+
// instead of the expected flat { dataset, longitudeColumn, ... }.
|
|
187
|
+
if (fitToData && !fitToData.dataset && typeof fitToData === 'object') {
|
|
188
|
+
const keys = Object.keys(fitToData);
|
|
189
|
+
if (keys.length === 1) {
|
|
190
|
+
const nested = fitToData[keys[0]];
|
|
191
|
+
if (nested && typeof nested === 'object' && nested.dataset) {
|
|
192
|
+
fitToData = nested;
|
|
193
|
+
config = { ...config, fitToData: fitToData };
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (!datasets || typeof datasets !== 'object' || !fitToData) {
|
|
198
|
+
return config;
|
|
199
|
+
}
|
|
200
|
+
const lonCol = fitToData.longitudeColumn;
|
|
201
|
+
const latCol = fitToData.latitudeColumn;
|
|
202
|
+
if (!lonCol || !latCol) {
|
|
203
|
+
return config;
|
|
204
|
+
}
|
|
205
|
+
const targetDatasetId = fitToData.dataset;
|
|
206
|
+
if (!targetDatasetId) {
|
|
207
|
+
return config;
|
|
208
|
+
}
|
|
209
|
+
const targetDataset = datasets[targetDatasetId];
|
|
210
|
+
if (!targetDataset) {
|
|
211
|
+
return config;
|
|
212
|
+
}
|
|
213
|
+
const source = targetDataset.source;
|
|
214
|
+
// Always normalize when using tableName without sqlQuery and fitToData
|
|
215
|
+
// provides coordinate columns — the geometry must be computed from them.
|
|
216
|
+
if (!source?.tableName || source.sqlQuery) {
|
|
217
|
+
return config;
|
|
218
|
+
}
|
|
219
|
+
const geometryColumn = targetDataset.geometryColumn ||
|
|
220
|
+
DEFAULT_AI_GEOMETRY_COLUMN;
|
|
221
|
+
const quotedLon = quoteDeckMapSqlIdentifier(lonCol);
|
|
222
|
+
const quotedLat = quoteDeckMapSqlIdentifier(latCol);
|
|
223
|
+
const quotedGeom = quoteDeckMapSqlIdentifier(geometryColumn);
|
|
224
|
+
const tableParts = splitIdentifierPathOutsideQuotes(source.tableName)
|
|
225
|
+
.map((p) => p.startsWith('"') && p.endsWith('"') ? p : quoteDeckMapSqlIdentifier(p))
|
|
226
|
+
.join('.');
|
|
227
|
+
const sqlQuery = [
|
|
228
|
+
`SELECT *, ST_AsWKB(ST_Point(${quotedLon}, ${quotedLat})) AS ${quotedGeom}`,
|
|
229
|
+
`FROM ${tableParts}`,
|
|
230
|
+
`WHERE ${quotedLon} IS NOT NULL AND ${quotedLat} IS NOT NULL`,
|
|
231
|
+
].join(' ');
|
|
232
|
+
return {
|
|
233
|
+
...config,
|
|
234
|
+
datasets: {
|
|
235
|
+
...datasets,
|
|
236
|
+
[targetDatasetId]: {
|
|
237
|
+
...targetDataset,
|
|
238
|
+
source: { sqlQuery },
|
|
239
|
+
geometryColumn,
|
|
240
|
+
geometryEncodingHint: 'wkb',
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
}
|
|
113
245
|
function cloneConfig(config) {
|
|
114
|
-
|
|
246
|
+
const normalized = normalizeAiMapConfig(config);
|
|
247
|
+
return JSON.parse(JSON.stringify(normalized));
|
|
115
248
|
}
|
|
116
|
-
|
|
249
|
+
/**
|
|
250
|
+
* Creates a dashboard-compatible Deck map panel from the native map config
|
|
251
|
+
* used by AI tools and embeddable map surfaces.
|
|
252
|
+
*/
|
|
253
|
+
export function createDeckMapPanelFromNativeConfig(params) {
|
|
117
254
|
return createDeckMapDashboardPanelConfig({
|
|
118
255
|
title: params.title || 'Map',
|
|
119
256
|
...cloneConfig(params.config),
|
|
120
257
|
});
|
|
121
258
|
}
|
|
259
|
+
function getFirstDatasetSourceTableName(config) {
|
|
260
|
+
if (!config.datasets || typeof config.datasets !== 'object') {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
return Object.values(config.datasets)
|
|
264
|
+
.map((dataset) => dataset.source)
|
|
265
|
+
.find((source) => source?.tableName)?.tableName;
|
|
266
|
+
}
|
|
122
267
|
export function createDeckMapConfigTool() {
|
|
123
268
|
return tool({
|
|
124
269
|
description: `Deck map config: validates and returns a reusable native Deck JSON map configuration without requiring a dashboard artifact.
|
|
125
270
|
|
|
126
|
-
Use when: a chat, agent, or artifact outside a dashboard needs a geospatial map config. Author the map using native Deck JSON: put layer classes in spec.layers[].@@type, bind layers to datasets through _sqlroomsBinding.dataset, and put tableName or sqlQuery sources in config.datasets. For data-driven colors, use color accessors such as getFillColor, getLineColor, getColor, getSourceColor, or getTargetColor with {"@@function":"colorScale", "field":"...", "type":"
|
|
271
|
+
Use when: a chat, agent, or artifact outside a dashboard needs a geospatial map config. Author the map using native Deck JSON: put layer classes in spec.layers[].@@type, bind layers to datasets through _sqlroomsBinding.dataset, and put tableName or sqlQuery sources in config.datasets. For data-driven colors, use color accessors such as getFillColor, getLineColor, getColor, getSourceColor, or getTargetColor with {"@@function":"colorScale", "field":"...", "type":"...", "scheme":"...", "domain":"auto"}. For categorical fields use scheme from: Tableau10, Set2, Category10, etc. For numeric fields use sequential schemes like Viridis.`,
|
|
127
272
|
inputSchema: DeckMapConfigToolParameters,
|
|
128
273
|
execute: async (params) => {
|
|
129
274
|
try {
|
|
@@ -152,34 +297,41 @@ Use when: a chat, agent, or artifact outside a dashboard needs a geospatial map
|
|
|
152
297
|
},
|
|
153
298
|
});
|
|
154
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Creates AI tools for Deck.gl map configuration.
|
|
302
|
+
* Returns tools for creating and configuring Deck.gl map panels.
|
|
303
|
+
*
|
|
304
|
+
* @returns Record mapping tool names to map configuration tools
|
|
305
|
+
*/
|
|
155
306
|
export function createDeckMapAiTools() {
|
|
156
307
|
return {
|
|
157
308
|
create_deck_map_config: createDeckMapConfigTool(),
|
|
158
309
|
};
|
|
159
310
|
}
|
|
160
|
-
|
|
311
|
+
/**
|
|
312
|
+
* Creates a tool for adding Deck.gl map panels to dashboards.
|
|
313
|
+
* Supports creating new map panels or updating existing ones with native Deck JSON configs.
|
|
314
|
+
*
|
|
315
|
+
* @param params - Parameters containing dashboard and database adapters
|
|
316
|
+
* @returns Tool instance for creating/updating Deck.gl map panels
|
|
317
|
+
*/
|
|
318
|
+
export function createDeckMapDashboardTool({ dashboardAdapter, databaseAdapter, }) {
|
|
161
319
|
return tool({
|
|
162
320
|
description: `Deck map panel: creates or updates an interactive geospatial map panel in a Mosaic dashboard from a native Deck JSON config.
|
|
163
321
|
|
|
164
|
-
Use when: the user asks for a map in a dashboard. Author the map using native Deck JSON: choose layer classes with spec.layers[].@@type, bind layers to datasets through _sqlroomsBinding.dataset, and put tableName or sqlQuery sources in config.datasets. For data-driven colors, use color accessors such as getFillColor, getLineColor, getColor, getSourceColor, or getTargetColor with {"@@function":"colorScale", "field":"...", "type":"
|
|
322
|
+
Use when: the user asks for a map in a dashboard. Author the map using native Deck JSON: choose layer classes with spec.layers[].@@type, bind layers to datasets through _sqlroomsBinding.dataset, and put tableName or sqlQuery sources in config.datasets. For data-driven colors, use color accessors such as getFillColor, getLineColor, getColor, getSourceColor, or getTargetColor with {"@@function":"colorScale", "field":"...", "type":"...", "scheme":"...", "domain":"auto"}. For categorical fields use scheme from: Tableau10, Set2, Category10, etc. For numeric fields use sequential schemes like Viridis.`,
|
|
165
323
|
inputSchema: DeckMapDashboardToolParameters,
|
|
166
|
-
execute: async (params
|
|
324
|
+
execute: async (params) => {
|
|
167
325
|
try {
|
|
168
|
-
const
|
|
169
|
-
if (
|
|
170
|
-
|
|
326
|
+
const tableName = params.tableName ?? getFirstDatasetSourceTableName(params.config);
|
|
327
|
+
if (tableName) {
|
|
328
|
+
ensureTable(databaseAdapter, tableName);
|
|
329
|
+
await dashboardAdapter.setSelectedTable(tableName);
|
|
171
330
|
}
|
|
172
331
|
const panel = createDeckMapPanelFromNativeConfig(params);
|
|
173
332
|
if (params.panelId) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (!existingPanel) {
|
|
177
|
-
throw new Error(`Panel "${params.panelId}" not found in dashboard "${artifactId}". Cannot update.`);
|
|
178
|
-
}
|
|
179
|
-
if (existingPanel.type !== DECK_MAP_DASHBOARD_PANEL_TYPE) {
|
|
180
|
-
throw new Error(`Panel "${params.panelId}" is not a map panel. Cannot update it with ${MAP_TOOL_KEY}.`);
|
|
181
|
-
}
|
|
182
|
-
deps.updatePanel(artifactId, params.panelId, {
|
|
333
|
+
ensurePanel(dashboardAdapter, params.panelId, DECK_MAP_DASHBOARD_PANEL_TYPE);
|
|
334
|
+
await dashboardAdapter.updatePanel(params.panelId, {
|
|
183
335
|
title: panel.title,
|
|
184
336
|
config: panel.config,
|
|
185
337
|
});
|
|
@@ -189,7 +341,6 @@ Use when: the user asks for a map in a dashboard. Author the map using native De
|
|
|
189
341
|
details: `Updated map panel "${panel.title}".`,
|
|
190
342
|
data: {
|
|
191
343
|
panelId: params.panelId,
|
|
192
|
-
artifactId,
|
|
193
344
|
title: panel.title,
|
|
194
345
|
type: DECK_MAP_DASHBOARD_PANEL_TYPE,
|
|
195
346
|
config: panel.config,
|
|
@@ -197,15 +348,13 @@ Use when: the user asks for a map in a dashboard. Author the map using native De
|
|
|
197
348
|
},
|
|
198
349
|
};
|
|
199
350
|
}
|
|
200
|
-
const panelId =
|
|
201
|
-
deps.setCurrentArtifact(artifactId);
|
|
351
|
+
const panelId = await dashboardAdapter.addPanel(panel);
|
|
202
352
|
return {
|
|
203
353
|
llmResult: {
|
|
204
354
|
success: true,
|
|
205
355
|
details: `Created map panel "${panel.title}".`,
|
|
206
356
|
data: {
|
|
207
357
|
panelId,
|
|
208
|
-
artifactId,
|
|
209
358
|
title: panel.title,
|
|
210
359
|
type: DECK_MAP_DASHBOARD_PANEL_TYPE,
|
|
211
360
|
config: panel.config,
|
|
@@ -224,9 +373,9 @@ Use when: the user asks for a map in a dashboard. Author the map using native De
|
|
|
224
373
|
},
|
|
225
374
|
});
|
|
226
375
|
}
|
|
227
|
-
export function createDeckMapDashboardAiTools(
|
|
376
|
+
export function createDeckMapDashboardAiTools(params) {
|
|
228
377
|
return {
|
|
229
|
-
[MAP_TOOL_KEY]: createDeckMapDashboardTool(
|
|
378
|
+
[MAP_TOOL_KEY]: createDeckMapDashboardTool(params),
|
|
230
379
|
};
|
|
231
380
|
}
|
|
232
381
|
//# sourceMappingURL=ai.js.map
|