@kepler.gl/mcp 0.0.0-stage → 3.3.0-alpha.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/cjs/commands/add-column-command.js +192 -0
  2. package/dist/cjs/commands/basemap-command.js +80 -0
  3. package/dist/cjs/commands/boundary-command.js +81 -0
  4. package/dist/cjs/commands/command-wrappers.js +122 -0
  5. package/dist/cjs/commands/dataset-context-command.js +87 -0
  6. package/dist/cjs/commands/index.js +230 -0
  7. package/dist/cjs/commands/layer-creation-command.js +534 -0
  8. package/dist/cjs/commands/layer-style-command.js +136 -0
  9. package/dist/cjs/commands/load-data-command.js +270 -0
  10. package/dist/cjs/commands/save-data-command.js +118 -0
  11. package/dist/cjs/commands/split-view-command.js +261 -0
  12. package/dist/cjs/commands/table-command.js +199 -0
  13. package/dist/cjs/commands/time-filter-command.js +289 -0
  14. package/dist/cjs/commands/toggle-time-filter-command.js +155 -0
  15. package/dist/cjs/commands/types.js +6 -0
  16. package/dist/cjs/commands/utils.js +536 -0
  17. package/dist/cjs/commands/view-mode-command.js +94 -0
  18. package/dist/cjs/index.js +39 -0
  19. package/dist/cjs/map-contract.js +6 -0
  20. package/dist/cjs/server/bridge-server.js +435 -0
  21. package/dist/cjs/server/index.js +31 -0
  22. package/dist/cjs/server/stdio.js +201 -0
  23. package/dist/cjs/types.js +30 -0
  24. package/dist/commands/add-column-command.d.ts +4 -0
  25. package/dist/commands/basemap-command.d.ts +4 -0
  26. package/dist/commands/boundary-command.d.ts +4 -0
  27. package/dist/commands/command-wrappers.d.ts +52 -0
  28. package/dist/commands/dataset-context-command.d.ts +4 -0
  29. package/dist/commands/index.d.ts +31 -0
  30. package/dist/commands/layer-creation-command.d.ts +8 -0
  31. package/dist/commands/layer-style-command.d.ts +4 -0
  32. package/dist/commands/load-data-command.d.ts +4 -0
  33. package/dist/commands/save-data-command.d.ts +4 -0
  34. package/dist/commands/split-view-command.d.ts +4 -0
  35. package/dist/commands/table-command.d.ts +4 -0
  36. package/dist/commands/time-filter-command.d.ts +13 -0
  37. package/dist/commands/toggle-time-filter-command.d.ts +4 -0
  38. package/dist/commands/types.d.ts +132 -0
  39. package/dist/commands/utils.d.ts +138 -0
  40. package/dist/commands/view-mode-command.d.ts +4 -0
  41. package/dist/esm/commands/add-column-command.js +185 -0
  42. package/dist/esm/commands/basemap-command.js +72 -0
  43. package/dist/esm/commands/boundary-command.js +73 -0
  44. package/dist/esm/commands/command-wrappers.js +114 -0
  45. package/dist/esm/commands/dataset-context-command.js +79 -0
  46. package/dist/esm/commands/index.js +51 -0
  47. package/dist/esm/commands/layer-creation-command.js +527 -0
  48. package/dist/esm/commands/layer-style-command.js +130 -0
  49. package/dist/esm/commands/load-data-command.js +264 -0
  50. package/dist/esm/commands/save-data-command.js +112 -0
  51. package/dist/esm/commands/split-view-command.js +255 -0
  52. package/dist/esm/commands/table-command.js +194 -0
  53. package/dist/esm/commands/time-filter-command.js +280 -0
  54. package/dist/esm/commands/toggle-time-filter-command.js +147 -0
  55. package/dist/esm/commands/types.js +3 -0
  56. package/dist/esm/commands/utils.js +521 -0
  57. package/dist/esm/commands/view-mode-command.js +86 -0
  58. package/dist/esm/index.js +20 -0
  59. package/dist/esm/map-contract.js +3 -0
  60. package/dist/esm/server/bridge-server.js +428 -0
  61. package/dist/esm/server/index.js +13 -0
  62. package/dist/esm/server/stdio.js +198 -0
  63. package/dist/esm/types.js +24 -0
  64. package/dist/index.d.ts +15 -0
  65. package/dist/map-contract.d.ts +31 -0
  66. package/dist/server/bridge-server.d.ts +53 -0
  67. package/dist/server/index.d.ts +9 -0
  68. package/dist/server/stdio.d.ts +2 -0
  69. package/dist/types.d.ts +24 -0
  70. package/package.json +84 -4
  71. package/skill/kepler/SKILL.md +438 -0
  72. package/skill/kepler/skill.yaml +4 -0
  73. package/README.md +0 -3
