@cplace/mcp-server 1.12.4 → 1.13.1
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/plugins/core/widget-specifications/cf.cplace.layoutTabsWidget.widget/_overview.md +2 -2
- package/dist/plugins/core/widget-specifications/cf.cplace.layoutTabsWidget.widget/_summary.md +1 -1
- package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/_implementation.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/_overview.md +2 -9
- package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/columns.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/groupColumn.md +13 -0
- package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/multiSortColumns.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.cplace.tableDetailViewWidget.widget/attributes.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.platform.connectedBarChart/attributeName.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.platform.connectedMatrix/attributeXName.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.platform.connectedMatrix/attributeYName.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.platform.connectedPieChart/attributeName.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.platform.connectedSingleAttribute/_implementation.md +1 -1
- package/dist/plugins/core/widget-specifications/cf.platform.connectedSingleAttribute/attributeName.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.platform.connectedSingleAttribute/singleSelectionWidgetId.md +1 -1
- package/dist/plugins/core/widget-specifications/cf.platform.embeddedSearchAsTable/columns.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.platform.embeddedSearchAsTable/multiSortColumns.md +1 -0
- package/dist/plugins/core/widget-specifications/cf.platform.singleAttribute/_implementation.md +1 -1
- package/dist/plugins/core/widget-specifications/cf.platform.singleAttribute/cf.platform.entity.md +1 -2
- package/dist/plugins/core/widget-specifications/cf.platform.singleAttribute/cf.platform.quotedAttributeName.md +1 -0
- package/dist/plugins/layouts.d.ts.map +1 -1
- package/dist/plugins/layouts.js +5 -0
- package/dist/plugins/layouts.js.map +1 -1
- package/dist/tools/embedded-widget-layout.d.ts +99 -0
- package/dist/tools/embedded-widget-layout.d.ts.map +1 -0
- package/dist/tools/embedded-widget-layout.js +249 -0
- package/dist/tools/embedded-widget-layout.js.map +1 -0
- package/dist/tools/layout.d.ts +1 -1
- package/dist/tools/layout.d.ts.map +1 -1
- package/dist/tools/layout.js +24 -2
- package/dist/tools/layout.js.map +1 -1
- package/dist/tools/page-action-simulation.d.ts +1 -1
- package/dist/tools/page-action-simulation.js +1 -1
- package/dist/tools/script.d.ts +2 -2
- package/dist/tools/script.js +3 -3
- package/dist/tools/type-layouts.d.ts +3 -3
- package/dist/tools/type-layouts.js +3 -3
- package/dist/tools/type-layouts.js.map +1 -1
- package/dist/tools/type-management.d.ts.map +1 -1
- package/dist/tools/type-management.js +17 -5
- package/dist/tools/type-management.js.map +1 -1
- package/dist/tools/widget-simulation.d.ts +1 -1
- package/dist/tools/widget-simulation.js +1 -1
- package/dist/tools/workflow-execution.d.ts.map +1 -1
- package/dist/tools/workflow-execution.js +9 -5
- package/dist/tools/workflow-execution.js.map +1 -1
- package/package.json +1 -1
package/dist/plugins/core/widget-specifications/cf.cplace.layoutTabsWidget.widget/_overview.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
## Overview
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Organize a type's alternative layouts as tabs.
|
|
4
4
|
|
|
5
|
-
The Alternative Layouts as Tabs widget can be
|
|
5
|
+
The Alternative Layouts as Tabs widget displays a type's alternative layouts as tabs on a cplace page, so widgets and information on the page can be structured and arranged in a meaningful manner. Alternative layouts are **type-scoped**: every tab is a layout defined on the page's type and shared by all pages of that type. The widget cannot scope a tab set to a single page on a shared type — in script mode it filters which of the type's layouts show per page, but it cannot create a per-page-unique tab set. A surface that needs its own view switcher needs its own type.
|
|
6
6
|
|
|
7
7
|
## Use Cases
|
|
8
8
|
|
package/dist/plugins/core/widget-specifications/cf.cplace.layoutTabsWidget.widget/_summary.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
Organizes a type's alternative layouts as tabs, letting users switch between layout views of the same page. Tabs are type-scoped: every tab is an alternative layout defined on the page's type and shared by all pages of that type — the widget cannot create a per-page-unique tab set on a shared type.
|
package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/_implementation.md
CHANGED
|
@@ -8,4 +8,5 @@
|
|
|
8
8
|
1. Configure `search` (and optionally `connectedWidgetId` for master-detail)
|
|
9
9
|
2. Define visible columns via `columns` attribute
|
|
10
10
|
3. Optionally configure sorting (`multiSortColumns`), filtering (`filters`), and grouping (`groupColumn`)
|
|
11
|
+
- `groupColumn` takes a single attribute-name string; custom names are single-quoted like `columns`, with an optional `groupOrder` (`asc`/`desc`). Single grouping is live-verified (validates and renders). Multi-level grouping via `enableMultiGrouping` + `multiGroupColumns` exists on current cplace (absent in 25.3/25.4). See the `groupColumn` attribute spec.
|
|
11
12
|
4. Configure display options via `displayOptions` multi-enum (always include `showLinksInNameColumn` unless explicitly told otherwise)
|
|
@@ -4,7 +4,7 @@ Displays a list of search results.
|
|
|
4
4
|
|
|
5
5
|
The Table Widget is a next-generation table implementation that presents search results in a tabular format with modern web component architecture. It serves as both a primary data display component and a powerful data producer for connected widgets, supporting advanced features like multi-column sorting, dynamic filtering, and customizable column configurations.
|
|
6
6
|
|
|
7
|
-
**Status**: Beta (
|
|
7
|
+
**Status**: Preferred table widget for new implementations. Marked `@Beta` in the platform API (the interface may still evolve), but it does **not** require a runtime feature flag.
|
|
8
8
|
|
|
9
9
|
## Key Capabilities
|
|
10
10
|
|
|
@@ -101,7 +101,6 @@ The Table Widget is a next-generation table implementation that presents search
|
|
|
101
101
|
|
|
102
102
|
Use the Table Widget when:
|
|
103
103
|
- You need a modern, feature-rich table implementation
|
|
104
|
-
- The `newTableEnabled` feature flag is active in your environment
|
|
105
104
|
- You're building new pages requiring table functionality
|
|
106
105
|
- You need master-detail patterns with connected widgets
|
|
107
106
|
- You want to provide search results to multiple visualization widgets
|
|
@@ -109,7 +108,6 @@ Use the Table Widget when:
|
|
|
109
108
|
### Prerequisites and Dependencies
|
|
110
109
|
|
|
111
110
|
**Required**:
|
|
112
|
-
- Feature flag `newTableEnabled` must be active
|
|
113
111
|
- Valid search definition in configuration
|
|
114
112
|
- Widget must be embedded in a page
|
|
115
113
|
|
|
@@ -122,8 +120,6 @@ Use the Table Widget when:
|
|
|
122
120
|
|
|
123
121
|
The widget is marked with `@Beta` annotation, indicating:
|
|
124
122
|
- API may undergo changes in future releases
|
|
125
|
-
- Feature flag controls availability in production
|
|
126
|
-
- Monitor feature flag status in target environments
|
|
127
123
|
- Consider migration planning if replacing legacy table widgets
|
|
128
124
|
|
|
129
125
|
## Common Patterns
|
|
@@ -164,20 +160,17 @@ Parent-child table relationship:
|
|
|
164
160
|
**Table Widget advantages**:
|
|
165
161
|
- Modern web component architecture (vs. legacy AngularJS)
|
|
166
162
|
- Cleaner producer interface implementation
|
|
167
|
-
- Feature-flagged for controlled rollout
|
|
168
163
|
- Better separation of concerns in state management
|
|
169
164
|
|
|
170
165
|
**When to use Table Widget**:
|
|
171
166
|
- New implementations on modern infrastructure
|
|
172
|
-
- When `newTableEnabled` feature flag is active
|
|
173
167
|
- For new pages requiring table functionality
|
|
174
168
|
|
|
175
169
|
**When to use Embedded Search as Table**:
|
|
176
170
|
- Legacy pages still on AngularJS
|
|
177
|
-
- When `newTableEnabled` feature flag is not active
|
|
178
171
|
- Existing implementations that don't need migration
|
|
179
172
|
|
|
180
|
-
The Table Widget is the preferred choice for new implementations. Embedded Search as Table is the legacy version — use it only
|
|
173
|
+
The Table Widget is the preferred choice for new implementations. Embedded Search as Table is the legacy version — use it only for maintaining existing implementations.
|
|
181
174
|
|
|
182
175
|
## Related Widgets
|
|
183
176
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
**Important**:
|
|
14
14
|
- **Custom attributes** require single quotes around the attribute name: `"'cf.cplace.myType.attributeName'"`
|
|
15
15
|
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`) are specified without quotes: `"name"`
|
|
16
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
16
17
|
- The pseudo-column **`_name_`** renders the page's display name with navigation link and is distinct from the builtin `name` attribute.
|
|
17
18
|
|
|
18
19
|
**Note**: Order in array determines column display order. Hidden columns (`visible: false`) can still be used for sorting/filtering.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
**Groups table rows by the value of a single attribute.**
|
|
2
|
+
|
|
3
|
+
**Format**: a single attribute-name string (not an array), plus an optional `groupOrder`.
|
|
4
|
+
- **Custom attributes** require single quotes around the attribute name: `"'cf.cplace.myType.attributeName'"`
|
|
5
|
+
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`) are specified without quotes: `"name"`
|
|
6
|
+
- **`groupOrder`**: `"asc"` or `"desc"`.
|
|
7
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so the single-quoted token needs no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
8
|
+
|
|
9
|
+
Live-verified on a current-version instance: the apostrophe-wrapped custom token validates (`VALID_COMPLETE`), is stored byte-for-byte, and renders visible grouping (rows grouped under "Status: Draft" / "Status: Active"). The **bare** custom name (no apostrophes) is rejected with `VALIDATION_ERROR` "Invalid Value" — the apostrophes are the discriminator. Read-back returns the stored value in the `\'`-escaped single-quoted form.
|
|
10
|
+
|
|
11
|
+
**Precondition — the attribute must be in the widget's `search`**: `groupColumn`'s legal options are computed live from the widget's `search`; the search's result type(s) must expose the attribute for it to appear in the enumeration. **If a correctly-quoted token still errors, check `search` first** — do not re-try quoting variants. (Reported edge, not re-verified live: if the `search` JSON is malformed, the option set collapses to a single `name`, so only `groupColumn: "name"` validates until `search` is fixed.)
|
|
12
|
+
|
|
13
|
+
**Multi-level grouping (current cplace)**: `enableMultiGrouping: true` + `multiGroupColumns` is the multi-level grouping path on current cplace. Both are **declared** attributes of the current tableWidget definition (confirm via `cplace_get_widget_definition`). They are **absent in 25.3/25.4** — on an older instance `groupColumn` is the only grouping path. The exact `multiGroupColumns` JSON is version-dependent; obtain it by configuring multi-grouping once in the UI, then reading it back via `cplace_get_layout_script`, rather than hand-authoring a literal.
|
package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/multiSortColumns.md
CHANGED
|
@@ -12,5 +12,6 @@
|
|
|
12
12
|
**Important**:
|
|
13
13
|
- **Custom attributes** require single quotes around the attribute name: `"'cf.cplace.myType.attributeName'"`
|
|
14
14
|
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`) are specified without quotes: `"name"`
|
|
15
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
15
16
|
|
|
16
17
|
**Note**: `sortingPriorityIndex` determines which sort applies first (lower = higher priority).
|
package/dist/plugins/core/widget-specifications/cf.cplace.tableDetailViewWidget.widget/attributes.md
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
**Value Format**:
|
|
4
4
|
- **Custom attributes**: Use fully qualified names like `'cf.cplace.solution.taskTitle'`
|
|
5
5
|
- **Built-in attributes**: Use simple feature names like `name`, `creator`, `created`
|
|
6
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
6
7
|
|
|
7
8
|
**Note**: The enumeration provider dynamically populates available attributes based on the connected table widget's type. Only attributes from the table's result type are selectable.
|
package/dist/plugins/core/widget-specifications/cf.platform.connectedBarChart/attributeName.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
**Important**:
|
|
4
4
|
- **Custom attributes** require single quotes around the attribute name: `'cf.cplace.myApp.myAttribute'`
|
|
5
5
|
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`) are specified without quotes: `name`
|
|
6
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
6
7
|
|
|
7
8
|
**Validation**: Before setting this attribute, verify that the attribute actually exists on the type returned by the data source (connected table or standalone search). Using a non-existent attribute will result in an empty or broken chart.
|
|
8
9
|
|
package/dist/plugins/core/widget-specifications/cf.platform.connectedMatrix/attributeXName.md
CHANGED
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
- **Custom attributes** require single quotes around the attribute name inside the string value: `"'cf.cplace.myApp.myAttribute'"`
|
|
5
5
|
- **Builtin attributes** (e.g., `name`, `createdAt`) are specified without inner quotes: `"name"`
|
|
6
6
|
- Without inner quotes, the widget silently fails and shows "Please complete the widget configuration"
|
|
7
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
7
8
|
|
|
8
9
|
**Validation**: Before setting this attribute, verify it exists on the type returned by the connected table's search. Using a non-existent or incorrectly quoted attribute results in a broken widget with no useful error message.
|
package/dist/plugins/core/widget-specifications/cf.platform.connectedMatrix/attributeYName.md
CHANGED
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
- **Custom attributes** require single quotes around the attribute name inside the string value: `"'cf.cplace.myApp.myAttribute'"`
|
|
5
5
|
- **Builtin attributes** (e.g., `name`, `createdAt`) are specified without inner quotes: `"name"`
|
|
6
6
|
- Without inner quotes, the widget silently fails and shows "Please complete the widget configuration"
|
|
7
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
7
8
|
|
|
8
9
|
**Validation**: Before setting this attribute, verify it exists on the type returned by the connected table's search. Using a non-existent or incorrectly quoted attribute results in a broken widget with no useful error message.
|
package/dist/plugins/core/widget-specifications/cf.platform.connectedPieChart/attributeName.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
**Important**:
|
|
4
4
|
- **Custom attributes** require single quotes around the attribute name: `'cf.cplace.myApp.myAttribute'`
|
|
5
5
|
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`) are specified without quotes: `name`
|
|
6
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
6
7
|
|
|
7
8
|
**Validation**: Before setting this attribute, verify that the attribute actually exists on the type returned by the data source (connected table or standalone search). Using a non-existent attribute will result in an empty or broken chart.
|
|
8
9
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
**Typical Configuration Workflow**:
|
|
7
7
|
1. Set `singleSelectionWidgetId` to the table/selection widget that provides entity selection
|
|
8
|
-
-
|
|
8
|
+
- Omit entirely when embedded inside a `cf.platform.connectedAttributesGroup` widget (the parent provides the connection)
|
|
9
9
|
2. Set `attributeName`
|
|
10
10
|
3. Configure display options:
|
|
11
11
|
- `withValue` and `withLabel` (at least one must be true)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
**Important**:
|
|
4
4
|
- **Custom attributes** require single quotes around the attribute name: `'cf.cplace.myApp.myAttribute'`
|
|
5
5
|
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`) are specified without quotes: `name`
|
|
6
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
6
7
|
|
|
7
8
|
**Workflow**:
|
|
8
9
|
1. Call `cplace_get_type_datamodel` for the type displayed in the connected table
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
**Valid Values**:
|
|
2
|
-
- When embedded inside a `cf.cplace.platform.connectedAttributesGroup` widget,
|
|
2
|
+
- When embedded inside a `cf.cplace.platform.connectedAttributesGroup` widget, omit this key entirely (or leave it empty) - the parent widget provides the actual table connection. Passing a value here causes a validation error.
|
|
3
3
|
- When the connection goes against a `cf.platform.treeTable` widget - insert the widget ID
|
package/dist/plugins/core/widget-specifications/cf.platform.embeddedSearchAsTable/columns.md
CHANGED
|
@@ -12,5 +12,6 @@
|
|
|
12
12
|
**Important**:
|
|
13
13
|
- **Custom attributes** require single quotes around the attribute name: `"'cf.cplace.myType.attributeName'"`
|
|
14
14
|
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`) are specified without quotes: `"name"`
|
|
15
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
15
16
|
|
|
16
17
|
**Note**: Order in array determines column display order. Hidden columns (`visible: false`) can still be used for sorting/filtering.
|
|
@@ -12,5 +12,6 @@
|
|
|
12
12
|
**Important**:
|
|
13
13
|
- **Custom attributes** require single quotes around the attribute name: `"'cf.cplace.myType.attributeName'"`
|
|
14
14
|
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`) are specified without quotes: `"name"`
|
|
15
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
15
16
|
|
|
16
17
|
**Note**: `sortingPriorityIndex` determines which sort applies first (lower = higher priority).
|
package/dist/plugins/core/widget-specifications/cf.platform.singleAttribute/_implementation.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
**Typical Configuration Workflow**:
|
|
6
6
|
1. Set `entity` to the page whose attribute should be displayed
|
|
7
7
|
- Leave empty for current page
|
|
8
|
-
-
|
|
8
|
+
- Omit entirely when embedded inside a `cf.platform.attributesGroup` widget (the parent provides the entity)
|
|
9
9
|
2. Set `quotedAttributeName` to the attribute to display
|
|
10
10
|
3. Configure display options:
|
|
11
11
|
- `withValue` and `withLabel` (at least one must be true)
|
package/dist/plugins/core/widget-specifications/cf.platform.singleAttribute/cf.platform.entity.md
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
**Valid Values**:
|
|
4
4
|
- Empty/null: Use the current (embedding) page
|
|
5
5
|
- Page UID: Reference to a specific page whose attribute should be displayed
|
|
6
|
-
- `"<empty>"`: Special value when embedded inside a `cf.platform.attributesGroup` widget
|
|
7
6
|
|
|
8
|
-
**Warning**: When embedded inside a `cf.platform.attributesGroup` widget,
|
|
7
|
+
**Warning**: When embedded inside a `cf.platform.attributesGroup` widget, omit this key entirely (or leave it empty) - the parent widget provides the target entity. Passing a value here causes a validation error.
|
|
9
8
|
|
|
10
9
|
**Note**: This parameter is hidden from the edit UI when the widget is embedded inside `cf.platform.attributesGroup`.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
**Important**:
|
|
4
4
|
- **Custom attributes** require single quotes around the attribute name: `'cf.cplace.myApp.myAttribute'`
|
|
5
5
|
- **Builtin attributes** (e.g., `name`, `createdAt`, `creator`, `modifiedAt`, `modifier`, `owner`, `_writers`) are specified without quotes: `name`
|
|
6
|
+
- **Inside a `layout.define` string**: wrap the config value in a **double-quoted** outer JS string so these single-quoted tokens need no escaping — see the `cplace_execute_layout_script` tool description (quoting/escaping note). Never wrap it in a single-quoted string with unescaped inner `'` (throws `SyntaxError`).
|
|
6
7
|
|
|
7
8
|
**Workflow**:
|
|
8
9
|
1. Call `cplace_get_type_datamodel` for the type of the target page
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layouts.d.ts","sourceRoot":"","sources":["../../src/plugins/layouts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"layouts.d.ts","sourceRoot":"","sources":["../../src/plugins/layouts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAwBpD,eAAO,MAAM,aAAa,EAAE,SA2B3B,CAAC"}
|
package/dist/plugins/layouts.js
CHANGED
|
@@ -5,6 +5,7 @@ import { registerRichStringWidgetTools, RICHSTRING_WIDGET_TOOL_DEFINITIONS, } fr
|
|
|
5
5
|
import { registerLayoutRichStringWidgetTools, LAYOUT_RICHSTRING_WIDGET_TOOL_DEFINITIONS, } from '../tools/layout-richstring-widgets.js';
|
|
6
6
|
import { registerBoardWidgetTools, BOARD_TOOL_DEFINITIONS } from '../tools/board-widget.js';
|
|
7
7
|
import { registerLayoutTools, LAYOUT_TOOL_DEFINITIONS } from '../tools/layout.js';
|
|
8
|
+
import { registerEmbeddedWidgetLayoutTools, EMBEDDED_WIDGET_LAYOUT_TOOL_DEFINITIONS, } from '../tools/embedded-widget-layout.js';
|
|
8
9
|
import { fileURLToPath } from 'url';
|
|
9
10
|
import { dirname } from 'path';
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -30,6 +31,10 @@ export const layoutsPlugin = {
|
|
|
30
31
|
},
|
|
31
32
|
'board-widget': { register: registerBoardWidgetTools, toolDefinitions: BOARD_TOOL_DEFINITIONS },
|
|
32
33
|
layout: { register: registerLayoutTools, toolDefinitions: LAYOUT_TOOL_DEFINITIONS },
|
|
34
|
+
'embedded-widget-layout': {
|
|
35
|
+
register: registerEmbeddedWidgetLayoutTools,
|
|
36
|
+
toolDefinitions: EMBEDDED_WIDGET_LAYOUT_TOOL_DEFINITIONS,
|
|
37
|
+
},
|
|
33
38
|
},
|
|
34
39
|
};
|
|
35
40
|
//# sourceMappingURL=layouts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layouts.js","sourceRoot":"","sources":["../../src/plugins/layouts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACjG,OAAO,EACL,6BAA6B,EAC7B,kCAAkC,GACnC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,mCAAmC,EACnC,yCAAyC,GAC1C,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC5F,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,CAAC,MAAM,aAAa,GAAc;IACtC,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,cAAc;IACvB,WAAW,EACT,oIAAoI;IACtI,UAAU,EAAE,SAAS;IACrB,OAAO,EAAE;QACP,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,eAAe,EAAE,uBAAuB,EAAE;QACzE,cAAc,EAAE;YACd,QAAQ,EAAE,uBAAuB;YACjC,eAAe,EAAE,4BAA4B;SAC9C;QACD,oBAAoB,EAAE;YACpB,QAAQ,EAAE,6BAA6B;YACvC,eAAe,EAAE,kCAAkC;SACpD;QACD,2BAA2B,EAAE;YAC3B,QAAQ,EAAE,mCAAmC;YAC7C,eAAe,EAAE,yCAAyC;SAC3D;QACD,cAAc,EAAE,EAAE,QAAQ,EAAE,wBAAwB,EAAE,eAAe,EAAE,sBAAsB,EAAE;QAC/F,MAAM,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE,eAAe,EAAE,uBAAuB,EAAE;
|
|
1
|
+
{"version":3,"file":"layouts.js","sourceRoot":"","sources":["../../src/plugins/layouts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACjG,OAAO,EACL,6BAA6B,EAC7B,kCAAkC,GACnC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,mCAAmC,EACnC,yCAAyC,GAC1C,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC5F,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EACL,iCAAiC,EACjC,uCAAuC,GACxC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,CAAC,MAAM,aAAa,GAAc;IACtC,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,cAAc;IACvB,WAAW,EACT,oIAAoI;IACtI,UAAU,EAAE,SAAS;IACrB,OAAO,EAAE;QACP,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,eAAe,EAAE,uBAAuB,EAAE;QACzE,cAAc,EAAE;YACd,QAAQ,EAAE,uBAAuB;YACjC,eAAe,EAAE,4BAA4B;SAC9C;QACD,oBAAoB,EAAE;YACpB,QAAQ,EAAE,6BAA6B;YACvC,eAAe,EAAE,kCAAkC;SACpD;QACD,2BAA2B,EAAE;YAC3B,QAAQ,EAAE,mCAAmC;YAC7C,eAAe,EAAE,yCAAyC;SAC3D;QACD,cAAc,EAAE,EAAE,QAAQ,EAAE,wBAAwB,EAAE,eAAe,EAAE,sBAAsB,EAAE;QAC/F,MAAM,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE,eAAe,EAAE,uBAAuB,EAAE;QACnF,wBAAwB,EAAE;YACxB,QAAQ,EAAE,iCAAiC;YAC3C,eAAe,EAAE,uCAAuC;SACzD;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { CplaceApiClient } from '../api.js';
|
|
4
|
+
export declare const EMBEDDED_WIDGET_LAYOUT_TOOL_DEFINITIONS: {
|
|
5
|
+
readonly cplace_add_widget_to_embedded_layout: {
|
|
6
|
+
readonly description: "Add a single child widget into a container widget's embedded layout (e.g. a \"Grouped Attributes\" widget: cf.cplace.platform.attributesGroup or cf.cplace.platform.connectedAttributesGroup), in place, and return the new widget's server-assigned id.\n\nUse this to add ONE embedded child without rebuilding the whole container. Unlike cplace_edit_layout (which regenerates EVERY widget id), this preserves the ids of all other widgets.\n\nWorks on both page and type layouts (set via context). Placement is index-based: rowIndex/columnIndex/widgetIndex. There is no before/after-widget placement. A non-existing rowIndex appends a new full-width row; a non-existing columnIndex adds to the last existing column.\n\nDISCOVERY: find the container widget id with cplace_get_layout_widget_details; verify the child widgetType and its config attribute names with cplace_get_widget_definition.\n\nReturns newWidgetId — use it to configure or cross-reference the widget you just added.";
|
|
7
|
+
readonly inputSchema: {
|
|
8
|
+
readonly context: z.ZodEffects<z.ZodUnion<[z.ZodObject<{
|
|
9
|
+
type: z.ZodLiteral<"page">;
|
|
10
|
+
pageUID: z.ZodString;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
type: "page";
|
|
13
|
+
pageUID: string;
|
|
14
|
+
}, {
|
|
15
|
+
type: "page";
|
|
16
|
+
pageUID: string;
|
|
17
|
+
}>, z.ZodObject<{
|
|
18
|
+
type: z.ZodLiteral<"type">;
|
|
19
|
+
workspaceId: z.ZodString;
|
|
20
|
+
typeInternalName: z.ZodString;
|
|
21
|
+
alternativeLayoutName: z.ZodOptional<z.ZodString>;
|
|
22
|
+
}, "strip", z.ZodTypeAny, {
|
|
23
|
+
type: "type";
|
|
24
|
+
workspaceId: string;
|
|
25
|
+
typeInternalName: string;
|
|
26
|
+
alternativeLayoutName?: string | undefined;
|
|
27
|
+
}, {
|
|
28
|
+
type: "type";
|
|
29
|
+
workspaceId: string;
|
|
30
|
+
typeInternalName: string;
|
|
31
|
+
alternativeLayoutName?: string | undefined;
|
|
32
|
+
}>]>, {
|
|
33
|
+
type: "page";
|
|
34
|
+
pageUID: string;
|
|
35
|
+
} | {
|
|
36
|
+
type: "type";
|
|
37
|
+
workspaceId: string;
|
|
38
|
+
typeInternalName: string;
|
|
39
|
+
alternativeLayoutName?: string | undefined;
|
|
40
|
+
}, unknown>;
|
|
41
|
+
readonly containerWidgetId: z.ZodString;
|
|
42
|
+
readonly layoutAttributeName: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
43
|
+
readonly widgetType: z.ZodString;
|
|
44
|
+
readonly rowIndex: z.ZodEffects<z.ZodNumber, number, unknown>;
|
|
45
|
+
readonly columnIndex: z.ZodEffects<z.ZodNumber, number, unknown>;
|
|
46
|
+
readonly widgetIndex: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, unknown>>;
|
|
47
|
+
readonly configuration: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
48
|
+
};
|
|
49
|
+
readonly annotations: {
|
|
50
|
+
readonly title: "Add Widget to Embedded Layout";
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
readonly cplace_remove_widget_from_embedded_layout: {
|
|
54
|
+
readonly description: "Remove a single child widget from a container widget's embedded layout (e.g. a \"Grouped Attributes\" widget: cf.cplace.platform.attributesGroup or cf.cplace.platform.connectedAttributesGroup), by widget id, in place.\n\nUse this to delete ONE embedded child without rebuilding the whole container. Unlike cplace_edit_layout (which round-trips through layout.define and regenerates EVERY widget id), this preserves the ids of all other widgets — the safe choice when embedded widgets are cross-referenced.\n\nWorks on both page and type layouts (set via context).\n\nDISCOVERY: find the container widget id and its embedded children with cplace_get_layout_widget_details. layoutAttributeName defaults to the standard grouped-attributes key; look it up with cplace_get_widget_definition only for other container kinds.\n\nIf the widget id is not present in the container, the call fails with a clear error (it does NOT silently succeed).";
|
|
55
|
+
readonly inputSchema: {
|
|
56
|
+
readonly context: z.ZodEffects<z.ZodUnion<[z.ZodObject<{
|
|
57
|
+
type: z.ZodLiteral<"page">;
|
|
58
|
+
pageUID: z.ZodString;
|
|
59
|
+
}, "strip", z.ZodTypeAny, {
|
|
60
|
+
type: "page";
|
|
61
|
+
pageUID: string;
|
|
62
|
+
}, {
|
|
63
|
+
type: "page";
|
|
64
|
+
pageUID: string;
|
|
65
|
+
}>, z.ZodObject<{
|
|
66
|
+
type: z.ZodLiteral<"type">;
|
|
67
|
+
workspaceId: z.ZodString;
|
|
68
|
+
typeInternalName: z.ZodString;
|
|
69
|
+
alternativeLayoutName: z.ZodOptional<z.ZodString>;
|
|
70
|
+
}, "strip", z.ZodTypeAny, {
|
|
71
|
+
type: "type";
|
|
72
|
+
workspaceId: string;
|
|
73
|
+
typeInternalName: string;
|
|
74
|
+
alternativeLayoutName?: string | undefined;
|
|
75
|
+
}, {
|
|
76
|
+
type: "type";
|
|
77
|
+
workspaceId: string;
|
|
78
|
+
typeInternalName: string;
|
|
79
|
+
alternativeLayoutName?: string | undefined;
|
|
80
|
+
}>]>, {
|
|
81
|
+
type: "page";
|
|
82
|
+
pageUID: string;
|
|
83
|
+
} | {
|
|
84
|
+
type: "type";
|
|
85
|
+
workspaceId: string;
|
|
86
|
+
typeInternalName: string;
|
|
87
|
+
alternativeLayoutName?: string | undefined;
|
|
88
|
+
}, unknown>;
|
|
89
|
+
readonly containerWidgetId: z.ZodString;
|
|
90
|
+
readonly layoutAttributeName: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
91
|
+
readonly widgetId: z.ZodString;
|
|
92
|
+
};
|
|
93
|
+
readonly annotations: {
|
|
94
|
+
readonly title: "Remove Widget from Embedded Layout";
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
export declare function registerEmbeddedWidgetLayoutTools(server: McpServer, client: CplaceApiClient): void;
|
|
99
|
+
//# sourceMappingURL=embedded-widget-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-widget-layout.d.ts","sourceRoot":"","sources":["../../src/tools/embedded-widget-layout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AA8C5C,eAAO,MAAM,uCAAuC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgF1C,CAAC;AAEX,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,QAqN3F"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { debugLogWithTag } from '../logger.js';
|
|
3
|
+
import { checkResponseSize } from '../utils.js';
|
|
4
|
+
import { LayoutContextSchema } from './layout.js';
|
|
5
|
+
import { buildRequestParams } from './widget-tool-helpers.js';
|
|
6
|
+
import { coerceNumber, unwrapSingleElementArrays } from './common-schemas.js';
|
|
7
|
+
const TOOL_ADD_EMBEDDED_WIDGET = 'cplace_add_widget_to_embedded_layout';
|
|
8
|
+
const TOOL_REMOVE_EMBEDDED_WIDGET = 'cplace_remove_widget_from_embedded_layout';
|
|
9
|
+
const DEFAULT_LAYOUT_ATTRIBUTE_NAME = 'cf.cplace.platform.attributesGroup.layout';
|
|
10
|
+
const DEBUG_TAG = 'EMBEDDED_WIDGET_LAYOUT';
|
|
11
|
+
function determineEmbeddedEndpoint(context) {
|
|
12
|
+
return context.type === 'page'
|
|
13
|
+
? 'json/page/embeddedWidgetLayout'
|
|
14
|
+
: 'json/type/embeddedWidgetLayout';
|
|
15
|
+
}
|
|
16
|
+
function buildEmbeddedRequestParams(context, containerWidgetId, layoutAttributeName) {
|
|
17
|
+
return { ...buildRequestParams(context), containerWidgetId, layoutAttributeName };
|
|
18
|
+
}
|
|
19
|
+
async function readEmbeddedLayout(client, context, containerWidgetId, layoutAttributeName) {
|
|
20
|
+
const endpoint = determineEmbeddedEndpoint(context);
|
|
21
|
+
const params = buildEmbeddedRequestParams(context, containerWidgetId, layoutAttributeName);
|
|
22
|
+
return await client.makeApiRequest(endpoint, 'GET', params);
|
|
23
|
+
}
|
|
24
|
+
function extractEmbeddedWidgetIds(embeddedLayout) {
|
|
25
|
+
const widgets = embeddedLayout?.widgets;
|
|
26
|
+
if (!Array.isArray(widgets))
|
|
27
|
+
return [];
|
|
28
|
+
return widgets.map((w) => w?.id).filter((id) => typeof id === 'string');
|
|
29
|
+
}
|
|
30
|
+
export const EMBEDDED_WIDGET_LAYOUT_TOOL_DEFINITIONS = {
|
|
31
|
+
[TOOL_ADD_EMBEDDED_WIDGET]: {
|
|
32
|
+
description: `Add a single child widget into a container widget's embedded layout (e.g. a "Grouped Attributes" widget: cf.cplace.platform.attributesGroup or cf.cplace.platform.connectedAttributesGroup), in place, and return the new widget's server-assigned id.
|
|
33
|
+
|
|
34
|
+
Use this to add ONE embedded child without rebuilding the whole container. Unlike cplace_edit_layout (which regenerates EVERY widget id), this preserves the ids of all other widgets.
|
|
35
|
+
|
|
36
|
+
Works on both page and type layouts (set via context). Placement is index-based: rowIndex/columnIndex/widgetIndex. There is no before/after-widget placement. A non-existing rowIndex appends a new full-width row; a non-existing columnIndex adds to the last existing column.
|
|
37
|
+
|
|
38
|
+
DISCOVERY: find the container widget id with cplace_get_layout_widget_details; verify the child widgetType and its config attribute names with cplace_get_widget_definition.
|
|
39
|
+
|
|
40
|
+
Returns newWidgetId — use it to configure or cross-reference the widget you just added.`,
|
|
41
|
+
inputSchema: {
|
|
42
|
+
context: LayoutContextSchema,
|
|
43
|
+
containerWidgetId: z
|
|
44
|
+
.string()
|
|
45
|
+
.describe('The id of the container widget to add the child into (find via cplace_get_layout_widget_details)'),
|
|
46
|
+
layoutAttributeName: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.default(DEFAULT_LAYOUT_ATTRIBUTE_NAME)
|
|
50
|
+
.describe(`The container's embedded-layout attribute key. Defaults to '${DEFAULT_LAYOUT_ATTRIBUTE_NAME}' (correct for both attributesGroup and connectedAttributesGroup). Override only for other container kinds — look up via cplace_get_widget_definition.`),
|
|
51
|
+
widgetType: z
|
|
52
|
+
.string()
|
|
53
|
+
.describe("The widget type of the new child (e.g. 'cf.platform.attributes'). Verify embeddability with cplace_get_widget_definition."),
|
|
54
|
+
rowIndex: coerceNumber(z.number()).describe('Target row index (0-based). A non-existing index appends a new full-width row.'),
|
|
55
|
+
columnIndex: coerceNumber(z.number()).describe('Target column index within the row (0-based). A non-existing index adds to the last existing column.'),
|
|
56
|
+
widgetIndex: coerceNumber(z.number())
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Insertion index within the column (0-based, default 0). -1 appends.'),
|
|
59
|
+
configuration: z
|
|
60
|
+
.record(z.any())
|
|
61
|
+
.optional()
|
|
62
|
+
.describe(`Optional widget configuration as attribute-name → value pairs (same convention as layout.define config). Verify attribute names with cplace_get_widget_definition — some are fully qualified. Localized strings use locale maps: { en: "Title", de: "Titel" }. Omit 'cf.platform.entity' (it defaults to the current context).`),
|
|
63
|
+
},
|
|
64
|
+
annotations: { title: 'Add Widget to Embedded Layout' },
|
|
65
|
+
},
|
|
66
|
+
[TOOL_REMOVE_EMBEDDED_WIDGET]: {
|
|
67
|
+
description: `Remove a single child widget from a container widget's embedded layout (e.g. a "Grouped Attributes" widget: cf.cplace.platform.attributesGroup or cf.cplace.platform.connectedAttributesGroup), by widget id, in place.
|
|
68
|
+
|
|
69
|
+
Use this to delete ONE embedded child without rebuilding the whole container. Unlike cplace_edit_layout (which round-trips through layout.define and regenerates EVERY widget id), this preserves the ids of all other widgets — the safe choice when embedded widgets are cross-referenced.
|
|
70
|
+
|
|
71
|
+
Works on both page and type layouts (set via context).
|
|
72
|
+
|
|
73
|
+
DISCOVERY: find the container widget id and its embedded children with cplace_get_layout_widget_details. layoutAttributeName defaults to the standard grouped-attributes key; look it up with cplace_get_widget_definition only for other container kinds.
|
|
74
|
+
|
|
75
|
+
If the widget id is not present in the container, the call fails with a clear error (it does NOT silently succeed).`,
|
|
76
|
+
inputSchema: {
|
|
77
|
+
context: LayoutContextSchema,
|
|
78
|
+
containerWidgetId: z
|
|
79
|
+
.string()
|
|
80
|
+
.describe("The id of the container widget whose embedded layout holds the child (find via cplace_get_layout_widget_details, e.g. '_a1b2c3')"),
|
|
81
|
+
layoutAttributeName: z
|
|
82
|
+
.string()
|
|
83
|
+
.optional()
|
|
84
|
+
.default(DEFAULT_LAYOUT_ATTRIBUTE_NAME)
|
|
85
|
+
.describe(`The container's embedded-layout attribute key. Defaults to '${DEFAULT_LAYOUT_ATTRIBUTE_NAME}', which is correct for both cf.cplace.platform.attributesGroup and cf.cplace.platform.connectedAttributesGroup. Override only for other container kinds — look up the key via cplace_get_widget_definition.`),
|
|
86
|
+
widgetId: z
|
|
87
|
+
.string()
|
|
88
|
+
.describe('The id of the embedded child widget to remove (find via cplace_get_layout_widget_details)'),
|
|
89
|
+
},
|
|
90
|
+
annotations: { title: 'Remove Widget from Embedded Layout' },
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
export function registerEmbeddedWidgetLayoutTools(server, client) {
|
|
94
|
+
server.registerTool(TOOL_ADD_EMBEDDED_WIDGET, EMBEDDED_WIDGET_LAYOUT_TOOL_DEFINITIONS[TOOL_ADD_EMBEDDED_WIDGET], async ({ context, containerWidgetId, layoutAttributeName, widgetType, rowIndex, columnIndex, widgetIndex, configuration, }) => {
|
|
95
|
+
debugLogWithTag(DEBUG_TAG, `ADD ${widgetType} to container ${containerWidgetId} in ${context.type} layout`);
|
|
96
|
+
try {
|
|
97
|
+
const before = await readEmbeddedLayout(client, context, containerWidgetId, layoutAttributeName);
|
|
98
|
+
const beforeIds = new Set(extractEmbeddedWidgetIds(before));
|
|
99
|
+
const position = { rowIndex, columnIndex };
|
|
100
|
+
if (widgetIndex !== undefined)
|
|
101
|
+
position.widgetIndex = widgetIndex;
|
|
102
|
+
const operation = { type: 'ADD', widgetType, position };
|
|
103
|
+
const normalizedConfig = unwrapSingleElementArrays(configuration);
|
|
104
|
+
if (normalizedConfig && Object.keys(normalizedConfig).length > 0) {
|
|
105
|
+
operation.configuration = normalizedConfig;
|
|
106
|
+
}
|
|
107
|
+
const endpoint = determineEmbeddedEndpoint(context);
|
|
108
|
+
const body = {
|
|
109
|
+
...buildEmbeddedRequestParams(context, containerWidgetId, layoutAttributeName),
|
|
110
|
+
operation,
|
|
111
|
+
};
|
|
112
|
+
const raw = await client.makeRawApiRequest(endpoint, 'PATCH', undefined, body);
|
|
113
|
+
if (raw?.success !== true) {
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: 'text',
|
|
118
|
+
text: `Failed to add embedded widget: ${raw?.errorMessage || 'Unknown error'}`,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
isError: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const after = typeof raw.result === 'string' ? JSON.parse(raw.result) : raw.result;
|
|
125
|
+
const newIds = extractEmbeddedWidgetIds(after).filter((id) => !beforeIds.has(id));
|
|
126
|
+
if (newIds.length !== 1) {
|
|
127
|
+
return {
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
type: 'text',
|
|
131
|
+
text: `Add could not be verified: expected exactly one new widget in container '${containerWidgetId}' but found ${newIds.length}${newIds.length ? ` (${newIds.join(', ')})` : ''}. The layout may have changed concurrently, or the add did not take effect. Inspect with cplace_get_layout_widget_details.`,
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
isError: true,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const response = {
|
|
138
|
+
operation: 'ADD_EMBEDDED_WIDGET',
|
|
139
|
+
success: true,
|
|
140
|
+
context,
|
|
141
|
+
containerWidgetId: raw.containerWidgetId ?? containerWidgetId,
|
|
142
|
+
newWidgetId: newIds[0],
|
|
143
|
+
widgetType,
|
|
144
|
+
};
|
|
145
|
+
const sizeCheck = checkResponseSize(response);
|
|
146
|
+
if (sizeCheck.tooLarge) {
|
|
147
|
+
return {
|
|
148
|
+
content: [
|
|
149
|
+
{
|
|
150
|
+
type: 'text',
|
|
151
|
+
text: `Widget added (id ${newIds[0]}) but the confirmation response was too large. Inspect with cplace_get_layout_widget_details.`,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
debugLogWithTag(DEBUG_TAG, `Added ${widgetType} as ${newIds[0]} to ${containerWidgetId}`);
|
|
157
|
+
return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] };
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
debugLogWithTag(DEBUG_TAG, `Error adding embedded widget: ${error instanceof Error ? error.message : String(error)}`);
|
|
161
|
+
return {
|
|
162
|
+
content: [
|
|
163
|
+
{
|
|
164
|
+
type: 'text',
|
|
165
|
+
text: `Error adding embedded widget: ${error instanceof Error ? error.message : String(error)}`,
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
isError: true,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
server.registerTool(TOOL_REMOVE_EMBEDDED_WIDGET, EMBEDDED_WIDGET_LAYOUT_TOOL_DEFINITIONS[TOOL_REMOVE_EMBEDDED_WIDGET], async ({ context, containerWidgetId, layoutAttributeName, widgetId }) => {
|
|
173
|
+
debugLogWithTag(DEBUG_TAG, `REMOVE ${widgetId} from container ${containerWidgetId} in ${context.type} layout`);
|
|
174
|
+
try {
|
|
175
|
+
const before = await readEmbeddedLayout(client, context, containerWidgetId, layoutAttributeName);
|
|
176
|
+
const beforeIds = extractEmbeddedWidgetIds(before);
|
|
177
|
+
if (!beforeIds.includes(widgetId)) {
|
|
178
|
+
return {
|
|
179
|
+
content: [
|
|
180
|
+
{
|
|
181
|
+
type: 'text',
|
|
182
|
+
text: `Widget '${widgetId}' is not present in the embedded layout of container '${containerWidgetId}'. Nothing was removed. Call cplace_get_layout_widget_details on the container to list its current embedded child ids.`,
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
isError: true,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const endpoint = determineEmbeddedEndpoint(context);
|
|
189
|
+
const body = {
|
|
190
|
+
...buildEmbeddedRequestParams(context, containerWidgetId, layoutAttributeName),
|
|
191
|
+
operation: { type: 'REMOVE', widgetId },
|
|
192
|
+
};
|
|
193
|
+
const raw = await client.makeRawApiRequest(endpoint, 'PATCH', undefined, body);
|
|
194
|
+
if (raw?.success !== true) {
|
|
195
|
+
return {
|
|
196
|
+
content: [
|
|
197
|
+
{
|
|
198
|
+
type: 'text',
|
|
199
|
+
text: `Failed to remove embedded widget: ${raw?.errorMessage || 'Unknown error'}`,
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
isError: true,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const after = typeof raw.result === 'string' ? JSON.parse(raw.result) : raw.result;
|
|
206
|
+
const afterIds = extractEmbeddedWidgetIds(after);
|
|
207
|
+
if (afterIds.includes(widgetId)) {
|
|
208
|
+
return {
|
|
209
|
+
content: [
|
|
210
|
+
{
|
|
211
|
+
type: 'text',
|
|
212
|
+
text: `Backend reported success but widget '${widgetId}' is still present in container '${containerWidgetId}'. The removal did not take effect.`,
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
isError: true,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const response = {
|
|
219
|
+
operation: 'REMOVE_EMBEDDED_WIDGET',
|
|
220
|
+
success: true,
|
|
221
|
+
context,
|
|
222
|
+
containerWidgetId: raw.containerWidgetId ?? containerWidgetId,
|
|
223
|
+
removedWidgetId: widgetId,
|
|
224
|
+
remainingWidgetIds: afterIds,
|
|
225
|
+
};
|
|
226
|
+
const sizeCheck = checkResponseSize(response);
|
|
227
|
+
if (sizeCheck.tooLarge) {
|
|
228
|
+
const compact = { ...response };
|
|
229
|
+
delete compact.remainingWidgetIds;
|
|
230
|
+
return { content: [{ type: 'text', text: JSON.stringify(compact, null, 2) }] };
|
|
231
|
+
}
|
|
232
|
+
debugLogWithTag(DEBUG_TAG, `Removed ${widgetId} from ${containerWidgetId}`);
|
|
233
|
+
return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] };
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
debugLogWithTag(DEBUG_TAG, `Error removing embedded widget: ${error instanceof Error ? error.message : String(error)}`);
|
|
237
|
+
return {
|
|
238
|
+
content: [
|
|
239
|
+
{
|
|
240
|
+
type: 'text',
|
|
241
|
+
text: `Error removing embedded widget: ${error instanceof Error ? error.message : String(error)}`,
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
isError: true,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=embedded-widget-layout.js.map
|