@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.
- package/dist/cjs/commands/add-column-command.js +192 -0
- package/dist/cjs/commands/basemap-command.js +80 -0
- package/dist/cjs/commands/boundary-command.js +81 -0
- package/dist/cjs/commands/command-wrappers.js +122 -0
- package/dist/cjs/commands/dataset-context-command.js +87 -0
- package/dist/cjs/commands/index.js +230 -0
- package/dist/cjs/commands/layer-creation-command.js +534 -0
- package/dist/cjs/commands/layer-style-command.js +136 -0
- package/dist/cjs/commands/load-data-command.js +270 -0
- package/dist/cjs/commands/save-data-command.js +118 -0
- package/dist/cjs/commands/split-view-command.js +261 -0
- package/dist/cjs/commands/table-command.js +199 -0
- package/dist/cjs/commands/time-filter-command.js +289 -0
- package/dist/cjs/commands/toggle-time-filter-command.js +155 -0
- package/dist/cjs/commands/types.js +6 -0
- package/dist/cjs/commands/utils.js +536 -0
- package/dist/cjs/commands/view-mode-command.js +94 -0
- package/dist/cjs/index.js +39 -0
- package/dist/cjs/map-contract.js +6 -0
- package/dist/cjs/server/bridge-server.js +435 -0
- package/dist/cjs/server/index.js +31 -0
- package/dist/cjs/server/stdio.js +201 -0
- package/dist/cjs/types.js +30 -0
- package/dist/commands/add-column-command.d.ts +4 -0
- package/dist/commands/basemap-command.d.ts +4 -0
- package/dist/commands/boundary-command.d.ts +4 -0
- package/dist/commands/command-wrappers.d.ts +52 -0
- package/dist/commands/dataset-context-command.d.ts +4 -0
- package/dist/commands/index.d.ts +31 -0
- package/dist/commands/layer-creation-command.d.ts +8 -0
- package/dist/commands/layer-style-command.d.ts +4 -0
- package/dist/commands/load-data-command.d.ts +4 -0
- package/dist/commands/save-data-command.d.ts +4 -0
- package/dist/commands/split-view-command.d.ts +4 -0
- package/dist/commands/table-command.d.ts +4 -0
- package/dist/commands/time-filter-command.d.ts +13 -0
- package/dist/commands/toggle-time-filter-command.d.ts +4 -0
- package/dist/commands/types.d.ts +132 -0
- package/dist/commands/utils.d.ts +138 -0
- package/dist/commands/view-mode-command.d.ts +4 -0
- package/dist/esm/commands/add-column-command.js +185 -0
- package/dist/esm/commands/basemap-command.js +72 -0
- package/dist/esm/commands/boundary-command.js +73 -0
- package/dist/esm/commands/command-wrappers.js +114 -0
- package/dist/esm/commands/dataset-context-command.js +79 -0
- package/dist/esm/commands/index.js +51 -0
- package/dist/esm/commands/layer-creation-command.js +527 -0
- package/dist/esm/commands/layer-style-command.js +130 -0
- package/dist/esm/commands/load-data-command.js +264 -0
- package/dist/esm/commands/save-data-command.js +112 -0
- package/dist/esm/commands/split-view-command.js +255 -0
- package/dist/esm/commands/table-command.js +194 -0
- package/dist/esm/commands/time-filter-command.js +280 -0
- package/dist/esm/commands/toggle-time-filter-command.js +147 -0
- package/dist/esm/commands/types.js +3 -0
- package/dist/esm/commands/utils.js +521 -0
- package/dist/esm/commands/view-mode-command.js +86 -0
- package/dist/esm/index.js +20 -0
- package/dist/esm/map-contract.js +3 -0
- package/dist/esm/server/bridge-server.js +428 -0
- package/dist/esm/server/index.js +13 -0
- package/dist/esm/server/stdio.js +198 -0
- package/dist/esm/types.js +24 -0
- package/dist/index.d.ts +15 -0
- package/dist/map-contract.d.ts +31 -0
- package/dist/server/bridge-server.d.ts +53 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/stdio.d.ts +2 -0
- package/dist/types.d.ts +24 -0
- package/package.json +84 -4
- package/skill/kepler/SKILL.md +438 -0
- package/skill/kepler/skill.yaml +4 -0
- package/README.md +0 -3
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// SPDX-License-Identifier: MIT
|
|
4
|
+
// Copyright contributors to the kepler.gl project
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `kepler-mcp` — a stdio MCP server for the kepler.gl map surface.
|
|
8
|
+
*
|
|
9
|
+
* The agent starts this process (it speaks MCP on stdin/stdout); the process
|
|
10
|
+
* also listens for the map page on a loopback WebSocket. It prints a URL that
|
|
11
|
+
* carries the one-time token — open that URL and the page connects, after which
|
|
12
|
+
* every map.* tool call executes against the live map.
|
|
13
|
+
*
|
|
14
|
+
* stdout belongs to the MCP protocol: every log line here goes to stderr.
|
|
15
|
+
*/
|
|
16
|
+
"use strict";
|
|
17
|
+
|
|
18
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
19
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
20
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
21
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
22
|
+
var _nodeFs = require("node:fs");
|
|
23
|
+
var _nodePath = require("node:path");
|
|
24
|
+
var _index = require("@modelcontextprotocol/sdk/server/index.js");
|
|
25
|
+
var _stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
26
|
+
var _types = require("@modelcontextprotocol/sdk/types.js");
|
|
27
|
+
var _bridgeServer = require("./bridge-server");
|
|
28
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
29
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
30
|
+
var DEFAULT_MAP_URL = 'http://localhost:8080';
|
|
31
|
+
function readVersion() {
|
|
32
|
+
if (typeof __dirname === 'undefined') return '0.0.0';
|
|
33
|
+
var directory = __dirname;
|
|
34
|
+
// Walk up until the package manifest is found, so this works both from src/
|
|
35
|
+
// (babel-node, tests) and from dist/cjs/server (the published bin).
|
|
36
|
+
for (var depth = 0; depth < 5; depth++) {
|
|
37
|
+
try {
|
|
38
|
+
var manifest = JSON.parse((0, _nodeFs.readFileSync)((0, _nodePath.join)(directory, 'package.json'), 'utf8'));
|
|
39
|
+
if (manifest.name === '@kepler.gl/mcp') return manifest.version;
|
|
40
|
+
} catch (_unused) {
|
|
41
|
+
// no manifest at this level — keep walking
|
|
42
|
+
}
|
|
43
|
+
directory = (0, _nodePath.dirname)(directory);
|
|
44
|
+
}
|
|
45
|
+
return '0.0.0';
|
|
46
|
+
}
|
|
47
|
+
function usage() {
|
|
48
|
+
return ['Usage: kepler-mcp [--port <n>] [--host <h>] [--map-url <url>]', '', 'Runs a stdio MCP server for the kepler.gl map surface and waits for a', 'kepler.gl page to connect over a loopback WebSocket.', '', ' --port <n> WebSocket port for the page (default 8765)', ' --host <h> loopback host to bind (default 127.0.0.1)', " --map-url <url> page URL printed with the token (default ".concat(DEFAULT_MAP_URL, ")")].join('\n');
|
|
49
|
+
}
|
|
50
|
+
function parseArgs(argv) {
|
|
51
|
+
var options = {};
|
|
52
|
+
for (var i = 0; i < argv.length; i++) {
|
|
53
|
+
var arg = argv[i];
|
|
54
|
+
if (arg === '--help' || arg === '-h') {
|
|
55
|
+
options.help = true;
|
|
56
|
+
} else if (arg === '--port') {
|
|
57
|
+
var value = Number(argv[++i]);
|
|
58
|
+
if (!Number.isInteger(value) || value < 0 || value > 65535) {
|
|
59
|
+
throw new Error("Invalid --port value: ".concat(argv[i]));
|
|
60
|
+
}
|
|
61
|
+
options.port = value;
|
|
62
|
+
} else if (arg === '--host') {
|
|
63
|
+
options.host = argv[++i];
|
|
64
|
+
} else if (arg === '--map-url') {
|
|
65
|
+
options.mapUrl = argv[++i];
|
|
66
|
+
} else {
|
|
67
|
+
throw new Error("Unknown argument: ".concat(arg));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return options;
|
|
71
|
+
}
|
|
72
|
+
function main() {
|
|
73
|
+
return _main.apply(this, arguments);
|
|
74
|
+
}
|
|
75
|
+
function _main() {
|
|
76
|
+
_main = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee4() {
|
|
77
|
+
var options, bridge, started, server, shutdown;
|
|
78
|
+
return _regenerator["default"].wrap(function _callee4$(_context4) {
|
|
79
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
80
|
+
case 0:
|
|
81
|
+
options = parseArgs(process.argv.slice(2));
|
|
82
|
+
if (!options.help) {
|
|
83
|
+
_context4.next = 4;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
console.error(usage());
|
|
87
|
+
return _context4.abrupt("return");
|
|
88
|
+
case 4:
|
|
89
|
+
bridge = new _bridgeServer.KeplerMcpBridge(options);
|
|
90
|
+
_context4.next = 7;
|
|
91
|
+
return bridge.start();
|
|
92
|
+
case 7:
|
|
93
|
+
started = _context4.sent;
|
|
94
|
+
server = new _index.Server({
|
|
95
|
+
name: 'kepler-mcp',
|
|
96
|
+
version: readVersion()
|
|
97
|
+
}, {
|
|
98
|
+
capabilities: {
|
|
99
|
+
tools: {}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
server.setRequestHandler(_types.ListToolsRequestSchema, /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
|
|
103
|
+
return _regenerator["default"].wrap(function _callee$(_context) {
|
|
104
|
+
while (1) switch (_context.prev = _context.next) {
|
|
105
|
+
case 0:
|
|
106
|
+
return _context.abrupt("return", {
|
|
107
|
+
tools: bridge.getTools().map(function (tool) {
|
|
108
|
+
return {
|
|
109
|
+
name: tool.name,
|
|
110
|
+
description: tool.description,
|
|
111
|
+
inputSchema: tool.inputSchema
|
|
112
|
+
};
|
|
113
|
+
})
|
|
114
|
+
});
|
|
115
|
+
case 1:
|
|
116
|
+
case "end":
|
|
117
|
+
return _context.stop();
|
|
118
|
+
}
|
|
119
|
+
}, _callee);
|
|
120
|
+
})));
|
|
121
|
+
server.setRequestHandler(_types.CallToolRequestSchema, /*#__PURE__*/function () {
|
|
122
|
+
var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(request) {
|
|
123
|
+
var _request$params, name, args, result, _formatResult, text, isError;
|
|
124
|
+
return _regenerator["default"].wrap(function _callee2$(_context2) {
|
|
125
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
126
|
+
case 0:
|
|
127
|
+
_request$params = request.params, name = _request$params.name, args = _request$params.arguments;
|
|
128
|
+
_context2.prev = 1;
|
|
129
|
+
_context2.next = 4;
|
|
130
|
+
return bridge.callTool(name, args !== null && args !== void 0 ? args : {});
|
|
131
|
+
case 4:
|
|
132
|
+
result = _context2.sent;
|
|
133
|
+
_formatResult = (0, _bridgeServer.formatResult)(result), text = _formatResult.text, isError = _formatResult.isError;
|
|
134
|
+
return _context2.abrupt("return", _objectSpread({
|
|
135
|
+
content: [{
|
|
136
|
+
type: 'text',
|
|
137
|
+
text: text
|
|
138
|
+
}]
|
|
139
|
+
}, isError ? {
|
|
140
|
+
isError: true
|
|
141
|
+
} : {}));
|
|
142
|
+
case 9:
|
|
143
|
+
_context2.prev = 9;
|
|
144
|
+
_context2.t0 = _context2["catch"](1);
|
|
145
|
+
return _context2.abrupt("return", {
|
|
146
|
+
content: [{
|
|
147
|
+
type: 'text',
|
|
148
|
+
text: _context2.t0 instanceof Error ? _context2.t0.message : String(_context2.t0)
|
|
149
|
+
}],
|
|
150
|
+
isError: true
|
|
151
|
+
});
|
|
152
|
+
case 12:
|
|
153
|
+
case "end":
|
|
154
|
+
return _context2.stop();
|
|
155
|
+
}
|
|
156
|
+
}, _callee2, null, [[1, 9]]);
|
|
157
|
+
}));
|
|
158
|
+
return function (_x) {
|
|
159
|
+
return _ref2.apply(this, arguments);
|
|
160
|
+
};
|
|
161
|
+
}());
|
|
162
|
+
shutdown = /*#__PURE__*/function () {
|
|
163
|
+
var _ref3 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee3() {
|
|
164
|
+
return _regenerator["default"].wrap(function _callee3$(_context3) {
|
|
165
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
166
|
+
case 0:
|
|
167
|
+
_context3.next = 2;
|
|
168
|
+
return bridge.close();
|
|
169
|
+
case 2:
|
|
170
|
+
process.exit(0);
|
|
171
|
+
case 3:
|
|
172
|
+
case "end":
|
|
173
|
+
return _context3.stop();
|
|
174
|
+
}
|
|
175
|
+
}, _callee3);
|
|
176
|
+
}));
|
|
177
|
+
return function shutdown() {
|
|
178
|
+
return _ref3.apply(this, arguments);
|
|
179
|
+
};
|
|
180
|
+
}();
|
|
181
|
+
process.on('SIGINT', shutdown);
|
|
182
|
+
process.on('SIGTERM', shutdown);
|
|
183
|
+
_context4.next = 16;
|
|
184
|
+
return server.connect(new _stdio.StdioServerTransport());
|
|
185
|
+
case 16:
|
|
186
|
+
console.error("[kepler-mcp] bridge listening on ws://".concat(started.host, ":").concat(started.port, "/ws"));
|
|
187
|
+
console.error("[kepler-mcp] open http://".concat(started.host, ":").concat(started.port, "/ in a browser \u2014 it redirects ") + 'to the map page with the token — so the agent can drive the map');
|
|
188
|
+
console.error("[kepler-mcp] or open ".concat(started.pageUrl));
|
|
189
|
+
case 19:
|
|
190
|
+
case "end":
|
|
191
|
+
return _context4.stop();
|
|
192
|
+
}
|
|
193
|
+
}, _callee4);
|
|
194
|
+
}));
|
|
195
|
+
return _main.apply(this, arguments);
|
|
196
|
+
}
|
|
197
|
+
main()["catch"](function (error) {
|
|
198
|
+
console.error("[kepler-mcp] ".concat(error instanceof Error ? error.message : String(error)));
|
|
199
|
+
process.exit(1);
|
|
200
|
+
});
|
|
201
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9yZWdlbmVyYXRvciIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJfYXN5bmNUb0dlbmVyYXRvcjIiLCJfbm9kZUZzIiwiX25vZGVQYXRoIiwiX2luZGV4IiwiX3N0ZGlvIiwiX3R5cGVzIiwiX2JyaWRnZVNlcnZlciIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiZGVmaW5lUHJvcGVydHkiLCJERUZBVUxUX01BUF9VUkwiLCJyZWFkVmVyc2lvbiIsIl9fZGlybmFtZSIsImRpcmVjdG9yeSIsImRlcHRoIiwibWFuaWZlc3QiLCJKU09OIiwicGFyc2UiLCJyZWFkRmlsZVN5bmMiLCJqb2luIiwibmFtZSIsInZlcnNpb24iLCJfdW51c2VkIiwiZGlybmFtZSIsInVzYWdlIiwiY29uY2F0IiwicGFyc2VBcmdzIiwiYXJndiIsIm9wdGlvbnMiLCJpIiwiYXJnIiwiaGVscCIsInZhbHVlIiwiTnVtYmVyIiwiaXNJbnRlZ2VyIiwiRXJyb3IiLCJwb3J0IiwiaG9zdCIsIm1hcFVybCIsIm1haW4iLCJfbWFpbiIsIm1hcmsiLCJfY2FsbGVlNCIsImJyaWRnZSIsInN0YXJ0ZWQiLCJzZXJ2ZXIiLCJzaHV0ZG93biIsIndyYXAiLCJfY2FsbGVlNCQiLCJfY29udGV4dDQiLCJwcmV2IiwibmV4dCIsInByb2Nlc3MiLCJzbGljZSIsImNvbnNvbGUiLCJlcnJvciIsImFicnVwdCIsIktlcGxlck1jcEJyaWRnZSIsInN0YXJ0Iiwic2VudCIsIlNlcnZlciIsImNhcGFiaWxpdGllcyIsInRvb2xzIiwic2V0UmVxdWVzdEhhbmRsZXIiLCJMaXN0VG9vbHNSZXF1ZXN0U2NoZW1hIiwiX2NhbGxlZSIsIl9jYWxsZWUkIiwiX2NvbnRleHQiLCJnZXRUb29scyIsIm1hcCIsInRvb2wiLCJkZXNjcmlwdGlvbiIsImlucHV0U2NoZW1hIiwic3RvcCIsIkNhbGxUb29sUmVxdWVzdFNjaGVtYSIsIl9yZWYyIiwiX2NhbGxlZTIiLCJyZXF1ZXN0IiwiX3JlcXVlc3QkcGFyYW1zIiwiYXJncyIsInJlc3VsdCIsIl9mb3JtYXRSZXN1bHQiLCJ0ZXh0IiwiaXNFcnJvciIsIl9jYWxsZWUyJCIsIl9jb250ZXh0MiIsInBhcmFtcyIsImNhbGxUb29sIiwiZm9ybWF0UmVzdWx0IiwiY29udGVudCIsInR5cGUiLCJ0MCIsIm1lc3NhZ2UiLCJTdHJpbmciLCJfeCIsIl9yZWYzIiwiX2NhbGxlZTMiLCJfY2FsbGVlMyQiLCJfY29udGV4dDMiLCJjbG9zZSIsImV4aXQiLCJvbiIsImNvbm5lY3QiLCJTdGRpb1NlcnZlclRyYW5zcG9ydCIsInBhZ2VVcmwiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmVyL3N0ZGlvLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIiMhL3Vzci9iaW4vZW52IG5vZGVcblxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuLyoqXG4gKiBga2VwbGVyLW1jcGAg4oCUIGEgc3RkaW8gTUNQIHNlcnZlciBmb3IgdGhlIGtlcGxlci5nbCBtYXAgc3VyZmFjZS5cbiAqXG4gKiBUaGUgYWdlbnQgc3RhcnRzIHRoaXMgcHJvY2VzcyAoaXQgc3BlYWtzIE1DUCBvbiBzdGRpbi9zdGRvdXQpOyB0aGUgcHJvY2Vzc1xuICogYWxzbyBsaXN0ZW5zIGZvciB0aGUgbWFwIHBhZ2Ugb24gYSBsb29wYmFjayBXZWJTb2NrZXQuIEl0IHByaW50cyBhIFVSTCB0aGF0XG4gKiBjYXJyaWVzIHRoZSBvbmUtdGltZSB0b2tlbiDigJQgb3BlbiB0aGF0IFVSTCBhbmQgdGhlIHBhZ2UgY29ubmVjdHMsIGFmdGVyIHdoaWNoXG4gKiBldmVyeSBtYXAuKiB0b29sIGNhbGwgZXhlY3V0ZXMgYWdhaW5zdCB0aGUgbGl2ZSBtYXAuXG4gKlxuICogc3Rkb3V0IGJlbG9uZ3MgdG8gdGhlIE1DUCBwcm90b2NvbDogZXZlcnkgbG9nIGxpbmUgaGVyZSBnb2VzIHRvIHN0ZGVyci5cbiAqL1xuXG5pbXBvcnQge3JlYWRGaWxlU3luY30gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQge2Rpcm5hbWUsIGpvaW59IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQge1NlcnZlcn0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvaW5kZXguanMnO1xuaW1wb3J0IHtTdGRpb1NlcnZlclRyYW5zcG9ydH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvc3RkaW8uanMnO1xuaW1wb3J0IHtDYWxsVG9vbFJlcXVlc3RTY2hlbWEsIExpc3RUb29sc1JlcXVlc3RTY2hlbWF9IGZyb20gJ0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvdHlwZXMuanMnO1xuaW1wb3J0IHtLZXBsZXJNY3BCcmlkZ2UsIGZvcm1hdFJlc3VsdH0gZnJvbSAnLi9icmlkZ2Utc2VydmVyJztcbmltcG9ydCB0eXBlIHtLZXBsZXJNY3BCcmlkZ2VPcHRpb25zfSBmcm9tICcuL2JyaWRnZS1zZXJ2ZXInO1xuXG5jb25zdCBERUZBVUxUX01BUF9VUkwgPSAnaHR0cDovL2xvY2FsaG9zdDo4MDgwJztcblxuZnVuY3Rpb24gcmVhZFZlcnNpb24oKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiBfX2Rpcm5hbWUgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gJzAuMC4wJztcbiAgbGV0IGRpcmVjdG9yeSA9IF9fZGlybmFtZTtcbiAgLy8gV2FsayB1cCB1bnRpbCB0aGUgcGFja2FnZSBtYW5pZmVzdCBpcyBmb3VuZCwgc28gdGhpcyB3b3JrcyBib3RoIGZyb20gc3JjL1xuICAvLyAoYmFiZWwtbm9kZSwgdGVzdHMpIGFuZCBmcm9tIGRpc3QvY2pzL3NlcnZlciAodGhlIHB1Ymxpc2hlZCBiaW4pLlxuICBmb3IgKGxldCBkZXB0aCA9IDA7IGRlcHRoIDwgNTsgZGVwdGgrKykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBtYW5pZmVzdCA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKGpvaW4oZGlyZWN0b3J5LCAncGFja2FnZS5qc29uJyksICd1dGY4JykpO1xuICAgICAgaWYgKG1hbmlmZXN0Lm5hbWUgPT09ICdAa2VwbGVyLmdsL21jcCcpIHJldHVybiBtYW5pZmVzdC52ZXJzaW9uO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gbm8gbWFuaWZlc3QgYXQgdGhpcyBsZXZlbCDigJQga2VlcCB3YWxraW5nXG4gICAgfVxuICAgIGRpcmVjdG9yeSA9IGRpcm5hbWUoZGlyZWN0b3J5KTtcbiAgfVxuICByZXR1cm4gJzAuMC4wJztcbn1cblxuZnVuY3Rpb24gdXNhZ2UoKTogc3RyaW5nIHtcbiAgcmV0dXJuIFtcbiAgICAnVXNhZ2U6IGtlcGxlci1tY3AgWy0tcG9ydCA8bj5dIFstLWhvc3QgPGg+XSBbLS1tYXAtdXJsIDx1cmw+XScsXG4gICAgJycsXG4gICAgJ1J1bnMgYSBzdGRpbyBNQ1Agc2VydmVyIGZvciB0aGUga2VwbGVyLmdsIG1hcCBzdXJmYWNlIGFuZCB3YWl0cyBmb3IgYScsXG4gICAgJ2tlcGxlci5nbCBwYWdlIHRvIGNvbm5lY3Qgb3ZlciBhIGxvb3BiYWNrIFdlYlNvY2tldC4nLFxuICAgICcnLFxuICAgICcgIC0tcG9ydCA8bj4gICAgICAgV2ViU29ja2V0IHBvcnQgZm9yIHRoZSBwYWdlIChkZWZhdWx0IDg3NjUpJyxcbiAgICAnICAtLWhvc3QgPGg+ICAgICAgIGxvb3BiYWNrIGhvc3QgdG8gYmluZCAoZGVmYXVsdCAxMjcuMC4wLjEpJyxcbiAgICBgICAtLW1hcC11cmwgPHVybD4gIHBhZ2UgVVJMIHByaW50ZWQgd2l0aCB0aGUgdG9rZW4gKGRlZmF1bHQgJHtERUZBVUxUX01BUF9VUkx9KWBcbiAgXS5qb2luKCdcXG4nKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VBcmdzKGFyZ3Y6IHN0cmluZ1tdKTogS2VwbGVyTWNwQnJpZGdlT3B0aW9ucyAmIHtoZWxwPzogYm9vbGVhbn0ge1xuICBjb25zdCBvcHRpb25zOiBLZXBsZXJNY3BCcmlkZ2VPcHRpb25zICYge2hlbHA/OiBib29sZWFufSA9IHt9O1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3YubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBhcmcgPSBhcmd2W2ldO1xuICAgIGlmIChhcmcgPT09ICctLWhlbHAnIHx8IGFyZyA9PT0gJy1oJykge1xuICAgICAgb3B0aW9ucy5oZWxwID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKGFyZyA9PT0gJy0tcG9ydCcpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gTnVtYmVyKGFyZ3ZbKytpXSk7XG4gICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIodmFsdWUpIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDY1NTM1KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCAtLXBvcnQgdmFsdWU6ICR7YXJndltpXX1gKTtcbiAgICAgIH1cbiAgICAgIG9wdGlvbnMucG9ydCA9IHZhbHVlO1xuICAgIH0gZWxzZSBpZiAoYXJnID09PSAnLS1ob3N0Jykge1xuICAgICAgb3B0aW9ucy5ob3N0ID0gYXJndlsrK2ldO1xuICAgIH0gZWxzZSBpZiAoYXJnID09PSAnLS1tYXAtdXJsJykge1xuICAgICAgb3B0aW9ucy5tYXBVcmwgPSBhcmd2WysraV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBhcmd1bWVudDogJHthcmd9YCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBvcHRpb25zO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtYWluKCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBvcHRpb25zID0gcGFyc2VBcmdzKHByb2Nlc3MuYXJndi5zbGljZSgyKSk7XG4gIGlmIChvcHRpb25zLmhlbHApIHtcbiAgICBjb25zb2xlLmVycm9yKHVzYWdlKCkpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGJyaWRnZSA9IG5ldyBLZXBsZXJNY3BCcmlkZ2Uob3B0aW9ucyk7XG4gIGNvbnN0IHN0YXJ0ZWQgPSBhd2FpdCBicmlkZ2Uuc3RhcnQoKTtcblxuICBjb25zdCBzZXJ2ZXIgPSBuZXcgU2VydmVyKFxuICAgIHtuYW1lOiAna2VwbGVyLW1jcCcsIHZlcnNpb246IHJlYWRWZXJzaW9uKCl9LFxuICAgIHtjYXBhYmlsaXRpZXM6IHt0b29sczoge319fVxuICApO1xuXG4gIHNlcnZlci5zZXRSZXF1ZXN0SGFuZGxlcihMaXN0VG9vbHNSZXF1ZXN0U2NoZW1hLCBhc3luYyAoKSA9PiAoe1xuICAgIHRvb2xzOiBicmlkZ2UuZ2V0VG9vbHMoKS5tYXAodG9vbCA9PiAoe1xuICAgICAgbmFtZTogdG9vbC5uYW1lLFxuICAgICAgZGVzY3JpcHRpb246IHRvb2wuZGVzY3JpcHRpb24sXG4gICAgICBpbnB1dFNjaGVtYTogdG9vbC5pbnB1dFNjaGVtYSBhcyB7dHlwZTogJ29iamVjdCc7IFtrZXk6IHN0cmluZ106IHVua25vd259XG4gICAgfSkpXG4gIH0pKTtcblxuICBzZXJ2ZXIuc2V0UmVxdWVzdEhhbmRsZXIoQ2FsbFRvb2xSZXF1ZXN0U2NoZW1hLCBhc3luYyByZXF1ZXN0ID0+IHtcbiAgICBjb25zdCB7bmFtZSwgYXJndW1lbnRzOiBhcmdzfSA9IHJlcXVlc3QucGFyYW1zO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBicmlkZ2UuY2FsbFRvb2wobmFtZSwgKGFyZ3MgPz8ge30pIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgICAgIGNvbnN0IHt0ZXh0LCBpc0Vycm9yfSA9IGZvcm1hdFJlc3VsdChyZXN1bHQpO1xuICAgICAgcmV0dXJuIHtjb250ZW50OiBbe3R5cGU6ICd0ZXh0JyBhcyBjb25zdCwgdGV4dH1dLCAuLi4oaXNFcnJvciA/IHtpc0Vycm9yOiB0cnVlfSA6IHt9KX07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICB7dHlwZTogJ3RleHQnIGFzIGNvbnN0LCB0ZXh0OiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9XG4gICAgICAgIF0sXG4gICAgICAgIGlzRXJyb3I6IHRydWVcbiAgICAgIH07XG4gICAgfVxuICB9KTtcblxuICBjb25zdCBzaHV0ZG93biA9IGFzeW5jICgpID0+IHtcbiAgICBhd2FpdCBicmlkZ2UuY2xvc2UoKTtcbiAgICBwcm9jZXNzLmV4aXQoMCk7XG4gIH07XG4gIHByb2Nlc3Mub24oJ1NJR0lOVCcsIHNodXRkb3duKTtcbiAgcHJvY2Vzcy5vbignU0lHVEVSTScsIHNodXRkb3duKTtcblxuICBhd2FpdCBzZXJ2ZXIuY29ubmVjdChuZXcgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQoKSk7XG5cbiAgY29uc29sZS5lcnJvcihgW2tlcGxlci1tY3BdIGJyaWRnZSBsaXN0ZW5pbmcgb24gd3M6Ly8ke3N0YXJ0ZWQuaG9zdH06JHtzdGFydGVkLnBvcnR9L3dzYCk7XG4gIGNvbnNvbGUuZXJyb3IoXG4gICAgYFtrZXBsZXItbWNwXSBvcGVuIGh0dHA6Ly8ke3N0YXJ0ZWQuaG9zdH06JHtzdGFydGVkLnBvcnR9LyBpbiBhIGJyb3dzZXIg4oCUIGl0IHJlZGlyZWN0cyBgICtcbiAgICAgICd0byB0aGUgbWFwIHBhZ2Ugd2l0aCB0aGUgdG9rZW4g4oCUIHNvIHRoZSBhZ2VudCBjYW4gZHJpdmUgdGhlIG1hcCdcbiAgKTtcbiAgY29uc29sZS5lcnJvcihgW2tlcGxlci1tY3BdIG9yIG9wZW4gJHtzdGFydGVkLnBhZ2VVcmx9YCk7XG59XG5cbm1haW4oKS5jYXRjaChlcnJvciA9PiB7XG4gIGNvbnNvbGUuZXJyb3IoYFtrZXBsZXItbWNwXSAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1gKTtcbiAgcHJvY2Vzcy5leGl0KDEpO1xufSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFUQTs7QUFBQSxJQUFBQSxzQkFBQSxHQUFBQyxPQUFBO0FBQUEsSUFBQUMsWUFBQSxHQUFBRixzQkFBQSxDQUFBQyxPQUFBO0FBQUEsSUFBQUUsZ0JBQUEsR0FBQUgsc0JBQUEsQ0FBQUMsT0FBQTtBQUFBLElBQUFHLGtCQUFBLEdBQUFKLHNCQUFBLENBQUFDLE9BQUE7QUFXQSxJQUFBSSxPQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxTQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxNQUFBLEdBQUFOLE9BQUE7QUFDQSxJQUFBTyxNQUFBLEdBQUFQLE9BQUE7QUFDQSxJQUFBUSxNQUFBLEdBQUFSLE9BQUE7QUFDQSxJQUFBUyxhQUFBLEdBQUFULE9BQUE7QUFBOEQsU0FBQVUsUUFBQUMsQ0FBQSxFQUFBQyxDQUFBLFFBQUFDLENBQUEsR0FBQUMsTUFBQSxDQUFBQyxJQUFBLENBQUFKLENBQUEsT0FBQUcsTUFBQSxDQUFBRSxxQkFBQSxRQUFBQyxDQUFBLEdBQUFILE1BQUEsQ0FBQUUscUJBQUEsQ0FBQUwsQ0FBQSxHQUFBQyxDQUFBLEtBQUFLLENBQUEsR0FBQUEsQ0FBQSxDQUFBQyxNQUFBLFdBQUFOLENBQUEsV0FBQUUsTUFBQSxDQUFBSyx3QkFBQSxDQUFBUixDQUFBLEVBQUFDLENBQUEsRUFBQVEsVUFBQSxPQUFBUCxDQUFBLENBQUFRLElBQUEsQ0FBQUMsS0FBQSxDQUFBVCxDQUFBLEVBQUFJLENBQUEsWUFBQUosQ0FBQTtBQUFBLFNBQUFVLGNBQUFaLENBQUEsYUFBQUMsQ0FBQSxNQUFBQSxDQUFBLEdBQUFZLFNBQUEsQ0FBQUMs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
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.MAP_TOOL_IDS = void 0;
|
|
7
|
+
// SPDX-License-Identifier: MIT
|
|
8
|
+
// Copyright contributors to the kepler.gl project
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Shared contract types for the kepler.gl map surface.
|
|
12
|
+
*
|
|
13
|
+
* This module is the home of the reusable *map surface* contract — the map.*
|
|
14
|
+
* tool namespace that any AI client can drive. It defines the map.* tool ids
|
|
15
|
+
* and the `ToolResult` shape so any host (the demo-app browser page, the
|
|
16
|
+
* kepler-assistant library, or a future MCP server) can implement or consume
|
|
17
|
+
* the same contract.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** A command/tool execution result. */
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The v1 map tool surface. These are the command ids the kepler.gl demo-app's
|
|
24
|
+
* assistant actually registers, reconciled with the kepler-mcp proposal. Most
|
|
25
|
+
* commands are pure map actuation (set-basemap, add-layer, ...); the table ops
|
|
26
|
+
* (map.create-table, map.add-column, map.save-data) are DuckDB-backed and are
|
|
27
|
+
* included because they mutate the map's datasets in place.
|
|
28
|
+
*/
|
|
29
|
+
var MAP_TOOL_IDS = exports.MAP_TOOL_IDS = ['map.set-basemap', 'map.get-boundary', 'map.add-layer', 'map.update-layer-color', 'map.load-data', 'map.save-data', 'map.create-table', 'map.add-column', 'map.add-time-filter', 'map.toggle-time-filter', 'map.split-view', 'map.get-dataset-context'];
|
|
30
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJNQVBfVE9PTF9JRFMiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3R5cGVzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbi8qKlxuICogU2hhcmVkIGNvbnRyYWN0IHR5cGVzIGZvciB0aGUga2VwbGVyLmdsIG1hcCBzdXJmYWNlLlxuICpcbiAqIFRoaXMgbW9kdWxlIGlzIHRoZSBob21lIG9mIHRoZSByZXVzYWJsZSAqbWFwIHN1cmZhY2UqIGNvbnRyYWN0IOKAlCB0aGUgbWFwLipcbiAqIHRvb2wgbmFtZXNwYWNlIHRoYXQgYW55IEFJIGNsaWVudCBjYW4gZHJpdmUuIEl0IGRlZmluZXMgdGhlIG1hcC4qIHRvb2wgaWRzXG4gKiBhbmQgdGhlIGBUb29sUmVzdWx0YCBzaGFwZSBzbyBhbnkgaG9zdCAodGhlIGRlbW8tYXBwIGJyb3dzZXIgcGFnZSwgdGhlXG4gKiBrZXBsZXItYXNzaXN0YW50IGxpYnJhcnksIG9yIGEgZnV0dXJlIE1DUCBzZXJ2ZXIpIGNhbiBpbXBsZW1lbnQgb3IgY29uc3VtZVxuICogdGhlIHNhbWUgY29udHJhY3QuXG4gKi9cblxuLyoqIEEgY29tbWFuZC90b29sIGV4ZWN1dGlvbiByZXN1bHQuICovXG5leHBvcnQgaW50ZXJmYWNlIFRvb2xSZXN1bHQge1xuICBzdWNjZXNzOiBib29sZWFuO1xuICBkYXRhPzogdW5rbm93bjtcbiAgZXJyb3I/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHYxIG1hcCB0b29sIHN1cmZhY2UuIFRoZXNlIGFyZSB0aGUgY29tbWFuZCBpZHMgdGhlIGtlcGxlci5nbCBkZW1vLWFwcCdzXG4gKiBhc3Npc3RhbnQgYWN0dWFsbHkgcmVnaXN0ZXJzLCByZWNvbmNpbGVkIHdpdGggdGhlIGtlcGxlci1tY3AgcHJvcG9zYWwuIE1vc3RcbiAqIGNvbW1hbmRzIGFyZSBwdXJlIG1hcCBhY3R1YXRpb24gKHNldC1iYXNlbWFwLCBhZGQtbGF5ZXIsIC4uLik7IHRoZSB0YWJsZSBvcHNcbiAqIChtYXAuY3JlYXRlLXRhYmxlLCBtYXAuYWRkLWNvbHVtbiwgbWFwLnNhdmUtZGF0YSkgYXJlIER1Y2tEQi1iYWNrZWQgYW5kIGFyZVxuICogaW5jbHVkZWQgYmVjYXVzZSB0aGV5IG11dGF0ZSB0aGUgbWFwJ3MgZGF0YXNldHMgaW4gcGxhY2UuXG4gKi9cbmV4cG9ydCBjb25zdCBNQVBfVE9PTF9JRFMgPSBbXG4gICdtYXAuc2V0LWJhc2VtYXAnLFxuICAnbWFwLmdldC1ib3VuZGFyeScsXG4gICdtYXAuYWRkLWxheWVyJyxcbiAgJ21hcC51cGRhdGUtbGF5ZXItY29sb3InLFxuICAnbWFwLmxvYWQtZGF0YScsXG4gICdtYXAuc2F2ZS1kYXRhJyxcbiAgJ21hcC5jcmVhdGUtdGFibGUnLFxuICAnbWFwLmFkZC1jb2x1bW4nLFxuICAnbWFwLmFkZC10aW1lLWZpbHRlcicsXG4gICdtYXAudG9nZ2xlLXRpbWUtZmlsdGVyJyxcbiAgJ21hcC5zcGxpdC12aWV3JyxcbiAgJ21hcC5nZXQtZGF0YXNldC1jb250ZXh0J1xuXSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgTWFwVG9vbElkID0gKHR5cGVvZiBNQVBfVE9PTF9JRFMpW251bWJlcl07XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sSUFBTUEsWUFBWSxHQUFBQyxPQUFBLENBQUFELFlBQUEsR0FBRyxDQUMxQixpQkFBaUIsRUFDakIsa0JBQWtCLEVBQ2xCLGVBQWUsRUFDZix3QkFBd0IsRUFDeEIsZUFBZSxFQUNmLGVBQWUsRUFDZixrQkFBa0IsRUFDbEIsZ0JBQWdCLEVBQ2hCLHFCQUFxQixFQUNyQix3QkFBd0IsRUFDeEIsZ0JBQWdCLEVBQ2hCLHlCQUF5QixDQUNqQiIsImlnbm9yZUxpc3QiOltdfQ==
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic utility for converting an existing AI SDK tool into a sqlrooms
|
|
3
|
+
* `RoomCommand`. Kept dependency-light (only `zod` + `RoomCommand` type) so it
|
|
4
|
+
* can be reused by any in-browser skill system that wants to expose its
|
|
5
|
+
* existing AI SDK tools as commands without rewriting them.
|
|
6
|
+
*
|
|
7
|
+
* The demo-app's own command factories return `RoomCommand` directly (preferred
|
|
8
|
+
* when you own the command — see `basemap-command.ts` for the reference shape). This
|
|
9
|
+
* wrapper is the fallback path for hosts that cannot rewrite their tools:
|
|
10
|
+
* it folds the tool's `execute`, `inputSchema`, and `toModelOutput` (the
|
|
11
|
+
* token-trim logic the AI SDK applies between tool call and model) into a
|
|
12
|
+
* single `RoomCommand.execute` so the registry-stored result already carries
|
|
13
|
+
* the model-facing subset.
|
|
14
|
+
*/
|
|
15
|
+
import type { RoomCommand } from './types';
|
|
16
|
+
import type { ZodType } from 'zod';
|
|
17
|
+
/** A built AI SDK tool, treated loosely for dynamic dispatch. */
|
|
18
|
+
export type AnyTool = {
|
|
19
|
+
execute?: (args: any, options: any) => Promise<any>;
|
|
20
|
+
toModelOutput?: (params: {
|
|
21
|
+
output: any;
|
|
22
|
+
toolCallId?: string;
|
|
23
|
+
}) => any;
|
|
24
|
+
description?: string;
|
|
25
|
+
inputSchema?: ZodType;
|
|
26
|
+
};
|
|
27
|
+
/** Metadata that the AI SDK tool does not carry but a `RoomCommand` requires. */
|
|
28
|
+
export type CommandMeta = {
|
|
29
|
+
/** Stable, namespaced command id, e.g. `map.set-basemap`. */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Human-readable name shown in the command palette / listings. */
|
|
32
|
+
name: string;
|
|
33
|
+
/** Optional grouping label, e.g. `Map`, `Data`, `GeoDa`. */
|
|
34
|
+
group?: string;
|
|
35
|
+
/** Optional search keywords. */
|
|
36
|
+
keywords?: string[];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Cast a concrete zod schema (e.g. `z.object({...})`, which is `ZodObject<...>`)
|
|
40
|
+
* to the `ZodType<unknown>` that `RoomCommand.inputSchema` expects. The
|
|
41
|
+
* installed zod `ZodObject` is not structurally assignable to sqlrooms'
|
|
42
|
+
* `ZodType<unknown>` (covariance on the output type), so a cast is required at
|
|
43
|
+
* the assignment site. This helper centralizes that cast.
|
|
44
|
+
*/
|
|
45
|
+
export declare function asInputSchema(schema: ZodType): ZodType<unknown>;
|
|
46
|
+
/**
|
|
47
|
+
* Wrap an existing AI SDK tool as a sqlrooms `RoomCommand`. The command's
|
|
48
|
+
* `execute` calls the tool's `execute` and then applies the tool's
|
|
49
|
+
* `toModelOutput` (if any) so the trimmed, model-facing shape is what the
|
|
50
|
+
* registry stores and downstream surfaces (AI skill, palette, CLI, MCP) see.
|
|
51
|
+
*/
|
|
52
|
+
export declare function toolToCommand(tool: AnyTool, meta: CommandMeta): RoomCommand;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { RoomCommand } from './types';
|
|
2
|
+
import type { KeplerContext } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Owner string under which all kepler-ai commands are registered in the
|
|
5
|
+
* room-store command registry. Used by `registerCommandsForOwner` /
|
|
6
|
+
* `unregisterCommandsForOwner` in the host's store wiring.
|
|
7
|
+
*/
|
|
8
|
+
export declare const KEPLER_COMMAND_OWNER = "kepler-ai";
|
|
9
|
+
/**
|
|
10
|
+
* Build the kepler-gl map-mutation commands for a given `KeplerContext`.
|
|
11
|
+
* Returns a map keyed by command id (e.g. `map.set-basemap`) so the registry
|
|
12
|
+
* registration is a flat merge.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getKeplerCommands(ctx: KeplerContext): Record<string, RoomCommand>;
|
|
15
|
+
export { getBasemapCommand } from './basemap-command';
|
|
16
|
+
export { getViewModeCommand } from './view-mode-command';
|
|
17
|
+
export { getMapBoundaryCommand } from './boundary-command';
|
|
18
|
+
export { getAddLayerCommand, guessDefaultLayer } from './layer-creation-command';
|
|
19
|
+
export { getUpdateLayerColorCommand } from './layer-style-command';
|
|
20
|
+
export { getLoadDataCommand } from './load-data-command';
|
|
21
|
+
export { getSaveDataCommand } from './save-data-command';
|
|
22
|
+
export { getTableCommand } from './table-command';
|
|
23
|
+
export { getAddColumnCommand } from './add-column-command';
|
|
24
|
+
export { getAddTimeFilterCommand } from './time-filter-command';
|
|
25
|
+
export { getToggleTimeFilterCommand } from './toggle-time-filter-command';
|
|
26
|
+
export { getSplitViewCommand } from './split-view-command';
|
|
27
|
+
export { getDatasetContextCommand } from './dataset-context-command';
|
|
28
|
+
export { toolToCommand, asInputSchema } from './command-wrappers';
|
|
29
|
+
export type { AnyTool, CommandMeta } from './command-wrappers';
|
|
30
|
+
export type { KeplerContext, KeplerStateAccessors, VisState, RoomCommandResult, RoomCommandExecuteOutput, ToolDescriptor } from './types';
|
|
31
|
+
export { datasetNameToTableName, convertArrowRowToObject, arrowTableToObjects, tableToLLMResult, formatResultsForLLM, NUMBER_OF_ROWS_RETURN_TO_LLM, LLM_PREVIEW_MAX_TOTAL_LENGTH, LLM_PREVIEW_MAX_VALUE_LENGTH, getValuesFromDataset, getValuesFromVectorTileLayer, isObjectColumn, isVectorTileLayer, stringifyObjectColumn, restoreObjectColumns, buildAddColumnPayload } from './utils';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RoomCommand } from './types';
|
|
2
|
+
import type KeplerTable from '@kepler.gl/table';
|
|
3
|
+
import type { KeplerContext } from './types';
|
|
4
|
+
export declare function guessDefaultLayer(dataset: KeplerTable, layerType: string, options?: {
|
|
5
|
+
countColumn?: string;
|
|
6
|
+
}): any;
|
|
7
|
+
export declare const addLayerCommandId: "map.add-layer";
|
|
8
|
+
export declare function getAddLayerCommand(ctx: KeplerContext): RoomCommand;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RoomCommand } from './types';
|
|
2
|
+
import type { KeplerContext } from './types';
|
|
3
|
+
export type IntervalKey = '1-second' | '1-minute' | '1-hour' | '1-day' | '1-week' | '1-month' | '3-month' | '1-year';
|
|
4
|
+
export declare const INTERVAL_MILLIS: Record<IntervalKey, number>;
|
|
5
|
+
/**
|
|
6
|
+
* Infer a sensible animation interval from a time filter's domain and (when
|
|
7
|
+
* available) the actual distinct timestamps in the dataset. Mirrors the logic
|
|
8
|
+
* used by spatial-agent's `detectIntervalFromDomain` so the skill-path behaves
|
|
9
|
+
* identically.
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectIntervalFromDomain(domain: [number, number], mappedValues?: number[]): IntervalKey;
|
|
12
|
+
export declare const addTimeFilterCommandId: "map.add-time-filter";
|
|
13
|
+
export declare function getAddTimeFilterCommand(ctx: KeplerContext): RoomCommand;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { Table as ArrowTable } from 'apache-arrow';
|
|
2
|
+
import type { ZodType } from 'zod';
|
|
3
|
+
import type { Datasets } from '@kepler.gl/table';
|
|
4
|
+
import type { KeplerDispatch } from './utils';
|
|
5
|
+
/**
|
|
6
|
+
* Structural subset of `@sqlrooms/room-store`'s `RoomCommand` — enough for the
|
|
7
|
+
* map.* command factories and for a host to register the built objects. Defined
|
|
8
|
+
* locally (with `zod`, already a dependency) so this package stays free of
|
|
9
|
+
* `@sqlrooms/room-store`; the objects the factories build are structurally
|
|
10
|
+
* compatible with sqlrooms' own `RoomCommand`.
|
|
11
|
+
*/
|
|
12
|
+
export type RoomCommandResult<TData = unknown> = {
|
|
13
|
+
success: boolean;
|
|
14
|
+
commandId: string;
|
|
15
|
+
message?: string;
|
|
16
|
+
code?: string;
|
|
17
|
+
data?: TData;
|
|
18
|
+
error?: string;
|
|
19
|
+
};
|
|
20
|
+
export type RoomCommandExecuteOutput<TData = unknown> = RoomCommandResult<TData> | TData | void;
|
|
21
|
+
export type RoomCommandExecutionContext = {
|
|
22
|
+
store: unknown;
|
|
23
|
+
getState: () => unknown;
|
|
24
|
+
invocation: unknown;
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
};
|
|
27
|
+
export type RoomCommandPolicyMetadata = {
|
|
28
|
+
readOnly?: boolean;
|
|
29
|
+
idempotent?: boolean;
|
|
30
|
+
riskLevel?: 'low' | 'medium' | 'high';
|
|
31
|
+
requiresConfirmation?: boolean;
|
|
32
|
+
};
|
|
33
|
+
export type RoomCommand = {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
group?: string;
|
|
38
|
+
keywords?: string[];
|
|
39
|
+
inputSchema?: ZodType<unknown>;
|
|
40
|
+
metadata?: RoomCommandPolicyMetadata;
|
|
41
|
+
execute: (context: RoomCommandExecutionContext, input?: unknown) => RoomCommandExecuteOutput | Promise<RoomCommandExecuteOutput>;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* A command's model-facing descriptor: the id/name/description/group/keywords
|
|
45
|
+
* plus a JSON-Schema-converted `inputSchema` and the policy metadata. This is
|
|
46
|
+
* the shape hosts advertise over the wire (e.g. the demo-app bridge's
|
|
47
|
+
* `toDescriptor`), so it lives in the map surface package to keep the contract
|
|
48
|
+
* self-contained.
|
|
49
|
+
*/
|
|
50
|
+
export type ToolDescriptor = {
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
description?: string;
|
|
54
|
+
group?: string;
|
|
55
|
+
keywords?: string[];
|
|
56
|
+
inputSchema: Record<string, unknown>;
|
|
57
|
+
metadata?: RoomCommandPolicyMetadata;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Structural slice of `@sqlrooms/duckdb`'s `DuckDbConnector` — only the methods
|
|
61
|
+
* the map.* commands call, typed against apache-arrow so the query result flows
|
|
62
|
+
* into `arrowTableToObjects` / `arrowSchemaToFields` unchanged. Kept local so
|
|
63
|
+
* this package needs no `@sqlrooms/duckdb` dependency; a host's real sqlrooms
|
|
64
|
+
* connector satisfies this shape.
|
|
65
|
+
*/
|
|
66
|
+
export type DuckDbConnector = {
|
|
67
|
+
execute(sql: string, options?: {
|
|
68
|
+
signal?: AbortSignal;
|
|
69
|
+
}): PromiseLike<unknown>;
|
|
70
|
+
query(sql: string, options?: {
|
|
71
|
+
signal?: AbortSignal;
|
|
72
|
+
}): PromiseLike<ArrowTable>;
|
|
73
|
+
loadArrow(table: ArrowTable | Uint8Array, tableName: string, opts?: {
|
|
74
|
+
schema?: string;
|
|
75
|
+
}): Promise<void>;
|
|
76
|
+
};
|
|
77
|
+
export type VisState = {
|
|
78
|
+
datasets: Datasets;
|
|
79
|
+
layers: any[];
|
|
80
|
+
layerData: any[];
|
|
81
|
+
loaders: any[];
|
|
82
|
+
loadOptions: Record<string, any>;
|
|
83
|
+
[key: string]: any;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Accessors to the kepler.gl application state the assistant needs. The host
|
|
87
|
+
* app supplies these (via `setKeplerStateAccessors`) so this module never
|
|
88
|
+
* hard-codes a redux state shape (e.g. `demo.keplerGl.map.visState`). Any
|
|
89
|
+
* app can provide accessors matching its own store.
|
|
90
|
+
*/
|
|
91
|
+
export type KeplerStateAccessors = {
|
|
92
|
+
getVisState: () => VisState;
|
|
93
|
+
getMapBoundary: () => {
|
|
94
|
+
nw: [number, number];
|
|
95
|
+
se: [number, number];
|
|
96
|
+
} | undefined;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* KeplerContext provides access to kepler.gl state and dispatch.
|
|
100
|
+
* This is passed into tool factories instead of using Redux directly.
|
|
101
|
+
*
|
|
102
|
+
* The four glue methods (`getValuesFromDataset`, `getDatasetContext`,
|
|
103
|
+
* `loadTableToKepler`, `loadTableIntoDuckDB`, `getConnector`) are the
|
|
104
|
+
* kepler-app-bound seam the map.* commands call. They are implemented by the
|
|
105
|
+
* host's glue (kepler-assistant) so this package stays free of the DuckDB /
|
|
106
|
+
* kepler-app wiring.
|
|
107
|
+
*/
|
|
108
|
+
export type KeplerContext = {
|
|
109
|
+
getVisState: () => VisState;
|
|
110
|
+
getMapBoundary: () => {
|
|
111
|
+
nw: [number, number];
|
|
112
|
+
se: [number, number];
|
|
113
|
+
} | undefined;
|
|
114
|
+
getMapboxToken: () => string | undefined;
|
|
115
|
+
dispatch: KeplerDispatch;
|
|
116
|
+
/** Read a column's values from a kepler dataset (by label or id). */
|
|
117
|
+
getValuesFromDataset: (datasetName: string, variableName: string) => unknown[];
|
|
118
|
+
/** Build the dataset+layer context string for the LLM. */
|
|
119
|
+
getDatasetContext: () => string;
|
|
120
|
+
/** Load a DuckDB table into kepler.gl as a dataset. */
|
|
121
|
+
loadTableToKepler: (tableName: string, options?: {
|
|
122
|
+
autoCreateLayers?: boolean;
|
|
123
|
+
centerMap?: boolean;
|
|
124
|
+
}) => Promise<{
|
|
125
|
+
success: boolean;
|
|
126
|
+
error?: string;
|
|
127
|
+
}>;
|
|
128
|
+
/** Materialize a kepler dataset's columns into a DuckDB table and return the connector. */
|
|
129
|
+
loadTableIntoDuckDB: (datasetName: string, variableNames: string[], dbTableName: string) => Promise<DuckDbConnector>;
|
|
130
|
+
/** The shared DuckDB connector (the store's, when wired). */
|
|
131
|
+
getConnector: () => Promise<DuckDbConnector>;
|
|
132
|
+
};
|