@@ -0,0 +1,438 @@
1
+ # Kepler map management
2
+
3
+ Create and configure kepler.gl map layers from datasets, animate them over
4
+ time, compare them side by side, change the basemap, update layer colors,
5
+ load data from a URL, add columns to existing datasets, and read the current
6
+ map boundary. These are direct map-mutation operations on the kepler.gl map
7
+ surface.
8
+
9
+ ## When to use
10
+
11
+ Use this skill when the user wants to create or reconfigure map layers, change
12
+ the appearance or configuration of the map itself, animate data over time, or
13
+ compare layers side by side. Examples:
14
+ - "Show the shops as points colored by visits"
15
+ - "Create a heatmap of the pickup locations"
16
+ - "Animate the trips over time"
17
+ - "Compare the 2019 and 2024 layers side by side"
18
+ - "Change the basemap to dark/satellite/positron"
19
+ - "Update the color of the layer to blue"
20
+ - "Load data from this URL"
21
+ - "Add a new variable / column to an existing dataset"
22
+ - "Change a column's type (e.g. make NOSOUTH a string)"
23
+ - "Rename a column on the existing dataset"
24
+ - "What's the current map boundary/extent?"
25
+
26
+ Do NOT use this skill for analysis beyond map mutation — spatial statistics,
27
+ spatial filtering, colocation, boundary fetching, or charts. Those belong to
28
+ your host's analysis skills (e.g. a spatial-analysis skill, a filter skill),
29
+ not this one.
30
+
31
+ ## Commands at a glance
32
+
33
+ | command | purpose |
34
+ | ------------------------ | -------------------------------------------------------------- |
35
+ | `map.add-layer` | Add a layer (point, flow, flowField, h3, arc, trip, hexagon, grid, cluster, heatmap, geojson, line, s2) to the map. |
36
+ | `map.add-time-filter` | Animate a NON-trip layer over a TIMESTAMP/DATE column. |
37
+ | `map.toggle-time-filter` | Show/hide the enlarged time controller at the bottom of the map. |
38
+ | `map.split-view` | Enable/disable dual-map comparison. |
39
+ | `map.update-layer-color` | Update an existing layer's color palette. |
40
+ | `map.set-basemap` | Change the basemap style. |
41
+ | `map.set-view-mode` | Switch between the flat 2D map, the tilted 3D map and the 3D globe. |
42
+ | `map.load-data` | Load data from a URL (no layer — call `map.add-layer`). |
43
+ | `map.save-data` | Save a DuckDB table as a map dataset (no layer — call `map.add-layer`). |
44
+ | `map.add-column` | Add a column to an EXISTING dataset in place (copy or expression). |
45
+ | `map.create-table` | Create a NEW dataset via SQL (original untouched — call `map.add-layer`). |
46
+ | `map.get-dataset-context` | List all loaded datasets with their fields and layer configurations. |
47
+ | `map.get-boundary` | Read the current map view's bounding box. |
48
+
49
+ Every command takes a `commandId` (one of the table above) and an `input`
50
+ object. Issue commands through your host's map-command dispatcher — the exact
51
+ envelope is described in your host's tool listing. In the kepler.gl demo
52
+ assistant the dispatcher is the `executeApi` tool with
53
+ `apiName: "executeCommand"` and `args: { commandId, input }`.
54
+
55
+ ## Picking a layer type
56
+
57
+ - Individual locations → `point` (`cluster` for zoom-out density, `heatmap`
58
+ for continuous intensity).
59
+ - Density without precomputed cells → `grid` or `hexagon` (auto-binned).
60
+ - Pre-aggregated H3 cells → `h3`.
61
+ - Origin→destination flows → `flow` (a dedicated flow layer with locations, clustering and weighted edges; requires two point lat/lng pairs — source + destination). Fall back to `arc` only when you want straight great-circle lines between points. For weighted flows optionally pass the magnitude column as `countColumn`.
62
+ - Vector fields — wind, currents, downhill terrain flow → `flowField`, animated streamlines over one vector per sample point. This is **not** `flow`: `flow` joins an origin pair to a destination pair, `flowField` draws many short lines through a field of vectors.
63
+
64
+ - Polylines / polygons → `line` / `geojson`. A decoded GEOMETRY `geom`
65
+ column can be rendered directly with `geojson` — do NOT convert it to
66
+ lat/lon columns or build an intermediate table. For geojson datasets use
67
+ geometryColumn `"_geojson"`.
68
+ - Time-animated movement → `trip`.
69
+
70
+ ## Color configuration
71
+
72
+ - `colorBy` is case-sensitive and must match the column name exactly.
73
+ - `simpleColor` is the string `"[r, g, b]"` (e.g. `"[255, 64, 0]"`), not an array.
74
+ It is a single static color for ALL features — NEVER use it for data-driven
75
+ coloring; use `colorBy` + `colorType` + `colorMap` for that.
76
+ - For continuous data use `colorType: "breaks"` with a `colorMap` whose last
77
+ entry has `value: null` (the color for the highest bucket):
78
+ `[{value: 0, color: "#fee5d9"}, {value: 50, color: "#fcae91"}, {value: 100, color: "#fb6a4a"}, {value: null, color: "#de2d26"}]`
79
+ - For categorical data use `colorType: "unique"`:
80
+ `[{value: "retail", color: "#1f77b4"}, {value: "restaurant", color: "#ff7f0e"}]`
81
+ HARD RULE: the `value`s MUST be the actual unique values in the column.
82
+ Classify the variable with your host's classification tool first and use the
83
+ returned unique values verbatim. NEVER guess category labels from the column
84
+ name — `map.add-layer` rejects values that do not exist in the data.
85
+ - For `heatmap`, only `colorRange` (from `colorMap`) takes effect.
86
+ - To compute the break values, classify the variable with your host's
87
+ classification tool first and pass the returned breaks as the `colorMap`
88
+ values.
89
+ - Generate ColorBrewer-style palettes automatically when the user does not
90
+ specify colors.
91
+
92
+ ### Suggested palettes
93
+
94
+ - Sequential green: `#ffffcc #c2e699 #78c679 #31a354 #006837 #004529`
95
+ - Sequential red: `#fee5d9 #fcae91 #fb6a4a #de2d26 #a50f15`
96
+ - Categorical (Tableau 10): `#1f77b4 #ff7f0e #2ca02c #d62728 #9467bd #8c564b`
97
+
98
+ ## Workflow
99
+
100
+ ### 1. Create a layer (`map.add-layer`)
101
+
102
+ Point layer colored by a continuous variable:
103
+
104
+ ```json
105
+ {
106
+ "datasetName": "shops",
107
+ "layerType": "point",
108
+ "layerName": "Shops by visits",
109
+ "colorBy": "visits",
110
+ "colorType": "breaks",
111
+ "colorMap": [
112
+ {"value": 3, "color": "#ffffcc"},
113
+ {"value": 10, "color": "#c2e699"},
114
+ {"value": 25, "color": "#78c679"},
115
+ {"value": 50, "color": "#31a354"},
116
+ {"value": 100, "color": "#006837"},
117
+ {"value": null, "color": "#004529"}
118
+ ]
119
+ }
120
+ ```
121
+
122
+ Point layer with a uniform color:
123
+
124
+ ```json
125
+ {
126
+ "datasetName": "pizza_stores",
127
+ "layerType": "point",
128
+ "layerName": "Pizza stores",
129
+ "simpleColor": "[255, 64, 0]"
130
+ }
131
+ ```
132
+
133
+ H3 layer:
134
+
135
+ ```json
136
+ {
137
+ "datasetName": "visits_h3_r9",
138
+ "layerType": "h3",
139
+ "layerName": "Visits density (h3 r9)",
140
+ "colorBy": "visit_count",
141
+ "colorType": "breaks",
142
+ "colorMap": [
143
+ {"value": 100, "color": "#fee5d9"},
144
+ {"value": 500, "color": "#fcae91"},
145
+ {"value": 2000, "color": "#fb6a4a"},
146
+ {"value": 10000, "color": "#de2d26"},
147
+ {"value": null, "color": "#a50f15"}
148
+ ]
149
+ }
150
+ ```
151
+
152
+ `map.add-layer` returns `dateTimeColumns` when the dataset has TIMESTAMP/DATE
153
+ fields — see "Time animation" below for the follow-up.
154
+
155
+ ### 2. Time animation (NON-trip layers)
156
+
157
+ When the user asks how something changed/evolved/trended over time and the
158
+ source dataset has a TIMESTAMP/DATE column, build a SINGLE layer and animate
159
+ it with `map.add-time-filter` — do NOT create a separate static layer per
160
+ time step. A stack of snapshot layers does not convey motion and clutters the
161
+ map; the animated layer is the deliverable.
162
+
163
+ - BEFORE creating any layer for a temporal request, DECLARE the expected
164
+ layer count: a change-over-time request ⇒ exactly **1** layer. If you find
165
+ yourself about to issue a 2nd `map.add-layer`, STOP — you have erred.
166
+ - `map.add-layer` returns `dateTimeColumns` when timestamp/date fields are
167
+ detected. Pass the first one to `map.add-time-filter`.
168
+ - If the column is an integer/string epoch, build a real TIMESTAMP column
169
+ first (Kepler.gl cannot handle negative epochs) — NEVER pass an
170
+ integer/string column directly.
171
+ - `map.add-time-filter` input: `{ datasetName, dateTimeColumn, interval? }`.
172
+ `interval` is auto-detected from the data when omitted.
173
+ - **Do not retry `map.add-time-filter` more than once.** If it fails, report
174
+ the error and continue — do not loop.
175
+ - LAYER ORDERING: create the time-filtered layer LAST so its animation is
176
+ not hidden behind later layers.
177
+
178
+ ```json
179
+ {
180
+ "datasetName": "earthquakes",
181
+ "dateTimeColumn": "time"
182
+ }
183
+ ```
184
+
185
+ ### Trip layers (`layerType: "trip"`)
186
+
187
+ - Trip layers have **built-in** time animation. Do NOT add a
188
+ `map.add-time-filter` for a trip layer — it is unnecessary and can break the
189
+ animation. After creating a trip layer, STOP.
190
+ - Strict columns: `id` (shared across a trip's waypoints), `latitude` /
191
+ `longitude` (DOUBLE), `timestamp` (epoch milliseconds). If your epoch is in
192
+ seconds, multiply by 1000.
193
+ - Densify sparse O-D data (interpolate lon/lat AND timestamp) or trips
194
+ teleport.
195
+
196
+ ### Flow field layer (`layerType: "flowField"`)
197
+
198
+ Animated streamlines over a vector field — wind, ocean currents, or downhill
199
+ terrain flow. Each row of the dataset is one sample point: a position plus a
200
+ direction. It is not the origin→destination `flow` layer — `flow` joins two
201
+ point pairs, `flowField` draws many short, continuously moving lines through a
202
+ field of vectors.
203
+
204
+ Pick the mode from the columns the dataset has; `map.add-layer` auto-detects
205
+ them in this order and names them in `flowField.*Column` when they differ:
206
+
207
+ | `flowField.mode` | Columns | Direction comes from |
208
+ |------------------|---------|----------------------|
209
+ | `UV` (default) | `u`, `v` (+ optional `altitude`) | east/north vector components |
210
+ | `SPEED_DIR` | `speed`, `direction` | speed plus compass direction (from) |
211
+ | `ELEVATION` | `altitude` | the downhill gradient of a height surface |
212
+
213
+ Position comes from lat/lng columns — auto-detected, or `latitudeColumn` /
214
+ `longitudeColumn` — or from a GeoJSON geometry column when the dataset has one.
215
+
216
+ Wind encoded as `u`/`v` (no extra parameters needed):
217
+
218
+ ```json
219
+ {
220
+ "datasetName": "wind_grid",
221
+ "layerType": "flowField",
222
+ "layerName": "Wind field",
223
+ "flowField": {"colorBySpeed": true}
224
+ }
225
+ ```
226
+
227
+ Wind encoded as speed + direction under different column names:
228
+
229
+ ```json
230
+ {
231
+ "datasetName": "wind_grid",
232
+ "layerType": "flowField",
233
+ "layerName": "Wind field",
234
+ "flowField": {
235
+ "mode": "SPEED_DIR",
236
+ "speedColumn": "wind_speed",
237
+ "directionColumn": "wind_dir"
238
+ }
239
+ }
240
+ ```
241
+
242
+ - `colorBySpeed: true` colors each streamline by its local speed (using the
243
+ layer's color range); without it the streamlines use `color`. `colorBy` /
244
+ `colorMap` do not apply to this layer.
245
+ - Do **not** add `map.add-time-filter` — the flow field animates continuously on
246
+ its own, like a trip layer.
247
+ - Streamline density (`linesPerScreen`), `strokeWidth`, `trailLength`,
248
+ `cycleSeconds`, `lineLifetime` and `smoothing` use tuned defaults; they are
249
+ adjusted in the layer panel, not through `map.add-layer`.
250
+ - A field layer over a very large grid is expensive: one row per sample point is
251
+ fine, but downsample rasters to roughly 10k–100k points before loading.
252
+
253
+ ### 3. Split map comparison (`map.split-view`)
254
+
255
+ - `action: "enable"` with `layerIdsForMap0` / `layerIdsForMap1`. Without the
256
+ layer-id arrays all layers show on both panels (no comparison). Use the SAME
257
+ `colorBy` / `colorType` for a fair comparison. `action: "disable"` returns
258
+ to one map.
259
+
260
+ ```json
261
+ {
262
+ "action": "enable",
263
+ "layerIdsForMap0": ["layer_2019"],
264
+ "layerIdsForMap1": ["layer_2024"]
265
+ }
266
+ ```
267
+
268
+ ### 4. Toggle the time controller
269
+
270
+ `map.toggle-time-filter` with `action: "show"` enlarges the time controller
271
+ at the bottom of the map; `action: "hide"` collapses it back to the side
272
+ panel. A time filter must already exist (created via `map.add-time-filter`).
273
+
274
+ ### 5. Basemap style
275
+
276
+ ```json
277
+ { "styleType": "dark" }
278
+ ```
279
+
280
+ Valid `styleType` values: `"no_map"`, `"dark-matter"`, `"positron"`,
281
+ `"voyager"`, `"satellite"`, `"dark"`, `"light"`, `"muted"`, `"muted_night"`.
282
+ If the user uses a descriptive name, map it to the closest valid `styleType`.
283
+ If the request is ambiguous, ask the user to clarify.
284
+
285
+ ### 6. Layer color
286
+
287
+ ```json
288
+ {
289
+ "layerId": "layer_xxx",
290
+ "numberOfColors": 5,
291
+ "customColors": ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd"]
292
+ }
293
+ ```
294
+
295
+ `customColors` is an array of hex color strings; `numberOfColors` must equal
296
+ its length. If the user describes colors qualitatively (e.g. "van gogh
297
+ starry night", "watercolor"), generate an appropriate palette from the
298
+ description. If the user refers to a layer by name rather than id, find the
299
+ matching `layerId` from the dataset context.
300
+
301
+ ### 7. Load data from URL
302
+
303
+ ```json
304
+ { "url": "https://..." }
305
+ ```
306
+
307
+ This fetches the data, parses it, and adds it to the map as a dataset. It
308
+ does NOT create a layer — call `map.add-layer` afterward to visualize the
309
+ data (with the layer type, color, and styling you want).
310
+
311
+ The dataset is named after the URL filename (e.g. `nyc.geojson`). If the
312
+ user wants a specific dataset name, pass it as `datasetName`:
313
+
314
+ ```json
315
+ { "url": "https://.../nyc.geojson", "datasetName": "NYC Neighborhoods" }
316
+ ```
317
+
318
+ Local files: a local file must be served over http(s) — the browser cannot
319
+ fetch `file://` paths. Copy the file into the demo app's served directory
320
+ (e.g. `examples/demo-app/dist/`) and pass `/filename.csv`, or serve it with
321
+ a CORS-enabled local server (`npx serve --cors -l 8000`) and pass
322
+ `http://localhost:8000/filename.csv`. If you have the file content but
323
+ cannot serve it (e.g. a remote browser context), pass it as a data URL —
324
+ `data:text/csv;base64,<base64 content>` (encode with `base64 -i file.csv`).
325
+ This works for small files (up to ~2MB).
326
+
327
+ For large files (over a few MB), prefer Parquet (`.parquet`) over
328
+ GeoJSON/CSV — it loads much faster and is less likely to time out. Convert
329
+ GeoJSON to GeoParquet with geopandas (`gdf.to_parquet("data.parquet")`);
330
+ kepler reads GeoParquet geometry (WKB) natively, so the map renders the
331
+ same lines.
332
+
333
+ Do NOT create a duplicate dataset just to rename it — never run
334
+ `map.create-table` with a plain `SELECT *` (or any copy) to give the loaded
335
+ data a friendlier name. `map.create-table` creates a SEPARATE new dataset and
336
+ is only for real column transformations; the rename belongs in
337
+ `map.load-data`'s `datasetName` (or in the user's hands). Use the loaded
338
+ dataset as-is and add the layer to it.
339
+
340
+ ### 8. Map boundary
341
+
342
+ ```json
343
+ {}
344
+ ```
345
+
346
+ Returns the northwest and southeast coordinates of the current map view:
347
+ `{ boundary: { nw: [lon, lat], se: [lon, lat] } }`. When the user says
348
+ "current map view", call this to scope spatial queries to the visible area.
349
+
350
+ ### 9. Add / rename / retype a column in an EXISTING dataset (`map.add-column`)
351
+
352
+ `map.add-column` adds a NEW column to an existing dataset **in place** — the
353
+ dataset keeps its name, id, color and layers, and existing columns are
354
+ untouched. The new column's values come from exactly ONE of two sources:
355
+
356
+ - `copyFromColumn` — copy an existing column's values. This is how you rename a
357
+ column in place: to rename `fare` to `fare_amount`, add `fare_amount` copying
358
+ `fare` (the original column stays — the command never removes columns).
359
+ - `expression` — an SQL expression computed per row, for a derived variable
360
+ (z-score, ratio, concatenation) OR a type change:
361
+ - z-score: `{ datasetName, newColumnName: "HR60_Z", expression: "(HR60 - AVG(HR60) OVER()) / STDDEV(HR60) OVER()" }`
362
+ - type change: `{ datasetName, newColumnName: "NOSOUTH_str", expression: "NOSOUTH::VARCHAR" }`
363
+ (or `CAST(NOSOUTH AS VARCHAR)`). The new column holds the cast values; the
364
+ original column stays.
365
+
366
+ ```json
367
+ {
368
+ "datasetName": "natregimes.geojson",
369
+ "newColumnName": "NOSOUTH_str",
370
+ "expression": "NOSOUTH::VARCHAR"
371
+ }
372
+ ```
373
+
374
+ `map.create-table` is NOT for this — it builds a separate NEW dataset and leaves
375
+ the original untouched. Prefer `map.add-column` whenever the user wants the
376
+ change to land in the existing dataset.
377
+
378
+ ### View mode: 2D map, 3D map, or globe (`map.set-view-mode`)
379
+
380
+ ```json
381
+ { "mode": "globe" }
382
+ ```
383
+
384
+ - `2d` — flat map, no tilt. The default for city- and region-scale data.
385
+ - `3d` — the flat map tilted (pitch 50). For extruded buildings, 3D layers and a
386
+ more dramatic camera; it is **not** a globe.
387
+ - `globe` — the 3D globe with atmosphere. Use it when the data spans the world
388
+ (global trips, arcs, lines, points, clusters, hexagons, grids, GeoJSON), so
389
+ the user sees the whole planet instead of a distorted flat world.
390
+
391
+ Switching to `globe` clamps zoom into the globe's range; switching back to
392
+ `2d`/`3d` restores the normal range. The camera mode is independent of the
393
+ basemap, so set both when the user asks for a "dark globe" and the like.
394
+
395
+ - **Keep `flow` and `flowField` layers off the globe.** Neither is supported
396
+ there yet — flow arrows collapse when seen edge-on, and the flow field's
397
+ clipping is mercator-only. Create a global flow field on the 2d map; if the
398
+ user wants a globe view of global movement, use `arc`, `line` or `trip`
399
+ instead, or tell them the field layer needs the flat map.
400
+ - Do not switch modes unless the user asks for it or the data's global extent
401
+ makes it clearly better; a map that suddenly becomes a globe is surprising.
402
+
403
+ ## Rules
404
+
405
+ - Commands that add datasets to the map — `map.load-data`, `map.save-data`,
406
+ `map.create-table` — do NOT auto-create layers. Always call `map.add-layer`
407
+ afterward to visualize the result.
408
+ - To add a variable to, rename a column in, or change a column type in an
409
+ EXISTING dataset, use `map.add-column` (copy or expression) — do NOT create a
410
+ new dataset. `map.create-table` only when the user wants a SEPARATE new
411
+ dataset.
412
+ - A dataset loaded from a URL keeps the URL filename (or the `datasetName` you
413
+ pass to `map.load-data`). NEVER create a duplicate dataset via
414
+ `map.create-table` just to rename it — use the loaded dataset as-is.
415
+ - For change-over-time requests, create exactly ONE animated layer — never
416
+ a separate static layer per time step.
417
+ - Do not add a `map.add-time-filter` to a trip layer — trips animate
418
+ themselves.
419
+ - If a basemap style name is ambiguous, ask the user to clarify rather than
420
+ guessing.
421
+ - For layer color updates, the `layerId` must match an existing layer on the
422
+ map. If the user refers to a layer by name rather than id, use the layer
423
+ name to find the matching layer id from the dataset context.
424
+
425
+ ## Before your final message
426
+
427
+ - If you created a layer, confirm the layer type, name, and (if any) the
428
+ color field/colorType applied.
429
+ - If you added a time filter, confirm the animated column and interval.
430
+ - If you enabled split view, confirm which layers are on each panel.
431
+ - If you changed the basemap, confirm the new `styleType`.
432
+ - If you updated layer colors, confirm the layer id and colors applied.
433
+ - If you loaded data, confirm the dataset was loaded and a layer was created.
434
+ - If you read the map boundary, report the northwest and southeast
435
+ coordinates.
436
+ - If `map.add-layer` returned `dateTimeColumns` and the user asked about
437
+ change over time, you MUST follow up with `map.add-time-filter` on the first
438
+ returned column — do not leave the temporal hint unactioned.
@@ -0,0 +1,4 @@
1
+ id: kepler
2
+ version: 0.2.0
3
+ name: Kepler map management
4
+ description: Create and configure kepler.gl map layers (point, flow, flowField, arc, line, grid, hexagon, geojson, cluster, heatmap, h3, trip, s2) from datasets, animate them over time, compare them side by side, change the basemap, switch between the 2D, 3D and globe views, update layer colors, load data from a URL, add columns to existing datasets, and read the current map boundary.
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.