@cplace/mcp-server 1.9.1 → 1.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -13
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/app-catalog.js +1 -1
- package/dist/plugins/app-catalog.js.map +1 -1
- package/dist/plugins/application-settings.d.ts.map +1 -1
- package/dist/plugins/application-settings.js +6 -3
- package/dist/plugins/application-settings.js.map +1 -1
- package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/columns.md +6 -0
- package/dist/plugins/core.d.ts.map +1 -1
- package/dist/plugins/core.js +25 -13
- package/dist/plugins/core.js.map +1 -1
- package/dist/plugins/forms-wizard.js +2 -2
- package/dist/plugins/forms-wizard.js.map +1 -1
- package/dist/plugins/history.d.ts.map +1 -1
- package/dist/plugins/history.js +6 -3
- package/dist/plugins/history.js.map +1 -1
- package/dist/plugins/jobs.js +2 -2
- package/dist/plugins/jobs.js.map +1 -1
- package/dist/plugins/layouts.d.ts.map +1 -1
- package/dist/plugins/layouts.js +17 -8
- package/dist/plugins/layouts.js.map +1 -1
- package/dist/plugins/low-code.d.ts.map +1 -1
- package/dist/plugins/low-code.js +48 -17
- package/dist/plugins/low-code.js.map +1 -1
- package/dist/plugins/project-planning.d.ts.map +1 -1
- package/dist/plugins/project-planning.js +6 -3
- package/dist/plugins/project-planning.js.map +1 -1
- package/dist/plugins/resource-management.d.ts.map +1 -1
- package/dist/plugins/resource-management.js +6 -3
- package/dist/plugins/resource-management.js.map +1 -1
- package/dist/plugins/solution-management.d.ts.map +1 -1
- package/dist/plugins/solution-management.js +6 -3
- package/dist/plugins/solution-management.js.map +1 -1
- package/dist/plugins/types-write.d.ts.map +1 -1
- package/dist/plugins/types-write.js +6 -3
- package/dist/plugins/types-write.js.map +1 -1
- package/dist/plugins/widget-specifications.d.ts.map +1 -1
- package/dist/plugins/widget-specifications.js +2 -2
- package/dist/plugins/widget-specifications.js.map +1 -1
- package/dist/plugins/workspace-admin.d.ts.map +1 -1
- package/dist/plugins/workspace-admin.js +6 -3
- package/dist/plugins/workspace-admin.js.map +1 -1
- package/dist/str-replace-utils.js +1 -1
- package/dist/str-replace-utils.js.map +1 -1
- package/dist/tools/apps-catalog.d.ts +1 -1
- package/dist/tools/apps-catalog.d.ts.map +1 -1
- package/dist/tools/apps-catalog.js +16 -12
- package/dist/tools/apps-catalog.js.map +1 -1
- package/dist/tools/board-widget.d.ts +2 -2
- package/dist/tools/board-widget.d.ts.map +1 -1
- package/dist/tools/board-widget.js +354 -201
- package/dist/tools/board-widget.js.map +1 -1
- package/dist/tools/change-listeners.d.ts +2 -2
- package/dist/tools/change-listeners.d.ts.map +1 -1
- package/dist/tools/change-listeners.js +125 -57
- package/dist/tools/change-listeners.js.map +1 -1
- package/dist/tools/common-schemas.d.ts +1 -1
- package/dist/tools/common-schemas.d.ts.map +1 -1
- package/dist/tools/common-schemas.js +5 -3
- package/dist/tools/common-schemas.js.map +1 -1
- package/dist/tools/csv-export.d.ts +2 -2
- package/dist/tools/csv-export.d.ts.map +1 -1
- package/dist/tools/csv-export.js +29 -24
- package/dist/tools/csv-export.js.map +1 -1
- package/dist/tools/documents.d.ts +2 -2
- package/dist/tools/documents.d.ts.map +1 -1
- package/dist/tools/documents.js +34 -14
- package/dist/tools/documents.js.map +1 -1
- package/dist/tools/expert-settings.d.ts +3 -3
- package/dist/tools/expert-settings.d.ts.map +1 -1
- package/dist/tools/expert-settings.js +97 -38
- package/dist/tools/expert-settings.js.map +1 -1
- package/dist/tools/get-operations.d.ts +2 -2
- package/dist/tools/get-operations.d.ts.map +1 -1
- package/dist/tools/get-operations.js +29 -21
- package/dist/tools/get-operations.js.map +1 -1
- package/dist/tools/job-schedule-trigger.d.ts +2 -2
- package/dist/tools/job-schedule-trigger.d.ts.map +1 -1
- package/dist/tools/job-schedule-trigger.js +19 -10
- package/dist/tools/job-schedule-trigger.js.map +1 -1
- package/dist/tools/job-scripts.d.ts +2 -2
- package/dist/tools/job-scripts.d.ts.map +1 -1
- package/dist/tools/job-scripts.js +119 -55
- package/dist/tools/job-scripts.js.map +1 -1
- package/dist/tools/jobs.d.ts +2 -2
- package/dist/tools/jobs.d.ts.map +1 -1
- package/dist/tools/jobs.js +68 -38
- package/dist/tools/jobs.js.map +1 -1
- package/dist/tools/layout-richstring-shared.d.ts +24 -1
- package/dist/tools/layout-richstring-shared.d.ts.map +1 -1
- package/dist/tools/layout-richstring-shared.js +99 -1
- package/dist/tools/layout-richstring-shared.js.map +1 -1
- package/dist/tools/layout-richstring-widgets.d.ts +94 -2
- package/dist/tools/layout-richstring-widgets.d.ts.map +1 -1
- package/dist/tools/layout-richstring-widgets.js +247 -25
- package/dist/tools/layout-richstring-widgets.js.map +1 -1
- package/dist/tools/layout.d.ts +5 -4
- package/dist/tools/layout.d.ts.map +1 -1
- package/dist/tools/layout.js +235 -124
- package/dist/tools/layout.js.map +1 -1
- package/dist/tools/linting.d.ts +2 -2
- package/dist/tools/linting.d.ts.map +1 -1
- package/dist/tools/linting.js +5 -5
- package/dist/tools/linting.js.map +1 -1
- package/dist/tools/page-action-simulation.d.ts +18 -0
- package/dist/tools/page-action-simulation.d.ts.map +1 -0
- package/dist/tools/page-action-simulation.js +88 -0
- package/dist/tools/page-action-simulation.js.map +1 -0
- package/dist/tools/page-actions.d.ts +60 -0
- package/dist/tools/page-actions.d.ts.map +1 -0
- package/dist/tools/page-actions.js +284 -0
- package/dist/tools/page-actions.js.map +1 -0
- package/dist/tools/pages.d.ts +3 -3
- package/dist/tools/pages.d.ts.map +1 -1
- package/dist/tools/pages.js +237 -112
- package/dist/tools/pages.js.map +1 -1
- package/dist/tools/ppt-export-schemas.d.ts +1 -1
- package/dist/tools/ppt-export-schemas.d.ts.map +1 -1
- package/dist/tools/ppt-export-schemas.js +269 -122
- package/dist/tools/ppt-export-schemas.js.map +1 -1
- package/dist/tools/ppt-export.d.ts +2 -2
- package/dist/tools/ppt-export.d.ts.map +1 -1
- package/dist/tools/ppt-export.js +82 -43
- package/dist/tools/ppt-export.js.map +1 -1
- package/dist/tools/profile-management.d.ts +2 -2
- package/dist/tools/profile-management.d.ts.map +1 -1
- package/dist/tools/profile-management.js +109 -82
- package/dist/tools/profile-management.js.map +1 -1
- package/dist/tools/references.d.ts +2 -2
- package/dist/tools/references.d.ts.map +1 -1
- package/dist/tools/references.js +36 -24
- package/dist/tools/references.js.map +1 -1
- package/dist/tools/resource-planner-widget.d.ts +2 -2
- package/dist/tools/resource-planner-widget.d.ts.map +1 -1
- package/dist/tools/resource-planner-widget.js +334 -138
- package/dist/tools/resource-planner-widget.js.map +1 -1
- package/dist/tools/richstring-marker-resolver.d.ts +16 -0
- package/dist/tools/richstring-marker-resolver.d.ts.map +1 -0
- package/dist/tools/richstring-marker-resolver.js +47 -0
- package/dist/tools/richstring-marker-resolver.js.map +1 -0
- package/dist/tools/richstring-widgets.d.ts +6 -16
- package/dist/tools/richstring-widgets.d.ts.map +1 -1
- package/dist/tools/richstring-widgets.js +184 -129
- package/dist/tools/richstring-widgets.js.map +1 -1
- package/dist/tools/schedule.d.ts +2 -2
- package/dist/tools/schedule.d.ts.map +1 -1
- package/dist/tools/schedule.js +23 -14
- package/dist/tools/schedule.js.map +1 -1
- package/dist/tools/script-logs.d.ts +2 -2
- package/dist/tools/script-logs.d.ts.map +1 -1
- package/dist/tools/script-logs.js +71 -32
- package/dist/tools/script-logs.js.map +1 -1
- package/dist/tools/script.d.ts +2 -2
- package/dist/tools/script.d.ts.map +1 -1
- package/dist/tools/script.js +44 -26
- package/dist/tools/script.js.map +1 -1
- package/dist/tools/search.d.ts +2 -2
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +139 -102
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/solution-packages.d.ts +2 -2
- package/dist/tools/solution-packages.d.ts.map +1 -1
- package/dist/tools/solution-packages.js +149 -61
- package/dist/tools/solution-packages.js.map +1 -1
- package/dist/tools/system.d.ts +2 -2
- package/dist/tools/system.d.ts.map +1 -1
- package/dist/tools/system.js +43 -21
- package/dist/tools/system.js.map +1 -1
- package/dist/tools/type-layouts.d.ts +2 -2
- package/dist/tools/type-layouts.d.ts.map +1 -1
- package/dist/tools/type-layouts.js +67 -31
- package/dist/tools/type-layouts.js.map +1 -1
- package/dist/tools/type-management.d.ts +86 -70
- package/dist/tools/type-management.d.ts.map +1 -1
- package/dist/tools/type-management.js +410 -138
- package/dist/tools/type-management.js.map +1 -1
- package/dist/tools/url-resolution.d.ts +2 -2
- package/dist/tools/url-resolution.d.ts.map +1 -1
- package/dist/tools/url-resolution.js +16 -12
- package/dist/tools/url-resolution.js.map +1 -1
- package/dist/tools/users.d.ts +2 -2
- package/dist/tools/users.d.ts.map +1 -1
- package/dist/tools/users.js +24 -14
- package/dist/tools/users.js.map +1 -1
- package/dist/tools/validators.d.ts +2 -2
- package/dist/tools/validators.d.ts.map +1 -1
- package/dist/tools/validators.js +68 -35
- package/dist/tools/validators.js.map +1 -1
- package/dist/tools/version-check.d.ts +2 -2
- package/dist/tools/version-check.d.ts.map +1 -1
- package/dist/tools/version-check.js +36 -30
- package/dist/tools/version-check.js.map +1 -1
- package/dist/tools/version-history.d.ts +2 -2
- package/dist/tools/version-history.d.ts.map +1 -1
- package/dist/tools/version-history.js +72 -41
- package/dist/tools/version-history.js.map +1 -1
- package/dist/tools/widget-simulation.d.ts +5 -6
- package/dist/tools/widget-simulation.d.ts.map +1 -1
- package/dist/tools/widget-simulation.js +60 -42
- package/dist/tools/widget-simulation.js.map +1 -1
- package/dist/tools/widget-tool-helpers.d.ts +17 -1
- package/dist/tools/widget-tool-helpers.d.ts.map +1 -1
- package/dist/tools/widget-tool-helpers.js +41 -6
- package/dist/tools/widget-tool-helpers.js.map +1 -1
- package/dist/tools/widgets.d.ts +2 -2
- package/dist/tools/widgets.d.ts.map +1 -1
- package/dist/tools/widgets.js +62 -43
- package/dist/tools/widgets.js.map +1 -1
- package/dist/tools/wizards.d.ts +2 -2
- package/dist/tools/wizards.d.ts.map +1 -1
- package/dist/tools/wizards.js +378 -182
- package/dist/tools/wizards.js.map +1 -1
- package/dist/tools/workflow-execution.d.ts +2 -2
- package/dist/tools/workflow-execution.d.ts.map +1 -1
- package/dist/tools/workflow-execution.js +27 -19
- package/dist/tools/workflow-execution.js.map +1 -1
- package/dist/tools/workflow-scripts.d.ts +2 -2
- package/dist/tools/workflow-scripts.d.ts.map +1 -1
- package/dist/tools/workflow-scripts.js +168 -81
- package/dist/tools/workflow-scripts.js.map +1 -1
- package/dist/tools/workflow.d.ts +2 -2
- package/dist/tools/workflow.d.ts.map +1 -1
- package/dist/tools/workflow.js +185 -74
- package/dist/tools/workflow.js.map +1 -1
- package/dist/tools/workspace-admin.d.ts +2 -2
- package/dist/tools/workspace-admin.d.ts.map +1 -1
- package/dist/tools/workspace-admin.js +82 -40
- package/dist/tools/workspace-admin.js.map +1 -1
- package/dist/tools/workspace-core.d.ts +2 -2
- package/dist/tools/workspace-core.d.ts.map +1 -1
- package/dist/tools/workspace-core.js +93 -53
- package/dist/tools/workspace-core.js.map +1 -1
- package/dist/utils/dateValidation.js.map +1 -1
- package/package.json +9 -4
|
@@ -1,63 +1,102 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import { debugLogWithTag } from
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { debugLogWithTag } from '../logger.js';
|
|
3
3
|
import { LayoutContextSchema } from './layout.js';
|
|
4
|
-
import { findWidgetById, buildUpdateRequestBody, determineApiEndpoint, buildRequestParams } from './widget-tool-helpers.js';
|
|
4
|
+
import { findWidgetById, buildUpdateRequestBody, determineApiEndpoint, buildRequestParams, } from './widget-tool-helpers.js';
|
|
5
5
|
const TOOL_BOARD_GET_CONFIGURATION = 'cplace_board_get_configuration';
|
|
6
6
|
const TOOL_BOARD_CONFIGURE_CARDS = 'cplace_board_configure_cards';
|
|
7
7
|
const TOOL_BOARD_CONFIGURE_COLUMNS = 'cplace_board_configure_columns';
|
|
8
8
|
const TOOL_BOARD_CONFIGURE_SWIMLANES = 'cplace_board_configure_swimlanes';
|
|
9
9
|
const TOOL_BOARD_CONFIGURE_VISUAL = 'cplace_board_configure_visual';
|
|
10
10
|
const BOARD_WIDGET_TYPE = 'cf.cplace.cboard.main.board';
|
|
11
|
-
const CardDisplaySchema = z
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
const CardDisplaySchema = z
|
|
12
|
+
.object({
|
|
13
|
+
dateAttribute: z
|
|
14
|
+
.string()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("Attribute for date shown in card footer (e.g., 'cf.myType.dueDate')"),
|
|
17
|
+
tagAttributes: z
|
|
18
|
+
.array(z.string())
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Attributes for colored tag badges on cards (e.g., ['cf.myType.category'])"),
|
|
21
|
+
colorAttribute: z
|
|
22
|
+
.object({
|
|
23
|
+
attribute: z
|
|
24
|
+
.string()
|
|
25
|
+
.describe("Enumeration attribute for dynamic left-border color (e.g., 'cf.myType.status')"),
|
|
26
|
+
colorMapping: z
|
|
27
|
+
.record(z.string())
|
|
28
|
+
.describe('Map of enumeration values to hex colors (e.g., {"Open": "#4CAF50", "Closed": "#F44336"})'),
|
|
29
|
+
})
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('Dynamic card border color based on an enumeration attribute'),
|
|
32
|
+
iconAttributes: z
|
|
33
|
+
.array(z.object({
|
|
34
|
+
attribute: z.string().describe('Attribute name for icon indicator'),
|
|
35
|
+
enabled: z
|
|
36
|
+
.boolean()
|
|
37
|
+
.optional()
|
|
38
|
+
.default(true)
|
|
39
|
+
.describe('Whether this icon is active (default: true)'),
|
|
40
|
+
}))
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Attributes shown as icon indicators on cards'),
|
|
43
|
+
})
|
|
44
|
+
.optional();
|
|
23
45
|
const CardConfigurationSchema = z.object({
|
|
24
|
-
searchId: z
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
46
|
+
searchId: z
|
|
47
|
+
.string()
|
|
48
|
+
.describe('Unique identifier for this card source - used to link columns/swimlanes'),
|
|
49
|
+
search: z
|
|
50
|
+
.string()
|
|
51
|
+
.describe('WARNING: Do not manually construct! Use cplaceJson from cplace_search_pages response. Must have \'filters\' array, e.g., {"filters":[{"relativeSpace":"true"},{"types":["cf.myType"]}]}'),
|
|
52
|
+
typeId: z.string().optional().describe('Explicit page type (optional, inferred from search)'),
|
|
53
|
+
cardDisplay: CardDisplaySchema,
|
|
28
54
|
});
|
|
29
|
-
const CardsInputSchema = z
|
|
55
|
+
const CardsInputSchema = z
|
|
56
|
+
.array(CardConfigurationSchema)
|
|
30
57
|
.min(1)
|
|
31
|
-
.describe(
|
|
58
|
+
.describe('Array of card source configurations. Order determines display priority.');
|
|
32
59
|
const LocalizedNamesSchema = z.object({
|
|
33
|
-
en: z.string().describe(
|
|
34
|
-
de: z.string().optional().describe(
|
|
60
|
+
en: z.string().describe('English name'),
|
|
61
|
+
de: z.string().optional().describe('German name (optional)'),
|
|
35
62
|
});
|
|
36
63
|
const MappingSchema = z.object({
|
|
37
|
-
searchId: z.string().describe(
|
|
64
|
+
searchId: z.string().describe('Must match a searchId from card configurations'),
|
|
38
65
|
attribute: z.string().describe("Attribute determining placement (e.g., 'cf.myType.status')"),
|
|
39
|
-
values: z
|
|
40
|
-
|
|
41
|
-
|
|
66
|
+
values: z
|
|
67
|
+
.array(z.string())
|
|
68
|
+
.optional()
|
|
69
|
+
.describe('Enumeration attribute values mapping to this column/swimlane'),
|
|
70
|
+
referenceValues: z
|
|
71
|
+
.array(z.string())
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("Reference attribute values as page UIDs (e.g., '6a0pydt3gd31ea3d42hdhqf4t')"),
|
|
74
|
+
dateRange: z
|
|
75
|
+
.object({
|
|
42
76
|
start: z.string(),
|
|
43
|
-
end: z.string()
|
|
44
|
-
})
|
|
77
|
+
end: z.string(),
|
|
78
|
+
})
|
|
79
|
+
.optional()
|
|
80
|
+
.describe('Date range for date-type attribute mapping'),
|
|
45
81
|
});
|
|
46
82
|
const StaticColumnSchema = z.object({
|
|
47
|
-
columnId: z.string().describe(
|
|
83
|
+
columnId: z.string().describe('Unique identifier for this column'),
|
|
48
84
|
names: LocalizedNamesSchema,
|
|
49
|
-
mappings: z.array(MappingSchema).min(1).describe(
|
|
85
|
+
mappings: z.array(MappingSchema).min(1).describe('Value mappings per card source'),
|
|
50
86
|
});
|
|
51
87
|
const StaticSwimlaneSchema = z.object({
|
|
52
|
-
swimlaneId: z.string().describe(
|
|
88
|
+
swimlaneId: z.string().describe('Unique identifier for this swimlane'),
|
|
53
89
|
names: LocalizedNamesSchema,
|
|
54
|
-
mappings: z.array(MappingSchema).min(1).describe(
|
|
90
|
+
mappings: z.array(MappingSchema).min(1).describe('Value mappings per card source'),
|
|
55
91
|
});
|
|
56
92
|
const DynamicConfigSchema = z.object({
|
|
57
|
-
mappedAttributes: z
|
|
93
|
+
mappedAttributes: z
|
|
94
|
+
.array(z.object({
|
|
58
95
|
searchId: z.string(),
|
|
59
|
-
attribute: z.string()
|
|
60
|
-
}))
|
|
96
|
+
attribute: z.string(),
|
|
97
|
+
}))
|
|
98
|
+
.min(1)
|
|
99
|
+
.describe('Attribute mappings per card source. Dynamic mode requires enumeration attributes.'),
|
|
61
100
|
});
|
|
62
101
|
const BOARD_TOOL_DEFINITIONS = {
|
|
63
102
|
[TOOL_BOARD_GET_CONFIGURATION]: {
|
|
@@ -72,9 +111,9 @@ Returns the current state of:
|
|
|
72
111
|
WORKFLOW: Use this tool first, then modify the relevant section and pass to the corresponding configure tool.`,
|
|
73
112
|
inputSchema: {
|
|
74
113
|
context: LayoutContextSchema,
|
|
75
|
-
widgetId: z.string().describe("The board widget ID (e.g., 'id_abc123')")
|
|
114
|
+
widgetId: z.string().describe("The board widget ID (e.g., 'id_abc123')"),
|
|
76
115
|
},
|
|
77
|
-
annotations: { title:
|
|
116
|
+
annotations: { title: 'Get Board Configuration' },
|
|
78
117
|
},
|
|
79
118
|
[TOOL_BOARD_CONFIGURE_CARDS]: {
|
|
80
119
|
description: `Configure card sources for a board widget. Declares the complete set of card sources - existing sources not in the array will be removed.
|
|
@@ -104,10 +143,10 @@ WORKFLOW:
|
|
|
104
143
|
3. Call this tool with the complete desired cards array`,
|
|
105
144
|
inputSchema: {
|
|
106
145
|
context: LayoutContextSchema,
|
|
107
|
-
widgetId: z.string().describe(
|
|
108
|
-
cards: CardsInputSchema
|
|
146
|
+
widgetId: z.string().describe('The board widget ID'),
|
|
147
|
+
cards: CardsInputSchema,
|
|
109
148
|
},
|
|
110
|
-
annotations: { title:
|
|
149
|
+
annotations: { title: 'Configure Board Cards' },
|
|
111
150
|
},
|
|
112
151
|
[TOOL_BOARD_CONFIGURE_COLUMNS]: {
|
|
113
152
|
description: `Configure column structure for a board widget. Declares the complete column configuration.
|
|
@@ -137,12 +176,15 @@ WORKFLOW:
|
|
|
137
176
|
4. Call this tool with complete desired state`,
|
|
138
177
|
inputSchema: {
|
|
139
178
|
context: LayoutContextSchema,
|
|
140
|
-
widgetId: z.string().describe(
|
|
141
|
-
mode: z.enum([
|
|
142
|
-
columns: z
|
|
143
|
-
|
|
179
|
+
widgetId: z.string().describe('The board widget ID'),
|
|
180
|
+
mode: z.enum(['static', 'dynamic']).describe('Column generation mode'),
|
|
181
|
+
columns: z
|
|
182
|
+
.array(StaticColumnSchema)
|
|
183
|
+
.optional()
|
|
184
|
+
.describe('Static column definitions (required for static mode)'),
|
|
185
|
+
dynamicConfig: DynamicConfigSchema.optional().describe('Dynamic column configuration (required for dynamic mode)'),
|
|
144
186
|
},
|
|
145
|
-
annotations: { title:
|
|
187
|
+
annotations: { title: 'Configure Board Columns' },
|
|
146
188
|
},
|
|
147
189
|
[TOOL_BOARD_CONFIGURE_SWIMLANES]: {
|
|
148
190
|
description: `Configure swimlane structure for a board widget. Swimlanes create horizontal groupings within columns.
|
|
@@ -170,13 +212,16 @@ WORKFLOW:
|
|
|
170
212
|
4. Call this tool with complete desired state`,
|
|
171
213
|
inputSchema: {
|
|
172
214
|
context: LayoutContextSchema,
|
|
173
|
-
widgetId: z.string().describe(
|
|
174
|
-
enabled: z.boolean().describe(
|
|
175
|
-
mode: z
|
|
176
|
-
|
|
177
|
-
|
|
215
|
+
widgetId: z.string().describe('The board widget ID'),
|
|
216
|
+
enabled: z.boolean().describe('false = no swimlanes (flat board)'),
|
|
217
|
+
mode: z
|
|
218
|
+
.enum(['static', 'dynamic'])
|
|
219
|
+
.optional()
|
|
220
|
+
.describe('Swimlane generation mode (required when enabled)'),
|
|
221
|
+
swimlanes: z.array(StaticSwimlaneSchema).optional().describe('Static swimlane definitions'),
|
|
222
|
+
dynamicConfig: DynamicConfigSchema.optional().describe('Dynamic swimlane configuration'),
|
|
178
223
|
},
|
|
179
|
-
annotations: { title:
|
|
224
|
+
annotations: { title: 'Configure Board Swimlanes' },
|
|
180
225
|
},
|
|
181
226
|
[TOOL_BOARD_CONFIGURE_VISUAL]: {
|
|
182
227
|
description: `Configure visual settings for a board widget. Controls UI features and display options.
|
|
@@ -193,37 +238,61 @@ Available settings:
|
|
|
193
238
|
Omitted settings retain their current values (this tool does partial updates for visual settings).`,
|
|
194
239
|
inputSchema: {
|
|
195
240
|
context: LayoutContextSchema,
|
|
196
|
-
widgetId: z.string().describe(
|
|
197
|
-
showCardCount: z.boolean().optional().describe(
|
|
241
|
+
widgetId: z.string().describe('The board widget ID'),
|
|
242
|
+
showCardCount: z.boolean().optional().describe('Show card count in column headers'),
|
|
198
243
|
enableQuickAdd: z.boolean().optional().describe("Show '+' button to create new cards"),
|
|
199
|
-
showUnmappedContainer: z
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
244
|
+
showUnmappedContainer: z
|
|
245
|
+
.boolean()
|
|
246
|
+
.optional()
|
|
247
|
+
.describe('Show container for cards without valid column mapping'),
|
|
248
|
+
unmappedContainerNames: LocalizedNamesSchema.optional().describe('Localized names for unmapped container'),
|
|
249
|
+
enableCardDetailsView: z
|
|
250
|
+
.boolean()
|
|
251
|
+
.optional()
|
|
252
|
+
.describe('Show card details inline instead of navigation'),
|
|
253
|
+
showSpaceAfterLastColumn: z
|
|
254
|
+
.boolean()
|
|
255
|
+
.optional()
|
|
256
|
+
.describe('Add visual spacing after last column'),
|
|
257
|
+
enableRecentHistory: z
|
|
258
|
+
.boolean()
|
|
259
|
+
.optional()
|
|
260
|
+
.describe('Show button to highlight recently changed cards'),
|
|
261
|
+
recentHistoryWeeks: z
|
|
262
|
+
.number()
|
|
263
|
+
.optional()
|
|
264
|
+
.describe("Time range for 'recent' cards (default: 2)"),
|
|
205
265
|
},
|
|
206
|
-
annotations: { title:
|
|
207
|
-
}
|
|
266
|
+
annotations: { title: 'Configure Board Visual Settings' },
|
|
267
|
+
},
|
|
208
268
|
};
|
|
209
269
|
function extractWidgetConfiguration(widget) {
|
|
210
270
|
const config = {};
|
|
211
271
|
const CBOARD_PREFIX = 'cf.cplace.cboard.';
|
|
212
|
-
const KNOWN_ATTRS = [
|
|
272
|
+
const KNOWN_ATTRS = [
|
|
273
|
+
'searchConfigurations',
|
|
274
|
+
'columnMapping',
|
|
275
|
+
'swimlaneMapping',
|
|
276
|
+
'visualComponents',
|
|
277
|
+
];
|
|
213
278
|
const parseSearchConfigurations = (value) => {
|
|
214
|
-
return (value || [])
|
|
279
|
+
return (value || [])
|
|
280
|
+
.map((v) => {
|
|
215
281
|
try {
|
|
216
282
|
return JSON.parse(v);
|
|
217
283
|
}
|
|
218
284
|
catch {
|
|
219
285
|
return null;
|
|
220
286
|
}
|
|
221
|
-
})
|
|
287
|
+
})
|
|
288
|
+
.filter((v) => v !== null);
|
|
222
289
|
};
|
|
223
290
|
const getShortName = (name) => {
|
|
224
291
|
return name.startsWith(CBOARD_PREFIX) ? name.slice(CBOARD_PREFIX.length) : name;
|
|
225
292
|
};
|
|
226
|
-
if (widget.configuration &&
|
|
293
|
+
if (widget.configuration &&
|
|
294
|
+
typeof widget.configuration === 'object' &&
|
|
295
|
+
!Array.isArray(widget.configuration)) {
|
|
227
296
|
for (const [key, value] of Object.entries(widget.configuration)) {
|
|
228
297
|
const shortName = getShortName(key);
|
|
229
298
|
if (shortName === 'searchConfigurations') {
|
|
@@ -247,12 +316,12 @@ function extractWidgetConfiguration(widget) {
|
|
|
247
316
|
return config;
|
|
248
317
|
}
|
|
249
318
|
function validateSearchIdReferences(referencedIds, availableIds, contextDescription) {
|
|
250
|
-
const invalidIds = referencedIds.filter(id => !availableIds.includes(id));
|
|
319
|
+
const invalidIds = referencedIds.filter((id) => !availableIds.includes(id));
|
|
251
320
|
if (invalidIds.length > 0) {
|
|
252
321
|
return {
|
|
253
322
|
valid: false,
|
|
254
|
-
error: `${contextDescription} references unknown searchId(s): ${invalidIds.map(id => `'${id}'`).join(', ')}. ` +
|
|
255
|
-
`Available searchIds: [${availableIds.map(id => `'${id}'`).join(', ')}]
|
|
323
|
+
error: `${contextDescription} references unknown searchId(s): ${invalidIds.map((id) => `'${id}'`).join(', ')}. ` +
|
|
324
|
+
`Available searchIds: [${availableIds.map((id) => `'${id}'`).join(', ')}]`,
|
|
256
325
|
};
|
|
257
326
|
}
|
|
258
327
|
return { valid: true };
|
|
@@ -262,7 +331,7 @@ function transformRawToFriendly(rawConfig) {
|
|
|
262
331
|
const card = {
|
|
263
332
|
searchId: sc.searchId,
|
|
264
333
|
search: sc.search,
|
|
265
|
-
typeId: sc.typeId
|
|
334
|
+
typeId: sc.typeId,
|
|
266
335
|
};
|
|
267
336
|
const hasCardDisplay = sc.visibleDateAttribute || sc.attributeTags || sc.colorAttribute || sc.customIconAttributes;
|
|
268
337
|
if (hasCardDisplay) {
|
|
@@ -276,13 +345,13 @@ function transformRawToFriendly(rawConfig) {
|
|
|
276
345
|
if (sc.colorAttribute) {
|
|
277
346
|
card.cardDisplay.colorAttribute = {
|
|
278
347
|
attribute: sc.colorAttribute.attributeSimpleName,
|
|
279
|
-
colorMapping: sc.colorAttribute.selection || {}
|
|
348
|
+
colorMapping: sc.colorAttribute.selection || {},
|
|
280
349
|
};
|
|
281
350
|
}
|
|
282
351
|
if (sc.customIconAttributes?.length) {
|
|
283
352
|
card.cardDisplay.iconAttributes = sc.customIconAttributes.map((cia) => ({
|
|
284
353
|
attribute: cia.attributeSimpleName,
|
|
285
|
-
enabled: cia.enabled
|
|
354
|
+
enabled: cia.enabled,
|
|
286
355
|
}));
|
|
287
356
|
}
|
|
288
357
|
}
|
|
@@ -336,28 +405,29 @@ function transformMappingToFriendly(raw, elementType) {
|
|
|
336
405
|
}
|
|
337
406
|
if (raw.dynamic) {
|
|
338
407
|
return {
|
|
339
|
-
mode:
|
|
408
|
+
mode: 'dynamic',
|
|
340
409
|
...(elementType === 'swimlane' && { enabled: true }),
|
|
341
410
|
dynamicConfig: {
|
|
342
411
|
mappedAttributes: raw.mappedAttributes?.map((ma) => ({
|
|
343
412
|
searchId: ma.searchId,
|
|
344
|
-
attribute: ma.attributeSimpleName
|
|
413
|
+
attribute: ma.attributeSimpleName,
|
|
345
414
|
})),
|
|
346
415
|
timeGranularity: raw.timeGranularity?.toLowerCase(),
|
|
347
416
|
dateRange: raw.dateRange,
|
|
348
|
-
dateFormatId: raw.dateFormatId
|
|
349
|
-
}
|
|
417
|
+
dateFormatId: raw.dateFormatId,
|
|
418
|
+
},
|
|
350
419
|
};
|
|
351
420
|
}
|
|
352
421
|
return {
|
|
353
|
-
mode:
|
|
422
|
+
mode: 'static',
|
|
354
423
|
...(elementType === 'swimlane' && { enabled: true }),
|
|
355
424
|
[pluralField]: raw.elements?.map((el) => ({
|
|
356
425
|
[idField]: el.id,
|
|
357
426
|
names: el.localizedNames,
|
|
358
427
|
mappings: el.mappedValues?.map((mv) => ({
|
|
359
428
|
searchId: mv.searchId,
|
|
360
|
-
attribute: raw.mappedAttributes?.find((ma) => ma.searchId === mv.searchId)
|
|
429
|
+
attribute: raw.mappedAttributes?.find((ma) => ma.searchId === mv.searchId)
|
|
430
|
+
?.attributeSimpleName,
|
|
361
431
|
values: mv.values?.length ? mv.values : undefined,
|
|
362
432
|
referenceValues: mv.referenceValues?.length
|
|
363
433
|
? mv.referenceValues.map((rv) => {
|
|
@@ -365,9 +435,9 @@ function transformMappingToFriendly(raw, elementType) {
|
|
|
365
435
|
return uid.startsWith('page/') ? uid.slice(5) : uid;
|
|
366
436
|
})
|
|
367
437
|
: undefined,
|
|
368
|
-
dateRange: mv.dateRange || undefined
|
|
369
|
-
}))
|
|
370
|
-
}))
|
|
438
|
+
dateRange: mv.dateRange || undefined,
|
|
439
|
+
})),
|
|
440
|
+
})),
|
|
371
441
|
};
|
|
372
442
|
}
|
|
373
443
|
function transformVisualToFriendly(raw) {
|
|
@@ -379,15 +449,15 @@ function transformVisualToFriendly(raw) {
|
|
|
379
449
|
enableCardDetailsView: raw.cardDetailsViewEnabled,
|
|
380
450
|
showSpaceAfterLastColumn: raw.spaceAfterLastColumnEnabled,
|
|
381
451
|
enableRecentHistory: raw.recentHistoryButtonEnabled,
|
|
382
|
-
recentHistoryWeeks: raw.recentHistoryTimeRangeWeeks
|
|
452
|
+
recentHistoryWeeks: raw.recentHistoryTimeRangeWeeks,
|
|
383
453
|
};
|
|
384
454
|
}
|
|
385
455
|
function transformCardsToRaw(cards) {
|
|
386
|
-
return cards.map(card => {
|
|
456
|
+
return cards.map((card) => {
|
|
387
457
|
const raw = {
|
|
388
458
|
searchId: card.searchId,
|
|
389
459
|
search: card.search,
|
|
390
|
-
typeId: card.typeId
|
|
460
|
+
typeId: card.typeId,
|
|
391
461
|
};
|
|
392
462
|
if (card.cardDisplay) {
|
|
393
463
|
if (card.cardDisplay.dateAttribute) {
|
|
@@ -399,13 +469,13 @@ function transformCardsToRaw(cards) {
|
|
|
399
469
|
if (card.cardDisplay.colorAttribute) {
|
|
400
470
|
raw.colorAttribute = {
|
|
401
471
|
attributeSimpleName: card.cardDisplay.colorAttribute.attribute,
|
|
402
|
-
selection: card.cardDisplay.colorAttribute.colorMapping
|
|
472
|
+
selection: card.cardDisplay.colorAttribute.colorMapping,
|
|
403
473
|
};
|
|
404
474
|
}
|
|
405
475
|
if (card.cardDisplay.iconAttributes) {
|
|
406
476
|
raw.customIconAttributes = card.cardDisplay.iconAttributes.map((ia) => ({
|
|
407
477
|
enabled: ia.enabled !== false,
|
|
408
|
-
attributeSimpleName: ia.attribute
|
|
478
|
+
attributeSimpleName: ia.attribute,
|
|
409
479
|
}));
|
|
410
480
|
}
|
|
411
481
|
}
|
|
@@ -419,8 +489,8 @@ function transformMappedValuesToRaw(mapping) {
|
|
|
419
489
|
referenceValues: (mapping.referenceValues || []).map((uid) => ({
|
|
420
490
|
linkUid: uid.startsWith('page/') ? uid : `page/${uid}`,
|
|
421
491
|
linkName: '',
|
|
422
|
-
linkIcon: ''
|
|
423
|
-
}))
|
|
492
|
+
linkIcon: '',
|
|
493
|
+
})),
|
|
424
494
|
};
|
|
425
495
|
if (mapping.dateRange) {
|
|
426
496
|
raw.dateRange = mapping.dateRange;
|
|
@@ -428,14 +498,14 @@ function transformMappedValuesToRaw(mapping) {
|
|
|
428
498
|
return raw;
|
|
429
499
|
}
|
|
430
500
|
function transformColumnsToRaw(columnsConfig) {
|
|
431
|
-
if (columnsConfig.mode ===
|
|
501
|
+
if (columnsConfig.mode === 'dynamic') {
|
|
432
502
|
return JSON.stringify({
|
|
433
503
|
dynamic: true,
|
|
434
504
|
mappedAttributes: columnsConfig.dynamicConfig.mappedAttributes.map((ma) => ({
|
|
435
505
|
searchId: ma.searchId,
|
|
436
|
-
attributeSimpleName: ma.attribute
|
|
506
|
+
attributeSimpleName: ma.attribute,
|
|
437
507
|
})),
|
|
438
|
-
elements: []
|
|
508
|
+
elements: [],
|
|
439
509
|
});
|
|
440
510
|
}
|
|
441
511
|
const mappedAttributesMap = new Map();
|
|
@@ -448,13 +518,13 @@ function transformColumnsToRaw(columnsConfig) {
|
|
|
448
518
|
dynamic: false,
|
|
449
519
|
mappedAttributes: Array.from(mappedAttributesMap.entries()).map(([searchId, attr]) => ({
|
|
450
520
|
searchId,
|
|
451
|
-
attributeSimpleName: attr
|
|
521
|
+
attributeSimpleName: attr,
|
|
452
522
|
})),
|
|
453
523
|
elements: columnsConfig.columns.map((col) => ({
|
|
454
524
|
id: col.columnId,
|
|
455
525
|
localizedNames: col.names,
|
|
456
|
-
mappedValues: col.mappings.map(transformMappedValuesToRaw)
|
|
457
|
-
}))
|
|
526
|
+
mappedValues: col.mappings.map(transformMappedValuesToRaw),
|
|
527
|
+
})),
|
|
458
528
|
});
|
|
459
529
|
}
|
|
460
530
|
function transformSwimlanesToRaw(swimlanesConfig) {
|
|
@@ -462,17 +532,17 @@ function transformSwimlanesToRaw(swimlanesConfig) {
|
|
|
462
532
|
return JSON.stringify({
|
|
463
533
|
dynamic: false,
|
|
464
534
|
mappedAttributes: [],
|
|
465
|
-
elements: []
|
|
535
|
+
elements: [],
|
|
466
536
|
});
|
|
467
537
|
}
|
|
468
|
-
if (swimlanesConfig.mode ===
|
|
538
|
+
if (swimlanesConfig.mode === 'dynamic') {
|
|
469
539
|
return JSON.stringify({
|
|
470
540
|
dynamic: true,
|
|
471
541
|
mappedAttributes: swimlanesConfig.dynamicConfig.mappedAttributes.map((ma) => ({
|
|
472
542
|
searchId: ma.searchId,
|
|
473
|
-
attributeSimpleName: ma.attribute
|
|
543
|
+
attributeSimpleName: ma.attribute,
|
|
474
544
|
})),
|
|
475
|
-
elements: []
|
|
545
|
+
elements: [],
|
|
476
546
|
});
|
|
477
547
|
}
|
|
478
548
|
const mappedAttributesMap = new Map();
|
|
@@ -485,13 +555,13 @@ function transformSwimlanesToRaw(swimlanesConfig) {
|
|
|
485
555
|
dynamic: false,
|
|
486
556
|
mappedAttributes: Array.from(mappedAttributesMap.entries()).map(([searchId, attr]) => ({
|
|
487
557
|
searchId,
|
|
488
|
-
attributeSimpleName: attr
|
|
558
|
+
attributeSimpleName: attr,
|
|
489
559
|
})),
|
|
490
560
|
elements: swimlanesConfig.swimlanes.map((sl) => ({
|
|
491
561
|
id: sl.swimlaneId,
|
|
492
562
|
localizedNames: sl.names,
|
|
493
|
-
mappedValues: sl.mappings.map(transformMappedValuesToRaw)
|
|
494
|
-
}))
|
|
563
|
+
mappedValues: sl.mappings.map(transformMappedValuesToRaw),
|
|
564
|
+
})),
|
|
495
565
|
});
|
|
496
566
|
}
|
|
497
567
|
function transformVisualToRaw(friendlyVisual) {
|
|
@@ -503,7 +573,7 @@ function transformVisualToRaw(friendlyVisual) {
|
|
|
503
573
|
enableCardDetailsView: 'cardDetailsViewEnabled',
|
|
504
574
|
showSpaceAfterLastColumn: 'spaceAfterLastColumnEnabled',
|
|
505
575
|
enableRecentHistory: 'recentHistoryButtonEnabled',
|
|
506
|
-
recentHistoryWeeks: 'recentHistoryTimeRangeWeeks'
|
|
576
|
+
recentHistoryWeeks: 'recentHistoryTimeRangeWeeks',
|
|
507
577
|
};
|
|
508
578
|
const raw = {};
|
|
509
579
|
for (const [friendlyName, rawName] of Object.entries(fieldMapping)) {
|
|
@@ -529,11 +599,13 @@ async function getCurrentBoardConfig(client, context, widgetId) {
|
|
|
529
599
|
const friendlyConfig = transformRawToFriendly(rawConfig);
|
|
530
600
|
return {
|
|
531
601
|
cards: friendlyConfig.cards,
|
|
532
|
-
visualComponents: friendlyConfig.visualComponents
|
|
602
|
+
visualComponents: friendlyConfig.visualComponents,
|
|
533
603
|
};
|
|
534
604
|
}
|
|
535
605
|
catch (error) {
|
|
536
|
-
return {
|
|
606
|
+
return {
|
|
607
|
+
error: `Failed to get current configuration: ${error instanceof Error ? error.message : String(error)}`,
|
|
608
|
+
};
|
|
537
609
|
}
|
|
538
610
|
}
|
|
539
611
|
export function registerBoardWidgetTools(server, client) {
|
|
@@ -546,154 +618,203 @@ export function registerBoardWidgetTools(server, client) {
|
|
|
546
618
|
const widget = findWidgetById(layoutResult.rows, widgetId);
|
|
547
619
|
if (!widget) {
|
|
548
620
|
return {
|
|
549
|
-
content: [
|
|
550
|
-
|
|
621
|
+
content: [
|
|
622
|
+
{ type: 'text', text: `Board widget with ID '${widgetId}' not found in layout` },
|
|
623
|
+
],
|
|
624
|
+
isError: true,
|
|
551
625
|
};
|
|
552
626
|
}
|
|
553
627
|
if (widget.widgetType !== BOARD_WIDGET_TYPE) {
|
|
554
628
|
return {
|
|
555
|
-
content: [
|
|
556
|
-
|
|
629
|
+
content: [
|
|
630
|
+
{
|
|
631
|
+
type: 'text',
|
|
632
|
+
text: `Widget '${widgetId}' is not a board widget (found: ${widget.widgetType})`,
|
|
633
|
+
},
|
|
634
|
+
],
|
|
635
|
+
isError: true,
|
|
557
636
|
};
|
|
558
637
|
}
|
|
559
638
|
const rawConfig = extractWidgetConfiguration(widget);
|
|
560
|
-
const isUnconfigured = (!rawConfig.searchConfigurations || rawConfig.searchConfigurations.length === 0)
|
|
561
|
-
|
|
562
|
-
|
|
639
|
+
const isUnconfigured = (!rawConfig.searchConfigurations || rawConfig.searchConfigurations.length === 0) &&
|
|
640
|
+
!rawConfig.columnMapping &&
|
|
641
|
+
!rawConfig.swimlaneMapping;
|
|
563
642
|
if (isUnconfigured) {
|
|
564
643
|
debugLogWithTag('BOARD', `Board widget ${widgetId} is unconfigured (no card sources or mappings)`);
|
|
565
644
|
return {
|
|
566
|
-
content: [
|
|
645
|
+
content: [
|
|
646
|
+
{
|
|
647
|
+
type: 'text',
|
|
648
|
+
text: JSON.stringify({
|
|
567
649
|
context,
|
|
568
650
|
widgetId,
|
|
569
651
|
configuration: {
|
|
570
|
-
status:
|
|
652
|
+
status: 'unconfigured',
|
|
571
653
|
cards: [],
|
|
572
654
|
columns: null,
|
|
573
655
|
swimlanes: null,
|
|
574
|
-
visualComponents: null
|
|
575
|
-
}
|
|
576
|
-
}, null, 2)
|
|
656
|
+
visualComponents: null,
|
|
657
|
+
},
|
|
658
|
+
}, null, 2),
|
|
659
|
+
},
|
|
660
|
+
],
|
|
577
661
|
};
|
|
578
662
|
}
|
|
579
663
|
const friendlyConfig = transformRawToFriendly(rawConfig);
|
|
580
664
|
debugLogWithTag('BOARD', `Successfully retrieved board configuration with ${friendlyConfig.cards?.length || 0} card sources`);
|
|
581
665
|
return {
|
|
582
|
-
content: [
|
|
666
|
+
content: [
|
|
667
|
+
{
|
|
668
|
+
type: 'text',
|
|
669
|
+
text: JSON.stringify({
|
|
583
670
|
context,
|
|
584
671
|
widgetId,
|
|
585
672
|
configuration: {
|
|
586
|
-
status:
|
|
587
|
-
...friendlyConfig
|
|
588
|
-
}
|
|
589
|
-
}, null, 2)
|
|
673
|
+
status: 'configured',
|
|
674
|
+
...friendlyConfig,
|
|
675
|
+
},
|
|
676
|
+
}, null, 2),
|
|
677
|
+
},
|
|
678
|
+
],
|
|
590
679
|
};
|
|
591
680
|
}
|
|
592
681
|
catch (error) {
|
|
593
682
|
debugLogWithTag('BOARD', `Error getting board configuration: ${error instanceof Error ? error.message : String(error)}`);
|
|
594
683
|
return {
|
|
595
|
-
content: [
|
|
596
|
-
|
|
684
|
+
content: [
|
|
685
|
+
{
|
|
686
|
+
type: 'text',
|
|
687
|
+
text: `Failed to get board configuration: ${error instanceof Error ? error.message : String(error)}`,
|
|
688
|
+
},
|
|
689
|
+
],
|
|
690
|
+
isError: true,
|
|
597
691
|
};
|
|
598
692
|
}
|
|
599
693
|
});
|
|
600
694
|
server.registerTool(TOOL_BOARD_CONFIGURE_CARDS, BOARD_TOOL_DEFINITIONS[TOOL_BOARD_CONFIGURE_CARDS], async ({ context, widgetId, cards }) => {
|
|
601
695
|
debugLogWithTag('BOARD', `Configuring ${cards.length} card sources for widget ${widgetId}`);
|
|
602
696
|
try {
|
|
603
|
-
const searchIds = cards.map(c => c.searchId);
|
|
697
|
+
const searchIds = cards.map((c) => c.searchId);
|
|
604
698
|
const duplicates = searchIds.filter((id, i) => searchIds.indexOf(id) !== i);
|
|
605
699
|
if (duplicates.length > 0) {
|
|
606
700
|
return {
|
|
607
|
-
content: [
|
|
608
|
-
|
|
701
|
+
content: [
|
|
702
|
+
{
|
|
703
|
+
type: 'text',
|
|
704
|
+
text: `Duplicate searchId(s) found: ${[...new Set(duplicates)].join(', ')}. Each searchId must be unique.`,
|
|
705
|
+
},
|
|
706
|
+
],
|
|
707
|
+
isError: true,
|
|
609
708
|
};
|
|
610
709
|
}
|
|
611
710
|
const rawSearchConfigurations = transformCardsToRaw(cards);
|
|
612
711
|
const endpoint = determineApiEndpoint(context);
|
|
613
|
-
const searchConfigurationsValue = rawSearchConfigurations.map(sc => JSON.stringify(sc));
|
|
712
|
+
const searchConfigurationsValue = rawSearchConfigurations.map((sc) => JSON.stringify(sc));
|
|
614
713
|
debugLogWithTag('BOARD', `searchConfigurationsValue: ${JSON.stringify(searchConfigurationsValue)}`);
|
|
615
714
|
const requestBody = buildUpdateRequestBody(context, widgetId, {
|
|
616
|
-
'cf.cplace.cboard.searchConfigurations': searchConfigurationsValue
|
|
715
|
+
'cf.cplace.cboard.searchConfigurations': searchConfigurationsValue,
|
|
617
716
|
});
|
|
618
717
|
await client.makeApiRequest(endpoint, 'PATCH', undefined, requestBody);
|
|
619
718
|
debugLogWithTag('BOARD', `Successfully configured ${cards.length} card sources`);
|
|
620
719
|
return {
|
|
621
|
-
content: [
|
|
622
|
-
|
|
623
|
-
|
|
720
|
+
content: [
|
|
721
|
+
{
|
|
722
|
+
type: 'text',
|
|
723
|
+
text: JSON.stringify({
|
|
724
|
+
operation: 'CONFIGURE_CARDS',
|
|
725
|
+
status: 'SUCCESS',
|
|
624
726
|
context,
|
|
625
727
|
widgetId,
|
|
626
728
|
cardCount: cards.length,
|
|
627
729
|
searchIds: searchIds,
|
|
628
|
-
message: `Board cards configured successfully with ${cards.length} source(s)
|
|
629
|
-
}, null, 2)
|
|
730
|
+
message: `Board cards configured successfully with ${cards.length} source(s)`,
|
|
731
|
+
}, null, 2),
|
|
732
|
+
},
|
|
733
|
+
],
|
|
630
734
|
};
|
|
631
735
|
}
|
|
632
736
|
catch (error) {
|
|
633
737
|
debugLogWithTag('BOARD', `Error configuring cards: ${error instanceof Error ? error.message : String(error)}`);
|
|
634
738
|
return {
|
|
635
|
-
content: [
|
|
636
|
-
|
|
739
|
+
content: [
|
|
740
|
+
{
|
|
741
|
+
type: 'text',
|
|
742
|
+
text: `Failed to configure board cards: ${error instanceof Error ? error.message : String(error)}`,
|
|
743
|
+
},
|
|
744
|
+
],
|
|
745
|
+
isError: true,
|
|
637
746
|
};
|
|
638
747
|
}
|
|
639
748
|
});
|
|
640
749
|
server.registerTool(TOOL_BOARD_CONFIGURE_COLUMNS, BOARD_TOOL_DEFINITIONS[TOOL_BOARD_CONFIGURE_COLUMNS], async ({ context, widgetId, mode, columns, dynamicConfig }) => {
|
|
641
750
|
debugLogWithTag('BOARD', `Configuring columns (${mode} mode) for widget ${widgetId}`);
|
|
642
751
|
try {
|
|
643
|
-
if (mode ===
|
|
752
|
+
if (mode === 'static' && (!columns || columns.length === 0)) {
|
|
644
753
|
return {
|
|
645
|
-
content: [
|
|
646
|
-
|
|
754
|
+
content: [
|
|
755
|
+
{ type: 'text', text: 'Static mode requires at least one column definition' },
|
|
756
|
+
],
|
|
757
|
+
isError: true,
|
|
647
758
|
};
|
|
648
759
|
}
|
|
649
|
-
if (mode ===
|
|
760
|
+
if (mode === 'dynamic' && !dynamicConfig) {
|
|
650
761
|
return {
|
|
651
|
-
content: [{ type:
|
|
652
|
-
isError: true
|
|
762
|
+
content: [{ type: 'text', text: 'Dynamic mode requires dynamicConfig' }],
|
|
763
|
+
isError: true,
|
|
653
764
|
};
|
|
654
765
|
}
|
|
655
766
|
const currentConfig = await getCurrentBoardConfig(client, context, widgetId);
|
|
656
767
|
if (currentConfig.error) {
|
|
657
768
|
return {
|
|
658
|
-
content: [{ type:
|
|
659
|
-
isError: true
|
|
769
|
+
content: [{ type: 'text', text: currentConfig.error }],
|
|
770
|
+
isError: true,
|
|
660
771
|
};
|
|
661
772
|
}
|
|
662
773
|
const availableSearchIds = currentConfig.cards?.map((c) => c.searchId) || [];
|
|
663
|
-
const referencedIds = mode ===
|
|
664
|
-
? [...new Set(columns.flatMap(col => col.mappings.map(m => m.searchId)))]
|
|
665
|
-
: (dynamicConfig?.mappedAttributes || []).map(ma => ma.searchId);
|
|
666
|
-
const validation = validateSearchIdReferences(referencedIds, availableSearchIds,
|
|
774
|
+
const referencedIds = mode === 'static'
|
|
775
|
+
? [...new Set(columns.flatMap((col) => col.mappings.map((m) => m.searchId)))]
|
|
776
|
+
: (dynamicConfig?.mappedAttributes || []).map((ma) => ma.searchId);
|
|
777
|
+
const validation = validateSearchIdReferences(referencedIds, availableSearchIds, 'Column configuration');
|
|
667
778
|
if (!validation.valid) {
|
|
668
779
|
return {
|
|
669
|
-
content: [{ type:
|
|
670
|
-
isError: true
|
|
780
|
+
content: [{ type: 'text', text: validation.error }],
|
|
781
|
+
isError: true,
|
|
671
782
|
};
|
|
672
783
|
}
|
|
673
784
|
const rawColumnMapping = transformColumnsToRaw({ mode, columns, dynamicConfig });
|
|
674
785
|
const endpoint = determineApiEndpoint(context);
|
|
675
786
|
const requestBody = buildUpdateRequestBody(context, widgetId, {
|
|
676
|
-
'cf.cplace.cboard.columnMapping': rawColumnMapping
|
|
787
|
+
'cf.cplace.cboard.columnMapping': rawColumnMapping,
|
|
677
788
|
});
|
|
678
789
|
await client.makeApiRequest(endpoint, 'PATCH', undefined, requestBody);
|
|
679
790
|
debugLogWithTag('BOARD', `Successfully configured columns in ${mode} mode`);
|
|
680
791
|
return {
|
|
681
|
-
content: [
|
|
682
|
-
|
|
683
|
-
|
|
792
|
+
content: [
|
|
793
|
+
{
|
|
794
|
+
type: 'text',
|
|
795
|
+
text: JSON.stringify({
|
|
796
|
+
operation: 'CONFIGURE_COLUMNS',
|
|
797
|
+
status: 'SUCCESS',
|
|
684
798
|
context,
|
|
685
799
|
widgetId,
|
|
686
800
|
mode,
|
|
687
|
-
columnCount: mode ===
|
|
688
|
-
message: `Board columns configured successfully (${mode} mode)
|
|
689
|
-
}, null, 2)
|
|
801
|
+
columnCount: mode === 'static' ? columns.length : 'dynamic',
|
|
802
|
+
message: `Board columns configured successfully (${mode} mode)`,
|
|
803
|
+
}, null, 2),
|
|
804
|
+
},
|
|
805
|
+
],
|
|
690
806
|
};
|
|
691
807
|
}
|
|
692
808
|
catch (error) {
|
|
693
809
|
debugLogWithTag('BOARD', `Error configuring columns: ${error instanceof Error ? error.message : String(error)}`);
|
|
694
810
|
return {
|
|
695
|
-
content: [
|
|
696
|
-
|
|
811
|
+
content: [
|
|
812
|
+
{
|
|
813
|
+
type: 'text',
|
|
814
|
+
text: `Failed to configure board columns: ${error instanceof Error ? error.message : String(error)}`,
|
|
815
|
+
},
|
|
816
|
+
],
|
|
817
|
+
isError: true,
|
|
697
818
|
};
|
|
698
819
|
}
|
|
699
820
|
});
|
|
@@ -704,81 +825,103 @@ export function registerBoardWidgetTools(server, client) {
|
|
|
704
825
|
const rawSwimlaneMapping = transformSwimlanesToRaw({ enabled: false });
|
|
705
826
|
const endpoint = determineApiEndpoint(context);
|
|
706
827
|
const requestBody = buildUpdateRequestBody(context, widgetId, {
|
|
707
|
-
'cf.cplace.cboard.swimlaneMapping': rawSwimlaneMapping
|
|
828
|
+
'cf.cplace.cboard.swimlaneMapping': rawSwimlaneMapping,
|
|
708
829
|
});
|
|
709
830
|
await client.makeApiRequest(endpoint, 'PATCH', undefined, requestBody);
|
|
710
831
|
return {
|
|
711
|
-
content: [
|
|
712
|
-
|
|
713
|
-
|
|
832
|
+
content: [
|
|
833
|
+
{
|
|
834
|
+
type: 'text',
|
|
835
|
+
text: JSON.stringify({
|
|
836
|
+
operation: 'CONFIGURE_SWIMLANES',
|
|
837
|
+
status: 'SUCCESS',
|
|
714
838
|
context,
|
|
715
839
|
widgetId,
|
|
716
840
|
enabled: false,
|
|
717
|
-
message:
|
|
718
|
-
}, null, 2)
|
|
841
|
+
message: 'Board swimlanes disabled (flat board)',
|
|
842
|
+
}, null, 2),
|
|
843
|
+
},
|
|
844
|
+
],
|
|
719
845
|
};
|
|
720
846
|
}
|
|
721
847
|
if (!mode) {
|
|
722
848
|
return {
|
|
723
|
-
content: [{ type:
|
|
724
|
-
isError: true
|
|
849
|
+
content: [{ type: 'text', text: 'Mode is required when swimlanes are enabled' }],
|
|
850
|
+
isError: true,
|
|
725
851
|
};
|
|
726
852
|
}
|
|
727
|
-
if (mode ===
|
|
853
|
+
if (mode === 'static' && (!swimlanes || swimlanes.length === 0)) {
|
|
728
854
|
return {
|
|
729
|
-
content: [
|
|
730
|
-
|
|
855
|
+
content: [
|
|
856
|
+
{ type: 'text', text: 'Static mode requires at least one swimlane definition' },
|
|
857
|
+
],
|
|
858
|
+
isError: true,
|
|
731
859
|
};
|
|
732
860
|
}
|
|
733
|
-
if (mode ===
|
|
861
|
+
if (mode === 'dynamic' && !dynamicConfig) {
|
|
734
862
|
return {
|
|
735
|
-
content: [{ type:
|
|
736
|
-
isError: true
|
|
863
|
+
content: [{ type: 'text', text: 'Dynamic mode requires dynamicConfig' }],
|
|
864
|
+
isError: true,
|
|
737
865
|
};
|
|
738
866
|
}
|
|
739
867
|
const currentConfig = await getCurrentBoardConfig(client, context, widgetId);
|
|
740
868
|
if (currentConfig.error) {
|
|
741
869
|
return {
|
|
742
|
-
content: [{ type:
|
|
743
|
-
isError: true
|
|
870
|
+
content: [{ type: 'text', text: currentConfig.error }],
|
|
871
|
+
isError: true,
|
|
744
872
|
};
|
|
745
873
|
}
|
|
746
874
|
const availableSearchIds = currentConfig.cards?.map((c) => c.searchId) || [];
|
|
747
|
-
const referencedIds = mode ===
|
|
748
|
-
? [...new Set(swimlanes.flatMap(sl => sl.mappings.map(m => m.searchId)))]
|
|
749
|
-
: (dynamicConfig?.mappedAttributes || []).map(ma => ma.searchId);
|
|
750
|
-
const validation = validateSearchIdReferences(referencedIds, availableSearchIds,
|
|
875
|
+
const referencedIds = mode === 'static'
|
|
876
|
+
? [...new Set(swimlanes.flatMap((sl) => sl.mappings.map((m) => m.searchId)))]
|
|
877
|
+
: (dynamicConfig?.mappedAttributes || []).map((ma) => ma.searchId);
|
|
878
|
+
const validation = validateSearchIdReferences(referencedIds, availableSearchIds, 'Swimlane configuration');
|
|
751
879
|
if (!validation.valid) {
|
|
752
880
|
return {
|
|
753
|
-
content: [{ type:
|
|
754
|
-
isError: true
|
|
881
|
+
content: [{ type: 'text', text: validation.error }],
|
|
882
|
+
isError: true,
|
|
755
883
|
};
|
|
756
884
|
}
|
|
757
|
-
const rawSwimlaneMapping = transformSwimlanesToRaw({
|
|
885
|
+
const rawSwimlaneMapping = transformSwimlanesToRaw({
|
|
886
|
+
enabled: true,
|
|
887
|
+
mode,
|
|
888
|
+
swimlanes,
|
|
889
|
+
dynamicConfig,
|
|
890
|
+
});
|
|
758
891
|
const endpoint = determineApiEndpoint(context);
|
|
759
892
|
const requestBody = buildUpdateRequestBody(context, widgetId, {
|
|
760
|
-
'cf.cplace.cboard.swimlaneMapping': rawSwimlaneMapping
|
|
893
|
+
'cf.cplace.cboard.swimlaneMapping': rawSwimlaneMapping,
|
|
761
894
|
});
|
|
762
895
|
await client.makeApiRequest(endpoint, 'PATCH', undefined, requestBody);
|
|
763
896
|
debugLogWithTag('BOARD', `Successfully configured swimlanes in ${mode} mode`);
|
|
764
897
|
return {
|
|
765
|
-
content: [
|
|
766
|
-
|
|
767
|
-
|
|
898
|
+
content: [
|
|
899
|
+
{
|
|
900
|
+
type: 'text',
|
|
901
|
+
text: JSON.stringify({
|
|
902
|
+
operation: 'CONFIGURE_SWIMLANES',
|
|
903
|
+
status: 'SUCCESS',
|
|
768
904
|
context,
|
|
769
905
|
widgetId,
|
|
770
906
|
enabled: true,
|
|
771
907
|
mode,
|
|
772
|
-
swimlaneCount: mode ===
|
|
773
|
-
message: `Board swimlanes configured successfully (${mode} mode)
|
|
774
|
-
}, null, 2)
|
|
908
|
+
swimlaneCount: mode === 'static' ? swimlanes.length : 'dynamic',
|
|
909
|
+
message: `Board swimlanes configured successfully (${mode} mode)`,
|
|
910
|
+
}, null, 2),
|
|
911
|
+
},
|
|
912
|
+
],
|
|
775
913
|
};
|
|
776
914
|
}
|
|
777
915
|
catch (error) {
|
|
778
916
|
debugLogWithTag('BOARD', `Error configuring swimlanes: ${error instanceof Error ? error.message : String(error)}`);
|
|
779
917
|
return {
|
|
780
|
-
content: [
|
|
781
|
-
|
|
918
|
+
content: [
|
|
919
|
+
{
|
|
920
|
+
type: 'text',
|
|
921
|
+
text: `Failed to configure board swimlanes: ${error instanceof Error ? error.message : String(error)}`,
|
|
922
|
+
},
|
|
923
|
+
],
|
|
924
|
+
isError: true,
|
|
782
925
|
};
|
|
783
926
|
}
|
|
784
927
|
});
|
|
@@ -788,8 +931,8 @@ export function registerBoardWidgetTools(server, client) {
|
|
|
788
931
|
const currentConfig = await getCurrentBoardConfig(client, context, widgetId);
|
|
789
932
|
if (currentConfig.error) {
|
|
790
933
|
return {
|
|
791
|
-
content: [{ type:
|
|
792
|
-
isError: true
|
|
934
|
+
content: [{ type: 'text', text: currentConfig.error }],
|
|
935
|
+
isError: true,
|
|
793
936
|
};
|
|
794
937
|
}
|
|
795
938
|
const currentVisual = currentConfig.visualComponents || {};
|
|
@@ -799,27 +942,37 @@ export function registerBoardWidgetTools(server, client) {
|
|
|
799
942
|
const rawVisualComponents = JSON.stringify(mergedRaw);
|
|
800
943
|
const endpoint = determineApiEndpoint(context);
|
|
801
944
|
const requestBody = buildUpdateRequestBody(context, widgetId, {
|
|
802
|
-
'cf.cplace.cboard.visualComponents': rawVisualComponents
|
|
945
|
+
'cf.cplace.cboard.visualComponents': rawVisualComponents,
|
|
803
946
|
});
|
|
804
947
|
await client.makeApiRequest(endpoint, 'PATCH', undefined, requestBody);
|
|
805
948
|
debugLogWithTag('BOARD', `Successfully configured visual settings`);
|
|
806
|
-
const appliedSettings = Object.keys(visualSettings).filter(k => visualSettings[k] !== undefined);
|
|
949
|
+
const appliedSettings = Object.keys(visualSettings).filter((k) => visualSettings[k] !== undefined);
|
|
807
950
|
return {
|
|
808
|
-
content: [
|
|
809
|
-
|
|
810
|
-
|
|
951
|
+
content: [
|
|
952
|
+
{
|
|
953
|
+
type: 'text',
|
|
954
|
+
text: JSON.stringify({
|
|
955
|
+
operation: 'CONFIGURE_VISUAL',
|
|
956
|
+
status: 'SUCCESS',
|
|
811
957
|
context,
|
|
812
958
|
widgetId,
|
|
813
959
|
appliedSettings,
|
|
814
|
-
message:
|
|
815
|
-
}, null, 2)
|
|
960
|
+
message: 'Board visual settings configured successfully',
|
|
961
|
+
}, null, 2),
|
|
962
|
+
},
|
|
963
|
+
],
|
|
816
964
|
};
|
|
817
965
|
}
|
|
818
966
|
catch (error) {
|
|
819
967
|
debugLogWithTag('BOARD', `Error configuring visual settings: ${error instanceof Error ? error.message : String(error)}`);
|
|
820
968
|
return {
|
|
821
|
-
content: [
|
|
822
|
-
|
|
969
|
+
content: [
|
|
970
|
+
{
|
|
971
|
+
type: 'text',
|
|
972
|
+
text: `Failed to configure board visual settings: ${error instanceof Error ? error.message : String(error)}`,
|
|
973
|
+
},
|
|
974
|
+
],
|
|
975
|
+
isError: true,
|
|
823
976
|
};
|
|
824
977
|
}
|
|
825
978
|
});
|