@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,138 @@
1
+ import type { Layer, VectorTileLayer } from '@kepler.gl/layers';
2
+ import type { Datasets } from '@kepler.gl/table';
3
+ import type { Field } from '@kepler.gl/types';
4
+ /** Type for a Redux dispatch function, used by tools that need to dispatch kepler actions */
5
+ export type KeplerDispatch = (action: any) => void;
6
+ /**
7
+ * Deterministically convert a dataset name into a valid DuckDB table name.
8
+ * Replaces non-alphanumeric characters (except underscores) with underscores,
9
+ * collapses consecutive underscores, trims leading/trailing underscores,
10
+ * lowercases the result, and prepends 'tbl_' to avoid reserved-word collisions.
11
+ */
12
+ export declare function datasetNameToTableName(datasetName: string): string;
13
+ /**
14
+ * Recursively convert an Arrow row (which uses proxy objects) into a plain JS
15
+ * object. Handles nested toJSON(), arrays, and bigint values. Extracted from
16
+ * query-tool.ts so the stock @sqlrooms/ai query tool wrapper can share it.
17
+ */
18
+ export declare function convertArrowRowToObject(row: any): unknown;
19
+ /**
20
+ * Convert an Arrow Table to an array of plain JS objects.
21
+ *
22
+ * Decimal columns are resolved to numbers using each column's declared scale.
23
+ * `row.toJSON()` passes Decimal values through as opaque BigNum objects
24
+ * ({0: low, 1: high, ...}), which kepler.gl then stores as `object`-typed
25
+ * fields and downstream commands (e.g. `data.merge-tables`) choke on when they
26
+ * try to re-materialize the dataset into DuckDB. The schema carries the scale,
27
+ * so we resolve the value here.
28
+ */
29
+ export declare function arrowTableToObjects(table: {
30
+ toArray: () => any[];
31
+ schema?: {
32
+ fields: {
33
+ name: string;
34
+ type?: {
35
+ typeId?: number;
36
+ scale?: number;
37
+ };
38
+ }[];
39
+ };
40
+ }): Record<string, unknown>[];
41
+ /**
42
+ * Read a column's values from a kepler dataset (by dataset label + field name).
43
+ * Vectors through the vector-tile layer when the dataset is a vector-tile
44
+ * dataset (whose values live in the layer's tile set, not the kepler table).
45
+ *
46
+ * Moved in from kepler-assistant's `src/glue/utils.ts` so this package is
47
+ * self-contained — the map.* commands that call this seam (via `KeplerContext`)
48
+ * cannot import from kepler-assistant (that would be circular).
49
+ */
50
+ export declare function getValuesFromDataset(datasets: Datasets, layers: Layer[], datasetName: string, variableName: string): unknown[];
51
+ export declare function isVectorTileLayer(layer: Layer): layer is VectorTileLayer;
52
+ export declare function getValuesFromVectorTileLayer(datasetId: string, layers: Layer[], field: Field): unknown[];
53
+ /**
54
+ * Whether a column holds any non-null object value — e.g. the `_geojson` column,
55
+ * which stores whole GeoJSON Feature objects. Such columns must NOT be handed to
56
+ * `tableFromArrays` raw: Arrow infers ONE type per column from the first value,
57
+ * and a dataset mixing Polygon (depth-3 `coordinates`) and MultiPolygon (depth-4)
58
+ * features gets the shallower type, so the MultiPolygon coordinates come back as
59
+ * `null` and the geometry disappears. Serialize them to JSON strings for the
60
+ * DuckDB round-trip and restore with `restoreObjectColumns`.
61
+ */
62
+ export declare function isObjectColumn(values: unknown[]): boolean;
63
+ /**
64
+ * Serialize object values to JSON strings (nulls/primitives pass through
65
+ * unchanged) so `tableFromArrays` never has to infer a nested-struct type.
66
+ */
67
+ export declare function stringifyObjectColumn(values: unknown[]): unknown[];
68
+ /**
69
+ * Restore object-valued columns that `stringifyObjectColumn` serialized back to
70
+ * their object form, in place. Used after a DuckDB query returns those columns
71
+ * as JSON strings (e.g. `_geojson` after `SELECT *`).
72
+ */
73
+ export declare function restoreObjectColumns(rows: Record<string, unknown>[], columnNames: string[]): void;
74
+ /**
75
+ * Build an `updateDataset` payload that appends ONE new column to an existing
76
+ * kepler dataset, keeping every existing column byte-for-byte identical.
77
+ *
78
+ * Existing columns are read straight from the kepler dataset (via
79
+ * `getValuesFromDataset`) and NEVER round-tripped through Arrow/DuckDB. That
80
+ * matters for `_geojson`: `tableFromArrays` infers a single Arrow type for the
81
+ * whole column, and a dataset mixing Polygon and MultiPolygon features gets the
82
+ * shallower type — the MultiPolygon's deeper coordinate nesting comes back as
83
+ * nulls and the geometry disappears. Only the NEW column's values come from the
84
+ * computation (DuckDB expression / copy, or geoda write-back).
85
+ *
86
+ * @param datasets kepler datasets (visState.datasets)
87
+ * @param layers kepler layers (visState.layers) — needed for vector-tile datasets
88
+ * @param datasetName the dataset label
89
+ * @param newColumnName name of the column being appended
90
+ * @param newColumnArrow single-column arrow table holding the new column's values
91
+ * @returns an `updateDataset` `data` payload: `{rows, fields}`
92
+ */
93
+ export declare function buildAddColumnPayload(datasets: Datasets, layers: Layer[], datasetName: string, newColumnName: string, newColumnArrow: any): {
94
+ rows: unknown[][];
95
+ fields: any[];
96
+ };
97
+ /**
98
+ * Default number of first rows to format and return to the LLM as a preview.
99
+ * Mirrors spatial-agent's NUMBER_OF_ROWS_RETURN_TO_LLM.
100
+ */
101
+ export declare const NUMBER_OF_ROWS_RETURN_TO_LLM = 5;
102
+ /**
103
+ * Default total character budget for the LLM-facing preview. Capped at ~1000
104
+ * chars so the preview stays small in context, matching spatial-agent's
105
+ * formatResultsForLLM default.
106
+ */
107
+ export declare const LLM_PREVIEW_MAX_TOTAL_LENGTH = 1000;
108
+ export declare const LLM_PREVIEW_MAX_VALUE_LENGTH = 80;
109
+ /**
110
+ * Format a query result table as a pipe-delimited string suitable for LLM
111
+ * consumption. Truncates individual cell values and total output to stay within
112
+ * a token budget. Shared by the stock @sqlrooms/ai query tool wrapper and the
113
+ * skill executeApi data.query path.
114
+ */
115
+ export declare function tableToLLMResult(table: Record<string, unknown>[], maxTotalLength?: number, maxValueLength?: number): string;
116
+ /**
117
+ * Format the first N rows of an Arrow result as a pipe-delimited string for the
118
+ * LLM, capped at maxTotalLength chars. Convenience wrapper combining
119
+ * arrowTableToObjects + tableToLLMResult: slices the first `numberOfRows`
120
+ * rows, normalizes Decimal columns via arrowTableToObjects (applying each
121
+ * column's declared scale so previews don't leak opaque BigNum word objects),
122
+ * then renders the pipe table.
123
+ */
124
+ export declare function formatResultsForLLM(result: {
125
+ toArray: () => any[];
126
+ schema?: {
127
+ fields: {
128
+ name: string;
129
+ type?: {
130
+ typeId?: number;
131
+ scale?: number;
132
+ };
133
+ }[];
134
+ };
135
+ }, numberOfRows?: number, options?: {
136
+ maxTotalLength?: number;
137
+ maxValueLength?: number;
138
+ }): string;
@@ -0,0 +1,4 @@
1
+ import type { RoomCommand } from './types';
2
+ import type { KeplerContext } from './types';
3
+ export declare const viewModeCommandId: "map.set-view-mode";
4
+ export declare function getViewModeCommand(ctx: KeplerContext): RoomCommand;
@@ -0,0 +1,185 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
2
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
+ // SPDX-License-Identifier: MIT
4
+ // Copyright contributors to the kepler.gl project
5
+
6
+ import { z } from 'zod';
7
+ import { updateDataset } from '@kepler.gl/actions';
8
+ import { buildAddColumnPayload } from './utils';
9
+ import { datasetNameToTableName, tableToLLMResult } from './utils';
10
+ export var addColumnCommandId = 'map.add-column';
11
+ export function getAddColumnCommand(ctx) {
12
+ return {
13
+ id: addColumnCommandId,
14
+ name: 'Add a column to an existing map dataset',
15
+ group: 'Map',
16
+ description: "Add a NEW column to an existing kepler.gl dataset (table), in place. The dataset keeps its name, id, color and layers; existing columns are untouched, so layers, filters and tooltips keep working unchanged.\nThe new column's values come from exactly ONE of two sources:\n- copyFromColumn \u2014 copy the values of an existing column. This is how you \"rename\" a column in place: to rename \"fare\" to \"fare_amount\", add a new column \"fare_amount\" that copies \"fare\" (the original \"fare\" column stays \u2014 this command never removes columns).\n- expression \u2014 an SQL expression computed in DuckDB against the dataset's rows, e.g. a z-score: \"(HR60 - AVG(HR60) OVER()) / STDDEV(HR60) OVER()\" adds HR60_Z holding the standardized value of HR60. The expression may reference existing columns and window functions; it must produce exactly one value per row.\nCHANGING A COLUMN'S TYPE: use expression to add a NEW column that casts the original, e.g. to turn \"NOSOUTH\" (numeric) into a string, add a new column with expression \"NOSOUTH::VARCHAR\" (or \"CAST(NOSOUTH AS VARCHAR)\"). The values become strings; the original column stays. Name the new column clearly (e.g. \"NOSOUTH_str\") or as the user requests.\nIMPORTANT: this command only ADDS columns. It cannot delete or rename-in-place an existing column, and it never changes the type OF an existing column in place \u2014 a type change is achieved by adding a NEW column holding the cast values. If you need to remove columns or rebuild the whole table, use map.create-table (which creates a NEW dataset; the original is untouched).",
17
+ metadata: {
18
+ readOnly: false,
19
+ riskLevel: 'medium',
20
+ idempotent: false
21
+ },
22
+ inputSchema: z.object({
23
+ datasetName: z.string().min(1).describe('The name (label) or id of the dataset to add the column to'),
24
+ newColumnName: z.string().min(1).describe('The name of the new column to add. Must not already exist in the dataset.'),
25
+ copyFromColumn: z.string().min(1).optional().describe('The name of an EXISTING column whose values the new column will copy. Mutually exclusive with `expression` — provide exactly one.'),
26
+ expression: z.string().min(1).optional().describe('An SQL expression computed in DuckDB against the dataset rows; the result becomes the new column. e.g. z-score: "(HR60 - AVG(HR60) OVER()) / STDDEV(HR60) OVER()". Mutually exclusive with `copyFromColumn` — provide exactly one.')
27
+ }).superRefine(function (data, ctx) {
28
+ var provided = [data.copyFromColumn, data.expression].filter(function (v) {
29
+ return v != null;
30
+ }).length;
31
+ if (provided !== 1) {
32
+ ctx.addIssue({
33
+ code: z.ZodIssueCode.custom,
34
+ message: 'Provide exactly one of copyFromColumn or expression.'
35
+ });
36
+ }
37
+ }),
38
+ execute: function () {
39
+ var _execute = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(_execCtx, input) {
40
+ var _ref, datasetName, newColumnName, copyFromColumn, expression, provided, visState, datasets, dataId, fieldNames, dbTableName, db, escapeIdent, appendedSql, arrowResult, _buildAddColumnPayloa, rows, fields, previewRows, valueSource;
41
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
42
+ while (1) switch (_context.prev = _context.next) {
43
+ case 0:
44
+ _ref = input !== null && input !== void 0 ? input : {}, datasetName = _ref.datasetName, newColumnName = _ref.newColumnName, copyFromColumn = _ref.copyFromColumn, expression = _ref.expression;
45
+ _context.prev = 1;
46
+ // Runtime guard: the bridge/webMCP call execute without zod parsing, so
47
+ // the superRefine "exactly one of copyFromColumn/expression" constraint
48
+ // is not enforced. Without it, both-missing would build
49
+ // `(undefined) AS ...` and produce a confusing DuckDB error.
50
+ provided = [copyFromColumn, expression].filter(function (v) {
51
+ return v != null;
52
+ }).length;
53
+ if (!(provided !== 1)) {
54
+ _context.next = 5;
55
+ break;
56
+ }
57
+ throw new Error('Provide exactly one of copyFromColumn or expression.');
58
+ case 5:
59
+ if (!(typeof datasetName !== 'string' || datasetName.length === 0)) {
60
+ _context.next = 7;
61
+ break;
62
+ }
63
+ throw new Error('datasetName must be a non-empty string.');
64
+ case 7:
65
+ if (!(typeof newColumnName !== 'string' || newColumnName.length === 0)) {
66
+ _context.next = 9;
67
+ break;
68
+ }
69
+ throw new Error('newColumnName must be a non-empty string.');
70
+ case 9:
71
+ if (!(copyFromColumn != null && (typeof copyFromColumn !== 'string' || copyFromColumn.length === 0))) {
72
+ _context.next = 11;
73
+ break;
74
+ }
75
+ throw new Error('copyFromColumn must be a non-empty string.');
76
+ case 11:
77
+ if (!(expression != null && (typeof expression !== 'string' || expression.length === 0))) {
78
+ _context.next = 13;
79
+ break;
80
+ }
81
+ throw new Error('expression must be a non-empty string.');
82
+ case 13:
83
+ visState = ctx.getVisState();
84
+ datasets = visState.datasets;
85
+ dataId = Object.keys(datasets).find(function (id) {
86
+ return id === datasetName || datasets[id].label === datasetName;
87
+ });
88
+ if (dataId) {
89
+ _context.next = 18;
90
+ break;
91
+ }
92
+ throw new Error("Dataset \"".concat(datasetName, "\" not found."));
93
+ case 18:
94
+ fieldNames = datasets[dataId].fields.map(function (f) {
95
+ return f.name;
96
+ });
97
+ if (!(copyFromColumn != null && !fieldNames.includes(copyFromColumn))) {
98
+ _context.next = 21;
99
+ break;
100
+ }
101
+ throw new Error("Column \"".concat(copyFromColumn, "\" does not exist in dataset \"").concat(datasetName, "\". ") + "Existing columns: ".concat(fieldNames.join(', '), "."));
102
+ case 21:
103
+ if (!fieldNames.includes(newColumnName)) {
104
+ _context.next = 23;
105
+ break;
106
+ }
107
+ throw new Error("Column \"".concat(newColumnName, "\" already exists in dataset \"").concat(datasetName, "\". Choose a different name."));
108
+ case 23:
109
+ // Derive the DuckDB table name from the resolved dataset id, not the
110
+ // user-provided label: different labels can sanitize to the same table
111
+ // name (e.g. "A-B" vs "A B"), which would clobber another dataset's
112
+ // temp table inside DuckDB and run the SQL against unintended data.
113
+ dbTableName = datasetNameToTableName(dataId); // Pass the user-provided datasetName (label or id) to
114
+ // loadTableIntoDuckDB — the documented KeplerContext contract — not
115
+ // the resolved id.
116
+ _context.next = 26;
117
+ return ctx.loadTableIntoDuckDB(datasetName, fieldNames, dbTableName);
118
+ case 26:
119
+ db = _context.sent;
120
+ // Add-only: compute ONLY the new column in DuckDB. Existing columns are
121
+ // never round-tripped through DuckDB/Arrow — `tableFromArrays` infers a
122
+ // single Arrow type for `_geojson`, and a dataset mixing Polygon and
123
+ // MultiPolygon features gets the shallower type, so the MultiPolygon
124
+ // coordinates come back as nulls and the geometry disappears.
125
+ // `buildAddColumnPayload` rebuilds the payload from the original kepler
126
+ // values instead, appending the new column from this single-column result.
127
+ // Escape double quotes in identifier names before embedding them in
128
+ // quoted SQL identifiers — a `"` in copyFromColumn/newColumnName would
129
+ // otherwise break the query or enable SQL injection into DuckDB. (The
130
+ // `expression` is user-provided SQL by design, so it is not escaped.)
131
+ escapeIdent = function escapeIdent(name) {
132
+ return name.replace(/"/g, '""');
133
+ };
134
+ appendedSql = copyFromColumn != null ? "\"".concat(escapeIdent(copyFromColumn), "\" AS \"").concat(escapeIdent(newColumnName), "\"") : "(".concat(expression, ") AS \"").concat(escapeIdent(newColumnName), "\"");
135
+ _context.next = 31;
136
+ return db.query("SELECT ".concat(appendedSql, " FROM \"").concat(dbTableName, "\""));
137
+ case 31:
138
+ arrowResult = _context.sent;
139
+ _buildAddColumnPayloa = buildAddColumnPayload(datasets, visState.layers, datasetName, newColumnName, arrowResult), rows = _buildAddColumnPayloa.rows, fields = _buildAddColumnPayloa.fields;
140
+ ctx.dispatch(updateDataset(dataId, {
141
+ rows: rows,
142
+ fields: fields
143
+ }));
144
+
145
+ // LLM-facing preview: first 5 rows of the full (original + new) payload.
146
+ previewRows = rows.slice(0, 5).map(function (r) {
147
+ return Object.fromEntries(fields.map(function (f, i) {
148
+ return [f.name, r[i]];
149
+ }));
150
+ });
151
+ valueSource = copyFromColumn != null ? "copied from \"".concat(copyFromColumn, "\"") : "computed";
152
+ return _context.abrupt("return", {
153
+ success: true,
154
+ commandId: addColumnCommandId,
155
+ data: {
156
+ details: "Added column \"".concat(newColumnName, "\" to dataset \"").concat(datasetName, "\" (").concat(valueSource, ", ").concat(rows.length, " rows)."),
157
+ addedColumns: [newColumnName],
158
+ firstFiveRows: tableToLLMResult(previewRows)
159
+ }
160
+ });
161
+ case 39:
162
+ _context.prev = 39;
163
+ _context.t0 = _context["catch"](1);
164
+ return _context.abrupt("return", {
165
+ success: false,
166
+ commandId: addColumnCommandId,
167
+ error: _context.t0 instanceof Error ? _context.t0.message : String(_context.t0),
168
+ data: {
169
+ instruction: 'Please explain the error and give a plan to fix it. Then try again.'
170
+ }
171
+ });
172
+ case 42:
173
+ case "end":
174
+ return _context.stop();
175
+ }
176
+ }, _callee, null, [[1, 39]]);
177
+ }));
178
+ function execute(_x, _x2) {
179
+ return _execute.apply(this, arguments);
180
+ }
181
+ return execute;
182
+ }()
183
+ };
184
+ }
185
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ6IiwidXBkYXRlRGF0YXNldCIsImJ1aWxkQWRkQ29sdW1uUGF5bG9hZCIsImRhdGFzZXROYW1lVG9UYWJsZU5hbWUiLCJ0YWJsZVRvTExNUmVzdWx0IiwiYWRkQ29sdW1uQ29tbWFuZElkIiwiZ2V0QWRkQ29sdW1uQ29tbWFuZCIsImN0eCIsImlkIiwibmFtZSIsImdyb3VwIiwiZGVzY3JpcHRpb24iLCJtZXRhZGF0YSIsInJlYWRPbmx5Iiwicmlza0xldmVsIiwiaWRlbXBvdGVudCIsImlucHV0U2NoZW1hIiwib2JqZWN0IiwiZGF0YXNldE5hbWUiLCJzdHJpbmciLCJtaW4iLCJkZXNjcmliZSIsIm5ld0NvbHVtbk5hbWUiLCJjb3B5RnJvbUNvbHVtbiIsIm9wdGlvbmFsIiwiZXhwcmVzc2lvbiIsInN1cGVyUmVmaW5lIiwiZGF0YSIsInByb3ZpZGVkIiwiZmlsdGVyIiwidiIsImxlbmd0aCIsImFkZElzc3VlIiwiY29kZSIsIlpvZElzc3VlQ29kZSIsImN1c3RvbSIsIm1lc3NhZ2UiLCJleGVjdXRlIiwiX2V4ZWN1dGUiLCJfYXN5bmNUb0dlbmVyYXRvciIsIl9yZWdlbmVyYXRvclJ1bnRpbWUiLCJtYXJrIiwiX2NhbGxlZSIsIl9leGVjQ3R4IiwiaW5wdXQiLCJfcmVmIiwidmlzU3RhdGUiLCJkYXRhc2V0cyIsImRhdGFJZCIsImZpZWxkTmFtZXMiLCJkYlRhYmxlTmFtZSIsImRiIiwiZXNjYXBlSWRlbnQiLCJhcHBlbmRlZFNxbCIsImFycm93UmVzdWx0IiwiX2J1aWxkQWRkQ29sdW1uUGF5bG9hIiwicm93cyIsImZpZWxkcyIsInByZXZpZXdSb3dzIiwidmFsdWVTb3VyY2UiLCJ3cmFwIiwiX2NhbGxlZSQiLCJfY29udGV4dCIsInByZXYiLCJuZXh0IiwiRXJyb3IiLCJnZXRWaXNTdGF0ZSIsIk9iamVjdCIsImtleXMiLCJmaW5kIiwibGFiZWwiLCJjb25jYXQiLCJtYXAiLCJmIiwiaW5jbHVkZXMiLCJqb2luIiwibG9hZFRhYmxlSW50b0R1Y2tEQiIsInNlbnQiLCJyZXBsYWNlIiwicXVlcnkiLCJsYXllcnMiLCJkaXNwYXRjaCIsInNsaWNlIiwiciIsImZyb21FbnRyaWVzIiwiaSIsImFicnVwdCIsInN1Y2Nlc3MiLCJjb21tYW5kSWQiLCJkZXRhaWxzIiwiYWRkZWRDb2x1bW5zIiwiZmlyc3RGaXZlUm93cyIsInQwIiwiZXJyb3IiLCJTdHJpbmciLCJpbnN0cnVjdGlvbiIsInN0b3AiLCJfeCIsIl94MiIsImFwcGx5IiwiYXJndW1lbnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2FkZC1jb2x1bW4tY29tbWFuZC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgdHlwZSB7Um9vbUNvbW1hbmR9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHt6fSBmcm9tICd6b2QnO1xuaW1wb3J0IHt1cGRhdGVEYXRhc2V0fSBmcm9tICdAa2VwbGVyLmdsL2FjdGlvbnMnO1xuaW1wb3J0IHR5cGUge0tlcGxlckNvbnRleHR9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHtidWlsZEFkZENvbHVtblBheWxvYWR9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHtkYXRhc2V0TmFtZVRvVGFibGVOYW1lLCB0YWJsZVRvTExNUmVzdWx0fSBmcm9tICcuL3V0aWxzJztcblxuZXhwb3J0IGNvbnN0IGFkZENvbHVtbkNvbW1hbmRJZCA9ICdtYXAuYWRkLWNvbHVtbicgYXMgY29uc3Q7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRBZGRDb2x1bW5Db21tYW5kKGN0eDogS2VwbGVyQ29udGV4dCk6IFJvb21Db21tYW5kIHtcbiAgcmV0dXJuIHtcbiAgICBpZDogYWRkQ29sdW1uQ29tbWFuZElkLFxuICAgIG5hbWU6ICdBZGQgYSBjb2x1bW4gdG8gYW4gZXhpc3RpbmcgbWFwIGRhdGFzZXQnLFxuICAgIGdyb3VwOiAnTWFwJyxcbiAgICBkZXNjcmlwdGlvbjogYEFkZCBhIE5FVyBjb2x1bW4gdG8gYW4gZXhpc3Rpbmcga2VwbGVyLmdsIGRhdGFzZXQgKHRhYmxlKSwgaW4gcGxhY2UuIFRoZSBkYXRhc2V0IGtlZXBzIGl0cyBuYW1lLCBpZCwgY29sb3IgYW5kIGxheWVyczsgZXhpc3RpbmcgY29sdW1ucyBhcmUgdW50b3VjaGVkLCBzbyBsYXllcnMsIGZpbHRlcnMgYW5kIHRvb2x0aXBzIGtlZXAgd29ya2luZyB1bmNoYW5nZWQuXG5UaGUgbmV3IGNvbHVtbidzIHZhbHVlcyBjb21lIGZyb20gZXhhY3RseSBPTkUgb2YgdHdvIHNvdXJjZXM6XG4tIGNvcHlGcm9tQ29sdW1uIOKAlCBjb3B5IHRoZSB2YWx1ZXMgb2YgYW4gZXhpc3RpbmcgY29sdW1uLiBUaGlzIGlzIGhvdyB5b3UgXCJyZW5hbWVcIiBhIGNvbHVtbiBpbiBwbGFjZTogdG8gcmVuYW1lIFwiZmFyZVwiIHRvIFwiZmFyZV9hbW91bnRcIiwgYWRkIGEgbmV3IGNvbHVtbiBcImZhcmVfYW1vdW50XCIgdGhhdCBjb3BpZXMgXCJmYXJlXCIgKHRoZSBvcmlnaW5hbCBcImZhcmVcIiBjb2x1bW4gc3RheXMg4oCUIHRoaXMgY29tbWFuZCBuZXZlciByZW1vdmVzIGNvbHVtbnMpLlxuLSBleHByZXNzaW9uIOKAlCBhbiBTUUwgZXhwcmVzc2lvbiBjb21wdXRlZCBpbiBEdWNrREIgYWdhaW5zdCB0aGUgZGF0YXNldCdzIHJvd3MsIGUuZy4gYSB6LXNjb3JlOiBcIihIUjYwIC0gQVZHKEhSNjApIE9WRVIoKSkgLyBTVERERVYoSFI2MCkgT1ZFUigpXCIgYWRkcyBIUjYwX1ogaG9sZGluZyB0aGUgc3RhbmRhcmRpemVkIHZhbHVlIG9mIEhSNjAuIFRoZSBleHByZXNzaW9uIG1heSByZWZlcmVuY2UgZXhpc3RpbmcgY29sdW1ucyBhbmQgd2luZG93IGZ1bmN0aW9uczsgaXQgbXVzdCBwcm9kdWNlIGV4YWN0bHkgb25lIHZhbHVlIHBlciByb3cuXG5DSEFOR0lORyBBIENPTFVNTidTIFRZUEU6IHVzZSBleHByZXNzaW9uIHRvIGFkZCBhIE5FVyBjb2x1bW4gdGhhdCBjYXN0cyB0aGUgb3JpZ2luYWwsIGUuZy4gdG8gdHVybiBcIk5PU09VVEhcIiAobnVtZXJpYykgaW50byBhIHN0cmluZywgYWRkIGEgbmV3IGNvbHVtbiB3aXRoIGV4cHJlc3Npb24gXCJOT1NPVVRIOjpWQVJDSEFSXCIgKG9yIFwiQ0FTVChOT1NPVVRIIEFTIFZBUkNIQVIpXCIpLiBUaGUgdmFsdWVzIGJlY29tZSBzdHJpbmdzOyB0aGUgb3JpZ2luYWwgY29sdW1uIHN0YXlzLiBOYW1lIHRoZSBuZXcgY29sdW1uIGNsZWFybHkgKGUuZy4gXCJOT1NPVVRIX3N0clwiKSBvciBhcyB0aGUgdXNlciByZXF1ZXN0cy5cbklNUE9SVEFOVDogdGhpcyBjb21tYW5kIG9ubHkgQUREUyBjb2x1bW5zLiBJdCBjYW5ub3QgZGVsZXRlIG9yIHJlbmFtZS1pbi1wbGFjZSBhbiBleGlzdGluZyBjb2x1bW4sIGFuZCBpdCBuZXZlciBjaGFuZ2VzIHRoZSB0eXBlIE9GIGFuIGV4aXN0aW5nIGNvbHVtbiBpbiBwbGFjZSDigJQgYSB0eXBlIGNoYW5nZSBpcyBhY2hpZXZlZCBieSBhZGRpbmcgYSBORVcgY29sdW1uIGhvbGRpbmcgdGhlIGNhc3QgdmFsdWVzLiBJZiB5b3UgbmVlZCB0byByZW1vdmUgY29sdW1ucyBvciByZWJ1aWxkIHRoZSB3aG9sZSB0YWJsZSwgdXNlIG1hcC5jcmVhdGUtdGFibGUgKHdoaWNoIGNyZWF0ZXMgYSBORVcgZGF0YXNldDsgdGhlIG9yaWdpbmFsIGlzIHVudG91Y2hlZCkuYCxcbiAgICBtZXRhZGF0YToge3JlYWRPbmx5OiBmYWxzZSwgcmlza0xldmVsOiAnbWVkaXVtJywgaWRlbXBvdGVudDogZmFsc2V9LFxuICAgIGlucHV0U2NoZW1hOiB6XG4gICAgICAub2JqZWN0KHtcbiAgICAgICAgZGF0YXNldE5hbWU6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAubWluKDEpXG4gICAgICAgICAgLmRlc2NyaWJlKCdUaGUgbmFtZSAobGFiZWwpIG9yIGlkIG9mIHRoZSBkYXRhc2V0IHRvIGFkZCB0aGUgY29sdW1uIHRvJyksXG4gICAgICAgIG5ld0NvbHVtbk5hbWU6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAubWluKDEpXG4gICAgICAgICAgLmRlc2NyaWJlKCdUaGUgbmFtZSBvZiB0aGUgbmV3IGNvbHVtbiB0byBhZGQuIE11c3Qgbm90IGFscmVhZHkgZXhpc3QgaW4gdGhlIGRhdGFzZXQuJyksXG4gICAgICAgIGNvcHlGcm9tQ29sdW1uOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLm1pbigxKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgJ1RoZSBuYW1lIG9mIGFuIEVYSVNUSU5HIGNvbHVtbiB3aG9zZSB2YWx1ZXMgdGhlIG5ldyBjb2x1bW4gd2lsbCBjb3B5LiBNdXR1YWxseSBleGNsdXNpdmUgd2l0aCBgZXhwcmVzc2lvbmAg4oCUIHByb3ZpZGUgZXhhY3RseSBvbmUuJ1xuICAgICAgICAgICksXG4gICAgICAgIGV4cHJlc3Npb246IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAubWluKDEpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICAnQW4gU1FMIGV4cHJlc3Npb24gY29tcHV0ZWQgaW4gRHVja0RCIGFnYWluc3QgdGhlIGRhdGFzZXQgcm93czsgdGhlIHJlc3VsdCBiZWNvbWVzIHRoZSBuZXcgY29sdW1uLiBlLmcuIHotc2NvcmU6IFwiKEhSNjAgLSBBVkcoSFI2MCkgT1ZFUigpKSAvIFNURERFVihIUjYwKSBPVkVSKClcIi4gTXV0dWFsbHkgZXhjbHVzaXZlIHdpdGggYGNvcHlGcm9tQ29sdW1uYCDigJQgcHJvdmlkZSBleGFjdGx5IG9uZS4nXG4gICAgICAgICAgKVxuICAgICAgfSlcbiAgICAgIC5zdXBlclJlZmluZSgoZGF0YSwgY3R4KSA9PiB7XG4gICAgICAgIGNvbnN0IHByb3ZpZGVkID0gW2RhdGEuY29weUZyb21Db2x1bW4sIGRhdGEuZXhwcmVzc2lvbl0uZmlsdGVyKHYgPT4gdiAhPSBudWxsKS5sZW5ndGg7XG4gICAgICAgIGlmIChwcm92aWRlZCAhPT0gMSkge1xuICAgICAgICAgIGN0eC5hZGRJc3N1ZSh7XG4gICAgICAgICAgICBjb2RlOiB6LlpvZElzc3VlQ29kZS5jdXN0b20sXG4gICAgICAgICAgICBtZXNzYWdlOiAnUHJvdmlkZSBleGFjdGx5IG9uZSBvZiBjb3B5RnJvbUNvbHVtbiBvciBleHByZXNzaW9uLidcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSkgYXMgYW55LFxuICAgIGV4ZWN1dGU6IGFzeW5jIChfZXhlY0N0eCwgaW5wdXQpID0+IHtcbiAgICAgIGNvbnN0IHtkYXRhc2V0TmFtZSwgbmV3Q29sdW1uTmFtZSwgY29weUZyb21Db2x1bW4sIGV4cHJlc3Npb259ID0gKGlucHV0ID8/IHt9KSBhcyB7XG4gICAgICAgIGRhdGFzZXROYW1lOiBzdHJpbmc7XG4gICAgICAgIG5ld0NvbHVtbk5hbWU6IHN0cmluZztcbiAgICAgICAgY29weUZyb21Db2x1bW4/OiBzdHJpbmc7XG4gICAgICAgIGV4cHJlc3Npb24/OiBzdHJpbmc7XG4gICAgICB9O1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gUnVudGltZSBndWFyZDogdGhlIGJyaWRnZS93ZWJNQ1AgY2FsbCBleGVjdXRlIHdpdGhvdXQgem9kIHBhcnNpbmcsIHNvXG4gICAgICAgIC8vIHRoZSBzdXBlclJlZmluZSBcImV4YWN0bHkgb25lIG9mIGNvcHlGcm9tQ29sdW1uL2V4cHJlc3Npb25cIiBjb25zdHJhaW50XG4gICAgICAgIC8vIGlzIG5vdCBlbmZvcmNlZC4gV2l0aG91dCBpdCwgYm90aC1taXNzaW5nIHdvdWxkIGJ1aWxkXG4gICAgICAgIC8vIGAodW5kZWZpbmVkKSBBUyAuLi5gIGFuZCBwcm9kdWNlIGEgY29uZnVzaW5nIER1Y2tEQiBlcnJvci5cbiAgICAgICAgY29uc3QgcHJvdmlkZWQgPSBbY29weUZyb21Db2x1bW4sIGV4cHJlc3Npb25dLmZpbHRlcih2ID0+IHYgIT0gbnVsbCkubGVuZ3RoO1xuICAgICAgICBpZiAocHJvdmlkZWQgIT09IDEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Byb3ZpZGUgZXhhY3RseSBvbmUgb2YgY29weUZyb21Db2x1bW4gb3IgZXhwcmVzc2lvbi4nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGRhdGFzZXROYW1lICE9PSAnc3RyaW5nJyB8fCBkYXRhc2V0TmFtZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RhdGFzZXROYW1lIG11c3QgYmUgYSBub24tZW1wdHkgc3RyaW5nLicpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgbmV3Q29sdW1uTmFtZSAhPT0gJ3N0cmluZycgfHwgbmV3Q29sdW1uTmFtZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25ld0NvbHVtbk5hbWUgbXVzdCBiZSBhIG5vbi1lbXB0eSBzdHJpbmcuJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhlIGJyaWRnZS93ZWJNQ1AgcGF0aCBza2lwcyB6b2QsIHNvIGFuIGVtcHR5IGNvcHlGcm9tQ29sdW1uL2V4cHJlc3Npb25cbiAgICAgICAgLy8gd291bGQgc2xpcCB0aHJvdWdoIGFuZCBidWlsZCBgKCkgQVMgLi4uYCAvIGBcIlwiIEFTIC4uLmAg4oCUIGEgY29uZnVzaW5nXG4gICAgICAgIC8vIER1Y2tEQiBlcnJvciBpbnN0ZWFkIG9mIGFuIGFjdGlvbmFibGUgb25lLiBFbmZvcmNlIG5vbi1lbXB0eSBzdHJpbmdzXG4gICAgICAgIC8vIGZvciB3aGljaGV2ZXIgc291cmNlIGlzIHNlbGVjdGVkLlxuICAgICAgICBpZiAoXG4gICAgICAgICAgY29weUZyb21Db2x1bW4gIT0gbnVsbCAmJlxuICAgICAgICAgICh0eXBlb2YgY29weUZyb21Db2x1bW4gIT09ICdzdHJpbmcnIHx8IGNvcHlGcm9tQ29sdW1uLmxlbmd0aCA9PT0gMClcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3B5RnJvbUNvbHVtbiBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZy4nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhwcmVzc2lvbiAhPSBudWxsICYmICh0eXBlb2YgZXhwcmVzc2lvbiAhPT0gJ3N0cmluZycgfHwgZXhwcmVzc2lvbi5sZW5ndGggPT09IDApKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHByZXNzaW9uIG11c3QgYmUgYSBub24tZW1wdHkgc3RyaW5nLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdmlzU3RhdGUgPSBjdHguZ2V0VmlzU3RhdGUoKTtcbiAgICAgICAgY29uc3QgZGF0YXNldHMgPSB2aXNTdGF0ZS5kYXRhc2V0cztcbiAgICAgICAgY29uc3QgZGF0YUlkID0gT2JqZWN0LmtleXMoZGF0YXNldHMpLmZpbmQoXG4gICAgICAgICAgaWQgPT4gaWQgPT09IGRhdGFzZXROYW1lIHx8IGRhdGFzZXRzW2lkXS5sYWJlbCA9PT0gZGF0YXNldE5hbWVcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFkYXRhSWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERhdGFzZXQgXCIke2RhdGFzZXROYW1lfVwiIG5vdCBmb3VuZC5gKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmaWVsZE5hbWVzID0gZGF0YXNldHNbZGF0YUlkXS5maWVsZHMubWFwKChmOiBhbnkpID0+IGYubmFtZSk7XG4gICAgICAgIGlmIChjb3B5RnJvbUNvbHVtbiAhPSBudWxsICYmICFmaWVsZE5hbWVzLmluY2x1ZGVzKGNvcHlGcm9tQ29sdW1uKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBDb2x1bW4gXCIke2NvcHlGcm9tQ29sdW1ufVwiIGRvZXMgbm90IGV4aXN0IGluIGRhdGFzZXQgXCIke2RhdGFzZXROYW1lfVwiLiBgICtcbiAgICAgICAgICAgICAgYEV4aXN0aW5nIGNvbHVtbnM6ICR7ZmllbGROYW1lcy5qb2luKCcsICcpfS5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZmllbGROYW1lcy5pbmNsdWRlcyhuZXdDb2x1bW5OYW1lKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBDb2x1bW4gXCIke25ld0NvbHVtbk5hbWV9XCIgYWxyZWFkeSBleGlzdHMgaW4gZGF0YXNldCBcIiR7ZGF0YXNldE5hbWV9XCIuIENob29zZSBhIGRpZmZlcmVudCBuYW1lLmBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVyaXZlIHRoZSBEdWNrREIgdGFibGUgbmFtZSBmcm9tIHRoZSByZXNvbHZlZCBkYXRhc2V0IGlkLCBub3QgdGhlXG4gICAgICAgIC8vIHVzZXItcHJvdmlkZWQgbGFiZWw6IGRpZmZlcmVudCBsYWJlbHMgY2FuIHNhbml0aXplIHRvIHRoZSBzYW1lIHRhYmxlXG4gICAgICAgIC8vIG5hbWUgKGUuZy4gXCJBLUJcIiB2cyBcIkEgQlwiKSwgd2hpY2ggd291bGQgY2xvYmJlciBhbm90aGVyIGRhdGFzZXQnc1xuICAgICAgICAvLyB0ZW1wIHRhYmxlIGluc2lkZSBEdWNrREIgYW5kIHJ1biB0aGUgU1FMIGFnYWluc3QgdW5pbnRlbmRlZCBkYXRhLlxuICAgICAgICBjb25zdCBkYlRhYmxlTmFtZSA9IGRhdGFzZXROYW1lVG9UYWJsZU5hbWUoZGF0YUlkKTtcbiAgICAgICAgLy8gUGFzcyB0aGUgdXNlci1wcm92aWRlZCBkYXRhc2V0TmFtZSAobGFiZWwgb3IgaWQpIHRvXG4gICAgICAgIC8vIGxvYWRUYWJsZUludG9EdWNrREIg4oCUIHRoZSBkb2N1bWVudGVkIEtlcGxlckNvbnRleHQgY29udHJhY3Qg4oCUIG5vdFxuICAgICAgICAvLyB0aGUgcmVzb2x2ZWQgaWQuXG4gICAgICAgIGNvbnN0IGRiID0gYXdhaXQgY3R4LmxvYWRUYWJsZUludG9EdWNrREIoZGF0YXNldE5hbWUsIGZpZWxkTmFtZXMsIGRiVGFibGVOYW1lKTtcblxuICAgICAgICAvLyBBZGQtb25seTogY29tcHV0ZSBPTkxZIHRoZSBuZXcgY29sdW1uIGluIER1Y2tEQi4gRXhpc3RpbmcgY29sdW1ucyBhcmVcbiAgICAgICAgLy8gbmV2ZXIgcm91bmQtdHJpcHBlZCB0aHJvdWdoIER1Y2tEQi9BcnJvdyDigJQgYHRhYmxlRnJvbUFycmF5c2AgaW5mZXJzIGFcbiAgICAgICAgLy8gc2luZ2xlIEFycm93IHR5cGUgZm9yIGBfZ2VvanNvbmAsIGFuZCBhIGRhdGFzZXQgbWl4aW5nIFBvbHlnb24gYW5kXG4gICAgICAgIC8vIE11bHRpUG9seWdvbiBmZWF0dXJlcyBnZXRzIHRoZSBzaGFsbG93ZXIgdHlwZSwgc28gdGhlIE11bHRpUG9seWdvblxuICAgICAgICAvLyBjb29yZGluYXRlcyBjb21lIGJhY2sgYXMgbnVsbHMgYW5kIHRoZSBnZW9tZXRyeSBkaXNhcHBlYXJzLlxuICAgICAgICAvLyBgYnVpbGRBZGRDb2x1bW5QYXlsb2FkYCByZWJ1aWxkcyB0aGUgcGF5bG9hZCBmcm9tIHRoZSBvcmlnaW5hbCBrZXBsZXJcbiAgICAgICAgLy8gdmFsdWVzIGluc3RlYWQsIGFwcGVuZGluZyB0aGUgbmV3IGNvbHVtbiBmcm9tIHRoaXMgc2luZ2xlLWNvbHVtbiByZXN1bHQuXG4gICAgICAgIC8vIEVzY2FwZSBkb3VibGUgcXVvdGVzIGluIGlkZW50aWZpZXIgbmFtZXMgYmVmb3JlIGVtYmVkZGluZyB0aGVtIGluXG4gICAgICAgIC8vIHF1b3RlZCBTUUwgaWRlbnRpZmllcnMg4oCUIGEgYFwiYCBpbiBjb3B5RnJvbUNvbHVtbi9uZXdDb2x1bW5OYW1lIHdvdWxkXG4gICAgICAgIC8vIG90aGVyd2lzZSBicmVhayB0aGUgcXVlcnkgb3IgZW5hYmxlIFNRTCBpbmplY3Rpb24gaW50byBEdWNrREIuIChUaGVcbiAgICAgICAgLy8gYGV4cHJlc3Npb25gIGlzIHVzZXItcHJvdmlkZWQgU1FMIGJ5IGRlc2lnbiwgc28gaXQgaXMgbm90IGVzY2FwZWQuKVxuICAgICAgICBjb25zdCBlc2NhcGVJZGVudCA9IChuYW1lOiBzdHJpbmcpID0+IG5hbWUucmVwbGFjZSgvXCIvZywgJ1wiXCInKTtcbiAgICAgICAgY29uc3QgYXBwZW5kZWRTcWwgPVxuICAgICAgICAgIGNvcHlGcm9tQ29sdW1uICE9IG51bGxcbiAgICAgICAgICAgID8gYFwiJHtlc2NhcGVJZGVudChjb3B5RnJvbUNvbHVtbil9XCIgQVMgXCIke2VzY2FwZUlkZW50KG5ld0NvbHVtbk5hbWUpfVwiYFxuICAgICAgICAgICAgOiBgKCR7ZXhwcmVzc2lvbn0pIEFTIFwiJHtlc2NhcGVJZGVudChuZXdDb2x1bW5OYW1lKX1cImA7XG4gICAgICAgIGNvbnN0IGFycm93UmVzdWx0ID0gYXdhaXQgZGIucXVlcnkoYFNFTEVDVCAke2FwcGVuZGVkU3FsfSBGUk9NIFwiJHtkYlRhYmxlTmFtZX1cImApO1xuXG4gICAgICAgIGNvbnN0IHtyb3dzLCBmaWVsZHN9ID0gYnVpbGRBZGRDb2x1bW5QYXlsb2FkKFxuICAgICAgICAgIGRhdGFzZXRzLFxuICAgICAgICAgIHZpc1N0YXRlLmxheWVycyxcbiAgICAgICAgICBkYXRhc2V0TmFtZSxcbiAgICAgICAgICBuZXdDb2x1bW5OYW1lLFxuICAgICAgICAgIGFycm93UmVzdWx0XG4gICAgICAgICk7XG4gICAgICAgIGN0eC5kaXNwYXRjaCh1cGRhdGVEYXRhc2V0KGRhdGFJZCwge3Jvd3MsIGZpZWxkc30gYXMgYW55KSk7XG5cbiAgICAgICAgLy8gTExNLWZhY2luZyBwcmV2aWV3OiBmaXJzdCA1IHJvd3Mgb2YgdGhlIGZ1bGwgKG9yaWdpbmFsICsgbmV3KSBwYXlsb2FkLlxuICAgICAgICBjb25zdCBwcmV2aWV3Um93cyA9IHJvd3NcbiAgICAgICAgICAuc2xpY2UoMCwgNSlcbiAgICAgICAgICAubWFwKHIgPT4gT2JqZWN0LmZyb21FbnRyaWVzKGZpZWxkcy5tYXAoKGYsIGkpID0+IFtmLm5hbWUsIHJbaV1dKSkpO1xuICAgICAgICBjb25zdCB2YWx1ZVNvdXJjZSA9IGNvcHlGcm9tQ29sdW1uICE9IG51bGwgPyBgY29waWVkIGZyb20gXCIke2NvcHlGcm9tQ29sdW1ufVwiYCA6IGBjb21wdXRlZGA7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICBjb21tYW5kSWQ6IGFkZENvbHVtbkNvbW1hbmRJZCxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBkZXRhaWxzOiBgQWRkZWQgY29sdW1uIFwiJHtuZXdDb2x1bW5OYW1lfVwiIHRvIGRhdGFzZXQgXCIke2RhdGFzZXROYW1lfVwiICgke3ZhbHVlU291cmNlfSwgJHtyb3dzLmxlbmd0aH0gcm93cykuYCxcbiAgICAgICAgICAgIGFkZGVkQ29sdW1uczogW25ld0NvbHVtbk5hbWVdLFxuICAgICAgICAgICAgZmlyc3RGaXZlUm93czogdGFibGVUb0xMTVJlc3VsdChwcmV2aWV3Um93cylcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgIGNvbW1hbmRJZDogYWRkQ29sdW1uQ29tbWFuZElkLFxuICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXG4gICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgaW5zdHJ1Y3Rpb246ICdQbGVhc2UgZXhwbGFpbiB0aGUgZXJyb3IgYW5kIGdpdmUgYSBwbGFuIHRvIGZpeCBpdC4gVGhlbiB0cnkgYWdhaW4uJ1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAg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
@@ -0,0 +1,72 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
2
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
+ // SPDX-License-Identifier: MIT
4
+ // Copyright contributors to the kepler.gl project
5
+
6
+ import { z } from 'zod';
7
+ import { DEFAULT_MAP_STYLES } from '@kepler.gl/constants';
8
+ import { mapStyleChange } from '@kepler.gl/actions';
9
+ export var basemapCommandId = 'map.set-basemap';
10
+ export function getBasemapCommand(ctx) {
11
+ return {
12
+ id: basemapCommandId,
13
+ name: 'Set basemap',
14
+ group: 'Map',
15
+ description: 'Change the basemap style of the kepler.gl map.',
16
+ metadata: {
17
+ readOnly: false,
18
+ riskLevel: 'low',
19
+ idempotent: true
20
+ },
21
+ inputSchema: z.object({
22
+ styleType: z["enum"](['no_map', 'dark-matter', 'positron', 'voyager', 'satellite', 'dark', 'light', 'muted', 'muted_night'])
23
+ }),
24
+ execute: function () {
25
+ var _execute = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(_execCtx, input) {
26
+ var _ref, styleType;
27
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
28
+ while (1) switch (_context.prev = _context.next) {
29
+ case 0:
30
+ _ref = input !== null && input !== void 0 ? input : {}, styleType = _ref.styleType;
31
+ _context.prev = 1;
32
+ if (DEFAULT_MAP_STYLES.find(function (style) {
33
+ return style.id === styleType;
34
+ })) {
35
+ _context.next = 4;
36
+ break;
37
+ }
38
+ throw new Error("Invalid basemap style: ".concat(styleType, "."));
39
+ case 4:
40
+ ctx.dispatch(mapStyleChange(styleType));
41
+ return _context.abrupt("return", {
42
+ success: true,
43
+ commandId: basemapCommandId,
44
+ data: {
45
+ details: "Basemap style changed to ".concat(styleType, ".")
46
+ }
47
+ });
48
+ case 8:
49
+ _context.prev = 8;
50
+ _context.t0 = _context["catch"](1);
51
+ return _context.abrupt("return", {
52
+ success: false,
53
+ commandId: basemapCommandId,
54
+ error: _context.t0 instanceof Error ? _context.t0.message : 'Unknown error',
55
+ data: {
56
+ instruction: 'Try to fix the error. If the error persists, ask the user to try with a different basemap style.'
57
+ }
58
+ });
59
+ case 11:
60
+ case "end":
61
+ return _context.stop();
62
+ }
63
+ }, _callee, null, [[1, 8]]);
64
+ }));
65
+ function execute(_x, _x2) {
66
+ return _execute.apply(this, arguments);
67
+ }
68
+ return execute;
69
+ }()
70
+ };
71
+ }
72
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ6IiwiREVGQVVMVF9NQVBfU1RZTEVTIiwibWFwU3R5bGVDaGFuZ2UiLCJiYXNlbWFwQ29tbWFuZElkIiwiZ2V0QmFzZW1hcENvbW1hbmQiLCJjdHgiLCJpZCIsIm5hbWUiLCJncm91cCIsImRlc2NyaXB0aW9uIiwibWV0YWRhdGEiLCJyZWFkT25seSIsInJpc2tMZXZlbCIsImlkZW1wb3RlbnQiLCJpbnB1dFNjaGVtYSIsIm9iamVjdCIsInN0eWxlVHlwZSIsImV4ZWN1dGUiLCJfZXhlY3V0ZSIsIl9hc3luY1RvR2VuZXJhdG9yIiwiX3JlZ2VuZXJhdG9yUnVudGltZSIsIm1hcmsiLCJfY2FsbGVlIiwiX2V4ZWNDdHgiLCJpbnB1dCIsIl9yZWYiLCJ3cmFwIiwiX2NhbGxlZSQiLCJfY29udGV4dCIsInByZXYiLCJuZXh0IiwiZmluZCIsInN0eWxlIiwiRXJyb3IiLCJjb25jYXQiLCJkaXNwYXRjaCIsImFicnVwdCIsInN1Y2Nlc3MiLCJjb21tYW5kSWQiLCJkYXRhIiwiZGV0YWlscyIsInQwIiwiZXJyb3IiLCJtZXNzYWdlIiwiaW5zdHJ1Y3Rpb24iLCJzdG9wIiwiX3giLCJfeDIiLCJhcHBseSIsImFyZ3VtZW50cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9iYXNlbWFwLWNvbW1hbmQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IHR5cGUge1Jvb21Db21tYW5kfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7en0gZnJvbSAnem9kJztcbmltcG9ydCB7REVGQVVMVF9NQVBfU1RZTEVTfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5pbXBvcnQge21hcFN0eWxlQ2hhbmdlfSBmcm9tICdAa2VwbGVyLmdsL2FjdGlvbnMnO1xuaW1wb3J0IHR5cGUge0tlcGxlckNvbnRleHR9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgYmFzZW1hcENvbW1hbmRJZCA9ICdtYXAuc2V0LWJhc2VtYXAnIGFzIGNvbnN0O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QmFzZW1hcENvbW1hbmQoY3R4OiBLZXBsZXJDb250ZXh0KTogUm9vbUNvbW1hbmQge1xuICByZXR1cm4ge1xuICAgIGlkOiBiYXNlbWFwQ29tbWFuZElkLFxuICAgIG5hbWU6ICdTZXQgYmFzZW1hcCcsXG4gICAgZ3JvdXA6ICdNYXAnLFxuICAgIGRlc2NyaXB0aW9uOiAnQ2hhbmdlIHRoZSBiYXNlbWFwIHN0eWxlIG9mIHRoZSBrZXBsZXIuZ2wgbWFwLicsXG4gICAgbWV0YWRhdGE6IHtyZWFkT25seTogZmFsc2UsIHJpc2tMZXZlbDogJ2xvdycsIGlkZW1wb3RlbnQ6IHRydWV9LFxuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBzdHlsZVR5cGU6IHouZW51bShbXG4gICAgICAgICdub19tYXAnLFxuICAgICAgICAnZGFyay1tYXR0ZXInLFxuICAgICAgICAncG9zaXRyb24nLFxuICAgICAgICAndm95YWdlcicsXG4gICAgICAgICdzYXRlbGxpdGUnLFxuICAgICAgICAnZGFyaycsXG4gICAgICAgICdsaWdodCcsXG4gICAgICAgICdtdXRlZCcsXG4gICAgICAgICdtdXRlZF9uaWdodCdcbiAgICAgIF0pXG4gICAgfSkgYXMgYW55LFxuICAgIGV4ZWN1dGU6IGFzeW5jIChfZXhlY0N0eCwgaW5wdXQpID0+IHtcbiAgICAgIGNvbnN0IHtzdHlsZVR5cGV9ID0gKGlucHV0ID8/IHt9KSBhcyB7c3R5bGVUeXBlOiBzdHJpbmd9O1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKCFERUZBVUxUX01BUF9TVFlMRVMuZmluZChzdHlsZSA9PiBzdHlsZS5pZCA9PT0gc3R5bGVUeXBlKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBiYXNlbWFwIHN0eWxlOiAke3N0eWxlVHlwZX0uYCk7XG4gICAgICAgIH1cbiAgICAgICAgY3R4LmRpc3BhdGNoKG1hcFN0eWxlQ2hhbmdlKHN0eWxlVHlwZSkpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgY29tbWFuZElkOiBiYXNlbWFwQ29tbWFuZElkLFxuICAgICAgICAgIGRhdGE6IHtkZXRhaWxzOiBgQmFzZW1hcCBzdHlsZSBjaGFuZ2VkIHRvICR7c3R5bGVUeXBlfS5gfVxuICAgICAgICB9O1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICBjb21tYW5kSWQ6IGJhc2VtYXBDb21tYW5kSWQsXG4gICAgICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogJ1Vua25vd24gZXJyb3InLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGluc3RydWN0aW9uOlxuICAgICAgICAgICAgICAnVHJ5IHRvIGZpeCB0aGUgZXJyb3IuIElmIHRoZSBlcnJvciBwZXJzaXN0cywgYXNrIHRoZSB1c2VyIHRvIHRyeSB3aXRoIGEgZGlmZmVyZW50IGJhc2VtYXAgc3R5bGUuJ1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTs7QUFHQSxTQUFRQSxDQUFDLFFBQU8sS0FBSztBQUNyQixTQUFRQyxrQkFBa0IsUUFBTyxzQkFBc0I7QUFDdkQsU0FBUUMsY0FBYyxRQUFPLG9CQUFvQjtBQUdqRCxPQUFPLElBQU1DLGdCQUFnQixHQUFHLGlCQUEwQjtBQUUxRCxPQUFPLFNBQVNDLGlCQUFpQkEsQ0FBQ0MsR0FBa0IsRUFBZTtFQUNqRSxPQUFPO0lBQ0xDLEVBQUUsRUFBRUgsZ0JBQWdCO0lBQ3BCSSxJQUFJLEVBQUUsYUFBYTtJQUNuQkMsS0FBSyxFQUFFLEtBQUs7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
@@ -0,0 +1,73 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
2
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
+ // SPDX-License-Identifier: MIT
4
+ // Copyright contributors to the kepler.gl project
5
+
6
+ import { z } from 'zod';
7
+ export var mapBoundaryCommandId = 'map.get-boundary';
8
+ export function getMapBoundaryCommand(ctx) {
9
+ return {
10
+ id: mapBoundaryCommandId,
11
+ name: 'Get map boundary',
12
+ group: 'Map',
13
+ description: 'Get the boundary of the map. Northwest and Southeast coordinates in [longitude, latitude] format.',
14
+ metadata: {
15
+ readOnly: true,
16
+ riskLevel: 'low',
17
+ idempotent: true
18
+ },
19
+ inputSchema: z.object({}),
20
+ execute: function () {
21
+ var _execute = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
22
+ var boundary;
23
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
24
+ while (1) switch (_context.prev = _context.next) {
25
+ case 0:
26
+ _context.prev = 0;
27
+ boundary = ctx.getMapBoundary();
28
+ if (boundary) {
29
+ _context.next = 4;
30
+ break;
31
+ }
32
+ return _context.abrupt("return", {
33
+ success: false,
34
+ commandId: mapBoundaryCommandId,
35
+ error: 'Map boundary not available.',
36
+ data: {
37
+ instruction: 'Please ensure the kepler.gl map is properly loaded and try again.'
38
+ }
39
+ });
40
+ case 4:
41
+ return _context.abrupt("return", {
42
+ success: true,
43
+ commandId: mapBoundaryCommandId,
44
+ data: {
45
+ details: "Map boundary retrieved. NW: [".concat(boundary.nw[0], ", ").concat(boundary.nw[1], "], SE: [").concat(boundary.se[0], ", ").concat(boundary.se[1], "]"),
46
+ boundary: boundary
47
+ }
48
+ });
49
+ case 7:
50
+ _context.prev = 7;
51
+ _context.t0 = _context["catch"](0);
52
+ return _context.abrupt("return", {
53
+ success: false,
54
+ commandId: mapBoundaryCommandId,
55
+ error: _context.t0 instanceof Error ? _context.t0.message : 'Unknown error',
56
+ data: {
57
+ instruction: 'Please ensure the kepler.gl map is properly loaded and try again.'
58
+ }
59
+ });
60
+ case 10:
61
+ case "end":
62
+ return _context.stop();
63
+ }
64
+ }, _callee, null, [[0, 7]]);
65
+ }));
66
+ function execute() {
67
+ return _execute.apply(this, arguments);
68
+ }
69
+ return execute;
70
+ }()
71
+ };
72
+ }
73
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ6IiwibWFwQm91bmRhcnlDb21tYW5kSWQiLCJnZXRNYXBCb3VuZGFyeUNvbW1hbmQiLCJjdHgiLCJpZCIsIm5hbWUiLCJncm91cCIsImRlc2NyaXB0aW9uIiwibWV0YWRhdGEiLCJyZWFkT25seSIsInJpc2tMZXZlbCIsImlkZW1wb3RlbnQiLCJpbnB1dFNjaGVtYSIsIm9iamVjdCIsImV4ZWN1dGUiLCJfZXhlY3V0ZSIsIl9hc3luY1RvR2VuZXJhdG9yIiwiX3JlZ2VuZXJhdG9yUnVudGltZSIsIm1hcmsiLCJfY2FsbGVlIiwiYm91bmRhcnkiLCJ3cmFwIiwiX2NhbGxlZSQiLCJfY29udGV4dCIsInByZXYiLCJuZXh0IiwiZ2V0TWFwQm91bmRhcnkiLCJhYnJ1cHQiLCJzdWNjZXNzIiwiY29tbWFuZElkIiwiZXJyb3IiLCJkYXRhIiwiaW5zdHJ1Y3Rpb24iLCJkZXRhaWxzIiwiY29uY2F0IiwibnciLCJzZSIsInQwIiwiRXJyb3IiLCJtZXNzYWdlIiwic3RvcCIsImFwcGx5IiwiYXJndW1lbnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2JvdW5kYXJ5LWNvbW1hbmQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IHR5cGUge1Jvb21Db21tYW5kfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7en0gZnJvbSAnem9kJztcbmltcG9ydCB0eXBlIHtLZXBsZXJDb250ZXh0fSBmcm9tICcuL3R5cGVzJztcblxuZXhwb3J0IGNvbnN0IG1hcEJvdW5kYXJ5Q29tbWFuZElkID0gJ21hcC5nZXQtYm91bmRhcnknIGFzIGNvbnN0O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TWFwQm91bmRhcnlDb21tYW5kKGN0eDogS2VwbGVyQ29udGV4dCk6IFJvb21Db21tYW5kIHtcbiAgcmV0dXJuIHtcbiAgICBpZDogbWFwQm91bmRhcnlDb21tYW5kSWQsXG4gICAgbmFtZTogJ0dldCBtYXAgYm91bmRhcnknLFxuICAgIGdyb3VwOiAnTWFwJyxcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgICdHZXQgdGhlIGJvdW5kYXJ5IG9mIHRoZSBtYXAuIE5vcnRod2VzdCBhbmQgU291dGhlYXN0IGNvb3JkaW5hdGVzIGluIFtsb25naXR1ZGUsIGxhdGl0dWRlXSBmb3JtYXQuJyxcbiAgICBtZXRhZGF0YToge3JlYWRPbmx5OiB0cnVlLCByaXNrTGV2ZWw6ICdsb3cnLCBpZGVtcG90ZW50OiB0cnVlfSxcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe30pIGFzIGFueSxcbiAgICBleGVjdXRlOiBhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBib3VuZGFyeSA9IGN0eC5nZXRNYXBCb3VuZGFyeSgpO1xuICAgICAgICBpZiAoIWJvdW5kYXJ5KSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgY29tbWFuZElkOiBtYXBCb3VuZGFyeUNvbW1hbmRJZCxcbiAgICAgICAgICAgIGVycm9yOiAnTWFwIGJvdW5kYXJ5IG5vdCBhdmFpbGFibGUuJyxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgaW5zdHJ1Y3Rpb246ICdQbGVhc2UgZW5zdXJlIHRoZSBrZXBsZXIuZ2wgbWFwIGlzIHByb3Blcmx5IGxvYWRlZCBhbmQgdHJ5IGFnYWluLidcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICBjb21tYW5kSWQ6IG1hcEJvdW5kYXJ5Q29tbWFuZElkLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGRldGFpbHM6IGBNYXAgYm91bmRhcnkgcmV0cmlldmVkLiBOVzogWyR7Ym91bmRhcnkubndbMF19LCAke2JvdW5kYXJ5Lm53WzFdfV0sIFNFOiBbJHtib3VuZGFyeS5zZVswXX0sICR7Ym91bmRhcnkuc2VbMV19XWAsXG4gICAgICAgICAgICBib3VuZGFyeVxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgY29tbWFuZElkOiBtYXBCb3VuZGFyeUNvbW1hbmRJZCxcbiAgICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiAnVW5rbm93biBlcnJvcicsXG4gICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgaW5zdHJ1Y3Rpb246ICdQbGVhc2UgZW5zdXJlIHRoZSBrZXBsZXIuZ2wgbWFwIGlzIHByb3Blcmx5IGxvYWRlZCBhbmQgdHJ5IGFnYWluLidcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0E7O0FBR0EsU0FBUUEsQ0FBQyxRQUFPLEtBQUs7QUFHckIsT0FBTyxJQUFNQyxvQkFBb0IsR0FBRyxrQkFBMkI7QUFFL0QsT0FBTyxTQUFTQyxxQkFBcUJBLENBQUNDLEdBQWtCLEVBQWU7RUFDckUsT0FBTztJQUNMQyxFQUFFLEVBQUVILG9CQUFvQjtJQUN4QkksSUFBSSxFQUFFLGtCQUFrQjtJQUN4QkMsS0FBSyxFQUFFLEtBQUs7SUFDWkMsV0FBVyxFQUNULG1HQUFtRztJQUNyR0MsUUFBUSxFQUFFO01BQUNDLFFBQVEsRUFBRSxJQUFJO01BQUVDLFNBQVMsRUFBRSxLQUFLO01BQUVDLFVBQVUsRUFBRTtJQUFJLENBQUM7SUFDOURDLFdBQVcsRUFBRVosQ0FBQyxDQUFDYSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQVE7SUFDaENDLE9BQU87TUFBQSxJQUFBQyxRQUFBLEdBQUFDLGlCQUFBLGNBQUFDLG1CQUFBLENBQUFDLElBQUEsQ0FBRSxTQUFBQyxRQUFBO1FBQUEsSUFBQUMsUUFBQTtRQUFBLE9BQUFILG1CQUFBLENBQUFJLElBQUEsVUFBQUMsU0FBQUMsUUFBQTtVQUFBLGtCQUFBQSxRQUFBLENBQUFDLElBQUEsR0FBQUQsUUFBQSxDQUFBRSxJQUFBO1lBQUE7Y0FBQUYsUUFBQSxDQUFBQyxJQUFBO2NBRUNKLFFBQVEsR0FBR2pCLEdBQUcsQ0FBQ3VCLGNBQWMsQ0FBQyxDQUFDO2NBQUEsSUFDaENOLFFBQVE7Z0JBQUFHLFFBQUEsQ0FBQUUsSUFBQTtnQkFBQTtjQUFBO2NBQUEsT0FBQUYsUUFBQSxDQUFBSSxNQUFBLFdBQ0o7Z0JBQ0xDLE9BQU8sRUFBRSxLQUFLO2dCQUNkQyxTQUFTLEVBQUU1QixvQkFBb0I7Z0JBQy9CNkIsS0FBSyxFQUFFLDZCQUE2QjtnQkFDcENDLElBQUksRUFBRTtrQkFDSkMsV0FBVyxFQUFFO2dCQUNmO2NBQ0YsQ0FBQztZQUFBO2NBQUEsT0FBQVQsUUFBQSxDQUFBSSxNQUFBLFdBRUk7Z0JBQ0xDLE9BQU8sRUFBRSxJQUFJO2dCQUNiQyxTQUFTLEVBQUU1QixvQkFBb0I7Z0JBQy9COEIsSUFBSSxFQUFFO2tCQUNKRSxPQUFPLGtDQUFBQyxNQUFBLENBQWtDZCxRQUFRLENBQUNlLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBQUQsTUFBQSxDQUFLZCxRQUFRLENBQUNlLEVBQUUsQ0FBQyxDQUFDLENBQUMsY0FBQUQsTUFBQSxDQUFXZCxRQUFRLENBQUNnQixFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQUFGLE1BQUEsQ0FBS2QsUUFBUSxDQUFDZ0IsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFHO2tCQUN6SGhCLFFBQVEsRUFBUkE7Z0JBQ0Y7Y0FDRixDQUFDO1lBQUE7Y0FBQUcsUUFBQSxDQUFBQyxJQUFBO2NBQUFELFFBQUEsQ0FBQWMsRUFBQSxHQUFBZCxRQUFBO2NBQUEsT0FBQUEsUUFBQSxDQUFBSSxNQUFBLFdBRU07Z0JBQ0xDLE9BQU8sRUFBRSxLQUFLO2dCQUNkQyxTQUFTLEVBQUU1QixvQkFBb0I7Z0JBQy9CNkIsS0FBSyxFQUFFUCxRQUFBLENBQUFjLEVBQUEsWUFBaUJDLEtBQUssR0FBR2YsUUFBQSxDQUFBYyxFQUFBLENBQU1FLE9BQU8sR0FBRyxlQUFlO2dCQUMvRFIsSUFBSSxFQUFFO2tCQUNKQyxXQUFXLEVBQUU7Z0JBQ2Y7Y0FDRixDQUFDO1lBQUE7WUFBQTtjQUFBLE9BQUFULFFBQUEsQ0FBQWlCLElBQUE7VUFBQTtRQUFBLEdBQUFyQixPQUFBO01BQUEsQ0FFSjtNQUFBLFNBL0JETCxPQUFPQSxDQUFBO1FBQUEsT0FBQUMsUUFBQSxDQUFBMEIsS0FBQSxPQUFBQyxTQUFBO01BQUE7TUFBQSxPQUFQNUIsT0FBTztJQUFBO0VBZ0NULENBQUM7QUFDSCIsImlnbm9yZUxpc3QiOltdfQ==