@trops/dash-core 0.1.288 → 0.1.289
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/electron/index.js +1000 -76
- package/dist/electron/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -67574,7 +67574,7 @@ const registeredPrompts = [];
|
|
|
67574
67574
|
* Register a tool to be exposed via the MCP server.
|
|
67575
67575
|
* Call this before starting the server (or restart after registering).
|
|
67576
67576
|
*/
|
|
67577
|
-
function registerTool$
|
|
67577
|
+
function registerTool$6(toolDef) {
|
|
67578
67578
|
registeredTools.push(toolDef);
|
|
67579
67579
|
}
|
|
67580
67580
|
|
|
@@ -67937,7 +67937,7 @@ const mcpDashServerController$4 = {
|
|
|
67937
67937
|
},
|
|
67938
67938
|
|
|
67939
67939
|
// Expose registration functions for other controllers
|
|
67940
|
-
registerTool: registerTool$
|
|
67940
|
+
registerTool: registerTool$6,
|
|
67941
67941
|
registerResource: registerResource$1,
|
|
67942
67942
|
registerPrompt: registerPrompt$1,
|
|
67943
67943
|
getServerContext,
|
|
@@ -70553,7 +70553,7 @@ const dashboardTools$1 = [
|
|
|
70553
70553
|
{
|
|
70554
70554
|
name: "create_dashboard",
|
|
70555
70555
|
description:
|
|
70556
|
-
"Create a new
|
|
70556
|
+
"Create a new dashboard with the given name. Optionally provide a layout to create a grid dashboard. Returns the dashboard ID. After creating, use search_widgets or list_widgets to find widgets, then add_widget to populate the dashboard.",
|
|
70557
70557
|
inputSchema: {
|
|
70558
70558
|
type: "object",
|
|
70559
70559
|
properties: {
|
|
@@ -70561,6 +70561,32 @@ const dashboardTools$1 = [
|
|
|
70561
70561
|
type: "string",
|
|
70562
70562
|
description: "Display name for the new dashboard",
|
|
70563
70563
|
},
|
|
70564
|
+
layout: {
|
|
70565
|
+
type: "object",
|
|
70566
|
+
description:
|
|
70567
|
+
"Optional grid layout configuration. When provided, creates a grid dashboard instead of a simple container.",
|
|
70568
|
+
properties: {
|
|
70569
|
+
rows: {
|
|
70570
|
+
type: "number",
|
|
70571
|
+
description: "Number of rows (1-10)",
|
|
70572
|
+
},
|
|
70573
|
+
cols: {
|
|
70574
|
+
type: "number",
|
|
70575
|
+
description: "Number of columns (1-10)",
|
|
70576
|
+
},
|
|
70577
|
+
gap: {
|
|
70578
|
+
type: "string",
|
|
70579
|
+
description:
|
|
70580
|
+
"Tailwind gap class (e.g. 'gap-2', 'gap-4'). Defaults to 'gap-2'.",
|
|
70581
|
+
},
|
|
70582
|
+
colModes: {
|
|
70583
|
+
type: "object",
|
|
70584
|
+
description:
|
|
70585
|
+
"Per-row column sizing. Keys are row numbers (as strings), values are mode strings: 'equal', '1/4', '1/3', '1/2', '2/3'.",
|
|
70586
|
+
},
|
|
70587
|
+
},
|
|
70588
|
+
required: ["rows", "cols"],
|
|
70589
|
+
},
|
|
70564
70590
|
},
|
|
70565
70591
|
required: ["name"],
|
|
70566
70592
|
},
|
|
@@ -70596,7 +70622,7 @@ const widgetTools$1 = [
|
|
|
70596
70622
|
{
|
|
70597
70623
|
name: "add_widget",
|
|
70598
70624
|
description:
|
|
70599
|
-
"Add a widget to a dashboard by component name. Call list_widgets or search_widgets first to discover available widget names. Can be called multiple times to add multiple widgets. Returns the widget instance ID for use with configure_widget.",
|
|
70625
|
+
"Add a widget to a dashboard by component name. Call list_widgets or search_widgets first to discover available widget names. Can be called multiple times to add multiple widgets. Returns the widget instance ID for use with configure_widget. If the dashboard has a grid layout, you can specify row/col for explicit placement, or omit them to auto-place in the next empty cell.",
|
|
70600
70626
|
inputSchema: {
|
|
70601
70627
|
type: "object",
|
|
70602
70628
|
properties: {
|
|
@@ -70610,6 +70636,16 @@ const widgetTools$1 = [
|
|
|
70610
70636
|
description:
|
|
70611
70637
|
"Component name of the widget to add (e.g. 'Clock', 'WeatherWidget')",
|
|
70612
70638
|
},
|
|
70639
|
+
row: {
|
|
70640
|
+
type: "number",
|
|
70641
|
+
description:
|
|
70642
|
+
"Grid row to place the widget in (1-indexed). Must be used together with col. Requires a grid layout on the dashboard.",
|
|
70643
|
+
},
|
|
70644
|
+
col: {
|
|
70645
|
+
type: "number",
|
|
70646
|
+
description:
|
|
70647
|
+
"Grid column to place the widget in (1-indexed). Must be used together with row.",
|
|
70648
|
+
},
|
|
70613
70649
|
},
|
|
70614
70650
|
required: ["widgetName"],
|
|
70615
70651
|
},
|
|
@@ -70860,12 +70896,108 @@ const providerTools$1 = [
|
|
|
70860
70896
|
},
|
|
70861
70897
|
];
|
|
70862
70898
|
|
|
70899
|
+
const layoutTools$1 = [
|
|
70900
|
+
{
|
|
70901
|
+
name: "set_layout",
|
|
70902
|
+
description:
|
|
70903
|
+
"Set or replace the grid layout on a dashboard. Creates a LayoutGridContainer with the specified dimensions. Existing widgets in cells that fit the new grid are preserved; widgets outside the new bounds are orphaned (kept but unassigned). Use this to add a grid to an existing dashboard or to resize the grid.",
|
|
70904
|
+
inputSchema: {
|
|
70905
|
+
type: "object",
|
|
70906
|
+
properties: {
|
|
70907
|
+
dashboardId: {
|
|
70908
|
+
type: "string",
|
|
70909
|
+
description: "Dashboard ID. Omit to use the active dashboard.",
|
|
70910
|
+
},
|
|
70911
|
+
rows: {
|
|
70912
|
+
type: "number",
|
|
70913
|
+
description: "Number of rows (1-10)",
|
|
70914
|
+
},
|
|
70915
|
+
cols: {
|
|
70916
|
+
type: "number",
|
|
70917
|
+
description: "Number of columns (1-10)",
|
|
70918
|
+
},
|
|
70919
|
+
gap: {
|
|
70920
|
+
type: "string",
|
|
70921
|
+
description:
|
|
70922
|
+
"Tailwind gap class (e.g. 'gap-2', 'gap-4'). Defaults to 'gap-2'.",
|
|
70923
|
+
},
|
|
70924
|
+
colModes: {
|
|
70925
|
+
type: "object",
|
|
70926
|
+
description:
|
|
70927
|
+
"Per-row column sizing. Keys are row numbers (as strings), values are mode strings: 'equal', '1/4', '1/3', '1/2', '2/3'.",
|
|
70928
|
+
},
|
|
70929
|
+
},
|
|
70930
|
+
required: ["rows", "cols"],
|
|
70931
|
+
},
|
|
70932
|
+
},
|
|
70933
|
+
{
|
|
70934
|
+
name: "update_layout",
|
|
70935
|
+
description:
|
|
70936
|
+
"Partially update the grid layout. Only specified properties change — omitted properties keep their current values. colModes is merged (not replaced). Widgets in removed rows/columns are orphaned. Dashboard must already have a grid layout.",
|
|
70937
|
+
inputSchema: {
|
|
70938
|
+
type: "object",
|
|
70939
|
+
properties: {
|
|
70940
|
+
dashboardId: {
|
|
70941
|
+
type: "string",
|
|
70942
|
+
description: "Dashboard ID. Omit to use the active dashboard.",
|
|
70943
|
+
},
|
|
70944
|
+
rows: {
|
|
70945
|
+
type: "number",
|
|
70946
|
+
description: "New number of rows (1-10). Omit to keep current.",
|
|
70947
|
+
},
|
|
70948
|
+
cols: {
|
|
70949
|
+
type: "number",
|
|
70950
|
+
description: "New number of columns (1-10). Omit to keep current.",
|
|
70951
|
+
},
|
|
70952
|
+
gap: {
|
|
70953
|
+
type: "string",
|
|
70954
|
+
description: "Tailwind gap class. Omit to keep current.",
|
|
70955
|
+
},
|
|
70956
|
+
colModes: {
|
|
70957
|
+
type: "object",
|
|
70958
|
+
description:
|
|
70959
|
+
"Column sizing modes to merge. Set a key to null to reset that row to default.",
|
|
70960
|
+
},
|
|
70961
|
+
},
|
|
70962
|
+
required: [],
|
|
70963
|
+
},
|
|
70964
|
+
},
|
|
70965
|
+
{
|
|
70966
|
+
name: "move_widget",
|
|
70967
|
+
description:
|
|
70968
|
+
"Move a widget to a different grid cell. If the target cell is occupied, the two widgets are swapped. The widget must already be placed in a grid cell. Use get_dashboard to find widget IDs and current positions.",
|
|
70969
|
+
inputSchema: {
|
|
70970
|
+
type: "object",
|
|
70971
|
+
properties: {
|
|
70972
|
+
dashboardId: {
|
|
70973
|
+
type: "string",
|
|
70974
|
+
description: "Dashboard ID. Omit to use the active dashboard.",
|
|
70975
|
+
},
|
|
70976
|
+
widgetId: {
|
|
70977
|
+
type: "string",
|
|
70978
|
+
description: "ID of the widget to move",
|
|
70979
|
+
},
|
|
70980
|
+
row: {
|
|
70981
|
+
type: "number",
|
|
70982
|
+
description: "Target row (1-indexed)",
|
|
70983
|
+
},
|
|
70984
|
+
col: {
|
|
70985
|
+
type: "number",
|
|
70986
|
+
description: "Target column (1-indexed)",
|
|
70987
|
+
},
|
|
70988
|
+
},
|
|
70989
|
+
required: ["widgetId", "row", "col"],
|
|
70990
|
+
},
|
|
70991
|
+
},
|
|
70992
|
+
];
|
|
70993
|
+
|
|
70863
70994
|
var toolDefinitions = {
|
|
70864
70995
|
dashboardTools: dashboardTools$1,
|
|
70865
70996
|
widgetTools: widgetTools$1,
|
|
70866
70997
|
themeTools: themeTools$1,
|
|
70867
70998
|
providerTools: providerTools$1,
|
|
70868
70999
|
guideTools: guideTools$1,
|
|
71000
|
+
layoutTools: layoutTools$1,
|
|
70869
71001
|
};
|
|
70870
71002
|
|
|
70871
71003
|
/**
|
|
@@ -71021,7 +71153,7 @@ async function handleGetDashboard$1({ dashboardId }) {
|
|
|
71021
71153
|
/**
|
|
71022
71154
|
* create_dashboard — Creates a new workspace with the given name.
|
|
71023
71155
|
*/
|
|
71024
|
-
async function handleCreateDashboard$1({ name }) {
|
|
71156
|
+
async function handleCreateDashboard$1({ name, layout }) {
|
|
71025
71157
|
if (!name || typeof name !== "string" || !name.trim()) {
|
|
71026
71158
|
return {
|
|
71027
71159
|
content: [
|
|
@@ -71036,8 +71168,86 @@ async function handleCreateDashboard$1({ name }) {
|
|
|
71036
71168
|
};
|
|
71037
71169
|
}
|
|
71038
71170
|
|
|
71171
|
+
// Validate optional layout parameter
|
|
71172
|
+
if (layout !== undefined && layout !== null) {
|
|
71173
|
+
if (typeof layout !== "object" || Array.isArray(layout)) {
|
|
71174
|
+
return {
|
|
71175
|
+
content: [
|
|
71176
|
+
{
|
|
71177
|
+
type: "text",
|
|
71178
|
+
text: JSON.stringify({
|
|
71179
|
+
error: "layout must be an object with rows and cols",
|
|
71180
|
+
}),
|
|
71181
|
+
},
|
|
71182
|
+
],
|
|
71183
|
+
isError: true,
|
|
71184
|
+
};
|
|
71185
|
+
}
|
|
71186
|
+
const { rows, cols } = layout;
|
|
71187
|
+
if (
|
|
71188
|
+
rows === undefined ||
|
|
71189
|
+
cols === undefined ||
|
|
71190
|
+
typeof rows !== "number" ||
|
|
71191
|
+
typeof cols !== "number"
|
|
71192
|
+
) {
|
|
71193
|
+
return {
|
|
71194
|
+
content: [
|
|
71195
|
+
{
|
|
71196
|
+
type: "text",
|
|
71197
|
+
text: JSON.stringify({
|
|
71198
|
+
error: "layout.rows and layout.cols are required numbers",
|
|
71199
|
+
}),
|
|
71200
|
+
},
|
|
71201
|
+
],
|
|
71202
|
+
isError: true,
|
|
71203
|
+
};
|
|
71204
|
+
}
|
|
71205
|
+
if (rows < 1 || rows > 10 || cols < 1 || cols > 10) {
|
|
71206
|
+
return {
|
|
71207
|
+
content: [
|
|
71208
|
+
{
|
|
71209
|
+
type: "text",
|
|
71210
|
+
text: JSON.stringify({
|
|
71211
|
+
error: "rows and cols must be between 1 and 10",
|
|
71212
|
+
}),
|
|
71213
|
+
},
|
|
71214
|
+
],
|
|
71215
|
+
isError: true,
|
|
71216
|
+
};
|
|
71217
|
+
}
|
|
71218
|
+
}
|
|
71219
|
+
|
|
71039
71220
|
const { win, appId } = requireContext$1();
|
|
71040
71221
|
|
|
71222
|
+
// Build root layout node — grid or plain container
|
|
71223
|
+
const rootNode =
|
|
71224
|
+
layout && layout.rows && layout.cols
|
|
71225
|
+
? {
|
|
71226
|
+
id: 1,
|
|
71227
|
+
order: 1,
|
|
71228
|
+
component: "LayoutGridContainer",
|
|
71229
|
+
type: "grid",
|
|
71230
|
+
parent: 0,
|
|
71231
|
+
hasChildren: 1,
|
|
71232
|
+
scrollable: false,
|
|
71233
|
+
width: "w-full",
|
|
71234
|
+
height: "h-full",
|
|
71235
|
+
workspace: "layout",
|
|
71236
|
+
grid: buildEmptyGrid(
|
|
71237
|
+
layout.rows,
|
|
71238
|
+
layout.cols,
|
|
71239
|
+
layout.gap,
|
|
71240
|
+
layout.colModes,
|
|
71241
|
+
),
|
|
71242
|
+
}
|
|
71243
|
+
: {
|
|
71244
|
+
id: 1,
|
|
71245
|
+
order: 1,
|
|
71246
|
+
component: "Container",
|
|
71247
|
+
parent: 0,
|
|
71248
|
+
items: [],
|
|
71249
|
+
};
|
|
71250
|
+
|
|
71041
71251
|
const newWorkspace = {
|
|
71042
71252
|
id: Date.now(),
|
|
71043
71253
|
name: name.trim(),
|
|
@@ -71045,15 +71255,7 @@ async function handleCreateDashboard$1({ name }) {
|
|
|
71045
71255
|
type: "workspace",
|
|
71046
71256
|
version: 1,
|
|
71047
71257
|
menuId: 1,
|
|
71048
|
-
layout: [
|
|
71049
|
-
{
|
|
71050
|
-
id: 1,
|
|
71051
|
-
order: 1,
|
|
71052
|
-
component: "Container",
|
|
71053
|
-
parentId: 0,
|
|
71054
|
-
items: [],
|
|
71055
|
-
},
|
|
71056
|
-
],
|
|
71258
|
+
layout: [rootNode],
|
|
71057
71259
|
};
|
|
71058
71260
|
|
|
71059
71261
|
const result = workspaceController$2.saveWorkspaceForApplication(
|
|
@@ -71074,15 +71276,16 @@ async function handleCreateDashboard$1({ name }) {
|
|
|
71074
71276
|
};
|
|
71075
71277
|
}
|
|
71076
71278
|
|
|
71279
|
+
const response = { id: String(newWorkspace.id), name: newWorkspace.name };
|
|
71280
|
+
if (layout && layout.rows && layout.cols) {
|
|
71281
|
+
response.layout = { rows: layout.rows, cols: layout.cols };
|
|
71282
|
+
}
|
|
71283
|
+
|
|
71077
71284
|
return {
|
|
71078
71285
|
content: [
|
|
71079
71286
|
{
|
|
71080
71287
|
type: "text",
|
|
71081
|
-
text: JSON.stringify(
|
|
71082
|
-
{ id: String(newWorkspace.id), name: newWorkspace.name },
|
|
71083
|
-
null,
|
|
71084
|
-
2,
|
|
71085
|
-
),
|
|
71288
|
+
text: JSON.stringify(response, null, 2),
|
|
71086
71289
|
},
|
|
71087
71290
|
],
|
|
71088
71291
|
};
|
|
@@ -71273,10 +71476,65 @@ function nextLayoutId(layout) {
|
|
|
71273
71476
|
return maxId + 1;
|
|
71274
71477
|
}
|
|
71275
71478
|
|
|
71479
|
+
/**
|
|
71480
|
+
* Helper: find the LayoutGridContainer node in a layout array.
|
|
71481
|
+
*/
|
|
71482
|
+
function findGridNode(layout) {
|
|
71483
|
+
if (!Array.isArray(layout)) return null;
|
|
71484
|
+
return (
|
|
71485
|
+
layout.find(
|
|
71486
|
+
(item) => item.component === "LayoutGridContainer" && item.grid,
|
|
71487
|
+
) || null
|
|
71488
|
+
);
|
|
71489
|
+
}
|
|
71490
|
+
|
|
71491
|
+
/**
|
|
71492
|
+
* Helper: build an empty grid object with cell slots for all row.col positions.
|
|
71493
|
+
*/
|
|
71494
|
+
function buildEmptyGrid(rows, cols, gap, colModes) {
|
|
71495
|
+
const grid = {
|
|
71496
|
+
rows,
|
|
71497
|
+
cols,
|
|
71498
|
+
gap: gap || "gap-2",
|
|
71499
|
+
};
|
|
71500
|
+
if (colModes && Object.keys(colModes).length > 0) {
|
|
71501
|
+
grid.colModes = colModes;
|
|
71502
|
+
}
|
|
71503
|
+
for (let r = 1; r <= rows; r++) {
|
|
71504
|
+
for (let c = 1; c <= cols; c++) {
|
|
71505
|
+
grid[`${r}.${c}`] = { component: null, hide: false };
|
|
71506
|
+
}
|
|
71507
|
+
}
|
|
71508
|
+
return grid;
|
|
71509
|
+
}
|
|
71510
|
+
|
|
71511
|
+
/**
|
|
71512
|
+
* Helper: find the next empty cell scanning left-to-right, top-to-bottom.
|
|
71513
|
+
*/
|
|
71514
|
+
function findNextEmptyCell(grid) {
|
|
71515
|
+
for (let r = 1; r <= grid.rows; r++) {
|
|
71516
|
+
for (let c = 1; c <= grid.cols; c++) {
|
|
71517
|
+
const key = `${r}.${c}`;
|
|
71518
|
+
const cell = grid[key];
|
|
71519
|
+
if (!cell || (cell.component === null && !cell.hide)) {
|
|
71520
|
+
return { row: r, col: c };
|
|
71521
|
+
}
|
|
71522
|
+
}
|
|
71523
|
+
}
|
|
71524
|
+
return null;
|
|
71525
|
+
}
|
|
71526
|
+
|
|
71527
|
+
/**
|
|
71528
|
+
* Helper: check if a row/col position is within grid bounds.
|
|
71529
|
+
*/
|
|
71530
|
+
function isValidCell(grid, row, col) {
|
|
71531
|
+
return row >= 1 && row <= grid.rows && col >= 1 && col <= grid.cols;
|
|
71532
|
+
}
|
|
71533
|
+
|
|
71276
71534
|
/**
|
|
71277
71535
|
* add_widget — Add a widget to a dashboard by component name.
|
|
71278
71536
|
*/
|
|
71279
|
-
async function handleAddWidget$1({ dashboardId, widgetName }) {
|
|
71537
|
+
async function handleAddWidget$1({ dashboardId, widgetName, row, col }) {
|
|
71280
71538
|
if (!widgetName || typeof widgetName !== "string" || !widgetName.trim()) {
|
|
71281
71539
|
return {
|
|
71282
71540
|
content: [
|
|
@@ -71291,6 +71549,25 @@ async function handleAddWidget$1({ dashboardId, widgetName }) {
|
|
|
71291
71549
|
};
|
|
71292
71550
|
}
|
|
71293
71551
|
|
|
71552
|
+
// Validate row/col pairing
|
|
71553
|
+
if (
|
|
71554
|
+
(row !== undefined && col === undefined) ||
|
|
71555
|
+
(row === undefined && col !== undefined)
|
|
71556
|
+
) {
|
|
71557
|
+
return {
|
|
71558
|
+
content: [
|
|
71559
|
+
{
|
|
71560
|
+
type: "text",
|
|
71561
|
+
text: JSON.stringify({
|
|
71562
|
+
error:
|
|
71563
|
+
"Both row and col must be provided together, or both omitted",
|
|
71564
|
+
}),
|
|
71565
|
+
},
|
|
71566
|
+
],
|
|
71567
|
+
isError: true,
|
|
71568
|
+
};
|
|
71569
|
+
}
|
|
71570
|
+
|
|
71294
71571
|
const { win, appId } = requireContext$1();
|
|
71295
71572
|
const result = workspaceController$2.listWorkspacesForApplication(win, appId);
|
|
71296
71573
|
if (result.error) {
|
|
@@ -71315,7 +71592,88 @@ async function handleAddWidget$1({ dashboardId, widgetName }) {
|
|
|
71315
71592
|
item.component === "LayoutContainer" ||
|
|
71316
71593
|
item.component === "LayoutGridContainer",
|
|
71317
71594
|
);
|
|
71318
|
-
|
|
71595
|
+
|
|
71596
|
+
const gridNode = findGridNode(layout);
|
|
71597
|
+
|
|
71598
|
+
// Determine grid placement
|
|
71599
|
+
let targetRow = null;
|
|
71600
|
+
let targetCol = null;
|
|
71601
|
+
|
|
71602
|
+
if (row !== undefined && col !== undefined) {
|
|
71603
|
+
// Explicit placement requested
|
|
71604
|
+
if (!gridNode) {
|
|
71605
|
+
return {
|
|
71606
|
+
content: [
|
|
71607
|
+
{
|
|
71608
|
+
type: "text",
|
|
71609
|
+
text: JSON.stringify({
|
|
71610
|
+
error:
|
|
71611
|
+
"Cannot specify row/col: dashboard has no grid layout. Use create_dashboard with layout or set_layout first.",
|
|
71612
|
+
}),
|
|
71613
|
+
},
|
|
71614
|
+
],
|
|
71615
|
+
isError: true,
|
|
71616
|
+
};
|
|
71617
|
+
}
|
|
71618
|
+
const r = Number(row);
|
|
71619
|
+
const c = Number(col);
|
|
71620
|
+
if (!isValidCell(gridNode.grid, r, c)) {
|
|
71621
|
+
return {
|
|
71622
|
+
content: [
|
|
71623
|
+
{
|
|
71624
|
+
type: "text",
|
|
71625
|
+
text: JSON.stringify({
|
|
71626
|
+
error: `Cell ${r}.${c} is out of bounds (grid is ${gridNode.grid.rows}x${gridNode.grid.cols})`,
|
|
71627
|
+
}),
|
|
71628
|
+
},
|
|
71629
|
+
],
|
|
71630
|
+
isError: true,
|
|
71631
|
+
};
|
|
71632
|
+
}
|
|
71633
|
+
const cellKey = `${r}.${c}`;
|
|
71634
|
+
const cell = gridNode.grid[cellKey];
|
|
71635
|
+
if (cell && cell.hide) {
|
|
71636
|
+
return {
|
|
71637
|
+
content: [
|
|
71638
|
+
{
|
|
71639
|
+
type: "text",
|
|
71640
|
+
text: JSON.stringify({
|
|
71641
|
+
error: `Cell ${r}.${c} is hidden`,
|
|
71642
|
+
}),
|
|
71643
|
+
},
|
|
71644
|
+
],
|
|
71645
|
+
isError: true,
|
|
71646
|
+
};
|
|
71647
|
+
}
|
|
71648
|
+
if (cell && cell.component !== null) {
|
|
71649
|
+
return {
|
|
71650
|
+
content: [
|
|
71651
|
+
{
|
|
71652
|
+
type: "text",
|
|
71653
|
+
text: JSON.stringify({
|
|
71654
|
+
error: `Cell ${r}.${c} is already occupied by widget ${cell.component}`,
|
|
71655
|
+
}),
|
|
71656
|
+
},
|
|
71657
|
+
],
|
|
71658
|
+
isError: true,
|
|
71659
|
+
};
|
|
71660
|
+
}
|
|
71661
|
+
targetRow = r;
|
|
71662
|
+
targetCol = c;
|
|
71663
|
+
} else if (gridNode) {
|
|
71664
|
+
// No row/col specified but grid exists — auto-place in next empty cell
|
|
71665
|
+
const empty = findNextEmptyCell(gridNode.grid);
|
|
71666
|
+
if (empty) {
|
|
71667
|
+
targetRow = empty.row;
|
|
71668
|
+
targetCol = empty.col;
|
|
71669
|
+
}
|
|
71670
|
+
}
|
|
71671
|
+
|
|
71672
|
+
const parentContainerId = gridNode
|
|
71673
|
+
? gridNode.id
|
|
71674
|
+
: container
|
|
71675
|
+
? container.id
|
|
71676
|
+
: 0;
|
|
71319
71677
|
|
|
71320
71678
|
const newId = nextLayoutId(layout);
|
|
71321
71679
|
const maxOrder = layout.reduce(
|
|
@@ -71327,12 +71685,22 @@ async function handleAddWidget$1({ dashboardId, widgetName }) {
|
|
|
71327
71685
|
id: newId,
|
|
71328
71686
|
order: maxOrder + 1,
|
|
71329
71687
|
component: widgetName.trim(),
|
|
71330
|
-
|
|
71688
|
+
parent: parentContainerId,
|
|
71331
71689
|
config: {},
|
|
71332
71690
|
};
|
|
71333
71691
|
|
|
71334
71692
|
workspace.layout = [...layout, newItem];
|
|
71335
71693
|
|
|
71694
|
+
// If placing in grid, update the cell assignment
|
|
71695
|
+
if (gridNode && targetRow !== null && targetCol !== null) {
|
|
71696
|
+
const cellKey = `${targetRow}.${targetCol}`;
|
|
71697
|
+
gridNode.grid[cellKey] = {
|
|
71698
|
+
...(gridNode.grid[cellKey] || {}),
|
|
71699
|
+
component: newId,
|
|
71700
|
+
hide: false,
|
|
71701
|
+
};
|
|
71702
|
+
}
|
|
71703
|
+
|
|
71336
71704
|
const saveResult = workspaceController$2.saveWorkspaceForApplication(
|
|
71337
71705
|
win,
|
|
71338
71706
|
appId,
|
|
@@ -71350,19 +71718,20 @@ async function handleAddWidget$1({ dashboardId, widgetName }) {
|
|
|
71350
71718
|
};
|
|
71351
71719
|
}
|
|
71352
71720
|
|
|
71721
|
+
const response = {
|
|
71722
|
+
widgetId: String(newId),
|
|
71723
|
+
name: widgetName.trim(),
|
|
71724
|
+
dashboardId: String(workspace.id),
|
|
71725
|
+
};
|
|
71726
|
+
if (targetRow !== null && targetCol !== null) {
|
|
71727
|
+
response.cell = { row: targetRow, col: targetCol };
|
|
71728
|
+
}
|
|
71729
|
+
|
|
71353
71730
|
return {
|
|
71354
71731
|
content: [
|
|
71355
71732
|
{
|
|
71356
71733
|
type: "text",
|
|
71357
|
-
text: JSON.stringify(
|
|
71358
|
-
{
|
|
71359
|
-
widgetId: String(newId),
|
|
71360
|
-
name: widgetName.trim(),
|
|
71361
|
-
dashboardId: String(workspace.id),
|
|
71362
|
-
},
|
|
71363
|
-
null,
|
|
71364
|
-
2,
|
|
71365
|
-
),
|
|
71734
|
+
text: JSON.stringify(response, null, 2),
|
|
71366
71735
|
},
|
|
71367
71736
|
],
|
|
71368
71737
|
};
|
|
@@ -71418,6 +71787,21 @@ async function handleRemoveWidget$1({ dashboardId, widgetId }) {
|
|
|
71418
71787
|
|
|
71419
71788
|
workspace.layout = layout.filter((item) => String(item.id) !== widgetId);
|
|
71420
71789
|
|
|
71790
|
+
// Clean up grid cell assignments that reference this widget
|
|
71791
|
+
const numericId = Number(widgetId);
|
|
71792
|
+
for (const item of workspace.layout) {
|
|
71793
|
+
if (item.grid) {
|
|
71794
|
+
for (const key of Object.keys(item.grid)) {
|
|
71795
|
+
if (/^\d+\.\d+$/.test(key)) {
|
|
71796
|
+
const cell = item.grid[key];
|
|
71797
|
+
if (cell && cell.component === numericId) {
|
|
71798
|
+
cell.component = null;
|
|
71799
|
+
}
|
|
71800
|
+
}
|
|
71801
|
+
}
|
|
71802
|
+
}
|
|
71803
|
+
}
|
|
71804
|
+
|
|
71421
71805
|
const saveResult = workspaceController$2.saveWorkspaceForApplication(
|
|
71422
71806
|
win,
|
|
71423
71807
|
appId,
|
|
@@ -72579,36 +72963,530 @@ async function handleGetSetupGuide$1({ topic }) {
|
|
|
72579
72963
|
};
|
|
72580
72964
|
}
|
|
72581
72965
|
|
|
72582
|
-
|
|
72583
|
-
handleListDashboards: handleListDashboards$1,
|
|
72584
|
-
handleGetDashboard: handleGetDashboard$1,
|
|
72585
|
-
handleCreateDashboard: handleCreateDashboard$1,
|
|
72586
|
-
handleDeleteDashboard: handleDeleteDashboard$1,
|
|
72587
|
-
handleGetAppStats: handleGetAppStats$1,
|
|
72588
|
-
handleAddWidget: handleAddWidget$1,
|
|
72589
|
-
handleRemoveWidget: handleRemoveWidget$1,
|
|
72590
|
-
handleConfigureWidget: handleConfigureWidget$1,
|
|
72591
|
-
handleListWidgets: handleListWidgets$1,
|
|
72592
|
-
handleSearchWidgets: handleSearchWidgets$1,
|
|
72593
|
-
handleListThemes: handleListThemes$1,
|
|
72594
|
-
handleGetTheme: handleGetTheme$1,
|
|
72595
|
-
handleCreateTheme: handleCreateTheme$1,
|
|
72596
|
-
handleCreateThemeFromUrl: handleCreateThemeFromUrl$1,
|
|
72597
|
-
handleApplyTheme: handleApplyTheme$1,
|
|
72598
|
-
handleListProviders: handleListProviders$1,
|
|
72599
|
-
handleAddProvider: handleAddProvider$1,
|
|
72600
|
-
handleRemoveProvider: handleRemoveProvider$1,
|
|
72601
|
-
handleGetSetupGuide: handleGetSetupGuide$1,
|
|
72602
|
-
};
|
|
72966
|
+
// --- Layout Tool Handlers ---
|
|
72603
72967
|
|
|
72604
72968
|
/**
|
|
72605
|
-
*
|
|
72606
|
-
*
|
|
72607
|
-
* Registers dashboard/workspace MCP tools with the MCP Dash server.
|
|
72608
|
-
* Call registerDashboardTools() during app startup (before or after server start).
|
|
72969
|
+
* set_layout — Set or replace the grid layout on a dashboard.
|
|
72609
72970
|
*/
|
|
72971
|
+
async function handleSetLayout$1({ dashboardId, rows, cols, gap, colModes }) {
|
|
72972
|
+
if (
|
|
72973
|
+
rows === undefined ||
|
|
72974
|
+
cols === undefined ||
|
|
72975
|
+
typeof rows !== "number" ||
|
|
72976
|
+
typeof cols !== "number"
|
|
72977
|
+
) {
|
|
72978
|
+
return {
|
|
72979
|
+
content: [
|
|
72980
|
+
{
|
|
72981
|
+
type: "text",
|
|
72982
|
+
text: JSON.stringify({
|
|
72983
|
+
error: "rows and cols are required numbers",
|
|
72984
|
+
}),
|
|
72985
|
+
},
|
|
72986
|
+
],
|
|
72987
|
+
isError: true,
|
|
72988
|
+
};
|
|
72989
|
+
}
|
|
72990
|
+
if (rows < 1 || rows > 10 || cols < 1 || cols > 10) {
|
|
72991
|
+
return {
|
|
72992
|
+
content: [
|
|
72993
|
+
{
|
|
72994
|
+
type: "text",
|
|
72995
|
+
text: JSON.stringify({
|
|
72996
|
+
error: "rows and cols must be between 1 and 10",
|
|
72997
|
+
}),
|
|
72998
|
+
},
|
|
72999
|
+
],
|
|
73000
|
+
isError: true,
|
|
73001
|
+
};
|
|
73002
|
+
}
|
|
72610
73003
|
|
|
72611
|
-
const {
|
|
73004
|
+
const { win, appId } = requireContext$1();
|
|
73005
|
+
const result = workspaceController$2.listWorkspacesForApplication(win, appId);
|
|
73006
|
+
if (result.error) {
|
|
73007
|
+
return {
|
|
73008
|
+
content: [
|
|
73009
|
+
{ type: "text", text: JSON.stringify({ error: result.message }) },
|
|
73010
|
+
],
|
|
73011
|
+
isError: true,
|
|
73012
|
+
};
|
|
73013
|
+
}
|
|
73014
|
+
|
|
73015
|
+
const found = findWorkspace(result.workspaces || [], dashboardId);
|
|
73016
|
+
if (found.error) return found.response;
|
|
73017
|
+
|
|
73018
|
+
const workspace = found.workspace;
|
|
73019
|
+
const layout = workspace.layout || [];
|
|
73020
|
+
|
|
73021
|
+
const newGrid = buildEmptyGrid(rows, cols, gap, colModes);
|
|
73022
|
+
const existingGridNode = findGridNode(layout);
|
|
73023
|
+
const orphanedWidgetIds = [];
|
|
73024
|
+
|
|
73025
|
+
if (existingGridNode) {
|
|
73026
|
+
// Preserve cell assignments that still fit in the new dimensions
|
|
73027
|
+
const oldGrid = existingGridNode.grid;
|
|
73028
|
+
for (const key of Object.keys(oldGrid)) {
|
|
73029
|
+
if (
|
|
73030
|
+
/^\d+\.\d+$/.test(key) &&
|
|
73031
|
+
oldGrid[key] &&
|
|
73032
|
+
oldGrid[key].component !== null
|
|
73033
|
+
) {
|
|
73034
|
+
const parts = key.split(".");
|
|
73035
|
+
const r = Number(parts[0]);
|
|
73036
|
+
const c = Number(parts[1]);
|
|
73037
|
+
if (r <= rows && c <= cols) {
|
|
73038
|
+
newGrid[key] = { ...newGrid[key], component: oldGrid[key].component };
|
|
73039
|
+
} else {
|
|
73040
|
+
orphanedWidgetIds.push(oldGrid[key].component);
|
|
73041
|
+
}
|
|
73042
|
+
}
|
|
73043
|
+
}
|
|
73044
|
+
existingGridNode.grid = newGrid;
|
|
73045
|
+
} else {
|
|
73046
|
+
// Replace root Container with a LayoutGridContainer
|
|
73047
|
+
const rootIdx = layout.findIndex(
|
|
73048
|
+
(item) =>
|
|
73049
|
+
item.parent === 0 &&
|
|
73050
|
+
(item.component === "Container" ||
|
|
73051
|
+
item.component === "LayoutContainer"),
|
|
73052
|
+
);
|
|
73053
|
+
|
|
73054
|
+
const newGridNode = {
|
|
73055
|
+
id: rootIdx >= 0 ? layout[rootIdx].id : nextLayoutId(layout),
|
|
73056
|
+
order: 1,
|
|
73057
|
+
component: "LayoutGridContainer",
|
|
73058
|
+
type: "grid",
|
|
73059
|
+
parent: 0,
|
|
73060
|
+
hasChildren: 1,
|
|
73061
|
+
scrollable: false,
|
|
73062
|
+
width: "w-full",
|
|
73063
|
+
height: "h-full",
|
|
73064
|
+
workspace: "layout",
|
|
73065
|
+
grid: newGrid,
|
|
73066
|
+
};
|
|
73067
|
+
|
|
73068
|
+
if (rootIdx >= 0) {
|
|
73069
|
+
// Reparent existing widgets to the new grid node
|
|
73070
|
+
const oldRootId = layout[rootIdx].id;
|
|
73071
|
+
for (const item of layout) {
|
|
73072
|
+
if (item.parent === oldRootId && item.id !== oldRootId) {
|
|
73073
|
+
item.parent = newGridNode.id;
|
|
73074
|
+
}
|
|
73075
|
+
}
|
|
73076
|
+
workspace.layout[rootIdx] = newGridNode;
|
|
73077
|
+
} else {
|
|
73078
|
+
workspace.layout = [newGridNode, ...layout];
|
|
73079
|
+
}
|
|
73080
|
+
}
|
|
73081
|
+
|
|
73082
|
+
const saveResult = workspaceController$2.saveWorkspaceForApplication(
|
|
73083
|
+
win,
|
|
73084
|
+
appId,
|
|
73085
|
+
workspace,
|
|
73086
|
+
);
|
|
73087
|
+
if (saveResult.error) {
|
|
73088
|
+
return {
|
|
73089
|
+
content: [
|
|
73090
|
+
{ type: "text", text: JSON.stringify({ error: saveResult.message }) },
|
|
73091
|
+
],
|
|
73092
|
+
isError: true,
|
|
73093
|
+
};
|
|
73094
|
+
}
|
|
73095
|
+
|
|
73096
|
+
return {
|
|
73097
|
+
content: [
|
|
73098
|
+
{
|
|
73099
|
+
type: "text",
|
|
73100
|
+
text: JSON.stringify(
|
|
73101
|
+
{
|
|
73102
|
+
dashboardId: String(workspace.id),
|
|
73103
|
+
grid: { rows, cols },
|
|
73104
|
+
orphanedWidgets: orphanedWidgetIds.map(String),
|
|
73105
|
+
},
|
|
73106
|
+
null,
|
|
73107
|
+
2,
|
|
73108
|
+
),
|
|
73109
|
+
},
|
|
73110
|
+
],
|
|
73111
|
+
};
|
|
73112
|
+
}
|
|
73113
|
+
|
|
73114
|
+
/**
|
|
73115
|
+
* update_layout — Partially update grid layout properties.
|
|
73116
|
+
*/
|
|
73117
|
+
async function handleUpdateLayout$1({ dashboardId, rows, cols, gap, colModes }) {
|
|
73118
|
+
if (
|
|
73119
|
+
rows === undefined &&
|
|
73120
|
+
cols === undefined &&
|
|
73121
|
+
gap === undefined &&
|
|
73122
|
+
colModes === undefined
|
|
73123
|
+
) {
|
|
73124
|
+
return {
|
|
73125
|
+
content: [
|
|
73126
|
+
{
|
|
73127
|
+
type: "text",
|
|
73128
|
+
text: JSON.stringify({
|
|
73129
|
+
error:
|
|
73130
|
+
"At least one of rows, cols, gap, or colModes must be provided",
|
|
73131
|
+
}),
|
|
73132
|
+
},
|
|
73133
|
+
],
|
|
73134
|
+
isError: true,
|
|
73135
|
+
};
|
|
73136
|
+
}
|
|
73137
|
+
|
|
73138
|
+
const { win, appId } = requireContext$1();
|
|
73139
|
+
const result = workspaceController$2.listWorkspacesForApplication(win, appId);
|
|
73140
|
+
if (result.error) {
|
|
73141
|
+
return {
|
|
73142
|
+
content: [
|
|
73143
|
+
{ type: "text", text: JSON.stringify({ error: result.message }) },
|
|
73144
|
+
],
|
|
73145
|
+
isError: true,
|
|
73146
|
+
};
|
|
73147
|
+
}
|
|
73148
|
+
|
|
73149
|
+
const found = findWorkspace(result.workspaces || [], dashboardId);
|
|
73150
|
+
if (found.error) return found.response;
|
|
73151
|
+
|
|
73152
|
+
const workspace = found.workspace;
|
|
73153
|
+
const gridNode = findGridNode(workspace.layout || []);
|
|
73154
|
+
|
|
73155
|
+
if (!gridNode) {
|
|
73156
|
+
return {
|
|
73157
|
+
content: [
|
|
73158
|
+
{
|
|
73159
|
+
type: "text",
|
|
73160
|
+
text: JSON.stringify({
|
|
73161
|
+
error:
|
|
73162
|
+
"Dashboard has no grid layout. Use set_layout or create_dashboard with layout first.",
|
|
73163
|
+
}),
|
|
73164
|
+
},
|
|
73165
|
+
],
|
|
73166
|
+
isError: true,
|
|
73167
|
+
};
|
|
73168
|
+
}
|
|
73169
|
+
|
|
73170
|
+
const grid = gridNode.grid;
|
|
73171
|
+
const oldRows = grid.rows;
|
|
73172
|
+
const oldCols = grid.cols;
|
|
73173
|
+
const newRows = rows !== undefined ? rows : oldRows;
|
|
73174
|
+
const newCols = cols !== undefined ? cols : oldCols;
|
|
73175
|
+
|
|
73176
|
+
if (newRows < 1 || newRows > 10 || newCols < 1 || newCols > 10) {
|
|
73177
|
+
return {
|
|
73178
|
+
content: [
|
|
73179
|
+
{
|
|
73180
|
+
type: "text",
|
|
73181
|
+
text: JSON.stringify({
|
|
73182
|
+
error: "rows and cols must be between 1 and 10",
|
|
73183
|
+
}),
|
|
73184
|
+
},
|
|
73185
|
+
],
|
|
73186
|
+
isError: true,
|
|
73187
|
+
};
|
|
73188
|
+
}
|
|
73189
|
+
|
|
73190
|
+
// Update gap if specified
|
|
73191
|
+
if (gap !== undefined) {
|
|
73192
|
+
grid.gap = gap;
|
|
73193
|
+
}
|
|
73194
|
+
|
|
73195
|
+
// Merge colModes if specified
|
|
73196
|
+
if (colModes !== undefined) {
|
|
73197
|
+
grid.colModes = { ...(grid.colModes || {}), ...colModes };
|
|
73198
|
+
// Remove entries set to null
|
|
73199
|
+
for (const k of Object.keys(grid.colModes)) {
|
|
73200
|
+
if (grid.colModes[k] === null) {
|
|
73201
|
+
delete grid.colModes[k];
|
|
73202
|
+
}
|
|
73203
|
+
}
|
|
73204
|
+
if (Object.keys(grid.colModes).length === 0) {
|
|
73205
|
+
delete grid.colModes;
|
|
73206
|
+
}
|
|
73207
|
+
}
|
|
73208
|
+
|
|
73209
|
+
// Handle dimension changes
|
|
73210
|
+
const orphanedWidgetIds = [];
|
|
73211
|
+
if (newRows !== oldRows || newCols !== oldCols) {
|
|
73212
|
+
// Add new cells
|
|
73213
|
+
for (let r = 1; r <= newRows; r++) {
|
|
73214
|
+
for (let c = 1; c <= newCols; c++) {
|
|
73215
|
+
const key = `${r}.${c}`;
|
|
73216
|
+
if (!grid[key]) {
|
|
73217
|
+
grid[key] = { component: null, hide: false };
|
|
73218
|
+
}
|
|
73219
|
+
}
|
|
73220
|
+
}
|
|
73221
|
+
// Collect orphaned widgets from removed cells
|
|
73222
|
+
for (const key of Object.keys(grid)) {
|
|
73223
|
+
if (/^\d+\.\d+$/.test(key)) {
|
|
73224
|
+
const parts = key.split(".");
|
|
73225
|
+
const r = Number(parts[0]);
|
|
73226
|
+
const c = Number(parts[1]);
|
|
73227
|
+
if (r > newRows || c > newCols) {
|
|
73228
|
+
if (grid[key] && grid[key].component !== null) {
|
|
73229
|
+
orphanedWidgetIds.push(grid[key].component);
|
|
73230
|
+
}
|
|
73231
|
+
delete grid[key];
|
|
73232
|
+
}
|
|
73233
|
+
}
|
|
73234
|
+
}
|
|
73235
|
+
grid.rows = newRows;
|
|
73236
|
+
grid.cols = newCols;
|
|
73237
|
+
}
|
|
73238
|
+
|
|
73239
|
+
const saveResult = workspaceController$2.saveWorkspaceForApplication(
|
|
73240
|
+
win,
|
|
73241
|
+
appId,
|
|
73242
|
+
workspace,
|
|
73243
|
+
);
|
|
73244
|
+
if (saveResult.error) {
|
|
73245
|
+
return {
|
|
73246
|
+
content: [
|
|
73247
|
+
{ type: "text", text: JSON.stringify({ error: saveResult.message }) },
|
|
73248
|
+
],
|
|
73249
|
+
isError: true,
|
|
73250
|
+
};
|
|
73251
|
+
}
|
|
73252
|
+
|
|
73253
|
+
return {
|
|
73254
|
+
content: [
|
|
73255
|
+
{
|
|
73256
|
+
type: "text",
|
|
73257
|
+
text: JSON.stringify(
|
|
73258
|
+
{
|
|
73259
|
+
dashboardId: String(workspace.id),
|
|
73260
|
+
grid: { rows: newRows, cols: newCols, gap: grid.gap },
|
|
73261
|
+
orphanedWidgets: orphanedWidgetIds.map(String),
|
|
73262
|
+
},
|
|
73263
|
+
null,
|
|
73264
|
+
2,
|
|
73265
|
+
),
|
|
73266
|
+
},
|
|
73267
|
+
],
|
|
73268
|
+
};
|
|
73269
|
+
}
|
|
73270
|
+
|
|
73271
|
+
/**
|
|
73272
|
+
* move_widget — Move a widget to a different grid cell (swap if occupied).
|
|
73273
|
+
*/
|
|
73274
|
+
async function handleMoveWidget$1({ dashboardId, widgetId, row, col }) {
|
|
73275
|
+
if (!widgetId || typeof widgetId !== "string") {
|
|
73276
|
+
return {
|
|
73277
|
+
content: [
|
|
73278
|
+
{
|
|
73279
|
+
type: "text",
|
|
73280
|
+
text: JSON.stringify({ error: "widgetId is required" }),
|
|
73281
|
+
},
|
|
73282
|
+
],
|
|
73283
|
+
isError: true,
|
|
73284
|
+
};
|
|
73285
|
+
}
|
|
73286
|
+
if (row === undefined || col === undefined) {
|
|
73287
|
+
return {
|
|
73288
|
+
content: [
|
|
73289
|
+
{
|
|
73290
|
+
type: "text",
|
|
73291
|
+
text: JSON.stringify({ error: "row and col are required" }),
|
|
73292
|
+
},
|
|
73293
|
+
],
|
|
73294
|
+
isError: true,
|
|
73295
|
+
};
|
|
73296
|
+
}
|
|
73297
|
+
|
|
73298
|
+
const { win, appId } = requireContext$1();
|
|
73299
|
+
const result = workspaceController$2.listWorkspacesForApplication(win, appId);
|
|
73300
|
+
if (result.error) {
|
|
73301
|
+
return {
|
|
73302
|
+
content: [
|
|
73303
|
+
{ type: "text", text: JSON.stringify({ error: result.message }) },
|
|
73304
|
+
],
|
|
73305
|
+
isError: true,
|
|
73306
|
+
};
|
|
73307
|
+
}
|
|
73308
|
+
|
|
73309
|
+
const found = findWorkspace(result.workspaces || [], dashboardId);
|
|
73310
|
+
if (found.error) return found.response;
|
|
73311
|
+
|
|
73312
|
+
const workspace = found.workspace;
|
|
73313
|
+
const gridNode = findGridNode(workspace.layout || []);
|
|
73314
|
+
|
|
73315
|
+
if (!gridNode) {
|
|
73316
|
+
return {
|
|
73317
|
+
content: [
|
|
73318
|
+
{
|
|
73319
|
+
type: "text",
|
|
73320
|
+
text: JSON.stringify({
|
|
73321
|
+
error: "Dashboard has no grid layout",
|
|
73322
|
+
}),
|
|
73323
|
+
},
|
|
73324
|
+
],
|
|
73325
|
+
isError: true,
|
|
73326
|
+
};
|
|
73327
|
+
}
|
|
73328
|
+
|
|
73329
|
+
const r = Number(row);
|
|
73330
|
+
const c = Number(col);
|
|
73331
|
+
if (!isValidCell(gridNode.grid, r, c)) {
|
|
73332
|
+
return {
|
|
73333
|
+
content: [
|
|
73334
|
+
{
|
|
73335
|
+
type: "text",
|
|
73336
|
+
text: JSON.stringify({
|
|
73337
|
+
error: `Cell ${r}.${c} is out of bounds (grid is ${gridNode.grid.rows}x${gridNode.grid.cols})`,
|
|
73338
|
+
}),
|
|
73339
|
+
},
|
|
73340
|
+
],
|
|
73341
|
+
isError: true,
|
|
73342
|
+
};
|
|
73343
|
+
}
|
|
73344
|
+
|
|
73345
|
+
const targetKey = `${r}.${c}`;
|
|
73346
|
+
const targetCell = gridNode.grid[targetKey];
|
|
73347
|
+
if (targetCell && targetCell.hide) {
|
|
73348
|
+
return {
|
|
73349
|
+
content: [
|
|
73350
|
+
{
|
|
73351
|
+
type: "text",
|
|
73352
|
+
text: JSON.stringify({
|
|
73353
|
+
error: `Cell ${r}.${c} is hidden`,
|
|
73354
|
+
}),
|
|
73355
|
+
},
|
|
73356
|
+
],
|
|
73357
|
+
isError: true,
|
|
73358
|
+
};
|
|
73359
|
+
}
|
|
73360
|
+
|
|
73361
|
+
// Find the widget's current cell
|
|
73362
|
+
const numericWidgetId = Number(widgetId);
|
|
73363
|
+
let sourceKey = null;
|
|
73364
|
+
for (const key of Object.keys(gridNode.grid)) {
|
|
73365
|
+
if (
|
|
73366
|
+
/^\d+\.\d+$/.test(key) &&
|
|
73367
|
+
gridNode.grid[key] &&
|
|
73368
|
+
gridNode.grid[key].component === numericWidgetId
|
|
73369
|
+
) {
|
|
73370
|
+
sourceKey = key;
|
|
73371
|
+
break;
|
|
73372
|
+
}
|
|
73373
|
+
}
|
|
73374
|
+
|
|
73375
|
+
if (!sourceKey) {
|
|
73376
|
+
return {
|
|
73377
|
+
content: [
|
|
73378
|
+
{
|
|
73379
|
+
type: "text",
|
|
73380
|
+
text: JSON.stringify({
|
|
73381
|
+
error: `Widget ${widgetId} not found in any grid cell`,
|
|
73382
|
+
}),
|
|
73383
|
+
},
|
|
73384
|
+
],
|
|
73385
|
+
isError: true,
|
|
73386
|
+
};
|
|
73387
|
+
}
|
|
73388
|
+
|
|
73389
|
+
if (sourceKey === targetKey) {
|
|
73390
|
+
return {
|
|
73391
|
+
content: [
|
|
73392
|
+
{
|
|
73393
|
+
type: "text",
|
|
73394
|
+
text: JSON.stringify(
|
|
73395
|
+
{
|
|
73396
|
+
widgetId,
|
|
73397
|
+
cell: { row: r, col: c },
|
|
73398
|
+
swapped: false,
|
|
73399
|
+
},
|
|
73400
|
+
null,
|
|
73401
|
+
2,
|
|
73402
|
+
),
|
|
73403
|
+
},
|
|
73404
|
+
],
|
|
73405
|
+
};
|
|
73406
|
+
}
|
|
73407
|
+
|
|
73408
|
+
// Perform the move (swap if target occupied)
|
|
73409
|
+
const targetComponentId = targetCell ? targetCell.component : null;
|
|
73410
|
+
gridNode.grid[targetKey] = {
|
|
73411
|
+
...(gridNode.grid[targetKey] || {}),
|
|
73412
|
+
component: numericWidgetId,
|
|
73413
|
+
};
|
|
73414
|
+
gridNode.grid[sourceKey] = {
|
|
73415
|
+
...(gridNode.grid[sourceKey] || {}),
|
|
73416
|
+
component: targetComponentId,
|
|
73417
|
+
};
|
|
73418
|
+
|
|
73419
|
+
const saveResult = workspaceController$2.saveWorkspaceForApplication(
|
|
73420
|
+
win,
|
|
73421
|
+
appId,
|
|
73422
|
+
workspace,
|
|
73423
|
+
);
|
|
73424
|
+
if (saveResult.error) {
|
|
73425
|
+
return {
|
|
73426
|
+
content: [
|
|
73427
|
+
{ type: "text", text: JSON.stringify({ error: saveResult.message }) },
|
|
73428
|
+
],
|
|
73429
|
+
isError: true,
|
|
73430
|
+
};
|
|
73431
|
+
}
|
|
73432
|
+
|
|
73433
|
+
const response = {
|
|
73434
|
+
widgetId,
|
|
73435
|
+
cell: { row: r, col: c },
|
|
73436
|
+
swapped: targetComponentId !== null,
|
|
73437
|
+
};
|
|
73438
|
+
if (targetComponentId !== null) {
|
|
73439
|
+
response.swappedWidgetId = String(targetComponentId);
|
|
73440
|
+
}
|
|
73441
|
+
|
|
73442
|
+
return {
|
|
73443
|
+
content: [
|
|
73444
|
+
{
|
|
73445
|
+
type: "text",
|
|
73446
|
+
text: JSON.stringify(response, null, 2),
|
|
73447
|
+
},
|
|
73448
|
+
],
|
|
73449
|
+
};
|
|
73450
|
+
}
|
|
73451
|
+
|
|
73452
|
+
var toolHandlers = {
|
|
73453
|
+
handleListDashboards: handleListDashboards$1,
|
|
73454
|
+
handleGetDashboard: handleGetDashboard$1,
|
|
73455
|
+
handleCreateDashboard: handleCreateDashboard$1,
|
|
73456
|
+
handleDeleteDashboard: handleDeleteDashboard$1,
|
|
73457
|
+
handleGetAppStats: handleGetAppStats$1,
|
|
73458
|
+
handleAddWidget: handleAddWidget$1,
|
|
73459
|
+
handleRemoveWidget: handleRemoveWidget$1,
|
|
73460
|
+
handleConfigureWidget: handleConfigureWidget$1,
|
|
73461
|
+
handleListWidgets: handleListWidgets$1,
|
|
73462
|
+
handleSearchWidgets: handleSearchWidgets$1,
|
|
73463
|
+
handleListThemes: handleListThemes$1,
|
|
73464
|
+
handleGetTheme: handleGetTheme$1,
|
|
73465
|
+
handleCreateTheme: handleCreateTheme$1,
|
|
73466
|
+
handleCreateThemeFromUrl: handleCreateThemeFromUrl$1,
|
|
73467
|
+
handleApplyTheme: handleApplyTheme$1,
|
|
73468
|
+
handleListProviders: handleListProviders$1,
|
|
73469
|
+
handleAddProvider: handleAddProvider$1,
|
|
73470
|
+
handleRemoveProvider: handleRemoveProvider$1,
|
|
73471
|
+
handleGetSetupGuide: handleGetSetupGuide$1,
|
|
73472
|
+
handleSetLayout: handleSetLayout$1,
|
|
73473
|
+
handleUpdateLayout: handleUpdateLayout$1,
|
|
73474
|
+
handleMoveWidget: handleMoveWidget$1,
|
|
73475
|
+
// Helpers (exported for testing)
|
|
73476
|
+
findGridNode,
|
|
73477
|
+
buildEmptyGrid,
|
|
73478
|
+
findNextEmptyCell,
|
|
73479
|
+
isValidCell,
|
|
73480
|
+
};
|
|
73481
|
+
|
|
73482
|
+
/**
|
|
73483
|
+
* dashboardTools.js
|
|
73484
|
+
*
|
|
73485
|
+
* Registers dashboard/workspace MCP tools with the MCP Dash server.
|
|
73486
|
+
* Call registerDashboardTools() during app startup (before or after server start).
|
|
73487
|
+
*/
|
|
73488
|
+
|
|
73489
|
+
const { registerTool: registerTool$5 } = mcpDashServerController_1;
|
|
72612
73490
|
const { dashboardTools } = toolDefinitions;
|
|
72613
73491
|
const {
|
|
72614
73492
|
handleListDashboards,
|
|
@@ -72619,7 +73497,7 @@ const {
|
|
|
72619
73497
|
} = toolHandlers;
|
|
72620
73498
|
|
|
72621
73499
|
// Map tool names to handler functions
|
|
72622
|
-
const handlerMap$
|
|
73500
|
+
const handlerMap$7 = {
|
|
72623
73501
|
list_dashboards: handleListDashboards,
|
|
72624
73502
|
get_dashboard: handleGetDashboard,
|
|
72625
73503
|
create_dashboard: handleCreateDashboard,
|
|
@@ -72632,12 +73510,12 @@ const handlerMap$6 = {
|
|
|
72632
73510
|
*/
|
|
72633
73511
|
function registerDashboardTools$1() {
|
|
72634
73512
|
for (const tool of dashboardTools) {
|
|
72635
|
-
const handler = handlerMap$
|
|
73513
|
+
const handler = handlerMap$7[tool.name];
|
|
72636
73514
|
if (!handler) {
|
|
72637
73515
|
console.warn(`[dashboardTools] No handler found for tool: ${tool.name}`);
|
|
72638
73516
|
continue;
|
|
72639
73517
|
}
|
|
72640
|
-
registerTool$
|
|
73518
|
+
registerTool$5({
|
|
72641
73519
|
name: tool.name,
|
|
72642
73520
|
description: tool.description,
|
|
72643
73521
|
inputSchema: tool.inputSchema,
|
|
@@ -72658,7 +73536,7 @@ var dashboardTools_1 = { registerDashboardTools: registerDashboardTools$1 };
|
|
|
72658
73536
|
* Call registerWidgetTools() during app startup (before or after server start).
|
|
72659
73537
|
*/
|
|
72660
73538
|
|
|
72661
|
-
const { registerTool: registerTool$
|
|
73539
|
+
const { registerTool: registerTool$4 } = mcpDashServerController_1;
|
|
72662
73540
|
const { widgetTools } = toolDefinitions;
|
|
72663
73541
|
const {
|
|
72664
73542
|
handleAddWidget,
|
|
@@ -72669,7 +73547,7 @@ const {
|
|
|
72669
73547
|
} = toolHandlers;
|
|
72670
73548
|
|
|
72671
73549
|
// Map tool names to handler functions
|
|
72672
|
-
const handlerMap$
|
|
73550
|
+
const handlerMap$6 = {
|
|
72673
73551
|
add_widget: handleAddWidget,
|
|
72674
73552
|
remove_widget: handleRemoveWidget,
|
|
72675
73553
|
configure_widget: handleConfigureWidget,
|
|
@@ -72682,12 +73560,12 @@ const handlerMap$5 = {
|
|
|
72682
73560
|
*/
|
|
72683
73561
|
function registerWidgetTools$1() {
|
|
72684
73562
|
for (const tool of widgetTools) {
|
|
72685
|
-
const handler = handlerMap$
|
|
73563
|
+
const handler = handlerMap$6[tool.name];
|
|
72686
73564
|
if (!handler) {
|
|
72687
73565
|
console.warn(`[widgetTools] No handler found for tool: ${tool.name}`);
|
|
72688
73566
|
continue;
|
|
72689
73567
|
}
|
|
72690
|
-
registerTool$
|
|
73568
|
+
registerTool$4({
|
|
72691
73569
|
name: tool.name,
|
|
72692
73570
|
description: tool.description,
|
|
72693
73571
|
inputSchema: tool.inputSchema,
|
|
@@ -72706,7 +73584,7 @@ var widgetTools_1 = { registerWidgetTools: registerWidgetTools$1 };
|
|
|
72706
73584
|
* Call registerThemeTools() during app startup (before or after server start).
|
|
72707
73585
|
*/
|
|
72708
73586
|
|
|
72709
|
-
const { registerTool: registerTool$
|
|
73587
|
+
const { registerTool: registerTool$3 } = mcpDashServerController_1;
|
|
72710
73588
|
const { themeTools } = toolDefinitions;
|
|
72711
73589
|
const {
|
|
72712
73590
|
handleListThemes,
|
|
@@ -72717,7 +73595,7 @@ const {
|
|
|
72717
73595
|
} = toolHandlers;
|
|
72718
73596
|
|
|
72719
73597
|
// Map tool names to handler functions
|
|
72720
|
-
const handlerMap$
|
|
73598
|
+
const handlerMap$5 = {
|
|
72721
73599
|
list_themes: handleListThemes,
|
|
72722
73600
|
get_theme: handleGetTheme,
|
|
72723
73601
|
create_theme: handleCreateTheme,
|
|
@@ -72730,12 +73608,12 @@ const handlerMap$4 = {
|
|
|
72730
73608
|
*/
|
|
72731
73609
|
function registerThemeTools$1() {
|
|
72732
73610
|
for (const tool of themeTools) {
|
|
72733
|
-
const handler = handlerMap$
|
|
73611
|
+
const handler = handlerMap$5[tool.name];
|
|
72734
73612
|
if (!handler) {
|
|
72735
73613
|
console.warn(`[themeTools] No handler found for tool: ${tool.name}`);
|
|
72736
73614
|
continue;
|
|
72737
73615
|
}
|
|
72738
|
-
registerTool$
|
|
73616
|
+
registerTool$3({
|
|
72739
73617
|
name: tool.name,
|
|
72740
73618
|
description: tool.description,
|
|
72741
73619
|
inputSchema: tool.inputSchema,
|
|
@@ -72754,7 +73632,7 @@ var themeTools_1 = { registerThemeTools: registerThemeTools$1 };
|
|
|
72754
73632
|
* Call registerProviderTools() during app startup (before or after server start).
|
|
72755
73633
|
*/
|
|
72756
73634
|
|
|
72757
|
-
const { registerTool: registerTool$
|
|
73635
|
+
const { registerTool: registerTool$2 } = mcpDashServerController_1;
|
|
72758
73636
|
const { providerTools } = toolDefinitions;
|
|
72759
73637
|
const {
|
|
72760
73638
|
handleListProviders,
|
|
@@ -72763,7 +73641,7 @@ const {
|
|
|
72763
73641
|
} = toolHandlers;
|
|
72764
73642
|
|
|
72765
73643
|
// Map tool names to handler functions
|
|
72766
|
-
const handlerMap$
|
|
73644
|
+
const handlerMap$4 = {
|
|
72767
73645
|
list_providers: handleListProviders,
|
|
72768
73646
|
add_provider: handleAddProvider,
|
|
72769
73647
|
remove_provider: handleRemoveProvider,
|
|
@@ -72774,12 +73652,12 @@ const handlerMap$3 = {
|
|
|
72774
73652
|
*/
|
|
72775
73653
|
function registerProviderTools$1() {
|
|
72776
73654
|
for (const tool of providerTools) {
|
|
72777
|
-
const handler = handlerMap$
|
|
73655
|
+
const handler = handlerMap$4[tool.name];
|
|
72778
73656
|
if (!handler) {
|
|
72779
73657
|
console.warn(`[providerTools] No handler found for tool: ${tool.name}`);
|
|
72780
73658
|
continue;
|
|
72781
73659
|
}
|
|
72782
|
-
registerTool$
|
|
73660
|
+
registerTool$2({
|
|
72783
73661
|
name: tool.name,
|
|
72784
73662
|
description: tool.description,
|
|
72785
73663
|
inputSchema: tool.inputSchema,
|
|
@@ -72800,22 +73678,22 @@ var providerTools_1 = { registerProviderTools: registerProviderTools$1 };
|
|
|
72800
73678
|
* Call registerGuideTools() during app startup.
|
|
72801
73679
|
*/
|
|
72802
73680
|
|
|
72803
|
-
const { registerTool } = mcpDashServerController_1;
|
|
73681
|
+
const { registerTool: registerTool$1 } = mcpDashServerController_1;
|
|
72804
73682
|
const { guideTools } = toolDefinitions;
|
|
72805
73683
|
const { handleGetSetupGuide } = toolHandlers;
|
|
72806
73684
|
|
|
72807
|
-
const handlerMap$
|
|
73685
|
+
const handlerMap$3 = {
|
|
72808
73686
|
get_setup_guide: handleGetSetupGuide,
|
|
72809
73687
|
};
|
|
72810
73688
|
|
|
72811
73689
|
function registerGuideTools$1() {
|
|
72812
73690
|
for (const tool of guideTools) {
|
|
72813
|
-
const handler = handlerMap$
|
|
73691
|
+
const handler = handlerMap$3[tool.name];
|
|
72814
73692
|
if (!handler) {
|
|
72815
73693
|
console.warn(`[guideTools] No handler found for tool: ${tool.name}`);
|
|
72816
73694
|
continue;
|
|
72817
73695
|
}
|
|
72818
|
-
registerTool({
|
|
73696
|
+
registerTool$1({
|
|
72819
73697
|
name: tool.name,
|
|
72820
73698
|
description: tool.description,
|
|
72821
73699
|
inputSchema: tool.inputSchema,
|
|
@@ -72827,6 +73705,49 @@ function registerGuideTools$1() {
|
|
|
72827
73705
|
|
|
72828
73706
|
var guideTools_1 = { registerGuideTools: registerGuideTools$1 };
|
|
72829
73707
|
|
|
73708
|
+
/**
|
|
73709
|
+
* layoutTools.js
|
|
73710
|
+
*
|
|
73711
|
+
* Registers layout/grid MCP tools with the MCP Dash server.
|
|
73712
|
+
* Call registerLayoutTools() during app startup (before or after server start).
|
|
73713
|
+
*/
|
|
73714
|
+
|
|
73715
|
+
const { registerTool } = mcpDashServerController_1;
|
|
73716
|
+
const { layoutTools } = toolDefinitions;
|
|
73717
|
+
const {
|
|
73718
|
+
handleSetLayout,
|
|
73719
|
+
handleUpdateLayout,
|
|
73720
|
+
handleMoveWidget,
|
|
73721
|
+
} = toolHandlers;
|
|
73722
|
+
|
|
73723
|
+
const handlerMap$2 = {
|
|
73724
|
+
set_layout: handleSetLayout,
|
|
73725
|
+
update_layout: handleUpdateLayout,
|
|
73726
|
+
move_widget: handleMoveWidget,
|
|
73727
|
+
};
|
|
73728
|
+
|
|
73729
|
+
/**
|
|
73730
|
+
* Register all layout tools with the MCP server controller.
|
|
73731
|
+
*/
|
|
73732
|
+
function registerLayoutTools$1() {
|
|
73733
|
+
for (const tool of layoutTools) {
|
|
73734
|
+
const handler = handlerMap$2[tool.name];
|
|
73735
|
+
if (!handler) {
|
|
73736
|
+
console.warn(`[layoutTools] No handler found for tool: ${tool.name}`);
|
|
73737
|
+
continue;
|
|
73738
|
+
}
|
|
73739
|
+
registerTool({
|
|
73740
|
+
name: tool.name,
|
|
73741
|
+
description: tool.description,
|
|
73742
|
+
inputSchema: tool.inputSchema,
|
|
73743
|
+
handler,
|
|
73744
|
+
});
|
|
73745
|
+
}
|
|
73746
|
+
console.log(`[layoutTools] Registered ${layoutTools.length} layout tools`);
|
|
73747
|
+
}
|
|
73748
|
+
|
|
73749
|
+
var layoutTools_1 = { registerLayoutTools: registerLayoutTools$1 };
|
|
73750
|
+
|
|
72830
73751
|
/**
|
|
72831
73752
|
* resourceDefinitions.js
|
|
72832
73753
|
*
|
|
@@ -73795,6 +74716,7 @@ const { registerWidgetTools } = widgetTools_1;
|
|
|
73795
74716
|
const { registerThemeTools } = themeTools_1;
|
|
73796
74717
|
const { registerProviderTools } = providerTools_1;
|
|
73797
74718
|
const { registerGuideTools } = guideTools_1;
|
|
74719
|
+
const { registerLayoutTools } = layoutTools_1;
|
|
73798
74720
|
const { registerResources } = resources;
|
|
73799
74721
|
const { registerPrompts } = promptRegistration;
|
|
73800
74722
|
registerDashboardTools();
|
|
@@ -73802,6 +74724,7 @@ registerWidgetTools();
|
|
|
73802
74724
|
registerThemeTools();
|
|
73803
74725
|
registerProviderTools();
|
|
73804
74726
|
registerGuideTools();
|
|
74727
|
+
registerLayoutTools();
|
|
73805
74728
|
registerResources();
|
|
73806
74729
|
registerPrompts();
|
|
73807
74730
|
|
|
@@ -73903,6 +74826,7 @@ var electron = {
|
|
|
73903
74826
|
registerWidgetTools,
|
|
73904
74827
|
registerThemeTools,
|
|
73905
74828
|
registerProviderTools,
|
|
74829
|
+
registerLayoutTools,
|
|
73906
74830
|
registerResources,
|
|
73907
74831
|
};
|
|
73908
74832
|
|